193 lines
6.5 KiB
Python
193 lines
6.5 KiB
Python
![]() |
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
|