feat: track RoomChanges in clan log (#1174)

Final part for clan log; closes #1152

Reviewed-on: OpenWF/SpaceNinjaServer#1174
This commit is contained in:
Sainan 2025-03-14 02:07:08 -07:00
parent 6508d16190
commit 0c06776985
7 changed files with 89 additions and 7 deletions

View File

@ -4,7 +4,8 @@ import {
getDojoClient,
getGuildForRequestEx,
processDojoBuildMaterialsGathered,
scaleRequiredCount
scaleRequiredCount,
setDojoRoomLogFunded
} from "@/src/services/guildService";
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService";
@ -40,6 +41,10 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r
}
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
processContribution(guild, request, inventory, inventoryChanges, meta, component);
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (component.CompletionTime) {
setDojoRoomLogFunded(guild, component);
}
} else {
// Room is past "Collecting Materials"
if (request.DecoId) {

View File

@ -35,6 +35,11 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
} else {
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
processContribution(component, meta, platinumDonated);
const entry = guild.RoomChanges?.find(x => x.componentId.equals(component._id));
if (entry) {
entry.dateTime = component.CompletionTime!;
}
}
await guild.save();

View File

@ -18,6 +18,13 @@ export const getGuildLogController: RequestHandler = async (req, res) => {
StandingsUpdates: [],
ClassChanges: []
};
guild.RoomChanges?.forEach(entry => {
log.RoomChanges.push({
dateTime: toMongoDate(entry.dateTime),
entryType: entry.entryType,
details: entry.details
});
});
guild.TechChanges?.forEach(entry => {
log.TechChanges.push({
dateTime: toMongoDate(entry.dateTime),

View File

@ -1,6 +1,11 @@
import { RequestHandler } from "express";
import { IDojoComponentClient } from "@/src/types/guildTypes";
import { getDojoClient, getGuildForRequest, processDojoBuildMaterialsGathered } from "@/src/services/guildService";
import {
getDojoClient,
getGuildForRequest,
processDojoBuildMaterialsGathered,
setDojoRoomLogFunded
} from "@/src/services/guildService";
import { Types } from "mongoose";
import { ExportDojoRecipes } from "warframe-public-export-plus";
import { config } from "@/src/services/configService";
@ -21,10 +26,20 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
guild.DojoEnergy += room.energy;
}
const componentId = new Types.ObjectId();
guild.RoomChanges ??= [];
guild.RoomChanges.push({
dateTime: new Date(),
entryType: 2,
details: request.PlacedComponent.pf,
componentId: componentId
});
const component =
guild.DojoComponents[
guild.DojoComponents.push({
_id: new Types.ObjectId(),
_id: componentId,
pf: request.PlacedComponent.pf,
ppf: request.PlacedComponent.ppf,
pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
@ -38,6 +53,7 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
if (room) {
processDojoBuildMaterialsGathered(guild, room);
}
setDojoRoomLogFunded(guild, component);
}
await guild.save();
res.json(await getDojoClient(guild, 0));

View File

@ -7,7 +7,8 @@ import {
IGuildMemberDatabase,
IGuildLogEntryNumber,
IGuildLogEntryString,
IGuildRank
IGuildRank,
IGuildLogRoomChange
} from "@/src/types/guildTypes";
import { Document, Model, model, Schema, Types } from "mongoose";
import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
@ -34,6 +35,7 @@ const dojoComponentSchema = new Schema<IDojoComponentDatabase>({
RegularCredits: Number,
MiscItems: { type: [typeCountSchema], default: undefined },
CompletionTime: Date,
CompletionLogPending: Boolean,
RushPlatinum: Number,
DestructionTime: Date,
Decos: [dojoDecoSchema],
@ -115,6 +117,16 @@ const guildLogEntryStringSchema = new Schema<IGuildLogEntryString>(
{ _id: false }
);
const guildLogRoomChangeSchema = new Schema<IGuildLogRoomChange>(
{
dateTime: Date,
entryType: Number,
details: String,
componentId: Types.ObjectId
},
{ _id: false }
);
const guildLogEntryNumberSchema = new Schema<IGuildLogEntryNumber>(
{
dateTime: Date,
@ -146,6 +158,7 @@ const guildSchema = new Schema<IGuildDatabase>(
CeremonyContributors: { type: [Types.ObjectId], default: undefined },
CeremonyResetDate: Date,
CeremonyEndo: Number,
RoomChanges: { type: [guildLogRoomChangeSchema], default: undefined },
TechChanges: { type: [guildLogEntryStringSchema], default: undefined },
RosterActivity: { type: [guildLogEntryStringSchema], default: undefined },
ClassChanges: { type: [guildLogEntryNumberSchema], default: undefined }

View File

@ -6,6 +6,7 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
import {
IDojoClient,
IDojoComponentClient,
IDojoComponentDatabase,
IDojoContributable,
IDojoDecoClient,
IGuildClient,
@ -126,7 +127,8 @@ export const getDojoClient = async (
DojoComponents: []
};
const roomsToRemove: Types.ObjectId[] = [];
guild.DojoComponents.forEach(dojoComponent => {
let needSave = false;
for (const dojoComponent of guild.DojoComponents) {
if (!componentId || dojoComponent._id.equals(componentId)) {
const clientComponent: IDojoComponentClient = {
id: toOid(dojoComponent._id),
@ -143,10 +145,18 @@ export const getDojoClient = async (
}
if (dojoComponent.CompletionTime) {
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
if (dojoComponent.CompletionLogPending && Date.now() >= dojoComponent.CompletionTime.getTime()) {
const entry = guild.RoomChanges?.find(x => x.componentId.equals(dojoComponent._id));
if (entry) {
dojoComponent.CompletionLogPending = undefined;
entry.entryType = 1;
needSave = true;
}
}
if (dojoComponent.DestructionTime) {
if (Date.now() >= dojoComponent.DestructionTime.getTime()) {
roomsToRemove.push(dojoComponent._id);
return;
continue;
}
clientComponent.DestructionTime = toMongoDate(dojoComponent.DestructionTime);
}
@ -175,12 +185,15 @@ export const getDojoClient = async (
}
dojo.DojoComponents.push(clientComponent);
}
});
}
if (roomsToRemove.length) {
logger.debug(`removing now-destroyed rooms`, roomsToRemove);
for (const id of roomsToRemove) {
removeDojoRoom(guild, id);
}
needSave = true;
}
if (needSave) {
await guild.save();
}
return dojo;
@ -203,6 +216,13 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types
}
moveResourcesToVault(guild, component);
component.Decos?.forEach(deco => moveResourcesToVault(guild, deco));
if (guild.RoomChanges) {
const index = guild.RoomChanges.findIndex(x => x.componentId.equals(component._id));
if (index != -1) {
guild.RoomChanges.splice(index, 1);
}
}
};
export const removeDojoDeco = (
@ -254,6 +274,16 @@ export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument,
}
};
// guild.save(); is expected some time after this function is called
export const setDojoRoomLogFunded = (guild: TGuildDatabaseDocument, component: IDojoComponentDatabase): void => {
const entry = guild.RoomChanges?.find(x => x.componentId.equals(component._id));
if (entry && entry.entryType == 2) {
entry.entryType = 0;
entry.dateTime = component.CompletionTime!;
component.CompletionLogPending = true;
}
};
export const fillInInventoryDataForGuildMember = async (member: IGuildMemberClient): Promise<void> => {
const inventory = await getInventory(member._id.$oid, "PlayerLevel ActiveAvatarImageType");
member.PlayerLevel = config.spoofMasteryRank == -1 ? inventory.PlayerLevel : config.spoofMasteryRank;

View File

@ -48,6 +48,7 @@ export interface IGuildDatabase {
CeremonyContributors?: Types.ObjectId[];
CeremonyResetDate?: Date;
RoomChanges?: IGuildLogRoomChange[];
TechChanges?: IGuildLogEntryString[];
RosterActivity?: IGuildLogEntryString[];
ClassChanges?: IGuildLogEntryNumber[];
@ -146,6 +147,7 @@ export interface IDojoComponentDatabase
_id: Types.ObjectId;
pi?: Types.ObjectId;
CompletionTime?: Date;
CompletionLogPending?: boolean;
DestructionTime?: Date;
Decos?: IDojoDecoDatabase[];
}
@ -193,6 +195,10 @@ export interface IGuildLogEntryString {
details: string;
}
export interface IGuildLogRoomChange extends IGuildLogEntryString {
componentId: Types.ObjectId;
}
export interface IGuildLogEntryNumber {
dateTime: Date;
entryType: number;