function transformMonitoringData2(inputData, SampleType) {
function parseDMSCoordinate(dmsStr) {
const regex = /(\d+)°(\d+)′([\d.]+)″([NSEWnsew])/;
const match = dmsStr.match(regex);
if (!match) return null;
const [_, degrees, minutes, seconds, direction] = match;
let decimal =
parseFloat(degrees) +
parseFloat(minutes) / 60 +
parseFloat(seconds) / 3600;
if (direction.toUpperCase() === "S" || direction.toUpperCase() === "W") {
decimal = -decimal;
}
return decimal;
}
function parseValue(valueStr) {
if (valueStr === undefined || valueStr === null) {
return { value: null, nd: null };
}
const ndMatch = String(valueStr).match(/ND\(([0-9.]+)\)/);
if (ndMatch) {
return {
value: null,
nd: parseFloat(ndMatch[1])
};
}
return {
value: parseFloat(valueStr),
nd: null
};
}
function findClosestStation(lon, lat, organization) {
let closestStation = null;
let minDistance = Infinity;
const toRadians = (deg) => (deg * Math.PI) / 180;
SeawaterSamplingLocations.forEach((station) => {
if (station.Organization !== organization) return;
const stationLon = parseFloat(station.Longitude);
const stationLat = parseFloat(station.Latitude);
const R = 6371;
const dLat = toRadians(stationLat - lat);
const dLon = toRadians(stationLon - lon);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat)) *
Math.cos(toRadians(stationLat)) *
Math.sin(dLon / 2) *
Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
if (distance < minDistance) {
minDistance = distance;
closestStation = station.Station;
}
});
return closestStation;
}
function findMatchingStation(lon, lat, organization) {
const targetLon = parseFloat(lon).toFixed(8);
const targetLat = parseFloat(lat).toFixed(8);
const match = SeawaterSamplingLocations.find((station) => {
return (
station.Organization === organization &&
parseFloat(station.Longitude).toFixed(8) === targetLon &&
parseFloat(station.Latitude).toFixed(8) === targetLat
);
});
return match ? match.Station : null;
}
const transformedData = [];
inputData.forEach((feature) => {
const props = feature.properties;
const coords = feature.geometry.coordinates;
const lat = parseDMSCoordinate(props.lat);
const lon = parseDMSCoordinate(props.lon);
if (props.item === "Fishes") {
if (props.sample && Array.isArray(props.sample)) {
props.sample.forEach((sample) => {
const baseEntry = {
begperiod: new Date(props.sampling_date),
point: coords,
org: props.organization,
species: sample.sample_name,
lon,
lat
};
if (sample.data && Array.isArray(sample.data)) {
const measurementsByRadionuclide = {};
sample.data.forEach((measurement) => {
if (!measurementsByRadionuclide[measurement.radionuclide]) {
measurementsByRadionuclide[measurement.radionuclide] = [];
}
measurementsByRadionuclide[measurement.radionuclide].push(
measurement
);
});
Object.entries(measurementsByRadionuclide).forEach(
([radionuclide, measurements]) => {
const measurement =
measurements.find((m) => {
if (radionuclide.includes("TFWT")) {
return m.unit === "Bq/L";
} else if (radionuclide.includes("OBT")) {
return m.unit === "Bq/kg-fresh";
}
return true;
}) || measurements[0];
const { value: parsedValue, nd } = parseValue(
measurement.value
);
baseEntry[radionuclide] = parsedValue;
baseEntry[`${radionuclide}_nd`] = nd;
baseEntry[`${radionuclide}_unit`] = measurement.unit;
}
);
}
transformedData.push(baseEntry);
});
}
} else if (props.item === "Seawater") {
props.depth.forEach((depth, depthIndex) => {
props.date.forEach((date, dateIndex) => {
const baseEntry = {
begperiod: new Date(date),
station:
findMatchingStation(coords[0], coords[1], props.organization) ||
findClosestStation(coords[0], coords[1], props.organization),
point: coords,
org: props.organization,
depth: depth.toLowerCase().includes("surface")
? "Surface"
: depth.toLowerCase().includes("bottom")
? "Bottom"
: depth,
unit: props.unit[depthIndex],
lon,
lat
};
props.nuclide.forEach((nuclide, nuclideIndex) => {
const value = props.value[depthIndex]?.[nuclideIndex];
const { value: parsedValue, nd } = parseValue(value);
baseEntry[nuclide] = parsedValue;
baseEntry[`${nuclide}_nd`] = nd;
});
transformedData.push(baseEntry);
});
});
}
});
return transformedData;
}