More dice stuff

This commit is contained in:
2024-08-20 17:50:10 -06:00
parent d17ff63662
commit df3171b646
10 changed files with 110 additions and 123 deletions

View File

@@ -1,3 +1,5 @@
import { sum } from "./utils/sum";
export class Dice {
private count!: number;
private sides!: number;
@@ -13,11 +15,23 @@ export class Dice {
}
public roll() {
let total = 0;
let results = [];
for (let i = 0; i < this.count; i++) {
total += this.rollSingle();
results.push(this.rollSingle());
}
return total;
return {
total: sum(...results),
max: Math.max(...results),
min: Math.min(...results),
results,
};
}
public rollMax() {
return this.roll().max;
}
public rollMin() {
return this.roll().min;
}
private rollSingle() {
@@ -25,13 +39,13 @@ export class Dice {
}
public rollAvg() {
return this.roll() / this.count;
return this.roll().total / this.count;
}
public rollTimes(times: number) {
let total = 0;
for (let i = 0; i < times; i++) {
total += this.roll();
total += this.roll().total;
}
return total;
}

View File

@@ -1,12 +1,12 @@
import { PublicationAtom } from "@/recoil/atoms/publication";
import { useState, useEffect, useCallback, useRef } from "react";
import { useState, useEffect, useCallback, useRef, ReactNode } from "react";
import { useRecoilValue } from "recoil";
import { TTCQueryResolver } from "../ttcQuery/TTCResolvers";
export function Resolver({ resolver }: { resolver: string }) {
const parser = useRecoilValue(PublicationAtom);
const [res] = useState(new TTCQueryResolver(parser));
const [content, setContent] = useState("");
const [content, setContent] = useState<ReactNode>("");
useEffect(() => {
setContent(res.resolve(resolver));
}, [resolver, res]);
@@ -24,7 +24,7 @@ export function OnDemandResolver({
}) {
const parser = useRecoilValue(PublicationAtom);
const res = useRef(new TTCQueryResolver(parser));
const [content, setContent] = useState("");
const [content, setContent] = useState<ReactNode>("");
const generateContent = useCallback(() => {
let content = template;
const stackIdxs = Array.from(new Set(template.match(/\$\d/g)));

View File

@@ -549,7 +549,7 @@ export const buildOnlyDefaultElements = () => {
// paragraph
registerIdentifier(
"p",
/(?<=\n\n|^)([\s\S]*?)(?=\n\n)/g,
/(?<=\n\n)([\s\S]*?)(?=\n\n)/g,
(s) => {
return {
content: s.replace("\n", " "),

View File

@@ -0,0 +1,48 @@
import { FC } from "react";
export const DiceChart: FC<{ dice: Record<string, number> }> = ({ dice }) => {
const data = Object.entries(dice).sort((a, b) => Number(a[0]) - Number(b[0]));
const max = Math.max(...data.map((d) => d[1]));
const _min = Math.min(...data.map((d) => d[1]));
const uniqueValues = Array.from(new Set(data.map((d) => d[1])));
return (
<div className="p-8 bg-black/30 rounded-md max-w-[35rem]">
<div className="relative flex px-2 gap-1 justify-around items-end h-48 border-b border-l">
<div className="absolute inset-0 flex flex-col-reverse">
{uniqueValues.map((_, i) => (
<div
key={"dicechartline" + i}
className="relative w-full border-t border-mixed-300/50 flex-grow"
>
{/* <div className="absolute right-full text-xs flex items-center -translate-y-1/2">
<span>
{Math.round(max / uniqueValues.length) * (i + 1)} {}
</span>
<div className="border-b w-1 ml-1"></div>
</div> */}
</div>
))}
</div>
{data.map((d) => (
<div
key={"dice" + d[0]}
title={d[0] + ": " + d[1]}
className="flex-grow px-[1px] border hover:border-mixed-300/50 border-transparent h-full flex transition-colors rounded-md @container"
>
<div
className="bg-purple-800 relative rounded-t-sm w-full mt-auto"
style={{ height: (d[1] / max) * 100 + "%" }}
>
<span className="absolute top-full left-1/2 -translate-x-1/2 text-xs @[.75rem]:inline hidden">
{d[0]}
</span>
</div>
</div>
))}
</div>
</div>
);
};

View File

@@ -1,4 +1,7 @@
/* eslint-disable react/display-name */
import { Dice } from "../dice";
import { sum } from "../utils/sum";
import { DiceChart } from "./DiceChart";
import { TTCQueryParser } from "./TTCQueryParser";
export class TTCQueryResolver {
@@ -68,13 +71,25 @@ export class TTCQueryResolver {
if (n && n.startsWith("$")) num = this.getFromStack(n);
switch (method) {
case "roll":
return () => d.roll();
return () => d.roll().total;
case "rollAvg":
return () => d.rollAvg();
case "rollTimes":
return () => d.rollTimes(num);
case "rollTimesAvg":
return () => d.rollTimesAvg(num);
case "rollLowest":
return () => d.rollMin();
case "rollHighest":
return () => d.rollMax();
case "rollDropHighest":
return () => sum(...d.roll().results.toSorted().toSpliced(-1, 1));
case "rollDropLowest":
return () => sum(...d.roll().results.toSorted().toSpliced(0, 1));
case "distribution":
return () => DiceChart({ dice: d.getRollDistribution() });
case "distribution.normalized":
return () => DiceChart({ dice: d.getNormalizedRollDistribution() });
default:
return "No valid method provided for dice";
}

3
lib/utils/sum.ts Normal file
View File

@@ -0,0 +1,3 @@
export const sum = (...args: number[]) => {
return args.reduce((a, b) => a + b, 0);
};