aboutsummaryrefslogtreecommitdiff
path: root/lib/admissionrules/preferentialadmission/PreferentialAdmission.class.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/admissionrules/preferentialadmission/PreferentialAdmission.class.php')
-rw-r--r--lib/admissionrules/preferentialadmission/PreferentialAdmission.class.php540
1 files changed, 0 insertions, 540 deletions
diff --git a/lib/admissionrules/preferentialadmission/PreferentialAdmission.class.php b/lib/admissionrules/preferentialadmission/PreferentialAdmission.class.php
deleted file mode 100644
index 6bb6ceb..0000000
--- a/lib/admissionrules/preferentialadmission/PreferentialAdmission.class.php
+++ /dev/null
@@ -1,540 +0,0 @@
-<?php
-
-/**
- * PreferentialAdmission.class.php
- *
- * An admission rule that favors selected courses of study or semesters of study.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * @author Thomas Hackl <thomas.hackl@uni-passau.de>
- * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
- * @category Stud.IP
- */
-
-require_once('lib/classes/admission/AdmissionRule.class.php');
-require_once('lib/classes/admission/UserFilter.class.php');
-
-class PreferentialAdmission extends AdmissionRule
-{
- // --- ATTRIBUTES ---
-
- /**
- * Stores IDs of userlists generated for representing the selected
- * conditions. These lists are created on seat distribution in the course
- * set and are deleted immediately after.
- */
- public $userlists = [];
-
- /**
- * Conditions for selecting the favored people in seat distribution.
- */
- public $conditions = [];
-
- /**
- * Should higher semesters of study be favored?
- */
- public $favorSemester = false;
-
- /**
- * If semesters are favored, which bonus difference shall be set between
- * each semester of study?
- */
- public $bonus_difference = 100;
-
- /**
- * The courseset this rule belongs to.
- */
- public $courseset = null;
-
- // --- OPERATIONS ---
-
- /**
- * Standard constructor.
- *
- * @param String ruleId If this rule has been saved previously, it
- * will be loaded from database.
- * @return AdmissionRule the current object (this).
- */
- public function __construct($ruleId='')
- {
- $this->id = $ruleId;
- if ($ruleId) {
- $this->load();
- } else {
- $this->id = $this->generateId('prefadmissions');
- }
- }
-
- /**
- * Adds a new UserFilter to this rule.
- *
- * @param UserFilter condition
- * @return PreferentialAdmission
- */
- public function addCondition($condition)
- {
- $this->conditions[$condition->getId()] = $condition;
- return $this;
- }
-
- /**
- * Hook that can be called after the seat distribution on the courseset
- * has completed. User lists that were generated before are removed now.
- */
- public function afterSeatDistribution($courseset)
- {
- foreach ($this->userlists as $id) {
- $current = new AdmissionUserList($id);
- $courseset->removeUserList($id);
- $current->delete();
- }
- }
-
- /**
- * Hook that can be called when the seat distribution on the courseset
- * starts. This type of admission rule gets all users that fulfill the
- * specified conditions and generates user lists with modified chances
- * in seat distribution.
- *
- * @param CourseSet The courseset this rule belongs to.
- */
- public function beforeSeatDistribution($courseset)
- {
- $this->courseset = $courseset;
- /*
- * First, we need to calculate the maximum of persons applying
- * for a single course as that number will influence the numbers
- * to set for preferation.
- */
- $this->bonus_difference = DBManager::get()->fetchColumn("SELECT MAX(users) FROM (
- SELECT `priority`, COUNT(DISTINCT `user_id`) AS users
- FROM `priorities`
- WHERE `set_id` = ?
- GROUP BY `priority`
- ) t", [$courseset->getId()]);
- $users = $this->getAffectedUsers();
-
- // No study semester variation, just put all users together.
- if (!$this->favorSemester) {
-
- $userlist = new AdmissionUserList();
- $userlist->setUsers($users)->setFactor($this->bonus_difference + 1)->store();
- $this->userlists[] = $userlist->getId();
- $courseset->addUserList($userlist->getId());
-
- // Study semesters need to be considered for differentiation...
- } else {
- /*
- * Build data grouped by semester of study for users affected
- * by given conditions.
- */
- if ($this->conditions) {
- $grouped = $this->getSemesterGroups($users, true);
-
- /*
- * Build data grouped by semester of study for all users
- * (excluding all users affected by given conditions).
- */
- $rest = $this->getSemesterGroups(
- array_keys(AdmissionPriority::getPriorities($courseset->getId())),
- false, $users);
-
- /*
- * Now set bonus factors to higher semesters. We are processing
- * users not affected by conditions first so that we get the
- * maximum bonus these users get and can build on top of that
- * for users affected by conditions.
- */
- $maxbonus = $this->setSemesterBonus($courseset, $rest);
-
- /*
- * Finally, set bonuses for the users affected by conditions.
- */
- $endbonus = $this->setSemesterBonus($courseset, $grouped, $maxbonus + 1);
- /*
- * No conditions given, just group all users
- * by their semester of study.
- */
- } else {
- // Build list of users by semester of study.
- $grouped = $this->getSemesterGroups(
- array_keys(AdmissionPriority::getPriorities($courseset->getId())),
- false);
-
- // Assign corresponding bonus to users.
- $maxbonus = $this->setSemesterBonus($courseset, $grouped);
- }
- }
- }
-
- /**
- * Deletes the admission rule and all associated data.
- */
- public function delete()
- {
- parent::delete();
- // Delete rule data.
- $stmt = DBManager::get()->prepare("DELETE FROM `prefadmissions`
- WHERE `rule_id`=?");
- $stmt->execute([$this->id]);
- // Delete all associated conditions...
- foreach ($this->conditions as $condition) {
- $condition->delete();
- }
- // ... and their connection to this rule.
- $stmt = DBManager::get()->prepare("DELETE FROM `prefadmission_condition`
- WHERE `rule_id`=?");
- $stmt->execute([$this->id]);
- }
-
- /**
- * Gets all users that are matched by thís rule.
- *
- * @return Array An array containing IDs of users who are matched by
- * this rule.
- */
- public function getAffectedUsers()
- {
- $users = [];
- if ($this->conditions) {
- // Get users from all specified conditions.
- foreach ($this->conditions as $condition) {
- $users = array_unique(array_merge($users, $condition->getUsers()));
- }
- } else {
- $users = array_keys(AdmissionPriority::getPriorities($this->courseset->getId()));
- }
- return $users;
- }
-
- /**
- * Gets all defined conditions.
- *
- * @return Array
- */
- public function getConditions()
- {
- return $this->conditions;
- }
-
- /**
- * Gets some text that describes what this AdmissionRule (or respective
- * subclass) does.
- */
- public static function getDescription()
- {
- return _('Sie können hier festlegen, dass bestimmte Studiengänge, '.
- 'Fachsemester etc. bei der Platzverteilung zu Veranstaltungen '.
- 'bevorzugt behandelt werden sollen.');
- }
-
- /**
- * Returns whether higher semesters of study should be favored.
- *
- * @return bool
- */
- public function getFavorSemester()
- {
- return $this->favorSemester;
- }
-
- /**
- * Return this rule's name.
- */
- public static function getName()
- {
- return _('Bevorzugte Anmeldung');
- }
-
- /**
- * Gets the semesters of study for the given users. If conditions are
- * set and should be considered, only the semesters of study belonging
- * to the given conditions are set.
- *
- * @param $users user IDs to process
- * @param $considerConditions should only the semesters of study belonging
- * to given conditions be considered?
- * @param array $exclude user IDs to exclude
- * @return array Users with their maximal semester of study.
- */
- public function getSemesterGroups($users, $considerConditions, $exclude = [])
- {
- /*
- * Get all selected condition values so that the study semester
- * can be matched against that data; we don't want some "general"
- * value for a user's study semester, but the one that is assigned
- * to a given subject and degree.
- */
- $queryParts = [];
- $values = [$users];
- if ($exclude) {
- $values[] = $exclude;
- }
- if ($considerConditions) {
- foreach ($this->conditions as $condition) {
- $queryPart = "";
- // Search for subject and degree entries.
- foreach ($condition->getFields() as $field) {
- switch (get_class($field)) {
- case 'DegreeCondition':
- if ($queryPart) {
- $queryPart .= " AND ";
- }
- $queryPart .= "`abschluss_id`".$field->getCompareOperator()."?";
- $values[] = $field->getValue() ?: '';
- break;
- case 'SubjectCondition':
- if ($queryPart) {
- $queryPart .= " AND ";
- }
- $queryPart .= "`fach_id`".$field->getCompareOperator()."?";
- $values[] = $field->getValue() ?: '';
- break;
- case 'SemesterOfStudyCondition':
- if ($queryPart) {
- $queryPart .= " AND ";
- }
- $queryPart .= "`semester`".$field->getCompareOperator()."?";
- $values[] = $field->getValue() ?: '';
- break;
- default:
- break;
- }
- }
- if ($queryPart) {
- $queryParts[] = $queryPart;
- }
- }
- }
- // Build SQL query with affected users and selected subjects and degrees.
- $query = "SELECT `user_id`, MAX(`semester`) AS semester
- FROM `user_studiengang`
- WHERE `user_id` IN (?)";
- if ($exclude) {
- $query .= " AND `user_id` NOT IN (?)";
- }
- if ($queryParts) {
- $query .= " AND ((".implode(") OR (", $queryParts)."))";
- }
- $query .= " GROUP BY `user_id` ORDER BY `semester`, `user_id`";
- $groups = [];
- foreach (DBManager::get()->fetchAll($query, $values) as $entry) {
- if (intval($entry['semester'])) {
- $groups[intval($entry['semester'])][] = $entry['user_id'];
- }
- }
- ksort($groups);
- return $groups;
- }
-
- /**
- * Gets the template that provides a configuration GUI for this rule.
- *
- * @return String
- */
- public function getTemplate()
- {
- $factory = new Flexi_TemplateFactory(__DIR__.'/templates/');
- // Now open specific template for this rule and insert base template.
- $tpl = $factory->open('configure');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
- * Helper function for loading data from DB. Generic AdmissionRule data is
- * loaded with the parent load() method.
- */
- public function load()
- {
- // Load basic data.
- $stmt = DBManager::get()->prepare("SELECT *
- FROM `prefadmissions` WHERE `rule_id`=? LIMIT 1");
- $stmt->execute([$this->id]);
- if ($current = $stmt->fetch(PDO::FETCH_ASSOC)) {
- $this->favorSemester = $current['favor_semester'];
- // Retrieve conditions.
- $stmt = DBManager::get()->prepare("SELECT *
- FROM `prefadmission_condition` WHERE `rule_id`=?");
- $stmt->execute([$this->id]);
- $conditions = $stmt->fetchAll(PDO::FETCH_ASSOC);
- foreach ($conditions as $condition) {
- $currentCondition = new UserFilter($condition['condition_id']);
- $this->conditions[$condition['condition_id']] = $currentCondition;
- }
- }
- }
-
- /**
- * Removes the condition with the given ID from the rule.
- *
- * @param String conditionId
- * @return PreferentialAdmission
- */
- public function removeCondition($conditionId)
- {
- $this->conditions[$conditionId]->delete();
- unset($this->conditions[$conditionId]);
- return $this;
- }
-
- /**
- * Admission is open for everyone. On seat distribution, the rule conditions
- * will be used to generate user lists with the specified chance.
- *
- * @param String $userId
- * @param String $courseId
- * @return Array Is the user allowed to register or are there any errors?
- */
- public function ruleApplies($userId, $courseId)
- {
- return [];
- }
-
- /**
- * Uses the given data to fill the object values. This can be used
- * as a generic function for storing data if the concrete rule type
- * isn't known in advance.
- *
- * @param Array $data
- * @return AdmissionRule This object.
- */
- public function setAllData($data)
- {
- UserFilterField::getAvailableFilterFields();
- parent::setAllData($data);
- $this->favorSemester = (bool) $data['favor_semester'];
- $this->conditions = [];
- if ($data['conditions']) {
- foreach ($data['conditions'] as $condition) {
- $this->addCondition(ObjectBuilder::build($condition, 'UserFilter'));
- }
- }
- return $this;
- }
-
- /**
- * New setting for favoring higher semesters of study.
- *
- * @param bool $newFavorSemester
- * @return PreferentialAdmission
- */
- public function setFavorSemester($newFavorSemester) {
- $this->favorSemester = $newFavorSemester;
- return $this;
- }
-
- /**
- * Create user lists and set bonus corresponding to
- * the maximal available semester of study for given users.
- *
- * @param $courseset CourseSet to add user lists to
- * @param $grouped associative array of users in the form
- * <semester> => array(<user_id1>, <user_id2, ...))
- * @param $baseBonus basic bonus to start with, defaults to 0.
- */
- public function setSemesterBonus($courseset, $grouped, $baseBonus = 1)
- {
- // Create user lists from each semester group.
- $bonus = $baseBonus;
- foreach ($grouped as $semester => $members) {
- $userlist = new AdmissionUserList();
- $userlist->setUsers($members);
- $userlist->setFactor($bonus);
- $userlist->store();
- $bonus = $bonus + ($this->bonus_difference + 1);
- $courseset->addUserList($userlist->getId());
- $this->userlists[] = $userlist->getId();
- }
- return $bonus;
- }
-
- /**
- * Helper function for storing data to DB.
- */
- public function store()
- {
- // Store rule data.
- $stmt = DBManager::get()->prepare("INSERT INTO `prefadmissions`
- (`rule_id`, `favor_semester`, `mkdate`, `chdate`)
- VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE
- `favor_semester`=VALUES(`favor_semester`),
- `chdate`=VALUES(`chdate`)");
- $stmt->execute([$this->id, $this->favorSemester, time(), time()]);
- // Delete removed conditions from DB.
- $entries = DBManager::get()->fetchAll("SELECT `condition_id` FROM
- `prefadmission_condition` WHERE `rule_id`=? AND `condition_id` NOT IN (?)",
- [$this->id, array_keys($this->conditions)]);
- foreach ($entries as $entry) {
- $current = new UserFilter($entry['condition_id']);
- $current->delete();
- }
- DBManager::get()->execute("DELETE FROM `prefadmission_condition`
- WHERE `rule_id`=? AND `condition_id` NOT IN (?)", [$this->id, array_keys($this->conditions)]);
- // Store all conditions.
- $queries = [];
- $parameters = [];
- if ($this->conditions) {
- foreach ($this->conditions as $condition) {
- // Store each condition...
- $condition->store();
- $queries[] = "(?, ?, ?)";
- $parameters[] = $this->id;
- $parameters[] = $condition->getId();
- $parameters[] = time();
- }
- // Store all assignments between rule and condition.
- $stmt = DBManager::get()->execute("INSERT INTO `prefadmission_condition`
- (`rule_id`, `condition_id`, `mkdate`)
- VALUES ".implode(",", $queries)." ON DUPLICATE KEY UPDATE
- `condition_id`=VALUES(`condition_id`)", $parameters);
- }
- return $this;
- }
-
- /**
- * A textual description of the current rule.
- *
- * @return String
- */
- public function toString()
- {
- $factory = new Flexi_TemplateFactory(__DIR__.'/templates/');
- $tpl = $factory->open('info');
- $tpl->set_attribute('rule', $this);
- return $tpl->render();
- }
-
- /**
- * Validates if the given request data is sufficient to configure this rule
- * (e.g. if required values are present).
- *
- * @param Array Request data
- * @return Array Error messages.
- */
- public function validate($data)
- {
- $errors = parent::validate($data);
- if (!$data['conditions'] && !$data['favor_semester']) {
- $errors[] = _('Es muss mindestens eine Auswahlbedingung angegeben werden.');
- }
- return $errors;
- }
-
- public function __clone()
- {
- $this->id = md5(uniqid(get_class($this)));
- $this->courseSetId = null;
- $cloned_conditions = [];
- foreach ($this->conditions as $condition) {
- $dolly = clone $condition;
- $cloned_conditions[$dolly->id] = $dolly;
- }
- $this->conditions = $cloned_conditions;
- }
-
-} /* end of class PreferentialAdmission */