testing
This commit is contained in:
131
main.py
131
main.py
@@ -5,10 +5,13 @@ from typing import Dict, List, Tuple, Optional, Any
|
||||
import networkx as nx
|
||||
from flask import Flask, render_template, request
|
||||
from pydantic import BaseModel, Field
|
||||
from plus import Items, Machines, Recipes, Recipe
|
||||
# from plus import Items, Machines, Recipes, Recipe
|
||||
from vanilla import Items, Machines, Recipes, Recipe, RawResources
|
||||
from rich import print
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
|
||||
# Helpers to map item names to safe query parameter keys
|
||||
def _slugify(name: str) -> str:
|
||||
s = ''.join(ch.lower() if ch.isalnum() else '_' for ch in name)
|
||||
@@ -29,53 +32,88 @@ class Production(BaseModel):
|
||||
recipe: Recipe
|
||||
quantity: float
|
||||
|
||||
class ProductionChain:
|
||||
def __init__(self):
|
||||
self.recipe_map: Dict[Items, list[Recipes]] = defaultdict(list)
|
||||
for r in Recipes:
|
||||
for o in r.value.outputs:
|
||||
self.recipe_map[o].append(r.value)
|
||||
|
||||
def get_recipe(item: Items, recipe_map: Dict[Items, list[Recipes]]) -> Optional[Recipe]:
|
||||
return recipe_map.get(item, (None,))[0]
|
||||
def get_recipe(self, item: Items, recipe_map: Dict[Items, list[Recipes]]) -> Optional[Recipe]:
|
||||
# TODO: make logic for priority selection of recipes
|
||||
return recipe_map.get(item, (None,))[0]
|
||||
|
||||
def compute_chain2(targets: Dict[Items, float]) -> Any:
|
||||
if not targets:
|
||||
return {}
|
||||
recipe_map: Dict[Items, list[Recipes]] = defaultdict(list)
|
||||
for r in Recipes:
|
||||
for o in r.value.outputs:
|
||||
recipe_map[o].append(r.value)
|
||||
# print(recipe_map)
|
||||
demand = defaultdict(float)
|
||||
for target in targets:
|
||||
demand[target] = targets[target]
|
||||
production = defaultdict(float)
|
||||
# add demands to production
|
||||
# find a recipe for that demand
|
||||
# add inputs to demand
|
||||
queue = deque(targets)
|
||||
g = nx.DiGraph()
|
||||
production_queue = []
|
||||
raw_resources = defaultdict(float)
|
||||
production_chain = defaultdict(float)
|
||||
while queue:
|
||||
item = queue.popleft()
|
||||
recipe = get_recipe(item, recipe_map)
|
||||
if recipe is None:
|
||||
raw_resources[item] += demand[item] - raw_resources[item]
|
||||
continue
|
||||
levels = []
|
||||
for out, quantity in recipe.outputs.items():
|
||||
if out in demand:
|
||||
target_quantity = demand[out] - production[out]
|
||||
if target_quantity > 0:
|
||||
levels.append(target_quantity / quantity)
|
||||
def calculate_excess(self, production: Dict[Items, float], demand: Dict[Items, float], raw_resources: Dict[Items, float]):
|
||||
excess = defaultdict(float)
|
||||
for item, quantity in demand.items():
|
||||
total = production[item] - demand[item]
|
||||
if total != 0:
|
||||
if item in RawResources:
|
||||
raw_resources[item] -= production[item]
|
||||
else:
|
||||
levels.append(0)
|
||||
production_level = max(levels) if max(levels) > 0 else 0
|
||||
production_chain[recipe.name] = production_level
|
||||
for out, quantity in recipe.outputs.items():
|
||||
production[out] += production_level * quantity
|
||||
for inp, quantity in recipe.inputs.items():
|
||||
queue.append(inp)
|
||||
demand[inp] += production_level * quantity
|
||||
print(demand, production, raw_resources, production_chain)
|
||||
return production
|
||||
excess[item] = total
|
||||
return excess
|
||||
|
||||
def calculate_byproduct(self, production: Dict[Items, float], demand: Dict[Items, float], raw_resources: Dict[Items, float]):
|
||||
byproduct = defaultdict(float)
|
||||
for item, quantity in production.items():
|
||||
if item not in demand:
|
||||
byproduct[item] = quantity
|
||||
return byproduct
|
||||
|
||||
def compute_chain(self, targets: Dict[Items, float]) -> Any:
|
||||
if not targets:
|
||||
return {}
|
||||
demand = defaultdict(float)
|
||||
for target in targets:
|
||||
demand[target] = targets[target]
|
||||
|
||||
queue = deque(targets)
|
||||
production = defaultdict(float)
|
||||
raw_resources = defaultdict(float)
|
||||
production_chain = defaultdict(float)
|
||||
while queue:
|
||||
item = queue.popleft()
|
||||
if item == Items.Silica:
|
||||
print("silica")
|
||||
recipe = self.get_recipe(item, self.recipe_map)
|
||||
if item in RawResources:
|
||||
raw_resources[item] += demand[item] - raw_resources[item]
|
||||
continue
|
||||
if item in production:
|
||||
if production[item] == demand[item]:
|
||||
continue
|
||||
|
||||
levels = []
|
||||
for out, quantity in recipe.outputs.items():
|
||||
if out in demand:
|
||||
target_quantity = demand[out] - production[out]
|
||||
levels.append(target_quantity / quantity)
|
||||
|
||||
production_level = max(levels)
|
||||
production_chain[recipe.name] += production_level
|
||||
for out, quantity in recipe.outputs.items():
|
||||
production[out] += production_level * quantity
|
||||
for byproduct, quantity in recipe.byproducts.items():
|
||||
production[byproduct] += production_level * quantity
|
||||
queue.append(byproduct)
|
||||
for inp, quantity in recipe.inputs.items():
|
||||
queue.append(inp)
|
||||
demand[inp] += production_level * quantity
|
||||
|
||||
excess = self.calculate_excess(production, demand, raw_resources)
|
||||
byproduct =self.calculate_byproduct(production, demand, raw_resources)
|
||||
|
||||
|
||||
print("demand:", demand)
|
||||
print("production:", production)
|
||||
print("excess:", excess)
|
||||
print("byproduct:", byproduct)
|
||||
print("raw resources:", raw_resources)
|
||||
print("production chain:", production_chain)
|
||||
|
||||
|
||||
return production_chain
|
||||
|
||||
|
||||
def compute_chain(targets: Dict[Items, float], preferred_by_output: Optional[Dict[Items, str]] = None) -> Tuple[Dict[str, float], List[dict], Dict[str, float], Dict[str, float]]:
|
||||
@@ -388,4 +426,5 @@ def create_app():
|
||||
if __name__ == "__main__":
|
||||
# For local dev: python main.py
|
||||
# app.run(host="0.0.0.0", port=5000, debug=True)
|
||||
compute_chain2({Items.ModularFrame: 45.0})
|
||||
prod_chain = ProductionChain()
|
||||
prod_chain.compute_chain({Items.FusedModularFrame: 1.5})
|
||||
Reference in New Issue
Block a user