Skip to content

Commit a2de8b4

Browse files
Update extract_submissions.py
1 parent e24ffaf commit a2de8b4

File tree

1 file changed

+51
-88
lines changed

1 file changed

+51
-88
lines changed
Lines changed: 51 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1+
from openpyxl import Workbook
2+
from openpyxl.styles import Font
3+
from openpyxl.utils import get_column_letter
14
import os
25
import csv
36
import random
47
from collections import defaultdict
5-
from openpyxl import Workbook
6-
from openpyxl.styles import Alignment, Font
7-
from openpyxl.utils import get_column_letter
8-
from openpyxl.worksheet.datavalidation import DataValidation
98

10-
# Load deduplicated submissions
9+
# === Load data ===
1110
with open("ambassador/ambassador_submissions_deduped.csv", newline='', encoding='utf-8') as f:
1211
reader = csv.DictReader(f)
1312
submissions = list(reader)
1413

15-
# Define reviewers
1614
reviewers = [f"Reviewer {i}" for i in range(1, 8)]
1715

1816
# Define rubric
@@ -41,117 +39,82 @@
4139
("Motivation and Vision", "Vision", "Proposed goals or initiatives that align with the mission of the PyTorch Foundation?")
4240
]
4341

44-
# Limit categories for summary
45-
summary_categories = [
46-
"Technical Expertise",
47-
"Open Source Contributions",
48-
"Thought Leadership and Technical Writing",
49-
"Community Engagement and Evangelism",
50-
"Online Influence and Reach",
51-
"Alignment and Values",
52-
"Motivation and Vision"
53-
]
42+
# Define category mapping
43+
categories = ["Technical Expertise", "Open Source Contributions", "Thought Leadership and Technical Writing",
44+
"Community Engagement and Evangelism", "Online Influence and Reach", "Alignment and Values",
45+
"Motivation and Vision"]
5446

55-
# Output folder
56-
output_folder = "ambassador/reviewer_sheets_excel"
57-
os.makedirs(output_folder, exist_ok=True)
47+
# Build a lookup for rubric indexes
48+
category_map = defaultdict(list)
49+
for i, (cat, _, _) in enumerate(rubric):
50+
category_map[cat].append(i)
5851

59-
# Assign reviewers
52+
# Random reviewer assignment
6053
assignments = []
6154
reviewer_counts = defaultdict(int)
6255
for submission in submissions:
63-
assigned = random.sample(sorted(reviewers, key=lambda r: reviewer_counts[r])[:4], 2)
56+
sorted_reviewers = sorted(reviewers, key=lambda r: reviewer_counts[r])
57+
assigned = random.sample(sorted_reviewers[:4], 2)
6458
for reviewer in assigned:
6559
reviewer_counts[reviewer] += 1
6660
assignments.append((submission, reviewer))
6761

68-
# Generate reviewer sheets
62+
# Output directory
63+
output_dir = "ambassador/reviewer_sheets_excel"
64+
os.makedirs(output_dir, exist_ok=True)
65+
66+
# Generate Excel with 2 sheets per reviewer
6967
for reviewer in reviewers:
7068
wb = Workbook()
7169
ws = wb.active
7270
ws.title = "Review Sheet"
7371

74-
summary_ws = wb.create_sheet("Score Summary")
75-
76-
# Review Sheet Header
77-
headers = [
78-
"Submission ID", "First Name", "Last Name", "Submission Summary",
79-
"Reviewer's Comment", "Category", "Subcategory", "Question", "Score"
80-
]
81-
ws.append(headers)
82-
for col in range(1, len(headers)+1):
83-
ws.cell(row=1, column=col).font = Font(bold=True)
84-
85-
# Dropdown for score
86-
dv = DataValidation(type="list", formula1='"Yes,No,N/A"', allow_blank=True)
87-
ws.add_data_validation(dv)
72+
# Summary worksheet
73+
summary_ws = wb.create_sheet(title="Score Summary")
74+
summary_headers = ["Submission ID", "First Name", "Last Name"] + categories + ["Final Score"]
75+
summary_ws.append(summary_headers)
76+
for col in summary_ws[1]:
77+
col.font = Font(bold=True)
8878

8979
row_idx = 2
90-
candidate_ranges = []
80+
summary_row = 2
9181

