【教師オリジナルアプリを作ろう】英文法学習ライブラリFasgram Ver1.0公開とその解説(Javascript)

これまで,スマートフォンで動作するwebアプリFasgramを断片的に開発してきましたが,ここで開発してきた機能を一つのライブラリにまとめました。

fasgram1.0.zip

zipファイルにはライブラリであるfasgram.jsや,サンプルコードを動かすためのindex.html,fasgram-main.js,効果音のmp3などのファイルが含まれています。

ライブラリのメソッドにアクセスすることで,英文法を学習できるさまざまな機能を実現することができます。

本ライブラリはオープンソースです。著作権者の許諾なしに自由に改変・再配布できます。

サンプルコード

ライブラリを扱うためのサンプルコードを示します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>fasgram 英文法トレーニングwebアプリ</title>
    <!--jquery-->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <!--jquery UI-->
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
    <!--Google Font-->
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Kosugi&family=Noto+Serif&display=swap" rel="stylesheet">
    <!--Font Awesome -->
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
    <!--Fasgram-->
    <script src="fasgram-main.js"></script>
    <script src="fasgram.js"></script>
    <link rel="stylesheet" href="./fasgram.css">
</head>
<body>
    <div class="container">
        <header>
            <p class="size-4">英文法トレーニングwebアプリ fasgram<span class="badge">動作サンプル</span></p>
            <div id="control-panel"></div>
        </header>
        <article>
            <div id="display"></div>
        </article>
        <footer></footer>
    </div>
<script>
    main();
</script>
</body>
</html>

まずは,htmlです。動作にはjquery,jquery UI,Font Awesomeが必要です。また,ここではGoogle Fontsも使用しています。

    <script src="fasgram-main.js"></script>
    <script src="fasgram.js"></script>
    <link rel="stylesheet" href="./fasgram.css">

Fasgramを動作させる部分です。fasgram-main.jsはhtmlの最後で呼び出している関数main()を記述しています。

fasgram.jsがライブラリ本体です。また,fasgram.cssも読み込んでください。

Fasgramのインスタンス

次に,関数main()を記述したfasgram-main.jsを見てみましょう。

//全体のフローチャート
async function main() {
    const obj = {
        selector: '#display', //問題文などを格納するセレクタ
        control_panel: '#control-panel', //コントロールパネルを格納するセレクタ
        local_storage_key: 'fasgram', //LocalStorageのキー
        session_goal: 20, //スコアがこの値に達したときにセッションを終了する
        //トレーニングごとに加算されるスコア
        score_description: 1,   //項目の説明
        score_read_aloud: 3,    //音読
        score_filling: 5,       //語句入力
        score_sorting: 5,       //並べかえ
        score_selecting: 5,     //語句選択
        score_fail: -5          //不正解の場合のスコアの減算値
    };
    const texts = await load_texts('./data/data.json'); //問題文の読み込み
    fasgram = new Fasgram(obj, texts); //fasgramのインスタンス
    //トレーニング実行のしきい値 スコアが[最小,最大]の間で表示
    const filter = {
        description: {min: 0, max: 5},   //項目の説明
        read_aloud: {min: 0, max: 10},   //音読
        filling: {min: 0, max: 15},      //語句入力
        sorting: {min: 10, max: 30},     //並べかえ
        selecting: {min: 20, max: 30},   //語句選択
        id_goal: 30  //それぞれの項目がこの値に達したら学習を達成したとみなす
    }
    await fasgram.auto(filter);  //自動でトレーニングを行う
    location.reload(); //ページを読み直して最初に戻る
}
//問題文の読み込み
async function load_texts(URL) {
    const data = await fetch(URL, {cache: "no-cache"});
    const obj = await data.json();
    const obj_json = JSON.stringify(obj); //json文字列に変換
    const texts = JSON.parse(obj_json); //配列に格納
    return texts;
}

ライブラリのメソッドの多くは逐次的に動作させるためにawaitを用いています。したがって,関数main()の先頭にasyncを付けておく必要があります。

    fasgram = new Fasgram(obj, texts); //fasgramのインスタンス

