├── .gitignore ├── README.md ├── github ├── README.md ├── analytics.pig ├── database.py └── osrcd ├── mail ├── README.md ├── counts.pig ├── elasticsearch.pig ├── email.avro.schema ├── encode.py ├── gmail │ ├── __init__.py │ ├── email_utils.py │ ├── gmail.py │ └── gmail_slurper.py └── utils.py ├── nginx ├── README.md ├── __init__.py ├── analytics.py ├── jython-load.pig ├── load.pig ├── load.sh ├── requirements.txt ├── screenshot.jpg ├── screenshot_nginx_map.jpg └── utils.py └── view ├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .yo-rc.json ├── Gruntfile.js ├── bower.json ├── country-codes.csv ├── country.json ├── img └── icon.png ├── index.html ├── package.json ├── scripts ├── latlng.js ├── main_ammap.js ├── main_ol.js └── ol.js ├── styles ├── main.css └── ol.css └── test ├── .bowerrc ├── bower.json ├── index.html └── spec └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.pyc 3 | data/access.log 4 | analytics.log 5 | *.log 6 | data 7 | log 8 | node_modules 9 | */test/ 10 | */data/ 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Learning Big Data 2 | 3 | ##nginx 4 | 5 | > Analytics Nginx log with pig, and show traffic country on map. 6 | 7 | ![Nginx Screenshot](./nginx/screenshot.jpg) 8 | 9 | ###Tech 10 | 11 | - Apache Pig 12 | - Python Geo Parse 13 | - Jython 14 | - ElasticSearch 15 | 16 | ##mail 17 | 18 | > Analytics & count mail. 19 | 20 | 21 | ##Github 22 | 23 | > TBD -------------------------------------------------------------------------------- /github/README.md: -------------------------------------------------------------------------------- 1 | ## 2 | 3 | - Elephant-bird -------------------------------------------------------------------------------- /github/analytics.pig: -------------------------------------------------------------------------------- 1 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/piggybank.jar; 2 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/elasticsearch-hadoop-pig-2.1.0.Beta3.jar; 3 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/elephant-bird-core-4.6.jar; 4 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/elephant-bird-hadoop-compat-4.6.jar; 5 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/elephant-bird-pig-4.6.jar; 6 | 7 | LOGS = LOAD 'data/2015-01-01-0.json' USING com.twitter.elephantbird.pig.load.JsonLoader() AS (json:map[]); 8 | 9 | B = FOREACH LOGS GENERATE json#'created_at' AS created_at, json#'actor' AS actor, json#'repo' AS repo, json#'payload' AS payload; 10 | 11 | STORE B INTO 'github/log' USING org.elasticsearch.hadoop.pig.EsStorage(); 12 | 13 | -------------------------------------------------------------------------------- /github/database.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import (division, print_function, absolute_import, 5 | unicode_literals) 6 | 7 | __all__ = ["get_pipeline", "format_key"] 8 | 9 | import redis 10 | 11 | 12 | def get_pipeline(): 13 | pool = redis.ConnectionPool(host='localhost', port=6379, db=5) 14 | r = redis.Redis(connection_pool=pool) 15 | return r.pipeline() 16 | 17 | 18 | def format_key(key): 19 | return "{0}:{1}".format("osrc", key) 20 | -------------------------------------------------------------------------------- /github/osrcd: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | from __future__ import (division, print_function, absolute_import, 5 | unicode_literals) 6 | 7 | __all__ = ["fetch"] 8 | 9 | import gevent 10 | from gevent import monkey 11 | monkey.patch_all() 12 | 13 | import re 14 | import os 15 | import glob 16 | import gzip 17 | import json 18 | import time 19 | import shutil 20 | import logging 21 | import requests 22 | from datetime import date, timedelta 23 | from tempfile import NamedTemporaryFile 24 | 25 | # from osrc.index import rebuild_index 26 | from database import get_pipeline 27 | from database import format_key as _format 28 | 29 | # The default time-to-live for every key (approx 6 months). 30 | DEFAULT_TTL = 6 * 30 * 24 * 60 * 60 31 | 32 | # Make sure that the directory for the local caching of the data exists. 33 | local_data_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 34 | "data") 35 | local_data_dir = os.environ.get("OSRC_DATA_DIR", local_data_dir) 36 | fn_template = os.path.join(local_data_dir, 37 | "{year}-{month:02d}-{day:02d}-{n}.json.gz") 38 | try: 39 | os.makedirs(local_data_dir) 40 | except os.error: 41 | pass 42 | 43 | # The URL template for the GitHub Archive. 44 | archive_url = ("http://data.githubarchive.org/" 45 | "{year}-{month:02d}-{day:02d}-{n}.json.gz") 46 | 47 | # Regular expression for parsing filename formats. 48 | date_re = re.compile(r"([0-9]{4})-([0-9]{2})-([0-9]{2})-([0-9]+)\.json.gz") 49 | 50 | 51 | def _redis_execute(pipe, cmd, key, *args, **kwargs): 52 | key = _format(key) 53 | r = getattr(pipe, cmd)(key, *args, **kwargs) 54 | pipe.expire(key, DEFAULT_TTL) 55 | return r 56 | 57 | 58 | def _fetch_one(year, month, day, n): 59 | kwargs = {"year": year, "month": month, "day": day, "n": n} 60 | local_fn = fn_template.format(**kwargs) 61 | 62 | # Skip if the file exists. 63 | if os.path.exists(local_fn): 64 | return 65 | 66 | # Download the remote file. 67 | remote = archive_url.format(**kwargs) 68 | r = requests.get(remote) 69 | if r.status_code == requests.codes.ok: 70 | # Atomically write to disk. 71 | # http://stackoverflow.com/questions/2333872/ \ 72 | # atomic-writing-to-file-with-python 73 | f = NamedTemporaryFile("wb", delete=False) 74 | f.write(r.content) 75 | f.flush() 76 | os.fsync(f.fileno()) 77 | f.close() 78 | shutil.move(f.name, local_fn) 79 | 80 | 81 | def fetch(year, month, day): 82 | """ 83 | Asynchronously download all the event archives for one day of activity 84 | from the GitHub Archive. 85 | 86 | :param year: The 4-digit year of the date. 87 | :param month: The integer id of the target month ``[1, 12]``. 88 | :param day: The integer id of the target day ``[1, 31]``. 89 | 90 | """ 91 | jobs = [gevent.spawn(_fetch_one, year, month, day, n) for n in range(24)] 92 | gevent.joinall(jobs) 93 | 94 | 95 | def process(filename): 96 | """ 97 | Process a single gzipped archive file and push the results to the database. 98 | 99 | :param filename: The absolute path to the archive file. 100 | 101 | """ 102 | # Figure out the day of the week from the filename (this is probably not 103 | # always right but it'll do). 104 | year, month, day, hour = map(int, date_re.findall(filename)[0]) 105 | weekday = date(year=year, month=month, day=day).strftime("%w") 106 | 107 | # Set up a redis pipeline. 108 | pipe = get_pipeline() 109 | 110 | # Unzip and load the file. 111 | strt = time.time() 112 | count = 0 113 | with gzip.GzipFile(filename) as f: 114 | # One event per line. 115 | events = [line.decode("utf-8", errors="ignore") for line in f] 116 | count = len(events) 117 | 118 | # One event per line. 119 | for n, line in enumerate(events): 120 | # Parse the JSON of this event. 121 | try: 122 | event = json.loads(line) 123 | except: 124 | logging.warn("Failed on line {0} of {1}-{2:02d}-{3:02d}-{4}" 125 | .format(n, year, month, day, hour)) 126 | continue 127 | 128 | # Get the user involved and skip if there isn't one. 129 | actor = event["actor"] 130 | 131 | attrs = event.get("actor_attributes", {}) 132 | # if actor is None or attrs.get("type") != "User": 133 | # continue 134 | 135 | # Normalize the user name. 136 | key = actor["login"].lower() 137 | 138 | # Get the type of event. 139 | evttype = event["type"] 140 | nevents = 1 141 | 142 | # Can this be called a "contribution"? 143 | contribution = evttype in ["IssuesEvent", "PullRequestEvent", 144 | "PushEvent"] 145 | 146 | # Increment the global sum histograms. 147 | _redis_execute(pipe, "incr", "total", nevents) 148 | _redis_execute(pipe, "hincrby", "day", weekday, nevents) 149 | _redis_execute(pipe, "hincrby", "hour", hour, nevents) 150 | _redis_execute(pipe, "zincrby", "user", key, nevents) 151 | _redis_execute(pipe, "zincrby", "event", evttype, nevents) 152 | 153 | # Event histograms. 154 | _redis_execute(pipe, "hincrby", "event:{0}:day".format(evttype), 155 | weekday, nevents) 156 | _redis_execute(pipe, "hincrby", "event:{0}:hour".format(evttype), 157 | hour, nevents) 158 | 159 | # User schedule histograms. 160 | _redis_execute(pipe, "hincrby", "user:{0}:day".format(key), 161 | weekday, nevents) 162 | _redis_execute(pipe, "hincrby", "user:{0}:hour".format(key), 163 | hour, nevents) 164 | 165 | # User event type histogram. 166 | _redis_execute(pipe, "zincrby", "user:{0}:event".format(key), 167 | evttype, nevents) 168 | _redis_execute(pipe, "hincrby", "user:{0}:event:{1}:day" 169 | .format(key, evttype), weekday, nevents) 170 | _redis_execute(pipe, "hincrby", "user:{0}:event:{1}:hour" 171 | .format(key, evttype), hour, nevents) 172 | 173 | # Parse the name and owner of the affected repository. 174 | repo = event.get("repository", {}) 175 | owner, name = repo.get("owner"), repo.get("name") 176 | if owner and name: 177 | repo_name = "{0}/{1}".format(owner, name) 178 | _redis_execute(pipe, "zincrby", "repo", repo_name, nevents) 179 | 180 | # Save the social graph. 181 | _redis_execute(pipe, "zincrby", "social:user:{0}".format(key), 182 | repo_name, nevents) 183 | _redis_execute(pipe, "zincrby", "social:repo:{0}" 184 | .format(repo_name), key, nevents) 185 | 186 | # Do we know what the language of the repository is? 187 | language = repo.get("language") 188 | if language: 189 | # Which are the most popular languages? 190 | _redis_execute(pipe, "zincrby", "lang", language, nevents) 191 | 192 | # Total number of pushes. 193 | if evttype == "PushEvent": 194 | _redis_execute(pipe, "zincrby", "pushes:lang", 195 | language, nevents) 196 | 197 | _redis_execute(pipe, "zincrby", "user:{0}:lang" 198 | .format(key), language, nevents) 199 | 200 | # Who are the most important users of a language? 201 | if contribution: 202 | _redis_execute(pipe, "zincrby", "lang:{0}:user" 203 | .format(language), key, nevents) 204 | 205 | pipe.execute() 206 | 207 | logging.info("Processed {0} events in {1} [{2:.2f} seconds]" 208 | .format(count, filename, time.time() - strt)) 209 | 210 | 211 | def fetch_and_process(year, month, day): 212 | logging.info("Processing data for {0:04d}-{1:02d}-{2:02d}" 213 | .format(year, month, day)) 214 | fetch(year, month, day) 215 | kwargs = {"year": year, "month": month, "day": day, "n": "*"} 216 | filenames = glob.glob(fn_template.format(**kwargs)) 217 | if len(filenames) != 24: 218 | logging.warn("Missing {0} archive files for date " 219 | "{1:04d}-{2:02d}-{3:02d}" 220 | .format(24 - len(filenames), year, month, day)) 221 | map(process, filenames) 222 | 223 | 224 | if __name__ == "__main__": 225 | import argparse 226 | 227 | vday = "2015-01-26" 228 | today = date(**dict(zip(["year", "month", "day"], map(int, vday.split("-"))))) 229 | 230 | # Parse the command line arguments. 231 | parser = argparse.ArgumentParser(description="Monitor GitHub activity.") 232 | parser.add_argument("--since", default=None, help="The starting date.") 233 | parser.add_argument("--config", default=None, 234 | help="The path to the local configuration file.") 235 | parser.add_argument("--log", default=None, 236 | help="The path to the log file.") 237 | args = parser.parse_args() 238 | 239 | largs = dict(level=logging.INFO, 240 | format="[%(asctime)s] %(name)s:%(levelname)s:%(message)s") 241 | if args.log is not None: 242 | largs["filename"] = args.log 243 | logging.basicConfig(**largs) 244 | 245 | # Initialize a flask app. 246 | 247 | # Set up the app in a request context. 248 | if args.since is not None: 249 | day = date(**dict(zip(["year", "month", "day"], 250 | map(int, args.since.split("-"))))) 251 | while day < today: 252 | fetch_and_process(day.year, day.month, day.day) 253 | day += timedelta(1) 254 | 255 | else: 256 | yesterday = today - timedelta(1) 257 | fetch_and_process(yesterday.year, yesterday.month, yesterday.day) 258 | 259 | logging.info("Rebuilding index.") 260 | # rebuild_index() 261 | logging.info("Finished.") 262 | -------------------------------------------------------------------------------- /mail/README.md: -------------------------------------------------------------------------------- 1 | ### Download your gmail inbox 2 | 3 | cd gmail 4 | ./gmail.py -m automatic -u me@gmail.com -p 'my_password_' -s ./email.avro.schema -f '[Gmail]/All Mail' -o /tmp/my_inbox_directory 2>&1 & 5 | 6 | Run 7 | 8 | pig elasticsearch.pig 9 | -------------------------------------------------------------------------------- /mail/counts.pig: -------------------------------------------------------------------------------- 1 | /* Set Home Directory - where we install software */ 2 | 3 | /* Avro uses json-simple, and is in piggybank until Pig 0.12, where AvroStorage and TrevniStorage are builtins */ 4 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/piggybank.jar; 5 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/avro-1.7.5.jar; 6 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/json-simple-1.1.jar; 7 | register file:/usr/local/Cellar/elasticsearch/1.4.4/libexec/*.jar; 8 | 9 | messages = load 'data/part-1.avro' using AvroStorage(); 10 | 11 | messages = FILTER messages BY (from IS NOT NULL) AND (tos IS NOT NULL); 12 | 13 | addresses = FOREACH messages GENERATE from.address AS from, FLATTEN(tos.(address)) AS to; 14 | 15 | lowers = FOREACH addresses GENERATE LOWER(from) AS from, LOWER(to) AS to; 16 | 17 | by_from_to = GROUP lowers BY (from, to); 18 | 19 | sent_counts = FOREACH by_from_to GENERATE FLATTEN(group) AS (from, to), COUNT_STAR(lowers) AS total; 20 | 21 | sent_counts = ORDER sent_counts BY total DESC; 22 | 23 | STORE sent_counts INTO 'test'; -------------------------------------------------------------------------------- /mail/elasticsearch.pig: -------------------------------------------------------------------------------- 1 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/piggybank.jar; 2 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/avro-1.7.5.jar; 3 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/json-simple-1.1.jar; 4 | register file:/usr/local/Cellar/elasticsearch/1.4.4/libexec/*.jar; 5 | register utils.py using jython as utils; 6 | 7 | messages = load 'data/part-1.avro' using AvroStorage(); 8 | 9 | messages = FILTER messages BY (from IS NOT NULL) AND (tos IS NOT NULL) AND (subject IS NOT NULL); 10 | 11 | info = FOREACH messages GENERATE from.address AS from, FLATTEN(tos.(address)) AS to, subject, date; 12 | 13 | STORE info INTO 'inbox/sendcounts' USING org.elasticsearch.hadoop.pig.EsStorage(); -------------------------------------------------------------------------------- /mail/email.avro.schema: -------------------------------------------------------------------------------- 1 | { 2 | "type":"record", 3 | "name":"Email", 4 | "fields":[ 5 | { 6 | "name":"message_id", 7 | "type":[ 8 | "null", 9 | "string" 10 | ], 11 | "doc":"" 12 | }, 13 | { 14 | "name":"thread_id", 15 | "type":[ 16 | "null", 17 | "string" 18 | ], 19 | "doc":"" 20 | }, 21 | { 22 | "name":"in_reply_to", 23 | "type":[ 24 | "string", 25 | "null" 26 | ] 27 | }, 28 | { 29 | "name":"subject", 30 | "type":[ 31 | "string", 32 | "null" 33 | ] 34 | }, 35 | { 36 | "name":"body", 37 | "type":[ 38 | "string", 39 | "null" 40 | ] 41 | }, 42 | { 43 | "name":"date", 44 | "type":[ 45 | "string", 46 | "null" 47 | ] 48 | }, 49 | { 50 | "name":"from", 51 | "type": 52 | { 53 | "type":"record", 54 | "name":"from", 55 | "fields":[ 56 | { 57 | "name":"real_name", 58 | "type":[ 59 | "null", 60 | "string" 61 | ], 62 | "doc":"" 63 | }, 64 | { 65 | "name":"address", 66 | "type":[ 67 | "null", 68 | "string" 69 | ], 70 | "doc":"" 71 | } 72 | ] 73 | } 74 | }, 75 | { 76 | "name":"tos", 77 | "type":[ 78 | "null", 79 | { 80 | "type":"array", 81 | "items":[ 82 | "null", 83 | { 84 | "type":"record", 85 | "name":"to", 86 | "fields":[ 87 | { 88 | "name":"real_name", 89 | "type":[ 90 | "null", 91 | "string" 92 | ], 93 | "doc":"" 94 | }, 95 | { 96 | "name":"address", 97 | "type":[ 98 | "null", 99 | "string" 100 | ], 101 | "doc":"" 102 | } 103 | ] 104 | } 105 | ] 106 | } 107 | ], 108 | "doc":"" 109 | }, 110 | { 111 | "name":"ccs", 112 | "type":[ 113 | "null", 114 | { 115 | "type":"array", 116 | "items":[ 117 | "null", 118 | { 119 | "type":"record", 120 | "name":"cc", 121 | "fields":[ 122 | { 123 | "name":"real_name", 124 | "type":[ 125 | "null", 126 | "string" 127 | ], 128 | "doc":"" 129 | }, 130 | { 131 | "name":"address", 132 | "type":[ 133 | "null", 134 | "string" 135 | ], 136 | "doc":"" 137 | } 138 | ] 139 | } 140 | ] 141 | } 142 | ], 143 | "doc":"" 144 | }, 145 | { 146 | "name":"bccs", 147 | "type":[ 148 | "null", 149 | { 150 | "type":"array", 151 | "items":[ 152 | "null", 153 | { 154 | "type":"record", 155 | "name":"bcc", 156 | "fields":[ 157 | { 158 | "name":"real_name", 159 | "type":[ 160 | "null", 161 | "string" 162 | ], 163 | "doc":"" 164 | }, 165 | { 166 | "name":"address", 167 | "type":[ 168 | "null", 169 | "string" 170 | ], 171 | "doc":"" 172 | } 173 | ] 174 | } 175 | ] 176 | } 177 | ], 178 | "doc":"" 179 | }, 180 | { 181 | "name":"reply_tos", 182 | "type":[ 183 | "null", 184 | { 185 | "type":"array", 186 | "items":[ 187 | "null", 188 | { 189 | "type":"record", 190 | "name":"reply_to", 191 | "fields":[ 192 | { 193 | "name":"real_name", 194 | "type":[ 195 | "null", 196 | "string" 197 | ], 198 | "doc":"" 199 | }, 200 | { 201 | "name":"address", 202 | "type":[ 203 | "null", 204 | "string" 205 | ], 206 | "doc":"" 207 | } 208 | ] 209 | } 210 | ] 211 | } 212 | ], 213 | "doc":"" 214 | } 215 | ] 216 | } 217 | -------------------------------------------------------------------------------- /mail/encode.py: -------------------------------------------------------------------------------- 1 | import base64 2 | 3 | #My buggy SSH account needs this to write unicode output, you hopefully won't 4 | import sys 5 | import codecs 6 | sys.stdout = codecs.getwriter('utf-8')(sys.stdout) 7 | 8 | 9 | encoded = '=?UTF-8?B?UmU6IFNjYWxlV29ya3MgRGV2T3Bz5Lqn5ZOB5pa55qGINC4yMue9keS4iuaOqOS7i+S8mg==?=' 10 | prefix = '=?UTF-8?B?' 11 | suffix = '?=' 12 | 13 | #extract the data part of the string 14 | middle = encoded[len(prefix):len(encoded)-len(suffix)] 15 | print "Middle: %s" % middle 16 | 17 | #decode the bytes 18 | decoded = base64.b64decode(middle) 19 | #decode the utf-8 20 | decoded = unicode(decoded, 'utf8') 21 | 22 | print decoded -------------------------------------------------------------------------------- /mail/gmail/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'fdhuang' 2 | -------------------------------------------------------------------------------- /mail/gmail/email_utils.py: -------------------------------------------------------------------------------- 1 | #!/opt/local/bin/python 2 | 3 | import imaplib 4 | import sys, signal 5 | from avro import schema, datafile, io 6 | import os, re 7 | import email 8 | import inspect, pprint 9 | import getopt 10 | import time 11 | from lepl.apps.rfc3696 import Email 12 | 13 | class EmailUtils(object): 14 | 15 | def __init__(self): 16 | """This class contains utilities for parsing and extracting structure from raw UTF-8 encoded emails""" 17 | self.is_email = Email() 18 | 19 | def strip_brackets(self, message_id): 20 | return str(message_id).strip('<>') 21 | 22 | def parse_date(self, date_string): 23 | tuple_time = email.utils.parsedate(date_string) 24 | iso_time = time.strftime("%Y-%m-%dT%H:%M:%S", tuple_time) 25 | return iso_time 26 | 27 | def get_charset(self, raw_email): 28 | if(type(raw_email)) is str: 29 | raw_email = email.message_from_string(raw_email) 30 | else: 31 | raw_email = raw_email 32 | charset = None 33 | for c in raw_email.get_charsets(): 34 | if c != None: 35 | charset = c 36 | break 37 | return charset 38 | 39 | # '1011 (X-GM-THRID 1292412648635976421 RFC822 {6499}' --> 1292412648635976421 40 | def get_thread_id(self, thread_string): 41 | p = re.compile('\d+ \(X-GM-THRID (.+) RFC822.*') 42 | m = p.match(thread_string) 43 | return m.group(1) 44 | 45 | def parse_addrs(self, addr_string): 46 | if(addr_string): 47 | addresses = email.utils.getaddresses([addr_string]) 48 | validated = [] 49 | for address in addresses: 50 | address_pair = {'real_name': None, 'address': None} 51 | if address[0]: 52 | address_pair['real_name'] = address[0] 53 | if self.is_email(address[1]): 54 | address_pair['address'] = address[1] 55 | if not address[0] and not self.is_email(address[1]): 56 | pass 57 | else: 58 | validated.append(address_pair) 59 | if(len(validated) == 0): 60 | validated = None 61 | return validated 62 | 63 | def process_email(self, raw_email, thread_id): 64 | msg = email.message_from_string(raw_email) 65 | subject = msg['Subject'] 66 | body = self.get_body(msg) 67 | 68 | # Without handling charsets, corrupt avros will get written 69 | charsets = msg.get_charsets() 70 | charset = None 71 | for c in charsets: 72 | if c != None: 73 | charset = c 74 | break 75 | print charset 76 | try: 77 | if charset: 78 | subject = subject.decode(charset) 79 | body = body.decode(charset) 80 | else: 81 | return {}, charset 82 | except: 83 | return {}, charset 84 | try: 85 | from_value = self.parse_addrs(msg['From'])[0] 86 | except: 87 | return {}, charset 88 | avro_parts = dict({ 89 | 'message_id': self.strip_brackets(msg['Message-ID']), 90 | 'thread_id': thread_id, 91 | 'in_reply_to': self.strip_brackets(msg['In-Reply-To']), 92 | 'subject': subject, 93 | 'date': self.parse_date(msg['Date']), 94 | 'body': body, 95 | 'from': from_value, 96 | 'tos': self.parse_addrs(msg['To']), 97 | 'ccs': self.parse_addrs(msg['Cc']), 98 | 'bccs': self.parse_addrs(msg['Bcc']), 99 | 'reply_tos': self.parse_addrs(msg['Reply-To']) 100 | }) 101 | return avro_parts, charset 102 | 103 | def get_body(self, msg): 104 | body = '' 105 | if msg: 106 | for part in msg.walk(): 107 | if part.get_content_type() == 'text/plain': 108 | body += part.get_payload() 109 | return body 110 | -------------------------------------------------------------------------------- /mail/gmail/gmail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This is a command line utility for slurping emails from gmail and storing them as avro documents. 4 | # I uses the GmailSlurper class, which in turn uses email utils. 5 | 6 | import os, sys, getopt 7 | from lepl.apps.rfc3696 import Email 8 | 9 | from gmail_slurper import GmailSlurper 10 | 11 | def usage(context): 12 | print """Usage: gmail.py -m -u -p -s -f -o """ 13 | 14 | def does_exist(path_string, name): 15 | if(os.path.exists(path_string)): 16 | pass 17 | else: 18 | print "Error: " + name + ": " + path_string + " does not exist." 19 | sys.exit(2) 20 | 21 | def main(): 22 | try: 23 | opts, args = getopt.getopt(sys.argv[1:], 'm:u:p:s:f:o:i:') 24 | except getopt.GetoptError, err: 25 | # print help information and exit: 26 | print "Error:" + str(err) # will print something like "option -a not recognized" 27 | usage("getopt") 28 | sys.exit(2) 29 | 30 | mode = None 31 | username = None 32 | password = None 33 | schema_path = None #'../avro/email.schema' 34 | imap_folder = None #'[Gmail]/All Mail' 35 | output_path = None 36 | single_id = None 37 | arg_check = dict() 38 | 39 | for o, a in opts: 40 | if o == "-m": 41 | mode = a 42 | if mode in ('automatic', 'interactive'): 43 | pass 44 | else: 45 | usage('opts') 46 | sys.exit(2) 47 | arg_check[o] = 1 48 | elif o in ("-u"): 49 | username = a 50 | arg_check[o] = 1 51 | elif o in ("-p"): 52 | password = a 53 | arg_check[o] = 1 54 | elif o in ("-s"): 55 | schema_path = a 56 | does_exist(schema_path, "filename") 57 | arg_check[o] = 1 58 | elif o in ("-f"): 59 | imap_folder = a 60 | arg_check[o] = 1 61 | elif o in ("-o"): 62 | output_path = a 63 | arg_check[o] = 1 64 | elif o in ("-i"): 65 | single_id = a 66 | arg_check[o] = a 67 | else: 68 | assert False, "unhandled option" 69 | 70 | if(len(arg_check.keys()) >= 6): 71 | pass 72 | else: 73 | usage('numargs') 74 | sys.exit(2) 75 | 76 | if(len(arg_check.keys()) == len(sys.argv[1:])/2): 77 | pass 78 | else: 79 | usage('badargs') 80 | sys.exit(2) 81 | 82 | slurper = GmailSlurper() 83 | slurper.init_avro(output_path, 1, schema_path) 84 | slurper.init_imap(username, password) 85 | status, count = slurper.init_folder(imap_folder) 86 | if(status == 'OK'): 87 | if(mode == 'automatic'): 88 | # Grab a single message if its ID is specified - useful for debug 89 | if(single_id): 90 | s, a, c = slurper.fetch_email(single_id) 91 | if(s == 'OK'): 92 | print s, c, a 93 | else: 94 | print "Problem fetching email ID: " + single_id + " - " + s 95 | # Otherwise grab them all 96 | else: 97 | print "Connected to folder " + imap_folder + " and downloading " + str(count) + " emails...\n" 98 | slurper.slurp() 99 | slurper.shutdown() 100 | else: 101 | print "Problem initializing imap connection." 102 | 103 | if __name__ == "__main__": 104 | main() 105 | -------------------------------------------------------------------------------- /mail/gmail/gmail_slurper.py: -------------------------------------------------------------------------------- 1 | #!/opt/local/bin/python 2 | 3 | import imaplib 4 | import sys, signal 5 | from avro import schema, datafile, io 6 | import os, re 7 | import email 8 | import inspect, pprint 9 | import time 10 | 11 | from email_utils import EmailUtils 12 | 13 | class GmailSlurper(object): 14 | 15 | def __init__(self): 16 | self.utils = EmailUtils() 17 | """This class downloads all emails in folders from your Gmail inbox and writes them as raw UTF-8 text in simple Avro records for further processing.""" 18 | 19 | def init_directory(self, directory): 20 | if os.path.exists(directory): 21 | print 'Warning: %(directory)s already exists:' % {"directory":directory} 22 | else: 23 | os.makedirs(directory) 24 | return directory 25 | 26 | def init_imap(self, username, password): 27 | self.username = username 28 | self.password = password 29 | try: 30 | imap.shutdown() 31 | except: 32 | pass 33 | try: 34 | self.imap = imaplib.IMAP4_SSL('imap.gmail.com', 993) 35 | self.imap.login(username, password) 36 | self.imap.is_readonly = True 37 | except: 38 | pass 39 | 40 | # part_id will be helpful one we're splitting files among multiple slurpers 41 | def init_avro(self, output_path, part_id, schema_path): 42 | output_dir = None 43 | output_dirtmp = None # Handle Avro Write Error 44 | if(type(output_path) is str): 45 | output_dir = self.init_directory(output_path) 46 | output_dirtmp = self.init_directory(output_path + 'tmp') # Handle Avro Write Error 47 | out_filename = '%(output_dir)s/part-%(part_id)s.avro' % \ 48 | {"output_dir": output_dir, "part_id": str(part_id)} 49 | out_filenametmp = '%(output_dirtmp)s/part-%(part_id)s.avro' % \ 50 | {"output_dirtmp": output_dirtmp, "part_id": str(part_id)} # Handle Avro Write Error 51 | self.schema = open(schema_path, 'r').read() 52 | email_schema = schema.parse(self.schema) 53 | rec_writer = io.DatumWriter(email_schema) 54 | self.avro_writer = datafile.DataFileWriter( 55 | open(out_filename, 'wb'), 56 | rec_writer, 57 | email_schema 58 | ) 59 | # CREATE A TEMP AvroWriter that can be used to workaround the UnicodeDecodeError when writing into AvroStorage 60 | self.avro_writertmp = datafile.DataFileWriter( 61 | open(out_filenametmp, 'wb'), 62 | rec_writer, 63 | email_schema 64 | ) 65 | 66 | def init_folder(self, folder): 67 | self.imap_folder = folder 68 | status, count = self.imap.select(folder) 69 | print "Folder '" + str(folder) + "' SELECT status: " + status 70 | if(status == 'OK'): 71 | count = int(count[0]) 72 | ids = range(1,count) 73 | ids.reverse() 74 | self.id_list = ids 75 | print "Folder '" + str(folder) + " has " + str(count) + "' emails...\n" 76 | self.folder_count = count 77 | return status, count 78 | 79 | def fetch_email(self, email_id): 80 | def timeout_handler(signum, frame): 81 | raise self.TimeoutException() 82 | 83 | signal.signal(signal.SIGALRM, timeout_handler) 84 | signal.alarm(30) # triger alarm in 30 seconds 85 | 86 | avro_record = dict() 87 | status = 'FAIL' 88 | try: 89 | status, data = self.imap.fetch(str(email_id), '(X-GM-THRID RFC822)') # Gmail's X-GM-THRID will get the thread of the message 90 | except self.TimeoutException: 91 | return 'TIMEOUT', {}, None 92 | except: 93 | return 'ABORT', {}, None 94 | 95 | charset = None 96 | if status != 'OK': 97 | return 'ERROR', {}, None 98 | else: 99 | raw_thread_id = data[0][0] 100 | encoded_email = data[0][1] 101 | 102 | try: 103 | charset = self.utils.get_charset(encoded_email) 104 | 105 | # RFC2822 says default charset is us-ascii, which often saves us when no charset is specified 106 | if(charset): 107 | pass 108 | else: 109 | charset = 'us-ascii' 110 | 111 | if(charset): # redundant, but saves our ass if we edit above 112 | #raw_email = encoded_email.decode(charset) 113 | thread_id = self.utils.get_thread_id(raw_thread_id) 114 | print "CHARSET: " + charset 115 | avro_record, charset = self.utils.process_email(encoded_email, thread_id) 116 | else: 117 | return 'UNICODE', {}, charset 118 | except UnicodeDecodeError: 119 | return 'UNICODE', {}, charset 120 | except: 121 | return 'ERROR', {}, None 122 | 123 | # Without a charset we pass bad chars to avro, and it dies. See AVRO-565. 124 | if charset: 125 | return status, avro_record, charset 126 | else: 127 | return 'CHARSET', {}, charset 128 | 129 | def shutdown(self): 130 | self.avro_writer.close() 131 | self.avro_writertmp.close() # Handle Avro write errors 132 | self.imap.close() 133 | self.imap.logout() 134 | 135 | def write(self, record): 136 | #self.avro_writer.append(record) 137 | # BEGIN - Handle errors when writing into Avro storage 138 | try: 139 | self.avro_writertmp.append(record) 140 | self.avro_writer.append(record) 141 | 142 | except UnicodeDecodeError: 143 | sys.stderr.write("ERROR IN Writing EMAIL to Avro for UnicodeDecode issue, SKIPPED ONE\n") 144 | pass 145 | 146 | except: 147 | pass 148 | # END - Handle errors when writing into Avro storage 149 | 150 | def flush(self): 151 | self.avro_writer.flush() 152 | self.avro_writertmp.flush() # Handle Avro write errors 153 | print "Flushed avro writer..." 154 | 155 | def slurp(self): 156 | if(self.imap and self.imap_folder): 157 | for email_id in self.id_list: 158 | (status, email_hash, charset) = self.fetch_email(email_id) 159 | if(status == 'OK' and charset and 'thread_id' in email_hash and 'from' in email_hash): 160 | print email_id, charset, email_hash['thread_id'] 161 | self.write(email_hash) 162 | if((int(email_id) % 1000) == 0): 163 | self.flush() 164 | elif(status == 'ERROR' or status == 'PARSE' or status == 'UNICODE' or status == 'CHARSET' or status =='FROM'): 165 | sys.stderr.write("Problem fetching email id " + str(email_id) + ": " + status + "\n") 166 | continue 167 | elif (status == 'ABORT' or status == 'TIMEOUT'): 168 | sys.stderr.write("resetting imap for " + status + "\n") 169 | stat, c = self.reset() 170 | sys.stderr.write("IMAP RESET: " + str(stat) + " " + str(c) + "\n") 171 | else: 172 | sys.stderr.write("ERROR IN PARSING EMAIL, SKIPPED ONE\n") 173 | continue 174 | 175 | def reset(self): 176 | self.init_imap(self.username, self.password) 177 | try: 178 | status, count = self.init_folder(self.imap_folder) 179 | except: 180 | self.reset() 181 | status = 'ERROR' 182 | count = 0 183 | return status, count 184 | 185 | class TimeoutException(Exception): 186 | """Indicates an operation timed out.""" 187 | sys.stderr.write("Timeout exception occurred!\n") 188 | pass 189 | -------------------------------------------------------------------------------- /mail/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | 5 | sys.path.append('/Users/fdhuang/py27/lib/python2.7/site-packages/') 6 | import base64 7 | import codecs 8 | 9 | sys.stdout = codecs.getwriter('utf-8')(sys.stdout) 10 | prefix = '=?UTF-8?B?' 11 | suffix = '?=' 12 | 13 | 14 | @outputSchema('subject:chararray') 15 | def encode_subject(subject): 16 | try: 17 | 18 | if prefix in subject and subject: 19 | middle = subject[len(prefix):len(subject) - len(suffix)] 20 | decoded = base64.b64decode(middle) 21 | subject = unicode(decoded, 'utf8') 22 | 23 | return subject 24 | except: 25 | pass -------------------------------------------------------------------------------- /nginx/README.md: -------------------------------------------------------------------------------- 1 | #Play Nginx with ES,Hadoop,Pig 2 | 3 | ##Setup 4 | 5 | 1.Install Python Deps 6 | 7 | pip install -r requirements.txt 8 | 9 | 2.Hadoop & ElasticSearch 10 | 11 | brew install hadoop 12 | brew install pig 13 | brew install elasticsearch 14 | 15 | 3.Install pig 16 | 17 | brew install pig 18 | 19 | 4.Install pig-elasticsearch 20 | 21 | 1. get jar from [https://github.com/elastic/elasticsearch-hadoop](https://github.com/elastic/elasticsearch-hadoop) 22 | 2. cp elasticsearch-hadoop-pig. for example to `` /usr/local/Cellar/pig/0.14.0/libexec/lib/`` 23 | 24 | 5.Run 25 | 26 | pig -x local load.pig 27 | 28 | ##ScreenShot 29 | ![Nginx Map with Ammap](screenshot.jpg) 30 | ![Nginx Map with ES Hadoop](screenshot_nginx_map.jpg) 31 | 32 | -------------------------------------------------------------------------------- /nginx/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'fdhuang' 2 | -------------------------------------------------------------------------------- /nginx/analytics.py: -------------------------------------------------------------------------------- 1 | from pyelasticsearch import ElasticSearch 2 | 3 | es = ElasticSearch('http://localhost:9200/') 4 | 5 | query = { 6 | 'query': { 7 | 'filtered': { 8 | 'filter': { 9 | 'range': { 10 | 'date': { 11 | 'gte': '2015-01-01', 12 | 'lte': 'now', 13 | 'time_zone': '+8:00' 14 | } 15 | } 16 | } 17 | }, 18 | }, 19 | } 20 | 21 | print es.search(query, index='nginx')["hits"]["total"] -------------------------------------------------------------------------------- /nginx/jython-load.pig: -------------------------------------------------------------------------------- 1 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/piggybank.jar; 2 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/elasticsearch-hadoop-pig-2.1.0.Beta3.jar; 3 | register utils.py using jython as utils; 4 | 5 | RAW_LOGS = LOAD 'data/access.log' USING TextLoader as (line:chararray); 6 | 7 | LOGS_BASE = FOREACH RAW_LOGS GENERATE 8 | FLATTEN( 9 | REGEX_EXTRACT_ALL(line, '(\\S+) - - \\[([^\\[]+)\\]\\s+"([^"]+)"\\s+(\\d+)\\s+(\\d+)\\s+"([^"]+)"\\s+"([^"]+)"\\s+-') 10 | ) 11 | AS ( 12 | ip: chararray, 13 | timestamp: chararray, 14 | url: chararray, 15 | status: chararray, 16 | bytes: chararray, 17 | referrer: chararray, 18 | useragent: chararray 19 | ); 20 | 21 | A = FOREACH LOGS_BASE GENERATE ToDate(timestamp, 'dd/MMM/yyyy:HH:mm:ss Z') as date, utils.get_country(ip) as country, 22 | utils.get_city(ip) as city, utils.get_geo(ip) as location,ip, 23 | utils.query(url) as url,(int)status,(int)bytes,referrer,useragent; 24 | 25 | STORE A INTO 'nginx/log' USING org.elasticsearch.hadoop.pig.EsStorage(); 26 | -------------------------------------------------------------------------------- /nginx/load.pig: -------------------------------------------------------------------------------- 1 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/piggybank.jar; 2 | register file:/usr/local/Cellar/pig/0.14.0/libexec/lib/elasticsearch-hadoop-pig-2.1.0.Beta3.jar; 3 | 4 | RAW_LOGS = LOAD 'data/access.log' USING TextLoader as (line:chararray); 5 | 6 | LOGS_BASE = FOREACH RAW_LOGS GENERATE 7 | FLATTEN( 8 | REGEX_EXTRACT_ALL(line, '(\\S+) - - \\[([^\\[]+)\\]\\s+"([^"]+)"\\s+(\\d+)\\s+(\\d+)\\s+"([^"]+)"\\s+"([^"]+)"\\s+-') 9 | ) 10 | AS ( 11 | ip: chararray, 12 | timestamp: chararray, 13 | url: chararray, 14 | status: chararray, 15 | bytes: chararray, 16 | referrer: chararray, 17 | useragent: chararray 18 | ); 19 | 20 | A = FOREACH LOGS_BASE GENERATE ToDate(timestamp, 'dd/MMM/yyyy:HH:mm:ss Z') as date, ip, url,(int)status,(int)bytes,referrer,useragent; 21 | --B = GROUP A BY (timestamp); 22 | --C = FOREACH B GENERATE FLATTEN(group) as (timestamp), COUNT(A) as count; 23 | --D = ORDER C BY timestamp,count desc; 24 | STORE A INTO 'nginx/log' USING org.elasticsearch.hadoop.pig.EsStorage(); 25 | -------------------------------------------------------------------------------- /nginx/load.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pig -x local load.pig 3 | -------------------------------------------------------------------------------- /nginx/requirements.txt: -------------------------------------------------------------------------------- 1 | pyelasticsearch 2 | GeoIP 3 | python-geoip 4 | python-geoip-geolite2 5 | -------------------------------------------------------------------------------- /nginx/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/learning-data/8459273f92c3bb9225ff79f1b36f7c23001db380/nginx/screenshot.jpg -------------------------------------------------------------------------------- /nginx/screenshot_nginx_map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/learning-data/8459273f92c3bb9225ff79f1b36f7c23001db380/nginx/screenshot_nginx_map.jpg -------------------------------------------------------------------------------- /nginx/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | sys.path.append('/Users/fdhuang/test/lib/python2.7/site-packages/') 5 | import pygeoip 6 | gi = pygeoip.GeoIP("data/GeoLiteCity.dat") 7 | 8 | @outputSchema('everything:chararray') 9 | def query(url): 10 | try: 11 | return url 12 | except: 13 | pass 14 | 15 | @outputSchema('city:chararray') 16 | def get_city(ip): 17 | try: 18 | city = gi.record_by_name(ip)["city"] 19 | return city 20 | except: 21 | pass 22 | 23 | 24 | @outputSchema('country:chararray') 25 | def get_country(ip): 26 | try: 27 | city = gi.record_by_name(ip)["country_name"] 28 | return city 29 | except: 30 | pass 31 | 32 | @outputSchema('location:chararray') 33 | def get_geo(ip): 34 | try: 35 | geo = str(gi.record_by_name(ip)["longitude"]) + "," + str(gi.record_by_name(ip)["latitude"]) 36 | return geo 37 | except: 38 | pass -------------------------------------------------------------------------------- /view/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /view/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /view/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /view/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | bower_components 5 | -------------------------------------------------------------------------------- /view/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "jquery": true 21 | } 22 | -------------------------------------------------------------------------------- /view/.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-mocha": {} 3 | } -------------------------------------------------------------------------------- /view/Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2015-04-28 using 2 | // generator-webapp 0.5.1 3 | 'use strict'; 4 | 5 | // # Globbing 6 | // for performance reasons we're only matching one level down: 7 | // 'test/spec/{,*/}*.js' 8 | // If you want to recursively match all subfolders, use: 9 | // 'test/spec/**/*.js' 10 | 11 | module.exports = function (grunt) { 12 | 13 | // Time how long tasks take. Can help when optimizing build times 14 | require('time-grunt')(grunt); 15 | 16 | // Load grunt tasks automatically 17 | require('load-grunt-tasks')(grunt); 18 | 19 | // Configurable paths 20 | var config = { 21 | app: 'app', 22 | dist: 'dist' 23 | }; 24 | 25 | // Define the configuration for all the tasks 26 | grunt.initConfig({ 27 | 28 | // Project settings 29 | config: config, 30 | 31 | // Watches files for changes and runs tasks based on the changed files 32 | watch: { 33 | bower: { 34 | files: ['bower.json'], 35 | tasks: ['wiredep'] 36 | }, 37 | js: { 38 | files: ['<%= config.app %>/scripts/{,*/}*.js'], 39 | tasks: ['jshint'], 40 | options: { 41 | livereload: true 42 | } 43 | }, 44 | jstest: { 45 | files: ['test/spec/{,*/}*.js'], 46 | tasks: ['test:watch'] 47 | }, 48 | gruntfile: { 49 | files: ['Gruntfile.js'] 50 | }, 51 | styles: { 52 | files: ['<%= config.app %>/styles/{,*/}*.css'], 53 | tasks: ['newer:copy:styles', 'autoprefixer'] 54 | }, 55 | livereload: { 56 | options: { 57 | livereload: '<%= connect.options.livereload %>' 58 | }, 59 | files: [ 60 | '<%= config.app %>/{,*/}*.html', 61 | '.tmp/styles/{,*/}*.css', 62 | '<%= config.app %>/images/{,*/}*' 63 | ] 64 | } 65 | }, 66 | 67 | // The actual grunt server settings 68 | connect: { 69 | options: { 70 | port: 9000, 71 | open: true, 72 | livereload: 35729, 73 | // Change this to '0.0.0.0' to access the server from outside 74 | hostname: 'localhost' 75 | }, 76 | livereload: { 77 | options: { 78 | middleware: function(connect) { 79 | return [ 80 | connect.static('.tmp'), 81 | connect().use('/bower_components', connect.static('./bower_components')), 82 | connect.static(config.app) 83 | ]; 84 | } 85 | } 86 | }, 87 | test: { 88 | options: { 89 | open: false, 90 | port: 9001, 91 | middleware: function(connect) { 92 | return [ 93 | connect.static('.tmp'), 94 | connect.static('test'), 95 | connect().use('/bower_components', connect.static('./bower_components')), 96 | connect.static(config.app) 97 | ]; 98 | } 99 | } 100 | }, 101 | dist: { 102 | options: { 103 | base: '<%= config.dist %>', 104 | livereload: false 105 | } 106 | } 107 | }, 108 | 109 | // Empties folders to start fresh 110 | clean: { 111 | dist: { 112 | files: [{ 113 | dot: true, 114 | src: [ 115 | '.tmp', 116 | '<%= config.dist %>/*', 117 | '!<%= config.dist %>/.git*' 118 | ] 119 | }] 120 | }, 121 | server: '.tmp' 122 | }, 123 | 124 | // Make sure code styles are up to par and there are no obvious mistakes 125 | jshint: { 126 | options: { 127 | jshintrc: '.jshintrc', 128 | reporter: require('jshint-stylish') 129 | }, 130 | all: [ 131 | 'Gruntfile.js', 132 | '<%= config.app %>/scripts/{,*/}*.js', 133 | '!<%= config.app %>/scripts/vendor/*', 134 | 'test/spec/{,*/}*.js' 135 | ] 136 | }, 137 | 138 | // Mocha testing framework configuration options 139 | mocha: { 140 | all: { 141 | options: { 142 | run: true, 143 | urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html'] 144 | } 145 | } 146 | }, 147 | 148 | // Add vendor prefixed styles 149 | autoprefixer: { 150 | options: { 151 | browsers: ['> 1%', 'last 2 versions', 'Firefox ESR', 'Opera 12.1'] 152 | }, 153 | dist: { 154 | files: [{ 155 | expand: true, 156 | cwd: '.tmp/styles/', 157 | src: '{,*/}*.css', 158 | dest: '.tmp/styles/' 159 | }] 160 | } 161 | }, 162 | 163 | // Automatically inject Bower components into the HTML file 164 | wiredep: { 165 | app: { 166 | ignorePath: /^\/|\.\.\//, 167 | src: ['<%= config.app %>/index.html'], 168 | exclude: ['bower_components/bootstrap/dist/js/bootstrap.js'] 169 | } 170 | }, 171 | 172 | // Renames files for browser caching purposes 173 | rev: { 174 | dist: { 175 | files: { 176 | src: [ 177 | '<%= config.dist %>/scripts/{,*/}*.js', 178 | '<%= config.dist %>/styles/{,*/}*.css', 179 | '<%= config.dist %>/images/{,*/}*.*', 180 | '<%= config.dist %>/styles/fonts/{,*/}*.*', 181 | '<%= config.dist %>/*.{ico,png}' 182 | ] 183 | } 184 | } 185 | }, 186 | 187 | // Reads HTML for usemin blocks to enable smart builds that automatically 188 | // concat, minify and revision files. Creates configurations in memory so 189 | // additional tasks can operate on them 190 | useminPrepare: { 191 | options: { 192 | dest: '<%= config.dist %>' 193 | }, 194 | html: '<%= config.app %>/index.html' 195 | }, 196 | 197 | // Performs rewrites based on rev and the useminPrepare configuration 198 | usemin: { 199 | options: { 200 | assetsDirs: [ 201 | '<%= config.dist %>', 202 | '<%= config.dist %>/images', 203 | '<%= config.dist %>/styles' 204 | ] 205 | }, 206 | html: ['<%= config.dist %>/{,*/}*.html'], 207 | css: ['<%= config.dist %>/styles/{,*/}*.css'] 208 | }, 209 | 210 | // The following *-min tasks produce minified files in the dist folder 211 | imagemin: { 212 | dist: { 213 | files: [{ 214 | expand: true, 215 | cwd: '<%= config.app %>/images', 216 | src: '{,*/}*.{gif,jpeg,jpg,png}', 217 | dest: '<%= config.dist %>/images' 218 | }] 219 | } 220 | }, 221 | 222 | svgmin: { 223 | dist: { 224 | files: [{ 225 | expand: true, 226 | cwd: '<%= config.app %>/images', 227 | src: '{,*/}*.svg', 228 | dest: '<%= config.dist %>/images' 229 | }] 230 | } 231 | }, 232 | 233 | htmlmin: { 234 | dist: { 235 | options: { 236 | collapseBooleanAttributes: true, 237 | collapseWhitespace: true, 238 | conservativeCollapse: true, 239 | removeAttributeQuotes: true, 240 | removeCommentsFromCDATA: true, 241 | removeEmptyAttributes: true, 242 | removeOptionalTags: true, 243 | removeRedundantAttributes: true, 244 | useShortDoctype: true 245 | }, 246 | files: [{ 247 | expand: true, 248 | cwd: '<%= config.dist %>', 249 | src: '{,*/}*.html', 250 | dest: '<%= config.dist %>' 251 | }] 252 | } 253 | }, 254 | 255 | // By default, your `index.html`'s will take care 256 | // of minification. These next options are pre-configured if you do not 257 | // wish to use the Usemin blocks. 258 | // cssmin: { 259 | // dist: { 260 | // files: { 261 | // '<%= config.dist %>/styles/main.css': [ 262 | // '.tmp/styles/{,*/}*.css', 263 | // '<%= config.app %>/styles/{,*/}*.css' 264 | // ] 265 | // } 266 | // } 267 | // }, 268 | // uglify: { 269 | // dist: { 270 | // files: { 271 | // '<%= config.dist %>/scripts/scripts.js': [ 272 | // '<%= config.dist %>/scripts/scripts.js' 273 | // ] 274 | // } 275 | // } 276 | // }, 277 | // concat: { 278 | // dist: {} 279 | // }, 280 | 281 | // Copies remaining files to places other tasks can use 282 | copy: { 283 | dist: { 284 | files: [{ 285 | expand: true, 286 | dot: true, 287 | cwd: '<%= config.app %>', 288 | dest: '<%= config.dist %>', 289 | src: [ 290 | '*.{ico,png,txt}', 291 | 'images/{,*/}*.webp', 292 | '{,*/}*.html', 293 | 'styles/fonts/{,*/}*.*' 294 | ] 295 | }, { 296 | src: 'node_modules/apache-server-configs/dist/.htaccess', 297 | dest: '<%= config.dist %>/.htaccess' 298 | }, { 299 | expand: true, 300 | dot: true, 301 | cwd: 'bower_components/bootstrap/dist', 302 | src: 'fonts/*', 303 | dest: '<%= config.dist %>' 304 | }] 305 | }, 306 | styles: { 307 | expand: true, 308 | dot: true, 309 | cwd: '<%= config.app %>/styles', 310 | dest: '.tmp/styles/', 311 | src: '{,*/}*.css' 312 | } 313 | }, 314 | 315 | // Run some tasks in parallel to speed up build process 316 | concurrent: { 317 | server: [ 318 | 'copy:styles' 319 | ], 320 | test: [ 321 | 'copy:styles' 322 | ], 323 | dist: [ 324 | 'copy:styles', 325 | 'imagemin', 326 | 'svgmin' 327 | ] 328 | } 329 | }); 330 | 331 | 332 | grunt.registerTask('serve', 'start the server and preview your app, --allow-remote for remote access', function (target) { 333 | if (grunt.option('allow-remote')) { 334 | grunt.config.set('connect.options.hostname', '0.0.0.0'); 335 | } 336 | if (target === 'dist') { 337 | return grunt.task.run(['build', 'connect:dist:keepalive']); 338 | } 339 | 340 | grunt.task.run([ 341 | 'clean:server', 342 | 'wiredep', 343 | 'concurrent:server', 344 | 'autoprefixer', 345 | 'connect:livereload', 346 | 'watch' 347 | ]); 348 | }); 349 | 350 | grunt.registerTask('server', function (target) { 351 | grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); 352 | grunt.task.run([target ? ('serve:' + target) : 'serve']); 353 | }); 354 | 355 | grunt.registerTask('test', function (target) { 356 | if (target !== 'watch') { 357 | grunt.task.run([ 358 | 'clean:server', 359 | 'concurrent:test', 360 | 'autoprefixer' 361 | ]); 362 | } 363 | 364 | grunt.task.run([ 365 | 'connect:test', 366 | 'mocha' 367 | ]); 368 | }); 369 | 370 | grunt.registerTask('build', [ 371 | 'clean:dist', 372 | 'wiredep', 373 | 'useminPrepare', 374 | 'concurrent:dist', 375 | 'autoprefixer', 376 | 'concat', 377 | 'cssmin', 378 | 'uglify', 379 | 'copy:dist', 380 | 'rev', 381 | 'usemin', 382 | 'htmlmin' 383 | ]); 384 | 385 | grunt.registerTask('default', [ 386 | 'newer:jshint', 387 | 'test', 388 | 'build' 389 | ]); 390 | }; 391 | -------------------------------------------------------------------------------- /view/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view", 3 | "private": true, 4 | "dependencies": { 5 | "bootstrap": "~3.2.0", 6 | "elasticsearch": "~4.0.2", 7 | "d3": "~3.5.5", 8 | "papaparse": "~4.1.1", 9 | "ammap": "~3.10.0" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /view/country-codes.csv: -------------------------------------------------------------------------------- 1 | name,name_fr,ISO3166-1-Alpha-2,ISO3166-1-Alpha-3,ISO3166-1-numeric,ITU,MARC,WMO,DS,Dial,FIFA,FIPS,GAUL,IOC,currency_alphabetic_code,currency_country_name,currency_minor_unit,currency_name,currency_numeric_code,is_independent 2 | Afghanistan,Afghanistan,AF,AFG,004,AFG,af,AF,AFG,93,AFG,AF,1,AFG,AFN,AFGHANISTAN,2,Afghani,971,Yes 3 | Albania,Albanie,AL,ALB,008,ALB,aa,AB,AL,355,ALB,AL,3,ALB,ALL,ALBANIA,2,Lek,008,Yes 4 | Algeria,Algérie,DZ,DZA,012,ALG,ae,AL,DZ,213,ALG,AG,4,ALG,DZD,ALGERIA,2,Algerian Dinar,012,Yes 5 | American Samoa,Samoa Américaines,AS,ASM,016,SMA,as, ,USA,1-684,ASA,AQ,5,ASA,USD,AMERICAN SAMOA,2,US Dollar,840,Territory of US 6 | Andorra,Andorre,AD,AND,020,AND,an, ,AND,376,AND,AN,7,AND,EUR,ANDORRA,2,Euro,978,Yes 7 | Angola,Angola,AO,AGO,024,AGL,ao,AN, ,244,ANG,AO,8,ANG,AOA,ANGOLA,2,Kwanza,973,Yes 8 | Anguilla,Anguilla,AI,AIA,660,AIA,am, , ,1-264,AIA,AV,9,AIA,XCD,ANGUILLA,2,East Caribbean Dollar,951,Territory of GB 9 | Antarctica,Antarctique,AQ,ATA,010, ,ay,AA, ,672,ROS,AY,10, ,,ANTARCTICA,,No universal currency,,International 10 | Antigua and Barbuda,Antigua-Et-Barbuda,AG,ATG,028,ATG,aq,AT, ,1-268,ATG,AC,11,ANT,XCD,ANTIGUA AND BARBUDA,2,East Caribbean Dollar,951,Yes 11 | Argentina,Argentine,AR,ARG,032,ARG,ag,AG,RA,54,ARG,AR,12,ARG,ARS,ARGENTINA,2,Argentine Peso,032,Yes 12 | Armenia,Arménie,AM,ARM,051,ARM,ai,AY,AM,374,ARM,AM,13,ARM,AMD,ARMENIA,2,Armenian Dram,051,Yes 13 | Aruba,Aruba,AW,ABW,533,ABW,aw,NU, ,297,ARU,AA,14,ARU,AWG,ARUBA,2,Aruban Florin,533,Part of NL 14 | Australia,Australie,AU,AUS,036,AUS,at,AU,AUS,61,AUS,AS,17,AUS,AUD,AUSTRALIA,2,Australian Dollar,036,Yes 15 | Austria,Autriche,AT,AUT,040,AUT,au,OS,A,43,AUT,AU,18,AUT,EUR,AUSTRIA,2,Euro,978,Yes 16 | Azerbaijan,Azerbaïdjan,AZ,AZE,031,AZE,aj,AJ,AZ,994,AZE,AJ,19,AZE,AZN,AZERBAIJAN,2,Azerbaijanian Manat,944,Yes 17 | Bahamas,Bahamas,BS,BHS,044,BAH,bf,BA,BS,1-242,BAH,BF,20,BAH,BSD,BAHAMAS,2,Bahamian Dollar,044,Yes 18 | Bahrain,Bahreïn,BH,BHR,048,BHR,ba,BN,BRN,973,BHR,BA,21,BRN,BHD,BAHRAIN,3,Bahraini Dinar,048,Yes 19 | Bangladesh,Bangladesh,BD,BGD,050,BGD,bg,BW,BD,880,BAN,BG,23,BAN,BDT,BANGLADESH,2,Taka,050,Yes 20 | Barbados,Barbade,BB,BRB,052,BRB,bb,BR,BDS,1-246,BRB,BB,24,BAR,BBD,BARBADOS,2,Barbados Dollar,052,Yes 21 | Belarus,Bélarus,BY,BLR,112,BLR,bw,BY,BY,375,BLR,BO,26,BLR,BYR,BELARUS,0,Belarussian Ruble,974,Yes 22 | Belgium,Belgique,BE,BEL,056,BEL,be,BX,B,32,BEL,BE,27,BEL,EUR,BELGIUM,2,Euro,978,Yes 23 | Belize,Belize,BZ,BLZ,084,BLZ,bh,BH,BZ,501,BLZ,BH,28,BIZ,BZD,BELIZE,2,Belize Dollar,084,Yes 24 | Benin,Bénin,BJ,BEN,204,BEN,dm,BJ,DY,229,BEN,BN,29,BEN,XOF,BENIN,0,CFA Franc BCEAO,952,Yes 25 | Bermuda,Bermudes,BM,BMU,060,BER,bm,BE, ,1-441,BER,BD,30,BER,BMD,BERMUDA,2,Bermudian Dollar,060,Territory of GB 26 | Bhutan,Bhoutan,BT,BTN,064,BTN,bt, , ,975,BHU,BT,31,BHU,INR,BHUTAN,2,Indian Rupee,356,Yes 27 | "Bolivia, Plurinational State of","Bolivie, l'État Plurinational de",BO,BOL,068,BOL,bo,BO,BOL,591,BOL,BL,33,BOL,BOB,"BOLIVIA, PLURINATIONAL STATE OF",2,Boliviano,068,Yes 28 | "Bonaire, Sint Eustatius and Saba","Bonaire, Saint-Eustache et Saba",BQ,BES,535,ATN,ca,NU,NA,599,ANT,NL,176,AHO,USD,"BONAIRE, SINT EUSTATIUS AND SABA",2,US Dollar,840,Part of NL 29 | Bosnia and Herzegovina,Bosnie-Herzégovine,BA,BIH,070,BIH,bn,BG,BIH,387,BIH,BK,34,BIH,BAM,BOSNIA AND HERZEGOVINA,2,Convertible Mark,977,Yes 30 | Botswana,Botswana,BW,BWA,072,BOT,bs,BC,BW,267,BOT,BC,35,BOT,BWP,BOTSWANA,2,Pula,072,Yes 31 | Bouvet Island,"Bouvet, Île",BV,BVT,074, ,bv,BV, ,47,,BV,36, ,NOK,BOUVET ISLAND,2,Norwegian Krone,578,Territory of NO 32 | Brazil,Brésil,BR,BRA,076,B,bl,BZ,BR,55,BRA,BR,37,BRA,BRL,BRAZIL,2,Brazilian Real,986,Yes 33 | British Indian Ocean Territory,"Océan Indien, Territoire Britannique de l'",IO,IOT,086,BIO,bi, , ,246,,IO,38, ,USD,BRITISH INDIAN OCEAN TERRITORY,2,US Dollar,840,Territory of GB 34 | Brunei Darussalam,Brunei Darussalam,BN,BRN,096,BRU,bx,BD,BRU,673,BRU,BX,40,BRU,BND,BRUNEI DARUSSALAM,2,Brunei Dollar,096,Yes 35 | Bulgaria,Bulgarie,BG,BGR,100,BUL,bu,BU,BG,359,BUL,BU,41,BUL,BGN,BULGARIA,2,Bulgarian Lev,975,Yes 36 | Burkina Faso,Burkina Faso,BF,BFA,854,BFA,uv,HV,BF,226,BFA,UV,42,BUR,XOF,BURKINA FASO,0,CFA Franc BCEAO,952,Yes 37 | Burundi,Burundi,BI,BDI,108,BDI,bd,BI,RU,257,BDI,BY,43,BDI,BIF,BURUNDI,0,Burundi Franc,108,Yes 38 | Cambodia,Cambodge,KH,KHM,116,CBG,cb,KP,K,855,CAM,CB,44,CAM,KHR,CAMBODIA,2,Riel,116,Yes 39 | Cameroon,Cameroun,CM,CMR,120,CME,cm,CM,CAM,237,CMR,CM,45,CMR,XAF,CAMEROON,0,CFA Franc BEAC,950,Yes 40 | Canada,Canada,CA,CAN,124,CAN,xxc,CN,CDN,1,CAN,CA,46,CAN,CAD,CANADA,2,Canadian Dollar,124,Yes 41 | Cape Verde,Cap-Vert,CV,CPV,132,CPV,cv,CV, ,238,CPV,CV,47,CPV,CVE,CABO VERDE,2,Cabo Verde Escudo,132,Yes 42 | Cayman Islands,"Caïmans, Îles",KY,CYM,136,CYM,cj,GC, ,1-345,CAY,CJ,48,CAY,KYD,CAYMAN ISLANDS,2,Cayman Islands Dollar,136,Territory of GB 43 | Central African Republic,"Centrafricaine, République",CF,CAF,140,CAF,cx,CE,RCA,236,CTA,CT,49,CAF,XAF,CENTRAL AFRICAN REPUBLIC,0,CFA Franc BEAC,950,Yes 44 | Chad,Tchad,TD,TCD,148,TCD,cd,CD,TCH,235,CHA,CD,50,CHA,XAF,CHAD,0,CFA Franc BEAC,950,Yes 45 | Chile,Chili,CL,CHL,152,CHL,cl,CH,RCH,56,CHI,CI,51,CHI,CLP,CHILE,0,Chilean Peso,152,Yes 46 | China,Chine,CN,CHN,156,CHN,cc,CI, ,86,CHN,CH,53,CHN,CNY,CHINA,2,Yuan Renminbi,156,Yes 47 | Christmas Island,"Christmas, Île",CX,CXR,162,CHR,xa,KI,AUS,61,CXR,KT,54, ,AUD,CHRISTMAS ISLAND,2,Australian Dollar,036,Territory of AU 48 | Cocos (Keeling) Islands,"Cocos (Keeling), Îles",CC,CCK,166,ICO,xb,KK,AUS,61,CCK,CK,56, ,AUD,COCOS (KEELING) ISLANDS,2,Australian Dollar,036,Territory of AU 49 | Colombia,Colombie,CO,COL,170,CLM,ck,CO,CO,57,COL,CO,57,COL,COP,COLOMBIA,2,Colombian Peso,170,Yes 50 | Comoros,Comores,KM,COM,174,COM,cq,IC, ,269,COM,CN,58,COM,KMF,COMOROS,0,Comoro Franc,174,Yes 51 | Congo,Congo,CG,COG,178,COG,cf,CG,RCB,242,CGO,CF,59,CGO,XAF,CONGO,0,CFA Franc BEAC,950,Yes 52 | "Congo, the Democratic Republic of the","Congo, la République Démocratique du",CD,COD,180,COD,cg,ZR,ZRE,243,COD,CG,68,COD,,,,,,Yes 53 | Cook Islands,"Cook, Îles",CK,COK,184,CKH,cw,KU,NZ,682,COK,CW,60,COK,NZD,COOK ISLANDS,2,New Zealand Dollar,554,Associated with NZ 54 | Costa Rica,Costa Rica,CR,CRI,188,CTR,cr,CS,CR,506,CRC,CS,61,CRC,CRC,COSTA RICA,2,Costa Rican Colon,188,Yes 55 | Croatia,Croatie,HR,HRV,191,HRV,ci,RH,HR,385,CRO,HR,62,CRO,HRK,CROATIA,2,Croatian Kuna,191,Yes 56 | Cuba,Cuba,CU,CUB,192,CUB,cu,CU,C,53,CUB,CU,63,CUB,CUP,CUBA,2,Cuban Peso,192,Yes 57 | Curaçao,Curaçao,CW,CUW,531,,co,,,599,,UC,,,ANG,CURAÇAO,2,Netherlands Antillean Guilder,532,Part of NL 58 | Cyprus,Chypre,CY,CYP,196,CYP,cy,CY,CY,357,CYP,CY,64,CYP,EUR,CYPRUS,2,Euro,978,Yes 59 | Czech Republic,"Tchèque, République",CZ,CZE,203,CZE,xr,CZ,CZ,420,CZE,EZ,65,CZE,CZK,CZECH REPUBLIC,2,Czech Koruna,203,Yes 60 | Côte d'Ivoire,Côte d'Ivoire,CI,CIV,384,CTI,iv,IV,CI,225,CIV,IV,66,CIV,XOF,CÔTE D'IVOIRE,0,CFA Franc BCEAO,952,Yes 61 | Denmark,Danemark,DK,DNK,208,DNK,dk,DN,DK,45,DEN,DA,69,DEN,DKK,DENMARK,2,Danish Krone,208,Yes 62 | Djibouti,Djibouti,DJ,DJI,262,DJI,ft,DJ, ,253,DJI,DJ,70,DJI,DJF,DJIBOUTI,0,Djibouti Franc,262,Yes 63 | Dominica,Dominique,DM,DMA,212,DMA,dq,DO,WD,1-767,DMA,DO,71,DMA,XCD,DOMINICA,2,East Caribbean Dollar,951,Yes 64 | Dominican Republic,"Dominicaine, République",DO,DOM,214,DOM,dr,DR,DOM,"1-809,1-829,1-849",DOM,DR,72,DOM,DOP,DOMINICAN REPUBLIC,2,Dominican Peso,214,Yes 65 | Ecuador,Équateur,EC,ECU,218,EQA,ec,EQ,EC,593,ECU,EC,73,ECU,USD,ECUADOR,2,US Dollar,840,Yes 66 | Egypt,Égypte,EG,EGY,818,EGY,ua,EG,ET,20,EGY,EG,40765,EGY,EGP,EGYPT,2,Egyptian Pound,818,Yes 67 | El Salvador,El Salvador,SV,SLV,222,SLV,es,ES,ES,503,SLV,ES,75,ESA,USD,EL SALVADOR,2,US Dollar,840,Yes 68 | Equatorial Guinea,Guinée Équatoriale,GQ,GNQ,226,GNE,eg,GQ, ,240,EQG,EK,76,GEQ,XAF,EQUATORIAL GUINEA,0,CFA Franc BEAC,950,Yes 69 | Eritrea,Érythrée,ER,ERI,232,ERI,ea, , ,291,ERI,ER,77,ERI,ERN,ERITREA,2,Nakfa,232,Yes 70 | Estonia,Estonie,EE,EST,233,EST,er,EO,EST,372,EST,EN,78,EST,EUR,ESTONIA,2,Euro,978,Yes 71 | Ethiopia,Éthiopie,ET,ETH,231,ETH,et,ET,ETH,251,ETH,ET,79,ETH,ETB,ETHIOPIA,2,Ethiopian Birr,230,Yes 72 | Falkland Islands (Malvinas),"Falkland, Îles (Malvinas)",FK,FLK,238,FLK,fk,FK, ,500,FLK,FK,81,FLK,FKP,FALKLAND ISLANDS (MALVINAS),2,Falkland Islands Pound,238,Territory of GB 73 | Faroe Islands,"Féroé, Îles",FO,FRO,234,FRO,fa,FA,FO,298,FRO,FO,82,FAR,DKK,FAROE ISLANDS,2,Danish Krone,208,Part of DK 74 | Fiji,Fidji,FJ,FJI,242,FJI,fj,FJ,FJI,679,FIJ,FJ,83,FIJ,FJD,FIJI,2,Fiji Dollar,242,Yes 75 | Finland,Finlande,FI,FIN,246,FIN,fi,FI,FIN,358,FIN,FI,84,FIN,EUR,FINLAND,2,Euro,978,Yes 76 | France,France,FR,FRA,250,F,fr,FR,F,33,FRA,FR,85,FRA,EUR,FRANCE,2,Euro,978,Yes 77 | French Guiana,Guyane Française,GF,GUF,254,GUF,fg,FG,F,594,GUF,FG,86,FGU,EUR,FRENCH GUIANA,2,Euro,978,Part of FR 78 | French Polynesia,Polynésie Française,PF,PYF,258,OCE,fp,PF,F,689,TAH,FP,87,FPO,XPF,FRENCH POLYNESIA,0,CFP Franc,953,Territory of FR 79 | French Southern Territories,Terres Australes Françaises,TF,ATF,260, ,fs, ,F,262,,FS,88, ,EUR,FRENCH SOUTHERN TERRITORIES,2,Euro,978,Territory of FR 80 | Gabon,Gabon,GA,GAB,266,GAB,go,GO,G,241,GAB,GB,89,GAB,XAF,GABON,0,CFA Franc BEAC,950,Yes 81 | Gambia,Gambie,GM,GMB,270,GMB,gm,GB,WAG,220,GAM,GA,90,GAM,GMD,GAMBIA,2,Dalasi,270,Yes 82 | Georgia,Géorgie,GE,GEO,268,GEO,gs,GG,GE,995,GEO,GG,92,GEO,GEL,GEORGIA,2,Lari,981,Yes 83 | Germany,Allemagne,DE,DEU,276,D,gw,DL,D,49,GER,GM,93,GER,EUR,GERMANY,2,Euro,978,Yes 84 | Ghana,Ghana,GH,GHA,288,GHA,gh,GH,GH,233,GHA,GH,94,GHA,GHS,GHANA,2,Ghana Cedi,936,Yes 85 | Gibraltar,Gibraltar,GI,GIB,292,GIB,gi,GI,GBZ,350,GBZ,GI,95,GIB,GIP,GIBRALTAR,2,Gibraltar Pound,292,Territory of GB 86 | Greece,Grèce,GR,GRC,300,GRC,gr,GR,GR,30,GRE,GR,97,GRE,EUR,GREECE,2,Euro,978,Yes 87 | Greenland,Groenland,GL,GRL,304,GRL,gl,GL,DK,299,GRL,GL,98,GRL,DKK,GREENLAND,2,Danish Krone,208,Part of DK 88 | Grenada,Grenade,GD,GRD,308,GRD,gd,GD,WG,1-473,GRN,GJ,99,GRN,XCD,GRENADA,2,East Caribbean Dollar,951,Yes 89 | Guadeloupe,Guadeloupe,GP,GLP,312,GDL,gp,MF,F,590,GLP,GP,100,GUD,EUR,GUADELOUPE,2,Euro,978,Part of FR 90 | Guam,Guam,GU,GUM,316,GUM,gu,GM,USA,1-671,GUM,GQ,101,GUM,USD,GUAM,2,US Dollar,840,Territory of US 91 | Guatemala,Guatemala,GT,GTM,320,GTM,gt,GU,GCA,502,GUA,GT,103,GUA,GTQ,GUATEMALA,2,Quetzal,320,Yes 92 | Guernsey,Guernesey,GG,GGY,831, ,uik, ,GBG,44,GBG,GK,104, ,GBP,GUERNSEY,2,Pound Sterling,826,Crown dependency of GB 93 | Guinea,Guinée,GN,GIN,324,GUI,gv,GN,RG,224,GUI,GV,106,GUI,GNF,GUINEA,0,Guinea Franc,324,Yes 94 | Guinea-Bissau,Guinée-Bissau,GW,GNB,624,GNB,pg,GW, ,245,GNB,PU,105,GBS,XOF,GUINEA-BISSAU,0,CFA Franc BCEAO,952,Yes 95 | Guyana,Guyana,GY,GUY,328,GUY,gy,GY,GUY,592,GUY,GY,107,GUY,GYD,GUYANA,2,Guyana Dollar,328,Yes 96 | Haiti,Haïti,HT,HTI,332,HTI,ht,HA,RH,509,HAI,HA,108,HAI,USD,HAITI,2,US Dollar,840,Yes 97 | Heard Island and McDonald Mcdonald Islands,"Heard-Et-Îles Macdonald, Île",HM,HMD,334, ,hm, ,AUS,672,,HM,109, ,AUD,HEARD ISLAND AND McDONALD ISLANDS,2,Australian Dollar,036,Territory of AU 98 | Holy See (Vatican City State),Saint-Siège (État de la Cité du Vatican),VA,VAT,336,CVA,vc, ,V,39-06,VAT,VT,110, ,EUR,HOLY SEE (VATICAN CITY STATE),2,Euro,978,Yes 99 | Honduras,Honduras,HN,HND,340,HND,ho,HO, ,504,HON,HO,111,HON,HNL,HONDURAS,2,Lempira,340,Yes 100 | Hong Kong,Hong Kong,HK,HKG,344,HKG, ,HK,HK,852,HKG,HK,33364,HKG,HKD,HONG KONG,2,Hong Kong Dollar,344,Part of CN 101 | Hungary,Hongrie,HU,HUN,348,HNG,hu,HU,H,36,HUN,HU,113,HUN,HUF,HUNGARY,2,Forint,348,Yes 102 | Iceland,Islande,IS,ISL,352,ISL,ic,IL,IS,354,ISL,IC,114,ISL,ISK,ICELAND,0,Iceland Krona,352,Yes 103 | India,Inde,IN,IND,356,IND,ii,IN,IND,91,IND,IN,115,IND,INR,INDIA,2,Indian Rupee,356,Yes 104 | Indonesia,Indonésie,ID,IDN,360,INS,io,ID,RI,62,IDN,ID,116,INA,IDR,INDONESIA,2,Rupiah,360,Yes 105 | "Iran, Islamic Republic of","Iran, République Islamique d'",IR,IRN,364,IRN,ir,IR,IR,98,IRN,IR,117,IRI,IRR,"IRAN, ISLAMIC REPUBLIC OF",2,Iranian Rial,364,Yes 106 | Iraq,Iraq,IQ,IRQ,368,IRQ,iq,IQ,IRQ,964,IRQ,IZ,118,IRQ,IQD,IRAQ,3,Iraqi Dinar,368,Yes 107 | Ireland,Irlande,IE,IRL,372,IRL,ie,IE,IRL,353,IRL,EI,119,IRL,EUR,IRELAND,2,Euro,978,Yes 108 | Isle of Man,Île de Man,IM,IMN,833, ,uik, ,GBM,44,GBM,IM,120, ,GBP,ISLE OF MAN,2,Pound Sterling,826,Crown dependency of GB 109 | Israel,Israël,IL,ISR,376,ISR,is,IS,IL,972,ISR,IS,121,ISR,ILS,ISRAEL,2,New Israeli Sheqel,376,Yes 110 | Italy,Italie,IT,ITA,380,I,it,IY,I,39,ITA,IT,122,ITA,EUR,ITALY,2,Euro,978,Yes 111 | Jamaica,Jamaïque,JM,JAM,388,JMC,jm,JM,JA,1-876,JAM,JM,123,JAM,JMD,JAMAICA,2,Jamaican Dollar,388,Yes 112 | Japan,Japon,JP,JPN,392,J,ja,JP,J,81,JPN,JA,126,JPN,JPY,JAPAN,0,Yen,392,Yes 113 | Jersey,Jersey,JE,JEY,832, ,uik, ,GBJ,44,GBJ,JE,128, ,GBP,JERSEY,2,Pound Sterling,826,Crown dependency of GB 114 | Jordan,Jordanie,JO,JOR,400,JOR,jo,JD,HKJ,962,JOR,JO,130,JOR,JOD,JORDAN,3,Jordanian Dinar,400,Yes 115 | Kazakhstan,Kazakhstan,KZ,KAZ,398,KAZ,kz,KZ,KZ,7,KAZ,KZ,132,KAZ,KZT,KAZAKHSTAN,2,Tenge,398,Yes 116 | Kenya,Kenya,KE,KEN,404,KEN,ke,KN,EAK,254,KEN,KE,133,KEN,KES,KENYA,2,Kenyan Shilling,404,Yes 117 | Kiribati,Kiribati,KI,KIR,296,KIR,gb,KB, ,686,KIR,KR,135,KIR,AUD,KIRIBATI,2,Australian Dollar,036,Yes 118 | "Korea, Democratic People's Republic of","Corée, République Populaire Démocratique de",KP,PRK,408,KRE,kn,KR, ,850,PRK,KN,67,PRK,KPW,"KOREA, DEMOCRATIC PEOPLE’S REPUBLIC OF",2,North Korean Won,408,Yes 119 | "Korea, Republic of","Corée, République de",KR,KOR,410,KOR,ko,KO,ROK,82,KOR,KS,202,KOR,KRW,"KOREA, REPUBLIC OF",0,Won,410,Yes 120 | Kuwait,Koweït,KW,KWT,414,KWT,ku,KW,KWT,965,KUW,KU,137,KUW,KWD,KUWAIT,3,Kuwaiti Dinar,414,Yes 121 | Kyrgyzstan,Kirghizistan,KG,KGZ,417,KGZ,kg,KG,KS,996,KGZ,KG,138,KGZ,KGS,KYRGYZSTAN,2,Som,417,Yes 122 | Lao People's Democratic Republic,"Lao, République Démocratique Populaire",LA,LAO,418,LAO,ls,LA,LAO,856,LAO,LA,139,LAO,LAK,LAO PEOPLE’S DEMOCRATIC REPUBLIC,2,Kip,418,Yes 123 | Latvia,Lettonie,LV,LVA,428,LVA,lv,LV,LV,371,LVA,LG,140,LAT,EUR,LATVIA,2,Euro,978,Yes 124 | Lebanon,Liban,LB,LBN,422,LBN,le,LB,RL,961,LIB,LE,141,LIB,LBP,LEBANON,2,Lebanese Pound,422,Yes 125 | Lesotho,Lesotho,LS,LSO,426,LSO,lo,LS,LS,266,LES,LT,142,LES,ZAR,LESOTHO,2,Rand,710,Yes 126 | Liberia,Libéria,LR,LBR,430,LBR,lb,LI,LB,231,LBR,LI,144,LBR,LRD,LIBERIA,2,Liberian Dollar,430,Yes 127 | Libya,Libye,LY,LBY,434,LBY,ly,LY,LAR,218,LBY,LY,145,LBA,LYD,LIBYA,3,Libyan Dinar,434,Yes 128 | Liechtenstein,Liechtenstein,LI,LIE,438,LIE,lh, ,FL,423,LIE,LS,146,LIE,CHF,LIECHTENSTEIN,2,Swiss Franc,756,Yes 129 | Lithuania,Lituanie,LT,LTU,440,LTU,li,LT,LT,370,LTU,LH,147,LTU,EUR,LITHUANIA,2,Euro,978,Yes 130 | Luxembourg,Luxembourg,LU,LUX,442,LUX,lu,BX,L,352,LUX,LU,148,LUX,EUR,LUXEMBOURG,2,Euro,978,Yes 131 | Macao,Macao,MO,MAC,446,MAC, ,MU, ,853,MAC,MC,149,MAC,MOP,MACAO,2,Pataca,446,Part of CN 132 | "Macedonia, the Former Yugoslav Republic of","Macédoine, l'Ex-république Yougoslave de",MK,MKD,807,MKD,xn,MJ,MK,389,MKD,MK,241,MKD,MKD,"MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF",2,Denar,807,Yes 133 | Madagascar,Madagascar,MG,MDG,450,MDG,mg,MG,RM,261,MAD,MA,150,MAD,MGA,MADAGASCAR,2,Malagasy Ariary,969,Yes 134 | Malawi,Malawi,MW,MWI,454,MWI,mw,MW,MW,265,MWI,MI,152,MAW,MWK,MALAWI,2,Kwacha,454,Yes 135 | Malaysia,Malaisie,MY,MYS,458,MLA,my,MS,MAL,60,MAS,MY,153,MAS,MYR,MALAYSIA,2,Malaysian Ringgit,458,Yes 136 | Maldives,Maldives,MV,MDV,462,MLD,xc,MV, ,960,MDV,MV,154,MDV,MVR,MALDIVES,2,Rufiyaa,462,Yes 137 | Mali,Mali,ML,MLI,466,MLI,ml,MI,RMM,223,MLI,ML,155,MLI,XOF,MALI,0,CFA Franc BCEAO,952,Yes 138 | Malta,Malte,MT,MLT,470,MLT,mm,ML,M,356,MLT,MT,156,MLT,EUR,MALTA,2,Euro,978,Yes 139 | Marshall Islands,"Marshall, Îles",MH,MHL,584,MHL,xe,MH, ,692,MHL,RM,157,MSH,USD,MARSHALL ISLANDS,2,US Dollar,840,Yes 140 | Martinique,Martinique,MQ,MTQ,474,MRT,mq,MR,F,596,MTQ,MB,158,MRT,EUR,MARTINIQUE,2,Euro,978,Part of FR 141 | Mauritania,Mauritanie,MR,MRT,478,MTN,mu,MT,RIM,222,MTN,MR,159,MTN,MRO,MAURITANIA,2,Ouguiya,478,Yes 142 | Mauritius,Maurice,MU,MUS,480,MAU,mf,MA,MS,230,MRI,MP,160,MRI,MUR,MAURITIUS,2,Mauritius Rupee,480,Yes 143 | Mayotte,Mayotte,YT,MYT,175,MYT,ot, , ,262,MYT,MF,161,MAY,EUR,MAYOTTE,2,Euro,978,Part of FR 144 | Mexico,Mexique,MX,MEX,484,MEX,mx,MX,MEX,52,MEX,MX,162,MEX,MXN,MEXICO,2,Mexican Peso,484,Yes 145 | "Micronesia, Federated States of","Micronésie, États Fédérés de",FM,FSM,583,FSM,fm, , ,691,FSM,FM,163,FSM,USD,"MICRONESIA, FEDERATED STATES OF",2,US Dollar,840,Yes 146 | "Moldova, Republic of","Moldova, République de",MD,MDA,498,MDA,mv,RM,MD,373,MDA,MD,165,MDA,MDL,"MOLDOVA, REPUBLIC OF",2,Moldovan Leu,498,Yes 147 | Monaco,Monaco,MC,MCO,492,MCO,mc, ,MC,377,MON,MN,166,MON,EUR,MONACO,2,Euro,978,Yes 148 | Mongolia,Mongolie,MN,MNG,496,MNG,mp,MO,MGL,976,MNG,MG,167,MGL,MNT,MONGOLIA,2,Tugrik,496,Yes 149 | Montenegro,Monténégro,ME,MNE,499,MNE,mo, ,MNE,382,MNE,MJ,2647,MGO,EUR,MONTENEGRO,2,Euro,978,Yes 150 | Montserrat,Montserrat,MS,MSR,500,MSR,mj, , ,1-664,MSR,MH,168,MNT,XCD,MONTSERRAT,2,East Caribbean Dollar,951,Territory of GB 151 | Morocco,Maroc,MA,MAR,504,MRC,mr,MC,MA,212,MAR,MO,169,MAR,MAD,MOROCCO,2,Moroccan Dirham,504,Yes 152 | Mozambique,Mozambique,MZ,MOZ,508,MOZ,mz,MZ,MOC,258,MOZ,MZ,170,MOZ,MZN,MOZAMBIQUE,2,Mozambique Metical,943,Yes 153 | Myanmar,Myanmar,MM,MMR,104,MYA,br,BM,BUR,95,MYA,BM,171,MYA,MMK,MYANMAR,2,Kyat,104,Yes 154 | Namibia,Namibie,NA,NAM,516,NMB,sx,NM,NAM,264,NAM,WA,172,NAM,ZAR,NAMIBIA,2,Rand,710,Yes 155 | Nauru,Nauru,NR,NRU,520,NRU,nu,NW,NAU,674,NRU,NR,173,NRU,AUD,NAURU,2,Australian Dollar,036,Yes 156 | Nepal,Népal,NP,NPL,524,NPL,np,NP,NEP,977,NEP,NP,175,NEP,NPR,NEPAL,2,Nepalese Rupee,524,Yes 157 | Netherlands,Pays-Bas,NL,NLD,528,HOL,ne,NL,NL,31,NED,NL,177,NED,EUR,NETHERLANDS,2,Euro,978,Yes 158 | New Caledonia,Nouvelle-Calédonie,NC,NCL,540,NCL,nl,NC,F,687,NCL,NC,178,NCD,XPF,NEW CALEDONIA,0,CFP Franc,953,Territory of FR 159 | New Zealand,Nouvelle-Zélande,NZ,NZL,554,NZL,nz,NZ,NZ,64,NZL,NZ,179,NZL,NZD,NEW ZEALAND,2,New Zealand Dollar,554,Yes 160 | Nicaragua,Nicaragua,NI,NIC,558,NCG,nq,NK,NIC,505,NCA,NU,180,NCA,NIO,NICARAGUA,2,Cordoba Oro,558,Yes 161 | Niger,Niger,NE,NER,562,NGR,ng,NR,RN,227,NIG,NG,181,NIG,XOF,NIGER,0,CFA Franc BCEAO,952,Yes 162 | Nigeria,Nigéria,NG,NGA,566,NIG,nr,NI,NGR,234,NGA,NI,182,NGR,NGN,NIGERIA,2,Naira,566,Yes 163 | Niue,Niué,NU,NIU,570,NIU,xh, ,NZ,683,NIU,NE,183,NIU,NZD,NIUE,2,New Zealand Dollar,554,Associated with NZ 164 | Norfolk Island,"Norfolk, Île",NF,NFK,574,NFK,nx,NF,AUS,672,NFK,NF,184,NFI,AUD,NORFOLK ISLAND,2,Australian Dollar,036,Territory of AU 165 | Northern Mariana Islands,"Mariannes du Nord, Îles",MP,MNP,580,MRA,nw,MY,USA,1-670,NMI,CQ,185,NMA,USD,NORTHERN MARIANA ISLANDS,2,US Dollar,840,Commonwealth of US 166 | Norway,Norvège,NO,NOR,578,NOR,no,NO,N,47,NOR,NO,186,NOR,NOK,NORWAY,2,Norwegian Krone,578,Yes 167 | Oman,Oman,OM,OMN,512,OMA,mk,OM, ,968,OMA,MU,187,OMA,OMR,OMAN,3,Rial Omani,512,Yes 168 | Pakistan,Pakistan,PK,PAK,586,PAK,pk,PK,PK,92,PAK,PK,188,PAK,PKR,PAKISTAN,2,Pakistan Rupee,586,Yes 169 | Palau,Palaos,PW,PLW,585,PLW,pw, , ,680,PLW,PS,189,PLW,USD,PALAU,2,US Dollar,840,Yes 170 | "Palestine, State of","Palestine, État de",PS,PSE,275, ,"gz,wj", , ,970,PLE,"GZ,WE","91,267",PLE,,"PALESTINE, STATE OF",,No universal currency,,In contention 171 | Panama,Panama,PA,PAN,591,PNR,pn,PM,PA,507,PAN,PM,191,PAN,USD,PANAMA,2,US Dollar,840,Yes 172 | Papua New Guinea,Papouasie-Nouvelle-Guinée,PG,PNG,598,PNG,pp,NG,PNG,675,PNG,PP,192,PNG,PGK,PAPUA NEW GUINEA,2,Kina,598,Yes 173 | Paraguay,Paraguay,PY,PRY,600,PRG,py,PY,PY,595,PAR,PA,194,PAR,PYG,PARAGUAY,0,Guarani,600,Yes 174 | Peru,Pérou,PE,PER,604,PRU,pe,PR,PE,51,PER,PE,195,PER,PEN,PERU,2,Nuevo Sol,604,Yes 175 | Philippines,Philippines,PH,PHL,608,PHL,ph,PH,RP,63,PHI,RP,196,PHI,PHP,PHILIPPINES,2,Philippine Peso,608,Yes 176 | Pitcairn,Pitcairn,PN,PCN,612,PTC,pc,PT, ,870,PCN,PC,197, ,NZD,PITCAIRN,2,New Zealand Dollar,554,Territory of GB 177 | Poland,Pologne,PL,POL,616,POL,pl,PL,PL,48,POL,PL,198,POL,PLN,POLAND,2,Zloty,985,Yes 178 | Portugal,Portugal,PT,PRT,620,POR,po,PO,P,351,POR,PO,199,POR,EUR,PORTUGAL,2,Euro,978,Yes 179 | Puerto Rico,Porto Rico,PR,PRI,630,PTR,pr,PU,USA,1,PUR,RQ,200,PUR,USD,PUERTO RICO,2,US Dollar,840,Commonwealth of US 180 | Qatar,Qatar,QA,QAT,634,QAT,qa,QT,Q,974,QAT,QA,201,QAT,QAR,QATAR,2,Qatari Rial,634,Yes 181 | Romania,Roumanie,RO,ROU,642,ROU,rm,RO,RO,40,ROU,RO,203,ROU,RON,ROMANIA,2,New Romanian Leu,946,Yes 182 | Russian Federation,"Russie, Fédération de",RU,RUS,643,RUS,ru,RS,RUS,7,RUS,RS,204,RUS,RUB,RUSSIAN FEDERATION,2,Russian Ruble,643,Yes 183 | Rwanda,Rwanda,RW,RWA,646,RRW,rw,RW,RWA,250,RWA,RW,205,RWA,RWF,RWANDA,0,Rwanda Franc,646,Yes 184 | Réunion,Réunion,RE,REU,638,REU,re,RE,F,262,REU,RE,206,REU,EUR,RÉUNION,2,Euro,978,Part of FR 185 | Saint Barthélemy,Saint-Barthélemy,BL,BLM,652, ,sc, , ,590, ,TB,, ,EUR,SAINT BARTHÉLEMY,2,Euro,978,Part of FR 186 | "Saint Helena, Ascension and Tristan da Cunha","Sainte-Hélène, Ascension et Tristan da Cunha",SH,SHN,654,SHN,xj,HE, ,290 n,SHN,SH,207,HEL,SHP,"SAINT HELENA, ASCENSION AND TRISTAN DA CUNHA",2,Saint Helena Pound,654,Territory of GB 187 | Saint Kitts and Nevis,Saint-Kitts-Et-Nevis,KN,KNA,659,KNA,xd,AT, ,1-869,SKN,SC,208,SKN,XCD,SAINT KITTS AND NEVIS,2,East Caribbean Dollar,951,Yes 188 | Saint Lucia,Sainte-Lucie,LC,LCA,662,LCA,xk,LC,WL,1-758,LCA,ST,209,LCA,XCD,SAINT LUCIA,2,East Caribbean Dollar,951,Yes 189 | Saint Martin (French part),Saint-Martin(partie Française),MF,MAF,663, ,st, , ,590, ,RN,, ,EUR,SAINT MARTIN (FRENCH PART),2,Euro,978,Part of FR 190 | Saint Pierre and Miquelon,Saint-Pierre-Et-Miquelon,PM,SPM,666,SPM,xl,FP,F,508,SPM,SB,210,SPM,EUR,SAINT PIERRE AND MIQUELON,2,Euro,978,Part of FR 191 | Saint Vincent and the Grenadines,Saint-Vincent-Et-Les Grenadines,VC,VCT,670,VCT,xm,VG,WV,1-784,VIN,VC,211,VIN,XCD,SAINT VINCENT AND THE GRENADINES,2,East Caribbean Dollar,951,Yes 192 | Samoa,Samoa,WS,WSM,882,SMO,ws,ZM,WS,685,SAM,WS,212,SAM,WST,SAMOA,2,Tala,882,Yes 193 | San Marino,Saint-Marin,SM,SMR,674,SMR,sm, ,RSM,378,SMR,SM,213,SMR,EUR,SAN MARINO,2,Euro,978,Yes 194 | Sao Tome and Principe,Sao Tomé-Et-Principe,ST,STP,678,STP,sf,TP, ,239,STP,TP,214,STP,STD,SAO TOME AND PRINCIPE,2,Dobra,678,Yes 195 | Saudi Arabia,Arabie Saoudite,SA,SAU,682,ARS,su,SD,SA,966,KSA,SA,215,KSA,SAR,SAUDI ARABIA,2,Saudi Riyal,682,Yes 196 | Senegal,Sénégal,SN,SEN,686,SEN,sg,SG,SN,221,SEN,SG,217,SEN,XOF,SENEGAL,0,CFA Franc BCEAO,952,Yes 197 | Serbia,Serbie,RS,SRB,688,SRB,rb,YG,SRB,381 p,SRB,"RI,KV",2648,SRB,RSD,SERBIA,2,Serbian Dinar,941,Yes 198 | Seychelles,Seychelles,SC,SYC,690,SEY,se,SC,SY,248,SEY,SE,220,SEY,SCR,SEYCHELLES,2,Seychelles Rupee,690,Yes 199 | Sierra Leone,Sierra Leone,SL,SLE,694,SRL,sl,SL,WAL,232,SLE,SL,221,SLE,SLL,SIERRA LEONE,2,Leone,694,Yes 200 | Singapore,Singapour,SG,SGP,702,SNG,si,SR,SGP,65,SIN,SN,222,SIN,SGD,SINGAPORE,2,Singapore Dollar,702,Yes 201 | Sint Maarten (Dutch part),Saint-Martin (Partie Néerlandaise),SX,SXM,534,,sn,,,1-721,,NN,,,ANG,SINT MAARTEN (DUTCH PART),2,Netherlands Antillean Guilder,532,Part of NL 202 | Slovakia,Slovaquie,SK,SVK,703,SVK,xo,SQ,SK,421,SVK,LO,223,SVK,EUR,SLOVAKIA,2,Euro,978,Yes 203 | Slovenia,Slovénie,SI,SVN,705,SVN,xv,LJ,SLO,386,SVN,SI,224,SLO,EUR,SLOVENIA,2,Euro,978,Yes 204 | Solomon Islands,"Salomon, Îles",SB,SLB,090,SLM,bp,SO, ,677,SOL,BP,225,SOL,SBD,SOLOMON ISLANDS,2,Solomon Islands Dollar,090,Yes 205 | Somalia,Somalie,SO,SOM,706,SOM,so,SI,SO,252,SOM,SO,226,SOM,SOS,SOMALIA,2,Somali Shilling,706,Yes 206 | South Africa,Afrique du Sud,ZA,ZAF,710,AFS,sa,ZA,ZA,27,RSA,SF,227,RSA,ZAR,SOUTH AFRICA,2,Rand,710,Yes 207 | South Georgia and the South Sandwich Islands,Géorgie du Sud-Et-Les Îles Sandwich du Sud,GS,SGS,239, ,xs, , ,500,,SX,228, ,,SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS,,No universal currency,,Territory of GB 208 | South Sudan,Soudan du Sud,SS,SSD,728,SSD,sd,,,211,,OD,,,SSP,SOUTH SUDAN,2,South Sudanese Pound,728,Yes 209 | Spain,Espagne,ES,ESP,724,E,sp,SP,E,34,ESP,SP,229,ESP,EUR,SPAIN,2,Euro,978,Yes 210 | Sri Lanka,Sri Lanka,LK,LKA,144,CLN,ce,SB,CL,94,SRI,CE,231,SRI,LKR,SRI LANKA,2,Sri Lanka Rupee,144,Yes 211 | Sudan,Soudan,SD,SDN,729,SDN,sj,SU,SUD,249,SUD,SU,40764,SUD,SDG,SUDAN,2,Sudanese Pound,938,Yes 212 | Suriname,Suriname,SR,SUR,740,SUR,sr,SM,SME,597,SUR,NS,233,SUR,SRD,SURINAME,2,Surinam Dollar,968,Yes 213 | Svalbard and Jan Mayen,Svalbard et Île Jan Mayen,SJ,SJM,744,NOR, ,SZ, ,47,,"SV,JN",234, ,NOK,SVALBARD AND JAN MAYEN,2,Norwegian Krone,578,Territory of NO 214 | Swaziland,Swaziland,SZ,SWZ,748,SWZ,sq,SV,SD,268,SWZ,WZ,235,SWZ,SZL,SWAZILAND,2,Lilangeni,748,Yes 215 | Sweden,Suède,SE,SWE,752,S,sw,SN,S,46,SWE,SW,236,SWE,SEK,SWEDEN,2,Swedish Krona,752,Yes 216 | Switzerland,Suisse,CH,CHE,756,SUI,sz,SW,CH,41,SUI,SZ,237,SUI,CHF,SWITZERLAND,2,Swiss Franc,756,Yes 217 | Syrian Arab Republic,"Syrienne, République Arabe",SY,SYR,760,SYR,sy,SY,SYR,963,SYR,SY,238,SYR,SYP,SYRIAN ARAB REPUBLIC,2,Syrian Pound,760,Yes 218 | "Taiwan, Province of China","Taïwan, Province de Chine",TW,TWN,158, ,ch, ,RC,886,TPE,TW,925,TPE,TWD,"TAIWAN, PROVINCE OF CHINA",2,New Taiwan Dollar,901,Yes 219 | Tajikistan,Tadjikistan,TJ,TJK,762,TJK,ta,TA,TJ,992,TJK,TI,239,TJK,TJS,TAJIKISTAN,2,Somoni,972,Yes 220 | "Tanzania, United Republic of","Tanzanie, République-Unie de",TZ,TZA,834,TZA,tz,TN,EAT,255,TAN,TZ,257,TAN,TZS,"TANZANIA, UNITED REPUBLIC OF",2,Tanzanian Shilling,834,Yes 221 | Thailand,Thaïlande,TH,THA,764,THA,th,TH,T,66,THA,TH,240,THA,THB,THAILAND,2,Baht,764,Yes 222 | Timor-Leste,Timor-Leste,TL,TLS,626,TLS,em,TM, ,670,TLS,TT,242,TLS,USD,TIMOR-LESTE,2,US Dollar,840,Yes 223 | Togo,Togo,TG,TGO,768,TGO,tg,TG,TG,228,TOG,TO,243,TOG,XOF,TOGO,0,CFA Franc BCEAO,952,Yes 224 | Tokelau,Tokelau,TK,TKL,772,TKL,tl,TK,NZ,690,TKL,TL,244, ,NZD,TOKELAU,2,New Zealand Dollar,554,Territory of NZ 225 | Tonga,Tonga,TO,TON,776,TON,to,TO, ,676,TGA,TN,245,TGA,TOP,TONGA,2,Pa’anga,776,Yes 226 | Trinidad and Tobago,Trinité-Et-Tobago,TT,TTO,780,TRD,tr,TD,TT,1-868,TRI,TD,246,TTO,TTD,TRINIDAD AND TOBAGO,2,Trinidad and Tobago Dollar,780,Yes 227 | Tunisia,Tunisie,TN,TUN,788,TUN,ti,TS,TN,216,TUN,TS,248,TUN,TND,TUNISIA,3,Tunisian Dinar,788,Yes 228 | Turkey,Turquie,TR,TUR,792,TUR,tu,TU,TR,90,TUR,TU,249,TUR,TRY,TURKEY,2,Turkish Lira,949,Yes 229 | Turkmenistan,Turkménistan,TM,TKM,795,TKM,tk,TR,TM,993,TKM,TX,250,TKM,TMT,TURKMENISTAN,2,Turkmenistan New Manat,934,Yes 230 | Turks and Caicos Islands,"Turks-Et-Caïcos, Îles",TC,TCA,796,TCA,tc,TI, ,1-649,TCA,TK,251,TKS,USD,TURKS AND CAICOS ISLANDS,2,US Dollar,840,Territory of GB 231 | Tuvalu,Tuvalu,TV,TUV,798,TUV,tv,TV, ,688,TUV,TV,252,TUV,AUD,TUVALU,2,Australian Dollar,036,Yes 232 | Uganda,Ouganda,UG,UGA,800,UGA,ug,UG,EAU,256,UGA,UG,253,UGA,UGX,UGANDA,0,Uganda Shilling,800,Yes 233 | Ukraine,Ukraine,UA,UKR,804,UKR,un,UR,UA,380,UKR,UP,254,UKR,UAH,UKRAINE,2,Hryvnia,980,Yes 234 | United Arab Emirates,Émirats Arabes Unis,AE,ARE,784,UAE,ts,ER, ,971,UAE,AE,255,UAE,AED,UNITED ARAB EMIRATES,2,UAE Dirham,784,Yes 235 | United Kingdom,Royaume-Uni,GB,GBR,826,G,xxk,UK,GB,44,"ENG,NIR,SCO,WAL",UK,256,GBR,GBP,UNITED KINGDOM,2,Pound Sterling,826,Yes 236 | United States,États-Unis,US,USA,840,USA,xxu,US,USA,1,USA,US,259,USA,USD,UNITED STATES,2,US Dollar,840,Yes 237 | United States Minor Outlying Islands,Îles Mineures Éloignées des États-Unis,UM,UMI,581, ,"ji,xf,wk,uc,up", ,USA, ,,"FQ,HQ,DQ,JQ,KQ,MQ,BQ,LQ,WQ",, ,USD,UNITED STATES MINOR OUTLYING ISLANDS,2,US Dollar,840,Territories of US 238 | Uruguay,Uruguay,UY,URY,858,URG,uy,UY,ROU,598,URU,UY,260,URU,UYU,URUGUAY,2,Peso Uruguayo,858,Yes 239 | Uzbekistan,Ouzbékistan,UZ,UZB,860,UZB,uz,UZ,UZ,998,UZB,UZ,261,UZB,UZS,UZBEKISTAN,2,Uzbekistan Sum,860,Yes 240 | Vanuatu,Vanuatu,VU,VUT,548,VUT,nn,NV, ,678,VAN,NH,262,VAN,VUV,VANUATU,0,Vatu,548,Yes 241 | "Venezuela, Bolivarian Republic of","Venezuela, République Bolivarienne du",VE,VEN,862,VEN,ve,VN,YV,58,VEN,VE,263,VEN,VEF,"VENEZUELA, BOLIVARIAN REPUBLIC OF",2,Bolivar,937,Yes 242 | Viet Nam,Viet Nam,VN,VNM,704,VTN,vm,VS,VN,84,VIE,VM,264,VIE,VND,VIET NAM,0,Dong,704,Yes 243 | "Virgin Islands, British",Îles Vierges Britanniques,VG,VGB,092,VRG,vb,VI,BVI,1-284,VGB,VI,39,IVB,USD,VIRGIN ISLANDS (BRITISH),2,US Dollar,840,Territory of GB 244 | "Virgin Islands, U.S.",Îles Vierges des États-Unis,VI,VIR,850,VIR,vi,VI,USA,1-340,VIR,VQ,258,ISV,USD,VIRGIN ISLANDS (U.S.),2,US Dollar,840,Territory of US 245 | Wallis and Futuna,Wallis et Futuna,WF,WLF,876,WAL,wf,FW,F,681,WLF,WF,266,WAF,XPF,WALLIS AND FUTUNA,0,CFP Franc,953,Territory of FR 246 | Western Sahara,Sahara Occidental,EH,ESH,732,AOE,ss, , ,212,SAH,WI,268, ,MAD,WESTERN SAHARA,2,Moroccan Dirham,504,In contention 247 | Yemen,Yémen,YE,YEM,887,YEM,ye,YE,YAR,967,YEM,YM,269,YEM,YER,YEMEN,2,Yemeni Rial,886,Yes 248 | Zambia,Zambie,ZM,ZMB,894,ZMB,za,ZB,Z,260,ZAM,ZA,270,ZAM,ZMW,ZAMBIA,2,Zambian Kwacha,967,Yes 249 | Zimbabwe,Zimbabwe,ZW,ZWE,716,ZWE,rh,ZW,ZW,263,ZIM,ZI,271,ZIM,ZWL,ZIMBABWE,2,Zimbabwe Dollar,932,Yes 250 | Åland Islands,"Åland, Îles",AX,ALA,248, , , ,FIN,358,ALD, ,1242, ,EUR,ÅLAND ISLANDS,2,Euro,978,Part of FI 251 | -------------------------------------------------------------------------------- /view/country.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Afghanistan", 4 | "code": "AF" 5 | }, 6 | { 7 | "name": "Albania", 8 | "code": "AL" 9 | }, 10 | { 11 | "name": "Algeria", 12 | "code": "DZ" 13 | }, 14 | { 15 | "name": "American Samoa", 16 | "code": "AS" 17 | }, 18 | { 19 | "name": "Andorra", 20 | "code": "AD" 21 | }, 22 | { 23 | "name": "Angola", 24 | "code": "AO" 25 | }, 26 | { 27 | "name": "Anguilla", 28 | "code": "AI" 29 | }, 30 | { 31 | "name": "Antarctica", 32 | "code": "AQ" 33 | }, 34 | { 35 | "name": "Antigua and Barbuda", 36 | "code": "AG" 37 | }, 38 | { 39 | "name": "Argentina", 40 | "code": "AR" 41 | }, 42 | { 43 | "name": "Armenia", 44 | "code": "AM" 45 | }, 46 | { 47 | "name": "Aruba", 48 | "code": "AW" 49 | }, 50 | { 51 | "name": "Australia", 52 | "code": "AU" 53 | }, 54 | { 55 | "name": "Austria", 56 | "code": "AT" 57 | }, 58 | { 59 | "name": "Azerbaijan", 60 | "code": "AZ" 61 | }, 62 | { 63 | "name": "Bahamas", 64 | "code": "BS" 65 | }, 66 | { 67 | "name": "Bahrain", 68 | "code": "BH" 69 | }, 70 | { 71 | "name": "Bangladesh", 72 | "code": "BD" 73 | }, 74 | { 75 | "name": "Barbados", 76 | "code": "BB" 77 | }, 78 | { 79 | "name": "Belarus", 80 | "code": "BY" 81 | }, 82 | { 83 | "name": "Belgium", 84 | "code": "BE" 85 | }, 86 | { 87 | "name": "Belize", 88 | "code": "BZ" 89 | }, 90 | { 91 | "name": "Benin", 92 | "code": "BJ" 93 | }, 94 | { 95 | "name": "Bermuda", 96 | "code": "BM" 97 | }, 98 | { 99 | "name": "Bhutan", 100 | "code": "BT" 101 | }, 102 | { 103 | "name": "Bolivia, Plurinational State of", 104 | "code": "BO" 105 | }, 106 | { 107 | "name": "Bonaire, Sint Eustatius and Saba", 108 | "code": "BQ" 109 | }, 110 | { 111 | "name": "Bosnia and Herzegovina", 112 | "code": "BA" 113 | }, 114 | { 115 | "name": "Botswana", 116 | "code": "BW" 117 | }, 118 | { 119 | "name": "Bouvet Island", 120 | "code": "BV" 121 | }, 122 | { 123 | "name": "Brazil", 124 | "code": "BR" 125 | }, 126 | { 127 | "name": "British Indian Ocean Territory", 128 | "code": "IO" 129 | }, 130 | { 131 | "name": "Brunei Darussalam", 132 | "code": "BN" 133 | }, 134 | { 135 | "name": "Bulgaria", 136 | "code": "BG" 137 | }, 138 | { 139 | "name": "Burkina Faso", 140 | "code": "BF" 141 | }, 142 | { 143 | "name": "Burundi", 144 | "code": "BI" 145 | }, 146 | { 147 | "name": "Cambodia", 148 | "code": "KH" 149 | }, 150 | { 151 | "name": "Cameroon", 152 | "code": "CM" 153 | }, 154 | { 155 | "name": "Canada", 156 | "code": "CA" 157 | }, 158 | { 159 | "name": "Cape Verde", 160 | "code": "CV" 161 | }, 162 | { 163 | "name": "Cayman Islands", 164 | "code": "KY" 165 | }, 166 | { 167 | "name": "Central African Republic", 168 | "code": "CF" 169 | }, 170 | { 171 | "name": "Chad", 172 | "code": "TD" 173 | }, 174 | { 175 | "name": "Chile", 176 | "code": "CL" 177 | }, 178 | { 179 | "name": "China", 180 | "code": "CN" 181 | }, 182 | { 183 | "name": "Christmas Island", 184 | "code": "CX" 185 | }, 186 | { 187 | "name": "Cocos (Keeling) Islands", 188 | "code": "CC" 189 | }, 190 | { 191 | "name": "Colombia", 192 | "code": "CO" 193 | }, 194 | { 195 | "name": "Comoros", 196 | "code": "KM" 197 | }, 198 | { 199 | "name": "Congo", 200 | "code": "CG" 201 | }, 202 | { 203 | "name": "Congo, the Democratic Republic of the", 204 | "code": "CD" 205 | }, 206 | { 207 | "name": "Cook Islands", 208 | "code": "CK" 209 | }, 210 | { 211 | "name": "Costa Rica", 212 | "code": "CR" 213 | }, 214 | { 215 | "name": "Croatia", 216 | "code": "HR" 217 | }, 218 | { 219 | "name": "Cuba", 220 | "code": "CU" 221 | }, 222 | { 223 | "name": "Curaçao", 224 | "code": "CW" 225 | }, 226 | { 227 | "name": "Cyprus", 228 | "code": "CY" 229 | }, 230 | { 231 | "name": "Czech Republic", 232 | "code": "CZ" 233 | }, 234 | { 235 | "name": "Côte d'Ivoire", 236 | "code": "CI" 237 | }, 238 | { 239 | "name": "Denmark", 240 | "code": "DK" 241 | }, 242 | { 243 | "name": "Djibouti", 244 | "code": "DJ" 245 | }, 246 | { 247 | "name": "Dominica", 248 | "code": "DM" 249 | }, 250 | { 251 | "name": "Dominican Republic", 252 | "code": "DO" 253 | }, 254 | { 255 | "name": "Ecuador", 256 | "code": "EC" 257 | }, 258 | { 259 | "name": "Egypt", 260 | "code": "EG" 261 | }, 262 | { 263 | "name": "El Salvador", 264 | "code": "SV" 265 | }, 266 | { 267 | "name": "Equatorial Guinea", 268 | "code": "GQ" 269 | }, 270 | { 271 | "name": "Eritrea", 272 | "code": "ER" 273 | }, 274 | { 275 | "name": "Estonia", 276 | "code": "EE" 277 | }, 278 | { 279 | "name": "Ethiopia", 280 | "code": "ET" 281 | }, 282 | { 283 | "name": "Falkland Islands (Malvinas)", 284 | "code": "FK" 285 | }, 286 | { 287 | "name": "Faroe Islands", 288 | "code": "FO" 289 | }, 290 | { 291 | "name": "Fiji", 292 | "code": "FJ" 293 | }, 294 | { 295 | "name": "Finland", 296 | "code": "FI" 297 | }, 298 | { 299 | "name": "France", 300 | "code": "FR" 301 | }, 302 | { 303 | "name": "French Guiana", 304 | "code": "GF" 305 | }, 306 | { 307 | "name": "French Polynesia", 308 | "code": "PF" 309 | }, 310 | { 311 | "name": "French Southern Territories", 312 | "code": "TF" 313 | }, 314 | { 315 | "name": "Gabon", 316 | "code": "GA" 317 | }, 318 | { 319 | "name": "Gambia", 320 | "code": "GM" 321 | }, 322 | { 323 | "name": "Georgia", 324 | "code": "GE" 325 | }, 326 | { 327 | "name": "Germany", 328 | "code": "DE" 329 | }, 330 | { 331 | "name": "Ghana", 332 | "code": "GH" 333 | }, 334 | { 335 | "name": "Gibraltar", 336 | "code": "GI" 337 | }, 338 | { 339 | "name": "Greece", 340 | "code": "GR" 341 | }, 342 | { 343 | "name": "Greenland", 344 | "code": "GL" 345 | }, 346 | { 347 | "name": "Grenada", 348 | "code": "GD" 349 | }, 350 | { 351 | "name": "Guadeloupe", 352 | "code": "GP" 353 | }, 354 | { 355 | "name": "Guam", 356 | "code": "GU" 357 | }, 358 | { 359 | "name": "Guatemala", 360 | "code": "GT" 361 | }, 362 | { 363 | "name": "Guernsey", 364 | "code": "GG" 365 | }, 366 | { 367 | "name": "Guinea", 368 | "code": "GN" 369 | }, 370 | { 371 | "name": "Guinea-Bissau", 372 | "code": "GW" 373 | }, 374 | { 375 | "name": "Guyana", 376 | "code": "GY" 377 | }, 378 | { 379 | "name": "Haiti", 380 | "code": "HT" 381 | }, 382 | { 383 | "name": "Heard Island and McDonald Mcdonald Islands", 384 | "code": "HM" 385 | }, 386 | { 387 | "name": "Holy See (Vatican City State)", 388 | "code": "VA" 389 | }, 390 | { 391 | "name": "Honduras", 392 | "code": "HN" 393 | }, 394 | { 395 | "name": "Hong Kong", 396 | "code": "HK" 397 | }, 398 | { 399 | "name": "Hungary", 400 | "code": "HU" 401 | }, 402 | { 403 | "name": "Iceland", 404 | "code": "IS" 405 | }, 406 | { 407 | "name": "India", 408 | "code": "IN" 409 | }, 410 | { 411 | "name": "Indonesia", 412 | "code": "ID" 413 | }, 414 | { 415 | "name": "Iran, Islamic Republic of", 416 | "code": "IR" 417 | }, 418 | { 419 | "name": "Iraq", 420 | "code": "IQ" 421 | }, 422 | { 423 | "name": "Ireland", 424 | "code": "IE" 425 | }, 426 | { 427 | "name": "Isle of Man", 428 | "code": "IM" 429 | }, 430 | { 431 | "name": "Israel", 432 | "code": "IL" 433 | }, 434 | { 435 | "name": "Italy", 436 | "code": "IT" 437 | }, 438 | { 439 | "name": "Jamaica", 440 | "code": "JM" 441 | }, 442 | { 443 | "name": "Japan", 444 | "code": "JP" 445 | }, 446 | { 447 | "name": "Jersey", 448 | "code": "JE" 449 | }, 450 | { 451 | "name": "Jordan", 452 | "code": "JO" 453 | }, 454 | { 455 | "name": "Kazakhstan", 456 | "code": "KZ" 457 | }, 458 | { 459 | "name": "Kenya", 460 | "code": "KE" 461 | }, 462 | { 463 | "name": "Kiribati", 464 | "code": "KI" 465 | }, 466 | { 467 | "name": "Korea, Democratic People's Republic of", 468 | "code": "KP" 469 | }, 470 | { 471 | "name": "Korea, Republic of", 472 | "code": "KR" 473 | }, 474 | { 475 | "name": "Kuwait", 476 | "code": "KW" 477 | }, 478 | { 479 | "name": "Kyrgyzstan", 480 | "code": "KG" 481 | }, 482 | { 483 | "name": "Lao People's Democratic Republic", 484 | "code": "LA" 485 | }, 486 | { 487 | "name": "Latvia", 488 | "code": "LV" 489 | }, 490 | { 491 | "name": "Lebanon", 492 | "code": "LB" 493 | }, 494 | { 495 | "name": "Lesotho", 496 | "code": "LS" 497 | }, 498 | { 499 | "name": "Liberia", 500 | "code": "LR" 501 | }, 502 | { 503 | "name": "Libya", 504 | "code": "LY" 505 | }, 506 | { 507 | "name": "Liechtenstein", 508 | "code": "LI" 509 | }, 510 | { 511 | "name": "Lithuania", 512 | "code": "LT" 513 | }, 514 | { 515 | "name": "Luxembourg", 516 | "code": "LU" 517 | }, 518 | { 519 | "name": "Macao", 520 | "code": "MO" 521 | }, 522 | { 523 | "name": "Macedonia, the Former Yugoslav Republic of", 524 | "code": "MK" 525 | }, 526 | { 527 | "name": "Madagascar", 528 | "code": "MG" 529 | }, 530 | { 531 | "name": "Malawi", 532 | "code": "MW" 533 | }, 534 | { 535 | "name": "Malaysia", 536 | "code": "MY" 537 | }, 538 | { 539 | "name": "Maldives", 540 | "code": "MV" 541 | }, 542 | { 543 | "name": "Mali", 544 | "code": "ML" 545 | }, 546 | { 547 | "name": "Malta", 548 | "code": "MT" 549 | }, 550 | { 551 | "name": "Marshall Islands", 552 | "code": "MH" 553 | }, 554 | { 555 | "name": "Martinique", 556 | "code": "MQ" 557 | }, 558 | { 559 | "name": "Mauritania", 560 | "code": "MR" 561 | }, 562 | { 563 | "name": "Mauritius", 564 | "code": "MU" 565 | }, 566 | { 567 | "name": "Mayotte", 568 | "code": "YT" 569 | }, 570 | { 571 | "name": "Mexico", 572 | "code": "MX" 573 | }, 574 | { 575 | "name": "Micronesia, Federated States of", 576 | "code": "FM" 577 | }, 578 | { 579 | "name": "Moldova, Republic of", 580 | "code": "MD" 581 | }, 582 | { 583 | "name": "Monaco", 584 | "code": "MC" 585 | }, 586 | { 587 | "name": "Mongolia", 588 | "code": "MN" 589 | }, 590 | { 591 | "name": "Montenegro", 592 | "code": "ME" 593 | }, 594 | { 595 | "name": "Montserrat", 596 | "code": "MS" 597 | }, 598 | { 599 | "name": "Morocco", 600 | "code": "MA" 601 | }, 602 | { 603 | "name": "Mozambique", 604 | "code": "MZ" 605 | }, 606 | { 607 | "name": "Myanmar", 608 | "code": "MM" 609 | }, 610 | { 611 | "name": "Namibia", 612 | "code": "NA" 613 | }, 614 | { 615 | "name": "Nauru", 616 | "code": "NR" 617 | }, 618 | { 619 | "name": "Nepal", 620 | "code": "NP" 621 | }, 622 | { 623 | "name": "Netherlands", 624 | "code": "NL" 625 | }, 626 | { 627 | "name": "New Caledonia", 628 | "code": "NC" 629 | }, 630 | { 631 | "name": "New Zealand", 632 | "code": "NZ" 633 | }, 634 | { 635 | "name": "Nicaragua", 636 | "code": "NI" 637 | }, 638 | { 639 | "name": "Niger", 640 | "code": "NE" 641 | }, 642 | { 643 | "name": "Nigeria", 644 | "code": "NG" 645 | }, 646 | { 647 | "name": "Niue", 648 | "code": "NU" 649 | }, 650 | { 651 | "name": "Norfolk Island", 652 | "code": "NF" 653 | }, 654 | { 655 | "name": "Northern Mariana Islands", 656 | "code": "MP" 657 | }, 658 | { 659 | "name": "Norway", 660 | "code": "NO" 661 | }, 662 | { 663 | "name": "Oman", 664 | "code": "OM" 665 | }, 666 | { 667 | "name": "Pakistan", 668 | "code": "PK" 669 | }, 670 | { 671 | "name": "Palau", 672 | "code": "PW" 673 | }, 674 | { 675 | "name": "Palestine, State of", 676 | "code": "PS" 677 | }, 678 | { 679 | "name": "Panama", 680 | "code": "PA" 681 | }, 682 | { 683 | "name": "Papua New Guinea", 684 | "code": "PG" 685 | }, 686 | { 687 | "name": "Paraguay", 688 | "code": "PY" 689 | }, 690 | { 691 | "name": "Peru", 692 | "code": "PE" 693 | }, 694 | { 695 | "name": "Philippines", 696 | "code": "PH" 697 | }, 698 | { 699 | "name": "Pitcairn", 700 | "code": "PN" 701 | }, 702 | { 703 | "name": "Poland", 704 | "code": "PL" 705 | }, 706 | { 707 | "name": "Portugal", 708 | "code": "PT" 709 | }, 710 | { 711 | "name": "Puerto Rico", 712 | "code": "PR" 713 | }, 714 | { 715 | "name": "Qatar", 716 | "code": "QA" 717 | }, 718 | { 719 | "name": "Romania", 720 | "code": "RO" 721 | }, 722 | { 723 | "name": "Russian Federation", 724 | "code": "RU" 725 | }, 726 | { 727 | "name": "Rwanda", 728 | "code": "RW" 729 | }, 730 | { 731 | "name": "Réunion", 732 | "code": "RE" 733 | }, 734 | { 735 | "name": "Saint Barthélemy", 736 | "code": "BL" 737 | }, 738 | { 739 | "name": "Saint Helena, Ascension and Tristan da Cunha", 740 | "code": "SH" 741 | }, 742 | { 743 | "name": "Saint Kitts and Nevis", 744 | "code": "KN" 745 | }, 746 | { 747 | "name": "Saint Lucia", 748 | "code": "LC" 749 | }, 750 | { 751 | "name": "Saint Martin (French part)", 752 | "code": "MF" 753 | }, 754 | { 755 | "name": "Saint Pierre and Miquelon", 756 | "code": "PM" 757 | }, 758 | { 759 | "name": "Saint Vincent and the Grenadines", 760 | "code": "VC" 761 | }, 762 | { 763 | "name": "Samoa", 764 | "code": "WS" 765 | }, 766 | { 767 | "name": "San Marino", 768 | "code": "SM" 769 | }, 770 | { 771 | "name": "Sao Tome and Principe", 772 | "code": "ST" 773 | }, 774 | { 775 | "name": "Saudi Arabia", 776 | "code": "SA" 777 | }, 778 | { 779 | "name": "Senegal", 780 | "code": "SN" 781 | }, 782 | { 783 | "name": "Serbia", 784 | "code": "RS" 785 | }, 786 | { 787 | "name": "Seychelles", 788 | "code": "SC" 789 | }, 790 | { 791 | "name": "Sierra Leone", 792 | "code": "SL" 793 | }, 794 | { 795 | "name": "Singapore", 796 | "code": "SG" 797 | }, 798 | { 799 | "name": "Sint Maarten (Dutch part)", 800 | "code": "SX" 801 | }, 802 | { 803 | "name": "Slovakia", 804 | "code": "SK" 805 | }, 806 | { 807 | "name": "Slovenia", 808 | "code": "SI" 809 | }, 810 | { 811 | "name": "Solomon Islands", 812 | "code": "SB" 813 | }, 814 | { 815 | "name": "Somalia", 816 | "code": "SO" 817 | }, 818 | { 819 | "name": "South Africa", 820 | "code": "ZA" 821 | }, 822 | { 823 | "name": "South Georgia and the South Sandwich Islands", 824 | "code": "GS" 825 | }, 826 | { 827 | "name": "South Sudan", 828 | "code": "SS" 829 | }, 830 | { 831 | "name": "Spain", 832 | "code": "ES" 833 | }, 834 | { 835 | "name": "Sri Lanka", 836 | "code": "LK" 837 | }, 838 | { 839 | "name": "Sudan", 840 | "code": "SD" 841 | }, 842 | { 843 | "name": "Suriname", 844 | "code": "SR" 845 | }, 846 | { 847 | "name": "Svalbard and Jan Mayen", 848 | "code": "SJ" 849 | }, 850 | { 851 | "name": "Swaziland", 852 | "code": "SZ" 853 | }, 854 | { 855 | "name": "Sweden", 856 | "code": "SE" 857 | }, 858 | { 859 | "name": "Switzerland", 860 | "code": "CH" 861 | }, 862 | { 863 | "name": "Syrian Arab Republic", 864 | "code": "SY" 865 | }, 866 | { 867 | "name": "Taiwan, Province of China", 868 | "code": "TW" 869 | }, 870 | { 871 | "name": "Tajikistan", 872 | "code": "TJ" 873 | }, 874 | { 875 | "name": "Tanzania, United Republic of", 876 | "code": "TZ" 877 | }, 878 | { 879 | "name": "Thailand", 880 | "code": "TH" 881 | }, 882 | { 883 | "name": "Timor-Leste", 884 | "code": "TL" 885 | }, 886 | { 887 | "name": "Togo", 888 | "code": "TG" 889 | }, 890 | { 891 | "name": "Tokelau", 892 | "code": "TK" 893 | }, 894 | { 895 | "name": "Tonga", 896 | "code": "TO" 897 | }, 898 | { 899 | "name": "Trinidad and Tobago", 900 | "code": "TT" 901 | }, 902 | { 903 | "name": "Tunisia", 904 | "code": "TN" 905 | }, 906 | { 907 | "name": "Turkey", 908 | "code": "TR" 909 | }, 910 | { 911 | "name": "Turkmenistan", 912 | "code": "TM" 913 | }, 914 | { 915 | "name": "Turks and Caicos Islands", 916 | "code": "TC" 917 | }, 918 | { 919 | "name": "Tuvalu", 920 | "code": "TV" 921 | }, 922 | { 923 | "name": "Uganda", 924 | "code": "UG" 925 | }, 926 | { 927 | "name": "Ukraine", 928 | "code": "UA" 929 | }, 930 | { 931 | "name": "United Arab Emirates", 932 | "code": "AE" 933 | }, 934 | { 935 | "name": "United Kingdom", 936 | "code": "GB" 937 | }, 938 | { 939 | "name": "United States", 940 | "code": "US" 941 | }, 942 | { 943 | "name": "United States Minor Outlying Islands", 944 | "code": "UM" 945 | }, 946 | { 947 | "name": "Uruguay", 948 | "code": "UY" 949 | }, 950 | { 951 | "name": "Uzbekistan", 952 | "code": "UZ" 953 | }, 954 | { 955 | "name": "Vanuatu", 956 | "code": "VU" 957 | }, 958 | { 959 | "name": "Venezuela, Bolivarian Republic of", 960 | "code": "VE" 961 | }, 962 | { 963 | "name": "Viet Nam", 964 | "code": "VN" 965 | }, 966 | { 967 | "name": "Virgin Islands, British", 968 | "code": "VG" 969 | }, 970 | { 971 | "name": "Virgin Islands, U.S.", 972 | "code": "VI" 973 | }, 974 | { 975 | "name": "Wallis and Futuna", 976 | "code": "WF" 977 | }, 978 | { 979 | "name": "Western Sahara", 980 | "code": "EH" 981 | }, 982 | { 983 | "name": "Yemen", 984 | "code": "YE" 985 | }, 986 | { 987 | "name": "Zambia", 988 | "code": "ZM" 989 | }, 990 | { 991 | "name": "Zimbabwe", 992 | "code": "ZW" 993 | }, 994 | { 995 | "name": "Åland Islands", 996 | "code": "AX" 997 | } 998 | ] -------------------------------------------------------------------------------- /view/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/learning-data/8459273f92c3bb9225ff79f1b36f7c23001db380/view/img/icon.png -------------------------------------------------------------------------------- /view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | view 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /view/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view", 3 | "devDependencies": { 4 | "apache-server-configs": "^2.7.1", 5 | "grunt": "^0.4.5", 6 | "grunt-autoprefixer": "^1.0.0", 7 | "grunt-concurrent": "^0.5.0", 8 | "grunt-contrib-clean": "^0.6.0", 9 | "grunt-contrib-concat": "^0.5.0", 10 | "grunt-contrib-connect": "^0.8.0", 11 | "grunt-contrib-copy": "^0.5.0", 12 | "grunt-contrib-cssmin": "^0.10.0", 13 | "grunt-contrib-htmlmin": "^0.3.0", 14 | "grunt-contrib-imagemin": "^0.8.0", 15 | "grunt-contrib-jshint": "^0.10.0", 16 | "grunt-contrib-uglify": "^0.5.1", 17 | "grunt-contrib-watch": "^0.6.1", 18 | "grunt-mocha": "^0.4.10", 19 | "grunt-newer": "^0.7.0", 20 | "grunt-rev": "^0.1.0", 21 | "grunt-svgmin": "^0.4.0", 22 | "grunt-usemin": "^2.3.0", 23 | "grunt-wiredep": "^1.7.0", 24 | "jshint-stylish": "^0.4.0", 25 | "load-grunt-tasks": "^0.4.0", 26 | "time-grunt": "^0.4.0" 27 | }, 28 | "engines": { 29 | "node": ">=0.10.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /view/scripts/latlng.js: -------------------------------------------------------------------------------- 1 | var latlong = {}; 2 | latlong["AD"] = { 3 | "latitude": 42.5, 4 | "longitude": 1.5 5 | }; 6 | latlong["AE"] = { 7 | "latitude": 24, 8 | "longitude": 54 9 | }; 10 | latlong["AF"] = { 11 | "latitude": 33, 12 | "longitude": 65 13 | }; 14 | latlong["AG"] = { 15 | "latitude": 17.05, 16 | "longitude": -61.8 17 | }; 18 | latlong["AI"] = { 19 | "latitude": 18.25, 20 | "longitude": -63.1667 21 | }; 22 | latlong["AL"] = { 23 | "latitude": 41, 24 | "longitude": 20 25 | }; 26 | latlong["AM"] = { 27 | "latitude": 40, 28 | "longitude": 45 29 | }; 30 | latlong["AN"] = { 31 | "latitude": 12.25, 32 | "longitude": -68.75 33 | }; 34 | latlong["AO"] = { 35 | "latitude": -12.5, 36 | "longitude": 18.5 37 | }; 38 | latlong["AP"] = { 39 | "latitude": 35, 40 | "longitude": 105 41 | }; 42 | latlong["AQ"] = { 43 | "latitude": -90, 44 | "longitude": 0 45 | }; 46 | latlong["AR"] = { 47 | "latitude": -34, 48 | "longitude": -64 49 | }; 50 | latlong["AS"] = { 51 | "latitude": -14.3333, 52 | "longitude": -170 53 | }; 54 | latlong["AT"] = { 55 | "latitude": 47.3333, 56 | "longitude": 13.3333 57 | }; 58 | latlong["AU"] = { 59 | "latitude": -27, 60 | "longitude": 133 61 | }; 62 | latlong["AW"] = { 63 | "latitude": 12.5, 64 | "longitude": -69.9667 65 | }; 66 | latlong["AZ"] = { 67 | "latitude": 40.5, 68 | "longitude": 47.5 69 | }; 70 | latlong["BA"] = { 71 | "latitude": 44, 72 | "longitude": 18 73 | }; 74 | latlong["BB"] = { 75 | "latitude": 13.1667, 76 | "longitude": -59.5333 77 | }; 78 | latlong["BD"] = { 79 | "latitude": 24, 80 | "longitude": 90 81 | }; 82 | latlong["BE"] = { 83 | "latitude": 50.8333, 84 | "longitude": 4 85 | }; 86 | latlong["BF"] = { 87 | "latitude": 13, 88 | "longitude": -2 89 | }; 90 | latlong["BG"] = { 91 | "latitude": 43, 92 | "longitude": 25 93 | }; 94 | latlong["BH"] = { 95 | "latitude": 26, 96 | "longitude": 50.55 97 | }; 98 | latlong["BI"] = { 99 | "latitude": -3.5, 100 | "longitude": 30 101 | }; 102 | latlong["BJ"] = { 103 | "latitude": 9.5, 104 | "longitude": 2.25 105 | }; 106 | latlong["BM"] = { 107 | "latitude": 32.3333, 108 | "longitude": -64.75 109 | }; 110 | latlong["BN"] = { 111 | "latitude": 4.5, 112 | "longitude": 114.6667 113 | }; 114 | latlong["BO"] = { 115 | "latitude": -17, 116 | "longitude": -65 117 | }; 118 | latlong["BR"] = { 119 | "latitude": -10, 120 | "longitude": -55 121 | }; 122 | latlong["BS"] = { 123 | "latitude": 24.25, 124 | "longitude": -76 125 | }; 126 | latlong["BT"] = { 127 | "latitude": 27.5, 128 | "longitude": 90.5 129 | }; 130 | latlong["BV"] = { 131 | "latitude": -54.4333, 132 | "longitude": 3.4 133 | }; 134 | latlong["BW"] = { 135 | "latitude": -22, 136 | "longitude": 24 137 | }; 138 | latlong["BY"] = { 139 | "latitude": 53, 140 | "longitude": 28 141 | }; 142 | latlong["BZ"] = { 143 | "latitude": 17.25, 144 | "longitude": -88.75 145 | }; 146 | latlong["CA"] = { 147 | "latitude": 54, 148 | "longitude": -100 149 | }; 150 | latlong["CC"] = { 151 | "latitude": -12.5, 152 | "longitude": 96.8333 153 | }; 154 | latlong["CD"] = { 155 | "latitude": 0, 156 | "longitude": 25 157 | }; 158 | latlong["CF"] = { 159 | "latitude": 7, 160 | "longitude": 21 161 | }; 162 | latlong["CG"] = { 163 | "latitude": -1, 164 | "longitude": 15 165 | }; 166 | latlong["CH"] = { 167 | "latitude": 47, 168 | "longitude": 8 169 | }; 170 | latlong["CI"] = { 171 | "latitude": 8, 172 | "longitude": -5 173 | }; 174 | latlong["CK"] = { 175 | "latitude": -21.2333, 176 | "longitude": -159.7667 177 | }; 178 | latlong["CL"] = { 179 | "latitude": -30, 180 | "longitude": -71 181 | }; 182 | latlong["CM"] = { 183 | "latitude": 6, 184 | "longitude": 12 185 | }; 186 | latlong["CN"] = { 187 | "latitude": 35, 188 | "longitude": 105 189 | }; 190 | latlong["CO"] = { 191 | "latitude": 4, 192 | "longitude": -72 193 | }; 194 | latlong["CR"] = { 195 | "latitude": 10, 196 | "longitude": -84 197 | }; 198 | latlong["CU"] = { 199 | "latitude": 21.5, 200 | "longitude": -80 201 | }; 202 | latlong["CV"] = { 203 | "latitude": 16, 204 | "longitude": -24 205 | }; 206 | latlong["CX"] = { 207 | "latitude": -10.5, 208 | "longitude": 105.6667 209 | }; 210 | latlong["CY"] = { 211 | "latitude": 35, 212 | "longitude": 33 213 | }; 214 | latlong["CZ"] = { 215 | "latitude": 49.75, 216 | "longitude": 15.5 217 | }; 218 | latlong["DE"] = { 219 | "latitude": 51, 220 | "longitude": 9 221 | }; 222 | latlong["DJ"] = { 223 | "latitude": 11.5, 224 | "longitude": 43 225 | }; 226 | latlong["DK"] = { 227 | "latitude": 56, 228 | "longitude": 10 229 | }; 230 | latlong["DM"] = { 231 | "latitude": 15.4167, 232 | "longitude": -61.3333 233 | }; 234 | latlong["DO"] = { 235 | "latitude": 19, 236 | "longitude": -70.6667 237 | }; 238 | latlong["DZ"] = { 239 | "latitude": 28, 240 | "longitude": 3 241 | }; 242 | latlong["EC"] = { 243 | "latitude": -2, 244 | "longitude": -77.5 245 | }; 246 | latlong["EE"] = { 247 | "latitude": 59, 248 | "longitude": 26 249 | }; 250 | latlong["EG"] = { 251 | "latitude": 27, 252 | "longitude": 30 253 | }; 254 | latlong["EH"] = { 255 | "latitude": 24.5, 256 | "longitude": -13 257 | }; 258 | latlong["ER"] = { 259 | "latitude": 15, 260 | "longitude": 39 261 | }; 262 | latlong["ES"] = { 263 | "latitude": 40, 264 | "longitude": -4 265 | }; 266 | latlong["ET"] = { 267 | "latitude": 8, 268 | "longitude": 38 269 | }; 270 | latlong["EU"] = { 271 | "latitude": 47, 272 | "longitude": 8 273 | }; 274 | latlong["FI"] = { 275 | "latitude": 62, 276 | "longitude": 26 277 | }; 278 | latlong["FJ"] = { 279 | "latitude": -18, 280 | "longitude": 175 281 | }; 282 | latlong["FK"] = { 283 | "latitude": -51.75, 284 | "longitude": -59 285 | }; 286 | latlong["FM"] = { 287 | "latitude": 6.9167, 288 | "longitude": 158.25 289 | }; 290 | latlong["FO"] = { 291 | "latitude": 62, 292 | "longitude": -7 293 | }; 294 | latlong["FR"] = { 295 | "latitude": 46, 296 | "longitude": 2 297 | }; 298 | latlong["GA"] = { 299 | "latitude": -1, 300 | "longitude": 11.75 301 | }; 302 | latlong["GB"] = { 303 | "latitude": 54, 304 | "longitude": -2 305 | }; 306 | latlong["GD"] = { 307 | "latitude": 12.1167, 308 | "longitude": -61.6667 309 | }; 310 | latlong["GE"] = { 311 | "latitude": 42, 312 | "longitude": 43.5 313 | }; 314 | latlong["GF"] = { 315 | "latitude": 4, 316 | "longitude": -53 317 | }; 318 | latlong["GH"] = { 319 | "latitude": 8, 320 | "longitude": -2 321 | }; 322 | latlong["GI"] = { 323 | "latitude": 36.1833, 324 | "longitude": -5.3667 325 | }; 326 | latlong["GL"] = { 327 | "latitude": 72, 328 | "longitude": -40 329 | }; 330 | latlong["GM"] = { 331 | "latitude": 13.4667, 332 | "longitude": -16.5667 333 | }; 334 | latlong["GN"] = { 335 | "latitude": 11, 336 | "longitude": -10 337 | }; 338 | latlong["GP"] = { 339 | "latitude": 16.25, 340 | "longitude": -61.5833 341 | }; 342 | latlong["GQ"] = { 343 | "latitude": 2, 344 | "longitude": 10 345 | }; 346 | latlong["GR"] = { 347 | "latitude": 39, 348 | "longitude": 22 349 | }; 350 | latlong["GS"] = { 351 | "latitude": -54.5, 352 | "longitude": -37 353 | }; 354 | latlong["GT"] = { 355 | "latitude": 15.5, 356 | "longitude": -90.25 357 | }; 358 | latlong["GU"] = { 359 | "latitude": 13.4667, 360 | "longitude": 144.7833 361 | }; 362 | latlong["GW"] = { 363 | "latitude": 12, 364 | "longitude": -15 365 | }; 366 | latlong["GY"] = { 367 | "latitude": 5, 368 | "longitude": -59 369 | }; 370 | latlong["HK"] = { 371 | "latitude": 22.25, 372 | "longitude": 114.1667 373 | }; 374 | latlong["HM"] = { 375 | "latitude": -53.1, 376 | "longitude": 72.5167 377 | }; 378 | latlong["HN"] = { 379 | "latitude": 15, 380 | "longitude": -86.5 381 | }; 382 | latlong["HR"] = { 383 | "latitude": 45.1667, 384 | "longitude": 15.5 385 | }; 386 | latlong["HT"] = { 387 | "latitude": 19, 388 | "longitude": -72.4167 389 | }; 390 | latlong["HU"] = { 391 | "latitude": 47, 392 | "longitude": 20 393 | }; 394 | latlong["ID"] = { 395 | "latitude": -5, 396 | "longitude": 120 397 | }; 398 | latlong["IE"] = { 399 | "latitude": 53, 400 | "longitude": -8 401 | }; 402 | latlong["IL"] = { 403 | "latitude": 31.5, 404 | "longitude": 34.75 405 | }; 406 | latlong["IN"] = { 407 | "latitude": 20, 408 | "longitude": 77 409 | }; 410 | latlong["IO"] = { 411 | "latitude": -6, 412 | "longitude": 71.5 413 | }; 414 | latlong["IQ"] = { 415 | "latitude": 33, 416 | "longitude": 44 417 | }; 418 | latlong["IR"] = { 419 | "latitude": 32, 420 | "longitude": 53 421 | }; 422 | latlong["IS"] = { 423 | "latitude": 65, 424 | "longitude": -18 425 | }; 426 | latlong["IT"] = { 427 | "latitude": 42.8333, 428 | "longitude": 12.8333 429 | }; 430 | latlong["JM"] = { 431 | "latitude": 18.25, 432 | "longitude": -77.5 433 | }; 434 | latlong["JO"] = { 435 | "latitude": 31, 436 | "longitude": 36 437 | }; 438 | latlong["JP"] = { 439 | "latitude": 36, 440 | "longitude": 138 441 | }; 442 | latlong["KE"] = { 443 | "latitude": 1, 444 | "longitude": 38 445 | }; 446 | latlong["KG"] = { 447 | "latitude": 41, 448 | "longitude": 75 449 | }; 450 | latlong["KH"] = { 451 | "latitude": 13, 452 | "longitude": 105 453 | }; 454 | latlong["KI"] = { 455 | "latitude": 1.4167, 456 | "longitude": 173 457 | }; 458 | latlong["KM"] = { 459 | "latitude": -12.1667, 460 | "longitude": 44.25 461 | }; 462 | latlong["KN"] = { 463 | "latitude": 17.3333, 464 | "longitude": -62.75 465 | }; 466 | latlong["KP"] = { 467 | "latitude": 40, 468 | "longitude": 127 469 | }; 470 | latlong["KR"] = { 471 | "latitude": 37, 472 | "longitude": 127.5 473 | }; 474 | latlong["KW"] = { 475 | "latitude": 29.3375, 476 | "longitude": 47.6581 477 | }; 478 | latlong["KY"] = { 479 | "latitude": 19.5, 480 | "longitude": -80.5 481 | }; 482 | latlong["KZ"] = { 483 | "latitude": 48, 484 | "longitude": 68 485 | }; 486 | latlong["LA"] = { 487 | "latitude": 18, 488 | "longitude": 105 489 | }; 490 | latlong["LB"] = { 491 | "latitude": 33.8333, 492 | "longitude": 35.8333 493 | }; 494 | latlong["LC"] = { 495 | "latitude": 13.8833, 496 | "longitude": -61.1333 497 | }; 498 | latlong["LI"] = { 499 | "latitude": 47.1667, 500 | "longitude": 9.5333 501 | }; 502 | latlong["LK"] = { 503 | "latitude": 7, 504 | "longitude": 81 505 | }; 506 | latlong["LR"] = { 507 | "latitude": 6.5, 508 | "longitude": -9.5 509 | }; 510 | latlong["LS"] = { 511 | "latitude": -29.5, 512 | "longitude": 28.5 513 | }; 514 | latlong["LT"] = { 515 | "latitude": 55, 516 | "longitude": 24 517 | }; 518 | latlong["LU"] = { 519 | "latitude": 49.75, 520 | "longitude": 6 521 | }; 522 | latlong["LV"] = { 523 | "latitude": 57, 524 | "longitude": 25 525 | }; 526 | latlong["LY"] = { 527 | "latitude": 25, 528 | "longitude": 17 529 | }; 530 | latlong["MA"] = { 531 | "latitude": 32, 532 | "longitude": -5 533 | }; 534 | latlong["MC"] = { 535 | "latitude": 43.7333, 536 | "longitude": 7.4 537 | }; 538 | latlong["MD"] = { 539 | "latitude": 47, 540 | "longitude": 29 541 | }; 542 | latlong["ME"] = { 543 | "latitude": 42.5, 544 | "longitude": 19.4 545 | }; 546 | latlong["MG"] = { 547 | "latitude": -20, 548 | "longitude": 47 549 | }; 550 | latlong["MH"] = { 551 | "latitude": 9, 552 | "longitude": 168 553 | }; 554 | latlong["MK"] = { 555 | "latitude": 41.8333, 556 | "longitude": 22 557 | }; 558 | latlong["ML"] = { 559 | "latitude": 17, 560 | "longitude": -4 561 | }; 562 | latlong["MM"] = { 563 | "latitude": 22, 564 | "longitude": 98 565 | }; 566 | latlong["MN"] = { 567 | "latitude": 46, 568 | "longitude": 105 569 | }; 570 | latlong["MO"] = { 571 | "latitude": 22.1667, 572 | "longitude": 113.55 573 | }; 574 | latlong["MP"] = { 575 | "latitude": 15.2, 576 | "longitude": 145.75 577 | }; 578 | latlong["MQ"] = { 579 | "latitude": 14.6667, 580 | "longitude": -61 581 | }; 582 | latlong["MR"] = { 583 | "latitude": 20, 584 | "longitude": -12 585 | }; 586 | latlong["MS"] = { 587 | "latitude": 16.75, 588 | "longitude": -62.2 589 | }; 590 | latlong["MT"] = { 591 | "latitude": 35.8333, 592 | "longitude": 14.5833 593 | }; 594 | latlong["MU"] = { 595 | "latitude": -20.2833, 596 | "longitude": 57.55 597 | }; 598 | latlong["MV"] = { 599 | "latitude": 3.25, 600 | "longitude": 73 601 | }; 602 | latlong["MW"] = { 603 | "latitude": -13.5, 604 | "longitude": 34 605 | }; 606 | latlong["MX"] = { 607 | "latitude": 23, 608 | "longitude": -102 609 | }; 610 | latlong["MY"] = { 611 | "latitude": 2.5, 612 | "longitude": 112.5 613 | }; 614 | latlong["MZ"] = { 615 | "latitude": -18.25, 616 | "longitude": 35 617 | }; 618 | latlong["NA"] = { 619 | "latitude": -22, 620 | "longitude": 17 621 | }; 622 | latlong["NC"] = { 623 | "latitude": -21.5, 624 | "longitude": 165.5 625 | }; 626 | latlong["NE"] = { 627 | "latitude": 16, 628 | "longitude": 8 629 | }; 630 | latlong["NF"] = { 631 | "latitude": -29.0333, 632 | "longitude": 167.95 633 | }; 634 | latlong["NG"] = { 635 | "latitude": 10, 636 | "longitude": 8 637 | }; 638 | latlong["NI"] = { 639 | "latitude": 13, 640 | "longitude": -85 641 | }; 642 | latlong["NL"] = { 643 | "latitude": 52.5, 644 | "longitude": 5.75 645 | }; 646 | latlong["NO"] = { 647 | "latitude": 62, 648 | "longitude": 10 649 | }; 650 | latlong["NP"] = { 651 | "latitude": 28, 652 | "longitude": 84 653 | }; 654 | latlong["NR"] = { 655 | "latitude": -0.5333, 656 | "longitude": 166.9167 657 | }; 658 | latlong["NU"] = { 659 | "latitude": -19.0333, 660 | "longitude": -169.8667 661 | }; 662 | latlong["NZ"] = { 663 | "latitude": -41, 664 | "longitude": 174 665 | }; 666 | latlong["OM"] = { 667 | "latitude": 21, 668 | "longitude": 57 669 | }; 670 | latlong["PA"] = { 671 | "latitude": 9, 672 | "longitude": -80 673 | }; 674 | latlong["PE"] = { 675 | "latitude": -10, 676 | "longitude": -76 677 | }; 678 | latlong["PF"] = { 679 | "latitude": -15, 680 | "longitude": -140 681 | }; 682 | latlong["PG"] = { 683 | "latitude": -6, 684 | "longitude": 147 685 | }; 686 | latlong["PH"] = { 687 | "latitude": 13, 688 | "longitude": 122 689 | }; 690 | latlong["PK"] = { 691 | "latitude": 30, 692 | "longitude": 70 693 | }; 694 | latlong["PL"] = { 695 | "latitude": 52, 696 | "longitude": 20 697 | }; 698 | latlong["PM"] = { 699 | "latitude": 46.8333, 700 | "longitude": -56.3333 701 | }; 702 | latlong["PR"] = { 703 | "latitude": 18.25, 704 | "longitude": -66.5 705 | }; 706 | latlong["PS"] = { 707 | "latitude": 32, 708 | "longitude": 35.25 709 | }; 710 | latlong["PT"] = { 711 | "latitude": 39.5, 712 | "longitude": -8 713 | }; 714 | latlong["PW"] = { 715 | "latitude": 7.5, 716 | "longitude": 134.5 717 | }; 718 | latlong["PY"] = { 719 | "latitude": -23, 720 | "longitude": -58 721 | }; 722 | latlong["QA"] = { 723 | "latitude": 25.5, 724 | "longitude": 51.25 725 | }; 726 | latlong["RE"] = { 727 | "latitude": -21.1, 728 | "longitude": 55.6 729 | }; 730 | latlong["RO"] = { 731 | "latitude": 46, 732 | "longitude": 25 733 | }; 734 | latlong["RS"] = { 735 | "latitude": 44, 736 | "longitude": 21 737 | }; 738 | latlong["RU"] = { 739 | "latitude": 60, 740 | "longitude": 100 741 | }; 742 | latlong["RW"] = { 743 | "latitude": -2, 744 | "longitude": 30 745 | }; 746 | latlong["SA"] = { 747 | "latitude": 25, 748 | "longitude": 45 749 | }; 750 | latlong["SB"] = { 751 | "latitude": -8, 752 | "longitude": 159 753 | }; 754 | latlong["SC"] = { 755 | "latitude": -4.5833, 756 | "longitude": 55.6667 757 | }; 758 | latlong["SD"] = { 759 | "latitude": 15, 760 | "longitude": 30 761 | }; 762 | latlong["SE"] = { 763 | "latitude": 62, 764 | "longitude": 15 765 | }; 766 | latlong["SG"] = { 767 | "latitude": 1.3667, 768 | "longitude": 103.8 769 | }; 770 | latlong["SH"] = { 771 | "latitude": -15.9333, 772 | "longitude": -5.7 773 | }; 774 | latlong["SI"] = { 775 | "latitude": 46, 776 | "longitude": 15 777 | }; 778 | latlong["SJ"] = { 779 | "latitude": 78, 780 | "longitude": 20 781 | }; 782 | latlong["SK"] = { 783 | "latitude": 48.6667, 784 | "longitude": 19.5 785 | }; 786 | latlong["SL"] = { 787 | "latitude": 8.5, 788 | "longitude": -11.5 789 | }; 790 | latlong["SM"] = { 791 | "latitude": 43.7667, 792 | "longitude": 12.4167 793 | }; 794 | latlong["SN"] = { 795 | "latitude": 14, 796 | "longitude": -14 797 | }; 798 | latlong["SO"] = { 799 | "latitude": 10, 800 | "longitude": 49 801 | }; 802 | latlong["SR"] = { 803 | "latitude": 4, 804 | "longitude": -56 805 | }; 806 | latlong["ST"] = { 807 | "latitude": 1, 808 | "longitude": 7 809 | }; 810 | latlong["SV"] = { 811 | "latitude": 13.8333, 812 | "longitude": -88.9167 813 | }; 814 | latlong["SY"] = { 815 | "latitude": 35, 816 | "longitude": 38 817 | }; 818 | latlong["SZ"] = { 819 | "latitude": -26.5, 820 | "longitude": 31.5 821 | }; 822 | latlong["TC"] = { 823 | "latitude": 21.75, 824 | "longitude": -71.5833 825 | }; 826 | latlong["TD"] = { 827 | "latitude": 15, 828 | "longitude": 19 829 | }; 830 | latlong["TF"] = { 831 | "latitude": -43, 832 | "longitude": 67 833 | }; 834 | latlong["TG"] = { 835 | "latitude": 8, 836 | "longitude": 1.1667 837 | }; 838 | latlong["TH"] = { 839 | "latitude": 15, 840 | "longitude": 100 841 | }; 842 | latlong["TJ"] = { 843 | "latitude": 39, 844 | "longitude": 71 845 | }; 846 | latlong["TK"] = { 847 | "latitude": -9, 848 | "longitude": -172 849 | }; 850 | latlong["TM"] = { 851 | "latitude": 40, 852 | "longitude": 60 853 | }; 854 | latlong["TN"] = { 855 | "latitude": 34, 856 | "longitude": 9 857 | }; 858 | latlong["TO"] = { 859 | "latitude": -20, 860 | "longitude": -175 861 | }; 862 | latlong["TR"] = { 863 | "latitude": 39, 864 | "longitude": 35 865 | }; 866 | latlong["TT"] = { 867 | "latitude": 11, 868 | "longitude": -61 869 | }; 870 | latlong["TV"] = { 871 | "latitude": -8, 872 | "longitude": 178 873 | }; 874 | latlong["TW"] = { 875 | "latitude": 23.5, 876 | "longitude": 121 877 | }; 878 | latlong["TZ"] = { 879 | "latitude": -6, 880 | "longitude": 35 881 | }; 882 | latlong["UA"] = { 883 | "latitude": 49, 884 | "longitude": 32 885 | }; 886 | latlong["UG"] = { 887 | "latitude": 1, 888 | "longitude": 32 889 | }; 890 | latlong["UM"] = { 891 | "latitude": 19.2833, 892 | "longitude": 166.6 893 | }; 894 | latlong["US"] = { 895 | "latitude": 38, 896 | "longitude": -97 897 | }; 898 | latlong["UY"] = { 899 | "latitude": -33, 900 | "longitude": -56 901 | }; 902 | latlong["UZ"] = { 903 | "latitude": 41, 904 | "longitude": 64 905 | }; 906 | latlong["VA"] = { 907 | "latitude": 41.9, 908 | "longitude": 12.45 909 | }; 910 | latlong["VC"] = { 911 | "latitude": 13.25, 912 | "longitude": -61.2 913 | }; 914 | latlong["VE"] = { 915 | "latitude": 8, 916 | "longitude": -66 917 | }; 918 | latlong["VG"] = { 919 | "latitude": 18.5, 920 | "longitude": -64.5 921 | }; 922 | latlong["VI"] = { 923 | "latitude": 18.3333, 924 | "longitude": -64.8333 925 | }; 926 | latlong["VN"] = { 927 | "latitude": 16, 928 | "longitude": 106 929 | }; 930 | latlong["VU"] = { 931 | "latitude": -16, 932 | "longitude": 167 933 | }; 934 | latlong["WF"] = { 935 | "latitude": -13.3, 936 | "longitude": -176.2 937 | }; 938 | latlong["WS"] = { 939 | "latitude": -13.5833, 940 | "longitude": -172.3333 941 | }; 942 | latlong["YE"] = { 943 | "latitude": 15, 944 | "longitude": 48 945 | }; 946 | latlong["YT"] = { 947 | "latitude": -12.8333, 948 | "longitude": 45.1667 949 | }; 950 | latlong["ZA"] = { 951 | "latitude": -29, 952 | "longitude": 24 953 | }; 954 | latlong["ZM"] = { 955 | "latitude": -15, 956 | "longitude": 30 957 | }; 958 | latlong["ZW"] = { 959 | "latitude": -20, 960 | "longitude": 30 961 | }; -------------------------------------------------------------------------------- /view/scripts/main_ammap.js: -------------------------------------------------------------------------------- 1 | var client = new $.es.Client({ 2 | hosts: 'localhost:9200' 3 | }); 4 | 5 | var query = { 6 | index: 'nginx', 7 | type: 'log', 8 | size: 200, 9 | body: { 10 | query: { 11 | query_string: { 12 | query: "*" 13 | } 14 | }, 15 | aggs: { 16 | 2: { 17 | terms: { 18 | field: "country", 19 | size: 200, 20 | order: { 21 | _count: "desc" 22 | } 23 | } 24 | } 25 | } 26 | } 27 | }; 28 | 29 | $(document).ready(function () { 30 | $.ajax({ 31 | type: "GET", 32 | url: "country.json", 33 | success: function (data) { 34 | generate_info(data) 35 | } 36 | }); 37 | }); 38 | 39 | var generate_info = function(data){ 40 | var mapDatas = []; 41 | client.search(query).then(function (results) { 42 | $.each(results.aggregations[2].buckets, function(index, bucket){ 43 | var mapData; 44 | $.each(data, function(index, country){ 45 | if(country.name.toLowerCase() === bucket.key) { 46 | mapData = { 47 | code: country.code, 48 | name: country.name, 49 | value: bucket.doc_count, 50 | color: "#eea638" 51 | }; 52 | } 53 | }); 54 | if(mapData !== undefined){ 55 | mapDatas.push(mapData); 56 | } 57 | }); 58 | create_map(mapDatas); 59 | }); 60 | }; 61 | 62 | var create_map = function(mapData){ 63 | var map; 64 | var minBulletSize = 3; 65 | var maxBulletSize = 70; 66 | var min = Infinity; 67 | var max = -Infinity; 68 | 69 | AmCharts.theme = AmCharts.themes.black; 70 | 71 | for (var i = 0; i < mapData.length; i++) { 72 | var value = mapData[i].value; 73 | if (value < min) { 74 | min = value; 75 | } 76 | if (value > max) { 77 | max = value; 78 | } 79 | } 80 | 81 | map = new AmCharts.AmMap(); 82 | map.pathToImages = "bower_components/ammap/dist/ammap/images/"; 83 | 84 | //map.addTitle("Website traffic Map", 14); 85 | //map.addTitle("source: nginx access log", 11); 86 | map.areasSettings = { 87 | unlistedAreasColor: "#FFFFFF", 88 | unlistedAreasAlpha: 0.1 89 | }; 90 | map.imagesSettings = { 91 | balloonText: "[[title]]: [[value]]", 92 | alpha: 0.6 93 | }; 94 | 95 | var dataProvider = { 96 | mapVar: AmCharts.maps.worldLow, 97 | images: [] 98 | }; 99 | 100 | var maxSquare = maxBulletSize * maxBulletSize * 2 * Math.PI; 101 | var minSquare = minBulletSize * minBulletSize * 2 * Math.PI; 102 | 103 | for (var i = 0; i < mapData.length; i++) { 104 | var dataItem = mapData[i]; 105 | var value = dataItem.value; 106 | // calculate size of a bubble 107 | var square = (value - min) / (max - min) * (maxSquare - minSquare) + minSquare; 108 | if (square < minSquare) { 109 | square = minSquare; 110 | } 111 | var size = Math.sqrt(square / (Math.PI * 2)); 112 | var id = dataItem.code; 113 | 114 | dataProvider.images.push({ 115 | type: "circle", 116 | width: size, 117 | height: size, 118 | color: dataItem.color, 119 | longitude: latlong[id].longitude, 120 | latitude: latlong[id].latitude, 121 | title: dataItem.name, 122 | value: value 123 | }); 124 | } 125 | 126 | map.dataProvider = dataProvider; 127 | 128 | map.write("mapdiv"); 129 | }; 130 | -------------------------------------------------------------------------------- /view/scripts/main_ol.js: -------------------------------------------------------------------------------- 1 | var exampleNS = {}; 2 | 3 | exampleNS.getRendererFromQueryString = function() { 4 | var obj = {}, queryString = location.search.slice(1), 5 | re = /([^&=]+)=([^&]*)/g, m; 6 | 7 | while (m = re.exec(queryString)) { 8 | obj[decodeURIComponent(m[1])] = decodeURIComponent(m[2]); 9 | } 10 | if ('renderers' in obj) { 11 | return obj['renderers'].split(','); 12 | } else if ('renderer' in obj) { 13 | return [obj['renderer']]; 14 | } else { 15 | return undefined; 16 | } 17 | }; 18 | 19 | var view = new ol.View({ 20 | center: [12119653.781323666,4054689.6824535457], 21 | zoom: 4 22 | }); 23 | 24 | var controls = ol.control.defaults({rotate: false}); 25 | var interactions = ol.interaction.defaults({altShiftDragRotate:false, pinchRotate:false}); 26 | 27 | var map = new ol.Map({ 28 | controls: controls, 29 | interactions: interactions, 30 | layers: [ 31 | new ol.layer.Tile({ 32 | source: new ol.source.BingMaps({ 33 | key: 'Ak-dzM4wZjSqTlzveKz5u0d4IQ4bRzVI309GxmkgSVr1ewS6iPSrOvOKhA-CJlm3', 34 | culture: 'zh-CN', 35 | imagerySet: 'Road' 36 | }) 37 | }) 38 | ], 39 | renderer: exampleNS.getRendererFromQueryString(), 40 | target: 'map', 41 | view: view 42 | }); 43 | 44 | var client = new $.es.Client({ 45 | hosts: 'localhost:9200' 46 | }); 47 | 48 | var query = { 49 | index: 'nginx', 50 | type: 'log', 51 | size: 200, 52 | body: { 53 | query: { 54 | query_string: { 55 | query: "*" 56 | } 57 | }, 58 | aggs: { 59 | 2: { 60 | terms: { 61 | field: "city", 62 | size: 10, 63 | order: { 64 | _count: "desc" 65 | } 66 | } 67 | } 68 | } 69 | } 70 | }; 71 | 72 | client.search(query).then(function(results){ 73 | var vectorSource = new ol.source.Vector({ }); 74 | $.each(results.hits.hits, function(index, result){ 75 | result = result._source; 76 | if(result.location === null) { 77 | return; 78 | } 79 | var position = result.location.split(","); 80 | var pos = ol.proj.transform([parseFloat(position[0]), parseFloat(position[1])], 'EPSG:4326', 'EPSG:3857'); 81 | 82 | var iconFeature = new ol.Feature({ 83 | geometry: new ol.geom.Point(pos), 84 | city: result.city 85 | }); 86 | vectorSource.addFeature(iconFeature); 87 | }); 88 | 89 | var iconStyle = new ol.style.Style({ 90 | image: new ol.style.Icon(({ 91 | anchor: [0.5, 46], 92 | anchorXUnits: 'fraction', 93 | anchorYUnits: 'pixels', 94 | opacity: 0.75, 95 | src: 'img/icon.png' 96 | })) 97 | }); 98 | 99 | var vectorLayer = new ol.layer.Vector({ 100 | source: vectorSource, 101 | style: iconStyle 102 | }); 103 | map.addLayer(vectorLayer); 104 | 105 | var element = document.getElementById('popup'); 106 | 107 | var popup = new ol.Overlay({ 108 | element: element, 109 | positioning: 'bottom-center', 110 | stopEvent: false 111 | }); 112 | map.addOverlay(popup); 113 | 114 | map.on('click', function(evt) { 115 | var feature = map.forEachFeatureAtPixel(evt.pixel, 116 | function(feature, layer) { 117 | return feature; 118 | }); 119 | 120 | if (feature) { 121 | var geometry = feature.getGeometry(); 122 | var coord = geometry.getCoordinates(); 123 | popup.setPosition(coord); 124 | $(element).popover({ 125 | 'placement': 'top', 126 | 'html': true, 127 | 'content': "

