atlasq 0.1.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/cache/formatted_output/country_title.json +1 -0
- data/cache/formatted_output/multiline_country.json +1 -0
- data/cache/formatted_output/one_line_country.json +1 -0
- data/cache/formatted_output/one_line_currency.json +1 -0
- data/cache/list/all_countries.json +1 -0
- data/cache/list/all_subregions.json +1 -0
- data/cache/search_index/countries_by_currency.json +1 -0
- data/cache/search_index/countries_by_region.json +1 -0
- data/cache/search_index/direct_match_country.json +1 -0
- data/cache/search_index/direct_match_currency.json +1 -0
- data/cache/search_index/partial_match_country.json +1 -0
- data/cache/search_index/partial_match_currency.json +1 -0
- data/lib/atlasq/cache.rb +27 -0
- data/lib/atlasq/command/any.rb +7 -5
- data/lib/atlasq/command/base.rb +1 -1
- data/lib/atlasq/command/country.rb +6 -6
- data/lib/atlasq/command/help.rb +2 -0
- data/lib/atlasq/command/money.rb +6 -5
- data/lib/atlasq/command/region.rb +3 -4
- data/lib/atlasq/command.rb +1 -0
- data/lib/atlasq/data.rb +34 -91
- data/lib/atlasq/format.rb +53 -126
- data/lib/atlasq/partial_match.rb +19 -0
- data/lib/atlasq/util/string.rb +42 -6
- data/lib/atlasq/util/word_map.rb +34 -0
- data/lib/atlasq/util.rb +1 -0
- data/lib/atlasq/version.rb +1 -1
- data/lib/atlasq.rb +2 -0
- metadata +17 -60
- data/lib/atlasq/data/currency.rb +0 -20
- data/lib/atlasq/data/region.rb +0 -24
@@ -0,0 +1 @@
|
|
1
|
+
{"978":["eur"],"eur":["eur"],"€":["eur"],"euro":["eur"],"784":["aed"],"aed":["aed"],"د.ا":["aed","jod"],"united":["aed","usd"],"arab":["aed"],"emirates":["aed"],"dirham":["aed","mad"],"971":["afn"],"afn":["afn"],"؋":["afn"],"afghan":["afn"],"afghani":["afn"],"951":["xcd"],"xcd":["xcd"],"$":["xcd","usd","ars","aud","bbd","bmd","bnd","bsd","bzd","cad","nzd","clp","cop","cup","cve","dop","fjd","gyd","hkd","jmd","kyd","lrd","mxn","nad","sbd","sgd","srd","ttd","twd"],"east":["xcd"],"caribbean":["xcd"],"dollar":["xcd","usd","aud","bbd","bmd","bnd","bsd","bzd","cad","nzd","fjd","gyd","hkd","jmd","kyd","lrd","nad","sbd","sgd","srd","ttd","twd"],"008":["all"],"all":["all"],"l":["all","hnl","lsl","mdl"],"albanian":["all"],"lek":["all"],"051":["amd"],"amd":["amd"],"դր.":["amd"],"armenian":["amd"],"dram":["amd"],"973":["aoa"],"aoa":["aoa"],"kz":["aoa"],"angolan":["aoa"],"kwanza":["aoa"],"840":["usd"],"usd":["usd"],"states":["usd"],"032":["ars"],"ars":["ars"],"argentine":["ars"],"peso":["ars","clp","cop","cup","dop","mxn","php","uyu"],"036":["aud"],"aud":["aud"],"australian":["aud"],"533":["awg"],"awg":["awg"],"f":["awg","ang"],"aruban":["awg"],"florin":["awg"],"944":["azn"],"azn":["azn"],"₼":["azn"],"azerbaijani":["azn"],"manat":["azn","tmt"],"977":["bam"],"bam":["bam"],"км":["bam"],"bosnia":["bam"],"and":["bam","std","ttd"],"herzegovina":["bam"],"convertible":["bam"],"mark":["bam"],"052":["bbd"],"bbd":["bbd"],"barbadian":["bbd"],"050":["bdt"],"bdt":["bdt"],"৳":["bdt"],"bangladeshi":["bdt"],"taka":["bdt"],"952":["xof"],"xof":["xof"],"fr":["xof","bif","cdf","gnf","kmf","xpf"],"west":["xof"],"african":["xof","xaf","zar"],"cfa":["xof","xaf"],"franc":["xof","bif","cdf","xaf","chf","djf","gnf","kmf","xpf","rwf"],"975":["bgn"],"bgn":["bgn"],"лв.":["bgn"],"bulgarian":["bgn"],"lev":["bgn"],"048":["bhd"],"bhd":["bhd"],"د.ب":["bhd"],"bahraini":["bhd"],"dinar":["bhd","dzd","iqd","jod","kwd","lyd","rsd","tnd"],"108":["bif"],"bif":["bif"],"burundian":["bif"],"060":["bmd"],"bmd":["bmd"],"bermudian":["bmd"],"096":["bnd"],"bnd":["bnd"],"brunei":["bnd"],"068":["bob"],"bob":["bob"],"bs.":["bob"],"bolivian":["bob"],"boliviano":["bob"],"986":["brl"],"brl":["brl"],"r$":["brl"],"brazilian":["brl"],"real":["brl"],"044":["bsd"],"bsd":["bsd"],"bahamian":["bsd"],"064":["btn"],"btn":["btn"],"nu.":["btn"],"bhutanese":["btn"],"ngultrum":["btn"],"578":["nok"],"nok":["nok"],"kr":["nok","sek"],"norwegian":["nok"],"krone":["nok","dkk"],"072":["bwp"],"bwp":["bwp"],"p":["bwp","mop"],"botswana":["bwp"],"pula":["bwp"],"933":["byn"],"byn":["byn"],"br":["byn","etb"],"belarusian":["byn"],"ruble":["byn","rub"],"084":["bzd"],"bzd":["bzd"],"belize":["bzd"],"124":["cad"],"cad":["cad"],"canadian":["cad"],"976":["cdf"],"cdf":["cdf"],"congolese":["cdf"],"950":["xaf"],"xaf":["xaf"],"central":["xaf"],"756":["chf"],"chf":["chf"],"swiss":["chf"],"554":["nzd"],"nzd":["nzd"],"new":["nzd","ils","pgk","twd"],"zealand":["nzd"],"152":["clp"],"clp":["clp"],"chilean":["clp"],"156":["cny"],"cny":["cny"],"¥":["cny","jpy"],"chinese":["cny"],"renminbi":["cny"],"yuan":["cny"],"170":["cop"],"cop":["cop"],"colombian":["cop"],"188":["crc"],"crc":["crc"],"₡":["crc"],"costa":["crc"],"rican":["crc"],"colon":["crc"],"192":["cup"],"cup":["cup"],"cuban":["cup"],"132":["cve"],"cve":["cve"],"cape":["cve"],"verdean":["cve"],"escudo":["cve"],"532":["ang"],"ang":["ang"],"netherlands":["ang"],"antillean":["ang"],"gulden":["ang"],"203":["czk"],"czk":["czk"],"kc":["czk"],"czech":["czk"],"koruna":["czk"],"262":["djf"],"djf":["djf"],"fdj":["djf"],"djiboutian":["djf"],"208":["dkk"],"dkk":["dkk"],"kr.":["dkk","isk"],"danish":["dkk"],"214":["dop"],"dop":["dop"],"dominican":["dop"],"012":["dzd"],"dzd":["dzd"],"د.ج":["dzd"],"algerian":["dzd"],"818":["egp"],"egp":["egp"],"ج.م":["egp"],"egyptian":["egp"],"pound":["egp","fkp","gbp","gip","lbp","sdg","shp","ssp","syp"],"504":["mad"],"mad":["mad"],"د.م.":["mad"],"moroccan":["mad"],"230":["etb"],"etb":["etb"],"ethiopian":["etb"],"birr":["etb"],"242":["fjd"],"fjd":["fjd"],"fijian":["fjd"],"238":["fkp"],"fkp":["fkp"],"£":["fkp","gbp","gip","sdg","shp","ssp"],"falkland":["fkp"],"826":["gbp"],"gbp":["gbp"],"british":["gbp"],"981":["gel"],"gel":["gel"],"ლ":["gel"],"georgian":["gel"],"lari":["gel"],"936":["ghs"],"ghs":["ghs"],"₵":["ghs"],"ghanaian":["ghs"],"cedi":["ghs"],"292":["gip"],"gip":["gip"],"gibraltar":["gip"],"270":["gmd"],"gmd":["gmd"],"d":["gmd"],"gambian":["gmd"],"dalasi":["gmd"],"324":["gnf"],"gnf":["gnf"],"guinean":["gnf","pgk"],"320":["gtq"],"gtq":["gtq"],"q":["gtq"],"guatemalan":["gtq"],"quetzal":["gtq"],"328":["gyd"],"gyd":["gyd"],"guyanese":["gyd"],"344":["hkd"],"hkd":["hkd"],"hong":["hkd"],"kong":["hkd"],"340":["hnl"],"hnl":["hnl"],"honduran":["hnl"],"lempira":["hnl"],"332":["htg"],"htg":["htg"],"g":["htg"],"haitian":["htg"],"gourde":["htg"],"348":["huf"],"huf":["huf"],"ft":["huf"],"hungarian":["huf"],"forint":["huf"],"360":["idr"],"idr":["idr"],"rp":["idr"],"indonesian":["idr"],"rupiah":["idr"],"376":["ils"],"ils":["ils"],"₪":["ils"],"israeli":["ils"],"sheqel":["ils"],"356":["inr"],"inr":["inr"],"₹":["inr"],"indian":["inr"],"rupee":["inr","lkr","mur","npr","pkr","scr"],"368":["iqd"],"iqd":["iqd"],"ع.د":["iqd"],"iraqi":["iqd"],"364":["irr"],"irr":["irr"],"ریال":["irr","yer"],"iranian":["irr"],"rial":["irr","omr","yer"],"352":["isk"],"isk":["isk"],"icelandic":["isk"],"krona":["isk","sek"],"388":["jmd"],"jmd":["jmd"],"jamaican":["jmd"],"400":["jod"],"jod":["jod"],"jordanian":["jod"],"392":["jpy"],"jpy":["jpy"],"japanese":["jpy"],"yen":["jpy"],"404":["kes"],"kes":["kes"],"ksh":["kes"],"kenyan":["kes"],"shilling":["kes","sos","tzs","ugx"],"417":["kgs"],"kgs":["kgs"],"som":["kgs","uzs"],"kyrgyzstani":["kgs"],"116":["khr"],"khr":["khr"],"៛":["khr"],"cambodian":["khr"],"riel":["khr"],"174":["kmf"],"kmf":["kmf"],"comorian":["kmf"],"408":["kpw"],"kpw":["kpw"],"₩":["kpw","krw"],"north":["kpw"],"korean":["kpw","krw"],"won":["kpw","krw"],"410":["krw"],"krw":["krw"],"south":["krw","ssp","zar"],"414":["kwd"],"kwd":["kwd"],"د.ك":["kwd"],"kuwaiti":["kwd"],"136":["kyd"],"kyd":["kyd"],"cayman":["kyd"],"islands":["kyd","sbd"],"398":["kzt"],"kzt":["kzt"],"₸":["kzt"],"kazakhstani":["kzt"],"tenge":["kzt"],"418":["lak"],"lak":["lak"],"₭":["lak"],"lao":["lak"],"kip":["lak"],"422":["lbp"],"lbp":["lbp"],"ل.ل":["lbp"],"lebanese":["lbp"],"144":["lkr"],"lkr":["lkr"],"Rs":["lkr","mur","pkr","scr"],"sri":["lkr"],"lankan":["lkr"],"430":["lrd"],"lrd":["lrd"],"liberian":["lrd"],"426":["lsl"],"lsl":["lsl"],"lesotho":["lsl"],"loti":["lsl"],"434":["lyd"],"lyd":["lyd"],"ل.د":["lyd"],"libyan":["lyd"],"498":["mdl"],"mdl":["mdl"],"moldovan":["mdl"],"leu":["mdl","ron"],"969":["mga"],"mga":["mga"],"ar":["mga"],"malagasy":["mga"],"ariary":["mga"],"807":["mkd"],"mkd":["mkd"],"ден":["mkd"],"macedonian":["mkd"],"denar":["mkd"],"104":["mmk"],"mmk":["mmk"],"k":["mmk","pgk","zmw"],"myanmar":["mmk"],"kyat":["mmk"],"496":["mnt"],"mnt":["mnt"],"₮":["mnt"],"mongolian":["mnt"],"togrog":["mnt"],"446":["mop"],"mop":["mop"],"macanese":["mop"],"pataca":["mop"],"929":["mru"],"mru":["mru"],"um":["mru"],"mauritanian":["mru"],"ouguiya":["mru"],"480":["mur"],"mur":["mur"],"mauritian":["mur"],"462":["mvr"],"mvr":["mvr"],"maldivian":["mvr"],"rufiyaa":["mvr"],"454":["mwk"],"mwk":["mwk"],"mk":["mwk"],"malawian":["mwk"],"kwacha":["mwk","zmw"],"484":["mxn"],"mxn":["mxn"],"mexican":["mxn"],"458":["myr"],"myr":["myr"],"rm":["myr"],"malaysian":["myr"],"ringgit":["myr"],"943":["mzn"],"mzn":["mzn"],"mtn":["mzn"],"mozambican":["mzn"],"metical":["mzn"],"516":["nad"],"nad":["nad"],"namibian":["nad"],"953":["xpf"],"xpf":["xpf"],"cfp":["xpf"],"566":["ngn"],"ngn":["ngn"],"₦":["ngn"],"nigerian":["ngn"],"naira":["ngn"],"558":["nio"],"nio":["nio"],"c$":["nio"],"nicaraguan":["nio"],"cordoba":["nio"],"524":["npr"],"npr":["npr"],"rs.":["npr"],"nepalese":["npr"],"512":["omr"],"omr":["omr"],"ر.ع.":["omr"],"omani":["omr"],"590":["pab"],"pab":["pab"],"b/.":["pab"],"panamanian":["pab"],"balboa":["pab"],"604":["pen"],"pen":["pen"],"s/":["pen"],"peruvian":["pen"],"sol":["pen"],"598":["pgk"],"pgk":["pgk"],"papua":["pgk"],"kina":["pgk"],"608":["php"],"php":["php"],"₱":["php"],"philippine":["php"],"586":["pkr"],"pkr":["pkr"],"pakistani":["pkr"],"985":["pln"],"pln":["pln"],"zl":["pln"],"polish":["pln"],"zloty":["pln"],"600":["pyg"],"pyg":["pyg"],"₲":["pyg"],"paraguayan":["pyg"],"guarani":["pyg"],"634":["qar"],"qar":["qar"],"ر.ق":["qar"],"qatari":["qar"],"riyal":["qar","sar"],"946":["ron"],"ron":["ron"],"lei":["ron"],"romanian":["ron"],"941":["rsd"],"rsd":["rsd"],"рсд":["rsd"],"serbian":["rsd"],"643":["rub"],"rub":["rub"],"₽":["rub"],"russian":["rub"],"646":["rwf"],"rwf":["rwf"],"frw":["rwf"],"rwandan":["rwf"],"682":["sar"],"sar":["sar"],"ر.س":["sar"],"saudi":["sar"],"090":["sbd"],"sbd":["sbd"],"solomon":["sbd"],"690":["scr"],"scr":["scr"],"seychellois":["scr"],"938":["sdg"],"sdg":["sdg"],"sudanese":["sdg","ssp"],"752":["sek"],"sek":["sek"],"swedish":["sek"],"702":["sgd"],"sgd":["sgd"],"singapore":["sgd"],"654":["shp"],"shp":["shp"],"saint":["shp"],"helenian":["shp"],"694":["sll"],"sll":["sll"],"le":["sll"],"sierra":["sll"],"leonean":["sll"],"leone":["sll"],"706":["sos"],"sos":["sos"],"sh":["sos","tzs"],"somali":["sos"],"968":["srd"],"srd":["srd"],"surinamese":["srd"],"728":["ssp"],"ssp":["ssp"],"678":["std"],"std":["std"],"db":["std"],"sao":["std"],"tome":["std"],"principe":["std"],"dobra":["std"],"760":["syp"],"syp":["syp"],"£s":["syp"],"syrian":["syp"],"748":["szl"],"szl":["szl"],"e":["szl"],"swazi":["szl"],"lilangeni":["szl"],"764":["thb"],"thb":["thb"],"฿":["thb"],"thai":["thb"],"baht":["thb"],"972":["tjs"],"tjs":["tjs"],"ѕм":["tjs"],"tajikistani":["tjs"],"somoni":["tjs"],"934":["tmt"],"tmt":["tmt"],"t":["tmt","wst"],"turkmenistani":["tmt"],"788":["tnd"],"tnd":["tnd"],"د.ت":["tnd"],"tunisian":["tnd"],"776":["top"],"top":["top"],"t$":["top"],"tongan":["top"],"paʻanga":["top"],"949":["try"],"try":["try"],"₺":["try"],"turkish":["try"],"lira":["try"],"780":["ttd"],"ttd":["ttd"],"trinidad":["ttd"],"tobago":["ttd"],"901":["twd"],"twd":["twd"],"taiwan":["twd"],"834":["tzs"],"tzs":["tzs"],"tanzanian":["tzs"],"980":["uah"],"uah":["uah"],"₴":["uah"],"ukrainian":["uah"],"hryvnia":["uah"],"800":["ugx"],"ugx":["ugx"],"ush":["ugx"],"ugandan":["ugx"],"858":["uyu"],"uyu":["uyu"],"$u":["uyu"],"uruguayan":["uyu"],"860":["uzs"],"uzs":["uzs"],"so'm":["uzs"],"uzbekistan":["uzs"],"928":["ves"],"ves":["ves"],"bs":["ves"],"venezuelan":["ves"],"bolivar":["ves"],"soberano":["ves"],"704":["vnd"],"vnd":["vnd"],"₫":["vnd"],"vietnamese":["vnd"],"dong":["vnd"],"548":["vuv"],"vuv":["vuv"],"vt":["vuv"],"vanuatu":["vuv"],"vatu":["vuv"],"882":["wst"],"wst":["wst"],"samoan":["wst"],"tala":["wst"],"886":["yer"],"yer":["yer"],"yemeni":["yer"],"710":["zar"],"zar":["zar"],"r":["zar"],"rand":["zar"],"967":["zmw"],"zmw":["zmw"],"zambian":["zmw"]}
|
data/lib/atlasq/cache.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Atlasq
|
6
|
+
module Cache
|
7
|
+
CACHE_DIR = File.expand_path("../../cache", __dir__).freeze
|
8
|
+
private_constant :CACHE_DIR
|
9
|
+
|
10
|
+
# @param full_name [String] namespace + file name (ex. "info/countries.json")
|
11
|
+
# @return file
|
12
|
+
def self.get(full_name)
|
13
|
+
@get ||= {}
|
14
|
+
@get.fetch(full_name) do
|
15
|
+
path = "#{CACHE_DIR}/#{full_name}"
|
16
|
+
content = File.read(path)
|
17
|
+
|
18
|
+
case full_name
|
19
|
+
when /\.json$/
|
20
|
+
JSON.parse(content)
|
21
|
+
else
|
22
|
+
content
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/atlasq/command/any.rb
CHANGED
@@ -7,11 +7,13 @@ module Atlasq
|
|
7
7
|
class Any < Base
|
8
8
|
def content
|
9
9
|
search_terms.map do |term|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
Format.
|
10
|
+
if (country = Data.country(term))
|
11
|
+
Format.country(country)
|
12
|
+
elsif (country_codes = Data.countries_by_region(term))
|
13
|
+
region_name = Util::String.titleize(term)
|
14
|
+
Format.countries(country_codes, title: "Region: #{region_name}")
|
15
|
+
elsif (currencies = Data.countries_by_currencies(term))
|
16
|
+
Format.currencies(currencies)
|
15
17
|
else
|
16
18
|
Atlasq.failed!
|
17
19
|
"Unknown search term: #{term}"
|
data/lib/atlasq/command/base.rb
CHANGED
@@ -8,14 +8,14 @@ module Atlasq
|
|
8
8
|
# @return [String]
|
9
9
|
def content
|
10
10
|
if search_terms.empty?
|
11
|
-
|
12
|
-
Format.countries(
|
11
|
+
country_codes = Data.all_countries
|
12
|
+
Format.countries(country_codes, title: "All Countries")
|
13
13
|
else
|
14
14
|
search_terms.map do |term|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
Format.
|
15
|
+
if (country_code = Data.country(term))
|
16
|
+
Format.country(country_code)
|
17
|
+
elsif (country_codes = PartialMatch.countries(term)).any?
|
18
|
+
Format.countries(country_codes, title: "Countries (Partial Match)")
|
19
19
|
else
|
20
20
|
Atlasq.failed!
|
21
21
|
"Unknown country: #{term}"
|
data/lib/atlasq/command/help.rb
CHANGED
@@ -41,6 +41,7 @@ module Atlasq
|
|
41
41
|
2. alpha3 (ISO3166 standard 3 letter code)
|
42
42
|
3. number (ISO3166 standard 3 digit code)
|
43
43
|
4. name (common, localized, unofficial)
|
44
|
+
5. partial match on name
|
44
45
|
|
45
46
|
-r/--region
|
46
47
|
: Display all countries by subregion
|
@@ -58,6 +59,7 @@ module Atlasq
|
|
58
59
|
1. code (ISO4127 standard 3 letter code)
|
59
60
|
2. name (ISO4127 standard name)
|
60
61
|
3. symbol
|
62
|
+
4. partial match on name
|
61
63
|
|
62
64
|
-h/--help
|
63
65
|
: Display this page
|
data/lib/atlasq/command/money.rb
CHANGED
@@ -11,13 +11,14 @@ module Atlasq
|
|
11
11
|
Format.currencies(currencies)
|
12
12
|
else
|
13
13
|
search_terms.map do |term|
|
14
|
-
currencies = Data.
|
15
|
-
|
16
|
-
|
14
|
+
if (currencies = Data.countries_by_currencies(term))
|
15
|
+
Format.currencies(currencies)
|
16
|
+
elsif (currency_codes = PartialMatch.currencies(term)).any?
|
17
|
+
currencies = Data.countries_by_currencies(currency_codes)
|
18
|
+
Format.currencies(currencies, partial_match: true)
|
19
|
+
else
|
17
20
|
Atlasq.failed!
|
18
21
|
"Unknown currency: #{term}"
|
19
|
-
else
|
20
|
-
Format.currencies(currencies)
|
21
22
|
end
|
22
23
|
end.join("\n\n")
|
23
24
|
end
|
@@ -11,10 +11,9 @@ module Atlasq
|
|
11
11
|
Format.subregions(subregions)
|
12
12
|
else
|
13
13
|
search_terms.map do |term|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Format.region(region)
|
14
|
+
if (country_codes = Data.countries_by_region(term))
|
15
|
+
region_name = Util::String.titleize(term)
|
16
|
+
Format.countries(country_codes, title: "Region: #{region_name}")
|
18
17
|
else
|
19
18
|
Atlasq.failed!
|
20
19
|
"Unknown region: #{term}"
|
data/lib/atlasq/command.rb
CHANGED
data/lib/atlasq/data.rb
CHANGED
@@ -1,113 +1,56 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "countries"
|
4
|
-
require "iso-639"
|
5
|
-
require "money"
|
6
|
-
require "money-heuristics"
|
7
|
-
|
8
|
-
ISO3166.configure do |config|
|
9
|
-
# Needed to allow us to access the `ISO3166::Country#currency`
|
10
|
-
# object which ends up being an instance of `Money::Currency`.
|
11
|
-
config.enable_currency_extension!
|
12
|
-
|
13
|
-
# Needed to allow us to search by localized country name.
|
14
|
-
config.locales = %i[
|
15
|
-
af am ar as az be bg bn br bs
|
16
|
-
ca cs cy da de dz el en eo es
|
17
|
-
et eu fa fi fo fr ga gl gu he
|
18
|
-
hi hr hu hy ia id is it ja ka
|
19
|
-
kk km kn ko ku lt lv mi mk ml
|
20
|
-
mn mr ms mt nb ne nl nn oc or
|
21
|
-
pa pl ps pt ro ru rw si sk sl
|
22
|
-
so sq sr sv sw ta te th ti tk
|
23
|
-
tl tr tt ug uk ve vi wa wo xh
|
24
|
-
zh zu
|
25
|
-
]
|
26
|
-
end
|
27
|
-
|
28
3
|
module Atlasq
|
29
4
|
module Data
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
Data.country(term) ||
|
37
|
-
Data.region(term) ||
|
38
|
-
Data.currencies(term)
|
5
|
+
# @param term [String] search term
|
6
|
+
# @return [String, nil] ISO3166 2 letter country code
|
7
|
+
def self.country(term)
|
8
|
+
Cache
|
9
|
+
.get("search_index/direct_match_country.json")
|
10
|
+
.dig(term)
|
39
11
|
end
|
40
12
|
|
41
|
-
# @param term [String]
|
42
|
-
# @return [
|
43
|
-
def self.
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
ISO3166::Country.find_country_by_any_name(term)
|
13
|
+
# @param term [String] search term
|
14
|
+
# @return [Array<String>, nil] ISO3166 2 letter country codes
|
15
|
+
def self.countries_by_region(term)
|
16
|
+
Cache
|
17
|
+
.get("search_index/countries_by_region.json")
|
18
|
+
.dig(term)
|
48
19
|
end
|
49
20
|
|
50
|
-
# @return [Array<
|
21
|
+
# @return [Array<String>] ISO3166 2 letter country codes
|
51
22
|
def self.all_countries
|
52
|
-
|
23
|
+
Cache.get("list/all_countries.json")
|
53
24
|
end
|
54
25
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
# @return [Atlasq::Data::Region|nil]
|
59
|
-
def self.region(term)
|
60
|
-
REGION_TYPES.each do |region_type|
|
61
|
-
countries = ISO3166::Country.find_all_by(region_type, term)
|
62
|
-
next if countries.empty?
|
26
|
+
# @return [Array<String>]
|
27
|
+
def self.all_subregions
|
28
|
+
subregions = Cache.get("list/all_subregions.json")
|
63
29
|
|
64
|
-
|
65
|
-
|
66
|
-
|
30
|
+
Cache
|
31
|
+
.get("search_index/countries_by_region.json")
|
32
|
+
.slice(*subregions)
|
67
33
|
end
|
68
34
|
|
69
|
-
# @
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
# (334 | HM | HMD | Heard Island and McDonald Islands)
|
78
|
-
subregions.delete("")
|
79
|
-
end
|
80
|
-
end
|
35
|
+
# @param terms [String, Array<String>] search terms
|
36
|
+
# @return [Hash<String, Array<String>>] ISO4127 3 letter currency code to ISO3166 2 letter country codes
|
37
|
+
def self.countries_by_currencies(terms)
|
38
|
+
terms = Array(terms)
|
39
|
+
currency_codes = Cache
|
40
|
+
.get("search_index/direct_match_currency.json")
|
41
|
+
.values_at(*terms)
|
42
|
+
.compact
|
81
43
|
|
82
|
-
|
83
|
-
# @return [Array<Atlasq::Data::Currency>]
|
84
|
-
def self.currencies(term)
|
85
|
-
currency_codes = Money::Currency.analyze(term)
|
86
|
-
currency_codes.filter_map do |currency_code|
|
87
|
-
countries = ISO3166::Country.find_all_by(:currency_code, currency_code)
|
88
|
-
next if countries.empty?
|
44
|
+
return if currency_codes.empty?
|
89
45
|
|
90
|
-
|
91
|
-
|
46
|
+
Cache
|
47
|
+
.get("search_index/countries_by_currency.json")
|
48
|
+
.slice(*currency_codes)
|
92
49
|
end
|
93
50
|
|
94
|
-
# @return [Array<
|
51
|
+
# @return [Hash<String, Array<String>>] ISO4127 3 letter currency code to ISO3166 2 letter country codes
|
95
52
|
def self.all_currencies
|
96
|
-
|
97
|
-
.group_by(&:currency_code)
|
98
|
-
.map do |currency_code, countries|
|
99
|
-
Currency.new(countries: countries, currency_code: currency_code)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# @param number [String] ISO3166-1 numeric country code
|
104
|
-
# @return [String, nil]
|
105
|
-
def self.emoji_flag(iso_number)
|
106
|
-
@emoji_flag ||= all_countries
|
107
|
-
.to_h { |country| [country.number, country.emoji_flag] }
|
108
|
-
.freeze
|
109
|
-
|
110
|
-
@emoji_flag[iso_number]
|
53
|
+
Cache.get("search_index/countries_by_currency.json")
|
111
54
|
end
|
112
55
|
end
|
113
56
|
end
|
data/lib/atlasq/format.rb
CHANGED
@@ -13,7 +13,7 @@ module Atlasq
|
|
13
13
|
[
|
14
14
|
"*",
|
15
15
|
"* #{title}",
|
16
|
-
"*#{" *" * ((title.size / 2) + 2)}"
|
16
|
+
"*#{" *" * ((title.size / 2) + 2)}",
|
17
17
|
].join("\n")
|
18
18
|
end
|
19
19
|
|
@@ -56,168 +56,95 @@ module Atlasq
|
|
56
56
|
|
57
57
|
[
|
58
58
|
Format.title(title),
|
59
|
-
*elements
|
59
|
+
*elements,
|
60
60
|
].join("\n")
|
61
61
|
end
|
62
62
|
|
63
|
-
# @
|
64
|
-
# *
|
65
|
-
# * Title
|
66
|
-
# * * * * *
|
67
|
-
# (attr1 | attr2 | attr3)
|
68
|
-
# | Info One: 1
|
69
|
-
# | Info Two: 2
|
70
|
-
# | Info Three: 3
|
71
|
-
# |________________________________________
|
72
|
-
#
|
63
|
+
# @param country_codes [Array<String>] ISO3166 2 letter country codes
|
73
64
|
# @param title [String]
|
74
|
-
# @param attributes [String]
|
75
|
-
# @param info [Hash<String, String>]
|
76
|
-
# @return [String]
|
77
|
-
def self.verbose_template(title:, attributes:, info:)
|
78
|
-
info_ladder = info.map.with_index do |(name, value), index|
|
79
|
-
"#{" " * (index + 1)}| #{name}: #{value}"
|
80
|
-
end
|
81
|
-
info_ladder << "#{" " * (info_ladder.size + 1)}|#{"_" * 40}"
|
82
|
-
|
83
|
-
[
|
84
|
-
Format.title(title),
|
85
|
-
attributes,
|
86
|
-
*info_ladder
|
87
|
-
].join("\n")
|
88
|
-
end
|
89
|
-
|
90
|
-
# @param value
|
91
|
-
# @param search_term [String]
|
92
|
-
# @return [String]
|
93
|
-
def self.any(value, search_term)
|
94
|
-
case value
|
95
|
-
in ISO3166::Country
|
96
|
-
Format.country(value, search_term)
|
97
|
-
in Atlasq::Data::Region
|
98
|
-
Format.region(value)
|
99
|
-
in [Atlasq::Data::Currency, *]
|
100
|
-
Format.currencies(value)
|
101
|
-
else
|
102
|
-
raise Error, "Unknown format type: #{value.class}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# @param country [ISO3166::Country]
|
107
|
-
# @param search_term [String]
|
108
|
-
# @return [String]
|
109
|
-
def self.country(country, search_term)
|
110
|
-
Format.verbose_template(
|
111
|
-
title: "Country: #{country.iso_long_name}",
|
112
|
-
attributes: Format.one_line_country(country),
|
113
|
-
info: {
|
114
|
-
"Search Term" => search_term,
|
115
|
-
"Languages" => Format.languages(country.languages),
|
116
|
-
"Nationality" => country.nationality,
|
117
|
-
"Region" => country.subregion,
|
118
|
-
"Continent" => country.continent,
|
119
|
-
"Currency" => "#{country.currency.symbol} #{country.currency.name}"
|
120
|
-
}.reject do |_, value|
|
121
|
-
# "countries" like Antarctica can have missing language, nationality,
|
122
|
-
# and region data so we remove that missing data beforehand.
|
123
|
-
value.nil? || value.empty?
|
124
|
-
end.to_h
|
125
|
-
)
|
126
|
-
end
|
127
|
-
|
128
|
-
# @example "English / Shona / Ndebele, North; North Ndebele"
|
129
|
-
# @param language_codes [Array<String>] Ex. ["id"]
|
130
65
|
# @return [String]
|
131
|
-
def self.
|
132
|
-
language_codes
|
133
|
-
.take(4) # arbitrary limit to avoid long lines
|
134
|
-
.map do |lang|
|
135
|
-
ISO_639.find(lang).english_name
|
136
|
-
end
|
137
|
-
.join(" / ")
|
138
|
-
end
|
139
|
-
|
140
|
-
# @param countries [Array<ISO3166::Country|Hash>]
|
141
|
-
# @param title [String]
|
142
|
-
# @return [String]
|
143
|
-
def self.countries(countries, title:)
|
66
|
+
def self.countries(country_codes, title:)
|
144
67
|
Format.brief_template(
|
145
68
|
title: title,
|
146
|
-
elements:
|
69
|
+
elements: country_codes.map do |country|
|
147
70
|
Format.one_line_country(country)
|
148
71
|
end
|
149
72
|
)
|
150
73
|
end
|
151
74
|
|
152
|
-
# @param
|
75
|
+
# @param country_code [String] ISO3166 2 letter country code
|
153
76
|
# @return [String]
|
154
|
-
def self.
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
country.alpha3,
|
162
|
-
country.iso_short_name
|
163
|
-
]
|
164
|
-
when Hash
|
165
|
-
values = country.slice(
|
166
|
-
"number",
|
167
|
-
"alpha2",
|
168
|
-
"alpha3",
|
169
|
-
"iso_short_name"
|
170
|
-
).values
|
77
|
+
def self.country(country_code)
|
78
|
+
[
|
79
|
+
Format.country_title(country_code),
|
80
|
+
Format.one_line_country(country_code),
|
81
|
+
Format.multiline_country(country_code),
|
82
|
+
].join("\n")
|
83
|
+
end
|
171
84
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
"(#{country_values.compact.join(" | ")})"
|
180
|
-
end
|
85
|
+
# @param country_code [String] ISO3166 2 letter country code
|
86
|
+
# @return [String]
|
87
|
+
def self.country_title(country_code)
|
88
|
+
Cache
|
89
|
+
.get("formatted_output/country_title.json")
|
90
|
+
.fetch(country_code)
|
91
|
+
.then(&Format.method(:title))
|
181
92
|
end
|
182
93
|
|
183
|
-
# @param
|
94
|
+
# @param country_code [String] ISO3166 2 letter country code
|
184
95
|
# @return [String]
|
185
|
-
def self.
|
186
|
-
|
187
|
-
|
96
|
+
def self.one_line_country(country_code)
|
97
|
+
Cache
|
98
|
+
.get("formatted_output/one_line_country.json")
|
99
|
+
.fetch(country_code)
|
100
|
+
end
|
188
101
|
|
189
|
-
|
102
|
+
# @param country_code [String] ISO3166 2 letter country code
|
103
|
+
# @return [String]
|
104
|
+
def self.multiline_country(country_code)
|
105
|
+
Cache
|
106
|
+
.get("formatted_output/multiline_country.json")
|
107
|
+
.fetch(country_code)
|
190
108
|
end
|
191
109
|
|
192
|
-
# @param subregions [Hash<String, Array<
|
110
|
+
# @param subregions [Hash<String, Array<String>>] region name to ISO3166 2 letter country codes
|
193
111
|
# @return [String]
|
194
112
|
def self.subregions(subregions)
|
195
|
-
subregions.
|
196
|
-
|
113
|
+
subregions = subregions.to_h do |region, countries|
|
114
|
+
[
|
115
|
+
Util::String.titleize(region),
|
116
|
+
countries.map(&Format.method(:one_line_country)),
|
117
|
+
]
|
197
118
|
end
|
198
119
|
|
199
120
|
Format.brief_template(title: "All Subregions", elements: subregions)
|
200
121
|
end
|
201
122
|
|
202
|
-
# @param currencies [Array<
|
123
|
+
# @param currencies [Hash<String, Array<String>>] 3 letter currency code to ISO3166 2 letter country codes
|
124
|
+
# @param partial_match [Boolean] defaults to false
|
203
125
|
# @return [String]
|
204
|
-
def self.currencies(currencies)
|
205
|
-
currencies = currencies.to_h do |
|
206
|
-
currency = Money::Currency.new(currency_class.currency_code)
|
207
|
-
|
126
|
+
def self.currencies(currencies, partial_match: false)
|
127
|
+
currencies = currencies.to_h do |currency, countries|
|
208
128
|
[
|
209
|
-
|
210
|
-
|
129
|
+
Format.one_line_currency(currency),
|
130
|
+
countries.map(&Format.method(:one_line_country)),
|
211
131
|
]
|
212
132
|
end
|
213
133
|
|
214
|
-
if currencies.size == 1
|
134
|
+
if !partial_match && currencies.size == 1
|
215
135
|
title, elements = currencies.first
|
216
136
|
title = "Currency: #{title}"
|
217
137
|
Format.brief_template(title: title, elements: elements)
|
218
138
|
else
|
219
|
-
|
139
|
+
title = partial_match ? "Currencies (Partial Match)" : "Currencies"
|
140
|
+
Format.brief_template(title: title, elements: currencies)
|
220
141
|
end
|
221
142
|
end
|
143
|
+
|
144
|
+
def self.one_line_currency(currency_code)
|
145
|
+
Cache
|
146
|
+
.get("formatted_output/one_line_currency.json")
|
147
|
+
.fetch(currency_code)
|
148
|
+
end
|
222
149
|
end
|
223
150
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Atlasq
|
4
|
+
module PartialMatch
|
5
|
+
# @param term [String]
|
6
|
+
# @return [Array<String>] 3 digit country codes (ISO3166)
|
7
|
+
def self.countries(term)
|
8
|
+
@countries ||= Util::WordMap.new(index: Cache.get("search_index/partial_match_country.json"))
|
9
|
+
@countries.search(term)
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param term [String]
|
13
|
+
# @return [Array<String>] 3 letter currency codes (ISO4217)
|
14
|
+
def self.currencies(term)
|
15
|
+
@currencies ||= Util::WordMap.new(index: Cache.get("search_index/partial_match_currency.json"))
|
16
|
+
@currencies.search(term)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/atlasq/util/string.rb
CHANGED
@@ -1,16 +1,52 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "unaccent"
|
4
|
+
|
3
5
|
module Atlasq
|
4
6
|
module Util
|
5
7
|
module String
|
6
|
-
|
8
|
+
ABBREVIATIONS = {
|
9
|
+
"AMER" => "North, Central and South America",
|
10
|
+
"APAC" => "Asia-Pacific",
|
11
|
+
"EMEA" => "Europe, Middle East, and Africa",
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
# @param string [String]
|
7
15
|
# @return [String]
|
8
16
|
def self.titleize(string)
|
9
|
-
string
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
17
|
+
abbreviation = string.upcase
|
18
|
+
|
19
|
+
if (full_name = ABBREVIATIONS[abbreviation])
|
20
|
+
"#{full_name} (#{abbreviation})"
|
21
|
+
else
|
22
|
+
words = string.split(/[-_ \t]+/)
|
23
|
+
words.map! do |word|
|
24
|
+
if word.match?(/^(?:of|the|and)$/i)
|
25
|
+
word.downcase
|
26
|
+
else
|
27
|
+
word.capitalize
|
28
|
+
end
|
29
|
+
end
|
30
|
+
words.join(" ")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Make string lowercase and remove accents.
|
35
|
+
#
|
36
|
+
# @param string [String]
|
37
|
+
# @return [String]
|
38
|
+
def self.normalize(string)
|
39
|
+
@normalize ||= {}
|
40
|
+
@normalize[string] ||= Unaccent.unaccent(string.downcase)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Split on spaces, tabs and punctuation separators.
|
44
|
+
# Note: Some punctuation can be connectors or separators based on the language.
|
45
|
+
#
|
46
|
+
# @param sentence [String]
|
47
|
+
# @return [Array<String>]
|
48
|
+
def self.word_split(sentence)
|
49
|
+
sentence.split(/[ \t,;:()]+/).reject(&:empty?)
|
14
50
|
end
|
15
51
|
end
|
16
52
|
end
|