clone

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

feat/elo-difficulty
puzzletea / games / wordsearch / elo_test.go
elo_test.go 3.0K
1package wordsearch23import (4 "fmt"5 "reflect"6 "testing"78 "github.com/FelineStateMachine/puzzletea/difficulty"9)1011func TestSpawnEloRejectsInvalidElo(t *testing.T) {12 mode := NewMode("Elo", "test", 10, 10, 6, 3, 5, []Direction{Right, Down, DownRight})1314 tests := []difficulty.Elo{15 difficulty.MinElo - 1,16 difficulty.SoftCapElo + 1,17 }18 for _, elo := range tests {19 t.Run(fmt.Sprint(elo), func(t *testing.T) {20 gamer, report, err := mode.SpawnElo("seed", elo)21 if err == nil {22 t.Fatalf("SpawnElo(%d) error = nil, want invalid Elo error", elo)23 }24 if gamer != nil {25 t.Fatalf("SpawnElo(%d) gamer = %#v, want nil", elo, gamer)26 }27 if !reflect.DeepEqual(report, difficulty.Report{}) {28 t.Fatalf("SpawnElo(%d) report = %#v, want zero report", elo, report)29 }30 })31 }32}3334func TestSpawnEloDeterministicForSameSeedAndElo(t *testing.T) {35 mode := NewMode("Elo", "test", 10, 10, 6, 3, 5, []Direction{Right, Down, DownRight})36 const seed = "wordsearch-deterministic"37 const elo = difficulty.Elo(1735)3839 gamerA, reportA, err := mode.SpawnElo(seed, elo)40 if err != nil {41 t.Fatalf("first SpawnElo returned error: %v", err)42 }43 gamerB, reportB, err := mode.SpawnElo(seed, elo)44 if err != nil {45 t.Fatalf("second SpawnElo returned error: %v", err)46 }4748 modelA := gamerA.(*Model)49 modelB := gamerB.(*Model)5051 if got, want := modelA.grid.String(), modelB.grid.String(); got != want {52 t.Fatalf("grid mismatch for same seed/Elo:\n%s\n\n%s", got, want)53 }54 if !reflect.DeepEqual(modelA.words, modelB.words) {55 t.Fatalf("words mismatch for same seed/Elo:\n%#v\n\n%#v", modelA.words, modelB.words)56 }57 if !reflect.DeepEqual(reportA, reportB) {58 t.Fatalf("report mismatch for same seed/Elo:\n%#v\n\n%#v", reportA, reportB)59 }60}6162func TestSpawnEloPopulatesDifficultyReport(t *testing.T) {63 mode := NewMode("Elo", "test", 10, 10, 6, 3, 5, []Direction{Right, Down, DownRight})64 const target = difficulty.Elo(2200)6566 gamer, report, err := mode.SpawnElo("report-fields", target)67 if err != nil {68 t.Fatalf("SpawnElo returned error: %v", err)69 }70 if gamer == nil {71 t.Fatal("SpawnElo returned nil gamer")72 }73 if report.TargetElo != target {74 t.Fatalf("TargetElo = %d, want %d", report.TargetElo, target)75 }76 if err := difficulty.ValidateElo(report.ActualElo); err != nil {77 t.Fatalf("ActualElo = %d is invalid: %v", report.ActualElo, err)78 }79 if report.Confidence == "" {80 t.Fatal("Confidence is empty")81 }8283 requiredMetrics := map[string]float64{84 "width": 1,85 "height": 1,86 "cells": 1,87 "target_words": 1,88 "placed_words": 1,89 "success_rate": 0,90 "avg_word_length": 1,91 "max_word_length": 1,92 "unique_directions": 1,93 "occupied_cells": 1,94 "density": 0,95 "attempts_per_word": 1,96 "fallback_rate": 0,97 }98 for key, min := range requiredMetrics {99 got, ok := report.Metrics[key]100 if !ok {101 t.Fatalf("Metrics[%q] missing from %#v", key, report.Metrics)102 }103 if got < min {104 t.Fatalf("Metrics[%q] = %v, want >= %v", key, got, min)105 }106 }107}