summaryrefslogtreecommitdiff
path: root/internal/batch/processor.go
blob: c785a91ed14457f66f5a9df68848ed73268d157b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package batch

import (
	"fmt"
	"os"
	"strings"

	"codeberg.org/snonux/totalrecall/internal"
)

// WordEntry represents a word with optional translation
type WordEntry struct {
	Bulgarian   string
	Translation string
	// NeedsTranslation indicates if translation from English to Bulgarian is needed
	NeedsTranslation bool
	// CardType indicates whether this is en-bg or bg-bg card
	CardType internal.CardType
}

// ReadBatchFile reads words from a file and returns WordEntry slice
// Supports formats:
// - Bulgarian word only: "ябълка" (will be translated to English)
// - With translation: "ябълка = apple" (both provided, no translation needed)
// - English only: "= apple" (will be translated to Bulgarian)
// - Bulgarian-Bulgarian: "word1 == definition" (bg-bg card, double equals)
func ReadBatchFile(filename string) ([]WordEntry, error) {
	content, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("failed to read batch file: %w", err)
	}

	var entries []WordEntry
	// Normalize \r\n to \n before splitting so both Windows and Unix line
	// endings are handled uniformly by strings.Split.
	normalized := strings.ReplaceAll(string(content), "\r\n", "\n")
	for _, line := range strings.Split(normalized, "\n") {
		if line = strings.TrimSpace(line); line != "" {
			entry := parseBatchLine(line)
			if entry != nil {
				entries = append(entries, *entry)
			}
		}
	}

	return entries, nil
}

// parseBatchLine parses a single batch file line and returns the appropriate WordEntry
func parseBatchLine(line string) *WordEntry {
	// Check for Bulgarian-Bulgarian format first (double equals ==)
	if strings.Contains(line, "==") {
		parts := strings.SplitN(line, "==", 2)
		if len(parts) == 2 {
			bulgarian1 := strings.TrimSpace(parts[0])
			bulgarian2 := strings.TrimSpace(parts[1])

			if bulgarian1 != "" && bulgarian2 != "" {
				return &WordEntry{
					Bulgarian:        bulgarian1,
					Translation:      bulgarian2,
					NeedsTranslation: false,
					CardType:         internal.CardTypeBgBg,
				}
			}
		}
		return nil
	}

	// Check for English-Bulgarian format (single equals =)
	if strings.Contains(line, "=") {
		parts := strings.SplitN(line, "=", 2)
		if len(parts) == 2 {
			bulgarian := strings.TrimSpace(parts[0])
			english := strings.TrimSpace(parts[1])

			if bulgarian == "" && english != "" {
				// Format: "= ENGLISH" - need to translate English to Bulgarian
				return &WordEntry{
					Bulgarian:        "",
					Translation:      english,
					NeedsTranslation: true,
					CardType:         internal.CardTypeEnBg,
				}
			} else if bulgarian != "" && english != "" {
				// Format: "BULGARIAN = ENGLISH" - both provided
				return &WordEntry{
					Bulgarian:        bulgarian,
					Translation:      english,
					NeedsTranslation: false,
					CardType:         internal.CardTypeEnBg,
				}
			}
		}
		return nil
	}

	// Just a Bulgarian word - needs translation to English
	return &WordEntry{
		Bulgarian:        line,
		Translation:      "",
		NeedsTranslation: false,
		CardType:         internal.CardTypeEnBg,
	}
}