#include <iostream>
#include <iomanip>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::setw;
using std::fixed;
using std::setprecision;
using std::string;

// constants estimating how many of item X fit in a one litre container
const float MarblesPerL = 78.0f;
const float PingPongPerL = 20.5f;
const float TennisPerL = 3.7f;

// constant fraction for the expected variation in how many of an item fit
const float Variability = 0.1f;  // i.e +/- 10%

// welcome() gives the user an introduction to our program
void welcome();

// getCName() prompts the user to enter a container name, reads and returns it
string getCName();

// getCSize(containerName) prompts the user to enter the size of the specified
//     container type in litres, then reads and returns the value
float getCSize(string containerName);

// displayFit(containerName, containerSize)
//     for the named container and its size, calculates and displays
//     the range of how many marbles, ping pong balls, and tennis balls
//     will fit in the container with the results columnized as shown
//     below (1 digit after the decimal point, width 6 for the column)
// example for displayFit("carton", 1.5):
// A carton of size 1.5 litres holds
//  105.3 to  128.7 small marbles
//   27.7 to   33.8 ping pong balls
//    5.0 to    6.1 tennis balls
void displayFit(string containerName, float containerSize);

int main()
{
   // storage for the name and size of the container
   string cname;
   float csize;

   // display overall program instructions
   welcome();

   // get the container name and size
   cname = getCName();
   csize = getCSize(cname);

   // display how many of each item fit in the container
   displayFit(cname, csize);

   cout << "\nThanks for using HowManyFit!" << endl << endl;
   return 0;
}

void welcome()
{
   cout << "\nWelcome to HowManyFit!\n\n";
   cout << "We estimate how many (small) marbles, ping pong balls, and tennis balls\n";
   cout << "fit in a container whose size you specify.\n" << endl;
}

string getCName()
{
   string contName;
   cout << "Please enter a name for the container (as a single word): ";
   cin >> contName;
   return contName;
}

float getCSize(string containerName)
{
   float contSize = 0;
   cout << "Please enter the size of a(n) " << containerName << " in litres (e.g. 4.6): ";
   cin >> contSize;
   return contSize;
}

// displayFit(containerName, containerSize)
//     for the named container and its size, calculates and displays
//     the range of how many marbles, ping pong balls, and tennis balls
//     will fit in the container with the results columnized as shown
//     below (1 digit after the decimal point, width 6 for the column)
// example for displayFit("carton", 1.5):
// A carton of size 1.5 litres holds
//  105.3 to  128.7 small marbles
//   27.7 to   33.8 ping pong balls
//    5.0 to    6.1 tennis balls
void displayFit(string containerName, float containerSize)
{
   // determine the range of marbles that will fit
   float minMarbles, maxMarbles;
   minMarbles = (1-Variability) * (containerSize*MarblesPerL);
   maxMarbles = (1+Variability) * (containerSize*MarblesPerL);

   // determine the range of ping pong balls that will fit
   float minPingPong, maxPingPong;
   minPingPong = (1-Variability) * (containerSize*PingPongPerL);
   maxPingPong = (1+Variability) * (containerSize*PingPongPerL);

   // determine the range of tennis balls that will fit
   float minTennis, maxTennis;
   minTennis = (1-Variability) * (containerSize*TennisPerL);
   maxTennis = (1+Variability) * (containerSize*TennisPerL);

   // display the results, formatted to a fixed column width and precision after decimal point
   const int colWidth = 6;
   const int displayDecimals = 1;
   cout << "\nA " << containerName << " of size " << containerSize << " litres holds" << endl;
   cout << fixed << setprecision(displayDecimals);
   cout << setw(colWidth) << minMarbles << " to " << setw(colWidth) << maxMarbles
        << " small marbles" << endl;
   cout << setw(colWidth) << minPingPong << " to " << setw(colWidth) << maxPingPong
        << " ping pong balls" << endl;
   cout << setw(colWidth) << minTennis << " to " << setw(colWidth) << maxTennis
        << " tennis balls" << endl;
}

