blob: 98c9311898a6e8a4bf948a62dd751952c538ad79 [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 Markovadcadcb62024-02-03 13:07:17 -080016 ScoreType,
17 StageType,
18 Submit2024Actions,
Filip Kujawa0b4b1e52023-04-15 14:05:40 -070019 MobilityAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070020 MobilityActionT,
Emily Markovadcadcb62024-02-03 13:07:17 -080021 PenaltyAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070022 PenaltyActionT,
Emily Markovadcadcb62024-02-03 13:07:17 -080023 PickupNoteAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070024 PickupNoteActionT,
Emily Markovadcadcb62024-02-03 13:07:17 -080025 PlaceNoteAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070026 PlaceNoteActionT,
Filip Kujawa0ef334c2023-02-20 19:42:45 -080027 RobotDeathAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070028 RobotDeathActionT,
Filip Kujawa0ef334c2023-02-20 19:42:45 -080029 EndMatchAction,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070030 EndMatchActionT,
Filip Kujawa0ef334c2023-02-20 19:42:45 -080031 ActionType,
32 Action,
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070033 ActionT,
Philipp Schradere5d13942024-03-17 15:44:35 -070034} from '@org_frc971/scouting/webserver/requests/messages/submit_2024_actions_generated';
35import {Match} from '@org_frc971/scouting/webserver/requests/messages/request_all_matches_response_generated';
Philipp Schraderad2a6fb2024-03-20 20:51:36 -070036import {
37 MatchListRequestor,
38 ActionsSubmitter,
39} from '@org_frc971/scouting/www/rpc';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070040import {ActionHelper, ConcreteAction} from './action_helper';
Philipp Schradere2e27ff2024-02-25 22:08:55 -080041import * as pako from 'pako';
Philipp Schrader8b8ed672022-03-05 18:08:50 -080042
Philipp Schrader817cce32022-03-26 15:00:00 -070043type Section =
44 | 'Team Selection'
Filip Kujawa0ef334c2023-02-20 19:42:45 -080045 | 'Init'
46 | 'Pickup'
47 | 'Place'
48 | 'Endgame'
49 | 'Dead'
Philipp Schrader817cce32022-03-26 15:00:00 -070050 | 'Review and Submit'
Philipp Schradere2e27ff2024-02-25 22:08:55 -080051 | 'QR Code'
Philipp Schrader817cce32022-03-26 15:00:00 -070052 | 'Success';
Philipp Schrader80587432022-03-05 15:41:22 -080053
Emily Markova9c18e9c2024-04-03 20:06:27 -070054type CompType = 'PreScouting' | 'Practice' | 'Regular';
55
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070056// TODO(phil): Deduplicate with match_list.component.ts.
57const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
Philipp Schraderba315da2024-03-17 16:16:50 -070058export type CompLevel = typeof COMP_LEVELS[number];
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070059
60// TODO(phil): Deduplicate with match_list.component.ts.
61const COMP_LEVEL_LABELS: Record<CompLevel, string> = {
62 qm: 'Qualifications',
63 ef: 'Eighth Finals',
64 qf: 'Quarter Finals',
65 sf: 'Semi Finals',
66 f: 'Finals',
67};
68
Philipp Schradere2e27ff2024-02-25 22:08:55 -080069// The maximum number of bytes per QR code. The user can adjust this value to
70// make the QR code contain less information, but easier to scan.
71const QR_CODE_PIECE_SIZES = [150, 300, 450, 600, 750, 900];
72
73// The default index into QR_CODE_PIECE_SIZES.
74const DEFAULT_QR_CODE_PIECE_SIZE_INDEX = QR_CODE_PIECE_SIZES.indexOf(750);
75
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070076// The actions that are purely used for tracking state. They don't actually
77// have any permanent meaning and will not be saved in the database.
78const STATE_ACTIONS: ActionType[] = [
79 ActionType.EndAutoPhaseAction,
80 ActionType.EndTeleopPhaseAction,
81];
emilym38d08ba2022-10-22 15:25:01 -070082
Philipp Schrader23993e82022-03-18 18:54:00 -070083@Component({
84 selector: 'app-entry',
85 templateUrl: './entry.ng.html',
Philipp Schrader175a93c2023-02-19 13:13:40 -080086 styleUrls: ['../app/common.css', './entry.component.css'],
Philipp Schrader23993e82022-03-18 18:54:00 -070087})
Philipp Schrader75021f52023-04-09 21:14:13 -070088export class EntryComponent implements OnInit {
Philipp Schrader36df73a2022-03-17 23:27:24 -070089 // Re-export the type here so that we can use it in the `[value]` attribute
90 // of radio buttons.
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070091 readonly COMP_LEVELS = COMP_LEVELS;
92 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
Philipp Schradere2e27ff2024-02-25 22:08:55 -080093 readonly QR_CODE_PIECE_SIZES = QR_CODE_PIECE_SIZES;
Emily Markovadcadcb62024-02-03 13:07:17 -080094 readonly ScoreType = ScoreType;
Emily Markova6079e2f2024-02-17 13:17:24 -080095 readonly StageType = StageType;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070096 readonly ActionT = ActionT;
97 readonly ActionType = ActionType;
98 readonly StartMatchActionT = StartMatchActionT;
99 readonly MobilityActionT = MobilityActionT;
100 readonly PickupNoteActionT = PickupNoteActionT;
101 readonly PlaceNoteActionT = PlaceNoteActionT;
102 readonly RobotDeathActionT = RobotDeathActionT;
103 readonly PenaltyActionT = PenaltyActionT;
104 readonly EndMatchActionT = EndMatchActionT;
Philipp Schrader36df73a2022-03-17 23:27:24 -0700105
Ravago Jones2813c032022-03-16 23:44:11 -0700106 section: Section = 'Team Selection';
Ravago Jones2813c032022-03-16 23:44:11 -0700107 @Input() matchNumber: number = 1;
Emily Markovae68b7632023-12-30 14:17:55 -0800108 @Input() teamNumber: string = '1';
Philipp Schrader30b4a682022-04-16 14:36:17 -0700109 @Input() setNumber: number = 1;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700110 @Input() compLevel: CompLevel = 'qm';
Emily Markova9c18e9c2024-04-03 20:06:27 -0700111 @Input() compType: CompType = 'Regular';
Philipp Schrader75021f52023-04-09 21:14:13 -0700112 @Input() skipTeamSelection = false;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800113
Philipp Schrader63198402024-03-16 14:19:02 -0700114 @ViewChild('header') header: ElementRef;
115
Philipp Schrader8702b782023-04-15 17:33:37 -0700116 matchList: Match[] = [];
117
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700118 actionHelper: ActionHelper;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800119 actionList: ActionT[] = [];
Philipp Schrader8702b782023-04-15 17:33:37 -0700120 progressMessage: string = '';
Ravago Jones2813c032022-03-16 23:44:11 -0700121 errorMessage: string = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800122 autoPhase: boolean = true;
Filip Kujawab73e94c2023-04-19 09:33:14 -0700123 mobilityCompleted: boolean = false;
Philipp Schraderba315da2024-03-17 16:16:50 -0700124 // TODO(phil): Come up with a better name here.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700125 selectedValue = 0;
Philipp Schraderba315da2024-03-17 16:16:50 -0700126 endGameAction: StageType = StageType.kMISSING;
127 noteIsTrapped: boolean = false;
128 endGameSpotlight: boolean = false;
129
Evelyn Yangc8036b12023-10-11 21:14:46 -0700130 nextTeamNumber = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800131
132 matchStartTimestamp: number = 0;
Emily Markovadcadcb62024-02-03 13:07:17 -0800133 penalties: number = 0;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800134
Philipp Schrader8702b782023-04-15 17:33:37 -0700135 teamSelectionIsValid = false;
136
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800137 // When the user chooses to generate QR codes, we convert the flatbuffer into
138 // a long string. Since we frequently have more data than we can display in a
139 // single QR code, we break the data into multiple QR codes. The data for
140 // each QR code ("pieces") is stored in the `qrCodeValuePieces` list below.
141 // The `qrCodeValueIndex` keeps track of which QR code we're currently
142 // displaying.
143 qrCodeValuePieceSize = QR_CODE_PIECE_SIZES[DEFAULT_QR_CODE_PIECE_SIZE_INDEX];
144 qrCodeValuePieces: string[] = [];
145 qrCodeValueIndex: number = 0;
146
Philipp Schraderad2a6fb2024-03-20 20:51:36 -0700147 constructor(
148 private readonly matchListRequestor: MatchListRequestor,
149 private readonly actionsSubmitter: ActionsSubmitter
150 ) {}
Philipp Schrader8702b782023-04-15 17:33:37 -0700151
Philipp Schrader75021f52023-04-09 21:14:13 -0700152 ngOnInit() {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700153 this.actionHelper = new ActionHelper(
154 (actionType: ActionType, action: ConcreteAction) => {
155 this.addAction(actionType, action);
156 }
157 );
158
Philipp Schrader75021f52023-04-09 21:14:13 -0700159 // When the user navigated from the match list, we can skip the team
160 // selection. I.e. we trust that the user clicked the correct button.
161 this.section = this.skipTeamSelection ? 'Init' : 'Team Selection';
Evelyn Yangc8036b12023-10-11 21:14:46 -0700162 this.fetchMatchList();
163 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700164
Evelyn Yangc8036b12023-10-11 21:14:46 -0700165 goToNextTeam() {
166 this.ngOnInit();
167 this.teamNumber = this.nextTeamNumber;
168 this.nextTeamNumber = '';
Philipp Schrader8702b782023-04-15 17:33:37 -0700169 }
170
171 async fetchMatchList() {
172 this.progressMessage = 'Fetching match list. Please be patient.';
173 this.errorMessage = '';
174
175 try {
176 this.matchList = await this.matchListRequestor.fetchMatchList();
177 this.progressMessage = 'Successfully fetched match list.';
178 } catch (e) {
179 this.errorMessage = e;
180 this.progressMessage = '';
181 }
182 }
183
184 // This gets called when the user changes something on the Init screen.
185 // It makes sure that the user can't click "Next" until the information is
Emily Markova9c18e9c2024-04-03 20:06:27 -0700186 // valid, or this is for pre-scouting or practice matches.
Philipp Schrader8702b782023-04-15 17:33:37 -0700187 updateTeamSelectionValidity(): void {
Emily Markova9c18e9c2024-04-03 20:06:27 -0700188 this.teamSelectionIsValid =
189 this.compType != 'Regular' || this.matchIsInMatchList();
Philipp Schrader8702b782023-04-15 17:33:37 -0700190 }
191
192 matchIsInMatchList(): boolean {
193 // If the user deletes the content of the teamNumber field, the value here
194 // is undefined. Guard against that.
195 if (this.teamNumber == null) {
196 return false;
197 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700198
199 for (const match of this.matchList) {
200 if (
201 this.matchNumber == match.matchNumber() &&
202 this.setNumber == match.setNumber() &&
203 this.compLevel == match.compLevel() &&
Evelyn Yangc8036b12023-10-11 21:14:46 -0700204 (this.teamNumber === match.r1() ||
205 this.teamNumber === match.r2() ||
206 this.teamNumber === match.r3() ||
207 this.teamNumber === match.b1() ||
208 this.teamNumber === match.b2() ||
209 this.teamNumber === match.b3())
Philipp Schrader8702b782023-04-15 17:33:37 -0700210 ) {
211 return true;
212 }
213 }
214 return false;
Philipp Schrader75021f52023-04-09 21:14:13 -0700215 }
216
Emily Markovadcadcb62024-02-03 13:07:17 -0800217 addPenalty(): void {
218 this.penalties += 1;
219 }
220
221 removePenalty(): void {
222 if (this.penalties > 0) {
223 this.penalties -= 1;
224 }
225 }
226
227 addPenalties(): void {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700228 this.actionHelper.addPenaltyAction({penalties: this.penalties});
Emily Markovadcadcb62024-02-03 13:07:17 -0800229 }
230
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700231 addAction(actionType: ActionType, action: ConcreteAction): void {
232 let timestamp: number = 0;
233
234 if (actionType == ActionType.StartMatchAction) {
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800235 // Unix nanosecond timestamp.
236 this.matchStartTimestamp = Date.now() * 1e6;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800237 } else {
238 // Unix nanosecond timestamp relative to match start.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700239 timestamp = Date.now() * 1e6 - this.matchStartTimestamp;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800240 }
241
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700242 if (actionType == ActionType.EndMatchAction) {
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800243 // endMatchAction occurs at the same time as penaltyAction so add to its
244 // timestamp to make it unique.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700245 timestamp += 1;
Emily Markovadcadcb62024-02-03 13:07:17 -0800246 }
247
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700248 if (actionType == ActionType.MobilityAction) {
Filip Kujawab73e94c2023-04-19 09:33:14 -0700249 this.mobilityCompleted = true;
250 }
251
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700252 this.actionList.push(new ActionT(BigInt(timestamp), actionType, action));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800253 }
254
255 undoLastAction() {
256 if (this.actionList.length > 0) {
257 let lastAction = this.actionList.pop();
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700258 switch (lastAction?.actionTakenType) {
259 case ActionType.EndAutoPhaseAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800260 this.autoPhase = true;
Emily Markovadcadcb62024-02-03 13:07:17 -0800261 this.section = 'Pickup';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700262 case ActionType.PickupNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800263 this.section = 'Pickup';
264 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700265 case ActionType.EndTeleopPhaseAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800266 this.section = 'Pickup';
267 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700268 case ActionType.PlaceNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800269 this.section = 'Place';
270 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700271 case ActionType.EndMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800272 this.section = 'Endgame';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700273 case ActionType.MobilityAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800274 this.mobilityCompleted = false;
275 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700276 case ActionType.StartMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800277 this.section = 'Init';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800278 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700279 case ActionType.RobotDeathAction:
Filip Kujawa9f56d0e2023-03-03 19:44:43 -0800280 // TODO(FILIP): Return user to the screen they
281 // clicked dead robot on. Pickup is fine for now but
282 // might cause confusion.
283 this.section = 'Pickup';
284 break;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800285 default:
286 break;
287 }
288 }
289 }
290
Emily Markovadcadcb62024-02-03 13:07:17 -0800291 stringifyScoreType(scoreType: ScoreType): String {
292 return ScoreType[scoreType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700293 }
294
Emily Markovadcadcb62024-02-03 13:07:17 -0800295 stringifyStageType(stageType: StageType): String {
296 return StageType[stageType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700297 }
298
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800299 changeSectionTo(target: Section) {
Philipp Schrader8702b782023-04-15 17:33:37 -0700300 // Clear the messages since they won't be relevant in the next section.
301 this.errorMessage = '';
302 this.progressMessage = '';
303
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800304 // For the QR code screen, we need to make the value to encode available.
305 if (target == 'QR Code') {
306 this.updateQrCodeValuePieceSize();
307 }
308
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800309 this.section = target;
310 }
Philipp Schrader80587432022-03-05 15:41:22 -0800311
Ravago Jones2813c032022-03-16 23:44:11 -0700312 private scrollToTop() {
313 this.header.nativeElement.scrollIntoView();
314 }
315
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800316 createActionsBuffer() {
James Kuszmauldac091f2022-03-22 09:35:06 -0700317 const builder = new Builder();
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800318 const actionOffsets: number[] = [];
319
320 for (const action of this.actionList) {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700321 if (STATE_ACTIONS.includes(action.actionTakenType)) {
322 // Actions only used for undo purposes are not submitted.
323 continue;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800324 }
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700325 actionOffsets.push(action.pack(builder));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800326 }
Emily Markovae68b7632023-12-30 14:17:55 -0800327 const teamNumberFb = builder.createString(this.teamNumber);
Philipp Schradere859e6e2023-03-22 19:59:51 -0700328 const compLevelFb = builder.createString(this.compLevel);
Emily Markova9c18e9c2024-04-03 20:06:27 -0700329 const compTypeFb = builder.createString(this.compType);
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800330
Emily Markovadcadcb62024-02-03 13:07:17 -0800331 const actionsVector = Submit2024Actions.createActionsListVector(
Philipp Schrader817cce32022-03-26 15:00:00 -0700332 builder,
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800333 actionOffsets
Philipp Schrader817cce32022-03-26 15:00:00 -0700334 );
Emily Markovadcadcb62024-02-03 13:07:17 -0800335 Submit2024Actions.startSubmit2024Actions(builder);
336 Submit2024Actions.addTeamNumber(builder, teamNumberFb);
337 Submit2024Actions.addMatchNumber(builder, this.matchNumber);
338 Submit2024Actions.addSetNumber(builder, this.setNumber);
339 Submit2024Actions.addCompLevel(builder, compLevelFb);
340 Submit2024Actions.addActionsList(builder, actionsVector);
Emily Markova9c18e9c2024-04-03 20:06:27 -0700341 Submit2024Actions.addCompType(builder, compTypeFb);
Emily Markovadcadcb62024-02-03 13:07:17 -0800342 builder.finish(Submit2024Actions.endSubmit2024Actions(builder));
Ravago Jones2813c032022-03-16 23:44:11 -0700343
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800344 return builder.asUint8Array();
345 }
346
347 // Same as createActionsBuffer, but encoded as Base64. It's also split into
348 // a number of pieces so that each piece is roughly limited to
349 // `qrCodeValuePieceSize` bytes.
350 createBase64ActionsBuffers(): string[] {
351 const originalBuffer = this.createActionsBuffer();
352 const deflatedData = pako.deflate(originalBuffer, {level: 9});
353
354 const pieceSize = this.qrCodeValuePieceSize;
355 const fullValue = btoa(String.fromCharCode(...deflatedData));
356 const numPieces = Math.ceil(fullValue.length / pieceSize);
357
358 let splitData: string[] = [];
359 for (let i = 0; i < numPieces; i++) {
360 const splitPiece = fullValue.slice(i * pieceSize, (i + 1) * pieceSize);
361 splitData.push(`${i}_${numPieces}_${pieceSize}_${splitPiece}`);
362 }
363 return splitData;
364 }
365
366 setQrCodeValueIndex(index: number) {
367 this.qrCodeValueIndex = Math.max(
368 0,
369 Math.min(index, this.qrCodeValuePieces.length - 1)
370 );
371 }
372
373 updateQrCodeValuePieceSize() {
374 this.qrCodeValuePieces = this.createBase64ActionsBuffers();
375 this.qrCodeValueIndex = 0;
376 }
377
378 async submit2024Actions() {
Philipp Schraderad2a6fb2024-03-20 20:51:36 -0700379 const res = await this.actionsSubmitter.submit(this.createActionsBuffer());
Ravago Jones2813c032022-03-16 23:44:11 -0700380
381 if (res.ok) {
382 // We successfully submitted the data. Report success.
383 this.section = 'Success';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800384 this.actionList = [];
Evelyn Yangc8036b12023-10-11 21:14:46 -0700385
Philipp Schrader63198402024-03-16 14:19:02 -0700386 // Keep track of the position of the last robot, use to figure out what
387 // the next robot in the same position is.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700388 let lastTeamPos = '0';
389 for (const match of this.matchList) {
390 if (
391 this.matchNumber === match.matchNumber() &&
392 this.setNumber === match.setNumber() &&
393 this.compLevel === match.compLevel()
394 ) {
395 this.teamNumber = this.teamNumber;
396 if (this.teamNumber == match.r1()) {
397 lastTeamPos = 'r1';
398 } else if (this.teamNumber == match.r2()) {
399 lastTeamPos = 'r2';
400 } else if (this.teamNumber == match.r3()) {
401 lastTeamPos = 'r3';
402 } else if (this.teamNumber == match.b1()) {
403 lastTeamPos = 'b1';
404 } else if (this.teamNumber == match.b2()) {
405 lastTeamPos = 'b2';
406 } else if (this.teamNumber == match.b3()) {
407 lastTeamPos = 'b3';
408 } else {
409 console.log('Position of scouted team not found.');
410 }
411 break;
412 }
413 }
414 if (lastTeamPos != '0') {
415 this.matchNumber += 1;
416 for (const match of this.matchList) {
417 if (
418 this.matchNumber == match.matchNumber() &&
419 this.setNumber == match.setNumber() &&
420 this.compLevel == match.compLevel()
421 ) {
422 if (lastTeamPos == 'r1') {
423 this.nextTeamNumber = match.r1();
424 } else if (lastTeamPos == 'r2') {
425 this.nextTeamNumber = match.r2();
426 } else if (lastTeamPos == 'r3') {
427 this.nextTeamNumber = match.r3();
428 } else if (lastTeamPos == 'b1') {
429 this.nextTeamNumber = match.b1();
430 } else if (lastTeamPos == 'b2') {
431 this.nextTeamNumber = match.b2();
432 } else if (lastTeamPos == 'b3') {
433 this.nextTeamNumber = match.b3();
434 } else {
435 console.log('Position of last team not found.');
436 }
437 break;
438 }
439 }
440 } else {
441 console.log('Last team position not found.');
442 }
443 this.matchList = [];
444 this.progressMessage = '';
445 this.errorMessage = '';
446 this.autoPhase = true;
447 this.actionList = [];
448 this.mobilityCompleted = false;
Emily Markova9c18e9c2024-04-03 20:06:27 -0700449 this.compType = 'Regular';
Evelyn Yangc8036b12023-10-11 21:14:46 -0700450 this.matchStartTimestamp = 0;
451 this.selectedValue = 0;
Ravago Jones2813c032022-03-16 23:44:11 -0700452 } else {
453 const resBuffer = await res.arrayBuffer();
454 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
James Kuszmauldac091f2022-03-22 09:35:06 -0700455 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
Ravago Jones2813c032022-03-16 23:44:11 -0700456
457 const errorMessage = parsedResponse.errorMessage();
Philipp Schrader817cce32022-03-26 15:00:00 -0700458 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
Alex Perrybb3d2062022-03-05 18:14:33 -0800459 }
Ravago Jones2813c032022-03-16 23:44:11 -0700460 }
Philipp Schrader80587432022-03-05 15:41:22 -0800461}