mirror of
https://github.com/Spythere/pojazdownik.git
synced 2026-05-03 05:18:10 +00:00
Poprawki funkcjonalności
This commit is contained in:
@@ -3,6 +3,13 @@
|
||||
<img :src="store.vehiclePreviewSrc" alt="preview" />
|
||||
</div>
|
||||
|
||||
<div class="g-card-dimmer" v-if="store.isRandomizerCardOpen" @click="store.isRandomizerCardOpen = false"></div>
|
||||
<div class="g-card-dimmer" v-if="store.isRealStockListCardOpen" @click="store.isRealStockListCardOpen = false"></div>
|
||||
|
||||
<keep-alive>
|
||||
<RandomizerCard v-if="store.isRandomizerCardOpen" />
|
||||
</keep-alive>
|
||||
|
||||
<div class="app_container">
|
||||
<header>
|
||||
<img :src="logoImage" alt="logo pojazdownik" />
|
||||
@@ -43,12 +50,14 @@ import ListSection from './components/ListSection.vue';
|
||||
import logoImage from './assets/logo.svg';
|
||||
import { useStore } from './store';
|
||||
import TrainImage from './components/TrainImageSection.vue';
|
||||
import RandomizerCard from './components/RandomizerCard.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
ListSection,
|
||||
InputsSection,
|
||||
TrainImage,
|
||||
RandomizerCard,
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
|
||||
@@ -7,10 +7,6 @@
|
||||
<span></span>
|
||||
<button class="btn" @click="shuffleCars">TASUJ WAGONY</button>
|
||||
<button class="btn" @click="store.isRandomizerCardOpen = true">LOSUJ SKŁAD</button>
|
||||
|
||||
<transition name="card-anim">
|
||||
<randomizer-card v-if="store.isRandomizerCardOpen" />
|
||||
</transition>
|
||||
</div>
|
||||
|
||||
<div class="stock-list_specs">
|
||||
@@ -31,16 +27,20 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- <div class="warnings">
|
||||
<div class="warning" v-if="warnings.locoNotSuitable.value">
|
||||
<div class="warnings">
|
||||
<div class="warning" v-if="locoNotSuitable">
|
||||
Lokomotywy EP07 i EP08 są przeznaczone jedynie do ruchu pasażerskiego!
|
||||
</div>
|
||||
|
||||
<div class="warning" v-if="warnings.trainTooLong.value">
|
||||
Ten skład jest za długi (pasażerskie max. 350m, towarowe max. 650m)!
|
||||
<div class="warning" v-if="trainTooLong && store.isTrainPassenger">
|
||||
Maksymalna długość składów pasażerskich nie może przekraczać 350m!
|
||||
</div>
|
||||
|
||||
<div class="warning" v-if="warnings.trainTooHeavy.value">
|
||||
<div class="warning" v-if="trainTooLong && !store.isTrainPassenger">
|
||||
Maksymalna długość składów innych niż pasażerskie nie może przekraczać 650m!
|
||||
</div>
|
||||
|
||||
<div class="warning" v-if="trainTooHeavy">
|
||||
Ten skład jest za ciężki! Sprawdź
|
||||
<a
|
||||
target="_blank"
|
||||
@@ -50,8 +50,8 @@
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="warning" v-if="warnings.tooManyLocos.value">Ten skład posiada za dużo pojazdów trakcyjnych!</div>
|
||||
</div> -->
|
||||
<div class="warning" v-if="tooManyLocomotives">Ten skład posiada za dużo pojazdów trakcyjnych!</div>
|
||||
</div>
|
||||
|
||||
<ul ref="list">
|
||||
<li v-if="store.stockList.length == 0" class="list-empty">
|
||||
@@ -126,10 +126,13 @@ import removeIcon from '../assets/remove-icon.svg';
|
||||
import lowerIcon from '../assets/lower-icon.svg';
|
||||
import higherIcon from '../assets/higher-icon.svg';
|
||||
import { useStore } from '../store';
|
||||
import warningsMixin from '../mixins/warningsMixin';
|
||||
|
||||
export default defineComponent({
|
||||
components: { RandomizerCard, TrainImage },
|
||||
|
||||
mixins: [warningsMixin],
|
||||
|
||||
setup() {
|
||||
const store = useStore();
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<template>
|
||||
<div class="g-card-dimmer" v-if="store.isRandomizerCardOpen" @click="store.isRandomizerCardOpen = false"></div>
|
||||
<div class="card">
|
||||
|
||||
<div class="wrapper">
|
||||
<div class="wrapper" ref="cardWrapper" tabindex="0">
|
||||
<!-- <h1>LOSUJ SKŁAD <img :src="icons.randomize" alt="losuj skład" /></h1>
|
||||
|
||||
<h3>
|
||||
@@ -13,7 +11,7 @@
|
||||
<div class="car-preview">
|
||||
<div class="image-wrapper">
|
||||
<div v-if="isPreviewLoading" class="loading">ŁADOWANIE...</div>
|
||||
<img v-if="focusedCar" :src="focusedCar?.imageSrc" :alt="focusedCar.type" @load="onPreviewLoaded" />
|
||||
<img v-if="focusedCar" :src="focusedCar?.imageSrc" :alt="focusedCar.type" />
|
||||
</div>
|
||||
<b class="text--accent" v-if="focusedCar">
|
||||
{{ focusedCar.type.split('_')[0] }} {{ focusedCar.type.split('_')[2] }}
|
||||
@@ -29,11 +27,12 @@
|
||||
<div>
|
||||
<button
|
||||
class="btn choice-btn"
|
||||
v-for="carType in carTypeList.filter((_, i) => i < 15)"
|
||||
v-for="carType in passengerCarTypeList"
|
||||
:key="carType"
|
||||
@click="toggleCarType(carType)"
|
||||
@mouseenter="displayPreview(carType)"
|
||||
:class="{ chosen: chosenCarTypes.includes(carType) }"
|
||||
@focus="displayPreview(carType)"
|
||||
:data-selected="chosenCarTypes.includes(carType)"
|
||||
>
|
||||
{{ carType }}
|
||||
</button>
|
||||
@@ -42,11 +41,12 @@
|
||||
<div style="margin-top: 0.5em">
|
||||
<button
|
||||
class="btn choice-btn"
|
||||
v-for="carType in carTypeList.filter((_, i) => i >= 15)"
|
||||
v-for="carType in cargoCarTypeList"
|
||||
:key="carType"
|
||||
@click="toggleCarType(carType)"
|
||||
@mouseenter="displayPreview(carType)"
|
||||
:class="{ chosen: chosenCarTypes.includes(carType) }"
|
||||
@focus="displayPreview(carType)"
|
||||
:data-selected="chosenCarTypes.includes(carType)"
|
||||
>
|
||||
{{ carType }}
|
||||
</button>
|
||||
@@ -75,9 +75,14 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div style="margin: 1em 0">
|
||||
<button class="btn choice-btn" :class="{ chosen: loadableByDefault }" @click="changeLoadableByDefault">
|
||||
DOMYŚLNIE ŁADOWNE
|
||||
<div class="cargo-filling g-choice" style="margin: 1em 0">
|
||||
<button
|
||||
class="btn choice-btn"
|
||||
v-for="mode in cargoFillModeList"
|
||||
:data-selected="mode.id == chosenCargoFillMode"
|
||||
@click="changeCargoFillMode(mode.id)"
|
||||
>
|
||||
{{ mode.value }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -90,7 +95,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
import carUsage from '../data/carUsage.json';
|
||||
import { ICarWagon, ILocomotive, ICargo } from '../types';
|
||||
@@ -98,6 +103,8 @@ import { ICarWagon, ILocomotive, ICargo } from '../types';
|
||||
import randomizeIcon from '../assets/randomize-icon.svg';
|
||||
import { useStore } from '../store';
|
||||
|
||||
type CargoFillModeType = 'cargo-random' | 'cargo-filled' | 'cargo-empty';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
@@ -105,30 +112,80 @@ export default defineComponent({
|
||||
return {
|
||||
store,
|
||||
|
||||
carTypeList: store.carDataList.reduce((list, car) => {
|
||||
const type = car.type.split('_')[0];
|
||||
carTypeList: store.carDataList
|
||||
.sort((a, b) => (b.useType == 'car-passenger' ? 1 : -1))
|
||||
.reduce((list, car) => {
|
||||
const type = car.type.split('_')[0];
|
||||
|
||||
if (list.includes(type)) return list;
|
||||
if (list.includes(type)) return list;
|
||||
|
||||
list.push(type);
|
||||
list.push(type);
|
||||
|
||||
return list;
|
||||
}, [] as string[]),
|
||||
return list;
|
||||
}, [] as string[]),
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
(this.$refs['cardWrapper'] as any).focus();
|
||||
},
|
||||
|
||||
computed: {
|
||||
passengerCarTypeList() {
|
||||
return this.store.carDataList
|
||||
.reduce((list, car) => {
|
||||
if (car.useType != 'car-passenger') return list;
|
||||
|
||||
const type = car.type.split('_')[0];
|
||||
if (!list.includes(type)) list.push(type);
|
||||
|
||||
return list;
|
||||
}, [] as string[])
|
||||
.sort((a, b) => (a > b ? 1 : -1));
|
||||
},
|
||||
|
||||
cargoCarTypeList() {
|
||||
return this.store.carDataList
|
||||
.reduce((list, car) => {
|
||||
if (car.useType != 'car-cargo') return list;
|
||||
|
||||
const type = car.type.split('_')[0];
|
||||
if (!list.includes(type)) list.push(type);
|
||||
|
||||
return list;
|
||||
}, [] as string[])
|
||||
.sort((a, b) => (a > b ? 1 : -1));
|
||||
},
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
randomStockMass: 1500,
|
||||
randomStockLength: 650,
|
||||
chosenCarTypes: [] as string[],
|
||||
|
||||
cargoFillModeList: [
|
||||
{
|
||||
id: 'cargo-random',
|
||||
value: 'LOSOWO',
|
||||
},
|
||||
{
|
||||
id: 'cargo-filled',
|
||||
value: 'ŁADOWNE',
|
||||
},
|
||||
{
|
||||
id: 'cargo-empty',
|
||||
value: 'PRÓŻNE',
|
||||
},
|
||||
] as { id: CargoFillModeType; value: string }[],
|
||||
|
||||
chosenCargoFillMode: 'cargo-random' as CargoFillModeType,
|
||||
|
||||
icons: {
|
||||
randomize: randomizeIcon,
|
||||
},
|
||||
|
||||
focusedCar: null as ICarWagon | null,
|
||||
isPreviewLoading: false,
|
||||
loadableByDefault: false,
|
||||
|
||||
cargoTypes: [
|
||||
'203V',
|
||||
@@ -162,15 +219,10 @@ export default defineComponent({
|
||||
if (this.focusedCar?.type == list[randIndex].type) return;
|
||||
|
||||
this.focusedCar = list[randIndex];
|
||||
this.isPreviewLoading = true;
|
||||
},
|
||||
|
||||
onPreviewLoaded() {
|
||||
this.isPreviewLoading = false;
|
||||
},
|
||||
|
||||
changeLoadableByDefault() {
|
||||
this.loadableByDefault = !this.loadableByDefault;
|
||||
changeCargoFillMode(mode: CargoFillModeType) {
|
||||
this.chosenCargoFillMode = mode;
|
||||
},
|
||||
|
||||
randomize() {
|
||||
@@ -234,7 +286,12 @@ export default defineComponent({
|
||||
if (randCar.length * count + totalStockLength >= this.randomStockLength) break;
|
||||
|
||||
let randCargo = undefined;
|
||||
let randNum = this.loadableByDefault ? 1 : Math.random();
|
||||
let randNum =
|
||||
this.chosenCargoFillMode == 'cargo-filled'
|
||||
? 1
|
||||
: this.chosenCargoFillMode == 'cargo-empty'
|
||||
? 0
|
||||
: Math.random();
|
||||
if (randCar.cargoList.length != 0 && randNum >= 0.6)
|
||||
randCargo = randCar.cargoList[Math.floor(Math.random() * randCar.cargoList.length)];
|
||||
|
||||
@@ -310,7 +367,7 @@ export default defineComponent({
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* @import url('../styles/global.scss'); */
|
||||
@import '../styles/global.scss';
|
||||
|
||||
.card {
|
||||
position: fixed;
|
||||
@@ -376,12 +433,10 @@ input {
|
||||
.car-choice div {
|
||||
display: grid;
|
||||
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
justify-content: center;
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
/* display: flex; */
|
||||
/* flex-wrap: wrap; */
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
@@ -390,19 +445,18 @@ button.choice-btn {
|
||||
color: gray;
|
||||
border-color: gray;
|
||||
|
||||
*:focus {
|
||||
color: white;
|
||||
&[data-selected='true'] {
|
||||
color: $accentColor;
|
||||
border-color: $accentColor;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
border-color: white;
|
||||
}
|
||||
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
button.chosen {
|
||||
border-color: gold;
|
||||
color: gold;
|
||||
}
|
||||
|
||||
.car-preview {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<template>
|
||||
<div class="g-card-dimmer" v-if="store.isRealStockListCardOpen" @click="store.isRealStockListCardOpen = false"></div>
|
||||
<div class="ready-stock-list" v-if="store.isRealStockListCardOpen">
|
||||
<div class="top-sticky">
|
||||
<button class="btn btn--text exit" @click="store.isRealStockListCardOpen = false">< POWRÓT</button>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
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() {
|
||||
const totalMass = this.store.totalMass;
|
||||
const isTrainPassenger = this.store.isTrainPassenger;
|
||||
const stockList = this.store.stockList;
|
||||
|
||||
if (stockList.length == 0 || !stockList[0].isLoco) return false;
|
||||
|
||||
const activeLocomotiveType = stockList[0].type;
|
||||
|
||||
// Spalinowy SM
|
||||
if (/^SM/.test(activeLocomotiveType) && totalMass > 2400) return true;
|
||||
|
||||
// Elektryczne EU07 / EP07 / EP08 / ET41
|
||||
|
||||
// Pasażerski elektr.
|
||||
if (isTrainPassenger) {
|
||||
if (/^(EU|EP)/.test(activeLocomotiveType) && totalMass > 650) return true;
|
||||
if (/^ET/.test(activeLocomotiveType) && totalMass > 700) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Towarowy / inny elektr.
|
||||
if (/^EU/.test(activeLocomotiveType) && totalMass > 2000) return true;
|
||||
if (/^ET/.test(activeLocomotiveType) && totalMass > 4000) return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
locoNotSuitable() {
|
||||
return (
|
||||
!this.store.isTrainPassenger &&
|
||||
this.store.stockList.length > 1 &&
|
||||
!this.store.stockList.every((stock) => stock.isLoco) &&
|
||||
this.store.stockList.find((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
-1
@@ -1,4 +1,4 @@
|
||||
import { ICarWagon, ILocomotive, IStore } from './types';
|
||||
import { IStore } from './types';
|
||||
import { defineStore } from 'pinia';
|
||||
import { carDataList, isTrainPassenger, locoDataList, maxStockSpeed, totalLength, totalMass } from './utils/vehicleUtils';
|
||||
|
||||
|
||||
+34
-13
@@ -93,12 +93,7 @@ button.btn {
|
||||
|
||||
transition: all 250ms;
|
||||
|
||||
&:hover {
|
||||
color: $accentColor;
|
||||
border-color: $accentColor;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
&:focus-visible {
|
||||
color: $accentColor;
|
||||
}
|
||||
|
||||
@@ -174,14 +169,40 @@ ul {
|
||||
}
|
||||
|
||||
.g-card-dimmer {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
background-color: #000000aa;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.g-choice {
|
||||
input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
span {
|
||||
padding: 0.25em 1em;
|
||||
border-radius: 0.25em;
|
||||
border: 2px solid white;
|
||||
margin: 0.25em;
|
||||
cursor: pointer;
|
||||
|
||||
background-color: #000000aa;
|
||||
z-index: 99;
|
||||
transition: all 100ms ease;
|
||||
}
|
||||
|
||||
span:focus {
|
||||
color: $accentColor;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
label > input:checked + span {
|
||||
color: $accentColor;
|
||||
border-color: $accentColor;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ export interface ILocomotive {
|
||||
export interface ICarWagon {
|
||||
//"203V_PKPC_Fll_01","203V",true,false,"100",img
|
||||
type: string;
|
||||
useType: string;
|
||||
useType: 'car-passenger' | 'car-cargo';
|
||||
constructionType: string;
|
||||
loadable: boolean;
|
||||
supportersOnly: boolean;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { EVehicleUseType } from "../enums/EVehicleUseType";
|
||||
import { IStock } from "../types";
|
||||
|
||||
export const verifyTrainSpec = (stockList: IStock[], vehicleMass: number, vehicleUseType: string) => {
|
||||
const hasHeadLoco = stockList.length > 0
|
||||
&& (stockList[0].useType == EVehicleUseType.LOCO_ELECTRICAL
|
||||
|| stockList[0].useType == EVehicleUseType.LOCO_DIESEL);
|
||||
|
||||
if (!hasHeadLoco) return;
|
||||
|
||||
const headLoco = stockList[0];
|
||||
const carList = stockList.filter(stock => !stock.isLoco);
|
||||
|
||||
|
||||
|
||||
const isTrainPassenger = carList.length != 0
|
||||
? carList.every(stock => stock.useType == EVehicleUseType.CAR_PASSENGER)
|
||||
&& vehicleUseType == EVehicleUseType.CAR_PASSENGER
|
||||
: false;
|
||||
|
||||
|
||||
}
|
||||
@@ -103,7 +103,7 @@ export function carDataList(state: IStore) {
|
||||
const carPropsData = vehiclePropsJSON.find((v) => car[0].toString().includes(v.type));
|
||||
|
||||
acc.push({
|
||||
useType: vehicleTypeKey,
|
||||
useType: vehicleTypeKey as 'car-passenger' | 'car-cargo',
|
||||
type: car[0] as string,
|
||||
constructionType: car[1] as string,
|
||||
loadable: car[2] as boolean,
|
||||
|
||||
Reference in New Issue
Block a user