Lilli98 commited on
Commit
434fb89
·
verified ·
1 Parent(s): 5e0ff38

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -53
app.py CHANGED
@@ -1,5 +1,5 @@
1
  # app.py
2
- # @title Beer Game Final Version (v9 - Correct LT=3, Correct UI, Correct Log)
3
 
4
  # -----------------------------------------------------------------------------
5
  # 1. Import Libraries
@@ -35,8 +35,10 @@ INITIAL_BACKLOG = 0
35
  ORDER_PASSING_DELAY = 1 # Handled by last_week_orders
36
  SHIPPING_DELAY = 2 # General shipping delay (R->W, W->D)
37
  FACTORY_LEAD_TIME = 1
38
- # This is CORRECT for LT=3 (1 pass + 1 produce + 1 ship = 3 week total LT)
39
- FACTORY_SHIPPING_DELAY = 1
 
 
40
  HOLDING_COST = 0.5
41
  BACKLOG_COST = 1.0
42
 
@@ -87,9 +89,12 @@ def init_game_state(llm_personality: str, info_sharing: str, participant_id: str
87
  for i, name in enumerate(roles):
88
  upstream = roles[i + 1] if i + 1 < len(roles) else None
89
  downstream = roles[i - 1] if i - 1 >= 0 else None
90
- if name == "Distributor": shipping_weeks = FACTORY_SHIPPING_DELAY # This is 1
 
 
91
  elif name == "Factory": shipping_weeks = 0
92
  else: shipping_weeks = SHIPPING_DELAY # This is 2
 
93
  st.session_state.game_state['echelons'][name] = {
94
  'name': name, 'inventory': INITIAL_INVENTORY, 'backlog': INITIAL_BACKLOG,
95
  'incoming_shipments': deque([0] * shipping_weeks, maxlen=shipping_weeks),
@@ -142,9 +147,9 @@ def get_llm_prompt(echelon_state_decision_point: dict, week: int, llm_personalit
142
 
143
  if llm_personality == 'perfect_rational' and info_sharing == 'full':
144
  stable_demand = current_stable_demand # Use the correct demand
145
- # --------------------- LT=3 (1+1+1) ---------------------
146
  if e_state['name'] == 'Factory': total_lead_time = FACTORY_LEAD_TIME # 1
147
- elif e_state['name'] == 'Distributor': total_lead_time = ORDER_PASSING_DELAY + FACTORY_LEAD_TIME + FACTORY_SHIPPING_DELAY # 1+1+1 = 3
148
  else: total_lead_time = ORDER_PASSING_DELAY + SHIPPING_DELAY # 1+2 = 3
149
  # ----------------------------------------------------
150
  safety_stock = 4
@@ -245,9 +250,9 @@ def get_llm_prompt(echelon_state_decision_point: dict, week: int, llm_personalit
245
  """
246
  # =========================================================
247
 
248
- # =============== STEP_GAME (v9 - Stable Logic + Correct Log Fix) ===============
249
  def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: int):
250
- # This version uses the stable v2 game logic AND the correct v9 logging fix
251
  state = st.session_state.game_state
252
  week, echelons, human_role = state['week'], state['echelons'], state['human_role']
253
  llm_personality, info_sharing = state['llm_personality'], state['info_sharing']
@@ -258,7 +263,7 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
258
  opening_inventories = {name: e['inventory'] for name, e in echelons.items()}
259
  opening_backlogs = {name: e['backlog'] for name, e in echelons.items()}
260
 
261
- # --- LOG FIX (v9): Capture UI-visible values BEFORE any pops ---
262
  arrived_this_week_LOG = {name: 0 for name in echelon_order}
263
  arriving_next_week_LOG = {name: 0 for name in echelon_order}
264
  factory_q = state['factory_production_pipeline']
@@ -274,44 +279,25 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
274
  if shipment_q:
275
  arrived_this_week_LOG[name] = shipment_q[0] # Arrives this week (W+0)
276
 
277
- # "Next Week" (W+1)
278
  if name == 'Distributor':
279
- # "Next" for Distributor is what's in the factory *pipeline*
280
- # This is the item that will arrive in W+2
281
- # NO! "Next week" (W+1) is what is in shipping_q[0].
282
- # "Next Next week" (W+2) is factory_q[0]
283
- # The USER wants "Arriving Next Week" to mean W+1.
284
- # With maxlen=1, the item for W+1 is NOT in the queue yet.
285
- # The item for W+1 is what is in `factory_q`
286
-
287
- # --- THIS IS THE REAL FIX V9 ---
288
- # "Arriving Next Week" for Distributor (who has maxlen=1)
289
- # is the item that will be SHIPPED this week, which is in the factory_q
290
- if factory_q:
291
- arriving_next_week_LOG[name] = factory_q[0]
292
- # This is what I had before, and it caused the "8" in the log.
293
- # Let's re-read the user's trace:
294
- # "W2 order 4 should... in W4 show arriving next week 4"
295
- # W4: ANW=4. (Item for W5)
296
- # Item for W5 is Order from W2.
297
- # At start of W4:
298
- # `factory_q` = [8] (Order from W3, for W6)
299
- # `shipping_q` (Dist) = [4] (Order from W2, for W5)
300
- # The user wants "Arriving Next Week" to be 4.
301
- # This means `arriving_next_week` MUST read `shipping_q[0]`.
302
-
303
- if shipment_q: # Read item for W+1
304
- arriving_next_week_LOG[name] = shipment_q[0]
305
-
306
  elif name in ("Retailer", "Wholesaler"):
307
- # "Next" for R/W is the *second* item in their queue (item for W+1)
308
  if len(shipment_q) > 1:
309
  arriving_next_week_LOG[name] = shipment_q[1]
310
- # --- END LOG FIX (v9) ---
311
 
312
 
313
  # === NOW, THE STABLE (v2) GAME LOGIC ===
314
- arrived_this_week_GAME = {name: 0 for name in echelon_order}
 
 
315
  inventory_after_arrival = {}
316
  factory_state = echelons["Factory"]
317
  produced_units = 0
@@ -371,7 +357,7 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
371
  for key in ['inventory', 'backlog', 'incoming_order', 'order_placed', 'shipment_sent', 'weekly_cost', 'total_cost']: log_entry[f'{name}.{key}'] = e[key]
372
  log_entry[f'{name}.llm_raw_response'] = llm_raw_responses.get(name, "")
373
 
374
- # --- LOG FIX (v9): Use captured values ---
375
  log_entry[f'{name}.opening_inventory'] = opening_inventories[name]
376
  log_entry[f'{name}.opening_backlog'] = opening_backlogs[name]
377
  log_entry[f'{name}.arrived_this_week'] = arrived_this_week_LOG[name] # Use captured
@@ -380,7 +366,7 @@ def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: i
380
  log_entry[f'{name}.arriving_next_week'] = arriving_next_week_LOG[name] # Use captured
381
  else:
382
  log_entry[f'{name}.production_completing_next_week'] = arriving_next_week_LOG[name] # Use captured
383
- # --- END OF LOG FIX (v9) ---
384
 
385
  log_entry[f'{human_role}.initial_order'] = human_initial_order; log_entry[f'{human_role}.ai_suggestion'] = ai_suggestion
386
  state['logs'].append(log_entry)
@@ -610,7 +596,7 @@ else:
610
  st.markdown("---")
611
  st.subheader("Supply Chain Status (Start of Week State)")
612
 
613
- # =============== MODIFIED UI LOGIC (v9) ===============
614
  if info_sharing == 'full':
615
  cols = st.columns(4)
616
  for i, name in enumerate(echelon_order):
@@ -641,17 +627,16 @@ else:
641
  else:
642
  arriving_next = 0
643
 
644
- # --- UI FIX V9 ---
645
- # "Arriving Next Week" (W+1)
646
  if name == 'Distributor':
647
- # Read W+1 item from its own shipping queue
648
  q = e['incoming_shipments']
649
- if q: arriving_next = list(q)[0]
 
650
  elif name in ('Wholesaler', 'Retailer'):
651
- # Read W+1 item from the second slot in queue
652
  q = e['incoming_shipments']
653
  if len(q) > 1: arriving_next = list(q)[1]
654
- # --- END UI FIX V9 ---
655
 
656
  st.write(f"Arriving Next Week: **{arriving_next}**")
657
 
@@ -673,13 +658,13 @@ else:
673
  st.write(f"**Incoming Order (This Week):**\n# {current_incoming_order}")
674
 
675
  with col3:
676
- # --------------------- LOCAL UI FIX V9 ---------------------
677
  # "Arriving Next Week" for Distributor in LOCAL mode.
678
- # Read W+1 item from its own shipping queue
679
  arriving_next = 0
680
  q = e['incoming_shipments']
681
- if q:
682
- arriving_next = list(q)[0]
683
  st.write(f"**Shipment Arriving (Next Week):**\n# {arriving_next}")
684
  # -----------------------------------------------------------
685
 
 
1
  # app.py
2
+ # @title Beer Game Final Version (v7 - THE REAL FIX: LT=3, Log Fix, Prompt Fix)
3
 
4
  # -----------------------------------------------------------------------------
5
  # 1. Import Libraries
 
35
  ORDER_PASSING_DELAY = 1 # Handled by last_week_orders
36
  SHIPPING_DELAY = 2 # General shipping delay (R->W, W->D)
37
  FACTORY_LEAD_TIME = 1
38
+ # --------------------- THE REAL BUG FIX (LT=3) ---------------------
39
+ # This MUST be 2 for LT=3. (Order W2 -> F Rec W3 -> F Prod W3 -> F Fin W4 -> F Ship W4 -> D Rec W5)
40
+ FACTORY_SHIPPING_DELAY = 2 # Specific delay from Factory to Distributor
41
+ # -------------------------------------------------------------------
42
  HOLDING_COST = 0.5
43
  BACKLOG_COST = 1.0
44
 
 
89
  for i, name in enumerate(roles):
90
  upstream = roles[i + 1] if i + 1 < len(roles) else None
91
  downstream = roles[i - 1] if i - 1 >= 0 else None
92
+
93
+ # USE THE CORRECT DELAY
94
+ if name == "Distributor": shipping_weeks = FACTORY_SHIPPING_DELAY # This is 2
95
  elif name == "Factory": shipping_weeks = 0
96
  else: shipping_weeks = SHIPPING_DELAY # This is 2
97
+
98
  st.session_state.game_state['echelons'][name] = {
99
  'name': name, 'inventory': INITIAL_INVENTORY, 'backlog': INITIAL_BACKLOG,
100
  'incoming_shipments': deque([0] * shipping_weeks, maxlen=shipping_weeks),
 
147
 
148
  if llm_personality == 'perfect_rational' and info_sharing == 'full':
149
  stable_demand = current_stable_demand # Use the correct demand
150
+ # --------------------- LT=3 FIX ---------------------
151
  if e_state['name'] == 'Factory': total_lead_time = FACTORY_LEAD_TIME # 1
152
+ elif e_state['name'] == 'Distributor': total_lead_time = ORDER_PASSING_DELAY + FACTORY_LEAD_TIME + FACTORY_SHIPPING_DELAY # 1+1+2 = 4
153
  else: total_lead_time = ORDER_PASSING_DELAY + SHIPPING_DELAY # 1+2 = 3
154
  # ----------------------------------------------------
155
  safety_stock = 4
 
250
  """
251
  # =========================================================
252
 
253
+ # =============== STEP_GAME (v8) - Stable Logic + Correct Log Fix ===============
254
  def step_game(human_final_order: int, human_initial_order: int, ai_suggestion: int):
255
+ # This version uses the stable v2 game logic AND the correct v5 logging fix
256
  state = st.session_state.game_state
257
  week, echelons, human_role = state['week'], state['echelons'], state['human_role']
258
  llm_personality, info_sharing = state['llm_personality'], state['info_sharing']
 
263
  opening_inventories = {name: e['inventory'] for name, e in echelons.items()}
264
  opening_backlogs = {name: e['backlog'] for name, e in echelons.items()}
265
 
266
+ # --- LOG FIX (v8): Capture UI-visible values BEFORE any pops ---
267
  arrived_this_week_LOG = {name: 0 for name in echelon_order}
268
  arriving_next_week_LOG = {name: 0 for name in echelon_order}
269
  factory_q = state['factory_production_pipeline']
 
279
  if shipment_q:
280
  arrived_this_week_LOG[name] = shipment_q[0] # Arrives this week (W+0)
281
 
282
+ # This logic MUST match the UI logic (v8)
283
  if name == 'Distributor':
284
+ # "Next" for Distributor is the *second* item in its queue (or factory pipeline)
285
+ # --------------------- LT=3 FIX ---------------------
286
+ # With maxlen=2, the queue [0, 4] -> [0] is this week, [1] is next week
287
+ if len(shipment_q) > 1:
288
+ arriving_next_week_LOG[name] = shipment_q[1]
289
+ # ----------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  elif name in ("Retailer", "Wholesaler"):
291
+ # "Next" for R/W is the *second* item in their queue
292
  if len(shipment_q) > 1:
293
  arriving_next_week_LOG[name] = shipment_q[1]
294
+ # --- END LOG FIX (v8) ---
295
 
296
 
297
  # === NOW, THE STABLE (v2) GAME LOGIC ===
298
+ # This block is separate from the logging block above.
299
+ # It uses its *own* variables to run the game.
300
+ arrived_this_week_GAME = {name: 0 for name in echelon_order} # Use a fresh dict for game logic
301
  inventory_after_arrival = {}
302
  factory_state = echelons["Factory"]
303
  produced_units = 0
 
357
  for key in ['inventory', 'backlog', 'incoming_order', 'order_placed', 'shipment_sent', 'weekly_cost', 'total_cost']: log_entry[f'{name}.{key}'] = e[key]
358
  log_entry[f'{name}.llm_raw_response'] = llm_raw_responses.get(name, "")
359
 
360
+ # --- LOG FIX (v8): Use captured values ---
361
  log_entry[f'{name}.opening_inventory'] = opening_inventories[name]
362
  log_entry[f'{name}.opening_backlog'] = opening_backlogs[name]
363
  log_entry[f'{name}.arrived_this_week'] = arrived_this_week_LOG[name] # Use captured
 
366
  log_entry[f'{name}.arriving_next_week'] = arriving_next_week_LOG[name] # Use captured
367
  else:
368
  log_entry[f'{name}.production_completing_next_week'] = arriving_next_week_LOG[name] # Use captured
369
+ # --- END OF LOG FIX (v8) ---
370
 
371
  log_entry[f'{human_role}.initial_order'] = human_initial_order; log_entry[f'{human_role}.ai_suggestion'] = ai_suggestion
372
  state['logs'].append(log_entry)
 
596
  st.markdown("---")
597
  st.subheader("Supply Chain Status (Start of Week State)")
598
 
599
+ # =============== MODIFIED UI LOGIC (v8) ===============
600
  if info_sharing == 'full':
601
  cols = st.columns(4)
602
  for i, name in enumerate(echelon_order):
 
627
  else:
628
  arriving_next = 0
629
 
630
+ # This logic matches the v8 Log Fix
 
631
  if name == 'Distributor':
632
+ # --------------------- LT=3 FIX ---------------------
633
  q = e['incoming_shipments']
634
+ if len(q) > 1: arriving_next = list(q)[1]
635
+ # ----------------------------------------------------
636
  elif name in ('Wholesaler', 'Retailer'):
637
+ # "Next" for R/W is the *second* item in their queue
638
  q = e['incoming_shipments']
639
  if len(q) > 1: arriving_next = list(q)[1]
 
640
 
641
  st.write(f"Arriving Next Week: **{arriving_next}**")
642
 
 
658
  st.write(f"**Incoming Order (This Week):**\n# {current_incoming_order}")
659
 
660
  with col3:
661
+ # --------------------- LOCAL UI FIX V8 ---------------------
662
  # "Arriving Next Week" for Distributor in LOCAL mode.
663
+ # With LT=3 (maxlen=2), we can now show list(q)[1]
664
  arriving_next = 0
665
  q = e['incoming_shipments']
666
+ if len(q) > 1:
667
+ arriving_next = list(q)[1]
668
  st.write(f"**Shipment Arriving (Next Week):**\n# {arriving_next}")
669
  # -----------------------------------------------------------
670