9282
for submission, assigned_reviewer in assignments:
9383
if assigned_reviewer != reviewer:
9484
continue
9585

96-
sid = submission["Issue #"]
97-
name = submission["Nominee Name"].split()
98-
fname = name[0]
99-
lname = name[-1] if len(name) > 1 else ""
100-
summary = f"""Contributions:\n{submission.get("Contributions", "")}
101-
102-
Ambassador Pitch:\n{submission.get("Ambassador Pitch", "")}
86+
issue_id = submission["Issue #"]
87+
name_parts = submission["Nominee Name"].split()
88+
first_name = name_parts[0] if name_parts else ""
89+
last_name = name_parts[-1] if len(name_parts) > 1 else ""
10390

104-
Additional Notes:\n{submission.get("Extra Notes", "")}"""
91+
category_rows = defaultdict(list)
92+
start_row = row_idx
10593

106-
start = row_idx
10794
for cat, subcat, question in rubric:
108-
ws.append([sid, fname, lname, summary, "", cat, subcat, question, ""])
95+
ws.append([
96+
issue_id, first_name, last_name, "", "", cat, subcat, question, ""
97+
])
98+
category_rows[cat].append(row_idx)
10999
row_idx += 1
110-
end = row_idx - 1
111-
candidate_ranges.append((sid, fname, lname, start, end))
112-
113-
# Merge
114-
for col in [1,2,3,4]:
115-
ws.merge_cells(start_row=start, end_row=end, start_column=col, end_column=col)
116-
cell = ws.cell(row=start, column=col)
117-
cell.alignment = Alignment(vertical="top", wrap_text=True)
118-
119-
# Apply dropdowns
120-
for r in range(start, end + 1):
121-
dv.add(ws[f"I{r}"])
122-
123-
# Auto column widths
124-
for col in ws.columns:
125-
max_len = max((len(str(cell.value)) if cell.value else 0) for cell in col)
126-
ws.column_dimensions[get_column_letter(col[0].column)].width = min(max_len + 5, 50)
127-
128-
# Score Summary Sheet Header
129-
summary_ws.append(["Submission ID", "First Name", "Last Name"] + summary_categories + ["Final Score"])
130-
for col in range(1, summary_ws.max_column + 1):
131-
summary_ws.cell(row=1, column=col).font = Font(bold=True)
132-
133-
# Fill Score Summary
134-
for sid, fname, lname, start, end in candidate_ranges:
135-
category_rows = defaultdict(list)
136-
for r in range(start, end + 1):
137-
category = ws.cell(row=r, column=6).value
138-
if category in summary_categories:
139-
category_rows[category].append(r)
140100

141-
formula_cells = []
142-
for cat in summary_categories:
101+
# Write summary formulas
102+
formulas = []
103+
for cat in categories:
143104
if cat in category_rows:
144105
rng = category_rows[cat]
145-
formula = f"SUMPRODUCT(--(Review Sheet!I{rng[0]}:I{rng[-1]}=\"Yes\"))"
106+
formula = f"=SUMPRODUCT(--('{ws.title}'!I{rng[0]}:I{rng[-1]}=\"Yes\"))"
107+
formulas.append(formula)
146108
else:
147-
formula = "0"
148-
formula_cells.append(f"={formula}")
109+
formulas.append("")
110+
111+
total_formula = f"=SUM({','.join([chr(68+i) + str(summary_row) for i in range(3, 3+len(categories))])})"
149112

150-
total_formula = f"=SUM({','.join([f'{get_column_letter(i+4)}{summary_ws.max_row+1}' for i in range(len(formula_cells))])})"
151-
summary_ws.append([sid, fname, lname] + formula_cells + [total_formula])
113+
summary_ws.append([issue_id, first_name, last_name] + formulas + [total_formula])
114+
summary_row += 1
152115

153-
# Save workbook
154-
path = os.path.join(output_folder, f"{reviewer.replace(' ', '_').lower()}_sheet.xlsx")
155-
wb.save(path)
116+
# Save file
117+
reviewer_file = os.path.join(output_dir, f"{reviewer.replace(' ', '_').lower()}_sheet.xlsx")
118+
wb.save(reviewer_file)
156119

157-
print("✅ Reviewer sheets generated with aligned score summary.")
120+
print("✅ All reviewer sheets generated with corrected formulas and aligned categories.")

0 commit comments

Comments
 (0)