「その会議いくら？」を算出する(JavaScript)

## はじめに
- JavaScriptの基礎を学んだ後に最初に作成したミニアプリです。

## 動機
- 仕事で比較的な大きなプログジェクトに関わっているとき、30人以上が参加する「定例進捗会議」に出ることがありました。
- 大きな声では言えませんが、お決まりの進捗会議ですので、本当にみんなで集まる必要あるの？という疑問が、おそらく全員が持っているような状態な感じです。（最近は少なくなりましたが、いまだにあるところにはありますよね、そんな会議。。）
- そこで、 **「いったい、いくらこの会議にかかっているんだ？」** と疑問に思いましたので、学習を兼ねて、JavaScriptで算出してみることにしました。
- 探してみると、[How much does this meeting pay?](https://howmuchdoesthismeetingpay.com/) といったサイト(英語)もあるようです。

## やろうと思ったこと
- 「参加人数」「平均月給」「月の仕事時間」を入力パラメータにしました。（それしか思いつかなかった・・・）

- 会議参加者の「平均月給」「月の仕事時間」をどうやって知るんだ、というツッコミは置いておいて、そこから、会議にかけた総合計時間とコストを計算しようと思いました。

## 注意点
- 「参加人数」「平均月給」「月の仕事時間」というパラメータしか思いつきませんでしたが、本当の会議の価値・コストをこれだけで測ることはできないと思います。
- 解決案をまとめる・ものごとが進む・Before/Afterで変化がある、などといったことが会議では重要ですので。
- 改善アイデアとして、「その会議の活発度」も一緒に取り込めるとよいのかな、と思ったりもします。（もうそんなアプリあるのかな・・） 例：「無音状態の少なさ」「喋っている人の数」「雰囲気（感情分析：ToneAnalyzerとか？）」　など

## やったこと
- 「参加人数」「平均月給」「月の仕事時間」をパラメータに、会議にかけた総合計時間とコストを計算する。休憩なども考慮して、START/STOPを何度でもできるようにする。

- [デモサイト](https://anotherskyjp.site/devapps/otherpg/01_conference/conference.html)

![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167772/61e7017a-72af-8f5d-7214-d28e3045d4c5.gif)

## コード(HTML/CSS/JavaScript)

~~~conference.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial=1.0">
    <title>その会議いくら?</title>
    <link rel="stylesheet" href="./conference.css">
  </head>

  <body>
    <h1>その会議いくら?</h1>
    <p>参加人数：<input type="text" name="people" id="people" value="30"> 人</p>
    <p>平均月給：<input type="text" name="salary" id="salary" value="350000"> 円</p>
    <p>月の仕事時間：<input type="text" name="worktime" id="worktime" value="160" > 時間</p>
    <p><span id="hourly">0</span>円 / 時間、<span id="minute">0</span>円 / 分、<span id="second">0</span>円 / 秒</p>
    <br>
    <p>かけた時間：<span id="timeText">0</span>分</p>
    <p>かかったコスト：<span id="costText">0</span>円</p>
    <br>
    <p>経過時間：<span id="timerText">0</span>秒</p>
    <br>
    <div id="start">会議START</div>
    <div id="stop">会議STOP</div>
    <div id="reset">リセット</div>

    <script type="text/javascript" src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/ui/1.10.3/jquery-ui.min.js"></script>

    <script type="text/javascript" src="./conference.js"></script>

  </body>
</html>
~~~

~~~conference.css
body {
    text-align: center;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 16px;
}
#people, #salary, #worktime {
    width: 80px;
    text-align: right;
}
#timerText {
    color: blue;
    font-size: 32px;
}
#timeText, #costText {
    color: red;
    font-size: 32px;
}
.btn {
    display: inline-block;
    width: 90px;
    padding: 6px;
    border-radius: 5px;
    box-shadow: 0 4px 0 #3a00cc;
    color: #fff;
    background: #7b00ee;
    cursor: pointer;
}
.btn + .btn {
    margin-left: 5px;
}
.btn.active {
    opacity: 1.0;
}
.btn.inactive {
    opacity: 0.5;
}
~~~

