Add reputation actions and localization updates: Implement getReputationActions method in FalukantService, enhancing reputation management. Update German and English localization files to include new reputation action terms and mood descriptions, improving user experience and clarity.
This commit is contained in:
@@ -70,6 +70,7 @@ import TownProductWorth from '../models/falukant/data/town_product_worth.js';
|
||||
import ProductWeatherEffect from '../models/falukant/type/product_weather_effect.js';
|
||||
import WeatherType from '../models/falukant/type/weather.js';
|
||||
import ReputationActionType from '../models/falukant/type/reputation_action.js';
|
||||
import ReputationActionLog from '../models/falukant/log/reputation_action.js';
|
||||
|
||||
function calcAge(birthdate) {
|
||||
const b = new Date(birthdate); b.setHours(0, 0);
|
||||
@@ -465,7 +466,7 @@ class FalukantService extends BaseService {
|
||||
{
|
||||
model: FalukantCharacter,
|
||||
as: 'character',
|
||||
attributes: ['id', 'birthdate', 'health'],
|
||||
attributes: ['id', 'birthdate', 'health', 'reputation'],
|
||||
include: [
|
||||
{
|
||||
model: Relationship,
|
||||
@@ -3007,10 +3008,96 @@ class FalukantService extends BaseService {
|
||||
return TitleOfNobility.findAll();
|
||||
}
|
||||
|
||||
async getReputationActions() {
|
||||
return ReputationActionType.findAll({
|
||||
async getReputationActions(hashedUserId) {
|
||||
const user = await getFalukantUserOrFail(hashedUserId);
|
||||
|
||||
// Lade alle Action-Typen
|
||||
const actionTypes = await ReputationActionType.findAll({
|
||||
order: [['cost', 'ASC']]
|
||||
});
|
||||
|
||||
// Berechne tägliche Nutzung (heute)
|
||||
const todayStart = new Date();
|
||||
todayStart.setHours(0, 0, 0, 0);
|
||||
const todayEnd = new Date();
|
||||
todayEnd.setHours(23, 59, 59, 999);
|
||||
|
||||
const todayActions = await ReputationActionLog.count({
|
||||
where: {
|
||||
falukantUserId: user.id,
|
||||
actionTimestamp: {
|
||||
[Op.between]: [todayStart, todayEnd]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Standard-Limits (können später konfigurierbar gemacht werden)
|
||||
const dailyCap = 10; // Maximal 10 Actions pro Tag
|
||||
const dailyUsed = todayActions;
|
||||
const dailyRemaining = Math.max(0, dailyCap - dailyUsed);
|
||||
|
||||
// Cooldown: 60 Minuten zwischen Actions
|
||||
const cooldownMinutes = 60;
|
||||
const lastAction = await ReputationActionLog.findOne({
|
||||
where: { falukantUserId: user.id },
|
||||
order: [['actionTimestamp', 'DESC']],
|
||||
attributes: ['actionTimestamp']
|
||||
});
|
||||
|
||||
let cooldownRemainingSec = 0;
|
||||
if (lastAction && lastAction.actionTimestamp) {
|
||||
const now = new Date();
|
||||
const lastActionTime = new Date(lastAction.actionTimestamp);
|
||||
const secondsSinceLastAction = Math.floor((now - lastActionTime) / 1000);
|
||||
const cooldownSec = cooldownMinutes * 60;
|
||||
cooldownRemainingSec = Math.max(0, cooldownSec - secondsSinceLastAction);
|
||||
}
|
||||
|
||||
// Berechne timesUsed für jede Action (basierend auf decay_window_days)
|
||||
const actionsWithUsage = await Promise.all(actionTypes.map(async (actionType) => {
|
||||
const windowStart = new Date();
|
||||
windowStart.setDate(windowStart.getDate() - actionType.decayWindowDays);
|
||||
|
||||
const usageCount = await ReputationActionLog.count({
|
||||
where: {
|
||||
falukantUserId: user.id,
|
||||
actionTypeId: actionType.id,
|
||||
actionTimestamp: {
|
||||
[Op.gte]: windowStart
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Berechne aktuellen Gewinn basierend auf decay
|
||||
let currentGain = actionType.baseGain;
|
||||
for (let i = 0; i < usageCount; i++) {
|
||||
currentGain = Math.max(
|
||||
actionType.minGain,
|
||||
Math.floor(currentGain * actionType.decayFactor)
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
id: actionType.id,
|
||||
tr: actionType.tr,
|
||||
cost: actionType.cost,
|
||||
baseGain: actionType.baseGain,
|
||||
currentGain: currentGain,
|
||||
timesUsed: usageCount,
|
||||
decayFactor: actionType.decayFactor,
|
||||
minGain: actionType.minGain,
|
||||
decayWindowDays: actionType.decayWindowDays
|
||||
};
|
||||
}));
|
||||
|
||||
return {
|
||||
actions: actionsWithUsage,
|
||||
dailyCap,
|
||||
dailyUsed,
|
||||
dailyRemaining,
|
||||
cooldownMinutes,
|
||||
cooldownRemainingSec
|
||||
};
|
||||
}
|
||||
|
||||
async getHouseTypes() {
|
||||
|
||||
@@ -651,6 +651,7 @@
|
||||
"happy": "Glücklich",
|
||||
"sad": "Traurig",
|
||||
"angry": "Wütend",
|
||||
"calm": "Ruhig",
|
||||
"nervous": "Nervös",
|
||||
"excited": "Aufgeregt",
|
||||
"bored": "Gelangweilt",
|
||||
@@ -746,7 +747,34 @@
|
||||
"reputation": {
|
||||
"title": "Reputation",
|
||||
"overview": {
|
||||
"title": "Übersicht"
|
||||
"title": "Übersicht",
|
||||
"current": "Aktuelle Reputation"
|
||||
},
|
||||
"actions": {
|
||||
"title": "Reputations-Aktionen",
|
||||
"description": "Du kannst verschiedene Aktionen durchführen, um deine Reputation zu verbessern.",
|
||||
"none": "Keine Reputations-Aktionen verfügbar.",
|
||||
"action": "Aktion",
|
||||
"cost": "Kosten",
|
||||
"gain": "Gewinn",
|
||||
"timesUsed": "Verwendet",
|
||||
"execute": "Ausführen",
|
||||
"running": "Läuft...",
|
||||
"dailyLimit": "Tägliches Limit: {remaining} von {cap} Aktionen übrig",
|
||||
"cooldown": "Cooldown: Noch {minutes} Minuten",
|
||||
"type": {
|
||||
"soup_kitchen": "Suppenküche",
|
||||
"library_donation": "Bibliotheksspende",
|
||||
"scholarships": "Stipendien",
|
||||
"church_hospice": "Kirchenhospiz",
|
||||
"school_funding": "Schulfinanzierung",
|
||||
"orphanage_build": "Waisenhaus bauen",
|
||||
"bridge_build": "Brücke bauen",
|
||||
"hospital_donation": "Krankenhausspende",
|
||||
"patronage": "Mäzenatentum",
|
||||
"statue_build": "Statue errichten",
|
||||
"well_build": "Brunnen bauen"
|
||||
}
|
||||
},
|
||||
"party": {
|
||||
"title": "Feste",
|
||||
|
||||
@@ -221,6 +221,60 @@
|
||||
"nobility": {
|
||||
"cooldown": "You can only advance again on {date}."
|
||||
},
|
||||
"mood": {
|
||||
"happy": "Happy",
|
||||
"sad": "Sad",
|
||||
"angry": "Angry",
|
||||
"calm": "Calm",
|
||||
"nervous": "Nervous",
|
||||
"excited": "Excited",
|
||||
"bored": "Bored",
|
||||
"fearful": "Fearful",
|
||||
"confident": "Confident",
|
||||
"curious": "Curious",
|
||||
"hopeful": "Hopeful",
|
||||
"frustrated": "Frustrated",
|
||||
"lonely": "Lonely",
|
||||
"grateful": "Grateful",
|
||||
"jealous": "Jealous",
|
||||
"guilty": "Guilty",
|
||||
"apathetic": "Apathetic",
|
||||
"relieved": "Relieved",
|
||||
"proud": "Proud",
|
||||
"ashamed": "Ashamed"
|
||||
},
|
||||
"character": {
|
||||
"brave": "Brave",
|
||||
"kind": "Kind",
|
||||
"greedy": "Greedy",
|
||||
"wise": "Wise",
|
||||
"loyal": "Loyal",
|
||||
"cunning": "Cunning",
|
||||
"generous": "Generous",
|
||||
"arrogant": "Arrogant",
|
||||
"honest": "Honest",
|
||||
"ambitious": "Ambitious",
|
||||
"patient": "Patient",
|
||||
"impatient": "Impatient",
|
||||
"selfish": "Selfish",
|
||||
"charismatic": "Charismatic",
|
||||
"empathetic": "Empathetic",
|
||||
"timid": "Timid",
|
||||
"stubborn": "Stubborn",
|
||||
"resourceful": "Resourceful",
|
||||
"reckless": "Reckless",
|
||||
"disciplined": "Disciplined",
|
||||
"optimistic": "Optimistic",
|
||||
"pessimistic": "Pessimistic",
|
||||
"manipulative": "Manipulative",
|
||||
"independent": "Independent",
|
||||
"dependent": "Dependent",
|
||||
"adventurous": "Adventurous",
|
||||
"humble": "Humble",
|
||||
"vengeful": "Vengeful",
|
||||
"pragmatic": "Pragmatic",
|
||||
"idealistic": "Idealistic"
|
||||
},
|
||||
"healthview": {
|
||||
"title": "Health",
|
||||
"age": "Age",
|
||||
@@ -436,6 +490,77 @@
|
||||
"success": "The child has been baptized.",
|
||||
"error": "The child could not be baptized."
|
||||
}
|
||||
},
|
||||
"reputation": {
|
||||
"title": "Reputation",
|
||||
"overview": {
|
||||
"title": "Overview",
|
||||
"current": "Current Reputation"
|
||||
},
|
||||
"actions": {
|
||||
"title": "Reputation Actions",
|
||||
"description": "You can perform various actions to improve your reputation.",
|
||||
"none": "No reputation actions available.",
|
||||
"action": "Action",
|
||||
"cost": "Cost",
|
||||
"gain": "Gain",
|
||||
"timesUsed": "Used",
|
||||
"execute": "Execute",
|
||||
"running": "Running...",
|
||||
"dailyLimit": "Daily limit: {remaining} of {cap} actions remaining",
|
||||
"cooldown": "Cooldown: {minutes} minutes remaining",
|
||||
"type": {
|
||||
"soup_kitchen": "Soup Kitchen",
|
||||
"library_donation": "Library Donation",
|
||||
"scholarships": "Scholarships",
|
||||
"church_hospice": "Church Hospice",
|
||||
"school_funding": "School Funding",
|
||||
"orphanage_build": "Build Orphanage",
|
||||
"bridge_build": "Build Bridge",
|
||||
"hospital_donation": "Hospital Donation",
|
||||
"patronage": "Patronage",
|
||||
"statue_build": "Build Statue",
|
||||
"well_build": "Build Well"
|
||||
}
|
||||
},
|
||||
"party": {
|
||||
"title": "Parties",
|
||||
"totalCost": "Total Cost",
|
||||
"order": "Order Party",
|
||||
"inProgress": "Parties in Preparation",
|
||||
"completed": "Completed Parties",
|
||||
"newpartyview": {
|
||||
"open": "Create New Party",
|
||||
"close": "Hide New Party",
|
||||
"type": "Party Type"
|
||||
},
|
||||
"music": {
|
||||
"label": "Music",
|
||||
"none": "No Music",
|
||||
"bard": "A Bard",
|
||||
"villageBand": "A Village Band",
|
||||
"chamberOrchestra": "A Chamber Orchestra",
|
||||
"symphonyOrchestra": "A Symphony Orchestra",
|
||||
"symphonyOrchestraWithChorusAndSolists": "A Symphony Orchestra with Chorus and Soloists"
|
||||
},
|
||||
"banquette": {
|
||||
"label": "Food",
|
||||
"bread": "Bread",
|
||||
"roastWithBeer": "Roast with Beer",
|
||||
"poultryWithVegetablesAndWine": "Poultry with Vegetables and Wine",
|
||||
"extensiveBuffet": "Festive Meal"
|
||||
},
|
||||
"servants": {
|
||||
"label": "One servant per ",
|
||||
"perPersons": " persons"
|
||||
},
|
||||
"esteemedInvites": {
|
||||
"label": "Invited Estates"
|
||||
},
|
||||
"type": "Party Type",
|
||||
"cost": "Cost",
|
||||
"date": "Date"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('falukant.family.spouse.mood') }}</td>
|
||||
<td>{{ $t(`falukant.mood.${relationships[0].character2.mood.tr}`) }}</td>
|
||||
<td>{{ relationships[0].character2.mood?.tr ? $t(`falukant.mood.${relationships[0].character2.mood.tr}`) : '—' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t('falukant.family.spouse.status') }}</td>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div v-else-if="activeTab === 'advance'">
|
||||
<div class="advance-section" v-if="next && next.labelTr">
|
||||
<p>
|
||||
{{ $t('falukant.nobility.nextTitle') }}:
|
||||
{{ $t('falukant.nobility.<<nextTitle') }}:
|
||||
<strong>{{ $t(`falukant.titles.${gender}.${next.labelTr}`) }}</strong>
|
||||
</p>
|
||||
<ul class="prerequisites" v-if="next.requirements && next.requirements.length > 0">
|
||||
|
||||
Reference in New Issue
Block a user