blob: d6829c5e2abb7aed5721dca275614f7a1768017f [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';
12import {ErrorResponse} from 'org_frc971/scouting/webserver/requests/messages/error_response_generated';
Philipp Schrader817cce32022-03-26 15:00:00 -070013import {
14 ClimbLevel,
15 SubmitDataScouting,
16} from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_generated';
Alex Perrybb901052022-03-23 19:46:15 -070017import {SubmitDataScoutingResponse} from 'org_frc971/scouting/webserver/requests/messages/submit_data_scouting_response_generated';
Philipp Schrader8b8ed672022-03-05 18:08:50 -080018
Philipp Schrader817cce32022-03-26 15:00:00 -070019type Section =
20 | 'Team Selection'
21 | 'Auto'
22 | 'TeleOp'
23 | 'Climb'
24 | 'Other'
25 | 'Review and Submit'
26 | 'Success';
Philipp Schrader80587432022-03-05 15:41:22 -080027
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070028// TODO(phil): Deduplicate with match_list.component.ts.
29const COMP_LEVELS = ['qm', 'ef', 'qf', 'sf', 'f'] as const;
30type CompLevel = typeof COMP_LEVELS[number];
31
32// TODO(phil): Deduplicate with match_list.component.ts.
33const COMP_LEVEL_LABELS: Record<CompLevel, string> = {
34 qm: 'Qualifications',
35 ef: 'Eighth Finals',
36 qf: 'Quarter Finals',
37 sf: 'Semi Finals',
38 f: 'Finals',
39};
40
Philipp Schrader23993e82022-03-18 18:54:00 -070041@Component({
42 selector: 'app-entry',
43 templateUrl: './entry.ng.html',
Philipp Schrader817cce32022-03-26 15:00:00 -070044 styleUrls: ['../common.css', './entry.component.css'],
Philipp Schrader23993e82022-03-18 18:54:00 -070045})
46export class EntryComponent {
Philipp Schrader36df73a2022-03-17 23:27:24 -070047 // Re-export the type here so that we can use it in the `[value]` attribute
48 // of radio buttons.
49 readonly ClimbLevel = ClimbLevel;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070050 readonly COMP_LEVELS = COMP_LEVELS;
51 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
Philipp Schrader36df73a2022-03-17 23:27:24 -070052
Ravago Jones2813c032022-03-16 23:44:11 -070053 section: Section = 'Team Selection';
54 @Output() switchTabsEvent = new EventEmitter<string>();
55 @Input() matchNumber: number = 1;
56 @Input() teamNumber: number = 1;
Philipp Schrader30b4a682022-04-16 14:36:17 -070057 @Input() setNumber: number = 1;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070058 @Input() compLevel: CompLevel = 'qm';
Ravago Jones2813c032022-03-16 23:44:11 -070059 autoUpperShotsMade: number = 0;
60 autoLowerShotsMade: number = 0;
61 autoShotsMissed: number = 0;
62 teleUpperShotsMade: number = 0;
63 teleLowerShotsMade: number = 0;
64 teleShotsMissed: number = 0;
65 defensePlayedOnScore: number = 0;
66 defensePlayedScore: number = 0;
Philipp Schrader36df73a2022-03-17 23:27:24 -070067 level: ClimbLevel = ClimbLevel.NoAttempt;
Ravago Jones2813c032022-03-16 23:44:11 -070068 ball1: boolean = false;
69 ball2: boolean = false;
70 ball3: boolean = false;
71 ball4: boolean = false;
72 ball5: boolean = false;
73 quadrant: number = 1;
74 errorMessage: string = '';
75 noShow: boolean = false;
76 neverMoved: boolean = false;
77 batteryDied: boolean = false;
78 mechanicallyBroke: boolean = false;
79 lostComs: boolean = false;
Philipp Schrader9bcbc332022-03-18 19:06:04 -070080 comment: string = '';
Philipp Schrader80587432022-03-05 15:41:22 -080081
Ravago Jones2813c032022-03-16 23:44:11 -070082 @ViewChild('header') header: ElementRef;
Philipp Schrader6b2e9502022-03-15 23:42:56 -070083
Ravago Jones2813c032022-03-16 23:44:11 -070084 nextSection() {
85 if (this.section === 'Team Selection') {
86 this.section = 'Auto';
87 } else if (this.section === 'Auto') {
88 this.section = 'TeleOp';
89 } else if (this.section === 'TeleOp') {
90 this.section = 'Climb';
91 } else if (this.section === 'Climb') {
92 this.section = 'Other';
93 } else if (this.section === 'Other') {
94 this.section = 'Review and Submit';
95 } else if (this.section === 'Review and Submit') {
96 this.submitDataScouting();
97 return;
98 } else if (this.section === 'Success') {
Philipp Schrader23993e82022-03-18 18:54:00 -070099 this.switchTabsEvent.emit('MatchList');
100 return;
Philipp Schrader80587432022-03-05 15:41:22 -0800101 }
Ravago Jones2813c032022-03-16 23:44:11 -0700102 // Scroll back to the top so that we can be sure the user sees the
103 // entire next screen. Otherwise it's easy to overlook input fields.
104 this.scrollToTop();
105 }
Philipp Schrader80587432022-03-05 15:41:22 -0800106
Ravago Jones2813c032022-03-16 23:44:11 -0700107 prevSection() {
108 if (this.section === 'Auto') {
109 this.section = 'Team Selection';
110 } else if (this.section === 'TeleOp') {
111 this.section = 'Auto';
112 } else if (this.section === 'Climb') {
113 this.section = 'TeleOp';
114 } else if (this.section === 'Other') {
115 this.section = 'Climb';
116 } else if (this.section === 'Review and Submit') {
117 this.section = 'Other';
Philipp Schrader6b2e9502022-03-15 23:42:56 -0700118 }
Ravago Jones2813c032022-03-16 23:44:11 -0700119 // Scroll back to the top so that we can be sure the user sees the
120 // entire previous screen. Otherwise it's easy to overlook input
121 // fields.
122 this.scrollToTop();
123 }
Philipp Schrader6b2e9502022-03-15 23:42:56 -0700124
Ravago Jones2813c032022-03-16 23:44:11 -0700125 private scrollToTop() {
126 this.header.nativeElement.scrollIntoView();
127 }
128
129 async submitDataScouting() {
130 this.errorMessage = '';
131
James Kuszmauldac091f2022-03-22 09:35:06 -0700132 const builder = new Builder();
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700133 const compLevel = builder.createString(this.compLevel);
Philipp Schrader70569f72022-03-18 19:15:05 -0700134 const comment = builder.createString(this.comment);
Ravago Jones2813c032022-03-16 23:44:11 -0700135 SubmitDataScouting.startSubmitDataScouting(builder);
136 SubmitDataScouting.addTeam(builder, this.teamNumber);
137 SubmitDataScouting.addMatch(builder, this.matchNumber);
Philipp Schrader30b4a682022-04-16 14:36:17 -0700138 SubmitDataScouting.addSetNumber(builder, this.setNumber);
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700139 SubmitDataScouting.addCompLevel(builder, compLevel);
Ravago Jones2813c032022-03-16 23:44:11 -0700140 SubmitDataScouting.addMissedShotsAuto(builder, this.autoShotsMissed);
141 SubmitDataScouting.addUpperGoalAuto(builder, this.autoUpperShotsMade);
142 SubmitDataScouting.addLowerGoalAuto(builder, this.autoLowerShotsMade);
143 SubmitDataScouting.addMissedShotsTele(builder, this.teleShotsMissed);
144 SubmitDataScouting.addUpperGoalTele(builder, this.teleUpperShotsMade);
145 SubmitDataScouting.addLowerGoalTele(builder, this.teleLowerShotsMade);
146 SubmitDataScouting.addDefenseRating(builder, this.defensePlayedScore);
Philipp Schrader817cce32022-03-26 15:00:00 -0700147 SubmitDataScouting.addDefenseReceivedRating(
148 builder,
149 this.defensePlayedOnScore
150 );
Ravago Jones2813c032022-03-16 23:44:11 -0700151 SubmitDataScouting.addAutoBall1(builder, this.ball1);
152 SubmitDataScouting.addAutoBall2(builder, this.ball2);
153 SubmitDataScouting.addAutoBall3(builder, this.ball3);
154 SubmitDataScouting.addAutoBall4(builder, this.ball4);
155 SubmitDataScouting.addAutoBall5(builder, this.ball5);
156 SubmitDataScouting.addStartingQuadrant(builder, this.quadrant);
Philipp Schrader36df73a2022-03-17 23:27:24 -0700157 SubmitDataScouting.addClimbLevel(builder, this.level);
Philipp Schrader70569f72022-03-18 19:15:05 -0700158 SubmitDataScouting.addComment(builder, comment);
Ravago Jones2813c032022-03-16 23:44:11 -0700159 builder.finish(SubmitDataScouting.endSubmitDataScouting(builder));
160
161 const buffer = builder.asUint8Array();
Philipp Schrader817cce32022-03-26 15:00:00 -0700162 const res = await fetch('/requests/submit/data_scouting', {
163 method: 'POST',
164 body: buffer,
165 });
Ravago Jones2813c032022-03-16 23:44:11 -0700166
167 if (res.ok) {
168 // We successfully submitted the data. Report success.
169 this.section = 'Success';
170 } else {
171 const resBuffer = await res.arrayBuffer();
172 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
James Kuszmauldac091f2022-03-22 09:35:06 -0700173 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
Ravago Jones2813c032022-03-16 23:44:11 -0700174
175 const errorMessage = parsedResponse.errorMessage();
Philipp Schrader817cce32022-03-26 15:00:00 -0700176 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
Alex Perrybb3d2062022-03-05 18:14:33 -0800177 }
Ravago Jones2813c032022-03-16 23:44:11 -0700178 }
Philipp Schrader80587432022-03-05 15:41:22 -0800179}