Shoraky commited on
Commit
ee66b74
·
1 Parent(s): 957266c

Return five annotated player skill ratings

Browse files
Files changed (1) hide show
  1. src/server.ts +24 -10
src/server.ts CHANGED
@@ -107,6 +107,28 @@ const meanPlayerScore = (values: number[]) => values.length
107
  ? values.reduce((sum, value) => sum + value, 0) / values.length * 10
108
  : null;
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  export async function accountRoleFor(userId: string) {
111
  const { data, error } = await supabaseAdmin.from("users").select("account_role").eq("user_id", userId).maybeSingle();
112
  if (error) throw new Error(`Unable to load account permissions: ${error.message}`);
@@ -522,21 +544,13 @@ app.get("/api/players-overview/:playerId", async (req, res, next) => {
522
  const ownSessions = (sessions ?? []).filter((row) => row.player_id === playerId.data);
523
  const ownActions = (actions ?? []).filter((row) => ownSessions.some((session) => session.session_id === row.session_id));
524
  const ownScores = ownActions.map((row) => scoreMap.get(row.action_id)).filter((score): score is number => score != null && Number.isFinite(score));
525
- const byAction = [...new Set(ownActions.map((row) => row.type))].map((type) => {
526
- const matching = ownActions.filter((row) => row.type === type);
527
- const values = matching.map((row) => scoreMap.get(row.action_id)).filter((score): score is number => score != null && Number.isFinite(score));
528
- return { axis: type, score: meanPlayerScore(values), samples: values.length };
529
- });
530
  const sessionPlayerById = new Map((sessions ?? []).map((row) => [row.session_id, row.player_id]));
531
  const squadActions = (actions ?? []).filter((action) => {
532
  const ownerId = sessionPlayerById.get(action.session_id);
533
  return Boolean(ownerId) && ownerId !== playerId.data;
534
  });
535
- const squadByAction = [...new Set(squadActions.map((action) => action.type))].map((type) => {
536
- const matching = squadActions.filter((action) => action.type === type);
537
- const values = matching.map((action) => scoreMap.get(action.action_id)).filter((score): score is number => score != null && Number.isFinite(score));
538
- return { axis: type, score: meanPlayerScore(values), samples: values.length };
539
- });
540
  const player = overview?.find((row) => row.player_id === playerId.data);
541
  if (!player) return res.status(404).json({ error: "Player not found." });
542
  const sessionsForPlayer = ownSessions.map((row) => {
 
107
  ? values.reduce((sum, value) => sum + value, 0) / values.length * 10
108
  : null;
109
 
110
+ const PLAYER_SKILL_CATEGORIES = [
111
+ { axis: "Pass", aliases: ["pass", "passing"] },
112
+ { axis: "Shoot", aliases: ["shoot", "shooting", "shot"] },
113
+ { axis: "Receive", aliases: ["receive", "receiving", "reception"] },
114
+ { axis: "Dribbling", aliases: ["dribble", "dribbling"] },
115
+ { axis: "Pace", aliases: ["pace"] },
116
+ ] as const;
117
+
118
+ function playerSkillRatings(
119
+ actions: Array<{ action_id: string; type: string }>,
120
+ scoreByAction: Map<string, number | null>,
121
+ ) {
122
+ return PLAYER_SKILL_CATEGORIES.map(({ axis, aliases }) => {
123
+ const names = new Set<string>(aliases);
124
+ const scores = actions
125
+ .filter(({ type }) => names.has(type.trim().toLowerCase().replace(/[^a-z0-9]/g, "")))
126
+ .map(({ action_id }) => scoreByAction.get(action_id))
127
+ .filter((score): score is number => score != null && Number.isFinite(score));
128
+ return { axis, score: meanPlayerScore(scores), samples: scores.length };
129
+ });
130
+ }
131
+
132
  export async function accountRoleFor(userId: string) {
133
  const { data, error } = await supabaseAdmin.from("users").select("account_role").eq("user_id", userId).maybeSingle();
134
  if (error) throw new Error(`Unable to load account permissions: ${error.message}`);
 
544
  const ownSessions = (sessions ?? []).filter((row) => row.player_id === playerId.data);
545
  const ownActions = (actions ?? []).filter((row) => ownSessions.some((session) => session.session_id === row.session_id));
546
  const ownScores = ownActions.map((row) => scoreMap.get(row.action_id)).filter((score): score is number => score != null && Number.isFinite(score));
547
+ const byAction = playerSkillRatings(ownActions, scoreMap);
 
 
 
 
548
  const sessionPlayerById = new Map((sessions ?? []).map((row) => [row.session_id, row.player_id]));
549
  const squadActions = (actions ?? []).filter((action) => {
550
  const ownerId = sessionPlayerById.get(action.session_id);
551
  return Boolean(ownerId) && ownerId !== playerId.data;
552
  });
553
+ const squadByAction = playerSkillRatings(squadActions, scoreMap);
 
 
 
 
554
  const player = overview?.find((row) => row.player_id === playerId.data);
555
  if (!player) return res.status(404).json({ error: "Player not found." });
556
  const sessionsForPlayer = ownSessions.map((row) => {