Browse Source

Worked on stuff

master
Patrick Gaskin 2 years ago
parent
commit
022364ba45
Signed by: geek1011 GPG Key ID: A2FD79F68A2AB707
  1. 78
      main.go

78
main.go

@ -1,6 +1,7 @@
package main
import (
"errors"
"fmt"
"image"
"math"
@ -43,6 +44,77 @@ func main() {
fmt.Println(dateExtrapolator(4824)) // Nov 20, 2016
fmt.Println(dateExtrapolator(6418)) // Mar 30, 2017
fmt.Println(dateExtrapolator(14387)) // Jan 8, 2019
var curPrice float64
if err := traceLine(img, graphBounds, isLineColor, func(x, y int, isDotted bool) {
date, price := dateExtrapolator(x), priceExtrapolator(y)
if curPrice == price {
return
}
fmt.Println(date, price)
curPrice = price
}); err != nil {
panic(err)
}
}
// The following functions are calibrated for camelcamelcamel graphs with a plot
// size of 2, and marker lines of 1. The graph should also have a border enclosing
// the grid area. Dashed and dotted lines should have intervals of at most 2.
// traceLine traces the grid line.
func traceLine(img image.Image, graphBounds image.Rectangle, line colorMatcherFunc, cb func(x, y int, isDotted bool)) error {
curY := -1
for y := graphBounds.Min.Y; y < graphBounds.Max.Y-1; y++ {
if line(img.At(graphBounds.Min.X, y)) && line(img.At(graphBounds.Min.X, y+1)) {
curY = y
break
}
}
if curY == -1 {
return errors.New("could not find two pixel high line start at beginning of graph")
}
curX := graphBounds.Min.X
wasMovingVertically := false
for {
cb(curX, curY, false)
// Calculate directions can go in, ignore gap of 1px. TODO: dotted line.
for oldX, movingUp, movingDown := curX, false, false; oldX == curX; {
movingVertically := movingUp || movingDown
fmt.Println(curX, curY, wasMovingVertically)
// ?? <- can skip 1 if needed
// UU <- going up
// oRF <- going right
// .RF o is current position
// DD <- going down
// ?? <- can skip 1 if needed
// ^--- going far right
canGoUp := (line(img.At(curX, curY-1)) && line(img.At(curX+1, curY-1)) || line(img.At(curX, curY-2)) && line(img.At(curX+1, curY-2)))
canGoRight := line(img.At(curX+1, curY)) && line(img.At(curX+1, curY+1))
canGoFarRight := line(img.At(curX+2, curY)) && line(img.At(curX+2, curY+1))
canGoDown := (line(img.At(curX, curY+2)) && line(img.At(curX+1, curY+2)) || line(img.At(curX, curY+3)) && line(img.At(curX+1, curY+3)))
if canGoFarRight && !wasMovingVertically && (canGoUp || canGoDown) {
return fmt.Errorf("line forks at (%d,%d): can go up/down at the same time as right", curX, curY)
} else if !movingVertically && canGoUp && canGoDown {
return fmt.Errorf("line tees at (%d,%d): can go up and down at the same time", curX, curY)
} else if movingVertically && canGoFarRight {
wasMovingVertically = true
curX++
} else if (!movingVertically || movingUp) && !wasMovingVertically && canGoUp {
movingUp = true
curY--
} else if (!movingVertically || movingDown) && !wasMovingVertically && canGoDown {
movingDown = true
curY++
} else if !movingVertically && canGoRight {
wasMovingVertically = false
curX++
} else {
return fmt.Errorf("line ends at (%d,%d): cannot go anywhere", curX, curY)
}
}
}
return nil
}
// getGraphBounds returns the detected graph bounds (based on lines of the grid
@ -102,9 +174,9 @@ func getPriceExtrapolator(img image.Image, graphBounds image.Rectangle, maxPrice
// getDateExtrapolator gets an extrapolator to extract the date from the image
// based on an x value relative to the image (NOT the grid).
func getDateExtrapolator(img image.Image, gridBounds image.Rectangle, startDate, endDate time.Time) func(y int) time.Time {
func getDateExtrapolator(img image.Image, gridBounds image.Rectangle, startDate, endDate time.Time) func(x int) time.Time {
dates := getDaysBetween(startDate, endDate)
return func(y int) time.Time {
return dates[int(math.Round(extrapolate(gridBounds.Min.X+1, gridBounds.Max.X, 0, float64(len(dates)), y)))]
return func(x int) time.Time {
return dates[int(math.Round(extrapolate(gridBounds.Min.X+1, gridBounds.Max.X, 0, float64(len(dates)), x)))]
}
}