Gmail Calendar Documents Reader Web more »
Recently Visited Groups | Help | Sign in
Google Groups Home
The Plan for the February Meeting
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  5 messages - Collapse all  -  Translate all to Translated (View all originals)
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
James Gray  
View profile  
 More options Jan 28, 5:46 pm
From: James Gray <ja...@grayproductions.net>
Date: Wed, 28 Jan 2009 16:46:04 -0600
Local: Wed, Jan 28 2009 5:46 pm
Subject: The Plan for the February Meeting
Grant and Brian have agreed to do a little code challenge experiment  
for us at the February meeting.  This is for the fun and education of  
us all. Thanks guys!

Below are the details of their challenge for them to see and for those  
of us who wish to follow along.

Tim is going to give a talk for the other half of the meeting, showing  
off a few of his favorite libraries.

As you can see, it's shaping up to be a great meeting!

James Edward Gray II

Calendar Code Challenge
=======================

The contestants will complete a simple calendar application with just  
two abilities:  users should be able to enter events and see what  
events will occur on a given day.  The primary challenge comes from  
the fact that the code is expected to handle multiple types of events.

Your Code
---------

The code you provide really only has to do two things:  accept new  
event entries and provide a way to list all events occurring on a  
given day.  No judging will be done on the interface, so you are free  
to provide a nice interface for these two action or just build methods  
to call in IRb or a testing environment.  Whatever is easiest for you  
is fine.

No judging will be done on tests, documentation, or any other  
ancillary assets to the code itself.  However, you will be judged on  
how easy it is for others to understand your code as outlined below  
and these items may help with that.

You also do not need to worry about the data stressing your code.  
You're program doesn't need to handle so much data that it can't all  
be stored in memory and event fields will be consistently sane.  No  
dates will be used that are outside a two year range centered on  
today, so you needn't worry about calendar changes or the resolution  
of Ruby's built in Time class.  You just need to build the core  
functionality of the problem.

Event Types
-----------

The main challenge is that your calendar is expected to support  
multiple types of events.  Users need to be able to create any or all  
of the types listed below and searches must check all known events  
returning all events that will fall on a given day, regardless of type.

Each event type can have different fields and the types share some  
fields.  Some fields are optional and some have defaults you need to  
account for.

All events have a unique name (a String) and a start date and time (a  
Time) that are always provided.  All events can also have an end date  
and time (also a Time), but this field can also be left nil to  
indicate that an event is ongoing and does not end.

You can mostly ignore the time portion of all dates and times for the  
purposes of this exercise.  We're only interested in which events  
appear on a given day and the times don't play into that.

Beyond that, the event types differ as follows:

* Daily events also have no additional fields.  They recur each day  
between their start date and end date.
* Weekly events have a frequency field (an Integer) that defaults to  
one and a list of days (an Array containing one or more Strings from  
the set:  "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",  
"Friday", and "Saturday").  These events recur each week between their  
start date and end date on the days indicated.  If frequency is  
anything but one, they only appear if the week in question is  
divisible by the frequency when counted as an offset from the start  
date.  For example, a frequency of two means an event occurs every  
other week and thus would appear within the first seven days of the  
start date, skip the next seven, appear in the next seven, etc.
* Monthly events can be set two ways.  The first type of monthly event  
has a frequency field (same as the weekly version, but in the scope of  
months), an "on the" field (a String from the set:  "first", "second",  
"third", and "last"), and a day field (a String from the same set  
mentioned in the weekly events days field).  Again, this date recurs  
monthly bounded by the start and end date and as dictated by the  
frequency.  The difference here is that the "on the" and day fields  
indicate which day of the month the event happens on.
* If the "on the" and day fields are omitted, you have the second type  
of monthly event.  This event just repeats on the same day of the  
month as the start date (if present in the current month).  These too  
can have a frequency to skip months.
* Finally, there are yearly events that just recur on the same day of  
the year as their start date.  These events have no additional fields.

The Judging
-----------

The spirit of this contest is totally for fun and there will be no  
official winner or loser.  However, we do have some criteria upon  
which entries will be considered, just for friendly bragging rights!

The contestants are expected to make their solutions publicly  
available by posting them to the mailing list two days before the  
February meeting.  That means solutions should be posted on February  
10th by 6:30 PM.

At the meeting, each of you will explain the other contestant's  
code.   You are expected to highlight how it works and point out  
things you like about the solution.  You will be judged on how well  
you understand the code you are showing and on how easy your code was  
to understand.

If you notice any problems with the code, like edge case searches it  
wouldn't get right, feel free to point those out as well.  This shows  
an even greater understanding of the code on your part.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
John Hornbeck  
View profile  
 More options Jan 28, 5:49 pm
From: John Hornbeck <hornb...@gmail.com>
Date: Wed, 28 Jan 2009 14:49:54 -0800
Local: Wed, Jan 28 2009 5:49 pm
Subject: Re: The Plan for the February Meeting

Have fun guys :)

On Wed, Jan 28, 2009 at 2:46 PM, James Gray <ja...@grayproductions.net>wrote:

--
John Hornbeck
Support Manager
Engine Yard
http://engineyard.com

"Work hard to find something that fascinates you." - Richard Feynman


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Grant Schofield  
View profile  
 More options Feb 10, 10:30 pm
From: Grant Schofield <gr...@surlysoft.com>
Date: Tue, 10 Feb 2009 21:30:50 -0600
Local: Tues, Feb 10 2009 10:30 pm
Subject: Re: The Plan for the February Meeting
Sorry for the delay. Didn't have power till just a little bit ago.

Code is here:
http://github.com/schofield/okcal/tree/master

