blob: 5ae1f76aa38e168f444c053861078b020b81ce60 [file] [log] [blame]
Ishan Katpallydad5f1a2022-03-23 21:06:36 -07001import {Component, OnInit} from '@angular/core';
Filip Kujawab5a16e32022-12-14 13:21:56 -08002import {
3 Ranking,
4 RequestAllDriverRankingsResponse,
Philipp Schraderd7efa2b2023-02-17 21:15:13 -08005} from '../../webserver/requests/messages/request_all_driver_rankings_response_generated';
Filip Kujawab5a16e32022-12-14 13:21:56 -08006import {
7 Stats,
8 RequestDataScoutingResponse,
Philipp Schraderd7efa2b2023-02-17 21:15:13 -08009} from '../../webserver/requests/messages/request_data_scouting_response_generated';
Filip Kujawab5a16e32022-12-14 13:21:56 -080010import {
11 Note,
12 RequestAllNotesResponse,
Philipp Schraderd7efa2b2023-02-17 21:15:13 -080013} from '../../webserver/requests/messages/request_all_notes_response_generated';
Filip Kujawab5a16e32022-12-14 13:21:56 -080014
Philipp Schrader175a93c2023-02-19 13:13:40 -080015import {ViewDataRequestor} from '../rpc';
Filip Kujawab5a16e32022-12-14 13:21:56 -080016
17type Source = 'Notes' | 'Stats' | 'DriverRanking';
18
19//TODO(Filip): Deduplicate
20const COMP_LEVEL_LABELS = {
21 qm: 'Qualifications',
22 ef: 'Eighth Finals',
23 qf: 'Quarter Finals',
24 sf: 'Semi Finals',
25 f: 'Finals',
26};
Ishan Katpallydad5f1a2022-03-23 21:06:36 -070027
28@Component({
29 selector: 'app-view',
30 templateUrl: './view.ng.html',
Philipp Schrader175a93c2023-02-19 13:13:40 -080031 styleUrls: ['../app/common.css', './view.component.css'],
Ishan Katpallydad5f1a2022-03-23 21:06:36 -070032})
Filip Kujawab5a16e32022-12-14 13:21:56 -080033export class ViewComponent {
34 constructor(private readonly viewDataRequestor: ViewDataRequestor) {}
35
36 // Make COMP_LEVEL_LABELS available in view.ng.html.
37 readonly COMP_LEVEL_LABELS = COMP_LEVEL_LABELS;
38
39 // Progress and error messages to display to
40 // the user when fetching data.
41 progressMessage: string = '';
42 errorMessage: string = '';
43
44 // The current data source being displayed.
45 currentSource: Source = 'Notes';
46
47 // Current sort (ascending/descending match numbers).
48 // noteList is sorted based on team number until match
49 // number is added for note scouting.
50 ascendingSort = true;
51
52 // Stores the corresponding data.
53 noteList: Note[] = [];
54 driverRankingList: Ranking[] = [];
55 statList: Stats[] = [];
56
57 // Fetch notes on initialization.
58 ngOnInit() {
59 this.fetchCurrentSource();
60 }
61
62 // Called when a user changes the sort direction.
63 // Changes the data order between ascending/descending.
64 sortData() {
65 this.ascendingSort = !this.ascendingSort;
66 if (!this.ascendingSort) {
67 this.driverRankingList.sort((a, b) => b.matchNumber() - a.matchNumber());
68 this.noteList.sort((a, b) => b.team() - a.team());
69 this.statList.sort((a, b) => b.match() - a.match());
70 } else {
71 this.driverRankingList.sort((a, b) => a.matchNumber() - b.matchNumber());
72 this.noteList.sort((a, b) => a.team() - b.team());
73 this.statList.sort((a, b) => a.match() - b.match());
74 }
75 }
76
77 // Called when a user selects a new data source
78 // from the dropdown.
79 switchDataSource(target: Source) {
80 this.currentSource = target;
81 this.progressMessage = '';
82 this.errorMessage = '';
83 this.noteList = [];
84 this.driverRankingList = [];
85 this.statList = [];
86 this.fetchCurrentSource();
87 }
88
89 // Call the method to fetch data for the current source.
90 fetchCurrentSource() {
91 switch (this.currentSource) {
92 case 'Notes': {
93 this.fetchNotes();
94 }
95
96 case 'Stats': {
97 this.fetchStats();
98 }
99
100 case 'DriverRanking': {
101 this.fetchDriverRanking();
102 }
103 }
104 }
105
106 // TODO(Filip): Add delete functionality.
107 // Gets called when a user clicks the delete icon.
108 async deleteData() {
109 const block_alerts = document.getElementById(
110 'block_alerts'
111 ) as HTMLInputElement;
112 if (!block_alerts.checked) {
113 if (!window.confirm('Actually delete data?')) {
114 this.errorMessage = 'Deleting data has not been implemented yet.';
115 return;
116 }
117 }
118 }
119
120 // Fetch all driver ranking data and store in driverRankingList.
121 async fetchDriverRanking() {
122 this.progressMessage = 'Fetching driver ranking data. Please be patient.';
123 this.errorMessage = '';
124
125 try {
126 this.driverRankingList =
127 await this.viewDataRequestor.fetchDriverRankingList();
128 this.progressMessage = 'Successfully fetched driver ranking data.';
129 } catch (e) {
130 this.errorMessage = e;
131 this.progressMessage = '';
132 }
133 }
134
135 // Fetch all data scouting (stats) data and store in statList.
136 async fetchStats() {
137 this.progressMessage = 'Fetching stats list. Please be patient.';
138 this.errorMessage = '';
139
140 try {
141 this.statList = await this.viewDataRequestor.fetchStatsList();
142 this.progressMessage = 'Successfully fetched stats list.';
143 } catch (e) {
144 this.errorMessage = e;
145 this.progressMessage = '';
146 }
147 }
148
149 // Fetch all notes data and store in noteList.
150 async fetchNotes() {
151 this.progressMessage = 'Fetching notes list. Please be patient.';
152 this.errorMessage = '';
153
154 try {
155 this.noteList = await this.viewDataRequestor.fetchNoteList();
156 this.progressMessage = 'Successfully fetched note list.';
157 } catch (e) {
158 this.errorMessage = e;
159 this.progressMessage = '';
160 }
161 }
162
163 // Parse all selected keywords for a note entry
164 // into one string to be displayed in the table.
165 parseKeywords(entry: Note) {
166 let parsedKeywords = '';
167
168 if (entry.goodDriving()) {
169 parsedKeywords += 'Good Driving ';
170 }
171 if (entry.badDriving()) {
172 parsedKeywords += 'Bad Driving ';
173 }
Filip Kujawa6f7f0b32023-03-30 13:26:08 -0700174 if (entry.solidPickup()) {
175 parsedKeywords += 'Solid Pickup ';
Filip Kujawab5a16e32022-12-14 13:21:56 -0800176 }
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800177 if (entry.sketchyPlacing()) {
Filip Kujawa6f7f0b32023-03-30 13:26:08 -0700178 parsedKeywords += 'Sketchy Placing ';
Filip Kujawab5a16e32022-12-14 13:21:56 -0800179 }
180 if (entry.goodDefense()) {
181 parsedKeywords += 'Good Defense ';
182 }
183 if (entry.badDefense()) {
184 parsedKeywords += 'Bad Defense ';
185 }
Filip Kujawa7ddd5652023-03-07 19:56:15 -0800186 if (entry.easilyDefended()) {
187 parsedKeywords += 'Easily Defended';
188 }
Filip Kujawab5a16e32022-12-14 13:21:56 -0800189
190 return parsedKeywords;
191 }
192}