mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-07-05 17:32:10 +02:00
Do some same name ambiguous + known sibling collapse
This commit is contained in:
@@ -110,10 +110,12 @@ describe('packetNetworkGraph', () => {
|
||||
const hiddenProjection = projectPacketNetwork(state, {
|
||||
showAmbiguousNodes: false,
|
||||
showAmbiguousPaths: false,
|
||||
collapseLikelyKnownSiblingRepeaters: true,
|
||||
});
|
||||
const shownProjection = projectPacketNetwork(state, {
|
||||
showAmbiguousNodes: false,
|
||||
showAmbiguousPaths: true,
|
||||
collapseLikelyKnownSiblingRepeaters: true,
|
||||
});
|
||||
|
||||
expect(snapshotNeighborIds(state)).toEqual(
|
||||
@@ -163,10 +165,12 @@ describe('packetNetworkGraph', () => {
|
||||
const projectedPath = projectCanonicalPath(state, ingested!.canonicalPath, {
|
||||
showAmbiguousNodes: false,
|
||||
showAmbiguousPaths: false,
|
||||
collapseLikelyKnownSiblingRepeaters: true,
|
||||
});
|
||||
const projection = projectPacketNetwork(state, {
|
||||
showAmbiguousNodes: false,
|
||||
showAmbiguousPaths: false,
|
||||
collapseLikelyKnownSiblingRepeaters: true,
|
||||
});
|
||||
|
||||
expect(projectedPath.nodes).toEqual(['aaaaaaaaaaaa', '565656565656', 'self']);
|
||||
@@ -206,4 +210,89 @@ describe('packetNetworkGraph', () => {
|
||||
]);
|
||||
expect(snapshotNeighborIds(state).get('?73')).toEqual(['?86', '?d2']);
|
||||
});
|
||||
|
||||
it('collapses a likely ambiguous repeater into its known sibling when both share the same next hop', () => {
|
||||
const selfKey = 'ffffffffffff0000000000000000000000000000000000000000000000000000';
|
||||
const state = createPacketNetworkState('Me');
|
||||
const context = buildPacketNetworkContext({
|
||||
contacts: [
|
||||
createContact('aaaaaaaaaaaa0000000000000000000000000000000000000000000000000000', 'Alice'),
|
||||
createContact('cccccccccccc0000000000000000000000000000000000000000000000000000', 'Carol'),
|
||||
createContact(
|
||||
'3232323232320000000000000000000000000000000000000000000000000000',
|
||||
'Relay A',
|
||||
CONTACT_TYPE_REPEATER
|
||||
),
|
||||
createContact(
|
||||
'32ababababab0000000000000000000000000000000000000000000000000000',
|
||||
'Relay B',
|
||||
CONTACT_TYPE_REPEATER
|
||||
),
|
||||
createContact(
|
||||
'5656565656560000000000000000000000000000000000000000000000000000',
|
||||
'Relay Next',
|
||||
CONTACT_TYPE_REPEATER
|
||||
),
|
||||
],
|
||||
config: createConfig(selfKey),
|
||||
repeaterAdvertPaths: [
|
||||
{
|
||||
public_key: '3232323232320000000000000000000000000000000000000000000000000000',
|
||||
paths: [
|
||||
{
|
||||
path: '',
|
||||
path_len: 1,
|
||||
next_hop: '565656565656',
|
||||
first_seen: 1,
|
||||
last_seen: 2,
|
||||
heard_count: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
splitAmbiguousByTraffic: false,
|
||||
useAdvertPathHints: true,
|
||||
});
|
||||
|
||||
packetFixtures.set('graph-ambiguous-sibling', {
|
||||
payloadType: PayloadType.TextMessage,
|
||||
messageHash: 'graph-ambiguous-sibling',
|
||||
pathBytes: ['32', '565656565656'],
|
||||
srcHash: 'aaaaaaaaaaaa',
|
||||
dstHash: 'ffffffffffff',
|
||||
advertPubkey: null,
|
||||
groupTextSender: null,
|
||||
anonRequestPubkey: null,
|
||||
});
|
||||
packetFixtures.set('graph-known-sibling', {
|
||||
payloadType: PayloadType.TextMessage,
|
||||
messageHash: 'graph-known-sibling',
|
||||
pathBytes: ['323232323232', '565656565656'],
|
||||
srcHash: 'cccccccccccc',
|
||||
dstHash: 'ffffffffffff',
|
||||
advertPubkey: null,
|
||||
groupTextSender: null,
|
||||
anonRequestPubkey: null,
|
||||
});
|
||||
|
||||
ingestPacketIntoPacketNetwork(state, context, createPacket('graph-ambiguous-sibling'));
|
||||
ingestPacketIntoPacketNetwork(state, context, createPacket('graph-known-sibling'));
|
||||
|
||||
const collapsed = projectPacketNetwork(state, {
|
||||
showAmbiguousNodes: false,
|
||||
showAmbiguousPaths: true,
|
||||
collapseLikelyKnownSiblingRepeaters: true,
|
||||
});
|
||||
const separated = projectPacketNetwork(state, {
|
||||
showAmbiguousNodes: false,
|
||||
showAmbiguousPaths: true,
|
||||
collapseLikelyKnownSiblingRepeaters: false,
|
||||
});
|
||||
|
||||
expect(collapsed.renderedNodeIds.has('?32')).toBe(false);
|
||||
expect(collapsed.renderedNodeIds.has('323232323232')).toBe(true);
|
||||
expect(collapsed.links.has('323232323232->aaaaaaaaaaaa')).toBe(true);
|
||||
expect(separated.renderedNodeIds.has('?32')).toBe(true);
|
||||
expect(separated.links.has('?32->aaaaaaaaaaaa')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { PayloadType } from '@michaelhart/meshcore-decoder';
|
||||
|
||||
import type { Contact, RadioConfig, RawPacket } from '../types';
|
||||
import type { Contact, ContactAdvertPathSummary, RadioConfig, RawPacket } from '../types';
|
||||
import { CONTACT_TYPE_REPEATER } from '../types';
|
||||
import { buildLinkKey } from '../utils/visualizerUtils';
|
||||
|
||||
@@ -61,10 +61,13 @@ function createContact(publicKey: string, name: string, type = 1): Contact {
|
||||
};
|
||||
}
|
||||
|
||||
function createPacket(data: string): RawPacket {
|
||||
function createPacket(
|
||||
data: string,
|
||||
{ id = 1, observationId = id }: { id?: number; observationId?: number } = {}
|
||||
): RawPacket {
|
||||
return {
|
||||
id: 1,
|
||||
observation_id: 1,
|
||||
id,
|
||||
observation_id: observationId,
|
||||
timestamp: 1_700_000_000,
|
||||
data,
|
||||
payload_type: 'TEXT',
|
||||
@@ -81,22 +84,29 @@ function renderVisualizerData({
|
||||
config,
|
||||
showAmbiguousPaths = false,
|
||||
showAmbiguousNodes = false,
|
||||
collapseLikelyKnownSiblingRepeaters = true,
|
||||
repeaterAdvertPaths = [],
|
||||
useAdvertPathHints = false,
|
||||
}: {
|
||||
packets: RawPacket[];
|
||||
contacts: Contact[];
|
||||
config: RadioConfig;
|
||||
showAmbiguousPaths?: boolean;
|
||||
showAmbiguousNodes?: boolean;
|
||||
collapseLikelyKnownSiblingRepeaters?: boolean;
|
||||
repeaterAdvertPaths?: ContactAdvertPathSummary[];
|
||||
useAdvertPathHints?: boolean;
|
||||
}) {
|
||||
return renderHook(() =>
|
||||
useVisualizerData3D({
|
||||
packets,
|
||||
contacts,
|
||||
config,
|
||||
repeaterAdvertPaths: [],
|
||||
repeaterAdvertPaths,
|
||||
showAmbiguousPaths,
|
||||
showAmbiguousNodes,
|
||||
useAdvertPathHints: false,
|
||||
useAdvertPathHints,
|
||||
collapseLikelyKnownSiblingRepeaters,
|
||||
splitAmbiguousByTraffic: false,
|
||||
chargeStrength: -200,
|
||||
letEmDrift: false,
|
||||
@@ -223,6 +233,92 @@ describe('useVisualizerData3D', () => {
|
||||
expect(result.current.links.has(buildLinkKey('self', 'bbbbbbbbbbbb'))).toBe(false);
|
||||
});
|
||||
|
||||
it('collapses a high-confidence ambiguous repeater into its known sibling when both share the same next hop', async () => {
|
||||
const selfKey = 'ffffffffffff0000000000000000000000000000000000000000000000000000';
|
||||
const aliceKey = 'aaaaaaaaaaaa0000000000000000000000000000000000000000000000000000';
|
||||
const carolKey = 'cccccccccccc0000000000000000000000000000000000000000000000000000';
|
||||
const knownRelayKey = '3232323232320000000000000000000000000000000000000000000000000000';
|
||||
const otherRelayKey = '32ababababab0000000000000000000000000000000000000000000000000000';
|
||||
const nextRelayKey = '5656565656560000000000000000000000000000000000000000000000000000';
|
||||
|
||||
packetFixtures.set('dm-ambiguous-sibling', {
|
||||
payloadType: PayloadType.TextMessage,
|
||||
messageHash: 'dm-ambiguous-sibling',
|
||||
pathBytes: ['32', '565656565656'],
|
||||
srcHash: 'aaaaaaaaaaaa',
|
||||
dstHash: 'ffffffffffff',
|
||||
advertPubkey: null,
|
||||
groupTextSender: null,
|
||||
anonRequestPubkey: null,
|
||||
});
|
||||
packetFixtures.set('dm-known-sibling', {
|
||||
payloadType: PayloadType.TextMessage,
|
||||
messageHash: 'dm-known-sibling',
|
||||
pathBytes: ['323232323232', '565656565656'],
|
||||
srcHash: 'cccccccccccc',
|
||||
dstHash: 'ffffffffffff',
|
||||
advertPubkey: null,
|
||||
groupTextSender: null,
|
||||
anonRequestPubkey: null,
|
||||
});
|
||||
|
||||
const sharedArgs = {
|
||||
packets: [
|
||||
createPacket('dm-ambiguous-sibling', { id: 1, observationId: 1 }),
|
||||
createPacket('dm-known-sibling', { id: 2, observationId: 2 }),
|
||||
],
|
||||
contacts: [
|
||||
createContact(aliceKey, 'Alice'),
|
||||
createContact(carolKey, 'Carol'),
|
||||
createContact(knownRelayKey, 'Relay A', CONTACT_TYPE_REPEATER),
|
||||
createContact(otherRelayKey, 'Relay B', CONTACT_TYPE_REPEATER),
|
||||
createContact(nextRelayKey, 'Relay Next', CONTACT_TYPE_REPEATER),
|
||||
],
|
||||
config: createConfig(selfKey),
|
||||
showAmbiguousPaths: true,
|
||||
useAdvertPathHints: true,
|
||||
repeaterAdvertPaths: [
|
||||
{
|
||||
public_key: knownRelayKey,
|
||||
paths: [
|
||||
{
|
||||
path: '',
|
||||
path_len: 1,
|
||||
next_hop: '565656565656',
|
||||
first_seen: 1,
|
||||
last_seen: 2,
|
||||
heard_count: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const collapsed = renderVisualizerData({
|
||||
...sharedArgs,
|
||||
collapseLikelyKnownSiblingRepeaters: true,
|
||||
});
|
||||
const separated = renderVisualizerData({
|
||||
...sharedArgs,
|
||||
collapseLikelyKnownSiblingRepeaters: false,
|
||||
});
|
||||
|
||||
await waitFor(() =>
|
||||
expect(collapsed.result.current.renderedNodeIds.has('323232323232')).toBe(true)
|
||||
);
|
||||
await waitFor(() => expect(separated.result.current.renderedNodeIds.has('?32')).toBe(true));
|
||||
|
||||
expect(collapsed.result.current.renderedNodeIds.has('?32')).toBe(false);
|
||||
expect(collapsed.result.current.links.has(buildLinkKey('aaaaaaaaaaaa', '323232323232'))).toBe(
|
||||
true
|
||||
);
|
||||
expect(collapsed.result.current.links.has(buildLinkKey('323232323232', '565656565656'))).toBe(
|
||||
true
|
||||
);
|
||||
expect(separated.result.current.renderedNodeIds.has('?32')).toBe(true);
|
||||
expect(separated.result.current.links.has(buildLinkKey('aaaaaaaaaaaa', '?32'))).toBe(true);
|
||||
});
|
||||
|
||||
it('picks back up with known repeaters after hiding ambiguous repeater segments', async () => {
|
||||
const selfKey = 'ffffffffffff0000000000000000000000000000000000000000000000000000';
|
||||
const aliceKey = 'aaaaaaaaaaaa0000000000000000000000000000000000000000000000000000';
|
||||
|
||||
Reference in New Issue
Block a user