started refactoring of dicerolling to use a context-free grammar.

This commit is contained in:
2020-07-29 20:31:10 +03:00
parent 48167cfd10
commit d2654fac24
4 changed files with 81 additions and 17 deletions

View File

@@ -1,6 +1,7 @@
from typing import Dict from typing import Dict
import re import re
import numpy as np import numpy as np
from dice.dice import Dice
commands: Dict = {} commands: Dict = {}
@@ -16,7 +17,6 @@ def command(*commandlist):
def handle_command(kwargs): def handle_command(kwargs):
c = kwargs['message'].split()[0] c = kwargs['message'].split()[0]
params = kwargs['message'].replace(c, '') params = kwargs['message'].replace(c, '')
params = re.sub(r'\s+', '', params)
if c in commands: if c in commands:
commands[c](kwargs, params) commands[c](kwargs, params)
@@ -26,21 +26,9 @@ def handle_command(kwargs):
@command('/roll') @command('/roll')
def custom_roll(kwargs, params): def custom_roll(kwargs, params):
pattern = re.compile('(?P<sign>(?:\+|\-)?)(?P<dice_num>\d+)(?i:d)(?P<dice_val>\d+)(?P<maths>(?:(?:\+|\-)\d+)*(?!(?i:d)))') print(f'Kwargs: {kwargs}. Params: {params}')
rolls = re.findall(pattern, params) dice = Dice()
print(dice.roll(params))
rng = np.random.default_rng()
results = []
for roll in rolls:
result = []
if int(roll[2]) < 2:
result.append(int(roll[2]))
else:
result.append(rng.integers(1, int(roll[2]), size=int(roll[1])).tolist())
result.append(roll[3])
results.append(result)
print(results)
print(f'/roll received {kwargs}. Roll parameters: {params}. Rolls recognized: {rolls}')
def error_response(kwargs, params): def error_response(kwargs, params):

0
dice/__init__.py Normal file
View File

75
dice/dice.py Normal file
View File

@@ -0,0 +1,75 @@
import pyparsing
import math
import operator
import numpy as np
from pyparsing import (
Literal,
CaselessLiteral,
Word,
Optional,
Group,
Forward,
nums,
ParseException,
)
class Dice:
exprStack = []
def __init__(self):
pass
def roll(self, roll_params):
self.exprStack[:] = [] # Reset the stack
try:
results = self.BNF().parseString(roll_params, parseAll=True)
except ParseException as pe:
print("Parse exception ", str(pe))
return
except Exception as e:
print("Exception ", str(e), self.exprStack)
return results
def push_first(self, tokens):
self.exprStack.append(tokens[0])
def BNF(self):
integer = Word(nums)
plus, minus = map(Literal, "+-")
addop = plus | minus
rollop = CaselessLiteral('d')
# lowop = CaselessLiteral('l')
# highop = CaselessLiteral('h')
# Define roll as a group
roll = Group(Optional(integer, default=1) + rollop + integer)
expression = Forward()
operand = (
addop[...]
+ (
# Numbers as a fallback, add everything else as (roll | exception | ...)
(roll).setParseAction(self.push_first)
| integer
)
)
term = operand + (rollop + operand).setParseAction(self.push_first)[...]
expression <<= term + (addop + term).setParseAction(self.push_first)[...]
bnf = expression
return bnf

View File

@@ -4,3 +4,4 @@ flask-cors==3.0.8
flask-restful==0.3.8 flask-restful==0.3.8
flask-socketio==4.3.1 flask-socketio==4.3.1
numpy==1.19.1 numpy==1.19.1
pyparsing==2.4.7