Simplify E12+ Metropolitano peers extraction.

Centralize sub-row slug helper, drop one-line filter wrappers, and scope E12 sub-row rollups to the Metropolitano region inputs.
This commit is contained in:
Francisco Ignácio Fontoura Solla 2026-07-29 08:24:19 -03:00
parent be2cbfbb43
commit 2b3d688be3
5 changed files with 29 additions and 35 deletions

View file

@ -6,7 +6,11 @@
* class slugs, and intra-TI capture benchmark (T4).
*/
import { municipalityCatalog, type MunicipalityCatalogEntry } from '@/lib/municipalityCatalog'
import {
getMunicipalityCatalogEntry,
municipalityCatalog,
type MunicipalityCatalogEntry,
} from '@/lib/municipalityCatalog'
export const METROPOLITANO_REGION = 'Metropolitano de Salvador'
export const SALVADOR_CITY = 'Salvador'
@ -35,6 +39,16 @@ export const filterSalvadorSubgroup = <T extends MetropolitanoGeo>(items: Readon
export const filterDemaisRmsSubgroup = <T extends MetropolitanoGeo>(items: ReadonlyArray<T>): T[] =>
items.filter(isDemaisRmsSubMunicipality)
export const slugsForMetropolitanoSubRowLabel = <T extends MetropolitanoGeo & { slug: string }>(
inputs: ReadonlyArray<T>,
label: string,
): string[] => {
const filtered = isSalvadorMetropolitanoSubRowLabel(label)
? filterSalvadorSubgroup(inputs)
: filterDemaisRmsSubgroup(inputs)
return filtered.map((input) => input.slug)
}
const peersForCatalogEntry = (
entry: MunicipalityCatalogEntry,
): ReadonlyArray<MunicipalityCatalogEntry> => {
@ -47,9 +61,9 @@ const peersForCatalogEntry = (
: municipalityCatalog.filter(isDemaisRmsSubMunicipality)
}
/** Catalog peers for one slug — TI-wide, or Metropolitano Salvador vs demais RMS. */
/** TI-wide peers, or Metropolitano Salvador vs demais RMS. */
export const catalogPeersForSlug = (slug: string): ReadonlyArray<MunicipalityCatalogEntry> => {
const entry = municipalityCatalog.find((row) => row.slug === slug)
const entry = getMunicipalityCatalogEntry(slug)
if (!entry) return []
return peersForCatalogEntry(entry)
}

View file

@ -4,11 +4,7 @@ import type { Payload } from 'payload'
import { cache } from 'react'
import { getMunicipalityFederalBaseline } from '@/lib/bahiaElectionAggregates'
import {
filterDemaisRmsSubgroup,
filterSalvadorSubgroup,
isSalvadorMetropolitanoSubRowLabel,
} from '@/lib/metropolitanoTerritoryPeers'
import { slugsForMetropolitanoSubRowLabel } from '@/lib/metropolitanoTerritoryPeers'
import { DEFAULT_VOTE_ESTIMATE_SCENARIO, type VoteEstimateScenario } from '@/lib/voteEstimate'
import type { CampaignUser, Municipality, User } from '@/payload-types'
import { loadMunicipalityGoalCoverageBundle } from '@/utilities/municipality/municipalityGoalAccount'
@ -32,16 +28,6 @@ type MunicipalityDoc = Pick<
type TerritoryReader = CampaignUser | User
const slugsForMetropolitanoSubRow = (
inputs: ReadonlyArray<TerritoryMunicipalityInput>,
label: string,
): string[] => {
const filtered = isSalvadorMetropolitanoSubRowLabel(label)
? filterSalvadorSubgroup(inputs)
: filterDemaisRmsSubgroup(inputs)
return filtered.map((input) => input.slug)
}
const attachTerritorialClasses = (
inputs: ReadonlyArray<TerritoryMunicipalityInput>,
rows: TerritoryOverviewRow[],
@ -53,7 +39,7 @@ const attachTerritorialClasses = (
const subRows = row.subRows?.map((subRow) => ({
...subRow,
territorialClass: computeAggregateTerritorialClass(
slugsForMetropolitanoSubRow(inputs, subRow.label),
slugsForMetropolitanoSubRowLabel(inputs, subRow.label),
),
}))
return {

View file

@ -2,9 +2,7 @@
* E12 — intra-TI capture benchmark (T4) for municipality detail.
*
* Pure over the committed TSE artifact + `municipalityCatalog` (client-safe).
* Peers share the same Território de Identidade; Metropolitano de Salvador
* splits Salvador (all zone slugs) vs demais RMS municipalities — same rule as
* E17/E12 rollups.
* Peers share the same Território de Identidade (`catalogPeersForSlug`).
*/
import { getMunicipalityFederalBaseline } from '@/lib/bahiaElectionAggregates'

View file

@ -242,14 +242,6 @@ const inputsInRegion = (
region: string,
): TerritoryMunicipalityInput[] => inputs.filter((input) => input.region === region)
const metropolitanoSalvadorInputs = (
inputs: ReadonlyArray<TerritoryMunicipalityInput>,
): TerritoryMunicipalityInput[] => filterSalvadorSubgroup(inputs)
const metropolitanoDemaisInputs = (
inputs: ReadonlyArray<TerritoryMunicipalityInput>,
): TerritoryMunicipalityInput[] => filterDemaisRmsSubgroup(inputs)
/**
* Computes the 27-TI comparative rollup. Rows are returned in first-seen order
* (catalog order when fed from the loader); the Metropolitano de Salvador row
@ -292,13 +284,13 @@ export const computeTerritoryRollup = (
METROPOLITANO_SALVADOR_SUB_ROW_LABEL,
metropolitanoSalvador,
stateTotal2022,
computeTerritoryE12Rollup(metropolitanoSalvadorInputs(inputs)),
computeTerritoryE12Rollup(filterSalvadorSubgroup(regionInputs)),
),
finalizeSubRow(
METROPOLITANO_DEMAIS_SUB_ROW_LABEL,
metropolitanoDemais,
stateTotal2022,
computeTerritoryE12Rollup(metropolitanoDemaisInputs(inputs)),
computeTerritoryE12Rollup(filterDemaisRmsSubgroup(regionInputs)),
),
]
}

View file

@ -1,5 +1,9 @@
import { describe, expect, it } from 'vitest'
import {
METROPOLITANO_DEMAIS_SUB_ROW_LABEL,
METROPOLITANO_SALVADOR_SUB_ROW_LABEL,
} from '@/lib/metropolitanoTerritoryPeers'
import {
computeTerritoryE12Rollup,
computeTerritoryRollup,
@ -134,8 +138,8 @@ describe('computeTerritoryRollup', () => {
expect(metro.subRows).toHaveLength(2)
const salvador = metro.subRows![0]
const demais = metro.subRows![1]
expect(salvador.label).toBe('Salvador (19 zonas)')
expect(demais.label).toBe('Demais municípios da RMS')
expect(salvador.label).toBe(METROPOLITANO_SALVADOR_SUB_ROW_LABEL)
expect(demais.label).toBe(METROPOLITANO_DEMAIS_SUB_ROW_LABEL)
expect(salvador.municipalityCount).toBe(1)
expect(demais.municipalityCount).toBe(1)
// Sub-rows sum to the Metropolitano total.
@ -187,7 +191,7 @@ describe('flattenTerritoryRows', () => {
expect(flattened[metroIndex + 1]).toMatchObject({
variant: 'sub',
parentRegion: 'Metropolitano de Salvador',
label: 'Salvador (19 zonas)',
label: METROPOLITANO_SALVADOR_SUB_ROW_LABEL,
})
})
})