forked from eros/curltastic
171 lines
4.2 KiB
TypeScript
171 lines
4.2 KiB
TypeScript
export const TICK_RATE_HZ = 120
|
|
export const SAMPLE_RATE_HZ = 40
|
|
export const STONES_PER_TEAM = 8
|
|
export const ENDS = 10
|
|
export const SHEET_WIDTH = 5.0
|
|
export const SHEET_LENGTH = 45.0
|
|
export const FEET_TO_METERS = 0.3048
|
|
export const HOUSE_CENTER = { x: 0, y: 38.5 }
|
|
export const HOUSE_RADIUS = 6 * FEET_TO_METERS
|
|
export const BUTTON_RADIUS = 0.5 * FEET_TO_METERS
|
|
export const FOUR_FT_RADIUS = 2 * FEET_TO_METERS
|
|
export const EIGHT_FT_RADIUS = 4 * FEET_TO_METERS
|
|
export const TWELVE_FT_RADIUS = 6 * FEET_TO_METERS
|
|
export const HOG_LINE_Y = 21.0
|
|
/** Backline on outer house ring (tee + 6 ft). */
|
|
export const BACK_LINE_Y = HOUSE_CENTER.y + HOUSE_RADIUS
|
|
export const HACK_Y = 2.0
|
|
export const STONE_RADIUS = 0.15
|
|
|
|
/** Feet relative to tee for weights 1..10 (front is negative). */
|
|
export const WEIGHT_STOP_OFFSET_FT = [-11, -9, -7, -5, -3, -1, 0, 1, 3, 5] as const
|
|
export const HACK_STOP_OFFSET_FT = 12
|
|
|
|
/** Calibrated m/s for weights 1..10 (open-ice stop vs tee offsets). */
|
|
export const WEIGHT_SPEEDS = [
|
|
2.2573, 2.2783, 2.2992, 2.3199, 2.3404, 2.3608, 2.3709, 2.3810, 2.4012, 2.4211,
|
|
] as const
|
|
export const HACK_SPEED = 2.4899
|
|
/** Takeouts: open-ice stop at hack+N feet (N = 6,12,18,24). */
|
|
export const BOARD_SPEED = 2.5492
|
|
export const CONTROL_SPEED = 2.6408
|
|
export const NORMAL_SPEED = 2.7448
|
|
export const PEEL_SPEED = 2.8499
|
|
export const BOARD_STOP_OFFSET_FT = HACK_STOP_OFFSET_FT + 6
|
|
export const CONTROL_STOP_OFFSET_FT = HACK_STOP_OFFSET_FT + 15
|
|
export const NORMAL_STOP_OFFSET_FT = HACK_STOP_OFFSET_FT + 25
|
|
export const PEEL_STOP_OFFSET_FT = HACK_STOP_OFFSET_FT + 35
|
|
/** Tee-line weight (category 7). */
|
|
export const DRAW_VELOCITY = WEIGHT_SPEEDS[6]
|
|
export const MIN_SPEED = WEIGHT_SPEEDS[0]
|
|
export const MAX_SPEED = WEIGHT_SPEEDS[9]
|
|
|
|
export type SpeedLabel =
|
|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
|
|
| 'hack' | 'board' | 'control' | 'normal' | 'peel'
|
|
|
|
export const SPEED_TABLE: Record<SpeedLabel, number> = {
|
|
1: WEIGHT_SPEEDS[0],
|
|
2: WEIGHT_SPEEDS[1],
|
|
3: WEIGHT_SPEEDS[2],
|
|
4: WEIGHT_SPEEDS[3],
|
|
5: WEIGHT_SPEEDS[4],
|
|
6: WEIGHT_SPEEDS[5],
|
|
7: WEIGHT_SPEEDS[6],
|
|
8: WEIGHT_SPEEDS[7],
|
|
9: WEIGHT_SPEEDS[8],
|
|
10: WEIGHT_SPEEDS[9],
|
|
hack: HACK_SPEED,
|
|
board: BOARD_SPEED,
|
|
control: CONTROL_SPEED,
|
|
normal: NORMAL_SPEED,
|
|
peel: PEEL_SPEED,
|
|
}
|
|
|
|
export type Team = 'team1' | 'team2'
|
|
export type Phase = 'waiting' | 'playing' | 'simulating' | 'scoring' | 'end_complete' | 'game_complete'
|
|
|
|
export interface StoneId {
|
|
team: Team
|
|
n: number
|
|
}
|
|
|
|
export interface StoneState {
|
|
id: StoneId
|
|
team: Team
|
|
x: number
|
|
y: number
|
|
rotation: number
|
|
}
|
|
|
|
export interface DrawableStone {
|
|
x: number
|
|
y: number
|
|
rotation: number
|
|
team: Team
|
|
}
|
|
|
|
export interface EndScore {
|
|
end: number
|
|
hammer: Team
|
|
team1: number
|
|
team2: number
|
|
}
|
|
|
|
export interface ClientThrowMessage {
|
|
type: 'throw'
|
|
team: Team
|
|
broom_x: number
|
|
broom_y: number
|
|
velocity: number
|
|
curl: number
|
|
}
|
|
|
|
export interface ServerJoinedMessage {
|
|
type: 'joined'
|
|
room: string
|
|
}
|
|
|
|
export interface ServerWaitingMessage {
|
|
type: 'waiting'
|
|
message: string
|
|
}
|
|
|
|
export interface ServerGameStateMessage {
|
|
type: 'game_state'
|
|
end: number
|
|
scores: number[]
|
|
hammer: Team
|
|
turn_team: Team
|
|
scoreboard: EndScore[]
|
|
stones_remaining: number[]
|
|
stones: StoneState[]
|
|
phase: Phase
|
|
}
|
|
|
|
/** Path samples are (x, y, theta). Time is sample_index / SAMPLE_RATE_HZ. */
|
|
export interface StonePath {
|
|
stone_id: StoneId
|
|
rotation: number
|
|
team: Team
|
|
trajectory: [number, number, number][]
|
|
}
|
|
|
|
export interface ServerTrajectoriesMessage {
|
|
type: 'trajectories'
|
|
stones: StonePath[]
|
|
}
|
|
|
|
export interface ServerGameOverMessage {
|
|
type: 'game_over'
|
|
scores: number[]
|
|
winner: Team | null
|
|
}
|
|
|
|
export interface ServerErrorMessage {
|
|
type: 'error'
|
|
message: string
|
|
}
|
|
|
|
export type ServerMessageTyped =
|
|
| ServerJoinedMessage
|
|
| ServerWaitingMessage
|
|
| ServerGameStateMessage
|
|
| ServerTrajectoriesMessage
|
|
| ServerGameOverMessage
|
|
| ServerErrorMessage
|
|
|
|
export type ServerMessage = ServerMessageTyped
|
|
|
|
export function isTeam(value: unknown): value is Team {
|
|
return value === 'team1' || value === 'team2'
|
|
}
|
|
|
|
export function stoneIdKey(id: StoneId): string {
|
|
return `${id.team}:${id.n}`
|
|
}
|
|
|
|
export function stoneIdsEqual(a: StoneId, b: StoneId): boolean {
|
|
return a.team === b.team && a.n === b.n
|
|
}
|