How I Spent One Day Learning & Coding and Became One of The Finalists in OpenStack Hackathon

OpenStack hosted its very first hackathon ever in Taipei, Taiwan. Of course I was very excited about it and signed up immediately without second thought. Right after signing up, I had a split second for second thoughts and I realized that I had no idea what the heck is OpenStack. Zero idea. Fortunately, I had a dear friend who not only saved my ignorant ___ but also assembled the A team with talents. We worked really well together and next thing we knew, we were one of the finalists and also won the Outstanding Concept Award.

The App

So what did we do? We built a smart decision assisting system that helps decision makers respond to situation better and faster. Why? We did this for large scale applications that handles dramatic data influx. For example, Obamacare website incidents in 2013. We wanted to build a private system that that handles natural disasters by utilizing the ability of cloud computing and dynamic provision to handle large amount to data and traffic and being able to analyze data in real time to provide users valuable information and actions to take regarding to the situation. And to be specific, we wanted to build a location-based system that visualizes analyzed data and provides actionable options for users.

Here is a little Screenshot of the app. The interaction was simply search with a keyword, click on one of the action buttons after clicking the targeted yellow circle.

Screenshot of our app’s UI

Our Approach

Here is how we did it, very generally.

  1. get data from Twitter and data.tainan.gov
  2. process data at backend
  3. present data on a globe map

The TODO List

As the Front End developer on the team, my job was to show data in a map primarily and also take care of the style and interactions of the application.

Because of the nature of hackathon, I knew I did not have time to make a perfect app with clean code and totally functional features. And even if I overlooked the quality of the code, it is still very likely that I may not make it in time. So what I did was to make a checklist of the necessary things I needed to do and once I checked all the boxes, I was done. The list went like this

  • determine which map API to use
  • setup front end structure with AngularJS
  • determine internal APIs for map with backend developers
  • determine internal API structures and make dummy data with backend developers
  • design UI interactions with designer
  • design action buttons
  • add map to index page
  • locate Tainan, Taiwan as center
  • change maps color scheme
  • add search bar
  • bind event handler to search bar input change
  • implement search function for change event handler
  • implement action buttons
  • bind click event handler for showing action buttons
  • implement recursive calls for getting data feed to simulate WebSocket

Once I checked all the boxes, I was done.

Map, What do I do with you

It certainly does not look like a whole lot but I knew I might screw it up because I do not have experience with any map api. Ok, it was still early. I can learn. Google maps APIs seemed like a popular choice and it turned out awesome. All I need was to apply for a key and then I can use the api fairly easy. Good. Since I am using AngularJS as my front end framework, it would be easier if there is a directive that I can use. Then I found this awesome Angular Google Maps open source directive what has good documentations and maintenance record. So, problem solved.

Setup the Project

Since it was a pretty basic project for frontend, I did not have many dependencies. I used npm to manage my dependencies.

package.json:

“dependencies”: { 
“angular”: “^1.5.0”,
“angular-google-maps”: “^2.3.2”,
“angular-resource”: “^1.5.2”,
“angular-route”: “^1.5.2”,
“angular-simple-logger”: “^0.1.7”,
“angular-ui-router”: “^0.2.18”,
“bootstrap”: “^3.3.6”,
“jquery”: “^2.2.2”,
“lodash”: “^4.6.1”
}

Making Dummy Data

To streamline my work on frontend, I had to be independent from the backend. So it was a good idea to discuss with backend developers about what APIs we need and how they should look like and make dummy data for developing before APIs are completed.

We only needed one api that possesses processed data including incidences, locations, and processed messages from twitter and official dataset from Tainan government.

dummy.json

{
"altitude":121.986188607,
"id":"56ed617ca058714630e969df",
"latitude":24.6516383036,
"longitude":121.986188607,
"message":"05:40救出8人(1人送醫)疏散26人(共34人)",
"messages":[{
"altitude":121.986188607,
"id":"56ed617ca058714630e969df",
"latitude":24.6516383036,
"longitude":121.986188607,
"message":"05:40救出8人(1人送醫)疏散26人(共34人)",
"name":"工務局",
"source":"official",
"status":0,
"time_updated":"2016-03-19T14:26:04.114000",
"type":0
}],
"msg_count":1,
"name":"工務局",
"source":"official",
"status":0,
"time_updated":"2016-03-19T14:26:04.114000",
"type":0
}

