Files
owniverse/tests/fixtures/legacy_quantity_math.gd
T
Kirill c4e7302567 Add new tests and implement frame budget management
- Introduced `civilization_benchmark.gd` and `legacy_quantity_math.gd` for benchmarking and legacy quantity calculations.
- Created `test_dynamic_math.gd`, `test_frame_evolution.gd`, and `test_sparse_batches.gd` to validate mathematical operations and frame evolution logic.
- Implemented `frame_budget.gd` to manage cooperative work on the main thread, ensuring no partially calculated state is published.
- Added UID files for all new scripts to maintain unique identifiers.
2026-10-01 23:43:34 +03:00

60 lines
2.7 KiB
GDScript

extends RefCounted
const E = preload("res://world/owniverse/math/exact.gd")
# Frozen apportionment before the civilization performance refactor.
static func allocate_whole(requests: Dictionary, limit: Variant) -> Dictionary:
var total: Variant = 0
for amount in requests.values():
total = E.add(total, E.floor_value(E.maximum(0, amount)))
var available: Variant = E.floor_value(E.minimum(E.maximum(0, limit), total))
var result: Dictionary = {}
var order: Array = []
var assigned: Variant = 0
for id in requests:
var expected: Variant = (E.mul_div(E.floor_value(E.maximum(0, requests[id])), available, total) if E.gt(total, 0) else 0)
result[id] = E.floor_value(expected)
assigned = E.add(assigned, result[id])
order.append({"id": id, "rest": E.subtract(expected, result[id])})
order.sort_custom(func ( a : Dictionary , b : Dictionary ) -> bool : return (E.gt(a.rest, b.rest) if E.ne(a.rest, b.rest) else E.lt(str(a.id), str(b.id))))
for item : Dictionary in order:
if E.ge(assigned, available):
break
if E.lt(result[item.id], E.floor_value(requests[item.id])):
result[item.id] = E.add(result[item.id], 1)
assigned = E.add(assigned, 1)
return result
static func sum(pop: Dictionary) -> Variant:
var result: Variant = 0
for n in pop.values(): result = E.add(result, n)
return result
static func split(remainders: Dictionary, key: String, count: Variant, weights: Dictionary) -> Dictionary:
var result: Dictionary = {}
var sum_weights: Variant = sum(weights)
if (E.le(count, 0) or E.le(sum_weights, 0)): return result
var expected: Dictionary = {}
var positive_sum: Variant = 0
for id in weights:
expected[id] = E.add(E.mul_div(count, weights[id], sum_weights), remainders.get(E.add(E.add(key, ":"), id), 0))
positive_sum = E.add(positive_sum, E.maximum(0, expected[id]))
var order: Array = []
var assigned: Variant = 0
for id in weights:
var normalized: Variant = (E.mul_div(E.maximum(0, expected[id]), count, positive_sum) if E.gt(positive_sum, 0) else 0)
result[id] = E.floor_value(normalized)
assigned = E.add(assigned, result[id])
order.append({"id": id, "rest": E.subtract(normalized, result[id])})
order.sort_custom(func ( a , b ) : return (E.gt(a.rest, b.rest) if E.ne(a.rest, b.rest) else E.lt(str(a.id), str(b.id))))
for entry in order:
if E.ge(assigned, count): break
result[entry.id] = E.add(result[entry.id], 1)
assigned = E.add(assigned, 1)
for id in weights:
remainders[E.add(E.add(key, ":"), id)] = E.clamp_value(E.subtract(expected[id], result[id]), E.neg(1), 1)
return result