R6: refactor + docs reconciliation + de-staging #37
@@ -4,194 +4,114 @@ import (
|
|||||||
flatbuffers "github.com/google/flatbuffers/go"
|
flatbuffers "github.com/google/flatbuffers/go"
|
||||||
|
|
||||||
"scrabble/backend/internal/engine"
|
"scrabble/backend/internal/engine"
|
||||||
fb "scrabble/pkg/fbs/scrabblefb"
|
"scrabble/pkg/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The builders below encode the nested wire tables embedded in enriched event
|
// The builders below encode the nested wire tables embedded in enriched event
|
||||||
// payloads. They mirror the gateway's transcode encoders, but read the domain's
|
// payloads. They map the domain's already-resolved values (notify.* payload structs
|
||||||
// already-resolved values (notify.* input structs and the decoded engine.MoveRecord)
|
// and the decoded engine.MoveRecord) to the neutral scrabble/pkg/wire structs and
|
||||||
// rather than the gateway's REST DTOs. Each returns the offset of the table it built;
|
// delegate the FlatBuffers construction to package wire — the single definition of the
|
||||||
// callers must build every nested table before opening the parent event table.
|
// nested-table layout shared with the gateway transcoder. Each returns the offset of
|
||||||
|
// the table it built; callers must build every nested table before opening the parent.
|
||||||
|
|
||||||
|
// toWireGame maps a GameSummary to the shared wire.GameView.
|
||||||
|
func toWireGame(g GameSummary) wire.GameView {
|
||||||
|
seats := make([]wire.SeatView, len(g.Seats))
|
||||||
|
for i, s := range g.Seats {
|
||||||
|
seats[i] = wire.SeatView{
|
||||||
|
Seat: s.Seat,
|
||||||
|
AccountID: s.AccountID,
|
||||||
|
Score: s.Score,
|
||||||
|
HintsUsed: s.HintsUsed,
|
||||||
|
IsWinner: s.IsWinner,
|
||||||
|
DisplayName: s.DisplayName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wire.GameView{
|
||||||
|
ID: g.ID,
|
||||||
|
Variant: g.Variant,
|
||||||
|
DictVersion: g.DictVersion,
|
||||||
|
Status: g.Status,
|
||||||
|
Players: g.Players,
|
||||||
|
ToMove: g.ToMove,
|
||||||
|
TurnTimeoutSecs: g.TurnTimeoutSecs,
|
||||||
|
MoveCount: g.MoveCount,
|
||||||
|
EndReason: g.EndReason,
|
||||||
|
Seats: seats,
|
||||||
|
LastActivityUnix: g.LastActivityUnix,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// buildGameView builds a GameView table from a GameSummary and returns its offset.
|
// buildGameView builds a GameView table from a GameSummary and returns its offset.
|
||||||
func buildGameView(b *flatbuffers.Builder, g GameSummary) flatbuffers.UOffsetT {
|
func buildGameView(b *flatbuffers.Builder, g GameSummary) flatbuffers.UOffsetT {
|
||||||
seatOffs := make([]flatbuffers.UOffsetT, len(g.Seats))
|
return wire.BuildGameView(b, toWireGame(g))
|
||||||
for i, s := range g.Seats {
|
|
||||||
aid := b.CreateString(s.AccountID)
|
|
||||||
dname := b.CreateString(s.DisplayName)
|
|
||||||
fb.SeatViewStart(b)
|
|
||||||
fb.SeatViewAddSeat(b, int32(s.Seat))
|
|
||||||
fb.SeatViewAddAccountId(b, aid)
|
|
||||||
fb.SeatViewAddScore(b, int32(s.Score))
|
|
||||||
fb.SeatViewAddHintsUsed(b, int32(s.HintsUsed))
|
|
||||||
fb.SeatViewAddIsWinner(b, s.IsWinner)
|
|
||||||
fb.SeatViewAddDisplayName(b, dname)
|
|
||||||
seatOffs[i] = fb.SeatViewEnd(b)
|
|
||||||
}
|
|
||||||
fb.GameViewStartSeatsVector(b, len(seatOffs))
|
|
||||||
for i := len(seatOffs) - 1; i >= 0; i-- {
|
|
||||||
b.PrependUOffsetT(seatOffs[i])
|
|
||||||
}
|
|
||||||
seats := b.EndVector(len(seatOffs))
|
|
||||||
|
|
||||||
id := b.CreateString(g.ID)
|
|
||||||
variant := b.CreateString(g.Variant)
|
|
||||||
dictVer := b.CreateString(g.DictVersion)
|
|
||||||
status := b.CreateString(g.Status)
|
|
||||||
endReason := b.CreateString(g.EndReason)
|
|
||||||
|
|
||||||
fb.GameViewStart(b)
|
|
||||||
fb.GameViewAddId(b, id)
|
|
||||||
fb.GameViewAddVariant(b, variant)
|
|
||||||
fb.GameViewAddDictVersion(b, dictVer)
|
|
||||||
fb.GameViewAddStatus(b, status)
|
|
||||||
fb.GameViewAddPlayers(b, int32(g.Players))
|
|
||||||
fb.GameViewAddToMove(b, int32(g.ToMove))
|
|
||||||
fb.GameViewAddTurnTimeoutSecs(b, int32(g.TurnTimeoutSecs))
|
|
||||||
fb.GameViewAddMoveCount(b, int32(g.MoveCount))
|
|
||||||
fb.GameViewAddEndReason(b, endReason)
|
|
||||||
fb.GameViewAddSeats(b, seats)
|
|
||||||
fb.GameViewAddLastActivityUnix(b, g.LastActivityUnix)
|
|
||||||
return fb.GameViewEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildMoveRecord builds a MoveRecord table from a decoded engine move and returns
|
// buildMoveRecord builds a MoveRecord table from a decoded engine move and returns its
|
||||||
// its offset. The values match the move-result DTO (Count is the engine count: the
|
// offset (Count is the engine count: the number of tiles swapped on an exchange, zero
|
||||||
// number of tiles swapped on an exchange, zero otherwise).
|
// otherwise).
|
||||||
func buildMoveRecord(b *flatbuffers.Builder, m engine.MoveRecord) flatbuffers.UOffsetT {
|
func buildMoveRecord(b *flatbuffers.Builder, m engine.MoveRecord) flatbuffers.UOffsetT {
|
||||||
tileOffs := make([]flatbuffers.UOffsetT, len(m.Tiles))
|
tiles := make([]wire.TileRecord, len(m.Tiles))
|
||||||
for i, t := range m.Tiles {
|
for i, t := range m.Tiles {
|
||||||
letter := b.CreateString(t.Letter)
|
tiles[i] = wire.TileRecord{Row: t.Row, Col: t.Col, Letter: t.Letter, Blank: t.Blank}
|
||||||
fb.TileRecordStart(b)
|
|
||||||
fb.TileRecordAddRow(b, int32(t.Row))
|
|
||||||
fb.TileRecordAddCol(b, int32(t.Col))
|
|
||||||
fb.TileRecordAddLetter(b, letter)
|
|
||||||
fb.TileRecordAddBlank(b, t.Blank)
|
|
||||||
tileOffs[i] = fb.TileRecordEnd(b)
|
|
||||||
}
|
}
|
||||||
fb.MoveRecordStartTilesVector(b, len(tileOffs))
|
return wire.BuildMoveRecord(b, wire.MoveRecord{
|
||||||
for i := len(tileOffs) - 1; i >= 0; i-- {
|
Player: m.Player,
|
||||||
b.PrependUOffsetT(tileOffs[i])
|
Action: m.Action.String(),
|
||||||
}
|
Dir: m.Dir.String(),
|
||||||
tiles := b.EndVector(len(tileOffs))
|
MainRow: m.MainRow,
|
||||||
|
MainCol: m.MainCol,
|
||||||
wordOffs := make([]flatbuffers.UOffsetT, len(m.Words))
|
Tiles: tiles,
|
||||||
for i, w := range m.Words {
|
Words: m.Words,
|
||||||
wordOffs[i] = b.CreateString(w)
|
Count: m.Count,
|
||||||
}
|
Score: m.Score,
|
||||||
fb.MoveRecordStartWordsVector(b, len(wordOffs))
|
Total: m.Total,
|
||||||
for i := len(wordOffs) - 1; i >= 0; i-- {
|
})
|
||||||
b.PrependUOffsetT(wordOffs[i])
|
|
||||||
}
|
|
||||||
words := b.EndVector(len(wordOffs))
|
|
||||||
|
|
||||||
action := b.CreateString(m.Action.String())
|
|
||||||
dir := b.CreateString(m.Dir.String())
|
|
||||||
fb.MoveRecordStart(b)
|
|
||||||
fb.MoveRecordAddPlayer(b, int32(m.Player))
|
|
||||||
fb.MoveRecordAddAction(b, action)
|
|
||||||
fb.MoveRecordAddDir(b, dir)
|
|
||||||
fb.MoveRecordAddMainRow(b, int32(m.MainRow))
|
|
||||||
fb.MoveRecordAddMainCol(b, int32(m.MainCol))
|
|
||||||
fb.MoveRecordAddTiles(b, tiles)
|
|
||||||
fb.MoveRecordAddWords(b, words)
|
|
||||||
fb.MoveRecordAddCount(b, int32(m.Count))
|
|
||||||
fb.MoveRecordAddScore(b, int32(m.Score))
|
|
||||||
fb.MoveRecordAddTotal(b, int32(m.Total))
|
|
||||||
return fb.MoveRecordEnd(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// buildAlphabet builds the AlphabetEntry vector embedded in a StateView and returns
|
|
||||||
// its offset.
|
|
||||||
func buildAlphabet(b *flatbuffers.Builder, entries []AlphabetLetter) flatbuffers.UOffsetT {
|
|
||||||
offs := make([]flatbuffers.UOffsetT, len(entries))
|
|
||||||
for i, e := range entries {
|
|
||||||
letter := b.CreateString(e.Letter)
|
|
||||||
fb.AlphabetEntryStart(b)
|
|
||||||
fb.AlphabetEntryAddIndex(b, byte(e.Index))
|
|
||||||
fb.AlphabetEntryAddLetter(b, letter)
|
|
||||||
fb.AlphabetEntryAddValue(b, int32(e.Value))
|
|
||||||
offs[i] = fb.AlphabetEntryEnd(b)
|
|
||||||
}
|
|
||||||
fb.StateViewStartAlphabetVector(b, len(offs))
|
|
||||||
for i := len(offs) - 1; i >= 0; i-- {
|
|
||||||
b.PrependUOffsetT(offs[i])
|
|
||||||
}
|
|
||||||
return b.EndVector(len(offs))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildStateView builds a StateView table from a PlayerState and returns its offset.
|
// buildStateView builds a StateView table from a PlayerState and returns its offset.
|
||||||
func buildStateView(b *flatbuffers.Builder, s PlayerState) flatbuffers.UOffsetT {
|
func buildStateView(b *flatbuffers.Builder, s PlayerState) flatbuffers.UOffsetT {
|
||||||
game := buildGameView(b, s.Game)
|
alphabet := make([]wire.AlphabetEntry, len(s.Alphabet))
|
||||||
rackBytes := make([]byte, len(s.Rack))
|
for i, e := range s.Alphabet {
|
||||||
for i, v := range s.Rack {
|
alphabet[i] = wire.AlphabetEntry{Index: e.Index, Letter: e.Letter, Value: e.Value}
|
||||||
rackBytes[i] = byte(v)
|
|
||||||
}
|
}
|
||||||
rack := b.CreateByteVector(rackBytes)
|
return wire.BuildStateView(b, wire.StateView{
|
||||||
hasAlphabet := len(s.Alphabet) > 0
|
Game: toWireGame(s.Game),
|
||||||
var alphabet flatbuffers.UOffsetT
|
Seat: s.Seat,
|
||||||
if hasAlphabet {
|
Rack: s.Rack,
|
||||||
alphabet = buildAlphabet(b, s.Alphabet)
|
BagLen: s.BagLen,
|
||||||
}
|
HintsRemaining: s.HintsRemaining,
|
||||||
fb.StateViewStart(b)
|
Alphabet: alphabet,
|
||||||
fb.StateViewAddGame(b, game)
|
})
|
||||||
fb.StateViewAddSeat(b, int32(s.Seat))
|
|
||||||
fb.StateViewAddRack(b, rack)
|
|
||||||
fb.StateViewAddBagLen(b, int32(s.BagLen))
|
|
||||||
fb.StateViewAddHintsRemaining(b, int32(s.HintsRemaining))
|
|
||||||
if hasAlphabet {
|
|
||||||
fb.StateViewAddAlphabet(b, alphabet)
|
|
||||||
}
|
|
||||||
return fb.StateViewEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildAccountRef builds an AccountRef table and returns its offset.
|
// buildAccountRef builds an AccountRef table and returns its offset.
|
||||||
func buildAccountRef(b *flatbuffers.Builder, a AccountRef) flatbuffers.UOffsetT {
|
func buildAccountRef(b *flatbuffers.Builder, a AccountRef) flatbuffers.UOffsetT {
|
||||||
aid := b.CreateString(a.AccountID)
|
return wire.BuildAccountRef(b, wire.AccountRef{AccountID: a.AccountID, DisplayName: a.DisplayName})
|
||||||
name := b.CreateString(a.DisplayName)
|
|
||||||
fb.AccountRefStart(b)
|
|
||||||
fb.AccountRefAddAccountId(b, aid)
|
|
||||||
fb.AccountRefAddDisplayName(b, name)
|
|
||||||
return fb.AccountRefEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildInvitation builds an Invitation table from an InvitationSummary and returns its offset.
|
// buildInvitation builds an Invitation table from an InvitationSummary and returns its offset.
|
||||||
func buildInvitation(b *flatbuffers.Builder, inv InvitationSummary) flatbuffers.UOffsetT {
|
func buildInvitation(b *flatbuffers.Builder, inv InvitationSummary) flatbuffers.UOffsetT {
|
||||||
inviter := buildAccountRef(b, inv.Inviter)
|
invitees := make([]wire.InvitationInvitee, len(inv.Invitees))
|
||||||
inviteeOffs := make([]flatbuffers.UOffsetT, len(inv.Invitees))
|
|
||||||
for i, iv := range inv.Invitees {
|
for i, iv := range inv.Invitees {
|
||||||
aid := b.CreateString(iv.AccountID)
|
invitees[i] = wire.InvitationInvitee{
|
||||||
name := b.CreateString(iv.DisplayName)
|
AccountID: iv.AccountID,
|
||||||
resp := b.CreateString(iv.Response)
|
DisplayName: iv.DisplayName,
|
||||||
fb.InvitationInviteeStart(b)
|
Seat: iv.Seat,
|
||||||
fb.InvitationInviteeAddAccountId(b, aid)
|
Response: iv.Response,
|
||||||
fb.InvitationInviteeAddDisplayName(b, name)
|
}
|
||||||
fb.InvitationInviteeAddSeat(b, int32(iv.Seat))
|
|
||||||
fb.InvitationInviteeAddResponse(b, resp)
|
|
||||||
inviteeOffs[i] = fb.InvitationInviteeEnd(b)
|
|
||||||
}
|
}
|
||||||
fb.InvitationStartInviteesVector(b, len(inviteeOffs))
|
return wire.BuildInvitation(b, wire.Invitation{
|
||||||
for i := len(inviteeOffs) - 1; i >= 0; i-- {
|
ID: inv.ID,
|
||||||
b.PrependUOffsetT(inviteeOffs[i])
|
Inviter: wire.AccountRef{AccountID: inv.Inviter.AccountID, DisplayName: inv.Inviter.DisplayName},
|
||||||
}
|
Invitees: invitees,
|
||||||
invitees := b.EndVector(len(inviteeOffs))
|
Variant: inv.Variant,
|
||||||
|
TurnTimeoutSecs: inv.TurnTimeoutSecs,
|
||||||
id := b.CreateString(inv.ID)
|
HintsAllowed: inv.HintsAllowed,
|
||||||
variant := b.CreateString(inv.Variant)
|
HintsPerPlayer: inv.HintsPerPlayer,
|
||||||
dropout := b.CreateString(inv.DropoutTiles)
|
DropoutTiles: inv.DropoutTiles,
|
||||||
status := b.CreateString(inv.Status)
|
Status: inv.Status,
|
||||||
gameID := b.CreateString(inv.GameID)
|
GameID: inv.GameID,
|
||||||
fb.InvitationStart(b)
|
ExpiresAtUnix: inv.ExpiresAtUnix,
|
||||||
fb.InvitationAddId(b, id)
|
})
|
||||||
fb.InvitationAddInviter(b, inviter)
|
|
||||||
fb.InvitationAddInvitees(b, invitees)
|
|
||||||
fb.InvitationAddVariant(b, variant)
|
|
||||||
fb.InvitationAddTurnTimeoutSecs(b, int32(inv.TurnTimeoutSecs))
|
|
||||||
fb.InvitationAddHintsAllowed(b, inv.HintsAllowed)
|
|
||||||
fb.InvitationAddHintsPerPlayer(b, int32(inv.HintsPerPlayer))
|
|
||||||
fb.InvitationAddDropoutTiles(b, dropout)
|
|
||||||
fb.InvitationAddStatus(b, status)
|
|
||||||
fb.InvitationAddGameId(b, gameID)
|
|
||||||
fb.InvitationAddExpiresAtUnix(b, inv.ExpiresAtUnix)
|
|
||||||
return fb.InvitationEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"scrabble/gateway/internal/backendclient"
|
"scrabble/gateway/internal/backendclient"
|
||||||
fb "scrabble/pkg/fbs/scrabblefb"
|
fb "scrabble/pkg/fbs/scrabblefb"
|
||||||
|
"scrabble/pkg/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The encoders build the FlatBuffers response payloads from the backend's typed
|
// The encoders build the FlatBuffers response payloads from the backend's typed
|
||||||
@@ -142,46 +143,24 @@ func encodeMoveResult(r backendclient.MoveResultResp) []byte {
|
|||||||
// client requests it on a per-variant cache miss).
|
// client requests it on a per-variant cache miss).
|
||||||
func encodeState(s backendclient.StateResp) []byte {
|
func encodeState(s backendclient.StateResp) []byte {
|
||||||
b := flatbuffers.NewBuilder(512)
|
b := flatbuffers.NewBuilder(512)
|
||||||
game := buildGameView(b, s.Game)
|
b.Finish(wire.BuildStateView(b, toWireState(s)))
|
||||||
rackBytes := make([]byte, len(s.Rack))
|
|
||||||
for i, v := range s.Rack {
|
|
||||||
rackBytes[i] = byte(v)
|
|
||||||
}
|
|
||||||
rack := b.CreateByteVector(rackBytes)
|
|
||||||
hasAlphabet := len(s.Alphabet) > 0
|
|
||||||
var alphabet flatbuffers.UOffsetT
|
|
||||||
if hasAlphabet {
|
|
||||||
alphabet = buildAlphabet(b, s.Alphabet)
|
|
||||||
}
|
|
||||||
fb.StateViewStart(b)
|
|
||||||
fb.StateViewAddGame(b, game)
|
|
||||||
fb.StateViewAddSeat(b, int32(s.Seat))
|
|
||||||
fb.StateViewAddRack(b, rack)
|
|
||||||
fb.StateViewAddBagLen(b, int32(s.BagLen))
|
|
||||||
fb.StateViewAddHintsRemaining(b, int32(s.HintsRemaining))
|
|
||||||
if hasAlphabet {
|
|
||||||
fb.StateViewAddAlphabet(b, alphabet)
|
|
||||||
}
|
|
||||||
b.Finish(fb.StateViewEnd(b))
|
|
||||||
return b.FinishedBytes()
|
return b.FinishedBytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildAlphabet builds the AlphabetEntry vector for a StateView and returns its offset.
|
// toWireState maps a StateResp to the shared wire.StateView.
|
||||||
func buildAlphabet(b *flatbuffers.Builder, entries []backendclient.AlphabetEntryJSON) flatbuffers.UOffsetT {
|
func toWireState(s backendclient.StateResp) wire.StateView {
|
||||||
offs := make([]flatbuffers.UOffsetT, len(entries))
|
alphabet := make([]wire.AlphabetEntry, len(s.Alphabet))
|
||||||
for i, e := range entries {
|
for i, e := range s.Alphabet {
|
||||||
letter := b.CreateString(e.Letter)
|
alphabet[i] = wire.AlphabetEntry{Index: e.Index, Letter: e.Letter, Value: e.Value}
|
||||||
fb.AlphabetEntryStart(b)
|
|
||||||
fb.AlphabetEntryAddIndex(b, byte(e.Index))
|
|
||||||
fb.AlphabetEntryAddLetter(b, letter)
|
|
||||||
fb.AlphabetEntryAddValue(b, int32(e.Value))
|
|
||||||
offs[i] = fb.AlphabetEntryEnd(b)
|
|
||||||
}
|
}
|
||||||
fb.StateViewStartAlphabetVector(b, len(offs))
|
return wire.StateView{
|
||||||
for i := len(offs) - 1; i >= 0; i-- {
|
Game: toWireGame(s.Game),
|
||||||
b.PrependUOffsetT(offs[i])
|
Seat: s.Seat,
|
||||||
|
Rack: s.Rack,
|
||||||
|
BagLen: s.BagLen,
|
||||||
|
HintsRemaining: s.HintsRemaining,
|
||||||
|
Alphabet: alphabet,
|
||||||
}
|
}
|
||||||
return b.EndVector(len(offs))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeMatch builds a MatchResult payload.
|
// encodeMatch builds a MatchResult payload.
|
||||||
@@ -328,80 +307,55 @@ func encodeChatList(r backendclient.ChatListResp) []byte {
|
|||||||
|
|
||||||
// buildGameView builds a GameView table and returns its offset.
|
// buildGameView builds a GameView table and returns its offset.
|
||||||
func buildGameView(b *flatbuffers.Builder, g backendclient.GameResp) flatbuffers.UOffsetT {
|
func buildGameView(b *flatbuffers.Builder, g backendclient.GameResp) flatbuffers.UOffsetT {
|
||||||
seatOffs := make([]flatbuffers.UOffsetT, len(g.Seats))
|
return wire.BuildGameView(b, toWireGame(g))
|
||||||
|
}
|
||||||
|
|
||||||
|
// toWireGame maps a GameResp to the shared wire.GameView.
|
||||||
|
func toWireGame(g backendclient.GameResp) wire.GameView {
|
||||||
|
seats := make([]wire.SeatView, len(g.Seats))
|
||||||
for i, s := range g.Seats {
|
for i, s := range g.Seats {
|
||||||
aid := b.CreateString(s.AccountID)
|
seats[i] = wire.SeatView{
|
||||||
dname := b.CreateString(s.DisplayName)
|
Seat: s.Seat,
|
||||||
fb.SeatViewStart(b)
|
AccountID: s.AccountID,
|
||||||
fb.SeatViewAddSeat(b, int32(s.Seat))
|
Score: s.Score,
|
||||||
fb.SeatViewAddAccountId(b, aid)
|
HintsUsed: s.HintsUsed,
|
||||||
fb.SeatViewAddScore(b, int32(s.Score))
|
IsWinner: s.IsWinner,
|
||||||
fb.SeatViewAddHintsUsed(b, int32(s.HintsUsed))
|
DisplayName: s.DisplayName,
|
||||||
fb.SeatViewAddIsWinner(b, s.IsWinner)
|
}
|
||||||
fb.SeatViewAddDisplayName(b, dname)
|
|
||||||
seatOffs[i] = fb.SeatViewEnd(b)
|
|
||||||
}
|
}
|
||||||
fb.GameViewStartSeatsVector(b, len(seatOffs))
|
return wire.GameView{
|
||||||
for i := len(seatOffs) - 1; i >= 0; i-- {
|
ID: g.ID,
|
||||||
b.PrependUOffsetT(seatOffs[i])
|
Variant: g.Variant,
|
||||||
|
DictVersion: g.DictVersion,
|
||||||
|
Status: g.Status,
|
||||||
|
Players: g.Players,
|
||||||
|
ToMove: g.ToMove,
|
||||||
|
TurnTimeoutSecs: g.TurnTimeoutSecs,
|
||||||
|
MoveCount: g.MoveCount,
|
||||||
|
EndReason: g.EndReason,
|
||||||
|
Seats: seats,
|
||||||
|
LastActivityUnix: g.LastActivityUnix,
|
||||||
}
|
}
|
||||||
seats := b.EndVector(len(seatOffs))
|
|
||||||
|
|
||||||
id := b.CreateString(g.ID)
|
|
||||||
variant := b.CreateString(g.Variant)
|
|
||||||
dictVer := b.CreateString(g.DictVersion)
|
|
||||||
status := b.CreateString(g.Status)
|
|
||||||
endReason := b.CreateString(g.EndReason)
|
|
||||||
|
|
||||||
fb.GameViewStart(b)
|
|
||||||
fb.GameViewAddId(b, id)
|
|
||||||
fb.GameViewAddVariant(b, variant)
|
|
||||||
fb.GameViewAddDictVersion(b, dictVer)
|
|
||||||
fb.GameViewAddStatus(b, status)
|
|
||||||
fb.GameViewAddPlayers(b, int32(g.Players))
|
|
||||||
fb.GameViewAddToMove(b, int32(g.ToMove))
|
|
||||||
fb.GameViewAddTurnTimeoutSecs(b, int32(g.TurnTimeoutSecs))
|
|
||||||
fb.GameViewAddMoveCount(b, int32(g.MoveCount))
|
|
||||||
fb.GameViewAddEndReason(b, endReason)
|
|
||||||
fb.GameViewAddSeats(b, seats)
|
|
||||||
fb.GameViewAddLastActivityUnix(b, g.LastActivityUnix)
|
|
||||||
return fb.GameViewEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildMoveRecord builds a MoveRecord table and returns its offset.
|
// buildMoveRecord builds a MoveRecord table and returns its offset.
|
||||||
func buildMoveRecord(b *flatbuffers.Builder, m backendclient.MoveRecordResp) flatbuffers.UOffsetT {
|
func buildMoveRecord(b *flatbuffers.Builder, m backendclient.MoveRecordResp) flatbuffers.UOffsetT {
|
||||||
tileOffs := make([]flatbuffers.UOffsetT, len(m.Tiles))
|
tiles := make([]wire.TileRecord, len(m.Tiles))
|
||||||
for i, t := range m.Tiles {
|
for i, t := range m.Tiles {
|
||||||
letter := b.CreateString(t.Letter)
|
tiles[i] = wire.TileRecord{Row: t.Row, Col: t.Col, Letter: t.Letter, Blank: t.Blank}
|
||||||
fb.TileRecordStart(b)
|
|
||||||
fb.TileRecordAddRow(b, int32(t.Row))
|
|
||||||
fb.TileRecordAddCol(b, int32(t.Col))
|
|
||||||
fb.TileRecordAddLetter(b, letter)
|
|
||||||
fb.TileRecordAddBlank(b, t.Blank)
|
|
||||||
tileOffs[i] = fb.TileRecordEnd(b)
|
|
||||||
}
|
}
|
||||||
fb.MoveRecordStartTilesVector(b, len(tileOffs))
|
return wire.BuildMoveRecord(b, wire.MoveRecord{
|
||||||
for i := len(tileOffs) - 1; i >= 0; i-- {
|
Player: m.Player,
|
||||||
b.PrependUOffsetT(tileOffs[i])
|
Action: m.Action,
|
||||||
}
|
Dir: m.Dir,
|
||||||
tiles := b.EndVector(len(tileOffs))
|
MainRow: m.MainRow,
|
||||||
|
MainCol: m.MainCol,
|
||||||
words := buildStringVector(b, m.Words, fb.MoveRecordStartWordsVector)
|
Tiles: tiles,
|
||||||
|
Words: m.Words,
|
||||||
action := b.CreateString(m.Action)
|
Count: m.Count,
|
||||||
dir := b.CreateString(m.Dir)
|
Score: m.Score,
|
||||||
fb.MoveRecordStart(b)
|
Total: m.Total,
|
||||||
fb.MoveRecordAddPlayer(b, int32(m.Player))
|
})
|
||||||
fb.MoveRecordAddAction(b, action)
|
|
||||||
fb.MoveRecordAddDir(b, dir)
|
|
||||||
fb.MoveRecordAddMainRow(b, int32(m.MainRow))
|
|
||||||
fb.MoveRecordAddMainCol(b, int32(m.MainCol))
|
|
||||||
fb.MoveRecordAddTiles(b, tiles)
|
|
||||||
fb.MoveRecordAddWords(b, words)
|
|
||||||
fb.MoveRecordAddCount(b, int32(m.Count))
|
|
||||||
fb.MoveRecordAddScore(b, int32(m.Score))
|
|
||||||
fb.MoveRecordAddTotal(b, int32(m.Total))
|
|
||||||
return fb.MoveRecordEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildStringVector builds a vector of strings using the table-specific
|
// buildStringVector builds a vector of strings using the table-specific
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"scrabble/gateway/internal/backendclient"
|
"scrabble/gateway/internal/backendclient"
|
||||||
fb "scrabble/pkg/fbs/scrabblefb"
|
fb "scrabble/pkg/fbs/scrabblefb"
|
||||||
|
"scrabble/pkg/wire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Social encoders: friends, blocks, invitations, statistics and GCG. They follow
|
// Social encoders: friends, blocks, invitations, statistics and GCG. They follow
|
||||||
@@ -12,12 +13,7 @@ import (
|
|||||||
|
|
||||||
// buildAccountRef builds an AccountRef table and returns its offset.
|
// buildAccountRef builds an AccountRef table and returns its offset.
|
||||||
func buildAccountRef(b *flatbuffers.Builder, r backendclient.AccountRefResp) flatbuffers.UOffsetT {
|
func buildAccountRef(b *flatbuffers.Builder, r backendclient.AccountRefResp) flatbuffers.UOffsetT {
|
||||||
id := b.CreateString(r.AccountID)
|
return wire.BuildAccountRef(b, wire.AccountRef{AccountID: r.AccountID, DisplayName: r.DisplayName})
|
||||||
name := b.CreateString(r.DisplayName)
|
|
||||||
fb.AccountRefStart(b)
|
|
||||||
fb.AccountRefAddAccountId(b, id)
|
|
||||||
fb.AccountRefAddDisplayName(b, name)
|
|
||||||
return fb.AccountRefEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildAccountRefVector builds a [AccountRef] vector using the table-specific
|
// buildAccountRefVector builds a [AccountRef] vector using the table-specific
|
||||||
@@ -110,43 +106,28 @@ func encodeStats(r backendclient.StatsResp) []byte {
|
|||||||
|
|
||||||
// buildInvitation builds an Invitation table and returns its offset.
|
// buildInvitation builds an Invitation table and returns its offset.
|
||||||
func buildInvitation(b *flatbuffers.Builder, inv backendclient.InvitationResp) flatbuffers.UOffsetT {
|
func buildInvitation(b *flatbuffers.Builder, inv backendclient.InvitationResp) flatbuffers.UOffsetT {
|
||||||
inviteeOffs := make([]flatbuffers.UOffsetT, len(inv.Invitees))
|
invitees := make([]wire.InvitationInvitee, len(inv.Invitees))
|
||||||
for i, iv := range inv.Invitees {
|
for i, iv := range inv.Invitees {
|
||||||
aid := b.CreateString(iv.AccountID)
|
invitees[i] = wire.InvitationInvitee{
|
||||||
name := b.CreateString(iv.DisplayName)
|
AccountID: iv.AccountID,
|
||||||
resp := b.CreateString(iv.Response)
|
DisplayName: iv.DisplayName,
|
||||||
fb.InvitationInviteeStart(b)
|
Seat: iv.Seat,
|
||||||
fb.InvitationInviteeAddAccountId(b, aid)
|
Response: iv.Response,
|
||||||
fb.InvitationInviteeAddDisplayName(b, name)
|
}
|
||||||
fb.InvitationInviteeAddSeat(b, int32(iv.Seat))
|
|
||||||
fb.InvitationInviteeAddResponse(b, resp)
|
|
||||||
inviteeOffs[i] = fb.InvitationInviteeEnd(b)
|
|
||||||
}
|
}
|
||||||
fb.InvitationStartInviteesVector(b, len(inviteeOffs))
|
return wire.BuildInvitation(b, wire.Invitation{
|
||||||
for i := len(inviteeOffs) - 1; i >= 0; i-- {
|
ID: inv.ID,
|
||||||
b.PrependUOffsetT(inviteeOffs[i])
|
Inviter: wire.AccountRef{AccountID: inv.Inviter.AccountID, DisplayName: inv.Inviter.DisplayName},
|
||||||
}
|
Invitees: invitees,
|
||||||
invitees := b.EndVector(len(inviteeOffs))
|
Variant: inv.Variant,
|
||||||
|
TurnTimeoutSecs: inv.TurnTimeoutSecs,
|
||||||
inviter := buildAccountRef(b, inv.Inviter)
|
HintsAllowed: inv.HintsAllowed,
|
||||||
id := b.CreateString(inv.ID)
|
HintsPerPlayer: inv.HintsPerPlayer,
|
||||||
variant := b.CreateString(inv.Variant)
|
DropoutTiles: inv.DropoutTiles,
|
||||||
dropout := b.CreateString(inv.DropoutTiles)
|
Status: inv.Status,
|
||||||
status := b.CreateString(inv.Status)
|
GameID: inv.GameID,
|
||||||
gameID := b.CreateString(inv.GameID)
|
ExpiresAtUnix: inv.ExpiresAtUnix,
|
||||||
fb.InvitationStart(b)
|
})
|
||||||
fb.InvitationAddId(b, id)
|
|
||||||
fb.InvitationAddInviter(b, inviter)
|
|
||||||
fb.InvitationAddInvitees(b, invitees)
|
|
||||||
fb.InvitationAddVariant(b, variant)
|
|
||||||
fb.InvitationAddTurnTimeoutSecs(b, int32(inv.TurnTimeoutSecs))
|
|
||||||
fb.InvitationAddHintsAllowed(b, inv.HintsAllowed)
|
|
||||||
fb.InvitationAddHintsPerPlayer(b, int32(inv.HintsPerPlayer))
|
|
||||||
fb.InvitationAddDropoutTiles(b, dropout)
|
|
||||||
fb.InvitationAddStatus(b, status)
|
|
||||||
fb.InvitationAddGameId(b, gameID)
|
|
||||||
fb.InvitationAddExpiresAtUnix(b, inv.ExpiresAtUnix)
|
|
||||||
return fb.InvitationEnd(b)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// encodeInvitation builds an Invitation payload.
|
// encodeInvitation builds an Invitation payload.
|
||||||
|
|||||||
@@ -0,0 +1,299 @@
|
|||||||
|
// Package wire holds the FlatBuffers builders for the nested wire tables that both
|
||||||
|
// the backend's push-event encoder (backend/internal/notify) and the gateway's edge
|
||||||
|
// transcoder (gateway/internal/transcode) emit. The two callers resolve their own
|
||||||
|
// source types (the backend's domain payloads, the gateway's REST DTOs) into the
|
||||||
|
// neutral structs below and delegate the actual FlatBuffers construction here, so the
|
||||||
|
// shared tables (GameView, MoveRecord, StateView, AccountRef, Invitation) have a
|
||||||
|
// single encoding definition that cannot drift between the two paths.
|
||||||
|
//
|
||||||
|
// FlatBuffers is built bottom-up: every string and child vector is created before the
|
||||||
|
// table that references it, and no two tables/vectors are under construction at once.
|
||||||
|
// Each builder returns the offset of the table (or vector) it built; the caller embeds
|
||||||
|
// that offset in a parent table or finishes the buffer with it.
|
||||||
|
package wire
|
||||||
|
|
||||||
|
import (
|
||||||
|
flatbuffers "github.com/google/flatbuffers/go"
|
||||||
|
|
||||||
|
fb "scrabble/pkg/fbs/scrabblefb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SeatView is one seat's public standing in a GameView.
|
||||||
|
type SeatView struct {
|
||||||
|
Seat int
|
||||||
|
AccountID string
|
||||||
|
Score int
|
||||||
|
HintsUsed int
|
||||||
|
IsWinner bool
|
||||||
|
DisplayName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GameView is the shared, non-private game summary.
|
||||||
|
type GameView struct {
|
||||||
|
ID string
|
||||||
|
Variant string
|
||||||
|
DictVersion string
|
||||||
|
Status string
|
||||||
|
Players int
|
||||||
|
ToMove int
|
||||||
|
TurnTimeoutSecs int
|
||||||
|
MoveCount int
|
||||||
|
EndReason string
|
||||||
|
Seats []SeatView
|
||||||
|
LastActivityUnix int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// TileRecord is one tile in a decoded MoveRecord (the concrete letter, "?" for a blank
|
||||||
|
// read from a hand).
|
||||||
|
type TileRecord struct {
|
||||||
|
Row int
|
||||||
|
Col int
|
||||||
|
Letter string
|
||||||
|
Blank bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// MoveRecord is one decoded move (a committed play, a hint preview). Action and Dir are
|
||||||
|
// the already-stringified move kind and direction.
|
||||||
|
type MoveRecord struct {
|
||||||
|
Player int
|
||||||
|
Action string
|
||||||
|
Dir string
|
||||||
|
MainRow int
|
||||||
|
MainCol int
|
||||||
|
Tiles []TileRecord
|
||||||
|
Words []string
|
||||||
|
Count int
|
||||||
|
Score int
|
||||||
|
Total int
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlphabetEntry is one letter of a variant's alphabet (Index is the wire alphabet-index
|
||||||
|
// byte; a value of 255 is the blank sentinel elsewhere).
|
||||||
|
type AlphabetEntry struct {
|
||||||
|
Index int
|
||||||
|
Letter string
|
||||||
|
Value int
|
||||||
|
}
|
||||||
|
|
||||||
|
// StateView is a player's view of a game: the shared summary plus their private rack
|
||||||
|
// (wire alphabet indices), bag size and hint budget. Alphabet is set only when the
|
||||||
|
// recipient may not have cached the variant's display table yet.
|
||||||
|
type StateView struct {
|
||||||
|
Game GameView
|
||||||
|
Seat int
|
||||||
|
Rack []int
|
||||||
|
BagLen int
|
||||||
|
HintsRemaining int
|
||||||
|
Alphabet []AlphabetEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountRef is a referenced account with its display name resolved.
|
||||||
|
type AccountRef struct {
|
||||||
|
AccountID string
|
||||||
|
DisplayName string
|
||||||
|
}
|
||||||
|
|
||||||
|
// InvitationInvitee is one invited player's seat and response inside an Invitation.
|
||||||
|
type InvitationInvitee struct {
|
||||||
|
AccountID string
|
||||||
|
DisplayName string
|
||||||
|
Seat int
|
||||||
|
Response string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invitation is a friend-game invitation with its settings and invitees.
|
||||||
|
type Invitation struct {
|
||||||
|
ID string
|
||||||
|
Inviter AccountRef
|
||||||
|
Invitees []InvitationInvitee
|
||||||
|
Variant string
|
||||||
|
TurnTimeoutSecs int
|
||||||
|
HintsAllowed bool
|
||||||
|
HintsPerPlayer int
|
||||||
|
DropoutTiles string
|
||||||
|
Status string
|
||||||
|
GameID string
|
||||||
|
ExpiresAtUnix int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildGameView builds a GameView table from g and returns its offset.
|
||||||
|
func BuildGameView(b *flatbuffers.Builder, g GameView) flatbuffers.UOffsetT {
|
||||||
|
seatOffs := make([]flatbuffers.UOffsetT, len(g.Seats))
|
||||||
|
for i, s := range g.Seats {
|
||||||
|
aid := b.CreateString(s.AccountID)
|
||||||
|
dname := b.CreateString(s.DisplayName)
|
||||||
|
fb.SeatViewStart(b)
|
||||||
|
fb.SeatViewAddSeat(b, int32(s.Seat))
|
||||||
|
fb.SeatViewAddAccountId(b, aid)
|
||||||
|
fb.SeatViewAddScore(b, int32(s.Score))
|
||||||
|
fb.SeatViewAddHintsUsed(b, int32(s.HintsUsed))
|
||||||
|
fb.SeatViewAddIsWinner(b, s.IsWinner)
|
||||||
|
fb.SeatViewAddDisplayName(b, dname)
|
||||||
|
seatOffs[i] = fb.SeatViewEnd(b)
|
||||||
|
}
|
||||||
|
fb.GameViewStartSeatsVector(b, len(seatOffs))
|
||||||
|
for i := len(seatOffs) - 1; i >= 0; i-- {
|
||||||
|
b.PrependUOffsetT(seatOffs[i])
|
||||||
|
}
|
||||||
|
seats := b.EndVector(len(seatOffs))
|
||||||
|
|
||||||
|
id := b.CreateString(g.ID)
|
||||||
|
variant := b.CreateString(g.Variant)
|
||||||
|
dictVer := b.CreateString(g.DictVersion)
|
||||||
|
status := b.CreateString(g.Status)
|
||||||
|
endReason := b.CreateString(g.EndReason)
|
||||||
|
|
||||||
|
fb.GameViewStart(b)
|
||||||
|
fb.GameViewAddId(b, id)
|
||||||
|
fb.GameViewAddVariant(b, variant)
|
||||||
|
fb.GameViewAddDictVersion(b, dictVer)
|
||||||
|
fb.GameViewAddStatus(b, status)
|
||||||
|
fb.GameViewAddPlayers(b, int32(g.Players))
|
||||||
|
fb.GameViewAddToMove(b, int32(g.ToMove))
|
||||||
|
fb.GameViewAddTurnTimeoutSecs(b, int32(g.TurnTimeoutSecs))
|
||||||
|
fb.GameViewAddMoveCount(b, int32(g.MoveCount))
|
||||||
|
fb.GameViewAddEndReason(b, endReason)
|
||||||
|
fb.GameViewAddSeats(b, seats)
|
||||||
|
fb.GameViewAddLastActivityUnix(b, g.LastActivityUnix)
|
||||||
|
return fb.GameViewEnd(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildMoveRecord builds a MoveRecord table from m and returns its offset.
|
||||||
|
func BuildMoveRecord(b *flatbuffers.Builder, m MoveRecord) flatbuffers.UOffsetT {
|
||||||
|
tileOffs := make([]flatbuffers.UOffsetT, len(m.Tiles))
|
||||||
|
for i, t := range m.Tiles {
|
||||||
|
letter := b.CreateString(t.Letter)
|
||||||
|
fb.TileRecordStart(b)
|
||||||
|
fb.TileRecordAddRow(b, int32(t.Row))
|
||||||
|
fb.TileRecordAddCol(b, int32(t.Col))
|
||||||
|
fb.TileRecordAddLetter(b, letter)
|
||||||
|
fb.TileRecordAddBlank(b, t.Blank)
|
||||||
|
tileOffs[i] = fb.TileRecordEnd(b)
|
||||||
|
}
|
||||||
|
fb.MoveRecordStartTilesVector(b, len(tileOffs))
|
||||||
|
for i := len(tileOffs) - 1; i >= 0; i-- {
|
||||||
|
b.PrependUOffsetT(tileOffs[i])
|
||||||
|
}
|
||||||
|
tiles := b.EndVector(len(tileOffs))
|
||||||
|
|
||||||
|
wordOffs := make([]flatbuffers.UOffsetT, len(m.Words))
|
||||||
|
for i, w := range m.Words {
|
||||||
|
wordOffs[i] = b.CreateString(w)
|
||||||
|
}
|
||||||
|
fb.MoveRecordStartWordsVector(b, len(wordOffs))
|
||||||
|
for i := len(wordOffs) - 1; i >= 0; i-- {
|
||||||
|
b.PrependUOffsetT(wordOffs[i])
|
||||||
|
}
|
||||||
|
words := b.EndVector(len(wordOffs))
|
||||||
|
|
||||||
|
action := b.CreateString(m.Action)
|
||||||
|
dir := b.CreateString(m.Dir)
|
||||||
|
fb.MoveRecordStart(b)
|
||||||
|
fb.MoveRecordAddPlayer(b, int32(m.Player))
|
||||||
|
fb.MoveRecordAddAction(b, action)
|
||||||
|
fb.MoveRecordAddDir(b, dir)
|
||||||
|
fb.MoveRecordAddMainRow(b, int32(m.MainRow))
|
||||||
|
fb.MoveRecordAddMainCol(b, int32(m.MainCol))
|
||||||
|
fb.MoveRecordAddTiles(b, tiles)
|
||||||
|
fb.MoveRecordAddWords(b, words)
|
||||||
|
fb.MoveRecordAddCount(b, int32(m.Count))
|
||||||
|
fb.MoveRecordAddScore(b, int32(m.Score))
|
||||||
|
fb.MoveRecordAddTotal(b, int32(m.Total))
|
||||||
|
return fb.MoveRecordEnd(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildStateViewAlphabet builds the AlphabetEntry vector embedded in a StateView and
|
||||||
|
// returns its offset.
|
||||||
|
func BuildStateViewAlphabet(b *flatbuffers.Builder, entries []AlphabetEntry) flatbuffers.UOffsetT {
|
||||||
|
offs := make([]flatbuffers.UOffsetT, len(entries))
|
||||||
|
for i, e := range entries {
|
||||||
|
letter := b.CreateString(e.Letter)
|
||||||
|
fb.AlphabetEntryStart(b)
|
||||||
|
fb.AlphabetEntryAddIndex(b, byte(e.Index))
|
||||||
|
fb.AlphabetEntryAddLetter(b, letter)
|
||||||
|
fb.AlphabetEntryAddValue(b, int32(e.Value))
|
||||||
|
offs[i] = fb.AlphabetEntryEnd(b)
|
||||||
|
}
|
||||||
|
fb.StateViewStartAlphabetVector(b, len(offs))
|
||||||
|
for i := len(offs) - 1; i >= 0; i-- {
|
||||||
|
b.PrependUOffsetT(offs[i])
|
||||||
|
}
|
||||||
|
return b.EndVector(len(offs))
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildStateView builds a StateView table from s and returns its offset. The alphabet
|
||||||
|
// table is embedded only when s.Alphabet is non-empty.
|
||||||
|
func BuildStateView(b *flatbuffers.Builder, s StateView) flatbuffers.UOffsetT {
|
||||||
|
game := BuildGameView(b, s.Game)
|
||||||
|
rackBytes := make([]byte, len(s.Rack))
|
||||||
|
for i, v := range s.Rack {
|
||||||
|
rackBytes[i] = byte(v)
|
||||||
|
}
|
||||||
|
rack := b.CreateByteVector(rackBytes)
|
||||||
|
hasAlphabet := len(s.Alphabet) > 0
|
||||||
|
var alphabet flatbuffers.UOffsetT
|
||||||
|
if hasAlphabet {
|
||||||
|
alphabet = BuildStateViewAlphabet(b, s.Alphabet)
|
||||||
|
}
|
||||||
|
fb.StateViewStart(b)
|
||||||
|
fb.StateViewAddGame(b, game)
|
||||||
|
fb.StateViewAddSeat(b, int32(s.Seat))
|
||||||
|
fb.StateViewAddRack(b, rack)
|
||||||
|
fb.StateViewAddBagLen(b, int32(s.BagLen))
|
||||||
|
fb.StateViewAddHintsRemaining(b, int32(s.HintsRemaining))
|
||||||
|
if hasAlphabet {
|
||||||
|
fb.StateViewAddAlphabet(b, alphabet)
|
||||||
|
}
|
||||||
|
return fb.StateViewEnd(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildAccountRef builds an AccountRef table from a and returns its offset.
|
||||||
|
func BuildAccountRef(b *flatbuffers.Builder, a AccountRef) flatbuffers.UOffsetT {
|
||||||
|
aid := b.CreateString(a.AccountID)
|
||||||
|
name := b.CreateString(a.DisplayName)
|
||||||
|
fb.AccountRefStart(b)
|
||||||
|
fb.AccountRefAddAccountId(b, aid)
|
||||||
|
fb.AccountRefAddDisplayName(b, name)
|
||||||
|
return fb.AccountRefEnd(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildInvitation builds an Invitation table from inv and returns its offset.
|
||||||
|
func BuildInvitation(b *flatbuffers.Builder, inv Invitation) flatbuffers.UOffsetT {
|
||||||
|
inviteeOffs := make([]flatbuffers.UOffsetT, len(inv.Invitees))
|
||||||
|
for i, iv := range inv.Invitees {
|
||||||
|
aid := b.CreateString(iv.AccountID)
|
||||||
|
name := b.CreateString(iv.DisplayName)
|
||||||
|
resp := b.CreateString(iv.Response)
|
||||||
|
fb.InvitationInviteeStart(b)
|
||||||
|
fb.InvitationInviteeAddAccountId(b, aid)
|
||||||
|
fb.InvitationInviteeAddDisplayName(b, name)
|
||||||
|
fb.InvitationInviteeAddSeat(b, int32(iv.Seat))
|
||||||
|
fb.InvitationInviteeAddResponse(b, resp)
|
||||||
|
inviteeOffs[i] = fb.InvitationInviteeEnd(b)
|
||||||
|
}
|
||||||
|
fb.InvitationStartInviteesVector(b, len(inviteeOffs))
|
||||||
|
for i := len(inviteeOffs) - 1; i >= 0; i-- {
|
||||||
|
b.PrependUOffsetT(inviteeOffs[i])
|
||||||
|
}
|
||||||
|
invitees := b.EndVector(len(inviteeOffs))
|
||||||
|
|
||||||
|
inviter := BuildAccountRef(b, inv.Inviter)
|
||||||
|
id := b.CreateString(inv.ID)
|
||||||
|
variant := b.CreateString(inv.Variant)
|
||||||
|
dropout := b.CreateString(inv.DropoutTiles)
|
||||||
|
status := b.CreateString(inv.Status)
|
||||||
|
gameID := b.CreateString(inv.GameID)
|
||||||
|
fb.InvitationStart(b)
|
||||||
|
fb.InvitationAddId(b, id)
|
||||||
|
fb.InvitationAddInviter(b, inviter)
|
||||||
|
fb.InvitationAddInvitees(b, invitees)
|
||||||
|
fb.InvitationAddVariant(b, variant)
|
||||||
|
fb.InvitationAddTurnTimeoutSecs(b, int32(inv.TurnTimeoutSecs))
|
||||||
|
fb.InvitationAddHintsAllowed(b, inv.HintsAllowed)
|
||||||
|
fb.InvitationAddHintsPerPlayer(b, int32(inv.HintsPerPlayer))
|
||||||
|
fb.InvitationAddDropoutTiles(b, dropout)
|
||||||
|
fb.InvitationAddStatus(b, status)
|
||||||
|
fb.InvitationAddGameId(b, gameID)
|
||||||
|
fb.InvitationAddExpiresAtUnix(b, inv.ExpiresAtUnix)
|
||||||
|
return fb.InvitationEnd(b)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user