Refactoring and dependency fixes
diff --git a/asterix-examples/src/main/resources/black-cherry/README.md b/asterix-examples/src/main/resources/black-cherry/README.md
index 22a3dca..84a8123 100755
--- a/asterix-examples/src/main/resources/black-cherry/README.md
+++ b/asterix-examples/src/main/resources/black-cherry/README.md
@@ -6,12 +6,12 @@
A running, local AsterixDB instance (via Managix), of the latest master version.
http://asterix.ics.uci.edu/documentation/install.html
-Python Requests Library
-http://docs.python-requests.org/en/latest/user/install/#install
+Please note that previous versions of this demo required Python's requests library.
+This dependency is no longer in place.
## Steps
-0. Install Python Requests, if you have not already
+0. Run your local AsterixDB instance via Managix.
1. Go to the top level of this demo and run
$ python run_black_cherry.py
diff --git a/asterix-examples/src/main/resources/black-cherry/run_black_cherry.py b/asterix-examples/src/main/resources/black-cherry/run_black_cherry.py
index f461934..d78514b 100755
--- a/asterix-examples/src/main/resources/black-cherry/run_black_cherry.py
+++ b/asterix-examples/src/main/resources/black-cherry/run_black_cherry.py
@@ -1,9 +1,8 @@
import black_cherry_bootstrap
-import requests
-from bottle import route, run, template, get, debug, static_file, request, response
-
-debug(True)
-http_header = { "content-type": "application/json" }
+from urllib2 import URLError, urlopen
+from urllib import urlencode
+from json import loads, dumps
+from bottle import route, run, template, static_file, request
# Core Routing
@route('/')
@@ -17,11 +16,38 @@
# API Helpers
def build_response(endpoint, data):
api_endpoint = "http://localhost:19002/" + endpoint
- response = requests.get(api_endpoint, params=data, headers=http_header)
+
try:
- return response.json();
- except ValueError:
- return []
+ # Encode data into url string
+ urlresponse = urlopen(api_endpoint + '?' + urlencode(data))
+
+ # There are some weird bits passed in from the Asterix JSON.
+ # We will remove them here before we pass the result string
+ # back to the frontend.
+ urlresult = ""
+ CHUNK = 16 * 1024
+ while True:
+ chunk = urlresponse.read(CHUNK)
+ if not chunk: break
+ urlresult += chunk
+ urlresult = ','.join(urlresult.split(']}{"results":['))
+
+ # Create JSON dump of resulting response
+ return loads(urlresult)
+
+ except ValueError, e:
+ pass
+
+ except URLError, e:
+
+ # Here we report possible errors in request fulfillment.
+ if hasattr(e, 'reason'):
+ print 'Failed to reach a server.'
+ print 'Reason: ', e.reason
+
+ elif hasattr(e, 'code'):
+ print 'The server couldn\'t fulfill the request.'
+ print 'Error code: ', e.code
# API Endpoints
@route('/query')
@@ -45,4 +71,4 @@
return (build_response("update", dict(request.query)))
res = black_cherry_bootstrap.bootstrap()
-run(host='localhost', port=8080, debug=True)
+run(host='localhost', port=8080, debug=True)
\ No newline at end of file
diff --git a/asterix-examples/src/main/resources/black-cherry/static/js/cherry.js b/asterix-examples/src/main/resources/black-cherry/static/js/cherry.js
index aa7a3d1..b187d38 100755
--- a/asterix-examples/src/main/resources/black-cherry/static/js/cherry.js
+++ b/asterix-examples/src/main/resources/black-cherry/static/js/cherry.js
@@ -530,29 +530,39 @@
var minWeight = Number.MAX_VALUE;
// Parse resulting JSON objects. Here is an example record:
- // { "cell": { rectangle: [{ point: [22.5, 64.5]}, { point: [24.5, 66.5]}]}, "count": { int64: 5 }}
+ // { "cell": rectangle("21.5,-98.5 24.5,-95.5"), "count": 78i64 }
$.each(res.results, function(i, data) {
-
- // First, parse a JSON object from a cleaned up string.
- var record = $.parseJSON(cleanJSON(data));
-
- // Parse Coordinates and Weights into a record
- var sw = record.cell.rectangle[0].point;
- var ne = record.cell.rectangle[1].point;
-
+
+ // We need to clean the JSON a bit to parse it properly in javascript
+ var cleanRecord = $.parseJSON(data
+ .replace('rectangle(', '')
+ .replace(')', '')
+ .replace('i64', ''));
+
+ var recordCount = cleanRecord["count"];
+ var rectangle = cleanRecord["cell"]
+ .replace(' ', ',')
+ .split(',')
+ .map( parseFloat );
+
+ // Now, using the record count and coordinates, we can create a
+ // coordinate system for this spatial cell.
var coordinate = {
- "latSW" : sw[0],
- "lngSW" : sw[1],
- "latNE" : ne[0],
- "lngNE" : ne[1],
- "weight" : record.count.int64
- }
+ "latSW" : rectangle[0],
+ "lngSW" : rectangle[1],
+ "latNE" : rectangle[2],
+ "lngNE" : rectangle[3],
+ "weight" : recordCount
+ };
+ // We track the minimum and maximum weight to support our legend.
maxWeight = Math.max(coordinate["weight"], maxWeight);
minWeight = Math.min(coordinate["weight"], minWeight);
+
+ // Save completed coordinate and move to next one.
coordinates.push(coordinate);
});
-
+
triggerUIUpdate(coordinates, maxWeight, minWeight);
}
@@ -877,8 +887,8 @@
.ReturnClause({
"tweetId" : "$m.tweetid",
"tweetText" : "$t.message-text",
- "tweetLoc" : "$t.sender-location",
- "tweetCom" : "$m.comment-text"
+ "tweetCom" : "$m.comment-text",
+ "tweetLoc" : "$t.sender-location"
});
APIqueryTracker = {
@@ -894,44 +904,46 @@
// Parse out tweet Ids, texts, and locations
var tweets = [];
- al = 1;
+ var al = 1;
+
$.each(res.results, function(i, data) {
- var json = $.parseJSON(cleanJSON(data));
+ // First, clean up the data
+ //{ "tweetId": "100293", "tweetText": " like at&t the touch-screen is amazing", "tweetLoc": point("31.59,-84.23") }
+ // We need to turn the point object at the end into a string
+ var json = $.parseJSON(data
+ .replace(': point(',': ')
+ .replace(') }', ' }'));
+ // Now, we construct a tweet object
var tweetData = {
- "tweetEntryId" : json["tweetId"],
- "tweetText" : json["tweetText"],
- "tweetLat" : json["tweetLoc"]["point"][0],
- "tweetLng" : json["tweetLoc"]["point"][1]
+ "tweetEntryId" : parseInt(json.tweetId),
+ "tweetText" : json.tweetText,
+ "tweetLat" : json.tweetLoc.split(",")[0],
+ "tweetLng" : json.tweetLoc.split(",")[1]
};
// If we are parsing out tweetbook data with comments, we need to check
// for those here as well.
if (json.hasOwnProperty("tweetCom")) {
- tweetData["tweetComment"] = json["tweetCom"];
+ tweetData["tweetComment"] = json.tweetCom;
}
tweets.push(tweetData)
});
- // Prepare to map the tweets
- var micon = APIqueryTracker["marker_path"];
- APIqueryTracker["markers_data"] = [];
-
// Create a marker for each tweet
$.each(tweets, function(i, t) {
// Create a phone marker at tweet's position
var map_tweet_m = new google.maps.Marker({
position: new google.maps.LatLng(tweets[i]["tweetLat"], tweets[i]["tweetLng"]),
map: map,
- icon: micon,
+ icon: APIqueryTracker["marker_path"],
clickable: true,
});
map_tweet_m["test"] = t;
// Open Tweet exploration window on click
- APIqueryTracker["markers_data"].push(tweets[i]);
google.maps.event.addListener(map_tweet_m, 'click', function (event) {
onClickTweetbookMapMarker(map_tweet_markers[i]["test"]);
});