blob: 230bfec06321b1d0ca65981de2d33586ddd5ee97 [file] [log] [blame]
Philipp Schrader817cce32022-03-26 15:00:00 -07001import {
2 Component,
3 ElementRef,
4 EventEmitter,
5 Input,
6 OnInit,
7 Output,
8 ViewChild,
9} from '@angular/core';
Ravago Jones2813c032022-03-16 23:44:11 -070010import {FormsModule} from '@angular/forms';
James Kuszmauldac091f2022-03-22 09:35:06 -070011import {Builder, ByteBuffer} from 'flatbuffers';
Philipp Schradere5d13942024-03-17 15:44:35 -070012import {ErrorResponse} from '@org_frc971/scouting/webserver/requests/messages/error_response_generated';
Philipp Schrader817cce32022-03-26 15:00:00 -070013import {
Filip Kujawa0ef334c2023-02-20 19:42:45 -080014 StartMatchAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070015 StartMatchActionT,
Emily Markovaf17f2812024-04-03 20:55:12 -070016 NoShowActionT,
17 NoShowAction,
Emily Markovadcadcb62024-02-03 13:07:17 -080018 ScoreType,
19 StageType,
20 Submit2024Actions,
Filip Kujawa0b4b1e52023-04-15 14:05:40 -070021 MobilityAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070022 MobilityActionT,
Emily Markovadcadcb62024-02-03 13:07:17 -080023 PenaltyAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070024 PenaltyActionT,
Emily Markovadcadcb62024-02-03 13:07:17 -080025 PickupNoteAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070026 PickupNoteActionT,
Emily Markovadcadcb62024-02-03 13:07:17 -080027 PlaceNoteAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070028 PlaceNoteActionT,
Filip Kujawa0ef334c2023-02-20 19:42:45 -080029 RobotDeathAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070030 RobotDeathActionT,
Filip Kujawa0ef334c2023-02-20 19:42:45 -080031 EndMatchAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070032 EndMatchActionT,
Filip Kujawa0ef334c2023-02-20 19:42:45 -080033 ActionType,
34 Action,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070035 ActionT,
Philipp Schradere5d13942024-03-17 15:44:35 -070036} from '@org_frc971/scouting/webserver/requests/messages/submit_2024_actions_generated';
37import {Match} from '@org_frc971/scouting/webserver/requests/messages/request_all_matches_response_generated';
Philipp Schraderad2a6fb2024-03-20 20:51:36 -070038import {
39 MatchListRequestor,
40 ActionsSubmitter,
41} from '@org_frc971/scouting/www/rpc';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070042import {ActionHelper, ConcreteAction} from './action_helper';
Philipp Schradere2e27ff2024-02-25 22:08:55 -080043import * as pako from 'pako';
Philipp Schrader8b8ed672022-03-05 18:08:50 -080044
Philipp Schrader817cce32022-03-26 15:00:00 -070045type Section =
46 | 'Team Selection'
Filip Kujawa0ef334c2023-02-20 19:42:45 -080047 | 'Init'
48 | 'Pickup'
49 | 'Place'
50 | 'Endgame'
51 | 'Dead'
Philipp Schrader817cce32022-03-26 15:00:00 -070052 | 'Review and Submit'
Philipp Schradere2e27ff2024-02-25 22:08:55 -080053 | 'QR Code'
Philipp Schrader817cce32022-03-26 15:00:00 -070054 | 'Success';
Philipp Schrader80587432022-03-05 15:41:22 -080055
Emily Markova9c18e9c2024-04-03 20:06:27 -070056type CompType = 'PreScouting' | 'Practice' | 'Regular';
57
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070058// TODO(phil): Deduplicate with match_list.component.ts.
59const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
Philipp Schraderba315da2024-03-17 16:16:50 -070060export type CompLevel = typeof COMP_LEVELS[number];
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070061
62// TODO(phil): Deduplicate with match_list.component.ts.
63const COMP_LEVEL_LABELS: Record<CompLevel, string> = {
64 qm: 'Qualifications',
65 ef: 'Eighth Finals',
66 qf: 'Quarter Finals',
67 sf: 'Semi Finals',
68 f: 'Finals',
69};
70
Philipp Schradere2e27ff2024-02-25 22:08:55 -080071// The maximum number of bytes per QR code. The user can adjust this value to
72// make the QR code contain less information, but easier to scan.
73const QR_CODE_PIECE_SIZES = [150, 300, 450, 600, 750, 900];
74
75// The default index into QR_CODE_PIECE_SIZES.
Philipp Schrader329b55a2024-04-18 09:42:59 -070076const DEFAULT_QR_CODE_PIECE_SIZE_INDEX = QR_CODE_PIECE_SIZES.indexOf(450);
Philipp Schradere2e27ff2024-02-25 22:08:55 -080077
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070078// The actions that are purely used for tracking state. They don't actually
79// have any permanent meaning and will not be saved in the database.
80const STATE_ACTIONS: ActionType[] = [
81 ActionType.EndAutoPhaseAction,
82 ActionType.EndTeleopPhaseAction,
83];
emilym38d08ba2022-10-22 15:25:01 -070084
Philipp Schrader23993e82022-03-18 18:54:00 -070085@Component({
86 selector: 'app-entry',
87 templateUrl: './entry.ng.html',
Philipp Schrader175a93c2023-02-19 13:13:40 -080088 styleUrls: ['../app/common.css', './entry.component.css'],
Philipp Schrader23993e82022-03-18 18:54:00 -070089})
Philipp Schrader75021f52023-04-09 21:14:13 -070090export class EntryComponent implements OnInit {
Philipp Schrader36df73a2022-03-17 23:27:24 -070091 // Re-export the type here so that we can use it in the `[value]` attribute
92 // of radio buttons.
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070093 readonly COMP_LEVELS = COMP_LEVELS;
94 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
Philipp Schradere2e27ff2024-02-25 22:08:55 -080095 readonly QR_CODE_PIECE_SIZES = QR_CODE_PIECE_SIZES;
Emily Markovadcadcb62024-02-03 13:07:17 -080096 readonly ScoreType = ScoreType;
Emily Markova6079e2f2024-02-17 13:17:24 -080097 readonly StageType = StageType;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070098 readonly ActionT = ActionT;
99 readonly ActionType = ActionType;
Emily Markovaf17f2812024-04-03 20:55:12 -0700100 readonly NoShowActionT = NoShowActionT;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700101 readonly StartMatchActionT = StartMatchActionT;
102 readonly MobilityActionT = MobilityActionT;
103 readonly PickupNoteActionT = PickupNoteActionT;
104 readonly PlaceNoteActionT = PlaceNoteActionT;
105 readonly RobotDeathActionT = RobotDeathActionT;
106 readonly PenaltyActionT = PenaltyActionT;
107 readonly EndMatchActionT = EndMatchActionT;
Philipp Schrader36df73a2022-03-17 23:27:24 -0700108
Ravago Jones2813c032022-03-16 23:44:11 -0700109 section: Section = 'Team Selection';
Ravago Jones2813c032022-03-16 23:44:11 -0700110 @Input() matchNumber: number = 1;
Emily Markovae68b7632023-12-30 14:17:55 -0800111 @Input() teamNumber: string = '1';
Philipp Schrader30b4a682022-04-16 14:36:17 -0700112 @Input() setNumber: number = 1;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700113 @Input() compLevel: CompLevel = 'qm';
Emily Markova9c18e9c2024-04-03 20:06:27 -0700114 @Input() compType: CompType = 'Regular';
Philipp Schrader75021f52023-04-09 21:14:13 -0700115 @Input() skipTeamSelection = false;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800116
Philipp Schrader63198402024-03-16 14:19:02 -0700117 @ViewChild('header') header: ElementRef;
118
Philipp Schrader8702b782023-04-15 17:33:37 -0700119 matchList: Match[] = [];
120
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700121 actionHelper: ActionHelper;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800122 actionList: ActionT[] = [];
Philipp Schrader8702b782023-04-15 17:33:37 -0700123 progressMessage: string = '';
Ravago Jones2813c032022-03-16 23:44:11 -0700124 errorMessage: string = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800125 autoPhase: boolean = true;
Filip Kujawab73e94c2023-04-19 09:33:14 -0700126 mobilityCompleted: boolean = false;
Philipp Schraderba315da2024-03-17 16:16:50 -0700127 // TODO(phil): Come up with a better name here.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700128 selectedValue = 0;
Philipp Schraderba315da2024-03-17 16:16:50 -0700129 endGameAction: StageType = StageType.kMISSING;
130 noteIsTrapped: boolean = false;
131 endGameSpotlight: boolean = false;
132
Evelyn Yangc8036b12023-10-11 21:14:46 -0700133 nextTeamNumber = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800134
135 matchStartTimestamp: number = 0;
Emily Markovadcadcb62024-02-03 13:07:17 -0800136 penalties: number = 0;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800137
Philipp Schrader8702b782023-04-15 17:33:37 -0700138 teamSelectionIsValid = false;
139
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800140 // When the user chooses to generate QR codes, we convert the flatbuffer into
141 // a long string. Since we frequently have more data than we can display in a
142 // single QR code, we break the data into multiple QR codes. The data for
143 // each QR code ("pieces") is stored in the `qrCodeValuePieces` list below.
144 // The `qrCodeValueIndex` keeps track of which QR code we're currently
145 // displaying.
146 qrCodeValuePieceSize = QR_CODE_PIECE_SIZES[DEFAULT_QR_CODE_PIECE_SIZE_INDEX];
147 qrCodeValuePieces: string[] = [];
148 qrCodeValueIndex: number = 0;
149
Philipp Schraderad2a6fb2024-03-20 20:51:36 -0700150 constructor(
151 private readonly matchListRequestor: MatchListRequestor,
152 private readonly actionsSubmitter: ActionsSubmitter
153 ) {}
Philipp Schrader8702b782023-04-15 17:33:37 -0700154
Philipp Schrader75021f52023-04-09 21:14:13 -0700155 ngOnInit() {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700156 this.actionHelper = new ActionHelper(
157 (actionType: ActionType, action: ConcreteAction) => {
158 this.addAction(actionType, action);
159 }
160 );
161
Philipp Schrader75021f52023-04-09 21:14:13 -0700162 // When the user navigated from the match list, we can skip the team
163 // selection. I.e. we trust that the user clicked the correct button.
164 this.section = this.skipTeamSelection ? 'Init' : 'Team Selection';
Evelyn Yangc8036b12023-10-11 21:14:46 -0700165 this.fetchMatchList();
166 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700167
Evelyn Yangc8036b12023-10-11 21:14:46 -0700168 goToNextTeam() {
169 this.ngOnInit();
170 this.teamNumber = this.nextTeamNumber;
171 this.nextTeamNumber = '';
Philipp Schrader8702b782023-04-15 17:33:37 -0700172 }
173
174 async fetchMatchList() {
175 this.progressMessage = 'Fetching match list. Please be patient.';
176 this.errorMessage = '';
177
178 try {
179 this.matchList = await this.matchListRequestor.fetchMatchList();
180 this.progressMessage = 'Successfully fetched match list.';
181 } catch (e) {
182 this.errorMessage = e;
183 this.progressMessage = '';
184 }
185 }
186
187 // This gets called when the user changes something on the Init screen.
188 // It makes sure that the user can't click "Next" until the information is
Emily Markova9c18e9c2024-04-03 20:06:27 -0700189 // valid, or this is for pre-scouting or practice matches.
Philipp Schrader8702b782023-04-15 17:33:37 -0700190 updateTeamSelectionValidity(): void {
Emily Markova9c18e9c2024-04-03 20:06:27 -0700191 this.teamSelectionIsValid =
192 this.compType != 'Regular' || this.matchIsInMatchList();
Philipp Schrader8702b782023-04-15 17:33:37 -0700193 }
194
195 matchIsInMatchList(): boolean {
196 // If the user deletes the content of the teamNumber field, the value here
197 // is undefined. Guard against that.
198 if (this.teamNumber == null) {
199 return false;
200 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700201
202 for (const match of this.matchList) {
203 if (
204 this.matchNumber == match.matchNumber() &&
205 this.setNumber == match.setNumber() &&
206 this.compLevel == match.compLevel() &&
Evelyn Yangc8036b12023-10-11 21:14:46 -0700207 (this.teamNumber === match.r1() ||
208 this.teamNumber === match.r2() ||
209 this.teamNumber === match.r3() ||
210 this.teamNumber === match.b1() ||
211 this.teamNumber === match.b2() ||
212 this.teamNumber === match.b3())
Philipp Schrader8702b782023-04-15 17:33:37 -0700213 ) {
214 return true;
215 }
216 }
217 return false;
Philipp Schrader75021f52023-04-09 21:14:13 -0700218 }
219
Emily Markovadcadcb62024-02-03 13:07:17 -0800220 addPenalty(): void {
221 this.penalties += 1;
222 }
223
224 removePenalty(): void {
225 if (this.penalties > 0) {
226 this.penalties -= 1;
227 }
228 }
229
230 addPenalties(): void {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700231 this.actionHelper.addPenaltyAction({penalties: this.penalties});
Emily Markovadcadcb62024-02-03 13:07:17 -0800232 }
233
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700234 addAction(actionType: ActionType, action: ConcreteAction): void {
235 let timestamp: number = 0;
236
237 if (actionType == ActionType.StartMatchAction) {
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800238 // Unix nanosecond timestamp.
239 this.matchStartTimestamp = Date.now() * 1e6;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800240 } else {
241 // Unix nanosecond timestamp relative to match start.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700242 timestamp = Date.now() * 1e6 - this.matchStartTimestamp;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800243 }
244
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700245 if (actionType == ActionType.EndMatchAction) {
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800246 // endMatchAction occurs at the same time as penaltyAction so add to its
247 // timestamp to make it unique.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700248 timestamp += 1;
Emily Markovadcadcb62024-02-03 13:07:17 -0800249 }
250
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700251 if (actionType == ActionType.MobilityAction) {
Filip Kujawab73e94c2023-04-19 09:33:14 -0700252 this.mobilityCompleted = true;
253 }
254
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700255 this.actionList.push(new ActionT(BigInt(timestamp), actionType, action));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800256 }
257
258 undoLastAction() {
259 if (this.actionList.length > 0) {
260 let lastAction = this.actionList.pop();
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700261 switch (lastAction?.actionTakenType) {
262 case ActionType.EndAutoPhaseAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800263 this.autoPhase = true;
Emily Markovadcadcb62024-02-03 13:07:17 -0800264 this.section = 'Pickup';
Philipp Schrader652a4c92024-04-18 10:53:39 -0700265 break;
Emily Markovaf17f2812024-04-03 20:55:12 -0700266 case ActionType.NoShowAction:
267 this.autoPhase = true;
268 this.section = 'Init';
269 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700270 case ActionType.PickupNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800271 this.section = 'Pickup';
272 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700273 case ActionType.EndTeleopPhaseAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800274 this.section = 'Pickup';
275 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700276 case ActionType.PlaceNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800277 this.section = 'Place';
278 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700279 case ActionType.EndMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800280 this.section = 'Endgame';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700281 case ActionType.MobilityAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800282 this.mobilityCompleted = false;
283 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700284 case ActionType.StartMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800285 this.section = 'Init';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800286 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700287 case ActionType.RobotDeathAction:
Filip Kujawa9f56d0e2023-03-03 19:44:43 -0800288 // TODO(FILIP): Return user to the screen they
289 // clicked dead robot on. Pickup is fine for now but
290 // might cause confusion.
291 this.section = 'Pickup';
292 break;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800293 default:
294 break;
295 }
296 }
297 }
298
Emily Markovadcadcb62024-02-03 13:07:17 -0800299 stringifyScoreType(scoreType: ScoreType): String {
300 return ScoreType[scoreType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700301 }
302
Emily Markovadcadcb62024-02-03 13:07:17 -0800303 stringifyStageType(stageType: StageType): String {
304 return StageType[stageType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700305 }
306
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800307 changeSectionTo(target: Section) {
Philipp Schrader8702b782023-04-15 17:33:37 -0700308 // Clear the messages since they won't be relevant in the next section.
309 this.errorMessage = '';
310 this.progressMessage = '';
311
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800312 // For the QR code screen, we need to make the value to encode available.
313 if (target == 'QR Code') {
314 this.updateQrCodeValuePieceSize();
315 }
316
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800317 this.section = target;
318 }
Philipp Schrader80587432022-03-05 15:41:22 -0800319
Ravago Jones2813c032022-03-16 23:44:11 -0700320 private scrollToTop() {
321 this.header.nativeElement.scrollIntoView();
322 }
323
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800324 createActionsBuffer() {
James Kuszmauldac091f2022-03-22 09:35:06 -0700325 const builder = new Builder();
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800326 const actionOffsets: number[] = [];
327
328 for (const action of this.actionList) {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700329 if (STATE_ACTIONS.includes(action.actionTakenType)) {
330 // Actions only used for undo purposes are not submitted.
331 continue;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800332 }
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700333 actionOffsets.push(action.pack(builder));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800334 }
Emily Markovae68b7632023-12-30 14:17:55 -0800335 const teamNumberFb = builder.createString(this.teamNumber);
Philipp Schradere859e6e2023-03-22 19:59:51 -0700336 const compLevelFb = builder.createString(this.compLevel);
Emily Markova9c18e9c2024-04-03 20:06:27 -0700337 const compTypeFb = builder.createString(this.compType);
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800338
Emily Markovadcadcb62024-02-03 13:07:17 -0800339 const actionsVector = Submit2024Actions.createActionsListVector(
Philipp Schrader817cce32022-03-26 15:00:00 -0700340 builder,
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800341 actionOffsets
Philipp Schrader817cce32022-03-26 15:00:00 -0700342 );
Emily Markovadcadcb62024-02-03 13:07:17 -0800343 Submit2024Actions.startSubmit2024Actions(builder);
344 Submit2024Actions.addTeamNumber(builder, teamNumberFb);
345 Submit2024Actions.addMatchNumber(builder, this.matchNumber);
346 Submit2024Actions.addSetNumber(builder, this.setNumber);
347 Submit2024Actions.addCompLevel(builder, compLevelFb);
348 Submit2024Actions.addActionsList(builder, actionsVector);
Emily Markova9c18e9c2024-04-03 20:06:27 -0700349 Submit2024Actions.addCompType(builder, compTypeFb);
Emily Markovadcadcb62024-02-03 13:07:17 -0800350 builder.finish(Submit2024Actions.endSubmit2024Actions(builder));
Ravago Jones2813c032022-03-16 23:44:11 -0700351
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800352 return builder.asUint8Array();
353 }
354
355 // Same as createActionsBuffer, but encoded as Base64. It's also split into
356 // a number of pieces so that each piece is roughly limited to
357 // `qrCodeValuePieceSize` bytes.
358 createBase64ActionsBuffers(): string[] {
359 const originalBuffer = this.createActionsBuffer();
360 const deflatedData = pako.deflate(originalBuffer, {level: 9});
361
362 const pieceSize = this.qrCodeValuePieceSize;
363 const fullValue = btoa(String.fromCharCode(...deflatedData));
364 const numPieces = Math.ceil(fullValue.length / pieceSize);
365
366 let splitData: string[] = [];
367 for (let i = 0; i < numPieces; i++) {
368 const splitPiece = fullValue.slice(i * pieceSize, (i + 1) * pieceSize);
369 splitData.push(`${i}_${numPieces}_${pieceSize}_${splitPiece}`);
370 }
371 return splitData;
372 }
373
374 setQrCodeValueIndex(index: number) {
375 this.qrCodeValueIndex = Math.max(
376 0,
377 Math.min(index, this.qrCodeValuePieces.length - 1)
378 );
379 }
380
381 updateQrCodeValuePieceSize() {
382 this.qrCodeValuePieces = this.createBase64ActionsBuffers();
383 this.qrCodeValueIndex = 0;
384 }
385
386 async submit2024Actions() {
Philipp Schraderad2a6fb2024-03-20 20:51:36 -0700387 const res = await this.actionsSubmitter.submit(this.createActionsBuffer());
Ravago Jones2813c032022-03-16 23:44:11 -0700388
389 if (res.ok) {
390 // We successfully submitted the data. Report success.
391 this.section = 'Success';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800392 this.actionList = [];
Evelyn Yangc8036b12023-10-11 21:14:46 -0700393
Philipp Schrader63198402024-03-16 14:19:02 -0700394 // Keep track of the position of the last robot, use to figure out what
395 // the next robot in the same position is.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700396 let lastTeamPos = '0';
397 for (const match of this.matchList) {
398 if (
399 this.matchNumber === match.matchNumber() &&
400 this.setNumber === match.setNumber() &&
401 this.compLevel === match.compLevel()
402 ) {
403 this.teamNumber = this.teamNumber;
404 if (this.teamNumber == match.r1()) {
405 lastTeamPos = 'r1';
406 } else if (this.teamNumber == match.r2()) {
407 lastTeamPos = 'r2';
408 } else if (this.teamNumber == match.r3()) {
409 lastTeamPos = 'r3';
410 } else if (this.teamNumber == match.b1()) {
411 lastTeamPos = 'b1';
412 } else if (this.teamNumber == match.b2()) {
413 lastTeamPos = 'b2';
414 } else if (this.teamNumber == match.b3()) {
415 lastTeamPos = 'b3';
416 } else {
417 console.log('Position of scouted team not found.');
418 }
419 break;
420 }
421 }
422 if (lastTeamPos != '0') {
423 this.matchNumber += 1;
424 for (const match of this.matchList) {
425 if (
426 this.matchNumber == match.matchNumber() &&
427 this.setNumber == match.setNumber() &&
428 this.compLevel == match.compLevel()
429 ) {
430 if (lastTeamPos == 'r1') {
431 this.nextTeamNumber = match.r1();
432 } else if (lastTeamPos == 'r2') {
433 this.nextTeamNumber = match.r2();
434 } else if (lastTeamPos == 'r3') {
435 this.nextTeamNumber = match.r3();
436 } else if (lastTeamPos == 'b1') {
437 this.nextTeamNumber = match.b1();
438 } else if (lastTeamPos == 'b2') {
439 this.nextTeamNumber = match.b2();
440 } else if (lastTeamPos == 'b3') {
441 this.nextTeamNumber = match.b3();
442 } else {
443 console.log('Position of last team not found.');
444 }
445 break;
446 }
447 }
448 } else {
449 console.log('Last team position not found.');
450 }
451 this.matchList = [];
452 this.progressMessage = '';
453 this.errorMessage = '';
454 this.autoPhase = true;
455 this.actionList = [];
456 this.mobilityCompleted = false;
Emily Markova9c18e9c2024-04-03 20:06:27 -0700457 this.compType = 'Regular';
Evelyn Yangc8036b12023-10-11 21:14:46 -0700458 this.matchStartTimestamp = 0;
459 this.selectedValue = 0;
Ravago Jones2813c032022-03-16 23:44:11 -0700460 } else {
461 const resBuffer = await res.arrayBuffer();
462 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
James Kuszmauldac091f2022-03-22 09:35:06 -0700463 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
Ravago Jones2813c032022-03-16 23:44:11 -0700464
465 const errorMessage = parsedResponse.errorMessage();
Philipp Schrader817cce32022-03-26 15:00:00 -0700466 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
Alex Perrybb3d2062022-03-05 18:14:33 -0800467 }
Ravago Jones2813c032022-03-16 23:44:11 -0700468 }
Philipp Schrader80587432022-03-05 15:41:22 -0800469}