Rearrange repo as monorepo

This commit is contained in:
Elnu 2023-07-20 13:08:35 -07:00
parent 2a59a96493
commit 848175efde
11 changed files with 216 additions and 172 deletions

34
shiritori/api/events.go Normal file
View file

@ -0,0 +1,34 @@
package api
import (
"fmt"
"net/http"
"git.elnu.com/ElnuDev/shiritori-go/httputils"
. "git.elnu.com/ElnuDev/shiritori-go/shiritori"
)
func GenerateApiEvents(clients *ClientSet) httputils.Handler {
return httputils.GenerateSseHandler(func(w http.ResponseWriter, r *http.Request) {
sendEvent := func(events ...httputils.SseEvent) {
for _, event := range events {
fmt.Fprint(w, event.Encode())
}
w.(http.Flusher).Flush()
}
sendEvent(clients.PlayerCountEvent(1))
ctx := r.Context()
channel := make(Client)
clients.Connect(channel)
outer:
for {
select {
case <-ctx.Done():
clients.Disconnect(channel)
break outer
case events := <-channel:
sendEvent(events...)
}
}
})
}

20
shiritori/api/submit.go Normal file
View file

@ -0,0 +1,20 @@
package api
import (
"net/http"
"git.elnu.com/ElnuDev/shiritori-go/httputils"
. "git.elnu.com/ElnuDev/shiritori-go/shiritori"
)
func GenerateApiSubmit(clients *ClientSet) httputils.Handler {
return httputils.GenerateHandler(
"",
func(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(0)
clients.BroadcastWord(r.FormValue("word"))
},
nil,
[]string{http.MethodPost},
)
}

76
shiritori/clientset.go Normal file
View file

@ -0,0 +1,76 @@
package shiritori
import (
"fmt"
"git.elnu.com/ElnuDev/shiritori-go/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("<div>%s</div>", 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)
}