From 7e752e56deef29320c100866f8a63cd0becb075a Mon Sep 17 00:00:00 2001 From: mrsombre <376535+mrsombre@users.noreply.github.com> Date: Tue, 16 Jan 2024 00:51:21 +0100 Subject: [PATCH] Game input read and data processing --- command.go | 32 +++++++++++++++++++++++ command_test.go | 30 ++++++++++++++++++++++ data.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ data_test.go | 24 +++++++++++++++++ input.go | 60 +++++++++++++++++++++++++++++++++++++++++++ input_test.go | 29 +++++++++++++++++++++ main.go | 28 ++++++++++++++++++++ reader.go | 32 +++++++++++++++++++++++ reader_test.go | 38 +++++++++++++++++++++++++++ 9 files changed, 341 insertions(+) create mode 100644 command.go create mode 100644 command_test.go create mode 100644 data.go create mode 100644 data_test.go create mode 100644 input.go create mode 100644 input_test.go create mode 100644 reader.go create mode 100644 reader_test.go diff --git a/command.go b/command.go new file mode 100644 index 0000000..542a24d --- /dev/null +++ b/command.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "io" + "os" +) + +// Command is an interface for game commands. + +var commandOutput io.Writer = os.Stdout + +type Command interface { + String() string +} + +type Commands []Command + +type MockCommand struct { + Param1 float64 + Param2 float64 +} + +func (c MockCommand) String() string { + return fmt.Sprintf("%.f %.f", c.Param1, c.Param2) +} + +func ExecuteCommands(commands Commands) { + for _, command := range commands { + fmt.Fprintln(commandOutput, command) + } +} diff --git a/command_test.go b/command_test.go new file mode 100644 index 0000000..416ecbc --- /dev/null +++ b/command_test.go @@ -0,0 +1,30 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +type mockWriter struct { + data []byte +} + +func (w *mockWriter) Write(p []byte) (n int, err error) { + w.data = p + return len(p), nil +} + +func TestMockCommand_String(t *testing.T) { + cmd := MockCommand{1, 2} + assert.Equal(t, "1 2", cmd.String()) +} + +func TestExecuteCommand(t *testing.T) { + commandOutput = &mockWriter{} + ExecuteCommands(Commands{MockCommand{1, 2}}) + + want := "1 2\n" + got := commandOutput.(*mockWriter).data + assert.Equal(t, want, string(got)) +} diff --git a/data.go b/data.go new file mode 100644 index 0000000..4f5f707 --- /dev/null +++ b/data.go @@ -0,0 +1,68 @@ +package main + +// Export/Import of data in the form of string arrays. +// This can be used to unload the conditions of a problem (input) +// in a compressed form into the debug console and unpack it in the IDE. + +import ( + "bytes" + "compress/gzip" + "encoding/base64" + "encoding/json" +) + +// DataExport serializes and compresses a slice of strings, +// returning a base64 encoded string. +func DataExport(data []string) string { + var err error + + jsonData, err := json.Marshal(data) + if err != nil { + panic(err) + } + + var gzBuf bytes.Buffer + gz := gzip.NewWriter(&gzBuf) + if _, err = gz.Write(jsonData); err != nil { + panic(err) + } + if err = gz.Close(); err != nil { + panic(err) + } + + return base64.StdEncoding.EncodeToString(gzBuf.Bytes()) +} + +// DataImport decodes a base64 string, decompresses it, +// and deserializes the JSON data into a slice of strings. +func DataImport(encodedData string) []string { + var err error + + gzData, err := base64.StdEncoding.DecodeString(encodedData) + if err != nil { + panic(err) + } + + gz, err := gzip.NewReader(bytes.NewBuffer(gzData)) + if err != nil { + panic(err) + } + defer func(gz *gzip.Reader) { + err = gz.Close() + if err != nil { + panic(err) + } + }(gz) + + var jsonData bytes.Buffer + if _, err = jsonData.ReadFrom(gz); err != nil { + panic(err) + } + + var data []string + if err = json.Unmarshal(jsonData.Bytes(), &data); err != nil { + panic(err) + } + + return data +} diff --git a/data_test.go b/data_test.go new file mode 100644 index 0000000..6dce732 --- /dev/null +++ b/data_test.go @@ -0,0 +1,24 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +var dataExportTests = []string{ + "123", + "abc", +} + +func TestDataExport(t *testing.T) { + data := DataExport(dataExportTests) + assert.Equal(t, dataImportTests, data) +} + +var dataImportTests = `H4sIAAAAAAAA/4pWMjQyVtJRSkxKVooFBAAA//9iXM2zDQAAAA==` + +func TestDataImport(t *testing.T) { + data := DataImport(dataImportTests) + assert.Equal(t, dataExportTests, data) +} diff --git a/input.go b/input.go new file mode 100644 index 0000000..d578bee --- /dev/null +++ b/input.go @@ -0,0 +1,60 @@ +package main + +import ( + "fmt" +) + +type Unit struct { + x, y, z float64 +} + +type Turn struct { + Power float64 + L, R string +} + +type Game struct { + Units []Unit +} + +func InputGame(data []string) Game { + var err error + var game Game + + var size int + size = StrToInt(data[0]) + data = data[1:] + var unit Unit + units := make([]Unit, 0, size) + for i := 0; i < size; i++ { + _, err = fmt.Sscan(data[i], &unit.x, &unit.y, &unit.z) + if err != nil { + panic(err) + } + units = append(units, unit) + } + + // some additional logic + game.Units = units + + return game +} + +func InputStep(data []string) Turn { + var err error + + var turn Turn + _, err = fmt.Sscan( + data[0], + &turn.Power, + &turn.L, + &turn.R, + ) + if err != nil { + panic(err) + } + + // some additional logic + + return turn +} diff --git a/input_test.go b/input_test.go new file mode 100644 index 0000000..3ac65df --- /dev/null +++ b/input_test.go @@ -0,0 +1,29 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestInputGame(t *testing.T) { + game := InputGame(readGameTests) + want := Game{ + Units: []Unit{ + {1, 2, 3}, + {4, 5, 6}, + {7, 8, 9}, + }, + } + assert.Equal(t, want, game) +} + +func TestInputStep(t *testing.T) { + turn := InputStep(readStepTests) + want := Turn{ + Power: 1, + L: "R", + R: "L", + } + assert.Equal(t, want, turn) +} diff --git a/main.go b/main.go index bdf24a4..b4c1204 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,9 @@ package main import ( + "bufio" "math/rand" + "os" "runtime" "time" ) @@ -13,3 +15,29 @@ func init() { rnd = rand.New(rand.NewSource(time.Now().UnixNano())) debug = true } + +func main() { + // example + scanner := bufio.NewScanner(os.Stdin) + scanner.Buffer(make([]byte, 1000000), 1000000) + + dataGame := ReadGame(scanner) + asText(DataExport(dataGame)) + game := InputGame(dataGame) + + dataStep := ReadStep(scanner) + asText(DataExport(dataStep)) + step := InputStep(dataStep) + + // some game logic for the first step + u(game, step) + + for { + dataStep = ReadStep(scanner) + asText(DataExport(dataStep)) + step = InputStep(dataStep) + + // some game logic for the next step + u(game, step) + } +} diff --git a/reader.go b/reader.go new file mode 100644 index 0000000..91cb89a --- /dev/null +++ b/reader.go @@ -0,0 +1,32 @@ +package main + +import ( + "bufio" +) + +// Reading the game state from the standard input stream. + +// ReadGame reads the game state from the standard input stream. +func ReadGame(s *bufio.Scanner) []string { + data := make([]string, 0, 32) + + s.Scan() + size := s.Text() + data = append(data, size) + for i := 0; i < StrToInt(size); i++ { + s.Scan() + data = append(data, s.Text()) + } + + return data +} + +// ReadStep reads the game turn state from the standard input stream. +func ReadStep(s *bufio.Scanner) []string { + data := make([]string, 0, 1) + + s.Scan() + data = append(data, s.Text()) + + return data +} diff --git a/reader_test.go b/reader_test.go new file mode 100644 index 0000000..b982254 --- /dev/null +++ b/reader_test.go @@ -0,0 +1,38 @@ +package main + +import ( + "bufio" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +var readGameTests = []string{ + "3", + "1 2 3", + "4 5 6", + "7 8 9", +} + +func TestReadGame(t *testing.T) { + s := strings.Join(readGameTests, "\n") + r := strings.NewReader(s) + b := bufio.NewScanner(r) + + data := ReadGame(b) + assert.Equal(t, readGameTests, data) +} + +var readStepTests = []string{ + "1 R L", +} + +func TestReadStep(t *testing.T) { + s := strings.Join(readStepTests, "\n") + r := strings.NewReader(s) + b := bufio.NewScanner(r) + + data := ReadStep(b) + assert.Equal(t, readStepTests, data) +}