teecup/frontend/lib/ny-runde/formats.ts

157 lines
4.8 KiB
TypeScript
Raw Permalink Normal View History

import type { FormatId } from "./types"
export interface FormatDef {
id: FormatId
label: string
description: string
}
export const FORMATS: FormatDef[] = [
{ id: "slagspill", label: "Slagspill", description: "Vanlig individuell runde." },
{
id: "stableford",
label: "Stableford",
description: "Poeng per hull i stedet for slag kan plukke opp ved 0 poeng.",
},
{ id: "match", label: "Match", description: "To sider, hull mot hull." },
{ id: "skins", label: "Skins", description: "Hvert hull er en egen premie minst 3 spillere." },
{ id: "fourball", label: "Fourball", description: "To mot to, beste ball per side." },
{ id: "foursome", label: "Foursome", description: "To mot to, én delt ball, annenhver slår." },
{
id: "greensome",
label: "Greensome",
description: "To mot to, begge slår ut, velger så én ball.",
},
{
id: "scramble2",
label: "Scramble (2)",
description: "To mot to, velger beste slag hver gang.",
},
{
id: "scramble4",
label: "Scramble (4)",
description: "Fire mot fire, velger beste slag hver gang.",
},
{
id: "chapman",
label: "Chapman",
description: "To mot to, bytter utslag, velger så én ball som foursome fra andre slag.",
},
{
id: "copenhagen",
label: "Københavner",
description: "Nøyaktig 3 spillere 6 poeng deles per hull etter rangering.",
},
{
id: "bbb",
label: "Bingo Bango Bongo",
description: "Poeng for først på green, nærmest hull, først i hull.",
},
{
id: "flag",
label: "Flaggturnering",
description: "Fast slagbudsjett (par + HCP) flagget plantes der slagene tar slutt.",
},
{
id: "shamble",
label: "Shamble",
description: "2-4 spillere, alle slår ut, velger beste spiller så egen ball inn.",
},
{
id: "moneyball",
label: "Money Ball",
description: "Fire spillere, én roterer som 'money ball' per hull.",
},
{
id: "highlowhigh",
label: "High-low-high",
description: "To lag à to høy mot høy, lav mot lav, per hull.",
},
{
id: "scramblevssolo",
label: "Scramble mot enkeltspiller",
description:
"Et lag med delt ball (minst 2 spillere) mot én enkeltspiller — nettoscore avgjør.",
},
{
id: "scramblevssolomatch",
label: "Scramble mot enkeltspiller (matchspill)",
description: "Samme oppsett som over, men avgjort hull for hull i stedet for netto totalsum.",
},
]
export const FORMAT_MAP: Record<FormatId, FormatDef> = FORMATS.reduce(
(acc, f) => {
acc[f.id] = f
return acc
},
{} as Record<FormatId, FormatDef>,
)
/** Two-sided team formats (drive the standard step-4 A/B layout). */
export const TWO_SIDED: FormatId[] = [
"match",
"fourball",
"foursome",
"greensome",
"scramble2",
"scramble4",
"chapman",
"highlowhigh",
]
export const SCRAMBLE_VS_SOLO: FormatId[] = ["scramblevssolo", "scramblevssolomatch"]
// Samme sett som app/handicap.py sin SIDE_IS_UNIT (+ chapman-aliaset) --
// avgjør om HCP-prosenten bygges som "combined" (delt enhet) eller
// "per_player" i allowance_override.strategy.
export const SIDE_IS_UNIT_FORMAT: FormatId[] = ["foursome", "greensome", "scramble2", "scramble4", "chapman"]
// "Bruk course handicap-justering" er skjult for disse to (ingen reell
// nytteverdi), men holdes funksjonelt PÅ uansett -- se wizard-context.tsx.
export const ORDINARY_FORMATS: FormatId[] = ["slagspill", "stableford"]
export function isTwoSided(f: FormatId): boolean {
return TWO_SIDED.includes(f)
}
export function isScrambleVsSolo(f: FormatId): boolean {
return SCRAMBLE_VS_SOLO.includes(f)
}
/** Whether the Teams & order step (4) is shown for a given format. */
export function showsTeamStep(f: FormatId): boolean {
return isTwoSided(f) || f === "moneyball" || isScrambleVsSolo(f)
}
// Wizardens FormatId -> ekte round.play_format-verdi (RoundCreate).
export const FORMAT_TO_API: Record<FormatId, string> = {
slagspill: "stroke",
stableford: "stableford",
match: "match",
skins: "skins",
fourball: "fourball",
foursome: "foursome",
greensome: "greensome",
scramble2: "scramble_2",
scramble4: "scramble_4",
chapman: "chapman",
copenhagen: "copenhagen",
bbb: "bbb",
flag: "flag",
shamble: "shamble",
moneyball: "money_ball",
highlowhigh: "high_low_high",
scramblevssolo: "scramble_solo",
scramblevssolomatch: "scramble_solo_match",
}
export const API_TO_FORMAT: Record<string, FormatId> = Object.fromEntries(
Object.entries(FORMAT_TO_API).map(([k, v]) => [v, k as FormatId]),
) as Record<string, FormatId>
export function apiStatLevel(s: StatLevelLike): "strokes_only" | "strokes_and_putts" | "full" {
return s === "score" ? "strokes_only" : s === "score_putts" ? "strokes_and_putts" : "full"
}
type StatLevelLike = "score" | "score_putts" | "full"