ketotrack/main.go

202 lines
4.8 KiB
Go
Raw Normal View History

2024-05-12 02:06:45 +00:00
package main
import (
"bufio"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"time"
)
var readingsFilename 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
readingsFilename = filepath.Join(ketotrackDir, "readings.json")
}
2024-05-12 18:13:24 +00:00
// Record holds a pointer to a Reading or Note.
type Record struct {
Reading *Reading `json:"reading,omitempty"`
Note *Note `json:"note,omitempty"`
}
// Note holds a text note along with the time the note was taken.
type Note struct {
Time time.Time `json:"time"`
Text string `json:"text"`
}
2024-05-12 02:06:45 +00:00
// Reading holds the glucose and ketone level measurements along with the time the measurements were taken.
type Reading struct {
Time time.Time `json:"time"`
Glucose float64 `json:"glucose"`
Ketone float64 `json:"ketone"`
2024-05-12 18:09:50 +00:00
GKI float64 `json:"GKI"`
2024-05-12 02:06:45 +00:00
}
// NewReading creates and returns a new Reading instance with the provided glucose and ketone levels, and records
// the current time. The glucose value should be provided in mg/dL, while the ketone level should be in mmol/L.
func NewReading(glucose, ketone float64) Reading {
2024-05-12 18:09:50 +00:00
var gki float64
if ketone == 0 {
gki = 0
} else {
gki = (glucose / 18) / ketone
}
2024-05-12 02:06:45 +00:00
return Reading{
Time: time.Now(),
Glucose: glucose,
Ketone: ketone,
2024-05-12 18:09:50 +00:00
GKI: gki,
2024-05-12 02:06:45 +00:00
}
}
2024-05-12 18:09:50 +00:00
/*
2024-05-12 02:06:45 +00:00
// GKI calculates and returns the Glucose Ketone Index of the reading.
// The Glucose Ketone Index helps determine the efficiency of glucose and ketone levels within the body. It is
// calculated as (glucose level in mg/dL / 18) divided by the ketone level.
func (r Reading) GKI() (float64, error) {
if r.Ketone == 0 {
return 0, errors.New("ketone level must not be zero to calculate GKI")
}
return (r.Glucose / 18) / r.Ketone, nil
2024-05-12 18:09:50 +00:00
}*/
2024-05-12 02:06:45 +00:00
func main() {
// Take a new reading from the user
reading, err := getReading()
if err != nil {
fmt.Println(err.Error())
return
}
// Calculate GKI
2024-05-12 18:09:50 +00:00
//gki, err := reading.GKI()
//if err != nil {
// fmt.Println(err.Error())
// fmt.Println("You are not in ketosis.")
// return
//}
// Display GKI and level of ketosis
fmt.Printf("\nYour GKI is: %0.2f\n", reading.GKI)
2024-05-12 02:06:45 +00:00
switch {
2024-05-12 18:09:50 +00:00
case reading.GKI <= 1:
2024-05-12 02:06:45 +00:00
fmt.Println("You're in the highest level of ketosis.")
2024-05-12 18:09:50 +00:00
case reading.GKI < 3:
2024-05-12 02:06:45 +00:00
fmt.Println("You're in a high therapeutic level of ketosis.")
2024-05-12 18:09:50 +00:00
case reading.GKI < 6:
2024-05-12 02:06:45 +00:00
fmt.Println("You're in a moderate level of ketosis.")
2024-05-12 18:09:50 +00:00
case reading.GKI <= 9:
2024-05-12 02:06:45 +00:00
fmt.Println("You're in a low level of ketosis.")
default:
fmt.Println("You are not in ketosis.")
}
// Save latest reading to readings file
readings, _ := loadReadingsFromFile(readingsFilename)
readings = append(readings, reading)
err = saveReadingsToFile(readingsFilename, readings)
if err != nil {
fmt.Printf("error saving data: %s\n", err.Error())
}
}
func saveReadingsToFile(filename string, data []Reading) error {
jsonData, err := json.Marshal(data)
if err != nil {
return err
}
return os.WriteFile(filename, jsonData, 0660)
}
func loadReadingsFromFile(filename string) ([]Reading, error) {
data, err := os.ReadFile(filename)
if err != nil {
return nil, err
}
var readings []Reading
err = json.Unmarshal(data, &readings)
if err != nil {
return nil, err
}
return readings, nil
}
func getReading() (Reading, error) {
// Get glucose reading
glucose, err := getUserFloat("Enter glucose reading (mg/dL)")
if err != nil {
return Reading{}, fmt.Errorf("error getting glucose reading: %w", err)
}
// Validate glucose reading
if glucose <= 0 {
return 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 Reading{}, fmt.Errorf("error getting ketone reading: %w", err)
}
// Validate ketone reading
if ketone < 0 {
fmt.Println("")
return Reading{}, errors.New("ketone reading cannot be less than 0")
}
return NewReading(glucose, ketone), 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
}