157 lines
4.8 KiB
TypeScript
157 lines
4.8 KiB
TypeScript
|
|
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"
|