Merge pull request #1090 from openHPI/java21-tips-intervention
Add tips intervention for Java2021 course
This commit is contained in:
@@ -768,8 +768,9 @@ var CodeOceanEditor = {
|
|||||||
* interventions
|
* interventions
|
||||||
* */
|
* */
|
||||||
initializeInterventionTimer: function () {
|
initializeInterventionTimer: function () {
|
||||||
|
const editor = $('#editor');
|
||||||
|
|
||||||
if ($('#editor').data('rfc-interventions') || $('#editor').data('break-interventions')) { // split in break or rfc intervention
|
if (editor.data('rfc-interventions') || editor.data('break-interventions') || editor.data('tips-interventions')) { // split in break or rfc intervention
|
||||||
window.onblur = function () {
|
window.onblur = function () {
|
||||||
window.blurred = true;
|
window.blurred = true;
|
||||||
};
|
};
|
||||||
@@ -777,30 +778,31 @@ var CodeOceanEditor = {
|
|||||||
window.blurred = false;
|
window.blurred = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
var delta = 100; // time in ms to wait for window event before time gets stopped
|
const delta = 100; // time in ms to wait for window event before time gets stopped
|
||||||
var tid;
|
let tid;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
data: {
|
data: {
|
||||||
exercise_id: $('#editor').data('exercise-id'),
|
exercise_id: editor.data('exercise-id'),
|
||||||
user_id: $('#editor').data('user-id')
|
user_id: editor.data('user-id')
|
||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
// get working times for this exercise
|
// get working times for this exercise
|
||||||
url: $('#editor').data('working-times-url'),
|
url: editor.data('working-times-url'),
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
var percentile75 = data['working_time_75_percentile'];
|
const percentile75 = data['working_time_75_percentile'];
|
||||||
var accumulatedWorkTimeUser = data['working_time_accumulated'];
|
const accumulatedWorkTimeUser = data['working_time_accumulated'];
|
||||||
|
|
||||||
var minTimeIntervention = 10 * 60 * 1000;
|
const minTimeIntervention = 10 * 1000;
|
||||||
|
|
||||||
|
let timeUntilIntervention;
|
||||||
if ((accumulatedWorkTimeUser - percentile75) > 0) {
|
if ((accumulatedWorkTimeUser - percentile75) > 0) {
|
||||||
// working time is already over 75 percentile
|
// working time is already over 75 percentile
|
||||||
var timeUntilIntervention = minTimeIntervention;
|
timeUntilIntervention = minTimeIntervention;
|
||||||
} else {
|
} else {
|
||||||
// working time is less than 75 percentile
|
// working time is less than 75 percentile
|
||||||
// ensure we give user at least minTimeIntervention before we bother the user
|
// ensure we give user at least minTimeIntervention before we bother the user
|
||||||
var timeUntilIntervention = Math.max(percentile75 - accumulatedWorkTimeUser, minTimeIntervention);
|
timeUntilIntervention = Math.max(percentile75 - accumulatedWorkTimeUser, minTimeIntervention);
|
||||||
}
|
}
|
||||||
|
|
||||||
tid = setInterval(function () {
|
tid = setInterval(function () {
|
||||||
@@ -809,9 +811,20 @@ var CodeOceanEditor = {
|
|||||||
}
|
}
|
||||||
timeUntilIntervention -= delta;
|
timeUntilIntervention -= delta;
|
||||||
if (timeUntilIntervention <= 0) {
|
if (timeUntilIntervention <= 0) {
|
||||||
|
const interventionSaveUrl = editor.data('intervention-save-url');
|
||||||
clearInterval(tid);
|
clearInterval(tid);
|
||||||
// timeUntilIntervention passed
|
// timeUntilIntervention passed
|
||||||
if ($('#editor').data('break-interventions')) {
|
if (editor.data('tips-interventions')) {
|
||||||
|
$('#tips-intervention-modal').modal('show');
|
||||||
|
$.ajax({
|
||||||
|
data: {
|
||||||
|
intervention_type: 'TipIntervention'
|
||||||
|
},
|
||||||
|
dataType: 'json',
|
||||||
|
type: 'POST',
|
||||||
|
url: interventionSaveUrl
|
||||||
|
});
|
||||||
|
} else if (editor.data('break-interventions')) {
|
||||||
$('#break-intervention-modal').modal('show');
|
$('#break-intervention-modal').modal('show');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
data: {
|
data: {
|
||||||
@@ -819,10 +832,10 @@ var CodeOceanEditor = {
|
|||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: $('#editor').data('intervention-save-url')
|
url: interventionSaveUrl
|
||||||
});
|
});
|
||||||
} else if ($('#editor').data('rfc-interventions')) {
|
} else if (editor.data('rfc-interventions')) {
|
||||||
var button = $('#requestComments');
|
const button = $('#requestComments');
|
||||||
// only show intervention if user did not requested for a comment already
|
// only show intervention if user did not requested for a comment already
|
||||||
if (!button.prop('disabled')) {
|
if (!button.prop('disabled')) {
|
||||||
$('#rfc_intervention_text').show();
|
$('#rfc_intervention_text').show();
|
||||||
@@ -833,7 +846,7 @@ var CodeOceanEditor = {
|
|||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
url: $('#editor').data('intervention-save-url')
|
url: interventionSaveUrl
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -296,10 +296,24 @@ raise: false
|
|||||||
|
|
||||||
if @embed_options[:disable_interventions]
|
if @embed_options[:disable_interventions]
|
||||||
@show_rfc_interventions = false
|
@show_rfc_interventions = false
|
||||||
|
@show_break_interventions = false
|
||||||
|
@show_tips_interventions = false
|
||||||
else
|
else
|
||||||
@show_rfc_interventions = (!user_solved_exercise && !user_got_enough_interventions).to_s
|
show_intervention = (!user_solved_exercise && !user_got_enough_interventions).to_s
|
||||||
|
if @tips.present? && Java21Study.show_tips_intervention?(current_user, @exercise)
|
||||||
|
@show_tips_interventions = show_intervention
|
||||||
|
@show_break_interventions = false
|
||||||
|
@show_rfc_interventions = false
|
||||||
|
elsif Java21Study.show_break_intervention?(current_user, @exercise)
|
||||||
|
@show_tips_interventions = false
|
||||||
|
@show_break_interventions = show_intervention
|
||||||
|
@show_rfc_interventions = false
|
||||||
|
else
|
||||||
|
@show_tips_interventions = false
|
||||||
|
@show_break_interventions = false
|
||||||
|
@show_rfc_interventions = show_intervention
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@show_break_interventions = false
|
|
||||||
|
|
||||||
@hide_rfc_button = @embed_options[:disable_rfc]
|
@hide_rfc_button = @embed_options[:disable_rfc]
|
||||||
|
|
||||||
|
@@ -3,8 +3,9 @@
|
|||||||
- consumer_id = @current_user.respond_to?(:external_id) ? @current_user.consumer_id : '' #'tests' #(@current_user.uuid.present? ? @current_user.uuid : '')
|
- consumer_id = @current_user.respond_to?(:external_id) ? @current_user.consumer_id : '' #'tests' #(@current_user.uuid.present? ? @current_user.uuid : '')
|
||||||
- show_break_interventions = @show_break_interventions || "false"
|
- show_break_interventions = @show_break_interventions || "false"
|
||||||
- show_rfc_interventions = @show_rfc_interventions || "false"
|
- show_rfc_interventions = @show_rfc_interventions || "false"
|
||||||
|
- show_tips_interventions = @show_tips_interventions || "false"
|
||||||
- hide_rfc_button = @hide_rfc_button || false
|
- hide_rfc_button = @hide_rfc_button || false
|
||||||
#editor.row data-exercise-id=@exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-submissions-url=submissions_path data-user-id=@current_user.id data-user-external-id=external_user_external_id data-working-times-url=working_times_exercise_path(@exercise) data-intervention-save-url=intervention_exercise_path(@exercise) data-rfc-interventions=show_rfc_interventions data-break-interventions=show_break_interventions data-course_token=@course_token data-search-save-url=search_exercise_path(@exercise)
|
#editor.row data-exercise-id=@exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-submissions-url=submissions_path data-user-id=@current_user.id data-user-external-id=external_user_external_id data-working-times-url=working_times_exercise_path(@exercise) data-intervention-save-url=intervention_exercise_path(@exercise) data-rfc-interventions=show_rfc_interventions data-break-interventions=show_break_interventions data-tips-interventions=show_tips_interventions data-course_token=@course_token data-search-save-url=search_exercise_path(@exercise)
|
||||||
- unless @embed_options[:hide_sidebar]
|
- unless @embed_options[:hide_sidebar]
|
||||||
|
|
||||||
- additional_classes = 'sidebar-col'
|
- additional_classes = 'sidebar-col'
|
||||||
@@ -53,3 +54,4 @@
|
|||||||
|
|
||||||
= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent') unless @embed_options[:disable_rfc]
|
= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent') unless @embed_options[:disable_rfc]
|
||||||
= render('shared/modal', id: 'break-intervention-modal', title: t('exercises.implement.break_intervention.title'), template: 'interventions/_break_intervention_modal') unless @embed_options[:disable_interventions]
|
= render('shared/modal', id: 'break-intervention-modal', title: t('exercises.implement.break_intervention.title'), template: 'interventions/_break_intervention_modal') unless @embed_options[:disable_interventions]
|
||||||
|
= render('shared/modal', id: 'tips-intervention-modal', title: t('exercises.implement.tips.heading'), template: 'interventions/_tips_intervention_modal') unless @embed_options[:disable_hints] or @tips.blank?
|
||||||
|
@@ -0,0 +1,3 @@
|
|||||||
|
h5 == t('exercises.implement.tips_intervention.text')
|
||||||
|
|
||||||
|
= render(partial: 'exercises/tips_content')
|
@@ -438,6 +438,8 @@ de:
|
|||||||
break_intervention:
|
break_intervention:
|
||||||
title: "Pause"
|
title: "Pause"
|
||||||
text: "Uns ist aufgefallen, dass du schon lange an dieser Aufgabe arbeitest. Möchtest du vielleicht später weiter machen um erstmal auf neue Gedanken zu kommen?"
|
text: "Uns ist aufgefallen, dass du schon lange an dieser Aufgabe arbeitest. Möchtest du vielleicht später weiter machen um erstmal auf neue Gedanken zu kommen?"
|
||||||
|
tips_intervention:
|
||||||
|
text: "Es scheint so als würden Sie Probleme mit der Aufgabe haben. </br> </br> Sind Ihnen die Tipps in der linken Seitenleiste aufgefallen? Sie könnten einige Ihrer Fragen beantworten und werden auch direkt hier angezeigt."
|
||||||
error_hints:
|
error_hints:
|
||||||
heading: "Hinweise"
|
heading: "Hinweise"
|
||||||
tips:
|
tips:
|
||||||
|
@@ -438,6 +438,8 @@ en:
|
|||||||
break_intervention:
|
break_intervention:
|
||||||
title: "Break"
|
title: "Break"
|
||||||
text: "We recognized that you are already working quite a while on this exercise. We would like to encourage you to take a break and come back later."
|
text: "We recognized that you are already working quite a while on this exercise. We would like to encourage you to take a break and come back later."
|
||||||
|
tips_intervention:
|
||||||
|
text: "It looks like you may struggle with this exercise. </br> </br> Did you notice the tips in the left sidebar? They might answer some of your questions and are also displayed below for your convenience."
|
||||||
error_hints:
|
error_hints:
|
||||||
heading: "Hints"
|
heading: "Hints"
|
||||||
tips:
|
tips:
|
||||||
|
7
db/migrate/20211114145024_create_tips_intervention.rb
Normal file
7
db/migrate/20211114145024_create_tips_intervention.rb
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class CreateTipsIntervention < ActiveRecord::Migration[6.1]
|
||||||
|
def change
|
||||||
|
Intervention.find_or_create_by(name: 'TipsIntervention')
|
||||||
|
end
|
||||||
|
end
|
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 2021_06_02_071834) do
|
ActiveRecord::Schema.define(version: 2021_11_14_145024) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "pg_trgm"
|
enable_extension "pg_trgm"
|
||||||
|
33
lib/java21_study.rb
Normal file
33
lib/java21_study.rb
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Java21Study
|
||||||
|
def self.get_for(exercise)
|
||||||
|
java21_collection = ExerciseCollection.find_by(name: 'java2021', id: 13)
|
||||||
|
|
||||||
|
exercise.exercise_collections.include? java21_collection
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.show_tips_intervention?(user, exercise)
|
||||||
|
java21_exercise = get_for(exercise)
|
||||||
|
return false unless java21_exercise # Exercise is not part of the experiment
|
||||||
|
|
||||||
|
user_group = UserGroupSeparator.get_intervention_group(user.id)
|
||||||
|
user_group == :show_tips_intervention
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.show_break_intervention?(user, exercise)
|
||||||
|
java21_exercise = get_for(exercise)
|
||||||
|
return false unless java21_exercise # Exercise is not part of the experiment
|
||||||
|
|
||||||
|
user_group = UserGroupSeparator.get_intervention_group(user.id)
|
||||||
|
user_group == :show_break_intervention
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.allow_redirect_to_community_solution?(user, exercise)
|
||||||
|
java21_exercise = get_for(exercise)
|
||||||
|
return false unless java21_exercise # Exercise is not part of the experiment
|
||||||
|
|
||||||
|
user_group = UserGroupSeparator.get_community_solution_group(user.id)
|
||||||
|
user_group == :show_community_solution
|
||||||
|
end
|
||||||
|
end
|
35
lib/user_group_separator.rb
Normal file
35
lib/user_group_separator.rb
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class UserGroupSeparator
|
||||||
|
# Different user groups for the Java21 course based on the user_id
|
||||||
|
# 0: show_tips_intervention && no_b
|
||||||
|
# 1: show_break_intervention && no_b
|
||||||
|
# 2: show_rfc_intervention && no_b
|
||||||
|
# 3: show_tips_intervention && show_b
|
||||||
|
# 4: show_break_intervention && show_b
|
||||||
|
# 5: show_rfc_intervention && show_b
|
||||||
|
|
||||||
|
# separates user into 33% tips interventions, 33% break intervention, 33% rfc intervention
|
||||||
|
def self.get_intervention_group(user_id)
|
||||||
|
user_group = user_id % 6 # => 0, 1, 2, 3, 4, 5
|
||||||
|
case user_group
|
||||||
|
when 0, 3
|
||||||
|
:show_tips_intervention
|
||||||
|
when 1, 4
|
||||||
|
:show_break_intervention
|
||||||
|
else # 2, 5
|
||||||
|
:show_rfc_intervention
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# separates user into 50% with Community Solution, 50% without Community Solution
|
||||||
|
def self.get_community_solution_group(user_id)
|
||||||
|
user_group = user_id % 6 # => 0, 1, 2, 3, 4, 5
|
||||||
|
case user_group
|
||||||
|
when 0, 1, 2
|
||||||
|
:show_community_solution
|
||||||
|
else # 3, 4, 5
|
||||||
|
:no_community_solution
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Reference in New Issue
Block a user