jsPsych6用のプログラムをjsPsych7用にインポートしてみた

## はじめに
いきなりの jsPsych の後方互換性無しのバージョンアップ、皆様ご愁傷様です。(私を含め)
何はともあれ今までのプログラムを最新版のVer.7で動作するようにインポートしてみました。

## 今回インポートするプログラム
こんな実験を用意しました。

1.学籍番号、性別、年齢の入力
2.以下の4枚の画像をランダムに表示して、5段階で魚かどうかを選択
　　(凝視点1秒→画像表示→キー入力待ち、を繰り返す。)
3.終了メッセージ

<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/53f5be40-e7f4-05d5-f733-c4f505173f36.jpeg"><img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/5f046203-40e5-eed5-11b0-689e5e4a1852.jpeg"><img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/02f0a6f4-2940-2053-14a7-744e10947fbf.jpeg"><img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1252322/49dc039f-fdcc-167c-37a2-3f107ed3f68a.jpeg">

実験用プログラムが動作している様子
<iframe width="560" height="315" src="https://www.youtube.com/embed/S6Z5zw2Nw1Y" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

## Ver.6で使用したプログラム

```html:index.html(ver6)
<!DOCTYPE html>
<meta charset="UTF-8">
<html>
    <head>
      <title>My experiment</title>
      <!-- jspsych 本体の読み込み -->
      <script src="../jspsych.js"></script>
      <link  href="../css/jspsych.css" rel="stylesheet" type="text/css">

      <!-- jspsych プラグインの読み込み -->
      <script src="../plugins/jspsych-html-keyboard-response.js"></script>
      <script src="../plugins/jspsych-survey-text.js"></script>

      <!-- jspsych 実験用プログラムの読み込み -->
      <script src="./script.js"></script>
  </head>
  <body>
  </body>
</html>
```

```javascript:script.js(ver6)
// ------------------------------------------------------------------------
// 固定の実験パーツ
// ------------------------------------------------------------------------

// 最初の説明と被検者情報の入力
var par_id = {
  type: 'survey-text',
  questions: [
    {prompt: '<strong>これから大学生における魚の認知度についての実験を始めます。</strong><br><br><br>学籍番号を入力してください', columns: 10, required: true, name: 'id'},
    {prompt: 'あなたの性別を男性であれば 1、女性であれば 2、答えたくない場合は 3 を入力してください。', columns: 5, required: true, name: 'sex'},
    {prompt: 'あなたの年齢を入力してください。', columns: 5, required: true, name: 'age'},
  ],
  button_label: '次へ',
};

// 実験の説明
var hello = {
  type: 'html-keyboard-response',
  stimulus: '実験を始めます。 写真の前には1秒凝視点が出ます。<br><br>何かキーを押すと始まります。',
};

// 凝視点
var eyepoint = {
  type: 'html-keyboard-response',
  stimulus: '<p style="font-size: 48px;">+</p>',
  choices: jsPsych.NO_KEYS,
  trial_duration: 1000,
};

// 実験の終了
var bye = {
  type: 'html-keyboard-response',
  stimulus: 'これで実験は終了です。 PCには触れずに実験者の指示に従ってください。',
};

// ------------------------------------------------------------------------
// 画像問題の作成
// ------------------------------------------------------------------------

// 画像ファイルの用意
var baseURL = './' ;
var examPictures = [
  { label: 'No.01 egi'           , filename: '1.jpg' },
  { label: 'No.02 akoudai'       , filename: '2.jpg' },
  { label: 'No.03 chikamekintoki', filename: '3.jpg' },
  { label: 'No.04 madako'        , filename: '4.jpg' },
];

// 選択肢
var myScale = '\
<font size=2>\
<center>\
これはどのくらい魚だと思いますか。\
<TABLE style=”border:none;">\
<TR>\
  <TD align="center">┣━━━━━━ 1 ━━━━━━<BR>魚</TD>\
  <TD align="center">┣━━━━━━ 2 ━━━━━━<BR>やや魚</TD>\
  <TD align="center">┣━━━━━━ 3 ━━━━━━<BR>どちらでもない</TD>\
  <TD align="center">┣━━━━━━ 4 ━━━━━━<BR>やや魚以外</TD>\
  <TD align="center">┣━━━━━━ 5 ━━━━━━┫<BR>魚以外</TD>\
</TR>\
</TABLE>\
</center>\
</font>\
' ;

// 順番をランダマイズしたいので指定しておく
var trials = {
  timeline: [],
  timeline_variables: examPictures,
  randomize_order: true,
};

// 画像問題の本体
var exam = {
    type: 'html-keyboard-response',
    stimulus: function () {return  '<img src="'+ baseURL + jsPsych.timelineVariable('filename') + '" height=350><br><br>'; },
    prompt: function () {return myScale; },
    choices: ["1","2","3","4","5"],
    data: {
      label: jsPsych.timelineVariable('label'),
    },
};

trials.timeline.push(eyepoint) ;
trials.timeline.push(exam) ;

// ------------------------------------------------------------------------
// 実験の開始
// ------------------------------------------------------------------------

jsPsych.init({
    timeline: [par_id,hello,trials,bye],
    on_finish: function() {
      //    jsPsych.data.get().localSave('csv', 'data.csv');
      jsPsych.data.displayData();
    },
});
```
## Ver.7のインストール
Ver.7 にはインストール方法が3つあります。
・ネット接続前提でCDN経由で使用
・npmでインストール
しかしこの2つは jsPsych のお手軽インストールとどこでも実験できる良さを台無しにしているような気がするので、個人的には
・丸っとダウンロード
一択です。
この時、gitのトップページからではなく、https://github.com/jspsych/jsPsych/releases ページの、最新版の assets  から Dist archive (zip)  をダウンロードして使います。
これをお好みの場所で展開すれば今までに近い感じで使うことができます。

