Class: DevFlow::Task

Inherits:
Object
  • Object
show all
Defined in:
lib/dev_flow/task.rb,
lib/dev_flow/task_js.rb,
lib/dev_flow/task_console.rb

Overview

Task object represent a single line on the Gantt chart

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(level, file = "-", ln = 0) ⇒ Task

initialize with level, file and line number



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/dev_flow/task.rb', line 20

def initialize level,file="-",ln=0
  @level = level.to_i
  raise "invalid level #{level}" unless level.to_i > 0
  @file, @ln = file, ln
  @children = Array.new
  @dependencies = Array.new
  @dependencie_names = Array.new
  @progress = 0
  @resources = Array.new
  @resource_names = Array.new
end

Instance Attribute Details

#branch_nameObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def branch_name
  @branch_name
end

#childrenObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def children
  @children
end

#completed_atObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def completed_at
  @completed_at
end

#dependencie_namesObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def dependencie_names
  @dependencie_names
end

#dependenciesObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def dependencies
  @dependencies
end

#display_nameObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def display_name
  @display_name
end

#end_dateObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def end_date
  @end_date
end

#fileObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def file
  @file
end

#is_deletedObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def is_deleted
  @is_deleted
end

#is_pendingObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def is_pending
  @is_pending
end

#levelObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def level
  @level
end

#lnObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def ln
  @ln
end

#parentObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def parent
  @parent
end

#progressObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def progress
  @progress
end

#resource_namesObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def resource_names
  @resource_names
end

#resourcesObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def resources
  @resources
end

#start_dateObject

which line of file defined the task



10
11
12
# File 'lib/dev_flow/task.rb', line 10

def start_date
  @start_date
end

Instance Method Details

#as_js(resource) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/dev_flow/task_js.rb', line 59

def as_js resource
  is_milestone_flag = self.is_milestone? ? 1 : 0
  is_parent_flag = self.is_parent? ? 1 : 0
  task_str = "    g.AddTaskItem(new JSGantt.TaskItem(%d,'%s','%s','%s','%s','%s',%d,'%s',%d,%d,%d,%d,'%s','%s'));\n"
  sprintf(task_str, self.task_id, self.display_name, 
          self.start_date.strftime("%m/%d/%Y"), 
          self.end_date.strftime("%m/%d/%Y"), 
          self.color(resource), '', is_milestone_flag, 
          self.resource_name, self.progress.to_i, is_parent_flag, 
          self.parent_id, 1, self.dependencies_str, self.caption)
end

#as_title(header = ' ') ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/dev_flow/task_console.rb', line 4

def as_title header = ' '
  name = self.display_name
  name = self.display_name.bold if self.is_workable?
  name = self.display_name.blue if self.progress > 0
  name = self.display_name.green if self.is_completed?
  name = self.display_name.magenta if self.is_urgent?
  name = self.display_name.red if self.is_delayed?

  if self.progress > 0 and self.progress < 100
    on_branch = sprintf "(=> %s, %02d%%)", self.branch_name.bold, self.progress
  end

  d1 = DateName.zh(self.start_date, DateTime.now.strftime("%F")).bold
  d2 = DateName.zh(self.end_date, DateTime.now.strftime("%F")).bold
  title = sprintf("%s[%s]%s (%s-%s) %s", '  '*(self.level-1), header, name, d1, d2, on_branch)
end

#captionObject



46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/dev_flow/task_js.rb', line 46

def caption 
  return "" if self.children.size > 0
  cap = self.resource_name
  cap = sprintf("Pending (%s)", cap) if self.is_pending?
  cap = sprintf("Deleted (%s)", cap) if self.is_deleted?
  if self.is_completed?
    cap += self.completed_at.strftime("%F")
  else
    cap += sprintf(':%02d\%', self.progress) if self.progress > 0
  end
  cap
end

#color(resource_ = nil) ⇒ Object

color reflects the status of a task, return a hex code without heading “#”



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/dev_flow/task_js.rb', line 22

