mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
Warn channels for delayed log rx
This commit is contained in:
@@ -489,7 +489,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 113;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEVELOPMENT_TEAM = JND55328G8;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -511,7 +511,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 113;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEVELOPMENT_TEAM = JND55328G8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
@@ -530,7 +530,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 113;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEVELOPMENT_TEAM = JND55328G8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
@@ -547,7 +547,7 @@
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 113;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEVELOPMENT_TEAM = JND55328G8;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
@@ -679,7 +679,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 113;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEVELOPMENT_TEAM = JND55328G8;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
@@ -702,7 +702,7 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 113;
|
||||
CURRENT_PROJECT_VERSION = 115;
|
||||
DEVELOPMENT_TEAM = JND55328G8;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>113</string>
|
||||
<string>115</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
||||
@@ -5,22 +5,24 @@
|
||||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000231">
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.001473">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.67336">
|
||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.569758">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: build_app" time="113.383916">
|
||||
<testcase classname="fastlane.lanes" name="2: build_app" time="95.271262">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="221.37558">
|
||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="91.795184">
|
||||
|
||||
<failure message="/opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/actions/actions_helper.rb:67:in 'Fastlane::Actions.execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:255:in 'block in Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:229:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:229:in 'Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:157:in 'Fastlane::Runner#trigger_action_by_name' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/fast_file.rb:159:in 'Fastlane::FastFile#method_missing' Fastfile:23:in 'block (2 levels) in Fastlane::FastFile#parsing_binding' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/cli_tools_distributor.rb:132:in 'Fastlane::CLIToolsDistributor.take_off' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/bin/fastlane:23:in '<top (required)>' /opt/homebrew/Cellar/ruby/4.0.1/lib/ruby/4.0.0/rubygems.rb:303:in 'Kernel#load' /opt/homebrew/Cellar/ruby/4.0.1/lib/ruby/4.0.0/rubygems.rb:303:in 'Gem.activate_and_load_bin_path' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/bin/fastlane:25:in '<main>' Invalid username and password combination. Used 'hey@dz0n.dev' as the username." />
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
@@ -108,6 +108,87 @@ class TraceNodeResolver {
|
||||
);
|
||||
}
|
||||
|
||||
static List<ResolvedTraceNode> alignPathSelections({
|
||||
required List<ResolvedTraceNode> nodes,
|
||||
MeshMapNode? startNode,
|
||||
MeshMapNode? endNode,
|
||||
}) {
|
||||
if (nodes.isEmpty || nodes.any((node) => node.candidates.isEmpty)) {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
final candidateCosts = List.generate(
|
||||
nodes.length,
|
||||
(_) => <double>[],
|
||||
growable: false,
|
||||
);
|
||||
final previousChoice = List.generate(
|
||||
nodes.length,
|
||||
(_) => <int>[],
|
||||
growable: false,
|
||||
);
|
||||
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
final currentCandidates = nodes[i].candidates;
|
||||
candidateCosts[i] = List<double>.filled(
|
||||
currentCandidates.length,
|
||||
double.infinity,
|
||||
);
|
||||
previousChoice[i] = List<int>.filled(currentCandidates.length, -1);
|
||||
|
||||
for (var j = 0; j < currentCandidates.length; j++) {
|
||||
final current = currentCandidates[j];
|
||||
if (i == 0) {
|
||||
candidateCosts[i][j] = startNode == null
|
||||
? 0
|
||||
: _distanceBetweenNodes(startNode, current);
|
||||
continue;
|
||||
}
|
||||
|
||||
final previousCandidates = nodes[i - 1].candidates;
|
||||
for (var k = 0; k < previousCandidates.length; k++) {
|
||||
final candidateCost =
|
||||
candidateCosts[i - 1][k] +
|
||||
_distanceBetweenNodes(previousCandidates[k], current);
|
||||
if (candidateCost < candidateCosts[i][j]) {
|
||||
candidateCosts[i][j] = candidateCost;
|
||||
previousChoice[i][j] = k;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var bestLastIndex = 0;
|
||||
var bestLastCost = double.infinity;
|
||||
final lastCandidates = nodes.last.candidates;
|
||||
for (var i = 0; i < lastCandidates.length; i++) {
|
||||
final endCost = endNode == null
|
||||
? 0
|
||||
: _distanceBetweenNodes(lastCandidates[i], endNode);
|
||||
final totalCost = candidateCosts.last[i] + endCost;
|
||||
if (totalCost < bestLastCost) {
|
||||
bestLastCost = totalCost;
|
||||
bestLastIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
final selectedIndices = List<int>.filled(nodes.length, 0);
|
||||
selectedIndices[nodes.length - 1] = bestLastIndex;
|
||||
for (var i = nodes.length - 1; i > 0; i--) {
|
||||
selectedIndices[i - 1] = previousChoice[i][selectedIndices[i]];
|
||||
}
|
||||
|
||||
return List<ResolvedTraceNode>.generate(nodes.length, (index) {
|
||||
final resolved = nodes[index];
|
||||
return ResolvedTraceNode(
|
||||
candidates: resolved.candidates,
|
||||
matchCount: resolved.matchCount,
|
||||
usedOnlineFallback: resolved.usedOnlineFallback,
|
||||
selectedIndex: selectedIndices[index],
|
||||
);
|
||||
}, growable: false);
|
||||
}
|
||||
|
||||
static double _scoreNode(
|
||||
MeshMapNode node, {
|
||||
LatLng? referenceA,
|
||||
@@ -126,6 +207,14 @@ class TraceNodeResolver {
|
||||
return double.maxFinite;
|
||||
}
|
||||
|
||||
static double _distanceBetweenNodes(MeshMapNode a, MeshMapNode b) {
|
||||
return _distance.as(
|
||||
LengthUnit.Meter,
|
||||
LatLng(a.latitude, a.longitude),
|
||||
LatLng(b.latitude, b.longitude),
|
||||
);
|
||||
}
|
||||
|
||||
static double _distanceToSegmentMeters(LatLng p, LatLng a, LatLng b) {
|
||||
final ax = a.longitude;
|
||||
final ay = a.latitude;
|
||||
|
||||
@@ -420,12 +420,17 @@ class _ContactTraceSheetState extends State<ContactTraceSheet> {
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
final alignedRelayNodes = TraceNodeResolver.alignPathSelections(
|
||||
nodes: matchedRelayNodes,
|
||||
startNode: senderNode.node,
|
||||
endNode: recipientNode.node,
|
||||
);
|
||||
|
||||
return _ContactTraceResult(
|
||||
sender: senderNode,
|
||||
recipient: recipientNode,
|
||||
routeHashes: routeHashes,
|
||||
matchedRelayNodes: matchedRelayNodes,
|
||||
matchedRelayNodes: alignedRelayNodes,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -531,12 +531,17 @@ class _MessageTraceSheetState extends State<MessageTraceSheet> {
|
||||
senderLatLng: senderLatLng,
|
||||
recipientLatLng: recipientLatLng,
|
||||
);
|
||||
final alignedMatched = TraceNodeResolver.alignPathSelections(
|
||||
nodes: matched,
|
||||
startNode: senderNode.node,
|
||||
endNode: recipientNode.node,
|
||||
);
|
||||
return _TraceResult(
|
||||
mode: TraceMode.packetPath,
|
||||
sender: senderNode,
|
||||
recipient: recipientNode,
|
||||
pathHashes: hopHashes,
|
||||
matchedPathNodes: matched,
|
||||
matchedPathNodes: alignedMatched,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 2026.0313.1+28
|
||||
version: 2026.0313.2+29
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
|
||||
@@ -88,6 +88,65 @@ void main() {
|
||||
expect(resolved.cycle().node?.name, 'First Match');
|
||||
expect(resolved.cycle().cycle().node?.name, 'Second Match');
|
||||
});
|
||||
|
||||
test('aligns ambiguous hops to the closest continuous path', () {
|
||||
final start = _node(
|
||||
name: 'Start',
|
||||
publicKey: 'start00',
|
||||
latitude: 46.000,
|
||||
longitude: 14.000,
|
||||
);
|
||||
final end = _node(
|
||||
name: 'End',
|
||||
publicKey: 'end000',
|
||||
latitude: 46.300,
|
||||
longitude: 14.300,
|
||||
);
|
||||
final hop1Near = _node(
|
||||
name: 'Hop 1 Near',
|
||||
publicKey: 'aa1100',
|
||||
latitude: 46.100,
|
||||
longitude: 14.100,
|
||||
);
|
||||
final hop1Far = _node(
|
||||
name: 'Hop 1 Far',
|
||||
publicKey: 'aa11ff',
|
||||
latitude: 46.250,
|
||||
longitude: 14.000,
|
||||
);
|
||||
final hop2Near = _node(
|
||||
name: 'Hop 2 Near',
|
||||
publicKey: 'bb2200',
|
||||
latitude: 46.200,
|
||||
longitude: 14.200,
|
||||
);
|
||||
final hop2Far = _node(
|
||||
name: 'Hop 2 Far',
|
||||
publicKey: 'bb22ff',
|
||||
latitude: 46.050,
|
||||
longitude: 14.280,
|
||||
);
|
||||
|
||||
final aligned = TraceNodeResolver.alignPathSelections(
|
||||
nodes: [
|
||||
TraceNodeResolver.resolveBest(
|
||||
nodes: [hop1Far, hop1Near],
|
||||
localPublicKeys: {hop1Near.publicKey, hop1Far.publicKey},
|
||||
prefixHex: 'aa11',
|
||||
),
|
||||
TraceNodeResolver.resolveBest(
|
||||
nodes: [hop2Far, hop2Near],
|
||||
localPublicKeys: {hop2Near.publicKey, hop2Far.publicKey},
|
||||
prefixHex: 'bb22',
|
||||
),
|
||||
],
|
||||
startNode: start,
|
||||
endNode: end,
|
||||
);
|
||||
|
||||
expect(aligned[0].node?.name, 'Hop 1 Near');
|
||||
expect(aligned[1].node?.name, 'Hop 2 Near');
|
||||
});
|
||||
}
|
||||
|
||||
MeshMapNode _node({
|
||||
|
||||
Reference in New Issue
Block a user