FUNCTION_BLOCK "FB_RearrangeSequencer"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      x_In_Reset : Bool;
      n_In_BlockID : Int;
   END_VAR

   VAR_IN_OUT 
      udt_InOutStorageSite : "udt_StorageSite";
   END_VAR

   VAR 
      arrint_PairA : Array[1..4] of Int;
      arrint_PairB : Array[1..4] of Int;
      xFoundPair : Bool;
      xFoundSingle : Bool;
      nNextPair : Int;
      nNextSingle : Int;
      nStartPair : Int;
      nCheckPair : Int;
      nPairIdx : Int;
      nStartSingle : Int;
      nCheckSingle : Int;
      nSingleIdx : Int;
      arrGlobalIndexOfBlockPos : Array[0..4] of Int;
      nBlockPosIdx : Int;
      nGlobalStorageIdx : Int;
   END_VAR

   VAR_TEMP 
      nPairLoopIndex : Int;
      nStartPairIndex : Int;
      nCheckPairIndex : Int;
      nSingleLoopIndex : Int;
      nStartSingleIndex : Int;
      nCheckSingleIndex : Int;
      ActivePosA : Int;   // aktuelle aktive Position A im Block (1–4)
      ActivePosB : Int;   // aktuelle aktive Position B im Block (1–4)
      GlobalIndexA : Int;   // globaler Index des aktiven Lagers A (1–12)
      GlobalIndexB : Int;   // globaler Index des aktiven Lagers B (1–12)
   END_VAR


