103 lines
3.8 KiB
GDScript
103 lines
3.8 KiB
GDScript
class_name ABGCompanyPageController
|
|
extends RefCounted
|
|
|
|
## UI-independent view-model assembly for the unaccepted Company pages.
|
|
## Callers provide a Company snapshot; this controller never loads, saves or
|
|
## mutates persistence and never reaches into Godot Control nodes.
|
|
|
|
|
|
func roster_snapshot(company: Dictionary, requested_recruit_id := "") -> Dictionary:
|
|
var members: Array[Dictionary] = []
|
|
for recruit in company.get("owned_recruits", []):
|
|
if recruit is Dictionary:
|
|
members.append(_member_snapshot(recruit))
|
|
var selected_id := _selected_id(members, requested_recruit_id)
|
|
var selected := _member_by_id(members, selected_id)
|
|
var dismissal := _dismissal_state(company, selected_id)
|
|
return {
|
|
"ok": true,
|
|
"page_id": "roster",
|
|
"selected_recruit_id": selected_id,
|
|
"members": _copy_array(members),
|
|
"selected": selected,
|
|
"dismissal": dismissal,
|
|
}
|
|
|
|
|
|
func recruit_detail_snapshot(company: Dictionary, recruit_id: String) -> Dictionary:
|
|
var recruit := _find_recruit(company, recruit_id)
|
|
if recruit.is_empty():
|
|
return {"ok": false, "code": "RECRUIT_NOT_FOUND", "recruit_id": recruit_id}
|
|
var member := _member_snapshot(recruit)
|
|
return {
|
|
"ok": true,
|
|
"page_id": "recruit_detail",
|
|
"selected_recruit_id": recruit_id,
|
|
"recruit": member,
|
|
"dismissal": _dismissal_state(company, recruit_id),
|
|
}
|
|
|
|
|
|
func _member_snapshot(recruit: Dictionary) -> Dictionary:
|
|
return {
|
|
"recruit_id": String(recruit.get("recruit_id", "")),
|
|
"rendered_name_snapshot": Dictionary(recruit.get("rendered_name_snapshot", {})).duplicate(true),
|
|
"profession_id": String(recruit.get("profession_id", "")),
|
|
"profession_job": String(recruit.get("profession_job", "")),
|
|
"profession_name": Dictionary(recruit.get("profession_name", {})).duplicate(true),
|
|
"trait_id": String(recruit.get("trait_id", "")),
|
|
"trait_name": Dictionary(recruit.get("trait_name", {})).duplicate(true),
|
|
"level": int(recruit.get("level", 0)),
|
|
"xp": int(recruit.get("xp", 0)),
|
|
"equipped_item_id": String(recruit.get("equipped_item_id", "")),
|
|
"starting_item_id": String(recruit.get("starting_item_id", "")),
|
|
"starting_item_name": Dictionary(recruit.get("starting_item_name", {})).duplicate(true),
|
|
"battle_history": Dictionary(recruit.get("battle_history", {})).duplicate(true),
|
|
}
|
|
|
|
|
|
func _dismissal_state(company: Dictionary, recruit_id: String) -> Dictionary:
|
|
var member_count := Array(company.get("owned_recruits", [])).size()
|
|
var phase := String(Dictionary(company.get("active_contract", {})).get("status", ""))
|
|
var eligible := not recruit_id.is_empty() and member_count > 1 and phase == "market"
|
|
var reason := "eligible"
|
|
if recruit_id.is_empty():
|
|
reason = "no_selection"
|
|
elif member_count <= 1:
|
|
reason = "last_member"
|
|
elif phase != "market":
|
|
reason = "phase_locked"
|
|
return {
|
|
"eligible": eligible,
|
|
"reason": reason,
|
|
"member_count": member_count,
|
|
"phase": phase,
|
|
}
|
|
|
|
|
|
func _selected_id(members: Array[Dictionary], requested_recruit_id: String) -> String:
|
|
if not requested_recruit_id.is_empty() and not _member_by_id(members, requested_recruit_id).is_empty():
|
|
return requested_recruit_id
|
|
return String(members[0].get("recruit_id", "")) if not members.is_empty() else ""
|
|
|
|
|
|
func _find_recruit(company: Dictionary, recruit_id: String) -> Dictionary:
|
|
for recruit in company.get("owned_recruits", []):
|
|
if recruit is Dictionary and String(recruit.get("recruit_id", "")) == recruit_id:
|
|
return Dictionary(recruit).duplicate(true)
|
|
return {}
|
|
|
|
|
|
func _member_by_id(members: Array[Dictionary], recruit_id: String) -> Dictionary:
|
|
for member in members:
|
|
if String(member.get("recruit_id", "")) == recruit_id:
|
|
return Dictionary(member).duplicate(true)
|
|
return {}
|
|
|
|
|
|
func _copy_array(values: Array[Dictionary]) -> Array[Dictionary]:
|
|
var copied: Array[Dictionary] = []
|
|
for value in values:
|
|
copied.append(Dictionary(value).duplicate(true))
|
|
return copied
|