-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroll.js
60 lines (48 loc) · 1.28 KB
/
roll.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
const regex = /^(\d*)d(\d+|%)(([+-/*bw])(\d+))?(([+-/*])(\d+|(\d*)d(\d+|%)(([+\-/*bw])(\d+))?))*$/;
const min = 1; // minimum number of sides on a dice
class roll {
constructor(random) {
this.random = random || Math.random.bind(Math);
}
validate(s) {
this.validation = regex.test(s);
return this.validation;
}
parse(s) {
if (!this.validate(s)) {
throw new Error(`${s} is an invalid dice roll!`);
}
const dice = [];
const segments = s.split(/[+-]/);
segments.forEach((segment) => {
const match = regex.exec(segment);
dice.push({
segment,
quantity: match[1] || 1,
sides: match[2],
});
});
return dice;
}
roll(input) {
const dice = this.parse(input);
const rolled = [];
dice.forEach((diceSet) => {
const diceSetRolled = [];
while (diceSetRolled.length < diceSet.quantity) {
diceSetRolled.push((Math.floor(this.random() * (diceSet.sides - min + 1)) + min));
}
rolled.push(...diceSetRolled);
});
const reducer = (acc, cur) => acc + cur;
const result = rolled.reduce(reducer);
const average = result / rolled.length;
return {
rolled,
average,
result,
};
}
}
module.exports = roll;
module.exports.Regex = regex;