Spaces:
Sleeping
Sleeping
File size: 6,798 Bytes
0836e11 9374a4b 0836e11 036ae9d 9374a4b 8425b4c 424218f 0caadca 58c2739 9374a4b 58c2739 8425b4c ab6bd39 8425b4c 9374a4b 8425b4c 0caadca 8425b4c ab6bd39 5a78c3e 9374a4b 0caadca 9374a4b ab6bd39 5a78c3e c6074bd 9219e07 e8b7ee1 0caadca 036ae9d 9219e07 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0968051 0dd86af 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b 0836e11 9374a4b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
import os
import pandas as pd
import random
import re
from sklearn.preprocessing import MinMaxScaler
# Function to assign main accounts
def assign_main_accounts(creators_file, chatter_files):
creators = pd.read_excel(creators_file)
creators.columns = creators.columns.str.strip()
# Debugging: Check initial columns
print("DEBUG: Initial Columns in Creator File:", creators.columns)
# Standardize column names
column_mapping = {
"Creator": "Creator",
"Total earnings": "Total earnings",
"Subscription": "Subscription",
"Active Fans": "ActiveFans",
"Total active fans": "ActiveFans",
}
creators.rename(columns={k: v for k, v in column_mapping.items() if k in creators.columns}, inplace=True)
# Debugging: Check renamed columns
print("DEBUG: Renamed Columns in Creator File:", creators.columns)
required_columns = ["Creator", "Total earnings", "Subscription", "ActiveFans"]
missing_columns = [col for col in required_columns if col not in creators.columns]
if missing_columns:
raise KeyError(f"Missing required columns in creators file: {missing_columns}")
# Process creators file
creators["Total earnings"] = creators["Total earnings"].replace("[\$,]", "", regex=True).astype(float)
creators["Subscription"] = creators["Subscription"].replace("[\$,]", "", regex=True).astype(float)
creators["ActiveFans"] = pd.to_numeric(creators["ActiveFans"], errors="coerce").fillna(0)
# Normalize data
scaler = MinMaxScaler()
creators[["Earnings_Normalized", "Subscriptions_Normalized"]] = scaler.fit_transform(
creators[["Total earnings", "Subscription"]]
)
creators["Penalty Factor"] = 1 - abs(creators["Earnings_Normalized"] - creators["Subscriptions_Normalized"])
creators["Score"] = (
0.7 * creators["Earnings_Normalized"] + 0.3 * creators["Subscriptions_Normalized"]
) * creators["Penalty Factor"]
creators["Rank"] = creators["Score"].rank(ascending=False)
creators = creators.sort_values(by="Rank").reset_index(drop=True)
processed_creator_file = creators[["Creator", "ActiveFans"]]
updated_chatter_files = []
for chatter_file in chatter_files:
chatters = pd.read_excel(chatter_file)
chatters.columns = chatters.columns.str.strip()
if len(chatters) > len(creators):
raise ValueError("Not enough creators to assign to all chatters.")
# Assign creators to chatters
chatters["Main Account"] = creators.iloc[:len(chatters)]["Creator"].values
updated_chatter_files.append(chatters)
# Combine all updated chatter files into a single DataFrame
combined_assignments = pd.concat(updated_chatter_files, ignore_index=True)
return updated_chatter_files, processed_creator_file, combined_assignments
def save_processed_files(assignments, output_dir):
"""
Save processed chatter files to the output directory.
"""
for idx, (shift, data) in enumerate(assignments.items()):
output_file = os.path.join(output_dir, f"Updated_{shift.lower()}_file.xlsx")
data.to_excel(output_file, index=False)
print(f"Saved {shift} file to {output_file}")
# Function to clean chatter data
def clean_chatter_data(chatter_data):
"""
Clean and prepare chatter data for scheduling.
"""
required_columns = ["Name", "Main Account", "Final Rating", "Available Work Days"]
for col in required_columns:
if col not in chatter_data.columns:
raise KeyError(f"Missing required column in chatter data: {col}")
chatter_data["WorkDays"] = pd.to_numeric(chatter_data.get("Available Work Days", 6), errors="coerce").fillna(6).astype(int)
chatter_data["Desired Off Day"] = chatter_data["Desired Off Day"].fillna("").apply(
lambda x: [day.strip().capitalize() for day in re.split(r"[ ,]+", x) if day.strip()]
)
return chatter_data
# Function to create a blank schedule template
def create_schedule_template(account_data):
"""
Create a blank schedule template with required columns.
"""
if "Creator" not in account_data.columns or "ActiveFans" not in account_data.columns:
raise KeyError("Account data must contain 'Creator' and 'ActiveFans' columns.")
schedule_template = account_data[["Creator", "ActiveFans"]].copy()
for day in ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]:
schedule_template[day] = None
return schedule_template
# Function to assign main accounts to the schedule
def assign_main_accounts_to_schedule(schedule, chatter_data):
"""
Assign main accounts to the schedule based on chatter data.
"""
for _, chatter in chatter_data.iterrows():
main_account = chatter["Main Account"]
if main_account in schedule["Creator"].values:
idx = schedule[schedule["Creator"] == main_account].index[0]
for day in schedule.columns[2:]:
schedule.at[idx, day] = chatter["Name"]
return schedule
# Function to assign off days
def assign_off_days(schedule, chatter_data):
"""
Assign days off for each chatter based on their 'Desired Off Day' field.
"""
for _, chatter in chatter_data.iterrows():
for off_day in chatter["Desired Off Day"]:
if off_day in schedule.columns[2:]:
schedule.loc[schedule[off_day] == chatter["Name"], off_day] = None
return schedule
# Function to randomly fill schedule slots
def randomly_fill_slots(schedule, chatter_data, max_accounts_per_day=3, max_fans_per_day=1000):
"""
Randomly fill remaining slots in the schedule while respecting constraints.
"""
days_of_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
chatters_list = chatter_data["Name"].tolist()
for day in days_of_week:
for idx, row in schedule.iterrows():
if pd.isnull(schedule.at[idx, day]):
random.shuffle(chatters_list)
for chatter in chatters_list:
schedule.at[idx, day] = chatter
break
return schedule
# Main schedule generation function
def generate_schedule(chatter_files, account_data):
schedules = {}
shift_names = ["Overnight", "Day", "Prime"]
for idx, chatter_df in enumerate(chatter_files):
shift_name = shift_names[idx]
chatter_df = clean_chatter_data(chatter_df)
schedule = create_schedule_template(account_data)
schedule = assign_main_accounts_to_schedule(schedule, chatter_df)
schedule = assign_off_days(schedule, chatter_df)
schedule = randomly_fill_slots(schedule, chatter_df)
schedules[shift_name] = schedule
return schedules
|