def color resource_ = nil
  today = DateTime.now.strftime("%Y%m%d").to_i 
  start_day = self.start_date.strftime("%Y%m%d").to_i 
  end_day = self.end_date.strftime("%Y%m%d").to_i 
  hex = "B0C4DE" # light steel blue as default 
  hex = "808080" unless self.is_workable? # grey for no able to start
  hex = "FFFF00" if self.progress > 0 and self.progress < 100 # blue for working
  hex = "FFD700" if start_day == today and progress == 0 # gold for must start now
  hex = "FFA500" if end_day == today and self.progress < 100 # orange for master complete today
 
  hex = "008000" if self.is_completed?    # green for completed
  hex = "FF0000" if self.progress < 100 and today > end_day   # red for not completed on time 
  hex = "FF0000" if self.progress == 0 and today > start_day  # red for late start
  hex = "EEE8AA" if self.is_deleted?
  hex = "C0C0C0" if self.is_pending?
 #  puts hex + ":" + self.progress.to_s + ";" + DateTime.now.strftime("%Y%m%d") + ":" + self.start_date.strftime("%Y%m%d")

  if resource_
    hex = "CCCCCC" unless self.resources.include? resource_
  end

  hex
end

#dependencies_strObject



17
18
19
# File 'lib/dev_flow/task_js.rb', line 17

def dependencies_str
  self.dependencies.map {|d| d.task_id}.join ","
end

#is_completable?Boolean

a task is completable if all children complated

Returns:

  • (Boolean)


22
23
24
25
26
27
28
# File 'lib/dev_flow/task_console.rb', line 22

def is_completable?
  return false if self.is_completed? 
  self.children.each do |child|
    return false unless child.is_completed?
  end
  true
end

#is_completed?Boolean

Returns:

  • (Boolean)


41
42
43
# File 'lib/dev_flow/task.rb', line 41

def is_completed?
  self.progress == 100
end

#is_delayed?Boolean

usually red

Returns:

  • (Boolean)


67
68
69
70
71
72
73
74
# File 'lib/dev_flow/task.rb', line 67

def is_delayed? # usually red
  today = DateTime.now.strftime("%Y%m%d").to_i 
  start_day = self.start_date.strftime("%Y%m%d").to_i 
  end_day = self.end_date.strftime("%Y%m%d").to_i
  return true if self.progress < 100 and today > end_day
  return true if self.progress == 0 and today > start_day
  false
end

#is_deleted?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/dev_flow/task.rb', line 49

def is_deleted?
  self.is_deleted ? true : false
end

#is_milestone?Boolean

filter methods

Returns:

  • (Boolean)


33
34
35
# File 'lib/dev_flow/task.rb', line 33

def is_milestone?
  self.branch_name =~ /^(milestone|release)\_/ ? true : false
end

#is_parent?Boolean

Returns:

  • (Boolean)


53
54
55
# File 'lib/dev_flow/task.rb', line 53

def is_parent?
  self.children.size > 0 ? true : false
end

#is_pending?Boolean

Returns:

  • (Boolean)


45
46
47
# File 'lib/dev_flow/task.rb', line 45

def is_pending?
  self.is_pending ? true :false
end

#is_release?Boolean

Returns:

  • (Boolean)


37
38
39
# File 'lib/dev_flow/task.rb', line 37

def is_release?
  self.branch_name =~ /^release\_/ ? true : false
end

#is_urgent?Boolean

usually orange

Returns:

  • (Boolean)


57
58
59
60
61
62
63
64
65
# File 'lib/dev_flow/task.rb', line 57

def is_urgent?  # usually orange
  today = DateTime.now.strftime("%Y%m%d").to_i 
  start_day = self.start_date.strftime("%Y%m%d").to_i 
  end_day = self.end_date.strftime("%Y%m%d").to_i
  
  return true if start_day == today and progress == 0
  return true if end_day == today and self.progress < 100
  false
end

#is_workable?Boolean

a task is workable (can be started) if all children task and dependent task are completed

Returns:

  • (Boolean)


32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/dev_flow/task_console.rb', line 32

def is_workable?
  # trivial: if already completed, do not start again
  return false if self.is_completed?
  return false if self.is_pending or self.is_deleted

  self.dependencies.each do |t|
    return false unless t.is_completed?
  end

  self.children.each do |t|
    return false unless t.is_completed?
  end
  true
end

#parent_idObject



9
10
11
# File 'lib/dev_flow/task_js.rb', line 9

