Skip to content

Commit

Permalink
Allows for league admin to have prediction points recalculated (#847)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukasdotcom authored Dec 19, 2024
1 parent c3e6e25 commit 7a4d5ce
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 45 deletions.
24 changes: 24 additions & 0 deletions components/LeagueAdminPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,30 @@ function AdminPanelAdmin({
>
{t("Save admin settings")}
</Button>
<br />
<br />
<Button
variant="outlined"
onClick={async () => {
const res = await fetch(`/api/league/${league}/recalculate`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
predictions: true,
}),
});
if (res.ok) {
notify(t(await res.text()), "success");
Router.push(Router.asPath);
} else {
notify(t(await res.text()), "error");
}
}}
>
{t("Recalculate Prediction Points")}
</Button>
</>
);
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"dev:part2": "ts-node --project=tsconfig2.json scripts/entrypoint.ts & next dev",
"build": "export NODE_ENV=production APP_ENV=production && npm ci && npm run start2:part1 && next build",
"start": "export NODE_ENV=production APP_ENV=production && npm run start2",
"test": "export NODE_ENV=test APP_ENV=test && ts-node --project=tsconfig2.json scripts/jestSetup.ts && jest",
"test": "export NODE_ENV=test APP_ENV=test && ts-node --project=tsconfig2.json scripts/jestSetup.ts && jest --watch",
"start:test": "export NODE_ENV=test APP_ENV=test && npm run clean && npm run start2",
"start2": "npm run start2:part1 && npm run start2:part2",
"start2:part1": "ts-node --project=tsconfig2.json scripts/startup.ts",
Expand Down
80 changes: 80 additions & 0 deletions pages/api/league/[league]/recalculate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import connect from "../../../../Modules/database";
import { authOptions } from "#/pages/api/auth/[...nextauth]";
import { getServerSession } from "next-auth";
import { NextApiRequest, NextApiResponse } from "next";
import { leagueUsers, points } from "#type/database";
import { calcHistoricalPredictionPoints } from "#scripts/calcPoints";

export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
const session = await getServerSession(req, res, authOptions);
if (session) {
const connection = await connect();
const league = parseInt(req.query.league as string);
// Variable to check if the league is archived
const isArchived = connection
.query("SELECT * FROM leagueSettings WHERE leagueID=? AND archived=0", [
league,
])
.then((e) => e.length === 0);
switch (req.method) {
// Used to edit a league
case "POST":
if (await isArchived) {
res.status(400).end("This league is archived");
break;
}
// Checks if the user is qualified to do this
const user: leagueUsers[] = await connection.query(
"SELECT * FROM leagueUsers WHERE leagueID=? AND user=? AND admin=1",
[league, session.user.id],
);
if (user.length === 0) {
res.status(403).end("You are not admin of this league");
break;
}
const matchdays: points[] = await connection.query(
"SELECT * FROM points WHERE leagueID=? ORDER BY user ASC",
[league],
);
let curr_user = -1;
let curr_leagueID = -1;
let change_in_points = 0;
for (const matchday of matchdays) {
if (curr_user !== matchday.user) {
if (curr_user !== -1) {
await connection.query(
"UPDATE main.leagueUsers SET points=points+?, predictionPoints=predictionPoints+? WHERE leagueID=? AND user=?",
[change_in_points, change_in_points, curr_leagueID, curr_user],
);
}
curr_user = matchday.user;
curr_leagueID = matchday.leagueID;
change_in_points = 0;
}
const points = await calcHistoricalPredictionPoints(matchday);
change_in_points += points - matchday.predictionPoints;
await connection.query(
"UPDATE points SET predictionPoints=?, points=points+? WHERE matchday=? AND leagueID=? AND user=?",
[
points,
points - matchday.predictionPoints,
matchday.matchday,
matchday.leagueID,
matchday.user,
],
);
}
res.status(200).end("Updated prediction points");
break;
default:
res.status(405).end(`Method ${req.method} Not Allowed`);
break;
}
connection.end();
} else {
res.status(401).end("Not logged in");
}
}
103 changes: 98 additions & 5 deletions scripts/calcPoints.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import connect from "../Modules/database";
import { calcPredictionsPoints, calcStarredPoints } from "./calcPoints";
import { leagueUsers, predictions } from "../types/database";
import {
calcHistoricalPredictionPoints,
calcPredicitionPointsRaw,
calcPredictionsPointsNow,
calcStarredPoints,
predictions_raw,
} from "./calcPoints";
import {
leagueSettings,
leagueUsers,
points,
predictions,
} from "../types/database";
import { describe } from "@jest/globals";

