Skip to content

Instantly share code, notes, and snippets.

@rschiang
Last active August 29, 2015 14:02
Show Gist options
  • Save rschiang/9381c39b8aa41d4f44f3 to your computer and use it in GitHub Desktop.
Save rschiang/9381c39b8aa41d4f44f3 to your computer and use it in GitHub Desktop.
102-2 臺大宿舍抽籤程式,檢驗樣本(Jesda 公司承包)
<?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