Commits

Sean Wilkinson committed e2fa1ea

Added a world map of QM API usage (currently from static JSON file)

Comments (0)

Files changed (4)

 #   Thanks for stopping by :-)
 #
 #                                                       ~~ (c) SRW, 06 Feb 2012
-#                                                   ~~ last updated 31 Aug 2013
+#                                                   ~~ last updated 12 Sep 2013
 
 PROJ_ROOT   :=  $(realpath $(dir $(firstword $(MAKEFILE_LIST))))
 
         favicon.ico                                                         \
         fluidicon.png                                                       \
         giant-favicon.ico                                                   \
+        hits-by-country.json                                                \
         homepage.js                                                         \
         html5shiv.js                                                        \
         icon-128.png                                                        \
 $(CACHE_DIR)/coffeescript.js: | $(CACHE_DIR)
 	@   $(call download-url, "http://goo.gl/2RqIb")
 
+$(CACHE_DIR)/hits-by-country.json:                                          \
+    $(SRC_DIR)/browser-client/hits-by-country.json                          \
+    | $(CACHE_DIR)
+	@   $(CP) $< $@
+
 $(CACHE_DIR)/homepage.js:                                                   \
     $(CACHE_DIR)/jquery-191.js                                              \
     $(CACHE_DIR)/bootstrap.js                                               \
     $(CACHE_DIR)/main.js                                                    \
+    $(CACHE_DIR)/world-map.js                                               \
     |   $(CACHE_DIR)
 	@   $(call replace-url-macros, $^, $@)                          ;   \
             $(call remove-source-maps, $@)
     | $(CACHE_DIR)
 	@   $(call minify-css, $^, $@)
 
+$(CACHE_DIR)/world-map.js: $(SRC_DIR)/browser-client/world-map.js | $(CACHE_DIR)
+	@   $(CP) $< $@
+
 $(ICONS_DIR):
 	@   $(call make-directory, $@)
 

src/browser-client/hits-by-country.json

+[["iso","hits","country"],["MM",0,"Myanmar"],["GU",0,"Guam"],["BQ",0,"Bonaire, Saint Eustatius and Saba"],["MP",0,"Northern Mariana Islands"],["ST",0,"Sao Tome and Principe"],["BL",0,"Saint Barthelemy"],["AS",0,"American Samoa"],["GW",0,"Guinea-Bissau"],["NR",0,"Nauru"],["CC",0,"Cocos (Keeling) Islands"],["FO",0,"Faroe Islands"],["PN",0,"Pitcairn Islands"],["TM",0,"Turkmenistan"],["TF",0,"French Southern Territories"],["TO",0,"Tonga"],["NU",0,"Niue"],["KI",0,"Kiribati"],["PW",0,"Palau"],["SR",0,"Suriname"],["TL",0,"Timor-Leste"],["LK",0,"Sri Lanka"],["SV",0,"El Salvador"],["GF",0,"French Guiana"],["HT",0,"Haiti"],["AD",0,"Andorra"],["TT",0,"Trinidad and Tobago"],["BN",0,"Brunei Darussalam"],["ER",0,"Eritrea"],["VU",0,"Vanuatu"],["SB",0,"Solomon Islands"],["PF",0,"French Polynesia"],["PY",0,"Paraguay"],["KN",0,"Saint Kitts and Nevis"],["PM",0,"Saint Pierre and Miquelon"],["AI",0,"Anguilla"],["AW",0,"Aruba"],["WS",0,"Samoa"],["AQ",0,"Antarctica"],["IO",0,"British Indian Ocean Territory"],["KY",0,"Cayman Islands"],["CR",0,"Costa Rica"],["CK",0,"Cook Islands"],["GL",0,"Greenland"],["KM",0,"Comoros"],["DJ",0,"Djibouti"],["MS",0,"Montserrat"],["SS",0,"South Sudan"],["BI",0,"Burundi"],["SH",0,"Saint Helena"],["CF",0,"Central African Republic"],["FK",0,"Falkland Islands (Malvinas)"],["NE",0,"Niger"],["SO",0,"Somalia"],["SL",0,"Sierra Leone"],["BF",0,"Burkina Faso"],["GP",0,"Guadeloupe"],["GT",0,"Guatemala"],["GN",0,"Guinea"],["SJ",0,"Svalbard and Jan Mayen"],["UY",0,"Uruguay"],["FM",0,"Micronesia, Federated States of"],["LS",0,"Lesotho"],["MZ",0,"Mozambique"],["CX",0,"Christmas Island"],["UG",0,"Uganda"],["MF",0,"Saint Martin"],["RW",0,"Rwanda"],["CV",0,"Cape Verde"],["NI",0,"Nicaragua"],["BT",0,"Bhutan"],["GS",0,"South Georgia and the South Sandwich Islands"],["BW",0,"Botswana"],["ML",0,"Mali"],["MW",0,"Malawi"],["CM",0,"Cameroon"],["CI",0,"Cote D'Ivoire"],["MG",0,"Madagascar"],["SX",0,"Sint Maarten (Dutch part)"],["EH",0,"Western Sahara"],["TZ",0,"Tanzania, United Republic of"],["LR",0,"Liberia"],["DM",0,"Dominica"],["EG",0,"Egypt"],["NG",0,"Nigeria"],["CD",0,"Congo, The Democratic Republic of the"],["SC",0,"Seychelles"],["GG",0,"Guernsey"],["MT",0,"Malta"],["LU",0,"Luxembourg"],["EC",0,"Ecuador"],["GD",0,"Grenada"],["VE",0,"Venezuela"],["HR",0,"Croatia"],["CO",0,"Colombia"],["DK",0,"Denmark"],["IE",0,"Ireland"],["CW",0,"Curacao"],["TG",0,"Togo"],["JO",0,"Jordan"],["BM",0,"Bermuda"],["SD",0,"Sudan"],["PE",0,"Peru"],["NC",0,"New Caledonia"],["BZ",0,"Belize"],["KW",0,"Kuwait"],["WF",0,"Wallis and Futuna"],["GR",0,"Greece"],["TK",0,"Tokelau"],["AU",0,"Australia"],["FJ",0,"Fiji"],["ZW",0,"Zimbabwe"],["TN",0,"Tunisia"],["BD",0,"Bangladesh"],["ZA",0,"South Africa"],["NF",0,"Norfolk Island"],["GM",0,"Gambia"],["PG",0,"Papua New Guinea"],["NP",0,"Nepal"],["SM",0,"San Marino"],["MU",0,"Mauritius"],["CZ",0,"Czech Republic"],["ID",0,"Indonesia"],["CL",0,"Chile"],["MN",0,"Mongolia"],["ET",0,"Ethiopia"],["VI",0,"Virgin Islands, U.S."],["BJ",0,"Benin"],["ZM",0,"Zambia"],["PR",0,"Puerto Rico"],["NA",0,"Namibia"],["MX",0,"Mexico"],["TR",0,"Turkey"],["DO",0,"Dominican Republic"],["LA",0,"Lao People's Democratic Republic"],["AM",0,"Armenia"],["PA",0,"Panama"],["MH",0,"Marshall Islands"],["RS",0,"Serbia"],["MO",0,"Macau"],["MQ",0,"Martinique"],["RO",0,"Romania"],["SZ",0,"Swaziland"],["BY",0,"Belarus"],["IM",0,"Isle of Man"],["YE",0,"Yemen"],["FR",0,"France"],["VG",0,"Virgin Islands, British"],["TD",0,"Chad"],["AE",0,"United Arab Emirates"],["FI",0,"Finland"],["LV",0,"Latvia"],["GY",0,"Guyana"],["SK",0,"Slovakia"],["KG",0,"Kyrgyzstan"],["DE",0,"Germany"],["BA",0,"Bosnia and Herzegovina"],["MK",0,"Macedonia"],["PL",0,"Poland"],["SA",0,"Saudi Arabia"],["EE",0,"Estonia"],["AR",0,"Argentina"],["SI",0,"Slovenia"],["VN",0,"Vietnam"],["RE",0,"Reunion"],["TC",0,"Turks and Caicos Islands"],["CG",0,"Congo"],["ME",0,"Montenegro"],["IN",0,"India"],["PK",0,"Pakistan"],["BG",0,"Bulgaria"],["CU",0,"Cuba"],["IS",0,"Iceland"],["A2",0,"Satellite Provider"],["KE",0,"Kenya"],["AG",0,"Antigua and Barbuda"],["KZ",0,"Kazakhstan"],["BR",0,"Brazil"],["VA",0,"Holy See (Vatican City State)"],["GI",0,"Gibraltar"],["AO",0,"Angola"],["AP",0,"Asia/Pacific Region"],["GH",0,"Ghana"],["JE",0,"Jersey"],["HK",0,"Hong Kong"],["MV",0,"Maldives"],["PS",0,"Palestinian Territory"],["BE",0,"Belgium"],["OM",0,"Oman"],["HU",0,"Hungary"],["AL",0,"Albania"],["PT",0,"Portugal"],["CH",0,"Switzerland"],["HN",0,"Honduras"],["AZ",0,"Azerbaijan"],["VC",0,"Saint Vincent and the Grenadines"],["AX",0,"Aland Islands"],["GE",0,"Georgia"],["QA",0,"Qatar"],["AF",0,"Afghanistan"],["MA",0,"Morocco"],["NZ",0,"New Zealand"],["CN",0,"China"],["KR",0,"Korea, Republic of"],["IT",0,"Italy"],["CA",0,"Canada"],["SE",0,"Sweden"],["GB",0,"United Kingdom"],["TH",0,"Thailand"],["DZ",0,"Algeria"],["MY",0,"Malaysia"],["UM",0,"United States Minor Outlying Islands"],["LY",0,"Libya"],["CY",0,"Cyprus"],["GQ",0,"Equatorial Guinea"],["BO",0,"Bolivia"],["BS",0,"Bahamas"],["AT",0,"Austria"],["KH",0,"Cambodia"],["NL",0,"Netherlands"],["TJ",0,"Tajikistan"],["UZ",0,"Uzbekistan"],["IQ",0,"Iraq"],["PH",0,"Philippines"],["JM",0,"Jamaica"],["NO",0,"Norway"],["IR",0,"Iran, Islamic Republic of"],["BH",0,"Bahrain"],["LB",0,"Lebanon"],["UA",0,"Ukraine"],["SG",0,"Singapore"],["LI",0,"Liechtenstein"],["TV",0,"Tuvalu"],["IL",0,"Israel"],["MC",0,"Monaco"],["MR",0,"Mauritania"],["SY",0,"Syrian Arab Republic"],["LC",0,"Saint Lucia"],["ES",0,"Spain"],["SN",0,"Senegal"],["LT",0,"Lithuania"],["KP",0,"Korea, Democratic People's Republic of"],["TW",0,"Taiwan"],["RU",0,"Russian Federation"],["BB",0,"Barbados"],["GA",0,"Gabon"],["YT",0,"Mayotte"],["US",0,"United States"],["JP",0,"Japan"],["MD",0,"Moldova, Republic of"]]

src/browser-client/index.html

 <!--
     index.html ~~
                                                         ~~ (c) SRW, 20 Nov 2012
-                                                    ~~ last updated 16 Aug 2013
+                                                    ~~ last updated 12 Sep 2013
 -->
 <!--[if IE]><![endif]-->
 <html lang="en">
     <script src="html5shiv.js"></script>
   <![endif]-->
 
+  <!-- Le Google Visualization API -->
+    <script src="https://www.google.com/jsapi"></script>
+    <script>
+        google.load('visualization', '1', {'packages': ['geochart']});
+    </script>
+
   <!--[if IE]>
     <link rel="shortcut icon" href="giant-favicon.ico">
   <![endif]-->
         </div>
       </div>
       <hr>
+      <div id="world-map" style="width: 100%"></div>
+      <div class="centered">
+        <h2>World-Wide Computing</h2>
+        Since April 2013, QMachine's API server has received more than 1.3
+        million calls from visitors representing more than 80 countries!
+      </div>
+      <hr>
     </div>
 
     <footer class="footer">

src/browser-client/world-map.js

+//- JavaScript source code
+
+//- world-map.js ~~
+//                                                      ~~ (c) SRW, 11 Sep 2013
+//                                                  ~~ last updated 12 Sep 2013
+
+(function () {
+    'use strict';
+
+ // Pragmas
+
+    /*global $: false, google: false */
+
+    /*jslint browser: true, devel: true, indent: 4, maxlen: 80 */
+
+ // Declarations
+
+    var convert_to_rank, get_data, main, options, sync_country_names;
+
+ // Definitions
+
+    convert_to_rank = function (x) {
+     // This function sorts the input data from greatest to least by hits and
+     // assigns a rank to each row as that row's index in the sorted dataset.
+     // Currently, this function does not attempt to note ties, but I plan to
+     // add that at the same time that I begin providing country codes for the
+     // countries that have not recorded any hits yet.
+        var i, n, ranks, temp, y;
+        ranks = {};
+        temp = x.slice(1).sort(function (a, b) {
+         // This function needs documentation.
+            return (a[1] < b[1]) ? 1 : -1;
+        });
+        n = temp.length;
+        for (i = 0; i < n; i += 1) {
+            if (ranks.hasOwnProperty(temp[i][1]) === false) {
+                ranks[temp[i][1]] = i + 1;
+            }
+        }
+        y = [['Country', 'Rank', 'Hits']];
+        for (i = 0; i < n; i += 1) {
+            y[i + 1] = [temp[i][0], ranks[temp[i][1]], temp[i][1]];
+        }
+        return y;
+    };
+
+    get_data = function (callback) {
+     // This function just wraps a bare AJAX call and provides a callback
+     // interface. I will wrap it with a `jQuery.ajax` call as soon as their
+     // documentation site comes back online ...
+        var req = new XMLHttpRequest();
+        req.onreadystatechange = function () {
+         // This function needs documentation.
+            if (req.readyState === 4) {
+                if (req.status === 200) {
+                    callback(null, JSON.parse(req.responseText));
+                } else {
+                    callback(new Error(req.statusText), null);
+                }
+            }
+            return;
+        };
+        req.open('GET', '/hits-by-country.json' + location.search, true);
+        req.setRequestHeader('Content-Type', 'application/json');
+        req.send(null);
+        return;
+    };
+
+    main = function () {
+     // This function needs documentation.
+        var geochart = new google.visualization.GeoChart($('#world-map')[0]);
+        get_data(function (err, data) {
+         // This function needs documentation.
+            if (err !== null) {
+                console.error('Error:', err);
+                return;
+            }
+            var sorted, table;
+            sorted = convert_to_rank(data);
+            table = google.visualization.arrayToDataTable(sorted);
+            sync_country_names(data, table);
+            geochart.draw(table, options);
+         /*
+            if (location.search !== '?stale_ok=false') {
+                $('#big-container')
+                    .append('<a href="?stale_ok=false">view latest</a>');
+            }
+         */
+            return;
+        });
+        return;
+    };
+
+    options = {
+        backgroundColor: '#428BCA', // '#5592CC'
+        colorAxis: {
+            colors: [
+             // These are "stolen" from the "rworldmap" package.
+                '#00441B', '#006D2C', '#238B45', '#41AB5D', '#74C476',
+                '#A1D99B', '#C7E9C0', 'white'
+            ]
+        },
+        legend: 'none'
+    };
+
+    sync_country_names = function (data, table) {
+     // This function hacks the Google Visualization API itself by attempting
+     // to deduce which jacked-up property name of the table object actually
+     // corresponds to the property that contains the row data. We can't rely
+     // on a certain property name to reference the row data because Google
+     // minifies things in an effort to keep us all *out*.
+     //
+     // NOTE: This function mutates `table` in-place by taking advantage of the
+     // fact that JavaScript passes objects by reference.
+     //
+        var key, i, j, m, n, x;
+        m = data.length - 1;
+        n = data.length;
+        for (key in table) {
+            if ((table.hasOwnProperty(key)) && (table[key] instanceof Array)) {
+                if (table[key].length === m) {
+                    x = table[key];
+                }
+            }
+        }
+        for (i = 0; i < m; i += 1) {
+            for (j = 1; j < n; j += 1) {
+             // The `f` and `v` properties seem to be part of the API, and they
+             // appear to stand for "format" and "value" ...
+                if (x[i].c[0].v === data[j][0]) {
+                    x[i].c[0].f = data[j][2];
+                }
+            }
+        }
+        return;
+    };
+
+ // Invocations
+
+    //google.load('visualization', '1', {'packages': ['geochart']});
+    google.setOnLoadCallback(main);
+
+ // That's all, folks!
+
+    return;
+
+}());
+
+//- vim:set syntax=javascript: