php - 请帮忙优化排班流程
伊谢尔伦
伊谢尔伦 2017-04-11 10:27:09
0
1
831

需求:公司每天下午会抽取4名员工,广州2名,上海2名

注意:员工若当天请假了,需要重新抽取1名员工出来

期待:公平的算法,保证每个员工值班次数在每一轮都近乎相同,并且值班间隔天数也差不多

附上自己的程序:

<?php
/**
 * 排班算法
 *
 * @param array  $date     日期范围
 * @param int    $dayDutys 排班人数
 * @param string $city     城市
 * @param boolean $isRound 是否循环轮次排班
 * @return false|array
 */
function schedule(array $date, $dayDutys = 4, $city = null, $isRound = false)
{
    // 值班数据 @todo 有一个值班表了,这边临时用数组代替
    $dutys = array();

    // 所有员工 @todo 有一个员工表了,这边临时用数组代替
    $employees = array(
        array('account' => 'a', 'city' => '上海'),
        array('account' => 'b', 'city' => '广州'),
        array('account' => 'c', 'city' => '上海'),
        array('account' => 'd', 'city' => '上海'),
        array('account' => 'e', 'city' => '上海'),
        array('account' => 'f', 'city' => '上海'),
        array('account' => 'g', 'city' => '广州'),
        array('account' => 'h', 'city' => '上海'),
        array('account' => 'i', 'city' => '广州'),
        array('account' => 'j', 'city' => '广州'),
        array('account' => 'k', 'city' => '广州'),
        array('account' => 'l', 'city' => '上海')
    );

    // 打乱数组
    shuffle($employees);

    $gzNum = 0;
    $shNum = 0;
    $num = 0;
    $today = 0;
    foreach ($employees as $employee) {

        // 无办公地点,过滤
        if (!$employee['city']) {
            continue;
        }

        // 超过最大日期,跳出循环
        $nowDate = clone($date[0]);
        if ($nowDate->modify($today . ' day') > $date[1]) {
            break;
        }

        // 达到当天值班人数峰值,计数清零
        if ($num % $dayDutys == 0) {
            $gzNum = 0;
            $shNum = 0;
        }

        // 达到当天办公地点值班人数峰值,过滤
        if ((($gzNum == $dayDutys / 2 && $employee['city'] == '广州') || ($shNum == $dayDutys / 2 && $employee['city'] == '上海')) && $dayDutys >= 2) {
            continue;
        }

        // 当日已排班,过滤
        if ($dutys['account'] == $employee['account'] && $dutys['date'] == array($nowDate, $nowDate)) {
            continue;
        }

        // 本轮未轮完、当月已排班,过滤
        if (!$isRound && $dutys['account'] == $employee['account'] && $dutys['date'] == array(new DateTime(date('Y-m-01')), new DateTime(date('Y-m-01') . '1 month'))) {
            continue;
        }

        // 新增值班员工记录
        $dutys[] = $employee;

        $num ++;
        $num % $dayDutys ? $today : $today ++;
        $employee['city'] == '广州' ? $gzNum ++ : $shNum ++;
    }

    // 本轮已轮完,进入下一轮
    if ($num % $dayDutys != 0) {
        $this->schedule($date, $dayDutys, $city, true);
    }

    if (!$num) {
        return false;
    }

    return $dutys;
}

希望大神们给予优化或分享,感谢!

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

reply all(1)
大家讲道理

这个不是算不算法
你建个表就可以了
要不然 你怎么知道昨天哪些人已经安排了呢
每天都在变你不可能提前知道一个时段有没有人请假 请假多少人

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!