mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-13 14:31:10 -05:00
* side layout initial * add elements to side nav * side buttons links * remove clog * calendar page initial * position sticky working * x trends page initial * new table * same mode selector * mobile friendly table * no underline for nav links * xsearch * x trends page outlined * sr initial * relocate calendar components * calendar fix flex * topnav fancier look * layout looking good edition * relocate xtrends * xtrends remove linecharts * x trends new * calender page new * delete headbanner, new login * remove calendar stuff from api * rename stuff in utils * fix user item margin * new home page initial * remove page concept * no pointer xtrends * remove xrank from app * xtrends service * move fa from app * move plus * maps tweaks * new table for plus history * navigational sidebar flex tweaks * builds page * analyzer * user page * free agents * plans * remove mx * tweaks * change layout to grid * home page finalized * mobile nav * restrict main content width * tweaks style * language switcher * container in css * sticky nav * use duplicate icons for now * change mapsketch width to old * chara tour vid * borzoic icons
90 lines
2.3 KiB
TypeScript
90 lines
2.3 KiB
TypeScript
import { RankedMode } from ".prisma/client";
|
|
import prisma from "prisma/client";
|
|
import { truncuateFloat } from "utils/numbers";
|
|
import { Unpacked } from "utils/types";
|
|
|
|
export type XTrends = Record<
|
|
RankedMode,
|
|
{
|
|
weapon: string;
|
|
count: number;
|
|
percentage: number;
|
|
averageXp: number;
|
|
progress: "UP" | "DOWN" | "SAME";
|
|
}[]
|
|
>;
|
|
|
|
const getXTrends = async (): Promise<XTrends> => {
|
|
const placements = await prisma.xRankPlacement.findMany({
|
|
orderBy: [{ year: "desc" }, { month: "desc" }],
|
|
// amount of placements in top 500 * amount of months we want * amount of modes
|
|
take: 500 * 4 * 4,
|
|
});
|
|
|
|
const referenceMonths = placements.slice(0, 500 * 4 * 3);
|
|
const lastThreeMonths = placements.slice(500 * 4);
|
|
|
|
const weaponXPowersGrouped = (
|
|
acc: Record<RankedMode, Record<string, number[]>>,
|
|
placement: Unpacked<typeof placements>
|
|
) => {
|
|
if (!acc[placement.mode][placement.weapon]) {
|
|
acc[placement.mode][placement.weapon] = [];
|
|
}
|
|
|
|
acc[placement.mode][placement.weapon].push(placement.xPower);
|
|
|
|
return acc;
|
|
};
|
|
|
|
const referenceWeaponsCounts = referenceMonths.reduce(weaponXPowersGrouped, {
|
|
SZ: {},
|
|
TC: {},
|
|
RM: {},
|
|
CB: {},
|
|
});
|
|
const lastThreeMonthsWeaponCounts = lastThreeMonths.reduce(
|
|
weaponXPowersGrouped,
|
|
{
|
|
SZ: {},
|
|
TC: {},
|
|
RM: {},
|
|
CB: {},
|
|
}
|
|
);
|
|
|
|
return (["SZ", "TC", "RM", "CB"] as const).reduce(
|
|
(acc: XTrends, mode: RankedMode) => {
|
|
acc[mode] = Object.entries(lastThreeMonthsWeaponCounts[mode])
|
|
.map(([weapon, xPowers]) => {
|
|
const previousCount =
|
|
referenceWeaponsCounts[mode][weapon]?.length ?? 0;
|
|
return {
|
|
weapon,
|
|
count: xPowers.length,
|
|
percentage: truncuateFloat(
|
|
(xPowers.length / (lastThreeMonths.length / 4)) * 100
|
|
),
|
|
averageXp: truncuateFloat(
|
|
xPowers.reduce((a, b) => a + b) / xPowers.length
|
|
),
|
|
progress:
|
|
previousCount === xPowers.length
|
|
? ("SAME" as const)
|
|
: previousCount > xPowers.length
|
|
? ("DOWN" as const)
|
|
: ("UP" as const),
|
|
};
|
|
})
|
|
.sort((a, b) => b.count - a.count);
|
|
|
|
return acc;
|
|
},
|
|
{ SZ: [], TC: [], RM: [], CB: [] }
|
|
);
|
|
};
|
|
|
|
export default {
|
|
getXTrends,
|
|
};
|