diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index a88a60c..6316c9a 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -98,6 +98,15 @@ function calcSellPrice(product, knowledgeFactor = 0) { return min + (max - min) * (knowledgeFactor / 100); } +/** Synchrone Preisberechnung, wenn worthPercent bereits bekannt ist (kein DB-Zugriff). */ +function calcRegionalSellPriceSync(product, knowledgeFactor, worthPercent) { + if (product.sellCost === null || product.sellCost === undefined) return null; + const basePrice = product.sellCost * (worthPercent / 100); + const min = basePrice * 0.6; + const max = basePrice; + return min + (max - min) * (knowledgeFactor / 100); +} + async function calcRegionalSellPrice(product, knowledgeFactor, regionId, worthPercent = null) { // Wenn worthPercent nicht übergeben wurde, hole es aus der Datenbank if (worthPercent === null) { @@ -4394,66 +4403,34 @@ class FalukantService extends BaseService { } async getAllProductPricesInRegion(hashedUserId, regionId) { - const startTime = Date.now(); - console.log(`[getAllProductPricesInRegion] Start für userId: ${hashedUserId}, regionId: ${regionId}`); - try { const user = await this.getFalukantUserByHashedId(hashedUserId); - const userTime = Date.now(); - console.log(`[getAllProductPricesInRegion] User geladen in ${userTime - startTime}ms`); - const character = await FalukantCharacter.findOne({ where: { userId: user.id } }); if (!character) { throw new Error(`No FalukantCharacter found for user with id ${user.id}`); } - const characterTime = Date.now(); - console.log(`[getAllProductPricesInRegion] Character geladen in ${characterTime - userTime}ms`); + const [products, knowledges, townWorths] = await Promise.all([ + ProductType.findAll({ attributes: ['id', 'sellCost'] }), + Knowledge.findAll({ + where: { characterId: character.id }, + attributes: ['productId', 'knowledge'] + }), + TownProductWorth.findAll({ + where: { regionId: regionId }, + attributes: ['productId', 'worthPercent'] + }) + ]); - // Lade alle Produkte auf einmal - const products = await ProductType.findAll({ - attributes: ['id', 'sellCost'] - }); - const productsTime = Date.now(); - console.log(`[getAllProductPricesInRegion] ${products.length} Produkte geladen in ${productsTime - characterTime}ms`); - - // Lade alle Knowledge-Werte für diesen Character auf einmal - const knowledges = await Knowledge.findAll({ - where: { characterId: character.id }, - attributes: ['productId', 'knowledge'] - }); const knowledgeMap = new Map(knowledges.map(k => [k.productId, k.knowledge || 0])); - const knowledgeTime = Date.now(); - console.log(`[getAllProductPricesInRegion] ${knowledges.length} Knowledge-Werte geladen in ${knowledgeTime - productsTime}ms`); - - // Lade alle TownProductWorth-Werte für diese Region auf einmal - const townWorths = await TownProductWorth.findAll({ - where: { regionId: regionId }, - attributes: ['productId', 'worthPercent'] - }); const worthMap = new Map(townWorths.map(tw => [tw.productId, tw.worthPercent || 50])); - const worthTime = Date.now(); - console.log(`[getAllProductPricesInRegion] ${townWorths.length} Worth-Werte geladen in ${worthTime - knowledgeTime}ms`); - // Berechne Preise für alle Produkte const prices = {}; for (const product of products) { - if (product.sellCost === null || product.sellCost === undefined) { - continue; // Überspringe Produkte ohne sellCost - } - + const worthPercent = worthMap.get(product.id) ?? 50; const knowledgeFactor = knowledgeMap.get(product.id) || 0; - const worthPercent = worthMap.get(product.id) || 50; - - // Verwende calcRegionalSellPrice mit bereits geladenem worthPercent - const price = await calcRegionalSellPrice(product, knowledgeFactor, regionId, worthPercent); - prices[product.id] = price; + const price = calcRegionalSellPriceSync(product, knowledgeFactor, worthPercent); + if (price !== null) prices[product.id] = price; } - const calcTime = Date.now(); - console.log(`[getAllProductPricesInRegion] Preise berechnet in ${calcTime - worthTime}ms`); - - const totalTime = Date.now() - startTime; - console.log(`[getAllProductPricesInRegion] Gesamtzeit: ${totalTime}ms für ${Object.keys(prices).length} Produkte`); - return { prices }; } catch (error) { console.error(`[getAllProductPricesInRegion] Error for regionId=${regionId}:`, error); diff --git a/frontend/src/components/form/FormattedDropdown.vue b/frontend/src/components/form/FormattedDropdown.vue index 4dfe9f3..7e85ce5 100644 --- a/frontend/src/components/form/FormattedDropdown.vue +++ b/frontend/src/components/form/FormattedDropdown.vue @@ -68,7 +68,6 @@ export default { }, methods: { toggleDropdown() { - console.log("toggleDropdown", 'clicked'); if (this.disabled) return; this.isOpen = !this.isOpen; }, diff --git a/frontend/src/views/falukant/BranchView.vue b/frontend/src/views/falukant/BranchView.vue index a124bd5..aaf91b4 100644 --- a/frontend/src/views/falukant/BranchView.vue +++ b/frontend/src/views/falukant/BranchView.vue @@ -360,6 +360,7 @@ export default { vehicles: [], activeTab: 'production', productPricesCache: {}, // Cache für regionale Preise: { productId: price } + productPricesCacheRegionId: null, // regionId, für die der Cache gültig ist tabs: [ { value: 'production', label: 'falukant.branch.tabs.production' }, { value: 'inventory', label: 'falukant.branch.tabs.inventory' }, @@ -569,20 +570,20 @@ export default { async loadProductPricesForCurrentBranch() { if (!this.selectedBranch || !this.selectedBranch.regionId) { this.productPricesCache = {}; + this.productPricesCacheRegionId = null; + return; + } + if (this.productPricesCacheRegionId === this.selectedBranch.regionId && Object.keys(this.productPricesCache).length > 0) { return; } - - // Lade alle Preise für die Region auf einmal (Bulk-Request) try { - const startTime = performance.now(); const { data } = await apiClient.get('/api/falukant/products/prices-in-region', { params: { regionId: this.selectedBranch.regionId } }); - const loadTime = performance.now() - startTime; - console.log(`[BranchView] Product prices loaded in ${loadTime.toFixed(2)}ms`); this.productPricesCache = data.prices || {}; + this.productPricesCacheRegionId = this.selectedBranch.regionId; } catch (error) { console.error(`Error loading product prices for region ${this.selectedBranch.regionId}:`, error); // Fallback: Lade Preise einzeln (alte Methode) @@ -607,6 +608,7 @@ export default { } } this.productPricesCache = prices; + this.productPricesCacheRegionId = this.selectedBranch?.regionId ?? null; } },