#include "statement.h" #include #include #include // https://stackoverflow.com/a/7277333/104370 class comma_numpunct : public std::numpunct { protected: virtual char do_thousands_sep() const override { return ','; } virtual std::string do_grouping() const override { return "\03"; } }; std::string format_as_dollars(float amount) { // this creates a new locale based on the current application default // (which is either the one given on startup, but can be overriden with // std::locale::global) - then extends it with an extra facet that // controls numeric output. const std::locale comma_locale(std::locale(), new comma_numpunct()); std::ostringstream out; // tell stream to use our new locale. out.imbue(comma_locale); out.precision(2); out << "$" << std::fixed << amount; return out.str(); } std::string statement( const nlohmann::json& invoice, const nlohmann::json& plays) { float total_amount = 0; int volume_credits = 0; std::stringstream result; result << "Statement for " << invoice["customer"].get() << '\n'; for( const auto& perf : invoice["performances"]) { float this_amount = 0; auto play = plays[perf["playID"].get()]; if (play["type"] == "tragedy") { this_amount = 40000; if (perf["audience"] > 30) { this_amount += 1000 * (perf["audience"].get() - 30); } } else if (play["type"] == "comedy") { this_amount = 30000; if (perf["audience"] > 20) { this_amount += 10000 + 500 * (perf["audience"].get() - 20); } this_amount += 300 * perf["audience"].get(); } else { throw std::domain_error("unknown type: " + play["type"].get()); } // add volume credits volume_credits += std::max(perf["audience"].get() - 30, 0); // add extra credit for every ten comedy attendees if ("comedy" == play["type"]) { volume_credits += perf["audience"].get() / 5; } // print line for this order result << " " << play["name"].get() << ": " << format_as_dollars(this_amount/100) << " (" << perf["audience"] << " seats)\n"; total_amount += this_amount; } result << "Amount owed is " << format_as_dollars(total_amount/100.0f) << "\n"; result << "You earned " << volume_credits << " credits"; return result.str(); }