update
This commit is contained in:
@@ -78,6 +78,84 @@ func (a *App) handleUpdateAdminSettings(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, state)
|
||||
}
|
||||
|
||||
func (a *App) handleStartCurrentStage(c echo.Context) error {
|
||||
var req StageControlStartRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return writeError(c, http.StatusBadRequest, "invalid request body")
|
||||
}
|
||||
|
||||
phase, ok := normalizeStagePhase(req.Phase)
|
||||
if !ok {
|
||||
return writeError(c, http.StatusBadRequest, "invalid phase")
|
||||
}
|
||||
groupKey, ok := normalizeStageGroup(phase, req.GroupKey)
|
||||
if !ok {
|
||||
return writeError(c, http.StatusBadRequest, "invalid group for selected phase")
|
||||
}
|
||||
round := normalizeStageRound(phase, req.Round)
|
||||
|
||||
current, err := a.readCurrentStage()
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
if current != nil {
|
||||
return writeError(c, http.StatusConflict, "there is already an active stage. end it first")
|
||||
}
|
||||
|
||||
_, err = a.db.Exec(`
|
||||
INSERT INTO stage_sessions(phase, group_key, round, started_at)
|
||||
VALUES(?, ?, ?, CURRENT_TIMESTAMP)
|
||||
`, phase, groupKey, round)
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, fmt.Sprintf("start stage: %v", err))
|
||||
}
|
||||
|
||||
a.events.Broadcast()
|
||||
|
||||
state, err := a.readState(true)
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return c.JSON(http.StatusOK, state)
|
||||
}
|
||||
|
||||
func (a *App) handleEndCurrentStage(c echo.Context) error {
|
||||
current, err := a.readCurrentStage()
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
if current == nil {
|
||||
return writeError(c, http.StatusBadRequest, "no active stage to end")
|
||||
}
|
||||
|
||||
_, err = a.db.Exec(`
|
||||
UPDATE stage_sessions
|
||||
SET ended_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND ended_at IS NULL
|
||||
`, current.ID)
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, fmt.Sprintf("end stage: %v", err))
|
||||
}
|
||||
|
||||
a.events.Broadcast()
|
||||
|
||||
state, err := a.readState(true)
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return c.JSON(http.StatusOK, state)
|
||||
}
|
||||
|
||||
func (a *App) handleGetStageHistory(c echo.Context) error {
|
||||
items, err := a.readStageHistory()
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return c.JSON(http.StatusOK, map[string]any{
|
||||
"items": items,
|
||||
})
|
||||
}
|
||||
|
||||
func (a *App) handleCreatePlayer(c echo.Context) error {
|
||||
var req PlayerCreateRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
@@ -295,6 +373,77 @@ func (a *App) handleAutoGroupPlayers(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, state)
|
||||
}
|
||||
|
||||
func (a *App) handleUpdatePositionBoard(c echo.Context) error {
|
||||
board, ok := normalizePositionBoard(c.Param("board"))
|
||||
if !ok {
|
||||
return writeError(c, http.StatusBadRequest, "invalid position board")
|
||||
}
|
||||
|
||||
var req PositionBoardUpdateRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return writeError(c, http.StatusBadRequest, "invalid request body")
|
||||
}
|
||||
|
||||
seen := map[int]bool{}
|
||||
for _, slot := range req.Slots {
|
||||
if slot.PlayerID <= 0 {
|
||||
return writeError(c, http.StatusBadRequest, "invalid player id")
|
||||
}
|
||||
if seen[slot.PlayerID] {
|
||||
return writeError(c, http.StatusBadRequest, "duplicate player id in slots")
|
||||
}
|
||||
seen[slot.PlayerID] = true
|
||||
if strings.TrimSpace(slot.GroupKey) == "" {
|
||||
return writeError(c, http.StatusBadRequest, "groupKey is required")
|
||||
}
|
||||
if slot.Position <= 0 {
|
||||
return writeError(c, http.StatusBadRequest, "position must be positive")
|
||||
}
|
||||
}
|
||||
|
||||
tx, err := a.db.Begin()
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, "failed to start position transaction")
|
||||
}
|
||||
defer tx.Rollback()
|
||||
|
||||
if _, err := tx.Exec(`DELETE FROM player_positions WHERE board = ?`, board); err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, fmt.Sprintf("clear board positions: %v", err))
|
||||
}
|
||||
|
||||
for _, slot := range req.Slots {
|
||||
groupKey := normalizePositionGroupKey(board, slot.GroupKey, "")
|
||||
if _, err := tx.Exec(`
|
||||
INSERT INTO player_positions(board, player_id, group_key, position, updated_at)
|
||||
VALUES(?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
`, board, slot.PlayerID, groupKey, slot.Position); err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, fmt.Sprintf("save board position: %v", err))
|
||||
}
|
||||
|
||||
if board == positionBoardPreliminary {
|
||||
groupCode := strings.TrimSpace(groupKey)
|
||||
if strings.EqualFold(groupCode, positionBoardUnassigned) {
|
||||
groupCode = ""
|
||||
}
|
||||
if _, err := tx.Exec(`UPDATE players SET group_code = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?`, groupCode, slot.PlayerID); err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, fmt.Sprintf("update player group from board: %v", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, "failed to commit positions")
|
||||
}
|
||||
|
||||
a.events.Broadcast()
|
||||
|
||||
state, err := a.readState(true)
|
||||
if err != nil {
|
||||
return writeError(c, http.StatusInternalServerError, err.Error())
|
||||
}
|
||||
return c.JSON(http.StatusOK, state)
|
||||
}
|
||||
|
||||
func (a *App) handleUpdateScore(c echo.Context) error {
|
||||
stage, err := validateStage(c.Param("stage"))
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user