From 9698d90308e34702f3212a386b1b7087fef3f9d4 Mon Sep 17 00:00:00 2001 From: Ethan Holz Date: Thu, 13 Oct 2022 17:02:55 -0500 Subject: [PATCH 1/3] feat: Initial changes to handline generating a timeline --- msp/changeover.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/msp/changeover.go b/msp/changeover.go index 24a735a..50d2a8a 100644 --- a/msp/changeover.go +++ b/msp/changeover.go @@ -1,6 +1,7 @@ package msp import ( + "fmt" "sort" "time" ) @@ -58,3 +59,26 @@ func FlattenPeriods(periods ...Period) (ids []string) { } return } + +func GenerateTimeline(periods ...Period) (out []string) { + periodsByID := make(map[string]Period) + ids := FlattenPeriods(periods...) + for _, val := range periods { + id := val.GetIdentifier() + periodsByID[id] = val + } + start := periodsByID[ids[0]].GetStartTime() + for _, val := range ids { + next, err := GetNextChangeOver(start, periods...) + if err == nil { + if next.Equal(periodsByID[val].GetStartTime()) { + start = periodsByID[val].GetStartTime() + next = periodsByID[val].GetEndTime() + } + frame := fmt.Sprintf("%s\t%s\t%s\n", val, start, next) + out = append(out, frame) + start = next + } + } + return out +} From 8612f90d46b538186b207541763d06b14ecc2168 Mon Sep 17 00:00:00 2001 From: Ethan Holz Date: Fri, 14 Oct 2022 14:17:50 -0500 Subject: [PATCH 2/3] feat: Completed functionality for generating a period timeline --- main.go | 14 +++- msp/changeover.go | 24 ------ msp/timeline.go | 31 ++++++++ msp/timeline_test.go | 169 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+), 25 deletions(-) create mode 100644 msp/timeline.go create mode 100644 msp/timeline_test.go diff --git a/main.go b/main.go index 084a405..4ccf759 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "bufio" "flag" "fmt" + "log" "os" "strings" "time" @@ -20,9 +21,11 @@ type Period struct { func (p Period) GetEndTime() time.Time { return p.EndTime } + func (p Period) GetStartTime() time.Time { return p.StartTime } + func (p Period) GetIdentifier() string { return p.Identifier } @@ -33,13 +36,18 @@ func init() { flag.PrintDefaults() } } + func warnMessage() { fmt.Print("Please type your date formats as follows, hit return between each field (RFC 3339), and hit Control+D to signal you are complete: \nIdentifier: id\nStartTime: 2019-10-12T07:20:50.52Z\nEndTime: 2019-10-12T07:20:50.52Z\n") - } func main() { + help := flag.Bool("h", false, "displays help command") flag.Parse() + if *help { + fmt.Println("Help goes here") + os.Exit(0) + } terminal := false fi, _ := os.Stdin.Stat() if (fi.Mode() & os.ModeCharDevice) == 0 { @@ -107,4 +115,8 @@ func main() { fmt.Printf("\nThe MSP from the list was: ") } fmt.Printf("%s\n", m) + vals := msp.GenerateTimeline(periods...) + for _, val := range vals { + log.Print(val) + } } diff --git a/msp/changeover.go b/msp/changeover.go index 50d2a8a..24a735a 100644 --- a/msp/changeover.go +++ b/msp/changeover.go @@ -1,7 +1,6 @@ package msp import ( - "fmt" "sort" "time" ) @@ -59,26 +58,3 @@ func FlattenPeriods(periods ...Period) (ids []string) { } return } - -func GenerateTimeline(periods ...Period) (out []string) { - periodsByID := make(map[string]Period) - ids := FlattenPeriods(periods...) - for _, val := range periods { - id := val.GetIdentifier() - periodsByID[id] = val - } - start := periodsByID[ids[0]].GetStartTime() - for _, val := range ids { - next, err := GetNextChangeOver(start, periods...) - if err == nil { - if next.Equal(periodsByID[val].GetStartTime()) { - start = periodsByID[val].GetStartTime() - next = periodsByID[val].GetEndTime() - } - frame := fmt.Sprintf("%s\t%s\t%s\n", val, start, next) - out = append(out, frame) - start = next - } - } - return out -} diff --git a/msp/timeline.go b/msp/timeline.go new file mode 100644 index 0000000..e1286fe --- /dev/null +++ b/msp/timeline.go @@ -0,0 +1,31 @@ +package msp + +import "fmt" + +// Outputs a formatted timeline of periods +func GenerateTimeline(periods ...Period) (out []string) { + if len(periods) == 0 { + out = []string{} + return out + } + periodsByID := make(map[string]Period) + ids := FlattenPeriods(periods...) + for _, val := range periods { + id := val.GetIdentifier() + periodsByID[id] = val + } + start := periodsByID[ids[0]].GetStartTime() + for _, val := range ids { + next, err := GetNextChangeOver(start, periods...) + if err == nil { + if next.Equal(periodsByID[val].GetStartTime()) { + start = periodsByID[val].GetStartTime() + next = periodsByID[val].GetEndTime() + } + frame := fmt.Sprintf("%s\t%s\t%s\n", val, start, next) + out = append(out, frame) + start = next + } + } + return out +} diff --git a/msp/timeline_test.go b/msp/timeline_test.go new file mode 100644 index 0000000..fd68b54 --- /dev/null +++ b/msp/timeline_test.go @@ -0,0 +1,169 @@ +package msp + +import ( + "fmt" + "testing" + "time" +) + +// (periods ...Period) (id string, err error) { +func TestGenerateTime(t *testing.T) { + now := time.Now() + testCases := []struct { + ts time.Time + testID string + result []string + periods []Period + }{ + { + testID: "No choices", + ts: now, + result: []string{}, + periods: []Period{}, + }, + { + testID: "Two Choices, shorter is second", + ts: now, + result: []string{ + fmt.Sprintf("A\t%s\t%s\n", now.Add(-5*time.Minute), now.Add(-2*time.Minute)), + fmt.Sprintf("B\t%s\t%s\n", now.Add(-2*time.Minute), now.Add(time.Minute)), + }, + periods: []Period{ + TimeWindow{ + StartTime: now.Add(-5 * time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "A", + }, + TimeWindow{ + StartTime: now.Add(-2 * time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "B", + }, + }, + }, + { + testID: "Two Choices, one is a year, other a minute", + ts: now, + result: []string{ + fmt.Sprintf("A\t%s\t%s\n", now.Add(-1*time.Hour*24*365), now.Add(-5*time.Minute)), + fmt.Sprintf("B\t%s\t%s\n", now.Add(-5*time.Minute), now.Add(time.Minute)), + }, + periods: []Period{ + TimeWindow{ + StartTime: now.Add(-1 * time.Hour * 24 * 365), + EndTime: now.Add(time.Minute), + Identifier: "A", + }, + TimeWindow{ + StartTime: now.Add(-5 * time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "B", + }, + }, + }, + { + testID: "Two Choices, shorter is first", + ts: now, + result: []string{ + fmt.Sprintf("B\t%s\t%s\n", now.Add(-5*time.Minute), now.Add(-2*time.Minute)), + fmt.Sprintf("A\t%s\t%s\n", now.Add(-2*time.Minute), now.Add(time.Minute)), + }, + periods: []Period{ + TimeWindow{ + StartTime: now.Add(-2 * time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "A", + }, + TimeWindow{ + StartTime: now.Add(-5 * time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "B", + }, + }, + }, + { + testID: "Two Choices, one in the past", + ts: now, + result: []string{ + fmt.Sprintf("B\t%s\t%s\n", now.Add(-2*time.Minute), now.Add(-time.Minute)), + fmt.Sprintf("A\t%s\t%s\n", now.Add(-time.Minute), now.Add(time.Minute)), + }, + periods: []Period{ + TimeWindow{ + StartTime: now.Add(-time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "A", + }, + TimeWindow{ + StartTime: now.Add(-2 * time.Minute), + EndTime: now.Add(-time.Minute), + Identifier: "B", + }, + }, + }, + { + testID: "Two Choices, one invalid", + ts: now, + result: []string{ + fmt.Sprintf("B\t%s\t%s\n", now.Add(-2*time.Minute), now.Add(time.Minute)), + }, + periods: []Period{ + TimeWindow{ + StartTime: now.Add(time.Minute), + EndTime: now.Add(-time.Minute), + Identifier: "A", + }, + TimeWindow{ + StartTime: now.Add(-2 * time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "B", + }, + }, + }, + { + testID: "Two Choices, Identical periods", + ts: now, + result: []string{ + fmt.Sprintf("B\t%s\t%s\n", now.Add(-time.Minute), now.Add(time.Minute)), + }, + periods: []Period{ + TimeWindow{ + StartTime: now.Add(-time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "A", + }, + TimeWindow{ + StartTime: now.Add(-time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "B", + }, + }, + }, + { + testID: "One choice", + ts: now, + result: []string{ + fmt.Sprintf("A\t%s\t%s\n", now.Add(-time.Minute), now.Add(time.Minute)), + }, + periods: []Period{TimeWindow{ + StartTime: now.Add(-time.Minute), + EndTime: now.Add(time.Minute), + Identifier: "A", + }}, + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("%s", tc.testID), func(t *testing.T) { + timeline := GenerateTimeline(tc.periods...) + if len(timeline) != len(tc.result) { + t.Fatalf("Time line had %d results, expected %d", len(timeline), len(tc.result)) + } + for idx, period := range timeline { + if period != tc.result[idx] { + t.Errorf("Expected:\t%s\t\tHad:\t%s", period, tc.result[idx]) + } + } + }) + } +} From a2c1864a77eccc69cc3618bdd2d2602d7ea45650 Mon Sep 17 00:00:00 2001 From: Ethan Holz Date: Fri, 14 Oct 2022 14:19:43 -0500 Subject: [PATCH 3/3] fix: Removed logging from main.go --- main.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/main.go b/main.go index 4ccf759..155a941 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,6 @@ import ( "bufio" "flag" "fmt" - "log" "os" "strings" "time" @@ -117,6 +116,6 @@ func main() { fmt.Printf("%s\n", m) vals := msp.GenerateTimeline(periods...) for _, val := range vals { - log.Print(val) + fmt.Println(val) } }