Add product weather effects and regional pricing enhancements
- Introduced a new endpoint in FalukantController to retrieve product prices based on region and product ID. - Implemented logic in FalukantService to calculate product prices considering user knowledge and regional factors. - Added weather-related data models and associations to enhance product pricing accuracy based on weather conditions. - Updated frontend components to cache and display regional product prices effectively, improving user experience.
This commit is contained in:
@@ -18,6 +18,10 @@ import PoliticalOfficeType from "../../models/falukant/type/political_office_typ
|
||||
import PoliticalOfficeBenefitType from "../../models/falukant/type/political_office_benefit_type.js";
|
||||
import PoliticalOfficePrerequisite from "../../models/falukant/predefine/political_office_prerequisite.js";
|
||||
import UndergroundType from "../../models/falukant/type/underground.js";
|
||||
import WeatherType from "../../models/falukant/type/weather.js";
|
||||
import Weather from "../../models/falukant/data/weather.js";
|
||||
import ProductWeatherEffect from "../../models/falukant/type/product_weather_effect.js";
|
||||
import ProductType from "../../models/falukant/type/product.js";
|
||||
|
||||
// Debug-Flag: Nur wenn DEBUG_FALUKANT=1 gesetzt ist, werden ausführliche Logs ausgegeben.
|
||||
const falukantDebug = process.env.DEBUG_FALUKANT === '1';
|
||||
@@ -43,6 +47,9 @@ export const initializeFalukantTypes = async () => {
|
||||
await initializePoliticalOfficePrerequisites();
|
||||
await initializeUndergroundTypes();
|
||||
await initializeVehicleTypes();
|
||||
await initializeFalukantWeatherTypes();
|
||||
await initializeFalukantWeathers();
|
||||
await initializeFalukantProductWeatherEffects();
|
||||
};
|
||||
|
||||
const regionTypes = [];
|
||||
@@ -1010,3 +1017,445 @@ export const initializeFalukantTitlesOfNobility = async () => {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const weatherTypes = [
|
||||
{ tr: "sunny" },
|
||||
{ tr: "cloudy" },
|
||||
{ tr: "rainy" },
|
||||
{ tr: "stormy" },
|
||||
{ tr: "snowy" },
|
||||
{ tr: "foggy" },
|
||||
{ tr: "windy" },
|
||||
{ tr: "clear" }
|
||||
];
|
||||
|
||||
export const initializeFalukantWeatherTypes = async () => {
|
||||
try {
|
||||
for (const weatherType of weatherTypes) {
|
||||
await WeatherType.findOrCreate({
|
||||
where: { tr: weatherType.tr },
|
||||
});
|
||||
}
|
||||
console.log(`[Falukant] Wettertypen initialisiert: ${weatherTypes.length} Typen`);
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Initialisieren der Falukant-Wettertypen:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const initializeFalukantWeathers = async () => {
|
||||
try {
|
||||
// Hole alle Städte (Regions vom Typ "city")
|
||||
const cityRegionType = await RegionType.findOne({ where: { labelTr: 'city' } });
|
||||
if (!cityRegionType) {
|
||||
console.warn('[Falukant] Kein RegionType "city" gefunden, überspringe Wetter-Initialisierung');
|
||||
return;
|
||||
}
|
||||
|
||||
const cities = await RegionData.findAll({
|
||||
where: { regionTypeId: cityRegionType.id },
|
||||
attributes: ['id', 'name']
|
||||
});
|
||||
|
||||
// Hole alle Wettertypen
|
||||
const allWeatherTypes = await WeatherType.findAll();
|
||||
if (allWeatherTypes.length === 0) {
|
||||
console.warn('[Falukant] Keine Wettertypen gefunden, überspringe Wetter-Initialisierung');
|
||||
return;
|
||||
}
|
||||
|
||||
// Weise jeder Stadt zufällig ein Wetter zu
|
||||
for (const city of cities) {
|
||||
const randomWeatherType = allWeatherTypes[Math.floor(Math.random() * allWeatherTypes.length)];
|
||||
await Weather.findOrCreate({
|
||||
where: { regionId: city.id },
|
||||
defaults: {
|
||||
weatherTypeId: randomWeatherType.id
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`[Falukant] Wetter für ${cities.length} Städte initialisiert`);
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Initialisieren der Falukant-Wetter:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const initializeFalukantProductWeatherEffects = async () => {
|
||||
try {
|
||||
// Hole alle Produkte und Wettertypen
|
||||
const products = await ProductType.findAll();
|
||||
const weatherTypes = await WeatherType.findAll();
|
||||
|
||||
if (products.length === 0 || weatherTypes.length === 0) {
|
||||
console.warn('[Falukant] Keine Produkte oder Wettertypen gefunden, überspringe Produkt-Wetter-Effekte');
|
||||
return;
|
||||
}
|
||||
|
||||
// Erstelle Map für schnellen Zugriff
|
||||
const productMap = new Map(products.map(p => [p.labelTr, p.id]));
|
||||
const weatherMap = new Map(weatherTypes.map(w => [w.tr, w.id]));
|
||||
|
||||
// Definiere Effekte für jedes Produkt-Wetter-Paar
|
||||
// Format: { productLabel: { weatherTr: effectValue } }
|
||||
// effectValue: -2 (sehr negativ), -1 (negativ), 0 (neutral), 1 (positiv), 2 (sehr positiv)
|
||||
const effects = {
|
||||
// Landwirtschaftliche Produkte
|
||||
wheat: {
|
||||
sunny: 1, // Gutes Wachstum
|
||||
cloudy: 0,
|
||||
rainy: 2, // Wasser ist essentiell
|
||||
stormy: -1, // Kann Ernte beschädigen
|
||||
snowy: -2, // Kein Wachstum
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
grain: {
|
||||
sunny: 1,
|
||||
cloudy: 0,
|
||||
rainy: 2,
|
||||
stormy: -1,
|
||||
snowy: -2,
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
carrot: {
|
||||
sunny: 1,
|
||||
cloudy: 0,
|
||||
rainy: 2,
|
||||
stormy: -1,
|
||||
snowy: -2,
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
fish: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: -2, // Gefährlich zu fischen
|
||||
snowy: -1, // Kaltes Wasser
|
||||
foggy: -1, // Schlechte Sicht
|
||||
windy: -1, // Schwierig zu fischen
|
||||
clear: 1
|
||||
},
|
||||
meat: {
|
||||
sunny: -1, // Kann verderben
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 1, // Kühlt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
leather: {
|
||||
sunny: -1, // Kann austrocknen
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 1, // Kühlt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
wood: {
|
||||
sunny: 1, // Trocknet gut
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -2, // Kann beschädigt werden
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
stone: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: 0,
|
||||
snowy: 0,
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
milk: {
|
||||
sunny: -1, // Kann sauer werden
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: -1,
|
||||
snowy: 1, // Kühlt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
cheese: {
|
||||
sunny: -1,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -1,
|
||||
snowy: 1, // Kühlt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
bread: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -1,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
beer: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: 0,
|
||||
snowy: 1, // Kühlt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
iron: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Rost
|
||||
stormy: -2, // Rost
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
copper: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Oxidation
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
spices: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -1,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
salt: {
|
||||
sunny: 1, // Trocknet gut
|
||||
cloudy: 0,
|
||||
rainy: -2, // Löst sich auf
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
sugar: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -2, // Löst sich auf
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
vinegar: {
|
||||
sunny: 1, // Heißes Wetter fördert Gärung
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: 0,
|
||||
snowy: -1, // Kaltes Wetter hemmt Gärung
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 1 // Heißes Wetter fördert Gärung
|
||||
},
|
||||
cotton: {
|
||||
sunny: 1, // Trocknet gut
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
wine: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: 0,
|
||||
snowy: 1, // Kühlt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
gold: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: 0,
|
||||
snowy: 0,
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
diamond: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: 0,
|
||||
stormy: 0,
|
||||
snowy: 0,
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
furniture: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
clothing: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
jewelry: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -2, // Kann beschädigt werden
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
painting: {
|
||||
sunny: -1, // Kann verblassen
|
||||
cloudy: 0,
|
||||
rainy: -2, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: -1
|
||||
},
|
||||
book: {
|
||||
sunny: -1, // Kann verblassen
|
||||
cloudy: 0,
|
||||
rainy: -2, // Feucht
|
||||
stormy: -2,
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: -1
|
||||
},
|
||||
weapon: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Rost
|
||||
stormy: -2, // Rost
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
armor: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Rost
|
||||
stormy: -2, // Rost
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
shield: {
|
||||
sunny: 0,
|
||||
cloudy: 0,
|
||||
rainy: -1, // Rost
|
||||
stormy: -2, // Rost
|
||||
snowy: 0,
|
||||
foggy: -1, // Feucht
|
||||
windy: 0,
|
||||
clear: 0
|
||||
},
|
||||
horse: {
|
||||
sunny: 1, // Gutes Wetter
|
||||
cloudy: 0,
|
||||
rainy: -1, // Nass
|
||||
stormy: -2, // Angst
|
||||
snowy: -1, // Kalt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 1
|
||||
},
|
||||
ox: {
|
||||
sunny: 1, // Gutes Wetter
|
||||
cloudy: 0,
|
||||
rainy: -1, // Nass
|
||||
stormy: -2, // Angst
|
||||
snowy: -1, // Kalt
|
||||
foggy: 0,
|
||||
windy: 0,
|
||||
clear: 1
|
||||
}
|
||||
};
|
||||
|
||||
// Erstelle alle Produkt-Wetter-Effekte
|
||||
const effectEntries = [];
|
||||
for (const [productLabel, weatherEffects] of Object.entries(effects)) {
|
||||
const productId = productMap.get(productLabel);
|
||||
if (!productId) {
|
||||
console.warn(`[Falukant] Produkt "${productLabel}" nicht gefunden, überspringe`);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const [weatherTr, effectValue] of Object.entries(weatherEffects)) {
|
||||
const weatherTypeId = weatherMap.get(weatherTr);
|
||||
if (!weatherTypeId) {
|
||||
console.warn(`[Falukant] Wettertyp "${weatherTr}" nicht gefunden, überspringe`);
|
||||
continue;
|
||||
}
|
||||
|
||||
effectEntries.push({
|
||||
productId,
|
||||
weatherTypeId,
|
||||
qualityEffect: effectValue
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Bulk insert mit ignoreDuplicates
|
||||
await ProductWeatherEffect.bulkCreate(effectEntries, {
|
||||
ignoreDuplicates: true
|
||||
});
|
||||
|
||||
console.log(`[Falukant] Produkt-Wetter-Effekte initialisiert: ${effectEntries.length} Einträge`);
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Initialisieren der Produkt-Wetter-Effekte:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user