package plays import ( "fmt" "net/http" "net/url" "strings" "time" "gitea.konchin.com/ytshih/inp2025/game/tracing" "gitea.konchin.com/ytshih/inp2025/game/types" tea "github.com/charmbracelet/bubbletea" "go.uber.org/zap" ) type RoomWaiting struct { *Base roomID string room *types.Room } func NewRoomWaiting(base *Base, roomID string) *RoomWaiting { return &RoomWaiting{ Base: base, roomID: roomID, } } func (m *RoomWaiting) checkRoomStatus() tea.Msg { resp, err := m.Base.client.R(). SetResult(&types.Room{}). Get(fmt.Sprintf("/api/rooms/%s", m.roomID)) if err != nil || resp.StatusCode() != http.StatusOK { return types.TickMsg{} // Keep polling } room := resp.Result().(*types.Room) if room.Status == types.RoomStatusPlaying { m.room = room return tea.Quit() // Stop polling and proceed } return types.TickMsg{} // Keep polling } func (m *RoomWaiting) Init() tea.Cmd { return tea.Batch(tea.ClearScreen, func() tea.Msg { return types.TickMsg(time.Now()) }) } func (m *RoomWaiting) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case types.TickMsg: time.Sleep(1 * time.Second) return m, m.checkRoomStatus case tea.KeyMsg: switch msg.String() { case "ctrl+c", "q": return m, tea.Quit } } return m, nil } func (m *RoomWaiting) View() string { var b strings.Builder b.WriteString("Waiting for another player to join...\n") b.WriteString(fmt.Sprintf("Room ID: %s\n", m.roomID)) return b.String() } func (m *RoomWaiting) Next(queue *[]*tea.Program) error { if m.room != nil && m.room.Status == types.RoomStatusPlaying { hostURL := m.Base.client.HostURL wsHost := strings.Replace(hostURL, "http", "ws", 1) wsURL := fmt.Sprintf("%s/api/rooms/%s/state", wsHost, m.roomID) tracing.Logger.Info("parsing websocket url", zap.String("url", wsURL)) u, err := url.Parse(wsURL) if err != nil { return err } *queue = append(*queue, tea.NewProgram(NewGame(m.Base, u, m.roomID))) } else { // If we quit without the room being ready, go back to the lobby. *queue = append(*queue, tea.NewProgram(NewLobby(m.Base))) } return nil }