fix
parent
366e4d9753
commit
bd437651a2
@ -0,0 +1,163 @@
|
|||||||
|
import json
|
||||||
|
from collections import defaultdict
|
||||||
|
from sqlalchemy import create_engine, text
|
||||||
|
|
||||||
|
# 🔧 Adjust this to your environment
|
||||||
|
DB_URL = "postgresql+psycopg2://postgres:postgres@192.168.1.86:5432/digital_aeros_fixed"
|
||||||
|
|
||||||
|
def export_rbd_json(project_id, output_file="rbd.json"):
|
||||||
|
engine = create_engine(DB_URL)
|
||||||
|
|
||||||
|
with engine.connect() as conn:
|
||||||
|
# --- Project info ---
|
||||||
|
project = conn.execute(
|
||||||
|
text('SELECT "ProjectId","ProjectName" FROM public."Projects" WHERE "ProjectId" = :pid'),
|
||||||
|
{"pid": project_id}
|
||||||
|
).mappings().first()
|
||||||
|
if not project:
|
||||||
|
raise ValueError(f"❌ Project {project_id} not found")
|
||||||
|
|
||||||
|
print(f"🔍 Loaded project: {project['ProjectName']} (ID={project_id})")
|
||||||
|
|
||||||
|
# --- Schematics ---
|
||||||
|
schematics = conn.execute(
|
||||||
|
text('SELECT "SchematicId","SchematicName" FROM public."Schematics" WHERE "ProjectId" = :pid'),
|
||||||
|
{"pid": project_id}
|
||||||
|
).mappings().all()
|
||||||
|
|
||||||
|
all_schematics_json = {}
|
||||||
|
|
||||||
|
for s in schematics:
|
||||||
|
sid = s["SchematicId"]
|
||||||
|
sname = s["SchematicName"]
|
||||||
|
print(f"\n=== Processing schematic {sid} ({sname}) ===")
|
||||||
|
|
||||||
|
# --- Nodes ---
|
||||||
|
nodes_data = conn.execute(
|
||||||
|
text('SELECT "NodeId","NodeUIId","NodeName","NodeTypeCode" '
|
||||||
|
'FROM public."RegularNodes" WHERE "SchematicId" = :sid'),
|
||||||
|
{"sid": sid}
|
||||||
|
).mappings().all()
|
||||||
|
|
||||||
|
# dict keyed by NodeId
|
||||||
|
nodes = {str(n["NodeId"]): dict(n) for n in nodes_data}
|
||||||
|
# map UIId -> NodeId
|
||||||
|
uiid_to_id = {str(n["NodeUIId"]): str(n["NodeId"]) for n in nodes_data}
|
||||||
|
|
||||||
|
print(f"🟦 Nodes: {len(nodes)}")
|
||||||
|
|
||||||
|
# --- Connectors (edges) ---
|
||||||
|
edges = conn.execute(
|
||||||
|
text('SELECT "SourceUIId","SinkUIId" FROM public."Connectors" WHERE "SchematicId" = :sid'),
|
||||||
|
{"sid": sid}
|
||||||
|
).mappings().all()
|
||||||
|
|
||||||
|
children_map = defaultdict(list)
|
||||||
|
for e in edges:
|
||||||
|
src_ui = str(e["SourceUIId"])
|
||||||
|
sink_ui = str(e["SinkUIId"])
|
||||||
|
if src_ui in uiid_to_id and sink_ui in uiid_to_id:
|
||||||
|
src_id = uiid_to_id[src_ui]
|
||||||
|
sink_id = uiid_to_id[sink_ui]
|
||||||
|
children_map[src_id].append(sink_id)
|
||||||
|
|
||||||
|
print(f"🔗 Connectors: {len(edges)}")
|
||||||
|
|
||||||
|
# --- Redundancies ---
|
||||||
|
redundancies = conn.execute(
|
||||||
|
text('SELECT * FROM public."Redundancies" WHERE "SchematicId" = :sid'),
|
||||||
|
{"sid": sid}
|
||||||
|
).mappings().all()
|
||||||
|
|
||||||
|
states = conn.execute(
|
||||||
|
text('SELECT * FROM public."RedundancyStates" WHERE "RedundancyId" IN '
|
||||||
|
'(SELECT "RedundancyId" FROM public."Redundancies" WHERE "SchematicId" = :sid)'),
|
||||||
|
{"sid": sid}
|
||||||
|
).mappings().all()
|
||||||
|
|
||||||
|
state_cells = conn.execute(
|
||||||
|
text('SELECT * FROM public."RedundancyStateCells" WHERE "RedundancyStateId" IN '
|
||||||
|
'(SELECT "StateId" FROM public."RedundancyStates" WHERE "RedundancyId" IN '
|
||||||
|
'(SELECT "RedundancyId" FROM public."Redundancies" WHERE "SchematicId" = :sid))'),
|
||||||
|
{"sid": sid}
|
||||||
|
).mappings().all()
|
||||||
|
|
||||||
|
# Build redundancy structure
|
||||||
|
redundancy_map = {}
|
||||||
|
for r in redundancies:
|
||||||
|
rid = str(r["RedundancyId"])
|
||||||
|
redundancy_map[rid] = {
|
||||||
|
"name": r["RedundancyName"],
|
||||||
|
"type": "standby" if r["IsKNStandby"] else "kofn",
|
||||||
|
"min_required": r["MinRequiredNodes"],
|
||||||
|
"switch_delay": r["SwitchDelay"],
|
||||||
|
"states": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for st in states:
|
||||||
|
sid2 = str(st["StateId"])
|
||||||
|
rid = str(st["RedundancyId"])
|
||||||
|
redundancy_map[rid]["states"][sid2] = {
|
||||||
|
"priority": st["StatePriority"],
|
||||||
|
"duration": st["StateDuration"],
|
||||||
|
"cells": []
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in state_cells:
|
||||||
|
sid2 = str(c["RedundancyStateId"])
|
||||||
|
for r_id, r in redundancy_map.items():
|
||||||
|
if sid2 in r["states"]:
|
||||||
|
node_id = str(c["InvolvedNodeId"])
|
||||||
|
if node_id in nodes: # only link if valid
|
||||||
|
r["states"][sid2]["cells"].append({
|
||||||
|
"node_id": node_id,
|
||||||
|
"status": c["NodeStatusCode"]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
# --- Build JSON nodes ---
|
||||||
|
json_nodes = {}
|
||||||
|
for node_id, n in nodes.items():
|
||||||
|
node_type = str(n["NodeTypeCode"]).lower()
|
||||||
|
node_json = {
|
||||||
|
"type": node_type,
|
||||||
|
"name": n["NodeName"],
|
||||||
|
"children": children_map.get(node_id, []), # now NodeId-based
|
||||||
|
"availability": 1.0 # ✅ default availability
|
||||||
|
}
|
||||||
|
json_nodes[node_id] = node_json
|
||||||
|
|
||||||
|
# --- Root detection ---
|
||||||
|
all_children = {c for lst in children_map.values() for c in lst}
|
||||||
|
root_candidates = [nid for nid in nodes.keys() if nid not in all_children]
|
||||||
|
root = root_candidates[0] if root_candidates else None
|
||||||
|
print(f"🌳 Root node detected: {root}")
|
||||||
|
|
||||||
|
# --- Assemble schematic JSON ---
|
||||||
|
schematic_json = {
|
||||||
|
"schematic_id": sid,
|
||||||
|
"schematic_name": sname,
|
||||||
|
"root": str(root) if root else None,
|
||||||
|
"nodes": json_nodes,
|
||||||
|
"redundancies": redundancy_map
|
||||||
|
}
|
||||||
|
all_schematics_json[str(sid)] = schematic_json
|
||||||
|
|
||||||
|
print(f"✅ Finished schematic {sid}")
|
||||||
|
|
||||||
|
# --- Final JSON ---
|
||||||
|
final_json = {
|
||||||
|
"project_id": project["ProjectId"],
|
||||||
|
"project_name": project["ProjectName"],
|
||||||
|
"schematics": all_schematics_json
|
||||||
|
}
|
||||||
|
|
||||||
|
with open(output_file, "w") as f:
|
||||||
|
json.dump(final_json, f, indent=2)
|
||||||
|
|
||||||
|
print(f"\n🎉 Exported simplified RBD JSON (NodeId-based, availability=1.0) "
|
||||||
|
f"for Project {project_id} → {output_file}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
export_rbd_json(project_id=70, output_file="project_70_rbd.json")
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,111 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
def series_availability(avails):
|
||||||
|
result = 1.0
|
||||||
|
for a in avails:
|
||||||
|
result *= a
|
||||||
|
return result
|
||||||
|
|
||||||
|
def parallel_availability(avails):
|
||||||
|
result = 1.0
|
||||||
|
for a in avails:
|
||||||
|
result *= (1 - a)
|
||||||
|
return 1 - result
|
||||||
|
|
||||||
|
def kofn_availability(avails, k):
|
||||||
|
if k <= 1:
|
||||||
|
return parallel_availability(avails)
|
||||||
|
return sum(avails) / len(avails) # simple approx
|
||||||
|
|
||||||
|
def compute_node_availability(node_id, schematic, schematics, overrides, visited):
|
||||||
|
if node_id in visited:
|
||||||
|
return 1.0
|
||||||
|
visited.add(node_id)
|
||||||
|
|
||||||
|
node = schematic["nodes"].get(node_id)
|
||||||
|
if not node:
|
||||||
|
return 1.0
|
||||||
|
|
||||||
|
node_name = node.get("name", "").strip().lower()
|
||||||
|
if node_name in overrides:
|
||||||
|
return overrides[node_name]
|
||||||
|
|
||||||
|
ntype = node["type"].lower()
|
||||||
|
|
||||||
|
if ntype == "regularnode":
|
||||||
|
return node.get("availability", 1.0)
|
||||||
|
|
||||||
|
elif ntype == "series":
|
||||||
|
return series_availability([
|
||||||
|
compute_node_availability(child, schematic, schematics, overrides, visited.copy())
|
||||||
|
for child in node.get("children", [])
|
||||||
|
])
|
||||||
|
|
||||||
|
elif ntype == "parallel":
|
||||||
|
return parallel_availability([
|
||||||
|
compute_node_availability(child, schematic, schematics, overrides, visited.copy())
|
||||||
|
for child in node.get("children", [])
|
||||||
|
])
|
||||||
|
|
||||||
|
elif ntype == "kofn":
|
||||||
|
k = node.get("min_required", 1)
|
||||||
|
return kofn_availability([
|
||||||
|
compute_node_availability(child, schematic, schematics, overrides, visited.copy())
|
||||||
|
for child in node.get("children", [])
|
||||||
|
], k)
|
||||||
|
|
||||||
|
elif ntype == "subschematic":
|
||||||
|
tschematic_id = node.get("tschematic_id")
|
||||||
|
if tschematic_id and str(tschematic_id) in schematics:
|
||||||
|
sub_schematic = schematics[str(tschematic_id)]
|
||||||
|
root = sub_schematic.get("root")
|
||||||
|
if root:
|
||||||
|
return compute_node_availability(root, sub_schematic, schematics, overrides, set())
|
||||||
|
return node.get("availability", 1.0)
|
||||||
|
|
||||||
|
return node.get("availability", 1.0)
|
||||||
|
|
||||||
|
|
||||||
|
def compute_schematic_availability(schematic, schematics, overrides):
|
||||||
|
root = schematic.get("root")
|
||||||
|
if not root:
|
||||||
|
return 1.0
|
||||||
|
return compute_node_availability(root, schematic, schematics, overrides, set())
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate_project(json_file, overrides=None):
|
||||||
|
with open(json_file, "r") as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
schematics = data["schematics"]
|
||||||
|
overrides = overrides or {}
|
||||||
|
|
||||||
|
results = {}
|
||||||
|
top_availability = None
|
||||||
|
|
||||||
|
for sid, schematic in schematics.items():
|
||||||
|
name = schematic["schematic_name"].strip()
|
||||||
|
avail = compute_schematic_availability(schematic, schematics, overrides)
|
||||||
|
results[name] = avail
|
||||||
|
if name == "- TJB - Unit 3 -":
|
||||||
|
top_availability = avail
|
||||||
|
|
||||||
|
return results, top_availability
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
overrides = {
|
||||||
|
"WTP": 0.0, # Example override
|
||||||
|
}
|
||||||
|
|
||||||
|
results, top_avail = evaluate_project("project_70_rbd.json", overrides=overrides)
|
||||||
|
|
||||||
|
print("\n--- Schematic Availabilities ---")
|
||||||
|
for sch_name, avail in results.items():
|
||||||
|
print(f"{sch_name:25s}: {avail:.6f}")
|
||||||
|
|
||||||
|
print("\n=== TOTAL SYSTEM AVAILABILITY ===")
|
||||||
|
if top_avail is not None:
|
||||||
|
print(f"Top schematic (- TJB - Unit 3 -): {top_avail:.6f}")
|
||||||
|
else:
|
||||||
|
print("Top schematic not found in JSON!")
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue