Compare commits
4 Commits
7aa3760711
...
0ca262c2ea
Author | SHA1 | Date | |
---|---|---|---|
0ca262c2ea | |||
de0a3b3e85 | |||
9b0597e680 | |||
3ae5ea780e |
20
config/config.go
Normal file
20
config/config.go
Normal file
@ -0,0 +1,20 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type AppConfig struct {
|
||||
DataPath string
|
||||
}
|
||||
|
||||
func Load() AppConfig {
|
||||
// TODO: Handle os.MkdirAll error gracefully
|
||||
homeDir, _ := os.UserHomeDir()
|
||||
ketotrackDir := filepath.Join(homeDir, ".ketotrack")
|
||||
os.MkdirAll(ketotrackDir, 0770) // handle error appropriately
|
||||
return AppConfig{
|
||||
DataPath: filepath.Join(ketotrackDir, "records.json"),
|
||||
}
|
||||
}
|
46
data/records.go
Normal file
46
data/records.go
Normal file
@ -0,0 +1,46 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"ketotrack/model"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Record holds a pointer to a Reading or Note.
|
||||
type Record struct {
|
||||
Reading *model.Reading `json:"reading,omitempty"`
|
||||
Note *model.Note `json:"note,omitempty"`
|
||||
}
|
||||
|
||||
// AppContext is the application data store that holds Records
|
||||
type AppContext struct {
|
||||
Records []Record
|
||||
}
|
||||
|
||||
// LoadRecords will load records from file
|
||||
func (ctx *AppContext) LoadRecords(filename string) error {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, &ctx.Records)
|
||||
}
|
||||
|
||||
// SaveRecords will save records to a file
|
||||
func (ctx *AppContext) SaveRecords(filename string) error {
|
||||
jsonData, err := json.Marshal(ctx.Records)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filename, jsonData, 0660)
|
||||
}
|
||||
|
||||
// AddReading will add a Reading to the AppContext
|
||||
func (ctx *AppContext) AddReading(reading model.Reading) {
|
||||
ctx.Records = append(ctx.Records, Record{Reading: &reading})
|
||||
}
|
||||
|
||||
// AddNote will a add a Note to the AppContext
|
||||
func (ctx *AppContext) AddNote(note model.Note) {
|
||||
ctx.Records = append(ctx.Records, Record{Note: ¬e})
|
||||
}
|
106
main.go
106
main.go
@ -2,14 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"ketotrack/data"
|
||||
"ketotrack/model"
|
||||
)
|
||||
|
||||
var recordsFilename string
|
||||
@ -36,89 +37,8 @@ func init() {
|
||||
recordsFilename = filepath.Join(ketotrackDir, "records.json")
|
||||
}
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// NewNote returns a new Note
|
||||
func NewNote(text string) Note {
|
||||
return Note{
|
||||
Time: time.Now(),
|
||||
Text: text,
|
||||
}
|
||||
}
|
||||
|
||||
// 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"`
|
||||
GKI float64 `json:"GKI"`
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var gki float64
|
||||
if ketone == 0 {
|
||||
gki = 0
|
||||
} else {
|
||||
gki = (glucose / 18) / ketone
|
||||
}
|
||||
|
||||
return Reading{
|
||||
Time: time.Now(),
|
||||
Glucose: glucose,
|
||||
Ketone: ketone,
|
||||
GKI: gki,
|
||||
}
|
||||
}
|
||||
|
||||
// AppContext is the application data store that holds Records
|
||||
type AppContext struct {
|
||||
Records []Record
|
||||
}
|
||||
|
||||
// LoadRecords will load records from file
|
||||
func (ctx *AppContext) LoadRecords(filename string) error {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(data, &ctx.Records)
|
||||
}
|
||||
|
||||
// SaveRecords will save records to a file
|
||||
func (ctx *AppContext) SaveRecords(filename string) error {
|
||||
jsonData, err := json.Marshal(ctx.Records)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(filename, jsonData, 0660)
|
||||
}
|
||||
|
||||
// AddReading will add a Reading to the AppContext
|
||||
func (ctx *AppContext) AddReading(reading Reading) {
|
||||
ctx.Records = append(ctx.Records, Record{Reading: &reading})
|
||||
}
|
||||
|
||||
// AddNote will a add a Note to the AppContext
|
||||
func (ctx *AppContext) AddNote(note Note) {
|
||||
ctx.Records = append(ctx.Records, Record{Note: ¬e})
|
||||
}
|
||||
|
||||
func main() {
|
||||
// TODO: Write option handlers (handleNewNote, handleNewReading)
|
||||
|
||||
var appCtx AppContext
|
||||
var appCtx data.AppContext
|
||||
|
||||
if err := appCtx.LoadRecords(recordsFilename); err != nil {
|
||||
fmt.Printf("Error loading records from file: %s\n", err)
|
||||
@ -164,39 +84,39 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func getNote() (Note, error) {
|
||||
func getNote() (model.Note, error) {
|
||||
text, err := getUserInput("Enter note text")
|
||||
if err != nil {
|
||||
return Note{}, err
|
||||
return model.Note{}, err
|
||||
}
|
||||
return NewNote(text), nil
|
||||
return model.NewNote(text), nil
|
||||
}
|
||||
|
||||
func getReading() (Reading, error) {
|
||||
func getReading() (model.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)
|
||||
return model.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")
|
||||
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 Reading{}, fmt.Errorf("error getting ketone reading: %w", err)
|
||||
return model.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 model.Reading{}, errors.New("ketone reading cannot be less than 0")
|
||||
}
|
||||
|
||||
reading := NewReading(glucose, ketone)
|
||||
reading := model.NewReading(glucose, ketone)
|
||||
|
||||
// Display GKI and level of ketosis
|
||||
fmt.Printf("\nYour GKI is: %0.2f\n", reading.GKI)
|
||||
|
43
model/types.go
Normal file
43
model/types.go
Normal file
@ -0,0 +1,43 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// NewNote returns a new Note
|
||||
func NewNote(text string) Note {
|
||||
return Note{
|
||||
Time: time.Now(),
|
||||
Text: text,
|
||||
}
|
||||
}
|
||||
|
||||
// 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"`
|
||||
GKI float64 `json:"GKI"`
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var gki float64
|
||||
if ketone == 0 {
|
||||
gki = 0
|
||||
} else {
|
||||
gki = (glucose / 18) / ketone
|
||||
}
|
||||
|
||||
return Reading{
|
||||
Time: time.Now(),
|
||||
Glucose: glucose,
|
||||
Ketone: ketone,
|
||||
GKI: gki,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user