Technology Inventory for Fantasy Golf

Linux - http://en.wikipedia.org/wiki/Linux
Linux was a project for a young college student, Linus Torvalds, back in the early 90s. It is the kernel for an operating system, combined with tools written by GNU, it makes up the GNU/Linux Operating System. The particular flavor of Linux that I use is CentOS 6.3.

Git - http://en.wikipedia.org/wiki/Git_(software)
Git was another project by Linus Torvalds. It is a version control system. Basically I can go back in time if I have to, to see versions of the code, or see where a bug might have been introduced. I can access my code “repository” from anywhere, and make updates to it from anywhere.

HTML5 - http://en.wikipedia.org/wiki/HTML5
Html Version 5 is the markup to display the content in a semantic way.

CSS - http://en.wikipedia.org/wiki/Cascading_Style_Sheets
Combined with HTML, Cascading Style Sheets are what make the site look pretty

Javascript - http://en.wikipedia.org/wiki/JavaScript
Javascript is a programming language that, in this instance, runs in the browser. It enables things like loading the data without having to refresh the page, and showing or hiding parts of the page. It was developed by Netscape back in the mid 90s.

Bootstrap - http://en.wikipedia.org/wiki/Bootstrap_(front-end_framework)
Developed by Twitter, Bootstrap is a front end framework, combining css and javascript. It makes the site look nice without a whole lot of design effort from my end. Programmers don’t do design or make things pretty, but Bootstrap makes it easy for a non-designer to make a professional looking site with minimal effort.

AngularJS - http://en.wikipedia.org/wiki/AngularJS
AngularJS is a Javascript framework written by Google. It doesn’t necessarily add anything that you can’t do with Javascript, it just makes it a whole lot easier to do everything.

MongoDB - http://en.wikipedia.org/wiki/MongoDB
MongoDB is where the Team data is stored. It is a database system which is different from standard “RDBMS” (relational database management systems) in that there’s no schema, and you don’t write SQL to access it. You actually write Javascript in native Mongo, but I am able to access it through Go.


Go (golang) - http://en.wikipedia.org/wiki/Go_(programming_language)
Go is a programming language written by Google. Go is what runs the server. When I ask for the scores from AngularJS, the code written in Go will fetch the data from pgatour.com, grab the data from MongoDB, and compile the data together, calculate, tabulate, sort, etc, and send the data back to the browser. Go was designed by one of the creators of Unix, Ken Thompson, hired by Google to do smart things like this. The syntax of Go is very easy to learn and it makes programming fun and new.

Fantasy Golf Tracking with Node.js, MongoDB, AngularJS, and Bootstrap - Part 2

I'll address this in parts since the first post really didn't cover anything technical, and was just a bunch of screenshots.

MongoDB Implementation

I previously went over the basic data structure for this app in the previous post.  Teams consist of the team name. Tournaments consist of the key, the name, the start and end date, the course name, the par for the course, and the current round. Also, bools for finished and in progress. Then there is the teams players per tournament which I called teamTournament. It also keeps historical records of their total for that tournament. This lead me to be able to build a leaderboard widget, since the lowest score at the end of the season gets a prize.

Tournament Sample Data

> db.tournaments.find().pretty()
{
        "_id" : ObjectId("53a0964d4fcdf5c39c912acd"),
        "key" : "us-open-2014",
        "name" : "U.S. Open",
        "scoresLocation" : "http://www.pgatour.com/data/r/026/leaderboard-v2.json",
        "startDate" : ISODate("2014-06-12T07:00:00Z"),
        "endDate" : ISODate("2014-06-15T19:00:00Z"),
        "latestRound" : 4,
        "inProgress" : false,
        "isFinished" : true,
        "course" : "Pinehurst No. 2",
        "par" : 70
}

Granted, that inProgress and isFinished can be determined real time, but that's ok.

Team Tournament Sample Data

> db.teamTournament.find().pretty()
{
        "_id" : ObjectId("53a2e61ed42498e823000001"),
        "players" : [
                "28259",
                "28087",
                "21209",
                "08075",
                "31202",
                "28486"
        ],
        "teamId" : ObjectId("53a193fc4fcdf5c39c912af7"),
        "tournamentId" : ObjectId("53a20488d7aee2e01b000001"),
        "tournamentTotal" : 1073
}

I used to use DBRef for referencing other collections, but then I found out that unless you don't know at runtime, you should just use ObjectID.  So my ObjectID of 53a19 etc is in the field of teamId, so I know it's a team reference. If it were called "documentId" and I had collections of "images" and "html snippets" and "swf files", then I could use the DBRef, since it could be one of 3 different collections I want to reference. But since I know, MongoDB says it's much more efficient to just use ObjectID references.

Node.js to Access the Database

As for writing code to access this, I use the Node MongoDB Native library for accessing node, and a helper class that I wrote so I'm not writing lots of code to do things that I do frequently. For instance, my code for getting tournaments looks like this:

this.getTournament = function(db, key, callback){
    dbhelp.findOne(db, "tournaments", { key: key }, function(tournament){
        callback(tournament);
    });
}

this.getCurrentTournament = function(db, callback){
    var upcoming = new Date().addDays(3);
    var past = new Date();

    dbhelp.find(db, "tournaments", { "$or": 
            [ 
                { "startDate": { "$lt": upcoming } },  
                { "endDate": { "$lt": past } }
            ] 
        }, null, { startDate: 1 }, function(tournaments){
        if (tournaments != null && tournaments.length > 0){ return callback(tournaments[0]); }
        else return callback(null);
    });
}

this.getTournaments = function(db, year, callback){
    var start = new Date(year, 0, 1);
    var end = new Date(year, 11, 31);

    dbhelp.find(db, "tournaments", { startDate: { "$gt": start }, endDate: { "$lt": end } }, function(tournaments){
        callback(tournaments);
    });
}

So, you can see, not a lot of code for getting a specific tournament, getting the current tournament, and getting all tournaments this year. (Also I've modified the Date prototype to include a .addDays method).

That is some sample code that I've written for this application. It covers the back end. Next up I'll cover the front end, using AngularJS and Bootstrap to make it work well and look great!

Fantasy Golf Tracking with Node.js, MongoDB, AngularJS, and Bootstrap - Part 1

My family and a bunch of friends are in a fantasy golf league together. The rules are pretty straightforward, although probably not standard.

Rules:
1. Pay $50
2. 10 Tournaments that span the PGA Tour season.
3. Pick 6 golfers before the first tee times on Thursday typically.
4. 4 lowest scores are added and that's your score for each day.
5. If 3 of your players miss the cut, you are assigned the worst score at the end of round 3, pretty much destroying your chance to win.
6. Lowest score wins. $50 payoff for majors (Masters, US Open, British Open, PGA Championship), $25 for the other tournaments.

My brother Pat is the score keeper and chairman of the league. The data collection and reporting was pretty much done in Excel.  This is a fine method for doing such things. The scores would be emailed out along with entertaining commentary.

But then it was my turn to do the data since Pat was going to Boston for the US Open weekend to visit some friends.

Excel was not a viable solution.

I happened to stumble on the PGA Tour Leaderboard website. I noticed that the data is loading in asynchronously, which could only mean AJAX. The question was, which format, and what data is available?

The answer was the start of this application. The data is JSON. And EVERYTHING is available. (I hope I don't get in too much trouble for grabbing it :). Well, everything I needed and some extra stuff.

The first step to building this app was to determine what the Information Architecture was going to look like.  Here's what I came up with:

Teams: Name, Email address of a person in the league.
Tournaments:  Tournament info include URL to the JSON file on pgatour.com, data like start / end date, is it in progress, is it finished.
Team Tournament: Each team's 6 initial golfers for each tournament, and total score recording.

Pulling in the tournament from the pgatour.com JSON file pulls in all of the information required for a tournament in my system, so all that is needed as input is the JSON file URL!

Next you assign teams. There can be 6 max.

Then scores are calculated.

And updated throughout the round, each day, for the whole tournament.

If a player doesn't have 4 players make the cut, they are given a substitute. The worst score from the 3rd round.

That is pretty much everything!  Once again, working with AngularJS is a breeze.

Check out the site at fantasygolf.jasontconnell.com! There you can view the source to get an idea of how it was written. It was very simple that I don't even feel like I can post any difficult code that I wrote, but it's just that it's really cool. Our next tournament is the Congressional next week, I hope everyone in the league uses the site.  I added GA tracking so I'll know for sure :)