Files
yourpart3/backend/services/taxiMapService.js
Torsten Schulz (local) 9db7c88086 Änderung: Erweiterung der Taxi-Map-Logik und Verbesserung der Benutzeroberfläche
Änderungen:
- Hinzufügung neuer Modelle für TaxiMapTile, TaxiStreetName und TaxiMapTileStreet zur Unterstützung der Tile- und Straßennamen-Logik.
- Anpassung der TaxiMap- und TaxiMapService-Logik zur Verwaltung von Tiles und Straßennamen.
- Implementierung von Methoden zur Upsert-Logik für Tiles und Straßennamen in der TaxiMapService.
- Verbesserung der Benutzeroberfläche in TaxiToolsView.vue zur Anzeige und Bearbeitung von Straßennamen und zusätzlichen Elementen.

Diese Anpassungen verbessern die Funktionalität und Benutzererfahrung im Taxi-Minispiel erheblich, indem sie eine detailliertere Verwaltung von Karten und Straßennamen ermöglichen.
2025-09-17 18:55:57 +02:00

300 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import BaseService from './BaseService.js';
import TaxiMap from '../models/taxi/taxiMap.js';
import TaxiMapType from '../models/taxi/taxiMapType.js';
import TaxiMapTile from '../models/taxi/taxiMapTile.js';
import TaxiStreetName from '../models/taxi/taxiStreetName.js';
import TaxiMapTileStreet from '../models/taxi/taxiMapTileStreet.js';
class TaxiMapService extends BaseService {
constructor() {
super();
}
/**
* Holt alle verfügbaren Map-Typen
*/
async getMapTypes() {
try {
const mapTypes = await TaxiMapType.findAll({
where: { isActive: true },
order: [['name', 'ASC']]
});
return mapTypes;
} catch (error) {
console.error('Error getting map types:', error);
throw error;
}
}
/**
* Holt alle verfügbaren Maps
*/
async getMaps() {
try {
const maps = await TaxiMap.findAll({
where: { isActive: true },
include: [
{ model: TaxiMapType, as: 'mapType' },
{ model: TaxiMapTile, as: 'tiles' },
{
model: TaxiMapTileStreet,
as: 'tileStreets',
include: [
{ model: TaxiStreetName, as: 'streetNameH' },
{ model: TaxiStreetName, as: 'streetNameV' }
]
}
],
order: [['name', 'ASC']]
});
return maps;
} catch (error) {
console.error('Error getting maps:', error);
throw error;
}
}
/**
* Holt eine spezifische Map
*/
async getMapById(mapId) {
try {
const map = await TaxiMap.findOne({
where: {
id: mapId,
isActive: true
},
include: [
{ model: TaxiMapType, as: 'mapType' },
{ model: TaxiMapTile, as: 'tiles' },
{
model: TaxiMapTileStreet,
as: 'tileStreets',
include: [
{ model: TaxiStreetName, as: 'streetNameH' },
{ model: TaxiStreetName, as: 'streetNameV' }
]
}
]
});
return map;
} catch (error) {
console.error('Error getting map by ID:', error);
throw error;
}
}
/**
* Holt die Standard-Map
*/
async getDefaultMap() {
try {
const map = await TaxiMap.findOne({
where: {
isDefault: true,
isActive: true
},
include: [{
model: TaxiMapType,
as: 'mapType'
}]
});
return map;
} catch (error) {
console.error('Error getting default map:', error);
throw error;
}
}
/**
* Erstellt eine neue Map
*/
async createMap(mapData) {
try {
const { tiles, tileStreetNames, ...mapFields } = mapData;
// mapData JSON ist entfernt map erstellen ohne mapData
const map = await TaxiMap.create(mapFields);
// Tiles upsert (optional)
if (Array.isArray(tiles) && tiles.length > 0) {
await this.upsertTiles(map.id, tiles);
}
// Street names (optional)
if (tileStreetNames && Object.keys(tileStreetNames).length > 0) {
await this.upsertTileStreetNames(map.id, tileStreetNames);
}
return await this.getMapById(map.id);
} catch (error) {
console.error('Error creating map:', error);
throw error;
}
}
/**
* Aktualisiert eine Map
*/
async updateMap(mapId, updateData) {
try {
const { tiles, tileStreetNames, ...mapFields } = updateData;
const [updatedRowsCount] = await TaxiMap.update(mapFields, {
where: { id: mapId }
});
if (updatedRowsCount === 0) {
throw new Error('Map not found');
}
// Tiles upsert (optional)
if (Array.isArray(tiles)) {
await this.upsertTiles(mapId, tiles);
}
if (tileStreetNames && Object.keys(tileStreetNames).length > 0) {
await this.upsertTileStreetNames(mapId, tileStreetNames);
}
return await this.getMapById(mapId);
} catch (error) {
console.error('Error updating map:', error);
throw error;
}
}
/**
* Speichert Straßennamen-Belegungen für eine Map
* @param {number} mapId
* @param {{[cellKey:string]:{streetNameH?:string, streetNameV?:string}}} tileNames
*/
async upsertTileStreetNames(mapId, tileNames) {
const entries = Object.entries(tileNames || {});
for (const [cellKey, data] of entries) {
const [x, y] = cellKey.split(',').map(Number);
const record = { mapId, x, y };
// Street names: findOrCreate
if (data.streetNameH) {
const [snH] = await TaxiStreetName.findOrCreate({ where: { name: data.streetNameH }, defaults: { name: data.streetNameH } });
record.streetNameHId = snH.id;
} else {
record.streetNameHId = null;
}
if (data.streetNameV) {
const [snV] = await TaxiStreetName.findOrCreate({ where: { name: data.streetNameV }, defaults: { name: data.streetNameV } });
record.streetNameVId = snV.id;
} else {
record.streetNameVId = null;
}
const [row] = await TaxiMapTileStreet.findOrCreate({ where: { mapId, x, y }, defaults: record });
await row.update(record);
}
return { success: true };
}
/**
* Upsert Tiles (x,y,tileType,meta?) pro Map
* Erwartet: tiles: Array<{x:number,y:number,tileType:string, meta?:object}>
*/
async upsertTiles(mapId, tiles) {
for (const tile of tiles) {
const { x, y, tileType, meta } = tile;
if (typeof x !== 'number' || typeof y !== 'number' || !tileType) continue;
const [row] = await TaxiMapTile.findOrCreate({
where: { mapId, x, y },
defaults: { mapId, x, y, tileType, meta: meta || null }
});
await row.update({ tileType, meta: meta || null });
}
return { success: true };
}
/**
* Löscht eine Map (soft delete)
*/
async deleteMap(mapId) {
try {
const [updatedRowsCount] = await TaxiMap.update(
{ isActive: false },
{ where: { id: mapId } }
);
if (updatedRowsCount === 0) {
throw new Error('Map not found');
}
return { success: true };
} catch (error) {
console.error('Error deleting map:', error);
throw error;
}
}
/**
* Setzt eine Map als Standard
*/
async setDefaultMap(mapId) {
try {
// Entferne Standard-Status von allen anderen Maps
await TaxiMap.update(
{ isDefault: false },
{ where: { isDefault: true } }
);
// Setze neue Standard-Map
const [updatedRowsCount] = await TaxiMap.update(
{ isDefault: true },
{ where: { id: mapId } }
);
if (updatedRowsCount === 0) {
throw new Error('Map not found');
}
return { success: true };
} catch (error) {
console.error('Error setting default map:', error);
throw error;
}
}
/**
* Initialisiert Standard-Map-Typen
*/
async initializeMapTypes() {
try {
const mapTypes = [
{ name: 'Corner Bottom Left', tileType: 'cornerBottomLeft', description: 'Bottom left corner tile' },
{ name: 'Corner Bottom Right', tileType: 'cornerBottomRight', description: 'Bottom right corner tile' },
{ name: 'Corner Top Left', tileType: 'cornerTopLeft', description: 'Top left corner tile' },
{ name: 'Corner Top Right', tileType: 'cornerTopRight', description: 'Top right corner tile' },
{ name: 'Horizontal', tileType: 'horizontal', description: 'Horizontal road tile' },
{ name: 'Vertical', tileType: 'vertical', description: 'Vertical road tile' },
{ name: 'Cross', tileType: 'cross', description: 'Cross intersection tile' },
{ name: 'Fuel Horizontal', tileType: 'fuelHorizontal', description: 'Horizontal road with fuel station' },
{ name: 'Fuel Vertical', tileType: 'fuelVertical', description: 'Vertical road with fuel station' },
{ name: 'T-Left', tileType: 'tLeft', description: 'T-junction facing left' },
{ name: 'T-Right', tileType: 'tRight', description: 'T-junction facing right' },
{ name: 'T-Up', tileType: 'tUp', description: 'T-junction facing up' },
{ name: 'T-Down', tileType: 'tDown', description: 'T-junction facing down' }
];
for (const mapType of mapTypes) {
await TaxiMapType.findOrCreate({
where: { name: mapType.name },
defaults: mapType
});
}
console.log('Taxi map types initialized');
} catch (error) {
console.error('Error initializing map types:', error);
throw error;
}
}
/**
* Erstellt eine Standard-Map
*/
async createDefaultMap() {
}
}
export default TaxiMapService;