Index: openacs-4/contrib/packages/simulation/sql/postgresql/simulation-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/sql/postgresql/Attic/simulation-drop.sql,v diff -u -r1.15 -r1.16 --- openacs-4/contrib/packages/simulation/sql/postgresql/simulation-drop.sql 16 Dec 2003 15:59:47 -0000 1.15 +++ openacs-4/contrib/packages/simulation/sql/postgresql/simulation-drop.sql 18 Dec 2003 15:22:54 -0000 1.16 @@ -5,7 +5,7 @@ --drop independent tables drop table sim_party_sim_map; drop table sim_tasks; -drop table sim_role_group_map; +drop table sim_role_party_map; drop table sim_roles; select acs_object_type__drop_type( 'simulation', Index: openacs-4/contrib/packages/simulation/sql/postgresql/simulation-tables-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/sql/postgresql/Attic/simulation-tables-create.sql,v diff -u -r1.15 -r1.16 --- openacs-4/contrib/packages/simulation/sql/postgresql/simulation-tables-create.sql 18 Dec 2003 15:19:33 -0000 1.15 +++ openacs-4/contrib/packages/simulation/sql/postgresql/simulation-tables-create.sql 18 Dec 2003 15:22:54 -0000 1.16 @@ -49,20 +49,20 @@ primary key, character_id integer constraint sim_roles_character_fk references cr_items - on delete cascade + on delete cascade, + users_per_case integer default 1 ); comment on table sim_roles is 'Each record is a role within a simulation template to be played by one or more users or a computer agent when the template is instantiated into cases.'; -create table sim_role_group_map ( - role_id integer constraint sim_role_group_map_ri_fk +create table sim_role_party_map ( + role_id integer constraint sim_role_party_map_ri_fk references workflow_roles(role_id) on delete cascade, - party_id integer constraint sim_role_group_map_party_fk + party_id integer constraint sim_role_party_map_party_fk references parties on delete cascade, - group_size integer default 1, - constraint sim_role_group_map_pk + constraint sim_role_party_map_pk primary key(role_id, party_id) ); Index: openacs-4/contrib/packages/simulation/tcl/sim-role-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/tcl/Attic/sim-role-procs.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/contrib/packages/simulation/tcl/sim-role-procs.tcl 17 Dec 2003 16:29:07 -0000 1.2 +++ openacs-4/contrib/packages/simulation/tcl/sim-role-procs.tcl 18 Dec 2003 15:22:55 -0000 1.3 @@ -79,7 +79,7 @@ # Handle columns in the sim_tasks table foreach attr { - character_id + character_id users_per_case } { if { [info exists row($attr)] } { set varname attr_$attr @@ -102,7 +102,7 @@ } } } - + db_transaction { # Base row set role_id [workflow::role::edit \ Index: openacs-4/contrib/packages/simulation/tcl/simulation-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/tcl/Attic/simulation-procs.tcl,v diff -u -r1.17 -r1.18 --- openacs-4/contrib/packages/simulation/tcl/simulation-procs.tcl 18 Dec 2003 08:31:03 -0000 1.17 +++ openacs-4/contrib/packages/simulation/tcl/simulation-procs.tcl 18 Dec 2003 15:22:56 -0000 1.18 @@ -172,12 +172,9 @@ @param enrolled_only Provide this switch to only get groups selected for auto enrollment. - @return An array lists on the format + @return A nested array lists on the format [list group_id1 [list group_name1 n_users1] group_id2 [list group_name2 n_users2] ...] -with label-id pairs, suitable to be passed - as the options attribute of a form builder select widget. - @author Peter Marklund } { # lookup package_id of the nearest subsite Index: openacs-4/contrib/packages/simulation/tcl/template-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/tcl/Attic/template-procs.tcl,v diff -u -r1.24 -r1.25 --- openacs-4/contrib/packages/simulation/tcl/template-procs.tcl 18 Dec 2003 14:19:28 -0000 1.24 +++ openacs-4/contrib/packages/simulation/tcl/template-procs.tcl 18 Dec 2003 15:22:56 -0000 1.25 @@ -242,52 +242,95 @@ # Additional API implementations #---------------------------------------------------------------------- -ad_proc -public simulation::template::delete_role_group_mappings { +ad_proc -public simulation::template::delete_role_party_mappings { {-workflow_id} } { + Clear out all role-party mappings for a template. Used when editing + the mappings before adding the new ones. + + @author Peter Marklund +} { db_dml clear_old_group_mappings { - delete from sim_role_group_map + delete from sim_role_party_map where role_id in (select role_id from workflow_roles where workflow_id = :workflow_id ) } } -ad_proc -public simulation::template::new_role_group_mapping { +ad_proc -public simulation::template::new_role_party_mappings { {-role_id:required} - {-group_id:required} - {-group_size:required} + {-parties:required} } { - db_dml map_group_to_role { - insert into sim_role_group_map (role_id, party_id, group_size) - values (:role_id, :group_id, :group_size) + Map a list of parties to a role + + @param parties A list of party ids to map to the role + +} { + foreach party_id $parties { + db_dml map_group_to_role { + insert into sim_role_party_map (role_id, party_id) + values (:role_id, :party_id) + } } } -ad_proc -public simulation::template::get_role_group_mappings { +ad_proc -public simulation::template::role_party_mappings { {-workflow_id} {-array:required} +} { + Return a nested array list with the parties mapped to roles and + the desired number of users to play a role per case for the given simulation + template + + @param array The name of the array to put the information in. The array list + will be nested on the following format: +
+ { + $role_id1 { + parties {$group_id1 $group_id2 ...} + users_per_case $users_per_case1 + } + + $role_id2 { + parties {$group_id1 $group_id2 ...} + users_per_case $users_per_case2 + } + } +} { upvar $array roles array set roles {} - db_foreach select_group_mappings { - select role_id, - party_id, - group_size - from sim_role_group_map - where role_id in (select role_id - from workflow_roles - where workflow_id = :workflow_id - ) + db_foreach select_party_mappings { + select srpm.role_id, + srpm.party_id, + sr.users_per_case + from sim_role_party_map srpm, + sim_roles sr, + workflow_roles wr + where srpm.role_id = wr.role_id + and wr.workflow_id = :workflow_id + and srpm.role_id = sr.role_id } { - set roles($role_id) [list $party_id $group_size] + array unset one_role + array set one_role {} + if { [info exists roles($role_id)] } { + array set one_role $roles($role_id) + } + + set one_role(users_per_case) $users_per_case + lappend one_role(parties) $party_id + + + set roles($role_id) [array get one_role] } } ad_proc -public simulation::template::get_parties { + {-members:boolean} {-workflow_id:required} {-rel_type "auto-enroll"} } { @@ -296,17 +339,31 @@ @param rel_type The type of relationship of the party to the simulation template. Permissible values are enrolled, invited, and auto-enroll + @param members Provide this switch if you want all members of + the simulation parties rather than the parties + themselves. @return A list of party_id:s } { ad_assert_arg_value_in_list rel_type {enrolled invited auto-enroll} - return [db_list template_parties { - select party_id - from sim_party_sim_map - where simulation_id = :workflow_id - and type = :rel_type - }] + if { $members_p } { + return [db_list template_parties { + select pamm.member_id + from sim_party_sim_map spsm, + party_approved_member_map pamm + where spsm.simulation_id = :workflow_id + and spsm.type = :rel_type + and pamm.party_id = spsm.party_id + }] + } else { + return [db_list template_parties { + select party_id + from sim_party_sim_map + where simulation_id = :workflow_id + and type = :rel_type + }] + } } ad_proc -public simulation::template::ready_for_casting_p { @@ -394,12 +451,16 @@ # no special error handling because the delete is pretty safe } -ad_proc -public simulation::template::start { +ad_proc -public simulation::template::force_start { {-workflow_id:required} } { - Make a simulation go live immediately. Does enrollment and - casting and sets sim_type attribute to live_sim. + Force a simulation to start immediately by updating case_start, + enroll_end, and enroll_start properties to reflect an immediate start + and then directly invoking simulation::template::start. + TODO: make sure the sweeper doesn't pick up simulations that + have been forced to start. + @author Peter Marklund } { simulation::template::get -workflow_id $workflow_id -array simulation @@ -420,17 +481,29 @@ # Set start_date to now set simulation_edit(case_start) $today + simulation::template::edit -workflow_id $workflow_id -array simulation_edit + + simulation::template::start -workflow_id $workflow_id + } +} + +ad_proc -public simulation::template::start { + {-workflow_id:required} +} { + Make a simulation go live. Does enrollment and + casting and sets sim_type attribute to live_sim. + + TODO: invoke this proc from a sweep + + @author Peter Marklund +} { + simulation::template::get -workflow_id $workflow_id -array simulation + + db_transaction { # Auto enroll users in auto-enroll groups set simulation_edit(enrolled) [list] - foreach party_id [simulation::template::get_parties -workflow_id $workflow_id] { - set simulation_edit(enrolled) [concat $simulation_edit(enrolled) \ - [db_list party_users { - select u.user_id - from party_approved_member_map pamm, - users u - where pamm.party_id = :party_id - and pamm.member_id = u.user_id - }]] + foreach users_list [simulation::template::get_parties -members -type auto-enroll -workflow_id $workflow_id] { + set simulation_edit(enrolled) [concat $simulation_edit(enrolled) $users_list] } # Change sim_type to live_sim @@ -457,14 +530,13 @@ @author Peter Marklund } { # Assuming here that mapped parties with type enrolled are users - set user_list [db_list select_users { - select party_id + set total_n_users [db_list select_users { + select count(*) from sim_party_sim_map where type = 'enrolled' }] - set total_n_users [llength $user_list] - simulation::template::get_role_group_mappings -workflow_id $workflow_id -array roles + simulation::template::role_party_mappings -workflow_id $workflow_id -array roles set n_users_per_case 0 foreach role_id [array names roles] { @@ -475,40 +547,53 @@ set n_cases [expr ($total_n_users - $mod_n_users) / $n_users_per_case] if { $mod_n_users == "0" } { - # No rest in dividing, the cases add up nicely - + # No rest in dividing, the cases add up nicely } else { # We are missing mod_n_users to fill up the simulation. Create a new simulation # for those students. set n_cases [expr $n_cases + 1] } - # Create the cases and for each case assign roles to parties - set users_start_index 0 + error "total_n_users=$total_n_users n_users_per_case=$n_users_per_case n_cases=$n_cases mod_n_users=$mod_n_users" + + # Create the cases and for each case assign users to roles for { set case_counter 0 } { $case_counter < $n_cases } { incr case_counter } { - # TODO: what should object_id be here? set object_id [ad_conn package_id] set case_id [workflow::case::new \ -workflow_id $workflow_id \ -object_id $object_id] - # Assign a group of users to each role in the case - set party_array_list [list] + # Assign users from the specified group for each role + set roles_assign_list [list] foreach role_id [array names roles] { - set role_short_name [workflow::role::get_element -role_id $role_id -element short_name] + set group_id [lindex $roles($role_id) 0] + set n_users_to_assign [lindex $roles($role_id) 1] - set users_end_index [expr $users_start_index + $groupings_array($role_id) - 1] + if { ![info exists group_members($group_id)] } { + set group_members($group_id) [party::approved_members -party_id $party_id -object_type user] + } + set n_users_in_group [llength $group_members($group_id)] - set parties_list [lrange $user_list $users_start_index $users_end_index] + if { ![info exists user_index($group_id)] } { + set user_index($group_id) 0 + } - lappend parties_array_list $role_short_name $parties_list + for {set i 0} {$i < $n_users_to_assign} {incr i} { + lappend users_to_assign [lindex $group_members($group_id) $user_index] + + incr user_index + if { $user_index >= $n_users_in_group } { + set user_index 0 + } + } - set users_start_index [expr $users_end_index + 1] + set role_short_name [workflow::role::get_element -role_id $role_id -element short_name] + lappend roles_assign_list $role_short_name $users_to_assign } workflow::case::role::assign \ -case_id $case_id \ - -array $parties_array_list \ + -array roles_assign_list \ -replace } } Index: openacs-4/contrib/packages/simulation/www/siminst/simulation-casting-3.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/www/siminst/Attic/simulation-casting-3.adp,v diff -u -r1.2 -r1.3 --- openacs-4/contrib/packages/simulation/www/siminst/simulation-casting-3.adp 18 Dec 2003 11:01:40 -0000 1.2 +++ openacs-4/contrib/packages/simulation/www/siminst/simulation-casting-3.adp 18 Dec 2003 15:22:56 -0000 1.3 @@ -12,9 +12,3 @@ list
TODO: at the bottom, show a list of all groups that are auto-enrolled but are not assigned anywhere (and hence won't be in any cases) - - - -
- Instantiate -
Index: openacs-4/contrib/packages/simulation/www/siminst/simulation-casting-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/www/siminst/Attic/simulation-casting-3.tcl,v diff -u -r1.6 -r1.7 --- openacs-4/contrib/packages/simulation/www/siminst/simulation-casting-3.tcl 18 Dec 2003 08:31:03 -0000 1.6 +++ openacs-4/contrib/packages/simulation/www/siminst/simulation-casting-3.tcl 18 Dec 2003 15:22:56 -0000 1.7 @@ -8,51 +8,53 @@ workflow_id:integer } -set page_title "Choose actors" +set page_title "Map user groups to roles" set context [list [list "." "SimInst"] $page_title] -# Loop over all workflow roles and append the actor and "in groups of" widgets to the form set form [list] set eligible_groups [simulation::casting_groups -enrolled_only -workflow_id $workflow_id] foreach role_id [workflow::get_roles -workflow_id $workflow_id] { - set role_pretty_name [workflow::role::get_element -role_id $role_id -element pretty_name] - lappend form [list actor_${role_id}:text(select) \ - [list label $role_pretty_name] \ + set role_${role_id}_pretty_name [workflow::role::get_element -role_id $role_id -element pretty_name] + + lappend form [list parties_${role_id}:text(checkbox),multiple \ + [list label \$role_${role_id}_pretty_name] \ [list options $eligible_groups] ] - lappend form [list group_${role_id}:integer [list label "In groups of"] [list value 1] [list html {size 2}]] + lappend form [list users_per_case_${role_id}:integer [list label "Target number of users for this group per case"] [list value 1] [list html {size 2}]] } ad_form \ -name actors \ -export { workflow_id } \ -form $form \ -on_request { - simulation::template::get_role_group_mappings -workflow_id $workflow_id -array roles - + simulation::template::role_party_mappings -workflow_id $workflow_id -array roles + foreach role_id [array names roles] { - set party_id [lindex $roles($role_id) 0] - set group_size [lindex $roles($role_id) 1] + array set one_role $roles($role_id) - element set_properties actors actor_${role_id} -value $party_id - element set_properties actors group_${role_id} -value $group_size + element::set_values actors parties_${role_id} $one_role(parties) + element set_properties actors users_per_case_${role_id} -value $one_role(users_per_case) } } -on_submit { # Validation - # Make sure the number of users per case does not exceed the number of users - # in each group + # Make sure the number of users per case does not exceed the total number of users + # in the selected parties array set groups [simulation::casting_groups_with_counts -enrolled_only -workflow_id $workflow_id] set error_p 0 foreach role_id [workflow::get_roles -workflow_id $workflow_id] { - set group_size [set group_$role_id] - set group_id [set actor_$role_id] - set n_members [lindex $groups($group_id) 1] + set users_per_case [set users_per_case_$role_id] - if { $group_size > $n_members } { - template::form::set_error actors group_$role_id "Group size is larger than the number of users in the group: $n_members" + set n_members 0 + foreach party_id [set parties_$role_id] { + set n_members [expr $n_members + [lindex $groups($party_id) 1]] + } + + if { $users_per_case > $n_members } { + template::form::set_error actors users_per_case_$role_id "Number of users per case is larger than the number of users in the selected groups: $n_members" set error_p 1 break } @@ -61,14 +63,14 @@ break } - # TODO: move this code into the simulation::template::edit proc? Low priority. - # Clear out old mappings - simulation::template::delete_role_group_mappings -workflow_id $workflow_id + simulation::template::delete_role_party_mappings -workflow_id $workflow_id foreach role_id [workflow::get_roles -workflow_id $workflow_id] { - simulation::template::new_role_group_mapping \ + set role_edit(users_per_case) [set users_per_case_$role_id] + simulation::role::edit -role_id $role_id -array role_edit + + simulation::template::new_role_party_mappings \ -role_id $role_id \ - -group_id [set actor_$role_id] \ - -group_size [set group_$role_id] + -parties [set parties_$role_id] \ } ad_returnredirect . Index: openacs-4/contrib/packages/simulation/www/siminst/simulation-start.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/contrib/packages/simulation/www/siminst/Attic/simulation-start.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/contrib/packages/simulation/www/siminst/simulation-start.tcl 17 Dec 2003 16:51:24 -0000 1.2 +++ openacs-4/contrib/packages/simulation/www/siminst/simulation-start.tcl 18 Dec 2003 15:22:56 -0000 1.3 @@ -7,6 +7,6 @@ workflow_id:integer } -simulation::template::start -workflow_id $workflow_id +simulation::template::force_start -workflow_id $workflow_id ad_returnredirect "../simplay" Index: openacs-4/packages/simulation/sql/postgresql/simulation-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/sql/postgresql/simulation-drop.sql,v diff -u -r1.15 -r1.16 --- openacs-4/packages/simulation/sql/postgresql/simulation-drop.sql 16 Dec 2003 15:59:47 -0000 1.15 +++ openacs-4/packages/simulation/sql/postgresql/simulation-drop.sql 18 Dec 2003 15:22:54 -0000 1.16 @@ -5,7 +5,7 @@ --drop independent tables drop table sim_party_sim_map; drop table sim_tasks; -drop table sim_role_group_map; +drop table sim_role_party_map; drop table sim_roles; select acs_object_type__drop_type( 'simulation', Index: openacs-4/packages/simulation/sql/postgresql/simulation-tables-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/sql/postgresql/simulation-tables-create.sql,v diff -u -r1.15 -r1.16 --- openacs-4/packages/simulation/sql/postgresql/simulation-tables-create.sql 18 Dec 2003 15:19:33 -0000 1.15 +++ openacs-4/packages/simulation/sql/postgresql/simulation-tables-create.sql 18 Dec 2003 15:22:54 -0000 1.16 @@ -49,20 +49,20 @@ primary key, character_id integer constraint sim_roles_character_fk references cr_items - on delete cascade + on delete cascade, + users_per_case integer default 1 ); comment on table sim_roles is 'Each record is a role within a simulation template to be played by one or more users or a computer agent when the template is instantiated into cases.'; -create table sim_role_group_map ( - role_id integer constraint sim_role_group_map_ri_fk +create table sim_role_party_map ( + role_id integer constraint sim_role_party_map_ri_fk references workflow_roles(role_id) on delete cascade, - party_id integer constraint sim_role_group_map_party_fk + party_id integer constraint sim_role_party_map_party_fk references parties on delete cascade, - group_size integer default 1, - constraint sim_role_group_map_pk + constraint sim_role_party_map_pk primary key(role_id, party_id) ); Index: openacs-4/packages/simulation/tcl/sim-role-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/tcl/sim-role-procs.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/packages/simulation/tcl/sim-role-procs.tcl 17 Dec 2003 16:29:07 -0000 1.2 +++ openacs-4/packages/simulation/tcl/sim-role-procs.tcl 18 Dec 2003 15:22:55 -0000 1.3 @@ -79,7 +79,7 @@ # Handle columns in the sim_tasks table foreach attr { - character_id + character_id users_per_case } { if { [info exists row($attr)] } { set varname attr_$attr @@ -102,7 +102,7 @@ } } } - + db_transaction { # Base row set role_id [workflow::role::edit \ Index: openacs-4/packages/simulation/tcl/simulation-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/tcl/simulation-procs.tcl,v diff -u -r1.17 -r1.18 --- openacs-4/packages/simulation/tcl/simulation-procs.tcl 18 Dec 2003 08:31:03 -0000 1.17 +++ openacs-4/packages/simulation/tcl/simulation-procs.tcl 18 Dec 2003 15:22:56 -0000 1.18 @@ -172,12 +172,9 @@ @param enrolled_only Provide this switch to only get groups selected for auto enrollment. - @return An array lists on the format + @return A nested array lists on the format [list group_id1 [list group_name1 n_users1] group_id2 [list group_name2 n_users2] ...] -with label-id pairs, suitable to be passed - as the options attribute of a form builder select widget. - @author Peter Marklund } { # lookup package_id of the nearest subsite Index: openacs-4/packages/simulation/tcl/template-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/tcl/template-procs.tcl,v diff -u -r1.24 -r1.25 --- openacs-4/packages/simulation/tcl/template-procs.tcl 18 Dec 2003 14:19:28 -0000 1.24 +++ openacs-4/packages/simulation/tcl/template-procs.tcl 18 Dec 2003 15:22:56 -0000 1.25 @@ -242,52 +242,95 @@ # Additional API implementations #---------------------------------------------------------------------- -ad_proc -public simulation::template::delete_role_group_mappings { +ad_proc -public simulation::template::delete_role_party_mappings { {-workflow_id} } { + Clear out all role-party mappings for a template. Used when editing + the mappings before adding the new ones. + + @author Peter Marklund +} { db_dml clear_old_group_mappings { - delete from sim_role_group_map + delete from sim_role_party_map where role_id in (select role_id from workflow_roles where workflow_id = :workflow_id ) } } -ad_proc -public simulation::template::new_role_group_mapping { +ad_proc -public simulation::template::new_role_party_mappings { {-role_id:required} - {-group_id:required} - {-group_size:required} + {-parties:required} } { - db_dml map_group_to_role { - insert into sim_role_group_map (role_id, party_id, group_size) - values (:role_id, :group_id, :group_size) + Map a list of parties to a role + + @param parties A list of party ids to map to the role + +} { + foreach party_id $parties { + db_dml map_group_to_role { + insert into sim_role_party_map (role_id, party_id) + values (:role_id, :party_id) + } } } -ad_proc -public simulation::template::get_role_group_mappings { +ad_proc -public simulation::template::role_party_mappings { {-workflow_id} {-array:required} +} { + Return a nested array list with the parties mapped to roles and + the desired number of users to play a role per case for the given simulation + template + + @param array The name of the array to put the information in. The array list + will be nested on the following format: ++ { + $role_id1 { + parties {$group_id1 $group_id2 ...} + users_per_case $users_per_case1 + } + + $role_id2 { + parties {$group_id1 $group_id2 ...} + users_per_case $users_per_case2 + } + } +} { upvar $array roles array set roles {} - db_foreach select_group_mappings { - select role_id, - party_id, - group_size - from sim_role_group_map - where role_id in (select role_id - from workflow_roles - where workflow_id = :workflow_id - ) + db_foreach select_party_mappings { + select srpm.role_id, + srpm.party_id, + sr.users_per_case + from sim_role_party_map srpm, + sim_roles sr, + workflow_roles wr + where srpm.role_id = wr.role_id + and wr.workflow_id = :workflow_id + and srpm.role_id = sr.role_id } { - set roles($role_id) [list $party_id $group_size] + array unset one_role + array set one_role {} + if { [info exists roles($role_id)] } { + array set one_role $roles($role_id) + } + + set one_role(users_per_case) $users_per_case + lappend one_role(parties) $party_id + + + set roles($role_id) [array get one_role] } } ad_proc -public simulation::template::get_parties { + {-members:boolean} {-workflow_id:required} {-rel_type "auto-enroll"} } { @@ -296,17 +339,31 @@ @param rel_type The type of relationship of the party to the simulation template. Permissible values are enrolled, invited, and auto-enroll + @param members Provide this switch if you want all members of + the simulation parties rather than the parties + themselves. @return A list of party_id:s } { ad_assert_arg_value_in_list rel_type {enrolled invited auto-enroll} - return [db_list template_parties { - select party_id - from sim_party_sim_map - where simulation_id = :workflow_id - and type = :rel_type - }] + if { $members_p } { + return [db_list template_parties { + select pamm.member_id + from sim_party_sim_map spsm, + party_approved_member_map pamm + where spsm.simulation_id = :workflow_id + and spsm.type = :rel_type + and pamm.party_id = spsm.party_id + }] + } else { + return [db_list template_parties { + select party_id + from sim_party_sim_map + where simulation_id = :workflow_id + and type = :rel_type + }] + } } ad_proc -public simulation::template::ready_for_casting_p { @@ -394,12 +451,16 @@ # no special error handling because the delete is pretty safe } -ad_proc -public simulation::template::start { +ad_proc -public simulation::template::force_start { {-workflow_id:required} } { - Make a simulation go live immediately. Does enrollment and - casting and sets sim_type attribute to live_sim. + Force a simulation to start immediately by updating case_start, + enroll_end, and enroll_start properties to reflect an immediate start + and then directly invoking simulation::template::start. + TODO: make sure the sweeper doesn't pick up simulations that + have been forced to start. + @author Peter Marklund } { simulation::template::get -workflow_id $workflow_id -array simulation @@ -420,17 +481,29 @@ # Set start_date to now set simulation_edit(case_start) $today + simulation::template::edit -workflow_id $workflow_id -array simulation_edit + + simulation::template::start -workflow_id $workflow_id + } +} + +ad_proc -public simulation::template::start { + {-workflow_id:required} +} { + Make a simulation go live. Does enrollment and + casting and sets sim_type attribute to live_sim. + + TODO: invoke this proc from a sweep + + @author Peter Marklund +} { + simulation::template::get -workflow_id $workflow_id -array simulation + + db_transaction { # Auto enroll users in auto-enroll groups set simulation_edit(enrolled) [list] - foreach party_id [simulation::template::get_parties -workflow_id $workflow_id] { - set simulation_edit(enrolled) [concat $simulation_edit(enrolled) \ - [db_list party_users { - select u.user_id - from party_approved_member_map pamm, - users u - where pamm.party_id = :party_id - and pamm.member_id = u.user_id - }]] + foreach users_list [simulation::template::get_parties -members -type auto-enroll -workflow_id $workflow_id] { + set simulation_edit(enrolled) [concat $simulation_edit(enrolled) $users_list] } # Change sim_type to live_sim @@ -457,14 +530,13 @@ @author Peter Marklund } { # Assuming here that mapped parties with type enrolled are users - set user_list [db_list select_users { - select party_id + set total_n_users [db_list select_users { + select count(*) from sim_party_sim_map where type = 'enrolled' }] - set total_n_users [llength $user_list] - simulation::template::get_role_group_mappings -workflow_id $workflow_id -array roles + simulation::template::role_party_mappings -workflow_id $workflow_id -array roles set n_users_per_case 0 foreach role_id [array names roles] { @@ -475,40 +547,53 @@ set n_cases [expr ($total_n_users - $mod_n_users) / $n_users_per_case] if { $mod_n_users == "0" } { - # No rest in dividing, the cases add up nicely - + # No rest in dividing, the cases add up nicely } else { # We are missing mod_n_users to fill up the simulation. Create a new simulation # for those students. set n_cases [expr $n_cases + 1] } - # Create the cases and for each case assign roles to parties - set users_start_index 0 + error "total_n_users=$total_n_users n_users_per_case=$n_users_per_case n_cases=$n_cases mod_n_users=$mod_n_users" + + # Create the cases and for each case assign users to roles for { set case_counter 0 } { $case_counter < $n_cases } { incr case_counter } { - # TODO: what should object_id be here? set object_id [ad_conn package_id] set case_id [workflow::case::new \ -workflow_id $workflow_id \ -object_id $object_id] - # Assign a group of users to each role in the case - set party_array_list [list] + # Assign users from the specified group for each role + set roles_assign_list [list] foreach role_id [array names roles] { - set role_short_name [workflow::role::get_element -role_id $role_id -element short_name] + set group_id [lindex $roles($role_id) 0] + set n_users_to_assign [lindex $roles($role_id) 1] - set users_end_index [expr $users_start_index + $groupings_array($role_id) - 1] + if { ![info exists group_members($group_id)] } { + set group_members($group_id) [party::approved_members -party_id $party_id -object_type user] + } + set n_users_in_group [llength $group_members($group_id)] - set parties_list [lrange $user_list $users_start_index $users_end_index] + if { ![info exists user_index($group_id)] } { + set user_index($group_id) 0 + } - lappend parties_array_list $role_short_name $parties_list + for {set i 0} {$i < $n_users_to_assign} {incr i} { + lappend users_to_assign [lindex $group_members($group_id) $user_index] + + incr user_index + if { $user_index >= $n_users_in_group } { + set user_index 0 + } + } - set users_start_index [expr $users_end_index + 1] + set role_short_name [workflow::role::get_element -role_id $role_id -element short_name] + lappend roles_assign_list $role_short_name $users_to_assign } workflow::case::role::assign \ -case_id $case_id \ - -array $parties_array_list \ + -array roles_assign_list \ -replace } } Index: openacs-4/packages/simulation/www/siminst/simulation-casting-3.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/www/siminst/simulation-casting-3.adp,v diff -u -r1.2 -r1.3 --- openacs-4/packages/simulation/www/siminst/simulation-casting-3.adp 18 Dec 2003 11:01:40 -0000 1.2 +++ openacs-4/packages/simulation/www/siminst/simulation-casting-3.adp 18 Dec 2003 15:22:56 -0000 1.3 @@ -12,9 +12,3 @@ list
TODO: at the bottom, show a list of all groups that are auto-enrolled but are not assigned anywhere (and hence won't be in any cases) - - - -
- Instantiate -
Index: openacs-4/packages/simulation/www/siminst/simulation-casting-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/www/siminst/simulation-casting-3.tcl,v diff -u -r1.6 -r1.7 --- openacs-4/packages/simulation/www/siminst/simulation-casting-3.tcl 18 Dec 2003 08:31:03 -0000 1.6 +++ openacs-4/packages/simulation/www/siminst/simulation-casting-3.tcl 18 Dec 2003 15:22:56 -0000 1.7 @@ -8,51 +8,53 @@ workflow_id:integer } -set page_title "Choose actors" +set page_title "Map user groups to roles" set context [list [list "." "SimInst"] $page_title] -# Loop over all workflow roles and append the actor and "in groups of" widgets to the form set form [list] set eligible_groups [simulation::casting_groups -enrolled_only -workflow_id $workflow_id] foreach role_id [workflow::get_roles -workflow_id $workflow_id] { - set role_pretty_name [workflow::role::get_element -role_id $role_id -element pretty_name] - lappend form [list actor_${role_id}:text(select) \ - [list label $role_pretty_name] \ + set role_${role_id}_pretty_name [workflow::role::get_element -role_id $role_id -element pretty_name] + + lappend form [list parties_${role_id}:text(checkbox),multiple \ + [list label \$role_${role_id}_pretty_name] \ [list options $eligible_groups] ] - lappend form [list group_${role_id}:integer [list label "In groups of"] [list value 1] [list html {size 2}]] + lappend form [list users_per_case_${role_id}:integer [list label "Target number of users for this group per case"] [list value 1] [list html {size 2}]] } ad_form \ -name actors \ -export { workflow_id } \ -form $form \ -on_request { - simulation::template::get_role_group_mappings -workflow_id $workflow_id -array roles - + simulation::template::role_party_mappings -workflow_id $workflow_id -array roles + foreach role_id [array names roles] { - set party_id [lindex $roles($role_id) 0] - set group_size [lindex $roles($role_id) 1] + array set one_role $roles($role_id) - element set_properties actors actor_${role_id} -value $party_id - element set_properties actors group_${role_id} -value $group_size + element::set_values actors parties_${role_id} $one_role(parties) + element set_properties actors users_per_case_${role_id} -value $one_role(users_per_case) } } -on_submit { # Validation - # Make sure the number of users per case does not exceed the number of users - # in each group + # Make sure the number of users per case does not exceed the total number of users + # in the selected parties array set groups [simulation::casting_groups_with_counts -enrolled_only -workflow_id $workflow_id] set error_p 0 foreach role_id [workflow::get_roles -workflow_id $workflow_id] { - set group_size [set group_$role_id] - set group_id [set actor_$role_id] - set n_members [lindex $groups($group_id) 1] + set users_per_case [set users_per_case_$role_id] - if { $group_size > $n_members } { - template::form::set_error actors group_$role_id "Group size is larger than the number of users in the group: $n_members" + set n_members 0 + foreach party_id [set parties_$role_id] { + set n_members [expr $n_members + [lindex $groups($party_id) 1]] + } + + if { $users_per_case > $n_members } { + template::form::set_error actors users_per_case_$role_id "Number of users per case is larger than the number of users in the selected groups: $n_members" set error_p 1 break } @@ -61,14 +63,14 @@ break } - # TODO: move this code into the simulation::template::edit proc? Low priority. - # Clear out old mappings - simulation::template::delete_role_group_mappings -workflow_id $workflow_id + simulation::template::delete_role_party_mappings -workflow_id $workflow_id foreach role_id [workflow::get_roles -workflow_id $workflow_id] { - simulation::template::new_role_group_mapping \ + set role_edit(users_per_case) [set users_per_case_$role_id] + simulation::role::edit -role_id $role_id -array role_edit + + simulation::template::new_role_party_mappings \ -role_id $role_id \ - -group_id [set actor_$role_id] \ - -group_size [set group_$role_id] + -parties [set parties_$role_id] \ } ad_returnredirect . Index: openacs-4/packages/simulation/www/siminst/simulation-start.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/simulation/www/siminst/simulation-start.tcl,v diff -u -r1.2 -r1.3 --- openacs-4/packages/simulation/www/siminst/simulation-start.tcl 17 Dec 2003 16:51:24 -0000 1.2 +++ openacs-4/packages/simulation/www/siminst/simulation-start.tcl 18 Dec 2003 15:22:56 -0000 1.3 @@ -7,6 +7,6 @@ workflow_id:integer } -simulation::template::start -workflow_id $workflow_id +simulation::template::force_start -workflow_id $workflow_id ad_returnredirect "../simplay"