まず,クラスのインスタンスを実行します。

インスタンスとは実体化とも訳されますが,Fasgramを動かすために初めに電源を入れるような動作だと解釈しても良いでしょう。

Fasgramには引数として初期設定を格納したオブジェクトobjと,問題文のデータを格納したオブジェクトtextsを渡します。

objの中身を見てみましょう。

        selector: '#display', //問題文などを格納するセレクタ

問題文などを格納するセレクタを指定します。

htmlの中で<div id="display"></div>とされているブロック要素に問題文などが表示されます。

        control_panel: '#control-panel', //コントロールパネルを格納するセレクタ

同様にコントロールパネルを格納するセレクタを指定します。

画面上部のコントロールパネルにはセッションの進捗を示すプログレスバーやボタンが表示されます。

        local_storage_key: 'fasgram', //LocalStorageのキー

LocalStrageのキーを指定します。

現在のところ,Fasgramは学習の記録をLocalStorageに保存します。LocalStorageはブラウザ自体にデータを保存する仕組みで,キーと値 のセットでデータを保存します。ここでは保存に用いるキーを指定します。

fasgramはセッションの途中でも,その都度学習記録を保存します。したがって,セッションの途中でブラウザを閉じても,トレーニングを再開したときには,ブラウザを閉じた時点での学習状態から再開することになります。

        session_goal: 20, //スコアがこの値に達したときにセッションを終了する

セッションの終了点を指定します。画面上ではプログレスバーの右端の点を表します。セッションのスコアがこの値に達するとセッションを終了します。

        //トレーニングごとに加算されるスコア
        score_description: 1,   //項目の説明
        score_read_aloud: 3,    //音読
        score_filling: 5,       //語句入力
        score_sorting: 5,       //並べかえ
        score_selecting: 5,     //語句選択

トレーニングごとに加算されるスコアを指定します。

実行できるトレーニングは,項目の説明,音読,語句入力,並べ替え,語句選択の5種類です。項目の説明と音読ではトレーニングが表示された時点でスコアが加算されます。語句入力,並べかえ,語句選択では問題に正解した場合にこれらの得点が加算されます。

あとで説明しますが,これらのスコアは文法の各項目ごとに加算されます。したがって,fasgramの中ではセッションのスコアと,それぞれの項目ごとのスコアが存在します。

        score_fail: -5          //不正解の場合のスコアの減算値

不正解の場合のスコアの減算値を指定します。サンプルでは,問題に不正解の場合,その項目のスコアを5減らすことになります。

トレーニングデータ

また,Fasgramにはトレーニングのデータtextsを与えます。

data.json

