mirror of
https://github.com/cjdenio/uta-trax-api.git
synced 2026-08-04 22:06:34 +00:00
cool stuff
This commit is contained in:
+90
-9
@@ -1,9 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -11,8 +14,62 @@ import (
|
|||||||
|
|
||||||
pb "github.com/cjdenio/uta-trax-api/proto"
|
pb "github.com/cjdenio/uta-trax-api/proto"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var scheduleDb *sql.DB
|
||||||
|
|
||||||
|
func distance(lat1 float64, lng1 float64, lat2 float64, lng2 float64) float64 {
|
||||||
|
radlat1 := float64(math.Pi * lat1 / 180)
|
||||||
|
radlat2 := float64(math.Pi * lat2 / 180)
|
||||||
|
|
||||||
|
theta := float64(lng1 - lng2)
|
||||||
|
radtheta := float64(math.Pi * theta / 180)
|
||||||
|
|
||||||
|
dist := math.Sin(radlat1)*math.Sin(radlat2) + math.Cos(radlat1)*math.Cos(radlat2)*math.Cos(radtheta)
|
||||||
|
if dist > 1 {
|
||||||
|
dist = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
dist = math.Acos(dist)
|
||||||
|
dist = dist * 180 / math.Pi
|
||||||
|
dist = dist * 60 * 1.1515
|
||||||
|
|
||||||
|
return dist
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStationForVehicle(vehicle *pb.VehiclePosition) *pb.VehicleFeed_Station {
|
||||||
|
rows, err := scheduleDb.Query(`SELECT stop_lat, stop_lon, stops.stop_id, stop_name FROM stop_times INNER JOIN stops ON stops.stop_id = stop_times.stop_id WHERE stop_times.trip_id = ? AND stop_times.pickup_type != 1 AND stop_times.drop_off_type != 1;`, vehicle.Trip.TripId)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
nearestStop := new(pb.VehicleFeed_Station)
|
||||||
|
nearestStopDistance := math.Inf(1)
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var stop_lat float32
|
||||||
|
var stop_lon float32
|
||||||
|
var stop_id string
|
||||||
|
var stop_name string
|
||||||
|
|
||||||
|
rows.Scan(&stop_lat, &stop_lon, &stop_id, &stop_name)
|
||||||
|
|
||||||
|
distance := distance(float64(stop_lat), float64(stop_lon), float64(*vehicle.Position.Latitude), float64(*vehicle.Position.Longitude))
|
||||||
|
if distance < nearestStopDistance {
|
||||||
|
nearestStop.Id = stop_id
|
||||||
|
nearestStop.Name = stop_name
|
||||||
|
nearestStop.Lat = stop_lat
|
||||||
|
nearestStop.Lon = stop_lon
|
||||||
|
|
||||||
|
nearestStopDistance = distance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nearestStop
|
||||||
|
}
|
||||||
|
|
||||||
func getVehicles() ([]*pb.VehiclePosition, error) {
|
func getVehicles() ([]*pb.VehiclePosition, error) {
|
||||||
resp, err := http.Get("https://apps.rideuta.com/tms/gtfs/Vehicle")
|
resp, err := http.Get("https://apps.rideuta.com/tms/gtfs/Vehicle")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -86,9 +143,9 @@ func loadTrips() error {
|
|||||||
case "45389":
|
case "45389":
|
||||||
trip_info.Line = pb.VehicleFeed_STREETCAR
|
trip_info.Line = pb.VehicleFeed_STREETCAR
|
||||||
trips[record[trip_id]] = trip_info
|
trips[record[trip_id]] = trip_info
|
||||||
case "41065":
|
// case "41065":
|
||||||
trip_info.Line = pb.VehicleFeed_FRONTRUNNER
|
// trip_info.Line = pb.VehicleFeed_FRONTRUNNER
|
||||||
trips[record[trip_id]] = trip_info
|
// trips[record[trip_id]] = trip_info
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
@@ -108,11 +165,12 @@ func feedifyVehicles(vehicles []*pb.VehiclePosition) pb.VehicleFeed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vehicle_feed = append(vehicle_feed, &pb.VehicleFeed_Vehicle{
|
vehicle_feed = append(vehicle_feed, &pb.VehicleFeed_Vehicle{
|
||||||
Lat: *vehicle.Position.Latitude,
|
Lat: *vehicle.Position.Latitude,
|
||||||
Lon: *vehicle.Position.Longitude,
|
Lon: *vehicle.Position.Longitude,
|
||||||
Line: trip.Line,
|
Line: trip.Line,
|
||||||
Id: *vehicle.Vehicle.Id,
|
Id: *vehicle.Vehicle.Id,
|
||||||
Direction: trip.Direction,
|
Direction: trip.Direction,
|
||||||
|
NearestStation: getStationForVehicle(vehicle),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +184,22 @@ func main() {
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_db, err := sql.Open("sqlite3", "uta-gtfs.db")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
scheduleDb = _db
|
||||||
|
|
||||||
|
// vehicles, err := getVehicles()
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatalln(err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for _, v := range vehicles {
|
||||||
|
// station := getStationForVehicle(v)
|
||||||
|
// fmt.Println(station)
|
||||||
|
// }
|
||||||
|
|
||||||
http.Handle("/", http.FileServer(http.Dir("./static")))
|
http.Handle("/", http.FileServer(http.Dir("./static")))
|
||||||
|
|
||||||
http.HandleFunc("/schema.proto", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/schema.proto", func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -144,5 +218,12 @@ func main() {
|
|||||||
w.Write(b)
|
w.Write(b)
|
||||||
})
|
})
|
||||||
|
|
||||||
http.ListenAndServe(":"+os.Getenv("PORT"), nil)
|
port := "3000"
|
||||||
|
if portEnv, ok := os.LookupEnv("PORT"); ok {
|
||||||
|
port = portEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Started on port %s\n", port)
|
||||||
|
|
||||||
|
http.ListenAndServe(":"+port, nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,7 @@ module github.com/cjdenio/uta-trax-api
|
|||||||
|
|
||||||
go 1.24.2
|
go 1.24.2
|
||||||
|
|
||||||
require google.golang.org/protobuf v1.36.6 // indirect
|
require (
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.28 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
|
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
|
|||||||
+105
-21
@@ -123,20 +123,89 @@ func (x *VehicleFeed) GetVehicles() []*VehicleFeed_Vehicle {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type VehicleFeed_Vehicle struct {
|
type VehicleFeed_Station struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Lat float32 `protobuf:"fixed32,1,opt,name=lat,proto3" json:"lat,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
Lon float32 `protobuf:"fixed32,2,opt,name=lon,proto3" json:"lon,omitempty"`
|
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
Line VehicleFeed_Line `protobuf:"varint,3,opt,name=line,proto3,enum=VehicleFeed_Line" json:"line,omitempty"`
|
Lat float32 `protobuf:"fixed32,3,opt,name=lat,proto3" json:"lat,omitempty"`
|
||||||
Direction int32 `protobuf:"varint,4,opt,name=direction,proto3" json:"direction,omitempty"`
|
Lon float32 `protobuf:"fixed32,4,opt,name=lon,proto3" json:"lon,omitempty"`
|
||||||
Id string `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"`
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) Reset() {
|
||||||
|
*x = VehicleFeed_Station{}
|
||||||
|
mi := &file_proto_schema_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*VehicleFeed_Station) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proto_schema_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use VehicleFeed_Station.ProtoReflect.Descriptor instead.
|
||||||
|
func (*VehicleFeed_Station) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proto_schema_proto_rawDescGZIP(), []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) GetId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Id
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) GetName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) GetLat() float32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Lat
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Station) GetLon() float32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Lon
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type VehicleFeed_Vehicle struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Lat float32 `protobuf:"fixed32,1,opt,name=lat,proto3" json:"lat,omitempty"`
|
||||||
|
Lon float32 `protobuf:"fixed32,2,opt,name=lon,proto3" json:"lon,omitempty"`
|
||||||
|
Line VehicleFeed_Line `protobuf:"varint,3,opt,name=line,proto3,enum=VehicleFeed_Line" json:"line,omitempty"`
|
||||||
|
Direction int32 `protobuf:"varint,4,opt,name=direction,proto3" json:"direction,omitempty"`
|
||||||
|
Id string `protobuf:"bytes,5,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
|
NearestStation *VehicleFeed_Station `protobuf:"bytes,6,opt,name=nearest_station,json=nearestStation,proto3" json:"nearest_station,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
func (x *VehicleFeed_Vehicle) Reset() {
|
func (x *VehicleFeed_Vehicle) Reset() {
|
||||||
*x = VehicleFeed_Vehicle{}
|
*x = VehicleFeed_Vehicle{}
|
||||||
mi := &file_proto_schema_proto_msgTypes[1]
|
mi := &file_proto_schema_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -148,7 +217,7 @@ func (x *VehicleFeed_Vehicle) String() string {
|
|||||||
func (*VehicleFeed_Vehicle) ProtoMessage() {}
|
func (*VehicleFeed_Vehicle) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *VehicleFeed_Vehicle) ProtoReflect() protoreflect.Message {
|
func (x *VehicleFeed_Vehicle) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_proto_schema_proto_msgTypes[1]
|
mi := &file_proto_schema_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -161,7 +230,7 @@ func (x *VehicleFeed_Vehicle) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use VehicleFeed_Vehicle.ProtoReflect.Descriptor instead.
|
// Deprecated: Use VehicleFeed_Vehicle.ProtoReflect.Descriptor instead.
|
||||||
func (*VehicleFeed_Vehicle) Descriptor() ([]byte, []int) {
|
func (*VehicleFeed_Vehicle) Descriptor() ([]byte, []int) {
|
||||||
return file_proto_schema_proto_rawDescGZIP(), []int{0, 0}
|
return file_proto_schema_proto_rawDescGZIP(), []int{0, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *VehicleFeed_Vehicle) GetLat() float32 {
|
func (x *VehicleFeed_Vehicle) GetLat() float32 {
|
||||||
@@ -199,19 +268,32 @@ func (x *VehicleFeed_Vehicle) GetId() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *VehicleFeed_Vehicle) GetNearestStation() *VehicleFeed_Station {
|
||||||
|
if x != nil {
|
||||||
|
return x.NearestStation
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var File_proto_schema_proto protoreflect.FileDescriptor
|
var File_proto_schema_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_proto_schema_proto_rawDesc = "" +
|
const file_proto_schema_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x12proto/schema.proto\"\xa0\x02\n" +
|
"\x12proto/schema.proto\"\xb2\x03\n" +
|
||||||
"\vVehicleFeed\x120\n" +
|
"\vVehicleFeed\x120\n" +
|
||||||
"\bvehicles\x18\x01 \x03(\v2\x14.VehicleFeed.VehicleR\bvehicles\x1a\x82\x01\n" +
|
"\bvehicles\x18\x01 \x03(\v2\x14.VehicleFeed.VehicleR\bvehicles\x1aQ\n" +
|
||||||
|
"\aStation\x12\x0e\n" +
|
||||||
|
"\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n" +
|
||||||
|
"\x04name\x18\x02 \x01(\tR\x04name\x12\x10\n" +
|
||||||
|
"\x03lat\x18\x03 \x01(\x02R\x03lat\x12\x10\n" +
|
||||||
|
"\x03lon\x18\x04 \x01(\x02R\x03lon\x1a\xc1\x01\n" +
|
||||||
"\aVehicle\x12\x10\n" +
|
"\aVehicle\x12\x10\n" +
|
||||||
"\x03lat\x18\x01 \x01(\x02R\x03lat\x12\x10\n" +
|
"\x03lat\x18\x01 \x01(\x02R\x03lat\x12\x10\n" +
|
||||||
"\x03lon\x18\x02 \x01(\x02R\x03lon\x12%\n" +
|
"\x03lon\x18\x02 \x01(\x02R\x03lon\x12%\n" +
|
||||||
"\x04line\x18\x03 \x01(\x0e2\x11.VehicleFeed.LineR\x04line\x12\x1c\n" +
|
"\x04line\x18\x03 \x01(\x0e2\x11.VehicleFeed.LineR\x04line\x12\x1c\n" +
|
||||||
"\tdirection\x18\x04 \x01(\x05R\tdirection\x12\x0e\n" +
|
"\tdirection\x18\x04 \x01(\x05R\tdirection\x12\x0e\n" +
|
||||||
"\x02id\x18\x05 \x01(\tR\x02id\"Z\n" +
|
"\x02id\x18\x05 \x01(\tR\x02id\x12=\n" +
|
||||||
|
"\x0fnearest_station\x18\x06 \x01(\v2\x14.VehicleFeed.StationR\x0enearestStation\"Z\n" +
|
||||||
"\x04Line\x12\x14\n" +
|
"\x04Line\x12\x14\n" +
|
||||||
"\x10LINE_UNSPECIFIED\x10\x00\x12\t\n" +
|
"\x10LINE_UNSPECIFIED\x10\x00\x12\t\n" +
|
||||||
"\x05GREEN\x10\x01\x12\a\n" +
|
"\x05GREEN\x10\x01\x12\a\n" +
|
||||||
@@ -233,20 +315,22 @@ func file_proto_schema_proto_rawDescGZIP() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file_proto_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
var file_proto_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_proto_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
var file_proto_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||||
var file_proto_schema_proto_goTypes = []any{
|
var file_proto_schema_proto_goTypes = []any{
|
||||||
(VehicleFeed_Line)(0), // 0: VehicleFeed.Line
|
(VehicleFeed_Line)(0), // 0: VehicleFeed.Line
|
||||||
(*VehicleFeed)(nil), // 1: VehicleFeed
|
(*VehicleFeed)(nil), // 1: VehicleFeed
|
||||||
(*VehicleFeed_Vehicle)(nil), // 2: VehicleFeed.Vehicle
|
(*VehicleFeed_Station)(nil), // 2: VehicleFeed.Station
|
||||||
|
(*VehicleFeed_Vehicle)(nil), // 3: VehicleFeed.Vehicle
|
||||||
}
|
}
|
||||||
var file_proto_schema_proto_depIdxs = []int32{
|
var file_proto_schema_proto_depIdxs = []int32{
|
||||||
2, // 0: VehicleFeed.vehicles:type_name -> VehicleFeed.Vehicle
|
3, // 0: VehicleFeed.vehicles:type_name -> VehicleFeed.Vehicle
|
||||||
0, // 1: VehicleFeed.Vehicle.line:type_name -> VehicleFeed.Line
|
0, // 1: VehicleFeed.Vehicle.line:type_name -> VehicleFeed.Line
|
||||||
2, // [2:2] is the sub-list for method output_type
|
2, // 2: VehicleFeed.Vehicle.nearest_station:type_name -> VehicleFeed.Station
|
||||||
2, // [2:2] is the sub-list for method input_type
|
3, // [3:3] is the sub-list for method output_type
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
3, // [3:3] is the sub-list for method input_type
|
||||||
2, // [2:2] is the sub-list for extension extendee
|
3, // [3:3] is the sub-list for extension type_name
|
||||||
0, // [0:2] is the sub-list for field type_name
|
3, // [3:3] is the sub-list for extension extendee
|
||||||
|
0, // [0:3] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proto_schema_proto_init() }
|
func init() { file_proto_schema_proto_init() }
|
||||||
@@ -260,7 +344,7 @@ func file_proto_schema_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_schema_proto_rawDesc), len(file_proto_schema_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_schema_proto_rawDesc), len(file_proto_schema_proto_rawDesc)),
|
||||||
NumEnums: 1,
|
NumEnums: 1,
|
||||||
NumMessages: 2,
|
NumMessages: 3,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,12 +11,20 @@ message VehicleFeed {
|
|||||||
FRONTRUNNER = 5;
|
FRONTRUNNER = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Station {
|
||||||
|
string id = 1;
|
||||||
|
string name = 2;
|
||||||
|
float lat = 3;
|
||||||
|
float lon = 4;
|
||||||
|
}
|
||||||
|
|
||||||
message Vehicle {
|
message Vehicle {
|
||||||
float lat = 1;
|
float lat = 1;
|
||||||
float lon = 2;
|
float lon = 2;
|
||||||
Line line = 3;
|
Line line = 3;
|
||||||
int32 direction = 4;
|
int32 direction = 4;
|
||||||
string id = 5;
|
string id = 5;
|
||||||
|
Station nearest_station = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
repeated Vehicle vehicles = 1;
|
repeated Vehicle vehicles = 1;
|
||||||
|
|||||||
+3
-1
@@ -55,7 +55,9 @@
|
|||||||
color: COLORS[vehicle.line],
|
color: COLORS[vehicle.line],
|
||||||
fillOpacity: 0.5,
|
fillOpacity: 0.5,
|
||||||
radius: 200,
|
radius: 200,
|
||||||
}).addTo(map);
|
})
|
||||||
|
.addTo(map)
|
||||||
|
.bindPopup(vehicle.nearestStation.name);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
BIN
Binary file not shown.
Reference in New Issue
Block a user