from datetime import datetime, timedelta
import random

# Your predefined variables…
duty_date = "2024-08-11"
date = datetime.strptime(duty_date, "%Y-%m-%d")

day_of_week = date.strftime("%A")

# Finding weekends
weekends = [date + timedelta(days=i) for i in range((5 - date.weekday()) % 7, 31, 7)] + \
           [date + timedelta(days=i) for i in range((6 - date.weekday()) % 7, 31, 7)]

# Ensure weekends include the 30th and 31st if they fall on a weekend
for i in range(30, 32):
    potential_weekend = datetime(date.year, date.month, i)
    if potential_weekend.weekday() in [5, 6]:  # Saturday or Sunday
        weekends.append(potential_weekend)

print(day_of_week)
print(weekends)

# Define the list of persons
primary_persons = ["NTALAMPEKOU", "MAFOUNI", "MEMIS", "RAISAKIS", "ENECHELIDOU", "DIMADIS"]
secondary_persons = ["SACHANIDOU", "VASILIADIS", "PAPAGEORGIOU", "KARAISKOS", "TSIPLAKIS", "SPANTIDAKIS", "PAPADOPOULOS"]

# Define the days they can’t be on duty
unavailable_days = {
    "NTALAMPEKOU": ["2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15", "2024-08-16", "2024-08-17", "2024-08-18", "2024-08-19"],
    "MAFOUNI": ["2024-08-20", "2024-08-21", "2024-08-22", "2024-08-23", "2024-08-24", "2024-08-25"],
    "MEMIS": ["2024-08-01", "2024-08-02", "2024-08-03", "2024-08-04", "2024-08-05", "2024-08-06", "2024-08-07"],
    "RAISAKIS": ["2024-08-10", "2024-08-11", "2024-08-12", "2024-08-13", "2024-08-15", "2024-08-16", "2024-08-17"],
    "ENECHELIDOU": ["2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15", "2024-08-16", "2024-08-17"],
    "DIMADIS": ["2024-08-05", "2024-08-06", "2024-08-07"],
    "SACHANIDOU": ["2024-08-21", "2024-08-22", "2024-08-23", "2024-08-24", "2024-08-25"],
    "VASILIADIS": ["2024-08-10", "2024-08-11", "2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15"],
    "PAPAGEORGIOU": ["2024-08-01", "2024-08-02", "2024-08-03", "2024-08-04", "2024-08-05", "2024-08-07"],
    "KARAISKOS": ["2024-08-11", "2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15"],
    "TSIPLAKIS": ["2024-08-15"],
    "SPANTIDAKIS": ["2024-08-14", "2024-08-15", "2024-08-16"],
    "PAPADOPOULOS": ["2024-08-12", "2024-08-13", "2024-08-14", "2024-08-15"]
}

# Define the history of previous months based on the table
previous_duties = {
    "NTALAMPEKOU": 24,
    "MAFOUNI": 22,
    "MEMIS": 22,
    "RAISAKIS": 24,
    "ENECHELIDOU": 0,
    "DIMADIS": 27,
    "SACHANIDOU": 9,
    "VASILIADIS": 12,
    "PAPAGEORGIOU": 11,
    "KARAISKOS": 11,
    "TSIPLAKIS": 8,
    "SPANTIDAKIS": 11,
    "PAPADOPOULOS": 22
}

# Define the history of duties on specific days of the week
weekly_duties = {
    "NTALAMPEKOU": {"Monday": 3, "Tuesday": 4, "Wednesday": 5, "Thursday": 5, "Friday": 1, "Saturday": 3, "Sunday": 3},
    "MAFOUNI": {"Monday": 2, "Tuesday": 5, "Wednesday": 5, "Thursday": 4, "Friday": 2, "Saturday": 2, "Sunday": 2},
    "MEMIS": {"Monday": 5, "Tuesday": 1, "Wednesday": 2, "Thursday": 2, "Friday": 4, "Saturday": 4, "Sunday": 4},
    "RAISAKIS": {"Monday": 2, "Tuesday": 3, "Wednesday": 6, "Thursday": 4, "Friday": 3, "Saturday": 4, "Sunday": 2},
    "ENECHELIDOU": {"Monday": 0, "Tuesday": 0, "Wednesday": 0, "Thursday": 0, "Friday": 0, "Saturday": 0, "Sunday": 0},
    "DIMADIS": {"Monday": 5, "Tuesday": 3, "Wednesday": 1, "Thursday": 3, "Friday": 5, "Saturday": 3, "Sunday": 7},
    "SACHANIDOU": {"Monday": 1, "Tuesday": 2, "Wednesday": 3, "Thursday": 0, "Friday": 1, "Saturday": 1, "Sunday": 1},
    "VASILIADIS": {"Monday": 1, "Tuesday": 2, "Wednesday": 0, "Thursday": 4, "Friday": 2, "Saturday": 1, "Sunday": 2},
    "PAPAGEORGIOU": {"Monday": 1, "Tuesday": 1, "Wednesday": 1, "Thursday": 2, "Friday": 2, "Saturday": 3, "Sunday": 1},
    "KARAISKOS": {"Monday": 1, "Tuesday": 3, "Wednesday": 2, "Thursday": 0, "Friday": 2, "Saturday": 2, "Sunday": 1},
    "TSIPLAKIS": {"Monday": 2, "Tuesday": 0, "Wednesday": 0, "Thursday": 1, "Friday": 2, "Saturday": 1, "Sunday": 2},
    "SPANTIDAKIS": {"Monday": 1, "Tuesday": 2, "Wednesday": 0, "Thursday": 2, "Friday": 3, "Saturday": 2, "Sunday": 1},
    "PAPADOPOULOS": {"Monday": 3, "Tuesday": 4, "Wednesday": 4, "Thursday": 3, "Friday": 2, "Saturday": 3, "Sunday": 3}
}

