Skip to content

Commit

Permalink
fix global stats date issues
Browse files Browse the repository at this point in the history
  • Loading branch information
mrosack committed Dec 4, 2023
1 parent 2118be0 commit e4eae5b
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 147 deletions.
9 changes: 3 additions & 6 deletions api/controllers/gameController/revert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ import { IUserRepository, USER_REPOSITORY_SYMBOL } from '../../../lib/dynamoose/
import { inject, provideSingleton } from '../../../lib/ioc';
import { pydtLogger } from '../../../lib/logging';
import { Game, GameTurn } from '../../../lib/models';
import {
GAME_TURN_SERVICE_SYMBOL,
GameTurnService,
IGameTurnService
} from '../../../lib/services/gameTurnService';
import { GAME_TURN_SERVICE_SYMBOL, IGameTurnService } from '../../../lib/services/gameTurnService';
import { ISnsProvider, SNS_PROVIDER_SYMBOL } from '../../../lib/snsProvider';
import { GameUtil } from '../../../lib/util/gameUtil';
import { ErrorResponse, HttpRequest, HttpResponseError } from '../../framework';
import { ISqsProvider, SQS_PROVIDER_SYMBOL } from '../../../lib/sqsProvider';
import { StatsUtil } from '../../../lib/util/statsUtil';

@Route('game')
@Tags('game')
Expand Down Expand Up @@ -61,7 +58,7 @@ export class GameController_Revert {
} while (!lastTurn);

const user = await this.userRepository.get(lastTurn.playerSteamId);
GameTurnService.updateTurnStatistics(game, lastTurn, user, true);
StatsUtil.updateTurnStatistics(game, lastTurn, user, true);

// Update previous turn data
delete lastTurn.skipped;
Expand Down
9 changes: 4 additions & 5 deletions functions/sns/dataMigrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import { IUserRepository, USER_REPOSITORY_SYMBOL } from '../../lib/dynamoose/use
import { inject } from '../../lib/ioc';
import { loggingHandler } from '../../lib/logging';
import { Game, TurnData, User } from '../../lib/models';
import { GameTurnService } from '../../lib/services/gameTurnService';
import {
IMiscDataRepository,
MISC_DATA_REPOSITORY_SYMBOL
} from '../../lib/dynamoose/miscDataRepository';
import { UserUtil } from '../../lib/util/userUtil';
import { GameUtil } from '../../lib/util/gameUtil';
import { StatsUtil } from '../../lib/util/statsUtil';