" + feature.get('city') + "

" 128 | }); 129 | $(element).popover('show'); 130 | } else { 131 | $(element).popover('destroy'); 132 | } 133 | }); 134 | 135 | var width = 300, 136 | height = 300, 137 | radius = Math.min(width, height) / 2; 138 | 139 | var color = d3.scale.ordinal() 140 | .range(["#1abc9c", "#16a085", "#2ecc71", "#27ae60", "#4caf50", "#8bc34a", "#cddc39", "#3498db", "#2980b9", "#34495e", "#2c3e50", "#2196f3", "#03a9f4", "#00bcd4", "#009688", "#e74c3c", "#c0392b", "#f44336", "#e67e22", "#d35400", "#f39c12", "#ff9800", "#ff5722", "#ffc107", "#f1c40f", "#ffeb3b", "#9b59b6", "#8e44ad", "#9c27b0", "#673ab7", "#e91e63", "#3f51b5", "#795548", "#9e9e9e", "#607d8b", "#7f8c8d", "#95a5a6", "#bdc3c7", "#ecf0f1", "#efefef"]); 141 | 142 | var arc = d3.svg.arc() 143 | .outerRadius(radius - 10) 144 | .innerRadius(0); 145 | 146 | var pie = d3.layout.pie() 147 | .sort(null) 148 | .value(function(d) { return d.doc_count; }); 149 | 150 | var svg = d3.select("body").append("svg") 151 | .attr("width", width) 152 | .attr("height", height) 153 | .append("g") 154 | .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); 155 | 156 | var citys = results.aggregations[2].buckets; 157 | citys.forEach(function(city) { 158 | city.doc_count = +city.doc_count; 159 | }); 160 | 161 | var g = svg.selectAll(".arc") 162 | .data(pie(citys)) 163 | .enter().append("g") 164 | .attr("class", "arc"); 165 | 166 | g.append("path") 167 | .attr("d", arc) 168 | .style("fill", function(city) { return color(city.data.key); }); 169 | 170 | g.append("text") 171 | .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) 172 | .attr("dy", ".35em") 173 | .style("text-anchor", "middle") 174 | .text(function(d) { return d.data.key; }); 175 | 176 | }); -------------------------------------------------------------------------------- /view/styles/main.css: -------------------------------------------------------------------------------- 1 | svg { 2 | position: absolute; 3 | left: 0px; 4 | top: 0px; 5 | 6 | z-index: 100; 7 | } -------------------------------------------------------------------------------- /view/styles/ol.css: -------------------------------------------------------------------------------- 1 | .ol-mouse-position{top:8px;right:8px;position:absolute}.ol-scale-line{background:#95b9e6;background:rgba(0,60,136,.3);border-radius:4px;bottom:8px;left:8px;padding:2px;position:absolute}.ol-scale-line-inner{border:1px solid #eee;border-top:none;color:#eee;font-size:10px;text-align:center;margin:1px;will-change:contents,width}.ol-overlay-container{will-change:left,right,top,bottom}.ol-unsupported{display:none}.ol-viewport .ol-unselectable{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ol-control{position:absolute;background-color:#eee;background-color:rgba(255,255,255,.4);border-radius:4px;padding:2px}.ol-control:hover{background-color:rgba(255,255,255,.6)}.ol-zoom{top:.5em;left:.5em}.ol-rotate{top:.5em;right:.5em;transition:opacity .25s linear,visibility 0s linear}.ol-rotate.ol-hidden{opacity:0;visibility:hidden;transition:opacity .25s linear,visibility 0s linear .25s}.ol-zoom-extent{top:4.643em;left:.5em}.ol-full-screen{right:.5em;top:.5em}@media print{.ol-control{display:none}}.ol-control button{display:block;margin:1px;padding:0;color:#fff;font-size:1.14em;font-weight:700;text-decoration:none;text-align:center;height:1.375em;width:1.375em;line-height:.4em;background-color:#7b98bc;background-color:rgba(0,60,136,.5);border:none;border-radius:2px}.ol-control button::-moz-focus-inner{border:none;padding:0}.ol-zoom-extent button{line-height:1.4em}.ol-compass{display:block;font-weight:400;font-size:1.2em;will-change:transform}.ol-touch .ol-control button{font-size:1.5em}.ol-touch .ol-zoom-extent{top:5.5em}.ol-control button:focus,.ol-control button:hover{text-decoration:none;background-color:#4c6079;background-color:rgba(0,60,136,.7)}.ol-zoom .ol-zoom-in{border-radius:2px 2px 0 0}.ol-zoom .ol-zoom-out{border-radius:0 0 2px 2px}.ol-attribution{text-align:right;bottom:.5em;right:.5em;max-width:calc(100% - 1.3em)}.ol-attribution ul{margin:0;padding:0 .5em;font-size:.7rem;line-height:1.375em;color:#000;text-shadow:0 0 2px #fff}.ol-attribution li{display:inline;list-style:none;line-height:inherit}.ol-attribution li:not(:last-child):after{content:" "}.ol-attribution img{max-height:2em;max-width:inherit}.ol-attribution button,.ol-attribution ul{display:inline-block}.ol-attribution.ol-collapsed ul{display:none}.ol-attribution.ol-logo-only ul{display:block}.ol-attribution:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-attribution.ol-uncollapsible{bottom:0;right:0;border-radius:4px 0 0;height:1.1em;line-height:1em}.ol-attribution.ol-logo-only{background:0 0;bottom:.4em;height:1.1em;line-height:1em}.ol-attribution.ol-uncollapsible img{margin-top:-.2em;max-height:1.6em}.ol-attribution.ol-logo-only button,.ol-attribution.ol-uncollapsible button{display:none}.ol-zoomslider{position:absolute;top:4.5em;left:.5em;background:#eee;background:rgba(255,255,255,.4);width:24px;height:200px}.ol-zoomslider-thumb{position:absolute;background:#7b98bc;background:rgba(0,60,136,.5);border-radius:2px;cursor:pointer;height:10px;width:22px;margin:3px}.ol-touch .ol-zoomslider{top:5.5em;width:2.052em}.ol-touch .ol-zoomslider-thumb{width:1.8em}.ol-overviewmap{position:absolute;left:.5em;bottom:.5em}.ol-overviewmap.ol-uncollapsible{bottom:0;left:0;border-radius:0 4px 0 0}.ol-overviewmap .ol-overviewmap-map,.ol-overviewmap button{display:inline-block}.ol-overviewmap .ol-overviewmap-map{border:1px solid #7b98bc;height:150px;margin:2px;width:150px}.ol-overviewmap:not(.ol-collapsed) button{bottom:1px;left:2px;position:absolute}.ol-overviewmap.ol-collapsed .ol-overviewmap-map,.ol-overviewmap.ol-uncollapsible button{display:none}.ol-overviewmap:not(.ol-collapsed){background:rgba(255,255,255,.8)}.ol-overviewmap-box{border:2px dotted rgba(0,60,136,.7)} -------------------------------------------------------------------------------- /view/test/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /view/test/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "view", 3 | "private": true, 4 | "dependencies": { 5 | "chai": "~1.8.0", 6 | "mocha": "~1.14.0" 7 | }, 8 | "devDependencies": {} 9 | } 10 | -------------------------------------------------------------------------------- /view/test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Mocha Spec Runner 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /view/test/spec/test.js: -------------------------------------------------------------------------------- 1 | /* global describe, it */ 2 | 3 | (function () { 4 | 'use strict'; 5 | 6 | describe('Give it some context', function () { 7 | describe('maybe a bit more context here', function () { 8 | it('should run here few assertions', function () { 9 | 10 | }); 11 | }); 12 | }); 13 | })(); 14 | --------------------------------------------------------------------------------