Add export to file (#58)

* Initial addition of a game exporter

* Fix snake state bug, remove test logs, fix final output line being empty

* Ignore test JSONL file

* Added explanation for design decision on the you key in SnakeResponse

* Adjust gitignore to be more generic

* Retain consistency in usage of pointer

* Re-word explanation to refer to requests instead of responses

* Remove unnecessary nil check

* Check error returned by WriteString

* Change file permissions for output file

* Initialise gameexporter regardless of whether output is requested

* Print error and exit if export to file fails

* Added another comment explaining reasoning around export checks

* Fixed broken test due to changed return type
This commit is contained in:
Simon Agius Muscat 2021-12-02 18:59:20 +01:00 committed by GitHub
parent 4a9dbbcaef
commit 142a5a6ecf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 184 additions and 38 deletions

86
cli/commands/output.go Normal file
View file

@ -0,0 +1,86 @@
package commands
import (
"encoding/json"
"fmt"
"log"
"os"
"github.com/BattlesnakeOfficial/rules/client"
)
type GameExporter struct {
game client.Game
snakeRequests []client.SnakeRequest
winner SnakeState
isDraw bool
}
type result struct {
WinnerID string `json:"winnerId"`
WinnerName string `json:"winnerName"`
IsDraw bool `json:"isDraw"`
}
func (ge *GameExporter) FlushToFile(filepath string, format string) error {
var formattedOutput []string
var formattingErr error
// TODO: Support more formats
if format == "JSONL" {
formattedOutput, formattingErr = ge.ConvertToJSON()
} else {
log.Fatalf("Invalid output format passed: %s", format)
}
if formattingErr != nil {
return formattingErr
}
f, err := os.OpenFile(filepath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer f.Close()
for _, line := range formattedOutput {
_, err := f.WriteString(fmt.Sprintf("%s\n", line))
if err != nil {
return err
}
}
log.Printf("Written %d lines of output to file: %s\n", len(formattedOutput), filepath)
return nil
}
func (ge *GameExporter) ConvertToJSON() ([]string, error) {
output := make([]string, 0)
serialisedGame, err := json.Marshal(ge.game)
if err != nil {
return output, err
}
output = append(output, string(serialisedGame))
for _, board := range ge.snakeRequests {
serialisedBoard, err := json.Marshal(board)
if err != nil {
return output, err
}
output = append(output, string(serialisedBoard))
}
serialisedResult, err := json.Marshal(result{
WinnerID: ge.winner.ID,
WinnerName: ge.winner.Name,
IsDraw: ge.isDraw,
})
if err != nil {
return output, err
}
output = append(output, string(serialisedResult))
return output, nil
}
func (ge *GameExporter) AddSnakeRequest(snakeRequest client.SnakeRequest) {
ge.snakeRequests = append(ge.snakeRequests, snakeRequest)
}