refacotr picking unused word out of AssignmentRotation body
parent
8d9815ee90
commit
c18f154328
|
|
@ -161,8 +161,9 @@ type (
|
|||
Killer string
|
||||
Victim string
|
||||
KillWord KillWord
|
||||
KillWords map[string]KillWords
|
||||
AllKillWords AllKillWords
|
||||
}
|
||||
AllKillWords map[string]KillWords
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -286,7 +287,7 @@ func (games Games) GameState(ctx context.Context, id string) (GameState, error)
|
|||
result.Players[k] = v
|
||||
}
|
||||
|
||||
for k, v := range assignmentRotation.KillWords {
|
||||
for k, v := range assignmentRotation.AllKillWords {
|
||||
player := result.Players[k]
|
||||
player.KillWords = v
|
||||
result.Players[k] = player
|
||||
|
|
@ -350,9 +351,6 @@ func (games Games) CreateEventPlayerLeave(ctx context.Context, id string, player
|
|||
return games.createEvent(ctx, id, EventPlayerLeave{Type: PlayerLeave, ID: player})
|
||||
}
|
||||
|
||||
//go:embed holiday.txt
|
||||
var wordsHoliday string
|
||||
|
||||
func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string, killer, victim, word string, points int) error {
|
||||
state, err := games.GameState(ctx, id)
|
||||
if err != nil {
|
||||
|
|
@ -368,7 +366,7 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
|
|||
Word: word,
|
||||
Points: points,
|
||||
},
|
||||
KillWords: map[string]KillWords{},
|
||||
AllKillWords: make(AllKillWords),
|
||||
}
|
||||
|
||||
toAssign := []string{}
|
||||
|
|
@ -379,7 +377,7 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
|
|||
toAssign = append(toAssign, k)
|
||||
doNotAssign[k] = v.Assignee
|
||||
|
||||
event.KillWords[k] = KillWords{
|
||||
event.AllKillWords[k] = KillWords{
|
||||
Global: v.Global,
|
||||
Assigned: now,
|
||||
Assignee: "",
|
||||
|
|
@ -390,13 +388,13 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
|
|||
if killerState, ok := state.Players[killer]; !ok {
|
||||
} else if victimState, ok := state.Players[victim]; !ok {
|
||||
} else {
|
||||
event.KillWords[killer] = KillWords{
|
||||
event.AllKillWords[killer] = KillWords{
|
||||
Global: killerState.KillWords.Global,
|
||||
Assigned: now,
|
||||
Assignee: victimState.KillWords.Assignee,
|
||||
Assignment: killerState.KillWords.Assignment,
|
||||
}
|
||||
toAssign = slices.DeleteFunc(toAssign, func(s string) bool { return s == event.KillWords[killer].Assignee })
|
||||
toAssign = slices.DeleteFunc(toAssign, func(s string) bool { return s == event.AllKillWords[killer].Assignee })
|
||||
|
||||
if killerState.KillWords.Global.Word != word {
|
||||
victimState.KillWords.Assignment = Assignment{}
|
||||
|
|
@ -407,17 +405,17 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
|
|||
for !func() bool {
|
||||
toAssign := slices.Clone(toAssign)
|
||||
doNotAssign := maps.Clone(doNotAssign)
|
||||
eventKillWords := maps.Clone(event.KillWords)
|
||||
allKillWords := maps.Clone(event.AllKillWords)
|
||||
|
||||
for i := range toAssign {
|
||||
j := rand.Intn(i + 1)
|
||||
toAssign[i], toAssign[j] = toAssign[j], toAssign[i]
|
||||
}
|
||||
for k, v := range eventKillWords {
|
||||
for k, v := range allKillWords {
|
||||
if k == toAssign[0] || doNotAssign[k] == toAssign[0] {
|
||||
return false
|
||||
}
|
||||
eventKillWords[k] = KillWords{
|
||||
allKillWords[k] = KillWords{
|
||||
Global: v.Global,
|
||||
Assigned: now,
|
||||
Assignee: toAssign[0],
|
||||
|
|
@ -426,66 +424,95 @@ func (games Games) CreateEventAssignmentRotation(ctx context.Context, id string,
|
|||
toAssign = toAssign[1:]
|
||||
}
|
||||
|
||||
event.KillWords = eventKillWords
|
||||
event.AllKillWords = allKillWords
|
||||
return true
|
||||
}() {
|
||||
}
|
||||
|
||||
globalsInUse := map[string]any{}
|
||||
publicsInUse := map[string]any{}
|
||||
privatesInUse := map[string]any{}
|
||||
for _, v := range event.KillWords {
|
||||
globalsInUse[v.Global.Word] = nil
|
||||
for _, public := range v.Assignment.Public {
|
||||
publicsInUse[public.Word] = nil
|
||||
}
|
||||
for _, private := range v.Assignment.Private {
|
||||
privatesInUse[private.Word] = nil
|
||||
}
|
||||
}
|
||||
|
||||
randWord := func(words string, taken map[string]any) string {
|
||||
wordsList := strings.Fields(words)
|
||||
for {
|
||||
got := wordsList[rand.Intn(len(wordsList))]
|
||||
if _, ok := taken[got]; !ok {
|
||||
taken[got] = nil
|
||||
return got
|
||||
}
|
||||
}
|
||||
}
|
||||
randGlobal := func() string {
|
||||
return randWord(wordsHoliday, globalsInUse)
|
||||
}
|
||||
randPublic := func() string {
|
||||
return randWord(wordsHoliday, publicsInUse)
|
||||
}
|
||||
randPrivate := func() string {
|
||||
return randWord(wordsHoliday, privatesInUse)
|
||||
}
|
||||
|
||||
// TODO generate .Global=...us major cities?, .Assignments.Public=...?, .Assignments.Private=holiday
|
||||
for k, v := range event.KillWords {
|
||||
for k, v := range event.AllKillWords {
|
||||
if v.Global.Word == "" {
|
||||
v.Global = KillWord{Word: randGlobal(), Points: -1}
|
||||
v.Global = KillWord{Word: event.AllKillWords.unusedGlobal(), Points: -1}
|
||||
event.AllKillWords[k] = v
|
||||
}
|
||||
if len(v.Assignment.Public) == 0 {
|
||||
v.Assignment.Public = []KillWord{
|
||||
KillWord{Word: randPublic(), Points: 50},
|
||||
KillWord{Word: randPublic(), Points: 50},
|
||||
v.Assignment.Public = []KillWord{}
|
||||
for i := 0; i < 2; i++ {
|
||||
v.Assignment.Public = append(v.Assignment.Public, KillWord{Word: event.AllKillWords.unusedPublic(), Points: 50})
|
||||
event.AllKillWords[k] = v
|
||||
}
|
||||
}
|
||||
if len(v.Assignment.Private) == 0 {
|
||||
v.Assignment.Private = []KillWord{
|
||||
KillWord{Word: randPrivate(), Points: 100},
|
||||
v.Assignment.Private = []KillWord{}
|
||||
for i := 0; i < 2; i++ {
|
||||
v.Assignment.Private = append(v.Assignment.Private, KillWord{Word: event.AllKillWords.unusedPrivate(), Points: 100})
|
||||
event.AllKillWords[k] = v
|
||||
}
|
||||
}
|
||||
event.KillWords[k] = v
|
||||
}
|
||||
|
||||
return games.createEvent(ctx, id, event)
|
||||
}
|
||||
|
||||
//go:embed holiday.txt
|
||||
var wordsHoliday string
|
||||
|
||||
func (m AllKillWords) unusedGlobal() string {
|
||||
pool := strings.Fields(wordsHoliday)
|
||||
inUse := func() []string {
|
||||
result := []string{}
|
||||
for _, killWords := range m {
|
||||
result = append(result, killWords.Global.Word)
|
||||
}
|
||||
return result
|
||||
}
|
||||
for {
|
||||
picked := pool[rand.Intn(len(pool))]
|
||||
if !slices.Contains(inUse(), picked) {
|
||||
return picked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO hard difficulty
|
||||
func (m AllKillWords) unusedPrivate() string {
|
||||
pool := strings.Fields(wordsHoliday)
|
||||
inUse := func() []string {
|
||||
result := []string{}
|
||||
for _, killWords := range m {
|
||||
for _, killWord := range killWords.Assignment.Private {
|
||||
result = append(result, killWord.Word)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
for {
|
||||
picked := pool[rand.Intn(len(pool))]
|
||||
if !slices.Contains(inUse(), picked) {
|
||||
return picked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO medium difficulty
|
||||
func (m AllKillWords) unusedPublic() string {
|
||||
pool := strings.Fields(wordsHoliday)
|
||||
inUse := func() []string {
|
||||
result := []string{}
|
||||
for _, killWords := range m {
|
||||
for _, killWord := range killWords.Assignment.Public {
|
||||
result = append(result, killWord.Word)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
for {
|
||||
picked := pool[rand.Intn(len(pool))]
|
||||
if !slices.Contains(inUse(), picked) {
|
||||
return picked
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (games Games) CreateEventGameComplete(ctx context.Context, id string) error {
|
||||
if err := games.db.Exec(ctx, `
|
||||
UPDATE games
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ func TestParseEvent(t *testing.T) {
|
|||
Word: "word",
|
||||
Points: 1,
|
||||
},
|
||||
KillWords: map[string]KillWords{
|
||||
AllKillWords: map[string]KillWords{
|
||||
"x": KillWords{
|
||||
Global: KillWord{
|
||||
Word: "a",
|
||||
|
|
|
|||
Loading…
Reference in New Issue