export const handler = loggingHandler(async (event, context, iocContainer) => {
const rus = iocContainer.resolve(DataMigrations);
Expand Down Expand Up @@ -105,7 +104,7 @@ export class DataMigrations {
user.statsByGameType = [];

for (const turn of allTurns) {
GameTurnService.updateTurnStatistics(
StatsUtil.updateTurnStatistics(
allGames[turn.gameId] ||
({
players: []
Expand Down Expand Up @@ -146,7 +145,7 @@ export class DataMigrations {
const turns = await this.gameTurnRepository.getAllTurnsForGame(game.gameId);

for (const turn of turns) {
GameTurnService.updateTurnStatistics(game, turn, {
StatsUtil.updateTurnStatistics(game, turn, {
steamId: turn.playerSteamId
} as User);
}
Expand All @@ -157,7 +156,7 @@ export class DataMigrations {

for (const curStats of [
globalStats.data,
UserUtil.getUserGameStats(globalStats.data, game.gameType)
StatsUtil.getGameStats(globalStats.data, game.gameType)
]) {
if (
!curStats.firstTurnEndDate ||
Expand Down
10 changes: 5 additions & 5 deletions functions/sqs/globalStatsUpdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import {
IMiscDataRepository,
MISC_DATA_REPOSITORY_SYMBOL
} from '../../lib/dynamoose/miscDataRepository';
import { GameTurnService } from '../../lib/services/gameTurnService';
import { GlobalStatsUpdateMessage } from '../../lib/sqsProvider';
import { UserUtil } from '../../lib/util/userUtil';
import { StatsUtil } from '../../lib/util/statsUtil';

export const handler = loggingHandler(async (event, context, iocContainer) => {
const uugc = iocContainer.resolve(GlobalStatsUpdate);
Expand All @@ -25,16 +24,17 @@ export class GlobalStatsUpdate {
const globalStats = await this.miscDataRepository.getGlobalStats(true);

for (const message of messages) {
console.log(message);
message.turn.endDate = message.turn.endDate ? new Date(message.turn.endDate) : undefined;
message.turn.startDate = message.turn.startDate
? new Date(message.turn.startDate)
: undefined;

GameTurnService.updateTurnData(message.turn, globalStats.data, message.undo);
StatsUtil.updateTurnData(message.turn, globalStats.data, message.undo);

GameTurnService.updateTurnData(
StatsUtil.updateTurnData(
message.turn,
UserUtil.getUserGameStats(globalStats.data, message.gameType),
StatsUtil.getGameStats(globalStats.data, message.gameType),
message.undo
);
}
Expand Down
7 changes: 2 additions & 5 deletions lib/dynamoose/gameRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Game, GamePlayer, User } from '../models';
import { BaseDynamooseRepository, IRepository } from './common';
import { CIV6_GAME } from '../metadata/civGames/civ6';
import { legacyBoolean, legacyStringSet } from '../util/dynamooseLegacy';
import { StatsUtil } from '../util/statsUtil';

export const GAME_REPOSITORY_SYMBOL = Symbol('IGameRepository');

Expand Down Expand Up @@ -79,11 +80,7 @@ export class GameRepository
// Legacy complex array, see above
type: String,
get: (value: string) =>
(value ? JSON.parse(value) : []).map(x => ({
...x,
firstTurnEndDate: x.firstTurnEndDate ? new Date(x.firstTurnEndDate) : undefined,
lastTurnEndDate: x.lastTurnEndDate ? new Date(x.lastTurnEndDate) : undefined
})),
(value ? JSON.parse(value) : []).map(x => StatsUtil.fixTurnDataDates(x)),
pydtSet: (value: GamePlayer[]) => {
return JSON.stringify(
(value || []).map(x => ({
Expand Down
12 changes: 6 additions & 6 deletions lib/dynamoose/miscDataRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Config } from '../config';
import { provideSingleton } from '../ioc';
import { GlobalStats, MiscData } from '../models/miscData';
import { StatsUtil } from '../util/statsUtil';
import { BaseDynamooseRepository, IRepository } from './common';

export const MISC_DATA_REPOSITORY_SYMBOL = Symbol('IMiscDataRepository');
Expand Down Expand Up @@ -37,12 +38,11 @@ export class MiscDataRepository
}
}) as GlobalStats;

result.data.firstTurnEndDate = result.data.firstTurnEndDate
? new Date(result.data.firstTurnEndDate)
: undefined;
result.data.lastTurnEndDate = result.data.lastTurnEndDate
? new Date(result.data.lastTurnEndDate)
: undefined;
StatsUtil.fixTurnDataDates(result.data);

for (const gameType of result.data.statsByGameType || []) {
StatsUtil.fixTurnDataDates(gameType);
}

return result;
}
Expand Down
7 changes: 2 additions & 5 deletions lib/dynamoose/userRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { User, DeprecatedUser } from '../models/user';
import { BaseDynamooseRepository, IRepository } from './common';
import { Game, GameTypeTurnData } from '../models';
import { legacyBoolean, legacyStringSet } from '../util/dynamooseLegacy';
import { StatsUtil } from '../util/statsUtil';

export const USER_REPOSITORY_SYMBOL = Symbol('IUserRepository');

Expand Down Expand Up @@ -117,11 +118,7 @@ export class UserRepository
// Legacy complex array, see above
type: String,
get: (value: string) =>
(value ? JSON.parse(value) : []).map(x => ({
...x,
firstTurnEndDate: x.firstTurnEndDate ? new Date(x.firstTurnEndDate) : undefined,
lastTurnEndDate: x.lastTurnEndDate ? new Date(x.lastTurnEndDate) : undefined
})),
(value ? JSON.parse(value) : []).map(x => StatsUtil.fixTurnDataDates(x)),
pydtSet: (value: GameTypeTurnData[]) => {
return JSON.stringify(
(value || []).map(x => ({
Expand Down
12 changes: 6 additions & 6 deletions lib/services/gameTurnService.int-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'reflect-metadata';
import { aws as dynamooseAws, Table } from 'dynamoose';
import { describe, it } from 'mocha';
import { v4 as uuid } from 'uuid';
import { GameTurnService } from './gameTurnService';
import { GameRepository } from '../dynamoose/gameRepository';
import { CIV6_GAME } from '../metadata/civGames/civ6';
import { Game, GameTurn, User } from '../models';
Expand All @@ -11,6 +10,7 @@ import { UserRepository } from '../dynamoose/userRepository';
import { expect } from 'chai';
import { cloneDeep } from 'lodash';
import { ONE_DAY, ONE_HOUR } from 'pydt-shared-models';
import { StatsUtil } from '../util/statsUtil';

dynamooseAws.ddb.set(
new dynamooseAws.ddb.DynamoDB({
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('GameTurnService_updateTurnStatistics', () => {
displayName: 'player 1'
} as User;

GameTurnService.updateTurnStatistics(game, turn1, user);
StatsUtil.updateTurnStatistics(game, turn1, user);

const gameRepository = new GameRepository();
const userRepository = new UserRepository();
Expand Down Expand Up @@ -114,7 +114,7 @@ describe('GameTurnService_updateTurnStatistics', () => {
expect(data.lastTurnEndDate).to.deep.equal(new Date('2023-11-02T09:00:00.000Z'));
}

GameTurnService.updateTurnStatistics(game, turn2, user);
StatsUtil.updateTurnStatistics(game, turn2, user);

await gameRepository.saveVersioned(game);
await userRepository.saveVersioned(user);
Expand Down Expand Up @@ -148,7 +148,7 @@ describe('GameTurnService_updateTurnStatistics', () => {
expect(data.lastTurnEndDate).to.deep.equal(new Date('2023-11-02T23:00:00.000Z'));
}

GameTurnService.updateTurnStatistics(game, turn3, user);
StatsUtil.updateTurnStatistics(game, turn3, user);

await gameRepository.saveVersioned(game);
await userRepository.saveVersioned(user);
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('GameTurnService_updateTurnStatistics', () => {
expect(data.lastTurnEndDate).to.deep.equal(new Date('2023-11-03T23:00:00.000Z'));
}

GameTurnService.updateTurnStatistics(game, turn3, user, true);
StatsUtil.updateTurnStatistics(game, turn3, user, true);

await gameRepository.saveVersioned(game);
await userRepository.saveVersioned(user);
Expand Down Expand Up @@ -216,7 +216,7 @@ describe('GameTurnService_updateTurnStatistics', () => {
expect(data.lastTurnEndDate).to.deep.equal(new Date('2023-11-03T23:00:00.000Z'));
}

GameTurnService.updateTurnStatistics(game, turn2, user, true);
StatsUtil.updateTurnStatistics(game, turn2, user, true);

await gameRepository.saveVersioned(game);
await userRepository.saveVersioned(user);
Expand Down
83 changes: 3 additions & 80 deletions lib/services/gameTurnService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { GAME_TURN_REPOSITORY_SYMBOL, IGameTurnRepository } from '../dynamoose/g
import { IUserRepository, USER_REPOSITORY_SYMBOL } from '../dynamoose/userRepository';
import { inject, provideSingleton } from '../ioc';
import { pydtLogger } from '../logging';
import { Game, GamePlayer, GameTurn, TurnData, User } from '../models';
import { Game, GamePlayer, GameTurn, User } from '../models';
import { IS3Provider, S3_PROVIDER_SYMBOL } from '../s3Provider';
import { ActorType, SaveHandler } from '../saveHandlers/saveHandler';
import { SaveHandlerFactory } from '../saveHandlers/saveHandlerFactory';
Expand All @@ -20,7 +20,7 @@ import {
IPrivateUserDataRepository
} from '../dynamoose/privateUserDataRepository';
import { ISqsProvider, SQS_PROVIDER_SYMBOL } from '../sqsProvider';
import { HOUR_OF_DAY_KEY, ONE_HOUR, TURN_BUCKETS } from 'pydt-shared-models';
import { StatsUtil } from '../util/statsUtil';

export const GAME_TURN_SERVICE_SYMBOL = Symbol('IGameTurnService');

Expand Down Expand Up @@ -66,7 +66,7 @@ export class GameTurnService implements IGameTurnService {
private async closeGameTurn(game: Game, gameTurn: GameTurn, user: User) {
game.lastTurnEndDate = gameTurn.endDate = new Date();

GameTurnService.updateTurnStatistics(game, gameTurn, user);
StatsUtil.updateTurnStatistics(game, gameTurn, user);

await this.gameTurnRepository.saveVersioned(gameTurn);
}
Expand Down Expand Up @@ -149,83 +149,6 @@ export class GameTurnService implements IGameTurnService {
await this.updateSaveFileForGameState(game, users, this.parseSaveFile(data.Body, game));
}

public static updateTurnStatistics(game: Game, gameTurn: GameTurn, user: User, undo?: boolean) {
const player =
game.players.find(p => {
return p.steamId === user.steamId;
}) || ({} as GamePlayer);

const gameStats = UserUtil.getUserGameStats(user, game.gameType);

GameTurnService.updateTurnData(gameTurn, player, !!undo);
GameTurnService.updateTurnData(gameTurn, user, !!undo);
GameTurnService.updateTurnData(gameTurn, gameStats, !!undo);
GameTurnService.updateTurnData(gameTurn, game, !!undo);
}

public static updateTurnData(gameTurn: GameTurn, turnData: Partial<TurnData>, undo: boolean) {
const undoInc = undo ? -1 : 1;

if (gameTurn.endDate) {
if (!turnData.firstTurnEndDate || gameTurn.endDate < turnData.firstTurnEndDate) {
turnData.firstTurnEndDate = gameTurn.endDate;
}

if (!turnData.lastTurnEndDate || gameTurn.endDate > turnData.lastTurnEndDate) {
turnData.lastTurnEndDate = gameTurn.endDate;
}

turnData.turnLengthBuckets = turnData.turnLengthBuckets || {};
turnData.yearBuckets = turnData.yearBuckets || {};

if (gameTurn.skipped) {
turnData.turnsSkipped = (turnData.turnsSkipped || 0) + undoInc;
} else {
turnData.turnsPlayed = (turnData.turnsPlayed || 0) + undoInc;

const timeTaken = gameTurn.endDate.getTime() - gameTurn.startDate.getTime();
turnData.timeTaken = (turnData.timeTaken || 0) + timeTaken * undoInc;

if (timeTaken < ONE_HOUR) {
turnData.fastTurns = (turnData.fastTurns || 0) + undoInc;
}

if (timeTaken > ONE_HOUR * 6) {
turnData.slowTurns = (turnData.slowTurns || 0) + undoInc;
}

const MAX_QUEUE_LENGTH = 100;

// Not sure undoing these queues will make sense in all scenarios...
if (!undo) {
turnData.hourOfDayQueue =
(turnData.hourOfDayQueue || '') + HOUR_OF_DAY_KEY[gameTurn.endDate.getUTCHours()];

if (turnData.hourOfDayQueue.length > MAX_QUEUE_LENGTH) {
turnData.hourOfDayQueue = turnData.hourOfDayQueue.substring(1);
}

turnData.dayOfWeekQueue = (turnData.dayOfWeekQueue || '') + gameTurn.endDate.getUTCDay();

if (turnData.dayOfWeekQueue.length > MAX_QUEUE_LENGTH) {
turnData.dayOfWeekQueue = turnData.dayOfWeekQueue.substring(1);
}
}

turnData.yearBuckets[gameTurn.endDate.getUTCFullYear()] =
(turnData.yearBuckets[gameTurn.endDate.getUTCFullYear()] || 0) + undoInc;

for (const bucket of TURN_BUCKETS) {
if (timeTaken < bucket) {
turnData.turnLengthBuckets[bucket] =
(turnData.turnLengthBuckets[bucket] || 0) + undoInc;
break;
}
}
}
}
}

public async updateSaveFileForGameState(game, users, handler: SaveHandler, setPlayerType = true) {
for (let i = 0; i < handler.civData.length; i++) {
if (game.players[i]) {
Expand Down
Loading

0 comments on commit e4eae5b

Please sign in to comment.