はじめに
- JavaScriptの基礎を学んだ後に最初に作成したミニアプリです。
動機
- 仕事で比較的な大きなプログジェクトに関わっているとき、30人以上が参加する「定例進捗会議」に出ることがありました。
- 大きな声では言えませんが、お決まりの進捗会議ですので、本当にみんなで集まる必要あるの?という疑問が、おそらく全員が持っているような状態な感じです。(最近は少なくなりましたが、いまだにあるところにはありますよね、そんな会議。。)
- そこで、 「いったい、いくらこの会議にかかっているんだ?」 と疑問に思いましたので、学習を兼ねて、JavaScriptで算出してみることにしました。
- 探してみると、How much does this meeting pay? といったサイト(英語)もあるようです。
やろうと思ったこと
-
「参加人数」「平均月給」「月の仕事時間」を入力パラメータにしました。(それしか思いつかなかった・・・)
-
会議参加者の「平均月給」「月の仕事時間」をどうやって知るんだ、というツッコミは置いておいて、そこから、会議にかけた総合計時間とコストを計算しようと思いました。
注意点
- 「参加人数」「平均月給」「月の仕事時間」というパラメータしか思いつきませんでしたが、本当の会議の価値・コストをこれだけで測ることはできないと思います。
- 解決案をまとめる・ものごとが進む・Before/Afterで変化がある、などといったことが会議では重要ですので。
- 改善アイデアとして、「その会議の活発度」も一緒に取り込めるとよいのかな、と思ったりもします。(もうそんなアプリあるのかな・・) 例:「無音状態の少なさ」「喋っている人の数」「雰囲気(感情分析:ToneAnalyzerとか?)」 など
やったこと
-
「参加人数」「平均月給」「月の仕事時間」をパラメータに、会議にかけた総合計時間とコストを計算する。休憩なども考慮して、START/STOPを何度でもできるようにする。
コード(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);
}
})();
まとめ
- 言語の基礎を学んだ後は、日付や時間計算のプログラムをやるとよい、と個人的に思います。
- 今回は「会議」というテーマで時間のプログラムを学習してみましたが、他のテーマでも自分が楽しんでやれれば学習テーマはなんでもありだと思います(例:素数日を出してみるなど)