Skip to content

Commit

Permalink
refactor: Rename many more instances of experiment to block
Browse files Browse the repository at this point in the history
  • Loading branch information
drikusroor committed Jul 3, 2024
1 parent 0630f3a commit 0547bf0
Show file tree
Hide file tree
Showing 109 changed files with 1,184 additions and 1,167 deletions.
8 changes: 4 additions & 4 deletions backend/experiment/actions/consent.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def render_html_or_markdown(dry_text: str, render_format: str) -> str:
class Consent(BaseAction): # pylint: disable=too-few-public-methods
"""
Provide data for a view that ask consent for using the experiment data
- text: Uploaded file via experiment.consent (fileField)
- text: Uploaded file via block.consent (fileField)
- title: The title to be displayed
- confirm: The text on the confirm button
- deny: The text on the deny button
Expand All @@ -49,7 +49,7 @@ class Consent(BaseAction): # pylint: disable=too-few-public-methods
Relates to client component: Consent.js
"""

# default consent text, that can be used for multiple experiments
# default consent text, that can be used for multiple blocks
ID = 'CONSENT'

default_text = "Lorem ipsum dolor sit amet, nec te atqui scribentur. Diam \
Expand All @@ -62,11 +62,11 @@ class Consent(BaseAction): # pylint: disable=too-few-public-methods
contentiones, vix ex maiorum denique! Lorem ipsum dolor sit \
amet, nec te atqui scribentur. Diam molestie posidonium te sit, \
ea sea expetenda suscipiantur contentiones."

def __init__(self, text, title='Informed consent', confirm='I agree', deny='Stop', url=''):
# Determine which text to use
if text!='':
# Uploaded consent via file field: experiment.consent (High priority)
# Uploaded consent via file field: block.consent (High priority)
with text.open('r') as f:
dry_text = f.read()
render_format = get_render_format(text.url)
Expand Down
2 changes: 1 addition & 1 deletion backend/experiment/actions/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def __init__(self, session, title: str = None, score=None, score_message=None, c
self.session = session
self.title = title or _('Round {rounds_passed} / {total_rounds}').format(
rounds_passed=session.rounds_passed(),
total_rounds=self.session.experiment.rounds
total_rounds=self.session.block.rounds
)
self.score = score or session.last_score()
self.score_message = score_message or self.default_score_message
Expand Down
22 changes: 11 additions & 11 deletions backend/experiment/actions/tests/test_actions_consent.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
from django.test import TestCase
from django.core.files.uploadedfile import SimpleUploadedFile

from experiment.models import Experiment
from experiment.models import Block
from experiment.actions.consent import Consent


class ConsentTest(TestCase):

@classmethod
def setUpTestData(cls):
Experiment.objects.create(
def setUpTestData(cls):
Block.objects.create(
name='test_md',
slug='MARKDOWN',
consent=SimpleUploadedFile('consent.md', b'#test', content_type='text/html')
)
Experiment.objects.create(
Block.objects.create(
name='test_html',
slug='HTML',
consent=SimpleUploadedFile('consent.html', b'<h1>test</h1>', content_type='text/html')
)
Experiment.objects.create(
Block.objects.create(
name='test_template',
slug='TEMPLATE',
consent=SimpleUploadedFile('template.html', b'{% load i18n %}{% blocktranslate %}<p>test</p>{% endblocktranslate %}', content_type='text/html')
Expand All @@ -34,16 +34,16 @@ def test_html_rendering(self):
self.assertEqual(consent.text, '<h1>test</h1>')

def test_uploaded_markdown_rendering(self):
experiment = Experiment.objects.get(slug='MARKDOWN')
consent = Consent(experiment.consent)
block = Block.objects.get(slug='MARKDOWN')
consent = Consent(block.consent)
self.assertEqual(consent.text, '<h1>test</h1>')

def test_uploaded_html_rendering(self):
experiment = Experiment.objects.get(slug='HTML')
consent = Consent(experiment.consent)
block = Block.objects.get(slug='HTML')
consent = Consent(block.consent)
self.assertEqual(consent.text, '<h1>test</h1>')

def test_template_language_rendering(self):
experiment = Experiment.objects.get(slug='TEMPLATE')
consent = Consent(experiment.consent)
block = Block.objects.get(slug='TEMPLATE')
consent = Consent(block.consent)
self.assertEqual(consent.text, '<p>test</p>')
2 changes: 1 addition & 1 deletion backend/experiment/actions/tests/test_actions_score.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def setUp(self):
self.mock_session.last_song.return_value = "Test Song"
self.mock_session.total_score.return_value = 50
self.mock_session.rounds_passed.return_value = 2
self.mock_session.experiment.rounds = 5
self.mock_session.block.rounds = 5

def test_initialization_full_parameters(self):
score = Score(
Expand Down
6 changes: 3 additions & 3 deletions backend/experiment/actions/tests/test_wrappers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from experiment.actions import Trial
from experiment.actions.wrappers import song_sync
from experiment.models import Experiment
from experiment.models import Block
from participant.models import Participant
from section.models import Playlist, Section
from session.models import Session
Expand All @@ -15,9 +15,9 @@ def setUp(self):
self.participant = Participant.objects.create()
self.section = Section.objects.create(
filename='some/audio/file.mp3', playlist=self.playlist)
self.experiment = Experiment.objects.create(name='TestExperiment')
self.block = Block.objects.create(name='TestBlock')
self.session = Session.objects.create(
experiment=self.experiment, participant=self.participant, playlist=self.playlist)
block=self.block, participant=self.participant, playlist=self.playlist)

def test_song_sync(self):
actions = song_sync(self.session, self.section, 'HookedTest')
Expand Down
6 changes: 3 additions & 3 deletions backend/experiment/actions/toontjehoger.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ToontjeHoger(BaseAction): # pylint: disable=too-few-public-methods

ID = "TOONTJEHOGER"

def __init__(self, config, experiments=[]):
def __init__(self, config, blocks=[]):
"""
ToontjeHoger shows the ToontjeHoger homepage
Expand All @@ -21,7 +21,7 @@ def __init__(self, config, experiments=[]):
- main_button_url
- score_label
- supporters_intro
experiments: A list of ExperimentData objects
blocks: A list of ExperimentData objects
"""
self.config = config
self.experiments = [vars(i) for i in self.experiments]
self.blocks = [vars(i) for i in self.blocks]
2 changes: 1 addition & 1 deletion backend/experiment/actions/trial.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(

def action(self):
"""
Serialize data for experiment action
Serialize data for a block action
"""
# Create action
Expand Down
12 changes: 6 additions & 6 deletions backend/experiment/actions/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@


def final_action_with_optional_button(session, final_text='', title=_('End'), button_text=_('Continue')):
""" given a session, a score message and an optional session dictionary from an experiment series,
return a Final.action, which has a button to continue to the next experiment if series is defined
""" given a session, a score message and an optional session dictionary from an experiment collection,
return a Final.action, which has a button to continue to the next block if series is defined
"""
collection_slug = session.load_json_data().get(COLLECTION_KEY)

Expand Down Expand Up @@ -49,7 +49,7 @@ def render_feedback_trivia(feedback, trivia):


def get_average_difference(session, num_turnpoints, initial_value):
"""
"""
return the average difference in milliseconds participants could hear
"""
last_turnpoints = get_last_n_turnpoints(session, num_turnpoints)
Expand All @@ -58,8 +58,8 @@ def get_average_difference(session, num_turnpoints, initial_value):
if last_result:
return float(last_result.section.song.name)
else:
# this cannot happen in DurationDiscrimination style experiments
# for future compatibility, still catch the condition that there may be no results
# this cannot happen in DurationDiscrimination style blocks
# for future compatibility, still catch the condition that there may be no results
return initial_value
return (sum([int(result.section.song.name) for result in last_turnpoints]) / last_turnpoints.count())

Expand All @@ -78,7 +78,7 @@ def get_average_difference_level_based(session, num_turnpoints, initial_value):
# no results right after the practice rounds
return initial_value
# Difference by level starts at initial value (which is level 1, so 20/(2^0)) and then halves for every next level
return sum([initial_value / (2 ** (int(result.section.song.name.split('_')[-1]) - 1)) for result in last_turnpoints]) / last_turnpoints.count()
return sum([initial_value / (2 ** (int(result.section.song.name.split('_')[-1]) - 1)) for result in last_turnpoints]) / last_turnpoints.count()


def get_fallback_result(session):
Expand Down
70 changes: 35 additions & 35 deletions backend/experiment/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from question.admin import QuestionSeriesInline
from experiment.forms import (
ExperimentCollectionForm,
ExperimentForm,
BlockForm,
ExportForm,
TemplateForm,
SocialMediaConfigForm,
Expand All @@ -46,9 +46,9 @@ class FeedbackInline(admin.TabularInline):
extra = 0


class ExperimentAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin):
list_display = ('image_preview', 'experiment_name_link',
'experiment_slug_link', 'rules',
class BlockAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin):
list_display = ('image_preview', 'block_name_link',
'block_slug_link', 'rules',
'rounds', 'playlist_count',
'session_count', 'active')
list_filter = ['active']
Expand All @@ -60,15 +60,15 @@ class ExperimentAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin):
'rounds', 'bonus_points', 'playlists',
'consent']
inlines = [QuestionSeriesInline, FeedbackInline]
form = ExperimentForm
form = BlockForm

# make playlists fields a list of checkboxes
formfield_overrides = {
models.ManyToManyField: {'widget': CheckboxSelectMultiple},
}

def export(self, request, obj, parent_obj=None):
"""Export experiment JSON data as zip archive, force download"""
"""Export block JSON data as zip archive, force download"""

# Init empty querysets
all_results = Result.objects.none()
Expand Down Expand Up @@ -112,7 +112,7 @@ def export(self, request, obj, parent_obj=None):
export.short_description = "Export JSON"

def export_csv(self, request, obj, parent_obj=None):
"""Export experiment data in CSV, force download"""
"""Export block data in CSV, force download"""
# Handle export command from intermediate form
if '_export' in request.POST:
session_keys = []
Expand All @@ -130,16 +130,16 @@ def export_csv(self, request, obj, parent_obj=None):
response['Content-Disposition'] = 'attachment; filename="{}.csv"'.format(
obj.slug)
# Get filtered data
experiment_table, fieldnames = obj.export_table(
block_table, fieldnames = obj.export_table(
session_keys, result_keys, export_options)
fieldnames.sort()
writer = csv.DictWriter(response, fieldnames)
writer.writeheader()
writer.writerows(experiment_table)
writer.writerows(block_table)
return response
# Go back to admin experiment overview
# Go back to admin block overview
if '_back' in request.POST:
return redirect('/admin/experiment/experiment')
return redirect('/admin/experiment/block')
# Load a template in the export form
if '_template' in request.POST:
selected_template = request.POST.get('select_template')
Expand Down Expand Up @@ -170,26 +170,26 @@ def image_preview(self, obj):
return mark_safe(f'<img src="{img_src}" style="max-height: 50px;"/>')
return ""

def experiment_name_link(self, obj):
"""Generate a link to the experiment's admin change page."""
url = reverse("admin:experiment_experiment_change", args=[obj.pk])
def block_name_link(self, obj):
"""Generate a link to the block's admin change page."""
url = reverse("admin:experiment_block_change", args=[obj.pk])
name = obj.name or obj.slug or "No name"
return format_html('<a href="{}">{}</a>', url, name)

def experiment_slug_link(self, obj):
def block_slug_link(self, obj):
dev_mode = settings.DEBUG is True
url = f"http://localhost:3000/{obj.slug}" if dev_mode else f"/{obj.slug}"

return format_html(
f'<a href="{url}" target="_blank" rel="noopener noreferrer" title="Open {obj.slug} experiment in new tab" >{obj.slug}&nbsp;<small>&#8599;</small></a>')
f'<a href="{url}" target="_blank" rel="noopener noreferrer" title="Open {obj.slug} block in new tab" >{obj.slug}&nbsp;<small>&#8599;</small></a>')

# Name the columns
image_preview.short_description = "Image"
experiment_name_link.short_description = "Name"
experiment_slug_link.short_description = "Slug"
block_name_link.short_description = "Name"
block_slug_link.short_description = "Slug"


admin.site.register(Block, ExperimentAdmin)
admin.site.register(Block, BlockAdmin)


class GroupedBlockInline(admin.StackedInline):
Expand Down Expand Up @@ -245,31 +245,31 @@ def phases(self, obj):

def dashboard(self, request, obj, parent_obj=None):
"""Open researchers dashboard for a collection"""
all_experiments = obj.associated_experiments()
all_blocks = obj.associated_blocks()
all_participants = obj.current_participants()
all_sessions = obj.export_sessions()
collect_data = {
'participant_count': len(all_participants),
'session_count': len(all_sessions)
}

experiments = [{
'id': exp.id,
'name': exp.name,
'started': len(all_sessions.filter(experiment=exp)),
blocks = [{
'id': block.id,
'name': block.name,
'started': len(all_sessions.filter(block=block)),
'finished': len(all_sessions.filter(
experiment=exp,
block=block,
finished_at__isnull=False,
)),
'participant_count': len(exp.current_participants()),
'participants': exp.current_participants()
} for exp in all_experiments]
'participant_count': len(block.current_participants()),
'participants': block.current_participants()
} for block in all_blocks]

return render(
request,
'collection-dashboard.html',
context={'collection': obj,
'experiments': experiments,
'blocks': blocks,
'sessions': all_sessions,
'participants': all_participants,
'collect_data': collect_data}
Expand All @@ -280,7 +280,7 @@ def dashboard(self, request, obj, parent_obj=None):


class PhaseAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin):
list_display = ('name_link', 'related_series', 'index', 'dashboard', 'randomize', 'experiments')
list_display = ('name_link', 'related_series', 'index', 'dashboard', 'randomize', 'blocks')
fields = ['name', 'series', 'index', 'dashboard', 'randomize']
inlines = [GroupedBlockInline]

Expand All @@ -295,13 +295,13 @@ def related_series(self, obj):
"admin:experiment_experimentcollection_change", args=[obj.series.pk])
return format_html('<a href="{}">{}</a>', url, obj.series.name)

def experiments(self, obj):
experiments = GroupedBlock.objects.filter(phase=obj)
def blocks(self, obj):
blocks = GroupedBlock.objects.filter(phase=obj)

if not experiments:
return "No experiments"
if not blocks:
return "No blocks"

return format_html(', '.join([f'<a href="/admin/experiment/groupedexperiment/{experiment.id}/change/">{experiment.block.name}</a>' for experiment in experiments]))
return format_html(', '.join([f'<a href="/admin/experiment/groupedblock/{block.id}/change/">{block.block.name}</a>' for block in blocks]))


admin.site.register(Phase, PhaseAdmin)
Loading

0 comments on commit 0547bf0

Please sign in to comment.