is_over_hours from yesterday tells you whether a project is over. But clients need more than a yes or no — they need to know how far over. Three tiers: on track, over by 10%, critical. How do you classify that right now?
I look at the number and make a judgment call. I don't have a consistent threshold. Two clients get different treatment for the same overage.
if/elif/else is that consistent threshold, written once, applied identically to every project. The logic is the same structure as a nested IF in your spreadsheet — but without the formula wrapping:
if actual < budgeted * 1.1:
return "on track"
elif actual < budgeted * 1.25:
return "over by 10%"
else:
return "critical"Why does the order matter? Could I put the else first and check from the top?
Python tests conditions top to bottom and stops at the first True. If you put the broadest condition first, everything falls into it and the elif/else branches never run. Start with the tightest test, widen with each branch:
def categorize_project_status(actual: float, budgeted: float) -> str:
result = "on track" if actual < budgeted * 1.1 else ("over by 10%" if actual < budgeted * 1.25 else "critical")
print(f"Status: {result}")
return resultSo this replaces the mental gymnastics I do every time I review a project list. One function call and every project gets a consistent label.
Every project. Same thresholds. No judgment call variation. That label feeds directly into Week 2 grouping.
My clients have been getting different risk conversations based on my mood. This makes it consistent.
Consistent thresholds are a deliverable, not just a technical detail. What would you change the 1.25 multiplier to for a client with zero revision tolerance?
Python tests conditions sequentially and short-circuits on the first True:
if condition_1:
# runs if condition_1 is True
elif condition_2:
# runs if condition_1 is False AND condition_2 is True
else:
# catch-all — runs when no condition above matchedPut the tightest test first. actual < budgeted * 1.1 is tighter than actual < budgeted * 1.25. If you reverse them, the 10% branch catches everything that is below 25%, and the critical branch never fires.
budgeted * 1.1 = 10% over budget. budgeted * 1.25 = 25% over budget.
is_over_hours from yesterday tells you whether a project is over. But clients need more than a yes or no — they need to know how far over. Three tiers: on track, over by 10%, critical. How do you classify that right now?
I look at the number and make a judgment call. I don't have a consistent threshold. Two clients get different treatment for the same overage.
if/elif/else is that consistent threshold, written once, applied identically to every project. The logic is the same structure as a nested IF in your spreadsheet — but without the formula wrapping:
if actual < budgeted * 1.1:
return "on track"
elif actual < budgeted * 1.25:
return "over by 10%"
else:
return "critical"Why does the order matter? Could I put the else first and check from the top?
Python tests conditions top to bottom and stops at the first True. If you put the broadest condition first, everything falls into it and the elif/else branches never run. Start with the tightest test, widen with each branch:
def categorize_project_status(actual: float, budgeted: float) -> str:
result = "on track" if actual < budgeted * 1.1 else ("over by 10%" if actual < budgeted * 1.25 else "critical")
print(f"Status: {result}")
return resultSo this replaces the mental gymnastics I do every time I review a project list. One function call and every project gets a consistent label.
Every project. Same thresholds. No judgment call variation. That label feeds directly into Week 2 grouping.
My clients have been getting different risk conversations based on my mood. This makes it consistent.
Consistent thresholds are a deliverable, not just a technical detail. What would you change the 1.25 multiplier to for a client with zero revision tolerance?
Python tests conditions sequentially and short-circuits on the first True:
if condition_1:
# runs if condition_1 is True
elif condition_2:
# runs if condition_1 is False AND condition_2 is True
else:
# catch-all — runs when no condition above matchedPut the tightest test first. actual < budgeted * 1.1 is tighter than actual < budgeted * 1.25. If you reverse them, the 10% branch catches everything that is below 25%, and the critical branch never fires.
budgeted * 1.1 = 10% over budget. budgeted * 1.25 = 25% over budget.
Mira reviews six client projects at month-end and needs a consistent status label for each. Write `categorize_project_status(actual, budgeted)` that returns `"on track"` when actual hours are below 110% of budget, `"over by 10%"` when between 110% and 125%, and `"critical"` when above 125%.
Tap each step for scaffolded hints.
No blank-editor panic.