Files
Theatrical-Players-Refactor…/cpp/statement.cpp
2019-08-13 09:44:16 +01:00

96 lines
2.6 KiB
C++

#include "statement.h"
#include <iostream>
#include <sstream>
#include <iomanip>
// https://stackoverflow.com/a/7277333/104370
class comma_numpunct : public std::numpunct<char>
{
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<std::string>() << '\n';
for( const auto& perf : invoice["performances"])
{
float this_amount = 0;
auto play = plays[perf["playID"].get<std::string>()];
if (play["type"] == "tragedy")
{
this_amount = 40000;
if (perf["audience"] > 30)
{
this_amount += 1000 * (perf["audience"].get<int>() - 30);
}
}
else if (play["type"] == "comedy")
{
this_amount = 30000;
if (perf["audience"] > 20)
{
this_amount += 10000 + 500 * (perf["audience"].get<int>() - 20);
}
this_amount += 300 * perf["audience"].get<int>();
}
else
{
throw std::domain_error("unknown type: " + play["type"].get<std::string>());
}
// add volume credits
volume_credits += std::max(perf["audience"].get<int>() - 30, 0);
// add extra credit for every ten comedy attendees
if ("comedy" == play["type"])
{
volume_credits += perf["audience"].get<int>() / 5;
}
// print line for this order
result << " " << play["name"].get<std::string>() << ": " << 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();
}