clone

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

chore/app-model-decomp
puzzletea / export / pdf / parse_wordsearch.go
parse_wordsearch.go 1.6K
1package pdfexport23import (4 "encoding/json"5 "fmt"6 "strings"7 "unicode"8)910type wordSearchSave struct {11 Width int `json:"width"`12 Height int `json:"height"`13 Grid string `json:"grid"`14 Words []wordSearchWord `json:"words"`15}1617type wordSearchWord struct {18 Text string `json:"text"`19}2021func ParseWordSearchPrintData(saveData []byte) (*WordSearchData, error) {22 if len(strings.TrimSpace(string(saveData))) == 0 {23 return nil, nil24 }2526 var save wordSearchSave27 if err := json.Unmarshal(saveData, &save); err != nil {28 return nil, fmt.Errorf("decode word search save: %w", err)29 }3031 rows := strings.Split(strings.ReplaceAll(strings.ReplaceAll(save.Grid, "\r\n", "\n"), "\r", "\n"), "\n")32 if len(rows) == 1 && rows[0] == "" {33 rows = nil34 }3536 width := save.Width37 for _, row := range rows {38 if n := len([]rune(row)); n > width {39 width = n40 }41 }4243 height := save.Height44 height = max(height, len(rows))45 if width <= 0 || height <= 0 {46 return nil, nil47 }4849 grid := make([][]string, height)50 for y := 0; y < height; y++ {51 grid[y] = make([]string, width)52 runes := []rune{}53 if y < len(rows) {54 runes = []rune(rows[y])55 }56 for x := 0; x < width; x++ {57 grid[y][x] = " "58 if x >= len(runes) {59 continue60 }61 r := runes[x]62 if unicode.IsSpace(r) {63 continue64 }65 grid[y][x] = string(unicode.ToUpper(r))66 }67 }6869 words := make([]string, 0, len(save.Words))70 for _, word := range save.Words {71 text := strings.ToUpper(strings.TrimSpace(word.Text))72 if text == "" {73 continue74 }75 words = append(words, text)76 }7778 return &WordSearchData{79 Width: width,80 Height: height,81 Grid: grid,82 Words: words,83 }, nil84}