blob: cd59884f6ef405392822de64ff90df4aa834adc4 [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';
36import {MatchListRequestor} from '@org_frc971/scouting/www/rpc';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070037import {ActionHelper, ConcreteAction} from './action_helper';
Philipp Schradere2e27ff2024-02-25 22:08:55 -080038import * as pako from 'pako';
Philipp Schrader8b8ed672022-03-05 18:08:50 -080039
Philipp Schrader817cce32022-03-26 15:00:00 -070040type Section =
41 | 'Team Selection'
Filip Kujawa0ef334c2023-02-20 19:42:45 -080042 | 'Init'
43 | 'Pickup'
44 | 'Place'
45 | 'Endgame'
46 | 'Dead'
Philipp Schrader817cce32022-03-26 15:00:00 -070047 | 'Review and Submit'
Philipp Schradere2e27ff2024-02-25 22:08:55 -080048 | 'QR Code'
Philipp Schrader817cce32022-03-26 15:00:00 -070049 | 'Success';
Philipp Schrader80587432022-03-05 15:41:22 -080050
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070051// TODO(phil): Deduplicate with match_list.component.ts.
52const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
Philipp Schraderba315da2024-03-17 16:16:50 -070053export type CompLevel = typeof COMP_LEVELS[number];
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070054
55// TODO(phil): Deduplicate with match_list.component.ts.
56const COMP_LEVEL_LABELS: Record<CompLevel, string> = {
57 qm: 'Qualifications',
58 ef: 'Eighth Finals',
59 qf: 'Quarter Finals',
60 sf: 'Semi Finals',
61 f: 'Finals',
62};
63
Philipp Schradere2e27ff2024-02-25 22:08:55 -080064// The maximum number of bytes per QR code. The user can adjust this value to
65// make the QR code contain less information, but easier to scan.
66const QR_CODE_PIECE_SIZES = [150, 300, 450, 600, 750, 900];
67
68// The default index into QR_CODE_PIECE_SIZES.
69const DEFAULT_QR_CODE_PIECE_SIZE_INDEX = QR_CODE_PIECE_SIZES.indexOf(750);
70
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070071// The actions that are purely used for tracking state. They don't actually
72// have any permanent meaning and will not be saved in the database.
73const STATE_ACTIONS: ActionType[] = [
74 ActionType.EndAutoPhaseAction,
75 ActionType.EndTeleopPhaseAction,
76];
emilym38d08ba2022-10-22 15:25:01 -070077
Philipp Schrader23993e82022-03-18 18:54:00 -070078@Component({
79 selector: 'app-entry',
80 templateUrl: './entry.ng.html',
Philipp Schrader175a93c2023-02-19 13:13:40 -080081 styleUrls: ['../app/common.css', './entry.component.css'],
Philipp Schrader23993e82022-03-18 18:54:00 -070082})
Philipp Schrader75021f52023-04-09 21:14:13 -070083export class EntryComponent implements OnInit {
Philipp Schrader36df73a2022-03-17 23:27:24 -070084 // Re-export the type here so that we can use it in the `[value]` attribute
85 // of radio buttons.
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070086 readonly COMP_LEVELS = COMP_LEVELS;
87 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
Philipp Schradere2e27ff2024-02-25 22:08:55 -080088 readonly QR_CODE_PIECE_SIZES = QR_CODE_PIECE_SIZES;
Emily Markovadcadcb62024-02-03 13:07:17 -080089 readonly ScoreType = ScoreType;
Emily Markova6079e2f2024-02-17 13:17:24 -080090 readonly StageType = StageType;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070091 readonly ActionT = ActionT;
92 readonly ActionType = ActionType;
93 readonly StartMatchActionT = StartMatchActionT;
94 readonly MobilityActionT = MobilityActionT;
95 readonly PickupNoteActionT = PickupNoteActionT;
96 readonly PlaceNoteActionT = PlaceNoteActionT;
97 readonly RobotDeathActionT = RobotDeathActionT;
98 readonly PenaltyActionT = PenaltyActionT;
99 readonly EndMatchActionT = EndMatchActionT;
Philipp Schrader36df73a2022-03-17 23:27:24 -0700100
Ravago Jones2813c032022-03-16 23:44:11 -0700101 section: Section = 'Team Selection';
Ravago Jones2813c032022-03-16 23:44:11 -0700102 @Input() matchNumber: number = 1;
Emily Markovae68b7632023-12-30 14:17:55 -0800103 @Input() teamNumber: string = '1';
Philipp Schrader30b4a682022-04-16 14:36:17 -0700104 @Input() setNumber: number = 1;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700105 @Input() compLevel: CompLevel = 'qm';
Philipp Schrader75021f52023-04-09 21:14:13 -0700106 @Input() skipTeamSelection = false;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800107
Philipp Schrader63198402024-03-16 14:19:02 -0700108 @ViewChild('header') header: ElementRef;
109
Philipp Schrader8702b782023-04-15 17:33:37 -0700110 matchList: Match[] = [];
111
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700112 actionHelper: ActionHelper;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800113 actionList: ActionT[] = [];
Philipp Schrader8702b782023-04-15 17:33:37 -0700114 progressMessage: string = '';
Ravago Jones2813c032022-03-16 23:44:11 -0700115 errorMessage: string = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800116 autoPhase: boolean = true;
Filip Kujawab73e94c2023-04-19 09:33:14 -0700117 mobilityCompleted: boolean = false;
Philipp Schraderba315da2024-03-17 16:16:50 -0700118 // TODO(phil): Come up with a better name here.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700119 selectedValue = 0;
Philipp Schraderba315da2024-03-17 16:16:50 -0700120 endGameAction: StageType = StageType.kMISSING;
121 noteIsTrapped: boolean = false;
122 endGameSpotlight: boolean = false;
123
Evelyn Yangc8036b12023-10-11 21:14:46 -0700124 nextTeamNumber = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800125
Philipp Schradere1498852023-04-15 18:06:45 -0700126 preScouting: boolean = false;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800127 matchStartTimestamp: number = 0;
Emily Markovadcadcb62024-02-03 13:07:17 -0800128 penalties: number = 0;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800129
Philipp Schrader8702b782023-04-15 17:33:37 -0700130 teamSelectionIsValid = false;
131
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800132 // When the user chooses to generate QR codes, we convert the flatbuffer into
133 // a long string. Since we frequently have more data than we can display in a
134 // single QR code, we break the data into multiple QR codes. The data for
135 // each QR code ("pieces") is stored in the `qrCodeValuePieces` list below.
136 // The `qrCodeValueIndex` keeps track of which QR code we're currently
137 // displaying.
138 qrCodeValuePieceSize = QR_CODE_PIECE_SIZES[DEFAULT_QR_CODE_PIECE_SIZE_INDEX];
139 qrCodeValuePieces: string[] = [];
140 qrCodeValueIndex: number = 0;
141
Philipp Schrader8702b782023-04-15 17:33:37 -0700142 constructor(private readonly matchListRequestor: MatchListRequestor) {}
143
Philipp Schrader75021f52023-04-09 21:14:13 -0700144 ngOnInit() {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700145 this.actionHelper = new ActionHelper(
146 (actionType: ActionType, action: ConcreteAction) => {
147 this.addAction(actionType, action);
148 }
149 );
150
Philipp Schrader75021f52023-04-09 21:14:13 -0700151 // When the user navigated from the match list, we can skip the team
152 // selection. I.e. we trust that the user clicked the correct button.
153 this.section = this.skipTeamSelection ? 'Init' : 'Team Selection';
Evelyn Yangc8036b12023-10-11 21:14:46 -0700154 this.fetchMatchList();
155 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700156
Evelyn Yangc8036b12023-10-11 21:14:46 -0700157 goToNextTeam() {
158 this.ngOnInit();
159 this.teamNumber = this.nextTeamNumber;
160 this.nextTeamNumber = '';
Philipp Schrader8702b782023-04-15 17:33:37 -0700161 }
162
163 async fetchMatchList() {
164 this.progressMessage = 'Fetching match list. Please be patient.';
165 this.errorMessage = '';
166
167 try {
168 this.matchList = await this.matchListRequestor.fetchMatchList();
169 this.progressMessage = 'Successfully fetched match list.';
170 } catch (e) {
171 this.errorMessage = e;
172 this.progressMessage = '';
173 }
174 }
175
176 // This gets called when the user changes something on the Init screen.
177 // It makes sure that the user can't click "Next" until the information is
Philipp Schradere1498852023-04-15 18:06:45 -0700178 // valid, or this is for pre-scouting.
Philipp Schrader8702b782023-04-15 17:33:37 -0700179 updateTeamSelectionValidity(): void {
Philipp Schradere1498852023-04-15 18:06:45 -0700180 this.teamSelectionIsValid = this.preScouting || this.matchIsInMatchList();
Philipp Schrader8702b782023-04-15 17:33:37 -0700181 }
182
183 matchIsInMatchList(): boolean {
184 // If the user deletes the content of the teamNumber field, the value here
185 // is undefined. Guard against that.
186 if (this.teamNumber == null) {
187 return false;
188 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700189
190 for (const match of this.matchList) {
191 if (
192 this.matchNumber == match.matchNumber() &&
193 this.setNumber == match.setNumber() &&
194 this.compLevel == match.compLevel() &&
Evelyn Yangc8036b12023-10-11 21:14:46 -0700195 (this.teamNumber === match.r1() ||
196 this.teamNumber === match.r2() ||
197 this.teamNumber === match.r3() ||
198 this.teamNumber === match.b1() ||
199 this.teamNumber === match.b2() ||
200 this.teamNumber === match.b3())
Philipp Schrader8702b782023-04-15 17:33:37 -0700201 ) {
202 return true;
203 }
204 }
205 return false;
Philipp Schrader75021f52023-04-09 21:14:13 -0700206 }
207
Emily Markovadcadcb62024-02-03 13:07:17 -0800208 addPenalty(): void {
209 this.penalties += 1;
210 }
211
212 removePenalty(): void {
213 if (this.penalties > 0) {
214 this.penalties -= 1;
215 }
216 }
217
218 addPenalties(): void {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700219 this.actionHelper.addPenaltyAction({penalties: this.penalties});
Emily Markovadcadcb62024-02-03 13:07:17 -0800220 }
221
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700222 addAction(actionType: ActionType, action: ConcreteAction): void {
223 let timestamp: number = 0;
224
225 if (actionType == ActionType.StartMatchAction) {
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800226 // Unix nanosecond timestamp.
227 this.matchStartTimestamp = Date.now() * 1e6;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800228 } else {
229 // Unix nanosecond timestamp relative to match start.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700230 timestamp = Date.now() * 1e6 - this.matchStartTimestamp;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800231 }
232
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700233 if (actionType == ActionType.EndMatchAction) {
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800234 // endMatchAction occurs at the same time as penaltyAction so add to its
235 // timestamp to make it unique.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700236 timestamp += 1;
Emily Markovadcadcb62024-02-03 13:07:17 -0800237 }
238
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700239 if (actionType == ActionType.MobilityAction) {
Filip Kujawab73e94c2023-04-19 09:33:14 -0700240 this.mobilityCompleted = true;
241 }
242
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700243 this.actionList.push(new ActionT(BigInt(timestamp), actionType, action));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800244 }
245
246 undoLastAction() {
247 if (this.actionList.length > 0) {
248 let lastAction = this.actionList.pop();
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700249 switch (lastAction?.actionTakenType) {
250 case ActionType.EndAutoPhaseAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800251 this.autoPhase = true;
Emily Markovadcadcb62024-02-03 13:07:17 -0800252 this.section = 'Pickup';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700253 case ActionType.PickupNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800254 this.section = 'Pickup';
255 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700256 case ActionType.EndTeleopPhaseAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800257 this.section = 'Pickup';
258 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700259 case ActionType.PlaceNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800260 this.section = 'Place';
261 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700262 case ActionType.EndMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800263 this.section = 'Endgame';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700264 case ActionType.MobilityAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800265 this.mobilityCompleted = false;
266 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700267 case ActionType.StartMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800268 this.section = 'Init';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800269 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700270 case ActionType.RobotDeathAction:
Filip Kujawa9f56d0e2023-03-03 19:44:43 -0800271 // TODO(FILIP): Return user to the screen they
272 // clicked dead robot on. Pickup is fine for now but
273 // might cause confusion.
274 this.section = 'Pickup';
275 break;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800276 default:
277 break;
278 }
279 }
280 }
281
Emily Markovadcadcb62024-02-03 13:07:17 -0800282 stringifyScoreType(scoreType: ScoreType): String {
283 return ScoreType[scoreType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700284 }
285
Emily Markovadcadcb62024-02-03 13:07:17 -0800286 stringifyStageType(stageType: StageType): String {
287 return StageType[stageType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700288 }
289
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800290 changeSectionTo(target: Section) {
Philipp Schrader8702b782023-04-15 17:33:37 -0700291 // Clear the messages since they won't be relevant in the next section.
292 this.errorMessage = '';
293 this.progressMessage = '';
294
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800295 // For the QR code screen, we need to make the value to encode available.
296 if (target == 'QR Code') {
297 this.updateQrCodeValuePieceSize();
298 }
299
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800300 this.section = target;
301 }
Philipp Schrader80587432022-03-05 15:41:22 -0800302
Ravago Jones2813c032022-03-16 23:44:11 -0700303 private scrollToTop() {
304 this.header.nativeElement.scrollIntoView();
305 }
306
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800307 createActionsBuffer() {
James Kuszmauldac091f2022-03-22 09:35:06 -0700308 const builder = new Builder();
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800309 const actionOffsets: number[] = [];
310
311 for (const action of this.actionList) {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700312 if (STATE_ACTIONS.includes(action.actionTakenType)) {
313 // Actions only used for undo purposes are not submitted.
314 continue;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800315 }
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700316 actionOffsets.push(action.pack(builder));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800317 }
Emily Markovae68b7632023-12-30 14:17:55 -0800318 const teamNumberFb = builder.createString(this.teamNumber);
Philipp Schradere859e6e2023-03-22 19:59:51 -0700319 const compLevelFb = builder.createString(this.compLevel);
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800320
Emily Markovadcadcb62024-02-03 13:07:17 -0800321 const actionsVector = Submit2024Actions.createActionsListVector(
Philipp Schrader817cce32022-03-26 15:00:00 -0700322 builder,
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800323 actionOffsets
Philipp Schrader817cce32022-03-26 15:00:00 -0700324 );
Emily Markovadcadcb62024-02-03 13:07:17 -0800325 Submit2024Actions.startSubmit2024Actions(builder);
326 Submit2024Actions.addTeamNumber(builder, teamNumberFb);
327 Submit2024Actions.addMatchNumber(builder, this.matchNumber);
328 Submit2024Actions.addSetNumber(builder, this.setNumber);
329 Submit2024Actions.addCompLevel(builder, compLevelFb);
330 Submit2024Actions.addActionsList(builder, actionsVector);
331 Submit2024Actions.addPreScouting(builder, this.preScouting);
332 builder.finish(Submit2024Actions.endSubmit2024Actions(builder));
Ravago Jones2813c032022-03-16 23:44:11 -0700333
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800334 return builder.asUint8Array();
335 }
336
337 // Same as createActionsBuffer, but encoded as Base64. It's also split into
338 // a number of pieces so that each piece is roughly limited to
339 // `qrCodeValuePieceSize` bytes.
340 createBase64ActionsBuffers(): string[] {
341 const originalBuffer = this.createActionsBuffer();
342 const deflatedData = pako.deflate(originalBuffer, {level: 9});
343
344 const pieceSize = this.qrCodeValuePieceSize;
345 const fullValue = btoa(String.fromCharCode(...deflatedData));
346 const numPieces = Math.ceil(fullValue.length / pieceSize);
347
348 let splitData: string[] = [];
349 for (let i = 0; i < numPieces; i++) {
350 const splitPiece = fullValue.slice(i * pieceSize, (i + 1) * pieceSize);
351 splitData.push(`${i}_${numPieces}_${pieceSize}_${splitPiece}`);
352 }
353 return splitData;
354 }
355
356 setQrCodeValueIndex(index: number) {
357 this.qrCodeValueIndex = Math.max(
358 0,
359 Math.min(index, this.qrCodeValuePieces.length - 1)
360 );
361 }
362
363 updateQrCodeValuePieceSize() {
364 this.qrCodeValuePieces = this.createBase64ActionsBuffers();
365 this.qrCodeValueIndex = 0;
366 }
367
368 async submit2024Actions() {
Emily Markovadcadcb62024-02-03 13:07:17 -0800369 const res = await fetch('/requests/submit/submit_2024_actions', {
Philipp Schrader817cce32022-03-26 15:00:00 -0700370 method: 'POST',
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800371 body: this.createActionsBuffer(),
Philipp Schrader817cce32022-03-26 15:00:00 -0700372 });
Ravago Jones2813c032022-03-16 23:44:11 -0700373
374 if (res.ok) {
375 // We successfully submitted the data. Report success.
376 this.section = 'Success';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800377 this.actionList = [];
Evelyn Yangc8036b12023-10-11 21:14:46 -0700378
Philipp Schrader63198402024-03-16 14:19:02 -0700379 // Keep track of the position of the last robot, use to figure out what
380 // the next robot in the same position is.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700381 let lastTeamPos = '0';
382 for (const match of this.matchList) {
383 if (
384 this.matchNumber === match.matchNumber() &&
385 this.setNumber === match.setNumber() &&
386 this.compLevel === match.compLevel()
387 ) {
388 this.teamNumber = this.teamNumber;
389 if (this.teamNumber == match.r1()) {
390 lastTeamPos = 'r1';
391 } else if (this.teamNumber == match.r2()) {
392 lastTeamPos = 'r2';
393 } else if (this.teamNumber == match.r3()) {
394 lastTeamPos = 'r3';
395 } else if (this.teamNumber == match.b1()) {
396 lastTeamPos = 'b1';
397 } else if (this.teamNumber == match.b2()) {
398 lastTeamPos = 'b2';
399 } else if (this.teamNumber == match.b3()) {
400 lastTeamPos = 'b3';
401 } else {
402 console.log('Position of scouted team not found.');
403 }
404 break;
405 }
406 }
407 if (lastTeamPos != '0') {
408 this.matchNumber += 1;
409 for (const match of this.matchList) {
410 if (
411 this.matchNumber == match.matchNumber() &&
412 this.setNumber == match.setNumber() &&
413 this.compLevel == match.compLevel()
414 ) {
415 if (lastTeamPos == 'r1') {
416 this.nextTeamNumber = match.r1();
417 } else if (lastTeamPos == 'r2') {
418 this.nextTeamNumber = match.r2();
419 } else if (lastTeamPos == 'r3') {
420 this.nextTeamNumber = match.r3();
421 } else if (lastTeamPos == 'b1') {
422 this.nextTeamNumber = match.b1();
423 } else if (lastTeamPos == 'b2') {
424 this.nextTeamNumber = match.b2();
425 } else if (lastTeamPos == 'b3') {
426 this.nextTeamNumber = match.b3();
427 } else {
428 console.log('Position of last team not found.');
429 }
430 break;
431 }
432 }
433 } else {
434 console.log('Last team position not found.');
435 }
436 this.matchList = [];
437 this.progressMessage = '';
438 this.errorMessage = '';
439 this.autoPhase = true;
440 this.actionList = [];
441 this.mobilityCompleted = false;
442 this.preScouting = false;
443 this.matchStartTimestamp = 0;
444 this.selectedValue = 0;
Ravago Jones2813c032022-03-16 23:44:11 -0700445 } else {
446 const resBuffer = await res.arrayBuffer();
447 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
James Kuszmauldac091f2022-03-22 09:35:06 -0700448 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
Ravago Jones2813c032022-03-16 23:44:11 -0700449
450 const errorMessage = parsedResponse.errorMessage();
Philipp Schrader817cce32022-03-26 15:00:00 -0700451 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
Alex Perrybb3d2062022-03-05 18:14:33 -0800452 }
Ravago Jones2813c032022-03-16 23:44:11 -0700453 }
Philipp Schrader80587432022-03-05 15:41:22 -0800454}