It's that time of year, when AYSO kicks off for a 10-week season and you fill your Saturdays with soccer, snacks, and socializing.
We have two kids playing for the first time this year, and the AYSO website (at least our local version) is super old school and primitive. They post the schedule for each team in an HTML table, with no hope of an export button, or import to calendar feature, or anything. The web developers and AYSO organization apparently expects every parent to painstakingly transcribe each game on to their family calendars, including the specific field involved, whether the team is home or away, and other tiny nuggets of info like who is in charge of snacks or what days does a parent need to ref.
This is only the first of many years of sports where we have multiple kids partaking. My wife and I live by our shared family calendar, both having it accessible on our phones and computers. Anything noteworthy goes on there and events sync to each device, alerting us of new additions to the schedule. Rather than enter yet another sequence of events (20 in total for our 2 kids, and then 30 total next year!), I decided to start automating.
The Approach
I went with Ruby, as I planned to start with a command line script, but could see it extending to be a simple web app. Ruby is simple and beautiful for scripting and file input/output. My goal was to take the HTML table as input and generate a file that conformed to the iCalendar specification, thus being able to import into our Apple calendar. First I needed to ensure I could get the data out of the website's table and into a reasonable form for parsing. Fortunately simply copying and pasting all the text in the table put it in a fairly easy format: new lines between each game, and tab characters between each column in the table. I pasted it into input.txt
.
The outer logic deals with the input and building up the final "ics"file that contains a list of events. This is done by creating a new "calendar", then adding each ical event to it:
class EventCreator
attr_reader :cal
def initialize
@cal = Icalendar::Calendar.new
make_events
end
def make_events
lines = File.read("input.txt").split("\n")
events = parse_into_events!(lines)
events.each do |event|
@cal.add_event(event)
end
end
def to_ics
File.open("events.ics", "w") { |f| f.write @cal.to_ical }
end
end
At that point, it was just a matter of mapping the columns in the table, to human readable sections of a calendar event. Another great thing about Ruby, is the community and gems available. There is an easy to use iCalendar gem for working with iCalendar events.
def parse_into_event!(line)
# each line can just be split by the tab character
data = line.split("\t").map { |col| col.strip }
date = Date.parse(data[0])
time = Date.parse(data[1])
field = data[2]
#... repeat for other columns
# using the gem interface
event = Icalendar::Event.new
event.dtstart = Time.local(date.year, date.month, date.day, time.hour, time.min)
event.duration = "P60M"
event.summary = build_summary(summary_suffix)
event.location = build_location(field)
event.description = build_description(home_or_away, opponent_coach, opponent_team)
event.to_ical
end
The above can be factored into smaller responsibilities, by creating an Event::Ayso
that does all the time conversion and string formatting (leaving the possibility for extending this tool to parse and create other sports events from other sites).
event = Event::Ayso.new(summary_suffix, date, time, field, home_or_away, opponent_team, opponent_coach)
event.to_ical
With all of the above, the script itself is as simple as requiring dependencies and using EventCreator
:
require "rubygems"
require "bundler"
Bundler.require
require_relative 'lib/event_creator.rb'
events = EventCreator.new
events.to_ics
The nice thing with the iCalendar format is that you can have all of the events in a single ics file, and when you import it into your Apple or Google Calendar, it will import all events. This works on mobile with the iOS Calendar app, Android calendar app, a desktop calendar program such as macOS Calendar, and you can also import to Google Calendar in a browser by going to Settings > Import & export > Import.
The latest version of the code is in my eventor repo.