Files
StarPilot/mapd_repo/cli/output.go
T
firestar5683 ab81464bd1 Maps
Add navigation and map matching providers with the vendored map service sources.

Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
2026-10-14 19:56:17 -05:00

139 lines
3.3 KiB
Go

package cli
import (
"fmt"
"math"
tea "github.com/charmbracelet/bubbletea"
"pfeifer.dev/mapd/cereal/custom"
)
type outputModel struct {
output custom.MapdOut
extendedOutput custom.MapdExtendedOut
valid bool
extendedValid bool
height, width int
}
func (m outputModel) Update(msg tea.Msg, mm *uiModel) (outputModel, tea.Cmd) {
out, success := mm.sub.Read()
if success {
m.valid = true
m.output = out
}
m.extendedValid = mm.extendedDataValid
m.extendedOutput = mm.extendedData
switch msg := msg.(type) {
case tea.WindowSizeMsg:
h, v := docStyle.GetFrameSize()
m.width = msg.Width - h
m.height = msg.Height - v
}
return m, nil
}
func (m outputModel) View() string {
if !m.valid || !m.extendedValid {
return ""
}
path, _ := m.extendedOutput.Path()
minLat := 180.0
minLon := 180.0
maxLat := -180.0
maxLon := -180.0
for i := range path.Len() {
point := path.At(i)
if point.Latitude() < minLat {
minLat = point.Latitude()
}
if point.Longitude() < minLon {
minLon = point.Longitude()
}
if point.Latitude() > maxLat {
maxLat = point.Latitude()
}
if point.Longitude() > maxLon {
maxLon = point.Longitude()
}
}
latRange := maxLat - minLat
lonRange := maxLon - minLon
gHeight := m.height - 15
gWidth := m.width
if gHeight < gWidth/2 {
gWidth = gHeight * 2
} else {
gHeight = gWidth / 2
}
grid := make([]byte, int(gWidth*gHeight+gHeight+1))
for i := range int(gWidth*gHeight + gHeight + 1) {
if i%(gWidth+1) == 0 && i != 0 {
grid[i] = '\n'
} else {
grid[i] = ' '
}
}
if latRange != 0 && lonRange != 0 {
aspect := latRange / lonRange
if lonRange > latRange {
aspect = lonRange / latRange
}
for i := range path.Len() {
point := path.At(i)
y := (point.Latitude() - minLat) / latRange
x := (lonRange - (point.Longitude() - minLon)) / lonRange
if latRange > lonRange {
x /= aspect
} else {
y /= aspect
}
idx := int(math.Floor(x*float64(gWidth)) + (math.Floor(y*float64(gHeight-1)) * (float64(gWidth) + 1)))
if idx%(gWidth+1) == 0 {
idx += 1
}
grid[idx] = '#'
}
position, err := m.extendedOutput.Position()
if err == nil {
y := (position.Latitude() - minLat) / latRange
x := (lonRange - (position.Longitude() - minLon)) / lonRange
if latRange > lonRange {
x /= aspect
} else {
y /= aspect
}
idx := int(math.Floor(x*float64(gWidth)) + (math.Floor(y*float64(gHeight-1)) * (float64(gWidth) + 1)))
if idx%(gWidth+1) == 0 {
idx += 1
}
if idx < len(grid) {
grid[idx] = 'X'
}
}
}
roadname, _ := m.output.RoadName()
return docStyle.Render(fmt.Sprintf(
"name: %s\nsuggested speed: %f\nspeed limit: %f\nspeed limit suggested speed: %f\nnext speed limit: %f\nnext speed limit distance: %f\nvision curve speed: %f\nmap curve speed: %f\ndistance from center: %f\nlanes: %d\nhighway class: %s\nselection type: %s\nloop rate average: %f\nloop rate min: %f\n\n%s",
roadname,
m.output.SuggestedSpeed(),
m.output.SpeedLimit(),
m.output.SpeedLimitSuggestedSpeed(),
m.output.NextSpeedLimit(),
m.output.NextSpeedLimitDistance(),
m.output.VisionCurveSpeed(),
m.output.MapCurveSpeed(),
m.output.DistanceFromWayCenter(),
m.output.Lanes(),
m.output.HighwayClass().String(),
m.output.WaySelectionType().String(),
m.extendedOutput.LoopRateAverage(),
m.extendedOutput.LoopRateMin(),
string(grid),
) + "\n")
}