Capture current source, content data, tests, asset licenses, and original-specification traceability. Original implementation remains incomplete. The accepted matching UI generation passed 154 suites and 12,253 checks, with eight rendered staff-contract screens reviewed. Latest native Windows and full-original acceptance remain outstanding.
129 lines
7.8 KiB
GDScript
129 lines
7.8 KiB
GDScript
extends SceneTree
|
|
|
|
const Accrual = preload("res://scripts/economy/facility_upkeep_accrual.gd")
|
|
const Settlement = preload("res://scripts/economy/facility_upkeep_settlement.gd")
|
|
var checks := 0
|
|
var failures := 0
|
|
|
|
class RejectingEconomy:
|
|
extends EconomyService
|
|
func post(_entries: Array, _key: StringName = &"", _transaction: StringName = &"", _notify := true) -> CommandResult:
|
|
return CommandResult.failed(CommandResult.Code.VALIDATION_FAILED, 0, "injected refusal")
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
func expect(value: bool, label: String) -> void:
|
|
checks += 1
|
|
if not value:
|
|
failures += 1
|
|
push_error(label)
|
|
|
|
func _economy(cash: int) -> EconomyService:
|
|
var economy := EconomyService.new({&"PLAYER_CASH": false})
|
|
if cash > 0:
|
|
economy.initialize_account(&"PLAYER_CASH", cash)
|
|
expect(Settlement.prepare_accounts(economy), "prepare designated expense/payable accounts")
|
|
return economy
|
|
|
|
func _period(start: int, units: Dictionary) -> Dictionary:
|
|
return {&"period_start": start, &"period_end": (start / 1440 + 1) * 1440, &"facility_units": units}
|
|
|
|
func _run() -> void:
|
|
var economy := _economy(5)
|
|
var service := Settlement.new()
|
|
var period := _period(0, {"a": 10 * 1440, "b": 2 * 1440 + 10})
|
|
var first := service.settle(period, economy)
|
|
expect(first.ok and not first.replayed, "first midnight settles")
|
|
expect(economy.get_balance(Settlement.CASH) == 0, "cash cannot become negative")
|
|
expect(economy.get_balance(Settlement.EXPENSE) == 12, "expense includes unpaid amount")
|
|
expect(economy.get_balance(Settlement.PAYABLE) == -7, "seven gold remains payable")
|
|
expect(service.get_report().arrears_by_facility == {"a": 5, "b": 2}, "insufficient funds allocate deterministically by facility ID")
|
|
expect(service.get_report().fraction_units == {"b": 10}, "sub-gold expense is retained")
|
|
expect(economy.has_pending_transaction_notification(first.transaction_id), "notification is deferred to outer transaction commit")
|
|
expect(economy.commit_transaction_notification(first.transaction_id), "notification can be published after state commit")
|
|
var guard := economy.create_snapshot()
|
|
var snapshot := service.create_snapshot()
|
|
var replay := service.settle(period, economy)
|
|
expect(replay.ok and replay.replayed and replay.transaction_id == &"", "same settlement is idempotent and emits no notification")
|
|
expect(economy.create_snapshot() == guard and service.create_snapshot() == snapshot, "replay changes neither balances nor receipts")
|
|
var wrong := period.duplicate(true)
|
|
wrong.facility_units.a += 1
|
|
expect(not service.settle(wrong, economy).ok and economy.create_snapshot() == guard, "changed request cannot reuse a closed period")
|
|
expect(not service.settle(_period(2880, {}), economy).ok, "missing financial day rejected")
|
|
# Facility a has been demolished; its debt must still be paid next midnight.
|
|
economy.initialize_account(Settlement.CASH, 20, 1500, &"cash.for.next.day")
|
|
var second := service.settle(_period(1440, {"b": 1430}), economy)
|
|
expect(second.ok, "following day settles including prior arrears")
|
|
expect(service.get_arrears_through(1439) == 0, "no historical debt before first settlement")
|
|
expect(service.get_arrears_through(1440) == 7, "historical close retains its original debt after repayment")
|
|
expect(service.get_arrears_through(2879) == 7, "interim query uses the last completed settlement")
|
|
expect(service.get_arrears_through(2880) == 0, "repayment boundary clears current debt")
|
|
expect(service.get_arrears_through(9999) == 0, "future query does not invent debt")
|
|
expect(economy.get_balance(Settlement.EXPENSE) == 13, "prior debt repayment is not a new expense")
|
|
expect(economy.get_balance(Settlement.CASH) == 12 and economy.get_balance(Settlement.PAYABLE) == 0, "eight gold pays debt and new fractional carry")
|
|
expect(service.get_report().arrears_total == 0 and service.get_report().fraction_units.is_empty(), "debt and fractions cleared after payment")
|
|
expect(service.validate_ledger(economy) and economy.validate_ledger().ok, "service and double-entry ledger reconcile")
|
|
var expense_entries := 0
|
|
var payment_entries := 0
|
|
for entry: LedgerEntry in economy.get_entries():
|
|
if entry.category == &"MAINTENANCE_ACCRUAL":
|
|
expense_entries += 1
|
|
expect(entry.absolute_minute in [1439, 2879], "expense belongs to the day being closed")
|
|
if entry.category == &"MAINTENANCE_PAYMENT":
|
|
payment_entries += 1
|
|
expect(entry.absolute_minute in [1440, 2880], "cash payment records actual midnight")
|
|
expect(expense_entries == 3 and payment_entries == 3, "only positive recognized expenses and payments produce entries")
|
|
var loaded_economy := EconomyService.new()
|
|
expect(loaded_economy.restore_snapshot(economy.create_snapshot()), "ledger restores")
|
|
var loaded := Settlement.new()
|
|
expect(loaded.restore_snapshot(service.create_snapshot(), loaded_economy), "receipts restore with ledger crosschecks")
|
|
expect(loaded.get_report() == service.get_report(), "derived debt/fractions rebuild exactly")
|
|
var future := _period(2880, {"new": 3 * 1440})
|
|
expect(service.settle(future, economy).ok and loaded.settle(future, loaded_economy).ok, "both timelines advance")
|
|
expect(service.create_snapshot() == loaded.create_snapshot() and economy.create_snapshot() == loaded_economy.create_snapshot(), "same future after reload")
|
|
var valid := loaded.create_snapshot()
|
|
var invalid := valid.duplicate(true)
|
|
invalid.receipts[0].rows[0].new_expense += 1
|
|
expect(not loaded.restore_snapshot(invalid, loaded_economy) and loaded.create_snapshot() == valid, "forged expense rejected atomically")
|
|
invalid = valid.duplicate(true)
|
|
invalid.receipts[0].rows[0].paid = true
|
|
expect(not loaded.restore_snapshot(invalid, loaded_economy), "boolean amount rejected")
|
|
invalid = valid.duplicate(true)
|
|
invalid.receipts[0].transaction_id = "missing"
|
|
expect(not loaded.restore_snapshot(invalid, loaded_economy), "missing ledger transaction rejected")
|
|
invalid = valid.duplicate(true)
|
|
invalid.receipts[0].period.facility_units.a += 1
|
|
expect(not loaded.restore_snapshot(invalid, loaded_economy), "forged numerator and unchanged receipt rejected")
|
|
invalid = valid.duplicate(true)
|
|
invalid.receipts.pop_front()
|
|
expect(not loaded.restore_snapshot(invalid, loaded_economy), "omitting settled debt history rejected by ledger ownership")
|
|
invalid = valid.duplicate(true)
|
|
invalid.version = 2
|
|
expect(not loaded.restore_snapshot(invalid, loaded_economy), "unknown save version rejected")
|
|
var unrelated := _economy(100)
|
|
expect(not loaded.restore_snapshot(valid, unrelated), "receipts cannot be restored onto unrelated money")
|
|
var rejecting := RejectingEconomy.new({Settlement.CASH: false})
|
|
expect(Settlement.prepare_accounts(rejecting), "prepare rejecting ledger")
|
|
var failed_service := Settlement.new()
|
|
var before_service := failed_service.create_snapshot()
|
|
var before_ledger := rejecting.create_snapshot()
|
|
expect(not failed_service.settle(_period(0, {"room": 1440}), rejecting).ok, "ledger failure propagates")
|
|
expect(failed_service.create_snapshot() == before_service and rejecting.create_snapshot() == before_ledger, "failed ledger post leaves all authoritative state unchanged")
|
|
var empty := Settlement.new()
|
|
var no_cash := _economy(0)
|
|
expect(empty.settle(_period(0, {}), no_cash).ok, "empty day requires no zero-value ledger entry")
|
|
var empty_loaded := Settlement.new()
|
|
expect(empty_loaded.restore_snapshot(empty.create_snapshot(), no_cash), "empty settled day persists")
|
|
# End-to-end cost math at completion/demolition boundaries with real ledger.
|
|
var accrual := Accrual.new()
|
|
accrual.start_at(360)
|
|
accrual.advance_to(720, {})
|
|
accrual.advance_to(1080, {"built_at_noon": 24})
|
|
var closed: Dictionary = accrual.advance_to(1440, {}).closed_periods[0]
|
|
var life := Settlement.new()
|
|
var life_cash := _economy(100)
|
|
expect(life.settle(closed, life_cash).ok and life_cash.get_balance(Settlement.EXPENSE) == 6, "six-hour completed ownership charges six gold after demolition")
|
|
print("%s: %d checks" % ["PASS" if failures == 0 else "FAIL", checks])
|
|
quit(failures)
|