[
{
    "id": "不定詞の名詞的用法",
    "description": ["<p class='size-4'>不定詞の名詞的用法</p><p class='size-1'>want to</p><p class='size-2'>~したい</p>"],
    "en_sentence": "He wants to be independent of his parents.",
    "ja_sentence": "彼は自分の親から自立したいと思っている。",
    "fill_sentence": "He # be independent of his parents.",
    "fill_answer": ["wants to"],
    "sort_sentence": "He # his parents.",
    "sort_option": ["wants","to","be","independent","of"],
    "sort_answer": ["wants to be independent of"] 
},
{
    "id": "不定詞の形容詞的用法1",
    "description": ["<p class='size-4'>不定詞の形容詞的用法</p><p class='size-1'>to ~</p><p class='size-2'>~するための</p><p class='size-3'>something to drink</p><p class='size-3'>飲むためのもの(飲み物)</p>"],
    "en_sentence": "After a long walk in the fields I wanted something cold to drink.",
    "ja_sentence": "野外での長い徒歩のあと,私は冷たい飲み物が欲しかった。",
    "fill_sentence": "After a long walk in the fields I wanted something cold #.",
    "fill_answer": ["to drink"],
    "sort_sentence": "After a long walk in the fields I wanted #.",
    "sort_option": ["something","cold","to","drink"],
    "sort_answer": ["something cold to drink"] 
},
{
    "id": "不定詞の形容詞的用法2",
    "description": ["<p class='size-4'>不定詞の形容詞的用法</p><p class='size-1'>to ~</p><p class='size-2'>~するための</p><p class='size-3'>a good way to lose weight</p><p class='size-3'>体重を減らすための良い方法</p>"],
    "en_sentence": "The doctor explained to his patient that jogging is a good way to lose weight.",
    "ja_sentence": "医者は患者にジョギングが体重を減らすのに良い方法であると説明した。",
    "fill_sentence": "The doctor explained to his patient that jogging is a good way # weight.",
    "fill_answer": ["to lose"],
    "sort_sentence": "The doctor explained to his patient that #.",
    "sort_option": ["jogging","is","a good","way","to","lose","weight"],
    "sort_answer": ["jogging is a good way to lose weight"] 
},
{
    "id": "不定詞の否定not-to",
    "description": ["<p class='size-4'>不定詞の否定</p><p class='size-1'>not to ~</p><p class='size-2'>~しないように</p><p class='size-3'>不定詞の否定の形は not to 動詞原形 となります。間違えて to not ~ としやすいので注意しましょう。</p>"],
    "en_sentence": "My father told me not to work too hard.",
    "ja_sentence": "私の父は私にあまりに働きすぎないように言った。",
    "fill_sentence": "My father told me # work too hard.",
    "fill_answer": ["not to"],
    "select_sentence": "My father told me # work too hard.",
    "select_option": ["not to","dont't","not","without"],
    "select_answer": ["not to"],
    "sort_sentence": "My father # too hard.",
    "sort_option": ["told","me","not","to","work"],
    "sort_answer": ["told me not to work"]
},
{
    "id": "人の性質を表す語に用いるof",
    "description": ["<p class='size-4'>人の性質を表す語に用いるof</p><p class='size-3'>It was careless <span class='color-blue'>of</span> you to leave the door unlocked.</p><p class='size-3'>ドアに鍵をかけないままにするとはあなたは不注意だ。</p><p class='size-3'>通常は It is ~ <span class='color-blue'>for</span> (人) to ・・・ ですが,kind,clever,careless など人の性質を表す語では <span class='color-blue'>of</span> が用いられます。</p>"],
    "en_sentence": "It was careless of you to leave the door unlocked.",
    "ja_sentence": "ドアに鍵をかけないままにするとはあなたは不注意だ。",
    "fill_sentence": "It was careless # to leave the door unlocked.",
    "fill_answer": ["of you"],
    "sort_sentence": "It was # the door unlocked.",
    "sort_option": ["careless","of","you","to","leave"],
    "sort_answer": ["careless of you to leave"]    
},
{
    "id": "expect-to",
    "description": ["<p class='size-1'>expect ~ to ・・・</p><p class='size-2'>~が・・・すると予想,期待する。</p>"],
    "en_sentence": "I liked his new house, but I hadn't expected it to be so small.",
    "ja_sentence": "私は彼の新しい家を気に入ったが,それがあれほど小さいとは予想していなかった。",
    "fill_sentence": "I liked his new house, but I hadn't expected it # so small.",
    "fill_answer": ["to be"],
    "select_sentence": "I liked his new house, but I hadn't expected it # so small.",
    "select_option": ["be","of being","to be","to being"],
    "select_answer": ["to be"],
    "sort_sentence": "I liked his new house, but I hadn't #.",
    "sort_option": ["expected","it","to","be","so","small"],
    "sort_answer": ["expected it to be so small"]
}
]

サンプルとして上記のデータを用意しています。ここでは高校英文法の不定詞を学習するために6個の項目を用意しました。こうしたデータを独自に用意することで,オリジナルの問題でトレーニングを行うことができます。

id 項目を識別する文字列

description 項目の説明。サンプルにあるようにhtmlで記述します。

en_sentence 英文。

ja_sentence 日本文。

fill_sentence 語句入力問題の英文。語句入力させたい部分を#で表す。#は文中に1か所だけ用いることができる。

fill_answer #に当てはまる解答。

select_sentence 語句選択問題の英文。語句入力させたい部分を#で表す。#は文中に1か所だけ用いることができる。

