Files
15-puzzle/internal/puzzle/form.go
T
Ilia Denisov 31957206b8 initial
2025-09-03 18:43:28 +03:00

114 lines
2.6 KiB
Go

package puzzle
import (
"15-puzzle/internal/model"
"fmt"
"image"
"image/color"
"strconv"
"sync/atomic"
"time"
)
const (
dials = 10
codeInputTemplate = `[%s] [%s] [%s] [%s]`
)
type form struct {
dials [dials]*button
request func(string)
requestSent bool
authFail bool
idx int
input [4]byte
mon atomic.Value
}
func intFn(i int) func() int { return func() int { return i } }
func stringFn(s string) func() string { return func() string { return s } }
func codeBox(b byte) string {
if b > 0 {
return "*"
}
return "_"
}
func newForm(request func(string)) *form {
col := func(i int) int { return (i%3)*puzzleTileSymW + 5 }
row := func(i int) int { return (i/3)*puzzleTileSymH + 3 }
f := &form{request: request}
for i := 1; i < dials; i++ {
f.dials[i] = NewButton(stringFn(strconv.Itoa(i)), intFn(col(i-1)), intFn(row(i-1)))
}
f.dials[0] = NewButton(stringFn("0"), intFn(col(10)), intFn(row(10)))
return f
}
func (f *form) ApiMonitoringHandler(m model.Monitoring) {
f.mon.Store(m)
f.authFail = false
}
func (f *form) Tick(t ticker) {
if t == ticker1Hz && f.requestSent {
f.authFail = f.mon.Load() == nil
}
}
func (f *form) Draw(s Screen) {
drawGameField(s)
if v := f.mon.Load(); v != nil {
m := v.(model.Monitoring)
printHeader(s, "Usage Statistics", 0)
s.Print(fmt.Sprintf("Players: %d\nGames: %d\nSolved: %d", m.Users, m.GamesStarted, m.GamesSolved),
image.Point{3, 4},
color.RGBA{0, 0xFF, 0xFF, 0xFF})
} else {
r := image.Rect(8, 1, len(codeInputTemplate)+4, 2)
if f.authFail {
s.Fill(r, color.RGBA{0xFF, 0, 0, 0xFF})
} else if f.idx == len(f.input) {
s.Fill(r, color.RGBA{0x80, 0x80, 0x80, 0xFF})
}
printHeader(s, fmt.Sprintf(codeInputTemplate, codeBox(f.input[0]), codeBox(f.input[1]), codeBox(f.input[2]), codeBox(f.input[3])), 0)
for i := range f.dials {
f.dials[i].Draw(s)
}
}
}
func (f *form) Interact(a Audio, col, row int, t time.Duration) actionResult {
if (image.Point{col, row}).In(image.Rect(2, 1, puzzleSymX-2, 2)) {
f.input = [4]byte{}
f.authFail = false
f.requestSent = false
f.idx = 0
return resultSwitchGame
}
if f.mon.Load() == nil {
for i := range f.dials {
if f.dials[i].Interact(col, row) {
f.pressNextButton('0' + byte(i))
break
}
}
}
return resultNone
}
func (f *form) pressNextButton(digit byte) {
if f.idx >= len(f.input) {
return
}
f.input[f.idx] = digit
f.idx++
if f.idx == len(f.input) {
f.request(string(f.input[:]))
f.requestSent = true
}
}
func (f *form) Activate() {}
func (f *form) SetLang(langCode) {}