Updated TimerList struct

This commit is contained in:
Brian Buller 2023-01-12 06:04:53 -06:00
parent 6310dc9f6b
commit 6060aa5d4a
2 changed files with 128 additions and 53 deletions

14
sort.go
View File

@ -13,6 +13,7 @@ const (
SORT_START_DATE_DESC SORT_START_DATE_DESC
SORT_FINISH_DATE_ASC SORT_FINISH_DATE_ASC
SORT_FINISH_DATE_DESC SORT_FINISH_DATE_DESC
SORT_ERROR
) )
// Sort allows a TimerList to be sorted by certain predefined fields. // Sort allows a TimerList to be sorted by certain predefined fields.
@ -28,8 +29,15 @@ func (timerlist *TimerList) Sort(sortFlag int) error {
default: default:
return errors.New("Unrecognized sort option") return errors.New("Unrecognized sort option")
} }
timerlist.sortFlag = sortFlag
return nil return nil
} }
func (timerlist *TimerList) refresh() {
timerlist.Sort(timerlist.sortFlag)
for i, t := range timerlist.timers {
t.Id = i
}
}
type timerlistSort struct { type timerlistSort struct {
timerlists TimerList timerlists TimerList
@ -37,15 +45,15 @@ type timerlistSort struct {
} }
func (ts *timerlistSort) Len() int { func (ts *timerlistSort) Len() int {
return len(ts.timerlists) return len(ts.timerlists.timers)
} }
func (ts *timerlistSort) Swap(l, r int) { func (ts *timerlistSort) Swap(l, r int) {
ts.timerlists[l], ts.timerlists[r] = ts.timerlists[r], ts.timerlists[l] ts.timerlists.timers[l], ts.timerlists.timers[r] = ts.timerlists.timers[r], ts.timerlists.timers[l]
} }
func (ts *timerlistSort) Less(l, r int) bool { func (ts *timerlistSort) Less(l, r int) bool {
return ts.by(ts.timerlists[l], ts.timerlists[r]) return ts.by(ts.timerlists.timers[l], ts.timerlists.timers[r])
} }
func (timerlist *TimerList) sortBy(by func(t1, t2 *Timer) bool) *TimerList { func (timerlist *TimerList) sortBy(by func(t1, t2 *Timer) bool) *TimerList {

View File

@ -6,32 +6,27 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"sort"
"strings" "strings"
"time" "time"
) )
// TimerList represents a list of timer.txt timer entries. // TimerList represents a list of timer.txt timer entries.
// It is usually loasded from a whole timer.txt file. // It is usually loasded from a whole timer.txt file.
type TimerList []*Timer type TimerList struct {
timers []*Timer
sortFlag int
}
// NewTimerList creates a new empty TimerList. // NewTimerList creates a new empty TimerList.
func NewTimerList() *TimerList { func NewTimerList() *TimerList { return &TimerList{} }
return &TimerList{} func (timerlist *TimerList) Size() int { return len(timerlist.timers) }
} func (timerlist *TimerList) GetTimerSlice() []*Timer { return timerlist.timers }
func (timerlist *TimerList) Size() int {
return len([]*Timer(*timerlist))
}
func (timerlist *TimerList) GetTimerSlice() []*Timer {
return []*Timer(*timerlist)
}
func (timerlist *TimerList) GetMostRecentTimer() (*Timer, error) { func (timerlist *TimerList) GetMostRecentTimer() (*Timer, error) {
var found *Timer var found *Timer
var latest time.Time var latest time.Time
for i := range *timerlist { for _, t := range timerlist.timers {
t := ([]*Timer(*timerlist))[i]
if t.FinishDate.IsZero() { if t.FinishDate.IsZero() {
if t.StartDate.After(latest) { if t.StartDate.After(latest) {
found = t found = t
@ -75,11 +70,81 @@ func (timerlist *TimerList) GetTimersWithProject(project string) *TimerList {
}) })
} }
func (timerlist *TimerList) GetContexts() []string {
var ret []string
added := make(map[string]bool)
for _, tmr := range timerlist.timers {
for _, c := range tmr.Contexts {
if !added[c] {
ret = append(ret, c)
added[c] = true
}
}
}
sort.Strings(ret)
return ret
}
func (timerlist *TimerList) GetProjects() []string {
var ret []string
added := make(map[string]bool)
for _, tmr := range timerlist.timers {
for _, p := range tmr.Projects {
if !added[p] {
ret = append(ret, p)
added[p] = true
}
}
}
sort.Strings(ret)
return ret
}
func (timerlist *TimerList) GetTagKVList() []string {
var ret []string
added := make(map[string]bool)
for _, tmr := range timerlist.timers {
for k, v := range tmr.AdditionalTags {
tag := fmt.Sprintf("%s:%s", k, v)
if !added[tag] {
ret = append(ret, tag)
added[tag] = true
}
}
}
sort.Strings(ret)
return ret
}
func (timerlist *TimerList) GetTagKeys() []string {
var ret []string
added := make(map[string]bool)
for _, tmr := range timerlist.timers {
for k := range tmr.AdditionalTags {
if !added[k] {
ret = append(ret, k)
added[k] = true
}
}
}
sort.Strings(ret)
return ret
}
func (timerlist *TimerList) GetTagValuesForKey(key string) []string {
var ret []string
added := make(map[string]bool)
for _, tmr := range timerlist.timers {
if v, ok := tmr.AdditionalTags[key]; ok && !added[v] {
ret = append(ret, v)
added[v] = true
}
}
sort.Strings(ret)
return ret
}
func (timerlist *TimerList) GetActiveTimers() *TimerList { func (timerlist *TimerList) GetActiveTimers() *TimerList {
t := *NewTimerList() t := *NewTimerList()
for _, v := range *timerlist { for _, v := range timerlist.timers {
if v.FinishDate.IsZero() { if v.FinishDate.IsZero() {
t = append(t, v) t.timers = append(t.timers, v)
} }
} }
return &t return &t
@ -88,7 +153,7 @@ func (timerlist *TimerList) GetActiveTimers() *TimerList {
// String returns a complete list of timers in timer.txt format. // String returns a complete list of timers in timer.txt format.
func (timerlist *TimerList) String() string { func (timerlist *TimerList) String() string {
var ret string var ret string
for _, timer := range *timerlist { for _, timer := range timerlist.timers {
ret += fmt.Sprintf("%s\n", timer.String()) ret += fmt.Sprintf("%s\n", timer.String())
} }
return ret return ret
@ -96,24 +161,23 @@ func (timerlist *TimerList) String() string {
// AddTimer prepends a Timer to the current TimerList and takes care to set the Timer.Id correctly // AddTimer prepends a Timer to the current TimerList and takes care to set the Timer.Id correctly
func (timerlist *TimerList) AddTimer(timer *Timer) { func (timerlist *TimerList) AddTimer(timer *Timer) {
// The new timer is going to be id 1 timerlist.timers = append(timerlist.timers, timer)
timer.Id = 1 timerlist.refresh()
for _, t := range *timerlist {
// Everything else gets incremented
t.Id++
} }
// Now prepend the timer to the slice
*timerlist = append(*timerlist, &Timer{}) // AddTimers adds all passed in timers to the list, sorts the list, then updates the Timer.Id values.
copy((*timerlist)[1:], (*timerlist)[0:]) func (timerlist *TimerList) AddTimers(timers []*Timer) {
(*timerlist)[0] = timer timerlist.timers = append(timerlist.timers, timers...)
timerlist.Sort(SORT_START_DATE_ASC)
} }
func (timerlist *TimerList) Combine(other *TimerList) { timerlist.AddTimers(other.timers) }
// GetTimer returns the Timer with the given timer 'id' from the TimerList. // GetTimer returns the Timer with the given timer 'id' from the TimerList.
// Returns an error if Timer could not be found. // Returns an error if Timer could not be found.
func (timerlist *TimerList) GetTimer(id int) (*Timer, error) { func (timerlist *TimerList) GetTimer(id int) (*Timer, error) {
for i := range *timerlist { for i := range timerlist.timers {
if ([]*Timer(*timerlist))[i].Id == id { if timerlist.timers[i].Id == id {
return ([]*Timer(*timerlist))[i], nil return timerlist.timers[i], nil
} }
} }
return nil, errors.New("timer not found") return nil, errors.New("timer not found")
@ -122,38 +186,40 @@ func (timerlist *TimerList) GetTimer(id int) (*Timer, error) {
// RemoveTimerById removes any Timer with given Timer 'id' from the TimerList. // RemoveTimerById removes any Timer with given Timer 'id' from the TimerList.
// Returns an error if no Timer was removed. // Returns an error if no Timer was removed.
func (timerlist *TimerList) RemoveTimerById(id int) error { func (timerlist *TimerList) RemoveTimerById(id int) error {
var newList TimerList
found := false found := false
for _, t := range *timerlist { var remIdx int
if t.Id != id { var t *Timer
newList = append(newList, t) for remIdx, t = range timerlist.timers {
} else { if t.Id == id {
found = true found = true
break
} }
} }
if !found { if !found {
return errors.New("timer not found") return errors.New("timer not found")
} }
*timerlist = newList timerlist.timers = append(timerlist.timers[:remIdx], timerlist.timers[remIdx+1:]...)
timerlist.refresh()
return nil return nil
} }
// RemoveTimer removes any Timer from the TimerList with the same String representation as the given Timer. // RemoveTimer removes any Timer from the TimerList with the same String representation as the given Timer.
// Returns an error if no Timer was removed. // Returns an error if no Timer was removed.
func (timerlist *TimerList) RemoveTimer(timer Timer) error { func (timerlist *TimerList) RemoveTimer(timer Timer) error {
var newList TimerList
found := false found := false
for _, t := range *timerlist { var remIdx int
if t.String() != timer.String() { var t *Timer
newList = append(newList, t) for remIdx, t = range timerlist.timers {
} else { if t.String() == timer.String() {
found = true found = true
break
} }
} }
if !found { if !found {
return errors.New("timer not found") return errors.New("timer not found")
} }
*timerlist = newList timerlist.timers = append(timerlist.timers[:remIdx], timerlist.timers[remIdx+1:]...)
timerlist.refresh()
return nil return nil
} }
@ -177,9 +243,9 @@ func (timerlist *TimerList) ArchiveTimerToFile(timer Timer, filename string) err
// bool), and returns a new TimerList. The original TimerList is not modified. // bool), and returns a new TimerList. The original TimerList is not modified.
func (timerlist *TimerList) Filter(predicate func(*Timer) bool) *TimerList { func (timerlist *TimerList) Filter(predicate func(*Timer) bool) *TimerList {
var newList TimerList var newList TimerList
for _, t := range *timerlist { for _, t := range timerlist.timers {
if predicate(t) { if predicate(t) {
newList = append(newList, t) newList.timers = append(newList.timers, t)
} }
} }
return &newList return &newList
@ -188,7 +254,7 @@ func (timerlist *TimerList) Filter(predicate func(*Timer) bool) *TimerList {
// LoadFromFile loads a TimerList from *os.File. // LoadFromFile loads a TimerList from *os.File.
// Note: This will clear the current TimerList and overwrite it's contents with whatever is in *os.File. // Note: This will clear the current TimerList and overwrite it's contents with whatever is in *os.File.
func (timerlist *TimerList) LoadFromFile(file *os.File) error { func (timerlist *TimerList) LoadFromFile(file *os.File) error {
*timerlist = []*Timer{} // Empty timerlist timerlist.timers = []*Timer{} // Empty timerlist
timerId := 1 timerId := 1
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(file)
for scanner.Scan() { for scanner.Scan() {
@ -202,12 +268,13 @@ func (timerlist *TimerList) LoadFromFile(file *os.File) error {
return err return err
} }
timer.Id = timerId timer.Id = timerId
*timerlist = append(*timerlist, timer)
timerId++ timerId++
timerlist.timers = append(timerlist.timers, timer)
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
return err return err
} }
timerlist.refresh()
return nil return nil
} }
@ -235,12 +302,12 @@ func (timerlist *TimerList) WriteToFilename(filename string) error {
} }
// LoadFromFile loads and returns a TimerList from *os.File. // LoadFromFile loads and returns a TimerList from *os.File.
func LoadFromFile(file *os.File) (TimerList, error) { func LoadFromFile(file *os.File) (*TimerList, error) {
timerlist := TimerList{} timerlist := TimerList{}
if err := timerlist.LoadFromFile(file); err != nil { if err := timerlist.LoadFromFile(file); err != nil {
return nil, err return nil, err
} }
return timerlist, nil return &timerlist, nil
} }
// WriteToFile writes a TimerList to *os.File. // WriteToFile writes a TimerList to *os.File.
@ -249,12 +316,12 @@ func WriteToFile(timerlist *TimerList, file *os.File) error {
} }
// LoadFromFilename loads and returns a TimerList from a file (most likely called "timer.txt") // LoadFromFilename loads and returns a TimerList from a file (most likely called "timer.txt")
func LoadFromFilename(filename string) (TimerList, error) { func LoadFromFilename(filename string) (*TimerList, error) {
timerlist := TimerList{} timerlist := TimerList{}
if err := timerlist.LoadFromFilename(filename); err != nil { if err := timerlist.LoadFromFilename(filename); err != nil {
return nil, err return nil, err
} }
return timerlist, nil return &timerlist, nil
} }
// WriteToFilename write a TimerList to the specified file (most likely called "timer.txt") // WriteToFilename write a TimerList to the specified file (most likely called "timer.txt")