P07-01-WX: 仕上がった天候の機能の受入:自然天候・雨・嵐・世界樹と成人客のマナ霧・上部の表示と予報・保存と移行(マナ炉の産出 120 を除く。P07-01 の補助の作業。原単位への加算 0)
This commit is contained in:
@@ -26,15 +26,23 @@ func _run() -> void:
|
||||
var straight := fixtures.new_fixture()
|
||||
var straight_runtime: Variant = straight[&"runtime"]
|
||||
var held_guest: Variant = straight_runtime.guest_service.get_guest(Fixture.HELD_GUEST)
|
||||
var held := {"hold": {}, "reason": &""}
|
||||
fixtures.play(straight, Fixture.FIRST_MINUTE, Fixture.LAST_MINUTE, func(_minute: int) -> void:
|
||||
var held := {"hold": {}, "reason": &"", "after": {}}
|
||||
fixtures.play(straight, Fixture.FIRST_MINUTE, Fixture.LAST_MINUTE, func(minute: int) -> void:
|
||||
if (held["hold"] as Dictionary).is_empty():
|
||||
held["hold"] = straight_runtime.weather.get_rain_hold(Fixture.HELD_GUEST)
|
||||
if StringName(held["reason"]).is_empty():
|
||||
held["reason"] = held_guest.exit_reason)
|
||||
held["reason"] = held_guest.exit_reason
|
||||
if minute == 363:
|
||||
_expect(straight_runtime.guest_service.get_guest(Fixture.HELD_GUEST) != null and held_guest.state == GuestRuntime.State.LEAVING
|
||||
and straight_runtime.weather.get_rain_hold(Fixture.HELD_GUEST) == Fixture.HOLD, "at 06:03 the held guest is still present and leaving with its hold")
|
||||
if minute == 364:
|
||||
_expect(straight_runtime.guest_service.get_guest(Fixture.HELD_GUEST) == null and straight_runtime.weather.get_rain_holds().is_empty(),
|
||||
"at 06:04 the held guest is gone and its hold left with it")
|
||||
if minute - 1 in Fixture.SAVE_MINUTES:
|
||||
held["after"][minute] = fixtures.state_bytes(straight_runtime))
|
||||
# The hold only moves the planned exit; every other current rule still applies,
|
||||
# so in this world without facilities the guest leaves for lack of one.
|
||||
_expect(held["hold"] == {"original_exit": 362, "extended_to": 602} and held_guest.planned_exit_at == 602 and held["reason"] == &"NO_SUITABLE_FACILITY",
|
||||
_expect(held["hold"] == Fixture.HOLD and held_guest.planned_exit_at == 602 and held["reason"] == &"NO_SUITABLE_FACILITY",
|
||||
"the guest due at 06:02 was held to 10:02 and still left by the current rules (%s)" % String(held["reason"]))
|
||||
_expect(straight[&"draws"][&"count"] == Fixture.DRAW_MINUTES.size() and straight_runtime.weather.get_last_draw_day() == 1, "the uninterrupted script draws day 1 once")
|
||||
var saving := fixtures.new_fixture()
|
||||
@@ -43,16 +51,39 @@ func _run() -> void:
|
||||
var saved_paths := {}
|
||||
fixtures.play(saving, Fixture.FIRST_MINUTE, Fixture.LAST_MINUTE, func(minute: int) -> void:
|
||||
if minute in Fixture.SAVE_MINUTES:
|
||||
if minute == 363:
|
||||
_expect(saving_runtime.guest_service.get_guest(Fixture.HELD_GUEST) != null and saving_runtime.weather.get_rain_holds() == {String(Fixture.HELD_GUEST): Fixture.HOLD}
|
||||
and saving_runtime.guest_service.get_guest(Fixture.HELD_GUEST).planned_exit_at == 602, "minute 363 saves the hold of the present held guest")
|
||||
if minute == 364:
|
||||
_expect(saving_runtime.guest_service.get_guest(Fixture.HELD_GUEST) == null and saving_runtime.weather.get_rain_holds().is_empty(), "minute 364 saves just after the held guest left, without its hold")
|
||||
if minute == 500:
|
||||
var held_present: bool = saving_runtime.guest_service.get_guest(Fixture.HELD_GUEST) != null
|
||||
_expect(saving_runtime.weather.get_kind() == &"rain" and (not held_present or not saving_runtime.weather.get_rain_hold(Fixture.HELD_GUEST).is_empty()), "minute 500 saves mid-rain with the hold of a present guest")
|
||||
_expect(saving_runtime.weather.get_kind() == &"rain", "minute 500 saves mid-rain")
|
||||
var path := Fixture.WRITER_SAVE % minute
|
||||
saved_states[minute] = fixtures.state_bytes(saving_runtime)
|
||||
_expect(bool(saving_runtime.save_to_path(path).get(&"ok", false)), "save file at minute %d" % minute)
|
||||
saved_paths[minute] = path)
|
||||
_expect(fixtures.state_bytes(saving_runtime) == fixtures.state_bytes(straight_runtime), "writing the save files leaves the weather state as without saving")
|
||||
var saves := _packages(Fixture.SAVE_MINUTES, saved_paths, saved_states, Fixture.WRITER_SAVE)
|
||||
var final_state := fixtures.state_bytes(straight_runtime)
|
||||
for minute: int in Fixture.SAVE_MINUTES:
|
||||
var reload := fixtures.new_fixture(false)
|
||||
var reload_runtime: Variant = reload[&"runtime"]
|
||||
_expect(bool(reload_runtime.load_from_path(str(saved_paths.get(minute, Fixture.WRITER_SAVE % minute))).get(&"ok", false))
|
||||
and fixtures.state_bytes(reload_runtime) == saved_states.get(minute, PackedByteArray()) and reload[&"clock"].absolute_minute == minute,
|
||||
"this process reloads the save file of minute %d exactly" % minute)
|
||||
if minute == 363:
|
||||
_expect(reload_runtime.weather.get_rain_holds() == {String(Fixture.HELD_GUEST): Fixture.HOLD} and reload_runtime.guest_service.get_guest(Fixture.HELD_GUEST).planned_exit_at == 602,
|
||||
"the reloaded minute 363 save keeps the one hold and the extended plan")
|
||||
fixtures.play(reload, minute, minute + 1, Callable())
|
||||
_expect(fixtures.state_bytes(reload_runtime) == held["after"].get(minute + 1, PackedByteArray()),
|
||||
"one minute after the minute %d reload equals the uninterrupted run (no second extension)" % minute)
|
||||
fixtures.play(reload, minute + 1, Fixture.LAST_MINUTE, Callable())
|
||||
_expect(fixtures.state_bytes(reload_runtime) == final_state, "the minute %d reload continues to the uninterrupted final state" % minute)
|
||||
fixtures.free_fixture(reload)
|
||||
var saves := _packages(Fixture.SAVE_MINUTES, saved_paths, saved_states, Fixture.WRITER_SAVE)
|
||||
var after := {}
|
||||
for minute: int in held["after"]:
|
||||
var bytes: PackedByteArray = held["after"][minute]
|
||||
after[str(minute)] = {"sha256": Fixture.sha256(bytes), "base64": Marshalls.raw_to_base64(bytes)}
|
||||
var fog := _fog_scene(fixtures)
|
||||
var handoff := {
|
||||
"schema": Fixture.HANDOFF_SCHEMA,
|
||||
@@ -62,6 +93,7 @@ func _run() -> void:
|
||||
"last_minute": Fixture.LAST_MINUTE,
|
||||
"straight_final_state_sha256": Fixture.sha256(final_state),
|
||||
"straight_final_state_base64": Marshalls.raw_to_base64(final_state),
|
||||
"after_states": after,
|
||||
"saves": saves,
|
||||
"fog": fog,
|
||||
}
|
||||
|
||||
@@ -55,19 +55,28 @@ func _check_restarts(handoff: Dictionary) -> void:
|
||||
_expect(Fixture.sha256(final_state) == str(handoff.get("straight_final_state_sha256", "")), "the writer's final state arrived intact")
|
||||
var saves: Array = handoff.get("saves", [])
|
||||
_expect(saves.size() == Fixture.SAVE_MINUTES.size(), "every save package was handed off")
|
||||
var after: Dictionary = handoff.get("after_states", {})
|
||||
for save: Variant in saves:
|
||||
var minute := int((save as Dictionary).get("minute", -1))
|
||||
var path := Fixture.READER_SAVE % minute
|
||||
_expect(_write_package(save, path), "save package at minute %d arrived byte-exact" % minute)
|
||||
var expected_state := Marshalls.base64_to_raw(str((save as Dictionary).get("state_base64", "")))
|
||||
var next_row: Dictionary = after.get(str(minute + 1), {})
|
||||
var next_state := Marshalls.base64_to_raw(str(next_row.get("base64", "")))
|
||||
_expect(not next_state.is_empty() and Fixture.sha256(next_state) == str(next_row.get("sha256", "")), "the writer's state one minute after %d arrived intact" % minute)
|
||||
var fixture := fixtures.new_fixture(false)
|
||||
var runtime: Variant = fixture[&"runtime"]
|
||||
_expect(bool(runtime.load_from_path(path).get(&"ok", false)), "the reader loads the minute %d save" % minute)
|
||||
_expect(fixtures.state_bytes(runtime) == expected_state and fixture[&"clock"].absolute_minute == minute, "the minute %d save resumes the writer's weather, holds, stream and plans" % minute)
|
||||
if minute == 363:
|
||||
_expect(runtime.weather.get_rain_holds() == {String(Fixture.HELD_GUEST): Fixture.HOLD} and runtime.guest_service.get_guest(Fixture.HELD_GUEST) != null
|
||||
and runtime.guest_service.get_guest(Fixture.HELD_GUEST).planned_exit_at == 602, "the reader resumes the one hold of the present held guest and its extended plan")
|
||||
# Loading replaces the event stream, so the draw counter subscribes again.
|
||||
fixture[&"draws"][&"count"] = 0
|
||||
fixtures.watch_draws(fixture)
|
||||
fixtures.play(fixture, minute, Fixture.LAST_MINUTE, Callable())
|
||||
fixtures.play(fixture, minute, minute + 1, Callable())
|
||||
_expect(fixtures.state_bytes(runtime) == next_state, "one minute after the minute %d save the reader equals the writer (no second extension)" % minute)
|
||||
fixtures.play(fixture, minute + 1, Fixture.LAST_MINUTE, Callable())
|
||||
var expected_draws := 0
|
||||
for draw_minute: int in Fixture.DRAW_MINUTES:
|
||||
if draw_minute > minute:
|
||||
|
||||
@@ -238,6 +238,16 @@ func _test_rain_stay_and_saves() -> void:
|
||||
## itself runs at the extended time: it is not held again and begins leaving
|
||||
## with the ordinary PLANNED_EXIT.
|
||||
func _test_rain_hold_exit() -> void:
|
||||
var natural := _new_runtime(SEED_RAIN)
|
||||
var natural_runtime: Variant = natural[&"runtime"]
|
||||
var departing: Variant = _spawn(natural_runtime, &"p07_departing_guest", &"traveler", 362)
|
||||
natural[&"clock"].advance_minutes(3)
|
||||
_expect(natural_runtime.weather.get_rain_hold(&"p07_departing_guest") == {"original_exit": 362, "extended_to": 602} and departing.state == GuestRuntime.State.LEAVING
|
||||
and departing.exit_reason == &"NO_SUITABLE_FACILITY", "in ordinary minutes the held guest still leaves by the current rules")
|
||||
natural[&"clock"].advance_minutes(1)
|
||||
var departed: Dictionary = natural_runtime.create_snapshot()
|
||||
_expect(natural_runtime.guest_service.get_guest(&"p07_departing_guest") == null and natural_runtime.weather.get_rain_holds().is_empty()
|
||||
and natural_runtime.restore_snapshot(departed) and natural_runtime.create_snapshot() == departed, "the hold leaves with the guest, so the minute it left restores")
|
||||
var rainy := _new_runtime(SEED_RAIN)
|
||||
var runtime: Variant = rainy[&"runtime"]
|
||||
var guest: Variant = _spawn(runtime, &"p07_exit_guest", &"traveler", 362)
|
||||
|
||||
@@ -5,6 +5,8 @@ extends RefCounted
|
||||
## (tests/environment/test_p07_weather_restart_2_read.gd), which run as separate
|
||||
## engine processes. Seed 1106 opens day 0 with rain 06:00-12:00 (A13), a guest
|
||||
## due at 06:02 is held to 10:02, production arrivals run, and day 1 draws at 06:00.
|
||||
## With no facility in this world the held guest starts leaving at 06:03 (still
|
||||
## present with its hold) and is gone at 06:04 (its hold leaves with it).
|
||||
## The fog scene (WX7): seed 1592 opens day 0 with mana fog 06:00-10:00, two
|
||||
## adult-verified guests arrive at 06:58 and 09:58 (with no facility in this
|
||||
## world a guest leaves after a few minutes, so each one is present at its
|
||||
@@ -16,8 +18,10 @@ const WRITER_SAVE := "user://p07_restart_write/minute_%d"
|
||||
const READER_SAVE := "user://p07_restart_read/minute_%d"
|
||||
const SEED := 1106
|
||||
const FIRST_MINUTE := 360
|
||||
# Mid-rain, just before and just after the rain end, just before and just after the day 1 draw.
|
||||
const SAVE_MINUTES: Array[int] = [500, 719, 720, 1799, 1800]
|
||||
# The held guest present with its hold, the minute it left, mid-rain, just before and
|
||||
# just after the rain end, just before and just after the day 1 draw.
|
||||
const SAVE_MINUTES: Array[int] = [363, 364, 500, 719, 720, 1799, 1800]
|
||||
const HOLD := {"original_exit": 362, "extended_to": 602}
|
||||
const LAST_MINUTE := 1830
|
||||
const DRAW_MINUTES: Array[int] = [1800]
|
||||
const HELD_GUEST := &"p07_restart_guest"
|
||||
|
||||
Reference in New Issue
Block a user