mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-08-28 22:18:25 +00:00
Show raw hop prefixes alongside friendly names in route patterns
Each hop now displays as 'NodeName [ab]' with the hex prefix visible. Makes prefix collisions obvious — e.g. same prefix resolving to same name confirms it's a collision, different prefixes confirm real route.
This commit is contained in:
+6
-1
@@ -784,10 +784,15 @@
|
||||
${data.subpaths.map((s, i) => {
|
||||
const barW = Math.max(2, Math.round(s.count / maxCount * 100));
|
||||
const hops = s.path.split(' → ');
|
||||
const rawHops = s.rawHops || [];
|
||||
const hasSelfLoop = hops.some((h, j) => j > 0 && h === hops[j - 1]);
|
||||
const routeDisplay = hops.map((h, j) => {
|
||||
const prefix = rawHops[j] || '';
|
||||
return `<span title="${esc(prefix)}">${esc(h)} <span class="hop-prefix">[${esc(prefix)}]</span></span>`;
|
||||
}).join(' → ');
|
||||
return `<tr${hasSelfLoop ? ' class="subpath-selfloop"' : ''}>
|
||||
<td>${i + 1}</td>
|
||||
<td class="mono" style="white-space:nowrap">${esc(s.path)}${hasSelfLoop ? ' <span title="Contains self-loop — likely 1-byte prefix collision" style="cursor:help">🔄</span>' : ''}</td>
|
||||
<td class="mono" style="white-space:nowrap">${routeDisplay}${hasSelfLoop ? ' <span title="Contains self-loop — likely 1-byte prefix collision" style="cursor:help">🔄</span>' : ''}</td>
|
||||
<td>${s.count.toLocaleString()}</td>
|
||||
<td>${s.pct}%</td>
|
||||
<td><div style="background:${hasSelfLoop ? '#f59e0b' : 'var(--accent,#3b82f6)'};height:14px;border-radius:3px;width:${barW}%;opacity:0.7"></div></td>
|
||||
|
||||
@@ -1150,3 +1150,6 @@ button.ch-item.ch-item-encrypted .ch-badge { filter: grayscale(0.6); }
|
||||
/* Self-loop subpath rows */
|
||||
.subpath-selfloop { opacity: 0.6; }
|
||||
.subpath-selfloop td:first-child::after { content: ''; }
|
||||
|
||||
/* Hop prefix in subpath routes */
|
||||
.hop-prefix { color: #9ca3af; font-size: 0.8em; }
|
||||
|
||||
@@ -1137,7 +1137,9 @@ app.get('/api/analytics/subpaths', (req, res) => {
|
||||
for (let len = minLen; len <= Math.min(maxLen, named.length); len++) {
|
||||
for (let start = 0; start <= named.length - len; start++) {
|
||||
const sub = named.slice(start, start + len).join(' → ');
|
||||
subpathCounts[sub] = (subpathCounts[sub] || 0) + 1;
|
||||
const raw = hops.slice(start, start + len).join(',');
|
||||
if (!subpathCounts[sub]) subpathCounts[sub] = { count: 0, raw };
|
||||
subpathCounts[sub].count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1145,11 +1147,12 @@ app.get('/api/analytics/subpaths', (req, res) => {
|
||||
// Sort by frequency, return top results
|
||||
const limit = Number(req.query.limit) || 100;
|
||||
const ranked = Object.entries(subpathCounts)
|
||||
.map(([path, count]) => ({
|
||||
.map(([path, data]) => ({
|
||||
path,
|
||||
count,
|
||||
rawHops: data.raw.split(','),
|
||||
count: data.count,
|
||||
hops: path.split(' → ').length,
|
||||
pct: totalPaths > 0 ? Math.round(count / totalPaths * 1000) / 10 : 0
|
||||
pct: totalPaths > 0 ? Math.round(data.count / totalPaths * 1000) / 10 : 0
|
||||
}))
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, limit);
|
||||
|
||||
Reference in New Issue
Block a user