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]) + } + } + }) + } +}