forked from devflowinc/monorepo
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget-statistics.ts
More file actions
122 lines (104 loc) · 3.43 KB
/
get-statistics.ts
File metadata and controls
122 lines (104 loc) · 3.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import { Team, Circuit, Season, Competitor, TeamTournamentResult, TeamRanking, Tournament, TournamentSpeakerResult, Bid } from "@shared/database";
import getRelativeTime from "@src/utils/get-relative-time";
type ExpandedTeam = Team & {
_count: {
rounds: number;
};
circuits: Circuit[];
seasons: Season[];
competitors: Competitor[];
results: (TeamTournamentResult & {
tournament: Tournament;
speaking: TournamentSpeakerResult[];
bid: Bid | any;
})[];
rankings: TeamRanking[];
}
interface TeamStatistics {
lastActive: string;
tWp: number;
pWp: number;
eWp: number;
pRecord: [number, number];
eRecord: [number, number];
avgOpWpM: number;
breakPct: number;
madeElims: number;
otr: number;
avgSpeaks: number;
stdDevSpeaks: number;
rankings: any;
bids: number;
inTop20Pct: number;
}
export function getAvg(arr: number[]) {
if (!arr.length) return 0;
let sum = 0;
arr.forEach(e => sum += e);
return sum / arr.length;
}
export function getDeflator(tourns: number) {
let N = 1;
let Y0 = 0.15;
let K = 1.3;
return Math.round(
N / ((N / Y0 - 1) * Math.pow(Math.E, -K * tourns) + 1) * 100
) / 100;
}
export default function getStatistics(data: ExpandedTeam) {
let statistics: any = {
lastActive: '',
tWp: 0,
pWp: 0,
eWp: 0,
pRecord: [0, 0],
eRecord: [0, 0],
avgOpWpM: [],
breakPct: [0, 0],
madeElims: 0,
otr: [],
avgSpeaks: [],
stdDevSpeaks: [],
rankings: [],
bids: 0,
inTop20Pct: 0,
};
data.results.forEach(result => {
statistics.pRecord[0] += result.prelimBallotsWon;
statistics.pRecord[1] += result.prelimBallotsLost;
statistics.eRecord[0] += result.elimWins || 0;
statistics.eRecord[1] += result.elimLosses || 0;
if (result.prelimPos / result.prelimPoolSize <= .2) statistics.inTop20Pct += 1;
if (result.tournament.hasElimRounds) {
// If they made elims one of these has to be truthy
if (result.elimWins || result.elimLosses) {
statistics.breakPct[0] += 1;
}
else {
statistics.breakPct[1] += 1;
}
}
statistics.otr.push(result.otrComp);
statistics.avgOpWpM.push(result.opWpM);
result.speaking.forEach(speakingResult => {
statistics.avgSpeaks.push(speakingResult.rawAvgPoints);
statistics.stdDevSpeaks.push(speakingResult.stdDevPoints);
});
if (result.bid) statistics.bids += result.bid.value == 'Full' ? 1 : 0.5;
});
data.results.sort((a, b) => a.tournament.start - b.tournament.start).reverse();
statistics.lastActive = getRelativeTime(data.results[0].tournament.start * 1000);
let numPrelims = statistics.pRecord[0] + statistics.pRecord[1];
let numElims = statistics.eRecord[0] + statistics.eRecord[1];
statistics.pWp = statistics.pRecord[0] / numPrelims;
statistics.eWp = statistics.eRecord[0] / numElims;
statistics.tWp = (statistics.pRecord[0] + (statistics.eRecord[0] || 0)) / (numPrelims + (numElims || 0)) + (statistics.eWp || 0) * 0.1;
if (statistics.tWp > 1) statistics.tWp = 1;
statistics.madeElims = statistics.breakPct[0];
statistics.breakPct = statistics.breakPct[0] / (statistics.breakPct[0] + statistics.breakPct[1]);
statistics.otr = getDeflator(data.results.length) * getAvg(statistics.otr);
statistics.avgOpWpM = getAvg(statistics.avgOpWpM);
statistics.avgSpeaks = getAvg(statistics.avgSpeaks);
statistics.stdDevSpeaks = getAvg(statistics.stdDevSpeaks)
return statistics as TeamStatistics;
}