Skip to content

Commit

Permalink
overlapping delays, NewSchedule refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
kneerunjun committed Dec 12, 2020
1 parent 101f299 commit 9525ebf
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 51 deletions.
26 changes: 24 additions & 2 deletions primarysched.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,26 @@ import (
type primarySched struct {
lower Trigger
higher Trigger
// whenever the schedule gets in a conflict the LHS induces increment in the RHS conflict
conflicts int
delay int // increasing this will increment the preceedence since this will be applied after a delay
}

func (ps *primarySched) Conflicts() int {
return ps.conflicts
}
func (ps *primarySched) AddConflict() Schedule {
ps.conflicts++
return ps
}
func (ps *primarySched) Delay() int {
return ps.delay
}
func (ps *primarySched) AddDelay(prior int) Schedule {
ps.delay = prior
ps.delay++
return ps
}
func (ps *primarySched) Triggers() (Trigger, Trigger) {
return ps.lower, ps.higher
}
Expand All @@ -29,7 +47,7 @@ func (ps *primarySched) Close() {
log.Infof("%s Schedule is now closing", ps)
}
func (ps *primarySched) String() string {
return fmt.Sprintf("%s - %s", tmStrFromUnixSecs(ps.lower.At()), tmStrFromUnixSecs(ps.higher.At()))
return fmt.Sprintf("%s - %s %v %v", tmStrFromUnixSecs(ps.lower.At()), tmStrFromUnixSecs(ps.higher.At()), ps.lower.RelayIDs(), ps.higher.RelayIDs())
}

// NearFarTrigger : in context of the current time, this helps to get the triggers that are near or far
Expand Down Expand Up @@ -72,9 +90,13 @@ func (ps *primarySched) overlapsWith(another Schedule) bool {
} else {
min, max = hfdur2, hfdur1
}
if (mdptdis > (hfdur1 + hfdur2)) || ((mdptdis + min) < max) {
if outside, inside := (mdptdis > (hfdur1 + hfdur2)), ((mdptdis + min) < max); outside || inside {
// case when the schedules are clearing and not interferring with one another
// either one schedule is inside the other or on one side
if inside {
// Here we would want to adjust the preceedence too.
another.AddDelay(ps.Delay())
}
return false
}
// all other cases the schedules are either partially/exactly overlapping
Expand Down
38 changes: 0 additions & 38 deletions rlystate.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package scheduling

import "fmt"

// RelayState : this is just to hold the state of relay with the identification of the relay
// relay should be identified with the same name as required by srvrelay
// Storing this as just a byte is also possible, but that is when we want the relay module to work as a block, not when we want to operate on individual relays
Expand Down Expand Up @@ -39,39 +37,3 @@ func (rs *RelayState) ID() string {
func NewRelayState(id string) *RelayState {
return &RelayState{byte(0), id}
}

// ================================== Json Relay state is for file reads ============================
// Making a relay state from a json file

// JSONRelayState : relaystate but in json format
type JSONRelayState struct {
ON string `json:"on"`
OFF string `json:"off"`
IDs []string `json:"ids"`
Primary bool `json:"primary"`
}

// ToSchedule : reads from json and pumps up a schedule
// this saves you the trouble of making a schedule via code,
// from a json file it can read up a relaystate and convert that to schedule
func (jrs *JSONRelayState) ToSchedule() (Schedule, error) {
onTm, err := TimeStr(jrs.ON).ToElapsedTm()
if err != nil {
return nil, fmt.Errorf("Failed to read ON time for schedule")
}
offTm, err := TimeStr(jrs.OFF).ToElapsedTm()
if err != nil {
return nil, fmt.Errorf("Failed to read OFF time for schedule")
}
offs := []*RelayState{}
ons := []*RelayState{}
for _, id := range jrs.IDs {
offs = append(offs, &RelayState{byte(0), id})
ons = append(ons, &RelayState{byte(1), id})
}
trg1, trg2 := NewTrg(offTm, offs...), NewTrg(onTm, ons...)
if jrs.Primary {
return NewPrimarySchedule(trg1, trg2)
}
return NewPatchSchedule(trg1, trg2)
}
26 changes: 25 additions & 1 deletion sch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ func TestScheduleRead(t *testing.T) {
return
}
t.Log("Now logging the JSONRelayState")
t.Log(c)
for _, s := range c.Schedules {
sched, err := s.ToSchedule()
if err != nil {
Expand All @@ -54,3 +53,28 @@ func TestScheduleRead(t *testing.T) {
t.Log(sched)
}
}

func TestScheduleNrFrTrigger(t *testing.T) {
jsonFile, _ := os.Open("test_sched.json")
// Reading bytes from the file and unmarshalling the same to struct values
bytes, _ := ioutil.ReadAll(jsonFile)
jsonFile.Close() // since this returns a closure, the call to this cannot be deferred
type conf struct {
Schedules []JSONRelayState `json:"schedules"`
}
c := conf{}
json.Unmarshal(bytes, &c)
for _, s := range c.Schedules {
sched, err := s.ToSchedule()
if err != nil {
t.Errorf("Error coverting to schedule objecy %s", err)
return
}
t.Logf("Schedule: %s", sched)
nr, fr, pre, post := sched.NearFarTrigger(elapsedSecondsNow())
t.Logf("Near trigger: %s", nr)
t.Logf("Far trigger: %s", fr)
t.Logf("Pre sleep: %d", pre)
t.Logf("Post sleep: %d", post)
}
}
56 changes: 48 additions & 8 deletions sched.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package scheduling

/*All the public facing interfaces here
Using this package from client code should be easy if you get your head around this file
*/

import (
"fmt"
)
Expand All @@ -11,6 +15,10 @@ type Schedule interface {
NearFarTrigger(elapsed int) (Trigger, Trigger, int, int)
ConflictsWith(another Schedule) bool
Midpoint() int
Delay() int
AddDelay(prior int) Schedule
Conflicts() int
AddConflict() Schedule
Close()
Apply(ok, cancel chan interface{}, send chan []byte, err chan error)
}
Expand All @@ -28,20 +36,52 @@ func sortTriggers(trg1, trg2 Trigger) (l, h Trigger, e error) {
return
}

// NewPrimarySchedule : makes a new TriggeredSchedul, will take 2 triggers
func NewPrimarySchedule(trg1, trg2 Trigger) (Schedule, error) {
// NewSchedule : makes a new TriggeredSchedul, will take 2 triggers
func NewSchedule(trg1, trg2 Trigger, primary bool) (Schedule, error) {
l, h, err := sortTriggers(trg1, trg2)
if err != nil {
return nil, err
}
return &primarySched{l, h}, nil
if !trg1.Intersects(trg2, true) || trg1.Coincides(trg2) {
// When triggers are paired in a schedule they have to be intersecting and not coincident
return nil, fmt.Errorf("%s-%s Triggers for the schedule are either not exactly intersecting or are coinciding", trg1, trg2)
}
if primary {
return &primarySched{l, h}, nil
}
return &patchSchedule{&primarySched{l, h}}, nil

}

// NewPatchSchedule : this makes a new patch schedule object
func NewPatchSchedule(trg1, trg2 Trigger) (Schedule, error) {
l, h, err := sortTriggers(trg1, trg2)
// JSONRelayState : relaystate but in json format
// ================================== Json Relay state is for file reads ============================
// Making a relay state from a json file
type JSONRelayState struct {
ON string `json:"on"`
OFF string `json:"off"`
IDs []string `json:"ids"`
Primary bool `json:"primary"`
}

// ToSchedule : reads from json and pumps up a schedule
// this saves you the trouble of making a schedule via code,
// from a json file it can read up a relaystate and convert that to schedule
func (jrs *JSONRelayState) ToSchedule() (Schedule, error) {
onTm, err := TimeStr(jrs.ON).ToElapsedTm()
if err != nil {
return nil, err
return nil, fmt.Errorf("Failed to read ON time for schedule")
}
return &patchSchedule{&primarySched{l, h}}, nil
offTm, err := TimeStr(jrs.OFF).ToElapsedTm()
if err != nil {
return nil, fmt.Errorf("Failed to read OFF time for schedule")
}
offs := []*RelayState{}
ons := []*RelayState{}
for _, id := range jrs.IDs {
offs = append(offs, &RelayState{byte(0), id})
ons = append(ons, &RelayState{byte(1), id})
}
trg1, trg2 := NewTrg(offTm, offs...), NewTrg(onTm, ons...)
return NewSchedule(trg1, trg2, jrs.Primary)

}
4 changes: 2 additions & 2 deletions test_sched.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
"schedules": [
{"on":"06:30 PM", "off":"06:30 AM","primary":true, "ids":["IN1","IN2","IN3","IN4"]},
{"on":"04:30 PM", "off":"05:29 PM","primary":false, "ids":["IN1"]},
{"on":"02:30 PM", "off":"04:00 PM","primary":false, "ids":["IN1"]},
{"on":"04:00 PM", "off":"04:45 PM","primary":false, "ids":["IN1"]},
{"on":"06:40 PM", "off":"08:40 PM","primary":false, "ids":["IN1"]},
{"on":"03:00 PM", "off":"04:45 PM","primary":false, "ids":["IN1"]},
{"on":"04:00 PM", "off":"04:45 PM","primary":false, "ids":["IN2"]}
]
}
4 changes: 4 additions & 0 deletions trg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package scheduling

import (
"encoding/json"
"fmt"
)

// rlyStateTrg : trigger is just a timestamp and collection of relay state
Expand All @@ -25,6 +26,9 @@ type Trigger interface {
Coincides(other Trigger) bool
}

func (tr *rlyStateTrg) String() string {
return fmt.Sprintf("%s, %v", tmStrFromUnixSecs(tr.at), tr.RelayIDs())
}
func (tr *rlyStateTrg) RelayIDs() ComparableSlice {
result := ComparableSlice{}
for _, item := range tr.rs {
Expand Down

0 comments on commit 9525ebf

Please sign in to comment.