192 lines
6.6 KiB
JavaScript
192 lines
6.6 KiB
JavaScript
import { getSession } from 'next-auth/react';
|
|
|
|
export default async function handler(req, res) {
|
|
// Authentication check
|
|
const session = await getSession({ req });
|
|
if (!session) {
|
|
return res.status(401).json({ error: 'Unauthorized' });
|
|
}
|
|
|
|
if (req.method !== 'POST') {
|
|
return res.status(405).json({ error: 'Method not allowed' });
|
|
}
|
|
|
|
try {
|
|
const { objects, cables } = req.body;
|
|
|
|
// Validate input data
|
|
if (!objects || !cables) {
|
|
return res.status(400).json({ error: 'Missing objects or cables data' });
|
|
}
|
|
|
|
// Find transformer (source)
|
|
const transformer = objects.find(obj => obj.type === 'transformer');
|
|
if (!transformer) {
|
|
return res.status(400).json({ error: 'No transformer found in the system' });
|
|
}
|
|
|
|
// Calculate voltage drops for each path
|
|
const results = calculateVoltageDrops(transformer, objects, cables);
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
data: results,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
} catch (error) {
|
|
console.error('Voltage drop calculation error:', error);
|
|
res.status(500).json({
|
|
error: 'Internal server error',
|
|
details: process.env.NODE_ENV === 'development' ? error.message : undefined
|
|
});
|
|
}
|
|
}
|
|
|
|
function calculateVoltageDrops(transformer, objects, cables) {
|
|
const results = {
|
|
transformer: transformer,
|
|
paths: [],
|
|
summary: {
|
|
totalPower: 0,
|
|
maxVoltageDrop: 0,
|
|
minVoltage: transformer.bottomVoltage
|
|
}
|
|
};
|
|
|
|
// Cable resistance values (Ω/km) - simplified values for common cable types
|
|
const cableResistance = {
|
|
'YAKY': {
|
|
16: 1.15, 25: 0.727, 35: 0.524, 50: 0.387, 70: 0.268, 95: 0.193, 120: 0.153, 150: 0.124, 185: 0.099, 240: 0.075
|
|
},
|
|
'NA2XY-J': {
|
|
16: 1.15, 25: 0.727, 35: 0.524, 50: 0.387, 70: 0.268, 95: 0.193, 120: 0.153, 150: 0.124, 185: 0.099, 240: 0.075
|
|
},
|
|
'AL': {
|
|
16: 1.91, 25: 1.20, 35: 0.868, 50: 0.641, 70: 0.443, 95: 0.320, 120: 0.253, 150: 0.206, 185: 0.164, 240: 0.125
|
|
},
|
|
'AsXSn': {
|
|
16: 1.91, 25: 1.20, 35: 0.868, 50: 0.641, 70: 0.443, 95: 0.320, 120: 0.253, 150: 0.206, 185: 0.164, 240: 0.125
|
|
}
|
|
};
|
|
|
|
// Find all paths from transformer to end connections
|
|
const paths = findAllPaths(transformer, objects, cables);
|
|
|
|
paths.forEach((path, index) => {
|
|
let totalVoltageDrop = 0;
|
|
let pathPower = 0;
|
|
const pathDetails = [];
|
|
|
|
// Calculate for each segment in the path
|
|
for (let i = 0; i < path.length - 1; i++) {
|
|
const fromNode = path[i];
|
|
const toNode = path[i + 1];
|
|
|
|
// Find the cable connecting these nodes
|
|
const cable = cables.find(c =>
|
|
(c.from === fromNode.id && c.to === toNode.id) ||
|
|
(c.from === toNode.id && c.to === fromNode.id)
|
|
);
|
|
|
|
if (cable) {
|
|
// Get cable resistance
|
|
const resistance = getCableResistance(cable, cableResistance);
|
|
|
|
// Calculate current (simplified - assuming balanced load)
|
|
const nodePower = toNode.powerRating || 0;
|
|
const current = nodePower > 0 ? (nodePower * 1000) / (Math.sqrt(3) * transformer.bottomVoltage * 0.9) : 0; // cos φ = 0.9
|
|
|
|
// Calculate voltage drop for this segment
|
|
const segmentVoltageDrop = Math.sqrt(3) * current * resistance * (cable.length / 1000); // length in km
|
|
|
|
totalVoltageDrop += segmentVoltageDrop;
|
|
pathPower += nodePower;
|
|
|
|
pathDetails.push({
|
|
from: fromNode.name,
|
|
to: toNode.name,
|
|
cable: {
|
|
label: cable.label,
|
|
type: cable.cableType,
|
|
crossSection: cable.crossSection,
|
|
length: cable.length
|
|
},
|
|
current: current.toFixed(2),
|
|
resistance: resistance.toFixed(4),
|
|
voltageDrop: segmentVoltageDrop.toFixed(2),
|
|
power: nodePower
|
|
});
|
|
}
|
|
}
|
|
|
|
const finalVoltage = transformer.bottomVoltage - totalVoltageDrop;
|
|
const voltageDropPercentage = (totalVoltageDrop / transformer.bottomVoltage) * 100;
|
|
|
|
results.paths.push({
|
|
id: index + 1,
|
|
endNode: path[path.length - 1].name,
|
|
totalVoltageDrop: totalVoltageDrop.toFixed(2),
|
|
finalVoltage: finalVoltage.toFixed(2),
|
|
voltageDropPercentage: voltageDropPercentage.toFixed(2),
|
|
pathPower: pathPower,
|
|
segments: pathDetails,
|
|
isValid: voltageDropPercentage <= 5 // 5% is typical limit
|
|
});
|
|
|
|
results.summary.totalPower += pathPower;
|
|
if (totalVoltageDrop > results.summary.maxVoltageDrop) {
|
|
results.summary.maxVoltageDrop = totalVoltageDrop;
|
|
results.summary.minVoltage = finalVoltage;
|
|
}
|
|
});
|
|
|
|
return results;
|
|
}
|
|
|
|
function findAllPaths(transformer, objects, cables) {
|
|
const paths = [];
|
|
const visited = new Set();
|
|
|
|
function dfs(currentNode, currentPath) {
|
|
visited.add(currentNode.id);
|
|
currentPath.push(currentNode);
|
|
|
|
// If this is an end connection, save the path
|
|
if (currentNode.type === 'end') {
|
|
paths.push([...currentPath]);
|
|
} else {
|
|
// Find all connected nodes
|
|
const connectedCables = cables.filter(cable =>
|
|
cable.from === currentNode.id || cable.to === currentNode.id
|
|
);
|
|
|
|
connectedCables.forEach(cable => {
|
|
const nextNodeId = cable.from === currentNode.id ? cable.to : cable.from;
|
|
const nextNode = objects.find(obj => obj.id === nextNodeId);
|
|
|
|
if (nextNode && !visited.has(nextNodeId)) {
|
|
dfs(nextNode, currentPath);
|
|
}
|
|
});
|
|
}
|
|
|
|
currentPath.pop();
|
|
visited.delete(currentNode.id);
|
|
}
|
|
|
|
dfs(transformer, []);
|
|
return paths;
|
|
}
|
|
|
|
function getCableResistance(cable, resistanceTable) {
|
|
const cableType = cable.cableType || 'YAKY';
|
|
const crossSection = cable.crossSection || 25;
|
|
|
|
if (resistanceTable[cableType] && resistanceTable[cableType][crossSection]) {
|
|
return resistanceTable[cableType][crossSection];
|
|
}
|
|
|
|
// Default resistance if not found
|
|
return 1.0;
|
|
}
|