mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
O coropleto do Inicio era quase monocromatico porque 0-100% dos validos comprime uma disputa cujo topo estadual e 4,71%. Tres escalas relativas ao proprio candidato, todas em classes discretas: quantis (novo default), padrao proprio (LQ) e posicao no municipio, ao lado de "% dos validos" (B11) e "Total (votos)". Artefato v3: federalRankByIbgeCode com a colocacao entre todos os candidatos com votos > 0 na geografia (2014/2018/2022), chaveado por ibgeCode porque e o que o mapa desenha. Fica no artefato commitado, nao em query de request, que varreria ~100 mil linhas por ano para um dado imutavel. 534 -> 623 KB (orcamento 700 KB). LQ virou 5 classes nas ancoras do E10, nao diverging: o plano pedia as duas coisas e se contradizia. Vermelho x azul continua significando "Solla x adversario" e segue exclusivo do compare. computeAggregateTerritorialClass classifica um grupo de slugs como um territorio so, somando insumos e rodando o mesmo classificador (LQ e razao; a media de razoes nao e a razao das somas) - o E12 herda o helper. TERRITORIAL_CLASS_ANCHORS mudou para src/lib/territorialClassAnchors.ts para nao arrastar o artefato TSE ao bundle do cliente. Quantis sobre o escopo de acesso do usuario, degradando para 3 classes abaixo de 10 municipios com a legenda declarando a contagem efetiva. Rank indisponivel em 2026 (dado TSE); LQ em 2026 reusa o padrao estadual de 2022. Bolhas opcionais por validos projetados (area proporcional ao valor, cor da classe E10, interactive: false). 417 marcadores medidos antes de otimizar - nao derrubaram o frame, entao o corte para top-K nao foi feito. Sem migration, sem collection, sem server action; bundle client de /campanha byte a byte igual.
162 lines
6.8 KiB
TypeScript
162 lines
6.8 KiB
TypeScript
import { statSync } from 'node:fs'
|
|
import { join } from 'node:path'
|
|
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
import {
|
|
FEDERAL_BASELINE_CANDIDATE_NUMBER,
|
|
federalBaselineMunicipalitySlugs,
|
|
getFederalCompetitiveRank,
|
|
getMunicipalityFederalBaseline,
|
|
} from '@/lib/bahiaElectionAggregates'
|
|
import {
|
|
BASELINE_TICKET_2022,
|
|
ELECTION_YEAR_2022,
|
|
HISTORICAL_SERIES_YEARS,
|
|
} from '@/lib/electionResults'
|
|
import { municipalityCatalog } from '@/lib/municipalityCatalog'
|
|
|
|
const ARTIFACT_PATH = join(process.cwd(), 'src/lib/electionAggregates/bahia-federal-baseline.json')
|
|
|
|
/**
|
|
* Pins the committed election-aggregate artifact to the municipality catalog.
|
|
* If either changes shape (new remodel, new TSE scope), regenerate with
|
|
* `pnpm build:election-aggregates` — a drift here means the map would render
|
|
* zeros silently.
|
|
*/
|
|
describe('election aggregates artifact', () => {
|
|
it('covers exactly the municipality catalog slugs', () => {
|
|
const artifactSlugs = new Set(federalBaselineMunicipalitySlugs())
|
|
const catalogSlugs = new Set(municipalityCatalog.map((entry) => entry.slug))
|
|
|
|
expect(artifactSlugs.size).toBe(catalogSlugs.size)
|
|
for (const slug of catalogSlugs) {
|
|
expect(artifactSlugs.has(slug)).toBe(true)
|
|
}
|
|
})
|
|
|
|
it('is generated for the baseline ticket candidate', () => {
|
|
expect(FEDERAL_BASELINE_CANDIDATE_NUMBER).toBe(BASELINE_TICKET_2022.candidate.candidateNumber)
|
|
})
|
|
|
|
it('has every historical year populated with plausible statewide totals', () => {
|
|
for (const year of HISTORICAL_SERIES_YEARS) {
|
|
let candidateTotal = 0
|
|
let validTotal = 0
|
|
for (const slug of federalBaselineMunicipalitySlugs()) {
|
|
const baseline = getMunicipalityFederalBaseline(slug)
|
|
const votes = baseline.votesByYear[String(year)]
|
|
const valid = baseline.validVotesByYear[String(year)]
|
|
expect(votes).toBeTypeOf('number')
|
|
expect(valid).toBeTypeOf('number')
|
|
expect(votes).toBeGreaterThanOrEqual(0)
|
|
expect(valid).toBeGreaterThanOrEqual(votes > 0 ? 1 : 0)
|
|
candidateTotal += votes ?? 0
|
|
validTotal += valid ?? 0
|
|
}
|
|
// A statewide federal-deputy campaign always lands in the 5-7 digit range.
|
|
expect(candidateTotal).toBeGreaterThan(10_000)
|
|
expect(validTotal).toBeGreaterThan(candidateTotal)
|
|
}
|
|
})
|
|
|
|
it('returns an empty baseline for unknown slugs', () => {
|
|
const baseline = getMunicipalityFederalBaseline('nao-existe')
|
|
expect(baseline.votesByYear).toEqual({})
|
|
expect(baseline.validVotesByYear).toEqual({})
|
|
expect(baseline.campoFederalVotesByYear).toEqual({})
|
|
expect(baseline.federalTallyByYear).toEqual({})
|
|
expect(baseline.majoritarian2022).toBeUndefined()
|
|
})
|
|
|
|
it('has campo federal votes + federal tally for every historical year (v2 fields)', () => {
|
|
for (const year of HISTORICAL_SERIES_YEARS) {
|
|
let campoTotal = 0
|
|
let tallyComparecimentoTotal = 0
|
|
for (const slug of federalBaselineMunicipalitySlugs()) {
|
|
const baseline = getMunicipalityFederalBaseline(slug)
|
|
const campo = baseline.campoFederalVotesByYear[String(year)]
|
|
const tally = baseline.federalTallyByYear[String(year)]
|
|
expect(campo).toBeTypeOf('number')
|
|
expect(campo).toBeGreaterThanOrEqual(0)
|
|
expect(tally).toBeDefined()
|
|
expect(tally.comparecimento).toBeGreaterThanOrEqual(0)
|
|
expect(tally.votosValidos).toBeGreaterThanOrEqual(0)
|
|
campoTotal += campo ?? 0
|
|
tallyComparecimentoTotal += tally?.comparecimento ?? 0
|
|
}
|
|
// The campo (PT + core-left partners) always outpolls Solla alone, and
|
|
// turnout always dwarfs any single candidate's nominal votes.
|
|
expect(campoTotal).toBeGreaterThan(10_000)
|
|
expect(tallyComparecimentoTotal).toBeGreaterThan(campoTotal)
|
|
}
|
|
})
|
|
|
|
it('has 2022 majoritarian (presidente/governador #13) votes+tally for every municipality', () => {
|
|
let presidentTotal = 0
|
|
for (const slug of federalBaselineMunicipalitySlugs()) {
|
|
const baseline = getMunicipalityFederalBaseline(slug)
|
|
const majoritarian = baseline.majoritarian2022
|
|
expect(majoritarian).toBeDefined()
|
|
if (!majoritarian) continue
|
|
expect(majoritarian.president.votes).toBeGreaterThanOrEqual(0)
|
|
expect(majoritarian.governor.votes).toBeGreaterThanOrEqual(0)
|
|
expect(majoritarian.president.comparecimento).toBeGreaterThanOrEqual(
|
|
majoritarian.president.votes,
|
|
)
|
|
presidentTotal += majoritarian.president.votes
|
|
}
|
|
expect(presidentTotal).toBeGreaterThan(10_000)
|
|
// Sanity: the 2022 majoritarian slice must not silently regress to a
|
|
// different election year (only 2022 is seeded/expected here).
|
|
expect(HISTORICAL_SERIES_YEARS).toContain(ELECTION_YEAR_2022)
|
|
})
|
|
|
|
it('has a plausible competitive placement per IBGE municipality (v3 field)', () => {
|
|
const ibgeCodes = new Set(municipalityCatalog.map((entry) => entry.ibgeCode))
|
|
let placed = 0
|
|
|
|
for (const ibgeCode of ibgeCodes) {
|
|
for (const year of HISTORICAL_SERIES_YEARS) {
|
|
const placement = getFederalCompetitiveRank(ibgeCode, year)
|
|
// Absent is legitimate: he took no votes in that municipality that
|
|
// year (351/417 municipalities placed in 2014, 416/417 in 2022).
|
|
if (!placement) continue
|
|
placed += 1
|
|
expect(placement.rank).toBeGreaterThanOrEqual(1)
|
|
expect(placement.candidates).toBeGreaterThanOrEqual(placement.rank)
|
|
}
|
|
}
|
|
|
|
// A statewide campaign places in most municipalities in most years.
|
|
expect(placed).toBeGreaterThan(ibgeCodes.size * 2)
|
|
})
|
|
|
|
it('gives Salvador one whole-city placement, not one per zone municipality', () => {
|
|
const salvadorZones = municipalityCatalog.filter((entry) => entry.kind === 'zona')
|
|
const salvadorCodes = new Set(salvadorZones.map((entry) => entry.ibgeCode))
|
|
|
|
// The 19 zone municipalities share Salvador's IBGE code, which is why the
|
|
// placement is keyed by code: "which place did he come in" only has an
|
|
// answer for the whole city.
|
|
expect(salvadorZones.length).toBeGreaterThan(1)
|
|
expect(salvadorCodes.size).toBe(1)
|
|
|
|
const [salvadorCode] = salvadorCodes
|
|
expect(getFederalCompetitiveRank(salvadorCode, ELECTION_YEAR_2022)).not.toBeNull()
|
|
})
|
|
|
|
it('has no placement for an unknown IBGE code', () => {
|
|
expect(getFederalCompetitiveRank('0000000', ELECTION_YEAR_2022)).toBeNull()
|
|
})
|
|
|
|
it('stays under the committed artifact byte budget', () => {
|
|
const { size } = statSync(ARTIFACT_PATH)
|
|
// v1 (votes + valid votes only) was ~96 KB; v2 adds campo votes, federal
|
|
// tally and the 2022 majoritarian slice, measured at ~522 KB; v3 adds the
|
|
// per-IBGE competitive placement, measured at ~613 KB — budget with
|
|
// headroom, not a precise pin, so future fields don't require touching
|
|
// this test.
|
|
expect(size).toBeLessThan(700 * 1024)
|
|
})
|
|
})
|