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