private static bool ShouldBeMerged(SpanEquipmentWithConnectsHolder firstSpanEquipment, SpanEquipmentWithConnectsHolder secondSpanEquipment) { if (firstSpanEquipment.Connects.Count == 1 && firstSpanEquipment.SpanEquipment.TryGetSpanSegment(firstSpanEquipment.Connects[0].ConnectInfo.SegmentId, out var firstSpanSegmentWithIndexInfo)) { // If we're dealing with structure index 0, then the client is connecting the outer span if (firstSpanSegmentWithIndexInfo.StructureIndex == 0) { return(true); } } return(false); }
private Result CheckIfConnectsAreAlligned(SpanEquipmentWithConnectsHolder firstSpanEquipment, SpanEquipmentWithConnectsHolder secondSpanEquipment) { // If more than 2 segments selected in each span equipment, check that they are alligned in terms of specifications if (firstSpanEquipment.Connects.Count > 1) { HashSet <Guid> firstSpanEquipmentStructureSpecIds = new HashSet <Guid>(); HashSet <Guid> secondSpanEquipmentStructureSpecIds = new HashSet <Guid>(); foreach (var firstEqSpanSegmentConnect in firstSpanEquipment.Connects) { firstSpanEquipment.SpanEquipment.TryGetSpanSegment(firstEqSpanSegmentConnect.ConnectInfo.SegmentId, out var spanSegmentWithIndexInfo); var structureSpecId = firstSpanEquipment.SpanEquipment.SpanStructures[spanSegmentWithIndexInfo.StructureIndex].SpecificationId; firstEqSpanSegmentConnect.StructureSpecificationId = structureSpecId; firstSpanEquipmentStructureSpecIds.Add(structureSpecId); } foreach (var secondEqSpanSegmentConnect in secondSpanEquipment.Connects) { secondSpanEquipment.SpanEquipment.TryGetSpanSegment(secondEqSpanSegmentConnect.ConnectInfo.SegmentId, out var spanSegmentWithIndexInfo); var structureSpecId = secondSpanEquipment.SpanEquipment.SpanStructures[spanSegmentWithIndexInfo.StructureIndex].SpecificationId; secondEqSpanSegmentConnect.StructureSpecificationId = structureSpecId; secondSpanEquipmentStructureSpecIds.Add(structureSpecId); } foreach (var firstStructureId in firstSpanEquipmentStructureSpecIds) { if (!secondSpanEquipmentStructureSpecIds.Contains(firstStructureId)) { return(Result.Fail(new ConnectSpanSegmentsAtRouteNodeError( ConnectSpanSegmentsAtRouteNodeErrorCodes.EXPECTED_SAME_SPECIFICATIONS_OF_SPAN_SEGMENTS_BELONGING_TO_TWO_SPAN_EQUIPMENT, $"Cannot connect the span segments specified because specifications on the span structures don't allign. Make sure that you connect span segments beloning to structure with the same specs - i.e. a red and blue Ø10 from one span equipment to a red and blue Ø10 in the other span equipment.") )); } } // Order connects by spec id firstSpanEquipment.Connects = firstSpanEquipment.Connects.OrderBy(s => s.StructureSpecificationId).ToList(); secondSpanEquipment.Connects = secondSpanEquipment.Connects.OrderBy(s => s.StructureSpecificationId).ToList(); } return(Result.Ok()); }
private Result ConnectTwoSpanEquipment(CommandContext cmdContext, Guid routeNodeId, SpanEquipmentWithConnectsHolder firstSpanEquipment, SpanEquipmentWithConnectsHolder secondSpanEquipment) { // Create junction/terminal ids used to connect span segments for (int i = 0; i < firstSpanEquipment.Connects.Count; i++) { var junctionId = Guid.NewGuid(); firstSpanEquipment.Connects[i].ConnectInfo.TerminalId = junctionId; firstSpanEquipment.Connects[i].ConnectInfo.ConnectionDirection = SpanSegmentToTerminalConnectionDirection.FromSpanSegmentToTerminal; secondSpanEquipment.Connects[i].ConnectInfo.TerminalId = junctionId; secondSpanEquipment.Connects[i].ConnectInfo.ConnectionDirection = SpanSegmentToTerminalConnectionDirection.FromTerminalToSpanSegment; } // Connect the first span equipment to terminals var firstSpanEquipmentAR = _eventStore.Aggregates.Load <SpanEquipmentAR>(firstSpanEquipment.SpanEquipment.Id); var firstSpanEquipmentConnectResult = firstSpanEquipmentAR.ConnectSpanSegmentsToSimpleTerminals( cmdContext: cmdContext, routeNodeId: routeNodeId, connects: firstSpanEquipment.Connects.Select(c => c.ConnectInfo).ToArray() ); if (firstSpanEquipmentConnectResult.IsFailed) { return(firstSpanEquipmentConnectResult); } // Connect the second span equipment to terminals var secondSpanEquipmentAR = _eventStore.Aggregates.Load <SpanEquipmentAR>(secondSpanEquipment.SpanEquipment.Id); var secondSpanEquipmentConnectResult = secondSpanEquipmentAR.ConnectSpanSegmentsToSimpleTerminals( cmdContext: cmdContext, routeNodeId: routeNodeId, connects: secondSpanEquipment.Connects.Select(c => c.ConnectInfo).ToArray() ); if (secondSpanEquipmentConnectResult.IsFailed) { return(secondSpanEquipmentConnectResult); } _eventStore.Aggregates.Store(firstSpanEquipmentAR); _eventStore.Aggregates.Store(secondSpanEquipmentAR); NotifyExternalServicesAboutConnectivityChange(firstSpanEquipment.SpanEquipment.Id, secondSpanEquipment.SpanEquipment.Id, routeNodeId); return(Result.Ok()); }
private Result ConnectSameEquipment(CommandContext cmdContext, Guid routeNodeId, SpanEquipmentWithConnectsHolder spanEquipmentToConnect) { if (spanEquipmentToConnect.Connects.Count != 2) { return (Result.Fail(new ConnectSpanSegmentsAtRouteNodeError( ConnectSpanSegmentsAtRouteNodeErrorCodes.SAME_SPAN_EQUIPMENT_CONNECTIONS_MUST_BE_DONE_TWO_SPAN_SEGMENTS_AT_THE_TIME, $"Cannot connect the span segments specified because {spanEquipmentToConnect.Connects.Count} segments are selected. Two span segments were expected.") )); } // Get the two segments from graph if (!_utilityNetwork.Graph.TryGetGraphElement <IUtilityGraphSegmentRef>(spanEquipmentToConnect.Connects[0].ConnectInfo.SegmentId, out var utilityGraphSegmentRefToConnect1)) { throw new ApplicationException($"Failed to lookup span segment with id: {spanEquipmentToConnect.Connects[0].ConnectInfo.SegmentId}"); } if (!_utilityNetwork.Graph.TryGetGraphElement <IUtilityGraphSegmentRef>(spanEquipmentToConnect.Connects[1].ConnectInfo.SegmentId, out var utilityGraphSegmentRefToConnect2)) { throw new ApplicationException($"Failed to lookup span segment with id: {spanEquipmentToConnect.Connects[1].ConnectInfo.SegmentId}"); } // If segment 1 -> (node) -> segment 2 if (utilityGraphSegmentRefToConnect1.SpanSegment(_utilityNetwork).ToNodeOfInterestIndex == utilityGraphSegmentRefToConnect2.SpanSegment(_utilityNetwork).FromNodeOfInterestIndex) { spanEquipmentToConnect.Connects[0].ConnectInfo.ConnectionDirection = SpanSegmentToTerminalConnectionDirection.FromSpanSegmentToTerminal; spanEquipmentToConnect.Connects[1].ConnectInfo.ConnectionDirection = SpanSegmentToTerminalConnectionDirection.FromTerminalToSpanSegment; } // If segment 2-> (node)-> segment 1 else if (utilityGraphSegmentRefToConnect1.SpanSegment(_utilityNetwork).FromNodeOfInterestIndex == utilityGraphSegmentRefToConnect2.SpanSegment(_utilityNetwork).ToNodeOfInterestIndex) { spanEquipmentToConnect.Connects[0].ConnectInfo.ConnectionDirection = SpanSegmentToTerminalConnectionDirection.FromTerminalToSpanSegment; spanEquipmentToConnect.Connects[1].ConnectInfo.ConnectionDirection = SpanSegmentToTerminalConnectionDirection.FromSpanSegmentToTerminal; } else { return (Result.Fail(new ConnectSpanSegmentsAtRouteNodeError( ConnectSpanSegmentsAtRouteNodeErrorCodes.SAME_SPAN_EQUIPMENT_U_TURN_CONNECTIONS_NOT_ALLOWED, $"Cannot connect the span segments specified because the two span segments selected will create an u-turn.") )); } // Create junction/terminal ids used to connect span segments var junctionId = Guid.NewGuid(); foreach (var connect in spanEquipmentToConnect.Connects) { connect.ConnectInfo.TerminalId = junctionId; } // Connect span equipment to terminals var spanEquipmentAR = _eventStore.Aggregates.Load <SpanEquipmentAR>(spanEquipmentToConnect.SpanEquipment.Id); var spanEquipmentConnectResult = spanEquipmentAR.ConnectSpanSegmentsToSimpleTerminals( cmdContext: cmdContext, routeNodeId: routeNodeId, connects: spanEquipmentToConnect.Connects.Select(c => c.ConnectInfo).ToArray() ); if (spanEquipmentConnectResult.IsFailed) { return(spanEquipmentConnectResult); } _eventStore.Aggregates.Store(spanEquipmentAR); NotifyExternalServicesAboutConnectivityChange(spanEquipmentToConnect.SpanEquipment.Id, routeNodeId); return(Result.Ok()); }
private Result MergeSpanEquipment(CommandContext cmdContext, Guid routeNodeId, SpanEquipmentWithConnectsHolder firstSpanEquipment, SpanEquipmentWithConnectsHolder secondSpanEquipment) { // Merge the first span equipment with the second one var firstSpanEquipmentAR = _eventStore.Aggregates.Load <SpanEquipmentAR>(firstSpanEquipment.SpanEquipment.Id); var firstSpanEquipmentConnectResult = firstSpanEquipmentAR.Merge( cmdContext: cmdContext, routeNodeId: routeNodeId, secondSpanEquipment.SpanEquipment ); if (firstSpanEquipmentConnectResult.IsFailed) { return(firstSpanEquipmentConnectResult); } var firstSpanEquipmentWalk = GetInterestInformation(firstSpanEquipment.SpanEquipment); var secondSpanEquipmentWalk = GetInterestInformation(secondSpanEquipment.SpanEquipment); // Update interest of the first span equipment to cover both span equipments var newSegmentIds = MergeWalks(firstSpanEquipmentWalk, secondSpanEquipmentWalk); var updateWalkOfInterestCommand = new UpdateWalkOfInterest(firstSpanEquipment.SpanEquipment.WalkOfInterestId, newSegmentIds); var updateWalkOfInterestCommandResult = _commandDispatcher.HandleAsync <UpdateWalkOfInterest, Result <RouteNetworkInterest> >(updateWalkOfInterestCommand).Result; if (updateWalkOfInterestCommandResult.IsFailed) { return(updateWalkOfInterestCommandResult); } // Remove the second span equipment var secondSpanEquipmentAR = _eventStore.Aggregates.Load <SpanEquipmentAR>(secondSpanEquipment.SpanEquipment.Id); var removeSpanEquipment = secondSpanEquipmentAR.Remove(cmdContext); if (removeSpanEquipment.IsSuccess) { // Remember to remove the walk of interest as well var unregisterInterestCmd = new UnregisterInterest(secondSpanEquipment.SpanEquipment.WalkOfInterestId); var unregisterInterestCmdResult = _commandDispatcher.HandleAsync <UnregisterInterest, Result>(unregisterInterestCmd).Result; if (unregisterInterestCmdResult.IsFailed) { throw new ApplicationException($"Failed to unregister interest: {secondSpanEquipment.SpanEquipment.WalkOfInterestId} of span equipment: {secondSpanEquipment.SpanEquipment.Id} in RemoveSpanStructureFromSpanEquipmentCommandHandler Error: {unregisterInterestCmdResult.Errors.First().Message}"); } } _eventStore.Aggregates.Store(firstSpanEquipmentAR); _eventStore.Aggregates.Store(secondSpanEquipmentAR); NotifyExternalServicesAboutMerge(firstSpanEquipment.SpanEquipment.Id, updateWalkOfInterestCommandResult.Value.RouteNetworkElementRefs.ToArray()); return(Result.Ok()); }