This commit is contained in:
Lucy 2025-03-30 20:14:08 +02:00
parent 059b8ff976
commit 4b5efa3d3d
2 changed files with 154 additions and 42 deletions

View file

@ -4,6 +4,7 @@
{ {
"Name": "Abschnitte", "Name": "Abschnitte",
"Path": "abschnitte", "Path": "abschnitte",
"DisplayTextColumn": 2,
"CSVFile": "abschnitte.csv", "CSVFile": "abschnitte.csv",
"Default_Language": "dt", "Default_Language": "dt",
"Default_Variants": ["hoch"] "Default_Variants": ["hoch"]
@ -11,6 +12,7 @@
{ {
"Name": "Gleise", "Name": "Gleise",
"Path": "gleise_zahlen", "Path": "gleise_zahlen",
"DisplayTextColumn": 2,
"CSVFile": "gleise_zahlen.csv", "CSVFile": "gleise_zahlen.csv",
"Default_Variants": ["hoch"], "Default_Variants": ["hoch"],
"Default_Language": "dt" "Default_Language": "dt"
@ -18,8 +20,99 @@
{ {
"Name": "Module", "Name": "Module",
"Path": "module", "Path": "module",
"DisplayTextColumn": 2,
"CSVFile": "module_dt.csv", "CSVFile": "module_dt.csv",
"Default_Language": "dt" "Default_Language": "dt"
},
{
"Name": "Ziele",
"Path": "ziele",
"DisplayTextColumn": 6,
"CSVFile": "ziele.csv",
"Default_Language": "dt",
"DefaultType": "hoch",
"Default_Variants": ["variante1"]
},
{
"Name": "Grund_dafuer",
"Path": "grund_dafuer",
"DisplayTextColumn": 7,
"CSVFile": "grund_dafuer.csv",
"Default_Language": "dt"
},
{
"Name": "Linien_Kombi",
"Path": "linien/linien_kombi",
"DisplayTextColumn": 2,
"CSVFile": "linien_kombi.csv",
"Default_Language": "dt"
},
{
"Name": "S_Linien_Nr",
"Path": "linien/s_linien_nr",
"DisplayTextColumn": 2,
"CSVFile": "s_linien_nr.csv",
"DefaultType": "hoch",
"Default_Language": "dt"
},
{
"Name": "Minuten",
"Path": "zeiten/minuten",
"DisplayTextColumn": 2,
"CSVFile": "minuten.csv",
"DefaultType": "hoch",
"Default_Language": "dt"
},
{
"Name": "Stunden",
"Path": "zeiten/stunden",
"DisplayTextColumn": 2,
"CSVFile": "stunden.csv",
"DefaultType": "hoch",
"Default_Language": "dt"
},
{
"Name": "Verspaetung_ab",
"Path": "zeiten/verspaetung_ab",
"DisplayTextColumn": 2,
"CSVFile": "verspaetung_ab.csv",
"Default_Language": "dt"
},
{
"Name": "verspaetung_an",
"Path": "zeiten/verspaetung_an",
"DisplayTextColumn": 2,
"CSVFile": "verspaetung_an.csv",
"Default_Language": "dt"
},
{
"Name": "verspaetung_heute",
"Path": "zeiten/verspaetung_heute",
"DisplayTextColumn": 2,
"CSVFile": "verspaetung_heute.csv",
"Default_Language": "dt"
},
{
"Name": "NZA",
"Path": "nza",
"DisplayTextColumn": 3,
"CSVFile": "nza.csv",
"Default_Language": "dt"
},
{
"Name": "Zusatztexte",
"Path": "zusatztexte",
"DisplayTextColumn": 3,
"CSVFile": "zusatztexte.csv",
"Default_Language": "dt"
},
{
"Name": "Zuggattungen",
"Path": "zuggattungen",
"DisplayTextColumn": 2,
"CSVFile": "zuggattungen.csv",
"DefaultType": "hoch",
"Default_Language": "dt"
} }
] ]
} }

103
main.go
View file

