Skip to content

Commit

Permalink
logic updates
Browse files Browse the repository at this point in the history
  • Loading branch information
jonassimoen committed Jun 3, 2024
1 parent 01731e6 commit 9ba0113
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 86 deletions.
6 changes: 4 additions & 2 deletions api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,22 @@ server.get("/metrics/prisma", async (req: any, res: any) => {
})

server.setErrorHandler((err, req, rep) => {
req.log.error(err);
if (err instanceof HttpError) {
if(err.statusCode !== 401) {
req.log.error(err);
}
rep.status(err.statusCode || 500).send({
statusCode: err.statusCode || 500,
message: err.message,
});
} else {
req.log.error(err);
rep.status(500).send(err);
}
});

server.listen({ host: "0.0.0.0", port: +(process.env.PORT || 8080) }, (err, address) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`Server listening at ${address}, environment: ${process.env.ENV}`);
Expand Down
144 changes: 80 additions & 64 deletions src/controllers/Team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { finalWeekId, upcomingWeekId, validateStartingLineup } from '../utils/Co
import { prisma } from "../db/client"
import HttpError from "../utils/HttpError";
import { max } from "lodash";
import { isValidLineup } from '../utils/FootballPicker';

const CheckValidTeam = async (allPlayerIds: number[], reqBody: any, weekId: number, skipReturn?: boolean) => {
const CheckValidTeam = async (allPlayerIds: number[], reqBody: any, weekId: number, teamId?: number): Promise<{
value: number,
playersWithValues: any[],
}> => {
const [allPlayers, maxSameClub] = await Promise.all([
await prisma.player.findMany({
where: {
Expand All @@ -17,6 +19,15 @@ const CheckValidTeam = async (allPlayerIds: number[], reqBody: any, weekId: numb
clubId: true,
positionId: true,
value: true,
selections: {
select: {
value: true,
},
where: {
teamId: teamId || 0,
weekId,
}
}
},
}),
(await prisma.week.findFirst({
Expand All @@ -32,49 +43,53 @@ const CheckValidTeam = async (allPlayerIds: number[], reqBody: any, weekId: numb
deadlineDate: 'asc',
}
}))?.maxSameClub || 0
]) ;
]);
const playerSelWithValue = allPlayers.map((p: any) => {
const playerSelection = p.selections && p.selections[0];
return {...p, value: playerSelection ? playerSelection.value : p.value };
});
// Business rules checks
// 1. Correct positions
const pos = allPlayers.reduce((res: number[], cur: any) => {
const pos = playerSelWithValue.reduce((res: number[], cur: any) => {
res[cur.positionId] = (res[cur.positionId] || 0) + 1;
return res;
}, [0,0,0,0,0])
if(pos.toString() !== "0,2,5,5,3")
throw new HttpError("Wrong selection of positions", 403);
// 2. Max players from same club
const clubs = allPlayers.reduce((res: number[], cur: any) => {
const clubs = playerSelWithValue.reduce((res: number[], cur: any) => {
res[cur.clubId] = (res[cur.clubId] || 0) + 1;
return res;
}, [])
if(clubs.some(count => count > maxSameClub)) {
throw new HttpError("Too much players of the same club", 403);
}
// 3. Within budget
console.log(allPlayers);
const totalValue = allPlayers.reduce((prev, curr) => ({ id: 0, value: (prev.value || 0) + (curr.value || 0) }), { id: 0, value: 0 }).value || 0;
const totalValue = playerSelWithValue.reduce((prev, curr) => ({ id: 0, value: (prev.value || 0) + (curr.value || 0) }), { id: 0, value: 0 }).value || 0;
const budget = 100 - totalValue;
if (budget <= 0) {
if (budget < 0) {
throw new HttpError(`Invalid budget (${budget})`, 403);
}
// 4. Valid position
if(validateStartingLineup(allPlayerIds.slice(0,11))) {
if(validateStartingLineup(playerSelWithValue.reduce((res: number[], cur: any) => {
res[cur.positionId] = (res[cur.positionId] || 0) + 1;
return res;
}, [0,0,0,0,0]))) {
throw new HttpError('Invalid lineup', 403);
}
if(skipReturn) {
return;
}

return allPlayerIds.map((id: number, index: number) => {
const player = allPlayers.find((p) => p.id === id);
return {
value: totalValue,
playersWithValues: allPlayerIds.map((id: number, index: number) => {
const player = playerSelWithValue.find((p) => p.id === id);
return {
order: index + 1,
playerId: id,
value: player?.value || 0,
captain: (id === reqBody.captainId) ? 1 : (id === reqBody.viceCaptainId ? 2 : 0),
starting: player ? (reqBody.starting.includes(player?.id) ? 1 : 0) : 0,
starting: (reqBody?.starting && player) ? (reqBody.starting.includes(player?.id) ? 1 : 0) : 0,
weekId,
}
});
})};
}

export const PostAddTeamHandler = async (req: any, rep: any) => {
Expand All @@ -85,23 +100,19 @@ export const PostAddTeamHandler = async (req: any, rep: any) => {

const [weekId, lastWeekId] = await Promise.all([upcomingWeekId(), finalWeekId()]);

const allWithValues = await CheckValidTeam(allIds, req.body, weekId);

const totalValue = allWithValues!.reduce((prev, curr) => ({ id: 0, value: (prev.value || 0) + (curr.value || 0) }), { id: 0, value: 0 }).value || 0;
const budget = 100 - totalValue;
const allWithValuesForAllRemainingWeeks = allWithValues!.flatMap((p: any) => Array.from(Array(lastWeekId - weekId + 1).keys()).map(x => x + weekId).map(wId => ({ ...p, weekId: wId })));
const {value, playersWithValues} = await CheckValidTeam(allIds, req.body, weekId);
const allWithValuesForAllRemainingWeeks = playersWithValues!.flatMap((p: any) => Array.from(Array(lastWeekId - weekId + 1).keys()).map(x => x + weekId).map(wId => ({ ...p, weekId: wId })));

const [team, audit] = await prisma.$transaction([
prisma.team.create({
const team = await prisma.team.create({
data: {
userId: req.user.id,
selections: {
createMany: {
data: allWithValuesForAllRemainingWeeks,
}
},
budget: budget,
value: totalValue,
budget: 100 - value,
value: value,
valid: true,
created: new Date(Date.now()),
name: req.body.teamName,
Expand All @@ -111,34 +122,35 @@ export const PostAddTeamHandler = async (req: any, rep: any) => {
selections: true,
user: true,
}
}),
prisma.audit.create({
data: {
userId: req.user.id,
action: 'POST_CREATE_UPDATE',
params: JSON.stringify({
teamId: req.team.id,
}).then((team) => {
prisma.audit.create({
data: {
userId: req.user.id,
selections: {
createMany: {
data: allWithValuesForAllRemainingWeeks,
}
},
budget: budget,
value: totalValue,
valid: true,
created: new Date(Date.now()),
name: req.body.teamName
}),
timestamp: new Date().toISOString(),
}
}),
])
action: 'POST_CREATE_UPDATE',
params: JSON.stringify({
teamId: team.id,
userId: req.user.id,
selections: {
createMany: {
data: allWithValuesForAllRemainingWeeks,
}
},
budget: 100 - value,
value: value,
valid: true,
created: new Date(Date.now()),
name: req.body.teamName
}),
timestamp: new Date().toISOString(),
}
});
return team;
});
rep.send({
user: team.user,
team: {
id: team.id,
name: team.name,
name: team?.name,
},
status: "success"
});
Expand Down Expand Up @@ -442,20 +454,13 @@ export const PostEditTeamHandler = async (req: any, rep: any) => {

const allIds = req.body.starting.concat(req.body.bench);

let allWithValues = await CheckValidTeam(allIds, req.body, weekId);
let {value, playersWithValues} = await CheckValidTeam(allIds, req.body, weekId, +req.params.id);
let weekIds = [weekId];

const totalValue = allWithValues!.reduce((prev, curr) => ({ id: 0, value: (prev.value || 0) + (curr.value || 0) }), { id: 0, value: 0 }).value || 0;
const budget = 100 - totalValue;

if (budget <= 0) {
throw new HttpError(`Invalid team: invalid budget (${budget})`, 400);
}

if (!hasFreeHit) {
// If editing team, all selections should be updated, except if it's for FREE HIT booster. (only 1 gameday!)
weekIds = Array.from(Array(lastWeekId - weekId + 1).keys()).map(x => x + weekId);
allWithValues = allWithValues!.flatMap((p: any) => weekIds.map(wId => ({ ...p, weekId: wId })));
playersWithValues = playersWithValues!.flatMap((p: any) => weekIds.map(wId => ({ ...p, weekId: wId })));
}

const [deletion, updatedTeam, audit] = await prisma.$transaction([
Expand All @@ -474,9 +479,11 @@ export const PostEditTeamHandler = async (req: any, rep: any) => {
data: {
name: req.body.teamName,
valid: true,
budget: 100-value,
value: value,
selections: {
createMany: {
data: allWithValues!
data: playersWithValues!
}
}
},
Expand All @@ -492,9 +499,9 @@ export const PostEditTeamHandler = async (req: any, rep: any) => {
params: JSON.stringify({
teamId: +req.params.id,
userId: req.user.id,
selections: allWithValues,
budget: budget,
value: totalValue,
selections: playersWithValues,
budget: 100-value,
value: value,
valid: true,
created: new Date(Date.now()),
name: req.body.teamName
Expand All @@ -516,7 +523,7 @@ export const PostSelectionsTeamHandler = async (req: any, rep: any) => {
throw new HttpError("Invalid team: invalid number of players", 400);
}
const allIds = req.body.starting.concat(req.body.bench);
const allWithValues = await CheckValidTeam(allIds, req.body, weekId);
const {value, playersWithValues} = await CheckValidTeam(allIds, req.body, weekId, +req.params.id);

try {
await prisma.$transaction( async (prisma) => {
Expand Down Expand Up @@ -603,7 +610,7 @@ export const PostTransfersTeamHandler = async (req: any, rep: any) => {
const tf = transfers.find((t: any) => t.outId === n.playerId);
return tf ? tf.inId : n.playerId;
});
await CheckValidTeam(allTfIds, req.body, weekId, true);
const {value, playersWithValues } = await CheckValidTeam(allTfIds, req.body, weekId, +req.params.id);

const transferCreateInput = transfers.map((transfer: any) => {
return {
Expand Down Expand Up @@ -632,6 +639,15 @@ export const PostTransfersTeamHandler = async (req: any, rep: any) => {
}
})
));
await prisma.team.update({
where: {
id: +req.params.id,
},
data: {
budget: 100-value,
value: value,
}
})
await prisma.audit.create({
data: {
userId: req.user.id,
Expand Down
15 changes: 8 additions & 7 deletions src/utils/Common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ export const finalWeekId = async () => {
return (week && week.id) || 0;
}

export const validateStartingLineup = (starting: number[]) => {
if(starting.reduce((sum: number, cur: number) => sum += cur) != 11) {
// startingByPosition = [0, nrGk, nrDef, nrMid, nrFw]
export const validateStartingLineup = (startingByPosition: number[]) => {
if(startingByPosition.reduce((sum: number, cur: number) => sum += cur) != 11) {
return false;
}
return (starting[0] === 0) && // 0 COACH
(starting[1] === 1) && // 1 GK
((starting[2] >= 3) && (starting[2] <= 5)) && // 3-5 DEF
((starting[3] >= 3) && (starting[3] <= 5)) && // 3-5 MID
((starting[4] >= 1) && (starting[4] <= 3)) // 1-3 FOR
return (startingByPosition[0] === 0) && // 0 COACH
(startingByPosition[1] === 1) && // 1 GK
((startingByPosition[2] >= 3) && (startingByPosition[2] <= 5)) && // 3-5 DEF
((startingByPosition[3] >= 3) && (startingByPosition[3] <= 5)) && // 3-5 MID
((startingByPosition[4] >= 1) && (startingByPosition[4] <= 3)) // 1-3 FOR
}
14 changes: 1 addition & 13 deletions src/utils/Jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,7 @@ const percentageSelectionsTask = new AsyncTask(
return prisma.$queryRaw`call "calculatePercentageSelections"()`.then(() => console.log("Update selections percentage successfully!"));
},
(err: any) => {
console.error("UPDATING PLAYER SELECTIONS WENT WRONG!")
prisma.audit.create({
data: {
action: "UPDATE_PSELECTION",
params: "WENT WRONG",
timestamp: new Date(),
user: {
connect: {
id: 1,
}
},
}
});
console.error("UPDATING PLAYER SELECTIONS WENT WRONG!", err)
}
);

Expand Down

0 comments on commit 9ba0113

Please sign in to comment.