def parent_id
  self.parent ? self.parent.task_id : 0 
end

#parse(line, headers = {}) ⇒ Object

parse the line from file:ln (line number), initialize the task object



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/dev_flow/task.rb', line 93

def parse line, headers = {}
  line = line.strip # delete head/trailing spaces

  /^((?<branch_name_>[a-zA-Z0-9_\-\#\.\/]+):)?\s*(?<display_name_>.+)\s+(?<start_date_>(\d\d\d\d\/)?\d\d?\/\d\d?)(-(?<end_date_>(\d\d\d\d\/)?\d\d?\/\d\d?))?(\s+\@(?<resource_>[a-z\@\;]+))?(\:(?<status_>(P|D))?(?<progress_>[\d\/]+)?)?(\s+\-\>\s*(?<dependencies_>.+))?$/ =~ line

  # assign branch name and display name
  self.branch_name = branch_name_

  self.display_name = display_name_

  # assign start and end date
  end_date_ = start_date_ unless end_date_
  raise "no valid start date found on #{self.file}:#{self.ln}" unless start_date_ and start_date_.size > 0
  if headers["year"]
    start_date_ = headers["year"].to_s + "/" + start_date_ unless start_date_ =~ /^\d\d\d\d/
    end_date_ = headers["year"].to_s + "/" + end_date_ unless end_date_ =~ /^\d\d\d\d/
  end

  begin
    self.start_date = DateTime.parse(start_date_)
    self.end_date = DateTime.parse(end_date_)
  rescue Exception => e
    raise "invalid date on #{self.file}:#{self.ln}"  
  end
  
  # assign for the resources (user name)
  unless resource_
    if headers["leader"]
      resource_ = headers["leader"]
    else
      raise "no resource defined on #{self.file}:#{self.ln}"
    end
  end

  resource_.gsub!("\@", "") # @ for other user is optional
  resource_.split(";").each do |r|
    self.resources << r
    # if the user is listed on known members
    rname = r
    if headers["members"] and headers["members"][r] and headers["members"][r][0]
      rname = headers["members"][r][0]
    end
    self.resource_names << rname
  end

  if dependencies_
    dependencies_.strip!
    dependencies_.gsub!(/;$/, "")
    self.dependencie_names = dependencies_.split(/;/)
  end

  # pending or deleted status
  if status_
    if status_ == "P"
      self.is_pending = true
    elsif status_ == "D"
      self.is_deleted = true
    end
  end

  # progress
  if progress_
    if progress_ =~ /^\d\d?$/ and progress_.to_i > 0 and progress_.to_i < 100
      self.progress = progress_.to_i
    elsif progress_ =~ /^\d\d\d\d\/\d\d?\/\d\d?$/
      self.progress = 100
      self.completed_at = DateTime.parse(progress_)
    elsif progress_ =~ /^\d\d?\/\d\d?$/ and headers["year"]
      self.progress = 100
      self.completed_at = DateTime.parse(headers["year"].to_s + "/" + progress_.to_s)
    else
      msg = "worng format around progress parameter '#{progress_}', on #{self.file}:#{self.ln}"
      msg += " (HINT: use date to complete a task, not 100)" if progress_.to_i == 100
      raise msg
    end
  end

  self
end

#resource_nameObject



13
14
15
# File 'lib/dev_flow/task_js.rb', line 13

def resource_name
  self.resource_names.join ","
end

#task_idObject



5
6
7
# File 'lib/dev_flow/task_js.rb', line 5

def task_id
  self.ln
end

#validate!Object

check whether the task is well defined, raise error otherwise.



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/dev_flow/task.rb', line 77

def validate!
  if self.is_milestone?
    unless self.level == 1
      raise "you can only tag a top level task as a release, on #{self.file}:#{self.ln}" if self.branch_name =~ /^release\_/
    end
  end
  raise "resource not found on #{self.file}:#{self.ln}" unless self.resources.size > 0
  raise "display_name not found on #{self.file}:#{self.ln}" unless self.display_name
  raise "valid start_date not found on #{self.file}:#{self.ln}" unless self.start_date
  raise "wrong date on #{self.file}:#{self.ln}" unless self.start_date and self.end_date and self.start_date <= self.end_date

  self
end