187 lines
4.4 KiB
Go
187 lines
4.4 KiB
Go
package parser
|
|
|
|
import (
|
|
"autobrew/action"
|
|
"autobrew/ingredient"
|
|
"autobrew/recipe"
|
|
"autobrew/utils"
|
|
"bufio"
|
|
"io/fs"
|
|
"log"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
var add_to_cauldron = regexp.MustCompile(`(?mi)^Add (\d+ .+)+? to the cauldron\.$`)
|
|
var add_to_mortar = regexp.MustCompile(`(?mi)^Add (\d+ .+)+? to the mortar, grind, and pour into the cauldron\.$`)
|
|
var boil = regexp.MustCompile(`(?mi)^Boil for (\d+) turn[s]*\.$`)
|
|
var boil_bellows = regexp.MustCompile(`(?mi)^Boil for (\d+) turn[s]* using bellows\.$`)
|
|
var extract_amount = regexp.MustCompile(`(?mi)^(\d+) (.*)$`)
|
|
|
|
func transformStep(lines []string) (name string, steps []recipe.Step, err error) {
|
|
|
|
name, lines = lines[0], lines[1:]
|
|
|
|
var ingredients []ingredient.Ingredient
|
|
|
|
for index, line := range lines {
|
|
if strings.HasPrefix(line, "Liquid Base:") {
|
|
i, err := ingredient.IngredientFromString(strings.TrimSpace(strings.Split(line, ": ")[1]))
|
|
utils.Check(err)
|
|
|
|
ingredients = append(ingredients, i)
|
|
}
|
|
|
|
if strings.HasPrefix(line, "Ingredients:") {
|
|
parts := strings.TrimSpace(strings.Split(line, ":")[1])
|
|
for _, i := range strings.Split(parts, ",") {
|
|
|
|
a := strings.Split(strings.TrimSpace(i), " x")
|
|
i, err := ingredient.IngredientFromString(strings.TrimSpace(a[0]))
|
|
utils.Check(err)
|
|
|
|
amount, err := strconv.Atoi(a[1])
|
|
utils.Check(err)
|
|
|
|
for range amount {
|
|
ingredients = append(ingredients, i)
|
|
}
|
|
}
|
|
}
|
|
|
|
if strings.HasPrefix(line, "Recipe") {
|
|
lines = lines[index+1:]
|
|
}
|
|
}
|
|
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.Prepare,
|
|
Ingredients: ingredients,
|
|
})
|
|
|
|
for _, line := range lines {
|
|
line = strings.TrimSpace(line)
|
|
if match := add_to_cauldron.FindStringSubmatch(line); match != nil {
|
|
parts := strings.Split(match[1], " and ")
|
|
var ingredients []ingredient.Ingredient
|
|
for _, part := range parts {
|
|
if match := extract_amount.FindStringSubmatch(part); match != nil {
|
|
i, err := strconv.Atoi(match[1])
|
|
utils.Check(err)
|
|
|
|
for range i {
|
|
i, err := ingredient.IngredientFromString(strings.TrimSpace(match[2]))
|
|
utils.Check(err)
|
|
|
|
ingredients = append(ingredients, i)
|
|
}
|
|
|
|
}
|
|
}
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.AddToCauldron,
|
|
Ingredients: ingredients,
|
|
})
|
|
}
|
|
|
|
if match := add_to_mortar.FindStringSubmatch(line); match != nil {
|
|
parts := strings.Split(match[1], " and ")
|
|
var ingredients []ingredient.Ingredient
|
|
for _, part := range parts {
|
|
if match := extract_amount.FindStringSubmatch(part); match != nil {
|
|
i, err := strconv.Atoi(match[1])
|
|
utils.Check(err)
|
|
|
|
for range i {
|
|
i, err := ingredient.IngredientFromString(strings.TrimSpace(match[2]))
|
|
utils.Check(err)
|
|
|
|
ingredients = append(ingredients, i)
|
|
}
|
|
|
|
}
|
|
}
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.GrindIngredients,
|
|
Ingredients: ingredients,
|
|
})
|
|
}
|
|
|
|
if match := boil.FindStringSubmatch(line); match != nil {
|
|
i, err := strconv.Atoi(match[1])
|
|
utils.Check(err)
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.Boil,
|
|
Turns: i,
|
|
})
|
|
}
|
|
|
|
if match := boil_bellows.FindStringSubmatch(line); match != nil {
|
|
i, err := strconv.Atoi(match[1])
|
|
utils.Check(err)
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.BoilBellows,
|
|
Turns: i,
|
|
})
|
|
}
|
|
|
|
if strings.HasPrefix(line, "Pour into phial.") {
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.PourPhial,
|
|
})
|
|
}
|
|
|
|
if strings.HasPrefix(line, "Prepare phial and distill.") {
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.Distill,
|
|
})
|
|
}
|
|
|
|
if strings.HasPrefix(line, "Pour into a mortar and grind.") {
|
|
steps = append(steps, recipe.Step{
|
|
Action: action.GrindPotion,
|
|
})
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func FromText(file fs.File) map[string][]recipe.Step {
|
|
scanner := bufio.NewScanner(file)
|
|
// optionally, resize scanner's capacity for lines over 64K, see next example
|
|
recipes := make(map[string][]recipe.Step, 0)
|
|
lines := make([]string, 0)
|
|
|
|
for scanner.Scan() {
|
|
line := strings.TrimSpace(scanner.Text())
|
|
if len(line) == 0 {
|
|
continue
|
|
}
|
|
|
|
if line == "--" {
|
|
name, recipe, err := transformStep(lines)
|
|
utils.Check(err)
|
|
recipes[name] = recipe
|
|
lines = make([]string, 0)
|
|
continue
|
|
}
|
|
|
|
lines = append(lines, line)
|
|
|
|
}
|
|
|
|
if len(lines) > 0 {
|
|
name, recipe, err := transformStep(lines)
|
|
utils.Check(err)
|
|
recipes[name] = recipe
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
return recipes
|
|
}
|