package tins2021 import ( "crypto/sha256" "encoding/base64" "fmt" ) const scoreFileName = "score.json" type Highscores []Score func (h Highscores) AddScore(score, difficulty int) (Highscores, bool) { highscores := len(h) var rank = highscores for ; rank > 0; rank-- { if score <= h[rank-1].Score { break } } highscore := NewScore(score, difficulty) if rank == highscores && highscores < 10 { return append(h, highscore), true } if rank < 10 { h = append(h[:rank], append([]Score{highscore}, h[rank:highscores]...)...) if len(h) > 10 { h = h[:10] } return h, true } return h, false } type Score struct { Score int Difficulty int Hash string } func NewScore(score, difficulty int) Score { s := Score{Score: score, Difficulty: difficulty} s.Hash = s.hash() return s } func (s *Score) hash() string { hashText := fmt.Sprintf("tins2021_qbitter, %d, %d", s.Score, s.Difficulty) hash := sha256.Sum256([]byte(hashText)) return base64.StdEncoding.EncodeToString(hash[:]) } func (s *Score) Validate() bool { hash := s.hash() if hash == s.Hash { return true } s.Score = 0 s.Difficulty = 0 return false } type ScoreState struct { Current Score CurrentLives int Highscores Highscores } func LoadScores() (ScoreState, error) { var state ScoreState if err := LoadUserFileJSON(scoreFileName, &state); err != nil { return ScoreState{}, err } state.Current.Validate() for i := 0; i < len(state.Highscores); { if !state.Highscores[i].Validate() { state.Highscores = append(state.Highscores[:i], state.Highscores[i+1:]...) } else { i++ } } return state, nil } func SaveScores(s *ScoreState) error { return SaveUserFileJSON(scoreFileName, s) }