プログラムを置くのはjsPsychを展開したディレクトリで、プログラム用のディレクトリ !Myexperiment を作成してある前提で説明を進めます。

Ver.6のディレクトリ構成

```
----  📂 !Myexperiment
----  📂 css
----  📂 examples
----  📂 plugins
----  📄 jspsych.js
----  📄 index.html
```

Ver.7のディレクトリ構成

```
----  📂 !Myexperiment
----  📂 dist
----  📂 examples
----  📄 code-of-conduct.md
----  📄 contributors.md
----  📄 license.txt
----  📄 README.md
```

## Ver.7対応(1) htmlファイルの修正
jsPsych本体/css/プラグインの、ファイル名とパスを修正します。
今回使っているプラグインは、html-keyboard-response / survey-text だけです。

```html:index.html(ver6)
      <!-- jspsych 本体の読み込み -->
      <script src="../jspsych.js"></script>
      <link  href="../css/jspsych.css" rel="stylesheet" type="text/css">
      <!-- jspsych プラグインの読み込み -->
      <script src="../plugins/jspsych-html-keyboard-response.js"></script>
      <script src="../plugins/jspsych-survey-text.js"></script>
```

```html:index.html(ver7)
      <!-- jspsych 本体の読み込み -->
      <script src="../dist/jspsych.js"></script>
      <link href="../dist/jspsych.css" rel="stylesheet" type="text/css">
      <!-- jspsych プラグインの読み込み -->
      <script src="../dist/plugin-html-keyboard-response.js"></script>
      <script src="../dist/plugin-survey-text.js"></script>
```
|  Ver6  |  Ver7  |
| ---- | ---- |
|  ../jspsych.js       |  ../dist/jspsych.js  |
|  ../css/jspsych.css  |  ../dist/jspsych.css |
|./plugins/jspsych-html-keyboard-response.js  | ../dist/plugin-html-keyboard-response.js |
|./plugins/jspsych-survey-text.js             | ../dist/plugin-survey-text.js |

