Skip to content

Instantly share code, notes, and snippets.

@atamis
Created November 3, 2010 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atamis/660593 to your computer and use it in GitHub Desktop.
Save atamis/660593 to your computer and use it in GitHub Desktop.
A ruby DSL for making timelines.
require 'date'
module Chronograph
class Timeline
include Enumerable
class Event < Struct.new(:name, :date, :desc)
attr_accessor :name, :date, :desc
def initialize(name, date, desc)
raise TypeError.new("date must be a date") unless date.is_a? Date
raise TypeError.new("name has to be a name or symbol") unless name.is_a?(String) || name.is_a?(Symbol)
raise TypeError.new("desc must be a string") unless desc.is_a? String
@name = name
@date = date
@desc = desc
end
end
class Person < Struct.new(:name, :birth, :death, :desc, :events)
attr_reader :name, :birth, :death, :desc, :events
def initialize(name, birth, death, desc, *events)
raise TypeError.new("name has to be a name or symbol") unless name.is_a?(String) || name.is_a?(Symbol)
raise TypeError.new("birth and death must be a date") unless birth.is_a?(Date) && death.is_a?(Date)
raise TypeError.new("desc must be a string") unless desc.is_a? String
@name = name
@birth = birth
@death = death
@desc = desc
@events = events
end
def events
[begining_event, ending_event, @events].flatten
end
def begining_event
Event.new("Birth of #{name}", birth, "#{name} is born")
end
def ending_event
Event.new("Death of #{name}", death, "#{name} dies")
end
end
class LongEvent < Person
def begining_event
Event.new("Begining of #{name}", birth, "#{name} begins")
end
def ending_event
Event.new("End of #{name}", death, "#{name} ends")
end
end
class War < LongEvent; end
def initialize(&block)
@people = []
@events = []
instance_eval(&block)
end
def each(&block)
consolidate.each(&block)
end
def person(name, birth, death, desc, &block)
@life_events = []
def life_event(name, date, desc)
@life_events << Event.new(name, date, desc)
end
instance_eval(&block) if block != nil
@people << Person.new(name, birth, death, desc, *@life_events)
end
def long_event(name, birth, death, desc, &block)
@long_events = []
def le_event(name, date, desc)
@long_events << Event.new(name, date, desc)
end
instance_eval(&block) if block != nil
@people << LongEvent.new(name, birth, death, desc, *@long_events)
end
def event(name, date, desc)
@events << Event.new(name, date, desc)
end
def today
event "Today", Date.today, "this day"
end
def consolidate
t = []
t << @events << @people.map { |x| x.events }
return t.flatten.sort { |a, b| a.date <=> b.date }
end
def get_text
consolidate.map { |x| "#{x.date}: #{x.name}, #{x.desc}" }.join("\n")
end
def get_html_table
r = "<table>"
consolidate.each do |x|
r += "<tr>"
r += [x.date, x.name, x.desc].map { |x| "<td>" + x.to_s + "</td>"}.join
r += "</tr>"
end
r += "</table>"
end
end
end
if $0 == __FILE__
t = Chronograph::Timeline.new do
person "Mr. Ruby", Date.new(1654), Date.new(2010), "He was awesome" do
life_event "Mr. Ruby leaves Japan", Date.new(2000), "It was easy"
long_event "War against Java", Date.new(2005), Date.new(2007), "It was needed" do
le_event "Battle of the MRI", Date.new(2005, 5, 6), "Mr. Ruby almost lost"
le_event "Battle of the JVM", Date.new(2005, 10, 31), "This was one scary halloween for Javaland"
end
end
event "Javaland founded", Date.new(1990), "1000s die"
today
end
#t.each { |x| puts x.inspect }
puts t.get_text
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment