Gustaf Neumann
XoWiki Content Flow - an XoWiki based workflow system implementing state-based behavior of wiki pages and forms
2021-09-15
WU Vienna
BSD-Style
2
-
-
+
+
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.88 -r1.1.2.89
--- openacs-4/packages/xowf/lib/inclass-exam.wf 9 Jan 2022 20:46:52 -0000 1.1.2.88
+++ openacs-4/packages/xowf/lib/inclass-exam.wf 31 Jan 2022 13:15:42 -0000 1.1.2.89
@@ -60,7 +60,7 @@
set :policy ::xowf::test_item::test-item-policy-publish
set :debug 0
set :live_updates 1
-set :QM ::xowf::test_item::question_manager
+
:forward QM ::xowf::test_item::question_manager
set :fc_repository {
@@ -540,8 +540,10 @@
# export results as CSV table
#
:proc www-exam-results {} {
- set manual_gradings [:property manual_gradings]
- set results [:property __results]
+ #set manual_gradings [:property manual_gradings]
+ set manual_gradings [xowf::test_item::answer_manager get_exam_results -obj [self] manual_gradings]
+ #set results [:property __results]
+ set results [xowf::test_item::answer_manager get_exam_results -obj [self] results]
xowf::test_item::answer_manager results_export -reply -manual_gradings $manual_gradings $results
ad_script_abort
}
@@ -561,7 +563,7 @@
-filter_id [:query_parameter id:int32 ""] \
-creation_user [:query_parameter creation_user:int32 ""] \
-revision_id [:query_parameter rid:int32 ""] \
- -form_objs [:query_parameter fos:int32 ""] \
+ -filter_form_ids [:query_parameter fos:int32 ""] \
-export [:query_parameter export:boolean 0] \
-orderby [:query_parameter orderby:token "online-exam-userName"] \
-grading [:query_parameter grading:token [:property grading]] \
@@ -808,15 +810,17 @@
set formDict [ns_set array [ns_getform]]
#
- # Update property "manual_gradings" of the exam
+ # Update property "manual_gradings" of the exam in the results page
#
- set manual_gradings [:property manual_gradings]
+ #set manual_gradings [:property manual_gradings]
+ set manual_gradings [xowf::test_item::answer_manager get_exam_results -obj [self] manual_gradings]
set user_id [dict get $formDict user_id]
set qn [dict get $formDict question_name]
dict set manual_gradings $user_id $qn achieved [dict get $formDict achieved]
dict set manual_gradings $user_id $qn comment [dict get $formDict comment]
- dict set :instance_attributes manual_gradings $manual_gradings
- :update_attribute_from_slot [:find_slot instance_attributes] ${:instance_attributes}
+ xowf::test_item::answer_manager set_exam_results -obj [self] manual_gradings $manual_gradings
+ #dict set :instance_attributes manual_gradings $manual_gradings
+ #:update_attribute_from_slot [:find_slot instance_attributes] ${:instance_attributes}
#
# Recompute the achieved points percentage for the full exam
Fisheye: Tag 1.1 refers to a dead (removed) revision in file `openacs-4/packages/xowf/resources/prototypes/inclass-exam-statistics.wf.page'.
Fisheye: No comparison available. Pass `N' to diff?
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.208 -r1.7.2.209
--- openacs-4/packages/xowf/tcl/test-item-procs.tcl 28 Jan 2022 07:50:54 -0000 1.7.2.208
+++ openacs-4/packages/xowf/tcl/test-item-procs.tcl 31 Jan 2022 13:15:42 -0000 1.7.2.209
@@ -1322,6 +1322,13 @@
namespace eval ::xowf::test_item {
+ # the fillowing is not yet ready for prime time.
+ if {0 && [acs::icanuse "nx::alias object"]} {
+ set register_command "alias"
+ } else {
+ set register_command "forward"
+ }
+
nx::Class create AssessmentInterface {
#
# Abstract class for common functionality
@@ -1449,7 +1456,6 @@
# - form_name_based_attribute_stem
# - name_to_question_obj_dict
#
- # - get_form_object
# - rename_attributes
#
@@ -1581,20 +1587,20 @@
return $form_obj
}
- :public method -deprecated get_form_object {ctx:object form_name} {
- #
- # Return the form object based on the provided form name. This
- # function performs attribute renaming on the returned form
- # object.
- #
- set form_id [$ctx default_load_form_id $form_name]
- set obj [$ctx object]
- set form_obj [::xowiki::FormPage get_instance_from_db -item_id $form_id]
- return [:rename_attributes $form_obj]
- }
+ # :method -deprecated get_form_object {ctx:object form_name} {
+ # #
+ # # Return the form object based on the provided form name. This
+ # # function performs attribute renaming on the returned form
+ # # object.
+ # #
+ # set form_id [$ctx default_load_form_id $form_name]
+ # set obj [$ctx object]
+ # set form_obj [::xowiki::FormPage get_instance_from_db -item_id $form_id]
+ # return [:rename_attributes $form_obj]
+ # }
}
- AssessmentInterface forward FL \
+ AssessmentInterface {*}$register_command FL \
[Renaming_form_loader create renaming_form_loader]
}
@@ -1968,7 +1974,8 @@
#
# Delete as well the manual gradings for this exam.
#
- $obj set_property -new 1 manual_gradings {}
+ #$obj set_property -new 1 manual_gradings {}
+ :AM set_exam_results -obj $obj manual_gradings {}
return $wf
}
@@ -2106,7 +2113,8 @@
dict set r examPublished [clock format $examPublishedClock -format "%H:%M:%S"]
set epTimeDiff [expr {$toClock - $examPublishedClock}]
dict set r examPublishedDuration "[expr {$epTimeDiff/60}]m [expr {$epTimeDiff%60}]s"
- ns_log notice "EP examPublishedDuration [dict get $r examPublishedDuration] EP [dict get $r examPublished] $exam_published_time"
+ #ns_log notice "EP examPublishedDuration [dict get $r examPublishedDuration]" \
+ "EP [dict get $r examPublished] $exam_published_time"
dict set r examPublishedSeconds $epTimeDiff
}
return $r
@@ -2326,6 +2334,7 @@
set totalPoints 0
set achievableTotalPoints 0
set details {}
+
foreach a [dict keys $answer_attributes] {
set f [$submission lookup_form_field -name $a $all_form_fields]
set points {}
@@ -2341,6 +2350,7 @@
} else {
set auto_correct_achieved ""
}
+ #ns_log notice "=== achieved_points <$a> auto_correct_achieved $auto_correct_achieved"
#
# Manual grading has higher priority than autograding.
@@ -2363,6 +2373,7 @@
auto_correct_achieved $auto_correct_achieved \
achievable $achievablePoints]
}
+
#ns_log notice "final details <$details>"
return [list achievedPoints $totalPoints \
details $details \
@@ -3010,13 +3021,13 @@
:method render_full_submission_form {
-wf:object
-submission:object
- -form_objs
+ -filter_form_ids:integer,0..n
} {
#
# Compute the HTML of the full submission with all form fields
# instantiated according to randomization.
#
- # @param form_objs used for filtering questions
+ # @param filter_form_ids used for filtering questions
# @return HTML of question form object containing all (wanted) questions
#
@@ -3042,7 +3053,7 @@
#
xo::cc eval_as_user -user_id [$submission creation_user] {
$submission set __feedback_mode 2
- $submission set __form_objs $form_objs
+ $submission set __form_objs $filter_form_ids
set question_form [$submission render_content]
}
@@ -3303,7 +3314,7 @@
{-examWf:object}
{-exam_question_dict}
{-filter_id:integer,0..1 ""}
- {-form_objs:integer,0..n ""}
+ {-filter_form_ids:integer,0..n ""}
{-grading_scheme:object}
{-recutil:object,0..1 ""}
{-zipFile:object,0..1 ""}
@@ -3318,7 +3329,7 @@
set userName [$submission set online-exam-userName]
set fullName [$submission set online-exam-fullName]
set user_id [$submission set creation_user]
- set manual_gradings [$examWf property manual_gradings]
+ set manual_gradings [:get_exam_results -obj $examWf manual_gradings]
set results ""
#if {[$submission state] ne "done"} {
@@ -3348,25 +3359,33 @@
# a subset, especially in cases, where filtering (e.g., show
# only one question of all candidates) happens.
#
+ set exam_question_objs [dict values $exam_question_dict]
+
set answeredAnswerAttributes \
[:FL answer_attributes [$submission instance_attributes]]
set formAnswerAttributeNames \
- [dict keys [:FL name_to_question_obj_dict $form_objs]]
+ [dict keys [:FL name_to_question_obj_dict $exam_question_objs]]
set usedAnswerAttributes {}
foreach {k v} $answeredAnswerAttributes {
if {$k in $formAnswerAttributeNames} {
dict set usedAnswerAttributes $k $v
}
}
+ #ns_log notice "filter_form_ids <$filter_form_ids>"
+ #ns_log notice "question_objs <[dict get $combined_form_info question_objs]>"
+ #ns_log notice "answeredAnswerAttributes <$answeredAnswerAttributes>"
+ #ns_log notice "formAnswerAttributeNames <$formAnswerAttributeNames> [:FL name_to_question_obj_dict $filter_form_ids]"
+ #ns_log notice "usedAnswerAttributes <$usedAnswerAttributes>"
+
#
# "render_full_submission_form" calls "summary_form" to obtain the
# user's answers to all questions.
#
set question_form [:render_full_submission_form \
-wf $wf \
-submission $submission \
- -form_objs $form_objs]
+ -filter_form_ids $filter_form_ids]
if {$recutil ne ""} {
:export_answer \
@@ -3391,8 +3410,8 @@
-answer_attributes $usedAnswerAttributes]
dict set achieved_points totalPoints $totalPoints
- #ns_log notice "achieved_points [dict get $achieved_points details]"
- #ns_log notice "manual_gradings [:dict_value $manual_gradings $user_id]"
+ #ns_log notice "user $user_id: achieved_points [dict get $achieved_points details]"
+ #ns_log notice "user $user_id: manual_gradings [:dict_value $manual_gradings $user_id]"
foreach pd [:dict_value $achieved_points details] {
set qn [dict get $pd attributeName]
@@ -3542,7 +3561,7 @@
{-filter_id:integer,0..1 ""}
{-creation_user:integer,0..1 ""}
{-revision_id:integer,0..1 ""}
- {-form_objs:integer,0..n ""}
+ {-filter_form_ids:integer,0..n ""}
{-export:boolean false}
{-orderby:token "online-exam-userName"}
{-grading:token,0..n ""}
@@ -3570,10 +3589,10 @@
return [list do_stream 0 HTML ""]
}
- if {$form_objs ne "" && $form_objs ni [dict get $combined_form_info question_objs]} {
- ns_log warning "inclass-exam: ignore invalid form_obj '$form_objs';" \
+ if {$filter_form_ids ne "" && $filter_form_ids ni [dict get $combined_form_info question_objs]} {
+ ns_log warning "inclass-exam: ignore invalid form_obj '$filter_form_ids';" \
"valid [dict get $combined_form_info question_objs]"
- set form_objs ""
+ set filter_form_ids ""
}
ns_log notice "--- grading '$grading'"
set grading_scheme [:grading_scheme -examWf $examWf -grading $grading -total_points $totalPoints]
@@ -3597,12 +3616,12 @@
::xo::cc set_parameter template_file view-plain-master
::xo::cc set_parameter MenuBar 0
- if {[llength $form_objs] > 0} {
+ if {[llength $filter_form_ids] > 0} {
#
# Filter by questions. For the time being, we allow only a
# single question, ... and we take the first ones.
#
- append HTML "#xowf.question#: [ns_quotehtml [[lindex $form_objs 0] title]]
\n"
+ append HTML "#xowf.question#: [ns_quotehtml [[lindex $filter_form_ids 0] title]]
\n"
set runtime_panel_view ""
} elseif {$as_student} {
@@ -3686,6 +3705,7 @@
set form_objs_exam [:QM load_question_objs $examWf [$examWf property question]]
set question_dict [:FL name_to_question_obj_dict $form_objs_exam]
+ #ns_log notice "passed filter_form_ids <$filter_form_ids> form_objs_exam <$form_objs_exam>"
#
# Iterate over the items sorted by orderby.
@@ -3701,7 +3721,7 @@
-autograde $autograde \
-combined_form_info $combined_form_info \
-filter_id $filter_id \
- -form_objs $form_objs \
+ -filter_form_ids $filter_form_ids \
-grading_scheme $grading_scheme \
-recutil $recutil \
-zipFile $zipFile \
@@ -3742,6 +3762,7 @@
# The following lines are conveniant for debugging
#
#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]
}
@@ -3760,8 +3781,8 @@
#
# Avoid empty entries for query parameters
#
- if {[llength $form_objs] > 0} {
- set fos $form_objs
+ if {[llength $filter_form_ids] > 0} {
+ set fos $filter_form_ids
}
foreach value {revision_id filter_id} var {rid id} {
if {[set $value] ne ""} {
@@ -3798,10 +3819,9 @@
$examWf unset $var
}
}
- dict set ia __statistics $statistics
+ :AM set_exam_results -obj $examWf statistics $statistics
}
- dict set ia __results $results
- $examWf update_attribute_from_slot [$examWf find_slot instance_attributes] $ia
+ :AM set_exam_results -obj $examWf results $results
}
return [list do_stream $do_stream HTML $HTML]
@@ -4656,9 +4676,62 @@
}]
}
}
+ #----------------------------------------------------------------------
+ # Class: Answer_manager
+ # Method: get_exam_results
+ #----------------------------------------------------------------------
+ :public method get_exam_results {
+ -obj:object,required
+ property
+ {default ""}
+ } {
+ set p [$obj childpage -name en:result -form inclass-exam-statistics.wf]
+ set instance_attributes [$p instance_attributes]
+ if {[dict exists $instance_attributes $property]} {
+ #ns_log notice "get_exam_results <$property> returns value from " \
+ "results page: [dict get $instance_attributes $property]"
+ return [dict get $instance_attributes $property]
+ }
+ #ns_log notice "get_exam_results <$property> returns default"
+ return $default
+ }
+
+ #----------------------------------------------------------------------
+ # Class: Answer_manager
+ # Method: set_exam_results
+ #----------------------------------------------------------------------
+ :public method set_exam_results {
+ -obj:object,required
+ property
+ value
+ } {
+ #ns_log notice "SES '$property' bytes [string length $value]"
+ set p [$obj childpage -name en:result -form inclass-exam-statistics.wf]
+ set instance_attributes [$p instance_attributes]
+ dict set instance_attributes $property $value
+ $p update_attribute_from_slot [$p find_slot instance_attributes] ${instance_attributes}
+ #
+ # cleanup of legacy values
+ #
+ set instance_attributes [$obj instance_attributes]
+ foreach property_name [list $property __$property] {
+ if {[dict exists $instance_attributes $property_name]} {
+ ns_log notice "SES set_exam_results:" \
+ "clearing values from earlier releases for '$property_name'" \
+ "was <[dict get $instance_attributes $property_name]>"
+ dict unset instance_attributes $property_name
+ $obj set instance_attributes $instance_attributes
+ #ns_log notice "FINAL IA <$instance_attributes> for item_id [$obj item_id]" \
+ "revision_id [$obj revision_id]"
+ $obj update_attribute_from_slot [$obj find_slot instance_attributes] $instance_attributes
+ ::xo::xotcl_object_cache flush [$obj item_id]
+ ::xo::xotcl_object_cache flush [$obj revision_id]
+ }
+ }
+ }
}
- AssessmentInterface forward AM \
+ AssessmentInterface {*}$register_command AM \
[Answer_manager create answer_manager]
}
@@ -6349,7 +6422,7 @@
#
# Provide a summary of all questions of an exam.
#
- set results [$obj property __results]
+ set results [:AM get_exam_results -obj $obj results]
if {$results ne ""} {
set href [$obj pretty_link -query m=exam-results]
set results_summary [subst {
@@ -6460,7 +6533,7 @@
# instance. These statistics are computed when the exam
# protocol is rendered.
#
- set statistics [$obj property __statistics]
+ set statistics [:AM get_exam_results -obj $obj statistics]
if {$statistics ne ""} {
foreach var {success_statistics count_statistics} key {success count} {
if {[dict exists $statistics $key]} {
@@ -6792,7 +6865,7 @@
}
}
set qm [Question_manager create question_manager]
- AssessmentInterface forward QM $qm
+ AssessmentInterface {*}$register_command QM $qm
::xowiki::formfield::TestItemField instforward QM $qm
}
Index: openacs-4/packages/xowf/tcl/xowf-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/tcl/xowf-procs.tcl,v
diff -u -r1.28.2.68 -r1.28.2.69
--- openacs-4/packages/xowf/tcl/xowf-procs.tcl 26 Jan 2022 07:52:43 -0000 1.28.2.68
+++ openacs-4/packages/xowf/tcl/xowf-procs.tcl 31 Jan 2022 13:15:42 -0000 1.28.2.69
@@ -64,11 +64,12 @@
online-exam.wf
inclass-quiz.wf
inclass-exam.wf
+ inclass-exam-statistics.wf
edit-interaction.wf
edit-grading-scheme.wf
answer-single-question.wf
topic-assignment.wf
-
+
quiz-select_question.form
select_question.form
select-topics.form
@@ -777,7 +778,7 @@
Context instproc initialize_context {obj} {
#:log "START-initialize_context <$obj>"
#
- # Keep the object in instance variable
+ # Keep the object in an instance variable.
#
set :object $obj
@@ -790,12 +791,18 @@
:set_current_state $state
if {![nsf::is object ${:current_state}]} {
- # The state was probably deleted from the workflow definition,
- # but the workflow instance does still need it. We complain an
- # reset the state to initial, which should be always present.
- :log "===== Workflow instance [$obj name] is in an undefined state '$state', reset to initial"
- $obj msg "Workflow instance [$obj name] is in an undefined state '$state', reset to initial"
- :set_current_state initial
+ if {$state eq "initial"} {
+ ns_log warning "no state object ${:current_state}"
+ } else {
+ #
+ # The state was probably deleted from the workflow definition,
+ # but the workflow instance does still need it. We complain an
+ # reset the state to "initial", which should be always present.
+ #
+ :log "===== Workflow instance [$obj name] is in an undefined state '$state', reset to initial"
+ $obj msg "Workflow instance [$obj name] is in an undefined state '$state', reset to initial"
+ :set_current_state initial
+ }
}
# Set the embedded_context to the workflow context,
@@ -2390,6 +2397,46 @@
return [$actionObj invoke -attributes $attributes]
}
+
+ WorkflowPage ad_instproc childpage {-name:required -form} {
+
+ Return the child page of the current object with the provided
+ name. In case the child object does not exist, create it as an
+ instance of the provided form.
+
+ @return page object
+ } {
+ if {[info exists form]} {
+ set child_page_id [::${:package_id} lookup \
+ -use_package_path false \
+ -default_lang en \
+ -name $name \
+ -parent_id ${:item_id}]
+ if {$child_page_id == 0} {
+ ns_log notice "child page '$name' does not exist"
+ set form_obj [::${:package_id} instantiate_forms \
+ -default_lang "en" \
+ -forms $form]
+ if {[llength $form_obj] == 0} {
+ error "childpage: cannot instantiate $form"
+ }
+ set p [$form_obj create_form_page_instance \
+ -name $name \
+ -nls_language en_US \
+ -parent_id ${:item_id} \
+ -package_id ${:package_id} \
+ -instance_attributes {}]
+ $p save_new
+ } else {
+ #ns_log notice "child page '$name' exists already (item_id $child_page_id)"
+ set p [::xo::db::CrClass get_instance_from_db -item_id $child_page_id]
+ }
+ return $p
+ } else {
+ error "cannot create '$name': API supports so far only form pages"
+ }
+ }
+
#
# Interface to atjobs
#
Index: openacs-4/packages/xowf/tcl/test/test-item-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/tcl/test/test-item-procs.tcl,v
diff -u -r1.1.2.27 -r1.1.2.28
--- openacs-4/packages/xowf/tcl/test/test-item-procs.tcl 31 Jan 2022 13:05:45 -0000 1.1.2.27
+++ openacs-4/packages/xowf/tcl/test/test-item-procs.tcl 31 Jan 2022 13:15:42 -0000 1.1.2.28
@@ -23,6 +23,7 @@
"::xo::ConnectionContext instproc eval_as_user"
"::xowf::Package instproc destroy"
+ "::xowf::WorkflowPage instproc childpage"
"::xowf::WorkflowPage instproc get_revision_sets"
"::xowf::WorkflowPage instproc is_wf"
"::xowf::WorkflowPage instproc is_wf_instance"
@@ -40,6 +41,7 @@
"::xowf::test_item::Answer_manager instproc get_answer_wf"
"::xowf::test_item::Answer_manager instproc get_answers"
"::xowf::test_item::Answer_manager instproc get_duration"
+ "::xowf::test_item::Answer_manager instproc get_exam_results"
"::xowf::test_item::Answer_manager instproc get_wf_instances"
"::xowf::test_item::Answer_manager instproc grading_dialog_setup"
"::xowf::test_item::Answer_manager instproc grading_table"
@@ -51,6 +53,7 @@
"::xowf::test_item::Answer_manager instproc render_answers"
"::xowf::test_item::Answer_manager instproc revisions_up_to"
"::xowf::test_item::Answer_manager instproc runtime_panel"
+ "::xowf::test_item::Answer_manager instproc set_exam_results"
"::xowf::test_item::Answer_manager instproc state_periods"
"::xowf::test_item::Answer_manager instproc student_submissions_exist"
"::xowf::test_item::Question_manager instproc add_seeds"