mirror of
				https://github.com/aclindsa/moneygo.git
				synced 2025-11-04 02:23:26 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"github.com/yuin/gopher-lua"
 | 
						|
	"net/http"
 | 
						|
)
 | 
						|
 | 
						|
const luaReportTypeName = "report"
 | 
						|
const luaSeriesTypeName = "series"
 | 
						|
 | 
						|
type Series struct {
 | 
						|
	Values   []float64
 | 
						|
	Children map[string]*Series
 | 
						|
}
 | 
						|
 | 
						|
type Report struct {
 | 
						|
	Title      string
 | 
						|
	Subtitle   string
 | 
						|
	XAxisLabel string
 | 
						|
	YAxisLabel string
 | 
						|
	Labels     []string
 | 
						|
	Series     map[string]*Series
 | 
						|
}
 | 
						|
 | 
						|
func (r *Report) Write(w http.ResponseWriter) error {
 | 
						|
	enc := json.NewEncoder(w)
 | 
						|
	return enc.Encode(r)
 | 
						|
}
 | 
						|
 | 
						|
func luaRegisterReports(L *lua.LState) {
 | 
						|
	mtr := L.NewTypeMetatable(luaReportTypeName)
 | 
						|
	L.SetGlobal("report", mtr)
 | 
						|
	L.SetField(mtr, "new", L.NewFunction(luaReportNew))
 | 
						|
	L.SetField(mtr, "__index", L.NewFunction(luaReport__index))
 | 
						|
	L.SetField(mtr, "__metatable", lua.LString("protected"))
 | 
						|
 | 
						|
	mts := L.NewTypeMetatable(luaSeriesTypeName)
 | 
						|
	L.SetGlobal("series", mts)
 | 
						|
	L.SetField(mts, "__index", L.NewFunction(luaSeries__index))
 | 
						|
	L.SetField(mts, "__metatable", lua.LString("protected"))
 | 
						|
}
 | 
						|
 | 
						|
// Checks whether the first lua argument is a *LUserData with *Report and returns *Report
 | 
						|
func luaCheckReport(L *lua.LState, n int) *Report {
 | 
						|
	ud := L.CheckUserData(n)
 | 
						|
	if report, ok := ud.Value.(*Report); ok {
 | 
						|
		return report
 | 
						|
	}
 | 
						|
	L.ArgError(n, "report expected")
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// Checks whether the first lua argument is a *LUserData with *Series and returns *Series
 | 
						|
func luaCheckSeries(L *lua.LState, n int) *Series {
 | 
						|
	ud := L.CheckUserData(n)
 | 
						|
	if series, ok := ud.Value.(*Series); ok {
 | 
						|
		return series
 | 
						|
	}
 | 
						|
	L.ArgError(n, "series expected")
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func luaReportNew(L *lua.LState) int {
 | 
						|
	numvalues := L.CheckInt(1)
 | 
						|
	ud := L.NewUserData()
 | 
						|
	ud.Value = &Report{
 | 
						|
		Labels: make([]string, numvalues),
 | 
						|
		Series: make(map[string]*Series),
 | 
						|
	}
 | 
						|
	L.SetMetatable(ud, L.GetTypeMetatable(luaReportTypeName))
 | 
						|
	L.Push(ud)
 | 
						|
	return 1
 | 
						|
}
 | 
						|
 | 
						|
func luaReport__index(L *lua.LState) int {
 | 
						|
	field := L.CheckString(2)
 | 
						|
 | 
						|
	switch field {
 | 
						|
	case "Label", "label":
 | 
						|
		L.Push(L.NewFunction(luaReportLabel))
 | 
						|
	case "Series", "series":
 | 
						|
		L.Push(L.NewFunction(luaReportSeries))
 | 
						|
	default:
 | 
						|
		L.ArgError(2, "unexpected report attribute: "+field)
 | 
						|
	}
 | 
						|
 | 
						|
	return 1
 | 
						|
}
 | 
						|
 | 
						|
func luaReportLabel(L *lua.LState) int {
 | 
						|
	report := luaCheckReport(L, 1)
 | 
						|
	labelnumber := L.CheckInt(2)
 | 
						|
	label := L.CheckString(3)
 | 
						|
 | 
						|
	if labelnumber > cap(report.Labels) || labelnumber < 1 {
 | 
						|
		L.ArgError(2, "Label index must be between 1 and the number of data points, inclusive")
 | 
						|
	}
 | 
						|
	report.Labels[labelnumber-1] = label
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
func luaReportSeries(L *lua.LState) int {
 | 
						|
	report := luaCheckReport(L, 1)
 | 
						|
	name := L.CheckString(2)
 | 
						|
	ud := L.NewUserData()
 | 
						|
 | 
						|
	s, ok := report.Series[name]
 | 
						|
	if ok {
 | 
						|
		ud.Value = s
 | 
						|
	} else {
 | 
						|
		report.Series[name] = &Series{
 | 
						|
			Children: make(map[string]*Series),
 | 
						|
			Values:   make([]float64, cap(report.Labels)),
 | 
						|
		}
 | 
						|
		ud.Value = report.Series[name]
 | 
						|
	}
 | 
						|
	L.SetMetatable(ud, L.GetTypeMetatable(luaSeriesTypeName))
 | 
						|
	L.Push(ud)
 | 
						|
	return 1
 | 
						|
}
 | 
						|
 | 
						|
func luaSeries__index(L *lua.LState) int {
 | 
						|
	field := L.CheckString(2)
 | 
						|
 | 
						|
	switch field {
 | 
						|
	case "Value", "value":
 | 
						|
		L.Push(L.NewFunction(luaSeriesValue))
 | 
						|
	case "Series", "series", "Child", "child":
 | 
						|
		L.Push(L.NewFunction(luaSeriesChildren))
 | 
						|
	default:
 | 
						|
		L.ArgError(2, "unexpected series attribute: "+field)
 | 
						|
	}
 | 
						|
 | 
						|
	return 1
 | 
						|
}
 | 
						|
 | 
						|
func luaSeriesValue(L *lua.LState) int {
 | 
						|
	series := luaCheckSeries(L, 1)
 | 
						|
	valuenumber := L.CheckInt(2)
 | 
						|
	value := float64(L.CheckNumber(3))
 | 
						|
 | 
						|
	if valuenumber > cap(series.Values) || valuenumber < 1 {
 | 
						|
		L.ArgError(2, "value index must be between 1 and the number of data points, inclusive")
 | 
						|
	}
 | 
						|
	series.Values[valuenumber-1] = value
 | 
						|
 | 
						|
	return 0
 | 
						|
}
 | 
						|
 | 
						|
func luaSeriesChildren(L *lua.LState) int {
 | 
						|
	parent := luaCheckSeries(L, 1)
 | 
						|
	name := L.CheckString(2)
 | 
						|
	ud := L.NewUserData()
 | 
						|
 | 
						|
	s, ok := parent.Children[name]
 | 
						|
	if ok {
 | 
						|
		ud.Value = s
 | 
						|
	} else {
 | 
						|
		parent.Children[name] = &Series{
 | 
						|
			Children: make(map[string]*Series),
 | 
						|
			Values:   make([]float64, cap(parent.Values)),
 | 
						|
		}
 | 
						|
		ud.Value = parent.Children[name]
 | 
						|
	}
 | 
						|
	L.SetMetatable(ud, L.GetTypeMetatable(luaSeriesTypeName))
 | 
						|
	L.Push(ud)
 | 
						|
	return 1
 | 
						|
}
 |