مدير التعبيرات
From LimeSurvey Manual
دليل البدء السريع
نظرة عامة
عند تخصيص الاستبيانات الخاصة بك، فإنك تحتاج عادةً إلى طريقة لتحديد ما يلي:
- التنقل/التفرع - السماح لإجابات المشارك بتغيير ترتيب عرض الأسئلة
- التخصيص/التضمين (Tailoring/Piping) - كيفية صياغة السؤال (مثل الإشارة إلى إجابات سابقة، أو تصريف الجمل بحسب عدد المشاركين أو جنسهم)، أو كيفية إنشاء تقارير مخصصة (مثل نتائج التقييم أو النصائح المخصصة).
- التحقق من الصحة - التأكد من أن الإجابات تستوفي معايير معينة، مثل الحد الأدنى والحد الأقصى للقيم، أو مطابقة نمط إدخال معين
يوفر مدير التعبيرات (Expression Manager - EM) طريقة بديهية لتحديد المنطق الخاص بكل ميزة من هذه الميزات. يُعد أي شيء تقريبًا يمكنك كتابته كمعادلة رياضية قياسية تعبيرًا صالحًا، حتى إن كنت تستدعي دوال. يتيح EM حاليًا الوصول إلى 80 دالة، ويمكن توسيعه بسهولة لدعم المزيد. كما يتيح لك الوصول إلى المتغيرات باستخدام أسماء متغيرات سهلة القراءة (بدلًا من أسماء SGQA).
توضح الأقسام التالية الأماكن الرئيسية التي يُستخدم فيها مدير التعبيرات
الصلة (التحكم في التنقل/التفرع)
تستخدم بعض الاستبيانات "منطق الانتقال (Goto Logic)"، بحيث إذا أجبت عن السؤال 1 بالخيار C، تنتقل إلى السؤال 5. هذا الأسلوب محدود جدًا، لأنه يصعب التحقق من صحته، ويتعطل بسهولة عند إعادة ترتيب الأسئلة. يستخدم EM معادلة صلة منطقية (Boolean) لتحديد جميع الشروط التي يكون السؤال صالحًا في ظلها. إذا كان السؤال ذا صلة، فسيتم عرضه، وإلا فهو غير قابل للتطبيق، ويتم تخزين القيمة NULL في قاعدة البيانات. هذا مشابه لما يمكن تنفيذه عبر محرر الشروط، لكن EM يتيح لك بسهولة تحديد معايير أكثر تعقيدًا وقوة (ويتيح لك استخدام اسم المتغير بدلًا من تسمية SGQA).
توضح هذه الصورة إحدى طرق مراجعة منطق الصلة في استبيان ما. يقوم الاستبيان بحساب مؤشر كتلة الجسم. تظهر معادلة الصلة بين قوسين مربعين مباشرةً بعد اسم المتغير (باللون الأخضر). وهكذا فإن صلة weight وweight_units وheight وheight_units كلها 1، أي أن هذه الأسئلة تُطرح دائمًا. أما صلة BMI فهي {!is_empty(height) and !is_empty(weight)}، مما يعني أنه لن يتم حساب BMI إلا إذا أدخل المشارك قيمة لكل من الطول والوزن (وبذلك يتم تجنب خطر حدوث خطأ القسمة على صفر). كما أن سؤال Report لا يظهر إلا إذا أجاب المشارك عن الأسئلة الرئيسية الأربعة (height وheight_units وweight وweight_units).
تظهر الصلة ويمكن تحريرها في الأماكن التالية:
عرض/تحرير الصلة على مستوى السؤال
تحسب هذه المعادلة مؤشر كتلة الجسم (BMI). ولا يتم طرح السؤال إلا إذا أدخل الشخص طوله ووزنه أولًا.
هذه شاشة التحرير الخاصة بسؤال BMI.
لاحظ أنك لا تستخدم الأقواس المعقوفة عند إدخال معادلة الصلة.
عرض/تحرير الصلة على مستوى المجموعة
هذا استبيان تعداد سكاني نموذجي. تسأل الصفحة الأولى عن عدد الأشخاص الذين يعيشون معك وتخزن ذلك في المتغير "cohabs". لا تظهر هذه الصفحة إلا إذا كان لديك أكثر من شخص يشاركك السكن (أي أنها تظهر للشخص الثاني الذي يشاركك السكن)، ولا تظهر أيضًا إلا إذا حددت صلة الشخص الأول بك (p1_rel).
كما ترى، تحتوي المجموعة أيضًا على معايير صلة على مستوى السؤال، بحيث لا يظهر كل سؤال إلا بعد أن تجيب عن السؤال الذي يسبقه (مثل {!is_empty(p1_sex)}). يجمع EM بين الصلة على مستوى المجموعة وعلى مستوى السؤال نيابةً عنك. لا تُطرح الأسئلة في المجموعة إلا إذا كانت المجموعة ككل ذات صلة. بعد ذلك، لا تُطرح إلا مجموعة الأسئلة الفرعية ذات الصلة داخل المجموعة.
هذه شاشة تحرير الصلة على مستوى المجموعة لذلك السؤال:
لاحظ أنك لا تستخدم الأقواس المعقوفة عند إدخال معادلة الصلة.
التخصيص/التضمين (Tailoring/Piping)
يتيح لك EM إجراء تخصيص شرطي بسيط ومعقد لأسئلتك بسهولة. أحيانًا تحتاج فقط إلى استبدال بسيط، مثل قول: "ذكرتَ أنك اشتريت [المنتج]. ما الذي أعجبك فيه أكثر؟". وأحيانًا تحتاج إلى استبدال شرطي مثل "[السيد/السيدة] [اسم العائلة]، هل ترغب في إكمال استبياننا؟". في هذه الحالة، تريد استخدام السيد أو السيدة بحسب جنس الشخص. وفي أحيان أخرى تحتاج إلى استبدال أكثر تعقيدًا (مثل ما يعتمد على عملية حسابية). يدعم EM كل هذه الأنواع من التخصيص/التضمين.
المعادلات الشرطية
يوضح مثال مؤشر كتلة الجسم إمكانية حساب BMI للشخص، حتى مع السماح له بإدخال طوله ووزنه بوحدات متريّة أو غير متريّة.
هنا weight_kg هو {if(weight_units == 'kg', weight, weight * .453592)}. تعني الدالة if() هذه أنه إذا أدخل المشارك الوزن بالكيلوغرام، فسيتم استخدام هذه القيمة، وإلا فسيتم ضرب القيمة المدخلة (التي كانت بالباوند) في .453592 لتحويلها إلى كيلوغرام. يستخدم المتغير height_m أسلوبًا مشابهًا لحساب طول الشخص بالمتر، حتى لو أدخل طوله بالبوصة.
يحسب BMI صيغة الوزن على النحو التالي {weight_kg / (height_m * height_m)}.
وأخيرًا، يقوم التقرير بتخصيص الرسالة للمشارك بشكل مشروط، ويخبره بما أدخله. ("لقد ذكرت أن طولك 2 متر ووزنك 70 كغ.")
على الرغم من أن الصورة أعلاه لا توضح ذلك جيدًا، فإن weight_status يستخدم عبارات if() متداخلة لتصنيف الشخص من نحيف إلى سمين بشكل مفرط. يمكنك رؤية معادلته في عرض المنطق (Show Logic View)
من نافذة التحرير الخاصة بهذا السؤال، يمكنك ملاحظة أمرين:
- يجب أن يحيط التخصيص بالتعبيرات بأقواس معقوفة {}
- يمكن أن تمتد التعبيرات على عدة أسطر إذا أردت، كما في هذه الحالة، تسهيل قراءة المنطق الشرطي المتداخل.
الأسئلة والإجابات والتقارير المخصصة
يعرض هذا المثال تقرير BMI.
هذه هي نافذة التحرير الخاصة بالسؤال نفسه.
كما ترى، يُعامل أي نص بين الأقواس المعقوفة على أنه تعبير، ولذلك يتم تمييز بنيته بالألوان في الصورة السابقة. وإذا كانت هناك أي أخطاء مطبعية (مثل أسماء متغيرات أو دوال مكتوبة بشكل خاطئ أو غير معرفة)، فسيعرض EM خطأً، كما في هذا المثال الذي يبين أن height_unit اسم متغير غير معرف (والصحيح هو height_units)، وأن rnd() وظيفة غير معروفة (اسم الدالة الصحيح هو round()). وفي الحالتين، يُحاط الخطأ بمربع أحمر لتسهيل اكتشافه وإصلاحه.
يمكنك أيضًا ملاحظة أنه يمكنك إنشاء تقارير معقدة بسرعة، مثل جدول بالقيم المدخلة أو نصائح مخصصة.
يرجى تذكر أن كل تخصيص يجب أن يحيط التعبيرات بأقواس معقوفة، حتى يعرف LimeSurvey أي أجزاء السؤال هي نص حر وأيها يجب معالجتها عبر Expression Manager.
التحقق من الصحة
يتحكم EM في طريقة عمل معظم خيارات السؤال المتقدمة. وتتحكم هذه الخيارات في جوانب مثل الحد الأدنى/الأقصى لعدد الإجابات، والحد الأدنى/الأقصى للقيم الفردية، والحد الأدنى/الأقصى لمجموع القيم، والتحقق من تطابق القيم المدخلة مع أنماط نصية محددة. وتستمر في إدخال خيارات السؤال المتقدمة هذه كالمعتاد. لكن أي قيمة في أحد هذه الحقول تُعتبر الآن تعبيرًا، لذا يمكنك وضع معايير حد أدنى/أقصى ذات علاقات شرطية معقدة مع أسئلة أخرى.
في جميع هذه الحالات، وبما أن خيار السؤال المتقدم يُعتبر دائمًا تعبيرًا، فلا تستخدم الأقواس المعقوفة عند تحديده.
تعرض صفحات الاستبيانات النموذجية أمثلة عملية كثيرة على استخدام التعبيرات للتحقق من الصحة.
مقدمة
يستخدم LimeSurvey وحدة Expression Manager (EM) الجديدة التي تتيح لـ LimeSurvey دعم تفرعات وتقييمات وتحقق من الصحة وتخصيص أكثر تعقيدًا. وستحل محل الطريقة التي يدير بها LimeSurvey الاستبدالات والشروط والتقييمات في الخلفية. كما ستسرّع المعالجة بشكل كبير لأنها تلغي معظم عمليات قراءة قاعدة البيانات أثناء التشغيل. طوّر EM الدكتور توماس وايت (TMSWhite).
هذه الصفحة هي المرجع النهائي لصيغة Expression Manager ووظائفه.
التعريفات الأساسية
- التعبير: أي شيء محاط بأقواس معقوفة
- بشرط عدم وجود مسافة فارغة مباشرة بعد القوس الافتتاحي أو قبل القوس الختامي
- يقوم EM بتقييم محتويات التعبيرات، لذا يمكن أن تحتوي على صيغ رياضية ودوال ومعالجة معقدة للنصوص والتواريخ.
- التخصيص: يُسمى أحيانًا "piping"، وهو عملية تعديل النص بشكل مشروط
- يمكنك الوصول إلى جميع "حقول الاستبدال" وبيانات المشارك وبيانات الردود.
- كما يمكنك الوصول بسهولة أكبر إلى الأسئلة وإجاباتها وخصائصها.
- معادلة الصلة: سمة سؤال جديدة تتحكم في ظهور السؤال
- إذا وُجدت معادلة صلة، فلا يُعرض السؤال إلا إذا كان تقييم الصلة صحيحًا.
- داخليًا، تتحول جميع أوامر array_filter وarray_filter_exclude إلى صلة على مستوى الأسئلة الفرعية
- نوع السؤال معادلة: نوع سؤال جديد يحفظ الحسابات أو التقارير في قاعدة البيانات
- يشبه سؤال Boilerplate، لكن محتوياته تُحفظ في قاعدة البيانات حتى لو قمت بتعيين "دائما اخف هذا السؤال"
- رمز السؤال: هذا هو اسم المتغير المفضل لدى EM
- يمكن أن يكون اسمًا وصفيًا يشير إلى الغرض من السؤال، مما يسهل قراءة المنطق المعقد
- يجب ألا تبدأ رموز الأسئلة الصالحة برقم، لذا عند استخدام رمز السؤال لترقيم أسئلتك، استخدم ببساطة "q1" أو "q1a" أو "g1q2".
- هذا هو ما يصبح حاليًا اسم المتغير إذا قمت بتصدير البيانات إلى SPSS أو R، لذا إذا كنت تجري تحليلًا إحصائيًا فمن المحتمل أنك جعلته فريدًا بالفعل.
هل يجب أن أستخدم EM؟
الإجابة المختصرة هي لا (ولكن نعم أيضًا).
EM متوافق تمامًا مع الإصدارات السابقة للاستبيانات الحالية. لذا، إذا كنت ترغب في استخدام الشروط والتقييمات بالأسلوب الذي استخدمه LimeSurvey في الإصدارات <= 1.91+، فيمكنك الاستمرار في ذلك.
ومع ذلك، يحل EM بالكامل محل الطريقة التي يتعامل بها LimeSurvey داخليًا مع الشروط. وعلى الرغم من أنه لا يزال بإمكانك استخدام محرر الشروط لإنشاء الشروط وإدارتها، فإن LimeSurvey 1.92 سيحوّلها إلى معادلات الصلة المكافئة. وكجزء من الترقية، سيحوّل LimeSurvey 1.92 تلقائيًا جميع الشروط الحالية إلى معادلات صلة.
يمنحك هذا أفضل ما في العالمين - يمكنك مواصلة استخدام LimeSurvey كما اعتدت، لكنك سترى المكافئ في صورة معادلة صلة، بحيث يمكنك الانتقال تدريجيًا إلى معادلات الصلة مباشرة متى رأيت ذلك مناسبًا.
هل يمكنني الجمع بين استخدام الشروط والصلة؟
نعم. يمكنك استخدام محرر الشروط لبعض الأسئلة ومحرر الصلة لأسئلة أخرى. يتم تحويل الشروط تلقائيًا إلى صلة عند حفظ السؤال.
لاحظ أننا نفترض أنك إذا كنت تستخدم محرر الشروط، فإنك تريد أن تحل هذه الشروط محل أي معادلة صلة تم إدخالها يدويًا. لذلك، إذا كانت لديك شروط موجودة وتريد تحرير الصلة يدويًا، فيرجى حذف الشروط الخاصة بهذا السؤال أولاً. وتحديدًا، انسخ معادلة الصلة التي تم إنشاؤها إلى محرر نصوص، ثم استخدم قائمة الشروط لحذف جميع شروط هذا السؤال (مما سيؤدي أيضًا إلى حذف الصلة)، ثم حرر السؤال والصق معادلة الصلة التي تم إنشاؤها من محرر النصوص في حقل الصلة الخاص بهذا السؤال (ثم احفظ السؤال). وإذا كان هناك طلب كافٍ على حذف الشروط دون حذف معادلة الصلة التي تم إنشاؤها، فيمكننا إضافة عملية تحويل مجمّعة.
كيف أختار بين الشروط والصلة؟
فيما يلي قائمة بمزايا وعيوب كل أسلوب:
| الأسلوب | المزايا | العيوب |
|---|---|---|
| الشروط | 1. واجهة رسومية جيدة لإنشاء شروط بسيطة 2. الواجهة الرسومية موثقة جيدًا ومفهومة لدى فريق الدعم |
1. تدعم المقارنات البسيطة فقط ولا تتعامل جيدًا مع الشروط AND/OR 2. الشروط المتتابعة تعمل بشكل غير منتظم 3. بطيئة - تعتمد بشكل مكثف على قاعدة البيانات، مما قد يبطئ الاستبيانات الطويلة 4. بعض المشكلات المبلّغ عنها عند إعادة تحميل الشروط 5. الواجهة الرسومية لا تتوسع جيدًا عند وجود عشرات أو مئات أو آلاف الأسئلة 6. قد يكون تحويل الاستبيانات الورقية بطيئًا لأنه يجب استخدام أسماء SGQA 7. غالبًا ما تحتاج إلى مبرمج لكتابة المنطق المطلوب للتفرع المعقد |
| الصلة | 1. تدعم منطقًا معقدًا جدًا، بما في ذلك أكثر من 80 دالة ومعاملات رياضية ونصية 2. دعم مثالي للمنطق المتتابع 3. سريعة - لا توجد استدعاءات إضافية لقاعدة البيانات، لذا تدعم استبيانات تضم أكثر من 1000 سؤال 4. لا مشكلات في إعادة تحميل المنطق لأنها لا تتطلب رموز SGQA 5. تمييز بناء الجملة يتوسع ليناسب استبيانات تضم أكثر من 1000 سؤال 6. سهلة وسريعة الاستخدام للجهات التي ترغب في حوسبة استبياناتها الورقية الحالية. 7. تدعم بسهولة المقابلات شبه المنظمة والاستبيانات الوبائية دون الحاجة إلى مبرمجين |
1. لا توجد واجهة رسومية للشروط البسيطة - استخدم تمييز بناء الجملة بدلاً منها 2. جديدة، لذلك لم يتقن فريق الدعم استخدام EM بعد. |
الخلاصة أنه إذا كنت راضيًا عن طريقة عمل LimeSurvey 1.91+، فلا يوجد سبب لتغيير ما تفعله.
ما هي بعض الفوائد الأخرى لاستخدام EM؟
فيما يلي بعض الأسباب الأخرى التي قد تدفعك لاستخدام EM.
- العمليات الحسابية - يمكنك إنشاء أي عملية حسابية يمكنك التفكير فيها:
- يمكنك الوصول إلى جميع المعاملات والدوال الرياضية الشائعة
- يمكنك الوصول إلى أكثر من 70 دالة لمعالجة الأعداد والتواريخ والنصوص
- من السهل نسبيًا على المطورين إضافة دوال جديدة إذا احتاج المستخدمون إليها
- تخزين العمليات الحسابية في قاعدة البيانات
- يمكنك الآن إجراء عمليات حسابية بسيطة ومعقدة و/أو درجات المقاييس مع تخزينها في قاعدة البيانات دون الحاجة إلى JavaScript.
- تستخدم نوع السؤال معادلة لتحقيق ذلك.
- التقييمات
- يمكنك الآن إنشاء تقييمات أو درجات مقاييس من أي نوع سؤال، وليس فقط من المجموعة الفرعية التي كانت مدعومة سابقًا
- يمكنك استخدام التخصيص لعرض درجات التقييم الجارية أو الإجمالية في أي مكان مطلوب - حتى في الصفحة نفسها
- لديك تحكم أكبر في التقارير التي يتم إنشاؤها بناءً على درجات التقييم هذه
- يمكنك تخزين درجات التقييم في قاعدة البيانات دون الحاجة إلى JavaScript
- يمكنك إخفاء درجات التقييم دون الحاجة إلى JavaScript أو CSS
- حقول الاستبدال
- استخدم كود السؤال لإدراج قيم من إجابات الأسئلة السابقة - مما يسهّل القراءة والتحقق.
- التخصيص - يمكنك عرض النص بشكل مشروط بناءً على قيم أخرى
- استخدم اللقب المناسب للمشارك، مثل (مثلاً "مرحبًا [السيد/السيدة] Smith")
- إنتاج جمل سليمة نحويًا عندما يكون للمفرد/الجمع أهمية: (مثلاً "لديك طفل واحد" مقابل "لديك طفلان")
- تصريف الأفعال وتغيير صيغ الأسماء بشكل مناسب بناءً على جنس المشارك وعدده.
- سمات المتغيرات الجديدة - يمكنك الوصول إلى ما يلي لإجراء التخصيص:
- (بدون لاحقة) - اسم بديل لـ qcode.code
- .code - رمز الرد المحدد للسؤال إذا كان ذا صلة (وإلا فارغ)، أو القيمة النصية إذا لم يكن سؤالاً مرمّزًا
- .NAOK - مثل .code، ولكن يمكن أن يكون جزءًا من العمليات الحسابية أو القوائم حتى لو لم يكن ذا صلة
- .value - قيمة التقييم للسؤال إذا كان ذا صلة (وإلا فارغ)، أو القيمة النصية إذا لم يكن سؤالاً مرمّزًا -- متاحة إذا كانت التقييمات مفعّلة للاستبيان، وإلا فهي صفر دائمًا
- .valueNAOK - مثل .value، ولكن يمكن أن يكون جزءًا من العمليات الحسابية أو القوائم حتى لو لم يكن ذا صلة
- .shown - الإجابة كما تُعرض للمستخدم
- .qid - معرف السؤال
- .gid - معرف المجموعة
- .sgqa - قيمة SGQA للسؤال
- .jsName - اسم متغير javascript الصحيح للسؤال، سواء عُرّف في هذه الصفحة أو في صفحة أخرى
- .qseq - تسلسل السؤال (يبدأ من 0)
- .gseq - تسلسل المجموعة (يبدأ من 0)
- .mandatory - ما إذا كان السؤال إلزاميًا (Y/N)
- .question - نص السؤال
- .relevance - معادلة الصلة للسؤال
- .grelevance - معادلة الصلة للمجموعة
- .relevanceStatus - ما إذا كان السؤال ذا صلة حاليًا أم لا (قيمة منطقية (قد تختلف بين PHP وJS))
- .type - نوع السؤال (الرمز المكوّن من حرف واحد)
- التغييرات الديناميكية داخل الصفحة
- تعمل جميع عمليات الصلة والحساب والتخصيص ديناميكيًا داخل الصفحة - لذا تُحدّث التغييرات في القيم الصفحة فورًا
- وبالتالي تظهر الأسئلة أو تختفي ديناميكيًا بناءً على ما إذا كانت ذات صلة
- كما يتم تخصيص الأسئلة ديناميكيًا بناءً على الردود في الصفحة، بحيث يمكنك رؤية المجاميع الجارية والجمل المخصصة والتقارير المخصصة.
- صفحة جديدة لإدخال البيانات
- بالإضافة إلى استخدام نظام إدخال البيانات الحالي، يمكنك استخدام Survey-All-In-One.
- يدعم هذا الصلة والتخصيص داخل الصفحة، بحيث يمكن لموظفي إدخال البيانات التنقل بسرعة وسيحتاجون فقط إلى إدخال الردود ذات الصلة
- قد يكون هذا أمرًا حاسمًا إذا كان مدخل البيانات بحاجة إلى رؤية التخصيص، وهو ديناميكي أيضًا.
- يلغي الحاجة إلى معظم أكواد JavaScript المخصصة
- يدعم EM بسهولة العمليات الحسابية المعقدة وحساب الدرجات والتخصيص والمنطق الشرطي.
- ستظل بعض الأمور بحاجة إلى JavaScript (مثل التخطيطات المخصصة وإخفاء العناصر الفرعية للسؤال بشكل مشروط)، ولكن يمكن لـ JavaScript الخاص بك استخدام دوال EM بحيث تصل إلى الأسئلة عبر Qcode بدلاً من SGQA، وإلى أي من خصائص السؤال المذكورة أعلاه.
ما هي بعض الميزات الجديدة المفيدة الأخرى التي يتيحها EM؟
بغض النظر عمّا إذا كنت ستواصل استخدام محرر الشروط أو ستكتب معادلات الصلة يدويًا، فستحصل على هذه الفوائد الإضافية:
- يمكنك إنشاء معايير تحقق من الصحة أكثر تعقيدًا
- يمكن لجميع سمات السؤال المتقدمة (مثل max_answers وmin_num_value_n وmax_num_value) استخدام التعابير. لذلك يمكن تعديل معايير الحد الأدنى والحد الأقصى بسهولة بناءً على الإجابات السابقة، حتى لو كانت في الصفحة نفسها.
- يتولى EM أيضًا جميع عمليات التحقق من الصحة المعتمدة على التعابير النمطية، لذا يمكنك الجمع بقوة بين سمات السؤال المعتمدة على preg وتلك المعتمدة على المعادلات.
- سهولة إعادة ترتيب (أو حذف) الأسئلة والمجموعات
- قبل الإصدار 1.92، لم يكن بالإمكان إعادة ترتيب الأسئلة أو المجموعات إذا رأى LimeSurvey أن إعادة الترتيب قد تُفسد الشروط التي تُستخدم فيها. وبالمثل، لم يكن بالإمكان حذف الأسئلة إذا كانت أسئلة أخرى تعتمد عليها.
- بفضل تمييز بناء الجملة في EM، من السهل رؤية والتحقق مما إذا كنت تحاول استخدام أسئلة قبل التصريح عنها. لذلك نسمح لك الآن بإعادة ترتيب الأسئلة والمجموعات أو حذفها متى شئت. سيحدّث EM تمييز بناء الجملة بالكامل ليُظهر لك الأخطاء المحتملة.
- تم تحسين عرض إعادة ترتيب الأسئلة للمساعدة في هذه المراجعة. فهو يعرض الآن معادلة صلة السؤال والتخصيص، ما يتيح لك أن ترى فورًا ما إذا أصبح أي متغير وردي اللون (أي أنه استُخدم قبل التصريح عنه).
- فهرس التنقل بين الأسئلة/المجموعات متاح دائمًا ودقيق
- قبل الإصدار 1.92، لم تكن هذه الفهارس متاحة إذا كانت هناك شروط معقدة.
- مع EM يمكننا ضمان دقتها.
- يمكن للمشاركين حتى الرجوع إلى سؤال سابق وتغيير الإجابة ثم الانتقال للأمام (أو الإرسال)
- عند الانتقال للأمام، سيعيد EM التحقق من صحة جميع الأسئلة/المجموعات الواقعة بين الموضعين.
- إذا أصبح أي سؤال غير ذي صلة، فسيتم تعيينه إلى NULL في قاعدة البيانات لتكون بياناتك متسقة داخليًا.
- إذا أصبح أي سؤال ذا صلة أو أخفق حديثًا في قواعد الإلزام أو التحقق من الصحة، فسيتوقف EM عند تلك الصفحة ويُلزم المستخدم بالإجابة عن تلك الأسئلة قبل الانتقال إلى وجهته النهائية.
- التحويل التلقائي للشروط إلى صلة
- عند ترقية قاعدة البيانات، سيتم إنشاء معادلات صلة لجميع الاستبيانات الحالية التي تحتوي على شروط
- عند استيراد استبيان، سيتم إنشاء معادلات الصلة حسب الحاجة
- عند إضافة الشروط أو حذفها أو تعديلها، سيُنشئ EM معادلة الصلة المناسبة.
- تمييز بناء الجملة المريح
- عندما يعرض EM معادلة الصلة، فإنه يعرض رمز السؤال (Qcode) حتى لو أدخلت رمز SGQA، لأننا نفترض أن ذلك أسهل في القراءة.
- جميع المتغيرات مرمّزة بالألوان لتوضح ما إذا كان التصريح عنها قبل السؤال الحالي أو بعده (أو قبل المجموعة الحالية أو بعدها). يتيح لك ذلك اكتشاف الحالات التي تحاول فيها استخدام متغيرات في معادلات الصلة (بما في ذلك array_filter) أو التخصيص أو التحقق من الصحة قبل التصريح عنها وإصلاحها بسرعة.
- بالإضافة إلى ذلك، إذا مرّرت مؤشر الماوس فوق المتغير المرمّز بالألوان، فسترى أهم البيانات الوصفية عن ذلك السؤال. وتشمل رقم تسلسل المجموعة، ورقم تسلسل السؤال، ورمز السؤال (Qcode)، ونص السؤال، وجميع خيارات الإجابة المتاحة (إذا كان نوع السؤال يحتوي على خيارات إجابة معدّدة).
- تستخدم قائمة خيارات الإجابة هذه الصيغة: 'answers':{key:val, ... }.
- للمفتاح key الصيغة 'scale~code' حيث scale هو نطاق الإجابة (مثل الأسئلة ثنائية النطاق)، وcode هو رمز الإجابة.
- للقيمة val الصيغة 'value~shown' حيث value هي قيمة التقييم (إذا كنت تستخدم التقييمات، وإلا فهي code) (مثل Qcode.value)، وshown هي القيمة المعروضة كما يراها المشارك (مثل Qcode.shown)
- يعني هذا أن كثيرًا من الاستبيانات يمكنها استخدام العمليات الحسابية دون الحاجة إلى وضع التقييم. إذا كانت لديك خيارات إجابة معدّدة فريدة وغير عشرية وغير سالبة، فيمكنك ببساطة إجراء العمليات الحسابية على قيم Qcode.code.
- مراجعة سهلة لمنطق الاستبيان ومحتواه بالكامل
- توجد ميزة جديدة هي عرض منطق الاستبيان تتيح لك رؤية كل شيء عن الاستبيان (أو المجموعة أو السؤال) في صفحة واحدة.
- تعرض تفاصيل المجموعة والسؤال والسؤال الفرعي والإجابة للنطاق المحدد (الاستبيان مقابل المجموعة مقابل السؤال)
- كما تعرض الصلة، وصلة مستوى الأسئلة الفرعية (لـ array_filter وarray_filter_exclude)، ومعادلة التحقق من الصحة المُنشأة (لـ preg وأي قواعد تحقق مثل الحد الأدنى/الأقصى للمجموع/عدد القيم)، وجميع سمات السؤال غير الفارغة.
- كل شيء ممَيَّز بناء الجملة بحيث يمكنك رؤية أخطاء بناء الجملة المحتملة (مثل الأقواس غير المتوازنة أو استخدام المتغيرات قبل التصريح عنها)
- يدعم تمييز بناء الجملة التنقل السريع وتحرير الاستبيان.
- إذا نقرت على اسم متغير، فسيفتح نافذة متصفح (أو علامة تبويب) تعرض لك ذلك السؤال وتتيح لك تحريره.
- إذا نقرت على اسم مجموعة، فسيفتح نافذة متصفح (أو علامة تبويب) تعرض عرض إعادة ترتيب المجموعة لتتمكن من نقل الأسئلة بسهولة.
- جميع سمات السؤال ممَيَّزة بناء الجملة أيضًا. يتيح لك ذلك ضبط التعابير ومشاهدتها داخل خيارات السؤال المتقدمة (مثل جعل الحد الأدنى/الأقصى لعدد القيم أو مجموعها مبنيًا على تعبير)
- استخدم مؤلف EM عرضًا مشابهًا (أكثر وضوحًا قليلًا) ليتيح لزملائه علماء الأوبئة ولجنة مراجعة المؤسسة التحقق من الاستبيانات التي تضم آلاف الأسئلة في مقابلات منظمة شديدة التفرع والتخصيص والمصادقة عليها
البدء
أفضل طريقة للبدء مع EM هي:
- ثبّت أحدث إصدار مستقر من http://www.limesurvey.org/en/download
- استورد الاستبيانات النموذجية واستكشفها.
- استكشف حالات الاستخدام والإرشادات والأمثلة خطوة بخطوة.
- استكشف وثائق EM (هذه الصفحة)
- افحص مجموعة اختبارات EM المدمجة
- من أي استبيان، ضمن الأدوات، اختر خيار EM
- تعرض الوظائف المتاحة أكثر من 70 وظيفة مع بناء الجملة الخاص بها
- اختبارات الوحدة للتعابير المعزولة
- تعرض أمثلة على استخدام جميع وظائف EM وعوامله، ونتائج PHP وJavaScript
- لاحظ أن هناك بعض الوظائف التي تعطي نتائج مختلفة في إصداري PHP وJavaScript، لذا تتيح لك هذه الصفحة تخطيط منطق EM بناءً على ذلك.
ما الوظائف التي يوسّعها/يستبدلها Expression Manager؟ (LimeSurvey <= 1.91+)
الشروط => الصلة
كانت الشروط تتحكم في الأسئلة المرئية. وكانت الصيغة العامة SGQA المعامل القيمة، مثل 111X2X3 == "Y". ويمكن ربط الشروط معًا باستخدام AND أو OR، لكن المزج بين AND وOR كان صعبًا. وكانت الشروط نفسها مخزنة في جدول منفصل، وخُصص جزء كبير من شيفرة LimeSurvey لإدارة الشروط. وبسبب كثرة الوصول إلى قاعدة البيانات، كانت معالجة أعداد كبيرة من الشروط قد تسبب مشكلات ملحوظة في الأداء. علاوة على ذلك، كان غالبًا لا يُسمح لك بإعادة ترتيب الأسئلة أو المجموعات أو حذفها بمجرد تعيين شروط لها.
التقييمات => المعادلات والتخصيص الدقيق
تتيح التقييمات للمستخدمين إنشاء درجات مقياس من مجموعة أسئلة. لكنها لم تكن قادرة على التغيّر ديناميكيًا في الصفحة الحالية، ولم تكن قيمها تُخزَّن في قاعدة البيانات.
الاستبدالات => التخصيص الدقيق
كان بإمكان المستخدمين تخصيص بعض الرسائل والأسئلة بناءً على الردود السابقة. على سبيل المثال، قد يكون السؤال: {TOKEN:FIRSTNAME}، لقد ذكرت أن {SPORT.shown} هي رياضتك المفضلة. لكن لم يكن ممكنًا إجراء تخصيص شرطي (مثل قول "السيد" أو "السيدة" بحسب جنس الشخص)، أو تصريف الأفعال وإعراب الأسماء دون JavaScript معقد. كان بإمكان المؤلفين تنفيذ استبيانات تبدو وكأنها تخصص الأسئلة، لكن ذلك تطلّب أسئلة منفصلة لكل احتمال، وشروطًا معقدة لتحديد الأسئلة التي ستُعرض.
التحقق من الصحة
كان يمكن التحقق من صحة السؤال باستخدام التعابير النمطية، أو القيم الدنيا/القصوى، أو بجعل رد ما يعمل كقيمة دنيا أو قصوى. لكن لم يكن ممكنًا بناء التحقق من الصحة على حسابات لمتغيرات أخرى دون JavaScript معقد.
المعادلات
لم تكن المعادلات مدعومة دون JavaScript معقد.
نوع سؤال المعادلة
لم يكن ممكنًا حفظ المعادلات في قاعدة البيانات (مثل الدرجة النهائية لتقييم ما) دون JavaScript معقد.
كيف سيستبدل Expression Manager تلك الوظائف أو يوسّعها؟
Expression Manager وحدة أساسية جديدة في LimeSurvey تجعل دعم هذا النوع من الوظائف المعقدة، التي كانت تتطلب JavaScript مخصصًا، أسهل بكثير. وهو أيضًا يحل محل الطريقة التي يدير بها LimeSurvey حاليًا الشروط والتقييمات.
مصطلحات جديدة عند الإشارة إلى Expression Manager (EM)
يتعامل EM مع وظائفه من خلال المفاهيم التالية:
- التفرع المبني على الصلة - إذا كان السؤال ذا صلة، فيُطرح، وإلا فلا يُطرح (أي يُجعل غير مرئي ويُعلَّم بالقيمة NULL في قاعدة البيانات). يوجد حقل صلة جديد لجميع أنواع الأسئلة، وكذلك لكل مجموعة (بحيث يمكنك تطبيق مجموعة من الشروط على مجموعة كاملة دون الحاجة إلى نسخ الشرط نفسه إلى كل سؤال، و/أو الجمع بين المنطق الشرطي على مستوى المجموعة والسؤال).
- التخصيص - بعد أن تعرف الأسئلة التي يجب طرحها، يحدد التخصيص (ويسمى أحيانًا piping) كيفية طرح السؤال. وهذا يتيح لك دعم الاستبدال البسيط (مثل {TOKEN:FIRSTNAME}) وكذلك تصريف الأفعال وإعراب الأسماء بحسب جنس المشاركين أو عددهم. كما يتيح لك تغيير الرسالة التي توجهها إلى المشارك بناءً على ما إذا كان قد أجاب عن أسئلة أخرى (أو كيف أجاب عنها).
- المعادلات - يضيف EM نوع سؤال جديدًا يسمى معادلة يخزّن نتيجة التعبير. تُحتسب نتائج هذه المعادلات وتُكتب في قاعدة البيانات، حتى لو أخفيتها في الصفحة. لذلك فهي مفيدة لحسابات الدرجات المخفية، والتنقل المبني على معادلات معقدة، والتقييمات، والتقارير التي ينبغي إنشاؤها وإتاحتها بسهولة داخل قاعدة البيانات.
الصلة والصلة المتتالية
أصبح لكل نوع سؤال الآن خيار صلة يتحكم في عرض السؤال. يعالج EM كل معادلة من معادلات الصلة بالترتيب الذي ينبغي أن تظهر به في الاستبيان. إذا كان التعبير صحيحًا (أو مفقودًا - لدعم الاستبيانات القديمة)، فسيُعرض السؤال. وإذا لم يكن ذا صلة، فسيُخفى السؤال، وستُعيَّن قيمته إلى NULL في قاعدة البيانات. وإذا لم تكن هناك أسئلة ذات صلة في مجموعة ما، فسيتم تخطي المجموعة بالكامل.
علاوة على ذلك، إذا كان أي من المتغيرات داخل التعبير غير ذي صلة، فإن التعبير يُقيَّم دائمًا إلى false. وهذا يتيح الصلة المتتالية بحيث لا تضطر إلى كتابة معادلات صلة طويلة جدًا لكل سؤال.
لنفترض أن لديك 5 أسئلة Q1-Q5، وتريد عرض Q2 فقط إذا تمت الإجابة عن Q1، وعرض Q3 فقط إذا تمت الإجابة عن Q2، وهكذا. قد تكون معادلات الصلة كما يلي:
| رمز السؤال | الصلة | السؤال |
|---|---|---|
| Q1 | 1 | ما اسمك؟ |
| Q2 | Q1 | {Q1}، كم عمرك؟ |
| Q3 | Q2 | إذن عمرك {Q2} سنة. هل أنت متزوج؟ |
| Q4 | Q3 == "Y" | {Q1}، منذ متى أنت متزوج؟ |
| Q5 | Q4 | كم عدد الأطفال لديك يا {Q1}؟ |
تعمل حسابات الصلة أيضًا في JavaScript - لذا يمكنك وضع جميع الأسئلة أعلاه في صفحة واحدة وستعمل كما هو متوقع. في الواقع، يستبدل EM بالكامل طريقة معالجة تنسيقات الاستبيان (استبيان كامل مقابل مجموعة مقابل سؤال واحد في كل مرة). فهي تستخدم الآن جميعها محرك التنقل نفسه تمامًا، لذا تعمل بالطريقة نفسها بغض النظر عن نمط الاستبيان.
ما دمت في الصفحة نفسها، فستظل أي بيانات أدخلتها موجودة، لكنها مخفية. لذا إذا أدخلت بعض المعلومات، ثم اخترت خيارًا يجعلها غير ذات صلة، ثم جعلتها ذات صلة مرة أخرى، فستظل إجاباتك متاحة. لكن بمجرد الانتقال إلى صفحة مختلفة، ستُفقد جميع الردود غير ذات الصلة حفاظًا على سلامة مجموعة البيانات.
الصلة على مستوى المجموعة
يدعم Expression Manager أيضًا الصلة على مستوى المجموعة. وهذا يسهّل تنفيذ التكرار. لنفترض أنك تريد جمع معلومات عن ما يصل إلى 10 كيانات (مثل المنتجات أو الأشخاص في أسرة معيشية)، حيث تحدد أولاً عدد الكيانات التي تحتاج إلى متابعة (مثل أن تسأل عن عدد الأشخاص الذين يعيشون في الأسرة، أو أن تطلب من المشاركين تحديد المنتجات التي تعجبهم من قائمة طويلة). بعد معرفة عدد الكيانات التي تحتاج إلى متابعة، يمكنك استخدام الصلة على مستوى المجموعة مثل {count >= 1}، {count >=2}، ... {count >= 10} لكل مجموعة من المجموعات العشر الخاصة بأسئلة المتابعة. وداخل كل مجموعة، يمكنك استخدام منطق شرطي على مستوى السؤال (مثل أسئلة متابعة خاصة بالجنس أو العمر لكل شخص). يتم الجمع بين معادلات الصلة على مستوى السؤال والمجموعة باستخدام AND لتحديد ما يجب عرضه.
التخصيص / التمرير (Tailoring / Piping)
أي شيء داخل الأقواس المعقوفة يُعامل الآن على أنه تعبير (مع استثناء واحد موضح أدناه). تستطيع التعبيرات الوصول إلى جميع LimeReplacementFields وجميع المتغيرات (عبر عدة أسماء مستعارة) وجميع معاملات المعادلات المعتادة (الرياضية والمنطقية والمقارنة) وعشرات الدوال (التي تعمل ديناميكيًا حتى على جانب العميل).
باستخدام هذه المعادلات، يمكنك القيام بأمور مثل:
- عرض رسائل مخصصة للمشاركين بشكل شرطي بناءً على الردود السابقة
- إنشاء تقييمات وعرض نتائج التقييم (أو التفرع الشرطي أو عرض الرسائل) بناءً على تلك النتائج، دون استخدام وحدة التقييمات نفسها
- تصريف الأفعال وإعراب الأسماء داخل الأسئلة والإجابات والتقارير.
- عرض ملخصات للردود قبل صفحة "عرض إجاباتك" في نهاية الاستبيان
المعادلات
يوجد نوع سؤال جديد يسمى معادلة. وهو يشبه أسئلة Boilerplate، إلا أنه يخزن قيمة ما يتم عرضه في قاعدة البيانات. لذا، إذا كان نص سؤال المعادلة يحتوي على حساب تقييم، فسيتم تخزين تلك القيمة في قاعدة البيانات في متغير يمكن عرضه ضمن الإحصاءات العامة أو الخاصة.
وهذا يحل طلبًا شائعًا لتخزين درجات التقييم داخل قاعدة البيانات
الصيغة
أي شيء موجود داخل الأقواس المعقوفة يُعتبر الآن تعبيرًا (مع استثناء واحد: يجب ألا تكون هناك مسافات بيضاء في البداية أو النهاية - وهذا ضروري لضمان عدم محاولة Expression Manager معالجة 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، يقوم معامل الجمع (+) بعملية الجمع إذا كان كلا المعاملين رقميين، لكنه يقوم بالدمج (concatenation) إذا كان كلا الجزأين سلسلتين نصيتين غير رقميتين. ومع ذلك، نوصي باستخدام الدالة join() للدمج والدالة sum() للجمع، لأن ذلك يوضح قصدك بشكل أفضل ويتجنب النتائج غير المتوقعة إذا كنت تتوقع سلاسل نصية لكنك حصلت على أرقام بدلاً من ذلك (أو العكس).
تحذير بشأن عدم التطابق بين الأرقام والسلاسل النصية والمقارنة الأبجدية
عندما تريد مقارنة قيمة باستخدام مقارنات نسبية أو مقارنات مساواة، انتبه إلى عدم تطابق الأنواع. يمكن استخدام القيمة التي أدخلها المستخدم أو رمز الإجابة المحدد كرقم إذا كانت رقمًا بوضوح.
إذا وضعت إحدى القيم بين " فسيؤدي ذلك إلى فرض المقارنة كنص (مقارنة أبجدية). إذا كنت تريد المقارنة رقميًا، فلا تضع الرقم أبدًا بين علامات اقتباس، ".
على سبيل المثال، Q0.NAOK > "50" تكون صحيحة إذا كان Q0.NAOK سؤالاً رقميًا قيمته 9. والسبب هو أن المعامل > سيفترض أنها مقارنة أبجدية وليست رقمية.
للتأكد من مقارنة قيمة عددية صحيحة، يمكنك استخدام intval(Q0.NAOK) > 50، مع تذكر أنه إذا لم يكن Q0.NAOK رقمًا (فارغًا أو سلسلة نصية)، فإن intval(Q0.NAOK) == 0. ولمقارنة قيمة نصية ("A" < "B") استخدم strcmp مباشرة : strcmp(Q0.NAOK,"B") أو strcmp(Q0.NAOK,"A5").
تنبيه بشأن استخدام معامل الإسناد (=)
لاحظ أنه يجب تجنب استخدام معاملات الإسناد ما لم تكن هناك ضرورة قصوى، لأنها قد تسبب آثارًا جانبية غير متوقعة. على سبيل المثال، إذا غيّرت قيمة رد سابق، فلن يُعاد حساب منطق الصلة المتتالية والتحقق من الصحة بين ذلك السؤال والسؤال الحالي، وقد ينتهي بك الأمر ببيانات غير متسقة داخليًا (مثل أسئلة تبقى مجابة بينما كان يجب تعيينها إلى NULL، أو أسئلة يتم تخطيها بينما كان يجب الإجابة عنها). بشكل عام، إذا كنت تريد إسناد قيمة إلى متغير، فيجب عليك إنشاء سؤال من نوع معادلة، واستخدام تعبير لتعيين قيمته. ومع ذلك، هناك بعض الحالات النادرة التي يحتاج فيها المستخدمون فعلاً إلى هذا المعامل، لذلك جعلناه متاحًا.
لتنبيهك بشأن هذا المعامل، يظهر باللون الأحمر داخل معادلات الصيغة (حتى لا تخلط بينه وبين "==")
استخدام معامل الإسناد
الأسباب الرئيسية التي قد تدفعك لاستخدام الإسناد هي:
- تحتاج إلى تعيين القيمة الافتراضية لسؤال لا يقبل القيم الافتراضية عبر المعادلة (مثل قائمة الاختيار الراديوي، حيث تتيح لك الواجهة اختيار أحد خيارات الإجابة، لكنها لا تتيح لك إدخال معادلة). ومع ذلك، كن حذرًا، لأن LimeSurvey لن يتمكن من التحقق من أن معادلتك تولّد إحدى الإجابات المسموح بها لذلك السؤال.
- تحتاج إلى تغيير الرد على سؤال سابق قسرًا بناءً على رد لاحق
- تحتاج إلى حصة معقدة : باستخدام سؤال اختيار فردي مخفي واحد للحصة وتعيينه باستخدام الإسناد
- إلخ...
يمكنك استخدام كل نظام Expression Manager لهذا الغرض.
بعض الأمثلة:
- تعيين إجابة سؤال نص قصير بأحرف صغيرة :
{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 (مثل TOKEN:FIRSTNAME وTOKEN:ATTRIBUTE_5) (فقط للاستبيانات غير المجهولة).
- QCODE.shown - القيمة المعروضة للإجابة (مثل "نعم") باستخدام مدير التعبيرات.
- جميع قيم {XXX} المستخدمة في القوالب.
- في نص السؤال، يمكنك استخدام {QID} ليتم استبداله بمعرف السؤال، و{SGQ} ليتم استبداله بقيمة SGQA الخاصة بالسؤال
بالإضافة إلى ذلك، يتيح لك مدير التعبيرات الإشارة إلى المتغيرات باستخدام رمز السؤال (العمود 'title' في جدول الأسئلة ضمن قاعدة البيانات). وهذا هو أيضاً اسم المتغير المستخدم عند تصدير بياناتك إلى SPSS أو R أو SAS. على سبيل المثال، إذا كانت لديك أسئلة عن الاسم والعمر والنوع، فيمكنك تسمية هذه المتغيرات name وage وgender بدلاً من 12345X13X22 و12345X13X23 و12345X13X24. هذا يجعل المعادلات أسهل للجميع في القراءة والتحقق من منطقها، كما يتيح تغيير ترتيب الأسئلة دون الحاجة إلى تتبع أرقام المجموعات أو الأسئلة.
مهم: من الآمن فقط الإشارة إلى المتغيرات الموجودة في الصفحات أو الأسئلة السابقة.
علاوة على ذلك، يتيح لك مدير التعبيرات الوصول إلى العديد من خصائص السؤال:
| الصيغة | المعنى | مثال | نتيجة المثال |
|---|---|---|---|
| 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 | اسم جافاسكريبت الصحيح للسؤال، سواء تم تعريفه في هذه الصفحة أو خارجها | {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 . '_' . SubQuestionCode . '_' . 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 | سؤال نص ثابت (Boilerplate) | 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' حصراً ضمن الخيارين المتقدمين "معادلة التحقق من صحة السؤال بالكامل" و"معادلة التحقق من صحة السؤال الفرعي". ويتوسع إلى أسماء المتغيرات الخاصة بكل خلية داخل تلك الأسئلة. لذلك، إذا أردت التأكد من أن كل إدخال أكبر من ثلاثة، فعليك تعيين "معادلة التحقق من صحة السؤال الفرعي" على (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 ....
- nosq_X - حيث X هو معرّف صف أو عمود. يتم تحديد الأسئلة الفرعية غير المطابقة للنمط X فقط. لاحظ أن البحث يتم على المعرّف الكامل للرمز، ثم تتطابق nosq_X ولا تشمل الأسئلة الفرعية nX وX وXn
أمثلة:
- هل تمت الإجابة عن أي جزء من السؤال؟ {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)}
- ما هو مجموع الصف C في q4؟ {sum(that.q4.sq_C.NAOK)}
- ما هو مجموع العمود 2 في q4؟ {sum(that.q4.sq_2.NAOK)}
يمكن استخدام المتغيرين 'self' و'that' في أي معادلة صلة أو تحقق من الصحة أو تخصيص.
التنبيه الوحيد هو أنه عند استخدام ميزة عرض ملف المنطق، ستعرض لك القيمة الموسّعة لـ 'self' و'that'. يتيح لك ذلك رؤية المعادلة الفعلية التي سيتم إنشاؤها ليتمكن مدير التعبيرات (وأنت) من التحقق من وجود المتغيرات. قد يبدو هذا محيّراً لأنك قد ترى معادلات طويلة جداً. لكن إذا قمت بتحرير السؤال، فسترى المعادلة الأصلية التي تستخدم 'self' و/أو 'that'
لاحظ أيضًا أنه لا ينبغي استخدام هذه المتغيرات في الحالتين التاليتين: (أ) إذا كنت تريد تسمية كل متغير مستخدم في المعادلة بشكل صريح، أو (ب) إذا كنت تستخدم متغيرات لا تحتوي على أسئلة فرعية (مثل أسئلة الإجابة الواحدة). في هذه الحالات، تكون إضافة البادئة 'that' إلى المتغير مبالغة غير ضرورية، وقد تحصل على نتائج غير متوقعة.
استخدام NAOK
NAOK --> "غير قابل للتطبيق" (NA) أمر مقبول (OK)
يعني استخدام NAOK أن جميع المتغيرات أو بعضها غير ذي صلة (أي أن "غير قابل للتطبيق" (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). وإذا كان السؤال الفرعي مخفيًا: يعيد Expression Manager سلسلة فارغة.
بدون NAOK: إذا كان سؤال واحد أو سؤال فرعي واحد مخفيًا، يعيد Expression Manager دائمًا سلسلة فارغة، وهو ما يعادل القيمة false.
يستخدم .shown دائمًا نظام NAOK (سلسلة فارغة إذا كان السؤال مخفيًا)، ولكن إذا كنت بحاجة إلى رمز الإجابة، فمن الأفضل دائمًا إضافة .NAOK بعد كود السؤال، إلا إذا كنت بحاجة إلى غير ذلك وتعرف ما تفعله.
يتوفر مثال ومعلومات إضافية في تجاوز الشروط المتتالية
الوصول إلى الدوال
يوفر Expression Manager إمكانية الوصول إلى الدوال الرياضية ودوال السلاسل النصية والدوال المعرّفة من قبل المستخدم، كما هو موضح أدناه. ولهذه الدوال مكافئات في PHP وJavaScript بحيث تعمل بالطريقة نفسها على جانب الخادم (PHP) وجانب العميل (JavaScript). ومن السهل إضافة دوال جديدة.
الدوال المنفذة
الدوال التالية متاحة حاليًا:
| الدالة | المعنى | الصيغة |
|---|---|---|
| abs | القيمة الملطقة | number abs(number) |
| acos | جيب التمام القوسي | number acos(number) |
| addslashes | اقتباس سلسلة بشرطات مائلة | string addslashes(string) |
| asin | قوس جيبي | number asin(number) |
| atan | قوس الظل | number atan(number) |
| atan2 | قوس الظل من متغيرين | number atan2(number, number) |
| ceil | قرب الكسور إلى أعداد صحيحة | number ceil(number) |
| checkdate | إرجاع صحيح (1) إذا كان التاريخ صالحًا في التقويم الميلادي | bool checkdate(month,day,year) |
| convert_value | تحويل قيمة رقمية باستخدام جدول إدخال وجدول إخراج من القيم الرقمية | number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList) |
| cos | جيب التمام | number cos(number) |
| count | عد عدد الأسئلة المجاب عنها (غير الفارغة) في القائمة | number count(arg1, arg12, ..., argN) |
| countif | عد عدد الأسئلة المجاب عنها في القائمة والمساوية للوسيط الأول | number countif(matches, arg1, arg2, ... argN) |
| countifop | عد عدد الأسئلة المجاب عنها في القائمة التي تستوفي المعيار (arg op value) | number countifop(op, value, arg1, arg2, ... argN) |
| date | نسق وقت/تاريخ محلي | string date(format [, timestamp=time()]) |
| exp | إحسب الأس | number exp(number) |
| fixnum | عرض الأرقام مع الفاصلة كفاصل عشري عند الحاجة | string fixnum(number) |
| floor | قرب الكسور إلى اعداد صحيحة | number floor(number) |
| gmdate | نسق توقيت/تاريخ جرينتش | string gmdate(format [, timestamp=time()]) |
| html_entity_decode | تحويل جميع كيانات HTML إلى الأحرف المقابلة لها (يستخدم دائمًا ENT_QUOTES و UTF-8) | string html_entity_decode(string) |
| htmlentities | تحويل جميع الأحرف القابلة للتحويل إلى كيانات HTML (يستخدم دائمًا ENT_QUOTES و UTF-8) | string htmlentities(string) |
| expr_mgr_htmlspecialchars | تحويل الأحرف الخاصة إلى كيانات HTML (يستخدم دائمًا ENT_QUOTES و UTF-8) | string htmlspecialchars(string) |
| expr_mgr_htmlspecialchars_decode | تحويل كيانات HTML الخاصة مرة أخرى إلى أحرف (يستخدم دائمًا ENT_QUOTES و UTF-8) | string htmlspecialchars_decode(string) |
| idate | نسق الوقت / التاريخ المحلي كعدد صحيح | string idate(string [, timestamp=time()]) |
| if (Updated in 3.0.2 ) | if بأسلوب Excel: if(test,result_if_true[,result_if_false = ""]) | if(test,result_if_true[,result_if_false = ""]) |
| implode | ضم عناصر المصفوفة مع سلسلة | string implode(glue,arg1,arg2,...,argN) |
| intval | احصل على قيمة عدد صحيح من متغير | int intval(number [, base=10]) |
| is_empty | تحديد ما إذا كان المتغير يعتبر فارغًا | bool is_empty(var) |
| is_float | جد ما إذا كان نوع المتغير عددًا عشريًا | bool is_float(var) |
| is_int | جد ما إذا كان نوع المتغير عددًا صحيحًا | bool is_int(var) |
| is_nan | جد ما إذا كانت القيمة ليست رقمًا | bool is_nan(var) |
| is_null | جد ما إذا كان المتغير NULL | bool is_null(var) |
| is_numeric | جد ما إذا كان المتغير رقمًا أو سلسلة رقمية | bool is_numeric(var) |
| is_string | جد ما إذا كان نوع المتغير سلسلة | bool is_string(var) |
| join (New in 2.0 build 130129) | ضم العناصر في سلسلة جديدة | join(arg1, arg2, ... argN) |
| list | إرجاع قائمة مفصولة بفواصل للقيم غير الفارغة | string list(arg1, arg2, ... argN) |
| listifop (New in 3.16.1 ) | إرجاع قائمة مفصولة بـ 'glue' لخاصية السؤال المحددة (retProp) من الأسئلة في القائمة التي تستوفي المعيار (cmpProp op value) | string listifop(cmpProp, op, value, retProp, glue, sgqa1, sgqa2, ... sgqaN) |
| log | اللوغاريتم للعدد بالنسبة للأساس إذا تم تحديده، أو اللوغاريتم الطبيعي. | number log(number,base=e) |
| ltrim | إزالة المسافات البيضاء (أو أحرف أخرى) من بداية السلسلة | string ltrim(string [, charlist]) |
| max | جد اكبر قيمة | number max(arg1, arg2, ... argN) |
| min | جد اقل قيمة | number min(arg1, arg2, ... argN) |
| mktime | الحصول على الطابع الزمني UNIX لتاريخ ما (جميع الوسائط الستة اختيارية) | number mktime([hour [, minute [, second [, month [, day [, year ]]]]]]) |
| modulo-function | دالة باقي القسمة غير مدعومة بعد. يمكنك استخدام الدالة floor() بدلًا منها | floor(x/y)==(x/y) |
| nl2br | إدراج فواصل أسطر HTML قبل جميع الأسطر الجديدة في السلسلة | string nl2br(string) |
| number_format | تنسيق رقم مع آلاف مجمعة | string number_format(number) |
| pi | احصل على قيمة ط | number pi() |
| pow | التعبير الأسي | number pow(base, exp) |
| quoted_printable_decode | تحويل سلسلة quoted-printable إلى سلسلة 8 بت | string quoted_printable_decode(string) |
| quoted_printable_encode | تحويل سلسلة 8 بت إلى سلسلة quoted-printable | string quoted_printable_encode(string) |
| quotemeta | اقتباس الأحرف الفوقية | string quotemeta(string) |
| rand | انتج عدد صحيح عشوائي، انظر هذا المثال | int rand() OR int rand(min, max) |
| regexMatch | مقارنة سلسلة بـالتعبير المنتظم | bool regexMatch(pattern,input) |
| round | تقريب رقم إلى دقة اختيارية | number round(val [, precision]) |
| rtrim | إزالة المسافات البيضاء (أو أحرف أخرى) من نهاية السلسلة | string rtrim(string [, charlist]) |
| sin | الجيب | number sin(arg) |
| sprintf | الرجوع بنص منسق | string sprintf(format, arg1, arg2, ... argN) |
| sqrt | الجذر التربيعي | number sqrt(arg) |
| stddev | حساب الانحراف المعياري للعينة لقائمة الأرقام | number stddev(arg1, arg2, ... argN) |
| str_pad | ملء سلسلة حتى طول معين بسلسلة أخرى | string str_pad(input, pad_length [, pad_string]) |
| str_repeat | كرر سلسلة حرفية | string str_repeat(input, multiplier) |
| str_replace | استبدال جميع مرات ظهور سلسلة البحث بسلسلة الاستبدال | string str_replace(search, replace, subject) |
| strcasecmp | مقارنة سلسلة ثنائية غير آمنة لحالة الأحرف | int strcasecmp(str1, str2) |
| strcmp | مقارنة سلسلة آمنة الثنائية | int strcmp(str1, str2) |
| strip_tags | تجريد علامات HTML و PHP من السلسلة | string strip_tags(str, allowable_tags) |
| stripos | إيجاد موضع أول ظهور لسلسلة يونيكود دون مراعاة حالة الأحرف (يبدأ من 0، ويرجع false إذا لم يوجد) | int stripos(haystack, needle [, offset=0]) |
| stripslashes | لا إقتباس لسلسلة مقتبسة | string stripslashes(string) |
| stristr | strst غير حساس لحالة الأحرف | string stristr(haystack, needle [, before_needle=false]) |
| strlen | هات طول سلسلة حرفية | int strlen(string) |
| strpos | إيجاد موضع أول ظهور لسلسلة يونيكود (يبدأ من 0، ويرجع false إذا لم يوجد) | int strpos(haystack, needle [ offset=0]) |
| strrev | اعكس سلسلة حرفيو | string strrev(string) |
| strstr | البحث عن التواجد الأول لسلسلة | string strstr(haystack, needle[, before_needle=false]) |
| strtolower | تحويل السلسلة إلى أحرف صغيرة | string strtolower(string) |
| strtotime | تحليل أي وصف نصي إنجليزي للتاريخ والوقت تقريبًا إلى طابع زمني UNIX | int strtotime(string) |
| strtoupper | تحويل السلسلة إلى أحرف كبيرة | string strtoupper(string) |
| substr | إرجاع جزء من سلسلة يونيكود | string substr(string, start [, length]) |
| sum | احسب مجموع القيم في مصفوفة | number sum(arg1, arg2, ... argN) |
| sumifop | جمع قيم الأسئلة المجاب عنها في القائمة التي تستوفي المعيار (arg op value) | number sumifop(op, value, arg1, arg2, ... argN) |
| tan | الظل | number tan(arg) |
| time | إرجاع الطابع الزمني UNIX الحالي | number time() |
| trim | إزالة المسافات البيضاء (أو أحرف أخرى) من بداية السلسلة ونهايتها | string trim(string [, charlist]) |
| ucwords | تحويل الحرف الأول من كل كلمة في السلسلة إلى حرف كبير | string ucwords(string) |
| unique | إرجاع صحيح إذا كانت جميع الاستجابات غير الفارغة فريدة | boolean unique(arg1, ..., argN) |
الدوال المخطط لها أو قيد الدراسة
هناك دوال أخرى مخطط لها (أو قيد الدراسة) ولكنها لم تُنفذ بعد، وتشمل ما يلي. بعضها موجود للتوافق مع الإصدارات السابقة مع أداة استبيانات أخرى.
| الصيغة | المعنى | تعليقات |
|---|---|---|
| e() | تُرجع قيمة e | |
| formatDate(X,PAT) | تُرجع القيمة النصية للتاريخ X منسقة وفق نمط تنسيق التاريخ PAT في Java | |
| formatNumber(X,PAT) | تُرجع القيمة النصية للرقم X منسقة وفق نمط تنسيق الأرقام PAT في Java | |
| getAnsOption(X) | برنامج مساعد أساسي ExpressionAnswerOptions | |
| getAnsOption(X,Y) | برنامج مساعد أساسي ExpressionAnswerOptions | |
| getRelevance(X) | تُرجع معادلة الصلة للسؤال X | |
| getStartTime() | تُرجع التاريخ المقابل لوقت النظام عند بدء المقابلة | |
| getType(X) | تُرجع اسم نوع البيانات كنص - مثل *NA* إذا كانت isNA() | |
| gotoFirst() | تنتقل إلى أول مجموعة من الأسئلة ذات الصلة - وهذا يخالف السير العادي للنظام | |
| gotoNext() | تنتقل إلى مجموعة الأسئلة ذات الصلة التالية - وهذا يخالف السير العادي للنظام | |
| gotoPrevious() | تنتقل إلى مجموعة الأسئلة ذات الصلة السابقة - وهذا يخالف السير العادي للنظام | |
| isAsked(X) | تُرجع true إذا لم تكن الإجابة من النوع *NA* أو *INVALID* أو *UNASKED* | |
| isInvalid(X) | تُرجع true إذا كانت الإجابة من النوع *INVALID* | |
| isNA(X) | تُرجع true إذا كانت الإجابة من النوع *NA* | |
| isNotUnderstood(X) | تُرجع true إذا كانت الإجابة من النوع *HUH* | |
| isRefused(X) | تُرجع true إذا كانت الإجابة من النوع *REFUSED* | |
| isSpecial(X) | تُرجع true إذا كانت الإجابة من النوع *UNASKED* أو *NA* أو *REFUSED* أو *INVALID* أو *UNKNOWN* أو *HUH* | |
| isUnknown(X) | تُرجع true إذا كانت الإجابة من النوع *UNKNOWN* | |
| jumpTo(X) | تنتقل إلى المجموعة التي تحتوي على السؤال المحدد -- وهذا يخالف السير العادي للنظام | |
| jumpToFirstUnasked() | تنتقل إلى أول سؤال لم يُطرح |
|
| lastIndexOf(X,Y) | تُرجع آخر فهرس (يبدأ من 0) للسلسلة Y في السلسلة X. تُرجع -1 إذا لم تكن Y موجودة ضمن X | |
| list(X,...) | سلسلة نصية تحتوي على قائمة مفصولة بفواصل من القيم الموجبة، مع الفصل بين آخر قيمتين بكلمة «و» | |
| mean(X,...) | تُرجع المتوسط الحسابي لقائمة من القيم | |
| numAnsOptions(X) | تُرجع عدد خيارات الإجابة الخاصة بالسؤال X | |
| orlist(X,...) | سلسلة نصية تحتوي على قائمة مفصولة بفواصل من القيم الموجبة، مع الفصل بين آخر قيمتين بكلمة «أو» | |
| parseDate(X,PAT) | تُرجع قيمة التاريخ للسلسلة X بعد تحليلها وفق نمط تنسيق التاريخ PAT في Java | |
| parseNumber(X,PAT) | تُرجع القيمة الرقمية للسلسلة X بعد تحليلها وفق نمط تنسيق الأرقام PAT في Java | |
| showAllResponsesExcept( questionList,attributeList,attributeTitleList) | ؛ attributeList = قائمة الخصائص مفصولة بالرمز | (مثل رقم السؤال والعنوان والنص والنوع - لتتمكن من تحديد ما سيُعرض)؛ attributeTitleList = قائمة عناوين الجدول مفصولة بالرمز |، لتتمكن من ترجمة التقرير. | |
| showTheseResponses( questionList,attributeList,attributeTitleList) | ؛ attributeList = قائمة الخصائص مفصولة بالرمز | (مثل رقم السؤال والعنوان والنص والنوع - لتتمكن من تحديد ما سيُعرض)؛ attributeTitleList = قائمة عناوين الجدول مفصولة بالرمز |، لتتمكن من ترجمة التقرير. |
يعرف Expression Manager أي المتغيرات محلية
لكي يبني Expression Manager شيفرة JavaScript الخاصة بالصفحة بشكل صحيح، يحتاج إلى معرفة المتغيرات المعيّنة في الصفحة ومعرّف JavaScript الخاص بكل منها (مثلًا لاستخدامه في document.getElementById(x)). كما يجب أن يعرف المتغيرات المعيّنة في صفحات أخرى (ليتأكد من وجود حقول <input type='hidden' value='x'> المطلوبة وامتلائها بالقيم).
الشروط المتسلسلة
إذا كان أي من المتغيرات غير ذي صلة، تصبح المعادلة بأكملها غير ذات صلة (false). على سبيل المثال، في الجدول التالي، تعني N/A أن أحد المتغيرات لم يكن ذا صلة
| العامل | مثال | a | b | النتيجة |
|---|---|---|---|---|
| + (unary) | +a | N/A | false | |
| ! | !a | N/A | false | |
| == (or eq) | a == b | N/A | 5 | false |
| == (or eq) | a == b | N/A | 0 | false |
| == (or eq) | a == b | N/A | N/A | false |
| != (or ne) | a != b | N/A | 5 | false |
| != (or ne) | a != b | N/A | N/A | false |
| != (or ne) | a != b | N/A | 0 | false |
| > (or gt) | a > b | N/A | 5 | false |
| >= (or ge) | a >= b | N/A | 5 | false |
| < (or lt) | a < b | N/A | 5 | false |
| <= (or 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 (أو فارغ) | 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 is OK). في هذه الحالة يحدث السلوك التالي. لنفترض أن لديك المتغير q1.NAOK
- لا تتم إضافة q1 إلى عبارة LEManyNA()
- ستواصل LEMval('q1') التحقق مما إذا كان الرد ذا صلة، وستُرجع '' إذا لم يكن كذلك (وبذلك تُتجاهل الردود الفردية غير ذات الصلة، دون أن تُبطل التعبير بأكمله).
إذن، حل مشكلة المجموع التراكمي هو استخدام المعادلة sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).
يتيح استخدام اللاحقة .NAOK أيضًا لمؤلفي الاستبيانات تصميم استبيانات ذات عدة مسارات محتملة تتلاقى لاحقًا في مسارات مشتركة. على سبيل المثال، لنفترض أن المشاركين أجابوا عن الاستبيان بطريقة خارج النطاق الطبيعي للردود. يمكن للمؤلف تنبيههم بأنهم قد لا يحصلون على نتائج صالحة، وسؤالهم هل يرغبون فعلًا في متابعة الاستبيان. إذا أجابوا بنعم، تُعرض بقية الأسئلة. وسيتحقق الشرط الخاص بـ«بقية الأسئلة» مما إذا كانت الردود الأولية ضمن النطاق الطبيعي أو (OR) ما إذا أجاب المشارك بنعم عن السؤال الذي لا يكون ذا صلة إلا إذا أجاب خارج النطاق الطبيعي.
كيف يدعم Expression Manager التخصيص الدقيق الشرطي؟
فيما يلي مثال على التخصيص الدقيق (حيث تعني Question Type=='expr' معادلة):
| كود السؤال | الصلة | نوع السؤال | السؤال |
|---|---|---|---|
| name | 1 | text | ما اسمك؟ |
| age | 1 | text | كم عمرك؟ |
| badage | !is_empty(age) | expr | {(age<16) or (age>80)} |
| agestop | badage | message | عذرًا، {name}، أنت {if( (age<16),'young',if( (age>80),'old','middle-aged') ) } جدًا لهذا الاختبار. |
| 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} |
يمكن وضع كل هذه الأسئلة في صفحة واحدة (أي في المجموعة نفسها)، ولن تُعرض سوى الأسئلة ذات الصلة. علاوة على ذلك، وأثناء إدخال أعمار الأطفال، سيتم تحديث التعبير sum() في السؤال الأخير ديناميكيًا في الصفحة.
يوفر Expression Manager هذه الوظيفة عن طريق إحاطة كل تعبير بعنصر <span> مُسمّى. وفي كل مرة تتغير فيها قيمة، يعيد حساب التعبير الذي يجب أن يظهر في عنصر <span> هذا ويعيد توليد العرض. يمكنك أن تضع عشرات أو حتى مئات من هذه التعبيرات المخصصة في الصفحة نفسها، وستعيد الصفحة عرضها جميعًا في تحديث واحد للشاشة.
مطابقة وظائف LimeSurvey 1.91+ مع وظائف Expression Manager
| الميزة القديمة | الميزة الجديدة | تعليقات |
|---|---|---|
| الشروط | الصلة | يمكنك استخدام معادلات شرطية معقدة جدًا، والوصول إلى نطاق أوسع من المتغيرات |
| التقييمات | المعادلة | يمكن إعادة هيكلة أي درجات تقييم في صورة معادلة. وهذا يضمن كتابة الدرجة في قاعدة البيانات، ويتيح لك أيضًا رؤية التغيرات الديناميكية في قيمة الدرجة في الصفحة الحالية |
| الاستبدالات | Expression Manager | يأخذ المحرك الأساسي النص المُدخل ويعامل كل ما بين الأقواس المعقوفة على أنه تعبير - وبذلك يتعامل مع جميع أنواع الاستبدالات السابقة. ولتجنب إفساد شيفرة JavaScript المضمّنة، لا يعالج Expression Manager المحتوى بين الأقواس المعقوفة إلا إذا (أ) لم تكن هناك مسافة فارغة في بدايته أو نهايته داخل الأقواس المعقوفة - مثلًا {expr} تعبير، لكن { expr} و{expr } و{ expr } ليست تعبيرات. كما أن Expression Manager لا يعالج المحتوى داخل السلاسل النصية الخاصة به (مثلًا {list('hi','there {braces}')} ينتج "hi there {braces}"). ويتجاهل أيضًا الأقواس المعقوفة المهرّبة (مثلًا \{this is not an expression\}) |
| التحقق من الصحة | Expression Manager | الخطة هي أخذ خصائص السؤال الحالية للحد الأدنى/الأقصى ومعالجتها عبر Expression Manager. وبذلك يمكن أن تكون قيم الحد الأدنى/الأقصى نفسها تعبيرات |
تمييز الصيغة
للمساعدة في إدخال التعبيرات والتحقق منها، يوفر EM تمييز الصيغة بالميزات التالية:
أنواع تمييز الصيغة ومعانيها
| اللون | عينة | المعنى | تلميح | ملاحظات |
|---|---|---|---|---|
| خلفية بيج | عينة | المعادلة بأكملها | لا يوجد | أي نص داخل أقواس معقوصة يتم التعرف عليه كمعادلة (أي لا توجد مسافة فارغة في بدايته أو نهايته) يتم تلوينه بخلفية بيج لتمييزه عن النص المحيط به |
| نص أحمر غامق | عينة | خطأ | شرح للخطأ | قد يكون متغيرًا غير معروف أو خطأ في دالة، ... قد يتعطل الاستبيان بالكامل، ولا يظهر هذا للمستخدم العام. |
| نص أزرق | عينة | اسم دالة | المعنى وبناء الجملة المسموح به | تظهر أسماء الدوال، أو ما يجب أن يكون دالة لأنه متبوع بقوس فتح، بنص أزرق غامق. تعرض التلميحات المعنى وبناء الجملة المسموح به للدالة. |
| نص رمادي | عينة | سلسلة نصية | لا يوجد | تظهر السلاسل النصية المحاطة بعلامات اقتباس مفردة أو مزدوجة بنص رمادي |
| نص سماوي | عينة | متغير تم تعيينه في الصفحة نفسها، | [الاسم أو رمز SGQA]: السؤال؛ القيمة؛ قائمة الإجابات التي تعرض الرموز لكل قيمة | يظهر أي متغير تم تعيينه في الصفحة نفسها للسؤال الحالي بنص سماوي، مما يعني أنه يمكن تحديثه في جافاسكريبت. يعرض التلميح اسمه والسؤال الفعلي وقيمته الحالية (أو فارغًا إذا لم تُعيَّن). إذا كان نوع السؤال يتوقع إجابات من مجموعة قيم محددة، فسيتم عرض تعيين الرموز إلى قيم العرض. |
| نص أخضر | عينة | متغير تم تعيينه في صفحة سابقة | [الاسم أو رمز SGQA]: السؤال؛ القيمة؛ قائمة الإجابات التي تعرض الرموز لكل قيمة | يظهر أي متغير تم تعيينه في صفحة سابقة بنص أخضر غامق. يعرض التلميح اسمه والسؤال الفعلي وقيمته الحالية (أو فارغًا إذا لم تُعيَّن). إذا كان نوع السؤال يتوقع إجابات من مجموعة قيم محددة، فسيتم عرض تعيين الرموز إلى قيم العرض. |
| نص وردي غامق | عينة | متغير تم تعيينه في صفحة لاحقة في العموم: يكون فارغًا عند بدء الاستبيان، ولكن يمكن ملؤه عبر الفهرس أو الانتقال إلى السابق | [الاسم أو رمز SGQA]: السؤال؛ القيمة؛ قائمة الإجابات التي تعرض الرموز لكل قيمة | يظهر أي متغير تم تعيينه في صفحة تالية بنص وردي غامق. يعرض التلميح اسمه والسؤال الفعلي وقيمته الحالية (أو فارغًا إذا لم تُعيَّن). إذا كان نوع السؤال يتوقع إجابات من مجموعة قيم محددة، فسيتم عرض تعيين الرموز إلى قيم العرض. |
| نص بني غامق | عينة | قيمة استبدال في Lime | القيمة | تظهر سلاسل الاستبدال في Lime (مثل {TOKEN:xxx} و{PRIVACY_MESSAGE}) بنص بني غامق. |
| نص أحمر | عينة | عامل الإسناد (=) | رسالة تحذير | إذا استخدمت عامل الإسناد (=) فسيظهر هذا العامل بنص أحمر. الهدف من ذلك المساعدة في منع إعادة إسناد القيم عن طريق الخطأ عندما كنت تقصد فعلاً التحقق مما إذا كان a == b بدلاً من تعيين قيمة a = b. |
| نص أسود عادي | عينة | علامات الترقيم | لا يوجد | تظهر جميع علامات الترقيم الأخرى داخل التعبير بنص أسود عادي. |
| نص داخل مربع أحمر | يحيط خط أحمر غامق بالخطأ | خطأ في بناء الجملة | وصف الخطأ | يتم عرض أي أخطاء في بناء الجملة يتم اكتشافها بإحاطة الخطأ بمربع أحمر. يعرض التلميح الخطأ. تشمل الأمثلة الأقواس غير المتطابقة، واستخدام دوال غير معرّفة، وتمرير عدد خاطئ من المعاملات إلى الدوال، والتعبيرات سيئة البناء (مثل غياب العوامل بين المتغيرات)، ومحاولة تعيين قيمة جديدة لمتغير للقراءة فقط، ومحاولة تعيين قيم لما ليس متغيرات، أو استخدام بناء جملة غير مدعوم. لاحظ أن نظام اكتشاف أخطاء بناء الجملة قد يبلغ عن خطأ واحد فقط في التعبير حتى لو وُجدت عدة أخطاء؛ ولكن إذا تم اكتشاف أي أخطاء، فسيتم عرض خطأ واحد على الأقل. |
قراءات إضافية
نماذج استبيانات Expression Manager
حالات الاستخدام والأدلة التعليمية
أمثلة خطوة بخطوة
دوال الإحصاء في Expression Manager
مرجع للمطورين










