90 lines
2.1 KiB
TypeScript
90 lines
2.1 KiB
TypeScript
export class Dice {
|
|
private count!: number;
|
|
private sides!: number;
|
|
|
|
constructor(dice: string) {
|
|
this.parseDice(dice);
|
|
}
|
|
|
|
private parseDice(dice: string) {
|
|
const [c, s] = dice.split(/[dD]/);
|
|
this.count = Number(c);
|
|
this.sides = Number(s);
|
|
}
|
|
|
|
public roll() {
|
|
let total = 0;
|
|
for (let i = 0; i < this.count; i++) {
|
|
total += this.rollSingle();
|
|
}
|
|
return total;
|
|
}
|
|
|
|
private rollSingle() {
|
|
return Math.ceil(Math.random() * this.sides);
|
|
}
|
|
|
|
public rollAvg() {
|
|
return this.roll() / this.count;
|
|
}
|
|
|
|
public rollTimes(times: number) {
|
|
let total = 0;
|
|
for (let i = 0; i < times; i++) {
|
|
total += this.roll();
|
|
}
|
|
return total;
|
|
}
|
|
|
|
public rollTimesAvg(times: number) {
|
|
return this.rollTimes(times) / times;
|
|
}
|
|
|
|
public getNormalizedRollDistribution(): Record<number, number> {
|
|
const distribution: Record<number, number> = this.computeDistribution();
|
|
|
|
// Normalize the distribution
|
|
const totalOutcomes = Math.pow(this.sides, this.count);
|
|
for (const sum in distribution) {
|
|
if (distribution.hasOwnProperty(sum)) {
|
|
distribution[sum] /= totalOutcomes;
|
|
}
|
|
}
|
|
|
|
return distribution;
|
|
}
|
|
|
|
public getRollDistribution(): Record<number, number> {
|
|
return this.computeDistribution();
|
|
}
|
|
|
|
private computeDistribution(): Record<number, number> {
|
|
const distribution: Record<number, number> = {};
|
|
|
|
// Helper function to compute the sum distribution for given number of dice
|
|
const computeSumDistribution = (
|
|
dice: number,
|
|
sides: number,
|
|
currentSum: number,
|
|
currentDice: number
|
|
): void => {
|
|
if (currentDice === dice) {
|
|
distribution[currentSum] = (distribution[currentSum] || 0) + 1;
|
|
return;
|
|
}
|
|
for (let i = 1; i <= sides; i++) {
|
|
computeSumDistribution(dice, sides, currentSum + i, currentDice + 1);
|
|
}
|
|
};
|
|
|
|
// Compute distribution
|
|
computeSumDistribution(this.count, this.sides, 0, 0);
|
|
|
|
return distribution;
|
|
}
|
|
// STATIC
|
|
static isDice(d: string) {
|
|
return /\d+[dD]\d+/.test(d);
|
|
}
|
|
}
|