Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions components/competition/MatchScheduleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@ export default function MatchScheduleCard(props: {
id={`//match${index}`}
className="md:relative md:-translate-y-80"
/>
<div className="items-middle flex flex-row items-center pt-4">
<div className="items-middle flex flex-row justify-center items-center pt-4 relative">
<h1 className="text-2xl font-bold">
Match {match.number}
</h1>
{isManager && (
<button
className="btn btn-link"
className="btn btn-link absolute right-4"
onClick={() => openEditMatchModal(match)}
>
Edit
Expand Down
3 changes: 3 additions & 0 deletions lib/Enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ export namespace DecodeEnums {
TwoBotPark = "Two Bot Park",
}

// This defines scouting option enums, grouped by game using namespaces. Namespaces
// like DecodeEnums group related enums so they can be referenced clearly.

export enum AutoStatus {
NoAuto = "No Auto",
MovePastStart = "Move Past Start",
Expand Down
10 changes: 10 additions & 0 deletions lib/Layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import {
ReefscapeEnums,
RebuiltEnums,
DecodeEnums,

// This imports DecodeEnums from the Enums module. It's used in the keyToType function to
// identify string fields that should render as enum dropdowns for Decode game properties.

} from "./Enums";
import { PitReportData, QuantData, Pitreport, Report, League } from "./Types";

Expand Down Expand Up @@ -228,6 +232,9 @@ export function keyToType(
DecodeEnums.EndgameParkStatus,
];

// These are enum options in the lookup array. The function checks if a form field's
// value matches any of these enums to determine if it should render as a dropdown.

if (key === "Defense") return Defense;
if (key === "swerveLevel") return SwerveLevel;

Expand All @@ -249,6 +256,9 @@ export function keyToType(
if (key == "EndgameParkStatusDecode") return DecodeEnums.EndgameParkStatus;
if (key == "AutoStatus") return DecodeEnums.AutoStatus;

// Special case mappings. If the field name is exactly "EndgameParkStatusDecode" or "AutoStatus",
// return the corresponding Decode enum directly instead of searching through the array.

for (const e of enums) {
if (Object.values(e).includes(exampleData[key])) return e;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/client/GameId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ export enum GameId {
Decode = "Decode",
}

// Creates a named set of constant values (game identifiers) and
// makes that list available for other files to import and use.

export const defaultGameId = GameId.Rebuilt;
53 changes: 53 additions & 0 deletions lib/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { Dot } from "@/components/stats/Heatmap";
import {
CenterStageEnums,
DecodeEnums,

// DecodeEnums provides the allowed Decode game options, such as parking status.
// getAvgPoints uses it to convert each parking status into the correct endgame points.

Defense,
FrcDrivetrain,
IntakeTypes,
Expand Down Expand Up @@ -1911,6 +1915,10 @@ export namespace Rebuilt {
EngameDefenseStatus: Defense = Defense.None;
LevelClimbed: RebuiltEnums.LevelClimbed = RebuiltEnums.LevelClimbed.No;
}

// Tracks fuel scored in 1/5/10 point categories during Auto and
// Teleop. It also records climb level and defense type as enums.

export class PitData extends PitReportData {
CanDriveOverBump: boolean = false;
CanDriveUnderTrench: boolean = false;
Expand All @@ -1923,6 +1931,13 @@ export namespace Rebuilt {
ClimbingCapabilities: RebuiltEnums.ClimbingCapabilities =
RebuiltEnums.ClimbingCapabilities.No;
}

// Pre-match Data: Robot abilities (bump/trench crossing, de-climb).
// Stores climbing capability level and hopper volume.

// Pit questions group into "Capabilities" and "Auto"
// sections. This is collected before matches for scouting.

const pitReportLayout: FormLayoutProps<PitData> = {
Capabilities: [
{ key: "CanDriveOverBump", label: "Can Drive Over Bump?" },
Expand All @@ -1933,6 +1948,10 @@ export namespace Rebuilt {
],
Auto: [{ key: "AutoAbilities", label: "Auto Capabilities?" }],
};

// Match entry organized into "Auto", "Teleop", and "Post Match"
// phases. Block layout [[],[]] displays fields side-by-side.

const quantitativeReportLayout: FormLayoutProps<QuantitativeData> = {
Auto: [
{ key: "AutoClimbedLevelOne", label: "Climbed Level One (Auto)" },
Expand Down Expand Up @@ -1982,6 +2001,9 @@ export namespace Rebuilt {
"Post Match": ["LevelClimbed", "EngameDefenseStatus"],
};

// Calculates auto/teleop fuel points with multipliers (1x, 5x,
// 10x). Min/max stats track alliance performance range.

const statsLayout: StatsLayout<PitData, QuantitativeData> = {
sections: {
Auto: [
Expand Down Expand Up @@ -2132,6 +2154,8 @@ export namespace Rebuilt {
},
};

// Creates visual tags for robot capabilities (bump drive, trench, climb levels).

function getBadges(
pitReport: Pitreport<PitData> | undefined,
quantitativeReports: Report<QuantitativeData>[] | undefined,
Expand Down Expand Up @@ -2165,6 +2189,9 @@ export namespace Rebuilt {
return badges;
}

// Loops through reports calculating endgame points by climb level.
// Multiplies fuel counts by point values, divides by number of reports.

function getAvgPoints(reports: Report<QuantitativeData>[] | undefined) {
if (!reports) return 0;

Expand All @@ -2191,6 +2218,10 @@ export namespace Rebuilt {
}
return totalPoints / Math.max(reports.length, 1);
}

// Bundles all Rebuilt configuration: data classes, forms, stats,
// and functions. Registered in games registry for app access.

export const game = new Game(
"Rebuilt",
2026,
Expand All @@ -2210,6 +2241,10 @@ export namespace Rebuilt {
}

export namespace Decode {

// Groups all configuration and logic for the FTC Decode game, including data classes, form layouts,
// statistics, badges, and scoring. export lets other files access it, such as Decode.game.

export class QuantitativeData extends QuantData {
AutoMovedPastStartingLine: boolean = false;

Expand All @@ -2227,6 +2262,9 @@ export namespace Decode {
EndgameDefense: Defense = Defense.None;
}

// It stores the robot's Decode endgame parking status, defaulting to No, and its
// defense level, defaulting to None. getAvgPoints checks EndgameParkStatus.

export class PitData extends PitReportData {
CanScoreClassifier: boolean = false;
CanScoreDepot: boolean = false;
Expand All @@ -2238,6 +2276,9 @@ export namespace Decode {
AutoAbilities: DecodeEnums.AutoStatus = DecodeEnums.AutoStatus.NoAuto;
}

// PitData stores information collected before matches about a Decode robot's abilities and autonomous
// performance. Boolean fields default to false, numbers to 0, and AutoAbilities to NoAuto.

const pitReportLayout: FormLayoutProps<PitData> = {
Capabilities: [
{ key: "CanScoreClassifier", label: "Can Score Classifier?" },
Expand Down Expand Up @@ -2293,6 +2334,9 @@ export namespace Decode {
Endgame: ["Defense", "EndgameParkStatusDecode"],
};

// This adds Defense and EndgameParkStatusDecode fields to the Decode post-match form under the
// Endgame section. The form uses those keys to collect each robot's defense and parking status.

const statsLayout: StatsLayout<PitData, QuantitativeData> = {
sections: {
Auto: [
Expand Down Expand Up @@ -2548,6 +2592,9 @@ export namespace Decode {
break;
}

// This loops through each report and adds endgame points based on the
// robot's parking status: No adds 0, Partial 5, Full 10, and TwoBotPark 20.

totalPoints +=
(report.AutoArtifactsClassified + report.TeleopArtifactsClassified) *
ArtifactPoints;
Expand Down Expand Up @@ -2581,6 +2628,9 @@ export namespace Decode {
);
}

// This creates the Decode game configuration with its data classes, forms, stats, image, badge generator,
// and scoring function. It exports the configured game as Decode.game so the application can use it.

export const games: { [id in GameId]: Game<any, any> } = Object.freeze({
[GameId.Rebuilt]: Rebuilt.game,
[GameId.Reefscape]: Reefscape.game,
Expand All @@ -2589,3 +2639,6 @@ export const games: { [id in GameId]: Game<any, any> } = Object.freeze({
[GameId.CenterStage]: CenterStage.game,
[GameId.Decode]: Decode.game,
});

// This creates a read-only lookup object connecting each GameId to its configured
// game. Object.freeze prevents the registry from being changed accidentally.
Loading
Loading