Skip to content

Commit

Permalink
feat: ✨ location updator 에 daily logtimes 갱신하는 로직 추가
Browse files Browse the repository at this point in the history
- close #52
  • Loading branch information
jpham005 committed Nov 6, 2023
1 parent 66031be commit cfab9ec
Showing 1 changed file with 132 additions and 0 deletions.
132 changes: 132 additions & 0 deletions app/src/location/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ import {
import { hasId } from '#lambda/util/hasId.js';

export const LOCATION_COLLECTION = 'locations';
export const DAILY_LOGTIME_COLLECTION = 'daily_logtimes';

type LocationsPerUser = {
userId: number;
locations: Pick<Location, 'beginAt' | 'endAt'>[];
};

type DailyLogtime = {
userId: number;
date: Date;
value: number;
};

// eslint-disable-next-line
export class LocationUpdator {
Expand Down Expand Up @@ -46,6 +58,7 @@ export class LocationUpdator {
await LocationUpdator.updatePrevOngoing(mongo);
await LocationUpdator.updateOngoing(mongo, start, end);
await LocationUpdator.updateEnded(mongo, start, end);
await LocationUpdator.updateDailyLogtime(mongo, end);
},
});
}
Expand Down Expand Up @@ -151,4 +164,123 @@ export class LocationUpdator {

return parseLocations(locationDtos);
}

@UpdateAction
@LogAsyncEstimatedTime
private static async updateDailyLogtime(
mongo: LambdaMongo,
end: Date,
): Promise<void> {
const start = new Date(end.getTime() - 1000 * 60 * 60 * 24 * 30);

const locations = await LocationUpdator.findLocationsPerUserByDate(
mongo,
start,
end,
);

const dailyLogtimes = locations.reduce(
(accLogtimes, location) => [
...accLogtimes,
...LocationUpdator.toDailyLogtime(location, start, end),
],
new Array<DailyLogtime>(),
);

await Promise.all(
dailyLogtimes.map((dailyLogtime) =>
LocationUpdator.saveDailyLogtime(mongo, dailyLogtime),
),
);
}

private static async findLocationsPerUserByDate(
mongo: LambdaMongo,
start: Date,
end: Date,
): Promise<LocationsPerUser[]> {
return await mongo
.db()
.collection(LOCATION_COLLECTION)
.aggregate<LocationsPerUser>([
{
$match: {
beginAt: { $lt: end },
$or: [{ endAt: { $gte: start } }, { endAt: null }],
},
},
{
$group: {
_id: '$user.id',
locations: {
$push: {
beginAt: '$beginAt',
endAt: '$endAt',
},
},
},
},
{
$project: {
_id: 0,
userId: '$_id',
locations: 1,
},
},
])
.toArray();
}

private static toDailyLogtime(
{ userId, locations }: LocationsPerUser,
start: Date,
end: Date,
): DailyLogtime[] {
const logtimeMap = locations.reduce((logtimeMap, curr) => {
const startDateTime = Math.max(curr.beginAt.getTime(), start.getTime());
const endDateTime = curr.endAt?.getTime() ?? end.getTime();

for (
let dateTime = startDateTime;
dateTime < endDateTime;
dateTime = new Date(dateTime).setHours(24, 0, 0, 0)
) {
const beginOfDate = new Date(dateTime).setHours(0, 0, 0, 0);
const beginOfNextDate = new Date(dateTime).setHours(24, 0, 0, 0);

const prevLogtime = logtimeMap.get(beginOfDate) ?? 0;

logtimeMap.set(
beginOfDate,
prevLogtime + (Math.min(endDateTime, beginOfNextDate) - dateTime),
);
}

return logtimeMap;
}, new Map<number, number>());

return Array.from(logtimeMap.entries()).map(([date, value]) => ({
userId,
date: new Date(date),
value,
}));
}

private static async saveDailyLogtime(
mongo: LambdaMongo,
logtime: DailyLogtime,
): Promise<void> {
await mongo.db().collection(DAILY_LOGTIME_COLLECTION).updateOne(
{
userId: logtime.userId,
date: logtime.date,
},
{
$set: logtime,
},
{
upsert: true,
},
);
}
}

0 comments on commit cfab9ec

Please sign in to comment.