Skip to content

Commit ace54b3

Browse files
authored
Merge pull request #302 from dice-roller/feature/301-Enable-rounding-to-zero
Feature/301 enable rounding to zero
2 parents c25344d + cfe1f9e commit ace54b3

File tree

4 files changed

+152
-7
lines changed

4 files changed

+152
-7
lines changed

.github/workflows/build.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ on:
55
- main
66
- develop
77
- 'releases/**'
8+
- 'next/**'
89
pull_request:
910
branches:
1011
- main
1112
- develop
1213
- 'releases/**'
14+
- 'next/**'
1315
jobs:
1416
test:
17+
name: 'Run tests'
1518
runs-on: ubuntu-latest
1619
steps:
1720
- name: Checkout
@@ -34,7 +37,8 @@ jobs:
3437
github-token: ${{ secrets.github_token }}
3538
parallel: true
3639

37-
build-typescript:
40+
build-definitions:
41+
name: 'Check TS definitions are compiled'
3842
runs-on: ubuntu-latest
3943
steps:
4044
- name: Checkout
@@ -48,10 +52,14 @@ jobs:
4852
- name: Install dependencies
4953
run: npm ci
5054

55+
- name: Build Grammars
56+
run: npm run build:grammars
57+
5158
- name: Build Typescript
52-
run: npm run build:declaration
59+
run: npm run build:definitions
5360

5461
build-api-docs:
62+
name: "Check API docs are built"
5563
runs-on: ubuntu-latest
5664
steps:
5765
- name: Checkout
@@ -69,6 +77,7 @@ jobs:
6977
run: npm run docs:build
7078

7179
finish:
80+
name: "Send Coverage"
7281
needs: test
7382
runs-on: ubuntu-latest
7483
steps:

src/parser/grammars/grammar.pegjs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ Main = Expression
77

88
// Expression / roll groups
99
RollGroup
10-
= "{" _ expr:Expression exprs:(_ "," _ Expression)* _ "}" modifiers:Modifier* descriptions:__ {
10+
= "{" _ expressions:ExpressionCollection _ "}" modifiers:Modifier* descriptions:__ {
1111
return new RollGroup(
12-
[
13-
expr,
14-
...exprs.map(v => v[3])
15-
],
12+
expressions,
1613
Object.assign({}, ...modifiers.map(item => {
1714
return {[item.name]: item};
1815
})),
@@ -170,6 +167,13 @@ Expression
170167
]
171168
}
172169

170+
ExpressionCollection = expr:Expression exprs:(_ "," _ Expression)* {
171+
return [
172+
expr,
173+
...exprs.map(v => v[3])
174+
];
175+
}
176+
173177
Factor
174178
= MathFunction
175179
/ Dice
@@ -194,6 +198,17 @@ MathFunction
194198
')',
195199
];
196200
}
201+
/ func:("fix" / "trunc" { return "fix" }) "(" _ expr1:Expression _ expr2:("," _ Expression _)? ")" {
202+
return [
203+
`${func}(`,
204+
...expr1,
205+
...(expr2 ? [
206+
',',
207+
...expr2[2],
208+
] : []),
209+
')',
210+
];
211+
}
197212

198213
FloatNumber
199214
= "-"? Number ([.] Number)? { return parseFloat(text()) }

tests/Feature/rolling.test.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,86 @@ describe('Rolling', () => {
113113
]);
114114
});
115115

116+
test('roll `fix(4d10/3)', () => {
117+
const rolls = new RollResults([2,3,6,2])
118+
jest.spyOn(StandardDice.prototype, 'roll')
119+
.mockImplementationOnce(() => rolls);
120+
const roll = roller.roll('fix(4d10/3)') as DiceRoll;
121+
122+
expect(roll).toBeInstanceOf(DiceRoll);
123+
expect(roll.notation).toEqual('fix(4d10/3)');
124+
expect(roll.total).toBe(4);
125+
expect(roll.output).toEqual('fix(4d10/3): fix([2, 3, 6, 2]/3) = 4');
126+
expect(roll.rolls).toEqual([
127+
'fix(',
128+
rolls,
129+
'/',
130+
3,
131+
')',
132+
]);
133+
});
134+
135+
test('roll `fix(4d10/3, 2)', () => {
136+
const rolls = new RollResults([2,3,6,2])
137+
jest.spyOn(StandardDice.prototype, 'roll')
138+
.mockImplementationOnce(() => rolls);
139+
const roll = roller.roll('fix(4d10/3, 2)') as DiceRoll;
140+
141+
expect(roll).toBeInstanceOf(DiceRoll);
142+
expect(roll.notation).toEqual('fix(4d10/3, 2)');
143+
expect(roll.total).toBe(4.33);
144+
expect(roll.output).toEqual('fix(4d10/3, 2): fix([2, 3, 6, 2]/3,2) = 4.33');
145+
expect(roll.rolls).toEqual([
146+
'fix(',
147+
rolls,
148+
'/',
149+
3,
150+
',',
151+
2,
152+
')',
153+
]);
154+
});
155+
156+
test('roll `trunc(4d10/3)', () => {
157+
const rolls = new RollResults([2,3,6,2])
158+
jest.spyOn(StandardDice.prototype, 'roll')
159+
.mockImplementationOnce(() => rolls);
160+
const roll = roller.roll('trunc(4d10/3)') as DiceRoll;
161+
162+
expect(roll).toBeInstanceOf(DiceRoll);
163+
expect(roll.notation).toEqual('trunc(4d10/3)');
164+
expect(roll.total).toBe(4);
165+
expect(roll.output).toEqual('trunc(4d10/3): fix([2, 3, 6, 2]/3) = 4');
166+
expect(roll.rolls).toEqual([
167+
'fix(',
168+
rolls,
169+
'/',
170+
3,
171+
')',
172+
]);
173+
});
174+
175+
test('roll `trunc(4d10/3, 2)', () => {
176+
const rolls = new RollResults([2,3,6,2])
177+
jest.spyOn(StandardDice.prototype, 'roll')
178+
.mockImplementationOnce(() => rolls);
179+
const roll = roller.roll('trunc(4d10/3, 2)') as DiceRoll;
180+
181+
expect(roll).toBeInstanceOf(DiceRoll);
182+
expect(roll.notation).toEqual('trunc(4d10/3, 2)');
183+
expect(roll.total).toBe(4.33);
184+
expect(roll.output).toEqual('trunc(4d10/3, 2): fix([2, 3, 6, 2]/3,2) = 4.33');
185+
expect(roll.rolls).toEqual([
186+
'fix(',
187+
rolls,
188+
'/',
189+
3,
190+
',',
191+
2,
192+
')',
193+
]);
194+
});
195+
116196
test('roll `3d6cs>3cf<3`', () => {
117197
jest.spyOn(StandardDice.prototype, 'rollOnce')
118198
.mockImplementationOnce(() => new RollResult(5))

tests/Unit/Parser/Parsing.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,47 @@ describe('Parsing', () => {
110110
}).toThrow(parser.PeggySyntaxError);
111111
});
112112
});
113+
114+
// Test the fix / trunc function
115+
['fix', 'trunc'].forEach((name) => {
116+
test(`can parse \`${name}(2d10*3)\``, () => {
117+
const parsed = Parser.parse(`${name}(2d10*3)`);
118+
119+
expect(parsed).toBeInstanceOf(Array);
120+
expect(parsed).toHaveLength(5);
121+
122+
expect(parsed[0]).toEqual('fix(');
123+
124+
const result = parsed[1] as Dice;
125+
expect(result).toBeInstanceOf(StandardDice);
126+
expect(result.sides).toBe(10);
127+
expect(result.qty).toBe(2);
128+
expect(result.modifiers).toEqual(new Map());
129+
130+
expect(parsed[2]).toEqual('*');
131+
expect(parsed[3]).toBe(3);
132+
expect(parsed[4]).toEqual(')');
133+
});
134+
135+
test(`can parse \`${name}(5d20, 2)\``, () => {
136+
const parsed = Parser.parse(`${name}(5d20, 2)`);
137+
138+
expect(parsed).toBeInstanceOf(Array);
139+
expect(parsed).toHaveLength(5);
140+
141+
expect(parsed[0]).toEqual('fix(');
142+
143+
const result = parsed[1] as Dice;
144+
expect(result).toBeInstanceOf(StandardDice);
145+
expect(result.sides).toBe(20);
146+
expect(result.qty).toBe(5);
147+
expect(result.modifiers).toEqual(new Map());
148+
149+
expect(parsed[2]).toEqual(',');
150+
expect(parsed[3]).toBe(2);
151+
expect(parsed[4]).toEqual(')');
152+
});
153+
});
113154
});
114155

115156
describe('Multiple dice', () => {

0 commit comments

Comments
 (0)