package shiritori import ( "fmt" "git.elnu.com/ElnuDev/jichanorg/httputils" ) type Client = chan []httputils.SseEvent const EventWord = "word" const EventPlayerCount = "players" const EventNavigate = "navigate" type ClientSet struct { clients map[Client]bool } func NewClientSet() ClientSet { return ClientSet{make(map[Client]bool)} } func (clients ClientSet) Broadcast(events ...httputils.SseEvent) { for client := range clients.clients { client <- events } } func (clients ClientSet) PlayerCount() int { return len(clients.clients) } func (clients ClientSet) PlayerCountEvent(offset int) httputils.SseEvent { playerCount := clients.PlayerCount() + offset var data string if playerCount == 0 { data = "No players online." } else { data = fmt.Sprintf("%d player%s online.", playerCount, map[bool]string{true: "", false: "s"}[playerCount == 1]) } return httputils.SseEvent{EventName: EventPlayerCount, Data: data} } func (clients ClientSet) BroadcastPlayerCount(offset int) { clients.Broadcast(clients.PlayerCountEvent(offset)) } func (clients ClientSet) BroadcastWord(word string) { clients.Broadcast( httputils.SseEvent{ EventName: EventWord, Data: fmt.Sprintf("
%s
", word), }, httputils.SseEvent{ EventName: EventNavigate, Data: fmt.Sprintf("https://jisho.org/search/%s", word), }, ) } func (clients ClientSet) Connect(client Client) { // Channels are blocking. // Client initialization is waiting for connect() to complete. // If we try to braodcast to it before connect() is done, // the channel handling logic wouldn't have started yet, // and broadcast() would be freeze. // Therefore, we must broadcast an offset player count first, // then actually add the client. clients.BroadcastPlayerCount(1) clients.clients[client] = true } func (clients ClientSet) Disconnect(client Client) { delete(clients.clients, client) clients.BroadcastPlayerCount(0) }