1 # frozen_string_literal: true
 
   5     @dict = build_dict(JSON.parse(path.read)).freeze
 
   8   def self.link(key, value)
 
   9     # skip if it's a full URL
 
  10     return nil if %r{\Ahttps?://}.match?(value)
 
  12     url_template = @dict[key]
 
  13     return nil unless url_template
 
  15     url_template.gsub("$1", value)
 
  18   def self.build_dict(data)
 
  20       # exclude deprecated and third-party URLs
 
  21       .reject { |item| item["rank"] == "deprecated" || item["source"] == "wikidata:P3303" }
 
  22       .group_by { |item| item["key"].sub(/^Key:/, "") }
 
  23       .transform_values { |items| choose_best_item(items) }
 
  25       .transform_values { |items| items["url"] }
 
  28   def self.choose_best_item(items)
 
  29     return nil if items.blank?
 
  31     return items.first if items.size == 1
 
  33     # move preferred to the start of the array
 
  34     ranked = items.sort_by { |item| item["rank"] == "preferred" ? 0 : 1 }.uniq { |item| item["url"] }
 
  35     top_rank = ranked.first["rank"]
 
  36     top_items = ranked.select { |i| i["rank"] == top_rank }
 
  38     # if only one top-ranked item, prefer that
 
  39     return top_items.first if top_items.size == 1
 
  41     grouped = top_items.group_by { |i| i["source"] }
 
  42     return nil if grouped.size > 2
 
  44     # if both sources have exactly one preferred, prefer osmwiki
 
  45     return grouped["osmwiki:P8"]&.first || grouped.values.flatten.first if grouped.all? { |_s, vals| vals.size == 1 }
 
  47     # if one source has multiple preferreds and the other has one, prefer the single one
 
  48     return grouped.min_by { |_s, vals| vals.size }.last.first if grouped.any? { |_s, vals| vals.size == 1 }
 
  50     # exclude any that are ambiguous
 
  53   private_class_method :choose_best_item