ランダムな問題を表示・評価する
STACK のマネをしたい
最近,あちらこちらに手を出しておりまして,moodle & STACK についても記事を書いております.ちょっと STACK のマネをしたくなりました.あくまでもマネでありまして,STACK に代わるシステムを作ろうなどという大それたことではありません(当たり前だ~
現在,線形代数について書きためておりまして(嘘! 書きはじめたばかり),まずは外積の計算をしてみます.これなら,評価が簡単だ~!
練習問題 次の外積を計算しましょう.
\(\ \times \ \) | \(\ = \ \) | |||||||||
外積の成分を入力して,Evaluation ボタンを click すると,正しい値の入った要素欄は背景色が水色になり,誤った値の入った要素欄は背景色がピンクになって正解を朱書きします.
こんなものは1時間だぁ,と思って作りはじめましたら,一日仕事になってしまいました.理由は ― MathJax と moodle に興味のない方は読み飛ばしてください ― Moodle の Page 上では
MathJax.Hub.Queue(['Typeset', MathJax.Hub, id]);
が上手く動いてくれず(前々から承知していたのですが,失念しておりました)無理と分かりつつも格闘を挑んでしまいました.となると,この問題が解決するまで,Page にランダム問題を載せることはできませんねぇ.
上の外積を見て,無理して列ベクトルにする必要もなかったなぁ,行ベクトルの方が処理も楽だし.などと敗北決定後に向きになってやった行為に対しても阿保らしさを感じております.取り敢えず,行ベクトル ver を作りましょう.
練習問題 次の2つのベクトルの外積を求めましょう.
\(\boldsymbol{a} = \ \)
\(\boldsymbol{b} = \ \)
\(\boldsymbol{a} \times \boldsymbol{b} = \ \)
解答は,問いに倣って丸括弧でも鍵括弧でも構いません.評価するときに,括弧は取り除いてしまいますので.ということは,3つの数字をカンマで区切って書くだけでも宜しいということです.正解すると,テキストボックスの背景色が水色に変わります.
HTML & Javascript
HTML
<p style="white-space: nowrap;">
¥(¥boldsymbol{a} = ¥ ¥) <input id="veca" type="text" style="width: 120px; border: none;" readonly="readonly"><br>
<input type="button" value="New question" onclick="makeQuiz2()"> <br>
¥(¥boldsymbol{b} = ¥ ¥) <input id="vecb" type="text" style="width: 120px; border: none;" readonly="readonly">
¥(¥boldsymbol{a} ¥times ¥boldsymbol{b} = ¥ ¥) <input id="vecab" type="text" style="width: 140px; text-align: center;" onchange="judge()" oninput="judge()"><br>
</p >
Javascript
<script type="text/Javascript">
var list_veca = [0, 0, 0];
var list_vecb = [0, 0, 0];
window.addEventListener('load', function() {makeQuiz()});
function makeQuiz() {
for (var i = 0; i < 3; i++) {
list_veca[i] = Math.floor(19 * Math.random(19)) - 9;
list_vecb[i] = Math.floor(19 * Math.random(19)) - 9;
}
document.getElementById('veca').value = '( ' + list_veca[0] + ', ' + list_veca[1] + ', ' + list_veca[2] + ' )';
document.getElementById('vecb').value = '( ' + list_vecb[0] + ', ' + list_vecb[1] + ', ' + list_vecb[2] + ' )';
document.getElementById('vecab').style.backgroundColor = 'white';
document.getElementById('vecab').value = '';
}
function judge() {
var ans = document.getElementById('vecab').value;
var correct_ans = [0, 0, 0];
var num_ans = [0, 0, 0];
document.getElementById('vecab').style.backgroundColor = 'white';<br>
for (i = 0; i < 3; i++) {
correct_ans[i] = list_veca[(i + 1) % 3] * list_vecb[(i + 2) % 3] - list_veca[(i + 2) % 3] * list_vecb[(i + 1) % 3];
}
if (ans.length >= 7) {
ans = ans.replace('(', '');
ans = ans.replace(')', '');
ans = ans.replace('[', '');
ans = ans.replace(']', '');
var list_ans = ans.split(',');
}
if (list_ans.length == 3) {
for (i = 0; i < 3; i++) {
num_ans[i] = Number(list_ans[i]);
}
if (num_ans[0] == correct_ans[0] && num_ans[1] == correct_ans[1] && num_ans[2] == correct_ans[2]) {
document.getElementById('vecab').style.backgroundColor = '#C0C0FF';
}
}
}
</script>
プチ解説
HTML の該当部分は,2つのベクトル \(\boldsymbol{a} = \) と \(\boldsymbol{b} = \) の後ろに,枠をとった text 型の input タグを readonly にして入れてあります.input タグは,本来このような用途に使用するものではありませんが,このサイトでは input タグが活躍してくれます.ここにベクトルを成分で表示します.
Javascript の記述では,まず,\(\boldsymbol{a}\) と \(\boldsymbol{b}\) の成分になるリストを list_veca と list_vecb としてグローバルに定義しています.makeQuiz() が問題を作成する関数であり,judge() が解答を評価する関数です.この両方で使うので,グローバル変数としました.
makeQuiz() は,Math.floor() と Math.random() により,-9 から 9 までの整数を作り,それを文字列としてベクトルの成分を表示しています.
judge() では,正答のリストである correct_ans と入力された解答のリストである num_ans を定義しました.最終的にこの2つを比較し,正誤評価を行います.数値型リストでは,要素ごとに値を比較しなければなりません.文字列型リストは List1 == List2 で比較できる(と記憶していましたが・・・)ので,文字列型に統一するの普通です.記憶も不確かでツイ数値型にしてしましました.
input タグの value から要素のみを取り出して num_ans に格納しなければなりません.その際,まず,( ) を取り除く必要があります.そこで使うのが,文字列に対するメソッド replace() です.
replace()
str.replace(char1, char2) のように書き,文字列 str の char1 を char2 に置換して返します.したがって,
( ) が取り除けたら,次に,これをリストにしなければなりません.そこで使うのは,やはり文字列のメソッド split() です.
split()
str.split(char) のように書いて,char をスプリッタとして文字列をリストに変換して返します.したがって,
ここで得られたリストは文字列型ですから,この要素を Number() により数値に変えます.数値と文字列の変換は,何種類かあります.私がよく使うのは,演算により変えるという方法です.
数字の文字列 * 1 とすると,数値になります.
数値 + '' とすると,数字の文字列になります.
最後に二つの要素をそれぞれ比較して,正解ならば input タグの背景色を変えます.