This repository has been archived on 2021-03-10. You can view files and clone it, but cannot push or open issues or pull requests.
perktree/backend/perks/parser.py

113 lines
3.5 KiB
Python

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2019 pavle <pavle.portic@tilda.center>
#
# Distributed under terms of the BSD-3-Clause license.
import csv
import re
from .models import Tree, Perk
requirement_pattern = re.compile(r'([\w\s]+) \(([\w\s]+)\)')
ability_pattern = re.compile(r'Strength|Dexterity|Constitution|Intelligence|Wisdom|Charisma \d+\+', re.IGNORECASE)
class_pattern = re.compile(r'((Artificer|Barbarian|Bard|Cleric|Druid|Fighter|Monk|Mystic|Paladin|Ranger|Rogue|Sorcerer|Warlock|Wizard|Mage|Alchemist|Magus)(, )?)+', re.IGNORECASE)
race_pattern = re.compile(r'((Dwarf|Elf|Halfling|Human|Dragonborn|Gnome|Half-Elf|Half-Orc|Tiefling)(, )?)+', re.IGNORECASE)
class PerkParser():
def __init__(self, filename):
self.filename = filename
self.trees = None
self.perks = None
def parse(self):
self.strip_whitespaces()
self.load_csv()
self.clean_db()
self.parse_perks()
self.link_perks()
def strip_whitespaces(self):
with open(self.filename, 'r') as file:
new = [line.rstrip() for line in file]
with open(self.filename, 'w') as file:
for line in new:
file.write(f'{line}\n')
def load_csv(self):
with open(self.filename, 'r', newline='') as csvfile:
perkreader = csv.DictReader(csvfile, delimiter='\t', restkey='requirements')
self.perks = []
for row in perkreader:
self.perks.append(dict(row))
def clean_db(self):
Perk.objects.all().delete()
Tree.objects.all().delete()
def parse_perks(self):
for p in self.perks:
perk = self.create_perk(name=p['name'].strip(), effect=p['effect'].strip(), level=int(p['level']), perk_type=0)
for tree_name in p['tree'].split(','):
tree_name = tree_name.strip()
try:
tree = Tree.objects.get(name=tree_name)
perk.trees.add(tree)
except Tree.DoesNotExist:
perk.trees.create(name=tree_name)
p['id'] = Perk.objects.latest('id').id
def create_perk(self, name, effect='', level=1, perk_type=4, trees=None):
new_perk = Perk(name=name, effect=effect, level=level, type=perk_type)
new_perk.save()
if trees is not None:
new_perk.trees.add(*trees)
return new_perk
def link_perks(self):
for p in self.perks:
if 'requirements' not in p:
continue
perk = Perk.objects.get(name=p['name'].strip())
for req_name in p['requirements']:
req_name = req_name.strip()
try:
req = Perk.objects.get(name__iexact=req_name)
if req.type == 0:
req_tree = req.trees.all()[0]
else:
req_tree = None
except Perk.DoesNotExist:
if re.match(class_pattern, req_name):
req = self.create_perk(name=req_name, level=0, perk_type=1)
elif re.match(race_pattern, req_name):
req = self.create_perk(name=req_name, level=0, perk_type=2)
elif re.match(ability_pattern, req_name):
req = self.create_perk(name=req_name, level=0, perk_type=3)
elif 'Skill Focus' in req_name or 'Ability Focus' in req_name:
req_match = re.match(requirement_pattern, req_name)
req_tree = Tree.objects.get(name=req_match.group(2))
req_base_name = req_match.group(1)
base_req = Perk.objects.get(name=req_base_name)
req = self.create_perk(name=req_name, effect=base_req.effect, level=base_req.level, perk_type=base_req.type, trees=[req_tree])
else:
req = self.create_perk(name=req_name, level=0, perk_type=4)
perk.parents.add(req)
def output_transform(self):
for tree, data in self.trees.items():
for i in range(len(data['nodes'])):
perk = data['nodes'][i]
if 'requirements' in perk:
perk.pop('requirements')