Merge pull request 'Merging Latest changes into main' (#1) from working into main
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Reviewed-on: #1
This commit is contained in:
commit
fb82d4c19a
@ -11,7 +11,7 @@ import uuid
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy import select, join
|
||||
from sqlalchemy.orm import DeclarativeBase
|
||||
from flask_wtf.csrf import CSRFProtect
|
||||
#from flask_wtf.csrf import CSRFProtect
|
||||
import os
|
||||
import csv
|
||||
from zipfile import ZipFile
|
||||
@ -33,6 +33,7 @@ app = Flask(__name__)
|
||||
# configure the database, give it a path (it will be in the instances folder)
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database.db"
|
||||
app.config["PERMANENT_SESSION_LIFETIME"] = 10800 #3 Stunden, 10800 sekunden
|
||||
app.config['MAX_CONTENT_LENGTH'] = 16 * 1000 * 1000 # try and fix video upload not working
|
||||
db.init_app(app)
|
||||
|
||||
#set the secret key (TODO change this for final deployment)
|
||||
@ -41,6 +42,9 @@ app.secret_key = b"29fe9e8edd407c5491d4f1c05632d9fa33e26ed8734a3f5e080ebac3772a5
|
||||
UPLOAD_FOLDER = 'uploads'
|
||||
EXPORT_FOLDER = 'exports'
|
||||
PASSWORD = '#1ACGmsjd'
|
||||
# CONFIGFILE = 'userstudy1.json'
|
||||
CONFIGFILE = 'test.json'
|
||||
# CONFIGFILE = 'default.json'
|
||||
|
||||
#csrf = CSRFProtect(app) #enable CSRF protection globally
|
||||
|
||||
@ -70,7 +74,7 @@ except SQLAlchemyError as e:
|
||||
#open, parse and execute json file
|
||||
|
||||
#open the json file with the config
|
||||
configfile = open("default.json", encoding='utf-8') #todo replace with other name
|
||||
configfile = open(CONFIGFILE, encoding='utf-8') #todo replace with other name
|
||||
#convert it to dict
|
||||
config = json.load(configfile)
|
||||
configfile.close()
|
||||
@ -374,16 +378,6 @@ def sendpage():
|
||||
print("Error occurred: {e}".format(e=str(e)))
|
||||
return "There was a problem while adding the response to the Database"
|
||||
|
||||
# handle possible Video that was send
|
||||
if 'recordedVideo' in request.files:
|
||||
video = request.files['recordedVideo']
|
||||
formatted_date = date.strftime("%Y.%m.%d %H-%M-%S")
|
||||
print("date: ", date)
|
||||
video_name = str(session_user_id) + "_" + session["current_block_name"] + "_" + session["current_stimulus_name"] + "_" + str(formatted_date) + ".webm"
|
||||
path = os.path.join(UPLOAD_FOLDER, video_name)
|
||||
print("path: ",path)
|
||||
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
|
||||
video.save(path)
|
||||
|
||||
if (session["current_block_index"] == session["number_of_blocks"]-1) and (session["current_stimulus_index"] >= session["number_of_stimuli"]-1):
|
||||
#update the database entry, the form is completed
|
||||
|
@ -1,64 +1,73 @@
|
||||
const buttonCamera = document.getElementById('buttonCamera');
|
||||
const buttonRecord = document.getElementById('buttonRecord');
|
||||
const buttonDelete = document.getElementById('buttonDelete');
|
||||
const videoDisplay = document.getElementById('videoDisplay');
|
||||
const buttonCameraIcon = document.getElementById('buttonCameraIcon');
|
||||
const buttonRecordIcon = document.getElementById('buttonRecordIcon');
|
||||
const buttonDeleteIcon = document.getElementById('buttonDeleteIcon');
|
||||
const videoContainer = document.getElementById('videoContainer');
|
||||
const videoContainerCss = document.querySelector(".video-container ") //might be unnecessary
|
||||
var mediaRecorder = null;
|
||||
var stream = null;
|
||||
let recordedVideoBlob = null;
|
||||
let isRecording = false;
|
||||
let videoAccess = false;
|
||||
let videoHeigt = 720;
|
||||
|
||||
const videoDisplay = document.getElementById('videoDisplay');
|
||||
const videoContainer = document.getElementById('videoContainer'); // div that contains the videodisplay
|
||||
|
||||
var mediaRecorder = null; // interface of the Media Stream Recording API to record the video stream
|
||||
var stream = null; // webcam video input stream
|
||||
let recordedVideoBlob = null; // recorded videodata
|
||||
let isRecording = false; // false to display record button, true to display stop button
|
||||
let videoAccess = false; // true if user has given permission to use the webcam
|
||||
|
||||
// default video dimensions
|
||||
let videoHeight = 720;
|
||||
let videoWidth = 1280;
|
||||
|
||||
// Handle form submission
|
||||
// handle form submission
|
||||
//the Video is beeing send together with the form data
|
||||
document.getElementById("question_form").addEventListener("submit", function (event) {
|
||||
event.preventDefault(); // Prevent the default form submission
|
||||
console.log("submit button pressed");
|
||||
// Create a FormData object
|
||||
// create a FormData object
|
||||
const formData = new FormData(event.target);
|
||||
|
||||
console.log("form data: ",formData);
|
||||
|
||||
// Append the recorded video Blob to the FormData object
|
||||
// append the recorded video blob to the FormData object
|
||||
if (recordedVideoBlob) {
|
||||
console.log("video is available: ", recordedVideoBlob);
|
||||
formData.append("recordedVideo", recordedVideoBlob, "recordedVideo.webm");
|
||||
}
|
||||
|
||||
|
||||
console.log("Data to be submitted: ",formData);
|
||||
|
||||
// Use fetch to send the form data and video to the backend
|
||||
console.log("try to send the form and video");
|
||||
|
||||
// send the form data and video to the backend
|
||||
fetch("/send", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
}).then(response => {
|
||||
// code to handle proper redirection after submit
|
||||
console.log('Response:', response);
|
||||
// Check if response is a redirect (HTTP 3xx status)
|
||||
// check if response is a redirect
|
||||
/*
|
||||
if (response.redirected) {
|
||||
console.log("Redirecting to:", response.url);
|
||||
window.location.href = response.url; // Redirect to the new page
|
||||
} else {
|
||||
console.log("Non-redirect response received.");
|
||||
// Handle other responses if needed
|
||||
console.log("No redirect response received.");
|
||||
}
|
||||
*/
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
// Handle errors if fetch fails
|
||||
});
|
||||
});
|
||||
|
||||
// enable/disable video recording feature
|
||||
async function cameraButton() {
|
||||
if (!videoAccess) {
|
||||
console.log("cameraButton case videoAccess = false");
|
||||
|
||||
try {
|
||||
// ask the user for permission to use the webcam
|
||||
// if given, assign it to "stream"
|
||||
stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: true,
|
||||
});
|
||||
@ -67,39 +76,61 @@ async function cameraButton() {
|
||||
return;
|
||||
}
|
||||
console.log("stream is active");
|
||||
|
||||
videoAccess = true;
|
||||
|
||||
videoHeigt = stream.getVideoTracks()[0].getSettings().height
|
||||
// set the dimensions of the webcam stream to the video display
|
||||
videoHeight = stream.getVideoTracks()[0].getSettings().height
|
||||
videoWidth = stream.getVideoTracks()[0].getSettings().width
|
||||
|
||||
let aspectratio = (videoHeigt / videoWidth) *100
|
||||
console.log("videoHeigt: ",videoHeigt);
|
||||
console.log("videoWidth: ",videoWidth);
|
||||
console.log("aspect ratio: ",aspectratio);
|
||||
console.log("device: ",stream.getVideoTracks()[0].getSettings().deviceId);
|
||||
videoContainer.style.setProperty("padding-bottom", "min("+videoHeigt+"px,"+aspectratio+"%)");
|
||||
// calculate the aspec ratio
|
||||
let aspectratio = (videoHeight / videoWidth) *100;
|
||||
//console.log("videoHeight: ",videoHeight);
|
||||
//console.log("videoWidth: ",videoWidth);
|
||||
//console.log("aspect ratio: ",aspectratio);
|
||||
//console.log("device: ",stream.getVideoTracks()[0].getSettings().deviceId);
|
||||
|
||||
if (videoHeigt > videoWidth){ //hochkant video
|
||||
videoContainer.style.setProperty("max-width", "min(80%,576");
|
||||
}else{ //Normal, horizontal
|
||||
// adjust CSS to make the video fit properly
|
||||
// this makes sure that there is no buggy "jumping" when the video display source changes
|
||||
videoContainer.style.setProperty("padding-bottom", "min("+videoHeight+"px,"+aspectratio+"%), 100vh");
|
||||
|
||||
|
||||
//TODO: Solution for this part:
|
||||
// If the video is vertical, I need to set the width to 0, the max-height to 100% and do the padding on the width, so turn the code around
|
||||
//This should always make the video fitt
|
||||
|
||||
// adjust the max width for horizontal and vertical video input
|
||||
if (videoHeight > videoWidth){ //hochkant video
|
||||
// I did this originally to display vertical video on a horizontal screen properly (video should not be higher than the screem)
|
||||
// but now I do this by adjusting the paddint to be at most 100vh, so this whole part should be useless now
|
||||
// But a new problem could be if I do too little padding and the ratio is lost because of it, so actually I also need to adjust the width
|
||||
videoContainer.style.setProperty("max-width", "min(80%,576)"); // maybe actually use the screen height here: instead of 80% maybe 80vh
|
||||
}else{ //normal, horizontal
|
||||
videoContainer.style.setProperty("max-width", "100%");
|
||||
}
|
||||
|
||||
// show the webcam input stream on the video display
|
||||
videoDisplay.srcObject = stream;
|
||||
|
||||
// change the icon to indicate the disable option
|
||||
buttonCameraIcon.src = ICON_PATHS.cameraofficon;
|
||||
buttonCameraIcon.alt = "Camera-off Icon";
|
||||
|
||||
// display the elements for the video recording
|
||||
buttonRecord.style.display = 'inline-block';
|
||||
buttonDelete.style.display = 'inline-block';
|
||||
videoDisplay.style.display = 'block';
|
||||
videoContainer.style.display = 'block';
|
||||
videoDisplay.classList.add("videomirror");
|
||||
|
||||
// initialize MediaRecorder, give it the webcam stream as input to record
|
||||
mediaRecorder = new MediaRecorder(stream, {
|
||||
mimeType: "video/webm", // could use different video format
|
||||
// videoBitsPerSecond: 5000000, // Standard bitrate for video is 2,5 mbps
|
||||
});
|
||||
|
||||
// when data is available at the mediaRecorder (this means the recording has ended, since I have not specified time intervalls)
|
||||
// save the data in "recordedVideoBlob"
|
||||
mediaRecorder.addEventListener("dataavailable", (event) => {
|
||||
console.log("Data available Event triggered");
|
||||
if (event.data.size > 0) {
|
||||
@ -110,28 +141,37 @@ async function cameraButton() {
|
||||
}
|
||||
});
|
||||
|
||||
// when recording is stopped, display the recorded video
|
||||
// TODO possibly replace this and just add it to the dataavailable event
|
||||
// TODO this would ensure proper order in a concurrent scenario (the stop code here can only be executed after the dataavailable code happened)
|
||||
// TODO part of it could also go to the record button function
|
||||
mediaRecorder.addEventListener("stop", () => {
|
||||
if (recordedVideoBlob) {
|
||||
videoDisplay.srcObject = null;
|
||||
videoDisplay.src = URL.createObjectURL(recordedVideoBlob);
|
||||
videoDisplay.controls = true;
|
||||
videoDisplay.pause();
|
||||
videoDisplay.srcObject = null; //remove the stream as input
|
||||
videoDisplay.src = URL.createObjectURL(recordedVideoBlob); // create a url for the recorded video and set it as input
|
||||
videoDisplay.controls = true; // display video controls
|
||||
videoDisplay.pause(); // pause, so that it doesn't immediately play, TODO maybe disable autoplay?
|
||||
|
||||
buttonRecordIcon.src = ICON_PATHS.recordicon;
|
||||
// TODO maybe move this to the record button function
|
||||
buttonRecordIcon.src = ICON_PATHS.recordicon; //change the icon of the record button back
|
||||
buttonRecordIcon.alt = 'Record Icon';
|
||||
isRecording = false;
|
||||
|
||||
console.log('Recording stopped');
|
||||
console.log("Src path:", videoDisplay.src);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// -> the user disabled the videorecording feature
|
||||
|
||||
console.log("cameraButton case videoAccess = true");
|
||||
|
||||
stream.getTracks().forEach(track => track.stop()); // Stop all tracks to release the camera
|
||||
stream.getTracks().forEach(track => track.stop()); // stop all tracks to release the camera
|
||||
stream = null;
|
||||
videoAccess = false;
|
||||
|
||||
// change the icon and hide all the elements again
|
||||
buttonCameraIcon.src = ICON_PATHS.cameraicon;
|
||||
buttonCameraIcon.alt = "Camera Icon";
|
||||
buttonRecord.style.display = 'none';
|
||||
@ -142,41 +182,57 @@ async function cameraButton() {
|
||||
console.log("camera button function ends");
|
||||
}
|
||||
|
||||
|
||||
function recordButton() {
|
||||
console.log("recordButton pressed");
|
||||
if (!isRecording) {
|
||||
// a new recording starts
|
||||
|
||||
console.log("recordButton pressed case isRecording = false");
|
||||
deleteButton();
|
||||
videoDisplay.classList.add("videomirror");
|
||||
buttonDelete.setAttribute("disabled", "");
|
||||
buttonDeleteIcon.classList.add("buttondisable");
|
||||
videoDisplay.srcObject = stream;
|
||||
videoDisplay.src = null;
|
||||
videoDisplay.controls = false;
|
||||
mediaRecorder.start();
|
||||
|
||||
deleteButton(); //delete previous video
|
||||
|
||||
videoDisplay.classList.add("videomirror"); // mirror the video while recording, for a more natural experience
|
||||
buttonDelete.setAttribute("disabled", ""); // can't delete during recording
|
||||
buttonDeleteIcon.classList.add("buttondisable"); // delete button icon indicates that it is disabled
|
||||
|
||||
videoDisplay.src = null; // get rid of the previous video on the display
|
||||
videoDisplay.srcObject = stream; // set webcam stream as input for the video display
|
||||
videoDisplay.controls = false; // hide the video controls durin recording, because they are confusing
|
||||
mediaRecorder.start(); // start recording
|
||||
|
||||
console.log("video bitrate = ",mediaRecorder.videoBitsPerSecond);
|
||||
|
||||
// change icon to indicate "stop"
|
||||
buttonRecordIcon.src = ICON_PATHS.stopicon;
|
||||
buttonRecordIcon.alt = 'Stop Icon';
|
||||
isRecording = true;
|
||||
|
||||
console.log('Recording started');
|
||||
} else {
|
||||
// recording got stopped
|
||||
|
||||
console.log("recordButton pressed case isRecording = true");
|
||||
mediaRecorder.stop();
|
||||
videoDisplay.classList.remove("videomirror");
|
||||
|
||||
mediaRecorder.stop(); // stop recording
|
||||
videoDisplay.classList.remove("videomirror"); // don't mirror the videodisplay anymore
|
||||
|
||||
console.log("recording stops");
|
||||
|
||||
// enable the deletebutton again
|
||||
buttonDelete.removeAttribute("disabled");
|
||||
buttonDeleteIcon.classList.remove("buttondisable");
|
||||
}
|
||||
}
|
||||
|
||||
function deleteButton() {
|
||||
// TODO delete data
|
||||
// delete the recorded video
|
||||
videoDisplay.controls = false;
|
||||
videoDisplay.srcObject = stream;
|
||||
videoDisplay.srcObject = stream; // set webcam stream as source for the video display again
|
||||
recordedVideoBlob = null
|
||||
videoDisplay.classList.add("videomirror");
|
||||
videoDisplay.classList.add("videomirror"); // mirror the video display during live feed again
|
||||
|
||||
// disable the deletebutton again
|
||||
buttonDelete.setAttribute("disabled", "");
|
||||
buttonDeleteIcon.classList.add("buttondisable");
|
||||
}
|
||||
|
@ -225,7 +225,6 @@ step={{question["step"]}}
|
||||
</div>
|
||||
|
||||
<script src="{{ url_for('static', filename='videoscript.js')}}">
|
||||
|
||||
</script>
|
||||
{% else %}
|
||||
<p>Error: Block {{config["question 1"]["blocks"][block]["type"]}} could not be loaded!</p>
|
||||
|
@ -1,37 +1,325 @@
|
||||
{
|
||||
"Block 1":{
|
||||
"type": "SinglePage",
|
||||
"template": "startpage.html"
|
||||
},
|
||||
"Block 2":{
|
||||
|
||||
"Block 2": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "tempaltetest1.html",
|
||||
"name" : "Block2Responses",
|
||||
"databasetable": {
|
||||
"question_title" : {
|
||||
"type":"likert"
|
||||
}
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "single_video",
|
||||
"order": "random",
|
||||
"list": {
|
||||
"video_1": "https://www.youtube-nocookie.com/embed/iI2bjpgLgu0?si=pWWwitq8Tl9zAs04",
|
||||
"video_2": "https://www.youtube-nocookie.com/embed/R_LNEJiShRM?si=vm5mj-xs04nfijkf",
|
||||
"video_3": "https://www.youtube-nocookie.com/embed/DJnHVnT2YEk?si=e6qe7nrHaRYJ3NQe",
|
||||
"video_4": "https://www.youtube-nocookie.com/embed/6BTZn7tqSzk?si=jQH8RHGMIP9ARsT5",
|
||||
"video_5": "https://www.youtube-nocookie.com/embed/bCRqmhWjuCk?si=iM2dwOSTosLq08Pr",
|
||||
"video_6": "https://www.youtube-nocookie.com/embed/hgE2k8y9-qc?si=kR2rshmVcb9P70r0"
|
||||
},
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"question 3":{
|
||||
"type": "single",
|
||||
"video1": "https://www.youtube-nocookie.com/embed/XTMIomsXxKM?si=r2zB6OKERH6Jdpi6",
|
||||
"scales": {
|
||||
"block1":{
|
||||
"questions": {
|
||||
"question1": {
|
||||
"type": "likert",
|
||||
"numberofpoints": "3",
|
||||
"points":{
|
||||
"point1": "left",
|
||||
"point2": "none",
|
||||
"point3": "right"
|
||||
"name": "likertscale",
|
||||
"text": "Wie würden sie dieses Video bewerten?",
|
||||
"required": "true",
|
||||
"points": {
|
||||
"p1": {
|
||||
"value": "1",
|
||||
"text": "Ich finde es gar nicht gut 🙁👎"
|
||||
},
|
||||
"p2": {
|
||||
"value": "2",
|
||||
"text": "Ich finde es nicht gut 👎"
|
||||
},
|
||||
"p3": {
|
||||
"value": "3",
|
||||
"text": "Ich finde es weder gut noch schlecht"
|
||||
},
|
||||
"p4": {
|
||||
"value": "4",
|
||||
"text": "Ich finde es gut 👍"
|
||||
},
|
||||
"p5": {
|
||||
"value": "5",
|
||||
"text": "Ich finde es sehr gut 😊👍"
|
||||
}
|
||||
}
|
||||
},
|
||||
"block2":{
|
||||
"question2": {
|
||||
"type": "textinput",
|
||||
"length": "200"
|
||||
"name": "text_feedback",
|
||||
"text": "Hier können sie uns Feedback geben",
|
||||
"required": "false",
|
||||
"size": "250"
|
||||
},
|
||||
"block3":{
|
||||
"type": "video"
|
||||
"question3": {
|
||||
"type": "videoinput",
|
||||
"text": "Hier können sie per Video Feedback geben",
|
||||
"name": "video_feedback",
|
||||
"required": "false"
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden.\\n Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt.\\n Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "single_video_responses",
|
||||
"fields": {
|
||||
"likertscale": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
},
|
||||
"text_feedback": {
|
||||
"type": "string",
|
||||
"size": "250",
|
||||
"nullable": "true"
|
||||
},
|
||||
"video_upload": {
|
||||
"type": "string",
|
||||
"size": "100",
|
||||
"nullable": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Block 1": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "empty",
|
||||
"list": {
|
||||
"empty_stimulus": ""
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1_alter": {
|
||||
"type": "numberinput",
|
||||
"name": "alter",
|
||||
"text": "Alter:",
|
||||
"required": "true",
|
||||
"min": "1",
|
||||
"max": "120"
|
||||
},
|
||||
"question2_geschlecht": {
|
||||
"type": "dropdowninput",
|
||||
"name": "geschlecht",
|
||||
"text": "Geschlecht:",
|
||||
"required": "true",
|
||||
"defaulttext": "",
|
||||
"points": {
|
||||
"männlich": {
|
||||
"value": "Männlich",
|
||||
"text": "Männlich"
|
||||
},
|
||||
"weiblich": {
|
||||
"value": "Weiblich",
|
||||
"text": "Weiblich"
|
||||
},
|
||||
"divers": {
|
||||
"value": "Divers",
|
||||
"text": "Divers"
|
||||
},
|
||||
"keine_angabe": {
|
||||
"value": "keine_angabe",
|
||||
"text": "Keine Angabe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question3_hoerstatus": {
|
||||
"type": "dropdowninput",
|
||||
"name": "hoerstatus",
|
||||
"text": "Hörstatus:",
|
||||
"required": "true",
|
||||
"defaulttext": "",
|
||||
"points": {
|
||||
"hörend": {
|
||||
"value": "Hörend",
|
||||
"text": "Hörend"
|
||||
},
|
||||
"schwerhörig": {
|
||||
"value": "Schwerhörig",
|
||||
"text": "Schwerhörig"
|
||||
},
|
||||
"gehörlos": {
|
||||
"value": "Gehörlos",
|
||||
"text": "Gehörlos"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question4_bevorzugte_kommunikation": {
|
||||
"type": "dropdowninput",
|
||||
"name": "bevorzugte_kommunikation",
|
||||
"text": "Bevorzugte Kommunikationsform:",
|
||||
"required": "true",
|
||||
"defaulttext": "",
|
||||
"points": {
|
||||
"gesprochen": {
|
||||
"value": "Gesprochene Sprache",
|
||||
"text": "Gesprochene Sprache"
|
||||
},
|
||||
"text": {
|
||||
"value": "Text",
|
||||
"text": "Text"
|
||||
},
|
||||
"gebärdensprache": {
|
||||
"value": "Gebärdensprache",
|
||||
"text": "Gebärdensprache"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question5_gebeardenzeitraum": {
|
||||
"type": "numberinput",
|
||||
"name": "gebärdenzeitraum",
|
||||
"text": "Wie viele Jahre verwenden sie schon Gebärdensprache:",
|
||||
"required": "true",
|
||||
"min": "0",
|
||||
"max": "100",
|
||||
"step": "0.5"
|
||||
},
|
||||
"question6_sprachkompetenz": {
|
||||
"type": "numberinput",
|
||||
"name": "gebärdensprachkompetenz",
|
||||
"text": "Wie schätzen sie ihre Gebärdensprachkompetenz ein (1-10):",
|
||||
"required": "true",
|
||||
"min": "1",
|
||||
"max": "10"
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden. \n Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt. Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "demographic_data",
|
||||
"fields": {
|
||||
"alter": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
},
|
||||
"geschlecht": {
|
||||
"type": "string",
|
||||
"size": "14",
|
||||
"nullable": "false"
|
||||
},
|
||||
"hoerstatus": {
|
||||
"type": "string",
|
||||
"size": "14",
|
||||
"nullable": "false"
|
||||
},
|
||||
"bevorzugte_kommunikation": {
|
||||
"type": "string",
|
||||
"size": "22",
|
||||
"nullable": "false"
|
||||
},
|
||||
"gebärdenzeitraum": {
|
||||
"type": "float",
|
||||
"nullable": "false"
|
||||
},
|
||||
"gebärdensprachkompetenz": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Block 3": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "double_video",
|
||||
"list_1": {
|
||||
"video_1": "https://www.youtube-nocookie.com/embed/IqGVT1q1PtM?si=kel7ZWEQl3h-h522",
|
||||
"video_2": "https://www.youtube-nocookie.com/embed/g9KA72jN5SM?si=O7dfqTXdFCCAScJ-"
|
||||
},
|
||||
"list_2": {
|
||||
"video_2": "https://www.youtube-nocookie.com/embed/g9KA72jN5SM?si=O7dfqTXdFCCAScJ-",
|
||||
"video_1": "https://www.youtube-nocookie.com/embed/IqGVT1q1PtM?si=kel7ZWEQl3h-h522"
|
||||
},
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1": {
|
||||
"type": "likert",
|
||||
"name": "likertscale",
|
||||
"text": "Welches Video gefällt ihnen besser?",
|
||||
"required": "true",
|
||||
"points": {
|
||||
"p1": {
|
||||
"value": "1",
|
||||
"text": "Ich finde das linke Video besser"
|
||||
},
|
||||
"p2": {
|
||||
"value": "2",
|
||||
"text": "Ich finde beide Videos gleich gut"
|
||||
},
|
||||
"p3": {
|
||||
"value": "3",
|
||||
"text": "Ich finde das rechte Video besser"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden. Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt. Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "double_video_responses",
|
||||
"fields": {
|
||||
"likertscale": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Block 4": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "empty",
|
||||
"list": {
|
||||
"empty_stimulus": ""
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1": {
|
||||
"type": "textinput",
|
||||
"name": "formfeedback",
|
||||
"text": "Das war der Prototyp für dieses Studientool. Über Feedback würde ich mich freuen. Entweder hier oder per Email unter: jan.dickmann@web.de",
|
||||
"required": "false",
|
||||
"size": "1000"
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden. Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt. Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "feedback_responses",
|
||||
"fields": {
|
||||
"formfeedback": {
|
||||
"type": "string",
|
||||
"size": "1000",
|
||||
"nullable": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
325
slaeforms/userstudy1.json
Normal file
325
slaeforms/userstudy1.json
Normal file
@ -0,0 +1,325 @@
|
||||
{
|
||||
"Block 1": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "empty",
|
||||
"list": {
|
||||
"empty_stimulus": ""
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1_alter": {
|
||||
"type": "numberinput",
|
||||
"name": "alter",
|
||||
"text": "Alter:",
|
||||
"required": "true",
|
||||
"min": "1",
|
||||
"max": "120"
|
||||
},
|
||||
"question2_geschlecht": {
|
||||
"type": "dropdowninput",
|
||||
"name": "geschlecht",
|
||||
"text": "Geschlecht:",
|
||||
"required": "true",
|
||||
"defaulttext": "",
|
||||
"points": {
|
||||
"männlich": {
|
||||
"value": "Männlich",
|
||||
"text": "Männlich"
|
||||
},
|
||||
"weiblich": {
|
||||
"value": "Weiblich",
|
||||
"text": "Weiblich"
|
||||
},
|
||||
"divers": {
|
||||
"value": "Divers",
|
||||
"text": "Divers"
|
||||
},
|
||||
"keine_angabe": {
|
||||
"value": "keine_angabe",
|
||||
"text": "Keine Angabe"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question3_hoerstatus": {
|
||||
"type": "dropdowninput",
|
||||
"name": "hoerstatus",
|
||||
"text": "Hörstatus:",
|
||||
"required": "true",
|
||||
"defaulttext": "",
|
||||
"points": {
|
||||
"hörend": {
|
||||
"value": "Hörend",
|
||||
"text": "Hörend"
|
||||
},
|
||||
"schwerhörig": {
|
||||
"value": "Schwerhörig",
|
||||
"text": "Schwerhörig"
|
||||
},
|
||||
"gehörlos": {
|
||||
"value": "Gehörlos",
|
||||
"text": "Gehörlos"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question4_bevorzugte_kommunikation": {
|
||||
"type": "dropdowninput",
|
||||
"name": "bevorzugte_kommunikation",
|
||||
"text": "Bevorzugte Kommunikationsform:",
|
||||
"required": "true",
|
||||
"defaulttext": "",
|
||||
"points": {
|
||||
"gesprochen": {
|
||||
"value": "Gesprochene Sprache",
|
||||
"text": "Gesprochene Sprache"
|
||||
},
|
||||
"text": {
|
||||
"value": "Text",
|
||||
"text": "Text"
|
||||
},
|
||||
"gebärdensprache": {
|
||||
"value": "Gebärdensprache",
|
||||
"text": "Gebärdensprache"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question5_gebeardenzeitraum": {
|
||||
"type": "numberinput",
|
||||
"name": "gebärdenzeitraum",
|
||||
"text": "Wie viele Jahre verwenden sie schon Gebärdensprache:",
|
||||
"required": "true",
|
||||
"min": "0",
|
||||
"max": "100",
|
||||
"step": "0.5"
|
||||
},
|
||||
"question6_sprachkompetenz": {
|
||||
"type": "numberinput",
|
||||
"name": "gebärdensprachkompetenz",
|
||||
"text": "Wie schätzen sie ihre Gebärdensprachkompetenz ein (1-10):",
|
||||
"required": "true",
|
||||
"min": "1",
|
||||
"max": "10"
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden. \n Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt. Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "demographic_data",
|
||||
"fields": {
|
||||
"alter": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
},
|
||||
"geschlecht": {
|
||||
"type": "string",
|
||||
"size": "14",
|
||||
"nullable": "false"
|
||||
},
|
||||
"hoerstatus": {
|
||||
"type": "string",
|
||||
"size": "14",
|
||||
"nullable": "false"
|
||||
},
|
||||
"bevorzugte_kommunikation": {
|
||||
"type": "string",
|
||||
"size": "22",
|
||||
"nullable": "false"
|
||||
},
|
||||
"gebärdenzeitraum": {
|
||||
"type": "float",
|
||||
"nullable": "false"
|
||||
},
|
||||
"gebärdensprachkompetenz": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Block 2": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "single_video",
|
||||
"order": "random",
|
||||
"list": {
|
||||
"video_1": "https://www.youtube-nocookie.com/embed/iI2bjpgLgu0?si=pWWwitq8Tl9zAs04",
|
||||
"video_2": "https://www.youtube-nocookie.com/embed/R_LNEJiShRM?si=vm5mj-xs04nfijkf",
|
||||
"video_3": "https://www.youtube-nocookie.com/embed/DJnHVnT2YEk?si=e6qe7nrHaRYJ3NQe",
|
||||
"video_4": "https://www.youtube-nocookie.com/embed/6BTZn7tqSzk?si=jQH8RHGMIP9ARsT5",
|
||||
"video_5": "https://www.youtube-nocookie.com/embed/bCRqmhWjuCk?si=iM2dwOSTosLq08Pr",
|
||||
"video_6": "https://www.youtube-nocookie.com/embed/hgE2k8y9-qc?si=kR2rshmVcb9P70r0"
|
||||
},
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1": {
|
||||
"type": "likert",
|
||||
"name": "likertscale",
|
||||
"text": "Wie würden sie dieses Video bewerten?",
|
||||
"required": "true",
|
||||
"points": {
|
||||
"p1": {
|
||||
"value": "1",
|
||||
"text": "Ich finde es gar nicht gut 🙁👎"
|
||||
},
|
||||
"p2": {
|
||||
"value": "2",
|
||||
"text": "Ich finde es nicht gut 👎"
|
||||
},
|
||||
"p3": {
|
||||
"value": "3",
|
||||
"text": "Ich finde es weder gut noch schlecht"
|
||||
},
|
||||
"p4": {
|
||||
"value": "4",
|
||||
"text": "Ich finde es gut 👍"
|
||||
},
|
||||
"p5": {
|
||||
"value": "5",
|
||||
"text": "Ich finde es sehr gut 😊👍"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question2": {
|
||||
"type": "textinput",
|
||||
"name": "text_feedback",
|
||||
"text": "Hier können sie uns Feedback geben",
|
||||
"required": "false",
|
||||
"size": "250"
|
||||
},
|
||||
"question3": {
|
||||
"type": "videoinput",
|
||||
"text": "Hier können sie per Video Feedback geben",
|
||||
"name": "video_feedback",
|
||||
"required": "false"
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden.\\n Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt.\\n Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "single_video_responses",
|
||||
"fields": {
|
||||
"likertscale": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
},
|
||||
"text_feedback": {
|
||||
"type": "string",
|
||||
"size": "250",
|
||||
"nullable": "true"
|
||||
},
|
||||
"video_upload": {
|
||||
"type": "string",
|
||||
"size": "100",
|
||||
"nullable": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Block 3": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "double_video",
|
||||
"list_1": {
|
||||
"video_1": "https://www.youtube-nocookie.com/embed/IqGVT1q1PtM?si=kel7ZWEQl3h-h522",
|
||||
"video_2": "https://www.youtube-nocookie.com/embed/g9KA72jN5SM?si=O7dfqTXdFCCAScJ-"
|
||||
},
|
||||
"list_2": {
|
||||
"video_2": "https://www.youtube-nocookie.com/embed/g9KA72jN5SM?si=O7dfqTXdFCCAScJ-",
|
||||
"video_1": "https://www.youtube-nocookie.com/embed/IqGVT1q1PtM?si=kel7ZWEQl3h-h522"
|
||||
},
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1": {
|
||||
"type": "likert",
|
||||
"name": "likertscale",
|
||||
"text": "Welches Video gefällt ihnen besser?",
|
||||
"required": "true",
|
||||
"points": {
|
||||
"p1": {
|
||||
"value": "1",
|
||||
"text": "Ich finde das linke Video besser"
|
||||
},
|
||||
"p2": {
|
||||
"value": "2",
|
||||
"text": "Ich finde beide Videos gleich gut"
|
||||
},
|
||||
"p3": {
|
||||
"value": "3",
|
||||
"text": "Ich finde das rechte Video besser"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden. Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt. Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "double_video_responses",
|
||||
"fields": {
|
||||
"likertscale": {
|
||||
"type": "integer",
|
||||
"nullable": "false"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Block 4": {
|
||||
"type": "TaskTemplate",
|
||||
"tempalte": "standard_template.html",
|
||||
"stimuli": {
|
||||
"type": "empty",
|
||||
"list": {
|
||||
"empty_stimulus": ""
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"question1": {
|
||||
"type": "textinput",
|
||||
"name": "formfeedback",
|
||||
"text": "Das war der Prototyp für dieses Studientool. Über Feedback würde ich mich freuen. Entweder hier oder per Email unter: jan.dickmann@web.de",
|
||||
"required": "false",
|
||||
"size": "1000"
|
||||
}
|
||||
},
|
||||
"infovideo": {
|
||||
"videourl": "https://www.youtube-nocookie.com/embed/F_w50c5Us3Y?si=-H07MmQ4lYOC2Bwh",
|
||||
"infotext": "Hier wird in Zukunft ein Erklärtext stehen, in dem die Fragestellungen erklärt werden. Dazu werden alle Fragen der Seite einzeln durchgegangen und einfach erklärt. Zum Beispiel wird hier erklärt, dass man um Feedback zu geben, ein Video aufnehmen kann. Dazu drückt man auf den Knopf mit dem Videokamera Symbol. Danach muss man oben links am Browser bestätigen, dass der Browser auf die Kamera zugreifen darf.",
|
||||
"configuration": {
|
||||
"embed": "yt"
|
||||
}
|
||||
},
|
||||
"database_table": {
|
||||
"table_name": "feedback_responses",
|
||||
"fields": {
|
||||
"formfeedback": {
|
||||
"type": "string",
|
||||
"size": "1000",
|
||||
"nullable": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user