## Ver.7対応(2) jsファイル,試行オブジェクト typeの修正
プログラム中の、全ての type を Ver7 用に修正します。

```javascript:script.js(ver6)
var par_id = {
  type: 'survey-text',
  questions: [
    {prompt: '<strong>これから大学生における魚の認知度についての実験を始めます。</strong><br><br><br>学籍番号を入力してください', columns: 10, required: true, name: 'id'},
    {prompt: 'あなたの性別を男性であれば 1、女性であれば 2、答えたくない場合は 3 を入力してください。', columns: 5, required: true, name: 'sex'},
    {prompt: 'あなたの年齢を入力してください。', columns: 5, required: true, name: 'age'},
  ],
  button_label: '次へ',
};
var bye = {
  type: 'html-keyboard-response',
  stimulus: 'これで実験は終了です。 PCには触れずに実験者の指示に従ってください。',
};
```

```javascript:script.js(ver7)
var par_id = {
  type: jsPsychSurveyText,
  questions: [
    {prompt: '<strong>これから大学生における魚の認知度についての実験を始めます。</strong><br><br><br>学籍番号を入力してください', columns: 10, required: true, name: 'id'},
    {prompt: 'あなたの性別を男性であれば 1、女性であれば 2、答えたくない場合は 3 を入力してください。', columns: 5, required: true, name: 'sex'},
    {prompt: 'あなたの年齢を入力してください。', columns: 5, required: true, name: 'age'},
  ],
  button_label: '次へ',
};

var bye = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: 'これで実験は終了です。 PCには触れずに実験者の指示に従ってください。',
};
```

|  Ver6  |  Ver7  |
| ---- | ---- |
|type: 'survey-text'            | type: jsPsychSurveyText           |
|type: 'html-keyboard-response' | type: jsPsychHtmlKeyboardResponse |

## Ver.7対応(3) jsファイル,init/runの修正

Ver6ではプログラムの一番最後に

```javascript:script.js(ver6)
jsPsych.init({
    timeline: [par_id,hello,trials,bye],
    on_finish: function() {
      //    jsPsych.data.get().localSave('csv', 'data.csv');
      jsPsych.data.displayData();
    },
});
```

と記述していましたが、Ver7では以下のようになります。

```javascript:script.js(ver7)
var jsPsych = initJsPsych({
  on_finish: function() {
//    jsPsych.data.get().localSave('csv', 'data.csv');
    jsPsych.data.displayData();
  }
});
・
・
プログラム(略)
・
・
jsPsych.run([par_id,hello,trials,bye]);
```

## 修正が完了したプログラム
全ての修正が終わると、プログラムはこのようになっています。

```html:index.html(ver7)
<!DOCTYPE html>
<meta charset="UTF-8">
<html>
    <head>
      <title>My experiment</title>
      <!-- jspsych 本体の読み込み -->
      <script src="../dist/jspsych.js"></script>
      <link href="../dist/jspsych.css" rel="stylesheet" type="text/css">

      <!-- jspsych プラグインの読み込み -->
      <script src="../dist/plugin-html-keyboard-response.js"></script>
      <script src="../dist/plugin-survey-text.js"></script>

      <!-- jspsych 実験用プログラムの読み込み -->
      <script src="./script.js"></script>
  </head>
  <body>
  </body>
</html>
```

