Ultimate Tournament


I recently launched my side project Ultimate Tournament and I’m pretty excited about it. It’s an app for running Ultimate tournaments that takes care of the tricky logistics involved in running an event. Brackets especially are a pretty non-trivial graph structure which is quite different from the data I usually work with so it was a fun learning experience. I used and learned some cool new tech on this project too, notably React.js and improving my css/sass skills.

Now I’m trying my hand at marketing to try and get the word out so people use my app.

There is a lot more I want to do on this project still like adding ActionCable for websockets and expanding it to other sports. I’ll probably build an API out soon as well, so stay tuned for some updates

If you happen to need tournament software or know someone who does please check it out!

Update - I worked on Ultimate Tournament for a number of years and learned a lot through the project. Alas web projects never really end and I wanted to move on so in 2020 I shutdown the app. Later on I wrote up some final thoughts on the project in the readme and open sourced it.

kevinhughes27/ultimate-tournament

read more

2015 a Year in Review

2015 was a pretty awesome year full of new experiences, growth and accomplishments. It marked my second year of working in software professionally and school seems like a faint memory at this point. Shopify, the company where I work, IPO’d this summer which was an exciting and [possibly] once in a lifetime experience. I think this kind of post is worth doing to reflect before simply setting our sights on the next goal. So here it is my year in review in bullet points:

Travel

  • Barcelona for FullStack Fest
  • Stockholm Sweden for Nordic.js
  • Paris France (for just over 24 hours but we saw a lot!)
  • Helsinki Finland for Junction 2015
  • Costa Rica for vacation
  • Peru for a vacation and to hike the Inca Trail!

Sports and Fitness

  • new PR squating at 255 lbs for 1 (although now I’m injured as I write this and my squat is low :sadface:)
  • ran 3k in 12:35 (mm::ss)
  • made a lot of improvement in mobility (I can now touch my toes!)
  • I discovered and became addicted to Yoga Tune Up which has really helped support my other fitness goals

Ultimate

  • I played my first season of competitive Ultimate with Swift
  • I attended 3 away tournaments with Swift in Toronto, New York and Barrie finishing our season at No Borders in Ottawa.
  • We didn’t win a lot of games (we were essentially the C team) but we did beat Goose when it counted!
  • I played in my first beach tournament ever!

Side Projects

New Tech

read more

LifeOps

I’ve recently started doing something that I’ve coined ‘LifeOps’. LifeOps is all about measuring, quantifying, tracking and alerting for things in my life. It’s my take on personal experimentation and improvement and what makes it different is the degree of software and automation involved.

I think the easiest way to explain LifeOps is with some concrete examples the first of which is fitness related. There are a lot of ways to measure fitness most of which are quite manual (recording lifts etc.) I’ve used a few different methods in the past but I always keep coming back to my weight as a sanity check. For me I know my fitness/health is starting to slip if I’m losing weight (I realize this is opposite of most people) so I decided to do something about it. I didn’t even own a home scale before so I went and purchased a FitBit Aria with a plan in mind.

I setup my Aria scale and then added a recipe to IFTTT to sync my weight and BMI data to a Google Spreadsheet. Here is where the Ops comes in. I wrote the following scripts to track and alert based on my data:

No Data Alert:

  function alertNoData() {
    var lastEntry = getLastEntry();
    var rawDateStr = lastEntry[0];
    var dateStr = rawDateStr
      .replace(' at', '')
      .replace('AM', ' AM')
      .replace('PM', ' PM');

    var date = new Date(dateStr);
    var today = new Date();
    var diff = dateDiff(date, today);
    var threshold = 2;

    if(diff > threshold) {
      var message = "Last entry was made on: " + rawDateStr
      MailApp.sendEmail(alertEmail, '[Alert][Weight Logs] - No Data', message);
    }
  }

Negative Trend Alert:

  function alertTrend() {
    var n = 8;
    var weights = getLastNWeights(n);

    var X = range(1, n);
    var Y = [];

    for(i=0; i < weights.length; ++i) {
      Y.push( weights[i][0] );
    }

    var ret = {};
    var f = leastSquares(X, Y, true, ret);
    var slope = ret.m;

    if(slope < 0) {
      message = "Weights: " + Y.join(', ');
      MailApp.sendEmail(alertEmail, '[Alert][Weight Logs] - Negative Trend', message);
    }
  }

Both these scripts run daily using triggers (essentially cron tasks). The results are pretty cool - I get an alert if my weight starts to trend negatively and I can make adjustments to stay on course. Weight is usually a pretty poor metric of health/fitness but I think with this setup the quantity of data will make up for the quality.

The next LifeOps script I made uses IFTTT to log connections and disconnections from my work WiFi network to another Google Spreadsheet. At the end of the week I rollup all the rows to count how many hours I spent at the office. Again - time spent at work isn’t a great metric but with this setup it’s so easy to measure I figured why not?

  function rollupToWeek() {
    var entries = getEntries();

    var week = parseDate(entries[0][1]).getWeek()

    // assumes:
    // a) the first row is always a 'connected to'
    // b) the rows always alternate from 'connected_to' to 'disconnected_from'
    var time = 0;
    for(i=0; i < entries.length; i+=2 ) {
      var inTime = parseTime( entries[i][1] );
      var outTime = parseTime( entries[i+1][1] );
      time += outTime - inTime;
    }

    var hours = time / (3600 * 1000)

    // save the rolled up data
    var sheet = SpreadsheetApp.openById('...').getSheetByName('WorkHours');
    sheet.appendRow([week, hours]);

    // clear raw data
    var sheet = SpreadsheetApp.openById('...').getSheetByName('Sheet1');
    sheet.clear();

    // email results
    message = hours + " spent at the office this past week. Remember to clear the spreadsheet manually for next week";
    MailApp.sendEmail("kevinhughes27@gmail.com", '[Report][Work Hours]', message);
  }

I’m excited to keep expanding on what I do with LifeOps. I’ve found this combo of IFTTT and Google AppScript to be quite powerful. IFTTT on its own isn’t very interesting in my opinion but combined with AppScript you can do some cool things. I’ve really come to re-accept Spreadsheets and AppScript as a great solution for small problems (the software engineer in me is always a bit wary of spreadsheets). Got any cool LifeOps of your own? Let me know about them in the comments!

read more