teqo/src/lib/campoParties.ts

63 lines
3.2 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { normalizePartySigla } from '@/lib/electionPartySpectrum'
/**
* Curated "campo" (Solla/PT political field) parties by year, used for the
* deputado-federal "share intracampo" diagnostic (E8): of the votes that went
* to the field, how many went to Solla specifically. This is NOT the same
* concept as `electionPartySpectrum.ts` (ideological esquerda/centro/direita
* bucket, from the Bolognesi et al. expert survey) — every entry here MUST
* also be in the `esquerda` bucket (enforced by
* `tests/unit/campoParties.unit.spec.ts`), but the reverse isn't required:
* plenty of `esquerda`-bucket parties are not part of this specific ticket's
* field in a given year.
*
* Deliberately NOT inferred from the raw TSE `coalition` string on
* `electionCandidateVote`: Brazilian proportional "coligações" bundle
* opportunistic, ideologically unrelated allies purely to maximize the
* quotient. Confirmed against the locally seeded 2014/2018 data — Solla's own
* registered coalition that year also included PP, PR, PSD, PTB (2014) /
* PODE, PP, PR, PSD (2018), none of which belong in the political field.
*
* Sourcing:
* - 2014: coalition "MAIS MUDANÇAS, NOVAS CONQUISTAS" (BA, deputado federal) —
* PT's core-left partners inside it: PC do B, PDT.
* - 2018: coalition "FRENTE DO TRABALHO POR TODA BAHIA" (BA, deputado
* federal) — PT's core-left partners inside it: PC do B, PSB.
* - 2022: PT ran under the "Federação Brasil da Esperança — FE Brasil"
* (PT/PC do B/PV), a permanent partisan federation (TSE registered it
* 2022-05-24) — not a temporary coalition. Verified via TSE candidate
* filing (Folha "Ficha do candidato" 2022) and press coverage (Estadão,
* Bahia Notícias). PSB backed the same governismo ticket for governor that
* year but ran its own deputado-federal slate outside the federation, so it
* is excluded from the 2022 federal-deputy field (would double count a
* separate slate as "ours").
* - 2026: FE Brasil is legally bound to stay unified through the end of the
* 2023–2026 mandate, so it carries over unchanged. Revisit once 2026
* deputado-federal candidacies are registered (TSE `consulta_cand_2026`).
*/
export type CampoElectionYear = 2014 | 2018 | 2022 | 2026
const CAMPO_PARTIES_BY_YEAR: Readonly<Record<CampoElectionYear, readonly string[]>> = {
2014: ['PT', 'PCDOB', 'PDT'],
2018: ['PT', 'PCDOB', 'PSB'],
2022: ['PT', 'PCDOB', 'PV'],
2026: ['PT', 'PCDOB', 'PV'],
}
export const CAMPO_ELECTION_YEARS = Object.keys(CAMPO_PARTIES_BY_YEAR).map(
Number,
) as CampoElectionYear[]
export const isCampoElectionYear = (year: number): year is CampoElectionYear =>
(CAMPO_ELECTION_YEARS as readonly number[]).includes(year)
/** Campo party siglas (already normalized) for one year, or [] for an unknown year. */
export const campoPartiesForYear = (year: number): readonly string[] =>
isCampoElectionYear(year) ? CAMPO_PARTIES_BY_YEAR[year] : []
/** Whether a TSE party sigla belongs to the curated field for that year. */
export const isCampoParty = (party: string | null | undefined, year: number): boolean => {
const normalized = normalizePartySigla(party)
if (!normalized) return false
return campoPartiesForYear(year).includes(normalized)
}