diff --git a/data/yaml/cleanyaml.py b/data/yaml/cleanyaml.py index b7dee3f..6169932 100644 --- a/data/yaml/cleanyaml.py +++ b/data/yaml/cleanyaml.py @@ -33,6 +33,13 @@ def main(): # print("Before: {}".format(i['trigger'])) i['trigger'] = i['trigger'].replace('’', "'") # print("After: {}".format(i['trigger'])) + if x == "triggers.yaml": + for i in data['trigger']: + print(i) + i = i.replace('’', "'") + + + final = yaml.safe_dump(data, allow_unicode=True) with open(x, 'w') as f: f.write(final) diff --git a/data/yaml/feats.yaml b/data/yaml/feats.yaml index 45e8248..a67324c 100644 --- a/data/yaml/feats.yaml +++ b/data/yaml/feats.yaml @@ -840,6 +840,7 @@ feat: damage you deal. frequency: null has_been_manually_proofread: false + level: 1 name: Burn It! prereqs: - descr: Ancestry Level 1 @@ -1103,6 +1104,7 @@ feat: need to have cover or greater cover or be concealed to Hide or Sneak. frequency: null has_been_manually_proofread: false + level: 1 name: Very, Very Sneaky prereqs: - descr: Very Sneaky @@ -1610,7 +1612,8 @@ feat: a critical success. frequency: null has_been_manually_proofread: false - name: Cooperataive Soul + level: 9 + name: Cooperative Soul prereqs: - descr: Cooperative Nature feat: Cooperative Nature @@ -17576,7 +17579,8 @@ feat: level: 2 name: Wilderness Spotter prereqs: - - expert in Survival + - descr: expert in Survival + feat: null requirement: null source: - abbr: CRB diff --git a/data/yaml/triggers.yaml b/data/yaml/triggers.yaml index 0d1baaf..13e2839 100644 --- a/data/yaml/triggers.yaml +++ b/data/yaml/triggers.yaml @@ -1,7 +1,7 @@ trigger: - An ally ends a move action adjacent to you. - You fail a skill check or saving throw. -- You attempt a check using a skill you’re untrained in. +- You attempt a check using a skill you're untrained in. - You would be reduced to 0 Hit Points but not immediately killed. - You attempt a saving throw against a spell or magical effect, before rolling. - You bring a foe to 0 Hit Points. @@ -13,12 +13,12 @@ trigger: than your advanced alchemy level. - You craft an elixer of life using Quick Alchemy, and that elixir is at least 2 levels lower than your advanced alchemy level. -- You craft an alchemical bomb using Quick Alchemy that’s at least 2 levels lower +- You craft an alchemical bomb using Quick Alchemy that's at least 2 levels lower than your advanced alchemy level. - A foe within reach attempts to move away from you. - You take damage and are capable of entering a rage. - A creature within your reach uses a manipulate action or a move action, makes a - ranged attack, or leaves a square during a move action it’s using. + ranged attack, or leaves a square during a move action it's using. - Your melee Strike kills a creature or knocks it unconscious, and another foe is adjacent to that creature. - A creature within your reach succeeds or critically succeeds at an attack against @@ -49,7 +49,7 @@ trigger: - You are targeted with a melee attack by an attacker you can see. - Your turn ends and you have a status penalty to your Speed or are immobilized or slowed. -- An enemy's attack hits you or you fail a saving throw against an enemy’s ability. +- An enemy's attack hits you or you fail a saving throw against an enemy's ability. - Your hunted prey is within your reach, and it uses a manipulate action, uses a move action, or leaves a square during a move action it's using. - You are about to roll a Perception or Survival check for initiative. @@ -71,10 +71,12 @@ trigger: area. - A creature casts a spell that you have in your repertoire. - A creature Casts a Spell that you have prepared. -- A creature within line of sight casts a spell that you don’t have prepared or in +- A creature within line of sight casts a spell that you don't have prepared or in your spell repertoire, or a trap or similar object casts such a spell. You must be aware of the casting. - While you have your shield raised, you would take damage from a physical attack. - An adjacent creature you are hunting attempts to move away from you using an action that has the move trait. - You attempt a saving throw against a magical effect, but you haven't rolled yet. +- You are unarmored and touching the ground. +- You are unarmored. diff --git a/gendb/gendb.py b/gendb/gendb.py index fdfd856..d2a1d3a 100644 --- a/gendb/gendb.py +++ b/gendb/gendb.py @@ -144,7 +144,7 @@ def do_feats(data, conn): actioncost_id INTEGER, descr TEXT NOT NULL, freq_id INTEGER, - level INTEGER NOT NULL, + level INTEGER, -- TODO Make not null once issue 88 is resolved name TEXT NOT NULL UNIQUE, requirement_id INTEGER, trigger_id INTEGER, @@ -157,8 +157,46 @@ def do_feats(data, conn): c = conn.cursor() c.execute(table) + table = """ +CREATE TABLE sourceentry_feat ( + id INTEGER PRIMARY KEY, + sourceentry_id INTEGER NOT NULL, + feat_id INTEGER NOT NULL, + UNIQUE (sourceentry_id, feat_id), -- prevent duplicates + FOREIGN KEY (sourceentry_id) REFERENCES sourceentry(sourceentry_id), + FOREIGN KEY (feat_id) REFERENCES feat(feat_id) +); + """ + c = conn.cursor() + c.execute(table) + + table = """ + CREATE TABLE trait_feat ( + id INTEGER PRIMARY KEY, + trait_id INTEGER NOT NULL, + feat_id INTEGER NOT NULL, + UNIQUE(trait_id, feat_id), + FOREIGN KEY (feat_id) REFERENCES feat(feat_id), + FOREIGN KEY (trait_id) REFERENCES trait(trait_id) + ); + """ + c.execute(table) + + table = """ + CREATE TABLE featprereq ( + featprereq_id INTEGER PRIMARY KEY, + descr TEXT NOT NULL, + parent_feat_id INTEGER NOT NULL, -- THE FEAT THAT REQUIRES THE PREREQ + is_prereq_feat_bool BOOL NOT NULL, -- THIS TELLS YOU THAT THE PREREQ ITSELF IS A FEAT + prereq_feat_id INTEGER, -- THIS IS THE PREREQ FEAT, NOT THE FEAT THAT REQUIRES THE PREREQ, if is_prereq_feat_bool == FALSE then this will also be null + FOREIGN KEY (prereq_feat_id) REFERENCES feat(feat_id), + FOREIGN KEY (parent_feat_id) REFERENCES feat(feat_id) + ); + """ + c.execute(table) feat_result_list = [] + feats_no_levels = [] for i in data['feat']: if i['actioncost'] == None: ac_id = None @@ -178,10 +216,163 @@ def do_feats(data, conn): t_id = None else: t_id = get_trigger_id_by_descr(i['trigger'], conn) + if 'level' not in i: + resl = {'name': i['name'], 'source': i['source']} + feats_no_levels.append(resl) + i['level'] = None - # res = (ac_id, i['descr'], f_id, i['level'], i['name'], r_id, t_id) + + + res = (ac_id, i['descr'], f_id, i['level'], i['name'], r_id, t_id) + feat_result_list.append(res) insert_stmt = "INSERT INTO feat (actioncost_id, descr, freq_id, level, name, requirement_id, trigger_id) VALUES (?,?,?,?,?,?,?);" + try: + conn.executemany(insert_stmt, feat_result_list) + except sqlite3.Error as e: + print("Error creating feats: {}".format(e)) + except: + print("Error creating feats something other than sqlite3 error") + else: + conn.commit() + + print("\n\nWARNING!\n\nThe following feats do not have level information and need to be manually checked!:\n") + for i in feats_no_levels: + print(i) + + # go through and do source entry linking + + for i in data['feat']: + # print("\n\nDoing the skill: {}".format(i['name'])) + srcs = [] + # TODO refactor this inner loop for sources out + for j in i['source']: + abbr = j['abbr'] + page_start = j['page_start'] + if 'page_stop' in j: + page_stop = j['page_stop'] + else: + page_stop = page_start + srcs.append([i['name'], abbr, page_start, page_stop]) + # print("srcs: {}".format(srcs)) + do_sourceentry_to_feats(srcs, conn) + + # do traits + for i in data['feat']: + traitlist = [] + if i['traits'] != None: + for j in i['traits']: + traitlist.append((i['name'], j)) + # print("traitlist is:\t{}".format(traitlist)) + + stmt = """ + INSERT INTO trait_feat (feat_id, trait_id) VALUES ( + (SELECT feat_id FROM feat WHERE name=?), + (SELECT trait_id FROM trait WHERE short_name=?) + ); + """ + try: + conn.executemany(stmt, traitlist) + except sqlite3.Error as e: + print("Error creating feat_trait: {}".format(e)) + except: + print( + "Error creating feat_trait something other than sqlite3 error" + ) + else: + conn.commit() + + # do prereqs + for i in data['feat']: + # print("\nDoing prereq:\t{}".format(i['name'])) + if i['prereqs'] == None: + # do nothing and start on next 'i' + # print("Continuing prereqs, skipping:\t{}".format(i['name'])) + continue + preqlist = [] + for j in i['prereqs']: + descr = j['descr'] + pfeat = j['feat'] + if pfeat == None: + is_feat_bool = False + else: + is_feat_bool = True + res = (descr, i['name'], is_feat_bool, pfeat) + preqlist.append(res) + # print(preqlist) + + # now to do the insert + istmt = """ + INSERT INTO featprereq (descr, parent_feat_id, is_prereq_feat_bool, prereq_feat_id) + VALUES ( + ?, + (SELECT feat_id FROM feat WHERE name=?), + ?, + (SELECT feat_id FROM feat WHERE name=?) + ) + """ + try: + conn.executemany(istmt, preqlist) + except sqlite3.Error as e: + print("Error creating featprereq {}".format(e)) + except: + print( + "Error creating featprereq something other than sqlite3 error" + ) + else: + conn.commit() + +# TODO ugggh;;; this is soooo ugly and needs refactoring but it's working +def do_sourceentry_to_feats(srcs, conn): + c = conn.cursor() + + stmt = "SELECT source.source_id, feat.feat_id FROM source, feat WHERE source.abbr=? AND feat.name=?" + istmt = "INSERT INTO sourceentry (source_id, page_start, page_stop) VALUES (?,?,?)" + for i in srcs: + # print("i in srcs: {}".format(i)) + inp_data = (i[1], i[0]) + # print("inp data: {}".format(inp_data)) + for row in c.execute(stmt, inp_data): + # print("source_id:{} skill_id:{}".format(row[0], row[1])) + iinp_data = (row[0], i[2], i[3]) + # print("iinp data: {}".format(iinp_data)) + + try: + c.execute(istmt, iinp_data) + except sqlite3.IntegrityError as e: + if "UNIQUE" in str(e): + # we fully expect UNIQUE constraint to fail on some of these so it's fine + conn.commit() + # print("committed istmt") + else: + # but we still want to know what's going on if there's some other error + print("Something went wrong with istmt: {}".format(e)) + except sqlite3.Error as e: + print("Error inserting a sourceentry for skill: {}".format(e)) + else: + conn.commit() + # print("committed istmt") + + linkstmt = "INSERT INTO sourceentry_feat (sourceentry_id, feat_id) VALUES ((SELECT sourceentry_id from sourceentry WHERE source_id=? AND page_start=? AND page_stop=?), ?)" + linkinp_data = (row[0], i[2], i[3], row[1]) + # print(linkinp_data) + try: + c.execute(linkstmt, linkinp_data) + except sqlite3.IntegrityError as e: + if "UNIQUE" in str(e): + # we fully expect UNIQUE constraint to fail on some of these so it's fine + conn.commit() + # print("committed linkstmt") + pass + else: + # but we still want to know what's going on if there's some other error + print(e) + except sqlite3.Error as e: + print("Error inserting a sourceentry for feat: {}".format(e)) + else: + # print("committed linkstmt") + conn.commit() + def get_trigger_id_by_descr(t, conn): qstmt = "SELECT trigger_id FROM trigger WHERE descr=?;" @@ -321,7 +512,7 @@ def do_ancestries(data, conn): c.execute(table) table = """ - CREATE TABLE ancestries_traits ( + CREATE TABLE trait_ancestries ( id INTEGER PRIMARY KEY, ancestry_id INTEGER NOT NULL, trait_id INTEGER NOT NULL, @@ -332,6 +523,7 @@ def do_ancestries(data, conn): """ c.execute(table) + # insert basics into ancestries table inp_data = [] for i in data['ancestries']: @@ -430,7 +622,7 @@ def do_ancestries(data, conn): # print("traitlist is:\t{}".format(traitlist)) stmt = """ - INSERT INTO ancestries_traits (ancestry_id, trait_id) VALUES ( + INSERT INTO trait_ancestries (ancestry_id, trait_id) VALUES ( (SELECT ancestry_id FROM ancestries WHERE name=?), (SELECT trait_id FROM trait WHERE short_name=?) ); @@ -438,15 +630,16 @@ def do_ancestries(data, conn): try: conn.executemany(stmt, traitlist) except sqlite3.Error as e: - print("Error creating ancestries_traits: {}".format(e)) + print("Error creating trait_ancestries {}".format(e)) except: print( - "Error creating ancestries_traits something other than sqlite3 error" + "Error creating trait_ancestries something other than sqlite3 error" ) else: conn.commit() + def do_gear(data, conn): table = """ CREATE TABLE gear(