commit
This commit is contained in:
@@ -200,15 +200,27 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
|
||||
|
||||
// Outlier/sensor glitch detection
|
||||
if (level > 0) {
|
||||
let isGlitch = false;
|
||||
if (staticConfig && staticConfig.minLevel && staticConfig.maxLevel) {
|
||||
const minAllowed = staticConfig.minLevel - 5;
|
||||
const maxAllowed = staticConfig.maxLevel + 5;
|
||||
if (level < minAllowed || level > maxAllowed) {
|
||||
// Glitch detected, fallback to last known valid level
|
||||
level = lastValidLevel !== null ? lastValidLevel : (staticConfig.minLevel + staticConfig.maxLevel) / 2;
|
||||
} else {
|
||||
lastValidLevel = level;
|
||||
isGlitch = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check rate of change: sudden spikes/drops
|
||||
if (!isGlitch && lastValidLevel !== null) {
|
||||
const isRiver = staticConfig?.type === 'river';
|
||||
const maxAllowedDelta = isRiver ? 50 : 0.5; // 50 cm for rivers, 0.5 m for reservoirs
|
||||
if (Math.abs(level - lastValidLevel) > maxAllowedDelta) {
|
||||
isGlitch = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isGlitch) {
|
||||
// Glitch detected, fallback to last known valid level
|
||||
level = lastValidLevel !== null ? lastValidLevel : (staticConfig && staticConfig.minLevel && staticConfig.maxLevel ? (staticConfig.minLevel + staticConfig.maxLevel) / 2 : level);
|
||||
} else {
|
||||
lastValidLevel = level;
|
||||
}
|
||||
@@ -394,15 +406,29 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
|
||||
e.preventDefault();
|
||||
const isTouchEvent = 'touches' in e;
|
||||
|
||||
const currentDomain = axis === 'left'
|
||||
? (leftCustomDomain || getDefaultLeftDomain())
|
||||
: (rightCustomDomain || getDefaultRightDomain());
|
||||
|
||||
// Calculate the center based on the middle of the actual data values to keep the graph line centered
|
||||
let dataCenter = (currentDomain[1] + currentDomain[0]) / 2;
|
||||
if (axis === 'left') {
|
||||
const levels = chartData.map(d => d.level).filter(v => v !== null && v !== undefined && !isNaN(v));
|
||||
if (levels.length > 0) {
|
||||
dataCenter = (Math.min(...levels) + Math.max(...levels)) / 2;
|
||||
}
|
||||
} else {
|
||||
const flows = chartData.flatMap(d => [d.outflow, d.inflow]).filter(v => v !== null && v !== undefined && !isNaN(v));
|
||||
if (flows.length > 0) {
|
||||
dataCenter = (Math.min(...flows) + Math.max(...flows)) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTouchEvent && e.touches.length === 2) {
|
||||
const touch1 = e.touches[0];
|
||||
const touch2 = e.touches[1];
|
||||
const dist = Math.abs(touch1.clientY - touch2.clientY);
|
||||
|
||||
const currentDomain = axis === 'left'
|
||||
? (leftCustomDomain || getDefaultLeftDomain())
|
||||
: (rightCustomDomain || getDefaultRightDomain());
|
||||
|
||||
const onTouchMove = (moveEvent: TouchEvent) => {
|
||||
if (moveEvent.touches.length === 2) {
|
||||
moveEvent.preventDefault(); // Stop native page zooming
|
||||
@@ -411,10 +437,9 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
|
||||
const currentDist = Math.abs(mTouch1.clientY - mTouch2.clientY);
|
||||
if (currentDist > 5) {
|
||||
const factor = dist / currentDist;
|
||||
const center = (currentDomain[0] + currentDomain[1]) / 2;
|
||||
const range = currentDomain[1] - currentDomain[0];
|
||||
const newMin = center - (range * factor) / 2;
|
||||
const newMax = center + (range * factor) / 2;
|
||||
const newMin = dataCenter - (range * factor) / 2;
|
||||
const newMax = dataCenter + (range * factor) / 2;
|
||||
|
||||
if (axis === 'left') {
|
||||
setLeftCustomDomain([newMin, newMax]);
|
||||
@@ -436,12 +461,7 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
|
||||
}
|
||||
|
||||
const startY = isTouchEvent ? e.touches[0].clientY : e.clientY;
|
||||
const currentDomain = axis === 'left'
|
||||
? (leftCustomDomain || getDefaultLeftDomain())
|
||||
: (rightCustomDomain || getDefaultRightDomain());
|
||||
|
||||
const initialRange = currentDomain[1] - currentDomain[0];
|
||||
const center = (currentDomain[1] + currentDomain[0]) / 2;
|
||||
|
||||
const onMove = (moveEvent: MouseEvent | TouchEvent) => {
|
||||
if ('touches' in moveEvent) {
|
||||
@@ -451,8 +471,8 @@ const LakeDetail = ({ language, lakeId, windUnit = 'kmh' }: Props) => {
|
||||
const deltaY = clientY - startY;
|
||||
|
||||
const factor = Math.pow(2.5, deltaY / 150);
|
||||
const newMin = center - (initialRange * factor) / 2;
|
||||
const newMax = center + (initialRange * factor) / 2;
|
||||
const newMin = dataCenter - (initialRange * factor) / 2;
|
||||
const newMax = dataCenter + (initialRange * factor) / 2;
|
||||
|
||||
if (axis === 'left') {
|
||||
setLeftCustomDomain([newMin, newMax]);
|
||||
|
||||
Reference in New Issue
Block a user