Move model views out of the dashboard utility bulk
Probability and multi-model view adapters were still embedded in dashboard-utils even though table, panel, modal, and city-card views use them as small pure selectors. This moves them into model-utils and keeps dashboard-utils re-export compatibility. Constraint: Preserve model/probability return shapes and existing fallback behavior. Rejected: Merge model-utils with chart-utils | model selectors and chart data preparation change at different rates. Confidence: high Scope-risk: narrow Reversibility: clean Tested: TypeScript diagnostics for model-utils, dashboard-utils, and PanelSections Tested: npm run build Not-tested: Bundle analyzer size comparison.
This commit is contained in:
@@ -26,10 +26,9 @@ import {
|
|||||||
import { getTemperatureChartData } from "@/lib/chart-utils";
|
import { getTemperatureChartData } from "@/lib/chart-utils";
|
||||||
import {
|
import {
|
||||||
getFutureModalView,
|
getFutureModalView,
|
||||||
getModelView,
|
|
||||||
getProbabilityView,
|
|
||||||
getWeatherSummary,
|
getWeatherSummary,
|
||||||
} from "@/lib/dashboard-utils";
|
} from "@/lib/dashboard-utils";
|
||||||
|
import { getModelView, getProbabilityView } from "@/lib/model-utils";
|
||||||
import { getTodayPaceView } from "@/lib/pace-utils";
|
import { getTodayPaceView } from "@/lib/pace-utils";
|
||||||
import { dashboardClient } from "@/lib/dashboard-client";
|
import { dashboardClient } from "@/lib/dashboard-client";
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ import type {
|
|||||||
ScanOpportunityRow,
|
ScanOpportunityRow,
|
||||||
} from "@/lib/dashboard-types";
|
} from "@/lib/dashboard-types";
|
||||||
import { getLocalizedCityName } from "@/lib/dashboard-home-copy";
|
import { getLocalizedCityName } from "@/lib/dashboard-home-copy";
|
||||||
import {
|
import { getModelView, getProbabilityView } from "@/lib/model-utils";
|
||||||
getModelView,
|
|
||||||
getProbabilityView,
|
|
||||||
} from "@/lib/dashboard-utils";
|
|
||||||
import { getTodayPaceView } from "@/lib/pace-utils";
|
import { getTodayPaceView } from "@/lib/pace-utils";
|
||||||
import {
|
import {
|
||||||
formatTemperatureValue,
|
formatTemperatureValue,
|
||||||
|
|||||||
@@ -15,11 +15,10 @@ import {
|
|||||||
import { getTemperatureChartData } from "@/lib/chart-utils";
|
import { getTemperatureChartData } from "@/lib/chart-utils";
|
||||||
import {
|
import {
|
||||||
getHeroMetaItems,
|
getHeroMetaItems,
|
||||||
getModelView,
|
|
||||||
getProbabilityView,
|
|
||||||
getRiskBadgeLabel,
|
getRiskBadgeLabel,
|
||||||
getWeatherSummary,
|
getWeatherSummary,
|
||||||
} from "@/lib/dashboard-utils";
|
} from "@/lib/dashboard-utils";
|
||||||
|
import { getModelView, getProbabilityView } from "@/lib/model-utils";
|
||||||
import {
|
import {
|
||||||
normalizeObservationSourceCode,
|
normalizeObservationSourceCode,
|
||||||
normalizeObservationSourceLabel,
|
normalizeObservationSourceLabel,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
useCityMarketScan,
|
useCityMarketScan,
|
||||||
} from "@/components/dashboard/scan-terminal/use-ai-city-card-data";
|
} from "@/components/dashboard/scan-terminal/use-ai-city-card-data";
|
||||||
import type { CityDetail, ScanOpportunityRow } from "@/lib/dashboard-types";
|
import type { CityDetail, ScanOpportunityRow } from "@/lib/dashboard-types";
|
||||||
import { getModelView } from "@/lib/dashboard-utils";
|
import { getModelView } from "@/lib/model-utils";
|
||||||
import { getTodayPaceView } from "@/lib/pace-utils";
|
import { getTodayPaceView } from "@/lib/pace-utils";
|
||||||
import { formatTemperatureValue } from "@/lib/temperature-utils";
|
import { formatTemperatureValue } from "@/lib/temperature-utils";
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { formatTafMarkerType } from "@/lib/taf-utils";
|
|||||||
import { normalizeHm } from "@/lib/time-utils";
|
import { normalizeHm } from "@/lib/time-utils";
|
||||||
|
|
||||||
export { getTemperatureChartData } from "@/lib/chart-utils";
|
export { getTemperatureChartData } from "@/lib/chart-utils";
|
||||||
|
export { getModelView, getProbabilityView } from "@/lib/model-utils";
|
||||||
export { getTodayPaceView } from "@/lib/pace-utils";
|
export { getTodayPaceView } from "@/lib/pace-utils";
|
||||||
export {
|
export {
|
||||||
formatTemperatureValue,
|
formatTemperatureValue,
|
||||||
@@ -246,56 +247,6 @@ export function getHeroMetaItems(detail: CityDetail, locale: Locale = "zh-CN") {
|
|||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getProbabilityView(detail: CityDetail, targetDate?: string | null) {
|
|
||||||
const date = targetDate || detail.local_date;
|
|
||||||
if (date === detail.local_date) {
|
|
||||||
return {
|
|
||||||
calibrationMode: detail.probabilities?.calibration_mode ?? null,
|
|
||||||
calibrationVersion: detail.probabilities?.calibration_version ?? null,
|
|
||||||
engine: detail.probabilities?.engine ?? null,
|
|
||||||
mu: detail.probabilities?.mu ?? null,
|
|
||||||
probabilities: detail.probabilities?.distribution || [],
|
|
||||||
probabilitiesAll:
|
|
||||||
detail.probabilities?.distribution_all ||
|
|
||||||
detail.probabilities?.distribution ||
|
|
||||||
[],
|
|
||||||
shadowProbabilities: detail.probabilities?.shadow_distribution || [],
|
|
||||||
shadowProbabilitiesAll:
|
|
||||||
detail.probabilities?.shadow_distribution_all ||
|
|
||||||
detail.probabilities?.shadow_distribution ||
|
|
||||||
[],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const daily = detail.multi_model_daily?.[date];
|
|
||||||
return {
|
|
||||||
calibrationMode: null,
|
|
||||||
calibrationVersion: null,
|
|
||||||
engine: null,
|
|
||||||
mu: daily?.deb?.prediction ?? null,
|
|
||||||
probabilities: daily?.probabilities || [],
|
|
||||||
probabilitiesAll: daily?.probabilities_all || daily?.probabilities || [],
|
|
||||||
shadowProbabilities: [],
|
|
||||||
shadowProbabilitiesAll: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getModelView(detail: CityDetail, targetDate?: string | null) {
|
|
||||||
const date = targetDate || detail.local_date;
|
|
||||||
const daily = detail.multi_model_daily?.[date];
|
|
||||||
if (daily) {
|
|
||||||
return {
|
|
||||||
deb: daily.deb?.prediction ?? null,
|
|
||||||
models: daily.models || {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
deb: detail.deb?.prediction ?? null,
|
|
||||||
models: detail.multi_model || {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function parseAiAnalysis(analysis: CityDetail["ai_analysis"]) {
|
export function parseAiAnalysis(analysis: CityDetail["ai_analysis"]) {
|
||||||
const fallback = {
|
const fallback = {
|
||||||
bullets: [] as string[],
|
bullets: [] as string[],
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import type { CityDetail } from "@/lib/dashboard-types";
|
||||||
|
|
||||||
|
export function getProbabilityView(detail: CityDetail, targetDate?: string | null) {
|
||||||
|
const date = targetDate || detail.local_date;
|
||||||
|
if (date === detail.local_date) {
|
||||||
|
return {
|
||||||
|
calibrationMode: detail.probabilities?.calibration_mode ?? null,
|
||||||
|
calibrationVersion: detail.probabilities?.calibration_version ?? null,
|
||||||
|
engine: detail.probabilities?.engine ?? null,
|
||||||
|
mu: detail.probabilities?.mu ?? null,
|
||||||
|
probabilities: detail.probabilities?.distribution || [],
|
||||||
|
probabilitiesAll:
|
||||||
|
detail.probabilities?.distribution_all ||
|
||||||
|
detail.probabilities?.distribution ||
|
||||||
|
[],
|
||||||
|
shadowProbabilities: detail.probabilities?.shadow_distribution || [],
|
||||||
|
shadowProbabilitiesAll:
|
||||||
|
detail.probabilities?.shadow_distribution_all ||
|
||||||
|
detail.probabilities?.shadow_distribution ||
|
||||||
|
[],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const daily = detail.multi_model_daily?.[date];
|
||||||
|
return {
|
||||||
|
calibrationMode: null,
|
||||||
|
calibrationVersion: null,
|
||||||
|
engine: null,
|
||||||
|
mu: daily?.deb?.prediction ?? null,
|
||||||
|
probabilities: daily?.probabilities || [],
|
||||||
|
probabilitiesAll: daily?.probabilities_all || daily?.probabilities || [],
|
||||||
|
shadowProbabilities: [],
|
||||||
|
shadowProbabilitiesAll: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getModelView(detail: CityDetail, targetDate?: string | null) {
|
||||||
|
const date = targetDate || detail.local_date;
|
||||||
|
const daily = detail.multi_model_daily?.[date];
|
||||||
|
if (daily) {
|
||||||
|
return {
|
||||||
|
deb: daily.deb?.prediction ?? null,
|
||||||
|
models: daily.models || {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
deb: detail.deb?.prediction ?? null,
|
||||||
|
models: detail.multi_model || {},
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user