| |
941 |
941 |
array set row [list] |
| |
942 |
942 |
foreach role_id [array names roles] { |
| |
943 |
943 |
array unset one_role |
| |
944 |
944 |
array set one_role $roles($role_id) |
| |
945 |
945 |
|
| |
946 |
946 |
# Get the number of already assigned users in the role and |
| |
947 |
947 |
# figure out if there are empty slots |
| |
948 |
948 |
set users_already_in_case [db_string n_users_already_in_case { |
| |
949 |
949 |
select count(*) |
| |
950 |
950 |
from workflow_case_role_party_map wcrpm |
| |
951 |
951 |
where wcrpm.case_id = :case_id |
| |
952 |
952 |
and wcrpm.role_id = :role_id |
| |
953 |
953 |
}] |
| |
954 |
954 |
|
| |
955 |
955 |
if { [expr $users_already_in_case >= $one_role(users_per_case)] } { |
| |
956 |
956 |
set n_users_to_assign 0 |
| |
957 |
957 |
} else { |
| |
958 |
958 |
set n_users_to_assign [expr $one_role(users_per_case) - $users_already_in_case] |
| |
959 |
959 |
} |
| |
960 |
960 |
|
| |
961 |
|
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - beginning of role loop role_id=$role_id n_users_to_assign=$n_users_to_assign" |
| |
|
961 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - beginning of role loop role_id=$role_id n_users_to_assign=$n_users_to_assign group_members=[array get group_members]" |
| |
962 |
962 |
|
| |
963 |
963 |
set assignees [list] |
| |
964 |
964 |
for { set i 0 } { $i < $n_users_to_assign } { incr i } { |
| |
965 |
965 |
set user_was_cast_p 0 |
| |
966 |
966 |
|
| |
967 |
967 |
# Get the list of users in groups mapped to this role |
| |
968 |
968 |
set role_group_users [list] |
| |
969 |
969 |
foreach group_id [util::randomize_list $one_role(parties)] { |
| |
970 |
970 |
set role_group_users [concat $role_group_users $group_members($group_id)] |
| |
971 |
971 |
} |
| |
972 |
972 |
|
| |
973 |
973 |
# 1. Get random user from users_to_cast list who fulfils either of: |
| |
974 |
974 |
# a) User is in non-multiple case group mapped to role (group_members) |
| |
975 |
975 |
# b) User is in multi case group mapped to role (group_members) |
| |
976 |
976 |
# c) User is not in any group (users_to_cast_not_in_groups) |
| |
|
977 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - before users_to_cast loop, users_to_cast=$users_to_cast role_group_users=$role_group_users" |
| |
977 |
978 |
foreach user_id $users_to_cast { |
| |
978 |
979 |
|
| |
979 |
980 |
set cast_user_p 0 |
| |
980 |
981 |
if { [lsearch $role_group_users $user_id] != -1 } { |
| |
981 |
982 |
# Case a) or b) - user is in a group mapped to the role |
| |
982 |
983 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting user_id=$user_id from group (case a or b)" |
| |
983 |
984 |
|
| |
984 |
985 |
set cast_user_p 1 |
| |
985 |
986 |
|
| |
986 |
987 |
remove_user_from_casting_groups \ |
| |
987 |
988 |
-user_id $user_id \ |
| |
988 |
989 |
-role_groups $one_role(parties) \ |
| |
989 |
990 |
-groups_array group_members \ |
| |
990 |
991 |
-full_groups_array full_group_members \ |
| |
991 |
992 |
-multiple_case_groups $multiple_case_groups |
| |
|
993 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users_to_cast loop, after remove_users_from_casting_groups, group_members=[array get group_members]" |
| |
992 |
994 |
|
| |
993 |
995 |
} elseif { [lsearch $users_to_cast_not_in_groups $user_id] != -1 } { |
| |
994 |
996 |
# Case c) - user not in a group mapped to any role |
| |
995 |
997 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting user_id=$user_id who is not in group (case c)" |
| |
996 |
998 |
|
| |
997 |
999 |
set cast_user_p 1 |
| |
998 |
1000 |
|
| |
999 |
1001 |
# Remove user from the users_to_cast_not_in_groups list |
| |
1000 |
1002 |
set cast_list_index [lsearch -exact $users_to_cast_not_in_groups $user_id] |
| |
1001 |
1003 |
set users_to_cast_not_in_groups [lreplace $users_to_cast_not_in_groups $cast_list_index $cast_list_index] |
| |
1002 |
1004 |
} |
| |
1003 |
1005 |
|
| |
1004 |
1006 |
if { $cast_user_p } { |
| |
1005 |
1007 |
# Cast user |
| |
1006 |
1008 |
lappend assignees $user_id |
| |
1007 |
1009 |
set user_was_cast_p 1 |
| |
1008 |
1010 |
|
| |
1009 |
1011 |
# Remove user from users_to_cast list |
| |
1010 |
1012 |
set cast_list_index [lsearch -exact $users_to_cast $user_id] |
| |
1011 |
1013 |
set users_to_cast [lreplace $users_to_cast $cast_list_index $cast_list_index] |
| |
1012 |
1014 |
|
| |
1013 |
1015 |
break |
| |
1014 |
1016 |
} |
| |
1015 |
1017 |
} |
| |
1016 |
1018 |
|
| |
1017 |
1019 |
# 2. Get user from multiple group mapped to role (a user who is not in the users_to_cast list because he has been cast before) |
| |
1018 |
1020 |
if { !$user_was_cast_p } { |
| |
1019 |
1021 |
foreach group_id $one_role(parties) { |
| |
1020 |
|
if { [lsearch $multiple_case_groups $group_id] == -1 } { |
| |
|
1022 |
if { [lsearch $multiple_case_groups $group_id] != -1 } { |
| |
1021 |
1023 |
# We have a non-empty (they are refilled) multiple group mapped to the role |
| |
1022 |
1024 |
# Cast random user from that group |
| |
|
1025 |
set user_id [lindex $group_members($group_id) 0] |
| |
|
1026 |
|
| |
1023 |
1027 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting already cast user_id=$user_id from multi case group $group_id" |
| |
1024 |
1028 |
|
| |
1025 |
1029 |
set user_was_cast_p 1 |
| |
1026 |
1030 |
lappend assignees $user_id |
| |
1027 |
1031 |
|
| |
1028 |
1032 |
remove_user_from_casting_groups \ |
| |
1029 |
1033 |
-user_id $user_id \ |
| |
1030 |
1034 |
-role_groups $one_role(parties) \ |
| |
1031 |
1035 |
-groups_array group_members \ |
| |
1032 |
1036 |
-full_groups_array full_group_members \ |
| |
1033 |
1037 |
-multiple_case_groups $multiple_case_groups |
| |
1034 |
1038 |
|
| |
1035 |
1039 |
# Remove user from users_to_cast list |
| |
1036 |
1040 |
set cast_list_index [lsearch -exact $users_to_cast $user_id] |
| |
1037 |
1041 |
set users_to_cast [lreplace $users_to_cast $cast_list_index $cast_list_index] |
| |
1038 |
1042 |
|
| |
1039 |
1043 |
break |
| |
1040 |
1044 |
} |
| |
1041 |
1045 |
} |
| |
1042 |
1046 |
} |
| |
1043 |
1047 |
|
| |
1044 |
1048 |
# 3. Last resort - cast admin (filler) |
| |
1045 |
1049 |
if { !$user_was_cast_p } { |
| |
1046 |
1050 |
#ns_log Notice "simulation::template::cast_users_in_case case_id=$case_id - in users to assign loop, role_id=$role_id i=$i casting resorting to cast admin_user_id=$admin_user_id" |
| |
1047 |
1051 |
set user_was_cast_p 1 |
| |
1048 |
1052 |
lappend assignees $admin_user_id |
| |
|
1053 |
# Only cast admin once |
| |
|
1054 |
break |
| |
1049 |
1055 |
} |
| |
1050 |
1056 |
} |
| |
1051 |
1057 |
|
| |
1052 |
1058 |
# Keep track of which users we decided to assign to the role and move on to the next one |
| |
1053 |
|
set row($role_short_name($role_id)) $assignees |
| |
|
1059 |
# It can happen with multi groups that a user gets mapped multiple times to one role. However, there is |
| |
|
1060 |
# a role-party unique constraint in workflow that we mustn't violate. |
| |
|
1061 |
# TODO: If we are removing a user here it means we are one of more users short |
| |
|
1062 |
# of the targeted number of users for the role. In that case we should assign the admin as well if we haven't already done so. |
| |
|
1063 |
set row($role_short_name($role_id)) [template::util::spellcheck::get_sorted_list_with_unique_elements -the_list $assignees] |
| |
1054 |
1064 |
} |
| |
1055 |
1065 |
|
| |
1056 |
1066 |
# Do all the user-role assignments in the case |
| |
1057 |
1067 |
workflow::case::role::assign \ |
| |
1058 |
1068 |
-case_id $case_id \ |
| |
1059 |
1069 |
-array row \ |
| |
1060 |
1070 |
} |
| |
1061 |
1071 |
|
| |
1062 |
1072 |
ad_proc -private simulation::template::remove_user_from_casting_groups { |
| |
1063 |
1073 |
{-user_id:required} |
| |
1064 |
1074 |
{-role_groups:required} |
| |
1065 |
1075 |
{-groups_array:required} |
| |
1066 |
1076 |
{-full_groups_array:required} |
| |
1067 |
1077 |
{-multiple_case_groups:required} |
| |
1068 |
1078 |
} { |
| |
1069 |
1079 |
Remove a cast user from the groups data structure and refill and empty |
| |
1070 |
1080 |
multicase groups. This is an internal proc used by the casting algorithm. |
| |
1071 |
1081 |
|
| |
1072 |
1082 |
@author Peter Marklund |
| |
1073 |
1083 |
} { |
| |
1074 |
1084 |
upvar $groups_array group_members |
| |
1075 |
1085 |
upvar $full_groups_array full_group_members |
| |
1076 |
1086 |
|
| |
1077 |
1087 |
# Remove the user from group_members |
| |
1078 |
1088 |
foreach group_id $role_groups { |
| |
1079 |
1089 |
set group_index [lsearch -exact $group_members($group_id) $user_id] |
| |
1080 |
1090 |
set group_members($group_id) [lreplace $group_members($group_id) $group_index $group_index] |
| |
1081 |
1091 |
|
| |
1082 |
1092 |
# Refill the group if it's now empty and multi-case |
| |
1083 |
|
if { [llength $group_members($group_id)] == 0 && [lsearch $multiple_case_groups $group_id] == -1 } { |
| |
|
1093 |
if { [llength $group_members($group_id)] == 0 && [lsearch $multiple_case_groups $group_id] != -1 } { |
| |
1084 |
1094 |
set group_members($group_id) $full_group_members($group_id) |
| |
1085 |
1095 |
} |
| |
1086 |
1096 |
} |
| |
1087 |
1097 |
} |
| |
1088 |
1098 |
|
| |
1089 |
1099 |
ad_proc -private simulation::template::admin_user_id { |
| |
1090 |
1100 |
{-workflow_id:required} |
| |
1091 |
1101 |
} { |
| |
1092 |
1102 |
When starting a simulation, get the user if of the simulation admin. The simulation |
| |
1093 |
1103 |
admin is the creator of the simulation. |
| |
1094 |
1104 |
|
| |
1095 |
1105 |
@author Peter Marklund |
| |
1096 |
1106 |
} { |
| |
1097 |
1107 |
return [db_string select_creation_user { |
| |
1098 |
1108 |
select creation_user |
| |
1099 |
1109 |
from acs_objects |
| |
1100 |
1110 |
where object_id = :workflow_id |
| |
1101 |
1111 |
}] |
| |
1102 |
1112 |
} |
| |
1103 |
1113 |
|