BEGIN
	
	REGION Info
	(* Company: Schönenberger Systeme GmbH / (C) Copyright (2022). All rights reserved.
	-----------------------------------------------------------------------------------------
	Title: FB_rearrangeSequencer
	Comment/Function: Manage the rearrange releases
	Library/Family: -
	Author: department: "Automatisierung" ; person in charge / contact: C.Nottelmann (Automated Intelligence)
	Target System: CPU 1518F-4 PN/DP
	Engineering: TIA Portal V20
	Restrictions: -
	Requirements: -
	-----------------------------------------------------------------------------------------
	Change log table:
	Version     | Date       | Signature (Safety) | Expert in charge | Changes applied
	------------|------------|--------------------|------------------|-----------------------
	001.000.000 | 2025-11-10 | -                  |                  | Header added on 10.11.2025
	                                                                   
	*)
	END_REGION
	
	
	
	REGION Allowed Combinations
	    
	    // erlaubte Paare in Block-Positionen
	    // Pair A [1, 2, 2, 1]
	    #arrint_PairA[1] := 1;
	    #arrint_PairA[2] := 2;
	    #arrint_PairA[3] := 2;
	    #arrint_PairA[4] := 1;
	    
	    // Pair B [3, 4, 3, 4]
	    #arrint_PairB[1] := 3;
	    #arrint_PairB[2] := 4;
	    #arrint_PairB[3] := 3;
	    #arrint_PairB[4] := 4;
	    
	    
	END_REGION
	
	REGION Block Mapping
	    
	    // Block 1: Lager 1..4 → Pos 1..4
	    #udt_InOutStorageSite.arrudt_Storage[1].udt_RearrangeStorageCtrl.nBlockID := 1;
	    #udt_InOutStorageSite.arrudt_Storage[1].udt_RearrangeStorageCtrl.nPosInBlock := 1;
	    #udt_InOutStorageSite.arrudt_Storage[2].udt_RearrangeStorageCtrl.nBlockID := 1;
	    #udt_InOutStorageSite.arrudt_Storage[2].udt_RearrangeStorageCtrl.nPosInBlock := 2;
	    #udt_InOutStorageSite.arrudt_Storage[3].udt_RearrangeStorageCtrl.nBlockID := 1;
	    #udt_InOutStorageSite.arrudt_Storage[3].udt_RearrangeStorageCtrl.nPosInBlock := 3;
	    #udt_InOutStorageSite.arrudt_Storage[4].udt_RearrangeStorageCtrl.nBlockID := 1;
	    #udt_InOutStorageSite.arrudt_Storage[4].udt_RearrangeStorageCtrl.nPosInBlock := 4;
	    
	    // Block 2: Lager 5..8 → Pos 1..4
	    #udt_InOutStorageSite.arrudt_Storage[5].udt_RearrangeStorageCtrl.nBlockID := 2;
	    #udt_InOutStorageSite.arrudt_Storage[5].udt_RearrangeStorageCtrl.nPosInBlock := 1;
	    #udt_InOutStorageSite.arrudt_Storage[6].udt_RearrangeStorageCtrl.nBlockID := 2;
	    #udt_InOutStorageSite.arrudt_Storage[6].udt_RearrangeStorageCtrl.nPosInBlock := 2;
	    #udt_InOutStorageSite.arrudt_Storage[7].udt_RearrangeStorageCtrl.nBlockID := 2;
	    #udt_InOutStorageSite.arrudt_Storage[7].udt_RearrangeStorageCtrl.nPosInBlock := 3;
	    #udt_InOutStorageSite.arrudt_Storage[8].udt_RearrangeStorageCtrl.nBlockID := 2;
	    #udt_InOutStorageSite.arrudt_Storage[8].udt_RearrangeStorageCtrl.nPosInBlock := 4;
	    
	    // Block 3: Lager 9..12 → Pos 1..4
	    #udt_InOutStorageSite.arrudt_Storage[9].udt_RearrangeStorageCtrl.nBlockID := 3;
	    #udt_InOutStorageSite.arrudt_Storage[9].udt_RearrangeStorageCtrl.nPosInBlock := 1;
	    #udt_InOutStorageSite.arrudt_Storage[10].udt_RearrangeStorageCtrl.nBlockID := 3;
	    #udt_InOutStorageSite.arrudt_Storage[10].udt_RearrangeStorageCtrl.nPosInBlock := 2;
	    #udt_InOutStorageSite.arrudt_Storage[11].udt_RearrangeStorageCtrl.nBlockID := 3;
	    #udt_InOutStorageSite.arrudt_Storage[11].udt_RearrangeStorageCtrl.nPosInBlock := 3;
	    #udt_InOutStorageSite.arrudt_Storage[12].udt_RearrangeStorageCtrl.nBlockID := 3;
	    #udt_InOutStorageSite.arrudt_Storage[12].udt_RearrangeStorageCtrl.nPosInBlock := 4;
	    
	    
	    
	    
	END_REGION
	
	
	
	REGION Logik
	    
	    
	    
	    // ---- Reset ----
	    IF #x_In_Reset THEN
	        #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne := 0;
	        #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo := 0;
	        #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.xIsPair := FALSE;
	        #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nLastPairSelected := 0;
	        #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nLastSingle := 0;
	        
	        // Grants im Block zurücksetzen
	        FOR #nGlobalStorageIdx := 1 TO 12 DO
	            IF #udt_InOutStorageSite.arrudt_Storage[#nGlobalStorageIdx].udt_RearrangeStorageCtrl.nBlockID = #n_In_BlockID THEN
	                #udt_InOutStorageSite.arrudt_Storage[#nGlobalStorageIdx].udt_RearrangeStorageState.xRearrangeGrant := FALSE;
	                #udt_InOutStorageSite.arrudt_Storage[#nGlobalStorageIdx].udt_RearrangeStorageState.xIsInPair := FALSE;
	            END_IF;
	        END_FOR;
	        
	    ELSE
	        // ---- Mapping: finde globale Lager-Indices für Pos 1..4 dieses Blocks ----
	        FOR #nBlockPosIdx := 1 TO 4 DO
	            #arrGlobalIndexOfBlockPos[#nBlockPosIdx] := 0;
	            FOR #nGlobalStorageIdx := 1 TO 12 DO
	                IF (#udt_InOutStorageSite.arrudt_Storage[#nGlobalStorageIdx].udt_RearrangeStorageCtrl.nBlockID = #n_In_BlockID)
	                    AND (#udt_InOutStorageSite.arrudt_Storage[#nGlobalStorageIdx].udt_RearrangeStorageCtrl.nPosInBlock = #nBlockPosIdx) THEN
	                    #arrGlobalIndexOfBlockPos[#nBlockPosIdx] := #nGlobalStorageIdx;
	                    EXIT;
	                END_IF;
	            END_FOR;
	        END_FOR;
	        
	        // ---- Kandidatensuche: Paar (beide UML-Req und ggf. Block-Ready) ----
	        #xFoundPair := FALSE;
	        #nNextPair := 0;
	        //Startindex bestimmen
	        #nStartPair := #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nLastPairSelected + 1;
	        IF #nStartPair > 4 THEN
	            #nStartPair := 1;
	        END_IF;
	        
	        #nCheckPair := #nStartPair;
	        // Schleife über alle 4 möglichen Paar-Kombinationen (1,3), (2,4), (2,3), (1,4)
	        FOR #nPairLoopIndex := 1 TO 4 DO
	            // Prüfen, ob beide Positionen im Block gültig belegt sind
	            IF (#arrGlobalIndexOfBlockPos[#arrint_PairA[#nCheckPair]] <> 0) AND (#arrGlobalIndexOfBlockPos[#arrint_PairB[#nCheckPair]] <> 0)
	            THEN
	                // Beide Lager aktiviert und haben Umlageranforderung?
	                IF #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#arrint_PairA[#nCheckPair]]].udt_RearrangeStorageCtrl.xEnableReaarrange
	                    AND #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#arrint_PairB[#nCheckPair]]].udt_RearrangeStorageCtrl.xEnableReaarrange
	                    AND #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#arrint_PairA[#nCheckPair]]].udt_RearrangeStorageCtrl.xRearrangeRequest
	                    AND #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#arrint_PairB[#nCheckPair]]].udt_RearrangeStorageCtrl.xRearrangeRequest
	                    AND (NOT #udt_InOutStorageSite.arrudt_Storage[ #arrGlobalIndexOfBlockPos[ #arrint_PairA[#nCheckPair] ] ].udt_RearrangeStorageState.xRemoveGrant) AND
	                    (NOT #udt_InOutStorageSite.arrudt_Storage[ #arrGlobalIndexOfBlockPos[ #arrint_PairB[#nCheckPair] ] ].udt_RearrangeStorageState.xRemoveGrant) AND
	                    (NOT #udt_InOutStorageSite.arrudt_Storage[ #arrGlobalIndexOfBlockPos[ #arrint_PairA[#nCheckPair] ] ].udt_RearrangeStorageState.xRemoveBusy)  AND
	                    (NOT #udt_InOutStorageSite.arrudt_Storage[ #arrGlobalIndexOfBlockPos[ #arrint_PairB[#nCheckPair] ] ].udt_RearrangeStorageState.xRemoveBusy)
	                    AND (NOT #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#arrint_PairA[#nCheckPair]]].udt_RearrangeStorageState.xEmptyBusy)
	                    AND (NOT #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#arrint_PairB[#nCheckPair]]].udt_RearrangeStorageState.xEmptyBusy)
	                    
	                THEN
	                    // optional:  Block muss für Umlagern bereit sein
	                    IF (#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupCtrl.xReadyRearrange) THEN
	                        #nNextPair := #nCheckPair;
	                        #xFoundPair := TRUE;
	                        EXIT;
	                    END_IF;
	                END_IF;
	            END_IF;
	            #nCheckPair := #nCheckPair + 1;
	            IF #nCheckPair > 4 THEN
	                #nCheckPair := 1;
	            END_IF;
	        END_FOR;
	        
	        
	        // ---- Kandidatensuche: Single (falls kein Paar) ----
	        #xFoundSingle := FALSE;
	        #nNextSingle := 0;
	        IF NOT #xFoundPair THEN
	            #nStartSingle := #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nLastSingle + 1;
	            IF #nStartSingle > 4 THEN
	                #nStartSingle := 1;
	            END_IF;
	            #nCheckSingle := #nStartSingle;
	            FOR #nSingleIdx := 1 TO 4 DO
	                IF (#arrGlobalIndexOfBlockPos[#nCheckSingle] <> 0)
	                    AND #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#nCheckSingle]].udt_RearrangeStorageCtrl.xEnableReaarrange
	                    AND #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#nCheckSingle]].udt_RearrangeStorageCtrl.xRearrangeRequest
	                    AND #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupCtrl.xReadyRearrange AND
	                    // Interlocks: keine parallele Auslager-Aktivität/Grant
	                    (NOT #udt_InOutStorageSite.arrudt_Storage[ #arrGlobalIndexOfBlockPos[#nCheckSingle] ].udt_RearrangeStorageState.xRemoveGrant) AND
	                    (NOT #udt_InOutStorageSite.arrudt_Storage[ #arrGlobalIndexOfBlockPos[#nCheckSingle] ].udt_RearrangeStorageState.xRemoveBusy)
	                THEN
	                    #nNextSingle := #nCheckSingle;
	                    #xFoundSingle := TRUE;
	                    EXIT;
	                END_IF;
	                #nCheckSingle := #nCheckSingle + 1;
	                IF #nCheckSingle > 4 THEN
	                    #nCheckSingle := 1;
	                END_IF;
	            END_FOR;
	        END_IF;
	        
	        
	        // ---- Zustand aktualisieren ----
	        // aktiv laufende Grants auf diesen Block bezogen pflegen
	        // (Mitglieder dürfen unabhängig fertig werden)
	        // 
	        // A)
	        // Wenn nichts aktiv: starten (Paar vor Single)
	        
	        IF (#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne = 0)
	            AND (#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo = 0) THEN
	            // alle Grants dieses Blocks resetten
	            FOR #nBlockPosIdx := 1 TO 4 DO
	                IF #arrGlobalIndexOfBlockPos[#nBlockPosIdx] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#nBlockPosIdx]].udt_RearrangeStorageState.xRearrangeGrant := FALSE;
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#nBlockPosIdx]].udt_RearrangeStorageState.xIsInPair := FALSE;
	                END_IF;
	            END_FOR;
	            // Paar gefunden
	            IF #xFoundPair THEN
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne := #arrint_PairA[#nNextPair];
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo := #arrint_PairB[#nNextPair];
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.xIsPair := TRUE;
	                
	                // Grants setzen
	                IF #arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xRearrangeGrant := TRUE;
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xIsInPair := TRUE;
	                END_IF;
	                IF #arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo]].udt_RearrangeStorageState.xRearrangeGrant := TRUE;
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo]].udt_RearrangeStorageState.xIsInPair := TRUE;
	                END_IF;
	            //Single gefunden
	            ELSIF #xFoundSingle THEN
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne := #nNextSingle;
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo := 0;
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.xIsPair := FALSE;
	                
	                IF #arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xRearrangeGrant := TRUE;
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xIsInPair := FALSE;
	                END_IF;
	            END_IF;
	        
	            // B)
	            // Wenn aktiv: Fortschritt überwachen, Mitglieder ggf. freigeben
	        ELSE
	            // aktive globale Indizes ermitteln
	            #ActivePosA := #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne;
	            #ActivePosB := #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo;
	            
	            #GlobalIndexA := 0;
	            #GlobalIndexB := 0;
	            
	            IF (#ActivePosA >= 1) AND (#ActivePosA <= 4) THEN
	                #GlobalIndexA := #arrGlobalIndexOfBlockPos[#ActivePosA];
	            END_IF;
	            
	            IF (#ActivePosB >= 1) AND (#ActivePosB <= 4) THEN
	                #GlobalIndexB := #arrGlobalIndexOfBlockPos[#ActivePosB];
	            END_IF;
	            
	            // Mitglied A fertig?
	            IF (#GlobalIndexA <> 0) THEN //nur reingehen wenn <> 0
	                IF #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexA].udt_RearrangeStorageState.xRearrangeGrant
	                    AND (#udt_InOutStorageSite.arrudt_Storage[#GlobalIndexA].udt_RearrangeStorageState.xRearrange_Done
	                    OR (NOT #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexA].udt_RearrangeStorageCtrl.xRearrangeRequest)
	                    OR (NOT #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexA].udt_RearrangeStorageCtrl.xEnableReaarrange))
	                THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexA].udt_RearrangeStorageState.xRearrangeGrant := FALSE;
	                    #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne := 0;
	                END_IF;
	            END_IF;
	            
	            // Mitglied B fertig?
	            IF (#GlobalIndexB <> 0) THEN //nur reingehen wenn <> 0 
	                IF #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexB].udt_RearrangeStorageState.xRearrangeGrant
	                    AND (#udt_InOutStorageSite.arrudt_Storage[#GlobalIndexB].udt_RearrangeStorageState.xRearrange_Done
	                    OR (NOT #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexB].udt_RearrangeStorageCtrl.xRearrangeRequest)
	                    OR (NOT #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexB].udt_RearrangeStorageCtrl.xEnableReaarrange))
	                THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#GlobalIndexB].udt_RearrangeStorageState.xRearrangeGrant := FALSE;
	                    #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo := 0;
	                END_IF;
	            END_IF;
	            
	        
	        // wenn beide 0 -> Abschluss & Nachfolge (Paar vor Single)
	            IF (#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne = 0) AND (#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo = 0) THEN
	            // Fairnessmarker setzen
	                IF #xFoundPair THEN
	                    #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nLastPairSelected := #nNextPair;
	                ELSIF #xFoundSingle THEN
	                    #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nLastSingle := #nNextSingle;
	                END_IF;
	            
	            // direkt Nachfolge starten
	                FOR #nBlockPosIdx := 1 TO 4 DO
	                    IF #arrGlobalIndexOfBlockPos[#nBlockPosIdx] <> 0 THEN
	                        #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#nBlockPosIdx]].udt_RearrangeStorageState.xIsInPair := FALSE;
	                END_IF;
	            END_FOR;
	            
	            IF #xFoundPair THEN
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne := #arrint_PairA[#nNextPair];
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo := #arrint_PairB[#nNextPair];
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.xIsPair := TRUE;
	                
	                IF #arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xRearrangeGrant := TRUE;
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xIsInPair := TRUE;
	                END_IF;
	                IF #arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo]].udt_RearrangeStorageState.xRearrangeGrant := TRUE;
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo]].udt_RearrangeStorageState.xIsInPair := TRUE;
	                END_IF;
	                
	            ELSIF #xFoundSingle THEN
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne := #nNextSingle;
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiveTwo := 0;
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.xIsPair := FALSE;
	                
	                IF #arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne] <> 0 THEN
	                    #udt_InOutStorageSite.arrudt_Storage[#arrGlobalIndexOfBlockPos[#udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.nActiceOne]].udt_RearrangeStorageState.xRearrangeGrant := TRUE;
	                END_IF;
	            ELSE
	                #udt_InOutStorageSite.arrudt_BlockGroup[#n_In_BlockID].udt_BlockGroupState.xIsPair := FALSE;
	            END_IF;
	        END_IF;
	    END_IF;
	END_IF;
	        
	        
	        
	        
	        
	        
	        
	        
	        
	        
	    END_REGION
END_FUNCTION_BLOCK

