Feat: works on my machine

This commit is contained in:
2025-10-16 05:07:56 +08:00
commit 5bbab63a2c
37 changed files with 4553 additions and 0 deletions

7
types/auth.go Normal file
View File

@@ -0,0 +1,7 @@
package types
type UserType struct{}
var (
UserKey = UserType{}
)

5
types/types.go Normal file
View File

@@ -0,0 +1,5 @@
package types
type ShutdownFunc func()
type UsernameType = string

10
types/udp.go Normal file
View File

@@ -0,0 +1,10 @@
package types
type JoinRequest struct {
Endpoint string
Username UsernameType
}
type JoinResponse struct {
Endpoint string
}

209
types/wordle.go Normal file
View File

@@ -0,0 +1,209 @@
package types
import (
"fmt"
"sort"
"strings"
"github.com/charmbracelet/lipgloss"
)
const (
GUESS_COUNT_LIMIT int = 6
GUESS_WORD_LENGTH int = 5
ALPHABET_COUNT int = 26
)
type GuessStateType int
const (
GuessStateNotGuessed GuessStateType = iota
GuessStateWrongChar
GuessStateWrongPos
GuessStateCorrect
)
type GuessChar struct {
Char rune
State GuessStateType
}
func (self GuessChar) View() string {
style := lipgloss.NewStyle().
Foreground(lipgloss.Color("#FFFFFF"))
switch self.State {
case GuessStateWrongChar:
style = style.Background(lipgloss.Color("#3a3a3c"))
case GuessStateWrongPos:
style = style.Background(lipgloss.Color("#b59f3b"))
case GuessStateCorrect:
style = style.Background(lipgloss.Color("#538d4e"))
}
return style.Render(string(self.Char))
}
type Guess struct {
Data [GUESS_WORD_LENGTH]GuessChar
}
type guessLeftType struct {
Rune rune
Idx int
}
func NewGuess(guess, ans string) Guess {
var ret Guess
var ansLeft []rune
var guessLeft []guessLeftType
for i := range ret.Data {
ret.Data[i] = GuessChar{
Char: rune(guess[i]),
State: GuessStateWrongChar,
}
if guess[i] == ans[i] {
ret.Data[i].State = GuessStateCorrect
} else {
ansLeft = append(ansLeft, rune(ans[i]))
guessLeft = append(guessLeft, guessLeftType{
Rune: rune(guess[i]),
Idx: i,
})
}
}
sort.Slice(ansLeft, func(i, j int) bool {
return int32(ansLeft[i]) < int32(ansLeft[j])
})
sort.Slice(guessLeft, func(i, j int) bool {
return int32(guessLeft[i].Rune) < int32(guessLeft[j].Rune)
})
i, j := 0, 0
for i < len(ansLeft) && j < len(guessLeft) {
if int32(ansLeft[i]) == int32(guessLeft[j].Rune) {
ret.Data[guessLeft[j].Idx].State = GuessStateWrongPos
i++
j++
} else {
if int32(ansLeft[i]) < int32(guessLeft[j].Rune) {
i++
} else {
j++
}
}
}
return ret
}
func (self Guess) View() string {
var b strings.Builder
for _, ch := range self.Data {
b.WriteString(ch.View())
}
return b.String()
}
type WordleState struct {
History map[UsernameType][GUESS_COUNT_LIMIT]Guess
CurrentGuess map[UsernameType]string
Round int
GameEnd bool
}
func NewWordleState() WordleState {
return WordleState{
History: make(map[UsernameType][GUESS_COUNT_LIMIT]Guess),
CurrentGuess: make(map[UsernameType]string),
Round: 0,
GameEnd: false,
}
}
func (self *WordleState) View() string {
var b strings.Builder
col := []string{}
for user := range self.History {
col = append(col, user)
}
sort.Slice(col, func(i, j int) bool {
return col[i] < col[j]
})
fmt.Fprintf(&b, " ")
for _, user := range col {
fmt.Fprintf(&b, "%5s ", user)
}
b.WriteRune('\n')
table := make([][]string, GUESS_COUNT_LIMIT)
for i := range table {
table[i] = make([]string, len(col))
}
for j, user := range col {
for i, guess := range self.History[user] {
table[i][j] = guess.View()
}
}
for i, row := range table {
fmt.Fprintf(&b, "%1d ", i+1)
for _, e := range row {
b.WriteString(e + " ")
}
b.WriteRune('\n')
}
return b.String()
}
type WordBank struct {
Data [ALPHABET_COUNT]GuessStateType
}
func NewWordBank(state WordleState) WordBank {
// FIXME: breaks when enter ^A-Z
var ret WordBank
for _, guesses := range state.History {
for i := 0; i < state.Round; i++ {
for _, ch := range guesses[i].Data {
ret.Data[int32(ch.Char)-'A'] = max(
ret.Data[int32(ch.Char)-'A'],
ch.State)
}
}
}
return ret
}
func (self WordBank) View() string {
var b strings.Builder
for i, state := range self.Data {
style := lipgloss.NewStyle().
Foreground(lipgloss.Color("#FFFFFF"))
switch state {
case GuessStateNotGuessed:
style = style.Background(lipgloss.Color("#2c3032"))
case GuessStateWrongChar:
style = style.Background(lipgloss.Color("#3a3a3c"))
case GuessStateWrongPos:
style = style.Background(lipgloss.Color("#b59f3b"))
case GuessStateCorrect:
style = style.Background(lipgloss.Color("#538d4e"))
}
b.WriteString(style.Render(string('A' + i)))
if i%10 == 9 {
b.WriteRune('\n')
}
}
return b.String()
}