dots for chart

This commit is contained in:
Sendou
2020-05-24 12:21:40 +03:00
parent 79aba396f8
commit b5b63b3366
3 changed files with 199 additions and 62 deletions

View File

@@ -1,29 +1,20 @@
import {
Box,
Flex,
Popover,
PopoverContent,
PopoverTrigger,
Progress,
} from "@chakra-ui/core"
import React, { useContext, useState } from "react"
import { FaChartLine, FaQuestion } from "react-icons/fa"
import { Explanation } from "../../hooks/useAbilityEffects"
import MyThemeContext from "../../themeContext"
import { Ability, Build } from "../../types"
import { mainOnlyAbilities } from "../../utils/lists"
import {
Progress,
Box,
Flex,
Popover,
PopoverTrigger,
PopoverContent,
} from "@chakra-ui/core"
import AbilityIcon from "../builds/AbilityIcon"
import {
LineChart,
CartesianGrid,
XAxis,
YAxis,
Legend,
Tooltip,
Line,
ResponsiveContainer,
} from "recharts"
import IconButton from "../elements/IconButton"
import { FaChartLine, FaInfo, FaQuestion } from "react-icons/fa"
import StatChart from "./StatChart"
interface BuildStatsProps {
explanations: Explanation[]
@@ -38,7 +29,11 @@ const BuildStats: React.FC<BuildStatsProps> = ({
build,
hideExtra,
}) => {
const { colorMode, themeColorWithShade } = useContext(MyThemeContext)
const { colorMode } = useContext(MyThemeContext)
const [expandedCharts, setExpandedCharts] = useState<Set<string>>(
new Set(["Shots per ink tank"])
)
const abilityArrays: Ability[][] = [
build.headgear ?? [],
build.clothing ?? [],
@@ -68,6 +63,10 @@ const BuildStats: React.FC<BuildStatsProps> = ({
progressBarValue: number
otherProgressBarValue?: number
getEffect?: (ap: number) => number
ap: number
otherAp?: number
chartExpanded: boolean
toggleChart: () => void
}> = ({
title,
effect,
@@ -76,21 +75,14 @@ const BuildStats: React.FC<BuildStatsProps> = ({
otherProgressBarValue,
getEffect,
info,
ap,
otherAp,
chartExpanded,
toggleChart,
progressBarValue = 0,
}) => {
const [showChart, setShowChart] = useState(false)
const { themeColorHex, darkerBgColor, themeColorWithShade } = useContext(
MyThemeContext
)
const { darkerBgColor, themeColorWithShade } = useContext(MyThemeContext)
const getData = () => {
const toReturn = []
for (let i = 0; i < 58; i++) {
toReturn.push({ name: `${i}AP`, [title]: getEffect!(i) })
}
return toReturn
}
return (
<>
<Flex justifyContent="space-between">
@@ -98,10 +90,7 @@ const BuildStats: React.FC<BuildStatsProps> = ({
<Box mr="0.5em">
<AbilityIcon ability={ability} size="TINY" />
</Box>
<IconButton
icon={FaChartLine}
onClick={() => setShowChart(!showChart)}
/>
<IconButton icon={FaChartLine} onClick={() => toggleChart()} />
{title}
{info && (
<Popover trigger="hover" placement="top-start">
@@ -162,39 +151,20 @@ const BuildStats: React.FC<BuildStatsProps> = ({
</Flex>
</>
)}
{getEffect && showChart && (
{getEffect && chartExpanded && (
<Box my="1em" ml="-26px">
<ResponsiveContainer width="100%" height={300}>
<LineChart data={getData()}>
<CartesianGrid strokeDasharray="3 3" color="#000" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip
contentStyle={{
background: darkerBgColor,
borderRadius: "5px",
border: 0,
}}
/>
<Legend />
<Line
type="monotone"
dataKey={title}
stroke={themeColorHex}
dot={false}
/>
</LineChart>
</ResponsiveContainer>
<StatChart
title={title}
ap={ap}
otherAp={otherAp}
getEffect={getEffect}
/>
</Box>
)}
</>
)
}
/*const explanationsToUse = !hideExtra
? explanations
: explanations.filter((e) => e.effectFromMax !== 0)*/
return (
<>
{explanations.map((_explanation, index) => {
@@ -224,6 +194,19 @@ const BuildStats: React.FC<BuildStatsProps> = ({
otherProgressBarValue={otherExplanation?.effectFromMax}
getEffect={explanation.getEffect}
info={explanation.info}
ap={explanation.ap}
otherAp={otherExplanation?.ap}
chartExpanded={expandedCharts.has(explanation.title)}
toggleChart={() => {
const newSet = new Set(expandedCharts)
if (newSet.has(explanation.title)) {
newSet.delete(explanation.title)
} else {
newSet.add(explanation.title)
}
setExpandedCharts(newSet)
}}
/>
</Box>
)

View File

@@ -0,0 +1,114 @@
import React, { useContext } from "react"
import {
ResponsiveContainer,
LineChart,
CartesianGrid,
XAxis,
YAxis,
Tooltip,
Legend,
Line,
} from "recharts"
import MyThemeContext from "../../themeContext"
interface StatChartProps {
title: string
getEffect: (ap: number) => number
ap: number
otherAp?: number
}
const StatChart: React.FC<StatChartProps> = ({
title,
ap,
otherAp,
getEffect,
}) => {
const { themeColorHex, darkerBgColor } = useContext(MyThemeContext)
const getData = () => {
const toReturn = []
for (let i = 0; i < 58; i++) {
toReturn.push({ name: `${i}AP`, [title]: getEffect(i) })
}
return toReturn
}
const CustomizedDot = (props: any) => {
const { cx, cy, payload } = props
if (payload.name === `${ap}AP`) {
return (
<svg
x={cx - 5}
y={cy - 5}
width={100}
height={100}
fill="red"
viewBox="0 0 1024 1024"
>
<circle
cx="50"
cy="50"
r="40"
stroke="white"
strokeWidth="18"
fill="#DD6B20"
/>
</svg>
)
}
if (payload.name === `${otherAp}AP`) {
return (
<svg
x={cx - 5}
y={cy - 5}
width={100}
height={100}
fill="red"
viewBox="0 0 1024 1024"
>
<circle
cx="50"
cy="50"
r="40"
stroke="white"
strokeWidth="18"
fill="#3182CE"
/>
</svg>
)
}
return null
}
return (
<ResponsiveContainer width="100%" height={300}>
<LineChart data={getData()}>
<CartesianGrid strokeDasharray="3 3" color="#000" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip
contentStyle={{
background: darkerBgColor,
borderRadius: "5px",
border: 0,
}}
/>
<Legend />
<Line
type="monotone"
dataKey={title}
stroke={themeColorHex}
dot={<CustomizedDot />}
isAnimationActive={false}
/>
</LineChart>
</ResponsiveContainer>
)
}
export default StatChart

View File

@@ -12,6 +12,7 @@ export interface Explanation {
ability: Ability
info?: string
getEffect?: (ap: number) => number
ap: number
}
function buildToAP(build: Partial<Build>) {
@@ -102,6 +103,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
parseFloat(
(1 / (mInkConsume * getEffect(highMidLow, ap)[0])).toFixed(2)
),
ap: amount,
})
}
@@ -119,6 +121,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
parseFloat(
(1 / (mInkConsumeRepeat * getEffect(highMidLow, ap)[0])).toFixed(2)
),
ap: amount,
})
}
@@ -139,6 +142,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
(mFullChargeInkConsume * getEffect(highMidLow, ap)[0])
).toFixed(2)
),
ap: amount,
})
}
@@ -158,6 +162,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
2
)
),
ap: amount,
})
}
@@ -183,6 +188,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
(mInkConsumeSplashJump * getEffect(highMidLow, ap)[0])
).toFixed(2)
),
ap: amount,
})
} else if (mInkConsumeSplashJump && mInkConsumeSplashStand) {
toReturn.push({
@@ -200,6 +206,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
(mInkConsumeSplashStand * getEffect(highMidLow, ap)[0])
).toFixed(2)
),
ap: amount,
})
toReturn.push({
@@ -217,6 +224,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
(mInkConsumeSplashJump * getEffect(highMidLow, ap)[0])
).toFixed(2)
),
ap: amount,
})
}
@@ -238,6 +246,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
2
)
),
ap: amount,
})
}
@@ -259,6 +268,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
2
)
),
ap: amount,
})
}
@@ -294,6 +304,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
(effect[0] * inkConsumption * 100).toFixed(2)
),
ability: "ISS" as Ability,
ap: amount,
},
]
}
@@ -329,6 +340,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
effectFromMaxActual:
(effectSquid[0] / getEffect(highMidLowSquid, 0)[0]) * 100,
ability: "REC" as Ability,
ap: amount,
},
/*{
title: "Ink tank recovery from empty to full (humanoid form)",
@@ -382,6 +394,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} distance units / frame`,
effectFromMax: moveEffect[1],
ability: "RSU" as Ability,
ap: amount,
},
{
title: "Run speed (firing)",
@@ -390,6 +403,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} distance units / frame`,
effectFromMax: shootEffect[1],
ability: "RSU" as Ability,
ap: amount,
},
]
}
@@ -423,6 +437,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
effect: `${parseFloat(effect[0].toFixed(2))} distance units / frame`,
effectFromMax: effect[1],
ability: "SSU" as Ability,
ap: amount,
},
]
}
@@ -448,6 +463,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}p)`,
effectFromMax: effect[1],
ability: "SCU" as Ability,
ap: amount,
},
]
}
@@ -471,6 +487,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}% of the charge`,
effectFromMax: effect[1],
ability: "SS" as Ability,
ap: amount,
})
if (weaponData[build.weapon!].Special === "Splashdown") {
@@ -490,6 +507,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
effect: `${parseFloat(((1.0 - lost) * 100).toFixed(2))}% of the charge`,
effectFromMax: fromMax,
ability: "SS" as Ability,
ap: amount,
})
}
@@ -525,6 +543,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
specialWeapon === "Inkjet"
? "Special Power Up also increases Ink Jet's shots' painting and blast radius"
: undefined,
ap: amount,
})
}
@@ -551,6 +570,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effect[1],
ability: "SPU" as Ability,
ap: amount,
})
toReturn.push({
title: "Tenta Missiles ink coverage",
@@ -559,6 +579,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effectPaint[1],
ability: "SPU" as Ability,
ap: amount,
})
}
@@ -585,6 +606,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effectNear[1],
ability: "SPU" as Ability,
ap: amount,
})
toReturn.push({
title: "Splashdown 70dmg hitbox size",
@@ -595,6 +617,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
ability: "SPU" as Ability,
info:
"55dmg hitbox can't be increased with Special Power Up so the total radius of the special doesn't change",
ap: amount,
})
}
@@ -612,6 +635,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} seconds)`,
effectFromMax: effect[1],
ability: "SPU" as Ability,
ap: amount,
})
}
@@ -631,6 +655,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
ability: "SPU" as Ability,
info:
"Amount inked by Ink Storm is not increased only in how long distance the droplets are spread",
ap: amount,
})
}
@@ -649,6 +674,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effect[1],
ability: "SPU" as Ability,
ap: amount,
})
const highHit = specialWeaponData.mBurst_Radius_FarHigh
@@ -665,6 +691,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effectHit[1],
ability: "SPU" as Ability,
ap: amount,
})
}
@@ -683,6 +710,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effectSize[1],
ability: "SPU" as Ability,
ap: amount,
})
const highHit = specialWeaponData.mCollisionPlayerRadiusMaxHigh
@@ -699,6 +727,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effectHit[1],
ability: "SPU" as Ability,
ap: amount,
})
}
@@ -717,6 +746,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effect[1],
ability: "SPU" as Ability,
ap: amount,
})
}
@@ -750,6 +780,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
ability: "QR" as Ability,
info:
"Quick Respawn activates when enemy kills you twice without you getting a kill in between",
ap: amount,
},
]
}
@@ -777,6 +808,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} seconds)`,
effectFromMax: effectTame[1],
ability: "QSJ" as Ability,
ap: amount,
},
{
title: "Quick Super Jump time (in the air)",
@@ -785,6 +817,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} seconds)`,
effectFromMax: effectMove[1],
ability: "QSJ" as Ability,
ap: amount,
},
]
}
@@ -831,6 +864,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}% (${parseFloat(effectVelo[0].toFixed(2))})`,
effectFromMax: effectVelo[1],
ability: "BRU" as Ability,
ap: amount,
})
}
@@ -848,6 +882,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} seconds)`,
effectFromMax: effectFirst[1],
ability: "BRU" as Ability,
ap: amount,
})
const highSecond = subWeaponData.mPeriod_SecondHigh
@@ -863,6 +898,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} seconds)`,
effectFromMax: effectSecond[1],
ability: "BRU" as Ability,
ap: amount,
})
}
@@ -880,6 +916,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)} seconds)`,
effectFromMax: effect[1],
ability: "BRU" as Ability,
ap: amount,
})
}
@@ -898,6 +935,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effect[1],
ability: "BRU" as Ability,
ap: amount,
})
}
@@ -916,6 +954,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
)}%`,
effectFromMax: effect[1],
ability: "BRU" as Ability,
ap: amount,
})
}
@@ -931,6 +970,7 @@ export default function useAbilityEffects(build: Partial<Build>) {
effect: `${Math.floor(effect[0])}AP`,
effectFromMax: effect[1],
ability: "BRU" as Ability,
ap: amount,
info:
"When jumping to Sub Power Up boosted beakons QSJ AP bonus is applied on top of any existing QSJ the jumper has. 57AP can't be exceeded",
})