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();
    }
}

Comments

No Comments