Skip to content

Experiment views

experiment.views#

get_associated_blocks(pk_list) #

get all the experiment objects registered in an Experiment field

Source code in experiment/views.py
def get_associated_blocks(pk_list):
    """get all the experiment objects registered in an Experiment field"""
    return [Block.objects.get(pk=pk) for pk in pk_list]

get_block(request, slug) #

Get block data from active block with given :slug DO NOT modify session data here, it will break participant_id system (/participant and /block/ are called at the same time by the frontend)

Source code in experiment/views.py
def get_block(request: HttpRequest, slug: str) -> JsonResponse:
    """Get block data from active block with given :slug
    DO NOT modify session data here, it will break participant_id system
       (/participant and /block/<slug> are called at the same time by the frontend)"""
    block = block_or_404(slug)
    class_name = ""
    active_language = get_language()

    if active_language.startswith("zh"):
        class_name = "chinese"

    participant = get_participant(request)
    session = Session(block=block, participant=participant)

    playlist = block.playlists.first()
    if playlist:
        session.playlist = playlist

    session.save()

    # create data
    block_data = {
        **serialize_block(block),
        "theme": serialize_theme(block.theme_config) if block.theme_config else None,
        "class_name": class_name,  # can be used to override style
        "rounds": block.rounds,
        "bonus_points": block.bonus_points,
        "playlists": [
            {"id": playlist.id, "name": playlist.name}
            for playlist in block.playlists.all()
        ],
        "feedback_info": block.get_rules().feedback_info(),
        "loading_text": _("Loading"),
        "session_id": session.id,
    }

    response = JsonResponse(block_data, json_dumps_params={"indent": 4})

    return response

get_experiment(request, slug) #

check which Phase objects are related to the Experiment with the given slug retrieve the phase with the lowest order (= current_phase) return the next block from the current_phase without a finished session except if Phase.dashboard = True, then all blocks of the current_phase will be returned as an array (also those with finished session)

Source code in experiment/views.py
def get_experiment(
    request: HttpRequest,
    slug: str,
) -> JsonResponse:
    """
    check which `Phase` objects are related to the `Experiment` with the given slug
    retrieve the phase with the lowest order (= current_phase)
    return the next block from the current_phase without a finished session
    except if Phase.dashboard = True,
    then all blocks of the current_phase will be returned as an array (also those with finished session)
    """

    try:
        experiment = Experiment.objects.get(slug=slug, active=True)
    except Experiment.DoesNotExist:
        raise Http404("Experiment does not exist or is not active")
    except Exception as e:
        logger.error(e)
        return JsonResponse(
            {"error": "Something went wrong while fetching the experiment. Please try again later."},
            status=500,
        )

    request.session[EXPERIMENT_KEY] = slug
    participant = get_participant(request)

    phases = list(experiment.phases.order_by("index").all())
    if not len(phases):
        return JsonResponse(
            {"error": "This experiment does not have phases and blocks configured"},
            status=500,
        )
    times_played_key = 'f"{slug}-xplayed"'
    times_played = request.session.get(times_played_key, 0)
    for phase in phases:
        serialized_phase = serialize_phase(phase, participant, times_played)
        if serialized_phase:
            return JsonResponse(
                {
                    **serialize_experiment(experiment),
                    **serialized_phase,
                }
            )
    # if no phase was found, start from scratch with the minimum session count
    request.session[times_played_key] = _get_min_session_count(experiment, participant)
    return get_experiment(request, slug)

validate_block_playlist(request, rules_id) #

Validate the playlist of an experiment based on the used rules

Source code in experiment/views.py
def validate_block_playlist(request: HttpRequest, rules_id: str) -> JsonResponse:
    """
    Validate the playlist of an experiment based on the used rules
    """

    if request.method != "POST":
        return JsonResponse({"status": "error", "message": "Only POST requests are allowed"})

    if not request.body:
        return JsonResponse({"status": "error", "message": "No body found in request"})

    if request.content_type != "application/json":
        return JsonResponse({"status": "error", "message": "Only application/json content type is allowed"})

    json_body = json.loads(request.body)
    playlist_ids = json_body.get("playlists", [])
    playlists = Playlist.objects.filter(id__in=playlist_ids)

    if not playlists:
        return JsonResponse({"status": "error", "message": "The block must have a playlist."})

    rules = BLOCK_RULES[rules_id]()

    if not rules.validate_playlist:
        return JsonResponse({"status": "warn", "message": "This rulesset does not have a playlist validation."})

    playlist_errors = []

    for playlist in playlists:
        errors = rules.validate_playlist(playlist)
        if errors:
            playlist_errors.append({"playlist": playlist.name, "errors": errors})

    if playlist_errors:
        return JsonResponse(
            {"status": "error", "message": "There are errors in the playlist.", "errors": playlist_errors}
        )

    return JsonResponse({"status": "ok", "message": "The playlist is valid."})