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:
@@ -54,11 +54,12 @@ type MoveRecordResp struct {
|
||||
|
||||
// SeatResp is one seat's public standing.
|
||||
type SeatResp struct {
|
||||
Seat int `json:"seat"`
|
||||
AccountID string `json:"account_id"`
|
||||
Score int `json:"score"`
|
||||
HintsUsed int `json:"hints_used"`
|
||||
IsWinner bool `json:"is_winner"`
|
||||
Seat int `json:"seat"`
|
||||
AccountID string `json:"account_id"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Score int `json:"score"`
|
||||
HintsUsed int `json:"hints_used"`
|
||||
IsWinner bool `json:"is_winner"`
|
||||
}
|
||||
|
||||
// GameResp is the shared game summary.
|
||||
@@ -189,3 +190,120 @@ func (c *Client) ChatPost(ctx context.Context, userID, gameID, body, clientIP st
|
||||
map[string]string{"body": body}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// HintResultResp is the top-ranked move plus the remaining hint budget.
|
||||
type HintResultResp struct {
|
||||
Move MoveRecordResp `json:"move"`
|
||||
HintsRemaining int `json:"hints_remaining"`
|
||||
}
|
||||
|
||||
// EvalResultResp is an unlimited move preview.
|
||||
type EvalResultResp struct {
|
||||
Legal bool `json:"legal"`
|
||||
Score int `json:"score"`
|
||||
Words []string `json:"words"`
|
||||
}
|
||||
|
||||
// WordCheckResp is a dictionary lookup outcome.
|
||||
type WordCheckResp struct {
|
||||
Word string `json:"word"`
|
||||
Legal bool `json:"legal"`
|
||||
}
|
||||
|
||||
// HistoryResp is a game's decoded move journal.
|
||||
type HistoryResp struct {
|
||||
GameID string `json:"game_id"`
|
||||
Moves []MoveRecordResp `json:"moves"`
|
||||
}
|
||||
|
||||
// GameListResp is the caller's games for the lobby.
|
||||
type GameListResp struct {
|
||||
Games []GameResp `json:"games"`
|
||||
}
|
||||
|
||||
// ChatListResp is a game's chat history.
|
||||
type ChatListResp struct {
|
||||
Messages []ChatResp `json:"messages"`
|
||||
}
|
||||
|
||||
func (c *Client) gamePath(gameID, suffix string) string {
|
||||
return "/api/v1/user/games/" + url.PathEscape(gameID) + suffix
|
||||
}
|
||||
|
||||
// Pass forfeits the player's turn.
|
||||
func (c *Client) Pass(ctx context.Context, userID, gameID string) (MoveResultResp, error) {
|
||||
var out MoveResultResp
|
||||
err := c.do(ctx, http.MethodPost, c.gamePath(gameID, "/pass"), userID, "", struct{}{}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Exchange swaps the chosen rack tiles back into the bag.
|
||||
func (c *Client) Exchange(ctx context.Context, userID, gameID string, tiles []string) (MoveResultResp, error) {
|
||||
var out MoveResultResp
|
||||
err := c.do(ctx, http.MethodPost, c.gamePath(gameID, "/exchange"), userID, "",
|
||||
map[string]any{"tiles": tiles}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Resign resigns the player from the game.
|
||||
func (c *Client) Resign(ctx context.Context, userID, gameID string) (MoveResultResp, error) {
|
||||
var out MoveResultResp
|
||||
err := c.do(ctx, http.MethodPost, c.gamePath(gameID, "/resign"), userID, "", struct{}{}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Hint reveals the top-ranked move and spends a hint.
|
||||
func (c *Client) Hint(ctx context.Context, userID, gameID string) (HintResultResp, error) {
|
||||
var out HintResultResp
|
||||
err := c.do(ctx, http.MethodPost, c.gamePath(gameID, "/hint"), userID, "", struct{}{}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Evaluate previews a tentative play's legality and score.
|
||||
func (c *Client) Evaluate(ctx context.Context, userID, gameID, dir string, tiles []TileJSON) (EvalResultResp, error) {
|
||||
var out EvalResultResp
|
||||
err := c.do(ctx, http.MethodPost, c.gamePath(gameID, "/evaluate"), userID, "",
|
||||
map[string]any{"dir": dir, "tiles": tiles}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// CheckWord looks a word up in the game's pinned dictionary.
|
||||
func (c *Client) CheckWord(ctx context.Context, userID, gameID, word string) (WordCheckResp, error) {
|
||||
var out WordCheckResp
|
||||
err := c.do(ctx, http.MethodGet, c.gamePath(gameID, "/check_word")+"?word="+url.QueryEscape(word), userID, "", nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Complaint disputes a word-check result.
|
||||
func (c *Client) Complaint(ctx context.Context, userID, gameID, word, note string) error {
|
||||
return c.do(ctx, http.MethodPost, c.gamePath(gameID, "/complaint"), userID, "",
|
||||
map[string]string{"word": word, "note": note}, nil)
|
||||
}
|
||||
|
||||
// History returns a game's decoded move journal.
|
||||
func (c *Client) History(ctx context.Context, userID, gameID string) (HistoryResp, error) {
|
||||
var out HistoryResp
|
||||
err := c.do(ctx, http.MethodGet, c.gamePath(gameID, "/history"), userID, "", nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// ChatList returns a game's chat history.
|
||||
func (c *Client) ChatList(ctx context.Context, userID, gameID string) (ChatListResp, error) {
|
||||
var out ChatListResp
|
||||
err := c.do(ctx, http.MethodGet, c.gamePath(gameID, "/chat"), userID, "", nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// Nudge posts a nudge to the player whose turn is awaited.
|
||||
func (c *Client) Nudge(ctx context.Context, userID, gameID string) (ChatResp, error) {
|
||||
var out ChatResp
|
||||
err := c.do(ctx, http.MethodPost, c.gamePath(gameID, "/nudge"), userID, "", struct{}{}, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
// GamesList returns the caller's active and finished games.
|
||||
func (c *Client) GamesList(ctx context.Context, userID string) (GameListResp, error) {
|
||||
var out GameListResp
|
||||
err := c.do(ctx, http.MethodGet, "/api/v1/user/games", userID, "", nil, &out)
|
||||
return out, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user