FUNCTION_BLOCK "FB_LineEmptyAnalyze"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      arLineBlk { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Array[1.."cNoLines"] of "stStorageLine";   // Daten pro Linie
   END_VAR

   VAR_OUTPUT 
      str_OutState : Struct
         n_LineMAX : USInt;
         arr_OrderLines : Array[1..21] of USInt;
         arr_StorageLvl : Array[1..21] of USInt;
      END_STRUCT;
   END_VAR

   VAR 
      udt_Blk { S7_SetPoint := 'False'} : "udt_LineStoreAnalyse";
   END_VAR

   VAR_TEMP 
      str_TempBlk : Struct
         tmpValue : Int;
         tmpIDX : Int;
         arr_StorageLvl : Array[1..21] of USInt;
         arr_Indizes : Array[1..21] of USInt;
      END_STRUCT;
   END_VAR


BEGIN
	
	REGION Info
	(* Company: Schönenberger Systeme GmbH / (C) Copyright (2022). All rights reserved.
	-----------------------------------------------------------------------------------------
	Title: FB_LineEmptyAnalyze
	Comment/Function: Analyze Empty Line level
	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-08-26 | -                  |                  | Header added on 26.08.2025
	                                                                   
	*)
	END_REGION
	
	
	
	// Füllgrad der Linien auswerten
	FOR #udt_Blk.str_Static.n_StorageLvlIdx := 1 TO "cNoLines"(* 19 *) DO
	    #udt_Blk.str_Static.n_loaded := 0;   // Zähler zurücksetzen
	    FOR #udt_Blk.str_Static.n_HelpIDX := 1 TO "cNoPositions"(* 108 *) DO
	        IF #arLineBlk[#udt_Blk.str_Static.n_StorageLvlIdx].arCarrier[#udt_Blk.str_Static.n_HelpIDX].nBarcode <> 0
	            AND NOT #arLineBlk[#udt_Blk.str_Static.n_StorageLvlIdx].arCarrier[#udt_Blk.str_Static.n_HelpIDX].bStatus.%X1 // Wenn Barcode ungleich 0, ist die Position belegt
	        THEN
	            #udt_Blk.str_Static.n_loaded += 1;   // Zähler erhöhen
	        END_IF;
	    END_FOR;
	    
	    
	    #udt_Blk.str_State.arr_StorageLvl[#udt_Blk.str_Static.n_StorageLvlIdx] := #udt_Blk.str_Static.n_loaded;    // Ergebnis in Output schreiben
	    #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_StorageLvlIdx] := #udt_Blk.str_Static.n_loaded;           // Für Sortierung merken
	    #str_TempBlk.arr_Indizes[#udt_Blk.str_Static.n_StorageLvlIdx] := #udt_Blk.str_Static.n_StorageLvlIdx;       // Ursprünglichen Index merken
	    
	END_FOR;
	
	// Sortieren nach Füllgrad (absteigend)
	FOR #udt_Blk.str_Static.n_StorageLvlIdx := 1 TO "cNoLines"(* 18 *) DO
	    FOR #udt_Blk.str_Static.n_HelpIDX := #udt_Blk.str_Static.n_StorageLvlIdx + 1 TO "cNoLines"(* 19 *) DO
	        IF #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_StorageLvlIdx] < #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_HelpIDX]
	            // Wenn aktueller Füllgrad kleiner als nächster, dann tauschen
	        THEN
	            //Füllgrad tauschen
	            #str_TempBlk.tmpValue := #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_StorageLvlIdx];
	            #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_StorageLvlIdx] := #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_HelpIDX];
	            #str_TempBlk.arr_StorageLvl[#udt_Blk.str_Static.n_HelpIDX] := #str_TempBlk.tmpValue;
	            
	            //Indizes mitziehen
	            #str_TempBlk.tmpIDX := #str_TempBlk.arr_Indizes[#udt_Blk.str_Static.n_StorageLvlIdx];
	            #str_TempBlk.arr_Indizes[#udt_Blk.str_Static.n_StorageLvlIdx] := #str_TempBlk.arr_Indizes[#udt_Blk.str_Static.n_HelpIDX];
	            #str_TempBlk.arr_Indizes[#udt_Blk.str_Static.n_HelpIDX] := #str_TempBlk.tmpIDX;
	            
	        END_IF;
	        
	    END_FOR;
	    
	    ;
	END_FOR;
	
	//Ergebnis zuweisen   
	#udt_Blk.str_State.arr_OrderLines := #str_TempBlk.arr_Indizes;         // Sortierte Indizes in den Output schreiben
	#udt_Blk.str_State.n_LineMAX := #str_TempBlk.arr_Indizes[1];           // Index der Linie mit dem höchsten Füllgrad (an erster Stelle)
	
	
	//Output Mapping
	#str_OutState := #udt_Blk.str_State;
	
	
	
	
	
END_FUNCTION_BLOCK

