Imports System.Collections.ObjectModel Imports EgtUILib Imports EgtWPFLib5 Public Class UnloadingAreaVM Inherits VMBase Friend m_refStatuMachine2VM As StatusMachine2VM Friend m_refTablePartWindowVM As TablePartWindowVM ' disabilito i comandi della pagina Private m_EnablePage As Boolean = True Public Property EnablePage As Boolean Get Return m_EnablePage End Get Set(value As Boolean) m_EnablePage = value NotifyPropertyChanged("EnablePage") End Set End Property ' lista dei magazzini disponibii (A, B) Private m_WarehouseList As New ObservableCollection(Of WarehouseVM) Public ReadOnly Property WarehouseList As ObservableCollection(Of WarehouseVM) Get Return m_WarehouseList End Get End Property ' definsice se deve ricalcolato la disposizione dei pezzi nel magazzino Private m_bOrganizeWarehouse As Boolean = True Public Property bOrganizeWarehouse As Boolean Get Return m_bOrganizeWarehouse End Get Set(value As Boolean) m_bOrganizeWarehouse = value End Set End Property ' indica il magazzino attivo (letto dalla macchina) Private m_ActiveWarehouse As Warehouses Public ReadOnly Property ActiveWarehouse As Warehouses Get Return m_ActiveWarehouse End Get End Property ' attendo la definizione dei pezzi manuali, Associato al bottone Reserve Private m_IsChecked_Manual As Boolean = False Public Property IsChecked_Manual As Boolean Get ' se la lastra è prenotata e non ci sono pezzi sul tavolo If m_IsChecked_Manual AndAlso GetParts(Place.ON_TABLE).Count = 0 Then Map.refSceneHostVM.MainScene.SetObjFilterForSel(False, False, True, False, False) Else Map.refSceneHostVM.MainScene.SetObjFilterForSel(False, False, False, False, False) 'Map.refSceneHostVM.MainScene.SetStatusNull() End If Return m_IsChecked_Manual End Get Set(value As Boolean) m_IsChecked_Manual = value NotifyPropertyChanged("ManualUnload") NotifyPropertyChanged("VisibilityTextReserve") NotifyPropertyChanged("IsChecked_Manual") End Set End Property ' apre la finestra per definire lo stato della macchina Private m_StatusMachine2 As Boolean = False Public Property StatusMachine2 As Boolean Get Return m_StatusMachine2 End Get Set(value As Boolean) m_StatusMachine2 = value If value Then m_refStatuMachine2VM = New StatusMachine2VM() m_refStatuMachine2VM.m_RefStusMachine2V.Show() EnablePage = False Else m_refStatuMachine2VM = Nothing EnablePage = True End If NotifyPropertyChanged("StatusMachine2") End Set End Property ' messaggio da mostrare a video Private m_OutputMessage As String Public Property OutputMessage As String Get Return m_OutputMessage End Get Set(value As String) m_OutputMessage = value End Set End Property ' colore del carattere del messaggio Private m_OutputMessage_Foreground As Brush = Brushes.Black Public Property OutputMessage_Foreground As Brush Get Return m_OutputMessage_Foreground End Get Set(value As Brush) m_OutputMessage_Foreground = value End Set End Property #Region "PARTS" ' elenco pezzi da scaricare (già ordinati) definita dalla funzione: CamAuto/MyUpdateVacuumsForUnloading() Private m_ListPart As New List(Of Part) Friend Property ListPart As List(Of Part) Get Return m_ListPart End Get Set(value As List(Of Part)) m_ListPart = value End Set End Property ' salvo locamente il pezzo correntemente manipolato dallo scaricatore Private m_CurrPartTable1 As Part Public Property CurrPartTable1 As Part Get Return m_CurrPartTable1 End Get Set(value As Part) m_CurrPartTable1 = value End Set End Property ' salvo locamente il pezzo correntemente manipolato dal pallettizzatore Private m_CurrPartTable2 As Part Public Property CurrPartTable2 As Part Get Return m_CurrPartTable2 End Get Set(value As Part) m_CurrPartTable2 = value End Set End Property ' salvo localmente l'ultimo Box utilizzato nel magazzino Private m_CurrBox As Box Public Property CurrBox As Box Get Return m_CurrBox End Get Set(value As Box) m_CurrBox = value End Set End Property ' salvo l'IdProj attualmente in lavorazione sulla tavola 2 Private m_IdProjTable2 As New Proj(-1) Public Property IdProjTable2 As Proj Get Return m_IdProjTable2 End Get Set(value As Proj) m_IdProjTable2 = value End Set End Property ' permette la visualizzazione del bottone "List Part" Public ReadOnly Property ShowTabParts As Visibility Get Return If(GetMainPrivateProfileInt("General", "ShowTabParts", 0) = 1, Visibility.Visible, Visibility.Hidden) End Get End Property Private m_WindowListPart As Boolean = False Public Property WindowListPart As Boolean Get Return m_WindowListPart End Get Set(value As Boolean) m_WindowListPart = value If value Then m_refTablePartWindowVM = New TablePartWindowVM(Map.refMainWindowVM.MainWindowM.nProjInd) m_refTablePartWindowVM.refTablePartWindowV.Show() Else m_refStatuMachine2VM = Nothing End If NotifyPropertyChanged("StatusMachine2") End Set End Property #End Region ' PARTS #Region "OFFSET PALLET/RACK" ' quanto fuori dalle corse devono essere posizionati i pezzi per determinare le giuste ventose Private m_OffsetRullerX As Double = 0 Public ReadOnly Property OffsetRullerX As Double Get Return m_OffsetRullerX End Get End Property Private m_OffsetRullerY As Double = 0 Public ReadOnly Property OffsetRullerY As Double Get Return m_OffsetRullerY End Get End Property ' le origini dei pallet sono in basso a siniatra (nel piano xy), gli offset restituiscono il centro Private m_OffsetPalletX As Double = 0 Public ReadOnly Property OffsetPalletX As Double Get Return m_OffsetPalletX End Get End Property Private m_OffsetPalletY As Double = 0 Public ReadOnly Property OffsetPalletY As Double Get Return m_OffsetPalletY End Get End Property Private m_OffsetPalletZ As Double = 0 Public ReadOnly Property OffsetPalletZ As Double Get Return m_OffsetPalletZ End Get End Property ' le origini sono in mezzo al rack (nel piano xy) Private m_OffsetRackX As Double = 0 Public ReadOnly Property OffsetRackX As Double Get Return m_OffsetRackX End Get End Property Private m_OffsetRackY As Double = 0 Public ReadOnly Property OffsetRackY As Double Get Return m_OffsetRackY End Get End Property Private m_OffsetRackZ As Double = 0 Public ReadOnly Property OffsetRackZ As Double Get Return m_OffsetRackZ End Get End Property Private m_AngRack As Double Public ReadOnly Property AngRack As Double Get Return m_AngRack End Get End Property ' altezza massima sul pallet Private m_MaxHeight As Double Public ReadOnly Property MaxHeight As Double Get Return m_MaxHeight End Get End Property ' lunghezza massima caricabile su pallet Private m_MaxLength As Double Public ReadOnly Property MaxLength As Double Get Return m_MaxLength End Get End Property '' larghezza massima caricabile su pallet 'Private m_MaxWidth As Double 'Public ReadOnly Property MaxWidth As Double ' Get ' Return m_MaxWidth ' End Get 'End Property Private m_MaxTollerance As Double Public ReadOnly Property MaxTollerance As Double Get Return m_MaxTollerance End Get End Property Private m_MinTollerance As Double Public ReadOnly Property MinTollerance As Double Get Return m_MinTollerance End Get End Property ' numero massimo di pezzi su rack Private m_MaxTile As Double Public ReadOnly Property MaxTile As Double Get Return m_MaxTile End Get End Property ' dimensione X del telaio porta ventose Private m_VacuumDimX As Double = 1350 Public ReadOnly Property VacuumDimX As Double Get Return m_VacuumDimX End Get End Property ' dimensione Y del telaio porta ventose Private m_VacuumDimY As Double = 350 Public ReadOnly Property VacuumDimY As Double Get Return m_VacuumDimY End Get End Property #End Region ' Offset pallet/rack #Region "PROPERTIES" ' bottone per la selezione della scena Public Property refScenaIsChecked As Boolean Get Return Map.refMainWindowVM.SceneIsChecked End Get Set(value As Boolean) Map.refMainWindowVM.SceneIsChecked = value End Set End Property ' notifico nella grafica la percentuale di pezzi presenti sulla tavola Public ReadOnly Property Table1Percentage As String Get ' numero di pezzi buoni rimasti sulla tavola Dim nTable As Integer = GetParts(Place.ON_TABLE).Count ' numero di pezzi scartati rimasti sulla tavola Dim nWaist As Integer = GetParts(Place.ON_TABLE, StatusPart.WASTE).Count ' numero totale di pezzi da scaricare Dim nTotal As Integer = GetParts(Place.ON_TABLE).Count + GetParts(Place.ON_TABLE, StatusPart.WASTE).Count nTotal = nTotal + GetParts(Place.ON_MOTOR_RULLER).Count + GetParts(Place.ON_MOTOR_RULLER, StatusPart.WASTE).Count nTotal = nTotal + GetParts(Place.ON_BOX).Count + GetParts(Place.ON_BOX, StatusPart.WASTE).Count nTotal = nTotal + GetParts(Place.ON_MANUAL_BOX).Count + GetParts(Place.ON_MANUAL_BOX, StatusPart.WASTE).Count ' notifico anche la finestra delle info NotifyPropertyChanged("InfoTable1") If Map.refMainWindowVM.WaitingConfirmManualPart Then Return "--" End If ' restituisce la parcentula di pezzi prelevabili (esclusi quelli da scartare) Dim sMessage As String = nTable.ToString & "/" & nTotal.ToString If nTotal = 0 Then sMessage = "0" End If 'Return DoubleToString(If(nTotal = 0, 0, nTable / nTotal * 100), 0) & "%" Return sMessage End Get End Property ' notifico il numero di pezzi presenti sulla rulliera motorizzata (anche progetti diversi) Public ReadOnly Property TableDifference As String Get NotifyPropertyChanged("InfoRuller") Dim nCount As Integer = GetAllParts(Place.ON_MOTOR_RULLER).Count nCount = nCount + GetAllParts(Place.ON_MOTOR_RULLER, StatusPart.NOT_LOADED).Count Return DoubleToString(nCount, 0) End Get End Property Public ReadOnly Property InfoTable1 As String Get Dim sInfo As String = String.Empty sInfo &= "IdProj: " & Map.refMainWindowVM.MainWindowM.nProjInd.ToString sInfo &= System.Environment.NewLine & "Counter Good: " & GetParts(Place.ON_TABLE).Count.ToString sInfo &= System.Environment.NewLine & "Counter Waste: " & GetParts(Place.ON_TABLE, StatusPart.WASTE).Count.ToString Return sInfo End Get End Property Public ReadOnly Property InfoRuller As String Get Dim sInfo As String = String.Empty sInfo &= "IdProj Table1: " & Map.refMainWindowVM.MainWindowM.nProjInd.ToString sInfo &= System.Environment.NewLine & "Counter : " & GetParts(Place.ON_MOTOR_RULLER).Count.ToString sInfo &= System.Environment.NewLine & "IdProj Table2: " & m_IdProjTable2.nProjInd sInfo &= System.Environment.NewLine & "Counter Good: " & GetParts(m_IdProjTable2.nProjInd, Place.ON_MOTOR_RULLER).Count.ToString ' devo contare anche i pezzi da scaricare manualmente (ed emettere un messaggio di avviso) sInfo &= System.Environment.NewLine & "Counter not unloadble: " & GetParts(m_IdProjTable2.nProjInd, Place.ON_MOTOR_RULLER, StatusPart.NOT_LOADED).Count.ToString Return sInfo End Get End Property ' testo all'interno del bottone per la prenotazione Private m_ManualUnload As String = String.Empty Public ReadOnly Property ManualUnload As String Get If Not m_IsChecked_Manual Then m_ManualUnload = "Reserve" ' se non sono nalla scena deseleziono tutto If Not refScenaIsChecked Then EgtDeselectAll() End If Else m_ManualUnload = "Cancel" End If Return m_ManualUnload End Get End Property ' messaggio sul bottone per la selezione dello stato del manipolatore2 Private m_MsgMachine2 As String = "Machine 2" Public ReadOnly Property MsgMachine2 As String Get Return m_MsgMachine2 End Get End Property ' visibilità del testo a lato del bottone per la prenotazione Private m_VisibilityTextReserve As Visibility = Visibility.Collapsed Public ReadOnly Property VisibilityTextReserve As Visibility Get If Not m_IsChecked_Manual Then m_VisibilityTextReserve = Visibility.Collapsed Else m_VisibilityTextReserve = Visibility.Visible End If Return m_VisibilityTextReserve End Get End Property ' messaggio di avvenuto prenotazione e conseguete stop di impianto Private m_TextReserve As String = "Waiting selection manual part" Public ReadOnly Property TextReserve As String Get Return m_TextReserve End Get End Property ' rendo visibile la freccia se: scarico manuale, pezzo non afferrabile Private m_RullerArrowVisibility As Visibility = Visibility.Collapsed Public Property RullerArrowVisibility As Visibility Get Return m_RullerArrowVisibility End Get Set(value As Visibility) m_RullerArrowVisibility = value NotifyPropertyChanged("RullerArrowImage") NotifyPropertyChanged("RullerArrowVisibility") End Set End Property Private m_RullerArrowImage As String = "/Resources/WhiteArrow.png" Public ReadOnly Property RullerArrowImage As String Get If m_RullerArrowVisibility = Visibility.Visible Then m_RullerArrowImage = "/Resources/RedArrow.png" Else m_RullerArrowImage = "/Resources/WhiteArrow.png" End If Return m_RullerArrowImage End Get End Property ' rendo visibile le freccia se: attesa di caricare la tavola Private m_Table1ArrowVisibility As Visibility = Visibility.Collapsed Public Property Table1ArrowVisibility As Visibility Get Return m_Table1ArrowVisibility End Get Set(value As Visibility) m_Table1ArrowVisibility = value NotifyPropertyChanged("Table1ArrowVisibility") NotifyPropertyChanged("Table1ArrowImage") End Set End Property Private m_Table1ArrowImage As String = "/Resources/WhiteArrow.png" Public ReadOnly Property Table1ArrowImage As String Get If m_Table1ArrowVisibility = Visibility.Visible Then m_Table1ArrowImage = "/Resources/RedArrow.png" Else m_Table1ArrowImage = "/Resources/WhiteArrow.png" End If Return m_Table1ArrowImage End Get End Property #End Region ' PROPERTIES #Region "OLD PROPERTIES" Private m_TileType As Integer Public ReadOnly Property TileType As String Get Return m_TileType.ToString End Get End Property Private m_Table1Counter As Integer Public ReadOnly Property Table1Counter As String Get Return m_Table1Counter.ToString End Get End Property Private m_Table2Counter As Integer Public ReadOnly Property Table2Counter As String Get Return m_Table2Counter.ToString End Get End Property Private m_TileThickness As Double Public ReadOnly Property TileThickness As String Get Return LenToString(m_TileThickness, 1) End Get End Property Private m_LastSlab As Boolean Public ReadOnly Property LastSlab As Boolean Get Return m_LastSlab End Get End Property #End Region ' Old Properties ' definizione comandi Private m_cmdUnloadedWaistPart As ICommand Private m_cmdUnloadedManualPart As ICommand #Region "CONSTRUCTOR" Sub New() Map.SetRefUnloadingAreaVM(Me) Init() m_WarehouseList.Add(New WarehouseVM(Warehouses.A)) m_WarehouseList.Add(New WarehouseVM(Warehouses.B)) End Sub #End Region ' CONSTRUCTOR #Region "METHODS" ' Rendo attivo il magazzino indicato (e disattivo l'altro) Friend Sub SetActiveWarehouse(ActiveWarehouse As Warehouses) ' verifico che il valore sia corretto, alrimenti assegno 0-> entrambi i magazzini sono disattivi If ActiveWarehouse < 0 OrElse ActiveWarehouse > 2 Then m_ActiveWarehouse = 0 Else m_ActiveWarehouse = ActiveWarehouse End If ' attivo il magazzino selezionato If ActiveWarehouse = Warehouses.A Then GetWarehouse(Warehouses.A).SetIsActive(True) GetWarehouse(Warehouses.B).SetIsActive(False) OutLogProcess("ActiveWarehouse() -> Attivo magazzino A") ElseIf ActiveWarehouse = Warehouses.B Then GetWarehouse(Warehouses.A).SetIsActive(False) GetWarehouse(Warehouses.B).SetIsActive(True) OutLogProcess("ActiveWarehouse() -> Attivo magazzino B") Else GetWarehouse(Warehouses.A).SetIsActive(False) GetWarehouse(Warehouses.B).SetIsActive(False) OutLogProcess("ActiveWarehouse() -> Disattivo magazzini A B") End If End Sub #End Region ' METHODS #Region "OLD METHODS" Friend Sub SetBoxIsActive(BoxId As Integer) If Not m_ActiveWarehouse > 0 AndAlso m_ActiveWarehouse <= 2 Then m_WarehouseList(GetWarehouseIndex(Warehouses.A)).SetBoxIsActive(0) m_WarehouseList(GetWarehouseIndex(Warehouses.A)).SetBoxIsActive(0) Else m_WarehouseList(GetWarehouseIndex(m_ActiveWarehouse)).SetBoxIsActive(BoxId) End If End Sub Friend Sub SetBoxState(Warehouse As Warehouses, Id As Integer, State As States) Dim x = GetWarehouseIndex(Warehouse) m_WarehouseList(GetWarehouseIndex(Warehouse)).SetBoxState(Id, State) End Sub Friend Sub FillActiveBox(Livello As Integer, Riga As Integer) If ActiveWarehouse = 0 Then Return m_WarehouseList(GetWarehouseIndex(m_ActiveWarehouse)).FillActiveBox(Livello, Riga) End Sub Friend Sub MaxFillActiveBox(MaxLivello As Integer, MaxRiga As Integer) If ActiveWarehouse = 0 Then Return m_WarehouseList(GetWarehouseIndex(m_ActiveWarehouse)).MaxFillActiveBox(MaxLivello, MaxRiga) End Sub Friend Sub SetTableCounters(Table1Counter As Integer, Table2Counter As Integer) m_Table1Counter = Table1Counter m_Table2Counter = Table2Counter NotifyPropertyChanged("TableDifference") End Sub Friend Sub SetTable2Counter(Table2Counter As Integer) m_Table2Counter = Table2Counter NotifyPropertyChanged("Table2Counter") End Sub 'Friend Sub SetTable1Percentage(Table1CurrRow As Integer, Table1NRow As Integer) ' m_Table1CurrRow = Table1CurrRow ' m_Table1NRow = Table1NRow ' NotifyPropertyChanged("Table1Percentage") 'End Sub Friend Sub SetTileType(TyleType As Integer) m_TileType = TyleType NotifyPropertyChanged("TileType") End Sub Friend Sub SetTileThickness(TileThickness As Double) m_TileThickness = TileThickness NotifyPropertyChanged("TileThickness") End Sub Friend Sub SetLastSlab(LastSlab As Boolean) m_LastSlab = LastSlab NotifyPropertyChanged("LastSlab") End Sub Friend Shared Function GetWarehouseIndex(Warehouse As Warehouses) As Integer If Warehouse = Warehouses.A Then Return 0 ElseIf Warehouse = Warehouses.B Then Return 1 Else EgtOutLog("Warehouse index out of range") Return 0 End If End Function #End Region ' Old Methods #Region "NEW METHODS" Public Function Init() As Boolean ' verifico che siano state caricate correttamente le costanti Dim bSetOffset As Boolean = SetOffset(K_PALLETX, m_OffsetPalletX) AndAlso SetOffset(K_PALLETY, m_OffsetPalletY) AndAlso SetOffset(K_PALLETZ, m_OffsetPalletZ) AndAlso SetOffset(K_RACKX, m_OffsetRackX) AndAlso SetOffset(K_RACKZ, m_OffsetRackZ) AndAlso SetOffset(K_RACKY, m_OffsetRackY) AndAlso SetOffset(K_ANGRACK, m_AngRack) AndAlso SetOffset(K_RULLERX, m_OffsetRullerX) AndAlso SetOffset(K_RULLERY, m_OffsetRullerY) Dim bSetMaxPallet As Boolean = SetMaxPallet(K_MAX_HEIGHT, m_MaxHeight) AndAlso SetMaxPallet(K_MAX_LENGTH, m_MaxLength) AndAlso SetMaxPallet(K_MAX_TOL, m_MaxTollerance) AndAlso SetMaxPallet(K_MIN_TOL, m_MinTollerance) Dim bSetMaxRack As Boolean = SetMaxTileRack(K_MAX_TILE, m_MaxTile) Dim bSetVacuumDimension As Boolean = SetDimVacuum(K_VACUUM_DIMX, m_VacuumDimX) AndAlso SetDimVacuum(K_VACUUM_DIMY, m_VacuumDimY) Return bSetOffset And bSetMaxPallet And bSetMaxRack End Function Public Overloads Sub SetOutputMessage(sMessage As String, Optional nMsgType As MSG_TYPE = MSG_TYPE.INFO) SetMsgColor(nMsgType) m_OutputMessage = sMessage NotifyPropertyChanged("OutputMessage") End Sub Public Sub SetMsgColor(nMsgType As MSG_TYPE) Select Case nMsgType Case MSG_TYPE.INFO m_OutputMessage_Foreground = Brushes.Black Case MSG_TYPE.WARNING m_OutputMessage_Foreground = Brushes.SaddleBrown Case MSG_TYPE.ERROR_ m_OutputMessage_Foreground = Brushes.Red End Select NotifyPropertyChanged("OutputMessage_Foreground") End Sub Public Overridable Sub ClearOutputMessage() m_OutputMessage_Foreground = Brushes.Black NotifyPropertyChanged("MsgColor") m_OutputMessage = String.Empty NotifyPropertyChanged("OutputMessage") End Sub ' leggo dalla configurazione gli offset dei pallet e dei rack Public Function SetOffset(sName As String, ByRef dVal As Double) As Boolean Dim sVal As String = String.Empty If GetMainPrivateProfileString(S_OFFSET, sName, "0", sVal) < 0 Then EgtOutLog("Error reading file Config.ini [Offset] -> " & sName) Return False Else If Not StringToLen(sVal, dVal) Then EgtOutLog("Error reading file Config.ini [Offset] -> " & sName & " is not numeric") Return False End If End If Return True End Function Public Function SetDimVacuum(sName As String, ByRef dVal As Double) As Boolean Dim sVal As String = String.Empty If GetMainPrivateProfileString(S_DIM_VACUMM, sName, "0", sVal) < 0 Then EgtOutLog("Error reading file Config.ini [Vacuum] -> " & sName) Return False Else If Not StringToLen(sVal, dVal) Then EgtOutLog("Error reading file Config.ini [Vacuum] -> " & sName & " is not numeric") Return False End If End If Return True End Function ' leggo le dimensioni massime caricabili su pallet Public Function SetMaxPallet(ByVal sName As String, ByRef dVal As Double) As Boolean Dim sVal As String = String.Empty If GetMainPrivateProfileString(S_BOX, sName, "0", sVal) < 0 Then EgtOutLog("Error reading file Config.ini [Box] -> " & sName) Return False Else If Not StringToLen(sVal, dVal) Then EgtOutLog("Error reading file Config.ini [Box] -> " & sName & " is not numeric") Return False End If End If Return True End Function ' leggo del dimansioni massime caricabili su rack Public Function SetMaxTileRack(ByVal sName As String, ByRef dVal As Double) As Boolean Dim sVal As String = String.Empty If GetMainPrivateProfileString(S_BOX, sName, "0", sVal) < 0 Then EgtOutLog("Error reading file Config.ini [Box] -> " & sName) Return False Else If Not StringToLen(sVal, dVal) Then EgtOutLog("Error reading file Config.ini [Box] -> " & sName & " is not numeric") Return False End If End If Return True End Function ' restituisco la lista di tutti i pezzi identificati dalla stessa posizione (di default quelli buoni) del progetto corrente sul tavolo Public Function GetParts(DefinePlce As Place, Optional DefineStatus As StatusPart = StatusPart.GOOD) As ObservableCollection(Of Part) Dim CurrList As New ObservableCollection(Of Part) For Each Item In Map.refUnloadingAreaVM.ListPart If Item.IdProject = Map.refMainWindowVM.MainWindowM.nProjInd And Item.enPlace = DefinePlce And DefineStatus = Item.enStatus Then CurrList.Add(Item) End If Next Return CurrList End Function ' restituisco la lista di tutti i pezzi identificati dalla stessa posizione (di default quelli buoni) del progetto indicato Public Function GetParts(IdProj As Integer, DefinePlce As Place, Optional DefineStatus As StatusPart = StatusPart.GOOD) As ObservableCollection(Of Part) Dim CurrList As New ObservableCollection(Of Part) For Each Item In Map.refUnloadingAreaVM.ListPart If Item.IdProject = IdProj And Item.enPlace = DefinePlce And DefineStatus = Item.enStatus Then CurrList.Add(Item) End If Next Return CurrList End Function ' restituisce il Box assocauto al pezzo indicato Public Function GetPartBox(CurrPart As Part, CurrWarehouse As WarehouseVM) As Box Dim CurrBox As Box = Nothing For Each ItemGridBox In CurrWarehouse.GridBoxList Dim bFoundBox As Boolean = False For Each ItemBox In ItemGridBox.CurrBoxList If ItemBox.Id = CurrPart.IdBox Then CurrBox = ItemBox bFoundBox = True Exit For End If Next If bFoundBox Then Exit For End If Next Return CurrBox End Function ' restituisce la lista di tutti i pezzi identificati dalla stessa posizione (di default quelli buoni) di tutti i progetti caricati Public Function GetAllParts(DefinePlce As Place, Optional DefineStatus As StatusPart = StatusPart.GOOD) As ObservableCollection(Of Part) Dim CurrList As New ObservableCollection(Of Part) For Each Item In Map.refUnloadingAreaVM.ListPart If Item.enPlace = DefinePlce And DefineStatus = Item.enStatus Then CurrList.Add(Item) End If Next Return CurrList End Function ' restituisce l'oggetto magazzino Public Function GetWarehouse(WarehouseId As Warehouses) As WarehouseVM For Each ItemWarehouse In m_WarehouseList If ItemWarehouse.Id = WarehouseId Then Return ItemWarehouse Next Return Nothing End Function ' restituisce il magazzino corrente, se nessun magazzino corrente restituisco nothing Public Function GetCurrentWarehouse() As WarehouseVM If ActiveWarehouse = Warehouses.A Then Return GetWarehouse(Warehouses.A) ElseIf ActiveWarehouse = Warehouses.B Then Return GetWarehouse(Warehouses.B) End If Return Nothing End Function ' quando si ha conferma dell'organizzazione del magazzino allora organizzo la pallettizzazione (false: mancano i Box) Public Function OrganaizeWarehouse(Optional ByVal Me_Warehouse As WarehouseVM = Nothing) As Boolean ' Se il progetto è terminato (scarico dell'ultimo pezzo avvenuto) If m_IdProjTable2.enStatus = StatusProj.DONE Then Dim bNewProjectExist As Boolean = False ' ricerco il primo proggetto in attesa di essere alaborato dalla tavola 2 (LOADING) For Each ItemProj In Map.refMainWindowVM.MainWindowM.ProjIndList If ItemProj.enStatus = StatusProj.LOADING Then m_IdProjTable2 = ItemProj bNewProjectExist = True Exit For End If Next ' se non c'è un nuovo progetto allora esco If Not bNewProjectExist Then Return True ElseIf m_IdProjTable2.enStatus = StatusProj.WORKING Then Return True ElseIf Map.refMainWindowVM.MainWindowM.ProjIndList.Count = 0 Then ' se non ci sono progetti esco Return True ElseIf Map.refMainWindowVM.MainWindowM.ProjIndList.Count = 1 Then m_IdProjTable2 = Map.refMainWindowVM.MainWindowM.ProjIndList(0) End If OutLogProcess("OrganaizeWarehouse() -> Nuovo progetto per scarico macchin 2: " & m_IdProjTable2.nProjInd.ToString) ' recupero il magazzino attivo Dim CurrWarehause As WarehouseVM = GetCurrentWarehouse() If Not IsNothing(Me_Warehouse) Then CurrWarehause = Me_Warehouse End If If IsNothing(CurrWarehause) Then OutLogProcess("OrganaizeWarehouse() -> Nessun magazzino attivo") Return False End If ' lista dei box disponibili (pallet/rack) Dim nPallet As Integer = 0 Dim nRack As Integer = 0 Dim AvailablePalletList As New ObservableCollection(Of Box) Dim AvailableRackList As New ObservableCollection(Of Box) For Each ItemGridBox In CurrWarehause.GridBoxList For Each ItemBox In ItemGridBox.CurrBoxList If ItemBox.State = States.AVAILABLE Then If ItemGridBox.IsPallet Then AvailablePalletList.Add(ItemBox) nPallet = nPallet + 1 Else AvailableRackList.Add(ItemBox) nRack = nRack + 1 End If End If Next Next ' divido i pezzi in due liste (pallet/rack) solo quelli con scarico automatico Dim nPartOnPallet As Integer = 0 Dim nPartOnRack As Integer = 0 Dim RackPartList As New List(Of Part) Dim PalletPartList As New List(Of Part) Dim NewPalletPartLisr As New List(Of Part) Dim dHeightTile As Double = 0 Dim dDistRack As Double = 0 ' tutti quelli già sul rullo (senza un Box definito) Dim ListMotorRuller As ObservableCollection(Of Part) = GetParts(m_IdProjTable2.nProjInd, Place.ON_MOTOR_RULLER) OutLogProcess("OrganaizeWarehouse() -> Pezzi sulla rulliera: " & ListMotorRuller.Count) For Each ItemPart In ListMotorRuller If ItemPart.enUnloading = Unloading.AUTOMATIC AndAlso ItemPart.IdBox = -1 Then If ItemPart.MinRectX > m_MaxLength Then RackPartList.Add(ItemPart) nPartOnRack = nPartOnRack + 1 dDistRack = ItemPart.Height Else If ItemPart.IdBox = -1 Then PalletPartList.Add(ItemPart) nPartOnPallet = nPartOnPallet + 1 dHeightTile = ItemPart.Height Else NewPalletPartLisr.Add(ItemPart) nPartOnPallet = nPartOnPallet + 1 dHeightTile = ItemPart.Height End If End If End If Next ' tutti quelli ancora sul tavolo (senza un Box definito) Dim ListTable As ObservableCollection(Of Part) = GetParts(m_IdProjTable2.nProjInd, Place.ON_TABLE) OutLogProcess("OrganaizeWarehouse() -> Pezzi sul tavolo: " & ListTable.Count) For Each ItemPart In ListTable If ItemPart.enUnloading = Unloading.AUTOMATIC AndAlso ItemPart.IdBox = -1 Then If ItemPart.MinRectX > m_MaxLength Then RackPartList.Add(ItemPart) nPartOnRack = nPartOnRack + 1 dDistRack = ItemPart.Height Else If ItemPart.IdBox = -1 Then PalletPartList.Add(ItemPart) nPartOnPallet = nPartOnPallet + 1 dHeightTile = ItemPart.Height Else NewPalletPartLisr.Add(ItemPart) nPartOnPallet = nPartOnPallet + 1 dHeightTile = ItemPart.Height End If End If End If Next ' recupero l'altezza del primo pezzo, altrimenti esco If dHeightTile = 0 And dDistRack = 0 Then EgtOutLog("Warning: no parts for unloading") SetOutputMessage("Warning: no parts for unloading.") Return True End If Dim RadAngRack As Double = Map.refUnloadingAreaVM.AngRack * Math.PI / 180 Dim OffsetZ = dDistRack / Math.Sin(RadAngRack) OffsetZ = RackPartList.Count * OffsetZ ' verifico la presenza del numero minimo di rack: impossibile scaricare-> cambio magazzino Dim nTemRack As Integer = CInt(Math.Ceiling(OffsetZ / m_MaxTile)) If nTemRack > nRack Then EgtOutLog("Error: needs rack for unloading some parts") SetOutputMessage("You need " & nTemRack.ToString & " rack for unloading.") Return False End If ' recupero l'indice di Layer massimo Dim nMaxLayer As Integer = 0 For Each ItemPart In PalletPartList If ItemPart.nLayer > nMaxLayer Then nMaxLayer = ItemPart.nLayer End If Next Dim nTemPallet As Integer = CInt(Math.Ceiling((nMaxLayer + 1) * dHeightTile / m_MaxHeight)) ' se non ci sono abbastanza pallet allora resituisco falso If nTemPallet > nPallet Then EgtOutLog("Error: needs more pallets for unloading") SetOutputMessage("You need " & nTemPallet.ToString & " pallet for unloading.") Return False End If ' ripulisco i messaggi ClearOutputMessage() ' verico che i rack non siano stati già riempiti Dim bOrganizeRack As Boolean = True If RackPartList.Count > 0 Then If RackPartList(0).IdBox > -1 Then OutLogProcess("OrganaizeWarehouse() -> Magazzino rack già organizzato per progetto: " & m_IdProjTable2.nProjInd.ToString) bOrganizeRack = False End If End If If bOrganizeRack Then ' riempio i box con i part che ho trovato, partendo dai rack perchè sono i pezzi più grandi For IndexPart = 0 To RackPartList.Count - 1 For IndexBox = 0 To nTemRack - 1 If IndexPart <= RackPartList.Count - 1 Then ' recupero e salvo l'indice del rack disponibile RackPartList(IndexPart).IdBox = AvailableRackList(IndexBox).Id RackPartList(IndexPart).enWarehouse = CurrWarehause.Id RackPartList(IndexPart).nLayer = -1 AvailableRackList(IndexBox).MyListPart.Add(RackPartList(IndexPart)) ' passo al prossimo pezzo IndexPart = IndexPart + 1 End If Next If IndexPart > 0 Then IndexPart = IndexPart - 1 End If Next End If ' verifico che il magazzino no sia già stato organizzato If PalletPartList.Count > 0 Then If PalletPartList(0).IdBox > -1 Then OutLogProcess("OrganaizeWarehouse() -> Magazzino pallet già organizzato per progetto: " & m_IdProjTable2.nProjInd.ToString) Return True End If End If '' blocco la forzatura ad aprire il magazzino 'Map.refMainWindowVM.m_CNCommunication.m_OpenWarehouse = False ' verifico che i pezzi siano definiti nella sequenza corretta (ovvero in Layer successivi) Dim LastIndex As Integer = 0 Dim nTestLayer As Integer = 0 If PalletPartList.Count > 0 Then nTestLayer = PalletPartList(0).nLayer End If For Each Item In PalletPartList If nTestLayer > Item.nLayer Then ClearOutputMessage() SetOutputMessage("Error in list part") Return False End If LastIndex = LastIndex + 1 Next ' parto dal primo layer calcolato Dim nCurrLayer As Integer = 0 ' definisco quale Layer deve essere riempito per tutti i pallet Dim SetCurrLayer As Integer = 0 For IndexPart = 0 To PalletPartList.Count - 1 For IndexBox = 0 To nTemPallet - 1 While IndexPart <= PalletPartList.Count - 1 If nCurrLayer = PalletPartList(IndexPart).nLayer Then ' recupero e salvo l'indice del pallet disponibile PalletPartList(IndexPart).IdBox = AvailablePalletList(IndexBox).Id ' salvo l'informazione del layer Corrente sul pallet PalletPartList(IndexPart).nLayer = SetCurrLayer ' indico il magazzno di appartenenza PalletPartList(IndexPart).enWarehouse = CurrWarehause.Id ' salvo le informazioni del pezzo nella lista del Boox AvailablePalletList(IndexBox).MyListPart.Add(PalletPartList(IndexPart)) Else Exit While End If ' passo al prossimo pezzo del layer corrente (altrimenti è il primo pezzo del layer successivo) IndexPart = IndexPart + 1 End While ' il prossimo pallet conterrà lo strato di layer successivo nCurrLayer = nCurrLayer + 1 Next ' ho terminato di riempire la stessa quota di layer su tutti i pallet disponibili If IndexPart > 0 Then ' perchè il ciclo "For" incrementa l'inidce dei pezzi (incrementati manualmente nel ciclo While) IndexPart = IndexPart - 1 End If ' indicizzo il nuovo strato di layer da salvare per i pallet SetCurrLayer = SetCurrLayer + 1 Next For Each ItemNewPallet In NewPalletPartLisr ItemNewPallet.IdBox = ItemNewPallet.IdBox + 1 Next ClearOutputMessage() SetOutputMessage("Warehouse confirmed") OutLogProcess("OrganaizeWarehouse() -> Organizzato magazzino per progetto: " & m_IdProjTable2.nProjInd.ToString) Return True End Function #End Region 'New Methods #Region "COMMANDS" #Region "UnloadTable1" ' Returns a command that manage the MainWindow_Unloaded command Public ReadOnly Property UnloadedWaistPart_Command() As ICommand Get If m_cmdUnloadedWaistPart Is Nothing Then m_cmdUnloadedWaistPart = New Command(AddressOf UnloadedWaistPart) End If Return m_cmdUnloadedWaistPart End Get End Property ' scarico tutti i pezzi rovinati rimasti sulla rulliera Public Sub UnloadedWaistPart() For Each ItemPart In GetParts(m_IdProjTable2.nProjInd, Place.ON_MOTOR_RULLER, StatusPart.NOT_LOADED) ItemPart.enPlace = Place.ON_WASTE_BOX Next ' Pezzi attualmente sulla rulliera motorizzata NotifyPropertyChanged("TableDifference") End Sub #End Region ' UnloadTable1 #Region "UnloadedManualPart" Public ReadOnly Property UnloadedManualPart_Command() As ICommand Get If m_cmdUnloadedManualPart Is Nothing Then m_cmdUnloadedManualPart = New Command(AddressOf UnloadedManualPart) End If Return m_cmdUnloadedManualPart End Get End Property ' scarico tutti i pezzi MANUALI rimasti sulla rulliera Public Sub UnloadedManualPart() Dim bManualUnloaded As Boolean = False For Each ItemPart In GetParts(Place.ON_MOTOR_RULLER, StatusPart.GOOD) If ItemPart.enUnloading = Unloading.MANUAL Then ItemPart.enPlace = Place.ON_MANUAL_BOX bManualUnloaded = True End If Next ' se non ci sono pezzi del progetto corrente sulla rulliera considero il progetto terminato If GetParts(Place.ON_MOTOR_RULLER).Count > 0 Then Return Dim nIdProj As Integer = -1 If m_IdProjTable2.nProjInd > 0 Then If bManualUnloaded Then m_IdProjTable2.enStatus = StatusProj.DONE nIdProj = m_IdProjTable2.nProjInd Else nIdProj = Map.refMainWindowVM.MainWindowM.nProjInd End If OutLogProcess("UnloadedManualPart() -> Pezzi manuali scaricati") OutLogProcess("UnloadedManualPart() -> Progetto terimnato: " & nIdProj.ToString) ' elimino il file ini associato Dim sFile As String = Map.refMainWindowVM.MainWindowM.sTempDir & "\PartList" & nIdProj.ToString & ".ini" If My.Computer.FileSystem.FileExists(sFile) Then My.Computer.FileSystem.DeleteFile(sFile) OutLogProcess("UnloadedManualPart() -> Eliminato file: " & sFile) End If ' cancello il file .lck Dim sProjLock As String = Map.refMainWindowVM.MainWindowM.sProjDir & "\" & CURR_PROJ_LOCK If My.Computer.FileSystem.FileExists(sProjLock) Then My.Computer.FileSystem.DeleteFile(sProjLock) OutLogProcess("[3] Eliminato file: " & sProjLock) End If End Sub #End Region ' UnloadedManualPart #End Region ' COMMANDS End Class