[system] / trunk / webwork2 / bin / ww_db_v2_to_v3 Repository:
ViewVC logotype

View of /trunk/webwork2/bin/ww_db_v2_to_v3

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3021 - (download) (annotate)
Thu Dec 9 16:30:12 2004 UTC (8 years, 6 months ago) by sh002i
File size: 20597 byte(s)
refactored status/role lookups, added abstract set/problem support

    1 #!/usr/bin/env perl
    2 ################################################################################
    3 # WeBWorK Online Homework Delivery System
    4 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    5 # $CVSHeader: webwork2/bin/ww_db_v2_to_v3,v 1.1 2004/11/25 05:50:51 sh002i Exp $
    6 # 
    7 # This program is free software; you can redistribute it and/or modify it under
    8 # the terms of either: (a) the GNU General Public License as published by the
    9 # Free Software Foundation; either version 2, or (at your option) any later
   10 # version, or (b) the "Artistic License" which comes with this package.
   11 # 
   12 # This program is distributed in the hope that it will be useful, but WITHOUT
   13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   14 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   15 # Artistic License for more details.
   16 ################################################################################
   17 
   18 =head1 NAME
   19 
   20 ww_db_v2_to_v3 - convert a WWDBv2 database to a WWDBv3 database.
   21 
   22 =head1 SYNOPSIS
   23 
   24  ww_db_v2_to_v3 -crsuv course ...
   25 
   26 =head1 DESCRIPTION
   27 
   28 Copies course data from legacy WWDBv2 database(s) to a WWDBv3 database. This may
   29 take a long time.
   30 
   31 You must disallow login to the WeBWorK system while the transfer is taking
   32 place. To disable logins for all courses, set the permission level necessary for
   33 C<login> to $nobody in F<global.conf>. (It is usually set to $student.)
   34 
   35 =head1 OPTIONS
   36 
   37 =over
   38 
   39 =item -c
   40 
   41 If an error occurs while copying a course's data, continue copying with the next
   42 course.
   43 
   44 =item -r
   45 
   46 Update role table in WWDBv3 database from permission level information in
   47 F<global.conf>.
   48 
   49 =item -s
   50 
   51 Update status table in WWDBv3 database from the status information in
   52 F<global.conf>.
   53 
   54 =item -u
   55 
   56 When importing a user that already exists in the WWDBv3 database, replace the
   57 existing information (including the password) with the information in the user
   58 record being imported.
   59 
   60 If this option is not specified, existing users are not updated.
   61 
   62 =item -v
   63 
   64 Verbose operation.
   65 
   66 =item course ...
   67 
   68 Data from these courses will be copied.
   69 
   70 =back
   71 
   72 =head1 BEHAVIOR
   73 
   74 =head2 ROLES
   75 
   76 =over
   77 
   78 =item *
   79 
   80 Roles created with the -r switch are created as system-wide roles.
   81 
   82 =item *
   83 
   84 Roles are created by observing the %permissionLevels hash in F<global.conf>, and
   85 collecting the privileges granted at each permission level into sets. Each set
   86 of privileges becomes a WWDBv3 role record.
   87 
   88 =item *
   89 
   90 When a role with the same set of permissions already exists in the WWDBv3
   91 database, a new one is not created.
   92 
   93 =back
   94 
   95 =head2 STATUSES
   96 
   97 =over
   98 
   99 =item *
  100 
  101 Statuses created with the -s switch are created as system-wide statuses.
  102 
  103 =item *
  104 
  105 Statuses are created by observing the %{$siteDefaults{status}} hash in
  106 F<global.conf>, and 
  107 
  108 =item *
  109 
  110 A status named "Enrolled" is imported into the database with the
  111 C<allow_course_access>, C<include_in_assignment>, C<include_in_stats>, and
  112 C<include_in_scoring> flags set.
  113 
  114 =item *
  115 
  116 A status named "Audit" is imported into the database with the
  117 C<allow_course_access>, C<include_in_assignment>, and C<include_in_stats>, flags
  118 set, and the C<include_in_scoring> flag unset.
  119 
  120 =item *
  121 
  122 A status named "Drop" is imported into the database with the
  123 C<allow_course_access>, C<include_in_assignment>, C<include_in_stats>, and
  124 C<include_in_scoring> flags unset.
  125 
  126 =item *
  127 
  128 Statuses with other names are imported into the database with the same flags set
  129 as the "Enrolled" flag.
  130 
  131 =back
  132 
  133 =head2 USERS
  134 
  135 =over
  136 
  137 =item *
  138 
  139 WWDBv2 user IDs are converted to login IDs.
  140 
  141 =item *
  142 
  143 Users with the same v2 user ID in different courses are assumed to be the same
  144 user.
  145 
  146 =item *
  147 
  148 A user's permission level is used to determine the role to assign to their v3
  149 participant record. (See L<ROLES>.) If the user has an empty permission level,
  150 they are assigned the role associated with permission level "0".
  151 
  152 =item *
  153 
  154 A user's status abbreviation is used to determine the status to assign to their
  155 v3 participant record. (See L<STATUSES>.) If the user has an empty status, they
  156 are assigned the status "Enrolled".
  157 
  158 =item *
  159 
  160 If a user has a non-empty section or recitation, their v3 participant record
  161 will be assigned to the section or recitation with a matching name.
  162 
  163 =back
  164 
  165 =cut
  166 
  167 use strict;
  168 use warnings;
  169 use Data::Dumper;
  170 use DateTime;
  171 use Getopt::Std;
  172 
  173 BEGIN {
  174 	die "WEBWORK_ROOT not found in environment.\n"
  175 		unless exists $ENV{WEBWORK_ROOT};
  176 }
  177 
  178 use lib "$ENV{WEBWORK_ROOT}/lib";
  179 use WeBWorK::CourseEnvironment;
  180 use WeBWorK::DB;
  181 use WeBWorK::DBv3;
  182 
  183 # map statuses from course environment to sets of status privileges
  184 use constant STATUS_MAP => {
  185 	Enrolled => { allow_course_access => 1, include_in_assignment => 1, include_in_stats => 1, include_in_scoring => 1 },
  186 	Audit    => { allow_course_access => 1, include_in_assignment => 1, include_in_stats => 1, include_in_scoring => 0 },
  187 	Drop     => { allow_course_access => 0, include_in_assignment => 0, include_in_stats => 0, include_in_scoring => 0 },
  188 };
  189 
  190 use constant DEFAULT_STATUS => "C";
  191 use constant DEFAULT_PERMISSION_LEVEL => "0";
  192 
  193 our ($opt_c, $opt_r, $opt_s, $opt_u, $opt_v);
  194 getopts("crsuv");
  195 
  196 sub debug { print STDERR @_ if $opt_v }
  197 sub usage { print STDERR "usage: $0 [-crsuv] course ...\n"; exit 1 }
  198 
  199 main(@ARGV);
  200 
  201 sub main {
  202 	my (@courseIDs) = @_;
  203 	
  204 	usage() unless @courseIDs;
  205 	
  206 	my $ce = WeBWorK::CourseEnvironment->new({webwork_dir => $ENV{WEBWORK_ROOT}});
  207 	
  208 	WeBWorK::DBv3::init($ce->{wwdbv3_settings});
  209 	
  210 	my %abbrev_to_status_id = set_up_statuses($ce->{siteDefaults}{status});
  211 	warn "abbrev_to_status_id: ", Dumper(\%abbrev_to_status_id);
  212 	
  213 	my %level_to_role_id = set_up_roles($ce->{permissionLevels});
  214 	warn "level_to_role_id: ", Dumper(\%level_to_role_id);
  215 	
  216 	foreach my $courseID (@courseIDs) {
  217 		eval { copy_course_data($courseID, \%abbrev_to_status_id, \%level_to_role_id) };
  218 		if ($@) {
  219 			warn "An error occured while copying data from course '$courseID':\n\n$@\n\n";
  220 			if ($opt_c) {
  221 				warn "Continuing with the next course...\n";
  222 			} else {
  223 				warn "Exiting.\n";
  224 				exit 2;
  225 			}
  226 		}
  227 	}
  228 }
  229 
  230 ################################################################################
  231 
  232 sub reverse_hash {
  233 	my (%hash) = @_;
  234 	
  235 	my %reverse_hash;
  236 	foreach my $key (keys %hash) {
  237 		my $value = $hash{$key};
  238 		if (defined $value and not ref $value) {
  239 			push @{ $reverse_hash{$value} }, $key;
  240 		#} else {
  241 		#	my $val_string = defined $value ? $value : "UNDEF";
  242 		#	warn "pair ( $key => $val_string ) skipped.\n";
  243 		}
  244 	}
  245 	
  246 	return %reverse_hash;
  247 }
  248 
  249 sub listeq {
  250 	my ($a, $b) = @_;
  251 	return "" unless @$a == @$b;
  252 	for (my $i = 0; $i < @$a; $i++) {
  253 		return "" unless $a->[$i] eq $b->[$i];
  254 	}
  255 	return 1;
  256 }
  257 
  258 sub is_empty {
  259 	my ($val) = @_;
  260 	return (not defined $val or $val eq "");
  261 }
  262 
  263 ################################################################################
  264 
  265 sub set_up_roles {
  266 	my ($permissionLevels) = @_;
  267 	my %permissionLevels = %$permissionLevels;
  268 	
  269 	my %level_to_role_id;
  270 	
  271 	# reverse the permission levels hash, resulting in a hash mapping
  272 	# permissions levels to arrayrefs containing privileges
  273 	my %levels = reverse_hash(%permissionLevels);
  274 	
  275 	# copy up the privileges at each level to the next-higher level
  276  	# also sort each level
  277 	my @level_names = sort { $a <=> $b } keys %levels;
  278 	foreach my $i (0 .. $#level_names-1) {
  279 		my $this_level = $level_names[$i];
  280 		my $next_level = $level_names[$i+1];
  281 		push @{ $levels{$next_level} }, @{ $levels{$this_level} };
  282 	}
  283 	
  284 	# sort the privileges in each level
  285 	debug("I found the following permission levels:\n");
  286 	foreach my $level (keys %levels) {
  287 		my @sorted = sort @{ $levels{$level} };
  288 		$levels{$level} = [ @sorted ];
  289 		debug("\t$level => @sorted\n");
  290 	}
  291 	
  292 	# keep track of role names so we know if we need to rename any of our new ones
  293 	my %role_names;
  294 	
  295 	# look at existing roles to see if we can avoid adding some new ones
  296 	my $i = retrieve_all WeBWorK::DBv3::Role;
  297 	while (my $Role = $i->next) {
  298 		$role_names{$Role->name} = 1;
  299 		my @role_privs = sort $Role->priv_list;
  300 		
  301 		foreach my $level (keys %levels) {
  302 			if (listeq($levels{$level}, \@role_privs)) {
  303 				debug("Permission level '$level' is already represented as role '",
  304 					$Role->name, "' (ID $Role) -- skipping.\n");
  305 				delete $levels{$level};
  306 				$level_to_role_id{$level} = $Role->id;
  307 			}
  308 		}
  309 	}
  310 	
  311 	if ($opt_r) {
  312 		debug("Updating role table (as per -r switch).\n");
  313 		foreach my $level (keys %levels) {
  314 			my $name = "Legacy permission level $level";
  315 			if (exists $role_names{$name}) {
  316 				my $i = 2;
  317 				while (1) {
  318 					my $try_name = "$name (#$i)";
  319 					if (not exists $role_names{$try_name}) {
  320 						$name = $try_name;
  321 						last;
  322 					}
  323 				}
  324 			}
  325 			
  326 			my @privs = @{ $levels{$level} };
  327 			
  328 			my $Role = create WeBWorK::DBv3::Role({name => $name });
  329 			$Role->priv_list(@privs);
  330 			$Role->update;
  331 			debug("Added role '", $Role->name, "' (ID $Role) with privileges '@privs'.\n");
  332 			$level_to_role_id{$level} = $Role->id;
  333 		}
  334 	} else {
  335 		debug("Not updating role table (as per lack of -r switch).\n");
  336 		debug("I might run into users with permission levels that don't map to roles later.\n");
  337 	}
  338 	
  339 	return %level_to_role_id;
  340 }
  341 
  342 sub set_up_statuses {
  343 	my ($abbrevs) = @_;
  344 	my %abbrevs = %$abbrevs;
  345 	
  346 	my %abbrev_to_status_id;
  347 	
  348 	# reverse the statuses hash, resulting in a hash mapping statuses to
  349 	# arrayrefs containing abbreviations
  350 	my %statuses = reverse_hash(%abbrevs);
  351 	
  352 	# look at existing statuses to see if we can avoid adding some new ones
  353 	my $i = retrieve_all WeBWorK::DBv3::Status;
  354 	while (my $Status = $i->next) {
  355 		if (exists $statuses{$Status->name}) {
  356 			debug("Status '", $Status->name, "' (ID $Status) already exists in the database -- skipping.\n");
  357 			# add entries mapping abbreviations to the ID of this status
  358 			foreach my $abbrev (@{$statuses{$Status->name}}) {
  359 				$abbrev_to_status_id{$abbrev} = $Status->id;
  360 			}
  361 			
  362 			delete $statuses{$Status->name};
  363 		}
  364 	}
  365 	
  366 	if ($opt_s) {
  367 		debug("Updating status table (as per -s switch).\n");
  368 		foreach my $status (keys %statuses) {
  369 			my %flags;
  370 			%flags = %{ STATUS_MAP->{$status} } if exists STATUS_MAP->{$status};
  371 			my $Status = create WeBWorK::DBv3::Status({name => $status, %flags});
  372 			
  373 			my @flags = grep { $flags{$_} } keys %flags;
  374 			debug("Added status '", $Status->name, "' (ID $Status) with flags '@flags'.\n");
  375 			
  376 			# add entries mapping abbreviations to the ID of this status
  377 			foreach my $abbrev (@{$statuses{$status}}) {
  378 				$abbrev_to_status_id{$abbrev} = $Status->id;
  379 			}
  380 		}
  381 	} else {
  382 		debug("Not updating status table (as per lack of -s switch).\n");
  383 		debug("I might run into users with status abbreviations that don't map to statuses later.\n");
  384 	}
  385 	
  386 	return %abbrev_to_status_id;
  387 }
  388 
  389 ################################################################################
  390 
  391 sub copy_course_data {
  392 	my ($courseID, $abbrev_to_status_id, $level_to_role_id) = @_;
  393 	
  394 	debug("Processing course '$courseID'...\n");
  395 	
  396 	my $course_ce = WeBWorK::CourseEnvironment->new({
  397 		webwork_dir => $ENV{WEBWORK_ROOT},
  398 		courseName => $courseID,
  399 	});
  400 	
  401 	my $course_db = WeBWorK::DB->new($course_ce->{dbLayout});
  402 	
  403 	# First we see if this course already exists. If it does, there's a problem
  404 	# and we throw an exception.
  405 	if (search WeBWorK::DBv3::Course(name => $courseID)) {
  406 		die "Course '$courseID' exists in v3 DB";
  407 	}
  408 	
  409 	debug("Course '$courseID' doesn't exist in v3 DB -- adding.\n");
  410 	my $v3Course = create WeBWorK::DBv3::Course({name => $courseID});
  411 	
  412 	copy_users($course_db, $v3Course, $abbrev_to_status_id, $level_to_role_id);
  413 	
  414 	copy_abstract_data($course_db, $v3Course);
  415 }
  416 
  417 ################################################################################
  418 
  419 sub copy_users {
  420 	my ($course_db, $v3Course, $abbrev_to_status_id, $level_to_role_id) = @_;
  421 	
  422 	my $DefaultStatus = find_status(DEFAULT_STATUS, $abbrev_to_status_id);
  423 	die "Default status '", DEFAULT_STATUS, "' does not correspond to any v3 status.\n"
  424 		unless $DefaultStatus;
  425 	
  426 	my $DefaultRole = find_role(DEFAULT_PERMISSION_LEVEL, $level_to_role_id);
  427 	die "Default permission level '", DEFAULT_PERMISSION_LEVEL, "' does not correspond to any v3 role.\n"
  428 		unless $DefaultRole;
  429 	
  430 	my @userIDs = $course_db->listUsers;
  431 	my %Users; @Users{@userIDs} = $course_db->getUsers(@userIDs);
  432 	my %Passwords; @Passwords{@userIDs} = $course_db->getPasswords(@userIDs);
  433 	my %PermissionLevels; @PermissionLevels{@userIDs} = $course_db->getPermissionLevels(@userIDs);
  434 	
  435 	foreach my $userID (keys %Users) {
  436 		my $User = $Users{$userID};
  437 		my $Password = $Passwords{$userID};
  438 		my $PermissionLevel = $PermissionLevels{$userID};
  439 		
  440 		unless (defined $User) {
  441 			debug("User record for user ID '$userID' not found -- skipping.\n");
  442 			next;
  443 		}
  444 		
  445 		debug("Processing user '$userID'...\n");
  446 		
  447 		# create/update user record
  448 		my ($v3User) = search WeBWorK::DBv3::User(login_id => $userID);
  449 		if ($v3User) {
  450 			debug("A user with login_id '$userID' exists in v3 database -- ");
  451 			if ($opt_u) {
  452 				# password record might not exist (annoying...)
  453 				my $password = defined $Password ? $Password->password : "";
  454 				
  455 				debug("updating (as per -u switch).\n");
  456 				$v3User->first_name($User->first_name) unless is_empty($User->first_name);
  457 				$v3User->last_name($User->first_name) unless is_empty($User->last_name);
  458 				$v3User->email_address($User->email_address) unless is_empty($User->email_address);
  459 				$v3User->student_id($User->student_id) unless is_empty($User->student_id);
  460 				$v3User->password($password) unless is_empty($password);
  461 				$v3User->update;
  462 			} else {
  463 				debug("not updating (as per lack of -u switch).\n");
  464 			}
  465 		} else {
  466 			# password record might not exist (annoying...)
  467 			my $password = defined $Password ? $Password->password : "";
  468 			
  469 			debug("No user with login_id '$userID' exists in v3 database -- adding.\n");
  470 			$v3User = create WeBWorK::DBv3::User({
  471 				first_name    => $User->first_name,
  472 				last_name     => $User->last_name,
  473 				email_address => $User->email_address,
  474 				student_id    => $User->student_id,
  475 				login_id      => $User->user_id,
  476 				password      => $password,
  477 			});
  478 		}
  479 		
  480 		# get status
  481 		my $v3Status = find_status($User->status, $abbrev_to_status_id);
  482 		unless ($v3Status) {
  483 			debug("Using default status '", $DefaultStatus->name, "'.\n");
  484 			$v3Status = $DefaultStatus;
  485 		}
  486 		
  487 		# get role
  488 		my $level = defined $PermissionLevel ? $PermissionLevel->permission : "";
  489 		my $v3Role = find_role($level, $level_to_role_id);
  490 		unless ($v3Role) {
  491 			debug("Using default role '", $DefaultRole->name, "'.\n");
  492 			$v3Role = $DefaultRole;
  493 		}
  494 		
  495 		# find/create section record
  496 		my $section = $User->section;
  497 		my $v3Section;
  498 		if (is_empty($section)) {
  499 			debug("This user has section '$section'.\n");
  500 			($v3Section) = search WeBWorK::DBv3::Section(course => $v3Course, name => $section);
  501 			if ($v3Section) {
  502 				debug("This corresponds to existing section ID $v3Section in v3 database.\n");
  503 			} else {
  504 				debug("No corresponding section exists in v3 DB -- adding.\n");
  505 				$v3Section = create WeBWorK::DBv3::Section({
  506 					course => $v3Course,
  507 					name   => $section,
  508 				});
  509 				debug("Added section '", $v3Section->name, "' (ID $v3Section).\n");
  510 			}
  511 		} else {
  512 			debug("This user has no section.\n");
  513 		}
  514 		
  515 		# find/create recitation record
  516 		my $recitation = $User->recitation;
  517 		my $v3Recitation;
  518 		if (is_empty($recitation)) {
  519 			debug("This user has recitation '$recitation'.\n");
  520  			($v3Recitation) = search WeBWorK::DBv3::Recitation(course => $v3Course, name => $User->recitation);
  521 			if ($v3Recitation) {
  522 				debug("This correponds to existing recitation ID $v3Recitation in v3 database.\n");
  523 			} else {
  524 				debug("No corresponding recitation exists in v3 DB -- adding.\n");
  525 				$v3Recitation = create WeBWorK::DBv3::Recitation({
  526 					course => $v3Course,
  527 					name   => $User->recitation,
  528 				});
  529 				debug("Added recitation '", $v3Recitation->name, "' (ID $v3Recitation).\n");
  530 			}
  531 		} else {
  532 			debug("This user has no recitation.\n");
  533 		}
  534 		
  535 		# create participant record
  536 		debug("Adding participant record for user '$userID'...");
  537 		#my $sectionID = $v3Section->id if defined $v3Section;
  538 		#my $recitationID = $v3Recitation->id if defined $v3Recitation;
  539 		my $v3Participant = create WeBWorK::DBv3::Participant({
  540 			course     => $v3Course,
  541 			user       => $v3User,
  542 			status     => $v3Status,
  543 			role       => $v3Role,
  544 			section    => $v3Section,
  545 			recitation => $v3Recitation,
  546 			comment    => $User->comment,
  547 		});
  548 		debug(" added participant ID $v3Participant.\n");
  549 	}
  550 }
  551 
  552 sub find_status {
  553 	my ($status, $abbrev_to_status_id) = @_;
  554 	
  555 	return if is_empty($status);
  556 	
  557 	my $v3Status_id = $abbrev_to_status_id->{$status};
  558 	my $v3Status;
  559 	if (defined $v3Status_id) {
  560 		#debug("Status '$status' maps to v3 status ID '$v3Status_id'.\n");
  561 		$v3Status = retrieve WeBWorK::DBv3::Status($v3Status_id);
  562 	} else {
  563 		#debug("Status '$status' doesn't map to any v3 status.\n");
  564 	}
  565 	
  566 	return $v3Status;
  567 }
  568 
  569 sub find_role {
  570 	my ($level, $level_to_role_id) = @_;
  571 	
  572 	return if is_empty($level);
  573 	
  574 	my $v3Role_id = $level_to_role_id->{$level};
  575 	my $v3Role;
  576 	if (defined $v3Role_id) {
  577 		#debug("Permission level '$level' maps to v3 role ID '$v3Role_id'.\n");
  578 		$v3Role = retrieve WeBWorK::DBv3::Role($v3Role_id);
  579 	} else {
  580 		#debug("Permission level '$level' doesn't map to any v3 role.\n");
  581 	}
  582 	
  583 	return $v3Role;
  584 }
  585 
  586 ################################################################################
  587 
  588 sub copy_abstract_data {
  589 	my ($course_db, $v3Course) = @_;
  590 	
  591 	my @globalSetIDs = $course_db->listGlobalSets;
  592 	my %GlobalSets; @GlobalSets{@globalSetIDs} = $course_db->getGlobalSets(@globalSetIDs);
  593 	
  594 	foreach my $globalSetID (keys %GlobalSets) {
  595 		my $GlobalSet = $GlobalSets{$globalSetID};
  596 		
  597 		unless (defined $GlobalSet) {
  598 			debug("Global set record for global set ID '$globalSetID' not found -- skipping.\n");
  599 			next;
  600 		}
  601 		
  602 		debug("Processing global set '$globalSetID'...\n");
  603 		
  604 		# set up some fields that need setting up
  605 		# (if the conditional is false, the variable is left undefined)
  606 		
  607 		# convert empty strings to undefined values
  608 		my $set_header = $GlobalSet->set_header unless is_empty($GlobalSet->set_header);
  609 		my $hardcopy_header = $GlobalSet->hardcopy_header unless is_empty($GlobalSet->hardcopy_header);
  610 		
  611 		# convert 
  612 		my $open_date = DateTime->from_epoch(epoch => $GlobalSet->open_date);
  613 		my $due_date = DateTime->from_epoch(epoch => $GlobalSet->due_date);
  614 		my $answer_date = DateTime->from_epoch(epoch => $GlobalSet->answer_date);
  615 		
  616 		# create abstract_set record
  617 		debug("Adding abstract_set record for global set '$globalSetID'...");
  618 		my $v3AbsSet = create WeBWorK::DBv3::AbstractSet({
  619 			course => $v3Course,
  620 			name => $GlobalSet->set_id,
  621 			set_header => $set_header,
  622 			hardcopy_header => $hardcopy_header,
  623 			open_date => $open_date,
  624 			due_date => $due_date,
  625 			answer_date => $answer_date,
  626 			published => $GlobalSet->published,
  627 		});
  628 		debug(" added abstract_set ID '$v3AbsSet'.\n");
  629 		
  630 		my @globalProblemIDs = sort { $a <=> $b } $course_db->listGlobalProblems($globalSetID);
  631 		warn "globalProblemIDs=@globalProblemIDs\n";
  632 		my %GlobalProblems; @GlobalProblems{@globalProblemIDs}
  633 			= $course_db->getGlobalProblems(map { [ $globalSetID, $_ ] } @globalProblemIDs);
  634 		
  635 		my @problem_order;
  636 		
  637 		foreach my $globalProblemID (@globalProblemIDs) {
  638 			my $GlobalProblem = $GlobalProblems{$globalProblemID};
  639 			
  640 			unless (defined $GlobalProblem) {
  641 				warn "Global problem record for global problem ID '$globalProblemID' in set ID '$globalSetID' not found -- skipping.\n";
  642 				next;
  643 			}
  644 			
  645 			debug("Processing global problem '$globalProblemID'...\n");
  646 		
  647 			# convert max_attempts of -1 to undef
  648 			my $max_attempts_per_version = $GlobalProblem->max_attempts
  649 				if $GlobalProblem->max_attempts >= 0;
  650 			
  651 			# create abstract_problem record
  652 			debug("Adding abstract_set record for global problem '$globalProblemID'...");
  653 			my $v3AbsProb = create WeBWorK::DBv3::AbstractProblem({
  654 				abstract_set => $v3AbsSet,
  655 				name => "Legacy problem $globalProblemID",
  656 				source_type => "file",
  657 				source_file => $GlobalProblem->source_file,
  658 				weight => $GlobalProblem->value,
  659 				max_attempts_per_version => $max_attempts_per_version,
  660 				version_creation_interval => undef,
  661 				versions_per_interval => 1,
  662 				version_due_date_offset => undef,
  663 				version_answer_date_offset => undef,
  664 			});
  665 			debug(" added abstract_problem ID '$v3AbsProb'.\n");
  666 			
  667 			push @problem_order, $v3AbsProb->id;
  668 		}
  669 		
  670 		# update problem order
  671 		debug("Setting problem order to: '@problem_order'...");
  672 		$v3AbsSet->problem_order_list(@problem_order);
  673 		$v3AbsSet->update;
  674 		debug(" done.\n");
  675 	}
  676 }
  677 
  678 
  679 
  680 
  681 
  682 
  683 
  684 
  685 
  686 
  687 
  688 
  689 
  690 
  691 

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9