Skip to content

Commit da0fb2a

Browse files
committed
Add another graph
1 parent 9233254 commit da0fb2a

2 files changed

Lines changed: 80 additions & 51 deletions

File tree

pages/tools/gachacalc.tsx

Lines changed: 72 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export default function GachaCalc({ location }: { location: string }) {
9191
const [guaranteed, setGuaranteed] = useState(false)
9292
const [guaranteedPity, setGuaranteedPity] = useState(0)
9393

94-
const [calculated, setCalculated] = useState([] as ReducedSim[])
94+
const [calculated, setCalculated] = useState([[]] as ReducedSim[][])
9595

9696
const [gachaName, setGacha] = useState(Object.values(gachas).map(g => g.bannerName)[0])
9797

@@ -114,6 +114,9 @@ export default function GachaCalc({ location }: { location: string }) {
114114
() => setCalculated(calcSimsRegular(current, pity, pulls, guaranteed, guaranteedPity, banner)),
115115
[current, pity, pulls, guaranteed, guaranteedPity, banner]
116116
)
117+
const consts = []
118+
for (let i = current; i <= banner.maxConst; i++) consts.push(i)
119+
console.log(calculated)
117120

118121
const desc = "Gacha rate calculator for Genshin Impact."
119122
return (
@@ -135,7 +138,6 @@ export default function GachaCalc({ location }: { location: string }) {
135138
<h1 className="text-5xl font-bold pb-2">
136139
Gacha rate calculator
137140
</h1>
138-
139141
<SelectInput label="Banner type" set={(g) => {
140142
if (current == banner.minConst)
141143
setCurrent((Object.values(gachas).find(x => x.bannerName == g) ?? Object.values(gachas)[0]).minConst)
@@ -148,15 +150,15 @@ export default function GachaCalc({ location }: { location: string }) {
148150
{banner.guaranteedPity && <NumberInput label="Epitomized Path" set={setGuaranteedPity} value={guaranteedPity} min={0} max={banner.guaranteedPity - 1} />}
149151

150152
<h3 className="text-lg font-bold pt-1" id="resistance">Results:</h3>
151-
<div className="columns-1 md:columns-2 mr-2">
153+
<div className="columns-1 md:columns-2 mr-2 mb-2">
152154
<div className="w-full bg-slate-800 rounded-xl p-1 my-2 md:my-0 text-white col-start-1">
153155
<Bar data={({
154-
labels: calculated.filter(x => x).map(c => getName(c, banner)),
156+
labels: calculated[calculated.length - 1].filter(x => x).map(c => getName(c.const, banner)),
155157
datasets: [
156158
{
157159
label: "Rate",
158160
backgroundColor: "rgb(75, 192, 192)",
159-
data: calculated.filter(x => x).map((c, i, a) => c.rate * 100),
161+
data: calculated[calculated.length - 1].filter(x => x).map((c, i, a) => c.rate * 100),
160162
borderColor: "white",
161163
borderWidth: 2,
162164
xAxisID: "xAxes"
@@ -183,14 +185,14 @@ export default function GachaCalc({ location }: { location: string }) {
183185
})} /></div>
184186
<div className="w-full bg-slate-800 rounded-xl p-1 my-2 md:my-0 text-white col-start-2">
185187
<Line data={({
186-
labels: calculated.filter(x => x).map(c => getName(c, banner)),
188+
labels: calculated[calculated.length - 1].filter(x => x).map(c => getName(c.const, banner)),
187189
datasets: [
188190
{
189191
label: "Cumulative rate",
190192
borderColor: "rgb(255, 99, 132)",
191193
borderWidth: 2,
192194
fill: false,
193-
data: calculated.filter(x => x).map((c, i, a) => a.slice(i, a.length).reduce((p, c) => p + c.rate, 0) * 100),
195+
data: calculated[calculated.length - 1].filter(x => x).map((c, i, a) => a.slice(i, a.length).reduce((p, c) => p + c.rate, 0) * 100),
194196
},
195197
],
196198
})} options={({
@@ -215,6 +217,42 @@ export default function GachaCalc({ location }: { location: string }) {
215217
})} />
216218
</div>
217219
</div>
220+
<div className="w-full bg-slate-800 rounded-xl p-1 my-2 md:my-0 text-white col-start-2">
221+
<Line data={({
222+
labels: calculated.map((_, i) => i + pity),
223+
datasets: consts.filter(i => i >= 0).map(i => ({
224+
label: getName(i, banner),
225+
backgroundColor: ["#c9c9c9", "#ff6363", "#ffd863", "#b1ff63", "#63ff8a", "#63ffff", "#638aff", "#b163ff", "#ff63d8"][i+1],
226+
borderColor: ["#c9c9c9", "#ff6363", "#ffd863", "#b1ff63", "#63ff8a", "#63ffff", "#638aff", "#b163ff", "#ff63d8"][i+1],
227+
fill: true,
228+
data: calculated.map((c) => (c?.filter(x => x.const >= i)?.reduce((p, c) => p + c.rate, 0) * 100)),
229+
borderWidth: 2,
230+
xAxisID: "xAxes"
231+
})),
232+
})} options={({
233+
color: "white",
234+
backgroundColor: "#333333",
235+
interaction: {
236+
mode: "index",
237+
intersect: false
238+
},
239+
scales: {
240+
yAxes: {
241+
max: 100,
242+
min: 0,
243+
ticks: {
244+
color: "white",
245+
callback: (v) => `${v}%`
246+
}
247+
},
248+
xAxes: {
249+
ticks: {
250+
color: "white"
251+
}
252+
}
253+
}
254+
})} />
255+
</div>
218256
<table className={`table-auto w-80 ${styles.table} ${styles.stattable} my-2 sm:text-base text-sm`}>
219257
<thead>
220258
<tr className="divide-x divide-gray-200 dark:divide-gray-500">
@@ -224,9 +262,9 @@ export default function GachaCalc({ location }: { location: string }) {
224262
</tr>
225263
</thead>
226264
<tbody className="divide-y divide-gray-200 dark:divide-gray-500">
227-
{calculated.filter(x => x)
265+
{calculated[calculated.length - 1].filter(x => x)
228266
.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}>
229-
<td>{getName(c, banner)}</td>
267+
<td>{getName(c.const, banner)}</td>
230268
<td>{(c.rate * 100).toFixed(3)}%</td>
231269
<td>{(a.slice(i, a.length).reduce((p, c) => p + c.rate, 0) * 100).toFixed(2)}%</td>
232270
</tr>)}
@@ -236,8 +274,8 @@ export default function GachaCalc({ location }: { location: string }) {
236274
)
237275
}
238276

239-
function getName(c: ReducedSim, banner: Banner) {
240-
return c.const == banner.minConst ? "Not owned" : `${banner.constFormat}${c.const}`
277+
function getName(c: number, banner: Banner) {
278+
return c == banner.minConst ? "Not owned" : `${banner.constFormat}${c}`
241279
}
242280

243281
function NumberInput({ value, set, label, min, max }: { value: number, set: (newValue: number) => unknown, label: string, min?: number, max?: number }) {
@@ -284,20 +322,7 @@ function SelectInput({ value, set, label, options }: { value: string, set: (newV
284322
</label></div>
285323
}
286324

287-
function calcSimsRegular(current: number, pity: number, pulls: number, guaranteed: boolean, guaranteedPity: number, banner: Banner): ReducedSim[] {
288-
// Max pity / const
289-
if (banner.guaranteed >= 1 && pulls + pity >= banner.maxPity * ((banner.maxConst + 1) * 2 - (guaranteed ? 1 : 0)))
290-
return [{
291-
const: banner.maxConst,
292-
rate: 1
293-
}]
294-
295-
if (banner.guaranteedPity && banner.guaranteedPity >= 1 && pulls + pity >= banner.maxPity * ((banner.maxConst + 1) * banner.guaranteedPity * 2 - (guaranteed ? 1 : 0)))
296-
return [{
297-
const: banner.maxConst,
298-
rate: 1
299-
}]
300-
325+
function calcSimsRegular(current: number, pity: number, pulls: number, guaranteed: boolean, guaranteedPity: number, banner: Banner): ReducedSim[][] {
301326
return calcSimsInt({
302327
pity,
303328
guaranteed,
@@ -307,31 +332,34 @@ function calcSimsRegular(current: number, pity: number, pulls: number, guarantee
307332
}, pulls, banner)
308333
}
309334

310-
function calcSimsInt(starterSim: Sim, pulls: number, banner: Banner): ReducedSim[] {
335+
function calcSimsInt(starterSim: Sim, pulls: number, banner: Banner): ReducedSim[][] {
311336
console.time("calc")
312-
const sims: Sim[] = calcSimsExact([starterSim], pulls, banner, 0)
337+
const sims: Sim[][] = calcSimsExact([starterSim], pulls, banner, 0)
313338
console.timeEnd("calc")
314339

315-
// Reducing to simple sims with less information
316-
const reducedSims: ReducedSim[] = []
317-
sims.forEach((sim: Sim) => {
318-
if (sim.rate == 0) return
319340

320-
const other = reducedSims[sim.const + 1]
341+
return sims.map(sim => {
342+
// Reducing to simple sims with less information
343+
const reducedSims: ReducedSim[] = []
344+
sim.forEach((sim: Sim) => {
345+
if (sim.rate == 0) return
321346

322-
if (other)
323-
other.rate += sim.rate
324-
else
325-
reducedSims[sim.const + 1] = {
326-
const: sim.const,
327-
rate: sim.rate
328-
}
329-
})
347+
const other = reducedSims[sim.const + 1]
330348

331-
return reducedSims
349+
if (other)
350+
other.rate += sim.rate
351+
else
352+
reducedSims[sim.const + 1] = {
353+
const: sim.const,
354+
rate: sim.rate
355+
}
356+
})
357+
return reducedSims
358+
})
332359
}
333360

334361
function calcSimsExact(sims: Sim[], pulls: number, banner: Banner, prune = 1e-8) {
362+
const allSims: Sim[][] = [sims]
335363
for (let i = 0; i < pulls; i++) {
336364
const newSims: Record<number, Sim> = {}
337365

@@ -358,7 +386,7 @@ function calcSimsExact(sims: Sim[], pulls: number, banner: Banner, prune = 1e-8)
358386
if (!sim) continue
359387
if (sim.rate <= prune) continue // Pruning
360388
if (sim.const >= banner.maxConst) { // Limited to C6
361-
addOrMerge(sim)
389+
addOrMerge({ ...sim })
362390
continue
363391
}
364392
const currentPity = sim.pity + 1
@@ -421,6 +449,7 @@ function calcSimsExact(sims: Sim[], pulls: number, banner: Banner, prune = 1e-8)
421449
}
422450

423451
sims = Object.values(newSims)
452+
allSims.push(sims)
424453
}
425-
return sims
454+
return allSims
426455
}

pages/tools/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@ export default function Tools({ location }: { location: string }) {
2020

2121
<ul>
2222
<li className="pb-3">
23-
<FormattedLink className="font-semibold text-2xl" location={location} href="/tools/reminders" >
24-
Reminders
23+
<FormattedLink className="font-semibold text-2xl" location={location} href="/tools/gachacalc" >
24+
Gacha Rate Calculator
2525
</FormattedLink>
2626
<div className="ml-6">
27-
Reminders are send to your Discord DM&apos;s via the Discord bot. Please make sure you share at least one server with the Discord bot
28-
and have DM&apos;s enabled in that server. You can invite the bot to your own Discord server or join the support server via the links on
29-
the <FormattedLink location={location} href="/" >homepage</FormattedLink>.
27+
Calculate odds of getting a certain constellation/refinement within a certain amount of pulls.
3028
</div>
3129
</li>
3230
<li className="pb-3">
33-
<FormattedLink className="font-semibold text-2xl" location={location} href="/tools/gachacalc" >
34-
Gacha Rate Calculator
31+
<FormattedLink className="font-semibold text-2xl" location={location} href="/tools/reminders" >
32+
Reminders
3533
</FormattedLink>
3634
<div className="ml-6">
37-
Calculate odds of getting a certain constellation/refinement within a certain amount of pulls.
35+
Reminders are send to your Discord DM&apos;s via the Discord bot. Please make sure you share at least one server with the Discord bot
36+
and have DM&apos;s enabled in that server. You can invite the bot to your own Discord server or join the support server via the links on
37+
the <FormattedLink location={location} href="/" >homepage</FormattedLink>.
3838
</div>
3939
</li>
4040
</ul>

0 commit comments

Comments
 (0)