103 lines
2.8 KiB
GDScript
103 lines
2.8 KiB
GDScript
class_name StorageStateRecord
|
|
extends RefCounted
|
|
|
|
const SCHEMA_VERSION := 1
|
|
const DEFAULT_CAPACITY := 100.0
|
|
|
|
var data: Dictionary
|
|
|
|
|
|
func _init(record_data: Dictionary = {}) -> void:
|
|
data = record_data.duplicate(true)
|
|
|
|
|
|
static func create(
|
|
storage_id: StringName, initial_amounts: Dictionary, capacity: float = DEFAULT_CAPACITY
|
|
) -> StorageStateRecord:
|
|
return StorageStateRecord.new(
|
|
{
|
|
"schema_version": SCHEMA_VERSION,
|
|
"storage_id": String(storage_id),
|
|
"amounts": initial_amounts.duplicate(true),
|
|
"capacity": capacity
|
|
}
|
|
)
|
|
|
|
|
|
static func from_dictionary(record_data: Dictionary) -> StorageStateRecord:
|
|
if int(record_data.get("schema_version", -1)) != SCHEMA_VERSION:
|
|
return null
|
|
if not record_data.has_all(["storage_id", "amounts", "capacity"]):
|
|
return null
|
|
if String(record_data["storage_id"]).is_empty():
|
|
return null
|
|
if not record_data["amounts"] is Dictionary:
|
|
return null
|
|
var capacity := float(record_data["capacity"])
|
|
if not is_finite(capacity) or capacity < 0.0:
|
|
return null
|
|
var normalized := record_data.duplicate(true)
|
|
normalized["schema_version"] = SCHEMA_VERSION
|
|
normalized["capacity"] = capacity
|
|
var normalized_amounts := {}
|
|
var total_amount := 0.0
|
|
for raw_item_id in record_data["amounts"]:
|
|
var item_id := String(raw_item_id)
|
|
var amount := float(record_data["amounts"][raw_item_id])
|
|
if (
|
|
item_id.is_empty()
|
|
or normalized_amounts.has(item_id)
|
|
or not is_finite(amount)
|
|
or amount < 0.0
|
|
):
|
|
return null
|
|
total_amount += amount
|
|
if not is_finite(total_amount) or total_amount > capacity:
|
|
return null
|
|
normalized_amounts[item_id] = amount
|
|
normalized["amounts"] = normalized_amounts
|
|
return StorageStateRecord.new(normalized)
|
|
|
|
|
|
func get_storage_id() -> StringName:
|
|
return StringName(data["storage_id"])
|
|
|
|
|
|
func get_amount(item_id: StringName) -> float:
|
|
return float(data["amounts"].get(String(item_id), 0.0))
|
|
|
|
|
|
func get_total_amount() -> float:
|
|
var total := 0.0
|
|
for amount in data["amounts"].values():
|
|
total += float(amount)
|
|
return total
|
|
|
|
|
|
func get_available_capacity() -> float:
|
|
return maxf(float(data["capacity"]) - get_total_amount(), 0.0)
|
|
|
|
|
|
func deposit(item_id: StringName, requested_amount: float) -> float:
|
|
if item_id.is_empty() or not is_finite(requested_amount) or requested_amount <= 0.0:
|
|
return 0.0
|
|
var accepted := minf(maxf(requested_amount, 0.0), get_available_capacity())
|
|
if accepted <= 0.0:
|
|
return 0.0
|
|
data["amounts"][String(item_id)] = get_amount(item_id) + accepted
|
|
return accepted
|
|
|
|
|
|
func withdraw(item_id: StringName, requested_amount: float) -> float:
|
|
if item_id.is_empty() or not is_finite(requested_amount) or requested_amount <= 0.0:
|
|
return 0.0
|
|
var removed := minf(maxf(requested_amount, 0.0), get_amount(item_id))
|
|
if removed <= 0.0:
|
|
return 0.0
|
|
data["amounts"][String(item_id)] = get_amount(item_id) - removed
|
|
return removed
|
|
|
|
|
|
func to_dictionary() -> Dictionary:
|
|
return data.duplicate(true)
|