Added self adjustment minLow and maxHigh values. Renamed Get method to GetIntervals. Removed Report method, moved functionality to the Intervals Springer implementation. Added GetMinLow and GetMaxHigh methods.

This commit is contained in:
Daniel Gil 2018-06-01 10:46:19 +02:00
parent 1d6fd664fa
commit 217eb78ab4
11 changed files with 504 additions and 132 deletions

20
add.go
View File

@ -1,5 +1,7 @@
package interval package interval
import "math"
func (intvls *intervals) Add(low, high int, obj interface{}) error { func (intvls *intervals) Add(low, high int, obj interface{}) error {
itvl := &Interval{ itvl := &Interval{
Low: low, Low: low,
@ -10,6 +12,17 @@ func (intvls *intervals) Add(low, high int, obj interface{}) error {
} }
func (intvls *intervals) AddInterval(itvl *Interval) error { func (intvls *intervals) AddInterval(itvl *Interval) error {
// the first time an interval is added, we check if a self adjustment is programmed to update some control variables
if len(intvls.Intervals) == 0 {
if intvls.SelfAdjustMinLow {
intvls.MinLow = math.MaxInt64
}
if intvls.SelfAdjustMaxHigh {
intvls.MaxHigh = math.MinInt64
}
}
low := intvls.getInclusiveLow(itvl.Low) low := intvls.getInclusiveLow(itvl.Low)
high := intvls.getInclusiveHigh(itvl.High) high := intvls.getInclusiveHigh(itvl.High)
@ -18,6 +31,13 @@ func (intvls *intervals) AddInterval(itvl *Interval) error {
return err return err
} }
if intvls.SelfAdjustMaxHigh && high > intvls.MaxHigh {
intvls.MaxHigh = high
}
if intvls.SelfAdjustMinLow && low < intvls.MinLow {
intvls.MinLow = low
}
intvls.Intervals = append(intvls.Intervals, itvl) intvls.Intervals = append(intvls.Intervals, itvl)
intvls.reset() intvls.reset()
return nil return nil

File diff suppressed because it is too large Load Diff

View File

@ -91,7 +91,14 @@ func readData(path string) ([]xy, error) {
} }
func initIntervals(xys []xy) interval.Intervals { func initIntervals(xys []xy) interval.Intervals {
intervals := interval.NewIntervals(MinX, MaxX, true, true) // initialize Intervals
minLow := MinX
maxHigh := MaxX
lowInclusive = true
highInclusive = true
selfAdjustMinLow := false
selfAdjustMaxHigh := true
intervals := interval.NewIntervals(minLow, maxHigh, lowInclusive, highInclusive, selfAdjustMinLow, selfAdjustMaxHigh)
if intervals.IsLowInclusive() { if intervals.IsLowInclusive() {
intervalOpening = "[" intervalOpening = "["
@ -110,7 +117,7 @@ func initIntervals(xys []xy) interval.Intervals {
} }
for _, xy := range xys { for _, xy := range xys {
err := intervals.Add(&interval.Interval{Low: xy.x, High: xy.y}) err := intervals.AddInterval(&interval.Interval{Low: xy.x, High: xy.y})
if err != nil { if err != nil {
fmt.Printf("invalid interval discarded: %v\n", err) fmt.Printf("invalid interval discarded: %v\n", err)
} }
@ -127,7 +134,7 @@ func convertToPlotterXYs(intervals []*interval.Interval) plotter.XYs {
return pxys return pxys
} }
func alignPlots(plotItems []*Superplot) *vgimg.Canvas { func alignPlots(plotItems []*Superplot, minLow, maxHigh int) *vgimg.Canvas {
rows, cols := len(plotItems), 1 rows, cols := len(plotItems), 1
plots := make([][]*plot.Plot, rows) plots := make([][]*plot.Plot, rows)
for j := 0; j < rows; j++ { for j := 0; j < rows; j++ {
@ -136,8 +143,8 @@ func alignPlots(plotItems []*Superplot) *vgimg.Canvas {
p := plotItems[j] p := plotItems[j]
// make sure the horizontal scales match // make sure the horizontal scales match
p.Plot.X.Min = MinX p.Plot.X.Min = float64(minLow) // MinX
p.Plot.X.Max = MaxX p.Plot.X.Max = float64(maxHigh) //MaxX
plots[j][i] = p.Plot plots[j][i] = p.Plot
} }
@ -232,7 +239,7 @@ func plotData(path string, intervals interval.Intervals) error {
plots = append(plots, p4) plots = append(plots, p4)
// join all plots, align them // join all plots, align them
canvas := alignPlots(plots) canvas := alignPlots(plots, intervals.GetMinLow(), intervals.GetMaxHigh())
err = createFileFromCanvas("out.png", canvas) err = createFileFromCanvas("out.png", canvas)
if err != nil { if err != nil {
return err return err

View File

@ -13,7 +13,9 @@ func initIntervalsForDemo001() interval.Intervals {
maxHigh := 100 maxHigh := 100
lowInclusive := true lowInclusive := true
highInclusive := true highInclusive := true
itvls := interval.NewIntervals(minLow, maxHigh, lowInclusive, highInclusive) selfAdjustMinLow := false
selfAdjustMaxHigh := true
itvls := interval.NewIntervals(minLow, maxHigh, lowInclusive, highInclusive, selfAdjustMinLow, selfAdjustMaxHigh)
// add new intervals // add new intervals
if err := itvls.AddInterval(&interval.Interval{Low: 5, High: 7}); err != nil { if err := itvls.AddInterval(&interval.Interval{Low: 5, High: 7}); err != nil {

View File

@ -20,6 +20,9 @@ func TestGaps(t *testing.T) {
demo010 := buildIntervalsDemo010() demo010 := buildIntervalsDemo010()
demo011 := buildIntervalsDemo011() demo011 := buildIntervalsDemo011()
demo012 := buildIntervalsDemo012() demo012 := buildIntervalsDemo012()
demo013 := buildIntervalsDemo013()
demo014 := buildIntervalsDemo014()
demo015 := buildIntervalsDemo015()
// tests for low/high exclusive // tests for low/high exclusive
demo101 := buildIntervalsDemo101() demo101 := buildIntervalsDemo101()
@ -79,6 +82,9 @@ func TestGaps(t *testing.T) {
{name: "demo010", intvls: demo010.Intervals, expectedGaps: demo010.ExpectedGaps}, {name: "demo010", intvls: demo010.Intervals, expectedGaps: demo010.ExpectedGaps},
{name: "demo011", intvls: demo011.Intervals, expectedGaps: demo011.ExpectedGaps}, {name: "demo011", intvls: demo011.Intervals, expectedGaps: demo011.ExpectedGaps},
{name: "demo012", intvls: demo012.Intervals, expectedGaps: demo012.ExpectedGaps}, {name: "demo012", intvls: demo012.Intervals, expectedGaps: demo012.ExpectedGaps},
{name: "demo013", intvls: demo013.Intervals, expectedGaps: demo013.ExpectedGaps},
{name: "demo014", intvls: demo014.Intervals, expectedGaps: demo014.ExpectedGaps},
{name: "demo015", intvls: demo015.Intervals, expectedGaps: demo015.ExpectedGaps},
{name: "demo101", intvls: demo101.Intervals, expectedGaps: demo101.ExpectedGaps}, {name: "demo101", intvls: demo101.Intervals, expectedGaps: demo101.ExpectedGaps},
{name: "demo102", intvls: demo102.Intervals, expectedGaps: demo102.ExpectedGaps}, {name: "demo102", intvls: demo102.Intervals, expectedGaps: demo102.ExpectedGaps},
@ -122,6 +128,9 @@ func TestGaps(t *testing.T) {
for _, tc := range tt { for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
// if tc.name == "demo014" {
// fmt.Printf("stop point")
// }
gaps := tc.intvls.Gaps() gaps := tc.intvls.Gaps()
unexpectedLength := false unexpectedLength := false
if len(gaps) != len(tc.expectedGaps) { if len(gaps) != len(tc.expectedGaps) {

2
get.go
View File

@ -1,6 +1,6 @@
package interval package interval
func (intvls *intervals) Get() []*Interval { func (intvls *intervals) GetIntervals() []*Interval {
// sort intervals (if necessary) // sort intervals (if necessary)
intvls.Sort() intvls.Sort()

View File

@ -5,10 +5,12 @@ import (
) )
const ( const (
defaultMinLow = 0 defaultMinLow = 0
defaultMaxHigh = math.MaxInt64 defaultMaxHigh = math.MaxInt64
defaultLowInclusive = true defaultLowInclusive = true
defaultHighInclusive = true defaultHighInclusive = true
defaultSelfAdjustMinLow = false
defaultSelfAdjustMaxHigh = true
) )
// Intervals is an interface to handle Interval structures discovering the existence of gaps or overlays // Intervals is an interface to handle Interval structures discovering the existence of gaps or overlays
@ -26,7 +28,7 @@ type Intervals interface {
HasGaps() bool HasGaps() bool
// Get returns the interval list // Get returns the interval list
Get() []*Interval GetIntervals() []*Interval
// Gaps returns the interval gaps // Gaps returns the interval gaps
Gaps() []*Interval Gaps() []*Interval
@ -43,43 +45,55 @@ type Intervals interface {
// FindIntervalsForValue returns all the intervals which contains the passed value // FindIntervalsForValue returns all the intervals which contains the passed value
FindIntervalsForValue(value int) []*Interval FindIntervalsForValue(value int) []*Interval
// Report creates a report of the interval sequence
Report() string
// IsLowInclusive indicates if the Low part of the interval is included, e. g. (3,5) --> the 3 is included as part of the interval // IsLowInclusive indicates if the Low part of the interval is included, e. g. (3,5) --> the 3 is included as part of the interval
IsLowInclusive() bool IsLowInclusive() bool
// IsHighInclusive indicates if the High part of the interval is included, e. g. (3,5) --> the 5 is included as part of the interval // IsHighInclusive indicates if the High part of the interval is included, e. g. (3,5) --> the 5 is included as part of the interval
IsHighInclusive() bool IsHighInclusive() bool
// GetMinLow returns the minimal Low, either the one configured in the constructor, or the self-adjusted calculated if SelfAdjustMinLow=true
GetMinLow() int
// GetMaxHigh returns the maximal High, either the one configured in the constructor, or the self-adjusted calculated if SelfAdjustMaxHigh=true
GetMaxHigh() int
} }
// intervals implements Intervals interface // intervals implements Intervals interface
type intervals struct { type intervals struct {
Intervals []*Interval Intervals []*Interval
GapsList []*Interval GapsList []*Interval
OverlappedList []*Interval OverlappedList []*Interval
MergeList []*Interval MergeList []*Interval
MinLow int MinLow int
MaxHigh int MaxHigh int
Sorted bool Sorted bool
LowInclusive bool LowInclusive bool
HighInclusive bool HighInclusive bool
SelfAdjustMinLow bool // set the minLow to the minimal Low value passed in Add or AddInterval methods
SelfAdjustMaxHigh bool // set the maxHigh to the maximal High value passed in Add or AddInterval methods
}
// String implements Stringer.Interface Interval
func (itvls *intervals) String() string {
return itvls.report()
} }
// NewIntervalsDefault is a constructor that returns an instance of the Intervals interface with default values // NewIntervalsDefault is a constructor that returns an instance of the Intervals interface with default values
func NewIntervalsDefault() Intervals { func NewIntervalsDefault() Intervals {
return NewIntervals(defaultMinLow, defaultMaxHigh, defaultLowInclusive, defaultHighInclusive) return NewIntervals(defaultMinLow, defaultMaxHigh, defaultLowInclusive, defaultHighInclusive, defaultSelfAdjustMinLow, defaultSelfAdjustMaxHigh)
} }
// NewIntervals is a constructor that returns an instance of the Intervals interface // NewIntervals is a constructor that returns an instance of the Intervals interface
func NewIntervals(minLow int, maxHigh int, lowInclusive bool, highInclusive bool) Intervals { func NewIntervals(minLow, maxHigh int, lowInclusive, highInclusive, selfAdjustMinLow, selfAdjustMaxHigh bool) Intervals {
return &intervals{ return &intervals{
MinLow: minLow, MinLow: minLow,
MaxHigh: maxHigh, MaxHigh: maxHigh,
Intervals: []*Interval{}, Intervals: []*Interval{},
Sorted: false, Sorted: false,
LowInclusive: lowInclusive, LowInclusive: lowInclusive,
HighInclusive: highInclusive, HighInclusive: highInclusive,
SelfAdjustMinLow: selfAdjustMinLow,
SelfAdjustMaxHigh: selfAdjustMaxHigh,
} }
} }
@ -90,3 +104,11 @@ func (intvls *intervals) IsLowInclusive() bool {
func (intvls *intervals) IsHighInclusive() bool { func (intvls *intervals) IsHighInclusive() bool {
return intvls.HighInclusive return intvls.HighInclusive
} }
func (intvls *intervals) GetMinLow() int {
return intvls.MinLow
}
func (intvls *intervals) GetMaxHigh() int {
return intvls.MaxHigh
}

View File

@ -20,6 +20,9 @@ func TestMerge(t *testing.T) {
demo010 := buildIntervalsDemo010() demo010 := buildIntervalsDemo010()
demo011 := buildIntervalsDemo011() demo011 := buildIntervalsDemo011()
demo012 := buildIntervalsDemo012() demo012 := buildIntervalsDemo012()
demo013 := buildIntervalsDemo013()
demo014 := buildIntervalsDemo014()
demo015 := buildIntervalsDemo015()
// tests for low/high exclusive // tests for low/high exclusive
demo101 := buildIntervalsDemo101() demo101 := buildIntervalsDemo101()
@ -79,6 +82,9 @@ func TestMerge(t *testing.T) {
{name: "demo010", intvls: demo010.Intervals, expectedMerges: demo010.ExpectedMerges}, {name: "demo010", intvls: demo010.Intervals, expectedMerges: demo010.ExpectedMerges},
{name: "demo011", intvls: demo011.Intervals, expectedMerges: demo011.ExpectedMerges}, {name: "demo011", intvls: demo011.Intervals, expectedMerges: demo011.ExpectedMerges},
{name: "demo012", intvls: demo012.Intervals, expectedMerges: demo012.ExpectedMerges}, {name: "demo012", intvls: demo012.Intervals, expectedMerges: demo012.ExpectedMerges},
{name: "demo013", intvls: demo013.Intervals, expectedMerges: demo013.ExpectedMerges},
{name: "demo014", intvls: demo014.Intervals, expectedMerges: demo014.ExpectedMerges},
{name: "demo015", intvls: demo015.Intervals, expectedMerges: demo015.ExpectedMerges},
{name: "demo101", intvls: demo101.Intervals, expectedMerges: demo101.ExpectedMerges}, {name: "demo101", intvls: demo101.Intervals, expectedMerges: demo101.ExpectedMerges},
{name: "demo102", intvls: demo102.Intervals, expectedMerges: demo102.ExpectedMerges}, {name: "demo102", intvls: demo102.Intervals, expectedMerges: demo102.ExpectedMerges},

View File

@ -20,6 +20,9 @@ func TestOverlapped(t *testing.T) {
demo010 := buildIntervalsDemo010() demo010 := buildIntervalsDemo010()
demo011 := buildIntervalsDemo011() demo011 := buildIntervalsDemo011()
demo012 := buildIntervalsDemo012() demo012 := buildIntervalsDemo012()
demo013 := buildIntervalsDemo013()
demo014 := buildIntervalsDemo014()
demo015 := buildIntervalsDemo015()
// tests for low/high exclusive // tests for low/high exclusive
demo101 := buildIntervalsDemo101() demo101 := buildIntervalsDemo101()
@ -79,6 +82,9 @@ func TestOverlapped(t *testing.T) {
{name: "demo010", intvls: demo010.Intervals, expectedOverlaps: demo010.ExpectedOverlaps}, {name: "demo010", intvls: demo010.Intervals, expectedOverlaps: demo010.ExpectedOverlaps},
{name: "demo011", intvls: demo011.Intervals, expectedOverlaps: demo011.ExpectedOverlaps}, {name: "demo011", intvls: demo011.Intervals, expectedOverlaps: demo011.ExpectedOverlaps},
{name: "demo012", intvls: demo012.Intervals, expectedOverlaps: demo012.ExpectedOverlaps}, {name: "demo012", intvls: demo012.Intervals, expectedOverlaps: demo012.ExpectedOverlaps},
{name: "demo013", intvls: demo013.Intervals, expectedOverlaps: demo013.ExpectedOverlaps},
{name: "demo014", intvls: demo014.Intervals, expectedOverlaps: demo014.ExpectedOverlaps},
{name: "demo015", intvls: demo015.Intervals, expectedOverlaps: demo015.ExpectedOverlaps},
{name: "demo101", intvls: demo101.Intervals, expectedOverlaps: demo101.ExpectedOverlaps}, {name: "demo101", intvls: demo101.Intervals, expectedOverlaps: demo101.ExpectedOverlaps},
{name: "demo102", intvls: demo102.Intervals, expectedOverlaps: demo102.ExpectedOverlaps}, {name: "demo102", intvls: demo102.Intervals, expectedOverlaps: demo102.ExpectedOverlaps},

View File

@ -25,7 +25,7 @@ func newSymbols() symbols {
} }
} }
func (intvls *intervals) Report() string { func (intvls *intervals) report() string {
intvls.Sort() intvls.Sort()
symbols := newSymbols() symbols := newSymbols()
intro := intvls.buildHeading() intro := intvls.buildHeading()

View File

@ -8,7 +8,13 @@ import (
) )
func TestReport(t *testing.T) { func TestReport(t *testing.T) {
itvls := interval.NewIntervals(0, 100, true, true) minLow := 0
maxHigh := 100
lowInclusive := true
highInclusive := true
selfAdjustMinLow := false
selfAdjustMaxHigh := true
itvls := interval.NewIntervals(minLow, maxHigh, lowInclusive, highInclusive, selfAdjustMinLow, selfAdjustMaxHigh)
var err error var err error
err = itvls.AddInterval(&interval.Interval{Low: 5, High: 7}) err = itvls.AddInterval(&interval.Interval{Low: 5, High: 7})
@ -49,7 +55,8 @@ func TestReport(t *testing.T) {
for _, tc := range tt { for _, tc := range tt {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
t.Log(tc.itvls.Report()) // this will call report() which implements Springer interface
t.Log(tc.itvls)
}) })
} }
} }