select_option #に当てはめる選択肢。サンプルでは選択肢の数はすべて4個だが,実際には任意の数に対応する。それぞれの選択肢はその都度,ランダムな順番で表示される。

select_answer #に当てはまる解答。

sort_sentence 並べ替え問題の英文。語句入力させたい部分を#で表す。#は文中に1か所だけ用いることができる。

sort_option #に当てはめる選択肢。それぞれの選択肢はその都度,ランダムな順番で表示される。

sort_answer 並べ替え問題の解答。

サンプルを見ると分かりますが,それぞれの項目は必須ではありません。学習項目によって並べかえ問題のみを実行する場合,並べかえと語句入力を実行する場合など,さまざまなパターンを用意することができます。

これらのデータをFasgramに与え,インスタンスを実行します。

オートモードの実行

    await fasgram.auto(filter);  //自動でトレーニングを行う

Fasgramにはオートモードが用意されています。上記のコードを書くだけで,基本的なトレーニングを自動で行うことができます。オードモードにはオブジェクトfilterを与える必要があります。

    //トレーニング実行のしきい値 スコアが[最小,最大]の間で表示
    const filter = {
        description: {min: 0, max: 5},   //項目の説明
        read_aloud: {min: 0, max: 10},   //音読
        filling: {min: 0, max: 15},      //語句入力
        sorting: {min: 10, max: 30},     //並べかえ
        selecting: {min: 20, max: 30},   //語句選択
        id_goal: 30  //それぞれの項目がこの値に達したら学習を達成したとみなす
    }

filterで与えるのは主にトレーニングのしきい値です。それぞれの項目のスコアがしきい値の間にあるときに,それぞれのトレーニングが実行されます。例えば,項目のスコアが0のときには,項目の説明,音読,語句入力が実行されます。また,項目のスコアが12のときには語句入力と並べかえが実行されることが分かります。

オートモードでは,このように学習の進捗によって実行するトレーニングが選択されるようになっています。サンプルのしきい値はあくまで一つの事例なので,必要性に応じて値を変更すると良いでしょう。

また,id_goalはそれぞれの項目の完了点を示し,スコアがこの点を超えると表示されることはありません。

    location.reload(); //ページを読み直して最初に戻る

セッションが終了したらページをリロードして,最初のスタート画面に戻ります。

オートモードを用いない場合

オートモードを用いず,メソッドを直接呼び出すことでトレーニングを実行することもできます。

async function main() {
    const obj = {
        selector: '#display', //問題文などを格納するセレクタ
        control_panel: '#control-panel', //コントロールパネルを格納するセレクタ
        local_storage_key: 'fasgram', //LocalStorageのキー
        session_goal: 20, //スコアがこの値に達したときにセッションを終了する
        //トレーニングごとに加算されるスコア
        score_description: 1,   //項目の説明
        score_read_aloud: 3,    //音読
        score_filling: 5,       //語句入力
        score_sorting: 5,       //並べかえ
        score_selecting: 5,     //語句選択
        score_fail: -5          //不正解の場合のスコアの減算値
    };
    const texts = await load_texts('./data/data.json'); //問題文の読み込み
    fasgram = new Fasgram(obj, texts); //fasgramのインスタンス
    await fasgram.filling(0);
  //語句入力問題
    await fasgram.sorting(0);
  //並べかえ問題
}
//問題文の読み込み
async function load_texts(URL) {
    const data = await fetch(URL, {cache: "no-cache"});
    const obj = await data.json();
    const obj_json = JSON.stringify(obj); //json文字列に変換
    const texts = JSON.parse(obj_json); //配列に格納
    return texts;
}

このコードは,Fasgramをインスタンスしたあと,語句入力問題と並べかえ問題を一つずつ実行します。filling()sorting()には読み込んだ問題文の配列の0番目を与えています。

このように,メソッドを呼び出してトレーニングを行う場合には,引数に配列の番号を与えます。メソッドを組み合わせることで,独自のトレーニングプログラムを作成することができます。

