formatter / app.py
kreemyyyy's picture
Update app.py
40ca158 verified
raw
history blame
3.95 kB
import pandas as pd
import gradio as gr
# 7-Day Schedule Converter with explicit iteration and header fill
def convert_schedule(file_path, direction):
# 1. Load Excel sheet into DataFrame
# Read without header to inspect first two rows for header fill
raw = pd.read_excel(file_path, header=None)
# Extract potential header rows (skip first column)
header1 = raw.iloc[0,1:].astype(object)
header2 = raw.iloc[1,1:].astype(object)
# Decide which header row to use: prefer second if fully populated
if header2.notna().all() and not header2.str.startswith('Unnamed').any():
days = header2.tolist()
data_start = 2
else:
# Forward-fill merged first-row headers
days = []
last = None
for val in header1:
if pd.isna(val) or str(val).startswith('Unnamed'):
days.append(last)
else:
last = str(val)
days.append(last)
data_start = 1
# Load actual data with day columns
df = pd.read_excel(
file_path,
header=data_start,
index_col=0,
usecols=[0] + list(range(1, len(days)+1))
)
df.columns = [str(day) for day in days]
# 2. Ensure we have exactly the original 7 day columns
day_cols = list(df.columns)
# 3. Build mapping: for each Model (or Texter) assign days
assignments = {}
if direction == 'A to B':
# Rows are Models → output rows are Texters
for model in df.index.astype(str):
for day in day_cols:
cell = df.at[model, day]
for texter in str(cell).split(','):
texter = texter.strip()
if not texter or texter.lower() in ['nan', 'none']:
continue
assignments.setdefault(texter, {d: [] for d in day_cols})
assignments[texter][day].append(model)
# Build output DataFrame
index = sorted(assignments.keys())
result = pd.DataFrame(index=index, columns=day_cols)
for texter, days_map in assignments.items():
for day in day_cols:
models = days_map.get(day, [])
result.at[texter, day] = ', '.join(models) if models else 'OFF'
else:
# Rows are Texters → output rows are Models
for texter in df.index.astype(str):
for day in day_cols:
cell = df.at[texter, day]
for model in str(cell).split(','):
model = model.strip()
if not model or model.lower() in ['nan', 'none']:
continue
assignments.setdefault(model, {d: [] for d in day_cols})
assignments[model][day].append(texter)
index = sorted(assignments.keys())
result = pd.DataFrame(index=index, columns=day_cols)
for model, days_map in assignments.items():
for day in day_cols:
texters = days_map.get(day, [])
result.at[model, day] = ', '.join(texters) if texters else 'OFF'
# 4. Cleanup axis names
result.index.name = None
result.columns.name = None
return result
# Gradio UI
def main():
iface = gr.Interface(
fn=convert_schedule,
inputs=[
gr.File(label='Upload Weekly Schedule (.xlsx)', file_count='single', type='filepath'),
gr.Radio(['A to B', 'B to A'], label='Convert Direction')
],
outputs=gr.Dataframe(label='Converted Schedule'),
title='7-Day Schedule Converter',
description=('Upload a 7-column weekly schedule (Models vs Days) with merged or single headers, '\
'then flip between Models→Texters or Texters→Models. Uses explicit iteration.'),
allow_flagging='never'
)
iface.launch(server_name='0.0.0.0', server_port=7860)
if __name__ == '__main__':
main()