Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 301 lines (241 sloc) 6.29 KB
#!/usr/bin/env ruby
require 'csv'
require 'rally_rest_api'
require 'ostruct'
require 'optparse'
require 'yaml'
require 'prawn'
require 'prawn/measurement_extensions'
#TODO: Refactor these classes, make them a gem maybe?
class KanbanCard
def initialize(id,name)
@id = id
@name = name
end
def to_s
"[Card #{@id}] #{@name}"
end
def draw(index,pdf)
#origin
x = 12.mm + (index % 2) * 94.mm
y = 290.mm - (index / 2 % 5) * 58.mm
#draw the card
pdf.stroke do
#card border
pdf.rectangle [x,y],89.mm,55.mm
# horizontal line
pdf.line [x,y - 21.mm],[x + 89.mm, y - 21.mm]
end
end
end
class KanbanStory < KanbanCard
def initialize(id, name, points)
super(id,name)
@points = points
end
def to_s
"[Story #{@id}:#{@points}] #{@name}"
end
def draw(index,pdf)
#origin
x = 12.mm + (index % 2) * 94.mm
y = 290.mm - (index / 2 % 5) * 58.mm
#draw the card
pdf.stroke do
#card border
pdf.rectangle [x,y],89.mm,55.mm
# horizontal line
pdf.line [x,y - 21.mm],[x + 89.mm, y - 21.mm]
end
pdf.bounding_box([x ,y - 5.mm ], :width=> 84.mm, :height=>21.mm ) do
pdf.text @id, :size => 24 , :align => :center, :style => :bold
pdf.text "Points: #{@points}", :size => 12 , :align => :center
end
pdf.bounding_box([x + 5.mm, y - 26.mm] ,
#change 89 to 60 when printing QRCODE
:width => 84.mm, :height => 34.mm ) do
pdf.text @name, :size => 16 , :style => :bold
end
end
end
class KanbanTask < KanbanCard
def initialize(id, name, parent_story)
super(id,name)
@parent_story = parent_story
end
def to_s
"[Task #{@parent_story}:#{@id}] #{@name}"
end
def draw(index,pdf)
#origin
x = 12.mm + (index % 2) * 94.mm
y = 290.mm - (index / 2 % 5) * 58.mm
#draw the card
pdf.stroke do
#card border
pdf.rectangle [x,y],89.mm,55.mm
# horizontal line
pdf.line [x,y - 21.mm],[x + 89.mm, y - 21.mm]
# vertical line
pdf.line [x + 34.mm ,y - 21.mm],[x + 34.mm, y ]
end
#put text into the bounding boxes
pdf.bounding_box([x ,y - 5.mm ], :width=> 34.mm, :height=>21.mm ) do
pdf.text @id, :style => :bold, :size => 20 , :align => :center
pdf.text @parent_story, :size => 12 , :align => :center
end
pdf.bounding_box([x + 5.mm, y - 26.mm] ,
#change 89 to 60 when printing QRCODE
:width => 89.mm, :height => 34.mm ) do
pdf.text @name, :size => 16 , :style => :bold
end
end
end
class KanbanBug < KanbanCard
def initialize(id, name, points)
super(id,name)
end
def to_s
"[Bug #{@id}] #{@name}"
end
def draw(index,pdf)
#origin
x = 12.mm + (index % 2) * 94.mm
y = 290.mm - (index / 2 % 5) * 58.mm
#draw the card
pdf.stroke do
#card border
pdf.rectangle [x,y],89.mm,55.mm
# horizontal line
pdf.line [x,y - 21.mm],[x + 89.mm, y - 21.mm]
end
#put text into the bounding boxes
pdf.bounding_box([x ,y - 5.mm ], :width=> 84.mm, :height=>21.mm ) do
pdf.text @id, :size => 24 , :align => :center, :style => :bold
pdf.text "Points: #{@points}", :size => 12 , :align => :center
end
pdf.bounding_box([x + 5.mm, y - 26.mm] ,
#change 89 to 60 when printing QRCODE
:width => 84.mm, :height => 34.mm ) do
pdf.text @name, :size => 16 , :style => :bold
end
end
end
class CardBook
def initialize
@CardBook = []
@pdf = Prawn::Document.new(:page_size => "A4",:margin => [5,5]) #TODO: These should be class attributes
end
def add(card)
@CardBook.push(card)
end
def to_s
cb = "Cardbook:\n"
index = 0
@CardBook.each do |card|
cb = cb + "\t#{index}: #{card.to_s}\n"
index = index + 1
end
cb
end
def render_file(filename)
index = 0
@CardBook.each do |card|
if index > 0 and index % 10 == 0 then @pdf.start_new_page end
card.draw(index,@pdf)
index = index + 1
end
@pdf.render_file filename
end
end
cb = CardBook.new
cb.render_file("teste.pdf")
options = OpenStruct.new
options.pdffile = "output.pdf"
options.csvfile = "output.csv"
options.csvoutput = false
options.pdfouput = false
options.iteration = ""
options.story = ""
options.user = nil
options.password = nil
opts = OptionParser.new
opts.banner = "Usage: iterstories <-i Iteration ID> <outputfile>"
opts.on('-iITERATION','--iteration=ITERATION','Iteration ID') do |iter|
options.iteration << iter
end
opts.on('-U username','--user=username','Provides a Rally User') do |user|
options.user = user
end
opts.on('-P password','--password=password','Provides a Rally Password') do |pass|
options.password = pass
end
options.stories = true
options.tasks = true
options.defects = true
opts.on('-t','--tasks','tasks only') do |tasks|
options.stories = false
options.tasks = true
options.defects = false
end
opts.on('-d','--defects','defects only') do |defects|
options.stories = false
options.tasks = false
options.defects = true
end
opts.on('-s','--stories','stories only') do |tasks|
options.stories = true
options.tasks = false
options.defects = false
end
opts.on_tail( '-h', '--help', 'Displays this screen' ) do
puts opts
exit
end
opts.parse!(ARGV)
output_file = ARGV[0]
begin
config = YAML.load_file("#{Dir.home}/.rallyutils")
rescue
if !options.user and !options.password then
puts opts
puts "\nERROR: #{Dir.home}/.rallyutils not found and no user/password provided"
exit
end
end
rally_user=options.user || config["user"]
rally_pass=options.password || config["password"]
if options.iteration.empty? or not output_file then
puts opts
exit
end
itername = options.iteration
#Queries iteration
rally = RallyRestAPI.new(:username => rally_user, :password => rally_pass)
if itername then
res = rally.find( :iteration ) { equal :object_i_d , itername }
iter = res.first
end
cb = CardBook.new
if options.stories then
stories = rally.find( :hierarchical_requirements ) { equal :iteration, iter }
stories.each do |story|
s = KanbanStory.new(story.formatted_i_d,story.name,story.plan_estimate)
cb.add(s)
end
end
if options.tasks then
tasks = rally.find( :tasks ) { equal :iteration, iter }
tasks.each do |task|
t = KanbanTask.new(task.formatted_i_d,task.name,task.work_product.formatted_i_d)
cb.add(t)
end
end
if options.defects then
defects = rally.find( :defects ) { equal :iteration, iter }
defects.each do |defect|
d = KanbanBug.new(defect.formatted_i_d,defect.name,defect.plan_estimate)
cb.add(d)
end
end
cb.render_file(output_file)