' Carro.vb ' Classe Carro ' Solução do exercício das aulas de 8, 11 e 15 de Novembro de 2002 Public Class Carro ' Constante que define a simulação da passagem de uma hora ' Neste caso, 2 seg Private Const UmaHora As Double = 2000 'Assumimos que TODOS os CARROS têm um depósito do mesmo tipo Public Shared ReadOnly CapacidadeDeposito As Double = 50 Private Shared ReadOnly Reserva As Double = 5 'Assumimos que TODOS os CARROS têm a mesma Velocidade Máxima Public Shared ReadOnly VelocidadeMaxima As Double = 160 'Assumimos que TODOS os CARROS têm o mesmo Consumo, constante Public Shared ReadOnly Consumo As Double = 7.5 Public Event CombustivelNaReserva() Public Event SemCombustivel() Public Event PassouUmaHoraViagem() 'Para o Evento CombustivelNaReserva disparar só uma vez. Private NotificadoNaReserva As Boolean 'Para o Evento SemCombustivel disparar só uma vez. Private NotificadoSemCombustivel As Boolean Private m_Velocidade As Double Private m_Combustivel As Double Private ContadorKlms As Double Private WithEvents Relogio As Timers.Timer 'Para calcular os klms percorridos e o combustível gasto quando o carro pára. Private UltimaContagem As DateTime ' Para contar o nr de eventos Elapsed do Relogio de forma a disparar o evento PassouUmaHoraViagem Private ContadorEventos As Integer Sub New() Velocidade = 0 m_Combustivel = CapacidadeDeposito ContadorKlms = 0 NotificadoNaReserva = False NotificadoSemCombustivel = False ' Quanto mais pequeno for o intervalo do relógio, ' mais exactos serão os eventos CombustivelNaReserva e SemCombustivel Relogio = New Timers.Timer(100) Relogio.AutoReset = True End Sub ' Ao implementarmos a Velocidade com uma Property (propriedade) ' podemos fazer um processamento adicional sempre que é alterado o seu valor Public Property Velocidade() As Double Get Return m_Velocidade End Get Set(ByVal NovaVelocidade As Double) If NovaVelocidade = m_Velocidade Then Exit Property ' Validações If NovaVelocidade > VelocidadeMaxima Then Throw New ArgumentException("Não pode exceder a velocidade máxima de {0} Klm/h !", VelocidadeMaxima) ElseIf NovaVelocidade < 0 Then Throw New ArgumentException("A velocidade não pode ser negativa!") ElseIf NovaVelocidade > 0 And m_Combustivel <= 0 Then Throw New ArgumentException("O carro não pode andar sem combustível!") End If ' Verificação se houve Mudança de Estado 'Se o Carro estava parado e inicia a sua marcha, inicia a contagem do relógio If m_Velocidade = 0 And NovaVelocidade > 0 Then Relogio.Start() UltimaContagem = Now ContadorEventos = 0 ' Se o Carro estava a andar e parou, pára o relógio e calcula o gasto de combustivel ElseIf m_Velocidade > 0 And NovaVelocidade = 0 Then CombustivelGasto(DateTime.Now.Subtract(UltimaContagem)) Relogio.Stop() End If 'Alteração do valor m_Velocidade = NovaVelocidade End Set End Property Public ReadOnly Property Combustivel() As Double Get Return m_Combustivel End Get End Property Public ReadOnly Property Klms() As Double Get Return ContadorKlms End Get End Property Public Sub Atestar() m_Combustivel = CapacidadeDeposito NotificadoNaReserva = False NotificadoSemCombustivel = False End Sub ' Calcula os Klms percorridos e o Combustivel gasto ' no período definido pelo parâmetro Tempo Private Sub CombustivelGasto(ByVal Tempo As TimeSpan) Dim Horas, Klms, CombGasto As Double UltimaContagem = Now 'Calcula o nr de horas passadas naquele período de Tempo Horas = Tempo.TotalMilliseconds / UmaHora ' Calcula quantos Kms fez naquele tempo Klms = Horas * m_Velocidade ContadorKlms = ContadorKlms + Klms 'Calcula quanto gastou de combustivel CombGasto = Consumo * (Klms / 100) m_Combustivel = m_Combustivel - CombGasto If m_Combustivel < Reserva Then If m_Combustivel > 0 And Not NotificadoNaReserva Then NotificadoNaReserva = True RaiseEvent CombustivelNaReserva() ElseIf m_Combustivel <= 0 And Not NotificadoSemCombustivel Then NotificadoSemCombustivel = True ' É intencional o uso da propriedade Velocidade e não do campo m_Velocidade ' Ao fazer a atribuição do valor 0 à propriedade Velocidade, ' todos os efeitos laterais relativos à paragem do carro serão tomados em consideração Velocidade = 0 RaiseEvent SemCombustivel() End If End If End Sub Private Sub Relogio_Elapsed(ByVal sender As Object, ByVal e As System.Timers.ElapsedEventArgs) Handles Relogio.Elapsed CombustivelGasto(TimeSpan.FromMilliseconds(Relogio.Interval)) ContadorEventos = ContadorEventos + 1 If ContadorEventos = UmaHora / Relogio.Interval Then RaiseEvent PassouUmaHoraViagem() ContadorEventos = 0 End If End Sub End Class