blob: 86df425bf28456a755337a112a639ca926640f3f [file] [log] [blame]
Alex Perrybb901052022-03-23 19:46:15 -07001import {Component} from '@angular/core';
2import {Builder, ByteBuffer} from 'flatbuffers';
3import {ErrorResponse} from 'org_frc971/scouting/webserver/requests/messages/error_response_generated';
4import {RequestNotesForTeam} from 'org_frc971/scouting/webserver/requests/messages/request_notes_for_team_generated';
Philipp Schrader817cce32022-03-26 15:00:00 -07005import {
6 Note as NoteFb,
7 RequestNotesForTeamResponse,
8} from 'org_frc971/scouting/webserver/requests/messages/request_notes_for_team_response_generated';
Alex Perrybb901052022-03-23 19:46:15 -07009import {SubmitNotes} from 'org_frc971/scouting/webserver/requests/messages/submit_notes_generated';
10import {SubmitNotesResponse} from 'org_frc971/scouting/webserver/requests/messages/submit_notes_response_generated';
11
Filip Kujawaf947cb42022-11-21 10:00:30 -080012/*
13For new games, the keywords being used will likely need to be updated.
14To update the keywords complete the following:
15 1) Update the Keywords Interface and KEYWORD_CHECKBOX_LABELS in notes.component.ts
16 The keys of Keywords and KEYWORD_CHECKBOX_LABELS should match.
17 2) In notes.component.ts, update the setTeamNumber() method with the new keywords.
18 3) Add/Edit the new keywords in /scouting/webserver/requests/messages/submit_notes.fbs.
19 4) In notes.component.ts, update the submitData() method with the newKeywords
20 so that it matches the updated flatbuffer
21 5) In db.go, update the NotesData struct and the
22 AddNotes method with the new keywords
23 6) In db_test.go update the TestNotes method so the test uses the keywords
24 7) Update the submitNoteScoutingHandler in requests.go with the new keywords
25 8) Finally, update the corresponding test in requests_test.go (TestSubmitNotes)
26
27 Note: If you change the number of keywords you might need to
28 update how they are displayed in notes.ng.html
29*/
30
31// TeamSelection: Display form to add a team to the teams being scouted.
32// Data: Display the note textbox and keyword selection form
33// for all the teams being scouted.
Philipp Schrader817cce32022-03-26 15:00:00 -070034type Section = 'TeamSelection' | 'Data';
Alex Perrybb901052022-03-23 19:46:15 -070035
Filip Kujawaf947cb42022-11-21 10:00:30 -080036// Every keyword checkbox corresponds to a boolean.
37// If the boolean is True, the checkbox is selected
38// and the note scout saw that the robot being scouted
39// displayed said property (ex. Driving really well -> goodDriving)
40interface Keywords {
41 goodDriving: boolean;
42 badDriving: boolean;
43 sketchyClimb: boolean;
44 solidClimb: boolean;
45 goodDefense: boolean;
46 badDefense: boolean;
Alex Perrybb901052022-03-23 19:46:15 -070047}
48
Filip Kujawaf947cb42022-11-21 10:00:30 -080049interface Input {
50 teamNumber: number;
51 notesData: string;
52 keywordsData: Keywords;
53}
54
55const KEYWORD_CHECKBOX_LABELS = {
56 goodDriving: 'Good Driving',
57 badDriving: 'Bad Driving',
58 solidClimb: 'Solid Climb',
59 sketchyClimb: 'Sketchy Climb',
60 goodDefense: 'Good Defense',
61 badDefense: 'Bad Defense',
62} as const;
63
Alex Perrybb901052022-03-23 19:46:15 -070064@Component({
65 selector: 'frc971-notes',
66 templateUrl: './notes.ng.html',
Philipp Schrader817cce32022-03-26 15:00:00 -070067 styleUrls: ['../common.css', './notes.component.css'],
Alex Perrybb901052022-03-23 19:46:15 -070068})
69export class Notes {
Filip Kujawaf947cb42022-11-21 10:00:30 -080070 // Re-export KEYWORD_CHECKBOX_LABELS so that we can
71 // use it in the checkbox properties.
72 readonly KEYWORD_CHECKBOX_LABELS = KEYWORD_CHECKBOX_LABELS;
73
74 // Necessary in order to iterate the keys of KEYWORD_CHECKBOX_LABELS.
75 Object = Object;
76
Alex Perrybb901052022-03-23 19:46:15 -070077 section: Section = 'TeamSelection';
Alex Perrybb901052022-03-23 19:46:15 -070078
79 errorMessage = '';
Filip Kujawaf947cb42022-11-21 10:00:30 -080080 teamNumberSelection: number = 971;
Alex Perrybb901052022-03-23 19:46:15 -070081
Filip Kujawaf947cb42022-11-21 10:00:30 -080082 // Data inputted by user is stored in this array.
83 // Includes the team number, notes, and keyword selection.
84 newData: Input[] = [];
Alex Perrybb901052022-03-23 19:46:15 -070085
Filip Kujawaf947cb42022-11-21 10:00:30 -080086 setTeamNumber() {
87 let data: Input = {
88 teamNumber: this.teamNumberSelection,
89 notesData: '',
90 keywordsData: {
91 goodDriving: false,
92 badDriving: false,
93 solidClimb: false,
94 sketchyClimb: false,
95 goodDefense: false,
96 badDefense: false,
97 },
98 };
Alex Perrybb901052022-03-23 19:46:15 -070099
Filip Kujawaf947cb42022-11-21 10:00:30 -0800100 this.newData.push(data);
101 this.section = 'Data';
102 }
Alex Perrybb901052022-03-23 19:46:15 -0700103
Filip Kujawaf947cb42022-11-21 10:00:30 -0800104 removeTeam(index: number) {
105 this.newData.splice(index, 1);
106 if (this.newData.length == 0) {
107 this.section = 'TeamSelection';
Alex Perrybb901052022-03-23 19:46:15 -0700108 } else {
Filip Kujawaf947cb42022-11-21 10:00:30 -0800109 this.section = 'Data';
Alex Perrybb901052022-03-23 19:46:15 -0700110 }
111 }
112
Filip Kujawaf947cb42022-11-21 10:00:30 -0800113 addTeam() {
Philipp Schrader817cce32022-03-26 15:00:00 -0700114 this.section = 'TeamSelection';
Alex Perrybb901052022-03-23 19:46:15 -0700115 }
Philipp Schrader817cce32022-03-26 15:00:00 -0700116
Alex Perrybb901052022-03-23 19:46:15 -0700117 async submitData() {
Filip Kujawaf947cb42022-11-21 10:00:30 -0800118 for (let i = 0; i < this.newData.length; i++) {
119 const builder = new Builder();
120 const dataFb = builder.createString(this.newData[i].notesData);
121 builder.finish(
122 SubmitNotes.createSubmitNotes(
123 builder,
124 this.newData[i].teamNumber,
125 dataFb,
126 this.newData[i].keywordsData.goodDriving,
127 this.newData[i].keywordsData.badDriving,
128 this.newData[i].keywordsData.sketchyClimb,
129 this.newData[i].keywordsData.solidClimb,
130 this.newData[i].keywordsData.goodDefense,
131 this.newData[i].keywordsData.badDefense
132 )
133 );
Alex Perrybb901052022-03-23 19:46:15 -0700134
Filip Kujawaf947cb42022-11-21 10:00:30 -0800135 const buffer = builder.asUint8Array();
136 const res = await fetch('/requests/submit/submit_notes', {
137 method: 'POST',
138 body: buffer,
139 });
Alex Perrybb901052022-03-23 19:46:15 -0700140
Filip Kujawaf947cb42022-11-21 10:00:30 -0800141 if (!res.ok) {
142 const resBuffer = await res.arrayBuffer();
143 const fbBuffer = new ByteBuffer(new Uint8Array(resBuffer));
144 const parsedResponse = ErrorResponse.getRootAsErrorResponse(fbBuffer);
145 const errorMessage = parsedResponse.errorMessage();
146 this.errorMessage = `Received ${res.status} ${res.statusText}: "${errorMessage}"`;
147 }
Alex Perrybb901052022-03-23 19:46:15 -0700148 }
Filip Kujawaf947cb42022-11-21 10:00:30 -0800149
150 this.newData = [];
151 this.errorMessage = '';
152 this.section = 'TeamSelection';
Alex Perrybb901052022-03-23 19:46:15 -0700153 }
154}