9494 list_tunnels ,
9595 delete_tunnel ,
9696 follow_tunnels ,
97+ _load_tunnels as _load_graph_tunnels ,
9798)
9899from .hallways import ( # noqa: E402
99100 list_hallways ,
@@ -2048,7 +2049,7 @@ def _sqlite_graph_stats():
20482049 (non-chroma backend, missing/unbootstrapped palace, sqlite error). The
20492050 reconstruction mirrors ``palace_graph.build_graph`` /
20502051 ``palace_graph.graph_stats`` exactly: a node is a room with a non-empty
2051- wing and a usable room name (the catch-all ``"general"`` is excluded ), and
2052+ wing and a usable room name (including the catch-all ``"general"``), and
20522053 edges are the per-hall cross-wing crossings of multi-wing rooms.
20532054 """
20542055 rows = None
@@ -2074,46 +2075,56 @@ def _sqlite_graph_stats():
20742075
20752076
20762077def _graph_stats_from_grouped_rows (rows ):
2077- """Rebuild ``graph_stats`` from ``(room, wing, hall, n)`` grouped rows.
2078+ """Rebuild ``graph_stats`` from grouped sqlite metadata rows.
20782079
2079- Backends may append a fifth ``last_date`` column for ``find_tunnels``;
2080- stats do not use it, so extra columns are ignored rather than unpacked.
2080+ Rows are ``(room, wing, hall, n)`` with an optional fifth ``last_date``
2081+ column. Because grouping includes ``hall``, one room placement can occupy
2082+ multiple SQL rows; room instances therefore use a distinct ``(wing, room)`` set.
20812083 """
20822084 from collections import Counter , defaultdict
20832085
20842086 room_data = defaultdict (lambda : {"wings" : set (), "halls" : set (), "count" : 0 })
2087+ room_instances = set ()
20852088 for row in rows :
20862089 room , wing , hall , n = row [0 ], row [1 ], row [2 ], row [3 ]
2087- if not room or room == "general" or not wing :
2090+ if not room or not wing :
20882091 continue
2089- node = room_data [room ]
2090- node ["wings" ].add (str (wing ))
2092+ room_key = str (room )
2093+ wing_key = str (wing )
2094+ room_instances .add ((wing_key , room_key ))
2095+ node = room_data [room_key ]
2096+ node ["wings" ].add (wing_key )
20912097 if hall :
20922098 node ["halls" ].add (str (hall ))
20932099 node ["count" ] += int (n )
20942100
2095- tunnel_rooms = 0
2101+ passive_tunnel_rooms = 0
20962102 total_edges = 0
20972103 wing_counts = Counter ()
20982104 for data in room_data .values ():
20992105 n_wings = len (data ["wings" ])
21002106 for wing in data ["wings" ]:
21012107 wing_counts [wing ] += 1
21022108 if n_wings >= 2 :
2103- tunnel_rooms += 1
2109+ passive_tunnel_rooms += 1
21042110 total_edges += (n_wings * (n_wings - 1 ) // 2 ) * len (data ["halls" ])
21052111
21062112 top_tunnels = [
21072113 {"room" : room , "wings" : sorted (data ["wings" ]), "count" : data ["count" ]}
2108- for room , data in sorted (room_data . items (), key = lambda kv : ( - len ( kv [ 1 ][ "wings" ]), kv [ 0 ]))[
2109- : 10
2110- ]
2114+ for room , data in sorted (
2115+ room_data . items (), key = lambda item : ( - len ( item [ 1 ][ "wings" ]), item [ 0 ])
2116+ )[: 10 ]
21112117 if len (data ["wings" ]) >= 2
21122118 ]
2119+ explicit_tunnel_count = len (_load_graph_tunnels (_config ))
21132120 return {
21142121 "total_rooms" : len (room_data ),
2115- "tunnel_rooms" : tunnel_rooms ,
2122+ "total_room_instances" : len (room_instances ),
2123+ "tunnel_rooms" : passive_tunnel_rooms ,
2124+ "passive_tunnel_rooms" : passive_tunnel_rooms ,
2125+ "explicit_tunnels" : explicit_tunnel_count ,
21162126 "total_edges" : total_edges ,
2127+ "total_connections" : total_edges + explicit_tunnel_count ,
21172128 "rooms_per_wing" : dict (wing_counts .most_common ()),
21182129 "top_tunnels" : top_tunnels ,
21192130 }
0 commit comments