Skip to content

Commit

Permalink
add stats package (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
vadv authored Aug 28, 2019
1 parent d4ac4b6 commit 5229da7
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ go get github.com/vadv/gopher-lua-libs
* [prometheus](/prometheus/client) prometheus exporter
* [regexp](/regexp) regexp port
* [runtime](/runtime) runtime port
* [stats](/stats) stats [https://github.com/montanaflynn/stats](https://github.com/montanaflynn/stats) port
* [storage](/storage) package for store persist data and share values between lua states
* [strings](/strings) strings port (utf supported)
* [tac](/tac) tac line-by-line scanner (from end of file to up)
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ require (
github.com/lib/pq v1.2.0
github.com/mattn/go-sqlite3 v1.11.0
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/montanaflynn/stats v0.4.0
github.com/prometheus/client_golang v1.0.0
github.com/technoweenie/multipartstreamer v1.0.1
github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/montanaflynn/stats v0.4.0 h1:Ug//pM6DXionEL5D5a8C0PJIXhojyxTFErfBVEEhqDM=
github.com/montanaflynn/stats v0.4.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
6 changes: 3 additions & 3 deletions http/util/util_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func ExampleParseUrl() {
Preload(state)
source := `
local http_util = require("http_util")
local url, err = http_util.parse_url("http://u1:p2@host:port/pathx?k1=v1&k2=v2&k1=vx")
local url, err = http_util.parse_url("http://u1:p2@host:80/pathx?k1=v1&k2=v2&k1=vx")
if err then error(err) end
print(url.path)
`
Expand All @@ -29,7 +29,7 @@ func ExampleBuidUrl() {
Preload(state)
source := `
local http_util = require("http_util")
local url, err = http_util.parse_url("http://u1:p2@host:port/pathx?k1=v1&k2=v2&k1=vx")
local url, err = http_util.parse_url("http://u1:p2@host:80/pathx?k1=v1&k2=v2&k1=vx")
if err then error(err) end
url.path = "path2"
print(http_util.build_url(url))
Expand All @@ -38,5 +38,5 @@ func ExampleBuidUrl() {
log.Fatal(err.Error())
}
// Output:
// http://u1:p2@host:port/path2?k1=v1&k1=vx&k2=v2
// http://u1:p2@host:80/path2?k1=v1&k1=vx&k2=v2
}
3 changes: 3 additions & 0 deletions plugin/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"context"
"sync"

"github.com/vadv/gopher-lua-libs/stats"

cloudwatch "github.com/vadv/gopher-lua-libs/aws/cloudwatch"
chef "github.com/vadv/gopher-lua-libs/chef"
cmd "github.com/vadv/gopher-lua-libs/cmd"
Expand Down Expand Up @@ -100,6 +102,7 @@ func NewPluginState() *lua.LState {
cloudwatch.Preload(state)
log.Preload(state)
prometheus.Preload(state)
stats.Preload(state)
return state
}

Expand Down
2 changes: 2 additions & 0 deletions preload.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
prometheus "github.com/vadv/gopher-lua-libs/prometheus/client"
regexp "github.com/vadv/gopher-lua-libs/regexp"
runtime "github.com/vadv/gopher-lua-libs/runtime"
"github.com/vadv/gopher-lua-libs/stats"
storage "github.com/vadv/gopher-lua-libs/storage"
strings "github.com/vadv/gopher-lua-libs/strings"
tac "github.com/vadv/gopher-lua-libs/tac"
Expand Down Expand Up @@ -65,4 +66,5 @@ func Preload(L *lua.LState) {
template.Preload(L)
cloudwatch.Preload(L)
log.Preload(L)
stats.Preload(L)
}
3 changes: 2 additions & 1 deletion preload.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ require("template")
require("pprof")
require("cloudwatch")
require("log")
require("prometheus")
require("prometheus")
require("stats")
16 changes: 16 additions & 0 deletions stats/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# stats [![GoDoc](https://godoc.org/github.com/vadv/gopher-lua-libs/stats?status.svg)](https://godoc.org/github.com/vadv/gopher-lua-libs/stats)

## Usage

```lua
local stats = require("stats")

local result, _ = stats.median({0,0,10})
print(result)
-- Output: 0

local result, _ = stats.percentile({0,0,10}, 100)
print(result)
-- Output: 10
```

80 changes: 80 additions & 0 deletions stats/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Package strings implements golang package montanaflynn/stats functionality for lua.
package stats

import (
"fmt"

gostats "github.com/montanaflynn/stats"
lua "github.com/yuin/gopher-lua"
)

// get float slice from table
func getFloatSliceFromTable(L *lua.LState, n int) ([]float64, error) {
tbl := L.CheckTable(n)
data := make([]float64, tbl.Len())
var err error
tbl.ForEach(func(k lua.LValue, v lua.LValue) {
value, ok := v.(lua.LNumber)
if !ok {
err = fmt.Errorf("only table of numbers is supported")
return
}
data = append(data, float64(value))
})
return data, err
}

// Median lua stats.median(table): port of go montanaflynn/stats.Median() returns value and error
func Median(L *lua.LState) int {
data, err := getFloatSliceFromTable(L, 1)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
result, err := gostats.Median(data)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
L.Push(lua.LNumber(result))
return 1
}

// Percentile lua stats.median(table, percentile): port of go montanaflynn/stats.Percentile() returns value and error
func Percentile(L *lua.LState) int {
data, err := getFloatSliceFromTable(L, 1)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
percentile := L.CheckNumber(2)
result, err := gostats.Percentile(data, float64(percentile))
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
L.Push(lua.LNumber(result))
return 1
}

// StandardDeviation lua stats.median(table, percentile): port of go montanaflynn/stats.StandardDeviation() returns value and error
func StandardDeviation(L *lua.LState) int {
data, err := getFloatSliceFromTable(L, 1)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
result, err := gostats.StandardDeviation(data)
if err != nil {
L.Push(lua.LNil)
L.Push(lua.LString(err.Error()))
return 2
}
L.Push(lua.LNumber(result))
return 1
}
15 changes: 15 additions & 0 deletions stats/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package stats

import (
"testing"

lua "github.com/yuin/gopher-lua"
)

func TestApi(t *testing.T) {
state := lua.NewState()
Preload(state)
if err := state.DoFile("./test/test_api.lua"); err != nil {
t.Fatalf("execute test: %s\n", err.Error())
}
}
27 changes: 27 additions & 0 deletions stats/loader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package stats

import (
lua "github.com/yuin/gopher-lua"
)

// Preload adds stats to the given Lua state's package.preload table. After it
// has been preloaded, it can be loaded using require:
//
// local stats = require("stats")
func Preload(L *lua.LState) {
L.PreloadModule("stats", Loader)
}

// Loader is the module loader function.
func Loader(L *lua.LState) int {
t := L.NewTable()
L.SetFuncs(t, api)
L.Push(t)
return 1
}

var api = map[string]lua.LGFunction{
"median": Median,
"percentile": Percentile,
"standard_deviation": StandardDeviation,
}
17 changes: 17 additions & 0 deletions stats/test/test_api.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
local stats = require("stats")

local result, err = stats.median({0,0,10})
if err then error(err) end
if not(result == 0) then error("median get: "..tostring(result)) end

local result, err = stats.percentile({0,0,10}, 100)
if err then error(err) end
if not(result == 10) then error("percentile get: "..tostring(result)) end

local result, err = stats.percentile({0,0,10}, 60)
if err then error(err) end
if not(result == 0) then error("percentile get: "..tostring(result)) end

local result, err = stats.standard_deviation({1,1,1,1})
if err then error(err) end
if not(result == 0.5) then error("standard_deviation get: "..tostring(result)) end

0 comments on commit 5229da7

Please sign in to comment.