Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
# app.py
|
| 2 |
-
# @title Beer Game Final Version (v4.25 - Based on v4.21 Logic + UI Fixes
|
| 3 |
|
| 4 |
# -----------------------------------------------------------------------------
|
| 5 |
# 1. Import Libraries
|
|
@@ -191,22 +191,56 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
|
|
| 191 |
llm_personality, info_sharing = state['llm_personality'], state['info_sharing']
|
| 192 |
echelon_order = ["Retailer", "Wholesaler", "Distributor", "Factory"]
|
| 193 |
llm_raw_responses = {}
|
|
|
|
|
|
|
| 194 |
opening_inventories = {name: e['inventory'] for name, e in echelons.items()}
|
| 195 |
opening_backlogs = {name: e['backlog'] for name, e in echelons.items()}
|
|
|
|
|
|
|
| 196 |
arrived_this_week = {name: 0 for name in echelon_order}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
inventory_after_arrival = {}
|
| 198 |
factory_state = echelons["Factory"]
|
| 199 |
produced_units = 0
|
| 200 |
if state['factory_production_pipeline']:
|
| 201 |
produced_units = state['factory_production_pipeline'].popleft()
|
| 202 |
-
arrived_this_week["Factory"] = produced_units
|
| 203 |
inventory_after_arrival["Factory"] = factory_state['inventory'] + produced_units
|
|
|
|
| 204 |
for name in ["Retailer", "Wholesaler", "Distributor"]:
|
| 205 |
arrived_shipment = 0
|
| 206 |
if echelons[name]['incoming_shipments']:
|
| 207 |
arrived_shipment = echelons[name]['incoming_shipments'].popleft()
|
| 208 |
-
arrived_this_week[name] = arrived_shipment
|
| 209 |
inventory_after_arrival[name] = echelons[name]['inventory'] + arrived_shipment
|
|
|
|
|
|
|
| 210 |
total_backlog_before_shipping = {}
|
| 211 |
for name in echelon_order:
|
| 212 |
incoming_order_for_this_week = 0
|
|
@@ -240,6 +274,8 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
|
|
| 240 |
if units_shipped["Factory"] > 0: echelons['Distributor']['incoming_shipments'].append(units_shipped["Factory"])
|
| 241 |
if units_shipped['Distributor'] > 0: echelons['Wholesaler']['incoming_shipments'].append(units_shipped['Distributor'])
|
| 242 |
if units_shipped['Wholesaler'] > 0: echelons['Retailer']['incoming_shipments'].append(units_shipped['Wholesaler'])
|
|
|
|
|
|
|
| 243 |
log_entry = {'timestamp': datetime.utcnow().isoformat() + "Z", 'week': week, **state}
|
| 244 |
del log_entry['echelons'], log_entry['factory_production_pipeline'], log_entry['logs'], log_entry['last_week_orders']
|
| 245 |
if 'current_ai_suggestion' in log_entry: del log_entry['current_ai_suggestion']
|
|
@@ -247,10 +283,18 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
|
|
| 247 |
e = echelons[name]; e['weekly_cost'] = (e['inventory'] * HOLDING_COST) + (e['backlog'] * BACKLOG_COST); e['total_cost'] += e['weekly_cost']
|
| 248 |
for key in ['inventory', 'backlog', 'incoming_order', 'order_placed', 'shipment_sent', 'weekly_cost', 'total_cost']: log_entry[f'{name}.{key}'] = e[key]
|
| 249 |
log_entry[f'{name}.llm_raw_response'] = llm_raw_responses.get(name, "")
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 254 |
log_entry[f'{human_role}.initial_order'] = human_initial_order; log_entry[f'{human_role}.ai_suggestion'] = ai_suggestion
|
| 255 |
state['logs'].append(log_entry)
|
| 256 |
state['week'] += 1; state['decision_step'] = 'initial_order'; state['last_week_orders'] = current_week_orders
|
|
@@ -554,9 +598,10 @@ else:
|
|
| 554 |
st.write(f"**Incoming Order (This Week):**\n# {current_incoming_order}")
|
| 555 |
|
| 556 |
with col3:
|
| 557 |
-
# FIX: 'Arriving This Week' removed from UI
|
|
|
|
| 558 |
|
| 559 |
-
# Arriving NEXT week (Distributor
|
| 560 |
arriving_next = 0
|
| 561 |
st.write(f"**Shipment Arriving (Next Week):**\n# {arriving_next}")
|
| 562 |
|
|
|
|
| 1 |
# app.py
|
| 2 |
+
# @title Beer Game Final Version (v4.25 - Based on v4.21 Logic + UI Fixes v3 - Log Fix)
|
| 3 |
|
| 4 |
# -----------------------------------------------------------------------------
|
| 5 |
# 1. Import Libraries
|
|
|
|
| 191 |
llm_personality, info_sharing = state['llm_personality'], state['info_sharing']
|
| 192 |
echelon_order = ["Retailer", "Wholesaler", "Distributor", "Factory"]
|
| 193 |
llm_raw_responses = {}
|
| 194 |
+
|
| 195 |
+
# Capture opening state for logging
|
| 196 |
opening_inventories = {name: e['inventory'] for name, e in echelons.items()}
|
| 197 |
opening_backlogs = {name: e['backlog'] for name, e in echelons.items()}
|
| 198 |
+
|
| 199 |
+
# --- LOG FIX (v3): Capture arrival data BEFORE mutation ---
|
| 200 |
arrived_this_week = {name: 0 for name in echelon_order}
|
| 201 |
+
# This dict will store the value shown on the UI for "next week"
|
| 202 |
+
opening_arriving_next_week_UI_VALUE = {name: 0 for name in echelon_order}
|
| 203 |
+
|
| 204 |
+
# Factory
|
| 205 |
+
factory_q = state['factory_production_pipeline']
|
| 206 |
+
if factory_q:
|
| 207 |
+
arrived_this_week["Factory"] = factory_q[0] # Read before pop
|
| 208 |
+
if len(factory_q) > 1:
|
| 209 |
+
opening_arriving_next_week_UI_VALUE["Factory"] = factory_q[1] # Read [1] before pop
|
| 210 |
+
|
| 211 |
+
# R, W, D
|
| 212 |
+
for name in ["Retailer", "Wholesaler", "Distributor"]:
|
| 213 |
+
shipment_q = echelons[name]['incoming_shipments']
|
| 214 |
+
if shipment_q:
|
| 215 |
+
arrived_this_week[name] = shipment_q[0] # Read before pop
|
| 216 |
+
|
| 217 |
+
# This logic MUST match the v2 UI logic
|
| 218 |
+
if name == 'Distributor':
|
| 219 |
+
# "Next" for Distributor is what's at the front of the Factory's pipeline
|
| 220 |
+
if factory_q:
|
| 221 |
+
opening_arriving_next_week_UI_VALUE[name] = factory_q[0]
|
| 222 |
+
elif name in ("Retailer", "Wholesaler"):
|
| 223 |
+
if len(shipment_q) > 1: # q_len=2
|
| 224 |
+
opening_arriving_next_week_UI_VALUE[name] = shipment_q[1]
|
| 225 |
+
elif len(shipment_q) == 1: # q_len=1
|
| 226 |
+
opening_arriving_next_week_UI_VALUE[name] = shipment_q[0] # Match the v2 UI
|
| 227 |
+
# --- END OF LOG FIX (v3) ---
|
| 228 |
+
|
| 229 |
+
# Now, the *actual* state mutation (popping)
|
| 230 |
inventory_after_arrival = {}
|
| 231 |
factory_state = echelons["Factory"]
|
| 232 |
produced_units = 0
|
| 233 |
if state['factory_production_pipeline']:
|
| 234 |
produced_units = state['factory_production_pipeline'].popleft()
|
|
|
|
| 235 |
inventory_after_arrival["Factory"] = factory_state['inventory'] + produced_units
|
| 236 |
+
|
| 237 |
for name in ["Retailer", "Wholesaler", "Distributor"]:
|
| 238 |
arrived_shipment = 0
|
| 239 |
if echelons[name]['incoming_shipments']:
|
| 240 |
arrived_shipment = echelons[name]['incoming_shipments'].popleft()
|
|
|
|
| 241 |
inventory_after_arrival[name] = echelons[name]['inventory'] + arrived_shipment
|
| 242 |
+
|
| 243 |
+
# (Rest of game logic)
|
| 244 |
total_backlog_before_shipping = {}
|
| 245 |
for name in echelon_order:
|
| 246 |
incoming_order_for_this_week = 0
|
|
|
|
| 274 |
if units_shipped["Factory"] > 0: echelons['Distributor']['incoming_shipments'].append(units_shipped["Factory"])
|
| 275 |
if units_shipped['Distributor'] > 0: echelons['Wholesaler']['incoming_shipments'].append(units_shipped['Distributor'])
|
| 276 |
if units_shipped['Wholesaler'] > 0: echelons['Retailer']['incoming_shipments'].append(units_shipped['Wholesaler'])
|
| 277 |
+
|
| 278 |
+
# (Logging)
|
| 279 |
log_entry = {'timestamp': datetime.utcnow().isoformat() + "Z", 'week': week, **state}
|
| 280 |
del log_entry['echelons'], log_entry['factory_production_pipeline'], log_entry['logs'], log_entry['last_week_orders']
|
| 281 |
if 'current_ai_suggestion' in log_entry: del log_entry['current_ai_suggestion']
|
|
|
|
| 283 |
e = echelons[name]; e['weekly_cost'] = (e['inventory'] * HOLDING_COST) + (e['backlog'] * BACKLOG_COST); e['total_cost'] += e['weekly_cost']
|
| 284 |
for key in ['inventory', 'backlog', 'incoming_order', 'order_placed', 'shipment_sent', 'weekly_cost', 'total_cost']: log_entry[f'{name}.{key}'] = e[key]
|
| 285 |
log_entry[f'{name}.llm_raw_response'] = llm_raw_responses.get(name, "")
|
| 286 |
+
|
| 287 |
+
# --- LOG FIX (v3): Use captured values ---
|
| 288 |
+
log_entry[f'{name}.opening_inventory'] = opening_inventories[name]
|
| 289 |
+
log_entry[f'{name}.opening_backlog'] = opening_backlogs[name]
|
| 290 |
+
log_entry[f'{name}.arrived_this_week'] = arrived_this_week[name] # Use captured value
|
| 291 |
+
|
| 292 |
+
if name != 'Factory':
|
| 293 |
+
log_entry[f'{name}.arriving_next_week'] = opening_arriving_next_week_UI_VALUE[name]
|
| 294 |
+
else:
|
| 295 |
+
log_entry[f'{name}.production_completing_next_week'] = opening_arriving_next_week_UI_VALUE[name]
|
| 296 |
+
# --- END OF LOG FIX (v3) ---
|
| 297 |
+
|
| 298 |
log_entry[f'{human_role}.initial_order'] = human_initial_order; log_entry[f'{human_role}.ai_suggestion'] = ai_suggestion
|
| 299 |
state['logs'].append(log_entry)
|
| 300 |
state['week'] += 1; state['decision_step'] = 'initial_order'; state['last_week_orders'] = current_week_orders
|
|
|
|
| 598 |
st.write(f"**Incoming Order (This Week):**\n# {current_incoming_order}")
|
| 599 |
|
| 600 |
with col3:
|
| 601 |
+
# FIX: 'Arriving This Week' removed from UI per user request
|
| 602 |
+
# st.write(f"**Shipment Arriving (This Week):**\n# {list(e['incoming_shipments'])[0] if e['incoming_shipments'] else 0}")
|
| 603 |
|
| 604 |
+
# Arriving NEXT week (Distributor's local view CANNOT see factory pipeline)
|
| 605 |
arriving_next = 0
|
| 606 |
st.write(f"**Shipment Arriving (Next Week):**\n# {arriving_next}")
|
| 607 |
|