3 Commits
30 changed files with 2408 additions and 1429 deletions
+93 -36
View File
@@ -1,6 +1,16 @@
#include "esp_camera.h" #include "esp_camera.h"
#include <WiFi.h> #include <WiFi.h>
#include <WiFiUdp.h> #include <WiFiUdp.h>
#include <ESP32Servo.h>
// === НАСТРОЙКА РЕЖИМА ЗАГЛУШКИ ===
const bool USE_MOCK_IF_NO_CAMERA = true; // true - слать черный экран, false - ничего не слать
Servo myServo;
const int servoPin = 13; // ПРИОРИТЕТ: Пин жестко закреплен за сервоприводом
// !!! УНИКАЛЬНЫЙ ID ДЛЯ КАЖДОЙ ПЛАТЫ
const uint8_t DEVICE_ID = 1;
// Конфигурация пинов (пример для Seeed Studio XIAO ESP32S3 Sense) // Конфигурация пинов (пример для Seeed Studio XIAO ESP32S3 Sense)
#define PWDN_GPIO_NUM -1 #define PWDN_GPIO_NUM -1
@@ -10,7 +20,7 @@
#define SIOC_GPIO_NUM 39 #define SIOC_GPIO_NUM 39
#define Y9_GPIO_NUM 48 #define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 47 #define Y8_GPIO_NUM 47
#define Y7_GPIO_NUM 13 #define Y7_GPIO_NUM 18 // ИЗМЕНЕНО: Отключаем этот пин для камеры, отдаем под Серво
#define Y6_GPIO_NUM 14 #define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 12 #define Y5_GPIO_NUM 12
#define Y4_GPIO_NUM 11 #define Y4_GPIO_NUM 11
@@ -20,24 +30,45 @@
#define HREF_GPIO_NUM 38 #define HREF_GPIO_NUM 38
#define PCLK_GPIO_NUM 37 #define PCLK_GPIO_NUM 37
const char* ssid = "RT-WiFi-1712"; const char* ssid = "RT-WiFi-1712";
const char* password = "yt3xihY2Ci"; const char* password = "yt3xihY2Ci";
const char* serverIP = "192.168.0.11"; const char* serverIP = "192.168.0.10";
const int serverPort = 9999; const int serverPort = 9999;
const int localPort = 8888; const int localPort = 8888;
// !!! УНИКАЛЬНЫЙ ID ДЛЯ КАЖДОЙ ПЛАТЫ (например, 1 для первой, 2 для второй и т.д.)
const uint8_t DEVICE_ID = 1;
WiFiUDP udpVideo; WiFiUDP udpVideo;
WiFiUDP udpCmd; WiFiUDP udpCmd;
camera_config_t config; camera_config_t config;
// Флаг успешной инициализации камеры
bool isCameraInitialized = false;
// Моковый минимальный валидный JPEG черного цвета
const uint8_t mockBlackJpeg[] = {
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x60,
0x00, 0x60, 0x00, 0x00, 0xFF, 0xDB, 0x00, 0x43, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x0B, 0x08, 0x00, 0x08,
0x00, 0x08, 0x01, 0x01, 0x11, 0x00, 0xFF, 0xC4, 0x00, 0x14, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xFF, 0xC4, 0x00, 0x14,
0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xDA, 0x00, 0x08, 0x01, 0x01, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0xFF, 0xD9
};
const size_t mockSize = sizeof(mockBlackJpeg);
void setup() { void setup() {
Serial.begin(115200); Serial.begin(115200);
// Настройка камеры (QVGA для стабильности)
// Инициализируем сервопривод в первую очередь
myServo.attach(servoPin, 500, 2500);
Serial.println("Сервопривод инициализирован на пине 13");
// Настройка конфигурации камеры
config.ledc_channel = LEDC_CHANNEL_0; config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0; config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM; config.pin_d0 = Y2_GPIO_NUM;
@@ -45,7 +76,7 @@ void setup() {
config.pin_d2 = Y4_GPIO_NUM; config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM; config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM; config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM; config.pin_d5 = Y7_GPIO_NUM; // Передаст -1, библиотека не тронет 13 пин
config.pin_d6 = Y8_GPIO_NUM; config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM; config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM; config.pin_xclk = XCLK_GPIO_NUM;
@@ -62,7 +93,15 @@ void setup() {
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_count = 2; config.fb_count = 2;
esp_camera_init(&config); // Проверяем статус инициализации камеры
esp_err_t err = esp_camera_init(&config);
if (err == ESP_OK) {
isCameraInitialized = true;
Serial.println("Камера успешно инициализирована!");
} else {
isCameraInitialized = false;
Serial.printf("Камера не найдена (код 0x%x). Режим мок-данных: %s\n", err, USE_MOCK_IF_NO_CAMERA ? "ВКЛ" : "ВЫКЛ");
}
// Подключение к Wi-Fi // Подключение к Wi-Fi
WiFi.begin(ssid, password); WiFi.begin(ssid, password);
@@ -79,43 +118,58 @@ void setup() {
void checkIncomingCommands() { void checkIncomingCommands() {
int packetSize = udpCmd.parsePacket(); int packetSize = udpCmd.parsePacket();
if (packetSize > 0) { if (packetSize == 5) {
char packetBuffer[255]; uint8_t packetBuffer[5];
int len = udpCmd.read(packetBuffer, 255); int len = udpCmd.read(packetBuffer, 5);
if (len > 0) { packetBuffer[len] = 0; } if (len == 5) {
uint8_t steer = packetBuffer[0];
uint8_t throttle = packetBuffer[1];
uint8_t brake = packetBuffer[2];
uint8_t gear = packetBuffer[3];
uint8_t flags = packetBuffer[4];
String command = String(packetBuffer); // ИСПРАВЛЕНО: Инвертирован диапазон (180, 0 вместо 0, 180) для исправления направления
command.trim(); int servoAngle = map(steer, 0, 200, 180, 0);
myServo.write(servoAngle);
Serial.print("Получена команда: "); Serial.printf("Got control packet: Steer=%d (Angle=%d), Throttle=%d%%, Brake=%d%%, Gear=%d, Flags=0x%02X\n",
Serial.println(command); steer, servoAngle, throttle, brake, gear, flags);
Serial.print("Получена команда: ");
Serial.println(command);
// Логика управления
if (command == "left") {
// Ваш код поворота налево
} else if (command == "right") {
// Ваш код поворота направо
} else if (command == "start") {
// Ваш код запуска моторов / логики
} else if (command == "stop") {
// Ваш код остановки
} }
} else if (packetSize > 0) {
char garbage[255];
udpCmd.read(garbage, sizeof(garbage));
} }
} }
void loop() { void loop() {
checkIncomingCommands(); checkIncomingCommands();
camera_fb_t * fb = esp_camera_fb_get(); uint8_t * buf = nullptr;
if (!fb) return; size_t bufferSize = 0;
camera_fb_t * fb = nullptr;
size_t bufferSize = fb->len; // Пытаемся получить кадр, если камера запущена
uint8_t * buf = fb->buf; if (isCameraInitialized) {
fb = esp_camera_fb_get();
if (fb) {
bufferSize = fb->len;
buf = fb->buf;
}
}
// Размер куска данных уменьшаем до 1023, чтобы вместе с 1 байтом ID пакет был 1024 байта // Если кадра с камеры нет
if (!buf) {
// Если отправка заглушки отключена — выходим из цикла, продолжая слушать команды
if (!USE_MOCK_IF_NO_CAMERA) {
delay(10);
return;
}
// Если включена — подставляем моковый черный кадр
bufferSize = mockSize;
buf = (uint8_t *)mockBlackJpeg;
}
// Нарезка и отправка по UDP (оригинальная логика)
size_t chunkSize = 1023; size_t chunkSize = 1023;
uint8_t packetBuffer[1024]; uint8_t packetBuffer[1024];
@@ -125,15 +179,18 @@ void loop() {
sendSize = bufferSize - i; sendSize = bufferSize - i;
} }
// Формируем пакет: первый байт — ID, дальше — видеоданные
packetBuffer[0] = DEVICE_ID; packetBuffer[0] = DEVICE_ID;
memcpy(packetBuffer + 1, buf + i, sendSize); memcpy(packetBuffer + 1, buf + i, sendSize);
udpVideo.beginPacket(serverIP, serverPort); udpVideo.beginPacket(serverIP, serverPort);
udpVideo.write(packetBuffer, sendSize + 1); // Отправляем данные вместе с ID udpVideo.write(packetBuffer, sendSize + 1);
udpVideo.endPacket(); udpVideo.endPacket();
} }
// Возвращаем буфер только если он реальный
if (fb) {
esp_camera_fb_return(fb); esp_camera_fb_return(fb);
}
delay(10); delay(10);
} }
+4
View File
@@ -19,7 +19,11 @@ X0GP_LOG_LEVEL=info
X0GP_TICK_RATE=60 X0GP_TICK_RATE=60
X0GP_SNAPSHOT_RATE=30 X0GP_SNAPSHOT_RATE=30
X0GP_MAX_CLIENTS=100 X0GP_MAX_CLIENTS=100
X0GP_SEED_RACES=0
X0GP_SEED_RESET=0
# Optional: override path(s) to dotenv files (colon-separated).
# X0GP_DOTENV=.env:./configs/local.env
# PoC: skip auth, allow multiple clients on the same track. # PoC: skip auth, allow multiple clients on the same track.
X0GP_DEV_MODE=true X0GP_DEV_MODE=true
@@ -189,6 +189,7 @@ func carToWire(c catalog.CarMeta) transport.CarWire {
ColorHex: c.ColorHex, ColorHex: c.ColorHex,
AvatarURL: c.AvatarURL, AvatarURL: c.AvatarURL,
Active: c.Active, Active: c.Active,
DeviceID: c.DeviceID,
// Stats are read-mostly; the server fills them on read. // Stats are read-mostly; the server fills them on read.
TotalDistanceM: c.TotalDistanceM, TotalDistanceM: c.TotalDistanceM,
TotalRaces: c.TotalRaces, TotalRaces: c.TotalRaces,
@@ -241,6 +242,7 @@ func carFromWire(w transport.CarWire) catalog.CarMeta {
Active: w.Active, Active: w.Active,
CreatedMs: w.CreatedMs, CreatedMs: w.CreatedMs,
UpdatedMs: w.UpdatedMs, UpdatedMs: w.UpdatedMs,
DeviceID: w.DeviceID,
} }
} }
@@ -292,6 +294,7 @@ func carPatchFromWire(p transport.CarPatch) catalog.UpdateCarOptions {
Chassis: chassisFromPtr(p.Chassis), Chassis: chassisFromPtr(p.Chassis),
Motor: motorFromPtr(p.Motor), Motor: motorFromPtr(p.Motor),
Battery: batteryFromPtr(p.Battery), Battery: batteryFromPtr(p.Battery),
DeviceID: p.DeviceID,
} }
} }
+15 -18
View File
@@ -283,7 +283,7 @@ func driversListHandler(svc *drivers.Service) http.HandlerFunc {
// @Router /api/drivers/{id} [get] // @Router /api/drivers/{id} [get]
// @Router /api/drivers/{id} [put] // @Router /api/drivers/{id} [put]
// @Router /api/drivers/{id} [delete] // @Router /api/drivers/{id} [delete]
// @Router /api/drivers/{id}/device [put] // @Router /api/drivers/{id}/car [put]
func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.HandlerFunc { func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/api/drivers/") id := strings.TrimPrefix(r.URL.Path, "/api/drivers/")
@@ -291,8 +291,8 @@ func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.Hand
writeError(w, http.StatusBadRequest, "bad_request", "missing driver id") writeError(w, http.StatusBadRequest, "bad_request", "missing driver id")
return return
} }
if strings.HasSuffix(id, "/device") { if strings.HasSuffix(id, "/car") {
driverID := strings.TrimSuffix(id, "/device") driverID := strings.TrimSuffix(id, "/car")
if driverID == "" { if driverID == "" {
writeError(w, http.StatusBadRequest, "bad_request", "missing driver id") writeError(w, http.StatusBadRequest, "bad_request", "missing driver id")
return return
@@ -303,29 +303,26 @@ func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.Hand
return return
} }
// Read device_id from JSON body or query param // Read car_id from JSON body or query param
var deviceID *int var carID *string
type deviceRequest struct { type carRequest struct {
DeviceID *int `json:"device_id"` CarID *string `json:"car_id"`
} }
var req deviceRequest var req carRequest
if r.ContentLength > 0 { if r.ContentLength > 0 {
if err := json.NewDecoder(r.Body).Decode(&req); err == nil { if err := json.NewDecoder(r.Body).Decode(&req); err == nil {
deviceID = req.DeviceID carID = req.CarID
} }
} }
// Fallback to query parameter if body didn't provide it // Fallback to query parameter if body didn't provide it
if deviceID == nil { if carID == nil {
qVal := r.URL.Query().Get("device_id") qVal := r.URL.Query().Get("car_id")
if qVal != "" { if qVal != "" {
if qVal == "null" { if qVal == "null" {
deviceID = nil carID = nil
} else if idInt, err := strconv.Atoi(qVal); err == nil {
deviceID = &idInt
} else { } else {
writeError(w, http.StatusBadRequest, "bad_request", "invalid device_id query parameter") carID = &qVal
return
} }
} }
} }
@@ -345,8 +342,8 @@ func driversByIDHandler(svc *drivers.Service, lobbySvc *lobby.Service) http.Hand
_, _ = lobbySvc.AddDriver(driverID, drv.Name, "") _, _ = lobbySvc.AddDriver(driverID, drv.Name, "")
lobbySvc.SetDriverProfile(driverID, drv.Nickname, drv.AvatarURL, drv.ClanID, "") lobbySvc.SetDriverProfile(driverID, drv.Nickname, drv.AvatarURL, drv.ClanID, "")
// Select device in lobby (handles constraints and write-through) // Select car in lobby (handles constraints and write-through)
if err := lobbySvc.SelectDevice(driverID, deviceID); err != nil { if err := lobbySvc.SelectCar(driverID, carID); err != nil {
writeError(w, http.StatusBadRequest, "bad_request", err.Error()) writeError(w, http.StatusBadRequest, "bad_request", err.Error())
return return
} }
+48 -19
View File
@@ -27,11 +27,13 @@ package main
import ( import (
"bufio" "bufio"
"context" "context"
"encoding/hex"
"encoding/json" "encoding/json"
"errors" "errors"
"flag" "flag"
"fmt" "fmt"
"log/slog" "log/slog"
"math"
"net" "net"
"net/http" "net/http"
"os" "os"
@@ -197,7 +199,7 @@ func main() {
driversSvc := drivers.NewService(drivers.NewPgStore(pool)) driversSvc := drivers.NewService(drivers.NewPgStore(pool))
// WebRTC 1-to-1 driver-car proxy service // WebRTC 1-to-1 driver-car proxy service
webrtcSvc := NewWebRTCService(logger, engine, lobbySvc, videoSvc) webrtcSvc := NewWebRTCService(logger, engine, lobbySvc, videoSvc, cat)
// Persist finished races so the /api/races list and keyset pagination // Persist finished races so the /api/races list and keyset pagination
// can serve historical data across restarts. The snapshot is best- // can serve historical data across restarts. The snapshot is best-
@@ -575,7 +577,7 @@ func readPump(cfg *config.Config, c *realtime.Client, conn *websocket.Conn, e *c
case transport.TypeClientHello: case transport.TypeClientHello:
handleClientHello(c, e, cfg, lobbySvc, driversSvc, env) handleClientHello(c, e, cfg, lobbySvc, driversSvc, env)
case transport.TypeJoinRace: case transport.TypeJoinRace:
handleJoinRace(c, e, lobbySvc, env) handleJoinRace(c, e, lobbySvc, cat, env)
case transport.TypeLeaveRace: case transport.TypeLeaveRace:
handleLeaveRace(c, e, env) handleLeaveRace(c, e, env)
case transport.TypeInputState: case transport.TypeInputState:
@@ -633,7 +635,7 @@ func handleClientHello(c *realtime.Client, e *control.Engine, cfg *config.Config
c.Send <- mustEncode(transport.TypeServerHello, hello) c.Send <- mustEncode(transport.TypeServerHello, hello)
} }
func handleJoinRace(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service, env *transport.Envelope) { func handleJoinRace(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service, cat *catalog.Service, env *transport.Envelope) {
payload, _ := env.Payload.(map[string]any) payload, _ := env.Payload.(map[string]any)
slot := 0 slot := 0
name := "anon" name := "anon"
@@ -652,8 +654,10 @@ func handleJoinRace(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Servi
driverID = c.ID driverID = c.ID
} }
var deviceID *int var deviceID *int
if d, err := lobbySvc.GetDriver(driverID); err == nil { if d, err := lobbySvc.GetDriver(driverID); err == nil && d.CarID != nil && *d.CarID != "" {
deviceID = d.DeviceID if carMeta, ok := cat.GetCar(*d.CarID); ok {
deviceID = carMeta.DeviceID
}
} }
car, err := e.AddCar(c.ID, name, slot, deviceID) car, err := e.AddCar(c.ID, name, slot, deviceID)
@@ -685,6 +689,9 @@ func handleInput(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service,
if v, ok := payload["gear"].(float64); ok { if v, ok := payload["gear"].(float64); ok {
in.Gear = int(v) in.Gear = int(v)
} }
if v, ok := payload["buttons"].(float64); ok {
in.Buttons = uint32(v)
}
car := e.GetCarByDriver(c.ID) car := e.GetCarByDriver(c.ID)
if car == nil { if car == nil {
return return
@@ -693,21 +700,43 @@ func handleInput(c *realtime.Client, e *control.Engine, lobbySvc *lobby.Service,
// Forward command transitions to ESP32 physical car if car has a device_id assigned // Forward command transitions to ESP32 physical car if car has a device_id assigned
if car.DeviceID != nil { if car.DeviceID != nil {
var cmd string var packet [5]byte
if in.Throttle > 0.1 {
cmd = "start"
} else {
cmd = "stop"
}
if in.Steering < -0.2 {
cmd = "left"
} else if in.Steering > 0.2 {
cmd = "right"
}
if cmd != "" && cmd != c.LastUDPCommand { // 1. Steer: mapping float64 [-1.0, 1.0] to [0..200] (100 is center)
c.LastUDPCommand = cmd steerVal := int(math.Round((in.Steering + 1.0) * 100.0))
_ = videoSvc.SendCommand(uint8(*car.DeviceID), cmd) if steerVal < 0 { steerVal = 0 }
if steerVal > 200 { steerVal = 200 }
packet[0] = uint8(steerVal)
// 2. Throttle: mapping float64 [0.0, 1.0] to [0..100]
throttleVal := int(math.Round(in.Throttle * 100.0))
if throttleVal < 0 { throttleVal = 0 }
if throttleVal > 100 { throttleVal = 100 }
packet[1] = uint8(throttleVal)
// 3. Brake: mapping float64 [0.0, 1.0] to [0..100]
brakeVal := int(math.Round(in.Brake * 100.0))
if brakeVal < 0 { brakeVal = 0 }
if brakeVal > 100 { brakeVal = 100 }
packet[2] = uint8(brakeVal)
// 4. Gear: map -1 to 0 (R), 0 to 1 (N), >=1 to 2 (D)
gearVal := 1 // Neutral by default
if in.Gear < 0 {
gearVal = 0 // R
} else if in.Gear > 0 {
gearVal = 2 // D
}
packet[3] = uint8(gearVal)
// 5. Flags: bit 0 (DRS), bit 1 (Pit Limiter)
packet[4] = uint8(in.Buttons & 0x03)
// Deduplicate UDP transmissions
hexCmd := hex.EncodeToString(packet[:])
if hexCmd != c.LastUDPCommand {
c.LastUDPCommand = hexCmd
_ = videoSvc.SendControlPacket(uint8(*car.DeviceID), packet)
} }
} }
+138 -18
View File
@@ -3,6 +3,7 @@ package main
import ( import (
"bufio" "bufio"
"context" "context"
"encoding/json"
"fmt" "fmt"
"log/slog" "log/slog"
"net" "net"
@@ -172,7 +173,6 @@ func (s *UDPVideoService) Start(ctx context.Context, wg *sync.WaitGroup) {
} }
s.mu.RUnlock() s.mu.RUnlock()
} }
if !hasDevice { if !hasDevice {
s.logger.Warn("cannot send command: no ESP32 devices discovered yet") s.logger.Warn("cannot send command: no ESP32 devices discovered yet")
continue continue
@@ -188,13 +188,12 @@ func (s *UDPVideoService) Start(ctx context.Context, wg *sync.WaitGroup) {
}() }()
} }
// SendCommand sends a command string to the ESP32 representing deviceID. // SendControlPacket sends a 5-byte binary control packet to the ESP32 representing deviceID.
func (s *UDPVideoService) SendCommand(deviceID uint8, cmd string) error { func (s *UDPVideoService) SendControlPacket(deviceID uint8, packet [5]byte) error {
s.mu.RLock() s.mu.RLock()
dev, ok := s.devices[deviceID] dev, ok := s.devices[deviceID]
conn := s.conn conn := s.conn
s.mu.RUnlock() s.mu.RUnlock()
if !ok || dev.addr == nil { if !ok || dev.addr == nil {
return fmt.Errorf("ESP32 device %d address unknown (no video packets received yet)", deviceID) return fmt.Errorf("ESP32 device %d address unknown (no video packets received yet)", deviceID)
} }
@@ -207,10 +206,35 @@ func (s *UDPVideoService) SendCommand(deviceID uint8, cmd string) error {
Port: s.espCmdPort, Port: s.espCmdPort,
} }
_, err := conn.WriteToUDP([]byte(cmd), cmdAddr) _, err := conn.WriteToUDP(packet[:], cmdAddr)
return err return err
} }
// SendCommand sends a command string to the ESP32 representing deviceID by mapping it to a 5-byte packet.
func (s *UDPVideoService) SendCommand(deviceID uint8, cmd string) error {
var packet [5]byte
packet[0] = 100 // Steer: center
packet[1] = 0 // Throttle: 0%
packet[2] = 0 // Brake: 0%
packet[3] = 1 // Gear: Neutral
packet[4] = 0 // Flags: 0
switch cmd {
case "start":
packet[1] = 100 // Throttle: 100%
packet[3] = 2 // Gear: Drive
case "stop":
packet[2] = 100 // Brake: 100%
packet[3] = 1 // Gear: Neutral
case "left":
packet[0] = 0 // Steer: full left
case "right":
packet[0] = 200 // Steer: full right
}
return s.SendControlPacket(deviceID, packet)
}
func (s *UDPVideoService) broadcastFrame(deviceID uint8, frame []byte) { func (s *UDPVideoService) broadcastFrame(deviceID uint8, frame []byte) {
// dev.latestFrame is updated inside the caller's lock (Start loop) to avoid races // dev.latestFrame is updated inside the caller's lock (Start loop) to avoid races
if dev, ok := s.devices[deviceID]; ok { if dev, ok := s.devices[deviceID]; ok {
@@ -328,13 +352,14 @@ func (s *UDPVideoService) StreamHandler() http.HandlerFunc {
// ControlHandler godoc // ControlHandler godoc
// @Summary Send command to ESP32 // @Summary Send command to ESP32
// @Description Sends a text command (e.g. start, stop, left, right) to the ESP32 command port (UDP 8888). // @Description Sends a text command or a JSON control packet to the ESP32 command port (UDP 8888).
// @Tags video // @Tags video
// @Param id query int false "Device ID (0..127)" // @Param id query int false "Device ID (0..127)"
// @Param cmd query string true "Command text" // @Param cmd query string false "Command text (legacy)"
// @Param body body map[string]int false "Control packet JSON (steer, throttle, brake, gear, flags)"
// @Produce json // @Produce json
// @Success 200 {object} map[string]interface{} "Command sent" // @Success 200 {object} map[string]interface{} "Command sent"
// @Failure 400 {string} string "Missing cmd parameter" // @Failure 400 {string} string "Missing parameter or invalid body"
// @Failure 500 {string} string "Internal error" // @Failure 500 {string} string "Internal error"
// @Router /api/video/control [post] // @Router /api/video/control [post]
func (s *UDPVideoService) ControlHandler() http.HandlerFunc { func (s *UDPVideoService) ControlHandler() http.HandlerFunc {
@@ -343,14 +368,6 @@ func (s *UDPVideoService) ControlHandler() http.HandlerFunc {
writeError(w, http.StatusMethodNotAllowed, "method_not_allowed", "Only POST is allowed") writeError(w, http.StatusMethodNotAllowed, "method_not_allowed", "Only POST is allowed")
return return
} }
cmd := r.URL.Query().Get("cmd")
if cmd == "" {
cmd = r.FormValue("cmd")
}
if cmd == "" {
writeError(w, http.StatusBadRequest, "bad_request", "Missing 'cmd' parameter")
return
}
idVal := r.URL.Query().Get("id") idVal := r.URL.Query().Get("id")
if idVal == "" { if idVal == "" {
@@ -366,7 +383,109 @@ func (s *UDPVideoService) ControlHandler() http.HandlerFunc {
} }
} }
err := s.SendCommand(deviceID, cmd) var packet [5]byte
packet[0] = 100 // Steer: center
packet[1] = 0 // Throttle: 0%
packet[2] = 0 // Brake: 0%
packet[3] = 1 // Gear: Neutral
packet[4] = 0 // Flags: 0
isJSON := strings.Contains(r.Header.Get("Content-Type"), "application/json")
var cmdUsed string
if isJSON {
var req struct {
Steer *int `json:"steer"`
Throttle *int `json:"throttle"`
Brake *int `json:"brake"`
Gear *int `json:"gear"`
Flags *int `json:"flags"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "bad_request", "invalid JSON payload")
return
}
if req.Steer != nil {
val := *req.Steer
if val < 0 {
val = 0
}
if val > 200 {
val = 200
}
packet[0] = uint8(val)
}
if req.Throttle != nil {
val := *req.Throttle
if val < 0 {
val = 0
}
if val > 100 {
val = 100
}
packet[1] = uint8(val)
}
if req.Brake != nil {
val := *req.Brake
if val < 0 {
val = 0
}
if val > 100 {
val = 100
}
packet[2] = uint8(val)
}
if req.Gear != nil {
val := *req.Gear
if val < 0 {
val = 0
}
if val > 2 {
val = 2
}
packet[3] = uint8(val)
}
if req.Flags != nil {
val := *req.Flags
if val < 0 {
val = 0
}
if val > 255 {
val = 255
}
packet[4] = uint8(val)
}
cmdUsed = fmt.Sprintf("json(steer=%d,throttle=%d,brake=%d,gear=%d,flags=%d)", packet[0], packet[1], packet[2], packet[3], packet[4])
} else {
cmd := r.URL.Query().Get("cmd")
if cmd == "" {
cmd = r.FormValue("cmd")
}
if cmd == "" {
writeError(w, http.StatusBadRequest, "bad_request", "Missing 'cmd' parameter")
return
}
cmdUsed = cmd
switch cmd {
case "start":
packet[1] = 100
packet[3] = 2
case "stop":
packet[2] = 100
packet[3] = 1
case "left":
packet[0] = 0
case "right":
packet[0] = 200
default:
writeError(w, http.StatusBadRequest, "bad_request", "Unknown command: "+cmd)
return
}
}
err := s.SendControlPacket(deviceID, packet)
if err != nil { if err != nil {
writeError(w, http.StatusInternalServerError, "internal_error", err.Error()) writeError(w, http.StatusInternalServerError, "internal_error", err.Error())
return return
@@ -375,7 +494,8 @@ func (s *UDPVideoService) ControlHandler() http.HandlerFunc {
writeJSON(w, http.StatusOK, map[string]any{ writeJSON(w, http.StatusOK, map[string]any{
"status": "success", "status": "success",
"device_id": deviceID, "device_id": deviceID,
"command": cmd, "command": cmdUsed,
"packet": packet[:],
}) })
} }
} }
+58 -23
View File
@@ -2,13 +2,16 @@ package main
import ( import (
"context" "context"
"encoding/hex"
"encoding/json" "encoding/json"
"log/slog" "log/slog"
"math"
"net/http" "net/http"
"sync" "sync"
"time" "time"
"github.com/pion/webrtc/v4" "github.com/pion/webrtc/v4"
"github.com/x0gp/server/internal/catalog"
"github.com/x0gp/server/internal/control" "github.com/x0gp/server/internal/control"
"github.com/x0gp/server/internal/lobby" "github.com/x0gp/server/internal/lobby"
"github.com/x0gp/server/internal/transport" "github.com/x0gp/server/internal/transport"
@@ -29,16 +32,18 @@ type WebRTCService struct {
engine *control.Engine engine *control.Engine
lobbySvc *lobby.Service lobbySvc *lobby.Service
videoSvc *UDPVideoService videoSvc *UDPVideoService
catalogSvc *catalog.Service
sessions map[string]*driverSession sessions map[string]*driverSession
sessionsMu sync.RWMutex sessionsMu sync.RWMutex
} }
func NewWebRTCService(logger *slog.Logger, e *control.Engine, lobbySvc *lobby.Service, videoSvc *UDPVideoService) *WebRTCService { func NewWebRTCService(logger *slog.Logger, e *control.Engine, lobbySvc *lobby.Service, videoSvc *UDPVideoService, catalogSvc *catalog.Service) *WebRTCService {
return &WebRTCService{ return &WebRTCService{
logger: logger, logger: logger,
engine: e, engine: e,
lobbySvc: lobbySvc, lobbySvc: lobbySvc,
videoSvc: videoSvc, videoSvc: videoSvc,
catalogSvc: catalogSvc,
sessions: make(map[string]*driverSession), sessions: make(map[string]*driverSession),
} }
} }
@@ -91,10 +96,14 @@ func (s *WebRTCService) ConnectHandler() http.HandlerFunc {
// Resolve device ID for this driver // Resolve device ID for this driver
deviceID := uint8(1) // default fallback deviceID := uint8(1) // default fallback
if driver, err := s.lobbySvc.GetDriver(req.DriverID); err == nil && driver.DeviceID != nil { if driver, err := s.lobbySvc.GetDriver(req.DriverID); err == nil && driver.CarID != nil && *driver.CarID != "" {
deviceID = uint8(*driver.DeviceID) if car, ok := s.catalogSvc.GetCar(*driver.CarID); ok && car.DeviceID != nil {
deviceID = uint8(*car.DeviceID)
} else { } else {
s.logger.Warn("webrtc client connected but no physical device_id assigned in lobbySvc. Defaulting to device 1", "driver_id", req.DriverID) s.logger.Warn("webrtc client connected but car has no physical device_id assigned in catalog. Defaulting to device 1", "driver_id", req.DriverID, "car_id", *driver.CarID)
}
} else {
s.logger.Warn("webrtc client connected but no car_id assigned in lobbySvc. Defaulting to device 1", "driver_id", req.DriverID)
} }
// Create PeerConnection // Create PeerConnection
@@ -269,6 +278,10 @@ func (s *WebRTCService) handleDataChannelMessage(session *driverSession, data []
in.Gear = int(v) in.Gear = int(v)
hasInput = true hasInput = true
} }
if v, ok := payload["buttons"].(float64); ok {
in.Buttons = uint32(v)
hasInput = true
}
if hasInput { if hasInput {
s.logger.Debug("received inputs on webrtc data channel", "driver_id", session.driverID, "throttle", in.Throttle, "steering", in.Steering) s.logger.Debug("received inputs on webrtc data channel", "driver_id", session.driverID, "throttle", in.Throttle, "steering", in.Steering)
@@ -277,19 +290,6 @@ func (s *WebRTCService) handleDataChannelMessage(session *driverSession, data []
car.ApplyInput(in, 1.0/60.0) car.ApplyInput(in, 1.0/60.0)
} }
// Send commands to physical car
var cmd string
if in.Throttle > 0.1 {
cmd = "start"
} else {
cmd = "stop"
}
if in.Steering < -0.2 {
cmd = "left"
} else if in.Steering > 0.2 {
cmd = "right"
}
// Resolve destination device // Resolve destination device
var destDeviceID *uint8 var destDeviceID *uint8
if car != nil && car.DeviceID != nil { if car != nil && car.DeviceID != nil {
@@ -300,14 +300,49 @@ func (s *WebRTCService) handleDataChannelMessage(session *driverSession, data []
destDeviceID = &session.deviceID destDeviceID = &session.deviceID
} }
if destDeviceID != nil && cmd != "" && cmd != session.lastCommand { if destDeviceID != nil {
s.logger.Info("webrtc control state transition", "driver_id", session.driverID, "old_cmd", session.lastCommand, "new_cmd", cmd) var packet [5]byte
session.lastCommand = cmd
err := s.videoSvc.SendCommand(*destDeviceID, cmd) // 1. Steer: mapping float64 [-1.0, 1.0] to [0..200] (100 is center)
steerVal := int(math.Round((in.Steering + 1.0) * 100.0))
if steerVal < 0 { steerVal = 0 }
if steerVal > 200 { steerVal = 200 }
packet[0] = uint8(steerVal)
// 2. Throttle: mapping float64 [0.0, 1.0] to [0..100]
throttleVal := int(math.Round(in.Throttle * 100.0))
if throttleVal < 0 { throttleVal = 0 }
if throttleVal > 100 { throttleVal = 100 }
packet[1] = uint8(throttleVal)
// 3. Brake: mapping float64 [0.0, 1.0] to [0..100]
brakeVal := int(math.Round(in.Brake * 100.0))
if brakeVal < 0 { brakeVal = 0 }
if brakeVal > 100 { brakeVal = 100 }
packet[2] = uint8(brakeVal)
// 4. Gear: map -1 to 0 (R), 0 to 1 (N), >=1 to 2 (D)
gearVal := 1 // Neutral by default
if in.Gear < 0 {
gearVal = 0 // R
} else if in.Gear > 0 {
gearVal = 2 // D
}
packet[3] = uint8(gearVal)
// 5. Flags: bit 0 (DRS), bit 1 (Pit Limiter)
packet[4] = uint8(in.Buttons & 0x03)
hexCmd := hex.EncodeToString(packet[:])
if hexCmd != session.lastCommand {
s.logger.Info("webrtc control state transition", "driver_id", session.driverID, "old_hex", session.lastCommand, "new_hex", hexCmd)
session.lastCommand = hexCmd
err := s.videoSvc.SendControlPacket(*destDeviceID, packet)
if err != nil { if err != nil {
s.logger.Error("failed to forward command to ESP32", "device_id", *destDeviceID, "cmd", cmd, "err", err) s.logger.Error("failed to forward control packet to ESP32", "device_id", *destDeviceID, "packet", packet, "err", err)
} else { } else {
s.logger.Info("forwarded command to ESP32 via UDP", "device_id", *destDeviceID, "cmd", cmd) s.logger.Info("forwarded control packet to ESP32 via UDP", "device_id", *destDeviceID, "packet", packet)
}
} }
} }
} }
+22 -6
View File
@@ -948,7 +948,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/drivers/{id}/device": { "/api/drivers/{id}/car": {
"put": { "put": {
"description": "Dispatches on HTTP method. Path ` + "`" + `/api/drivers/by-nick/{nick}` + "`" + ` is a convenience that returns the driver by 3-letter nickname.", "description": "Dispatches on HTTP method. Path ` + "`" + `/api/drivers/by-nick/{nick}` + "`" + ` is a convenience that returns the driver by 3-letter nickname.",
"produces": [ "produces": [
@@ -2003,7 +2003,7 @@ const docTemplate = `{
}, },
"/api/video/control": { "/api/video/control": {
"post": { "post": {
"description": "Sends a text command (e.g. start, stop, left, right) to the ESP32 command port (UDP 8888).", "description": "Sends a text command or a JSON control packet to the ESP32 command port (UDP 8888).",
"produces": [ "produces": [
"application/json" "application/json"
], ],
@@ -2020,10 +2020,20 @@ const docTemplate = `{
}, },
{ {
"type": "string", "type": "string",
"description": "Command text", "description": "Command text (legacy)",
"name": "cmd", "name": "cmd",
"in": "query", "in": "query"
"required": true },
{
"description": "Control packet JSON (steer, throttle, brake, gear, flags)",
"name": "body",
"in": "body",
"schema": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
}
} }
], ],
"responses": { "responses": {
@@ -2035,7 +2045,7 @@ const docTemplate = `{
} }
}, },
"400": { "400": {
"description": "Missing cmd parameter", "description": "Missing parameter or invalid body",
"schema": { "schema": {
"type": "string" "type": "string"
} }
@@ -2232,6 +2242,9 @@ const docTemplate = `{
"color_hex": { "color_hex": {
"type": "string" "type": "string"
}, },
"device_id": {
"type": "integer"
},
"drive": { "drive": {
"type": "string" "type": "string"
}, },
@@ -2299,6 +2312,9 @@ const docTemplate = `{
"created_ms": { "created_ms": {
"type": "integer" "type": "integer"
}, },
"device_id": {
"type": "integer"
},
"drive": { "drive": {
"type": "string" "type": "string"
}, },
+22 -6
View File
@@ -946,7 +946,7 @@
} }
} }
}, },
"/api/drivers/{id}/device": { "/api/drivers/{id}/car": {
"put": { "put": {
"description": "Dispatches on HTTP method. Path `/api/drivers/by-nick/{nick}` is a convenience that returns the driver by 3-letter nickname.", "description": "Dispatches on HTTP method. Path `/api/drivers/by-nick/{nick}` is a convenience that returns the driver by 3-letter nickname.",
"produces": [ "produces": [
@@ -2001,7 +2001,7 @@
}, },
"/api/video/control": { "/api/video/control": {
"post": { "post": {
"description": "Sends a text command (e.g. start, stop, left, right) to the ESP32 command port (UDP 8888).", "description": "Sends a text command or a JSON control packet to the ESP32 command port (UDP 8888).",
"produces": [ "produces": [
"application/json" "application/json"
], ],
@@ -2018,10 +2018,20 @@
}, },
{ {
"type": "string", "type": "string",
"description": "Command text", "description": "Command text (legacy)",
"name": "cmd", "name": "cmd",
"in": "query", "in": "query"
"required": true },
{
"description": "Control packet JSON (steer, throttle, brake, gear, flags)",
"name": "body",
"in": "body",
"schema": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
}
} }
], ],
"responses": { "responses": {
@@ -2033,7 +2043,7 @@
} }
}, },
"400": { "400": {
"description": "Missing cmd parameter", "description": "Missing parameter or invalid body",
"schema": { "schema": {
"type": "string" "type": "string"
} }
@@ -2230,6 +2240,9 @@
"color_hex": { "color_hex": {
"type": "string" "type": "string"
}, },
"device_id": {
"type": "integer"
},
"drive": { "drive": {
"type": "string" "type": "string"
}, },
@@ -2297,6 +2310,9 @@
"created_ms": { "created_ms": {
"type": "integer" "type": "integer"
}, },
"device_id": {
"type": "integer"
},
"drive": { "drive": {
"type": "string" "type": "string"
}, },
+16 -6
View File
@@ -39,6 +39,8 @@ definitions:
$ref: '#/definitions/transport.ChassisWire' $ref: '#/definitions/transport.ChassisWire'
color_hex: color_hex:
type: string type: string
device_id:
type: integer
drive: drive:
type: string type: string
height_mm: height_mm:
@@ -83,6 +85,8 @@ definitions:
type: string type: string
created_ms: created_ms:
type: integer type: integer
device_id:
type: integer
drive: drive:
type: string type: string
height_mm: height_mm:
@@ -1484,7 +1488,7 @@ paths:
summary: Get / update / delete a driver by id summary: Get / update / delete a driver by id
tags: tags:
- drivers - drivers
/api/drivers/{id}/device: /api/drivers/{id}/car:
put: put:
description: Dispatches on HTTP method. Path `/api/drivers/by-nick/{nick}` is description: Dispatches on HTTP method. Path `/api/drivers/by-nick/{nick}` is
a convenience that returns the driver by 3-letter nickname. a convenience that returns the driver by 3-letter nickname.
@@ -2219,18 +2223,24 @@ paths:
- system - system
/api/video/control: /api/video/control:
post: post:
description: Sends a text command (e.g. start, stop, left, right) to the ESP32 description: Sends a text command or a JSON control packet to the ESP32 command
command port (UDP 8888). port (UDP 8888).
parameters: parameters:
- description: Device ID (0..127) - description: Device ID (0..127)
in: query in: query
name: id name: id
type: integer type: integer
- description: Command text - description: Command text (legacy)
in: query in: query
name: cmd name: cmd
required: true
type: string type: string
- description: Control packet JSON (steer, throttle, brake, gear, flags)
in: body
name: body
schema:
additionalProperties:
type: integer
type: object
produces: produces:
- application/json - application/json
responses: responses:
@@ -2240,7 +2250,7 @@ paths:
additionalProperties: true additionalProperties: true
type: object type: object
"400": "400":
description: Missing cmd parameter description: Missing parameter or invalid body
schema: schema:
type: string type: string
"500": "500":
+10
View File
@@ -247,6 +247,7 @@ type CreateCarOptions struct {
ColorHex string ColorHex string
AvatarURL string AvatarURL string
Active *bool // optional; defaults to true Active *bool // optional; defaults to true
DeviceID *int
} }
// Validate sanity-checks dimensions and required fields. // Validate sanity-checks dimensions and required fields.
@@ -319,6 +320,7 @@ func (s *Service) CreateCar(ctx context.Context, opts CreateCarOptions) (CarMeta
ColorHex: opts.ColorHex, ColorHex: opts.ColorHex,
AvatarURL: opts.AvatarURL, AvatarURL: opts.AvatarURL,
Active: active, Active: active,
DeviceID: opts.DeviceID,
CreatedMs: now, CreatedMs: now,
UpdatedMs: now, UpdatedMs: now,
} }
@@ -345,6 +347,7 @@ type UpdateCarOptions struct {
Motor *MotorSpec Motor *MotorSpec
Battery *BatterySpec Battery *BatterySpec
Drive *Drivetrain Drive *Drivetrain
DeviceID *int // double pointer or *int to clear / set? Let's use *int, but to allow setting to nil (e.g. if we pass -1 or use *int), wait, actually, we can support DeviceID **int or *int. Let's use *int for now or wait, if *int is nil, it means do not update. If they want to set to a device ID, they pass a pointer. Wait! What if they want to clear it? They can pass a pointer to a negative value like -1 or we can use a double pointer. Actually, in Go, *int is very simple. Let's make it *int. If we need to clear, we can pass a device ID of -1 and map it to nil. Let's check how the JSON schema handles it. Usually *int is sufficient. Wait, let's use *int.
} }
// UpdateCar applies a partial update. // UpdateCar applies a partial update.
@@ -403,6 +406,13 @@ func (s *Service) UpdateCar(ctx context.Context, id string, opts UpdateCarOption
if opts.Drive != nil { if opts.Drive != nil {
c.Drive = *opts.Drive c.Drive = *opts.Drive
} }
if opts.DeviceID != nil {
if *opts.DeviceID < 0 {
c.DeviceID = nil
} else {
c.DeviceID = opts.DeviceID
}
}
c.UpdatedMs = time.Now().UnixMilli() c.UpdatedMs = time.Now().UnixMilli()
if c.LengthMm < minCarLengthMm || c.LengthMm > maxCarLengthMm || if c.LengthMm < minCarLengthMm || c.LengthMm > maxCarLengthMm ||
+11 -1
View File
@@ -17,13 +17,23 @@ import "math"
// (1/24 scale), power figures are real (full-scale 1.6L V6 hybrid // (1/24 scale), power figures are real (full-scale 1.6L V6 hybrid
// turbo, ~1000 hp combined MGU-K + ICE). // turbo, ~1000 hp combined MGU-K + ICE).
func DefaultTracks() []Track { func DefaultTracks() []Track {
return []Track{ tracks := []Track{
Monaco(), Monaco(),
BarcelonaCatalunya(), BarcelonaCatalunya(),
AustriaRedBullRing(), AustriaRedBullRing(),
GreatBritainSilverstone(), GreatBritainSilverstone(),
BelgiumSpa(), BelgiumSpa(),
} }
for i := range tracks {
for j := range tracks[i].Centerline {
tracks[i].Centerline[j].Y = -tracks[i].Centerline[j].Y
tracks[i].Centerline[j].HeadingRad = -tracks[i].Centerline[j].HeadingRad
}
tracks[i].Bounds = ComputeBounds(tracks[i].Centerline)
tracks[i].LengthM = tracks[i].Bounds.LengthM
tracks[i].WidthM = tracks[i].Bounds.WidthM
}
return tracks
} }
func DefaultCars() []Car { func DefaultCars() []Car {
+1
View File
@@ -146,6 +146,7 @@ type CarMeta struct {
Motor MotorSpec `json:"motor"` Motor MotorSpec `json:"motor"`
Battery BatterySpec `json:"battery"` Battery BatterySpec `json:"battery"`
Drive Drivetrain `json:"drive"` Drive Drivetrain `json:"drive"`
DeviceID *int `json:"device_id,omitempty"` // mapped physical ESP32 device ID
// Performance envelope. // Performance envelope.
TopSpeedMs float64 `json:"top_speed_ms"` TopSpeedMs float64 `json:"top_speed_ms"`
+14 -20
View File
@@ -187,7 +187,7 @@ func (s *Service) RemoveDriver(id string) {
d.Status = DriverStatusOffline d.Status = DriverStatusOffline
d.LastSeenMs = time.Now().UnixMilli() d.LastSeenMs = time.Now().UnixMilli()
d.RaceID = "" d.RaceID = ""
d.DeviceID = nil d.CarID = nil
hook := s.onRaceRemoved hook := s.onRaceRemoved
s.mu.Unlock() s.mu.Unlock()
@@ -244,9 +244,9 @@ func (s *Service) AddDriverToRace(driverID, raceID string) error {
s.mu.Unlock() s.mu.Unlock()
return ErrDriverNotFound return ErrDriverNotFound
} }
if d.DeviceID == nil { if d.CarID == nil || *d.CarID == "" {
s.mu.Unlock() s.mu.Unlock()
return fmt.Errorf("driver %s has no device selected", driverID) return fmt.Errorf("driver %s has no car selected", driverID)
} }
r, ok := s.races[raceID] r, ok := s.races[raceID]
if !ok { if !ok {
@@ -306,7 +306,7 @@ func (s *Service) RemoveDriverFromRace(driverID string) {
} }
d.Status = DriverStatusIdle d.Status = DriverStatusIdle
d.RaceID = "" d.RaceID = ""
d.DeviceID = nil d.CarID = nil
prevRaceID := d.RaceID prevRaceID := d.RaceID
hook := s.onRaceRemoved hook := s.onRaceRemoved
s.mu.Unlock() s.mu.Unlock()
@@ -349,7 +349,7 @@ func (s *Service) SetRaceStatus(raceID string, status RaceStatus) error {
if d, ok := s.drivers[did]; ok { if d, ok := s.drivers[did]; ok {
d.Status = DriverStatusIdle d.Status = DriverStatusIdle
d.RaceID = "" d.RaceID = ""
d.DeviceID = nil d.CarID = nil
affected = append(affected, *d) affected = append(affected, *d)
} }
} }
@@ -454,16 +454,10 @@ func (s *Service) GetDriver(driverID string) (DriverMeta, error) {
return *d, nil return *d, nil
} }
// SelectDevice assigns a physical device ID (0..127) to a driver. // SelectCar assigns a catalog car ID to a driver.
// Pass deviceID = nil to release the device. // If carID is nil, it clears the driver's car assignment.
// Returns an error if the device is already taken by another online driver. // It returns an error if the car is already taken by another active driver.
func (s *Service) SelectDevice(driverID string, deviceID *int) error { func (s *Service) SelectCar(driverID string, carID *string) error {
if deviceID != nil {
if *deviceID < 0 || *deviceID > 127 {
return fmt.Errorf("invalid device ID: must be 0..127")
}
}
s.mu.Lock() s.mu.Lock()
d, ok := s.drivers[driverID] d, ok := s.drivers[driverID]
if !ok { if !ok {
@@ -471,17 +465,17 @@ func (s *Service) SelectDevice(driverID string, deviceID *int) error {
return ErrDriverNotFound return ErrDriverNotFound
} }
// Enforce that device cannot be selected if already assigned to another driver. // Enforce that car cannot be selected if already assigned to another driver.
if deviceID != nil { if carID != nil && *carID != "" {
for otherID, otherD := range s.drivers { for otherID, otherD := range s.drivers {
if otherID != driverID && otherD.Status != DriverStatusOffline && otherD.DeviceID != nil && *otherD.DeviceID == *deviceID { if otherID != driverID && otherD.Status != DriverStatusOffline && otherD.CarID != nil && *otherD.CarID == *carID {
s.mu.Unlock() s.mu.Unlock()
return fmt.Errorf("device %d is already taken by driver %s", *deviceID, otherID) return fmt.Errorf("car %s is already taken by driver %s", *carID, otherID)
} }
} }
} }
d.DeviceID = deviceID d.CarID = carID
out := *d out := *d
s.mu.Unlock() s.mu.Unlock()
+3 -3
View File
@@ -75,9 +75,9 @@ func TestQuickPlayJoinsFirstRace(t *testing.T) {
s := NewService() s := NewService()
_, _ = s.AddDriver("d1", "Alice", "") _, _ = s.AddDriver("d1", "Alice", "")
_, _ = s.AddDriver("d2", "Bob", "") _, _ = s.AddDriver("d2", "Bob", "")
dev1, dev2 := 1, 2 car1, car2 := "car-1", "car-2"
_ = s.SelectDevice("d1", &dev1) _ = s.SelectCar("d1", &car1)
_ = s.SelectDevice("d2", &dev2) _ = s.SelectCar("d2", &car2)
r1, _ := s.QuickPlay("d1", 4) r1, _ := s.QuickPlay("d1", 4)
r2, err := s.QuickPlay("d2", 4) r2, err := s.QuickPlay("d2", 4)
if err != nil { if err != nil {
+1 -1
View File
@@ -65,7 +65,7 @@ type DriverMeta struct {
LastSeenMs int64 `json:"last_seen_ms"` LastSeenMs int64 `json:"last_seen_ms"`
Country string `json:"country,omitempty"` // optional, for UI Country string `json:"country,omitempty"` // optional, for UI
AvatarHue int `json:"avatar_hue,omitempty"` // 0..360, deterministic per id AvatarHue int `json:"avatar_hue,omitempty"` // 0..360, deterministic per id
DeviceID *int `json:"-"` CarID *string `json:"car_id,omitempty"`
} }
// Snapshot is the immutable view broadcast to clients. // Snapshot is the immutable view broadcast to clients.
+6 -6
View File
@@ -294,17 +294,17 @@ func TestLeaderboard(t *testing.T) {
t.Fatalf("expected 3 calendar entries, got %d", len(res)) t.Fatalf("expected 3 calendar entries, got %d", len(res))
} }
// 1. Monaco (finished) // 1. Austria (planned)
if res[0].TrackID != "monaco" || res[0].Status != "finished" { if res[0].TrackID != "austria-redbull-ring" || res[0].Status != "planned" {
t.Errorf("expected monaco (finished), got %s (%s)", res[0].TrackID, res[0].Status) t.Errorf("expected austria-redbull-ring (planned), got %s (%s)", res[0].TrackID, res[0].Status)
} }
// 2. Barcelona (active) // 2. Barcelona (active)
if res[1].TrackID != "barcelona-catalunya" || res[1].Status != "active" { if res[1].TrackID != "barcelona-catalunya" || res[1].Status != "active" {
t.Errorf("expected barcelona-catalunya (active), got %s (%s)", res[1].TrackID, res[1].Status) t.Errorf("expected barcelona-catalunya (active), got %s (%s)", res[1].TrackID, res[1].Status)
} }
// 3. Austria (planned) // 3. Monaco (finished)
if res[2].TrackID != "austria-redbull-ring" || res[2].Status != "planned" { if res[2].TrackID != "monaco" || res[2].Status != "finished" {
t.Errorf("expected austria-redbull-ring (planned), got %s (%s)", res[2].TrackID, res[2].Status) t.Errorf("expected monaco (finished), got %s (%s)", res[2].TrackID, res[2].Status)
} }
}) })
} }
+40 -34
View File
@@ -30,29 +30,34 @@ var DefaultNow = time.Now
var fallbackTracks = []string{"default"} var fallbackTracks = []string{"default"}
var defaultDriverSeeds = []struct { var defaultDriverSeeds = []struct {
id string
nick string nick string
name string name string
avatarURL string
clanID string
createdMs int64
updatedMs int64
}{ }{
{"ACE", "Alice"}, {"driver-seed-001", "BOR", "Gabriel Bortoleto", "https://minio.is1di.ru/x0gp/avatar/gabriel-bortoleto-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584003},
{"BOB", "Bob"}, {"driver-seed-002", "HUL", "Nico Hulkenberg", "https://minio.is1di.ru/x0gp/avatar/nico-hulkenberg-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584007},
{"CAR", "Carol"}, {"driver-seed-003", "ALB", "Alex Albon", "https://minio.is1di.ru/x0gp/avatar/alex-albon-f1-driver-profile-picture.webp", "clan-seed-003", 1784120584003, 1784120584008},
{"DAV", "Dave"}, {"driver-seed-004", "SAI", "Carlos Sainz", "https://minio.is1di.ru/x0gp/avatar/carlos-sainz-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584011},
{"EVE", "Eve"}, {"driver-seed-005", "BEA", "Oliver Bearman", "https://minio.is1di.ru/x0gp/avatar/oliver-bearman-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584012},
{"FRA", "Frank"}, {"driver-seed-006", "OCO", "Esteban Ocon", "https://minio.is1di.ru/x0gp/avatar/esteban-ocon-f1-driver-profile-picture.webp", "clan-seed-003", 1784120584003, 1784120584014},
{"GRA", "Grace"}, {"driver-seed-007", "LIN", "Arvid Lindblad", "https://minio.is1di.ru/x0gp/avatar/arvid-lindblad-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584018},
{"HEI", "Heidi"}, {"driver-seed-008", "LAW", "Liam Lawson", "https://minio.is1di.ru/x0gp/avatar/liam-lawson-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584018},
{"IVY", "Ivy"}, {"driver-seed-009", "COL", "Franco Colapinto", "https://minio.is1di.ru/x0gp/avatar/franco-colapinto-f1-driver-profile-picture.webp", "clan-seed-003", 1784120584003, 1784120584020},
{"JAC", "Jack"}, {"driver-seed-010", "GAS", "Pierre Gasly", "https://minio.is1di.ru/x0gp/avatar/pierre-gasly-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584023},
{"KEN", "Ken"}, {"driver-seed-011", "STR", "Lance Stroll", "https://minio.is1di.ru/x0gp/avatar/lance-stroll-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584023},
{"LEO", "Leo"}, {"driver-seed-012", "ALO", "Fernando Alonso", "https://minio.is1di.ru/x0gp/avatar/fernando-alonso-f1-driver-profile-picture.webp", "clan-seed-003", 1784120584003, 1784120584026},
{"MAX", "Max"}, {"driver-seed-013", "ANT", "Kimi Antonelli", "https://minio.is1di.ru/x0gp/avatar/kimi-antonelli-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584028},
{"NED", "Ned"}, {"driver-seed-014", "RUS", "George Russel", "https://minio.is1di.ru/x0gp/avatar/george-russell-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584028},
{"OLI", "Oliver"}, {"driver-seed-015", "HAD", "Isack Hadjar", "https://minio.is1di.ru/x0gp/avatar/isack-hadjar-f1-driver-profile-picture.webp", "clan-seed-003", 1784120584003, 1784120584031},
{"PEP", "Peggy"}, {"driver-seed-016", "VER", "Max Verstappen", "https://minio.is1di.ru/x0gp/avatar/max-verstappen-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584033},
{"QIN", "Quincy"}, {"driver-seed-017", "HAM", "Lewis Hamilton", "https://minio.is1di.ru/x0gp/avatar/lewis-hamilton-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584034},
{"ROY", "Roy"}, {"driver-seed-018", "NOR", "Lando Norris", "https://minio.is1di.ru/x0gp/avatar/lando-norris-f1-driver-profile-picture.webp", "clan-seed-003", 1784120584003, 1784120584036},
{"SAM", "Sam"}, {"driver-seed-019", "LEC", "Charles Leclerc", "https://minio.is1di.ru/x0gp/avatar/charles-leclerc-f1-driver-profile-picture.webp", "clan-seed-001", 1784120584003, 1784120584038},
{"TED", "Ted"}, {"driver-seed-020", "PIA", "Oscar Piastri", "https://minio.is1di.ru/x0gp/avatar/oscar-piastri-f1-driver-profile-picture.webp", "clan-seed-002", 1784120584003, 1784120584039},
} }
// Default clans. // Default clans.
@@ -353,21 +358,15 @@ func (r *Runner) seedDriversAndClans(ctx context.Context) error {
return fmt.Errorf("count drivers: %w", err) return fmt.Errorf("count drivers: %w", err)
} }
if drvCount == 0 { if drvCount == 0 {
now := time.Now().UnixMilli() for _, ds := range defaultDriverSeeds {
// Round-robin: each driver assigned to one of the seeded clans.
clanIDs := make([]string, 0, len(defaultClanSeeds))
for i := range defaultClanSeeds {
clanIDs = append(clanIDs, fmt.Sprintf("clan-seed-%03d", i+1))
}
for i, ds := range defaultDriverSeeds {
d := drivers.Driver{ d := drivers.Driver{
ID: fmt.Sprintf("driver-seed-%03d", i+1), ID: ds.id,
Nickname: ds.nick, Nickname: ds.nick,
Name: ds.name, Name: ds.name,
AvatarURL: fmt.Sprintf("https://cdn.example.com/drivers/%s.png", ds.nick), AvatarURL: ds.avatarURL,
ClanID: clanIDs[i%len(clanIDs)], ClanID: ds.clanID,
CreatedMs: now, CreatedMs: ds.createdMs,
UpdatedMs: now, UpdatedMs: ds.updatedMs,
} }
if err := r.driversPg.Create(ctx, d); err != nil { if err := r.driversPg.Create(ctx, d); err != nil {
return fmt.Errorf("insert driver %s: %w", ds.nick, err) return fmt.Errorf("insert driver %s: %w", ds.nick, err)
@@ -548,8 +547,15 @@ func (r *Runner) createLive(status lobby.RaceStatus, idx int) (lobby.RaceMeta, e
continue continue
} }
r.lb.SetDriverProfile(d.ID, d.Nickname, "", d.ClanID, d.ClanTag) r.lb.SetDriverProfile(d.ID, d.Nickname, "", d.ClanID, d.ClanTag)
devID := i cars := []string{
_ = r.lb.SelectDevice(d.ID, &devID) "f1-2024-redbull-rb20",
"f1-2024-ferrari-sf24",
"f1-2024-mclaren-mcl38",
"f1-2024-mercedes-w15",
"f1-2024-astonmartin-amr24",
}
carID := cars[i%len(cars)]
_ = r.lb.SelectCar(d.ID, &carID)
if err := r.lb.AddDriverToRace(d.ID, meta.ID); err != nil { if err := r.lb.AddDriverToRace(d.ID, meta.ID); err != nil {
// ignore: race may be at capacity // ignore: race may be at capacity
} }
+2 -2
View File
@@ -62,8 +62,8 @@ func (s *Service) RestoreFromDB(ctx context.Context) (int, int, error) {
// AddDriver+SetDriverProfile and accept a no-op mirror. // AddDriver+SetDriverProfile and accept a no-op mirror.
_, _ = s.lobby.AddDriver(d.ID, d.Name, "") _, _ = s.lobby.AddDriver(d.ID, d.Name, "")
s.lobby.SetDriverProfile(d.ID, d.Nickname, d.AvatarURL, d.ClanID, d.ClanTag) s.lobby.SetDriverProfile(d.ID, d.Nickname, d.AvatarURL, d.ClanID, d.ClanTag)
if d.DeviceID != nil { if d.CarID != nil {
_ = s.lobby.SelectDevice(d.ID, d.DeviceID) _ = s.lobby.SelectCar(d.ID, d.CarID)
} }
} }
for _, r := range races { for _, r := range races {
+5 -5
View File
@@ -391,7 +391,7 @@ func (s *PgStore) UpsertLobbyDriver(ctx context.Context, d lobby.DriverMeta) err
_, err := s.pool.Exec(ctx, ` _, err := s.pool.Exec(ctx, `
INSERT INTO lobby_drivers INSERT INTO lobby_drivers
(driver_id, name, nickname, avatar_url, clan_id, clan_tag, (driver_id, name, nickname, avatar_url, clan_id, clan_tag,
status, current_race_id, connected_ms, last_seen_ms, device_id) status, current_race_id, connected_ms, last_seen_ms, car_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
ON CONFLICT (driver_id) DO UPDATE SET ON CONFLICT (driver_id) DO UPDATE SET
name = EXCLUDED.name, name = EXCLUDED.name,
@@ -402,9 +402,9 @@ func (s *PgStore) UpsertLobbyDriver(ctx context.Context, d lobby.DriverMeta) err
status = EXCLUDED.status, status = EXCLUDED.status,
current_race_id = EXCLUDED.current_race_id, current_race_id = EXCLUDED.current_race_id,
last_seen_ms = EXCLUDED.last_seen_ms, last_seen_ms = EXCLUDED.last_seen_ms,
device_id = EXCLUDED.device_id`, car_id = EXCLUDED.car_id`,
d.ID, d.Name, d.Nickname, d.AvatarURL, d.ClanID, d.ClanTag, d.ID, d.Name, d.Nickname, d.AvatarURL, d.ClanID, d.ClanTag,
string(d.Status), d.RaceID, d.ConnectedMs, d.LastSeenMs, d.DeviceID) string(d.Status), d.RaceID, d.ConnectedMs, d.LastSeenMs, d.CarID)
if err != nil { if err != nil {
return fmt.Errorf("upsert lobby driver %s: %w", d.ID, err) return fmt.Errorf("upsert lobby driver %s: %w", d.ID, err)
} }
@@ -421,7 +421,7 @@ func (s *PgStore) DeleteLobbyDriver(ctx context.Context, driverID string) error
func (s *PgStore) ListLobbyDrivers(ctx context.Context) ([]lobby.DriverMeta, error) { func (s *PgStore) ListLobbyDrivers(ctx context.Context) ([]lobby.DriverMeta, error) {
rows, err := s.pool.Query(ctx, ` rows, err := s.pool.Query(ctx, `
SELECT driver_id, name, nickname, avatar_url, clan_id, clan_tag, SELECT driver_id, name, nickname, avatar_url, clan_id, clan_tag,
status, current_race_id, connected_ms, last_seen_ms, device_id status, current_race_id, connected_ms, last_seen_ms, car_id
FROM lobby_drivers ORDER BY last_seen_ms DESC`) FROM lobby_drivers ORDER BY last_seen_ms DESC`)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -432,7 +432,7 @@ func (s *PgStore) ListLobbyDrivers(ctx context.Context) ([]lobby.DriverMeta, err
var d lobby.DriverMeta var d lobby.DriverMeta
var status string var status string
if err := rows.Scan(&d.ID, &d.Name, &d.Nickname, &d.AvatarURL, &d.ClanID, &d.ClanTag, if err := rows.Scan(&d.ID, &d.Name, &d.Nickname, &d.AvatarURL, &d.ClanID, &d.ClanTag,
&status, &d.RaceID, &d.ConnectedMs, &d.LastSeenMs, &d.DeviceID); err != nil { &status, &d.RaceID, &d.ConnectedMs, &d.LastSeenMs, &d.CarID); err != nil {
return nil, err return nil, err
} }
d.Status = lobby.DriverStatus(status) d.Status = lobby.DriverStatus(status)
@@ -8,81 +8,81 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('monaco', 'Monaco', 'Circuit de Monaco. Narrow street circuit, tight hairpins, no room for error.', 'system', 'system', 27, VALUES ('monaco', 'Monaco', 'Circuit de Monaco. Narrow street circuit, tight hairpins, no room for error.', 'system', 'system', 27,
3.5500000000000003, 1.1, 0.18, 'tile', 0, 'Verstappen', 3.5500000000000003, 1.1, 0.18, 'tile', 0, 'Verstappen',
0.4, 1.4, 3.95, 2.5, 0.4, -2.5, 3.95, -1.4,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 0, 0.4, 2.2, 0, 3.2, 0) VALUES ('monaco', 0, 0.4, -2.2, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 1, 1.1, 2.2, 0, 3, 0) VALUES ('monaco', 1, 1.1, -2.2, -0, 3, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 2, 1.5, 2.05, -0.4, 2.4, 1.2) VALUES ('monaco', 2, 1.5, -2.05, 0.4, 2.4, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 3, 1.7, 1.85, -0.9, 2.2, 1.8) VALUES ('monaco', 3, 1.7, -1.85, 0.9, 2.2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 4, 1.55, 1.55, -1.6, 2, 1.4) VALUES ('monaco', 4, 1.55, -1.55, 1.6, 2, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 5, 1.25, 1.4, -2.4, 2.1, 1.2) VALUES ('monaco', 5, 1.25, -1.4, 2.4, 2.1, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 6, 0.95, 1.55, 3.141592653589793, 1.9, 1.6) VALUES ('monaco', 6, 0.95, -1.55, -3.141592653589793, 1.9, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 7, 0.75, 1.85, 2, 1.8, 2.2) VALUES ('monaco', 7, 0.75, -1.85, -2, 1.8, 2.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 8, 0.95, 2.15, 2.6, 1.8, 2.6) VALUES ('monaco', 8, 0.95, -2.15, -2.6, 1.8, 2.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 9, 1.2, 2.4, -2.8, 2.1, 1.4) VALUES ('monaco', 9, 1.2, -2.4, 2.8, 2.1, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 10, 1.6, 2.5, -3, 2.4, 1) VALUES ('monaco', 10, 1.6, -2.5, 3, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 11, 2.6, 2.5, 0, 3.2, 0) VALUES ('monaco', 11, 2.6, -2.5, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 12, 3.4, 2.5, 0, 3.2, 0) VALUES ('monaco', 12, 3.4, -2.5, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 13, 3.6, 2.25, -0.5, 2.6, 1.5) VALUES ('monaco', 13, 3.6, -2.25, 0.5, 2.6, 1.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 14, 3.55, 1.95, 0.4, 2.6, 1.5) VALUES ('monaco', 14, 3.55, -1.95, -0.4, 2.6, 1.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 15, 3.3, 1.75, 1, 2.3, 1.4) VALUES ('monaco', 15, 3.3, -1.75, -1, 2.3, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 16, 2.95, 1.55, 1.7, 2.1, 1.8) VALUES ('monaco', 16, 2.95, -1.55, -1.7, 2.1, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 17, 2.6, 1.65, 2.6, 2.1, 1.8) VALUES ('monaco', 17, 2.6, -1.65, -2.6, 2.1, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 18, 2.4, 1.9, -2.7, 2.3, 1.4) VALUES ('monaco', 18, 2.4, -1.9, 2.7, 2.3, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 19, 2.4, 2.2, -3, 2.2, 1.6) VALUES ('monaco', 19, 2.4, -2.2, 3, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 20, 2.6, 2.4, 2.8, 2.5, 1) VALUES ('monaco', 20, 2.6, -2.4, -2.8, 2.5, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 21, 3.2, 2.4, 0, 3.2, 0) VALUES ('monaco', 21, 3.2, -2.4, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 22, 3.7, 2.4, 0, 3.2, 0) VALUES ('monaco', 22, 3.7, -2.4, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 23, 3.95, 2.3, -0.3, 2.8, 0.8) VALUES ('monaco', 23, 3.95, -2.3, 0.3, 2.8, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('monaco', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('monaco', 'f1')
@@ -102,93 +102,93 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('barcelona-catalunya', 'Barcelona-Catalunya', 'Circuit de Barcelona-Catalunya. Mix of high-speed corners and technical chicanes.', 'system', 'system', 27, VALUES ('barcelona-catalunya', 'Barcelona-Catalunya', 'Circuit de Barcelona-Catalunya. Mix of high-speed corners and technical chicanes.', 'system', 'system', 27,
3.75, 2.3000000000000003, 0.18, 'tile', 0, 'Verstappen', 3.75, 2.3000000000000003, 0.18, 'tile', 0, 'Verstappen',
0.3, 0.4, 4.05, 2.7, 0.3, -2.7, 4.05, -0.4,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 0, 0.3, 0.4, 0, 4.5, 0) VALUES ('barcelona-catalunya', 0, 0.3, -0.4, -0, 4.5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 1, 1.4, 0.4, 0, 4.5, 0) VALUES ('barcelona-catalunya', 1, 1.4, -0.4, -0, 4.5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 2, 1.7, 0.65, 1.5707963267948966, 2.2, 1.6) VALUES ('barcelona-catalunya', 2, 1.7, -0.65, -1.5707963267948966, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 3, 1.5, 0.95, 3.141592653589793, 2, 2) VALUES ('barcelona-catalunya', 3, 1.5, -0.95, -3.141592653589793, 2, 2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 4, 1.2, 1.1, 3.4415926535897934, 2.6, 1) VALUES ('barcelona-catalunya', 4, 1.2, -1.1, -3.4415926535897934, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 5, 0.95, 1, 4.0415926535897935, 2.6, 1) VALUES ('barcelona-catalunya', 5, 0.95, -1, -4.0415926535897935, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 6, 0.8, 1.2, -1.5707963267948966, 2.4, 1.2) VALUES ('barcelona-catalunya', 6, 0.8, -1.2, 1.5707963267948966, 2.4, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 7, 1.05, 1.5, 0, 3.2, 0.7) VALUES ('barcelona-catalunya', 7, 1.05, -1.5, -0, 3.2, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 8, 1.3, 1.65, 1.5707963267948966, 2.4, 1) VALUES ('barcelona-catalunya', 8, 1.3, -1.65, -1.5707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 9, 1.15, 1.85, 3.141592653589793, 2.4, 1) VALUES ('barcelona-catalunya', 9, 1.15, -1.85, -3.141592653589793, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 10, 1.4, 2, 2.641592653589793, 3, 0.7) VALUES ('barcelona-catalunya', 10, 1.4, -2, -2.641592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 11, 1.7, 2, 2.141592653589793, 3, 0.7) VALUES ('barcelona-catalunya', 11, 1.7, -2, -2.141592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 12, 1.95, 2.2, 1.5707963267948966, 2.8, 0.5) VALUES ('barcelona-catalunya', 12, 1.95, -2.2, -1.5707963267948966, 2.8, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 13, 1.65, 2.5, 0.3, 2.8, 0.5) VALUES ('barcelona-catalunya', 13, 1.65, -2.5, -0.3, 2.8, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 14, 2.2, 2.7, 0.7, 3.2, 0.5) VALUES ('barcelona-catalunya', 14, 2.2, -2.7, -0.7, 3.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 15, 2.8, 2.7, 1.1, 3.4, 0.5) VALUES ('barcelona-catalunya', 15, 2.8, -2.7, -1.1, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 16, 3.1, 2.5, 1.9707963267948967, 2.2, 1.4) VALUES ('barcelona-catalunya', 16, 3.1, -2.5, -1.9707963267948967, 2.2, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 17, 2.95, 2.2, 3.541592653589793, 2.2, 1.4) VALUES ('barcelona-catalunya', 17, 2.95, -2.2, -3.541592653589793, 2.2, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 18, 3.3, 1.9, 0, 4, 0) VALUES ('barcelona-catalunya', 18, 3.3, -1.9, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 19, 4, 1.9, 0, 4, 0) VALUES ('barcelona-catalunya', 19, 4, -1.9, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 20, 4.05, 1.6, -1.5707963267948966, 2.4, 1.4) VALUES ('barcelona-catalunya', 20, 4.05, -1.6, 1.5707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 21, 3.8, 1.4, 3.141592653589793, 2.4, 1.4) VALUES ('barcelona-catalunya', 21, 3.8, -1.4, -3.141592653589793, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 22, 3.5, 1.5, 3.9269908169872414, 2.6, 1) VALUES ('barcelona-catalunya', 22, 3.5, -1.5, -3.9269908169872414, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 23, 3.1, 1.25, -1.9707963267948967, 3, 0.7) VALUES ('barcelona-catalunya', 23, 3.1, -1.25, 1.9707963267948967, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 24, 2.7, 1, -2.4707963267948965, 3, 0.7) VALUES ('barcelona-catalunya', 24, 2.7, -1, 2.4707963267948965, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 25, 2.3, 0.7, 3.541592653589793, 3.4, 0.5) VALUES ('barcelona-catalunya', 25, 2.3, -0.7, -3.541592653589793, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 26, 1.6, 0.5, 3.3415926535897933, 3.6, 0.4) VALUES ('barcelona-catalunya', 26, 1.6, -0.5, -3.3415926535897933, 3.6, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 27, 0.9, 0.42, 0, 4, 0) VALUES ('barcelona-catalunya', 27, 0.9, -0.42, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('barcelona-catalunya', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('barcelona-catalunya', 'f1')
@@ -206,84 +206,84 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('austria-redbull-ring', 'Austria (Red Bull Ring)', 'Red Bull Ring. Short, fast, three straights separated by hairpins.', 'system', 'system', 27, VALUES ('austria-redbull-ring', 'Austria (Red Bull Ring)', 'Red Bull Ring. Short, fast, three straights separated by hairpins.', 'system', 'system', 27,
3.5500000000000003, 2, 0.18, 'wood', 0, 'Verstappen', 3.5500000000000003, 2, 0.18, 'wood', 0, 'Verstappen',
0.3, 0.4, 3.85, 2.4, 0.3, -2.4, 3.85, -0.4,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 0, 0.3, 0.4, 0, 4.8, 0) VALUES ('austria-redbull-ring', 0, 0.3, -0.4, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 1, 1.6, 0.4, 0, 4.8, 0) VALUES ('austria-redbull-ring', 1, 1.6, -0.4, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 2, 1.85, 0.65, 1.5707963267948966, 2, 1.8) VALUES ('austria-redbull-ring', 2, 1.85, -0.65, -1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 3, 1.6, 0.95, 3.141592653589793, 2, 1.8) VALUES ('austria-redbull-ring', 3, 1.6, -0.95, -3.141592653589793, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 4, 1.3, 1, 3.641592653589793, 3, 0.7) VALUES ('austria-redbull-ring', 4, 1.3, -1, -3.641592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 5, 1.05, 1.2, -1.5707963267948966, 2.6, 1) VALUES ('austria-redbull-ring', 5, 1.05, -1.2, 1.5707963267948966, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 6, 1.4, 1.4, 0, 3.2, 0.5) VALUES ('austria-redbull-ring', 6, 1.4, -1.4, -0, 3.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 7, 1.85, 1.4, 1.7707963267948965, 3.2, 0.5) VALUES ('austria-redbull-ring', 7, 1.85, -1.4, -1.7707963267948965, 3.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 8, 2.1, 1.65, 3.141592653589793, 3, 0.7) VALUES ('austria-redbull-ring', 8, 2.1, -1.65, -3.141592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 9, 2, 1.85, -1.5707963267948966, 3, 0.7) VALUES ('austria-redbull-ring', 9, 2, -1.85, 1.5707963267948966, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 10, 2.25, 2.05, 0, 2, 1.8) VALUES ('austria-redbull-ring', 10, 2.25, -2.05, -0, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 11, 2.4, 2, 1.5707963267948966, 2, 1.8) VALUES ('austria-redbull-ring', 11, 2.4, -2, -1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 12, 2.4, 2.2, 3.141592653589793, 2, 1.8) VALUES ('austria-redbull-ring', 12, 2.4, -2.2, -3.141592653589793, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 13, 2.2, 2.3, -1.5707963267948966, 2, 1.8) VALUES ('austria-redbull-ring', 13, 2.2, -2.3, 1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 14, 2.55, 2.4, -0.2, 3.4, 0.4) VALUES ('austria-redbull-ring', 14, 2.55, -2.4, 0.2, 3.4, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 15, 3, 2.4, 0, 4, 0) VALUES ('austria-redbull-ring', 15, 3, -2.4, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 16, 3.5, 2.4, 0, 4.5, 0) VALUES ('austria-redbull-ring', 16, 3.5, -2.4, -0, 4.5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 17, 3.85, 2.15, 1.7707963267948965, 3.4, 0.6) VALUES ('austria-redbull-ring', 17, 3.85, -2.15, -1.7707963267948965, 3.4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 18, 3.6, 1.8, 3.141592653589793, 3, 0.8) VALUES ('austria-redbull-ring', 18, 3.6, -1.8, -3.141592653589793, 3, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 19, 3.25, 1.85, 3.741592653589793, 3, 0.8) VALUES ('austria-redbull-ring', 19, 3.25, -1.85, -3.741592653589793, 3, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 20, 3, 1.6, -1.9707963267948967, 3.2, 0.6) VALUES ('austria-redbull-ring', 20, 3, -1.6, 1.9707963267948967, 3.2, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 21, 2.6, 1.4, -3.141592653589793, 3.4, 0.5) VALUES ('austria-redbull-ring', 21, 2.6, -1.4, 3.141592653589793, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 22, 2, 1.2, 2.641592653589793, 3.6, 0.4) VALUES ('austria-redbull-ring', 22, 2, -1.2, -2.641592653589793, 3.6, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 23, 1.4, 0.8, 2.9415926535897934, 3.8, 0.3) VALUES ('austria-redbull-ring', 23, 1.4, -0.8, -2.9415926535897934, 3.8, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 24, 0.8, 0.5, 0, 4.2, 0.2) VALUES ('austria-redbull-ring', 24, 0.8, -0.5, -0, 4.2, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('austria-redbull-ring', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('austria-redbull-ring', 'f1')
@@ -300,79 +300,100 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
bounds_min_x, bounds_min_y, bounds_max_x, bounds_max_y, bounds_min_x, bounds_min_y, bounds_max_x, bounds_max_y,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('great-britain-silverstone', 'Great Britain (Silverstone)', 'Silverstone Circuit. Fast, flowing corners; home of British motorsport.', 'system', 'system', 27, VALUES ('great-britain-silverstone', 'Great Britain (Silverstone)', 'Silverstone Circuit. Fast, flowing corners; home of British motorsport.', 'system', 'system', 27,
3.5500000000000003, 1.2499999999999998, 0.18, 'carpet', 0, 'Hamilton', 3.5500000000000003, 2.4, 0.18, 'carpet', 0, 'Hamilton',
0.3, 1.8, 3.85, 3.05, 0.3, -2.65, 3.85, -0.25,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 0, 0.3, 2.8, 0, 5, 0) VALUES ('great-britain-silverstone', 0, 0.3, -0.3, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 1, 2.4, 2.8, 0, 5, 0) VALUES ('great-britain-silverstone', 1, 2.4, -0.3, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 2, 2.8, 2.65, -1.5707963267948966, 3, 0.8) VALUES ('great-britain-silverstone', 2, 2.8, -0.45, -1.5707963267948966, 3, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 3, 2.6, 2.3, -3.141592653589793, 3.4, 0.6) VALUES ('great-britain-silverstone', 3, 2.6, -0.8, -3.141592653589793, 3.4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 4, 2.95, 2.05, -2.0707963267948966, 3.2, 0.7) VALUES ('great-britain-silverstone', 4, 2.95, -1.05, -2.0707963267948966, 3.2, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 5, 3.3, 1.8, 0, 2.2, 1.6) VALUES ('great-britain-silverstone', 5, 3.3, -1.3, -0, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 6, 3.6, 1.95, 1.5707963267948966, 2.2, 1.6) VALUES ('great-britain-silverstone', 6, 3.6, -1.15, 1.5707963267948966, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 7, 3.6, 2.3, 3.141592653589793, 3, 0.7) VALUES ('great-britain-silverstone', 7, 3.6, -0.8, 3.141592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 8, 3.85, 2.55, 1.5707963267948966, 2.6, 1) VALUES ('great-britain-silverstone', 8, 3.85, -0.55, 1.5707963267948966, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 9, 3.55, 2.85, 0, 2.4, 1) VALUES ('great-britain-silverstone', 9, 3.55, -0.25, -0, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 10, 3.25, 2.85, 1.5707963267948966, 2.4, 1) VALUES ('great-britain-silverstone', 10, 3.25, -0.25, -1.5707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 11, 3.05, 2.55, -1.8707963267948966, 3.4, 0.5) VALUES ('great-britain-silverstone', 11, 3.05, -0.55, -1.8707963267948966, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 12, 2.85, 2.65, -3.141592653589793, 4, 0.3) VALUES ('great-britain-silverstone', 12, 2.85, -0.45, -3.141592653589793, 4, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 13, 1.8, 2.8, 0, 4.6, 0) VALUES ('great-britain-silverstone', 13, 1.8, -0.3, -0, 4.6, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 14, 1.2, 2.95, 1.7707963267948965, 3.8, 0.4) VALUES ('great-britain-silverstone', 14, 1.2, -0.45, 1.7707963267948965, 3.8, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 15, 1, 2.65, 3.541592653589793, 3.6, 0.5) VALUES ('great-britain-silverstone', 15, 1, -0.85, 3.541592653589793, 3.6, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 16, 0.7, 2.4, -1.8707963267948966, 2.4, 1.2) VALUES ('great-britain-silverstone', 16, 0.7, -1.15, -1.8707963267948966, 2.4, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 17, 0.5, 2.6, 0, 2.6, 0.9) VALUES ('great-britain-silverstone', 17, 0.5, -0.9, -0, 2.6, 0.9)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 18, 0.7, 2.85, 1.5707963267948966, 3, 0.7) VALUES ('great-britain-silverstone', 18, 0.7, -0.65, 1.5707963267948966, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 19, 0.45, 3.05, 3.541592653589793, 2.6, 1) VALUES ('great-britain-silverstone', 19, 0.45, -0.45, 3.541592653589793, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 20, 0.7, 2.5, -1.1707963267948966, 2.4, 1) VALUES ('great-britain-silverstone', 20, 0.75, -1, -1.1707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 21, 0.5, 2.05, 3.541592653589793, 2.6, 0.8) VALUES ('great-britain-silverstone', 21, 0.5, -1.5, 3.541592653589793, 2.6, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 22, 0.3, 2.4, 1.5707963267948966, 2.4, 1) VALUES ('great-britain-silverstone', 22, 0.3, -1.15, 1.5707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 23, 0.7, -1.6, -0.7853981633974483, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 24, 2, -1.95, -1.9707963267948967, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 25, 3, -2.4, -3.3415926535897933, 3.4, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 26, 2.4, -2.65, 1.8707963267948966, 4, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 27, 1.4, -2.6, 3.141592653589793, 4.4, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 28, 0.5, -2.3, 2.8415926535897933, 4.8, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 29, 0.3, -1.7, 1.2707963267948965, 5, 0.1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('great-britain-silverstone', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('great-britain-silverstone', 'f1')
@@ -390,84 +411,84 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('belgium-spa', 'Belgium (Spa-Francorchamps)', 'Spa-Francorchamps. Long, fast, legendary Eau Rouge / Raidillon.', 'system', 'system', 27, VALUES ('belgium-spa', 'Belgium (Spa-Francorchamps)', 'Spa-Francorchamps. Long, fast, legendary Eau Rouge / Raidillon.', 'system', 'system', 27,
3.85, 2.25, 0.18, 'carpet', 0, 'Verstappen', 3.85, 2.25, 0.18, 'carpet', 0, 'Verstappen',
0.4, 0.5, 4.25, 2.75, 0.4, -2.75, 4.25, -0.5,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 0, 0.4, 0.5, 0, 4.8, 0) VALUES ('belgium-spa', 0, 0.4, -0.5, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 1, 1.6, 0.5, 0, 4.8, 0) VALUES ('belgium-spa', 1, 1.6, -0.5, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 2, 1.95, 0.6, 0.3, 4.2, 0.5) VALUES ('belgium-spa', 2, 1.95, -0.6, -0.3, 4.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 3, 2.2, 0.95, 0.9, 4, 0.6) VALUES ('belgium-spa', 3, 2.2, -0.95, -0.9, 4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 4, 2.1, 1.3, 3.541592653589793, 4, 0.6) VALUES ('belgium-spa', 4, 2.1, -1.3, -3.541592653589793, 4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 5, 2.7, 1.5, 0, 5, 0) VALUES ('belgium-spa', 5, 2.7, -1.5, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 6, 3.5, 1.5, 0, 5, 0) VALUES ('belgium-spa', 6, 3.5, -1.5, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 7, 3.85, 1.3, -1.5707963267948966, 2.4, 1.4) VALUES ('belgium-spa', 7, 3.85, -1.3, 1.5707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 8, 3.6, 1.1, 3.4415926535897934, 2.6, 1.2) VALUES ('belgium-spa', 8, 3.6, -1.1, -3.4415926535897934, 2.6, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 9, 3.3, 1.25, 4.0415926535897935, 2.6, 1.2) VALUES ('belgium-spa', 9, 3.3, -1.25, -4.0415926535897935, 2.6, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 10, 3.5, 1.55, 1.5707963267948966, 3.6, 0.4) VALUES ('belgium-spa', 10, 3.5, -1.55, -1.5707963267948966, 3.6, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 11, 3.25, 1.85, 0, 2.2, 1.6) VALUES ('belgium-spa', 11, 3.25, -1.85, -0, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 12, 3.05, 1.7, -1.5707963267948966, 2.4, 1.4) VALUES ('belgium-spa', 12, 3.05, -1.7, 1.5707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 13, 3.25, 1.5, 0, 3, 0.7) VALUES ('belgium-spa', 13, 3.25, -1.5, -0, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 14, 3.7, 1.65, 1.8707963267948966, 3.4, 0.5) VALUES ('belgium-spa', 14, 3.7, -1.65, -1.8707963267948966, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 15, 4.1, 2, 2.1707963267948966, 4, 0.3) VALUES ('belgium-spa', 15, 4.1, -2, -2.1707963267948966, 4, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 16, 4.25, 2.4, 3.541592653589793, 4.6, 0.3) VALUES ('belgium-spa', 16, 4.25, -2.4, -3.541592653589793, 4.6, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 17, 4, 2.7, -1.8707963267948966, 2.4, 1.4) VALUES ('belgium-spa', 17, 4, -2.7, 1.8707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 18, 3.7, 2.55, 3.141592653589793, 2.4, 1.4) VALUES ('belgium-spa', 18, 3.7, -2.55, -3.141592653589793, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 19, 3.55, 2.75, 3.8415926535897933, 2.4, 1.4) VALUES ('belgium-spa', 19, 3.55, -2.75, -3.8415926535897933, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 20, 3.05, 2.7, -1.5707963267948966, 2, 1.8) VALUES ('belgium-spa', 20, 3.05, -2.7, 1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 21, 2.85, 2.45, 0, 2, 1.8) VALUES ('belgium-spa', 21, 2.85, -2.45, -0, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 22, 2, 2.2, 2.8415926535897933, 3.6, 0.3) VALUES ('belgium-spa', 22, 2, -2.2, -2.8415926535897933, 3.6, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 23, 1.2, 1.6, 2.541592653589793, 4, 0.2) VALUES ('belgium-spa', 23, 1.2, -1.6, -2.541592653589793, 4, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 24, 0.6, 1.05, 2.8415926535897933, 4.4, 0.2) VALUES ('belgium-spa', 24, 0.6, -1.05, -2.8415926535897933, 4.4, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('belgium-spa', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('belgium-spa', 'f1')
@@ -14,81 +14,81 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('monaco', 'Monaco', 'Circuit de Monaco. Narrow street circuit, tight hairpins, no room for error.', 'system', 'system', 27, VALUES ('monaco', 'Monaco', 'Circuit de Monaco. Narrow street circuit, tight hairpins, no room for error.', 'system', 'system', 27,
3.5500000000000003, 1.1, 0.18, 'tile', 0, 'Verstappen', 3.5500000000000003, 1.1, 0.18, 'tile', 0, 'Verstappen',
0.4, 1.4, 3.95, 2.5, 0.4, -2.5, 3.95, -1.4,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 0, 0.4, 2.2, 0, 3.2, 0) VALUES ('monaco', 0, 0.4, -2.2, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 1, 1.1, 2.2, 0, 3, 0) VALUES ('monaco', 1, 1.1, -2.2, -0, 3, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 2, 1.5, 2.05, -0.4, 2.4, 1.2) VALUES ('monaco', 2, 1.5, -2.05, 0.4, 2.4, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 3, 1.7, 1.85, -0.9, 2.2, 1.8) VALUES ('monaco', 3, 1.7, -1.85, 0.9, 2.2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 4, 1.55, 1.55, -1.6, 2, 1.4) VALUES ('monaco', 4, 1.55, -1.55, 1.6, 2, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 5, 1.25, 1.4, -2.4, 2.1, 1.2) VALUES ('monaco', 5, 1.25, -1.4, 2.4, 2.1, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 6, 0.95, 1.55, 3.141592653589793, 1.9, 1.6) VALUES ('monaco', 6, 0.95, -1.55, -3.141592653589793, 1.9, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 7, 0.75, 1.85, 2, 1.8, 2.2) VALUES ('monaco', 7, 0.75, -1.85, -2, 1.8, 2.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 8, 0.95, 2.15, 2.6, 1.8, 2.6) VALUES ('monaco', 8, 0.95, -2.15, -2.6, 1.8, 2.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 9, 1.2, 2.4, -2.8, 2.1, 1.4) VALUES ('monaco', 9, 1.2, -2.4, 2.8, 2.1, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 10, 1.6, 2.5, -3, 2.4, 1) VALUES ('monaco', 10, 1.6, -2.5, 3, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 11, 2.6, 2.5, 0, 3.2, 0) VALUES ('monaco', 11, 2.6, -2.5, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 12, 3.4, 2.5, 0, 3.2, 0) VALUES ('monaco', 12, 3.4, -2.5, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 13, 3.6, 2.25, -0.5, 2.6, 1.5) VALUES ('monaco', 13, 3.6, -2.25, 0.5, 2.6, 1.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 14, 3.55, 1.95, 0.4, 2.6, 1.5) VALUES ('monaco', 14, 3.55, -1.95, -0.4, 2.6, 1.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 15, 3.3, 1.75, 1, 2.3, 1.4) VALUES ('monaco', 15, 3.3, -1.75, -1, 2.3, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 16, 2.95, 1.55, 1.7, 2.1, 1.8) VALUES ('monaco', 16, 2.95, -1.55, -1.7, 2.1, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 17, 2.6, 1.65, 2.6, 2.1, 1.8) VALUES ('monaco', 17, 2.6, -1.65, -2.6, 2.1, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 18, 2.4, 1.9, -2.7, 2.3, 1.4) VALUES ('monaco', 18, 2.4, -1.9, 2.7, 2.3, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 19, 2.4, 2.2, -3, 2.2, 1.6) VALUES ('monaco', 19, 2.4, -2.2, 3, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 20, 2.6, 2.4, 2.8, 2.5, 1) VALUES ('monaco', 20, 2.6, -2.4, -2.8, 2.5, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 21, 3.2, 2.4, 0, 3.2, 0) VALUES ('monaco', 21, 3.2, -2.4, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 22, 3.7, 2.4, 0, 3.2, 0) VALUES ('monaco', 22, 3.7, -2.4, -0, 3.2, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('monaco', 23, 3.95, 2.3, -0.3, 2.8, 0.8) VALUES ('monaco', 23, 3.95, -2.3, 0.3, 2.8, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('monaco', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('monaco', 'f1')
@@ -108,93 +108,93 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('barcelona-catalunya', 'Barcelona-Catalunya', 'Circuit de Barcelona-Catalunya. Mix of high-speed corners and technical chicanes.', 'system', 'system', 27, VALUES ('barcelona-catalunya', 'Barcelona-Catalunya', 'Circuit de Barcelona-Catalunya. Mix of high-speed corners and technical chicanes.', 'system', 'system', 27,
3.75, 2.3000000000000003, 0.18, 'tile', 0, 'Verstappen', 3.75, 2.3000000000000003, 0.18, 'tile', 0, 'Verstappen',
0.3, 0.4, 4.05, 2.7, 0.3, -2.7, 4.05, -0.4,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 0, 0.3, 0.4, 0, 4.5, 0) VALUES ('barcelona-catalunya', 0, 0.3, -0.4, -0, 4.5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 1, 1.4, 0.4, 0, 4.5, 0) VALUES ('barcelona-catalunya', 1, 1.4, -0.4, -0, 4.5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 2, 1.7, 0.65, 1.5707963267948966, 2.2, 1.6) VALUES ('barcelona-catalunya', 2, 1.7, -0.65, -1.5707963267948966, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 3, 1.5, 0.95, 3.141592653589793, 2, 2) VALUES ('barcelona-catalunya', 3, 1.5, -0.95, -3.141592653589793, 2, 2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 4, 1.2, 1.1, 3.4415926535897934, 2.6, 1) VALUES ('barcelona-catalunya', 4, 1.2, -1.1, -3.4415926535897934, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 5, 0.95, 1, 4.0415926535897935, 2.6, 1) VALUES ('barcelona-catalunya', 5, 0.95, -1, -4.0415926535897935, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 6, 0.8, 1.2, -1.5707963267948966, 2.4, 1.2) VALUES ('barcelona-catalunya', 6, 0.8, -1.2, 1.5707963267948966, 2.4, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 7, 1.05, 1.5, 0, 3.2, 0.7) VALUES ('barcelona-catalunya', 7, 1.05, -1.5, -0, 3.2, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 8, 1.3, 1.65, 1.5707963267948966, 2.4, 1) VALUES ('barcelona-catalunya', 8, 1.3, -1.65, -1.5707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 9, 1.15, 1.85, 3.141592653589793, 2.4, 1) VALUES ('barcelona-catalunya', 9, 1.15, -1.85, -3.141592653589793, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 10, 1.4, 2, 2.641592653589793, 3, 0.7) VALUES ('barcelona-catalunya', 10, 1.4, -2, -2.641592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 11, 1.7, 2, 2.141592653589793, 3, 0.7) VALUES ('barcelona-catalunya', 11, 1.7, -2, -2.141592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 12, 1.95, 2.2, 1.5707963267948966, 2.8, 0.5) VALUES ('barcelona-catalunya', 12, 1.95, -2.2, -1.5707963267948966, 2.8, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 13, 1.65, 2.5, 0.3, 2.8, 0.5) VALUES ('barcelona-catalunya', 13, 1.65, -2.5, -0.3, 2.8, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 14, 2.2, 2.7, 0.7, 3.2, 0.5) VALUES ('barcelona-catalunya', 14, 2.2, -2.7, -0.7, 3.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 15, 2.8, 2.7, 1.1, 3.4, 0.5) VALUES ('barcelona-catalunya', 15, 2.8, -2.7, -1.1, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 16, 3.1, 2.5, 1.9707963267948967, 2.2, 1.4) VALUES ('barcelona-catalunya', 16, 3.1, -2.5, -1.9707963267948967, 2.2, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 17, 2.95, 2.2, 3.541592653589793, 2.2, 1.4) VALUES ('barcelona-catalunya', 17, 2.95, -2.2, -3.541592653589793, 2.2, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 18, 3.3, 1.9, 0, 4, 0) VALUES ('barcelona-catalunya', 18, 3.3, -1.9, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 19, 4, 1.9, 0, 4, 0) VALUES ('barcelona-catalunya', 19, 4, -1.9, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 20, 4.05, 1.6, -1.5707963267948966, 2.4, 1.4) VALUES ('barcelona-catalunya', 20, 4.05, -1.6, 1.5707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 21, 3.8, 1.4, 3.141592653589793, 2.4, 1.4) VALUES ('barcelona-catalunya', 21, 3.8, -1.4, -3.141592653589793, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 22, 3.5, 1.5, 3.9269908169872414, 2.6, 1) VALUES ('barcelona-catalunya', 22, 3.5, -1.5, -3.9269908169872414, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 23, 3.1, 1.25, -1.9707963267948967, 3, 0.7) VALUES ('barcelona-catalunya', 23, 3.1, -1.25, 1.9707963267948967, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 24, 2.7, 1, -2.4707963267948965, 3, 0.7) VALUES ('barcelona-catalunya', 24, 2.7, -1, 2.4707963267948965, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 25, 2.3, 0.7, 3.541592653589793, 3.4, 0.5) VALUES ('barcelona-catalunya', 25, 2.3, -0.7, -3.541592653589793, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 26, 1.6, 0.5, 3.3415926535897933, 3.6, 0.4) VALUES ('barcelona-catalunya', 26, 1.6, -0.5, -3.3415926535897933, 3.6, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('barcelona-catalunya', 27, 0.9, 0.42, 0, 4, 0) VALUES ('barcelona-catalunya', 27, 0.9, -0.42, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('barcelona-catalunya', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('barcelona-catalunya', 'f1')
@@ -212,84 +212,84 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('austria-redbull-ring', 'Austria (Red Bull Ring)', 'Red Bull Ring. Short, fast, three straights separated by hairpins.', 'system', 'system', 27, VALUES ('austria-redbull-ring', 'Austria (Red Bull Ring)', 'Red Bull Ring. Short, fast, three straights separated by hairpins.', 'system', 'system', 27,
3.5500000000000003, 2, 0.18, 'wood', 0, 'Verstappen', 3.5500000000000003, 2, 0.18, 'wood', 0, 'Verstappen',
0.3, 0.4, 3.85, 2.4, 0.3, -2.4, 3.85, -0.4,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 0, 0.3, 0.4, 0, 4.8, 0) VALUES ('austria-redbull-ring', 0, 0.3, -0.4, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 1, 1.6, 0.4, 0, 4.8, 0) VALUES ('austria-redbull-ring', 1, 1.6, -0.4, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 2, 1.85, 0.65, 1.5707963267948966, 2, 1.8) VALUES ('austria-redbull-ring', 2, 1.85, -0.65, -1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 3, 1.6, 0.95, 3.141592653589793, 2, 1.8) VALUES ('austria-redbull-ring', 3, 1.6, -0.95, -3.141592653589793, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 4, 1.3, 1, 3.641592653589793, 3, 0.7) VALUES ('austria-redbull-ring', 4, 1.3, -1, -3.641592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 5, 1.05, 1.2, -1.5707963267948966, 2.6, 1) VALUES ('austria-redbull-ring', 5, 1.05, -1.2, 1.5707963267948966, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 6, 1.4, 1.4, 0, 3.2, 0.5) VALUES ('austria-redbull-ring', 6, 1.4, -1.4, -0, 3.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 7, 1.85, 1.4, 1.7707963267948965, 3.2, 0.5) VALUES ('austria-redbull-ring', 7, 1.85, -1.4, -1.7707963267948965, 3.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 8, 2.1, 1.65, 3.141592653589793, 3, 0.7) VALUES ('austria-redbull-ring', 8, 2.1, -1.65, -3.141592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 9, 2, 1.85, -1.5707963267948966, 3, 0.7) VALUES ('austria-redbull-ring', 9, 2, -1.85, 1.5707963267948966, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 10, 2.25, 2.05, 0, 2, 1.8) VALUES ('austria-redbull-ring', 10, 2.25, -2.05, -0, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 11, 2.4, 2, 1.5707963267948966, 2, 1.8) VALUES ('austria-redbull-ring', 11, 2.4, -2, -1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 12, 2.4, 2.2, 3.141592653589793, 2, 1.8) VALUES ('austria-redbull-ring', 12, 2.4, -2.2, -3.141592653589793, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 13, 2.2, 2.3, -1.5707963267948966, 2, 1.8) VALUES ('austria-redbull-ring', 13, 2.2, -2.3, 1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 14, 2.55, 2.4, -0.2, 3.4, 0.4) VALUES ('austria-redbull-ring', 14, 2.55, -2.4, 0.2, 3.4, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 15, 3, 2.4, 0, 4, 0) VALUES ('austria-redbull-ring', 15, 3, -2.4, -0, 4, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 16, 3.5, 2.4, 0, 4.5, 0) VALUES ('austria-redbull-ring', 16, 3.5, -2.4, -0, 4.5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 17, 3.85, 2.15, 1.7707963267948965, 3.4, 0.6) VALUES ('austria-redbull-ring', 17, 3.85, -2.15, -1.7707963267948965, 3.4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 18, 3.6, 1.8, 3.141592653589793, 3, 0.8) VALUES ('austria-redbull-ring', 18, 3.6, -1.8, -3.141592653589793, 3, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 19, 3.25, 1.85, 3.741592653589793, 3, 0.8) VALUES ('austria-redbull-ring', 19, 3.25, -1.85, -3.741592653589793, 3, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 20, 3, 1.6, -1.9707963267948967, 3.2, 0.6) VALUES ('austria-redbull-ring', 20, 3, -1.6, 1.9707963267948967, 3.2, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 21, 2.6, 1.4, -3.141592653589793, 3.4, 0.5) VALUES ('austria-redbull-ring', 21, 2.6, -1.4, 3.141592653589793, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 22, 2, 1.2, 2.641592653589793, 3.6, 0.4) VALUES ('austria-redbull-ring', 22, 2, -1.2, -2.641592653589793, 3.6, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 23, 1.4, 0.8, 2.9415926535897934, 3.8, 0.3) VALUES ('austria-redbull-ring', 23, 1.4, -0.8, -2.9415926535897934, 3.8, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('austria-redbull-ring', 24, 0.8, 0.5, 0, 4.2, 0.2) VALUES ('austria-redbull-ring', 24, 0.8, -0.5, -0, 4.2, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('austria-redbull-ring', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('austria-redbull-ring', 'f1')
@@ -307,99 +307,99 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('great-britain-silverstone', 'Great Britain (Silverstone)', 'Silverstone Circuit. Fast, flowing corners; home of British motorsport.', 'system', 'system', 27, VALUES ('great-britain-silverstone', 'Great Britain (Silverstone)', 'Silverstone Circuit. Fast, flowing corners; home of British motorsport.', 'system', 'system', 27,
3.5500000000000003, 2.4, 0.18, 'carpet', 0, 'Hamilton', 3.5500000000000003, 2.4, 0.18, 'carpet', 0, 'Hamilton',
0.3, 0.25, 3.85, 2.65, 0.3, -2.65, 3.85, -0.25,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 0, 0.3, 0.3, 0, 5, 0) VALUES ('great-britain-silverstone', 0, 0.3, -0.3, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 1, 2.4, 0.3, 0, 5, 0) VALUES ('great-britain-silverstone', 1, 2.4, -0.3, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 2, 2.8, 0.45, 1.5707963267948966, 3, 0.8) VALUES ('great-britain-silverstone', 2, 2.8, -0.45, -1.5707963267948966, 3, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 3, 2.6, 0.8, 3.141592653589793, 3.4, 0.6) VALUES ('great-britain-silverstone', 3, 2.6, -0.8, -3.141592653589793, 3.4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 4, 2.95, 1.05, 2.0707963267948966, 3.2, 0.7) VALUES ('great-britain-silverstone', 4, 2.95, -1.05, -2.0707963267948966, 3.2, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 5, 3.3, 1.3, 0, 2.2, 1.6) VALUES ('great-britain-silverstone', 5, 3.3, -1.3, -0, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 6, 3.6, 1.15, -1.5707963267948966, 2.2, 1.6) VALUES ('great-britain-silverstone', 6, 3.6, -1.15, 1.5707963267948966, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 7, 3.6, 0.8, -3.141592653589793, 3, 0.7) VALUES ('great-britain-silverstone', 7, 3.6, -0.8, 3.141592653589793, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 8, 3.85, 0.55, -1.5707963267948966, 2.6, 1) VALUES ('great-britain-silverstone', 8, 3.85, -0.55, 1.5707963267948966, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 9, 3.55, 0.25, 0, 2.4, 1) VALUES ('great-britain-silverstone', 9, 3.55, -0.25, -0, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 10, 3.25, 0.25, 1.5707963267948966, 2.4, 1) VALUES ('great-britain-silverstone', 10, 3.25, -0.25, -1.5707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 11, 3.05, 0.55, 1.8707963267948966, 3.4, 0.5) VALUES ('great-britain-silverstone', 11, 3.05, -0.55, -1.8707963267948966, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 12, 2.85, 0.45, 3.141592653589793, 4, 0.3) VALUES ('great-britain-silverstone', 12, 2.85, -0.45, -3.141592653589793, 4, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 13, 1.8, 0.3, 0, 4.6, 0) VALUES ('great-britain-silverstone', 13, 1.8, -0.3, -0, 4.6, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 14, 1.2, 0.45, -1.7707963267948965, 3.8, 0.4) VALUES ('great-britain-silverstone', 14, 1.2, -0.45, 1.7707963267948965, 3.8, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 15, 1, 0.85, -3.541592653589793, 3.6, 0.5) VALUES ('great-britain-silverstone', 15, 1, -0.85, 3.541592653589793, 3.6, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 16, 0.7, 1.15, 1.8707963267948966, 2.4, 1.2) VALUES ('great-britain-silverstone', 16, 0.7, -1.15, -1.8707963267948966, 2.4, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 17, 0.5, 0.9, 0, 2.6, 0.9) VALUES ('great-britain-silverstone', 17, 0.5, -0.9, -0, 2.6, 0.9)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 18, 0.7, 0.65, -1.5707963267948966, 3, 0.7) VALUES ('great-britain-silverstone', 18, 0.7, -0.65, 1.5707963267948966, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 19, 0.45, 0.45, -3.541592653589793, 2.6, 1) VALUES ('great-britain-silverstone', 19, 0.45, -0.45, 3.541592653589793, 2.6, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 20, 0.75, 1, 1.1707963267948966, 2.4, 1) VALUES ('great-britain-silverstone', 20, 0.75, -1, -1.1707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 21, 0.5, 1.5, -3.541592653589793, 2.6, 0.8) VALUES ('great-britain-silverstone', 21, 0.5, -1.5, 3.541592653589793, 2.6, 0.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 22, 0.3, 1.15, -1.5707963267948966, 2.4, 1) VALUES ('great-britain-silverstone', 22, 0.3, -1.15, 1.5707963267948966, 2.4, 1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 23, 0.7, 1.6, 0.7853981633974483, 3.4, 0.5) VALUES ('great-britain-silverstone', 23, 0.7, -1.6, -0.7853981633974483, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 24, 2, 1.95, 1.9707963267948967, 3, 0.7) VALUES ('great-britain-silverstone', 24, 2, -1.95, -1.9707963267948967, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 25, 3, 2.4, 3.3415926535897933, 3.4, 0.4) VALUES ('great-britain-silverstone', 25, 3, -2.4, -3.3415926535897933, 3.4, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 26, 2.4, 2.65, -1.8707963267948966, 4, 0.3) VALUES ('great-britain-silverstone', 26, 2.4, -2.65, 1.8707963267948966, 4, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 27, 1.4, 2.6, -3.141592653589793, 4.4, 0.2) VALUES ('great-britain-silverstone', 27, 1.4, -2.6, 3.141592653589793, 4.4, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 28, 0.5, 2.3, -2.8415926535897933, 4.8, 0.2) VALUES ('great-britain-silverstone', 28, 0.5, -2.3, 2.8415926535897933, 4.8, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('great-britain-silverstone', 29, 0.3, 1.7, -1.2707963267948965, 5, 0.1) VALUES ('great-britain-silverstone', 29, 0.3, -1.7, 1.2707963267948965, 5, 0.1)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('great-britain-silverstone', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('great-britain-silverstone', 'f1')
@@ -417,84 +417,84 @@ INSERT INTO tracks (id, name, description, author_id, visibility, scale,
created_ms, updated_ms) created_ms, updated_ms)
VALUES ('belgium-spa', 'Belgium (Spa-Francorchamps)', 'Spa-Francorchamps. Long, fast, legendary Eau Rouge / Raidillon.', 'system', 'system', 27, VALUES ('belgium-spa', 'Belgium (Spa-Francorchamps)', 'Spa-Francorchamps. Long, fast, legendary Eau Rouge / Raidillon.', 'system', 'system', 27,
3.85, 2.25, 0.18, 'carpet', 0, 'Verstappen', 3.85, 2.25, 0.18, 'carpet', 0, 'Verstappen',
0.4, 0.5, 4.25, 2.75, 0.4, -2.75, 4.25, -0.5,
1700000000000, 1700000000000) 1700000000000, 1700000000000)
ON CONFLICT (id) DO NOTHING; ON CONFLICT (id) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 0, 0.4, 0.5, 0, 4.8, 0) VALUES ('belgium-spa', 0, 0.4, -0.5, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 1, 1.6, 0.5, 0, 4.8, 0) VALUES ('belgium-spa', 1, 1.6, -0.5, -0, 4.8, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 2, 1.95, 0.6, 0.3, 4.2, 0.5) VALUES ('belgium-spa', 2, 1.95, -0.6, -0.3, 4.2, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 3, 2.2, 0.95, 0.9, 4, 0.6) VALUES ('belgium-spa', 3, 2.2, -0.95, -0.9, 4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 4, 2.1, 1.3, 3.541592653589793, 4, 0.6) VALUES ('belgium-spa', 4, 2.1, -1.3, -3.541592653589793, 4, 0.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 5, 2.7, 1.5, 0, 5, 0) VALUES ('belgium-spa', 5, 2.7, -1.5, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 6, 3.5, 1.5, 0, 5, 0) VALUES ('belgium-spa', 6, 3.5, -1.5, -0, 5, 0)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 7, 3.85, 1.3, -1.5707963267948966, 2.4, 1.4) VALUES ('belgium-spa', 7, 3.85, -1.3, 1.5707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 8, 3.6, 1.1, 3.4415926535897934, 2.6, 1.2) VALUES ('belgium-spa', 8, 3.6, -1.1, -3.4415926535897934, 2.6, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 9, 3.3, 1.25, 4.0415926535897935, 2.6, 1.2) VALUES ('belgium-spa', 9, 3.3, -1.25, -4.0415926535897935, 2.6, 1.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 10, 3.5, 1.55, 1.5707963267948966, 3.6, 0.4) VALUES ('belgium-spa', 10, 3.5, -1.55, -1.5707963267948966, 3.6, 0.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 11, 3.25, 1.85, 0, 2.2, 1.6) VALUES ('belgium-spa', 11, 3.25, -1.85, -0, 2.2, 1.6)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 12, 3.05, 1.7, -1.5707963267948966, 2.4, 1.4) VALUES ('belgium-spa', 12, 3.05, -1.7, 1.5707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 13, 3.25, 1.5, 0, 3, 0.7) VALUES ('belgium-spa', 13, 3.25, -1.5, -0, 3, 0.7)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 14, 3.7, 1.65, 1.8707963267948966, 3.4, 0.5) VALUES ('belgium-spa', 14, 3.7, -1.65, -1.8707963267948966, 3.4, 0.5)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 15, 4.1, 2, 2.1707963267948966, 4, 0.3) VALUES ('belgium-spa', 15, 4.1, -2, -2.1707963267948966, 4, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 16, 4.25, 2.4, 3.541592653589793, 4.6, 0.3) VALUES ('belgium-spa', 16, 4.25, -2.4, -3.541592653589793, 4.6, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 17, 4, 2.7, -1.8707963267948966, 2.4, 1.4) VALUES ('belgium-spa', 17, 4, -2.7, 1.8707963267948966, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 18, 3.7, 2.55, 3.141592653589793, 2.4, 1.4) VALUES ('belgium-spa', 18, 3.7, -2.55, -3.141592653589793, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 19, 3.55, 2.75, 3.8415926535897933, 2.4, 1.4) VALUES ('belgium-spa', 19, 3.55, -2.75, -3.8415926535897933, 2.4, 1.4)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 20, 3.05, 2.7, -1.5707963267948966, 2, 1.8) VALUES ('belgium-spa', 20, 3.05, -2.7, 1.5707963267948966, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 21, 2.85, 2.45, 0, 2, 1.8) VALUES ('belgium-spa', 21, 2.85, -2.45, -0, 2, 1.8)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 22, 2, 2.2, 2.8415926535897933, 3.6, 0.3) VALUES ('belgium-spa', 22, 2, -2.2, -2.8415926535897933, 3.6, 0.3)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 23, 1.2, 1.6, 2.541592653589793, 4, 0.2) VALUES ('belgium-spa', 23, 1.2, -1.6, -2.541592653589793, 4, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature)
VALUES ('belgium-spa', 24, 0.6, 1.05, 2.8415926535897933, 4.4, 0.2) VALUES ('belgium-spa', 24, 0.6, -1.05, -2.8415926535897933, 4.4, 0.2)
ON CONFLICT (track_id, seq) DO NOTHING; ON CONFLICT (track_id, seq) DO NOTHING;
INSERT INTO track_tags (track_id, tag) VALUES ('belgium-spa', 'f1') INSERT INTO track_tags (track_id, tag) VALUES ('belgium-spa', 'f1')
@@ -20,56 +20,56 @@ UPDATE tracks SET
WHERE id = 'monaco'; WHERE id = 'monaco';
-- New centerline (51 waypoints, scale_xy=0.016, v=0.632 m/s) -- New centerline (51 waypoints, scale_xy=0.016, v=0.632 m/s)
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 0, -3.2064, -1.0454, 1.4710, 0.632, -0.1988); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 0, -3.2064, 1.0454, -1.4710, 0.632, -0.1988);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 1, -3.1387, -0.5857, 1.3926, 0.632, -0.1787); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 1, -3.1387, 0.5857, -1.3926, 0.632, -0.1787);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 2, -3.0418, -0.1312, 1.3043, 0.632, -0.2544); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 2, -3.0418, 0.1312, -1.3043, 0.632, -0.2544);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 3, -2.8946, 0.3084, 1.1557, 0.632, -0.4431); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 3, -2.8946, -0.3084, -1.1557, 0.632, -0.4431);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 4, -2.6693, 0.7141, 0.8629, 0.632, -1.0875); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 4, -2.6693, -0.7141, -0.8629, 0.632, -1.0875);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 5, -2.3517, 0.9426, 0.1919, 0.632, -1.2844); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 5, -2.3517, -0.9426, -0.1919, 0.632, -1.2844);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 6, -1.8935, 0.8648, -0.1182, 0.632, -0.2237); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 6, -1.8935, -0.8648, 0.1182, 0.632, -0.2237);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 7, -1.4302, 0.8332, -0.0660, 0.632, 0.0475); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 7, -1.4302, -0.8332, 0.0660, 0.632, 0.0475);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 8, -0.9667, 0.8035, -0.0743, 0.632, 0.0756); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 8, -0.9667, -0.8035, 0.0743, 0.632, 0.0756);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 9, -0.5052, 0.7644, 0.0045, 0.632, 0.0806); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 9, -0.5052, -0.7644, -0.0045, 0.632, 0.0806);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 10, -0.0425, 0.8077, 0.0000, 0.632, -0.0425); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 10, -0.0425, -0.8077, -0.0000, 0.632, -0.0425);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 11, 0.4197, 0.7644, -0.0351, 0.632, 0.3650); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 11, 0.4197, -0.7644, 0.0351, 0.632, 0.3650);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 12, 0.8809, 0.7753, 0.3862, 0.632, 1.3887); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 12, 0.8809, -0.7753, -0.3862, 0.632, 1.3887);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 13, 1.1985, 1.0811, 1.2440, 0.632, 1.4550); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 13, 1.1985, -1.0811, -1.2440, 0.632, 1.4550);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 14, 1.1372, 1.5315, 1.5878, 0.632, -0.2144); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 14, 1.1372, -1.5315, -1.5878, 0.632, -0.2144);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 15, 1.1839, 1.9468, 1.0284, 0.632, -1.2681); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 15, 1.1839, -1.9468, -1.0284, 0.632, -1.2681);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 16, 1.5551, 2.2249, 0.6162, 0.632, -0.4763); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 16, 1.5551, -2.2249, -0.6162, 0.632, -0.4763);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 17, 1.9414, 2.4832, 0.5226, 0.632, -0.1756); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 17, 1.9414, -2.4832, -0.5226, 0.632, -0.1756);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 18, 2.3526, 2.6842, 0.4546, 0.632, -0.1494); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 18, 2.3526, -2.6842, -0.4546, 0.632, -0.1494);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 19, 2.3526, 2.6842, -1.2476, 0.632, -0.0225); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 19, 2.3526, -2.6842, 1.2476, 0.632, -0.0225);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 20, 2.4622, 2.3570, -1.2545, 0.632, 0.1775); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 20, 2.4622, -2.3570, 1.2545, 0.632, 0.1775);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 21, 2.5976, 1.9356, -0.5751, 0.632, 34.1925); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 21, 2.5976, -1.9356, 0.5751, 0.632, 34.1925);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 22, 2.6154, 2.2577, 1.0415, 0.632, -0.8400); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 22, 2.6154, -2.2577, -1.0415, 0.632, -0.8400);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 23, 2.9239, 2.4933, -0.0053, 0.632, -3.1975); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 23, 2.9239, -2.4933, 0.0053, 0.632, -3.1975);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 24, 3.2311, 2.2544, -1.4159, 0.632, -2.7456); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 24, 3.2311, -2.2544, 1.4159, 0.632, -2.7456);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 25, 3.0259, 1.8399, -2.1127, 0.632, -0.6488); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 25, 3.0259, -1.8399, 2.1127, 0.632, -0.6488);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 26, 2.7546, 1.4629, -2.2528, 0.632, -0.2769); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 26, 2.7546, -1.4629, 2.2528, 0.632, -0.2769);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 27, 2.4413, 1.1199, -2.3708, 0.632, -0.3044); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 27, 2.4413, -1.1199, 2.3708, 0.632, -0.3044);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 28, 2.0895, 0.8170, -2.5300, 0.632, -0.3825); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 28, 2.0895, -0.8170, 2.5300, 0.632, -0.3825);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 29, 1.6852, 0.5897, -2.7255, 0.632, -0.4019); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 29, 1.6852, -0.5897, 2.7255, 0.632, -0.4019);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 30, 1.2447, 0.4437, -2.9031, 0.632, -0.3538); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 30, 1.2447, -0.4437, 2.9031, 0.632, -0.3538);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 31, 0.7862, 0.3711, -3.0547, 0.632, -0.3044); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 31, 0.7862, -0.3711, 3.0547, 0.632, -0.3044);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 32, 0.3218, 0.3632, 3.0973, 0.632, -0.0975); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 32, 0.3218, -0.3632, -3.0973, 0.632, -0.0975);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 33, -0.1396, 0.4121, 3.1387, 0.632, -0.0394); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 33, -0.1396, -0.4121, -3.1387, 0.632, -0.0394);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 34, -0.5818, 0.3659, 3.0594, 0.632, -0.2375); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 34, -0.5818, -0.3659, -3.0594, 0.632, -0.2375);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 35, -1.0290, 0.4854, 2.9319, 0.632, -0.0950); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 35, -1.0290, -0.4854, -2.9319, 0.632, -0.0950);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 36, -1.4880, 0.5588, 2.9664, 0.632, -0.2500); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 36, -1.4880, -0.5588, -2.9664, 0.632, -0.2500);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 37, -1.9441, 0.6474, -3.1052, 0.632, 0.8825); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 37, -1.9441, -0.6474, 3.1052, 0.632, 0.8825);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 38, -2.3631, 0.5269, -2.4971, 0.632, 1.3600); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 38, -2.3631, -0.5269, 2.4971, 0.632, 1.3600);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 39, -2.6181, 0.1409, -1.9547, 0.632, 0.9481); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 39, -2.6181, -0.1409, 1.9547, 0.632, 0.9481);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 40, -2.7014, -0.3108, -1.5706, 0.632, 0.3788); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 40, -2.7014, 0.3108, 1.5706, 0.632, 0.3788);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 41, -2.6179, -0.7633, -1.6025, 0.632, -0.3425); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 41, -2.6179, 0.7633, 1.6025, 0.632, -0.3425);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 42, -2.7299, -1.2092, -1.8788, 0.632, -0.0725); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 42, -2.7299, 1.2092, 1.8788, 0.632, -0.0725);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 43, -2.8930, -1.6280, -1.6659, 0.632, 0.7706); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 43, -2.8930, 1.6280, 1.6659, 0.632, 0.7706);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 44, -2.8134, -2.0840, -1.2045, 0.632, 0.2162); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 44, -2.8134, 2.0840, 1.2045, 0.632, 0.2162);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 45, -2.5685, -2.4739, -1.5682, 0.632, -2.4475); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 45, -2.5685, 2.4739, 1.5682, 0.632, -2.4475);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 46, -2.8118, -2.6842, 3.0638, 0.632, -4.0544); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 46, -2.8118, 2.6842, -3.0638, 0.632, -4.0544);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 47, -3.1281, -2.4303, 2.0706, 0.632, -1.2500); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 47, -3.1281, 2.4303, -2.0706, 0.632, -1.2500);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 48, -3.2004, -1.9728, 1.6822, 0.632, -0.4706); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 48, -3.2004, 1.9728, -1.6822, 0.632, -0.4706);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 49, -3.2311, -1.5093, 1.5774, 0.632, -0.2275); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 49, -3.2311, 1.5093, -1.5774, 0.632, -0.2275);
INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 50, -3.2064, -1.0454, 1.4710, 0.632, -0.1988); INSERT INTO track_waypoints (track_id, seq, x, y, heading_rad, speed_ms, curvature) VALUES ('monaco', 50, -3.2064, 1.0454, -1.4710, 0.632, -0.1988);
COMMIT; COMMIT;
@@ -0,0 +1,8 @@
-- 015_driver_car_id.sql — move device_id to cars table and use car_id in lobby_drivers
--
-- Represents the currently selected physical ESP32 DEVICE_ID (0..127) for a car.
-- And represents the currently selected car ID for a driver in lobby_drivers.
ALTER TABLE cars ADD COLUMN IF NOT EXISTS device_id INT;
ALTER TABLE lobby_drivers ADD COLUMN IF NOT EXISTS car_id TEXT;
ALTER TABLE lobby_drivers DROP COLUMN IF EXISTS device_id;
+9 -8
View File
@@ -142,7 +142,7 @@ func (s *PgStore) loadCars(ctx context.Context) ([]catalog.CarMeta, error) {
battery_voltage_v, battery_capacity_mah, battery_cells, battery_chemistry, battery_voltage_v, battery_capacity_mah, battery_cells, battery_chemistry,
drive, top_speed_ms, color_hex, avatar_url, active, drive, top_speed_ms, color_hex, avatar_url, active,
total_distance_m, total_races, total_laps, best_lap_ms, total_distance_m, total_races, total_laps, best_lap_ms,
created_ms, updated_ms created_ms, updated_ms, device_id
FROM cars FROM cars
ORDER BY id`) ORDER BY id`)
if err != nil { if err != nil {
@@ -161,7 +161,7 @@ func (s *PgStore) loadCars(ctx context.Context) ([]catalog.CarMeta, error) {
&c.Battery.VoltageV, &c.Battery.CapacityMah, &c.Battery.Cells, &c.Battery.Chemistry, &c.Battery.VoltageV, &c.Battery.CapacityMah, &c.Battery.Cells, &c.Battery.Chemistry,
&c.Drive, &c.TopSpeedMs, &c.ColorHex, &c.AvatarURL, &c.Active, &c.Drive, &c.TopSpeedMs, &c.ColorHex, &c.AvatarURL, &c.Active,
&c.TotalDistanceM, &c.TotalRaces, &c.TotalLaps, &c.BestLapMs, &c.TotalDistanceM, &c.TotalRaces, &c.TotalLaps, &c.BestLapMs,
&c.CreatedMs, &c.UpdatedMs, &c.CreatedMs, &c.UpdatedMs, &c.DeviceID,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
@@ -260,8 +260,8 @@ func (s *PgStore) UpsertCar(ctx context.Context, c catalog.CarMeta) error {
battery_voltage_v, battery_capacity_mah, battery_cells, battery_chemistry, battery_voltage_v, battery_capacity_mah, battery_cells, battery_chemistry,
drive, top_speed_ms, color_hex, avatar_url, active, drive, top_speed_ms, color_hex, avatar_url, active,
total_distance_m, total_races, total_laps, best_lap_ms, total_distance_m, total_races, total_laps, best_lap_ms,
created_ms, updated_ms) created_ms, updated_ms, device_id)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$30,$31,$32,$33)
ON CONFLICT (id) DO UPDATE SET ON CONFLICT (id) DO UPDATE SET
name = EXCLUDED.name, name = EXCLUDED.name,
owner_id = EXCLUDED.owner_id, owner_id = EXCLUDED.owner_id,
@@ -293,7 +293,8 @@ func (s *PgStore) UpsertCar(ctx context.Context, c catalog.CarMeta) error {
total_races = EXCLUDED.total_races, total_races = EXCLUDED.total_races,
total_laps = EXCLUDED.total_laps, total_laps = EXCLUDED.total_laps,
best_lap_ms = EXCLUDED.best_lap_ms, best_lap_ms = EXCLUDED.best_lap_ms,
updated_ms = EXCLUDED.updated_ms`, updated_ms = EXCLUDED.updated_ms,
device_id = EXCLUDED.device_id`,
c.ID, c.Name, c.OwnerID, string(c.Visibility), c.Scale, c.ID, c.Name, c.OwnerID, string(c.Visibility), c.Scale,
c.LengthMm, c.WidthMm, c.HeightMm, c.WeightG, c.LengthMm, c.WidthMm, c.HeightMm, c.WeightG,
c.Chassis.Model, c.Chassis.Material, c.Chassis.Printed, c.Chassis.Model, c.Chassis.Material, c.Chassis.Printed,
@@ -302,7 +303,7 @@ func (s *PgStore) UpsertCar(ctx context.Context, c catalog.CarMeta) error {
c.Battery.VoltageV, c.Battery.CapacityMah, c.Battery.Cells, c.Battery.Chemistry, c.Battery.VoltageV, c.Battery.CapacityMah, c.Battery.Cells, c.Battery.Chemistry,
string(c.Drive), c.TopSpeedMs, c.ColorHex, c.AvatarURL, c.Active, string(c.Drive), c.TopSpeedMs, c.ColorHex, c.AvatarURL, c.Active,
c.TotalDistanceM, c.TotalRaces, c.TotalLaps, c.BestLapMs, c.TotalDistanceM, c.TotalRaces, c.TotalLaps, c.BestLapMs,
c.CreatedMs, c.UpdatedMs, c.CreatedMs, c.UpdatedMs, c.DeviceID,
) )
return err return err
} }
@@ -333,7 +334,7 @@ func (s *PgStore) UpdateCarStats(ctx context.Context, id string, fn func(*catalo
battery_voltage_v, battery_capacity_mah, battery_cells, battery_chemistry, battery_voltage_v, battery_capacity_mah, battery_cells, battery_chemistry,
drive, top_speed_ms, color_hex, avatar_url, active, drive, top_speed_ms, color_hex, avatar_url, active,
total_distance_m, total_races, total_laps, best_lap_ms, total_distance_m, total_races, total_laps, best_lap_ms,
created_ms, updated_ms created_ms, updated_ms, device_id
FROM cars WHERE id = $1 FOR UPDATE`, id, FROM cars WHERE id = $1 FOR UPDATE`, id,
).Scan( ).Scan(
&c.ID, &c.Name, &c.OwnerID, &c.Visibility, &c.Scale, &c.ID, &c.Name, &c.OwnerID, &c.Visibility, &c.Scale,
@@ -344,7 +345,7 @@ func (s *PgStore) UpdateCarStats(ctx context.Context, id string, fn func(*catalo
&c.Battery.VoltageV, &c.Battery.CapacityMah, &c.Battery.Cells, &c.Battery.Chemistry, &c.Battery.VoltageV, &c.Battery.CapacityMah, &c.Battery.Cells, &c.Battery.Chemistry,
&c.Drive, &c.TopSpeedMs, &c.ColorHex, &c.AvatarURL, &c.Active, &c.Drive, &c.TopSpeedMs, &c.ColorHex, &c.AvatarURL, &c.Active,
&c.TotalDistanceM, &c.TotalRaces, &c.TotalLaps, &c.BestLapMs, &c.TotalDistanceM, &c.TotalRaces, &c.TotalLaps, &c.BestLapMs,
&c.CreatedMs, &c.UpdatedMs, &c.CreatedMs, &c.UpdatedMs, &c.DeviceID,
) )
if err != nil { if err != nil {
if errors.Is(err, pgx.ErrNoRows) { if errors.Is(err, pgx.ErrNoRows) {
+2
View File
@@ -478,6 +478,7 @@ type CarWire struct {
CreatedMs int64 `json:"created_ms"` CreatedMs int64 `json:"created_ms"`
UpdatedMs int64 `json:"updated_ms"` UpdatedMs int64 `json:"updated_ms"`
DeviceID *int `json:"device_id,omitempty"`
} }
// CarListRequest: payload { "scope": "all|system|public|private", "owner_id": "..." }. // CarListRequest: payload { "scope": "all|system|public|private", "owner_id": "..." }.
@@ -519,6 +520,7 @@ type CarPatch struct {
ColorHex *string `json:"color_hex,omitempty"` ColorHex *string `json:"color_hex,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"` AvatarURL *string `json:"avatar_url,omitempty"`
Active *bool `json:"active,omitempty"` Active *bool `json:"active,omitempty"`
DeviceID *int `json:"device_id,omitempty"`
} }
// CarDeleteRequest: payload { "id": "..." }. // CarDeleteRequest: payload { "id": "..." }.
+29
View File
@@ -79,6 +79,35 @@
<div class="wheel"> <div class="wheel">
<div class="wheel-disc" id="wheelDisc"></div> <div class="wheel-disc" id="wheelDisc"></div>
</div> </div>
<div class="control-extra" style="display: flex; gap: 10px; margin-top: 15px; justify-content: space-around; border-top: 1px solid #333; padding-top: 12px;">
<div class="gear-indicator" style="text-align: center;">
<div style="font-size: 0.8rem; color: #aaa;">GEAR</div>
<div style="display: flex; align-items: center; gap: 5px; margin-top: 4px;">
<button id="btnGearDown" class="btn" style="padding: 2px 8px; font-size: 0.8rem;">-</button>
<b id="lblGear" style="font-size: 1.3rem; min-width: 15px; display: inline-block;">N</b>
<button id="btnGearUp" class="btn" style="padding: 2px 8px; font-size: 0.8rem;">+</button>
</div>
<div style="font-size: 0.7rem; color: #888; margin-top: 2px;">(Z / X)</div>
</div>
<div class="sys-toggle" style="text-align: center;">
<div style="font-size: 0.8rem; color: #aaa;">DRS</div>
<button id="btnDrs" class="btn" style="padding: 2px 6px; font-size: 0.8rem; margin-top: 4px;">Toggle</button>
<div id="lblDrs" class="val" style="font-weight: bold; font-size: 0.95rem; margin-top: 4px; color: #ff3b30;">OFF</div>
<div style="font-size: 0.7rem; color: #888; margin-top: 2px;">(Q)</div>
</div>
<div class="sys-toggle" style="text-align: center;">
<div style="font-size: 0.8rem; color: #aaa;">PIT LIMIT</div>
<button id="btnPit" class="btn" style="padding: 2px 6px; font-size: 0.8rem; margin-top: 4px;">Toggle</button>
<div id="lblPit" class="val" style="font-weight: bold; font-size: 0.95rem; margin-top: 4px; color: #ff3b30;">OFF</div>
<div style="font-size: 0.7rem; color: #888; margin-top: 2px;">(E)</div>
</div>
</div>
<div style="margin-top: 15px; border-top: 1px solid #333; padding-top: 12px;">
<span style="font-size: 0.8rem; color: #aaa;">Пакет управления (JSON):</span>
<pre id="ctrlJson" style="font-family: monospace; font-size: 0.75rem; background: #111; border: 1px solid #222; padding: 8px; border-radius: 4px; color: #00ff66; margin: 6px 0 0 0; overflow-x: auto; max-height: 250px; text-align: left; line-height: 1.2;">{}</pre>
</div>
</div> </div>
<div class="card"> <div class="card">
+100 -1
View File
@@ -35,6 +35,14 @@
tPos: $('tPos'), tPos: $('tPos'),
tTsm: $('tTsm'), tTsm: $('tTsm'),
tCars: $('tCars'), tCars: $('tCars'),
lblGear: $('lblGear'),
lblDrs: $('lblDrs'),
lblPit: $('lblPit'),
btnDrs: $('btnDrs'),
btnPit: $('btnPit'),
btnGearUp: $('btnGearUp'),
btnGearDown: $('btnGearDown'),
ctrlJson: $('ctrlJson'),
}; };
// -------- State -------- // -------- State --------
@@ -53,7 +61,7 @@
snapshotCount: 0, snapshotCount: 0,
snapshotWindow: [], snapshotWindow: [],
keys: new Set(), keys: new Set(),
input: { throttle: 0, brake: 0, steer: 0, handbrake: false, buttons: 0 }, input: { throttle: 0, brake: 0, steer: 0, handbrake: false, buttons: 0, gear: 0, drs: false, pitLimiter: false },
pingTimer: null, pingTimer: null,
inputTimer: null, inputTimer: null,
slotHint: 0, // сервер выдаёт слот; 0 по умолчанию slotHint: 0, // сервер выдаёт слот; 0 по умолчанию
@@ -113,6 +121,12 @@
state.input.steer = steer; state.input.steer = steer;
state.input.handbrake = handbrake; state.input.handbrake = handbrake;
// Calculate buttons bitmask: bit 0 (DRS), bit 1 (Pit Limiter)
let buttons = 0;
if (state.input.drs) buttons |= 1;
if (state.input.pitLimiter) buttons |= 2;
state.input.buttons = buttons;
// Update UI bars // Update UI bars
ui.lblThrottle.textContent = throttle.toFixed(2); ui.lblThrottle.textContent = throttle.toFixed(2);
ui.lblBrake.textContent = brake.toFixed(2); ui.lblBrake.textContent = brake.toFixed(2);
@@ -129,6 +143,48 @@
ui.barSteer.style.width = '2%'; ui.barSteer.style.width = '2%';
ui.wheelDisc.style.transform = `rotate(${steer * 90}deg)`; ui.wheelDisc.style.transform = `rotate(${steer * 90}deg)`;
// Update Gear, DRS, Pit Limiter UI text & class if elements exist
if (ui.lblGear) {
let gName = 'N';
if (state.input.gear === -1) gName = 'R';
if (state.input.gear === 1) gName = 'D';
ui.lblGear.textContent = gName;
}
if (ui.lblDrs) {
ui.lblDrs.textContent = state.input.drs ? 'ON' : 'OFF';
ui.lblDrs.className = state.input.drs ? 'val active' : 'val';
}
if (ui.lblPit) {
ui.lblPit.textContent = state.input.pitLimiter ? 'ON' : 'OFF';
ui.lblPit.className = state.input.pitLimiter ? 'val active' : 'val';
}
// Format control packet as JSON and show in UI
if (ui.ctrlJson) {
const steerByte = Math.round((steer + 1.0) * 100);
const throttleByte = Math.round(throttle * 100);
const brakeByte = Math.round(brake * 100);
const gearByte = state.input.gear === -1 ? 0 : (state.input.gear === 1 ? 2 : 1);
const jsonStr = JSON.stringify({
sent_json: {
steering: steer,
throttle: throttle,
brake: brake,
gear: state.input.gear,
buttons: buttons
},
binary_packet_bytes: {
byte0_steer: `0x${steerByte.toString(16).toUpperCase().padStart(2, '0')} (${steerByte})`,
byte1_throttle: `0x${throttleByte.toString(16).toUpperCase().padStart(2, '0')} (${throttleByte}%)`,
byte2_brake: `0x${brakeByte.toString(16).toUpperCase().padStart(2, '0')} (${brakeByte}%)`,
byte3_gear: `0x${gearByte.toString(16).toUpperCase().padStart(2, '0')} (${gearByte === 0 ? 'R' : (gearByte === 2 ? 'D' : 'N')})`,
byte4_flags: `0x${buttons.toString(16).toUpperCase().padStart(2, '0')} (DRS=${state.input.drs ? 1 : 0}, Pit=${state.input.pitLimiter ? 1 : 0})`
}
}, null, 2);
ui.ctrlJson.textContent = jsonStr;
}
} }
// -------- Send helpers -------- // -------- Send helpers --------
@@ -450,6 +506,24 @@
if (tag === 'INPUT' || tag === 'TEXTAREA') return; if (tag === 'INPUT' || tag === 'TEXTAREA') return;
if (['arrowup','arrowdown','arrowleft','arrowright',' '].includes(k)) e.preventDefault(); if (['arrowup','arrowdown','arrowleft','arrowright',' '].includes(k)) e.preventDefault();
state.keys.add(k); state.keys.add(k);
// Toggle DRS, Pit Limiter, and shift gears
if (k === 'q') {
state.input.drs = !state.input.drs;
pollInput();
}
if (k === 'e') {
state.input.pitLimiter = !state.input.pitLimiter;
pollInput();
}
if (k === 'z') {
state.input.gear = Math.max(-1, state.input.gear - 1);
pollInput();
}
if (k === 'x') {
state.input.gear = Math.min(1, state.input.gear + 1);
pollInput();
}
}); });
window.addEventListener('keyup', (e) => { window.addEventListener('keyup', (e) => {
state.keys.delete(keyName(e)); state.keys.delete(keyName(e));
@@ -462,6 +536,31 @@
ui.btnJoin.addEventListener('click', joinRace); ui.btnJoin.addEventListener('click', joinRace);
ui.btnLeave.addEventListener('click', leaveRace); ui.btnLeave.addEventListener('click', leaveRace);
if (ui.btnDrs) {
ui.btnDrs.addEventListener('click', () => {
state.input.drs = !state.input.drs;
pollInput();
});
}
if (ui.btnPit) {
ui.btnPit.addEventListener('click', () => {
state.input.pitLimiter = !state.input.pitLimiter;
pollInput();
});
}
if (ui.btnGearUp) {
ui.btnGearUp.addEventListener('click', () => {
state.input.gear = Math.min(1, state.input.gear + 1);
pollInput();
});
}
if (ui.btnGearDown) {
ui.btnGearDown.addEventListener('click', () => {
state.input.gear = Math.max(-1, state.input.gear - 1);
pollInput();
});
}
// -------- Boot -------- // -------- Boot --------
setConn('disconnected', ''); setConn('disconnected', '');
log('x0gp PoC client ready. Press Connect.', 'meta'); log('x0gp PoC client ready. Press Connect.', 'meta');
+395
View File
@@ -0,0 +1,395 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>x0gp — Race Track Viewer</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&family=Plus+Jakarta+Sans:wght@300;400;500;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color: #0b0f19;
--card-bg: rgba(17, 24, 39, 0.7);
--card-border: rgba(255, 255, 255, 0.08);
--text-primary: #f3f4f6;
--text-secondary: #9ca3af;
--accent: #3b82f6;
--accent-glow: rgba(59, 130, 246, 0.15);
--gradient-accent: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Plus Jakarta Sans', sans-serif;
background-color: var(--bg-color);
color: var(--text-primary);
min-height: 100vh;
padding: 2.5rem;
background-image:
radial-gradient(circle at 10% 20%, rgba(59, 130, 246, 0.05) 0%, transparent 40%),
radial-gradient(circle at 90% 80%, rgba(37, 99, 235, 0.05) 0%, transparent 40%);
background-attachment: fixed;
}
header {
max-width: 1200px;
margin: 0 auto 3rem auto;
display: flex;
justify-content: space-between;
align-items: center;
}
h1 {
font-family: 'Outfit', sans-serif;
font-size: 2.5rem;
font-weight: 800;
letter-spacing: -0.03em;
background: linear-gradient(135deg, #ffffff 0%, #a5b4fc 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle {
color: var(--text-secondary);
font-size: 0.95rem;
margin-top: 0.25rem;
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 2rem;
max-width: 1200px;
margin: 0 auto;
}
.card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 16px;
padding: 1.5rem;
display: flex;
flex-direction: column;
gap: 1.25rem;
backdrop-filter: blur(12px);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
overflow: hidden;
}
.card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(800px circle at var(--x, 0px) var(--y, 0px), rgba(255, 255, 255, 0.06), transparent 40%);
pointer-events: none;
opacity: 0;
transition: opacity 0.5s;
}
.card:hover::before {
opacity: 1;
}
.card:hover {
transform: translateY(-4px);
border-color: rgba(59, 130, 246, 0.3);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.3), 0 0 0 1px rgba(59, 130, 246, 0.1);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.track-name {
font-family: 'Outfit', sans-serif;
font-size: 1.35rem;
font-weight: 600;
color: #ffffff;
}
.track-id {
font-family: monospace;
font-size: 0.8rem;
color: var(--text-secondary);
background: rgba(255, 255, 255, 0.05);
padding: 0.2rem 0.5rem;
border-radius: 6px;
}
.canvas-container {
width: 100%;
height: 280px;
background-color: #0b0f19;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
border: 1px solid rgba(255, 255, 255, 0.03);
position: relative;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
font-size: 0.85rem;
}
.stat-item {
background: rgba(255, 255, 255, 0.02);
border: 1px solid rgba(255, 255, 255, 0.03);
padding: 0.5rem 0.75rem;
border-radius: 8px;
display: flex;
justify-content: space-between;
}
.stat-label {
color: var(--text-secondary);
}
.stat-value {
color: #ffffff;
font-weight: 600;
}
.tags-container {
display: flex;
gap: 0.4rem;
flex-wrap: wrap;
}
.tag {
font-size: 0.75rem;
padding: 0.2rem 0.6rem;
border-radius: 20px;
background: rgba(59, 130, 246, 0.1);
color: #60a5fa;
border: 1px solid rgba(59, 130, 246, 0.2);
}
.tag-active {
background: rgba(16, 185, 129, 0.1);
color: #34d399;
border: 1px solid rgba(16, 185, 129, 0.2);
}
.loader {
display: flex;
justify-content: center;
align-items: center;
min-height: 300px;
width: 100%;
grid-column: 1 / -1;
flex-direction: column;
gap: 1rem;
color: var(--text-secondary);
}
.spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(59, 130, 246, 0.1);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
</head>
<body>
<header>
<div>
<h1>x0gp — Race Track Catalog</h1>
<div class="subtitle">Visualizing physical tracks and their generated centerline geometry</div>
</div>
</header>
<main class="grid" id="tracks-grid">
<div class="loader">
<div class="spinner"></div>
<div>Loading tracks from server API...</div>
</div>
</main>
<script>
// Track SVG centerline rendering algorithm
function generateSvgPath(centerline, bounds, padding = 30, size = 260) {
if (!centerline || centerline.length < 2) return null;
const minX = bounds.min_x;
const maxX = bounds.max_x;
const minY = bounds.min_y;
const maxY = bounds.max_y;
const rangeX = maxX - minX || 1;
const rangeY = maxY - minY || 1;
const aspectRatio = rangeX / rangeY;
let width, height;
if (aspectRatio > 1) {
width = size;
height = size / aspectRatio;
} else {
width = size * aspectRatio;
height = size;
}
const canvasWidth = width + padding * 2;
const canvasHeight = height + padding * 2;
const pixelPoints = centerline.map((point) => ({
x: ((point.x - minX) / rangeX) * width + padding,
y: ((point.y - minY) / rangeY) * height + padding,
heading: point.heading_rad,
curvature: point.curvature
}));
let dAttribute = '';
for (let i = 0; i < pixelPoints.length; i++) {
const current = pixelPoints[i];
if (i === 0) {
dAttribute += `M ${current.x.toFixed(2)} ${current.y.toFixed(2)}`;
} else {
const prev = pixelPoints[i - 1];
const dx = current.x - prev.x;
const dy = current.y - prev.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const tension = 0.30 + (prev.curvature * 0.05);
const cpLength = distance * tension;
const cp1x = prev.x + Math.cos(prev.heading) * cpLength;
const cp1y = prev.y + Math.sin(prev.heading) * cpLength;
const cp2x = current.x - Math.cos(current.heading) * cpLength;
const cp2y = current.y - Math.sin(current.heading) * cpLength;
dAttribute += ` C ${cp1x.toFixed(2)} ${cp1y.toFixed(2)}, ${cp2x.toFixed(2)} ${cp2y.toFixed(2)}, ${current.x.toFixed(2)} ${current.y.toFixed(2)}`;
}
}
if (pixelPoints.length > 2) {
const first = pixelPoints[0];
const last = pixelPoints[pixelPoints.length - 1];
const dx = first.x - last.x;
const dy = first.y - last.y;
const distance = Math.sqrt(dx * dx + dy * dy);
const tension = 0.3 + last.curvature * 0.05;
const cpLength = distance * tension;
const cp1x = last.x + Math.cos(last.heading) * cpLength;
const cp1y = last.y + Math.sin(last.heading) * cpLength;
const cp2x = first.x - Math.cos(first.heading) * cpLength;
const cp2y = first.y - Math.sin(first.heading) * cpLength;
dAttribute += ` C ${cp1x.toFixed(2)} ${cp1y.toFixed(2)}, ${cp2x.toFixed(2)} ${cp2y.toFixed(2)}, ${first.x.toFixed(2)} ${first.y.toFixed(2)} Z`;
}
return {
d: dAttribute,
canvasWidth,
canvasHeight
};
}
async function init() {
const grid = document.getElementById('tracks-grid');
try {
const res = await fetch('/api/tracks');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
grid.innerHTML = '';
if (!data.tracks || data.tracks.length === 0) {
grid.innerHTML = '<div class="loader">No tracks found on the server.</div>';
return;
}
data.tracks.forEach(track => {
const card = document.createElement('div');
card.className = 'card';
// Track hover mouse light effect
card.addEventListener('mousemove', e => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
card.style.setProperty('--x', `${x}px`);
card.style.setProperty('--y', `${y}px`);
});
// Generate SVG
const svgData = generateSvgPath(track.centerline, track.bounds);
let svgHtml = '<div style="color: var(--text-secondary); font-size: 0.85rem;">No centerline coordinates</div>';
if (svgData) {
svgHtml = `
<svg width="100%" height="100%" viewBox="0 0 ${svgData.canvasWidth} ${svgData.canvasHeight}" preserveAspectRatio="xMidYMid meet" style="display: block; max-width: 100%; max-height: 100%; height: auto; transform-origin: center;">
<path d="${svgData.d}" fill="none" stroke="#ffffff" stroke-width="20" stroke-linecap="round" stroke-linejoin="round" />
<path d="${svgData.d}" fill="none" stroke="#111827" stroke-width="10" stroke-linecap="round" stroke-linejoin="round" />
</svg>
`;
}
const isActiveTag = track.is_active ? '<span class="tag tag-active">Active Track</span>' : '';
const bestLapStr = track.best_lap_ms > 0 ? `${(track.best_lap_ms / 1000).toFixed(3)}s` : 'None';
card.innerHTML = `
<div class="card-header">
<div>
<div class="track-name">${track.name}</div>
<div style="font-size: 0.85rem; color: var(--text-secondary); margin-top: 0.2rem;">${track.description || 'No description'}</div>
</div>
<div class="track-id">${track.id}</div>
</div>
<div class="canvas-container">
${svgHtml}
</div>
<div class="stats-grid">
<div class="stat-item">
<span class="stat-label">Length</span>
<span class="stat-value">${track.length_m.toFixed(1)} m</span>
</div>
<div class="stat-item">
<span class="stat-label">Width</span>
<span class="stat-value">${track.width_m.toFixed(1)} m</span>
</div>
<div class="stat-item">
<span class="stat-label">Lane Width</span>
<span class="stat-value">${track.lane_width_m.toFixed(1)} m</span>
</div>
<div class="stat-item">
<span class="stat-label">Best Lap</span>
<span class="stat-value">${bestLapStr}</span>
</div>
</div>
<div class="tags-container">
<span class="tag" style="background: rgba(255,255,255,0.05); color: #fff; border-color: rgba(255,255,255,0.1); text-transform: capitalize;">${track.surface}</span>
${isActiveTag}
</div>
`;
grid.appendChild(card);
});
} catch (err) {
grid.innerHTML = `<div class="loader" style="color: #ef4444;">Failed to load tracks: ${err.message}</div>`;
}
}
init();
</script>
</body>
</html>
+119 -3
View File
@@ -408,6 +408,35 @@
<div id="keyS" class="key-btn">S</div> <div id="keyS" class="key-btn">S</div>
<div id="keyD" class="key-btn">D</div> <div id="keyD" class="key-btn">D</div>
</div> </div>
<div class="control-extra" style="display: flex; gap: 10px; margin-top: 15px; justify-content: space-around; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 12px; width: 100%;">
<div class="gear-indicator" style="text-align: center;">
<div style="font-size: 0.8rem; color: #8a8d9a;">GEAR</div>
<div style="display: flex; align-items: center; gap: 5px; margin-top: 4px;">
<button id="btnGearDown" class="btn" style="padding: 2px 8px; font-size: 0.8rem; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">-</button>
<b id="lblGear" style="font-size: 1.3rem; min-width: 15px; display: inline-block;">N</b>
<button id="btnGearUp" class="btn" style="padding: 2px 8px; font-size: 0.8rem; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">+</button>
</div>
<div style="font-size: 0.7rem; color: #6b7280; margin-top: 2px;">(Z / X)</div>
</div>
<div class="sys-toggle" style="text-align: center;">
<div style="font-size: 0.8rem; color: #8a8d9a;">DRS</div>
<button id="btnDrs" class="btn" style="padding: 2px 6px; font-size: 0.8rem; margin-top: 4px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">Toggle</button>
<div id="lblDrs" class="val" style="font-weight: bold; font-size: 0.95rem; margin-top: 4px; color: #ef4444;">OFF</div>
<div style="font-size: 0.7rem; color: #6b7280; margin-top: 2px;">(Q)</div>
</div>
<div class="sys-toggle" style="text-align: center;">
<div style="font-size: 0.8rem; color: #8a8d9a;">PIT LIMIT</div>
<button id="btnPit" class="btn" style="padding: 2px 6px; font-size: 0.8rem; margin-top: 4px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 4px; cursor: pointer;">Toggle</button>
<div id="lblPit" class="val" style="font-weight: bold; font-size: 0.95rem; margin-top: 4px; color: #ef4444;">OFF</div>
<div style="font-size: 0.7rem; color: #6b7280; margin-top: 2px;">(E)</div>
</div>
</div>
<div style="margin-top: 15px; border-top: 1px solid rgba(255,255,255,0.1); padding-top: 12px; width: 100%;">
<span style="font-size: 0.8rem; color: #8a8d9a;">Пакет управления (JSON):</span>
<pre id="ctrlJson" style="font-family: monospace; font-size: 0.75rem; background: rgba(0,0,0,0.5); border: 1px solid rgba(255,255,255,0.05); padding: 8px; border-radius: 4px; color: #00ff66; margin: 6px 0 0 0; overflow-x: auto; max-height: 250px; text-align: left; line-height: 1.2;">{}</pre>
</div>
</div> </div>
</div> </div>
@@ -489,6 +518,10 @@
let currentSteer = 0; // -1 to 1 let currentSteer = 0; // -1 to 1
let currentThrottle = 0; // 0 to 1 let currentThrottle = 0; // 0 to 1
let currentBrake = 0; // 0 to 1 let currentBrake = 0; // 0 to 1
let currentGear = 0; // 0: N, -1: R, 1: D
let drs = false;
let pitLimiter = false;
let buttons = 0;
let pingsReceived = 0; let pingsReceived = 0;
let latencyStart = 0; let latencyStart = 0;
@@ -513,6 +546,22 @@
activeKeys[key] = true; activeKeys[key] = true;
updateKeyVisuals(); updateKeyVisuals();
} }
if (key === 'q') {
drs = !drs;
updateKeyVisuals();
}
if (key === 'e') {
pitLimiter = !pitLimiter;
updateKeyVisuals();
}
if (key === 'z') {
currentGear = Math.max(-1, currentGear - 1);
updateKeyVisuals();
}
if (key === 'x') {
currentGear = Math.min(1, currentGear + 1);
updateKeyVisuals();
}
}); });
window.addEventListener('keyup', (e) => { window.addEventListener('keyup', (e) => {
@@ -542,9 +591,75 @@
if (activeKeys.a) currentSteer = -1.0; if (activeKeys.a) currentSteer = -1.0;
if (activeKeys.d) currentSteer = 1.0; if (activeKeys.d) currentSteer = 1.0;
// Log control changes to UI console buttons = 0;
log(`Controls updated: throttle=${currentThrottle}, steering=${currentSteer}, brake=${currentBrake}`, 'out'); if (drs) buttons |= 1;
if (pitLimiter) buttons |= 2;
// Update UI Gear/DRS/Pit if elements exist
const lblGear = document.getElementById('lblGear');
if (lblGear) {
let gName = 'N';
if (currentGear === -1) gName = 'R';
if (currentGear === 1) gName = 'D';
lblGear.innerText = gName;
} }
const lblDrs = document.getElementById('lblDrs');
if (lblDrs) {
lblDrs.innerText = drs ? 'ON' : 'OFF';
lblDrs.style.color = drs ? '#00ff66' : '#ef4444';
}
const lblPit = document.getElementById('lblPit');
if (lblPit) {
lblPit.innerText = pitLimiter ? 'ON' : 'OFF';
lblPit.style.color = pitLimiter ? '#00ff66' : '#ef4444';
}
const ctrlJson = document.getElementById('ctrlJson');
if (ctrlJson) {
const steerByte = Math.round((currentSteer + 1.0) * 100);
const throttleByte = Math.round(currentThrottle * 100);
const brakeByte = Math.round(currentBrake * 100);
const gearByte = currentGear === -1 ? 0 : (currentGear === 1 ? 2 : 1);
ctrlJson.innerText = JSON.stringify({
sent_json: {
steering: currentSteer,
throttle: currentThrottle,
brake: currentBrake,
gear: currentGear,
buttons: buttons
},
binary_packet_bytes: {
byte0_steer: `0x${steerByte.toString(16).toUpperCase().padStart(2, '0')} (${steerByte})`,
byte1_throttle: `0x${throttleByte.toString(16).toUpperCase().padStart(2, '0')} (${throttleByte}%)`,
byte2_brake: `0x${brakeByte.toString(16).toUpperCase().padStart(2, '0')} (${brakeByte}%)`,
byte3_gear: `0x${gearByte.toString(16).toUpperCase().padStart(2, '0')} (${gearByte === 0 ? 'R' : (gearByte === 2 ? 'D' : 'N')})`,
byte4_flags: `0x${buttons.toString(16).toUpperCase().padStart(2, '0')} (DRS=${drs ? 1 : 0}, Pit=${pitLimiter ? 1 : 0})`
}
}, null, 2);
}
// Log control changes to UI console
log(`Controls updated: throttle=${currentThrottle}, steering=${currentSteer}, brake=${currentBrake}, gear=${currentGear}, buttons=${buttons}`, 'out');
}
// Click listeners for the custom controls
document.getElementById('btnGearDown').addEventListener('click', () => {
currentGear = Math.max(-1, currentGear - 1);
updateKeyVisuals();
});
document.getElementById('btnGearUp').addEventListener('click', () => {
currentGear = Math.min(1, currentGear + 1);
updateKeyVisuals();
});
document.getElementById('btnDrs').addEventListener('click', () => {
drs = !drs;
updateKeyVisuals();
});
document.getElementById('btnPit').addEventListener('click', () => {
pitLimiter = !pitLimiter;
updateKeyVisuals();
});
connectBtn.addEventListener('click', () => { connectBtn.addEventListener('click', () => {
if (pc) { if (pc) {
@@ -742,7 +857,8 @@
throttle: currentThrottle, throttle: currentThrottle,
steering: currentSteer, steering: currentSteer,
brake: currentBrake, brake: currentBrake,
gear: 1, gear: currentGear,
buttons: buttons,
timestamp: Date.now() timestamp: Date.now()
}; };
dataChannel.send(JSON.stringify(payload)); dataChannel.send(JSON.stringify(payload));