com.zepben.evolve.services.network.tracing.phases.PhaseTrace.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of evolve-sdk Show documentation
Show all versions of evolve-sdk Show documentation
SDK for interaction with the evolve platform
/*
* Copyright 2020 Zeppelin Bend Pty Ltd
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
package com.zepben.evolve.services.network.tracing.phases
import com.zepben.evolve.cim.iec61970.base.core.Terminal
import com.zepben.evolve.cim.iec61970.base.wires.SinglePhaseKind
import com.zepben.evolve.services.network.NetworkService
import com.zepben.evolve.services.network.tracing.OpenTest
import com.zepben.evolve.services.network.tracing.connectivity.ConnectivityResult
import com.zepben.evolve.services.network.tracing.feeder.DirectionSelector
import com.zepben.evolve.services.network.tracing.feeder.FeederDirection
import com.zepben.evolve.services.network.tracing.phases.PhaseStep.Companion.continueAt
import com.zepben.evolve.services.network.tracing.traversals.BasicTraversal
import com.zepben.evolve.services.network.tracing.traversals.WeightedPriorityQueue.Companion.processQueue
/**
* A class that creates commonly used phase based traces. You can add custom step actions and stop conditions
* to the returned traversal.
*/
object PhaseTrace {
/**
* @return a traversal that traces along phases in all directions through all open points.
*/
fun newTrace(): BasicTraversal = newTrace(OpenTest.IGNORE_OPEN)
/**
* @return a traversal that traces along phases in all directions stopping at normally open points.
*/
fun newNormalTrace(): BasicTraversal = newTrace(OpenTest.NORMALLY_OPEN)
/**
* @return a traversal that traces along phases in all directions stopping at currently open points.
*/
fun newCurrentTrace(): BasicTraversal = newTrace(OpenTest.CURRENTLY_OPEN)
/**
* @return a traversal that traces along phases in a downstream direction stopping at normally open points.
*/
fun newNormalDownstreamTrace(): BasicTraversal =
newDownstreamTrace(OpenTest.NORMALLY_OPEN, DirectionSelector.NORMAL_DIRECTION)
/**
* @return a traversal that traces along phases in a downstream direction stopping at currently open points.
*/
fun newCurrentDownstreamTrace(): BasicTraversal =
newDownstreamTrace(OpenTest.CURRENTLY_OPEN, DirectionSelector.CURRENT_DIRECTION)
/**
* @return a traversal that traces along phases in an upstream direction stopping at normally open points.
*/
fun newNormalUpstreamTrace(): BasicTraversal =
newUpstreamTrace(OpenTest.NORMALLY_OPEN, DirectionSelector.NORMAL_DIRECTION)
/**
* @return a traversal that traces along phases in an upstream direction stopping at currently open points.
*/
fun newCurrentUpstreamTrace(): BasicTraversal =
newUpstreamTrace(OpenTest.CURRENTLY_OPEN, DirectionSelector.CURRENT_DIRECTION)
private fun newTrace(isOpenTest: OpenTest): BasicTraversal =
BasicTraversal(queueNext(isOpenTest), processQueue { it.phases.size }, PhaseStepTracker())
private fun newDownstreamTrace(isOpenTest: OpenTest, activeDirection: DirectionSelector): BasicTraversal =
BasicTraversal(queueNextDownstream(isOpenTest, activeDirection), processQueue { it.phases.size }, PhaseStepTracker())
private fun newUpstreamTrace(isOpenTest: OpenTest, activeDirection: DirectionSelector): BasicTraversal =
BasicTraversal(queueNextUpstream(isOpenTest, activeDirection), processQueue { it.phases.size }, PhaseStepTracker())
private fun queueNext(openTest: OpenTest): BasicTraversal.QueueNext =
BasicTraversal.QueueNext { phaseStep, traversal ->
val downPhases = mutableSetOf()
phaseStep.conductingEquipment.terminals.forEach {
downPhases.clear()
for (phase in phaseStep.phases) {
if (!openTest.isOpen(phaseStep.conductingEquipment, phase)) {
downPhases.add(phase)
}
}
queueConnected(traversal, it, downPhases)
}
}
private fun queueNextDownstream(openTest: OpenTest, activeDirection: DirectionSelector): BasicTraversal.QueueNext =
BasicTraversal.QueueNext { phaseStep, traversal ->
phaseStep.conductingEquipment.terminals.forEach {
queueConnected(traversal, it, getPhasesWithDirection(openTest, activeDirection, it, phaseStep.phases, FeederDirection.DOWNSTREAM))
}
}
private fun queueConnected(traversal: BasicTraversal, terminal: Terminal, downPhases: Set) {
if (downPhases.isNotEmpty()) {
NetworkService.connectedTerminals(terminal, downPhases).forEach {
tryQueue(traversal, it, it.toNominalPhases)
}
}
}
private fun queueNextUpstream(openTest: OpenTest, activeDirection: DirectionSelector): BasicTraversal.QueueNext =
BasicTraversal.QueueNext { phaseStep, traversal ->
phaseStep.conductingEquipment.terminals.forEach { terminal ->
val upPhases = getPhasesWithDirection(openTest, activeDirection, terminal, phaseStep.phases, FeederDirection.UPSTREAM)
if (upPhases.isNotEmpty()) {
NetworkService.connectedTerminals(terminal, upPhases).forEach { cr ->
// When going upstream, we only want to traverse to connected terminals that have a DOWNSTREAM direction
if (FeederDirection.DOWNSTREAM in activeDirection.select(cr.toTerminal).value)
tryQueue(traversal, cr, cr.toNominalPhases)
}
}
}
}
private fun tryQueue(traversal: BasicTraversal, cr: ConnectivityResult, downPhases: Collection) {
cr.to?.let { traversal.queue.add(continueAt(it, downPhases, cr.from)) }
}
private fun getPhasesWithDirection(
openTest: OpenTest,
activeDirection: DirectionSelector,
terminal: Terminal,
candidatePhases: Set,
direction: FeederDirection
): Set {
val matchedPhases = mutableSetOf()
if (direction !in activeDirection.select(terminal).value)
return matchedPhases
val conductingEquipment = terminal.conductingEquipment!!
for (phase in candidatePhases) {
if (terminal.phases.singlePhases.contains(phase) && !openTest.isOpen(conductingEquipment, phase))
matchedPhases.add(phase)
}
return matchedPhases
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy