def gen_bom(m): md = '## Bill of Materials\n\n' md += 'Make sure you have all of the following parts before you begin.\n\n' # vitamins if len(m['vitamins']) > 0: m['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in m['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # printed parts if len(m['printed']) > 0: m['printed'].sort(key=printed_call, reverse=False) md += '### Printed Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['printed']: md += str(v['qty']) + ' | ' md += '['+v['title']+'](../printedparts/stl/'+ openscad.stl_filename(v['title']) +') | ' md += '![](../printedparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' md += '\n' return md
def gen_cut(m, a): md = '## '+a['title'] if a['qty'] > 1: md += ' (x'+str(a['qty'])+')' md += '\n\n' # vitamins if len(a['vitamins']) > 0: a['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in a['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # fabrication steps if len(a['steps']) > 0: md += '### Fabrication Steps\n\n' for step in a['steps']: md += str(step['num']) + '. '+step['desc'] + '\n' for view in step['views']: md += '![](../cutparts/images/'+views.view_filename(a['title']+'_step'+str(step['num'])+'_'+view['title'])+')\n' md += '\n' md += '\n' return md
def gen_cut(m, a): md = '## '+a['title'] if a['qty'] > 1: md += ' (x'+str(a['qty'])+')' md += '\n\n' # vitamins if len(a['vitamins']) > 0: a['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in a['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # fabrication steps if len(a['steps']) > 0: md += '### Fabrication Steps\n\n' for step in a['steps']: md += str(step['num']) + '. '+step['desc'] + '\n' for view in step['views']: md += '![](../cutparts/images/'+views.view_filename(a['title']+'_step'+str(step['num'])+'_'+view['title'])+')\n' md += '\n' md += '\n' return md
def gen_bom(m): md = '## Bill of Materials\n\n' md += 'Make sure you have all of the following parts before you begin.\n\n' # vitamins if len(m['vitamins']) > 0: m['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in m['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # cut parts if len(m['cut']) > 0: m['cut'].sort(key=cut_call, reverse=False) md += '### Cut Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['cut']: md += str(v['qty']) + ' | ' md += v['title'] + ' | ' md += '![](../cutparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # printed parts if len(m['printed']) > 0: vol = 0 weight = 0 m['printed'].sort(key=printed_call, reverse=False) md += '### Printed Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['printed']: md += str(v['qty']) + ' | ' md += '['+v['title']+'](../printedparts/stl/'+ openscad.stl_filename(v['title']) +') | ' md += '![](../printedparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' if 'plasticWeight' in v: weight += v['qty'] * v['plasticWeight'] vol += v['qty'] * v['plasticVolume'] md += '\n\n' md += '**Plastic Required**\n\n' md += str(round(vol,1))+'cm3, '; md += str(round(weight,2))+'KG, '; md += ' approx: '+str(round(weight * 13,2))+' GBP\n\n'; md += '\n' return md
def gen_bom(m): md = '## Bill of Materials\n\n' md += 'Make sure you have all of the following parts before you begin.\n\n' # vitamins if len(m['vitamins']) > 0: m['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in m['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # cut parts if len(m['cut']) > 0: m['cut'].sort(key=cut_call, reverse=False) md += '### Cut Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['cut']: md += str(v['qty']) + ' | ' md += v['title'] + ' | ' md += '![](../cutparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # printed parts if len(m['printed']) > 0: vol = 0 weight = 0 m['printed'].sort(key=printed_call, reverse=False) md += '### Printed Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['printed']: md += str(v['qty']) + ' | ' md += '['+v['title']+'](../printedparts/stl/'+ openscad.stl_filename(v['title']) +') | ' md += '![](../printedparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' if 'plasticWeight' in v: weight += v['qty'] * v['plasticWeight'] vol += v['qty'] * v['plasticVolume'] md += '\n\n' md += '**Plastic Required**\n\n' md += str(round(vol,1))+'cm3, '; md += str(round(weight,2))+'KG, '; md += ' approx: '+str(round(weight * 13,2))+' GBP\n\n'; md += '\n' return md
def gen_assembly(m, a): if len(a['steps']) == 0: return "" md = '## '+a['title'] if a['qty'] > 1: md += ' (x'+str(a['qty'])+')' md += '\n\n' # vitamins if len(a['vitamins']) > 0: a['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in a['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # printed parts if len(a['printed']) > 0: a['printed'].sort(key=printed_call, reverse=False) md += '### Printed Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in a['printed']: md += str(v['qty']) + ' | ' md += '['+v['title']+'](../printedparts/stl/'+ openscad.stl_filename(v['title']) +') | ' md += '![](../printedparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # sub-assemblies if len(a['assemblies']) > 0: md += '### Sub-Assemblies\n\n' md += 'Qty | Name \n' md += '--- | --- \n' for v in a['assemblies']: md += str(v['qty']) + ' | ' md += v['title'] md += '\n' md += '\n' # assembly steps if len(a['steps']) > 0: md += '### Assembly Steps\n\n' for step in a['steps']: md += str(step['num']) + '. '+step['desc'] + '\n' for view in step['views']: md += '![](../assemblies/'+machine_dir(m['title'])+'/'+views.view_filename(a['title']+'_step'+str(step['num'])+'_'+view['title'])+')\n' md += '\n' md += '\n' return md
def gen_assembly(m, a): if len(a['steps']) == 0: return "" md = '## '+a['title'] if a['qty'] > 1: md += ' (x'+str(a['qty'])+')' md += '\n\n' # vitamins if len(a['vitamins']) > 0: a['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in a['vitamins']: md += str(v['qty']) + ' | ' md += '['+v['title']+']() | ' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # printed parts if len(a['printed']) > 0: a['printed'].sort(key=printed_call, reverse=False) md += '### Printed Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in a['printed']: md += str(v['qty']) + ' | ' md += '['+v['title']+'](../printedparts/stl/'+ openscad.stl_filename(v['title']) +') | ' md += '![](../printedparts/images/'+views.view_filename(v['title']+'_view') + ') | ' md += '\n' md += '\n' # sub-assemblies if len(a['assemblies']) > 0: md += '### Sub-Assemblies\n\n' md += 'Qty | Name \n' md += '--- | --- \n' for v in a['assemblies']: md += str(v['qty']) + ' | ' md += v['title'] md += '\n' md += '\n' # assembly steps if len(a['steps']) > 0: md += '### Assembly Steps\n\n' for step in a['steps']: md += str(step['num']) + '. '+step['desc'] + '\n' for view in step['views']: md += '![](../assemblies/'+machine_dir(m['title'])+'/'+views.view_filename(a['title']+'_step'+str(step['num'])+'_'+view['title'])+')\n' md += '\n' md += '\n' return md
def gen_bom(m): md = '## Bill of Materials\n\n' md += 'Make sure you have all of the following parts before you begin.\n\n' # vitamins if len(m['vitamins']) > 0: m['vitamins'].sort(key=vitamin_call, reverse=False) md += '### Vitamins\n\n' md += 'Qty | Vitamin | Image\n' md += '--- | --- | ---\n' for v in m['vitamins']: md += str(v['qty']) + ' | ' md += '[' + v['title'] + ']() | ' md += '![](../vitamins/images/' + views.view_filename( v['title'] + '_view') + ') | ' md += '\n' md += '\n' # cut parts if len(m['cut']) > 0: m['cut'].sort(key=cut_call, reverse=False) md += '### Cut Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['cut']: md += str(v['qty']) + ' | ' md += v['title'] + ' | ' md += '![](../cutparts/images/' + views.view_filename( v['title'] + '_view') + ') | ' md += '\n' md += '\n' # printed parts if len(m['printed']) > 0: m['printed'].sort(key=printed_call, reverse=False) md += '### Printed Parts\n\n' md += 'Qty | Part Name | Image\n' md += '--- | --- | ---\n' for v in m['printed']: md += str(v['qty']) + ' | ' md += '[' + v[ 'title'] + '](../printedparts/stl/' + openscad.stl_filename( v['title']) + ') | ' md += '![](../printedparts/images/' + views.view_filename( v['title'] + '_view') + ') | ' md += '\n' md += '\n' md += '\n' return md
def compile_vitamin(v, dom): temp_name = "temp.scad" # # Make the target directories # target_dir = "../vitamins/stl" if not os.path.isdir(target_dir): os.makedirs(target_dir) view_dir = "../vitamins/images" if not os.path.isdir(view_dir): os.makedirs(view_dir) # Compile print(" "+v['title']) fn = '../' + v['file'] if (os.path.isfile(fn)): print(" Checking csg hash") h = openscad.get_csg_hash(temp_name, v['call'], [fn]); os.remove(temp_name); hashchanged = ('hash' in v and h != v['hash']) or (not 'hash' in v) # update hash in json v['hash'] = h # STL print(" STL Parts") for part in v['children']: if type(part) is DictType and part['type'] == 'part': stlpath = target_dir + '/' + openscad.stl_filename(part['title']) if hashchanged or (not os.path.isfile(stlpath)): print(" Rendering STL...") openscad.render_stl(temp_name, stlpath, part['call'], [fn]) else: print(" STL up to date") # Views print(" Views") for view in v['children']: if type(view) is DictType and view['type'] == 'view': print(" "+view['title']) render_view(v['title'], v['call'], view_dir, view, hashchanged, h, [fn], False) png_name = view_dir + '/' + view_filename(v['title'] + '_' + view['title']) view['png_name'] = png_name node = add_vitamin(v, dom) else: print(" Error: scad file not found: "+v['file'])
def compile_vitamin(v, dom): temp_name = "temp.scad" # # Make the target directories # target_dir = "../vitamins/stl" if not os.path.isdir(target_dir): os.makedirs(target_dir) view_dir = "../vitamins/images" if not os.path.isdir(view_dir): os.makedirs(view_dir) # Compile print(" " + v['title']) fn = '../' + v['file'] if (os.path.isfile(fn)): print(" Checking csg hash") h = openscad.get_csg_hash(temp_name, v['call'], [fn]) os.remove(temp_name) hashchanged = ('hash' in v and h != v['hash']) or (not 'hash' in v) # update hash in json v['hash'] = h # STL print(" STL Parts") for part in v['children']: if type(part) is DictType and part['type'] == 'part': stlpath = target_dir + '/' + openscad.stl_filename( part['title']) if hashchanged or (not os.path.isfile(stlpath)): print(" Rendering STL...") openscad.render_stl(temp_name, stlpath, part['call'], [fn]) else: print(" STL up to date") # Views print(" Views") for view in v['children']: if type(view) is DictType and view['type'] == 'view': print(" " + view['title']) render_view(v['title'], v['call'], view_dir, view, hashchanged, h, [fn], False) png_name = view_dir + '/' + view_filename(v['title'] + '_' + view['title']) view['png_name'] = png_name node = add_vitamin(v, dom) else: print(" Error: scad file not found: " + v['file'])
def gen_index(jso, index_file, index_template): # Generate index file # build object indexObj = { 'machines': [] }; for m in jso: if type(m) is DictType and m['type'] == 'machine': # tack in a view filename m['viewFilename'] = views.view_filename(m['title'] + '_view') indexObj['machines'].append(m) print("Saving index") with open(index_file,'w') as o: with open(index_template,'r') as i: o.write(pystache.render(i.read(), indexObj))
def compile_vitamin(v, dom): # # Make the target directories # if not os.path.isdir(config.paths['vitaminsimages']): os.makedirs(config.paths['vitaminsimages']) # Compile print(" " + v['title']) fn = '../' + v['file'] if (os.path.isfile(fn)): print(" Checking csg hash") h = openscad.get_csg_hash(config.paths['tempscad'], v['call'], [fn]) os.remove(config.paths['tempscad']) hashchanged = ('hash' in v and h != v['hash']) or (not 'hash' in v) # update hash in json v['hash'] = h # Views print(" Views") for view in v['children']: if isinstance(view, dict) and view['type'] == 'view': print(" " + view['title']) render_view(v['title'], v['call'], config.paths['vitaminsimages'], view, hashchanged, h, [fn], False, useVitaminSTL=False) png_name = os.path.join( config.paths['vitaminsimages'], view_filename(v['title'] + '_' + view['title'])) view['png_name'] = png_name node = add_vitamin(v, dom) else: print(" Error: scad file not found: " + v['file'])
def gen_index(jso, index_file, index_template): # Generate index file # build object indexObj = { 'machines': [], 'project': '' } for m in jso: if isinstance(m, dict) and m['type'] == 'machine': # tack in a view filename m['viewFilename'] = views.view_filename(m['title'] + '_view') if indexObj['project'] == '': indexObj['project'] = m['title'] indexObj['machines'].append(m) print("Saving index") with open(index_file, 'w') as o: with open(index_template, 'r') as i: o.write(pystache.render(i.read(), indexObj))
def gen_sourcing_guide(m, target_dir, guide_template): print(m['title']) if len(m['vitamins']) == 0: return {}; md = '' md += '# '+m['title'] + '\n' md += '# Sourcing Guide\n\n' cost = 0 qty = 0 m['vitamins'].sort(key=vitamin_call, reverse=False) for v in m['vitamins']: vn = v['title'] md += '### '+str(v['qty']) + 'x ' + vn+'\n\n' qty += v['qty'] # table of sources and effective cost for qty required if vn in sourcing: md += 'Unit Cost | Source | Notes \n' md += '--- | --- | --- \n' # calc cheapest option and add to running total lc = 0 for src in sourcing[vn]: tc = float(src['Cost']) if tc < lc or lc == 0: lc = tc md += src['Cost'] + ' | ' link = src['Source'] if link[:7] == 'http://': md += '[link]('+link+') | ' else: md += link + ' | ' md += src['Notes'] + '\n' cost += lc * v['qty'] else: md += 'No sources found\n' md += '\n' md += '![](../vitamins/images/'+views.view_filename(v['title']+'_view') + ') \n' md += '\n' if 'markdown' in v and len(v['markdown']) > 0: md += '**Notes**\n\n' for note in v['markdown']: if 'markdown' in note: md += ' * ' + note['markdown'] + '\n' md += '\n\n' md += '\n' md += '\n\n' md += '## Summary\n\n' md += '### Total Costs\n\n' md += 'Metric | Value \n' md += '--- | --- \n' md += 'Total Vitamins | ' + str(qty) + '\n' md += 'Total Cost (cheapest) | '+str(round(cost,2))+' GBP\n' md += '\n\n' print(" Saving markdown") mdfilename = md_filename(m['title'] +'SourcingGuide') mdpath = target_dir + '/' +mdfilename with open(mdpath,'w') as f: f.write(md) print(" Generating htm") htmfilename = htm_filename(m['title'] +'SourcingGuide') htmpath = target_dir + '/' + htmfilename with open(htmpath, 'w') as f: for line in open(guide_template, "r").readlines(): line = line.replace("{{mdfilename}}", mdfilename) f.write(line) return {'title':m['title'] + ' Sourcing Guide', 'mdfilename':mdfilename, 'htmfilename':htmfilename}
def gen_printing_guide(m, target_dir, guide_template): print(m['title']) if len(m['printed']) == 0: return {}; md = '' md += '# '+m['title'] + '\n' md += '# Printing Guide\n\n' vol = 0 weight = 0 qty = 0 m['printed'].sort(key=printed_call, reverse=False) for v in m['printed']: md += '### '+v['title']+'\n\n' md += 'Metric | Value \n' md += '--- | --- \n' md += 'Quantity | ' + str(v['qty']) + '\n' qty += v['qty'] md += 'STL | ' + '['+v['title']+'](../printedparts/stl/'+ openscad.stl_filename(v['title']) +')\n' if 'plasticWeight' in v: w = v['qty'] * v['plasticWeight'] weight += w vol += v['qty'] * v['plasticVolume'] md += 'Plastic (Kg) | ' + str(round(w,2)) + '\n' md += 'Plastic (cm3) | ' + str(round(v['qty'] * v['plasticVolume'],1)) + '\n' md += 'Approx Plastic Cost | '+str(round(w * 15,2))+' GBP\n'; md += '\n' md += '![](../printedparts/images/'+views.view_filename(v['title']+'_view') + ')\n' md += '\n' if 'markdown' in v and len(v['markdown']) > 0: md += '**Notes**\n\n' for note in v['markdown']: if 'markdown' in note: md += ' * ' + note['markdown'] + '\n' md += '\n\n' md += '\n\n' md += '## Summary\n\n' md += '### Statistics\n\n' md += 'Metric | Value \n' md += '--- | --- \n' md += 'Total Parts | ' + str(qty) + '\n' md += 'Total Plastic (Kg) | ' +str(round(weight,2))+'KG\n' md += 'Total Plastic (cm3) | ' +str(round(vol,1))+'cm3\n' md += 'Approx Plastic Cost | '+str(round(weight * 15,2))+' GBP\n' md += '\n\n' print(" Saving markdown") mdfilename = md_filename(m['title'] +'PrintingGuide') mdpath = target_dir + '/' +mdfilename with open(mdpath,'w') as f: f.write(md) print(" Generating htm") htmfilename = htm_filename(m['title'] +'PrintingGuide') htmpath = target_dir + '/' + htmfilename with open(htmpath, 'w') as f: for line in open(guide_template, "r").readlines(): line = line.replace("{{mdfilename}}", mdfilename) f.write(line) return {'title':m['title'] + ' Printing Guide', 'mdfilename':mdfilename, 'htmfilename':htmfilename}