#include <iostream>  // cout、cinを用いる
#include <string>    // string型の文字列を用いる
#include <random>    // 乱数を用いる
#include <windows.h> // Sleep()を使うためにインクルードする
using namespace std; // std名前空間を使用して記述を簡略化する

// ゲームに使用する各種のデータを定義する
const int PUR_PRICE = 100; // アイスクリーム1個の仕入れ値
const int SEL_PRICE = 300; // 売値
const string DAY_OF_WEEK[] = { "月", "火", "水", "木", "金", "土", "日" }; // 曜日の文字列
const int BASE_NUMBER[] = { 300, 300, 300, 300, 400, 500, 600 };   // 来場者の基本的な人数
const string WEATHER[] = { "快晴", "晴れ", "曇り", "小雨", "雨" }; // 天気の文字列
const float EFFECTS[] = { 1.5, 1.0, 0.8, 0.6, 0.4 }; // 天気による人数の変化、BASE_NUMBERに掛ける
const int BUY_PER[] = { 8, 10, 12, 20, 30 }; // 各天気で何人に1人がアイスクリームを買うか
const string DIV_LINE = "-------------------------------------------------"; // 区切り線
const int CASH_ON_HAND = 10000; // ゲーム開始時の資金
int money = CASH_ON_HAND;       // お金を代入する変数

random_device rd;         // ランダムデバイスを用意
unsigned int seed = rd(); // 乱数の種を取得
mt19937 rand_mt(seed);    // 種を与えて乱数生成器を準備する

int main() { // main関数
    // ゲーム開始時に説明文を表示
    cout << "アイスクリーム１個の仕入れ値は" << PUR_PRICE << "円" << endl;
    cout << "アイスクリーム１個の売値は" << SEL_PRICE << "円" << endl;
    cout << "ゲーム開始！" << endl;
    cout << DIV_LINE << endl;

    for (int day = 0; day < 7; day++) { // 7日間（一週間）繰り返す
        int forecast = rand_mt() % size(WEATHER); // 予想される天気を乱数で決める
        int icecream = 0; // 仕入れるアイスクリームの数を代入する変数

        // ゲームに必要な情報を出力
        cout << "明日は" << DAY_OF_WEEK[day] << "曜日です。" << endl;
        cout << DAY_OF_WEEK[day] << "曜の平均的な来場者数は" << BASE_NUMBER[day] << "人です。" << endl;
        cout << "天気予報は「" << WEATHER[forecast] << "」" << endl;
        cout << "手持ち資金は" << money << "円。";
        cout << (money / PUR_PRICE) << "個まで仕入れられます。" << endl;

        while (true) { // 仕入れるアイスクリームの数を入力する処理
            cout << "何個、仕入れますか？（1個" << PUR_PRICE << "円）";
            cin >> icecream; // 入力を受け付ける
            if (icecream <= 0) { // 0以下を入力した時
                cout << "最低１個は仕入れましょう。" << endl;
            }
            else if (money < PUR_PRICE * icecream) { // 仕入れられる数を超えた時
                cout << "手持ち資金が足りません。" << endl;
            }
            else { // 正しい数を入力した時
                money = money - PUR_PRICE * icecream; // 資金を減らす
                break; // whileを抜ける
            }
        }
        cout << "仕入れ" << icecream << "個／支出" << PUR_PRICE * icecream << "円／手持ち資金" << money << "円" << endl;
        Sleep(3000); // "間"を設ける

        int weather = forecast; // 実際の天気
        if (rand_mt() % 3 == 0) weather = rand_mt() % size(WEATHER); // 天気予報が外れることがある
        int beachgoers = BASE_NUMBER[day] * EFFECTS[weather] * (80 + rand_mt() % 41) / 100; // 海水浴客数を乱数で増減する
        int buy_per = BUY_PER[weather] * (80 + rand_mt() % 41) / 100; // 何人に1人が買うかを決める
        int sel_num = beachgoers / buy_per; // 売れた数
        if (sel_num > icecream) sel_num = icecream; // 仕入れた数を超えないようにする

        // その日の結果を出力
        cout << DIV_LINE << endl;
        cout << day + 1 << "日目 " << DAY_OF_WEEK[day] << "曜日" << endl;
        cout << "天気は" << WEATHER[weather] << "です。" << endl;
        if (weather != forecast) cout << "天気予報は外れました。" << endl;
        cout << "この日は海水浴客が" << beachgoers << "人、訪れました。" << endl;
        cout << buy_per << "人に1人がアイスクリームを買いました。" << endl;
        cout << sel_num << "個、売れ、" << SEL_PRICE * sel_num << "円、売り上げました。" << endl;
        cout << DIV_LINE << endl;
        money = money + SEL_PRICE * sel_num; // 売り上げを手持ち資金に加える
        Sleep(3000); // "間"を設ける
    }
    // ゲームの結果を出力して終了
    cout << "ゲーム終了です。" << endl;
    cout << "所持金は " << money << "円" << endl;
    if (money >= CASH_ON_HAND)
        cout << (money - CASH_ON_HAND) << "円の利益が出ました。" << endl;
    else
        cout << (CASH_ON_HAND - money) << "円の赤字になりました、、、" << endl;
}
