tabletop-frog/ttfrog/db/bootstrap.py

156 lines
5.5 KiB
Python
Raw Normal View History

2024-01-28 00:46:19 -08:00
import logging
2024-01-30 01:25:02 -08:00
from ttfrog.db.manager import db
from ttfrog.db import schema
2024-01-28 00:46:19 -08:00
2024-01-30 01:25:02 -08:00
from sqlalchemy.exc import IntegrityError
2024-01-28 00:46:19 -08:00
# move this to json or whatever
data = {
2024-02-08 01:14:35 -08:00
'CharacterClass': [
{
'id': 1,
2024-02-08 01:14:35 -08:00
'name': 'fighter',
'hit_dice': '1d10',
'hit_dice_stat': 'CON',
'proficiencies': 'all armor, all shields, simple weapons, martial weapons',
'saving_throws': ['STR, CON'],
'skills': ['Acrobatics', 'Animal Handling', 'Athletics', 'History', 'Insight', 'Intimidation', 'Perception', 'Survival'],
},
{
'id': 2,
2024-02-08 01:14:35 -08:00
'name': 'rogue',
'hit_dice': '1d8',
'hit_dice_stat': 'DEX',
'proficiencies': 'simple weapons, hand crossbows, longswords, rapiers, shortswords',
'saving_throws': ['DEX', 'INT'],
'skills': ['Acrobatics', 'Athletics', 'Deception', 'Insight', 'Intimidation', 'Investigation', 'Perception', 'Performance', 'Persuasion', 'Sleight of Hand', 'Stealth'],
},
],
2024-02-08 01:14:35 -08:00
'Skill': [
{'name': 'Acrobatics'},
{'name': 'Animal Handling'},
{'name': 'Athletics'},
{'name': 'Deception'},
{'name': 'History'},
{'name': 'Insight'},
{'name': 'Intimidation'},
{'name': 'Investigation'},
{'name': 'Perception'},
{'name': 'Performance'},
{'name': 'Persuasion'},
{'name': 'Sleight of Hand'},
{'name': 'Stealth'},
{'name': 'Survival'},
],
2024-01-30 01:25:02 -08:00
'Ancestry': [
{'id': 1, 'name': 'human', 'creature_type': 'humanoid'},
{'id': 2, 'name': 'dragonborn', 'creature_type': 'humanoid'},
{'id': 3, 'name': 'tiefling', 'creature_type': 'humanoid'},
2024-02-18 19:30:41 -08:00
{'id': 4, 'name': 'elf', 'creature_type': 'humanoid'},
],
'AncestryTrait': [
{ 'id': 1, 'name': '+1 to All Ability Scores', },
{ 'id': 2, 'name': 'Breath Weapon', },
{ 'id': 3, 'name': 'Darkvision', },
],
'AncestryTraitMap': [
{ 'ancestry_id': 1, 'ancestry_trait_id': 1, 'level': 1}, # human +1 to scores
{ 'ancestry_id': 2, 'ancestry_trait_id': 2, 'level': 1}, # dragonborn breath weapon
{ 'ancestry_id': 3, 'ancestry_trait_id': 3, 'level': 1}, # tiefling darkvision
{ 'ancestry_id': 2, 'ancestry_trait_id': 2, 'level': 1}, # elf darkvision
],
'CharacterClassMap': [
{
'character_id': 1,
'character_class_id': 1,
'level': 2,
},
{
'character_id': 1,
'character_class_id': 2,
'level': 3,
},
2024-01-28 00:46:19 -08:00
],
2024-01-30 01:25:02 -08:00
'Character': [
2024-02-08 01:14:35 -08:00
{
'id': 1,
'name': 'Sabetha',
2024-02-18 19:30:41 -08:00
'ancestry_id': 1,
2024-02-08 01:14:35 -08:00
'armor_class': 10,
'max_hit_points': 14,
'hit_points': 14,
'temp_hit_points': 0,
'speed': 30,
2024-02-08 01:14:35 -08:00
'str': 16,
'dex': 12,
'con': 18,
'int': 11,
'wis': 12,
'cha': 8,
'proficiencies': 'all armor, all shields, simple weapons, martial weapons',
'saving_throws': ['STR', 'CON'],
'skills': ['Acrobatics', 'Animal Handling'],
},
],
'ClassAttribute': [
2024-02-18 19:30:41 -08:00
{'id': 1, 'name': 'Fighting Style', 'value': 'Archery'},
],
2024-02-18 19:30:41 -08:00
'ClassAttributeMap': [
{'class_attribute_id': 1, 'character_class_id': 1, 'level': 2}, # Fighter: Archery fighting style
],
2024-02-18 19:30:41 -08:00
'CharacterClassAttributeMap': [
{'class_attribute_id': 1, 'character_id': 1}, # Sabetha: Archery fighting style
],
'Modifier': [
# Humans
{'source_table_name': 'ancestry_trait', 'source_table_id': 1, 'value': '+1', 'type': 'stat', 'target': 'str'},
{'source_table_name': 'ancestry_trait', 'source_table_id': 1, 'value': '+1', 'type': 'stat', 'target': 'dex'},
{'source_table_name': 'ancestry_trait', 'source_table_id': 1, 'value': '+1', 'type': 'stat', 'target': 'con'},
{'source_table_name': 'ancestry_trait', 'source_table_id': 1, 'value': '+1', 'type': 'stat', 'target': 'int'},
{'source_table_name': 'ancestry_trait', 'source_table_id': 1, 'value': '+1', 'type': 'stat', 'target': 'wis'},
{'source_table_name': 'ancestry_trait', 'source_table_id': 1, 'value': '+1', 'type': 'stat', 'target': 'cha'},
# Dragonborn
{'source_table_name': 'ancestry_trait', 'source_table_id': 2, 'value': '60', 'type': 'attribute ', 'target': 'Darkvision'},
{'source_table_name': 'ancestry_trait', 'source_table_id': 2, 'value': '+1', 'type': 'stat', 'target': ''},
{'source_table_name': 'ancestry_trait', 'source_table_id': 2, 'value': '+1', 'type': 'stat', 'target': ''},
# Fighting Style: Archery
{'source_table_name': 'class_attribute', 'source_table_id': 1, 'value': '+2', 'type': 'weapon ', 'target': 'ranged'},
],
2024-01-28 00:46:19 -08:00
}
def bootstrap():
"""
Initialize the database with source data. Idempotent; will skip anything that already exists.
"""
2024-01-30 01:25:02 -08:00
db.init()
for table, records in data.items():
model = getattr(schema, table)
2024-01-28 22:14:50 -08:00
2024-01-30 01:25:02 -08:00
for rec in records:
2024-01-31 22:39:54 -08:00
obj = model(**rec)
try:
with db.transaction():
db.session.add(obj)
2024-02-04 11:40:30 -08:00
logging.info(f"Created {table} {obj}")
2024-01-31 22:39:54 -08:00
except IntegrityError as e:
if 'UNIQUE constraint failed' in str(e):
logging.info(f"Skipping existing {table} {obj}")
continue
raise