Skip to content

Commit 53702a4

Browse files
dveltonCopilot
andcommitted
Fix zone analysis to account for teams switching ends
The Shots by Zone section now classifies shots as Offensive, Neutral, or Defensive relative to each team, adjusting for the end switch between periods. In P1/P3/OT the home team attacks right; in P2 they attack left. A home team shot on the right side in P1 is correctly classified as offensive, and a shot on the right side in P2 is correctly classified as defensive. Previously the zones were just Left/Center/Right based on raw position, which didn't account for the side switch and produced misleading results. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 17993d4 commit 53702a4

File tree

1 file changed

+50
-23
lines changed

1 file changed

+50
-23
lines changed

src/components/GameSummary.jsx

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,49 @@ export default function GameSummary({ game, onBack }) {
5252
return d.toLocaleTimeString(undefined, { hour: 'numeric', minute: '2-digit' });
5353
};
5454

55-
// Zone analysis: divide rink into thirds (defensive 0-0.33, neutral 0.33-0.66, offensive 0.66-1.0)
56-
const zoneLabel = (x) => {
57-
if (x < 0.375) return 'left';
58-
if (x > 0.625) return 'right';
55+
// Zone analysis: classify shots as offensive/neutral/defensive relative to each team.
56+
// Standard hockey: P1 & P3 & OT: home attacks right. P2: home attacks left.
57+
const classifyZone = (x, team, periodNumber) => {
58+
const homeAttacksRight = periodNumber !== 2;
59+
const isLeft = x < 0.375;
60+
const isRight = x > 0.625;
61+
62+
if (team === 'home') {
63+
if (homeAttacksRight) {
64+
if (isRight) return 'offensive';
65+
if (isLeft) return 'defensive';
66+
} else {
67+
if (isLeft) return 'offensive';
68+
if (isRight) return 'defensive';
69+
}
70+
} else if (team === 'away') {
71+
if (homeAttacksRight) {
72+
if (isLeft) return 'offensive';
73+
if (isRight) return 'defensive';
74+
} else {
75+
if (isRight) return 'offensive';
76+
if (isLeft) return 'defensive';
77+
}
78+
}
5979
return 'neutral';
6080
};
6181

62-
const zoneStats = (shots) => {
63-
const left = shots.filter((s) => zoneLabel(s.x) === 'left');
64-
const neutral = shots.filter((s) => zoneLabel(s.x) === 'neutral');
65-
const right = shots.filter((s) => zoneLabel(s.x) === 'right');
66-
return { left, neutral, right };
82+
// Tag each shot with its period, then compute zone stats
83+
const taggedShots = game.periods.flatMap((p) =>
84+
p.shots.map((s) => ({ ...s, periodNumber: p.number }))
85+
);
86+
const taggedHome = taggedShots.filter((s) => s.team === 'home');
87+
const taggedAway = taggedShots.filter((s) => s.team === 'away');
88+
89+
const buildZoneStats = (shots, team) => {
90+
const offensive = shots.filter((s) => classifyZone(s.x, team, s.periodNumber) === 'offensive');
91+
const neutral = shots.filter((s) => classifyZone(s.x, team, s.periodNumber) === 'neutral');
92+
const defensive = shots.filter((s) => classifyZone(s.x, team, s.periodNumber) === 'defensive');
93+
return { offensive, neutral, defensive };
6794
};
6895

69-
const homeZones = zoneStats(homeShots);
70-
const awayZones = zoneStats(awayShots);
96+
const homeZones = buildZoneStats(taggedHome, 'home');
97+
const awayZones = buildZoneStats(taggedAway, 'away');
7198

7299
// Build player stats
73100
const playerStats = {};
@@ -333,27 +360,27 @@ export default function GameSummary({ game, onBack }) {
333360
<div className="bg-slate-50 rounded-xl p-4">
334361
<div className="text-sm font-semibold text-blue-600 mb-2">{game.homeTeam}</div>
335362
<div className="space-y-1.5">
336-
<ZoneBar label="Left" count={homeZones.left.length} total={homeShots.length} color="#3b82f6" />
337-
<ZoneBar label="Center" count={homeZones.neutral.length} total={homeShots.length} color="#3b82f6" />
338-
<ZoneBar label="Right" count={homeZones.right.length} total={homeShots.length} color="#3b82f6" />
363+
<ZoneBar label="Offensive" count={homeZones.offensive.length} total={homeShots.length} color="#3b82f6" />
364+
<ZoneBar label="Neutral" count={homeZones.neutral.length} total={homeShots.length} color="#3b82f6" />
365+
<ZoneBar label="Defensive" count={homeZones.defensive.length} total={homeShots.length} color="#3b82f6" />
339366
</div>
340367
<div className="text-xs text-slate-400 mt-2">
341-
{pct(homeZones.left.length, homeShots.length)} left
342-
{' / '}{pct(homeZones.neutral.length, homeShots.length)} center
343-
{' / '}{pct(homeZones.right.length, homeShots.length)} right
368+
{pct(homeZones.offensive.length, homeShots.length)} offensive
369+
{' / '}{pct(homeZones.neutral.length, homeShots.length)} neutral
370+
{' / '}{pct(homeZones.defensive.length, homeShots.length)} defensive
344371
</div>
345372
</div>
346373
<div className="bg-slate-50 rounded-xl p-4">
347374
<div className="text-sm font-semibold text-red-500 mb-2">{game.awayTeam}</div>
348375
<div className="space-y-1.5">
349-
<ZoneBar label="Left" count={awayZones.left.length} total={awayShots.length} color="#ef4444" />
350-
<ZoneBar label="Center" count={awayZones.neutral.length} total={awayShots.length} color="#ef4444" />
351-
<ZoneBar label="Right" count={awayZones.right.length} total={awayShots.length} color="#ef4444" />
376+
<ZoneBar label="Offensive" count={awayZones.offensive.length} total={awayShots.length} color="#ef4444" />
377+
<ZoneBar label="Neutral" count={awayZones.neutral.length} total={awayShots.length} color="#ef4444" />
378+
<ZoneBar label="Defensive" count={awayZones.defensive.length} total={awayShots.length} color="#ef4444" />
352379
</div>
353380
<div className="text-xs text-slate-400 mt-2">
354-
{pct(awayZones.left.length, awayShots.length)} left
355-
{' / '}{pct(awayZones.neutral.length, awayShots.length)} center
356-
{' / '}{pct(awayZones.right.length, awayShots.length)} right
381+
{pct(awayZones.offensive.length, awayShots.length)} offensive
382+
{' / '}{pct(awayZones.neutral.length, awayShots.length)} neutral
383+
{' / '}{pct(awayZones.defensive.length, awayShots.length)} defensive
357384
</div>
358385
</div>
359386
</div>

0 commit comments

Comments
 (0)