SurveyJS

Source: demos/survey_js

PsyNet integrates with SurveyJS, a flexible survey design tool that is particularly good for implementing questionnaires and multi-response interfaces. One uses the SurveyJSControl class, and passes it a JSON-style dictionary which contains all the survey specifications.

The recommended way to design a SurveyJS survey is to use their free Survey Creator tool. You design your survey using the interactive editor. Once you are done, click the “JSON Editor” tab. Copy and paste the provided JSON into the design argument of your SurveyJSControl. You may need to update a few details to match Python syntax, for example replacing true with True; your syntax highlighter should flag up points that need updating. That’s it!

Note, near the bottom of the script, the use of the argument bot_response. This is used to tell PsyNet how to simulate the response of a participant to a given page, and is most commonly used by automated tests. We provide it with a function that generates the kind of questionnaire response that a real participant might produce. In the current example the function just hard-codes a value, but alternatively this function could include a random component, and it could refer to the state of the participant itself.

import psynet.experiment
from psynet.consent import NoConsent
from psynet.modular_page import ModularPage, SurveyJSControl
from psynet.page import DebugResponsePage, SuccessfulEndPage
from psynet.timeline import Timeline


class Exp(psynet.experiment.Experiment):
    label = "SurveyJS demo"
    initial_recruitment_size = 1

    timeline = Timeline(
        NoConsent(),
        ModularPage(
            "example_1",
            "Here's a simple SurveyJS example.",
            SurveyJSControl(
                {
                    "logoPosition": "right",
                    "pages": [
                        {
                            "name": "page1",
                            "elements": [
                                {
                                    "type": "text",
                                    "name": "name",
                                    "title": "Please enter your name",
                                },
                                {
                                    "type": "dropdown",
                                    "name": "gender",
                                    "title": "Select your gender",
                                    "choices": [
                                        {"value": "male", "text": "Male"},
                                        {"value": "female", "text": "Female"},
                                        {"value": "non_binary", "text": "Non-binary"},
                                        {
                                            "value": "prefer_not_to_say",
                                            "text": "Prefer not to say",
                                        },
                                    ],
                                    "showOtherItem": True,
                                    "otherText": "Other (please specify)",
                                },
                                {
                                    "type": "ranking",
                                    "name": "animal_preferences",
                                    "title": "Please rank these in order of preference",
                                    "choices": [
                                        {"value": "cats", "text": "Cats"},
                                        {"value": "dogs", "text": "Dogs"},
                                        {"value": "goldfish", "text": "Goldfish"},
                                    ],
                                },
                                {
                                    "type": "rating",
                                    "name": "weather",
                                    "title": "Please rate your weather today.",
                                    "rateValues": [
                                        {"value": "1", "text": "1"},
                                        {"value": "2", "text": "2"},
                                        {"value": "3", "text": "3"},
                                        {"value": "4", "text": "4"},
                                        {"value": "5", "text": "5"},
                                    ],
                                    "minRateDescription": "Awful",
                                    "maxRateDescription": "Amazing",
                                },
                            ],
                        },
                        {
                            "name": "page2",
                            "elements": [
                                {
                                    "type": "text",
                                    "name": "final_question",
                                    "title": "Here's a final question before you submit the questionnaire...",
                                }
                            ],
                        },
                    ],
                },
            ),
            time_estimate=5,
            bot_response=lambda: {
                "name": "Beatrix",
                "gender": "Female",
                "animal_preferences": ["goldfish", "dogs", "cats"],
                "weather": "5",
                "final_question": "Goodbye",
            },
        ),
        DebugResponsePage(),
        SuccessfulEndPage(),
    )