Last active
August 29, 2015 14:02
-
-
Save rschiang/9381c39b8aa41d4f44f3 to your computer and use it in GitHub Desktop.
102-2 臺大宿舍抽籤程式,檢驗樣本(Jesda 公司承包)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once APPLICATION_PATH . '/modules/staff/controllers/BallotController.php'; | |
/** | |
* 新生遷出住宿抽籤 | |
* | |
* @author Kim | |
* | |
*/ | |
class Staff_BallotNewMoveController extends Staff_BallotController | |
{ | |
protected $ballotType = BALLOT_NEW_MOVE; | |
protected $ballotName = '大學部新生遷出作業'; | |
protected $applyController = 'move'; | |
public function init() | |
{ | |
$this->setModelName('Staff/Ballot'); | |
parent::init(); | |
$this->setBreadcrumbsAppend('新增大學部新生遷出作業'); | |
$this->setBreadcrumbsList('大學部新生遷出作業'); | |
} | |
/** | |
* 各宿舍空床 | |
* | |
* @var array | |
*/ | |
private $_rooms = null; | |
/** | |
* 依房間空床數及宿舍分配 | |
* | |
* @param unknown $ballotSN | |
* @param unknown $gender | |
*/ | |
protected function initBedGroupByUsableCount($ballotSN, $gender) | |
{ | |
$this->_rooms = array(); | |
// 取得抽籤作業可使用的床位,所有鎖定床位但不包含保留床位 | |
$beds = $this->getModel('Staff/BallotBed')->fetchBedForAllot($ballotSN, 0, $gender); | |
// 隨機排序 | |
shuffle($beds); | |
// 依各宿舍房間分類 | |
foreach ($beds as $bed) { | |
if (! isset($this->_rooms[$bed['dorm_building_sn']])) { | |
$this->_rooms[$bed['dorm_building_sn']] = array(); | |
} | |
if (! isset($this->_rooms[$bed['dorm_building_sn']][$bed['room_id']])) { | |
$this->_rooms[$bed['dorm_building_sn']][$bed['room_id']] = array(); | |
} | |
$this->_rooms[$bed['dorm_building_sn']][$bed['room_id']][$bed['sn']] = $bed; | |
} | |
} | |
/** | |
* 有希望室友申請資料 | |
*/ | |
private $_appliesByReqBedCount = array(); | |
/** | |
* 沒有希望室友 | |
* | |
* @var array | |
*/ | |
private $_appliesSingle = array(); | |
/** | |
* 未申請名單,但須分配 | |
* | |
* @var array | |
*/ | |
private $_notApplies = array(); | |
/** | |
* 希望室友申請名單但不限任何宿舍 | |
* | |
* @var array | |
*/ | |
private $_appliesByReqBedCountForAnyBuilding = array(); | |
/** | |
* 依需要的空床數排序 | |
* | |
* @param integer $ballotSN | |
* @param integer $gender | |
*/ | |
protected function initAppliesByReqBedCount($ballotSN, $gender) | |
{ | |
$this->number = array( | |
0 => 0, | |
1 => 0, | |
2 => 0, | |
3 => 0, | |
4 => 0 | |
); | |
$this->_appliesByReqBedCount = array( | |
4 => array(), | |
3 => array(), | |
2 => array(), | |
1 => array() | |
); | |
$this->_appliesByReqBedCountForAnyBuilding = array( | |
4 => array(), | |
3 => array(), | |
2 => array() | |
); | |
$this->_appliesSingle = array(); | |
$this->_notApplies = array(); | |
// 取得申請名單 | |
$rows = $this->getModel('Staff/BallotApplyMove') | |
->getSelectWithJoinPart() | |
->where('ballot_apply.ballot_sn = ?', $ballotSN) | |
->where('school_roll.gender_key = ?', $gender) | |
->where('ballot_apply.sn NOT IN (SELECT ballot_apply_sn FROM ballot_result WHERE ballot_sn = ?)', $ballotSN) | |
->query() | |
->fetchAll(); | |
foreach ($rows as $row) { | |
$reqBedCount = 1; | |
for ($i = 1; $i <= 3; $i ++) { | |
if (trim($row['roommate_student_id' . $i])) { | |
$reqBedCount ++; | |
} | |
} | |
if ($reqBedCount > 1) { | |
// 有希望室友 | |
$this->_appliesByReqBedCount[$reqBedCount][] = $row; | |
} else { | |
// 沒有希望室友 | |
$this->_appliesSingle[] = $row; | |
} | |
} | |
// 符合資格未申請名單 | |
$this->_notApplies = $this->getModel('Staff/BallotStudent')->fetchNotApplyRows($ballotSN, $gender); | |
} | |
/** | |
* 移除已分配的床位 | |
* | |
* @param array $allotedRcds | |
*/ | |
private function _removeAllotedBeds($allotRcds) | |
{ | |
foreach ($allotRcds as $studentId => $bed) { | |
$this->_removeAllotedBed($bed); | |
} | |
} | |
/** | |
* 移除已分配的床位 | |
* | |
* @param array $allotedRcds | |
*/ | |
private function _removeAllotedBed($bed) | |
{ | |
unset($this->_rooms[$bed['dorm_building_sn']][$bed['room_id']][$bed['sn']]); | |
if (count($this->_rooms[$bed['dorm_building_sn']][$bed['room_id']]) == 0) { | |
unset($this->_rooms[$bed['dorm_building_sn']][$bed['room_id']]); | |
} | |
if (count($this->_rooms[$bed['dorm_building_sn']]) == 0) { | |
unset($this->_rooms[$bed['dorm_building_sn']]); | |
} | |
} | |
/** | |
* 分配床位 | |
*/ | |
public function allot($ballotSN, $gender) | |
{ | |
// 依宿舍空床數 | |
$this->initBedGroupByUsableCount($ballotSN, $gender); | |
// 依需要的空床數排序 | |
$this->initAppliesByReqBedCount($ballotSN, $gender); | |
// 第一階段依志願序及空床數分配 | |
foreach ($this->_appliesByReqBedCount as $reqBedCount => $applies) { | |
shuffle($applies); | |
foreach ($applies as $apply) { | |
// 依宿舍志願序分配 | |
for ($i = 1; $i <= 3; $i ++) { | |
$allotRcds = array(); | |
$dormBuildingSN = $apply['dorm_building_sn' . $i]; | |
if ($dormBuildingSN && isset($this->_rooms[$dormBuildingSN])) { | |
foreach ($this->_rooms[$dormBuildingSN] as $roomId => $beds) { | |
// 有符合需要床位數的空床 | |
if (count($beds) == $reqBedCount) { | |
$j = 0; | |
foreach ($beds as $bed) { | |
if (count($allotRcds) == 0) { | |
$bed['apply_sn'] = $apply['sn']; | |
$allotRcds[$apply['student_id']] = $bed; | |
} elseif (isset($apply['roommate_student_id' . $j]) && $apply['roommate_student_id' . $j]) { | |
$bed['apply_sn'] = $apply['sn']; | |
$allotRcds[$apply['roommate_student_id' . $j]] = $bed; | |
} | |
$j ++; | |
} | |
break; | |
} | |
} | |
if (count($allotRcds)) { | |
break; | |
} | |
} else { | |
break; | |
} | |
} | |
if (count($allotRcds)) { | |
// 清除已分配床位 | |
$this->_removeAllotedBeds($allotRcds); | |
// 加入分配名單 | |
$this->saveResult($ballotSN, $allotRcds); | |
} else { | |
if ($reqBedCount > 1) { | |
// 加入第二階段名單不分宿舍分配 | |
$this->_appliesByReqBedCountForAnyBuilding[$reqBedCount][] = $apply; | |
} else { | |
// 加入個人單獨分配 | |
$this->_appliesSingle[] = array( | |
'sn' => $apply['sn'], | |
'student_id' => $apply['student_id'] | |
); | |
for ($i = 1; $i <= 3; $i ++) { | |
if ($apply['roommate_student_id' . $i]) { | |
$this->_appliesSingle[] = array( | |
'sn' => $apply['sn'], | |
'student_id' => $apply['roommate_student_id' . $i] | |
); | |
} | |
} | |
} | |
} | |
} | |
} | |
// 第二階段同寢名單不分宿舍分配 | |
foreach ($this->_appliesByReqBedCountForAnyBuilding as $reqBedCount => $applies) { | |
foreach ($applies as $apply) { | |
$allotRcds = array(); | |
foreach ($this->_rooms as $roomsByBuilding) { | |
foreach ($roomsByBuilding as $roomId => $beds) { | |
// 有符合需要床位數的空床 | |
if (count($beds) == $reqBedCount) { | |
$j = 0; | |
foreach ($beds as $bed) { | |
if (count($allotRcds) == 0) { | |
$bed['apply_sn'] = $apply['sn']; | |
$allotRcds[$apply['student_id']] = $bed; | |
} elseif (isset($apply['roommate_student_id' . $j]) && $apply['roommate_student_id' . $j]) { | |
$bed['apply_sn'] = $apply['sn']; | |
$allotRcds[$apply['roommate_student_id' . $j]] = $bed; | |
} | |
$j ++; | |
} | |
break; | |
} | |
} | |
if (count($allotRcds)) | |
break; | |
} | |
if (count($allotRcds)) { | |
// 清除已分配床位 | |
$this->_removeAllotedBeds($allotRcds); | |
// 加入分配名單 | |
$this->saveResult($ballotSN, $allotRcds); | |
} else { | |
// 加入個人單獨分配 | |
$this->_appliesSingle[] = array( | |
'sn' => $apply['sn'], | |
'student_id' => $apply['student_id'] | |
); | |
for ($i = 1; $i <= 3; $i ++) { | |
if ($apply['roommate_student_id' . $i]) { | |
$this->_appliesSingle[] = array( | |
'sn' => $apply['sn'], | |
'student_id' => $apply['roommate_student_id' . $i] | |
); | |
} | |
} | |
} | |
} | |
} | |
// 隨機打亂名單 | |
shuffle($this->_appliesSingle); | |
// 依個人單人分配單人床位 | |
foreach ($this->_appliesSingle as $apply) { | |
if (count($this->_rooms)) { | |
// 尚有床位 | |
$allotedBed = null; | |
foreach ($this->_rooms as $roomsByBuilding) { | |
foreach ($roomsByBuilding as $beds) { | |
foreach ($beds as $bed) { | |
$allotedBed = $bed; | |
break; | |
} | |
if ($allotedBed) | |
break; | |
} | |
if ($allotedBed) | |
break; | |
} | |
if ($allotedBed) { | |
// 加入分配結果 | |
$allotedBed['apply_sn'] = $apply['sn']; | |
$this->saveResult($ballotSN, array( | |
$apply['student_id'] => $allotedBed | |
)); | |
// 移除已分配床位 | |
$this->_removeAllotedBed($allotedBed); | |
} | |
} else { | |
// 加入候補 | |
$this->saveWaiting($ballotSN, $apply['sn'], $apply['student_id']); | |
} | |
} | |
// 隨機打亂名單 | |
shuffle($this->_notApplies); | |
// 分配未申請名單 | |
foreach ($this->_notApplies as $student) { | |
if (count($this->_rooms)) { | |
// 尚有床位 | |
$allotedBed = null; | |
foreach ($this->_rooms as $roomsByBuilding) { | |
foreach ($roomsByBuilding as $beds) { | |
foreach ($beds as $bed) { | |
$allotedBed = $bed; | |
break; | |
} | |
if ($allotedBed) | |
break; | |
} | |
if ($allotedBed) | |
break; | |
} | |
if ($allotedBed) { | |
// 加入分配結果 | |
$allotedBed['apply_sn'] = 0; | |
$this->saveResult($ballotSN, array( | |
$student['student_id'] => $allotedBed | |
)); | |
// 清除已分配床位 | |
$this->_removeAllotedBed($allotedBed); | |
} | |
} else { | |
// 加入候補 | |
$this->saveWaiting($ballotSN, 0, $student['student_id']); | |
} | |
} | |
} | |
/** | |
* 儲存分配結果 | |
* | |
* @param integer $ballotSN | |
* @param array $allotRcds | |
*/ | |
protected function saveResult($ballotSN, $allotRcds) | |
{ | |
$reqCount = count($allotRcds); | |
$user = Jesda_Auth::getStaticUser(ROLE_EMPLOYEE); | |
foreach ($allotRcds as $studentId => $bed) { | |
$dormStudent = $this->getModel('Staff/DormStudent')->fetchByStudentId($studentId); | |
if (! $dormStudent) { | |
throw new Exception(sprintf('沒有遷出學生[%s]的目前住宿資料', $studentId)); | |
} | |
$this->number[$reqCount] ++; | |
$data = array( | |
'ballot_sn' => $ballotSN, | |
'ballot_apply_sn' => $bed['apply_sn'], | |
'dorm_bed_sn' => $bed['sn'], | |
'allot_user_sn' => $user['sn'], | |
'allot_time' => date('Y-m-d H:i:s'), | |
'number' => $this->number[$reqCount], | |
'allot_type_key' => ALLOT_BALLOT, | |
'move_dorm_student_sn' => $dormStudent['sn'] | |
); | |
$this->getModel('Staff/BallotResult')->insert($data); | |
} | |
} | |
/** | |
* 加入後補名單 | |
* | |
* @param unknown $ballotSN | |
* @param unknown $applySN | |
* @param unknown $studentId | |
*/ | |
protected function saveWaiting($ballotSN, $applySN, $studentId) | |
{ | |
$this->number[0] ++; | |
$user = Jesda_Auth::getStaticUser(ROLE_EMPLOYEE); | |
$dormStudent = $this->getModel('Staff/DormStudent')->fetchByStudentId($studentId); | |
if (! $dormStudent) { | |
throw new Exception(sprintf('沒有遷出學生[%s]的目前住宿資料', $studentId)); | |
} | |
$data = array( | |
'ballot_sn' => $ballotSN, | |
'ballot_apply_sn' => $applySN, | |
'dorm_bed_sn' => 0, | |
'allot_user_sn' => $user['sn'], | |
'allot_time' => date('Y-m-d H:i:s'), | |
'number' => $this->number[0], | |
'allot_type_key' => ALLOT_BALLOT_WAITING, | |
'move_dorm_student_sn' => $dormStudent['sn'] | |
); | |
$this->getModel('Staff/BallotResult')->insert($data); | |
} | |
/** | |
* 分配床位頁面 | |
*/ | |
public function allotAction() | |
{ | |
$view = $this->view; | |
$view->ballotSN = $this->getParam('ballot_sn'); | |
} | |
/** | |
* 開始分配 | |
*/ | |
public function allotAjaxAction() | |
{ | |
set_time_limit(0); | |
try { | |
$ballot = $this->getModel('Staff/Ballot')->fetchRow('sn = ' . $this->getParam('ballot_sn')); | |
$this->getModel('Staff/BallotResult')->delete('ballot_sn = ' . $ballot['sn']); | |
$this->allot($ballot['sn'], 0); | |
$this->allot($ballot['sn'], 1); | |
$ballot->ballot_rule_sn = 1; | |
$ballot->save(); | |
echo 'OK'; | |
} catch (Exception $e) { | |
echo $e->getMessage(); | |
} | |
exit(); | |
} | |
/** | |
* 清除分配內容 | |
*/ | |
public function clearAction() | |
{ | |
$ballot = $this->getModel('Staff/Ballot')->fetchRow('sn = ' . $this->getParam('ballot_sn')); | |
$this->getModel('Staff/BallotResult')->delete('ballot_sn = ' . $ballot['sn']); | |
$ballot->ballot_rule_sn = 0; | |
$ballot->save(); | |
$this->_helper->redirector->gotoSimple('allot', null, null, array( | |
'ballot_sn' => $ballot['sn'] | |
)); | |
} | |
public function resultAction() | |
{ | |
$this->view->ballotSN = $this->getParam('ballot_sn'); | |
$ballot = $this->getModel('Staff/Ballot')->fetchRowByPrimary($this->getParam('ballot_sn')); | |
$this->view->ballot = $ballot; | |
// 分配名單 | |
$rows = $this->getModel('Staff/BallotResultMove') | |
->getSelectWithJoinPart() | |
->where('ballot_result.ballot_sn = ?', $this->getParam('ballot_sn')) | |
->order(array( | |
'ds.gender_key', | |
'number' | |
)) | |
->query() | |
->fetchAll(); | |
$waiting = array( | |
0 => array(), | |
1 => array() | |
); | |
$groupByRoom = array( | |
0 => array(), | |
1 => array() | |
); | |
$moveDormStudentSns = array(); | |
foreach ($rows as $row) { | |
$moveDormStudentSns[] = $row['move_dorm_student_sn']; | |
if ($row['dorm_bed_sn'] == 0) { | |
$waiting[$row['gender_key']][] = $row; | |
continue; | |
} | |
if (! isset($groupByRoom[$row['gender_key']][$row['allot_building_sn']])) { | |
$groupByRoom[$row['gender_key']][$row['allot_building_sn']] = array(); | |
} | |
if (! isset($groupByRoom[$row['gender_key']][$row['allot_building_sn']][$row['allot_room_id']])) { | |
$groupByRoom[$row['gender_key']][$row['allot_building_sn']][$row['allot_room_id']] = array(); | |
} | |
if (! isset($groupByRoom[$row['gender_key']][$row['allot_building_sn']][$row['allot_room_id']][$row['ballot_apply_sn']])) { | |
$groupByRoom[$row['gender_key']][$row['allot_building_sn']][$row['allot_room_id']][$row['ballot_apply_sn']] = array(); | |
} | |
$groupByRoom[$row['gender_key']][$row['allot_building_sn']][$row['allot_room_id']][$row['ballot_apply_sn']][] = $row; | |
} | |
$this->view->groupByRoom = $groupByRoom; | |
$this->view->waiting = $waiting; | |
// 取得新生宿舍未分配名單 | |
$this->view->notAllotStudents = $this->getModel('Staff/DormStudent')->fetchNewStudentNotMoveout($moveDormStudentSns); | |
// 取得排除名單 | |
$exclude = array(); | |
$rows = $this->getModel('Staff/BallotStudentExclude') | |
->getSelectWithJoinPart() | |
->where('ballot_sn = ' . $ballot['sn']) | |
->query() | |
->fetchAll(); | |
foreach ($rows as $row) { | |
$exclude[] = $row['sn']; | |
} | |
$this->view->exclude = $exclude; | |
$this->initSideBarForList($this->getParam('ballot_sn'), 'allot'); | |
} | |
protected $ballot; | |
/** | |
* | |
* @return the | |
* $ballot | |
*/ | |
public function getBallot($sn = null) | |
{ | |
if (! $this->ballot) { | |
$this->ballot = $this->getModel('Staff/Ballot')->getSingleton($this->getParam('ballot_sn')); | |
} | |
return $this->ballot; | |
} | |
/** | |
* 設定左側選單 | |
*/ | |
protected function initSideBarForList($ballotSN, $active) | |
{ | |
$this->setEnableBreadcrumbsTab(false); | |
$this->initSideBarForForm($ballotSN, $active); | |
$this->setScriptLeftNavbar('ballot/form-nav.phtml'); | |
$tab = $this->getHelper('tab'); | |
$item = $tab->getItem('staff-ballot.new.move-edit'); | |
if ($item) { | |
$item->setUrl($_SERVER['REQUEST_URI']); | |
$tab->save(); | |
} | |
} | |
public function initSideBarForForm($ballotSN, $active) | |
{ | |
$view = $this->view; | |
// 取得抽籤作業 | |
$ballot = $this->getBallot($ballotSN); | |
if ($ballot) { | |
$view->ballot = $ballot; | |
} | |
$view->active = $active; | |
} | |
/** | |
* 刪除分配結果 | |
*/ | |
public function removeResultAjaxAction() | |
{ | |
try { | |
$this->getModel('Staff/BallotResult')->delete('sn = ' . $this->getParam('sn')); | |
echo 'OK'; | |
} catch (Exception $e) { | |
echo $e->getMessage(); | |
} | |
exit(); | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment