sendou.ink/app/features/plus-voting/loaders/plus.voting.results.server.ts
Kalle d2551d2706
Some checks failed
Tests and checks on push / run-checks-and-tests (push) Has been cancelled
Updates translation progress / update-translation-progress-issue (push) Has been cancelled
Global roles refactor (#2212)
* Initial

* isMod etc.

* canPerformAdminActions

* isAdmin

* isSupporter

* admin override

* Lohi

* Badge manage with new permissions style

* Refactor badge loading logic

* Move funcs

* Delete permissions.ts

* DRY
2025-04-21 23:51:30 +03:00

96 lines
2.6 KiB
TypeScript

import type { LoaderFunctionArgs } from "@remix-run/node";
import type { UserWithPlusTier } from "~/db/tables";
import { getUser } from "~/features/auth/core/user.server";
import * as PlusVotingRepository from "~/features/plus-voting/PlusVotingRepository.server";
import { lastCompletedVoting } from "~/features/plus-voting/core";
import { isSupporter } from "~/modules/permissions/utils";
import invariant from "~/utils/invariant";
import { roundToNDecimalPlaces } from "~/utils/number";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const user = await getUser(request);
const results = await PlusVotingRepository.resultsByMonthYear(
lastCompletedVoting(new Date()),
);
return {
results: censorScores(results),
ownScores: ownScores({ results, user }),
lastCompletedVoting: lastCompletedVoting(new Date()),
};
};
function censorScores(results: PlusVotingRepository.ResultsByMonthYearItem[]) {
return results.map((tier) => ({
...tier,
passed: tier.passed.map((result) => ({
...result,
score: undefined,
})),
failed: tier.failed.map((result) => ({
...result,
score: undefined,
})),
}));
}
function ownScores({
results,
user,
}: {
results: PlusVotingRepository.ResultsByMonthYearItem[];
user?: Pick<UserWithPlusTier, "id" | "patronTier">;
}) {
return results
.flatMap((tier) => [...tier.failed, ...tier.passed])
.filter((result) => {
return result.id === user?.id;
})
.map((result) => {
const showScore =
(result.wasSuggested && !result.passedVoting) || isSupporter(user);
const resultsOfOwnTierExcludingOwn = () => {
const ownTierResults = results.find(
(tier) => tier.tier === result.tier,
);
invariant(ownTierResults, "own tier results not found");
return [...ownTierResults.failed, ...ownTierResults.passed].filter(
(otherResult) => otherResult.id !== result.id,
);
};
const mappedResult: {
tier: number;
score?: number;
passedVoting: number;
betterThan?: number;
} = {
tier: result.tier,
score: databaseAvgToPercentage(result.score),
passedVoting: result.passedVoting,
betterThan: roundToNDecimalPlaces(
(resultsOfOwnTierExcludingOwn().filter(
(otherResult) => otherResult.score <= result.score,
).length /
resultsOfOwnTierExcludingOwn().length) *
100,
),
};
if (!showScore) mappedResult.score = undefined;
if (!isSupporter(user) || !result.passedVoting) {
mappedResult.betterThan = undefined;
}
return mappedResult;
});
}
function databaseAvgToPercentage(score: number) {
const scoreNormalized = score + 1;
return roundToNDecimalPlaces((scoreNormalized / 2) * 100);
}