Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions cliff_watch/calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
DEFAULT_SERIES_TARGET_POINTS,
DEFAULT_YEAR,
FILING_STATUS_OPTIONS,
HOUSEHOLD_COST_DEFINITIONS,
MARRIED_FILING_STATUSES,
HOUSEHOLD_TYPE_BY_ID,
PROGRAM_DEFINITIONS,
Expand Down Expand Up @@ -55,6 +56,9 @@ class HouseholdInput:


PROGRAM_LABEL_BY_KEY = {item["key"]: item["label"] for item in PROGRAM_DEFINITIONS}
HOUSEHOLD_COST_LABEL_BY_KEY = {
item["key"]: item["label"] for item in HOUSEHOLD_COST_DEFINITIONS
}
FILING_STATUS_CODES = {item["code"] for item in FILING_STATUS_OPTIONS}
REFUNDABLE_CREDIT_COMPONENTS = (
{"key": "eitc", "variable": "eitc", "map_to": "tax_unit"},
Expand Down Expand Up @@ -125,10 +129,6 @@ def _candidate_policyengine_repo() -> Path | None:
repo = os.getenv("POLICYENGINE_US_REPO")
if repo:
return Path(repo).expanduser()

sibling = Path(__file__).resolve().parents[1].parent / "policyengine-us"
if sibling.exists():
return sibling
return None


Expand Down Expand Up @@ -1000,6 +1000,24 @@ def _build_cliff_drivers(
}
)

for key, label in HOUSEHOLD_COST_LABEL_BY_KEY.items():
annual_change = round(
result["household_costs"][key] - previous_result["household_costs"][key],
2,
)
if annual_change > 0:
drivers.append(
{
"key": key,
"label": label,
"kind": "household_cost_increase",
"raw_change_annual": annual_change,
"raw_change_monthly": _monthly_amount(annual_change),
"resource_effect_annual": round(-annual_change, 2),
"resource_effect_monthly": _monthly_amount(-annual_change),
}
)

tax_change = round(
result["totals"]["taxes"] - previous_result["totals"]["taxes"],
2,
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"test": "node --test src/policyengineApi.test.js",
"build": "vite build",
"preview": "vite preview"
},
Expand Down
19 changes: 18 additions & 1 deletion frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ import {
import { decodeInputs, syncUrlToInputs } from './utils/urlState'
import { refineCliffZones } from './utils/seriesRefine'

function cleanSeriesErrorMessage(error) {
const message = error?.message?.trim()
if (!message) {
return 'The cliff chart is unavailable right now.'
}

if (message.startsWith('Calculation failed:')) {
return message
}

return `Chart calculation failed: ${message}`
}

function App() {
const [metadata, setMetadata] = useState(null)
const [inputs, setInputs] = useState(null)
Expand Down Expand Up @@ -91,23 +104,27 @@ function App() {
const isCancelled = () => requestVersion !== requestVersionRef.current

let primary = null
let primaryError = null
try {
primary = await calculateSeries(nextInputs, metadata, { step: defaultStep })
} catch (err) {
primaryError = err
console.error(err)
}

if (isCancelled()) return

if (!primary) {
let fallbackError = null
try {
primary = await calculateSeries(nextInputs, metadata, { step: fallbackStep })
if (isCancelled()) return
setSeriesError('Sampled coarsely for speed; refining around detected cliffs.')
} catch (err) {
fallbackError = err
console.error(err)
if (isCancelled()) return
setSeriesError('The cliff chart timed out. Try a smaller chart max and run it again.')
setSeriesError(cleanSeriesErrorMessage(fallbackError || primaryError))
setSeriesLoading(false)
return
}
Expand Down
Loading
Loading