Help us understand the problem. What is going on with this article?

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

はじめに

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

動機

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

やろうと思ったこと

  • 「参加人数」「平均月給」「月の仕事時間」を入力パラメータにしました。(それしか思いつかなかった・・・)

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

注意点

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

やったこと

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

  • デモサイト

2.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);
    }

})();

まとめ

  • 言語の基礎を学んだ後は、日付や時間計算のプログラムをやるとよい、と個人的に思います。
  • 今回は「会議」というテーマで時間のプログラムを学習してみましたが、他のテーマでも自分が楽しんでやれれば学習テーマはなんでもありだと思います(例:素数日を出してみるなど)
yoshi_yast
個人開発初学者です。「1か月後の自分は他人である」・「自分の"やったこと"や"つまずき"はきっと誰かの役に立つ」・「アウトプットは最後は自分に返ってくる」ということを意識して個人の記録をOUTPUTしていきたいと思います。
https://anotherskyjp.site/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away