Merge pull request #1 from ethanholz/generate-timeline

Added functionality to generate timeline and preliminary support for help function
This commit is contained in:
2022-10-14 13:11:04 -07:00
committed by GitHub
3 changed files with 212 additions and 1 deletions

13
main.go
View File

@@ -20,9 +20,11 @@ type Period struct {
func (p Period) GetEndTime() time.Time { func (p Period) GetEndTime() time.Time {
return p.EndTime return p.EndTime
} }
func (p Period) GetStartTime() time.Time { func (p Period) GetStartTime() time.Time {
return p.StartTime return p.StartTime
} }
func (p Period) GetIdentifier() string { func (p Period) GetIdentifier() string {
return p.Identifier return p.Identifier
} }
@@ -33,13 +35,18 @@ func init() {
flag.PrintDefaults() flag.PrintDefaults()
} }
} }
func warnMessage() { 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") 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() { func main() {
help := flag.Bool("h", false, "displays help command")
flag.Parse() flag.Parse()
if *help {
fmt.Println("Help goes here")
os.Exit(0)
}
terminal := false terminal := false
fi, _ := os.Stdin.Stat() fi, _ := os.Stdin.Stat()
if (fi.Mode() & os.ModeCharDevice) == 0 { if (fi.Mode() & os.ModeCharDevice) == 0 {
@@ -107,4 +114,8 @@ func main() {
fmt.Printf("\nThe MSP from the list was: ") fmt.Printf("\nThe MSP from the list was: ")
} }
fmt.Printf("%s\n", m) fmt.Printf("%s\n", m)
vals := msp.GenerateTimeline(periods...)
for _, val := range vals {
fmt.Println(val)
}
} }

31
msp/timeline.go Normal file
View File

@@ -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
}

169
msp/timeline_test.go Normal file
View File

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