@@ -22,6 +22,9 @@ import 'token_index.dart';
2222final _logger = Logger ('search.mem_index' );
2323final _textSearchTimeout = Duration (milliseconds: 500 );
2424
25+ // Quantized equivalent of the `0.01` score.
26+ const _apiScoreCutoff = scoreQuantization ~ / 100 ;
27+
2528class InMemoryPackageIndex {
2629 final List <PackageDocument > _documents;
2730 final _nameToIndex = < String , int > {};
@@ -37,8 +40,8 @@ class InMemoryPackageIndex {
3740 final _tagBitArrays = < String , BitArray > {};
3841
3942 /// Adjusted score takes the overall score and transforms
40- /// it linearly into the [0.4-1.0] range.
41- late final List <double > _adjustedOverallScores;
43+ /// it linearly into the [0.4-1.0] range, stored with [scoreQuantization] .
44+ late final List <int > _adjustedOverallScores;
4245 late final List <IndexedPackageHit > _overallOrderedHits;
4346 late final List <IndexedPackageHit > _createdOrderedHits;
4447 late final List <IndexedPackageHit > _updatedOrderedHits;
@@ -294,7 +297,7 @@ class InMemoryPackageIndex {
294297 }
295298 // Check whether the best name match will increase the total item count.
296299 if (bestNameIndex != null &&
297- packageScores.getValue (bestNameIndex) <= 0.0 ) {
300+ packageScores.isNotPositive (bestNameIndex)) {
298301 totalCount++ ;
299302 }
300303 indexedHits = _rankWithValues (
@@ -333,7 +336,7 @@ class InMemoryPackageIndex {
333336 packageHits = indexedHits.map ((ps) {
334337 final apiPages = textResults! .topApiPages? [ps.index]
335338 // TODO(https://github.com/dart-lang/pub-dev/issues/7106): extract title for the page
336- ? .map ((MapEntry <String , double > e) => ApiPageRef (path: e.key))
339+ ? .map ((MapEntry <String , int > e) => ApiPageRef (path: e.key))
337340 .toList ();
338341 return ps.hit.change (apiPages: apiPages);
339342 }).toList ();
@@ -418,8 +421,8 @@ class InMemoryPackageIndex {
418421
419422 final overall = popularityScore * 0.5 + pointScore * 0.5 ;
420423 doc.overallScore = overall;
421- // adding a base score prevents later multiplication with zero
422- return 0.4 + 0.6 * overall;
424+ // adding a base score prevents later multiplication with zero (quantized)
425+ return (( 0.4 + 0.6 * overall) * scoreQuantization). round () ;
423426 }).toList ();
424427 }
425428
@@ -445,7 +448,7 @@ class InMemoryPackageIndex {
445448
446449 for (final index in packages.asIntIterable ()) {
447450 if (index >= _documents.length) break ;
448- packageScores.setValue (index, 1.0 );
451+ packageScores.setValue (index, scoreQuantization );
449452 }
450453
451454 bool aborted = false ;
@@ -479,7 +482,7 @@ class InMemoryPackageIndex {
479482 );
480483 }
481484
482- final topApiPages = List <List <MapEntry <String , double >>?>.filled (
485+ final topApiPages = List <List <MapEntry <String , int >>?>.filled (
483486 _documents.length,
484487 null ,
485488 );
@@ -492,14 +495,13 @@ class InMemoryPackageIndex {
492495 ) async {
493496 for (var i = 0 ; i < symbolPages.length; i++ ) {
494497 final value = symbolPages.getValue (i);
495- if (value < 0.01 ) continue ;
498+ if (value < _apiScoreCutoff ) continue ;
496499
497500 final doc = _apiDocPageKeys[i];
498501 if (! packages[doc.index]) continue ;
499502
500503 // skip if the previously found pages are better than the current one
501- final pages = topApiPages[doc.index] ?? =
502- < MapEntry <String , double >> [];
504+ final pages = topApiPages[doc.index] ?? = < MapEntry <String , int >> [];
503505 if (pages.length >= maxApiPageCount && pages.last.value > value) {
504506 continue ;
505507 }
@@ -564,7 +566,7 @@ class InMemoryPackageIndex {
564566 });
565567 for (var i = 0 ; i < score.length; i++ ) {
566568 final value = score.getValue (i);
567- if (value <= 0.0 && i != bestNameIndex) continue ;
569+ if (value <= 0 && i != bestNameIndex) continue ;
568570 heap.collect (i);
569571 }
570572 return heap
@@ -574,7 +576,7 @@ class InMemoryPackageIndex {
574576 i,
575577 PackageHit (
576578 package: _documents[i].package,
577- score: score.getValue (i),
579+ score: score.getValue (i) / scoreQuantization ,
578580 ),
579581 ),
580582 );
@@ -640,7 +642,7 @@ class InMemoryPackageIndex {
640642
641643class _TextResults {
642644 final bool hasNoMatch;
643- final List <List <MapEntry <String , double >>?>? topApiPages;
645+ final List <List <MapEntry <String , int >>?>? topApiPages;
644646 final String ? errorMessage;
645647
646648 factory _TextResults .empty ({String ? errorMessage}) {
@@ -710,12 +712,13 @@ class PackageNameIndex {
710712 }
711713
712714 /// Score assigned when the query n-gram(s) occur in the original (underscored)
713- /// package name.
714- static const _originalNameScore = 1.0 ;
715+ /// package name (1.0 quantized) .
716+ static const _originalNameScore = scoreQuantization ;
715717
716718 /// Score assigned when the query n-gram(s) occur only in the collapsed name,
717- /// i.e. the match spans a removed underscore.
718- static const _collapsedNameScore = _collapsedNameWeight / _originalNameWeight;
719+ /// i.e. the match spans a removed underscore (0.99 quantized).
720+ static final _collapsedNameScore =
721+ (_collapsedNameWeight * scoreQuantization / _originalNameWeight).round ();
719722
720723 /// Posting weight bytes: the match score scaled by 100. Storing them as small
721724 /// integers lets the trigram counter sum the weights and recognize a perfect
@@ -742,7 +745,9 @@ class PackageNameIndex {
742745 final result = < String , double > {};
743746 for (var i = 0 ; i < _packageNames.length; i++ ) {
744747 final v = score.getValue (i);
745- if (v > 0.0 ) result[_packageNames[i]] = v;
748+ if (v > 0 ) {
749+ result[_packageNames[i]] = v / scoreQuantization;
750+ }
746751 }
747752 return result;
748753 }
@@ -786,7 +791,9 @@ class PackageNameIndex {
786791 for (final part in parts) {
787792 final postings = _ngramPostings[part];
788793 if (postings == null ) continue ;
789- postings.forEach ((i, weight) => counts.add (i, weight));
794+ postings.forEach ((i, weight) {
795+ counts.add (i, weight);
796+ });
790797 }
791798
792799 final n = parts.length;
@@ -804,7 +811,7 @@ class PackageNameIndex {
804811 score.setValue (i, _originalNameScore);
805812 } else {
806813 // Partial match: fractional relevance score in [0.5, 1.0).
807- score.setValue (i, sum / fullMatchSum);
814+ score.setValue (i, sum * scoreQuantization ~ / fullMatchSum);
808815 }
809816 }
810817 },
0 commit comments