Skip to content

Commit e7d2006

Browse files
committed
Merge branch 'feat/player-drops-page-improvements' into develop
2 parents 065e319 + 6017647 commit e7d2006

7 files changed

Lines changed: 86 additions & 13 deletions

File tree

panel/src/pages/PlayerDropsPage/DrilldownCard.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import DrilldownOverviewSubcard from "./DrilldownOverviewSubcard";
1111
import { DisplayLodType, DrilldownRangeSelectionType } from "./PlayerDropsPage";
1212
import InlineCode from "@/components/InlineCode";
1313
import DrilldownResourcesSubcard from "./DrilldownResourcesSubcard";
14+
import { DynamicNewItem } from "@/components/DynamicNewBadge";
1415

1516

1617
export function DrilldownCardLoading({ isError }: { isError?: boolean }) {
@@ -31,17 +32,17 @@ export function DrilldownCardLoading({ isError }: { isError?: boolean }) {
3132
</div>
3233
<div className="flex flex-col flex-shrink px-1 sm:px-4 py-2 space-y-4 border-t border-b bg-secondary/35">
3334
<div className="flex items-center space-x-2">
34-
<div className='hidden xs:block'><SkullIcon className="size-4" /></div>
35-
<h2 className="font-mono text-sm">Crash Reasons</h2>
35+
<div className='hidden xs:block'><ShapesIcon className="size-4" /></div>
36+
<h2 className="font-mono text-sm">Environment Changes</h2>
3637
</div>
3738
</div>
3839
<div className="px-4 pt-2 pb-4">
3940
<PlayerDropsLoadingSpinner isError={isError} />
4041
</div>
4142
<div className="flex flex-col flex-shrink px-1 sm:px-4 py-2 space-y-4 border-t border-b bg-secondary/35">
4243
<div className="flex items-center space-x-2">
43-
<div className='hidden xs:block'><ShapesIcon className="size-4" /></div>
44-
<h2 className="font-mono text-sm">Environment Changes</h2>
44+
<div className='hidden xs:block'><SkullIcon className="size-4" /></div>
45+
<h2 className="font-mono text-sm">Crash Reasons</h2>
4546
</div>
4647
</div>
4748
<div className="px-4 pt-2 pb-4 space-y-4">
@@ -113,6 +114,9 @@ const DrilldownCardInner = function DrilldownCard({
113114
<div className="flex items-center space-x-2">
114115
<div className='hidden xs:block'><ShapesIcon className="size-4" /></div>
115116
<h2 className="font-mono text-sm">Environment Changes</h2>
117+
<DynamicNewItem featName="playerDropsEnvChangesReversed" durationDays={14}>
118+
<span className="text-2xs text-warning-inline/80">Note: This list now shows the most recent changes first.</span>
119+
</DynamicNewItem>
116120
</div>
117121
</div>
118122
<DrilldownChangesSubcard changes={windowData.changes} />

panel/src/pages/PlayerDropsPage/DrilldownChangesSubcard.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export default function DrilldownChangesSubcard({ changes }: DrilldownChangesSub
107107
};
108108

109109
const sortedChanges = useMemo(() => {
110-
return changes.sort((a, b) => a.ts - b.ts);
110+
return changes.sort((a, b) => b.ts - a.ts);
111111
}, [changes]);
112112

113113
if (!changes.length) {

panel/src/pages/PlayerDropsPage/TimelineCard.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ const TimelineCard = memo(({
3838
const endDate = new Date(dataTs);
3939
if (displayLod === 'day') {
4040
// 14d window, 12h+15m padding start
41-
startDate.setHours(-(14 * 24) - 12, -15, 0, 0);
41+
const chartDurationHours = (14 - 1) * 24; //minus 1 day
42+
startDate.setHours(-chartDurationHours - 12, 0, 0, 0);
4243
endDate.setHours(12, 0, 0, 0);
4344
} else {
4445
// 7d window, 30m+15m padding start
45-
startDate.setHours(startDate.getHours() - 7 * 24, -45, 0, 0);
46-
endDate.setMinutes(30, 0, 0);
46+
const chartDurationHours = (7 * 24) + 1; //plus 1 hour
47+
startDate.setHours(startDate.getHours() - chartDurationHours, 15, 0, 0);
48+
endDate.setMinutes(endDate.getMinutes() + 30, 0, 0);
4749
}
4850
const processed = processDropsSummary(summaryData, displayLod, startDate);
4951
if (!processed) return;

panel/src/pages/PlayerDropsPage/chartingUtils.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ import { DisplayLodType } from "./PlayerDropsPage";
55

66
export type PlayerDropsCategoryCount = [category: string, count: number];
77

8+
// Helper function to floor a date to the start of the day
9+
const floorToStartOfDay = (dateString: string) => {
10+
const date = new Date(dateString);
11+
date.setHours(0, 0, 0, 0);
12+
return date.toISOString();
13+
};
14+
15+
816
/**
917
* Processes the player drops summary api data to return the data for the timeline chart.
1018
*
@@ -31,17 +39,22 @@ export const processDropsSummary = (apiData: PlayerDropsSummaryHour[], displayLo
3139
let currDayData: PlayerDropsSummaryHour | undefined;
3240
for (const hourData of windowData) {
3341
const hourDayOfMonth = (new Date(hourData.hour)).getDate();
42+
const hourDayStart = floorToStartOfDay(hourData.hour);
3443
if (!currDayData) {
3544
currDayOfMonth = hourDayOfMonth;
3645
currDayData = {
37-
hour: hourData.hour,
46+
hour: hourDayStart,
3847
changes: 0,
3948
dropTypes: [],
4049
};
4150
} else if (hourDayOfMonth !== currDayOfMonth) {
4251
binnedData.push(currDayData);
4352
currDayOfMonth = hourDayOfMonth;
44-
currDayData = structuredClone(hourData);
53+
currDayData = {
54+
hour: hourDayStart,
55+
changes: hourData.changes,
56+
dropTypes: structuredClone(hourData.dropTypes),
57+
};
4558
continue;
4659
}
4760

panel/src/pages/PlayerDropsPage/drawDropsTimeline.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ export default function drawDropsTimeline({
163163
ctx.setLineDash([]);
164164

165165
//Drawing the timeline
166+
let barsRendered = 0;
166167
ctx.lineWidth = 1;
167168
for (const intervalData of data.log) {
168169
const baseX = timeScale(intervalData.startDate);
@@ -173,6 +174,7 @@ export default function drawDropsTimeline({
173174
const renderOffsetX = baseX - renderStartX;
174175
const barWidth = Math.round(intervalWidth + renderOffsetX) + 1 - barCenterOffset - barPadding;
175176
if (barWidth < 1) continue;
177+
barsRendered++;
176178

177179
//Draw the count blocks
178180
let dropSum = 0;
@@ -221,6 +223,7 @@ export default function drawDropsTimeline({
221223
}
222224
if (isFirstRender) {
223225
console.timeEnd('drawing canvas timeline');
226+
console.log('Bars rendered:', barsRendered);
224227
}
225228
}
226229
drawCanvasTimeline();
@@ -400,8 +403,9 @@ export default function drawDropsTimeline({
400403
wasTransitionDisabled = true;
401404
}
402405
const legendWidth = legendRef.clientWidth;
403-
let legendX = datumStartX - legendWidth - 10 + margins.left;
404-
if (legendX < margins.left) legendX = datumStartX + 10 + margins.left;
406+
const legendOffset = 36;
407+
let legendX = datumStartX - legendWidth - legendOffset + margins.left;
408+
if (legendX < margins.left) legendX = datumStartX + legendOffset + margins.left;
405409
legendRef.style.left = `${legendX}px`;
406410
legendRef.style.opacity = '1';
407411
if (wasTransitionDisabled) {
@@ -468,7 +472,7 @@ export default function drawDropsTimeline({
468472

469473
// Handle svg mouse events
470474
let isEventInCooldown = false;
471-
const cooldownTime = 20;
475+
const cooldownTime = 75;
472476
chartGroup.on('mousemove', function (event) {
473477
const [pointerX] = d3.pointer(event);
474478
if (!isEventInCooldown) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* This script is used to merge multiple stats_playerDrop files into a single file with the last 336 hours of data.
3+
* NOTE: use npx tsx scripts/dev/makeOldStatsFile.local.ts to run this script
4+
*/
5+
import fs from 'node:fs';
6+
import { PDLChangeEventType, PDLFileType } from '../../core/modules/Metrics/playerDrop/playerDropSchemas';
7+
import * as d3 from 'd3';
8+
9+
// const hours = d3.timeHour.offset()
10+
const currentHour = d3.timeHour.floor(new Date());
11+
export default (sourceFile: string, targetFileName: string) => {
12+
const fileData = JSON.parse(fs.readFileSync(sourceFile, 'utf8')) as PDLFileType;
13+
14+
let lastHour = d3.timeHour.offset(currentHour, -1);
15+
for (let i = fileData.log.length - 1; i >= 0; i--) {
16+
const log = fileData.log[i];
17+
const logHour = new Date(log.hour);
18+
const newHour = d3.timeHour.offset(lastHour, -1);
19+
const hourDiff = newHour.getTime() - logHour.getTime();
20+
log.hour = newHour.toISOString();
21+
lastHour = newHour;
22+
for (const change of log.changes) {
23+
if ('ts' in change) {
24+
change.ts = change.ts - hourDiff;
25+
}
26+
}
27+
console.log('Updated', logHour.toISOString(), 'to', newHour.toISOString());
28+
}
29+
fileData.lastResourceList = [];
30+
fileData.lastUnknownReasons = [];
31+
32+
//Write new file
33+
console.log('Writing file', targetFileName);
34+
fs.writeFileSync(targetFileName, JSON.stringify(fileData));
35+
}

scripts/dev/updatePlayerDropsV2.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* This script is used to update the timestamps of a stats_playerDrop.json v2 file
3+
*
4+
* NOTE: RENAME TO updatePlayerDropsV2.local.ts
5+
* NOTE: THEN RUN npx tsx scripts/dev/updatePlayerDropsV2.local.ts
6+
* NOTE: Add --overwrite to overwrite the actual stats_playerDrop.json file instead of creating a timestamped copy
7+
*/
8+
import updatePlayerDropsV2 from "./updatePlayerDropsV2.code";
9+
10+
const sourceFile = 'xxxxx/stats_playerDrop.json';
11+
const baseTargetPath = 'xxxxxxxx/txData/default/data/stats_playerDrop.json';
12+
const overwrite = process.argv.includes('--overwrite');
13+
const formattedTimestamp = new Date().toISOString().replace(/:/g, '-').split('.')[0];
14+
const targetFileName = overwrite ? baseTargetPath : `${baseTargetPath}.${formattedTimestamp}`;
15+
updatePlayerDropsV2(sourceFile, targetFileName);

0 commit comments

Comments
 (0)