Trilhas
/
Elixir
Elixir
/
Exercícios
/
Carrinho de controle remoto
Carrinho de controle remoto

Carrinho de controle remoto

Exercício de aprendizagem

Introdução

Structs

Structs são uma extensão construída sobre mapas, que oferecem verificações em tempo de compilação e valores padrão. Um struct recebe o nome do módulo em que é definido. Para definir um struct, use a construção defstruct. A construção normalmente vem logo depois da definição do módulo. defstruct aceita uma lista de átomos (para valores padrão nil) ou uma lista de palavras-chave (para valores padrão especificados). Os campos sem valor padrão devem vir antes dos campos com valor padrão.

defmodule Plane do
  defstruct [:engine, wings: 2]
end

plane = %Plane{}
# => %Plane{engine: nil, wings: 2}

Acessando e atualizando campos

Como structs são construídos sobre mapas, podemos usar a maioria das funções de mapa para obter e manipular valores. O Access Behaviour não é implementado para structs. Em vez disso, recomenda-se usar o operador de acesso estático . para acessar os campos do struct.

  • obter/buscar valores de campos:

    plane = %Plane{}
    plane.engine
    # => nil
    Map.fetch(plane, :wings)
    # => {:ok, 2}
    
  • atualizar valores de campos

    plane = %Plane{}
    %{plane | wings: 4}
    # => %Plane{engine: nil, wings: 4}
    

Pattern matching

Structs podem ser usados em pattern matching com ou sem o nome do struct.

plane = %Plane{}
%Plane{wings: wings} = plane
%{wings: wings} = plane

Ao incluir o nome do struct no padrão, você garante que tanto o lado esquerdo quanto o direito sejam structs do mesmo tipo.

defmodule Helicopter do
  defstruct [:engine, rotors: 1]
end

%Plane{} = %Helicopter{}
# => (MatchError) no match of right hand side value: %Helicopter{engine: nil, rotors: 1}

Exigindo a inicialização dos valores dos campos

Podemos usar o atributo de módulo @enforce_keys com uma lista das chaves dos campos para garantir que os valores sejam inicializados quando o struct for criado. Se uma chave não estiver listada, seu valor será nil, como no exemplo acima. Se uma chave exigida não for inicializada, um erro é lançado.

defmodule User do
  @enforce_keys [:username]
  defstruct [:username]
end

%User{}
# => (ArgumentError) the following keys must also be given when building struct User: [:username]

Instruções

Neste exercício, você vai brincar com um carro de controle remoto, aquele que você finalmente juntou dinheiro suficiente para comprar.

Os carros começam com a bateria cheia (100%). Cada vez que você dirige o carro com o controle remoto, ele percorre 20 metros e consome um por cento da bateria. O apelido do carro não é conhecido até que ele seja criado.

O carro de controle remoto tem um display de LED sofisticado que mostra duas informações:

  • A distância total percorrida, exibida como: "<METERS> meters".
  • A carga restante da bateria, exibida como: "Battery at <PERCENTAGE>%".

Se a bateria estiver em 0%, você não pode mais dirigir o carro e o display da bateria vai mostrar "Battery empty".

1. Crie um carro de controle remoto novinho em folha

Implemente a função RemoteControlCar.new/0 para retornar uma struct de carro de controle remoto novinho em folha:

RemoteControlCar.new()
# => %RemoteControlCar{
#      battery_percentage: 100,
#      distance_driven_in_meters: 0,
#      nickname: "none"
#    }

O apelido é exigido pela struct. Certifique-se de que um valor seja inicializado na função new, mas não na struct.

2. Crie um carro de controle remoto novinho em folha com um apelido

Implemente a função RemoteControlCar.new/1 para retornar uma struct de carro de controle remoto novinho em folha com um apelido fornecido:

RemoteControlCar.new("Blue")
# => %RemoteControlCar{
#      battery_percentage: 100,
#      distance_driven_in_meters: 0,
#      nickname: "Blue"
#    }

3. Exiba a distância

Implemente a função RemoteControlCar.display_distance/1 para retornar a distância conforme exibida no display de LED:

car = RemoteControlCar.new()
RemoteControlCar.display_distance(car)
# => "0 meters"

Certifique-se de que a função aceite apenas uma struct RemoteControlCar como argumento.

4. Exiba a porcentagem da bateria

Implemente a função RemoteControlCar.display_battery/1 para retornar a porcentagem da bateria conforme exibida no display de LED:

car = RemoteControlCar.new()
RemoteControlCar.display_battery(car)
# => "Battery at 100%"

Certifique-se de que a função aceite apenas uma struct RemoteControlCar como argumento. Se a bateria estiver em 0%, o display da bateria vai mostrar "Battery empty".

5. Dirigir altera a bateria e a distância percorrida

Implemente a função RemoteControlCar.drive/1 que:

  • aumenta em 20 o número de metros percorridos
  • consome 1% da bateria
RemoteControlCar.new("Red")
|> RemoteControlCar.drive()

# => %RemoteControlCar{
#      battery_percentage: 99,
#      distance_driven_in_meters: 20,
#      nickname: "Red"
#    }

Certifique-se de que a função aceite apenas uma struct RemoteControlCar como argumento.

6. Leve em conta dirigir com a bateria descarregada

Atualize a função RemoteControlCar.drive/1 para não aumentar a distância percorrida nem diminuir a porcentagem da bateria quando a bateria estiver descarregada (em 0%):

%RemoteControlCar{
  battery_percentage: 0,
  distance_driven_in_meters: 1980,
  nickname: "Red"
}
|> RemoteControlCar.drive()

# => %RemoteControlCar{
#      battery_percentage: 0,
#      distance_driven_in_meters: 1980,
#      nickname: "Red"
#    }
Editar via GitHub O link abre em uma nova janela ou aba
Elixir Exercism

Tudo pronto para começar Carrinho de controle remoto?

Crie sua conta no Exercism para aprender e dominar Elixir com 58 conceitos168 exercícios e mentoria humana de verdade, tudo de graça.