2020年2月15日土曜日

夜勤新人月が終わったら

夜勤新人月が終わった後、また来年も使うかもしれませんので、メンテナンスしておきましょう。

実は、訓練期間が、下のようにブランクだと、右ペインに示されるようにエラーになってしまいます。
原因は、行制約で訓練期間では、2回夜勤を行うという制約をハード制約として記述したからです。
単純にソフト制約とすれば回避できますが、ソフトエラーとしてカウントされるのが面白くない、という方もおられでしょう。それが今日のテーマです。


訓練期間が定義されていないときは、制約そのものをDisableしてしまえばよい、という発想が浮かびます。下の最後の方、 夜勤新人Disable()が制約をDisableする記述です。僅か3行で済みます。

スタッフプロパティで夜勤新人を設定、上で期間設定を行う、ということをマニュアルに書いておけば、来年もまた使えます。

import sc3

def 夜勤回数設定sub(person):
    st=staffdef[person]+'夜勤回数を制約'
    sc3.print(st+'します。\n')
    max=-1
    min=0
    if person in 夜勤回数最大属性:
        max=夜勤回数最大属性[person]
    if person in 夜勤回数最小属性:
        min=夜勤回数最小属性[person]

    sc3.print(str(max)+str(min)+'\n')
    vlist=[]
    for day in 今月:
        v=sc3.GetShiftVar(person,day,'入り')
        vlist.append(v)
    sc3.AddSoft(sc3.SeqError(min,max,3,vlist),st,5)

def 夜勤回数設定():
    for person in 夜勤あり:
        夜勤回数設定sub(person)
   


def 公休数設定():
    for person in 全スタッフ:
        max=-1
        min=0
        if person not in 公休数属性最大:
            continue
        st=staffdef[person]+'公休数を制約'
        sc3.print(st+'します。\n')
        if person in 公休数属性最大:
                max=公休数属性最大[person]#float
        if person in 公休数属性最小:
                min=公休数属性最小[person]
        max *=2
        min *=2
        if isinstance(max, float) and not max.is_integer():
            sc3.print('公休数設定で、maxが整数型ではありません。')
            continue
        if isinstance(min, float) and not min.is_integer():
            sc3.print('公休数設定で、minが整数型ではありません。')
            continue
        max =int(max) #float to int
        min =int(min) #float to int
        sc3.print(str(max)+str(min)+'\n')
        vlist=[]
        for day in 今月:
            v=sc3.GetShiftVar(person,day,'公休')#公休は2回分カウント
            vlist.append(v)
            vlist.append(v)
            v=sc3.GetShiftVar(person,day,'早半休')#早半休は1回
            vlist.append(v)
            v=sc3.GetShiftVar(person,day,'半休')#半休は1回
            vlist.append(v)
        sc3.AddSoft(sc3.SeqError(min,max,4,vlist),st,6)

def 土曜以外の半休抑制():
    for person in 全スタッフ:
        for day in 土曜でない今月:
            ts=shift_schedules[person][day][0]
            if ts !='半休':
                v=sc3.GetShiftVar(person,day,'半休')
                st=staffdef[person]+'土曜以外の半休抑制'
                sc3.AddSoft(~v,st,1)

def 夜勤新人Disable():
    if len(夜勤新人訓練期間)==0:
        sc3.ConstraintEnable('夜勤新人.夜勤新人は、夜勤訓練期間に2回訓練を行う',False)


夜勤回数設定()
公休数設定()
土曜以外の半休抑制()
夜勤新人Disable()
 
夜勤新人訓練期間がなくても意図通り動作しました。
 
期間を日月火水木にした例です。
 

0 件のコメント:

コメントを投稿