describe("calcStarredPoints", () => {
Expand All @@ -27,7 +38,7 @@ describe("calcStarredPoints", () => {
});
});

describe("calcPredictionsPoints", () => {
describe("calcPredictionsPointsNow", () => {
beforeEach(async () => {
const connection = await connect();
await connection.query("DELETE FROM predictions");
Expand Down Expand Up @@ -57,15 +68,97 @@ describe("calcPredictionsPoints", () => {
admin: false,
tutorial: false,
};
await calcPredictionsPoints(user);
await calcPredictionsPointsNow(user);
const prediction_list: predictions[] = await connection.query(
"SELECT * FROM predictions WHERE leagueID=1 AND user=1",
);
console.log(prediction_list);
for (let i = 0; i < prediction_list.length; i++) {
expect(prediction_list[i].home).not.toBeNull();
expect(prediction_list[i].away).not.toBeNull();
}
connection.end();
});
});

describe("calcPredictionsPoints", () => {
const defaultleagueSettings: leagueSettings = {
leagueID: 1,
leagueName: "test",
archived: 0,
startMoney: 0,
transfers: 0,
duplicatePlayers: 0,
starredPercentage: 0,
matchdayTransfers: false,
fantasyEnabled: false,
predictionsEnabled: true,
top11: false,
active: true,
inActiveDays: 0,
league: "league",
predictExact: 5,
predictDifference: 3,
predictWinner: 1,
};
it("no predictions", () => {
expect(calcPredicitionPointsRaw([], [], defaultleagueSettings));
});
it("Simple with exact, difference and winner", () => {
const predictions: predictions_raw[] = [
{ home: 2, away: 2, club: "1" },
{ home: 5, away: 1, club: "2" },
{ home: 5, away: 1, club: "3" },
];
const games: predictions_raw[] = [
{ home: 2, away: 2, club: "1" },
{ home: 3, away: 0, club: "2" },
{ home: 4, away: 0, club: "3" },
];
expect(
calcPredicitionPointsRaw(predictions, games, defaultleagueSettings),
).toBe(9);
});
});

describe("calcHistoricalPredictionPoints", () => {
const point_data: points = {
leagueID: 1,
user: 1,
points: 0,
fantasyPoints: 0,
predictionPoints: 0,
time: 1,
matchday: 1,
money: 0,
};
beforeEach(async () => {
const connection = await connect();
await connection.query("DELETE FROM leagueSettings");
await connection.query("DELETE FROM historicalClubs");
await connection.query(
"INSERT INTO leagueSettings (leagueID, predictExact, league) VALUES (1, 10, 'league')",
);
await connection.query(
"INSERT INTO historicalClubs (home, time, teamScore, opponentScore, club, league) VALUES (1, 1, 1, 1, 'test', 'league')",
);
await connection.query(
"INSERT INTO leagueUsers (user, leagueID) VALUES (1, 1)",
);
connection.end();
});
it("no prediction", async () => {
const connection = await connect();
await connection.query("DELETE FROM historicalPredictions");
expect(await calcHistoricalPredictionPoints(point_data)).toBe(0);
connection.end();
});
it("one prediction", async () => {
const connection = await connect();
await connection.query("DELETE FROM historicalPredictions");
await connection.query(
"INSERT INTO historicalPredictions (user, leagueID, matchday, home, away, club) VALUES (1, 1, 1, 1, 1, 'test')",
);
expect(await calcHistoricalPredictionPoints(point_data)).toBe(10);
connection.end();
});
});
Loading

0 comments on commit 7a4d5ce

Please sign in to comment.