Besoin d'aide pour améliorer Ruby DSL afin de contrôler un distributeur de boissons contrôlé par Arduino (Bar Monkey)

StackOverflow https://stackoverflow.com/questions/164095

Question

J'écris un Ruban DSL en Ruby pour contrôler un projet Arduino sur lequel je travaille; Bardino. C'est un singe de bar qui sera contrôlé par logiciel pour servir des boissons. L’Arduino reçoit des commandes via le port série pour indiquer à l’Arduino quelles pompes allumer et pendant combien de temps.

Il lit actuellement une recette (voir ci-dessous) et l’imprime. Le code des communications série doit encore être inséré, de même que certaines autres idées que j'ai mentionnées ci-dessous.

Ceci est mon premier DSL et je travaille à partir d'un exemple précédent, donc c'est très difficile sur les bords. Toute critique, amélioration du code (existe-t-il de bonnes références pour les meilleures pratiques ou idiomes de Ruby DSL?) Ou des commentaires généraux.

Comme je dispose actuellement d'un brouillon de la LIS, une recette de boisson ressemble à ceci: lien Github ):

desc "Simple glass of water"
recipe "water" do
  ingredients(
  "Water" => 2.ounces
  )
end

Ceci est à son tour interprété et produit les résultats suivants ( Lien Github ):

[mwilliams@Danzig barduino-tender]$ ruby barduino-tender.rb examples/water.rb
Preparing: Simple glass of water

Ingredients:
 Water: 2 ounces

C’est un bon début pour le DSL, cependant, je pense qu’il pourrait être mis en œuvre un peu mieux. Quelques idées que j'ai eues ci-dessous:

  1. Définition des "ingrédients" " sont disponibles en utilisant le nom de l'ingrédient et le numéro de pompe auquel il est connecté. Peut-être en utilisant un hash? ingrédients = {" eau " = > 1, " vodka " = > 2}. Ainsi, lorsqu'un ingrédient est interprété, il peut soit: a) envoyer le numéro de la pompe sur le port série, suivi du nombre d'onces que l'Arduino doit distribuer, b) informer l'utilisateur que cet ingrédient n'existe pas et abandonner sans que rien ne soit distribué c) avoir facilement la possibilité de changer ou d'ajouter de nouveaux ingrédients s'ils sont changés.
  2. Faire en sorte que la recette ressemble moins à du code, ce qui est l'objectif principal d'un DSL, peut-être créer un constructeur de recettes? Utilisation des ingrédients disponibles pour inviter l’utilisateur à indiquer le nom de la boisson, les ingrédients en cause et quelle quantité?

Le projet Github est ici , n'hésitez pas à passer à la fourchette et à tirer. demandes, ou postez vos suggestions de code et exemples ici pour que les autres utilisateurs les voient. Et si vous êtes curieux, le code Arduino, en utilisant le framework de développement Ruby Arduino, est ici .

Mettre à jour

J'ai modifié et nettoyé un peu les choses pour refléter la suggestion d'Orion Edwards concernant une recette. Cela ressemble maintenant à ce qui suit.

description 'Screwdriver' do 
  serve_in 'Highball Glass'
  ingredients do
    2.ounces :vodka
    5.ounces :orange_juice
  end
end

J'ai également ajouté un hachage (la clé étant l'ingrédient et la valeur le numéro de pompe auquel il est relié). Je pense que cela a fourni beaucoup de progrès. Je laisserai la question ouverte pour toute suggestion supplémentaire pour l'instant, mais je choisirai finalement la réponse d'Orion. Le code DSL mis à jour est ici .

Était-ce utile?

La solution

Sans regarder dans les détails de la mise en œuvre (ni dans vos liens github), j'essaierais d'écrire un DSL comme celui-ci:

(vol à partir d'ici: 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

J'espère que ça aide!

Autres conseils

Si vous souhaitez que la recette paraisse plus naturelle, pourquoi pas (d'après la même recette utilisée par Orion Ewards, merci!):

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)

Ajoutez ensuite Treetop au mélange. Vous pourriez avoir des règles telles que:

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

Le compilateur de cime des arbres se transformera en un joli module ruby. Puis:

parser = CocktailParser.new
r = parser.parse(recipe)

Le DSL d'Orion est très joli. Le seul changement que je pourrais éventuellement suggérer de votre part "mis à jour". le code est

  1. Remplacez description par recette . C'est un terme plus descriptif
  2. Etant donné que l'ensemble des ingrédients et des actions est fixe, liez les ingrédients aux variables plutôt qu'aux symboles, c.-à-d. que vous avez vodka =: vodka défini quelque part. C'est plus facile à dire

    mélangez la vodka, le gin et le triple_sec # au lieu d'utiliser: vodka,: gin et: triple_sec.

de toute façon c'est un petit nit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top