feat(falukant): enhance product pricing and nobility advancement features
All checks were successful
Deploy to production / deploy (push) Successful in 2m52s

- Updated the `getAllProductPricesInRegion` method in `FalukantService` to accept additional parameters for network worth and branch ID, improving pricing calculations based on user branches.
- Enhanced the nobility advancement logic in `NobilityView` to display unmet requirements clearly, providing users with better feedback on advancement conditions.
- Refactored the revenue calculation in `ProductionSection` to utilize a cached product prices object, optimizing performance and reducing redundant API calls.
- Updated localization files to include new translations for attack sources across multiple languages, enhancing the user experience for diverse audiences.
- Removed obsolete C++ worker references and streamlined the retention logic for production logs, ensuring efficient data management.
This commit is contained in:
Torsten Schulz (local)
2026-04-09 09:08:32 +02:00
parent 360bb59a4e
commit 1118a691b9
20 changed files with 216 additions and 85 deletions

View File

@@ -76,6 +76,8 @@
branchId: { type: Number, required: true },
products: { type: Array, required: true },
currentCertificate: { type: Number, default: 1 },
/** Gleiche regionalen Preise wie Ertrags-Tabelle (BranchView / prices-in-region, optional MAX-Worth). */
productPricesCache: { type: Object, default: () => ({}) },
},
data() {
return {
@@ -194,10 +196,15 @@
if (!product.knowledges || product.knowledges.length === 0) {
return { absolute: 0, perMinute: 0 };
}
const knowledgeFactor = product.knowledges[0].knowledge || 0;
const maxPrice = product.sellCost;
const minPrice = maxPrice * 0.6;
const revenuePerUnit = minPrice + (maxPrice - minPrice) * (knowledgeFactor / 100);
let revenuePerUnit;
if (this.productPricesCache[product.id] !== undefined) {
revenuePerUnit = this.productPricesCache[product.id];
} else {
const knowledgeFactor = product.knowledges[0].knowledge || 0;
const maxPrice = product.sellCost;
const minPrice = maxPrice * 0.7; // KNOWLEDGE_PRICE_FLOOR wie backend/falukantProductEconomy
revenuePerUnit = minPrice + (maxPrice - minPrice) * (knowledgeFactor / 100);
}
const perMinute = product.productionTime > 0 ? revenuePerUnit / product.productionTime : 0;
return {
absolute: revenuePerUnit.toFixed(2),

View File

@@ -20,7 +20,11 @@
</tr>
</thead>
<tbody>
<tr v-for="product in products" :key="product.id" :class="{ highlight: product.id === productWithMaxProfitPerMinute?.id }">
<tr
v-for="product in sortedProductsByProfitPerMinute"
:key="product.id"
:class="{ highlight: product.id === topProductByProfitPerMinute?.id }"
>
<td>{{ $t(`falukant.product.${product.labelTr}`) }}</td>
<td>{{ product.knowledges && product.knowledges[0] ? product.knowledges[0].knowledge : 0 }}</td>
<td>{{ calculateProductRevenue(product).absolute }}</td>
@@ -72,13 +76,19 @@
};
},
computed: {
productWithMaxProfitPerMinute() {
if (!this.products || this.products.length === 0) return null;
return this.products.reduce((maxProduct, currentProduct) => {
const currentProfit = parseFloat(this.calculateProductProfit(currentProduct).perMinute);
const maxProfit = maxProduct ? parseFloat(this.calculateProductProfit(maxProduct).perMinute) : Number.NEGATIVE_INFINITY;
return currentProfit > maxProfit ? currentProduct : maxProduct;
}, null);
/** Gleiche Metrik wie Daemon: Gewinn/Minute ≈ (Erlös/Stück Stückkosten) / Produktionszeit; höchste zuerst. */
sortedProductsByProfitPerMinute() {
if (!this.products || this.products.length === 0) return [];
return [...this.products].sort((a, b) => {
const pb = parseFloat(this.calculateProductProfit(b).perMinute);
const pa = parseFloat(this.calculateProductProfit(a).perMinute);
if (pb !== pa) return pb - pa;
return (a.labelTr || '').localeCompare(b.labelTr || '');
});
},
topProductByProfitPerMinute() {
const list = this.sortedProductsByProfitPerMinute;
return list.length ? list[0] : null;
},
},
async mounted() {