| お客さまの要求仕様は以下です。 金土、夜勤を行った者は公休1日取得 | 
| 土日、夜勤を行った者は公休2日取得 | 
| 日月、夜勤を行った者は公休1日取得 | 
| 祭日、夜勤を行った者は公休なし | 
| 土日祭日、日勤を行った者は公休なし | 
| 公休取得は、夜勤を行った日の前後3日以内 | 
ここでいう公休は、代休といった方がイメージが合うかもしれません。
で、実装を考えました。
| 制約開始日 | ~ | 水 | 木 | 金 | 土 | 日 | 月 | 火 | 水 | ~ | 制約終了日 | |||
| 代休禁止 | 代休カウント期間 | 入り | 明け | 代休カウント期間 | 代休数1 | 代休禁止 | ||||||||
| 代休カウント期間 | 入り | 明け | 代休カウント期間 | 代級数2 | ||||||||||
| 代休カウント期間 | 入り | 明け | 代休カウント期間 | 代級数1 | ||||||||||
| 夜勤カウント期間 | ||||||||||||||
SeqCompで、「夜勤カウント期間における夜勤カウントと代休期間における代休カウントが等しい」
と制約すればよいことが分かります。
なお、3日間は、前が水木金、後が月火水固定、ただし、前月や次月に跨ることは不可、という仕様です。
実装は、下のPythonソースです。2週連続夜勤が発生すると誤動作するのでGUIで7日以内の夜勤連続を禁止しています。また、別に、制約開始日付近と制約終了日付近で、夜勤カウント区間がないときは、代休を禁止する処理も行っています。
def 土日夜勤した場合前後3日間で公休を取る():
    for day in 祝でない今月土:
        if day > 制約開始日:#Always True
            dstart=day-3
            holiday_domain=[]
            sat_sun=[]
            for i in range(8):#前3日 土日 後3日 Total8days
                if dstart+i <制約開始日 or dstart+i>制約終了日:
                    continue
                if dstart+i =day+2:#後ならば
                    if dstart+i in 休診日:
                        continue
                    holiday_domain.append(dstart+i)
            #必要な期間を得たので夜勤可能者について制約する
            
            for person in 夜勤可能:
                
                vsat_sun=[]
                vholidays=[]
                for day in sat_sun:
                    sc3.print('土'+str(day)+'\n')
                    v1=sc3.GetShiftVar(person,day,'入り')#
                    v2=sc3.GetShiftVar(person,day,'明け')
                    vsat_sun.append(v1|v2)
                for day in holiday_domain:
                    sc3.print('H'+str(day))
                    v1=sc3.GetShiftVar(person,day,'公休')#
                    vholidays.append(v1)
                s=staffdef[person]+daydef[day]+'代休処理'
                sc3.AddSoft(sc3.SeqComp(vsat_sun,vholidays),s,7)
 
 
0 件のコメント:
コメントを投稿