Inital commit

This commit is contained in:
2026-01-02 05:00:07 +01:00
commit 950aaffcc7
14 changed files with 1864 additions and 0 deletions

186
parser/parser.go Normal file
View File

@@ -0,0 +1,186 @@
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
}