βOperational capability ready for immediate use.
'
el_tip_box = document.getElementById("unlock-modal-pro-tip-box")
el_tip = document.getElementById("unlock-modal-pro-tip")
if el_tip_box and el_tip:
if item.get("pro_tip"):
el_tip_box.style.display = "flex"
el_tip.innerText = item.get("pro_tip")
else:
el_tip_box.style.display = "none"
el_queue = document.getElementById("unlock-modal-queue-indicator")
if el_queue:
if len(mechanic_unlock_queue) > 1:
el_queue.style.display = "inline-block"
el_queue.innerText = f"1 of {len(mechanic_unlock_queue)}"
else:
el_queue.style.display = "none"
btn_tab = document.getElementById("btn-unlock-modal-view-tab")
if btn_tab:
t_tab = item.get("target_tab")
if t_tab:
btn_tab.style.display = "inline-block"
btn_tab.onclick = create_proxy(lambda e: (dismiss_mechanic_unlock_modal(), switch_to_tab(t_tab)))
else:
btn_tab.style.display = "none"
btn_ack = document.getElementById("btn-unlock-modal-acknowledge")
if btn_ack:
btn_ack.innerText = "Next Milestone β" if len(mechanic_unlock_queue) > 1 else "Acknowledge & Continue β"
btn_ack.onclick = create_proxy(lambda e: dismiss_mechanic_unlock_modal())
try:
window.eval('var el = document.getElementById("modalMechanicUnlock"); if (el) { var m = bootstrap.Modal.getOrCreateInstance(el); if (m) m.show(); }')
is_mechanic_modal_open = True
except Exception as e:
print("Error displaying mechanic unlock modal:", e)
def dismiss_mechanic_unlock_modal():
global is_mechanic_modal_open, mechanic_unlock_queue
try:
window.eval('var el = document.getElementById("modalMechanicUnlock"); if (el) { var m = bootstrap.Modal.getOrCreateInstance(el); if (m) m.hide(); }')
except Exception:
pass
is_mechanic_modal_open = False
if mechanic_unlock_queue:
mechanic_unlock_queue.pop(0)
if mechanic_unlock_queue:
window.setTimeout(create_proxy(process_mechanic_unlock_queue), 350)
def switch_to_tab(tab_id: str):
try:
btn = document.getElementById(tab_id)
if btn:
btn.click()
except Exception as e:
print("Error switching tab:", e)
def update_declarative_visibility():
"""Dynamically evaluate declarative milestone data attributes across DOM elements."""
if not hasattr(engine, "unlocked_milestones"):
engine.unlocked_milestones = set()
if isinstance(engine.unlocked_milestones, list):
engine.unlocked_milestones = set(engine.unlocked_milestones)
if not hasattr(engine, "unlocked_mechanic_tutorials"):
engine.unlocked_mechanic_tutorials = set()
if isinstance(engine.unlocked_mechanic_tutorials, list):
engine.unlocked_mechanic_tutorials = set(engine.unlocked_mechanic_tutorials)
elements = document.querySelectorAll("[data-phases], [data-phase], [data-min-cash], [data-min-tickets], [data-min-kp], [data-min-facilities], [data-unlock-var]")
for i in range(len(elements)):
el = elements[i]
# Skip primary navigation tab items managed exclusively by PHASE_TAB_CONFIG to prevent click flickering
if el.parentElement and getattr(el.parentElement, "id", "") == "gameTabs":
continue
if hasattr(el, "closest") and el.closest("#gameTabs"):
continue
# 1. Phase Check
phases_attr = el.getAttribute("data-phases") or el.getAttribute("data-phase") or ""
allowed_phases = parse_allowed_phases(phases_attr)
if engine.phase not in allowed_phases:
el.style.display = "none"
continue
# Determine milestone key
tut_key = el.getAttribute("data-tutorial-key")
milestone_key = el.getAttribute("data-milestone-key") or tut_key or el.id
# If this milestone was already achieved during this run/save, keep it permanently unlocked!
already_unlocked = bool(milestone_key and milestone_key in engine.unlocked_milestones)
if not already_unlocked:
# Check threshold requirements
# 2. Min Cash (checks current cash OR lifetime cash earned)
min_cash_attr = el.getAttribute("data-min-cash")
if min_cash_attr:
try:
req_cash = float(min_cash_attr)
if engine.cash < req_cash and getattr(engine, "total_cash_earned", 0.0) < req_cash:
el.style.display = "none"
continue
except Exception:
pass
# 3. Min Tickets
min_tix_attr = el.getAttribute("data-min-tickets")
if min_tix_attr:
try:
if engine.tickets_solved < int(min_tix_attr):
el.style.display = "none"
continue
except Exception:
pass
# 4. Min KP
min_kp_attr = el.getAttribute("data-min-kp")
if min_kp_attr:
try:
if engine.knowledge_points < float(min_kp_attr):
el.style.display = "none"
continue
except Exception:
pass
# 5. Min Facilities (e.g. data-min-facilities="corporate:1")
min_fac_attr = el.getAttribute("data-min-facilities")
if min_fac_attr:
fac_met = True
for fac_item in min_fac_attr.split(","):
if ":" in fac_item:
f_k, f_c = fac_item.strip().split(":", 1)
if hasattr(engine, "phase3_facilities") and isinstance(engine.phase3_facilities, dict):
if engine.phase3_facilities.get(f_k, 0) < int(f_c):
fac_met = False
break
elif hasattr(engine, "facilities") and isinstance(engine.facilities, dict):
if engine.facilities.get(f_k, 0) < int(f_c):
fac_met = False
break
if not fac_met:
el.style.display = "none"
continue
# 6. Unlock Variable (e.g. data-unlock-var="career_choice" or data-unlock-var="ai_documenter")
unlock_var_attr = el.getAttribute("data-unlock-var")
if unlock_var_attr:
val = getattr(engine, unlock_var_attr, None)
if val is None and hasattr(engine, "upgrades") and isinstance(engine.upgrades, dict):
val = engine.upgrades.get(unlock_var_attr, None)
unlock_amt_attr = el.getAttribute("data-unlock-amt")
req_amt = int(unlock_amt_attr) if unlock_amt_attr else 1
if val is None or (isinstance(val, (int, float)) and val < req_amt) or (isinstance(val, bool) and not val):
el.style.display = "none"
continue
# All conditions met for the first time -> Register Permanent Unlock!
if milestone_key:
engine.unlocked_milestones.add(milestone_key)
# Check tutorial discovery trigger
if tut_key and tut_key not in engine.unlocked_mechanic_tutorials:
tut_title = el.getAttribute("data-tutorial-title")
tut_desc = el.getAttribute("data-tutorial-desc")
queue_mechanic_unlock(tut_key, tut_title, tut_desc)
# All conditions met (or already permanently unlocked) -> Reveal element!
el.style.display = ""
def handle_secret_click(event=None):
engine.register_secret_click()
update_ui()
def update_phase_promotions(engine):
"""Universal promotion check: updates requirement labels and enables/disables the button."""
config = engine.get_promotion_config()
if not config:
return
all_satisfied = True
for req in config.get("requirements", []):
el = document.getElementById(req["id"])
if not el:
continue
is_met = req["check"](engine)
text_content = req["text"](engine)
if is_met:
el.className = "mb-1 text-success fw-bold text-center"
el.innerHTML = f"βοΈ {text_content}"
else:
el.className = "mb-1 text-muted text-center"
el.innerHTML = f"β {text_content}"
all_satisfied = False
# Toggle the promotion button for the current phase
btn_id = config.get("button_id")
if btn_id:
btn = document.getElementById(btn_id)
if btn:
if all_satisfied:
btn.removeAttribute("disabled")
else:
btn.setAttribute("disabled", "true")
def generate_svg_sparkline(history: list, is_up: bool) -> str:
"""Generate a clean mini SVG sparkline chart from price history points."""
if not history or len(history) < 2:
return ''
min_p = min(history)
max_p = max(history)
rng = max_p - min_p if max_p > min_p else 1.0
n = len(history)
pts = []
for i, val in enumerate(history):
x = (i / (n - 1)) * 100.0
y = 21.0 - ((val - min_p) / rng) * 18.0
pts.append(f"{x:.1f},{y:.1f}")
poly_pts = " ".join(pts)
color = "#00ffcc" if is_up else "#ff3366"
return f''
def show_achievement_toast(achievement_id):
"""Dynamically spawn a beautiful Bootstrap 5 toast notification for unlocks."""
defs = achievement_system.definitions or ACHIEVEMENT_DETAILS
details = defs.get(achievement_id, {})
name = details.get("name", achievement_id.replace("_", " ").title())
desc = details.get("description", "Milestone reached!")
icon = details.get("icon", "π")
toast_container = document.getElementById("toast-container")
if toast_container:
toast_html = f"""
{icon}
π Achievement Unlocked!
{name}
{desc}
"""
div = document.createElement("div")
div.innerHTML = toast_html.strip()
toast_element = div.firstElementChild if hasattr(div, "firstElementChild") and div.firstElementChild else div.firstChild
toast_container.appendChild(toast_element)
# Remove the toast after 6 seconds
def remove_toast():
try:
if toast_element and toast_element in toast_container.children:
toast_container.removeChild(toast_element)
except Exception:
pass
window.setTimeout(create_proxy(remove_toast), 6000)
update_achievements_ui()
def show_feature_discovery_toast(key, title=None, desc=None, icon="β¨"):
"""Dynamically spawn a discovery toast notification when a new game system unlocks."""
toast_container = document.getElementById("toast-container")
if not toast_container:
return
t_title = title or key.replace("_", " ").title()
t_desc = desc or "New system feature unlocked. Click to open full operational briefing."
toast_html = f"""
{icon}
β¨ Milestone Unlocked!
{t_title}
{t_desc}
"""
div = document.createElement("div")
div.innerHTML = toast_html.strip()
toast_element = div.firstElementChild if hasattr(div, "firstElementChild") and div.firstElementChild else div.firstChild
toast_container.appendChild(toast_element)
def remove_toast():
try:
if toast_element and toast_element in toast_container.children:
toast_container.removeChild(toast_element)
except Exception:
pass
window.setTimeout(create_proxy(remove_toast), 7000)
current_syslog_filter = "ALL"
def show_event_log_js():
"""Render and open the IT Syslog Console modal."""
render_syslog_entries()
try:
window.eval('var el = document.getElementById("systemEventLogModal"); if (el) { var m = bootstrap.Modal.getOrCreateInstance(el); if (m) m.show(); }')
except Exception as e:
print("Error showing syslog modal:", e)
def set_syslog_filter_js(filter_cat: str):
global current_syslog_filter
current_syslog_filter = filter_cat
group = document.getElementById("syslog-filter-group")
if group:
for btn in group.querySelectorAll("button"):
onclick_attr = btn.getAttribute("onclick") or ""
if f"'{filter_cat}'" in onclick_attr:
btn.className = "btn btn-outline-info active" if filter_cat == "ALL" else (
"btn btn-outline-warning active" if filter_cat == "EVENT" else (
"btn btn-outline-danger active" if filter_cat == "HARDWARE" else (
"btn btn-outline-success active" if filter_cat == "MILESTONE" else "btn btn-outline-primary active"
)
)
)
else:
btn.className = "btn btn-outline-secondary"
render_syslog_entries()
def clear_syslog_js():
if hasattr(engine, "event_log") and engine.event_log:
engine.event_log.clear()
render_syslog_entries()
def render_syslog_entries():
feed = document.getElementById("syslog-console-feed")
count_badge = document.getElementById("syslog-entry-count")
if not feed:
return
if not hasattr(engine, "event_log") or not engine.event_log:
feed.innerHTML = '
No syslog events recorded yet.
'
return
cat_filt = None if current_syslog_filter == "ALL" else current_syslog_filter
entries = engine.event_log.get_entries(limit=50, category_filter=cat_filt)
if count_badge:
count_badge.innerText = f"{len(engine.event_log.entries)} entries"
if not entries:
feed.innerHTML = f'
No entries matching filter [{current_syslog_filter}].
'
return
html = ""
for e in entries:
lvl = e.get("level", "INFO")
cat = e.get("category", "SYSTEM")
ts = e.get("timestamp", "--:--:--")
msg = e.get("message", "")
tab = e.get("link_tab")
lbl = e.get("link_label")
lvl_color = "#38bdf8" if lvl == "INFO" else ("#4ade80" if lvl == "SUCCESS" else ("#fbbf24" if lvl == "WARN" else "#f87171"))
cat_badge = f'[{cat}]'
lvl_badge = f'{lvl}'
link_btn = ""
if tab:
link_btn = f' '
html += f"""
[{ts}]
{cat_badge}
{lvl_badge}
{msg}
{link_btn}
"""
feed.innerHTML = html
def toggle_milestone_toasts_js(val: bool = None):
global is_mechanic_modal_open, mechanic_unlock_queue
if not hasattr(engine, "settings") or not isinstance(engine.settings, dict):
engine.settings = {}
if val is None:
curr = engine.settings.get("milestone_toasts_only", False)
engine.settings["milestone_toasts_only"] = not curr
else:
engine.settings["milestone_toasts_only"] = bool(val)
chk = document.getElementById("toggle-milestone-toasts")
if chk:
chk.checked = bool(engine.settings["milestone_toasts_only"])
mode_text = "Discreet Toasts" if engine.settings["milestone_toasts_only"] else "Full Modal Dialogs"
print(f"[Settings] Milestone notification mode set to: {mode_text}")
# If activated via the modal button, dismiss modal immediately and provide confirmation feedback
if is_mechanic_modal_open or val is True:
try:
window.eval('var el = document.getElementById("modalMechanicUnlock"); if (el) { var m = bootstrap.Modal.getOrCreateInstance(el); if (m) m.hide(); }')
except Exception:
pass
is_mechanic_modal_open = False
# Flush any remaining queued milestone modals into toast alerts
if mechanic_unlock_queue:
mechanic_unlock_queue.pop(0)
while mechanic_unlock_queue:
q_item = mechanic_unlock_queue.pop(0)
show_feature_discovery_toast(
q_item.get("key", "milestone"),
title=q_item.get("title"),
desc=q_item.get("summary"),
icon=q_item.get("icon", "β¨")
)
# Show confirmation feedback toast
show_feature_discovery_toast(
"milestone_toast_preference",
title="π Toast Alerts Enabled",
desc="Milestone unlocks will now appear as corner toasts. You can re-enable full modals in Settings at any time.",
icon="π"
)
_active_event_modal_info = None
def show_random_event_modal(ev: dict):
"""Populate and display the Random Event modal."""
global _active_event_modal_info
el_icon = document.getElementById("event-modal-icon")
el_cat = document.getElementById("event-modal-category")
el_title = document.getElementById("event-modal-title")
el_desc = document.getElementById("event-modal-desc")
el_dur = document.getElementById("event-modal-duration")
el_effects = document.getElementById("event-modal-effects-list")
dur = float(ev.get("duration", 30))
_active_event_modal_info = {
"id": ev.get("id"),
"name": ev.get("name"),
"end_time": time.time() + dur,
"duration": dur,
"active": True
}
if el_icon: el_icon.innerText = ev.get("icon", "β‘")
if el_cat: el_cat.innerText = f"{ev.get('category', 'Incident').upper()} EVENT"
if el_title: el_title.innerText = ev.get("name", "Random Incident")
if el_desc: el_desc.innerText = ev.get("description", "A random operational incident has occurred.")
if el_dur: el_dur.innerText = f"{dur:.0f}s"
if el_effects:
effs = ev.get("effects", {})
eff_html = ""
for k, v in effs.items():
if k.endswith("_fallback"):
continue
k_name = k.replace("_", " ").title()
val_str = f"{v}x" if "mult" in k else (f"+{v}%" if "pct" in k else str(v))
eff_html += f'
β’ {k_name}:{val_str}
'
el_effects.innerHTML = eff_html or '
No immediate adverse effects.
'
try:
window.eval('var el = document.getElementById("randomEventModal"); if (el) { var m = bootstrap.Modal.getOrCreateInstance(el); if (m) m.show(); }')
except Exception as e:
print("Error displaying random event modal:", e)
def set_achievements_filter(filter_name):
global current_ach_filter
current_ach_filter = filter_name
filter_container = document.getElementById("ach-filter-buttons")
if filter_container:
for btn in filter_container.querySelectorAll(".ach-filter-btn"):
f_val = btn.getAttribute("data-filter")
if f_val == filter_name:
btn.className = "btn btn-sm btn-warning active ach-filter-btn"
else:
if f_val == "unlocked":
btn.className = "btn btn-sm btn-outline-success ach-filter-btn"
elif f_val == "locked":
btn.className = "btn btn-sm btn-outline-secondary ach-filter-btn"
else:
btn.className = "btn btn-sm btn-outline-light ach-filter-btn"
update_achievements_ui()
def init_achievements_ui():
global achievements_ui_initialized
grid = document.getElementById("achievements-grid")
if not grid:
return
defs = achievement_system.definitions or ACHIEVEMENT_DETAILS
if not defs:
return
html_parts = []
for ach_id, ach in defs.items():
icon = ach.get("icon", "π")
name = ach.get("name", ach_id)
desc = ach.get("description", "")
phase = ach.get("phase_unlock", 1)
card_html = f"""
{icon}
{name}
π Locked
{desc}
Phase {phase}
"""
html_parts.append(card_html)
grid.innerHTML = "".join(html_parts)
# Filter button listeners
filter_container = document.getElementById("ach-filter-buttons")
if filter_container:
for btn in filter_container.querySelectorAll(".ach-filter-btn"):
f_val = btn.getAttribute("data-filter")
btn.addEventListener("click", create_proxy(lambda e, f=f_val: set_achievements_filter(f)))
achievements_ui_initialized = True
update_achievements_ui()
def update_achievements_ui():
global current_ach_filter
grid = document.getElementById("achievements-grid")
if not grid:
return
defs = achievement_system.definitions or ACHIEVEMENT_DETAILS
if not defs:
return
total_count = len(defs)
unlocked_count = sum(1 for k, v in engine.achievements.items() if v and k in defs)
pct = round((unlocked_count / total_count * 100.0), 1) if total_count > 0 else 0.0
count_el = document.getElementById("ach-unlocked-count")
total_el = document.getElementById("ach-total-count")
pct_el = document.getElementById("ach-pct")
bar_el = document.getElementById("ach-progress-bar")
if count_el: count_el.innerText = str(unlocked_count)
if total_el: total_el.innerText = str(total_count)
if pct_el: pct_el.innerText = f"{pct:.0f}%"
if bar_el:
bar_el.style.width = f"{pct}%"
bar_el.setAttribute("aria-valuenow", str(int(pct)))
if pct >= 100.0:
bar_el.className = "progress-bar bg-success progress-bar-striped"
else:
bar_el.className = "progress-bar bg-warning progress-bar-striped progress-bar-animated"
# Filter buttons phase visibility (Hide future phase buttons)
filter_container = document.getElementById("ach-filter-buttons")
if filter_container:
for btn in filter_container.querySelectorAll(".ach-filter-btn"):
f_val = btn.getAttribute("data-filter")
if f_val and f_val.startswith("phase-"):
try:
p_num = int(f_val.split("-")[1])
if p_num > engine.phase:
btn.style.display = "none"
if current_ach_filter == f_val:
current_ach_filter = "all"
else:
btn.style.display = "inline-block"
except Exception:
pass
for ach_id, ach in defs.items():
card_el = document.getElementById(f"card-ach-{ach_id}")
if not card_el:
continue
is_unlocked = bool(engine.achievements.get(ach_id, False))
phase = ach.get("phase_unlock", 1)
is_future = (phase > engine.phase)
# Check filter visibility
visible = True
if current_ach_filter == "all":
visible = True
elif current_ach_filter == "phase-1":
visible = (phase == 1)
elif current_ach_filter == "phase-2":
visible = (phase == 2)
elif current_ach_filter == "phase-3":
visible = (phase == 3)
elif current_ach_filter == "phase-4":
visible = (phase == 4)
elif current_ach_filter == "unlocked":
visible = is_unlocked
elif current_ach_filter == "locked":
visible = not is_unlocked
card_el.style.display = "block" if visible else "none"
# Update styling, content & badge
badge_el = document.getElementById(f"badge-ach-{ach_id}")
card_inner = document.getElementById(f"card-inner-ach-{ach_id}")
icon_box = document.getElementById(f"icon-box-ach-{ach_id}")
title_el = document.getElementById(f"title-ach-{ach_id}")
desc_el = document.getElementById(f"desc-ach-{ach_id}")
if is_future:
# Grayed out without details (Fog of War)
if title_el:
title_el.innerText = "π Classified Milestone"
title_el.className = "mb-0 fw-bold text-muted ach-title"
if desc_el:
desc_el.innerText = f"Milestone objective classified until unlocking Phase {phase}."
desc_el.className = "text-muted small mb-2 fst-italic"
if badge_el:
badge_el.innerHTML = 'π Classified'
if card_inner:
card_inner.className = "card h-100 bg-dark bg-opacity-50 text-muted border-secondary opacity-50 p-3 rounded shadow-sm"
card_inner.style.background = ""
if icon_box:
icon_box.innerText = "β"
icon_box.className = "fs-1 me-3 p-2 rounded bg-black bg-opacity-25 border border-secondary text-muted text-center"
elif is_unlocked:
if title_el:
title_el.innerText = ach.get("name", ach_id)
title_el.className = "mb-0 fw-bold text-white ach-title"
if desc_el:
desc_el.innerText = ach.get("description", "")
desc_el.className = "text-light text-opacity-75 small mb-2"
if badge_el:
badge_el.innerHTML = 'π’ Unlocked'
if card_inner:
card_inner.className = "card h-100 bg-dark text-white border-success shadow p-3 rounded"
card_inner.style.background = "linear-gradient(135deg, rgba(20,40,30,0.85), rgba(15,25,20,0.95))"
if icon_box:
icon_box.innerText = ach.get("icon", "π")
icon_box.className = "fs-1 me-3 p-2 rounded bg-success bg-opacity-25 border border-success text-center"
else:
if title_el:
title_el.innerText = ach.get("name", ach_id)
title_el.className = "mb-0 fw-bold text-white ach-title"
if desc_el:
desc_el.innerText = ach.get("description", "")
desc_el.className = "text-muted small mb-2"
if badge_el:
badge_el.innerHTML = 'π Locked'
if card_inner:
card_inner.className = "card h-100 bg-dark bg-opacity-75 text-white border-secondary opacity-75 p-3 rounded shadow-sm"
card_inner.style.background = ""
if icon_box:
icon_box.innerText = ach.get("icon", "π")
icon_box.className = "fs-1 me-3 p-2 rounded bg-black bg-opacity-50 border border-secondary text-center"
# Bind the Achievements System
provider = WebAchievementProvider(toast_callback=show_achievement_toast)
achievement_system = AchievementSystem(provider)
engine.achievement_system = achievement_system
# Autosave / UI Message flash helpers
def flash_save_status():
status_el = document.getElementById("settings-message")
status_el.innerText = "Progress saved to LocalStorage!"
window.setTimeout(create_proxy(lambda: setattr(status_el, "innerText", "")), 3000)
def flash_autosave_status():
autosave_indicator = document.getElementById("autosave-indicator")
if autosave_indicator:
autosave_indicator.style.opacity = "1"
window.setTimeout(create_proxy(lambda: setattr(autosave_indicator.style, "opacity", "0")), 2000)
def confirm_and_reset():
if window.confirm("Are you sure you want to completely wipe all progress? This cannot be undone."):
save.clear_localstorage()
engine.reset()
update_ui()
status_el = document.getElementById("settings-message")
status_el.innerText = "Game reset successful!"
window.setTimeout(create_proxy(lambda: setattr(status_el, "innerText", "")), 3000)
def export_save_text():
save_str = save.export_save(engine)
area = document.getElementById("save-text-area")
area.value = save_str
window.navigator.clipboard.writeText(save_str)
area.select()
status_el = document.getElementById("settings-message")
status_el.innerText = "Save string copied to clipboard!"
window.setTimeout(create_proxy(lambda: setattr(status_el, "innerText", "")), 3000)
def import_save_text():
area = document.getElementById("save-text-area")
save_str = area.value.strip()
if not save_str:
return
success = save.import_save(engine, save_str)
status_el = document.getElementById("settings-message")
if success:
save.save_to_localstorage(engine)
area.value = ""
status_el.innerText = "Save imported successfully!"
update_ui()
else:
status_el.innerText = "Invalid save string!"
window.setTimeout(create_proxy(lambda: setattr(status_el, "innerText", "")), 3000)
def toggle_auto_research(e):
engine.auto_research_active = e.target.checked
update_ui()
def toggle_auto_kb(e):
engine.auto_kb_active = e.target.checked
update_ui()
def toggle_auto_dispatch(e):
engine.auto_dispatch = e.target.checked
update_ui()
def assign_worker_js(incident_id, worker_type):
if worker_type == "none":
engine.assign_incident(incident_id, None)
else:
engine.assign_incident(incident_id, worker_type)
update_ui()
def hire_branch_manager_js(branch_id):
engine.hire_branch_manager(branch_id)
update_ui()
def set_branch_directive_js(branch_id, directive):
engine.set_branch_directive(branch_id, directive)
update_ui()
def toggle_it_policy_js(policy_id):
engine.toggle_it_policy(policy_id)
update_ui()
def start_rd_project_js(project_id):
engine.start_rd_project(project_id)
update_ui()
def hire_cto_leader_js(role_id):
engine.hire_cto_leader(role_id)
update_ui()
def set_cto_staffing_policy_js(policy_id):
engine.set_cto_staffing_policy(policy_id)
update_ui()
def set_cto_procedure_policy_js(policy_id):
engine.set_cto_procedure_policy(policy_id)
update_ui()
def build_facility_js(facility_type):
if engine.build_phase3_facility(str(facility_type)):
update_ui()
def research_tech_js(tech_id):
if engine.select_research_project(str(tech_id)):
update_ui()
def synthesize_kp_js(amount):
if engine.synthesize_knowledge(float(amount)):
update_ui()
def toggle_auto_synthesis_js(e):
engine.auto_synthesis_active = bool(e.target.checked)
update_ui()
def hire_candidate_js(candidate_id):
if engine.hire_candidate(str(candidate_id)):
update_ui()
def fire_tech_js(tech_id):
if engine.fire_tech(str(tech_id)):
update_ui()
def trigger_hr_ability_js(ability_id):
if engine.trigger_hr_ability(str(ability_id)):
update_ui()
def show_guide_js(guide_id):
guide = resources.MECHANIC_GUIDES.get(str(guide_id))
if not guide:
return
el_icon = document.getElementById("guide-modal-icon")
if el_icon:
el_icon.innerText = guide.get("icon", "π‘")
el_title = document.getElementById("guide-modal-title")
if el_title:
el_title.innerText = guide.get("title", "Mechanic Overview")
el_cat = document.getElementById("guide-modal-category")
if el_cat:
el_cat.innerText = guide.get("category", "Operations")
el_sum = document.getElementById("guide-modal-summary")
if el_sum:
el_sum.innerText = guide.get("summary", "")
el_mech = document.getElementById("guide-modal-mechanics")
if el_mech:
items_html = []
for m in guide.get("key_mechanics", []):
items_html.append(f'
{m}
')
el_mech.innerHTML = "".join(items_html)
el_res = document.getElementById("guide-modal-resources")
if el_res:
pills_html = []
for r in guide.get("resources_involved", []):
pills_html.append(f'{r}')
el_res.innerHTML = "".join(pills_html)
el_tips = document.getElementById("guide-modal-tips")
if el_tips:
el_tips.innerText = guide.get("pro_tips", "")
try:
window.eval("""
(function() {
const modalEl = document.getElementById('mechanicGuideModal');
if (modalEl) {
if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
const inst = bootstrap.Modal.getOrCreateInstance(modalEl);
inst.show();
} else {
modalEl.classList.add('show');
modalEl.style.display = 'block';
modalEl.removeAttribute('aria-hidden');
modalEl.setAttribute('aria-modal', 'true');
}
}
})();
""")
except Exception as ex:
print(f"Error opening guide modal: {ex}")
def show_orientation_js(phase_or_key):
"""Populates and opens the Phase Corporate Orientation Packet Modal."""
try:
p_num = int(phase_or_key)
except (ValueError, TypeError):
p_num = 1
packet = getattr(resources, "ORIENTATION_PACKETS", {}).get(p_num)
if not packet:
return
el_icon = document.getElementById("orientation-modal-icon")
if el_icon: el_icon.innerText = packet.get("icon", "π")
el_title = document.getElementById("orientation-modal-title")
if el_title: el_title.innerText = packet.get("title", "ORIENTATION PACKET")
el_sub = document.getElementById("orientation-modal-subtitle")
if el_sub: el_sub.innerText = packet.get("subtitle", "")
el_memo = document.getElementById("orientation-modal-memo")
if el_memo: el_memo.innerText = packet.get("sender_memo", "")
el_badge = document.getElementById("orientation-modal-badge")
if el_badge:
el_badge.innerText = packet.get("theme_badge", "ORIENTATION")
color = packet.get("theme_color", "info")
el_badge.className = f"badge bg-{color} text-dark fw-bold font-monospace px-2 py-1"
el_fantasy = document.getElementById("orientation-modal-fantasy")
if el_fantasy: el_fantasy.innerText = packet.get("fantasy_overview", "")
el_tabs = document.getElementById("orientation-modal-tabs")
if el_tabs:
tabs_html = []
for t in packet.get("unlocked_tabs", []):
tabs_html.append(f'''
{t.get("icon", "π")}{t.get("name", "")}
{t.get("desc", "")}
''')
el_tabs.innerHTML = "".join(tabs_html)
el_mechs = document.getElementById("orientation-modal-mechanics")
if el_mechs:
mechs_html = []
for m in packet.get("key_mechanics", []):
mechs_html.append(f'''
{m.get("icon", "βοΈ")}{m.get("title", "")}
{m.get("desc", "")}
''')
el_mechs.innerHTML = "".join(mechs_html)
el_chk = document.getElementById("orientation-modal-checklist")
if el_chk:
chk_html = []
for item in packet.get("first_day_checklist", []):
chk_html.append(f'
No candidates currently available. Click Refresh Pool to recruit!
'
# Update Live Technician Floor Roster grid (in Staff Tab)
roster_grid = document.getElementById("tech-roster-grid")
if roster_grid and engine.phase >= 2:
roster_items = [f"{t.get('id')}_{t.get('status')}_{int(t.get('stress', 0))}_{t.get('level')}_{t.get('xp')}_{t.get('lifetime_solved')}" for t in engine.tech_roster]
roster_sig = ",".join(roster_items)
global last_roster_sig
if roster_sig != last_roster_sig:
last_roster_sig = roster_sig
if engine.tech_roster:
cards = []
# Check for solo rush pressure by queue
unassigned_low = sum(1 for i in engine.active_incidents if i.get("severity") == "low" and not i.get("assigned_to"))
unassigned_med = sum(1 for i in engine.active_incidents if i.get("severity") == "medium" and not i.get("assigned_to"))
unassigned_high = sum(1 for i in engine.active_incidents if i.get("severity") == "high" and not i.get("assigned_to"))
unassigned_onsite = sum(1 for i in engine.active_incidents if i.get("severity") in ["onsite", "critical"] and not i.get("assigned_to"))
l1_count = len([t for t in engine.tech_roster if t.get("role") == "l1_tech"])
l2_count = len([t for t in engine.tech_roster if t.get("role") == "l2_tech"])
sys_count = len([t for t in engine.tech_roster if t.get("role") == "sysadmin"])
onsite_count = len([t for t in engine.tech_roster if t.get("role") == "onsite_tech"])
for t in engine.tech_roster:
t_id = t["id"]
t_name = t["name"]
t_role = t["role"]
t_status = t.get("status", "idle")
t_stress = t.get("stress", 0.0)
t_lvl = t.get("level", 1)
t_xp = t.get("xp", 0)
t_req_xp = t_lvl * 50
t_solved = t.get("lifetime_solved", 0)
t_trait_name = t.get("trait_name", "Reliable")
t_trait_icon = t.get("trait_icon", "π‘οΈ")
# Solo rush detection for fantasy immersion
is_solo_rush = False
if t_role == "l1_tech" and l1_count == 1 and unassigned_low >= 2:
is_solo_rush = True
elif t_role == "l2_tech" and l2_count == 1 and unassigned_med >= 2:
is_solo_rush = True
elif t_role == "sysadmin" and sys_count == 1 and unassigned_high >= 2:
is_solo_rush = True
elif t_role == "onsite_tech" and onsite_count == 1 and unassigned_onsite >= 2:
is_solo_rush = True
rush_badge = 'β οΈ Solo Rush' if is_solo_rush else ""
role_icon = "π" if t_role == "l1_tech" else ("π»" if t_role == "l2_tech" else ("π‘οΈ" if t_role == "sysadmin" else "π"))
role_title = "L1 Helpdesk" if t_role == "l1_tech" else ("L2 Support" if t_role == "l2_tech" else ("Sysadmin" if t_role == "sysadmin" else "Field On-Site"))
if t_status == "working":
status_badge = 'β‘ Working'
elif t_status == "break":
status_badge = 'β Break'
elif t_status == "burned_out":
status_badge = 'π₯ Burned Out'
else:
status_badge = 'π’ Idle'
stress_bar_color = "bg-success" if t_stress < 50 else ("bg-warning" if t_stress < 80 else "bg-danger")
wage_min = t.get("wage_per_sec", resources.STAFF_ROLES_CONFIG.get(t_role, {}).get("wage_per_sec", 0.05)) * 60.0
card_html = f"""
No support technicians hired yet. Recruit candidates from the talent pool above to build your team!
'
# Update Payroll / Wage burn display
staff_burn_el = document.getElementById("staff-burn-rate")
if staff_burn_el:
staff_burn_el.innerText = f"Payroll: -${getattr(engine, 'team_wage_burn_rate', 0.0):.2f}/s"
# Phase 3 Personnel View vs Phase 2 Staff Roster View
staff_p2 = document.getElementById("staff-phase2-view")
staff_p3 = document.getElementById("staff-phase3-view")
if staff_p2 and staff_p3:
if engine.phase >= 3:
staff_p2.style.display = "none"
staff_p3.style.display = "block"
else:
staff_p2.style.display = "block"
staff_p3.style.display = "none"
if engine.phase == 3 and staff_p3:
health = engine.get_cto_staffing_health()
# Staffing Health Badge
badge_health = document.getElementById("badge-cto-staffing-health")
if badge_health:
if health["status"] == "Optimal":
badge_health.className = "badge bg-success fs-6 px-3 py-2 fw-bold"
badge_health.innerText = "STAFFING: OPTIMAL"
elif health["status"] == "Understaffed":
badge_health.className = "badge bg-warning text-dark fs-6 px-3 py-2 fw-bold"
badge_health.innerText = "STAFFING: UNDERSTAFFED"
else:
badge_health.className = "badge bg-info text-dark fs-6 px-3 py-2 fw-bold"
badge_health.innerText = "STAFFING: OVERSTAFFED"
# KPIs
el_hired = document.getElementById("display-cto-leaders-hired")
if el_hired:
el_hired.innerText = f"{health['total_hired']} / {health['total_required']}"
el_ratio = document.getElementById("display-cto-staffing-ratio")
if el_ratio:
el_ratio.innerText = f"{int(health['ratio'] * 100)}%"
comp_spec = resources.CTO_COMPENSATION_POLICIES.get(engine.cto_staffing_policy, {})
salary_mult = comp_spec.get("salary_mult", 1.0)
leadership_salary = sum(engine.cto_hired_leadership.get(r, 0) * spec["base_salary"] * salary_mult for r, spec in getattr(resources, "CTO_LEADERSHIP_ROLES", {}).items())
el_payroll = document.getElementById("display-cto-leader-payroll")
if el_payroll:
el_payroll.innerText = f"-${leadership_salary:.2f}/s"
el_perk = document.getElementById("display-cto-perk-mult")
if el_perk:
el_perk.innerText = f"{engine.get_cto_leadership_bonus_mult():.2f}x"
# Role cards
for role_id, r_info in health["details"].items():
badge_dem = document.getElementById(f"badge-leader-demand-{role_id}")
badge_cnt = document.getElementById(f"badge-leader-count-{role_id}")
btn_hire = document.getElementById(f"btn-hire-leader-{role_id}")
lbl_ratio = document.getElementById(f"lbl-leader-ratio-{role_id}")
if lbl_ratio and r_info.get("facility_ratio_desc"):
lbl_ratio.innerHTML = f'{r_info["facility_ratio_desc"]} (Target: {r_info["required"]})'
if badge_dem:
if r_info["hired"] < r_info["required"]:
diff = r_info["required"] - r_info["hired"]
badge_dem.className = "badge bg-warning text-dark me-2"
badge_dem.innerText = f"{diff} Needed"
else:
badge_dem.className = "badge bg-success me-2"
badge_dem.innerText = "Fulfilled"
if badge_cnt:
badge_cnt.innerText = f"{r_info['hired']} / {r_info['max_slots']}"
if btn_hire:
if r_info["hired"] >= r_info["max_slots"]:
btn_hire.innerText = "Max Appointed"
btn_hire.disabled = True
btn_hire.className = "btn btn-sm btn-secondary fw-bold"
else:
btn_hire.innerText = f"Appoint (${r_info['cost']:,.2f})"
btn_hire.disabled = (engine.cash < r_info["cost"] or engine.burnout or engine.pc_crashed or engine.is_rebooting)
btn_hire.className = "btn btn-sm btn-outline-success fw-bold"
# Policy buttons & descriptions
for pol_k in ["lean", "market", "premium"]:
p_btn = document.getElementById(f"btn-comp-policy-{pol_k}")
if p_btn:
if engine.cto_staffing_policy == pol_k:
p_btn.className = "btn btn-outline-primary btn-sm active"
else:
p_btn.className = "btn btn-outline-secondary btn-sm"
desc_comp = document.getElementById("box-comp-policy-desc")
if desc_comp:
desc_comp.innerText = comp_spec.get("desc", "")
proc_spec = resources.CTO_PROCEDURE_POLICIES.get(engine.cto_procedure_policy, {})
for proc_k in ["agile", "balanced", "iso9001"]:
pr_btn = document.getElementById(f"btn-proc-policy-{proc_k}")
if pr_btn:
if engine.cto_procedure_policy == proc_k:
pr_btn.className = "btn btn-outline-primary btn-sm active"
else:
pr_btn.className = "btn btn-outline-secondary btn-sm"
desc_proc = document.getElementById("box-proc-policy-desc")
if desc_proc:
desc_proc.innerText = proc_spec.get("desc", "")
# Update Company-Wide Staffing Telemetry Dashboard
wf = engine.get_headcount_breakdown() if hasattr(engine, "get_headcount_breakdown") else {
"total": len(engine.tech_roster), "call_center_agents": 0, "support_specialists": 0,
"dc_engineers": 0, "corporate_researchers": 0, "branch_leads": 0, "executive_leaders": 0, "core_techs": len(engine.tech_roster)
}
tps = engine.get_company_ticket_throughput_rate() if hasattr(engine, "get_company_ticket_throughput_rate") else 0.0
badge_tps = document.getElementById("display-corp-tps-badge")
if badge_tps:
badge_tps.innerText = f"β‘ {tps:.1f} Tickets/sec"
el_wf_tot = document.getElementById("display-corp-total-workforce")
if el_wf_tot:
el_wf_tot.innerText = f"{wf['total']:,}"
el_wf_tech = document.getElementById("display-corp-total-techs")
if el_wf_tech:
el_wf_tech.innerText = f"{wf['support_specialists'] + wf['core_techs']:,}"
el_wf_br = document.getElementById("display-corp-branch-staff")
if el_wf_br:
el_wf_br.innerText = f"{wf['call_center_agents']:,}"
el_wf_ld = document.getElementById("display-corp-leaders")
if el_wf_ld:
el_wf_ld.innerText = f"{wf['branch_leads'] + wf['executive_leaders']:,}"
tot_wf = max(1, wf["total"])
def set_headcount_bar(cnt_id, bar_id, count, label_suffix="Staff"):
el_c = document.getElementById(cnt_id)
el_b = document.getElementById(bar_id)
if el_c:
el_c.innerText = f"{count:,} {label_suffix}"
if el_b:
pct = min(100.0, max(5.0 if count > 0 else 0.0, (count / tot_wf) * 100.0))
el_b.style.width = f"{pct:.1f}%"
set_headcount_bar("lbl-dept-cc-count", "bar-dept-cc", wf["call_center_agents"], "Agents")
set_headcount_bar("lbl-dept-hd-count", "bar-dept-hd", wf["support_specialists"], "Techs")
set_headcount_bar("lbl-dept-dc-count", "bar-dept-dc", wf["dc_engineers"], "Engineers")
set_headcount_bar("lbl-dept-corp-count", "bar-dept-corp", wf["corporate_researchers"], "Staff")
set_headcount_bar("lbl-dept-lead-count", "bar-dept-lead", wf["branch_leads"] + wf["executive_leaders"], "Directors")
set_headcount_bar("lbl-dept-core-count", "bar-dept-core", wf["core_techs"], "Techs")
# Update Policies & R&D Tab Header & OpEx (Phase 3+)
if engine.phase >= 3:
badge_rp = document.getElementById("display-policies-rp-badge")
if badge_rp:
badge_rp.innerText = f"RP: {engine.research_points:.1f} / {engine.get_max_research_points():.0f}"
policy_burn = 0.0
if "cloud_migration" in engine.active_it_policies:
policy_burn += 0.25
if "on_call_rotation" in engine.active_it_policies:
policy_burn += 0.20
if "ai_escalation" in engine.active_it_policies or "ai_auto_escalate" in engine.active_it_policies:
policy_burn += 0.75
el_p_burn = document.getElementById("display-cto-policy-burn")
if el_p_burn:
el_p_burn.innerText = f"-${policy_burn:.2f}/s"
# Synchronize Corporate IT Policy Governance Switches & Corporate HQ requirements
has_corp_hq = engine.phase3_facilities.get("corporate", 0) >= 1
badge_hq = document.getElementById("badge-policy-hq-req")
if badge_hq:
if has_corp_hq:
badge_hq.className = "badge bg-success bg-opacity-75 py-2 px-3 border border-success"
badge_hq.innerText = "ποΈ Corporate HQ Online (Policies Active)"
else:
badge_hq.className = "badge bg-warning bg-opacity-75 py-2 px-3 border border-warning text-dark"
badge_hq.innerText = "ποΈ Requires 1 Corporate HQ Facility"
policy_switch_map = {
"switch-policy-zero_trust_mfa": "zero_trust_mfa",
"switch-policy-standard_soe": "standard_soe",
"switch-policy-cloud_migration": "cloud_migration",
"switch-policy-cicd_automation": "cicd_automation",
"switch-policy-on_call_rotation": "on_call_rotation",
"switch-policy-ai_escalation": "ai_escalation"
}
for el_id, p_key in policy_switch_map.items():
sw = document.getElementById(el_id)
if sw:
is_active = (p_key in engine.active_it_policies) or \
(p_key == "cicd_automation" and "cicd_devops" in engine.active_it_policies) or \
(p_key == "ai_escalation" and "ai_auto_escalate" in engine.active_it_policies)
sw.checked = is_active
sw.disabled = not has_corp_hq
# Update Tech Manuals & Certifications HUD
doc_section_visible = (engine.phase > 1 or engine.get_progression_tier() >= 2)
if doc_section_visible:
document.getElementById("display-manuals-count").innerText = f"{engine.tech_manuals} Manuals"
manual_rate = 0.50 * engine.tech_manuals
document.getElementById("display-manuals-income").innerText = f"+${manual_rate:.2f}/s passive"
manual_cost = engine.get_manual_kb_cost()
btn_manual = document.getElementById("btn-publish-manual")
btn_manual.innerText = f"π Publish Manual ({manual_cost} KB)"
if engine.kb_articles >= manual_cost and not engine.burnout and not engine.pc_crashed and not engine.is_rebooting:
btn_manual.removeAttribute("disabled")
else:
btn_manual.setAttribute("disabled", "true")
# AI Documenter Progressive Controls (Operations tab)
ai_doc_panel = document.getElementById("panel-ai-documenter")
if ai_doc_panel:
ai_doc_lvl = engine.upgrades.get("ai_documenter", 0)
if ai_doc_lvl > 0:
ai_doc_panel.style.display = "block"
lvl_badge = document.getElementById("badge-ai-documenter-level")
if lvl_badge:
lvl_badge.innerText = f"Lvl {ai_doc_lvl}"
cfg = resources.AI_DOCUMENTER_CONFIG.get(ai_doc_lvl, resources.AI_DOCUMENTER_CONFIG[1])
# Subroutine 1: Auto-Research
for sw_id in ["switch-ai-auto-research", "switch-auto-research"]:
sw_res = document.getElementById(sw_id)
if sw_res:
sw_res.checked = getattr(engine, "auto_research_active", False)
lbl_res_sub = document.getElementById("lbl-auto-research-sub")
if lbl_res_sub:
lbl_res_sub.innerText = f"1 Ticket β +{cfg['kp_gain']:.0f} KP / {cfg['interval_sec']:.0f}s (${cfg['cash_drain_per_sec']:.2f}/s)"
# Subroutine 2: Auto-KB Articles
for sw_id in ["switch-ai-auto-kb", "switch-auto-kb"]:
sw_kb = document.getElementById(sw_id)
if sw_kb:
sw_kb.checked = getattr(engine, "auto_kb_active", False)
# Subroutine 3: Auto-Manuals
for sw_id in ["switch-ai-auto-manuals", "switch-auto-manuals"]:
sw_man = document.getElementById(sw_id)
if sw_man:
if ai_doc_lvl >= 2:
sw_man.removeAttribute("disabled")
sw_man.checked = getattr(engine, "auto_manuals_active", False)
else:
sw_man.setAttribute("disabled", "true")
sw_man.checked = False
lbl_man_sub = document.getElementById("lbl-auto-manuals-sub")
if lbl_man_sub:
if ai_doc_lvl >= 2:
lbl_man_sub.className = "text-info font-monospace"
lbl_man_sub.innerText = f"{cfg.get('manual_kb_cost', 3)} KB β 1 Manual / {cfg.get('manual_interval_sec', 45):.0f}s"
else:
lbl_man_sub.className = "text-warning font-monospace"
lbl_man_sub.innerText = "π Req: Lvl 2 Documenter"
# Subroutine 4: Auto-Courses
for sw_id in ["switch-ai-auto-courses", "switch-auto-courses"]:
sw_crs = document.getElementById(sw_id)
if sw_crs:
if ai_doc_lvl >= 3:
sw_crs.removeAttribute("disabled")
sw_crs.checked = getattr(engine, "auto_courses_active", False)
else:
sw_crs.setAttribute("disabled", "true")
sw_crs.checked = False
lbl_crs_sub = document.getElementById("lbl-auto-courses-sub")
if lbl_crs_sub:
if ai_doc_lvl >= 3:
lbl_crs_sub.className = "text-info font-monospace"
lbl_crs_sub.innerText = f"{engine.get_course_manual_cost()} Manuals β 1 Course / 60s"
else:
lbl_crs_sub.className = "text-warning font-monospace"
lbl_crs_sub.innerText = "π Req: Lvl 3 Documenter"
else:
ai_doc_panel.style.display = "none"
# Auto-Dispatch Controls (Incident Dispatcher Board)
lock_ad = document.getElementById("lock-auto-dispatch")
container_ad = document.getElementById("container-switch-auto-dispatch")
sw_ad = document.getElementById("switch-auto-dispatch")
has_ad_software = engine.upgrades.get("auto_dispatcher_software", 0) > 0
if has_ad_software:
if lock_ad: lock_ad.style.display = "none"
if container_ad: container_ad.style.display = "block"
if sw_ad: sw_ad.checked = getattr(engine, "auto_dispatch", False)
else:
if lock_ad: lock_ad.style.display = "inline-block"
if container_ad: container_ad.style.display = "none"
if sw_ad: sw_ad.checked = False
container_cert = document.getElementById("container-cert-courses")
if engine.phase >= 2:
container_cert.style.display = "block"
document.getElementById("display-courses-count").innerText = f"{engine.certification_courses} Courses"
course_rate = 5.00 * engine.certification_courses
course_cp = 1.0 * engine.certification_courses
document.getElementById("display-courses-income").innerText = f"+${course_rate:.2f}/s, +{course_cp:.1f} CP/m"
course_cost = engine.get_course_manual_cost()
btn_course = document.getElementById("btn-publish-course")
btn_course.innerText = f"π Publish Course ({course_cost} Manuals)"
if engine.tech_manuals >= course_cost and not engine.burnout and not engine.pc_crashed and not engine.is_rebooting:
btn_course.removeAttribute("disabled")
else:
btn_course.setAttribute("disabled", "true")
else:
container_cert.style.display = "none"
# Dynamic stable incident board rendering (in-place updates to eliminate DOM rebuilding & flickering)
tbody = document.getElementById("incidents-board-body")
if not engine.active_incidents:
tbody.innerHTML = '
π’ Incidents Queue Empty! Techs standby...
'
else:
# Clear empty queue placeholder if present
empty_ph = tbody.querySelector("td[colspan='5']")
if empty_ph:
tbody.innerHTML = ""
active_ids = {inc["id"] for inc in engine.active_incidents}
# Remove completed/expired incident rows
existing_rows = list(tbody.querySelectorAll("tr[id^='inc-row-']"))
for r in existing_rows:
r_id = r.id.replace("inc-row-", "")
if r_id not in active_ids:
r.remove()
for inc in engine.active_incidents:
inc_id = inc["id"]
cat = inc["category"]
sev = inc["severity"]
sla_rem = inc["sla_remaining"]
sla_max = inc["sla_max"]
progress = inc["progress"]
assigned = inc.get("assigned_to")
assigned_tech = next((t for t in engine.tech_roster if t["id"] == assigned or t.get("role") == assigned), None)
assigned_role = assigned_tech.get("role") if assigned_tech else (assigned if assigned else None)
assigned_name = assigned_tech.get("name") if assigned_tech else ("Unassigned" if not assigned else str(assigned))
sev_class = "bg-success" if sev == "low" else ("bg-warning text-dark" if sev == "medium" else "bg-danger")
sla_pct = min(100.0, max(0.0, (sla_rem / sla_max) * 100.0))
sla_bar_class = "bg-success" if sla_pct > 50.0 else ("bg-warning" if sla_pct > 25.0 else "bg-danger progress-bar-striped progress-bar-animated")
total_l1 = len([t for t in engine.tech_roster if t.get("role") == "l1_tech"]) or engine.upgrades.get("l1_techs", 0)
total_l2 = len([t for t in engine.tech_roster if t.get("role") == "l2_tech"]) or engine.upgrades.get("l2_techs", 0)
total_sys = len([t for t in engine.tech_roster if t.get("role") == "sysadmin"]) or engine.upgrades.get("sysadmins", 0)
total_onsite = len([t for t in engine.tech_roster if t.get("role") == "onsite_tech"]) or len(getattr(engine, "hired_onsite_techs", []))
l1_disabled = not (total_l1 > 0 and sev == "low")
l2_disabled = not (total_l2 > 0 and sev in ["low", "medium"])
sys_disabled = not (total_sys > 0)
onsite_disabled = not (total_onsite > 0)
row_el = document.getElementById(f"inc-row-{inc_id}")
if not row_el:
row_html = f"""
{cat}
{f'π€ {assigned_name}' if assigned else 'β³ Unassigned'}
{sev.upper()}
{sla_rem:.1f}s
{progress:.1f}%
"""
tbody.insertAdjacentHTML("beforeend", row_html)
# Perform in-place updates without replacing HTML elements
tech_txt = document.getElementById(f"inc-tech-text-{inc_id}")
if tech_txt:
tech_txt.innerHTML = f'π€ {assigned_name}' if assigned else 'β³ Unassigned'
sla_bar = document.getElementById(f"inc-sla-bar-{inc_id}")
if sla_bar:
sla_bar.style.width = f"{sla_pct}%"
sla_bar.className = f"progress-bar {sla_bar_class}"
sla_txt = document.getElementById(f"inc-sla-text-{inc_id}")
if sla_txt:
sla_txt.innerText = f"{sla_rem:.1f}s"
prog_bar = document.getElementById(f"inc-prog-bar-{inc_id}")
if prog_bar:
prog_bar.style.width = f"{progress:.1f}%"
prog_txt = document.getElementById(f"inc-prog-text-{inc_id}")
if prog_txt:
prog_txt.innerText = f"{progress:.1f}%"
# Update button classes and disabled states in-place
l1_btn = document.getElementById(f"btn-inc-l1-{inc_id}")
if l1_btn:
l1_btn.className = f"btn {'btn-info text-dark fw-bold' if (assigned_role == 'l1_tech' or str(assigned).startswith('l1_')) else 'btn-outline-secondary'} px-2 py-0 fw-bold"
if l1_disabled:
l1_btn.setAttribute("disabled", "true")
else:
l1_btn.removeAttribute("disabled")
l2_btn = document.getElementById(f"btn-inc-l2-{inc_id}")
if l2_btn:
l2_btn.className = f"btn {'btn-primary fw-bold' if (assigned_role == 'l2_tech' or str(assigned).startswith('l2_')) else 'btn-outline-secondary'} px-2 py-0 fw-bold"
if l2_disabled:
l2_btn.setAttribute("disabled", "true")
else:
l2_btn.removeAttribute("disabled")
sys_btn = document.getElementById(f"btn-inc-sys-{inc_id}")
if sys_btn:
sys_btn.className = f"btn {'btn-warning text-dark fw-bold' if (assigned_role == 'sysadmin' or str(assigned).startswith('sys_')) else 'btn-outline-secondary'} px-2 py-0 fw-bold"
if sys_disabled:
sys_btn.setAttribute("disabled", "true")
else:
sys_btn.removeAttribute("disabled")
onsite_btn = document.getElementById(f"btn-inc-onsite-{inc_id}")
if onsite_btn:
is_onsite_assigned = (assigned_role == 'onsite_tech' or str(assigned).startswith('onsite_'))
onsite_btn.className = f"btn {'btn-success text-white fw-bold' if is_onsite_assigned else 'btn-outline-secondary'} px-2 py-0 fw-bold"
if onsite_disabled:
onsite_btn.setAttribute("disabled", "true")
else:
onsite_btn.removeAttribute("disabled")
clear_btn = document.getElementById(f"btn-inc-clear-{inc_id}")
if clear_btn:
clear_btn.className = f"btn {'btn-outline-danger' if assigned is not None else 'btn-outline-secondary'} px-2 py-0 fw-bold"
if assigned is None:
clear_btn.setAttribute("disabled", "true")
else:
clear_btn.removeAttribute("disabled")
# Render Mobile Incident Cards (< 768px)
mobile_pane = document.getElementById("incidents-board-mobile")
if mobile_pane:
if not engine.active_incidents:
mobile_pane.innerHTML = '
π’ Incidents Queue Empty! Techs standby...
'
else:
active_ids = {inc["id"] for inc in engine.active_incidents}
for c in list(mobile_pane.querySelectorAll("div[id^='inc-card-']")):
c_id = c.id.replace("inc-card-", "")
if c_id not in active_ids:
c.remove()
for inc in engine.active_incidents:
inc_id = inc["id"]
cat = inc["category"]
sev = inc["severity"]
sla_rem = inc["sla_remaining"]
sla_max = inc["sla_max"]
progress = inc["progress"]
assigned = inc.get("assigned_to")
assigned_tech = next((t for t in engine.tech_roster if t["id"] == assigned or t.get("role") == assigned), None)
assigned_role = assigned_tech.get("role") if assigned_tech else (assigned if assigned else None)
assigned_name = assigned_tech.get("name") if assigned_tech else ("Unassigned" if not assigned else str(assigned))
sev_class = "bg-success" if sev == "low" else ("bg-warning text-dark" if sev == "medium" else "bg-danger")
sla_pct = min(100.0, max(0.0, (sla_rem / sla_max) * 100.0))
sla_bar_class = "bg-success" if sla_pct > 50.0 else ("bg-warning" if sla_pct > 25.0 else "bg-danger progress-bar-striped progress-bar-animated")
total_l1 = len([t for t in engine.tech_roster if t.get("role") == "l1_tech"]) or engine.upgrades.get("l1_techs", 0)
total_l2 = len([t for t in engine.tech_roster if t.get("role") == "l2_tech"]) or engine.upgrades.get("l2_techs", 0)
total_sys = len([t for t in engine.tech_roster if t.get("role") == "sysadmin"]) or engine.upgrades.get("sysadmins", 0)
total_onsite = len([t for t in engine.tech_roster if t.get("role") == "onsite_tech"]) or len(getattr(engine, "hired_onsite_techs", []))
l1_disabled = not (total_l1 > 0 and sev == "low")
l2_disabled = not (total_l2 > 0 and sev in ["low", "medium"])
sys_disabled = not (total_sys > 0)
onsite_disabled = not (total_onsite > 0)
card_el = document.getElementById(f"inc-card-{inc_id}")
if not card_el:
card_html = f"""
{cat}{sev.upper()}
SLA:
{sla_rem:.1f}s
Prog:
{progress:.0f}%
Assign:
"""
mobile_pane.insertAdjacentHTML("beforeend", card_html)
c_sla_bar = document.getElementById(f"inc-sla-card-bar-{inc_id}")
if c_sla_bar:
c_sla_bar.style.width = f"{sla_pct}%"
c_sla_bar.className = f"progress-bar {sla_bar_class}"
c_sla_txt = document.getElementById(f"inc-sla-card-text-{inc_id}")
if c_sla_txt:
c_sla_txt.innerText = f"{sla_rem:.1f}s"
c_prog_bar = document.getElementById(f"inc-prog-card-bar-{inc_id}")
if c_prog_bar:
c_prog_bar.style.width = f"{progress:.1f}%"
c_prog_txt = document.getElementById(f"inc-prog-card-text-{inc_id}")
if c_prog_txt:
c_prog_txt.innerText = f"{progress:.0f}%"
sel = document.getElementById(f"inc-assign-select-{inc_id}")
if sel:
cur_val = assigned_role if assigned_role in ["l1_tech", "l2_tech", "sysadmin", "onsite_tech"] else ("none" if not assigned else "l1_tech")
if not assigned:
cur_val = "none"
if sel.value != cur_val:
sel.value = cur_val
# Research button state
btn_res = document.getElementById("btn-research")
if btn_res:
if engine.burnout or engine.pc_crashed or engine.is_rebooting or is_busy or engine.knowledge_points >= engine.get_max_kp() or engine.solved_tickets_inventory < 1:
btn_res.setAttribute("disabled", "true")
else:
btn_res.removeAttribute("disabled")
# Achievements badges list
for ach_id in engine.achievements:
ach_el = document.getElementById(f"ach-{ach_id}")
if ach_el:
if engine.achievements[ach_id]:
ach_el.className = "list-group-item d-flex justify-content-between align-items-center bg-dark text-white border-success mb-2 p-3 rounded"
status_icon = ach_el.querySelector(".achievement-status")
if status_icon:
status_icon.innerHTML = "π’ Unlocked"
status_icon.className = "badge bg-success achievement-status"
else:
ach_el.className = "list-group-item d-flex justify-content-between align-items-center bg-dark text-muted mb-2 p-3 rounded"
status_icon = ach_el.querySelector(".achievement-status")
if status_icon:
status_icon.innerHTML = "π Locked"
status_icon.className = "badge bg-secondary achievement-status"
# Re-evaluate upgrades subtabs and automation console switches
upgrade_subtabs = document.getElementById("upgradeSubTabs")
if engine.phase >= 2:
upgrade_subtabs.style.display = "flex"
else:
upgrade_subtabs.style.display = "none"
panel_ai = document.getElementById("panel-ai-documenter")
if panel_ai:
if engine.upgrades.get("ai_documenter", 0) > 0:
panel_ai.style.display = "block"
sw_res = document.getElementById("switch-auto-research")
if sw_res:
sw_res.checked = engine.auto_research_active
sw_kb = document.getElementById("switch-auto-kb")
if sw_kb:
sw_kb.checked = engine.auto_kb_active
else:
panel_ai.style.display = "none"
# Phase 3 CTO View vs Phase 4 Enterprise View vs Standard View & Sidebar Hardware HUD
ops_std = document.getElementById("operations-standard-view")
ops_cto = document.getElementById("operations-cto-view")
ops_ent = document.getElementById("operations-enterprise-view")
if ops_std and ops_ent:
if engine.phase >= 4:
ops_std.style.display = "none"
if ops_cto:
ops_cto.style.display = "none"
ops_ent.style.display = "block"
elif engine.phase == 3:
ops_std.style.display = "none"
if ops_cto:
ops_cto.style.display = "block"
ops_ent.style.display = "none"
else:
ops_std.style.display = "block"
if ops_cto:
ops_cto.style.display = "none"
ops_ent.style.display = "none"
# Phase 3 CTO Command Suite In-Place UI Updates
if engine.phase == 3:
# 1. Executive Aura
badge_aura = document.getElementById("badge-cto-aura")
txt_aura_cd = document.getElementById("txt-cto-aura-cd")
if badge_aura and txt_aura_cd:
if engine.executive_aura_duration > 0.0:
badge_aura.style.display = "inline-block"
txt_aura_cd.innerText = f"{engine.executive_aura_duration:.1f}s"
else:
badge_aura.style.display = "none"
# 2. Comprehensive Company-Wide Telemetry Matrix
el_cash_val = document.getElementById("display-cto-cash-val")
if el_cash_val:
el_cash_val.innerText = f"${engine.cash:,.2f}"
el_cash_flow = document.getElementById("display-cto-cash-flow")
if el_cash_flow:
mrr_sec = engine.get_mrr() / 2592000.0 if hasattr(engine, "get_mrr") else 0.0
fac_opex = engine.get_phase3_facilities_opex()
tech_wages = engine.get_total_wages() if hasattr(engine, "get_total_wages") else 0.0
net_sec = mrr_sec - fac_opex - tech_wages
sign_f = "+" if net_sec >= 0 else "-"
el_cash_flow.innerText = f"{sign_f}${abs(net_sec):,.2f}/s net"
el_cash_flow.className = "text-success font-monospace d-block" if net_sec >= 0 else "text-danger font-monospace d-block"
el_staff_cnt = document.getElementById("display-cto-staff-count")
if el_staff_cnt:
el_staff_cnt.innerText = f"{engine.get_enterprise_headcount():,} Employees"
el_mgr_cnt = document.getElementById("display-cto-mgr-count")
if el_mgr_cnt:
hired_mgrs = len([b for b in engine.branch_managers.values() if b.get("hired")])
el_mgr_cnt.innerText = f"{hired_mgrs}/4 Branch Leads"
el_stress_val = document.getElementById("display-cto-stress-val")
if el_stress_val:
el_stress_val.innerText = f"{engine.stress:.1f}%"
bar_stress = document.getElementById("bar-cto-stress")
if bar_stress:
bar_stress.style.width = f"{min(100.0, engine.stress):.1f}%"
bar_stress.className = "progress-bar bg-danger" if engine.burnout or engine.stress > 75 else ("progress-bar bg-warning" if engine.stress > 40 else "progress-bar bg-success")
badge_stress_st = document.getElementById("badge-cto-stress-status")
if badge_stress_st:
if engine.burnout:
badge_stress_st.className = "badge bg-danger"
badge_stress_st.innerText = "BURNOUT"
elif engine.stress > 60:
badge_stress_st.className = "badge bg-warning text-dark"
badge_stress_st.innerText = "HIGH"
else:
badge_stress_st.className = "badge bg-secondary"
badge_stress_st.innerText = "NORMAL"
el_csi_val = document.getElementById("display-cto-csi-val")
if el_csi_val:
el_csi_val.innerText = f"{getattr(engine, 'customer_satisfaction', 100.0):.1f}% CSI"
el_sla_val = document.getElementById("display-cto-sla-val")
if el_sla_val:
el_sla_val.innerText = f"{getattr(engine, 'sla_breaches_total', 0)} SLA Breaches"
el_tot_fac = document.getElementById("display-cto-total-facilities")
if el_tot_fac:
el_tot_fac.innerText = f"{sum(engine.phase3_facilities.values())} Active"
el_fac_opex = document.getElementById("display-cto-facility-opex")
if el_fac_opex:
el_fac_opex.innerText = f"-${engine.get_phase3_facilities_opex():.2f}/s OpEx"
el_cto_vel = document.getElementById("display-cto-solve-velocity")
if el_cto_vel:
el_cto_vel.innerText = f"{1.0 + engine.phase3_facilities.get('helpdesk', 0)*0.25:.1f}/s Vel"
el_q_cnt = document.getElementById("display-cto-queue-count")
if el_q_cnt:
el_q_cnt.innerText = f"{engine.tickets_queue} in Queue"
el_cto_kp_ov = document.getElementById("display-cto-kp-val")
if el_cto_kp_ov:
el_cto_kp_ov.innerText = f"{engine.knowledge_points:,.1f} KP"
el_cto_rd_nodes = document.getElementById("display-cto-rd-nodes")
if el_cto_rd_nodes:
el_cto_rd_nodes.innerText = f"{len(engine.rd_techs_unlocked)}/9 Techs Researched"
el_mrr_val = document.getElementById("display-cto-mrr-val")
if el_mrr_val:
mrr_val = engine.get_mrr() if hasattr(engine, "get_mrr") else 0.0
el_mrr_val.innerText = f"${mrr_val:,.2f}/mo"
el_debt_val = document.getElementById("display-cto-debt-val")
if el_debt_val:
debt = getattr(engine, "total_debt", getattr(engine, "loan_principal", 0.0))
el_debt_val.innerText = f"${debt:,.2f} Loan Debt"
# Infrastructure Governor & SLA Compliance Console
infra = engine.get_infra_status() if hasattr(engine, "get_infra_status") else {}
b_sla = document.getElementById("badge-infra-sla")
if b_sla and "sla_uptime_pct" in infra:
sla_val = infra["sla_uptime_pct"]
if sla_val >= 99.99:
b_sla.className = "badge bg-success font-monospace fs-6 px-3 py-2 fw-bold"
b_sla.innerText = f"{sla_val:.3f}% SLA (FIVE NINES)"
elif sla_val >= 99.0:
b_sla.className = "badge bg-warning text-dark font-monospace fs-6 px-3 py-2 fw-bold"
b_sla.innerText = f"{sla_val:.3f}% SLA (WARNING)"
else:
b_sla.className = "badge bg-danger font-monospace fs-6 px-3 py-2 fw-bold"
b_sla.innerText = f"{sla_val:.3f}% SLA (BREACH)"
# Live Financial Cashflow & Revenue Breakdown calculation & DOM update
tf = current_cashflow_timeframe
mode = current_cashflow_mode
# Timeframe units and multipliers (1 in-game day = 216s, 1 month = 6480s, 1 quarter = 19440s, 1 year = 77760s)
tf_labels = {
"sec": "/s",
"day": "/day",
"month": "/mo",
"quarter": "/Q",
"year": "/yr"
}
unit_str = tf_labels.get(tf, "/s")
if mode == "real":
# Real continuous flows (actual delta per real-time second multiplied by timeframe duration)
real_seconds_map = {
"sec": 1.0,
"day": 216.0,
"month": 6480.0,
"quarter": 19440.0,
"year": 77760.0
}
tf_mult = real_seconds_map.get(tf, 1.0)
contracts_inflow = (engine.get_mrr() / 6480.0) * tf_mult
ticket_tps = engine.get_company_ticket_throughput_rate()
avg_tix_payout = resources.get_ticket_cash_value("low", engine.upgrades.get("dual_monitors", 0), engine.xp, engine.sla, engine.kb_articles, engine.upgrades.get("ticket_payout_boost", 0), engine.csi)
tickets_inflow = ticket_tps * avg_tix_payout * tf_mult
sla_bonus_inflow = 0.0
if infra.get("sla_uptime_pct", 100.0) >= 99.99:
sla_bonus_inflow = (contracts_inflow + tickets_inflow) * 0.15
total_inflow = contracts_inflow + tickets_inflow + sla_bonus_inflow
fac_opex = engine.get_phase3_facilities_opex() * tf_mult
mgmt_salary_sec = 0.0
for b_id, b_data in engine.branch_managers.items():
if b_data.get("hired"):
spec = resources.CALL_CENTER_BRANCHES.get(b_id, {})
dir_k = b_data.get("directive", "quality")
dir_spec = resources.BRANCH_DIRECTIVE_SPECS.get(dir_k, {})
mgmt_salary_sec += spec.get("base_salary", 0.35) * dir_spec.get("salary_mult", 1.0)
comp_spec = resources.CTO_COMPENSATION_POLICIES.get(engine.cto_staffing_policy, {})
salary_mult = comp_spec.get("salary_mult", 1.0)
mgmt_salary_sec += sum(engine.cto_hired_leadership.get(r, 0) * spec["base_salary"] * salary_mult for r, spec in getattr(resources, "CTO_LEADERSHIP_ROLES", {}).items())
mgmt_salary = mgmt_salary_sec * tf_mult
tech_payroll = getattr(engine, "team_wage_burn_rate", 0.0) * tf_mult
policy_opex_sec = 0.0
for pol in engine.active_it_policies:
pol_spec = getattr(resources, "IT_POLICIES_REGISTRY", {}).get(pol, {})
policy_opex_sec += pol_spec.get("opex_per_sec", 0.0)
policy_opex = policy_opex_sec * tf_mult
total_outflow = fac_opex + mgmt_salary + tech_payroll + policy_opex
else:
# Calendar Accounting Run-Rate (Monthly run-rate scaled to nominal accounting periods)
cal_mult_map = {
"sec": 1.0 / 6480.0,
"day": 1.0 / 30.0,
"month": 1.0,
"quarter": 3.0,
"year": 12.0
}
tf_mult = cal_mult_map.get(tf, 1.0)
mrr_nominal = engine.get_mrr()
contracts_inflow = mrr_nominal * tf_mult
ticket_tps = engine.get_company_ticket_throughput_rate()
avg_tix_payout = resources.get_ticket_cash_value("low", engine.upgrades.get("dual_monitors", 0), engine.xp, engine.sla, engine.kb_articles, engine.upgrades.get("ticket_payout_boost", 0), engine.csi)
# 1 nominal month = 6480s of ticket velocity
tickets_inflow = ticket_tps * avg_tix_payout * 6480.0 * tf_mult
sla_bonus_inflow = 0.0
if infra.get("sla_uptime_pct", 100.0) >= 99.99:
sla_bonus_inflow = (contracts_inflow + tickets_inflow) * 0.15
total_inflow = contracts_inflow + tickets_inflow + sla_bonus_inflow
fac_opex = engine.get_phase3_facilities_opex() * 6480.0 * tf_mult
mgmt_salary_sec = 0.0
for b_id, b_data in engine.branch_managers.items():
if b_data.get("hired"):
spec = resources.CALL_CENTER_BRANCHES.get(b_id, {})
dir_k = b_data.get("directive", "quality")
dir_spec = resources.BRANCH_DIRECTIVE_SPECS.get(dir_k, {})
mgmt_salary_sec += spec.get("base_salary", 0.35) * dir_spec.get("salary_mult", 1.0)
comp_spec = resources.CTO_COMPENSATION_POLICIES.get(engine.cto_staffing_policy, {})
salary_mult = comp_spec.get("salary_mult", 1.0)
mgmt_salary_sec += sum(engine.cto_hired_leadership.get(r, 0) * spec["base_salary"] * salary_mult for r, spec in getattr(resources, "CTO_LEADERSHIP_ROLES", {}).items())
mgmt_salary = mgmt_salary_sec * 6480.0 * tf_mult
tech_payroll = getattr(engine, "team_wage_burn_rate", 0.0) * 6480.0 * tf_mult
policy_opex_sec = 0.0
for pol in engine.active_it_policies:
pol_spec = getattr(resources, "IT_POLICIES_REGISTRY", {}).get(pol, {})
policy_opex_sec += pol_spec.get("opex_per_sec", 0.0)
policy_opex = policy_opex_sec * 6480.0 * tf_mult
total_outflow = fac_opex + mgmt_salary + tech_payroll + policy_opex
net_val = total_inflow - total_outflow
el_subnote = document.getElementById("txt-breakdown-subnote")
if el_subnote:
if mode == "real":
el_subnote.innerText = "β‘ Real Continuous: Actual real-time funds flowing into/out of your bank balance (1 game day = 216s, 1 game month = 6,480s)."
else:
el_subnote.innerText = "π Accounting Run-Rate: Nominal periodic run-rate metrics (30 days/month, 90 days/quarter, 360 days/year)."
el_net_badge = document.getElementById("display-breakdown-net-badge")
if el_net_badge:
sign = "+" if net_val >= 0 else "-"
el_net_badge.className = f"badge font-monospace {'bg-success' if net_val >= 0 else 'bg-danger'}"
el_net_badge.innerText = f"Net: {sign}${abs(net_val):,.2f}{unit_str}"
el_inflow_tot = document.getElementById("display-breakdown-total-income")
if el_inflow_tot: el_inflow_tot.innerText = f"+${total_inflow:,.2f}{unit_str}"
el_inflow_c = document.getElementById("display-breakdown-contracts")
if el_inflow_c: el_inflow_c.innerText = f"+${contracts_inflow:,.2f}{unit_str}"
el_inflow_t = document.getElementById("display-breakdown-tickets")
if el_inflow_t: el_inflow_t.innerText = f"+${tickets_inflow:,.2f}{unit_str}"
el_inflow_s = document.getElementById("display-breakdown-sla-bonus")
if el_inflow_s: el_inflow_s.innerText = f"+${sla_bonus_inflow:,.2f}{unit_str}"
el_outflow_tot = document.getElementById("display-breakdown-total-expense")
if el_outflow_tot: el_outflow_tot.innerText = f"-${total_outflow:,.2f}{unit_str}"
el_outflow_f = document.getElementById("display-breakdown-fac-opex")
if el_outflow_f: el_outflow_f.innerText = f"-${fac_opex:,.2f}{unit_str}"
el_outflow_m = document.getElementById("display-breakdown-mgmt-salary")
if el_outflow_m: el_outflow_m.innerText = f"-${mgmt_salary:,.2f}{unit_str}"
el_outflow_p = document.getElementById("display-breakdown-tech-payroll")
if el_outflow_p: el_outflow_p.innerText = f"-${tech_payroll:,.2f}{unit_str}"
el_outflow_pol = document.getElementById("display-breakdown-policy-opex")
if el_outflow_pol: el_outflow_pol.innerText = f"-${policy_opex:,.2f}{unit_str}"
el_strain = document.getElementById("display-infra-strain-val")
if el_strain and "thermal_strain" in infra:
el_strain.innerText = f"{infra['thermal_strain']:.1f}%"
bar_strain = document.getElementById("bar-infra-strain")
if bar_strain and "thermal_strain" in infra:
s_val = infra["thermal_strain"]
bar_strain.style.width = f"{s_val:.1f}%"
bar_strain.className = "progress-bar " + ("bg-danger" if s_val >= 80 else ("bg-warning" if s_val >= 50 else "bg-info"))
el_cool = document.getElementById("display-infra-cooling-val")
if el_cool and "cooling_capacity" in infra:
el_cool.innerText = f"+{infra['cooling_capacity']:.1f}/s"
txt_maint = document.getElementById("txt-infra-maint-cd")
btn_maint = document.getElementById("btn-infra-maintenance")
if txt_maint and btn_maint and "cooldown_remaining" in infra:
cd = infra["cooldown_remaining"]
if cd > 0.0:
txt_maint.innerText = f"{cd:.0f}s CD"
btn_maint.disabled = True
else:
txt_maint.innerText = "READY"
btn_maint.disabled = (engine.burnout or engine.pc_crashed or engine.is_rebooting)
# Mode buttons active state
cur_mode = getattr(engine, "infra_governor_mode", "nominal")
for m_k in ["eco", "nominal", "turbo"]:
b_m = document.getElementById(f"btn-infra-mode-{m_k}")
if b_m:
spec = resources.INFRASTRUCTURE_GOVERNOR_MODES.get(m_k, {})
outline_cls = spec.get("badge_class", "bg-primary").replace("bg-", "btn-outline-")
if cur_mode == m_k:
b_m.className = f"btn {outline_cls} active w-100 p-2 text-start h-100"
else:
b_m.className = f"btn {outline_cls} w-100 p-2 text-start h-100"
# 2.5 Executive Company-Wide Telemetry KPI Cards
el_cto_cash = document.getElementById("display-cto-cash-val")
if el_cto_cash: el_cto_cash.innerText = f"${engine.cash:,.2f}"
el_cto_cflow = document.getElementById("display-cto-cash-flow")
if el_cto_cflow:
sign_cf = "+" if net_val >= 0 else "-"
el_cto_cflow.innerText = f"{sign_cf}${abs(net_val):,.2f}/s net"
el_cto_cflow.className = f"font-monospace d-block {'text-success' if net_val >= 0 else 'text-danger'}"
wf = engine.get_company_workforce_breakdown() if hasattr(engine, "get_company_workforce_breakdown") else {}
el_cto_staff = document.getElementById("display-cto-staff-count")
if el_cto_staff: el_cto_staff.innerText = f"{wf.get('total_workforce', 0):,} Staff"
el_cto_mgr = document.getElementById("display-cto-mgr-count")
if el_cto_mgr:
hired_mgrs = len([b for b in getattr(engine, 'branch_managers', {}).values() if b.get('hired')])
el_cto_mgr.innerText = f"{hired_mgrs}/4 Branch Leads"
el_cto_stress = document.getElementById("display-cto-stress-val")
if el_cto_stress: el_cto_stress.innerText = f"{engine.stress:.1f}%"
bar_cto_stress = document.getElementById("bar-cto-stress")
if bar_cto_stress:
bar_cto_stress.style.width = f"{engine.stress:.1f}%"
bar_cto_stress.className = "progress-bar " + ("bg-danger" if engine.stress >= 80 else ("bg-warning" if engine.stress >= 50 else "bg-success"))
badge_cto_stress = document.getElementById("badge-cto-stress-status")
if badge_cto_stress:
if engine.burnout:
badge_cto_stress.className = "badge bg-danger"
badge_cto_stress.innerText = "BURNOUT"
elif engine.stress >= 75.0:
badge_cto_stress.className = "badge bg-warning text-dark"
badge_cto_stress.innerText = "HIGH STRESS"
else:
badge_cto_stress.className = "badge bg-success"
badge_cto_stress.innerText = "OPTIMAL"
badge_cto_sla = document.getElementById("badge-cto-sla")
if badge_cto_sla:
badge_cto_sla.innerText = f"SLA {engine.sla:.1f}%"
badge_cto_sla.className = "badge " + ("bg-success bg-opacity-25 text-success" if engine.sla >= 85 else ("bg-warning bg-opacity-25 text-warning" if engine.sla >= 60 else "bg-danger bg-opacity-25 text-danger"))
el_cto_csi = document.getElementById("display-cto-csi-val")
if el_cto_csi: el_cto_csi.innerText = f"{engine.csi:.1f}% CSI"
el_cto_sla = document.getElementById("display-cto-sla-val")
if el_cto_sla: el_cto_sla.innerText = f"SLA: {engine.sla:.1f}% Compliance"
el_cto_fac = document.getElementById("display-cto-total-facilities")
if el_cto_fac: el_cto_fac.innerText = f"{sum(engine.phase3_facilities.values())} Active"
el_cto_fac_op = document.getElementById("display-cto-facility-opex")
if el_cto_fac_op: el_cto_fac_op.innerText = f"-${engine.get_phase3_facilities_opex():,.2f}/s OpEx"
el_cto_vel = document.getElementById("display-cto-solve-velocity")
if el_cto_vel: el_cto_vel.innerText = f"{ticket_tps:.1f}/s Vel"
el_cto_q = document.getElementById("display-cto-queue-count")
if el_cto_q: el_cto_q.innerText = f"{int(engine.tickets_queue):,} in Queue"
badge_cto_q = document.getElementById("badge-cto-queue-status")
if badge_cto_q:
intake_p3 = getattr(engine, "phase3_facilities", {}).get("call_center", 0) * 15.0
if engine.tickets_queue <= 0:
badge_cto_q.className = "badge bg-success bg-opacity-25 text-success"
badge_cto_q.innerText = "CLEAR"
elif ticket_tps > intake_p3:
badge_cto_q.className = "badge bg-info bg-opacity-25 text-info"
badge_cto_q.innerText = "DRAINING"
else:
badge_cto_q.className = "badge bg-warning bg-opacity-25 text-warning"
badge_cto_q.innerText = "FILLING"
el_cto_kp = document.getElementById("display-cto-kp-val")
if el_cto_kp: el_cto_kp.innerText = f"{engine.knowledge_points:,.0f} KP"
el_cto_rd = document.getElementById("display-cto-rd-nodes")
if el_cto_rd: el_cto_rd.innerText = f"{len(engine.rd_techs_unlocked)}/9 Techs Researched"
el_cto_mrr = document.getElementById("display-cto-mrr-val")
if el_cto_mrr: el_cto_mrr.innerText = f"${engine.get_mrr():,.2f}/mo"
el_cto_debt = document.getElementById("display-cto-debt-val")
if el_cto_debt: el_cto_debt.innerText = f"${getattr(engine, 'total_debt', 0.0):,.2f} Loan Debt"
# 3. Facilities Fleet Cards & Construction Queues
fac_registry = getattr(resources, "PHASE3_FACILITIES", getattr(resources, "PHASE3_FACILITIES_CONFIG", {}))
for f_type, cfg in fac_registry.items():
count = engine.phase3_facilities.get(f_type, 0)
cost = engine.get_facility_cost(f_type)
opex = count * cfg.get("operating_cost_per_sec", cfg.get("opex_per_sec", 0.5))
staff_per_fac = cfg.get("staff_per_facility", 10)
el_cnt = document.getElementById(f"display-facility-count-{f_type}")
if el_cnt:
el_cnt.innerText = str(count)
el_op = document.getElementById(f"display-facility-opex-{f_type}")
if el_op:
el_op.innerText = f"-${opex:.2f}/s"
el_fac_staff = document.getElementById(f"display-facility-staff-{f_type}")
if el_fac_staff:
el_fac_staff.innerText = f"{count * staff_per_fac:,}"
el_desc = document.getElementById(f"display-facility-desc-{f_type}")
if el_desc:
if hasattr(resources, "get_facility_description"):
el_desc.innerText = resources.get_facility_description(f_type)
elif "description" in cfg:
el_desc.innerText = cfg["description"]
el_cost_badge = document.getElementById(f"badge-facility-cost-{f_type}")
if el_cost_badge:
el_cost_badge.innerText = f"${cost:,.2f}"
btn_build = document.getElementById(f"btn-build-facility-{f_type}")
container_const = document.getElementById(f"container-construction-{f_type}")
is_building = f_type in getattr(engine, "facility_construction_queues", {})
if is_building:
q = engine.facility_construction_queues[f_type]
rem = max(0.0, q.get("time_remaining", 0.0))
tot = max(1.0, q.get("total_time", 1.0))
pct = max(0.0, min(100.0, ((tot - rem) / tot) * 100.0))
rush_cost = round(q.get("cost", 5000.0) * (rem / tot) * 1.5, 2)
if btn_build:
btn_build.style.display = "none"
if container_const:
container_const.style.display = "block"
t_el = document.getElementById(f"display-construction-time-{f_type}")
if t_el:
t_el.innerText = f"{rem:.0f}s remaining"
bar_el = document.getElementById(f"bar-construction-{f_type}")
if bar_el:
bar_el.style.width = f"{pct:.0f}%"
btn_rush = document.getElementById(f"btn-rush-facility-{f_type}")
if btn_rush:
btn_rush.innerText = f"β‘ Rush Construction (${rush_cost:,.2f})"
btn_rush.disabled = (engine.cash < rush_cost or engine.burnout or engine.pc_crashed or engine.is_rebooting)
else:
if container_const:
container_const.style.display = "none"
if btn_build:
btn_build.style.display = "block"
btn_build.innerText = f"ποΈ Construct {cfg['name']} (${cost:,.2f})"
btn_build.disabled = (engine.cash < cost or engine.burnout or engine.pc_crashed or engine.is_rebooting)
# 4. Corporate IT Policies switches & Panel Gating
el_pol_panel = document.getElementById("panel-policy-governance")
has_corp_hq = engine.phase3_facilities.get("corporate", 0) >= 1
if el_pol_panel:
el_pol_panel.style.display = "block" if has_corp_hq else "none"
for p_id in ["zero_trust_mfa", "standard_soe", "cloud_migration", "cicd_devops", "byod_program", "ai_auto_escalate", "on_call_rotation", "cicd_automation", "green_datacenter"]:
sw_p = document.getElementById(f"switch-policy-{p_id}")
if sw_p:
sw_p.checked = (p_id in engine.active_it_policies)
sw_p.disabled = not has_corp_hq
# 5. R&D Tech Tree & Progressive Research Dashboard
el_rd_badge = document.getElementById("display-rd-kp-badge")
if el_rd_badge:
el_rd_badge.innerText = f"KP: {engine.knowledge_points:,.1f} / {engine.get_max_kp():,.0f}"
el_rd_kp = document.getElementById("display-rd-kp-val")
if el_rd_kp:
el_rd_kp.innerText = f"{engine.knowledge_points:,.1f} / {engine.get_max_kp():,.0f}"
el_rd_tix = document.getElementById("display-rd-tickets-val")
if el_rd_tix:
el_rd_tix.innerText = f"{engine.solved_tickets_inventory:,}"
el_rd_cnt = document.getElementById("display-rd-completed-count")
if el_rd_cnt:
el_rd_cnt.innerText = f"{len(engine.rd_techs_unlocked)} / {len(getattr(resources, 'RD_TECH_TREE', resources.PHASE3_RD_TECHS_CONFIG))}"
el_rd_rate = document.getElementById("display-rd-synthesis-rate")
if el_rd_rate:
el_rd_rate.innerText = f"{25.0 * (1.0 + engine.phase3_facilities.get('corporate', 0)*0.2):.1f} KP/s" if engine.auto_synthesis_active else "0 KP/s"
badge_syn = document.getElementById("badge-synthesis-status")
if badge_syn:
badge_syn.className = "badge bg-success" if engine.auto_synthesis_active else "badge bg-secondary"
badge_syn.innerText = "ACTIVE" if engine.auto_synthesis_active else "INACTIVE"
sw_syn = document.getElementById("switch-auto-synthesis")
if sw_syn:
sw_syn.checked = engine.auto_synthesis_active
# Synthesis buttons
btn_syn_100 = document.getElementById("btn-synthesize-100kp")
if btn_syn_100:
btn_syn_100.disabled = (engine.solved_tickets_inventory < 10 or engine.knowledge_points >= engine.get_max_kp())
btn_syn_1000 = document.getElementById("btn-synthesize-1000kp")
if btn_syn_1000:
btn_syn_1000.disabled = (engine.solved_tickets_inventory < 100 or engine.knowledge_points >= engine.get_max_kp())
# Active Research Project Live Progress Banner
is_blocked = bool(engine.burnout or engine.pc_crashed or engine.is_rebooting)
panel_active_res = document.getElementById("panel-active-research")
if panel_active_res:
if getattr(engine, "active_research_project", None) and engine.active_research_project in getattr(resources, "RD_TECH_TREE", {}):
panel_active_res.style.display = "block"
act_id = engine.active_research_project
act_spec = resources.RD_TECH_TREE[act_id]
prog = engine.research_progress.get(act_id, {"progress": 0.0, "spent_kp": 0.0, "spent_cash": 0.0, "spent_tickets": 0.0})
total_dur = float(act_spec.get("duration_seconds", 45.0))
cur_prog = min(total_dur, prog.get("progress", 0.0))
pct = max(0.0, min(100.0, (cur_prog / max(1.0, total_dur)) * 100.0))
rem_time = max(0.0, total_dur - cur_prog)
title_el = document.getElementById("display-active-research-title")
if title_el:
title_el.innerText = f"{act_spec.get('icon', 'π¬')} {act_spec['name']} (Tier {act_spec.get('tier', 1)})"
eta_el = document.getElementById("display-active-research-eta")
if eta_el:
eta_el.innerText = f"ETA: {rem_time:.0f}s"
bar_res = document.getElementById("bar-active-research")
if bar_res:
bar_res.style.width = f"{pct:.0f}%"
bar_res.innerText = f"{pct:.0f}% Complete"
spent_el = document.getElementById("display-active-research-spent")
if spent_el:
spent_el.innerText = f"Funneled: {prog.get('spent_kp', 0.0):,.0f} KP β’ ${prog.get('spent_cash', 0.0):,.0f} β’ {prog.get('spent_tickets', 0.0):,.0f} Tickets"
btn_exp = document.getElementById("btn-expedite-research")
if btn_exp:
btn_exp.disabled = (engine.cash < 1000.0 or is_blocked)
else:
panel_active_res.style.display = "none"
# Multi-Tier Tech Tree nodes
rd_tech_dict = getattr(resources, "RD_TECH_TREE", resources.PHASE3_RD_TECHS_CONFIG)
for tech_id, t_cfg in rd_tech_dict.items():
is_unlocked = tech_id in engine.rd_techs_unlocked
is_active = (getattr(engine, "active_research_project", None) == tech_id)
t_badge = document.getElementById(f"badge-tech-{tech_id}")
t_btn = document.getElementById(f"btn-tech-{tech_id}")
t_desc = document.getElementById(f"desc-tech-{tech_id}")
if t_desc:
raw_perk = t_cfg.get('perk_desc', t_cfg.get('description', ''))
if raw_perk:
if not raw_perk.strip().lower().startswith("perk:"):
t_desc.innerText = f"Perk: {raw_perk}"
else:
t_desc.innerText = raw_perk
if is_unlocked:
if t_badge:
t_badge.className = "badge bg-success"
t_badge.innerText = "RESEARCHED"
if t_btn:
t_btn.className = "btn btn-sm btn-success w-100 fw-bold disabled"
t_btn.disabled = True
t_btn.innerText = "β Researched"
elif is_active:
prog = engine.research_progress.get(tech_id, {}).get("progress", 0.0)
dur = float(t_cfg.get("duration_seconds", 45.0))
pct = int((prog / max(1.0, dur)) * 100)
if t_badge:
t_badge.className = "badge bg-warning text-dark font-monospace"
t_badge.innerText = f"SYNTHESIZING {pct}%"
if t_btn:
t_btn.className = "btn btn-sm btn-warning text-dark w-100 fw-bold"
t_btn.disabled = True
t_btn.innerText = f"β³ Synthesizing ({pct}%)..."
else:
kp_c = t_cfg.get("kp_cost", t_cfg.get("cost_kp", 500.0))
cash_c = t_cfg.get("cash_cost", 0.0)
tix_c = t_cfg.get("tickets_cost", 0)
dur = t_cfg.get("duration_seconds", 45.0)
if t_badge:
t_badge.className = "badge bg-warning text-dark font-monospace"
if cash_c > 0:
t_badge.innerText = f"{kp_c:,.0f} KP β’ ${cash_c:,.0f} β’ {tix_c} Tix ({dur:.0f}s)"
else:
t_badge.innerText = f"{kp_c:,.0f} KP"
if t_btn:
t_btn.className = "btn btn-sm btn-outline-warning w-100 fw-bold"
t_btn.disabled = is_blocked
t_btn.innerText = f"π¬ Select for Research"
# 5b. R&D Laboratory Tech Upgrades UI Update
for up_id, up_spec in resources.PHASE3_RD_UPGRADES_REGISTRY.items():
curr_lvl = engine.upgrades.get(up_id, 0)
costs = engine.get_rd_upgrade_cost_dict(up_id)
req_tech = up_spec.get("req_tech")
is_req_met = (req_tech in engine.rd_techs_unlocked) if req_tech else True
el_lvl = document.getElementById(f"rd-level-{up_id}")
if el_lvl:
el_lvl.innerText = f"Lvl {curr_lvl}"
el_kp = document.getElementById(f"rd-cost-kp-{up_id}")
if el_kp:
el_kp.innerText = "MAX" if costs["is_max"] else f"{costs['kp']:,} KP"
el_tickets = document.getElementById(f"rd-cost-tickets-{up_id}")
if el_tickets:
el_tickets.innerText = "MAX" if costs["is_max"] else f"{costs['solved_tickets']:,} Tickets"
el_cash = document.getElementById(f"rd-cost-cash-{up_id}")
if el_cash:
el_cash.innerText = "MAX" if costs["is_max"] else f"${costs['cash']:,.2f}"
el_req = document.getElementById(f"rd-req-{up_id}")
if el_req:
if is_req_met:
el_req.innerHTML = 'β Tech Unlocked'
else:
el_req.innerHTML = f'π Req: {up_spec.get("req_tech_name", "")}'
btn_up = document.getElementById(f"btn-rd-buy-{up_id}")
if btn_up:
if costs["is_max"]:
btn_up.innerText = "β Max Level"
btn_up.className = "btn btn-sm btn-outline-warning w-100 fw-bold disabled"
btn_up.disabled = True
elif not is_req_met:
btn_up.innerText = "π Locked"
btn_up.className = "btn btn-sm btn-outline-secondary w-100 fw-bold disabled"
btn_up.disabled = True
else:
can_afford = (engine.knowledge_points >= costs["kp"] and engine.solved_tickets_inventory >= costs["solved_tickets"] and engine.cash >= costs["cash"] and not is_blocked)
btn_up.innerText = f"Upgrade ({costs['kp']:,} KP + {costs['solved_tickets']:,} Tix)"
btn_up.disabled = not can_afford
if can_afford:
btn_up.className = "btn btn-sm btn-info w-100 fw-bold"
else:
btn_up.className = "btn btn-sm btn-outline-info w-100 fw-bold"
# Auto-Pitch Proposal Controls in Sales
auto_pitch_lvl = engine.upgrades.get("auto_pitch_engine", 0)
badge_ap = document.getElementById("badge-auto-pitch-status")
box_ap = document.getElementById("container-switch-auto-pitch")
if badge_ap and box_ap:
if auto_pitch_lvl == 0:
badge_ap.style.display = "inline-block"
box_ap.style.display = "none"
else:
badge_ap.style.display = "none"
box_ap.style.display = "flex"
sw_ap = document.getElementById("switch-auto-pitch")
if sw_ap:
sw_ap.checked = getattr(engine, "auto_pitch_enabled", True)
# 6. Executive Diagnostic Alerts & Action Feed
container_alerts = document.getElementById("container-executive-alerts")
badge_alerts_cnt = document.getElementById("badge-alerts-count")
if container_alerts:
alerts = []
# Check Bandwidth
bw_used = engine.get_used_bandwidth() if hasattr(engine, "get_used_bandwidth") else 0.0
bw_max = engine.get_max_bandwidth() if hasattr(engine, "get_max_bandwidth") else 50.0
bw_pct = (bw_used / max(1.0, bw_max)) * 100.0
if bw_pct >= 85.0:
alerts.append({
"id": "alert-bw",
"icon": "β οΈ", "badge": "bg-warning text-dark",
"title": "High Bandwidth Load (SLA Saturation Risk)",
"detail": f"{bw_used:.0f}/{bw_max:.0f} Mbps ({int(bw_pct)}%)",
"action_text": "Upgrade Fiber", "tab": "sales-tab", "elem": "display-sales-bw-usage"
})
# Check Queue
q_cur = int(engine.tickets_queue)
q_max = int(engine.get_max_tickets_queue())
if q_cur >= q_max * 0.8:
alerts.append({
"id": "alert-queue-high",
"icon": "π¨", "badge": "bg-danger",
"title": "Incident Queue Saturation (SLA Breach Imminent)",
"detail": f"{q_cur}/{q_max} Tickets",
"action_text": "Build Helpdesk", "tab": "helpdesk-tab", "elem": "card-facility-helpdesk"
})
elif q_cur <= 1 and engine.phase3_facilities.get("call_center", 0) >= 1:
alerts.append({
"id": "alert-queue-low",
"icon": "π", "badge": "bg-info text-dark",
"title": "Incident Queue Empty (Technicians Idle)",
"detail": f"{q_cur}/{q_max} Tickets",
"action_text": "Pitch SLA Contracts", "tab": "sales-tab", "elem": "row-sales-proposals"
})
# Check Research Project
if not getattr(engine, "active_research_project", None) and len(engine.rd_techs_unlocked) < 9:
alerts.append({
"id": "alert-rd-idle",
"icon": "π¬", "badge": "bg-primary",
"title": "R&D Innovation Labs Idle (No Active Project)",
"detail": "0 Active Projects",
"action_text": "Select Tech Node", "tab": "rd-tab", "elem": "panel-active-research"
})
# Check Facilities Building
if getattr(engine, "facility_construction_queues", {}):
n_bldg = len(engine.facility_construction_queues)
alerts.append({
"id": "alert-bldg",
"icon": "ποΈ", "badge": "bg-warning text-dark",
"title": "Active Construction Fleet Operating",
"detail": f"{n_bldg} Fleet in Progress",
"action_text": "View Fleet", "tab": "helpdesk-tab", "elem": "card-facility-call_center"
})
# Check DC Thermal Strain
if getattr(engine, "infra_thermal_strain", 0.0) >= 50.0:
alerts.append({
"id": "alert-thermal",
"icon": "π‘οΈ", "badge": "bg-danger",
"title": "Critical Infrastructure Thermal Strain",
"detail": f"{int(engine.infra_thermal_strain)}% Strain",
"action_text": "Maintenance Window", "tab": "datacenter-tab", "elem": "btn-infra-maintenance"
})
if badge_alerts_cnt:
badge_text = f"{len(alerts)} Active Alerts" if alerts else "Nominal (0 Alerts)"
if badge_alerts_cnt.innerText != badge_text:
badge_alerts_cnt.innerText = badge_text
alert_ids_key = ",".join(alt["id"] for alt in alerts)
if getattr(engine, "_last_alert_ids_key", None) != alert_ids_key:
engine._last_alert_ids_key = alert_ids_key
if alerts:
items_html = []
for alt in alerts:
items_html.append(
f'
'
f'
'
f'{alt["icon"]}'
f'{alt["title"]}'
f'{alt.get("detail", "")}'
f'