Skip to content

Commit

Permalink
automatically scale the score graph and use the rectengular form
Browse files Browse the repository at this point in the history
  • Loading branch information
ftl committed Jun 8, 2023
1 parent e7955bb commit 342befa
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 21 deletions.
25 changes: 25 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ func (s Score) StackedGraphPerBand() []BandGraph {
stackedGraph := BandGraph{
Band: graph.Band,
DataPoints: make([]BandScore, len(graph.DataPoints)),
Max: graph.Max,
startTime: graph.startTime,
binSeconds: graph.binSeconds,
}
Expand All @@ -507,6 +508,7 @@ func (s Score) StackedGraphPerBand() []BandGraph {
stackedGraph.DataPoints[i].Duplicates += lastDataPoints[i].Duplicates
stackedGraph.DataPoints[i].Points += lastDataPoints[i].Points
stackedGraph.DataPoints[i].Multis += lastDataPoints[i].Multis
stackedGraph.Max = stackedGraph.Max.Max(stackedGraph.DataPoints[i])
}
}

Expand All @@ -519,6 +521,7 @@ func (s Score) StackedGraphPerBand() []BandGraph {
type BandGraph struct {
Band Band
DataPoints []BandScore
Max BandScore

startTime time.Time
binSeconds float64
Expand All @@ -534,6 +537,7 @@ func NewBandGraph(band Band, startTime time.Time, duration time.Duration) BandGr
return BandGraph{
Band: band,
DataPoints: make([]BandScore, int(binCount)),
Max: BandScore{},

binSeconds: duration.Seconds() / float64(binCount),
startTime: startTime,
Expand All @@ -559,6 +563,8 @@ func (g *BandGraph) Add(timestamp time.Time, score QSOScore) {
bandScore := g.DataPoints[bindex]
bandScore.AddQSO(score)
g.DataPoints[bindex] = bandScore

g.Max = g.Max.Max(bandScore)
}

func (g *BandGraph) Bindex(timestamp time.Time) int {
Expand Down Expand Up @@ -625,6 +631,25 @@ func (s *BandScore) AddQSO(qso QSOScore) {
}
}

func (s BandScore) Max(other BandScore) BandScore {
result := s

if result.QSOs < other.QSOs {
result.QSOs = other.QSOs
}
if result.Duplicates < other.Duplicates {
result.Duplicates = other.Duplicates
}
if result.Points < other.Points {
result.Points = other.Points
}
if result.Multis < other.Multis {
result.Multis = other.Multis
}

return result
}

func (s BandScore) PointsPerQSO() float64 {
if s.QSOs == 0 {
return 0
Expand Down
93 changes: 72 additions & 21 deletions ui/scoreGraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ func (s *scoreGraphStyle) Refresh() {

type scoreGraph struct {
graphs []core.BandGraph
maxPoints int
maxMultis int
pointsGoal int
multisGoal int
timeFrameIndex int
Expand Down Expand Up @@ -70,6 +72,16 @@ func (g *scoreGraph) RefreshStyle() {

func (g *scoreGraph) SetGraphs(graphs []core.BandGraph) {
g.graphs = graphs
g.maxPoints = 0
g.maxMultis = 0
for _, graph := range graphs {
if g.maxPoints < graph.Max.Points {
g.maxPoints = graph.Max.Points
}
if g.maxMultis < graph.Max.Multis {
g.maxMultis = graph.Max.Multis
}
}
g.updateBinGoals()
g.UpdateTimeFrame()
}
Expand Down Expand Up @@ -99,13 +111,14 @@ func (g *scoreGraph) UpdateTimeFrame() {
}

type graphLayout struct {
width float64
height float64
marginY float64
zeroY float64
maxHeight float64
lowZoneHeight float64
binWidth float64
width float64
height float64
marginY float64
zeroY float64
maxHeight float64
pointsLowZoneHeight float64
multisLowZoneHeight float64
binWidth float64
}

func (g *scoreGraph) Draw(da *gtk.DrawingArea, cr *cairo.Context) {
Expand All @@ -125,18 +138,18 @@ func (g *scoreGraph) Draw(da *gtk.DrawingArea, cr *cairo.Context) {

// the zone
cr.SetSourceRGBA(g.style.lowZoneColor.WithAlpha(g.style.areaAlpha))
cr.MoveTo(0, layout.zeroY-layout.lowZoneHeight)
cr.LineTo(layout.width, layout.zeroY-layout.lowZoneHeight)
cr.LineTo(layout.width, layout.zeroY+layout.lowZoneHeight)
cr.LineTo(0, layout.zeroY+layout.lowZoneHeight)
cr.MoveTo(0, layout.zeroY-layout.pointsLowZoneHeight)
cr.LineTo(layout.width, layout.zeroY-layout.pointsLowZoneHeight)
cr.LineTo(layout.width, layout.zeroY+layout.multisLowZoneHeight)
cr.LineTo(0, layout.zeroY+layout.multisLowZoneHeight)
cr.ClosePath()
cr.Fill()

cr.SetSourceRGBA(g.style.lowZoneColor.WithAlpha(g.style.borderAlpha))
cr.MoveTo(0, layout.zeroY-layout.lowZoneHeight)
cr.LineTo(layout.width, layout.zeroY-layout.lowZoneHeight)
cr.LineTo(layout.width, layout.zeroY+layout.lowZoneHeight)
cr.LineTo(0, layout.zeroY+layout.lowZoneHeight)
cr.MoveTo(0, layout.zeroY-layout.pointsLowZoneHeight)
cr.LineTo(layout.width, layout.zeroY-layout.pointsLowZoneHeight)
cr.LineTo(layout.width, layout.zeroY+layout.multisLowZoneHeight)
cr.LineTo(0, layout.zeroY+layout.multisLowZoneHeight)
cr.ClosePath()
cr.Stroke()

Expand All @@ -146,14 +159,14 @@ func (g *scoreGraph) Draw(da *gtk.DrawingArea, cr *cairo.Context) {
color := bandColor(g.style, graph.Band)
cr.SetSourceRGB(color.ToRGB())

g.drawDataPoints(cr, layout, graph.DataPoints)
g.drawDataPointsRectangular(cr, layout, graph.DataPoints)
}

// the time frame
if g.timeFrameIndex >= 0 && valueCount > 1 {
startX := float64(g.timeFrameIndex) * layout.binWidth
endX := float64(g.timeFrameIndex+1) * layout.binWidth
cr.SetSourceRGBA(g.style.timeFrameColor.ToRGBA()) // TODO calculate the achievment of the current time frame and use the corresponding color
cr.SetSourceRGBA(g.style.timeFrameColor.ToRGBA())
cr.MoveTo(startX, layout.zeroY-layout.maxHeight)
cr.LineTo(endX, layout.zeroY-layout.maxHeight)
cr.LineTo(endX, layout.zeroY+layout.maxHeight)
Expand All @@ -178,7 +191,8 @@ func (g *scoreGraph) calculateLayout(da *gtk.DrawingArea, valueCount int) graphL

result.zeroY = result.height / 2.0
result.maxHeight = result.zeroY - result.marginY
result.lowZoneHeight = result.maxHeight / 2.0
result.pointsLowZoneHeight = math.Min(result.maxHeight/2.0, (result.maxHeight/float64(g.maxPoints))*g.pointsBinGoal)
result.multisLowZoneHeight = math.Min(result.maxHeight/2.0, (result.maxHeight/float64(g.maxMultis))*g.multisBinGoal)
result.binWidth = result.width / float64(valueCount)

return result
Expand All @@ -192,12 +206,49 @@ func (g *scoreGraph) fillBackground(cr *cairo.Context) {
cr.Paint()
}

func (g *scoreGraph) drawDataPoints(cr *cairo.Context, layout graphLayout, datapoints []core.BandScore) {
func (g *scoreGraph) drawDataPointsRectangular(cr *cairo.Context, layout graphLayout, datapoints []core.BandScore) {
valueCount := len(datapoints)

cr.MoveTo(0, layout.zeroY)

valueScaling := layout.pointsLowZoneHeight / g.pointsBinGoal
for i := 0; i < valueCount; i++ {
startX := float64(i) * layout.binWidth
endX := float64(i+1) * layout.binWidth
value := float64(datapoints[i].Points)
y := layout.zeroY - math.Min(value*valueScaling, layout.maxHeight)
cr.LineTo(startX, y)
cr.LineTo(endX, y)
if i == valueCount-1 {
cr.LineTo(endX, layout.zeroY)
}
}

valueScaling = layout.multisLowZoneHeight / g.multisBinGoal
for i := valueCount - 1; i >= 0; i-- {
startX := float64(i+1) * layout.binWidth
endX := float64(i) * layout.binWidth
value := float64(datapoints[i].Multis)
y := layout.zeroY + math.Min(value*valueScaling, layout.maxHeight)
cr.LineTo(startX, y)
cr.LineTo(endX, y)
if i == valueCount-1 {
cr.LineTo(endX, layout.zeroY)
}
if i == 0 {
cr.LineTo(endX, layout.zeroY)
}
}
cr.ClosePath()
cr.Fill()
}

func (g *scoreGraph) drawDataPointsCurved(cr *cairo.Context, layout graphLayout, datapoints []core.BandScore) {
valueCount := len(datapoints)

cr.MoveTo(0, layout.zeroY)

valueScaling := layout.lowZoneHeight / g.pointsBinGoal
valueScaling := layout.pointsLowZoneHeight / g.pointsBinGoal
lastY := layout.zeroY
for i := 0; i < valueCount; i++ {
startX := float64(i) * layout.binWidth
Expand All @@ -219,7 +270,7 @@ func (g *scoreGraph) drawDataPoints(cr *cairo.Context, layout graphLayout, datap
lastY = y
}

valueScaling = layout.lowZoneHeight / g.multisBinGoal
valueScaling = layout.multisLowZoneHeight / g.multisBinGoal
lastY = layout.zeroY
for i := valueCount - 1; i >= 0; i-- {
startX := float64(i+1) * layout.binWidth
Expand Down

0 comments on commit 342befa

Please sign in to comment.