Grant

On Jan 28, 2009, at 4:46 , James Gray wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Brian Clubb  
View profile  
 More options Feb 11, 8:02 am
From: Brian Clubb <bcl...@gmail.com>
Date: Wed, 11 Feb 2009 05:02:23 -0800 (PST)
Local: Wed, Feb 11 2009 8:02 am
Subject: Re: The Plan for the February Meeting
Sorry for the delay, I was saving orphans from forrest fires and
helping Barack with the economy.  In my time away from that I've been
solving this problem here http://github.com/bclubb/calendar/tree/master#.

Brian

On Feb 10, 9:30 pm, Grant Schofield <gr...@surlysoft.com> wrote:


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
James Gray  
View profile  
 More options Feb 12, 10:19 pm
From: James Gray <ja...@grayproductions.net>
Date: Thu, 12 Feb 2009 21:19:08 -0600
Local: Thurs, Feb 12 2009 10:19 pm
Subject: Re: The Plan for the February Meeting
On Feb 10, 2009, at 9:30 PM, Grant Schofield wrote:

> Sorry for the delay. Didn't have power till just a little bit ago.

> Code is here:
> http://github.com/schofield/okcal/tree/master

Some people wanted to see my solution to the code challenge.

Here's the original MySQL solution:

     if not params[:date].blank?
       condition[<<-END_DATE_SQL, *([params[:date]] * 14)]
       start_date <= ? AND (end_date IS NULL OR ? <= end_date) AND
       IF(repeats IS NULL OR TRIM(repeats) = '' OR repeats = 'Daily', 1,
       IF(repeats = 'Weekly' AND  
#{params[:date].strftime("%A").downcase} = 1 AND FLOOR(DATEDIFF(?,  
start_date) / 7) % frequency = 0, 1,
       IF(repeats = 'Monthly' AND (((on_the IS NULL AND  
DAYOFMONTH(start_date) = DAYOFMONTH(?)) OR  
(#{params[:date].strftime("%A").downcase} = 1 AND IF(on_the = 'first'  
AND DAYOFMONTH(?) <= 7, 1, IF(on_the = 'second' AND DAYOFMONTH(?) > 7  
AND DAYOFMONTH(?) <= 14, 1, IF(on_the = 'third' AND DAYOFMONTH(?) > 14  
AND DAYOFMONTH(?) <= 21, 1, IF(on_the = 'last' AND MONTH(?) !=  
MONTH(DATE_ADD(?, INTERVAL 8 DAY)), 1, 0)))))) AND PERIOD_DIFF(YEAR(?)  
* 100 + MONTH(?), YEAR(start_date) * 100 + MONTH(start_date)) %  
frequency = 0), 1,
       IF(repeats = 'Yearly' AND DAYOFYEAR(start_date) = DAYOFYEAR(?),  
1, 0))))
       END_DATE_SQL
       if params[:date] == Date.today
         condition["start_time IS NULL OR start_time >= TIME(?)",  
Time.now]
       end
     end

I'm pretty sure that one works right.

Here's another on in Ruby that may work, but I admit that I've only  
tested it a tiny bit.  It likely still has bugs:

#!/usr/bin/env ruby -wKU

class Event
   DAY_IN_SECONDS = 24 * 60 * 60

   def initialize(name, details)
     @name       = name
     @start_date = details[:start_date]
     @end_date   = details[:end_date]
   end

   attr_reader :name, :start_date, :end_date

   def on?(on)
     start_date <= on and (end_date.nil? or on <= end_date)
   end
end

class DailyEvent < Event

end

class WeeklyEvent < Event
   def initialize(*args)
     super
     @days      = args.last[:days]
     @frequency = args.last[:frequency] || 1
   end

   attr_reader :days, :frequency

   def on?(on)
     super                            and
     days.include?(on.strftime("%A")) and
     ((on - start_date).abs.to_i / (7 * DAY_IN_SECONDS) %  
frequency).zero?
   end
end

class MonthlyEvent < Event
   def initialize(*args)
     super
     @frequency = args.last[:frequency] || 1
     @on_the    = args.last[:on_the]
     @day       = args.last[:day]
   end

   attr_reader :on_the, :day

   def on?(on)
     super and
     ( (on_the.nil? and start_date.mday == on.mday) or
       (day == on.strftime("%A") and is_on?(on)) ) and
     (month_diff(on) % frequency).zero?
   end

   private

   def is_on?(on)
     case on_the.to_sym
     when :first
       on.mday <= 7
     when :second
       on.mday.between? 8, 14
     when :third
       on.mday.between? 15, 21
     when :last
       on.mon != (on + 8 * DAY_IN_SECONDS).mon
     end
   end

   def month_diff(on)
     early, late = [start_date, on].sort
     year_diff   = (late.year - early.year).abs
     if year_diff.nonzero? and late.mon < early.mon
       (year_diff - 1) * 12 + (start_date.mon - on.mon).abs
     else
       year_diff * 12 + (start_date.mon - on.mon).abs
     end
   end
end

class YearlyEvent < Event
   def on?(on)
     super and @start_date.yday == on.yday
   end
end

class EventList
   def initialize
     @events = [ ]
   end

   def all_on(on)
     @events.select { |event| event.on? on }
   end

   def method_missing(meth, *args, &blk)
     if meth.to_s =~ /\Aadd_(daily|weekly|monthly|yearly)_event\z/
       @events << Object.const_get("#{$1.capitalize}Event").new(*args)
     else
       super
     end
   end
end

__END__

Great work guys.  I think it was a good learning experience for all!

James Edward Gray II


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google