wip
This commit is contained in:
141
packages/db/src/engine/format.ts
Normal file
141
packages/db/src/engine/format.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import {
|
||||
average,
|
||||
getPreviousMetric,
|
||||
max,
|
||||
min,
|
||||
round,
|
||||
slug,
|
||||
sum,
|
||||
} from '@openpanel/common';
|
||||
import { alphabetIds } from '@openpanel/constants';
|
||||
import type { FinalChart } from '@openpanel/validation';
|
||||
import type { ConcreteSeries } from './types';
|
||||
|
||||
/**
|
||||
* Format concrete series into FinalChart format (backward compatible)
|
||||
* TODO: Migrate frontend to use cleaner ChartResponse format
|
||||
*/
|
||||
export function format(
|
||||
concreteSeries: ConcreteSeries[],
|
||||
definitions: Array<{
|
||||
id?: string;
|
||||
type: 'event' | 'formula';
|
||||
displayName?: string;
|
||||
formula?: string;
|
||||
name?: string;
|
||||
}>,
|
||||
includeAlphaIds: boolean,
|
||||
previousSeries: ConcreteSeries[] | null = null,
|
||||
): FinalChart {
|
||||
const series = concreteSeries.map((cs) => {
|
||||
// Find definition for this series
|
||||
const definition = definitions[cs.definitionIndex];
|
||||
const alphaId = includeAlphaIds
|
||||
? alphabetIds[cs.definitionIndex]
|
||||
: undefined;
|
||||
|
||||
// Build display name with optional alpha ID
|
||||
let displayName: string[];
|
||||
|
||||
// Replace the first name (which is the event name) with the display name if it exists
|
||||
const names = cs.name.slice(0);
|
||||
if (cs.definition.displayName) {
|
||||
names.splice(0, 1, cs.definition.displayName);
|
||||
}
|
||||
// Add the alpha ID to the first name if it exists
|
||||
if (alphaId) {
|
||||
displayName = [`(${alphaId}) ${names[0]}`, ...names.slice(1)];
|
||||
} else {
|
||||
displayName = names;
|
||||
}
|
||||
|
||||
// Calculate metrics for this series
|
||||
const counts = cs.data.map((d) => d.count);
|
||||
const metrics = {
|
||||
sum: sum(counts),
|
||||
average: round(average(counts), 2),
|
||||
min: min(counts),
|
||||
max: max(counts),
|
||||
count: cs.data.find((item) => !!item.total_count)?.total_count,
|
||||
};
|
||||
|
||||
// Build event object for compatibility
|
||||
const eventName =
|
||||
definition?.type === 'formula'
|
||||
? definition.displayName || definition.formula || 'Formula'
|
||||
: definition?.name || cs.context.event || 'unknown';
|
||||
|
||||
// Find matching previous series
|
||||
const previousSerie = previousSeries?.find(
|
||||
(ps) =>
|
||||
ps.definitionIndex === cs.definitionIndex &&
|
||||
ps.name.slice(1).join(':::') === cs.name.slice(1).join(':::'),
|
||||
);
|
||||
|
||||
return {
|
||||
id: cs.id,
|
||||
names: displayName,
|
||||
// TODO: Do we need this now?
|
||||
event: {
|
||||
id: definition?.id,
|
||||
name: eventName,
|
||||
breakdowns: cs.context.breakdowns,
|
||||
},
|
||||
metrics: {
|
||||
...metrics,
|
||||
...(previousSerie
|
||||
? {
|
||||
previous: {
|
||||
sum: getPreviousMetric(
|
||||
metrics.sum,
|
||||
sum(previousSerie.data.map((d) => d.count)),
|
||||
),
|
||||
average: getPreviousMetric(
|
||||
metrics.average,
|
||||
round(average(previousSerie.data.map((d) => d.count)), 2),
|
||||
),
|
||||
min: getPreviousMetric(
|
||||
metrics.min,
|
||||
min(previousSerie.data.map((d) => d.count)),
|
||||
),
|
||||
max: getPreviousMetric(
|
||||
metrics.max,
|
||||
max(previousSerie.data.map((d) => d.count)),
|
||||
),
|
||||
count: getPreviousMetric(
|
||||
metrics.count ?? 0,
|
||||
previousSerie.data.find((item) => !!item.total_count)
|
||||
?.total_count ?? null,
|
||||
),
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
data: cs.data.map((item, index) => ({
|
||||
date: item.date,
|
||||
count: item.count,
|
||||
previous: previousSerie?.data[index]
|
||||
? getPreviousMetric(
|
||||
item.count,
|
||||
previousSerie.data[index]?.count ?? null,
|
||||
)
|
||||
: undefined,
|
||||
})),
|
||||
};
|
||||
});
|
||||
|
||||
// Calculate global metrics
|
||||
const allValues = concreteSeries.flatMap((cs) => cs.data.map((d) => d.count));
|
||||
const globalMetrics = {
|
||||
sum: sum(allValues),
|
||||
average: round(average(allValues), 2),
|
||||
min: min(allValues),
|
||||
max: max(allValues),
|
||||
count: undefined as number | undefined,
|
||||
};
|
||||
|
||||
return {
|
||||
series,
|
||||
metrics: globalMetrics,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user