155 lines
4.7 KiB
Python
155 lines
4.7 KiB
Python
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
|