|
|
""" |
|
|
Constants module for Supply Roster Optimization Tool |
|
|
Replaces hard-coded magic numbers with meaningful named constants |
|
|
""" |
|
|
from src.preprocess import extract |
|
|
|
|
|
class ShiftType: |
|
|
""" |
|
|
Shift type constants to replace magic numbers |
|
|
1 = Regular, 2 = Evening, 3 = Overtime |
|
|
""" |
|
|
REGULAR = 1 |
|
|
EVENING = 2 |
|
|
OVERTIME = 3 |
|
|
|
|
|
|
|
|
ALL_SHIFTS = [REGULAR, EVENING, OVERTIME] |
|
|
|
|
|
|
|
|
REGULAR_AND_OVERTIME = [REGULAR, OVERTIME] |
|
|
|
|
|
@classmethod |
|
|
def get_name(cls, shift_id): |
|
|
"""Get human-readable name for shift ID""" |
|
|
names = { |
|
|
cls.REGULAR: "Regular", |
|
|
cls.EVENING: "Evening", |
|
|
cls.OVERTIME: "Overtime" |
|
|
} |
|
|
return names.get(shift_id, "Unknown") |
|
|
|
|
|
@classmethod |
|
|
def get_all_names(cls): |
|
|
"""Get dictionary mapping shift IDs to names""" |
|
|
return { |
|
|
cls.REGULAR: "Regular", |
|
|
cls.EVENING: "Evening", |
|
|
cls.OVERTIME: "Overtime" |
|
|
} |
|
|
|
|
|
class LineType: |
|
|
""" |
|
|
Line type constants to replace magic numbers |
|
|
6 = Long Line, 7 = Mini Load |
|
|
""" |
|
|
LONG_LINE = 6 |
|
|
MINI_LOAD = 7 |
|
|
|
|
|
|
|
|
ALL_LINE_TYPES = [LONG_LINE, MINI_LOAD] |
|
|
|
|
|
@classmethod |
|
|
def get_name(cls, line_id): |
|
|
"""Get human-readable name for line type ID""" |
|
|
names = { |
|
|
cls.LONG_LINE: "Long Line", |
|
|
cls.MINI_LOAD: "Mini Load" |
|
|
} |
|
|
return names.get(line_id, "Unknown") |
|
|
|
|
|
@classmethod |
|
|
def get_all_names(cls): |
|
|
"""Get dictionary mapping line type IDs to names""" |
|
|
return { |
|
|
cls.LONG_LINE: "Long Line", |
|
|
cls.MINI_LOAD: "Mini Load" |
|
|
} |
|
|
|
|
|
class KitLevel: |
|
|
""" |
|
|
Kit hierarchy level constants |
|
|
0 = Prepack, 1 = Subkit, 2 = Master |
|
|
""" |
|
|
PREPACK = 0 |
|
|
SUBKIT = 1 |
|
|
MASTER = 2 |
|
|
|
|
|
|
|
|
ALL_LEVELS = [PREPACK, SUBKIT, MASTER] |
|
|
|
|
|
@classmethod |
|
|
def get_name(cls, level_id): |
|
|
"""Get human-readable name for kit level ID""" |
|
|
names = { |
|
|
cls.PREPACK: "prepack", |
|
|
cls.SUBKIT: "subkit", |
|
|
cls.MASTER: "master" |
|
|
} |
|
|
return names.get(level_id, "unknown") |
|
|
|
|
|
@classmethod |
|
|
def get_all_names(cls): |
|
|
"""Get dictionary mapping level IDs to names""" |
|
|
return { |
|
|
cls.PREPACK: "prepack", |
|
|
cls.SUBKIT: "subkit", |
|
|
cls.MASTER: "master" |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PaymentMode: |
|
|
""" |
|
|
Payment mode constants |
|
|
""" |
|
|
BULK = "bulk" |
|
|
PARTIAL = "partial" |
|
|
|
|
|
@classmethod |
|
|
def get_all_modes(cls): |
|
|
"""Get all available payment modes""" |
|
|
return [cls.BULK, cls.PARTIAL] |
|
|
|
|
|
|
|
|
class DefaultConfig: |
|
|
"""Default configuration values using constants""" |
|
|
|
|
|
|
|
|
PAYMENT_MODE_CONFIG = { |
|
|
ShiftType.REGULAR: PaymentMode.BULK, |
|
|
ShiftType.EVENING: PaymentMode.BULK, |
|
|
ShiftType.OVERTIME: PaymentMode.PARTIAL |
|
|
} |
|
|
|
|
|
|
|
|
MAX_HOUR_PER_SHIFT_PER_PERSON = { |
|
|
ShiftType.REGULAR: 7.5, |
|
|
ShiftType.EVENING: 7.5, |
|
|
ShiftType.OVERTIME: 5 |
|
|
} |
|
|
|
|
|
|
|
|
MAX_PARALLEL_WORKERS = { |
|
|
LineType.LONG_LINE: 15, |
|
|
LineType.MINI_LOAD: 15 |
|
|
} |
|
|
|
|
|
|
|
|
FIXED_MIN_UNICEF_PER_DAY = 2 |
|
|
|
|
|
|
|
|
LINE_COUNT_LONG_LINE = 3 |
|
|
LINE_COUNT_MINI_LOAD = 2 |
|
|
|
|
|
|
|
|
MAX_PARALLEL_WORKERS_LONG_LINE = 7 |
|
|
MAX_PARALLEL_WORKERS_MINI_LOAD = 5 |
|
|
|
|
|
|
|
|
DEFAULT_COST_RATES = { |
|
|
"UNICEF Fixed term": { |
|
|
ShiftType.REGULAR: 43.27, |
|
|
ShiftType.EVENING: 43.27, |
|
|
ShiftType.OVERTIME: 64.91 |
|
|
}, |
|
|
"Humanizer": { |
|
|
ShiftType.REGULAR: 27.94, |
|
|
ShiftType.EVENING: 27.94, |
|
|
ShiftType.OVERTIME: 41.91 |
|
|
} |
|
|
} |
|
|
|
|
|
EMPLOYEE_TYPE_LIST =extract.read_employee_data()["employment_type"].unique().tolist() |
|
|
SHIFT_LIST = extract.get_shift_info()["id"].unique().tolist() |
|
|
EVENING_SHIFT_MODE = "normal" |
|
|
EVENING_SHIFT_DEMAND_THRESHOLD = 0.9 |
|
|
|
|
|
|
|
|
SCHEDULE_TYPE = "weekly" |
|
|
|
|
|
|
|
|
FIXED_STAFF_MODE = "priority" |
|
|
|
|
|
|
|
|
UNICEF_RATE_SHIFT_1 = 12.5 |
|
|
UNICEF_RATE_SHIFT_2 = 15.0 |
|
|
UNICEF_RATE_SHIFT_3 = 18.75 |
|
|
HUMANIZER_RATE_SHIFT_1 = 10.0 |
|
|
HUMANIZER_RATE_SHIFT_2 = 12.0 |
|
|
HUMANIZER_RATE_SHIFT_3 = 15.0 |
|
|
LINE_LIST = extract.read_packaging_line_data()["id"].unique().tolist() |
|
|
LINE_CNT_PER_TYPE = extract.read_packaging_line_data().set_index("id")["line_count"].to_dict() |
|
|
|
|
|
|
|
|
@staticmethod |
|
|
def get_max_employee_per_type_on_day(date_span): |
|
|
"""Get max employee per type configuration for given date span""" |
|
|
return { |
|
|
"UNICEF Fixed term": { |
|
|
t: 8 for t in date_span |
|
|
}, |
|
|
"Humanizer": { |
|
|
t: 10 for t in date_span |
|
|
} |
|
|
} |
|
|
MAX_UNICEF_PER_DAY = 8 |
|
|
MAX_HUMANIZER_PER_DAY = 10 |
|
|
MAX_HOUR_PER_PERSON_PER_DAY = 14 |
|
|
KIT_LEVELS, KIT_DEPENDENCIES, PRODUCTION_PRIORITY_ORDER = extract.get_production_order_data() |
|
|
|
|
|
|
|
|
|