v50 Steam/Premium information for editors
- v50 information can now be added to pages in the main namespace. v0.47 information can still be found in the DF2014 namespace. See here for more details on the new versioning policy.
- Use this page to report any issues related to the migration.
This notice may be cached—the current version can be found here.
Difference between revisions of "User:Button/ModestMod"
Jump to navigation
Jump to search
Line 524: | Line 524: | ||
if output_stream == None: | if output_stream == None: | ||
outfile.close()'''</pre> | outfile.close()'''</pre> | ||
+ | |||
+ | ==== Minor breakthrough ==== | ||
+ | |||
+ | <pre>graphics_nodes = _walk_filenames_into_tagnode_collection() | ||
+ | target_nodes = _walk_filenames_into_tagnode_collection() | ||
+ | |||
+ | |||
+ | |||
+ | class TagNode: | ||
+ | |||
+ | def __init__(self,filename,template,tag,parent=None): | ||
+ | self._tag = tag | ||
+ | self._filename = filename | ||
+ | self._parent = parent | ||
+ | self._template = template | ||
+ | self._lit_children = {} | ||
+ | self._pat_children = {} | ||
+ | self._pattern = self.get_pattern() | ||
+ | |||
+ | global graphics_tokens_by_file | ||
+ | if parent != None: | ||
+ | parent.add_child(self) | ||
+ | |||
+ | def add_child(self, child_tag_node): | ||
+ | self._lit_children[child_tag_node._tag] = child_tag_node | ||
+ | self._pat_children[child_tag_node.get_pattern()] = child_tag_node | ||
+ | |||
+ | def apply_graphics(self, graphics_node): | ||
+ | tags = self._tag.split(':') | ||
+ | graphics = graphics_node._tag.split(':') | ||
+ | tag_template = self._template.get_template_match(self._tag)[0] | ||
+ | merged = [] | ||
+ | graphics_template = self._template.get_template_match(graphics_node._tag)[0] | ||
+ | # print("Graphics cannot be applied from ",graphics_node._tag," onto ",self._tag) | ||
+ | |||
+ | for ii in range(0,len(tag_template)): | ||
+ | if tag_template[ii] != graphics_template[ii]: | ||
+ | print("Graphics cannot be applied from ",graphics_node._tag," onto ",self._tag," because their templates do not match.") | ||
+ | elif tag_template[ii] != '&' and tag_template[ii] != '?': | ||
+ | if tags[ii] != graphics[ii]: | ||
+ | print("Tags are not compatible because token ",ii," does not match. Target: ",tags[ii]," Graphics: ",graphics[ii]) | ||
+ | else: | ||
+ | merged.append(tags[ii]) | ||
+ | elif tag_template[ii] == '&': | ||
+ | merged.append(tags[ii]) | ||
+ | elif tag_template[ii] == '?': | ||
+ | merged.append(graphics[ii]) | ||
+ | else: | ||
+ | print("This block should never be reached. Big problem in TagNode.apply_graphics.") | ||
+ | |||
+ | return ":".join(merged) | ||
+ | |||
+ | # Too much work | ||
+ | # def compatible_with(self, graphics_tag_node): | ||
+ | # return self._template.resolve(self._tag,graphics_tag_node._tag) != None | ||
+ | |||
+ | def get_pattern(self): | ||
+ | if self._pattern == None: | ||
+ | to_return = self._tag.split(':') | ||
+ | tag_tokens = self._tag.split(':') | ||
+ | template_possibilities = self._template.get_template_match(self._tag) | ||
+ | if len(template_possibilities) != 1: | ||
+ | print("Tag ",self._tag," has ",len(template_possibilities)," possible configurations: ") | ||
+ | for config in template_possibilities: | ||
+ | print(config,', ') | ||
+ | else: | ||
+ | for ii in range(0,len(tag_tokens)): | ||
+ | if template_possibilities[0][ii] in [tag_tokens[ii],'$']: | ||
+ | to_return[ii] = tag_tokens[ii] | ||
+ | elif template_possibilities[0][ii] in ['?','&']: | ||
+ | to_return[ii] = template_possibilities[0][ii] | ||
+ | else: | ||
+ | print("Tag does not match its own template!! Tag: ",self._tag,"; Template: ",self._template._template_tag) | ||
+ | self._pattern = ":".join(to_return) | ||
+ | return self._pattern | ||
+ | |||
+ | def aligns_with(self,other_tag): | ||
+ | return self._template == other_tag._template and self.get_pattern() == other_tag.get_pattern() | ||
+ | |||
+ | class BoundNode: | ||
+ | def __init__(self,target_node,graphics_node,parent=None): | ||
+ | self._parent = parent | ||
+ | self._children = {} | ||
+ | self._popped_children = {} | ||
+ | self._additional = [] | ||
+ | self._target_node = target_node | ||
+ | self._graphics_node = graphics_node | ||
+ | if parent != None: | ||
+ | parent.add_child(self) | ||
+ | #self._popped = False | ||
+ | |||
+ | def add_child(self, child_node): | ||
+ | self._children[child_node._target_node._tag]=child_node | ||
+ | self._popped_children[child_node._target_node._tag]=False | ||
+ | |||
+ | def create_child_nodes(self): | ||
+ | # Children with pattern keys in both target & graphics | ||
+ | for shared_key in self._target_node._pat_children.keys().intersection(self._graphics_node._pat_children.keys()): | ||
+ | new_node = BoundNode(self._target_node._pat_children[shared_key],self._graphics_node._pat_children[shared_key],self) | ||
+ | self.add_child(new_node) | ||
+ | new_node.create_child_nodes() | ||
+ | # Children with pattern keys in target but not in graphics can be ignored | ||
+ | |||
+ | # Children with pattern keys in graphics but not in target | ||
+ | for graphics_key in self._graphics_node._pat_children.keys() - self._target_node._pat_children.keys(): | ||
+ | graphics_in_question = self._graphics_node._pat_children[graphics_key] | ||
+ | if graphics_in_question.is_graphics_tag(): | ||
+ | self._additional.append(graphics_in_question) | ||
+ | # End | ||
+ | |||
+ | def are_all_children_popped(self): | ||
+ | to_return = True | ||
+ | for child in self._popped_children.keys(): | ||
+ | to_return &= self._popped_children.keys()[child] | ||
+ | return to_return | ||
+ | |||
+ | def get_merge(self): | ||
+ | return self._target_node.apply_graphics(self._graphics_node) | ||
+ | |||
+ | def pop_child(self, target_tag): | ||
+ | if target_tag not in self._children.keys(): | ||
+ | return self | ||
+ | else: | ||
+ | if self._popped_children[target_tag]: | ||
+ | print("Popping tag that has already been popped: ",target_tag) | ||
+ | |||
+ | self._popped_children[target_tag] = True | ||
+ | return self._children[target_tag]</pre> |
Revision as of 22:00, 15 May 2015
This is a directory page for my Modest Mod work.
I feel a little bad for clogging up the wiki with this stuff, but sometimes I get bored and I'm not at my home computer.
Plans
- Moving the no-fear-of-commitment orientation mods out into a pair of creature variations, in c_variation_modest. May make a Module applying them to sapients as well. Eternal Lovers are kind of frustrating.
- Could probably just make the plant growths that I currently have wrapping tree nuts, edible or pressable or whatever in their own right, and never have to deal with the seeds. OTOH, that might mess up grinding them to paste/pressing them? And would still need the hulling reaction for plantable legumes.
- Could change implementation of all plants, including those brewed 'whole', into growths. Then would be able to share reactions better, and do seed/no seed on a purely FAKESEED basis.
- Probably not worth it in vanilla, but maybe fore plant features, since we'll be needing to mill "whole plants" (e.g. cassava, whip vines) and also to mill seedheads.
- Need to move Plump Helmets back to a usable plant instead of a fruit. Save it as fruit for the Basic Adventurer's Pack.
- Need to look at the expanded creature variation replacement tokens in preparation for the vampire anti-sobriety module.
Accelerated
- Need to look at the old Accelerated Modest Mod and see how much of it is applicable to the current version.
- Need to see about thinning down plant materials, like a lot.
- Need to remove useless plant growths, like cherry blossoms etc. Leaves? Or would that be too ugly?
- Could probably reduce grass to a single species? Or would that make pandas shitty?
Plant Features
- Could probably make grain use the fruit(like?) reactions for brewing, milling, etc.
- Kahlua & Chajun & possibly the plant products that are used to make them could give a temporary [NOSLEEP] tag? Followed by a 'crash' of a drowsiness syndrome?
- Jellies? Preserves? Juices?
- More variation in material values
Basic Adventurer's Pack
This needs to be a basic pack. Don't get cocky.
Must include
- Plump helmet to fruit
- Backpacks, bags, quivers, waterskins.
- Tanning
- Stone knife
- Spinning & weaving
- Spindle
- Tanning
- Bone ammo
- Stone chisel
- Arrow bamboo?
- Trophy jewelry/crafts for trading
Might want to include
- Leather armor.
- Bone & shell armor.
- Bone bows, crossbows, blowguns
- Bamboo?
- Plant fiber thread. Rope reeds, pig tail stalks, others?
- For the merge with Plant Features, abaca/banana/pineapple leaves, cotton bolls, etc. A lot of the plant fabric stuff is Plant Features-necessary.
Probably going too far
- Enable a whole bunch of sapients playable as outsiders. Not just the ones in the gear-already-exists size range.
- Hahaha, fairies as a playable outsider race |D That would be silly
- Cooking. Just biscuits? Or full-on recipes?
- Flour? Oil? Good use for mortar & pestle...
- Maybe a balanced meal would require a veg, a protein, & a sugar/starch, & would provide minor (temporary) attribute boosts?
- Self-buff "cheats"?
Raws
- creature_subterranean
- c_variation_default
- body_modest_pearl
- c_variation_modest
- plant_crops
- plant_garden
- plant_standard
- plant_new_trees
import os template_tree = None runconfig = 'resources/run.config' ascii_codes = None #graphics_tokens_by_file = {} properties = { 'target':['dir'], 'source':['dir'], 'output':['dir'], 'save':['dir'], 'templates':['file'], 'ascii':['file'] } def default_run(): load_run_config() load_all_templates() # Guessing at syntax, don't have that func here atm graphics_tags_by_file = load_graphics_source() target_tags_by_file = load_target_raws() #merged_tags_by_file = apply_graphics(target_tags_by_file,graphics_tags_by_file) def apply_graphics(target_tags,graphics_tags): for filename in target_tags.keys(): if filename in graphics_tags.keys(): for root_tag in target_tags[filename].keys(): if root_tag in graphics_tags[filename].keys(): target_tags[filename][root_tag].recursively_apply_graphics(graphics_tags[filename][root_tag]) def create_new_raws(targetdir, outputdir, target_tags, graphics_tags): file_list = [] for child in target_tags._children.keys(): this_file_name = target_tags._children[child]._filename if this_file_name not in file_list: file_list.append(this_file_name) ### START HERE ### # Walk the directory targetdir for reading # For each file, create a corresponding file in outputdir. Remember you'll need to create its directory structure! # If the name of the file is in file_list, call modify_file_as_its_copied(targetfilepath, outputfilepath, target_tags, graphics_tags), otherwise just copy the file over. Remember to close the file output stream after copying! # Remember to close the target file after copying! ### END HERE ### def modify_file_as_its_copied(targetfilepath, outputfilepath, target_tags, graphics_tags): curr_node = target_tags ### START HERE ### # open targetfile for read & outputfile for write # read each line from targetfile # for each tag in the line # for each template_node in curr_node._template._childref[tag.split(':')[0]] # new_tag = template_node.get_child_matching(tag) ### END HERE ### def load_run_config(): global runconfig runconfig_file = open(runconfig,'r') global properties for line in runconfig_file: props = line.strip().split('=') if len(props) == 0: continue elif len(props) != 2: print('Line "',line,'" in ',runconfig,' is improperly configured. Please format properties thus: "propertyname=value" (without quotes).') elif props[0] not in properties.keys(): print('Unknown property "',props[0],'" in ',runconfig) elif len(properties[props[0]]) > 1: print('Property "',props[0],'" is already defined.') elif not os.path.exists(props[1]): print('Property "',props[0],'" (',props[1],') not found on disk.') elif properties[props[0]][0] == 'dir' and not os.path.isdir(props[1]): print('The value of property "',props[0],'" must point to a directory.') elif properties[props[0]][0] == 'file' and not os.path.isfile(props[1]): print('The value of property "',props[0],'" must point to a file.') else: properties[props[0]].append(props[1]) runconfig_file.close() def load_all_templates(): global properties if properties['templates'][1] == None: # TODO error handling print("Undefined graphics template file. Please add a 'templates' property in ",runconfig,".") else: alltemplates = open(properties['templates'][1],'r') global template_tree if template_tree == None: # initialize the template tree template_tree = TemplateNode(None) for line in alltemplates: real_line = line.strip() # Starting at the root of the tree with each newline curr_node = template_tree if len(real_line) > 0: # TODO continue tags = real_line.split('|') for tag in tags: if tag in curr_node._children.keys(): curr_node = curr_node._children[tag] else: curr_node = TemplateNode(curr_node,tag) curr_node._is_graphics_tag = True alltemplates.close() #def check_file(filehandle): def _load_ascii_conversions(): global ascii_codes if ascii_codes == None: ascii_codes = {} if properties['ascii'][1] == None: print("Undefined ascii conversion file. Please add an 'ascii' property in ",runconfig,".") else: for line in open(properties['ascii'][1]): real_line = line.strip() if len(real_line) == 0: continue elif '=' not in real_line: print('ASCII conversion file contains the improperly-formatted line ',real_line,'.') else: point = real_line.rindex('=') if real_line[:point] in ascii_codes.keys(): print('Duplicate entry for ascii replacement ',real_line[:point]) else: ascii_codes[real_line[:point]] = real_line[point+1:] def load_graphics_source(): global properties if len(properties['source']) < 2: # TODO error handling print("Undefined graphics source file. Please add a 'source' property in ",runconfig,".") else: return _walk_rawfiles_into_tagnode_collection(properties['source'][1]) ''' else: for root, dirs, files in os.walk(properties['source'][1]): for rawfile in files: global template_tree curr_template_node = template_tree curr_graphics_node = None tarpath = os.path.join(root,rawfile) openfile = open(tarpath,encoding='cp437') for line in openfile: for tag in tags(line): matching_node = curr_template_node.find_template_match(tag) if matching_node != None: curr_template_node = matching_node if curr_graphics_node == None or matching_node in template_tree._children: curr_graphics_node = TagNode(rawfile,None,matching_node,tag) else: while matching_node._tag_template not in curr_graphics_node._template._children: curr_graphics_node = curr_graphics_node._parent curr_graphics_node = TagNode(rawfile,curr_graphics_node,matching_node,tag) openfile.close() ''' def load_target_raws(): global properties if len(properties['target']) < 2: # TODO error handling print("Undefined target raw file. Please add a 'target' property in ",runconfig,".") else: return _walk_rawfiles_into_tagnode_collection(properties['target'][1]) def _walk_rawfiles_into_tagnode_collection(directory): node_collection = {} for root, dirs, files in os.walk(directory): for rawfile in files: global template_tree # curr_template_node keeps track of what format of tag we've most recently seen, and thus what's valid next curr_template_node = template_tree # curr_real_node keeps track of the tag we stored that corresponds to the most local instance of curr_template_node. curr_real_node = None tarpath = os.path.join(root, rawfile) openfile = open(tarpath,encoding='cp437') for line in openfile: for tag in tags(line): matching_node = curr_template_node.find_template_match(tag) if matching_node != None: curr_template_node = matching_node if curr_real_node == None or matching_node in template_tree._children: curr_real_node = TagNode(rawfile,matching_node,tag) else: while curr_real_node != None and matching_node._tag_template not in curr_real_node._template._children: curr_real_node = curr_real_node._parent curr_real_node = TagNode(rawfile,matching_node,tag,curr_real_node) if rawfile not in node_collection: node_collection[rawfile] = { } if curr_real_node._parent == None: node_collection[rawfile][tag] = curr_real_node openfile.close() return node_collection def tags(line): processed_line = escape_problematic_literals(line) to_return = [] # list of strings, a la split() while '[' in processed_line and ']' in processed_line and processed_line.index('[') < processed_line.rindex(']'): if processed_line.index(']') < processed_line.index('['): processed_line = processed_line[processed_line.index('['):] to_return.append(processed_line[processed_line.index('[')+1:processed_line.index(']')]) processed_line = processed_line[processed_line.index(']')+1:] return to_return def escape_problematic_literals(rawline): global ascii_codes if ascii_codes == None: _load_ascii_conversions() line = rawline.strip() # Replace literal key characters with number codes # Literal colons are going to require some special processing, because of the following case: GROWTH:'r':'x': etc. That's why we can't just use a blind replaceAll. bracketscount = 0 # If odd, we are inside a tag. If even, we are outside a tag. count = 0 # Where we are in the string quotescount = 0 while count < len(line)-2: # Going from inside a tag to outside or vice versa if (bracketscount%2 == 0 and line[count] == "[") or (bracketscount%2 == 1 and line[count] == "]"): bracketscount += 1 # We are inside a tag and we have discovered a ' character beginning a literal value, with another 2 characters down on the other side. elif quotescount%2 == 0 and bracketscount%2 == 1 and line[count:count+3] in ascii_codes.keys(): # If the character could be a problem for later processing, replace it with its ascii code. #TODO rejigger this syntax line = line[:count] + ascii_codes[line[count:count+3]] + line[count+3:] elif line[count] == "'": quotescount += 1 elif bracketscount%2 == 1 and line[count] == ':': quotescount = 0 count += 1 # line has now had its literal "use this tile" versions of its special characters replaced with their numbers. return line class TemplateNode: #self._tag_template #string #self._children # dict of TemplateNodes #self._childref # dict of lists of TemplateNodes where the key is the first token #self._parent # TemplateNode #self._is_graphics_tag # Boolean #string does not contain the character '|'. def __init__(self, parent, string=""): self._is_graphics_tag = False self._children = {} self._childref = {} global template_tree if parent == None: self._parent = None template_tree = self else: if template_tree == None: self._parent = TemplateNode(None, "") else: self._parent = parent self._tag_template = string parent.add_child(self) def add_child(self, node): if node._tag_template in self._children.keys(): return self._children[node._tag_template] else: self._children[node._tag_template] = node first_token = node._tag_template.split(':')[0] if first_token not in self._childref.keys(): self._childref[first_token] = [] self._childref[first_token].append(node) return node def find_template_match(self, tag): curr_node = self matching_node = None out_of_parents = False while matching_node == None and not out_of_parents: matching_node = curr_node.get_child_matching(tag) if curr_node._parent == None: out_of_parents = True else: curr_node = curr_node._parent return matching_node def get_child_matching(self, tag): if tag in self._children.keys(): return self._children[tag] else: return_possibilities = [] first_token = tag.split(':')[0] for child in self._childref[first_token]: return_node = child.get_template_match(tag) if return_node != None: return_possibilities.append(child) if len(return_possibilities) == 1: return return_possibilities[0] elif len(return_possibilities) == 0: return None else: # TODO error handling print("Found more than one matching child. You put it together wrong. Matching children are: ") for poss in return_possibilities: print(poss) return return_possibilities[0] # This tells if a single tag matches a single tag; that is, it assumes we've got one element of the |-separated list def get_template_match(self, tag_to_compare): template_token_bag = [] template_token_bag.append(self._tag_template.split(':')) candidate_tokens = tag_to_compare.split(':') ii = 0 while ii < len(candidate_tokens) and len(template_token_bag) > 0: good_to_go = False for var in template_token_bag: if ii >= len(var): template_token_bag.remove(var) elif '&' == var[ii] or '?' == var[ii] or '$' == var[ii] or var[ii] == candidate_tokens[ii]: # This case is an auto-pass good_to_go = True else: if '&' in var[ii] or '?' in var[ii] or '$' in var[ii]: varii_type = var[ii][0] varii_range = var[ii][2:var[ii].index(')')].split(',') # If len(varii_range) == 1 then we have a range of format (x,), indicating any number of :'s if len(varii_range[1]) == 0: varii_range[1] = len(candidate_tokens)-len(var) + 1 # For every possible length (the +1 is because range is exclusive-end and my notation is inclusive-end) for jj in range(int(varii_range[0]),int(varii_range[1])+1): # Make a copy of var new_var = var[:] # Remove the range item del new_var[ii] # Replace it with (one of the possible lengths) times the multiplied symbol # If jj is 0 the range item is just removed for kk in range(0,jj): new_var.insert(ii,varii_type) # Place the new variant in the token bag for evaluation template_token_bag.append(new_var) # No counting, there is a new template_token_bag[ii] template_token_bag.remove(var) if good_to_go: ii += 1 for tag in template_token_bag: if len(tag) != len(candidate_tokens): template_token_bag.remove(tag) if ii < len(candidate_tokens): return None elif len(template_token_bag) == 1: return template_token_bag else: # TODO error handling # TODO plant GROWTH_PRINTs are throwing this when they end and there are templates of size n and n+1, fix that up plz print("Button, there's a problem, more than one template matched.\nTag: ",tag_to_compare,"Matches:") for template in template_token_bag: print(template) # Technically this does in fact have a matching template return template_token_bag def how_many_generations(self): temp_node = self count = -1 global template_tree while temp_node != template_tree: temp_node = temp_node._parent count = count + 1 return count def resolve(self, target_tag, graphics_tag): target_tag_bag = self.get_template_match(target_tag) graphics_tag_bag = self.get_template_match(graphics_tag) shared_tag_bag = [] for tarlist in target_tag_bag: for graphlist in graphics_tag_bag: if len(tarlist) == len(graphlist): found_flaw = False ii = 0 while ii < len(graphlist) and not found_flaw: found_flaw = graphlist[ii] != tarlist[ii] if not found_flaw: shared_tag_bag.append(graphlist[ii]) if len(shared_tag_bag) == 0: return None elif len(shared_tag_bag) > 1: print("Hey Button there's too many shared tag_bags in TemplateNode.resolve.") # Just gonna go with the first valid shared tag bag until I see a multi-shared-tag_bag so I have a better idea of how to deal with it template_tag_bag = shared_tag_bag[0] target_tag_bag = target_tag.split(':') graphics_tag_bag = graphics_tag.split(':') irreconcilable = False ii = 0 while ii < len(template_tag_bag) and not irreconcilable: if template_tag_bag[ii] == '$': irreconcilable = target_tag_bag[ii] != graphics_tag_bag[ii] elif template_tag_bag[ii] == '&': continue elif template_tag_bag[ii] == '?': target_tag_bag[ii] = graphics_tag_bag[ii] else: irreconcilable = target_tag_bag[ii] != graphics_tag_bag[ii] or target_tag_bag != template_tag_bag[ii] if not irreconcilable: return ":".join(target_tag_bag) else: return None class TagNode: def __init__(self,filename,template,tag,parent=None): self._tag = tag self._filename = filename self._parent = parent self._template = template self._children = {} global graphics_tokens_by_file if parent != None: parent._children[tag] = self ''' def recursively_apply_graphics(self,graphics_tag_node): continue_ok = True if self.compatible_with(graphics_tag_node): for child in self._children.keys(): continue_ok = continue_ok and self._children[child].recursively_apply_graphics(graphics_tag_node._children[child]) if continue_ok: continue_ok = self.graphicsify(graphics_tag_node) return continue_ok''' def compatible_with(self, graphics_tag_node): return self._template.resolve(self._tag,graphics_tag_node._tag) != None ''' def graphicsify(self, graphics_tag_node): upcoming_tag = self._template.resolve(self._tag,graphics_tag_node._tag) if upcoming_tag != None: self._tag = upcoming_tag return True else: return False def abbrev_write(self,tabnums=0,output_stream=None): if output_stream == None: outfile = self._filename.open('w',encoding='cp437') else: outfile = output_stream print(tabnums*'\t','[',self._tag,']\n',outfile) for child in self._children.keys(): self._children[child].abbrev_write(tabnums+1,outfile) if output_stream == None: outfile.close()'''
Minor breakthrough
graphics_nodes = _walk_filenames_into_tagnode_collection() target_nodes = _walk_filenames_into_tagnode_collection() class TagNode: def __init__(self,filename,template,tag,parent=None): self._tag = tag self._filename = filename self._parent = parent self._template = template self._lit_children = {} self._pat_children = {} self._pattern = self.get_pattern() global graphics_tokens_by_file if parent != None: parent.add_child(self) def add_child(self, child_tag_node): self._lit_children[child_tag_node._tag] = child_tag_node self._pat_children[child_tag_node.get_pattern()] = child_tag_node def apply_graphics(self, graphics_node): tags = self._tag.split(':') graphics = graphics_node._tag.split(':') tag_template = self._template.get_template_match(self._tag)[0] merged = [] graphics_template = self._template.get_template_match(graphics_node._tag)[0] # print("Graphics cannot be applied from ",graphics_node._tag," onto ",self._tag) for ii in range(0,len(tag_template)): if tag_template[ii] != graphics_template[ii]: print("Graphics cannot be applied from ",graphics_node._tag," onto ",self._tag," because their templates do not match.") elif tag_template[ii] != '&' and tag_template[ii] != '?': if tags[ii] != graphics[ii]: print("Tags are not compatible because token ",ii," does not match. Target: ",tags[ii]," Graphics: ",graphics[ii]) else: merged.append(tags[ii]) elif tag_template[ii] == '&': merged.append(tags[ii]) elif tag_template[ii] == '?': merged.append(graphics[ii]) else: print("This block should never be reached. Big problem in TagNode.apply_graphics.") return ":".join(merged) # Too much work # def compatible_with(self, graphics_tag_node): # return self._template.resolve(self._tag,graphics_tag_node._tag) != None def get_pattern(self): if self._pattern == None: to_return = self._tag.split(':') tag_tokens = self._tag.split(':') template_possibilities = self._template.get_template_match(self._tag) if len(template_possibilities) != 1: print("Tag ",self._tag," has ",len(template_possibilities)," possible configurations: ") for config in template_possibilities: print(config,', ') else: for ii in range(0,len(tag_tokens)): if template_possibilities[0][ii] in [tag_tokens[ii],'$']: to_return[ii] = tag_tokens[ii] elif template_possibilities[0][ii] in ['?','&']: to_return[ii] = template_possibilities[0][ii] else: print("Tag does not match its own template!! Tag: ",self._tag,"; Template: ",self._template._template_tag) self._pattern = ":".join(to_return) return self._pattern def aligns_with(self,other_tag): return self._template == other_tag._template and self.get_pattern() == other_tag.get_pattern() class BoundNode: def __init__(self,target_node,graphics_node,parent=None): self._parent = parent self._children = {} self._popped_children = {} self._additional = [] self._target_node = target_node self._graphics_node = graphics_node if parent != None: parent.add_child(self) #self._popped = False def add_child(self, child_node): self._children[child_node._target_node._tag]=child_node self._popped_children[child_node._target_node._tag]=False def create_child_nodes(self): # Children with pattern keys in both target & graphics for shared_key in self._target_node._pat_children.keys().intersection(self._graphics_node._pat_children.keys()): new_node = BoundNode(self._target_node._pat_children[shared_key],self._graphics_node._pat_children[shared_key],self) self.add_child(new_node) new_node.create_child_nodes() # Children with pattern keys in target but not in graphics can be ignored # Children with pattern keys in graphics but not in target for graphics_key in self._graphics_node._pat_children.keys() - self._target_node._pat_children.keys(): graphics_in_question = self._graphics_node._pat_children[graphics_key] if graphics_in_question.is_graphics_tag(): self._additional.append(graphics_in_question) # End def are_all_children_popped(self): to_return = True for child in self._popped_children.keys(): to_return &= self._popped_children.keys()[child] return to_return def get_merge(self): return self._target_node.apply_graphics(self._graphics_node) def pop_child(self, target_tag): if target_tag not in self._children.keys(): return self else: if self._popped_children[target_tag]: print("Popping tag that has already been popped: ",target_tag) self._popped_children[target_tag] = True return self._children[target_tag]