clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

refactor/root-tui-model
puzzletea / games / fillomino / export.go
export.go 2.2K
1package fillomino23import (4 "encoding/json"5 "fmt"67 "github.com/FelineStateMachine/puzzletea/game"8)910type Save struct {11 Width int `json:"width"`12 Height int `json:"height"`13 State string `json:"state"`14 Provided string `json:"provided"`15 ModeTitle string `json:"mode_title"`16 MaxCellValue int `json:"max_cell_value,omitempty"`17}1819func (m Model) GetSave() ([]byte, error) {20 save := Save{21 Width: m.width,22 Height: m.height,23 State: encodeGrid(m.grid),24 Provided: serializeProvided(m.provided),25 ModeTitle: m.modeTitle,26 MaxCellValue: m.maxCellValue,27 }28 data, err := json.Marshal(save)29 if err != nil {30 return nil, fmt.Errorf("marshal fillomino save: %w", err)31 }32 return data, nil33}3435func ImportModel(data []byte) (*Model, error) {36 var save Save37 if err := json.Unmarshal(data, &save); err != nil {38 return nil, fmt.Errorf("unmarshal fillomino save: %w", err)39 }40 if save.Width <= 0 || save.Height <= 0 {41 return nil, fmt.Errorf("invalid fillomino size %dx%d", save.Width, save.Height)42 }4344 state, err := parseGrid(save.State, save.Width, save.Height)45 if err != nil {46 return nil, fmt.Errorf("decode fillomino state: %w", err)47 }48 provided := deserializeProvided(save.Provided, save.Width, save.Height)49 for y := range save.Height {50 for x := range save.Width {51 if provided[y][x] && state[y][x] == 0 {52 return nil, fmt.Errorf("provided cell at (%d,%d) is empty", x, y)53 }54 }55 }5657 m := &Model{58 width: save.Width,59 height: save.Height,60 grid: state,61 initialGrid: initialGridForImport(state, provided),62 provided: provided,63 cursor: game.Cursor{},64 keys: DefaultKeyMap,65 modeTitle: save.ModeTitle,66 maxCellValue: restoredMaxCellValue(save.MaxCellValue, state),67 }68 m.recompute()69 return m, nil70}7172func restoredMaxCellValue(savedMax int, state grid) int {73 if savedMax > 0 {74 return savedMax75 }7677 return max(1, maxCellValue(state))78}7980func initialGridForImport(state grid, provided [][]bool) grid {81 initial := newGrid(len(state[0]), len(state))82 for y := range len(state) {83 for x := range len(state[y]) {84 if provided[y][x] {85 initial[y][x] = state[y][x]86 }87 }88 }89 return initial90}