@@ -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