package main import ( "bufio" "errors" "fmt" "os" "path/filepath" "strconv" "strings" "ketotrack/data" "ketotrack/model" ) var recordsFilename string func init() { // Get user's homeDir directory homeDir, err := os.UserHomeDir() if err != nil { fmt.Println("Error fetching user's home directory:", err) os.Exit(1) } // Define the path to the application data directory ketotrackDir := filepath.Join(homeDir, ".ketotrack") // Create the directory if it does not exist err = os.MkdirAll(ketotrackDir, 0770) if err != nil { fmt.Println("Error creating .ketotrack directory:", err) os.Exit(1) } // Set data file path for readings recordsFilename = filepath.Join(ketotrackDir, "records.json") } func main() { var appCtx data.AppContext if err := appCtx.LoadRecords(recordsFilename); err != nil { fmt.Printf("Error loading records from file: %s\n", err) } for { choice, err := getUserInput("1. Enter new reading\n2. Enter new note\n3. Exit\nYour choice") if err != nil { fmt.Printf("Error reading choice: %s\n", err) continue } if choice == "3" { fmt.Println("Exiting...") break } switch choice { case "1": // Get a new Reading from the user reading, err := getReading() if err != nil { fmt.Printf("Error getting reading: %s\n", err) } else { appCtx.AddReading(reading) } case "2": // Get a new Note from the user note, err := getNote() if err != nil { fmt.Printf("Error getting note: %s\n", err) } else { appCtx.AddNote(note) } default: fmt.Printf("Invalid choice, please try again.\n\n") } } // Save Records before exiting if err := appCtx.SaveRecords(recordsFilename); err != nil { fmt.Printf("Error saving records to file: %s\n", err) } } func getNote() (model.Note, error) { text, err := getUserInput("Enter note text") if err != nil { return model.Note{}, err } return model.NewNote(text), nil } func getReading() (model.Reading, error) { // Get glucose reading glucose, err := getUserFloat("Enter glucose reading (mg/dL)") if err != nil { return model.Reading{}, fmt.Errorf("error getting glucose reading: %w", err) } // Validate glucose reading if glucose <= 0 { return model.Reading{}, errors.New("glucose reading cannot be less than or equal to 0") } // Get ketone reading ketone, err := getUserFloat("Enter ketone reading (mmol/L)") if err != nil { return model.Reading{}, fmt.Errorf("error getting ketone reading: %w", err) } // Validate ketone reading if ketone < 0 { fmt.Println("") return model.Reading{}, errors.New("ketone reading cannot be less than 0") } reading := model.NewReading(glucose, ketone) // Display GKI and level of ketosis fmt.Printf("\nYour GKI is: %0.2f\n", reading.GKI) switch { case reading.GKI <= 1: fmt.Println("You're in the highest level of ketosis.") case reading.GKI < 3: fmt.Println("You're in a high therapeutic level of ketosis.") case reading.GKI < 6: fmt.Println("You're in a moderate level of ketosis.") case reading.GKI <= 9: fmt.Println("You're in a low level of ketosis.") default: fmt.Println("You are not in ketosis.") } return reading, nil } func getUserInput(prompt string) (string, error) { fmt.Printf("%s: ", prompt) reader := bufio.NewReader(os.Stdin) input, err := reader.ReadString('\n') if err != nil { return "", err } return strings.TrimSpace(input), nil } func getUserFloat(prompt string) (float64, error) { // Get input as a string s, err := getUserInput(prompt) if err != nil { return 0, err } // Convert string to float f, err := strconv.ParseFloat(s, 64) if err != nil { return 0, err } return f, nil }