def rate_of_one_factory(self): """How many items can be produced per second, by one factory? Fraction or None. None is returned if (according to the XML) the item is "raw" and as such cannot be supplied by any factory. """ if self._produced is None: return None else: base_rate = (self._produced / _F(1, 1)) / (self._time / _F(1, 1)) return base_rate
def itemFromXML(item_idmap, itemel): if itemel.tag != 'item': raise ValueError(f"Got element '{itemel.tag}', expecting 'item'.") itemid = itemel.attrib['id'] if not _checkXMLHasNoText(itemel): raise ValueError(f"Invalid item {itemid}") if itemid in item_idmap: raise ValueError(f"Item {itemid} defined twice.") name = itemel.attrib.get('name', itemid) time = itemel.attrib.get('time', None) produced = itemel.attrib.get('produced', None) if (produced is None) != (time is None): raise ValueError(f"Invalid item '{itemid}'.") if time is not None: time = _F(time) produced = int(produced) ingredients = [] for ingredientel in itemel.getchildren(): if ingredientel.tag != 'ingredient': raise ValueError(f"Item {itemid} has {ingredientel.tag}") ingid = ingredientel.attrib['idref'] if not _checkXMLHasNoText(ingredientel): raise ValueError(f"Invalid ingredient '{ingid}' in '{itemid}'") ingcount = int(ingredientel.attrib['count']) if ingid not in item_idmap: raise ValueError(f"Item '{itemid}' mentions ingredient " f"'{ingid}' before it's defined.") ingredients.append((ingcount, item_idmap[ingid])) if (len(ingredients) > 0) and (time is None): raise ValueError(f"Item '{itemid}' has ingredients but " "no production time.") return (itemid, ItemType(name, time, tuple(ingredients), produced))
def _parse_section(section): try: try: num, name = section.split("*") except: num, name = section.strip().split(" ", 1) num = _F(num) name = name.strip() except: raise Exception("Expecting the format similar to: " "\"2*Inserter + 1/2 * Black Science\"") return num, _parse_item_type(name)
def ingredient_demand_of_one_factory(self): """What's the demand on ingredients needed to keep one factory running? Either list of ItemTypeDemand objects, or None. None is returned if (according to the XML) the item is "raw" and as such cannot be supplied by any factory. """ if self._produced is None: return None result = [] for count, ingr_type in self._ingredients: result.append(ItemTypeDemand(ingr_type, _F(count, self._time))) return result
def production_rate(dest_item, rate, source_item, raw_materials=frozenset()): if dest_item is source_item: return rate if (dest_item._produced is None) or (dest_item in raw_materials): return 0 produced = dest_item._produced / _F(1, 1) scale = rate / produced # print(f"name, scale == {dest_item._name}, {scale}") total = 0 for sub_item_ct, sub_item in dest_item._ingredients: sub_rate = production_rate(sub_item, scale * sub_item_ct, source_item, raw_materials=raw_materials) total += sub_rate return total
def recursive_count(dest_item, rate, cur_source=None): if cur_source is None: cur_source = dest_item if cur_source in items_so_far: return items_so_far.add(cur_source) source_rate = production_rate(dest_item, rate, cur_source, raw_materials=raw_materials) if (cur_source._produced is None) or (cur_source in raw_materials): factory_list.append( FactoryInfo(None, None, source_rate, cur_source)) else: factories = cur_source.factories(source_rate) int_fact = factories // _F(1, 1) if (factories - int_fact) > 0: int_fact += 1 assert (int_fact >= factories) factory_list.append( FactoryInfo(int_fact, factories, source_rate, cur_source)) for _, next_source in cur_source._ingredients: recursive_count(dest_item, rate, next_source)
def __init__(self, item_type, requested_rate=_F(0, 1)): assert isinstance(item_type, ItemType) self.item_type = item_type assert isinstance(requested_rate, _F) self.requested_rate = requested_rate
def base_rate(self): if self._produced is None: return None else: base_rate = (self._produced / _F(1, 1)) / (self._time / _F(1, 1)) return base_rate
def produced_for_each(dest_item, factory_list): for int_fact, _, _, item in factory_list: if int_fact is not None: rate = (_F(int_fact, 1) * item._produced) / item._time cur_produced = how_many_produced(item, rate, dest_item) yield cur_produced
def how_many_produced(source_item, rate, dest_item): forward_rate = production_rate(dest_item, _F(1, 1), source_item) return rate / forward_rate