mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
- ~190 findings zerados: knip --fix (grafo corrigido: tests como entries, migrations como consumidores) + delecao guardada dos orfaos (git grep -w antes de deletar) + reparos manuais dos corpos arrow pendurados - pecas nao usadas do kit ui deletadas (PaginationLink/Next/Previous, familias Sidebar/Combobox/Sheet/Drawer/Dialog etc.) - shadcn add recoloca se precisar - acoes mortas removidas (updateCampaignDemandDetails*, *Record orfaos), schemas/tipos mortos (campaignDemandDetailsUpdateSchema, Contact do zod), helpers mortos - tipos de eleicao derivam direto das *_OPTIONS (consts intermediarias eliminadas) - knip.json: rules exports/types/enumMembers=error, duplicates=off (unicos hits: 6 aliases deliberados canUpdateX=canReadX); hints aplicados (payload.config entry redundante, ignores de tsx/sharp/playwright/payload-types desnecessarios) - ledger: linha P2 dos unused exports fechada
73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
/**
|
||
* "Evolução de votos" — numeric trend derived from the candidate's federal
|
||
* series (2014/2018/2022). Distinct concept from the manually recorded
|
||
* "Tendência política" (`municipality.politicalTrend`). Survivor of the
|
||
* nucleus-era `electionInsights.ts`, gutted in Pass 2 W4a — the deleted
|
||
* absolute-threshold insight clusters are superseded by E10's relative
|
||
* territorial classification (see `docs/plans/classificacao-territorial-relativa.md`).
|
||
*/
|
||
const VOTE_TREND_STABLE_BAND = 0.1
|
||
|
||
type VoteTrendStatus = 'decline' | 'stable' | 'increase' | 'noBaseline'
|
||
|
||
export type VoteTrendSeries = {
|
||
y2014: number
|
||
y2018: number
|
||
y2022: number
|
||
}
|
||
|
||
export type VoteTrendResult = {
|
||
status: VoteTrendStatus
|
||
message: string
|
||
ratio: number | null
|
||
}
|
||
|
||
type TrendPair = { fromVotes: number; toVotes: number; fromYear: number; toYear: number }
|
||
|
||
const trendPairsByPriority = (series: VoteTrendSeries): TrendPair[] => [
|
||
{ fromVotes: series.y2018, toVotes: series.y2022, fromYear: 2018, toYear: 2022 },
|
||
{ fromVotes: series.y2014, toVotes: series.y2018, fromYear: 2014, toYear: 2018 },
|
||
{ fromVotes: series.y2014, toVotes: series.y2022, fromYear: 2014, toYear: 2022 },
|
||
]
|
||
|
||
/**
|
||
* Classify vote trend from the federal candidate series (2014/2018/2022).
|
||
* Uses the most recent consecutive pair with votes in both years; ±10% → stable.
|
||
*/
|
||
export const computeVoteTrend = (series: VoteTrendSeries): VoteTrendResult => {
|
||
for (const pair of trendPairsByPriority(series)) {
|
||
if (pair.fromVotes <= 0 || pair.toVotes <= 0) continue
|
||
|
||
const ratio = pair.toVotes / pair.fromVotes
|
||
const change = ratio - 1
|
||
const percent = Math.round(Math.abs(change) * 100)
|
||
|
||
if (Math.abs(change) <= VOTE_TREND_STABLE_BAND) {
|
||
return {
|
||
status: 'stable',
|
||
ratio,
|
||
message: `Mantém (${pair.fromYear}→${pair.toYear}, variação de ${percent}%)`,
|
||
}
|
||
}
|
||
|
||
if (change > VOTE_TREND_STABLE_BAND) {
|
||
return {
|
||
status: 'increase',
|
||
ratio,
|
||
message: `Aumento (${pair.fromYear}→${pair.toYear}, +${percent}%)`,
|
||
}
|
||
}
|
||
|
||
return {
|
||
status: 'decline',
|
||
ratio,
|
||
message: `Queda (${pair.fromYear}→${pair.toYear}, −${percent}%)`,
|
||
}
|
||
}
|
||
|
||
return {
|
||
status: 'noBaseline',
|
||
ratio: null,
|
||
message: 'Sem série histórica suficiente para tendência',
|
||
}
|
||
}
|