Skip to content

Commit 7a54e82

Browse files
committed
Revert globe coloring to old algorithm
1 parent 3a5153f commit 7a54e82

1 file changed

Lines changed: 20 additions & 7 deletions

File tree

  • apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)

apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/(overview)/globe.tsx

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -696,14 +696,29 @@ function GlobeSectionInner({ countryData, totalUsers, activeUsersByCountry, sate
696696
}, [cameraDistance, shouldShowGlobe, globeSize]);
697697

698698

699-
// Heatmap-style coloring: log-scaled user counts, normalized with a steeper curve so neighboring
700-
// countries with different volumes (e.g. US vs Canada vs Mexico) don't all land in the same band.
699+
const totalUsersInCountries = Object.values(countryData).reduce((acc, curr) => acc + curr, 0);
700+
const totalPopulationInCountries = countries.features.reduce((acc, curr) => acc + curr.properties.POP_EST, 0);
701+
const oneSided95PercentZScore = 1.645;
702+
703+
const getCountryColorValue = (countryUsers: number, countryPopulation: number): number | null => {
704+
if (countryUsers === 0) return null;
705+
706+
const observedProportion = countryUsers / totalUsersInCountries;
707+
const standardError = Math.sqrt(observedProportion * (1 - observedProportion) / totalUsersInCountries);
708+
const proportionLowerBound = Math.max(0, observedProportion - oneSided95PercentZScore * standardError);
709+
const populationProportion = countryPopulation / totalPopulationInCountries;
710+
const likelihoodRatio = proportionLowerBound / populationProportion;
711+
712+
return Math.max(0, Math.log(100 * likelihoodRatio));
713+
};
714+
715+
// Heatmap-style coloring: population-normalized user concentration, with a
716+
// confidence lower bound so tiny samples don't make a country look too strong.
701717
const numericColorValues = countries.features
702718
.map((country) => {
703719
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
704720
const countryUsers = countryData[country.properties.ISO_A2_EH] ?? 0;
705-
if (countryUsers === 0) return null;
706-
return Math.log1p(countryUsers);
721+
return getCountryColorValue(countryUsers, country.properties.POP_EST);
707722
})
708723
.filter((v): v is number => v !== null)
709724
.sort((a, b) => a - b);
@@ -720,9 +735,7 @@ function GlobeSectionInner({ countryData, totalUsers, activeUsersByCountry, sate
720735
const colorValues = new Map(countries.features.map((country) => {
721736
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
722737
const countryUsers = countryData[country.properties.ISO_A2_EH] ?? 0;
723-
if (countryUsers === 0) return [country.properties.ISO_A2_EH, null] as const;
724-
725-
const colorValue = Math.log1p(countryUsers);
738+
const colorValue = getCountryColorValue(countryUsers, country.properties.POP_EST);
726739
return [country.properties.ISO_A2_EH, colorValue] as const;
727740
}));
728741
const maxColorValue = spreadMax;

0 commit comments

Comments
 (0)