Trilhas
/
Crystal
Crystal
/
Exercícios
/
Mitigação do colapso
Mitigação do colapso

Mitigação do colapso

Exercício de aprendizagem

Introdução

Crystal tem o que chamamos de expressões de controle. Elas definem como o programa será executado e recebem um valor verdadeiro ou falso. Existem operadores que podem ser usados para criar valores verdadeiros ou falsos, os operadores de igualdade e comparação.

Existem duas expressões de controle principais, usadas para definir qual código será executado e qual não será. Em outras palavras, qual bloco será executado.

Essas duas são: a expressão if e a expressão unless.

Operadores de comparação

Os operadores de comparação são usados para comparar valores e retornam um valor true ou false. Esses operadores exigem que dois valores do mesmo tipo sejam comparados. Se os valores não forem do mesmo tipo, o compilador vai lançar um erro. Veja a lista dos operadores de comparação e um exemplo de quando eles resultam em true:

Operador Descrição Exemplo
< menor que 4 < 5
<= menor ou igual a 4 <= 4
> maior que 3 > 1
>= maior ou igual a 2 >= 2

Operadores de igualdade

Os operadores de igualdade são parecidos com os operadores de comparação, mas servem para verificar se dois valores são iguais ou não.

O operador == verifica se dois valores são iguais, incluindo o tipo do valor. Se os valores forem iguais, ele retorna true; caso contrário, retorna false. O operador == pode comparar qualquer tipo de valor com qualquer outro tipo de valor. O != funciona do mesmo jeito, mas retorna true se os valores não forem iguais e false se forem iguais.

A condicional if

A condicional if é usada para verificar se uma determinada condição é verdadeira ou falsa. Se a condição for verdadeira, o código dentro da condicional if será executado. Uma condicional if termina com a palavra-chave end.

if 1 == 1
  puts "1 is equal to 1"
end
# => 1 is equal to 1

if 1 > 2
  puts "1 is greater than 2"
end
# => no output

A condicional unless

A condicional unless funciona de forma muito parecida com a condicional if, mas executa o código dentro dela se a condição for falsa.

unless 1 == 1
  puts "1 is not equal to 1"
end
# => no output

unless 1 > 2
  puts "1 is not greater than 2"
end
# => 1 is not greater than 2

A cláusula else

A cláusula else pode ser usada junto com as condicionais if e unless. A cláusula else será executada se o bloco do if ou o bloco do unless não for executado.

Embora um bloco `else` possa ser usado junto com `unless,` isso não é recomendado, porque prejudica a legibilidade.
Em vez disso, recomenda-se usar `if !condition` com um bloco `else`.
if 1 == 1
  puts "1 is equal to 1"
else
  puts "1 is not equal to 1"
end
# => 1 is equal to 1

unless 1 < 2
  puts "1 is not greater than 2"
else
  puts "1 is greater than 2"
end
# => 1 is greater than 2

Condicionais em cascata

A cláusula elsif pode ser usada junto com a condicional if. A cláusula elsif será executada se o bloco do if não for executado e a condição da cláusula elsif for verdadeira. As cláusulas elsif podem ser encadeadas e a primeira condição verdadeira será executada. Também pode haver uma cláusula else no final da condicional if, que será executada se nenhuma das condições anteriores for verdadeira.

if 1 != 1
  puts "1 is not equal to 1"
elsif 1 > 2
  puts "1 is greater than 2"
else
  puts "1 is not equal to 1 and 1 is not greater than 2"
end
# => 1 is not equal to 1 and 1 is not greater than 2

Tipos com condicionais

Ao receber valores de tipos diferentes, a variável carrega os dois tipos. Isso acontece porque o compilador não sabe qual bloco será executado. Essa atribuição múltipla, também conhecida como união, será explicada em conceitos posteriores. Veja isso no exemplo a seguir:

if 1 == 1
  a = 1
else
  a = "1"
end

typeof(a) # => Int32 | String

Operador ternário

Crystal tem um operador ternário, uma condicional if-else de uma única linha: condition ? expression_if_truthy : expression_if_falsey

