def load_traits(self,files): for file_name in files: f = open(file_name) data = yaml.load(f) f.close() yamlhelp.merge(data,self.traits) for trait_id in self.traits: trait = self.traits[trait_id] trait = Trait(trait_id,**self.traits[trait_id]) self.traits[trait_id] = trait for trait_id in self.traits: #second pass needed since traits defs include other traits trait = self.traits[trait_id] if trait.replaces: trait.replaces = self.traits[trait.replaces] if not trait.cancels: trait.cancels=[] for i in range(len(trait.cancels)): trait.cancels[i] = self.traits[trait.cancels[i]] trait.effect = StatusEffect(trait_id,**trait.effect) if trait.cost: yamlhelp.convert_keys(trait.cost,self.materials) if trait.removal_cost: yamlhelp.convert_keys(trait.removal_cost,self.materials)
def export_all_traits(self, suite, dirname=None): self.report_start_exporting_traits() traitdb = Trait(self.conn, suite) traits = traitdb.get_trait_list() self.report_total_traits(len(traits)) for trait in traits: self.export_trait(trait, dirname=dirname, traitdb=traitdb)
def generate(self, num_loci): for i in range( self.k ): # randomly choose a niche and whether it is "on" or "off" #self.eco.append([]) # the 2k characteristics; ecological and preference #self.pref.append([]) self.eco.append(Trait(num_loci)) self.pref.append(Trait(num_loci))
def traits(self): profileTraits = self.profile.traits adoptersTraits = [a.traits for a in self.adopters] return [ Trait("id", self.id), Trait("shelter_id", self.shelter_id), ]
def _find_missing_packages(self, suite, traits, dirname): missing = dict() traitdb = Trait(self.conn, suite) for trait in traits: tdir = dirname / trait traitxml = traitdb.parse_trait_xml(tdir, suite=suite) missing_list = traitdb.find_missing_packages(traitxml) if missing_list: missing[trait] = missing_list return missing
def character_generator(): mapping = {'Ace': 12, 'King': 10, 'Queen': 10, 'Jack': 8, '10': 8, '9': 8, '8': 6, '7': 6, '6': 6, '5': 6, '4': 6, '3': 6, '2': 4, 'Spades': 4, 'Hearts': 3, 'Diamonds': 2, 'Clubs': 1} deck = pydealer.Deck() deck.shuffle() # Deadlands rules are deal 12, toss two from 3 to A inclusive (2, Jkr must stay) # selection = deck.deal(12) # But for now, we'll just take 10 randomly and live with it. selection = deck.deal(10) traits = { 'deftness': Trait(mapping[selection[0].suit], mapping[selection[0].value]), 'nimbleness': Trait(mapping[selection[1].suit], mapping[selection[1].value]), 'quickness': Trait(mapping[selection[2].suit], mapping[selection[2].value]), 'strength': Trait(mapping[selection[3].suit], mapping[selection[3].value]), 'vigor': Trait(mapping[selection[4].suit], mapping[selection[4].value]), 'cognition': Trait(mapping[selection[5].suit], mapping[selection[5].value]), 'knowledge': Trait(mapping[selection[6].suit], mapping[selection[6].value]), 'mien': Trait(mapping[selection[7].suit], mapping[selection[7].value]), 'smarts': Trait(mapping[selection[8].suit], mapping[selection[8].value]), 'spirit': Trait(mapping[selection[9].suit], mapping[selection[9].value])} # deftness = Trait(mapping[selection[0].suit], mapping[selection[0].value]) # nimbleness = Trait(mapping[selection[1].suit], mapping[selection[1].value]) # quickness = Trait(mapping[selection[2].suit], mapping[selection[2].value]) # strength = Trait(mapping[selection[3].suit], mapping[selection[3].value]) # vigor = Trait(mapping[selection[4].suit], mapping[selection[4].value]) # # cognition = Trait(mapping[selection[5].suit], mapping[selection[5].value]) # knowledge = Trait(mapping[selection[6].suit], mapping[selection[6].value]) # mien = Trait(mapping[selection[7].suit], mapping[selection[7].value]) # smarts = Trait(mapping[selection[8].suit], mapping[selection[8].value]) # spirit = Trait(mapping[selection[9].suit], mapping[selection[9].value]) return traits
def _find_missing_packages(self, suite, traits): missing = dict() tdb = Trait(self.conn, suite) print suite, traits for trait in traits: path = self._get_trait_path(suite, trait) traitxml = tdb.parse_trait_xml(path, suite=suite) missing_list = tdb.find_missing_packages(traitxml) if missing_list: #print 'in trait,', trait, ', missing packages: ', missing_list missing[trait] = missing_list return missing
def _find_missing_packages(self, suite, traits): missing = dict() tdb = Trait(self.conn, suite) print suite, traits for trait in traits: path = self._get_trait_path(suite, trait) traitxml = tdb.parse_trait_xml(path, suite=suite) missing_list = tdb.find_missing_packages(traitxml) if missing_list: # print 'in trait,', trait, ', missing packages: ', missing_list missing[trait] = missing_list return missing
def export_trait(self, trait, suite=None, dirname=None, traitdb=None): if traitdb is None: if suite is None: RuntimeError , "you must pass a suite if you don't pass a Trait object" print "make new traitdb" traitdb = Trait(self.conn, suite) traitdb.set_trait(trait) if suite is None: suite = traitdb.suite if dirname is None: dirname = self._make_suite_export_path(suite) traitdb.export_trait(dirname) self.report_trait_exported(trait, dirname)
def defaultTraits(): return [ Trait("name"), Trait("address"), Trait("city"), Trait("state"), Trait("zipcode"), Trait("website"), Trait("occupancy"), Trait("capacity") ]
def traits(self): return [ Trait("name", self.name), Trait("address", self.address), Trait("city", self.city), Trait("state", self.state), Trait("zipcode", self.zipCode), Trait("website", self.website), Trait("occupancy", self.current_occupancy), Trait("capacity", self.maximum_capacity) ]
def traits(self): return [ Trait("picture", self.picture, "image"), Trait("name", self.name), Trait("weight", self.weight), Trait("gender", self.gender, "select", ['male', 'female']), Trait("birthday", self.dateOfBirth, "date"), Trait("description", self.description, "textarea"), Trait("needs", self.specialNeeds, "textarea") ]
def defaultTraits(): return [ Trait("picture"), Trait("name"), Trait("weight"), Trait("gender", 'male', "select", ['male', 'female']), Trait("birthday", '2015-11-17', "date"), Trait("description", "", "textarea"), Trait("needs", "", "textarea") ]
def testTextAreaTrait(): profile = session.query(Profile).filter_by(id=1).one() trait = Trait("description", profile.description, "textarea") print trait.asInputElement("editPuppyForm") print trait.asOutputElement()
def testTextTrait(): profile = session.query(Profile).filter_by(id=1).one() trait = Trait("name", profile.name) print trait.asInputElement("editPuppyForm") print trait.asOutputElement()
def testDateTrait(): profile = session.query(Profile).filter_by(id=1).one() trait = Trait("birthday", profile.dateOfBirth, "date") print trait.asInputElement("editPuppyForm") print trait.asOutputElement()
def parse_traits(pages: List[str]) -> Optional[List[object]]: traits: List[Any] = [] for ind, page in enumerate(pages): if page == '': continue # placeholder to properly enumerate "bad" array items print('parsing id={}\tof\t{}'.format(ind + 1, len(pages))) trait = Trait() whole_text = BeautifulSoup(page, 'html.parser').find( 'span', {'id': 'ctl00_MainContent_DetailedOutput'}) # get name trait.id = ind + 1 trait.name = str(whole_text.h1.string) # get description if whole_text.find(True, text=re.compile('This trait was not listed')): trait.description = None else: d_node = whole_text.find( 'a', class_='external-link', href=re.compile('https://paizo.com/products/')).findNext('br') while d_node and not d_node.name == 'h2': if type(d_node) == NavigableString or d_node.text: trait.description = ''.join( [trait.description, str(d_node.string)]) d_node = d_node.next_sibling # get source src_tuple: Tuple[str, str] = whole_text.find( 'a', class_='external-link', href=re.compile('https://paizo.com/products/')).string.split('pg.') trait.source.book = src_tuple[0].strip() trait.source.page = int(src_tuple[1].strip()) # pymongo does not accept anything but dicts and mutablemappings, hence asdict() traits.append(dataclasses.asdict(trait)) # now we put them in the groups defined on https://2e.aonprd.com/Traits.aspx with fetch.urlopen('http://2e.aonprd.com/Traits.aspx') as res: if not res: raise HTTPError s = res.read() traits_main_page = BeautifulSoup(s, 'html.parser').find( 'span', id='ctl00_MainContent_DetailedOutput') d_node = traits_main_page group_label = '' while d_node: if d_node.name == 'h2': group_label = str(d_node.string.split('Traits')[0].strip()) if d_node.name == 'span' and d_node.attrs.get('class') == ['trait']: for t in traits: if group_label and d_node.get('title') == t.get('name'): t['groups'].append(group_label) d_node = d_node.next_element return traits
def testSelectTrait(): profile = session.query(Profile).filter_by(id=1).one() sexes = ['male', 'female'] trait = Trait("gender", profile.gender, "select", sexes) print trait.asInputElement("editPuppyForm") print trait.asOutputElement()
def backup(self, path=None): if path is None: path = self.path if not isdir(path): raise Error, '%s not a directory' % path dbfile = file(join(path, 'database.xml'), 'w') self.writexml(dbfile, indent='\t', newl='\n', addindent='\t') dbfile.close() self.backup_profiles(path) suites = [x.suite for x in self._suite_rows()] for suite in suites: makepaths(join(path, suite)) trait = Trait(self.conn, suite) for t in trait.get_trait_list(): trait.set_trait(t) trait.backup_trait(join(path, suite))
def export_trait(self, trait, suite=None, dirname=None, traitdb=None): if traitdb is None: if suite is None: RuntimeError, "you must pass a suite if you don't pass a Trait object" print "make new traitdb" traitdb = Trait(self.conn, suite) traitdb.set_trait(trait) if suite is None: suite = traitdb.suite if dirname is None: dirname = self._make_suite_export_path(suite) traitdb.export_trait(dirname) self.report_trait_exported(trait, dirname)
def _import_trait(self, suite, dirname): traitdb = Trait(self.conn, suite) traitdb.insert_trait(dirname, suite)
def parse_creatures(pages: List[str]) -> Optional[List[object]]: # parse the families of creatures from http://2e.aonprd.com/Monsters.aspx?Letter=All try: with fetch.urlopen( 'http://2e.aonprd.com/Monsters.aspx?Letter=All') as inf: fam_page = inf.read() if not fam_page: raise ValueError('unable to fetch families table from AoN') except Exception: print('error fetching family table') sys.exit(1) fam_table: List[Tag] = BeautifulSoup(fam_page, 'html.parser').find_all('tr') fams = {} for tr in fam_table[1:]: name = tr.findChildren('td')[0].a.u.string fam = str(tr.findChildren('td')[1].string).strip() if fams.get(fam): fams.get(fam).append(name) else: fams[fam] = [name] creatures: List[object] = [] for ind, page in enumerate(pages): if page == '': continue # placeholder to properly ennumerate "bad" array items print('parsing id={}\tof\t{}'.format(ind + 1, len(pages))) creature: Creature = Creature() main_tag = BeautifulSoup(page, 'html.parser').find( 'span', id='ctl00_MainContent_DetailedOutput') # id/name/level creature.id = ind + 1 creature.name = str(main_tag.h1.string) creature.level = main_tag.find( 'span', text=re.compile('Creature -?[0-9]+')).text.split()[1] # source source_tag = main_tag.find('b', text=re.compile('^Source$')).find_next( 'a', class_='external-link').find_next('i').text src = [s.strip() for s in str(source_tag).split('pg.')] creature.source.book = src[0] creature.source.page = int(src[1]) # HP TODO REWORK THE WHOLE SECTION hp_tag = main_tag hp_re = re.compile( r'\s*HP\s*(?P<hp>[0-9]+);?\s*(?P<hp_notes>[\w\d\s\-()\'’+.,]*);?\s*' ) while hp_tag.next: if hp_tag.name and hp_tag.name == 'b' and hp_tag.text == 'HP': break hp_tag = hp_tag.next hp_str = '' while hp_tag.next: if hp_tag.name == 'br' or hp_tag.name == 'hr': # or (hp_tag.name == 'b' and hp_tag.string in ['Immunities', 'Resistances', 'Weaknesses']): break if type(hp_tag) == NavigableString: hp_str = ''.join((hp_str, hp_tag.string)) hp_tag = hp_tag.next hp_match = re.match(hp_re, hp_str) creature.hitPoints = int(hp_match.groupdict().get('hp')) creature.hitPointsNotes = hp_match.groupdict().get('hp_notes') regen_re = re.compile( r'\s*[rR]egeneration (?P<regen>[0-9]+)\s*,?\s*\(?deactivated by\s*(?P<deactivated>[\w ]+)\)?\s*' ) hardness_re = re.compile(r'\s*[hH]ardness (?P<hard>[0-9]+)') if creature.hitPointsNotes: creature.hitPointsNotes = ''.join( re.split(re.compile(r'\s*HP [0-9]+[,;]+\s*'), creature.hitPointsNotes)[1:]).strip(' ;,') regen_match: Match = re.match(regen_re, creature.hitPointsNotes) if regen_match: creature.regeneration = int(regen_match.group('regen')) creature.deactivatedBy = regen_match.group('deactivated') hardness_match: Match = re.match(hardness_re, creature.hitPointsNotes) if hardness_match: creature.hardness = int(hardness_match.group('hard')) creature.hitPointsNotes = re.sub(hardness_re, '', creature.hitPointsNotes) # Immunities; Weaknesses; Resistances imm_pattern = re.compile( r'\s*(Immunities\s*(?P<imm>[\w\d\s\-(),\']*);?)?\s*(Weaknesses\s*(?P<weak>[\w\d\s\-(),\']*);?)?\s*(Resistances\s*(?P<res>[\w\d\s\-(),\']*);?)?' ) imm_str = '' while hp_tag.next: if hp_tag.name == 'br' or hp_tag.name == 'hr': break if type(hp_tag) == NavigableString: imm_str = ''.join([imm_str, hp_tag.string]) hp_tag = hp_tag.next imm_match = re.match(imm_pattern, imm_str) creature.immunities = [ x.strip() for x in imm_match.group('imm').split(',') ] if imm_match.group('imm') else [] creature.weaknesses = [ x.strip() for x in imm_match.group('weak').split(',') ] if imm_match.group('weak') else [] creature.resistances = [ x.strip() for x in imm_match.group('res').split(',') ] if imm_match.group('res') else [] # Traits trait_tag = main_tag while trait_tag.next: # scan through until traits section if trait_tag.name and (trait_tag.get('class') == ['traituncommon' ]): creature.rarity = 'uncommon' if trait_tag.name and (trait_tag.get('class') == ['traitrare']): creature.rarity = 'rare' if trait_tag.a.string == 'Rare' else 'unique' if trait_tag.name and trait_tag.get('class') == ['traitalignment']: break trait_tag = trait_tag.next while trait_tag.next: if trait_tag.name == 'br' or trait_tag.name == 'hr': break if trait_tag.name and trait_tag.get('class') == ['traitalignment']: creature.alignment = trait_tag.text if trait_tag.name and trait_tag.get('class') == ['traitsize']: creature.size = trait_tag.text if trait_tag.name and trait_tag.get('class') == ['trait']: t: Trait = Trait(name=trait_tag.text, description=trait_tag.get('title')) creature.traits.append(t) trait_tag = trait_tag.next # Perception and senses sense_tag = trait_tag sense_str = '' sense_re = re.compile( r'\s*Perception\s*(?P<per>[+-]?[0-9]+);?\s*(?P<per_notes>[\w\d\s\-()\'+.,]*)?\s*' ) while sense_tag.next: if sense_tag.name == 'b' and sense_tag.string == 'Perception': break sense_tag = sense_tag.next while sense_tag.next: if sense_tag.name == 'br' or sense_tag.name == 'hr': break elif type(sense_tag) == NavigableString: sense_str = ''.join((sense_str, sense_tag.string)) sense_tag = sense_tag.next sense_match = re.match(sense_re, sense_str) creature.perception = int(sense_match.group('per')) creature.senses = [ x.strip() for x in sense_match.group('per_notes').split(',') ] # languages language_tag = sense_tag.find_next('b', text='Languages') language_re = re.compile( r'\s*Languages\s*(?P<langs>[\w\d\s\-()\'+.,]*);?\s*(?P<comms>[\w\d\s\-()\'+.,]*)?\s*' ) if language_tag: language_str = '' while language_tag.next: if language_tag.name == 'br' or language_tag.name == 'hr': break elif type(language_tag) == NavigableString: language_str = ''.join((language_str, language_tag.string)) language_tag = language_tag.next language_match = re.match(language_re, language_str) creature.languages = [ x.strip() for x in language_match.group('langs').split(',') ] creature.otherCommunication = [ x.strip() for x in language_match.group('comms').split(',') ] # skills skill_tag = sense_tag.find_next('b', text='Skills') skills_re = re.compile(r'\s*Skills\s*(?P<skills>[\w\d\s\-()\'+.,]*)') skill_re = re.compile( r'(?P<name>[\w ]*)\s*(?P<mod>[+-]+[0-9]+)\s*(?P<notes>\([\w\d\s\-()\'+.,]*\))?\s*' ) if skill_tag: skill_str = '' while skill_tag.next: if skill_tag.name == 'br' or skill_tag.name == 'hr': break elif type(skill_tag) == NavigableString: skill_str = ''.join((skill_str, skill_tag.string)) skill_tag = skill_tag.next skill_match = re.match(skills_re, skill_str) for s in re.finditer(skill_re, skill_match.group('skills')): skill = Header(s.group('name'), s.group('notes'), int(s.group('mod'))) creature.skills.append(skill) # ability mods abm_tag = main_tag abm_str = '' abm_re = re.compile( r'\s*Str\s*(?P<str>[+-][0-9]+),\s*Dex\s*(?P<dex>[+-][0-9]+),\s*Con\s*(?P<con>[+-][0-9]+),\s*Int\s*(?P<int>[+-][0-9]+),\s*Wis\s*(?P<wis>[+-][0-9]+),\s*Cha\s*(?P<cha>[+-][0-9]+)\s*' ) while abm_tag.next: if abm_tag.name == 'b' and abm_tag.string == 'Str': break abm_tag = abm_tag.next while abm_tag.next: if abm_tag.name == 'br' or abm_tag.name == 'hr': break elif type(abm_tag) == NavigableString: abm_str = ''.join((abm_str, abm_tag.string)) abm_tag = abm_tag.next abmods = re.match(abm_re, abm_str) creature.abilityMods = [int(x) for x in abmods.groups()] # items # (for some reason these are listed in the template as ABOVE interaction abilities, but are often NOT) item_tag = abm_tag item_str = '' item_re = re.compile(r'\s*(?P<item>[\w\d\s\-()\'+.,]+),?\s*') while item_tag.next: if item_tag.name == 'b' and item_tag.string == 'Items': break item_tag = item_tag.next while item_tag.next: if item_tag.name == 'br' or item_tag.name == 'hr': break elif type(item_tag) == NavigableString: item_str = ''.join((item_str, item_tag.string)) item_tag = item_tag.next if item_str: item_str = item_str.replace('Items', '', 1) item_matches = re.findall(item_re, item_str) creature.items = [x.strip() for x in item_matches if x.strip()] # interaction abilities creature.interactionAbilities, _ = get_abilities(abm_tag) # AC ac_tag = main_tag while ac_tag.next and not creature.ac: if ac_tag.name and ac_tag.name == 'b' and ac_tag.text == 'AC' and type( ac_tag.next) == NavigableString: creature.ac = int( re.match(re.compile(r'\s*(?P<ac>[0-9]+)[;,]?\s*'), ac_tag.next_sibling.string).group('ac')) ac_tag = ac_tag.next # AC notes, iterate until saves while ac_tag.next: if ac_tag.name == 'b' and ac_tag.text == 'Fort': break elif not ac_tag.name: creature.acNotes = ''.join([creature.acNotes, ac_tag.string]) ac_tag = ac_tag.next if creature.acNotes: creature.acNotes = re.sub(re.compile(r'\s*AC\s*[0-9]+\s*[;,]*'), '', creature.acNotes).strip() # iterate through the whole row until hr/br, then parse the resulting string for saves and notes save_pattern = re.compile( r'\s*Fort\s*(?P<fort>[+\-][0-9]+)\s*(?P<fort_notes>[\w\d\s\-()\'+.,]*),\s*' r'Ref\s*(?P<ref>[+\-][0-9]+)\s*(?P<ref_notes>[\w\d\s\-()\'+.,]*),\s*' r'Will\s*(?P<will>[+\-][0-9]+)\s*(?P<will_notes>[\w\d\s\-()\'+.,]*);?' r'(?P<save_notes>[\w\d\s\-()\'+.,]*)?\s*') saves_str = '' while ac_tag.next: if ac_tag.name == 'hr' or ac_tag.name == 'br': break if type(ac_tag) == NavigableString: saves_str = ''.join([saves_str, ac_tag.string]) ac_tag = ac_tag.next saves_match = re.match(save_pattern, saves_str) creature.fortitude = int(saves_match.group('fort')) creature.fortitudeNotes = saves_match.group('fort_notes') creature.reflex = int(saves_match.group('ref')) creature.reflexNotes = saves_match.group('ref_notes') creature.will = int(saves_match.group('will')) creature.willNotes = saves_match.group('will_notes') creature.saveNotes = saves_match.group('save_notes') # automatic abilities creature.automaticAbilities, _ = get_abilities(hp_tag) # speed speed_tag = hp_tag.next speed_str = '' while speed_tag.next: if speed_tag.name == 'b' and speed_tag.string == 'Speed': break speed_tag = speed_tag.next while speed_tag.next and speed_tag.name != 'hr' and speed_tag.name != 'br': if type(speed_tag) == NavigableString and speed_tag.string.strip( ) != 'Speed': speed_str = ''.join((speed_str, speed_tag.string)) speed_tag = speed_tag.next creature.speed = speed_str # offensive/proactive abilities action_tag: Tag = speed_tag.next creature.strikes, action_tag = get_strikes(action_tag) creature, action_tag = get_spells(creature, action_tag) creature.activeAbilities, action_tag = get_abilities(action_tag) creature.sidebars, action_tag = get_sidebars(action_tag) # set family creature.family = [k for (k, v) in fams.items() if creature.name in v] creature.family = creature.family[0] if creature.family else '—' # NAVIGABLE STRINGS CAUSE RECURSION MAX DEPTH EXCEPTIONS. Convert to str before setting fields creatures.append(dataclasses.asdict(creature)) return creatures
def traits(self): return [Trait("name", self.name)]
def defaultTraits(): return [Trait("name")]
def _insert_trait_(self, trait, suite): traitdb = Trait(self.conn, suite) #path = join(self.main_path, suite, trait + '.tar') path = join(self.main_path, suite, trait) traitdb.insert_trait(path, suite)
def defaultTraits(): return [Trait("id"), Trait("shelter_id")]
def _insert_trait_(self, trait, suite): traitdb = Trait(self.conn, suite) path = join(self.main_path, suite, trait + '.tar') traitdb.insert_trait(path, suite)