fix: derive missing A3 batch metrics

This commit is contained in:
2026-04-23 17:41:33 +08:00
parent fb45f0cea8
commit b3bcc2af45
2 changed files with 121 additions and 2 deletions
+87 -2
View File
@@ -76,11 +76,13 @@ export function mapBackendMetricsSearchResponse(payload: unknown): BackendMetric
return [
{
a3IncreaseCount: formatDecimalValue(row.avg_a3_increase_cnt),
a3IncreaseCount: formatDecimalValue(
readAverageA3IncreaseCount(row)
),
afterViewSearchCount: formatDecimalValue(row.avg_after_view_search_cnt),
afterViewSearchRate: formatRateValue(row.avg_after_view_search_rate),
cpSearch: formatDecimalValue(row.cp_search),
cpa3: formatDecimalValue(row.cpa3),
cpa3: formatDecimalValue(readCpa3Value(row)),
newA3Rate: formatRateValue(row.avg_new_a3_rate),
starId: row.star_id
}
@@ -88,6 +90,84 @@ export function mapBackendMetricsSearchResponse(payload: unknown): BackendMetric
});
}
function readAverageA3IncreaseCount(row: Record<string, unknown>): number | null {
const directAverage = readFiniteNumber(row.avg_a3_increase_cnt);
if (directAverage !== null) {
return directAverage;
}
const totalNewA3 = readTotalNewA3Value(row);
const videoCount =
readFiniteNumber(row.video_count) ?? readNestedVideoCount(row.videos);
if (totalNewA3 === null || videoCount === null || videoCount <= 0) {
return null;
}
return totalNewA3 / videoCount;
}
function readCpa3Value(row: Record<string, unknown>): number | null {
const directCpa3 = readFiniteNumber(row.cpa3);
if (directCpa3 !== null) {
return directCpa3;
}
const totalCost = readFiniteNumber(row.total_estimated_video_cost);
const totalNewA3 = readTotalNewA3Value(row);
if (totalCost === null || totalNewA3 === null || totalNewA3 <= 0) {
return null;
}
return totalCost / totalNewA3;
}
function readTotalNewA3Value(row: Record<string, unknown>): number | null {
const derivedFromTotals = deriveTotalNewA3FromTotals(row);
if (derivedFromTotals !== null) {
return derivedFromTotals;
}
return deriveTotalNewA3FromVideos(row.videos);
}
function deriveTotalNewA3FromTotals(row: Record<string, unknown>): number | null {
const totalPlayCount = readFiniteNumber(row.total_play_cnt);
const averageNewA3Rate = readFiniteNumber(row.avg_new_a3_rate);
if (totalPlayCount === null || averageNewA3Rate === null) {
return null;
}
return totalPlayCount * averageNewA3Rate;
}
function deriveTotalNewA3FromVideos(value: unknown): number | null {
if (!Array.isArray(value)) {
return null;
}
let total = 0;
let hasFiniteValue = false;
value.forEach((video) => {
if (!isRecord(video)) {
return;
}
const newA3 = readFiniteNumber(video.new_a3);
if (newA3 === null) {
return;
}
hasFiniteValue = true;
total += newA3;
});
return hasFiniteValue ? total : null;
}
function readNestedVideoCount(value: unknown): number | null {
return Array.isArray(value) ? value.length : null;
}
function readResponseRows(payload: unknown): unknown[] | null {
if (!isRecord(payload) || payload.success !== true) {
return null;
@@ -130,3 +210,8 @@ async function defaultFetch(input: string, init?: RequestInit) {
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}
function readFiniteNumber(value: unknown): number | null {
const number = typeof value === "number" ? value : Number(value);
return Number.isFinite(number) ? number : null;
}