ExpressionScript - presentation/ja
From LimeSurvey Manual
はじめに
LimeSurveyでは、新しいExpressionScript(EM)モジュールを使用して、より複雑な分岐、評価、検証、および文言調整がサポートされています。LimeSurveyがサーバー内で行う置換、条件、評価の管理方法を置き換えることができます。また、ランタイムデータベースの読み込みのほとんどが不要になるため、処理速度が大幅に向上します。EMはDr. Thomas White(TMSWhite)が開発しました。
主な定義
- 式: 中括弧で囲まれたもの
- 開く中括弧の直後または閉じる中括弧の直前に空白がない
- 式の内容はEMが評価するため、数式、関数、複雑な文字列と日付処理を含めることができます。
- 文言調整: "パイピング"とも呼ばれますが、これは条件付きでテキストを変更するプロセスです。
- すべての'置換フィールド'、参加者データ、回答データにアクセスできます。
- 質問、回答、およびそのプロパティにも簡単にアクセスできます。
- 出現条件式: 質問を表示するかを制御する新しい質問属性
- 出現条件式がある場合、その出現条件が真と評価された場合にのみ質問が表示されます。
- 内部では、すべてのarray_filterコマンドとarray_filter_excludeコマンドがサブ質問レベルの出現条件になります。
- SGQA: LimeSurvey <= 1.91+で変数の命名に使われているものです。
- Survey(アンケート)-Group(グループ)-Question(質問)-Answer(回答)の略です。
- SGQA変数は123X5X382X971のようなもので、サブ質問の接尾辞がつくことがあります。
- これらの変数はベースとなるS/Q/G/Aデータベースコードに固有のもので、変更する必要があることが良くあります。
- 式質問タイプ: データベースに計算やレポートを保存する新しい質問タイプ
- これはテキストを表示する質問のようなものですが、"この質問をいつも隠す"を設定しても、その内容はデータベースに保存されます。
- 質問コード: EMでの使用が推奨される変数名
- これは質問の目的を示すわかりやすい名前にすることができ、複雑なロジックを読みやすくなります。
- 質問コードは数字で始めることはできないので、質問番号を質問コードにするときは、単に"q1"、"q1a"、"g1q2"のようにしてください。
- 現在のところ、データをSPSSまたはRにエクスポートすると、これが変数名になります。したがって、統計分析を行う場合は、ユニークにしなければなりません。
EMを使わなければならないのか?
短い答えは"いいえ"ですが、作成するアンケートがどれだけ複雑かによって変わります。
例えば、条件エディターでは、アンケートの質問に適用できるいくつかの基本的な式を扱います。ただし、条件エディタには制限があります。EMが使用されているのはこのためです。EMがカスタマイズの可能性を広げています。
条件と出現条件式の両方を使えるか?
はい。質問によって条件エディターを使用することも、出現条件式を使用することもできます。
条件と式の両方を同じ質問で設定することはできません。 条件が設定されると、出現条件のフィールドに書き込まれた式は使われません。さらに、出現条件式フィールドは手動では編集できません。
しかし、質問内で式と条件の両方を使用する方法があります。上で述べたように、条件式は出現条件式のフィールドを置き換えます。完了したら、新しく作成された式を確認し、テキストエディターにコピーします。条件エディターで作成した条件を削除し、残りの式と一緒にテキストエディターにコピーした条件ベースの式を追加して質問を編集します。
条件と関連のどちらを選ぶべきか?
各々の長所と短所のリストを以下に示します。
スタイル | 長所 | 短所 |
---|---|---|
条件 | 1. シンプルな条件を作成するための優れたGUI 2. サポートチームにより文書化され理解しやすいGUI |
1. 簡単な比較のみをサポートし、"AND"/"OR"条件はうまく機能しない 2. 条件を入れ子にした場合の動作が不安定 3. データベースアクセスが遅く、アンケートに時間がかかる 4. 条件のリロードで不具合がレポートされている 5. GUIに拡張性がなく、何十、何百、または何千もの質問があるときにうまくいかない 6. SGQA名を使用しなければならないので、紙ベースのアンケートを変換するのが遅いかもしれない 7. 複雑な分岐が必要な場合、カスタムコードロジックを書くプログラマーが必要なことがある |
出現条件 | 1. 80以上の関数と数学/文字列演算子を含む非常に複雑なロジックのサポート 2. 入れ子のロジックの完全サポート 3. 高速 - 余計なデータベースアクセスがなく、1000以上の質問があるアンケートをサポート 4. SGQAコードを必要としないため、リロードロジックで問題が生じない 5. 構文ハイライト機能は1000以上の質問があるアンケートにも対応 6. 既存の紙ベースのアンケートの電子化に簡単かつ迅速に対応 7. プログラマーを必要とせずに半構造化インタビューや疫学調査を容易にサポート |
1. 単純な条件のためのGUIがない(代わりに構文ハイライト機能を使用) |
- ニーズに合ったものを使用することをお勧めします。
- EM機能の詳細については、こちらをクリックしてください。
はじめに
式マネージャーを始める最善の方法は以下のとおりです。
- http://www.limesurvey.org/en/download からLimeSurveyの最新の安定版をインストールしてください。
- サンプルアンケートをインポートして確認します。
- 使用例と使用法やステップバイステップの例を読んでください。
- EMに関するドキュメント(このページ)を読んでください。
- 分離された式の単体テスト(上級)
- すべてのEM関数と演算子、PHPとJavaScriptの結果の使用例を表示します。
- PHPとJavaScriptのバージョンで異なる結果を生成する関数はほとんどありません。このページの内容を踏まえ、EMロジックを適切に計画することができます。
- 分離された式の単体テスト(上級)
用語
これらの単語は、EMの機能を記述するために一般的に使用されます。
- 出現条件に基づく分岐 - 質問が出現条件を満たす場合は質問し、満たさない場合は質問しません(非表示となり、データベース内ではNULLとして格納されます)。質問エディターパネルと質問グループエディターパネルに出現条件フィールドがあります。後者では、各質問に同じ条件をコピーしたり、グループと質問レベルの条件付きロジックを組み合わせたりせずに、一連の条件をグループ全体に適用するために使用されます。
- 文言調整 - どの質問を表示すべきか決めたら、文言調整(パイピングとも呼ぶ)でどのように質問するかを指定します。これは簡単な置換(例: {TOKEN:FIRSTNAME})だけでなく、回答者が回答した性別、数に基づいて、動詞や名詞を変化させることもできます。また、アンケート回答者が回答したか(またはどのように回答したか)に基づいて、アンケート回答者に送信するメッセージを変更することもできます。
- 式 - EMでは、式という新しい質問タイプを追加され、式の結果が格納されます。式はページ内で非表示であっても結果が計算され、データベースに書き込まれます。したがって、非表示のまま行うスコア計算、複雑な式に基づくナビゲーション、評価、データベース内に作成・格納されるレポートに使用されます。
出現条件とカスケードされた出現条件
すべての質問タイプで、質問が表示されるかどうかを制御する出現条件オプション が追加されました。EMは、アンケートに登場する順に出現条件式を処理します。式が真(または式がない - 古い形式のアンケート向け)の場合、質問が表示されます。出現条件式が偽の場合、質問は非表示になり、その値はデータベースでNULLになります。グループに出現条件を満たす質問がない場合、グループ全体がスキップされます。
さらに、式に含まれる変数のいずれかの出現条件が偽の場合、式は常に偽と評価されます。これにより出現条件の入れ子が可能になり、各々の質問に対して非常に長い出現条件の式を書く必要がなくなります。
たとえば、5つの質問Q1〜Q5があり、Q1が答えられたらQ2、Q2に答えられたらQ3などを表示したいとします。出現条件の式は次のようになります。
質問コード | 出現条件 | 質問 |
---|---|---|
Q1 | 1 | 名前は何ですか。 |
Q2 | Q1 | {Q1}さん、何歳ですか。 |
Q3 | Q2 | {Q2}歳なのですね。結婚していますか。 |
Q4 | Q3 == "Y" | {Q1}さん、結婚して何年になりますか。 |
Q5 | Q4 | {Q1}さん、子供は何人いますか。 |
グループレベルの出現条件
ExpressionScriptはグループレベルの関連性もサポートしています。これにより、ループの実装が容易になります。最大10のエンティティ(製品や家族など)から情報を収集したい場合、(家族の人数を答えさせたり、長いリストから好きな製品を選択させたりして)繰り返しが必要なエンティティの数を最初に判断します。エンティティの数がわかったら、10こある繰り返し用グループごとに{count >= 1}, {count >=2}, ... {count >= 10}のようにグループレベルの出現条件を設定します。各々のグループ内では、質問レベルの条件付きロジック(例:各々のエンティティの性別や年齢に基づく質問)を作成できます。質問とグループレベルの出現条件の式は、表示すべきかを決定するためにAND演算されます。
例を確認するには、次のアンケートをインポートします。国勢調査の例
以下のスクリーンショットでは、回答者が少なくとももう1人の同居者と一緒に住んでいる場合、グループPerson 1が表示されている(出現条件を満たしている)ことがわかります。
文言調整/パイプ
中括弧内のものはすべて式として扱われるようになりました(後述する例外が1つあります)。式はすべてのLimeReplacementFields、すべての変数(いくつかのエイリアスを介して)、すべての一般的な演算子(数学、論理、比較)、数多くの関数(クライアント側でも動的に機能する)にアクセスします。
これらの式を使用すると、次のようなことができます。
- 先行する質問への回答に基づいて文言調整されたメッセージを回答者に表示する
- 評価を作成し、その結果に基づいて評価結果を表示する(条件付きで分岐、またはメッセージを表示する)(評価モジュール自体は使用しない)
- 質問、回答、およびレポート内の動詞、名詞を変化させる
- アンケートの最後で、"回答を表示する"ページの前に回答の要約を表示する
式
式と呼ばれる新しい質問タイプがあります。これは、表示されている値をデータベースに格納することを除き、テキスト表示質問タイプと似ています。したがって、式の質問テキストに評価計算が含まれている場合、パブリックまたはプライベート統計情報内に表示できる変数の値がデータベースに格納されます。
構文
中カッコ内に含まれるものはすべて式と見なされます(ただし、先頭または末尾に空白がないことが必要です。これは、式マネージャーが埋め込みJavaScriptを処理しないようにするためです)。
開く括弧の後、閉じる括弧の前に空白がない限り、式は複数の行にまたがっても構いません。特に次のような入れ子のif()構文が見やすくなります。
{if(is_empty(PFTotals),
'',
if(PFTotals >= -5 && PFTotals <= -4,
'Very Soft',
if(PFTotals >= -3 && PFTotals <= -2,
'Soft',
if(PFTotals == -1,
'Somewhat Soft',
if(PFTotals == 0,
'Moderate',
if(PFTotals == 1,
'Somewhat Hard',
if(PFTotals >= 2 && PFTotals <= 3,
'Hard',
if(PFTotals >= 4 && PFTotals <= 5,
'Very Hard',
''
)
)
)
)
)
)
)
)}
式マネージャは、次の構文をサポートしています。
- 標準的な数学演算子(例: +,-,*,/,!)
- 標準的な比較演算子(例: <,<=,==,!=,>,>=, およびこれらと同じ意味を持つlt, le, eq, ne, gt, ge)
- かっこ(入れ子の式をグループ化できます)
- 条件演算子(例: &&, | | およびこれらと同じ意味を持つand, or)
- シングルまたはダブルクオートで囲まれた文字列(別のクオート記号で囲まれた文字列を含めることができます)
- コンマ演算子(式のリストを持ち、最終結果を返します)
- 代入演算子(=)
- 定義済み変数(質問、質問属性、回答を参照する) - 例: SGQAコード
- 定義済み関数(80以上あり、簡単に追加できます)
演算子
EM構文は、通常の演算子の優先順位に従います。
レベル | 演算子 | 説明 |
---|---|---|
1 | () | グループ化または関数呼び出しのための括弧 |
2 | ! - + | 単項演算子: 否定、正負 |
3 | * / | 乗算、除算 |
4 | + - | 加算、減算 |
5 | < <= > >= lt le gt ge | 比較演算子 |
6 | == != eq ne | 同等比較 |
7 | and | 論理積 AND |
8 | or | 論理和 OR |
9 | = | 代入演算子 |
10 | , | コンマ演算子 |
番号と文字列の不一致およびアルファベット/数字の比較に関する注意
次の用語は、EMの機能を記述するためによく使用されます。
たとえば、Q0.NAOKが数値質問で値が9である場合、Q0.NAOK > "50"
はtrueとなります。これは、演算子>
が、これを数値の比較ではなく、文字列の比較とみなすためです。
整数値を確実に比較するには、intval(Q0.NAOK) > 50
を使用します。Q0.NAOKが数値でない(空または文字列)場合は、intval(Q0.NAOK) === 0となります。文字列値を比較する("A" < "B")場合は、直接strcmpを使用します。strcmp(Q0.NAOK,"B")
またはstrcmp(Q0.NAOK,"A5")
代入演算子(=)を使用する際の注意
代入演算子は、予期しない副作用を引き起こす可能性があるため、どうしても必要な場合を除いて使用しないでください。たとえば、先行する質問の値を変更すると、その質問と現在の質問との間で入れ子となった出現条件と検証ロジックが再計算されないため、内部的に一貫性のないデータになることがあります(たとえば、NULLにすべきなのに回答がある、回答すべきだがスキップされる、等)。一般に、変数に値を割り当てる場合は、式の質問タイプを作成し、その値を設定する式を使用する必要があります。しかし、この演算子がまれに必要となるため用意されています。
この演算子について注意を促すため、構文式の中では赤いフォントで表示されています("=="と混同しないようにするため)。
代入演算子を使用する
代入演算子を使用する主な理由は次のとおりです。
- 既定値を設定できない質問の既定値を式を使って設定する必要がある(ユーザーインターフェイスでは回答オプションの1つを選択できるが、式を入力することができないリスト、ラジオなど)。ただし、LimeSurveyは式がその質問に対する許容可能な回答を生成できるかどうかを検証できないため、注意して使用してください。
- 後続の回答に基づいて先行する質問への回答を強制的に変更する必要がある
- など...
この目的のために、式マネージャーシステムを使用することができます。この目的のため、式を使用する方がよいでしょう。
例:
- 質問への回答を小文字にする:
{QCODE=strtolower(QCODE.NAOK)}
- アンケートの開始時に配列質問タイプに既定の回答を設定する:
{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),"A99",Q1_SQ1.NAOK)}
- アンケート開始時に配列テキストの質問タイプに対する既定の回答を設定する:
{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),"Inserted answer", Q1_SQY1_SQX1.NAOK)}
- 条件付きの回答を設定する:
{QCODE=if(YesNo="Y","A1","")}
XSS セキュリティ
XSSを有効にすると、式マネージャーシステムの一部がつかえなくなります。
- 式でHTMLタグを開き、別の式で閉じる
- URL内で複雑な式を使用する
例と解決策
{if( 1 ,"<strong>","")}information{if( 1 ,"</strong>","")}
はXSSでは正常に動作しないため、次のようにします。{if(1,"<strong>information</strong>","information")}
<a href="/script.php?value={if(QCODE == "Y","yes","no")}">next</a>
は、ここでは式の質問を使います。なぜなら、完全な質問コードがOKだからです。<a href="/script.php?value={EQUATION.NAOK}">next</a>
変数へのアクセス
式マネージャーでは、必要な変数に読み取り専用でアクセスできます。互換性のため、次のものにアクセスできます。
- TOKEN:xxx - TOKENの値(例: TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5)(匿名アンケートでないもののみ)
- INSERTANS:SGQA - 回答の表示値("はい"など) - {QCODE.shown}と類似
- すべてのテンプレートで使われる{XXX}の値
- 質問テキストでは、質問idの代わりに{QID}、質問のSGQAの代わりに{SGQ}を使います。
さらに、式マネージャーでは、質問コード(データベース内の質問テーブルの'タイトル'列)で変数を参照できます。これは、データをSPSS、R、またはSASにエクスポートするときにも使用される変数ラベルです。たとえば、名前、年齢、性別に関する質問がある場合、12345X13X22、12345X13X23’'、12345X13X24の代わりに、変数name、age、genderで呼び出すことができます。これにより、誰もが簡単にロジックを理解し検証することができ、グループや質問の数を把握しなくても質問をシャッフルすることができます。
重要: 先行するページや質問で発生する変数を参照するのが安全です。
さらに、式マネージャーを使用すると、多くの質問プロパティにアクセスできます。
構文 | 意味 | 例 | 例の実行結果 |
---|---|---|---|
Qcode | Qcode.codeの別名 | {implode(',',name,gender)} | 'Tom','M' |
Qcode.code | 質問で選択した回答のコード(出現条件を満たす場合。満たさない場合は空白)、またはコード化されていない質問のテキスト値 | {implode(',',name.code,gender.code)} | 'Tom','M' |
Qcode.NAOK | Qcodeと同じ - NAOKについての議論を参照 | {gender.NAOK} | 'M' |
Qcode.value | 質問の評価値(出現条件を満たす場合。満たさない場合は空白)、またはコード化されていない質問のテキスト値 | {gender.value} | '1' |
Qcode.valueNAOK | Qcode.valueと同じ - NAOKについての議論を参照 | {gender.valueNAOK} | '1' |
Qcode.shown | 質問の表示値 | {implode(',',name.shown,gender.shown)} | 'Tom','Male' |
Qcode.question | 質問のテキスト | {gender.question} | 'What is your gender?' |
Qcode.mandatory | 質問が必須かどうか(Y/N) | {gender.mandatory} | 'N' |
Qcode.qid | 内部で使用する質問番号(順番を示す連続番号ではない) | {gender.qid} | 337 |
Qcode.type | 質問タイプ | {gender.type} | 'G' |
Qcode.jsName | 質問の正しいjavascript名(このページで宣言されているかどうかにかかわらず) | {gender.jsName} | 'java1827X3X337' |
Qcode.gid | 内部で使用するグループ番号(順番を示す連続番号ではない) | {gender.gid} | 3 |
Qcode.qseq | 質問の連続番号(0から始まる) | {gender.qseq} | 5 |
Qcode.gseq | グループの連続番号(0から始まる) | {gender.gseq} | 1 |
Qcode.relevanceStatus | 質問が現在出現条件を満たすかどうか(0または1) | {gender.relevanceStatus} | 1 |
Qcode.relevance | 質問レベルの出現条件式 | {gender.relevance} | '!is_empty(name)' |
Qcode.grelevance | グループレベルの出現条件式 | {gender.grelevance} | 'num_children >= 5' |
Qcode.sgqa | この質問のSGQA値 | {gender.sgqa} | '1827X3X337' |
HTMLエディターの問題
HTMLエディターを使用すると、一部の文字がHTML実体に置き換えられます。
- & → &
- < → <
- > → >
HTMLエディターを使用する場合は、次のものを使用する必要があります。
- & に対しては and
- < に対してはlt
- <= に対してはle
- > に対してはgt
- >= に対してはge
式の中のHTML表現を消去することをお勧めします。 LimeSurvey HTMLエディターを使用する場合は、エディターの左上にある"ソース"ボタンをクリックして、式に関連しないすべての文字を削除します(例:
、
など)。
Qcode変数の命名
Qcodeを構成する方法(およびいくつかのプロパティにアクセスする方法)の質問タイプ別の詳細は次のとおりです。一般に、Qcodeは次のように構成されます。
QuestionCode . '_' . SubQuestionID . '_' . ScaleId
commentとotherの場合、対応する質問コードはそれぞれQuestionCode_comment、QuestionCode_otherです。
種類 | 説明 | コード | サブ質問 | 回答オプション | 尺度 | 回答コード | 回答表示 | 出現条件 |
---|---|---|---|---|---|---|---|---|
5 | 5点尺度ラジオボタン | Q1 | 1-5 | {Q1} | {Q1.shown} | {Q1==3} | ||
B | 配列(10点選択)ラジオボタン | Q2 | L1-L6 | 1-10 | {Q2_L2} | {Q2_L2.shown} | {Q2_L2==7} | |
A | 配列(5点選択)ラジオボタン | Q3 | 1-5 | 1-5 | {Q3_1} | {Q3_1.shown} | {Q3_1>=3} | |
1 | 配列(フレキシブルラベル)二元尺度 | Q4 | sq1-sq5 | 0:a1-a3 | 1:b1-b3 | {Q4_sq1_0} | {Q4_sq1_1.shown} | {Q4_sq1_1=='b2'} |
H | 配列(フレキシブル) - 列フォーマット | Q5 | 1-5 | s,m,t | {Q5_1} | {Q5_1.shown} | {Q5_1=='s'} | |
F | 配列(フレキシブル) - 行フォーマット | Q6 | F1-F5 | 1-5 | {Q6_F3} | {Q6_F3.shown} | {Q6_F3==4} | |
E | 配列(増加/同じ/減少)ラジオボタン | Q7 | 1-7 | I,S,D | {Q7_4} | {Q7_4.shown} | {Q7_4=='D'} | |
: | 配列(数値)1から10 | Q8 | ls1,todo,ls2 | min,max,avg | {Q8_ls1_max} | {Q8_ls2_avg.shown} | {Q8_ls2_min==7} | |
; | 配列(テキスト) | Q9 | hp,st,sw | 1st,2nd,3rd | {Q9_hp_3rd} | {Q9_hp_3rd.shown} | {Q9_hp_3rd=='Peter'} | |
C | 配列(はい/わからない/いいえ)ラジオボタン | Q10 | 1-5 | Y,N,U | {Q10_1} | {Q10_1.shown} | {Q10_3=='Y'} | |
X | テキスト表示 | Q11 | {Q11.shown} | |||||
D | 日付 | Q12 | {Q12} | {Q12.shown} | ||||
* | 式 | Q13 | {Q13} | {Q13.shown} | {Q13>5} | |||
~124~ | ファイルアップロード(アップロードファイル数を記録) | Q14 | {Q14} | {Q14>0} | ||||
G | 性別ドロップダウンリスト | Q15 | M,F | {Q15} | {Q15.shown} | {Q15=='M'} | ||
U | 非常に長いテキスト | Q16 | {Q16} | {Q16.shown} | {strlen(Q16)>100} | |||
I | 言語 | Q17 | {Q17} | {Q17.shown} | {Q17=='en'} | |||
! | リスト - ドロップダウン | Q18 | 1-5 | {Q18} | {Q18.shown} | {Q18==3} | ||
L | リスト ドロップダウン/ラジオボタンリスト | Q19 | A-Z | {Q19} | {Q19.shown} | {Q19=='X'} | ||
O | コメント付きリスト(ドロップダウン/ラジオボタンリスト + テキスト領域) | Q20 | A-F | {Q20},{Q20comment} | {Q20.shown} | {Q20=='B'} | ||
T | 長いテキスト | Q21 | {Q21} | {Q21.shown} | {strstr(Q21,'hello')>0} | |||
M | 複数選択チェックボックス | Q22 | A-F, other | {Q22_E}, {Q22_other} | {Q22_E.shown}, {Q22_other.shown} | {Q22_E=='Y'} | ||
P | コメント付き複数選択(チェックボックス + テキスト) | Q23 | A-F | {Q23_D}, {Q23_Dcomment} | {Q23_D.shown} | {!is_empty(Q23)} | ||
K | 数値入力(複数) | Q24 | self,mom,dad | {Q24_self} | {Q24_self.shown} | {Q24_self>30} | ||
Q | 複数の短いテキスト | Q25 | A-F | {Q25_B} | {Q25_B.shown} | {substr(Q25_B,1,1)=='Q'} | ||
N | 数値 | Q26 | {Q26} | {Q26.shown} | {Q26 > 30} | |||
R | 順位 | Q27 | 1-4 | {Q27_1} | {Q27_1.shown} | {Q27_1==3} | ||
S | 短いテキスト | Q28 | {Q28} | {Q28.shown} | {Q28=='mine'} | |||
Y | はい/いいえラジオボタン | Q29 | {Q29} | {Q29.shown} | {Q29=='Y'} |
NAOKの利用
NAOK --> "Not Applicable"(該当なし、NA)は問題ない(OK)
NAOKは、すべてまたは一部の変数が出現条件を満たさないということです。"Not Applicable"(該当なし、NA)は問題ない(OK)。
例: count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) は、Q1のサブ質問の一つがフィルターされている場合、常に空文字となります。このような質問で、チェックされたサブ質問の数をカウントするには、count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK)とします。サブ質問が隠されている場合、式マネージャーは空文字を返します。
NAOKがない場合、1つの質問または1つのサブ質問が非表示になっている場合、式マネージャーは常に空の文字列を返します(falseを返すのと同じです)。
.shownは常にNAOKの仕組み(非表示の時は空文字)を使っていますが、回答のコードが必要な場合は、質問コードの後に.NAOKを付加するとよいでしょう。それが必要で、内容を理解している場合は別です。
詳細は、入れ子条件の上書きの項にあります。
予約変数 "this"、"self"、"that"
回答されたサブ質問の数を数えたり、スコアを合計するなど、質問の全体を評価したい場合がよくあります。また、質問の特定の行や列(行や列の合計を取得してデータベースに格納するなど)を処理したい場合もあります。以下の予約変数により、そのプロセスを簡単に実現できます。
変数"This"
"this"変数は、"質問全体の検証式と"サブ質問の検証式"のオプションで排他的に使用されます(後者はGUIからは使えません)。該当の質問内の各セルの変数名に展開されます。したがって、各エントリが3より大きいかどうかを確認する場合は、"サブ質問の検証式"を(this > 3)に設定します。
変数"Self"
"self"と"that"変数はより強力で、式を処理する前に展開されるマクロとして機能します。"self"変数の構文は次のとおりです。
- self
- self.suffix
- self.sub-selector
- self.sub-selector.suffix
- suffixは、通常のqcode接尾辞のいずれかです(例: NAOK、value、shown)。
- サブセレクターは次のようなものがあります。
- comments - コメントとなるサブ質問のみ(コメント付き複数選択、コメント付きリストなど)
- nocomments - コメントのないサブ質問のみ
- sq_X - Xは行か列の識別子。パターンXと一致するサブ質問のみが選択されます。検索は完全なコード識別子で行われ、sq_XはnX、X、Xnといったサブ質問にマッチしますが(例えば、sq_1を使用する場合はサブ質問a1、1a、1、11または001がマッチします)。 二元スケール質問タイプではサブ質問はQCODE_SQCODE_1とQCODE_SQCODE_1になり、順位付け質問タイプではサブ質問コードがQCODE_1,QCODE_2 ....となります。
例:
- 質問に対して何らかの回答があったか? -> {count(self.NAOK)>0}
- この質問の評価点数は? -> {sum(self.value)}
行と列の合計を取得することもできます。列A-Eと行1-5の数字の配列があるとします。
- 総合計は? -> {sum(self.NAOK)}
- 列Bの合計は? -> {sum(self.sq_B.NAOK)}
- 行3の合計は? -> {sum(self.sq_3.NAOK)}
変数"That"
"that"は"self"に似ていますが、他の質問を参照することができます。構文は次のとおりです。
- that.qname
- that.qname.suffix
- that.qname.sub-selector
- that.qname.sub-selector.suffix
qnameは、サブ質問拡張がない質問の名前です。質問 'q1'を作成したら、それがqnameとなります。
例:
- 質問q1に対して何らかの回答があったか? -> {count(that.q1.NAOK)>0}
- q2の評価点数は? -> {sum(that.q2.NAOK)}
- q3の総合計は? -> {sum(that.q3.NAOK)}
- q4の列Cの合計は? -> {sum(that.q4.sq_C.NAOK)}
- q4の行2の合計は? -> {sum(that.q4.sq_2.NAOK)}
"self"と"that"変数は、出現条件、検証、文言調整の式で使用できます。
注意すべき点は、ロジックファイルの表示機能を使用すると、"self"と"that"を展開した値が表示されることです。これにより、生成される実際の式が表示され、その結果、変数が存在することを検証できるようになります。かなり長い式になるかもしれないので、混乱しているように見えるかもしれません。しかし、質問を編集すると、"self"や"that"を使っている元の式が表示されます。
- 式に使用される各変数を明示的に命名する場合。
- サブ質問を持たない変数を使用する場合(例:単一回答の質問)。そのような場合に、変数にプレフィックスとして"that"をつけると、予期しない結果が出る危険があります。
関数へのアクセス
式マネージャーでは、以下に示すように、数学関数、文字列関数、およびユーザー定義関数が利用できます。これらの関数にはPHPとJavaScriptに同等のものがあるので、サーバ側(PHP)とクライアント側(JavaScript)で同じように動作します。新しい機能を追加するのは簡単です。
実装済み関数
現在、以下の関数が利用可能です。
機能 | 意味 | 構文 |
---|---|---|
abs | 絶対値 | number abs(数値) |
acos | アークコサイン | number acos(数値) |
addslashes | 文字列をスラッシュで引用 | string addslashes(文字列) |
asin | アークサイン | number asin(数値) |
atan | アークタンジェント | number atan(数値) |
atan2 | 2変数のアークタンジェント | number atan2(number, 数値) |
ceil | 切り上げ | number ceil(数値) |
checkdate | グレゴリオ暦で有効な日付であれば真(1)を返す | bool checkdate(月,日,年) |
convert_value | 変換元リストにある数値を対応する変換先リストの数値に変換する | number convert_value(変換する数値, 一致フラグ, 変換元リスト, 変換先リスト) |
cos | コサイン | number cos(数値) |
count | リスト内で回答された(空白でない)質問の数 | number count(arg1, arg12, ..., argN) |
countif | 回答された質問のうち、比較値と等しいリスト内の回答の数 | number countif(比較値, arg1, arg2, ... argN) |
countifop | 回答された質問のうち、条件を満たすリスト内の回答の数(回答 演算子 比較値) | number countifop(演算子, 比較値, arg1, arg2, ... argN) |
date | 指定した、もしくは現在のローカルの日付/時刻を書式化する | string date(日付書式 [, 指定時刻=time()]) |
exp | eの累乗を計算する | number exp(数値) |
fixnum | 必要に応じてカンマで区切られた数字を表示する | string fixnum(数値) |
floor | 切り捨て | number floor(数値) |
gmdate | 指定した、もしくは現在のGMTの日付/時刻を書式化する | string gmdate(日付書式 [, 指定時刻=time()]) |
html_entity_decode | HTML エンティティを適切な文字に変換する (常にENT_QUOTES、UTF-8を使用) | string html_entity_decode(文字列) |
htmlentities | すべての変換可能な文字をHTMLエンティティに変換する(常にENT_QUOTES、UTF-8を使用) | string htmlentities(文字列) |
expr_mgr_htmlspecialchars | 特殊文字をHTMLエンティティに変換する(常にENT_QUOTESとUTF-8を使用) | string htmlspecialchars(文字列) |
expr_mgr_htmlspecialchars_decode | Convert special特殊な HTML エンティティを文字に戻す(常にENT_QUOTESとUTF-8を使用) | string htmlspecialchars_decode(文字列) |
idate | 指定した、もしくは現在のローカルな時刻/日付を整数として整形する | string idate(文字列 [, 指定時刻=time()]) |
if | Excelスタイルのif(条件,trueの時の結果,falseの時の結果) | if(条件,trueの時の結果,falseの時の結果) |
implode | 配列要素を文字列により連結する | string implode(区切り文字,arg1,arg2,...,argN) |
intval | 変数の整数としての値を取得する | int intval(数値 [, 基数=10]) |
is_empty | 変数が空であるかどうかを検査する | bool is_empty(変数) |
is_float | 変数の型が float かどうか調べる | bool is_float(変数) |
is_int | 変数が整数型かどうかを検査する | bool is_int(変数) |
is_nan | 値が数値でないかどうかを判定する | bool is_nan(変数) |
is_null | 変数が NULL かどうか調べる | bool is_null(変数) |
is_numeric | 変数が数字または数値形式の文字列であるかを調べる | bool is_numeric(変数) |
is_string | 変数の型が文字列かどうかを調べる | bool is_string(変数) |
join (New in 2.0 build 130129) | 要素を新しい文字列として結合する | join(arg1, arg2, ... argN) |
list | 空白でない値をコンマ区切りリストで返す | string list(arg1, arg2, ... argN) |
log | 自然対数(底が指定されている場合は底に対する対数) | number log(数値,底=e) |
ltrim | 文字列の最初から空白 (もしくはその他の文字) を取り除く | 文字列 ltrim(string [, 削除する文字のリスト]) |
max | 最大値を返す | number max(arg1, arg2, ... argN) |
min | 最小値を返す | number min(arg1, arg2, ... argN) |
mktime | 日付を Unix のタイムスタンプとして取得する(引数は省略可) | number mktime([時 [, 分 [, 秒 [, 月 [, 日 [, 年 ]]]]]]) |
modulo-function | モジュロ関数はまだサポートされていません。代わりにfloor()関数を使用します。 | floor(x/y)==(x/y) |
nl2br | 改行文字の前にHTMLの改行タグを挿入する | string nl2br(文字列) |
number_format | 数字を千位毎にグループ化してフォーマットする | string number_format(数値) |
pi | 円周率 | number pi() |
pow | 指数表現 | number pow(基数, 指数) |
quoted_printable_decode | quoted-printable 文字列を 8 ビット文字列に変換する | string quoted_printable_decode(文字列) |
quoted_printable_encode | 8 ビット文字列を quoted-printable 文字列に変換する | string quoted_printable_encode(文字列) |
quotemeta | メタ文字をクォートする | string quotemeta(文字列) |
rand | 乱数を生成する(例) | int rand() OR int rand(最小値, 最大値) |
regexMatch | 文字列を正規表現で比較する | bool regexMatch(パターン,文字列) |
round | 数値を任意の精度に丸める | number round(値 [, 丸める桁数]) |
rtrim | 文字列の最後から空白(またはその他の文字)を取り除く | string rtrim(文字列 [, 削除する文字のリスト]) |
sin | サイン | number sin(arg) |
sprintf | フォーマットされた文字列を返す | string sprintf(フォーマット, arg1, arg2, ... argN) |
sqrt | 平方根 | number sqrt(arg) |
stddev | 数値のリストのサンプル標準偏差を計算する | number stddev(arg1, arg2, ... argN) |
str_pad | 文字列を固定長になるまで他の文字列で埋める | string str_pad(入力文字列, 文字列の長さ [, 埋める文字列]) |
str_repeat | 文字列を反復する | string str_repeat(入力文字列, 繰り返し回数) |
str_replace | 検索文字列に一致したすべての文字列を置換する | string str_replace(検索文字列, 置き換える値, 対象の文字列) |
strcasecmp | 大文字小文字を区別しないバイナリセーフな文字列比較を行う | int strcasecmp(文字列1, 文字列2) |
strcmp | バイナリセーフな文字列比較を行う | int strcmp(文字列1, 文字列2) |
strip_tags | 文字列から HTML および PHP タグを取り除く | string strip_tags(文字列, 取り除かないタグ) |
stripos | 大文字小文字を区別せずに文字列が最初に現れる位置を探す(0から始まり、現れなければfalse) | int stripos(対象文字列, 検索文字列 [, 検索開始位置=0]) |
stripslashes | クォートされた文字列のクォート部分を取り除く | string stripslashes(文字列) |
stristr | 大文字小文字を区別しないstrstr | string stristr(対象文字列, 検索文字列 [, 検索文字列の前まで=false]) |
strlen | 文字列の長さを得る | int strlen(文字列) |
strpos | 文字列内の部分文字列が最初に現れる場所を見つける(0から始まり、現れなければfalse) | int strpos(対象文字列, 検索文字列 [ 検索開始位置=0]) |
strrev | 文字列を逆順にする | string strrev(文字列) |
strstr | 文字列が最初に現れる位置を見つける | string strstr(対象文字列, 検索文字列[, 検索文字列の前まで=false]) |
strtolower | 文字列を小文字にする | string strtolower(文字列) |
strtotime | P英文形式の日付をUnixタイムスタンプに変換する | int strtotime(文字列) |
strtoupper | 文字列を大文字にする | string strtoupper(文字列) |
substr | unicode文字列の一部分を返す | string substr(文字列, 開始位置 [, 長さ]) |
sum | 配列中の値の合計 | number sum(arg1, arg2, ... argN) |
sumifop | 回答された質問のうち、条件を満たすリスト内の回答の合計(回答 演算子 比較値) | number sumifop(演算子, 値, arg1, arg2, ... argN) |
tan | タンジェント | number tan(arg) |
time | 現在の Unix タイムスタンプを返す | number time() |
trim | 文字列の先頭および最後から空白(またはその他の文字)を取り除く | string trim(文字列 [, 削除する文字のリスト]) |
ucwords | 文字列の各単語の最初の文字を大文字にする | string ucwords(文字列) |
unique | 空白以外の回答のすべてが一意である場合にtrueを返す | boolean unique(arg1, ..., argN) |
式マネージャーとローカル変数
ページのJavaScriptを適切に構築するため、式マネージャーはページに設定されている変数とJavaScript IDが何であるかを知る必要があります(例: document.getElementById(x))。また、他のページにどの変数が設定されているかも知る必要があります(これにより、必要な<input type='hidden' value='x'>フィールドが存在しているか確認できます)。
条件の入れ子
いずれかの変数がfalseである場合、式全体はfalseになります。たとえば、次の表では、N/Aは変数の1つがtrueでないことを意味します。
演算子 | 例 | a | b | 結果 |
---|---|---|---|---|
+ (単項演算子) | +a | N/A | false | |
- (単項演算子) | -a | N/A | false | |
! | !a | N/A | false | |
== (またはeq) | a == b | N/A | 5 | false |
== (またはeq) | a == b | N/A | 0 | false |
== (またはeq) | a == b | N/A | N/A | false |
!= (またはne) | a != b | N/A | 5 | false |
!= (またはne) | a != b | N/A | N/A | false |
!= (またはne) | a != b | N/A | 0 | false |
> (またはgt) | a > b | N/A | 5 | false |
>= (またはge) | a >= b | N/A | 5 | false |
< (またはlt) | a < b | N/A | 5 | false |
<= (またはle) | a <= b | N/A | 5 | false |
and | a and b | N/A | 5 | false |
and | a and b | N/A | N/A | false |
or | a or b | N/A | N/A | false |
or | a or b | N/A | 5 | false |
+ | a + b | N/A | 5 | false |
* | a * b | N/A | 5 | false |
/ | a / b | 5 | N/A | false |
() | (a) | N/A | false | |
(式) | (a && b) | N/A | 5 | false |
(式) 演算子 (式) | (b + b) > (a && b) | N/A | 5 | false |
関数 | sum(a,b,b) | N/A | 5 | false |
関数 | max(a,b) | N/A | 5 | false |
関数 | min(a,b) | N/A | 5 | false |
関数 | implode(', ',a,b,a,b) | N/A | 5 | false |
関数 | if(a,a,b) | N/A | 5 | false |
関数 | is_empty(a) | N/A | false | |
関数 | is_empty(a) | 0 (or blank) | true | |
関数 | !is_empty(a) | N/A | false |
入れ子条件の上書き
出現条件を満たした回答の合計を表示したいとします。式 {sum(q1,q2,q3,...,qN)}を使おうとするでしょう。しかし、これは内部的にLEMif(LEManyNA("q1","q2","q3",...,"qN"),"",sum(LEMval("q1"),LEMval("q2"),LEMval("q3"),...,LEMval("qN")))に変換されます。これにより、値q1〜qNのいずれかが出現条件を満たさない場合、式は常にfalseを返します。この場合、sum()はすべての質問が出現して回答されない限り"0"となります。
この問題を回避するために、各変数には".NAOK"という接尾辞(「Not Applicable」はOK)を追加することができます。このような場合、次のような現象が発生します。変数q1.NAOKがあるとします。
- q1はLEManyNA()節には追加されません
- LEMval('q1')は回答が出現条件を満たしているかを確認し、そうでない場合は""を返します(出現条件を満たさない回答は無視されますが、式全体を無効にしません)。
したがって、合計を求める方法は、次の式となります。sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK)
.NAOK接尾辞を使用することで、いくつかの可能な経路を経て、後に共通の経路に収束するアンケートを設計することができます。例えば、回答者が通常の範囲から外れた回答をしたとします。アンケート実施者は、有効な結果を得られない可能性があることを回答者に警告し、アンケートを継続するかどうかを尋ねることができます。彼らが"はい"と答えると、残りの質問が表示されます。 "残りの質問"の条件は、回答が正常範囲内で回答されたか、または正常範囲外で回答した場合にのみ表示される質問に対して"はい"と回答したかどうかをチェックします。
式マネージャーはどのように条件付き文言調整を実現するか?
ここでは、カスタマイズ(質問タイプ'expr'は式を意味します)の例を示します。
質問コード | 出現条件 | 質問タイプ | 質問 |
---|---|---|---|
name | 1 | text | 名前は何ですか。 |
age | 1 | text | 何歳ですか。 |
badage | !is_empty(age) | expr | {(age<16) or (age>80)} |
agestop | badage | message | すみません、{name}さん。あなたは{if( (age<16),'若い',if( (age>80),'高齢','中間の年齢') ) }です。 |
kids | !badage | yesno | 子供はいますか。 |
parents | 1 | expr | {!badage && kids=='Y'} |
numKids | parents | text | 子供は何人いますか。 |
kid1 | parents && numKids >= 1 | text | 一人目の子供は何歳ですか。 |
kid2 | parents && numKids >= 2 | text | 二人目の子供は何歳ですか。 |
kid3 | parents && numKids >= 3 | text | 三人目の子供は何歳ですか。 |
kid4 | parents && numKids >= 4 | text | 四人目の子供は何歳ですか。 |
kid5 | parents && numKids >= 5 | text | 五人目の子供は何歳ですか。 |
sumage | 1 | expr | {sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)} |
report | parents | text | {name}さん、あなたの年齢は{age}歳で、{numKids}人の子供がいます。上から{min(numKids,5)}人の子供の年齢の合計は{sumage}です。 |
このアンケート例をダウンロードするには、次のリンクをクリックしてください。子供の数のアンケート例
これらの質問はすべて1つのページ(たとえば同じグループ)に入れることができ、出現条件に合致する質問のみが表示されます。さらに、子供の年齢を入力すると、最後の質問のsum()式がページ上で動的に更新されます。
式マネージャーは、各式を名前付き<span>要素で囲むことでこの機能を提供します。値が変更されるたびに、その<span>要素に表示される式を再計算し、再表示します。そのようなカスタマイズされた式が同じページに数十、または数百もあっても、ページは一度の画面更新ですべて再表示されます。
構文ハイライト
式の入力と検証を支援するために、EMでは以下のような構文強調表示機能を提供しています。
構文ハイライトの種類と意味
色 | 例 | 意味 | ツールチップ | コメント |
---|---|---|---|---|
黄褐色の背景 | 例 | 式全体 | なし | 式として認識される中括弧内のもの(先頭または末尾に空白がない)は、周囲のテキストと区別するために黄褐色の背景で色分けされます。 |
太字の赤色テキスト | 例 | エラー | エラーに関する説明 | 不明な変数または関数のエラーである可能性があります。アンケートは正常に動作せず、式に依存する質問は回答者には表示されません。 |
青色のテキスト | 例 | 関数名 | 意味と許容される構文 | これは、関数の名前、または関数と思われるもの(開く括弧が続くため)を示します。太字の青いテキストで表示されます。ツールチップには、その関数の意味と許容される構文が表示されます。 |
灰色のテキスト | 例 | 文字列 | なし | 一重引用符と二重引用符で囲まれた文字列は灰色のテキストで表示されます。 |
水色のテキスト | 例 | 同一ページでセットされた変数 | [名前またはSGQAコード]: 質問; 値; それぞれの値に対するコードを示すanswerList | 現在編集している質問と同じページで設定された変数は水色のテキストで表示されます(javascriptで更新できます)。ツールチップには、名前(INSERTANS:xxxを使用した場合)またはそのSGQAコード(新しい命名システムを使用した場合)、実際の質問、および現在の値(設定されていない場合は空白)が表示されます。列挙された値セットからの選択を期待する質問タイプの場合、コードの表示値へのマッピングが示されます。 |
緑色のテキスト | 例 | 先行するページでセットされた変数 | [名前またはSGQAコード]: 質問; 値; それぞれの値に対するコードを示すanswerList | 先行するページで設定された変数は太字の緑色のテキストで表示されます。ツールチップには、名前(INSERTANS:xxxを使用した場合)またはそのSGQAコード(新しい命名システムを使用した場合)、実際の質問、および現在の値(設定されていない場合は空白)が表示されます。列挙された値セットからの選択を期待する質問タイプの場合、コードの表示値へのマッピングが示されます。 |
太字のピンク色のテキスト | 例 | 後続のページでセットされる変数通常、アンケート開始時は空ですが、質問番号にしたり、前に戻ることができます。 | [名前またはSGQAコード]: 質問; 値; それぞれの値に対するコードを示すanswerList | 後続のページで設定される変数は太字のピンク色のテキストで表示されます。ツールチップには、名前(INSERTANS:xxxを使用した場合)またはそのSGQAコード(新しい命名システムを使用した場合)、実際の質問、および現在の値(設定されていない場合は空白)が表示されます。列挙された値セットからの選択を期待する質問タイプの場合、コードの表示値へのマッピングが示されます。 |
太字の黄褐色のテキスト | 例 | LimeSurveyの置換値 | 値 | LimeSurveyの置換文字列({TOKEN:xxx}、{PRIVACY_MESSAGE}など)は、太字の黄褐色のテキストで表示されます。 |
赤色のテキスト | 例 | 代入演算子(=) | 警告メッセージ | 代入演算子(=)を使用している場合、演算子は赤色のテキストで表示されます。aにbを代入するのではなく、aとbが等しいかをチェックしようとする場合に誤って代入することのないようにするためのものです。 |
通常の黒色のテキスト | 例 | その他の記号 | なし | 式の中のその他の記号は通常の黒色のテキストで表示されます。 |
赤枠で囲まれたテキスト | 太い赤枠で囲まれたエラー | 構文エラー | エラーの説明 | 構文エラーは赤色のボックス内に示されています。ツールチップは、エラーを示します。例としては、括弧の不一致、未定義関数の使用、関数に渡す引数の数の誤り、不完全に構造化された式(変数の間の演算子欠落など)、読み取り専用の変数への値の代入、非変数への値の代入、またはサポートされていない構文の使用などです。構文エラー検知システムは、複数のエラーがある場合でも、式の中のエラーを1つだけ報告します。 |