搜尋

首頁  >  問答  >  主體

php - 请帮忙优化排班流程

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

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

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

附上自己的程序:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

<code><?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;

}

</code>

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

伊谢尔伦伊谢尔伦2908 天前930

全部回覆(1)我來回復

  • 大家讲道理

    大家讲道理2017-04-11 10:29:09

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

    回覆
    0
  • 取消回覆