option: "unique first names" and "relative/total"

This commit is contained in:
julius 2024-11-04 10:46:21 +01:00
parent fc073de1de
commit d78e07f513
Signed by: julius
GPG Key ID: C80A63E6A5FD7092
3 changed files with 157 additions and 31 deletions

View File

@ -38,20 +38,33 @@ def load_stats():
def team_table_json(): def team_table_json():
players, preferences = load_stats() players, preferences = load_stats()
mean, team0, team1 = apply_brute_force(players, preferences) best = apply_brute_force(players, preferences)
data = {} data = {k: {} for k in best}
for i, team in enumerate([team0, team1]): for k, v in best.items():
tablename = f"Team {i+1}" mean, team0, team1 = v[0]
data[tablename] = [] overall_matches = 0
for p in sorted(list(team)): overall_preference_statements = 0
prefs = preferences[p] for i, team in enumerate([team0, team1]):
matches = sum([pref in team for pref in preferences[p]]) tablename = f"Team {i+1}"
data[tablename].append([p, matches, len(prefs)]) data[k][tablename] = []
for p in sorted(list(team)):
prefs = preferences[p]
matches = sum([pref in team for pref in preferences[p]])
data[k][tablename].append([p, matches, len(prefs)])
overall_matches += matches
overall_preference_statements += len(prefs)
# data[k]["overall_matches"] = overall_matches
# data[k]["overall_preference_statements"] = overall_preference_statements
with open("prefs_page/src/table.json", "w") as f: with open("prefs_page/src/table.json", "w") as f:
json.dump(data, f) json.dump(data, f)
def unique_names(team):
"""check if first names are unique"""
return len(set(team)) == len(set([p.split()[0] for p in team]))
def apply_brute_force(players, preferences): def apply_brute_force(players, preferences):
def evaluate_teams(team0, team1): def evaluate_teams(team0, team1):
scores = [] scores = []
@ -63,33 +76,43 @@ def apply_brute_force(players, preferences):
percentages.append(scores[-1] / len(preferences[p])) percentages.append(scores[-1] / len(preferences[p]))
return np.mean(scores), np.mean(percentages) * 100 return np.mean(scores), np.mean(percentages) * 100
best_score = [(0, [], [])] best = {
best_percentage = [(0, [], [])] f"{i},{j}": [(0, [], [])]
for i, j in itertools.product(["total", "relative"], ["unique", "non-unique"])
}
for team0 in itertools.combinations(players, 9): for team0 in itertools.combinations(players, 9):
team1 = {player for player in players if player not in team0} team1 = {player for player in players if player not in team0}
score, percentage = evaluate_teams(team0, team1) score, percentage = evaluate_teams(team0, team1)
if score > best_score[0][0]: for k, v in best.items():
best_score = [(score, team0, team1)] if k.startswith("total"):
if score == best_score[0][0] and set(team0) != set(best_score[0][1]): meassure = score
best_score.append((score, team0, team1)) elif k.startswith("relative"):
if percentage > best_percentage[0][0]: meassure = percentage
best_percentage = [(percentage, team0, team1)] if meassure > best[k][0][0]:
if percentage == best_percentage[0][0] and set(team0) != set(best_score[0][1]): if k.endswith(",unique") and not (
best_percentage.append((percentage, team0, team1)) unique_names(team0) and unique_names(team1)
):
continue
best[k] = [(meassure, team0, team1)]
elif meassure == best[k][0][0] and set(team0) != set(best[k][0][1]):
if k.endswith(",unique") and not (
unique_names(team0) and unique_names(team1)
):
continue
best[k].append((meassure, team0, team1))
if __name__ == "__main__": if __name__ == "__main__":
for result in best_score: for k, v in best.items():
print(result[0]) print("##", k)
print(result[1]) for result in v:
print(result[2]) print(result[0])
print(sorted(result[1]))
for result in best_percentage: print(sorted(result[2]))
print(result[0]) print()
print(result[1])
print(result[2])
# team_table(score, team0, team1) # team_table(score, team0, team1)
return best_percentage[0] return best
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,5 +1,5 @@
#root { #root {
max-width: 60vw; max-width: 70vw;
margin: 0 auto; margin: 0 auto;
padding: 2rem; padding: 2rem;
text-align: center; text-align: center;
@ -11,4 +11,5 @@
.read-the-docs { .read-the-docs {
color: #888; color: #888;
padding: 0;
} }

View File

@ -1,3 +1,4 @@
import { useState } from "react";
import Table from "@mui/material/Table"; import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody"; import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell"; import TableCell from "@mui/material/TableCell";
@ -6,12 +7,47 @@ import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow"; import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper"; import Paper from "@mui/material/Paper";
import data from "./table.json"; import data from "./table.json";
import {
Box,
Checkbox,
FormControlLabel,
Stack,
Switch,
Typography,
} from "@mui/material";
interface Data {
[index: string]: Teams;
}
interface Teams {
teamname: Row;
}
type Row = [player: string, fulfilled: number, total: number]; type Row = [player: string, fulfilled: number, total: number];
export default function TeamTables() { function RenderTable(data: object) {
let nMatches: number = 0;
let nTotal: number = 0;
let nPlayers: number = 0;
let relativeScore: number = 0.0;
for (const rows of Object.values(data)) {
for (const row of rows) {
nMatches += row[1];
nTotal += row[2];
relativeScore += row[1] / row[2];
nPlayers++;
}
}
return ( return (
<> <>
<Paper elevation={2} sx={{ p: 2, display: "inline-block" }}>
average wishes fulfilled:{" "}
<Typography sx={{ fontFamily: "monospace" }}>
{(nMatches / nPlayers).toPrecision(2)} (
{((relativeScore / nPlayers) * 100).toPrecision(3)}%)
</Typography>
</Paper>
{Object.entries(data).map(([teamname, rows]) => ( {Object.entries(data).map(([teamname, rows]) => (
<> <>
<h1>{teamname}</h1> <h1>{teamname}</h1>
@ -47,3 +83,69 @@ export default function TeamTables() {
</> </>
); );
} }
export default function TeamTables() {
const [total, setTotal] = useState("relative");
const [unique, setUnique] = useState("non-unique");
const handleTotalChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.checked) {
setTotal("relative");
} else {
setTotal("total");
}
};
const handleUniqueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
if (event.target.checked) {
setUnique("unique");
} else {
setUnique("non-unique");
}
};
let tabledata: Data = data as unknown as Data;
return (
<>
<Box
sx={{
m: "auto",
display: "flex",
flexWrap: "wrap",
justifyContent: "center",
}}
>
<Paper elevation={2} sx={{ m: 1, p: 1 }}>
<Typography className="read-the-docs">according to</Typography>
<Stack
direction="row"
spacing={1}
sx={{ p: "0 16px", m: "0 8px", alignItems: "center" }}
>
<Typography>total</Typography>
<Switch defaultChecked onChange={handleTotalChange} />
<Typography>relative</Typography>
</Stack>
<Typography className="read-the-docs">
number of wishes fulfilled
</Typography>
</Paper>
<Paper elevation={2} sx={{ m: 1, p: 1, justifyContent: "center" }}>
<FormControlLabel
sx={{ padding: 2, m: 1 }}
control={
<Checkbox
checked={unique === "unique"}
onChange={handleUniqueChange}
/>
}
label="unique first names"
/>
</Paper>
</Box>
{RenderTable(tabledata[[total, unique].join(",") as string])}
</>
);
}