Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b6d776d94e | |||
| 3a97f6a7ac | |||
| c03e524f37 | |||
| 89e947d462 | |||
| f286933a81 | |||
| 9bc5f083eb | |||
| a48cc17c08 | |||
| 9098ffbfbc | |||
| 603b55b44f | |||
| ad94c93932 | |||
| e7eb7c4010 | |||
| e2c2d1b99d | |||
| 9756914434 | |||
| 0b397ee31d | |||
| d726c8424e | |||
| 6b0c6d63a4 | |||
| 1723a1b0bd | |||
| 86ba9112de | |||
| cd41e46ef5 | |||
| 32d5f0269b | |||
| 1750e406e0 | |||
| 7457d59dea | |||
| 2578f5c8d4 | |||
| 6af6764c30 | |||
| 50102c6127 | |||
| 210c49fb04 | |||
| bc3db163b1 | |||
| b364586ebc | |||
| f3509ef217 | |||
| d584d99f4c | |||
| 078c941910 | |||
| 76670ceb29 | |||
| 4cdd8ea06a | |||
| 454ae138f7 | |||
| 640c5e262b | |||
| 7416d7d59f | |||
| ca1255b37e | |||
| de0a8520f3 | |||
| e51919896f | |||
| f9cd9a2a33 | |||
| 897d6d0c36 | |||
| b241b60657 | |||
| 1f1bef1cc9 | |||
| 05f8a0ca68 | |||
| 541572e415 | |||
| 61c7f15fcf | |||
| 1da1645c51 | |||
| 8dc670b631 | |||
| 3424f9a952 | |||
| 4079426506 | |||
| 35f2a5ca09 | |||
| b840a6cd46 | |||
| 1aca0f7ed1 | |||
| b009bc03e8 | |||
| baa39a5a99 | |||
| 99cbde3828 | |||
| e72b73ccf0 | |||
| 75e34d9f75 | |||
| 13aa1acc54 | |||
| 966181c977 | |||
| 06eb4bc607 | |||
| c07a16d245 | |||
| 7e67e34526 | |||
| 6cfc535dec | |||
| d072692db7 | |||
| 6255efd98d | |||
| 9c59c30f12 | |||
| 31302cc053 | |||
| 26fd0c67e4 | |||
| d98ec94a66 | |||
| 28485cc28c | |||
| b14c7a9502 | |||
| 90e78e5ac5 | |||
| 27f02e2c2b | |||
| 421ae1db6b | |||
| 90824dc0e5 | |||
| 583c2887e9 | |||
| f915094775 | |||
| d5e735b59e | |||
| 43a724bf13 | |||
| 337425d21c | |||
| 9ff9341851 | |||
| f9276f6c71 | |||
| f4f9a4729f | |||
| ed0906b63e | |||
| 2ae19123a3 | |||
| 0c2be7b927 | |||
| ffce2b572b | |||
| 1b5a26e380 | |||
| c9b681eaee | |||
| 160879adec | |||
| d6ddbe7af7 | |||
| 1c7b72ea1d | |||
| 83f5b07c7e | |||
| 77cb64e25a | |||
| 6d0cc8e7cd | |||
| 7fb4b0ae26 | |||
| ed191d597b | |||
| 5d24accb15 | |||
| 54c6850121 | |||
| fad8c40b4b | |||
| a8485b3531 | |||
| e7dcd125ec | |||
| d886f44c59 | |||
| 5ff6c0504e | |||
| 2158145ae8 | |||
| 6101c9bfb2 | |||
| bd9af9a630 | |||
| 2188dbdf9b | |||
| c4576d7802 | |||
| 86cb4cff4d | |||
| 0534848677 | |||
| c5d116e2db | |||
| 3dce5ec7c0 | |||
| 956ff8afd7 | |||
| 5b629833df | |||
| b53201a7ff | |||
| f0ddd0e27f | |||
| 94bfba2c49 | |||
| 1e4541ef0d | |||
| c25a55a7d9 | |||
| bea3c59405 | |||
| 8cd43adff3 | |||
| 5ab1963117 | |||
| 50d784a0de | |||
| f61135ce6b | |||
| 5e43ece1aa | |||
| 37e4149a34 | |||
| e515203557 | |||
| 0d79c71eba | |||
| 2bbf9a8ac3 | |||
| 45b2bd01a2 | |||
| 665ffb9dce | |||
| 1c2a93fbd5 | |||
| 57ab6cc02d |
@@ -0,0 +1,13 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
require('@rushstack/eslint-patch/modern-module-resolution');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
extends: ['plugin:vue/vue3-essential', 'eslint:recommended', '@vue/eslint-config-typescript', '@vue/eslint-config-prettier/skip-formatting'],
|
||||||
|
rules: {
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
env: {
|
|
||||||
node: true,
|
|
||||||
},
|
|
||||||
extends: [
|
|
||||||
"plugin:vue/vue3-essential",
|
|
||||||
"eslint:recommended",
|
|
||||||
"@vue/typescript/recommended",
|
|
||||||
"@vue/prettier",
|
|
||||||
"@vue/prettier/@typescript-eslint",
|
|
||||||
],
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 2020,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
|
||||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: npm ci && npm run build
|
- run: yarn && yarn build
|
||||||
- uses: FirebaseExtended/action-hosting-deploy@v0
|
- uses: FirebaseExtended/action-hosting-deploy@v0
|
||||||
with:
|
with:
|
||||||
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: npm ci && npm run build
|
- run: yarn && yarn build
|
||||||
- uses: FirebaseExtended/action-hosting-deploy@v0
|
- uses: FirebaseExtended/action-hosting-deploy@v0
|
||||||
with:
|
with:
|
||||||
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
github-releases-to-discord:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Github Releases To Discord
|
||||||
|
uses: SethCohen/github-releases-to-discord@v1.13.1
|
||||||
|
with:
|
||||||
|
webhook_url: ${{ secrets.WEBHOOK_URL }}
|
||||||
|
color: "15844367"
|
||||||
|
footer_title: "Changelog - Pojazdownik"
|
||||||
|
footer_timestamp: true
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"printWidth": 100
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
presets: ["@vue/cli-plugin-babel/preset"],
|
|
||||||
};
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"hosting": {
|
"hosting": {
|
||||||
"public": "dist",
|
"public": "dist",
|
||||||
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
|
"ignore": [],
|
||||||
"rewrites": [
|
"rewrites": [
|
||||||
{
|
{
|
||||||
"source": "**",
|
"source": "**",
|
||||||
@@ -9,4 +9,4 @@
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
@@ -8,22 +8,20 @@
|
|||||||
<title>Pojazdownik</title>
|
<title>Pojazdownik</title>
|
||||||
<meta name="description" content="Edytor pociągów online do symulatora Train Driver 2" />
|
<meta name="description" content="Edytor pociągów online do symulatora Train Driver 2" />
|
||||||
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
<link rel="icon" href="/favicon.ico" sizes="any" />
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
|
<link rel="apple-touch-icon" href="/apple-touch-icon-180x180.png" />
|
||||||
<link rel="manifest" href="/site.webmanifest" />
|
|
||||||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
|
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" />
|
||||||
|
<link rel="manifest" href="/site.webmanifest" />
|
||||||
|
|
||||||
<meta name="msapplication-TileColor" content="#da532c" />
|
<meta name="msapplication-TileColor" content="#da532c" />
|
||||||
<meta name="theme-color" content="#e4c428" />
|
<meta name="theme-color" content="#111" />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
<strong>
|
<strong> We're sorry but Pojazdownik doesn't work properly without JavaScript enabled. Please enable it to continue. </strong>
|
||||||
We're sorry but Pojazdownik doesn't work properly without JavaScript enabled. Please enable it to continue.
|
|
||||||
</strong>
|
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.ts"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,36 @@
|
|||||||
{
|
{
|
||||||
"name": "pojazdownik",
|
"name": "pojazdownik",
|
||||||
"version": "1.6.0",
|
"version": "1.8.11",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc --noEmit && vite build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"preview": "yarn build && vite preview --port 4174"
|
"preview": "yarn build && vite preview",
|
||||||
|
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
|
||||||
|
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
|
||||||
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"pinia": "^2.0.17",
|
"pinia": "^2.0.17",
|
||||||
|
"prettier": "^3.0.3",
|
||||||
"vue": "^3.2.37",
|
"vue": "^3.2.37",
|
||||||
"vue-i18n": "9"
|
"vue-i18n": "9.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "^4.1.0",
|
"@rushstack/eslint-patch": "^1.3.3",
|
||||||
|
"@vite-pwa/assets-generator": "^0.2.3",
|
||||||
|
"@vitejs/plugin-vue": "^5.0.3",
|
||||||
|
"@vue/eslint-config-prettier": "^9.0.0",
|
||||||
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
|
"@vue/tsconfig": "^0.5.1",
|
||||||
|
"eslint": "^8.49.0",
|
||||||
|
"eslint-plugin-vue": "^9.17.0",
|
||||||
"sass": "^1.59.3",
|
"sass": "^1.59.3",
|
||||||
"typescript": "^5.0.2",
|
"typescript": "^5.0.2",
|
||||||
"vite": "^4.2.1",
|
"vite": "^5.0.12",
|
||||||
"vite-plugin-pwa": "^0.14.6",
|
"vite-plugin-pwa": "^0.17.5",
|
||||||
"vue-tsc": "^1.2.0"
|
"vue-tsc": "^1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
|
After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,24 @@
|
|||||||
|
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<mask id="path-1-inside-1_102_63" fill="white">
|
||||||
|
<path d="M0 250C0 111.929 111.929 6.10352e-05 250 6.10352e-05C388.071 6.10352e-05 500 111.929 500 250C500 388.071 388.071 500 250 500C111.929 500 0 388.071 0 250Z"/>
|
||||||
|
</mask>
|
||||||
|
<path d="M0 250C0 111.929 111.929 6.10352e-05 250 6.10352e-05C388.071 6.10352e-05 500 111.929 500 250C500 388.071 388.071 500 250 500C111.929 500 0 388.071 0 250Z" fill="#242424"/>
|
||||||
|
<path d="M0 222.821C0 84.7503 111.929 -27.1785 250 -27.1785C388.071 -27.1785 500 84.7503 500 222.821V250C500 126.939 388.071 27.1787 250 27.1787C111.929 27.1787 0 126.939 0 250V222.821ZM500 277.179C500 415.25 388.071 527.179 250 527.179C111.929 527.179 0 415.25 0 277.179V250C0 373.061 111.929 472.821 250 472.821C388.071 472.821 500 373.061 500 250V277.179ZM0 500V6.10352e-05V500ZM500 6.10352e-05V500V6.10352e-05Z" fill="#FFD600" mask="url(#path-1-inside-1_102_63)"/>
|
||||||
|
<path d="M210.369 301.604C210.369 301.604 210.369 341.807 210.369 364.846C210.369 387.885 202.798 417.491 171.591 417.491C140.385 417.491 132.813 417.491 132.813 417.491L132.812 78.125L250.754 78.125C274.312 78.125 294.504 80.9665 311.331 86.6494C328.311 92.1788 342.232 99.8585 353.093 109.689C364.107 119.519 372.214 131.115 377.415 144.478C382.616 157.84 385.217 172.278 385.217 187.791C385.217 204.533 382.54 219.892 377.186 233.869C371.832 247.846 363.648 259.827 352.634 269.81C341.62 279.794 327.623 287.627 310.643 293.31C293.816 298.839 273.853 301.604 250.754 301.604L210.369 301.604ZM210.369 242.854L250.754 242.854C270.946 242.854 285.479 238.016 294.351 228.34C303.224 218.663 307.66 205.147 307.66 187.791C307.66 180.111 306.512 173.123 304.218 166.825C301.923 160.528 298.405 155.152 293.663 150.698C289.074 146.09 283.184 142.558 275.995 140.1C268.958 137.643 260.544 136.414 250.754 136.414L210.369 136.414L210.369 242.854Z" fill="url(#paint0_linear_102_63)"/>
|
||||||
|
<path d="M239.215 301.604C239.215 301.604 239.215 341.807 239.215 364.846C239.215 387.885 231.643 417.491 200.437 417.491C169.231 417.491 161.659 417.491 161.659 417.491L161.658 78.125L279.6 78.125C303.158 78.125 323.35 80.9665 340.177 86.6494C357.157 92.1788 371.077 99.8585 381.938 109.689C392.952 119.519 401.06 131.115 406.261 144.478C411.462 157.84 414.062 172.278 414.062 187.791C414.062 204.533 411.385 219.892 406.031 233.869C400.677 247.846 392.493 259.827 381.479 269.81C370.465 279.794 356.468 287.627 339.488 293.31C322.662 298.839 302.699 301.604 279.6 301.604L239.215 301.604ZM239.215 242.854L279.6 242.854C299.792 242.854 314.325 238.016 323.197 228.34C332.069 218.663 336.505 205.147 336.505 187.791C336.505 180.111 335.358 173.123 333.064 166.825C330.769 160.528 327.251 155.152 322.509 150.698C317.919 146.09 312.03 142.558 304.84 140.1C297.804 137.643 289.39 136.414 279.6 136.414L239.215 136.414L239.215 242.854Z" fill="url(#paint1_linear_102_63)"/>
|
||||||
|
<path d="M210.685 301.604C210.685 301.604 210.685 341.807 210.685 364.846C210.685 387.885 203.082 417.491 171.749 417.491C140.416 417.491 132.813 417.491 132.813 417.491L132.812 78.125L251.233 78.125C274.887 78.125 295.161 80.9665 312.057 86.6494C329.105 92.1788 343.083 99.8585 353.988 109.689C365.046 119.519 373.187 131.115 378.409 144.478C383.631 157.84 386.242 172.278 386.242 187.791C386.242 204.533 383.555 219.892 378.179 233.869C372.803 247.846 364.586 259.827 353.527 269.81C342.468 279.794 328.414 287.627 311.365 293.31C294.47 298.839 274.426 301.604 251.233 301.604L210.685 301.604ZM210.685 242.854L251.233 242.854C271.508 242.854 286.099 238.016 295.008 228.34C303.916 218.663 308.37 205.147 308.37 187.791C308.37 180.111 307.218 173.123 304.914 166.825C302.611 160.528 299.078 155.152 294.316 150.698C289.709 146.09 283.795 142.558 276.576 140.1C269.511 137.643 261.063 136.414 251.233 136.414L210.685 136.414L210.685 242.854Z" fill="url(#paint2_radial_102_63)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_102_63" x1="259.015" y1="78.125" x2="259.015" y2="417.491" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.135417" stop-color="#FFD600"/>
|
||||||
|
<stop offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear_102_63" x1="287.86" y1="78.125" x2="287.86" y2="417.491" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop offset="0.135417" stop-color="#FFD600"/>
|
||||||
|
<stop offset="1"/>
|
||||||
|
</linearGradient>
|
||||||
|
<radialGradient id="paint2_radial_102_63" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(259.527 247.808) rotate(0.36307) scale(345.948 325.206)">
|
||||||
|
<stop offset="0.484375" stop-color="white"/>
|
||||||
|
<stop offset="1"/>
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="white" width="18px" height="18px"><path d="M0 0h24v24H0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
|
||||||
|
After Width: | Height: | Size: 256 B |
|
Before Width: | Height: | Size: 1020 B After Width: | Height: | Size: 1020 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 932 B After Width: | Height: | Size: 932 B |
|
Before Width: | Height: | Size: 953 B After Width: | Height: | Size: 953 B |
@@ -5,15 +5,26 @@
|
|||||||
"description": "Generator składów online dla symulatora Train Driver 2",
|
"description": "Generator składów online dla symulatora Train Driver 2",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "pwa-64x64.png",
|
||||||
|
"sizes": "64x64",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "pwa-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "pwa-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any maskable"
|
"purpose": "any"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "maskable-icon-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#2c3149",
|
"theme_color": "#2c3149",
|
||||||
|
|||||||
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
@@ -5,19 +5,29 @@
|
|||||||
"description": "Generator składów online dla symulatora Train Driver 2",
|
"description": "Generator składów online dla symulatora Train Driver 2",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "pwa-64x64.png",
|
||||||
|
"sizes": "64x64",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "pwa-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "pwa-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png",
|
"type": "image/png",
|
||||||
"purpose": "any maskable"
|
"purpose": "any"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "maskable-icon-512x512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png",
|
||||||
|
"purpose": "maskable"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#2c3149",
|
"theme_color": "#2c3149",
|
||||||
"background_color": "#2c3149",
|
"background_color": "#2c3149",
|
||||||
"display": "standalone"
|
"display": "standalone"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,21 +12,17 @@ import AppContainerView from './views/AppContainerView.vue';
|
|||||||
import AppModals from './components/app/AppModals.vue';
|
import AppModals from './components/app/AppModals.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: { ImageFullscreenPreview, AppContainerView, AppModals },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
async created() {
|
async created() {
|
||||||
/* dev info testing */
|
|
||||||
// if (import.meta.env['VITE_STOCK_DEV'] == '1') {
|
|
||||||
// const data = await import('../stockInfoDev.json');
|
|
||||||
// this.store.stockData = data.default as any;
|
|
||||||
// }
|
|
||||||
this.store.fetchStockInfoData();
|
|
||||||
this.store.handleRouting();
|
this.store.handleRouting();
|
||||||
|
this.store.setupAPIData();
|
||||||
},
|
},
|
||||||
components: { ImageFullscreenPreview, AppContainerView, AppModals },
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -39,31 +35,14 @@ export default defineComponent({
|
|||||||
|
|
||||||
color: $textColor;
|
color: $textColor;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
padding: 1em 0.5em;
|
padding: 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* HEADER SECTION */
|
@media screen and (max-width: $breakpointMd) {
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin: 0;
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
|
|
||||||
color: $accentColor;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-bottom {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.5em;
|
|
||||||
|
|
||||||
color: #d1d1d1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $breakpointMd) {
|
|
||||||
#app {
|
|
||||||
font-size: calc(0.7rem + 0.75vw);
|
font-size: calc(0.7rem + 0.75vw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media screen and (orientation: landscape) and (max-width: $breakpointMd) {
|
||||||
|
font-size: calc(0.75rem + 0.4vw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<RealStockCard v-if="store.isRealStockListCardOpen" />
|
<RealStockCard v-if="store.isRealStockListCardOpen" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import RealStockCard from '../cards/RealStockCard.vue';
|
import RealStockCard from '../cards/RealStockCard.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { RealStockCard },
|
components: { RealStockCard },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
@@ -1,49 +1,44 @@
|
|||||||
<template>
|
<template>
|
||||||
<footer>
|
<footer>
|
||||||
<i18n-t keypath="footer.disclaimer" tag="div" class="text--grayed">
|
<i18n-t keypath="footer.disclaimer" tag="div" class="text--grayed">
|
||||||
<template #tos>
|
<template #tos>
|
||||||
<a style="color: #ccc" :href="$t('footer.tos-href')" target="_blank">
|
<a style="color: #ccc" :href="$t('footer.tos-href')" target="_blank">
|
||||||
{{ $t('footer.tos') }}
|
{{ $t('footer.tos') }}
|
||||||
</a>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
|
|
||||||
<div class="text--grayed" v-if="store.stockData">
|
<div class="text--grayed" v-if="store.vehiclesData">
|
||||||
{{ $t('footer.version-check', { version: store.stockData.version }) }}
|
{{ $t('footer.version-check', { version: store.compatibleSimulatorVersion }) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
©
|
©
|
||||||
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
|
<a href="https://td2.info.pl/profile/?u=20777" target="_blank">Spythere</a>
|
||||||
{{ new Date().getUTCFullYear() }} | v{{ VERSION }}{{ !isOnProductionHost ? 'dev' : '' }}
|
{{ new Date().getUTCFullYear() }} | v{{ VERSION }}{{ !isOnProductionHost ? 'dev' : '' }}
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import packageInfo from '../../../package.json';
|
import packageInfo from '../../../package.json';
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isOnProductionHost: location.hostname == 'pojazdownik-td2.web.app',
|
isOnProductionHost: location.hostname == 'pojazdownik-td2.web.app',
|
||||||
VERSION: packageInfo.version,
|
VERSION: packageInfo.version,
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
footer {
|
footer {
|
||||||
display: flex;
|
text-align: center;
|
||||||
flex-direction: column;
|
padding: 1em 1em 0 1em;
|
||||||
gap: 0.25em;
|
}
|
||||||
|
</style>
|
||||||
text-align: center;
|
|
||||||
padding: 1em 1em 0 1em;
|
|
||||||
margin-top: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,45 +1,50 @@
|
|||||||
<template>
|
<template>
|
||||||
<main>
|
<main>
|
||||||
<LogoSection />
|
<LogoSection />
|
||||||
<InputsSection />
|
<InputsSection />
|
||||||
<TrainImageSection />
|
<TrainImageSection />
|
||||||
<StockSection />
|
<StockSection />
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import LogoSection from '../sections/LogoSection.vue';
|
import LogoSection from '../sections/LogoSection.vue';
|
||||||
import InputsSection from '../sections/InputsSection.vue';
|
import InputsSection from '../sections/InputsSection.vue';
|
||||||
import TrainImageSection from '../sections/TrainImageSection.vue';
|
import TrainImageSection from '../sections/TrainImageSection.vue';
|
||||||
import StockSection from '../sections/StockSection.vue';
|
import StockSection from '../sections/StockSection.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: { LogoSection, InputsSection, TrainImageSection, StockSection },
|
components: { LogoSection, InputsSection, TrainImageSection, StockSection },
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../styles/global.scss';
|
@import '../../styles/global.scss';
|
||||||
|
|
||||||
main {
|
main {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 1500px;
|
max-width: 1350px;
|
||||||
min-height: 75vh;
|
|
||||||
|
grid-template-columns: 1fr 2fr;
|
||||||
grid-template-columns: 1fr 2fr;
|
grid-template-rows: auto 360px minmax(300px, 1fr);
|
||||||
grid-template-rows: auto 360px minmax(400px, 1fr);
|
|
||||||
}
|
background-color: darken($color: $bgColor, $amount: 5);
|
||||||
|
border-radius: 1em;
|
||||||
@media screen and (max-width: $breakpointMd) {
|
|
||||||
main {
|
min-height: 950px;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
padding: 1em;
|
||||||
grid-template-columns: 1fr;
|
}
|
||||||
grid-template-rows: 1fr;
|
|
||||||
}
|
@media screen and (max-width: $breakpointMd) {
|
||||||
}
|
main {
|
||||||
</style>
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -6,9 +6,12 @@
|
|||||||
<div class="card_nav">
|
<div class="card_nav">
|
||||||
<div class="top-pane">
|
<div class="top-pane">
|
||||||
<h1>
|
<h1>
|
||||||
{{ $t('realstock.title') }} <a href="https://td2.info.pl/profile/?u=17708" target="_blank">Railtrains997</a>
|
{{ $t('realstock.title') }}
|
||||||
|
<a href="https://td2.info.pl/profile/?u=17708" target="_blank">Railtrains997</a>
|
||||||
</h1>
|
</h1>
|
||||||
<button class="btn exit-btn" @click="store.isRealStockListCardOpen = false">⨯</button>
|
<button class="btn action-exit" @click="store.isRealStockListCardOpen = false">
|
||||||
|
<img src="/images/icon-exit.svg" alt="" />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="filters" ref="focus" tabindex="0">
|
<div class="filters" ref="focus" tabindex="0">
|
||||||
@@ -19,7 +22,11 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<datalist id="readyStockDataList">
|
<datalist id="readyStockDataList">
|
||||||
<option v-for="stock in store.readyStockList" :value="stock.stockId">
|
<option
|
||||||
|
v-for="stock in filteredCompositionList"
|
||||||
|
:value="stock.stockId"
|
||||||
|
:key="stock.name"
|
||||||
|
>
|
||||||
{{ stock.stockId }}
|
{{ stock.stockId }}
|
||||||
</option>
|
</option>
|
||||||
</datalist>
|
</datalist>
|
||||||
@@ -31,37 +38,49 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<datalist id="readyStockStringList">
|
<datalist id="readyStockStringList">
|
||||||
<option v-for="stock in computedAvailableStockTypes" :value="stock">
|
<option
|
||||||
{{ stock }}
|
v-for="stockType in availableCompositionTypes"
|
||||||
|
:value="stockType"
|
||||||
|
:key="stockType"
|
||||||
|
>
|
||||||
|
{{ stockType }}
|
||||||
</option>
|
</option>
|
||||||
</datalist>
|
</datalist>
|
||||||
|
|
||||||
<button class="btn" @click="resetStockFilters">{{ $t('realstock.action-reset') }}</button>
|
<button class="btn action-reset" @click="resetStockFilters">
|
||||||
|
{{ $t('realstock.action-reset') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ul class="card_list" ref="list" @scroll="onListScroll">
|
<ul class="card_list" ref="list" @scroll="onListScroll">
|
||||||
<li
|
<li v-for="rStock in filteredCompositionList" :key="rStock.stockId">
|
||||||
v-for="rStock in computedReadyStockList"
|
<!-- :data-last-selected="store.ch === rStock.stockId" -->
|
||||||
:key="rStock.stockId"
|
<div
|
||||||
:data-last-selected="store.chosenRealStockName === rStock.stockId"
|
class="stock-title"
|
||||||
>
|
tabindex="0"
|
||||||
<div class="stock-title" tabindex="0" @click="chooseStock(rStock)" @keydown.enter="chooseStock(rStock)">
|
@click="chooseStock(rStock)"
|
||||||
|
@keydown.enter="chooseStock(rStock)"
|
||||||
|
>
|
||||||
<img class="stock-icon" :src="getIconURL(rStock.type)" :alt="rStock.type" />
|
<img class="stock-icon" :src="getIconURL(rStock.type)" :alt="rStock.type" />
|
||||||
<b class="text--accent" style="margin-left: 5px"> {{ rStock.name }}</b>
|
<b class="text--accent" style="margin-left: 5px"> {{ rStock.name }}</b>
|
||||||
<div>{{ rStock.number }}</div>
|
<div>{{ rStock.number }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stock-thumbnails" ref="thumbnailsRef">
|
<div class="stock-thumbnails" ref="thumbnailsRef">
|
||||||
<div class="thumbnail-item" v-for="stockType in rStock.stockString.split(';')">
|
<div
|
||||||
|
class="thumbnail-item"
|
||||||
|
v-for="stockType in rStock.stockString.split(';')"
|
||||||
|
:key="stockType"
|
||||||
|
>
|
||||||
<div class="thumbnail-container">
|
<div class="thumbnail-container">
|
||||||
<div>{{ stockType }}</div>
|
<div>{{ stockType }}</div>
|
||||||
<img
|
<img
|
||||||
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stockType}.png`"
|
:src="`https://static.spythere.eu/thumbnails/${stockType}.png`"
|
||||||
:title="stockType"
|
:title="stockType"
|
||||||
style="opacity: 0"
|
style="opacity: 0"
|
||||||
@error="(e) => onStockItemError(e, stockType)"
|
@error="(e) => onStockItemError(e, stockType)"
|
||||||
@load="e => (e.target as HTMLElement).style.opacity = '1'"
|
@load="(e) => ((e.target as HTMLElement).style.opacity = '1')"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,17 +100,13 @@ import { useStore } from '../../store';
|
|||||||
import imageMixin from '../../mixins/imageMixin';
|
import imageMixin from '../../mixins/imageMixin';
|
||||||
import stockMixin from '../../mixins/stockMixin';
|
import stockMixin from '../../mixins/stockMixin';
|
||||||
|
|
||||||
import { IReadyStockItem } from '../../types';
|
import { IRealComposition, VehicleGroupType } from '../../types';
|
||||||
|
|
||||||
interface ResponseJSONData {
|
function getVehicleType(stockType: string): VehicleGroupType {
|
||||||
[key: string]: string;
|
if (/^E/.test(stockType)) return 'loco-electric';
|
||||||
}
|
if (/^S/.test(stockType)) return 'loco-diesel';
|
||||||
|
|
||||||
function getVehicleType(stockType: string) {
|
return 'wagon-passenger';
|
||||||
if (/^E/.test(stockType)) return 'loco-e';
|
|
||||||
if (/^S/.test(stockType)) return 'loco-s';
|
|
||||||
|
|
||||||
return 'car-passenger';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -100,7 +115,10 @@ export default defineComponent({
|
|||||||
data: () => ({
|
data: () => ({
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
responseStatus: 'loading',
|
responseStatus: 'loading',
|
||||||
isMobile: 'ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/) ? true : false,
|
isMobile:
|
||||||
|
'ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/)
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
observer: null as IntersectionObserver | null,
|
observer: null as IntersectionObserver | null,
|
||||||
searchedReadyStockName: '',
|
searchedReadyStockName: '',
|
||||||
searchedReadyStockString: '',
|
searchedReadyStockString: '',
|
||||||
@@ -109,9 +127,8 @@ export default defineComponent({
|
|||||||
scrollTop: 0,
|
scrollTop: 0,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
async mounted() {
|
mounted() {
|
||||||
this.mountObserver();
|
this.mountObserver();
|
||||||
this.fetchStockListData();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
activated() {
|
activated() {
|
||||||
@@ -124,20 +141,22 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
computedReadyStockList() {
|
filteredCompositionList() {
|
||||||
if (this.searchedReadyStockName == null) return this.store.readyStockList;
|
return this.store.realCompositionList
|
||||||
|
|
||||||
return this.store.readyStockList
|
|
||||||
.filter(
|
.filter(
|
||||||
(rs) =>
|
(rc) =>
|
||||||
rs.stockId.toLocaleLowerCase().includes(this.searchedReadyStockName.toLocaleLowerCase()) &&
|
rc.stockId
|
||||||
rs.stockString.toLocaleLowerCase().includes(this.searchedReadyStockString.toLocaleLowerCase())
|
.toLocaleLowerCase()
|
||||||
|
.includes(this.searchedReadyStockName.toLocaleLowerCase()) &&
|
||||||
|
rc.stockString
|
||||||
|
.toLocaleLowerCase()
|
||||||
|
.includes(this.searchedReadyStockString.toLocaleLowerCase())
|
||||||
)
|
)
|
||||||
.filter((_, i) => i <= this.visibleIndexesTo);
|
.filter((_, i) => i <= this.visibleIndexesTo);
|
||||||
},
|
},
|
||||||
|
|
||||||
computedAvailableStockTypes() {
|
availableCompositionTypes() {
|
||||||
return this.store.readyStockList
|
return this.store.realCompositionList
|
||||||
.reduce((acc, rs) => {
|
.reduce((acc, rs) => {
|
||||||
rs.stockString.split(';').forEach((s) => {
|
rs.stockString.split(';').forEach((s) => {
|
||||||
if (!acc.includes(s)) acc.push(s);
|
if (!acc.includes(s)) acc.push(s);
|
||||||
@@ -150,7 +169,7 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
computedReadyStockList(curr, prev) {
|
filteredCompositionList(curr, prev) {
|
||||||
if (curr.length < prev.length) {
|
if (curr.length < prev.length) {
|
||||||
this.visibleIndexesTo = 20;
|
this.visibleIndexesTo = 20;
|
||||||
(this.$refs['list'] as HTMLElement).scrollTo({
|
(this.$refs['list'] as HTMLElement).scrollTo({
|
||||||
@@ -161,35 +180,6 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async fetchStockListData() {
|
|
||||||
const readyStockJSONData: ResponseJSONData = await (
|
|
||||||
await fetch(`https://spythere.github.io/api/td2/data/readyStock.json?t=${Math.floor(Date.now() / 60000)}`)
|
|
||||||
).json();
|
|
||||||
|
|
||||||
if (!readyStockJSONData) {
|
|
||||||
this.responseStatus = 'error';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let stockKey in readyStockJSONData) {
|
|
||||||
const [type, number, ...name] = stockKey.split(' ');
|
|
||||||
|
|
||||||
const obj = {
|
|
||||||
number: number.replace(/_/g, '/'),
|
|
||||||
name: name.join(' '),
|
|
||||||
stockString: readyStockJSONData[stockKey],
|
|
||||||
type,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.store.readyStockList.push({
|
|
||||||
...obj,
|
|
||||||
stockId: `${obj.type} ${obj.number} ${obj.name}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.responseStatus = 'loaded';
|
|
||||||
},
|
|
||||||
|
|
||||||
mountObserver() {
|
mountObserver() {
|
||||||
this.observer = new IntersectionObserver((entries) => {
|
this.observer = new IntersectionObserver((entries) => {
|
||||||
if (entries[0].intersectionRatio > 0) this.visibleIndexesTo += 20;
|
if (entries[0].intersectionRatio > 0) this.visibleIndexesTo += 20;
|
||||||
@@ -207,7 +197,7 @@ export default defineComponent({
|
|||||||
this.searchedReadyStockString = '';
|
this.searchedReadyStockString = '';
|
||||||
},
|
},
|
||||||
|
|
||||||
chooseStock(stockItem: IReadyStockItem) {
|
chooseStock(stockItem: IRealComposition) {
|
||||||
this.loadStockFromString(stockItem.stockString);
|
this.loadStockFromString(stockItem.stockString);
|
||||||
this.lastSelectedStockId = stockItem.stockId;
|
this.lastSelectedStockId = stockItem.stockId;
|
||||||
this.store.isRealStockListCardOpen = false;
|
this.store.isRealStockListCardOpen = false;
|
||||||
@@ -232,13 +222,15 @@ export default defineComponent({
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../styles/global.scss';
|
@import '../../styles/global.scss';
|
||||||
|
|
||||||
.exit-btn {
|
.action-exit {
|
||||||
font-size: 1.2em;
|
display: flex;
|
||||||
margin: 0.25em 0;
|
background-color: #333;
|
||||||
|
border-radius: 0.25em;
|
||||||
|
padding: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn {
|
.action-reset {
|
||||||
background-color: #444;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card_content {
|
.card_content {
|
||||||
@@ -378,4 +370,3 @@ ul {
|
|||||||
padding: 1em;
|
padding: 1em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" :data-disabled="disabled" :disabled="disabled" v-model="model" />
|
||||||
|
<div><slot /></div>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
const model = defineModel();
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
disabled: Boolean,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
label {
|
||||||
|
text-transform: uppercase;
|
||||||
|
transition: color 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
background-color: #222;
|
||||||
|
border-radius: 0.25em;
|
||||||
|
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '\2716';
|
||||||
|
margin-right: 0.5em;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
position: absolute;
|
||||||
|
clip: rect(1px, 1px, 1px, 1px);
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
width: 1px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&:focus-visible + div {
|
||||||
|
outline: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:checked + div {
|
||||||
|
color: palegreen;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
color: palegreen;
|
||||||
|
content: '\2714';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
|
||||||
|
+ div {
|
||||||
|
opacity: 0.55;
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,8 +7,9 @@
|
|||||||
<div class="vehicle-types locos">
|
<div class="vehicle-types locos">
|
||||||
<button
|
<button
|
||||||
v-for="locoType in locomotiveTypeList"
|
v-for="locoType in locomotiveTypeList"
|
||||||
|
:key="locoType.id"
|
||||||
class="btn btn--choice"
|
class="btn btn--choice"
|
||||||
:data-selected="locoType.id == store.chosenLocoPower"
|
:data-selected="locoType.id == store.chosenLocoGroup"
|
||||||
@click="selectLocoType(locoType.id)"
|
@click="selectLocoType(locoType.id)"
|
||||||
>
|
>
|
||||||
{{ $t(`inputs.${locoType.id}`) }}
|
{{ $t(`inputs.${locoType.id}`) }}
|
||||||
@@ -23,9 +24,12 @@
|
|||||||
@keydown.enter.prevent="addOrSwitchVehicle"
|
@keydown.enter.prevent="addOrSwitchVehicle"
|
||||||
@keydown.backspace="removeVehicle"
|
@keydown.backspace="removeVehicle"
|
||||||
>
|
>
|
||||||
<option :value="null" disabled>{{ $t('inputs.input-vehicle') }}</option>
|
<option :value="null" disabled>
|
||||||
|
{{ $t('inputs.input-vehicle') }}
|
||||||
|
</option>
|
||||||
<option v-for="loco in locoOptions" :value="loco" :key="loco.type">
|
<option v-for="loco in locoOptions" :value="loco" :key="loco.type">
|
||||||
{{ loco.type }}<b v-if="loco.supportersOnly">*</b>
|
{{ loco.type
|
||||||
|
}}<b v-if="loco.sponsorOnlyTimestamp && loco.sponsorOnlyTimestamp > Date.now()">*</b>
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -34,8 +38,9 @@
|
|||||||
<div class="vehicle-types carwagons">
|
<div class="vehicle-types carwagons">
|
||||||
<button
|
<button
|
||||||
v-for="carType in carTypeList"
|
v-for="carType in carTypeList"
|
||||||
|
:key="carType.id"
|
||||||
class="btn btn--choice"
|
class="btn btn--choice"
|
||||||
:data-selected="carType.id == store.chosenCarUseType"
|
:data-selected="carType.id == store.chosenCarGroup"
|
||||||
@click="selectCarWagonType(carType.id)"
|
@click="selectCarWagonType(carType.id)"
|
||||||
>
|
>
|
||||||
{{ $t(`inputs.${carType.id}`) }}
|
{{ $t(`inputs.${carType.id}`) }}
|
||||||
@@ -50,10 +55,13 @@
|
|||||||
@keydown.enter.prevent="addOrSwitchVehicle"
|
@keydown.enter.prevent="addOrSwitchVehicle"
|
||||||
@keydown.backspace="removeVehicle"
|
@keydown.backspace="removeVehicle"
|
||||||
>
|
>
|
||||||
<option :value="null" disabled>{{ $t('inputs.input-carwagon') }}</option>
|
<option :value="null" disabled>
|
||||||
|
{{ $t('inputs.input-carwagon') }}
|
||||||
|
</option>
|
||||||
|
|
||||||
<option v-for="car in carOptions" :value="car" :key="car.type">
|
<option v-for="car in carOptions" :value="car" :key="car.type">
|
||||||
{{ car.type }}<b v-if="car.supportersOnly">*</b>
|
{{ car.type
|
||||||
|
}}<b v-if="car.sponsorOnlyTimestamp && car.sponsorOnlyTimestamp > Date.now()">*</b>
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -64,7 +72,7 @@
|
|||||||
id="cargo-select"
|
id="cargo-select"
|
||||||
:disabled="
|
:disabled="
|
||||||
(store.chosenCar && !store.chosenCar.loadable) ||
|
(store.chosenCar && !store.chosenCar.loadable) ||
|
||||||
(store.chosenCar && store.chosenCar.useType == 'car-passenger') ||
|
(store.chosenCar && store.chosenCar.group == 'wagon-passenger') ||
|
||||||
!store.chosenCar
|
!store.chosenCar
|
||||||
"
|
"
|
||||||
data-select="cargo"
|
data-select="cargo"
|
||||||
@@ -78,9 +86,10 @@
|
|||||||
<option :value="null" v-if="!store.chosenCar || !store.chosenCar.loadable">
|
<option :value="null" v-if="!store.chosenCar || !store.chosenCar.loadable">
|
||||||
{{ $t('inputs.no-cargo-available') }}
|
{{ $t('inputs.no-cargo-available') }}
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
<option :value="null" v-else>{{ $t('inputs.cargo-empty') }}</option>
|
<option :value="null" v-else>{{ $t('inputs.cargo-empty') }}</option>
|
||||||
|
|
||||||
<option v-for="cargo in store.chosenCar?.cargoList" :value="cargo" :key="cargo.id">
|
<option v-for="cargo in store.chosenCar?.cargoTypes" :value="cargo" :key="cargo.id">
|
||||||
{{ cargo.id }}
|
{{ cargo.id }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -117,48 +126,58 @@ import imageMixin from '../../mixins/imageMixin';
|
|||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import stockPreviewMixin from '../../mixins/stockPreviewMixin';
|
import stockPreviewMixin from '../../mixins/stockPreviewMixin';
|
||||||
import stockMixin from '../../mixins/stockMixin';
|
import stockMixin from '../../mixins/stockMixin';
|
||||||
|
import { LocoGroupType, WagonGroupType } from '../../types';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
mixins: [imageMixin, stockPreviewMixin, stockMixin],
|
mixins: [imageMixin, stockPreviewMixin, stockMixin],
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
store: useStore(),
|
||||||
locomotiveTypeList: [
|
locomotiveTypeList: [
|
||||||
{
|
{
|
||||||
id: 'loco-e',
|
id: 'loco-electric',
|
||||||
desc: 'ELEKTRYCZNE',
|
desc: 'ELEKTRYCZNE',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'loco-s',
|
id: 'loco-diesel',
|
||||||
desc: 'SPALINOWE',
|
desc: 'SPALINOWE',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'loco-ezt',
|
id: 'unit-electric',
|
||||||
desc: 'ELEKTR. ZESPOŁY TRAKCYJNE',
|
desc: 'ELEKTR. ZESPOŁY TRAKCYJNE',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'loco-szt',
|
id: 'unit-diesel',
|
||||||
desc: 'SPAL. ZESPOŁY TRAKCYJNE',
|
desc: 'SPAL. ZESPOŁY TRAKCYJNE',
|
||||||
},
|
},
|
||||||
],
|
] as { id: LocoGroupType; desc: string }[],
|
||||||
|
|
||||||
carTypeList: [
|
carTypeList: [
|
||||||
{
|
{
|
||||||
id: 'car-passenger',
|
id: 'wagon-passenger',
|
||||||
desc: 'PASAŻERSKIE',
|
desc: 'PASAŻERSKIE',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'car-cargo',
|
id: 'wagon-freight',
|
||||||
desc: 'TOWAROWE',
|
desc: 'TOWAROWE',
|
||||||
},
|
},
|
||||||
],
|
] as { id: WagonGroupType; desc: string }[],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
setup() {
|
computed: {
|
||||||
const store = useStore();
|
locoOptions() {
|
||||||
|
return this.store.locoDataList
|
||||||
|
.slice()
|
||||||
|
.sort((a, b) => (a.type > b.type ? 1 : -1))
|
||||||
|
.filter((loco) => loco.group == this.store.chosenLocoGroup);
|
||||||
|
},
|
||||||
|
|
||||||
return {
|
carOptions() {
|
||||||
store,
|
return this.store.carDataList
|
||||||
};
|
.slice()
|
||||||
|
.sort((a, b) => (a.type > b.type ? 1 : -1))
|
||||||
|
.filter((car) => car.group == this.store.chosenCarGroup);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
@@ -169,17 +188,15 @@ export default defineComponent({
|
|||||||
addOrSwitchVehicle() {
|
addOrSwitchVehicle() {
|
||||||
if (!this.store.chosenVehicle) return;
|
if (!this.store.chosenVehicle) return;
|
||||||
|
|
||||||
if (this.store.chosenStockListIndex == -1) this.addVehicle(this.store.chosenVehicle, this.store.chosenCargo);
|
if (this.store.chosenStockListIndex == -1)
|
||||||
|
this.addVehicle(this.store.chosenVehicle, this.store.chosenCargo);
|
||||||
else this.switchVehicles();
|
else this.switchVehicles();
|
||||||
},
|
},
|
||||||
|
|
||||||
removeVehicle() {
|
removeVehicle() {
|
||||||
if (this.store.stockList.length == 0) return;
|
if (this.store.stockList.length == 0) return;
|
||||||
|
|
||||||
const lastStock = this.store.stockList.slice(-1)[0];
|
this.store.stockList.splice(-1);
|
||||||
|
|
||||||
if (lastStock.count > 1) lastStock.count--;
|
|
||||||
else this.store.stockList.splice(-1);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
switchVehicles() {
|
switchVehicles() {
|
||||||
@@ -192,6 +209,32 @@ export default defineComponent({
|
|||||||
const stockObject = this.getStockObject(vehicle, this.store.chosenCargo);
|
const stockObject = this.getStockObject(vehicle, this.store.chosenCargo);
|
||||||
this.store.stockList[this.store.chosenStockListIndex] = stockObject;
|
this.store.stockList[this.store.chosenStockListIndex] = stockObject;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
selectLocoType(locoGroupType: LocoGroupType) {
|
||||||
|
this.store.chosenLocoGroup = locoGroupType;
|
||||||
|
this.store.chosenVehicle = this.locoOptions[0];
|
||||||
|
this.store.chosenLoco = this.locoOptions[0];
|
||||||
|
},
|
||||||
|
|
||||||
|
selectCarWagonType(wagonGroupType: WagonGroupType) {
|
||||||
|
this.store.chosenCarGroup = wagonGroupType;
|
||||||
|
this.store.chosenVehicle = this.carOptions[0];
|
||||||
|
this.store.chosenCar = this.carOptions[0];
|
||||||
|
this.store.chosenCargo = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
previewVehicleByType(type: 'loco' | 'car' | 'cargo') {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!this.store.chosenLoco && !this.store.chosenCar) return;
|
||||||
|
|
||||||
|
this.store.chosenVehicle = type == 'loco' ? this.store.chosenLoco : this.store.chosenCar;
|
||||||
|
|
||||||
|
this.store.chosenCargo =
|
||||||
|
this.store.chosenCar?.cargoTypes.find(
|
||||||
|
(cargo) => cargo.id == this.store.chosenCargo?.id
|
||||||
|
) || null;
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -207,6 +250,11 @@ export default defineComponent({
|
|||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input_container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 380px;
|
||||||
|
}
|
||||||
|
|
||||||
.input_header {
|
.input_header {
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
@@ -226,6 +274,10 @@ button.btn--choice {
|
|||||||
.input_list {
|
.input_list {
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
@@ -267,4 +319,3 @@ button.btn--choice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button
|
<button
|
||||||
class="btn btn--text"
|
|
||||||
v-for="action in localeActions"
|
v-for="action in localeActions"
|
||||||
|
:key="action.name"
|
||||||
|
class="btn btn--text"
|
||||||
:data-selected="$i18n.locale == action.locale"
|
:data-selected="$i18n.locale == action.locale"
|
||||||
@click="chooseLocale(action.locale)"
|
@click="chooseLocale(action.locale)"
|
||||||
>
|
>
|
||||||
@@ -50,7 +51,6 @@ export default {
|
|||||||
.logo-section {
|
.logo-section {
|
||||||
grid-row: 1;
|
grid-row: 1;
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
margin-bottom: 1.5em;
|
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -76,4 +76,3 @@ img {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
<section class="stock-section">
|
<section class="stock-section">
|
||||||
<div class="section_modes">
|
<div class="section_modes">
|
||||||
<button
|
<button
|
||||||
|
v-for="(id, i) in sectionModes"
|
||||||
|
:key="id"
|
||||||
class="btn"
|
class="btn"
|
||||||
ref="sectionButtonRefs"
|
ref="sectionButtonRefs"
|
||||||
v-for="(id, i) in sectionModes"
|
|
||||||
@click="chooseSection(id)"
|
@click="chooseSection(id)"
|
||||||
:data-selected="store.stockSectionMode == id"
|
:data-selected="store.stockSectionMode == id"
|
||||||
>
|
>
|
||||||
@@ -15,14 +16,14 @@
|
|||||||
|
|
||||||
<transition name="tab-change" mode="out-in">
|
<transition name="tab-change" mode="out-in">
|
||||||
<keep-alive>
|
<keep-alive>
|
||||||
<component :is="chosenSectionComponent" :key="chosenSectionComponent"></component>
|
<component :is="chosenSectionComponent"></component>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, KeepAlive, onMounted, ref } from 'vue';
|
import { computed, onMounted, ref } from 'vue';
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import StockListTab from '../tabs/StockListTab.vue';
|
import StockListTab from '../tabs/StockListTab.vue';
|
||||||
import StockGeneratorTab from '../tabs/StockGeneratorTab.vue';
|
import StockGeneratorTab from '../tabs/StockGeneratorTab.vue';
|
||||||
@@ -34,16 +35,22 @@ const sectionButtonRefs = ref([]);
|
|||||||
const store = useStore();
|
const store = useStore();
|
||||||
type SectionMode = typeof store.stockSectionMode;
|
type SectionMode = typeof store.stockSectionMode;
|
||||||
|
|
||||||
const sectionModes: SectionMode[] = ['stock-list', 'wiki-list', 'number-generator', 'stock-generator'];
|
const sectionModes: SectionMode[] = [
|
||||||
|
'stock-list',
|
||||||
|
'wiki-list',
|
||||||
|
'number-generator',
|
||||||
|
'stock-generator',
|
||||||
|
];
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window.addEventListener('keydown', (e) => {
|
window.addEventListener('keydown', (e) => {
|
||||||
if (e.target instanceof HTMLInputElement) return;
|
if (e.target instanceof HTMLInputElement) return;
|
||||||
|
|
||||||
if (/[1234]/.test(e.key)) {
|
if (/^[1234]$/.test(e.key)) {
|
||||||
const keyNum = Number(e.key);
|
const keyNum = Number(e.key);
|
||||||
|
|
||||||
store.stockSectionMode = sectionModes[keyNum - 1];
|
store.stockSectionMode = sectionModes[keyNum - 1];
|
||||||
(sectionButtonRefs.value[keyNum - 1] as HTMLButtonElement).focus();
|
(sectionButtonRefs.value[keyNum - 1] as HTMLButtonElement)?.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -134,4 +141,3 @@ function chooseSection(sectionId: SectionMode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,57 +1,76 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="train-image-section">
|
<section class="train-image-section">
|
||||||
<div class="train-image__wrapper">
|
<div v-if="store.chosenVehicle">
|
||||||
<div class="train-image__content" :class="{ supporter: store.chosenVehicle?.supportersOnly }">
|
<div class="image-wrapper">
|
||||||
<transition name="img-message-anim">
|
|
||||||
<div class="empty-message" v-if="store.imageLoading && store.chosenVehicle?.imageSrc">
|
|
||||||
{{ $t('preview.loading') }}
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
|
|
||||||
<div class="no-img" v-if="!store.chosenVehicle">{{ $t('preview.title') }}</div>
|
|
||||||
|
|
||||||
<img
|
<img
|
||||||
v-if="store.chosenVehicle"
|
:src="getThumbnailURL(store.chosenVehicle.type, 'small')"
|
||||||
:src="`https://spythere.github.io/api/td2/images/${store.chosenVehicle.type}--300px.jpg`"
|
:data-preview-active="store.chosenVehicle !== null"
|
||||||
:alt="store.chosenVehicle.type"
|
:data-sponsor-only="
|
||||||
@load="onImageLoad"
|
store.chosenVehicle.sponsorOnlyTimestamp &&
|
||||||
|
store.chosenVehicle.sponsorOnlyTimestamp > Date.now()
|
||||||
|
"
|
||||||
|
:data-team-only="store.chosenVehicle.teamOnly"
|
||||||
@click="onImageClick"
|
@click="onImageClick"
|
||||||
|
@keydown.enter="onImageClick"
|
||||||
|
@load="onImageLoad"
|
||||||
|
@error="onImageError"
|
||||||
|
tabindex="0"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- <div class="empty-message" v-if="store.chosenVehicle && !store.chosenVehicle.imageSrc">Ten pojazd nie ma jeszcze podglądu!</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="train-image__info" v-if="store.chosenVehicle">
|
<div class="image-info">
|
||||||
<b class="text--accent">{{ store.chosenVehicle.type }}</b> •
|
<b class="text--accent">{{ store.chosenVehicle.type }}</b> •
|
||||||
<b style="color: #ccc">
|
<b style="color: #ccc">
|
||||||
{{
|
{{
|
||||||
$t(`preview.${isLocomotive(store.chosenVehicle) ? store.chosenVehicle.power : store.chosenVehicle.useType}`)
|
$t(
|
||||||
|
`preview.${isTractionUnit(store.chosenVehicle) ? store.chosenVehicle.group : store.chosenVehicle.group}`
|
||||||
|
)
|
||||||
}}
|
}}
|
||||||
</b>
|
</b>
|
||||||
|
|
||||||
<div style="color: #ccc">
|
<div style="color: #ccc">
|
||||||
<div>
|
<div>
|
||||||
{{ store.chosenVehicle.length }}m | {{ store.chosenVehicle.mass }}t |
|
{{ store.chosenVehicle.length }}m |
|
||||||
|
{{ (store.chosenVehicle.weight / 1000).toFixed(1) }}t |
|
||||||
{{ store.chosenVehicle.maxSpeed }} km/h
|
{{ store.chosenVehicle.maxSpeed }} km/h
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="isLocomotive(store.chosenVehicle)">
|
<div v-if="isTractionUnit(store.chosenVehicle)">
|
||||||
{{ $t('preview.cabin') }} {{ store.chosenVehicle.cabinType }}
|
{{ $t('preview.cabin') }} {{ store.chosenVehicle.cabinType }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else>
|
<div v-else>
|
||||||
{{
|
{{
|
||||||
store.chosenVehicle.useType == 'car-cargo' // ? store.stockData?.usage[store.chosenVehicle.constructionType]
|
store.chosenVehicle.group == 'wagon-freight'
|
||||||
? $t(`usage.${store.chosenVehicle.constructionType}`)
|
? $t(`usage.${store.chosenVehicle.constructionType}`)
|
||||||
: `${$t('preview.construction')} ${store.chosenVehicle.constructionType}`
|
: `${$t('preview.construction')} ${store.chosenVehicle.constructionType}`
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<b style="color: salmon" v-if="store.chosenVehicle.supportersOnly">{{ $t('preview.sponsor-only') }}</b>
|
<b
|
||||||
|
v-if="
|
||||||
|
store.chosenVehicle.sponsorOnlyTimestamp &&
|
||||||
|
store.chosenVehicle.sponsorOnlyTimestamp > Date.now()
|
||||||
|
"
|
||||||
|
class="sponsor-only"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
$t('preview.sponsor-only', [
|
||||||
|
new Date(store.chosenVehicle.sponsorOnlyTimestamp).toLocaleDateString(
|
||||||
|
$i18n.locale == 'pl' ? 'pl-PL' : 'en-GB'
|
||||||
|
),
|
||||||
|
])
|
||||||
|
}}
|
||||||
|
</b>
|
||||||
|
|
||||||
|
<b v-if="store.chosenVehicle.teamOnly" class="team-only">{{ $t('preview.team-only') }}</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="train-image__info" v-else>{{ $t('preview.desc') }}</div>
|
<div v-else>
|
||||||
|
<img src="/images/placeholder.jpg" alt="placeholder image" />
|
||||||
|
<div class="image-info">{{ $t('preview.desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
@@ -59,124 +78,149 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { computed, defineComponent } from 'vue';
|
import { computed, defineComponent } from 'vue';
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import { isLocomotive } from '../../utils/vehicleUtils';
|
import { isTractionUnit } from '../../utils/vehicleUtils';
|
||||||
import { ILocomotive, Vehicle } from '../../types';
|
import imageMixin from '../../mixins/imageMixin';
|
||||||
|
import { watch } from 'vue';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { Ref } from 'vue';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
mixins: [imageMixin],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
noImageAvailable: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
|
const { chosenVehicle } = storeToRefs(store);
|
||||||
|
|
||||||
|
const imageStatus = ref('none') as Ref<'none' | 'loading' | 'loaded' | 'error'>;
|
||||||
|
|
||||||
|
watch(chosenVehicle, () => {
|
||||||
|
imageStatus.value = 'loading';
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
store,
|
store,
|
||||||
|
imageStatus,
|
||||||
chosenVehicle: computed(() => store.chosenVehicle),
|
chosenVehicle: computed(() => store.chosenVehicle),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
|
||||||
chosenVehicle(vehicle: Vehicle, prevVehicle: Vehicle) {
|
|
||||||
if (vehicle && vehicle.type != prevVehicle?.type) {
|
|
||||||
this.store.imageLoading = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onImageLoad() {
|
isTractionUnit,
|
||||||
this.store.imageLoading = false;
|
|
||||||
|
onImageError(e: Event) {
|
||||||
|
const el = e.target as HTMLImageElement;
|
||||||
|
if (el.src == '/images/placeholder.jpg') return;
|
||||||
|
|
||||||
|
el.src = '/images/placeholder.jpg';
|
||||||
|
this.imageStatus = 'error';
|
||||||
},
|
},
|
||||||
|
|
||||||
isLocomotive(vehicle: Vehicle): vehicle is ILocomotive {
|
onImageLoad(e: Event) {
|
||||||
return isLocomotive(vehicle);
|
this.imageStatus = 'loaded';
|
||||||
},
|
},
|
||||||
|
|
||||||
onImageClick() {
|
onImageClick(e: Event) {
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
|
||||||
const chosenVehicle = this.store.chosenVehicle;
|
const chosenVehicle = this.store.chosenVehicle;
|
||||||
|
|
||||||
if (!chosenVehicle) return;
|
if (!chosenVehicle) return;
|
||||||
|
|
||||||
this.store.vehiclePreviewSrc = `https://spythere.github.io/api/td2/images/${chosenVehicle.type}--800px.jpg`;
|
this.store.lastFocusedElement = target;
|
||||||
|
this.store.vehiclePreviewSrc = this.getThumbnailURL(chosenVehicle.type, 'large');
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import '../../styles/global.scss';
|
@import '../../styles/global';
|
||||||
|
|
||||||
.train-image-section {
|
.train-image-section {
|
||||||
grid-row: 3;
|
display: flex;
|
||||||
grid-column: 1;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
margin-top: 2em;
|
min-height: 250px;
|
||||||
height: 22em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.train-image {
|
& > div {
|
||||||
&__wrapper {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__content {
|
|
||||||
border: 1px solid white;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
max-width: 100%;
|
||||||
|
width: 380px;
|
||||||
max-width: 22em;
|
|
||||||
height: 13em;
|
|
||||||
margin: 0 auto;
|
|
||||||
|
|
||||||
&.supporter {
|
|
||||||
border: 1px solid salmon;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
cursor: zoom-in;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-message,
|
|
||||||
.no-img {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
padding: 0.3em 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.empty-message {
|
|
||||||
background: rgba(#000, 0.75);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.train-image__info {
|
img {
|
||||||
margin: 1em 0;
|
width: 100%;
|
||||||
|
|
||||||
|
&[data-preview-active='true'] {
|
||||||
|
border: 1px solid white;
|
||||||
|
cursor: zoom-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-sponsor-only='true'] {
|
||||||
|
border: 1px solid $sponsorColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-team-only='true'] {
|
||||||
|
border: 1px solid $teamColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-wrapper {
|
||||||
|
position: relative;
|
||||||
|
min-height: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
background-color: #2b2b2b;
|
||||||
|
padding: 1em;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-info {
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
padding: 0 1em;
|
padding: 0.5em;
|
||||||
|
// margin: 0.5em auto;
|
||||||
|
line-height: 1.35;
|
||||||
|
|
||||||
b {
|
width: 100%;
|
||||||
font-size: 1.1em;
|
max-width: 380px;
|
||||||
}
|
|
||||||
|
|
||||||
div {
|
background-color: $secondaryColor;
|
||||||
margin: 0.25em 0;
|
font-weight: bold;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transition animations
|
.placeholder {
|
||||||
.img-message-anim {
|
height: 250px;
|
||||||
&-enter-from,
|
|
||||||
&-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-enter-active,
|
background-color: $bgColor;
|
||||||
&-leave-active {
|
}
|
||||||
transition: opacity 75ms ease-in 100ms;
|
|
||||||
}
|
.sponsor-only {
|
||||||
|
color: $sponsorColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.team-only {
|
||||||
|
color: $teamColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $breakpointMd) {
|
@media screen and (max-width: $breakpointMd) {
|
||||||
@@ -185,4 +229,3 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -2,51 +2,110 @@
|
|||||||
<div class="number-generator tab">
|
<div class="number-generator tab">
|
||||||
<div class="tab_header">
|
<div class="tab_header">
|
||||||
<h2>{{ $t('numgen.title') }}</h2>
|
<h2>{{ $t('numgen.title') }}</h2>
|
||||||
|
<h3>{{ $t('numgen.subtitle') }}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab_content">
|
<div class="tab_content">
|
||||||
<div class="options">
|
<div class="inputs">
|
||||||
<select v-model="chosenCategory" @change="randomizeTrainNumber()">
|
<label>
|
||||||
<option :value="null" disabled>{{ $t('numgen.train-category') }}</option>
|
<span>{{ $t('numgen.train-category') }}</span>
|
||||||
<option v-for="(_, category) in genData.categories" :value="category">
|
<select v-model="chosenCategory" @change="randomizeTrainNumber()">
|
||||||
{{ $t(`numgen.categories.${category}`) }}
|
<option :value="null" disabled>
|
||||||
</option>
|
{{ $t('numgen.train-category') }}
|
||||||
</select>
|
</option>
|
||||||
|
<option
|
||||||
|
v-for="(_, category) in genData.categoriesRules"
|
||||||
|
:key="category"
|
||||||
|
:value="category"
|
||||||
|
>
|
||||||
|
{{ $t(`numgen.categories.${category}`) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
<select v-model="beginRegionName" @change="randomizeTrainNumber()">
|
<label>
|
||||||
<option :value="null" disabled>{{ $t('numgen.start-region') }}</option>
|
<span>{{ $t('numgen.start-region') }}</span>
|
||||||
<option v-for="(_, name) in genData.regionNumbers" :value="name">{{ name }}</option>
|
<select v-model="beginRegionName" @change="randomizeTrainNumber()">
|
||||||
</select>
|
<option :value="null" disabled>
|
||||||
|
{{ $t('numgen.start-region') }}
|
||||||
|
</option>
|
||||||
|
<option v-for="(_, name) in genData.regionNumbers" :key="name" :value="name">
|
||||||
|
{{ name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
<select v-model="endRegionName" @change="randomizeTrainNumber()">
|
<label>
|
||||||
<option :value="null" disabled>{{ $t('numgen.end-region') }}</option>
|
<span> {{ $t('numgen.end-region') }}</span>
|
||||||
<option v-for="(_, name) in genData.regionNumbers" :value="name">{{ name }}</option>
|
<select v-model="endRegionName" @change="randomizeTrainNumber()">
|
||||||
</select>
|
<option :value="null" disabled>
|
||||||
|
{{ $t('numgen.end-region') }}
|
||||||
|
</option>
|
||||||
|
<option v-for="(_, name) in genData.regionNumbers" :key="name" :value="name">
|
||||||
|
{{ name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="generated-number" @click="copyNumber">
|
<div class="generated-number" @click="copyNumber">
|
||||||
<span v-if="trainNumber">
|
<span v-if="trainNumber">
|
||||||
{{ $t('numgen.number-info') }} <b class="text--accent">{{ trainNumber }}</b>
|
{{ $t('numgen.number-info') }}
|
||||||
|
<b class="text--accent">{{ trainNumber }}</b>
|
||||||
</span>
|
</span>
|
||||||
<span v-else>{{ $t('numgen.warning') }}</span>
|
<span v-else>{{ $t('numgen.warning') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <div v-if="chosenCategory">
|
<div class="category-rules" v-if="chosenCategory && categoryRules && trainNumber">
|
||||||
Current numbering rules: {{ $t(`numgen.rules.${chosenCategory}`) }};
|
<!-- First & second digit (the same regions) -->
|
||||||
|
<div v-if="beginRegionName && endRegionName && beginRegionName == endRegionName">
|
||||||
|
<b>{{ $t('numgen.rules.two-first-digits') }}</b>
|
||||||
|
{{ $t('numgen.rules.from-pool') }}
|
||||||
|
<b class="text--accent">{{ genData.sameRegions[beginRegionName].join(', ') }}</b>
|
||||||
|
{{ $t('numgen.rules.for-region') }} {{ beginRegionName }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<span v-if="beginRegionName && endRegionName">
|
<!-- First & second digit (different regions) -->
|
||||||
<span v-if="beginRegionName == endRegionName">
|
<div v-else>
|
||||||
pierwsze dwie cyfry:
|
<div>
|
||||||
{{ genData.sameRegions[beginRegionName].join(', ') }}
|
<b>
|
||||||
(numer w obrębie obszaru {{ beginRegionName }})
|
{{ $t('numgen.rules.first-digit') }}
|
||||||
</span>
|
<span class="text--accent">{{ trainNumber[0] }}</span>
|
||||||
|
</b>
|
||||||
|
{{ $t('numgen.rules.for-region-begin') }} {{ beginRegionName }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<span v-else>
|
<div>
|
||||||
pierwsza cyfra: {{ genData.regionNumbers[beginRegionName] }}; druga cyfra:
|
<b>
|
||||||
{{ genData.regionNumbers[endRegionName] }}
|
{{ $t('numgen.rules.second-digit') }}
|
||||||
</span>
|
<span class="text--accent">{{ trainNumber[1] }} </span>
|
||||||
</span>
|
</b>
|
||||||
</div> -->
|
{{ $t('numgen.rules.for-region-end') }} {{ endRegionName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Third digit (non-passenger only) -->
|
||||||
|
<div v-if="categoryRules[0] != null">
|
||||||
|
<b>
|
||||||
|
{{ $t('numgen.rules.third-digit') }}
|
||||||
|
<span class="text--accent">{{ categoryRules[0] }}</span>
|
||||||
|
</b>
|
||||||
|
{{ $t('numgen.rules.for-category') }} {{ chosenCategory }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Last digits -->
|
||||||
|
<div>
|
||||||
|
<b>
|
||||||
|
{{
|
||||||
|
$t(`numgen.rules.${categoryRules[1]?.length == 3 ? 'three' : 'two'}-last-digits`)
|
||||||
|
}}</b
|
||||||
|
>
|
||||||
|
{{ $t('numgen.rules.from-range') }}
|
||||||
|
<b class="text--accent">{{ categoryRules[1] }}-{{ categoryRules[2] }}</b>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
|
||||||
<div class="tab_links">
|
<div class="tab_links">
|
||||||
<a :href="$t('numgen.td2-wiki-link')" target="_blank">
|
<a :href="$t('numgen.td2-wiki-link')" target="_blank">
|
||||||
@@ -57,8 +116,17 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div class="tab_actions">
|
<div class="tab_actions">
|
||||||
<button class="btn" @click="randomizeTrainNumber(true)">{{ $t('numgen.action-random-region') }}</button>
|
<button class="btn" @click="randomizeTrainNumber(true)">
|
||||||
<button class="btn" @click="randomizeTrainNumber(false)">{{ $t('numgen.action-random-number') }}</button>
|
{{ $t('numgen.action-random-region') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn" @click="randomizeCategory">
|
||||||
|
{{ $t('numgen.action-random-category') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn" @click="randomizeTrainNumber(false)">
|
||||||
|
{{ $t('numgen.action-random-number') }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,10 +137,11 @@ import { Ref, ref } from 'vue';
|
|||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
import genData from '../../constants/numberGeneratorData.json';
|
import genData from '../../constants/numberGeneratorData.json';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
type RegionName = keyof typeof genData.regionNumbers;
|
type RegionName = keyof typeof genData.regionNumbers;
|
||||||
type Category = keyof typeof genData.categories;
|
type Category = keyof typeof genData.categoriesRules;
|
||||||
|
|
||||||
const beginRegionName = ref(null) as Ref<RegionName | null>;
|
const beginRegionName = ref(null) as Ref<RegionName | null>;
|
||||||
const endRegionName = ref(null) as Ref<RegionName | null>;
|
const endRegionName = ref(null) as Ref<RegionName | null>;
|
||||||
@@ -87,6 +156,19 @@ const copyNumber = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const categoryRules = computed(() => {
|
||||||
|
if (!chosenCategory.value) return null;
|
||||||
|
|
||||||
|
return genData.categoriesRules[chosenCategory.value];
|
||||||
|
});
|
||||||
|
|
||||||
|
const randomizeCategory = () => {
|
||||||
|
const categoryKeys = Object.keys(genData.categoriesRules) as Category[];
|
||||||
|
chosenCategory.value = categoryKeys[~~(Math.random() * categoryKeys.length)];
|
||||||
|
|
||||||
|
randomizeTrainNumber(false);
|
||||||
|
};
|
||||||
|
|
||||||
const randomizeTrainNumber = (randomizeRegions = false) => {
|
const randomizeTrainNumber = (randomizeRegions = false) => {
|
||||||
// if (categoryRules.value == null) return;
|
// if (categoryRules.value == null) return;
|
||||||
|
|
||||||
@@ -100,9 +182,11 @@ const randomizeTrainNumber = (randomizeRegions = false) => {
|
|||||||
|
|
||||||
let number = '';
|
let number = '';
|
||||||
|
|
||||||
|
// Two first numbers (begin & end regions)
|
||||||
if (beginRegionName.value == endRegionName.value) {
|
if (beginRegionName.value == endRegionName.value) {
|
||||||
const sameRegionsNumbers = genData.sameRegions[beginRegionName.value!];
|
const sameRegionsNumbers = genData.sameRegions[beginRegionName.value!];
|
||||||
const randRegionNumber = sameRegionsNumbers[Math.floor(Math.random() * sameRegionsNumbers.length)];
|
const randRegionNumber =
|
||||||
|
sameRegionsNumbers[Math.floor(Math.random() * sameRegionsNumbers.length)];
|
||||||
number += randRegionNumber.toString();
|
number += randRegionNumber.toString();
|
||||||
} else {
|
} else {
|
||||||
const beginRegionNumber = genData.regionNumbers[beginRegionName.value!];
|
const beginRegionNumber = genData.regionNumbers[beginRegionName.value!];
|
||||||
@@ -117,25 +201,23 @@ const randomizeTrainNumber = (randomizeRegions = false) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Choose default category if it's not chosen
|
||||||
if (chosenCategory.value == null) chosenCategory.value = 'EI';
|
if (chosenCategory.value == null) chosenCategory.value = 'EI';
|
||||||
|
|
||||||
const rulesArray = genData.categories[chosenCategory.value].split(';').map((r) => ({
|
// Get category rules
|
||||||
index: r.split(':')[0],
|
const [thirdNumber, minRange, maxRange] = categoryRules.value!;
|
||||||
rule: r.split(':')[1],
|
|
||||||
nums: Number(r.split(':')[2] || '1'),
|
|
||||||
}));
|
|
||||||
|
|
||||||
rulesArray.forEach((r) => {
|
// Third number
|
||||||
const range = r.rule.split('-');
|
number += thirdNumber ?? '';
|
||||||
|
|
||||||
if (range.length == 1) number += r.rule;
|
// Remaining numbers
|
||||||
else {
|
const rangeNums = minRange!.length;
|
||||||
const [minRange, maxRange] = range;
|
const randRange = Math.floor(
|
||||||
const randRange = Math.floor(Math.random() * (Number(maxRange) - Number(minRange)) + Number(minRange)).toString();
|
Math.random() * (Number(maxRange) - Number(minRange)) + Number(minRange)
|
||||||
|
).toString();
|
||||||
|
const leadingZeros = new Array(Math.abs(randRange.length - rangeNums)).fill('0').join('');
|
||||||
|
|
||||||
number += new Array(Math.abs(randRange.length - r.nums)).fill('0').join('') + randRange;
|
number += `${leadingZeros}${randRange}`;
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
trainNumber.value = number;
|
trainNumber.value = number;
|
||||||
};
|
};
|
||||||
@@ -145,13 +227,31 @@ const randomizeTrainNumber = (randomizeRegions = false) => {
|
|||||||
@import '../../styles/tab.scss';
|
@import '../../styles/tab.scss';
|
||||||
@import '../../styles/global.scss';
|
@import '../../styles/global.scss';
|
||||||
|
|
||||||
.options {
|
.category-select {
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
||||||
gap: 0.5em;
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
width: 100%;
|
width: auto;
|
||||||
|
min-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
|
||||||
|
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs > label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25em;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #ccc;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,14 +267,19 @@ const randomizeTrainNumber = (randomizeRegions = false) => {
|
|||||||
background-color: $secondaryColor;
|
background-color: $secondaryColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category-rules {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.tab_actions {
|
.tab_actions {
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: repeat(3, 1fr);
|
||||||
margin: 0.5em 0;
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab_links {
|
.tab_links {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
margin: 0.25em 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $breakpointMd) {
|
@media screen and (max-width: $breakpointMd) {
|
||||||
@@ -184,9 +289,20 @@ const randomizeTrainNumber = (randomizeRegions = false) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: $breakpointSm) {
|
@media screen and (max-width: $breakpointSm) {
|
||||||
.options select {
|
.regions-select {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.regions-select select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.category-select select {
|
||||||
|
min-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-rules {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,28 @@
|
|||||||
{{ $t('stockgen.properties-desc') }}
|
{{ $t('stockgen.properties-desc') }}
|
||||||
</b>
|
</b>
|
||||||
|
|
||||||
<div class="tab_attributes">
|
<div class="inputs">
|
||||||
<label>
|
<label>
|
||||||
{{ $t('stockgen.input-mass') }}
|
<span>{{ $t('stockgen.input-mass') }}</span>
|
||||||
<input type="number" v-model="maxMass" step="100" max="4000" min="0" />
|
<input type="number" v-model="maxTons" step="100" max="4000" min="0" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
{{ $t('stockgen.input-length') }}
|
<span>{{ $t('stockgen.input-length') }}</span>
|
||||||
<input type="number" v-model="maxLength" step="25" max="650" min="0" />
|
<input type="number" v-model="maxLength" step="25" max="650" min="0" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label>
|
<label>
|
||||||
{{ $t('stockgen.input-carcount') }}
|
<span>{{ $t('stockgen.input-carcount') }}</span>
|
||||||
<input type="number" v-model="maxCarCount" step="1" max="60" min="1" />
|
<input type="number" v-model="maxCarCount" step="1" max="60" min="1" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <hr style="margin: 1em 0" /> -->
|
||||||
|
|
||||||
|
<!-- <div class="generator_options">
|
||||||
|
<Checkbox v-model="isCarGroupingEnabled">Grupuj wylosowane wagony (ustawia podobne wagony obok siebie w składzie)</Checkbox>
|
||||||
|
</div> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -37,12 +43,13 @@
|
|||||||
|
|
||||||
<div class="generator_cargo">
|
<div class="generator_cargo">
|
||||||
<button
|
<button
|
||||||
|
v-for="cargo in computedCargoData"
|
||||||
|
:key="cargo.name"
|
||||||
class="btn"
|
class="btn"
|
||||||
:data-chosen="chosenCargoTypes.includes(cargoName.toString())"
|
:data-chosen="chosenCargoTypes.includes(cargo.name)"
|
||||||
v-for="(cargoArray, cargoName) in store.stockData?.generator.cargo"
|
@click="toggleCargoChosen(cargo.name, cargo.cargoList)"
|
||||||
@click="toggleCargoChosen(cargoName.toString(), cargoArray)"
|
|
||||||
>
|
>
|
||||||
{{ $t(`cargo.${cargoName}`) }}
|
{{ $t(`cargo.${cargo.name}`) }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -78,15 +85,27 @@
|
|||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
<div class="tab_actions">
|
<div class="tab_actions">
|
||||||
<button class="btn" :data-disabled="computedChosenCarTypes.size == 0" @click="generateStock()">
|
<button
|
||||||
|
class="btn"
|
||||||
|
:data-disabled="computedChosenCarTypes.size == 0"
|
||||||
|
@click="generateStock()"
|
||||||
|
>
|
||||||
{{ $t('stockgen.action-generate') }}
|
{{ $t('stockgen.action-generate') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn" :data-disabled="computedChosenCarTypes.size == 0" @click="generateStock(true)">
|
<button
|
||||||
|
class="btn"
|
||||||
|
:data-disabled="computedChosenCarTypes.size == 0"
|
||||||
|
@click="generateStock(true)"
|
||||||
|
>
|
||||||
{{ $t('stockgen.action-generate-empty') }}
|
{{ $t('stockgen.action-generate-empty') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button class="btn" :data-disabled="computedChosenCarTypes.size == 0" @click="resetChosenCargo">
|
<button
|
||||||
|
class="btn"
|
||||||
|
:data-disabled="computedChosenCarTypes.size == 0"
|
||||||
|
@click="resetChosenCargo"
|
||||||
|
>
|
||||||
{{ $t('stockgen.action-reset') }}
|
{{ $t('stockgen.action-reset') }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -100,12 +119,13 @@ import { useStore } from '../../store';
|
|||||||
|
|
||||||
import stockMixin from '../../mixins/stockMixin';
|
import stockMixin from '../../mixins/stockMixin';
|
||||||
import { ICargo, ICarWagon, IStock } from '../../types';
|
import { ICargo, ICarWagon, IStock } from '../../types';
|
||||||
import warningsMixin from '../../mixins/warningsMixin';
|
import { isTractionUnit } from '../../utils/vehicleUtils';
|
||||||
|
|
||||||
|
import generatorDataJSON from '../../data/generatorData.json';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'stock-generator',
|
name: 'stock-generator',
|
||||||
|
mixins: [stockMixin],
|
||||||
mixins: [stockMixin, warningsMixin],
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -116,17 +136,30 @@ export default defineComponent({
|
|||||||
|
|
||||||
previewTimeout: -1,
|
previewTimeout: -1,
|
||||||
|
|
||||||
maxMass: 3000,
|
maxTons: 3000,
|
||||||
maxLength: 650,
|
maxLength: 650,
|
||||||
maxCarCount: 50,
|
maxCarCount: 50,
|
||||||
|
|
||||||
|
isCarGroupingEnabled: false,
|
||||||
|
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
computedChosenCarTypes() {
|
computedChosenCarTypes() {
|
||||||
return new Set<string>(this.chosenCarTypes.sort((c1, c2) => (c1 > c2 ? 1 : -1)));
|
return new Set<string>(this.chosenCarTypes.slice().sort((c1, c2) => (c1 > c2 ? 1 : -1)));
|
||||||
|
},
|
||||||
|
|
||||||
|
computedCargoData() {
|
||||||
|
const cargoGeneratorData = generatorDataJSON.cargo;
|
||||||
|
|
||||||
|
return Object.keys(cargoGeneratorData)
|
||||||
|
.sort((v1, v2) => this.$t(`cargo.${v1}`).localeCompare(this.$t(`cargo.${v2}`)))
|
||||||
|
.map((v) => ({
|
||||||
|
name: v,
|
||||||
|
cargoList: cargoGeneratorData[v as keyof typeof generatorDataJSON.cargo],
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -149,65 +182,95 @@ export default defineComponent({
|
|||||||
this.excludedCarTypes.length = 0;
|
this.excludedCarTypes.length = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// WIP
|
||||||
|
groupStock(stockList: IStock[]) {
|
||||||
|
if (!this.isCarGroupingEnabled) return false;
|
||||||
|
|
||||||
|
stockList.sort((s1, s2) => {
|
||||||
|
return (s1.vehicleRef.constructionType + s1.cargo?.id).localeCompare(
|
||||||
|
s2.vehicleRef.constructionType + s2.cargo?.id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
generateStock(empty = false) {
|
generateStock(empty = false) {
|
||||||
const generatedChosenStockList = this.chosenCargoTypes.reduce((acc, type) => {
|
const generatedChosenStockList = this.chosenCargoTypes.reduce(
|
||||||
this.store.stockData?.generator.cargo[type]
|
(acc, type) => {
|
||||||
.filter((c) => !this.excludedCarTypes.includes(c.split(':')[0]))
|
generatorDataJSON.cargo[type as keyof typeof generatorDataJSON.cargo]
|
||||||
.forEach((c) => {
|
.filter((c) => !this.excludedCarTypes.includes(c.split(':')[0]))
|
||||||
const [type, cargoType] = c.split(':');
|
.forEach((c) => {
|
||||||
|
const [type, cargoType] = c.split(':');
|
||||||
|
|
||||||
const carWagonObjs = this.store.carDataList.filter((cw) => cw.type.startsWith(type));
|
const carWagonObjs = this.store.carDataList.filter((cw) => cw.type.startsWith(type));
|
||||||
const cargoObjs = [] as (ICargo | undefined)[];
|
const cargoObjs = [] as (ICargo | undefined)[];
|
||||||
|
|
||||||
if (!cargoType || empty) cargoObjs.push(undefined);
|
if (!cargoType || empty) cargoObjs.push(undefined);
|
||||||
else if (cargoType == 'all') cargoObjs.push(...carWagonObjs[0]?.cargoList);
|
else if (cargoType == 'all') cargoObjs.push(...carWagonObjs[0]!.cargoTypes);
|
||||||
else cargoObjs.push(carWagonObjs[0]?.cargoList.find((cargo) => cargo.id == cargoType));
|
else
|
||||||
|
cargoObjs.push(carWagonObjs[0]?.cargoTypes.find((cargo) => cargo.id == cargoType));
|
||||||
|
|
||||||
carWagonObjs.forEach((cw) => {
|
carWagonObjs.forEach((cw) => {
|
||||||
cargoObjs.forEach((cargoObj) => {
|
cargoObjs.forEach((cargoObj) => {
|
||||||
const chosenStock = acc.find((a) => a.constructionType.includes(cw.constructionType));
|
const chosenStock = acc.find((a) =>
|
||||||
|
a.constructionType.includes(cw.constructionType)
|
||||||
|
);
|
||||||
|
|
||||||
if (!chosenStock)
|
if (!chosenStock)
|
||||||
acc.push({
|
acc.push({
|
||||||
constructionType: cw.constructionType,
|
constructionType: cw.constructionType,
|
||||||
carPool: [{ carWagon: cw, cargo: cargoObj }],
|
carPool: [{ carWagon: cw, cargo: cargoObj }],
|
||||||
});
|
});
|
||||||
else chosenStock.carPool.push({ carWagon: cw, cargo: cargoObj });
|
else chosenStock.carPool.push({ carWagon: cw, cargo: cargoObj });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as { constructionType: string; carPool: { carWagon: ICarWagon; cargo?: ICargo }[] }[]);
|
},
|
||||||
|
[] as {
|
||||||
|
constructionType: string;
|
||||||
|
carPool: { carWagon: ICarWagon; cargo?: ICargo }[];
|
||||||
|
}[]
|
||||||
|
);
|
||||||
|
|
||||||
let bestGeneration: { stockList: IStock[]; value: number } = { stockList: [], value: 0 };
|
let bestGeneration: { stockList: IStock[]; value: number } = {
|
||||||
|
stockList: [],
|
||||||
|
value: 0,
|
||||||
|
};
|
||||||
|
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
const headingLoco = this.store.stockList[0]?.isLoco ? this.store.stockList[0] : undefined;
|
this.store.stockList.splice(
|
||||||
this.store.stockList.length = headingLoco ? 1 : 0;
|
this.store.stockList.length > 0 && isTractionUnit(this.store.stockList[0].vehicleRef)
|
||||||
|
? 1
|
||||||
|
: 0
|
||||||
|
);
|
||||||
|
|
||||||
const maxMass =
|
let carCount = 0;
|
||||||
this.store.acceptableMass > 0 ? Math.min(this.store.acceptableMass, this.maxMass) : this.maxMass;
|
const maxWeight =
|
||||||
|
this.store.acceptableWeight > 0
|
||||||
|
? Math.min(this.store.acceptableWeight, this.maxTons * 1000)
|
||||||
|
: this.maxTons * 1000;
|
||||||
|
|
||||||
let exceeded = false;
|
// eslint-disable-next-line no-constant-condition
|
||||||
|
while (true) {
|
||||||
while (!exceeded) {
|
const randomStockType =
|
||||||
const randomStockType = generatedChosenStockList[~~(Math.random() * generatedChosenStockList.length)];
|
generatedChosenStockList[~~(Math.random() * generatedChosenStockList.length)];
|
||||||
const { carWagon, cargo } = randomStockType.carPool[~~(Math.random() * randomStockType.carPool.length)];
|
const { carWagon, cargo } =
|
||||||
|
randomStockType.carPool[~~(Math.random() * randomStockType.carPool.length)];
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.store.totalMass + (cargo?.totalMass || carWagon.mass) > maxMass ||
|
this.store.totalWeight + (carWagon.weight + (cargo?.weight ?? 0)) > maxWeight ||
|
||||||
this.store.totalLength + carWagon.length > this.maxLength ||
|
this.store.totalLength + carWagon.length > this.maxLength ||
|
||||||
this.store.stockList.length > this.maxCarCount
|
carCount >= this.maxCarCount
|
||||||
) {
|
) {
|
||||||
exceeded = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addCarWagon(carWagon, cargo);
|
this.addCarWagon(carWagon, cargo);
|
||||||
|
carCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentGenerationValue = this.store.totalLength + this.store.totalMass + this.store.stockList.length;
|
const currentGenerationValue = this.store.totalLength + this.store.totalWeight + carCount;
|
||||||
|
|
||||||
if (bestGeneration.value < currentGenerationValue) {
|
if (bestGeneration.value < currentGenerationValue) {
|
||||||
bestGeneration.stockList = this.store.stockList;
|
bestGeneration.stockList = this.store.stockList;
|
||||||
@@ -215,6 +278,10 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bestStockList = bestGeneration.stockList;
|
||||||
|
|
||||||
|
this.groupStock(bestStockList);
|
||||||
|
|
||||||
this.store.stockList = bestGeneration.stockList;
|
this.store.stockList = bestGeneration.stockList;
|
||||||
this.store.stockSectionMode = 'stock-list';
|
this.store.stockSectionMode = 'stock-list';
|
||||||
},
|
},
|
||||||
@@ -227,7 +294,7 @@ export default defineComponent({
|
|||||||
this.store.chosenLoco = null;
|
this.store.chosenLoco = null;
|
||||||
this.store.chosenCargo = null;
|
this.store.chosenCargo = null;
|
||||||
|
|
||||||
if (c) this.store.chosenCarUseType = c?.useType;
|
if (c) this.store.chosenCarGroup = c?.group;
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleCargoChosen(cargoType: string, vehicles: string[]) {
|
toggleCargoChosen(cargoType: string, vehicles: string[]) {
|
||||||
@@ -261,6 +328,11 @@ export default defineComponent({
|
|||||||
@import '../../styles/global.scss';
|
@import '../../styles/global.scss';
|
||||||
@import '../../styles/tab.scss';
|
@import '../../styles/tab.scss';
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.generator_cargo,
|
.generator_cargo,
|
||||||
.generator_vehicles {
|
.generator_vehicles {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -277,13 +349,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
background-color: $secondaryColor;
|
background-color: $secondaryColor;
|
||||||
|
|
||||||
&[data-chosen='true'] {
|
|
||||||
background-color: $accentColor;
|
|
||||||
color: black;
|
|
||||||
|
|
||||||
box-shadow: 0 0 5px 1px $accentColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[data-excluded='true'] {
|
&[data-excluded='true'] {
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@@ -308,6 +373,34 @@ export default defineComponent({
|
|||||||
gap: 1em;
|
gap: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inputs {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(12em, 1fr));
|
||||||
|
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs > label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25em;
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type='text'] {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.generator_options {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.generator_warning {
|
.generator_warning {
|
||||||
background-color: $accentColor;
|
background-color: $accentColor;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
@@ -316,4 +409,3 @@ export default defineComponent({
|
|||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -4,200 +4,246 @@
|
|||||||
<h2>{{ $t('stocklist.title') }}</h2>
|
<h2>{{ $t('stocklist.title') }}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stock_actions">
|
<div class="tab_content">
|
||||||
<label class="file-label">
|
<div class="stock_actions">
|
||||||
<div class="btn btn--image">
|
<button class="btn btn--image" @click="clickFileInput">
|
||||||
<img src="/images/icon-upload.svg" alt="" />
|
<input type="file" @change="uploadStock" ref="conFile" accept=".con,.txt" />
|
||||||
|
<img src="/images/icon-upload.svg" alt="upload icon" />
|
||||||
{{ $t('stocklist.action-upload') }}
|
{{ $t('stocklist.action-upload') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:data-disabled="stockIsEmpty"
|
||||||
|
:disabled="stockIsEmpty"
|
||||||
|
@click="downloadStock"
|
||||||
|
>
|
||||||
|
<img src="/images/icon-download.svg" alt="download icon" />
|
||||||
|
{{ $t('stocklist.action-download') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:data-disabled="stockIsEmpty"
|
||||||
|
:disabled="stockIsEmpty"
|
||||||
|
@click="copyToClipboard"
|
||||||
|
>
|
||||||
|
<img src="/images/icon-copy.svg" alt="copy icon" />
|
||||||
|
{{ $t('stocklist.action-copy') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:data-disabled="stockIsEmpty"
|
||||||
|
:disabled="stockIsEmpty"
|
||||||
|
@click="resetStock"
|
||||||
|
>
|
||||||
|
<img src="/images/icon-reset.svg" alt="reset icon" />
|
||||||
|
{{ $t('stocklist.action-reset') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:data-disabled="stockIsEmpty"
|
||||||
|
:disabled="stockIsEmpty"
|
||||||
|
@click="shuffleCars"
|
||||||
|
>
|
||||||
|
<img src="/images/icon-shuffle.svg" alt="shuffle icon" />
|
||||||
|
{{ $t('stocklist.action-shuffle') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stock_controls" :data-disabled="store.chosenStockListIndex == -1">
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:tabindex="store.chosenStockListIndex == -1 ? -1 : 0"
|
||||||
|
@click="moveUpStock(store.chosenStockListIndex)"
|
||||||
|
>
|
||||||
|
<img :src="getIconURL('higher')" alt="move up vehicle" />
|
||||||
|
{{ $t('stocklist.action-move-up') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:tabindex="store.chosenStockListIndex == -1 ? -1 : 0"
|
||||||
|
@click="moveDownStock(store.chosenStockListIndex)"
|
||||||
|
>
|
||||||
|
<img :src="getIconURL('lower')" alt="move down vehicle" />
|
||||||
|
{{ $t('stocklist.action-move-down') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn--image"
|
||||||
|
:tabindex="store.chosenStockListIndex == -1 ? -1 : 0"
|
||||||
|
@click="removeStock(store.chosenStockListIndex)"
|
||||||
|
>
|
||||||
|
<img :src="getIconURL('remove')" alt="remove vehicle" />
|
||||||
|
{{ $t('stocklist.action-remove') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stock_specs">
|
||||||
|
<b class="real-stock-info" v-if="chosenRealComposition">
|
||||||
|
<span class="text--accent">
|
||||||
|
<img :src="getIconURL(chosenRealComposition.type)" :alt="chosenRealComposition.type" />
|
||||||
|
{{ chosenRealComposition.number }} {{ chosenRealComposition.name }}
|
||||||
|
</span>
|
||||||
|
|
|
||||||
|
</b>
|
||||||
|
|
||||||
|
<span>
|
||||||
|
{{ $t('stocklist.mass') }}
|
||||||
|
<span class="text--accent">{{ (store.totalWeight / 1000).toFixed(1) }}t</span>
|
||||||
|
({{ $t('stocklist.mass-accepted') }}:
|
||||||
|
<span class="text--accent">{{
|
||||||
|
store.acceptableWeight ? `${~~(store.acceptableWeight / 1000)}t` : '-'
|
||||||
|
}}</span
|
||||||
|
>) - {{ $t('stocklist.length') }}:
|
||||||
|
<span class="text--accent">{{ store.totalLength }}m</span>
|
||||||
|
- {{ $t('stocklist.vmax') }}
|
||||||
|
<span tabindex="0" :data-tooltip="$t('stocklist.disclaimer')">(?)</span>:
|
||||||
|
<span class="text--accent">{{ store.maxStockSpeed }} km/h</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div></div>
|
||||||
|
|
||||||
|
<div class="stock_spawn-settings">
|
||||||
|
<Checkbox :disabled="!store.stockSupportsColdStart" v-model="store.isColdStart">
|
||||||
|
{{ $t('stocklist.coldstart-info') }}
|
||||||
|
</Checkbox>
|
||||||
|
|
||||||
|
<Checkbox :disabled="!store.stockSupportsDoubleManning" v-model="store.isDoubleManned">
|
||||||
|
{{ $t('stocklist.doublemanning-info') }}
|
||||||
|
</Checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stock_warnings" v-if="hasAnyWarnings">
|
||||||
|
<div class="warning" v-if="locoNotSuitable">
|
||||||
|
(!) {{ $t('stocklist.warning-not-suitable') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<input type="file" @change="uploadStock" ref="conFile" accept=".con,.txt" />
|
<div class="warning" v-if="lengthExceeded && store.isTrainPassenger">
|
||||||
</label>
|
(!) {{ $t('stocklist.warning-passenger-too-long') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn btn--image" :data-disabled="stockIsEmpty" :disabled="stockIsEmpty" @click="downloadStock">
|
<div class="warning" v-if="lengthExceeded && !store.isTrainPassenger">
|
||||||
<img src="/images/icon-download.svg" alt="download icon" />
|
(!) {{ $t('stocklist.warning-freight-too-long') }}
|
||||||
{{ $t('stocklist.action-download') }}
|
</div>
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="btn btn--image" :data-disabled="stockIsEmpty" :disabled="stockIsEmpty" @click="copyToClipboard">
|
<div class="warning" v-if="teamOnlyVehicles.length > 0">
|
||||||
<img src="/images/icon-copy.svg" alt="copy icon" />
|
(!)
|
||||||
{{ $t('stocklist.action-copy') }}
|
{{
|
||||||
</button>
|
$t('stocklist.warning-team-only-vehicle', [
|
||||||
|
teamOnlyVehicles.map((v) => v.vehicleRef.type).join(', '),
|
||||||
|
])
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn btn--image" :data-disabled="stockIsEmpty" :disabled="stockIsEmpty" @click="resetStock">
|
<div class="warning" v-if="weightExceeded">
|
||||||
<img src="/images/icon-reset.svg" alt="reset icon" />
|
(!)
|
||||||
{{ $t('stocklist.action-reset') }}
|
<i18n-t keypath="stocklist.warning-too-heavy">
|
||||||
</button>
|
<template #href>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://docs.google.com/spreadsheets/d/1BvTU-U7huIaEheov22TrhTtROUM4MwVfdbq03GVAEM8"
|
||||||
|
>
|
||||||
|
{{ $t('stocklist.acceptable-mass-docs') }}
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn btn--image" :data-disabled="stockIsEmpty" :disabled="stockIsEmpty" @click="shuffleCars">
|
<div class="warning" v-if="locoCountExceeded">
|
||||||
<img src="/images/icon-shuffle.svg" alt="shuffle icon" />
|
{{ $t('stocklist.warning-too-many-locos') }}
|
||||||
{{ $t('stocklist.action-shuffle') }}
|
</div>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stock_controls" :data-disabled="store.chosenStockListIndex == -1">
|
|
||||||
<b v-if="store.chosenStockListIndex >= 0">
|
|
||||||
{{ $t('stocklist.vehicle-no') }} <span class="text--accent">{{ store.chosenStockListIndex + 1 }}</span>
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<b v-else>
|
|
||||||
{{ $t('stocklist.no-vehicle-chosen') }}
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn"
|
|
||||||
:tabindex="store.chosenStockListIndex == -1 ? -1 : 0"
|
|
||||||
@click="moveUpStock(store.chosenStockListIndex)"
|
|
||||||
>
|
|
||||||
<img :src="getIconURL('higher')" alt="move up vehicle" />
|
|
||||||
{{ $t('stocklist.action-move-up') }}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn"
|
|
||||||
:tabindex="store.chosenStockListIndex == -1 ? -1 : 0"
|
|
||||||
@click="moveDownStock(store.chosenStockListIndex)"
|
|
||||||
>
|
|
||||||
<img :src="getIconURL('lower')" alt="move down vehicle" />
|
|
||||||
{{ $t('stocklist.action-move-down') }}
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn"
|
|
||||||
:tabindex="store.chosenStockListIndex == -1 ? -1 : 0"
|
|
||||||
@click="removeStock(store.chosenStockListIndex)"
|
|
||||||
>
|
|
||||||
<img :src="getIconURL('remove')" alt="remove vehicle" />
|
|
||||||
{{ $t('stocklist.action-remove') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stock_specs">
|
|
||||||
<b class="real-stock-info" v-if="store.chosenRealStock">
|
|
||||||
<span class="text--accent">
|
|
||||||
<img :src="getIconURL(store.chosenRealStock.type)" :alt="store.chosenRealStock.type" />
|
|
||||||
{{ store.chosenRealStock.number }} {{ store.chosenRealStock.name }}
|
|
||||||
</span>
|
|
||||||
|
|
|
||||||
</b>
|
|
||||||
|
|
||||||
<span>
|
|
||||||
{{ $t('stocklist.mass') }} <span class="text--accent">{{ store.totalMass }}t</span> ({{
|
|
||||||
$t('stocklist.mass-accepted')
|
|
||||||
}}: <span class="text--accent">{{ store.acceptableMass ? store.acceptableMass + 't' : '-' }}</span
|
|
||||||
>) - {{ $t('stocklist.length') }}:
|
|
||||||
<span class="text--accent">{{ store.totalLength }}m</span>
|
|
||||||
- {{ $t('stocklist.vmax') }}: <span class="text--accent">{{ store.maxStockSpeed }} km/h</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stock_cold-start">
|
|
||||||
<label>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
v-model="store.isColdStart"
|
|
||||||
:disabled="!locoSupportsColdStart(store.stockList[0]?.constructionType || '')"
|
|
||||||
/>
|
|
||||||
{{ $t('stocklist.coldstart-info') }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="stock_warnings" v-if="stockHasWarnings">
|
|
||||||
<div class="warning" v-if="locoNotSuitable">(!) {{ $t('stocklist.warning-not-suitable') }}</div>
|
|
||||||
|
|
||||||
<div class="warning" v-if="trainTooLong && store.isTrainPassenger">
|
|
||||||
(!) {{ $t('stocklist.warning-passenger-too-long') }}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="warning" v-if="trainTooLong && !store.isTrainPassenger">
|
<StockThumbnails :onListItemClick="onListItemClick" />
|
||||||
(!) {{ $t('stocklist.warning-freight-too-long') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="warning" v-if="trainTooHeavy">
|
<!-- Stock list -->
|
||||||
(!)
|
<div class="list-wrapper">
|
||||||
<i18n-t keypath="stocklist.warning-too-heavy">
|
<div v-if="stockIsEmpty" class="list-empty">
|
||||||
<template #href>
|
<div class="stock-info">{{ $t('stocklist.list-empty') }}</div>
|
||||||
<a
|
</div>
|
||||||
target="_blank"
|
|
||||||
href="https://docs.google.com/spreadsheets/d/1bFXUsHsAu4youmNz-46Q1HslZaaoklvfoBDS553TnNk/edit"
|
<ul v-else>
|
||||||
|
<transition-group name="stock-list-anim">
|
||||||
|
<li
|
||||||
|
v-for="(stock, i) in store.stockList"
|
||||||
|
:key="stock.id"
|
||||||
|
:class="{ loco: isTractionUnit(stock.vehicleRef) }"
|
||||||
|
tabindex="0"
|
||||||
|
@click="onListItemClick(i)"
|
||||||
|
@keydown.enter="onListItemClick(i)"
|
||||||
|
@keydown.w="moveUpStock(i)"
|
||||||
|
@keydown.s="moveDownStock(i)"
|
||||||
|
@keydown.backspace="removeStock(i)"
|
||||||
|
ref="itemRefs"
|
||||||
>
|
>
|
||||||
{{ $t('stocklist.acceptable-mass-docs') }}
|
<div
|
||||||
</a>
|
class="stock-info"
|
||||||
</template>
|
@dragstart="onDragStart(i)"
|
||||||
</i18n-t>
|
@drop="onDrop($event, i)"
|
||||||
</div>
|
@dragover="allowDrop"
|
||||||
|
draggable="true"
|
||||||
|
>
|
||||||
|
<span class="stock-info-no" :data-selected="i == store.chosenStockListIndex">
|
||||||
|
<span v-if="i == store.chosenStockListIndex">• </span>
|
||||||
|
{{ i + 1 }}.
|
||||||
|
</span>
|
||||||
|
|
||||||
<div class="warning" v-if="tooManyLocomotives">
|
<span
|
||||||
{{ $t('stocklist.warning-too-many-locos') }}
|
class="stock-info-type"
|
||||||
|
:data-sponsor-only="
|
||||||
|
stock.vehicleRef.sponsorOnlyTimestamp &&
|
||||||
|
stock.vehicleRef.sponsorOnlyTimestamp > Date.now()
|
||||||
|
"
|
||||||
|
:data-team-only="stock.vehicleRef.teamOnly"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
isTractionUnit(stock.vehicleRef)
|
||||||
|
? stock.vehicleRef.type
|
||||||
|
: getCarSpecFromType(stock.vehicleRef.type)
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="stock-info-cargo" v-if="stock.cargo">
|
||||||
|
{{ stock.cargo.id }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span class="stock-info-length">{{ stock.vehicleRef.length }}m</span>
|
||||||
|
|
||||||
|
<span class="stock-info-mass">
|
||||||
|
{{ ((stock.vehicleRef.weight + (stock.cargo?.weight ?? 0)) / 1000).toFixed(1) }}t
|
||||||
|
</span>
|
||||||
|
<span class="stock-info-speed">{{ stock.vehicleRef.maxSpeed }}km/h</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</transition-group>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<StockThumbnails :onListItemClick="onListItemClick" />
|
|
||||||
|
|
||||||
<!-- Stock list -->
|
|
||||||
<ul ref="stock_list">
|
|
||||||
<li v-if="stockIsEmpty" class="list-empty">
|
|
||||||
<div class="stock-info">{{ $t('stocklist.list-empty') }}</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<TransitionGroup name="stock-list-anim">
|
|
||||||
<li
|
|
||||||
v-for="(stock, i) in store.stockList"
|
|
||||||
:key="stock.id"
|
|
||||||
:class="{ loco: stock.isLoco }"
|
|
||||||
tabindex="0"
|
|
||||||
@click="onListItemClick(i)"
|
|
||||||
@keydown.enter="onListItemClick(i)"
|
|
||||||
@keydown.w="moveUpStock(i)"
|
|
||||||
@keydown.s="moveDownStock(i)"
|
|
||||||
@keydown.backspace="removeStock(i)"
|
|
||||||
ref="itemRefs"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="stock-info"
|
|
||||||
@dragstart="onDragStart(i)"
|
|
||||||
@drop="onDrop($event, i)"
|
|
||||||
@dragover="allowDrop"
|
|
||||||
draggable="true"
|
|
||||||
>
|
|
||||||
<span class="stock-info__no" :data-selected="i == store.chosenStockListIndex">
|
|
||||||
<span v-if="i == store.chosenStockListIndex">• </span>
|
|
||||||
{{ i + 1 }}.
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="stock-info__type" :class="{ supporter: stock.supportersOnly }">
|
|
||||||
{{ stock.isLoco ? stock.type : getCarSpecFromType(stock.type) }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="stock-info__cargo" v-if="stock.cargo"> {{ stock.cargo.id }} </span>
|
|
||||||
<span class="stock-info__length"> {{ stock.length }}m </span>
|
|
||||||
<span class="stock-info__mass">{{ stock.cargo ? stock.cargo.totalMass : stock.mass }}t </span>
|
|
||||||
<span class="stock-info__speed"> {{ stock.maxSpeed }}km/h </span>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</TransitionGroup>
|
|
||||||
</ul>
|
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import TrainImage from '../sections/TrainImageSection.vue';
|
|
||||||
|
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
|
|
||||||
import { locoSupportsColdStart } from '../../utils/locoUtils';
|
|
||||||
import warningsMixin from '../../mixins/warningsMixin';
|
|
||||||
import imageMixin from '../../mixins/imageMixin';
|
import imageMixin from '../../mixins/imageMixin';
|
||||||
import stockPreviewMixin from '../../mixins/stockPreviewMixin';
|
import stockPreviewMixin from '../../mixins/stockPreviewMixin';
|
||||||
import StockThumbnails from '../utils/StockThumbnails.vue';
|
import StockThumbnails from '../utils/StockThumbnails.vue';
|
||||||
import stockMixin from '../../mixins/stockMixin';
|
import stockMixin from '../../mixins/stockMixin';
|
||||||
|
import Checkbox from '../common/Checkbox.vue';
|
||||||
|
import { isTractionUnit } from '../../utils/vehicleUtils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'stock-list',
|
name: 'stock-list',
|
||||||
components: { TrainImage, StockThumbnails },
|
components: { StockThumbnails, Checkbox },
|
||||||
|
|
||||||
mixins: [warningsMixin, imageMixin, stockMixin, stockPreviewMixin],
|
mixins: [imageMixin, stockMixin, stockPreviewMixin],
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
@@ -215,14 +261,30 @@ export default defineComponent({
|
|||||||
}),
|
}),
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
chosenRealComposition() {
|
||||||
|
const currentStockString = this.store.stockList.map((s) => s.vehicleRef.type).join(';');
|
||||||
|
|
||||||
|
return this.store.realCompositionList.find((rc) => rc.stockString == currentStockString);
|
||||||
|
},
|
||||||
|
|
||||||
stockString() {
|
stockString() {
|
||||||
|
if (this.store.stockList.length == 0) return '';
|
||||||
|
|
||||||
|
const includeColdStart = this.store.isColdStart && this.store.stockSupportsColdStart;
|
||||||
|
const includeDoubleManned =
|
||||||
|
this.store.isDoubleManned && this.store.stockSupportsDoubleManning;
|
||||||
|
|
||||||
return this.store.stockList
|
return this.store.stockList
|
||||||
.map((stock, i) => {
|
.map((stock, i) => {
|
||||||
let stockTypeStr = stock.isLoco || !stock.cargo ? stock.type : `${stock.type}:${stock.cargo.id}`;
|
let stockTypeStr =
|
||||||
let coldStart =
|
isTractionUnit(stock.vehicleRef) || !stock.cargo
|
||||||
i == 0 && this.store.isColdStart && locoSupportsColdStart(stock.constructionType || '') ? ',c' : '';
|
? stock.vehicleRef.type
|
||||||
|
: `${stock.vehicleRef.type}:${stock.cargo.id}`;
|
||||||
|
|
||||||
return stockTypeStr + coldStart;
|
if (i == 0 && (includeColdStart || includeDoubleManned))
|
||||||
|
return `${stockTypeStr},${includeColdStart ? 'c' : ''}${includeDoubleManned ? 'd' : ''}`;
|
||||||
|
|
||||||
|
return stockTypeStr;
|
||||||
})
|
})
|
||||||
.join(';');
|
.join(';');
|
||||||
},
|
},
|
||||||
@@ -232,16 +294,59 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
|
|
||||||
chosenStockVehicle() {
|
chosenStockVehicle() {
|
||||||
return this.store.chosenStockListIndex == -1 ? undefined : this.store.stockList[this.store.chosenStockListIndex];
|
return this.store.chosenStockListIndex == -1
|
||||||
|
? undefined
|
||||||
|
: this.store.stockList[this.store.chosenStockListIndex];
|
||||||
},
|
},
|
||||||
|
|
||||||
stockHasWarnings() {
|
lengthExceeded() {
|
||||||
return this.tooManyLocomotives || this.trainTooHeavy || this.trainTooLong || this.locoNotSuitable;
|
return (
|
||||||
|
(this.store.totalLength > 350 && this.store.isTrainPassenger) ||
|
||||||
|
(this.store.totalLength > 650 && !this.store.isTrainPassenger)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
weightExceeded() {
|
||||||
|
return this.store.acceptableWeight && this.store.totalWeight > this.store.acceptableWeight;
|
||||||
|
},
|
||||||
|
|
||||||
|
locoNotSuitable() {
|
||||||
|
return (
|
||||||
|
!this.store.isTrainPassenger &&
|
||||||
|
this.store.stockList.length > 1 &&
|
||||||
|
!this.store.stockList.every((stock) => isTractionUnit(stock.vehicleRef)) &&
|
||||||
|
this.store.stockList.some(
|
||||||
|
(stock) => isTractionUnit(stock.vehicleRef) && stock.vehicleRef.type.startsWith('EP')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
locoCountExceeded() {
|
||||||
|
return (
|
||||||
|
this.store.stockList.reduce((acc, stock) => {
|
||||||
|
if (isTractionUnit(stock.vehicleRef)) acc += 1;
|
||||||
|
return acc;
|
||||||
|
}, 0) > 2
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
teamOnlyVehicles() {
|
||||||
|
return this.store.stockList.filter((stock) => stock.vehicleRef.teamOnly);
|
||||||
|
},
|
||||||
|
|
||||||
|
hasAnyWarnings() {
|
||||||
|
return (
|
||||||
|
this.locoCountExceeded ||
|
||||||
|
this.weightExceeded ||
|
||||||
|
this.lengthExceeded ||
|
||||||
|
this.locoNotSuitable ||
|
||||||
|
this.teamOnlyVehicles
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
locoSupportsColdStart,
|
isTractionUnit,
|
||||||
|
|
||||||
copyToClipboard() {
|
copyToClipboard() {
|
||||||
navigator.clipboard.writeText(this.stockString);
|
navigator.clipboard.writeText(this.stockString);
|
||||||
@@ -251,11 +356,18 @@ export default defineComponent({
|
|||||||
}, 20);
|
}, 20);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clickFileInput() {
|
||||||
|
(this.$refs['conFile'] as HTMLInputElement).click();
|
||||||
|
},
|
||||||
|
|
||||||
onListItemClick(stockID: number) {
|
onListItemClick(stockID: number) {
|
||||||
const stock = this.store.stockList[stockID];
|
const stock = this.store.stockList[stockID];
|
||||||
|
|
||||||
this.store.chosenStockListIndex =
|
this.store.chosenStockListIndex =
|
||||||
this.store.chosenStockListIndex == stockID && this.store.chosenVehicle?.type == stock.type ? -1 : stockID;
|
this.store.chosenStockListIndex == stockID &&
|
||||||
|
this.store.chosenVehicle?.type == stock.vehicleRef.type
|
||||||
|
? -1
|
||||||
|
: stockID;
|
||||||
|
|
||||||
if (this.store.chosenStockListIndex == -1) {
|
if (this.store.chosenStockListIndex == -1) {
|
||||||
this.store.chosenVehicle = null;
|
this.store.chosenVehicle = null;
|
||||||
@@ -284,20 +396,6 @@ export default defineComponent({
|
|||||||
this.store.chosenStockListIndex = -1;
|
this.store.chosenStockListIndex = -1;
|
||||||
},
|
},
|
||||||
|
|
||||||
addStock(index: number) {
|
|
||||||
if (index == -1) return;
|
|
||||||
|
|
||||||
this.store.stockList[index].count++;
|
|
||||||
},
|
|
||||||
|
|
||||||
subStock(index: number) {
|
|
||||||
if (index == -1) return;
|
|
||||||
|
|
||||||
if (this.store.stockList[index].count < 2) return;
|
|
||||||
|
|
||||||
this.store.stockList[index].count--;
|
|
||||||
},
|
|
||||||
|
|
||||||
removeStock(index: number) {
|
removeStock(index: number) {
|
||||||
if (index == -1) return;
|
if (index == -1) return;
|
||||||
|
|
||||||
@@ -331,7 +429,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
shuffleCars() {
|
shuffleCars() {
|
||||||
const availableIndexes = this.store.stockList.reduce((acc, stock, i) => {
|
const availableIndexes = this.store.stockList.reduce((acc, stock, i) => {
|
||||||
if (!stock.isLoco) acc.push(i);
|
if (!isTractionUnit(stock.vehicleRef)) acc.push(i);
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as number[]);
|
}, [] as number[]);
|
||||||
@@ -341,7 +439,8 @@ export default defineComponent({
|
|||||||
|
|
||||||
availableIndexes.splice(i, -1);
|
availableIndexes.splice(i, -1);
|
||||||
|
|
||||||
const randAvailableIndex = availableIndexes[Math.floor(Math.random() * availableIndexes.length)];
|
const randAvailableIndex =
|
||||||
|
availableIndexes[Math.floor(Math.random() * availableIndexes.length)];
|
||||||
const tempSwap = this.store.stockList[randAvailableIndex];
|
const tempSwap = this.store.stockList[randAvailableIndex];
|
||||||
|
|
||||||
this.store.stockList[randAvailableIndex] = this.store.stockList[i];
|
this.store.stockList[randAvailableIndex] = this.store.stockList[i];
|
||||||
@@ -352,9 +451,9 @@ export default defineComponent({
|
|||||||
downloadStock() {
|
downloadStock() {
|
||||||
if (this.store.stockList.length == 0) return alert(this.$t('stocklist.alert-empty'));
|
if (this.store.stockList.length == 0) return alert(this.$t('stocklist.alert-empty'));
|
||||||
|
|
||||||
const defaultName = `${this.store.chosenRealStockName || this.store.stockList[0].type} ${
|
const defaultName = `${this.chosenRealComposition ? this.chosenRealComposition.stockId + ' ' : ''}${this.store.stockList[0].vehicleRef.type} ${(this.store.totalWeight / 1000).toFixed(1)}t; ${
|
||||||
this.store.totalMass
|
this.store.totalLength
|
||||||
}t; ${this.store.totalLength}m; vmax ${this.store.maxStockSpeed}`;
|
}m; vmax ${this.store.maxStockSpeed}`;
|
||||||
|
|
||||||
const fileName = prompt(this.$t('stocklist.prompt-file'), defaultName);
|
const fileName = prompt(this.$t('stocklist.prompt-file'), defaultName);
|
||||||
|
|
||||||
@@ -390,7 +489,7 @@ export default defineComponent({
|
|||||||
this.loadStockFromString(stockString);
|
this.loadStockFromString(stockString);
|
||||||
};
|
};
|
||||||
|
|
||||||
reader.onerror = (err) => console.log(err);
|
reader.onerror = (err) => console.error(err);
|
||||||
|
|
||||||
inputEl.value = '';
|
inputEl.value = '';
|
||||||
},
|
},
|
||||||
@@ -425,13 +524,15 @@ export default defineComponent({
|
|||||||
@import '../../styles/global';
|
@import '../../styles/global';
|
||||||
@import '../../styles/tab.scss';
|
@import '../../styles/tab.scss';
|
||||||
|
|
||||||
.stock-list-tab {
|
.tab_content {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-gap: 0.5em;
|
flex-direction: column;
|
||||||
|
gap: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning {
|
.warning {
|
||||||
padding: 0.25em;
|
padding: 0.25em;
|
||||||
|
margin: 0.25em 0;
|
||||||
background: $accentColor;
|
background: $accentColor;
|
||||||
color: black;
|
color: black;
|
||||||
|
|
||||||
@@ -447,9 +548,9 @@ export default defineComponent({
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
@@ -464,21 +565,6 @@ export default defineComponent({
|
|||||||
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input#stock-count {
|
|
||||||
width: 3em;
|
|
||||||
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.25em;
|
|
||||||
outline: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
img {
|
|
||||||
margin-right: 0.25em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stock_actions {
|
.stock_actions {
|
||||||
@@ -487,25 +573,41 @@ export default defineComponent({
|
|||||||
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
|
||||||
label.file-label {
|
button {
|
||||||
text-align: center;
|
width: 100%;
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
input {
|
input {
|
||||||
display: none;
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.stock_spawn-settings {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.real-stock-info {
|
.real-stock-info {
|
||||||
img {
|
img {
|
||||||
height: 1.3ch;
|
height: 1.3ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
.list-wrapper {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
}
|
||||||
|
|
||||||
|
.list-empty {
|
||||||
|
background-color: $secondaryColor;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
padding: 0.75em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
overflow-y: scroll;
|
||||||
height: 500px;
|
height: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,16 +625,11 @@ ul > li {
|
|||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: 1px solid white;
|
outline: 1px solid white;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.list-empty {
|
|
||||||
background-color: $secondaryColor;
|
|
||||||
border-radius: 0.5em;
|
|
||||||
padding: 0.75em;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
li > .stock-info {
|
li > .stock-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 0.25em;
|
||||||
|
|
||||||
color: white;
|
color: white;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -541,46 +638,39 @@ li > .stock-info {
|
|||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
margin-right: 0.25em;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.supporter {
|
.stock-info-no,
|
||||||
color: salmon;
|
.stock-info-type {
|
||||||
|
background-color: $secondaryColor;
|
||||||
|
|
||||||
|
&[data-team-only='true'] {
|
||||||
|
color: $teamColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-sponsor-only='true'] {
|
||||||
|
color: $sponsorColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.stock-info {
|
.stock-info-no {
|
||||||
&__no,
|
min-width: 3.5em;
|
||||||
&__type {
|
text-align: right;
|
||||||
background-color: $secondaryColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__count {
|
&[data-selected='true'] {
|
||||||
background-color: #e04e3e;
|
color: $accentColor;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__no {
|
.stock-info-cargo {
|
||||||
min-width: 3.5em;
|
background-color: #333;
|
||||||
text-align: right;
|
}
|
||||||
|
|
||||||
&[data-selected='true'] {
|
.stock-info-length,
|
||||||
color: $accentColor;
|
.stock-info-mass,
|
||||||
}
|
.stock-info-speed {
|
||||||
}
|
background-color: #555;
|
||||||
|
|
||||||
&__cargo {
|
|
||||||
background-color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__length,
|
|
||||||
&__mass,
|
|
||||||
&__speed {
|
|
||||||
background-color: #555;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stock-list-anim {
|
.stock-list-anim {
|
||||||
@@ -610,4 +700,3 @@ li > .stock-info {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,356 +1,324 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="wiki-list tab">
|
<section class="wiki-list tab">
|
||||||
<div class="tab_header">
|
<div class="tab_header">
|
||||||
<h2>{{ $t('wiki.title') }}</h2>
|
<h2>{{ $t('wiki.title') }}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab_content">
|
<div class="tab_content">
|
||||||
<div class="actions-panel">
|
<div class="actions">
|
||||||
<div class="actions-panel_vehicles">
|
<div class="action action-input">
|
||||||
<button class="btn btn--choice" @click="changeWikiMode('locomotives')">
|
<label for="search-vehicle">
|
||||||
{{ $t('wiki.action-vehicles') }}
|
{{ $t('wiki.labels.search-vehicle') }}
|
||||||
</button>
|
<button class="reset-btn" @click="resetSearchInput">
|
||||||
<button class="btn btn--choice" @click="changeWikiMode('carWagons')">
|
<img src="/images/icon-exit.svg" alt="reset vehicle input icon" />
|
||||||
{{ $t('wiki.action-carriages') }}
|
</button>
|
||||||
</button>
|
</label>
|
||||||
</div>
|
<input
|
||||||
|
type="text"
|
||||||
<div class="actions-panel_search">
|
id="search-vehicle"
|
||||||
<input type="text" :placeholder="$t('wiki.search')" v-model="searchedVehicleTypeName" />
|
name="search-vehicle"
|
||||||
</div>
|
:placeholder="$t('wiki.labels.search-vehicle-placeholder')"
|
||||||
</div>
|
v-model="searchedVehicleTypeName"
|
||||||
|
/>
|
||||||
<div class="table-wrapper" @scroll="scrollEvent" ref="table-wrapper">
|
</div>
|
||||||
<table>
|
|
||||||
<thead>
|
<div class="action action-select">
|
||||||
<tr>
|
<label for="filter-type">{{ $t('wiki.labels.vehicles') }}</label>
|
||||||
<th v-for="header in wikiMode == 'locomotives' ? locoHeaders : carHeaders" @click="toggleSorter(header)">
|
<select name="filter-type" id="filter-type" v-model="filterType">
|
||||||
{{ $t(`wiki.header.${header.id}`) }}
|
<option v-for="filter in filters" :key="filter" :value="filter">
|
||||||
|
{{ $t(`wiki.filters.${filter}`) }}
|
||||||
<span v-if="currentModeSorter.id == header.id">
|
</option>
|
||||||
{{ currentModeSorter.direction == 1 ? `⇑` : `⇓` }}
|
</select>
|
||||||
</span>
|
</div>
|
||||||
</th>
|
|
||||||
</tr>
|
<div class="action action-select">
|
||||||
</thead>
|
<label for="sorter-type">{{ $t('wiki.labels.sort-by') }}</label>
|
||||||
|
<select name="sorter-type" id="sorter-type" v-model="sorterType">
|
||||||
<tbody v-if="wikiMode == 'locomotives'">
|
<option v-for="sorter in sorters" :key="sorter" :value="sorter">
|
||||||
<tr
|
{{ $t(`wiki.sort-by.${sorter}`) }}
|
||||||
v-for="loco in computedLocoList"
|
</option>
|
||||||
@click="previewLocomotive(loco)"
|
</select>
|
||||||
@keydown.enter="previewLocomotive(loco)"
|
</div>
|
||||||
@dblclick="addLocomotive(loco)"
|
|
||||||
tabindex="0"
|
<div class="action action-select">
|
||||||
>
|
<label for="sorter-direction">{{ $t('wiki.labels.sort-direction') }}</label>
|
||||||
<td>
|
|
||||||
<img
|
<select name="sorter-direction" id="sorter-direction" v-model="sorterDirection">
|
||||||
:src="`https://spythere.github.io/api/td2/images/${loco.type}--300px.jpg`"
|
<option value="asc">{{ $t('wiki.sort-direction.asc') }}</option>
|
||||||
loading="lazy"
|
<option value="desc">{{ $t('wiki.sort-direction.desc') }}</option>
|
||||||
:alt="`Lokomotywa ${loco.type}`"
|
</select>
|
||||||
/>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
|
|
||||||
<td>{{ loco.type }}</td>
|
<ul class="vehicles" ref="vehicles">
|
||||||
<td>{{ $t(`wiki.${loco.power}`) }}</td>
|
<li
|
||||||
<td>{{ loco.constructionType }}</td>
|
v-for="vehicle in computedVehicles"
|
||||||
<td>{{ locoSupportsColdStart(loco.constructionType) ? `✓` : '✗' }}</td>
|
:key="vehicle.type"
|
||||||
<td>{{ loco.length }}m</td>
|
:data-preview="vehicle.type === store.chosenVehicle?.type"
|
||||||
<td>{{ loco.mass }}t</td>
|
@click="previewVehicle(vehicle)"
|
||||||
<td>{{ loco.maxSpeed }}km/h</td>
|
@dblclick="addVehicle(vehicle)"
|
||||||
</tr>
|
@keydown.enter="onVehicleSelect(vehicle)"
|
||||||
</tbody>
|
tabindex="0"
|
||||||
|
>
|
||||||
<tbody v-else>
|
<img loading="lazy" width="120" :src="getThumbnailURL(vehicle.type, 'small')" />
|
||||||
<tr
|
|
||||||
v-for="car in computedCarList"
|
<span>
|
||||||
@keydow.enter="previewCarWagon(car)"
|
<span
|
||||||
@click="previewCarWagon(car)"
|
class="vehicle-name"
|
||||||
@dblclick="addCarWagon(car)"
|
:class="{
|
||||||
tabindex="0"
|
'sponsor-only':
|
||||||
>
|
vehicle.sponsorOnlyTimestamp && vehicle.sponsorOnlyTimestamp > Date.now(),
|
||||||
<td>
|
'team-only': vehicle.teamOnly,
|
||||||
<img
|
}"
|
||||||
:src="`https://spythere.github.io/api/td2/images/${car.type}--300px.jpg`"
|
>
|
||||||
loading="lazy"
|
<b>{{ vehicle.type.replace(/_/g, ' ') }}</b>
|
||||||
:alt="`Lokomotywa ${car.type}`"
|
</span>
|
||||||
/>
|
|
||||||
</td>
|
<div class="vehicle-group">
|
||||||
|
{{ $t(`wiki.${vehicle.group}`) }} |
|
||||||
<td>{{ car.type }}</td>
|
{{ isTractionUnit(vehicle) ? vehicle.cabinType : vehicle.constructionType }}
|
||||||
<td>{{ car.constructionType }}</td>
|
</div>
|
||||||
<td>{{ car.length }}m</td>
|
|
||||||
<td>{{ car.mass }}t</td>
|
<div class="vehicle-props">
|
||||||
<td>{{ car.maxSpeed }}km/h</td>
|
{{ vehicle.length }}m | {{ (vehicle.weight / 1000).toFixed(1) }}t |
|
||||||
<td>{{ car.cargoList.length == 0 ? '-' : car.cargoList.length }}</td>
|
{{ vehicle.maxSpeed }}km/h
|
||||||
</tr>
|
</div>
|
||||||
</tbody>
|
</span>
|
||||||
</table>
|
</li>
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
|
||||||
</section>
|
<div class="no-vehicles-warning" v-if="computedVehicles.length == 0">
|
||||||
</template>
|
{{ $t('wiki.no-vehicles') }}
|
||||||
|
</div>
|
||||||
<script lang="ts">
|
</div>
|
||||||
import { defineComponent } from 'vue';
|
</section>
|
||||||
import { useStore } from '../../store';
|
</template>
|
||||||
import stockPreviewMixin from '../../mixins/stockPreviewMixin';
|
|
||||||
import { Vehicle } from '../../types';
|
<script lang="ts">
|
||||||
import { isLocomotive } from '../../utils/vehicleUtils';
|
import { defineComponent } from 'vue';
|
||||||
import stockMixin from '../../mixins/stockMixin';
|
import { useStore } from '../../store';
|
||||||
import { locoSupportsColdStart } from '../../utils/locoUtils';
|
import stockPreviewMixin from '../../mixins/stockPreviewMixin';
|
||||||
|
import { IVehicle } from '../../types';
|
||||||
type WikiMode = 'locomotives' | 'carWagons';
|
import { isTractionUnit } from '../../utils/vehicleUtils';
|
||||||
type SorterID =
|
import stockMixin from '../../mixins/stockMixin';
|
||||||
| 'type'
|
import imageMixin from '../../mixins/imageMixin';
|
||||||
| 'constructionType'
|
|
||||||
| 'image'
|
const sorters = ['type', 'group', 'length', 'weight', 'maxSpeed'] as const;
|
||||||
| 'length'
|
const filters = ['vehicles-all', 'vehicles-traction', 'vehicles-wagon'] as const;
|
||||||
| 'mass'
|
|
||||||
| 'maxSpeed'
|
type SorterType = (typeof sorters)[number];
|
||||||
| 'cargoCount'
|
type SorterDirection = 'asc' | 'desc';
|
||||||
| 'power'
|
|
||||||
| 'coldStart';
|
type FilterType = (typeof filters)[number];
|
||||||
|
|
||||||
interface WikiHeader {
|
export default defineComponent({
|
||||||
id: SorterID;
|
mixins: [stockPreviewMixin, stockMixin, imageMixin],
|
||||||
sortable: boolean;
|
|
||||||
}
|
data() {
|
||||||
|
return {
|
||||||
const locoHeaders: WikiHeader[] = [
|
store: useStore(),
|
||||||
{ id: 'image', sortable: false },
|
observer: null as IntersectionObserver | null,
|
||||||
{ id: 'type', sortable: true },
|
|
||||||
{ id: 'power', sortable: true },
|
sorters: sorters,
|
||||||
{ id: 'constructionType', sortable: true },
|
filters: filters,
|
||||||
{ id: 'coldStart', sortable: true },
|
|
||||||
{ id: 'length', sortable: true },
|
searchedVehicleTypeName: '',
|
||||||
{ id: 'mass', sortable: true },
|
|
||||||
{ id: 'maxSpeed', sortable: true },
|
sorterType: 'type' as SorterType,
|
||||||
];
|
sorterDirection: 'asc' as SorterDirection,
|
||||||
|
|
||||||
const carHeaders: WikiHeader[] = [
|
filterType: 'vehicles-all' as FilterType,
|
||||||
{ id: 'image', sortable: false },
|
|
||||||
{ id: 'type', sortable: true },
|
lastScrollTop: 0,
|
||||||
{ id: 'constructionType', sortable: true },
|
};
|
||||||
{ id: 'length', sortable: true },
|
},
|
||||||
{ id: 'mass', sortable: true },
|
|
||||||
{ id: 'maxSpeed', sortable: true },
|
deactivated() {
|
||||||
{ id: 'cargoCount', sortable: true },
|
this.lastScrollTop = (this.$refs['vehicles'] as HTMLUListElement)?.scrollTop || 0;
|
||||||
];
|
},
|
||||||
|
|
||||||
export default defineComponent({
|
activated() {
|
||||||
mixins: [stockPreviewMixin, stockMixin],
|
(this.$refs['vehicles'] as HTMLUListElement)?.scrollTo({ top: this.lastScrollTop });
|
||||||
|
},
|
||||||
data() {
|
|
||||||
return {
|
watch: {
|
||||||
store: useStore(),
|
computedVehicles() {
|
||||||
locoHeaders,
|
const vehiclesRef = this.$refs['vehicles'] as HTMLElement;
|
||||||
carHeaders,
|
|
||||||
|
vehiclesRef.scrollTo({
|
||||||
locosScrollTop: 0,
|
top: 0,
|
||||||
carsScrollTop: 0,
|
});
|
||||||
|
},
|
||||||
wikiMode: 'locomotives' as WikiMode,
|
},
|
||||||
searchedVehicleTypeName: '',
|
|
||||||
|
methods: {
|
||||||
currentLocoSorter: {
|
isTractionUnit,
|
||||||
id: 'type' as SorterID,
|
|
||||||
direction: 1,
|
onVehicleSelect(vehicle: IVehicle) {
|
||||||
},
|
if (this.store.chosenVehicle?.type === vehicle.type) this.addVehicle(vehicle);
|
||||||
|
this.previewVehicle(vehicle);
|
||||||
currentCarSorter: {
|
},
|
||||||
id: 'type' as SorterID,
|
|
||||||
direction: 1,
|
resetSearchInput() {
|
||||||
},
|
this.searchedVehicleTypeName = '';
|
||||||
};
|
},
|
||||||
},
|
|
||||||
|
filterVehicles(v: IVehicle) {
|
||||||
activated() {
|
if (
|
||||||
const tableWrapperRef = this.$refs['table-wrapper'] as HTMLElement;
|
this.searchedVehicleTypeName != '' &&
|
||||||
tableWrapperRef.scrollTo({ top: this.wikiMode == 'locomotives' ? this.locosScrollTop : this.carsScrollTop });
|
!v.type.toLocaleLowerCase().includes(this.searchedVehicleTypeName.toLocaleLowerCase())
|
||||||
},
|
)
|
||||||
|
return false;
|
||||||
methods: {
|
|
||||||
locoSupportsColdStart,
|
if (
|
||||||
|
(this.filterType == 'vehicles-traction' && !isTractionUnit(v)) ||
|
||||||
scrollEvent(e: Event) {
|
(this.filterType == 'vehicles-wagon' && isTractionUnit(v))
|
||||||
const tableScrollTop = (e.target as HTMLElement).scrollTop;
|
)
|
||||||
|
return false;
|
||||||
if (this.wikiMode == 'locomotives') this.locosScrollTop = tableScrollTop;
|
|
||||||
else this.carsScrollTop = tableScrollTop;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
changeWikiMode(wikiMode: WikiMode) {
|
sortVehicles(v1: IVehicle, v2: IVehicle) {
|
||||||
this.searchedVehicleTypeName = '';
|
const direction = this.sorterDirection == 'asc' ? 1 : -1;
|
||||||
this.wikiMode = wikiMode;
|
|
||||||
},
|
switch (this.sorterType) {
|
||||||
|
case 'type':
|
||||||
toggleSorter(header: WikiHeader) {
|
case 'group':
|
||||||
if (!header.sortable) return;
|
return direction * v1[this.sorterType].localeCompare(v2[this.sorterType]);
|
||||||
|
|
||||||
if (header.id == this.currentModeSorter.id) this.currentModeSorter.direction *= -1;
|
case 'weight':
|
||||||
this.currentModeSorter.id = header.id;
|
case 'length':
|
||||||
},
|
case 'maxSpeed':
|
||||||
|
return Math.sign(v1[this.sorterType] - v2[this.sorterType]) * direction;
|
||||||
sortVehicles(vA: Vehicle, vB: Vehicle) {
|
|
||||||
const { id, direction } = this.currentModeSorter;
|
default:
|
||||||
const vehiclesAreLocos = isLocomotive(vA) && isLocomotive(vB);
|
return v1.type.localeCompare(v2.type) * direction;
|
||||||
const vehiclesAreCars = !isLocomotive(vA) && !isLocomotive(vB);
|
}
|
||||||
|
},
|
||||||
switch (id) {
|
},
|
||||||
case 'type':
|
|
||||||
case 'constructionType':
|
computed: {
|
||||||
return direction == 1 ? vA[id].localeCompare(vB[id]) : vB[id].localeCompare(vA[id]);
|
computedVehicles() {
|
||||||
|
return this.store.vehicleDataList.filter(this.filterVehicles).sort(this.sortVehicles);
|
||||||
case 'mass':
|
},
|
||||||
case 'length':
|
},
|
||||||
case 'maxSpeed':
|
});
|
||||||
return Math.sign(vA[id] - vB[id]) * direction;
|
</script>
|
||||||
|
|
||||||
case 'cargoCount':
|
<style lang="scss" scoped>
|
||||||
if (vehiclesAreCars) return Math.sign((vA.cargoList.length || -1) - (vB.cargoList.length || -1)) * direction;
|
@import '../../styles/tab.scss';
|
||||||
|
|
||||||
case 'coldStart':
|
.actions {
|
||||||
if (vehiclesAreLocos)
|
display: grid;
|
||||||
return (
|
grid-template-columns: repeat(auto-fit, minmax(10em, 1fr));
|
||||||
(locoSupportsColdStart(vA.constructionType) > locoSupportsColdStart(vB.constructionType) ? 1 : -1) *
|
|
||||||
direction
|
flex-wrap: wrap;
|
||||||
);
|
gap: 0.5em;
|
||||||
|
}
|
||||||
default:
|
|
||||||
break;
|
.action {
|
||||||
}
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
return direction == 1 ? vA.type.localeCompare(vB.type) : vB.type.localeCompare(vA.type);
|
gap: 0.5em;
|
||||||
},
|
|
||||||
},
|
label {
|
||||||
|
color: #ccc;
|
||||||
computed: {
|
position: relative;
|
||||||
currentModeSorter() {
|
}
|
||||||
return this.wikiMode == 'carWagons' ? this.currentCarSorter : this.currentLocoSorter;
|
}
|
||||||
},
|
|
||||||
|
.action.action-input label {
|
||||||
computedLocoList() {
|
display: flex;
|
||||||
const trimmedSearchValue = this.searchedVehicleTypeName.trim();
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
return this.store.locoDataList
|
}
|
||||||
.filter((loco) => new RegExp(`${trimmedSearchValue}`, 'i').test(loco.type))
|
|
||||||
.sort(this.sortVehicles);
|
.reset-btn {
|
||||||
},
|
display: flex;
|
||||||
|
background-color: #161c2e;
|
||||||
computedCarList() {
|
border-radius: 0.25em;
|
||||||
const trimmedSearchValue = this.searchedVehicleTypeName.trim();
|
}
|
||||||
|
|
||||||
return this.store.carDataList
|
.vehicles {
|
||||||
.filter((car) => new RegExp(`${trimmedSearchValue}`, 'i').test(car.type))
|
display: grid;
|
||||||
.sort(this.sortVehicles);
|
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
|
||||||
},
|
gap: 0.5em;
|
||||||
},
|
overflow: auto;
|
||||||
});
|
|
||||||
</script>
|
max-height: 730px;
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
margin-top: 0.75em;
|
||||||
@import '../../styles/tab.scss';
|
padding: 0.25em;
|
||||||
|
}
|
||||||
.actions-panel {
|
|
||||||
display: flex;
|
.vehicles > li {
|
||||||
justify-content: space-between;
|
display: flex;
|
||||||
align-items: center;
|
gap: 0.5em;
|
||||||
|
|
||||||
flex-wrap: wrap;
|
background-color: #161c2e;
|
||||||
gap: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
margin: 0.5em 0;
|
min-height: 75px;
|
||||||
}
|
cursor: pointer;
|
||||||
|
|
||||||
.actions-panel_vehicles {
|
&[data-preview='true'] {
|
||||||
display: flex;
|
background-color: #435288;
|
||||||
gap: 0.5em;
|
}
|
||||||
}
|
|
||||||
|
& > span {
|
||||||
.actions-panel_search {
|
display: flex;
|
||||||
input {
|
flex-direction: column;
|
||||||
width: auto;
|
justify-content: space-between;
|
||||||
}
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.table-wrapper {
|
|
||||||
overflow: auto;
|
.vehicle-name {
|
||||||
height: 750px;
|
overflow: hidden;
|
||||||
max-height: 95vh;
|
text-wrap: nowrap;
|
||||||
}
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
.wiki-list table {
|
|
||||||
border-collapse: collapse;
|
.sponsor-only {
|
||||||
width: 100%;
|
color: $sponsorColor;
|
||||||
|
|
||||||
thead {
|
&::after {
|
||||||
position: sticky;
|
content: '*';
|
||||||
top: 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
.team-only {
|
||||||
background-color: #111;
|
color: $teamColor;
|
||||||
padding: 0.5em;
|
|
||||||
user-select: none;
|
&::after {
|
||||||
-moz-user-select: none;
|
content: '*';
|
||||||
-webkit-user-select: none;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tr {
|
.vehicle-props {
|
||||||
cursor: pointer;
|
color: #ccc;
|
||||||
background-color: #333;
|
}
|
||||||
|
|
||||||
&:nth-child(odd) {
|
.no-vehicles-warning {
|
||||||
background-color: #444;
|
text-align: center;
|
||||||
}
|
padding: 1em;
|
||||||
|
background-color: #161c2e;
|
||||||
&:hover {
|
}
|
||||||
background-color: #666;
|
|
||||||
}
|
@media screen and (max-width: $breakpointSm) {
|
||||||
}
|
.actions-panel {
|
||||||
|
align-items: stretch;
|
||||||
td {
|
flex-direction: column;
|
||||||
text-align: center;
|
}
|
||||||
padding: 0.25em;
|
|
||||||
height: 85px;
|
.actions-panel_vehicles {
|
||||||
}
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
td:first-child {
|
}
|
||||||
width: 120px;
|
|
||||||
}
|
.actions-panel_search {
|
||||||
|
display: grid;
|
||||||
td img {
|
}
|
||||||
display: block;
|
}
|
||||||
width: 120px;
|
</style>
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $breakpointMd) {
|
|
||||||
.wiki-list table {
|
|
||||||
td {
|
|
||||||
width: 100px;
|
|
||||||
height: auto;
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 6em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: $breakpointSm) {
|
|
||||||
.actions-panel {
|
|
||||||
align-items: stretch;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions-panel_vehicles {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions-panel_search {
|
|
||||||
display: grid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="image-preview"
|
class="image-preview"
|
||||||
@click="store.vehiclePreviewSrc = ''"
|
@click="store.vehiclePreviewSrc = ''"
|
||||||
@keydown.esc="store.vehiclePreviewSrc = ''"
|
@keydown.esc="store.vehiclePreviewSrc = ''"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<img :src="store.vehiclePreviewSrc" alt="preview" />
|
<img :src="store.vehiclePreviewSrc" alt="preview" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$el.focus();
|
this.$el.focus();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.image-preview {
|
.image-preview {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
background: rgba(black, 0.85);
|
background: rgba(black, 0.85);
|
||||||
cursor: zoom-out;
|
cursor: zoom-out;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,36 +1,52 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="stock_thumbnails" ref="thumbnailsRef">
|
<div class="stock-thumbnails" ref="thumbnailsRef">
|
||||||
<div
|
<ul>
|
||||||
v-for="(stock, stockIndex) in store.stockList"
|
<li
|
||||||
:data-selected="store.chosenStockListIndex == stockIndex"
|
class="thumbnail-item"
|
||||||
draggable="true"
|
v-for="(stock, stockIndex) in store.stockList"
|
||||||
@dragstart="onDragStart(stockIndex)"
|
:key="stockIndex"
|
||||||
@drop="onDrop($event, stockIndex)"
|
:data-selected="store.chosenStockListIndex == stockIndex"
|
||||||
@dragover="allowDrop"
|
:data-sponsor-only="
|
||||||
>
|
stock.vehicleRef.sponsorOnlyTimestamp &&
|
||||||
<span @click="onListItemClick(stockIndex)" :key="stock.id">
|
stock.vehicleRef.sponsorOnlyTimestamp > Date.now()
|
||||||
<b :class="{ supporter: stock.supportersOnly }">
|
"
|
||||||
{{ stock.type }}
|
:data-team-only="stock.vehicleRef.teamOnly"
|
||||||
</b>
|
draggable="true"
|
||||||
|
@dragstart="onDragStart(stockIndex)"
|
||||||
|
@drop="onDrop($event, stockIndex)"
|
||||||
|
@dragover="allowDrop"
|
||||||
|
@click="onListItemClick(stockIndex)"
|
||||||
|
>
|
||||||
|
<div class="stock-text">
|
||||||
|
<p>
|
||||||
|
{{ stock.vehicleRef.type.replace(/_/g, ' ') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
<img
|
<img
|
||||||
|
v-for="thumbnail in getVehicleThumbnails(stock.vehicleRef.type)"
|
||||||
draggable="false"
|
draggable="false"
|
||||||
:src="`https://rj.td2.info.pl/dist/img/thumbnails/${stock.type}.png`"
|
style="min-width: 200px"
|
||||||
:alt="stock.type"
|
:src="`https://static.spythere.eu/thumbnails/v2/${thumbnail.src}.png`"
|
||||||
:title="stock.type"
|
:alt="stock.vehicleRef.type"
|
||||||
@error="stockImageError($event, stock)"
|
:title="stock.vehicleRef.type"
|
||||||
|
@load="($event) => (($event.target as HTMLImageElement).style.minWidth = 'auto')"
|
||||||
|
@error="
|
||||||
|
($event) =>
|
||||||
|
(($event.target as HTMLImageElement).src = `/images/${thumbnail.fallbackSrc}.png`)
|
||||||
|
"
|
||||||
|
height="70"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</li>
|
||||||
</div>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Ref, computed, nextTick, ref, watch } from 'vue';
|
import { Ref, computed, nextTick, ref, watch } from 'vue';
|
||||||
import { useStore } from '../../store';
|
import { useStore } from '../../store';
|
||||||
import { IStock } from '../../types';
|
|
||||||
|
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const emit = defineEmits(['listItemClick']);
|
const emit = defineEmits(['listItemClick']);
|
||||||
@@ -42,10 +58,6 @@ const onListItemClick = (index: number) => {
|
|||||||
emit('listItemClick', index);
|
emit('listItemClick', index);
|
||||||
};
|
};
|
||||||
|
|
||||||
const stockImageError = (e: Event, stock: IStock) => {
|
|
||||||
(e.target as HTMLImageElement).src = `images/${stock.useType}-unknown.png`;
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
computed(() => store.chosenStockListIndex),
|
computed(() => store.chosenStockListIndex),
|
||||||
(index) => {
|
(index) => {
|
||||||
@@ -53,8 +65,12 @@ watch(
|
|||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
(thumbnailsRef.value as HTMLElement)
|
(thumbnailsRef.value as HTMLElement)
|
||||||
.querySelector(`div:nth-child(${index + 1})`)
|
.querySelector(`li:nth-child(${index + 1})`)
|
||||||
?.scrollIntoView({ block: 'nearest', inline: 'start', behavior: 'smooth' });
|
?.scrollIntoView({
|
||||||
|
block: 'nearest',
|
||||||
|
inline: 'start',
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -67,7 +83,7 @@ const onDragStart = (vehicleIndex: number) => {
|
|||||||
const onDrop = (e: DragEvent, vehicleIndex: number) => {
|
const onDrop = (e: DragEvent, vehicleIndex: number) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
let targetEl = thumbnailsRef.value.querySelector(`div:nth-child(${vehicleIndex + 1})`);
|
let targetEl = thumbnailsRef.value.querySelector(`li:nth-child(${vehicleIndex + 1})`);
|
||||||
|
|
||||||
if (!targetEl && draggedIndex.value != -1) return;
|
if (!targetEl && draggedIndex.value != -1) return;
|
||||||
|
|
||||||
@@ -81,45 +97,134 @@ const onDrop = (e: DragEvent, vehicleIndex: number) => {
|
|||||||
const allowDrop = (e: DragEvent) => {
|
const allowDrop = (e: DragEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getVehicleThumbnails = (vehicleString: string) => {
|
||||||
|
const [vehicleName, vehicleCargo] = vehicleString.split(':');
|
||||||
|
|
||||||
|
const thumbnails: { src: string; fallbackSrc: string }[] = [];
|
||||||
|
|
||||||
|
// Generowanie członów EN57
|
||||||
|
if (vehicleName.startsWith('EN57')) {
|
||||||
|
thumbnails.push(
|
||||||
|
{ src: vehicleName + 'ra', fallbackSrc: 'unknown_ezt-ra' },
|
||||||
|
{ src: vehicleName + 's', fallbackSrc: 'unknown_ezt-s' },
|
||||||
|
{ src: vehicleName + 'rb', fallbackSrc: 'unknown_ezt-rb' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generowanie członów EN71
|
||||||
|
else if (vehicleName.startsWith('EN71')) {
|
||||||
|
thumbnails.push(
|
||||||
|
{ src: vehicleName + 'ra', fallbackSrc: 'unknown_ezt-ra' },
|
||||||
|
{ src: vehicleName + 'sa', fallbackSrc: 'unknown_ezt-sa' },
|
||||||
|
{ src: vehicleName + 'sb', fallbackSrc: 'unknown_ezt-sb' },
|
||||||
|
{ src: vehicleName + 'rb', fallbackSrc: 'unknown_ezt-rb' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generowanie pojazdów i członów 2EN57
|
||||||
|
else if (vehicleString.startsWith('2EN57')) {
|
||||||
|
const [firstVehicleNumber, secondVehicleNumber] = vehicleString
|
||||||
|
.replace('2EN57-', '')
|
||||||
|
.split('+');
|
||||||
|
|
||||||
|
thumbnails.push(
|
||||||
|
{ src: `EN57-${firstVehicleNumber}ra`, fallbackSrc: 'unknown_ezt-ra' },
|
||||||
|
{ src: `EN57-${firstVehicleNumber}s`, fallbackSrc: 'unknown_ezt-s' },
|
||||||
|
{ src: `EN57-${firstVehicleNumber}rb`, fallbackSrc: 'unknown_ezt-rb' },
|
||||||
|
{ src: `EN57-${secondVehicleNumber}ra`, fallbackSrc: 'unknown_ezt-ra' },
|
||||||
|
{ src: `EN57-${secondVehicleNumber}s`, fallbackSrc: 'unknown_ezt-s' },
|
||||||
|
{ src: `EN57-${secondVehicleNumber}rb`, fallbackSrc: 'unknown_ezt-rb' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generowanie członów Gor77
|
||||||
|
else if (vehicleString.startsWith('Gor77')) {
|
||||||
|
thumbnails.push(
|
||||||
|
{ src: vehicleName + '-A', fallbackSrc: 'unknown_Gor77-A' },
|
||||||
|
{ src: vehicleName + '-B', fallbackSrc: 'unknown_Gor77-B' },
|
||||||
|
{ src: vehicleName + '-C', fallbackSrc: 'unknown_Gor77-C' },
|
||||||
|
{ src: vehicleName + '-D', fallbackSrc: 'unknown_Gor77-D' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generowanie członów ET41
|
||||||
|
else if (vehicleString.startsWith('ET41')) {
|
||||||
|
thumbnails.push(
|
||||||
|
{ src: vehicleName + '-A', fallbackSrc: 'unknown_ET41-A' },
|
||||||
|
{ src: vehicleName + '-B', fallbackSrc: 'unknown_ET41-B' }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generowanie pozostałych pojazdów
|
||||||
|
else {
|
||||||
|
let fallbackVehicleImage = 'unknown_cargo';
|
||||||
|
|
||||||
|
if (/^(EP|EU)/.test(vehicleName)) fallbackVehicleImage = 'unknown_train';
|
||||||
|
else if (/^(SM42)/.test(vehicleName)) fallbackVehicleImage = 'unknown_SM42';
|
||||||
|
else if (/(\d{3}a|(Bau|Gor)\d{2}|304C)_/.test(vehicleName))
|
||||||
|
fallbackVehicleImage = 'unknown_passenger';
|
||||||
|
|
||||||
|
thumbnails.push({ src: vehicleName, fallbackSrc: fallbackVehicleImage });
|
||||||
|
}
|
||||||
|
|
||||||
|
return thumbnails;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.stock_thumbnails {
|
@import '../../styles/global.scss';
|
||||||
display: flex;
|
|
||||||
|
.stock-thumbnails {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background-color: #353a57;
|
background-color: #353a57;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
> div {
|
ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
cursor: pointer;
|
min-height: 110px;
|
||||||
min-height: 100px;
|
}
|
||||||
|
|
||||||
&[data-selected='true'] {
|
.thumbnail-item {
|
||||||
background-color: rebeccapurple;
|
cursor: pointer;
|
||||||
}
|
font-size: 0.85em;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
> span {
|
user-select: none;
|
||||||
display: flex;
|
-moz-user-select: none;
|
||||||
flex-direction: column;
|
-webkit-user-select: none;
|
||||||
gap: 0.5em;
|
|
||||||
padding: 0.5em 0;
|
|
||||||
|
|
||||||
text-align: center;
|
&[data-selected='true'] {
|
||||||
|
background-color: rebeccapurple;
|
||||||
|
}
|
||||||
|
|
||||||
font-size: 0.85em;
|
&[data-sponsor-only='true'] > b {
|
||||||
user-select: none;
|
color: $sponsorColor;
|
||||||
-moz-user-select: none;
|
}
|
||||||
}
|
|
||||||
|
&[data-team-only='true'] > b {
|
||||||
|
color: $teamColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
max-height: 60px;
|
max-height: 70px;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.supporter {
|
.stock-text {
|
||||||
color: salmon;
|
font-weight: bold;
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail-item > span {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-end;
|
||||||
|
cursor: crosshair;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"EU06": [650000, 2000000],
|
||||||
|
"EU07": [650000, 2000000],
|
||||||
|
"4E": [650000, 2000000],
|
||||||
|
"EU07E": [650000, 2000000],
|
||||||
|
"EP07": [650000, 650000],
|
||||||
|
"EP08": [650000, 650000],
|
||||||
|
"EP09": [800000, 800000],
|
||||||
|
"ET41": [700000, 4000000],
|
||||||
|
"SM42": [2400000, 2400000]
|
||||||
|
}
|
||||||
@@ -1,38 +1,64 @@
|
|||||||
{
|
{
|
||||||
"regionNumbers": {
|
"regionNumbers": {
|
||||||
"Warszawa": 1,
|
"Warszawa (1)": 1,
|
||||||
"Lublin": 2,
|
"Lublin (2)": 2,
|
||||||
"Kraków": 3,
|
"Kraków (3)": 3,
|
||||||
"Sosnowiec": 4,
|
"Sosnowiec (4)": 4,
|
||||||
"Gdańsk": 5,
|
"Gdańsk (5)": 5,
|
||||||
"Wrocław": 6,
|
"Wrocław (6)": 6,
|
||||||
"Poznań": 7,
|
"Poznań (7)": 7,
|
||||||
"Szczecin": 8,
|
"Szczecin (8)": 8,
|
||||||
"Rezerwa": 9
|
"Rezerwa (9)": 9
|
||||||
},
|
},
|
||||||
"sameRegions": {
|
"sameRegions": {
|
||||||
"Losowy": [
|
"Losowy": [
|
||||||
10, 11, 19, 91, 93, 97, 99, 20, 22, 29, 30, 33, 39, 40, 44, 49, 94, 50, 55, 59, 90, 95, 96, 66, 60, 69, 77, 70,
|
10, 11, 19, 91, 93, 97, 99, 20, 22, 29, 30, 33, 39, 40, 44, 49, 94, 50, 55, 59, 90, 95, 96,
|
||||||
79, 88, 80, 89, 92, 98
|
66, 60, 69, 77, 70, 79, 88, 80, 89, 92, 98
|
||||||
],
|
],
|
||||||
"Warszawa": [10, 11, 19, 91, 93, 97, 99],
|
"Warszawa (1)": [10, 11, 19, 91, 93, 97, 99],
|
||||||
"Lublin": [20, 22, 29],
|
"Lublin (2)": [20, 22, 29],
|
||||||
"Kraków": [30, 33, 39],
|
"Kraków (3)": [30, 33, 39],
|
||||||
"Sosnowiec": [40, 44, 49, 94],
|
"Sosnowiec (4)": [40, 44, 49, 94],
|
||||||
"Gdańsk": [50, 55, 59, 90, 95, 96],
|
"Gdańsk (5)": [50, 55, 59, 90, 95, 96],
|
||||||
"Wrocław": [66, 60, 69],
|
"Wrocław (6)": [66, 60, 69],
|
||||||
"Poznań": [77, 70, 79],
|
"Poznań (7)": [77, 70, 79],
|
||||||
"Szczecin": [88, 80],
|
"Szczecin (8)": [88, 80],
|
||||||
"Rezerwa": [89, 92, 98]
|
"Rezerwa (9)": [89, 92, 98]
|
||||||
},
|
},
|
||||||
"categories": {
|
"categoriesRules": {
|
||||||
"EI": "2:00-99:2",
|
"EI": [null, "00", "99"],
|
||||||
"MP/RP": "2:050-169:3",
|
"EC": [null, "000", "049"],
|
||||||
"RO": "2:200-999:3",
|
"EN": [null, "000", "049"],
|
||||||
"PW": "2:6;3:0-899:3",
|
|
||||||
"TM": "2:4;3:0-899:3",
|
"RO": [null, "200", "999"],
|
||||||
"TK": "2:3;3:0-899:3",
|
"RP": [null, "050", "169"],
|
||||||
"LT": "2:5;3:0-899:3"
|
"RM": [null, "200", "999"],
|
||||||
|
"RA": [null, "200", "999"],
|
||||||
|
|
||||||
|
"MO": [null, "200", "999"],
|
||||||
|
"MP": [null, "050", "169"],
|
||||||
|
"MM": [null, "001", "049"],
|
||||||
|
"MH": [null, "170", "199"],
|
||||||
|
|
||||||
|
"PW": ["6", "000", "899"],
|
||||||
|
"PX": ["6", "000", "899"],
|
||||||
|
|
||||||
|
"TM": ["4", "000", "899"],
|
||||||
|
"TN": ["3", "000", "899"],
|
||||||
|
"TK": ["3", "000", "899"],
|
||||||
|
"TD": ["2", "000", "899"],
|
||||||
|
"TG": ["1", "000", "899"],
|
||||||
|
"TR": ["1", "000", "899"],
|
||||||
|
"TC": ["0", "000", "899"],
|
||||||
|
"TS": ["5", "000", "899"],
|
||||||
|
"TH": ["5", "000", "899"],
|
||||||
|
|
||||||
|
"LT": ["5", "000", "899"],
|
||||||
|
"LP": ["6", "000", "899"],
|
||||||
|
"LS": ["9", "000", "899"],
|
||||||
|
"LZ": ["9", "000", "899"],
|
||||||
|
|
||||||
|
"ZN": ["9", "000", "899"],
|
||||||
|
"ZU": ["9", "000", "899"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +1,102 @@
|
|||||||
{
|
{
|
||||||
"EU07": {
|
"EU07": {
|
||||||
"passenger": {
|
"passenger": {
|
||||||
"650": 125
|
"650000": 125
|
||||||
},
|
},
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"2000": 70
|
"2000000": 70
|
||||||
}
|
},
|
||||||
|
"none": 110
|
||||||
|
},
|
||||||
|
"4E": {
|
||||||
|
"passenger": {
|
||||||
|
"650000": 125
|
||||||
|
},
|
||||||
|
"cargo": {
|
||||||
|
"2000000": 70
|
||||||
|
},
|
||||||
|
"none": 110
|
||||||
},
|
},
|
||||||
"EU07E": {
|
"EU07E": {
|
||||||
"passenger": {
|
"passenger": {
|
||||||
"650": 125
|
"650000": 125
|
||||||
},
|
},
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"2000": 70
|
"2000000": 70
|
||||||
}
|
},
|
||||||
|
"none": 110
|
||||||
},
|
},
|
||||||
"EP07": {
|
"EP07": {
|
||||||
"passenger": {
|
"passenger": {
|
||||||
"650": 125
|
"650000": 125
|
||||||
},
|
},
|
||||||
"cargo": null
|
"cargo": null,
|
||||||
|
"none": 110
|
||||||
},
|
},
|
||||||
"EP08": {
|
"EP08": {
|
||||||
"passenger": {
|
"passenger": {
|
||||||
"650": 140
|
"650000": 140
|
||||||
},
|
},
|
||||||
"cargo": null
|
"cargo": null,
|
||||||
|
"none": 110
|
||||||
|
},
|
||||||
|
"EP09": {
|
||||||
|
"passenger": {
|
||||||
|
"650000": 160
|
||||||
|
},
|
||||||
|
"cargo": null,
|
||||||
|
"none": 160
|
||||||
|
},
|
||||||
|
"ET22": {
|
||||||
|
"passenger": {
|
||||||
|
"650000": 125
|
||||||
|
},
|
||||||
|
"cargo": {
|
||||||
|
"1200000": 100,
|
||||||
|
"3100000": 70
|
||||||
|
},
|
||||||
|
"none": 125
|
||||||
|
},
|
||||||
|
"201E": {
|
||||||
|
"passenger": {
|
||||||
|
"650000": 125
|
||||||
|
},
|
||||||
|
"cargo": {
|
||||||
|
"1200000": 100,
|
||||||
|
"3100000": 70
|
||||||
|
},
|
||||||
|
"none": 125
|
||||||
},
|
},
|
||||||
"ET41": {
|
"ET41": {
|
||||||
"passenger": {
|
"passenger": {
|
||||||
"700": 125
|
"700000": 125
|
||||||
},
|
},
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"4000": 70
|
"4000000": 70
|
||||||
}
|
},
|
||||||
|
"none": 110
|
||||||
},
|
},
|
||||||
"SM42": {
|
"SM42": {
|
||||||
"passenger": {
|
"passenger": {
|
||||||
"95": 90,
|
"95000": 90,
|
||||||
"200": 80,
|
"200000": 80,
|
||||||
"300": 70,
|
"300000": 70,
|
||||||
"450": 60,
|
"450000": 60,
|
||||||
"750": 50,
|
"750000": 50,
|
||||||
"1130": 40,
|
"1130000": 40,
|
||||||
"1720": 30,
|
"1720000": 30,
|
||||||
"2400": 20
|
"2400000": 20
|
||||||
},
|
},
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"95": 90,
|
"95000": 90,
|
||||||
"200": 80,
|
"200000": 80,
|
||||||
"300": 70,
|
"300000": 70,
|
||||||
"450": 60,
|
"450000": 60,
|
||||||
"750": 50,
|
"750000": 50,
|
||||||
"1130": 40,
|
"1130000": 40,
|
||||||
"1720": 30,
|
"1720000": 30,
|
||||||
"2400": 20
|
"2400000": 20
|
||||||
}
|
},
|
||||||
|
"none": 90
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"cargo": {
|
||||||
|
"kontenery": ["627Z:all", "412Z:all"],
|
||||||
|
"chłodnia": ["202Lc:all"],
|
||||||
|
"drobnica": ["426S:all", "208Kf:all", "401Ka_PKP_Gags:all", "401Ka_PKPC_Gags:all"],
|
||||||
|
"węgiel": ["412W:coal_01", "413S:coal_413S", "429W:coal_01", "401Zb:coal_02"],
|
||||||
|
"ruda": ["412W:ore_01", "401Zl:ore_35", "429W:ore_01"],
|
||||||
|
"piasek": [
|
||||||
|
"412W:sand_01",
|
||||||
|
"412W:sand_02",
|
||||||
|
"413S:sand_413S",
|
||||||
|
"401Zl:sand_30",
|
||||||
|
"429W:sand_01",
|
||||||
|
"429W:sand_02",
|
||||||
|
"401Zb:sand_03",
|
||||||
|
"418Va:sand_418V",
|
||||||
|
"418Vb:sand_418V"
|
||||||
|
],
|
||||||
|
"kreda": ["413S:chalk_413S"],
|
||||||
|
"kamień": [
|
||||||
|
"412W:stone_01",
|
||||||
|
"412W:stone_50",
|
||||||
|
"401Zl:stone_25",
|
||||||
|
"429W:stone_01",
|
||||||
|
"401Zb:stone_02",
|
||||||
|
"418Va:stone_418V",
|
||||||
|
"418Vb:stone_418V"
|
||||||
|
],
|
||||||
|
"złom": ["412W:scrap_01", "412W:scrap_02", "429W:scrap_01", "429W:scrap_02"],
|
||||||
|
"paliwo": ["29R_CTLL:all", "29R_PKP:all", "445Rb:all"],
|
||||||
|
"melasa": ["29R_PLPOL:all"],
|
||||||
|
"żwir": ["441V"],
|
||||||
|
"koła": ["424Z:wheels_01"],
|
||||||
|
"drewno": ["424Z:woods_01", "424Z:woods_02"],
|
||||||
|
"szyny": ["424Z:rails_01"],
|
||||||
|
"kable": ["424Z:cables_01", "24Z:cables_Ks", "401Ze:cables_02"],
|
||||||
|
"kruszywo": ["59WS:all"],
|
||||||
|
"techniczne": ["209c", "304Ca", "102a_PKPE", "401Ka_PKP_XGa:all"],
|
||||||
|
"poczta": ["211K:all"],
|
||||||
|
"cement": [
|
||||||
|
"408S:cement_4",
|
||||||
|
"206S_CEMET:cement_3",
|
||||||
|
"206S_SPEED:cement_3",
|
||||||
|
"220S_CEMET:cement_3"
|
||||||
|
],
|
||||||
|
"wapno": ["408S:lime_4", "206S_CEMET:lime_3", "206S_SPEED:lime_3", "220S_CEMET:lime_3"],
|
||||||
|
"soda": ["408S:soda_4", "206S_CEMET:soda_3", "206S_SPEED:soda_3", "220S_CEMET:soda_3"],
|
||||||
|
"pszenica": ["206Sh_PKP_Ugpps:wheat_3", "206Sh_PKPC_Ugpps:wheat_3"],
|
||||||
|
"kukurydza": ["206Sh_PKP_Ugpps:corn_3", "206Sh_PKPC_Ugpps:corn_3"],
|
||||||
|
"pasza": ["206Sh_PKP_Ugpps:forage_3", "206Sh_PKPC_Ugpps:forage_3"],
|
||||||
|
"pojazdy": ["426Z:tank_01", "426Z:truck_01", "426Z:vehicles_01"],
|
||||||
|
"karbid": ["421S:carbide_01"],
|
||||||
|
"wrażliwe": ["425S:all", "421S:carbide_01"],
|
||||||
|
"stal": ["401Ze:steel_01", "401Ze:steel_02"],
|
||||||
|
"gaz": ["WB117:all"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
{
|
||||||
|
"EIC 45_71006_71007 Sprewa": "EP08-006v2;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 15100_15101 Słowiniec": "EP08-006v2;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 15103 Podlasiak": "EP07-1039;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 15106_15107 Brda": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_01",
|
||||||
|
"IC 15155_15154 Lazur": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 16150_16151 Śnieżka": "EP08-006v2;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 17100_17101 Zamenhof": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 17102_17103 Zielonogórzanin": "EP08-006v2;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 17104_17105 Warta": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 18100_18101 Gałczyński": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 18102_18103 Podlasiak": "EP08-006v2;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 18104_18105 Rybak": "EP07-1043;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 18106_18107 Mewa": "EP08-006v2;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 18112_18113 Noteć": "EP08-006v2;111a_PKPIC_B9nopuvz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 18153_18152 Parsęta": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 19100_19101 Łodzianin": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_01",
|
||||||
|
"IC 20100_20101 Hetman": "EP08-006v2;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 21100_21101 Chełmianin": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 22100_22101 Hetman": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 23100_23101 Jagiełło": "EP07-544;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 24100_24101 Sztygar": "EP07-1009;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 24105 Morcinek": "EP07-1025;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_01",
|
||||||
|
"IC 25100_25101 Kochanowski": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 26100_26101 Hetman": "EP08-006v2;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 26102_26103 Bolko": "EP07-1054;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 26104_26105 Morcinek": "EP07-1039;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 27100_27101 Lubuszanin": "EP08-006v2;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 31104_31105 Witos": "EP07-356;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 31106_31107 San": "EP07-1056;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 31110_31111 Marszałek Piłsudski": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 32100_32101 Jagiełło": "EP07-1054;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 35102_35103 Kochanowski": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 35150_35151 Halny": "EP07-391;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 35202_35203 Przebojowy pociąg RMF FM": "EP08-006v2;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 36104_36105 Kossak": "EP07-1043;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 38100_38101 Górski": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 38102_38103 Osterwa": "EP07-1025;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 38104_38105 Mehoffer": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 38172_38173 Przemyślanin": "EP08-006v2;110a_PKPIC_Bcdu_01;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 38192_38193 Podhalanin": "EP07-1043;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02",
|
||||||
|
"IC 42100_42101 Sztygar": "EP07-544;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 42104 Morcinek": "EP07-1002;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 48150_48151 Gwarek": "EP07-384;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 50104_50105 Niegocin": "EP07-391;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 51100_51101 Słowiniec": "EP08-006v2;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 51102 Podlasiak": "EP07-335;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 51106_51107 Brda": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 51155_51154 Lazur": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 52100_52101 Kochanowski": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01\n",
|
||||||
|
"IC 53102_53103 Kochanowski": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 53150_53151 Halny": "EP07-1043;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 55104_55105 Niegocin": "EP07-1031;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 56102_56103 Mamry": "EP07-1043;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 56104_56105 Jeziorak": "EP07-1038;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 57100_57101 Ukiel": "EP07-1048;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 57102_57103 Drwęca": "EP07-1043;159a_PKPIC_B9mnopuz_01;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02\n",
|
||||||
|
"IC 57104_57105 Bachus": "EP07-174;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 57106_57107 Lednica": "EP07-1025;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 57108_57109 Stoczniowiec": "EP07-335;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 58100_58101 Albatros": "EP07-1039;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 58102_58103 Żuławy": "EP07-1038;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 58104_58105 Bryza": "EP07-1009;111a_PKPIC_B9nopuvz_02;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01\n",
|
||||||
|
"IC 58106_58107 Gryf": "EP07-1009;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 58108_58109 Stańczyk": "EP07-444;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 60101 Mehoffer": "EP07-1025;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 60151 Śnieżka": "SM42-506;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 61150_61151 Śnieżka": "EP08-006v2;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 62100_62101 Hetman": "EP08-006;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 62102_62103 Bolko": "EP07-391;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 62104_62105 Morcinek": "EP07-1043;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 63104_63105 Kossak": "EU07-015;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 65102_65103 Mamry": "EP07-1031;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 65104_65105 Jeziorak": "EP07-1043;159a_PKPIC_B9mnopuz_01;154a_PKPIC_B10mnouz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 66100 Mehoffer": "EP07-1025;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 66150 Śnieżka": "SM42-506;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 68100_68101 Bosman": "EP07-1002;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 68102_68103 Szkuner": "EP07-1056;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 68104_68105 Swarożyc": "EP07-1025;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 71100_71101 Zamenhof": "EP08-006v2;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 71102_71103 Zielonogórzanin": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 71104_71105 Warta": "EP08-006v2;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 72100_72101 Lubuszanin": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 75100_75101 Ukiel": "EP07-1043;159a_PKPIC_B9mnopuz_01;154a_PKPIC_B10mnouz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 75102_75103 Drwęca": "EP07-1025;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;154a_PKPIC_B10mnouz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"IC 75104_75105 Bachus": "EP07-335;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 75106_75107 Lednica": "EP07-1031;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 75108_75109 Stoczniowiec": "EP07-1025;111a_PKPIC_B9nopuvz_02;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 78101 Gałczyński": "SM42-506;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 78103 Lubuszanin": "SM42-506;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 78103 Mewa": "SM42-506;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 80150 Rowokół": "EP07-1038;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 81100_81101 Gałczyński": "EP08-006v2;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 81102_81103 Podlasiak": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 81104_81105 Rybak": "EP07-480;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 81106_81107 Mewa": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 81112_81113 Noteć": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 81152_81153 Parsęta": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 83100_83101 Górski": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 83102_83103 Osterwa": "EP07-444;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 83104_83105 Mehoffer": "EP08-006v2;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 83192_83193 Podhalanin": "EP07-1056;110a_PKPIC_Bcdu_01;110a_PKPIC_Bcdu_02;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 84150_84151 Gwarek": "EP07-1043;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 85100_85101 Albatros": "EP07-1038;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 85102_85103 Żuławy": "EP07-335;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;154a_PKPIC_B10mnouz_01",
|
||||||
|
"IC 85104_85105 Bryza": "EP07-480;159a_PKPIC_B9mnopuz_01;154a_PKPIC_B10mnouz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 85106_85107 Gryf": "EP07-444;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 85108_85109 Stańczyk": "EU07-077;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 86100_86101 Bosman": "EP07-544;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 86102_86103 Szkuner": "EP07-174;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;113a_PKPIC_WRbd_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 86104_86105 Swarożyc": "EP07-1056;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 87100 Gałczyński": "SM42-506;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 87102 Lubuszanin": "SM42-506;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01",
|
||||||
|
"IC 87172_87173 Przemyślanin": "EP07-1054;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"IC 88151 Rowokół": "EP07-444;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;113a_PKPIC_WRbd_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"IC 91100_91101 Lodzianin": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"TLK 10100_10101 Żubr": "EP07-1009;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 10110_10111 Żubr": "EP07-355;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 12110_12111 Nida": "EP07-444;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 301_43004_43005 Galicja (PKPIC) R 301 Galicja (ČD) ": "EP07-480;112a_PKPIC_A9ou_01;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01",
|
||||||
|
"TLK 310_24000_24001 Roztocze (PKPIC) R 310 Roztocze (ČD)": "EP07-480;Bau84_CD_B249_01;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01",
|
||||||
|
"TLK 31100_31101 Malinowski": "EP07-1025;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 31102_31103 Hańcza": "EP07-480;612a_PKPIC_BD4osuv_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;612a_PKPIC_BD4osuv_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 31106_31107 San": "EP07-444;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 31110_31111 Wit Stwosz": "EP08-006;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;158a_PKPIC_A9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 31150_31151 Karłowicz": "EP07-391;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 311_42000_42001 Roztocze (PKPIC) R 311 Roztocze (ČD) ": "EP07-480;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;Bau84_CD_B249_01",
|
||||||
|
"TLK 33100_33101 Malinowski": "EU07-324;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 33104_33105 Łukasiewicz": "EP07-544;112a_PKPIC_A9ou_01;Bau84_CD_B249_01;Bau84_CD_B249_01;Bau84_CD_B249_01",
|
||||||
|
"TLK 35100_35101 Małopolska": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 35106_35107 Artus": "EP07-444;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01\n",
|
||||||
|
"TLK 35106_35107 ArtusV2": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01\n",
|
||||||
|
"TLK 35170_35171 Karpaty": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 35190_35191 Korsarz": "SM42-506;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 36102_36103 Sudety": "SM42-506;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 36170_36171 Pogórze": "EP07-1025;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;110a_PKPIC_Bcdu_02\n",
|
||||||
|
"TLK 37100_37101 Pułaski": "EU07-334;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01",
|
||||||
|
"TLK 37102_37103 Wybicki": "EP07-444;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 37170_37171 Pogórze": "EP07-544;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 38106_38107 Zefir": "EU07-334;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 38154_38155 Lubomirski": "EP08-006;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01",
|
||||||
|
"TLK 38170_38171 Ustronie": "EP07-444;110a_PKPIC_Bcdu_01;110a_PKPIC_Bcdu_02;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 38190_38191 Bursztyn": "EP07-1031;110a_PKPIC_Bcdu_02;112a_PKPIC_A9ou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 400_84070_84071 Wolin (PKPIC) R 400 Wolin (ČD)": "EU07-334;110a_PKPIC_Bcdu_02;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;612a_PKPIC_BD4osuv_01;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01",
|
||||||
|
"TLK 40160_40161 Pirat": "EP07-544;612a_PKPIC_BD4osuv_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 401_48070_48071 Wolin (PKPIC) R 401 Wolin (ČD) ": "EP07-544;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;612a_PKPIC_BD4osuv_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 402_54070_54071 Wydmy (PKPIC) R 402 Wydmy (ČD)": "EP07-1009;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;612a_PKPIC_BD4osuv_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 403_45070_45071 Wydmy (PKPIC) R 403 Wydmy (ČD) ": "EP07-1009;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;612a_PKPIC_BD4osuv_01;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01",
|
||||||
|
"TLK 405_48072_48073 Pirat (PKPIC) R 405 Pirat (ČD) ": "EP07-391;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;612a_PKPIC_BD4osuv_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;Bau84_CD_B10nou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 41100_41101 Chemik": "EP07-355;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01\n",
|
||||||
|
"TLK 41102_41103 Wysocki": "EP07-444;111a_PKPIC_B9nopuvz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_01",
|
||||||
|
"TLK 41104_41105 Kmicic": "EP07-1056;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 44160_44161 Pirat": "EU07-334;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;612a_PKPIC_BD4osuv_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 45100_45101 Doker ": "EP07-1056;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 45150_45151 Halny ": "EP07-1054;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 45170_45171 Rozewie ": "EP07-391;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 45190_45191 Rozewie ": "EP07-544;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 47100_47101 Spodek ": "EP07-1038;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 50150_50151 Gardno": "SM42-506;110a_PKPIC_Bcdu_02;Bau84_CD_B249_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01",
|
||||||
|
"TLK 50160_50161 Korsarz": "EP07-1038;110a_PKPIC_Bcdu_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 50170_50171 Mierzeja": "SM42-506;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 51104_51105 Biebrza": "EP07-1025;111a_PKPIC_Bnouz_01;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_Bnouz_01",
|
||||||
|
"TLK 51112_51113 Kociewie": "EP07-1002;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01",
|
||||||
|
"TLK 51150_51151 Delfin": "EP07-335;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01\n",
|
||||||
|
"TLK 51152_51153 Wybrzeże": "EP07-444;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 53100_53101 Małopolska": "EU07-545;EU07-015;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;Bau84_PKPIC_B10nou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 53104_53105 Lubomirski": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 53106_53107 Artus V2": "EP07-335;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 53170_53171 Karpaty": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 53190_53191 Korsarz": "EP07-1054;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 54100_54101 Doker": "EP07-1038;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 54150_54151 Halny": "EP07-174;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 54170_54171 Rozewie": "EP07-1025;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 55154 Wydmy": "EU07-545;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 55160_55161 Korsarz": "EU07-545;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 55162_55163 Rozewie": "SM42-506;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;612a_PKPIC_BD4osuv_01",
|
||||||
|
"TLK 55170_55171 Mierzeja": "SM42-506;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 56100_56101 Kormoran": "EP07-355;EP07-1038;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 58104_58105 Bryza": "EP07-1038;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 58110_58111 Bory Tucholskie": "SM42-506;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01",
|
||||||
|
"TLK 64160_64161 Wolin": "EU07-015;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;612a_PKPIC_BD4osuv_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 65100_65101 Kormoran": "EP07-444;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 66166_66167 Rozewie": "EP07-391;612a_PKPIC_BD4osuv_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B249_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 71106_71107 Konopnicka": "EP08-006v2;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B9nopuvz_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 73100_73101 Pułaski": "EP07-1054;Bau84_CD_B249_01;Bau84_CD_B249_01;Bau84_CD_B249_01",
|
||||||
|
"TLK 73102_73103 Wybicki V2": "EP07-1056;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 73102_73103 Wybicki": "EP07-1025;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;Bau84_PKPIC_B10nou_01",
|
||||||
|
"TLK 73170_73171 Pogórze": "EP07-444;110a_PKPIC_Bcdu_02;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02",
|
||||||
|
"TLK 74100_74101 Spodek": "EP07-544;Bau84_CD_B249_01;Bau84_CD_B249_01;Bau84_CD_B249_01",
|
||||||
|
"TLK 76106_76107 Konopnicka": "SM42-506;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 81114_81115 Pobrzeże": "EP08-006;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B9nopuvz_02;Bau84_PKPIC_B10nou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 81150_81151 Słupia": "EU07-015;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 81170_81171 Uznam": "EP07-480;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 82100_82101 Staszic": "EP08-006v2;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 82102_82103 Wyczółkowski": "EP07-391;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 82104_82105 Zamoyski": "EP07-480;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 82170_82171 Mierzeja": "EP07-1009;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 83100_83101 Górski": "EP08-006v2;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;158a_PKPIC_A9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01;159a_PKPIC_B9mnopuz_01",
|
||||||
|
"TLK 83106_83107 Zefir": "EP07-1054;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 83154_83155 Lubomirski": "EP08-006;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;159a_PKPIC_B9mnopuz_01;111a_PKPIC_B10ou_01;Bau84_PKPIC_B10nou_01;Bau84_PKPIC_B10nou_01",
|
||||||
|
"TLK 83170_83171 Ustronie V2": "EP07-391;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;159a_PKPIC_B9mnopuz_01;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 83190_83191 Bursztyn": "EP07-1031;110a_PKPIC_Bcdu_02;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;Bau84_CD_B10nou_01;112a_PKPIC_A9ou_01;110a_PKPIC_Bcdu_02",
|
||||||
|
"TLK 85104_85105 Bryza": "EP07-1038;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 86116_86117 Jamno": "EP07-1025;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01",
|
||||||
|
"TLK 88160_88161 Ustronie": "EU07-015;110a_PKPIC_Bcdu_02;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 91130_91131 Zosia": "EP07-544;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"TLK 91132_91133 Korczak": "EP07-1002;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B9nopuvz_02;159a_PKPIC_B9mnopuz_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;112a_PKPIC_A9ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01;111a_PKPIC_B10ou_01",
|
||||||
|
"iR 11121 Żubr": "EN57-1953",
|
||||||
|
"iR 11130 Żubr": "EN57-1953",
|
||||||
|
"iR 12121 Bystrzyca": "EN71-028",
|
||||||
|
"iR 12125 Cisy": "EN71-028",
|
||||||
|
"iR 13126 Jan Matejko": "EP07-370;111a_PKP_Bdnu_02;111a_PKP_Bdnu_02;111a_PKP_Bdnu_02;111a_PKP_Bdnu_02;111a_PKP_Bdnu_02;111a_PKP_Bdnu_02",
|
||||||
|
"iR 31130 Semafor": "EN57-1953",
|
||||||
|
"iR 36120 Galicja V2": "EN57-1914",
|
||||||
|
"iR 36120 Galicja": "EN71-010",
|
||||||
|
"iR 36122 Łużyce": "EN57-1747",
|
||||||
|
"iR 40110 Torunianin": "EN71-028",
|
||||||
|
"iR 43127_6 Giewont": "EN57-1542",
|
||||||
|
"iR 43421 Orlik": "EN57-1542",
|
||||||
|
"iR 46121 Spodek": "EN57-1542",
|
||||||
|
"iR 46123 Ostrów Tumski": "EN57-1542",
|
||||||
|
"iR 46125 Oleńka": "EN57-1542",
|
||||||
|
"iR 46140 Szyndzielnia": "EN57-1542",
|
||||||
|
"iR 46142 Szyndzielnia": "EN57-1542",
|
||||||
|
"iR 48102 Pirania": "EP07-338;111a_PRREG_B10_01;112a_PKP_A9nou_01;111a_PRREG_B10_01;112a_PKP_A9nou_01",
|
||||||
|
"iR 51110 Flisak": "EP07-338;111a_PKPIC_B9ouv_01;111a_PKP_Bdnu_02;111a_PKP_Bdnu_02;111a_PRREG_B10_01",
|
||||||
|
"iR 51204 Szczeliniec": "EP07-135;111a_PRREG_B10_01;111a_PRREG_B10_01",
|
||||||
|
"iR 56110 Sokoliki": "EP07-424;111a_PRREG_B10_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_A9ou_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_A9ou_01",
|
||||||
|
"iR 57110 Mamry": "EN57-1542",
|
||||||
|
"iR 57112 Drwęca": "EN57-1542",
|
||||||
|
"iR 57112 Niegocin": "SM42-329;Gor89_PKP_B16mnopux_04;Gor89_PKP_B16mnopux_04;Gor89_PKP_B16mnopux_04",
|
||||||
|
"iR 57120 Lednica": "EN57-1542",
|
||||||
|
"iR 61122 Prosna": "EN57-1542",
|
||||||
|
"iR 61126 Piast": "EP07-338;111a_PKPIC_B9ouv_01;120a_PRREG_B51p_02;120a_PRREG_B51p_02;111a_PRREG_B10_01",
|
||||||
|
"iR 61128 Rudawy": "EP07-242;111a_PRREG_A9ou_01;111a_PRREG_A9ou_01;111a_PKPIC_B9ouv_01;111a_PRREG_B10_01;111a_PRREG_B10_01;111a_PKP_Bnouz_01",
|
||||||
|
"iR 62120 Łysica": "EN57-1747",
|
||||||
|
"iR 63120 Łużyce": "EN57-1542",
|
||||||
|
"iR 64102 Szyndzielnia": "EN57-1542",
|
||||||
|
"iR 64122 Oleńka": "EN57-1542",
|
||||||
|
"iR 64124 Lompa": "EN57-1953",
|
||||||
|
"iR 64126 Spodek": "EN57-1542",
|
||||||
|
"iR 65114 Mamry": "EP07-1008;111a_PRREG_B10_01;112a_PKP_A9nou_01;111a_PKPIC_B9ouv_01;111a_PRREG_B10_01;111a_PRREG_B10_01",
|
||||||
|
"iR 70111 Rusałka": "EN57-1542",
|
||||||
|
"iR 71110 Wielkopolska": "EN57-1747",
|
||||||
|
"iR 71120 Ner": "EU07-475;111a_PKPIC_B9ouv_01;111a_PRREG_B10_01;111a_PRREG_B10_01;Gor89_PKP_B16mnopux_05",
|
||||||
|
"iR 72112 Koziołek": "EN57-1542",
|
||||||
|
"iR 75110 Drwęca": "EN57-1542",
|
||||||
|
"iR 75112 Niegocin": "EU07-222;Gor89_PKP_B16mnopux_05;Gor89_PKP_B16mnopux_05;Gor89_PKP_B16mnopux_05",
|
||||||
|
"iR 75116 Lednica": "EN57-1542",
|
||||||
|
"iR 77111 Rusałka": "EN57-1542",
|
||||||
|
"iR 78111 Delfin": "EN57-1542",
|
||||||
|
"iR 78113 Merkury": "EU07-368;Gor89_PKP_B16mnopux_05;Gor89_PKP_B16mnopux_05;Gor89_PKP_B16mnopux_05",
|
||||||
|
"iR 78115 Wały Chrobrego": "EN57-1542",
|
||||||
|
"iR 78117 Wilda": "EU07-475;Gor89_PKP_B16mnopux_05;Gor89_PKP_B16mnopux_05",
|
||||||
|
"iR 78510 Wolin": "EN57-1747",
|
||||||
|
"iR 81122 Portowiec": "EU07-222;111a_PKPIC_B9ouv_01;111a_Grafitti_1;111a_PRREG_B10_01;111a_PRREG_B10_01;111a_PRREG_A9ouy_01;111a_PKP_Brdu_01;111a_PKP_Brdu_01",
|
||||||
|
"iR 81522 Bosman": "EU07-222;111a_PKPIC_B9ouv_01;111a_PKPIC_B9ouv_01;111a_PRREG_B10_01;111a_PKP_Bdnu_02",
|
||||||
|
"iR 84522 Pirania": "EU07-222;120a_PRREG_B51p_02;111a_PRREG_B10_01;111a_PRREG_A9ou_01;111a_PKPIC_B9ouv_01",
|
||||||
|
"iR 87110 Merkury": "EU07-368;111a_PKPIC_B9ouv_01;111a_PRREG_B10_01;111a_PKPIC_B9ouv_01;111a_PKPIC_B9ouv_01",
|
||||||
|
"iR 87112 Wały Chrobrego": "EN57-1542",
|
||||||
|
"iR 87114 Delfin": "EN57-1542",
|
||||||
|
"iR 87116 Wilda": "SM42-302;Gor89_PKP_B16mnopux_01;Gor89_PKP_B16mnopux_01",
|
||||||
|
"iR 87512 Wolin": "2EN57-1542+1747",
|
||||||
|
"RE 14120 Chemik": "EN57-1747",
|
||||||
|
"RE 18122 Mewa": "EU07-222;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_02;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;112a_PKP_Adu_01;112a_PKP_Adu_01;112a_PKP_Adu_01",
|
||||||
|
"RE 26122 Bolko": "EU07-222;111a_PRREG_A9ou_02;112a_PKP_A9nou_01;111a_PRREG_A9ou_01;111a_PRREG_B10_01",
|
||||||
|
"RE 27120 Warta": "EU06-18;111a_PRREG_A9ou_02;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_02",
|
||||||
|
"RE 41120 Chemik": "EU07-222;111a_PKPIC_B9ouv_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_02",
|
||||||
|
"RE 62122 Bolko": "EP07-1055;Gor89_PKP_B16mnopux_04;111a_PRREG_A9ou_02;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01",
|
||||||
|
"RE 72110 Warta": "EU07-222;111a_PRREG_A9ou_02;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_02",
|
||||||
|
"RE 81120 Mewa": "EU07-222;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_02;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01;111a_PRREG_Bbnopuvz_01"
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
export const enum EVehicleUseType {
|
|
||||||
LOCO_ELECTRICAL = 'loco-e',
|
|
||||||
LOCO_DIESEL = "loco-s",
|
|
||||||
EMU = "loco-ezt",
|
|
||||||
DMU = "loco-szt",
|
|
||||||
|
|
||||||
CAR_PASSENGER = "car-passenger",
|
|
||||||
CAR_CARGO = "car-cargo"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const http = axios.create({
|
||||||
|
baseURL:
|
||||||
|
import.meta.env.VITE_API_DEV === '1' && import.meta.env.DEV
|
||||||
|
? 'http://localhost:3001'
|
||||||
|
: 'https://stacjownik.spythere.eu',
|
||||||
|
});
|
||||||
|
|
||||||
|
export default http;
|
||||||
@@ -1,33 +1,24 @@
|
|||||||
import localePL from './locales/pl.json';
|
import localePL from './locales/pl.json';
|
||||||
import localeEN from './locales/en.json';
|
import localeEN from './locales/en.json';
|
||||||
import { createI18n } from 'vue-i18n';
|
import { createI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
|
||||||
|
type LocaleMessageSchema = typeof localePL;
|
||||||
type LocaleMessageSchema = typeof localePL;
|
type LocaleKey = 'en' | 'pl';
|
||||||
type LocaleKey = 'en' | 'pl';
|
|
||||||
|
const locales: { [key in LocaleKey]: LocaleMessageSchema } = {
|
||||||
const locales: { [key in LocaleKey]: LocaleMessageSchema } = {
|
en: localeEN,
|
||||||
en: localeEN,
|
pl: localePL,
|
||||||
pl: localePL,
|
};
|
||||||
};
|
|
||||||
|
const locale =
|
||||||
const locale = window.localStorage.getItem('locale') || (/^pl\b/.test(navigator.language) ? 'pl' : 'en');
|
window.localStorage.getItem('locale') || (/^pl\b/.test(navigator.language) ? 'pl' : 'en');
|
||||||
|
|
||||||
const i18n = createI18n<[LocaleMessageSchema], 'en' | 'pl'>({
|
const i18n = createI18n<[LocaleMessageSchema], 'en' | 'pl'>({
|
||||||
locale,
|
locale,
|
||||||
fallbackLocale: 'pl',
|
fallbackLocale: 'pl',
|
||||||
legacy: false,
|
legacy: false,
|
||||||
globalInjection: true,
|
globalInjection: true,
|
||||||
messages: locales,
|
messages: locales,
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetchBackendTranslations() {
|
export default i18n;
|
||||||
const localeData = (await axios.get(`https://spythere.github.io/api/td2/data/locales.json`)).data;
|
|
||||||
|
|
||||||
i18n.global.mergeLocaleMessage('pl', localeData.pl);
|
|
||||||
i18n.global.mergeLocaleMessage('en', localeData.en);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchBackendTranslations();
|
|
||||||
|
|
||||||
export default i18n;
|
|
||||||
|
|||||||
@@ -1,150 +1,310 @@
|
|||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"title": "ROLLING STOCK EDITOR"
|
"title": "ROLLING STOCK EDITOR"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"disclaimer": "This site has only an informational intent. The author does not carry any responsibility for creating trains against {tos}!",
|
"disclaimer": "This site has only an informational intent. The author does not carry any responsibility for creating trains against {tos}!",
|
||||||
"tos": "Train Driver 2 simulator rules",
|
"tos": "Train Driver 2 simulator rules",
|
||||||
"tos-href": "https://docs.google.com/document/d/1UAAPUtN0d_RoS4RgOzEzllJZJhA0VcizzCzKW4QylbY/edit#heading=h.1ldcvhomwjp9",
|
"tos-href": "https://docs.google.com/document/d/1UAAPUtN0d_RoS4RgOzEzllJZJhA0VcizzCzKW4QylbY/edit#heading=h.1ldcvhomwjp9",
|
||||||
"version-check": "Site is complete for version {version} of Train Driver 2 simulator"
|
"version-check": "Site is complete for version {version} of Train Driver 2 simulator"
|
||||||
},
|
},
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"title": "CHOOSE A VEHICLE",
|
"title": "CHOOSE A VEHICLE",
|
||||||
"input-vehicle": "Choose a traction unit",
|
"input-vehicle": "Choose a traction unit",
|
||||||
"input-carwagon": "Choose a carriage",
|
"input-carwagon": "Choose a carriage",
|
||||||
"cargo-title": "Cargo (only selected freight cars)",
|
"cargo-title": "Cargo (only selected freight cars)",
|
||||||
"no-cargo-available": "no cargo available",
|
"no-cargo-available": "no cargo available",
|
||||||
"cargo-empty": "empty",
|
"cargo-empty": "empty",
|
||||||
"loco-e": "ELECTR.",
|
"loco-electric": "ELECTR.",
|
||||||
"loco-s": "DIESEL",
|
"loco-diesel": "DIESEL",
|
||||||
"loco-ezt": "EMU",
|
"unit-electric": "EMU",
|
||||||
"loco-szt": "DMU",
|
"unit-diesel": "DMU",
|
||||||
"car-passenger": "PASSENGER",
|
"wagon-passenger": "PASSENGER",
|
||||||
"car-cargo": "FREIGHT",
|
"wagon-freight": "FREIGHT",
|
||||||
"action-add": "ADD NEW",
|
"action-add": "ADD NEW",
|
||||||
"action-swap": "SWAP WITH",
|
"action-swap": "SWAP WITH",
|
||||||
"real-stock": "POLISH TRAIN COMPOSITIONS"
|
"real-stock": "POLISH TRAIN COMPOSITIONS"
|
||||||
},
|
},
|
||||||
"preview": {
|
"preview": {
|
||||||
"title": "RAILWAY VEHICLE PREVIEW",
|
"title": "RAILWAY VEHICLE PREVIEW",
|
||||||
"loading": "IMAGE LOADING...",
|
"loading": "IMAGE LOADING...",
|
||||||
"desc": "Choose a railway vehicle above to see its preview",
|
"desc": "Choose a railway vehicle above to see its preview",
|
||||||
"sponsor-only": "* SPONSORS ONLY",
|
"sponsor-only": "* SPONSORS ONLY UNTIL {0}",
|
||||||
"loco-e": "ELECTRIC LOCO",
|
"team-only": "* TD2 TEAM ONLY",
|
||||||
"loco-s": "DIESEL LOCO",
|
"loco-electric": "ELECTRIC LOCO",
|
||||||
"loco-ezt": "ELECTRIC M.U.",
|
"loco-diesel": "DIESEL LOCO",
|
||||||
"loco-szt": "DIESEL M.U.",
|
"unit-electric": "ELECTRIC M.U.",
|
||||||
"car-passenger": "PASSENGER CARRIAGE",
|
"unit-diesel": "DIESEL M.U.",
|
||||||
"car-cargo": "FREIGHT CAR",
|
"wagon-passenger": "PASSENGER CARRIAGE",
|
||||||
"cabin": "Cabin type:",
|
"wagon-freight": "FREIGHT CARRIAGE",
|
||||||
"construction": "Construction type:"
|
"cabin": "Cabin type:",
|
||||||
},
|
"construction": "Construction type:"
|
||||||
"topbar": {
|
},
|
||||||
"stock-list": "STOCK",
|
"topbar": {
|
||||||
"wiki-list": "VEHICLES",
|
"stock-list": "STOCK",
|
||||||
"number-generator": "NUMBER GEN.",
|
"wiki-list": "VEHICLES",
|
||||||
"stock-generator": "STOCK GEN."
|
"number-generator": "NUMBER GEN.",
|
||||||
},
|
"stock-generator": "STOCK GEN."
|
||||||
"stocklist": {
|
},
|
||||||
"title": "STOCK EDITOR",
|
"stocklist": {
|
||||||
"alert-copied": "The rolling stock has been copied to your clipboard!",
|
"title": "STOCK EDITOR",
|
||||||
"alert-empty": "Lista pojazdów jest pusta!",
|
"disclaimer": "Theorethical value based on vehicles maximum speed in the current composition. It may be inaccurate in relation to the correct operational speed in certain configurations.",
|
||||||
"prompt-file": "Name a file and download it to the Presets folder (Documents/TTSK/TrainDriver2):",
|
"alert-copied": "The rolling stock has been copied to your clipboard!",
|
||||||
"vehicle-no": "VEHICLE NO.",
|
"alert-empty": "Lista pojazdów jest pusta!",
|
||||||
"no-vehicle-chosen": "NO VEHICLE CHOSEN",
|
"prompt-file": "Name a file and download it to the Presets folder (Documents/TTSK/TrainDriver2):",
|
||||||
"action-move-up": "MOVE UP",
|
"vehicle-no": "VEHICLE NO.",
|
||||||
"action-move-down": "MOVE DOWN",
|
"no-vehicle-chosen": "NO VEHICLE CHOSEN",
|
||||||
"action-remove": "REMOVE",
|
"action-move-up": "MOVE UP",
|
||||||
"action-upload": "LOAD",
|
"action-move-down": "MOVE DOWN",
|
||||||
"action-download": "DOWNLOAD",
|
"action-remove": "REMOVE",
|
||||||
"action-copy": "COPY",
|
"action-upload": "LOAD",
|
||||||
"action-reset": "RESET",
|
"action-download": "DOWNLOAD",
|
||||||
"action-shuffle": "SHUFFLE",
|
"action-copy": "COPY",
|
||||||
"mass": "Mass",
|
"action-reset": "RESET",
|
||||||
"mass-accepted": "accepted",
|
"action-shuffle": "SHUFFLE",
|
||||||
"length": "Length",
|
"mass": "Mass",
|
||||||
"vmax": "vMax",
|
"mass-accepted": "accepted",
|
||||||
"coldstart-info": "Cold start heading locomotive (only locos 303E & 203E type)",
|
"length": "Length",
|
||||||
"list-empty": "Stock list is empty!",
|
"vmax": "vMax",
|
||||||
"warning-not-suitable": "EP07 & EP08 type locomotives are designed for passenger traffic only!",
|
"coldstart-info": "Locomotive cold start",
|
||||||
"warning-passenger-too-long": "Maximum length of a passenger train may not be greater than 350m!",
|
"doublemanning-info": "Double manning",
|
||||||
"warning-freight-too-long": "Maximum length of a freight train may not be greater than 650m!",
|
"list-empty": "Stock list is empty!",
|
||||||
"warning-too-many-locos": "This train has too many traction units!",
|
|
||||||
"warning-too-heavy": "This train is too heavy! Check {href}",
|
"warning-not-suitable": "EP series locomotives are designed for passenger traffic only!",
|
||||||
"acceptable-mass-docs": "acceptable rolling stock masses (PL)"
|
"warning-passenger-too-long": "Maximum length of a passenger train may not be greater than 350m!",
|
||||||
},
|
"warning-freight-too-long": "Maximum length of a freight train may not be greater than 650m!",
|
||||||
"stockgen": {
|
"warning-too-many-locos": "This train has too many traction units!",
|
||||||
"title": "FREIGHT TRAIN GENERATOR",
|
"warning-too-heavy": "This train is too heavy! Check {href}",
|
||||||
"properties-title": "ROLLING STOCK PROPERTIES",
|
"warning-team-only-vehicle": "There's at least one vehicle available only for TD2 team members in your stock composition! ({0})",
|
||||||
"properties-desc": "⇐ Add a locomotive in the first place of the stock list to include it in a drawing!",
|
"acceptable-mass-docs": "acceptable rolling stock masses (PL)"
|
||||||
"input-mass": "Max. mass (t)",
|
},
|
||||||
"input-length": "Max. length (m)",
|
"stockgen": {
|
||||||
"input-carcount": "Max. car count",
|
"title": "FREIGHT TRAIN GENERATOR",
|
||||||
"cargo-title": "CARGO",
|
"properties-title": "ROLLING STOCK PROPERTIES",
|
||||||
"cargo-desc": "Choose cargo you want to fill available cars with:",
|
"properties-desc": "⇐ Add a locomotive in the first place of the stock list to include it in a drawing!",
|
||||||
"chosen-title": "CARS WITH CHOSEN CARGO",
|
"input-mass": "Max. mass (t)",
|
||||||
"chosen-empty-warning": "Choose at least one cargo type to see available cars!",
|
"input-length": "Max. length (m)",
|
||||||
"chosen-warning": "Cars containing chosen cargo are shown below. Hover over a type to see a preview of the car. Click it to include/exclude it from a drawing (only highlighted types will be included).",
|
"input-carcount": "Max. car count",
|
||||||
"action-generate": "GENERATE",
|
"cargo-title": "CARGO",
|
||||||
"action-generate-empty": "GENERATE EMPTY",
|
"cargo-desc": "Choose cargo you want to fill available cars with:",
|
||||||
"action-reset": "RESET CARGO"
|
"chosen-title": "CARS WITH CHOSEN CARGO",
|
||||||
},
|
"chosen-empty-warning": "Choose at least one cargo type to see available cars!",
|
||||||
"numgen": {
|
"chosen-warning": "Cars containing chosen cargo are shown below. Hover over a type to see a preview of the car. Click it to include/exclude it from a drawing (only highlighted types will be included).",
|
||||||
"title": "TRAIN NUMBER GENERATOR",
|
"action-generate": "GENERATE",
|
||||||
"alert": "The number has been copied to your clipboard!",
|
"action-generate-empty": "GENERATE EMPTY",
|
||||||
"start-region": "Beginning construction region",
|
"action-reset": "RESET CARGO"
|
||||||
"end-region": "Terminating construction region",
|
},
|
||||||
"train-category": "Train category",
|
"numgen": {
|
||||||
"number-info": "Generated train number:",
|
"title": "TRAIN NUMBER GENERATOR",
|
||||||
"warning": "Choose category and (optionally) construction regions",
|
"subtitle": "Generates real train number based on Polish railway instruction Ir-11",
|
||||||
"td2-wiki": "> Polish rules of train numbering (TD2 wiki)",
|
"alert": "The number has been copied to your clipboard!",
|
||||||
"td2-wiki-link": "https://wiki.td2.info.pl/index.php?title=Zasady_numeracji_poci%C4%85g%C3%B3w/en",
|
"start-region": "Beginning construction region",
|
||||||
"action-random-region": "DRAW REGIONS",
|
"end-region": "Terminating construction region",
|
||||||
"action-random-number": "DRAW A NUMBER",
|
"train-category": "Train category",
|
||||||
"categories": {
|
"number-info": "Generated train number:",
|
||||||
"EI": "domestic express (EI)",
|
"warning": "Choose category and (optionally) construction regions",
|
||||||
"MP/RP": "(inter)voivodeship bullet (MP/RP)",
|
"td2-wiki": "> Polish rules of train numbering (forum thread)",
|
||||||
"RO": "regional passenger (RO)",
|
"td2-wiki-link": "https://td2.info.pl/english-boards/new-train-categories-in-the-simulator/",
|
||||||
"PW": "empty passenger (PW)",
|
"action-random-region": "DRAW REGIONS",
|
||||||
"TM": "mass transport freight (TM)",
|
"action-random-number": "DRAW LAST DIGITS",
|
||||||
"TK": "non-mass transport freight (TK)",
|
"action-random-category": "DRAW A CATEGORY",
|
||||||
"LT": "locomotive alone (LT)"
|
|
||||||
},
|
"rules": {
|
||||||
"rules": {
|
"first-digit": "First digit:",
|
||||||
"EI": "4 digits - ends within the range of 00-99",
|
"second-digit": "Second digit:",
|
||||||
"MP/RP": "5 digits - ends within the range of 050-169",
|
"third-digit": "Third digit:",
|
||||||
"RO": "5 digits - ends within the range of 200-999",
|
"two-first-digits": "Two first digits:",
|
||||||
"PW": "6 digits - '6' on the 3rd place; ends within the range of 000-899",
|
"two-last-digits": "Two last digits:",
|
||||||
"TM": "6 digits - '4' on the 3rd place; ends within the range of 000-899",
|
"three-last-digits": "Three last digits:",
|
||||||
"TK": "6 digits - '3' on the 3rd place; ends within the range of 000-899",
|
"from-pool": "from pool of",
|
||||||
"LT": "6 digits - '5' on the 3rd place; ends within the range of 000-899"
|
"for-category": "for category",
|
||||||
}
|
"for-region": "for region",
|
||||||
},
|
"for-region-begin": "for the beginning construction region",
|
||||||
"wiki": {
|
"for-region-end": "for the terminating construction region",
|
||||||
"title": "LIST OF AVAILABLE VEHICLES",
|
"from-range": "from range of"
|
||||||
"action-vehicles": "TRACTION UNITS",
|
},
|
||||||
"action-carriages": "CARRIAGES",
|
|
||||||
"search": "Search for a vehicle...",
|
"categories": {
|
||||||
"header": {
|
"EI": "EI - domestic express",
|
||||||
"image": "Image",
|
"EC": "EC - international express",
|
||||||
"type": "Name",
|
"EN": "EN - domestic night express",
|
||||||
"power": "Type",
|
|
||||||
"constructionType": "Construction",
|
"MP": "MP - intervoivodeship bullet",
|
||||||
"coldStart": "Cold start",
|
"MO": "MO - intervoivodeship regio",
|
||||||
"length": "Length",
|
"MM": "MM - international bullet",
|
||||||
"mass": "Mass",
|
"MH": "MH - intervoivodeship night bullet",
|
||||||
"maxSpeed": "Speed",
|
|
||||||
"cargoCount": "Cargo count"
|
"RP": "RP - voivodeship bullet",
|
||||||
},
|
"RM": "RM - international voivodeship regio",
|
||||||
"loco-ezt": "EMU",
|
"RO": "RO - voivodeship regio",
|
||||||
"loco-szt": "DMU",
|
"RA": "RA - voivodeship regio (urban)",
|
||||||
"loco-s": "Diesel locomotive",
|
|
||||||
"loco-e": "Electric locomotive"
|
"PW": "PW - empty passenger",
|
||||||
},
|
"PX": "PX - empty passenger test drive",
|
||||||
"realstock": {
|
|
||||||
"title": "POLISH TRAIN COMPOSITIONS by",
|
"TC": "TC - international freight (intermodal)",
|
||||||
"search-name": "Search by name",
|
"TG": "TG - international freight (organized cargo)",
|
||||||
"search-stock": "Search by vehicles",
|
"TR": "TR - international freight (unorganized cargo)",
|
||||||
"action-reset": "RESET"
|
"TD": "TD - domestic freight (intermodal)",
|
||||||
}
|
"TM": "TM - domestic freight (organized cargo)",
|
||||||
}
|
"TN": "TN - domestic freight (unorganized cargo)",
|
||||||
|
"TK": "TK - freight (for stations & sidings)",
|
||||||
|
"TS": "TS - empty freight test drive",
|
||||||
|
"TH": "TH - locomotive rolling stock (over 3 vehicles)",
|
||||||
|
|
||||||
|
"LT": "LT - freight locomotive only",
|
||||||
|
"LP": "LP - passenger locomotive only",
|
||||||
|
"LS": "LS - shunting locomotive only",
|
||||||
|
"LZ": "LS - shunting locomotive only",
|
||||||
|
|
||||||
|
"ZN": "ZN - inspection / diagnostic type",
|
||||||
|
"ZU": "ZU - other maintenance type"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wiki": {
|
||||||
|
"title": "LIST OF AVAILABLE VEHICLES",
|
||||||
|
"no-vehicles": "No vehicles to show with the selected filters!",
|
||||||
|
"labels": {
|
||||||
|
"vehicles": "Vehicles",
|
||||||
|
"sort-by": "Sort by",
|
||||||
|
"sort-direction": "Sort direction",
|
||||||
|
"search-vehicle": "Find a vehicle",
|
||||||
|
"search-vehicle-placeholder": "Input a vehicle name"
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"vehicles-all": "all",
|
||||||
|
"vehicles-traction": "traction units",
|
||||||
|
"vehicles-wagon": "wagons"
|
||||||
|
},
|
||||||
|
"sort-by": {
|
||||||
|
"type": "name",
|
||||||
|
"group": "type group",
|
||||||
|
"length": "length",
|
||||||
|
"weight": "mass",
|
||||||
|
"maxSpeed": "speed",
|
||||||
|
"coldStart": "cold start",
|
||||||
|
"cargoCount": "cargo count"
|
||||||
|
},
|
||||||
|
"sort-direction": {
|
||||||
|
"asc": "ascending",
|
||||||
|
"desc": "descending"
|
||||||
|
},
|
||||||
|
"unit-electric": "EMU",
|
||||||
|
"unit-diesel": "DMU",
|
||||||
|
"loco-diesel": "Diesel locomotive",
|
||||||
|
"loco-electric": "Electric locomotive",
|
||||||
|
"wagon-passenger": "Passenger carriage",
|
||||||
|
"wagon-freight": "Frieght carriage"
|
||||||
|
},
|
||||||
|
"realstock": {
|
||||||
|
"title": "POLISH TRAIN COMPOSITIONS by",
|
||||||
|
"search-name": "Search by name",
|
||||||
|
"search-stock": "Search by vehicles",
|
||||||
|
"action-reset": "RESET"
|
||||||
|
},
|
||||||
|
"cargo": {
|
||||||
|
"kontenery": "containers",
|
||||||
|
"chłodnia": "refrigerator",
|
||||||
|
"drobnica": "loose cargo",
|
||||||
|
"węgiel": "coal",
|
||||||
|
"ruda": "ore",
|
||||||
|
"piasek": "sand",
|
||||||
|
"kreda": "chalk",
|
||||||
|
"kamień": "stone",
|
||||||
|
"złom": "scrap",
|
||||||
|
"paliwo": "fuel",
|
||||||
|
"melasa": "molasses",
|
||||||
|
"żwir": "gravel",
|
||||||
|
"koła": "wheels",
|
||||||
|
"drewno": "wood",
|
||||||
|
"szyny": "rails",
|
||||||
|
"kable": "cables",
|
||||||
|
"kruszywo": "aggregate",
|
||||||
|
"techniczne": "technical",
|
||||||
|
"poczta": "mail",
|
||||||
|
"cement": "concrete",
|
||||||
|
"wapno": "lime",
|
||||||
|
"soda": "soda",
|
||||||
|
"pszenica": "wheat",
|
||||||
|
"kukurydza": "corn",
|
||||||
|
"pasza": "fodder",
|
||||||
|
"karbid": "carbide",
|
||||||
|
"pojazdy": "vehicles",
|
||||||
|
"wrażliwe": "sensitive",
|
||||||
|
"stal": "steel",
|
||||||
|
"gaz": "gas"
|
||||||
|
},
|
||||||
|
"usage": {
|
||||||
|
"Gor89": "passenger carriage",
|
||||||
|
"Gor77": "passenger carriage",
|
||||||
|
"Bau84": "passenger carriage",
|
||||||
|
"Bau84_CD": "passenger carriage",
|
||||||
|
"612a": "passenger carriage",
|
||||||
|
"504a": "passenger carriage",
|
||||||
|
"304c": "passenger carriage",
|
||||||
|
"159a": "passenger carriage",
|
||||||
|
"158a": "passenger carriage",
|
||||||
|
"154a": "passenger carriage",
|
||||||
|
"120a_PRREG": "passenger carriage",
|
||||||
|
"113a": "passenger carriage",
|
||||||
|
"113a_1": "passenger carriage",
|
||||||
|
"112a": "passenger carriage",
|
||||||
|
"112a_1": "passenger carriage",
|
||||||
|
"111a_PKP": "passenger carriage",
|
||||||
|
"111a_PKPIC": "passenger carriage",
|
||||||
|
"111a_PRREG": "passenger carriage",
|
||||||
|
"111a_Grafitti": "passenger carriage",
|
||||||
|
"110a": "passenger carriage",
|
||||||
|
"110a_PKP": "passenger carriage",
|
||||||
|
"110a_PKPIC": "passenger carriage",
|
||||||
|
"101a": "passenger carriage",
|
||||||
|
"102a": "passenger carriage",
|
||||||
|
"102A": "technical car",
|
||||||
|
"24Z": "copper wiring reels",
|
||||||
|
"202Lc": "refrigerator car",
|
||||||
|
"206S_CEMET": "cement, lime, soda",
|
||||||
|
"206S_SPEED": "cement, lime, soda",
|
||||||
|
"206Sh_PKP": "wheat, corn, fodder",
|
||||||
|
"206Sh_PKPC": "wheat, corn, fodder",
|
||||||
|
"220S_CEMET": "cement, lime, soda",
|
||||||
|
"211K": "express parcel car",
|
||||||
|
"220S": "cement, lime, soda",
|
||||||
|
"59WS": "loose cargo, limestone, mine waste",
|
||||||
|
"208Kf": "loose cargo, LCL",
|
||||||
|
"209c": "technical car",
|
||||||
|
"29R": "liquid paraffin products",
|
||||||
|
"29R_PLPOL": "molasses",
|
||||||
|
"304Ca": "special vehicle",
|
||||||
|
"401Ka": "loose cargo, LCL",
|
||||||
|
"401Ka_XGa": "utility car",
|
||||||
|
"401Zb_PKESA": "coal, stone, sand",
|
||||||
|
"401Zb_PKPC": "coal, stone, sand",
|
||||||
|
"401Ze_KLP": "concrete panels, cable reels, steel",
|
||||||
|
"401Ze_PNUIK": "concrete panels, cable reels, steel",
|
||||||
|
"401Ze_PKESA": "concrete panels, cable reels, steel",
|
||||||
|
"401Zl": "heavy loose cargo",
|
||||||
|
"408S": "cement, lime, fly ash, slag",
|
||||||
|
"412W": "loose cargo, coal",
|
||||||
|
"412Z": "containers",
|
||||||
|
"413S": "coal, chalk, sand",
|
||||||
|
"421S": "carbide, weather-sensitive loads",
|
||||||
|
"424Z": "vehicles, logs, rough timber",
|
||||||
|
"425S": "weather-sensitive loads",
|
||||||
|
"426Z": "solid cargo, vehicles",
|
||||||
|
"426S": "loose cargo",
|
||||||
|
"429W": "weatherproof cargo (coal, ore)",
|
||||||
|
"441V": "hard coal, gravel",
|
||||||
|
"627Z": "containers",
|
||||||
|
"WB117": "gas, gas mixtures",
|
||||||
|
"445Rb": "liquid paraffin products",
|
||||||
|
"418Va_AWT": "loose cargo (sand, stone)",
|
||||||
|
"418Va_BENET": "loose cargo (sand, stone)",
|
||||||
|
"418Va_TSS": "loose cargo (sand, stone)",
|
||||||
|
"418Vb_DB": "loose cargo (sand, stone)",
|
||||||
|
"418Vb_DOLWR": "loose cargo (sand, stone)",
|
||||||
|
"418Vb_PKPC": "loose cargo (sand, stone)",
|
||||||
|
"418Vb_WIEBE": "loose cargo (sand, stone)",
|
||||||
|
"418Vb_ZOS": "loose cargo (sand, stone)",
|
||||||
|
"418Vb_ZUE": "loose cargo (sand, stone)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,150 +1,309 @@
|
|||||||
{
|
{
|
||||||
"app": {
|
"app": {
|
||||||
"title": "EDYTOR SKŁADÓW ONLINE"
|
"title": "EDYTOR SKŁADÓW ONLINE"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"disclaimer": "Ta strona ma charakter informacyjny. Autor nie ponosi odpowiedzialności za tworzenie pociągów niezgodnych z {tos}!",
|
"disclaimer": "Ta strona ma charakter informacyjny. Autor nie ponosi odpowiedzialności za tworzenie pociągów niezgodnych z {tos}!",
|
||||||
"tos": "regulaminem symulatora Train Driver 2",
|
"tos": "regulaminem symulatora Train Driver 2",
|
||||||
"tos-href": "https://docs.google.com/document/d/1UAAPUtN0d_RoS4RgOzEzllJZJhA0VcizzCzKW4QylbY/edit",
|
"tos-href": "https://docs.google.com/document/d/1UAAPUtN0d_RoS4RgOzEzllJZJhA0VcizzCzKW4QylbY/edit",
|
||||||
"version-check": "Strona jest kompletna dla wersji {version} symulatora TD2"
|
"version-check": "Strona jest kompletna dla wersji {version} symulatora TD2"
|
||||||
},
|
},
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"title": "WYBIERZ POJAZD SZYNOWY",
|
"title": "WYBIERZ POJAZD",
|
||||||
"input-vehicle": "Wybierz pojazd trakcyjny",
|
"input-vehicle": "Wybierz pojazd trakcyjny",
|
||||||
"input-carwagon": "Wybierz wagon",
|
"input-carwagon": "Wybierz wagon",
|
||||||
"cargo-title": "Ładunek (tylko wybrane towarowe)",
|
"cargo-title": "Ładunek (tylko wybrane towarowe)",
|
||||||
"no-cargo-available": "brak dostępnych ładunków",
|
"no-cargo-available": "brak dostępnych ładunków",
|
||||||
"cargo-empty": "próżny",
|
"cargo-empty": "próżny",
|
||||||
"loco-e": "ELEKTR.",
|
"loco-electric": "ELEKTR.",
|
||||||
"loco-s": "SPAL.",
|
"loco-diesel": "SPAL.",
|
||||||
"loco-ezt": "EZT",
|
"unit-electric": "EZT",
|
||||||
"loco-szt": "SZT",
|
"unit-diesel": "SZT",
|
||||||
"car-passenger": "PASAŻERSKIE",
|
"wagon-passenger": "PASAŻERSKIE",
|
||||||
"car-cargo": "TOWAROWE",
|
"wagon-freight": "TOWAROWE",
|
||||||
"action-add": "DODAJ NOWY",
|
"action-add": "DODAJ NOWY",
|
||||||
"action-swap": "ZAMIEŃ ZA",
|
"action-swap": "ZAMIEŃ ZA",
|
||||||
"real-stock": "REALNE ZESTAWIENIA"
|
"real-stock": "REALNE ZESTAWIENIA"
|
||||||
},
|
},
|
||||||
"preview": {
|
"preview": {
|
||||||
"title": "PODGLĄD WYBRANEGO POJAZDU",
|
"title": "PODGLĄD WYBRANEGO POJAZDU",
|
||||||
"loading": "ŁADOWANIE OBRAZU...",
|
"loading": "ŁADOWANIE OBRAZU...",
|
||||||
"desc": "Wybierz pojazd lub wagon, aby zobaczyć jego podgląd powyżej",
|
"desc": "Wybierz pojazd lub wagon, aby zobaczyć jego podgląd powyżej",
|
||||||
"sponsor-only": "* TYLKO DLA SPONSORÓW",
|
"sponsor-only": "* TYLKO DLA SPONSORÓW DO {0}",
|
||||||
"loco-e": "ELEKTROWÓZ",
|
"team-only": "* TYLKO DLA ZESPOŁU TD2",
|
||||||
"loco-s": "SPALINOWÓZ",
|
"loco-electric": "ELEKTROWÓZ",
|
||||||
"loco-ezt": "EZT",
|
"loco-diesel": "SPALINOWÓZ",
|
||||||
"loco-szt": "SZT",
|
"unit-electric": "EZT",
|
||||||
"car-passenger": "WAGON PASAŻERSKI",
|
"unit-diesel": "SZT",
|
||||||
"car-cargo": "WAGON TOWAROWY",
|
"wagon-passenger": "WAGON PASAŻERSKI",
|
||||||
"cabin": "Typ kabiny:",
|
"wagon-freight": "WAGON TOWAROWY",
|
||||||
"construction": "Typ konstrukcji:"
|
"cabin": "Typ kabiny:",
|
||||||
},
|
"construction": "Typ konstrukcji:"
|
||||||
"topbar": {
|
},
|
||||||
"stock-list": "SKŁAD",
|
"topbar": {
|
||||||
"wiki-list": "POJAZDY",
|
"stock-list": "SKŁAD",
|
||||||
"number-generator": "GNR NUMERU",
|
"wiki-list": "POJAZDY",
|
||||||
"stock-generator": "GNR SKŁADU"
|
"number-generator": "GNR NUMERU",
|
||||||
},
|
"stock-generator": "GNR SKŁADU"
|
||||||
"stocklist": {
|
},
|
||||||
"title": "EDYTOR SKŁADU",
|
"stocklist": {
|
||||||
"alert-copied": "Skład został skopiowany do twojego schowka!",
|
"title": "EDYTOR SKŁADU",
|
||||||
"alert-empty": "Lista pojazdów jest pusta!",
|
"disclaimer": "Wartość poglądowa wzorowana na prędkościach maksymalnych poszczególnych pojazdów w zestawieniu. Może nie zgadzać się z prawdziwymi prędkościami eksploatacyjnymi w konkretnych konfiguracjach.",
|
||||||
"prompt-file": "Nazwij plik, a następnie pobierz do folderu Presets (Dokumenty/TTSK/TrainDriver2):",
|
"alert-copied": "Skład został skopiowany do twojego schowka!",
|
||||||
"vehicle-no": "POJAZD NR",
|
"alert-empty": "Lista pojazdów jest pusta!",
|
||||||
"no-vehicle-chosen": "NIE WYBRANO POJAZDU",
|
"prompt-file": "Nazwij plik, a następnie pobierz do folderu Presets (Dokumenty/TTSK/TrainDriver2):",
|
||||||
"action-move-up": "PRZENIEŚ WYŻEJ",
|
"vehicle-no": "POJAZD NR",
|
||||||
"action-move-down": "PRZENIEŚ NIŻEJ",
|
"no-vehicle-chosen": "NIE WYBRANO POJAZDU",
|
||||||
"action-remove": "USUŃ",
|
"action-move-up": "PRZENIEŚ WYŻEJ",
|
||||||
"action-upload": "WCZYTAJ",
|
"action-move-down": "PRZENIEŚ NIŻEJ",
|
||||||
"action-download": "POBIERZ",
|
"action-remove": "USUŃ",
|
||||||
"action-copy": "SKOPIUJ",
|
"action-upload": "WCZYTAJ",
|
||||||
"action-reset": "ZRESETUJ",
|
"action-download": "POBIERZ",
|
||||||
"action-shuffle": "PRZETASUJ",
|
"action-copy": "SKOPIUJ",
|
||||||
"mass": "Masa",
|
"action-reset": "ZRESETUJ",
|
||||||
"mass-accepted": "dopuszczalna",
|
"action-shuffle": "PRZETASUJ",
|
||||||
"length": "Długość",
|
"mass": "Masa",
|
||||||
"vmax": "vMax",
|
"mass-accepted": "dopuszczalna",
|
||||||
"coldstart-info": "Zimny start lokomotywy czołowej (tylko elektrowozy typów 303E i 203E)",
|
"length": "Długość",
|
||||||
"list-empty": "Lista pojazdów jest pusta!",
|
"vmax": "vMax",
|
||||||
"warning-not-suitable": "Lokomotywy EP07 i EP08 są przeznaczone jedynie do ruchu pasażerskiego!",
|
"coldstart-info": "Zimny start",
|
||||||
"warning-passenger-too-long": "Maksymalna długość składów pasażerskich nie może przekraczać 350m!",
|
"doublemanning-info": "Podwójna obsada",
|
||||||
"warning-freight-too-long": "Maksymalna długość składów innych niż pasażerskie nie może przekraczać 650m!",
|
"list-empty": "Lista pojazdów jest pusta!",
|
||||||
"warning-too-many-locos": "Ten skład posiada za dużo pojazdów trakcyjnych!",
|
|
||||||
"warning-too-heavy": "Ten skład jest za ciężki! Sprawdź {href}",
|
"warning-not-suitable": "Lokomotywy serii EP są przeznaczone jedynie do ruchu pasażerskiego!",
|
||||||
"acceptable-mass-docs": "dopuszczalne masy składów"
|
"warning-passenger-too-long": "Maksymalna długość składów pasażerskich nie może przekraczać 350m!",
|
||||||
},
|
"warning-freight-too-long": "Maksymalna długość składów innych niż pasażerskie nie może przekraczać 650m!",
|
||||||
"stockgen": {
|
"warning-too-many-locos": "Ten skład posiada za dużo pojazdów trakcyjnych!",
|
||||||
"title": "GENERATOR SKŁADU TOWAROWEGO",
|
"warning-too-heavy": "Ten skład jest za ciężki! Sprawdź {href}",
|
||||||
"properties-title": "WŁAŚCIWOŚCI SKŁADU",
|
"warning-team-only-vehicle": "W zestawieniu znajduje się co najmniej jeden pojazd dostępny tylko dla członków zespołu TD2! ({0})",
|
||||||
"properties-desc": "⇐ Dodaj lokomotywę na pierwsze miejsce listy, aby uwzględnić ją przy losowaniu składu!",
|
"acceptable-mass-docs": "dopuszczalne masy składów"
|
||||||
"input-mass": "Maksymalna masa (t)",
|
},
|
||||||
"input-length": "Maks. długość (m)",
|
"stockgen": {
|
||||||
"input-carcount": "Maks. liczba wagonów",
|
"title": "GENERATOR SKŁADU TOWAROWEGO",
|
||||||
"cargo-title": "ŁADUNEK",
|
"properties-title": "WŁAŚCIWOŚCI SKŁADU",
|
||||||
"cargo-desc": "Wybierz ładunki, którymi chcesz wypełnić dostępne wagony:",
|
"properties-desc": "⇐ Dodaj lokomotywę na pierwsze miejsce listy, aby uwzględnić ją przy losowaniu składu!",
|
||||||
"chosen-title": "WAGONY Z WYBRANYMI ŁADUNKAMI",
|
"input-mass": "Maksymalna masa (t)",
|
||||||
"chosen-empty-warning": "Wybierz co najmniej jeden ładunek, aby zobaczyć wagony, które go posiadają!",
|
"input-length": "Maks. długość (m)",
|
||||||
"chosen-warning": "Wagony posiadające wybrane ładunki. Najedź na nazwę, aby zobaczyć podgląd wagonu. Kliknij, aby wyłączyć z losowania (tylko podświetlone nazwy będą uwzględnione).",
|
"input-carcount": "Maks. liczba wagonów",
|
||||||
"action-generate": "WYGENERUJ",
|
"cargo-title": "ŁADUNEK",
|
||||||
"action-generate-empty": "WYGENERUJ PRÓŻNE WAGONY",
|
"cargo-desc": "Wybierz ładunki, którymi chcesz wypełnić dostępne wagony:",
|
||||||
"action-reset": "ZRESETUJ ŁADUNKI"
|
"chosen-title": "WAGONY Z WYBRANYMI ŁADUNKAMI",
|
||||||
},
|
"chosen-empty-warning": "Wybierz co najmniej jeden ładunek, aby zobaczyć wagony, które go posiadają!",
|
||||||
"numgen": {
|
"chosen-warning": "Wagony posiadające wybrane ładunki. Najedź na nazwę, aby zobaczyć podgląd wagonu. Kliknij, aby wyłączyć z losowania (tylko podświetlone nazwy będą uwzględnione).",
|
||||||
"title": "GENERATOR NUMERU POCIĄGU",
|
"action-generate": "WYGENERUJ",
|
||||||
"alert": "Numer został skopiowany do twojego schowka!",
|
"action-generate-empty": "WYGENERUJ PRÓŻNE WAGONY",
|
||||||
"start-region": "Początkowy obszar konstrukcyjny",
|
"action-reset": "ZRESETUJ ŁADUNKI"
|
||||||
"end-region": "Końcowy obszar konstrukcyjny",
|
},
|
||||||
"train-category": "Kategoria pociągu",
|
"numgen": {
|
||||||
"number-info": "Wygenerowany numer pociągu:",
|
"title": "GENERATOR NUMERU POCIĄGU",
|
||||||
"warning": "Wybierz kategorię oraz (opcjonalnie) obszary konstrukcyjne",
|
"subtitle": "Generuje realny numer pociągu na podstawie instrukcji Ir-11",
|
||||||
"td2-wiki": "> Szczegółowe zasady numeracji (wikipedia TD2)",
|
"alert": "Numer został skopiowany do twojego schowka!",
|
||||||
"td2-wiki-link": "https://wiki.td2.info.pl/index.php?title=Zasady_numeracji_poci%C4%85g%C3%B3w",
|
"start-region": "Obszar początkowy",
|
||||||
"action-random-region": "LOSUJ OBSZARY",
|
"end-region": "Obszar końcowy",
|
||||||
"action-random-number": "LOSUJ NUMER",
|
"train-category": "Kategoria pociągu",
|
||||||
"categories": {
|
"number-info": "Wygenerowany numer pociągu:",
|
||||||
"EI": "ekspres krajowy (EI)",
|
"warning": "Wybierz kategorię oraz (opcjonalnie) obszary konstrukcyjne",
|
||||||
"MP/RP": "(między)wojewódzki pośpieszny (MP/RP)",
|
"td2-wiki": "> Szczegółowe zasady numeracji (wątek forum)",
|
||||||
"RO": "wojewódzki osobowy (RO)",
|
"td2-wiki-link": "https://td2.info.pl/ogloszenia/nowe-kategorie-pociagow-w-symulatorze/",
|
||||||
"PW": "próżny \"służbowy\" (PW)",
|
"action-random-region": "LOSUJ OBSZARY",
|
||||||
"TM": "towarowy do przewozów masowych (TM)",
|
"action-random-number": "LOSUJ KOŃCÓWKĘ",
|
||||||
"TK": "towarowy do obsługi stacji (TK)",
|
"action-random-category": "LOSUJ KATEGORIĘ",
|
||||||
"LT": "lokomotywa luzem (LT)"
|
|
||||||
},
|
"rules": {
|
||||||
"rules": {
|
"first-digit": "Pierwsza cyfra:",
|
||||||
"EI": "4 cyfry - końcówka z przedziału 00-99",
|
"second-digit": "Druga cyfra:",
|
||||||
"MP/RP": "5 cyfr - końcówka z przedziału 050-169",
|
"third-digit": "Trzecia cyfra:",
|
||||||
"RO": "5 cyfr - końcówka z przedziału 200-999",
|
"two-first-digits": "Dwie pierwsze cyfry:",
|
||||||
"PW": "6 cyfr - '6' na 3. miejscu; końcówka z przedziału 000-899",
|
"two-last-digits": "Dwie ostatnie cyfry:",
|
||||||
"TM": "6 cyfr - '4' na 3. miejscu; końcówka z przedziału 000-899",
|
"three-last-digits": "Trzy ostatnie cyfry:",
|
||||||
"TK": "6 cyfr - '3' na 3. miejscu; końcówka z przedziału 000-899",
|
"from-pool": "z puli",
|
||||||
"LT": "6 cyfr - '5' na 3. miejscu; końcówka z przedziału 000-899"
|
"for-category": "dla kategorii",
|
||||||
}
|
"for-region": "dla obszaru",
|
||||||
},
|
"for-region-begin": "dla początkowego obszaru konstrukcyjnego",
|
||||||
"wiki": {
|
"for-region-end": "dla końcowego obszaru konstrukcyjnego",
|
||||||
"title": "LISTA DOSTĘPNYCH POJAZDÓW",
|
"from-range": "z przedziału"
|
||||||
"action-vehicles": "POJ. TRAKCYJNE",
|
},
|
||||||
"action-carriages": "WAGONY",
|
|
||||||
"search": "Wyszukaj pojazd...",
|
"categories": {
|
||||||
"header": {
|
"EI": "EI - ekspres krajowy",
|
||||||
"image": "Zdjęcie",
|
"EC": "EC - ekspres międzynarodowy",
|
||||||
"type": "Nazwa",
|
"EN": "EN - ekspres krajowy nocny",
|
||||||
"power": "Rodzaj",
|
|
||||||
"constructionType": "Konstrukcja",
|
"MP": "MP - międzywoj. pośpieszny",
|
||||||
"coldStart": "Zimny start",
|
"RP": "RP - wojewódzki pośpieszny",
|
||||||
"length": "Długość",
|
"MO": "MO - międzywoj. osobowy",
|
||||||
"mass": "Masa",
|
"RO": "RO - wojewódzki osobowy",
|
||||||
"maxSpeed": "Prędkość",
|
|
||||||
"cargoCount": "Ładunki"
|
"MM": "MM - międzynar. pośpieszny",
|
||||||
},
|
"MH": "MH - międzywoj. pośpieszny hotelowy",
|
||||||
"loco-ezt": "EZT",
|
"RM": "RM - woj. osobowy międzynarodowy",
|
||||||
"loco-szt": "SZT",
|
"RA": "RA - woj. osobowy algomeracyjny",
|
||||||
"loco-s": "Spalinowóz",
|
|
||||||
"loco-e": "Elektrowóz"
|
"PW": "PW - pasażerski próżny - służbowy",
|
||||||
},
|
"PX": "PX - pasażerski próżny próbny",
|
||||||
"realstock": {
|
|
||||||
"title": "ZESTAWIENIA REALNE by",
|
"TC": "TC - towarowy międzynarodowy intermodalny",
|
||||||
"search-name": "Szukaj po nazwie",
|
"TG": "TG - towarowy międzynarodowy masowy",
|
||||||
"search-stock": "Szukaj po pojazdach",
|
"TR": "TR - towarowy międzynarodowy niemasowy",
|
||||||
"action-reset": "RESETUJ"
|
"TD": "TD - towarowy krajowy intermodalny",
|
||||||
}
|
"TM": "TM - towarowy krajowy masowy",
|
||||||
}
|
"TN": "TN - towarowy krajowy niemasowy",
|
||||||
|
"TK": "TK - towarowy (stacje i bocznice)",
|
||||||
|
"TS": "TS - towarowy próżny próbny",
|
||||||
|
"TH": "TH - skład lokomotyw (powyżej 3 pojazdów)",
|
||||||
|
|
||||||
|
"LT": "LT - lokomotywa towarowa luzem",
|
||||||
|
"LP": "LP - lokomotywa pasażerska luzem",
|
||||||
|
"LS": "LS - lokomotywa manewrowa luzem",
|
||||||
|
"LZ": "LZ - lokomotywa dla poc. utrzymaniowo-naprawczych",
|
||||||
|
|
||||||
|
"ZN": "ZN - inspekcyjny / diagnostyczny",
|
||||||
|
"ZU": "ZU - inny utrzymaniowy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"wiki": {
|
||||||
|
"title": "LISTA DOSTĘPNYCH POJAZDÓW",
|
||||||
|
"no-vehicles": "Brak pojazdów do pokazania przy obecnych filtrach!",
|
||||||
|
"labels": {
|
||||||
|
"vehicles": "Pojazdy",
|
||||||
|
"sort-by": "Sortuj wg",
|
||||||
|
"sort-direction": "Kierunek sortowania",
|
||||||
|
"search-vehicle": "Wyszukaj pojazd",
|
||||||
|
"search-vehicle-placeholder": "Wpisz nazwę pojazdu"
|
||||||
|
},
|
||||||
|
"filters": {
|
||||||
|
"vehicles-all": "wszystkie",
|
||||||
|
"vehicles-traction": "trakcyjne",
|
||||||
|
"vehicles-wagon": "wagony"
|
||||||
|
},
|
||||||
|
"sort-by": {
|
||||||
|
"type": "nazwa",
|
||||||
|
"group": "rodzaj",
|
||||||
|
"length": "długość",
|
||||||
|
"weight": "masa",
|
||||||
|
"maxSpeed": "prędkość",
|
||||||
|
"coldStart": "zimny start",
|
||||||
|
"cargoCount": "ładunki"
|
||||||
|
},
|
||||||
|
"sort-direction": {
|
||||||
|
"asc": "rosnąco",
|
||||||
|
"desc": "malejąco"
|
||||||
|
},
|
||||||
|
"loco-diesel": "Spalinowóz",
|
||||||
|
"loco-electric": "Elektrowóz",
|
||||||
|
"unit-electric": "EZT",
|
||||||
|
"unit-diesel": "SZT",
|
||||||
|
"wagon-passenger": "Wagon pasażerski",
|
||||||
|
"wagon-freight": "Wagon towarowy"
|
||||||
|
},
|
||||||
|
"realstock": {
|
||||||
|
"title": "ZESTAWIENIA REALNE by",
|
||||||
|
"search-name": "Szukaj po nazwie",
|
||||||
|
"search-stock": "Szukaj po pojazdach",
|
||||||
|
"action-reset": "RESETUJ"
|
||||||
|
},
|
||||||
|
"cargo": {
|
||||||
|
"kontenery": "kontenery",
|
||||||
|
"chłodnia": "chłodnia",
|
||||||
|
"drobnica": "drobnica",
|
||||||
|
"węgiel": "węgiel",
|
||||||
|
"ruda": "ruda",
|
||||||
|
"piasek": "piasek",
|
||||||
|
"kreda": "kreda",
|
||||||
|
"kamień": "kamień",
|
||||||
|
"złom": "złom",
|
||||||
|
"paliwo": "paliwo",
|
||||||
|
"melasa": "melasa",
|
||||||
|
"żwir": "żwir",
|
||||||
|
"koła": "koła",
|
||||||
|
"drewno": "drewno",
|
||||||
|
"szyny": "szyny",
|
||||||
|
"kable": "kable",
|
||||||
|
"kruszywo": "kruszywo",
|
||||||
|
"techniczne": "techniczne",
|
||||||
|
"poczta": "poczta",
|
||||||
|
"cement": "cement",
|
||||||
|
"wapno": "wapno",
|
||||||
|
"soda": "soda",
|
||||||
|
"pszenica": "pszenica",
|
||||||
|
"kukurydza": "kukurydza",
|
||||||
|
"pasza": "pasza",
|
||||||
|
"karbid": "karbid",
|
||||||
|
"pojazdy": "pojazdy",
|
||||||
|
"wrażliwe": "wrażliwe",
|
||||||
|
"stal": "stal",
|
||||||
|
"gaz": "gaz"
|
||||||
|
},
|
||||||
|
"usage": {
|
||||||
|
"Gor89": "wagon pasażerski",
|
||||||
|
"Gor77": "wagon pasażerski",
|
||||||
|
"Bau84": "wagon pasażerski",
|
||||||
|
"Bau84_CD": "wagon pasażerski",
|
||||||
|
"612a": "wagon pasażerski",
|
||||||
|
"504a": "wagon pasażerski",
|
||||||
|
"304c": "wagon pasażerski",
|
||||||
|
"159a": "wagon pasażerski",
|
||||||
|
"158a": "wagon pasażerski",
|
||||||
|
"154a": "wagon pasażerski",
|
||||||
|
"120a_PRREG": "wagon pasażerski",
|
||||||
|
"113a": "wagon pasażerski",
|
||||||
|
"113a_1": "wagon pasażerski",
|
||||||
|
"112a": "wagon pasażerski",
|
||||||
|
"112a_1": "wagon pasażerski",
|
||||||
|
"111a_PKP": "wagon pasażerski",
|
||||||
|
"111a_PKPIC": "wagon pasażerski",
|
||||||
|
"111a_PRREG": "wagon pasażerski",
|
||||||
|
"111a_Grafitti": "wagon pasażerski",
|
||||||
|
"110a": "wagon pasażerski",
|
||||||
|
"110a_PKP": "wagon pasażerski",
|
||||||
|
"110a_PKPIC": "wagon pasażerski",
|
||||||
|
"101a": "wagon pasażerski",
|
||||||
|
"102a": "wagon pasażerski",
|
||||||
|
"102A": "wagon techniczny (sieciowy)",
|
||||||
|
"24Z": "bębny z drutami miedzianymi",
|
||||||
|
"202Lc": "wagon chłodnia",
|
||||||
|
"206S_CEMET": "cement, wapno, soda",
|
||||||
|
"206S_SPEED": "cement, wapno, soda",
|
||||||
|
"206Sh_PKP": "pszenica, kukurydza, pasza",
|
||||||
|
"206Sh_PKPC": "pszenica, kukurydza, pasza",
|
||||||
|
"220S_CEMET": "cement, wapno, soda",
|
||||||
|
"211K": "wagon do przesyłek ekspresowych",
|
||||||
|
"59WS": "kruszywo, kamień wapienny, odpady kopalniane",
|
||||||
|
"208Kf": "drobnica, ładunki sypkie, ładunki sztukowe",
|
||||||
|
"209c": "wagon techniczny",
|
||||||
|
"29R": "produkty naftowe",
|
||||||
|
"29R_PLPOL": "melasa",
|
||||||
|
"304Ca": "pojazd specjalny",
|
||||||
|
"401Ka": "drobnica, ładunki sypkie, ładunki sztukowe",
|
||||||
|
"401Ka_XGa": "wagon gospodarczy",
|
||||||
|
"401Zb_PKESA": "węgiel, kamień, piasek",
|
||||||
|
"401Zb_PKPC": "węgiel, kamień, piasek",
|
||||||
|
"401Ze_KLP": "płyty betonowe, bębny kablowe, stal",
|
||||||
|
"401Ze_PNUIK": "płyty betonowe, bębny kablowe, stal",
|
||||||
|
"401Ze_PKESA": "płyty betonowe, bębny kablowe, stal",
|
||||||
|
"401Zl": "ładunki sypkie o dużej masie usypowej",
|
||||||
|
"408S": "cement, wapno, popioły lotne, żużel",
|
||||||
|
"412W": "drobnica, kruszywo, węgiel",
|
||||||
|
"412Z": "kontenery",
|
||||||
|
"413S": "węgiel, kreda, piasek",
|
||||||
|
"421S": "karbid, ładunki wrażliwe na czynniki atm.",
|
||||||
|
"424Z": "ładunki skupione, pojazdy, dłużyca",
|
||||||
|
"425S": "ładunki wrażliwe na czynniki atm.",
|
||||||
|
"426S": "drobnica",
|
||||||
|
"426Z": "ładunki skupione, pojazdy",
|
||||||
|
"429W": "towary masowe odporne na warunki atmosferyczne (węgiel, ruda)",
|
||||||
|
"441V": "węgiel kamienny, żwir",
|
||||||
|
"627Z": "kontenery",
|
||||||
|
"WB117": "gaz, mieszaniny gazów",
|
||||||
|
"445Rb": "produkty naftowe",
|
||||||
|
"418Va_AWT": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Va_BENET": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Va_TSS": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Vb_DB": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Vb_DOLWR": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Vb_PKPC": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Vb_WIEBE": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Vb_ZOS": "drobnica, ładunki sypkie (piasek, kamień)",
|
||||||
|
"418Vb_ZUE": "drobnica, ładunki sypkie (piasek, kamień)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,14 +1,8 @@
|
|||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
import { registerSW } from 'virtual:pwa-register';
|
|
||||||
|
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import i18n from './i18n-setup';
|
import i18n from './i18n-setup';
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
|
||||||
registerSW({
|
|
||||||
immediate: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
createApp(App).use(pinia).use(i18n).mount('#app');
|
createApp(App).use(pinia).use(i18n).mount('#app');
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,9 @@ export default defineComponent({
|
|||||||
getIconURL(name: string, ext = 'svg'): string {
|
getIconURL(name: string, ext = 'svg'): string {
|
||||||
return `/images/icon-${name}.${ext}`;
|
return `/images/icon-${name}.${ext}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getThumbnailURL(vehicleType: string, size: 'small' | 'large') {
|
||||||
|
return `https://static.spythere.eu/images/${vehicleType}--${size == 'small' ? 300 : 800}px.jpg`;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { useStore } from '../store';
|
import { useStore } from '../store';
|
||||||
import { ICargo, ICarWagon, ILocomotive, IStock, Vehicle } from '../types';
|
import { ICarWagon, ILocomotive, IStock, ICargo, IVehicle } from '../types';
|
||||||
import { isLocomotive } from '../utils/vehicleUtils';
|
import { isTractionUnit } from '../utils/vehicleUtils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
@@ -15,38 +15,33 @@ export default defineComponent({
|
|||||||
return `${Math.random().toString(36).slice(5)}`;
|
return `${Math.random().toString(36).slice(5)}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
getStockObject(vehicle: Vehicle, cargo?: ICargo | null, count = 1): IStock {
|
getStockObject(vehicle: IVehicle, cargo?: ICargo | null): IStock {
|
||||||
const isLoco = isLocomotive(vehicle);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: this.getStockId(),
|
id: this.getStockId(),
|
||||||
type: vehicle.type,
|
vehicleRef: vehicle,
|
||||||
length: vehicle.length,
|
cargo: !isTractionUnit(vehicle) && vehicle.loadable && cargo ? cargo : undefined,
|
||||||
mass: vehicle.mass,
|
|
||||||
maxSpeed: vehicle.maxSpeed,
|
|
||||||
isLoco,
|
|
||||||
cargo: !isLoco && vehicle.loadable && cargo ? cargo : undefined,
|
|
||||||
count,
|
|
||||||
imgSrc: vehicle.imageSrc,
|
|
||||||
useType: isLoco ? vehicle.power : vehicle.useType,
|
|
||||||
supportersOnly: vehicle.supportersOnly,
|
|
||||||
constructionType: vehicle.constructionType,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
addVehicle(vehicle: Vehicle | null, cargo?: ICargo | null) {
|
addVehicle(vehicle: IVehicle | null, cargo?: ICargo | null) {
|
||||||
if (!vehicle) return;
|
if (!vehicle) return;
|
||||||
|
|
||||||
const stock = this.getStockObject(vehicle, cargo);
|
const stock = this.getStockObject(vehicle, cargo);
|
||||||
|
|
||||||
if (stock.isLoco && !this.store.stockList[0]?.isLoco) this.store.stockList.unshift(stock);
|
if (
|
||||||
|
isTractionUnit(stock.vehicleRef) &&
|
||||||
|
this.store.stockList.length > 0 &&
|
||||||
|
!isTractionUnit(this.store.stockList[0].vehicleRef)
|
||||||
|
)
|
||||||
|
this.store.stockList.unshift(stock);
|
||||||
else this.store.stockList.push(stock);
|
else this.store.stockList.push(stock);
|
||||||
},
|
},
|
||||||
|
|
||||||
addLocomotive(loco: ILocomotive) {
|
addLocomotive(loco: ILocomotive) {
|
||||||
const stockObj = this.getStockObject(loco);
|
const stockObj = this.getStockObject(loco);
|
||||||
|
|
||||||
if (this.store.stockList.length > 0 && !this.store.stockList[0].isLoco) this.store.stockList.unshift(stockObj);
|
if (this.store.stockList.length > 0 && !isTractionUnit(this.store.stockList[0].vehicleRef))
|
||||||
|
this.store.stockList.unshift(stockObj);
|
||||||
else this.store.stockList.push(stockObj);
|
else this.store.stockList.push(stockObj);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -69,26 +64,31 @@ export default defineComponent({
|
|||||||
this.store.swapVehicles = false;
|
this.store.swapVehicles = false;
|
||||||
|
|
||||||
stockArray.forEach((type, i) => {
|
stockArray.forEach((type, i) => {
|
||||||
let vehicle: Vehicle | null = null;
|
let vehicle: IVehicle | null = null;
|
||||||
let vehicleCargo: ICargo | null = null;
|
let vehicleCargo: ICargo | null = null;
|
||||||
|
|
||||||
if (/^(EU|EP|ET|SM|EN|2EN|SN)/.test(type)) {
|
const isTractionUnit = /^([a-zA-Z\d]{0,}-\d{0,})/.test(type);
|
||||||
const [locoType, coldStart] = type.split(',');
|
|
||||||
|
if (isTractionUnit) {
|
||||||
|
const [locoType, spawnProps] = type.split(',');
|
||||||
vehicle = this.store.locoDataList.find((loco) => loco.type == locoType) || null;
|
vehicle = this.store.locoDataList.find((loco) => loco.type == locoType) || null;
|
||||||
|
|
||||||
if (i == 0 && coldStart == 'c') this.store.isColdStart = true;
|
// Spawn settings
|
||||||
|
if (i == 0 && spawnProps) {
|
||||||
|
this.store.isColdStart = spawnProps.includes('c');
|
||||||
|
this.store.isDoubleManned = spawnProps.includes('d');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const [carType, cargo] = type.split(':');
|
const [carType, cargo] = type.split(':');
|
||||||
vehicle = this.store.carDataList.find((car) => car.type == carType) || null;
|
vehicle = this.store.carDataList.find((car) => car.type == carType) || null;
|
||||||
|
|
||||||
if (cargo) vehicleCargo = vehicle?.cargoList.find((c) => c.id == cargo) || null;
|
if (cargo) vehicleCargo = vehicle?.cargoTypes.find((c) => c.id == cargo) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vehicle) console.log('Brak pojazdu:', type);
|
if (!vehicle) console.warn('Brak pojazdu / rodzaj pojazdu źle wczytany:', type);
|
||||||
|
|
||||||
this.addVehicle(vehicle, vehicleCargo);
|
this.addVehicle(vehicle, vehicleCargo);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { useStore } from '../store';
|
import { useStore } from '../store';
|
||||||
import { ICarWagon, ILocomotive, IStock, Vehicle } from '../types';
|
import { ICarWagon, ILocomotive, IStock, IVehicle, LocoGroupType, WagonGroupType } from '../types';
|
||||||
|
import { isTractionUnit } from '../utils/vehicleUtils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
@@ -9,78 +10,44 @@ export default defineComponent({
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {},
|
||||||
locoOptions() {
|
|
||||||
return this.store.locoDataList
|
|
||||||
.sort((a, b) => (a.type > b.type ? 1 : -1))
|
|
||||||
.filter((loco) => loco.power == this.store.chosenLocoPower);
|
|
||||||
},
|
|
||||||
|
|
||||||
carOptions() {
|
|
||||||
return this.store.carDataList
|
|
||||||
.sort((a, b) => (a.type > b.type ? 1 : -1))
|
|
||||||
.filter((car) => car.useType == this.store.chosenCarUseType);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
selectLocoType(locoTypeId: string) {
|
|
||||||
this.store.chosenLocoPower = locoTypeId;
|
|
||||||
this.store.chosenVehicle = this.locoOptions[0];
|
|
||||||
this.store.chosenLoco = this.locoOptions[0];
|
|
||||||
},
|
|
||||||
|
|
||||||
selectCarWagonType(carWagonTypeId: string) {
|
|
||||||
this.store.chosenCarUseType = carWagonTypeId;
|
|
||||||
this.store.chosenVehicle = this.carOptions[0];
|
|
||||||
this.store.chosenCar = this.carOptions[0];
|
|
||||||
this.store.chosenCargo = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
previewVehicleByType(type: 'loco' | 'car' | 'cargo') {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (!this.store.chosenLoco && !this.store.chosenCar) return;
|
|
||||||
|
|
||||||
this.store.chosenVehicle = type == 'loco' ? this.store.chosenLoco : this.store.chosenCar;
|
|
||||||
|
|
||||||
this.store.chosenCargo =
|
|
||||||
this.store.chosenCar?.cargoList.find((cargo) => cargo.id == this.store.chosenCargo?.id) || null;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
previewStock(stock: IStock) {
|
previewStock(stock: IStock) {
|
||||||
if (this.store.chosenVehicle?.imageSrc != stock.imgSrc) this.store.imageLoading = true;
|
const vehicleRef = stock.vehicleRef;
|
||||||
|
|
||||||
if (stock.isLoco) {
|
this.store.chosenVehicle = vehicleRef;
|
||||||
const chosenLoco = this.store.locoDataList.find((v) => v.type == stock.type) || null;
|
|
||||||
this.store.chosenVehicle = chosenLoco;
|
if (isTractionUnit(vehicleRef)) {
|
||||||
this.store.chosenLoco = chosenLoco;
|
this.store.chosenLoco = vehicleRef;
|
||||||
this.store.chosenCargo = null;
|
this.store.chosenCargo = null;
|
||||||
this.store.chosenLocoPower = stock.useType;
|
this.store.chosenLocoGroup = vehicleRef.group as LocoGroupType;
|
||||||
} else {
|
} else {
|
||||||
const chosenCar = this.store.carDataList.find((v) => v.type == stock.type) || null;
|
this.store.chosenCar = vehicleRef;
|
||||||
this.store.chosenVehicle = chosenCar;
|
|
||||||
this.store.chosenCar = chosenCar;
|
|
||||||
|
|
||||||
this.store.chosenCargo = stock.cargo || null;
|
this.store.chosenCargo = stock.cargo || null;
|
||||||
this.store.chosenCarUseType = stock.useType;
|
this.store.chosenCarGroup = vehicleRef.group as WagonGroupType;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
previewLocomotive(loco: ILocomotive) {
|
previewLocomotive(loco: ILocomotive) {
|
||||||
this.store.chosenLoco = loco;
|
this.store.chosenLoco = loco;
|
||||||
this.store.chosenVehicle = loco;
|
this.store.chosenVehicle = loco;
|
||||||
this.store.chosenLocoPower = loco.power;
|
this.store.chosenLocoGroup = loco.group;
|
||||||
},
|
},
|
||||||
|
|
||||||
previewCarWagon(carWagon: ICarWagon) {
|
previewCarWagon(carWagon: ICarWagon) {
|
||||||
this.store.chosenCar = carWagon;
|
this.store.chosenCar = carWagon;
|
||||||
this.store.chosenCarUseType = carWagon.useType;
|
this.store.chosenCarGroup = carWagon.group;
|
||||||
this.store.chosenVehicle = carWagon;
|
this.store.chosenVehicle = carWagon;
|
||||||
|
|
||||||
this.store.chosenCargo = null;
|
this.store.chosenCargo = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
previewVehicle(vehicle: IVehicle) {
|
||||||
|
if (isTractionUnit(vehicle)) this.previewLocomotive(vehicle);
|
||||||
|
else this.previewCarWagon(vehicle);
|
||||||
|
},
|
||||||
|
|
||||||
resetPreview() {
|
resetPreview() {
|
||||||
this.store.chosenVehicle = null;
|
this.store.chosenVehicle = null;
|
||||||
this.store.chosenCar = null;
|
this.store.chosenCar = null;
|
||||||
@@ -89,4 +56,3 @@ export default defineComponent({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
import { defineComponent } from 'vue';
|
|
||||||
import { useStore } from '../store';
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
setup() {
|
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
return {
|
|
||||||
store,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
trainTooLong() {
|
|
||||||
return (
|
|
||||||
(this.store.totalLength > 350 && this.store.isTrainPassenger) ||
|
|
||||||
(this.store.totalLength > 650 && !this.store.isTrainPassenger)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
trainTooHeavy() {
|
|
||||||
return this.store.acceptableMass && this.store.totalMass > this.store.acceptableMass;
|
|
||||||
},
|
|
||||||
|
|
||||||
locoNotSuitable() {
|
|
||||||
return (
|
|
||||||
!this.store.isTrainPassenger &&
|
|
||||||
this.store.stockList.length > 1 &&
|
|
||||||
!this.store.stockList.every((stock) => stock.isLoco) &&
|
|
||||||
this.store.stockList.some((stock) => stock.isLoco && stock.type.startsWith('EP'))
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
tooManyLocomotives() {
|
|
||||||
return this.store.stockList.reduce((acc, stock) => {
|
|
||||||
if (stock.isLoco) acc += stock.count;
|
|
||||||
return acc;
|
|
||||||
}, 0) > 2;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,68 +1,141 @@
|
|||||||
import { IStore } from './types';
|
import {
|
||||||
|
IVehiclesAPIResponse,
|
||||||
|
ICarWagon,
|
||||||
|
ILocomotive,
|
||||||
|
ICargo,
|
||||||
|
IVehicle,
|
||||||
|
IStock,
|
||||||
|
IRealComposition,
|
||||||
|
LocoGroupType,
|
||||||
|
WagonGroupType,
|
||||||
|
IVehicleData,
|
||||||
|
} from './types';
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import {
|
import {
|
||||||
acceptableMass,
|
acceptableWeight,
|
||||||
carDataList,
|
carDataList,
|
||||||
chosenRealStock,
|
isTractionUnit,
|
||||||
isTrainPassenger,
|
isTrainPassenger,
|
||||||
locoDataList,
|
locoDataList,
|
||||||
maxStockSpeed,
|
maxStockSpeed,
|
||||||
totalLength,
|
totalLength,
|
||||||
totalMass,
|
totalWeight,
|
||||||
} from './utils/vehicleUtils';
|
} from './utils/vehicleUtils';
|
||||||
|
|
||||||
|
import i18n from './i18n-setup';
|
||||||
|
import http from './http';
|
||||||
|
|
||||||
|
import realCompositionsJSON from './data/realCompositions.json';
|
||||||
|
|
||||||
export const useStore = defineStore({
|
export const useStore = defineStore({
|
||||||
id: 'store',
|
id: 'store',
|
||||||
state: () =>
|
state: () => ({
|
||||||
({
|
chosenCar: null as ICarWagon | null,
|
||||||
chosenCar: null,
|
chosenLoco: null as ILocomotive | null,
|
||||||
chosenLoco: null,
|
chosenCargo: null as ICargo | null,
|
||||||
chosenCargo: null,
|
chosenVehicle: null as IVehicle | null,
|
||||||
chosenVehicle: null,
|
|
||||||
|
|
||||||
isColdStart: false,
|
isColdStart: false,
|
||||||
|
isDoubleManned: false,
|
||||||
|
|
||||||
showSupporter: false,
|
chosenLocoGroup: 'loco-electric' as LocoGroupType,
|
||||||
imageLoading: false,
|
chosenCarGroup: 'wagon-passenger' as WagonGroupType,
|
||||||
|
|
||||||
chosenLocoPower: 'loco-e',
|
stockList: [] as IStock[],
|
||||||
chosenCarUseType: 'car-passenger',
|
cargoOptions: [] as any[][],
|
||||||
|
|
||||||
stockList: [],
|
swapVehicles: false,
|
||||||
cargoOptions: [],
|
|
||||||
|
|
||||||
readyStockList: [],
|
chosenStockListIndex: -1,
|
||||||
|
|
||||||
swapVehicles: false,
|
vehiclePreviewSrc: '',
|
||||||
|
|
||||||
chosenStockListIndex: -1,
|
stockSectionMode: 'stock-list',
|
||||||
chosenRealStockName: undefined,
|
|
||||||
|
|
||||||
vehiclePreviewSrc: '',
|
isRandomizerCardOpen: false,
|
||||||
|
isRealStockListCardOpen: false,
|
||||||
|
|
||||||
stockSectionMode: 'stock-list',
|
vehiclesData: undefined as IVehicleData[] | undefined,
|
||||||
|
|
||||||
isRandomizerCardOpen: false,
|
lastFocusedElement: null as HTMLElement | null,
|
||||||
isRealStockListCardOpen: false,
|
|
||||||
|
|
||||||
stockData: undefined,
|
compatibleSimulatorVersion: '2024.1.2',
|
||||||
} as IStore),
|
}),
|
||||||
|
|
||||||
getters: {
|
getters: {
|
||||||
locoDataList: (state) => locoDataList(state),
|
locoDataList: (state) => locoDataList(state.vehiclesData),
|
||||||
carDataList: (state) => carDataList(state),
|
carDataList: (state) => carDataList(state.vehiclesData),
|
||||||
totalMass: (state) => totalMass(state),
|
vehicleDataList: (state) => [
|
||||||
totalLength: (state) => totalLength(state),
|
...locoDataList(state.vehiclesData),
|
||||||
maxStockSpeed: (state) => maxStockSpeed(state),
|
...carDataList(state.vehiclesData),
|
||||||
isTrainPassenger: (state) => isTrainPassenger(state),
|
],
|
||||||
chosenRealStock: (state) => chosenRealStock(state),
|
totalWeight: (state) => totalWeight(state.stockList),
|
||||||
acceptableMass: (state) => acceptableMass(state),
|
totalLength: (state) => totalLength(state.stockList),
|
||||||
|
maxStockSpeed: (state) => maxStockSpeed(state.stockList),
|
||||||
|
isTrainPassenger: (state) => isTrainPassenger(state.stockList),
|
||||||
|
acceptableWeight: (state) => acceptableWeight(state.stockList),
|
||||||
|
|
||||||
|
realCompositionList: (state) => {
|
||||||
|
if (!state.vehiclesData) return [];
|
||||||
|
|
||||||
|
return Object.keys(realCompositionsJSON).reduce<IRealComposition[]>((acc, key) => {
|
||||||
|
const [type, number, ...name] = key.split(' ');
|
||||||
|
|
||||||
|
const obj = {
|
||||||
|
number: number.replace(/_/g, '/'),
|
||||||
|
name: name.join(' '),
|
||||||
|
stockString: realCompositionsJSON[key as keyof typeof realCompositionsJSON],
|
||||||
|
type,
|
||||||
|
};
|
||||||
|
|
||||||
|
acc.push({
|
||||||
|
stockId: `${obj.type} ${obj.number} ${obj.name}`,
|
||||||
|
...obj,
|
||||||
|
});
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
},
|
||||||
|
|
||||||
|
stockSupportsColdStart: (state) => {
|
||||||
|
if (state.stockList.length == 0) return false;
|
||||||
|
|
||||||
|
if (!isTractionUnit(state.stockList[0].vehicleRef)) return false;
|
||||||
|
else if (state.stockList.length > 1) return false;
|
||||||
|
|
||||||
|
const headingLoco = state.stockList[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
state.vehiclesData?.find((vehicle) => vehicle.name == headingLoco.vehicleRef.type)?.group
|
||||||
|
.locoProps?.coldStart ?? false
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
stockSupportsDoubleManning: (state) => {
|
||||||
|
if (state.stockList.length == 0) return false;
|
||||||
|
if (!isTractionUnit(state.stockList[0].vehicleRef)) return false;
|
||||||
|
|
||||||
|
const headingLoco = state.stockList[0];
|
||||||
|
|
||||||
|
return (
|
||||||
|
state.vehiclesData?.find((vehicle) => vehicle.name == headingLoco.vehicleRef.type)?.group
|
||||||
|
.locoProps?.doubleManned ?? false
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async fetchStockInfoData() {
|
async fetchVehiclesAPI() {
|
||||||
const stockData = await (await fetch(`https://spythere.github.io/api/td2/data/stockInfo.json`)).json();
|
try {
|
||||||
this.stockData = stockData;
|
const vehiclesData = (await http.get<IVehiclesAPIResponse>('/api/getVehicles')).data;
|
||||||
|
this.vehiclesData = vehiclesData;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async setupAPIData() {
|
||||||
|
await this.fetchVehiclesAPI();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleRouting() {
|
handleRouting() {
|
||||||
@@ -82,5 +155,3 @@ export const useStore = defineStore({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,268 +1,335 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900&display=swap');
|
$breakpointMd: 960px;
|
||||||
|
$breakpointSm: 550px;
|
||||||
$breakpointMd: 960px;
|
|
||||||
$breakpointSm: 550px;
|
$bgColor: #2b3552;
|
||||||
|
$textColor: #fff;
|
||||||
$bgColor: #2b3552;
|
$secondaryColor: #1b1b1b;
|
||||||
$textColor: #fff;
|
$accentColor: #e4c428;
|
||||||
$secondaryColor: #222;
|
|
||||||
$accentColor: #e4c428;
|
$sponsorColor: gold;
|
||||||
|
$teamColor: #ff4848;
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 7px;
|
@font-face {
|
||||||
height: 7px;
|
font-family: 'Lato';
|
||||||
|
src:
|
||||||
&-track {
|
url('/fonts/Lato-Light.woff2') format('woff2'),
|
||||||
background: #222;
|
url('/fonts/Lato-Light.woff') format('woff');
|
||||||
border-radius: 0.5rem;
|
font-weight: 300;
|
||||||
}
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
&-thumb {
|
}
|
||||||
border-radius: 1rem;
|
|
||||||
background: #777;
|
@font-face {
|
||||||
}
|
font-family: 'Lato';
|
||||||
|
src:
|
||||||
&-corner {
|
url('/fonts/Lato-Bold.woff2') format('woff2'),
|
||||||
background: #222;
|
url('/fonts/Lato-Bold.woff') format('woff');
|
||||||
}
|
font-weight: bold;
|
||||||
}
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
body,
|
}
|
||||||
html {
|
|
||||||
margin: 0;
|
@font-face {
|
||||||
padding: 0;
|
font-family: 'Lato';
|
||||||
|
src:
|
||||||
font-family: 'Lato', sans-serif;
|
url('/fonts/Lato-Regular.woff2') format('woff2'),
|
||||||
|
url('/fonts/Lato-Regular.woff') format('woff');
|
||||||
background-color: $bgColor;
|
font-weight: normal;
|
||||||
overflow-x: hidden;
|
font-style: normal;
|
||||||
}
|
font-display: swap;
|
||||||
|
}
|
||||||
*,
|
|
||||||
*::before,
|
::-webkit-scrollbar {
|
||||||
*::after {
|
width: 7px;
|
||||||
box-sizing: border-box;
|
height: 7px;
|
||||||
}
|
|
||||||
|
&-track {
|
||||||
a {
|
background: #222;
|
||||||
color: white;
|
border-radius: 0.5rem;
|
||||||
text-decoration: none;
|
}
|
||||||
|
|
||||||
transition: color 250ms;
|
&-thumb {
|
||||||
|
border-radius: 1rem;
|
||||||
&:visited {
|
background: #777;
|
||||||
color: white;
|
}
|
||||||
}
|
|
||||||
|
&-corner {
|
||||||
&:hover,
|
background: #222;
|
||||||
&:focus {
|
}
|
||||||
color: $accentColor;
|
}
|
||||||
}
|
|
||||||
}
|
body,
|
||||||
|
html {
|
||||||
select,
|
margin: 0;
|
||||||
option,
|
padding: 0;
|
||||||
input,
|
|
||||||
button {
|
font-family: Lato, sans-serif;
|
||||||
font-family: 'Lato', sans-serif;
|
|
||||||
font-size: 1em;
|
background-color: $bgColor;
|
||||||
}
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
button {
|
|
||||||
border: none;
|
*,
|
||||||
outline: none;
|
*::before,
|
||||||
background: none;
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
padding: 0;
|
}
|
||||||
margin: 0;
|
|
||||||
|
a {
|
||||||
cursor: pointer;
|
color: white;
|
||||||
|
text-decoration: none;
|
||||||
font-size: 1em;
|
|
||||||
color: white;
|
transition: color 250ms;
|
||||||
|
|
||||||
&:hover {
|
&:visited {
|
||||||
color: $accentColor;
|
color: white;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
&:hover,
|
||||||
.btn {
|
&:focus {
|
||||||
padding: 0.4em 0.75em;
|
color: $accentColor;
|
||||||
|
}
|
||||||
outline: none;
|
}
|
||||||
background-color: #222;
|
|
||||||
border-radius: 8px;
|
select,
|
||||||
font-weight: bold;
|
option,
|
||||||
|
input,
|
||||||
transition: all 250ms;
|
button {
|
||||||
|
font-family: Lato, sans-serif;
|
||||||
&:hover {
|
font-size: 1em;
|
||||||
color: $accentColor;
|
}
|
||||||
}
|
|
||||||
|
button {
|
||||||
&.btn--outline {
|
border: none;
|
||||||
background: none;
|
outline: none;
|
||||||
font-weight: bold;
|
background: none;
|
||||||
outline: 1px solid $accentColor;
|
|
||||||
}
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
&:focus-visible {
|
|
||||||
color: $accentColor;
|
cursor: pointer;
|
||||||
outline: 1px solid white;
|
|
||||||
}
|
font-size: 1em;
|
||||||
|
color: white;
|
||||||
&[data-disabled='true'] {
|
|
||||||
user-select: none;
|
&:hover {
|
||||||
pointer-events: none;
|
color: $accentColor;
|
||||||
-moz-user-select: none;
|
}
|
||||||
-webkit-user-select: none;
|
|
||||||
|
&:focus-visible {
|
||||||
opacity: 0.75;
|
outline: 1px solid $accentColor;
|
||||||
background-color: #2b2b2b;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&--image {
|
[data-tooltip]:hover::after,
|
||||||
display: flex;
|
[data-tooltip]:focus::after {
|
||||||
justify-content: center;
|
position: absolute;
|
||||||
align-items: center;
|
transform: translateX(10px);
|
||||||
gap: 0.5em;
|
|
||||||
|
content: attr(data-tooltip);
|
||||||
img {
|
color: white;
|
||||||
width: 1.3em;
|
background: black;
|
||||||
vertical-align: middle;
|
padding: 0.5em;
|
||||||
}
|
max-width: 300px;
|
||||||
}
|
z-index: 100;
|
||||||
|
}
|
||||||
&--text {
|
|
||||||
font-weight: bold;
|
[data-tooltip] {
|
||||||
transition: all 250ms;
|
cursor: pointer;
|
||||||
background: none;
|
}
|
||||||
padding: 0;
|
|
||||||
|
.btn {
|
||||||
&:focus-visible {
|
padding: 0.4em 0.75em;
|
||||||
outline: 1px solid white;
|
|
||||||
}
|
outline: none;
|
||||||
}
|
background-color: $secondaryColor;
|
||||||
}
|
border-radius: 8px;
|
||||||
|
font-weight: bold;
|
||||||
select,
|
|
||||||
input[type='text'],
|
transition:
|
||||||
input[type='number'] {
|
color 150ms,
|
||||||
background: none;
|
background-color 150ms;
|
||||||
border: 2px solid #aaa;
|
|
||||||
outline: none;
|
&:hover {
|
||||||
|
color: $accentColor;
|
||||||
padding: 0.25em 0.35em;
|
}
|
||||||
|
|
||||||
color: white;
|
&.btn--outline {
|
||||||
font-size: 1em;
|
background: none;
|
||||||
|
font-weight: bold;
|
||||||
width: 18em;
|
outline: 1px solid $accentColor;
|
||||||
|
}
|
||||||
&:focus-visible {
|
|
||||||
border-color: $accentColor;
|
&:focus-visible {
|
||||||
}
|
color: $accentColor;
|
||||||
|
outline: 1px solid white;
|
||||||
&::placeholder {
|
}
|
||||||
color: #aaa;
|
|
||||||
}
|
&[data-chosen='true'] {
|
||||||
}
|
background-color: $accentColor;
|
||||||
|
color: black;
|
||||||
option {
|
|
||||||
color: white;
|
box-shadow: 0 0 5px 1px $accentColor;
|
||||||
border: none;
|
}
|
||||||
background-color: $bgColor;
|
|
||||||
}
|
&[data-disabled='true'] {
|
||||||
|
user-select: none;
|
||||||
ul {
|
pointer-events: none;
|
||||||
list-style: none;
|
-moz-user-select: none;
|
||||||
margin: 0;
|
-webkit-user-select: none;
|
||||||
padding: 0;
|
|
||||||
}
|
opacity: 0.75;
|
||||||
|
background-color: #2b2b2b;
|
||||||
.text {
|
}
|
||||||
&--accent {
|
|
||||||
color: $accentColor;
|
&--image {
|
||||||
}
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
&--grayed {
|
align-items: center;
|
||||||
color: #aaa;
|
gap: 0.5em;
|
||||||
}
|
|
||||||
}
|
img {
|
||||||
|
width: 1.3em;
|
||||||
.g-card {
|
vertical-align: middle;
|
||||||
position: fixed;
|
}
|
||||||
top: 1em;
|
}
|
||||||
left: 0;
|
|
||||||
|
&--text {
|
||||||
width: 100vw;
|
font-weight: bold;
|
||||||
height: 100vh;
|
transition: all 250ms;
|
||||||
|
background: none;
|
||||||
display: flex;
|
padding: 0;
|
||||||
justify-content: center;
|
|
||||||
|
&:focus-visible {
|
||||||
z-index: 200;
|
outline: 1px solid white;
|
||||||
|
}
|
||||||
&_bg {
|
}
|
||||||
position: fixed;
|
}
|
||||||
top: 0;
|
|
||||||
left: 0;
|
select,
|
||||||
|
input[type='text'],
|
||||||
width: 100vw;
|
input[type='number'] {
|
||||||
height: 100vh;
|
background: $bgColor;
|
||||||
|
border: 2px solid #aaa;
|
||||||
background-color: #000000aa;
|
outline: none;
|
||||||
z-index: 10;
|
|
||||||
}
|
padding: 0.25em 0.35em;
|
||||||
}
|
height: 100%;
|
||||||
|
|
||||||
.g-choice {
|
color: white;
|
||||||
input {
|
font-size: 1em;
|
||||||
display: none;
|
|
||||||
}
|
&:focus-visible {
|
||||||
|
border-color: $accentColor;
|
||||||
span {
|
}
|
||||||
padding: 0.25em 1em;
|
|
||||||
border-radius: 0.25em;
|
&::placeholder {
|
||||||
border: 2px solid white;
|
color: #aaa;
|
||||||
margin: 0.25em;
|
}
|
||||||
cursor: pointer;
|
}
|
||||||
|
|
||||||
transition: all 100ms ease;
|
option {
|
||||||
}
|
color: white;
|
||||||
|
border: none;
|
||||||
span:focus {
|
background-color: $bgColor;
|
||||||
color: $accentColor;
|
}
|
||||||
outline: none;
|
|
||||||
}
|
ul {
|
||||||
|
list-style: none;
|
||||||
label > input:checked + span {
|
margin: 0;
|
||||||
color: $accentColor;
|
padding: 0;
|
||||||
border-color: $accentColor;
|
}
|
||||||
}
|
|
||||||
}
|
.text {
|
||||||
|
&--accent {
|
||||||
// Vue Transition anims
|
color: $accentColor;
|
||||||
.slide-top {
|
}
|
||||||
&-enter-from,
|
|
||||||
&-leave-to {
|
&--grayed {
|
||||||
transform: translateY(-100%);
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
&-enter-active,
|
|
||||||
&-leave-active {
|
hr {
|
||||||
transition: transform 100ms ease-in-out;
|
height: 3px;
|
||||||
}
|
background-color: white;
|
||||||
}
|
outline: none;
|
||||||
|
margin: 0;
|
||||||
.card-appear {
|
}
|
||||||
&-enter-from,
|
|
||||||
&-leave-to {
|
.g-card {
|
||||||
opacity: 0;
|
position: fixed;
|
||||||
}
|
top: 1em;
|
||||||
|
left: 0;
|
||||||
&-enter-active,
|
|
||||||
&-leave-active {
|
width: 100vw;
|
||||||
transition: all 100ms ease-in-out;
|
height: 100vh;
|
||||||
}
|
|
||||||
}
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
z-index: 200;
|
||||||
|
|
||||||
|
&_bg {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
background-color: #000000aa;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.g-choice {
|
||||||
|
input {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
padding: 0.25em 1em;
|
||||||
|
border-radius: 0.25em;
|
||||||
|
border: 2px solid white;
|
||||||
|
margin: 0.25em;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
transition: all 100ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:focus {
|
||||||
|
color: $accentColor;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
label > input:checked + span {
|
||||||
|
color: $accentColor;
|
||||||
|
border-color: $accentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vue Transition anims
|
||||||
|
.slide-top {
|
||||||
|
&-enter-from,
|
||||||
|
&-leave-to {
|
||||||
|
transform: translateY(-100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&-enter-active,
|
||||||
|
&-leave-active {
|
||||||
|
transition: transform 100ms ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-appear {
|
||||||
|
&-enter-from,
|
||||||
|
&-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-enter-active,
|
||||||
|
&-leave-active {
|
||||||
|
transition: all 100ms ease-in-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,12 +8,18 @@
|
|||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
|
|
||||||
background-color: $secondaryColor;
|
background-color: $secondaryColor;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 1.35em;
|
font-size: 1.35em;
|
||||||
text-align: center;
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0.5em 0 0 0;
|
||||||
|
font-size: 1.15em;
|
||||||
|
color: #aaa;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -58,13 +64,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
|
||||||
height: 3px;
|
|
||||||
background-color: white;
|
|
||||||
outline: none;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (max-width: 470px) {
|
@media only screen and (max-width: 470px) {
|
||||||
.tab_attributes {
|
.tab_attributes {
|
||||||
label {
|
label {
|
||||||
@@ -77,4 +76,3 @@ hr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,119 +1,62 @@
|
|||||||
export type Vehicle = ILocomotive | ICarWagon;
|
export type IVehicle = ILocomotive | ICarWagon;
|
||||||
export type StockSectionMode = 'STOCK_LIST' | 'STOCK_GENERATOR';
|
export type StockSectionMode = 'STOCK_LIST' | 'STOCK_GENERATOR';
|
||||||
|
|
||||||
export interface IStore {
|
export type LocoGroupType = 'loco-electric' | 'loco-diesel' | 'unit-electric' | 'unit-diesel';
|
||||||
chosenCar: ICarWagon | null;
|
export type WagonGroupType = 'wagon-passenger' | 'wagon-freight';
|
||||||
chosenLoco: ILocomotive | null;
|
export type VehicleGroupType = LocoGroupType | WagonGroupType;
|
||||||
chosenCargo: ICargo | null;
|
export type RestrictionType = 'sponsorOnly' | 'teamOnly';
|
||||||
chosenVehicle: Vehicle | null;
|
|
||||||
|
|
||||||
isColdStart: boolean;
|
export interface IVehicleProps {
|
||||||
|
|
||||||
showSupporter: boolean;
|
|
||||||
imageLoading: boolean;
|
|
||||||
|
|
||||||
chosenLocoPower: string;
|
|
||||||
chosenCarUseType: string;
|
|
||||||
|
|
||||||
stockList: IStock[];
|
|
||||||
readyStockList: IReadyStockItem[];
|
|
||||||
cargoOptions: any[][];
|
|
||||||
|
|
||||||
chosenStockListIndex: number;
|
|
||||||
chosenRealStockName?: string;
|
|
||||||
|
|
||||||
swapVehicles: boolean;
|
|
||||||
vehiclePreviewSrc: string;
|
|
||||||
|
|
||||||
isRandomizerCardOpen: boolean;
|
|
||||||
isRealStockListCardOpen: boolean;
|
|
||||||
|
|
||||||
stockSectionMode: 'stock-list' | 'stock-generator' | 'number-generator' | 'wiki-list';
|
|
||||||
stockData?: IStockData;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TStockInfoKey = 'loco-e' | 'loco-s' | 'loco-ezt' | 'loco-szt' | 'car-passenger' | 'car-cargo';
|
|
||||||
|
|
||||||
export interface IStockProps {
|
|
||||||
type: string;
|
type: string;
|
||||||
|
speed: number;
|
||||||
length: number;
|
length: number;
|
||||||
mass: number;
|
weight: number;
|
||||||
cargo: string;
|
cargoTypes?: ICargo[];
|
||||||
}
|
coldStart?: boolean;
|
||||||
|
doubleManned?: boolean;
|
||||||
export interface IStockData {
|
|
||||||
version: string;
|
|
||||||
|
|
||||||
generator: {
|
|
||||||
passenger: any;
|
|
||||||
cargo: {
|
|
||||||
[key: string]: string[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
info: {
|
|
||||||
'car-cargo': [string, string, boolean, boolean, string][];
|
|
||||||
'car-passenger': [string, string, boolean, boolean, string][];
|
|
||||||
'loco-e': [string, string, string, string, boolean][];
|
|
||||||
'loco-s': [string, string, string, string, boolean][];
|
|
||||||
'loco-szt': [string, string, string, string, boolean][];
|
|
||||||
'loco-ezt': [string, string, string, string, boolean][];
|
|
||||||
};
|
|
||||||
|
|
||||||
props: IStockProps[];
|
|
||||||
|
|
||||||
usage: { [key: string]: string };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ILocomotive {
|
|
||||||
type: string;
|
|
||||||
power: string;
|
|
||||||
constructionType: string;
|
|
||||||
cabinType: string;
|
|
||||||
maxSpeed: number;
|
|
||||||
supportersOnly: boolean;
|
|
||||||
imageSrc: string;
|
|
||||||
|
|
||||||
mass: number;
|
|
||||||
length: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ICarWagon {
|
|
||||||
//"203V_PKPC_Fll_01","203V",true,false,"100",img
|
|
||||||
type: string;
|
|
||||||
useType: 'car-passenger' | 'car-cargo';
|
|
||||||
constructionType: string;
|
|
||||||
loadable: boolean;
|
|
||||||
supportersOnly: boolean;
|
|
||||||
maxSpeed: number;
|
|
||||||
imageSrc: string;
|
|
||||||
|
|
||||||
mass: number;
|
|
||||||
length: number;
|
|
||||||
cargoList: { id: string; totalMass: number }[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICargo {
|
export interface ICargo {
|
||||||
id: string;
|
id: string;
|
||||||
totalMass: number;
|
weight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IVehiclesAPIResponse = IVehicleData[];
|
||||||
|
|
||||||
|
export interface ILocomotive {
|
||||||
|
type: string;
|
||||||
|
group: LocoGroupType;
|
||||||
|
constructionType: string;
|
||||||
|
cabinType: string;
|
||||||
|
maxSpeed: number;
|
||||||
|
weight: number;
|
||||||
|
length: number;
|
||||||
|
coldStart: boolean;
|
||||||
|
doubleManned: boolean;
|
||||||
|
sponsorOnlyTimestamp: number;
|
||||||
|
teamOnly: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICarWagon {
|
||||||
|
type: string;
|
||||||
|
group: WagonGroupType;
|
||||||
|
constructionType: string;
|
||||||
|
loadable: boolean;
|
||||||
|
maxSpeed: number;
|
||||||
|
weight: number;
|
||||||
|
length: number;
|
||||||
|
cargoTypes: ICargo[];
|
||||||
|
sponsorOnlyTimestamp: number;
|
||||||
|
teamOnly: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStock {
|
export interface IStock {
|
||||||
id: string;
|
id: string;
|
||||||
type: string;
|
vehicleRef: IVehicle;
|
||||||
useType: string;
|
cargo?: ICargo;
|
||||||
constructionType: string;
|
|
||||||
length: number;
|
|
||||||
mass: number;
|
|
||||||
maxSpeed: number;
|
|
||||||
cargo?: { id: string; totalMass: number };
|
|
||||||
isLoco: boolean;
|
|
||||||
supportersOnly: boolean;
|
|
||||||
count: number;
|
|
||||||
imgSrc?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IReadyStockItem {
|
export interface IRealComposition {
|
||||||
stockId: string;
|
stockId: string;
|
||||||
stockString: string;
|
stockString: string;
|
||||||
type: string;
|
type: string;
|
||||||
@@ -121,3 +64,37 @@ export interface IReadyStockItem {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IVehicleData {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
cabinName: string | null;
|
||||||
|
restrictions: IVehicleRestrictions | null;
|
||||||
|
vehicleGroupsId: number;
|
||||||
|
group: IVehicleGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVehicleRestrictions {
|
||||||
|
sponsorOnly: number | null;
|
||||||
|
teamOnly: boolean | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVehicleGroup {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
speed: number;
|
||||||
|
length: number;
|
||||||
|
weight: number;
|
||||||
|
cargoTypes: IVehicleCargoType[] | null;
|
||||||
|
locoProps: IVehicleLocoProps | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVehicleCargoType {
|
||||||
|
id: string;
|
||||||
|
weight: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVehicleLocoProps {
|
||||||
|
coldStart: boolean;
|
||||||
|
doubleManned: boolean;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
const supportedConstructions = ['303e', '203e'];
|
|
||||||
|
|
||||||
export function locoSupportsColdStart(constructionType: string) {
|
|
||||||
return new RegExp(`(${supportedConstructions.join('|')})`).test(constructionType);
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import speedLimitTable from '../constants/speedLimits.json';
|
|
||||||
export type LocoType = keyof typeof speedLimitTable;
|
|
||||||
|
|
||||||
export const calculateSpeedLimit = (locoType: LocoType, stockMass: number, isTrainPassenger: boolean) => {
|
|
||||||
const speedTable = speedLimitTable[locoType][isTrainPassenger ? 'passenger' : 'cargo'];
|
|
||||||
|
|
||||||
if (!speedTable) return undefined;
|
|
||||||
|
|
||||||
let speedLimit = 0;
|
|
||||||
for (let mass in speedTable) if (stockMass > Number(mass)) speedLimit = (speedTable as any)[mass];
|
|
||||||
|
|
||||||
return speedLimit;
|
|
||||||
};
|
|
||||||
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import speedLimits from '../constants/speedLimits.json';
|
||||||
|
import massLimits from '../constants/massLimits.json';
|
||||||
|
|
||||||
|
export type SpeedLimitLocoType = keyof typeof speedLimits;
|
||||||
|
export type MassLimitLocoType = keyof typeof massLimits;
|
||||||
|
|
||||||
|
export function calculateSpeedLimit(
|
||||||
|
locoType: SpeedLimitLocoType,
|
||||||
|
stockTotalWeight: number,
|
||||||
|
stockCount: number,
|
||||||
|
isTrainPassenger: boolean
|
||||||
|
) {
|
||||||
|
if (speedLimits[locoType] === undefined) return 0;
|
||||||
|
|
||||||
|
if (stockCount == 1) return speedLimits[locoType]['none'];
|
||||||
|
|
||||||
|
const stockType = isTrainPassenger ? 'passenger' : 'cargo';
|
||||||
|
const speedTable = speedLimits[locoType][stockType];
|
||||||
|
|
||||||
|
if (!speedTable) return undefined;
|
||||||
|
|
||||||
|
let speedLimit = 0;
|
||||||
|
for (const mass in speedTable)
|
||||||
|
if (stockTotalWeight > Number(mass)) speedLimit = (speedTable as any)[mass];
|
||||||
|
|
||||||
|
return speedLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateMassLimit(locoType: MassLimitLocoType, isTrainPassenger: boolean) {
|
||||||
|
if (massLimits[locoType] === undefined) return 0;
|
||||||
|
|
||||||
|
return massLimits[locoType][isTrainPassenger ? 0 : 1] || 0;
|
||||||
|
}
|
||||||
@@ -1,161 +1,129 @@
|
|||||||
import { EVehicleUseType } from '../enums/EVehicleUseType';
|
import {
|
||||||
import { ICarWagon, ILocomotive, IStore, TStockInfoKey } from '../types';
|
ICarWagon,
|
||||||
import { LocoType, calculateSpeedLimit } from './speedLimitUtils';
|
ILocomotive,
|
||||||
|
IStock,
|
||||||
|
IVehicleData,
|
||||||
|
IVehiclesAPIResponse,
|
||||||
|
LocoGroupType,
|
||||||
|
WagonGroupType,
|
||||||
|
} from '../types';
|
||||||
|
import {
|
||||||
|
MassLimitLocoType,
|
||||||
|
SpeedLimitLocoType,
|
||||||
|
calculateMassLimit,
|
||||||
|
calculateSpeedLimit,
|
||||||
|
} from './vehicleLimitsUtils';
|
||||||
|
|
||||||
export function isLocomotive(vehicle: ILocomotive | ICarWagon): vehicle is ILocomotive {
|
export function isTractionUnit(vehicle: ILocomotive | ICarWagon): vehicle is ILocomotive {
|
||||||
return (vehicle as ILocomotive).power !== undefined;
|
return (vehicle as ILocomotive).cabinType !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function locoDataList(state: IStore) {
|
export function locoDataList(vehiclesData: IVehicleData[] | undefined) {
|
||||||
if (!state.stockData) return [];
|
if (!vehiclesData) return [];
|
||||||
|
|
||||||
const stockData = state.stockData;
|
return vehiclesData.reduce<ILocomotive[]>((acc, data) => {
|
||||||
|
if (!data.cabinName) return acc;
|
||||||
|
|
||||||
return Object.keys(stockData.info).reduce((acc, vehiclePower) => {
|
acc.push({
|
||||||
if (!vehiclePower.startsWith('loco')) return acc;
|
group: data.type as LocoGroupType,
|
||||||
|
type: data.name,
|
||||||
|
|
||||||
const locoVehiclesData = stockData.info[vehiclePower as 'loco-e' | 'loco-s' | 'loco-ezt' | 'loco-szt'];
|
constructionType: data.group.name,
|
||||||
|
cabinType: data.cabinName,
|
||||||
|
|
||||||
locoVehiclesData.forEach((loco) => {
|
sponsorOnlyTimestamp: data.restrictions?.sponsorOnly ?? 0,
|
||||||
if (state.showSupporter && !loco[4]) return;
|
teamOnly: data.restrictions?.teamOnly ?? false,
|
||||||
|
|
||||||
const [type, constructionType, cabinType, maxSpeed, supportersOnly] = loco;
|
maxSpeed: data.group.speed,
|
||||||
const locoProps = stockData.props.find((prop) => constructionType == prop.type);
|
length: data.group.length,
|
||||||
|
weight: data.group.weight,
|
||||||
|
|
||||||
acc.push({
|
coldStart: data.group.locoProps?.coldStart ?? false,
|
||||||
power: vehiclePower,
|
doubleManned: data.group.locoProps?.doubleManned ?? false,
|
||||||
type,
|
|
||||||
constructionType,
|
|
||||||
cabinType,
|
|
||||||
maxSpeed: Number(maxSpeed),
|
|
||||||
supportersOnly,
|
|
||||||
imageSrc: '',
|
|
||||||
|
|
||||||
length: locoProps?.length && type.startsWith('2EN') ? locoProps.length * 2 : locoProps?.length || 0,
|
|
||||||
mass: locoProps?.mass && type.startsWith('2EN') ? 253 : locoProps?.mass || 0,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as ILocomotive[]);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function carDataList(state: IStore) {
|
export function carDataList(vehiclesData: IVehicleData[] | undefined) {
|
||||||
if (!state.stockData) return [];
|
if (!vehiclesData) return [];
|
||||||
|
|
||||||
const stockData = state.stockData;
|
return vehiclesData.reduce<ICarWagon[]>((acc, data) => {
|
||||||
|
if (data.cabinName !== null) return acc;
|
||||||
|
|
||||||
return Object.keys(stockData.info).reduce((acc, vehicleUseType) => {
|
acc.push({
|
||||||
if (!vehicleUseType.startsWith('car')) return acc;
|
group: data.type as WagonGroupType,
|
||||||
|
type: data.name,
|
||||||
|
constructionType: data.group.name,
|
||||||
|
loadable: data.group.cargoTypes !== null && data.group.cargoTypes.length > 0,
|
||||||
|
cargoTypes: data.group?.cargoTypes ?? [],
|
||||||
|
|
||||||
const carVehiclesData = stockData.info[vehicleUseType as 'car-passenger' | 'car-cargo'];
|
sponsorOnlyTimestamp: data.restrictions?.sponsorOnly ?? 0,
|
||||||
|
teamOnly: data.restrictions?.teamOnly ?? false,
|
||||||
|
|
||||||
carVehiclesData.forEach((car) => {
|
maxSpeed: data.group.speed,
|
||||||
if (state.showSupporter && !car[3]) return;
|
length: data.group.length,
|
||||||
|
weight: data.group.weight,
|
||||||
const carPropsData = stockData.props.find((v) => car[0].toString().startsWith(v.type));
|
|
||||||
|
|
||||||
acc.push({
|
|
||||||
useType: vehicleUseType as 'car-passenger' | 'car-cargo',
|
|
||||||
type: car[0],
|
|
||||||
constructionType: car[1],
|
|
||||||
loadable: car[2],
|
|
||||||
supportersOnly: car[3],
|
|
||||||
maxSpeed: Number(car[4]),
|
|
||||||
imageSrc: '',
|
|
||||||
cargoList:
|
|
||||||
!carPropsData || carPropsData.cargo === null
|
|
||||||
? []
|
|
||||||
: carPropsData.cargo.split(';').map((cargo) => ({
|
|
||||||
id: cargo.split(':')[0],
|
|
||||||
totalMass: Number(cargo.split(':')[1]),
|
|
||||||
})),
|
|
||||||
|
|
||||||
mass: carPropsData?.mass || 0,
|
|
||||||
length: carPropsData?.length || 0,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, [] as ICarWagon[]);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function totalMass(state: IStore) {
|
export function totalWeight(stockList: IStock[]) {
|
||||||
return ~~state.stockList.reduce(
|
return stockList.reduce(
|
||||||
(acc, stock) => acc + (stock.cargo ? stock.cargo.totalMass : stock.mass) * stock.count,
|
(acc, stock) => acc + (stock.vehicleRef.weight + (stock.cargo?.weight ?? 0)),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function totalLength(state: IStore) {
|
export function totalLength(stockList: IStock[]) {
|
||||||
return state.stockList.reduce((acc, stock) => acc + stock.length * stock.count, 0);
|
return stockList.reduce((acc, stock) => acc + stock.vehicleRef.length, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function maxStockSpeed(state: IStore) {
|
export function maxStockSpeed(stockList: IStock[]) {
|
||||||
const stockSpeedLimit = state.stockList.reduce(
|
const stockSpeedLimit = stockList.reduce(
|
||||||
(acc, stock) => (stock.maxSpeed < acc || acc == 0 ? stock.maxSpeed : acc),
|
(acc, stock) => (stock.vehicleRef.maxSpeed < acc || acc == 0 ? stock.vehicleRef.maxSpeed : acc),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const headingLoco = state.stockList[0]?.isLoco ? state.stockList[0] : undefined;
|
const headingLoco =
|
||||||
|
stockList[0] && isTractionUnit(stockList[0].vehicleRef) ? stockList[0] : undefined;
|
||||||
|
|
||||||
if (!headingLoco) return stockSpeedLimit;
|
if (!headingLoco) return stockSpeedLimit;
|
||||||
|
|
||||||
const locoType = headingLoco.type.split('-')[0];
|
const locoType = headingLoco.vehicleRef.type.split('-')[0];
|
||||||
|
|
||||||
if (/^(EN|2EN|SN)/.test(locoType)) return stockSpeedLimit;
|
if (/^(EN|2EN|SN)/.test(locoType)) return stockSpeedLimit;
|
||||||
|
|
||||||
const stockMass = totalMass(state);
|
const speedLimitByMass = calculateSpeedLimit(
|
||||||
|
locoType as SpeedLimitLocoType,
|
||||||
const speedLimitByMass = calculateSpeedLimit(locoType as LocoType, stockMass, isTrainPassenger(state));
|
totalWeight(stockList),
|
||||||
|
stockList.length,
|
||||||
|
isTrainPassenger(stockList)
|
||||||
|
);
|
||||||
|
|
||||||
return speedLimitByMass ? Math.min(stockSpeedLimit, speedLimitByMass) : stockSpeedLimit;
|
return speedLimitByMass ? Math.min(stockSpeedLimit, speedLimitByMass) : stockSpeedLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function acceptableMass(state: IStore) {
|
export function acceptableWeight(stockList: IStock[]) {
|
||||||
if (state.stockList.length == 0 || !state.stockList[0].isLoco) return 0;
|
if (stockList.length == 0 || !isTractionUnit(stockList[0].vehicleRef)) return 0;
|
||||||
const activeLocomotiveType = state.stockList[0].type;
|
|
||||||
|
|
||||||
if (/^SM/.test(activeLocomotiveType)) return 2400;
|
const activeLocomotiveType = stockList[0].vehicleRef.type.split('-')[0];
|
||||||
|
|
||||||
// Elektryczne EU07 / EP07 / EP08 / ET41
|
const locoMassLimit = calculateMassLimit(
|
||||||
|
activeLocomotiveType as MassLimitLocoType,
|
||||||
|
isTrainPassenger(stockList)
|
||||||
|
);
|
||||||
|
|
||||||
// Pasażerski elektr.
|
return locoMassLimit;
|
||||||
if (isTrainPassenger(state)) {
|
|
||||||
if (/^(EU|EP)/.test(activeLocomotiveType)) return 650;
|
|
||||||
if (/^ET/.test(activeLocomotiveType)) return 700;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Towarowy / inny elektr.
|
|
||||||
if (/^EU/.test(activeLocomotiveType)) return 2000;
|
|
||||||
if (/^ET/.test(activeLocomotiveType)) return 4000;
|
|
||||||
if (/^EP/.test(activeLocomotiveType)) return 650;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isTrainPassenger(state: IStore) {
|
export function isTrainPassenger(stockList: IStock[]) {
|
||||||
if (state.stockList.length == 0) return false;
|
if (stockList.length == 0) return false;
|
||||||
if (state.stockList.every((stock) => stock.isLoco)) return false;
|
if (stockList.every((stock) => isTractionUnit(stock.vehicleRef))) return false;
|
||||||
|
|
||||||
return state.stockList
|
return stockList
|
||||||
.filter((stock) => !stock.isLoco)
|
.filter((stock) => !isTractionUnit(stock.vehicleRef))
|
||||||
.every((stock) => stock.useType === EVehicleUseType.CAR_PASSENGER);
|
.every((stock) => stock.vehicleRef.group === 'wagon-passenger');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function chosenRealStock(state: IStore) {
|
|
||||||
const currentStockString = state.stockList
|
|
||||||
.reduce((acc, stock) => {
|
|
||||||
for (let i = 0; i < stock.count; i++) acc.push(stock.type);
|
|
||||||
return acc;
|
|
||||||
}, [] as string[])
|
|
||||||
.join(';');
|
|
||||||
|
|
||||||
const realStockObj = state.readyStockList.find((readyStock) => readyStock.stockString == currentStockString);
|
|
||||||
|
|
||||||
state.chosenRealStockName = realStockObj?.stockId ?? undefined;
|
|
||||||
|
|
||||||
return realStockObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +1,37 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
<MainContainer />
|
<MainContainer />
|
||||||
<Footer />
|
<FooterVue />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { useStore } from '../store';
|
import { useStore } from '../store';
|
||||||
|
|
||||||
import MainContainer from '../components/app/MainContainer.vue';
|
import MainContainer from '../components/app/MainContainer.vue';
|
||||||
import Footer from '../components/app/Footer.vue';
|
import FooterVue from '../components/app/Footer.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
MainContainer,
|
MainContainer,
|
||||||
Footer,
|
FooterVue,
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
store: useStore(),
|
store: useStore(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.app-container {
|
.app-container {
|
||||||
min-height: 100vh;
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
display: flex;
|
align-items: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
}
|
min-height: 100vh;
|
||||||
</style>
|
padding: 0.5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import type { DefineComponent } from 'vue'
|
import type { DefineComponent } from 'vue';
|
||||||
const component: DefineComponent<{}, {}, any>
|
const component: DefineComponent<{}, {}, any>;
|
||||||
export default component
|
export default component;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,29 +6,33 @@ import { VitePWA } from 'vite-plugin-pwa';
|
|||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
server: {
|
server: {
|
||||||
port: 2137,
|
port: 2138,
|
||||||
|
},
|
||||||
|
preview: {
|
||||||
|
port: 4138,
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
VitePWA({
|
VitePWA({
|
||||||
registerType: 'autoUpdate',
|
registerType: 'autoUpdate',
|
||||||
|
|
||||||
|
includeAssets: ['/images/*.{png,svg,jpg}', '/fonts/*.{woff,woff2,ttf}'],
|
||||||
|
|
||||||
|
devOptions: {
|
||||||
|
suppressWarnings: true,
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
|
||||||
workbox: {
|
workbox: {
|
||||||
// globPatterns: ['**/*.{js,css,html,png,svg,img}'],
|
cleanupOutdatedCaches: true,
|
||||||
|
globPatterns: ['**/*.{js,css,html,jpg,png,svg,img,woff,woff2}'],
|
||||||
|
|
||||||
runtimeCaching: [
|
runtimeCaching: [
|
||||||
{
|
{
|
||||||
urlPattern: /^https:\/\/rj.td2.info.pl\/dist\/img\/thumbnails\/.*/i,
|
urlPattern: /^https:\/\/.*\.spythere\.eu\/.*/i,
|
||||||
handler: 'CacheFirst',
|
handler: 'StaleWhileRevalidate',
|
||||||
options: {
|
options: {
|
||||||
cacheName: 'swdr-images-cache',
|
cacheName: 'spythere-cache',
|
||||||
expiration: {
|
|
||||||
maxEntries: 50,
|
|
||||||
maxAgeSeconds: 60 * 60 * 24 * 7, // <== 7 days
|
|
||||||
},
|
|
||||||
cacheableResponse: {
|
|
||||||
statuses: [404],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -36,5 +40,3 @@ export default defineConfig({
|
|||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||