mirror of
https://github.com/atsunatsu/Look4Sat.git
synced 2026-10-02 03:15:37 +00:00
fix: AMSAT name matching token-based; SSTV filters to in-orbit only
- matchesAmSatName: exact token match instead of substring contains, so 'ISS' no longer matches AISSAT-1 and 'AO-7' no longer matches AO-73 (FUNCUBE-1); resolves missing ISS in FM and missing AO-7 in Linear lists - resolveTypeIds: intersect SSTV catnums with current in-orbit TLE set, excluding retired satellites (e.g. TIROS) whose radios are tagged SSTV - add regression tests for token matching
This commit is contained in:
1 parent
e7754a4c9e
commit
30000a913e
4 files changed
+27
-5
No files matched your search
@@ -140,7 +140,7 @@ class DatabaseRepo(
|
|||||||
fun resolve(names: List<String>): Set<Int> = names.mapNotNull { name ->
|
fun resolve(names: List<String>): Set<Int> = names.mapNotNull { name ->
|
||||||
val keys = dataParser.normalizeAmSatName(name)
|
val keys = dataParser.normalizeAmSatName(name)
|
||||||
nameToCatnum.entries.firstOrNull { (localName, _) ->
|
nameToCatnum.entries.firstOrNull { (localName, _) ->
|
||||||
keys.any { key -> localName.contains(key) }
|
dataParser.matchesAmSatName(localName, keys)
|
||||||
}?.value
|
}?.value
|
||||||
}.toSet()
|
}.toSet()
|
||||||
val fmCatnums = resolve(fmNames)
|
val fmCatnums = resolve(fmNames)
|
||||||
|
|||||||
+11
-1
@@ -74,7 +74,17 @@ class SelectionRepo(
|
|||||||
when (type) {
|
when (type) {
|
||||||
Sources.virtualTypeNames[0] -> idsSet.addAll(settingsRepo.getAmSatFmCatnums())
|
Sources.virtualTypeNames[0] -> idsSet.addAll(settingsRepo.getAmSatFmCatnums())
|
||||||
Sources.virtualTypeNames[1] -> idsSet.addAll(settingsRepo.getAmSatLinearCatnums())
|
Sources.virtualTypeNames[1] -> idsSet.addAll(settingsRepo.getAmSatLinearCatnums())
|
||||||
Sources.virtualTypeNames[2] -> idsSet.addAll(localSource.getIdsWithModes(listOf("SSTV")))
|
// Live SSTV: mode=SSTV transponder records intersected with the
|
||||||
|
// currently-tracked (in-orbit, from the selected TLE sources)
|
||||||
|
// satellites. The raw mode query alone would include retired
|
||||||
|
// weather/experimental birds (e.g. TIROS catnum 1430 whose old
|
||||||
|
// TV downlink is labelled SSTV but is long gone from orbit).
|
||||||
|
Sources.virtualTypeNames[2] -> {
|
||||||
|
val inOrbitIds = currentItems.value.map { it.catnum }.toHashSet()
|
||||||
|
idsSet.addAll(
|
||||||
|
localSource.getIdsWithModes(listOf("SSTV")).filter { it in inOrbitIds }
|
||||||
|
)
|
||||||
|
}
|
||||||
else -> idsSet.addAll(settingsRepo.getSatelliteTypesIds(listOf(type)))
|
else -> idsSet.addAll(settingsRepo.getSatelliteTypesIds(listOf(type)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,10 +128,18 @@ class DataParser(private val dispatcher: CoroutineDispatcher) {
|
|||||||
return keys.distinct()
|
return keys.distinct()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True if a local entry name matches any of the AMSAT normalized keys. */
|
/** True if a local entry name matches any of the AMSAT normalized keys.
|
||||||
|
* Token-based exact match (split on spaces/brackets/slashes), so a key
|
||||||
|
* like "ISS" does not substring-match "AISSAT-1" — the key must equal a
|
||||||
|
* whole name token (case-insensitive). */
|
||||||
fun matchesAmSatName(localName: String, amSatKeys: List<String>): Boolean {
|
fun matchesAmSatName(localName: String, amSatKeys: List<String>): Boolean {
|
||||||
val localUpper = localName.uppercase()
|
val localTokens = localName.uppercase()
|
||||||
return amSatKeys.any { key -> localUpper.contains(key) }
|
.split(Regex("[\\s()\\[\\]/]+"))
|
||||||
|
.filter { it.isNotBlank() }
|
||||||
|
.toSet()
|
||||||
|
return amSatKeys.any { key ->
|
||||||
|
key.uppercase() in localTokens
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseCSV(values: List<String>): OrbitalData? = runCatching {
|
private fun parseCSV(values: List<String>): OrbitalData? = runCatching {
|
||||||
|
|||||||
@@ -279,6 +279,10 @@ class DataParserTest {
|
|||||||
assert(dataParser.normalizeAmSatName("ISS") == listOf("ISS"))
|
assert(dataParser.normalizeAmSatName("ISS") == listOf("ISS"))
|
||||||
assert(dataParser.matchesAmSatName("AO-91 (RADFXSAT)", listOf("AO-91", "RADFXSAT")))
|
assert(dataParser.matchesAmSatName("AO-91 (RADFXSAT)", listOf("AO-91", "RADFXSAT")))
|
||||||
assert(!dataParser.matchesAmSatName("SO-50", listOf("AO-91")))
|
assert(!dataParser.matchesAmSatName("SO-50", listOf("AO-91")))
|
||||||
|
// Regression: "ISS" must not substring-match "AISSAT-1" (token match only).
|
||||||
|
assert(dataParser.matchesAmSatName("ISS (ZARYA)", listOf("ISS")))
|
||||||
|
assert(!dataParser.matchesAmSatName("AISSAT-1", listOf("ISS")))
|
||||||
|
assert(!dataParser.matchesAmSatName("TESS", listOf("ISS")))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in new issue
Block a user