diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/account.cc | 43 | ||||
-rw-r--r-- | src/account.h | 49 | ||||
-rw-r--r-- | src/output.cc | 98 | ||||
-rw-r--r-- | src/output.h | 46 | ||||
-rw-r--r-- | src/report.cc | 6 | ||||
-rw-r--r-- | src/stats.cc | 125 | ||||
-rw-r--r-- | src/stats.h | 59 |
8 files changed, 239 insertions, 189 deletions
diff --git a/Makefile.am b/Makefile.am index 5dd139aa..48e77086 100644 --- a/Makefile.am +++ b/Makefile.am @@ -65,6 +65,7 @@ libledger_data_la_LDFLAGS = -release $(VERSION).0 libledger_report_la_SOURCES = \ src/quotes.cc \ + src/stats.cc \ src/generate.cc \ src/derive.cc \ src/emacs.cc \ @@ -123,6 +124,7 @@ pkginclude_HEADERS = \ src/precmd.h \ src/derive.h \ src/generate.h \ + src/stats.h \ src/output.h \ src/emacs.h \ src/quotes.h \ diff --git a/src/account.cc b/src/account.cc index b9955120..0db42cdb 100644 --- a/src/account.cc +++ b/src/account.cc @@ -309,7 +309,36 @@ std::size_t account_t::children_with_flags(xdata_t::flags_t flags) const account_t::xdata_t::details_t& account_t::xdata_t::details_t::operator+=(const details_t& other) { - // jww (2009-03-05): NYI + posts_count += other.posts_count; + posts_virtuals_count += other.posts_virtuals_count; + posts_cleared_count += other.posts_cleared_count; + posts_last_7_count += other.posts_last_7_count; + posts_last_30_count += other.posts_last_30_count; + posts_this_month_count += other.posts_this_month_count; + + if (! is_valid(earliest_post) || + (is_valid(other.earliest_post) && + other.earliest_post < earliest_post)) + earliest_post = other.earliest_post; + if (! is_valid(earliest_cleared_post) || + (is_valid(other.earliest_cleared_post) && + other.earliest_cleared_post < earliest_cleared_post)) + earliest_cleared_post = other.earliest_cleared_post; + + if (! is_valid(latest_post) || + (is_valid(other.latest_post) && + other.latest_post > latest_post)) + latest_post = other.latest_post; + if (! is_valid(latest_cleared_post) || + (is_valid(other.latest_cleared_post) && + other.latest_cleared_post > latest_cleared_post)) + latest_cleared_post = other.latest_cleared_post; + + filenames.insert(other.filenames.begin(), other.filenames.end()); + accounts_referenced.insert(other.accounts_referenced.begin(), + other.accounts_referenced.end()); + payees_referenced.insert(other.payees_referenced.begin(), + other.payees_referenced.end()); return *this; } @@ -377,7 +406,7 @@ account_t::family_details(bool gather_all) const foreach (const accounts_map::value_type& pair, accounts) xdata_->family_details += pair.second->family_details(gather_all); - xdata_->self_details += self_details(gather_all); + xdata_->family_details += self_details(gather_all); } return xdata_->family_details; } @@ -385,16 +414,8 @@ account_t::family_details(bool gather_all) const void account_t::xdata_t::details_t::update(post_t& post, bool gather_all) { - if (last_xact != post.xact) { - xacts_count++; - last_xact = post.xact; - } - if (last_post == &post) - return; - - last_post = &post; - posts_count++; + if (post.has_flags(POST_VIRTUAL)) posts_virtuals_count++; diff --git a/src/account.h b/src/account.h index f161a11f..0fa03dde 100644 --- a/src/account.h +++ b/src/account.h @@ -138,41 +138,34 @@ class account_t : public scope_t struct details_t { - value_t total; - bool calculated; - bool gathered; + value_t total; + bool calculated; + bool gathered; // The following are only calculated if --totals is enabled - std::size_t xacts_count; + std::size_t posts_count; + std::size_t posts_virtuals_count; + std::size_t posts_cleared_count; + std::size_t posts_last_7_count; + std::size_t posts_last_30_count; + std::size_t posts_this_month_count; - std::size_t posts_count; - std::size_t posts_virtuals_count; - std::size_t posts_cleared_count; - std::size_t posts_last_7_count; - std::size_t posts_last_30_count; - std::size_t posts_this_month_count; + date_t earliest_post; + date_t earliest_cleared_post; + date_t latest_post; + date_t latest_cleared_post; - date_t earliest_post; - date_t earliest_cleared_post; - date_t latest_post; - date_t latest_cleared_post; - - xact_t * last_xact; - post_t * last_post; - - std::size_t last_size; + std::size_t last_size; // The following are only calculated if --gather is enabled - std::set<path> filenames; - std::set<string> accounts_referenced; - std::set<string> payees_referenced; + std::set<path> filenames; + std::set<string> accounts_referenced; + std::set<string> payees_referenced; details_t() : calculated(false), gathered(false), - xacts_count(0), - posts_count(0), posts_virtuals_count(0), posts_cleared_count(0), @@ -180,14 +173,6 @@ class account_t : public scope_t posts_last_30_count(0), posts_this_month_count(0), - earliest_post(0), - earliest_cleared_post(0), - latest_post(0), - latest_cleared_post(0), - - last_xact(NULL), - last_post(NULL), - last_size(0) {} details_t& operator+=(const details_t& other); diff --git a/src/output.cc b/src/output.cc index 975d8077..02bd7120 100644 --- a/src/output.cc +++ b/src/output.cc @@ -111,104 +111,6 @@ void format_posts::operator()(post_t& post) } } -void gather_statistics::flush() -{ - std::ostream& out(report.output_stream); - - { - straccstream accum; - out << ACCUM(accum << "Time period: %1 to %2" << statistics.earliest_post - << statistics.latest_post) << std::endl << std::endl; - } - - out << _(" Files these postings came from:") << std::endl; - - foreach (const path& pathname, statistics.filenames) - if (! pathname.empty()) - out << " " << pathname.string() << std::endl; - out << std::endl; - - out << _(" Unique payees: "); - out.width(8); - out << std::right << statistics.payees_referenced.size() << std::endl; - - out << _(" Unique accounts: "); - out.width(8); - out << std::right << statistics.accounts_referenced.size() << std::endl; - - out << _(" Number of transactions: ") ; - out.width(8); - out << std::right << statistics.total_xacts << std::endl; - - out << _(" Number of postings: "); - out.width(8); - out << std::right << statistics.total_posts; - - out << " ("; - out.precision(2); - out << (double((statistics.latest_post - statistics.earliest_post).days()) / - double(statistics.total_posts)) << _(" per day)") << std::endl; - - out << _(" Days since last post: "); - out.width(8); - out << std::right << (CURRENT_DATE() - statistics.latest_post).days() - << std::endl; - - out << _(" Posts in last 7 days: "); - out.width(8); - out << std::right << statistics.total_last_7_days << std::endl; - out << _(" Posts in last 30 days: "); - out.width(8); - out << std::right << statistics.total_last_30_days << std::endl; - out << _(" Posts seen this month: "); - out.width(8); - out << std::right << statistics.total_this_month << std::endl; - - out << _(" Uncleared postings: "); - out.width(8); - out << std::right << statistics.total_uncleared_posts << std::endl; - - out.flush(); -} - -void gather_statistics::operator()(post_t& post) -{ - if (last_xact != post.xact) { - statistics.total_xacts++; - last_xact = post.xact; - } - if (last_post != &post) { - statistics.total_posts++; - last_post = &post; - - statistics.filenames.insert(post.pathname); - - date_t date = post.date(); - - if (date.year() == CURRENT_DATE().year() && - date.month() == CURRENT_DATE().month()) - statistics.total_this_month++; - - if ((CURRENT_DATE() - date).days() <= 30) - statistics.total_last_30_days++; - if ((CURRENT_DATE() - date).days() <= 7) - statistics.total_last_7_days++; - - if (post.state() != item_t::CLEARED) - statistics.total_uncleared_posts++; - - if (! is_valid(statistics.earliest_post) || - post.date() < statistics.earliest_post) - statistics.earliest_post = post.date(); - if (! is_valid(statistics.latest_post) || - post.date() > statistics.latest_post) - statistics.latest_post = post.date(); - - statistics.accounts_referenced.insert(post.account->fullname()); - statistics.payees_referenced.insert(post.xact->payee); - } -} - format_accounts::format_accounts(report_t& _report, const string& format) : report(_report), disp_pred() diff --git a/src/output.h b/src/output.h index c7e108fe..19dc5e20 100644 --- a/src/output.h +++ b/src/output.h @@ -89,52 +89,6 @@ public: * * Long. */ -class gather_statistics : public item_handler<post_t> -{ -protected: - report_t& report; - xact_t * last_xact; - post_t * last_post; - - struct statistics_t { - std::set<path> filenames; - - std::size_t total_xacts; - std::size_t total_posts; - std::size_t total_uncleared_posts; - std::size_t total_last_7_days; - std::size_t total_last_30_days; - std::size_t total_this_month; - - date_t earliest_post; - date_t latest_post; - - std::set<string> accounts_referenced; - std::set<string> payees_referenced; - - statistics_t() - : total_xacts(0), total_posts(0), total_uncleared_posts(0), - total_last_7_days(0), total_last_30_days(0), total_this_month(0) {} - } statistics; - -public: - gather_statistics(report_t& _report) - : report(_report), last_xact(NULL), last_post(NULL) { - TRACE_CTOR(gather_statistics, "report&"); - } - virtual ~gather_statistics() { - TRACE_DTOR(gather_statistics); - } - - virtual void flush(); - virtual void operator()(post_t& post); -}; - -/** - * @brief Brief - * - * Long. - */ class format_accounts : public item_handler<account_t> { protected: diff --git a/src/report.cc b/src/report.cc index e4eef741..76546528 100644 --- a/src/report.cc +++ b/src/report.cc @@ -37,6 +37,7 @@ #include "iterators.h" #include "filters.h" #include "precmd.h" +#include "stats.h" #include "generate.h" #include "derive.h" #include "emacs.h" @@ -728,8 +729,9 @@ expr_t::ptr_op_t report_t::lookup(const string& name) case 's': if (is_eq(q, "stats") || is_eq(q, "stat")) - return WRAP_FUNCTOR(reporter<>(new gather_statistics(*this), *this)); - else if (is_eq(q, "server") && maybe_import("ledger.server")) + return WRAP_FUNCTOR(report_statistics); + else + if (is_eq(q, "server") && maybe_import("ledger.server")) return session.lookup(string(CMD_PREFIX) + "server"); break; } diff --git a/src/stats.cc b/src/stats.cc new file mode 100644 index 00000000..5a99579c --- /dev/null +++ b/src/stats.cc @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2003-2009, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "derive.h" +#include "xact.h" +#include "post.h" +#include "account.h" +#include "report.h" +#include "session.h" + +namespace ledger { + +value_t report_statistics(call_scope_t& args) +{ + report_t& report(find_scope<report_t>(args)); + std::ostream& out(report.output_stream); + + const account_t::xdata_t::details_t& + statistics(report.session.master->family_details(true)); + + if (! is_valid(statistics.earliest_post) && + ! is_valid(statistics.latest_post)) + return NULL_VALUE; + + assert(is_valid(statistics.earliest_post)); + assert(is_valid(statistics.latest_post)); + + { + straccstream accum; + out << ACCUM(accum << _("Time period: %1 to %2 (%3 days)") + << format_date(statistics.earliest_post) + << format_date(statistics.latest_post) + << (statistics.latest_post - + statistics.earliest_post).days()) + << std::endl << std::endl; + } + + out << _(" Files these postings came from:") << std::endl; + + foreach (const path& pathname, statistics.filenames) + if (! pathname.empty()) + out << " " << pathname.string() << std::endl; + out << std::endl; + + out << _(" Unique payees: "); + out.width(6); + out << statistics.payees_referenced.size() << std::endl; + + out << _(" Unique accounts: "); + out.width(6); + out << statistics.accounts_referenced.size() << std::endl; + + out << std::endl; + +#if 0 + out << _(" Number of transactions: ") ; + out.width(6); + out << statistics.xacts_count << std::endl; +#endif + + out << _(" Number of postings: "); + out.width(6); + out << statistics.posts_count; + + out << " ("; + out.precision(2); + out << (double((statistics.latest_post - statistics.earliest_post).days()) / + double(statistics.posts_count)) << _(" per day)") << std::endl; + + out << _(" Uncleared postings: "); + out.width(6); + out << (statistics.posts_count - + statistics.posts_cleared_count) << std::endl; + + out << std::endl; + + out << _(" Days since last post: "); + out.width(6); + out << (CURRENT_DATE() - statistics.latest_post).days() + << std::endl; + + out << _(" Posts in last 7 days: "); + out.width(6); + out << statistics.posts_last_7_count << std::endl; + out << _(" Posts in last 30 days: "); + out.width(6); + out << statistics.posts_last_30_count << std::endl; + out << _(" Posts seen this month: "); + out.width(6); + out << statistics.posts_this_month_count << std::endl; + + out.flush(); + + return NULL_VALUE; +} + +} // namespace ledger diff --git a/src/stats.h b/src/stats.h new file mode 100644 index 00000000..db8e9a0d --- /dev/null +++ b/src/stats.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2003-2009, John Wiegley. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of New Artisans LLC nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @addtogroup stats + */ + +/** + * @file stats.h + * @author John Wiegley + * + * @ingroup report + * + * @brief Brief + * + * Long. + */ +#ifndef _STATS_H +#define _STATS_H + +#include "value.h" + +namespace ledger { + +class call_scope_t; + +value_t report_statistics(call_scope_t& scope); + +} // namespace ledger + +#endif // _STATS_H |