Skip to content

Commit a258cd7

Browse files
authored
Merge pull request #494 from The-Purple-Warehouse/main
[staging deploy] add picklist helper feature
2 parents 69bf7d2 + 83da32b commit a258cd7

6 files changed

Lines changed: 266 additions & 73 deletions

File tree

config/scouting/2025/index.ts

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,127 @@ export function formatParsedData(data, categories, teams) {
11311131
.join("\n")}`;
11321132
}
11331133

1134+
export interface picklist {
1135+
team: string;
1136+
"avg-auto-pieces": number;
1137+
"avg-tele-pieces": number;
1138+
"avg-l1": number;
1139+
"avg-l2": number;
1140+
"avg-l3": number;
1141+
"avg-l4": number;
1142+
"avg-proc": number;
1143+
"avg-net": number;
1144+
"deep-climbs": number;
1145+
}
1146+
1147+
export async function formPicklist(
1148+
data: { [team: string]: any[] },
1149+
categories,
1150+
teams: any[]
1151+
) {
1152+
let analysis: picklist[] = [];
1153+
console.log(teams);
1154+
for (const t1 of teams) {
1155+
const t = t1.team_number;
1156+
let dat = data[t];
1157+
if (!dat) continue;
1158+
let autoPieces = 0;
1159+
let telePieces = 0;
1160+
let l1 = 0;
1161+
let l2 = 0;
1162+
let l3 = 0;
1163+
let l4 = 0;
1164+
let proc = 0;
1165+
let net = 0;
1166+
let deepClimbs = 0;
1167+
let total = 0;
1168+
for (const d of dat) {
1169+
if (!d || !d.accuracy || !d.accuracy.calculated) {
1170+
continue;
1171+
}
1172+
let acc = d.accuracy.percentage;
1173+
1174+
autoPieces += acc * find(d, "counters", categories, "25-20", 0);
1175+
telePieces += acc * find(d, "counters", categories, "25-24", 0);
1176+
let autocoral = find(d, "data", categories, "25-18", []);
1177+
let telecoral = find(d, "data", categories, "25-22", []);
1178+
let autol4 = autocoral.filter((el) => el == 0).length;
1179+
let autol3 = autocoral.filter((el) => el == 1).length;
1180+
let autol2 = autocoral.filter((el) => el == 2).length;
1181+
let autol1 = autocoral.filter((el) => el == 3).length;
1182+
let telel4 = telecoral.filter((el) => el == 0).length;
1183+
let telel3 = telecoral.filter((el) => el == 1).length;
1184+
let telel2 = telecoral.filter((el) => el == 2).length;
1185+
let telel1 = telecoral.filter((el) => el == 3).length;
1186+
l1 += acc * (autol1 + telel1);
1187+
l2 += acc * (autol2 + telel2);
1188+
l3 += acc * (autol3 + telel3);
1189+
l4 += acc * (autol4 + telel4);
1190+
let autoalgae = find(d, "data", categories, "25-17", []);
1191+
let telealgae = find(d, "data", categories, "25-21", []);
1192+
let autoNe = autoalgae.filter((el) => el == 4).length;
1193+
let autoPr = autoalgae.filter((el) => el == 5).length;
1194+
let teleNe = telealgae.filter((el) => el == 4).length;
1195+
let telePr = telealgae.filter((el) => el == 5).length;
1196+
net += acc * (autoNe + teleNe);
1197+
proc += acc * (autoPr + telePr);
1198+
let climb = find(d, "abilities", categories, "25-8", 0);
1199+
if (acc > 0.5) deepClimbs += climb == 3 ? 1 : 0;
1200+
1201+
total += acc;
1202+
}
1203+
if (dat.length == 0 || total == 0) {
1204+
analysis.push({
1205+
team: t,
1206+
"avg-auto-pieces": NaN,
1207+
"avg-tele-pieces": NaN,
1208+
"avg-l1": NaN,
1209+
"avg-l2": NaN,
1210+
"avg-l3": NaN,
1211+
"avg-l4": NaN,
1212+
"avg-proc": NaN,
1213+
"avg-net": NaN,
1214+
"deep-climbs": NaN
1215+
});
1216+
} else {
1217+
analysis.push({
1218+
team: t,
1219+
"avg-auto-pieces": autoPieces / total,
1220+
"avg-tele-pieces": telePieces / total,
1221+
"avg-l1": l1 / total,
1222+
"avg-l2": l2 / total,
1223+
"avg-l3": l3 / total,
1224+
"avg-l4": l4 / total,
1225+
"avg-proc": proc / total,
1226+
"avg-net": net / total,
1227+
"deep-climbs": deepClimbs
1228+
});
1229+
}
1230+
}
1231+
1232+
return formatPicklist(analysis);
1233+
}
1234+
1235+
function formatPicklist(analysis) {
1236+
return `entry,team,"avg auto pieces","avg tele pieces","avg l1","avg l2","avg l3","avg l4","avg processor","avg net","# of deep climbs"\n${analysis
1237+
.map((entry, i) => {
1238+
return [
1239+
i,
1240+
entry.team || 0,
1241+
entry["avg-auto-pieces"],
1242+
entry["avg-tele-pieces"],
1243+
entry["avg-l1"],
1244+
entry["avg-l2"],
1245+
entry["avg-l3"],
1246+
entry["avg-l4"],
1247+
entry["avg-proc"],
1248+
entry["avg-net"],
1249+
entry["deep-climbs"]
1250+
].join(",");
1251+
})
1252+
.join("\n")}`;
1253+
}
1254+
11341255
export function notes() {
11351256
return ``;
11361257
}
@@ -1547,6 +1668,7 @@ const scouting2025 = {
15471668
preload,
15481669
formatData,
15491670
formatParsedData,
1671+
formPicklist,
15501672
notes,
15511673
analysis,
15521674
compare,

config/scouting/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ if (scoutingConfig[year].formatParsedData != null) {
2020
} else {
2121
scoutingConfig.formatParsedData = scoutingConfig[year].formatData;
2222
}
23+
if (scoutingConfig[year].formPicklist != null) {
24+
scoutingConfig.formPicklist = scoutingConfig[year].formPicklist;
25+
} else {
26+
scoutingConfig.formPicklist = async (data, teams) => {
27+
return "";
28+
};
29+
}
2330
scoutingConfig.notes = scoutingConfig[year].notes;
2431
scoutingConfig.analysis = scoutingConfig[year].analysis;
2532
scoutingConfig.accuracy = scoutingConfig[year].accuracy;

helpers/scouting.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import ScoutingEntry from "../models/scoutingEntry";
22
import ScoutingCategory from "../models/scoutingCategory";
33
import Team from "../models/team";
44
import { getTeamByNumber } from "./teams";
5-
import { getEventTeams } from "./tba";
5+
import { getEventTeams, getTeamEvents } from "./tba";
66
import * as crypto from "crypto";
77
import scoutingConfig from "../config/scouting";
88
import config from "../config";
@@ -449,7 +449,7 @@ export async function addEntry(
449449
}
450450
});
451451
await entry.save();
452-
if(!event.endsWith("-prac")) {
452+
if (!event.endsWith("-prac")) {
453453
pendingAccuracy.add(event);
454454
}
455455
}
@@ -666,6 +666,35 @@ export async function getSharedData(
666666
}
667667
}
668668

669+
export async function getPicklistData(event: string, teamNumber: string) {
670+
let teams = await getEventTeams(event, config.year);
671+
let team = (await getTeamByNumber(teamNumber)) || { _id: "" };
672+
let events = new Set<string>();
673+
for (const t of teams) {
674+
let tevents = await getTeamEvents(config.year, t.team_number);
675+
for (let i = 0; i < tevents.length; ++i) {
676+
events.add(tevents[i].key);
677+
}
678+
}
679+
events.delete(`${config.year}all-prac`);
680+
// get all the data from all of the events
681+
let categories;
682+
let aData: { [team: string]: any[] } = {};
683+
for (const event of events) {
684+
let { data, categories: nCategories } = await getAllRawDataByEvent(
685+
event
686+
);
687+
if (categories == null) categories = nCategories;
688+
for (const d of data) {
689+
if (isNaN(d.team)) continue;
690+
if (aData[d.team] == null) aData[d.team] = [];
691+
aData[d.team].push(d);
692+
}
693+
}
694+
695+
return await scoutingConfig.formPicklist(aData, categories, teams);
696+
}
697+
669698
export async function getTeamsAtEvent(
670699
event: string,
671700
teamNumber: string,
@@ -769,7 +798,7 @@ export async function getTeamData(
769798

770799
export async function updatePendingAccuracy() {
771800
let events = [...pendingAccuracy] as any;
772-
for(let i = 0; i < events.length; i++) {
801+
for (let i = 0; i < events.length; i++) {
773802
pendingAccuracy.delete(events[i]);
774803
await updateAccuracy(events[i]);
775804
}

index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ import { addAPIHeaders } from "./helpers/utils";
1515

1616
import config from "./config";
1717
import { registerComponentsWithinDirectory } from "./helpers/componentRegistration";
18-
import { getStats, initializeCategories, updatePendingAccuracy } from "./helpers/scouting";
18+
import {
19+
getStats,
20+
initializeCategories,
21+
updatePendingAccuracy
22+
} from "./helpers/scouting";
1923

2024
// import loginRouter from "./routers/login"; // contains base route "/"
2125
import defaultRouter from "./routers/default"; // contains base route "/"
@@ -209,7 +213,7 @@ app.use(serve("./static", {}));
209213

210214
let calculatingAccuracy = false;
211215
setInterval(async () => {
212-
if(!calculatingAccuracy) {
216+
if (!calculatingAccuracy) {
213217
calculatingAccuracy = true;
214218
console.log("calculating accuracy");
215219
await updatePendingAccuracy();

routers/api/scouting.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ import {
2121
getTeamData,
2222
getTotalIncentives,
2323
getLevelAndProgress,
24-
aggregateLeaderboard
24+
aggregateLeaderboard,
25+
getPicklistData
2526
} from "../../helpers/scouting";
2627
import {
2728
getTeamByNumber,
@@ -212,6 +213,24 @@ router.get(
212213
}
213214
);
214215

216+
router.get(
217+
"/entry/data/event/:event/picklist",
218+
requireScoutingAuth,
219+
async (ctx, next) => {
220+
addAPIHeaders(ctx);
221+
ctx.body = {
222+
success: true,
223+
body: {
224+
csv: await getPicklistData(
225+
ctx.params.event,
226+
ctx.session.scoutingTeamNumber
227+
),
228+
notes: scoutingConfig.notes()
229+
}
230+
};
231+
}
232+
);
233+
215234
router.get(
216235
"/entry/data/event/:event/tba",
217236
requireScoutingAuth,

0 commit comments

Comments
 (0)