医院排班程序

前言:

    这个前后做了几个月

 

    


目录

  •      需求说明
  •      代码架构

一   需求说明

       1.1 班次类型

      

工作日班次
医生夜班连留
一线医生
二线医生 

 

周五班次(夜班算周末夜班)
医生夜班连留
一线医生
二线医生 

                                               

 

 

                                            

周末班次
医生白班夜班
一线医生
二线医生

 

 

                              

会诊
医生会诊
一线医生
一线医生

 

 

  1.2  员工信息表(该表格需要手动填写,自己申报)

        

  1.3   排班日期表(第一列需要手动更新)

 

排班规则

   夜班: 

     不能超过最大夜班数量

      夜班不能连续上

     夜班当天不会诊,不连留

    调休日不夜班

 

     会诊

         不能超过最大会诊数量

         当天不夜班

         休息日不会诊

       连留

               休息日不连留

                不能超过最大数量

                  当天不夜班

      周末白班

                   当天不调休

                     不能跟夜班冲突

                    不能超过最大夜班数量

 

 

二  代码实现:

# -*- coding: utf-8 -*-
"""
Created on Mon May 25 13:40:20 2020

@author: chengxf2
V2: 2020/06/29
增加规则
  1: 当前夜班,前两天都不能是夜班
  2: 会诊人员可能是一线人员,不能跟连留,夜班 冲突
  3:  每次加载表格的时候,清空一下表格的内容,防止上一次残留
  
v3: 2020/7/23
  1: 休息日白班不能连续排班
  2: 在排班结果没有确定下来之前不再写表格,I/O 读取的时间耗时
  3: 运用墨菲定律,迭代次数为30000次,总排序有3千万
       连续迭代100次,
  4: 周五班属于周末班次,但是要排会诊连留
  5  某些人上固定班次
  6: 会诊一线二线医生都有
       
"""


import os
from openpyxl import load_workbook
import numpy as np
from datetime import datetime
from enum import Enum


class DoctorKind(Enum):
    
    LineOne = 0 #一线医生
    LineSecond = 1 #二线医生

class Night_Type(Enum):
    
    WorkingDay = 0
    Weekend = 1

class CheckType(Enum):
    Stay = 0  #连留
    Diagnosis =1 #会诊
    

class Week(Enum):
      WorkingDay = 0 #工作日
      Weekend =1 #周末
      Friday = 2 #周末

class AppointedDay(Enum):
    ONE_DAY =   0 #一线白班
    ONE_NIGHT = 2 #一线夜班
    TWO_DAY =   4 #二线白班
    TWO_NIGHT = 6 #二线夜班
    
class Result(Enum):
    Success = 0 # "排班成功"
    Error =  100
    Failure_ONE_Stay = 102 #"一线连留失败"
    Failure_ONE_Night = 104 #"一线夜班失败"
    Failure_ONE_Working = 106 #工作日班次失败
    Failure_ONE_Weekend = 108 #周末班次失败
    Failure_ONE_Friday = 110 #夜班失败
    Failure_ONE_WeekendDay = 112 #"一线周末白班失败"
    Failure_ONE_WeekendNight = 114 #"一线周末夜班失败"
    Failure_ONE_Fixed_Stay = 116 #"一线连留失败"
    Failure_ONE_Fixed_Night = 118 #"一线夜班失败"
    Failure_ONE_Fixed_WeekendDay = 120 #"一线周末白班失败"
    Failure_ONE_Fixed_WeekendNight = 122 #"一线周末夜班失败"
    Failure_TWO_Working = 200  #二线工作日
    Failure_TWO_WeekEnd = 202 #二线夜班
    Failure_TWO_Friday = 204 #二线周五
    Failure_TWO_Night = 206 #"二线夜班失败"
    Failure_TWO_WeekendDay = 208  # "二线周末白班失败"
    Failure_TWO_WeekendNight = 210 # "二线夜班失败"
    Failure_Fixed_Dianosisi = 212 #"会诊失败"
    Failure_TWO_Fixed_Night = 214 #"二线夜班失败"
    Failure_TWO_Fixed_WeekendDay = 216  # "二线周末白班失败"
    Failure_TWO_Fixed_WeekendNight = 218 # "二线夜班失败"
    Failure_Dianosisi = 300 #"会诊失败"
    

"""
excel开头的代表从表里读; count 代表当前已经排出来的情况
workNight: 工作日夜班总数
restDay: 休息日白班总数
restNight: 休息日夜班总数
stay: 连留总数
diagnosis: 会诊总数
noDiagnosis: 会诊里外日
noWork: 调休;不上班
row: 行号
column: 列号

"""
class Doctor:
    def __init__(self,workNight, restDay, restNight, stay, diagnosis, noDiagnosis, noWork,listdayPer,listnightPer):
        self.excelWorkNight = workNight; #工作日夜班,一线二线医生都有
        self.countWorkNight = 0 ;#计数工作日夜班数量
        self.excelRest = restDay ; #休息日白班,从表读出
        self.countRest = 0; #计数休息日白班
        self.excelRestNight = restNight #休息日夜班,从表读出
        self.countRestNight = 0 #计数休息日夜班数量
        self.excelStay = stay; #连留,一线医生
        self.countStay = 0 #计算连留总数
        self.excelDiagnosis = diagnosis ; #会诊;二线医生
        self.countDiagnosis = 0 #计数会诊总数
        self.excelnoDiagnosis  = noDiagnosis; #会诊例外日,这个时间段不能会诊
        self.excelNoWork = noWork #调休日期
        self.indexNight = []  #上夜班的时序
        self.indexDay =[] #休息日白班的时序   
        self.indexStay =[]  #连留的时序
        self.indexNightPermanent = listnightPer #上固定的夜班
        self.indexDayPermanent = listdayPer #固定的休息日白班
        self.column = -1 #列号
        self.columnDay = -1# 二线白班的列号
        self.columnNight = -1 #二线夜班的列号
        self.columnDiagnosis = -1 #会诊的列号
        
        

