@inventure71/paddockjs 0.3.0 → 1.0.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 +39 -0
- package/INSTALL_AND_UPDATE.md +3 -1
- package/README.md +142 -9
- package/docs/architecture.md +49 -15
- package/docs/concepts.md +20 -3
- package/docs/data_contract.md +185 -27
- package/docs/data_model.md +1 -1
- package/docs/learnings.md +1 -1
- package/docs/rules.md +140 -19
- package/docs/system_specs.md +39 -16
- package/docs/training.md +103 -1
- package/examples/train-basic-policy.mjs +5 -6
- package/examples/trainingData.mjs +133 -0
- package/package.json +5 -2
- package/src/api/PaddockSimulatorController.js +32 -2
- package/src/app/F1SimulatorApp.js +1101 -128
- package/src/app/domBindings.js +10 -1
- package/src/config/defaultOptions.js +4 -4
- package/src/environment/actions.js +25 -2
- package/src/environment/evaluation.js +184 -0
- package/src/environment/index.d.ts +281 -1
- package/src/environment/index.js +13 -0
- package/src/environment/observationOptions.js +12 -0
- package/src/environment/observations.js +189 -17
- package/src/environment/options.js +7 -0
- package/src/environment/recorder.js +28 -0
- package/src/environment/runtime.js +41 -6
- package/src/environment/scenarios.js +220 -0
- package/src/environment/sensors.js +145 -35
- package/src/environment/specs.js +92 -8
- package/src/environment/workerProtocol.js +52 -0
- package/src/index.d.ts +366 -3
- package/src/index.js +21 -0
- package/src/rendering/proceduralTrackAsset.js +336 -23
- package/src/simulation/collisionGeometry.js +214 -0
- package/src/simulation/driverController.js +431 -65
- package/src/simulation/raceSimulation.js +2132 -171
- package/src/simulation/rules/collisionSteward.js +69 -0
- package/src/simulation/rules/penaltyLedger.js +153 -0
- package/src/simulation/rules/pitLaneSpeedingSteward.js +71 -0
- package/src/simulation/rules/tireRequirementSteward.js +29 -0
- package/src/simulation/rules/trackLimitsSteward.js +85 -0
- package/src/simulation/rulesConfig.js +352 -0
- package/src/simulation/trackModel.js +1154 -76
- package/src/simulation/units.js +6 -4
- package/src/simulation/vehicleGeometry.js +247 -0
- package/src/simulation/vehiclePhysics.js +82 -50
- package/src/simulation/wheelSurface.js +338 -0
- package/src/styles.css +300 -42
- package/src/ui/bannerTemplates.js +69 -0
- package/src/ui/componentTemplates.js +36 -96
- package/src/ui/raceControlStatusBanner.js +39 -0
- package/src/ui/shellTemplate.js +1 -1
- package/src/ui/templateUtils.js +23 -0
package/src/styles.css
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
--text: #f4f7fb;
|
|
11
11
|
--muted: #8d97a7;
|
|
12
12
|
--red: var(--paddock-accent-color, #e10600);
|
|
13
|
+
--race-control-red: #e10600;
|
|
13
14
|
--green: var(--paddock-green-color, #14c784);
|
|
14
15
|
--yellow: var(--paddock-yellow-color, #ffd166);
|
|
15
16
|
--blue: #39a7ff;
|
|
@@ -68,6 +69,8 @@
|
|
|
68
69
|
|
|
69
70
|
.sim-backlink,
|
|
70
71
|
.sim-control {
|
|
72
|
+
min-width: 0;
|
|
73
|
+
overflow: hidden;
|
|
71
74
|
border: 1px solid var(--line-strong);
|
|
72
75
|
color: var(--text);
|
|
73
76
|
background: rgba(255, 255, 255, 0.05);
|
|
@@ -77,6 +80,8 @@
|
|
|
77
80
|
font-size: 0.76rem;
|
|
78
81
|
font-weight: 800;
|
|
79
82
|
padding: 0.75rem 0.9rem;
|
|
83
|
+
text-overflow: ellipsis;
|
|
84
|
+
white-space: nowrap;
|
|
80
85
|
cursor: pointer;
|
|
81
86
|
}
|
|
82
87
|
|
|
@@ -92,7 +97,8 @@
|
|
|
92
97
|
border-color: var(--yellow);
|
|
93
98
|
}
|
|
94
99
|
|
|
95
|
-
.camera-controls button.is-active
|
|
100
|
+
.camera-controls button.is-active,
|
|
101
|
+
.camera-controls button[aria-pressed='true'] {
|
|
96
102
|
color: #08090b;
|
|
97
103
|
background: var(--text);
|
|
98
104
|
border-color: var(--text);
|
|
@@ -121,6 +127,7 @@
|
|
|
121
127
|
}
|
|
122
128
|
|
|
123
129
|
.sim-controls {
|
|
130
|
+
min-width: 0;
|
|
124
131
|
display: flex;
|
|
125
132
|
gap: 0.6rem;
|
|
126
133
|
justify-content: flex-end;
|
|
@@ -128,7 +135,7 @@
|
|
|
128
135
|
|
|
129
136
|
.sim-external-camera-controls {
|
|
130
137
|
display: flex;
|
|
131
|
-
justify-content: flex-
|
|
138
|
+
justify-content: flex-start;
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
.sim-grid {
|
|
@@ -136,7 +143,7 @@
|
|
|
136
143
|
min-height: 0;
|
|
137
144
|
position: relative;
|
|
138
145
|
display: grid;
|
|
139
|
-
grid-template-columns: minmax(
|
|
146
|
+
grid-template-columns: minmax(0, 0.78fr) minmax(0, 3fr) minmax(0, 0.9fr);
|
|
140
147
|
gap: 0.9rem;
|
|
141
148
|
}
|
|
142
149
|
|
|
@@ -229,12 +236,12 @@
|
|
|
229
236
|
}
|
|
230
237
|
|
|
231
238
|
.sim-shell--left-tower-overlay .race-data-panel {
|
|
232
|
-
z-index:
|
|
239
|
+
z-index: 12;
|
|
233
240
|
grid-template-columns: clamp(4.6rem, 7.5cqw, 7rem) minmax(0, 1fr) auto;
|
|
234
241
|
}
|
|
235
242
|
|
|
236
243
|
.sim-canvas-panel--with-timing-tower .race-data-panel {
|
|
237
|
-
z-index:
|
|
244
|
+
z-index: 12;
|
|
238
245
|
grid-template-columns: clamp(4.6rem, 7.5cqw, 7rem) minmax(0, 1fr) auto;
|
|
239
246
|
}
|
|
240
247
|
|
|
@@ -296,8 +303,13 @@
|
|
|
296
303
|
|
|
297
304
|
.telemetry-stack {
|
|
298
305
|
display: grid;
|
|
306
|
+
grid-auto-rows: max-content;
|
|
307
|
+
align-content: start;
|
|
299
308
|
gap: 0.72rem;
|
|
300
309
|
min-height: 0;
|
|
310
|
+
max-height: 100%;
|
|
311
|
+
overflow-y: auto;
|
|
312
|
+
scrollbar-width: thin;
|
|
301
313
|
}
|
|
302
314
|
|
|
303
315
|
.telemetry-stack > .sim-telemetry {
|
|
@@ -360,7 +372,7 @@
|
|
|
360
372
|
|
|
361
373
|
.broadcast-brand,
|
|
362
374
|
.broadcast-lap,
|
|
363
|
-
.broadcast-
|
|
375
|
+
.broadcast-race-control-banner,
|
|
364
376
|
.broadcast-column-head,
|
|
365
377
|
.timing-list {
|
|
366
378
|
position: relative;
|
|
@@ -409,21 +421,31 @@
|
|
|
409
421
|
letter-spacing: -0.04em;
|
|
410
422
|
}
|
|
411
423
|
|
|
412
|
-
.broadcast-
|
|
424
|
+
.broadcast-race-control-banner {
|
|
413
425
|
display: grid;
|
|
414
426
|
grid-template-columns: 3.4rem minmax(0, 1fr);
|
|
415
427
|
align-items: center;
|
|
416
428
|
margin: 0;
|
|
429
|
+
background: rgba(255, 255, 255, 0.16);
|
|
430
|
+
color: #fff;
|
|
431
|
+
text-transform: uppercase;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.broadcast-race-control-banner.is-safety-car {
|
|
417
435
|
background: #e0ce00;
|
|
418
436
|
color: #0a0b0d;
|
|
419
|
-
text-transform: uppercase;
|
|
420
437
|
}
|
|
421
438
|
|
|
422
|
-
.broadcast-
|
|
439
|
+
.broadcast-race-control-banner.is-red-flag {
|
|
440
|
+
background: var(--race-control-red);
|
|
441
|
+
color: #fff;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.broadcast-race-control-banner[hidden] {
|
|
423
445
|
display: none;
|
|
424
446
|
}
|
|
425
447
|
|
|
426
|
-
.broadcast-
|
|
448
|
+
.broadcast-race-control-banner span {
|
|
427
449
|
display: grid;
|
|
428
450
|
place-items: center;
|
|
429
451
|
min-height: 2.65rem;
|
|
@@ -434,7 +456,7 @@
|
|
|
434
456
|
letter-spacing: -0.06em;
|
|
435
457
|
}
|
|
436
458
|
|
|
437
|
-
.broadcast-
|
|
459
|
+
.broadcast-race-control-banner strong {
|
|
438
460
|
padding: 0 0.65rem;
|
|
439
461
|
font-size: 1.1rem;
|
|
440
462
|
font-weight: 900;
|
|
@@ -562,6 +584,11 @@
|
|
|
562
584
|
scrollbar-width: thin;
|
|
563
585
|
}
|
|
564
586
|
|
|
587
|
+
.timing-list > li {
|
|
588
|
+
min-width: 0;
|
|
589
|
+
overflow: hidden;
|
|
590
|
+
}
|
|
591
|
+
|
|
565
592
|
.sim-shell--left-tower-overlay .timing-list {
|
|
566
593
|
overflow-x: hidden;
|
|
567
594
|
overflow-y: auto;
|
|
@@ -603,6 +630,10 @@
|
|
|
603
630
|
min-width: 0;
|
|
604
631
|
}
|
|
605
632
|
|
|
633
|
+
.timing-row > * {
|
|
634
|
+
min-width: 0;
|
|
635
|
+
}
|
|
636
|
+
|
|
606
637
|
.sim-shell--left-tower-overlay .timing-row {
|
|
607
638
|
min-width: 0;
|
|
608
639
|
}
|
|
@@ -668,7 +699,9 @@
|
|
|
668
699
|
|
|
669
700
|
.timing-name {
|
|
670
701
|
min-width: 0;
|
|
671
|
-
display:
|
|
702
|
+
display: flex;
|
|
703
|
+
align-items: center;
|
|
704
|
+
gap: 0.26rem;
|
|
672
705
|
overflow: hidden;
|
|
673
706
|
padding-inline: 0.45rem;
|
|
674
707
|
font-size: 0.76rem;
|
|
@@ -680,11 +713,37 @@
|
|
|
680
713
|
text-transform: uppercase;
|
|
681
714
|
}
|
|
682
715
|
|
|
716
|
+
.timing-name > span:first-child {
|
|
717
|
+
min-width: 0;
|
|
718
|
+
overflow: hidden;
|
|
719
|
+
text-overflow: ellipsis;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.timing-penalty-badge {
|
|
723
|
+
flex: 0 0 auto;
|
|
724
|
+
display: grid;
|
|
725
|
+
place-items: center;
|
|
726
|
+
width: 1rem;
|
|
727
|
+
height: 1rem;
|
|
728
|
+
color: #fff;
|
|
729
|
+
background: #e10600;
|
|
730
|
+
border: 1px solid rgba(255, 220, 220, 0.78);
|
|
731
|
+
border-radius: 0.18rem;
|
|
732
|
+
font-family: var(--font-mono);
|
|
733
|
+
font-size: 0.66rem;
|
|
734
|
+
font-weight: 900;
|
|
735
|
+
line-height: 1;
|
|
736
|
+
box-shadow: 0 0 14px rgba(225, 6, 0, 0.42);
|
|
737
|
+
}
|
|
738
|
+
|
|
683
739
|
.timing-gap {
|
|
684
740
|
color: rgba(244, 247, 251, 0.76);
|
|
685
741
|
font-size: 0.66rem;
|
|
742
|
+
overflow: hidden;
|
|
686
743
|
padding-right: 0.25rem;
|
|
687
744
|
text-align: right;
|
|
745
|
+
text-overflow: ellipsis;
|
|
746
|
+
white-space: nowrap;
|
|
688
747
|
}
|
|
689
748
|
|
|
690
749
|
.timing-row.is-selected .timing-gap {
|
|
@@ -728,6 +787,11 @@
|
|
|
728
787
|
.track-canvas {
|
|
729
788
|
position: absolute;
|
|
730
789
|
inset: 0;
|
|
790
|
+
z-index: 0;
|
|
791
|
+
background: #2e7d32;
|
|
792
|
+
cursor: default;
|
|
793
|
+
user-select: none;
|
|
794
|
+
touch-action: auto;
|
|
731
795
|
}
|
|
732
796
|
|
|
733
797
|
.track-canvas canvas {
|
|
@@ -738,19 +802,41 @@
|
|
|
738
802
|
|
|
739
803
|
.race-telemetry-drawer {
|
|
740
804
|
--telemetry-drawer-width: min(390px, max(300px, 30cqw));
|
|
805
|
+
--race-toolbar-height: 3.4rem;
|
|
741
806
|
position: relative;
|
|
742
|
-
display:
|
|
807
|
+
display: flex;
|
|
808
|
+
flex-direction: column;
|
|
743
809
|
container-type: inline-size;
|
|
744
810
|
inline-size: 100%;
|
|
745
|
-
|
|
811
|
+
max-inline-size: 100%;
|
|
812
|
+
height: var(--paddock-race-view-height, var(--paddock-race-view-min-height, 620px));
|
|
813
|
+
min-height: min(100%, var(--paddock-race-view-min-height, 620px));
|
|
746
814
|
overflow: hidden;
|
|
747
815
|
background: #000;
|
|
748
816
|
}
|
|
749
817
|
|
|
818
|
+
.race-telemetry-drawer__toolbar {
|
|
819
|
+
position: relative;
|
|
820
|
+
z-index: 13;
|
|
821
|
+
display: flex;
|
|
822
|
+
align-items: center;
|
|
823
|
+
justify-content: space-between;
|
|
824
|
+
gap: 0.7rem;
|
|
825
|
+
min-height: var(--race-toolbar-height);
|
|
826
|
+
padding: 0.45rem;
|
|
827
|
+
background: #090b0d;
|
|
828
|
+
border-bottom: 1px solid var(--line);
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.race-telemetry-drawer__toolbar .camera-controls--external {
|
|
832
|
+
flex: 1 1 auto;
|
|
833
|
+
}
|
|
834
|
+
|
|
750
835
|
.race-telemetry-drawer__race {
|
|
751
836
|
min-width: 0;
|
|
752
837
|
display: flex;
|
|
753
|
-
|
|
838
|
+
flex: 1 1 auto;
|
|
839
|
+
min-height: 0;
|
|
754
840
|
margin-right: 0;
|
|
755
841
|
transition: margin-right 320ms cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
756
842
|
}
|
|
@@ -761,15 +847,12 @@
|
|
|
761
847
|
|
|
762
848
|
.race-telemetry-drawer__race > .sim-canvas-panel {
|
|
763
849
|
flex: 1 1 auto;
|
|
764
|
-
min-height:
|
|
765
|
-
height:
|
|
850
|
+
min-height: 0;
|
|
851
|
+
height: 100%;
|
|
766
852
|
}
|
|
767
853
|
|
|
768
854
|
.race-telemetry-drawer__controls {
|
|
769
|
-
|
|
770
|
-
z-index: 12;
|
|
771
|
-
top: 1rem;
|
|
772
|
-
right: 1rem;
|
|
855
|
+
min-width: 0;
|
|
773
856
|
display: flex;
|
|
774
857
|
flex-wrap: wrap;
|
|
775
858
|
justify-content: flex-end;
|
|
@@ -780,7 +863,6 @@
|
|
|
780
863
|
.race-telemetry-drawer__controls .telemetry-drawer-toggle {
|
|
781
864
|
min-height: 2.45rem;
|
|
782
865
|
padding: 0.62rem 0.72rem;
|
|
783
|
-
box-shadow: 0 14px 34px rgba(0, 0, 0, 0.3);
|
|
784
866
|
}
|
|
785
867
|
|
|
786
868
|
.telemetry-drawer-toggle {
|
|
@@ -798,47 +880,46 @@
|
|
|
798
880
|
.telemetry-drawer {
|
|
799
881
|
position: absolute;
|
|
800
882
|
z-index: 11;
|
|
801
|
-
top:
|
|
883
|
+
top: var(--race-toolbar-height);
|
|
802
884
|
right: 0;
|
|
803
885
|
bottom: 0;
|
|
804
886
|
width: var(--telemetry-drawer-width);
|
|
805
887
|
min-width: 0;
|
|
806
|
-
height: 100
|
|
888
|
+
height: calc(100% - var(--race-toolbar-height));
|
|
807
889
|
overflow: hidden;
|
|
808
890
|
color: var(--text);
|
|
809
891
|
background:
|
|
810
892
|
linear-gradient(180deg, rgba(255, 255, 255, 0.075), transparent 22%),
|
|
811
893
|
rgba(8, 9, 11, 0.97);
|
|
812
894
|
border-left: 1px solid var(--line);
|
|
813
|
-
|
|
895
|
+
clip-path: inset(0 0 0 100%);
|
|
896
|
+
transform: translate3d(0, 0, 0);
|
|
814
897
|
opacity: 0;
|
|
815
898
|
pointer-events: none;
|
|
816
899
|
will-change: transform, opacity;
|
|
817
900
|
transition:
|
|
818
|
-
|
|
901
|
+
clip-path 320ms cubic-bezier(0.2, 0.8, 0.2, 1),
|
|
819
902
|
opacity 180ms ease;
|
|
820
903
|
}
|
|
821
904
|
|
|
822
905
|
.race-telemetry-drawer.is-telemetry-open .telemetry-drawer {
|
|
823
|
-
|
|
906
|
+
clip-path: inset(0);
|
|
824
907
|
opacity: 1;
|
|
825
908
|
pointer-events: auto;
|
|
826
909
|
}
|
|
827
910
|
|
|
828
|
-
.telemetry-drawer__header {
|
|
829
|
-
min-height: 3.4rem;
|
|
830
|
-
border-bottom: 1px solid var(--line);
|
|
831
|
-
}
|
|
832
|
-
|
|
833
911
|
.telemetry-drawer__content {
|
|
834
|
-
|
|
835
|
-
gap: 0.72rem;
|
|
836
|
-
height: calc(100% - 3.4rem);
|
|
912
|
+
height: 100%;
|
|
837
913
|
padding: 0.72rem;
|
|
838
|
-
|
|
914
|
+
min-height: 0;
|
|
915
|
+
overflow: hidden;
|
|
839
916
|
scrollbar-width: thin;
|
|
840
917
|
}
|
|
841
918
|
|
|
919
|
+
.telemetry-drawer__content > .telemetry-stack {
|
|
920
|
+
height: 100%;
|
|
921
|
+
}
|
|
922
|
+
|
|
842
923
|
.camera-controls {
|
|
843
924
|
position: absolute;
|
|
844
925
|
top: 1rem;
|
|
@@ -855,6 +936,8 @@
|
|
|
855
936
|
|
|
856
937
|
.camera-controls--external {
|
|
857
938
|
position: relative;
|
|
939
|
+
top: auto;
|
|
940
|
+
left: auto;
|
|
858
941
|
max-width: 100%;
|
|
859
942
|
justify-content: flex-end;
|
|
860
943
|
background: rgba(8, 9, 11, 0.84);
|
|
@@ -877,6 +960,89 @@
|
|
|
877
960
|
border-color: var(--text);
|
|
878
961
|
}
|
|
879
962
|
|
|
963
|
+
.steward-message {
|
|
964
|
+
--steward-panel-bg: rgba(8, 9, 11, 0.92);
|
|
965
|
+
--steward-chip-bg: color-mix(in srgb, var(--steward-color, var(--yellow)) 18%, rgba(8, 9, 11, 0.94));
|
|
966
|
+
--steward-chip-color: var(--steward-color, var(--yellow));
|
|
967
|
+
position: absolute;
|
|
968
|
+
top: 1rem;
|
|
969
|
+
left: 50%;
|
|
970
|
+
z-index: 8;
|
|
971
|
+
display: grid;
|
|
972
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
973
|
+
gap: 0.16rem 0.7rem;
|
|
974
|
+
min-width: min(28rem, calc(100% - 2rem));
|
|
975
|
+
max-width: min(34rem, calc(100% - 2rem));
|
|
976
|
+
padding: 0.62rem 0.75rem;
|
|
977
|
+
color: var(--text);
|
|
978
|
+
background: var(--steward-panel-bg);
|
|
979
|
+
border: 1px solid color-mix(in srgb, var(--steward-color, var(--yellow)) 70%, transparent);
|
|
980
|
+
box-shadow:
|
|
981
|
+
inset 0 3px 0 var(--steward-color, var(--yellow)),
|
|
982
|
+
0 16px 40px rgba(0, 0, 0, 0.34);
|
|
983
|
+
transform: translate(-50%, 0);
|
|
984
|
+
opacity: 1;
|
|
985
|
+
pointer-events: none;
|
|
986
|
+
transition:
|
|
987
|
+
opacity 160ms ease,
|
|
988
|
+
transform 160ms ease;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
.steward-message.is-penalty {
|
|
992
|
+
--steward-panel-bg: linear-gradient(110deg, rgba(68, 6, 8, 0.96), rgba(8, 9, 11, 0.94) 58%);
|
|
993
|
+
--steward-chip-bg: #e10600;
|
|
994
|
+
--steward-chip-color: #fff;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
.steward-message.is-warning {
|
|
998
|
+
--steward-panel-bg: linear-gradient(110deg, rgba(70, 56, 8, 0.96), rgba(8, 9, 11, 0.94) 58%);
|
|
999
|
+
--steward-chip-bg: var(--yellow);
|
|
1000
|
+
--steward-chip-color: #111318;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.steward-message.is-hidden {
|
|
1004
|
+
opacity: 0;
|
|
1005
|
+
transform: translate(-50%, -0.55rem);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.steward-message__kicker {
|
|
1009
|
+
grid-row: span 2;
|
|
1010
|
+
align-self: center;
|
|
1011
|
+
min-width: 4.9rem;
|
|
1012
|
+
padding: 0.48rem 0.62rem;
|
|
1013
|
+
color: var(--steward-chip-color);
|
|
1014
|
+
background: var(--steward-chip-bg);
|
|
1015
|
+
border: 1px solid color-mix(in srgb, var(--steward-chip-color) 34%, transparent);
|
|
1016
|
+
font-family: var(--font-mono);
|
|
1017
|
+
font-size: 1.05rem;
|
|
1018
|
+
font-weight: 900;
|
|
1019
|
+
letter-spacing: 0.02em;
|
|
1020
|
+
line-height: 1;
|
|
1021
|
+
text-align: center;
|
|
1022
|
+
text-transform: uppercase;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.steward-message strong {
|
|
1026
|
+
min-width: 0;
|
|
1027
|
+
overflow-wrap: anywhere;
|
|
1028
|
+
overflow: hidden;
|
|
1029
|
+
color: var(--text);
|
|
1030
|
+
font-size: 0.92rem;
|
|
1031
|
+
line-height: 1.08;
|
|
1032
|
+
text-transform: uppercase;
|
|
1033
|
+
white-space: normal;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.steward-message span:last-child {
|
|
1037
|
+
min-width: 0;
|
|
1038
|
+
overflow-wrap: anywhere;
|
|
1039
|
+
overflow: hidden;
|
|
1040
|
+
color: var(--muted);
|
|
1041
|
+
font-size: 0.7rem;
|
|
1042
|
+
text-overflow: ellipsis;
|
|
1043
|
+
white-space: normal;
|
|
1044
|
+
}
|
|
1045
|
+
|
|
880
1046
|
.fps-counter {
|
|
881
1047
|
position: absolute;
|
|
882
1048
|
top: 1rem;
|
|
@@ -1133,11 +1299,13 @@
|
|
|
1133
1299
|
left: var(--race-data-banner-left);
|
|
1134
1300
|
bottom: 1.2rem;
|
|
1135
1301
|
transform: translateX(var(--race-data-banner-translate-x));
|
|
1136
|
-
z-index:
|
|
1302
|
+
z-index: 12;
|
|
1137
1303
|
display: grid;
|
|
1138
|
-
grid-template-columns: clamp(6.5rem, 12vw, 9.6rem) minmax(
|
|
1304
|
+
grid-template-columns: clamp(6.5rem, 12vw, 9.6rem) minmax(0, 1fr) auto;
|
|
1139
1305
|
align-items: center;
|
|
1140
1306
|
width: var(--race-data-banner-width);
|
|
1307
|
+
max-width: calc(100% - 1.5rem);
|
|
1308
|
+
min-width: 0;
|
|
1141
1309
|
min-height: 104px;
|
|
1142
1310
|
color: var(--text);
|
|
1143
1311
|
background:
|
|
@@ -1187,15 +1355,78 @@
|
|
|
1187
1355
|
|
|
1188
1356
|
.race-data-copy,
|
|
1189
1357
|
.race-data-number,
|
|
1190
|
-
.race-data-link
|
|
1358
|
+
.race-data-link,
|
|
1359
|
+
.race-data-dismiss {
|
|
1191
1360
|
position: relative;
|
|
1192
1361
|
z-index: 1;
|
|
1193
1362
|
}
|
|
1194
1363
|
|
|
1364
|
+
.race-data-dismiss {
|
|
1365
|
+
--race-data-dismiss-icon-color: rgba(244, 247, 251, 0.9);
|
|
1366
|
+
position: absolute;
|
|
1367
|
+
top: 0.44rem;
|
|
1368
|
+
right: 0.48rem;
|
|
1369
|
+
display: grid;
|
|
1370
|
+
place-items: center;
|
|
1371
|
+
width: 0.95rem;
|
|
1372
|
+
height: 0.95rem;
|
|
1373
|
+
padding: 0;
|
|
1374
|
+
overflow: hidden;
|
|
1375
|
+
color: transparent;
|
|
1376
|
+
background: rgba(8, 10, 16, 0.62);
|
|
1377
|
+
border: 1px solid rgba(244, 247, 251, 0.24);
|
|
1378
|
+
border-radius: 999px;
|
|
1379
|
+
font-family: var(--font-mono);
|
|
1380
|
+
font-size: 0;
|
|
1381
|
+
font-weight: 900;
|
|
1382
|
+
line-height: 0;
|
|
1383
|
+
text-transform: none;
|
|
1384
|
+
white-space: nowrap;
|
|
1385
|
+
z-index: 4;
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
.race-data-dismiss::before,
|
|
1389
|
+
.race-data-dismiss::after {
|
|
1390
|
+
content: "";
|
|
1391
|
+
position: absolute;
|
|
1392
|
+
left: 50%;
|
|
1393
|
+
top: 50%;
|
|
1394
|
+
width: 0.48rem;
|
|
1395
|
+
height: 0.1rem;
|
|
1396
|
+
background: var(--race-data-dismiss-icon-color);
|
|
1397
|
+
border-radius: 999px;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
.race-data-dismiss::before {
|
|
1401
|
+
transform: translate(-50%, -50%) rotate(45deg);
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
.race-data-dismiss::after {
|
|
1405
|
+
transform: translate(-50%, -50%) rotate(-45deg);
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
.race-data-dismiss:hover {
|
|
1409
|
+
--race-data-dismiss-icon-color: #fff;
|
|
1410
|
+
color: transparent;
|
|
1411
|
+
border-color: color-mix(in srgb, var(--driver-color, var(--red)) 70%, #ffffff);
|
|
1412
|
+
background: color-mix(in srgb, var(--driver-color, var(--red)) 52%, rgba(8, 10, 16, 0.72));
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
.race-data-dismiss:focus-visible {
|
|
1416
|
+
outline: 2px solid var(--driver-color, var(--red));
|
|
1417
|
+
outline-offset: 2px;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
.race-data-panel--with-telemetry .race-data-dismiss,
|
|
1421
|
+
.race-data-panel.is-radio-mode .race-data-dismiss {
|
|
1422
|
+
z-index: 4;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1195
1425
|
.race-data-copy {
|
|
1196
1426
|
grid-column: 2;
|
|
1197
1427
|
grid-row: 1;
|
|
1198
1428
|
min-width: 0;
|
|
1429
|
+
overflow: hidden;
|
|
1199
1430
|
padding: 0.92rem 1.45rem 0.98rem 0.55rem;
|
|
1200
1431
|
}
|
|
1201
1432
|
|
|
@@ -1223,6 +1454,9 @@
|
|
|
1223
1454
|
|
|
1224
1455
|
.race-data-subtitle {
|
|
1225
1456
|
display: block;
|
|
1457
|
+
overflow: hidden;
|
|
1458
|
+
text-overflow: ellipsis;
|
|
1459
|
+
white-space: nowrap;
|
|
1226
1460
|
margin-top: 0.28rem;
|
|
1227
1461
|
color: rgba(244, 247, 251, 0.72);
|
|
1228
1462
|
font-family: var(--font-mono);
|
|
@@ -1259,7 +1493,7 @@
|
|
|
1259
1493
|
}
|
|
1260
1494
|
|
|
1261
1495
|
.race-data-panel--with-telemetry {
|
|
1262
|
-
grid-template-columns: clamp(6.5rem, 11vw, 8.7rem) minmax(
|
|
1496
|
+
grid-template-columns: clamp(6.5rem, 11vw, 8.7rem) minmax(0, 1fr) minmax(150px, 0.48fr) auto;
|
|
1263
1497
|
min-height: 112px;
|
|
1264
1498
|
}
|
|
1265
1499
|
|
|
@@ -1308,7 +1542,7 @@
|
|
|
1308
1542
|
}
|
|
1309
1543
|
|
|
1310
1544
|
.race-data-panel.is-radio-mode {
|
|
1311
|
-
grid-template-columns: minmax(
|
|
1545
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1312
1546
|
}
|
|
1313
1547
|
|
|
1314
1548
|
.race-data-panel.is-radio-mode .race-data-copy {
|
|
@@ -1360,9 +1594,13 @@
|
|
|
1360
1594
|
place-items: center;
|
|
1361
1595
|
align-self: center;
|
|
1362
1596
|
min-width: clamp(132px, 13vw, 176px);
|
|
1597
|
+
max-width: calc(100% - 0.85rem);
|
|
1363
1598
|
min-height: 3.1rem;
|
|
1364
1599
|
margin-right: 0.85rem;
|
|
1365
1600
|
padding: 0 1.05rem;
|
|
1601
|
+
overflow: hidden;
|
|
1602
|
+
text-overflow: ellipsis;
|
|
1603
|
+
white-space: nowrap;
|
|
1366
1604
|
color: #f6f8fb;
|
|
1367
1605
|
background: color-mix(in srgb, var(--driver-color, var(--red)) 88%, #111318);
|
|
1368
1606
|
border: 1px solid color-mix(in srgb, var(--driver-color, var(--red)) 72%, #ffffff);
|
|
@@ -1382,6 +1620,9 @@
|
|
|
1382
1620
|
|
|
1383
1621
|
.telemetry-grid dt {
|
|
1384
1622
|
display: block;
|
|
1623
|
+
min-width: 0;
|
|
1624
|
+
overflow: hidden;
|
|
1625
|
+
text-overflow: ellipsis;
|
|
1385
1626
|
margin-bottom: 0.22rem;
|
|
1386
1627
|
color: var(--muted);
|
|
1387
1628
|
font-family: var(--font-mono);
|
|
@@ -1392,6 +1633,10 @@
|
|
|
1392
1633
|
}
|
|
1393
1634
|
|
|
1394
1635
|
.telemetry-grid dd {
|
|
1636
|
+
min-width: 0;
|
|
1637
|
+
overflow: hidden;
|
|
1638
|
+
text-overflow: ellipsis;
|
|
1639
|
+
white-space: nowrap;
|
|
1395
1640
|
margin: 0;
|
|
1396
1641
|
font-family: var(--font-mono);
|
|
1397
1642
|
font-size: clamp(0.86rem, 1.6vw, 1.15rem);
|
|
@@ -1417,9 +1662,10 @@
|
|
|
1417
1662
|
}
|
|
1418
1663
|
|
|
1419
1664
|
.telemetry-grid > div {
|
|
1665
|
+
min-width: 0;
|
|
1420
1666
|
display: flex;
|
|
1421
1667
|
justify-content: space-between;
|
|
1422
|
-
gap:
|
|
1668
|
+
gap: 0.55rem;
|
|
1423
1669
|
padding: 0.82rem 0.7rem;
|
|
1424
1670
|
background: var(--surface-panel);
|
|
1425
1671
|
}
|
|
@@ -1621,6 +1867,8 @@
|
|
|
1621
1867
|
.telemetry-lap-table,
|
|
1622
1868
|
.telemetry-sector-table {
|
|
1623
1869
|
width: 100%;
|
|
1870
|
+
min-width: 0;
|
|
1871
|
+
table-layout: fixed;
|
|
1624
1872
|
border-collapse: collapse;
|
|
1625
1873
|
overflow: hidden;
|
|
1626
1874
|
background: rgba(255, 255, 255, 0.045);
|
|
@@ -1641,10 +1889,13 @@
|
|
|
1641
1889
|
.telemetry-lap-table td,
|
|
1642
1890
|
.telemetry-sector-table th,
|
|
1643
1891
|
.telemetry-sector-table td {
|
|
1892
|
+
overflow: hidden;
|
|
1644
1893
|
padding: 0.55rem 0.5rem;
|
|
1645
1894
|
font-size: 0.68rem;
|
|
1646
1895
|
line-height: 1;
|
|
1647
1896
|
text-align: right;
|
|
1897
|
+
text-overflow: ellipsis;
|
|
1898
|
+
white-space: nowrap;
|
|
1648
1899
|
}
|
|
1649
1900
|
|
|
1650
1901
|
.telemetry-lap-table th,
|
|
@@ -2202,6 +2453,13 @@
|
|
|
2202
2453
|
min-height: 48px;
|
|
2203
2454
|
}
|
|
2204
2455
|
|
|
2456
|
+
.race-data-dismiss {
|
|
2457
|
+
top: 0.38rem;
|
|
2458
|
+
right: 0.42rem;
|
|
2459
|
+
width: 0.95rem;
|
|
2460
|
+
height: 0.95rem;
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2205
2463
|
.sim-telemetry {
|
|
2206
2464
|
display: block;
|
|
2207
2465
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { createLoadingMarkup } from './templateUtils.js';
|
|
2
|
+
|
|
3
|
+
export function createStewardMessageMarkup() {
|
|
4
|
+
return `
|
|
5
|
+
<div class="steward-message is-hidden" data-paddock-component="steward-message" data-steward-message aria-live="polite">
|
|
6
|
+
<span class="steward-message__kicker" data-steward-message-kicker>Race control</span>
|
|
7
|
+
<strong data-steward-message-title>--</strong>
|
|
8
|
+
<span data-steward-message-detail>--</span>
|
|
9
|
+
</div>
|
|
10
|
+
`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createRaceDataPanelMarkup({ ui = {} } = {}) {
|
|
14
|
+
const sizeMode = ui.raceDataBannerSize === 'auto' ? 'auto' : 'custom';
|
|
15
|
+
const telemetryDetail = Boolean(ui.raceDataTelemetryDetail);
|
|
16
|
+
const classNames = ['race-data-panel', `race-data-panel--${sizeMode}`];
|
|
17
|
+
if (telemetryDetail) classNames.push('race-data-panel--with-telemetry');
|
|
18
|
+
return `
|
|
19
|
+
<div class="${classNames.join(' ')}" data-paddock-component="race-data-panel" data-race-data-panel aria-live="polite">
|
|
20
|
+
<button class="race-data-dismiss" type="button" data-race-data-dismiss aria-label="Close race data pill">x</button>
|
|
21
|
+
<div class="race-data-copy">
|
|
22
|
+
<span class="race-data-kicker" data-race-data-kicker>Project</span>
|
|
23
|
+
<strong data-race-data-title>Select driver</strong>
|
|
24
|
+
<span class="race-data-subtitle" data-race-data-subtitle>Race entry</span>
|
|
25
|
+
</div>
|
|
26
|
+
${telemetryDetail ? createRaceDataTelemetryMarkup() : ''}
|
|
27
|
+
<strong class="race-data-number" data-race-data-number>--</strong>
|
|
28
|
+
<button class="race-data-link" type="button" data-race-data-open>Open project</button>
|
|
29
|
+
${createLoadingMarkup('Race data')}
|
|
30
|
+
</div>
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function createRaceDataTelemetryMarkup() {
|
|
35
|
+
return `
|
|
36
|
+
<div class="race-data-telemetry" data-race-data-telemetry aria-label="Project sector telemetry">
|
|
37
|
+
<span class="race-data-telemetry__label">Sectors</span>
|
|
38
|
+
<div class="race-data-telemetry__bars">
|
|
39
|
+
${[1, 2, 3].map((sector) => `
|
|
40
|
+
<div class="telemetry-sector-bar race-data-sector-bar" data-telemetry-sector-bar="${sector}" style="--sector-fill: 0%">
|
|
41
|
+
<span>S${sector}</span>
|
|
42
|
+
<strong data-telemetry-sector-time="${sector}">--</strong>
|
|
43
|
+
</div>
|
|
44
|
+
`).join('')}
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function createTelemetrySectorBannerMarkup() {
|
|
51
|
+
return `
|
|
52
|
+
<section class="telemetry-sector-banner" data-paddock-component="telemetry-sector-banner" data-telemetry-sector-banner aria-label="Broadcast sector telemetry">
|
|
53
|
+
<div class="telemetry-sector-banner__copy">
|
|
54
|
+
<span><b data-selected-code>--</b> sector telemetry</span>
|
|
55
|
+
<strong data-selected-name>Select driver</strong>
|
|
56
|
+
<em data-telemetry-current-sector>S1</em>
|
|
57
|
+
</div>
|
|
58
|
+
<div class="telemetry-sector-banner__bars">
|
|
59
|
+
${[1, 2, 3].map((sector) => `
|
|
60
|
+
<div class="telemetry-sector-bar" data-telemetry-sector-bar="${sector}" style="--sector-fill: 0%">
|
|
61
|
+
<span>S${sector}</span>
|
|
62
|
+
<strong data-telemetry-sector-time="${sector}">--</strong>
|
|
63
|
+
</div>
|
|
64
|
+
`).join('')}
|
|
65
|
+
</div>
|
|
66
|
+
${createLoadingMarkup('Sector banner')}
|
|
67
|
+
</section>
|
|
68
|
+
`;
|
|
69
|
+
}
|