- Implemented "task ghistory" command to draw a bar chart.

This commit is contained in:
Paul Beckingham 2008-06-27 00:15:06 -04:00
parent 5c91a0d963
commit 6066cc3bab
6 changed files with 238 additions and 4 deletions

View file

@ -17,6 +17,7 @@ represents a feature release, and the Z represents a patch.
reports have been run (and therefore TDB::gc run)
+ Added averages to the "task history" report
+ Added ability to override ~/.taskrc with rc:<file>
+ Added bar chart history report "task ghistory"
+ Bug: Fixed where Esc[0m sequences were being emitted for no good reason
+ Bug: Fixed underlined table headers when color is turned off

View file

@ -415,10 +415,12 @@ with no arguments will generate a help message that lists all these commands.
% task history
Year Month Added Completed Deleted Net
2008 March 21 16 0 5
April 13 11 1 1
May 8 14 3 -9
Year Month Added Completed Deleted Net
2008 March 21 16 0 5
April 13 11 1 1
May 8 14 3 -9
Average 14 13 1 -1
This shows that for the three months that task has been used, March and April
saw the total number of tasks increase, but in May the number decreased as
@ -426,6 +428,23 @@ with no arguments will generate a help message that lists all these commands.
% task ghistory
--------------
This report shows you an overview of how many tasks were added, completed and
deleted, by month, as does "task history", but as a bar chart. It looks like this:
% task history
Year Month Added/Completed/Deleted
2008 March +++++++++++++++++++++XXXXXXXXXXXXXXXX
April +++++++++++++XXXXXXXXXXX-
May ++++++++XXXXXXXXXXXXXX---
With color enabled, the bars contain the size of each bar.
% task calendar
---------------

View file

@ -51,6 +51,7 @@
<li>Added "task undelete" feature to restore a (very) recently deleted
task
<li>Added averages to the "task history" report
<li>Added bar chart history report "task ghistory"
<li>Added support for rc:&lt;file&gt; to allow override of the default
~/.taskrc file
<li>Fixed bug where Esc[0m sequences were being emitted for no good reason
@ -1090,6 +1091,7 @@ on_white on_bright_white</code></pre>
task tags
task summary
task history
task ghistory
task next
task calendar
task active

View file

@ -126,6 +126,7 @@ static const char* commands[] =
"export",
"help",
"history",
"ghistory",
"info",
"list",
"long",

View file

@ -140,6 +140,10 @@ static void shortUsage (Config& conf)
table.addCell (row, 1, "task history");
table.addCell (row, 2, "Shows a report of task history, by month");
row = table.addRow ();
table.addCell (row, 1, "task ghistory");
table.addCell (row, 2, "Shows a graphical report of task history, by month");
row = table.addRow ();
table.addCell (row, 1, "task next");
table.addCell (row, 2, "Shows the most important tasks for each project");
@ -304,6 +308,7 @@ int main (int argc, char** argv)
else if (command == "summary") handleReportSummary (tdb, task, conf);
else if (command == "next") handleReportNext (tdb, task, conf);
else if (command == "history") handleReportHistory (tdb, task, conf);
else if (command == "ghistory") handleReportGHistory (tdb, task, conf);
else if (command == "calendar") handleReportCalendar (tdb, task, conf);
else if (command == "active") handleReportActive (tdb, task, conf);
else if (command == "overdue") handleReportOverdue (tdb, task, conf);
@ -1719,6 +1724,211 @@ void handleReportHistory (const TDB& tdb, T& task, Config& conf)
std::cout << "No tasks." << std::endl;
}
////////////////////////////////////////////////////////////////////////////////
void handleReportGHistory (const TDB& tdb, T& task, Config& conf)
{
// Determine window size, and set table accordingly.
int width = conf.get ("defaultwidth", 80);
#ifdef HAVE_LIBNCURSES
if (conf.get ("curses", true))
{
WINDOW* w = initscr ();
width = w->_maxx + 1;
endwin ();
}
#endif
int widthOfBar = width - 15; // strlen ("2008 September ")
std::map <time_t, int> groups;
std::map <time_t, int> addedGroup;
std::map <time_t, int> completedGroup;
std::map <time_t, int> deletedGroup;
// Scan the pending tasks.
std::vector <T> pending;
tdb.allPendingT (pending);
for (unsigned int i = 0; i < pending.size (); ++i)
{
T task (pending[i]);
time_t epoch = monthlyEpoch (task.getAttribute ("entry"));
if (epoch)
{
groups[epoch] = 0;
if (addedGroup.find (epoch) != addedGroup.end ())
addedGroup[epoch] = addedGroup[epoch] + 1;
else
addedGroup[epoch] = 1;
if (task.getStatus () == T::deleted)
{
epoch = monthlyEpoch (task.getAttribute ("end"));
if (deletedGroup.find (epoch) != deletedGroup.end ())
deletedGroup[epoch] = deletedGroup[epoch] + 1;
else
deletedGroup[epoch] = 1;
}
else if (task.getStatus () == T::completed)
{
epoch = monthlyEpoch (task.getAttribute ("end"));
if (completedGroup.find (epoch) != completedGroup.end ())
completedGroup[epoch] = completedGroup[epoch] + 1;
else
completedGroup[epoch] = 1;
}
}
}
// Scan the completed tasks.
std::vector <T> completed;
tdb.allCompletedT (completed);
for (unsigned int i = 0; i < completed.size (); ++i)
{
T task (completed[i]);
time_t epoch = monthlyEpoch (task.getAttribute ("entry"));
if (epoch)
{
groups[epoch] = 0;
if (addedGroup.find (epoch) != addedGroup.end ())
addedGroup[epoch] = addedGroup[epoch] + 1;
else
addedGroup[epoch] = 1;
epoch = monthlyEpoch (task.getAttribute ("end"));
if (task.getStatus () == T::deleted)
{
epoch = monthlyEpoch (task.getAttribute ("end"));
if (deletedGroup.find (epoch) != deletedGroup.end ())
deletedGroup[epoch] = deletedGroup[epoch] + 1;
else
deletedGroup[epoch] = 1;
}
else if (task.getStatus () == T::completed)
{
epoch = monthlyEpoch (task.getAttribute ("end"));
if (completedGroup.find (epoch) != completedGroup.end ())
completedGroup[epoch] = completedGroup[epoch] + 1;
else
completedGroup[epoch] = 1;
}
}
}
// Now build the table.
Table table;
table.setDateFormat (conf.get ("dateformat", "m/d/Y"));
table.addColumn ("Year");
table.addColumn ("Month");
table.addColumn ("Added/Completed/Deleted");
if (conf.get ("color", true))
{
table.setColumnUnderline (0);
table.setColumnUnderline (1);
}
// Determine the longest line.
int maxLine = 0;
foreach (i, groups)
{
int line = addedGroup[i->first] + completedGroup[i->first] + deletedGroup[i->first];
if (line > maxLine)
maxLine = line;
}
if (maxLine > 0)
{
int totalAdded = 0;
int totalCompleted = 0;
int totalDeleted = 0;
int priorYear = 0;
int row = 0;
foreach (i, groups)
{
row = table.addRow ();
totalAdded += addedGroup[i->first];
totalCompleted += completedGroup[i->first];
totalDeleted += deletedGroup[i->first];
Date dt (i->first);
int m, d, y;
dt.toMDY (m, d, y);
if (y != priorYear)
{
table.addCell (row, 0, y);
priorYear = y;
}
table.addCell (row, 1, Date::monthName(m));
unsigned int addedBar = (widthOfBar * addedGroup[i->first]) / maxLine;
unsigned int completedBar = (widthOfBar * completedGroup[i->first]) / maxLine;
unsigned int deletedBar = (widthOfBar * deletedGroup[i->first]) / maxLine;
std::string bar;
if (conf.get ("color", true))
{
char number[24];
sprintf (number, "%d", addedGroup[i->first]);
std::string aBar = number;
while (aBar.length () < addedBar)
aBar = " " + aBar;
sprintf (number, "%d", completedGroup[i->first]);
std::string cBar = number;
while (cBar.length () < completedBar)
cBar = " " + cBar;
sprintf (number, "%d", deletedGroup[i->first]);
std::string dBar = number;
while (dBar.length () < deletedBar)
dBar = " " + dBar;
bar = Text::colorize (Text::black, Text::on_green, aBar);
bar += Text::colorize (Text::black, Text::on_yellow, cBar);
bar += Text::colorize (Text::black, Text::on_red, dBar);
}
else
{
std::string aBar = ""; while (aBar.length () < addedBar) aBar += "+";
std::string cBar = ""; while (cBar.length () < completedBar) cBar += "+";
std::string dBar = ""; while (dBar.length () < deletedBar) dBar += "+";
bar = aBar + cBar + dBar;
}
table.addCell (row, 2, bar);
}
}
if (table.rowCount ())
{
std::cout << optionalBlankLine (conf)
<< table.render ()
<< std::endl;
if (conf.get ("color", true))
std::cout << "Legend: "
<< Text::colorize (Text::black, Text::on_green, "added")
<< ", "
<< Text::colorize (Text::black, Text::on_yellow, "completed")
<< ", "
<< Text::colorize (Text::black, Text::on_red, "deleted")
<< std::endl;
else
std::cout << "Legend: + added, X completed, - deleted" << std::endl;
}
else
std::cout << "No tasks." << std::endl;
}
////////////////////////////////////////////////////////////////////////////////
// A summary of the command usage. Not useful to users, but used to display
// usage statistics for feedback.

View file

@ -69,6 +69,7 @@ void handleCompleted (const TDB&, T&, Config&);
void handleReportSummary (const TDB&, T&, Config&);
void handleReportNext (const TDB&, T&, Config&);
void handleReportHistory (const TDB&, T&, Config&);
void handleReportGHistory (const TDB&, T&, Config&);
void handleReportUsage (const TDB&, T&, Config&);
void handleReportCalendar (const TDB&, T&, Config&);
void handleReportActive (const TDB&, T&, Config&);