How Bonus Points and Deductions Are Calculated in the Resume Scoring System
Bonus points are added and deductions subtracted from the aggregated core category scores, with the final total capped at the maximum category score plus a 20-point bonus ceiling.
The interviewstreet/hiring-agent repository implements a structured resume scoring system that evaluates candidates across four core categories before applying bonus points and deductions to reach a final score. According to the source code in score.py and models.py, the calculation follows a strict order of operations where adjustments are applied after initial aggregation and bounded by configurable limits.
Order of Operations for Score Calculation
In score.py (lines 57–68), the scoring logic processes the evaluation data in three distinct steps after the initial resume parsing:
- Aggregate core scores – Sum the scores from the four primary categories (Open Source, Self Projects, Production, Technical Skills).
- Apply adjustments – Add the value of
evaluation.bonus_points.totaland subtractevaluation.deductions.total. - Enforce ceiling – Compare the result against
max_possible_score, defined as the sum of category maximums plus 20 (the bonus ceiling). If the total exceeds this value, it is truncated and a warning is printed.
This sequence ensures that deductions are always calculated after bonus points are applied, and neither adjustment can push the score beyond the predefined theoretical maximum.
Data Models and Validation Constraints
The Pydantic models governing these adjustments are defined in models.py (lines 31–42):
BonusPoints– Contains atotalfield constrained to the range 0–20 and abreakdownstring describing the justification (e.g., “Hackathon winner”).Deductions– Contains atotalnon-negative integer or float and areasonsstring. The sign is applied programmatically during calculation rather than stored in the model.
These constraints prevent configuration errors that could award excessive bonus points or store invalid negative deduction values.
Reporting and Export Functionality
The print_evaluation_results function in score.py (lines 71–84) displays these adjustments in formatted output blocks labeled “BONUS POINTS” and “DEDUCTIONS,” mirroring the internal calculation logic for auditing purposes.
For downstream analysis, transform_evaluation_response in transform.py (lines 15–22) serializes the data into four distinct CSV columns:
bonus_points– The numeric total.bonus_breakdown– The human-readable description.deductions– The numeric total.deduction_reasons– The explanation for the penalty.
Practical Example: Creating a Scored Evaluation
The following example demonstrates how to construct an EvaluationData object with both bonus points and deductions, then calculate the final score:
from models import (
CategoryScore,
Scores,
BonusPoints,
Deductions,
EvaluationData,
)
# Core category scores
scores = Scores(
open_source=CategoryScore(score=30, max=35, evidence="..."),
self_projects=CategoryScore(score=25, max=30, evidence="..."),
production=CategoryScore(score=20, max=25, evidence="..."),
technical_skills=CategoryScore(score=8, max=10, evidence="..."),
)
# Bonus points earned (e.g., for a hackathon win)
bonus = BonusPoints(total=12.5, breakdown="Hackathon winner (+12.5)")
# Deductions (e.g., missing contact info)
deductions = Deductions(total=3, reasons="Missing phone number")
# Full evaluation object
evaluation = EvaluationData(
scores=scores,
bonus_points=bonus,
deductions=deductions,
key_strengths=["Strong open‑source contributions"],
areas_for_improvement=["Add a professional summary"],
)
# Calculate and display final results
from score import print_evaluation_results
print_evaluation_results(evaluation, candidate_name="Alice Example")
Running this script produces formatted output showing the adjustments:
⭐ BONUS POINTS: 12.5
Hackathon winner (+12.5)
⚠️ DEDUCTIONS: -3
Missing phone number
To export these values for spreadsheet analysis:
from transform import transform_evaluation_response
row = transform_evaluation_response(
file_name="alice_resume.pdf",
resume_data=None,
github_data=None,
evaluation=evaluation,
)
print(row["bonus_points"], row["bonus_breakdown"])
# → 12.5 Hackathon winner (+12.5)
Summary
- Bonus points (0–20 max) are added to the sum of core category scores.
- Deductions are subtracted after bonus points are applied.
- The final total is capped at
max_score + 20to prevent overflow. - Adjustments are persisted in CSV exports via
transform.pyusing dedicated columns for totals and descriptions. - All logic is centralized in
score.pyfor calculation andmodels.pyfor validation.
Frequently Asked Questions
What is the maximum number of bonus points allowed?
The BonusPoints.total field is constrained to a maximum of 20 points by the Pydantic model definition in models.py. This limit is strictly enforced at the data validation layer before the score calculation begins.
Where is the final score capping logic implemented?
The capping logic resides in score.py (lines 57–68), where the code calculates max_possible_score as the sum of all category maximums plus the 20-point bonus ceiling. If the aggregated total exceeds this value, the score is truncated to the ceiling value.
How are bonus and deduction details stored in CSV exports?
The transform_evaluation_response function in transform.py (lines 15–22) maps the data to four columns: bonus_points (numeric), bonus_breakdown (description), deductions (numeric), and deduction_reasons (description). This structure separates the quantitative values from the qualitative justifications for analytics purposes.
Can deductions reduce the final score below zero?
The source code analysis explicitly describes an upper bound cap (max_possible_score) but does not specify a lower bound floor at zero. The calculation subtracts the deduction total from the sum of core scores and bonus points, though the Deductions model requires a non-negative total value with the negative sign applied mathematically during the final aggregation step.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →