""" open/dulcinea/lib/material.py """ from dulcinea.category import Category from durus.persistent import PersistentObject from durus.persistent_dict import PersistentDict from durus.persistent_list import PersistentList from qp.lib.spec import boolean, sequence, instance, add_getters_and_setters from qp.lib.spec import spec, specify, require, string, Specified, mapping from qp.pub.common import get_publisher from qpy import xml, xml_quote from random import randrange def get_material_db(): return get_publisher().get_connection().get_root().get('material_db') class Material (Category): """ Represents a material and a category of materials. """ html_name_is = spec( (string, None), "The name to be used in html displays. " "This may include html tags for subscripts. " "Other materials may have the same html_name, " "but that is probably a bad idea.") html_color_is = spec( (string, None), "A string in the form #ffee99 that identifies " "a color that might be used in html concerning " "this Material. " "Other materials may have the same color.") deleted_is = spec( boolean, "Tells if this this material is deprecated.") children_is = sequence(instance('Material'), PersistentList) parents_is = sequence(instance('Material'), PersistentList) def __init__(self, name, html_name=None, html_color=None): Category.__init__(self) specify(self, name=name, html_color=html_color or random_light_color(), html_name=html_name or name, deleted=0) def __str__(self): if self.get_children(): return '%s (category)' % self.get_label() else: return self.get_label() def get_label(self): return self.label or self.name def format(self, html=False): if html: if self.html_name: return xml(self.html_name) else: return xml_quote(self.get_label()) else: return self.get_label() def is_deleted(self): return self.deleted def is_other(self): return self.name == "other" add_getters_and_setters(Material) def random_light_color(): red = 256 green = 256 blue = 256 maximum_light = (256*3-100) minimum_light = 300 while ((red+green+blue > maximum_light) or (red+green+blue < minimum_light)): red = randrange(16,256) green = randrange(16,256) blue = randrange(16,256) r = hex(red)[-2:] g = hex(green)[-2:] b = hex(blue)[-2:] return '#%s%s%s' % (r,g,b) def material_sort(materials): """(seq [Material]) -> [Material]""" def lower_case_label(material): return material.get_label().lower() return sorted(materials, key=lower_case_label) class MaterialDatabase (PersistentObject, Specified): materials_is = spec( mapping({string:Material}, PersistentDict), "all material objects keyed on name") def __init__(self): specify(self, materials=PersistentDict()) def __getitem__(self, material_name): return self.materials[material_name] def add_material(self, material): require(material, Material) if self.materials.has_key(material.get_name()): raise ValueError( "material named '%s' already exists" % material.get_name()) self.materials[material.get_name()] = material def get_material(self, material_name): return self.materials.get(material_name) def get_materials(self): return list(self.materials.values())