Solução dos desafios 13 e 14
Desafio 13 Considere que existam dois tipos de paradas: uma do R2D2 e outra do canhão de combate. A parada do canhão de combate ocorre sempre depois de 25 horas de viagem (em quebra ou não) e seu reparo dura 2 horas. Contudo, para não perder tempo, a manutenção do canhão só é realizada quando o R2D2 quebra.
Inicialmente, precisamos de uma variável global para verificar a situação do canhão:
import simpy
canhao = True # variável global que avisa se o canhão está funcionando
viajando = False # variável global que avisa se o x-wing está operando
duracaoViagem = 30 # variável global que marca a duração atual da viagem
A função viagem, agora deve lidar com um tempo de parada do canhão. Contudo, não existe uma interrupção para o canhão, pois nosso indomável piloto jedi apenas verifica a situação do canhão ao término do concerto do R2D2:
def viagem(env, tempoParada, tempoParadaCanhao):
# processo de viagem do x-wing
global viajando, duracaoViagem, canhao
partida = env.now # início da viagem
while duracaoViagem > 0: # enquanto ainda durar a viagem, execute:
try:
viajando = True
# (re)inicio da viagem
inicioViagem = env.now
print("%5.1f Viagem iniciada" %(env.now))
# tempo de viagem restante
yield env.timeout(duracaoViagem)
duracaoViagem -= env.now - inicioViagem
except simpy.Interrupt:
# se o processo de viagem foi interrompido execute
# atualiza o tempo restante de viagem
duracaoViagem -= env.now - inicioViagem
print("%5.1f Falha do R2D2\tTempo de viagem restante: %4.1f horas"
%(env.now, duracaoViagem))
# tempo de manutenção do R2D2
yield env.timeout(tempoParada)
print("%5.1f R2D2 operante" %env.now)
# se o canhão não estiver funcionando
if not canhao:
print("%5.1f R2, ligue o canhão!" % env.now)
# tempo de manutenção do canhão
yield env.timeout(tempoParadaCanhao)
canhao = True
print("%5.1f Pi..bi...bi\tTradução: canhão operante!" % env.now)
# ao final avisa o término da viagem e sua duração
print("%5.1f Viagem concluida\tDuração total da viagem: %4.1f horas"
%(env.now, env.now-partida))
Além da função de parada técnica (já pertencente ao nosso modelo desde a seção anterior), precisamos de uma função que tire de operação o canhão, ou seja, apenas desligue a variável global canhao:
def quebraCanhao(env, intervaloCanhao):
# processo de quebra do canhao entre intervalos definidos
global canhao, duracaoViagem
while duracaoViagem > 0: # este processo só ocorre durante a viagem
yield env.timeout(intervaloCanhao) # aguarda a próxima quebra do canhao
if canhao:
canhao = False
print("%5.1f Pi uiui...bi\tTradução: canhão inoperante!" % (env.now))
Por fim, o processo de quebra do canhão deve ser inciado juntamente com o resto do modelo de simulação:
env = simpy.Environment()
viagem = env.process(viagem(env, 15, 2))
env.process(paradaTecnica(env, 10, viagem))
env.process(quebraCanhao(env, 25))
env.run()
Quando o modelo completo é executado, ele fornece como saída:
0.0 Viagem iniciada
10.0 Falha do R2D2 Tempo de viagem restante: 20.0 horas
25.0 Pi uiui...bi Tradução: canhão inoperante!
25.0 R2D2 operante
25.0 R2, ligue o canhão!
27.0 Pi..bi...bi Tradução: canhão operante!
27.0 Viagem iniciada
30.0 Falha do R2D2 Tempo de viagem restante: 17.0 horas
45.0 R2D2 operante
45.0 Viagem iniciada
50.0 Pi uiui...bi Tradução: canhão inoperante!
50.0 Falha do R2D2 Tempo de viagem restante: 12.0 horas
65.0 R2D2 operante
65.0 R2, ligue o canhão!
67.0 Pi..bi...bi Tradução: canhão operante!
67.0 Viagem iniciada
70.0 Falha do R2D2 Tempo de viagem restante: 9.0 horas
75.0 Pi uiui...bi Tradução: canhão inoperante!
85.0 R2D2 operante
85.0 R2, ligue o canhão!
87.0 Pi..bi...bi Tradução: canhão operante!
87.0 Viagem iniciada
90.0 Falha do R2D2 Tempo de viagem restante: 6.0 horas
100.0 Pi uiui...bi Tradução: canhão inoperante!
105.0 R2D2 operante
105.0 R2, ligue o canhão!
107.0 Pi..bi...bi Tradução: canhão operante!
107.0 Viagem iniciada
110.0 Falha do R2D2 Tempo de viagem restante: 3.0 horas
125.0 Pi uiui...bi Tradução: canhão inoperante!
125.0 R2D2 operante
125.0 R2, ligue o canhão!
127.0 Pi..bi...bi Tradução: canhão operante!
127.0 Viagem iniciada
130.0 Falha do R2D2 Tempo de viagem restante: 0.0 horas
145.0 R2D2 operante
145.0 Viagem concluida Duração total da viagem: 145.0 horas
150.0 Pi uiui...bi Tradução: canhão inoperante!
Desafio 14 Você não acha que pode viajar pelo espaço infinito sem encontrar alguns TIEs das forças imperiais, não é mesmo? Considere que a cada 25 horas, você se depara com um TIE imperial. O ataque dura 30 minutos e, se nesse tempo você não estiver com o canhão funcionando, a sua próxima viagem é para o encontro do mestre Yoda.
Dica: construa uma função executaCombate que controla todo o processo de combate. Você vai precisar também de uma variável global que informa se o X-Wing está ou não em combate.
Incialmente, precisamos de uma variável global para verificar a situação do combate:
import simpy
emCombate = False # variável global que avisa se o x-wing está em combate
canhao = True # variável global que avisa se o canhão está funcionando
viajando = False # variável global que avisa se o x-wing está operando
duracaoViagem = 30 # variável global que marca a duração atual da viagem
A função executaCombate
a seguir, incia o processo de combate e verifica quem foi o vitorioso:
def executaCombate(env, intervaloCombate, duracaoCombate):
# processo de execução do combate
global emCombate, canhao, duracaoViagem
while duracaoViagem > 0: # este processo só ocorre durante a viagem
# aguarda o próximo encontro com as forças imperirais
yield env.timeout(intervaloCombate)
# inicio do combate
emCombate = True
if not canhao:
print("%5.1f Fim da viagem\tO lado negro venceu" %env.now)
break
else:
print("%5.1f Combate iniciado\tReze para que o canhão não quebre!"
%env.now)
try:
yield env.timeout(duracaoCombate)
emCombate = False
print("%5.1f Fim do combate\tR2D2 diz: tá tudo tranquilo, tá tudo normalizado."
%env.now)
except simpy.Interrupt:
print("%5.1f OPS... O canhão quebrou durante o combate." %env.now)
print("%5.1f Fim da viagem\tO lado negro venceu" %env.now)
break
A quebra de canhão agora deve verificar se a nave está em combate, pois, neste caso, o X-Wing será esmagado pelo TIE:
def quebraCanhao(env, intervaloCanhao, combate):
# processo de quebra do canhao entre intervalos definidos
global canhao, duracaoViagem, emCombate
while duracaoViagem > 0: # este processo só ocorre durante a viagem
yield env.timeout(intervaloCanhao) # aguarda a próxima quebra do canhao
if canhao:
canhao = False
print("%5.1f Pi uiui...bi\tTradução: canhão inoperante!" % (env.now))
if emCombate:
combate.interrupt()
Finalmente, a incialização do modelo deve contar com uma chamada para o processo executaCombate:
env = simpy.Environment()
viagem = env.process(viagem(env, 15, 2))
combate = env.process(executaCombate(env, 20, 0.5))
env.process(paradaTecnica(env, 10, viagem))
env.process(quebraCanhao(env, 25, combate))
env.run(until=combate)
A última linha do código anterior tem algo importante: optei por executar a simulação enquanto durar o processo de combate, afinal, ele mesmo só é executado caso a X-Wing esteja ainda em viagem.
Por fim, quando executado, o modelo completo fornece como saída:
0.0 Viagem iniciada
10.0 Falha do R2D2 Tempo de viagem restante: 20.0 horas
20.0 Combate iniciado Reze para que o canhão não quebre!
20.5 Fim do combate R2D2 diz: tá tudo tranquilo, tá tudo normalizado.
25.0 Pi uiui...bi Tradução: canhão inoperante!
25.0 R2D2 operante
25.0 R2, ligue o canhão!
27.0 Pi..bi...bi Tradução: canhão operante!
27.0 Viagem iniciada
30.0 Falha do R2D2 Tempo de viagem restante: 17.0 horas
40.5 Combate iniciado Reze para que o canhão não quebre!
41.0 Fim do combate R2D2 diz: tá tudo tranquilo, tá tudo normalizado.
45.0 R2D2 operante
45.0 Viagem iniciada
50.0 Pi uiui...bi Tradução: canhão inoperante!
50.0 Falha do R2D2 Tempo de viagem restante: 12.0 horas
61.0 Fim da viagem O lado negro venceu
Teste seus conhecimentos
- Não colocamos distribuições aleatórias nos processos. Acrescente distribuições nos diversos processos e verifique se o modelo precisa de alterações;
- Acrescente a tentativa da destruição da Estrela da Morte ao final da viagem: com 50% de chances, nosso intrépido jedi consegue acertar um tiro na entrada do reator e explodir a Estrela da Morte (se ele erra, volta ao combate). Replique algumas vezes o modelo e estime a probabilidade de sucesso da operação.