Poprawki funkcjonalności

This commit is contained in:
2022-07-30 16:42:07 +02:00
parent 767e0839e0
commit 27405485bd
10 changed files with 217 additions and 88 deletions
+9
View File
@@ -3,6 +3,13 @@
<img :src="store.vehiclePreviewSrc" alt="preview" /> <img :src="store.vehiclePreviewSrc" alt="preview" />
</div> </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"> <div class="app_container">
<header> <header>
<img :src="logoImage" alt="logo pojazdownik" /> <img :src="logoImage" alt="logo pojazdownik" />
@@ -43,12 +50,14 @@ import ListSection from './components/ListSection.vue';
import logoImage from './assets/logo.svg'; import logoImage from './assets/logo.svg';
import { useStore } from './store'; import { useStore } from './store';
import TrainImage from './components/TrainImageSection.vue'; import TrainImage from './components/TrainImageSection.vue';
import RandomizerCard from './components/RandomizerCard.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
ListSection, ListSection,
InputsSection, InputsSection,
TrainImage, TrainImage,
RandomizerCard,
}, },
data: () => ({ data: () => ({
+14 -11
View File
@@ -7,10 +7,6 @@
<span></span> <span></span>
<button class="btn" @click="shuffleCars">TASUJ WAGONY</button> <button class="btn" @click="shuffleCars">TASUJ WAGONY</button>
<button class="btn" @click="store.isRandomizerCardOpen = true">LOSUJ SKŁAD</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>
<div class="stock-list_specs"> <div class="stock-list_specs">
@@ -31,16 +27,20 @@
</button> </button>
</div> </div>
<!-- <div class="warnings"> <div class="warnings">
<div class="warning" v-if="warnings.locoNotSuitable.value"> <div class="warning" v-if="locoNotSuitable">
Lokomotywy EP07 i EP08 przeznaczone jedynie do ruchu pasażerskiego! Lokomotywy EP07 i EP08 przeznaczone jedynie do ruchu pasażerskiego!
</div> </div>
<div class="warning" v-if="warnings.trainTooLong.value"> <div class="warning" v-if="trainTooLong && store.isTrainPassenger">
Ten skład jest za długi (pasażerskie max. 350m, towarowe max. 650m)! Maksymalna długość składów pasażerskich nie może przekraczać 350m!
</div> </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ź Ten skład jest za ciężki! Sprawdź
<a <a
target="_blank" target="_blank"
@@ -50,8 +50,8 @@
</a> </a>
</div> </div>
<div class="warning" v-if="warnings.tooManyLocos.value">Ten skład posiada za dużo pojazdów trakcyjnych!</div> <div class="warning" v-if="tooManyLocomotives">Ten skład posiada za dużo pojazdów trakcyjnych!</div>
</div> --> </div>
<ul ref="list"> <ul ref="list">
<li v-if="store.stockList.length == 0" class="list-empty"> <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 lowerIcon from '../assets/lower-icon.svg';
import higherIcon from '../assets/higher-icon.svg'; import higherIcon from '../assets/higher-icon.svg';
import { useStore } from '../store'; import { useStore } from '../store';
import warningsMixin from '../mixins/warningsMixin';
export default defineComponent({ export default defineComponent({
components: { RandomizerCard, TrainImage }, components: { RandomizerCard, TrainImage },
mixins: [warningsMixin],
setup() { setup() {
const store = useStore(); const store = useStore();
+92 -38
View File
@@ -1,8 +1,6 @@
<template> <template>
<div class="g-card-dimmer" v-if="store.isRandomizerCardOpen" @click="store.isRandomizerCardOpen = false"></div>
<div class="card"> <div class="card">
<div class="wrapper" ref="cardWrapper" tabindex="0">
<div class="wrapper">
<!-- <h1>LOSUJ SKŁAD <img :src="icons.randomize" alt="losuj skład" /></h1> <!-- <h1>LOSUJ SKŁAD <img :src="icons.randomize" alt="losuj skład" /></h1>
<h3> <h3>
@@ -13,7 +11,7 @@
<div class="car-preview"> <div class="car-preview">
<div class="image-wrapper"> <div class="image-wrapper">
<div v-if="isPreviewLoading" class="loading">ŁADOWANIE...</div> <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> </div>
<b class="text--accent" v-if="focusedCar"> <b class="text--accent" v-if="focusedCar">
{{ focusedCar.type.split('_')[0] }} {{ focusedCar.type.split('_')[2] }} {{ focusedCar.type.split('_')[0] }} {{ focusedCar.type.split('_')[2] }}
@@ -29,11 +27,12 @@
<div> <div>
<button <button
class="btn choice-btn" class="btn choice-btn"
v-for="carType in carTypeList.filter((_, i) => i < 15)" v-for="carType in passengerCarTypeList"
:key="carType" :key="carType"
@click="toggleCarType(carType)" @click="toggleCarType(carType)"
@mouseenter="displayPreview(carType)" @mouseenter="displayPreview(carType)"
:class="{ chosen: chosenCarTypes.includes(carType) }" @focus="displayPreview(carType)"
:data-selected="chosenCarTypes.includes(carType)"
> >
{{ carType }} {{ carType }}
</button> </button>
@@ -42,11 +41,12 @@
<div style="margin-top: 0.5em"> <div style="margin-top: 0.5em">
<button <button
class="btn choice-btn" class="btn choice-btn"
v-for="carType in carTypeList.filter((_, i) => i >= 15)" v-for="carType in cargoCarTypeList"
:key="carType" :key="carType"
@click="toggleCarType(carType)" @click="toggleCarType(carType)"
@mouseenter="displayPreview(carType)" @mouseenter="displayPreview(carType)"
:class="{ chosen: chosenCarTypes.includes(carType) }" @focus="displayPreview(carType)"
:data-selected="chosenCarTypes.includes(carType)"
> >
{{ carType }} {{ carType }}
</button> </button>
@@ -75,9 +75,14 @@
/> />
</div> </div>
<div style="margin: 1em 0"> <div class="cargo-filling g-choice" style="margin: 1em 0">
<button class="btn choice-btn" :class="{ chosen: loadableByDefault }" @click="changeLoadableByDefault"> <button
DOMYŚLNIE ŁADOWNE class="btn choice-btn"
v-for="mode in cargoFillModeList"
:data-selected="mode.id == chosenCargoFillMode"
@click="changeCargoFillMode(mode.id)"
>
{{ mode.value }}
</button> </button>
</div> </div>
@@ -90,7 +95,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, inject } from 'vue'; import { defineComponent } from 'vue';
import carUsage from '../data/carUsage.json'; import carUsage from '../data/carUsage.json';
import { ICarWagon, ILocomotive, ICargo } from '../types'; import { ICarWagon, ILocomotive, ICargo } from '../types';
@@ -98,6 +103,8 @@ import { ICarWagon, ILocomotive, ICargo } from '../types';
import randomizeIcon from '../assets/randomize-icon.svg'; import randomizeIcon from '../assets/randomize-icon.svg';
import { useStore } from '../store'; import { useStore } from '../store';
type CargoFillModeType = 'cargo-random' | 'cargo-filled' | 'cargo-empty';
export default defineComponent({ export default defineComponent({
setup() { setup() {
const store = useStore(); const store = useStore();
@@ -105,30 +112,80 @@ export default defineComponent({
return { return {
store, store,
carTypeList: store.carDataList.reduce((list, car) => { carTypeList: store.carDataList
const type = car.type.split('_')[0]; .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; return list;
}, [] as string[]), }, [] 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: () => ({ data: () => ({
randomStockMass: 1500, randomStockMass: 1500,
randomStockLength: 650, randomStockLength: 650,
chosenCarTypes: [] as string[], 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: { icons: {
randomize: randomizeIcon, randomize: randomizeIcon,
}, },
focusedCar: null as ICarWagon | null, focusedCar: null as ICarWagon | null,
isPreviewLoading: false, isPreviewLoading: false,
loadableByDefault: false,
cargoTypes: [ cargoTypes: [
'203V', '203V',
@@ -162,15 +219,10 @@ export default defineComponent({
if (this.focusedCar?.type == list[randIndex].type) return; if (this.focusedCar?.type == list[randIndex].type) return;
this.focusedCar = list[randIndex]; this.focusedCar = list[randIndex];
this.isPreviewLoading = true;
}, },
onPreviewLoaded() { changeCargoFillMode(mode: CargoFillModeType) {
this.isPreviewLoading = false; this.chosenCargoFillMode = mode;
},
changeLoadableByDefault() {
this.loadableByDefault = !this.loadableByDefault;
}, },
randomize() { randomize() {
@@ -234,7 +286,12 @@ export default defineComponent({
if (randCar.length * count + totalStockLength >= this.randomStockLength) break; if (randCar.length * count + totalStockLength >= this.randomStockLength) break;
let randCargo = undefined; 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) if (randCar.cargoList.length != 0 && randNum >= 0.6)
randCargo = randCar.cargoList[Math.floor(Math.random() * randCar.cargoList.length)]; randCargo = randCar.cargoList[Math.floor(Math.random() * randCar.cargoList.length)];
@@ -310,7 +367,7 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
/* @import url('../styles/global.scss'); */ @import '../styles/global.scss';
.card { .card {
position: fixed; position: fixed;
@@ -376,12 +433,10 @@ input {
.car-choice div { .car-choice div {
display: grid; display: grid;
grid-template-columns: repeat(5, 1fr); grid-template-columns: repeat(6, 1fr);
justify-content: center; justify-content: center;
@media screen and (max-width: 800px) { @media screen and (max-width: 800px) {
/* display: flex; */
/* flex-wrap: wrap; */
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
} }
} }
@@ -390,19 +445,18 @@ button.choice-btn {
color: gray; color: gray;
border-color: gray; border-color: gray;
*:focus { &[data-selected='true'] {
color: white; color: $accentColor;
border-color: $accentColor;
}
&:focus-visible {
border-color: white; border-color: white;
} }
user-select: none; user-select: none;
} }
button.chosen {
border-color: gold;
color: gold;
}
.car-preview { .car-preview {
display: flex; display: flex;
justify-content: center; justify-content: center;
-1
View File
@@ -1,5 +1,4 @@
<template> <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="ready-stock-list" v-if="store.isRealStockListCardOpen">
<div class="top-sticky"> <div class="top-sticky">
<button class="btn btn--text exit" @click="store.isRealStockListCardOpen = false">&lt; POWRÓT</button> <button class="btn btn--text exit" @click="store.isRealStockListCardOpen = false">&lt; POWRÓT</button>
+65
View File
@@ -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
View File
@@ -1,4 +1,4 @@
import { ICarWagon, ILocomotive, IStore } from './types'; import { IStore } from './types';
import { defineStore } from 'pinia'; import { defineStore } from 'pinia';
import { carDataList, isTrainPassenger, locoDataList, maxStockSpeed, totalLength, totalMass } from './utils/vehicleUtils'; import { carDataList, isTrainPassenger, locoDataList, maxStockSpeed, totalLength, totalMass } from './utils/vehicleUtils';
+34 -13
View File
@@ -93,12 +93,7 @@ button.btn {
transition: all 250ms; transition: all 250ms;
&:hover { &:focus-visible {
color: $accentColor;
border-color: $accentColor;
}
&:focus {
color: $accentColor; color: $accentColor;
} }
@@ -174,14 +169,40 @@ ul {
} }
.g-card-dimmer { .g-card-dimmer {
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100vw; width: 100vw;
height: 100vh; 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; cursor: pointer;
background-color: #000000aa; transition: all 100ms ease;
z-index: 99; }
span:focus {
color: $accentColor;
outline: none;
}
label > input:checked + span {
color: $accentColor;
border-color: $accentColor;
}
} }
+1 -1
View File
@@ -46,7 +46,7 @@ export interface ILocomotive {
export interface ICarWagon { export interface ICarWagon {
//"203V_PKPC_Fll_01","203V",true,false,"100",img //"203V_PKPC_Fll_01","203V",true,false,"100",img
type: string; type: string;
useType: string; useType: 'car-passenger' | 'car-cargo';
constructionType: string; constructionType: string;
loadable: boolean; loadable: boolean;
supportersOnly: boolean; supportersOnly: boolean;
-22
View File
@@ -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;
}
+1 -1
View File
@@ -103,7 +103,7 @@ export function carDataList(state: IStore) {
const carPropsData = vehiclePropsJSON.find((v) => car[0].toString().includes(v.type)); const carPropsData = vehiclePropsJSON.find((v) => car[0].toString().includes(v.type));
acc.push({ acc.push({
useType: vehicleTypeKey, useType: vehicleTypeKey as 'car-passenger' | 'car-cargo',
type: car[0] as string, type: car[0] as string,
constructionType: car[1] as string, constructionType: car[1] as string,
loadable: car[2] as boolean, loadable: car[2] as boolean,