Monday, June 24, 2013

RevoltDC Hackathon 20130622

Tools I tried for this hackathon [http://www.revoltdc.com/] Saturday, June 22, 2013 from 8:00 AM to 7:00 PM (EDT) Washington, DC
  • https://github.com/zenkay/d3-cloud-simplified
  • Meteor JS, packages D3,jquery, jquery-ui

There are two parts to this, one part coding, the other part story.

The coding

Well to update things, I wasn't able to actually able to add it to the repo for the hackathon so up with the buzzer code here

There are a few components here I'll go over briefly. The first is meteor router.

Meteor Router

View the how the router worked at the time by clicking here and reviewing the example js file

Now if you've been following local trends, routing is sort of being handled on client and server. In meteor, sometimes client code is treated more or less as a stub. However, routing seems like it can be mostly superfiscial; the server may only need to know when it needs to run code that processes variables or needs to call methods - or so it seems. Given that atmosphere (meteorite) packages don't have tons of documentation at this time we have to infer a lot. I am still busy inferring and may have to do some code diving on this one. Eventedmind has a simplepages version they go over, and that version is well explained in the video.

Why the router? Well it affords me the opportunity to try different things on different URLs

So now let's go through what I did with the router.

Meteor.Router.add
    '/test':'somedata',
    '/nice/:query': (query)->
            Meteor.call("checkSunlight",query,
                (err,res)->
                    Session.set("result",res)
            )
            return "nice"
    '/capitol/:query': (query)->
            Meteor.call("checkCapitolWords", query,
                (err,res)->
                    console.log("test")
                    Session.set("result",res)
            )
            return "capitol"

To quickly explain, the code above is located under the Client/Client.coffee file. This means that it is only served to the client.

The first section may be self explanatory, but each '/<blah>' is what is parsed from the url and that in turn gets routed through a javascript function - which, on return will render the template of the string returned. I believe the function may also allow a call to a Meteor.<mytemplate>.render function directly, but I'd have to test that. The latter portion is the function or string used to identify the template to render. it is inside here that I use Meteor.call to call specially crafted asynchronous calls to the server [which in turn fire asynchronous calls to Sunlight]

Our routable template

We have our templates defined below


  revoltdc_hackthon20130622 -  {{title}}
   
    
    



  {{renderPage}}





Note here that I was trying to call the D3 cloud libraries in a hacky way when the buzzer went. Just trying to make things work before making them work right. The hello world template comes out of box, I was in a hurry so I left it.

Meteor methods - or the way to do Ajax in meteor

The sunlight api is pretty nifty. Free to use, you can get a key and try it out right off their website. I'd encourage you to take a gander to understand the few methods here.

Meteor.Router.add
    '/test':'somedata'
    
sunlight_api_key = "yourapikey"
        
Meteor.methods 
    checkSunlight: (query) ->
        @unblock()
        result = Meteor.http.call( "GET","http://congress.api.sunlightfoundation.com/votes",
            params:
                "apikey": sunlight_api_key,
                "query": query      
        )
        console.log( query + " is query")
        if result.statusCode is 200
            resulting = JSON.parse(result.content);
            console.log(resulting)
            return resulting  
        false        
    checkCapitolWords: (query) ->
        @unblock()
        result = Meteor.http.call('GET',"http://congress.api.sunlightfoundation.com/legislators",
            params:
                "apikey": sunlight_api_key,
                "last_name": query      
        )   
        console.log( query + " is query")
        if result.statusCode is 200
           resulting = JSON.parse(result.content); 
           console.log( resulting.results[0].bioguide_id )
           bioguide_id = resulting.results[0].bioguide_id
           capitol_by_leg = Meteor.http.call('GET',"http://capitolwords.org/api/1/phrases.json"
                params:
                    "apikey": sunlight_api_key,
                    "entity_type": "legislator",
                    "entity_value": bioguide_id
           )
           if capitol_by_leg.statusCode is 200
              resulting = JSON.parse(capitol_by_leg.content);  
              resulting.sort (a, b)->
                return b.count - a.count
              console.log(resulting)
              return resulting
            else
                return resulting
        false

So before I had really decided what I would even try to accomplish, I had written the first method. That seemed to work fine and consistent. Now reviewing this code I am beginning to think one of my major oversights was leaving in the

@unblock

code. In retrospect you'll see that the meteor http call to legislators makes a single call in the meteor method checkSunlight, but for two calls, if the javascript isn't blocked, I might not get back the call for that gave me the bioguide id for a legislator - required to get the words they used! What a pity! Fortunately I'll try to use some time to continue this learning experience. In any event, the code was erratic and I would get a forEach error for trying to iterate over an undefined, and by writing this blog I think I just figured out why.

We are back to the client code again, Client.coffee

Trying to get hacky with the head

Still not being clear whether or not I could inject javascript into the header of a rendered template, I wanted to see if I could manipulate the title which explains the following code

Meteor.startup ->
  Meteor.autorun ->
    document.title = Session.get('document-title');

Here the idea is to see if I can manipulate the title dynamically. I abandoned this pretty quick

Creating a method stub

As I understand things, while loading is happening on the back end for a meteor call, the method can have a stub locally on the client, explaining this code

Meteor.methods 
    checkSunlight: (query) ->
        return "Loading"

Now for the last bit

Template.nice.rendered =->
    Session.set("document-title","testing")
    console.log "test"
    "blah"

Template.nice.helpers
        result: ->
            console.log(Session.get("result"))
            return Session.get("result")

Template.capitol.helpers
        result: ->
            console.log(Session.get("result"))
            
            return Session.get("result")
        cloud: ->
            words = Session.get("result")
            console.log words
            scriptn = ""
            return scriptn

So here I have some helpers, these are there to ensure rerendering of the templates happens when the Session variable changes. The meteor session should not be though of as what most web architectures think of it as: rather it is a value key store that is used to track and fire dependencies when they are changed in meteor [RTFM ;-) ].

