mirror of
https://github.com/taigrr/most-specific-period.git
synced 2026-04-02 03:38:41 -07:00
Uses an interface instead of a struct now
This commit is contained in:
27
main.go
27
main.go
@@ -11,6 +11,22 @@ import (
|
|||||||
"github.com/taigrr/most-specific-period/msp"
|
"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() {
|
func init() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
|
||||||
@@ -41,7 +57,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
periods := []msp.Period{}
|
periods := []msp.Period{}
|
||||||
|
currentPeriod := Period{}
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
input := s.Text()
|
input := s.Text()
|
||||||
input = strings.TrimSpace(input)
|
input = strings.TrimSpace(input)
|
||||||
@@ -54,14 +70,15 @@ func main() {
|
|||||||
fmt.Printf("ERROR: Invalid timestamp: %v", t)
|
fmt.Printf("ERROR: Invalid timestamp: %v", t)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
periods[(count-1)/3].EndTime = t
|
currentPeriod.EndTime = t
|
||||||
|
|
||||||
|
periods = append(periods, currentPeriod)
|
||||||
if terminal {
|
if terminal {
|
||||||
fmt.Print("Identifier: ")
|
fmt.Print("Identifier: ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if count%3 == 1 {
|
if count%3 == 1 {
|
||||||
periods = append(periods, msp.Period{Identifier: s.Text()})
|
currentPeriod = Period{Identifier: s.Text()}
|
||||||
if terminal {
|
if terminal {
|
||||||
fmt.Print("StartTime: ")
|
fmt.Print("StartTime: ")
|
||||||
}
|
}
|
||||||
@@ -72,7 +89,7 @@ func main() {
|
|||||||
fmt.Printf("ERROR: Invalid timestamp: %v", t)
|
fmt.Printf("ERROR: Invalid timestamp: %v", t)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
periods[(count-1)/3].StartTime = t
|
currentPeriod.StartTime = t
|
||||||
|
|
||||||
if terminal {
|
if terminal {
|
||||||
fmt.Print("EndTime: ")
|
fmt.Print("EndTime: ")
|
||||||
@@ -87,7 +104,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if terminal {
|
if terminal {
|
||||||
fmt.Printf("The MSP from the list was: ")
|
fmt.Printf("\nThe MSP from the list was: ")
|
||||||
}
|
}
|
||||||
fmt.Printf("%s\n", m)
|
fmt.Printf("%s\n", m)
|
||||||
}
|
}
|
||||||
|
|||||||
18
msp/msp.go
18
msp/msp.go
@@ -12,9 +12,9 @@ func MostSpecificPeriod(ts time.Time, periods ...Period) (id string, err error)
|
|||||||
return "", ErrNoValidPeriods
|
return "", ErrNoValidPeriods
|
||||||
}
|
}
|
||||||
// find the shortest duration
|
// 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 {
|
for _, x := range periods {
|
||||||
p, err := GetDuration(x.StartTime, x.EndTime)
|
p, err := GetDuration(x.GetStartTime(), x.GetEndTime())
|
||||||
if err == nil && p < d {
|
if err == nil && p < d {
|
||||||
d = p
|
d = p
|
||||||
}
|
}
|
||||||
@@ -22,29 +22,29 @@ func MostSpecificPeriod(ts time.Time, periods ...Period) (id string, err error)
|
|||||||
// find all periods with this shortest duration
|
// find all periods with this shortest duration
|
||||||
var matchingDurations []Period
|
var matchingDurations []Period
|
||||||
for _, x := range periods {
|
for _, x := range periods {
|
||||||
p, err := GetDuration(x.StartTime, x.EndTime)
|
p, err := GetDuration(x.GetStartTime(), x.GetEndTime())
|
||||||
if err == nil && p == d {
|
if err == nil && p == d {
|
||||||
matchingDurations = append(matchingDurations, x)
|
matchingDurations = append(matchingDurations, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Find the newest time a period starts
|
// Find the newest time a period starts
|
||||||
newest := matchingDurations[0].StartTime
|
newest := matchingDurations[0].GetStartTime()
|
||||||
for _, x := range matchingDurations {
|
for _, x := range matchingDurations {
|
||||||
if x.StartTime.After(newest) {
|
if x.GetStartTime().After(newest) {
|
||||||
newest = x.StartTime
|
newest = x.GetStartTime()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Determine whichever of these periods have the same start time in addtion to duration
|
// Determine whichever of these periods have the same start time in addtion to duration
|
||||||
var matchingDurationsAndStartTimes []Period
|
var matchingDurationsAndStartTimes []Period
|
||||||
for _, x := range matchingDurations {
|
for _, x := range matchingDurations {
|
||||||
if x.StartTime == newest {
|
if x.GetStartTime() == newest {
|
||||||
matchingDurationsAndStartTimes = append(matchingDurationsAndStartTimes, x)
|
matchingDurationsAndStartTimes = append(matchingDurationsAndStartTimes, x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finally, return the period with the 'last' name lexicographically
|
// Finally, return the period with the 'last' name lexicographically
|
||||||
var identifiers []string
|
var identifiers []string
|
||||||
for _, x := range matchingDurationsAndStartTimes {
|
for _, x := range matchingDurationsAndStartTimes {
|
||||||
identifiers = append(identifiers, x.Identifier)
|
identifiers = append(identifiers, x.GetIdentifier())
|
||||||
}
|
}
|
||||||
sort.Strings(identifiers)
|
sort.Strings(identifiers)
|
||||||
return identifiers[len(identifiers)-1], nil
|
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 {
|
func ValidTimePeriods(ts time.Time, periods ...Period) []Period {
|
||||||
var valid []Period
|
var valid []Period
|
||||||
for _, p := range periods {
|
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)
|
valid = append(valid, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,22 @@ import (
|
|||||||
"time"
|
"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) {
|
//(periods ...Period) (id string, err error) {
|
||||||
func TestMostSpecificPeriod(t *testing.T) {
|
func TestMostSpecificPeriod(t *testing.T) {
|
||||||
// use a static timestamp to make sure tests don't fail on slower systems or during a process pause
|
// 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,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{{StartTime: now.Add(-5 * time.Minute),
|
periods: []Period{TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"},
|
Identifier: "A"},
|
||||||
{StartTime: now.Add(-2 * time.Minute),
|
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B"}}},
|
||||||
{testID: "Two Choices, one is a year, other a minute",
|
{testID: "Two Choices, one is a year, other a minute",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
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),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"},
|
Identifier: "A"},
|
||||||
{StartTime: now.Add(-5 * time.Minute),
|
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B"}}},
|
||||||
|
|
||||||
@@ -46,47 +62,47 @@ func TestMostSpecificPeriod(t *testing.T) {
|
|||||||
ts: now,
|
ts: now,
|
||||||
result: "A",
|
result: "A",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{{StartTime: now.Add(-2 * time.Minute),
|
periods: []Period{TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"},
|
Identifier: "A"},
|
||||||
{StartTime: now.Add(-5 * time.Minute),
|
TimeWindow{StartTime: now.Add(-5 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B"}}},
|
||||||
{testID: "Two Choices, one in the past",
|
{testID: "Two Choices, one in the past",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "A",
|
result: "A",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"},
|
Identifier: "A"},
|
||||||
{StartTime: now.Add(-2 * time.Minute),
|
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(-time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B"}}},
|
||||||
{testID: "Two Choices, one invalid",
|
{testID: "Two Choices, one invalid",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{{StartTime: now.Add(time.Minute),
|
periods: []Period{TimeWindow{StartTime: now.Add(time.Minute),
|
||||||
EndTime: now.Add(-time.Minute),
|
EndTime: now.Add(-time.Minute),
|
||||||
Identifier: "A"},
|
Identifier: "A"},
|
||||||
{StartTime: now.Add(-2 * time.Minute),
|
TimeWindow{StartTime: now.Add(-2 * time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B"}}},
|
||||||
{testID: "Two Choices, Identical periods",
|
{testID: "Two Choices, Identical periods",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "B",
|
result: "B",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"},
|
Identifier: "A"},
|
||||||
{StartTime: now.Add(-time.Minute),
|
TimeWindow{StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "B"}}},
|
Identifier: "B"}}},
|
||||||
{testID: "One choice",
|
{testID: "One choice",
|
||||||
ts: now,
|
ts: now,
|
||||||
result: "A",
|
result: "A",
|
||||||
err: nil,
|
err: nil,
|
||||||
periods: []Period{{StartTime: now.Add(-time.Minute),
|
periods: []Period{TimeWindow{StartTime: now.Add(-time.Minute),
|
||||||
EndTime: now.Add(time.Minute),
|
EndTime: now.Add(time.Minute),
|
||||||
Identifier: "A"}}}}
|
Identifier: "A"}}}}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package msp
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Period struct {
|
type Period interface {
|
||||||
StartTime time.Time `json:"startTime"`
|
GetStartTime() time.Time
|
||||||
EndTime time.Time `json:"endTime"`
|
GetEndTime() time.Time
|
||||||
Identifier string `json:"identifier"`
|
GetIdentifier() string
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user