1 == 1 ? puts("1 is equal to 1") : puts("1 is not equal to 1")
# => 1 is equal to 1

Instruções

Neste exercício, vamos desenvolver um sistema de controle simples para um reator nuclear.

Para um reator produzir energia, ele precisa estar em um estado de criticalidade. Se o reator estiver em um estado abaixo da criticalidade, ele pode ser danificado. Se o estado do reator ultrapassar a criticalidade, ele pode sobrecarregar e resultar em um derretimento do núcleo. Queremos reduzir as chances de derretimento do núcleo e gerenciar corretamente o estado do reator.

As três tarefas a seguir estão todas relacionadas a escrever código para manter o estado ideal do reator.

1. Verificar a criticalidade

A primeira coisa que um sistema de controle precisa fazer é verificar se o reator está equilibrado na criticalidade. Dizemos que um reator é crítico se ele satisfizer as seguintes condições:

  • A temperatura é menor que 800 K.
  • O número de nêutrons emitidos por segundo é maior que 500.
  • O produto da temperatura pelos nêutrons emitidos por segundo é menor que 500000.

Implemente o método Reactor.criticality_balanced?, que recebe temperature, medida em kelvin, e neutrons_emitted como parâmetros, e retorna true se as condições de criticalidade forem atendidas, e false caso contrário.

Reactor.criticality_balanced?(750, 600)
# => true

2. Determinar a faixa de potência de saída

Depois que o reator começa a produzir energia, é preciso determinar sua eficiência. A eficiência pode ser agrupada em 4 faixas:

  1. green -> eficiência de 80% ou mais,
  2. orange -> eficiência menor que 80%, mas de pelo menos 60%,
  3. red -> eficiência abaixo de 60%, mas ainda de 30% ou mais,
  4. black -> eficiência menor que 30%.

O valor percentual pode ser calculado como (generated_power/theoretical_max_power)*100, em que generated_power = voltage * current. Repare que o valor percentual geralmente não é um número inteiro, então certifique-se de usar corretamente as comparações < e <=.

Implemente o método Reactor.reactor_efficiency, com três parâmetros: voltage, current e theoretical_max_power. Essa função deve retornar a faixa de eficiência do reator: "green", "orange", "red" ou "black".

Reactor.reactor_efficiency(200,50,15000)
# => "orange"

3. Mecanismo à prova de falhas

Sua tarefa final é criar um mecanismo à prova de falhas para evitar sobrecarga e derretimento do núcleo. Esse mecanismo vai determinar se o reator está abaixo, no nível ou acima do limite ideal de criticalidade. A criticalidade pode então ser aumentada, diminuída ou interrompida inserindo (ou removendo) barras de controle no reator.

Implemente o método chamado Reactor.fail_safe(), que recebe 3 parâmetros: temperature, medida em kelvin, neutrons_produced_per_second e threshold, e retorna um código de status para o reator.

  • Se temperature * neutrons_produced_per_second for < 90% de threshold, retorne o código de status "LOW", indicando que as barras de controle precisam ser removidas para produzir energia.

  • Se temperature * neutrons_produced_per_second estiver dentro de mais ou menos 10% de threshold, o reator está em criticalidade e o código de status "NORMAL" deve ser retornado, indicando que o reator está em condição ideal e que as barras de controle estão em uma posição ideal.

  • Se temperature * neutrons_produced_per_second não estiver nas faixas acima, o reator vai sofrer um derretimento do núcleo e o código de status "DANGER" deve ser retornado para desligar o reator imediatamente.

temperature = 1000
neutrons_produced_per_second = 30
threshold = 5000
Reactor.fail_safe(temperature, neutrons_produced_per_second, threshold)
# => "DANGER"
Editar via GitHub O link abre em uma nova janela ou aba
Crystal Exercism

Tudo pronto para começar Mitigação do colapso?

Crie sua conta no Exercism para aprender e dominar Crystal com 26 conceitos142 exercícios e mentoria humana de verdade, tudo de graça.