fix(map): convert actual demand display units
This commit is contained in:
@@ -32,9 +32,23 @@ import {
|
|||||||
} from "./styleEditorTypes";
|
} from "./styleEditorTypes";
|
||||||
import { LegendStyleConfig } from "./StyleLegend";
|
import { LegendStyleConfig } from "./StyleLegend";
|
||||||
import { calculateClassification } from "@utils/breaksClassification";
|
import { calculateClassification } from "@utils/breaksClassification";
|
||||||
|
import { isLpsFlowProperty, toM3h } from "@utils/units";
|
||||||
|
|
||||||
const UNIT_HEADLOSS_RANGE: [number, number] = [0, 5];
|
const UNIT_HEADLOSS_RANGE: [number, number] = [0, 5];
|
||||||
|
|
||||||
|
const normalizeComputedStyleValue = (property: string, value: unknown) => {
|
||||||
|
const numericValue = Number(value);
|
||||||
|
if (!Number.isFinite(numericValue)) {
|
||||||
|
return Number.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
const displayValue = isLpsFlowProperty(property)
|
||||||
|
? toM3h(numericValue, "lps")
|
||||||
|
: numericValue;
|
||||||
|
|
||||||
|
return property === "flow" ? Math.abs(displayValue) : displayValue;
|
||||||
|
};
|
||||||
|
|
||||||
export const useStyleEditor = ({
|
export const useStyleEditor = ({
|
||||||
layerStyleStates,
|
layerStyleStates,
|
||||||
setLayerStyleStates,
|
setLayerStyleStates,
|
||||||
@@ -337,12 +351,20 @@ export const useStyleEditor = ({
|
|||||||
layerType === "junctions"
|
layerType === "junctions"
|
||||||
? isElevation && elevationRange
|
? isElevation && elevationRange
|
||||||
? [elevationRange[0], elevationRange[1]]
|
? [elevationRange[0], elevationRange[1]]
|
||||||
: currentJunctionCalData?.map((item: any) => item.value) || []
|
: currentJunctionCalData
|
||||||
|
?.map((item: any) =>
|
||||||
|
normalizeComputedStyleValue(effectiveStyleConfig.property, item.value)
|
||||||
|
)
|
||||||
|
.filter(Number.isFinite) || []
|
||||||
: isDiameter && diameterRange
|
: isDiameter && diameterRange
|
||||||
? [diameterRange[0], diameterRange[1]]
|
? [diameterRange[0], diameterRange[1]]
|
||||||
: isUnitHeadloss
|
: isUnitHeadloss
|
||||||
? [UNIT_HEADLOSS_RANGE[0], UNIT_HEADLOSS_RANGE[1]]
|
? [UNIT_HEADLOSS_RANGE[0], UNIT_HEADLOSS_RANGE[1]]
|
||||||
: currentPipeCalData?.map((item: any) => item.value) || [];
|
: currentPipeCalData
|
||||||
|
?.map((item: any) =>
|
||||||
|
normalizeComputedStyleValue(effectiveStyleConfig.property, item.value)
|
||||||
|
)
|
||||||
|
.filter(Number.isFinite) || [];
|
||||||
|
|
||||||
const canApply =
|
const canApply =
|
||||||
layerType === "junctions"
|
layerType === "junctions"
|
||||||
@@ -416,7 +438,7 @@ export const useStyleEditor = ({
|
|||||||
|
|
||||||
const dataMap = new Map<string, number>();
|
const dataMap = new Map<string, number>();
|
||||||
records.forEach((record: any) => {
|
records.forEach((record: any) => {
|
||||||
dataMap.set(record.ID, record.value || 0);
|
dataMap.set(record.ID, normalizeComputedStyleValue(property, record.value || 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
vectorTileSources.forEach((vectorTileSource) => {
|
vectorTileSources.forEach((vectorTileSource) => {
|
||||||
@@ -434,8 +456,7 @@ export const useStyleEditor = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFeature.properties_[property] =
|
renderFeature.properties_[property] = value;
|
||||||
property === "flow" ? Math.abs(value) : value;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -457,7 +478,7 @@ export const useStyleEditor = ({
|
|||||||
|
|
||||||
const dataMap = new Map<string, number>();
|
const dataMap = new Map<string, number>();
|
||||||
records.forEach((record: any) => {
|
records.forEach((record: any) => {
|
||||||
dataMap.set(record.ID, record.value || 0);
|
dataMap.set(record.ID, normalizeComputedStyleValue(property, record.value || 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
const listener = (event: any) => {
|
const listener = (event: any) => {
|
||||||
@@ -478,8 +499,7 @@ export const useStyleEditor = ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFeature.properties_[property] =
|
renderFeature.properties_[property] = value;
|
||||||
property === "flow" ? Math.abs(value) : value;
|
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error processing tile load event:", error);
|
console.error("Error processing tile load event:", error);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { TextLayer } from "@deck.gl/layers";
|
|||||||
import { TripsLayer } from "@deck.gl/geo-layers";
|
import { TripsLayer } from "@deck.gl/geo-layers";
|
||||||
import { CollisionFilterExtension } from "@deck.gl/extensions";
|
import { CollisionFilterExtension } from "@deck.gl/extensions";
|
||||||
import { ContourLayer } from "deck.gl";
|
import { ContourLayer } from "deck.gl";
|
||||||
import { toM3h } from "@utils/units";
|
import { isLpsFlowProperty, toM3h } from "@utils/units";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import {
|
import {
|
||||||
cleanupTransientMapResources,
|
cleanupTransientMapResources,
|
||||||
@@ -204,8 +204,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
return junctionData.map((j) => {
|
return junctionData.map((j) => {
|
||||||
const record = nodeMap.get(j.id);
|
const record = nodeMap.get(j.id);
|
||||||
let val = record ? record.value : undefined;
|
let val = record ? record.value : undefined;
|
||||||
// 在这合并时将实际需水量从 LPS 转换为大写表示
|
if (val !== undefined && isLpsFlowProperty(junctionText)) {
|
||||||
if (val !== undefined && junctionText === "actualdemand") {
|
|
||||||
val = toM3h(val, "lps");
|
val = toM3h(val, "lps");
|
||||||
}
|
}
|
||||||
return record ? { ...j, [junctionText]: val } : j;
|
return record ? { ...j, [junctionText]: val } : j;
|
||||||
@@ -236,7 +235,7 @@ const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
|
|||||||
return junctionData.map((j) => {
|
return junctionData.map((j) => {
|
||||||
const record = nodeMap.get(j.id);
|
const record = nodeMap.get(j.id);
|
||||||
let val = record ? record.value : undefined;
|
let val = record ? record.value : undefined;
|
||||||
if (val !== undefined && junctionText === "actualdemand") {
|
if (val !== undefined && isLpsFlowProperty(junctionText)) {
|
||||||
val = toM3h(val, "lps");
|
val = toM3h(val, "lps");
|
||||||
}
|
}
|
||||||
return record ? { ...j, [junctionText]: val } : j;
|
return record ? { ...j, [junctionText]: val } : j;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { FLOW_DISPLAY_UNIT, isLpsFlowProperty, toM3h } from "./units";
|
||||||
|
|
||||||
|
describe("flow display units", () => {
|
||||||
|
it("uses cubic meters per hour as the flow display unit", () => {
|
||||||
|
expect(FLOW_DISPLAY_UNIT).toBe("m³/h");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("converts L/s values to m³/h", () => {
|
||||||
|
expect(toM3h(10, "lps")).toBe(36);
|
||||||
|
expect(toM3h(10, "L/s")).toBe(36);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("recognizes computed properties that arrive from the backend in L/s", () => {
|
||||||
|
expect(isLpsFlowProperty("flow")).toBe(true);
|
||||||
|
expect(isLpsFlowProperty("actual_demand")).toBe(true);
|
||||||
|
expect(isLpsFlowProperty("actualdemand")).toBe(true);
|
||||||
|
expect(isLpsFlowProperty("pressure")).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
export const FLOW_DISPLAY_UNIT = "m³/h";
|
export const FLOW_DISPLAY_UNIT = "m³/h";
|
||||||
const M3H_FACTOR = 3600;
|
const M3H_FACTOR = 3600;
|
||||||
|
const LPS_FLOW_PROPERTIES = new Set(["flow", "actual_demand", "actualdemand"]);
|
||||||
|
|
||||||
|
export const isLpsFlowProperty = (property: string) =>
|
||||||
|
LPS_FLOW_PROPERTIES.has(property);
|
||||||
|
|
||||||
export const toM3h = (value: number, sourceUnit: string = "m³/s") => {
|
export const toM3h = (value: number, sourceUnit: string = "m³/s") => {
|
||||||
if (!Number.isFinite(value)) return Number.NaN;
|
if (!Number.isFinite(value)) return Number.NaN;
|
||||||
|
|||||||
Reference in New Issue
Block a user