Add getting car config
This commit is contained in:
@@ -3,7 +3,8 @@ import os
|
|||||||
import json
|
import json
|
||||||
import dbus
|
import dbus
|
||||||
from urllib.parse import parse_qs
|
from urllib.parse import parse_qs
|
||||||
from change_track import change_track, get_all_tracks, get_configs, get_preview_image, get_outline_image
|
from ac_maps import change_track, get_all_tracks, get_configs, get_preview_image, get_outline_image
|
||||||
|
from ac_cars import get_all_cars
|
||||||
|
|
||||||
class Handler(BaseHTTPRequestHandler):
|
class Handler(BaseHTTPRequestHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
@@ -27,51 +28,76 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
"""
|
"""
|
||||||
# Serve preview images
|
# Serve preview images
|
||||||
if self.path.startswith("/img/"):
|
if self.path.startswith("/img/"):
|
||||||
parts = self.path.split("/")
|
return self.handle_get_img_path()
|
||||||
parts = [p for p in parts if p] # remove empty
|
|
||||||
|
|
||||||
img_type = parts[1] if len(parts) > 1 else ""
|
|
||||||
|
|
||||||
track, config = self.extract_track_and_config(parts)
|
|
||||||
|
|
||||||
img_path = ""
|
|
||||||
if (img_type == "preview"):
|
|
||||||
img_path = get_preview_image(track, config)
|
|
||||||
elif (img_type == "outline"):
|
|
||||||
img_path = get_outline_image(track, config)
|
|
||||||
if img_path == "":
|
|
||||||
|
|
||||||
img_path = get_preview_image(track, config)
|
|
||||||
else:
|
|
||||||
self.send_error(404)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
self.send_image(img_path)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
# JSON track info
|
|
||||||
if self.path.startswith("/track/"):
|
if self.path.startswith("/track/"):
|
||||||
track = self.path.replace("/track/", "").strip("/")
|
return self.handle_get_track_path()
|
||||||
configs = get_configs(track)
|
|
||||||
|
if self.path == "/cars":
|
||||||
data = {
|
return self.handle_get_cars_path()
|
||||||
"track": track,
|
|
||||||
"configs": configs,
|
|
||||||
"image": f"/img/preview/{track}",
|
|
||||||
"outline": f"/img/outline/{track}"
|
|
||||||
}
|
|
||||||
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "application/json")
|
|
||||||
self.end_headers()
|
|
||||||
self.wfile.write(json.dumps(data).encode())
|
|
||||||
return True
|
|
||||||
|
|
||||||
if self.path == "/" or self.path == "/index.html":
|
if self.path == "/" or self.path == "/index.html":
|
||||||
with open("index.html", "r") as f:
|
return self.handle_get_root_path()
|
||||||
html = f.read()
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def handle_get_img_path(self):
|
||||||
|
parts = self.path.split("/")
|
||||||
|
parts = [p for p in parts if p] # remove empty
|
||||||
|
|
||||||
|
img_type = parts[1] if len(parts) > 1 else ""
|
||||||
|
|
||||||
|
img_path = ""
|
||||||
|
if (img_type == "preview"):
|
||||||
|
track, config = self.extract_track_and_config(parts)
|
||||||
|
img_path = get_preview_image(track, config)
|
||||||
|
elif (img_type == "outline"):
|
||||||
|
track, config = self.extract_track_and_config(parts)
|
||||||
|
img_path = get_outline_image(track, config)
|
||||||
|
if img_path == "":
|
||||||
|
|
||||||
|
img_path = get_preview_image(track, config)
|
||||||
|
else:
|
||||||
|
self.send_error(404)
|
||||||
|
return True
|
||||||
|
|
||||||
|
self.send_image(img_path)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def handle_get_track_path(self):
|
||||||
|
track = self.path.replace("/track/", "").strip("/")
|
||||||
|
configs = get_configs(track)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"track": track,
|
||||||
|
"configs": configs,
|
||||||
|
"image": f"/img/preview/{track}",
|
||||||
|
"outline": f"/img/outline/{track}"
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/json")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps(data).encode())
|
||||||
|
return True
|
||||||
|
|
||||||
|
def handle_get_cars_path(self):
|
||||||
|
cars = get_all_cars()
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"cars": cars
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/json")
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(json.dumps(data).encode())
|
||||||
|
return True
|
||||||
|
|
||||||
|
def handle_get_root_path(self):
|
||||||
|
with open("index.html", "r") as f:
|
||||||
|
html = f.read()
|
||||||
|
|
||||||
tracks = get_all_tracks()
|
tracks = get_all_tracks()
|
||||||
track_options = "".join([f'<option value="{t}">{t}</option>' for t in tracks])
|
track_options = "".join([f'<option value="{t}">{t}</option>' for t in tracks])
|
||||||
@@ -84,8 +110,6 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(html.encode())
|
self.wfile.write(html.encode())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def handle_POST_path(self):
|
def handle_POST_path(self):
|
||||||
if (self.path.startswith("/changetrack/")):
|
if (self.path.startswith("/changetrack/")):
|
||||||
|
|||||||
@@ -1,78 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
# CONTENT_FOLDER = "/home/sem/assetto-corsa/content"
|
|
||||||
CONFIG_FILE = "server_cfg.ini"
|
|
||||||
# CONFIG_PATH = "/home/sem/assetto-corsa/cfg"
|
|
||||||
CONTENT_FOLDER = "./content"
|
|
||||||
CONFIG_PATH = "./cfg"
|
|
||||||
|
|
||||||
TRACKS_FOLDER = os.path.join(CONTENT_FOLDER, "tracks")
|
|
||||||
|
|
||||||
def get_all_tracks():
|
|
||||||
return sorted([x.name for x in os.scandir(TRACKS_FOLDER) if x.is_dir()])
|
|
||||||
|
|
||||||
def get_preview_image(track: str, config: str = ""):
|
|
||||||
return get_path_image("preview", track, config)
|
|
||||||
|
|
||||||
def get_outline_image(track: str, config: str = ""):
|
|
||||||
return get_path_image("outline", track, config)
|
|
||||||
|
|
||||||
def get_path_image(image_name, track: str, config: str = ""):
|
|
||||||
img_path = os.path.join(TRACKS_FOLDER, track, "ui", config)
|
|
||||||
for name in os.listdir(img_path):
|
|
||||||
lower = name.lower()
|
|
||||||
if image_name in lower and lower.endswith(".png") or lower.endswith(".jpg"):
|
|
||||||
return os.path.join(img_path, name)
|
|
||||||
|
|
||||||
img_path = os.path.join(TRACKS_FOLDER, track, config)
|
|
||||||
for name in os.listdir(img_path):
|
|
||||||
lower = name.lower()
|
|
||||||
if image_name in lower and lower.endswith(".png") or lower.endswith(".jpg"):
|
|
||||||
return os.path.join(img_path, name)
|
|
||||||
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def get_configs(track) -> list[str]:
|
|
||||||
track_path = os.path.join(TRACKS_FOLDER, track);
|
|
||||||
configdirs = [x.path.replace(track_path + "/","") for x in os.scandir(track_path) if x.is_dir()]
|
|
||||||
configdirs.sort()
|
|
||||||
standard_folders = {'ai', 'ui', 'extension', 'data', 'skins','texture', 'sfx'}
|
|
||||||
for s in standard_folders:
|
|
||||||
if s in configdirs:
|
|
||||||
configdirs.remove(s)
|
|
||||||
if (len(configdirs) == 0):
|
|
||||||
print("===== The map you entered does not have a config! =====")
|
|
||||||
config = ""
|
|
||||||
return configdirs
|
|
||||||
|
|
||||||
def change_track(newname, config=""):
|
|
||||||
|
|
||||||
print(f"handling track change for {newname} with config {config}")
|
|
||||||
|
|
||||||
if newname not in get_all_tracks():
|
|
||||||
return False, f"Track '{newname}' does not exist!"
|
|
||||||
|
|
||||||
new_content = ""
|
|
||||||
|
|
||||||
config_file = os.path.join(CONFIG_PATH, CONFIG_FILE)
|
|
||||||
with open(config_file,'r') as file:
|
|
||||||
for line in file:
|
|
||||||
line = line.strip()
|
|
||||||
if line.startswith("TRACK="):
|
|
||||||
new_content += "TRACK=" + str(newname)
|
|
||||||
print("changing line " + line + " to " + "TRACK=" + str(newname))
|
|
||||||
elif line.startswith("CONFIG_TRACK="):
|
|
||||||
if (len(config) > 1):
|
|
||||||
new_content +="CONFIG_TRACK=" + str(config)
|
|
||||||
print("changing line " + line + " to " + "CONFIG_TRACK=" + str(config))
|
|
||||||
else:
|
|
||||||
new_content += "CONFIG_TRACK="
|
|
||||||
print("no config entered, setting config line to CONFIG_TRACK=")
|
|
||||||
else:
|
|
||||||
new_content += line
|
|
||||||
new_content += "\n"
|
|
||||||
|
|
||||||
with open(config_file,'w') as newfile:
|
|
||||||
newfile.write(new_content)
|
|
||||||
|
|
||||||
return True, f"Changed track to: {newname}"
|
|
||||||
100
index.html
100
index.html
@@ -18,12 +18,21 @@
|
|||||||
<img id="outline" src="" width="400">
|
<img id="outline" src="" width="400">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2>Choose cars</h2>
|
||||||
|
<button id="addCarBtn">Add Car</button>
|
||||||
|
|
||||||
|
<div id="carList"></div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const trackSelect = document.getElementById("trackSelect");
|
const trackSelect = document.getElementById("trackSelect");
|
||||||
const configSelect = document.getElementById("configSelect");
|
const configSelect = document.getElementById("configSelect");
|
||||||
const previewImg = document.getElementById("preview");
|
const previewImg = document.getElementById("preview");
|
||||||
const outlineImg = document.getElementById("outline");
|
const outlineImg = document.getElementById("outline");
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
updateTrack();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function updateTrack() {
|
function updateTrack() {
|
||||||
|
|
||||||
@@ -57,7 +66,7 @@
|
|||||||
outlineImg.src = "/img/outline/" + trackSelect.value + "/" + configSelect.value;
|
outlineImg.src = "/img/outline/" + trackSelect.value + "/" + configSelect.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function apply(){
|
function apply() {
|
||||||
const URL = '/changetrack/' + trackSelect.value + "/" + configSelect.value;
|
const URL = '/changetrack/' + trackSelect.value + "/" + configSelect.value;
|
||||||
fetch(URL, { method: "POST" })
|
fetch(URL, { method: "POST" })
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
@@ -71,6 +80,95 @@
|
|||||||
|
|
||||||
window.onload = updateTrack;
|
window.onload = updateTrack;
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
const addCarBtn = document.getElementById("addCarBtn");
|
||||||
|
const carList = document.getElementById("carList");
|
||||||
|
|
||||||
|
async function addCar() {
|
||||||
|
const wrapper = document.createElement("div");
|
||||||
|
wrapper.style.marginTop = "12px";
|
||||||
|
wrapper.className = "car-block";
|
||||||
|
|
||||||
|
// --- elementen ---
|
||||||
|
const carSelect = document.createElement("select");
|
||||||
|
carSelect.className = "car-select";
|
||||||
|
|
||||||
|
const skinSelect = document.createElement("select");
|
||||||
|
skinSelect.className = "skin-select";
|
||||||
|
skinSelect.style.marginLeft = "10px";
|
||||||
|
|
||||||
|
const img = document.createElement("img");
|
||||||
|
img.className = "skin-preview";
|
||||||
|
img.style.display = "block";
|
||||||
|
img.style.marginTop = "10px";
|
||||||
|
img.style.maxWidth = "200px";
|
||||||
|
|
||||||
|
wrapper.appendChild(carSelect);
|
||||||
|
wrapper.appendChild(skinSelect);
|
||||||
|
wrapper.appendChild(img);
|
||||||
|
carList.appendChild(wrapper);
|
||||||
|
|
||||||
|
// --- cars ophalen ---
|
||||||
|
const url = '/cars';
|
||||||
|
const res = await fetch(url);
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
const cars = data.cars; // array met cars
|
||||||
|
|
||||||
|
console.log(cars);
|
||||||
|
|
||||||
|
// cars inladen
|
||||||
|
cars.forEach(car => {
|
||||||
|
let o = document.createElement("option");
|
||||||
|
o.value = car.name; // of car.id
|
||||||
|
o.textContent = car.name;
|
||||||
|
carSelect.appendChild(o);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- helper: laad skins voor de geselecteerde car ---
|
||||||
|
function loadSkins(carName) {
|
||||||
|
const car = cars.find(c => c.name === carName);
|
||||||
|
skinSelect.innerHTML = "";
|
||||||
|
|
||||||
|
car.skins.forEach(cfg => {
|
||||||
|
let o = document.createElement("option");
|
||||||
|
o.value = cfg.name;
|
||||||
|
o.textContent = cfg.name;
|
||||||
|
skinSelect.appendChild(o);
|
||||||
|
});
|
||||||
|
|
||||||
|
// direct de eerste skin tonen
|
||||||
|
updateImage(car.skins[0].image);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- helper: update image ---
|
||||||
|
function updateImage(imgPath) {
|
||||||
|
img.src = imgPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- event: auto veranderen ---
|
||||||
|
carSelect.addEventListener("change", () => {
|
||||||
|
const selectedCar = carSelect.value;
|
||||||
|
loadSkins(selectedCar);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- event: skin veranderen ---
|
||||||
|
skinSelect.addEventListener("change", () => {
|
||||||
|
const selectedCar = carSelect.value;
|
||||||
|
const selectedSkin = skinSelect.value;
|
||||||
|
|
||||||
|
const car = cars.find(c => c.name === selectedCar);
|
||||||
|
const cfg = car.skins.find(x => x.name === selectedSkin);
|
||||||
|
|
||||||
|
updateImage(cfg.image);
|
||||||
|
});
|
||||||
|
|
||||||
|
// laad skins voor de eerste auto direct
|
||||||
|
loadSkins(cars[0].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCarBtn.addEventListener("click", addCar);
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user