proyecto - Necesita ayuda para mejorar un DSL de Ruby para controlar un dispensador de bebidas controlado por Arduino(barra de mono)
dispensador de gaseosa con arduino (3)
Estoy escribiendo un DSL en Ruby para controlar un proyecto de Arduino en el que estoy trabajando; Bardino. Es un mono de barra que será controlado por software para servir bebidas. El Arduino toma comandos a través del puerto serie para decirle al Arduino qué bombas encender y durante cuánto tiempo.
Actualmente lee una receta (ver más abajo) y la imprime de nuevo. El código para las comunicaciones en serie todavía necesita ser trabajado, así como algunas otras ideas que he mencionado a continuación.
Este es mi primer DSL y estoy trabajando en un ejemplo anterior, así que es muy difícil en los bordes. Cualquier crítica, mejoras en el código (¿hay alguna buena referencia para las mejores prácticas o expresiones idiomáticas de Ruby DSL?) O cualquier comentario general.
Actualmente tengo un borrador de la DSL así que una receta de bebida se parece a la siguiente ( enlace de Github ):
desc "Simple glass of water"
recipe "water" do
ingredients(
"Water" => 2.ounces
)
end
Esto, a su vez, se interpreta y se obtiene actualmente con lo siguiente ( enlace de Github ):
[mwilliams@Danzig barduino-tender]$ ruby barduino-tender.rb examples/water.rb
Preparing: Simple glass of water
Ingredients:
Water: 2 ounces
Este es un buen comienzo para DSL, sin embargo, creo que podría implementarse un poco mejor. Algunas ideas que tengo a continuación:
- Definir qué "ingredientes" están disponibles usando el nombre del ingrediente y la bomba de número a la que está conectado. ¿Tal vez usando un hash? ingredientes = {"agua" => 1, "vodka" => 2}. De esta manera, cuando se interpreta un ingrediente, puede a) enviar el número de la bomba sobre el puerto serie seguido del número de onzas para que el Arduino lo distribuya b) decirle al usuario que el ingrediente no existe y abortar para que no se administre nada c) tener fácilmente la capacidad de cambiar o agregar nuevos ingredientes si se cambian.
- Hacer que la receta parezca menos codificada, que es el objetivo principal de una DSL, ¿tal vez construir un generador de recetas? ¿Usando los ingredientes disponibles para solicitar al usuario el nombre de una bebida, los ingredientes involucrados y cuánto?
El proyecto Github está aquí , siéntase libre de copiar y hacer solicitudes de extracción, o publicar aquí sus sugerencias de códigos y ejemplos para que los vean otros usuarios. Y si tiene curiosidad, el código de Arduino, que utiliza el marco de desarrollo de Ruby Arduino, está aquí .
Actualizar
Modifiqué y limpié un poco las cosas para reflejar la sugerencia de Orion Edwards para una receta. Ahora se ve como el siguiente.
description ''Screwdriver'' do
serve_in ''Highball Glass''
ingredients do
2.ounces :vodka
5.ounces :orange_juice
end
end
También agregué un hash (la clave es el ingrediente y el valor del número de bomba al que está conectado). Creo que esto proporcionó mucho progreso. Dejaré la pregunta abierta para cualquier otra sugerencia por ahora, pero finalmente seleccionaré la respuesta de Orion. El código DSL actualizado está aquí .
Sin buscar detalles de implementación (o sus enlaces github), trataría de escribir una DSL como esta:
(robando desde aquí: http://supercocktails.com/1310/Long-Island-Iced-Tea- )
describe "Long Island Iced Tea" do
serve_in ''Highball Glass''
ingredients do
half.ounce.of :vodka
half.ounce.of :tequila
half.ounce.of :light_rum
half.ounce.of :gin
1.dash.of :coca_cola
#ignoring lemon peel as how can a robot peel a lemon?
end
steps do
add :vodka, :tequila, :light_rum, :gin
stir :gently
add :coca_cola
end
end
¡Espero que ayude!
El DSL de Orion se ve muy bien. El único cambio que posiblemente sugiero de tu código "actualizado" es
- Reemplazar la
description
con larecipe
. Es un término más descriptivo Dado que el conjunto de ingredientes y acciones es fijo, vincula los ingredientes a variables en lugar de símbolos, es decir, tienes
vodka = :vodka
definido en algún lugar. Es más fácil decirlomezcle vodka, gin y triple_sec # en lugar de usar: vodka,: gin y: triple_sec.
de todos modos, eso es una liendre menor.
Si desea que la receta se vea más natural, ¿por qué no? (De la misma receta que usó Orion Ewards, ¡gracias!):
Recipe for Long Island Iced Tea #1
Ingredients:
1/2 oz Vodka
1/2 oz Tequila
1/2 oz Light Rum
1/2 oz Gin
1 Dash Coca-Cola
# ignored Twist of Lemon Peel (or Lime)
Luego agrega Treetop a la mezcla. Usted podría tener reglas tales como:
grammar Cocktail
rule cocktail
title ingredients
end
rule title
''Recipe for'' S text:(.*) EOF
end
rule ingredients
ingredient+
end
rule ingredient
qty S liquid
end
# ...
end
Que el compilador treetop transformará en un buen módulo ruby. Entonces:
parser = CocktailParser.new
r = parser.parse(recipe)