From dec2618aeda1c0d059e1cfccc92cb1334b6819a2 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 21 Mar 2024 15:20:24 -0700 Subject: [PATCH 1/4] Support for custom plant agents/currencies / appLogger debugging --- simoc_server/front_end_routes.py | 45 +++++++++++++++++++++++++------- simoc_server/views.py | 4 +++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/simoc_server/front_end_routes.py b/simoc_server/front_end_routes.py index 3cd30ed8..fd138f97 100644 --- a/simoc_server/front_end_routes.py +++ b/simoc_server/front_end_routes.py @@ -189,6 +189,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): """ full_game_config = { # The object to be returned by this function. 'agents': {}, + 'currencies': {}, 'termination': [], } # Create a working_config which will be modified by this function, so as @@ -196,6 +197,8 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): working_config = copy.deepcopy(game_config) agent_desc = load_data_file('agent_desc.json') currency_dict = get_default_currency_data() + # working_config['food_storage']['capacity']={} + #working_config['food_storage']['capacity']['rice_7']=10000 is_b2 = False ########################################################################### @@ -287,25 +290,32 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): # Plants: A list of objects with 'species' and 'amount' plants_in_config = [] - input_food_storage = working_config.pop('food_storage', None) + input_food_storage = working_config.pop('food_storage', None) #### FOOD STORAGE GRABBED #### crop_mgmt_input = working_config.pop('improvedCropManagement', False) crop_mgmt_factor = 1.5 if crop_mgmt_input is True else 1 if 'plants' in working_config and isinstance(working_config['plants'], list): plants = working_config.pop('plants') + app.logger.info(f'ZZZZZZZZZZZZZZZZZ PLANTS ZZZZZZZZZZZZZZZZZ {plants} ' ) for plant in plants: amount = plant.get('amount', 0) or 0 - plant_type = plant.get('species', None) + plant_type = plant.pop('species') # plant.get('species', None) # plant.pop('species') if not (plant_type and amount): continue plants_in_config.append(plant_type) - working_config[plant_type] = dict(amount=amount) + plant['amount']=amount + if plant_type not in working_config: # Could be in the working config already as a custom agent + working_config[plant_type]=plant + else: + working_config[plant_type]['amount']=amount + if is_b2: working_config[plant_type]['properties'] = { 'crop_management_factor': {'value': crop_mgmt_factor}, 'density_factor': {'value': 0.5} } + app.logger.info(f'BBBBBBBBBBBBBB WORKING CONFIG BBBBBBBBBBBBBBBB {working_config} ' ) if plants_in_config: - working_config['food_storage'] = dict(amount=1) + working_config['food_storage'] = dict(amount=1)# FOOD STORAGE CLEARED!?!?! # Lights if is_b2: working_config['b2_sun'] = {'amount': 1} @@ -317,10 +327,15 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): # Add custom lamp for plant lamp_id = f'{species}_lamp' working_config[lamp_id] = {'amount': 1, 'prototypes': ['lamp'], - 'flows': {'out': {'par': {'connections': [lamp_id]}}}} + 'flows': {'out': {'par': {'connections': [lamp_id]}}}} # species to lamp_id? Nope, that crashes it. ERROR: 'rice' does not store par # Add connection to plant 'par' flow - par_flow_stub = {'in': {'par': {'connections': [lamp_id]}}} - working_config[species]['flows'] = par_flow_stub + par_flow_stub = {'in': {'par': {'connections': [lamp_id]}}} + app.logger.info(f'5555555555555555555555555 WORKING CONFIG SPECIES 5555555555555555555555555 {working_config[species]} ' ) + if 'flows' in working_config[species]: + working_config[species]['flows']['in']['par']['connections'].clear() # Remove excess lamps + working_config[species]['flows']['in']['par']['connections'].append(lamp_id) # Add specific lamp + else: + working_config[species]['flows']=par_flow_stub # Everything else (amt, rate, schedule) managed by LampAgent # Default Storages: Some listed, some not. Need to calculate amount. # 'food_storage' now holds fresh food, and 'ration_storage' holds the rations. Rations are @@ -357,7 +372,9 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): capacity = agent_desc[storage_type]['capacity'][field] amount = max(amount, math.ceil(value / capacity)) storage_agent['amount'] = amount - working_config[storage_type] = storage_agent + working_config[storage_type] = storage_agent + working_config['food_storage']['capacity']={}; + working_config['food_storage']['capacity']['rice_7']=10000; ## HARD CODED if 'human_agent' in working_config: human = working_config.pop('human_agent') working_config['human'] = human @@ -446,10 +463,20 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): ########################################################################### # STEP 3: Add all agents to output # ########################################################################### + custom_currencies = {} + # Save the currencies + if 'currencies' in working_config: + custom_currencies = working_config.pop('currencies') for agent_id, agent in working_config.items(): full_game_config['agents'][agent_id] = agent - + + for currency_id, currency in custom_currencies.items(): + full_game_config['currencies'][currency_id] = currency + + #if(plant.custom_flag=true) + #full_game_config['currencies']= new currency for custom plant + # Print result if save_output: timestamp = datetime.datetime.now() diff --git a/simoc_server/views.py b/simoc_server/views.py index c72532b4..41af8f2e 100644 --- a/simoc_server/views.py +++ b/simoc_server/views.py @@ -281,13 +281,17 @@ def new_game(): raise BadRequest("step_num is required.") step_num = int(input["step_num"]) try: + app.logger.info(f'XXXXXXXXXX PRE GAME CONFIG XXXXXXXXXXXXXX {input["game_config"]} ' ) game_config = convert_configuration(input["game_config"]) + app.logger.info(f'BBBBBBBBBBBBB POST GAME CONFIG BBBBBBBBBBBBB {game_config} ' ) except BadRequest as e: raise BadRequest(f"Cannot retrieve game config. Reason: {e}") if step_num >= MAX_STEP_NUMBER: raise BadRequest("Too many steps requested.") user = get_standard_user_obj() user_cleanup(user) + + tasks.new_game.apply_async(args=[user.username, game_config, step_num]) while True: time.sleep(0.5) From 980264742d21378d25023476090f75b42e40a748 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 26 Mar 2024 18:35:36 -0700 Subject: [PATCH 2/4] Removed hardcoding for food storages --- simoc_server/front_end_routes.py | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/simoc_server/front_end_routes.py b/simoc_server/front_end_routes.py index fd138f97..3a659d49 100644 --- a/simoc_server/front_end_routes.py +++ b/simoc_server/front_end_routes.py @@ -315,7 +315,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): } app.logger.info(f'BBBBBBBBBBBBBB WORKING CONFIG BBBBBBBBBBBBBBBB {working_config} ' ) if plants_in_config: - working_config['food_storage'] = dict(amount=1)# FOOD STORAGE CLEARED!?!?! + working_config['food_storage'] = dict(amount=1) # Lights if is_b2: working_config['b2_sun'] = {'amount': 1} @@ -373,8 +373,24 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): amount = max(amount, math.ceil(value / capacity)) storage_agent['amount'] = amount working_config[storage_type] = storage_agent - working_config['food_storage']['capacity']={}; - working_config['food_storage']['capacity']['rice_7']=10000; ## HARD CODED + + # For any custom food currencies, it is necessary that food storage be created for them + # Because food storage is set to a new object above (and combined later with food storage in simoc-abm's + # default JSON file), a capacity is defined subobject is defined here. + custom_currencies = {} + if 'currencies' in working_config: + custom_currencies = working_config.pop('currencies') # These are later added to config in format expected by simoc-abm + working_config['food_storage']['capacity']={}; + # Check if each custom currency is a food, and if it is, add a food storage capacity for this food. + for currency_name, currency_parameters in custom_currencies.items(): + if 'category' in currency_parameters: + if currency_parameters['category'] == 'food': + # working_config['food_storage']['capacity']['rice_7']=10000; ## HARD CODED + working_config['food_storage']['capacity'][currency_name]=10000 + # Next, iterate through the custom agents and see if they are a food type agent. + # If they are, set the capacity to 10,000 which is the default hardcoded amount in the simoc-abm JSON for a food item + + if 'human_agent' in working_config: human = working_config.pop('human_agent') working_config['human'] = human @@ -463,10 +479,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): ########################################################################### # STEP 3: Add all agents to output # ########################################################################### - custom_currencies = {} - # Save the currencies - if 'currencies' in working_config: - custom_currencies = working_config.pop('currencies') + for agent_id, agent in working_config.items(): full_game_config['agents'][agent_id] = agent From 92daf9574067c5d89c7b707ef2bfd0683ad9c1ca Mon Sep 17 00:00:00 2001 From: GregRRoss Date: Sat, 11 May 2024 12:33:11 -0700 Subject: [PATCH 3/4] Improve comments --- simoc_server/front_end_routes.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/simoc_server/front_end_routes.py b/simoc_server/front_end_routes.py index 3a659d49..f7e701ba 100644 --- a/simoc_server/front_end_routes.py +++ b/simoc_server/front_end_routes.py @@ -197,8 +197,6 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): working_config = copy.deepcopy(game_config) agent_desc = load_data_file('agent_desc.json') currency_dict = get_default_currency_data() - # working_config['food_storage']['capacity']={} - #working_config['food_storage']['capacity']['rice_7']=10000 is_b2 = False ########################################################################### @@ -298,7 +296,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): app.logger.info(f'ZZZZZZZZZZZZZZZZZ PLANTS ZZZZZZZZZZZZZZZZZ {plants} ' ) for plant in plants: amount = plant.get('amount', 0) or 0 - plant_type = plant.pop('species') # plant.get('species', None) # plant.pop('species') + plant_type = plant.pop('species') if not (plant_type and amount): continue plants_in_config.append(plant_type) @@ -327,7 +325,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): # Add custom lamp for plant lamp_id = f'{species}_lamp' working_config[lamp_id] = {'amount': 1, 'prototypes': ['lamp'], - 'flows': {'out': {'par': {'connections': [lamp_id]}}}} # species to lamp_id? Nope, that crashes it. ERROR: 'rice' does not store par + 'flows': {'out': {'par': {'connections': [lamp_id]}}}} # Add connection to plant 'par' flow par_flow_stub = {'in': {'par': {'connections': [lamp_id]}}} app.logger.info(f'5555555555555555555555555 WORKING CONFIG SPECIES 5555555555555555555555555 {working_config[species]} ' ) @@ -340,7 +338,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): # Default Storages: Some listed, some not. Need to calculate amount. # 'food_storage' now holds fresh food, and 'ration_storage' holds the rations. Rations are # still pre-loaded to 'food_storage' on the front-end though, so need to change the label. - if input_food_storage and input_food_storage.get('ration') is not None: # b2: initialize with food (plants) instead of rations + if input_food_storage and input_food_storage.get('ration') is not None: # b2: initialize with food (plants) instead of rations if is_b2: starting_food = input_food_storage['ration'] greenhouse_layout = {p: working_config[p]['amount'] for p in plants_in_config} @@ -486,9 +484,10 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): for currency_id, currency in custom_currencies.items(): full_game_config['currencies'][currency_id] = currency - - #if(plant.custom_flag=true) - #full_game_config['currencies']= new currency for custom plant + + # Might need something like this to eliminate excess currency bug: + #if(plant.custom_flag=true) + #full_game_config['currencies']= new currency for custom plant # Print result if save_output: From 7557731237283ce1a193eedc26acadd62ce1e46e Mon Sep 17 00:00:00 2001 From: GregRRoss Date: Sun, 9 Jun 2024 17:54:12 -0700 Subject: [PATCH 4/4] Eliminate unused custom plants from simulation config --- simoc_server/front_end_routes.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/simoc_server/front_end_routes.py b/simoc_server/front_end_routes.py index f7e701ba..a31a7ab3 100644 --- a/simoc_server/front_end_routes.py +++ b/simoc_server/front_end_routes.py @@ -291,6 +291,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): input_food_storage = working_config.pop('food_storage', None) #### FOOD STORAGE GRABBED #### crop_mgmt_input = working_config.pop('improvedCropManagement', False) crop_mgmt_factor = 1.5 if crop_mgmt_input is True else 1 + if 'plants' in working_config and isinstance(working_config['plants'], list): plants = working_config.pop('plants') app.logger.info(f'ZZZZZZZZZZZZZZZZZ PLANTS ZZZZZZZZZZZZZZZZZ {plants} ' ) @@ -305,13 +306,23 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): working_config[plant_type]=plant else: working_config[plant_type]['amount']=amount - if is_b2: working_config[plant_type]['properties'] = { 'crop_management_factor': {'value': crop_mgmt_factor}, 'density_factor': {'value': 0.5} } app.logger.info(f'BBBBBBBBBBBBBB WORKING CONFIG BBBBBBBBBBBBBBBB {working_config} ' ) + # 'plants' in working_config correspond to the ones selected by the user in the wizard, + # but does not include custom plant agents that were not selected in wizard but may have + # been sent over as an agent, which need to be removed before simulation start. + unused_custom_plants = [] + for agent_key, config_agent in working_config.items(): + if 'agent_class' in config_agent and config_agent['agent_class']=='plants': + if agent_key not in plants_in_config: + unused_custom_plants.append(agent_key) + for deletable_plant in unused_custom_plants: + working_config.pop(deletable_plant) + # For the plants that are actually in the simulation, add lamps if plants_in_config: working_config['food_storage'] = dict(amount=1) # Lights @@ -327,8 +338,7 @@ def convert_configuration(game_config, agent_desc=None, save_output=False): working_config[lamp_id] = {'amount': 1, 'prototypes': ['lamp'], 'flows': {'out': {'par': {'connections': [lamp_id]}}}} # Add connection to plant 'par' flow - par_flow_stub = {'in': {'par': {'connections': [lamp_id]}}} - app.logger.info(f'5555555555555555555555555 WORKING CONFIG SPECIES 5555555555555555555555555 {working_config[species]} ' ) + par_flow_stub = {'in': {'par': {'connections': [lamp_id]}}} if 'flows' in working_config[species]: working_config[species]['flows']['in']['par']['connections'].clear() # Remove excess lamps working_config[species]['flows']['in']['par']['connections'].append(lamp_id) # Add specific lamp