import random from .commoditys import commoditys as cm from .exchange import Exchange from .business import Price_Believe_Business import uuid class Simulation(): """ Class for controlling the different calculation steps of the Simulation. """ def __init__(self) -> None: self.tick_funcs={} self.reset_funcs={} self.tick_count=0 self.episode_count=0 self.cells={} self.businesses=[] self.production_util={} for k in cm.productions.items(): l=k[1] for i in l: self.production_util[i["id"]]=0 self.cx=Exchange() pass def set_cells(self,cells): for c in cells: self.cells[c.name]=c def set_businesses(self,bus): self.businesses=bus def seed(self,a): """ Sets the random seed """ random.seed(a) def register_agent(self,id,tickfunc,resetfunc): self.tick_funcs[id]=tickfunc self.reset_funcs[id]=resetfunc def tick_agents_random_order(self): """ Ticks all agents in a Random Order """ keys=list(self.tick_funcs.keys()) random.shuffle(keys) for k in keys: fun=self.tick_funcs[k] fun(self.tick_count,self.episode_count) def tick(self,episode_length): """ Executes a tick of the simulation """ self.tick_agents_random_order() for cell_id,c in self.cells.items(): c.setup_demand_for_step(episode_length) for b in self.businesses: b.tick(self.tick_count) self.tick_count+=1 def reset(self): """ Resets all agents to new Episode """ for k,v in self.reset_funcs.items(): v(self.episode_count) for cell_id,cell in self.cells.items(): cell.setup_supply_for_episode() self.tick_count=0 self.episode_count+=1 def get_underutelized_prods(self,threshold): """ Returns all productions that fall under the given threshold """ under=[] for k,v in self.production_util.items(): if v0: # we need to create more businesses selected_prod=random.choice(under_prods) else: selected_prod=self.get_max_profit_prod() prod=cm.productions_id_map[selected_prod] # Now select cell to place business cells=self.select_business_cell(prod) cell_id=random.choice(cells) cell=self.cells[cell_id] cxs=[cell.exchange,self.cx] business=Price_Believe_Business.Price_Believe_Business(uuid.uuid4(),prod,1000,cxs,self) self.businesses.append(business) self.production_util[selected_prod]+=1 return business def get_max_profit_prod(self): """ Returns the prod with the highest profit in last episode """ profit=self.businesses[0].balance-self.businesses[0].balance_history[-1] prod=self.businesses[0].production for b in self.businesses: diff=b.balance-b.balance_history[-1] if diff>profit: profit=diff prod=b.production return prod def select_business_cell(self,prod): """ Calculate score for placement. Return cell with best score. """ cell_score={self.cells[k].name: 0 for k in self.cells} for id,cell in self.cells.items(): cx=cell.exchange # Best prod resource availability # Using the exchange in that cell, lookup supply or demand of resources. Supply +1 / Demand -1 for prod_item in prod["prod"]: key=list(prod_item.keys())[0] val=prod_item[key] a=cx.get_total_supply(key) cell_score[cell.name]+=(cx.get_total_supply(key)/val) cell_score[cell.name]-=(cx.get_total_demand(key)/val) # If demand for prod item in cell then score +1/ score -1 if supply is already there a=cx.get_total_demand(prod["name"]) cell_score[cell.name]+=cx.get_total_demand(prod["name"]) cell_score[cell.name]-=cx.get_total_supply(prod["name"]) max_keys = [key for key, value in cell_score.items() if value == max(cell_score.values())] return max_keys