Skip to content
Community engagement

city_battle_votes

Cross-city battle votes — the tier above per-city voting. Each row is one vote in a head-to-head between two cities' champion videos (the current month's highest-ELO approved video per city). Ranks CITIES, not videos, into the "Top dance cities" leaderboard. videoIds are stored for provenance only (plain uuid, no FK — champions rotate as ELO shifts, and this must survive video deletion).

Columns

ColumnTypeNullDefaultKeys
iduuid nogen_random_uuid()
PK
competition_monthtext no—
winner_city_slugtext no—
loser_city_slugtext no—
winner_video_iduuid yes—
loser_video_iduuid yes—
voter_session_idtext no—
voter_dancer_iduuid yes—
created_attimestamp yesnow()

Value lists come from .$type<'a' | 'b'>() in the schema — enforced in TypeScript only, not by the database.

Keys, constraints & indexes

Unique

None besides the primary key.

Indexes

  • (voter_session_id, competition_month)
    city_battle_votes_session_idx
  • (competition_month)
    city_battle_votes_month_idx

Foreign keys

  • voter_dancer_id → dancers.id
    on delete no action

Used by

Code that reads or writes this table, found by static analysis of the tRPC routers and API handlers (including helpers they call).

Relations

Rendering diagram…

Diagram source
erDiagram
  city_battle_votes {
    uuid id PK
    uuid voter_dancer_id FK
  }
  dancers {
    uuid id PK
    text email UK
    text neon_auth_id UK
    text username UK
  }
  dancers |o--o{ city_battle_votes : "voter_dancer_id"

Defined at server/database/schema.ts:211 as cityBattleVotes.