式マネージャー
From LimeSurvey Manual
クイックスタート
概要
アンケートをカスタマイズするには、通常、次のことを指定する方法が必要です :
- ナビゲーション・分岐 - アンケート参加者の回答によって質問の順番を変更できるようにします。
- テーラーリング・パイピング - 質問の表現方法(先行する回答の参照、調査の課題による参加者数や性別に合わせた語句の変化など)、(評価スコアやカスタマイズしたアドバイスなど)カスタマイズしたレポートを生成する方法
- 検証 - 最小値と最大値、または入力パターンの一致など、回答が特定の基準を満たしていることを確認します。
式マネージャー(EM)では、各機能のロジックを指定する直感的な方法が提供されています。関数を呼び出しているものであっても、標準的な数式として書くことができるものは、ほとんどが有効な式になります。EMは現在、70の関数が利用でき、より多くの機能をサポートするよう、簡単に拡張することができます。また、(SGQA名ではなく)人間が読める変数名を使用して変数にアクセスすることもできます。
以下のセクションで、式マネージャーを使う主な場面を紹介します。
関連(ナビゲーション制御/分岐)
アンケートによっては、"Gotoロジック"を使用して、質問1でCと答えた場合は質問5にジャンプしたりします。このアプローチは、検証が難しく、質問を並べ替えるときにロジックが壊れてしまうため、大きな制約があります。EMでは、質問が有効かどうかを決めるすべての条件を、ブール値の出現条件式を使用して指定します。質問が出現条件を満たす場合は質問が表示され、それ以外の場合は「適用外」となり、データベースにはNULL値が格納されます。これは条件エディターで実行できるものと似ていますが、EMではより複雑で強力な条件を簡単に指定でき、さらにSGQA名ではなく変数名を使用できます。
この画像では、アンケートの関連性ロジックを確認する例を示しており、ここでは、体格指数(BMI)を計算します。関連式は、変数名の直後の角カッコで示されています(緑色)。体重、体重の単位、身長、身長の単位の関連式はすべて1です。つまり、これらの項目は常に質問されます。しかし、BMIの関連式は、 {!is_empty(height) and !is_empty(weight)}となっており、BMIは、身長と体重の両方を入力しないと計算しないようになっています(ゼロで割るリスクも避けています)。また、「Report」の質問は、主たる4つの質問(身長、身長の単位、体重、体重の単位)すべてに回答した場合にのみ表示されます。
関連は以下の場所て表示・編集ができます。
質問レベルの関連の閲覧/編集
この式は、体格指数(BMI)を計算します。最初に身長と体重を入力した場合のみ対象となります。
こちらがBMI質問の編集画面です。
関連式を入力するときは中括弧を使用しないようにしてください。
グループレベルの関連の閲覧/編集
これは、国勢調査の調査例です。最初のページで、回答者に同居人数を尋ね、結果が"cohabs"変数に格納されています。このページは、複数の同居人がいる場合(つまり、このページは同居している2番目の人物に関するもの)で、回答者と「人物1」の関係(p1_rel)を指定した場合にのみ表示されます。
ご覧のように、グループには質問レベルの関連基準もあり、こうした質問は、先行する質問に回答したときにのみ表示されます(例:{!is_empty(p1_sex)})。EMは、グループと質問レベルの関連を結合します。グループ内の質問は、グループ全体が関連する場合にのみ尋ねられます。次に、関連するグループ内の質問のサブセットのみが尋ねられます。
その質問のグループレベルの関連を編集する画面は次のとおりです。
関連式を入力するときは中括弧を使用しないようにしてください。
カスタマイズ/パイプ
EMを使用すると、単純な、または複雑な条件付きの質問を簡単に作成できます。例えば、"[製品]を購入したと回答しました。よかった点は何ですか?"のように、単純な「置き換え」が必要な場合があります。また、"[Mr./Mrs.] [LastName]、アンケートを完了してもよろしいですか?"のように、条件付きの置き換えが必要な場合もあります。この場合、回答者の性別に基づいてMr.かMrs.を使用します。また、例えば、数学的計算に基づいてさらに複雑な置き換えが必要になることもあります。EMは、このような場合のカスタマイズ/パイプをサポートしています。
条件式
体格指数の例では、身長と体重の入力単位がメートル法であってもメートル法でなくても、BMIが計算できることを示しています。
ここで、weight_kgは、{if(weight_units == 'kg', weight, weight * .453592)}となっています。このif()関数では、キログラムで体重が入力されていた場合は入力値をそのまま採用し、それ以外の場合は入力値(単位はポンド)に0.453592をかけてキログラムに変換します。同様に、変数height_mは、身長がインチ単位で入力されていてもメートル単位の身長を計算するようになっています。
BMIは、{weight_kg / (height_m * height_m)}という式で計算されます。
最後に、回答者に対し、条件付きでカスタマイズして入力した内容を表示します。("身長2メートル、体重70キロと回答しました。")
上の画像ではわかりにくくなっていますが、weight_statusは入れ子のif()ステートメントを使用し、その人物がやせているのか肥満なのかを分類します。その式をロジックビューで見ることができます。
この質問の編集ウィンドウから、次の2つのことがわかります。
- 中括弧で表現を囲む必要があります
- 式は、例えばこの例のように、ネストされた条件付きロジックを読みやすくするため、複数の行にまたがって記述することができます。
カスタマイズされた質問・解答・レポート
この例は、BMIレポートを示しています。
同じ質問の編集ウィンドウです。
ご覧のように、中括弧で囲われた部分は式として扱われるので、前の画像では構文ハイライト(色分け)されています。タイプミスや定義されていない変数名や関数のような誤字があった場合、EMはこのようなエラーを表示します。例えば、height_unitは未定義の変数名(実際はheight_units)、rnd()は未定義関数(正しくはround())です。いずれの場合も、エラーを赤い枠で囲み、見つけて修正しやすくなっています。
また、入力された値の一覧やカスタマイズされたアドバイスなど、複雑なレポートをすばやく作成できます。
質問のどの部分がフリーテキストで、どの部分が式マネージャーで解析する必要があるかをLimeSurveyが判断するため、すべての式をCurly Bracesで囲む必要があります。
検証
EMは、高度な質問オプションがどのように機能するかを制御します。回答の数、個々の入力値や合計の最小値/最大値を制限したり、入力された値が指定された文字列パターンと一致していることを確認したりします。いつものように高度な質問オプションの入力を行いますが、これらのフィールドの値はどれも式と見なされるため、他の質問と複雑な条件で組み合わせ、最小値/最大値基準を設定することができます。
これらのすべてのケースでは、高度な質問オプションは常に式と見なされるため、中括弧を使用することはありません。
サンプルアンケートページには、検証のために式を使用した実例がたくさんあります。
はじめに
LimeSurveyでは、新しいExpression Manager(EM)モジュールを使用して、より複雑な分岐、評価、検証、およびカスタマイズがサポートされています。LimeSurveyがサーバー内で行う置換、条件、評価の管理方法を置き換えることができます。また、ランタイムデータベースの読み込みのほとんどが不要になるため、処理速度が大幅に向上します。EMはDr. Thomas White(TMSWhite)が開発しました。
このwikiページは、Expression Managerの構文と機能のリファレンスです。
主な定義
- 式: 中括弧で囲まれたもの
- 開く中括弧の直後または閉じる中括弧の直前に空白がない
- 式の内容はEMが評価するため、数式、関数、複雑な文字列と日付処理を含めることができます。
- カスタマイズ: "パイピング"とも呼ばれますが、これは条件付きでテキストを変更するプロセスです。
- すべての'置換フィールド'、参加者データ、回答データにアクセスできます。
- 質問、回答、およびそのプロパティにも簡単にアクセスできます。
- 出現条件式: 質問を表示するかを制御する新しい質問属性
- 出現条件式がある場合、その出現条件が真と評価された場合にのみ質問が表示されます。
- 内部では、すべてのarray_filterコマンドとarray_filter_excludeコマンドがサブ質問レベルの出現条件になります。
- 式質問タイプ: データベースに計算やレポートを保存する新しい質問タイプ
- これはテキストを表示する質問のようなものですが、"この質問をいつも隠す"を設定しても、その内容はデータベースに保存されます。
- 質問コード: EMでの使用が推奨される変数名
- これは質問の目的を示すわかりやすい名前にすることができ、複雑なロジックを読みやすくなります。
- 質問コードは数字で始めることはできないので、質問番号を質問コードにするときは、単に"q1"、"q1a"、"g1q2"のようにしてください。
- 現在のところ、データをSPSSまたはRにエクスポートすると、これが変数名になります。したがって、統計分析を行う場合は、ユニークにしなければなりません。
EMを使わなければならないのか?
短い答えは「いいえ」ですが、「はい」でもあります。
EMは、既存のアンケートと完全に後方互換性があります。LimeSurveyバージョン1.91+以前で使用されていたスタイルの条件と評価は、引き続き使うことができます。
ただし、EMでは、LimeSurveyが内部的にどのように条件を処理するかについて完全に置き換えられています。条件エディタを使用して条件を作成したり管理したりすることはできますが、LimeSurvey 1.92ではそれらは同等の関連式に変換されます。アップグレードの一環として、LimeSurvey 1.92では既存のすべての条件が関連式に自動変換されます。
これにより、新旧のいいとこ取りができます。これまで通りLimeSurveyを使い続けることもできますが、同等の関連式が表示されるので、関連式に徐々に移行することもできます。
条件と関連の両方を使えるか?
はい。質問によって条件エディターを使用することも、出現条件エディターを使用することもできます。質問を保存すると、条件は自動的に出現条件に変換されます。
条件エディターを使用している場合、手動で入力した関連式は上書きされます。したがって、すでに条件があって、関連を手動で編集したい場合は、まずその質問の条件を削除してください。具体的には、生成された関連式をテキストエディターにコピーし、条件メニューからその質問の条件をすべて削除し(関連も削除)、質問を編集し、テキストエディタからその質問の関連フィールドに貼り付け、質問を保存します。生成された関連式を削除せずに条件を削除したいというニーズが場合、一括変換プロセスの追加開発を検討します。
条件と関連のどちらを選ぶべきか?
各々の長所と短所のリストを以下に示します。
スタイル | 長所 | 短所 |
---|---|---|
条件 | 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がない(代わりに構文ハイライト機能を使用) 2. まだ新しい機能で、サポートチームがまだEMをマスターしていない |
LimeSurvey 1.91+の仕組みに満足していれば、変える理由はありません。
EMのメリットは他にあるか?
EMを使うべき理由がいくつかあります。
- 計算 - 任意の計算式を作成することができます。
- 一般的な数学的演算子と関数のすべてを利用できます。
- 70以上の数学、日付、および文字列処理関数を利用できます。
- 必要な場合、新しい関数を簡単に追加できます。
- データベースへの計算の保存
- シンプル/複雑な式や評価点を計算し、JavaScriptを要せずにデータベースに保存できるようになりました。
- 式の質問タイプを使用してます。
- 評価
- 以前は一部のみサポートされていましたが、すべての質問タイプからの評価やスケールの作成が可能になりました。
- カスタマイズを使用すると、同じページであっても、必要な場所で、途中または合計の評価点数を表示できます。
- 評価点数に基づいて生成されたレポートをより細かくコントロールできます。
- JavaScriptを使用せずに評価点数をデータベースに保存することができます。
- 評価点数は、JavaScriptやCSSを使わずに非表示にできます。
- 代替フィールド
- {INSERTANS:SGQA}を使う代わりに、質問コードを使用すると、読みやすく、検証しやすくできます。
- これにより、すべてを動作させるため質問を編集してSGQAコードを変更する必要もなくなります。
- カスタマイズ - 他の値に基づいてテキストをカスタマイズして表示できます。#*適切な敬称を使用する(例: "Hello [Mr./Mrs.] Smith")。
- 単数/複数に基づき文法的に正しい文章を出力する(例: "You have 1 child"と"You have 2 children")
- 性や数に基づいて動詞や名詞を変化させる
- 新しい変数の属性 - 次の項目にアクセスして調整できます。
- (接尾辞なし) - qcode.codeの別名
- .code - 質問が表示された場合は選択された回答コード(それ以外の場合は空白)、またはテキスト値(コード化されていない質問の場合)
- .NAOK - .codeと同じですが、非表示となる場合であっても計算やリストに含めることができます。
- .value - 質問が表示対象となる場合はその質問の評価値(それ以外の場合は空白)、またはテキスト値(コード化されていない質問の場合)
- .valueNAOK - .valueと同じですが、非表示となる場合であっても計算やリストに含めることができます。
- .shown - ユーザーに表示される回答(これは{INSERTANS:xxx}の機能です)
- .qid - 質問ID
- .gid - グループID
- .sgqa - 質問のSGQA値
- .jsName - (このページで定義されているかどうかに関係なく)質問に対する正しいjavascript変数名
- .qseq - 質問の順番(0から開始)
- .gseq - グループの順番(0から開始)
- .mandatory - 質問が必須かどうか(Y/N)
- .question - 質問のテキスト
- .relevance - 質問の関連式
- .grelevance - グループの関連式
- .relevanceStatus - 質問が表示条件を満たしているかどうか(1/0)
- .type - 質問タイプ(1文字のコード)
- ページ内の動的変更
- すべての関連、計算、およびカスタマイズはページ内で動的に機能するため、値の変更によりページが即座に更新されます。
- したがって、関連の評価結果に基づいて、質問が動的に表示/非表示になります。
- また、ページ内の回答に基づいて質問も動的に調整されるため、合計値、カスタマイズされた文、カスタマイズされたレポートをみることができます。
- 新しいデータ入力画面
- 現在のデータ入力システムを使用するだけでなく、単ページアンケートでも使用することもできます。
- ページ内の関連とカスタマイズがサポートされており、データ入力担当者はタブキーで入力を進め、関連する回答を入力するだけで済みます。
- この特徴は、データ入力者がカスタマイズによる動的変化を確認する必要がある場合に重要です。
- ほとんどのカスタムJavaScriptの必要性を排除
- EMは、複雑な計算、点数づけ、カスタマイズ、および条件付きロジックを容易にサポートします。
- JavaScript(カスタムレイアウトや条件付きの質問サブ要素など)を必要とするものもありますが、JavaScriptによって、EM関数を使用してSGQAの代わりにQcodeで質問にアクセスし、上記の質問属性にアクセスすることができます。
式マネージャーのその他の新機能
条件エディターを引き続き使用するか、または関連式を手動で作成するかにかかわらず、次のような利点があります。
- より複雑な検証基準を作成することができます。
- すべての高度な質問属性(max_answers、min_num_value_n、max_num_valueなど)は式を使用できます。したがって、最小値・最大値の条件は、同じページの先行する質問の回答に基づいて簡単に調整できます。
- EMは正規表現ベースの検証をすべて処理するので、pregと式ベースの質問属性を強固に組み合わせることができます。
- 質問とグループの並べ替え(または削除)が容易にできます。
- バージョン1.92より前のバージョンでは、並べ替えによって条件が成立しなくなる可能性があると認識された場合、質問やグループの並べ替えはできませんでした。同様に、ある質問に依存する質問がある場合は、その質問を削除できませんでした。
- EMの構文強調表示により、これから宣言して使おうとしている質問を確認し、検証することが簡単にできです。したがって、いつでも質問やグループを並べ替えたり、削除したりすることができます。EMは潜在的なエラーを表示するためにすべての構文強調表示を更新します。
- このようなレビューに役立つように、質問並べ替えの表示が強化されました。質問の関連式とカスタマイズが表示されるので、変数がピンク(宣言する前に使用されていることを意味します)になったかどうかをすぐに確認できます。
- 質問やグループのナビゲーション番号は常に利用可能で正確です。
- バージョン1.92以前は、複雑な条件があった場合、ナビゲーション番号は利用できませんでした。
- EMでは、正確であることを保証されています。
- 前の質問に戻り、答えを変えてから、後ろにジャンプする(または送信する)こともできます。
- 前進すると、EMは関係するすべての質問/グループを再検証します。
- 表示条件に該当しなくなる質問があれば、データは内部で一貫性を保つためデータベースにNULLが格納されます。
- 質問が表示条件に該当したり、新たに必須条件または検証ルールに適合しなくなった場合、EMはそのページで停止し、ユーザーが最終ページに飛ぶ前にそれらの質問に答えなければならないようにします。
- 条件から関連への自動変換
- データベースをアップグレードすると、条件を持つ既存のすべてのアンケートに関連式が生成されます。
- アンケートをインポートするたびに、関連式が必要に応じて作成されます。
- 条件を追加、削除、または変更すると、EMは適切な関連式を生成します。
- 便利な構文強調表示
- SGQAコードを入力した場合であっても、EMが関連式を表示するときは、Qcodeが表示されます。読みやすくするためです。
- すべての変数は、現在の質問の前後(または現在のグループの前後)に宣言されたかどうかを示すために色分けされています。これにより、変数を宣言する前に、関連(array_filterを含む)、カスタマイズ、検証式で使用する変数を使うケースをすばやく検出して修正できます。
- 色付けされた変数の上にマウスを移動すると、その質問に関する追加情報が表示されます。これには、グループ番号、質問番号、Qcode、質問のテキスト、利用可能な回答の選択肢(該当する質問タイプの場合)が含まれます。
- 回答の選択肢のリストは、次のような構文を使用します: 'answers':{key:val, ... }.
- keyは'scale~code'という構文となります。scaleは回答の尺度(二元スケールなど)、codeは回答コードです。
- valは'value~shown'という構文となります。valueは評価値(評価を使う場合。その他の場合はコード)、shownは表示される値です(Qcode.shownなど)。
- つまり、多くの場合、アンケートで評価モードを使わずに計算を使用できます。ユニークで、10進数でなく、負の数でない回答オプションを列挙する場合は、Qcode.code値の計算を行うことができます。
- アンケートロジックとコンテンツ全体の簡単なレビュー
- 新しいアンケートロジック表示機能があり、アンケート(またはグループ、質問)に関するすべての情報を1ページに表示できます。
- 選択したスコープ(アンケート、グループ、質問)のグループ、質問、サブ質問、回答レベルの詳細を表示します。
- また、関連、サブ質問レベルの関連(array_filterとarray_filter_exclude)、生成された検証式(pregと合計の最小値・最大値、値の数などの検証ルール)、およびすべての空白以外の質問属性も表示されます。
- すべて構文強調表示されているため、潜在的な構文エラー(括弧の不一致、未宣言の変数使用など)を発見できます。
- 構文強調表示により、アンケートのナビゲーションと編集が迅速にできるようになります。
- 変数名をクリックすると、その質問を示すブラウザウィンドウ(またはタブ)が開き、編集することができます。
- グループ名をクリックすると、グループの並べ替えビューを表示するブラウザウィンドウ(またはタブ)が開き、簡単に質問を移動できます。
- すべての質問属性も構文強調表示されています。これにより、高度な質問オプション内で式を設定したり表示したりすることができます(式の最大値/最小値/合計など)
- EMの製作者は、似たようなビューを使い、疫学者と治験審査委員会が高度に分岐する、何千もの質問があるアンケートを検証し、認可できるよう協力しました。
始めてみる
式マネージャーを始める最善の方法は以下のとおりです。
- http://www.limesurvey.org/en/downloadからLimeSurveyの最新の安定版をインストールしてください。
- サンプルアンケートをインポートして確認します。
- 使用例と使用法やステップバイステップの例を読んでください。
- EMに関するドキュメント(このページ)を読んでください。
- ビルトインのEMテスト環境を試してみてください。
- それぞれのアンケートのツールの下にあるEMオプションを選択します。
- 使用可能な関数として、70以上の関数と構文を表示します。
- 分離された式の単体テスト
- すべてのEM関数と演算子、PHPとJavaScriptの結果の使用例を表示します。
- PHPとJavaScriptのバージョンで異なる結果を生成する関数はほとんどありません。このページの内容を踏まえ、EMロジックを適切に計画することができます。
式マネージャーでは、どの機能が拡張/置換されたのか?(LimeSurvey 1.91から)
条件 → 関連
どの質問が表示されるかを制御する条件。一般的な構文は、111X2X3 == "Y"'のようなSGQA 演算子 値でした。条件はANDまたはORを組み合わせることができますが、ANDとORを混在させることは困難でした。条件自体は独立したテーブルに保存され、LimeSurveyのコードの大部分は条件の管理に費やされていました。膨大なデータベースアクセスのため、多数の条件を処理すると、パフォーマンス上の深刻な問題が発生する可能性がありました。さらに、条件が質問やグループに一旦割り当てられると、それらを並べ替えたり削除したりすることはできませんでした。
評価 → 式と細かいカスタマイズ
評価機能により、一連の質問から評価値を算出することができます。ただし、表示中のページ内で動的に変更することはできず、またその値はデータベースに保存されませんでした。
置換 → 細かいカスタマイズ
ユーザーは、先行する回答に基づいてメッセージや質問をカスタマイズできます。たとえば、{TOKEN:FIRSTNAME}さん、あなたは{INSERTANS:111X3X4}が好きなスポーツだと回答しましたのような質問が可能です。しかし、条件付きのカスタマイズ(性別に応じて"Mr."や"Mrs."をつけるなど)や、動詞や名詞を変化させたりすることはJavaScriptなしにはできませんでした。質問をカスタマイズするようなアンケートを実装することはできましたが、すべての組み合わせに対する個別の質問が必要であり、表示する質問を決定する複雑な条件が必要でした。
検証
質問は、正規表現や最小値/最大値で検証するか、SGQAの回答を最小値または最大値として使用することができました。ただし、JavaScriptなしで他の変数の計算に基づいて検証することはできませんでした。
式
式はJavaScriptなしでは実現できませんでした。
式の質問タイプ
JavaScriptを使用せずに式をデータベースに保存すること(評価の最終スコアなど)はできませんでした。
式マネージャーはどのように機能を拡張するのか?
式マネージャーは、カスタムJavaScriptを必要とする複雑な機能をより簡単に実現できるLimeSurveyの新しいコアモジュールです。LimeSurveyが条件と評価を管理する現場の方法に取って代わるものです。
式マネージャー(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}さん、子供は何人いますか。 |
関連性の計算はJavaScriptでも機能しますので、上記のすべての質問を1ページに置くことができ、期待どおりに動作します。実際、EMは、アンケート、グループ、一画面での一斉質問フォーマットの仕組みを完全に置き換えています。今では、まったく同じナビゲーションエンジンを使用しているので、アンケートスタイルに関係なく同じように動作します。
同じページにいる限り、入力した回答データは隠れていますが保持されています。したがって、情報を入力たあと、出現条件を満たさなくなるようなオプションを選択し、再び出現条件を満たすような選択をすると、回答は引き続き利用可能になります。ただし、別のページに移動すると、データセットの整合性を保つため、出現条件を満たさないすべての回答は失われます。
グループレベルの出現条件
式マネージャーはグループレベルの出現条件もサポートしています。これにより、ループ(繰り返し)の実装が容易になります。最大10個の事柄(たとえば、製品や家庭内の人物など)に関する情報を収集するため、まずその数を質問するとします(例えば、家族の人数を聞いたり、リストの中からどの製品が好みなのかを選んでもらったりして)。後から繰り返し聞くべき回数が分かったら、10個用意したグループごとに{count>=1}、{count>=2}、... {count>=10}といった形で、グループレベルの出現条件を設定することができます。それぞれのグループ内では、質問レベルの条件付きロジック(例:回答者の性別や年齢別の質問)を作成することができます。質問とグループレベルの出現条件の式は、表示すべきかを決定するためにAND演算されます。
カスタマイズ/パイプ
中括弧内のものはすべて式として扱われるようになりました(後述する例外が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コード
- 定義済みの関数(既に70以上ありますが、簡単に追加できます)
演算子
EM構文は、通常の演算子の優先順位に従います。
レベル | 演算子 | 説明 |
---|---|---|
1 | () | グループ化または関数呼び出しのための括弧 |
2 | ! - + | 単項演算子: 否定、正負 |
3 | * / | 乗算、除算 |
4 | + - | 加算、減算 |
5 | < <= > >= lt le gt ge | 比較演算子 |
6 | == != eq ne | 同等比較 |
7 | and | 論理積 AND |
8 | or | 論理和 OR |
9 | = | 代入演算子 |
10 | , | コンマ演算子 |
プラス演算子に関する注意(+)
JavaScriptとPHPの間の一貫性を保つために、プラス演算子(+)は両方のオペランドが数値の場合は加算を行いますが、両方の部分が数値以外の文字列の場合は連結します。しかし、意図をもっとはっきりさせるため、連結関数join()を使うことをお勧めします。
数と文字列の型の不一致、および文字列としての強制比較に関する注意
値を不等号や等号で比較する場合は、値の型の不一致に注意してください。ユーザーが入力した値や選択した回答コードが明確に数値であれば、数値として使用されます。
いずれかの値が"
で囲まれている場合: 強制的にテキストとして比較します。数値として比較したい場合は"
で囲んではいけません。
たとえば、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>
は、ここでは式の質問を使います。なぜなら、完全な質問コードが使用できるからです。<a href="/script.php?value={EQUATION.NAOK}">next</a>
変数へのアクセス
式マネージャーでは、必要な変数に読み取り専用でアクセスできます。下位互換性を保つため、次のものにアクセスすることができます。
- TOKEN:xxx - トークンの属性値(例: TOKEN:FIRSTNAME、TOKEN:ATTRIBUTE_5)(匿名でないアンケート向け)
- INSERTANS:SGQA - 回答として表示する値(例: "はい")。式マネージャーでは、{QCODE.shown}と同じです。
- テンプレート内で使われるすべての{XXX}
- 質問テキストでは、{QID}を質問IDで置き換え、{SGQ}を質問のSGQAで置き換えることができます。
さらに、式マネージャーでは、質問コード(データベース内の質問テーブルの'タイトル'列)で変数を参照できます。これは、データを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
Qcode変数の命名
Qcodeを構成する方法(およびいくつかのプロパティにアクセスする方法)の質問タイプ別の詳細は次のとおりです。一般に、Qcodeは次のように構成されます。
QuestionCode . '_' . SubQuestionID . '_' . ScaleId
コメントおよびその他の質問コードは、それぞれ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'} |
予約変数 this、self、that
回答されたサブ質問の数を数えたり、スコアを合計するなど、質問の全体を評価したい場合がよくあります。また、質問の特定の行や列(行や列の合計を取得してデータベースに格納するなど)を処理したい場合もあります。以下の予約変数により、そのプロセスを簡単に実現できます。
'this'変数は、"完全な質問の検証式"と"サブ質問の検証式"の高度な質問オプション内で排他的に使用されます。該当の質問内の各セルの変数名に展開されます。したがって、各エントリが3より大きいかどうかを確認する場合は、"サブ質問の検証式"を(this > 3)に設定します。
'self'と 'that'変数はより強力で、式を処理する前に展開されるマクロとして機能します。構文は次のとおりです。
- self
- self.suffix
- self.sub-selector
- self.sub-selector.suffix
suffixは、通常のqcode接尾辞のいずれかです(例: NAOK、value、shown)。
sub-selectorは次のいずれかです。
- 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'は'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'を使っている元の式が表示されます。
また、(a)式に使用される各変数を明示的に命名する場合、または(b)サブ質問を持たない変数を使用する場合(例:単一回答の質問)、これらの変数を使用しないでください。そのような場合に、変数に'that'をつけてプレフィックスをつけると、予期しない結果が出る危険があります。
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を付加するとよいでしょう。それが必要で、内容を理解している場合は別です。
その他の例と情報は、カスケードされた条件の上書きを参照してください。
関数へのアクセス
式マネージャーでは、以下に示すように、数学関数、文字列関数、およびユーザー定義関数が利用できます。これらの関数にはPHPとJavaScriptに同等のものがあるので、サーバ側(PHP)とクライアント側(JavaScript)で同じように動作します。新しい機能を追加するのは簡単です。
実装済み関数
現在、以下の関数が利用可能です。
関数 | 意味 | 構文 |
---|---|---|
abs | 絶対値 | number abs(数値) |
acos | アークコサイン | number acos(数値) |
addslashes | 文字列をスラッシュで引用 | string addslashes(文字列) |
asin | アークサイン | number asin(数値) |
atan | アークタンジェント | number atan(数値) |
atan2 | 2変数のアークタンジェント | number atan2(数値, 数値) |
ceil | 切り上げ | number ceil(数値) |
checkdate | グレゴリオ暦で有効な日付であれば真(1)を返す | bool checkdate(月,日,年) |
convert_value | 変換元リストにある数値を対応する変換先リストの数値に変換する | number convert_value(変換する数値, 一致フラグ, 変換元リスト, 変換先リスト) |
cos | コサイン | number cos(数値) |
count | リスト内で回答された(空白でない)質問の数 | number count(arg1, arg2, ..., 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 エンティティを適切な文字に変換する (always uses ENT_QUOTES and UTF-8) | string html_entity_decode(文字列) |
htmlentities | Convert all applicable characters to HTML entities(常にENT_QUOTESとUTF-8を使用) | string htmlentities(string) |
expr_mgr_htmlspecialchars | 特殊文字を HTML エンティティに変換す(常にENT_QUOTESとUTF-8を使用) | string htmlspecialchars(文字列) |
expr_mgr_htmlspecialchars_decode | 特殊な HTML エンティティを文字に戻す(常にENT_QUOTESとUTF-8を使用) | string htmlspecialchars_decode(文字列) |
idate | 指定した、もしくは現在のローカルな時刻/日付を整数として整形する | string idate(文字列[, 指定時刻=time()]) |
if | Excelスタイルのif(条件,trueの時の結果,falseの時の結果) | if(条件,trueの時の結果,falseの時の結果) |
implode | 配列要素を文字列により連結するg | 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 (2.0 build 130129から追加) | 要素を新しい文字列として結合する | join(arg1, arg2, ... argN) |
list | 空白でない値をコンマ区切りリストで返す | string list(arg1, arg2, ... argN) |
log | 自然対数(底が指定されている場合は底に対する対数) | number log(数値,底=e) |
ltrim | 文字列の最初から空白 (もしくはその他の文字) を取り除く | string ltrim(文字列 [, 削除する文字のリスト]) |
max | 最大値を返す | number max(arg1, arg2, ... argN) |
min | number min(arg1, arg2, ... argN) | |
mktime | 日付を Unix のタイムスタンプとして取得する(引数は省略可) | number mktime([時 [, 分 [, 秒 [, 月 [, 日 [, 年 ]]]]]]) |
モジュロ関数 | モジュロ関数はまだサポートされていません。代わりに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(数値) |
sprintf | フォーマットされた文字列を返す | string sprintf(フォーマット, arg1, arg2, ... argN) |
sqrt | 平方根 | number sqrt(数値) |
stddev | 数値のリストのサンプル標準偏差を計算する | number stddev(arg1, arg2, ... argN) |
str_pad | 文字列を固定長になるまで他の文字列で埋める | string str_pad(入力文字列, 文字列の長さ [, 埋める文字列]) |
str_repeat | 文字列を反復する | string str_repeat(入力文字列, 繰り返し回数) |
str_replace | 検索文字列に一致したすべての文字列を置換する | string str_replace(検索文字列, 置き換える値, 対象の文字列) |
strcasecmp | Binary safe case-insensitive string comparison | int strcasecmp(str1, str2) |
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(対象文字列, 検索文字列 [, before_needle=false]) |
strlen | 文字列の長さを得る | int strlen(文字列) |
strpos | 文字列内の部分文字列が最初に現れる場所を見つける(0から始まり、現れなければfalse) | int strpos(対象文字列, 検索文字列 [ 検索開始位置=0]) |
strrev | 文字列を逆順にする | string strrev(文字列) |
strstr | 文字列が最初に現れる位置を見つける | string strstr(対象文字列, 検索文字列[, before_needle=false]) |
strtolower | 文字列を小文字にする | string strtolower(文字列) |
strtotime | 英文形式の日付を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(数値) |
time | 現在の Unix タイムスタンプを返す | number time() |
trim | 文字列の先頭および最後から空白(またはその他の文字)を取り除く | string trim(文字列 [, 削除する文字のリスト]) |
ucwords | 文字列の各単語の最初の文字を大文字にする | string ucwords(文字列) |
unique | 空白以外の回答のすべてが一意である場合にtrueを返す | boolean unique(arg1, ..., argN) |
計画中・検討中の関数
計画中(または検討中)でまだ実装されていない関数は、以下の通りです。このうちいくつかは別のアンケートツールとの下位互換性のためのものです。
構文 | 意味 | コメント |
---|---|---|
e() | eの値を返す | |
formatDate(X,PAT) | Javaデータ形式パターンPATに従ってフォーマットされた日付Xの文字列値を返す | |
formatNumber(X,PAT) | Java数値書式パターンPATに従ってフォーマットされた数値Xの文字列を返す | |
getAnsOption(X) | コアプラグインExpressionAnswerOptions | |
getAnsOption(X,Y) | コアプラグインExpressionAnswerOptions | |
getRelevance(X) | 質問Xの出現条件の式を返す | |
getStartTime() | アンケートが開始されたシステム時刻の日付を返す | |
getType(X) | データタイプの名前を返す(例: isNA()なら*NA*) | |
gotoFirst() | 出現条件を満たす最初の質問にジャンプする(これはシステムの通常の流れに反する) | |
gotoNext() | 出現条件を満たす次の質問にジャンプする(これはシステムの通常の流れに反する) | |
gotoPrevious() | 出現条件を満たすひとつ前の質問にジャンプする(これはシステムの通常の流れに反する) | |
isAsked(X) | 回答が*NA*、*INVALID*、*UNASKED*のいずれでもなければtrueを返す | |
isInvalid(X) | 回答が*INVALID*の場合trueを返す | |
isNA(X) | 回答が*NA*の場合trueを返す | |
isNotUnderstood(X) | 回答が*HUH*の場合trueを返す | |
isRefused(X) | 回答が*REFUSED*の場合trueを返す | |
isSpecial(X) | 回答が*UNASKED*、*NA*、*REFUSED*、*INVALID*、*UNKNOWN*、*HUH*のいずれかの場合trueを返す | |
isUnknown(X) | 回答が*UNKNOWN*の場合trueを返す | |
jumpTo(X) | 指定した名前の質問を含むグループにジャンプする(これはシステムの通常の流れに反する) | |
jumpToFirstUnasked() | ||
lastIndexOf(X,Y) | 文字列Xに文字列Yが最後に現れる位置(0始まり)を返す(XにYが含まれない場合は-1を返す) | |
list(X,...) | 正の値のリスト(値はコンマで区切り、最後の2つの間は"and"で区切る) | |
mean(X,...) | リストの値の平均を返す | |
numAnsOptions(X) | 質問Xの回答オプションの数を返す | |
orlist(X,...) | 正の値のリスト(値はコンマで区切り、最後の2つの間は"or"で区切る) | |
parseDate(X,PAT) | 文字列XをJavaの日付書式パターンPATで解析した日付値を返す | |
parseNumber(X,PAT) | 文字列XをJavaの数値書式パターンPATで解析した数値を返す | |
showAllResponsesExcept( questionList,attributeList,attributeTitleList) | questionListはパイプで区切られた質問IDのリスト、attributeListはパイプで区切られた属性のリスト(question#、title、text、typeなど、表示したいもの)、attributeTitleListはパイプで区切られたテーブルヘッダーで、レポートを国際化する | |
showTheseResponses( questionList,attributeList,attributeTitleList) | questionListはパイプで区切られた質問IDのリスト、attributeListはパイプで区切られた属性のリスト(question#、title、text、typeなど、表示したいもの)、attributeTitleListはパイプで区切られたテーブルヘッダーで、レポートを国際化する |
式マネージャーとローカル変数
ページの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 | |
== (または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 | |
(exp) | (a && b) | N/A | 5 | false |
(exp) op (exp) | (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 | yesno | {name}さん、あなたの年齢は{age}歳、{numKids}名のお子様がいると回答しました。{min(numKids,5)}番目のお子様までの年齢の合計は、{sumage}です。 |
これらの質問はすべて1つのページ(たとえば同じグループ)に入れることができ、出現条件に合致する質問のみが表示されます。さらに、子供の年齢を入力すると、最後の質問のsum()式がページ上で動的に更新されます。
式マネージャーは、各式を名前付き<span>要素で囲むことでこの機能を提供します。値が変更されるたびに、その<span>要素に表示される式を再計算し、再表示します。そのようなカスタマイズされた式が同じページに数十、または数百もあっても、ページは一度の画面更新ですべて再表示されます。
LimeSurvey 1.91と式マネージャー機能の対照表
旧機能 | 新機能 | コメント |
---|---|---|
条件 | 出現条件 | 非常に複雑な条件式を使用して、より広い範囲の変数にアクセスできます。 |
評価 | 式 | どの評価スコアも式に再構成することができます。これにより、スコアがデータベースに書き込まれるとともに、現在のページでスコア値が動的に変化しても表示できます。 |
置換 | 式マネージャー | コアエンジンは入力文字列を取得すると、中括弧内のすべてを式として扱います。したがって、すべての置換タイプを処理します。埋め込まれたJavaScriptの混乱を避けるために、式マネージャーでは、中括弧内に先頭または末尾の空白がない限り、中括弧間のコンテンツしか処理しません。たとえば{expr}は式ですが、{ expr}、{expr }、{ expr }は式ではありません。さらに、式マネージャーは文字列内のコンテンツを処理しません(たとえば、{list('hi','there {braces}')}は"hi there {braces}"となります)。また、エスケープされた中括弧も無視されます(例えば、\{this is not an expression\})。 |
検証 | 式マネージャー | 現在の最小/最大の質問属性を使って、式マネージャーからそれらを処理する計画です。これにより、最小値/最大値は式そのものになります。 |
構文ハイライト
式の入力と検証を支援するために、EMでは以下のような構文強調表示機能を提供しています。
構文ハイライトの種類と意味
色 | サンプル | 意味 | ツールチップ | コメント |
---|---|---|---|---|
黄褐色の背景 | サンプル | 式全体 | なし | 式として認識される中括弧内のもの(先頭または末尾の空白がない)は、周囲のテキストと区別するのに役立つ黄褐色の背景で色分けされます。 |
太字赤色のテキスト | サンプル | エラー | エラーに関する説明 | 未知の変数または関数のエラーの可能性があります。アンケートは完全に壊れている可能性がありますが、これは一般ユーザーには表示されません。 |
青色のテキスト | サンプル | 関数名 | 関数の意味と構文 | 関数名、または開く括弧が続くので関数と思われるものは、太字の青いテキストで表示されます。ツールチップには、その機能の意味と許容される構文が表示されます。 |
灰色のテキスト | サンプル | 文字列 | なし | シングルもしくはダブルクォートで囲まれた文字列が灰色のテキストとして表示されます。 |
水色のテキスト | サンプル | 同じページにセットされた変数 | [名前またはSGQAコード]: 質問; 値; それぞれの値のコードが示された回答リスト | 現在の質問と同じページに設定されている変数は水色のテキストで表示され、javascriptで更新されます。ツールチップには、名前(INSERTANS:xxxを使用した場合)またはSGQAコード(新しい命名システムを使用した場合)、実際の質問、および現在の値(設定されていない場合は空欄)が表示されます。列挙された値セットからの選択を期待する質問タイプの場合、コードの表示値へのマッピングが表示されます。 |
緑色のテキスト | サンプル | 先行するページでセットされた変数 | [名前またはSGQAコード]: 質問; 値; それぞれの値のコードが示された回答リスト | 先行するページに設定されている変数は太字の緑色のテキストで表示されます。ツールチップには、名前(INSERTANS:xxxを使用した場合)またはSGQAコード(新しい命名システムを使用した場合)、実際の質問、および現在の値(設定されていない場合は空欄)が表示されます。列挙された値セットからの選択を期待する質問タイプの場合、コードの表示値へのマッピングが表示されます。 |
太字桃色のテキスト | サンプル | 後続のページでセットされた変数一般的には、アンケート開始時は空で、インデックスや前への移動を使用した時に値が入ります。 | [名前またはSGQAコード]: 質問; 値; それぞれの値のコードが示された回答リスト | 後続のページに設定されている変数は太字の桃色のテキストで表示されます。ツールチップには、名前(INSERTANS:xxxを使用した場合)またはSGQAコード(新しい命名システムを使用した場合)、実際の質問、および現在の値(設定されていない場合は空欄)が表示されます。列挙された値セットからの選択を期待する質問タイプの場合、コードの表示値へのマッピングが表示されます。 |
太字の黄褐色のテキスト | サンプル | LimeSurveyの置換値 | 値 | LimeSurveyの置換文字列({TOKEN:xxx}、{PRIVACY_MESSAGE}など)は太字の黄褐色のテキストとして表示されます。 |
赤色のテキスト | サンプル | 代入演算子(=) | 注意喚起メッセージ | 代入演算子(=)を使用すると、演算子は赤色のテキストで表示されます。これは、aとbは等しいことを確認しようとしているとき、誤ってbの値をaに代入することを防ぐのに役立ちます。 |
通常の黒色のテキスト | サンプル | 句読点 | なし | 式の内の他の句読点はすべて、通常の黒文字で表示されます。 |
赤枠で囲まれたテキスト | 赤い太線で囲まれたエラー | 構文エラー | エラーの説明 | 検出された構文エラーは、エラーを赤い枠線で囲んで表示されます。ツールチップにエラーが表示されます。例としては、括弧の不一致、未定義関数の使用、関数に渡す引数の数の誤り、構造化が不十分な式(変数間の演算子の欠落など)、読み取り専用変数に値を代入しようとする、変数でないものに値を代入しようとする、サポートされていない構文を使用するなどです。構文エラー検出システムは、複数のエラーがあっても式内の1つのエラーだけを報告することがあります。ただし、エラーが検出された場合は、少なくとも1つのエラーが表示されます。 |
参考記事
式マネージャーのサンプル
ユースケースとHowTo
ステップバイステップの例
式マネージャーの統計関数
開発者向け参考情報