tracco 0.0.12 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +17 -0
- data/Gemfile.lock +2 -2
- data/lib/patches/trello/member.rb +3 -3
- data/lib/tracco/effort.rb +2 -1
- data/lib/tracco/google_docs_exporter.rb +1 -1
- data/lib/tracco/member.rb +1 -1
- data/lib/tracco/tracked_card.rb +15 -5
- data/lib/tracco/tracking/effort_tracking.rb +14 -17
- data/lib/tracco/tracking/estimate_tracking.rb +1 -4
- data/lib/tracco/tracking/factory.rb +26 -0
- data/lib/tracco/trello_tracker.rb +2 -2
- data/lib/tracco/version.rb +1 -1
- data/lib/tracco.rb +1 -1
- data/spec/effort_spec.rb +1 -1
- data/spec/factories/effort_factory.rb +11 -0
- data/spec/factories/estimate_factory.rb +9 -0
- data/spec/factories/tracked_card_factory.rb +6 -7
- data/spec/spec_helper.rb +0 -38
- data/spec/support/spec_helper_methods.rb +32 -0
- data/spec/tracked_card_spec.rb +119 -77
- data/spec/tracking/card_done_tracking_spec.rb +1 -1
- data/spec/tracking/effort_tracking_spec.rb +4 -4
- data/spec/tracking/estimate_tracking_spec.rb +7 -7
- data/spec/tracking_factory_spec.rb +4 -4
- data/tracco.sublime-project +1 -1
- metadata +7 -4
- data/lib/tracco/tracking_factory.rb +0 -22
data/CHANGELOG
CHANGED
@@ -1,42 +1,59 @@
|
|
1
|
+
0.0.13 / 2013-02-27
|
2
|
+
==================
|
3
|
+
* adding muted status on Effort to be able to 'turn off' a card's specific effort
|
4
|
+
* adding a TrackedCard.efforts_between method to fetch all the cards with an effort spent in a given date range
|
5
|
+
* improving TrackedCard#trello_notifications
|
6
|
+
|
1
7
|
0.0.12
|
8
|
+
======
|
2
9
|
- Adding a TrackedCard#trello_notifications to fetch all the notifications belonging to the card
|
3
10
|
- Introducing FactoryGirl as a factory gem to simplify specs
|
4
11
|
|
5
12
|
0.0.11
|
13
|
+
======
|
6
14
|
- Adding a TrackedCard.all_tracked_cards method to fetch all cards with a valid tracking. Moreover, sorting_options can be passed to sort using a method e.g. TrackedCard.all_tracked_cards(:method => :name, :order => :desc)
|
7
15
|
|
8
16
|
0.0.10
|
17
|
+
======
|
9
18
|
- Including Mongoid::MultiParameterAttributes in Effort and Estimate to enable date params to be collected correctly by Rails app (e.g. using the Rails' date_select form helper)
|
10
19
|
|
11
20
|
0.0.8 - 0.0.9
|
21
|
+
=============
|
12
22
|
- Gem rename :)
|
13
23
|
|
14
24
|
0.0.7
|
25
|
+
=====
|
15
26
|
- Minor refactorings on the rake tasks
|
16
27
|
|
17
28
|
0.0.6
|
29
|
+
=====
|
18
30
|
- Added TrackedCard#status to track card status: :todo if no effort has been spent, :done if the card is in a DONE column, :in_progress otherwise
|
19
31
|
- Added a Members#effort_spent and #effort_spent_since to extract the overall effort tracked by a member since a given date
|
20
32
|
- Re-merged in the trello_effort_app branch to bring on the Rails app
|
21
33
|
|
22
34
|
0.0.5
|
35
|
+
=====
|
23
36
|
- Improved docs
|
24
37
|
- Improved use of this tool as a gem
|
25
38
|
|
26
39
|
0.0.4
|
40
|
+
=====
|
27
41
|
- A card moved into a DONE column is closed
|
28
42
|
|
29
43
|
0.0.3
|
44
|
+
=====
|
30
45
|
- When I send a tracking with "DONE" then the card is "closed" (aka "finished")
|
31
46
|
- Export all cards in a Google Docs spreadsheet
|
32
47
|
- When I card change its name, the tracked card should be updated too
|
33
48
|
- A card should tells its estimate error (3)
|
34
49
|
|
35
50
|
0.0.2
|
51
|
+
=====
|
36
52
|
- Very simple Rails app on a separate branch, still experimenting
|
37
53
|
- Should be able to open a Trello console with a rake task
|
38
54
|
- Avoid running the script if already run for that period
|
39
55
|
- Tracking data is now persisted in a mongo database
|
40
56
|
|
41
57
|
0.0.1
|
58
|
+
=====
|
42
59
|
- Initial Release.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tracco (0.0.
|
4
|
+
tracco (0.0.13)
|
5
5
|
bson_ext
|
6
6
|
chronic
|
7
7
|
google_drive
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
activesupport (3.2.12)
|
20
20
|
i18n (~> 0.6)
|
21
21
|
multi_json (~> 1.0)
|
22
|
-
addressable (2.3.
|
22
|
+
addressable (2.3.3)
|
23
23
|
bson (1.8.2)
|
24
24
|
bson_ext (1.8.2)
|
25
25
|
bson (~> 1.8.2)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Trello
|
2
2
|
class Member
|
3
3
|
# Reopening the Trello::Member class to add a notifications helper method
|
4
|
-
def
|
4
|
+
def notifications_since(starting_date)
|
5
5
|
notifications(limit:1000).select(&greater_than_or_equal_to(starting_date)).select(&tracking_notification?)
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
private
|
9
9
|
|
10
10
|
def greater_than_or_equal_to(starting_date)
|
@@ -14,7 +14,7 @@ module Trello
|
|
14
14
|
def tracking_notification?
|
15
15
|
lambda { |notification| notification.type == "mentionedOnCard" }
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
end
|
19
19
|
|
20
20
|
end
|
data/lib/tracco/effort.rb
CHANGED
@@ -6,11 +6,12 @@ class Effort
|
|
6
6
|
field :amount, type: BigDecimal
|
7
7
|
field :date, type: Date
|
8
8
|
field :tracking_notification_id
|
9
|
+
field :muted, type: Boolean, default: false
|
9
10
|
|
10
11
|
embeds_many :members
|
11
12
|
embedded_in :tracked_card
|
12
13
|
|
13
|
-
default_scope asc(:date)
|
14
|
+
default_scope where(muted: false).asc(:date)
|
14
15
|
|
15
16
|
validates_presence_of :amount, :date, :members
|
16
17
|
|
@@ -18,7 +18,7 @@ class GoogleDocsExporter
|
|
18
18
|
create_header(worksheet)
|
19
19
|
index = 2 # skip the header
|
20
20
|
|
21
|
-
cards = TrackedCard.
|
21
|
+
cards = TrackedCard.all_tracked_cards(:method => :first_activity_date, :order => :desc)
|
22
22
|
cards.each do |card|
|
23
23
|
print ".".color(:green)
|
24
24
|
worksheet[index, columns[:user_story_id]] = card.short_id
|
data/lib/tracco/member.rb
CHANGED
@@ -28,7 +28,7 @@ class Member
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def effort_spent(from_date=nil)
|
31
|
-
cards = TrackedCard.
|
31
|
+
cards = TrackedCard.with_effort_spent_by(username)
|
32
32
|
efforts = cards.map(&:efforts).compact.flatten
|
33
33
|
efforts = efforts.select {|e| e.date >= from_date} if from_date
|
34
34
|
efforts.select { |effort| effort.include?(self) }.inject(0) { |total, effort| total + effort.amount_per_member }
|
data/lib/tracco/tracked_card.rb
CHANGED
@@ -19,6 +19,8 @@ class TrackedCard
|
|
19
19
|
validates_presence_of :name, :short_id, :trello_id
|
20
20
|
validates_numericality_of :short_id
|
21
21
|
|
22
|
+
scope :with_effort_spent_by, ->(username){ where("efforts.members.username" => username) }
|
23
|
+
|
22
24
|
def self.find_by_trello_id(trello_id)
|
23
25
|
without_mongo_raising_errors do
|
24
26
|
find_by(trello_id: trello_id)
|
@@ -35,10 +37,9 @@ class TrackedCard
|
|
35
37
|
|
36
38
|
def self.all_tracked_cards(sorting_options = {})
|
37
39
|
cards = all.reject(&:no_tracking?)
|
38
|
-
|
39
|
-
cards
|
40
|
-
|
41
|
-
sorting_options[:order] == :desc ? cards.reverse : cards
|
40
|
+
cards.sort_by!(&sorting_options[:sort_by].to_sym) if sorting_options[:sort_by]
|
41
|
+
cards.reverse! if sorting_options[:order] == :desc
|
42
|
+
return cards
|
42
43
|
end
|
43
44
|
|
44
45
|
def self.build_from(trello_card)
|
@@ -47,6 +48,15 @@ class TrackedCard
|
|
47
48
|
new(trello_card.attributes.merge(trello_id: trello_card_id))
|
48
49
|
end
|
49
50
|
|
51
|
+
def self.efforts_between(search_options)
|
52
|
+
condition = {}
|
53
|
+
{'$gte' => :from_date, '$lte' => :to_date}.each do |selection, option_key|
|
54
|
+
condition[selection] = search_options[option_key] if search_options[option_key]
|
55
|
+
end
|
56
|
+
|
57
|
+
where("efforts.date" => condition)
|
58
|
+
end
|
59
|
+
|
50
60
|
def status
|
51
61
|
if done?
|
52
62
|
:done
|
@@ -118,7 +128,7 @@ class TrackedCard
|
|
118
128
|
|
119
129
|
def trello_notifications
|
120
130
|
notification_ids = efforts.map(&:tracking_notification_id) | estimates.map(&:tracking_notification_id)
|
121
|
-
notification_ids.map { |
|
131
|
+
notification_ids.map { |id| Trello::Notification.find(id) rescue nil }.compact.sort_by(&:date)
|
122
132
|
end
|
123
133
|
|
124
134
|
def to_s
|
@@ -2,39 +2,36 @@ module Tracking
|
|
2
2
|
class EffortTracking
|
3
3
|
include Base
|
4
4
|
|
5
|
-
#TODO: rename to 'amount' ?
|
6
|
-
#TODO: avoid recomputing effort every time using a lazy instance variable
|
7
|
-
def effort
|
8
|
-
effort_amount = convert_to_hours(raw_effort)
|
9
|
-
if effort_amount
|
10
|
-
total_effort = effort_amount * effort_members.size
|
11
|
-
Effort.new(amount: total_effort, date: date, members: effort_members, tracking_notification_id: tracking_notification.id)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
5
|
def add_to(card)
|
16
6
|
card.efforts << effort unless card.contains_effort?(effort)
|
17
7
|
end
|
18
8
|
|
9
|
+
def effort
|
10
|
+
@effort ||= Effort.new(amount: total_effort_from(raw_effort), date: date, members: effort_members, tracking_notification_id: tracking_notification.id)
|
11
|
+
end
|
12
|
+
|
19
13
|
private
|
20
14
|
|
15
|
+
def total_effort_from(raw_effort)
|
16
|
+
effort_amount = convert_to_hours(raw_effort)
|
17
|
+
total_effort = effort_amount * effort_members.size
|
18
|
+
end
|
19
|
+
|
21
20
|
def raw_effort
|
22
21
|
extract_match_from_raw_tracking(/\+#{DURATION_REGEXP}/)
|
23
22
|
end
|
24
23
|
|
25
24
|
def effort_members
|
26
|
-
@effort_members ||=
|
25
|
+
@effort_members ||= members_involved_in_the_effort.map do |username|
|
27
26
|
Member.build_from(Trello::Member.find(username))
|
28
27
|
end
|
29
|
-
|
30
|
-
@effort_members
|
31
28
|
end
|
32
29
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
30
|
+
def members_involved_in_the_effort
|
31
|
+
members_involved_in_the_effort = raw_tracking.scan(/@(\w+)/).flatten
|
32
|
+
members_involved_in_the_effort << notifier.username unless should_count_only_listed_members?
|
36
33
|
|
37
|
-
|
34
|
+
members_involved_in_the_effort
|
38
35
|
end
|
39
36
|
|
40
37
|
def should_count_only_listed_members?
|
@@ -2,11 +2,8 @@ module Tracking
|
|
2
2
|
class EstimateTracking
|
3
3
|
include Base
|
4
4
|
|
5
|
-
#TODO: rename to 'amount' ?
|
6
|
-
#TODO: avoid recomputing estimate every time using a lazy instance variable
|
7
5
|
def estimate
|
8
|
-
estimate
|
9
|
-
Estimate.new(amount: estimate, date: date, tracking_notification_id: tracking_notification.id)
|
6
|
+
@estimate ||= Estimate.new(amount: convert_to_hours(raw_estimate), date: date, tracking_notification_id: tracking_notification.id)
|
10
7
|
end
|
11
8
|
|
12
9
|
def add_to(card)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Tracking
|
2
|
+
class Factory
|
3
|
+
|
4
|
+
DURATION_REGEXP = '(\d+\.?\d*[phdg])'
|
5
|
+
|
6
|
+
@match_pairs = {}
|
7
|
+
|
8
|
+
def self.build_from(tracking_notification)
|
9
|
+
matching_pair = @match_pairs.find { |regexp, tracking_class| tracking_notification.data['text'] =~ regexp }
|
10
|
+
|
11
|
+
tracking_class = matching_pair ? matching_pair.last : Tracking::InvalidTracking
|
12
|
+
tracking_class.new(tracking_notification)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def self.match(match_pair)
|
18
|
+
@match_pairs.merge!(match_pair)
|
19
|
+
end
|
20
|
+
|
21
|
+
match /\[#{DURATION_REGEXP}\]/ => Tracking::EstimateTracking
|
22
|
+
match /\+#{DURATION_REGEXP}/ => Tracking::EffortTracking
|
23
|
+
match /DONE/ => Tracking::CardDoneTracking
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -10,13 +10,13 @@ class TrelloTracker
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def track(starting_date=Date.today)
|
13
|
-
notifications = tracker.
|
13
|
+
notifications = tracker.notifications_since(starting_date)
|
14
14
|
|
15
15
|
oldest, latest = boundary_dates_in(notifications)
|
16
16
|
Trello.logger.info "Processing #{notifications.size} tracking notifications (from #{oldest} to #{latest}) starting from #{starting_date}..."
|
17
17
|
|
18
18
|
notifications.each do |notification|
|
19
|
-
tracking =
|
19
|
+
tracking = Tracking::Factory.build_from(notification)
|
20
20
|
begin
|
21
21
|
tracked_card = TrackedCard.update_or_create_with(notification.card)
|
22
22
|
tracked_card.add!(tracking)
|
data/lib/tracco/version.rb
CHANGED
data/lib/tracco.rb
CHANGED
@@ -18,7 +18,7 @@ require 'tracco/tracking/estimate_tracking'
|
|
18
18
|
require 'tracco/tracking/effort_tracking'
|
19
19
|
require 'tracco/tracking/card_done_tracking'
|
20
20
|
require 'tracco/tracking/invalid_tracking'
|
21
|
-
require 'tracco/
|
21
|
+
require 'tracco/tracking/factory'
|
22
22
|
require 'tracco/trello_tracker'
|
23
23
|
require 'tracco/google_docs_exporter'
|
24
24
|
|
data/spec/effort_spec.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
FactoryGirl.define do
|
2
|
+
|
2
3
|
factory :tracked_card do
|
3
|
-
sequence(:
|
4
|
-
description "any description"
|
5
|
-
sequence(:short_id, 1000) { |n| n }
|
4
|
+
sequence(:short_id, 1000)
|
6
5
|
sequence(:trello_id, 100000) { |n| "xyz#{n}" }
|
7
|
-
|
6
|
+
sequence(:name) { |n| "any_card_#{n}" }
|
7
|
+
description "any description"
|
8
|
+
done false
|
8
9
|
closed false
|
9
|
-
|
10
|
-
# embeds_many :estimates
|
11
|
-
# embeds_many :efforts
|
12
10
|
end
|
11
|
+
|
13
12
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -14,8 +14,6 @@ rescue Bundler::GemNotFound => e
|
|
14
14
|
exit!
|
15
15
|
end
|
16
16
|
|
17
|
-
Bundler.require(:spec)
|
18
|
-
|
19
17
|
require 'tracco'
|
20
18
|
|
21
19
|
require 'factory_girl'
|
@@ -32,39 +30,3 @@ end
|
|
32
30
|
|
33
31
|
# force test env for the mongodb configuration
|
34
32
|
TrelloConfiguration::Database.load_env("test")
|
35
|
-
|
36
|
-
|
37
|
-
## Spec Helper Methods (TODO: should we move them in a separate file?)
|
38
|
-
|
39
|
-
def unrecognized_notification
|
40
|
-
create_notification(data: { 'text' => '@trackinguser hi there!' })
|
41
|
-
end
|
42
|
-
|
43
|
-
def notification_with_message(message)
|
44
|
-
create_notification(data: { 'text' => message })
|
45
|
-
end
|
46
|
-
|
47
|
-
def create_estimate(time_measurement)
|
48
|
-
create_notification(data: { 'text' => "@trackinguser [1.5#{TIME_MEASUREMENTS[time_measurement]}]" })
|
49
|
-
end
|
50
|
-
|
51
|
-
def create_effort(time_measurement)
|
52
|
-
create_notification(data: { 'text' => "@trackinguser +4.5#{TIME_MEASUREMENTS[time_measurement]}]" })
|
53
|
-
end
|
54
|
-
|
55
|
-
def with(notification)
|
56
|
-
tracking = TrackingFactory.build_from(notification)
|
57
|
-
yield(tracking)
|
58
|
-
end
|
59
|
-
|
60
|
-
def with_message(notification_message, &block)
|
61
|
-
with(notification_with_message(notification_message), &block)
|
62
|
-
end
|
63
|
-
|
64
|
-
def create_notification(custom_params)
|
65
|
-
params = { data: { 'text' => "@trackinguser +2h" }, date: "2012-10-28T21:06:14.801Z", member_creator: stub(username: "pietrodibello") }
|
66
|
-
params.merge!(custom_params)
|
67
|
-
|
68
|
-
stub(data: params[:data], date: params[:date], member_creator: params[:member_creator]).as_null_object
|
69
|
-
end
|
70
|
-
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
def unrecognized_notification
|
3
|
+
create_notification(data: { 'text' => '@trackinguser hi there!' })
|
4
|
+
end
|
5
|
+
|
6
|
+
def notification_with_message(message)
|
7
|
+
create_notification(data: { 'text' => message })
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_estimate(time_measurement)
|
11
|
+
create_notification(data: { 'text' => "@trackinguser [1.5#{TIME_MEASUREMENTS[time_measurement]}]" })
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_effort(time_measurement)
|
15
|
+
create_notification(data: { 'text' => "@trackinguser +4.5#{TIME_MEASUREMENTS[time_measurement]}]" })
|
16
|
+
end
|
17
|
+
|
18
|
+
def with(notification)
|
19
|
+
tracking = Tracking::Factory.build_from(notification)
|
20
|
+
yield(tracking)
|
21
|
+
end
|
22
|
+
|
23
|
+
def with_message(notification_message, &block)
|
24
|
+
with(notification_with_message(notification_message), &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_notification(custom_params)
|
28
|
+
params = { data: { 'text' => "@trackinguser +2h" }, date: "2012-10-28T21:06:14.801Z", member_creator: stub(username: "pietrodibello") }
|
29
|
+
params.merge!(custom_params)
|
30
|
+
|
31
|
+
stub(data: params[:data], date: params[:date], member_creator: params[:member_creator]).as_null_object
|
32
|
+
end
|
data/spec/tracked_card_spec.rb
CHANGED
@@ -8,6 +8,11 @@ describe TrackedCard do
|
|
8
8
|
|
9
9
|
subject(:card) { build(:tracked_card) }
|
10
10
|
|
11
|
+
before(:each) do
|
12
|
+
# adding a muted effort to check that won't be counted
|
13
|
+
card.efforts << build(:effort, amount: 1000, muted: true)
|
14
|
+
end
|
15
|
+
|
11
16
|
%w{piero tommaso michele}.each do |username|
|
12
17
|
let(username.to_sym) { Member.new(username: username) }
|
13
18
|
end
|
@@ -40,60 +45,67 @@ describe TrackedCard do
|
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
|
-
describe ".
|
44
|
-
it "finds all
|
45
|
-
|
46
|
-
|
47
|
-
:efforts => [Effort.new(amount: 3, date: Date.today, members: [piero])])
|
48
|
-
card_without_tracking = create(:tracked_card)
|
48
|
+
describe ".with_effort_spent_by" do
|
49
|
+
it "finds all the cards worked by a given member" do
|
50
|
+
card = create(:tracked_card, efforts: [build(:effort, members: [piero, tommaso])])
|
51
|
+
another_card = create(:tracked_card, efforts: [build(:effort, members: [piero, michele])])
|
49
52
|
|
53
|
+
TrackedCard.with_effort_spent_by("piero").should =~ [card, another_card]
|
54
|
+
TrackedCard.with_effort_spent_by("tommaso").should == [card]
|
55
|
+
TrackedCard.with_effort_spent_by("michele").should == [another_card]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe ".efforts_between" do
|
60
|
+
it "finds all the cards worked in a given date range" do
|
61
|
+
a_card = create(:tracked_card, efforts: [build(:effort, date: Date.parse("2013-01-02"))])
|
62
|
+
another_card = create(:tracked_card, efforts: [build(:effort, date: Date.parse("2013-11-03"))])
|
63
|
+
a_very_old_card = create(:tracked_card, efforts: [build(:effort, date: Date.parse("2009-11-03"))])
|
50
64
|
|
51
|
-
TrackedCard.
|
65
|
+
TrackedCard.efforts_between(from_date: Date.parse("2012-01-01")).should =~ [a_card, another_card]
|
66
|
+
TrackedCard.efforts_between(from_date: Date.parse("2013-01-01")).should =~ [a_card, another_card]
|
67
|
+
TrackedCard.efforts_between(from_date: Date.parse("2013-01-22")).should == [another_card]
|
68
|
+
TrackedCard.efforts_between(from_date: Date.parse("2014-01-22")).should == []
|
69
|
+
|
70
|
+
TrackedCard.efforts_between(from_date: Date.parse("2012-01-01"), to_date: Date.parse("2012-11-01")).should == []
|
71
|
+
TrackedCard.efforts_between(from_date: Date.parse("2012-01-01"), to_date: Date.parse("2013-02-02")).should == [a_card]
|
72
|
+
TrackedCard.efforts_between(from_date: Date.parse("2012-01-01"), to_date: Date.parse("2014-02-02")).should =~ [a_card, another_card]
|
52
73
|
end
|
74
|
+
end
|
53
75
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
76
|
+
describe ".all_tracked_cards" do
|
77
|
+
let!(:card) { create(:tracked_card, name: "AAA", estimates: [build(:estimate)], efforts: [build(:effort)]) }
|
78
|
+
let!(:another_card) { create(:tracked_card, name: "ZZZ", estimates: [build(:estimate)], efforts: [build(:effort)]) }
|
79
|
+
let!(:card_without_tracking) { create(:tracked_card) }
|
58
80
|
|
59
|
-
|
60
|
-
|
61
|
-
|
81
|
+
it "finds all tracked cards with a valid tracking" do
|
82
|
+
TrackedCard.all_tracked_cards.should =~ [card, another_card]
|
83
|
+
end
|
62
84
|
|
63
|
-
|
85
|
+
it "optionally sorts the cards using a given sorting method" do
|
86
|
+
card.update_attributes(name: "AAA")
|
87
|
+
another_card.update_attributes(name: "ZZZ")
|
64
88
|
|
65
|
-
TrackedCard.all_tracked_cards(:
|
89
|
+
TrackedCard.all_tracked_cards(:sort_by => :name).should == [card, another_card]
|
66
90
|
end
|
67
91
|
|
68
92
|
it "applies an optional sorting order" do
|
69
|
-
card
|
70
|
-
|
71
|
-
card.efforts << Effort.new(amount: 3, date: Date.today, members: [piero])
|
72
|
-
|
73
|
-
another_card = create(:tracked_card, name: "ZZZ")
|
74
|
-
another_card.estimates << Estimate.new(amount: 5, date: Date.today)
|
75
|
-
another_card.efforts << Effort.new(amount: 3, date: Date.today, members: [piero])
|
93
|
+
card.update_attributes(name: "AAA")
|
94
|
+
another_card.update_attributes(name: "ZZZ")
|
76
95
|
|
77
96
|
card_without_tracking = create(:tracked_card)
|
78
97
|
|
79
|
-
TrackedCard.all_tracked_cards(:
|
98
|
+
TrackedCard.all_tracked_cards(:sort_by => :name, :order => :desc).should == [another_card, card]
|
80
99
|
end
|
81
100
|
|
82
101
|
it "uses the ascending order as default sorting order option" do
|
83
|
-
card
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
another_card = create(:tracked_card, name: "ZZZ", short_id: 12)
|
88
|
-
another_card.estimates << Estimate.new(amount: 5, date: Date.today)
|
89
|
-
another_card.efforts << Effort.new(amount: 3, date: Date.today, members: [piero])
|
102
|
+
card.update_attributes(name: "AAA", short_id: 44)
|
103
|
+
another_card.update_attributes(name: "ZZZ", short_id: 11)
|
104
|
+
card_without_tracking.update_attributes(short_id: 3456)
|
90
105
|
|
91
|
-
|
92
|
-
|
93
|
-
TrackedCard.all_tracked_cards(:method => :short_id).should == [another_card, card]
|
106
|
+
TrackedCard.all_tracked_cards(:sort_by => :short_id).should == [another_card, card]
|
94
107
|
end
|
95
108
|
|
96
|
-
|
97
109
|
end
|
98
110
|
|
99
111
|
describe ".update_or_create_with" do
|
@@ -162,22 +174,39 @@ describe TrackedCard do
|
|
162
174
|
|
163
175
|
end
|
164
176
|
|
177
|
+
describe "card with muted effort" do
|
178
|
+
it "fetches only non-muted efforts" do
|
179
|
+
card = create(:tracked_card, efforts: [build(:effort, muted: false)])
|
180
|
+
card_with_muted_effort = create(:tracked_card, efforts: [build(:effort, muted: true)])
|
181
|
+
|
182
|
+
TrackedCard.should have(2).cards
|
183
|
+
|
184
|
+
card.efforts.should have(1).effort
|
185
|
+
|
186
|
+
card_with_muted_effort.efforts.should be_empty
|
187
|
+
card_with_muted_effort.efforts.unscoped.should have(1).effort
|
188
|
+
end
|
189
|
+
|
190
|
+
it "skips muted effort when computing the total effort on the card" do
|
191
|
+
card.efforts << build(:effort, amount: 3, muted: true)
|
192
|
+
card.efforts << build(:effort, amount: 5, muted: false)
|
193
|
+
|
194
|
+
card.total_effort.should == 5
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
165
198
|
it "has no estimates and efforts initially" do
|
166
199
|
card.estimates.should be_empty
|
167
200
|
card.efforts.should be_empty
|
168
201
|
end
|
169
202
|
|
170
203
|
it "is possible to add estimates" do
|
171
|
-
card.estimates <<
|
172
|
-
card.estimates << Estimate.new(amount: 12, date: Date.today)
|
173
|
-
|
204
|
+
card.estimates << build(:estimate) << build(:estimate)
|
174
205
|
card.estimates.should have(2).estimates
|
175
206
|
end
|
176
207
|
|
177
208
|
it "is possible to add efforts" do
|
178
|
-
card.efforts <<
|
179
|
-
card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
|
180
|
-
|
209
|
+
card.efforts << build(:effort) << build(:effort)
|
181
210
|
card.efforts.should have(2).efforts
|
182
211
|
end
|
183
212
|
|
@@ -185,14 +214,26 @@ describe TrackedCard do
|
|
185
214
|
let(:first_notification) { stub("notification1", date: Date.yesterday) }
|
186
215
|
let(:second_notification) { stub("notification1", date: Date.today) }
|
187
216
|
|
188
|
-
it "
|
217
|
+
it "fetches all the card notifications from trello" do
|
189
218
|
card.estimates << Estimate.new(tracking_notification_id: "xyz987", amount: 5, date: Date.yesterday)
|
190
219
|
card.efforts << Effort.new(tracking_notification_id: "abc123", amount: 3, date: Date.today, members: [piero])
|
191
220
|
|
192
221
|
Trello::Notification.should_receive(:find).with("xyz987").and_return(second_notification)
|
193
222
|
Trello::Notification.should_receive(:find).with("abc123").and_return(first_notification)
|
223
|
+
|
194
224
|
card.trello_notifications.should == [first_notification, second_notification]
|
195
225
|
end
|
226
|
+
|
227
|
+
it "skips the notifications not found" do
|
228
|
+
card.estimates << build(:estimate, tracking_notification_id: "unexisting_id")
|
229
|
+
card.efforts << build(:effort, tracking_notification_id: "first_notification_id")
|
230
|
+
|
231
|
+
Trello::Notification.should_receive(:find).with("unexisting_id").and_raise(Trello::Error)
|
232
|
+
Trello::Notification.should_receive(:find).with("first_notification_id").and_return(first_notification)
|
233
|
+
|
234
|
+
card.trello_notifications.should == [first_notification]
|
235
|
+
end
|
236
|
+
|
196
237
|
end
|
197
238
|
|
198
239
|
describe "equality" do
|
@@ -207,7 +248,7 @@ describe TrackedCard do
|
|
207
248
|
end
|
208
249
|
|
209
250
|
describe "#add" do
|
210
|
-
let(:card) {
|
251
|
+
let(:card) { build(:tracked_card) }
|
211
252
|
let(:estimate_tracking) { Tracking::EstimateTracking.new(create_notification(data: { 'text' => "@trackinguser [1h]" })) }
|
212
253
|
|
213
254
|
it "adds an estimate from a tracking estimate notification" do
|
@@ -232,7 +273,7 @@ describe TrackedCard do
|
|
232
273
|
end
|
233
274
|
|
234
275
|
describe "#add!" do
|
235
|
-
let(:card) {
|
276
|
+
let(:card) { build(:tracked_card) }
|
236
277
|
|
237
278
|
it "saves the tracked card after adding the tracking" do
|
238
279
|
any_tracking = Tracking::EstimateTracking.new(create_notification(data: { 'text' => "@trackinguser [1h]" }))
|
@@ -248,50 +289,51 @@ describe TrackedCard do
|
|
248
289
|
end
|
249
290
|
|
250
291
|
it "computes the total effort on the card" do
|
251
|
-
card.efforts <<
|
252
|
-
card.efforts <<
|
292
|
+
card.efforts << build(:effort, amount: 3)
|
293
|
+
card.efforts << build(:effort, amount: 5)
|
253
294
|
|
254
295
|
card.total_effort.should == 3+5
|
255
296
|
end
|
256
297
|
end
|
257
298
|
|
258
299
|
describe "#last_estimate_error" do
|
300
|
+
|
259
301
|
it "is nil when the card has no estimate" do
|
260
|
-
card.efforts <<
|
302
|
+
card.efforts << build(:effort, amount: 5)
|
261
303
|
|
262
304
|
card.last_estimate_error.should be_nil
|
263
305
|
end
|
264
306
|
|
265
307
|
it "is nil when the card has no effort" do
|
266
|
-
card.efforts <<
|
308
|
+
card.efforts << build(:estimate)
|
267
309
|
|
268
310
|
card.last_estimate_error.should be_nil
|
269
311
|
end
|
270
312
|
|
271
313
|
it "is zero when actual effort is equal to estimate" do
|
272
|
-
card.estimates <<
|
273
|
-
card.efforts <<
|
314
|
+
card.estimates << build(:estimate, amount: 5)
|
315
|
+
card.efforts << build(:effort, amount: 5)
|
274
316
|
|
275
317
|
card.last_estimate_error.should == 0.0
|
276
318
|
end
|
277
319
|
|
278
320
|
it "is 100 when the actual effort is twice the given estimate" do
|
279
|
-
card.estimates <<
|
280
|
-
card.efforts <<
|
321
|
+
card.estimates << build(:estimate, amount: 5)
|
322
|
+
card.efforts << build(:effort, amount: 10)
|
281
323
|
|
282
324
|
card.last_estimate_error.should == 100.0
|
283
325
|
end
|
284
326
|
|
285
327
|
it "is -50 when the actual effort is half of the given estimate" do
|
286
|
-
card.estimates <<
|
287
|
-
card.efforts <<
|
328
|
+
card.estimates << build(:estimate, amount: 10)
|
329
|
+
card.efforts << build(:effort, amount: 5)
|
288
330
|
|
289
331
|
card.last_estimate_error.should == -50.0
|
290
332
|
end
|
291
333
|
|
292
334
|
it "is rounded with two decimal digits" do
|
293
|
-
card.estimates <<
|
294
|
-
card.efforts <<
|
335
|
+
card.estimates << build(:estimate, amount: 3)
|
336
|
+
card.efforts << build(:effort, amount: 5)
|
295
337
|
|
296
338
|
card.last_estimate_error.should == 66.67
|
297
339
|
end
|
@@ -313,9 +355,9 @@ describe TrackedCard do
|
|
313
355
|
|
314
356
|
describe "#members" do
|
315
357
|
it "lists all the members which spent some effort on the card" do
|
316
|
-
card.efforts <<
|
317
|
-
card.efforts <<
|
318
|
-
card.efforts <<
|
358
|
+
card.efforts << build(:effort, members: [piero, tommaso])
|
359
|
+
card.efforts << build(:effort, members: [tommaso])
|
360
|
+
card.efforts << build(:effort, members: [tommaso, michele])
|
319
361
|
|
320
362
|
card.members.should == [piero, tommaso, michele]
|
321
363
|
end
|
@@ -324,9 +366,9 @@ describe TrackedCard do
|
|
324
366
|
describe "#working_start_date" do
|
325
367
|
|
326
368
|
it "is the date of the first effort spent on the card" do
|
327
|
-
card.efforts <<
|
328
|
-
card.efforts <<
|
329
|
-
card.efforts <<
|
369
|
+
card.efforts << build(:effort, date: Date.today)
|
370
|
+
card.efforts << build(:effort, date: Date.yesterday)
|
371
|
+
card.efforts << build(:effort, date: Date.tomorrow)
|
330
372
|
|
331
373
|
card.working_start_date.should == Date.yesterday
|
332
374
|
end
|
@@ -334,12 +376,12 @@ describe TrackedCard do
|
|
334
376
|
|
335
377
|
describe "#first_activity_date" do
|
336
378
|
it "is the date of the first effort or estimate given on the card" do
|
337
|
-
card.estimates <<
|
338
|
-
card.estimates <<
|
339
|
-
card.estimates <<
|
379
|
+
card.estimates << build(:estimate, date: Date.yesterday)
|
380
|
+
card.estimates << build(:estimate, date: Date.yesterday.prev_day)
|
381
|
+
card.estimates << build(:estimate, date: Date.tomorrow)
|
340
382
|
|
341
|
-
card.efforts <<
|
342
|
-
card.efforts <<
|
383
|
+
card.efforts << build(:effort, date: Date.yesterday)
|
384
|
+
card.efforts << build(:effort, date: Date.today)
|
343
385
|
|
344
386
|
card.first_activity_date.should == Date.yesterday.prev_day
|
345
387
|
end
|
@@ -347,9 +389,9 @@ describe TrackedCard do
|
|
347
389
|
|
348
390
|
describe "#first_estimate_date" do
|
349
391
|
it "is the date of the first estimate given on the card" do
|
350
|
-
card.estimates <<
|
351
|
-
card.estimates <<
|
352
|
-
card.estimates <<
|
392
|
+
card.estimates << build(:estimate, date: Date.tomorrow)
|
393
|
+
card.estimates << build(:estimate, date: Date.yesterday.prev_day)
|
394
|
+
card.estimates << build(:estimate, date: Date.today)
|
353
395
|
|
354
396
|
card.first_estimate_date.should == Date.yesterday.prev_day
|
355
397
|
end
|
@@ -357,9 +399,9 @@ describe TrackedCard do
|
|
357
399
|
|
358
400
|
describe "#last_estimate_date" do
|
359
401
|
it "is the date of the last estimate given on the card" do
|
360
|
-
card.estimates <<
|
361
|
-
card.estimates <<
|
362
|
-
card.estimates <<
|
402
|
+
card.estimates << build(:estimate, date: Date.yesterday)
|
403
|
+
card.estimates << build(:estimate, date: Date.tomorrow)
|
404
|
+
card.estimates << build(:estimate, date: Date.today)
|
363
405
|
|
364
406
|
card.last_estimate_date.should == Date.tomorrow
|
365
407
|
end
|
@@ -369,7 +411,7 @@ describe TrackedCard do
|
|
369
411
|
it "is false when there's no effort or estimate tracked on the card" do
|
370
412
|
card.no_tracking?.should be_true
|
371
413
|
|
372
|
-
card.estimates <<
|
414
|
+
card.estimates << build(:estimate, date: Date.yesterday)
|
373
415
|
card.no_tracking?.should be_false
|
374
416
|
end
|
375
417
|
end
|
@@ -387,10 +429,10 @@ describe TrackedCard do
|
|
387
429
|
|
388
430
|
describe "#status" do
|
389
431
|
it "is done when is done" do
|
390
|
-
done_card = TrackedCard.new(done:true)
|
432
|
+
done_card = TrackedCard.new(done: true)
|
391
433
|
done_card.status.should == :done
|
392
434
|
|
393
|
-
done_card.efforts <<
|
435
|
+
done_card.efforts << build(:effort)
|
394
436
|
done_card.status.should == :done
|
395
437
|
end
|
396
438
|
|
@@ -398,7 +440,7 @@ describe TrackedCard do
|
|
398
440
|
card = TrackedCard.new
|
399
441
|
card.status.should == :todo
|
400
442
|
|
401
|
-
card.efforts <<
|
443
|
+
card.efforts << build(:effort)
|
402
444
|
card.status.should == :in_progress
|
403
445
|
end
|
404
446
|
end
|
@@ -7,7 +7,7 @@ module Tracking
|
|
7
7
|
it "marks the card as done" do
|
8
8
|
card = TrackedCard.new
|
9
9
|
|
10
|
-
done_tracking =
|
10
|
+
done_tracking = Tracking::Factory.build_from(notification_with_message("DONE"))
|
11
11
|
done_tracking.add_to(card)
|
12
12
|
|
13
13
|
card.done?.should be_true
|
@@ -28,7 +28,7 @@ module Tracking
|
|
28
28
|
date: "2012-10-28T21:06:14.801Z",
|
29
29
|
member_creator: stub(username: "michelepangrazzi"))
|
30
30
|
|
31
|
-
|
31
|
+
Tracking::Factory.build_from(raw_data).effort.should == Effort.new(amount: 2.0, date: Date.parse('2012-10-28'), members: [michelepangrazzi])
|
32
32
|
end
|
33
33
|
|
34
34
|
it "converts the effort in hours when the notification contains an effort in days" do
|
@@ -87,7 +87,7 @@ module Tracking
|
|
87
87
|
it "tracks the effort with the date given in the notification text, not the actual notification date" do
|
88
88
|
raw_data = create_notification(data: { 'text' => "@trackinguser 22.11.2012 +6p" }, date: "2012-09-19T12:46:13.713Z")
|
89
89
|
|
90
|
-
tracking =
|
90
|
+
tracking = Tracking::Factory.build_from(raw_data)
|
91
91
|
|
92
92
|
tracking.effort.date.should == Date.parse('2012-11-22')
|
93
93
|
end
|
@@ -95,7 +95,7 @@ module Tracking
|
|
95
95
|
it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
|
96
96
|
raw_data = create_notification(data: { 'text' => "@trackinguser yesterday +6p" }, date: "2012-09-19T12:46:13.713Z")
|
97
97
|
|
98
|
-
tracking =
|
98
|
+
tracking = Tracking::Factory.build_from(raw_data)
|
99
99
|
|
100
100
|
tracking.effort.date.should == Date.parse('2012-09-18')
|
101
101
|
end
|
@@ -103,7 +103,7 @@ module Tracking
|
|
103
103
|
it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
|
104
104
|
raw_data = create_notification(data: { 'text' => "@trackinguser +6p yesterday" }, date: "2012-09-19T12:46:13.713Z")
|
105
105
|
|
106
|
-
tracking =
|
106
|
+
tracking = Tracking::Factory.build_from(raw_data)
|
107
107
|
|
108
108
|
tracking.effort.date.should == Date.parse('2012-09-18')
|
109
109
|
end
|
@@ -6,34 +6,34 @@ module Tracking
|
|
6
6
|
describe "#estimate" do
|
7
7
|
|
8
8
|
it "is nil when the notification does not contain an estimate" do
|
9
|
-
|
9
|
+
Tracking::Factory.build_from(unrecognized_notification).estimate.should be_nil
|
10
10
|
end
|
11
11
|
|
12
12
|
it "is the hour-based estimate when the notification contains an estimate in hours" do
|
13
13
|
raw_data = create_notification(data: { 'text' => "@trackinguser [2h]" }, date: "2012-10-28T21:06:14.801Z")
|
14
14
|
|
15
|
-
|
15
|
+
Tracking::Factory.build_from(raw_data).estimate.should == Estimate.new(amount: 2.0, date: Date.parse('2012-10-28'))
|
16
16
|
end
|
17
17
|
|
18
18
|
it "converts the estimate in hours when the notification contains an estimate in days" do
|
19
|
-
|
20
|
-
|
19
|
+
Tracking::Factory.build_from(create_notification(data: { 'text' => "@trackinguser [1.5d]" })).estimate.amount.should == 8+4
|
20
|
+
Tracking::Factory.build_from(create_notification(data: { 'text' => "@trackinguser [1.5g]" })).estimate.amount.should == 8+4
|
21
21
|
end
|
22
22
|
|
23
23
|
it "converts the estimate in hours when the notification contains an estimate in pomodori" do
|
24
24
|
raw_data = create_notification(data: { 'text' => "@trackinguser [10p]" })
|
25
|
-
|
25
|
+
Tracking::Factory.build_from(raw_data).estimate.amount.should == 5
|
26
26
|
end
|
27
27
|
|
28
28
|
it "fetch the estimate from a complex estimate message" do
|
29
29
|
raw_data = create_notification(data: { 'text' => "@maxmazza Dobbiamo ancora lavorarci.\n@trackinguser ristimo ancora [3h] per il fix" })
|
30
|
-
|
30
|
+
Tracking::Factory.build_from(raw_data).estimate.amount.should == 3.0
|
31
31
|
end
|
32
32
|
|
33
33
|
it "tracks the effort with the date given in the notification text, not the actual notification date" do
|
34
34
|
raw_data = create_notification( data: { 'text' => "@trackinguser 22.11.2012 [6p]" }, date: "2012-09-19T12:46:13.713Z")
|
35
35
|
|
36
|
-
tracking =
|
36
|
+
tracking = Tracking::Factory.build_from(raw_data)
|
37
37
|
|
38
38
|
tracking.estimate.date.should == Date.parse('2012-11-22')
|
39
39
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Tracking::Factory do
|
4
4
|
|
5
5
|
TIME_MEASUREMENTS = {
|
6
6
|
hours: 'h',
|
@@ -11,7 +11,7 @@ describe TrackingFactory do
|
|
11
11
|
|
12
12
|
context "unknown tracking format" do
|
13
13
|
it "builds an invalid tracking instance" do
|
14
|
-
|
14
|
+
Tracking::Factory.build_from(unrecognized_notification).class.should == Tracking::InvalidTracking
|
15
15
|
|
16
16
|
with_message("@trackinguser +30m") { |tracking| tracking.class.should == Tracking::InvalidTracking }
|
17
17
|
end
|
@@ -21,13 +21,13 @@ describe TrackingFactory do
|
|
21
21
|
|
22
22
|
context "estimate tracking notification in #{time_measurement}" do
|
23
23
|
it "builds an estimate tracking instance" do
|
24
|
-
|
24
|
+
Tracking::Factory.build_from(create_estimate(time_measurement)).class.should == Tracking::EstimateTracking
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
context "effort tracking notification in #{time_measurement}" do
|
29
29
|
it "builds an effort tracking instance" do
|
30
|
-
|
30
|
+
Tracking::Factory.build_from(create_effort(time_measurement)).class.should == Tracking::EffortTracking
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
data/tracco.sublime-project
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tracco
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby-trello
|
@@ -272,8 +272,8 @@ files:
|
|
272
272
|
- lib/tracco/tracking/card_done_tracking.rb
|
273
273
|
- lib/tracco/tracking/effort_tracking.rb
|
274
274
|
- lib/tracco/tracking/estimate_tracking.rb
|
275
|
+
- lib/tracco/tracking/factory.rb
|
275
276
|
- lib/tracco/tracking/invalid_tracking.rb
|
276
|
-
- lib/tracco/tracking_factory.rb
|
277
277
|
- lib/tracco/trello_authorize.rb
|
278
278
|
- lib/tracco/trello_configuration.rb
|
279
279
|
- lib/tracco/trello_tracker.rb
|
@@ -284,6 +284,8 @@ files:
|
|
284
284
|
- script/mate.sh
|
285
285
|
- spec/effort_spec.rb
|
286
286
|
- spec/estimate_spec.rb
|
287
|
+
- spec/factories/effort_factory.rb
|
288
|
+
- spec/factories/estimate_factory.rb
|
287
289
|
- spec/factories/tracked_card_factory.rb
|
288
290
|
- spec/integration/trello_authorization_spec.rb
|
289
291
|
- spec/integration/trello_tracker_spec.rb
|
@@ -291,6 +293,7 @@ files:
|
|
291
293
|
- spec/patches/trello/card_spec.rb
|
292
294
|
- spec/spec_helper.rb
|
293
295
|
- spec/support/database_cleaner.rb
|
296
|
+
- spec/support/spec_helper_methods.rb
|
294
297
|
- spec/tracked_card_spec.rb
|
295
298
|
- spec/tracking/card_done_tracking_spec.rb
|
296
299
|
- spec/tracking/effort_tracking_spec.rb
|
@@ -315,7 +318,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
315
318
|
version: '0'
|
316
319
|
segments:
|
317
320
|
- 0
|
318
|
-
hash:
|
321
|
+
hash: 1645942165596305334
|
319
322
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
320
323
|
none: false
|
321
324
|
requirements:
|
@@ -1,22 +0,0 @@
|
|
1
|
-
class TrackingFactory
|
2
|
-
|
3
|
-
DURATION_REGEXP = '(\d+\.?\d*[phdg])'
|
4
|
-
|
5
|
-
@match_pairs = {}
|
6
|
-
|
7
|
-
def self.match(match_pair)
|
8
|
-
@match_pairs.merge!(match_pair)
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.build_from(tracking_notification)
|
12
|
-
matching_pair = @match_pairs.find { |regexp, tracking_class| tracking_notification.data['text'] =~ regexp }
|
13
|
-
|
14
|
-
tracking_class = matching_pair ? matching_pair.last : Tracking::InvalidTracking
|
15
|
-
tracking_class.new(tracking_notification)
|
16
|
-
end
|
17
|
-
|
18
|
-
match /\[#{DURATION_REGEXP}\]/ => Tracking::EstimateTracking
|
19
|
-
match /\+#{DURATION_REGEXP}/ => Tracking::EffortTracking
|
20
|
-
match /DONE/ => Tracking::CardDoneTracking
|
21
|
-
|
22
|
-
end
|