Skip to content

Commit

Permalink
Game input read and data processing
Browse files Browse the repository at this point in the history
  • Loading branch information
mrsombre committed Jan 15, 2024
1 parent 5896f9a commit 7e752e5
Show file tree
Hide file tree
Showing 9 changed files with 341 additions and 0 deletions.
32 changes: 32 additions & 0 deletions command.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
30 changes: 30 additions & 0 deletions command_test.go
Original file line number Diff line number Diff line change
@@ -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))
}
68 changes: 68 additions & 0 deletions data.go
Original file line number Diff line number Diff line change
@@ -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)

Check warning on line 21 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L21

Added line #L21 was not covered by tests
}

var gzBuf bytes.Buffer
gz := gzip.NewWriter(&gzBuf)
if _, err = gz.Write(jsonData); err != nil {
panic(err)

Check warning on line 27 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L27

Added line #L27 was not covered by tests
}
if err = gz.Close(); err != nil {
panic(err)

Check warning on line 30 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L30

Added line #L30 was not covered by tests
}

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)

Check warning on line 43 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L43

Added line #L43 was not covered by tests
}

gz, err := gzip.NewReader(bytes.NewBuffer(gzData))
if err != nil {
panic(err)

Check warning on line 48 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L48

Added line #L48 was not covered by tests
}
defer func(gz *gzip.Reader) {
err = gz.Close()
if err != nil {
panic(err)

Check warning on line 53 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L53

Added line #L53 was not covered by tests
}
}(gz)

var jsonData bytes.Buffer
if _, err = jsonData.ReadFrom(gz); err != nil {
panic(err)

Check warning on line 59 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L59

Added line #L59 was not covered by tests
}

var data []string
if err = json.Unmarshal(jsonData.Bytes(), &data); err != nil {
panic(err)

Check warning on line 64 in data.go

View check run for this annotation

Codecov / codecov/patch

data.go#L64

Added line #L64 was not covered by tests
}

return data
}
24 changes: 24 additions & 0 deletions data_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
60 changes: 60 additions & 0 deletions input.go
Original file line number Diff line number Diff line change
@@ -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)

Check warning on line 32 in input.go

View check run for this annotation

Codecov / codecov/patch

input.go#L32

Added line #L32 was not covered by tests
}
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)

Check warning on line 54 in input.go

View check run for this annotation

Codecov / codecov/patch

input.go#L54

Added line #L54 was not covered by tests
}

// some additional logic

return turn
}
29 changes: 29 additions & 0 deletions input_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
28 changes: 28 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package main

import (
"bufio"
"math/rand"
"os"
"runtime"
"time"
)
Expand All @@ -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)
}

Check warning on line 42 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L19-L42

Added lines #L19 - L42 were not covered by tests
}
32 changes: 32 additions & 0 deletions reader.go
Original file line number Diff line number Diff line change
@@ -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
}
38 changes: 38 additions & 0 deletions reader_test.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 7e752e5

Please sign in to comment.