Spaces:
Running on Zero
Running on Zero
Add matched four-vehicle support to ALD training
Browse filesPreserve vehicle Type 0–3 through network import, training and export. Select the packaged trusted vehicle scene, enforce original control-output rules and report vehicle identity for optional global Steam estimates. Keep the existing CPU-private and GPU-protected Space visibility settings and package member boundary unchanged.
- BETA_TESTING.md +1 -1
- BINARY_PROVENANCE.json +64 -16
- CUDA_REFERENCE.md +1 -1
- DATA_POLICY.md +1 -1
- FRONTEND_SOURCE.json +3 -3
- README.md +2 -2
- RELEASE_MANIFEST.json +15 -12
- assets/rally_template.json +112 -0
- assets/snowmobile_template.json +123 -0
- assets/truck_template.json +112 -0
- bin/altd-sim +2 -2
- bin/libaltd_gpu.so +2 -2
- client.js +4 -1
- index.html +37 -15
- server.py +4 -4
- worker.py +21 -3
BETA_TESTING.md
CHANGED
|
@@ -36,7 +36,7 @@ restricted source repository as the app entry point.
|
|
| 36 |
|
| 37 |
## Supported runner contract
|
| 38 |
|
| 39 |
-
The worker
|
| 40 |
|
| 41 |
The preview shows tile layout and terrain, not collision geometry. Star challenges are not evaluated.
|
| 42 |
|
|
|
|
| 36 |
|
| 37 |
## Supported runner contract
|
| 38 |
|
| 39 |
+
The worker preserves Formula (Type 0), Rally (Type 1), Snowmobile (Type 2), and Truck (Type 3) on import, in candidate exports, and in run reports. Formula imports retain legacy ordered output subsets. Fresh networks for all vehicles require Steering and Acceleration; Rally, Snowmobile and Truck imports must also retain those outputs. Snowmobile Handbrake is unavailable in the original editor. Networks allow at most 20 inputs (13 raycasts plus 7 other sensors), 12 total layers, and 16 neurons per hidden layer. The maximum is `[20]+[16]*10+[5]` (2,869 parameters) for Formula, Rally and Truck; Snowmobile has at most four outputs, `[20]+[16]*10+[4]` (2,852 parameters). All 13 game sensor types use original-game defaults for omitted parameters. These are vanilla worker limits, not support for arbitrary modified-game networks.
|
| 40 |
|
| 41 |
The preview shows tile layout and terrain, not collision geometry. Star challenges are not evaluated.
|
| 42 |
|
BINARY_PROVENANCE.json
CHANGED
|
@@ -1,24 +1,72 @@
|
|
| 1 |
{
|
| 2 |
-
"
|
| 3 |
-
"simulator_source_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f",
|
| 4 |
-
"simulator_source_space": "TiGa-RCE/ald-tao-gpu",
|
| 5 |
-
"simulator_source_space_revision": "ba07e35a39211af7a0deda0ebd9adb2c554b4f38",
|
| 6 |
-
"source_space_image_config": "sha256:31f7854e5fac0b54679eed2899c8951cd96571650ea6c74c27e2400a8c4aa6d3",
|
| 7 |
-
"importer_source_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f",
|
| 8 |
-
"ui_refresh_date": "2026-10-12",
|
| 9 |
-
"reason": "Current upstream b90b8af GH Actions library is HIP/ROCm and cannot run on NVIDIA ZeroGPU. This matched prior CUDA simulator/library pair supports the current Formula-only worker. The two newer upstream commits add snowmobile GPU support, which this worker does not expose.",
|
| 10 |
-
"artifacts": {
|
| 11 |
"bin/altd-sim": {
|
| 12 |
-
"
|
| 13 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
},
|
| 15 |
"bin/libaltd_gpu.so": {
|
| 16 |
-
"
|
| 17 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
},
|
| 19 |
"bin/extract_saved_track": {
|
| 20 |
-
"
|
| 21 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
}
|
| 23 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"artifact_origins": {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
"bin/altd-sim": {
|
| 4 |
+
"actions_run_id": 38203558700,
|
| 5 |
+
"archive_member": "altd-sim-nightly-x86_64-unknown-linux-gnu/altd-sim",
|
| 6 |
+
"bytes": 15774792,
|
| 7 |
+
"evidence_path": "build/receipts/upstream-altd-sim-nightly-x86_64-unknown-linux-gnu.tar.gz",
|
| 8 |
+
"evidence_sha256": "15ddf3cc8748a13ab123226ed328fb65acfaade08351f97a93686223aa2cceed",
|
| 9 |
+
"origin_type": "github_actions_archive_member",
|
| 10 |
+
"run_conclusion": "success",
|
| 11 |
+
"sha256": "0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166",
|
| 12 |
+
"source_archive_sha256": "15ddf3cc8748a13ab123226ed328fb65acfaade08351f97a93686223aa2cceed",
|
| 13 |
+
"source_repository": "https://github.com/Zorro909/driving_sim_rs",
|
| 14 |
+
"source_revision": "b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0"
|
| 15 |
+
},
|
| 16 |
+
"bin/extract_saved_track": {
|
| 17 |
+
"build_receipt_path": "cpu/IMPORTER_BUILD_RECEIPT.json",
|
| 18 |
+
"build_receipt_sha256": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
|
| 19 |
+
"bytes": 3247776,
|
| 20 |
+
"compatibility_receipt": "build/receipts/build-receipt.json",
|
| 21 |
+
"evidence_path": "cpu/IMPORTER_BUILD_RECEIPT.json",
|
| 22 |
+
"evidence_sha256": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
|
| 23 |
+
"origin_type": "retained_verified_importer_binary",
|
| 24 |
+
"sha256": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
|
| 25 |
+
"source_repository": "https://github.com/Zorro909/driving_sim_rs",
|
| 26 |
+
"source_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f"
|
| 27 |
},
|
| 28 |
"bin/libaltd_gpu.so": {
|
| 29 |
+
"build_command": "CUDA_ARCH=sm_86,sm_120 OUT=/work/artifacts/gpu bash /work/source/gpu/build-cuda.sh",
|
| 30 |
+
"build_log_path": "build/receipts/cuda-build.log",
|
| 31 |
+
"build_log_sha256": "c4ea4bde35aa972644dd3d6ad7511d097736547ab2afb216920e67b26d954be6",
|
| 32 |
+
"builder_image": "nvidia/cuda:13.0.2-devel-ubuntu22.04",
|
| 33 |
+
"builder_image_digest": "sha256:1c517d4fb96528c8999e14e6e6b16d7e2ff9ae8d194fd788d60fdc88e693e982",
|
| 34 |
+
"bytes": 4711704,
|
| 35 |
+
"compiled_architectures": [
|
| 36 |
+
"sm_86",
|
| 37 |
+
"sm_120",
|
| 38 |
+
"compute_120 PTX"
|
| 39 |
+
],
|
| 40 |
+
"evidence_path": "build/source-b90b8af.tar.gz",
|
| 41 |
+
"evidence_sha256": "e9e561c6d9c56cedf344aaf9d91f584a4d5730ccd26ac5a2bfa23c3eed9204e6",
|
| 42 |
+
"origin_type": "local_cuda_build",
|
| 43 |
+
"sha256": "3b1b88bccc06a21acc33ac4400af016d55a7e3d8727136a0c43b541f3c7887ca",
|
| 44 |
+
"source_archive_path": "build/source-b90b8af.tar.gz",
|
| 45 |
+
"source_archive_sha256": "e9e561c6d9c56cedf344aaf9d91f584a4d5730ccd26ac5a2bfa23c3eed9204e6",
|
| 46 |
+
"source_repository": "https://github.com/Zorro909/driving_sim_rs",
|
| 47 |
+
"source_revision": "b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0"
|
| 48 |
+
}
|
| 49 |
+
},
|
| 50 |
+
"artifacts": {
|
| 51 |
+
"bin/altd-sim": {
|
| 52 |
+
"bytes": 15774792,
|
| 53 |
+
"sha256": "0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166"
|
| 54 |
},
|
| 55 |
"bin/extract_saved_track": {
|
| 56 |
+
"bytes": 3247776,
|
| 57 |
+
"sha256": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a"
|
| 58 |
+
},
|
| 59 |
+
"bin/libaltd_gpu.so": {
|
| 60 |
+
"bytes": 4711704,
|
| 61 |
+
"sha256": "3b1b88bccc06a21acc33ac4400af016d55a7e3d8727136a0c43b541f3c7887ca"
|
| 62 |
}
|
| 63 |
+
},
|
| 64 |
+
"build_receipt": "../build/receipts/build-receipt.json",
|
| 65 |
+
"build_receipt_sha256": "789806b8d70b73a718e889fb202171c18b50070e04a70ab57af9b93d0ad58a76",
|
| 66 |
+
"github_actions_run": 38203558700,
|
| 67 |
+
"importer_source_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f",
|
| 68 |
+
"note": "The simulator is the exact b90 Linux Actions artifact; the CUDA library is built from the same b90 source for sm_86 and sm_120 with compute_120 PTX. Rust/C layout ABI validation passed. No CUDA device or kernel execution was available in the local builder; hosted CUDA qualification remains separate. The retained d8 track importer is separately identified and bounded compatibility is linked.",
|
| 69 |
+
"run_conclusion": "success",
|
| 70 |
+
"source_repository": "https://github.com/Zorro909/driving_sim_rs",
|
| 71 |
+
"source_revision": "b90b8af06ffc4ea4e4fd703becd1107a48b8e5e0"
|
| 72 |
}
|
CUDA_REFERENCE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Bounded CPU/CUDA reference check
|
| 2 |
|
| 3 |
-
This protocol defines a reproducible generated input for qualifying the package's largest vanilla Formula network through the native simulator. A passing run covers only the selected B01 track, fixture, settings, and build. It does not establish broad original-game parity, training quality, or general CPU/CUDA equivalence.
|
| 4 |
|
| 5 |
## Public-package fixture
|
| 6 |
|
|
|
|
| 1 |
# Bounded CPU/CUDA reference check
|
| 2 |
|
| 3 |
+
This protocol defines a reproducible generated input for qualifying the package's largest vanilla Formula network through the native simulator. This maximum five-output Formula fixture is one bounded qualification case; separate vehicle-specific runtime checks are required for Rally, Snowmobile and Truck. A passing run covers only the selected B01 track, fixture, settings, and build. It does not establish broad original-game parity, training quality, or general CPU/CUDA equivalence.
|
| 4 |
|
| 5 |
## Public-package fixture
|
| 6 |
|
DATA_POLICY.md
CHANGED
|
@@ -112,7 +112,7 @@ turn public ephemeral storage into persistent storage.
|
|
| 112 |
|
| 113 |
## Optional public Steam leaderboard check
|
| 114 |
|
| 115 |
-
The “After a completed lap” checkbox is off by default. With it off, or when a run reports no completed lap, the browser makes no leaderboard request. When enabled, the browser sends only the built-in track ID and hash,
|
| 116 |
|
| 117 |
The app reads the public Steam Community track index and matching board XML without a Steam login or publisher key. It resolves exact catalog reference labels against that live index; an absent or ambiguous mapping is unavailable. The app retains only a short-lived in-process cache of public board rank/time rows (up to 60 seconds) and the public index mapping (up to five minutes). Player names, Steam IDs and raw XML are discarded after parsing. The comparison request and result are not stored in the job result store or recipe library.
|
| 118 |
|
|
|
|
| 112 |
|
| 113 |
## Optional public Steam leaderboard check
|
| 114 |
|
| 115 |
+
The “After a completed lap” checkbox is off by default. With it off, or when a run reports no completed lap, the browser makes no leaderboard request. When enabled, the browser sends only the built-in track ID and hash, reported vehicle type (Formula, Rally, Snowmobile or Truck), and best-lap seconds to this app's same-origin server. Custom or unidentified tracks are not sent. HF does not forward the lap, network, Steam ID, account credential, file name or other run data to Steam.
|
| 116 |
|
| 117 |
The app reads the public Steam Community track index and matching board XML without a Steam login or publisher key. It resolves exact catalog reference labels against that live index; an absent or ambiguous mapping is unavailable. The app retains only a short-lived in-process cache of public board rank/time rows (up to 60 seconds) and the public index mapping (up to five minutes). Player names, Steam IDs and raw XML are discarded after parsing. The comparison request and result are not stored in the job result store or recipe library.
|
| 118 |
|
FRONTEND_SOURCE.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
{
|
| 2 |
"source": "Runner r14 single-engine browser UI; selected .track tile renderer added from simulator atlas",
|
| 3 |
"source_sha256": "65d1e5f2c4e19b4951b828e82510005ab99a5270cf3dcb9f4eaa0fa1af8c40f8",
|
| 4 |
-
"output_sha256": "
|
| 5 |
"scope": "Frontend only; no engine, private data, track assets, API calls or storage copied",
|
| 6 |
-
"status": "
|
| 7 |
"track_atlas_sha256": "d97c8900e3e5fb17734b5bd61d1f4f4b196d9be30af9848e2e273ae7e4079ae4",
|
| 8 |
-
"client_sha256": "
|
| 9 |
"track_map_sha256": "ab5374aa49c7ccec90a787ee8c56cd71beb56b903bf2bbc322783e6f43c009f0"
|
| 10 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"source": "Runner r14 single-engine browser UI; selected .track tile renderer added from simulator atlas",
|
| 3 |
"source_sha256": "65d1e5f2c4e19b4951b828e82510005ab99a5270cf3dcb9f4eaa0fa1af8c40f8",
|
| 4 |
+
"output_sha256": "ef759a06305e94edb5ed0e49a587db8c39e3833ec2e02a1bec441c0287c385fd",
|
| 5 |
"scope": "Frontend only; no engine, private data, track assets, API calls or storage copied",
|
| 6 |
+
"status": "Four vehicle UI and Type plumbing; native vehicle support pending runtime qualification; optional Steam comparison",
|
| 7 |
"track_atlas_sha256": "d97c8900e3e5fb17734b5bd61d1f4f4b196d9be30af9848e2e273ae7e4079ae4",
|
| 8 |
+
"client_sha256": "f227469481a6a393f78636fde214473f54219c8af016050b35c6ef1af86eff34",
|
| 9 |
"track_map_sha256": "ab5374aa49c7ccec90a787ee8c56cd71beb56b903bf2bbc322783e6f43c009f0"
|
| 10 |
}
|
README.md
CHANGED
|
@@ -8,9 +8,9 @@ hf_oauth: true
|
|
| 8 |
hf_oauth_expiration_minutes: 60
|
| 9 |
---
|
| 10 |
|
| 11 |
-
Public GPU app package. Its intended topology is a publicly reachable app at https://tiga-rce-ald-tao-gpu.hf.space/ with the GPU Space source repository restricted; the standalone CPU Space remains private. Deployment status and build-specific qualification are recorded in the release receipt. The native Formula
|
| 12 |
|
| 13 |
-
The selected track map previews tile layout and asphalt/dirt/ice directly from the selected file. Twenty-eight reconstructed editor-format tracks are included. Settings-only recipes and batches save in the visitor's browser. Formula networks
|
| 14 |
|
| 15 |
Application-controlled inputs and intermediate files are temporary. Outputs are held in memory for at most five minutes and deleted sooner after verified download by default; a single-run visitor may explicitly keep the result until that five-minute deadline. This is not a provider-wide zero-data-retention guarantee. Read DATA_POLICY.md and TRACK_LIBRARY.md. Upstream code and license: https://github.com/Zorro909/driving_sim_rs. Open upstream PRs 19 and 21 are not included.
|
| 16 |
|
|
|
|
| 8 |
hf_oauth_expiration_minutes: 60
|
| 9 |
---
|
| 10 |
|
| 11 |
+
Public GPU app package. Its intended topology is a publicly reachable app at https://tiga-rce-ald-tao-gpu.hf.space/ with the GPU Space source repository restricted; the standalone CPU Space remains private. Deployment status and build-specific qualification are recorded in the release receipt. The native runner accepts Formula (Type 0), Rally (Type 1), Snowmobile (Type 2), and Truck (Type 3) networks and selects a packaged trusted scene template from the network type. Build-specific native vehicle support must be qualified with the matching simulator and importer binaries recorded in the release receipt. CPU runs anonymously. GPU is explicitly selected and subject to available HF allowance; optional HF sign-in uses the official OAuth flow and needs no personal token entry.
|
| 12 |
|
| 13 |
+
The selected track map previews tile layout and asphalt/dirt/ice directly from the selected file. Twenty-eight reconstructed editor-format tracks are included. Settings-only recipes and batches save in the visitor's browser. Formula networks preserve legacy ordered output subsets. Fresh networks for all vehicles require Steering and Acceleration. Rally, Snowmobile and Truck imports must also retain those required outputs; Snowmobile cannot use Handbrake. Formula imports keep the previously supported ordered subsets. Networks have at most 20 inputs (13 raycasts plus 7 other sensors), 12 total layers and 16 neurons per hidden layer. The maximum is `[20]+[16]*10+[5]` (2,869 parameters) for Formula, Rally and Truck; Snowmobile uses up to four outputs (`[20]+[16]*10+[4]`, 2,852 parameters). All 13 game sensor types use original-game defaults for omitted parameters. These limits describe this vanilla worker contract, not unrestricted modified-game networks.
|
| 14 |
|
| 15 |
Application-controlled inputs and intermediate files are temporary. Outputs are held in memory for at most five minutes and deleted sooner after verified download by default; a single-run visitor may explicitly keep the result until that five-minute deadline. This is not a provider-wide zero-data-retention guarantee. Read DATA_POLICY.md and TRACK_LIBRARY.md. Upstream code and license: https://github.com/Zorro909/driving_sim_rs. Open upstream PRs 19 and 21 are not included.
|
| 16 |
|
RELEASE_MANIFEST.json
CHANGED
|
@@ -2,26 +2,29 @@
|
|
| 2 |
"backend": "cpu+zerogpu",
|
| 3 |
"files": {
|
| 4 |
".gitattributes": "c2ad16718fc51c888d32efc88c8f6e23ebe5fcf6f48e2954f896ba9770f24d72",
|
| 5 |
-
"BETA_TESTING.md": "
|
| 6 |
-
"BINARY_PROVENANCE.json": "
|
| 7 |
-
"CUDA_REFERENCE.md": "
|
| 8 |
-
"DATA_POLICY.md": "
|
| 9 |
"FEEDBACK.md": "f95b8f6afbf4a360976c0edca5d52f5b3a0b668c9a944d4947b840a7c53a122a",
|
| 10 |
-
"FRONTEND_SOURCE.json": "
|
| 11 |
"GODOT_LICENSE": "fb2b3bb82c60f1e76841ba2122eb902f8e39c151476fe21ce10c9a05d1045304",
|
| 12 |
"IMPORTER_BUILD_RECEIPT.json": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
|
| 13 |
"LICENSE": "53d5851b6440feeae36f72a5f57fcab37858c48b7084765ece4b0c54b9a28ed8",
|
| 14 |
-
"README.md": "
|
| 15 |
"STORAGE_BOUNDARY.md": "9a1ffb5854230690dba3f0895f9a8e570716de47be2c553de13a6892dd740015",
|
| 16 |
"TRACK_LIBRARY.md": "66b3656ed84f137d5b6116a0075731cd467818f555cca0969084aff67875319f",
|
| 17 |
"UPSTREAM.json": "40a2f31fa9abc11e47e247c56909b93b587d1f5be524ab158b24f1f9eed93765",
|
| 18 |
"app.py": "162486abd6ac7c9281c8e75c15e33373e0fddba2baf6a799dfd54d333fd575d2",
|
| 19 |
"app_release.py": "7482559c667a665fd3cb6aa8af6c78422a822b515e14589db8306f7fd4860a8b",
|
| 20 |
"assets/formula_template.json": "80f745df82bb7be45af52785fd582460bcddc63c5a4e1d8375d85b3122db4c6b",
|
|
|
|
|
|
|
| 21 |
"assets/track-atlas.json": "d97c8900e3e5fb17734b5bd61d1f4f4b196d9be30af9848e2e273ae7e4079ae4",
|
| 22 |
-
"
|
|
|
|
| 23 |
"bin/extract_saved_track": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
|
| 24 |
-
"bin/libaltd_gpu.so": "
|
| 25 |
"build_info.py": "93d331c0405cd10076a544f87761bb4a00f6556bbbdab8abc12e070c4661bd78",
|
| 26 |
"builtin_tracks.py": "2ecc2b1d00fe15701b0271d71e1e68d2e7e59c596330879494055f9b2a99c242",
|
| 27 |
"builtin_tracks/catalog.json": "65006e70a87a5a53e3738166b0895bc4db9f99767dd891d917b68029abb4e80a",
|
|
@@ -53,14 +56,14 @@
|
|
| 53 |
"builtin_tracks/tracks/Replica R08 Demolition Derby.track": "6f11a9ffbcb477c9d19964566b1b612d2a94675605246e93e21f27bbbdb357ef",
|
| 54 |
"builtin_tracks/tracks/Replica R09 Eau Noir.track": "3ec0a78478cca1a4f0d2d98ac81f40783928adf271b70f0c32d295a6da2cdaa9",
|
| 55 |
"builtin_tracks/tracks/Replica The Champions Trial.track": "a3bfb76422affc774b44c739b0636d08acb901fa7615b9adcb52c069f79834e1",
|
| 56 |
-
"client.js": "
|
| 57 |
"delivery.py": "07453999c3831a16e8b1fcc2b4ae5fb28beb7d3952a3fae8de65d16eb6f11e5b",
|
| 58 |
"gpu_tickets.py": "b81aadb5ed42cec9212d44da7e7bbb7b413c5bd517383cac0b49ec9b4d659c92",
|
| 59 |
"hf-auth.js": "d5cf17b961d1f2efa9d4648d33ba86a148eff0d542c74a121710c4df35c92936",
|
| 60 |
"hf_identity.py": "6993d0238ada835606dbdc3275c17a3fe5a5cac5ad2156ab78230acf2d051eba",
|
| 61 |
-
"index.html": "
|
| 62 |
"requirements.txt": "9b532747e51bd052e82090ece860d6dafe027407f4512dc74272c148ea104c22",
|
| 63 |
-
"server.py": "
|
| 64 |
"steam_leaderboard.py": "d76397c39cae58f636ddf9a9be1a46ae3d77fefd6b7269feac73d34d97165481",
|
| 65 |
"track-library.js": "351ec4c026b49420ce963f4310cb000d9e987fd28e6dac5ecd0176509340f6e6",
|
| 66 |
"track-map.js": "ab5374aa49c7ccec90a787ee8c56cd71beb56b903bf2bbc322783e6f43c009f0",
|
|
@@ -71,7 +74,7 @@
|
|
| 71 |
"vendor/hf-oauth/LICENSE": "d6e7b19451c1b3d1d66353bb4b1274138953b3bfd9ae60c56e77b1f548796982",
|
| 72 |
"vendor/hf-oauth/index.js": "53282844000a171011e547f6472a3846bb4cecb5071adafea079fcac3a2aee7e",
|
| 73 |
"vendor/hf-oauth/package.json": "fafd4d8891023a1961546a7d3bc25cd24f64923a2ebfc449fe6d516a2949bda8",
|
| 74 |
-
"worker.py": "
|
| 75 |
},
|
| 76 |
"interface": "single-engine-runner-with-map",
|
| 77 |
"upstream_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f"
|
|
|
|
| 2 |
"backend": "cpu+zerogpu",
|
| 3 |
"files": {
|
| 4 |
".gitattributes": "c2ad16718fc51c888d32efc88c8f6e23ebe5fcf6f48e2954f896ba9770f24d72",
|
| 5 |
+
"BETA_TESTING.md": "27e2492f9fe87cc04f52de2974b685b44041f7de9fa1155926b66c436f0bc613",
|
| 6 |
+
"BINARY_PROVENANCE.json": "825d98f9ae91d88ee08143b11d1af9dd6f889c37f68dbea24163f718759dda3e",
|
| 7 |
+
"CUDA_REFERENCE.md": "f7453c3254d244f8b0de41fde5851cb025159f5cea4a4d1a5d8208a955550c6c",
|
| 8 |
+
"DATA_POLICY.md": "d5a4066759c823a34ad68a04cf7d9bfa2e39441b24b9466984d06fdb38eb566c",
|
| 9 |
"FEEDBACK.md": "f95b8f6afbf4a360976c0edca5d52f5b3a0b668c9a944d4947b840a7c53a122a",
|
| 10 |
+
"FRONTEND_SOURCE.json": "165fc6a32b0c132e73679ad7e69a1b30376ea0ac6a789283b22206e98d7212c9",
|
| 11 |
"GODOT_LICENSE": "fb2b3bb82c60f1e76841ba2122eb902f8e39c151476fe21ce10c9a05d1045304",
|
| 12 |
"IMPORTER_BUILD_RECEIPT.json": "4ba5c533cc617105478e4d85c83f456a7dfa68b1388049624619871ba9e42e9d",
|
| 13 |
"LICENSE": "53d5851b6440feeae36f72a5f57fcab37858c48b7084765ece4b0c54b9a28ed8",
|
| 14 |
+
"README.md": "b2e1d4a21c1ffd0d652a6e2448284b358f4e42dbfa8a0af6b1842d55c2f7c954",
|
| 15 |
"STORAGE_BOUNDARY.md": "9a1ffb5854230690dba3f0895f9a8e570716de47be2c553de13a6892dd740015",
|
| 16 |
"TRACK_LIBRARY.md": "66b3656ed84f137d5b6116a0075731cd467818f555cca0969084aff67875319f",
|
| 17 |
"UPSTREAM.json": "40a2f31fa9abc11e47e247c56909b93b587d1f5be524ab158b24f1f9eed93765",
|
| 18 |
"app.py": "162486abd6ac7c9281c8e75c15e33373e0fddba2baf6a799dfd54d333fd575d2",
|
| 19 |
"app_release.py": "7482559c667a665fd3cb6aa8af6c78422a822b515e14589db8306f7fd4860a8b",
|
| 20 |
"assets/formula_template.json": "80f745df82bb7be45af52785fd582460bcddc63c5a4e1d8375d85b3122db4c6b",
|
| 21 |
+
"assets/rally_template.json": "7350a3fe28d9b4da7a0965ae6ea7ca3472fb7885303e342310d63a0dce80851c",
|
| 22 |
+
"assets/snowmobile_template.json": "12d30545876011fd6fccdd3e721f9c465938c9c58ac99338205481d5e7ac6742",
|
| 23 |
"assets/track-atlas.json": "d97c8900e3e5fb17734b5bd61d1f4f4b196d9be30af9848e2e273ae7e4079ae4",
|
| 24 |
+
"assets/truck_template.json": "a83bffea4d5e818c135ab3aba68a47aa288d6ad0e7b8bd9c95ed0dea9e9df2f7",
|
| 25 |
+
"bin/altd-sim": "0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166",
|
| 26 |
"bin/extract_saved_track": "3a7733c45b4301a786fcbfe92660a1c484749272da5f608d62f34878bd4ff31a",
|
| 27 |
+
"bin/libaltd_gpu.so": "3b1b88bccc06a21acc33ac4400af016d55a7e3d8727136a0c43b541f3c7887ca",
|
| 28 |
"build_info.py": "93d331c0405cd10076a544f87761bb4a00f6556bbbdab8abc12e070c4661bd78",
|
| 29 |
"builtin_tracks.py": "2ecc2b1d00fe15701b0271d71e1e68d2e7e59c596330879494055f9b2a99c242",
|
| 30 |
"builtin_tracks/catalog.json": "65006e70a87a5a53e3738166b0895bc4db9f99767dd891d917b68029abb4e80a",
|
|
|
|
| 56 |
"builtin_tracks/tracks/Replica R08 Demolition Derby.track": "6f11a9ffbcb477c9d19964566b1b612d2a94675605246e93e21f27bbbdb357ef",
|
| 57 |
"builtin_tracks/tracks/Replica R09 Eau Noir.track": "3ec0a78478cca1a4f0d2d98ac81f40783928adf271b70f0c32d295a6da2cdaa9",
|
| 58 |
"builtin_tracks/tracks/Replica The Champions Trial.track": "a3bfb76422affc774b44c739b0636d08acb901fa7615b9adcb52c069f79834e1",
|
| 59 |
+
"client.js": "f227469481a6a393f78636fde214473f54219c8af016050b35c6ef1af86eff34",
|
| 60 |
"delivery.py": "07453999c3831a16e8b1fcc2b4ae5fb28beb7d3952a3fae8de65d16eb6f11e5b",
|
| 61 |
"gpu_tickets.py": "b81aadb5ed42cec9212d44da7e7bbb7b413c5bd517383cac0b49ec9b4d659c92",
|
| 62 |
"hf-auth.js": "d5cf17b961d1f2efa9d4648d33ba86a148eff0d542c74a121710c4df35c92936",
|
| 63 |
"hf_identity.py": "6993d0238ada835606dbdc3275c17a3fe5a5cac5ad2156ab78230acf2d051eba",
|
| 64 |
+
"index.html": "ef759a06305e94edb5ed0e49a587db8c39e3833ec2e02a1bec441c0287c385fd",
|
| 65 |
"requirements.txt": "9b532747e51bd052e82090ece860d6dafe027407f4512dc74272c148ea104c22",
|
| 66 |
+
"server.py": "e00369e6840f0cab5350824e95fc0577ae59524d87ad0a34c32795708be17662",
|
| 67 |
"steam_leaderboard.py": "d76397c39cae58f636ddf9a9be1a46ae3d77fefd6b7269feac73d34d97165481",
|
| 68 |
"track-library.js": "351ec4c026b49420ce963f4310cb000d9e987fd28e6dac5ecd0176509340f6e6",
|
| 69 |
"track-map.js": "ab5374aa49c7ccec90a787ee8c56cd71beb56b903bf2bbc322783e6f43c009f0",
|
|
|
|
| 74 |
"vendor/hf-oauth/LICENSE": "d6e7b19451c1b3d1d66353bb4b1274138953b3bfd9ae60c56e77b1f548796982",
|
| 75 |
"vendor/hf-oauth/index.js": "53282844000a171011e547f6472a3846bb4cecb5071adafea079fcac3a2aee7e",
|
| 76 |
"vendor/hf-oauth/package.json": "fafd4d8891023a1961546a7d3bc25cd24f64923a2ebfc449fe6d516a2949bda8",
|
| 77 |
+
"worker.py": "481ba85e6edceb0ed6aa993b028029a2f10ab2d7c983ef16c2a4cdcd7c084894"
|
| 78 |
},
|
| 79 |
"interface": "single-engine-runner-with-map",
|
| 80 |
"upstream_revision": "d8ab74c25df70b6a86ed101080e33d5fb785ea6f"
|
assets/rally_template.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"vehicle": {
|
| 3 |
+
"type": "Rally",
|
| 4 |
+
"mass": 3,
|
| 5 |
+
"inertia_property": 0,
|
| 6 |
+
"inertia_server": 1171.25,
|
| 7 |
+
"shape_size": [
|
| 8 |
+
62,
|
| 9 |
+
29
|
| 10 |
+
],
|
| 11 |
+
"shape_position": [
|
| 12 |
+
0,
|
| 13 |
+
0
|
| 14 |
+
],
|
| 15 |
+
"shape_rotation": 1.5708,
|
| 16 |
+
"gravity_scale": 1,
|
| 17 |
+
"linear_damp": 0,
|
| 18 |
+
"angular_damp": 0,
|
| 19 |
+
"max_contacts_reported": 4,
|
| 20 |
+
"continuous_cd": "Disabled",
|
| 21 |
+
"friction": 0.95,
|
| 22 |
+
"bounce": 0.1,
|
| 23 |
+
"grip": 2.25,
|
| 24 |
+
"steering_speed": 0.4000000059604645,
|
| 25 |
+
"center_steering": true,
|
| 26 |
+
"air_resistance": 0.15,
|
| 27 |
+
"max_velocity": 1000,
|
| 28 |
+
"surfaces": {
|
| 29 |
+
"asphalt": {
|
| 30 |
+
"grip": 1,
|
| 31 |
+
"power": 0.77,
|
| 32 |
+
"steering": 1
|
| 33 |
+
},
|
| 34 |
+
"dirt": {
|
| 35 |
+
"grip": 0.9,
|
| 36 |
+
"power": 0.82,
|
| 37 |
+
"steering": 1
|
| 38 |
+
},
|
| 39 |
+
"ice": {
|
| 40 |
+
"grip": 0.42,
|
| 41 |
+
"power": 0.6,
|
| 42 |
+
"steering": 1
|
| 43 |
+
}
|
| 44 |
+
},
|
| 45 |
+
"wheels": [
|
| 46 |
+
{
|
| 47 |
+
"position": [
|
| 48 |
+
-14,
|
| 49 |
+
-24
|
| 50 |
+
],
|
| 51 |
+
"steering": true,
|
| 52 |
+
"max_angle_deg": 35,
|
| 53 |
+
"power": 2.5,
|
| 54 |
+
"brake_power": 3.5,
|
| 55 |
+
"handbrake_power": 0
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"position": [
|
| 59 |
+
14,
|
| 60 |
+
-24
|
| 61 |
+
],
|
| 62 |
+
"steering": true,
|
| 63 |
+
"max_angle_deg": 35,
|
| 64 |
+
"power": 2.5,
|
| 65 |
+
"brake_power": 3.5,
|
| 66 |
+
"handbrake_power": 0
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"position": [
|
| 70 |
+
-14,
|
| 71 |
+
24
|
| 72 |
+
],
|
| 73 |
+
"steering": false,
|
| 74 |
+
"max_angle_deg": 0,
|
| 75 |
+
"power": 3.5,
|
| 76 |
+
"brake_power": 0,
|
| 77 |
+
"handbrake_power": 0
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"position": [
|
| 81 |
+
14,
|
| 82 |
+
24
|
| 83 |
+
],
|
| 84 |
+
"steering": false,
|
| 85 |
+
"max_angle_deg": 0,
|
| 86 |
+
"power": 3.5,
|
| 87 |
+
"brake_power": 0,
|
| 88 |
+
"handbrake_power": 0
|
| 89 |
+
}
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
"physics": {
|
| 93 |
+
"real_precision": "single",
|
| 94 |
+
"contact_recycle_radius": 1,
|
| 95 |
+
"contact_max_separation": 1.5,
|
| 96 |
+
"contact_max_allowed_penetration": 0.3,
|
| 97 |
+
"contact_default_bias": 0.8,
|
| 98 |
+
"solver_iterations": 16
|
| 99 |
+
},
|
| 100 |
+
"track": {
|
| 101 |
+
"name": "Generated track template",
|
| 102 |
+
"tiles": [],
|
| 103 |
+
"path": [],
|
| 104 |
+
"walls": [],
|
| 105 |
+
"physics_shapes": []
|
| 106 |
+
},
|
| 107 |
+
"reset_position": [
|
| 108 |
+
0,
|
| 109 |
+
0
|
| 110 |
+
],
|
| 111 |
+
"reset_rotation": 0
|
| 112 |
+
}
|
assets/snowmobile_template.json
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"vehicle": {
|
| 3 |
+
"type": "Snowmobile",
|
| 4 |
+
"mass": 1.5,
|
| 5 |
+
"inertia_property": 0,
|
| 6 |
+
"inertia_server": 552.625732421875,
|
| 7 |
+
"shape_size": [
|
| 8 |
+
65,
|
| 9 |
+
14.0002
|
| 10 |
+
],
|
| 11 |
+
"shape_position": [
|
| 12 |
+
-0.000114441,
|
| 13 |
+
0.499986
|
| 14 |
+
],
|
| 15 |
+
"shape_rotation": 1.5708,
|
| 16 |
+
"gravity_scale": 1,
|
| 17 |
+
"linear_damp": 0,
|
| 18 |
+
"angular_damp": 0,
|
| 19 |
+
"max_contacts_reported": 4,
|
| 20 |
+
"continuous_cd": "Disabled",
|
| 21 |
+
"friction": 0.95,
|
| 22 |
+
"bounce": 0.1,
|
| 23 |
+
"grip": 2,
|
| 24 |
+
"steering_speed": 0.2,
|
| 25 |
+
"center_steering": true,
|
| 26 |
+
"air_resistance": 0.3,
|
| 27 |
+
"max_velocity": 600,
|
| 28 |
+
"surfaces": {
|
| 29 |
+
"asphalt": {
|
| 30 |
+
"grip": 0.9,
|
| 31 |
+
"power": 0.9,
|
| 32 |
+
"steering": 0.25
|
| 33 |
+
},
|
| 34 |
+
"dirt": {
|
| 35 |
+
"grip": 0.7,
|
| 36 |
+
"power": 0.8,
|
| 37 |
+
"steering": 0.7
|
| 38 |
+
},
|
| 39 |
+
"ice": {
|
| 40 |
+
"grip": 0.4,
|
| 41 |
+
"power": 0.8,
|
| 42 |
+
"steering": 0.7
|
| 43 |
+
}
|
| 44 |
+
},
|
| 45 |
+
"wheels": [
|
| 46 |
+
{
|
| 47 |
+
"position": [
|
| 48 |
+
-10,
|
| 49 |
+
-25
|
| 50 |
+
],
|
| 51 |
+
"steering": true,
|
| 52 |
+
"max_angle_deg": 35,
|
| 53 |
+
"power": 0,
|
| 54 |
+
"brake_power": 0,
|
| 55 |
+
"handbrake_power": 0
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"position": [
|
| 59 |
+
10,
|
| 60 |
+
-25
|
| 61 |
+
],
|
| 62 |
+
"steering": true,
|
| 63 |
+
"max_angle_deg": 35,
|
| 64 |
+
"power": 0,
|
| 65 |
+
"brake_power": 0,
|
| 66 |
+
"handbrake_power": 0
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"position": [
|
| 70 |
+
0,
|
| 71 |
+
28
|
| 72 |
+
],
|
| 73 |
+
"steering": false,
|
| 74 |
+
"max_angle_deg": 0,
|
| 75 |
+
"power": 1.3,
|
| 76 |
+
"brake_power": 1.5,
|
| 77 |
+
"handbrake_power": 0
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"position": [
|
| 81 |
+
0,
|
| 82 |
+
22
|
| 83 |
+
],
|
| 84 |
+
"steering": false,
|
| 85 |
+
"max_angle_deg": 0,
|
| 86 |
+
"power": 1.3,
|
| 87 |
+
"brake_power": 1.5,
|
| 88 |
+
"handbrake_power": 0
|
| 89 |
+
},
|
| 90 |
+
{
|
| 91 |
+
"position": [
|
| 92 |
+
0,
|
| 93 |
+
16
|
| 94 |
+
],
|
| 95 |
+
"steering": false,
|
| 96 |
+
"max_angle_deg": 0,
|
| 97 |
+
"power": 1.3,
|
| 98 |
+
"brake_power": 1.5,
|
| 99 |
+
"handbrake_power": 0
|
| 100 |
+
}
|
| 101 |
+
]
|
| 102 |
+
},
|
| 103 |
+
"physics": {
|
| 104 |
+
"real_precision": "single",
|
| 105 |
+
"contact_recycle_radius": 1,
|
| 106 |
+
"contact_max_separation": 1.5,
|
| 107 |
+
"contact_max_allowed_penetration": 0.3,
|
| 108 |
+
"contact_default_bias": 0.8,
|
| 109 |
+
"solver_iterations": 16
|
| 110 |
+
},
|
| 111 |
+
"track": {
|
| 112 |
+
"name": "Generated track template",
|
| 113 |
+
"tiles": [],
|
| 114 |
+
"path": [],
|
| 115 |
+
"walls": [],
|
| 116 |
+
"physics_shapes": []
|
| 117 |
+
},
|
| 118 |
+
"reset_position": [
|
| 119 |
+
0,
|
| 120 |
+
0
|
| 121 |
+
],
|
| 122 |
+
"reset_rotation": 0
|
| 123 |
+
}
|
assets/truck_template.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"vehicle": {
|
| 3 |
+
"type": "Truck",
|
| 4 |
+
"mass": 8,
|
| 5 |
+
"inertia_property": 0,
|
| 6 |
+
"inertia_server": 11059.5,
|
| 7 |
+
"shape_size": [
|
| 8 |
+
124.5,
|
| 9 |
+
33
|
| 10 |
+
],
|
| 11 |
+
"shape_position": [
|
| 12 |
+
0,
|
| 13 |
+
1.25
|
| 14 |
+
],
|
| 15 |
+
"shape_rotation": 1.5708,
|
| 16 |
+
"gravity_scale": 1,
|
| 17 |
+
"linear_damp": 0,
|
| 18 |
+
"angular_damp": 0,
|
| 19 |
+
"max_contacts_reported": 4,
|
| 20 |
+
"continuous_cd": "Disabled",
|
| 21 |
+
"friction": 0.95,
|
| 22 |
+
"bounce": 0.1,
|
| 23 |
+
"grip": 12,
|
| 24 |
+
"steering_speed": 0.15,
|
| 25 |
+
"center_steering": true,
|
| 26 |
+
"air_resistance": 0.4,
|
| 27 |
+
"max_velocity": 600,
|
| 28 |
+
"surfaces": {
|
| 29 |
+
"asphalt": {
|
| 30 |
+
"grip": 1,
|
| 31 |
+
"power": 0.85,
|
| 32 |
+
"steering": 1
|
| 33 |
+
},
|
| 34 |
+
"dirt": {
|
| 35 |
+
"grip": 0.65,
|
| 36 |
+
"power": 0.8,
|
| 37 |
+
"steering": 1
|
| 38 |
+
},
|
| 39 |
+
"ice": {
|
| 40 |
+
"grip": 0.15,
|
| 41 |
+
"power": 0.7,
|
| 42 |
+
"steering": 1
|
| 43 |
+
}
|
| 44 |
+
},
|
| 45 |
+
"wheels": [
|
| 46 |
+
{
|
| 47 |
+
"position": [
|
| 48 |
+
-17,
|
| 49 |
+
-51
|
| 50 |
+
],
|
| 51 |
+
"steering": true,
|
| 52 |
+
"max_angle_deg": 22,
|
| 53 |
+
"power": 0,
|
| 54 |
+
"brake_power": 3.5,
|
| 55 |
+
"handbrake_power": 0
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"position": [
|
| 59 |
+
17,
|
| 60 |
+
-51
|
| 61 |
+
],
|
| 62 |
+
"steering": true,
|
| 63 |
+
"max_angle_deg": 22,
|
| 64 |
+
"power": 0,
|
| 65 |
+
"brake_power": 3.5,
|
| 66 |
+
"handbrake_power": 0
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"position": [
|
| 70 |
+
-17,
|
| 71 |
+
46
|
| 72 |
+
],
|
| 73 |
+
"steering": false,
|
| 74 |
+
"max_angle_deg": 0,
|
| 75 |
+
"power": 6,
|
| 76 |
+
"brake_power": 3,
|
| 77 |
+
"handbrake_power": 3
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"position": [
|
| 81 |
+
17,
|
| 82 |
+
46
|
| 83 |
+
],
|
| 84 |
+
"steering": false,
|
| 85 |
+
"max_angle_deg": 0,
|
| 86 |
+
"power": 6,
|
| 87 |
+
"brake_power": 3,
|
| 88 |
+
"handbrake_power": 3
|
| 89 |
+
}
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
"physics": {
|
| 93 |
+
"real_precision": "single",
|
| 94 |
+
"contact_recycle_radius": 1,
|
| 95 |
+
"contact_max_separation": 1.5,
|
| 96 |
+
"contact_max_allowed_penetration": 0.3,
|
| 97 |
+
"contact_default_bias": 0.8,
|
| 98 |
+
"solver_iterations": 16
|
| 99 |
+
},
|
| 100 |
+
"track": {
|
| 101 |
+
"name": "Generated track template",
|
| 102 |
+
"tiles": [],
|
| 103 |
+
"path": [],
|
| 104 |
+
"walls": [],
|
| 105 |
+
"physics_shapes": []
|
| 106 |
+
},
|
| 107 |
+
"reset_position": [
|
| 108 |
+
0,
|
| 109 |
+
0
|
| 110 |
+
],
|
| 111 |
+
"reset_rotation": 0
|
| 112 |
+
}
|
bin/altd-sim
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:0135ecc3d435a9d327be7a92e048cfb5c5291a02ef1e0dddd6ead1cc19b31166
|
| 3 |
+
size 15774792
|
bin/libaltd_gpu.so
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:
|
| 3 |
-
size
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:3b1b88bccc06a21acc33ac4400af016d55a7e3d8727136a0c43b541f3c7887ca
|
| 3 |
+
size 4711704
|
client.js
CHANGED
|
@@ -99,7 +99,9 @@ async function checkSteamLeaderboard(trackInfo,report){
|
|
| 99 |
const status=$('leaderboard_status'),optIn=$('leaderboard_opt_in');
|
| 100 |
if(!optIn?.checked)return;
|
| 101 |
const lap=report?.best_lap_seconds;
|
|
|
|
| 102 |
if(typeof lap!=='number'||!Number.isFinite(lap)||lap<=0){status.textContent='Steam check not run: no completed best lap was reported.';return;}
|
|
|
|
| 103 |
if(trackInfo?.source!=='builtin'||typeof trackInfo.id!=='string'||typeof trackInfo.sha256!=='string'){
|
| 104 |
status.textContent='Steam check unavailable for custom or unidentified tracks. Your run result is unaffected.';return;
|
| 105 |
}
|
|
@@ -109,7 +111,7 @@ async function checkSteamLeaderboard(trackInfo,report){
|
|
| 109 |
status.textContent='Checking the public Steam board in the background…';
|
| 110 |
const timer=setTimeout(()=>controller.abort(),8000);
|
| 111 |
try{
|
| 112 |
-
const response=await fetch('/api/leaderboard/compare',{method:'POST',cache:'no-store',credentials:'same-origin',signal:controller.signal,headers:{'Content-Type':'application/json'},body:JSON.stringify({track_id:trackInfo.id,track_sha256:trackInfo.sha256,vehicle_type:
|
| 113 |
const result=await response.json();
|
| 114 |
if(generation!==leaderboardGeneration)return;
|
| 115 |
if(!response.ok)throw Error('Steam check unavailable');
|
|
@@ -209,6 +211,7 @@ $('run').onclick = async () => {
|
|
| 209 |
$('runSummary').textContent=r?[
|
| 210 |
'Build: '+(r.build?.build_id??'Not reported'),
|
| 211 |
'Backend: '+job.backend.toUpperCase(),
|
|
|
|
| 212 |
'Track: '+(trackInfo?.source==='builtin'?trackInfo.display_name:'Custom upload'),
|
| 213 |
'Generations: '+r.generations_completed+' / '+r.generations_requested+' · Population: '+r.population,
|
| 214 |
'Server processing: '+metric(r.elapsed_seconds)+' s',
|
|
|
|
| 99 |
const status=$('leaderboard_status'),optIn=$('leaderboard_opt_in');
|
| 100 |
if(!optIn?.checked)return;
|
| 101 |
const lap=report?.best_lap_seconds;
|
| 102 |
+
const vehicleType=report?.vehicle_type;
|
| 103 |
if(typeof lap!=='number'||!Number.isFinite(lap)||lap<=0){status.textContent='Steam check not run: no completed best lap was reported.';return;}
|
| 104 |
+
if(!Number.isInteger(vehicleType)||vehicleType<0||vehicleType>3){status.textContent='Steam check not run: the completed report did not identify a supported vehicle.';return;}
|
| 105 |
if(trackInfo?.source!=='builtin'||typeof trackInfo.id!=='string'||typeof trackInfo.sha256!=='string'){
|
| 106 |
status.textContent='Steam check unavailable for custom or unidentified tracks. Your run result is unaffected.';return;
|
| 107 |
}
|
|
|
|
| 111 |
status.textContent='Checking the public Steam board in the background…';
|
| 112 |
const timer=setTimeout(()=>controller.abort(),8000);
|
| 113 |
try{
|
| 114 |
+
const response=await fetch('/api/leaderboard/compare',{method:'POST',cache:'no-store',credentials:'same-origin',signal:controller.signal,headers:{'Content-Type':'application/json'},body:JSON.stringify({track_id:trackInfo.id,track_sha256:trackInfo.sha256,vehicle_type:vehicleType,lap_seconds:lap})});
|
| 115 |
const result=await response.json();
|
| 116 |
if(generation!==leaderboardGeneration)return;
|
| 117 |
if(!response.ok)throw Error('Steam check unavailable');
|
|
|
|
| 211 |
$('runSummary').textContent=r?[
|
| 212 |
'Build: '+(r.build?.build_id??'Not reported'),
|
| 213 |
'Backend: '+job.backend.toUpperCase(),
|
| 214 |
+
'Vehicle: '+(Number.isInteger(r.vehicle_type)&&r.vehicle_type>=0&&r.vehicle_type<=3?['Formula','Rally','Snowmobile','Truck'][r.vehicle_type]+' (Type '+r.vehicle_type+')':'Not reported'),
|
| 215 |
'Track: '+(trackInfo?.source==='builtin'?trackInfo.display_name:'Custom upload'),
|
| 216 |
'Generations: '+r.generations_completed+' / '+r.generations_requested+' · Population: '+r.population,
|
| 217 |
'Server processing: '+metric(r.elapsed_seconds)+' s',
|
index.html
CHANGED
|
@@ -29,7 +29,7 @@
|
|
| 29 |
})();
|
| 30 |
</script>
|
| 31 |
<header><div class="eyebrow">AI LEARNS TO DRIVE · TRAINING LAB</div><h1>Train, inspect, repeat.</h1><p class="intro">Pick a track and network, run a bounded training session, and keep your recipes in this browser.</p><details class="about"><summary>About this beta and its data handling</summary><p>Simulator by <a href="https://github.com/Zorro909/driving_sim_rs">Zorro909</a>; interface and hosting by <a href="https://github.com/seeker-cyber-maker/driving_sim_rs">TiGa</a>. Inspired by the <a href="https://store.steampowered.com/app/3312030/AI_Learns_To_Drive/">game by ActivationFunction</a>. Built-in tracks are reconstructed replicas. Star challenges are not evaluated here.</p><p>Uploaded files are used for the requested run. Results are held briefly in application memory and deleted after verified download or expiry. Browser recipes contain settings only. <a href="/policy" target="_blank" rel="noopener">Read the data policy</a>.</p></details><p><a id="feedbackLink" href="https://github.com/seeker-cyber-maker/driving_sim_rs/issues/new" target="_blank" rel="noopener">Report a problem on GitHub</a> · Opens an editable draft and never submits it. Review details before posting; export a run receipt separately if it helps explain the issue.</p><p id="buildLabel" class="hint">Build: connecting…</p></header>
|
| 32 |
-
<nav class="tabs" aria-label="Lab sections"><button data-tab="drive" aria-selected="true">1 · Drive & view</button><button data-tab="training" aria-selected="false">2 · Training runs & presets</button><button data-tab="batch" aria-selected="false">3 · Batches</button><button data-tab="editor" aria-selected="false">4 · Network editor</button></nav><div id="drive" class="pane"><div class="grid"><section class="card"><h2>Simulation</h2><button id="run" disabled>Run training</button><p class="hint">Select or create a network below to enable training. Review settings on tab 2 before running.</p><p>Supports
|
| 33 |
<p id="computeBlock"><label for="backend">Compute</label><select id="backend" disabled><option value="cpu">CPU — no GPU allowance</option><option id="gpuOption" value="gpu" disabled>GPU — uses GPU allowance</option></select></p><p id="backendNote" class="hint">Checking available backends…</p>
|
| 34 |
<div id="connectionRecovery" hidden><button id="retry" type="button">Reconnect to app</button><p class="hint">Checks server availability. Does not restart training, sign you in, or reset GPU allowance.</p></div>
|
| 35 |
<div id="gpuAccount" aria-label="Optional GPU account"><p><button id="hfSignIn" type="button" disabled>Sign in with HF for account GPU allowance</button><span id="hfAccount" hidden></span> <button id="hfSignOut" type="button" disabled hidden>Disconnect account</button></p><p id="hfIdentity" role="status" class="hint">CPU needs no sign-in. Checking optional GPU account connection…</p>
|
|
@@ -38,7 +38,7 @@
|
|
| 38 |
<p data-track-status role="status" class="hint">Loading built-in replica tracks…</p>
|
| 39 |
|
| 40 |
<p><label>Track (.track) <input id="track" type="file" accept=".track"></label></p>
|
| 41 |
-
<p><label>
|
| 42 |
<p id="networkChoice" role="status">Choose an uploaded file or use a network from the browser editor.</p><p class="privacy-note">Uploads are processed for this run. By default, the server copy is deleted after the browser verifies the download.</p><details><summary>Optional repeat download</summary><label class="keep-result"><input id="keepServer" type="checkbox"> Keep this result on the server for up to five minutes so I can download it again</label><p class="privacy-note">This is optional and resets after each run. All results expire after five minutes. <a href="/policy" target="_blank" rel="noopener">Data policy</a></p>
|
| 43 |
</details></section><section class="card"><h2>Selected track & terrain</h2><p id="mapStatus" class="map-status" role="status">Loading selected track…</p><div class="map"><canvas id="trackMap" width="1000" height="500" role="img" aria-label="Selected track tile layout and terrain"></canvas></div><div class="map-legend"><span><i class="terrain asphalt"></i> Asphalt</span><span><i class="terrain dirt"></i> Dirt</span><span><i class="terrain ice"></i> Ice</span><span><i class="terrain start"></i> Start</span></div><p id="mapLegend" class="hint"></p><h2>Run & results</h2><button id="download" disabled>Download result</button> <button id="erase" disabled>Delete server-side job data now</button>
|
| 44 |
<p><button id="saveLocal" disabled>Save received result again (browser only)</button> <button id="forgetLocal" disabled>Discard browser result</button></p>
|
|
@@ -64,7 +64,7 @@
|
|
| 64 |
</details>
|
| 65 |
<details id="reward_settings"><summary>Rewards · presets and up to five metrics</summary>
|
| 66 |
<label for="reward_preset">Reward preset</label><select id="reward_preset" disabled><option value="custom">Custom</option><option value="distance">First laps · distance only</option><option value="center">Example mix · center, clearance, collisions</option><option value="clean">Clean driving · distance + collision penalty</option><option value="lap">Lap refinement · best lap only</option></select>
|
| 67 |
-
<div id="rewards"></div><button id="add" disabled>+ Add reward</button><small>Weights −100…+100; absolute shares normalize to 100%. Five distinct metrics maximum. The current
|
| 68 |
</details></div>
|
| 69 |
<details id="run_settings"><summary>Run settings · timing and elimination</summary><div class="row"><div><label for="control_hz">Decisions per second</label><select id="control_hz" disabled><option>60</option><option>30</option><option>15</option></select></div><div><label for="workers">Parallel simulations</label><select id="workers" disabled><option>1</option><option selected>2</option><option>3</option><option>4</option></select></div></div><small>Physics runs at 60 Hz. CPU jobs can use 1–4 worker threads.</small><div id="seed_group"><label for="seed">Random seed</label><input id="seed" type="number" min="0" max="2147483647" value="42105" disabled></div><label><input id="collision" type="checkbox" disabled> Eliminate on wall contact</label><label><input id="idle" type="checkbox" disabled> Eliminate when stuck</label></details></div><div id="libraries" class="card"><h3>Recipes · A–J · saved in this browser</h3>
|
| 70 |
<p>Each recipe contains the training settings and reward mix. Tracks, networks and results stay out of the recipe library. Saving a recipe sends nothing to the server. Settings are sent when you start a run.</p>
|
|
@@ -75,7 +75,7 @@
|
|
| 75 |
<p>Recipes are specific to this browser and site. Clearing site data removes them. Export a backup to move them between the local runner and HF. Browser privacy settings may prevent saving.</p>
|
| 76 |
<details><summary>Advanced recipe JSON</summary><textarea id="recipe_draft" rows="12" style="width:100%" aria-label="Recipe settings JSON"></textarea><button id="recipe_apply_draft">Apply JSON to form</button></details></div></section>
|
| 77 |
<section id="batch" class="pane" hidden><div class="card"><h2>Training batches · A–J</h2><p>Choose files and CPU/GPU on Drive & view, then start a saved batch here. Up to 20 runs and 4,000,000 vehicle-ticks in total. Recipes freeze at start. Each server result is automatically deleted after verified receipt. The last candidate is kept in browser memory. Stop prevents the next run; the current run finishes.</p><label for="batch_slot">Batch slot</label><select id="batch_slot" disabled><option>A</option><option>B</option><option>C</option><option>D</option><option>E</option><option>F</option><option>G</option><option>H</option><option>I</option><option>J</option></select><label for="batch_name">Display name</label><input id="batch_name" type="text" maxlength="80" value="My curriculum" disabled><label><input id="carry" type="checkbox" checked disabled> Continue from the previous run’s candidate</label><p class="hint">Unchecked: each run starts from the original selected network. Repeated run references are allowed. Recipes freeze when the batch starts.</p><label for="batch_recipe_sequence">Recipe sequence (comma-separated slots)</label><input id="batch_recipe_sequence" value="A" maxlength="300"><label for="batch_add_recipe">Add recipe<select id="batch_add_recipe"><option>A</option><option>B</option><option>C</option><option>D</option><option>E</option><option>F</option><option>G</option><option>H</option><option>I</option><option>J</option></select></label><button id="queue_add" disabled>+ Add run</button><div class="toolbar"><button id="batch_save" disabled>Save batch</button><button id="batch_load" disabled>Load batch</button><button class="primary" id="batch_start" disabled>Start saved batch</button><button id="batch_stop" disabled>Stop after current run</button><button id="batch_export" disabled>Export batch receipt</button></div><div id="batch_status" role="status">No batch selected.</div><div id="batch_history"></div><div id="batches_feedback" role="status" aria-live="polite"></div></div></section>
|
| 78 |
-
<section id="editor" class="pane" hidden><div class="card"><h2>Network editor</h2><p class="hint">An original editor inspired by <a href="https://the-mars-guy.github.io/AI-Learns-To-Drive-Tool/" target="_blank" rel="noopener">Mars’s network creator</a>. Create networks
|
| 79 |
(function(root){
|
| 80 |
const KEY='tiga.ald.recipes.v1';
|
| 81 |
const defaults={population:4,generations:1,ticks:60,mutation:0.01,seed:42,
|
|
@@ -168,6 +168,7 @@
|
|
| 168 |
</script><script>/* Pure browser/Node structural checks and deterministic fresh initialization. */
|
| 169 |
(function(root){
|
| 170 |
const scalarTypes=['speed','velocityFront','velocitySide','angularVelocity','wheelAngle','boostCapacity','correctDirection'];
|
|
|
|
| 171 |
const outputsValid=outputs=>Array.isArray(outputs)&&outputs.length>=1&&outputs.length<=5&&outputs.every(x=>Number.isInteger(x)&&x>=0&&x<=4)&&new Set(outputs).size===outputs.length;
|
| 172 |
function neural(value){
|
| 173 |
if(!value||!Array.isArray(value.Shape)||value.Shape.length<2||value.Shape.length>12||value.Shape.some(n=>!Number.isInteger(n)||n<1||n>20))throw Error('Shape must contain 2–12 layers with 1–20 inputs');
|
|
@@ -188,7 +189,10 @@
|
|
| 188 |
}
|
| 189 |
function compatible(value){
|
| 190 |
const n=neural(value?.NeuralNetwork),s=value.Sensors;
|
| 191 |
-
if(value.Type
|
|
|
|
|
|
|
|
|
|
| 192 |
if(n.Shape[0]>20||n.Shape.slice(1,-1).some(x=>x>16)||n.Shape.length>12)throw Error('Shape exceeds the original-game limits');
|
| 193 |
if(!Array.isArray(s)||s.length!==n.Shape[0])throw Error('Sensor count does not match input shape');
|
| 194 |
let rays=0,other=0;
|
|
@@ -229,9 +233,13 @@
|
|
| 229 |
if(!id)throw Error('Secure GUID generation is unavailable');
|
| 230 |
return {Id:id,Name:name.trim(),Type:source.Type,Stats:{Generations:[]},Snapshots:[],Outputs:[...source.Outputs],Sensors:JSON.parse(JSON.stringify(source.Sensors)),NeuralNetwork:network};
|
| 231 |
}
|
| 232 |
-
function fresh({
|
|
|
|
|
|
|
| 233 |
if(!Array.isArray(shape)||shape.length<1||shape.length>11||shape.some(n=>!Number.isInteger(n)||n<1)||shape[0]>20||shape.slice(1).some(n=>n>16))throw Error('Fresh shape: 1–20 inputs and 0–10 hidden layers of 1–16 nodes');
|
| 234 |
if(!outputsValid(outputs))throw Error('Choose one to five unique output IDs from 0–4');
|
|
|
|
|
|
|
| 235 |
const fullShape=[...shape,outputs.length];if(fullShape.length>12)throw Error('Fresh networks allow at most 12 layers');
|
| 236 |
if(!Number.isInteger(seed)||seed<0||seed>2147483647)throw Error('Seed must be 0–2147483647');
|
| 237 |
if(typeof xavier!=='boolean'||typeof bias!=='boolean')throw Error('Invalid initialization switches');
|
|
@@ -246,9 +254,9 @@
|
|
| 246 |
const rays=Math.min(13,shape[0]-1),extra=shape[0]-1-rays;
|
| 247 |
const sensors=[{$type:'speed'},...scalarTypes.slice(1,1+extra).map($type=>({$type}))];
|
| 248 |
for(let i=0;i<rays;i++)sensors.push({$type:'raycast',Degrees:rays===1?0:-90+180*i/(rays-1),Length:800});
|
| 249 |
-
return edited({Type:
|
| 250 |
}
|
| 251 |
-
const api={neural,compatible,edited,fresh,outputsValid};
|
| 252 |
if(typeof module!=='undefined'&&module.exports)module.exports=api;else root.NetworkEditor=api;
|
| 253 |
})(typeof window!=='undefined'?window:globalThis);
|
| 254 |
</script><script>(() => {
|
|
@@ -452,13 +460,26 @@ document.querySelectorAll('[data-tab]').forEach(button=>button.addEventListener(
|
|
| 452 |
const q=id=>document.getElementById(id),api=window.NetworkEditor;
|
| 453 |
const status=text=>q('editor_status').textContent=text;
|
| 454 |
let source=null,exportURL=null;
|
| 455 |
-
for(const id of ['editor_name','editor_preset','editor_shape','editor_seed','editor_xavier','editor_bias','editor_create','editor_import','editor_outputs',...Array.from({length:5},(_,i)=>'editor_output_'+i)])q(id).disabled=false;
|
| 456 |
const outputIds=[0,1,2,3,4],outputName=id=>'editor_output_'+id;
|
| 457 |
function setOutputs(ids){for(const id of outputIds)q(outputName(id)).checked=ids.includes(id);}
|
| 458 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 459 |
q('editor_preset').onchange=()=>preset(q('editor_preset').value);
|
|
|
|
| 460 |
q('editor_shape').oninput=()=>q('editor_preset').value='custom';
|
| 461 |
-
for(const id of outputIds)q(outputName(id)).onchange=()=>q('editor_preset').value='custom';
|
|
|
|
| 462 |
window.setEditorBusy=busy=>{q('editor_apply').disabled=busy||!source;};
|
| 463 |
function graph(n){
|
| 464 |
const canvas=q('network_map'),ctx=canvas.getContext('2d');ctx.clearRect(0,0,canvas.width,canvas.height);
|
|
@@ -471,10 +492,11 @@ document.querySelectorAll('[data-tab]').forEach(button=>button.addEventListener(
|
|
| 471 |
}
|
| 472 |
function show(value){
|
| 473 |
const n=api.neural(value.NeuralNetwork);source=value;
|
|
|
|
| 474 |
const count=n.Weights.reduce((sum,m)=>sum+m.reduce((s,r)=>s+r.length,0),0)+n.Biases.reduce((s,r)=>s+r.length,0);
|
| 475 |
q('editor_json').value=JSON.stringify(n,null,2);q('editor_json').disabled=false;
|
| 476 |
-
q('editor_name').value=value.Name||'Edited network';q('editor_shape').value=n.Shape.slice(0,-1).join(',');q('editor_preset').value='custom';setOutputs(Array.isArray(value.Outputs)?value.Outputs:[]);
|
| 477 |
-
q('editor_metadata').textContent=n.Shape.join(' → ')+' · '+count+' parameters. Structure checked; no game/leaderboard validation claimed.';
|
| 478 |
q('editor_contract').textContent=JSON.stringify({sensors:value.Sensors,outputs:value.Outputs,vehicle:value.Type},null,2);
|
| 479 |
try{api.compatible(value);q('editor_legality').textContent='Supported by the current training worker.';}
|
| 480 |
catch(error){q('editor_legality').textContent='Inspection/export only: '+error.message;}
|
|
@@ -520,13 +542,13 @@ document.querySelectorAll('[data-tab]').forEach(button=>button.addEventListener(
|
|
| 520 |
if(!source)throw Error('Load or create a network first');
|
| 521 |
const next=JSON.parse(q('editor_json').value);
|
| 522 |
for(const input of q('editor_parameters').querySelectorAll('input'))if(input.value!==input.dataset.initial)updateParameter(next,input);
|
| 523 |
-
const value=api.edited(source,next,q('editor_name').value);
|
| 524 |
const blob=await new Response(new Blob([JSON.stringify(value)]).stream().pipeThrough(new CompressionStream('gzip'))).blob();
|
| 525 |
if(blob.size>1048576)throw Error('Export exceeds 1 MB');
|
| 526 |
return {value,file:new File([blob],'edited-network.evolution',{type:'application/octet-stream'})};
|
| 527 |
}
|
| 528 |
q('editor_file').onchange=load;q('editor_import').onclick=load;
|
| 529 |
-
q('editor_create').onclick=()=>{try{const outputs=outputIds.filter(id=>q(outputName(id)).checked);show(api.fresh({shape:q('editor_shape').value.split(',').map(Number),outputs,seed:Number(q('editor_seed').value),xavier:q('editor_xavier').checked,bias:q('editor_bias').checked,name:q('editor_name').value}));status('Fresh
|
| 530 |
q('editor_apply').onclick=async()=>{try{const {value,file}=await artifact();api.compatible(value);window.TrainingClient.useNetwork(file);show(value);status('Edited network selected for the next run. No upload yet.');}catch(error){status('Not applied: '+error.message);}};
|
| 531 |
q('editor_download').onclick=async event=>{
|
| 532 |
event.preventDefault();try{const {file}=await artifact();if(exportURL)URL.revokeObjectURL(exportURL);exportURL=URL.createObjectURL(file);const a=document.createElement('a');a.href=exportURL;a.download=file.name;a.click();status('Export requested. This is a new edited artifact with no inherited training scores.');}catch(error){status('Not exported: '+error.message);}
|
|
|
|
| 29 |
})();
|
| 30 |
</script>
|
| 31 |
<header><div class="eyebrow">AI LEARNS TO DRIVE · TRAINING LAB</div><h1>Train, inspect, repeat.</h1><p class="intro">Pick a track and network, run a bounded training session, and keep your recipes in this browser.</p><details class="about"><summary>About this beta and its data handling</summary><p>Simulator by <a href="https://github.com/Zorro909/driving_sim_rs">Zorro909</a>; interface and hosting by <a href="https://github.com/seeker-cyber-maker/driving_sim_rs">TiGa</a>. Inspired by the <a href="https://store.steampowered.com/app/3312030/AI_Learns_To_Drive/">game by ActivationFunction</a>. Built-in tracks are reconstructed replicas. Star challenges are not evaluated here.</p><p>Uploaded files are used for the requested run. Results are held briefly in application memory and deleted after verified download or expiry. Browser recipes contain settings only. <a href="/policy" target="_blank" rel="noopener">Read the data policy</a>.</p></details><p><a id="feedbackLink" href="https://github.com/seeker-cyber-maker/driving_sim_rs/issues/new" target="_blank" rel="noopener">Report a problem on GitHub</a> · Opens an editable draft and never submits it. Review details before posting; export a run receipt separately if it helps explain the issue.</p><p id="buildLabel" class="hint">Build: connecting…</p></header>
|
| 32 |
+
<nav class="tabs" aria-label="Lab sections"><button data-tab="drive" aria-selected="true">1 · Drive & view</button><button data-tab="training" aria-selected="false">2 · Training runs & presets</button><button data-tab="batch" aria-selected="false">3 · Batches</button><button data-tab="editor" aria-selected="false">4 · Network editor</button></nav><div id="drive" class="pane"><div class="grid"><section class="card"><h2>Simulation</h2><button id="run" disabled>Run training</button><p class="hint">Select or create a network below to enable training. Review settings on tab 2 before running.</p><p>Supports Formula, Rally, Snowmobile and Truck networks. Control outputs follow the original vehicle editor rules. Network shape and supported sensors are bounded by the original game contract.</p>
|
| 33 |
<p id="computeBlock"><label for="backend">Compute</label><select id="backend" disabled><option value="cpu">CPU — no GPU allowance</option><option id="gpuOption" value="gpu" disabled>GPU — uses GPU allowance</option></select></p><p id="backendNote" class="hint">Checking available backends…</p>
|
| 34 |
<div id="connectionRecovery" hidden><button id="retry" type="button">Reconnect to app</button><p class="hint">Checks server availability. Does not restart training, sign you in, or reset GPU allowance.</p></div>
|
| 35 |
<div id="gpuAccount" aria-label="Optional GPU account"><p><button id="hfSignIn" type="button" disabled>Sign in with HF for account GPU allowance</button><span id="hfAccount" hidden></span> <button id="hfSignOut" type="button" disabled hidden>Disconnect account</button></p><p id="hfIdentity" role="status" class="hint">CPU needs no sign-in. Checking optional GPU account connection…</p>
|
|
|
|
| 38 |
<p data-track-status role="status" class="hint">Loading built-in replica tracks…</p>
|
| 39 |
|
| 40 |
<p><label>Track (.track) <input id="track" type="file" accept=".track"></label></p>
|
| 41 |
+
<p><label>Vehicle network (.evolution) <input id="network" type="file" accept=".evolution"></label></p>
|
| 42 |
<p id="networkChoice" role="status">Choose an uploaded file or use a network from the browser editor.</p><p class="privacy-note">Uploads are processed for this run. By default, the server copy is deleted after the browser verifies the download.</p><details><summary>Optional repeat download</summary><label class="keep-result"><input id="keepServer" type="checkbox"> Keep this result on the server for up to five minutes so I can download it again</label><p class="privacy-note">This is optional and resets after each run. All results expire after five minutes. <a href="/policy" target="_blank" rel="noopener">Data policy</a></p>
|
| 43 |
</details></section><section class="card"><h2>Selected track & terrain</h2><p id="mapStatus" class="map-status" role="status">Loading selected track…</p><div class="map"><canvas id="trackMap" width="1000" height="500" role="img" aria-label="Selected track tile layout and terrain"></canvas></div><div class="map-legend"><span><i class="terrain asphalt"></i> Asphalt</span><span><i class="terrain dirt"></i> Dirt</span><span><i class="terrain ice"></i> Ice</span><span><i class="terrain start"></i> Start</span></div><p id="mapLegend" class="hint"></p><h2>Run & results</h2><button id="download" disabled>Download result</button> <button id="erase" disabled>Delete server-side job data now</button>
|
| 44 |
<p><button id="saveLocal" disabled>Save received result again (browser only)</button> <button id="forgetLocal" disabled>Discard browser result</button></p>
|
|
|
|
| 64 |
</details>
|
| 65 |
<details id="reward_settings"><summary>Rewards · presets and up to five metrics</summary>
|
| 66 |
<label for="reward_preset">Reward preset</label><select id="reward_preset" disabled><option value="custom">Custom</option><option value="distance">First laps · distance only</option><option value="center">Example mix · center, clearance, collisions</option><option value="clean">Clean driving · distance + collision penalty</option><option value="lap">Lap refinement · best lap only</option></select>
|
| 67 |
+
<div id="rewards"></div><button id="add" disabled>+ Add reward</button><small>Weights −100…+100; absolute shares normalize to 100%. Five distinct metrics maximum. The current vehicle runner accepts these metrics; choose them for the behavior you want to train.</small>
|
| 68 |
</details></div>
|
| 69 |
<details id="run_settings"><summary>Run settings · timing and elimination</summary><div class="row"><div><label for="control_hz">Decisions per second</label><select id="control_hz" disabled><option>60</option><option>30</option><option>15</option></select></div><div><label for="workers">Parallel simulations</label><select id="workers" disabled><option>1</option><option selected>2</option><option>3</option><option>4</option></select></div></div><small>Physics runs at 60 Hz. CPU jobs can use 1–4 worker threads.</small><div id="seed_group"><label for="seed">Random seed</label><input id="seed" type="number" min="0" max="2147483647" value="42105" disabled></div><label><input id="collision" type="checkbox" disabled> Eliminate on wall contact</label><label><input id="idle" type="checkbox" disabled> Eliminate when stuck</label></details></div><div id="libraries" class="card"><h3>Recipes · A–J · saved in this browser</h3>
|
| 70 |
<p>Each recipe contains the training settings and reward mix. Tracks, networks and results stay out of the recipe library. Saving a recipe sends nothing to the server. Settings are sent when you start a run.</p>
|
|
|
|
| 75 |
<p>Recipes are specific to this browser and site. Clearing site data removes them. Export a backup to move them between the local runner and HF. Browser privacy settings may prevent saving.</p>
|
| 76 |
<details><summary>Advanced recipe JSON</summary><textarea id="recipe_draft" rows="12" style="width:100%" aria-label="Recipe settings JSON"></textarea><button id="recipe_apply_draft">Apply JSON to form</button></details></div></section>
|
| 77 |
<section id="batch" class="pane" hidden><div class="card"><h2>Training batches · A–J</h2><p>Choose files and CPU/GPU on Drive & view, then start a saved batch here. Up to 20 runs and 4,000,000 vehicle-ticks in total. Recipes freeze at start. Each server result is automatically deleted after verified receipt. The last candidate is kept in browser memory. Stop prevents the next run; the current run finishes.</p><label for="batch_slot">Batch slot</label><select id="batch_slot" disabled><option>A</option><option>B</option><option>C</option><option>D</option><option>E</option><option>F</option><option>G</option><option>H</option><option>I</option><option>J</option></select><label for="batch_name">Display name</label><input id="batch_name" type="text" maxlength="80" value="My curriculum" disabled><label><input id="carry" type="checkbox" checked disabled> Continue from the previous run’s candidate</label><p class="hint">Unchecked: each run starts from the original selected network. Repeated run references are allowed. Recipes freeze when the batch starts.</p><label for="batch_recipe_sequence">Recipe sequence (comma-separated slots)</label><input id="batch_recipe_sequence" value="A" maxlength="300"><label for="batch_add_recipe">Add recipe<select id="batch_add_recipe"><option>A</option><option>B</option><option>C</option><option>D</option><option>E</option><option>F</option><option>G</option><option>H</option><option>I</option><option>J</option></select></label><button id="queue_add" disabled>+ Add run</button><div class="toolbar"><button id="batch_save" disabled>Save batch</button><button id="batch_load" disabled>Load batch</button><button class="primary" id="batch_start" disabled>Start saved batch</button><button id="batch_stop" disabled>Stop after current run</button><button id="batch_export" disabled>Export batch receipt</button></div><div id="batch_status" role="status">No batch selected.</div><div id="batch_history"></div><div id="batches_feedback" role="status" aria-live="polite"></div></div></section>
|
| 78 |
+
<section id="editor" class="pane" hidden><div class="card"><h2>Network editor</h2><p class="hint">An original editor inspired by <a href="https://the-mars-guy.github.io/AI-Learns-To-Drive-Tool/" target="_blank" rel="noopener">Mars’s network creator</a>. Create fresh networks with the selected vehicle’s game-legal controls, or use its largest original-game shape. Loaded networks keep their original vehicle, output order and sensor parameters. Unsupported files can still be inspected without changing the original.</p><div class="toolbar"><label for="editor_file">Load an existing .evolution file</label><input id="editor_file" type="file" accept=".evolution"><button id="editor_import" disabled>Inspect selected network</button><button id="editor_create" disabled>Create fresh network</button><button id="editor_apply" disabled>Use edited network</button><a id="editor_download" hidden download>Download .evolution</a></div><div class="row"><div><label for="editor_name">Network name</label><input id="editor_name" type="text" maxlength="80" value="Fresh network" disabled><label for="editor_vehicle">Vehicle type for fresh networks</label><select id="editor_vehicle" disabled><option value="0">Formula</option><option value="1">Rally</option><option value="2">Snowmobile</option><option value="3">Truck</option></select><small>This selector applies only when you create a fresh network. Imported vehicle type is retained and shown with the current network.</small><label for="editor_preset">Fresh network preset</label><select id="editor_preset" disabled><option id="editor_small_label" value="small">Small starter · 6 inputs, 4 hidden nodes, 5 outputs</option><option id="editor_maximum_label" value="maximum">Largest game network · 20 inputs, 10 × 16 hidden nodes, 5 outputs</option><option value="custom">Custom</option></select><label for="editor_shape">Input and hidden layer sizes</label><input id="editor_shape" type="text" value="6,4" disabled><small id="editor_shape_hint">Enter 1–20 inputs, followed by 0–10 hidden layers of 1–16 nodes. Output width follows the selected controls. Maximum shape: 20 → ten layers of 16 → 5 (2,869 parameters).</small><fieldset id="editor_outputs" disabled><legend id="editor_output_legend">Fresh network outputs</legend><div class="output-options"><label><input id="editor_output_0" type="checkbox" value="0" checked disabled> Steering (0)</label><label><input id="editor_output_1" type="checkbox" value="1" checked disabled> Acceleration (1)</label><label><input id="editor_output_2" type="checkbox" value="2" checked disabled> Handbrake (2)</label><label><input id="editor_output_3" type="checkbox" value="3" checked disabled> Brake (3)</label><label><input id="editor_output_4" type="checkbox" value="4" checked disabled> Boost (4)</label></div><small id="editor_output_hint">Steering and Acceleration are required. Fresh output IDs preserve this order.</small></fieldset></div><div><label for="editor_seed">Initialization seed</label><input id="editor_seed" type="number" min="0" max="2147483647" value="42105" disabled><label><input id="editor_xavier" type="checkbox" checked disabled> Seeded Xavier uniform weights (browser algorithm)</label><label><input id="editor_bias" type="checkbox" disabled> Xavier uniform biases</label><small>Unchecked: zeros. Biases default to zero.</small></div></div><p id="editor_status" role="status">Choose a file or create a fresh network. Editor changes are browser-local until you explicitly start a run.</p><p id="editor_metadata" class="hint"></p><p id="editor_legality" class="hint"></p><details id="editor_history_panel"><summary>Training history · recorded generations</summary><div class="table-scroll"><table><thead><tr><th>Record</th><th>Time</th><th>Mutation</th><th>Best score</th><th>Best lap</th></tr></thead><tbody id="editor_history"></tbody></table></div><details><summary>Full saved training metadata</summary><pre id="editor_stats"></pre></details></details><canvas aria-label="Network architecture preview" id="network_map" width="1100" height="450"></canvas><details id="weight_values"><summary>Individual weight and bias values</summary><div class="table-scroll" style="max-height:420px;overflow:auto"><table><thead><tr><th>Connection / bias</th><th>Value</th></tr></thead><tbody id="editor_parameters"></tbody></table></div></details><details><summary>Weights, biases and input contract</summary><pre id="editor_contract"></pre><label for="editor_json">NeuralNetwork JSON · editable weights and biases</label><textarea id="editor_json" rows="16" style="width:100%;box-sizing:border-box;background:#0c1725;color:#e5edf5" disabled></textarea></details></div></section><script>/* Settings-only recipe contract. Storage is injected; no network or job data. */
|
| 79 |
(function(root){
|
| 80 |
const KEY='tiga.ald.recipes.v1';
|
| 81 |
const defaults={population:4,generations:1,ticks:60,mutation:0.01,seed:42,
|
|
|
|
| 168 |
</script><script>/* Pure browser/Node structural checks and deterministic fresh initialization. */
|
| 169 |
(function(root){
|
| 170 |
const scalarTypes=['speed','velocityFront','velocitySide','angularVelocity','wheelAngle','boostCapacity','correctDirection'];
|
| 171 |
+
const vehicleNames=['Formula','Rally','Snowmobile','Truck'];
|
| 172 |
const outputsValid=outputs=>Array.isArray(outputs)&&outputs.length>=1&&outputs.length<=5&&outputs.every(x=>Number.isInteger(x)&&x>=0&&x<=4)&&new Set(outputs).size===outputs.length;
|
| 173 |
function neural(value){
|
| 174 |
if(!value||!Array.isArray(value.Shape)||value.Shape.length<2||value.Shape.length>12||value.Shape.some(n=>!Number.isInteger(n)||n<1||n>20))throw Error('Shape must contain 2–12 layers with 1–20 inputs');
|
|
|
|
| 189 |
}
|
| 190 |
function compatible(value){
|
| 191 |
const n=neural(value?.NeuralNetwork),s=value.Sensors;
|
| 192 |
+
if(!Number.isInteger(value.Type)||value.Type<0||value.Type>=vehicleNames.length)throw Error('Vehicle Type must be Formula (0), Rally (1), Snowmobile (2), or Truck (3)');
|
| 193 |
+
if(!outputsValid(value.Outputs)||n.Shape.at(-1)!==value.Outputs.length)throw Error('Outputs must be a unique ordered subset of IDs 0–4 matching the output width');
|
| 194 |
+
if(value.Type!==0&&(!value.Outputs.includes(0)||!value.Outputs.includes(1)))throw Error(vehicleNames[value.Type]+' networks require Steering and Acceleration outputs');
|
| 195 |
+
if(value.Type===2&&value.Outputs.includes(2))throw Error('Snowmobile Handbrake output is unavailable in the original game editor; the imported network is inspect-only');
|
| 196 |
if(n.Shape[0]>20||n.Shape.slice(1,-1).some(x=>x>16)||n.Shape.length>12)throw Error('Shape exceeds the original-game limits');
|
| 197 |
if(!Array.isArray(s)||s.length!==n.Shape[0])throw Error('Sensor count does not match input shape');
|
| 198 |
let rays=0,other=0;
|
|
|
|
| 233 |
if(!id)throw Error('Secure GUID generation is unavailable');
|
| 234 |
return {Id:id,Name:name.trim(),Type:source.Type,Stats:{Generations:[]},Snapshots:[],Outputs:[...source.Outputs],Sensors:JSON.parse(JSON.stringify(source.Sensors)),NeuralNetwork:network};
|
| 235 |
}
|
| 236 |
+
function fresh({type=0,shape,outputs,seed,xavier=true,bias=false,name='Fresh network'}){
|
| 237 |
+
if(!Number.isInteger(type)||type<0||type>=vehicleNames.length)throw Error('Choose Formula, Rally, Snowmobile, or Truck');
|
| 238 |
+
if(outputs===undefined)outputs=type===2?[0,1,3,4]:[0,1,2,3,4];
|
| 239 |
if(!Array.isArray(shape)||shape.length<1||shape.length>11||shape.some(n=>!Number.isInteger(n)||n<1)||shape[0]>20||shape.slice(1).some(n=>n>16))throw Error('Fresh shape: 1–20 inputs and 0–10 hidden layers of 1–16 nodes');
|
| 240 |
if(!outputsValid(outputs))throw Error('Choose one to five unique output IDs from 0–4');
|
| 241 |
+
if(!outputs.includes(0)||!outputs.includes(1))throw Error(vehicleNames[type]+' fresh networks require Steering and Acceleration outputs');
|
| 242 |
+
if(type===2&&outputs.includes(2))throw Error('Snowmobile Handbrake output is unavailable in the original game editor');
|
| 243 |
const fullShape=[...shape,outputs.length];if(fullShape.length>12)throw Error('Fresh networks allow at most 12 layers');
|
| 244 |
if(!Number.isInteger(seed)||seed<0||seed>2147483647)throw Error('Seed must be 0–2147483647');
|
| 245 |
if(typeof xavier!=='boolean'||typeof bias!=='boolean')throw Error('Invalid initialization switches');
|
|
|
|
| 254 |
const rays=Math.min(13,shape[0]-1),extra=shape[0]-1-rays;
|
| 255 |
const sensors=[{$type:'speed'},...scalarTypes.slice(1,1+extra).map($type=>({$type}))];
|
| 256 |
for(let i=0;i<rays;i++)sensors.push({$type:'raycast',Degrees:rays===1?0:-90+180*i/(rays-1),Length:800});
|
| 257 |
+
return edited({Type:type,Outputs:[...outputs],Sensors:sensors},n,name);
|
| 258 |
}
|
| 259 |
+
const api={neural,compatible,edited,fresh,outputsValid,vehicleNames};
|
| 260 |
if(typeof module!=='undefined'&&module.exports)module.exports=api;else root.NetworkEditor=api;
|
| 261 |
})(typeof window!=='undefined'?window:globalThis);
|
| 262 |
</script><script>(() => {
|
|
|
|
| 460 |
const q=id=>document.getElementById(id),api=window.NetworkEditor;
|
| 461 |
const status=text=>q('editor_status').textContent=text;
|
| 462 |
let source=null,exportURL=null;
|
| 463 |
+
for(const id of ['editor_name','editor_vehicle','editor_preset','editor_shape','editor_seed','editor_xavier','editor_bias','editor_create','editor_import','editor_outputs',...Array.from({length:5},(_,i)=>'editor_output_'+i)])q(id).disabled=false;
|
| 464 |
const outputIds=[0,1,2,3,4],outputName=id=>'editor_output_'+id;
|
| 465 |
function setOutputs(ids){for(const id of outputIds)q(outputName(id)).checked=ids.includes(id);}
|
| 466 |
+
const freshType=()=>Number(q('editor_vehicle').value),allowedOutputs=type=>type===2?[0,1,3,4]:outputIds,defaultOutputs=type=>allowedOutputs(type);
|
| 467 |
+
function refreshOutputRules(reset=false){
|
| 468 |
+
const type=freshType(),allowed=allowedOutputs(type);
|
| 469 |
+
if(reset)setOutputs(defaultOutputs(type));
|
| 470 |
+
for(const id of outputIds){const input=q(outputName(id)),required=id===0||id===1,unavailable=!allowed.includes(id);input.disabled=required||unavailable;if(required)input.checked=true;if(unavailable)input.checked=false;}
|
| 471 |
+
q('editor_small_label').textContent='Small starter · 6 inputs, 4 hidden nodes, '+allowed.length+' outputs';
|
| 472 |
+
q('editor_shape_hint').textContent='Enter 1–20 inputs, followed by 0–10 hidden layers of 1–16 nodes. Output width follows the selected controls. Maximum shape: 20 → ten layers of 16 → '+allowed.length+' ('+(2784+17*allowed.length).toLocaleString()+' parameters).';
|
| 473 |
+
q('editor_maximum_label').textContent='Largest game network · 20 inputs, 10 × 16 hidden nodes, '+allowed.length+' outputs ('+(2784+17*allowed.length).toLocaleString()+' parameters)';
|
| 474 |
+
q('editor_output_legend').textContent='Fresh network outputs · '+api.vehicleNames[type];
|
| 475 |
+
q('editor_output_hint').textContent=type===2?'Steering and Acceleration are required. Snowmobile Handbrake is unavailable; at most four outputs.':'Steering and Acceleration are required. Fresh output IDs preserve this order; up to five outputs.';
|
| 476 |
+
}
|
| 477 |
+
function preset(value){if(value==='small'){q('editor_shape').value='6,4';refreshOutputRules(true);}else if(value==='maximum'){q('editor_shape').value=[20,...Array(10).fill(16)].join(',');refreshOutputRules(true);}}
|
| 478 |
q('editor_preset').onchange=()=>preset(q('editor_preset').value);
|
| 479 |
+
q('editor_vehicle').onchange=()=>refreshOutputRules(q('editor_preset').value!=='custom');
|
| 480 |
q('editor_shape').oninput=()=>q('editor_preset').value='custom';
|
| 481 |
+
for(const id of outputIds)q(outputName(id)).onchange=()=>{q('editor_preset').value='custom';refreshOutputRules(false);};
|
| 482 |
+
refreshOutputRules(false);
|
| 483 |
window.setEditorBusy=busy=>{q('editor_apply').disabled=busy||!source;};
|
| 484 |
function graph(n){
|
| 485 |
const canvas=q('network_map'),ctx=canvas.getContext('2d');ctx.clearRect(0,0,canvas.width,canvas.height);
|
|
|
|
| 492 |
}
|
| 493 |
function show(value){
|
| 494 |
const n=api.neural(value.NeuralNetwork);source=value;
|
| 495 |
+
if(Number.isInteger(value.Type)&&value.Type>=0&&value.Type<api.vehicleNames.length){q('editor_vehicle').value=String(value.Type);refreshOutputRules(false);}
|
| 496 |
const count=n.Weights.reduce((sum,m)=>sum+m.reduce((s,r)=>s+r.length,0),0)+n.Biases.reduce((s,r)=>s+r.length,0);
|
| 497 |
q('editor_json').value=JSON.stringify(n,null,2);q('editor_json').disabled=false;
|
| 498 |
+
q('editor_name').value=value.Name||'Edited network';q('editor_shape').value=n.Shape.slice(0,-1).join(',');q('editor_preset').value='custom';setOutputs((Array.isArray(value.Outputs)?value.Outputs:[]).filter(id=>allowedOutputs(freshType()).includes(id)));refreshOutputRules(false);
|
| 499 |
+
q('editor_metadata').textContent='Current network: '+(api.vehicleNames[value.Type]||'Unknown vehicle')+' (Type '+String(value.Type)+') · '+n.Shape.join(' → ')+' · '+count+' parameters. Structure checked; no game/leaderboard validation claimed.';
|
| 500 |
q('editor_contract').textContent=JSON.stringify({sensors:value.Sensors,outputs:value.Outputs,vehicle:value.Type},null,2);
|
| 501 |
try{api.compatible(value);q('editor_legality').textContent='Supported by the current training worker.';}
|
| 502 |
catch(error){q('editor_legality').textContent='Inspection/export only: '+error.message;}
|
|
|
|
| 542 |
if(!source)throw Error('Load or create a network first');
|
| 543 |
const next=JSON.parse(q('editor_json').value);
|
| 544 |
for(const input of q('editor_parameters').querySelectorAll('input'))if(input.value!==input.dataset.initial)updateParameter(next,input);
|
| 545 |
+
const value=api.edited(source,next,q('editor_name').value);api.compatible(value);
|
| 546 |
const blob=await new Response(new Blob([JSON.stringify(value)]).stream().pipeThrough(new CompressionStream('gzip'))).blob();
|
| 547 |
if(blob.size>1048576)throw Error('Export exceeds 1 MB');
|
| 548 |
return {value,file:new File([blob],'edited-network.evolution',{type:'application/octet-stream'})};
|
| 549 |
}
|
| 550 |
q('editor_file').onchange=load;q('editor_import').onclick=load;
|
| 551 |
+
q('editor_create').onclick=()=>{try{const outputs=outputIds.filter(id=>q(outputName(id)).checked);show(api.fresh({type:freshType(),shape:q('editor_shape').value.split(',').map(Number),outputs,seed:Number(q('editor_seed').value),xavier:q('editor_xavier').checked,bias:q('editor_bias').checked,name:q('editor_name').value}));status('Fresh '+api.vehicleNames[freshType()]+' network created. No training history, upload or storage.');}catch(error){status('Not created: '+error.message);}};
|
| 552 |
q('editor_apply').onclick=async()=>{try{const {value,file}=await artifact();api.compatible(value);window.TrainingClient.useNetwork(file);show(value);status('Edited network selected for the next run. No upload yet.');}catch(error){status('Not applied: '+error.message);}};
|
| 553 |
q('editor_download').onclick=async event=>{
|
| 554 |
event.preventDefault();try{const {file}=await artifact();if(exportURL)URL.revokeObjectURL(exportURL);exportURL=URL.createObjectURL(file);const a=document.createElement('a');a.href=exportURL;a.download=file.name;a.click();status('Export requested. This is a new edited artifact with no inherited training scores.');}catch(error){status('Not exported: '+error.message);}
|
server.py
CHANGED
|
@@ -35,12 +35,10 @@ def create_app(worker=run_reported,store=None,gpu_worker=None,track_library=None
|
|
| 35 |
if not isinstance(body,dict) or set(body)!={'track_id','track_sha256','vehicle_type','lap_seconds'}:
|
| 36 |
raise ValueError()
|
| 37 |
if not isinstance(body['track_id'],str) or not isinstance(body['track_sha256'],str): raise ValueError()
|
| 38 |
-
if type(body['vehicle_type']) is not int: raise ValueError()
|
| 39 |
milliseconds(body['lap_seconds'])
|
| 40 |
except Exception: raise HTTPException(400,'Invalid leaderboard comparison request') from None
|
| 41 |
finally: data.clear()
|
| 42 |
-
if body['vehicle_type']!=0:
|
| 43 |
-
return {'status':'unsupported_vehicle','message':'Steam comparison is available only for Formula runs.'}
|
| 44 |
entry=next((track for track in library.catalog()['tracks'] if track['id']==body['track_id']),None)
|
| 45 |
if entry is None:
|
| 46 |
return {'status':'unsupported_track','message':'Steam comparison is available only for supported built-in tracks.'}
|
|
@@ -49,7 +47,9 @@ def create_app(worker=run_reported,store=None,gpu_worker=None,track_library=None
|
|
| 49 |
if not leaderboard_admission.acquire(blocking=False):
|
| 50 |
return {'status':'busy','message':'Another Steam check is in progress. The completed result is unaffected.'}
|
| 51 |
try:
|
| 52 |
-
|
|
|
|
|
|
|
| 53 |
except SteamUnavailable as error:
|
| 54 |
result={'status':'unavailable','failure_category':error.failure_category,
|
| 55 |
'message':'Steam could not provide a complete public leaderboard. The completed result is unaffected.'}
|
|
|
|
| 35 |
if not isinstance(body,dict) or set(body)!={'track_id','track_sha256','vehicle_type','lap_seconds'}:
|
| 36 |
raise ValueError()
|
| 37 |
if not isinstance(body['track_id'],str) or not isinstance(body['track_sha256'],str): raise ValueError()
|
| 38 |
+
if type(body['vehicle_type']) is not int or not 0<=body['vehicle_type']<=3: raise ValueError()
|
| 39 |
milliseconds(body['lap_seconds'])
|
| 40 |
except Exception: raise HTTPException(400,'Invalid leaderboard comparison request') from None
|
| 41 |
finally: data.clear()
|
|
|
|
|
|
|
| 42 |
entry=next((track for track in library.catalog()['tracks'] if track['id']==body['track_id']),None)
|
| 43 |
if entry is None:
|
| 44 |
return {'status':'unsupported_track','message':'Steam comparison is available only for supported built-in tracks.'}
|
|
|
|
| 47 |
if not leaderboard_admission.acquire(blocking=False):
|
| 48 |
return {'status':'busy','message':'Another Steam check is in progress. The completed result is unaffected.'}
|
| 49 |
try:
|
| 50 |
+
result=await run_in_threadpool(compare_public_best_lap,entry,body['lap_seconds'])
|
| 51 |
+
if result.get('status')=='ok':result['vehicle_type']=body['vehicle_type']
|
| 52 |
+
return result
|
| 53 |
except SteamUnavailable as error:
|
| 54 |
result={'status':'unavailable','failure_category':error.failure_category,
|
| 55 |
'message':'Steam could not provide a complete public leaderboard. The completed result is unaffected.'}
|
worker.py
CHANGED
|
@@ -33,6 +33,7 @@ def read_json(data):
|
|
| 33 |
return result
|
| 34 |
|
| 35 |
OUTPUT_NAMES = ('Steering', 'Acceleration', 'Handbrake', 'Brake', 'Boost')
|
|
|
|
| 36 |
SCALAR_SENSORS = {'speed', 'velocityFront', 'velocitySide', 'angularVelocity',
|
| 37 |
'wheelAngle', 'boostCapacity', 'correctDirection'}
|
| 38 |
|
|
@@ -74,10 +75,16 @@ def sensor_input(sensor):
|
|
| 74 |
def network_input(data):
|
| 75 |
value=read_json(data)
|
| 76 |
network=value['NeuralNetwork']; shape=network['Shape']; outputs=value.get('Outputs')
|
| 77 |
-
|
|
|
|
|
|
|
| 78 |
if (not isinstance(outputs,list) or not 1<=len(outputs)<=5 or
|
| 79 |
any(type(n) is not int or not 0<=n<5 for n in outputs) or len(set(outputs))!=len(outputs)):
|
| 80 |
raise ValueError('Use an ordered unique subset of the five game outputs')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
if (not isinstance(shape,list) or not 2<=len(shape)<=12 or
|
| 82 |
any(type(n) is not int or n<1 for n in shape) or shape[0]>20 or
|
| 83 |
any(n>16 for n in shape[1:-1]) or shape[-1]!=len(outputs)):
|
|
@@ -97,7 +104,7 @@ def network_input(data):
|
|
| 97 |
for n in [x for row in weights[i] for x in row]+biases[i]:
|
| 98 |
if type(n) not in (int,float) or not math.isfinite(n) or abs(n)>1e6: raise ValueError('Weight value')
|
| 99 |
return {'Id':str(uuid.uuid4()),'Stats':{'Generations':[]},'Snapshots':[],
|
| 100 |
-
'Type':
|
| 101 |
'Name':'HF candidate','NeuralNetwork':{'Shape':shape,'InputShape':shape[0],'OutputShape':shape[-1],
|
| 102 |
'NeuronsCount':sum(shape),'TotalParams':sum((a+1)*b for a,b in zip(shape,shape[1:])),
|
| 103 |
'Weights':weights,'Biases':biases}}
|
|
@@ -132,6 +139,16 @@ def best_run_lap(history):
|
|
| 132 |
laps = [v for v in values if type(v) in (int, float) and math.isfinite(v) and v > 0]
|
| 133 |
return min(laps) if laps else None
|
| 134 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 135 |
def run_native(track_bytes,network_bytes,*,binary=None,importer=None,scene_template=None,with_report=False,gpu_library=None,config=None):
|
| 136 |
started=time.perf_counter()
|
| 137 |
config=validate_config(config)
|
|
@@ -139,7 +156,7 @@ def run_native(track_bytes,network_bytes,*,binary=None,importer=None,scene_templ
|
|
| 139 |
# Deployment paths are supplied by trusted application configuration, never uploads.
|
| 140 |
binary=Path(binary or ROOT/'target/release/altd-sim').resolve()
|
| 141 |
importer=Path(importer or ROOT/'target/release/examples/extract_saved_track').resolve()
|
| 142 |
-
scene_template=
|
| 143 |
if not all(p.is_file() for p in (binary,importer,scene_template)):
|
| 144 |
raise RuntimeError('Native tools or scene template unavailable')
|
| 145 |
# No inherited provider tokens, credential paths, or caller-chosen commands.
|
|
@@ -189,6 +206,7 @@ def run_native(track_bytes,network_bytes,*,binary=None,importer=None,scene_templ
|
|
| 189 |
'best_lap_seconds':best_run_lap(history),'best_lap_scope':'Best completed lap observed during this run; may belong to a different car than the exported candidate','lapped_cars':last.get('lapped_cars'),
|
| 190 |
'simulated_ticks':last.get('simulated_ticks'),'requested_ticks':config['ticks'],
|
| 191 |
'candidate_validated':True,'execution_backend':'cuda' if gpu_library is not None else 'cpu',
|
|
|
|
| 192 |
'inputs':{'track_sha256':hashlib.sha256(track_bytes).hexdigest(),'network_sha256':hashlib.sha256(network_bytes).hexdigest()},
|
| 193 |
'settings':config,'history':[{'generation':i+1,'mutation':h.get('mutation_rate'),
|
| 194 |
'best_score':h.get('best_score'),'mean_score':h.get('mean_score'),'best_lap_seconds':h.get('best_lap_s'),
|
|
|
|
| 33 |
return result
|
| 34 |
|
| 35 |
OUTPUT_NAMES = ('Steering', 'Acceleration', 'Handbrake', 'Brake', 'Boost')
|
| 36 |
+
VEHICLE_NAMES = ('Formula', 'Rally', 'Snowmobile', 'Truck')
|
| 37 |
SCALAR_SENSORS = {'speed', 'velocityFront', 'velocitySide', 'angularVelocity',
|
| 38 |
'wheelAngle', 'boostCapacity', 'correctDirection'}
|
| 39 |
|
|
|
|
| 75 |
def network_input(data):
|
| 76 |
value=read_json(data)
|
| 77 |
network=value['NeuralNetwork']; shape=network['Shape']; outputs=value.get('Outputs')
|
| 78 |
+
vehicle_type=value.get('Type')
|
| 79 |
+
if type(vehicle_type) is not int or not 0<=vehicle_type<len(VEHICLE_NAMES):
|
| 80 |
+
raise ValueError('Vehicle Type must be Formula (0), Rally (1), Snowmobile (2), or Truck (3)')
|
| 81 |
if (not isinstance(outputs,list) or not 1<=len(outputs)<=5 or
|
| 82 |
any(type(n) is not int or not 0<=n<5 for n in outputs) or len(set(outputs))!=len(outputs)):
|
| 83 |
raise ValueError('Use an ordered unique subset of the five game outputs')
|
| 84 |
+
if vehicle_type!=0 and not {0,1}.issubset(outputs):
|
| 85 |
+
raise ValueError('Rally, Snowmobile, and Truck networks require Steering and Acceleration outputs')
|
| 86 |
+
if vehicle_type==2 and 2 in outputs:
|
| 87 |
+
raise ValueError('Snowmobile Handbrake output is unavailable in the original game editor')
|
| 88 |
if (not isinstance(shape,list) or not 2<=len(shape)<=12 or
|
| 89 |
any(type(n) is not int or n<1 for n in shape) or shape[0]>20 or
|
| 90 |
any(n>16 for n in shape[1:-1]) or shape[-1]!=len(outputs)):
|
|
|
|
| 104 |
for n in [x for row in weights[i] for x in row]+biases[i]:
|
| 105 |
if type(n) not in (int,float) or not math.isfinite(n) or abs(n)>1e6: raise ValueError('Weight value')
|
| 106 |
return {'Id':str(uuid.uuid4()),'Stats':{'Generations':[]},'Snapshots':[],
|
| 107 |
+
'Type':vehicle_type,'Outputs':outputs[:],'Sensors':clean_sensors,
|
| 108 |
'Name':'HF candidate','NeuralNetwork':{'Shape':shape,'InputShape':shape[0],'OutputShape':shape[-1],
|
| 109 |
'NeuronsCount':sum(shape),'TotalParams':sum((a+1)*b for a,b in zip(shape,shape[1:])),
|
| 110 |
'Weights':weights,'Biases':biases}}
|
|
|
|
| 139 |
laps = [v for v in values if type(v) in (int, float) and math.isfinite(v) and v > 0]
|
| 140 |
return min(laps) if laps else None
|
| 141 |
|
| 142 |
+
def vehicle_scene_template(scene_template, vehicle_type):
|
| 143 |
+
if type(vehicle_type) is not int or not 0<=vehicle_type<len(VEHICLE_NAMES):
|
| 144 |
+
raise ValueError('Unsupported vehicle Type')
|
| 145 |
+
formula=Path(scene_template or ROOT/'assets/formula_template.json').resolve()
|
| 146 |
+
if vehicle_type==0:return formula
|
| 147 |
+
name=VEHICLE_NAMES[vehicle_type].lower()
|
| 148 |
+
# Only the application-supplied Formula path determines the sibling asset
|
| 149 |
+
# directory; uploaded JSON never supplies a template path.
|
| 150 |
+
return (formula.parent/(name+'_template.json')).resolve()
|
| 151 |
+
|
| 152 |
def run_native(track_bytes,network_bytes,*,binary=None,importer=None,scene_template=None,with_report=False,gpu_library=None,config=None):
|
| 153 |
started=time.perf_counter()
|
| 154 |
config=validate_config(config)
|
|
|
|
| 156 |
# Deployment paths are supplied by trusted application configuration, never uploads.
|
| 157 |
binary=Path(binary or ROOT/'target/release/altd-sim').resolve()
|
| 158 |
importer=Path(importer or ROOT/'target/release/examples/extract_saved_track').resolve()
|
| 159 |
+
scene_template=vehicle_scene_template(scene_template,template['Type'])
|
| 160 |
if not all(p.is_file() for p in (binary,importer,scene_template)):
|
| 161 |
raise RuntimeError('Native tools or scene template unavailable')
|
| 162 |
# No inherited provider tokens, credential paths, or caller-chosen commands.
|
|
|
|
| 206 |
'best_lap_seconds':best_run_lap(history),'best_lap_scope':'Best completed lap observed during this run; may belong to a different car than the exported candidate','lapped_cars':last.get('lapped_cars'),
|
| 207 |
'simulated_ticks':last.get('simulated_ticks'),'requested_ticks':config['ticks'],
|
| 208 |
'candidate_validated':True,'execution_backend':'cuda' if gpu_library is not None else 'cpu',
|
| 209 |
+
'vehicle_type':template['Type'],'vehicle_name':VEHICLE_NAMES[template['Type']],
|
| 210 |
'inputs':{'track_sha256':hashlib.sha256(track_bytes).hexdigest(),'network_sha256':hashlib.sha256(network_bytes).hexdigest()},
|
| 211 |
'settings':config,'history':[{'generation':i+1,'mutation':h.get('mutation_rate'),
|
| 212 |
'best_score':h.get('best_score'),'mean_score':h.get('mean_score'),'best_lap_seconds':h.get('best_lap_s'),
|