# Function to check availability
def is_available(person, date):
    return date not in unavailable_days.get(person, []) and date not in predefined_duties.get(person, [])

# Modified Generate Schedule Function
def generate_schedule(month, year):
    schedule = {}
    date = datetime(year, month, 1)
    primary_duties = {p: 0 for p in primary_persons}
    secondary_duties = {p: 0 for p in secondary_persons}
    
    # Assign predefined duties
    for person, dates in predefined_duties.items():
        for duty_date in dates:
            date_obj = datetime.strptime(duty_date, "%Y-%m-%d")
            schedule[duty_date] = person
            if person in primary_duties:
                primary_duties[person] += 1
            else:
                secondary_duties[person] += 1
            
            previous_duties[person] += 1
            day_of_week = date_obj.strftime("%A")
            weekly_duties[person][day_of_week] += 1
    
    # Shuffle weekends
    random.shuffle(weekends)
    
    # Assign duties on weekends
    for person in primary_persons:
        for weekend in weekends:
            weekend_date = weekend.strftime("%Y-%m-%d")
            if is_available(person, weekend_date):                    
                schedule[weekend_date] = person
                primary_duties[person] += 1
                previous_duties[person] += 1
                day_of_week = weekend.strftime("%A")
                weekly_duties[person][day_of_week] += 1
                weekends.remove(weekend)  # Remove the weekend once assigned
                break

    # Main scheduling loop
    while date.month == month:
        date_str = date.strftime("%Y-%m-%d")
        if date_str not in schedule:
            available_primary = [p for p in primary_persons if is_available(p, date_str) and primary_duties[p] < 3]
            available_secondary = [p for p in secondary_persons if is_available(p, date_str) and secondary_duties[p] < 2]
            
            if available_primary:
                available_primary.sort(key=lambda p: (previous_duties.get(p, 0), weekly_duties[p][date.strftime("%A")]))
                person = available_primary[0]
                primary_duties[person] += 1
            elif available_secondary:
                available_secondary.sort(key=lambda p: (previous_duties.get(p, 0), weekly_duties[p][date.strftime("%A")]))
                person = available_secondary[0]
                secondary_duties[person] += 1
            else:
                person = None  # Handle the case where nobody is available
                print(f"No available duty person on {date_str}")  # Logging
            
            if person:
                schedule[date_str] = person
        
        date += timedelta(days=1)
    
    return schedule

# Generate the schedule
schedule = generate_schedule(8, 2024)  # August 2024
for day, person in sorted(schedule.items()):
    print(f"{day}: {person}")
when i run the code i get the error : Sunday
[datetime.datetime(2024, 8, 17, 0, 0), datetime.datetime(2024, 8, 24, 0, 0), datetime.datetime(2024, 8, 31, 0, 0), datetime.datetime(2024, 9, 7, 0, 0), datetime.datetime(2024, 8, 11, 0, 0), datetime.datetime(2024, 8, 18, 0, 0), datetime.datetime(2024, 8, 25, 0, 0), datetime.datetime(2024, 9, 1, 0, 0), datetime.datetime(2024, 9, 8, 0, 0), datetime.datetime(2024, 8, 31, 0, 0)]
Traceback (most recent call last):
  File "/Users/chrismackom/Desktop/final5.py", line 146, in <module>
    schedule = generate_schedule(8, 2024)  # August 2024
  File "/Users/chrismackom/Desktop/final5.py", line 90, in generate_schedule
    for person, dates in predefined_duties.items():
NameError: name 'predefined_duties' is not defined