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; }