P23-03: 生活の観察
This commit is contained in:
@@ -166,6 +166,9 @@ func draw_rectangles(report: Dictionary, view: WorldPreview) -> Dictionary:
|
||||
var rest := actor_rectangle(actor)
|
||||
rest["category"] = "rest"
|
||||
rows.append(rest)
|
||||
for index: int in range(report.get(&"actor_aggregations", []).size()):
|
||||
var badge: Dictionary = report[&"actor_aggregations"][index]
|
||||
rows.append(badge_rectangle("aggregation", str(index), badge[&"at"], badge[&"text"]))
|
||||
for index: int in range(report.get(&"badges", []).size()):
|
||||
var badge: Dictionary = report[&"badges"][index]
|
||||
rows.append(badge_rectangle("goods" if badge[&"kind"] == &"supply" else "business", str(index), badge[&"at"], badge[&"text"]))
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"purpose": "Historical negative only; not fresh acceptance evidence",
|
||||
"source_request": "os-pair/A/reader-request-0003/request.json",
|
||||
"source_request_sha256": "7dc3ee0bcc428e9d103726ee2448c767f1dd4107f9490833dc860c0b5140068c",
|
||||
"manifest_sha256": "53aa8e2f12e5d0a089529457fcd55ee1ba0600e8dffff2225bb8b057d007fe1a",
|
||||
"independent_judgment": [11, false, false, false],
|
||||
"source_rows": [11, 29],
|
||||
"report_inputs": {
|
||||
"actor_drawings": [
|
||||
{"key": "guest/guest-auto-00000041", "at": [651.0, 517.0], "scale": 3.0, "mode": "wait", "frame": 12, "flip": false},
|
||||
{"key": "staff/staff_gina", "at": [651.0, 517.0], "scale": 3.0, "mode": "idle", "frame": 3, "flip": false}
|
||||
],
|
||||
"cabins": []
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"purpose": "Historical diagnostic input for placement-rule clarification; not fresh acceptance evidence",
|
||||
"source_request": "os-pair/A/reader-request-0003/request.json",
|
||||
"source_request_sha256": "7dc3ee0bcc428e9d103726ee2448c767f1dd4107f9490833dc860c0b5140068c",
|
||||
"guests": [
|
||||
{"id": "guest-auto-00000044", "state": "RECEIVING_SERVICE", "cell": [5, 0, 0], "target": "facility_00000003", "service": "service_00000009", "queue": ""},
|
||||
{"id": "guest-auto-00000019", "state": "RECEIVING_SERVICE", "cell": [-6, 2, 0], "target": "facility_00000007", "service": "service_00000002", "queue": ""}
|
||||
],
|
||||
"room_rects": {
|
||||
"facility_00000003": [1027.0, 388.0, 256.0, 192.0],
|
||||
"facility_00000007": [131.0, 292.0, 128.0, 96.0]
|
||||
},
|
||||
"traffic": [
|
||||
{"cell": [5, 0, 0], "traffic": {"base_capacity": 4, "current_density": 6, "dynamic_cost": 0, "temporary_block": false}, "rect": [965.0, 486.0, 60.0, 92.0]},
|
||||
{"cell": [-6, 2, 0], "traffic": {"base_capacity": 4, "current_density": 3, "dynamic_cost": 0, "temporary_block": false}, "rect": [261.0, 294.0, 60.0, 92.0]}
|
||||
]
|
||||
}
|
||||
@@ -56,6 +56,61 @@ func run() -> void:
|
||||
view.size = Vector2(1440, 810)
|
||||
view.set_runtime(runtime)
|
||||
root.add_child(view)
|
||||
# R13's four same-cell MOVING guests. Component fixture only, no Runtime edit.
|
||||
var crowd: Array = []
|
||||
var offsets := [0, 16, -16, 8]
|
||||
for i: int in 4:
|
||||
crowd.append({&"row": {&"key": "guest/os-p23-%03d" % (12+i),
|
||||
&"center": Vector2(108+offsets[i], 118-4*(i%2)),
|
||||
&"at": Vector2(84+offsets[i], 103-4*(i%2)), &"scale": 3.0,
|
||||
&"mode": &"idle", &"frame": 0, &"flip": false,
|
||||
&"state": GuestRuntime.State.MOVING, &"cell": Vector3i(1,1,0)},
|
||||
&"bounds": Rect2(80,74,56,88), &"transit": false})
|
||||
crowd.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return a[&"row"][&"center"].x < b[&"row"][&"center"].x)
|
||||
# _life_pack uses the view's cell dimensions for the unchanged feet formula.
|
||||
# The x-capacity assertion is independent of the current default world size.
|
||||
expect(view._life_pack(crowd, 3).is_empty(), "four cores cannot fit 72px in 56px")
|
||||
var saved_size := view.size
|
||||
var saved_zoom := view.zoom_level
|
||||
var dim: Vector2 = view._cell_dimensions()
|
||||
view.zoom_level *= 64.0/dim.x
|
||||
var fitted: Array = view._life_pack(crowd, 2)
|
||||
expect(fitted.size() == 4, "all four R13 occupants fit at p=2")
|
||||
for row: Dictionary in fitted:
|
||||
expect(row[&"scale"] == 2.0 and row[&"cell"] == Vector3i(1,1,0), "fitting preserves cell and uses p=2")
|
||||
var regroup: Array = crowd.slice(0, 2).duplicate(true)
|
||||
for i: int in 2:
|
||||
regroup[i][&"row"][&"center"] = Vector2(108, 118+26*i)
|
||||
regroup[i][&"bounds"] = Rect2(80,74,20,130)
|
||||
var regrouped: Array = view._life_fitted_groups(regroup)
|
||||
expect(regrouped.size() == 2, "scale change splits vertical component")
|
||||
for group: Array in regrouped:
|
||||
expect(group.size() == 1 and group[0][&"row"][&"scale"] == 2.0, "regroup avoids stale p=1 fit")
|
||||
var saturated: Array = []
|
||||
for i: int in 10:
|
||||
var member: Dictionary = crowd[0].duplicate(true)
|
||||
member[&"row"][&"key"] = "guest/saturation-%02d" % i
|
||||
member[&"row"][&"center"] = Vector2(108,118)
|
||||
saturated.append(member)
|
||||
var saturated_groups: Array = view._life_fitted_groups(saturated)
|
||||
expect(saturated_groups.size() == 1, "saturation keeps one vertical component")
|
||||
expect(view._life_pack(saturated_groups[0], 1).is_empty(), "ten cores cannot fit 60px in 56px")
|
||||
expect(view._life_pack(saturated_groups[0].slice(0,9), 1).size() == 9, "nine cores fit without losing identities")
|
||||
var aggregate_model := {&"guests": [], &"staff": [], &"actor_drawings": [], &"cabins": []}
|
||||
var aggregate_rows: Array = []
|
||||
for member: Dictionary in saturated:
|
||||
var row: Dictionary = member[&"row"].duplicate(true)
|
||||
row[&"riding"] = true
|
||||
aggregate_rows.append(row)
|
||||
aggregate_model[&"guests"].append({&"id": String(row[&"key"]).trim_prefix("guest/"), &"cell": Vector3i(1,1,0)})
|
||||
aggregate_model[&"cabins"].append({&"rect": Rect2(76,70,64,96), &"passengers": aggregate_rows})
|
||||
view._fit_life_actors(aggregate_model)
|
||||
expect(aggregate_model[&"cabins"][0][&"passengers"].size() == 9, "aggregation draws all nine fitting members")
|
||||
var aggregate: Dictionary = aggregate_model[&"actor_aggregations"][0]
|
||||
expect(aggregate[&"members"].size() == 10 and aggregate[&"drawn_keys"].size() == 9, "aggregation retains every identity")
|
||||
expect(aggregate[&"text"] == "+1" and aggregate[&"at"] == Vector2(80,74), "actual aggregation badge position and text")
|
||||
view.zoom_level = saved_zoom
|
||||
view.size = saved_size
|
||||
var before: PackedByteArray = var_to_bytes(runtime.create_snapshot())
|
||||
var tracks: PackedByteArray = var_to_bytes([view._actor_tracks, view._elevator_tracks])
|
||||
var model := view._build_life_observation()
|
||||
@@ -67,6 +122,10 @@ func run() -> void:
|
||||
await process_frame
|
||||
var report := view.get_life_observation_report()
|
||||
expect(not report.is_empty(), "actual drawing published an observation")
|
||||
expect(report.get(&"observation_serial", -1) == report.get(&"overlay_consumed_serial", -2), "LifeOverlay consumed this observation")
|
||||
expect(report.get(&"overlay_passes", []) == [&"traffic", &"actors"], "traffic drawn before actors")
|
||||
var indices: Array = report.get(&"overlay_child_indices", [])
|
||||
expect(indices.size() == 3 and indices[0] < indices[1] and indices[1] < indices[2], "LifeOverlay above inactive art and below lens")
|
||||
# The getter exposes the last actual draw and must not create another model.
|
||||
var original: PackedByteArray = var_to_bytes(report)
|
||||
if report.has(&"traffic"):
|
||||
|
||||
Reference in New Issue
Block a user