blob: 41f492c222a92e1163ce992e92b2d11cd40b34f0 [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
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070054// TODO(phil): Deduplicate with match_list.component.ts.
55const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
Philipp Schraderba315da2024-03-17 16:16:50 -070056export type CompLevel = typeof COMP_LEVELS[number];
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070057
58// TODO(phil): Deduplicate with match_list.component.ts.
59const COMP_LEVEL_LABELS: Record<CompLevel, string> = {
60 qm: 'Qualifications',
61 ef: 'Eighth Finals',
62 qf: 'Quarter Finals',
63 sf: 'Semi Finals',
64 f: 'Finals',
65};
66
Philipp Schradere2e27ff2024-02-25 22:08:55 -080067// The maximum number of bytes per QR code. The user can adjust this value to
68// make the QR code contain less information, but easier to scan.
69const QR_CODE_PIECE_SIZES = [150, 300, 450, 600, 750, 900];
70
71// The default index into QR_CODE_PIECE_SIZES.
72const DEFAULT_QR_CODE_PIECE_SIZE_INDEX = QR_CODE_PIECE_SIZES.indexOf(750);
73
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070074// The actions that are purely used for tracking state. They don't actually
75// have any permanent meaning and will not be saved in the database.
76const STATE_ACTIONS: ActionType[] = [
77 ActionType.EndAutoPhaseAction,
78 ActionType.EndTeleopPhaseAction,
79];
emilym38d08ba2022-10-22 15:25:01 -070080
Philipp Schrader23993e82022-03-18 18:54:00 -070081@Component({
82 selector: 'app-entry',
83 templateUrl: './entry.ng.html',
Philipp Schrader175a93c2023-02-19 13:13:40 -080084 styleUrls: ['../app/common.css', './entry.component.css'],
Philipp Schrader23993e82022-03-18 18:54:00 -070085})
Philipp Schrader75021f52023-04-09 21:14:13 -070086export class EntryComponent implements OnInit {
Philipp Schrader36df73a2022-03-17 23:27:24 -070087 // Re-export the type here so that we can use it in the `[value]` attribute
88 // of radio buttons.
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070089 readonly COMP_LEVELS = COMP_LEVELS;
90 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
Philipp Schradere2e27ff2024-02-25 22:08:55 -080091 readonly QR_CODE_PIECE_SIZES = QR_CODE_PIECE_SIZES;
Emily Markovadcadcb62024-02-03 13:07:17 -080092 readonly ScoreType = ScoreType;
Emily Markova6079e2f2024-02-17 13:17:24 -080093 readonly StageType = StageType;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -070094 readonly ActionT = ActionT;
95 readonly ActionType = ActionType;
96 readonly StartMatchActionT = StartMatchActionT;
97 readonly MobilityActionT = MobilityActionT;
98 readonly PickupNoteActionT = PickupNoteActionT;
99 readonly PlaceNoteActionT = PlaceNoteActionT;
100 readonly RobotDeathActionT = RobotDeathActionT;
101 readonly PenaltyActionT = PenaltyActionT;
102 readonly EndMatchActionT = EndMatchActionT;
Philipp Schrader36df73a2022-03-17 23:27:24 -0700103
Ravago Jones2813c032022-03-16 23:44:11 -0700104 section: Section = 'Team Selection';
Ravago Jones2813c032022-03-16 23:44:11 -0700105 @Input() matchNumber: number = 1;
Emily Markovae68b7632023-12-30 14:17:55 -0800106 @Input() teamNumber: string = '1';
Philipp Schrader30b4a682022-04-16 14:36:17 -0700107 @Input() setNumber: number = 1;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700108 @Input() compLevel: CompLevel = 'qm';
Philipp Schrader75021f52023-04-09 21:14:13 -0700109 @Input() skipTeamSelection = false;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800110
Philipp Schrader63198402024-03-16 14:19:02 -0700111 @ViewChild('header') header: ElementRef;
112
Philipp Schrader8702b782023-04-15 17:33:37 -0700113 matchList: Match[] = [];
114
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700115 actionHelper: ActionHelper;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800116 actionList: ActionT[] = [];
Philipp Schrader8702b782023-04-15 17:33:37 -0700117 progressMessage: string = '';
Ravago Jones2813c032022-03-16 23:44:11 -0700118 errorMessage: string = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800119 autoPhase: boolean = true;
Filip Kujawab73e94c2023-04-19 09:33:14 -0700120 mobilityCompleted: boolean = false;
Philipp Schraderba315da2024-03-17 16:16:50 -0700121 // TODO(phil): Come up with a better name here.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700122 selectedValue = 0;
Philipp Schraderba315da2024-03-17 16:16:50 -0700123 endGameAction: StageType = StageType.kMISSING;
124 noteIsTrapped: boolean = false;
125 endGameSpotlight: boolean = false;
126
Evelyn Yangc8036b12023-10-11 21:14:46 -0700127 nextTeamNumber = '';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800128
Philipp Schradere1498852023-04-15 18:06:45 -0700129 preScouting: boolean = false;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800130 matchStartTimestamp: number = 0;
Emily Markovadcadcb62024-02-03 13:07:17 -0800131 penalties: number = 0;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800132
Philipp Schrader8702b782023-04-15 17:33:37 -0700133 teamSelectionIsValid = false;
134
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800135 // When the user chooses to generate QR codes, we convert the flatbuffer into
136 // a long string. Since we frequently have more data than we can display in a
137 // single QR code, we break the data into multiple QR codes. The data for
138 // each QR code ("pieces") is stored in the `qrCodeValuePieces` list below.
139 // The `qrCodeValueIndex` keeps track of which QR code we're currently
140 // displaying.
141 qrCodeValuePieceSize = QR_CODE_PIECE_SIZES[DEFAULT_QR_CODE_PIECE_SIZE_INDEX];
142 qrCodeValuePieces: string[] = [];
143 qrCodeValueIndex: number = 0;
144
Philipp Schraderad2a6fb2024-03-20 20:51:36 -0700145 constructor(
146 private readonly matchListRequestor: MatchListRequestor,
147 private readonly actionsSubmitter: ActionsSubmitter
148 ) {}
Philipp Schrader8702b782023-04-15 17:33:37 -0700149
Philipp Schrader75021f52023-04-09 21:14:13 -0700150 ngOnInit() {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700151 this.actionHelper = new ActionHelper(
152 (actionType: ActionType, action: ConcreteAction) => {
153 this.addAction(actionType, action);
154 }
155 );
156
Philipp Schrader75021f52023-04-09 21:14:13 -0700157 // When the user navigated from the match list, we can skip the team
158 // selection. I.e. we trust that the user clicked the correct button.
159 this.section = this.skipTeamSelection ? 'Init' : 'Team Selection';
Evelyn Yangc8036b12023-10-11 21:14:46 -0700160 this.fetchMatchList();
161 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700162
Evelyn Yangc8036b12023-10-11 21:14:46 -0700163 goToNextTeam() {
164 this.ngOnInit();
165 this.teamNumber = this.nextTeamNumber;
166 this.nextTeamNumber = '';
Philipp Schrader8702b782023-04-15 17:33:37 -0700167 }
168
169 async fetchMatchList() {
170 this.progressMessage = 'Fetching match list. Please be patient.';
171 this.errorMessage = '';
172
173 try {
174 this.matchList = await this.matchListRequestor.fetchMatchList();
175 this.progressMessage = 'Successfully fetched match list.';
176 } catch (e) {
177 this.errorMessage = e;
178 this.progressMessage = '';
179 }
180 }
181
182 // This gets called when the user changes something on the Init screen.
183 // It makes sure that the user can't click "Next" until the information is
Philipp Schradere1498852023-04-15 18:06:45 -0700184 // valid, or this is for pre-scouting.
Philipp Schrader8702b782023-04-15 17:33:37 -0700185 updateTeamSelectionValidity(): void {
Philipp Schradere1498852023-04-15 18:06:45 -0700186 this.teamSelectionIsValid = this.preScouting || this.matchIsInMatchList();
Philipp Schrader8702b782023-04-15 17:33:37 -0700187 }
188
189 matchIsInMatchList(): boolean {
190 // If the user deletes the content of the teamNumber field, the value here
191 // is undefined. Guard against that.
192 if (this.teamNumber == null) {
193 return false;
194 }
Philipp Schrader8702b782023-04-15 17:33:37 -0700195
196 for (const match of this.matchList) {
197 if (
198 this.matchNumber == match.matchNumber() &&
199 this.setNumber == match.setNumber() &&
200 this.compLevel == match.compLevel() &&
Evelyn Yangc8036b12023-10-11 21:14:46 -0700201 (this.teamNumber === match.r1() ||
202 this.teamNumber === match.r2() ||
203 this.teamNumber === match.r3() ||
204 this.teamNumber === match.b1() ||
205 this.teamNumber === match.b2() ||
206 this.teamNumber === match.b3())
Philipp Schrader8702b782023-04-15 17:33:37 -0700207 ) {
208 return true;
209 }
210 }
211 return false;
Philipp Schrader75021f52023-04-09 21:14:13 -0700212 }
213
Emily Markovadcadcb62024-02-03 13:07:17 -0800214 addPenalty(): void {
215 this.penalties += 1;
216 }
217
218 removePenalty(): void {
219 if (this.penalties > 0) {
220 this.penalties -= 1;
221 }
222 }
223
224 addPenalties(): void {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700225 this.actionHelper.addPenaltyAction({penalties: this.penalties});
Emily Markovadcadcb62024-02-03 13:07:17 -0800226 }
227
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700228 addAction(actionType: ActionType, action: ConcreteAction): void {
229 let timestamp: number = 0;
230
231 if (actionType == ActionType.StartMatchAction) {
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800232 // Unix nanosecond timestamp.
233 this.matchStartTimestamp = Date.now() * 1e6;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800234 } else {
235 // Unix nanosecond timestamp relative to match start.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700236 timestamp = Date.now() * 1e6 - this.matchStartTimestamp;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800237 }
238
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700239 if (actionType == ActionType.EndMatchAction) {
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800240 // endMatchAction occurs at the same time as penaltyAction so add to its
241 // timestamp to make it unique.
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700242 timestamp += 1;
Emily Markovadcadcb62024-02-03 13:07:17 -0800243 }
244
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700245 if (actionType == ActionType.MobilityAction) {
Filip Kujawab73e94c2023-04-19 09:33:14 -0700246 this.mobilityCompleted = true;
247 }
248
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700249 this.actionList.push(new ActionT(BigInt(timestamp), actionType, action));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800250 }
251
252 undoLastAction() {
253 if (this.actionList.length > 0) {
254 let lastAction = this.actionList.pop();
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700255 switch (lastAction?.actionTakenType) {
256 case ActionType.EndAutoPhaseAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800257 this.autoPhase = true;
Emily Markovadcadcb62024-02-03 13:07:17 -0800258 this.section = 'Pickup';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700259 case ActionType.PickupNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800260 this.section = 'Pickup';
261 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700262 case ActionType.EndTeleopPhaseAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800263 this.section = 'Pickup';
264 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700265 case ActionType.PlaceNoteAction:
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800266 this.section = 'Place';
267 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700268 case ActionType.EndMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800269 this.section = 'Endgame';
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700270 case ActionType.MobilityAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800271 this.mobilityCompleted = false;
272 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700273 case ActionType.StartMatchAction:
Emily Markovadcadcb62024-02-03 13:07:17 -0800274 this.section = 'Init';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800275 break;
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700276 case ActionType.RobotDeathAction:
Filip Kujawa9f56d0e2023-03-03 19:44:43 -0800277 // TODO(FILIP): Return user to the screen they
278 // clicked dead robot on. Pickup is fine for now but
279 // might cause confusion.
280 this.section = 'Pickup';
281 break;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800282 default:
283 break;
284 }
285 }
286 }
287
Emily Markovadcadcb62024-02-03 13:07:17 -0800288 stringifyScoreType(scoreType: ScoreType): String {
289 return ScoreType[scoreType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700290 }
291
Emily Markovadcadcb62024-02-03 13:07:17 -0800292 stringifyStageType(stageType: StageType): String {
293 return StageType[stageType];
Emily Markovaf4b06a22023-05-10 17:44:09 -0700294 }
295
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800296 changeSectionTo(target: Section) {
Philipp Schrader8702b782023-04-15 17:33:37 -0700297 // Clear the messages since they won't be relevant in the next section.
298 this.errorMessage = '';
299 this.progressMessage = '';
300
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800301 // For the QR code screen, we need to make the value to encode available.
302 if (target == 'QR Code') {
303 this.updateQrCodeValuePieceSize();
304 }
305
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800306 this.section = target;
307 }
Philipp Schrader80587432022-03-05 15:41:22 -0800308
Ravago Jones2813c032022-03-16 23:44:11 -0700309 private scrollToTop() {
310 this.header.nativeElement.scrollIntoView();
311 }
312
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800313 createActionsBuffer() {
James Kuszmauldac091f2022-03-22 09:35:06 -0700314 const builder = new Builder();
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800315 const actionOffsets: number[] = [];
316
317 for (const action of this.actionList) {
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700318 if (STATE_ACTIONS.includes(action.actionTakenType)) {
319 // Actions only used for undo purposes are not submitted.
320 continue;
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800321 }
Philipp Schrader3d7dedc2024-03-16 16:27:25 -0700322 actionOffsets.push(action.pack(builder));
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800323 }
Emily Markovae68b7632023-12-30 14:17:55 -0800324 const teamNumberFb = builder.createString(this.teamNumber);
Philipp Schradere859e6e2023-03-22 19:59:51 -0700325 const compLevelFb = builder.createString(this.compLevel);
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800326
Emily Markovadcadcb62024-02-03 13:07:17 -0800327 const actionsVector = Submit2024Actions.createActionsListVector(
Philipp Schrader817cce32022-03-26 15:00:00 -0700328 builder,
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800329 actionOffsets
Philipp Schrader817cce32022-03-26 15:00:00 -0700330 );
Emily Markovadcadcb62024-02-03 13:07:17 -0800331 Submit2024Actions.startSubmit2024Actions(builder);
332 Submit2024Actions.addTeamNumber(builder, teamNumberFb);
333 Submit2024Actions.addMatchNumber(builder, this.matchNumber);
334 Submit2024Actions.addSetNumber(builder, this.setNumber);
335 Submit2024Actions.addCompLevel(builder, compLevelFb);
336 Submit2024Actions.addActionsList(builder, actionsVector);
337 Submit2024Actions.addPreScouting(builder, this.preScouting);
338 builder.finish(Submit2024Actions.endSubmit2024Actions(builder));
Ravago Jones2813c032022-03-16 23:44:11 -0700339
Philipp Schradere2e27ff2024-02-25 22:08:55 -0800340 return builder.asUint8Array();
341 }
342
343 // Same as createActionsBuffer, but encoded as Base64. It's also split into
344 // a number of pieces so that each piece is roughly limited to
345 // `qrCodeValuePieceSize` bytes.
346 createBase64ActionsBuffers(): string[] {
347 const originalBuffer = this.createActionsBuffer();
348 const deflatedData = pako.deflate(originalBuffer, {level: 9});
349
350 const pieceSize = this.qrCodeValuePieceSize;
351 const fullValue = btoa(String.fromCharCode(...deflatedData));
352 const numPieces = Math.ceil(fullValue.length / pieceSize);
353
354 let splitData: string[] = [];
355 for (let i = 0; i < numPieces; i++) {
356 const splitPiece = fullValue.slice(i * pieceSize, (i + 1) * pieceSize);
357 splitData.push(`${i}_${numPieces}_${pieceSize}_${splitPiece}`);
358 }
359 return splitData;
360 }
361
362 setQrCodeValueIndex(index: number) {
363 this.qrCodeValueIndex = Math.max(
364 0,
365 Math.min(index, this.qrCodeValuePieces.length - 1)
366 );
367 }
368
369 updateQrCodeValuePieceSize() {
370 this.qrCodeValuePieces = this.createBase64ActionsBuffers();
371 this.qrCodeValueIndex = 0;
372 }
373
374 async submit2024Actions() {
Philipp Schraderad2a6fb2024-03-20 20:51:36 -0700375 const res = await this.actionsSubmitter.submit(this.createActionsBuffer());
Ravago Jones2813c032022-03-16 23:44:11 -0700376
377 if (res.ok) {
378 // We successfully submitted the data. Report success.
379 this.section = 'Success';
Filip Kujawa0ef334c2023-02-20 19:42:45 -0800380 this.actionList = [];
Evelyn Yangc8036b12023-10-11 21:14:46 -0700381
Philipp Schrader63198402024-03-16 14:19:02 -0700382 // Keep track of the position of the last robot, use to figure out what
383 // the next robot in the same position is.
Evelyn Yangc8036b12023-10-11 21:14:46 -0700384 let lastTeamPos = '0';
385 for (const match of this.matchList) {
386 if (
387 this.matchNumber === match.matchNumber() &&
388 this.setNumber === match.setNumber() &&
389 this.compLevel === match.compLevel()
390 ) {
391 this.teamNumber = this.teamNumber;
392 if (this.teamNumber == match.r1()) {
393 lastTeamPos = 'r1';
394 } else if (this.teamNumber == match.r2()) {
395 lastTeamPos = 'r2';
396 } else if (this.teamNumber == match.r3()) {
397 lastTeamPos = 'r3';
398 } else if (this.teamNumber == match.b1()) {
399 lastTeamPos = 'b1';
400 } else if (this.teamNumber == match.b2()) {
401 lastTeamPos = 'b2';
402 } else if (this.teamNumber == match.b3()) {
403 lastTeamPos = 'b3';
404 } else {
405 console.log('Position of scouted team not found.');
406 }
407 break;
408 }
409 }
410 if (lastTeamPos != '0') {
411 this.matchNumber += 1;
412 for (const match of this.matchList) {
413 if (
414 this.matchNumber == match.matchNumber() &&
415 this.setNumber == match.setNumber() &&
416 this.compLevel == match.compLevel()
417 ) {
418 if (lastTeamPos == 'r1') {
419 this.nextTeamNumber = match.r1();
420 } else if (lastTeamPos == 'r2') {
421 this.nextTeamNumber = match.r2();
422 } else if (lastTeamPos == 'r3') {
423 this.nextTeamNumber = match.r3();
424 } else if (lastTeamPos == 'b1') {
425 this.nextTeamNumber = match.b1();
426 } else if (lastTeamPos == 'b2') {
427 this.nextTeamNumber = match.b2();
428 } else if (lastTeamPos == 'b3') {
429 this.nextTeamNumber = match.b3();
430 } else {
431 console.log('Position of last team not found.');
432 }
433 break;
434 }
435 }
436 } else {
437 console.log('Last team position not found.');
438 }
439 this.matchList = [];
440 this.progressMessage = '';
441 this.errorMessage = '';
442 this.autoPhase = true;
443 this.actionList = [];
444 this.mobilityCompleted = false;
445 this.preScouting = false;
446 this.matchStartTimestamp = 0;
447 this.selectedValue = 0;
Ravago Jones2813c032022-03-16 23:44:11 -0700448 } else {
449 const resBuffer = await res.arrayBuffer();
450 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
James Kuszmauldac091f2022-03-22 09:35:06 -0700451 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
Ravago Jones2813c032022-03-16 23:44:11 -0700452
453 const errorMessage = parsedResponse.errorMessage();
Philipp Schrader817cce32022-03-26 15:00:00 -0700454 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
Alex Perrybb3d2062022-03-05 18:14:33 -0800455 }
Ravago Jones2813c032022-03-16 23:44:11 -0700456 }
Philipp Schrader80587432022-03-05 15:41:22 -0800457}