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