Skip to content

Commit

Permalink
50 add per season per role std dev and variance metric (#98)
Browse files Browse the repository at this point in the history
* add subtitle style

* add role std dev calc implementation

* display to screen
  • Loading branch information
thearyadev committed Jan 19, 2024
1 parent 01eeba1 commit 972151b
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 5 deletions.
2 changes: 1 addition & 1 deletion frontend/app/components/card/card.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
}

.subtitle{
@apply font-extralight
@apply font-extralight text-center
}

.cardBodyWrap {
Expand Down
36 changes: 34 additions & 2 deletions frontend/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,34 @@ type SeasonData = {
[key: string]: SingleChart;
}

type StdDevs = {
DAMAGE: number;
SUPPORT: number;
TANK: number;
}


const HeroStdDev = ({value, role}: {value: number, role: string}) => {
return (
<div className="text-center pt-5 pb-5">
<h5>{role}</h5>
<h6 className="text-lg text-center">{Math.round((value + Number.EPSILON) * 100) / 100}</h6>

const Index = ({data, season_list}: { data: SeasonData, season_list: string[]}) => {
</div>
)
}

const Index = ({data, season_list, std_devs}: { data: SeasonData, season_list: string[], std_devs: StdDevs}) => {
return (
<>

<Card title="Role Standard Deviation: All Slots, All Regions" subtitle={"Note: The standard deviation is calculated with the 10th percentile excluded. T500 aggregator by nature skews the accuracy of the low outliers in a data set. For this reason, the bottom 10% of entries for any given set (support, damage or tank) is excluded from the calculation."}>
<HeroStdDev value={std_devs.SUPPORT} role={"SUPPORT"} />
<HeroStdDev value={std_devs.DAMAGE} role={"DAMAGE"}/>
<HeroStdDev value={std_devs.TANK} role={"TANK"}/>
</Card>


<Card title="Hero Occurrences: All Slots" nowrap>
{Object.keys(data).map(key => {
if (key.includes("O_ALL")){
Expand Down Expand Up @@ -74,21 +98,29 @@ const Index = ({data, season_list}: { data: SeasonData, season_list: string[]})

export async function getServerSideProps(context: GetServerSidePropsContext) {

const seasonNumber = "7"

// Make an API call using seasonNumber
const res = await fetch(`http://server:8000/chart/7_8`);
const res = await fetch(`http://server:8000/chart/${seasonNumber}_8`);
const data = await res.json();


const res2 = await fetch("http://server:8000/d/seasons")
const season_list = await res2.json()

const res3 = await fetch(`http://server:8000/d/single_season_std_by_role/${seasonNumber}_8`)
const std_devs = await res3.json()

return {
props: {
data,
season_list,
std_devs
},
};
}




export default Index
27 changes: 26 additions & 1 deletion frontend/pages/season/[seasonNumber].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,31 @@ type SeasonData = {
[key: string]: SingleChart;
}

type StdDevs = {
DAMAGE: number;
SUPPORT: number;
TANK: number;
}

const Season = ({data, season_list}: { data: SeasonData, season_list: string[]}) => {
const HeroStdDev = ({value, role}: {value: number, role: string}) => {
return (
<div className="text-center pt-5 pb-5">
<h5>{role}</h5>
<h6 className="text-lg text-center">{Math.round((value + Number.EPSILON) * 100) / 100}</h6>

</div>
)
}

const Season = ({data, season_list, std_devs}: { data: SeasonData, season_list: string[], std_devs: StdDevs}) => {
return (
<>
<Card title="Role Standard Deviation: All Slots, All Regions" subtitle={"Note: The standard deviation is calculated with the 10th percentile excluded. T500 aggregator by nature skews the accuracy of the low outliers in a data set. For this reason, the bottom 10% of entries for any given set (support, damage or tank) is excluded from the calculation."}>
<HeroStdDev value={std_devs.SUPPORT} role={"SUPPORT"} />
<HeroStdDev value={std_devs.DAMAGE} role={"DAMAGE"}/>
<HeroStdDev value={std_devs.TANK} role={"TANK"}/>
</Card>

<Card title="Hero Occurrences: All Slots" nowrap>
{Object.keys(data).map(key => {
if (key.includes("O_ALL")){
Expand Down Expand Up @@ -85,10 +106,14 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
const res2 = await fetch("http://server:8000/d/seasons")
const season_list = await res2.json()

const res3 = await fetch(`http://server:8000/d/single_season_std_by_role/${seasonNumber}_8`)
const std_devs = await res3.json()

return {
props: {
data,
season_list,
std_devs
},
};
}
Expand Down
54 changes: 53 additions & 1 deletion server.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
get_occurrences_most_played,
get_stdev,
get_variance,
get_hero_occurrences_single_season,
)
from utils.raise_for_missing_env import raise_for_missing_env_vars
import heroes
import numpy as np

load_dotenv()
templates = Jinja2Templates(directory="templates")
Expand Down Expand Up @@ -408,14 +411,63 @@ def trends_data() -> list[dict[str, list[int]]]:
return get_hero_occurrence_trend(db=db)


@lru_cache
def std_dev_data() -> dict[str, dict[str, float]]:
result: dict[str, dict[str, float]] = dict()
for season in seasons_list():
support, tank, damage = (
[
get_hero_occurrences_single_season(
db.get_all_records(seasonNumber=season), name
)
for name, role in heroes.Heroes().hero_role.items()
if role == "SUPPORT"
],
[
get_hero_occurrences_single_season(
db.get_all_records(seasonNumber=season), name
)
for name, role in heroes.Heroes().hero_role.items()
if role == "TANK"
],
[
get_hero_occurrences_single_season(
db.get_all_records(seasonNumber=season), name
)
for name, role in heroes.Heroes().hero_role.items()
if role == "DAMAGE"
],
)

# feeling creative.
# this file is a writeoff anyway.
def filter_fn(percentile):
def filter_fn_inner(x):
return x > percentile
return filter_fn_inner
exclude_percentile = 10
support = list(filter(filter_fn(np.percentile(support, exclude_percentile)), support))
damage = list(filter(filter_fn(np.percentile(damage, exclude_percentile)), damage))
tank = list(filter(filter_fn(np.percentile(tank, exclude_percentile)), tank))

result[season] = dict(SUPPORT=np.std(support), DAMAGE=np.std(damage), TANK=np.std(tank))
return result


@app.get("/d/seasons")
async def seasons_list_d():
return Response(json.dumps(seasons_list()), media_type="application/json")


@app.get("/d/single_season_std_by_role/{season}")
async def single_season_std_by_role(season: str):
return Response(
content=json.dumps(std_dev_data()[season]), media_type="application/json"
)


@app.get("/chart/{season}")
async def chart_data(season: str):
print("gnome!")
return Response(
content=json.dumps(season_data()[season]), media_type="application/json"
)
Expand Down

0 comments on commit 972151b

Please sign in to comment.