diff --git a/src/commodity.cc b/src/commodity.cc index f8ab523e..2a4bdcc9 100644 --- a/src/commodity.cc +++ b/src/commodity.cc @@ -46,6 +46,9 @@ namespace ledger { void commodity_t::base_t::history_t::add_price(const datetime_t& date, const amount_t& price) { + DEBUG("commodity.prices", + "add_price: " << date << ", " << price); + history_map::iterator i = prices.find(date); if (i != prices.end()) { (*i).second = price; @@ -58,6 +61,8 @@ void commodity_t::base_t::history_t::add_price(const datetime_t& date, bool commodity_t::base_t::history_t::remove_price(const datetime_t& date) { + DEBUG("commodity.prices", "remove_price: " << date); + history_map::size_type n = prices.erase(date); if (n > 0) return true; @@ -67,6 +72,9 @@ bool commodity_t::base_t::history_t::remove_price(const datetime_t& date) void commodity_t::base_t::varied_history_t::add_price(const datetime_t& date, const amount_t& price) { + DEBUG("commodity.prices", + "varied_add_price: " << date << ", " << price); + optional hist = history(price.commodity()); if (! hist) { std::pair result @@ -82,8 +90,11 @@ void commodity_t::base_t::varied_history_t::add_price(const datetime_t& date, } bool commodity_t::base_t::varied_history_t::remove_price(const datetime_t& date, - const commodity_t& comm) + commodity_t& comm) { + DEBUG("commodity.prices", + "varied_remove_price: " << date << ", " << comm); + if (optional hist = history(comm)) return hist->remove_price(date); return false; @@ -95,19 +106,35 @@ commodity_t::base_t::history_t::find_price(const optional& moment) optional age; optional price; - if (prices.size() == 0) +#if defined(DEBUG_ON) + if (moment) { + DEBUG("commodity.prices", "find_price: " << *moment); + } else { + DEBUG("commodity.prices", "find_price"); + } +#endif + + if (prices.size() == 0) { + DEBUG("commodity.prices", " there are no prices in the history"); return none; + } if (! moment) { history_map::const_reverse_iterator r = prices.rbegin(); age = (*r).first; price = (*r).second; + + DEBUG("commodity.prices", + " returning most recent price: " << age << ", " << price); } else { history_map::const_iterator i = prices.lower_bound(*moment); if (i == prices.end()) { history_map::const_reverse_iterator r = prices.rbegin(); age = (*r).first; price = (*r).second; + + DEBUG("commodity.prices", + " returning last price: " << age << ", " << price); } else { age = (*i).first; if (*moment != *age) { @@ -121,6 +148,9 @@ commodity_t::base_t::history_t::find_price(const optional& moment) } else { price = (*i).second; } + + DEBUG("commodity.prices", + " returning found price: " << age << ", " << price); } } @@ -139,25 +169,79 @@ commodity_t::base_t::history_t::find_price(const optional& moment) optional commodity_t::base_t::varied_history_t::find_price - (const optional& commodity, - const optional& moment) + (const optional& commodity, + const optional& moment) { - return none; + optional amt; + +#if defined(DEBUG_ON) + DEBUG("commodity.prices", "varied_find_price"); + + if (commodity) + DEBUG("commodity.prices", " looking for commodity '" << *commodity << "'"); + else + DEBUG("commodity.prices", " looking for any commodity"); + + if (moment) + DEBUG("commodity.prices", " time index: " << *moment); +#endif + + if (optional hist = history(commodity)) { + DEBUG("commodity.prices", " found a history for the commodity"); + + amt = hist->find_price(moment); + +#if defined(DEBUG_ON) + if (amt) + DEBUG("commodity.prices", " found price in that history: " << *amt); + else + DEBUG("commodity.prices", " found no price in that history"); +#endif + } + + // Either we couldn't find a history for the target commodity, or we + // couldn't find a price. In either case, search all histories known + // to this commodity for a price which we can calculate in terms of + // the goal commodity. + if (! amt && commodity) { + foreach (history_by_commodity_map::value_type hist, histories) { + commodity_t& comm(*hist.first); + + DEBUG("commodity.prices", + " searching for price via commodity '" << comm << "'"); + + amt = comm.find_price(commodity, moment); + // jww (2008-09-24): look for the most recent match + +#if defined(DEBUG_ON) + if (amt) + DEBUG("commodity.prices", " found price there: " << *amt); + else + DEBUG("commodity.prices", " found no price there"); +#endif + } + } + + return amt; } optional commodity_t::base_t::varied_history_t::find_price - (const std::vector& commodities, - const optional& moment) + (const std::vector& commodities, + const optional& moment) { + foreach (commodity_t * commodity, commodities) { + if (optional amt = find_price(*commodity, moment)) + return amt; + } return none; } optional commodity_t::base_t::varied_history_t::history - (const optional& commodity) + (const optional& commodity) { - const commodity_t * comm = NULL; + commodity_t * comm = NULL; if (! commodity) { if (histories.size() > 1) // jww (2008-09-20): Document which option switch to use here @@ -177,14 +261,14 @@ commodity_t::base_t::varied_history_t::history optional commodity_t::base_t::varied_history_t::history - (const std::vector& commodities) + (const std::vector& commodities) { // This function differs from the single commodity case avoid in that // 'commodities' represents a list of preferred valuation commodities. // If no price can be located in terms of the first commodity, then // the second is chosen, etc. - foreach (const commodity_t * commodity, commodities) { + foreach (commodity_t * commodity, commodities) { if (optional hist = history(*commodity)) return hist; } diff --git a/src/commodity.h b/src/commodity.h index 29011a7f..1277b2c2 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -77,26 +77,26 @@ public: optional find_price(const optional& moment = none); }; - typedef std::map history_by_commodity_map; + typedef std::map history_by_commodity_map; struct varied_history_t { history_by_commodity_map histories; void add_price(const datetime_t& date, const amount_t& price); - bool remove_price(const datetime_t& date, const commodity_t& commodity); + bool remove_price(const datetime_t& date, commodity_t& commodity); optional - find_price(const optional& commodity = none, - const optional& moment = none); + find_price(const optional& commodity = none, + const optional& moment = none); optional - find_price(const std::vector& commodities, - const optional& moment = none); + find_price(const std::vector& commodities, + const optional& moment = none); optional - history(const optional& commodity = none); + history(const optional& commodity = none); optional - history(const std::vector& commodities); + history(const std::vector& commodities); }; #define COMMODITY_STYLE_DEFAULTS 0x00 @@ -230,12 +230,12 @@ protected: } optional - history(const optional& commodity); + history(const optional& commodity); optional - history(const std::vector& commodities); + history(const std::vector& commodities); optional - find_price(const commodity_t& commodity, + find_price(commodity_t& commodity, const optional& moment, std::vector& bools); @@ -249,23 +249,23 @@ public: base->varied_history->add_price(date, price); } - bool remove_price(const datetime_t& date, const commodity_t& commodity) { + bool remove_price(const datetime_t& date, commodity_t& commodity) { if (base->varied_history) base->varied_history->remove_price(date, commodity); return false; } optional - find_price(const optional& commodity = none, - const optional& moment = none) { + find_price(const optional& commodity = none, + const optional& moment = none) { if (base->varied_history) return base->varied_history->find_price(commodity, moment); return none; } optional - find_price(const std::vector& commodities, - const optional& moment = none) { + find_price(const std::vector& commodities, + const optional& moment = none) { if (base->varied_history) return base->varied_history->find_price(commodities, moment); return none;