extends GutTest const WORLD_ID := &"regional_bosnia" const LOCATION_ID := &"location_jajce" const CONTEXT_ID := &"jajce_surface" func test_two_thousand_candidates_stay_bounded_pinned_and_order_independent() -> void: var policy := PresentationRelevancePolicy.new() var candidates := _large_candidate_fixture() var first := policy.select_detailed_visuals( _context(), _address(LOCATION_ID, Vector3.ZERO), candidates ) assert_true(first["valid"]) assert_eq(first["candidate_count"], 2000) assert_eq(first["selected_ids"].size(), PresentationRelevancePolicy.DEFAULT_DETAIL_LIMIT) assert_eq(first["mandatory_count"], 6) for mandatory_id in _mandatory_ids(): assert_has(first["selected_ids"], mandatory_id) var decision := policy.get_decision(first, mandatory_id) assert_true(decision["selected"]) assert_true(decision["mandatory"]) assert_true("selected_mandatory_pin" in decision["reason_trace"]) var reordered := candidates.duplicate(true) for candidate: Dictionary in reordered: candidate["loaded"] = not bool(candidate["loaded"]) reordered.reverse() var second := policy.select_detailed_visuals( _context(), _address(LOCATION_ID, Vector3.ZERO), reordered ) assert_true(second["valid"]) assert_eq(second["selected_ids"], first["selected_ids"]) assert_eq(_selected_scores(second), _selected_scores(first)) func test_context_and_location_scope_override_equal_coordinates_and_foreign_pins() -> void: var policy := PresentationRelevancePolicy.new() var candidates: Array[Dictionary] = [ _candidate(&"local_named", LOCATION_ID, Vector3.ZERO, 0.2), _candidate( &"foreign_threat", &"location_travnik", Vector3.ZERO, 1.0, {"player_affecting_threat": true} ), _candidate( &"other_context_leader", LOCATION_ID, Vector3.ZERO, 1.0, {"context_id": &"jajce_interior", "leader": true} ), ] var result := policy.select_detailed_visuals( _context(), _address(LOCATION_ID, Vector3.ZERO), candidates, 2 ) assert_true(result["valid"]) assert_eq(result["selected_ids"], [&"local_named"]) var foreign := policy.get_decision(result, &"foreign_threat") assert_false(foreign["selected"]) assert_has(foreign["reason_trace"], "rejected_different_location") assert_has(foreign["reason_trace"], "pin_ignored_outside_active_scope") assert_has(foreign["reason_trace"], "pin_player_affecting_threat") var other_context := policy.get_decision(result, &"other_context_leader") assert_has(other_context["reason_trace"], "rejected_inactive_context") func test_score_distance_and_stable_id_form_a_total_tie_order_with_rejection_trace() -> void: var policy := PresentationRelevancePolicy.new() var candidates: Array[Dictionary] = [ _candidate(&"entity_b", LOCATION_ID, Vector3(3.0, 0.0, 0.0), 0.5), _candidate(&"entity_a", LOCATION_ID, Vector3(3.0, 0.0, 0.0), 0.5), _candidate(&"entity_far", LOCATION_ID, Vector3(20.0, 0.0, 0.0), 0.1), ] var result := policy.select_detailed_visuals( _context(), _address(LOCATION_ID, Vector3.ZERO), candidates, 1 ) assert_true(result["valid"]) assert_eq(result["selected_ids"], [&"entity_a"]) var rejected_tie := policy.get_decision(result, &"entity_b") assert_false(rejected_tie["selected"]) assert_true(_trace_contains_prefix(rejected_tie["reason_trace"], "importance_units_")) assert_true(_trace_contains_prefix(rejected_tie["reason_trace"], "distance_millimeters_")) assert_true( _trace_contains_prefix(rejected_tie["reason_trace"], "rejected_detail_capacity_rank_") ) candidates.reverse() var reordered := policy.select_detailed_visuals( _context(), _address(LOCATION_ID, Vector3.ZERO), candidates, 1 ) assert_eq(reordered["selected_ids"], result["selected_ids"]) func test_unsatisfiable_pin_overflow_fails_closed_instead_of_silently_unpinning() -> void: var policy := PresentationRelevancePolicy.new() var candidates: Array[Dictionary] = [ _candidate(&"leader_a", LOCATION_ID, Vector3.ZERO, 0.1, {"leader": true}), _candidate(&"leader_b", LOCATION_ID, Vector3.ONE, 0.2, {"leader": true}), _candidate(&"leader_c", LOCATION_ID, Vector3.RIGHT, 0.3, {"leader": true}), ] var result := policy.select_detailed_visuals( _context(), _address(LOCATION_ID, Vector3.ZERO), candidates, 2 ) assert_false(result["valid"]) assert_true(result["selected_ids"].is_empty()) assert_eq(result["mandatory_count"], 3) assert_true("mandatory_pin_overflow" in String(result["errors"][0])) for candidate in candidates: var decision := policy.get_decision(result, candidate["stable_id"]) assert_has(decision["reason_trace"], "rejected_unsatisfiable_pin_overflow") func test_navigation_request_budget_grants_only_two_new_stable_requests_per_frame() -> void: var budget := PresentationNavRequestBudget.new() assert_true(budget.enqueue(&"entity_c", 5, ["relevant"])) assert_true(budget.enqueue(&"entity_b", 10, ["threat"])) assert_true(budget.enqueue(&"entity_a", 10, ["leader"])) assert_true(budget.enqueue(&"entity_d", 1, ["nearby"])) assert_false(budget.enqueue(&"entity_a", 99, ["duplicate"])) var first_frame := budget.take_new_requests(42) assert_eq(_request_ids(first_frame), [&"entity_a", &"entity_b"]) assert_eq(first_frame.size(), PresentationNavRequestBudget.MAX_NEW_REQUESTS_PER_FRAME) assert_true(budget.take_new_requests(42).is_empty()) assert_eq(budget.get_in_flight_ids(), [&"entity_a", &"entity_b"]) assert_eq(budget.get_pending_ids(), [&"entity_c", &"entity_d"]) var next_frame := budget.take_new_requests(43) assert_eq(_request_ids(next_frame), [&"entity_c", &"entity_d"]) assert_true(budget.complete(&"entity_a")) assert_true(budget.enqueue(&"entity_a", 2, ["retargeted"])) assert_eq(_request_ids(budget.take_new_requests(44)), [&"entity_a"]) func _large_candidate_fixture() -> Array[Dictionary]: var candidates: Array[Dictionary] = [] for index in 2000: var extras := {} match index: 1994: extras["pinned"] = true 1995: extras["player_affecting_threat"] = true 1996: extras["situation_participant"] = true 1997: extras["commitment_participant"] = true 1998: extras["leader"] = true 1999: extras["unique_owner"] = true var position := Vector3(float(index % 73), 0.0, float((index * 11) % 89)) var importance := float((index * 37) % 1000) / 999.0 var candidate := _candidate( StringName("named_entity_%04d" % index), LOCATION_ID, position, importance, extras ) candidate["loaded"] = index % 3 == 0 candidates.append(candidate) return candidates func _mandatory_ids() -> Array[StringName]: return [ &"named_entity_1994", &"named_entity_1995", &"named_entity_1996", &"named_entity_1997", &"named_entity_1998", &"named_entity_1999", ] func _candidate( stable_id: StringName, location_id: StringName, position: Vector3, importance: float, extras: Dictionary = {} ) -> Dictionary: var descriptor := { "stable_id": stable_id, "context_id": CONTEXT_ID, "address": _address(location_id, position), "importance": importance, "named": true, "loaded": false, } for field in extras: descriptor[field] = extras[field] return descriptor func _context() -> Dictionary: return {"context_id": CONTEXT_ID, "world_id": WORLD_ID, "location_id": LOCATION_ID} func _address(location_id: StringName, position: Vector3) -> SpatialAddress: return SpatialAddress.create(WORLD_ID, location_id, position) func _selected_scores(result: Dictionary) -> Array[int]: var scores: Array[int] = [] for decision: Dictionary in result["selected_details"]: scores.append(int(decision["score_units"])) return scores func _request_ids(requests: Array[Dictionary]) -> Array[StringName]: var ids: Array[StringName] = [] for request in requests: ids.append(StringName(request["stable_id"])) return ids func _trace_contains_prefix(trace: Array, prefix: String) -> bool: for reason in trace: if String(reason).begins_with(prefix): return true return false