Skip to content

Commit 749e3e0

Browse files
docker rewrite patch
1 parent da20cdb commit 749e3e0

File tree

2 files changed

+161
-50
lines changed

2 files changed

+161
-50
lines changed

client/src/apps/match/MatchApp.tsx

Lines changed: 160 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,82 @@ const teleTowerOptions: TeleTowerResult[] = ['None', 'Failed', 'level1', 'level2
133133
const driverQualityOptions: DriverQuality[] = ['great', 'good', 'ok', 'rough'];
134134
const breakdownOptions: BreakdownType[] = ['None', 'stuck', 'tipped', 'comms', 'mechanism', 'other'];
135135

136-
const foulLabels: Array<{ key: keyof MatchData['fouls']; label: string }> = [
137-
{ key: 'pinning', label: 'Pinning' },
138-
{ key: 'towerContactInEndgame', label: 'Tower Contact (Endgame)' },
139-
{ key: 'outOfZoneShooting', label: 'Out-of-Zone Shooting' },
140-
{ key: 'ejectedFuel', label: 'Ejected Fuel' },
141-
{ key: 'other', label: 'Other' },
136+
const foulLabels: Array<{
137+
key: keyof MatchData['fouls'];
138+
label: string;
139+
definition: string;
140+
example: string;
141+
}> = [
142+
{
143+
key: 'pinning',
144+
label: 'Pinning',
145+
definition:
146+
'Illegal restriction of an opponent robot’s movement by trapping it against a field element or another robot beyond the allowed time limit.',
147+
example: 'Holding a robot against the wall for more than 5 seconds.',
148+
},
149+
{
150+
key: 'towerContactInEndgame',
151+
label: 'Tower Contact (Endgame)',
152+
definition:
153+
'Contacting or interfering with an opponent’s tower or climbing mechanism during the protected endgame period when such interactions are prohibited.',
154+
example: 'Hitting a robot while it is climbing in endgame.',
155+
},
156+
{
157+
key: 'outOfZoneShooting',
158+
label: 'Out-of-Zone Shooting',
159+
definition:
160+
'Launching game pieces from a location on the field where scoring actions are not permitted by game rules.',
161+
example: 'Shooting while outside the designated scoring zone.',
162+
},
163+
{
164+
key: 'ejectedFuel',
165+
label: 'Ejected Fuel',
166+
definition:
167+
'Intentionally or negligently expelling game pieces in a way that violates control, safety, or scoring rules.',
168+
example: 'Dumping balls across the field instead of scoring.',
169+
},
170+
{
171+
key: 'other',
172+
label: 'Other',
173+
definition:
174+
'Any rule violation not explicitly categorized that results in a referee-assessed foul based on game rules.',
175+
example: 'Entering a protected zone illegally.',
176+
},
142177
];
143178

144-
const breakLabels: Array<{ key: keyof MatchData['breaks']; label: string }> = [
145-
{ key: 'mechanism', label: 'Mechanism' },
146-
{ key: 'battery', label: 'Battery' },
147-
{ key: 'comms', label: 'Comms' },
148-
{ key: 'bumper', label: 'Bumper' },
179+
const breakLabels: Array<{
180+
key: keyof MatchData['breaks'];
181+
label: string;
182+
definition: string;
183+
example: string;
184+
}> = [
185+
{
186+
key: 'mechanism',
187+
label: 'Mechanism',
188+
definition: 'Failure of a robot’s mechanical subsystem that impairs functionality.',
189+
example: 'Intake arm breaks and cannot collect game pieces.',
190+
},
191+
{
192+
key: 'battery',
193+
label: 'Battery',
194+
definition:
195+
'Power loss or electrical failure due to battery issues such as depletion, disconnection, or voltage drop.',
196+
example: 'Robot shuts off mid-match.',
197+
},
198+
{
199+
key: 'comms',
200+
label: 'Comms',
201+
definition:
202+
'Loss or degradation of communication between the robot and driver station, preventing control.',
203+
example: 'Robot stops responding due to radio disconnect.',
204+
},
205+
{
206+
key: 'bumper',
207+
label: 'Bumper',
208+
definition:
209+
'Damage, detachment, or illegal configuration of bumpers that affects compliance or robot interaction.',
210+
example: 'Bumper falls off during defense.',
211+
},
149212
];
150213

151214
const autoFieldImageByAlliance: Record<AllianceColor, string> = {
@@ -349,6 +412,8 @@ function MatchApp() {
349412
const [defenseReceived, setDefenseReceived] = useState(false);
350413
const [fouls, setFouls] = useState<MatchData['fouls']>(makeEmptyFouls());
351414
const [breaks, setBreaks] = useState<MatchData['breaks']>(makeEmptyBreaks());
415+
const [activeFoulInfo, setActiveFoulInfo] = useState<keyof MatchData['fouls'] | null>(null);
416+
const [activeBreakInfo, setActiveBreakInfo] = useState<keyof MatchData['breaks'] | null>(null);
352417
const [freeText, setFreeText] = useState('');
353418
const [actionTicks, setActionTicks] = useState<ActionTick[]>([]);
354419
const nextTickIdRef = useRef(1);
@@ -1478,25 +1543,48 @@ function MatchApp() {
14781543
{foulLabels.map(entry => (
14791544
<div
14801545
key={entry.key}
1481-
className='flex items-center gap-2 rounded-lg border border-white/10 bg-[#121a28] px-2 py-2'>
1482-
<HoldButton
1483-
onHold={() => adjustFoul(entry.key, -1)}
1484-
repeatDelay={120}
1485-
repeatInterval={90}
1486-
className='rounded bg-[#c44e4e] px-2 py-1 text-xs font-semibold text-white'>
1487-
-
1488-
</HoldButton>
1489-
<span className='flex-1 text-xs text-gray-200'>{entry.label}</span>
1490-
<span className='w-8 text-right text-sm font-semibold tabular-nums text-white'>
1491-
{fouls[entry.key]}
1492-
</span>
1493-
<HoldButton
1494-
onHold={() => adjustFoul(entry.key, 1)}
1495-
repeatDelay={120}
1496-
repeatInterval={90}
1497-
className='rounded bg-[#48c55c] px-2 py-1 text-xs font-semibold text-black'>
1498-
+
1499-
</HoldButton>
1546+
className='rounded-lg border border-white/10 bg-[#121a28]'>
1547+
<div className='flex items-center gap-2 px-2 py-2'>
1548+
<HoldButton
1549+
onHold={() => adjustFoul(entry.key, -1)}
1550+
repeatDelay={120}
1551+
repeatInterval={90}
1552+
className='rounded bg-[#c44e4e] px-2 py-1 text-xs font-semibold text-white'>
1553+
-
1554+
</HoldButton>
1555+
<span className='flex-1 text-xs text-gray-200'>{entry.label}</span>
1556+
<button
1557+
type='button'
1558+
onClick={() =>
1559+
setActiveFoulInfo(previous =>
1560+
previous === entry.key ? null : entry.key
1561+
)
1562+
}
1563+
aria-expanded={activeFoulInfo === entry.key}
1564+
className={`rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide transition ${
1565+
activeFoulInfo === entry.key
1566+
? 'border-sky-300/70 bg-sky-300/15 text-sky-100'
1567+
: 'border-white/25 bg-white/5 text-gray-300 hover:bg-white/10'
1568+
}`}>
1569+
Info
1570+
</button>
1571+
<span className='w-8 text-right text-sm font-semibold tabular-nums text-white'>
1572+
{fouls[entry.key]}
1573+
</span>
1574+
<HoldButton
1575+
onHold={() => adjustFoul(entry.key, 1)}
1576+
repeatDelay={120}
1577+
repeatInterval={90}
1578+
className='rounded bg-[#48c55c] px-2 py-1 text-xs font-semibold text-black'>
1579+
+
1580+
</HoldButton>
1581+
</div>
1582+
{activeFoulInfo === entry.key ? (
1583+
<div className='border-t border-white/10 bg-[#0f1522] px-3 py-2 text-[11px] text-gray-200'>
1584+
<p>{entry.definition}</p>
1585+
<p className='mt-1 text-gray-300'>Example: {entry.example}</p>
1586+
</div>
1587+
) : null}
15001588
</div>
15011589
))}
15021590
</div>
@@ -1510,25 +1598,48 @@ function MatchApp() {
15101598
{breakLabels.map(entry => (
15111599
<div
15121600
key={entry.key}
1513-
className='flex items-center gap-2 rounded-lg border border-white/10 bg-[#121a28] px-2 py-2'>
1514-
<HoldButton
1515-
onHold={() => adjustBreak(entry.key, -1)}
1516-
repeatDelay={120}
1517-
repeatInterval={90}
1518-
className='rounded bg-[#c44e4e] px-2 py-1 text-xs font-semibold text-white'>
1519-
-
1520-
</HoldButton>
1521-
<span className='flex-1 text-xs text-gray-200'>{entry.label}</span>
1522-
<span className='w-8 text-right text-sm font-semibold tabular-nums text-white'>
1523-
{breaks[entry.key]}
1524-
</span>
1525-
<HoldButton
1526-
onHold={() => adjustBreak(entry.key, 1)}
1527-
repeatDelay={120}
1528-
repeatInterval={90}
1529-
className='rounded bg-[#48c55c] px-2 py-1 text-xs font-semibold text-black'>
1530-
+
1531-
</HoldButton>
1601+
className='rounded-lg border border-white/10 bg-[#121a28]'>
1602+
<div className='flex items-center gap-2 px-2 py-2'>
1603+
<HoldButton
1604+
onHold={() => adjustBreak(entry.key, -1)}
1605+
repeatDelay={120}
1606+
repeatInterval={90}
1607+
className='rounded bg-[#c44e4e] px-2 py-1 text-xs font-semibold text-white'>
1608+
-
1609+
</HoldButton>
1610+
<span className='flex-1 text-xs text-gray-200'>{entry.label}</span>
1611+
<button
1612+
type='button'
1613+
onClick={() =>
1614+
setActiveBreakInfo(previous =>
1615+
previous === entry.key ? null : entry.key
1616+
)
1617+
}
1618+
aria-expanded={activeBreakInfo === entry.key}
1619+
className={`rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide transition ${
1620+
activeBreakInfo === entry.key
1621+
? 'border-sky-300/70 bg-sky-300/15 text-sky-100'
1622+
: 'border-white/25 bg-white/5 text-gray-300 hover:bg-white/10'
1623+
}`}>
1624+
Info
1625+
</button>
1626+
<span className='w-8 text-right text-sm font-semibold tabular-nums text-white'>
1627+
{breaks[entry.key]}
1628+
</span>
1629+
<HoldButton
1630+
onHold={() => adjustBreak(entry.key, 1)}
1631+
repeatDelay={120}
1632+
repeatInterval={90}
1633+
className='rounded bg-[#48c55c] px-2 py-1 text-xs font-semibold text-black'>
1634+
+
1635+
</HoldButton>
1636+
</div>
1637+
{activeBreakInfo === entry.key ? (
1638+
<div className='border-t border-white/10 bg-[#0f1522] px-3 py-2 text-[11px] text-gray-200'>
1639+
<p>{entry.definition}</p>
1640+
<p className='mt-1 text-gray-300'>Example: {entry.example}</p>
1641+
</div>
1642+
) : null}
15321643
</div>
15331644
))}
15341645
</div>

server/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dotenv.load({ path: '.env.local' });
1313

1414
const REMOTE = process.env.LOCATION === 'remote';
1515

16-
process.env.CONTAINER_NAME = 'cala-quals';
16+
process.env.CONTAINER_NAME ??= 'cala-quals';
1717

1818
const container = await startDockerContainer(process.env.CONTAINER_NAME);
1919

0 commit comments

Comments
 (0)