Index: openacs-4/packages/xowf/lib/inclass-exam-answer.wf =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/xowf/lib/inclass-exam-answer.wf,v diff -u -r1.1.2.30 -r1.1.2.31 --- openacs-4/packages/xowf/lib/inclass-exam-answer.wf 5 Mar 2021 12:32:37 -0000 1.1.2.30 +++ openacs-4/packages/xowf/lib/inclass-exam-answer.wf 16 Mar 2021 22:09:22 -0000 1.1.2.31 @@ -224,9 +224,12 @@ # background to be able to refer to links relative to the from, when # it was created. # - $form_obj set_property form [$obj substitute_markup \ - -context_obj $form_obj \ - [$form_obj property form]] + set d [::xowf::test_item::question_manager item_substitute_markup \ + -obj $obj \ + -position $position \ + -form_obj $form_obj] + $form_obj set_property form [dict get $d form] + # # Update IP address each time the form is loaded. # @@ -366,6 +369,7 @@ -with_points \ -user_specific \ -shuffle_id $shuffle_id \ + -user_answers $obj \ $parent_obj] #ns_log notice "SUMMARY FORM shuffle_id $shuffle_id $form_info" 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.112 -r1.7.2.113 --- openacs-4/packages/xowf/tcl/test-item-procs.tcl 13 Mar 2021 20:24:33 -0000 1.7.2.112 +++ openacs-4/packages/xowf/tcl/test-item-procs.tcl 16 Mar 2021 22:09:22 -0000 1.7.2.113 @@ -598,10 +598,17 @@ set widget [test_item set richtextWidget] ns_log notice "[self] [:info class] auto_correct=${:auto_correct}" + if {[acs_user::site_wide_admin_p]} { + set substvalues "{substvalues {textarea,label=Substitution Values}}" + } else { + set substvalues "" + } + #{substvalues {textarea,label=Substitution Values}} :create_components [subst { {text {$widget,height=100px,label=#xowf.exercise-text#,plugins=OacsFs}} {attachments {[:attachments_widget ${:nr_attachments}]}} {answer {short_text_field,repeat=1..${:nr},label=}} + $substvalues }] set :__initialized 1 } @@ -610,6 +617,11 @@ set intro_text [:get_named_sub_component_value text] set answerFields [:get_named_sub_component_value -from_repeat answer] + if {[acs_user::site_wide_admin_p]} { + set substvalues [:get_named_sub_component_value substvalues] + } else { + set substvalues "" + } set options {} set render_hints {} @@ -657,6 +669,7 @@ ${:object} set_property -new 1 anon_instances $anon_instances ${:object} set_property -new 1 auto_correct ${:auto_correct} ${:object} set_property -new 1 has_solution false + ${:object} set_property -new 1 substvalues $substvalues } # @@ -773,13 +786,14 @@ answer:[:dict_to_fc -type reorder_box $fc_dict] \ @categories:off @cr_fields:hidden - ns_log notice "reorder_interaction $form\n$fc" + #ns_log notice "reorder_interaction $form\n$fc" ${:object} set_property -new 1 form $form ${:object} set_property -new 1 form_constraints $fc set anon_instances true ;# TODO make me configurable ${:object} set_property -new 1 anon_instances $anon_instances ${:object} set_property -new 1 auto_correct ${:auto_correct} ${:object} set_property -new 1 has_solution false + #ns_log notice "${:name} FINAL FC $fc" } } @@ -2877,6 +2891,86 @@ return $result } + :method percent_substitute {-verbose:switch -substvalues -seed text} { + set result "" + set start 0 + foreach {p0 p1 p2} [regexp -all -inline -indices {%([a-zA-Z0-9_]+)[.]?([a-zA-Z0-9_]*)%} $text] { + lassign $p0 first last + set match [string range $text $first $last] + set m1 [string range $text {*}$p1] + set m2 [string range $text {*}$p2] + if {[dict exists $substvalues $m1]} { + set values [dict get $substvalues $m1] + if {[info exists seed]} { + set index [::xowiki::randomized_index -seed $seed [llength $values]] + ns_log notice "XXX percent_substitute called with seed <$seed> -> index $index <[llength $values]>" + set value [lindex $values $index] + } else { + set value [lindex $values 0] + } + if {$m2 ne "" && [dict exists $value $m2]} { + set value [dict get $value $m2] + if {$verbose} { + ns_log notice "XXX percent_substitute chooses '$value' for $m2 from <$values>" + } + } + set replacement $value + } else { + set replacement '$match' + } + append result \ + [string range $text $start $first-1] \ + $replacement + set start [incr last] + } + append result [string range $text $start [string length $text]] + return $result + } + + :public method item_substitute_markup { + -obj:object + {-position:integer 0} + -form_obj:object + } { + # + # Substitute everything item-specific in the text, including + # markup (handling e.g. images resolving in the context of the + # original question) and also percent-substitutions + # + :assert_answer_instance $obj + set html [$obj substitute_markup \ + -context_obj $form_obj \ + [$form_obj property form]] + set fc [$form_obj property form_constraints] + set dfc [$form_obj property disabled_form_constraints] + set form_name [$form_obj name] + ns_log notice "CHECK-AA $form_name obj $obj [$obj name] form_obj $form_obj form $html seeds [$obj property seeds] pos $position" + #ns_log notice "CHECK-AA $form_name fc <[$form_obj property form_constraints]>" + set seed [lindex [$obj property seeds] $position] + + ns_log notice "CHECK-AA $form_name seed <$seed> // seeds <[$obj property seeds]>" + if {$seed eq ""} { + ns_log warning "item_substitute_markup cannot substitute percent variables in $form_name" + } else { + set substvalues [$form_obj property substvalues] + if {$substvalues ne ""} { + set html [:percent_substitute \ + -seed $seed \ + -substvalues $substvalues \ + $html] + set fc [:percent_substitute \ + -seed $seed \ + -substvalues $substvalues \ + $fc] + set dfc [:percent_substitute -verbose \ + -seed $seed \ + -substvalues [$form_obj property substvalues] \ + $dfc] + } + } + return [list form $html form_constraints $fc disabled_form_constraints $dfc] + } + :public method disallow_paste {form_obj:object} { # # This function changes the form_constraints of the provided @@ -2912,15 +3006,22 @@ }] } - :method question_info { + :public method question_info { {-numbers ""} {-with_title:switch false} {-with_minutes:switch false} {-with_points:switch false} {-titleless_form:switch false} {-obj:object} + {-user_answers:object:object,0..1 ""} form_objs } { + # + # Returns a dict containing "form", "title_infos", + # "form_constraints" "disabled_form_constraints" + # "randomization_for_exam" "autograde" and "question_objs". This + # information is obtained from the provided "form_objs". + # set full_form {} set full_fc {} set full_disabled_fc {} @@ -2938,17 +3039,15 @@ set points $minutes } set time_budget [$obj property time_budget] - ns_log notice "[$form_obj name]: TIME BUDGET '$time_budget'" if {$time_budget ni {"" 100}} { set minutes [expr {$time_budget*$minutes/100.0}] ns_log notice "[$form_obj name]: TIME BUDGET '$time_budget' -> minutes set to $minutes" - ns_log notice "[$form_obj name]: [$obj instance_attributes]" } set mapping {show_points with_points show_minutes with_minutes} foreach property {show_points show_minutes} { if {[$obj property $property] ne ""} { set [dict get $mapping $property] [$obj property $property] - ns_log notice "[$form_obj name]: override flag via exam setting: '$property' -> [$obj property $property]" + #ns_log notice "[$form_obj name]: override flag via exam setting: '$property' -> [$obj property $property]" } } set title "" @@ -2967,16 +3066,25 @@ if {!$titleless_form} { append full_form \ - "