tabletop-frog/src/ttfrog/db/bootstrap.py

193 lines
6.5 KiB
Python
Raw Normal View History

2024-03-26 00:53:21 -07:00
import logging
from sqlalchemy.exc import IntegrityError
from ttfrog.db import schema
from ttfrog.db.manager import db
# move this to json or whatever
data = {
"CharacterClass": [
{
"id": 1,
"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,
"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",
],
},
],
"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"},
],
"Ancestry": [
{"id": 1, "name": "human", "creature_type": "humanoid"},
{"id": 2, "name": "dragonborn", "creature_type": "humanoid"},
{"id": 3, "name": "tiefling", "creature_type": "humanoid"},
{"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,
},
],
"Character": [
{
"id": 1,
"name": "Sabetha",
"ancestry_id": 1,
"armor_class": 10,
"max_hit_points": 14,
"hit_points": 14,
"temp_hit_points": 0,
"speed": 30,
"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": [
{"id": 1, "name": "Fighting Style"},
{"id": 2, "name": "Another Attribute"},
],
"ClassAttributeOption": [
{"id": 1, "attribute_id": 1, "name": "Archery"},
{"id": 2, "attribute_id": 1, "name": "Battlemaster"},
{"id": 3, "attribute_id": 2, "name": "Another Option 1"},
{"id": 4, "attribute_id": 2, "name": "Another Option 2"},
],
"ClassAttributeMap": [
{"class_attribute_id": 1, "character_class_id": 1, "level": 2}, # Fighter: Fighting Style
{"class_attribute_id": 2, "character_class_id": 1, "level": 1}, # Fighter: Another Attr
],
"CharacterClassAttributeMap": [
{"character_id": 1, "class_attribute_id": 2, "option_id": 4}, # Sabetha, another option, option 2
{"character_id": 1, "class_attribute_id": 1, "option_id": 1}, # Sabetha, fighting style, archery
],
"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",
},
],
}
def bootstrap():
"""
Initialize the database with source data. Idempotent; will skip anything that already exists.
"""
db.init()
for table, records in data.items():
model = getattr(schema, table)
for rec in records:
obj = model(**rec)
try:
with db.transaction():
db.session.add(obj)
logging.info(f"Created {table} {obj}")
except IntegrityError as e:
if "UNIQUE constraint failed" in str(e):
logging.info(f"Skipping existing {table} {obj}")
continue
raise