refactor(db)!: adopt project-routed pooled databases

Reorganize WNDB by responsibility and remove legacy scheme endpoints.\n\nRoute analysis and time-series access through project pools, preserve transactional realtime replacement, and refresh GIS materialized views after writes.\n\nAdd database architecture documentation, live pooling coverage, API contract updates, and executable container verification.\n\nBREAKING CHANGE: legacy scheme APIs and flat app.native.wndb module imports are removed.
This commit is contained in:
2026-08-25 18:35:05 +08:00
parent fdbcc5c033
commit fa188af0b1
181 changed files with 8446 additions and 33546 deletions
+104
View File
@@ -0,0 +1,104 @@
from app.native.wndb.commands.executor import execute_batch_command
from app.native.wndb.core.database import ChangeSet
from app.native.wndb.gis.region_geometry import Topology, get_nodes_in_region
from app.native.wndb.model.demands import get_demand
from app.native.wndb.model.elements import get_nodes, is_junction
DISTRIBUTION_TYPE_ADD = 'ADD'
DISTRIBUTION_TYPE_OVERRIDE = 'OVERRIDE'
def calculate_demand_to_nodes(name: str, demand: float, nodes: list[str]) -> dict[str, float]:
if len(nodes) == 0 or demand == 0.0:
return {}
topology = Topology(name, nodes)
t_nodes = topology.nodes()
t_links = topology.links()
length_sum = 0.0
for value in t_links.values():
length_sum += abs(value['length'])
if length_sum <= 0.0:
return {}
demand_per_length = demand / length_sum
result: dict[str, float] = {}
for node, value in t_nodes.items():
if not is_junction(name, node):
continue
demand_per_node = 0.0
for link in value['links']:
demand_per_node += abs(t_links[link]['length']) * demand_per_length * 0.5
result[node] = demand_per_node
return result
def calculate_demand_to_region(name: str, demand: float, region: str) -> dict[str, float]:
nodes = get_nodes_in_region(name, region)
return calculate_demand_to_nodes(name, demand, nodes)
def calculate_demand_to_network(name: str, demand: float) -> dict[str, float]:
nodes = get_nodes(name)
return calculate_demand_to_nodes(name, demand, nodes)
def distribute_demand_to_nodes(name: str, demand: float, nodes: list[str], type: str = DISTRIBUTION_TYPE_ADD) -> ChangeSet:
if len(nodes) == 0 or demand == 0.0:
return ChangeSet()
if type != DISTRIBUTION_TYPE_ADD and type != DISTRIBUTION_TYPE_OVERRIDE:
return ChangeSet()
topology = Topology(name, nodes)
t_nodes = topology.nodes()
t_links = topology.links()
length_sum = 0.0
for value in t_links.values():
length_sum += abs(value['length'])
if length_sum <= 0.0:
return ChangeSet()
demand_per_length = demand / length_sum
cs = ChangeSet()
for node, value in t_nodes.items():
if not is_junction(name, node):
continue
demand_per_node = 0.0
for link in value['links']:
demand_per_node += abs(t_links[link]['length']) * demand_per_length * 0.5
ds = get_demand(name, node)['demands']
if len(ds) == 0:
ds = [{'demand': demand_per_node, 'pattern': None, 'category': None}]
elif type == DISTRIBUTION_TYPE_ADD:
ds[0]['demand'] += demand_per_node
else:
ds[0]['demand'] = demand_per_node
cs.update({'type': 'demand', 'junction': node, 'demands': ds})
return execute_batch_command(name, cs)
def distribute_demand_to_region(name: str, demand: float, region: str, type: str = DISTRIBUTION_TYPE_ADD) -> ChangeSet:
nodes = get_nodes_in_region(name, region)
return distribute_demand_to_nodes(name, demand, nodes, type)
def get_total_base_demand(name:str,region:str)->float:
nodes = get_nodes_in_region(name, region)
t_demands=0.0
for node in nodes:
if not is_junction(name, node):
continue
ds = get_demand(name, node)['demands']
t_demands= t_demands+ds[0]['demand']
return t_demands