fix(simulation): use report step for schemes
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
import json
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from app.infra.db.timescaledb.repositories.scheme import SchemeRepository
|
||||
from app.services.time_api import parse_utc_time
|
||||
|
||||
|
||||
def _node_result(periods: int) -> list[dict]:
|
||||
return [
|
||||
{
|
||||
"node": "J1",
|
||||
"result": [
|
||||
{"demand": index, "head": index, "pressure": index, "quality": index}
|
||||
for index in range(periods)
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def _link_result(periods: int) -> list[dict]:
|
||||
return [
|
||||
{
|
||||
"link": "P1",
|
||||
"result": [
|
||||
{
|
||||
"flow": index,
|
||||
"friction": index,
|
||||
"headloss": index,
|
||||
"quality": index,
|
||||
"reaction": index,
|
||||
"setting": index,
|
||||
"status": index,
|
||||
"velocity": index,
|
||||
}
|
||||
for index in range(periods)
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_store_scheme_simulation_uses_15_minute_report_step(monkeypatch):
|
||||
inserted: dict[str, list[dict]] = {}
|
||||
|
||||
monkeypatch.setattr(
|
||||
SchemeRepository,
|
||||
"insert_nodes_batch_sync",
|
||||
staticmethod(lambda conn, data: inserted.setdefault("nodes", data)),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
SchemeRepository,
|
||||
"insert_links_batch_sync",
|
||||
staticmethod(lambda conn, data: inserted.setdefault("links", data)),
|
||||
)
|
||||
|
||||
SchemeRepository.store_scheme_simulation_result_sync(
|
||||
conn=object(),
|
||||
scheme_type="burst_analysis",
|
||||
scheme_name="five_hour_case",
|
||||
node_result_list=_node_result(21),
|
||||
link_result_list=_link_result(21),
|
||||
result_start_time="2026-07-16T00:00:00Z",
|
||||
num_periods=21,
|
||||
result_timestep_seconds=900,
|
||||
)
|
||||
|
||||
start_time = parse_utc_time("2026-07-16T00:00:00Z")
|
||||
assert len(inserted["nodes"]) == 21
|
||||
assert inserted["nodes"][0]["time"] == start_time
|
||||
assert inserted["nodes"][-1]["time"] == start_time + timedelta(hours=5)
|
||||
assert inserted["links"][-1]["time"] == start_time + timedelta(hours=5)
|
||||
|
||||
|
||||
def test_store_scheme_simulation_uses_hourly_report_step(monkeypatch):
|
||||
inserted: dict[str, list[dict]] = {}
|
||||
|
||||
monkeypatch.setattr(
|
||||
SchemeRepository,
|
||||
"insert_nodes_batch_sync",
|
||||
staticmethod(lambda conn, data: inserted.setdefault("nodes", data)),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
SchemeRepository,
|
||||
"insert_links_batch_sync",
|
||||
staticmethod(lambda conn, data: inserted.setdefault("links", data)),
|
||||
)
|
||||
|
||||
SchemeRepository.store_scheme_simulation_result_sync(
|
||||
conn=object(),
|
||||
scheme_type="burst_analysis",
|
||||
scheme_name="hourly_case",
|
||||
node_result_list=_node_result(6),
|
||||
link_result_list=_link_result(6),
|
||||
result_start_time="2026-07-16T00:00:00Z",
|
||||
num_periods=6,
|
||||
result_timestep_seconds=3600,
|
||||
)
|
||||
|
||||
start_time = parse_utc_time("2026-07-16T00:00:00Z")
|
||||
assert [item["time"] for item in inserted["nodes"]] == [
|
||||
start_time + timedelta(hours=index) for index in range(6)
|
||||
]
|
||||
|
||||
|
||||
def test_run_simulation_passes_report_step_for_extended_scheme(monkeypatch):
|
||||
import app.services.simulation as simulation
|
||||
|
||||
time_updates: list[dict] = []
|
||||
storage_calls: list[tuple] = []
|
||||
|
||||
monkeypatch.setattr(simulation, "open_project", lambda name: None)
|
||||
monkeypatch.setattr(
|
||||
simulation,
|
||||
"get_time",
|
||||
lambda name: {
|
||||
"HYDRAULIC TIMESTEP": "00:15:00",
|
||||
"REPORT TIMESTEP": "1:00",
|
||||
"DURATION": "0:00",
|
||||
"PATTERN START": "0:00",
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
simulation,
|
||||
"set_time",
|
||||
lambda name, changeset: time_updates.append(changeset.operations[0]),
|
||||
)
|
||||
monkeypatch.setattr(simulation, "run_project", lambda name: json.dumps({
|
||||
"simulation_result": "successful",
|
||||
"output": {
|
||||
"times": {"num_periods": 21, "report_step": 900},
|
||||
"node_results": _node_result(21),
|
||||
"link_results": _link_result(21),
|
||||
},
|
||||
}))
|
||||
monkeypatch.setattr(
|
||||
simulation.TimescaleInternalStorage,
|
||||
"store_scheme_simulation",
|
||||
staticmethod(lambda *args, **kwargs: storage_calls.append((args, kwargs))),
|
||||
)
|
||||
|
||||
simulation.run_simulation(
|
||||
name="fengyang",
|
||||
simulation_type="extended",
|
||||
modify_pattern_start_time="2026-07-16T00:00:00+08:00",
|
||||
modify_total_duration=18000,
|
||||
scheme_type="burst_analysis",
|
||||
scheme_name="five_hour_case",
|
||||
)
|
||||
|
||||
assert time_updates[0]["DURATION"] == "05:00:00"
|
||||
assert time_updates[0]["REPORT TIMESTEP"] == "1:00"
|
||||
assert storage_calls[0][0][5] == 21
|
||||
assert storage_calls[0][0][6] == 900
|
||||
Reference in New Issue
Block a user