@johnmorrisdotca/kyogijo-stadiums 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +133 -0
- package/NOTICE.md +182 -2
- package/README.md +106 -19
- package/dist/annotate.js +1 -1
- package/dist/arenas-entry.d.ts +4 -0
- package/dist/arenas-entry.js +3 -0
- package/dist/arenas.d.ts +125 -0
- package/dist/arenas.data.d.ts +2 -0
- package/dist/arenas.data.js +3763 -0
- package/dist/arenas.js +72 -0
- package/dist/athletics/describe.d.ts +8 -0
- package/dist/athletics/describe.js +41 -0
- package/dist/athletics/events.d.ts +17 -0
- package/dist/athletics/events.js +48 -0
- package/dist/athletics/facilities.d.ts +80 -0
- package/dist/athletics/facilities.js +176 -0
- package/dist/athletics/infield.d.ts +79 -0
- package/dist/athletics/infield.js +166 -0
- package/dist/athletics/layout.d.ts +13 -0
- package/dist/athletics/layout.js +98 -0
- package/dist/athletics/oval.d.ts +57 -0
- package/dist/athletics/oval.js +116 -0
- package/dist/athletics/plan.d.ts +97 -0
- package/dist/athletics/plan.js +355 -0
- package/dist/athletics/races.d.ts +102 -0
- package/dist/athletics/races.js +355 -0
- package/dist/athletics/steeplechase.d.ts +72 -0
- package/dist/athletics/steeplechase.js +196 -0
- package/dist/athletics/stencil.d.ts +13 -0
- package/dist/athletics/stencil.js +85 -0
- package/dist/athletics/track.d.ts +54 -0
- package/dist/athletics/track.js +105 -0
- package/dist/athletics/types.d.ts +77 -0
- package/dist/athletics/types.js +1 -0
- package/dist/athletics-entry.d.ts +17 -0
- package/dist/athletics-entry.js +11 -0
- package/dist/athletics.style.d.ts +16 -0
- package/dist/athletics.style.js +51 -0
- package/dist/atlas-entry.d.ts +6 -2
- package/dist/atlas-entry.js +4 -2
- package/dist/atlas.d.ts +117 -23
- package/dist/atlas.js +197 -12
- package/dist/background.js +2 -1
- package/dist/budo/describe.d.ts +13 -0
- package/dist/budo/describe.js +120 -0
- package/dist/budo/dojo.api.d.ts +64 -0
- package/dist/budo/dojo.api.js +46 -0
- package/dist/budo/dojo.d.ts +72 -0
- package/dist/budo/dojo.js +300 -0
- package/dist/budo/judo.d.ts +61 -0
- package/dist/budo/judo.js +109 -0
- package/dist/budo/karate.d.ts +29 -0
- package/dist/budo/karate.js +80 -0
- package/dist/budo/kendo.d.ts +18 -0
- package/dist/budo/kendo.js +44 -0
- package/dist/budo/kimarite.d.ts +19 -0
- package/dist/budo/kimarite.js +33 -0
- package/dist/budo/kit.d.ts +16 -0
- package/dist/budo/kit.js +24 -0
- package/dist/budo/kyudo.d.ts +28 -0
- package/dist/budo/kyudo.js +66 -0
- package/dist/budo/looks.d.ts +28 -0
- package/dist/budo/looks.js +58 -0
- package/dist/budo/parts.d.ts +32 -0
- package/dist/budo/parts.js +10 -0
- package/dist/budo/plan.d.ts +64 -0
- package/dist/budo/plan.js +139 -0
- package/dist/budo/room.d.ts +133 -0
- package/dist/budo/room.js +111 -0
- package/dist/budo/sumo.d.ts +31 -0
- package/dist/budo/sumo.js +71 -0
- package/dist/budo/tatami.d.ts +55 -0
- package/dist/budo/tatami.js +156 -0
- package/dist/budo/types.d.ts +192 -0
- package/dist/budo/types.js +2 -0
- package/dist/budo-entry.d.ts +22 -0
- package/dist/budo-entry.js +13 -0
- package/dist/budo.board.d.ts +28 -0
- package/dist/budo.board.js +81 -0
- package/dist/budo.score.d.ts +18 -0
- package/dist/budo.score.js +52 -0
- package/dist/budo.style.d.ts +6 -0
- package/dist/budo.style.js +67 -0
- package/dist/charts-entry.d.ts +6 -1
- package/dist/charts-entry.js +3 -0
- package/dist/charts.athletics.d.ts +183 -0
- package/dist/charts.athletics.js +455 -0
- package/dist/charts.baseball.js +1 -1
- package/dist/charts.curling.heat.d.ts +24 -0
- package/dist/charts.curling.heat.js +116 -0
- package/dist/charts.curling.js +14 -3
- package/dist/charts.js +4 -4
- package/dist/charts.pool.d.ts +67 -0
- package/dist/charts.pool.js +76 -0
- package/dist/charts.skating.d.ts +204 -0
- package/dist/charts.skating.js +426 -0
- package/dist/charts.soccer.js +3 -3
- package/dist/charts.types.d.ts +63 -1
- package/dist/colour.d.ts +4 -4
- package/dist/colour.js +4 -4
- package/dist/court.d.ts +85 -2
- package/dist/court.js +102 -7
- package/dist/court.more.d.ts +46 -0
- package/dist/court.more.js +219 -0
- package/dist/courts.style.d.ts +14 -2
- package/dist/courts.style.js +51 -4
- package/dist/crowd.d.ts +164 -0
- package/dist/crowd.draw.d.ts +17 -0
- package/dist/crowd.draw.js +204 -0
- package/dist/crowd.js +480 -0
- package/dist/crowd.park.d.ts +19 -0
- package/dist/crowd.park.js +153 -0
- package/dist/curling.stats.d.ts +271 -0
- package/dist/curling.stats.js +301 -0
- package/dist/draw.d.ts +16 -0
- package/dist/draw.js +462 -54
- package/dist/element-entry.d.ts +3 -1
- package/dist/element-entry.js +2 -1
- package/dist/element.d.ts +13 -2
- package/dist/element.js +79 -4
- package/dist/emblems-source.d.ts +50 -0
- package/dist/emblems-source.js +56 -0
- package/dist/eras.d.ts +3 -1
- package/dist/eras.js +8 -3
- package/dist/features.js +204 -0
- package/dist/field.data.d.ts +16 -0
- package/dist/field.data.js +50 -0
- package/dist/fields.kit.d.ts +2 -2
- package/dist/fields.types.d.ts +24 -4
- package/dist/formations.js +18 -7
- package/dist/formations.sports.d.ts +8 -0
- package/dist/formations.sports.js +251 -0
- package/dist/frames.providers.js +71 -8
- package/dist/geojson.js +3 -0
- package/dist/geometry-entry.d.ts +2 -1
- package/dist/geometry-entry.js +2 -1
- package/dist/geometry.d.ts +20 -0
- package/dist/geometry.js +78 -1
- package/dist/grounds.d.ts +4 -0
- package/dist/grounds.data.js +12 -0
- package/dist/halls.d.ts +65 -0
- package/dist/halls.js +122 -0
- package/dist/hardwood.d.ts +31 -0
- package/dist/hardwood.js +157 -0
- package/dist/heat.js +21 -13
- package/dist/heat.types.d.ts +5 -0
- package/dist/heat.zones.d.ts +4 -2
- package/dist/heat.zones.js +207 -7
- package/dist/homeside.js +24 -0
- package/dist/index.d.ts +30 -4
- package/dist/index.js +18 -2
- package/dist/layers-entry.d.ts +2 -1
- package/dist/layers-entry.js +1 -0
- package/dist/layers.d.ts +2 -1
- package/dist/layers.env.d.ts +12 -1
- package/dist/layers.env.js +36 -4
- package/dist/layers.js +32 -13
- package/dist/layers.types.d.ts +9 -2
- package/dist/leagues/athletics.d.ts +63 -0
- package/dist/leagues/athletics.js +87 -0
- package/dist/leagues/budo.d.ts +196 -0
- package/dist/leagues/budo.js +105 -0
- package/dist/leagues/courts.d.ts +269 -4
- package/dist/leagues/courts.js +155 -1
- package/dist/leagues/hockey.js +41 -19
- package/dist/leagues/skating.d.ts +145 -0
- package/dist/leagues/skating.js +73 -0
- package/dist/leagues/sources.js +41 -0
- package/dist/leagues/types.d.ts +1 -1
- package/dist/leagues-entry.d.ts +4 -2
- package/dist/leagues-entry.js +2 -1
- package/dist/leagues.d.ts +17 -4
- package/dist/leagues.js +246 -5
- package/dist/lineup.codes.d.ts +23 -0
- package/dist/lineup.codes.js +122 -0
- package/dist/logo.d.ts +25 -0
- package/dist/logo.js +47 -0
- package/dist/look.d.ts +3 -3
- package/dist/look.js +39 -6
- package/dist/outline.d.ts +1 -1
- package/dist/outline.js +46 -4
- package/dist/pageant.d.ts +120 -0
- package/dist/pageant.draw.d.ts +21 -0
- package/dist/pageant.draw.js +171 -0
- package/dist/pageant.js +211 -0
- package/dist/pageant.style.d.ts +8 -0
- package/dist/pageant.style.js +42 -0
- package/dist/png.d.ts +8 -1
- package/dist/png.js +21 -1
- package/dist/pointer-entry.d.ts +2 -0
- package/dist/pointer-entry.js +2 -0
- package/dist/pointer.d.ts +113 -0
- package/dist/pointer.js +151 -0
- package/dist/pool.d.ts +176 -0
- package/dist/pool.figures.d.ts +306 -0
- package/dist/pool.figures.js +148 -0
- package/dist/pool.js +304 -0
- package/dist/pool.kit.d.ts +48 -0
- package/dist/pool.kit.js +141 -0
- package/dist/pool.labels.d.ts +20 -0
- package/dist/pool.labels.js +258 -0
- package/dist/pool.race.d.ts +65 -0
- package/dist/pool.race.js +140 -0
- package/dist/pool.replay.d.ts +46 -0
- package/dist/pool.replay.js +127 -0
- package/dist/pool.section.d.ts +13 -0
- package/dist/pool.section.js +83 -0
- package/dist/pool.style.d.ts +20 -0
- package/dist/pool.style.js +169 -0
- package/dist/pool.types.d.ts +145 -0
- package/dist/pool.types.js +3 -0
- package/dist/pool.words.d.ts +13 -0
- package/dist/pool.words.js +101 -0
- package/dist/ranges.names.js +53 -3
- package/dist/replay-entry.d.ts +3 -0
- package/dist/replay-entry.js +2 -0
- package/dist/restyle.js +1 -1
- package/dist/road.draw.js +3 -2
- package/dist/road.js +2 -1
- package/dist/road.types.d.ts +3 -0
- package/dist/rules.d.ts +138 -0
- package/dist/rules.js +511 -0
- package/dist/rules.types.d.ts +4 -0
- package/dist/rules.types.js +64 -0
- package/dist/score.d.ts +3 -0
- package/dist/score.js +93 -6
- package/dist/sheet.d.ts +3 -0
- package/dist/sheet.js +7 -3
- package/dist/situation.d.ts +135 -0
- package/dist/situation.draw.d.ts +34 -0
- package/dist/situation.draw.js +202 -0
- package/dist/situation.js +337 -0
- package/dist/situation.style.d.ts +2 -0
- package/dist/situation.style.js +45 -0
- package/dist/situation.types.d.ts +77 -0
- package/dist/situation.types.js +3 -0
- package/dist/situation.widgets.d.ts +39 -0
- package/dist/situation.widgets.js +129 -0
- package/dist/skating/describe.d.ts +7 -0
- package/dist/skating/describe.js +44 -0
- package/dist/skating/events.d.ts +24 -0
- package/dist/skating/events.js +47 -0
- package/dist/skating/figure.d.ts +24 -0
- package/dist/skating/figure.js +37 -0
- package/dist/skating/long.d.ts +54 -0
- package/dist/skating/long.js +111 -0
- package/dist/skating/parts.d.ts +43 -0
- package/dist/skating/parts.js +40 -0
- package/dist/skating/plan.d.ts +55 -0
- package/dist/skating/plan.js +197 -0
- package/dist/skating/short.d.ts +47 -0
- package/dist/skating/short.js +89 -0
- package/dist/skating/track.d.ts +66 -0
- package/dist/skating/track.js +94 -0
- package/dist/skating/types.d.ts +57 -0
- package/dist/skating/types.js +3 -0
- package/dist/skating-entry.d.ts +17 -0
- package/dist/skating-entry.js +11 -0
- package/dist/skating.style.d.ts +4 -0
- package/dist/skating.style.js +24 -0
- package/dist/strings.d.ts +470 -0
- package/dist/strings.js +674 -13
- package/dist/style.d.ts +2 -0
- package/dist/style.js +19 -2
- package/dist/surfaces/artistic.d.ts +9 -0
- package/dist/surfaces/artistic.js +94 -0
- package/dist/surfaces/athletics.d.ts +16 -0
- package/dist/surfaces/athletics.js +132 -0
- package/dist/surfaces/baseball.js +17 -0
- package/dist/surfaces/basketball.floor.d.ts +27 -0
- package/dist/surfaces/basketball.floor.js +83 -0
- package/dist/surfaces/basketball.gear.d.ts +27 -0
- package/dist/surfaces/basketball.gear.js +90 -0
- package/dist/surfaces/basketball.js +44 -22
- package/dist/surfaces/budo.d.ts +6 -0
- package/dist/surfaces/budo.js +104 -0
- package/dist/surfaces/curling.d.ts +16 -0
- package/dist/surfaces/curling.fold.d.ts +67 -0
- package/dist/surfaces/curling.fold.js +107 -0
- package/dist/surfaces/curling.js +37 -3
- package/dist/surfaces/dive.d.ts +9 -0
- package/dist/surfaces/dive.js +128 -0
- package/dist/surfaces/field.d.ts +7 -2
- package/dist/surfaces/field.js +15 -9
- package/dist/surfaces/football.js +7 -0
- package/dist/surfaces/hockey.js +4 -2
- package/dist/surfaces/net.d.ts +2 -1
- package/dist/surfaces/net.js +160 -15
- package/dist/surfaces/polo.d.ts +12 -0
- package/dist/surfaces/polo.js +159 -0
- package/dist/surfaces/pool.d.ts +27 -0
- package/dist/surfaces/pool.js +198 -0
- package/dist/surfaces/skating.d.ts +6 -0
- package/dist/surfaces/skating.js +62 -0
- package/dist/surfaces/soccer.js +2 -1
- package/dist/surfaces/surface.d.ts +76 -0
- package/dist/surfaces/venue.d.ts +15 -0
- package/dist/surfaces/venue.js +95 -0
- package/dist/target-entry.d.ts +2 -0
- package/dist/target-entry.js +2 -0
- package/dist/target.d.ts +200 -0
- package/dist/target.js +525 -0
- package/dist/team.common.d.ts +1 -1
- package/dist/team.common.js +3 -3
- package/dist/team.formation.d.ts +3 -1
- package/dist/team.formation.js +3 -3
- package/dist/team.layers.d.ts +2 -2
- package/dist/team.layers.js +4 -1
- package/dist/team.lineup.d.ts +27 -0
- package/dist/team.lineup.js +207 -0
- package/dist/team.network.js +6 -5
- package/dist/team.shape.js +5 -5
- package/dist/team.types.d.ts +40 -1
- package/dist/tenants.d.ts +77 -0
- package/dist/tenants.data.d.ts +8 -0
- package/dist/tenants.data.js +1793 -0
- package/dist/tenants.js +46 -0
- package/dist/turn-entry.d.ts +12 -0
- package/dist/turn-entry.js +7 -0
- package/dist/turn.camera.d.ts +116 -0
- package/dist/turn.camera.js +184 -0
- package/dist/turn.dom.d.ts +40 -0
- package/dist/turn.dom.js +353 -0
- package/dist/turn.kit.d.ts +86 -0
- package/dist/turn.kit.js +110 -0
- package/dist/turn.markup.d.ts +48 -0
- package/dist/turn.markup.js +108 -0
- package/dist/turn.model.d.ts +78 -0
- package/dist/turn.model.js +91 -0
- package/dist/turn.style.d.ts +5 -0
- package/dist/turn.style.js +56 -0
- package/dist/types.d.ts +221 -20
- package/dist/units.d.ts +1 -1
- package/dist/units.js +22 -1
- package/dist/uprights.board.d.ts +17 -0
- package/dist/uprights.board.js +59 -0
- package/dist/uprights.budo.d.ts +17 -0
- package/dist/uprights.budo.js +87 -0
- package/dist/uprights.d.ts +37 -0
- package/dist/uprights.fields.d.ts +32 -0
- package/dist/uprights.fields.js +172 -0
- package/dist/uprights.goal.d.ts +49 -0
- package/dist/uprights.goal.js +69 -0
- package/dist/uprights.js +169 -0
- package/dist/uprights.more.d.ts +7 -0
- package/dist/uprights.more.js +183 -0
- package/dist/uprights.net.d.ts +12 -0
- package/dist/uprights.net.js +109 -0
- package/dist/uprights.netkit.d.ts +28 -0
- package/dist/uprights.netkit.js +67 -0
- package/dist/uprights.pools.d.ts +8 -0
- package/dist/uprights.pools.js +190 -0
- package/dist/uprights.rinks.d.ts +27 -0
- package/dist/uprights.rinks.js +106 -0
- package/dist/uprights.track.d.ts +50 -0
- package/dist/uprights.track.js +246 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/zones-entry.d.ts +2 -0
- package/dist/zones-entry.js +2 -0
- package/package.json +56 -3
package/dist/score.js
CHANGED
|
@@ -142,6 +142,27 @@ export function glyph(sport) {
|
|
|
142
142
|
case "tabletennis":
|
|
143
143
|
// A table: the net across it and the centre line.
|
|
144
144
|
return "M-16 -8H16V8H-16ZM0 -10V10M-16 0H16";
|
|
145
|
+
case "padel":
|
|
146
|
+
// A court: the net, the service lines and the central service line.
|
|
147
|
+
return "M-18 -10H18V10H-18ZM0 -10V10M-12.5 -10V10M12.5 -10V10M-12.5 0H12.5";
|
|
148
|
+
case "squash":
|
|
149
|
+
// A court, the front wall at the left: the short line, the half court line and the two service boxes.
|
|
150
|
+
return "M-18 -10H18V10H-18ZM2.3 -10V10M2.3 0H18M8.2 -10V-5H2.3M8.2 10V5H2.3";
|
|
151
|
+
case "racquetball":
|
|
152
|
+
// A court, the front wall at the left: the short line, the service line and the broken receiving line.
|
|
153
|
+
return "M-18 -10H18V10H-18ZM0 -10V10M-4.5 -10V10M4.5 -10V-8M4.5 -6V-4M4.5 -2V0M4.5 2V4M4.5 6V8";
|
|
154
|
+
case "sepaktakraw":
|
|
155
|
+
// A court: the centre line, the quarter circles at its ends and the service circles.
|
|
156
|
+
return "M-18 -10H18V10H-18ZM0 -10V10M-3 -10A3 3 0 0 0 0 -7A3 3 0 0 0 3 -10M-3 10A3 3 0 0 1 0 7A3 3 0 0 1 3 10M-12.9 0A1.5 1.5 0 1 0 -9.9 0A1.5 1.5 0 1 0 -12.9 0M9.9 0A1.5 1.5 0 1 0 12.9 0A1.5 1.5 0 1 0 9.9 0";
|
|
157
|
+
case "teqball":
|
|
158
|
+
// A court: the halfway line and the service lines, and the table.
|
|
159
|
+
return "M-18 -10H18V10H-18ZM0 -10V10M-7.9 -10V10M7.9 -10V10M-3.4 -1.3H3.4V1.3H-3.4Z";
|
|
160
|
+
case "roundnet":
|
|
161
|
+
// A court: the serving line and the no hit zone line round the set, and the marks at the four service positions.
|
|
162
|
+
return "M-10 -10H10V10H-10ZM-8 0A8 8 0 1 0 8 0A8 8 0 1 0 -8 0M-2.8 0A2.8 2.8 0 1 0 2.8 0A2.8 2.8 0 1 0 -2.8 0M-1.2 0A1.2 1.2 0 1 0 1.2 0A1.2 1.2 0 1 0 -1.2 0M-9 0H-7M7 0H9M0 -9V-7M0 7V9";
|
|
163
|
+
case "netball":
|
|
164
|
+
// A court: the transverse lines, the centre circle and the goal circles.
|
|
165
|
+
return "M-18 -10H18V10H-18ZM-6 -10V10M6 -10V10M-1 0A1 1 0 1 0 1 0A1 1 0 1 0 -1 0M-18 -6.4A6.4 6.4 0 0 1 -18 6.4M18 -6.4A6.4 6.4 0 0 0 18 6.4";
|
|
145
166
|
case "lacrosse":
|
|
146
167
|
// A field: the centre line, the goal circles and the restraining lines.
|
|
147
168
|
return "M-18 -10H18V10H-18ZM0 -10V10M-12 0A3 3 0 1 0 -6 0A3 3 0 1 0 -12 0M12 0A3 3 0 1 0 6 0A3 3 0 1 0 12 0M-7 -10V10M7 -10V10";
|
|
@@ -163,6 +184,42 @@ export function glyph(sport) {
|
|
|
163
184
|
case "handball":
|
|
164
185
|
// A court: the centre line, and the goal areas with their arcs.
|
|
165
186
|
return "M-18 -10H18V10H-18ZM0 -10V10M-18 -6A6 6 0 0 1 -12 0A6 6 0 0 1 -18 6M18 -6A6 6 0 0 0 12 0A6 6 0 0 0 18 6";
|
|
187
|
+
case "swimming":
|
|
188
|
+
// A pool: the lane ropes, and the cross lines at the ends of the lane markings.
|
|
189
|
+
return "M-18 -10H18V10H-18ZM-18 -5H18M-18 0H18M-18 5H18M-14 -7.5V-2.5M14 -7.5V-2.5M-14 2.5V7.5M14 2.5V7.5";
|
|
190
|
+
case "waterpolo":
|
|
191
|
+
// A field: the half distance line, the 2 and 6 metre lines, and a goal at each end.
|
|
192
|
+
return "M-18 -10H18V10H-18ZM0 -10V10M-14 -10V10M14 -10V10M-18 -3H-21V3H-18M18 -3H21V3H18M-9 -10V10M9 -10V10";
|
|
193
|
+
case "diving":
|
|
194
|
+
// A well: the boards along one wall, and the lines across the well.
|
|
195
|
+
return "M-18 -10H18V10H-18ZM-18 -7H-9V-5H-18ZM-18 -1H-12V1H-18ZM-18 5H-9V7H-18ZM0 -9V9M6 -9V9M12 -9V9";
|
|
196
|
+
case "artisticswimming":
|
|
197
|
+
// An area: the lines along the floor, and the judges' platform on one side.
|
|
198
|
+
return "M-18 -10H18V10H-18ZM-18 -5H18M-18 0H18M-18 5H18M-10 -13H10";
|
|
199
|
+
case "skating":
|
|
200
|
+
// A rink: the oval of a track inside the boards, and the finishing line.
|
|
201
|
+
return "M-18 -10H18V10H-18ZM-9 -6H9A6 6 0 0 1 9 6H-9A6 6 0 0 1 -9 -6ZM-9 -3.5H9A3.5 3.5 0 0 1 9 3.5H-9A3.5 3.5 0 0 1 -9 -3.5ZM4 3.5V10";
|
|
202
|
+
case "judo":
|
|
203
|
+
// A contest area: the safety area, the contest area inside it and the two start marks.
|
|
204
|
+
return "M-10 -10H10V10H-10ZM-6 -6H6V6H-6ZM-3 -1.5V1.5M3 -1.5V1.5";
|
|
205
|
+
case "karate":
|
|
206
|
+
// A competition area: the square, the outer band and the two start mats.
|
|
207
|
+
return "M-10 -10H10V10H-10ZM-7 -7H7V7H-7ZM-4.5 -1.5H-2.5V1.5H-4.5ZM2.5 -1.5H4.5V1.5H2.5Z";
|
|
208
|
+
case "kendo":
|
|
209
|
+
// A shiai-jo: the boundary, the cross at the centre and the two start lines.
|
|
210
|
+
return "M-10 -10H10V10H-10ZM-1.5 0H1.5M0 -1.5V1.5M-4 -1.5V1.5M4 -1.5V1.5";
|
|
211
|
+
case "sumo":
|
|
212
|
+
// A dohyō: the clay square, the ring and the two shikiri-sen.
|
|
213
|
+
return "M-10 -10H10V10H-10ZM-7 0A7 7 0 1 0 7 0A7 7 0 1 0 -7 0M-1.5 -2V2M1.5 -2V2";
|
|
214
|
+
case "kyudo":
|
|
215
|
+
// A range: the shajō, the line to the targets and the mound.
|
|
216
|
+
return "M-18 -5H-9V5H-18ZM-9 0H13M13 -6V6H16V-6ZM14.5 -1.5V1.5";
|
|
217
|
+
case "dojo":
|
|
218
|
+
// A dojo: a floor of mats laid so that no four corners meet.
|
|
219
|
+
return "M-14 -10H14V10H-14ZM-14 0H14M-5 -10V0M5 0V10";
|
|
220
|
+
case "athletics":
|
|
221
|
+
// A track: the oval's outer edge, a lane line and the kerb, and the finish line across the straight.
|
|
222
|
+
return "M-9 -10H9A10 10 0 0 1 9 10H-9A10 10 0 0 1 -9 -10ZM-9 -8.2H9A8.2 8.2 0 0 1 9 8.2H-9A8.2 8.2 0 0 1 -9 -8.2ZM-9 -6.4H9A6.4 6.4 0 0 1 9 6.4H-9A6.4 6.4 0 0 1 -9 -6.4ZM9 6.4V10";
|
|
166
223
|
}
|
|
167
224
|
}
|
|
168
225
|
/** The state each of two scores puts its team in. */
|
|
@@ -171,6 +228,12 @@ export function stateOf(winner, role) {
|
|
|
171
228
|
return "none";
|
|
172
229
|
return winner === role ? "win" : "lose";
|
|
173
230
|
}
|
|
231
|
+
/** The least gap between a team's code and its score in the badge, and the least size of the code and of the score before the flag is left out. */
|
|
232
|
+
const BADGE_GAP = 10;
|
|
233
|
+
const BADGE_MEASURE_SCORE = 1.12;
|
|
234
|
+
const BADGE_MEASURE_CODE = 1.2;
|
|
235
|
+
const BADGE_ABBR_LEAST = 12;
|
|
236
|
+
const BADGE_SCORE_LEAST = 16;
|
|
174
237
|
/** The badge: one strip, [logo abbreviation score] [picture and status] [score abbreviation logo]. */
|
|
175
238
|
export function badgeMarkup(left, right, o) {
|
|
176
239
|
const W = 440;
|
|
@@ -183,18 +246,38 @@ export function badgeMarkup(left, right, o) {
|
|
|
183
246
|
const isLeft = team.side === "left";
|
|
184
247
|
const logoSize = 40;
|
|
185
248
|
const logoX = isLeft ? 12 : W - 12 - logoSize;
|
|
186
|
-
const textStart = isLeft ? (team.logo === undefined ? 14 : 60) : W - (team.logo === undefined ? 14 : 60);
|
|
187
249
|
const scoreEdge = isLeft ? block - 14 : W - block + 14;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const
|
|
250
|
+
// The code and the score each keep to their own room, with a gap between them: the score is measured, and when the two do not fit the code shrinks to the least that reads, then the score does,
|
|
251
|
+
// and then the flag is left out to give them its room. A short score in a roomy block is laid out as it always was.
|
|
252
|
+
const fit = (withLogo) => {
|
|
253
|
+
const textStart = isLeft ? (withLogo ? 60 : 14) : W - (withLogo ? 60 : 14);
|
|
254
|
+
const avail = Math.abs(scoreEdge - textStart);
|
|
255
|
+
// The measure is an estimate, under what a bold face draws (by a tenth for digits, a fifth for capitals): the layout allows for that.
|
|
256
|
+
const ws = Math.max(1, textWidth(team.score) * BADGE_MEASURE_SCORE);
|
|
257
|
+
const wa = Math.max(1, textWidth(team.abbr) * BADGE_MEASURE_CODE);
|
|
258
|
+
let scoreSize = Math.min(32, (block * 0.42) / ws);
|
|
259
|
+
let abbrSize = Math.min(22, (avail - ws * scoreSize - BADGE_GAP) / wa);
|
|
260
|
+
if (abbrSize < BADGE_ABBR_LEAST) {
|
|
261
|
+
abbrSize = BADGE_ABBR_LEAST;
|
|
262
|
+
scoreSize = Math.min(scoreSize, (avail - BADGE_GAP - abbrSize * wa) / ws);
|
|
263
|
+
}
|
|
264
|
+
return { textStart, scoreSize, abbrSize, ok: scoreSize >= BADGE_SCORE_LEAST };
|
|
265
|
+
};
|
|
266
|
+
const withLogo = team.logo !== undefined;
|
|
267
|
+
let laid = fit(withLogo);
|
|
268
|
+
const logoShown = withLogo && (laid.ok || !fit(false).ok);
|
|
269
|
+
if (withLogo && !logoShown)
|
|
270
|
+
laid = fit(false);
|
|
271
|
+
const { textStart } = laid;
|
|
272
|
+
const scoreSize = Math.max(laid.scoreSize, 8);
|
|
273
|
+
const abbrSize = Math.max(laid.abbrSize, 8);
|
|
191
274
|
// The hammer: a small stone in the corner of the team's block.
|
|
192
275
|
if (team.hammer === true)
|
|
193
276
|
out += el("g", { class: `ky-badge-hammer ky-badge-hammer-${team.side}`, transform: `translate(${isLeft ? block - 11 : W - block + 11} 11)` }, el("circle", { class: "ky-hammer", r: 6 }) + el("circle", { class: "ky-hammer-in", r: 2.6 }));
|
|
194
277
|
// The ball of the team that is serving, in the same corner.
|
|
195
278
|
if (team.serving === true)
|
|
196
279
|
out += el("g", { transform: `translate(${isLeft ? block - 11 : W - block + 11} 11)` }, el("circle", { class: "ky-serve", r: 6 }) + el("path", { class: "ky-serve-seam", d: "M-4.7 -1.8Q0 1.8 4.7 -1.8", "stroke-width": 0.9 }));
|
|
197
|
-
out += el("g", { class: `ky-badge-team ky-badge-${team.side} ky-${team.state}`, part: part(o.parts, `team ${team.role}`) }, (team.logo === undefined
|
|
280
|
+
out += el("g", { class: `ky-badge-team ky-badge-${team.side} ky-${team.state}`, part: part(o.parts, `team ${team.role}`) }, (!logoShown || team.logo === undefined
|
|
198
281
|
? ""
|
|
199
282
|
: team.round === true
|
|
200
283
|
? roundMarkup({ id: `${o.id ?? "ky"}-mk-${team.role}`, cx: logoX + logoSize / 2, cy: 12 + logoSize / 2, r: logoSize / 2, href: team.logo, fit: team.fit, ring: 2 })
|
|
@@ -203,7 +286,11 @@ export function badgeMarkup(left, right, o) {
|
|
|
203
286
|
el("text", { class: `ky-text ky-score ky-ink-${team.side} ky-${team.state}`, x: scoreEdge, y: H / 2 + scoreSize * 0.36, "font-size": scoreSize, "text-anchor": isLeft ? "end" : "start", part: part(o.parts, `score ${team.role}-score`) }, esc(team.score)));
|
|
204
287
|
}
|
|
205
288
|
const mid = W / 2;
|
|
206
|
-
|
|
289
|
+
// A situation takes the place of the picture of the surface: the game's pill, scorebug or tag.
|
|
290
|
+
if (o.situation !== undefined)
|
|
291
|
+
out += el("g", { class: "ky-badge-situation", transform: `translate(${mid} ${o.status ? 23 : 32})` }, o.situation);
|
|
292
|
+
else
|
|
293
|
+
out += el("path", { class: "ky-glyph", d: glyph(o.sport), transform: `translate(${mid} ${o.status ? 22 : 32}) scale(0.9)`, fill: "none" });
|
|
207
294
|
if (o.status) {
|
|
208
295
|
const size = Math.min(11.5, 76 / Math.max(1, textWidth(o.status, false)));
|
|
209
296
|
out += el("text", { class: "ky-text ky-badge-status", x: mid, y: 52 + size * 0.2, "font-size": size }, esc(o.status));
|
package/dist/sheet.d.ts
CHANGED
|
@@ -9,6 +9,9 @@ export interface SheetPlan {
|
|
|
9
9
|
guardZone: boolean;
|
|
10
10
|
show: SheetShow;
|
|
11
11
|
end: "left" | "right";
|
|
12
|
+
/** `show: "folded"`: what each enlarged panel holds, and the shape of the frame it fills. */
|
|
13
|
+
panels: "half" | "house";
|
|
14
|
+
fit: number;
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* The sheet the options ask for. A `league` picks the rulebook (World Curling's by default); `sheet.length` and `sheet.width` are in `units`
|
package/dist/sheet.js
CHANGED
|
@@ -5,7 +5,7 @@ import { CURLING_LEAGUES } from "./leagues/curling.js";
|
|
|
5
5
|
import { lengthUnit } from "./common.js";
|
|
6
6
|
import { parseRange } from "./ranges.names.js";
|
|
7
7
|
import { convertLength } from "./units.js";
|
|
8
|
-
const SHOWS = ["sheet", "half", "house"];
|
|
8
|
+
const SHOWS = ["sheet", "half", "house", "folded"];
|
|
9
9
|
const FEET = (feet) => String(Math.round(feet * 100) / 100);
|
|
10
10
|
/**
|
|
11
11
|
* The sheet the options ask for. A `league` picks the rulebook (World Curling's by default); `sheet.length` and `sheet.width` are in `units`
|
|
@@ -33,6 +33,10 @@ export function sheetFor(o) {
|
|
|
33
33
|
const ranged = o.sport === "curling" ? parseRange(o) : undefined;
|
|
34
34
|
const named = ranged !== undefined && ranged.kind === "name" ? ranged : undefined;
|
|
35
35
|
const show = named !== undefined ? named.name : SHOWS.includes(asked.show) ? asked.show : "sheet";
|
|
36
|
-
const end = named?.asked !== undefined ? named.asked : asked.end === "right" ? "right" : "left";
|
|
37
|
-
|
|
36
|
+
const end = named?.asked !== undefined ? named.asked : asked.end === "right" || asked.end === "bottom" ? "right" : "left";
|
|
37
|
+
const panels = asked.panels === "house" ? "house" : "half";
|
|
38
|
+
if (asked.fit !== undefined && !(typeof asked.fit === "number" && asked.fit >= 0.5 && asked.fit <= 2))
|
|
39
|
+
throw new RangeError(`The folded sheet's fit is its width over its height, 0.5 to 2: ${String(asked.fit)} is not`);
|
|
40
|
+
const fit = asked.fit ?? 1;
|
|
41
|
+
return { league, spec: { ...base, length, width }, pebble: asked.pebble === true, guardZone: asked.guardZone === true, show, end, panels, fit };
|
|
38
42
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { DirectionOptions, Language, Side, Sport } from "./types.ts";
|
|
2
|
+
import type { DriveResult, Situation, SituationTeam } from "./situation.types.ts";
|
|
3
|
+
export type { BaseballSituation, DriveLeg, DriveResult, FootballSituation, HockeySituation, ShootoutAttempt, ShootoutRound, Situation, SituationTeam } from "./situation.types.ts";
|
|
4
|
+
/** The most rounds of a shootout that are drawn. */
|
|
5
|
+
export declare const SHOOTOUT_MAX = 12;
|
|
6
|
+
/** The rounds that are regular: the rounds after them are sudden death. */
|
|
7
|
+
export declare const SHOOTOUT_REGULAR = 3;
|
|
8
|
+
/** The most drives drawn in a drive chart. */
|
|
9
|
+
export declare const DRIVES_MAX = 24;
|
|
10
|
+
/** The red zone: the yards before the goal line the offence attacks. */
|
|
11
|
+
export declare const RED_ZONE_YARDS = 20;
|
|
12
|
+
/** The yards to a first down. */
|
|
13
|
+
export declare const FIRST_DOWN_YARDS = 10;
|
|
14
|
+
/** The short code each drive result is written with at the head of its arrow. */
|
|
15
|
+
export declare const DRIVE_CODES: Readonly<Record<DriveResult, string>>;
|
|
16
|
+
/** What a reading needs to know of the drawing it is for. */
|
|
17
|
+
export interface SituationContext {
|
|
18
|
+
/** The sport as drawn (`chooseLeague(o).sport`): `nhl`, `mlb`, `nfl`, `cfl` or `ifaf`; a situation is for these only. */
|
|
19
|
+
sport: Sport;
|
|
20
|
+
/** The side the home team's banner is on. */
|
|
21
|
+
homeSide: Side;
|
|
22
|
+
/** The attack arrows' options, which say which end each team attacks. */
|
|
23
|
+
direction?: DirectionOptions;
|
|
24
|
+
/** The football field: the yards between the goal lines and the downs a team has. */
|
|
25
|
+
football?: {
|
|
26
|
+
yards: number;
|
|
27
|
+
downs: number;
|
|
28
|
+
};
|
|
29
|
+
/** The teams' names, when the drawing has teams. */
|
|
30
|
+
names?: {
|
|
31
|
+
home: string;
|
|
32
|
+
away: string;
|
|
33
|
+
};
|
|
34
|
+
/** The league's id as the options name it (`iihf`, `olympic`), when they name one. */
|
|
35
|
+
league?: string;
|
|
36
|
+
}
|
|
37
|
+
/** Hockey, read. */
|
|
38
|
+
export interface HockeyRead {
|
|
39
|
+
kind: "hockey";
|
|
40
|
+
/** The skaters, when known. */
|
|
41
|
+
away?: number;
|
|
42
|
+
home?: number;
|
|
43
|
+
/** The team that is attacking (more skaters, or the goalkeeper pulled, or the other team of a delayed penalty), and the end it heads for. */
|
|
44
|
+
attacker?: SituationTeam;
|
|
45
|
+
toward?: "left" | "right";
|
|
46
|
+
/** The attacker's skaters and the other team's, in that order, when both are known. */
|
|
47
|
+
strength?: [number, number];
|
|
48
|
+
/** More skaters than the other team. */
|
|
49
|
+
powerPlay: boolean;
|
|
50
|
+
emptyNet?: SituationTeam;
|
|
51
|
+
delayed?: SituationTeam;
|
|
52
|
+
clock?: string;
|
|
53
|
+
/** The shootout is called the game winning shots (GWS) in this league. */
|
|
54
|
+
gws: boolean;
|
|
55
|
+
shootout?: {
|
|
56
|
+
rounds: [boolean | null, boolean | null][];
|
|
57
|
+
goals: [number, number];
|
|
58
|
+
sudden: number;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/** Baseball, read. */
|
|
62
|
+
export interface BaseballRead {
|
|
63
|
+
kind: "baseball";
|
|
64
|
+
bases?: [boolean, boolean, boolean];
|
|
65
|
+
outs?: number;
|
|
66
|
+
inning?: number;
|
|
67
|
+
half?: "top" | "bottom";
|
|
68
|
+
balls?: number;
|
|
69
|
+
strikes?: number;
|
|
70
|
+
}
|
|
71
|
+
/** A drive, read: in yards from the team's own goal line, and the end it heads for. */
|
|
72
|
+
export interface DriveRead {
|
|
73
|
+
team: SituationTeam;
|
|
74
|
+
from: number;
|
|
75
|
+
to: number;
|
|
76
|
+
result?: DriveResult;
|
|
77
|
+
toward: "left" | "right";
|
|
78
|
+
}
|
|
79
|
+
/** Football, read. */
|
|
80
|
+
export interface FootballRead {
|
|
81
|
+
kind: "football";
|
|
82
|
+
yards: number;
|
|
83
|
+
downs: number;
|
|
84
|
+
ballOn?: number;
|
|
85
|
+
toGo?: number | "goal";
|
|
86
|
+
down?: number;
|
|
87
|
+
possession?: SituationTeam;
|
|
88
|
+
/** The end zone the offence heads for. */
|
|
89
|
+
toward: "left" | "right";
|
|
90
|
+
redZone: boolean;
|
|
91
|
+
drive: DriveRead[];
|
|
92
|
+
}
|
|
93
|
+
/** A situation, read. */
|
|
94
|
+
export type SituationRead = HockeyRead | BaseballRead | FootballRead;
|
|
95
|
+
/** `m:ss`, `m:ss.s`, or a whole number of seconds written as `m:ss`; anything else is left out. */
|
|
96
|
+
export declare function clockText(value: unknown): string | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* The situation a drawing's options ask for, decided: which team attacks and which end, what is lit. `undefined` when the options have none, when the sport has no situation (only
|
|
99
|
+
* hockey, baseball and football do), or when nothing in it is a value the sport can have.
|
|
100
|
+
*/
|
|
101
|
+
export declare function readSituation(situation: unknown, ctx: SituationContext): SituationRead | undefined;
|
|
102
|
+
/** A yard line as the tag writes it: `OWN 35`, `OPP 12`, or the middle of the field. */
|
|
103
|
+
export declare function yardLineText(ballOn: number, yards: number, language: Language): string;
|
|
104
|
+
/** The down and distance as the tag writes it (`3rd & 7`, `1st & Goal`), or `undefined` when there is no down. */
|
|
105
|
+
export declare function downTag(read: FootballRead, language: Language): string | undefined;
|
|
106
|
+
/** The strength of a hockey situation on the pill: `5v4 PP`, `6v5 EN`, `4v4`, `DEL PEN`, with the clock after it; `undefined` when there is nothing to say (5 against 5). */
|
|
107
|
+
export declare function hockeyPill(read: HockeyRead, language: Language): string | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* The short label of a situation as the drawing writes it: hockey's `5v4 PP 1:42`, baseball's `Top 7 · 2 out · 3-2`, football's `3rd & 7`. `undefined` when there is none to write.
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* import { situationText } from "@johnmorrisdotca/kyogijo-stadiums";
|
|
113
|
+
* console.log(situationText({ sport: "nhl", situation: { awaySkaters: 5, homeSkaters: 4, clock: "1:42" } }));
|
|
114
|
+
* console.log(situationText({ sport: "mlb", situation: { inning: 7, half: "top", outs: 2, balls: 3, strikes: 2 } }));
|
|
115
|
+
* console.log(situationText({ sport: "nfl", situation: { ballOn: 88, down: 3, toGo: 7 } }));
|
|
116
|
+
* // 5v4 PP 1:42
|
|
117
|
+
* // Top 7 · 2 out · 3-2
|
|
118
|
+
* // 3rd & 7 · OPP 12
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export declare function situationText(options: {
|
|
122
|
+
sport: Sport;
|
|
123
|
+
league?: string;
|
|
124
|
+
homeSide?: Side;
|
|
125
|
+
direction?: DirectionOptions;
|
|
126
|
+
language?: Language;
|
|
127
|
+
situation?: Situation;
|
|
128
|
+
}, language?: Language): string | undefined;
|
|
129
|
+
/** The short label of a reading, in a language. */
|
|
130
|
+
export declare function tagOf(read: SituationRead, language: Language): string | undefined;
|
|
131
|
+
/** The sentences a description adds for a situation, each beginning with a capital. */
|
|
132
|
+
export declare function situationSentences(read: SituationRead, language: Language, names?: {
|
|
133
|
+
home: string;
|
|
134
|
+
away: string;
|
|
135
|
+
}): string[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type SituationRead } from "./situation.ts";
|
|
2
|
+
import { type Surface } from "./surfaces/surface.ts";
|
|
3
|
+
import type { Language, Side } from "./types.ts";
|
|
4
|
+
/** What a situation is drawn with. */
|
|
5
|
+
export interface SituationEnv {
|
|
6
|
+
id: string;
|
|
7
|
+
language: Language;
|
|
8
|
+
/** The side the home team is on. */
|
|
9
|
+
homeSide: Side;
|
|
10
|
+
/** The two teams' short names, when the drawing has teams. */
|
|
11
|
+
abbrs?: {
|
|
12
|
+
home: string;
|
|
13
|
+
away: string;
|
|
14
|
+
};
|
|
15
|
+
/** The score's panel stands in the middle of the surface. */
|
|
16
|
+
plate: boolean;
|
|
17
|
+
/** The strip under the drawing shows the situation (the pill, the scorebug or the tag), so the surface does not: a lineup's players stand where they would be. */
|
|
18
|
+
strip?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/** What a situation adds to a drawing. */
|
|
21
|
+
export interface SituationDrawn {
|
|
22
|
+
/** Over the surface's ground and under its lines. */
|
|
23
|
+
under: string;
|
|
24
|
+
/** Over the lines and the data, under the score's panel. */
|
|
25
|
+
over: string;
|
|
26
|
+
defs: string;
|
|
27
|
+
}
|
|
28
|
+
/** A situation drawn on a surface, or `undefined` when nothing is to be drawn. */
|
|
29
|
+
export declare function drawSituation(read: SituationRead, surface: Surface, env: SituationEnv): SituationDrawn | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* A situation as the badge (and the compact card's strip) shows it in place of the picture of the surface: the markup centred on the origin of a box 76 wide, and `undefined` when there is
|
|
32
|
+
* nothing to show. Hockey's pill, baseball's scorebug and football's tag, each shrunk to fit.
|
|
33
|
+
*/
|
|
34
|
+
export declare function badgeSituation(read: SituationRead, language: Language): string | undefined;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// A situation drawn on a surface: hockey's pill and tinted attacking zone, its empty net and shootout strip; baseball's lit bases and scorebug; football's line of scrimmage, first-down line,
|
|
2
|
+
// red zone, tag and drive chart. What is under the surface's lines (a tint) is `under`, what is over them is `over`; both are in the surface's wide frame, in feet, with the widgets set
|
|
3
|
+
// upright (turned back when the surface is turned a quarter).
|
|
4
|
+
import { wideView } from "./annotate.js";
|
|
5
|
+
import { el, num } from "./format.js";
|
|
6
|
+
import { DRIVE_CODES, downTag, hockeyPill, yardLineText } from "./situation.js";
|
|
7
|
+
import { pillWidget, scorebugWidget, shootoutWidget, tagWidget } from "./situation.widgets.js";
|
|
8
|
+
import { KYOGIJO_STRINGS } from "./strings.js";
|
|
9
|
+
import { roundedRect, textOn } from "./surfaces/surface.js";
|
|
10
|
+
/** A widget set where the eye wants it, upright however the surface lies. */
|
|
11
|
+
function put(widget, cx, cy, turned) {
|
|
12
|
+
return el("g", { class: "ky-sit-w", transform: `translate(${num(cx)} ${num(cy)})${turned ? " rotate(-90)" : ""}` }, widget.markup);
|
|
13
|
+
}
|
|
14
|
+
/** A value held between `lo` and `hi`; the middle of them when they cross. */
|
|
15
|
+
const within = (value, lo, hi) => (hi < lo ? (lo + hi) / 2 : Math.min(hi, Math.max(lo, value)));
|
|
16
|
+
/**
|
|
17
|
+
* A widget's centre held inside a box with a little to spare. A surface turned a quarter turns the widget back, so its width then lies along the wide frame's y and its height along x.
|
|
18
|
+
*/
|
|
19
|
+
function inside(widget, turned, box, cx, cy) {
|
|
20
|
+
const hx = (turned ? widget.h : widget.w) / 2 + 1;
|
|
21
|
+
const hy = (turned ? widget.w : widget.h) / 2 + 1;
|
|
22
|
+
return [within(cx, box.x + hx, box.x + box.w - hx), within(cy, box.y + hy, box.y + box.h - hy)];
|
|
23
|
+
}
|
|
24
|
+
const sideOf = (team, homeSide) => ((team === "home") === (homeSide === "left") ? "left" : "right");
|
|
25
|
+
/** The rotation, on the eye's page, of an arrow that points to the `left` or `right` end of a surface drawn wide (turned a quarter, `right` is down). */
|
|
26
|
+
const headAngle = (toward, turned) => (turned ? (toward === "right" ? 90 : -90) : toward === "right" ? 0 : 180);
|
|
27
|
+
function drawHockey(read, surface, env) {
|
|
28
|
+
const a = surface.anchors?.kind === "hockey" ? surface.anchors : undefined;
|
|
29
|
+
const out = { under: "", over: "", defs: "" };
|
|
30
|
+
if (a === undefined)
|
|
31
|
+
return out;
|
|
32
|
+
const vb = surface.box ?? { x: 0, y: 0, w: a.length, h: a.width };
|
|
33
|
+
const size = 5.2;
|
|
34
|
+
const words = KYOGIJO_STRINGS[env.language].situation;
|
|
35
|
+
if (read.shootout !== undefined) {
|
|
36
|
+
const labels = [env.abbrs?.away ?? words.awayShort, env.abbrs?.home ?? words.homeShort];
|
|
37
|
+
const strip = shootoutWidget({ rounds: read.shootout.rounds, goals: read.shootout.goals, sudden: read.shootout.sudden, labels, sides: [sideOf("away", env.homeSide), sideOf("home", env.homeSide)], suddenWord: words.sudden }, size * 0.56, true);
|
|
38
|
+
const cx = vb.x + vb.w / 2;
|
|
39
|
+
// Under the score's panel when it stands in the middle, else across the middle of what is shown.
|
|
40
|
+
const below = env.plate ? surface.plate.cy + surface.plate.h / 2 + 2 + strip.h / 2 : vb.y + vb.h / 2;
|
|
41
|
+
out.over = put(strip, ...inside(strip, surface.turned, vb, cx, below), surface.turned);
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
const label = hockeyPill(read, env.language);
|
|
45
|
+
if (read.attacker !== undefined && read.toward !== undefined) {
|
|
46
|
+
// The attacking zone, from the blue line to the end boards, in the attacking team's colour, cut to the ice.
|
|
47
|
+
const x0 = read.toward === "right" ? a.length - a.blueLine : 0;
|
|
48
|
+
out.defs = el("clipPath", { id: `${env.id}-sit-ice` }, el("path", { d: roundedRect(0, 0, a.length, a.width, a.cornerRadius) }));
|
|
49
|
+
out.under = el("g", { class: "ky-sit-zone-g", "clip-path": `url(#${env.id}-sit-ice)` }, el("rect", { class: `ky-sit-zone ky-sit-zone-${sideOf(read.attacker, env.homeSide)}`, x: x0, y: 0, width: a.blueLine, height: a.width }));
|
|
50
|
+
}
|
|
51
|
+
if (read.emptyNet !== undefined && read.toward !== undefined) {
|
|
52
|
+
// The empty net is at the end the attackers are leaving: ringed.
|
|
53
|
+
const gx = read.toward === "right" ? a.goalLine : a.length - a.goalLine;
|
|
54
|
+
const dir = read.toward === "right" ? -1 : 1;
|
|
55
|
+
const pad = 1.3;
|
|
56
|
+
out.over += el("rect", { class: "ky-sit-net", x: dir < 0 ? gx - a.net.depth - pad : gx - pad, y: a.width / 2 - a.net.width / 2 - pad, width: a.net.depth + 2 * pad, height: a.net.width + 2 * pad, rx: 1.2 });
|
|
57
|
+
}
|
|
58
|
+
if (label !== undefined && env.strip !== true) {
|
|
59
|
+
const pill = pillWidget(label, size, read.attacker === undefined ? undefined : sideOf(read.attacker, env.homeSide));
|
|
60
|
+
// Wide, at the top of the ice in the middle; tall, just inside the top blue line, in the middle across.
|
|
61
|
+
const at = surface.turned
|
|
62
|
+
? inside(pill, true, vb, (vb.x <= a.blueLine ? a.blueLine : vb.x) + pill.h / 2 + 3, vb.y + vb.h / 2)
|
|
63
|
+
: inside(pill, false, vb, vb.x + vb.w / 2, vb.y + pill.h / 2 + 3);
|
|
64
|
+
out.over += put(pill, ...at, surface.turned);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
function drawBaseball(read, surface, env) {
|
|
69
|
+
const a = surface.anchors?.kind === "baseball" ? surface.anchors : undefined;
|
|
70
|
+
const out = { under: "", over: "", defs: "" };
|
|
71
|
+
if (a === undefined)
|
|
72
|
+
return out;
|
|
73
|
+
// The occupied bases, lit larger than they are drawn so that they read from a distance.
|
|
74
|
+
if (read.bases !== undefined) {
|
|
75
|
+
const k = a.half * 2.6;
|
|
76
|
+
read.bases.forEach((on, i) => {
|
|
77
|
+
if (!on)
|
|
78
|
+
return;
|
|
79
|
+
const [u, v] = a.bases[i];
|
|
80
|
+
out.over += el("path", { class: "ky-sit-lit", d: `M${num(u)} ${num(v - k)}L${num(u + k)} ${num(v)}L${num(u)} ${num(v + k)}L${num(u - k)} ${num(v)}Z` });
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// The scorebug at the foot of the field, behind home plate, held inside what is shown.
|
|
84
|
+
const view = wideView(surface);
|
|
85
|
+
const bug = { bases: read.bases, outs: read.outs, inning: read.inning, half: read.half, balls: read.balls, strikes: read.strikes };
|
|
86
|
+
if (env.strip !== true && Object.values(bug).some((value) => value !== undefined)) {
|
|
87
|
+
let u = Math.min(11, view.h * 0.2, view.w * 0.1);
|
|
88
|
+
let widget = scorebugWidget(bug, u, true);
|
|
89
|
+
// A drawing cut very small gets a bug that fits it.
|
|
90
|
+
if (widget.w > view.w * 0.9) {
|
|
91
|
+
u *= (view.w * 0.9) / widget.w;
|
|
92
|
+
widget = scorebugWidget(bug, u, true);
|
|
93
|
+
}
|
|
94
|
+
out.over += put(widget, within(0, view.x + widget.w / 2 + 1, view.x + view.w - widget.w / 2 - 1), view.y + view.h - widget.h / 2 - 3, false);
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
}
|
|
98
|
+
function drawFootball(read, surface, env) {
|
|
99
|
+
const a = surface.anchors?.kind === "football" ? surface.anchors : undefined;
|
|
100
|
+
const out = { under: "", over: "", defs: "" };
|
|
101
|
+
if (a === undefined)
|
|
102
|
+
return out;
|
|
103
|
+
const e = a.endZone;
|
|
104
|
+
const G = a.length;
|
|
105
|
+
const W = a.width;
|
|
106
|
+
const dir = read.toward === "right" ? 1 : -1;
|
|
107
|
+
// A distance in yards from a team's own goal line, as a place along the field, for a team heading for `toward`.
|
|
108
|
+
const at = (yards, toward) => (toward === "right" ? e + yards * 3 : e + G - yards * 3);
|
|
109
|
+
const vb = surface.box ?? { x: 0, y: 0, w: G + 2 * e, h: W };
|
|
110
|
+
// The red zone: the last 20 yards before the goal line the offence is attacking.
|
|
111
|
+
if (read.redZone) {
|
|
112
|
+
const goal = read.toward === "right" ? e + G : e;
|
|
113
|
+
out.under = el("rect", { class: "ky-sit-red", x: Math.min(goal, goal - dir * 60), y: 0, width: 60, height: W });
|
|
114
|
+
}
|
|
115
|
+
let x;
|
|
116
|
+
if (read.ballOn !== undefined) {
|
|
117
|
+
x = at(read.ballOn, read.toward);
|
|
118
|
+
out.over += el("path", { class: "ky-sit-los-halo", d: `M${num(x)} 0V${num(W)}`, fill: "none" });
|
|
119
|
+
// The first-down line, ten yards on or where the options put it, unless the goal line is nearer.
|
|
120
|
+
if (typeof read.toGo === "number" && read.ballOn + read.toGo < read.yards) {
|
|
121
|
+
const fd = at(read.ballOn + read.toGo, read.toward);
|
|
122
|
+
out.over += el("path", { class: "ky-sit-fd-halo", d: `M${num(fd)} 0V${num(W)}`, fill: "none" });
|
|
123
|
+
out.over += el("path", { class: "ky-sit-fd", d: `M${num(fd)} 0V${num(W)}`, fill: "none" });
|
|
124
|
+
}
|
|
125
|
+
out.over += el("path", { class: "ky-sit-los", d: `M${num(x)} 0V${num(W)}`, fill: "none" });
|
|
126
|
+
}
|
|
127
|
+
// The drive chart: an arrow for each drive, in a lane of its own across the field.
|
|
128
|
+
const n = read.drive.length;
|
|
129
|
+
if (n > 0) {
|
|
130
|
+
// The lanes lie across the field; the score's panel stands over the middle of it, so they go in the band below it.
|
|
131
|
+
const y0 = env.plate ? surface.plate.cy + surface.plate.h / 2 + 3 : 10;
|
|
132
|
+
const y1 = env.plate ? W - 6 : W - 10;
|
|
133
|
+
const step = Math.min(10, Math.max(2.4, (y1 - y0) / n));
|
|
134
|
+
const top = y0 + (y1 - y0 - step * n) / 2;
|
|
135
|
+
read.drive.forEach((leg, i) => {
|
|
136
|
+
const y = top + step * (i + 0.5);
|
|
137
|
+
const x0 = at(leg.from, leg.toward);
|
|
138
|
+
const x1 = at(leg.to, leg.toward);
|
|
139
|
+
const d = Math.sign(x1 - x0) || (leg.toward === "right" ? 1 : -1);
|
|
140
|
+
const head = Math.min(3.4, Math.abs(x1 - x0));
|
|
141
|
+
const cls = `ky-sit-d-${leg.result ?? "none"}`;
|
|
142
|
+
out.over += el("path", { class: `ky-sit-dr-halo`, d: `M${num(x0)} ${num(y)}H${num(x1 - d * head * 0.6)}`, fill: "none" });
|
|
143
|
+
out.over += el("path", { class: `ky-sit-dr ${cls}`, d: `M${num(x0)} ${num(y)}H${num(x1 - d * head * 0.6)}`, fill: "none" });
|
|
144
|
+
out.over += el("circle", { class: `ky-sit-dot-s ${cls}`, cx: x0, cy: y, r: 1.2 });
|
|
145
|
+
if (head > 0.5)
|
|
146
|
+
out.over += el("path", { class: `ky-sit-dh ${cls}`, d: `M${num(x1)} ${num(y)}L${num(x1 - d * head)} ${num(y - head * 0.62)}V${num(y + head * 0.62)}Z` });
|
|
147
|
+
if (leg.result !== undefined)
|
|
148
|
+
out.over += textOn(surface.turned, x1 + d * 1.8, y + 3.6 * 0.36, DRIVE_CODES[leg.result], { size: 3.6, anchor: d > 0 ? "start" : "end", cls: "ky-sit-dl", weight: 800 });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
// The tag: the down and distance, with the yard line, behind the line of scrimmage near the far sideline.
|
|
152
|
+
const main = downTag(read, env.language);
|
|
153
|
+
const where = read.ballOn === undefined ? undefined : yardLineText(read.ballOn, read.yards, env.language);
|
|
154
|
+
if (env.strip !== true && (main !== undefined || where !== undefined)) {
|
|
155
|
+
const tag = tagWidget(main ?? where ?? "", main === undefined ? undefined : where, 5.6, headAngle(read.toward, surface.turned));
|
|
156
|
+
const along = (surface.turned ? tag.h : tag.w) / 2;
|
|
157
|
+
const across = (surface.turned ? tag.w : tag.h) / 2;
|
|
158
|
+
const cy = vb.y + across + 5;
|
|
159
|
+
// Behind the line of scrimmage, 4 feet off it; nudged along the field, to the line first and then away from it, until it covers none of the yard numbers and the arrows beside them that point to a goal line.
|
|
160
|
+
// Where there is no such room it keeps off the arrows at least.
|
|
161
|
+
const clear = (cx, hide) => {
|
|
162
|
+
const [px, py] = inside(tag, surface.turned, vb, cx, cy);
|
|
163
|
+
return !hide.some(([ox, oy, hx, hy]) => Math.abs(ox - px) < along + hx + 0.8 && Math.abs(oy - py) < across + hy + 0.8);
|
|
164
|
+
};
|
|
165
|
+
const gaps = [4, 3, 2, 1, 0.5, ...Array.from({ length: 36 }, (_, i) => 5 + i)];
|
|
166
|
+
const gap = x === undefined ? undefined : (gaps.find((g) => clear(x - dir * (along + g), [...a.arrows, ...a.numerals])) ?? gaps.find((g) => clear(x - dir * (along + g), a.arrows)) ?? 4);
|
|
167
|
+
const beside = x === undefined || gap === undefined ? vb.x + vb.w / 2 : x - dir * (along + gap);
|
|
168
|
+
out.over += put(tag, ...inside(tag, surface.turned, vb, beside, cy), surface.turned);
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
/** A situation drawn on a surface, or `undefined` when nothing is to be drawn. */
|
|
173
|
+
export function drawSituation(read, surface, env) {
|
|
174
|
+
const drawn = read.kind === "hockey" ? drawHockey(read, surface, env) : read.kind === "baseball" ? drawBaseball(read, surface, env) : drawFootball(read, surface, env);
|
|
175
|
+
return drawn.under === "" && drawn.over === "" ? undefined : drawn;
|
|
176
|
+
}
|
|
177
|
+
/** The widest a badge's middle holds, in the badge's units. */
|
|
178
|
+
const BADGE_ROOM = 74;
|
|
179
|
+
/**
|
|
180
|
+
* A situation as the badge (and the compact card's strip) shows it in place of the picture of the surface: the markup centred on the origin of a box 76 wide, and `undefined` when there is
|
|
181
|
+
* nothing to show. Hockey's pill, baseball's scorebug and football's tag, each shrunk to fit.
|
|
182
|
+
*/
|
|
183
|
+
export function badgeSituation(read, language) {
|
|
184
|
+
let widget;
|
|
185
|
+
if (read.kind === "hockey") {
|
|
186
|
+
const label = hockeyPill(read, language);
|
|
187
|
+
widget = label === undefined ? undefined : pillWidget(label, 9);
|
|
188
|
+
}
|
|
189
|
+
else if (read.kind === "baseball") {
|
|
190
|
+
const bug = { bases: read.bases, outs: read.outs, inning: read.inning, half: read.half, balls: read.balls, strikes: read.strikes };
|
|
191
|
+
widget = Object.values(bug).some((value) => value !== undefined) ? scorebugWidget(bug, 8.4, false) : undefined;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
const main = downTag(read, language);
|
|
195
|
+
const where = read.ballOn === undefined ? undefined : yardLineText(read.ballOn, read.yards, language);
|
|
196
|
+
widget = main === undefined && where === undefined ? undefined : tagWidget(main ?? where ?? "", main === undefined ? undefined : where, 8.2);
|
|
197
|
+
}
|
|
198
|
+
if (widget === undefined)
|
|
199
|
+
return undefined;
|
|
200
|
+
const k = Math.min(1, BADGE_ROOM / widget.w);
|
|
201
|
+
return k === 1 ? widget.markup : el("g", { transform: `scale(${k.toFixed(3)})` }, widget.markup);
|
|
202
|
+
}
|