~~~conferenece.js
(function() {
    'use strict';

    //平均月給フォーカスアウト
    $('#salary').on('blur', function(){
        var num = $(this).val();
        num = num.replace(/(\d)(?=(\d\d\d)+$)/g, '$1,');
        $(this).val(num);
    });
    //平均月給フォーカス
    $('#salary').on('focus', function(){
        var num = $(this).val();
        num = num.replace(/,/g, '');
        $(this).val(num);
    });

    //デフォルト表示の取得
    var people = document.getElementById('people').value;
    var salary = document.getElementById('salary').value;
    var worktime = document.getElementById('worktime').value;
    //デフォルト値の計算
    var hSalary = ( people * salary ) / worktime;
    var mSalary = hSalary / 60;
    var sSalary = mSalary / 60;
    //デフォルト値のセット
    document.getElementById('hourly').innerHTML = Math.round(hSalary).toLocaleString();
    document.getElementById('minute').innerHTML = Math.round(mSalary).toLocaleString();
    document.getElementById('second').innerHTML = Math.round(sSalary).toLocaleString();

    //項目が変更されたときは再計算を実施
    $('#people').change(function() {
        people = document.getElementById('people').value;
        calcSalary();
    });

    $('#salary').change(function() {
        salary = document.getElementById('salary').value;
        calcSalary();
    });

    $('#worktime').change(function() {
        worktime = document.getElementById('worktime').value;
        calcSalary();
    });

    var hSalary_recalc;
    var mSalary_recalc;
    var sSalary_recalc;

    function calcSalary(){
        hSalary_recalc = ( people * salary ) / worktime;
        mSalary_recalc = hSalary_recalc / 60;
        sSalary_recalc = mSalary_recalc / 60;
        document.getElementById('hourly').innerHTML = Math.round(hSalary_recalc).toLocaleString();
        document.getElementById('minute').innerHTML = Math.round(mSalary_recalc).toLocaleString();
        document.getElementById('second').innerHTML = Math.round(sSalary_recalc).toLocaleString();
        sSalary = sSalary_recalc;
    };

    //変数設定
    var startTime;
    var timerId;
    var elapsedTime = 0;
    var isRunning = false;

    var startButton = document.getElementById('start');
    var stopButton = document.getElementById('stop');
    var resetButton = document.getElementById('reset');
    var timerText = document.getElementById('timerText');
    var timeText = document.getElementById('timeText');
    var costText = document.getElementById('costText');

    //ボタンステータス管理
    function setButtonState(start, stop, reset){
        startButton.className = start ? 'btn active' : 'btn inactive';
        stopButton.className = stop ?  'btn active' : 'btn inactive';
        resetButton.className = reset ?  'btn active' : 'btn inactive';
    }

    //初期画面(startボタンのみON)
    setButtonState(true, false, false);

    //startボタンが押下されたとき
    startButton.addEventListener('click', function(){
        if(isRunning){
            return;
        }
        isRunning = true;
        startTime = Date.now();               //19700101 00:00:00からの経過ミリ秒
        updateTimerText();
        setButtonState(false, true, false);   //ボタンのステータス：STOPをON
    });

    //stopボタンが押下されたとき
    stopButton.addEventListener('click', function(){
        if(!isRunning){
            return;
        }
        isRunning = false;
        elapsedTime += Date.now() - startTime;
        clearTimeout(timerId);
        setButtonState(true, false, true);     //ボタンのステータス：Start/ResetをON
    });

    //resetボタンが押下されたとき
    resetButton.addEventListener('click', function(){
        if(isRunning){
            return;
        }
        timerText.innerHTML = '0';
        timeText.innerHTML = '0';
        costText.innerHTML = '0';
        elapsedTime = 0;
        setButtonState(true, false, false);    //ボタンのステータス：StartをON
    });

    //経過時間・時間・コストの更新
    function updateTimerText(){
        timerId = setTimeout(function(){
            var t = Date.now() - startTime + elapsedTime;
            timerText.innerHTML = (t / 1000).toFixed(0);
            timeText.innerHTML = ((timerText.innerHTML * people) / 60).toFixed(1);
            costText.innerHTML = Math.round(sSalary * timerText.innerHTML).toLocaleString();
            updateTimerText();
        }, 10);
    }

})();
~~~

## まとめ
- 言語の基礎を学んだ後は、日付や時間計算のプログラムをやるとよい、と個人的に思います。
- 今回は「会議」というテーマで時間のプログラムを学習してみましたが、他のテーマでも自分が楽しんでやれれば学習テーマはなんでもありだと思います（例：素数日を出してみるなど）