import os import re from typing import List from flask import Flask, render_template, request from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, BooleanField from wtforms import DecimalField, RadioField, SelectField, TextAreaField, FileField, IntegerField from wtforms.validators import InputRequired,DataRequired,length app = Flask(__name__) app.config['SECRET_KEY'] = 'secretkey' class MyForm(FlaskForm): chatTekst = TextAreaField('Chat tekst', validators=[InputRequired()]) ac = IntegerField(label='Ac', validators=[InputRequired()]) advantage = BooleanField(label='Har advantage') critRange = IntegerField(label='Crit over :' , validators=[InputRequired()]) class Action: def __init__(self) -> None: self.Dam=[] self.hit=[] self.targetAc=0 self.advantage=0 self.failedHitValue=0 self.critAbove=20 self.crits=False self.atkMod=0 def setActionTypeToDam(self,value,value2,DamType): self.Dam.append([value,value2,DamType]) def setAtkMod(self, mod): if(mod>0): self.atkMod=mod def setActionTypeToHit(self,hitArray): if(len(hitArray)>1): self.hit=[hitArray[0][0],hitArray[0][1],hitArray[1][0],hitArray[1][1]] else: self.hit=[hitArray[0][0],hitArray[0][1],0,0] def setTargetAc(self,ac): self.targetAc=ac def setWithAdvantage(self): self.advantage=self.advantage+1 def setWithDisAdvantage(self): self.advantage=self.advantage-1 def setCritRange(self,crit): self.critAbove=crit def getDamForHit(self): dam=dict() hits=False crit=False if(self.advantage==0): if(((self.hit[0]+self.hit[1]) >=self.targetAc and (self.hit[0]-self.atkMod)>1) or self.critAbove<=(self.hit[0]-self.atkMod)): # 0 (rul 1 value), 1 (rul 1 bonus), 2 (rul 2 value), 3(rul 2 bonus) hits=1 if(self.critAbove<=(self.hit[0]-self.atkMod)): self.crits=1 if(self.advantage==1): if(((self.hit[2]+self.hit[3]) >=self.targetAc and (self.hit[2]-self.atkMod)>1 or (self.hit[0]+self.hit[1]) >=self.targetAc and (self.hit[0]-self.atkMod)>1) or (self.critAbove<=self.hit[2]-self.atkMod) or (self.critAbove<=self.hit[0]-self.atkMod)): hits=1 if((self.critAbove<=self.hit[2]-self.atkMod) or (self.critAbove<=self.hit[0]-self.atkMod)): self.crits=1 if(self.advantage==-1): if((((self.hit[2]+self.hit[3]) >=self.targetAc and (self.hit[2]-self.atkMod)>1) or ((self.critAbove<=self.hit[2]-self.atkMod))) and (((self.hit[0]+self.hit[1]) >=self.targetAc and (self.hit[0]-self.atkMod)>1) or (self.critAbove<=self.hit[0]-self.atkMod))): hits=1 if((self.critAbove<=self.hit[2]-self.atkMod) and (self.critAbove<=self.hit[0]-self.atkMod)): self.crits=1 if(hits==1): for d in self.Dam: # Dam def: value,value2,DamType if(self.crits): dam[d[2]]=d[0]+d[1] else: dam[d[2]]=d[0] return dam def getFumble(self): fumbles=True if(self.advantage==0): if((self.hit[0]-self.atkMod)>1): # 0 (rul 1 value), 1 (rul 1 bonus), 2 (rul 2 value), 3(rul 2 bonus) fumbles=False if(self.advantage==1): if((self.hit[0]-self.atkMod)>1 or (self.hit[2]-self.atkMod)>1): fumbles=False if(self.advantage==-1): if((self.hit[0]-self.atkMod)>1 and (self.hit[2]-self.atkMod)>1): fumbles=False return fumbles damTypes=["Slashing","Radiant","Great Weapon Master","Divine","Holy Weapon","Great Weapon Master/Radiant", "Bludgeoning","arm of dawn, Awakend","Lightning"] con=0 def incContext(): res=0 if(con==0): con=1 res=1 con=con+1 if(con>2): con=1 res=1 def getContext(): return con def isItTheRightContext(c,line): res=0 return res def checkIfCounts(line): estCon=0 if(re.match("(^_?[0-9]+){1}( \+ [0-9]+)?( [0-9]+( \+ [0-9])*)?", line)): print("match : " + line) estCon=1 # attackroll eller s=re.search('\([-|\+][0-9]+\)+', line) if(s!=None): print("match modifier: " + line) estCon=3 return estCon def getAllDamage(runder): dam=dict() dam['Samlet']=0 for r in runder: print(r) damage = r.getDamForHit() for d in damage: print(d) if(dam.get(d)==None): dam[d]=damage[d] dam['Samlet']=dam['Samlet']+damage[d] else: dam[d]=dam[d]+damage[d] dam['Samlet']=dam['Samlet']+damage[d] return dam def parseText(runder,lines,ac,advantage,critRange): line=None attMod=0 for nextLine in lines: nextLine=nextLine.strip() if(line==None): line=nextLine continue print(line) c=checkIfCounts(line) if(c==3): # attack modifier s=re.search('\([-|\+][0-9]+\)+', line) v=re.search('[0-9]+', s.group(0)) if(s.group(0)[1]=='+'): curAction.setAtkMod(int(v.group(0))) else: curAction.setAtkMod(0-int(v.group(0))) if(c==1): if(nextLine in damTypes): c=2 # damage else: c=1 # to hit if(c==1): # Hit lastActionFumble=False if(len(runder)>0): lastActionFumble=curAction.getFumble() curAction=Action() curAction.setTargetAc(ac) if(critRange!=20 and critRange!=None): curAction.setCritRange(critRange) if(advantage): curAction.setWithAdvantage() if(lastActionFumble): curAction.setWithDisAdvantage() h=line.split(" ") HitArray=[] if(h[0].rfind("+")>-1 or h[0].rfind("-")>-1): if(h[0].rfind("+")>-1): HitArray.append([int(h[0].split("+")[0]),int(h[0].split("+")[1].strip())]) else: HitArray.append([int(h[0].split("+")[0]),0-int(h[0].split("+")[1].strip())]) else: HitArray.append([int(h[0].strip()),0]) if(len(h)>1): if((h[1].rfind("+")>-1 or h[1].rfind("-")>-1)): if(h[1].rfind("+")>-1): HitArray.append([int(h[1].split("+")[0]),int(h[1].split("+")[1].strip())]) else: HitArray.append([int(h[1].split("-")[0]),0-int(h[1].split("-")[1].strip())]) else: HitArray.append([int(h[1].strip()),0]) curAction.setActionTypeToHit(HitArray) runder.append(curAction) if(c==2): # Skade if(len(runder)==0): continue curAction=runder[len(runder)-1] if(line.rfind("+")>-1 or line.rfind("-")>-1): if(line.rfind("+")>-1): curAction.setActionTypeToDam(int(line.split("+")[0]),int(line.split("+")[1].strip()),nextLine) else: curAction.setActionTypeToDam(int(line.split("-")[0]),0-int(line.split("-")[1].strip()),nextLine) else: curAction.setActionTypeToDam(int(line.strip()),0,nextLine) line=nextLine file1 = open("input.txt", "w") @app.route('/', methods=['GET', 'POST']) def main(): form = MyForm() runder: List[Action] = list() if form.validate_on_submit(): for a in form.chatTekst.data.splitlines(): file1.writelines(form.chatTekst.data.splitlines()) parseText(runder,form.chatTekst.data.splitlines(),form.ac.data, form.advantage.data, form.critRange.data) dam=getAllDamage(runder) return render_template('index.html', dam=dam, form=form) if __name__ == '__main__': app.run(debug=False, port=5432, host='0.0.0.0')