次に,Fasgramで用意されているメソッドを説明します。

メソッド

Fasgramのメソッドの多くは逐次的に実行するために,メソッドの前にawaitを記述する必要があります。そのため,メソッドを呼び出す関数にもasyncを記述してください。

await Fasgram.auto(filter) オートモードを実行します。引数にしきい値などを格納したオブジェクトfilterを与えます。filterについては上記を参考にしてください。

await Fasgram.filling(k) 語句入力問題を実行します。引数kには問題文データの配列の番号を与えます。トレーニングを実行すると,正解・不正解によってその項目のスコアが加算されます。

await Fasgram.sorting(k) 並べかえ問題を実行します。引数kには問題文データの配列の番号を与えます。トレーニングを実行すると,正解・不正解によってその項目のスコアが加算されます。

await Fasgram.selecting(k) 語句選択問題を実行します。引数kには問題文データの配列の番号を与えます。トレーニングを実行すると,正解・不正解によってその項目のスコアが加算されます。

await Fasgram.description(k) 項目の学習内容を表示します。引数kには問題文データの配列の番号を与えます。トレーニングを実行すると,その項目のスコアが加算されます。

await Fasgram.read_aloud(k) 英文を表示し,音読を行います。引数kには問題文データの配列の番号を与えます。トレーニングを実行すると,その項目のスコアが加算されます。

Fasgram.score_transaction(id, score) 項目ごとのスコアを加算または減算します。たとえば,

fasgram.score_transaction("不定詞の名詞的用法", 5);

とすると,項目"不定詞の名詞的用法"に,5点が加算されます。scoreに負の数を指定すると減算されます。項目ごとのスコアは,以下のようなオブジェクトとして格納されます。

{不定詞の名詞的用法: 5, 不定詞の形容詞的用法1: 12, 不定詞の形容詞的用法2: 32, 不定詞の否定not-to: 32, 人の性質を表す語に用いるof: 32, …}

スコアを減算しても0点以下になることはありません。

score_transactionを実行すると,指定されたLocalStorageにスコアが保存されます。保存されたデータは,Fasgramをインスタンスしたときに自動的に読み込まれます。

Fasgram.get_score_by_id() 項目ごとのスコアを格納したオブジェクトを返します。

let obj = fasgram.get_score_by_id();

--->

obj = {不定詞の名詞的用法: 5, 不定詞の形容詞的用法1: 12, 不定詞の形容詞的用法2: 32, 不定詞の否定not-to: 32, 人の性質を表す語に用いるof: 32, …}

Fasgram.get_session_score() セッションのスコアを返します。

await Fasgram.starting() スタート画面を表示します。

await Fasgram.session_closing() セッションの終了を知らせる画面を表示します。

await Fasgram.category_closing() 学習項目をすべて終了したことを知らせる画面を表示します。

Fasgram.set_control_panel() コントロールパネルを設置します。セッションの進捗状況を示すプログレスバーと「はじめに戻る」ボタンを表示します。

Fasgram.progress_bar() セッションの進捗状況を示すプログレスバーを表示します。

await Fasgram.button_confirm(selector) 「次に進む」ボタンを表示します。引数にボタンを表示するセレクタを指定します。

Fasgram.keyboard(selector) ソフトウェアキーボードを表示します。引数にキーボードを表示するセレクタを指定します。keyboard()はあくまでソフトウェアキーボードを表示するだけです。戻り値としてそれぞれのキーのセレクタを配列として返すので,それをもとにイベントリスナーを設置してください。

Fasgram.set_speech_sentence(selector1, selector2, en_sentence) 表示されている英文に,読み上げ機能を追加します。selector1に指定したセレクタには’英文をクリックして音声を聞きましょう。’というメッセージが表示されます。また,selector2に指定したセレクタをクリックすると英文を読み上げます。en_sentenceには読み上げる英文の文字列を指定します。

Fasgram.speech_sentence(sentence) sentenceで指定した英文の文字列を読み上げます。

現在,用意されているメソッドは以上です。これらのメソッドを組み合わせて独自のトレーニングプログラムを作成できます。