+ Achievable Points
Achieved Points
Allow Cut and Paste
Is the student allowed to use cut and paste in multiline text fields?
@@ -53,6 +54,8 @@
Automated exam review not possible
Automated exam review possible
Summary
+ Exam Statistics per Participant
+ Exam Statistics per Question
Exam Time Window
Optional time window for automatically open/close exam. When these values are set, manual opening and closing of the exam is still possible.
Exercise
@@ -61,7 +64,10 @@
Open Text Exercise
Single Choice Exercise
Export Results
- Export results and comments per question
+ Export Results and Comments per Question
+ Export Points
+ Export Grades
+ Export Points and Grades
Feedback
Feedback Correct
Feedback Incorrect
@@ -185,10 +191,12 @@
%achievedPoints% (rounded %achievedPointsRounded%) of possible %totalPoints% points, %percentage%%, grade: %grade%
Participant
Participants
+ Percentage
participants answered this question
Please answer
Point
Points
+ Points and Grades
Pool Question
Pool Folder
Item Types
Index: openacs-4/packages/xowf/lib/inclass-exam.wf
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/lib/inclass-exam.wf,v
diff -u -r1.1.2.103 -r1.1.2.104
--- openacs-4/packages/xowf/lib/inclass-exam.wf 21 Nov 2022 19:46:19 -0000 1.1.2.103
+++ openacs-4/packages/xowf/lib/inclass-exam.wf 15 Dec 2022 19:28:20 -0000 1.1.2.104
@@ -43,17 +43,17 @@
# The policy has to allow the following methods on FormPages:
#
# - "answer" (for students),
-# - "proctor" (for students),
-# - "view-my-exam" (for students),
+# - "delete" (for lecturers),
# - "edit" (for students),
+# - "exam-results" (for lecturers),
# - "poll" (for lecturers),
# - "print-answers" (for lecturers),
-# - "print-answer-table" (for lecturers),
# - "print-participants" (for lecturers),
+# - "proctor" (for students),
+# - "qrcode" (for lecturers)
# - "question-summary" (for lecturers),
-# - "delete" (for lecturers),
# - "toggle-publish-status" (for lecturers),
-# - "qrcode" (for lecturers)
+# - "view-my-exam" (for students),
#
# Gustaf Neumann, Feb 2012-2021
########################################################################
@@ -264,8 +264,10 @@
#
}
- set answers [$obj AM get_answer_attributes $wf]
-
+ set answers [:AM get_answer_attributes $wf]
+ set results [:AM get_exam_results -obj $obj results]
+ set autograded [dict get $combined_form_info autograde]
+ set grading_scheme_name [$obj property grading]
#
# Per default, the entries are disabled. When there are answers,
# these will be enabled.
@@ -275,15 +277,23 @@
listing {obj $wf m list label #xowf.online-exam-exam_instances# icon list}
participants {obj $obj m print-participants label #xowf.Participants# icon user}
protocol {obj $obj m print-answers label #xowf.online-exam-protocol# icon list-alt}
- results {obj $obj m print-answer-table label #xowf.online-exam-results-table# icon th-list}
+ grades {obj $obj m exam-results label #xowf.Points_and_grades# icon graph-up-arrow}
}]
if {![acs_user::site_wide_admin_p -user_id [::xo::cc user_id]]} {
dict unset md listing
}
- dict unset md results ;# deactivate results for now
- #ns_log notice ALL=$text
+ ns_log notice "ANSWERS grading_scheme_name $grading_scheme_name $answers resultsNr [llength $results], autograde [dict get $combined_form_info autograde]"
+ #
+ # We assume here that when we have results, we have also some points.
+ #
+ if {[llength $results] == 0} {
+ dict unset md grades
+ } elseif {$grading_scheme_name in {"" "none"}} {
+ dict set grades label "Points"
+ }
+ #ns_log notice ALL=$text
set menu "\n"
dict for {name d} $md {
set href [[dict get $d obj] pretty_link -query m=[dict get $d m]]
@@ -455,45 +465,6 @@
}
########################################################################
- # web-callable method "print-answer-table"
- #
- # Print the answers in a tabular form.
- #
- :proc www-print-answer-table {} {
- set HTML ""
- set withAnswerColumns [${:package_id} query_parameter with_answers:boolean 0]
-
- set wf [:AM get_answer_wf [self]]
- if {$wf ne ""} {
- #set form_info [:QM combined_question_form -with_numbers [self]]
-
- set items [:AM get_wf_instances $wf]
- set items2 [$items deep_copy]
- foreach i [$items2 children] {
- $i set online-exam-userName [acs_user::get_element -user_id [$i creation_user] -element username]
- $i set online-exam-fullName [::xo::get_user_name [$i creation_user]]
- }
- set HTML [:AM results_table \
- -package_id ${:package_id} \
- -items $items2 \
- -state * \
- -with_answers $withAnswerColumns \
- [self]]
- $items2 destroy
- }
- if {$HTML eq ""} {
- set HTML "#xowiki.no_data#"
- } else {
- set HTML "#xowf.online-exam-results-table#
$HTML"
- }
- set return_url [[$wf package_id] query_parameter local_return_url:localurl [:pretty_link]]
- append HTML "
#xowiki.back#
\n"
-
- xo::Page requireCSS /resources/xowf/test-item.css
- :www-view $HTML
- }
-
- ########################################################################
# web-callable method "print-participants"
#
# Print participants in a tabular form.
@@ -554,18 +525,144 @@
########################################################################
# web-callable method "exam-results"
#
- # export results as CSV table
+ # Print results (grades, statistics) for a lecturer.
#
:proc www-exam-results {} {
- #set manual_gradings [:property manual_gradings]
- set manual_gradings [:AM get_exam_results -obj [self] manual_gradings]
- #set results [:property __results]
+ set form_info [:QM combined_question_form [self]]
+ set autograde [dict get $form_info autograde]
+ set orderby [:query_parameter orderby:token "participant,desc"]
+ set format [:query_parameter format:alpha ""]
+ set perQuestion [:query_parameter per-question:boolean 0]
+
+ set grading_scheme_name [:property grading]
+ if {$grading_scheme_name eq ""} {
+ set grading_scheme_name none
+ }
+ set gradingScheme [:AM grading_scheme -examWf [self] -grading $grading_scheme_name]
+ set withGrades [expr {$gradingScheme ne "::xowf::test_item::grading::none"}]
+
+ set return_url [:query_parameter local_return_url:localurl [:pretty_link]]
+ set backButtonHTML "
#xowiki.back#
\n"
+
set results [:AM get_exam_results -obj [self] results]
- :AM results_export -reply -manual_gradings $manual_gradings $results
- ad_script_abort
+ if {[llength $results] eq 0} {
+ #
+ # Actually, the link leading to this result should not be
+ # active. The message is just for cases of URL hacking.
+ #
+ return [:www-view "No submission results available.$backButtonHTML"]
+ }
+ set manual_gradings [:AM get_exam_results -obj [self] manual_gradings]
+
+ if {$format eq "csv"} {
+ return [:AM exam_results \
+ -format csv \
+ -reply \
+ -orderby $orderby \
+ -only_grades [:query_parameter onlygrades:boolean true] \
+ -gradingScheme [expr {$perQuestion ? "" : $gradingScheme}] \
+ -manual_gradings $manual_gradings \
+ $results]
+
+ #:AM exam_results -reply -manual_gradings $manual_gradings $results
+
+ }
+
+ set statistics [:AM get_exam_results -obj [self] statistics]
+
+ #
+ # We have to following options:
+ # - perParticipant with grades
+ # - perParticipant without grades
+ # - perQuestion (always without grades, since this includes as well the statistics per alternative)
+ #
+ set HTML ""
+ if {0} {
+ set HTML [subst {
+
+ autograde $autograde
+ manual_gradings $manual_gradings
+ results $results
+ statistics $statistics
+ }]
+ append HTML \n\nper_question\n[:AM exam_results -manual_gradings $manual_gradings $results]
+ append HTML \nper_student\n[:AM exam_results -gradingScheme $gradingScheme \
+ -manual_gradings $manual_gradings $results]
+ append HTML
+ }
+ if {$perQuestion} {
+ append HTML \
+ "#xowf.exam_statistics_question#
\n" \
+ [:AM exam_results -format html \
+ -manual_gradings $manual_gradings \
+ $results]
+ set exportQuestionResultsURL [ad_return_url {{format csv} {onlygrades 0}}]
+ set perParticipantURL [ns_conn url]?[::xo::update_query [ns_conn query] per-question 0]
+ set buttonsHTML [subst {
+
+ #xowf.export_results_title#
+
+ #xowf.exam_statistics_participant#
+ }]
+ } else {
+ append HTML \
+ "#xowf.exam_statistics_participant#
" \
+ "#xowf.Grading-Scheme#: [$gradingScheme cget -title]\n" \
+ [:AM exam_results -format html \
+ -orderby $orderby \
+ -gradingScheme $gradingScheme \
+ -manual_gradings $manual_gradings \
+ $results]
+ set exportPointGradesURL [ad_return_url {{format csv} {onlygrades 0}}]
+
+ if {$withGrades} {
+ #
+ # Only grades as table
+ #
+ #append HTML [:AM exam_results -format html \
+ # -orderby $orderby \
+ # -only_grades true \
+ # -gradingScheme $gradingScheme \
+ # -manual_gradings $manual_gradings \
+ # $results]
+ append HTML [:AM exam_results -format chart \
+ -orderby $orderby \
+ -only_grades true \
+ -gradingScheme $gradingScheme \
+ -manual_gradings $manual_gradings \
+ $results]
+ set exportGradesURL [ad_return_url {{format csv}}]
+ set buttonsHTML [subst {
+
+ #xowf.export_grades_title#
+
+ #xowf.export_points_and_grades_title#
+ }]
+ } else {
+ set buttonsHTML [subst {
+
+ #xowf.export_points_title#
+ }]
+ }
+ set perQuestionURL [ns_conn url]?[::xo::update_query [ns_conn query] per-question 1]
+ append buttonsHTML [subst {
+
+ #xowf.exam_statistics_question#
+ }]
+ }
+
+ if {$HTML eq ""} {
+ set HTML "#xowiki.no_data#"
+ } else {
+ append HTML $buttonsHTML
+ }
+ append HTML $backButtonHTML
+
+ :www-view $HTML
}
+
########################################################################
# web-callable method "print-answers"
#
@@ -610,8 +707,6 @@
}
}
-
-
########################################################################
# web-callable method "answer"
#
@@ -776,7 +871,8 @@
:proc www-blank-inputs {} {
#
# Analyze the student submissions an find situations, where input
- # is "cleared" between revisions.
+ # is "cleared" between revisions. This method is primarily for
+ # debugging purposes.
#
template::head::add_link -rel stylesheet -href /resources/xowf/test-item.css
set HTML [:AM render_answers_with_edit_history [self]]
@@ -881,25 +977,25 @@
set last_instance_attributes ${:instance_attributes}
set field_names_with_child_components [lmap f [::xowiki::formfield::child_components $form_fields] {$f name}]
#ns_log notice "\nORIG $field_names \NEW $field_names_with_child_components"
-
+
lassign [:get_form_data -field_names $field_names_with_child_components $form_fields] validation_errors category_ids
if {$validation_errors == 0} {
if {$last_instance_attributes eq ${:instance_attributes}} {
ns_log notice "UPDATE CONFIG ... nothing has changed"
} else {
ns_log notice "UPDATE CONFIG ... no validation_errors -> SAVE"
-
+
:update_attribute_from_slot [:find_slot instance_attributes] ${:instance_attributes}
-
+
if {[dict exists $last_instance_attributes time_window]} {
set old_time_window [dict get $last_instance_attributes time_window]
- set new_time_window [dict get ${:instance_attributes} time_window]
+ set new_time_window [dict get ${:instance_attributes} time_window]
if {$old_time_window ne $new_time_window} {
ns_log notice "UPDATE CONFIG time_window $new_time_window"
:AM time_window_setup [self] -time_window $new_time_window
ns_log notice "UPDATE CONFIG time_window $new_time_window DONE"
}
- }
+ }
}
ns_return 200 text/plain OK
} else {
Index: openacs-4/packages/xowf/tcl/grading-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/tcl/grading-procs.tcl,v
diff -u -r1.1.2.3 -r1.1.2.4
--- openacs-4/packages/xowf/tcl/grading-procs.tcl 12 Sep 2022 14:18:12 -0000 1.1.2.3
+++ openacs-4/packages/xowf/tcl/grading-procs.tcl 15 Dec 2022 19:28:21 -0000 1.1.2.4
@@ -86,7 +86,7 @@
return $grade
}
- :method complete_dict {achieved_points} {
+ :public method grading_dict {achieved_points} {
# Important dict members of "achieved_points":
# - achievedPoints: points that the student has achieved in her exam
@@ -115,9 +115,9 @@
} {
set achievablePoints 0
set achievedPoints 0
- #ns_log notice "RECALC in complete_dict "
+ #ns_log notice "RECALC in grading_dict "
foreach detail [dict get $achieved_points details] {
- #ns_log notice "RECALC in complete_dict '$detail'"
+ #ns_log notice "RECALC in grading_dict '$detail'"
set achievedPoints [expr {$achievedPoints + [dict get $detail achieved]}]
set achievablePoints [expr {$achievablePoints + [dict get $detail achievable]}]
}
@@ -157,7 +157,7 @@
# Return a dict containing the members "panel" and "csv"
# depending on the type of rounding options
#
- set achieved_points [:complete_dict $achieved_points]
+ set achieved_points [:grading_dict $achieved_points]
set grade [:grade -achieved_points $achieved_points]
dict with achieved_points {
return [list panel [_ xowf.panel_[namespace tail [:info class]]] csv [subst ${:csv}]]
@@ -179,7 +179,7 @@
# Return a numeric grade for an exam submission based on rounded
# points. On invalid data, return 0.
#
- set achieved_points [:complete_dict $achieved_points]
+ set achieved_points [:grading_dict $achieved_points]
dict with achieved_points {
return [:calc_grade -points $achievedPointsRounded -achievable_points $totalPoints]
}
@@ -200,7 +200,7 @@
# Return a numeric grade for an exam submission based on rounded
# percentage. On invalid data, return 0.
#
- set achieved_points [:complete_dict $achieved_points]
+ set achieved_points [:grading_dict $achieved_points]
if {[dict exists $achieved_points achievedPoints]} {
dict with achieved_points {
return [:calc_grade -percentage $percentageRounded]
@@ -224,7 +224,7 @@
# special rounding (2 digits). On invalid data, return 0.
#
if {[dict exists $achieved_points achievedPoints]} {
- set achieved_points [:complete_dict $achieved_points]
+ set achieved_points [:grading_dict $achieved_points]
dict with achieved_points {
return [:calc_grade -percentage $percentage]
}
Index: openacs-4/packages/xowf/tcl/test-item-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/tcl/test-item-procs.tcl,v
diff -u -r1.7.2.260 -r1.7.2.261
--- openacs-4/packages/xowf/tcl/test-item-procs.tcl 6 Dec 2022 12:43:39 -0000 1.7.2.260
+++ openacs-4/packages/xowf/tcl/test-item-procs.tcl 15 Dec 2022 19:28:21 -0000 1.7.2.261
@@ -1730,8 +1730,9 @@
#
# - marked_results
# - answers_panel
- # - results_table
+ # - exam_results
# - grading_table
+ # - grading_scheme
# - grade
# - participants_table
#
@@ -3862,10 +3863,10 @@
# Class: Answer_manager
# Method: grading_scheme
#----------------------------------------------------------------------
- :method grading_scheme {
+ :public method grading_scheme {
{-examWf:object,required}
{-grading:token,0..n ""}
- {-total_points}
+ {-total_points 100}
} {
#
# Return the grading scheme object based on the provided short
@@ -3882,6 +3883,10 @@
#
# @return fully qualified grading scheme object
#
+
+ #
+ # When not grading is provided, this muse be a legacy question.
+ #
if {$grading eq ""} {
#set grading [expr {$total_points < 40 ? "round-none" : "round-points"}]
set grading "none"
@@ -3893,6 +3898,8 @@
#
# Maybe we have to load this grading scheme...
#
+ #ns_log notice "grading_scheme_name load loaded yet: '$grading'"
+ #::xo::show_stack
::xowf::test_item::grading::load_grading_schemes \
-package_id [$examWf package_id] \
-parent_id [$examWf parent_id]
@@ -4125,7 +4132,7 @@
#set manual_gradings [$examWf property manual_gradings]
#set manual_gradings [:get_exam_results -obj $examWf manual_gradings]
#append HTML $manual_gradings
- #append HTML [:results_export -manual_gradings $manual_gradings $results]
+ #append HTML [:exam_results -manual_gradings $manual_gradings $results]
}
if {$create_zip_file} {
@@ -4283,18 +4290,162 @@
}
}
+ :method "result_table per_question" {
+ {-manual_gradings "" }
+ results_dict
+ } {
+ set table [::xowiki::TableWidget new \
+ -name results \
+ -columns {
+ Field create participant -label #xowf.participant# \
+ -orderby participant
+ Field create question -label #xowf.question#
+ Field create achieved -label #xowf.Achieved_points# \
+ -orderby achieved -html {align right}
+ Field create achievable -label #xowf.Achievable_points# \
+ -orderby achievable -html {align right}
+ Field create comment -label #xowf.feedback#
+ }]
+ foreach user_id [dict keys $results_dict] {
+ set manual_grading [:dict_value $manual_gradings $user_id]
+ set participant [acs_user::get_element -user_id $user_id -element username]
+ foreach qn [dict keys [dict get $results_dict $user_id]] {
+ set achievable [dict get $results_dict $user_id $qn achievable]
+ set achieved [dict get $results_dict $user_id $qn achieved]
+ $table add \
+ -participant $participant \
+ -question [string trimright $qn _] \
+ -achievable $achievable \
+ -achieved [format %.2f $achieved] \
+ -comment [:dict_value [:dict_value $manual_grading $qn] comment]
+ }
+ }
+ return $table
+ }
+
+ :method "result_table per_participant" {
+ {-manual_gradings ""}
+ {-gradingScheme}
+ {-only_grades:boolean false}
+ results_dict
+ } {
+ ns_log notice "per_participant gradingScheme $gradingScheme"
+ #
+ # In case "only_grades" is specified, hide field "achieved".
+ #
+ set fieldType [expr {$only_grades ? "HiddenField" : "Field"}]
+ set fieldTypeGrade [expr {$gradingScheme eq "::xowf::test_item::grading::none"
+ ? "HiddenField"
+ : "Field"}]
+ set grade_dict {}
+ set table \
+ [::xowiki::TableWidget new \
+ -name results \
+ -columns [subst {
+ Field create participant -label #xowf.participant# \
+ -orderby participant
+ $fieldType create achieved -label #xowf.Achieved_points# \
+ -orderby achieved -html {align right}
+ HiddenField create achievable -label #xowf.Achievable_points# \
+ -orderby achievable -html {align right}
+ $fieldType create percentage -label #xowf.Percentage# \
+ -orderby percentage -html {align right}
+ $fieldTypeGrade create grade -label #xowf.Grade# \
+ -orderby grade -html {align right}
+ }]]
+ #ns_log notice "We have in results_dict the following users: [dict keys $results_dict]"
+ foreach {user_id properties} $results_dict {
+ if {[llength $properties] == 0} {
+ #
+ # The user has not seen any exercises, probably in "initial"
+ # state, ignore it.
+ #
+ continue
+ }
+ set manual_grading [:dict_value $manual_gradings $user_id]
+ set achievedPoints 0.0
+ set achievablePoints 0.0
+ set participant [acs_user::get_element -user_id $user_id -element username]
+ foreach qn [dict keys [dict get $results_dict $user_id]] {
+ set achievable [dict get $results_dict $user_id $qn achievable]
+ #
+ # Respect manual_grading, since these are eagerly updated
+ # via exam protocol.
+ #
+ set achieved [:dict_value [:dict_value $manual_grading $qn] achieved]
+ if {$achieved eq ""} {
+ set achieved [dict get $results_dict $user_id $qn achieved]
+ }
+
+ #
+ # When a participant has not done yet this exercise, the
+ # value might be empty.
+ #
+ if {$achieved eq ""} {
+ set achieved 0
+ }
+ set achievedPoints [expr {$achievedPoints + $achieved}]
+ set achievablePoints [expr {$achievablePoints + $achievable}]
+ }
+ set gradingDict [$gradingScheme grading_dict [list achievedPoints $achievedPoints \
+ achievablePoints $achievablePoints \
+ totalPoints $achievablePoints]]
+ #ns_log notice "COMPLETED DICT $gradingDict"
+ set grade [$gradingScheme grade -achieved_points $gradingDict]
+ dict incr grade_dict $grade
+
+ set l [::xo::Table::Line new]
+ $table add \
+ -participant $participant \
+ -achievable $achievablePoints \
+ -achieved [dict get $gradingDict achievedPoints] \
+ -percentage [dict get $gradingDict percentageRounded] \
+ -grade $grade
+
+ }
+ $table set __grade_dict $grade_dict
+ return $table
+ }
+
#----------------------------------------------------------------------
# Class: Answer_manager
- # Method: results_export
+ # Method: exam_results
#----------------------------------------------------------------------
- :public method results_export {
+ :public method exam_results {
{-manual_gradings "" }
+ {-gradingScheme ""}
+ {-only_grades:boolean false}
{-reply:switch false}
+ {-format csv}
+ {-orderby "participant,desc"}
results_dict
} {
#
- # Exports results as csv
+ # Return results either as HTML table, as HTML chart or as
+ # csv. When "reply" is set. the result is returned directly to
+ # the browser (for downloading).
#
+ # When "gradingScheme" is empty, this method returns the
+ # following fields:
+ #
+ # participant, question, achieved_points, achievable points, comment
+ #
+ # When the "gradingScheme" is specified the results are
+ # per-participant. In this cases, when the "gradingScheme" is
+ # "....::none", the fields are
+ #
+ # participant, achieved, percentage
+ #
+ # otherwise the grade and rounding of achieved points and
+ # percentage are exported based on the rules of the grading
+ # scheme.
+ #
+ # participant, achieved, percentage, grade
+ #
+ # When additionally "only_grades" is specified, just participant
+ # and grad are returned/exported.
+ #
+ # @param gradingScheme needed for reporting grades, can be empty
# @param reply when false, csv will be returned as text, when
# true, it will be returned as response to the
# browser.
@@ -4303,34 +4454,43 @@
#
# @return csv as value or as response to the client
#
- set t [::xo::Table new -volatile \
- -name results \
- -columns {
- Field create participant -label participant
- Field create query_name -label query_name
- Field create achieved -label achieved
- Field create achievable -label achievable
- Field create comment -label comment
- }]
- foreach user_id [dict keys $results_dict] {
- set manual_grading [:dict_value $manual_gradings $user_id]
- foreach qn [dict keys [dict get $results_dict $user_id]] {
- set l [::xo::Table::Line new]
- $t add \
- -participant [acs_user::get_element \
- -user_id $user_id \
- -element username] \
- -query_name [string trimright $qn _] \
- -achievable [dict get $results_dict $user_id $qn achievable] \
- -achieved [dict get $results_dict $user_id $qn achieved] \
- -comment [:dict_value [:dict_value $manual_grading $qn] comment]
- }
+ set result ""
+ if {$gradingScheme eq ""} {
+ set t [:result_table per_question \
+ -manual_gradings $manual_gradings \
+ $results_dict]
+ } else {
+ set t [:result_table per_participant \
+ -gradingScheme $gradingScheme \
+ -only_grades $only_grades \
+ -manual_gradings $manual_gradings \
+ $results_dict]
}
+
+ lassign [split $orderby ,] att order
+
+ $t orderby \
+ -order [expr {$order eq "asc" ? "increasing" : "decreasing"}] \
+ -type [ad_decode $att achieved real achievable real grade integer dictionary] \
+ $att
+
if {$reply} {
- $t write_csv
+ switch $format {
+ html {
+ ns_return 200 "text/html; charset=utf-8" [$t asHTML]
+ ad_script_abort
+ }
+ default {set result [$t write_csv]}
+ }
} else {
- $t format_csv
+ switch $format {
+ chart {set result [:grading_table [$t set __grade_dict]]}
+ html {set result [$t asHTML]}
+ default {set result [$t format_csv]}
+ }
}
+ $t destroy
+ return $result
}
#----------------------------------------------------------------------
@@ -4348,7 +4508,8 @@
"\n"
set nrGrades 0
foreach v [dict values $grade_dict] { incr nrGrades $v}
- foreach k [lsort [dict keys $grade_dict]] {
+ set grades [lsort [dict keys $grade_dict]]
+ foreach k $grades {
set count [dict get $grade_dict $k]
set countPercentage [format %.2f [expr {$count *100.0 / $nrGrades}]]
append gradingTable \
@@ -4358,7 +4519,35 @@
style="width:$countPercentage%">$countPercentage%\n
}
- append gradingTable "\n$csv
\n"
+ append gradingTable "\n"
+ if {$csv ne "" } {
+ append gradingTable "$csv
\n"
+ }
+
+ if {[template::head::can_resolve_urn urn:ad:js:highcharts]} {
+ #
+ # The highcharts package is available
+ #
+ template::add_body_script -src urn:ad:js:highcharts
+ set graphID pie-[incr ::__xotcl_highcharts_pie]
+ append gradingTable "\n"
+ set data ""
+ foreach k $grades {
+ set count [dict get $grade_dict $k]
+ set countPercentage [format %.2f [expr {$count *100.0 / $nrGrades}]]
+ lappend data [subst {{name:'$k', y: $countPercentage}}]
+ }
+ set gradeLabel [_ xowf.Grade]
+ template::add_body_script -script [subst [ns_trim {
+ Highcharts.chart('$graphID', {
+ chart: {type: 'pie'},
+ plotOptions: {pie: {size: 200}, series: {dataLabels: {enabled: true, format: '$gradeLabel {point.name}: {point.y:.1f}%'} }},
+ title: {text: ''},
+ credits: {enabled: true },
+ series: \[{name: 'Percentage', data: \[ [join $data ,] \]}\]
+ });
+ }]]
+ }
return $gradingTable
}
@@ -4377,7 +4566,8 @@
} {
#
# Render the results in format of a table and return HTML.
- # Currently deactivated.
+ # Currently mostly deactivated (but potentially called by
+ # online-exam.wf and topic-assignment.wf).
#
#set form_info [:combined_question_form -with_numbers $wf]
@@ -6873,7 +7063,8 @@
#
set results [:AM get_exam_results -obj $obj results]
if {$results ne ""} {
- set href [$obj pretty_link -query m=exam-results]
+ #https://localhost:8443/xowf/online-exam/inclass-exam1?per-question=1&m=print-statistics&format=csv&onlygrades=0
+ set href [$obj pretty_link -query m=exam-results&format=csv&per-question=1]
set results_summary [subst {
#xowf.export_results#:
@@ -7592,7 +7783,7 @@
# activities.
#
#
- # Policy for creating and publishing of exams.
+ # Policy for lecturers (creating and publishing of exams)
#
test-item-policy-publish contains {
Class create FormPage -array set require_permission {