diff --git a/src/app/features/search/search-ranking.spec.ts b/src/app/features/search/search-ranking.spec.ts index 85d3423..93d2774 100644 --- a/src/app/features/search/search-ranking.spec.ts +++ b/src/app/features/search/search-ranking.spec.ts @@ -81,6 +81,11 @@ describe('rankSearchResults', () => { expect(rank(entries, 'Proxima')[0]).toBe('Proxima Centauri'); }); + it("lists a host's own planets ahead of the systems whose names run on from its own", () => { + const entries = [star('K2-18'), star('K2-180'), star('K2-181'), exoplanet('K2-18 b'), exoplanet('K2-18 c')]; + expect(rank(entries, 'K2-18')).toEqual(['K2-18', 'K2-18 b', 'K2-18 c', 'K2-180', 'K2-181']); + }); + it('breaks remaining ties by name length, then alphabetically', () => { const entries = [exoplanet('Kepler-1292 b'), exoplanet('Kepler-9 c'), exoplanet('Kepler-9 b'), exoplanet('Kepler-15 b')]; expect(rank(entries, 'Kepler')).toEqual(['Kepler-9 b', 'Kepler-9 c', 'Kepler-15 b', 'Kepler-1292 b']); diff --git a/src/app/features/search/search-ranking.ts b/src/app/features/search/search-ranking.ts index d5f207c..6a86db0 100644 --- a/src/app/features/search/search-ranking.ts +++ b/src/app/features/search/search-ranking.ts @@ -28,6 +28,13 @@ export function entrySubtitle(entry: SearchEntry): string { * prefix match, and so on, so a better kind of match can never be crowded out by a worse one. */ const MATCH_EXACT = 4; +/** + * A prefix that ends where a word does, "kepler-186 f" for "kepler-186", ahead of one running on into + * the same word, "kepler-1860". Level with it, the star outranked the planet on kind, and once the + * archive's hosts became stars, searching a host's name listed K2-180 to K2-186 and none of K2-18's + * planets: 325 hosts lost some of their own planets from the eight rows shown, and now 50 do. + */ +const MATCH_WORD_PREFIX = 3.5; const MATCH_PREFIX = 3; const MATCH_WORD_START = 2; const MATCH_SUBSTRING = 1; @@ -89,7 +96,7 @@ function scoreIndexed(indexed: IndexedSearchEntry, normalizedQuery: string, comp return MATCH_EXACT; } if (indexed.normalizedName.startsWith(normalizedQuery)) { - return MATCH_PREFIX; + return WORD_SEPARATORS.test(indexed.normalizedName.charAt(normalizedQuery.length)) ? MATCH_WORD_PREFIX : MATCH_PREFIX; } if (indexed.words.some((word) => word.startsWith(normalizedQuery))) { return MATCH_WORD_START;