# THIS FILE IS A PART OF VCStudio # PYTHON 3 import os def get_list(filepath): # This fucntion converts text documents. (.progress) into a more machine # friendly recursive dict. # In the original organizer evaluation of the checklist was done separatelly # in a different function. Which made it very messy for recursive stuff. # I will attemp to combine it. And make it more clean as a result. checklist = { "fraction":0.0, # The percentage of a checklist. From 0.0 to 1.0 "string":filepath, "editing":False,# Whethere the string is during editing. UI. "open":True, # Whether to draw the suptasks. UI. "subtasks":[] # List of subtastks. (In the same format as the checklist) } data = open(filepath) data = data.read() data = data.split("\n") # Let's filter out all the comments. Lines starting with #. For some reason # in the old organizer. I just thought it wasn't important. LOL. And just # started reading from the 10th line. # Here is an example of the first 9 lines. # 1 #### Blender orgainizer checklist format # 2 #### INDINTATION (4 SPACES LONG) # 3 #### STR means Start date of the ASSET # 4 #### FIN means Finish deadline of the asset # 5 #### [ ] means that task is on list # 6 #### [V] means that tast is finished # 7 #### DO NOT USE EMPTY LINES # 8 STR 24/02/2020 # 9 FIN 01/05/2021 # You can see a trace from a very long time ago. From the first versions # of the blender organizer. The STR and FIN values. Which are start and # deadline of the project. # I guess we need to filter it out a bit differently. Checking whether a # given line starts with a [ or with a number of spaces and [. This will # make the file a little more open to editing by hand. Without too much # worrying that something will break. cleandata = [] for line in data: # So not to mangle the line. tmp = line while tmp.startswith(" "): tmp = tmp[1:] # Checking if tmp.startswith("[ ]") or tmp.startswith("[V]"): cleandata.append(line) # Now since we have the cleandata. We can try to parse it somehow into a # checklist thing. For this we need a reqursion. I gonna use a method from # the blender-organizer. By running the function with in itself. It's not # very wise. I know. In python3 it will give you no more then 996 recursions # untill it will declare an error. BUT. It's 996 layers of a subtaks. # For now I don't see a need in so many subtasks. Let's think of layers of # subtasks as of memory. This laptop has only 8 GB of RAM. I can't put more # data into it even if I wanted. def convert(part, indent=0): # If a thing have subtasks it should not even be a checkbox. So trying # To evaluate it's fraction by whether it's a [ ] or [V] shoun't be # done. subtask = [] for num, line in enumerate(part): # Let's get the NEXT line. I'm not kidding. We gonna work with the # next line to see whether to count this lines [V] if line[indent:].startswith("["): thisline = { "fraction":0.0, "string":line[line.find("]")+2:], "editing":False, "open":False, "subtasks":[] } try: nextline = part[num+1] except: nextline = "" if not line[line.find("]")+1] == ".": thisline["open"] = True if nextline.find("[")-1 <= indent: if line[indent:].startswith("[V]"): thisline["fraction"] = 1.0 else: subpart = [] subdent = indent for n, l in enumerate(part[num+1:]): if n == 0: subdent = l.find("[") if l.find("[")-1 <= indent: break else: subpart.append(l) #print(subpart) thisline["subtasks"] = convert(subpart, subdent) fracs = [] for task in thisline["subtasks"]: if not task["string"].startswith("#"): fracs.append(task["fraction"]) try: thisline["fraction"] = sum(fracs) / len(fracs) except: thisline["fraction"] = 0.0 # Sometime it was showing 99% when infect it's 100% if thisline["fraction"] == 0.9999: thisline["fraction"] = 1.0 subtask.append(thisline) return subtask checklist["subtasks"] = convert(cleandata) fracs = [] for task in checklist["subtasks"]: if not task["string"].startswith("#"): fracs.append(task["fraction"]) try: checklist["fraction"] = sum(fracs) / len(fracs) except: checklist["fraction"] = 0.0 # Sometime it was showing 99% when infect it's 100% if checklist["fraction"] == 0.9999: checklist["fraction"] = 1.0 return checklist def get_fraction(win, path): ############################################################################ # This function will return a fraction of a given checklist. It will ignore # complitelly what is the asset / shot / project the checklist is from. # For sake of making this function actually somewhat useful, aka not bloated # I will use it to cashe the whole checklist data objects. So they could be # easily accesable later on. # This is usefull so I would not need to create 2 cash data structures. One # for fractions and for the checklists them selves. ############################################################################ if path not in win.checklists: # Let's check if path exists in the project first. if os.path.exists(win.project+"/"+path): win.checklists[path] = get_list(win.project+"/"+path) else: win.checklists[path] = get_list(path) # Let's now return back the fraction return win.checklists[path]["fraction"]