Files
owniverse/tests/test_time.gd
T

94 lines
4.3 KiB
GDScript
Raw Normal View History

extends SceneTree
const E = preload("res://world/owniverse/math/exact.gd")
const Clock = preload("res://world/owniverse/simulation_time.gd")
var checks: int = 0
var failures: int = 0
func _initialize() -> void:
call_deferred("run")
func check(condition: bool, message: String) -> void:
checks = E.add(checks, 1)
if (not condition):
failures = E.add(failures, 1)
push_error(message)
func fixture():
var world = load("res://world/owniverse/owniverse.gd").new()
var global: Node = root.get_node("Global")
for id in global.OwniverseEntities:
var entity = load("res://world/owniverse/owniverse_entity.gd").new(global.OwniverseEntities[id])
world.catalog.entities[id] = entity
world.state.amount[id] = 0
world.state.stats.total_amount[id] = 0
if E.ne(entity.group_as, ""):
world.state.amount[entity.group_as] = 0
world.state.stats.total_amount[entity.group_as] = 0
world.catalog.entities["N"].life_product = {}
world.catalog.entities["N"].product_per_year_type = "H"
world.catalog.entities["N"].product_per_year_amount = 10
world.catalog.entities["N"].auto = 0
world.state.amount.N = 1
return world
func dispose(world) -> void:
for entity in world.catalog.entities.values():
entity.free()
world.free()
func run() -> void:
var saves: Node = root.get_node("SaveManager")
var world = fixture()
world.evolute(E.of("0.09"))
check(E.eq(world.state.time.year, 0), "Do not process before a tenth boundary")
check(E.eq(world.state.amount.H, 0), "No premature production")
world.evolute(E.of("0.01"))
check(E.eq(world.state.time.year, E.of("0.1")), "Process the first tenth")
check(E.eq(world.state.amount.H, 1), "Production runs at 0.1 year")
world.evolute(E.of("0.2"))
check((E.eq(world.state.time.year, E.of("0.3")) and E.eq(world.state.amount.H, 3)), "Do not reprocess previous tenths")
var before: Dictionary = world.state.duplicate(true)
2026-10-01 07:48:52 +03:00
for invalid in [0, E.neg(1), NAN, INF, 1e308]:
world.evolute(invalid)
check(E.eq(world.state, before), "Invalid/overflow interval rejected")
check(E.eq(saves.validate_data({"format_version": 6, "app_version": "", "ui": {"current_page": 0}, "state": world.state}), ""), "Fractional save is valid")
var invalid_save: Dictionary = world.state.duplicate(true)
invalid_save.time.year = E.of("0.25")
check(E.ne(saves.validate_data({"format_version": 6, "app_version": "", "ui": {"current_page": 0}, "state": invalid_save}), ""), "Reject inconsistent fractional clock")
dispose(world)
for fps in [30, 60, 144]:
world = fixture()
for frame in fps:
world.evolute(E.divide(1, fps))
check(E.eq(world.state.time.year, 1), ("One second at %d fps" % fps))
check(E.eq(world.state.amount.H, 10), ("Production across frames at %d fps" % fps))
dispose(world)
world = fixture()
world.evolute(E.of("0.05"))
world.speed = 2
world.evolute(E.of("0.005"))
check(E.eq(world.state.time.year, E.of("0.1")), "Speed change preserves accumulated fraction")
world.speed = 100
var speed_limit: int = root.get_node("Global").SPEED_LIMIT
check((E.eq(world.speed, speed_limit) and E.eq(world.state.speed_in_year, E.power(10, E.subtract(speed_limit, 1)))), "Configured upper speed limit")
world.speed = E.neg(10)
check((E.eq(world.speed, 1) and E.eq(world.state.speed_in_year, 1)), "Lower speed limit unchanged")
dispose(world)
world = fixture()
dispose(world)
world = fixture()
world.catalog.entities.N.output_and = {"He": 1}
world.catalog.entities.N.output_or = {}
world.state.batches.N = [{"start_year": E.of("0.1"), "end_year": E.of("0.1"), "amount": 1}]
world.evolute(E.of("0.1"))
check((E.eq(world.state.amount.N, 0) and E.eq(world.state.amount.He, 1)), "Existing evolution executes at fractional boundary")
dispose(world)
check(E.eq(Clock.processed_year(E.of("0.099")), 0), "Do not round a genuine incomplete tenth forward")
check(E.eq(Clock.processed_year(E.add(E.of("1e9"), E.of("0.45"))), E.add(E.of("1e9"), E.of("0.4"))), "Large ages preserve fractional precision")
print(("Time state: %d checks, %d failures" % [checks, failures]))
quit((0 if E.eq(failures, 0) else 1))