Battling with Google Maps API

For Map, I had to work on a few things.

  • put google maps on the page
  • add google maps circles to the location from data and indicate magnitudes
  • style google maps

First things first, after setting up AngularJS and the modules I needed, adding map and circles was straightforward.

For adding google map on the page, I simply did

partials/map.html

<ui-gmap-google-map
center="map.center"
zoom="map.zoom"
options="map.options">
</ui-gmap-google-map>

which set the map the the location I provided as center, zoom in, and setup the style with options attribute.

I spent a lot of time dealing with the style. It turns out that styling google maps is a lot of fun and you can basically change how it looks entirely.

The style look like this.

controllers/MapController.js

[
{
"stylers": [
{ "visibility": "simplified" },
{ gamma: 0.5 }
]
},
{
“elementType”: “labels.text”,
“stylers”: [
{ “color”: “#626464” },
{ “visibility”: “off” },
{ “weight”: 0.5}
]
},
{
“elementType”: “labels.icon”,
“stylers”: [
{ “visibility”: “off” }
]
},
{
"featureType": "land",
“elementType”: “geometry”,
"stylers": [{ "color": "#474949" }]
},
{
"featureType": "road",
“elementType”: “geometry”,
"stylers": [{ "color": "#3e3e3e" }]
},
{
“featureType”: “road”,
“elementType”: “labels.text”,
“stylers”: [
{ “visibility”: “on” },
{ “color”: “#616464” }
]
},
{
"featureType": "water",
"stylers": [{ "color": "#3A3C3C"}]
}
];

I thought it would be easy at the beginning but immediately I ran into problems and wasted a lot of time because I did not understand the basic idea of the styling. It looks fairly easy in the example but I made a mistake by trying it out before I really understood it.

The style takes an array of objects, and each object has three attributes. FeatureType, elementType and stylers. FeatureType allows you to identify which component you want to modify. ElementType allows you to specify what aspect of the feature you are targeting. Finally, stylers is where you put your styles in.

Of course, this was a little overwhelming considering the time pressure. Fortunately, I found a great tool called Styled Maps Wizard. It allowed me to specify the things I wanted to style and generate the style code for me.

For the circles, I implemented a get incidences service with $resources to get all the resources by keyword and specified ng-repeat to show the incidence data as circle in the map.

partials/map.html

<ui-gmap-google-map
center="map.center"
zoom="map.zoom"
options="map.options">
<ui-gmap-circle
ng-repeat="i in incidences"
events="{click: showActions,}"
center="{latitude: i.latitude, longitude: i.altitude}"
stroke="circle[i.status].stroke"
fill="circle[i.status].fill"
radius="i.msg_count * 15">
</ui-gmap-circle>
</ui-gmap-google-map>

Adding Action Buttons Click Event

For the click event on the circles, I simply show the buttons in the Path way. Here is a great tutorial on how to make path button animation with push CSS3.

Simulate WebSocket

Finally, we had to make the data update in real time. I did not have enough time to configure socket.io, so I simulated it by calling the get incidences API every three seconds for the demonstration’s sake.

I know. It is ugly. But I am a true believer of my own 1–99 principle, meaning one percent of effort, 99 percent of impact, during the hackathon.

controllers/MapContollers.js

setInterval(function () {
$scope.searchProps.iter++;
Incidences.get({
keyword: $scope.searchProps.keyword,
iter: $scope.searchProps.iter})
.$promise.then(function (res) {
$.extend($scope.incidences, res.objects);
});
}, 3000);
}

Of course, it does not work well but it did successfully create the illusion that the data was real time so I was satisfied.

The Pitch

The live demo went smoothly. The user interface was easy enough to comprehend and effectively conveyed our idea to the judges. We marketed its potential with the fact that it is highly extendable and no restriction to type of industries. As long as the data sources and business logic is provided, we are able to train our analysis unit and provide desired outcome for users.

Judges liked it. We went home with a shiny trophy in our hands.

In case you need a proof