#################排班主程序##############################

class Arrange :
    
    """
    变量初始化
    """
    def __init__(self):
        
        self.pathStaff = "" #员工表格路径
        self.pathDay =   "" #排班表格路径
        self.ResultOne = True # 一线班排的结果
        self.ResultTwo= True # 二线班排的结果
        self.Resultdiagnosis = False # 会诊班排列结果
        self.maxIter = 1 #10000*20 #最多排次班,墨菲定律,如果概率是1/一千万,找到该可能是80%  
        self.nameStaff = "staff.xlsx" #该表格是员工信息
        self.nameDay =   "day.xlsx" #该表格是一个月班次
        self.HeadTwo =["二线白班","二线夜班","会诊"] #二线人员要上的班种类
        self.Head = [] #表头
        self.dictFixed ={} #指定班次
        self.dictOne ={} #一线人员词典
        self.dictTwo ={} #二线人员词典
        self.listOne =[] #一线人员名字列表
        self.listTwo =[] # 二线人员名字列表
        self.listDay = []# a[0] 工作日,休息日, a[1] 行号
        self.listDiagnosis =[] #一线二线人员都可以是会诊人员[name,type]
  
        

      
    """
    初始化改变过的变量
    Args
      None
    return
      None
    """
    def InitPara(self,DictInfo):
        
       # print("\n ***************重新初始化***************\n")
       
        for name in DictInfo.keys():
            
              #print("\n name ",name)
         
              doctor = DictInfo[name] ##value
              
              doctor.countWorkNight = 0 #工作日夜班
              doctor.countRest  = 0  #休息日白班
              doctor.countRestNight  = 0 #休息日夜班数量
              doctor.countStay = 0 #连留上限
              doctor.countDiagnosis = 0 #会诊上限
              doctor.indexNight = [] #夜班时续联
              doctor.indexDay = [] #白班时序
              doctor.indexStay =[] #休息日白班的时序   

              DictInfo[name] = doctor
    
    """
    清除排班表内容
    Args
       maxRow 最大行
       maxCol 最大列
    return
       None
    """
    def ClearExcel(self):
        
         wb = load_workbook(self.pathDay)
         sheet = wb["1"]
         maxRow = sheet.max_row  #员工数
         maxCol = sheet.max_column #天数
         
         for i in range(1,maxRow+1):
             for j in range(3,maxCol+1):
                 sheet.cell(row =i, column = j).value = ""
        
         wb.save(self.pathDay)
         wb.close()
                 
                 
             
             
          
    """
    字符串转为列表
    Args
       str
    return
       listStr
    """
    def ConvertStr(self, strInfo):
        
        listInfo =[]
        
        if strInfo =="0":
            return listInfo
        
        if isinstance(strInfo, str):
                listInfo = strInfo.split("/")
                listInfo = list(map(int, listInfo))
        
        return listInfo
        
    
    """
        配置人员班次:
        1: 一线班人员
        2: 二线班人员
        Args
            filePath: Excel 表格
         return
            None
    """
    def GetInfo(self):
        

        self.numOne = 0 #一线线医生
        self.numTwo = 0 #二线医生
        wbStaff = load_workbook(self.pathStaff)
        wbDay = load_workbook(self.pathDay)
        sheetStaff = wbStaff["1"]
        sheetDay = wbDay["1"]
        numStaff = sheetStaff.max_row  #员工数
        numDay =   sheetDay.max_row  #本月情况
  
        
        
        print("\n num",numStaff, "\n path: ",self.pathStaff)
        ###########一个月的班次情况##################
        
        weekendNum = 0
        workingNum = 0
        FridayNum = 0
        for index in range(2, numDay+1):
            cate = sheetDay.cell(row=index, column=1).value #类型 0: 工作日,1: 周末  2: 周五
            day =Week(cate)
            self.listDay.append([day,index])
            if day is Week.Weekend :
                weekendNum += 1
            elif day is Week.Friday:
                FridayNum  +=1
            else:
                workingNum +=1

   
        print("\n 工作日 ",workingNum,"\t 周五: ",FridayNum,"\t 周末 ",weekendNum)
        ################获取人员信息,从第二行开始排###################
        for i in range(2,numStaff+1): 
            
            name = sheetStaff.cell(row=i, column=1).value #姓名
            staffType = sheetStaff.cell(row=i, column=2).value #一线二线
            workNight = sheetStaff.cell(row=i, column=3).value  #工作日夜班
            restDay = sheetStaff.cell(row=i, column=4).value  #休息日白班
            restNight = sheetStaff.cell(row=i, column=5).value  #休息日夜班
            stay = sheetStaff.cell(row=i, column=6).value  #连留
            diagnosis = sheetStaff.cell(row=i, column=7).value  #会诊
            strNoDiagnosis = sheetStaff.cell(row=i, column=8).value  #会诊例外日
            strNoWork = sheetStaff.cell(row=i, column=9).value  #休息日
            strDayPer = sheetStaff.cell(row=i, column=10).value  #固定白班
            strNightPer = sheetStaff.cell(row=i, column=11).value  #固定夜班
            
            kind = DoctorKind(staffType)
            if int(diagnosis)>=1: #有会诊
                
                diagItem =[name,kind]
                self.listDiagnosis.append(diagItem)
               # print("\n name ",name,"\t diagnosis: ",diagnosis,"\t  jobType: ",jobType)
            
            listNoDiagnosis = []
            listNoWork =  []
            listnightPer =[] #固定伤的夜班
            listdayPer =[] #固定上的白班
            listNoDiagnosis = self.ConvertStr(strNoDiagnosis) #会诊例外日
            listNoWork = self.ConvertStr(strNoWork) #调休日
            listdayPer = self.ConvertStr(strDayPer) #固定白班日期
            listnightPer = self.ConvertStr(strNightPer) #固定夜班日期
            
            dtr = Doctor(workNight,restDay, restNight,stay,diagnosis, listNoDiagnosis,listNoWork,listdayPer,listnightPer)
            
            #print("\n name: ",name,"\t listNoWork: ",listNoWork)
            
            if kind is DoctorKind.LineOne:  #一线人员
                self.dictOne[name]= dtr
                self.listOne.append(name)
                self.numOne +=1
                #print("\t name ",name)
            
            else: # 二线人员 
                self.dictTwo[name] = dtr
                self.listTwo.append(name)
                self.numTwo +=1

        self.Head.extend(self.listOne) #表头
        self.Head.extend(self.HeadTwo) #表头
    """
    GetDesDays 获得对应固定上班的日期
    Args
       doctor: 医生词典
       kind: 一线,二线医生
    return
       rowRet
    """    
    def GetDesDays(self, dictDoctor,kind):
        
        rowRet =[]
        for name in  dictDoctor.keys():
           
            doctor = dictDoctor[name]
            listNight = doctor.indexNightPermanent #上固定的夜班
            listDay =  doctor.indexDayPermanent #固定的休息日白班
            
            ###固定白班###
            if len(listDay)>0: #固定白班[日期,指定班次类型,名字]
                for row  in listDay:
                   if row<1:
                        continue
                   
                   if kind is DoctorKind.LineOne: ##一线医生
                       item = [row, AppointedDay.ONE_DAY, name]
                      
                   else: #二线医生
                       item = [row, AppointedDay.TWO_DAY, name]
                   
                   rowRet.append(item)
            ###固定夜班###      
            if len(listNight)>0: #固定夜班[日期,指定班次类型,名字]
                if row<1:
                        continue
                for row  in listNight:
                   if kind is DoctorKind.LineOne: ##一线医生
                       item = [row, AppointedDay.ONE_NIGHT, name]
                      
                   else:
                       item = [row, AppointedDay.TWO_NIGHT, name]
                   rowRet.append(item)
        return rowRet
                
            
    """
    获得列表
    Args
      item: 原来列表
      day:  工作日|周五|休息日
      name: 姓名
      Job: 工作类型
    return
      [0,0,0,0,0,0,0,0]
      #一线白班标志位
      #name
    """    
    def  ConfigItem(self,  item, day, name):
       
     
          
           
       arg0 = item[0] #一线白班标志位
       arg1 = item[1] #白班名字
       arg2 = item[2] #一线夜班标志位
       arg3 = item[3] #一线夜班名字  
       arg4 = item[4] #二线白班标志位
       arg5 = item[5]#二线白班名字
       arg6 = item[6] #二线夜班标志位
       arg7 = item[7]#二线夜班名字
           
       if day  is AppointedDay.ONE_DAY:
           arg0 = True
           arg1 = name
        
       elif day is  AppointedDay.ONE_NIGHT:
           arg2 = True
           arg3 = name
           #print("\n 一线夜班",name)
       elif day is  AppointedDay.TWO_DAY:
           arg4 = True
           arg5 = name
          # print("\n 二线白班",name)
       elif day is AppointedDay.TWO_NIGHT:
           arg6 = True
           arg7 = name
       else:
           print("==============ErrorItem==========")
          # print("\n 二线夜班",name)
       item = [arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7,-1]
       return item
       
    """
    获得指定班次
    Args
       None
    return
       self.listDay1: 已经有人上了固定的班
       self.listDay2: 无人上固定的班次
    """  
    def GetDesignated(self):
    
        rowMerge =[] 
        row1 = self.GetDesDays(self.dictOne,DoctorKind.LineOne)
        row2 = self.GetDesDays(self.dictTwo,DoctorKind.LineSecond)
        if len(row1)>1:
            rowMerge.extend(row1) 
        if len(row2)>1:
            rowMerge.extend(row2)

        #[index,SPECDay.Night.value, name,cate]
        for item in rowMerge:
            row = item[0] #日期
            day = item[1] #白班|夜班、
            name =item[2] #姓名
            
            retItem =[] 
            if row not in self.dictFixed:
                curItem =  [False,None,False,None,False,None,False,None,-1] #[一线白班,name,一线夜班.name, "二线白班",name, "二线夜班",name,Day]
              
            else:
                curItem = self.dictFixed[row]
            retItem = self.ConfigItem(curItem, day,name)
            self.dictFixed[row] = retItem
            
            
                

        
    """
    获得正常班次
    Arg
       None
    return 
       None
    """    
    def GetNormal(self):
        
        dayAppoint = self.dictFixed.keys()
        self.listNorml =[]
        
        for item in self.listDay:
            day = item[0]  #工作日/周五/休息日
            row = item[1] #当前行号
            if row not in dayAppoint:
                self.listNorml.append(item)
            else:
                itemFixed = self.dictFixed[row]
                itemFixed[-1]= day
                self.dictFixed[row]=itemFixed


      

       
        
    """
    更新一线,二线人员的情况
    写表头
    Args
       None
    return
       None
    """
    def ExcelInit(self):

        day_wb = load_workbook(self.pathDay)
        sheet= day_wb["1"]
        
        indexColumn= 3#[节假日,日期,一线人员]
        m = len(self.listOne) #一线人员的个数
        columnDay = indexColumn+m #二线人员休息日白班列
        columnNight = columnDay+1 #二线夜班列
        columnDiagnosis = columnNight+1#会诊列
        
        for name in self.listOne:
            
            doctor = self.dictOne[name]
            doctor.column = indexColumn #所在列
            doctor.columnDiagnosis = columnDiagnosis#会诊所在列
            indexColumn = indexColumn+1
            self.dictOne[name] = doctor
            

        for name in self.listTwo:

            doctor = self.dictTwo[name]
            doctor.columnDay = columnDay # 二线白班的列号
            doctor.columnNight = columnNight #二线夜班的列号
            doctor.columnDiagnosis = columnDiagnosis#会诊列号
            self.dictTwo[name] = doctor
            
        
        ##写表格头####
        col =3
        for name in self.Head:
            sheet.cell(row =1, column = col).value = name
            col = col+1

        day_wb.save(self.pathDay)
        day_wb.close()
      
    """
    初始化
        
        读取day.xlsx,staff.xlsx,
        写表格头day.xlsx
    Args
       retCode
    return
       retCode
    """
    def MainInit(self):
        
        #获得文件路径
        self.GetFile()
        #清空表格
        self.ClearExcel()
        #获得一线,二线人员情况
        self.GetInfo()
        
        #写表头,以及配置一线二线人员信息
        self.ExcelInit()
        
        #获得指定班次
        self.GetDesignated()
        
        #获得正常班次
        self.GetNormal()
        
       
        print("\n **********配置信息读取完毕**************\n")
    
    """
````获取Excel表格路径
````Args
        retCode
    return 
        self.pathDay:    排班表格
        self.pathStaff:  员工表格
````"""
    def GetFile(self):
    
        self.pathStaff = os.path.abspath(self.nameStaff)
        self.pathDay =  os.path.abspath(self.nameDay)
     
        if not os.path.exists(self.pathStaff):
            print("\n 员工信息表格不存在 ")
        
        if not os.path.exists(self.pathDay):
            print("\n 排班日记表格不存在")
        
            
   
            
    
    """
    Args
       one: 一线人员名单
       Two: 二线人员名单
    return
       retCode
    """
    def Debug(self,dictDoctor):
        
        #,"\t 列: ",doctor.column,":  二綫白班列 ",doctor.columnDay,"  二綫夜班列: ",doctor.columnNight,":  診斷列 :",doctor.columnDiagnosis
        for name in dictDoctor.keys():
            doctor =dictDoctor[name]
            print("\n  Name: ",name,"\t 周末白班: ",doctor.excelRest, ":  实际 ",doctor.countRest)
            """
            print("\n 夜班: ",doctor.excelWorkNight, ":  实际 ",doctor.countWorkNight,
                  "\t 周末白班: ",doctor.excelRest, ":  实际 ",doctor.countRest,
                  "\t 周末夜班: ",doctor.excelRestNight , ":  实际 ",doctor.countRestNight,
                  "\t 连留: ",doctor.excelStay, ":  实际 ",doctor.countStay,
                  "\t 会诊: ",doctor.excelDiagnosis, ":  实际 ",doctor.countDiagnosis
                  )

           """
           #print("\n 二线 ",name, "\t 夜班:  ",workNightCount,"\t 会诊: ",gcCount,"\t 休息白班 ",restDay,"\t 休息夜班 ",restNight)
    
    """
    检查夜班条件:
          
           不能超过最大夜班数量
           前一天不能夜班
           前两天不能夜班
           当天不调休
    Args
       cate: Night_Type
       index: 当前天序号
       Doctor: 医生情况
    return
       False: 不满足
       True:  满足
    """
    def CheckNight(self, cate, index, doctor):
        
        
        if cate is Night_Type.WorkingDay: #工作日
            cond1 = (doctor.countWorkNight < doctor.excelWorkNight)#不超過 最大夜班数量
        else:
            cond1 = (doctor.countRestNight< doctor.excelRestNight) 
            
        if False == cond1:
           return False
            
        cond2 = ((index-1) not in doctor.indexNight)# 前一天不夜班
        if False == cond2:
            return False
        
        cond3 = ((index-2) not in doctor.indexNight) #前兩天不夜班
        if False == cond3:
            return False
        
        cond4 =  (index not in doctor.excelNoWork )  #调休日不夜班
        if  False ==cond4:
            return False
        
        return True
    

    """
    周末白班
        cond1: 不超过最大班次
        cond2: 前一天不夜班
        cond3: 当天没调休
        cond4: 前一天白班
    Args
       index: 当天班次
       doctor: 医生情况
    return
       False: 不满足
       True: 满足
    """
    def CheckWeekendDay(self, index, doctor):
        
    
        cond1 = (doctor.countRest < doctor.excelRest) #不超过范围
        if False == cond1:
            return False

        cond2 = (index-1 not in doctor.indexNight) and (index not in doctor.indexNight) #当天,前一天不夜班
        if False == cond2:
           return False             
      
        cond3 =  (index not in doctor.excelNoWork)  #当前不休息
        if False == cond3:
            return False
        
        cond4 = ((index-1) not in doctor.indexDay) #白班也不能连续上,要不然上十四天班了
        if False == cond4:
            return False
        
        return True
   
   
    """
    檢查会诊或者连留

           不超过最大数量
           当天不夜班
           前一天不夜班
           当天不休息
    Args
       kind: 0 连留 1会诊
       
       index: 当天班次
       doctor: 医生情况
    return
       False: 不满足
       True: 满足
    """
    def CheckStayDiag(self, kind, index, doctor):
        
   
        ####一线连留####
        if kind is CheckType.Stay:
            cond1 = (doctor.countStay < doctor.excelStay)  #连留在当天排班的时候已经过滤过夜班名单了
        else:
            cond1 = (doctor.countDiagnosis< doctor.excelDiagnosis) and (index not in doctor.indexNight)  #不超过会诊上限,以及当天不夜班
                    
            
        if False == cond1:
            return False
        
        
        
        cond2 = (index-1 not in doctor.indexNight)   #前一天,当天不夜班
        if False == cond2:
           return False             
      
        cond3 =  (index not in doctor.excelNoWork)  #当前不休息
        if False == cond3:
            return False
        
        return True
    
    
     

    
    """
    排正常日期的班次
    Args
       retCode
    return
       Row[row,col,value] #排班表
    """        
    def SchedulingNormal(self):
        
        result = Result.Success
        rows =[]
        retCode =""

        
        for item in self.listNorml: #行号
            day = item[0] #日期
            index = item[1] #行号
            
            if day is Week.WorkingDay: ####排工作日######
                #一线人员
                result, columnNight,columnStay = self.GetOneWorking(index, False, None)
                if result  is  Result.Success:
                    rows.append([index,columnNight,"夜"])
                    rows.append([index,columnStay,"连留"])
                else:
                    return Result.Failure_ONE_Working,retCode
                    
                #二线人员
                result, columnNight,nightName = self.GetSecondWorking(index,False,None)
                if result  is  Result.Success:
                    rows.append([index,columnNight,nightName])
                else:
                    return Result.Failure_TWO_Working,retCode
                    
                #会诊人员
                result,columnDiagnosis,diagNosisName = self.GetDiagnosis(index)
                if result  is  Result.Success:
                    rows.append([index,columnDiagnosis,diagNosisName])
                else:
                    return Result.Failure_Dianosisi,None
                
                    
            elif  day is Week.Weekend: #排周末########
                #一线人员
                result, columnNight,columnDay,nameNight,nameDay = self.GetOneWeekend(index,False, None, False, None)
                if result  is  Result.Success:
                    rows.append([index,columnDay,"白"])
                    rows.append([index,nameNight,"夜"])
                else:
                    return Result.Failure_ONE_WeekendDay,retCode
                    
                #二线人员
                result, columnNight,columnDay,nameNight,nameDay = self.GetSecondWeekend(index,False,None,False,None)
                if result  is  Result.Success:
                    rows.append([index,columnDay,nameDay])
                    rows.append([index,columnNight,nameNight])
                else:
                    return Result.Failure_TWO_WeekEnd,retCode
             
                
            else: ##############排周五班次########################
                #先一线
                result, columnNight,columnStay = self.GetOneFriday(index, False, None)
                if result  is  Result.Success:
                    rows.append([index,columnNight,"夜"])
                    rows.append([index,columnStay,"连留"])
                else:
                    return result,retCode
                
                    
                #二线
                result, columnNight,nightName = self.GetSecondFriday(index,False,None)
                if result  is  Result.Success:
                    rows.append([index,columnNight,nightName])
                else:
                    return Result.Failure_TWO_Friday,retCode
                    
                #会诊人员
                result,columnDiagnosis,diagNosisName = self.GetDiagnosis(index)
                if result  is not Result.Success:
                    rows.append([index,columnDiagnosis,diagNosisName])
                else:
                    return Result.Failure_Dianosisi,retCode
                   # print("\n 周五","\t  : ",day,"\t  ",index)
        
        return Result.Success,rows
                

    """
    排二线线工作日班次
       工作日夜班
    Args:
        index: 当前天的序列号
        isNight 夜班是否有固定人员上了
        nightName: 名字
    return
        result: 是否查着成功
        columnNight: 夜班列号
        nameNight: 夜班人员名单

      
    """
    def GetSecondWorking(self,index,isNight,nightName):
        result = False
        columnNight = -1
        nameNight =""


         #####先夜班####
        listNight = [] #夜班人员
 
        if True == isNight:
            nameNight = nightName
        else:
            
            for name in self.listTwo: ##二线线人员名单
                doctor = self.dictTwo[name]  #当前信息
                result = self.CheckNight(Night_Type.WorkingDay,index, doctor) #檢查夜班
                
                if True == result:
                    listNight.append(name)
                else:
                    continue

            if len(listNight)>0:
                np.random.shuffle(listNight)
                nameNight = listNight[0] 
            else:  #直接退出了,找不到
                 return Result.Failure_TWO_Fixed_Night, columnNight,nameNight
         
            
       
        self.dictTwo[nameNight].countWorkNight  = self.dictTwo[nameNight].countWorkNight +1
        self.dictTwo[nameNight].indexNight.append(index)
        columnNight = self.dictTwo[nameNight].columnNight

        return Result.Success, columnNight,nameNight
    
    """
    排二线周末班次
        夜班
        白班
    Args:
        index: 当前天的序列号
    return
        find: 是否查着成功
        columnNight: 夜班列号
        columnDay: 白班
    """
    def GetSecondWeekend(self,index,isDay,dayName,isNight,nightName):
        
        
        
        columnNight = -1
        columnDay =-1
        nameNight =""
        nameDay =""
        listNight = [] #夜班人员
        listDay =[]  #白班
        

         #####先夜班####
        
        if   isNight is True:#夜班有人上了
            nameNight = nightName
        else:
            for name in self.listTwo: ##二线线人员名单
                doctor = self.dictTwo[name]  #当前信息
                cond = self.CheckNight(Night_Type.Weekend,index, doctor) #檢查夜班
                if cond:
                    listNight.append(name)
                else:
                    continue
            if len(listNight)>0:
                np.random.shuffle(listNight)
                nameNight = listNight[0] 
            else:  #直接退出了
                return Result.Failure_TWO_WeekendNight, columnNight,columnDay,nameNight,nameDay
         
            
        ######再排白班 #######
        if isDay is True:
            nameDay = dayName
        else:
            for name in self.listTwo:
                if name == nameNight:
                    continue
                doctor = self.dictTwo[name]
                cond =self.CheckWeekendDay(index,doctor)
                if True == cond:
                    listDay.append(name)
                else:
                    continue
                    
            if len(listDay)>0:     
                np.random.shuffle(listDay)
                nameDay = listDay[0]
            else: #没有办法排班了
                return Result.Failure_TWO_WeekendDay, columnNight,columnDay,nameNight,nameDay

       
        self.dictTwo[nameNight].countRestNight  = self.dictTwo[nameNight].countRestNight +1
        self.dictTwo[nameNight].indexNight.append(index)
        self.dictTwo[nameDay].countRest = self.dictTwo[nameDay].countRest+1
        self.dictTwo[nameDay].indexDay.append(index)
        columnNight = self.dictTwo[nameNight].columnNight
        columnDay = self.dictTwo[nameDay].columnDay 
        
        return Result.Success, columnNight,columnDay,nameNight,nameDay
    
    """
    排二线周五班次
        夜班:算周五班次
    Args:
        index: 当前天的序列号
    return
        find: 是否查着成功
        columnNight: 夜班列号
        columnDay: 白班
    """
    def GetSecondFriday(self,index,isNight,nightName):   
        
        result = False
        columnNight = -1
        nameNight =""
        listNight = [] #夜班人员
 
        if True == isNight:
            nameNight = nightName
        else:

            for name in self.listTwo: ##二线线人员名单
                doctor = self.dictTwo[name]  #当前信息
                result = self.CheckNight(Night_Type.Weekend,index, doctor) #檢查夜班
                if True == result:
                    listNight.append(name)
                else:
                    continue

            if len(listNight)>0:
                np.random.shuffle(listNight)
                nameNight = listNight[0] 
            else:  #直接退出了,找不到
                 return Result.Failure_TWO_Fixed_Night, columnNight,nameNight
         
            
       
        self.dictTwo[nameNight].countRestNight  = self.dictTwo[nameNight].countRestNight +1
        self.dictTwo[nameNight].indexNight.append(index)
        columnNight = self.dictTwo[nameNight].columnNight

        return Result.Success, columnNight,nameNight
        
   
    
    """
    排一线周五班
        夜班: 算周末班次
        连留: 一线连留
    Args:
        index: 当前天的序列号
        isNight: 夜班是否
        nightName: 夜班名字
    return
        find: 是否查着成功
        columnNight: 夜班列号
        columnDay: 白班
    """
    def GetOneFriday(self,index,isNight,nightName):
        result = False
        columnNight = -1
        columnStay =-1
        listNight = [] #夜班人员
        listStay =[]  #连留人员
        
        
        
         #####先夜班####
        
        if True == isNight: #是否已经有固定人上了
            nameNight = nightName
        else:
            
            for name in self.listOne: ##一线人员名单
                doctor = self.dictOne[name]  #当前信息
                result = self.CheckNight(Night_Type.Weekend,index, doctor) #檢查夜班
                if True == result:
                    listNight.append(name)
                else:
                    continue

            if len(listNight)>0: #可选人员列表
                np.random.shuffle(listNight)
                nameNight = listNight[0] 
            else:  #直接退出
                return Result.Failure_ONE_Fixed_WeekendNight, columnNight,columnStay
         
            
        ######再排连留 #######
        for name in self.listOne:
            if name == nameNight:
                continue
            doctor = self.dictOne[name]
            result =self.CheckStayDiag(CheckType.Stay,index,doctor)
          
                    
            if True == result:
                listStay.append(name)
            else:
                continue
                
        if len(listStay)>0:     
            np.random.shuffle(listStay)
            nameStay = listStay[0]
        else: #没有办法排班了
            return Result.Failure_ONE_Fixed_Stay, columnNight,columnStay

        
        self.dictOne[nameNight].countRestNight  = self.dictOne[nameNight].countRestNight +1 #工作日夜班
        self.dictOne[nameNight].indexNight.append(index) #夜班时序
        self.dictOne[nameStay].countStay = self.dictOne[nameStay].countStay+1
        self.dictOne[nameStay].indexStay.append(index) #连留时序
        columnNight = self.dictOne[nameNight].column
        columnStay = self.dictOne[nameStay].column

        return Result.Success, columnNight,columnStay
        
      
    
    
    """
    排会诊班次
    Args:
        index: 当前天的序列号
    return
        Result: 结果
        columnDiagnosis: 会诊列号
        nameDiagnosis: 会诊人员名字
    """
    def GetDiagnosis(self,index):
        
        listDiagnosis =[]
        columnDiagnosis = -1
        retName = ""
        
          ######再排连留 ####### diagItem =[name,diagnosis,staffType]
        for item  in self.listDiagnosis:
            
            name = item[0]
            kind = item[1]
            if kind is DoctorKind.LineOne: #一线医生
                doctor = self.dictOne[name]
            else:
                doctor = self.dictTwo[name]
                
            result =self.CheckStayDiag(CheckType.Diagnosis,index,doctor)
   
            if True == result:
                listDiagnosis.append(name)
            else:
                continue
                
        if len(listDiagnosis)>0:     
            np.random.shuffle(listDiagnosis)
            retName = listDiagnosis[0]
        else: #没有办法排班了
            return Result.Failure_Fixed_Dianosisi, columnDiagnosis,retName

        if retName in self.listOne:
            self.dictOne[retName].countDiagnosis  = self.dictOne[retName].countDiagnosis +1 #会诊
            columnDiagnosis = self.dictOne[retName].columnDiagnosis
        else:
            self.dictTwo[retName].countDiagnosis  = self.dictTwo[retName].countDiagnosis +1 #会诊
            columnDiagnosis = self.dictTwo[retName].columnDiagnosis
            
        
        return Result.Success, columnDiagnosis,retName

    
    """
    排一线工作日班次
       工作日夜班
       工作日连留
    Args:
        index: 当前天的序列号
        isNight: 夜班已经有人上了
        nightName: 夜班人员名字
    return
        result: 是否查着成功
        columnNight: 夜班列号
        columnDay: 白班
    """
    def GetOneWorking(self,index,isNight,nightName):
        
        result = False
        columnNight = -1
        columnStay =-1
        listNight = [] #夜班人员
        listStay =[]  #连留人员
        
        
        
         #####先夜班####
        
        if True == isNight: #是否已经有固定人上了
            nameNight = nightName
        else:
            
            for name in self.listOne: ##一线人员名单
                doctor = self.dictOne[name]  #当前信息
                result = self.CheckNight(Night_Type.WorkingDay,index, doctor) #檢查夜班
                if True == result:
                    listNight.append(name)
                else:
                    continue

            if len(listNight)>0: #可选人员列表
                np.random.shuffle(listNight)
                nameNight = listNight[0] 
            else:  #直接退出
                return Result.Failure_ONE_Fixed_Night, columnNight,columnStay
         
            
        ######再排连留 #######
        for name in self.listOne:
            if name == nameNight:
                continue
            doctor = self.dictOne[name]
            result =self.CheckStayDiag(CheckType.Stay,index,doctor)
            if True == result:
                listStay.append(name)
            else:
                continue
                
        if len(listStay)>0:     
            np.random.shuffle(listStay)
            nameStay = listStay[0]
        else: #没有办法排班了
            return Result.Failure_ONE_Fixed_Stay, columnNight,columnStay

        
        self.dictOne[nameNight].countWorkNight  = self.dictOne[nameNight].countWorkNight +1 #工作日夜班
        self.dictOne[nameNight].indexNight.append(index) #夜班时序
        self.dictOne[nameStay].countStay = self.dictOne[nameStay].countStay+1
        self.dictOne[nameStay].indexStay.append(index) #连留时序
        columnNight = self.dictOne[nameNight].column
        columnStay = self.dictOne[nameStay].column

        return Result.Success, columnNight,columnStay
        
    """
    排一线班次
       白班
       夜班
    Args:
        index: 当前天的序列号
        isDay:白班是否有人上了
        dayName 白班
        isNight 夜班是否有人上了
        nightName 夜班名字
    return
        find: 是否查着成功
        columnNight: 夜班列号
        columnStay: 连留列号
      
    """
    def GetOneWeekend(self,index,isDay,dayName,isNight,nightName):
        
        
        columnNight = -1
        columnDay =-1
        nameNight =""
        nameDay =""
        listNight = [] #夜班人员
        listDay =[]  #白班

         #####先夜班####
        if   isNight is True:#夜班有人上了
            nameNight = nightName
        else:
            for name in self.listOne: ##二线线人员名单
                doctor = self.dictOne[name]  #当前信息
                cond = self.CheckNight(Night_Type.Weekend,index, doctor) #檢查夜班
                if cond:
                    listNight.append(name)
                else:
                    continue
            if len(listNight)>0:
                np.random.shuffle(listNight)
                nameNight = listNight[0] 
            else:  #直接退出了
                return Result.Failure_ONE_WeekendNight, columnNight,columnDay,nameNight,nameDay
         
            
        ######再排白班 #######
        if isDay is True:
            nameDay = dayName
        else:
            for name in self.listOne:
                if name == nameNight:
                    continue
                doctor = self.dictOne[name]
                cond =self.CheckWeekendDay(index,doctor)
                if True == cond:
                    listDay.append(name)
                else:
                    continue
                    
            if len(listDay)>0:     
                np.random.shuffle(listDay)
                nameDay = listDay[0]
            else: #没有办法排班了
                return Result.Failure_ONE_WeekendDay, columnNight,columnDay,nameNight,nameDay

       
        self.dictOne[nameNight].countRestNight  = self.dictOne[nameNight].countRestNight +1
        self.dictOne[nameNight].indexNight.append(index)
        self.dictOne[nameDay].countRest = self.dictOne[nameDay].countRest+1
        self.dictOne[nameDay].indexDay.append(index)
        columnNight = self.dictOne[nameNight].columnNight
        columnDay = self.dictOne[nameDay].columnDay 
        
        return Result.Success, columnNight,columnDay,nameNight,nameDay
    
    
    """
    排固定日期的班次
    Args
       None: 这些天,已经有人上指定的班次了
    return
       Row[row,col,value] #排班表
    """        
    def SchedulingFixed(self):
        
        result = Result.Success
        rows =[]
        retCode =""
        
        keys =self.dictFixed.keys()
        
        if len(keys)<1:
            return Result.Success,retCode
        for index in keys: #行号
            item = self.dictFixed[index]
            isDayOne = item[0] #一线白班
            dayNameOne = item[1] #name 
            isNightOne = item[2] #一线夜班
            nightNameOne = item[3] #name 
            isDaySecond = item[4] #二线白班
            dayNameSecond = item[5] #name
            isNightSecond = item[6] #二线夜班
            nightNameSecond = item[7] #name
            day = item[8]#day
            #print("一线白班 ",arg0,":",arg1,"    一线夜班: ",arg2,": ",arg3,"\t 二线白班 ",arg4,": ",arg5,"    二线夜班 ",arg6,": ",arg7)
            
            if day is Week.WorkingDay: ####排工作日######
                #一线人员
                result, columnNight,columnStay = self.GetOneWorking(index, isNightOne, nightNameOne)
                if result  is  Result.Success:
                    rows.append([index,columnNight,"夜"])
                    rows.append([index,columnStay,"连留"])
                else:
                    return Result.Failure_ONE_Working,retCode
                    
                #二线人员
                result, columnNight,nightName = self.GetSecondWorking(index,isNightSecond,nightNameSecond)
                if result  is  Result.Success:
                    rows.append([index,columnNight,nightName])
                else:
                    return Result.Failure_TWO_Working,retCode
                    
                    
                #会诊人员
                result,columnDiagnosis,diagNosisName = self.GetDiagnosis(index)
                if result  is  Result.Success:
                    rows.append([index,columnDiagnosis,diagNosisName])
                else:
                    return Result.Failure_Dianosisi,retCode
                    
            elif  day is Week.Weekend: #排周末########
                #一线人员
                result, columnNight,columnDay,nameNight,nameDay = self.GetOneWeekend(index,isDayOne, dayNameOne, isNightOne, nightNameOne)
                if result  is  Result.Success:
                    rows.append([index,columnDay,"白"])
                    rows.append([index,nameNight,"夜"])
                else:
                    return Result.Failure_ONE_Fixed_WeekendDay,retCode
                    
                #二线人员
                result, columnNight,columnDay,nameNight,nameDay = self.GetSecondWeekend(index,isDaySecond,dayNameSecond,isNightSecond,nightNameSecond)
                if result  is  Result.Success:
                    rows.append([index,columnDay,nameDay])
                    rows.append([index,columnNight,nameNight])
                else:
                    return Result.Failure_TWO_Fixed_WeekendDay,retCode
                
            else: ##############排周五班次########################
                ###先一线####
                result, columnNight,columnStay = self.GetOneFriday(index, isNightOne, nightNameOne)
                if result  is not Result.Success:
                    return Result.Error,retCode
                else:
                    rows.append([index,columnNight,"夜"])
                    rows.append([index,columnStay,"连留"])
                    
                #二线
                result, columnNight,nightName = self.GetSecondFriday(index,isNightSecond,nightNameSecond)
                if result  is not Result.Success:
                    return Result.Failure_TWO_Friday,retCode
                else:
                    rows.append([index,columnNight,nightName])
                    
                #会诊人员
                result,columnDiagnosis,diagNosisName = self.GetDiagnosis(index)
                if result  is not Result.Success:
                    return Result.Failure_Dianosisi,retCode
                else:
                    rows.append([index,columnDiagnosis,diagNosisName])

        return Result.Success,rows
        

    """
    排班
    Args
       None
    return
       result
    """
    
    """
    保存内容
    Args
       rows: 要保存的内容
    return
       None
    """
    def SaveExcel(self, rows):
         wb = load_workbook(self.pathDay)
         sheet = wb["1"]
         
         for item in rows:
             rowIndex = item[0]
             columnIndex = item[1]
             value = item[2]
             sheet.cell(row =rowIndex, column = columnIndex).value = value
         
         wb.save(self.pathDay)
         
    """
    排班
    Args
      None
    return
      写表格
    """
    def   Scheduling(self):
        
         result = Result.Success
         rows =[]
         retCode =""

         #先排固定班次
         result,rowFixed = self.SchedulingFixed()
         #print("\n result",result,"\t rows " ,rowFixed)
         
         if result is  Result.Success:
             rows.append(rowFixed)
         else:
             return result,retCode
         
            
         result, rowsNormal = self.SchedulingNormal()
         if result is  Result.Success:
             rows.append(rowsNormal)
         else:
             return result,retCode

         return Result.Success,rows
    
    """
    排班
    Args
      None
    return
      写表格
    """
    def Run(self):
        
        self.MainInit() #参数初始化#FailCause.cause300.value
        print("\n  ==========排班开始==========:")
      
        for i in range(self.maxIter):
          
             result,rows =  self.Scheduling()
             
             #print("\n result ",result)
             
             if result is Result.Success:
                 self.SaveExcel(rows)
                 print("\n 排班成功了")
                 break
             else:
                 self.InitPara(self.dictOne)
                 self.InitPara(self.dictTwo)
                 
             
             
             #print("\n result ",result)
        print("\n  ==========排班结束==========:",i)
            
        
 
ag =Arrange()     
ag.Run()   

   

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值