Top level plugin. It defines the 3 columns of the page:
the left menu, the heart of the page and the administrator menu.
This plugin is the page composer, it must be
the last one to be executed. css_attributesCSS selector | English | French |
---|
.heart > DIV P | max-width: 45em ; | .heart > DIV UL | max-width: 45em ; | translationsCSS selector | English | French |
---|
answer_with_linefeed | YOUR ANSWER CONTAINS A LINEFEED | VOTRE REPONSE CONTIENT DES RETOURS A LA LIGNE | answer_with_nbsp | YOUR ANSWER CONTAINS AN UNBREAKABLE SPACE | VOTRE REPONSE CONTIENT UN ESPACE INSÉCABLE | int_required | The answer must be an integer wrote in decimal. | La réponse à cette question doit être un nombre entier écrit en décimal. | possible_answers | Possible answers are: | Les réponses autorisées sont : | string_expected | Your answer must contain: | Dans votre réponse, on devrait trouver : | string_rejected | Your answer must not contain: | Dans votre réponse, on ne doit pas trouver : | yes_or_no | This answer must be YES or NO. | La réponse doit être OUI ou NON. | The ACLS are not predefined, any plugin can add its own.
The roles ACLS may be defined in the user named after the role.
ACLS are taken from:
* The default ACLs from plugin:
acls = {'Default':('executable','hiddable'), 'Teacher':('!executable',)}
* The ACLs from role
* The student ACLs
acls = {plugin_A:('executable',), plugin_B: ('!hiddable', )}
The code assume that :
* The role of a role does not change
* A role is a student: The ACLs of a role are the ACLs of the student | This plugin add links in the 'work done' page in order to
allow students to change an old good answer css_attributesCSS selector | English | French |
---|
/A.question_change_answer | font-size: 60% ; | /A.question_change_answer:before | content:' (change your answer)' | content:' (Changer votre réponse)' | option_help | "integer"
Define the time in seconds allowed to modify an answer
once it has be accepted.
The plugin 'question_change_answer' must be activated. |
---|
| The left column in the page. css_attributesCSS selector | English | French |
---|
.box_title | display: block ; | /@media print | DIV.menu { display: none ; } ; | > DIV | overflow: hidden; max-width: 100%; min-width:100%; transition: max-width 0.5s; webkit-transition: max-width 0.5s; display: inline-block; z-index: 10 ; position: relative | > DIV > TABLE > TBODY > TR > TD | white-space: nowrap ; | > DIV:hover | max-width: 25em; transition: max-width 2s; webkit-transition: max-width 2s ; overflow: visible | Display the identity of the connected user. tip | All the informations about your identity and the current session | Ce bloc dont le titre est votre nom contient toutes les informations concernant votre identité et votre session en cours |
---|
If 15% of the questions are answered
and there is 4 hours without answers.
Then no more answers are allowed.
The student may see there answers. translationsCSS selector | English | French |
---|
session_stopped | The session is terminated | La session est terminée | | Display the realname of the student. option_help | "('ldap.domain.org', 636, 'login', 'password')"
Set the LDAP connection information to retrieve student name and mail.
The value is a python tuple. |
---|
| It rejects any work before the session start. translationsCSS selector | English | French |
---|
session_not_started | The session is not yet started | La session n'a pas encore commencée | tip | Session start date | Date de début de la session |
---|
option_help | "HH:MM DD/MM/YYYY"
Set the examination start date.
The value can be a Python dictionnary with student id as keys,
the default value is defined by the empty ("") key. |
---|
| It rejects any work after the session stop. translationsCSS selector | English | French |
---|
session_stopped | The session is terminated | La session est terminée | tip | Session stop date. | Date de fin de la session. |
---|
option_help | "HH:MM DD/MM/YYYY"
Set the examination termination date. |
---|
| Display the session duration. tip | Time before the session end | Temps restant jusqu'à la fin de la session |
---|
javascript |
var remaining_seconds, starting_time ;
function decrement_time(s)
{
remaining_seconds = s ;
var now = new Date() ;
starting_time = now.getTime() ;
setInterval(update_time, 1000) ;
}
function duration(t)
{
var s ;
var r = t % 60 ;
var t = Math.floor(t / 60) ;
if (r)
{
s = r ;
if (t == 0)
s += 's' ;
}
else
s = "" ;
r = t % 60 ;
t = Math.floor(t / 60) ;
if (t+r && (r != 0 || s != ""))
s = r + "m" + s ;
r = t % 24 ;
t = Math.floor(t / 24) ;
if (t+r && (r != 0 || s != ""))
s = r + "h" + s ;
r = t % 7 ;
t = Math.floor(t / 7) ;
if(t+r && (r != 0 || s != ""))
s = r + "j" + s ;
if (t)
s = t + "s" + s ;
return s ;
}
function update_time()
{
var now = new Date() ;
var s = remaining_seconds - (now.getTime() - starting_time)/1000 ;
s = s.toFixed(0) ;
document.getElementById('remaining').innerHTML = duration(s) ;
if ( s < 300 )
{
document.getElementById('remaining').style.color = '#000' ;
}
if ( s < 60 )
{
document.getElementById('remaining').style.background = '#F00' ;
document.getElementById('remaining').style.color = '#FFF' ;
}
}
|
---|
| Display session start/stop in one line. tip | Session begin and end dates | Dates de début et fin de session |
---|
| The 'logout' button. tip | Deconnexion keep anyone to use your browser to answer the questions | La déconnexion empêche quiconque d'utiliser votre navigateur pour continuer à répondre au questionnaire |
---|
| Set the user language for the session.
It is not a persistent option. | Role ????? Display the 'role' menu. This plugin needs JavaScript.
It will create the 'roles' file with the default role. tip | Choose your role | Permet de choisir votre role |
---|
option_help | "single" or "multiple"
If 'single', a user can have one session active at a time.
So it is not possible to have 2 roles on 2 web pages.
But time accounting is better because students can not
open multiple questions at the same time. |
---|
| For each role, display the number of active users
currently in this role. tip | Number of active users the last 10 minutes per role | Qui a travaillé pendant les 10 dernières minutes en fonction du role |
---|
|
| The questions box, it displays the list of competences. css_attributesCSS selector | English | French |
---|
.box_title | padding-top: 0.5em; padding-bottom: 0.5em; | .box_title CANVAS, .openclose CANVAS, .nice_results CANVAS |
webkit-transition: transform 0.5s;
transition: transform 0.5s;
position: relative ;
transform: scale(1.,1.) ;
| .box_title CANVAS:hover, .openclose:hover CANVAS, .nice_results:hover CANVAS |
transform: scale(2.5,2.5) ;
z-index: 1 ;
}
| .box_title TT | font-weight: normal; font-size: 80% | .line CANVAS | height: 1em ; opacity: 0.6 | .line:hover A | color: #000 | .line:hover CANVAS | opacity: 1 | .nice_results | display: inline-block; vertical-align: bottom; border-spacing: 1px | .nice_results .bad | background: #F00 ; | .nice_results .good | background: #00F ; | .nice_results .perfect | background: #0F0 ; | .nice_results TD | width: 5px; height: 5px; padding: 0px ; | /.competences CANVAS | height: 1em ; | /.title_bar DIV.competences .nice_results | border-spacing: 2px; | /.title_bar DIV.competences .nice_results TD | width: 9px; height: 9px | A.answered | color:#040; | A.bad_answer_given | color:#F00; | A.current_question | text-decoration:underline; | A.highlight | background: black; color: white;text-decoration: blink; | A.indice_given | font-style:italic; | A.max_descendants | font-weight: bold; | A.not_answerable | color:#DDD; | A.not_seen | color:#00F; | A.perfect_answer | color:#0A0; | A.question_given | color:#888; | A.suspended_until | background:#FDD; | VAR | font-style: normal | title | Competences | Compétences |
---|
translationsCSS selector | English | French |
---|
answered>SPAN | A good answer was given | Vous avez bien répondu | bad_answer_given>SPAN | A bad answer was given | Vous avez donné une mauvaise réponse | char_recycle>SPAN | 'Clear your answer to recycle the question | Effacer votre réponse pour recycler la question | nice_results>SPAN | Red: bad answer\A Blue: good answer\A Green : Fast good answer\A\A Click to try another version of the question\A\A If the border is complete:\A you have done all the question versions | Rouge : Mauvais, Bleu : Bon, Vert : Super\A Cliquez pour essayer une autre version de la question.\A Bord complet : toutes les versions ont été vues. | not_answerable>SPAN | Not yet available question | Vous ne l'avez pas encore débloquée | not_seen>SPAN | Never read question | Vous ne l'avez jamais lue | openclose>SPAN | Open/close question list | Ouvre/ferme la liste des questions | perfect_answer>SPAN | Perfect answer time: ready for the exam | Réponse parfaite, prêt pour l'examen | question_erase P | Erase your answer | Effacer votre réponse | question_given>SPAN | Never answered | Vous n'avez pas encore répondu | resigned>SPAN | Never answered | Vous n'avez pas encore répondu | suspended_until>SPAN | Locked question because you tried to many times | Question bloquée car vous avez trop fait d'essai | tip | Choose a 'competence', or open it, or click on the graphic | Cliquez sur une compétence au dessous,
ou ouvrez-là ou bien cliquez sur le graphique |
---|
javascript | /* -*- coding: utf-8 -*- */
add_messages('fr', {
"competences:center_before": "% de réponses rapides (vert)\n",
"competences:center_after": "\nCliquez pour avoir une question adaptée",
"competences:before": "",
"competences:after": "",
"competences:question_before": "",
"competences:question_after": "",
"competences:recycle": "Cliquez sur le disque à gauche du titre pour répondre à une autre version de la question",
"competences:star1": "Vous avez accès à toutes les questions",
"competences:star2": "Vous avez vu toutes les questions",
"competences:star3": "Vous avez répondu correctement à toutes les questions",
"competences:star4": "Vous avez vu toutes les versions des questions",
"competences:star5": "Vous avez répondu rapidement à toutes les questions"
}) ;
add_messages('en', {
"competences:center_before": "% of fast answers (green)\n",
"competences:center_after": "\nClick to pick an adapted question",
"competences:recycle": "Click on the disc to answer another version of the question",
"competences:star1": "You have access to all the questions",
"competences:star2": "You readed all the questions",
"competences:star3": "You correctly answered all the questions",
"competences:star4": "You saw all the questions alternatives",
"competences:star5": "You answered quickly to all the questions"
}) ;
var char_close = '▼' ;
var char_open = '▶' ;
var font_small = "6px sans-serif" ;
var font_normal = "10px sans-serif" ;
var font_selected = "20px sans-serif" ;
var competences = {} ; // competence name -> competence object
var competence_names = [] ; // sorted competences
var current_question = '' ;
var questions = {} ; // question name -> question object
var open_close_is_stats = true ;
var nr_questions = 0 ;
var ordered = [
'suspended_until',
'perfect_answer',
'answered',
'bad_answer_given',
'not_answerable',
'not_seen',
'resigned',
'question_given'
] ;
var student_seed ;
function escape2(txt)
{
return encodeURIComponent(txt) ;
}
function js(t)
{
return "'" + t.toString().replace(/\\/g,'\\\\')
.replace(/"/g,'\\042').replace(/'/g,"\\047").replace(/\n/g,'\\n')
+ "'" ;
}
function stop_event(event)
{
(event || window.event).cancelBubble = true ;
}
function random_jump(question_list)
{
var q = [] ;
for(var question in question_list)
{
q.push(question_list[question]) ;
question_list[question].the_weight = question_list[question].weight() ;
}
q.sort(function(a, b) { return b.the_weight - a.the_weight ; }) ;
q[0].jump() ;
}
function question_redo()
{
window.location.search = "?question=" + escape2(current_question)
+ '&erase=1' ;
}
function Question(info)
{
this.name = info[0] ;
this.classes = info[1] ;
this.nr_bad = info[2] ;
this.nr_good = info[3] ;
this.nr_perfect = info[4] ;
this.competences = info[5] ;
this.level = info[6] ;
this.nr_versions = info[7] ;
this.current = this.name == current_question ;
for(var competence in this.competences)
{
competence = this.competences[competence] ;
if ( competences[competence] === undefined )
competences[competence] = new Competence(competence) ;
competences[competence].add(this) ;
}
}
Question.prototype.weight = function()
{
var weight ;
if ( this.classes.indexOf("not_answerable") != -1
|| this.classes.indexOf("erasable") == -1
)
weight = -2 ;
else if ( this.classes.indexOf("question_given") == -1 ) // NOT GIVEN
weight = 14 ;
else if ( this.nr_bad + this.nr_good == 0 )
weight = 12 ;
else if ( this.nr_good == 0 )
weight = 10 ;
else if ( ! this.is_answered() )
weight = 8 ;
else if ( this.nr_good < this.nr_versions )
weight = 6 ;
else if ( this.nr_perfect == 0 )
weight = 4 + Math.log( (this.nr_bad+1) / this.nr_good ) / 10 ;
else
weight = 2 - this.nr_perfect / this.nr_versions ;
if ( this.current )
weight -= 1 ;
weight += Math.pow(Math.random(), 2) ;
return weight ;
} ;
Question.prototype.jump = function(recycle)
{
var erase = '' ;
if ( this.classes.indexOf("erasable") == -1 )
recycle = false ;
if ( recycle )
erase = '&erase=1' ;
window.location = "?question=" + escape2(this.name) + erase ;
} ;
Question.prototype.nice_results = function(left_to_right)
{
var cols = Math.max(this.nr_bad,
this.nr_good - this.nr_perfect,
this.nr_perfect,
6) ;
var s = ['<a class="tips nice_results"><table class="nice_results">'] ;
function add_line(nr, cls)
{
s.push('<tr>') ;
for(var i=0; i < cols; i++)
{
if ( left_to_right
? i < nr
: i >= cols - nr
)
s.push('<td class="' + cls + '">') ;
else
s.push('<td>') ;
}
s.push("</tr>") ;
}
add_line(this.nr_bad, "bad") ;
add_line(this.nr_good - this.nr_perfect, "good") ;
add_line(this.nr_perfect, "perfect") ;
s.push("</table><span></span></a>") ;
return s.join('') ;
} ;
function draw_nice_results(canvas_id)
{
var c = document.getElementById('C_' + canvas_id) ;
if ( ! c )
return ;
if ( ! c.getContext )
return ;
c.width = c.height ;
var ctx = c.getContext("2d") ;
var q = canvas_question[canvas_id] ;
ctx.translate(c.width/2, c.height/2) ;
var n = 2 * Math.PI / (q.nr_bad + q.nr_good) ;
if ( q.nr_bad + q.nr_good == 0 )
{
slice(ctx, "#FFFFFF", 0 , c.width/2, 0, 1, "") ;
slice(ctx, "#808080", c.width/2.1, c.width/2, 0, 1, "") ;
return ;
}
var t = [ ["", 0],
["#0F0", q.nr_perfect],
["#44F", q.nr_good],
["#F00", q.nr_bad + q.nr_good]
] ;
for(var i = 1; i < t.length; i++)
{
if ( !q.is_answered || q.is_answered() )
ctx.fillStyle = t[i][0] ;
else
ctx.fillStyle = t[i][0].replace(/[^#F]/g, "9") ;
slice_path(ctx, 0, c.width/2, t[i-1][1] * n, t[i][1] * n) ;
ctx.fill() ;
}
if ( q.nr_versions )
{
ctx.globalAlpha = 0.8 ;
var good = 2 * Math.PI * Math.min(q.nr_good, q.nr_versions
) / q.nr_versions ;
ctx.fillStyle = "#FFF" ;
slice_path(ctx, c.width/2.4, c.width/2, good, 2 * Math.PI) ;
ctx.fill() ;
ctx.fillStyle = "#000" ;
slice_path(ctx, c.width/2.4, c.width/2, 0, good) ;
ctx.fill() ;
if ( q.nr_good > q.nr_versions )
{
var good = 2 * Math.PI * Math.min(q.nr_good - q.nr_versions,
q.nr_versions
) / q.nr_versions ;
slice_path(ctx, c.width/2.8, c.width/2.4, 0, good) ;
ctx.fill() ;
}
}
}
var canvas_id = 0 ;
var canvas_question = {} ;
Question.prototype.click = function()
{
this.jump(true) ;
}
Question.prototype.icons = function(left_to_right, classe)
{
var c = left_to_right ? 0 : canvas_id++ ;
if ( classe === undefined )
classe = "nice_results" ;
canvas_question[c] = this ;
return '<div class="competences" style="display:inline">'
+ '<a class="tips ' + classe + '" onclick="'
+ (questions[this.name] ? 'questions' : 'competences')
+ '[' + js(this.name) + '].click()"><canvas id="C_'
+ c + '"></canvas><span></span></a></div>' ;
} ;
Question.prototype.is_answered = function()
{
return this.classes.indexOf("answered") != -1 ;
} ;
function MyRand(seed_between_0_1)
{
this.seed = 2 * Math.PI * seed_between_0_1 ;
}
MyRand.prototype.get = function(max)
{
var n = Math.sin(this.seed) ;
this.seed++ ;
return Math.floor(Math.abs(n * max * 10000)) % max ;
}
function html(txt)
{
return txt.replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<");
}
Question.prototype.display_name = function()
{
var name = html(this.name) ;
var short_name = name.split(":") ;
if ( isNaN(short_name[1]) )
return name ;
name = "" ;
var c = "BCFRTNSDL" ;
var v = "aeiou" ;
var rand = new MyRand(student_seed + 1 / (1 + short_name[1]))
for(var i=0 ; i < 3 ; i++)
{
name += c.substr(rand.get(c.length), 1) ;
name += v.substr(rand.get(v.length), 1) ;
}
return short_name[0] + ":" + name ;
}
Question.prototype.html = function()
{
var info = '' ;
for(var i in ordered)
{
if ( this.classes.indexOf(ordered[i]) != -1 )
{
info = ordered[i] ;
break ;
}
}
if ( this.current )
info += ' current_question' ;
return (open_close_is_stats ? ' ' : '')
+ this.icons()
+ '<a class="tips ' + info + '" onclick="questions['
+ js(this.name) + '].jump()">' + this.display_name() + '<span>'
+ '</span></a>' ;
} ;
function Competence(name)
{
this.name = name ;
this.questions = [] ;
this.nr_bad = 0 ;
this.nr_good = 0 ;
this.nr_perfect = 0 ;
this.nr_versions = 0 ;
this.level = 1e9 ;
competence_names.push(name) ;
}
Competence.prototype.add = function(question)
{
this.questions.push(question) ;
this.nr_bad += question.nr_bad ;
this.nr_good += question.nr_good ;
this.nr_perfect += question.nr_perfect ;
this.nr_versions += question.nr_versions ;
this.level = Math.min(question.level, this.level) ;
} ;
Competence.prototype.sort = function()
{
this.questions.sort(function(a,b) { return a.level - b.level ; }) ;
} ;
Competence.prototype.is_open = function()
{
return localStorage[this.name] == '1' ;
} ;
Competence.prototype.open = function()
{
localStorage[this.name] = '1' ;
} ;
Competence.prototype.toggle = function()
{
localStorage[this.name] = this.is_open() ? '0' : '1' ;
update_competences() ;
} ;
Competence.prototype.choose_question = function()
{
// this.open() ;
random_jump(this.questions) ;
}
Competence.prototype.nr_questions_perfect = function()
{
var nr = 0 ;
for(var i in this.questions)
if ( this.questions[i].nr_perfect )
nr++ ;
return nr ;
}
Competence.prototype.classe = function()
{
var keys = {} ;
for(var question in this.questions)
{
q_info = this.questions[question].classes.split(/ */) ;
for(var i in q_info)
{
if ( keys[q_info[i]] === undefined )
keys[q_info[i]] = 0 ;
keys[q_info[i]]++ ;
}
}
if ( keys['perfect_answer'] == this.questions.length )
info = 'perfect_answer' ;
else if ( keys['answered'] == this.questions.length )
info = 'answered' ;
else if ( keys['not_answerable'] == this.questions.length )
info = 'not_answerable' ;
else if ( keys['not_seen'] )
info = 'not_seen' ;
else if ( keys['resigned'] )
info = 'question_given' ;
else if ( keys['suspended_until'] )
info = 'suspended_until' ;
else if ( keys['bad_answer_given'] )
info = 'bad_answer_given' ;
else
info = '' ;
return info ;
} ;
Competence.prototype.icons = Question.prototype.icons ;
Competence.prototype.click = function()
{
this.toggle(true) ;
}
Competence.prototype.html = function()
{
if (this.name === '')
return '' ;
var link = '<a class="tips ' + this.classe()
+ '" onclick="competences[' + js(this.name) + '].choose_question()">' ;
return (open_close_is_stats ? '': link)
+ (open_close_is_stats
? this.icons(false, 'openclose')
: '<var onclick="competences['+ js(this.name)
+ '].toggle();stop_event(event)">'
+ (this.is_open() ? char_close : char_open)
+ '</var> '
)
+ (open_close_is_stats ? link : '')
+ this.name + '<span></span></a>' ;
} ;
function get_color(nr_bad, nr_good, nr_perfect)
{
var s = nr_bad + nr_good ;
if ( s == 0 )
return [1, 1, 1] ;
s *= 2 ;
return [0.5 + nr_bad / s, 0.5 + nr_perfect / s,
0.5 + (nr_good - nr_perfect) / s] ;
}
Competence.prototype.color = function()
{
return get_color(this.nr_bad, this.nr_good, this.nr_perfect) ;
} ;
function update_competences()
{
var s = [] ;
canvas_id = 1 ; // Do not erase the title canvas
for(var competence in competence_names)
{
competence = competences[competence_names[competence]] ;
s.push('<div class="line">') ;
s.push(competence.html()) ;
s.push('</div>') ;
if ( competence.is_open() || competence.name === '' )
{
for(var question in competence.questions)
{
s.push('<div class="line">') ;
s.push(competence.questions[question].html()) ;
s.push('</div>') ;
}
}
}
document.getElementById("competences").innerHTML = s.join('\n') ;
for(var i = 0; i < canvas_id; i++)
draw_nice_results(i) ;
}
function patch_title()
{
var d = document.getElementsByTagName('DIV') ;
var title ;
var state = "", heart ;
for(var i = 0 ; i < d.length; i++)
{
if ( d[i].className == 'competences' )
{
title = title || d[i].getElementsByTagName('EM')[0] ;
}
else if ( d[i].className == 'title_bar' )
{
var q = questions[current_question] ;
if ( q )
{
var icon = document.createElement("TD") ;
icon.style = "font-size: 200%" ;
icon.innerHTML = questions[current_question].icons(true) ;
var tr = d[i].getElementsByTagName("TR")[0] ;
tr.childNodes[1].getElementsByTagName(
"A")[0].innerHTML = q.display_name() ;
tr.insertBefore(icon, tr.childNodes[1]) ;
draw_nice_results(0) ;
}
display_sunburst(title, -300, -300) ;
heart = d[i].parentNode ;
}
else if ( d[i].className == 'question_bad' )
state = "bad" ;
else if ( d[i].className == 'question_good' )
state = "good" ;
else if ( d[i].className == 'question_answer' && state === '' )
{
if ( d[i].innerHTML.match(/<form /) )
state = "asked" ;
else
state = "done" ;
}
}
if ( heart
&& current_question && current_question !== ''
&& get_level() > 0.05
)
{
var s = '' ;
var q = questions[current_question] ;
var c = q.competences ;
for(var competence in c)
{
competence = c[competence] ;
s += '<div class="question_good" style="display:inline">'
+ '<a class="tips key_enter">'
+ '<button onclick="competences[\'' + competence
+ '\'].choose_question()"><p> ∈ ' + competence
+ '</p></button></a></div>' ;
}
s += '<div class="' + (questions[current_question].nr_versions < 2
? 'question_erase' : 'question_redo')
+ '" style="display:inline"><a class="tips question_redo">'
+ '<button onclick="question_redo()" style="background:#FEE"'
+ (questions[current_question].classes.indexOf("erasable") != -1
? '' : ' disabled')
+ '><p></p></button><span></span></a></div>' ;
var more = document.createElement("DIV") ;
more.style.marginTop = "1em" ;
more.className = "competences" ;
more.innerHTML = '<div class="question_good" style="display:inline">'
+ '<a class="tips key_enter">'
+ '<button onclick="click_on_next_button()"><p></p></button>'
+ (state === 'done' || state == "good" ? '<span></span>' : '')
+ '</a></div>'
+ s ;
heart.appendChild(more) ;
var e = document.getElementById('question_good_buttons') ;
if ( e )
e.style.display = "none" ;
}
if ( ! heart )
setTimeout(patch_title, 10) ;
}
function hex2(x)
{
x = Math.floor(255*x).toString(16) ;
if ( x.length < 2 )
x = "0" + x ;
return x ;
}
function hex_color(color)
{
return "#" + hex2(color[0]) + hex2(color[1]) + hex2(color[2]) ;
}
function slice_path(ctx, radius0, radius, angle1, angle2)
{
ctx.beginPath() ;
ctx.moveTo(radius0 * Math.cos(angle1), radius0 * Math.sin(angle1)) ;
ctx.lineTo(radius * Math.cos(angle1), radius * Math.sin(angle1)) ;
ctx.arc(0, 0, radius, angle1, angle2) ;
ctx.lineTo(radius0 * Math.cos(angle2), radius0 * Math.sin(angle2)) ;
ctx.arc(0, 0, radius0, angle2, angle1, true) ;
ctx.closePath() ;
}
function slice(ctx, color, radius0, radius, angle1, angle2, text, x, y)
{
angle1 += 0.0001 ;
angle2 -= 0.0001 ;
if ( angle2 < angle1 )
return ;
angle1 = 2 * Math.PI * angle1 ;
angle2 = 2 * Math.PI * angle2 ;
ctx.fillStyle = color ;
slice_path(ctx, radius0, radius, angle1, angle2) ;
var inside = x && ctx.isPointInPath(x, y) ;
if ( color !== '' )
ctx.fill() ;
if ( inside && text != "" )
{
if ( text.indexOf(":") == -1 )
slice_path(ctx, radius0, 150, angle1, angle2) ;
ctx.fillStyle = "#FFFFFF" ;
ctx.globalAlpha = 0.5 ;
ctx.fill() ;
ctx.globalAlpha = 1 ;
}
if ( text !== "" )
{
var scale = 0.2 ;
ctx.save() ;
ctx.scale(scale, scale) ;
var angle = (angle1 + angle2) / 2 ;
if ( angle > Math.PI/2 && angle < 3*Math.PI/2 )
{
angle += Math.PI ;
radius0 *= -1 ;
ctx.textAlign = "end" ;
}
var display_text = text ;
if ( text.substr(0,1) == " " )
{
// Center label
display_text = text.substr(1) ;
if ( inside )
display_text = _("competences:center_before") + display_text
+ _("competences:center_after") ;
ctx.textAlign = "center" ;
}
else
{
if ( inside )
{
if ( text.indexOf(":") == -1 )
{
display_text = _("competences:before") + display_text
+ _("competences:after") ;
}
else
{
display_text = _("competences:question_before")
+ display_text + _("competences:question_after") ;
}
}
}
ctx.rotate(angle) ;
ctx.fillStyle = "#000000" ;
if ( inside )
ctx.font = font_selected ;
else
{
if ( angle2 - angle1 > 0.08 )
ctx.font = font_normal ;
else
ctx.font = font_small ;
}
var t = display_text.split('\n') ;
var h = ctx.font.split('px')[0] ;
ctx.translate(0, h*(0.5 - t.length/2)) ;
for(var i in t)
{
ctx.fillText(t[i], radius0/scale, 0) ;
ctx.translate(0, h) ;
}
ctx.restore() ;
}
return inside ? text : false ;
}
function get_xy(event)
{
event = event || window.event ;
if ( event.touches && event.touches.length >= 1 )
{
var finger0 = event.touches[0] ;
return [finger0.pageX, finger0.pageY - 30] ;
}
else
return [event.pageX, event.pageY] ;
}
var do_draw_sunburst = false ;
function draw_sunburst(x, y)
{
do_draw_sunburst = [x, y] ;
}
function zoom_me_move(event)
{
xy = get_xy(event) ;
draw_sunburst(xy[0], xy[1]) ;
}
function zoom_me(event)
{
var e = document.createElement("DIV") ;
e.style.position = "absolute" ;
e.style.left = "0%" ;
e.style.right = "0%" ;
e.style.top = "0%" ;
e.style.bottom = "0%" ;
e.style.zIndex = 11 ;
e.id = "competences_zoomed" ;
e.onmousemove = zoom_me_move ;
e.addEventListener("touchmove", zoom_me_move, false);
e.onclick = function(event) {
event = event || window.event ;
draw_sunburst(event.pageX, event.pageY) ;
select = draw_sunburst_real() ;
if ( select )
{
if ( select.substr(0, 1) == " " )
random_jump(questions) ;
else if ( questions[select] )
questions[select].jump() ;
else if ( competences[select] )
competences[select].choose_question() ;
else
alert("BUG=(" + select + ')') ;
}
else
e.parentNode.removeChild(e) ;
} ;
document.getElementsByTagName("BODY")[0].appendChild(e) ;
xy = get_xy(event) ;
display_sunburst(e, e.offsetWidth, e.offsetHeight, xy[0], xy[1]) ;
}
Question.prototype.sunburst = function(ctx, center, scale, i, x, y)
{
var i_next = i + 1./nr_questions ;
slice(ctx, "#FFA0A0",
center + scale*this.nr_good,
center + scale*(this.nr_good + this.nr_bad),
i, i_next, "", x, y) ;
slice(ctx, "#8080FF",
center + scale*this.nr_perfect,
center + scale*this.nr_good,
i, i_next, "", x, y) ;
slice(ctx, "#40DD40",
center,
center + scale*this.nr_perfect,
i, i_next, "", x, y) ;
slice(ctx, "#CCC", center * 0.9, center, i,
i + Math.min(this.nr_good, this.nr_versions)
/ this.nr_versions / nr_questions,
"", x, y) ;
if ( this.nr_good > this.nr_versions )
slice(ctx, "#888", center * 0.9, center, i,
i + Math.min(this.nr_good - this.nr_versions, this.nr_versions)
/ this.nr_versions / nr_questions,
"", x, y) ;
var selected = slice(ctx, "",
center,
center + scale*(this.nr_good + this.nr_bad),
i, i_next, this.display_name(), x, y) ;
if ( this.name == current_question )
slice(ctx, "#FFFF00", center * 0.8, center * 0.9, i, i_next, "", x, y) ;
return selected ;
} ;
function draw_sunburst_real()
{
if ( ! do_draw_sunburst )
return ;
var select ;
var ctx = display_sunburst.ctx ;
x = do_draw_sunburst[0] ;
y = do_draw_sunburst[1] ;
if ( x )
{
ctx.fillStyle = "#FFFFFF" ;
ctx.fillRect(-100, -100, 200, 200) ;
}
var i = 0 ;
var scale = 5 ;
var center = 20 ;
var nr_perfect = 0, nr_good = 0, nr_bad = 0 ;
var redraw, selected_question ;
for(var competence in competences)
{
competence = competences[competence] ;
var i_start = i ;
for(var question in competence.questions)
{
question = competence.questions[question] ;
var question_hover = question.sunburst(ctx, center, scale, i, x, y) ;
if ( question_hover !== false )
{
redraw = i ;
selected_question = question ;
}
select = question_hover || select ;
i += 1./nr_questions ;
}
if ( redraw !== undefined )
selected_question.sunburst(ctx, center, scale, redraw, x, y) ;
select = slice(ctx, hex_color(competence.color()),
center / 3., center * 0.8, i_start, i,
competence.name, x, y) || select ;
nr_good += competence.nr_good ;
nr_perfect += competence.nr_perfect ;
nr_bad += competence.nr_bad ;
}
var pc = Math.floor(100 * nr_perfect / (nr_bad+nr_good)) ;
if ( isNaN(pc) )
pc = "0" ;
select = slice(ctx,
hex_color(get_color(nr_bad, nr_good, nr_perfect)),
0, center / 3. * 0.8, 0, 1, ' ' + pc + '%',
x, y) || select ;
do_draw_sunburst = false ;
return select ;
}
var star_color = "#0D0" ;
var star_color_bad = "#CCC" ;
var tip_style = ' style="z-index:1000; color:#000"' ;
var star_good = '<b style="color:' + star_color + ';display:inline">★</b>';
var star_bad = '<b style="color:'+star_color_bad+ ';display:inline">★</b>';
function progress_bar(percent)
{
return '<b style="display: inline-block; height: 0.5em; width:5em;'
+ 'border-radius: 0.2em; background: ' + star_color_bad + ';">'
+ '<span style="background:' + star_color
+ ';display:block; text-align:left; width: '
+ percent + '%; height: 100%"></span></b>' ;
}
function display_sunburst(d, width, height, x, y)
{
var c = document.createElement('CANVAS') ;
if ( ! c.getContext )
return ;
if ( width < 0 )
{
var level = get_level() ;
var s = '<br><a class="tips">' ;
for(var i=1; i<6; i++)
s += (level >= i ? star_good : star_bad) ;
s += '<span' + tip_style + '>' ;
for(var i=1; i<6; i++)
s += (level >= i ? star_good : star_bad)
+ _("competences:star" + i) + '<br>' ;
s += '</span></a>' ;
if ( level < 5 )
s += '<br><a class="tips">'
+ progress_bar(100*(level%1)) + '<span' + tip_style + '>'
+ (100*(level % 1)).toFixed(0) + '% → ' + star_good
+ _("competences:star" + Math.ceil(level))
+ '</span></a>' ;
d.innerHTML = s ;
height = -height ;
width = -width ;
c.style.position = "absolute" ;
c.style.left = "0px" ;
c.style.top = "0px" ;
c.style.width = d.offsetHeight ;
c.style.height = d.offsetHeight ;
c.onclick = zoom_me ;
}
var ctx = c.getContext("2d") ;
c.width = width ;
c.height = height ;
d.appendChild(c) ;
ctx.translate(width/2, height/2) ;
ctx.scale(width/200, width/200) ;
ctx.textBaseline = "middle";
display_sunburst.ctx = ctx ;
draw_sunburst(x, y) ;
return c ;
}
function display_competences(data, question, seed)
{
current_question = question ;
student_seed = seed / 1000000000 ;
for(var i in data)
questions[data[i][0]] = new Question(data[i]) ;
for(var competence in competences)
competences[competence].sort() ;
competence_names.sort(
function(a,b) { return competences[a].level - competences[b].level ;}) ;
document.write('<div id="competences"></div>') ;
update_competences() ;
for(var competence in competences)
nr_questions += competences[competence].questions.length ;
if ( document.getElementsByTagName("BODY")[0] )
document.getElementsByTagName("BODY")[0].onkeypress = function(event) {
if ( event.eventPhase == Event.AT_TARGET && event.keyCode == 13 )
random_jump(questions) ;
e = document.getElementById("competences_zoomed") ;
if ( e )
e.parentNode.removeChild(e) ;
} ;
patch_title() ;
setInterval(draw_sunburst_real, 100) ;
}
// 0 - 1 : % questions accessibles
// 1 - 2 : % questions viewed
// 2 - 3 : % questions correctly answered
// 3 - 4 : % questions perfectly answered
// 4 - 5 : % questions versions done
function get_level()
{
var nr = 0 ;
var nr_accessible = 0 ;
var nr_view = 0 ;
var nr_good = 0 ;
var nr_perfect = 0 ;
var nr_versions = 0 ;
var nr_total_versions = 0 ;
var level ;
for(var question in questions)
{
question = questions[question] ;
nr++ ;
if ( question.classes.indexOf("not_answerable") == -1 )
nr_accessible++ ;
if ( question.classes.indexOf("question_given") != -1 )
nr_view++ ;
if ( question.nr_good )
nr_good++ ;
if ( question.nr_perfect )
nr_perfect++ ;
if ( question.nr_good >= question.nr_versions )
nr_versions++ ;
nr_total_versions += question.nr_versions ;
if ( false )
{
console.log(question) ;
console.log(question.name + ' ' + question.weight()) ;
}
}
if ( nr_accessible < nr )
level = nr_accessible / nr ;
else if ( nr_view < nr )
level = 1 + nr_view / nr ;
else if ( nr_good < nr )
level = 2 + nr_good / nr ;
else if ( nr_versions < nr )
level = 3 + nr_versions / nr ;
else
level = 4 + nr_perfect / nr ;
if ( true )
console.log('questions=' + nr
+ ' accessible=' + nr_accessible
+ ' view=' + nr_view
+ ' good=' + nr_good
+ ' perfect=' + nr_perfect
+ ' all_versions_done=' + nr_versions
+ ' total_versions=' + nr_total_versions
+ ' level=' + level
) ;
return level ;
} |
---|
option_help | #seconds
The student can erase its answer and try another question version
if the last answer is older than this time.
It is to not have students retrying to many times. |
---|
| The questions box, it displays the allowed questions. css_attributesCSS selector | English | French |
---|
A.bad_answer_given | color:#F00; | A.current_question | text-decoration:underline; | A.highlight | background: black; color: white;text-decoration: blink; | A.indice_given | font-style:italic; | A.max_descendants | font-weight: bold; | A.question_given | color:#888; | title | Questions | Les questions |
---|
tip | Choose your question in the following list | Vous devez choisir une question parmi les suivantes |
---|
option_help | "integer"
If the number of questions in the menu is greater than
this number, then pulldown menus are used. |
---|
Display a menu allowing to choose between seeing all the questions
or only the allowed ones. translationsCSS selector | English | French |
---|
all | All | Toutes | normal | Possible | Normal | tip | Choose your question list:
* All the questionnary questions.
* The possible questions as in the students list. | Choix de la liste des questions à afficher :
* Toutes les questions qui existent.
* Celles accessibles normalement avec les prérequis. |
---|
| If enabled, this plugin shuffle the allowed question list. | Next question ????? Allow to go to the next question in alphabetical order. tip | Goto the next question in alphabetical order. | Passez à la question suivante dans l'ordre alphabétique |
---|
| No more questions!!! ????? Display an informative text when there is no more questions to answer. tip | You have finished the questionnary. Congratulation! | Vous êtes arrivé au bout du questionnaire, félicitations ! |
---|
|
| An IFRAME containing data
from a server locally launched by Quenlig on the student computer.
Only useful for the 'cs-xxx' questionnaries css_attributesCSS selector | English | French |
---|
IFRAME | width:100%; height: 21em; border: 0px | javascript |
function cs_loaded()
{
if ( document.getElementById("cs_script").src === "" )
return;
document.getElementById("cs_script").cs_loaded = true ;
document.getElementById("cs_script").onload = function() { } ;
}
function launch_local_server()
{
var miframe = document.getElementById("cs_script") ;
if ( ! miframe.cs_loaded )
{
miframe.src = "data:text/html;charset=utf8,Lancement du serveur de surveillance." ;
document.getElementsByTagName("BODY")[0].innerHTML += '<img width=1 height=1 src="'
+ window.location.toString().split('?')[0]
+ '?cs_state=start">' ;
}
}
function reload_cs_state()
{
document.getElementById("cs_script").src = "http://127.0.0.1:51342/?i="
+ reload_cs_state.i++ ;
}
reload_cs_state.i = 0 ;
|
---|
| The statistics menu box. title | Statistics | Statistiques |
---|
tip | Information about the questions and your progression within the group. | Informations concernant les exercices à faire et votre progression dans le groupe |
---|
Add smileys to the statistics of good/bad/tip/... translationsCSS selector | English | French |
---|
statmenubad-1 | You give many bad answers. Check your answer before answering | Testez votre réponse avant de la donner | statmenubad-2 | You give really too many bad answers! | Vous répondez vraiment trop souvent des bétises ! | statmenubad1 | Fine, you give not many bad answers. | Bien, vous donnez peu de mauvaises réponses | statmenubad2 | Good! You give not many bad answers. | Vous vous trompez vraiment pas souvent ! | statmenugood-1 | Your are behind the other | Vous êtes en retard | statmenugood-2 | Your are behind the other, ask help to the teacher | Vous êtes très en retard, faites vous aider | statmenugood1 | Fine, continue | Bien, continuez | statmenugood2 | Good! | Très bien ! | statmenuindice-1 | You ask many tips. | Vous regardez trop les indices | statmenuindice-2 | You ask too much tip. Try to think by yourself. | Vous demandez systématiquement les indices, c'est pas bien | statmenuindice1 | Fine, you ask not many tip. | Bien, vous regardez peu les indices | statmenuindice2 | Good. You use really not many tip! | Vous utilisez très peu les indices ! | statmenutime-1 | After you have given a good answer, choose quickly another question. | Après avoir répondu, passez rapidement à une autre question | statmenutime-2 | You take too much time without question displayed on your screen | Vous passez trop de temps sans question affichée | statmenutime1 | You should read the the informations given after you correctly answered a question | Vous devriez lire ce qui est affiché après avoir répondu | statmenutime2 | You do not read the explanations displayed after you correctly answered a question | Vous ne lisez pas les explications affichées après avoir répondu | | Displays a graphical state of the questions and students css_attributesCSS selector | English | French |
---|
| position: relative; height: 35em | .bad | color:red | .me | background: #FF0; | .ok | color:green | A.tips:hover TT | left:30em; width:24em; top: -3em; font-size: 100% | DIV | position: absolute; font-family: monospace | SPAN | top: 5em; left:20em; width:20em | tip | '.' are peoples, 'x' are questions, the yellow square: it's you. Verticaly it's the level, and horizontaly it's the average time. | Les '.' sont les personnes, les 'x' les questions et le carré jaune, c'est vous. Verticalement c'est le niveau et horizontalement, c'est le temps de réflexion. |
---|
javascript |
function time_to_slot(x)
{
return Math.log(x/15) / Math.log(1.500000) ;
}
function histogram(t, time_searching)
{
var s = '' ;
var h = 17 ;
var m = 1.7 ;
var mx = 1 ;
var dx = 3 ;
var x ;
var slot = time_to_slot(time_searching).toFixed(0) ;
for(var i=5; i<2*h; i++)
s += ' <br>' ;
for(var i in t)
{
s += '<div style="height:' + Math.abs(m*t[i]).toFixed(1)
+ 'em;left:' + (dx+mx*i).toFixed(1)
+ 'em;top:' + Math.min(h-m*t[i], h).toFixed(1)
+ 'em;border:1px solid black'
+ (i == slot ? ';background:green' : '')
+ '">'
+ ' '
+ '</div>' ;
}
for(var i=-9; i<=9; i++)
{
s += '<div style="left:0px;top:' + (h-m*i-0.5).toFixed(1)
+ 'em">'
+ (i >= 0 ? ' ' + i : i )
+ '</div>' ;
}
for(var i=1; i<200; i*=5)
{
x = dx + mx * time_to_slot(i*60) ;
s += '<div style="left:' + x.toFixed(0) + 'em;top:' + (2*h) + 'em">'
+ i
+ 'min.</div>' ;
}
document.write(s) ;
}
|
---|
| CSV rank export ????? The output of this plugin is a CSV file containing for each student
the normalized number of good/bad answers and indices.
There is also the work time in hours. tip | Table to import into a spreadsheet, for each student there is:
The student name
#good answers
#bad answers
#given tips
Work time in hours
Values are normalized between 0 and 1. | Tableau intégrable dans un tableur avec pour chaque étudiant :
Nom de l'étudiant
#bonnes réponses
#mauvaises réponses
#indices affichés
Temps passé en TP en heures
Les différentes valeurs sont normalisées 0 c'est aucun et 1 c'est le maximum. |
---|
| ????? good answers color:green The number of good answers. tip | Number of good answer you have given | Nombres de bonnes réponses que vous avez donné |
---|
| ????? bad answers color:red The number of bad answers. tip | Number of bad answer you have given, do not randomly answer if you can test your answer. | Nombres de mauvaises réponses que vous avez donné, évitez de répondre au hasard si vous avez la possibilité de tester. |
---|
| ????? tips asked The number of given tips. tip | Number of tips you have asked | Nombres d'indices différents que vous avez regardés |
---|
| ????? questions defined The total number of questions. tip | Total number of question. | Nombres de questions que le système contient. |
---|
| ????? of work Display the student work time. translationsCSS selector | English | French |
---|
no_more_time | No more time to answer. | Temps de réflexion dépassé, vous ne pouvez plus répondre | tip | The time you were working | Le temps que vous avez passé à travailler |
---|
option_help | "{'':60, 'student1': 90}"
A Python dictionnary with the maximum number of minutes
of work time per student. The key is the student ID.
The '' key indicates the default time. |
---|
| Position: ????? Displays the student rank computed with the number of good answers.
It is only useful when all the students are working together. tip | Your position in the group (this is not your grade) | Votre classement dans le groupe (ceci n'est pas votre note) |
---|
| Students ????? Displays a statistics table about all the students. translationsCSS selector | English | French |
---|
//CAPTION | For each student. display statistics about its work | Pour chaque étudiant affiche les statistiques concernant l'ensemble de son travail | //c0 | Name | Nom | //c0>SPAN | Link to the student work. | Pointeur sur les statistiques de l'étudiant | //c1 | Good | Bon | //c10 | Sim. | //c10>SPAN | Simultaneous answers with other students | Taux de réponses simultanés (sans intérêt) | //c11 | Var. | //c11>SPAN | Standard deviance of the student reflexion time for all the questions | Variance du temps de réflexion sur l'ensemble des questions | //c12 | IP | //c12>SPAN | Last connection IP of the student | Dernière IP utilisée | //c1>SPAN | #good answer (green: behind the others, red: late) | Nombre de bonnes réponses (vert si en avance et rouge si en retard) | //c2 | Disp. | Posé | //c2>SPAN | #known questions | Nombre de questions connues | //c3 | Bad | Mau. | //c3>SPAN | #bad answers (green: no many, red: many. The color take into account the number of known questions.) | Nombre de mauvaises réponses (vert si peu de mauvaises réponses par rapport au nombre de questions connues. Pour rouge, c'est qu'il y a trop de mauvaises réponses) | //c4 | Tip | Ind. | //c4>SPAN | #tips asked (green: no many, red: many. The color take into account the number of known questions.) | Nombre d'indices vus (vert si peu d'indices demandés par rapport au nombre de questions connues. Pour rouge, c'est qu'il y a trop d'indices demandés) | //c5 | // | //c5>SPAN | #comments | Nombre de commentaires laissés | //c6 | Search | Cherche | //c6>SPAN | Searching answer time | Temps total passé à chercher les réponses | //c7 | After | Après | //c7>SPAN | Time between questions (red: the student take too many time to choose another question, green: the student go too quickly to another question without reading the answer comment | Temps total passé avant de passer à la question suivante en cas de bonne réponse (rouge : l'étudiant passe trop de temps sans question affiché sur l'écran. Vert: l'étudiant passe à la question suivante sans même lire ce qui est affiché sur l'écran) | //c8 | First | Première | //c8>SPAN | First connection | Première connexion | //c9 | Last | Dernière | //c9>SPAN | Last connection | Dernière connexion | tip | For each student. display statistics about its work | Pour chaque étudiant affiche les statistiques concernant l'ensemble de son travail |
---|
| Questions ????? Displays session statistics about the questions. translationsCSS selector | English | French |
---|
//CAPTION | For each question, display statistics about all the students | Pour chaque question affiche les statistiques concernant l'ensemble des étudiants | //c0 | The question | La question | //c0>SPAN | The question | La question pour laquelle on donne les statistiques | //c1 | Saw | Vue | //c1>SPAN | 0: Nobody saw it, 1: Everybody saw it | 0: Personne ne la connaît, 1: tous le monde la connaît | //c2 | Display | Posées | //c2>SPAN | #displayed on screen / #students saw it | Nombre de fois quelle a été posée / Nombre de personne qui la connaisse | //c3 | Answered | Répondus | //c3>SPAN | 0: Nobody answered, 1: All students knowing it answered it | 0: Personne n'a répondu, 1: tous ceux qui la connaisse ont répondu | //c4 | Bad | Mauvaise | //c4>SPAN | #bad answers / #students saw it | Nombre de mauvaises réponses / Nombre de personnes qui la connaisse | //c5 | Tips | Indices | //c5>SPAN | #tip / #students saw it | Nombre d'indices / Nombre de personnes qui la connaisse | //c6 | time | Temps | //c6>SPAN | Full time HH:MM:SS to answer the question | Temps total HH:MM:SS passé pour répondre à la question | //c7 | Comment | Commentaire | //c7>SPAN | #comments about the question | Nombre de commentaires déposés | //c8 | P.Time | //c8>SPAN | Current perfect time in seconds | Temps courant pour avoir une réponse parfaite | tip | For each question, display statistics about all the students | Pour chaque question affiche les statistiques concernant l'ensemble des étudiants |
---|
|
| The 'action' box tip | Select the action you want to do | Choisissez ce que vous voulez faire |
---|
Debug ????? Allow to display plugin definition in tips from the plugin interface css_attributesCSS selector | English | French |
---|
a.tips > div.tips > div | white-space: pre; | tip | Activate debugging on this page | Activation du débuggage sur cette page |
---|
| Session options ????? Allow to change session options css_attributesCSS selector | English | French |
---|
/.options TEXTAREA | width: 40em; height: 100% | ??? | /BUTTON.save_options:before | content:'Save the options' | content:'Sauver les options' | translationsCSS selector | English | French |
---|
//CAPTION | View or set the session options | ??? | //c0 | Command line option and plugin name | Option de ligne de commande et plugin | //c1 | Documentation | //c2 | Default value | Valeur par défaut | //c3 | Current value | Valeur courante | tip | View or set the session options | Affiche ou modifie les options de la session |
---|
| Allow to change the ACL of users and roles. css_attributesCSS selector | English | French |
---|
/.doc | font-size: 70%; | /.nowrap | white-space: nowrap ; | /A.change_acl:before | content:'Edit the access rights (ACL)' | content:'Editer les droits d\'accès (ACL)' | /BUTTON.change_acl_save | font-size: 130% | /BUTTON.change_acl_save:before | content:'Save the ACL' | content:'Sauvegarder les droits' | /tt.roles | font-size: 70%; font-weight: normal ; | javascript |
function change_acls(user)
{
var f = document.getElementById('acls_form') ;
var selects = f.getElementsByTagName('SELECT') ;
var s = [user] ;
for(var i=0; i<selects.length; i++)
s.push( selects[i].name + '=' + selects[i].selectedIndex ) ;
window.location = '?change_acl=' + s.join(',') ;
}
|
---|
| Work done by the others ????? Display the questions and answers of any student.
This plugin link is not visible on the web page.
To use it, you must click on a student name on the student statistics page. css_attributesCSS selector | English | French |
---|
.comment | background: #DDD ; | DIV.an_answer, PRE.an_answer | font-weight: bold ; | TABLE.bad_answer .an_answer | background: #FDD ; | TABLE.good_answer .an_answer | background: #DFD ; | translationsCSS selector | English | French |
---|
//an_answer | Your answer: | Votre réponse : | //answered_by | Answered by: | Réponses de : | //comment TD | Your comment: | Votre commentaire : | tip | See all the questions and answers in the work you have done | Voir toutes les questions et réponses qui ont été faites |
---|
| Reload plugins ????? Reload all the modified Quenlig plugins.
It is currently not working nicely, do not try to use. tip | Reload server plugin
This does not reload question definitions | Recharge les plugins du serveur s'ils ont été modifié
Cela ne recharge pas les questions |
---|
| Reload question ????? Reload the current question source file.
This plugin can be used while a real session is running.
It is not totally safe, if you introduce a syntax error in the module,
the server will need a restart to restore the question file. tip | Reload the Python file containing the question definition | Relit le fichier Python contenant la définition de la question |
---|
| When called, generate 'Students/SESSION/perfect_time.py'
with the current 'perfect_time' for each question.
If the file exists, it is readed on question loading | Delete students ????? Destroy all the students with 0 or 1 good answer. translationsCSS selector | English | French |
---|
//deleted | Theses students have been deleted from the system. The bracketed number indicate the number of good answers they have given | Ces étudiants ont été enlevés du système. Le nombre entre parenthèses indique le nombre de bonnes réponses qu'ils ont donnés | tip | Delete the students having answered only to a couple of question | Détruit tous les étudiants qui n'ont donné aucune bonne réponse |
---|
| Question graph ????? Display the question graph with statistics for this session. tip | Display the question graph with session statistics. Click to see SVG file | Affiche le graphe des questions avec les statistique de la session. Cliquez pour voir le fichier SVG |
---|
| The work done ????? Display all the questions and answer given by the connected student. css_attributesCSS selector | English | French |
---|
.comment | background: #DDD ; | DIV.an_answer, PRE.an_answer | font-weight: bold ; | TABLE.bad_answer .an_answer | background: #FDD ; | TABLE.good_answer .an_answer | background: #DFD ; | translationsCSS selector | English | French |
---|
//an_answer | Your answer: | Votre réponse : | //answered_by | Answered by: | Réponses de : | //comment TD | Your comment: | Votre commentaire : | tip | See all the questions and answers in the work you have done | Voir toutes les questions et réponses qui ont été faites |
---|
| Visible ????? This plugin allows to remove acls to others users.
It is not yet working. css_attributesCSS selector | English | French |
---|
/TT.hide | background:yellow | /TT.hide:before | content:'×' | tip | Visibility management of plugins | Gestion des vues |
---|
javascript | var hide_message = 'Give the role/student list to which remove this plugin:' ;
function hide_stop_event(event)
{
if ( event.stopPropagation )
event.stopPropagation(true) ;
if ( event.preventDefault )
event.preventDefault(true) ;
else
{
event.returnValue = false;
event.keyCode = 0;
}
event.cancelBubble = true ;
}
function hide(event, plugin)
{
hide_stop_event(event) ;
var who = prompt('«' + plugin + '»\n\n' + hide_message, hide_roles) ;
window.location = '?hide=' + plugin + ',' + who ;
return false ;
}
| var hide_message = 'Donnez la liste des roles à qui faut-il enlever ce droit :' ;
function hide_stop_event(event)
{
if ( event.stopPropagation )
event.stopPropagation(true) ;
if ( event.preventDefault )
event.preventDefault(true) ;
else
{
event.returnValue = false;
event.keyCode = 0;
}
event.cancelBubble = true ;
}
function hide(event, plugin)
{
hide_stop_event(event) ;
var who = prompt('«' + plugin + '»\n\n' + hide_message, hide_roles) ;
window.location = '?hide=' + plugin + ',' + who ;
return false ;
}
|
---|
| Load old students ????? Destroy all the students with 0 or 1 good answer. tip | Load student who have not worked since a long time. | Charge les anciens, même ceux qui n'ont pas travaillé depuis longtemps |
---|
option_help | "#days"
Students who have not worked the last #days are not loaded
on startup and so not used to compute statistics or export grades.
If the number of days is negative: it is the number of seconds
allowed to read the student list, the most recent firsts. |
---|
| Course documentation ????? Display all the questions definition. css_attributesCSS selector | English | French |
---|
.question_title | margin-top: 1.5em ; margin-bottom: 0em }/BODY { orphans: 3; widows: 3; | /.course_question | page-break-before: avoid | /@media print | .hide_on_print { display: none ; }
BODY, H1,
TABLE.information_table TD,
TABLE.information_table TH
{ background: #FFF }
DIV.heart { margin-left: -1em }
| /@media screen | .hide_on_screen { display: none ; | /H2 | page-break-after: avoid | /H3 | page-break-after: avoid | tip | Display the full course documentation | Voir le support de cours complet |
---|
javascript |
function add_courses_index()
{
var t = document.getElementsByTagName("DIV") ;
var course_menu, keys = [] ;
for(var i in t)
{
if ( t[i].className == 'course_question' )
{
var q = t[i].getElementsByTagName('A')[0].textContent ;
var tt = t[i].getElementsByTagName('KEY') ;
for(var k=0; k < tt.length; k++)
keys.push([tt[k].textContent, q]) ;
}
else if ( t[i].className == 'courses'
&& t[i].parentNode.className != "heart_content" )
course_menu = t[i] ;
}
var t = document.getElementsByTagName("A") ;
var toc = [] ;
for(var i in t)
{
if ( ! t[i].name )
continue ;
if ( t[i].name.substr(0,3) != 'toc' )
continue ;
toc.append('<a href="' + window.location + '#' + t[i].name + '">'
+ t[i].innerHTML + '</a>') ;
}
var s = [] ;
keys.sort() ;
for(var j in keys)
s.push('<a href="?question='+escape2(keys[j][1])+'">'
+ keys[j][0] + '</a>') ;
if ( s.length || toc.length )
course_menu.innerHTML = '<br>' + toc.join("<br>") + '<br>'
+ 'Index:</br>'
+ '<div style="margin-left:1em; font-size: 80%">'
+ s.join('<br>')
+ '</div>' ;
}
setTimeout(add_courses_index, 500) ;
|
---|
| Help/Explanations ????? Display the file 'help.html' in a frame.
Any questionnary can redefine its own page. translationsCSS selector | English | French |
---|
//object_unsupported | Your browser does not know OBJECT tag. | Votre navigateur ne supporte pas la balise OBJECT | tip | See the help page about this work | Voir une page d'aide concernant le TP |
---|
option_help | "true" or "false"
Display HTML/help.html when starting a session. |
---|
| The good answers ????? Display all the questions definition. tip | See the answers | Voir les réponses |
---|
|
| Analyse menu title | Analysis tools | Analyser |
---|
tip | Analysis tools | Divers outils pour analyser le travail |
---|
All the comments ????? displays all the comments about all the questions. translationsCSS selector | English | French |
---|
//CAPTION | The students comments | Les commentaires déposés par les étudiants | //c0 | The question | La question | //c0>SPAN | The commented question. It's None if there was no active question | La question pour laquelle l'étudiant à déposé un commentaire. Il y a None si aucune question n'était affichée lors du dépôt du commentaire | //c1 | Comment | Commentaire | //c1>SPAN | The comment | Le texte du commentaire déposé par l'étudiant | //c2 | Student | Étudiant | //c2>SPAN | Display the student answers | Voir les réponses de l'étudiant | //c3 | Date | //c3>SPAN | The comment date | La date de dépôt du commentaire | tip | All the students comments | L'ensemble des commentaires qui ont été déposés par l'ensemble des étudiants |
---|
| Answered questions ????? Display for each question answered the informations about the question.
Not really useful.
It should be enhanced to allow the teacher to see these informations
for the other students. translationsCSS selector | English | French |
---|
//CAPTION | Information about each question saw by the student | Pour chaque question, indique comment l'étudiant a répondu | //c0 | Date | //c0>SPAN | The last time the question was saw | Le moment ou la question a été vue la dernière fois | //c1 | OK | //c1>SPAN | True if the good answer was given | True si la bonne réponse a été donnée | //c2 | #Disp. | #Vus | //c2>SPAN | Number of the the question was displayed | Nombre de fois que la question a été vue | //c3 | #Bad | #Mau. | //c3>SPAN | Number of bad answer given | Nombre de mauvaises réponses données | //c4 | Tip | Indices | //c4>SPAN | #tip saw / #tip total | Nombre d'indices vue / nombre d'indice total | //c5 | #Com. | //c5>SPAN | #comment leaved for the question | Nombre de commentaire déposés | //c6 | Time | Temps | //c6>SPAN | Time with this question on screen | Temps passé avec la question affichée sur l'écran | //c7 | Question | //c7>SPAN | A link the the question itself | Le nom de la question avec un lien vous dirigeant vers la question | tip | Statistics about the questions a student answered | Statistiques sur les questions auxquelles un étudiant a répondu |
---|
| Recompute grades ????? DANGEROUS: allow to recompute all the automatic computed grades.
DO NOT USE if the grading is contextual to the student.
It is only useful if the grading functions are modified after
the examination. translationsCSS selector | English | French |
---|
//grade_recompute | Automatic grading recomputed | Le recalcul des notations automatique est terminé | tip | Beware: DO NOT USE IN CASE OF CONTEXTUAL GRADING. It is only useful if you have modified an automatic grading test | Attention : NE PAS FAIRE SI LA NOTATION EST CONTEXTUELLE. C'est seulement utile dans le cas où vous avez modifié le test de notation automatique |
---|
| Histogram good answer ????? Display the histogram of the number of good and bad answers
for all the students. translationsCSS selector | English | French |
---|
//histogram | Good answer histogramm | L'histogramme du nombre de bonnes réponses | histobad | Bad answer histogram | L'histogramme du nombre de mauvaises réponses | tip | See the number of good answers histogram per student | Voir l'histogramme du nombre de bonnes réponses par étudiants |
---|
| Session graphic ????? Display an SVG graphic of the session with all the questions and statistics.
This graphic is very slow to display so it is unusable. tip | Display a SVG graphic about the state of the student group and their answers. | Affiche un fichier SVG représentant graphiquement la façon dont le groupe répond à l'ensemble des questions. |
---|
| Cheaters too fast ????? Detection of students answering too quickly. translationsCSS selector | English | French |
---|
//CAPTION | Student answering too quickly to questions. Number of questions answered with 10, 20 and 40 less time than the average answer time | Étudiants répondant trop rapidement. Nombre de questions répondues en 10, 20, 40 fois moins de temps que le temps moyen de réponse. | //c0 | Student | Étudiant | //c1 | 10 time | 10*+rapide | //c2 | 20 time | 20*+rapide | //c3 | 40 time | 40*+rapide | tip | Search students answering too quickly. | Cherche ceux qui répondent trop vite (liste bonne réponses) |
---|
| Cheaters pairs ????? Detection of the student always giving the same answer at the same time. translationsCSS selector | English | French |
---|
//CAPTION | Students working not alone | Étudiants travaillant à plusieurs | //c0 | Student 1 | Étudiant 1 | //c0>SPAN | A student of the couple | Un des étudiants | //c1 | Student 2 | Étudiant 2 | //c1>SPAN | Another student of the couple | L'autre étudiant | //c2 | 1 copied on 2 | 1 copie su 2 | //c2>SPAN | Number of good answers given by 1 less than one minute after the good answer given by 2 | Nombre de bonne réponses saisies par 1 moins d'une minute après une bonne réponse saisie par 2 | //c3 | 2 copied on 1 | 2 copie sur 1 | //c3>SPAN | Number of good answers given by 2 less than one minute after the good answer given by 1 | Nombre de bonne réponses saisies par 2 moins d'une minute après une bonne réponse saisie par 1 | //c4 | % copied from 2 | % de bonne réponse copiées par 1 | //c4>SPAN | Percentage of answers copied from the student 2 | Pourcentage de bonne réponses copiées sur 2 | //c5 | % copied from 1 | % de bonne réponse copiées par 2 | //c5>SPAN | Percentage of answers copied from the student 1 | Pourcentage de bonne réponses copiées sur 1 | no_pairs_found | No cheater pair found. | Aucun copieur n'a été trouvé. | tip | Search cheaters pairs | Cherche les copieurs |
---|
|
| Allow to evaluate arbitrary Python code for debugging. css_attributesCSS selector | English | French |
---|
BUTTON | width: 100% ; | FORM.highlight BUTTON P | background: #CFC ; | TEXTAREA | font-size: 80% ; width: 100% | translationsCSS selector | English | French |
---|
evaluate_button | Run! | Exécuter | evaluate_result | Result: | Résultat : | tip | Type Python code here. | Taper du code Python ici |
---|
| Allow the students to leave a comment about the question. css_attributesCSS selector | English | French |
---|
.comment_given | white-space: normal; | :hover FORM | max-height: 20em | BUTTON | width: 100% ; white-space: normal | FORM |
max-height: 0px ;
margin: 0px;
transition: max-height 1s;
webkit-transition: max-height 1s;
overflow: hidden ;
| FORM.highlight | max-height: initial ; | FORM.highlight BUTTON P | background: #CFC ; | TEXTAREA | font-size: 80% ; width: 100% | translationsCSS selector | English | French |
---|
comment_button | Send your comment | Envoyer votre commentaire | comment_given | Your comment: | Votre commentaire : | tip | If there is a problem in the question (ambiguity, grammar...).
If more tips are needed.
If an answer you think good is rejected.
Then: leave a comment. | S'il y a un problème dans l'énoncé de la question (ambiguïté, grammaire, ...).
Si les indices ne sont pas suffisants.
Si une réponse que vous considérez bonne n'est pas acceptée.
Alors : laissez un commentaire. |
---|
javascript |
function PersistentInput(element_id, name)
{
this.input = document.getElementById(element_id) ;
this.form = this.input ;
while( this.form.tagName != 'FORM' )
this.form = this.form.parentNode ;
this.key = 'persistent_input/' + element_id + '/' + (name || '') ;
if ( this.get_persistent() !== '')
{
this.input.value = this.get_persistent() ;
this.show() ;
}
this.form.onsubmit = this.onsubmit.bind(this) ;
if ( this.input.onkeypress )
this.old_onkeypress = this.input.onkeypress.bind(this) ;
this.input.onkeypress = this.onkeypress.bind(this) ;
this.input.persistent = this ;
}
PersistentInput.prototype.debug = function(txt)
{
if ( false )
console.log(this.key + " " + txt + " " + this.input.value) ;
} ;
PersistentInput.prototype.get_persistent = function()
{
this.debug("GET") ;
return localStorage[this.key] || '' ;
} ;
PersistentInput.prototype.set_persistent = function(txt)
{
this.debug("SET") ;
localStorage[this.key] = txt ;
this.show() ;
} ;
PersistentInput.prototype.show = function()
{
this.debug("SHOW") ;
this.form.className = this.input.value != '' ? "highlight" : '' ;
} ;
PersistentInput.prototype.onkeypress_real = function()
{
this.debug("KEYREAL") ;
this.set_persistent(this.input.value) ;
} ;
PersistentInput.prototype.onkeypress = function(event)
{
this.debug("KEY (" + event.char + ") code=" + event.keyCode) ;
if ( event.char === '' && event.keyCode != 9 )
return ;
// Needed because INPUT.value is modified after the keypress
setTimeout(this.onkeypress_real.bind(this), 100) ;
if ( this.old_onkeypress )
this.old_onkeypress(event) ;
} ;
PersistentInput.prototype.onsubmit = function()
{
this.debug("SUBMIT") ;
this.set_persistent("") ;
} ;
|
---|
option_help | ("the_teacher@university.org", "smtp.university.org")
If defined, on each student comment:
a mail is sent to 'the_teacher@university.org'
via the 'smtp.university.org' mail server. |
---|
| Display a graphical map of the questions. css_attributesCSS selector | English | French |
---|
IMG | width: 100% ; margin-top: 0.3em ; | tip | There is a square per question, the first questions are on the left, the last on the right.
Yellow: The question on screen
Green: question answered correctly
Red: question you answered incorrectly
Dark blue: question you may look but you did not.
Light Blue: you saw the question text
The color is lighter if tips have been asked. | Il y a un carré par question, on part de la gauche on doit arriver à droite.
Jaune : la question affichée sur l'écran
Vert : question à laquelle vous avez répondu correctement
Rouge : question pour laquelle votre dernière réponse était fausse
Bleu foncé : question qu'il est possible de regarder
Bleu clair : Question abandonnée
La couleur est plus pâle si des indices ont été demandés. |
---|
| About Quenlig box. Running version of Quenlig tip | QUENLIG version number | Version de QUENLIG utilisée |
---|
| Display the directory name containing the questionnary tip | The questionnary is in this directory | Nom du répertoire contenant la définition du questionnaire |
---|
| ????? seconds CPU time used to create the HTML page tip | CPU time used to generate this page | Temps CPU utilisé pour générer cette page |
---|
|
|
| The heart of the web page. css_attributesCSS selector | English | French |
---|
.box_title | padding: 2px; | > DIV | margin-top: 0.7em; | > DIV > TABLE.box_content | background: #EEE ; | An horizontal bar at the top of the page. Display the page title. tip | It's the question name or the page title if you are not answering to a question | C'est le nom de la question ou le titre de la page si vous n'êtes pas en train de répondre à une question |
---|
option_help | "Title of the session"
It is displayed as the page title if there is no current question. |
---|
| Display the mean time used by student to answer the current question. tip | Average search time before answering correctly to this question | Temps de réflexion moyen de l'ensemble du groupe pour cette question |
---|
| Display the remaining time to answer the current question. css_attributesCSS selector | English | French |
---|
#ttl | font-size: 70%; font-weight: bold | tip | Remaining time to answer | Temps restant pour répondre à la question |
---|
|
| display the 'before answering' informations box. title | Before answering | Avant de répondre |
---|
tip | Information displayed here are courses remainder and/or action you must do before answering the question. | Les informations affichées ici sont des rappels de cours et/ou des actions que vous devez effectuer avant de répondre à la question. |
---|
| This plugin display the content of the first plugin with
an not empty attribute named 'heart_content'.
This allow plugins in the menu to display their content in the
heart of the page when clicked, for example the 'action_help' plugin. | Display the question text. tip | The question you must answer | La question que l'on vous pose et à laquelle vous devez répondre |
---|
option_help | "(nr_bad_answers, multiply, max_suspend)"
After 'nr_bad_answers': the student must wait 1 minute
before answering again.
After each new bad answer, the wait time is multiplied by 'multiply'.
The maximum wait time is 'max_suspend' minutes. |
---|
| It both display the INPUT HTML tag to enter the answer
but it also verify the answer.
As the answer may modify the question list, it must be executed
before the question list computation. css_attributesCSS selector | English | French |
---|
.show_on_hover | overflow: hidden ; max-height: 0px ; transition: max-height 1s ; webkit-transition: max-height 1s ; | :hover .show_on_hover | max-height: 10em | BUTTON | margin-top: 0.5em | BUTTON P | margin: 0px ; | FORM | margin: 0px | INPUT | width: 100% ; font-family: times; font-size:120% | INPUT.checkbox | width: auto | TEXTAREA | width: 100% ; | title | ('Your answer', 'Your answer was') | ('Votre réponse', 'Vous avez répondu') |
---|
translationsCSS selector | English | French |
---|
answer_button | Send the answer | Envoyer la réponse | maximum_bad_answer | You can no more answer to this question, choose another one | Vous ne pouvez plus répondre à cette question, choisissez en une autre | missing_required | You must answer some other questions to open this one | Vous devez avancer dans le questionnaire avant de pouvoir répondre à cette question | nr_try | Number of remaining answer attempts: | Nombre d'essais que vous pouvez encore faire : | suspended_until | You made too many tries, you must now wait before checking a new answer. Beware, the wait time is multiplied on each bad answer: | Vous avez fait trop de mauvaises réponses, vous devez maintenant attendre avant de faire une autre proposition. Attention le temps d'attente augmente à chaque mauvaise réponse : | tip | Do not forget to test your answer before validating it, If no, you may give incorrect answer. | Pensez à tester votre réponse dans la réalité avant de la saisir ici, afin d'éviter des erreurs bêtes |
---|
javascript |
function disable_tab(event)
{
if ( window.event )
event = window.event ;
key = event.keyCode ;
if(key == 9)
{
event.target.value += ' ' ;
return false;
}
else
return true;
}
function check_button(e)
{
while(e.tagName != 'FORM')
e = e.parentNode ;
var input = e.getElementsByTagName("INPUT") ;
var button = e.getElementsByTagName("BUTTON")[0] ;
for(var i in input)
if ( input[i].checked )
{
button.disabled = false ;
return ;
}
button.disabled = true ;
}
function seconds()
{
var t = new Date() ;
return t.getTime() / 1000 ;
}
var suspended_until_time ;
function change_state(state)
{
var t = document.getElementById("questionanswer") ;
if (state)
t.action = "javascript: alert('⏱' + duration((suspended_until_time - seconds()).toFixed(0)))" ;
else
t.action = "#" ;
}
function update_suspended_time()
{
var e = document.getElementById("suspended_until") ;
if ( ! e )
return ;
var dt = suspended_until_time - seconds() ;
change_state(dt > 0);
if ( dt <= 0 )
{
// Activate
e.innerHTML = " GO!" ;
e.id = "" ;
change_state(false);
}
else
e.innerHTML = " <b>" + duration(dt.toFixed(0)) + '</b>' ;
}
function suspended_until(t)
{
if ( seconds() > t )
return ;
document.write('<span id="suspended_until" class="suspended_until"></span>');
suspended_until_time = t ;
setInterval(update_suspended_time, 1000) ;
}
|
---|
option_help | "always" or "hover"
When returning to an answered question the last answer is displayed
automaticaly or only if the mouse goes on the box title. |
---|
| This plugin allow to do an autoevaluation of questions and students level.
There is no more question choice for students.
To make it work, the ACLS: Students/SESSION/Logs/Student/acls
Must be set to :
{
'question_bad': ('!executable',),
'map': ('!executable',),
'answered': ('!executable',),
'about': ('!executable',),
'about_questions': ('!executable',),
'about_time': ('!executable',),
'about_version': ('!executable',),
'action': ('!executable',),
'question_before': ('!executable',),
'question_good': ('!executable',),
'question_indices': ('!executable',),
'question_required': ('!executable',),
'questions': ('!executable',),
'questions_nomore': ('!executable',),
'questions_shuffle': ('!executable',),
'session_duration': ('!executable',),
'session_start': ('!executable',),
'session_stop': ('!executable',),
'statmenu_bad': ('!executable',),
'statmenu_good': ('!executable',),
'statmenu_indice': ('!executable',),
'statmenu_nr_questions': ('!executable',),
'statmenu_rank': ('!executable',),
'statmenu_smiley': ('!executable',),
'statmenu_time': ('!executable',),
'comment': ('hide',),
'autoeval': ('executable',),
'autoeval_stats': ('executable',),
} translationsCSS selector | English | French |
---|
autoeval_good | Congratulation! You can continue if you want: | Bravo, vous pouvez continuer si vous le désirez. | give_solution | Give your answer above and strike 'Enter'. | Saisissez la réponse au dessus et tapez sur la touche 'Entrée'. | giveup_problem | I give up: I will never see again this problem. | J'abandonne : je ne pourrais plus faire ce problème. | intro_problem | Problems are in limited time (less than one hour) and can not be paused. The only way to start another problem is to give up or answer successfuly. Click on the button to start: | Les problèmes sont en temps limité (moins d'une heure) et ne peuvent être suspendus. Les seuls moyens de changer de problème sont d'abandonner ou bien de réussir. Cliquer sur le bouton pour le lancer : | nomore_problem | No more problem to do. | Il n'y a plus de problèmes à faire pour le moment. | start_problem | Start a new problem | Démarrer un nouveau problème | | Add the REDO button after the student answer. css_attributesCSS selector | English | French |
---|
BUTTON P:before | content:'Answer another version' | content:'Autre version' | translationsCSS selector | English | French |
---|
/.question_redo SPAN | Erase your answer so you can try another version of the question | Effacer votre réponse pour pouvoir répondre à une version différente de cette question | tip | Erase your answer so you can try another version of the question | Effacer votre réponse pour pouvoir répondre à une version différente de cette question |
---|
| Display the information box in case of good answer. title | Good answer! | Bonne réponse ! |
---|
translationsCSS selector | English | French |
---|
/.key_enter P | next question | Autre question | /.key_enter SPAN | Hit «Enter» to see the next question | Appuyez sur «Entrée» pour avoir la prochaine question | javascript |
function click_on_next_button()
{
var e = document.getElementById(1) ;
if ( e )
{
window.location = e.href ;
}
else
{
// We want the same behaviour than the enter key
triggerKeyboardEvent(document.getElementsByTagName('BODY')[0], 13) ;
}
}
|
---|
| This plugin display a box with the information about the bad answer. title | Bad answer | Mauvaise réponse |
---|
| Displays the box with the tips for the current question. title | Tips to help you | Des indices pour vous aider |
---|
translationsCSS selector | English | French |
---|
first_indice | Give me a tip | Donnez-moi un indice | next_indice | Give me another tip | Donnez-moi un autre indice | tip | If you have no idea about a way to answer, you may ask a tip | Si vous n'avez aucune idée sur la manière de répondre à la question, demandez un indice |
---|
| Spoil the answer:
* Minimum and maximum size in characters of the good answers css_attributesCSS selector | English | French |
---|
| display: inline | .spoil | display: inline ; position: relative; margin-left: 1em | .spoil:hover .spoil_tip | opacity: 1 ; transition: opacity 8s; webkit-transition: opacity 8s; | .spoil_tip | opacity: 0; pointer-events: none ; position:absolute; bottom:1.5em; left: 0px; padding-right: 1em; transition: opacity 0.5s; webkit-transition: opacity 0.5s; | .spoil_tip *, .spoil_tip | background: #FFE ; | translationsCSS selector | English | French |
---|
spoil | 📦 | spoil_char | characters | caractères | spoil_diff | compared to expected answers: | comparée aux réponses attendues : | spoil_diff_ok | contains the good characters | contient les bons caractères | spoil_less | is too short of | est trop courte de | spoil_miss | Missing chars | Il manque | spoil_more | is too long of | est trop longue de | spoil_ok | has the right length | est de la bonne longueur | spoil_unexpected | Unexpected chars | En trop | javascript |
var spoil ;
function Spoil(goods)
{
this.goods = goods ;
this.spoil_min = 1e30 ;
this.spoil_max = 0 ;
for(var i in this.goods)
{
this.goods[i] = this.canonize(this.goods[i]) ;
if ( this.goods[i].length < this.spoil_min )
this.spoil_min = this.goods[i].length ;
if ( this.goods[i].length > this.spoil_max )
this.spoil_max = this.goods[i].length ;
}
document.write('<div class="spoiler">'
+ '<div class="spoil" onmouseover="spoil.length(event)">'
+ '<span class="spoil_tip"></span></div>'
+ '<div class="spoil" onmouseover="spoil.diff(event)">'
+ '<span class="spoil_tip"></span></div>'
+ '</div>'
);
}
Spoil.prototype.canonize = function(txt) {
var t = [] ;
txt = txt.replace(/ /g, '') ;
for(var i=0; i<txt.length; i++)
t.push(txt.substr(i, 1)) ;
t.sort() ;
return t.join('') ;
} ;
Spoil.prototype.answer = function(txt) {
var f = document.getElementById('questionanswer') ;
if ( ! f )
return ;
var input = (f.getElementsByTagName("INPUT")
|| f.getElementsByTagName("TEXTAREA"))[0] ;
return this.canonize(input.value) ;
} ;
Spoil.prototype.feedback = function(event, content) {
var t = (event || window.event).target ;
if ( t.className != 'spoil' )
return ;
t.firstChild.innerHTML = content ;
} ;
Spoil.prototype.distance = function(a, b) {
var r1 = 0 ;
var r2 = 0 ;
var ca, cb, miss_a = "", miss_b = "" ;
a += '\uFFFF' ;
b += '\uFFFF' ;
while( r1 < a.length || r2 < b.length )
{
ca = a.substr(r1, 1) ;
cb = b.substr(r2, 1) ;
if ( ca == cb )
{
r1++ ;
r2++ ;
}
else if ( ca < cb )
{
miss_b += ca ;
r1++ ;
}
else
{
miss_a += cb ;
r2++ ;
}
}
return [miss_a, miss_b] ;
}
Spoil.prototype.diff = function(event) {
var answer = this.answer() ;
if ( answer === undefined )
return ;
var s = [] ;
for(var i in this.goods)
{
var d = this.distance(answer, this.goods[i]) ;
var x = '' ;
if ( d[0] !== '' )
x += '<b style="color:#0A0">' + html(d[0]) + '</b>' ;
if ( d[1] !== '' )
x += '<b style="color:#800">' + html(d[1]) + '</b>' ;
if ( x !== '' )
s.push('<tr><td>' + d[0] + '<td>' + d[1] + '</tr>') ;
}
if ( s.length )
this.feedback(event,
'<p class="spoil_diff"></p>'
+ '<table class="information_table" style="display:inline">'
+ '<tr><th><p class="spoil_miss"><th><p class="spoil_unexpected"></tr>'
+ s.join('')
+ '</table><p>');
else
this.feedback(event, '<p class="spoil_diff_ok"></p>');
} ;
Spoil.prototype.length = function(event) {
var answer = this.answer() ;
if ( answer === undefined )
return ;
if ( answer.length < this.spoil_min )
this.feedback(event,
'<p class="spoil_less"> ' + (this.spoil_min - answer.length)
+ ' <span class="spoil_char"></span>') ;
else if ( answer.length > this.spoil_max )
this.feedback(event,
'<p class="spoil_more"> ' + (answer.length - this.spoil_max)
+ ' <span class="spoil_char"></span>') ;
else
this.feedback(event, '<p class="spoil_ok"></p>');
} ;
function set_spoiler(goods)
{
if ( goods.length == 0 )
return ;
spoil = new Spoil(goods) ;
}
|
---|
| Display the informations about the required questions. css_attributesCSS selector | English | French |
---|
#display_tab | height: 9em;
overflow: auto;
background: #FFF ;
padding-top: 0.4em ;
| .box_content | padding: 0.5em | DIV.before | position: absolute;top: 0px; left: 50% ; | DIV.content | position: relative; | DIV.name | border: 1px solid #BBB ;
display: inline ;
border-top-right-radius: 0.4em ;
border-top-left-radius: 0.4em ;
border-bottom: 0px ;
margin-right: 0.2em ;
| DIV.question | position: absolute; top: 0px; left: 0px ; right: 50% ; | DIV.tab | display: inline ; | DIV.tabs | height: 1.1em; | DIV.tabs DIV.answer | display: none | DIV.tabs DIV.content | display: none | title | Questions you have already answered | Questions auxquelles vous avez déjà répondues |
---|
translationsCSS selector | English | French |
---|
answer | Your answer: | Votre réponse : | tip | You will find here informations that may help you to answer the question. If you are stuck, think to read the informations displayed here. | Souvent vous trouverez ici des informations pouvant vous aider à répondre à la question que l'on vous pose. Si vous êtes bloqué, pensez à relire les informations qui sont affichées ici. |
---|
javascript |
function goto_tab(t)
{
while ( t && t.className != "tab" )
t = t.parentNode ;
if ( ! t )
return ;
var selected = t ;
while ( t.className != "tabs" )
t = t.parentNode ;
for(var i = 0 ; i < t.childNodes.length; i++)
{
var e = t.childNodes[i] ;
e.childNodes[0].style.background = ( e === selected ? "#FFF" : "#CCC") ;
}
document.getElementById("display_tab").innerHTML = selected.childNodes[1].outerHTML ;
document.getElementById("display_answer").innerHTML = selected.childNodes[2].outerHTML ;
}
|
---|
| Displays all the comments about the current question. title | Comments about this question | Les commentaires qui ont été déposés à propos de cette question |
---|
translationsCSS selector | English | French |
---|
c0 | Comment | Commentaire | c0>SPAN | The student comment | Le texte du commentaire déposé par l'étudiant | c1 | Student | Étudiant | c1>SPAN | Student login, you can click to send a mail. The mail will be initialized with the question and its comment | Le login de l'étudiant, vous pouvez cliquer pour lui envoyer un mail avec le rappel de la question et le contenu de son commentaire | c2 | Date | c2>SPAN | The comment date | La date de dépôt du commentaire | | Allow to grade and comment the good answers. css_attributesCSS selector | English | French |
---|
/.question_correction_comment | text-decoration: underline; | /.question_correction_table IMG | width: 8px; height: 8px; background: #F00; border: 0px | /.question_correction_table SPAN | white-space: pre ; | translationsCSS selector | English | French |
---|
c0 | Student answer | Réponse de l'étudiant | c0>SPAN | Student answer | Réponse de l'étudiant | c1 | Grade | Note | c1>SPAN | Click on the grade you want to give | Cliquer pour indiquer la note à lui donner | c2 | Comment | Commentaire | c2>SPAN | Enter a comment about the student answer.\A They can be sent to the student. | Saisissez un commentaire sur sa réponse.\A Ces commentaire peuvent être envoyés aux étudiants.. | question_correction_comment | A teacher comment by: | Un commentaire laissé par : | javascript |
function question_correction(event)
{
var input = event ? event.target : window.event ;
var url = "?question_correction=" + input.name + "," + encode_uri(input.value) ;
var img = document.createElement('IMG') ;
img.src = url ;
var td = input.parentNode ;
if ( td.tagName != 'TD' )
td = td.parentNode ;
td.style.background = 'yellow' ;
input.parentNode.appendChild(img) ;
}
|
---|
| Displays all the bad answers given for a question. css_attributesCSS selector | English | French |
---|
DIV.uncommented | background: #FAA; display: inline-block | DIV.uncommented PRE | background-color: #FAA ; | title | Bad answers given to this question | Les mauvaises réponses données à cette question |
---|
translationsCSS selector | English | French |
---|
c0 | Question | c0>SPAN | Question text really asked with the randomization | Texte de la question posée. | c1 | Bad answer given | Mauvaise réponse donnée par l'étudiant | c1>SPAN | If the bad answer background is red\A this mean that it has not been comment.\A\A If there is '!!!' this means that the answer was not counted as good\A but after a questionnary modification it is now a valid answer | Si la mauvaise réponse est sur fond rouge\A cela veux dire que l'étudiant n'a pas eu de commentaire.\A\AS'il y a des '!!!' c'est que sa réponse a été comptabilisée comme bonne\A mais que suite à une modification du système elle est maintenant considérée comme valide | c2 | The students | Les étudiants | c2>SPAN | The students that have given this bad answer\A In bold if they have not found the good answer\A Italic if they have asked a tip | Les étudiants ayant donné cette mauvaise réponse\A En gras s'ils n'ont pas trouvé la bonne réponse\A En italique s'ils ont demandé un indice | | Displays some statistics about the current question. css_attributesCSS selector | English | French |
---|
> TABLE > TR | vertical-align: top ; | P | margin: 0.1em ; | title | Question statistics | Statistiques sur cette question |
---|
translationsCSS selector | English | French |
---|
bad | Bad answers | Mauvaises réponse | comment | Comments | Commentaires | given | Saw by | Vues par | good | Good answers | Bonnes réponse | indice | Tip asked | Indices demandés | time | Mean time | Temps moyen | view | Display | Affichages | tip | Bracketed number indicates the mean value for student that saw the question | Entre parenthèses ce sont les moyennes pour tous les étudiants ayant vu la question |
---|
| Display the students grades for a question sorted by answer title | Grades for this question | Notes pour cette question |
---|
tip | For each teacher or competence, indicates the number of points gained or lost | Pour chaque enseignant ou compétence, indique le nombre de points en négatif ou positif. |
---|
| Displays all the bad answers given for a question. | Displays the question Python source. css_attributesCSS selector | English | French |
---|
/BUTTON.save_source:before | content:'Save this source code in the question file' | content:'Sauvegarder ce code dans le fichier source des questions' | /PRE.python_error | background: #F88; font-size:150% | javascript |
function encode_uri(t)
{
return encodeURI(t).replace(/\?/g, "%3F").replace(/#/g, "%23")
.replace(/[.]/g, "%2E").replace(/;/g, "%3B").replace(/&/g, "%26")
.replace(/\//g, "%2F").replace(/,/g, "%2C").replace(/[+]/g, '%2B') ;
}
|
---|
|
|
|