Uses an interface instead of a struct now

This commit is contained in:
2022-03-07 16:46:17 -08:00
parent ca6ba89bce
commit 14aa89a047
4 changed files with 64 additions and 31 deletions

27
main.go
View File

@@ -11,6 +11,22 @@ import (
"github.com/taigrr/most-specific-period/msp"
)
type Period struct {
EndTime time.Time
StartTime time.Time
Identifier string
}
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
}
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
@@ -41,7 +57,7 @@ func main() {
}
periods := []msp.Period{}
currentPeriod := Period{}
for s.Scan() {
input := s.Text()
input = strings.TrimSpace(input)
@@ -54,14 +70,15 @@ func main() {
fmt.Printf("ERROR: Invalid timestamp: %v", t)
os.Exit(1)
}
periods[(count-1)/3].EndTime = t
currentPeriod.EndTime = t
periods = append(periods, currentPeriod)
if terminal {
fmt.Print("Identifier: ")
}
}
if count%3 == 1 {
periods = append(periods, msp.Period{Identifier: s.Text()})
currentPeriod = Period{Identifier: s.Text()}
if terminal {
fmt.Print("StartTime: ")
}
@@ -72,7 +89,7 @@ func main() {
fmt.Printf("ERROR: Invalid timestamp: %v", t)
os.Exit(1)
}
periods[(count-1)/3].StartTime = t
currentPeriod.StartTime = t
if terminal {
fmt.Print("EndTime: ")
@@ -87,7 +104,7 @@ func main() {
os.Exit(1)
}
if terminal {
fmt.Printf("The MSP from the list was: ")
fmt.Printf("\nThe MSP from the list was: ")
}
fmt.Printf("%s\n", m)
}

View File

@@ -12,9 +12,9 @@ func MostSpecificPeriod(ts time.Time, periods ...Period) (id string, err error)
return "", ErrNoValidPeriods
}
// find the shortest duration
d, err := GetDuration(periods[0].StartTime, periods[0].EndTime)
d, err := GetDuration(periods[0].GetStartTime(), periods[0].GetEndTime())
for _, x := range periods {
p, err := GetDuration(x.StartTime, x.EndTime)
p, err := GetDuration(x.GetStartTime(), x.GetEndTime())
if err == nil && p < d {
d = p
}
@@ -22,29 +22,29 @@ func MostSpecificPeriod(ts time.Time, periods ...Period) (id string, err error)
// find all periods with this shortest duration
var matchingDurations []Period
for _, x := range periods {
p, err := GetDuration(x.StartTime, x.EndTime)
p, err := GetDuration(x.GetStartTime(), x.GetEndTime())
if err == nil && p == d {
matchingDurations = append(matchingDurations, x)
}
}
// Find the newest time a period starts
newest := matchingDurations[0].StartTime
newest := matchingDurations[0].GetStartTime()
for _, x := range matchingDurations {
if x.StartTime.After(newest) {
newest = x.StartTime
if x.GetStartTime().After(newest) {
newest = x.GetStartTime()
}
}
// Determine whichever of these periods have the same start time in addtion to duration
var matchingDurationsAndStartTimes []Period
for _, x := range matchingDurations {
if x.StartTime == newest {
if x.GetStartTime() == newest {
matchingDurationsAndStartTimes = append(matchingDurationsAndStartTimes, x)
}
}
// Finally, return the period with the 'last' name lexicographically
var identifiers []string
for _, x := range matchingDurationsAndStartTimes {
identifiers = append(identifiers, x.Identifier)
identifiers = append(identifiers, x.GetIdentifier())
}
sort.Strings(identifiers)
return identifiers[len(identifiers)-1], nil
@@ -61,7 +61,7 @@ func GetDuration(start time.Time, end time.Time) (dur time.Duration, err error)
func ValidTimePeriods(ts time.Time, periods ...Period) []Period {
var valid []Period
for _, p := range periods {
if p.StartTime.Before(ts) && p.EndTime.After(ts) {
if p.GetStartTime().Before(ts) && p.GetEndTime().After(ts) {
valid = append(valid, p)
}
}

View File

@@ -6,6 +6,22 @@ import (
"time"
)
type TimeWindow struct {
StartTime time.Time
EndTime time.Time
Identifier string
}
func (p TimeWindow) GetIdentifier() string {
return p.Identifier
}
func (p TimeWindow) GetEndTime() time.Time {
return p.EndTime
}
func (p TimeWindow) GetStartTime() time.Time {
return p.StartTime
}
//(periods ...Period) (id string, err error) {
func TestMostSpecificPeriod(t *testing.T) {
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
@@ -25,20 +41,20 @@ func TestMostSpecificPeriod(t *testing.T) {
ts: now,
result: "B",
err: nil,
periods: []Period{{StartTime: now.Add(-5 * time.Minute),
periods: []Period{TimeWindow{StartTime: now.Add(-5 * time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "A"},
{StartTime: now.Add(-2 * time.Minute),
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: "B",
err: nil,
periods: []Period{{StartTime: now.Add(-1 * time.Hour * 24 * 365),
periods: []Period{TimeWindow{StartTime: now.Add(-1 * time.Hour * 24 * 365),
EndTime: now.Add(time.Minute),
Identifier: "A"},
{StartTime: now.Add(-5 * time.Minute),
TimeWindow{StartTime: now.Add(-5 * time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "B"}}},
@@ -46,47 +62,47 @@ func TestMostSpecificPeriod(t *testing.T) {
ts: now,
result: "A",
err: nil,
periods: []Period{{StartTime: now.Add(-2 * time.Minute),
periods: []Period{TimeWindow{StartTime: now.Add(-2 * time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "A"},
{StartTime: now.Add(-5 * time.Minute),
TimeWindow{StartTime: now.Add(-5 * time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "B"}}},
{testID: "Two Choices, one in the past",
ts: now,
result: "A",
err: nil,
periods: []Period{{StartTime: now.Add(-time.Minute),
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "A"},
{StartTime: now.Add(-2 * time.Minute),
TimeWindow{StartTime: now.Add(-2 * time.Minute),
EndTime: now.Add(-time.Minute),
Identifier: "B"}}},
{testID: "Two Choices, one invalid",
ts: now,
result: "B",
err: nil,
periods: []Period{{StartTime: now.Add(time.Minute),
periods: []Period{TimeWindow{StartTime: now.Add(time.Minute),
EndTime: now.Add(-time.Minute),
Identifier: "A"},
{StartTime: now.Add(-2 * time.Minute),
TimeWindow{StartTime: now.Add(-2 * time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "B"}}},
{testID: "Two Choices, Identical periods",
ts: now,
result: "B",
err: nil,
periods: []Period{{StartTime: now.Add(-time.Minute),
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "A"},
{StartTime: now.Add(-time.Minute),
TimeWindow{StartTime: now.Add(-time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "B"}}},
{testID: "One choice",
ts: now,
result: "A",
err: nil,
periods: []Period{{StartTime: now.Add(-time.Minute),
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
EndTime: now.Add(time.Minute),
Identifier: "A"}}}}
for _, tc := range testCases {

View File

@@ -2,8 +2,8 @@ package msp
import "time"
type Period struct {
StartTime time.Time `json:"startTime"`
EndTime time.Time `json:"endTime"`
Identifier string `json:"identifier"`
type Period interface {
GetStartTime() time.Time
GetEndTime() time.Time
GetIdentifier() string
}