Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save sparr/105a45689768f103decc1459156a12f6 to your computer and use it in GitHub Desktop.

Select an option

Save sparr/105a45689768f103decc1459156a12f6 to your computer and use it in GitHub Desktop.
Philadelphia Police Pools Budget Balancer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Philadelphia Police vs Pools Budget Balancer</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
background: #eee;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
h1 {
font-size: 24px;
color: #222;
margin: 0 0 0 0;
text-align: center;
}
.card {
background: #ffffff;
border-radius: 16px;
box-shadow: 0 8px 24px rgba(0,0,0,0.08);
width: 500px;
margin-top: 6px;
margin-bottom: 6px;
padding: 12px 40px;
}
.interface {
padding: 40px 40px;
}
.slider-labels {
display: flex;
justify-content: space-between;
font-weight: 600;
color: #333;
margin-bottom: 8px;
font-size: 14px;
}
input[type="range"] {
width: 100%;
height: 8px;
border-radius: 4px;
background: linear-gradient(to right, #00f, #f00);
outline: none;
-webkit-appearance: none;
margin-bottom: 32px;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 24px;
height: 24px;
border-radius: 50%;
background: #fff;
border: 3px solid;
cursor: pointer;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
input[type="range"]::-moz-range-thumb {
width: 24px;
height: 24px;
border-radius: 50%;
background: #fff;
border: 3px solid;
cursor: pointer;
box-shadow: 0 2px 4px 4rgba(0,0,0,0.2);
}
.stats {
display: flex;
justify-content: space-between;
gap: 20px;
}
.stat {
flex: 1;
text-align: center;
background: #eee;
border-radius: 12px;
padding: 20px 10px;
}
.stat .label {
font-size: 16px;
color: #444;
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 6px;
}
.stat .value {
font-size: 28px;
font-weight: 700;
color: #222;
}
</style>
</head>
<body>
<h1>Philadelphia Budget Balancer</h1>
<p>by <a href="https://github.com/sparr">sparr</a></p>
<div class="card interface">
<div class="slider-labels">
<span>More Pools</span>
<span>More Police</span>
</div>
<input type="range" id="slider" min="0" max="63" value="63">
<div class="stats">
<div class="stat">
<div class="label">Pools</div>
<div class="value" id="poolsValue">All 63 Closed</div>
</div>
<div class="stat">
<div class="label">Police Officers</div>
<div class="value" id="policeValue">6500</div>
</div>
</div>
</div>
<div class="card">
<p>City budget documents and controller reports establish a total average cost of ~$135k/yr/officer, including base salary, overtime, and benefits.</p>
<p>Approximately 25% of the $84M Parks & Recreation Department budget is spent on pools (maintenance, lifeguards, supplies, other staff), or ~$333k/yr/pool.</p>
</div>
<script>
const slider = document.getElementById('slider');
const policeValue = document.getElementById('policeValue');
const poolsValue = document.getElementById('poolsValue');
const POLICE_MAX = 6500; // at "More Police" end
const POLICE_COST = 135000
const POOLS_MAX = 63; // at "More Pools" end
const POOLS_MIN = 0; // at "More Police" end
const POOLS_COST = 333333
function update() {
// t = 0 -> full "More Pools", t = 1 -> full "More Police"
const t = slider.value / slider.max;
const pools = Math.round(POOLS_MAX - t * (POOLS_MAX - POOLS_MIN));
const police = POLICE_MAX - Math.ceil(pools * POOLS_COST / POLICE_COST);
policeValue.textContent = police.toLocaleString();
if (pools === POOLS_MIN) {
poolsValue.textContent = "All " + POOLS_MAX + " Closed";
} else if (pools === POOLS_MAX) {
poolsValue.textContent = "All " + POOLS_MAX + " Open";
} else {
poolsValue.textContent = pools;
}
}
slider.addEventListener('input', update);
update();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment