lib/card.rb
# Copyright (c) 2013-2014 SUSE LLC
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 3 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact SUSE LLC.
#
# To contact SUSE about this file by physical or electronic mail,
# you may find current contact information at www.suse.com
class Card
# Assuming we have card titles as follows '(8) This is the card name'
ESTIMATED_REGEX = /\(([\d.]+)\)/
SPRINT_NUMBER_REGEX = /\ASprint (\d+)/
def initialize(board_data, card_id, settings = nil)
init_data(board_data, card_id, settings)
end
def init_data(board_data, card_id, settings = nil)
@board_data = board_data
@settings = settings
@card_data = @board_data['cards'].find{|c| c['id'] == card_id}
end
def as_json
JSON.pretty_generate(@card_data)
end
def estimated?
name =~ ESTIMATED_REGEX
end
def story_points
return 0.0 unless estimated?
name.match(ESTIMATED_REGEX).captures.first.to_f
end
def done_tasks
filtered_checklists.map(&:done_tasks).sum
end
def tasks
filtered_checklists.map(&:tasks).sum
end
def card_labels
@card_data['labels'] || []
end
def label?(label_name)
card_labels.any? do |label|
label['name'].include?(label_name)
end
end
def checklists
return [] unless @card_data['checklists']
@card_data['checklists'].map do |checklist|
Checklist.new(checklist)
end
end
def filtered_checklists
checklists.reject do |checklist|
@settings && @settings.no_task_checklists.include?(checklist.name)
end
end
def desc
@card_data['desc']
end
def extra?
card_labels.any? do |label|
label['name'].include?('BelowWaterline') ||
label['name'].include?('Under waterline')
end
end
def unplanned?
card_labels.any? do |label|
label['name'].include?('Unplanned')
end
end
def swimlane?
card_labels.each do |label|
@settings.swimlanes.each do |swimlane|
return true if label['name'].include?(swimlane)
end
end
false
end
def meta_card?
name =~ SPRINT_NUMBER_REGEX
end
def sprint_number
raise ArgumentError unless meta_card?
name.match(SPRINT_NUMBER_REGEX).captures.first.to_i
end
def fast_lane?
# TODO: move to settings
card_labels.map{|l| l['name']}.include?('FastLane')
end
# TODO: rethink storage for meta data for sprint
def self.parse_yaml_from_description(description)
description =~ /```(yaml)?\n(.*)```/m
yaml = Regexp.last_match(2)
if yaml
return YAML.load(yaml) # throws an exception for invalid yaml
else
return nil
end
end
def name
@card_data['name']
end
def name=(str)
@card_data['name'] = str
end
def id
@card_data['id']
end
end