✨ Add ic-merge command
Still needs some work, like saving to a new file, but works well so far.
This commit is contained in:
parent
7aae44048a
commit
8a3da4c5fe
8 changed files with 499 additions and 0 deletions
34
cmd/ic-merge/main.go
Normal file
34
cmd/ic-merge/main.go
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
c "codeberg.org/danjones000/utils/cli/context"
|
||||||
|
e "codeberg.org/danjones000/utils/cli/err"
|
||||||
|
ic "codeberg.org/danjones000/utils/infinitecraft"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
ctx, done := c.SelfCancelingContext(context.Background())
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
m, err := ic.NewMerger(os.Args[1:])
|
||||||
|
e.HandleErr(err)
|
||||||
|
defer m.Close()
|
||||||
|
|
||||||
|
err = m.ParseFiles()
|
||||||
|
e.HandleErr(err)
|
||||||
|
err = m.ReadData(ctx)
|
||||||
|
e.HandleErr(err)
|
||||||
|
|
||||||
|
g, err := m.Merge(ctx)
|
||||||
|
e.HandleErr(err)
|
||||||
|
|
||||||
|
jsout := json.NewEncoder(os.Stdout)
|
||||||
|
jsout.SetIndent("", "\t")
|
||||||
|
err = jsout.Encode(g)
|
||||||
|
e.HandleErr(err)
|
||||||
|
// */
|
||||||
|
}
|
||||||
9
go.mod
9
go.mod
|
|
@ -6,6 +6,8 @@ require (
|
||||||
codeberg.org/danjones000/ezcache v0.5.2
|
codeberg.org/danjones000/ezcache v0.5.2
|
||||||
github.com/charmbracelet/bubbles v0.20.0
|
github.com/charmbracelet/bubbles v0.20.0
|
||||||
github.com/charmbracelet/bubbletea v1.1.1
|
github.com/charmbracelet/bubbletea v1.1.1
|
||||||
|
github.com/glebarez/go-sqlite v1.22.0
|
||||||
|
github.com/jmoiron/sqlx v1.4.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
@ -15,7 +17,9 @@ require (
|
||||||
github.com/charmbracelet/lipgloss v0.13.0 // indirect
|
github.com/charmbracelet/lipgloss v0.13.0 // indirect
|
||||||
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
github.com/charmbracelet/x/ansi v0.2.3 // indirect
|
||||||
github.com/charmbracelet/x/term v0.2.0 // indirect
|
github.com/charmbracelet/x/term v0.2.0 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
|
github.com/google/uuid v1.5.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
|
|
@ -23,8 +27,13 @@ require (
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/muesli/termenv v0.15.2 // indirect
|
github.com/muesli/termenv v0.15.2 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.24.0 // indirect
|
golang.org/x/sys v0.24.0 // indirect
|
||||||
golang.org/x/text v0.3.8 // indirect
|
golang.org/x/text v0.3.8 // indirect
|
||||||
|
modernc.org/libc v1.37.6 // indirect
|
||||||
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
|
modernc.org/memory v1.7.2 // indirect
|
||||||
|
modernc.org/sqlite v1.28.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
28
go.sum
28
go.sum
|
|
@ -1,5 +1,7 @@
|
||||||
codeberg.org/danjones000/ezcache v0.5.2 h1:msWRwbLj+HHCU3dnFbsdedCRuhyPQCOFbT9EgjwN9KM=
|
codeberg.org/danjones000/ezcache v0.5.2 h1:msWRwbLj+HHCU3dnFbsdedCRuhyPQCOFbT9EgjwN9KM=
|
||||||
codeberg.org/danjones000/ezcache v0.5.2/go.mod h1:wLTvTXfXxaEDUS9dOILqQmhAlB/9lUZCC2yB5CyGBfk=
|
codeberg.org/danjones000/ezcache v0.5.2/go.mod h1:wLTvTXfXxaEDUS9dOILqQmhAlB/9lUZCC2yB5CyGBfk=
|
||||||
|
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
|
||||||
|
|
@ -14,8 +16,22 @@ github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4h
|
||||||
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
|
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
|
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
|
||||||
|
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||||
|
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||||
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||||
|
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||||
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
|
@ -24,6 +40,8 @@ github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2J
|
||||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||||
|
|
@ -32,6 +50,8 @@ github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo
|
||||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
|
@ -51,3 +71,11 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
modernc.org/libc v1.37.6 h1:orZH3c5wmhIQFTXF+Nt+eeauyd+ZIt2BX6ARe+kD+aw=
|
||||||
|
modernc.org/libc v1.37.6/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
|
||||||
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
|
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||||
|
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||||
|
modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ=
|
||||||
|
modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
|
||||||
|
|
|
||||||
5
infinitecraft/errors.go
Normal file
5
infinitecraft/errors.go
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
package infinitecraft
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var ErrNotParsed = errors.New("not yet parsed")
|
||||||
10
infinitecraft/game.go
Normal file
10
infinitecraft/game.go
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
package infinitecraft
|
||||||
|
|
||||||
|
type Game struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Created uint64 `json:"created"`
|
||||||
|
Updated uint64 `json:"updated"`
|
||||||
|
Instances []any `json:"instances" db:"-"`
|
||||||
|
Items []Item `json:"items" db:"-"`
|
||||||
|
}
|
||||||
9
infinitecraft/item.go
Normal file
9
infinitecraft/item.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package infinitecraft
|
||||||
|
|
||||||
|
type Item struct {
|
||||||
|
Id int32 `json:"id"`
|
||||||
|
Text string `json:"text" db:"name"`
|
||||||
|
Emoji string `json:"emoji"`
|
||||||
|
Discovery bool `json:"discovery,omitempty"`
|
||||||
|
Recipes [][]int32 `json:"recipes,omitempty" db:"-"`
|
||||||
|
}
|
||||||
379
infinitecraft/merger.go
Normal file
379
infinitecraft/merger.go
Normal file
|
|
@ -0,0 +1,379 @@
|
||||||
|
package infinitecraft
|
||||||
|
|
||||||
|
import (
|
||||||
|
"compress/gzip"
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
_ "github.com/glebarez/go-sqlite"
|
||||||
|
"github.com/jmoiron/sqlx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Merger struct {
|
||||||
|
files []*os.File
|
||||||
|
games []Game
|
||||||
|
parsed bool
|
||||||
|
db *sqlx.DB
|
||||||
|
gameMap map[int64]Game
|
||||||
|
itemMap map[int64]Item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) Games() map[int64]Game {
|
||||||
|
return m.gameMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) Items() map[int64]Item {
|
||||||
|
return m.itemMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) Close() error {
|
||||||
|
errs := make([]error, 0, len(m.files)+1)
|
||||||
|
for _, f := range m.files {
|
||||||
|
errs = append(errs, f.Close())
|
||||||
|
}
|
||||||
|
errs = append(errs, m.db.Close())
|
||||||
|
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) ParseFiles() error {
|
||||||
|
m.games = make([]Game, len(m.files))
|
||||||
|
errs := make([]error, len(m.files))
|
||||||
|
for idx, f := range m.files {
|
||||||
|
unz, err := gzip.NewReader(f)
|
||||||
|
if err != nil {
|
||||||
|
errs[idx] = err
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dec := json.NewDecoder(unz)
|
||||||
|
errs[idx] = dec.Decode(&(m.games[idx]))
|
||||||
|
}
|
||||||
|
err := errors.Join(errs...)
|
||||||
|
if err == nil {
|
||||||
|
m.parsed = true
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
const schema string = `
|
||||||
|
CREATE TABLE IF NOT EXISTS games (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
version TEXT NOT NULL,
|
||||||
|
created INTEGER NOT NULL,
|
||||||
|
updated INTEGER NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS items (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
emoji TEXT NOT NULL,
|
||||||
|
discovery BOOLEAN NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS games_items (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
game_id INTEGER NOT NULL,
|
||||||
|
item_id INTEGER NOT NULL,
|
||||||
|
orig_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(game_id) REFERENCES games(id),
|
||||||
|
FOREIGN KEY(item_id) REFERENCES items(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS recipes (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
item_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(item_id) REFERENCES items(id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS recipes_items (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
recipe_id INTEGER NOT NULL,
|
||||||
|
parent_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY(recipe_id) REFERENCES recipes(id),
|
||||||
|
FOREIGN KEY(parent_id) REFERENCES items(id)
|
||||||
|
);
|
||||||
|
`
|
||||||
|
|
||||||
|
// select i.name as text, group_concat(par.name) as ingredients from items i join recipes r on r.item_id = i.id join recipes_items ri on ri.recipe_id = r.id join items par on ri.parent_id = par.id group by ri.recipe_id ;
|
||||||
|
|
||||||
|
func (m *Merger) ReadData(ctx context.Context) (err error) {
|
||||||
|
//nolint:gocritic // temp stuff
|
||||||
|
// m.db, err = sqlx.Open("sqlite", "foo.db")
|
||||||
|
m.db, err = sqlx.Open("sqlite", ":memory:")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = m.db.ExecContext(ctx, schema)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.gameMap, err = m.insertGames(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.itemMap = make(map[int64]Item)
|
||||||
|
for gameID, game := range m.gameMap {
|
||||||
|
var itM map[int64]Item
|
||||||
|
itM, err = m.insertItems(ctx, gameID, game.Items)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for itemID, it := range itM {
|
||||||
|
m.itemMap[itemID] = it
|
||||||
|
err = m.insertRecipes(ctx, gameID, itemID, it.Recipes)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) getGameDetails(ctx context.Context, g *Game) error {
|
||||||
|
return m.db.GetContext(ctx, g, `SELECT name, version FROM games ORDER BY id ASC LIMIT 1`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) getGameCreated(ctx context.Context, date *uint64) error {
|
||||||
|
return m.db.GetContext(ctx, date, `SELECT MIN(created) FROM games`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) getGameUpdated(ctx context.Context, date *uint64) error {
|
||||||
|
return m.db.GetContext(ctx, date, `SELECT MAX(updated) FROM games`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) getItems(ctx context.Context, items *[]Item) error {
|
||||||
|
return m.db.SelectContext(ctx, items, `
|
||||||
|
SELECT
|
||||||
|
id-1 AS id,
|
||||||
|
name,
|
||||||
|
emoji,
|
||||||
|
discovery
|
||||||
|
FROM items
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) getRecipes(ctx context.Context, items []Item) (err error) {
|
||||||
|
var rows *sqlx.Rows
|
||||||
|
if rows, err = m.db.QueryxContext(ctx, `
|
||||||
|
SELECT
|
||||||
|
r.item_id-1 AS itemid,
|
||||||
|
ri.recipe_id AS recipeid,
|
||||||
|
ri.parent_id-1 AS parentid
|
||||||
|
FROM recipes_items ri
|
||||||
|
JOIN recipes r ON ri.recipe_id = r.id
|
||||||
|
`); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rows.Close()
|
||||||
|
rm := make(map[int32]map[int32][]int32)
|
||||||
|
var found bool
|
||||||
|
var recRow struct {
|
||||||
|
ItemID int32
|
||||||
|
RecipeID int32
|
||||||
|
ParentID int32
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
if err = rows.StructScan(&recRow); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, found = rm[recRow.ItemID]; !found {
|
||||||
|
rm[recRow.ItemID] = make(map[int32][]int32)
|
||||||
|
}
|
||||||
|
if _, found = rm[recRow.ItemID][recRow.RecipeID]; !found {
|
||||||
|
rm[recRow.ItemID][recRow.RecipeID] = make([]int32, 0, 2)
|
||||||
|
}
|
||||||
|
rm[recRow.ItemID][recRow.RecipeID] = append(rm[recRow.ItemID][recRow.RecipeID], recRow.ParentID)
|
||||||
|
}
|
||||||
|
var recs map[int32][]int32
|
||||||
|
for idx := range items {
|
||||||
|
if recs, found = rm[items[idx].Id]; found {
|
||||||
|
items[idx].Recipes = make([][]int32, 0, len(recs))
|
||||||
|
for _, rec := range recs {
|
||||||
|
items[idx].Recipes = append(items[idx].Recipes, rec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) Merge(ctx context.Context) (g Game, err error) {
|
||||||
|
if err = m.getGameDetails(ctx, &g); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = m.getGameCreated(ctx, &g.Created); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = m.getGameUpdated(ctx, &g.Updated); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = m.getItems(ctx, &g.Items); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = m.getRecipes(ctx, g.Items)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type GameItem struct {
|
||||||
|
Game string `db:"game"`
|
||||||
|
GameID int64 `db:"game_id"`
|
||||||
|
Text string `db:"name"`
|
||||||
|
Emoji string
|
||||||
|
Id int64 `db:"orig_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) GameItems(ctx context.Context) (gits []GameItem, err error) {
|
||||||
|
err = m.db.SelectContext(ctx, &gits, `
|
||||||
|
SELECT
|
||||||
|
g.name AS game,
|
||||||
|
g.id AS game_id,
|
||||||
|
it.name,
|
||||||
|
it.emoji,
|
||||||
|
it.id - 1 AS orig_id
|
||||||
|
FROM games_items gi
|
||||||
|
JOIN items it ON gi.item_id = it.id
|
||||||
|
JOIN games g ON gi.game_id = g.id
|
||||||
|
ORDER BY gi.id ASC
|
||||||
|
`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) insertGames(ctx context.Context) (mp map[int64]Game, err error) {
|
||||||
|
mp = make(map[int64]Game, len(m.games))
|
||||||
|
var res sql.Result
|
||||||
|
var stmt *sqlx.NamedStmt
|
||||||
|
stmt, err = m.db.PrepareNamedContext(ctx, `
|
||||||
|
INSERT INTO games
|
||||||
|
(name, version, created, updated)
|
||||||
|
VALUES (:name, :version, :created, :updated)
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
for _, g := range m.games {
|
||||||
|
res, err = stmt.ExecContext(ctx, g)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var id int64
|
||||||
|
id, err = res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mp[id] = g
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) insertItems(ctx context.Context, gameID int64, items []Item) (itM map[int64]Item, err error) {
|
||||||
|
itM = make(map[int64]Item, len(items))
|
||||||
|
var stmt *sqlx.NamedStmt
|
||||||
|
var fetchIDStmt *sqlx.Stmt
|
||||||
|
var relStmt *sqlx.Stmt
|
||||||
|
stmt, err = m.db.PrepareNamedContext(ctx, `
|
||||||
|
INSERT OR IGNORE INTO items
|
||||||
|
(name, emoji, discovery)
|
||||||
|
VALUES (:name, :emoji, :discovery)
|
||||||
|
ON CONFLICT(name) DO UPDATE SET
|
||||||
|
emoji=excluded.emoji,
|
||||||
|
discovery=excluded.discovery
|
||||||
|
`)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer stmt.Close()
|
||||||
|
fetchIDStmt, err = m.db.PreparexContext(ctx, `SELECT id FROM items WHERE name = ?`)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer fetchIDStmt.Close()
|
||||||
|
relStmt, err = m.db.PreparexContext(ctx, `
|
||||||
|
INSERT INTO games_items
|
||||||
|
(game_id, item_id, orig_id)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer relStmt.Close()
|
||||||
|
for _, it := range items {
|
||||||
|
_, err = stmt.ExecContext(ctx, it)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var id int64
|
||||||
|
err = fetchIDStmt.GetContext(ctx, &id, it.Text)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = relStmt.ExecContext(ctx, gameID, id, it.Id)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
itM[id] = it
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Merger) insertRecipes(ctx context.Context, gameID, itemID int64, recipes [][]int32) (err error) {
|
||||||
|
var res sql.Result
|
||||||
|
var insertStmt *sqlx.Stmt
|
||||||
|
var selStmt *sqlx.Stmt
|
||||||
|
var insertRecItemStmt *sqlx.Stmt
|
||||||
|
insertStmt, err = m.db.PreparexContext(ctx, `
|
||||||
|
INSERT INTO recipes (item_id) VALUES (?)
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer insertStmt.Close()
|
||||||
|
insertRecItemStmt, err = m.db.PreparexContext(ctx, `
|
||||||
|
INSERT INTO recipes_items
|
||||||
|
(recipe_id, parent_id)
|
||||||
|
VALUES (?, ?)
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer insertRecItemStmt.Close()
|
||||||
|
selStmt, err = m.db.PreparexContext(ctx, `
|
||||||
|
SELECT item_id FROM games_items
|
||||||
|
WHERE game_id = ? AND orig_id = ?
|
||||||
|
`)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer selStmt.Close()
|
||||||
|
for _, recipe := range recipes {
|
||||||
|
var recipeID int64
|
||||||
|
res, err = insertStmt.ExecContext(ctx, itemID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
recipeID, err = res.LastInsertId()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, origID := range recipe {
|
||||||
|
var parentID int64
|
||||||
|
err = selStmt.GetContext(ctx, &parentID, gameID, origID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = insertRecItemStmt.ExecContext(ctx, recipeID, parentID)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
25
infinitecraft/new.go
Normal file
25
infinitecraft/new.go
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
package infinitecraft
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewMerger(args []string) (*Merger, error) {
|
||||||
|
m := Merger{}
|
||||||
|
var err error
|
||||||
|
if len(args) < 2 {
|
||||||
|
//nolint:err113 // Don't care
|
||||||
|
return nil, fmt.Errorf("expected at lease 2 arguments. Got %d", len(args))
|
||||||
|
}
|
||||||
|
fs := make([]*os.File, len(args))
|
||||||
|
for idx, pth := range args {
|
||||||
|
fs[idx], err = os.Open(pth)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.files = fs
|
||||||
|
|
||||||
|
return &m, nil
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue