/* Coffermap core: pure helpers shared by the pages and the Node tests. © 2026 CyberMax. All rights reserved. */ (function (root) { 'use strict'; function money(v) { v = Number(v) || 0; var a = Math.abs(v); if (a >= 1e12) return '$' + (v / 1e12).toFixed(2) + 'T'; if (a >= 1e9) return '$' + (v / 1e9).toFixed(1) + 'B'; if (a >= 1e6) return '$' + (v / 1e6).toFixed(1) + 'M'; if (a >= 1e3) return '$' + (v / 1e3).toFixed(1) + 'K'; return '$' + Math.round(v).toLocaleString('en-US'); } function dollars(v) { return '$' + Math.round(Number(v) || 0).toLocaleString('en-US'); } function perCap(amount, pop) { return pop ? amount / pop : null; } // compact data.json county row [fips, st, name, contracts, grants, pop] -> object function county(r) { return { fips: r[0], state: r[1], county: r[2], contracts: r[3], grants: r[4], population: r[5], perCapita: perCap(r[3], r[5]) }; } function state(r) { return { state: r[0], name: r[1], contracts: r[2], grants: r[3], population: r[4], perCapita: perCap(r[2], r[4]) }; } function norm(s) { return String(s || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/[^a-z0-9 ]/g, ' ').replace(/\s+/g, ' ').trim(); } function filterCounties(list, q, st) { var toks = norm(q).split(' ').filter(Boolean); return list.filter(function (c) { if (st && c.state !== st) return false; var hay = ' ' + norm(c.county + ' ' + c.state) + ' '; return toks.every(function (t) { return hay.indexOf(t) >= 0; }); }); } function sortBy(list, key, desc) { return list.slice().sort(function (a, b) { var x = a[key], y = b[key]; if (x == null) return 1; if (y == null) return -1; var r = typeof x === 'string' ? x.localeCompare(y) : x - y; return desc ? -r : r; }); } function csvCell(v) { var s = v == null ? '' : String(v); if (/^[=+\-@]/.test(s)) s = "'" + s; return /[",\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s; } function toCsv(rows, cols) { return [cols.join(',')].concat(rows.map(function (r) { return cols.map(function (c) { return csvCell(r[c]); }).join(','); })).join('\r\n') + '\r\n'; } // USAspending county-level top contractors request body (FY = federal fiscal year) function countyTopBody(st, countyCode, fy, limit) { return { filters: { time_period: [{ start_date: (fy - 1) + '-10-01', end_date: fy + '-09-30' }], award_type_codes: ['A', 'B', 'C', 'D'], place_of_performance_locations: [{ country: 'USA', state: st, county: countyCode }] }, limit: limit || 10, page: 1 }; } function titleCase(s) { return String(s || '').toLowerCase().replace(/\b([a-z])/g, function (m) { return m.toUpperCase(); }).replace(/\b(Llc|Inc|Lp|Llp|Usa|Us|Ii|Iii|Jv)\b/g, function (m) { return m.toUpperCase(); }); } var api = { money: money, dollars: dollars, perCap: perCap, county: county, state: state, filterCounties: filterCounties, sortBy: sortBy, toCsv: toCsv, csvCell: csvCell, countyTopBody: countyTopBody, titleCase: titleCase, norm: norm }; if (typeof module !== 'undefined' && module.exports) module.exports = api; else root.FF = api; })(typeof window !== 'undefined' ? window : this);