@yuebai008/cli
Version:
Command line interface for rapid qg-minigame development
1 lines • 5.92 kB
JavaScript
import*as Helpers from"../helpers/helpers.js";import{data as metaHandlerData}from"./MetaHandler.js";import{data as screenshotsHandlerData}from"./ScreenshotsHandler.js";import*as Platform from"../../../core/platform/platform.js";import*as Types from"../types/types.js";export const MAX_CLUSTER_DURATION=Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(5e3));export const MAX_SHIFT_TIME_DELTA=Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(1e3));const layoutShiftEvents=[],layoutInvalidationEvents=[],styleRecalcInvalidationEvents=[],prePaintEvents=[];let sessionMaxScore=0,clsWindowID=-1;const clusters=[],scoreRecords=[];let handlerState=1;export function initialize(){if(1!==handlerState)throw new Error("LayoutShifts Handler was not reset");handlerState=2}export function reset(){handlerState=1,layoutShiftEvents.length=0,layoutInvalidationEvents.length=0,prePaintEvents.length=0,clusters.length=0,sessionMaxScore=0,scoreRecords.length=0,clsWindowID=-1}export function handleEvent(e){if(2!==handlerState)throw new Error("Handler is not initialized");!Types.TraceEvents.isTraceEventLayoutShift(e)||e.args.data?.had_recent_input?Types.TraceEvents.isTraceEventLayoutInvalidation(e)?layoutInvalidationEvents.push(e):(Types.TraceEvents.isTraceEventStyleRecalcInvalidation(e)&&styleRecalcInvalidationEvents.push(e),Types.TraceEvents.isTraceEventPrePaint(e)&&prePaintEvents.push(e)):layoutShiftEvents.push(e)}function traceWindowFromTime(e){return{min:e,max:e,range:Types.Timing.MicroSeconds(0)}}function updateTraceWindowMax(e,t){e.max=t,e.range=Types.Timing.MicroSeconds(e.max-e.min)}function findNextScreenshotSource(e){const t=screenshotsHandlerData(),s=findNextScreenshotEventIndex(t,e);if(s)return`data:img/png;base64,${t[s].args.snapshot}`}export function findNextScreenshotEventIndex(e,t){return Platform.ArrayUtilities.nearestIndexFromBeginning(e,(e=>e.ts>t))}function buildScoreRecords(){const{traceBounds:e}=metaHandlerData();scoreRecords.push({ts:e.min,score:0});for(const e of clusters){let t=0;e.events[0].args.data&&scoreRecords.push({ts:e.clusterWindow.min,score:e.events[0].args.data.weighted_score_delta});for(let s=0;s<e.events.length;s++){const n=e.events[s];n.args.data&&(t+=n.args.data.weighted_score_delta,scoreRecords.push({ts:n.ts,score:t}))}scoreRecords.push({ts:e.clusterWindow.max,score:0})}}export async function finalize(){layoutShiftEvents.sort(((e,t)=>e.ts-t.ts)),prePaintEvents.sort(((e,t)=>e.ts-t.ts)),layoutInvalidationEvents.sort(((e,t)=>e.ts-t.ts)),await buildLayoutShiftsClusters(),buildScoreRecords(),handlerState=3}async function buildLayoutShiftsClusters(){const{navigationsByFrameId:e,mainFrameId:t,traceBounds:s}=metaHandlerData(),n=e.get(t)||[];if(0===layoutShiftEvents.length)return;let o=layoutShiftEvents[0].ts,a=layoutShiftEvents[0].ts,r=null;for(const e of layoutShiftEvents){const t=e.ts-o>MAX_CLUSTER_DURATION,s=e.ts-a>MAX_SHIFT_TIME_DELTA,i=Platform.ArrayUtilities.nearestIndexFromEnd(n,(t=>t.ts<e.ts)),c=r!==i&&null!==i;if(t||s||c||!clusters.length){const r=e.ts,d=t?o+MAX_CLUSTER_DURATION:1/0,l=s?a+MAX_SHIFT_TIME_DELTA:1/0,u=c?n[i].ts:1/0,m=Math.min(d,l,u);if(clusters.length>0){updateTraceWindowMax(clusters[clusters.length-1].clusterWindow,Types.Timing.MicroSeconds(m))}clusters.push({events:[],clusterWindow:traceWindowFromTime(r),clusterCumulativeScore:0,scoreWindows:{good:traceWindowFromTime(r),needsImprovement:null,bad:null}}),o=r}const d=clusters[clusters.length-1],l=null!==i?Types.Timing.MicroSeconds(e.ts-n[i].ts):void 0;if(d.clusterCumulativeScore+=e.args.data?e.args.data.weighted_score_delta:0,!e.args.data)continue;const u={...e,args:{frame:e.args.frame,data:{...e.args.data,rawEvent:e}},parsedData:{screenshotSource:findNextScreenshotSource(e.ts),timeFromNavigation:l,cumulativeWeightedScoreInWindow:d.clusterCumulativeScore,sessionWindowData:{cumulativeWindowScore:0,id:clusters.length}}};d.events.push(u),updateTraceWindowMax(d.clusterWindow,e.ts),a=e.ts,r=i}for(const e of clusters){let t=0,o=-1;if(e===clusters[clusters.length-1]){const t=MAX_CLUSTER_DURATION+e.clusterWindow.min,o=e.clusterWindow.max+MAX_SHIFT_TIME_DELTA,a=Platform.ArrayUtilities.nearestIndexFromBeginning(n,(t=>t.ts>e.clusterWindow.max)),r=a?n[a].ts:1/0,i=Math.min(t,o,s.max,r);updateTraceWindowMax(e.clusterWindow,Types.Timing.MicroSeconds(i))}for(const s of e.events){t+=s.args.data?s.args.data.weighted_score_delta:0,o=s.parsedData.sessionWindowData.id;const n=s.ts;s.parsedData.sessionWindowData.cumulativeWindowScore=e.clusterCumulativeScore,t<.1?updateTraceWindowMax(e.scoreWindows.good,n):t>=.1&&t<.25?(e.scoreWindows.needsImprovement||(updateTraceWindowMax(e.scoreWindows.good,Types.Timing.MicroSeconds(n-1)),e.scoreWindows.needsImprovement=traceWindowFromTime(n)),updateTraceWindowMax(e.scoreWindows.needsImprovement,n)):t>=.25&&(e.scoreWindows.bad||(e.scoreWindows.needsImprovement?updateTraceWindowMax(e.scoreWindows.needsImprovement,Types.Timing.MicroSeconds(n-1)):updateTraceWindowMax(e.scoreWindows.good,Types.Timing.MicroSeconds(n-1)),e.scoreWindows.bad=traceWindowFromTime(s.ts)),updateTraceWindowMax(e.scoreWindows.bad,n)),e.scoreWindows.bad?updateTraceWindowMax(e.scoreWindows.bad,e.clusterWindow.max):e.scoreWindows.needsImprovement?updateTraceWindowMax(e.scoreWindows.needsImprovement,e.clusterWindow.max):updateTraceWindowMax(e.scoreWindows.good,e.clusterWindow.max)}t>sessionMaxScore&&(clsWindowID=o,sessionMaxScore=t)}}export function data(){if(3!==handlerState)throw new Error("Layout Shifts Handler is not finalized");return{clusters:[...clusters],sessionMaxScore:sessionMaxScore,clsWindowID:clsWindowID,prePaintEvents:[...prePaintEvents],layoutInvalidationEvents:[...layoutInvalidationEvents],styleRecalcInvalidationEvents:[],scoreRecords:[...scoreRecords]}}export function deps(){return["Screenshots","Meta"]}export function stateForLayoutShiftScore(e){let t="good";return e>=.1&&(t="ok"),e>=.25&&(t="bad"),t}