@ -16,8 +16,8 @@ import (
// Config represents the structure of the config.json file. // Config represents the structure of the config.json file.
type Config struct { type Config struct {
BaseDir string `json:"Base_Dir"` BaseDir string `json:"Base_Dir"`
Modules []Module `json:"Modules"` Modules []Module `json:"Modules"`
} }
// Module represents a module entry in the config.json file. // Module represents a module entry in the config.json file.
@ -27,6 +27,8 @@ type Module struct {
CSVFile string `json:"CSVFile"` CSVFile string `json:"CSVFile"`
DefaultLanguage string `json:"Default_Language"` DefaultLanguage string `json:"Default_Language"`
DefaultVariants []string `json:"Default_Variants"` DefaultVariants []string `json:"Default_Variants"`
DefaultType string `json:"DefaultType"` // New config value for DefaultType
DisplayTextColumn int `json:"DisplayTextColumn"` // New config value for DisplayTextColumn
} }
func main() { func main() {
@ -118,12 +120,12 @@ func printPrompt(currentInput []string) {
} }
} }
// Collect all display texts for autocomplete // Collect all display texts for autocomplete, using the module's DisplayTextColumn
func collectAllDisplayTexts(config Config) []string { func collectAllDisplayTexts(config Config) []string {
var displayTexts []string var displayTexts []string
for _, module := range config.Modules { for _, module := range config.Modules {
// Unpack both return values (displayTexts and fileNames) // Pass both the file path and DisplayTextColumn to readDisplayTextsAndFileNames
moduleDisplayTexts, _ := readDisplayTextsAndFileNames(config.BaseDir + "/" + module.CSVFile) moduleDisplayTexts, _ := readDisplayTextsAndFileNames(config.BaseDir + "/" + module.CSVFile, module.DisplayTextColumn)
displayTexts = append(displayTexts, moduleDisplayTexts...) displayTexts = append(displayTexts, moduleDisplayTexts...)
} }
return displayTexts return displayTexts
@ -132,7 +134,6 @@ func collectAllDisplayTexts(config Config) []string {
// Function to collect all display texts and play matching files // Function to collect all display texts and play matching files
func autocompleteAndPlay(config Config, inputText []string) { func autocompleteAndPlay(config Config, inputText []string) {
var matchingFiles []string // Store matching files in the order of inputText var matchingFiles []string // Store matching files in the order of inputText
var moduleNames []string // Store corresponding module names for each matched file
// Normalize each input word (e.g., convert umlauts to standard form) // Normalize each input word (e.g., convert umlauts to standard form)
for _, part := range inputText { for _, part := range inputText {
@ -140,15 +141,16 @@ func autocompleteAndPlay(config Config, inputText []string) {
// Collect matching filenames from the second column (display text) and first column (filenames) // Collect matching filenames from the second column (display text) and first column (filenames)
for _, module := range config.Modules { for _, module := range config.Modules {
displayTexts, fileNames := readDisplayTextsAndFileNames(config.BaseDir + "/" + module.CSVFile) // Pass both the file path and DisplayTextColumn to readDisplayTextsAndFileNames
displayTexts, fileNames := readDisplayTextsAndFileNames(config.BaseDir + "/" + module.CSVFile, module.DisplayTextColumn)
for i, text := range displayTexts { for i, text := range displayTexts {
// Normalize display text before comparing and remove any trailing spaces // Normalize display text before comparing
normalizedText := norm.NFC.String(strings.TrimSpace(text)) normalizedText := norm.NFC.String(text)
// Explicitly compare both normalized strings (case-sensitive) // Exact match: check if the input exactly matches the display text (case-insensitive)
if normalizedText == normalizedInputText { if strings.EqualFold(normalizedText, normalizedInputText) {
matchingFiles = append(matchingFiles, fileNames[i]) // Include the module name to be used for path construction
moduleNames = append(moduleNames, module.Name) // Track the module that matched matchingFiles = append(matchingFiles, fmt.Sprintf("%s:%s", module.Name, fileNames[i]))
} }
} }
} }
@ -160,19 +162,32 @@ func autocompleteAndPlay(config Config, inputText []string) {
return return
} }
// Debugging: print matched files and their corresponding modules // Debugging: print matched files
fmt.Println("Matched files:") fmt.Println("Matched files:")
for i, fileName := range matchingFiles { for _, fileName := range matchingFiles {
fmt.Printf(" - File: %s, Module: %s\n", fileName, moduleNames[i]) fmt.Println(" - ", fileName)
} }
// Play matching audio files in the exact order they were entered // Play matching audio files in the exact order they were entered
for i, fileName := range matchingFiles { for _, fileName := range matchingFiles {
// Get the module name associated with this matched file // Extract module and filename
moduleName := moduleNames[i] parts := strings.SplitN(fileName, ":", 2)
if len(parts) != 2 {
continue
}
moduleName, file := parts[0], parts[1]
// Construct the correct audio path using the module information // Find the correct module by name
audioPath := constructAudioPath(config, fileName, moduleName) var module Module
for _, m := range config.Modules {
if m.Name == moduleName {
module = m
break
}
}
// Construct the audio path using the correct module
audioPath := constructAudioPath(config, module, file)
// Debugging: print the constructed audio path // Debugging: print the constructed audio path
fmt.Printf("Attempting to play audio from path: %s\n", audioPath) fmt.Printf("Attempting to play audio from path: %s\n", audioPath)
@ -192,36 +207,38 @@ func autocompleteAndPlay(config Config, inputText []string) {
} }
// Function to construct the audio file path with language and variant considerations // Function to construct the audio file path with language and variant considerations
func constructAudioPath(config Config, fileName, moduleName string) string { func constructAudioPath(config Config, module Module, fileName string) string {
var audioPath string var audioPath string
var languagePart, variantPart string var languagePart, typePart, variantPart string
// Find the module for which we need to construct the path // If a language is set in the module, use it
var selectedModule Module if len(module.DefaultLanguage) > 0 {
for _, module := range config.Modules { languagePart = module.DefaultLanguage + "/"
if module.Name == moduleName {
selectedModule = module
break
}
} }
// If a language is set in the selected module, use it // If DefaultType is set in the module, use it
if len(selectedModule.DefaultLanguage) > 0 { if len(module.DefaultType) > 0 {
languagePart = selectedModule.DefaultLanguage + "/" typePart = module.DefaultType + "/"
} }
// If a variant is set in the selected module, use it // If DefaultVariants is set in the module, use it
if len(selectedModule.DefaultVariants) > 0 { if len(module.DefaultVariants) > 0 {
variantPart = selectedModule.DefaultVariants[0] + "/" variantPart = module.DefaultVariants[0] + "/"
}
// Only add DefaultType and DefaultVariants to the path if they are set
if languagePart != "" || typePart != "" || variantPart != "" {
audioPath = fmt.Sprintf("%s/%s%s/%s%s/%s", config.BaseDir, languagePart, module.Path, variantPart, typePart, fileName)
} else {
// If neither DefaultType nor DefaultVariants is set, omit both from the path
audioPath = fmt.Sprintf("%s/%s/%s", config.BaseDir, module.Path, fileName)
} }
// Construct the path
audioPath = fmt.Sprintf("%s/%s%s/%s%s", config.BaseDir, languagePart, selectedModule.Path, variantPart, fileName)
return audioPath return audioPath
} }
// Function to read display texts (second column) and filenames (first column) from a CSV file // Function to read display texts (specified column) and filenames from a CSV file
func readDisplayTextsAndFileNames(filePath string) ([]string, []string) { func readDisplayTextsAndFileNames(filePath string, displayTextColumn int) ([]string, []string) {
file, err := os.Open(filePath) file, err := os.Open(filePath)
if err != nil { if err != nil {
log.Fatalf("Error opening CSV file: %v", err) log.Fatalf("Error opening CSV file: %v", err)
@ -238,7 +255,9 @@ func readDisplayTextsAndFileNames(filePath string) ([]string, []string) {
for _, record := range records { for _, record := range records {
if len(record) > 1 { if len(record) > 1 {
fileNames = append(fileNames, record[0]) // First column is the filename fileNames = append(fileNames, record[0]) // First column is the filename
displayTexts = append(displayTexts, record[1]) // Second column is the display text if displayTextColumn-1 < len(record) {
displayTexts = append(displayTexts, strings.TrimSpace(record[displayTextColumn-1])) // The specified column is the display text
}
} }
} }
return displayTexts, fileNames return displayTexts, fileNames
@ -249,7 +268,7 @@ func playAudioFiles(filePath string) error {
// Debugging: print the file path being played // Debugging: print the file path being played
fmt.Printf("Playing audio from: %s\n", filePath) fmt.Printf("Playing audio from: %s\n", filePath)
cmd := exec.Command("ffplay", "-nodisp", "-autoexit", filePath) cmd := exec.Command("ffplay", "-nodisp", "-hide_banner", "-autoexit", filePath)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
err := cmd.Run() err := cmd.Run()