In the cloud helper I am trying to force rerending and create a cloud with D3. Unfortunately it was a bust.

The story

How never to win a hackathon

I rolled into this hackathon with less than five hours left where most folks had 10. Why did I bother?

Hackathons are marginally about code. Some people come to hack and learn. I came with a guest, I came to hack and learn, but only a small amount of working code is actually needed. However, to assume that hacking and learning is the point is a fallacy. The point is ideas and proof of concept.

For example, one big winner wrote some good code, but for the latter portion of the exercise showed an animation for voting where the votes would drive two cars forward. According to an observer, the animation was not actually coded. It was hypothetical according to this observer; no more than an animation. In addition, two MBAs with no coders merely demonstrated a clever use of a tool and walked away with a prize. In the end, I believe these people deserved their prizes. They showed enough of a bright idea to win.

So to win, focus on proof of concept, originality, design and selling the idea are as important as writing some hard demo code. If something isn't working, mock it and move on. You should have some real working parts, but its as important to demonstrate all of the aforementioned attributes as to have some marginal amount of code to make things demo-able.

Now the way not to win is to explain data without a visualization. That was me, eyes frost really quickly when you don't have a visualization to go with that data.

Thing is, I did this to learn more about meteor, and for my guest to learn why I hack and to see the ideas coming to life. My guest was very impressed, and for me that was more important than anything.

A Harvard MBA, breaking all the obvious rules (there was a 3 slide limit, she used around 20 with a very prepared presentation, they used well over five minutes and not much real workings were shown) and took the grand prize with her team. Again, here, I don't want you to get the wrong understanding; it's the ideas that count, not the superficial nature of the demo. The thing is, my ideas really inspired a select but important few in the crowd. I walked away with a number of business cards. To a contractor, which do you think is more valuable?

So my point is not winning at a hackathon is just as important as winning one. You should always play at least one song only a master of your instrument will comprehend and appreciate; not that this crappy code does any of that per say; I'd just like to think the vision I put forward worked out ;-).

Some of the folks that approached me gave me ideas, and I'd like to try to find time to implement them - so I'll give it a whirl here.

Understanding this blog

This is a blog about failure and success. I put failure forward here, because in software, creating good software and gaining experience is all about failure first and foremost.

Too often a hot new technology comes out claiming it is the best thing since array slice.  People show you it working claiming the code takes just a few minutes and BAM - you get an amazing functional system in five minutes.

This approach is the opposite of most blogs I have seen, it is about learning to code in different environments and finding the challenges and limits of the systems. This blog itself is an experiment; let's see how it goes.

Hacking a calendar with meteor [Iteration 8] {Fail: unstable}

We call this iteration a failure:

  • Data from the publishing mechanism doesn't want to push properly
  • Get inconsistent errors for my Collection variables

This document is about meteor version 0.6.3, code is in coffeescript

I am not sure if the tabs below will work until I publish, we'll see and apologies if it doesn't work.

Templates and CSS

I am keeping nothing in this directory except templates and CSS and a model.coffee file

CoffeeScript with server stuff

This directory has server code, in this case one file

  • Planner.js

Public

An ico file

Server

A file containing publish code

Packages

Meteorite packages: fullcalendar, jquery, jquery-ui, router

In Planner.js file under the client directory:

eventdata = (start,end,callback)-> 
    #I am setting the object event using a session key
    #session keys are "reactive", ie they should trigger the function to change
    docs = Session.get "docs"
    console.log "Got docs" 
    if docs
        #I am mapping this because I want specific elements for the calendar
        #You may not need to do it this way, for example, you can publish a specific data set (in theory)
        formatted_docs = docs.map (item)->
            { title: item.title, start:item.start,end:item.end }
        console.log formatted_docs
        callback formatted_docs


#because javascript calls functions, which may become modified at the last
#moment, our session var creates a trigger to re-render and our eventdata function changes
#so rendering the template gets called with the new eventdata     
Template.calendar.rendered = ->
 $('#calendar').fullCalendar
        dayClick: daycallback
        events: eventdata
        header: 
            left: 'prev,next today',
            center: 'title',
            right: 'month,basicWeek,basicDay' 
 return ""

Now I've been updating this since having moved on, but I could never quite get the publish code working right. In principle meteor serves up client and server stuff separately if they are under the respective directory. Now my model.coffee file was in the base directory, but even though the only call I have in there is the Collection which should (and is) utilized by both client and server, the client would never be able to find this variable if it is held in a different file. This was a very curious issue for which I haven't yet found resolution.