Skip to content

Commit 5483eb6

Browse files
committed
Add graphs to gc
1 parent 8afe1e9 commit 5483eb6

File tree

6 files changed

+150
-27
lines changed

6 files changed

+150
-27
lines changed

components/Toasts.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ToastContainer } from "react-toastify"
2+
import "react-toastify/dist/ReactToastify.css"
3+
4+
5+
const contextClass = {
6+
success: "bg-green-600 dark:bg-green-900",
7+
error: "bg-red-600 dark:bg-red-900",
8+
info: "bg-gray-600 dark:bg-gray-900",
9+
warning: "bg-orange-400 dark:bg-orange-800",
10+
default: "bg-indigo-600 dark:bg-indigo-900",
11+
dark: "bg-white-600 dark:bg-white-900",
12+
}
13+
14+
export default function Toast() {
15+
return <ToastContainer
16+
toastClassName={({ type = "default" } = {}) => contextClass[type || "default"] +
17+
" relative flex p-1 min-h-10 rounded-md justify-between overflow-hidden cursor-pointer"
18+
}
19+
position="bottom-center"
20+
theme={"colored"}
21+
/>
22+
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
"lint": "next lint"
99
},
1010
"dependencies": {
11+
"chart.js": "^3.7.0",
1112
"cookie": "^0.4.1",
1213
"jsonwebtoken": "^8.5.1",
1314
"next": "12.0.7",
1415
"node-fetch": "2.6.6",
1516
"react": "17.0.2",
17+
"react-chartjs-2": "^4.0.1",
1618
"react-dom": "17.0.2",
1719
"react-markdown": "^7.1.1",
1820
"react-modal": "^3.14.4",

pages/_app.tsx

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
11
import type { AppProps } from "next/app"
22
import Head from "next/head"
33
import { useEffect } from "react"
4-
import { ToastContainer } from "react-toastify"
5-
import "react-toastify/dist/ReactToastify.css"
64
import "tailwindcss/tailwind.css"
75
import Footer from "../components/Footer"
86
import NavBar from "../components/NavBar"
97
import "../public/global.css"
108
import * as gtag from "../utils/gtag"
119

12-
const contextClass = {
13-
success: "bg-green-600 dark:bg-green-900",
14-
error: "bg-red-600 dark:bg-red-900",
15-
info: "bg-gray-600 dark:bg-gray-900",
16-
warning: "bg-orange-400 dark:bg-orange-800",
17-
default: "bg-indigo-600 dark:bg-indigo-900",
18-
dark: "bg-white-600 dark:bg-white-900",
19-
}
20-
2110
export default function MyApp({ Component, pageProps, router }: AppProps) {
2211
useEffect(() => {
2312
const handleRouteChange = (url: string) => {
@@ -41,13 +30,7 @@ export default function MyApp({ Component, pageProps, router }: AppProps) {
4130
<div className="p-4 flex flex-col w-full flex-1 px-1 lg:px-20 items-center justify-center">
4231
<Component {...pageProps} location={router.asPath} />
4332
</div>
44-
<ToastContainer
45-
toastClassName={({ type = "default" } = {}) => contextClass[type || "default"] +
46-
" relative flex p-1 min-h-10 rounded-md justify-between overflow-hidden cursor-pointer"
47-
}
48-
position="bottom-center"
49-
theme={"colored"}
50-
/>
33+
5134
</div>
5235
<Footer />
5336
</div>

pages/tools/gachacalc.tsx

Lines changed: 105 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
1+
import {
2+
BarElement, CategoryScale, Chart as ChartJS, Legend, LinearScale, LineElement, PointElement, Tooltip
3+
} from "chart.js"
14
import Head from "next/head"
2-
import { useEffect, useState } from "react"
5+
import { DependencyList, EffectCallback, useEffect, useState } from "react"
6+
import { Chart } from "react-chartjs-2"
37
import FormattedLink from "../../components/FormattedLink"
48
import Main from "../../components/Main"
59
import styles from "../style.module.css"
610

11+
ChartJS.register(
12+
LinearScale,
13+
CategoryScale,
14+
BarElement,
15+
PointElement,
16+
LineElement,
17+
Legend,
18+
Tooltip
19+
)
20+
721
function pityRate(baseRate: number, pityStart: number): (pity: number) => number {
822
return (pity) => pity < pityStart ? baseRate : baseRate + baseRate * 10 * (pity - pityStart + 1)
923
}
@@ -69,6 +83,7 @@ type ReducedSim = {
6983
rate: number
7084
}
7185

86+
7287
export default function GachaCalc({ location }: { location: string }) {
7388
const [current, setCurrent] = useState(-1)
7489
const [pity, setPity] = useState(0)
@@ -82,10 +97,18 @@ export default function GachaCalc({ location }: { location: string }) {
8297

8398
const banner = Object.values(gachas).find(x => x.bannerName == gachaName) ?? Object.values(gachas)[0]
8499

85-
if (pity >= banner.maxPity) setPity(banner.maxPity - 1)
86-
if (banner.guaranteedPity && guaranteedPity >= banner.guaranteedPity) setGuaranteedPity(banner.guaranteedPity)
87-
if (current > banner.maxConst) setCurrent(banner.maxConst)
88-
if (current < banner.minConst) setCurrent(banner.minConst)
100+
function delayed(f: EffectCallback) {
101+
const timeout = setTimeout(() => {
102+
f()
103+
}, 3000)
104+
105+
return () => clearTimeout(timeout)
106+
}
107+
108+
useEffect(() => delayed(() => { if (pity >= banner.maxPity) setPity(banner.maxPity - 1) }), [banner, pity])
109+
useEffect(() => delayed(() => { if (banner.guaranteedPity && guaranteedPity >= banner.guaranteedPity) setGuaranteedPity(banner.guaranteedPity) }), [banner, guaranteedPity])
110+
useEffect(() => delayed(() => { if (current > banner.maxConst) setCurrent(banner.maxConst) }), [banner, current])
111+
useEffect(() => delayed(() => { if (current < banner.minConst) setCurrent(banner.minConst) }), [current, banner])
89112

90113
useEffect(
91114
() => setCalculated(calcSimsRegular(current, pity, pulls, guaranteed, guaranteedPity, banner)),
@@ -115,7 +138,7 @@ export default function GachaCalc({ location }: { location: string }) {
115138

116139
<SelectInput label="Banner type" set={(g) => {
117140
if (current == banner.minConst)
118-
setCurrent(-5)
141+
setCurrent((Object.values(gachas).find(x => x.bannerName == g) ?? Object.values(gachas)[0]).minConst)
119142
setGacha(g)
120143
}} value={gachaName} options={Object.values(gachas).map(g => g.bannerName)} />
121144
<NumberInput label="Pulls" set={setPulls} value={pulls} min={0} max={1260} />
@@ -125,7 +148,76 @@ export default function GachaCalc({ location }: { location: string }) {
125148
{banner.guaranteedPity && <NumberInput label="Epitomized Path" set={setGuaranteedPity} value={guaranteedPity} min={0} max={banner.guaranteedPity - 1} />}
126149

127150
<h3 className="text-lg font-bold pt-1" id="resistance">Results:</h3>
128-
<table className={`table-auto w-80 ${styles.table} ${styles.stattable} mb-2 sm:text-base text-sm`}>
151+
<div className="columns-1 md:columns-2 mr-2">
152+
<div className="w-full bg-slate-800 rounded-xl p-1 my-2 md:my-0 text-white col-start-1">
153+
<Chart type="bar" data={({
154+
labels: calculated.filter(x => x).map(c => getName(c, banner)),
155+
datasets: [
156+
{
157+
type: "bar" as const,
158+
label: "Rate",
159+
backgroundColor: "rgb(75, 192, 192)",
160+
data: calculated.filter(x => x).map((c, i, a) => c.rate * 100),
161+
borderColor: "white",
162+
borderWidth: 2,
163+
xAxisID: "xAxes"
164+
},
165+
],
166+
})} options={({
167+
indexAxis: "y",
168+
color: "white",
169+
backgroundColor: "#333333",
170+
scales: {
171+
xAxes: {
172+
min: 0,
173+
ticks: {
174+
color: "white",
175+
callback: (v) => `${v}%`
176+
}
177+
},
178+
yAxes: {
179+
ticks: {
180+
color: "white"
181+
}
182+
}
183+
}
184+
})} /></div>
185+
<div className="w-full bg-slate-800 rounded-xl p-1 my-2 md:my-0 text-white col-start-2">
186+
<Chart type="bar" data={({
187+
labels: calculated.filter(x => x).map(c => getName(c, banner)),
188+
datasets: [
189+
{
190+
type: "line" as const,
191+
label: "Cumulative rate",
192+
borderColor: "rgb(255, 99, 132)",
193+
borderWidth: 2,
194+
fill: false,
195+
data: calculated.filter(x => x).map((c, i, a) => a.slice(i, a.length).reduce((p, c) => p + c.rate, 0) * 100),
196+
},
197+
],
198+
})} options={({
199+
indexAxis: "y",
200+
color: "white",
201+
backgroundColor: "#333333",
202+
scales: {
203+
xAxes: {
204+
max: 100,
205+
min: 0,
206+
ticks: {
207+
color: "white",
208+
callback: (v) => `${v}%`
209+
}
210+
},
211+
yAxes: {
212+
ticks: {
213+
color: "white"
214+
}
215+
}
216+
}
217+
})} />
218+
</div>
219+
</div>
220+
<table className={`table-auto w-80 ${styles.table} ${styles.stattable} my-2 sm:text-base text-sm`}>
129221
<thead>
130222
<tr className="divide-x divide-gray-200 dark:divide-gray-500">
131223
<th>{banner.constName}</th>
@@ -134,9 +226,9 @@ export default function GachaCalc({ location }: { location: string }) {
134226
</tr>
135227
</thead>
136228
<tbody className="divide-y divide-gray-200 dark:divide-gray-500">
137-
{calculated
229+
{calculated.filter(x => x)
138230
.map((c, i, a) => <tr className={`pr-1 divide-x divide-gray-200 dark:divide-gray-500 ${c.rate < 0.0005 ? "opacity-60" : ""}`} key={c.const}>
139-
<td>{c.const == banner.minConst ? "Not owned" : `${banner.constFormat}${c.const}`}</td>
231+
<td>{getName(c, banner)}</td>
140232
<td>{(c.rate * 100).toFixed(3)}%</td>
141233
<td>{(a.slice(i, a.length).reduce((p, c) => p + c.rate, 0) * 100).toFixed(2)}%</td>
142234
</tr>)}
@@ -146,6 +238,10 @@ export default function GachaCalc({ location }: { location: string }) {
146238
)
147239
}
148240

241+
function getName(c: ReducedSim, banner: Banner) {
242+
return c.const == banner.minConst ? "Not owned" : `${banner.constFormat}${c.const}`
243+
}
244+
149245
function NumberInput({ value, set, label, min, max }: { value: number, set: (newValue: number) => unknown, label: string, min?: number, max?: number }) {
150246
return <div><label>
151247
{label}

pages/tools/reminders.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import ReactModal from "react-modal"
66
import { toast } from "react-toastify"
77
import FormattedLink from "../../components/FormattedLink"
88
import Main from "../../components/Main"
9+
import Toast from "../../components/Toasts"
910
import { config } from "../../utils/config"
1011
import * as gtag from "../../utils/gtag"
1112
import { parseUser } from "../../utils/parse-user"
@@ -111,6 +112,7 @@ export default class Reminders extends Component<Props & { location: string }, {
111112
addReminder={(r) => this.setState({ reminders: [...reminders, r] })}
112113
/>
113114
</div>
115+
<Toast />
114116
</Main>
115117
)
116118
}

pnpm-lock.yaml

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)