sendou.ink/services/xtrends.ts
Kalle 1589b84c4b
New layout (#427) closes #405
* 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
2021-04-21 17:26:50 +03:00

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,
};