2 using System
.Collections
;
6 namespace Wv
.Schedulator
8 public class Task
: IComparable
10 public Task(Source source
, string id
, string name
)
17 public int array_index
; // used by TaskList; don't touch!
25 get { return source.name + ":" + id; }
33 public Person assignedto
;
36 public bool halfdone
; // eg. "needs verification" bugs
37 public DateTime donedate
;
39 // set no more than two of the startdate, duedate, and work
40 // estimate, or scheduling results may be undefined!
41 public DateTime startdate
, duedate
;
43 public TimeSpan origest
, currest
, elapsed
;
44 public TimeSpan remain
46 get { return currest - elapsed; }
49 public bool is_estimated()
51 return !wv
.isempty(currest
) || !wv
.isempty(elapsed
);
54 public DateSlider habits
;
55 public DateSlider
find_habits()
59 else if (fixfor
!= null
60 && fixfor
.default_habits
!= null)
61 return fixfor
.default_habits
;
62 else if (fixfor
!= null && fixfor
.project
!= null
63 && fixfor
.project
.default_habits
!= null)
64 return fixfor
.project
.default_habits
;
66 return source
.s
.default_habits
;
69 public int firstpriority()
71 if (parent
!= null && parent
.priority
< priority
)
72 return parent
.firstpriority();
77 public FixFor
firstfixfor()
80 return null; // null fixfors always come "first"
81 if (parent
!= null && fixfor
.CompareTo(parent
.fixfor
) > 0)
82 return parent
.firstfixfor();
87 public bool has_ancestor(Task t
)
89 for (Task p
= parent
; p
!= null; p
= p
.parent
)
98 for (Task t
= parent
; t
!= null; t
= t
.parent
)
103 public Task
up(int n
)
106 for (int i
= 0; i
< n
; i
++)
111 // Note: the duedate field doesn't affect bug comparisons, because
112 // this is really a "bug priority comparison" algorithm, and simply
113 // having a due date doesn't make a bug more important. That said,
114 // it *might* make it get scheduled earlier than a more important bug,
115 // but that's a job for the scheduling algorithm, and there are too
116 // many variables involved in that to be able to include it in a
117 // simple bug-vs-bug comparison like this one.
119 // This prioritized list is useful for the scheduler, but it will have
120 // to pull out the due-date bugs and insert them at the appropriate
122 public int CompareTo(object _y
)
125 return 1; // null task? Oh well, it comes first.
130 return done
? -1 : 1;
131 else if (done
) // so also y.done
133 if (donedate
!= y
.donedate
)
134 return donedate
.CompareTo(y
.donedate
);
135 else // just preserve the original array ordering
136 return array_index
- y
.array_index
;
138 else if (firstfixfor() != y
.firstfixfor()) // & !done & !y.done
140 if (firstfixfor() == null)
141 return -y
.firstfixfor().CompareTo(firstfixfor());
143 return firstfixfor().CompareTo(y
.firstfixfor());
145 else if (firstpriority() != y
.firstpriority())
147 // default priority 0 should be the highest - it means the
148 // task is uncategorized, so it should be at the top to
149 // remind you to prioritize it ASAP.
150 return firstpriority() - y
.firstpriority();
152 else if (y
.has_ancestor(this))
153 return -1; // parent before child
154 else if (has_ancestor(y
))
155 return 1; // child after parent
156 else if (parent
!= y
.parent
)
158 // this is a bit complicated. If two subtasks are mostly
159 // equal but have different parents, this will order them
160 // in the same order as their parent. That sort of makes
161 // sense, since if one parent is more important than
162 // another parent, we might as well do all his subtasks
163 // before the less-important-parent's subtasks, but only
164 // if the subtasks themselves are otherwise equivalent.
167 // Anyway, the real reason this is important is that we
168 // want to group all of each parent's subtasks together
169 // in the much more common case that all the parents, and
170 // all the subtasks, have the same priority.
172 int dx
= depth(), dy
= y
.depth();
175 int d
= -y
.CompareTo(up(dx
-dy
));
177 return 1; // I'm deeper, so I'm later
183 int d
= CompareTo(y
.up(dy
-dx
));
185 return -1; // y is deeper, so I'm earlier
190 return parent
.CompareTo(y
.parent
);
192 else // preserve the original array ordering
193 return array_index
- y
.array_index
;
198 public class TaskList
: SortedHash
200 protected string make_key(Source source
, string id
)
202 return source
.name
+ "\0" + id
;
205 public Task
Add(Source source
, string id
, string name
)
207 Task t
= new Task(source
, id
, name
);
208 base.Add(make_key(source
, id
), t
);
209 t
.array_index
= Count
-1;
213 #pragma warning disable 0109 // appease mono 1.1.13.6
214 public new virtual Task
this[int index
]
216 get { return (Task)base[index]; }
218 #pragma warning restore 0109
220 public Task
Find(Source source
, string id
)
222 return (Task
)base.Find(make_key(source
, id
));
225 public Task
FindByName(string name
)
227 foreach (Task t
in this)
233 public Task
FindById(string id
)
235 foreach (Task t
in this)
236 if (id
== t
.id
|| id
== (t
.source
.name
+ ":" + t
.id
))
241 public override void Sort()
243 // note: this doesn't update the array_index field, because
244 // it's the *original* array_index that is most useful.