Stage 7 (wip): wire remaining ops (backend REST, FBS, gateway transcode) + real UI transport
backend: REST handlers for pass/exchange/resign/hint/evaluate/check_word/complaint/history/chat-list/nudge + new game.ListForAccount (my games) + seat display_name resolution pkg/fbs: GameActionRequest/ExchangeRequest/EvalRequest/EvalResult/CheckWordRequest/WordCheckResult/ComplaintRequest/HintResult/History/GameList/ChatList + SeatView.display_name; committed Go regenerated (flatc 23.5.26) gateway: 11 new transcode ops + backendclient methods + FB encoders ui: edge TS codegen (flatc --ts + protoc-gen-es, committed), FlatBuffers<->model codec, real connect-web transport (binary, bearer auth, Subscribe). prod bundle ~69KB gzip JS
This commit is contained in:
@@ -26,6 +26,17 @@ const (
|
||||
MsgLobbyEnqueue = "lobby.enqueue"
|
||||
MsgLobbyPoll = "lobby.poll"
|
||||
MsgChatPost = "chat.post"
|
||||
MsgGamesList = "games.list"
|
||||
MsgGamePass = "game.pass"
|
||||
MsgGameExchange = "game.exchange"
|
||||
MsgGameResign = "game.resign"
|
||||
MsgGameHint = "game.hint"
|
||||
MsgGameEvaluate = "game.evaluate"
|
||||
MsgGameCheckWord = "game.check_word"
|
||||
MsgGameComplaint = "game.complaint"
|
||||
MsgGameHistory = "game.history"
|
||||
MsgChatList = "chat.list"
|
||||
MsgChatNudge = "chat.nudge"
|
||||
)
|
||||
|
||||
// Request is one decoded Execute call.
|
||||
@@ -69,6 +80,17 @@ func NewRegistry(backend *backendclient.Client, tg auth.TelegramValidator) *Regi
|
||||
r.ops[MsgLobbyEnqueue] = Op{Handler: enqueueHandler(backend), Auth: true}
|
||||
r.ops[MsgLobbyPoll] = Op{Handler: pollHandler(backend), Auth: true}
|
||||
r.ops[MsgChatPost] = Op{Handler: chatPostHandler(backend), Auth: true}
|
||||
r.ops[MsgGamesList] = Op{Handler: gamesListHandler(backend), Auth: true}
|
||||
r.ops[MsgGamePass] = Op{Handler: passHandler(backend), Auth: true}
|
||||
r.ops[MsgGameExchange] = Op{Handler: exchangeHandler(backend), Auth: true}
|
||||
r.ops[MsgGameResign] = Op{Handler: resignHandler(backend), Auth: true}
|
||||
r.ops[MsgGameHint] = Op{Handler: hintHandler(backend), Auth: true}
|
||||
r.ops[MsgGameEvaluate] = Op{Handler: evaluateHandler(backend), Auth: true}
|
||||
r.ops[MsgGameCheckWord] = Op{Handler: checkWordHandler(backend), Auth: true}
|
||||
r.ops[MsgGameComplaint] = Op{Handler: complaintHandler(backend), Auth: true}
|
||||
r.ops[MsgGameHistory] = Op{Handler: historyHandler(backend), Auth: true}
|
||||
r.ops[MsgChatList] = Op{Handler: chatListHandler(backend), Auth: true}
|
||||
r.ops[MsgChatNudge] = Op{Handler: nudgeHandler(backend), Auth: true}
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -219,3 +241,150 @@ func decodeTiles(in *fb.SubmitPlayRequest) []backendclient.TileJSON {
|
||||
}
|
||||
return tiles
|
||||
}
|
||||
|
||||
// decodeEvalTiles reads the tentative tiles from an EvalRequest.
|
||||
func decodeEvalTiles(in *fb.EvalRequest) []backendclient.TileJSON {
|
||||
n := in.TilesLength()
|
||||
tiles := make([]backendclient.TileJSON, 0, n)
|
||||
var t fb.TileRecord
|
||||
for i := 0; i < n; i++ {
|
||||
if in.Tiles(&t, i) {
|
||||
tiles = append(tiles, backendclient.TileJSON{
|
||||
Row: int(t.Row()),
|
||||
Col: int(t.Col()),
|
||||
Letter: string(t.Letter()),
|
||||
Blank: t.Blank(),
|
||||
})
|
||||
}
|
||||
}
|
||||
return tiles
|
||||
}
|
||||
|
||||
// decodeStringVector reads the exchange tiles from an ExchangeRequest.
|
||||
func decodeStringVector(in *fb.ExchangeRequest) []string {
|
||||
n := in.TilesLength()
|
||||
out := make([]string, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
out = append(out, string(in.Tiles(i)))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func gamesListHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
res, err := backend.GamesList(ctx, req.UserID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeGameList(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func passHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsGameActionRequest(req.Payload, 0)
|
||||
res, err := backend.Pass(ctx, req.UserID, string(in.GameId()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeMoveResult(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func resignHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsGameActionRequest(req.Payload, 0)
|
||||
res, err := backend.Resign(ctx, req.UserID, string(in.GameId()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeMoveResult(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func exchangeHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsExchangeRequest(req.Payload, 0)
|
||||
res, err := backend.Exchange(ctx, req.UserID, string(in.GameId()), decodeStringVector(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeMoveResult(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func hintHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsGameActionRequest(req.Payload, 0)
|
||||
res, err := backend.Hint(ctx, req.UserID, string(in.GameId()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeHintResult(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func evaluateHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsEvalRequest(req.Payload, 0)
|
||||
res, err := backend.Evaluate(ctx, req.UserID, string(in.GameId()), string(in.Dir()), decodeEvalTiles(in))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeEvalResult(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func checkWordHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsCheckWordRequest(req.Payload, 0)
|
||||
res, err := backend.CheckWord(ctx, req.UserID, string(in.GameId()), string(in.Word()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeWordCheck(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func complaintHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsComplaintRequest(req.Payload, 0)
|
||||
if err := backend.Complaint(ctx, req.UserID, string(in.GameId()), string(in.Word()), string(in.Note())); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeAck(true), nil
|
||||
}
|
||||
}
|
||||
|
||||
func historyHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsGameActionRequest(req.Payload, 0)
|
||||
res, err := backend.History(ctx, req.UserID, string(in.GameId()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeHistory(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func chatListHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsGameActionRequest(req.Payload, 0)
|
||||
res, err := backend.ChatList(ctx, req.UserID, string(in.GameId()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeChatList(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
func nudgeHandler(backend *backendclient.Client) Handler {
|
||||
return func(ctx context.Context, req Request) ([]byte, error) {
|
||||
in := fb.GetRootAsGameActionRequest(req.Payload, 0)
|
||||
res, err := backend.Nudge(ctx, req.UserID, string(in.GameId()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeChat(res), nil
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user