diff --git a/backend/services/falukantService.js b/backend/services/falukantService.js index b514d43..d12e8d7 100644 --- a/backend/services/falukantService.js +++ b/backend/services/falukantService.js @@ -97,16 +97,26 @@ async function getBranchOrFail(userId, branchId) { return branch; } -/** - * Gesamtkosten für eine Produktionscharge (früher: quantity * category * 6 pro Einheit). - * Pro Einheit jetzt 2 * Kategorie (z.B. Kat.1 = 2, Kat.2 = 4), damit Nettoerlös und - * typischer town_product_worth (oft 40–60 %, siehe Model-Hook) zusammenpassen. - */ -function productionCostTotal(quantity, category) { +const PRODUCTION_COST_BASE = 6.0; +const PRODUCTION_COST_PER_PRODUCT_CATEGORY = 1.0; +const PRODUCTION_HEADROOM_DISCOUNT_PER_STEP = 0.035; +const PRODUCTION_HEADROOM_DISCOUNT_CAP = 0.14; + +function productionPieceCost(certificate, category) { const c = Math.max(1, Number(category) || 1); + const cert = Math.max(1, Number(certificate) || 1); + const raw = PRODUCTION_COST_BASE + (c * PRODUCTION_COST_PER_PRODUCT_CATEGORY); + const headroom = Math.max(0, cert - c); + const discount = Math.min( + headroom * PRODUCTION_HEADROOM_DISCOUNT_PER_STEP, + PRODUCTION_HEADROOM_DISCOUNT_CAP + ); + return raw * (1 - discount); +} + +function productionCostTotal(quantity, category, certificate) { const q = Math.min(100, Math.max(1, Number(quantity) || 1)); - const perUnit = 2 * c; - return q * perUnit; + return q * productionPieceCost(certificate, category); } /** Regionaler Nachfragewert: sehr niedrige Werte aus der DB sonst unspielbar; Decke nach oben bei 100. */ @@ -2053,7 +2063,7 @@ class FalukantService extends BaseService { } if (!p) throw new Error('Product not found'); quantity = Math.min(100, quantity); - const cost = productionCostTotal(quantity, p.category); + const cost = productionCostTotal(quantity, p.category, u.certificate); if (u.money < cost) throw new Error('notenoughmoney'); const r = await updateFalukantUserMoney(u.id, -cost, 'Production cost', u.id); if (!r.success) throw new Error('Failed to update money'); diff --git a/backend/sql/rebalance_product_certificates.sql b/backend/sql/rebalance_product_certificates.sql new file mode 100644 index 0000000..c57cdf6 --- /dev/null +++ b/backend/sql/rebalance_product_certificates.sql @@ -0,0 +1,51 @@ +BEGIN; + +UPDATE falukant_type.product +SET sell_cost = CASE label_tr + WHEN 'wheat' THEN 7 + WHEN 'grain' THEN 7 + WHEN 'carrot' THEN 4 + WHEN 'fish' THEN 7 + WHEN 'meat' THEN 7 + WHEN 'leather' THEN 7 + WHEN 'wood' THEN 7 + WHEN 'stone' THEN 7 + WHEN 'milk' THEN 5 + WHEN 'cheese' THEN 5 + WHEN 'bread' THEN 5 + WHEN 'beer' THEN 22 + WHEN 'iron' THEN 24 + WHEN 'copper' THEN 24 + WHEN 'spices' THEN 42 + WHEN 'salt' THEN 24 + WHEN 'sugar' THEN 24 + WHEN 'vinegar' THEN 24 + WHEN 'cotton' THEN 24 + WHEN 'wine' THEN 24 + WHEN 'gold' THEN 40 + WHEN 'diamond' THEN 40 + WHEN 'furniture' THEN 40 + WHEN 'clothing' THEN 40 + WHEN 'jewelry' THEN 58 + WHEN 'painting' THEN 58 + WHEN 'book' THEN 58 + WHEN 'weapon' THEN 58 + WHEN 'armor' THEN 58 + WHEN 'shield' THEN 58 + WHEN 'horse' THEN 78 + WHEN 'ox' THEN 78 + ELSE sell_cost +END, +production_time = CASE label_tr + WHEN 'carrot' THEN 2 + ELSE production_time +END +WHERE label_tr IN ( + 'wheat', 'grain', 'carrot', 'fish', 'meat', 'leather', 'wood', 'stone', + 'milk', 'cheese', 'bread', 'beer', 'iron', 'copper', 'spices', 'salt', + 'sugar', 'vinegar', 'cotton', 'wine', 'gold', 'diamond', 'furniture', + 'clothing', 'jewelry', 'painting', 'book', 'weapon', 'armor', 'shield', + 'horse', 'ox' +); + +COMMIT; diff --git a/backend/utils/falukant/initializeFalukantPredefines.js b/backend/utils/falukant/initializeFalukantPredefines.js index f9ddb7c..1ffc40a 100644 --- a/backend/utils/falukant/initializeFalukantPredefines.js +++ b/backend/utils/falukant/initializeFalukantPredefines.js @@ -250,37 +250,36 @@ async function initializeFalukantProducts() { const baseProducts = [ { labelTr: 'wheat', category: 1, productionTime: 2, sellCost: 7 }, { labelTr: 'grain', category: 1, productionTime: 2, sellCost: 7 }, - // Wie Weizen/Getreide (kein Debug-Tempo mehr); Verkaufspreis wie Milch/Brot (Kat. 1, schnelle Ware) - { labelTr: 'carrot', category: 1, productionTime: 2, sellCost: 6 }, + { labelTr: 'carrot', category: 1, productionTime: 2, sellCost: 4 }, { labelTr: 'fish', category: 1, productionTime: 2, sellCost: 7 }, { labelTr: 'meat', category: 1, productionTime: 2, sellCost: 7 }, { labelTr: 'leather', category: 1, productionTime: 2, sellCost: 7 }, { labelTr: 'wood', category: 1, productionTime: 2, sellCost: 7 }, { labelTr: 'stone', category: 1, productionTime: 2, sellCost: 7 }, - { labelTr: 'milk', category: 1, productionTime: 1, sellCost: 6 }, - { labelTr: 'cheese', category: 1, productionTime: 1, sellCost: 6 }, - { labelTr: 'bread', category: 1, productionTime: 1, sellCost: 6 }, - { labelTr: 'beer', category: 2, productionTime: 3, sellCost: 6 }, - { labelTr: 'iron', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'copper', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'spices', category: 2, productionTime: 8, sellCost: 30 }, - { labelTr: 'salt', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'sugar', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'vinegar', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'cotton', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'wine', category: 2, productionTime: 4, sellCost: 15 }, - { labelTr: 'gold', category: 3, productionTime: 4, sellCost: 30 }, - { labelTr: 'diamond', category: 3, productionTime: 4, sellCost: 30 }, - { labelTr: 'furniture', category: 3, productionTime: 4, sellCost: 30 }, - { labelTr: 'clothing', category: 3, productionTime: 4, sellCost: 30 }, - { labelTr: 'jewelry', category: 4, productionTime: 5, sellCost: 60 }, - { labelTr: 'painting', category: 4, productionTime: 5, sellCost: 60 }, - { labelTr: 'book', category: 4, productionTime: 5, sellCost: 60 }, - { labelTr: 'weapon', category: 4, productionTime: 5, sellCost: 60 }, - { labelTr: 'armor', category: 4, productionTime: 5, sellCost: 60 }, - { labelTr: 'shield', category: 4, productionTime: 5, sellCost: 60 }, - { labelTr: 'horse', category: 5, productionTime: 5, sellCost: 60 }, - { labelTr: 'ox', category: 5, productionTime: 5, sellCost: 60 }, + { labelTr: 'milk', category: 1, productionTime: 1, sellCost: 5 }, + { labelTr: 'cheese', category: 1, productionTime: 1, sellCost: 5 }, + { labelTr: 'bread', category: 1, productionTime: 1, sellCost: 5 }, + { labelTr: 'beer', category: 2, productionTime: 3, sellCost: 22 }, + { labelTr: 'iron', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'copper', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'spices', category: 2, productionTime: 8, sellCost: 42 }, + { labelTr: 'salt', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'sugar', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'vinegar', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'cotton', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'wine', category: 2, productionTime: 4, sellCost: 24 }, + { labelTr: 'gold', category: 3, productionTime: 4, sellCost: 40 }, + { labelTr: 'diamond', category: 3, productionTime: 4, sellCost: 40 }, + { labelTr: 'furniture', category: 3, productionTime: 4, sellCost: 40 }, + { labelTr: 'clothing', category: 3, productionTime: 4, sellCost: 40 }, + { labelTr: 'jewelry', category: 4, productionTime: 5, sellCost: 58 }, + { labelTr: 'painting', category: 4, productionTime: 5, sellCost: 58 }, + { labelTr: 'book', category: 4, productionTime: 5, sellCost: 58 }, + { labelTr: 'weapon', category: 4, productionTime: 5, sellCost: 58 }, + { labelTr: 'armor', category: 4, productionTime: 5, sellCost: 58 }, + { labelTr: 'shield', category: 4, productionTime: 5, sellCost: 58 }, + { labelTr: 'horse', category: 5, productionTime: 5, sellCost: 78 }, + { labelTr: 'ox', category: 5, productionTime: 5, sellCost: 78 }, ]; const productsToInsert = baseProducts.map(p => ({ diff --git a/frontend/src/components/falukant/ProductionSection.vue b/frontend/src/components/falukant/ProductionSection.vue index eacc559..e644fd4 100644 --- a/frontend/src/components/falukant/ProductionSection.vue +++ b/frontend/src/components/falukant/ProductionSection.vue @@ -64,11 +64,18 @@