```javascript:script.js(ver7)
var jsPsych = initJsPsych({
  on_finish: function() {
//    jsPsych.data.get().localSave('csv', 'data.csv');
    jsPsych.data.displayData();
  }
});

// ------------------------------------------------------------------------
// 固定の実験パーツ
// ------------------------------------------------------------------------

// 最初の説明と被検者情報の入力
var par_id = {
  type: jsPsychSurveyText,
  questions: [
    {prompt: '<strong>これから大学生における魚の認知度についての実験を始めます。</strong><br><br><br>学籍番号を入力してください', columns: 10, required: true, name: 'id'},
    {prompt: 'あなたの性別を男性であれば 1、女性であれば 2、答えたくない場合は 3 を入力してください。', columns: 5, required: true, name: 'sex'},
    {prompt: 'あなたの年齢を入力してください。', columns: 5, required: true, name: 'age'},
  ],
  button_label: '次へ',
};

// 実験の説明
var hello = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: '実験を始めます。 写真の前には1秒凝視点が出ます。<br><br>何かキーを押すと始まります。',
};

// 凝視点
var eyepoint = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: '<p style="font-size: 48px;">+</p>',
  choices: jsPsych.NO_KEYS,
  trial_duration: 1000,
};

// 実験の終了
var bye = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: 'これで実験は終了です。 PCには触れずに実験者の指示に従ってください。',
};

// ------------------------------------------------------------------------
// 画像問題の作成
// ------------------------------------------------------------------------

// 画像ファイルの用意
var baseURL = './' ;
var examPictures = [
  { label: 'No.01 egi'           , filename: '1.jpg' },
  { label: 'No.02 akoudai'       , filename: '2.jpg' },
  { label: 'No.03 chikamekintoki', filename: '3.jpg' },
  { label: 'No.04 madako'        , filename: '4.jpg' },
];

// 選択肢
var myScale = '\
<font size=2>\
<center>\
これはどのくらい魚だと思いますか。\
<TABLE style=”border:none;border-collapse:collapse;">\
<TR>\
  <TD align="center">┣━━━━━━ 1 ━━━━━━<BR>魚</TD>\
  <TD align="center">┣━━━━━━ 2 ━━━━━━<BR>やや魚</TD>\
  <TD align="center">┣━━━━━━ 3 ━━━━━━<BR>どちらでもない</TD>\
  <TD align="center">┣━━━━━━ 4 ━━━━━━<BR>やや魚以外</TD>\
  <TD align="center">┣━━━━━━ 5 ━━━━━━┫<BR>魚以外</TD>\
</TR>\
</TABLE>\
</center>\
</font>\
' ;

// 順番をランダマイズしたいので指定しておく
var trials = {
  timeline: [],
  timeline_variables: examPictures,
  randomize_order: true,
};

// 画像問題の本体
var exam = {
    type: jsPsychHtmlKeyboardResponse,
    stimulus: function () {return  '<img src="'+ baseURL + jsPsych.timelineVariable('filename') + '" height=350><br><br>'; },
    prompt: function () {return myScale; },
    choices: ["1","2","3","4","5"],
    data: {
      label: jsPsych.timelineVariable('label'),
    },
};

trials.timeline.push(eyepoint) ;
trials.timeline.push(exam) ;

// ------------------------------------------------------------------------
// 実験の開始
// ------------------------------------------------------------------------

jsPsych.run([par_id,hello,trials,bye]);
```

上記の画像ファイルをダウンロードして同じディレクトリに、1.jpg,2.jpg,3.jpg,4.jpg と名前を付けて保存しておけばこのプログラムが動きます。

## まとめ

### インポートの手順
1.一式を間違わずにダウンロードして、
2.htmlファイルでのjs/css読み込みのパスを変更
3.typeを変更
4.jsPsychオブジェクトの定義と、run
といった手順で移行できました。

### 今までと変わらないところ
・各試行のオプション指定
・結果の表示保存方法
・ランダム表示

### 余談
・慣れたら30分もかかりませんが、これだけのバージョンアップ直後にあまりテストをしないで投入するような勇気はないので、やはり使うのは来年度からにしておこうと思います。 その間に人柱や、ちゃんとしたドキュメントを残してくれる人が出てくるでしょう。

・何人かに jsPsych をレクチャーしたところ、パスの記述とカッコのツジツマでつまずいていました。
次回レクチャーをするときは、相対パスとデバッグ方法を重点的にやっておこうと思いました。

・どうして type の互換性をわざわざ無くしたのか、思いついてコードを書いた人は丸刈りにして正座した上で理由を述べて欲しいです。