There will be a short maintenance break on Wed 27.10. at 12:00. Estimated time 30 minutes.

Commit 10f3f46f authored by Ossi Laine's avatar Ossi Laine
Browse files

Experiments divided between user groups

parent 9968f630
{% extends "base.html" %}
{% block content %}
<h1 class="container mt-5 display-4 text-center"><br>Create new experiment: (1/4)</h1>
<br>
<br>
<p class="lead">Please input the following information. All fields are required.
</p>
{% from "_formhelpers.html" import render_field %}
<div class=container"><br>
<div class="row align-items-center justify-content-center">
{% extends "base.html" %} {% block content %}
<h1 class="container mt-5 display-4 text-center">
<br />Create new experiment: (1/4)
</h1>
<br />
<br />
<p class="lead">
Please input the following information. All fields are required.
</p>
{% from "_formhelpers.html" import render_field %} <div class=container"><br />
<div class="row align-items-center justify-content-center">
<div class="col-12">
<form action="" method="post" role="form">
<div class="form-group">
<label for="name">Your name:</label>
<input required type="text" class="form-control" id="creator_name" name="creator_name" placeholder="Creator name?">
<br>
<input
required
type="text"
class="form-control"
id="creator_name"
name="creator_name"
placeholder="Creator name?"
/>
<br />
{% for group in groups %} {{ group }} {% endfor %}
<label for="research-group">Group:</label>
<select class="form-control" id="group" name="group">
{% for group in valid_groups %}
<option value="{{group.id}}">{{ group.name }}</option>
{% endfor %}
</select>
<br />
<label for="name">Name of the experiment:</label>
<input required type="text" class="form-control" id="name" name="name" placeholder="Experiment name?">
<br>
<input
required
type="text"
class="form-control"
id="name"
name="name"
placeholder="Experiment name?"
/>
<br />
<div class="form-group">
<label for="language">Select a language for the experiment:</label>
<select class="form-control" id="language" name="language">
<option disabled selected value></option>
<!--<option disabled selected value></option>-->
<option value="Afrikanns">Afrikanns</option>
<option value="Albanian">Albanian</option>
<option value="Arabic">Arabic</option>
......@@ -36,7 +60,7 @@
<option value="Czech">Czech</option>
<option value="Danish">Danish</option>
<option value="Dutch">Dutch</option>
<option value="English">English</option>
<option selected value="English">English</option>
<option value="Estonian">Estonian</option>
<option value="Fiji">Fiji</option>
<option value="Finnish">Finnish</option>
......@@ -80,7 +104,7 @@
<option value="Slovenian">Slovenian</option>
<option value="Spanish">Spanish</option>
<option value="Swahili">Swahili</option>
<option value="Swedish ">Swedish </option>
<option value="Swedish ">Swedish</option>
<option value="Tamil">Tamil</option>
<option value="Tatar">Tatar</option>
<option value="Telugu">Telugu</option>
......@@ -96,36 +120,69 @@
<option value="Xhosa">Xhosa</option>
</select>
<br>
<p>Instructions for the experiment come in three forms:
<br> (1) A single sentence instruction that is shown during the rating task above the sliders.
<br> (2) A short general description of the task that is shown on the experiment listing on Onni's front page and on the informed consent page.
<br> (3) a longer detailed explanation of the instructions that is shown to the participant after the consent and before the rating task begins.
<br> Please input all three types of instructions below:
<br />
<p>
Instructions for the experiment come in three forms: <br />
(1) A single sentence instruction that is shown during the rating
task above the sliders. <br />
(2) A short general description of the task that is shown on the
experiment listing on Onni's front page and on the informed consent
page. <br />
(3) a longer detailed explanation of the instructions that is shown
to the participant after the consent and before the rating task
begins. <br />
Please input all three types of instructions below:
</p>
<label for="single_sentence_instruction">(1) Single sentence:</label>
<input required type="text" class="form-control" id="single_sentence_instruction" name="single_sentence_instruction" placeholder="Input here" required>
<br>
<input
required
type="text"
class="form-control"
id="single_sentence_instruction"
name="single_sentence_instruction"
placeholder="Input here"
required
/>
<br />
<label for="short_instruction">(2) Short description:</label>
<textarea class="form-control" rows="5" id="short_instruction" name="short_instruction" placeholder="Input here" required></textarea>
<br>
<textarea
class="form-control"
rows="5"
id="short_instruction"
name="short_instruction"
placeholder="Input here"
required
></textarea>
<br />
<label for="instruction">(3) Longer version:</label>
<textarea class="form-control" rows="15" id="instruction" name="instruction" placeholder="Input here" required></textarea>
<br>
<textarea
class="form-control"
rows="15"
id="instruction"
name="instruction"
placeholder="Input here"
required
></textarea>
<br />
<label for="instruction">Please input consent form text</label>
<textarea class="form-control" rows="15" id="consent_text" name="consent_text" placeholder="Input here" required></textarea>
<br>
<textarea
class="form-control"
rows="15"
id="consent_text"
name="consent_text"
placeholder="Input here"
required
></textarea>
<br />
</div>
</div>
<br>
<br />
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endblock %}
\ No newline at end of file
{% endblock %}
</div>
</div>
......@@ -16,12 +16,7 @@ from flask_login import login_required
from app.routes import APP_ROOT
from app import app, db
from app.models import background_question, experiment
from app.models import background_question_answer
from app.models import page, question
from app.models import background_question_option
from app.models import answer_set, answer, forced_id
from app.models import user, trial_randomization
from app.models import background_question, experiment, background_question_answer, page, question, background_question_option, answer_set, answer, forced_id, user, trial_randomization, research_group, user_in_group
from app.forms import (
CreateExperimentForm, CreateBackgroundQuestionForm,
CreateQuestionForm, UploadStimuliForm
......@@ -39,20 +34,32 @@ def create_experiment():
form = CreateExperimentForm(request.form)
user_groups = user_in_group.query.filter_by(
iduser=session['user_id']).all()
if user_groups:
user_groups = [ug.idgroup for ug in user_groups]
valid_groups = research_group.query.filter(
research_group.id.in_(user_groups)).all()
else:
valid_groups = []
if request.method == 'POST' and form.validate():
the_time = datetime.now()
the_time = the_time.replace(microsecond=0)
new_exp = experiment(name=request.form['name'], instruction=request.form['instruction'], language=request.form['language'], status='Hidden', randomization='Off', single_sentence_instruction=request.form['single_sentence_instruction'],
short_instruction=request.form['short_instruction'], creator_name=request.form['creator_name'], is_archived='False', creation_time=the_time, stimulus_size='7', consent_text=request.form['consent_text'], use_forced_id='Off')
short_instruction=request.form['short_instruction'], creator_name=request.form['creator_name'], is_archived='False', creation_time=the_time, stimulus_size='7', consent_text=request.form['consent_text'], use_forced_id='Off', group_id=request.form['group'])
db.session.add(new_exp)
db.session.commit()
exp_id = new_exp.idexperiment
return redirect(url_for('create.experiment_bgquestions', exp_id=exp_id))
return render_template('create_experiment.html', form=form)
return render_template('create_experiment.html', form=form, valid_groups=valid_groups)
@create_blueprint.route('/experiment_bgquestions', methods=['GET', 'POST'])
......
......@@ -58,6 +58,11 @@
<td>{{ exp.creator_name }} - {{ exp.creation_time }}</td>
<td nowrap></td>
</tr>
<tr>
<td nowrap>Group:</td>
<td>{{ group_info.name }}</td>
<td nowrap></td>
</tr>
<tr>
<td nowrap>Language:</td>
<td>{{ exp.language }}</td>
......
......@@ -20,13 +20,7 @@ from flask import (
from app import app, db, socketio
from app.routes import APP_ROOT
from app.models import background_question, experiment
from app.models import background_question_answer
from app.models import page, question
from app.models import background_question_option
from app.models import answer_set, answer, forced_id
from app.models import trial_randomization
from app.models import embody_answer, embody_question
from app.models import background_question, experiment, background_question_answer, page, question, background_question_option, answer_set, answer, forced_id, trial_randomization, embody_answer, embody_question, research_group
from app.forms import (
CreateBackgroundQuestionForm,
CreateQuestionForm, UploadStimuliForm, EditBackgroundQuestionForm,
......@@ -62,6 +56,9 @@ def view():
# experiment info
experiment_info = experiment.query.filter_by(idexperiment=exp_id).all()
group_info = research_group.query.filter_by(
id=experiment_info[0].group_id).first()
# background questions
questions_and_options = {}
questions = background_question.query.filter_by(
......@@ -93,7 +90,7 @@ def view():
embody_pictures = embody_question.query.filter_by(
experiment_idexperiment=exp_id).all()
return render_template('view_experiment.html', exp_id=exp_id, media=media, mtype=mtype, experiment_info=experiment_info, categories1=categories1, questions1=questions1, embody_pictures=embody_pictures)
return render_template('view_experiment.html', exp_id=exp_id, media=media, mtype=mtype, experiment_info=experiment_info, categories1=categories1, questions1=questions1, embody_pictures=embody_pictures, group_info=group_info)
# Experiment info:
......
......@@ -10,6 +10,52 @@ from app import login
from datetime import datetime
class user(UserMixin, db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<user {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login.user_loader
def load_user(id):
return user.query.get(int(id))
class research_group(db.Model):
__tablename__ = "research_group"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text)
tag = db.Column(db.Text)
description = db.Column(db.Text)
def __repr__(self):
return "<id= '%s', name= '%s', tag= '%s', description= '%s' >" % (self.id, self.name, self.tag, self.description)
class user_in_group (db.Model):
__tablename__ = "user_in_group"
__table_args__ = (
db.PrimaryKeyConstraint('idgroup', 'iduser'),
)
idgroup = db.Column(
db.Integer, db.ForeignKey('research_group.id'))
iduser = db.Column(
db.Integer, db.ForeignKey('user.id'))
role = db.Column(db.Text)
class background_question(db.Model):
__tablename__ = "background_question"
idbackground_question = db.Column(db.Integer, primary_key=True)
......@@ -53,6 +99,9 @@ class experiment (db.Model):
use_forced_id = db.Column(db.String(120))
embody_enabled = db.Column(db.Boolean, unique=False, default=False)
group_id = db.Column(
db.Integer, db.ForeignKey('research_group.id'))
def __repr__(self):
return "<idexperiment = '%s', name='%s', instruction='%s', directoryname='%s', language='%s', status='%s', randomization='%s', short_instruction='%s', single_sentence_instruction='%s', is_archived='%s', creator_name='%s', research_notification_filename='%s', creation_time='%s', stimulus_size='%s', consent_text='%s', use_forced_id='%s', embody_enabled='%s'>" % (self.idexperiment, self.name, self.instruction, self.directoryname, self.language, self.status, self.randomization, self.short_instruction, self.single_sentence_instruction, self.is_archived, self.creator_name, self.research_notification_filename, self.creation_time, self.stimulus_size, self.consent_text, self.use_forced_id, self.embody_enabled)
......@@ -207,25 +256,3 @@ class forced_id (db.Model):
def __repr__(self):
return "<idforced_id = '%s', experiment_idexperiment = '%s', pregenerated_id = '%s'>" % (self.idforced_id, self.experiment_idexperiment, self.pregenerated_id)
class user(UserMixin, db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return '<user {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login.user_loader
def load_user(id):
return user.query.get(int(id))
......@@ -3,22 +3,13 @@ import random
import secrets
from datetime import datetime
from flask import (render_template,
request,
session,
flash,
redirect,
url_for)
from flask import render_template, request, session, flash, redirect, url_for
from sqlalchemy import and_
from flask_login import current_user, login_user, logout_user, login_required
from app import app, db
from app.models import background_question, experiment
from app.models import background_question_answer
from app.models import page
from app.models import background_question_option
from app.models import answer_set, forced_id
from app.models import user, trial_randomization
from app.models import (background_question, experiment, background_question_answer, page,
background_question_option, answer_set, forced_id, user, trial_randomization, research_group)
from app.forms import LoginForm, RegisterForm, StartWithIdForm
# Stimuli upload folder setting
......@@ -28,15 +19,33 @@ APP_ROOT = os.path.dirname(os.path.abspath(__file__))
@app.route('/')
@app.route('/index')
def index():
experiments = experiment.query.all()
groups = research_group.query.all()
session['group'] = None
if not session:
session['language'] = "English"
return render_template('home.html', title='Home', groups=groups)
@app.route('/<group_tag>')
def group_page(group_tag):
#experiments = experiment.query.all()
if session:
flash("")
group = research_group.query.filter_by(tag=group_tag).first()
if not group:
flash("Group not found")
experiments = []
else:
#flash("sessio ei voimassa")
experiments = experiment.query.filter_by(group_id=group.id).all()
session['group'] = group_tag
if not session:
session['language'] = "English"
return render_template('index.html', title='Home', experiments=experiments)
return render_template('index.html', title='Home', experiments=experiments, group=group)
@app.route('/consent')
......@@ -62,8 +71,13 @@ def consent():
@app.route('/set_language')
def set_language():
session['language'] = request.args.get('language', None)
lang = request.args.get('lang', None)
if session['group']:
return redirect(url_for('group_page', lang=lang, group_tag=session['group']))
else:
return redirect(url_for('index', lang=lang))
......
......@@ -2,14 +2,12 @@ body {
font-family: Helvetica, Arial, sans-serif;
}
#header{
#header {
background-color: darkslategrey;
color: white;
text-align: center;
}
#embody-canvas {
display: block;
margin: 0 auto;
......@@ -18,31 +16,33 @@ body {
}
.clear-button {
margin:10px;
margin: 10px;
}
.crosshair {cursor: crosshair;}
.crosshair {
cursor: crosshair;
}
@keyframes spinner-border {
to {
transform: rotate(360deg);
}
}
.spinner-border{
.spinner-border {
display: inline-block;
width: 2rem;
height: 2rem;
vertical-align: text-bottom;
border: .25em solid currentColor;
border: 0.25em solid currentColor;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: spinner-border .75s linear infinite;
animation: spinner-border .75s linear infinite;width: 1rem;
-webkit-animation: spinner-border 0.75s linear infinite;
animation: spinner-border 0.75s linear infinite;
width: 1rem;
}
.spinner-border-sm{
.spinner-border-sm {
height: 1rem;
border-width: .2em;
border-width: 0.2em;
}
.hidden {
......@@ -50,16 +50,15 @@ body {
}
.progress-bar {
height:2em;
height: 2em;
}
.progress {
height:2em;
background-color:rgb(248, 249, 250);
height: 2em;
background-color: rgb(248, 249, 250);
-webkit-box-shadow: none;
box-shadow: none;
}
.thumbnail {
max-height: 100px;
}
......@@ -68,13 +67,10 @@ body {
text-align: center;
}
@media (max-width: 600px) {
.stimulus {
max-width: 90%;
}
}
.stimulus img {
......@@ -82,13 +78,31 @@ body {
object-fit: contain;
}
#export-link-container {
margin-top: 20px;
padding: 10px;
}
#export-error {
float:right;
color:red;
float: right;
color: red;
}
.squares {
display: flex;
justify-content: center;
}
.boxed-link {
display: inline-block;
padding: 20px 30px;
background: #f8f9fa;
margin: 20px;
color: black;
}
.boxed-link:hover,
.boxed-link:focus {
background: hsl(208, 12%, 78%);
text-decoration: none;
color: black;
}
This diff is collapsed.
......@@ -9,14 +9,8 @@
</div>
<p class="lead text-center mt-5 font-weight-bold">{{_(group.description)}}</p>
<p class="lead text-center mt-5 font-weight-bold">{{ _('Welcome to the Human Emotion Systems -laboratory`s Onni-net laboratory! The experiments that are currently underway are listed below -
you can participate for as many experiments you want.') }}</p>
<p class="lead text-center mt-5">{{ _('If you are participating for a study for the first time, click on the "Begin task" -button. If you are returning to continue
a previously started task, click on the "Continue task" button.') }}</p>
......@@ -203,23 +197,6 @@
......
......@@ -91,10 +91,7 @@ msgid "Please insert your participant ID:"
msgstr "Παρακαλώ εισάγετε τον κωδικό αναγνώρισης σας"
#: app/templates/index.html:18
msgid ""
"Welcome to the Human Emotion Systems -laboratory`s Onni-net laboratory! "
"The experiments that are currently underway are listed below -\n"
" you can participate for as many experiments you want."
msgid "Welcome to the Human Emotion Systems -laboratory`s Onni-net laboratory! The experiments that are currently underway are listed below - you can participate for as many experiments you want."
msgstr "Καλώς ήρθατε στο εργαστήριο συστημάτων των ανθρώπινων συναισθημάτων! Τα πειράματα που βρίσκονται σε εξέλιξη αναφέρονται παρακάτω - μπορείτε να συμμετάσχετε σε όσα πειράματα θέλετε."