blob: 08f4dd4122f78e3124b2a3510231c5199e398cb9 [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
emilym38d08ba2022-10-22 15:25:01 -070041const IMAGES_ARRAY = [
42 {
43 id: 'field_quadrants_image',
44 original_image:
45 '/sha256/cbb99a057a2504e80af526dae7a0a04121aed84c56a6f4889e9576fe1c20c61e/pictures/field/quadrants.jpeg',
46 reversed_image:
47 '/sha256/2c67fffbb722e9a7d0e1d270f1aad7f39a2dc8493c2e7ad1ae50bd6fa52d5bb7/pictures/field/reversed_quadrants.jpeg',
48 },
49 {
50 id: 'field_balls_image',
51 original_image:
52 '/sha256/e095cc8a75d804b0e2070e0a941fab37154176756d4c1a775e53cc48c3a732b9/pictures/field/balls.jpeg',
53 reversed_image:
54 '/sha256/fe4a4605c03598611c583d4dcdf28e06a056a17302ae91f5c527568966d95f3a/pictures/field/reversed_balls.jpeg',
55 },
56];
57
Philipp Schrader23993e82022-03-18 18:54:00 -070058@Component({
59 selector: 'app-entry',
60 templateUrl: './entry.ng.html',
Philipp Schrader817cce32022-03-26 15:00:00 -070061 styleUrls: ['../common.css', './entry.component.css'],
Philipp Schrader23993e82022-03-18 18:54:00 -070062})
63export class EntryComponent {
Philipp Schrader36df73a2022-03-17 23:27:24 -070064 // Re-export the type here so that we can use it in the `[value]` attribute
65 // of radio buttons.
66 readonly ClimbLevel = ClimbLevel;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070067 readonly COMP_LEVELS = COMP_LEVELS;
68 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
Philipp Schrader36df73a2022-03-17 23:27:24 -070069
Ravago Jones2813c032022-03-16 23:44:11 -070070 section: Section = 'Team Selection';
71 @Output() switchTabsEvent = new EventEmitter<string>();
72 @Input() matchNumber: number = 1;
73 @Input() teamNumber: number = 1;
Philipp Schrader30b4a682022-04-16 14:36:17 -070074 @Input() setNumber: number = 1;
Philipp Schrader8aeb14f2022-04-08 21:23:18 -070075 @Input() compLevel: CompLevel = 'qm';
Ravago Jones2813c032022-03-16 23:44:11 -070076 autoUpperShotsMade: number = 0;
77 autoLowerShotsMade: number = 0;
78 autoShotsMissed: number = 0;
79 teleUpperShotsMade: number = 0;
80 teleLowerShotsMade: number = 0;
81 teleShotsMissed: number = 0;
82 defensePlayedOnScore: number = 0;
83 defensePlayedScore: number = 0;
Philipp Schrader36df73a2022-03-17 23:27:24 -070084 level: ClimbLevel = ClimbLevel.NoAttempt;
Ravago Jones2813c032022-03-16 23:44:11 -070085 ball1: boolean = false;
86 ball2: boolean = false;
87 ball3: boolean = false;
88 ball4: boolean = false;
89 ball5: boolean = false;
90 quadrant: number = 1;
91 errorMessage: string = '';
92 noShow: boolean = false;
93 neverMoved: boolean = false;
94 batteryDied: boolean = false;
95 mechanicallyBroke: boolean = false;
96 lostComs: boolean = false;
Philipp Schrader9bcbc332022-03-18 19:06:04 -070097 comment: string = '';
Philipp Schrader80587432022-03-05 15:41:22 -080098
Ravago Jones2813c032022-03-16 23:44:11 -070099 @ViewChild('header') header: ElementRef;
Philipp Schrader6b2e9502022-03-15 23:42:56 -0700100
Ravago Jones2813c032022-03-16 23:44:11 -0700101 nextSection() {
102 if (this.section === 'Team Selection') {
103 this.section = 'Auto';
104 } else if (this.section === 'Auto') {
105 this.section = 'TeleOp';
106 } else if (this.section === 'TeleOp') {
107 this.section = 'Climb';
108 } else if (this.section === 'Climb') {
109 this.section = 'Other';
110 } else if (this.section === 'Other') {
111 this.section = 'Review and Submit';
112 } else if (this.section === 'Review and Submit') {
113 this.submitDataScouting();
114 return;
115 } else if (this.section === 'Success') {
Philipp Schrader23993e82022-03-18 18:54:00 -0700116 this.switchTabsEvent.emit('MatchList');
117 return;
Philipp Schrader80587432022-03-05 15:41:22 -0800118 }
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 next screen. Otherwise it's easy to overlook input fields.
121 this.scrollToTop();
122 }
Philipp Schrader80587432022-03-05 15:41:22 -0800123
Ravago Jones2813c032022-03-16 23:44:11 -0700124 prevSection() {
125 if (this.section === 'Auto') {
126 this.section = 'Team Selection';
127 } else if (this.section === 'TeleOp') {
128 this.section = 'Auto';
129 } else if (this.section === 'Climb') {
130 this.section = 'TeleOp';
131 } else if (this.section === 'Other') {
132 this.section = 'Climb';
133 } else if (this.section === 'Review and Submit') {
134 this.section = 'Other';
Philipp Schrader6b2e9502022-03-15 23:42:56 -0700135 }
Ravago Jones2813c032022-03-16 23:44:11 -0700136 // Scroll back to the top so that we can be sure the user sees the
137 // entire previous screen. Otherwise it's easy to overlook input
138 // fields.
139 this.scrollToTop();
140 }
Philipp Schrader6b2e9502022-03-15 23:42:56 -0700141
emilym38d08ba2022-10-22 15:25:01 -0700142 flipImages() {
143 for (let obj of IMAGES_ARRAY) {
144 let img = document.getElementById(obj.id) as HTMLImageElement;
145 img.src = img.src.endsWith(obj.original_image)
146 ? obj.reversed_image
147 : obj.original_image;
148 }
149 }
Ravago Jones2813c032022-03-16 23:44:11 -0700150 private scrollToTop() {
151 this.header.nativeElement.scrollIntoView();
152 }
153
154 async submitDataScouting() {
155 this.errorMessage = '';
156
James Kuszmauldac091f2022-03-22 09:35:06 -0700157 const builder = new Builder();
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700158 const compLevel = builder.createString(this.compLevel);
Philipp Schrader70569f72022-03-18 19:15:05 -0700159 const comment = builder.createString(this.comment);
Ravago Jones2813c032022-03-16 23:44:11 -0700160 SubmitDataScouting.startSubmitDataScouting(builder);
161 SubmitDataScouting.addTeam(builder, this.teamNumber);
162 SubmitDataScouting.addMatch(builder, this.matchNumber);
Philipp Schrader30b4a682022-04-16 14:36:17 -0700163 SubmitDataScouting.addSetNumber(builder, this.setNumber);
Philipp Schrader8aeb14f2022-04-08 21:23:18 -0700164 SubmitDataScouting.addCompLevel(builder, compLevel);
Ravago Jones2813c032022-03-16 23:44:11 -0700165 SubmitDataScouting.addMissedShotsAuto(builder, this.autoShotsMissed);
166 SubmitDataScouting.addUpperGoalAuto(builder, this.autoUpperShotsMade);
167 SubmitDataScouting.addLowerGoalAuto(builder, this.autoLowerShotsMade);
168 SubmitDataScouting.addMissedShotsTele(builder, this.teleShotsMissed);
169 SubmitDataScouting.addUpperGoalTele(builder, this.teleUpperShotsMade);
170 SubmitDataScouting.addLowerGoalTele(builder, this.teleLowerShotsMade);
171 SubmitDataScouting.addDefenseRating(builder, this.defensePlayedScore);
Philipp Schrader817cce32022-03-26 15:00:00 -0700172 SubmitDataScouting.addDefenseReceivedRating(
173 builder,
174 this.defensePlayedOnScore
175 );
Ravago Jones2813c032022-03-16 23:44:11 -0700176 SubmitDataScouting.addAutoBall1(builder, this.ball1);
177 SubmitDataScouting.addAutoBall2(builder, this.ball2);
178 SubmitDataScouting.addAutoBall3(builder, this.ball3);
179 SubmitDataScouting.addAutoBall4(builder, this.ball4);
180 SubmitDataScouting.addAutoBall5(builder, this.ball5);
181 SubmitDataScouting.addStartingQuadrant(builder, this.quadrant);
Philipp Schrader36df73a2022-03-17 23:27:24 -0700182 SubmitDataScouting.addClimbLevel(builder, this.level);
Philipp Schrader70569f72022-03-18 19:15:05 -0700183 SubmitDataScouting.addComment(builder, comment);
Ravago Jones2813c032022-03-16 23:44:11 -0700184 builder.finish(SubmitDataScouting.endSubmitDataScouting(builder));
185
186 const buffer = builder.asUint8Array();
Philipp Schrader817cce32022-03-26 15:00:00 -0700187 const res = await fetch('/requests/submit/data_scouting', {
188 method: 'POST',
189 body: buffer,
190 });
Ravago Jones2813c032022-03-16 23:44:11 -0700191
192 if (res.ok) {
193 // We successfully submitted the data. Report success.
194 this.section = 'Success';
195 } else {
196 const resBuffer = await res.arrayBuffer();
197 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
James Kuszmauldac091f2022-03-22 09:35:06 -0700198 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
Ravago Jones2813c032022-03-16 23:44:11 -0700199
200 const errorMessage = parsedResponse.errorMessage();
Philipp Schrader817cce32022-03-26 15:00:00 -0700201 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
Alex Perrybb3d2062022-03-05 18:14:33 -0800202 }
Ravago Jones2813c032022-03-16 23:44:11 -0700203 }
Philipp Schrader80587432022-03-05 15:41:22 -0800204}