tss site blah

This commit is contained in:
FURRO404
2026-06-20 21:58:27 -07:00
parent 1eb0f1ffc8
commit 45142f280a
5 changed files with 83 additions and 16 deletions
+4
View File
@@ -6,6 +6,10 @@ It reads two SQLite databases:
- `TSS_BATTLES_DB` for `tss_battles.db` (matches, players, and the `match_logs` table)
- `TSS_TEAMS_DB` for `tss_teams.db`
- `TSS_TOURNAMENTS_DB` for `tss_tournaments.db`
If any of these are unset, the backend first looks under `STORAGE_VOL_PATH`
before falling back to the current working directory.
- `BACKEND_HOST` bind host, default `127.0.0.1`
- `BACKEND_ALLOWED_ORIGINS` comma-separated browser origins allowed by CORS
+7 -3
View File
@@ -2299,9 +2299,13 @@ fn lookup_vehicle_icon(icons: &HashMap<String, String>, cdk: &str) -> String {
}
fn resolve_db_path(env_key: &str, default_file: &str) -> PathBuf {
let raw = env::var(env_key).unwrap_or_else(|_| default_file.to_string());
let expanded = expand_home(&raw);
let path = PathBuf::from(expanded);
let path = if let Ok(raw) = env::var(env_key) {
PathBuf::from(expand_home(&raw))
} else if let Ok(storage) = env::var("STORAGE_VOL_PATH") {
PathBuf::from(expand_home(&storage)).join(default_file)
} else {
PathBuf::from(default_file)
};
if path.is_absolute() {
path
} else {
+1
View File
@@ -10,6 +10,7 @@ BACKEND_HOST=127.0.0.1
BACKEND_ALLOWED_ORIGINS=https://example.com
TSS_BATTLES_DB=./tss_battles.db
TSS_TEAMS_DB=./tss_teams.db
TSS_TOURNAMENTS_DB=./tss_tournaments.db
# Vehicle name translation + icon caches (shared STORAGE/CACHE, built by the bots).
# The backend loads these at startup to translate vehicle_internal (cdk) -> name
+30 -13
View File
@@ -3714,10 +3714,11 @@ function tournamentStatusLabel(status) {
return raw.charAt(0).toUpperCase() + raw.slice(1)
}
function sideFromMatch(match) {
function sideFromMatch(match, context = {}) {
const bracket = String(match?.type_bracket || '').toLowerCase()
if (context.hasLoserSide && bracket.includes('semifinal')) return 'loser'
const side = String(match?.side || '').toLowerCase()
if (side) return side
const bracket = String(match?.type_bracket || '').toLowerCase()
if (bracket.includes('swiss')) return 'swiss'
if (bracket.includes('group')) return 'group'
if (bracket.includes('looser') || bracket.includes('loser')) return 'loser'
@@ -3813,8 +3814,15 @@ function TournamentsPage({ navigate }) {
function groupMatchesBySide(matches) {
const bySide = new Map()
const context = {
hasLoserSide: matches.some((match) => {
const bracket = String(match?.type_bracket || '').toLowerCase()
const side = String(match?.side || '').toLowerCase()
return bracket.includes('looser') || bracket.includes('loser') || side === 'loser'
}),
}
matches.forEach((match) => {
const side = sideFromMatch(match)
const side = sideFromMatch(match, context)
if (!bySide.has(side)) bySide.set(side, [])
bySide.get(side).push(match)
})
@@ -3862,7 +3870,7 @@ function TournamentMatchCard({ match, navigate }) {
const bWon = winner && teamB && winner === teamB.toLowerCase()
const battles = Array.isArray(match.battles) ? match.battles : []
const teamRow = (name, score, won) => (
const teamRow = (name, score, won, emptyLabel = 'TBD') => (
<div className="flex items-center justify-between gap-2">
{name ? (
<button
@@ -3876,16 +3884,17 @@ function TournamentMatchCard({ match, navigate }) {
{name}
</button>
) : (
<span className="min-w-0 truncate font-semibold text-text-muted">TBD</span>
<span className="min-w-0 truncate font-semibold text-text-muted">{emptyLabel}</span>
)}
<span className={`shrink-0 tabular-nums ${won ? 'text-win' : 'text-text-soft'}`}>{formatNumber(score)}</span>
</div>
)
const emptyLabel = match.status === 'bye' ? 'BYE' : 'TBD'
return (
<div className="rounded-md border border-border bg-bg p-2.5 text-sm shadow-sm">
{teamRow(teamA, match.score_a, aWon)}
<div className="mt-1">{teamRow(teamB, match.score_b, bWon)}</div>
{teamRow(teamA, match.score_a, aWon, emptyLabel)}
<div className="mt-1">{teamRow(teamB, match.score_b, bWon, emptyLabel)}</div>
<div className="mt-2 flex items-center justify-between gap-2 text-[10px] font-semibold uppercase tracking-wide text-text-muted">
<span>{tournamentStatusLabel(match.status)}</span>
{match.position !== null && match.position !== undefined ? <span>Slot {Number(match.position) + 1}</span> : null}
@@ -3923,19 +3932,27 @@ function TournamentBracketSide({ side, navigate }) {
<div>
<h3 className="mb-3 text-sm font-semibold uppercase tracking-wide text-fury-cyan">{side.label}</h3>
<div className="overflow-x-auto pb-2">
<div className="flex gap-4">
<div className="tournament-bracket-grid">
{rounds.map((round, roundIndex) => (
<div className="flex min-w-[190px] flex-col gap-3" key={round.round}>
<div className="tournament-round-column" key={round.round}>
<p className="text-xs font-semibold uppercase tracking-wide text-text-muted">
{roundLabel(side.raw, round.round, roundIndex, rounds.length)}
</p>
<div className="flex flex-1 flex-col justify-around gap-3">
{round.matches.map((match) => (
<TournamentMatchCard
<div
className={[
'tournament-match-node',
roundIndex > 0 ? 'tournament-match-node-left' : '',
roundIndex < rounds.length - 1 ? 'tournament-match-node-right' : '',
].filter(Boolean).join(' ')}
key={`${match.type_bracket}-${match.match_id}`}
match={match}
navigate={navigate}
/>
>
<TournamentMatchCard
match={match}
navigate={navigate}
/>
</div>
))}
</div>
</div>
+41
View File
@@ -831,6 +831,47 @@ h3 {
font-size: 0.62rem;
}
.tournament-bracket-grid {
display: flex;
gap: 2.6rem;
min-width: max-content;
}
.tournament-round-column {
position: relative;
display: flex;
width: 190px;
min-width: 190px;
flex-direction: column;
gap: 0.75rem;
}
.tournament-match-node {
position: relative;
z-index: 1;
}
.tournament-match-node::before,
.tournament-match-node::after {
position: absolute;
top: 50%;
z-index: 0;
display: block;
height: 1px;
width: 1.3rem;
background: color-mix(in srgb, var(--color-border) 78%, var(--color-fury-violet));
content: "";
pointer-events: none;
}
.tournament-match-node-left::before {
right: calc(100% + 0.05rem);
}
.tournament-match-node-right::after {
left: calc(100% + 0.05rem);
}
@keyframes scrollPulse {
0% {
transform: translateY(-100%);