metric.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package query
  2. import (
  3. "hash/fnv"
  4. "strings"
  5. "github.com/adrg/strutil"
  6. )
  7. const minVotes = 30
  8. // TODO: Add support for Popularity and LastModified
  9. func (a *abstractResults) aurSortByMetric(pkg *abstractResult) float64 {
  10. return 1 - (minVotes / (minVotes + float64(pkg.votes)))
  11. }
  12. func (a *abstractResults) GetMetric(pkg *abstractResult) float64 {
  13. if v, ok := a.distanceCache[pkg.name]; ok {
  14. return v
  15. }
  16. if strings.EqualFold(pkg.name, a.search) {
  17. return 1.0
  18. }
  19. sim := strutil.Similarity(pkg.name, a.search, a.metric)
  20. for _, prov := range pkg.provides {
  21. // If the package provides search, it's a perfect match
  22. // AUR packages don't populate provides
  23. candidate := strutil.Similarity(prov, a.search, a.metric) * 0.80
  24. if candidate > sim {
  25. sim = candidate
  26. }
  27. }
  28. simDesc := strutil.Similarity(pkg.description, a.search, a.metric)
  29. // slightly overweight sync sources by always giving them max popularity
  30. popularity := 1.0
  31. if pkg.source == sourceAUR {
  32. popularity = a.aurSortByMetric(pkg)
  33. }
  34. sim = sim*0.5 + simDesc*0.2 + popularity*0.3
  35. a.distanceCache[pkg.name] = sim
  36. return sim
  37. }
  38. func (a *abstractResults) separateSourceScore(source string, score float64) float64 {
  39. if !a.separateSources {
  40. return 0
  41. }
  42. if score == 1.0 {
  43. return 50
  44. }
  45. switch source {
  46. case sourceAUR:
  47. return 0
  48. case "core":
  49. return 40
  50. case "extra":
  51. return 30
  52. case "community":
  53. return 20
  54. case "multilib":
  55. return 10
  56. }
  57. if v, ok := a.separateSourceCache[source]; ok {
  58. return v
  59. }
  60. h := fnv.New32a()
  61. h.Write([]byte(source))
  62. sourceScore := float64(int(h.Sum32())%9 + 2)
  63. a.separateSourceCache[source] = sourceScore
  64. return sourceScore
  65. }
  66. func (a *abstractResults) calculateMetric(pkg *abstractResult) float64 {
  67. score := a.GetMetric(pkg)
  68. return a.separateSourceScore(pkg.source, score) + score
  69. }