SPB Git forge

spb/cancerindex

Public
37commits 1branches 0releases
2.9 MBsize
maindefault branch
10 days agolast push
TypeScript 97.2% SQL 1.5% CSS 0.6% JavaScript 0.5%
1.4 KB · 35 lines typescript
Raw Blame History
1/** Pure part of entity search (§294, §312): tier → match label and the final ordering. */23export type SearchType = 'cancer' | 'gene' | 'variant' | 'drug' | 'trial' | 'publication' | 'source';4export type SearchMatch = 'exact' | 'alias' | 'prefix' | 'trigram' | 'identifier';56export interface RankedHit {7  type: SearchType;8  title: string;9  /** 0 exact · 1 alias/identifier · 2 prefix · 3 trigram */10  tier: number;11  /** pg_trgm similarity (0..1), higher is better */12  score: number;13}1415const IDENTIFIER_TYPES: ReadonlySet<SearchType> = new Set(['gene', 'trial', 'publication', 'variant']);1617/** Tier 1 means "matched an identifier" for code-like entities and "matched an alias" for the rest. */18export function matchFromTier(tier: number, type: SearchType): SearchMatch {19  if (tier <= 0) return 'exact';20  if (tier === 1) return IDENTIFIER_TYPES.has(type) ? 'identifier' : 'alias';21  if (tier === 2) return 'prefix';22  return 'trigram';23}2425/** Ordering: exact > alias/identifier > prefix > trigram, then similarity desc, then title A→Z. */26export function compareHits(a: RankedHit, b: RankedHit): number {27  if (a.tier !== b.tier) return a.tier - b.tier;28  if (a.score !== b.score) return b.score - a.score;29  return a.title.localeCompare(b.title, 'en', { sensitivity: 'base' });30}3132export function sortHits<T extends RankedHit>(hits: T[]): T[] {33  return [...hits].sort(compareHits);34}35