diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5d8f72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin/ +dist/ diff --git a/cmd/cli/main.go b/cmd/cli/main.go new file mode 100644 index 0000000..249ceba --- /dev/null +++ b/cmd/cli/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "log" + "os" + + "git.tuxpa.in/a/card_id/common/game" +) + +func main() { + g, err := game.NewFromRoot(os.Getenv("CARD_DATA_DIR")) + if err != nil { + log.Panicln(err) + } + + log.Println(g.RandomLevel().RandomTable().RandomResult()) + +} diff --git a/common/data/grades.go b/common/data/grades.go new file mode 100644 index 0000000..4a263ca --- /dev/null +++ b/common/data/grades.go @@ -0,0 +1,31 @@ +package data + +import ( + "os" + + "gopkg.in/yaml.v3" +) + +type Grades []Grade + +type Grade struct { + Grade int `yaml:"Grade"` + Rate float64 `yaml:"Rate0"` + SpecialTable int `yaml:"Special_Table"` + SpecialRate float64 `yaml:"Special_Rate"` +} + +func NewGradesFromFile(path string) (Grades, error) { + out := []Grade{} + bts, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + err = yaml.Unmarshal(bts, &out) + if err != nil { + return nil, err + } + + return out, nil +} diff --git a/common/data/result.go b/common/data/result.go new file mode 100644 index 0000000..296ed25 --- /dev/null +++ b/common/data/result.go @@ -0,0 +1,30 @@ +package data + +import ( + "os" + + "gopkg.in/yaml.v3" +) + +type Results []Result + +type Result struct { + Itemid int `yaml:"Itemid"` + Name string `yaml:"Name"` + Rate float64 `yaml:"Rate"` +} + +func NewResultsFromFile(path string) (Results, error) { + out := []Result{} + bts, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + err = yaml.Unmarshal(bts, &out) + if err != nil { + return nil, err + } + + return out, nil +} diff --git a/common/game/game.go b/common/game/game.go new file mode 100644 index 0000000..36af49c --- /dev/null +++ b/common/game/game.go @@ -0,0 +1,68 @@ +package game + +import ( + "log" + "path" + "strconv" + + "git.tuxpa.in/a/card_id/common/data" + "git.tuxpa.in/a/card_id/common/game/level" + "git.tuxpa.in/a/card_id/common/game/table" + "lukechampine.com/frand" +) + +type Game struct { + Levels map[string]*level.Level + TotalProbability float64 +} + +func NewFromRoot(datadir string) (*Game, error) { + out := &Game{ + Levels: make(map[string]*level.Level, 12), + } + if datadir == "" { + datadir = "./data" + } + grades, err := data.NewGradesFromFile(path.Join(datadir, "GradeInfo.yaml")) + if err != nil { + return nil, err + } + for _, v := range grades { + lvl := &level.Level{} + lvl.Name = strconv.Itoa(v.Grade) + out.Levels[lvl.Name] = lvl + lvl.SelectionWeight = v.Rate + out.TotalProbability = out.TotalProbability + v.Rate + + rres, err := data.NewResultsFromFile(path.Join(datadir, "ResultTable", lvl.Name+".yaml")) + if err != nil { + return nil, err + } + lvl.RewardTable = table.New(rres) + if v.SpecialRate > 0 { + lvl.SpecialChance = v.SpecialRate + sres, err := data.NewResultsFromFile(path.Join(datadir, "SpecialTable", lvl.Name+".yaml")) + if err != nil { + return nil, err + } + lvl.SpecialTable = table.New(sres) + } + } + return out, nil +} + +func (g *Game) RandomLevel() *level.Level { + selector := frand.Float64() * g.TotalProbability + sofar := 0.0 + if len(g.Levels) == 0 { + return nil + } + for _, v := range g.Levels { + sofar = sofar + v.SelectionWeight + if sofar >= selector-0.000000001 { + return v + } + } + log.Println("BAD BAD BAD BAD BAD BAD PLEASE REPORT OH NO OH NO OH FISJAFIJNSAF") + return g.RandomLevel() +} diff --git a/common/game/level/level.go b/common/game/level/level.go new file mode 100644 index 0000000..5691131 --- /dev/null +++ b/common/game/level/level.go @@ -0,0 +1,25 @@ +package level + +import ( + "git.tuxpa.in/a/card_id/common/game/table" + "lukechampine.com/frand" +) + +type Level struct { + Name string + + SelectionWeight float64 + RewardTable *table.Table + SpecialTable *table.Table + SpecialChance float64 +} + +func (l *Level) RandomTable() *table.Table { + if l.SpecialChance == 0 { + return l.RewardTable + } + if l.SpecialChance > (frand.Float64() * 100) { + return l.SpecialTable + } + return l.RewardTable +} diff --git a/common/game/table/table.go b/common/game/table/table.go new file mode 100644 index 0000000..841b980 --- /dev/null +++ b/common/game/table/table.go @@ -0,0 +1,42 @@ +package table + +import ( + "fmt" + + "git.tuxpa.in/a/card_id/common/data" + "lukechampine.com/frand" +) + +// a table is a collection of results + +type Table struct { + raw data.Results + + TotalProbability float64 +} + +func New(r data.Results) *Table { + out := &Table{} + out.raw = r + + for _, v := range out.raw { + out.TotalProbability = out.TotalProbability + v.Rate + } + + return out +} + +func (t *Table) RandomResult() data.Result { + selector := frand.Float64() * t.TotalProbability + sofar := 0.0 + for _, v := range t.raw { + sofar = sofar + v.Rate + if sofar >= selector-0.000000001 { + return v + } + } + return data.Result{ + Name: fmt.Sprintf("please report this bug: %v", selector), + Rate: selector, + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8a4f0d7 --- /dev/null +++ b/go.mod @@ -0,0 +1,11 @@ +module git.tuxpa.in/a/card_id + +go 1.18 + +require gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + +require ( + github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb // indirect + lukechampine.com/frand v1.4.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a10dd4e --- /dev/null +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +lukechampine.com/frand v1.4.2 h1:RzFIpOvkMXuPMBb9maa4ND4wjBn71E1Jpf8BzJHMaVw= +lukechampine.com/frand v1.4.2/go.mod h1:4S/TM2ZgrKejMcKMbeLjISpJMO+/eZ1zu3vYX9dtj3s=