Build an Engineering Team Performance Review System
Instructions
Overview
In this lab, you will build a Python Performance Review System that an Engineering Manager could use to track team performance across a quarter. The system will manage team members, their goals, calculate completion rates, identify underperformers who need coaching, and generate formatted review summaries.
Core Concepts
This lab applies the performance management frameworks from Module 2:
- OKR-style goal tracking with measurable completion percentages
- Underperformer identification using configurable thresholds
- SBI-ready review summaries with specific, evidence-based assessments
- Calibration-friendly output that enables cross-team comparison
Requirements
Part 1: Team Member Management
Create a function add_team_member(team, name, role, level) that:
- Accepts a team dictionary, member name (string), role (string), and level (string, e.g., "L3", "L4", "L5")
- Adds the member to the team with an empty goals list and a default status of "on_track"
- Returns the updated team dictionary
- Raises
ValueErrorif the member name already exists in the team
Create a function remove_team_member(team, name) that:
- Removes a member from the team dictionary
- Returns the updated team dictionary
- Raises
KeyErrorif the member does not exist
Part 2: Goal Management
Create a function add_goal(team, member_name, goal_title, weight) that:
- Adds a goal to the specified member's goals list
- Each goal has:
title(string),weight(float, 0.0 to 1.0),completion(float, defaults to 0.0) - Validates that total weights for a member do not exceed 1.0
- Raises
ValueErrorif the member does not exist or if adding the goal would exceed total weight of 1.0
Create a function update_goal_completion(team, member_name, goal_title, completion) that:
- Updates the completion percentage (0.0 to 1.0) for a specific goal
- Raises
ValueErrorif completion is not between 0.0 and 1.0 - Raises
KeyErrorif the member or goal does not exist
Part 3: Performance Calculations
Create a function calculate_member_score(team, member_name) that:
- Calculates a weighted performance score: sum of (goal_weight * goal_completion) for all goals
- Returns a float rounded to 2 decimal places
- Raises
KeyErrorif the member does not exist
Create a function identify_underperformers(team, threshold=0.6) that:
- Returns a list of dictionaries for members whose weighted score is below the threshold
- Each dictionary contains:
name,score,role,level, andstruggling_goals(list of goal titles with completion below 0.5) - The list is sorted by score in ascending order (lowest performers first)
Create a function calculate_team_stats(team) that:
- Returns a dictionary with:
team_size: Total number of membersaverage_score: Average weighted score across all members (rounded to 2 decimal places)highest_performer: Dictionary withnameandscoreof the top performerlowest_performer: Dictionary withnameandscoreof the lowest performeron_track_count: Number of members with score >= 0.7at_risk_count: Number of members with score between 0.4 and 0.7underperforming_count: Number of members with score < 0.4
Part 4: Review Summary Generation
Create a function generate_review_summary(team) that:
- Returns a formatted string containing:
- A header with the team statistics
- A section for each team member showing:
- Name, role, and level
- Each goal with its weight, completion percentage, and a visual progress bar using block characters
- Overall weighted score
- Status classification: "Exceeding" (>= 0.9), "On Track" (>= 0.7), "Needs Attention" (>= 0.4), or "Underperforming" (< 0.4)
- A summary section listing underperformers with recommended actions
- The output must be clean, readable, and well-structured
Example Usage
team = {}
# Add members
team = add_team_member(team, "Alice Chen", "Senior Engineer", "L5")
team = add_team_member(team, "Bob Kumar", "Engineer", "L4")
team = add_team_member(team, "Carol Davis", "Junior Engineer", "L3")
# Add goals for Alice
team = add_goal(team, "Alice Chen", "Lead API redesign", 0.4)
team = add_goal(team, "Alice Chen", "Mentor 2 junior engineers", 0.3)
team = add_goal(team, "Alice Chen", "Reduce P1 incidents by 50%", 0.3)
# Update completions
team = update_goal_completion(team, "Alice Chen", "Lead API redesign", 0.9)
team = update_goal_completion(team, "Alice Chen", "Mentor 2 junior engineers", 0.8)
team = update_goal_completion(team, "Alice Chen", "Reduce P1 incidents by 50%", 0.7)
# Calculate scores
score = calculate_member_score(team, "Alice Chen")
print(f"Alice's score: {score}") # 0.81
# Generate full review
summary = generate_review_summary(team)
print(summary)
Expected Output Format
================================================
ENGINEERING TEAM PERFORMANCE REVIEW
================================================
Team Size: 3
Average Score: 0.64
On Track: 1 | At Risk: 1 | Underperforming: 1
------------------------------------------------
Alice Chen | Senior Engineer | L5
------------------------------------------------
Lead API redesign (40%) [==========-] 90%
Mentor 2 junior engineers (30%) [========--] 80%
Reduce P1 incidents by 50% (30%) [=======---] 70%
Weighted Score: 0.81 — STATUS: On Track
------------------------------------------------
Bob Kumar | Engineer | L4
------------------------------------------------
Deliver auth service (50%) [======----] 60%
Write tech spec for caching (30%) [=====-----] 50%
Improve test coverage (20%) [====------] 40%
Weighted Score: 0.53 — STATUS: Needs Attention
------------------------------------------------
Carol Davis | Junior Engineer | L3
------------------------------------------------
Complete onboarding tasks (40%) [========--] 80%
Fix 10 bugs from backlog (30%) [===-------] 30%
Shadow on-call rotation (30%) [==--------] 20%
Weighted Score: 0.47 — STATUS: Needs Attention
================================================
UNDERPERFORMERS REQUIRING ACTION
================================================
1. Carol Davis (L3) — Score: 0.47
Struggling goals: Fix 10 bugs from backlog, Shadow on-call rotation
Recommended: Create a 30-60-90 day coaching plan
================================================