atlasq 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- 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/country.rb +6 -3
- 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 +48 -60
- data/lib/atlasq/format.rb +14 -39
- data/lib/atlasq/partial_match.rb +19 -0
- data/lib/atlasq/util/string.rb +41 -6
- data/lib/atlasq/util/word_map.rb +46 -0
- data/lib/atlasq/util.rb +1 -0
- data/lib/atlasq/version.rb +1 -1
- data/lib/atlasq.rb +2 -0
- metadata +11 -18
- 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, term)
|
12
|
+
elsif (countries = Data.countries_by_region(term))
|
13
|
+
region_name = Util::String.titleize(term)
|
14
|
+
Format.countries(countries, 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}"
|
@@ -12,10 +12,13 @@ module Atlasq
|
|
12
12
|
Format.countries(countries, title: "All Countries")
|
13
13
|
else
|
14
14
|
search_terms.map do |term|
|
15
|
-
country = Data.country(term)
|
16
|
-
|
17
|
-
if country
|
15
|
+
if (country = Data.country(term))
|
18
16
|
Format.country(country, term)
|
17
|
+
elsif (country_codes = PartialMatch.countries(term)).any?
|
18
|
+
countries = country_codes.map do |code|
|
19
|
+
Data.country_by_code(code)
|
20
|
+
end
|
21
|
+
Format.countries(countries, title: "Countries (Partial Match)")
|
19
22
|
else
|
20
23
|
Atlasq.failed!
|
21
24
|
"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 (countries = Data.countries_by_region(term))
|
15
|
+
region_name = Util::String.titleize(term)
|
16
|
+
Format.countries(countries, 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
@@ -3,48 +3,28 @@
|
|
3
3
|
require "countries"
|
4
4
|
require "iso-639"
|
5
5
|
require "money"
|
6
|
-
require "money-heuristics"
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
7
|
+
# Needed to allow us to access the `ISO3166::Country#currency`
|
8
|
+
# object which ends up being an instance of `Money::Currency`.
|
9
|
+
ISO3166.configure(&:enable_currency_extension!)
|
27
10
|
|
28
11
|
module Atlasq
|
29
12
|
module Data
|
30
13
|
autoload :Currency, "atlasq/data/currency"
|
31
|
-
autoload :Region, "atlasq/data/region"
|
32
14
|
|
33
15
|
# @param term [String]
|
34
|
-
# @return [ISO3166::Country,
|
35
|
-
def self.
|
36
|
-
|
37
|
-
|
38
|
-
|
16
|
+
# @return [ISO3166::Country, nil]
|
17
|
+
def self.country(term)
|
18
|
+
Cache
|
19
|
+
.get("search_index/direct_match_country.json")
|
20
|
+
.dig(Util::String.normalize(term))
|
21
|
+
&.then { |key| ISO3166::Country.new(key) }
|
39
22
|
end
|
40
23
|
|
41
|
-
# @param
|
42
|
-
# @return [ISO3166::Country
|
43
|
-
def self.
|
44
|
-
ISO3166::Country.find_country_by_alpha2(
|
45
|
-
ISO3166::Country.find_country_by_alpha3(term) ||
|
46
|
-
ISO3166::Country.find_country_by_number(term) ||
|
47
|
-
ISO3166::Country.find_country_by_any_name(term)
|
24
|
+
# @param code [String] alpha2 country code
|
25
|
+
# @return [ISO3166::Country, nil]
|
26
|
+
def self.country_by_code(code)
|
27
|
+
ISO3166::Country.find_country_by_alpha2(code)
|
48
28
|
end
|
49
29
|
|
50
30
|
# @return [Array<ISO3166::Country>]
|
@@ -52,18 +32,13 @@ module Atlasq
|
|
52
32
|
@all_countries ||= ISO3166::Country.all
|
53
33
|
end
|
54
34
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
next if countries.empty?
|
63
|
-
|
64
|
-
return Region.new(countries: countries.values, type: region_type)
|
65
|
-
end
|
66
|
-
nil
|
35
|
+
# @param term [String]
|
36
|
+
# @return [Array<ISO3166::Country>, nil]
|
37
|
+
def self.countries_by_region(term)
|
38
|
+
Cache
|
39
|
+
.get("search_index/countries_by_region.json")
|
40
|
+
.dig(Util::String.normalize(term))
|
41
|
+
&.map { |key| ISO3166::Country.new(key) }
|
67
42
|
end
|
68
43
|
|
69
44
|
# @return [Hash<String, Array<ISO3166::Country>>] Ex. { "Central Asia" => [...], ... }
|
@@ -79,24 +54,37 @@ module Atlasq
|
|
79
54
|
end
|
80
55
|
end
|
81
56
|
|
82
|
-
# @param
|
83
|
-
# @return [Array<
|
84
|
-
def self.
|
85
|
-
|
86
|
-
currency_codes
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
57
|
+
# @param terms [String, Array<String>]
|
58
|
+
# @return [Hash<Money::Currency, Array<ISO3166::Country>>]
|
59
|
+
def self.countries_by_currencies(terms)
|
60
|
+
terms = Array(terms).map(&Util::String.method(:normalize))
|
61
|
+
currency_codes = Cache
|
62
|
+
.get("search_index/direct_match_currency.json")
|
63
|
+
.values_at(*terms)
|
64
|
+
.compact
|
65
|
+
|
66
|
+
return if currency_codes.empty?
|
67
|
+
|
68
|
+
Cache
|
69
|
+
.get("search_index/countries_by_currency.json")
|
70
|
+
.slice(*currency_codes)
|
71
|
+
.to_h do |currency_code, country_codes|
|
72
|
+
[
|
73
|
+
Money::Currency.new(currency_code),
|
74
|
+
country_codes.map(&Data.method(:country_by_code)),
|
75
|
+
]
|
76
|
+
end
|
92
77
|
end
|
93
78
|
|
94
|
-
# @return [Array<
|
79
|
+
# @return [Hash<Money::Currency, Array<ISO3166::Country>>]
|
95
80
|
def self.all_currencies
|
96
|
-
|
97
|
-
.
|
98
|
-
.
|
99
|
-
|
81
|
+
Cache
|
82
|
+
.get("search_index/countries_by_currency.json")
|
83
|
+
.to_h do |currency_code, country_codes|
|
84
|
+
[
|
85
|
+
Money::Currency.new(currency_code),
|
86
|
+
country_codes.map(&Data.method(:country_by_code)),
|
87
|
+
]
|
100
88
|
end
|
101
89
|
end
|
102
90
|
|
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,7 +56,7 @@ module Atlasq
|
|
56
56
|
|
57
57
|
[
|
58
58
|
Format.title(title),
|
59
|
-
*elements
|
59
|
+
*elements,
|
60
60
|
].join("\n")
|
61
61
|
end
|
62
62
|
|
@@ -83,26 +83,10 @@ module Atlasq
|
|
83
83
|
[
|
84
84
|
Format.title(title),
|
85
85
|
attributes,
|
86
|
-
*info_ladder
|
86
|
+
*info_ladder,
|
87
87
|
].join("\n")
|
88
88
|
end
|
89
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
90
|
# @param country [ISO3166::Country]
|
107
91
|
# @param search_term [String]
|
108
92
|
# @return [String]
|
@@ -116,7 +100,7 @@ module Atlasq
|
|
116
100
|
"Nationality" => country.nationality,
|
117
101
|
"Region" => country.subregion,
|
118
102
|
"Continent" => country.continent,
|
119
|
-
"Currency" => "#{country.currency.symbol} #{country.currency.name}"
|
103
|
+
"Currency" => "#{country.currency.symbol} #{country.currency.name}",
|
120
104
|
}.reject do |_, value|
|
121
105
|
# "countries" like Antarctica can have missing language, nationality,
|
122
106
|
# and region data so we remove that missing data beforehand.
|
@@ -159,7 +143,7 @@ module Atlasq
|
|
159
143
|
country.number,
|
160
144
|
country.alpha2,
|
161
145
|
country.alpha3,
|
162
|
-
country.iso_short_name
|
146
|
+
country.iso_short_name,
|
163
147
|
]
|
164
148
|
when Hash
|
165
149
|
values = country.slice(
|
@@ -171,7 +155,7 @@ module Atlasq
|
|
171
155
|
|
172
156
|
[
|
173
157
|
Data.emoji_flag(country.fetch("number")),
|
174
|
-
*values
|
158
|
+
*values,
|
175
159
|
]
|
176
160
|
else
|
177
161
|
raise Error, "Unknown country type: #{country.class}"
|
@@ -180,15 +164,6 @@ module Atlasq
|
|
180
164
|
end
|
181
165
|
end
|
182
166
|
|
183
|
-
# @param region [Atlasq::Data::Region]
|
184
|
-
# @return [String]
|
185
|
-
def self.region(region)
|
186
|
-
type = Util::String.titleize(region.type)
|
187
|
-
title = "#{type}: #{region.name}"
|
188
|
-
|
189
|
-
Format.countries(region.countries, title: title)
|
190
|
-
end
|
191
|
-
|
192
167
|
# @param subregions [Hash<String, Array<ISO3166::Country>>]
|
193
168
|
# @return [String]
|
194
169
|
def self.subregions(subregions)
|
@@ -199,24 +174,24 @@ module Atlasq
|
|
199
174
|
Format.brief_template(title: "All Subregions", elements: subregions)
|
200
175
|
end
|
201
176
|
|
202
|
-
# @param currencies [Array<
|
177
|
+
# @param currencies [Hash<Money::Currency, Array<ISO3166::Country>>]
|
178
|
+
# @param partial_match [Boolean] defaults to false
|
203
179
|
# @return [String]
|
204
|
-
def self.currencies(currencies)
|
205
|
-
currencies = currencies.to_h do |
|
206
|
-
currency = Money::Currency.new(currency_class.currency_code)
|
207
|
-
|
180
|
+
def self.currencies(currencies, partial_match: false)
|
181
|
+
currencies = currencies.to_h do |currency, countries|
|
208
182
|
[
|
209
183
|
"[#{currency.iso_code}] #{currency.symbol} #{currency.name}",
|
210
|
-
|
184
|
+
countries.map(&Format.method(:one_line_country)),
|
211
185
|
]
|
212
186
|
end
|
213
187
|
|
214
|
-
if currencies.size == 1
|
188
|
+
if !partial_match && currencies.size == 1
|
215
189
|
title, elements = currencies.first
|
216
190
|
title = "Currency: #{title}"
|
217
191
|
Format.brief_template(title: title, elements: elements)
|
218
192
|
else
|
219
|
-
|
193
|
+
title = partial_match ? "Currencies (Partial Match)" : "Currencies"
|
194
|
+
Format.brief_template(title: title, elements: currencies)
|
220
195
|
end
|
221
196
|
end
|
222
197
|
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,51 @@
|
|
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 a sentence on words ignoring irrelevant punctuation.
|
44
|
+
#
|
45
|
+
# @param sentence [String]
|
46
|
+
# @return [Array<String>]
|
47
|
+
def self.word_split(sentence)
|
48
|
+
sentence.split(/[ \t,;:()]+/).reject(&:empty?)
|
14
49
|
end
|
15
50
|
end
|
16
51
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
require "unaccent"
|
5
|
+
|
6
|
+
module Atlasq
|
7
|
+
module Util
|
8
|
+
# This data structure provides partial match support for words in sentences.
|
9
|
+
#
|
10
|
+
# For example, if we take a country like "Bonaire, Sint Eustatius and Saba"
|
11
|
+
# the searches "Bonaire", "Sint Eustatius" and "saba bonaire" should all match
|
12
|
+
# while the searches "bonaire france" and "saba bolivia" should not because
|
13
|
+
# they include words not found in the original sentence.
|
14
|
+
class WordMap
|
15
|
+
# @param index [Hash<String, Array<String>>]
|
16
|
+
def initialize(index:)
|
17
|
+
@index = index
|
18
|
+
end
|
19
|
+
|
20
|
+
# Search for ids that include all of the search term words.
|
21
|
+
#
|
22
|
+
# @param search_term [String]
|
23
|
+
# @return [Array<String>] list of ids
|
24
|
+
def search(search_term)
|
25
|
+
search_term
|
26
|
+
.then { |string| split(string) }
|
27
|
+
.map { |word| Util::String.normalize(word) }
|
28
|
+
.uniq
|
29
|
+
.map { |word| @index.fetch(word, []) }
|
30
|
+
.inject(&:intersection)
|
31
|
+
.sort
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# Split on spaces, tabs and punctuation separators.
|
37
|
+
# Note: Some punctuation can be connectors or separators based on the language.
|
38
|
+
#
|
39
|
+
# @param sentence [String]
|
40
|
+
# @return [Array<String>]
|
41
|
+
def split(sentence)
|
42
|
+
sentence.split(/[ \t,;:()]+/).reject(&:empty?)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/atlasq/util.rb
CHANGED
data/lib/atlasq/version.rb
CHANGED
data/lib/atlasq.rb
CHANGED
@@ -6,9 +6,11 @@ module Atlasq
|
|
6
6
|
class Error < StandardError; end
|
7
7
|
DEBUG = ENV.key?("ATLASQ_DEBUG")
|
8
8
|
|
9
|
+
autoload :Cache, "atlasq/cache"
|
9
10
|
autoload :Command, "atlasq/command"
|
10
11
|
autoload :Data, "atlasq/data"
|
11
12
|
autoload :Format, "atlasq/format"
|
13
|
+
autoload :PartialMatch, "atlasq/partial_match"
|
12
14
|
autoload :Shell, "atlasq/shell"
|
13
15
|
autoload :Util, "atlasq/util"
|
14
16
|
|