Fixing a Test and Adding the Progression Feature
I found a flaw in my test, which was less detectable since I didn't have a good range test. The values were six months apart from each other, and I didn't realize that the partial value was calculated incorrectly. It should have been instead this:
TimeSpan fullValue = completionDate.Subtract(lastCompletionDate);
TimeSpan partialValue = currentDate.Subtract(lastCompletionDate);
I was calculating the higher end of the value (what was to come instead of what has elapsed. So, my final value was calculated in the Task's PercentageDue property defined below. I took the code from the test and adapted, refactoring the variable names to make more sense:
public double PercentageDue
{
get
{
//Return 100 if no due date
if (!this.Attributes.Contains("DueDate"))
return 100;
//Get the date values
DateTime dueDate = this.GetAttributeValue<DateTime>("DueDate");
DateTime currentDate = DateTime.Today;
//If the due date is less than the current date (overdue), return 100
if (dueDate < currentDate)
return 100;
DateTime originDate;
//If the last completed date has been provided, use this value
if (this.Attributes.Contains("LastCompletedDate"))
originDate = this.GetAttributeValue<DateTime>("LastCompletedDate");
//Otherwise, first time so use the creation date
else
originDate = this.GetAttributeValue<DateTime>("CreationDate");
//Get the time span difference between the date values
TimeSpan totalTime = dueDate.Subtract(originDate);
TimeSpan timeElapsed = currentDate.Subtract(originDate);
//Get the days value in double form
double totalDays = Convert.ToDouble(totalTime.Days);
double elapsedDays = Convert.ToDouble(timeElapsed.Days);
//Get the percentage value of dividing partial value
//by the full value; multiply by 100
return Math.Round((elapsedDays / totalDays) * 100, 1);
}
}
I also return a rounded value, instead of a true floating value.
Adding another column to the task list, I also provided the means to add the new field to the subitems list, so it is displayed in the interface. In addition, the due date calculation turned out to be complex, so I added another method to render it in the list view. If the current date is overdue, I wanted it to say "Overdue"; however, if the due date attribute isn't provided, I wanted it to say "Complete", and lastly, if the value is there, write it.
private string RenderDueDate(Task task)
{
if (task.Attributes.Contains("DueDate"))
{
DateTime dueDate = task.GetAttributeValue<DateTime>("DueDate");
if (dueDate < DateTime.Today)
return "Overdue";
else
return dueDate.ToShortDateString();
}
else
return "Completed";
}
It is rendered in the list view as such:
internal void UpdateTaskInformation(Task task)
{
string name = task.Name;
string category = task.Category;
bool reoccurring = task.GetAttributeValue<bool>("IsReoccurring");
string dueDate = this.RenderDueDate(task);
double percentage = task.PercentageDue;
ListViewItem item = this.FindByTag(task);
if (item != null)
{
item.Text = name;
item.SubItems[1].Text = category;
item.SubItems[2].Text = reoccurring.ToString();
item.SubItems[3].Text = dueDate;
item.SubItems[4].Text = percentage.ToString();
}
}