Add function to resolve most recent completed actor path state
This commit is contained in:
@@ -21,8 +21,11 @@ import { normalizeYawDegrees } from "../entities/entity-instances";
|
|||||||
import {
|
import {
|
||||||
cloneProjectScheduler,
|
cloneProjectScheduler,
|
||||||
compareProjectScheduleRoutinePriority,
|
compareProjectScheduleRoutinePriority,
|
||||||
|
getProjectScheduleRoutineDurationHours,
|
||||||
getProjectScheduleRoutineElapsedHoursAt,
|
getProjectScheduleRoutineElapsedHoursAt,
|
||||||
|
isProjectScheduleDaySelectionActive,
|
||||||
isProjectScheduleRoutineActiveAt,
|
isProjectScheduleRoutineActiveAt,
|
||||||
|
resolveProjectScheduleWeekday,
|
||||||
type ProjectScheduler,
|
type ProjectScheduler,
|
||||||
type ProjectScheduleRoutine
|
type ProjectScheduleRoutine
|
||||||
} from "../sequencer/project-sequencer";
|
} from "../sequencer/project-sequencer";
|
||||||
@@ -413,6 +416,101 @@ function resolveActorScheduleRules(
|
|||||||
.sort(compareProjectScheduleRoutinePriority);
|
.sort(compareProjectScheduleRoutinePriority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAbsoluteScheduleHours(dayNumber: number, timeOfDayHours: number): number {
|
||||||
|
return (Math.floor(dayNumber) - 1) * 24 + timeOfDayHours;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveMostRecentCompletedActorPathState(options: {
|
||||||
|
actorRules: ActorScheduleRoutine[];
|
||||||
|
sequences: ProjectSequenceLibrary;
|
||||||
|
actorId: string;
|
||||||
|
dayNumber: number;
|
||||||
|
timeOfDayHours: number;
|
||||||
|
pathsById?: ReadonlyMap<string, RuntimeProjectSchedulePathDefinition>;
|
||||||
|
}): {
|
||||||
|
pathEffect: FollowActorPathControlEffect;
|
||||||
|
resolvedPath: RuntimeResolvedActorPathState;
|
||||||
|
} | null {
|
||||||
|
const currentAbsoluteHours = getAbsoluteScheduleHours(
|
||||||
|
options.dayNumber,
|
||||||
|
options.timeOfDayHours
|
||||||
|
);
|
||||||
|
let bestMatch:
|
||||||
|
| {
|
||||||
|
endAbsoluteHours: number;
|
||||||
|
routine: ActorScheduleRoutine;
|
||||||
|
pathEffect: FollowActorPathControlEffect;
|
||||||
|
}
|
||||||
|
| null = null;
|
||||||
|
|
||||||
|
for (const routine of options.actorRules) {
|
||||||
|
const heldSteps = getProjectScheduleRoutineHeldSteps(routine, options.sequences);
|
||||||
|
const pathEffect = findHeldSequenceControlEffect(heldSteps, "followActorPath");
|
||||||
|
|
||||||
|
if (pathEffect === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const durationHours = getProjectScheduleRoutineDurationHours(routine);
|
||||||
|
|
||||||
|
for (let dayOffset = 0; dayOffset <= 7; dayOffset += 1) {
|
||||||
|
const occurrenceStartDayNumber = options.dayNumber - dayOffset;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!isProjectScheduleDaySelectionActive(
|
||||||
|
routine.days,
|
||||||
|
resolveProjectScheduleWeekday(occurrenceStartDayNumber)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const occurrenceEndAbsoluteHours =
|
||||||
|
getAbsoluteScheduleHours(occurrenceStartDayNumber, routine.startHour) +
|
||||||
|
durationHours;
|
||||||
|
|
||||||
|
if (occurrenceEndAbsoluteHours > currentAbsoluteHours) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
bestMatch !== null &&
|
||||||
|
(bestMatch.endAbsoluteHours > occurrenceEndAbsoluteHours ||
|
||||||
|
(bestMatch.endAbsoluteHours === occurrenceEndAbsoluteHours &&
|
||||||
|
compareProjectScheduleRoutinePriority(bestMatch.routine, routine) <= 0))
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bestMatch = {
|
||||||
|
endAbsoluteHours: occurrenceEndAbsoluteHours,
|
||||||
|
routine,
|
||||||
|
pathEffect
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestMatch === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvedPath = resolveActorSchedulePathState({
|
||||||
|
effect: bestMatch.pathEffect,
|
||||||
|
elapsedHours: getProjectScheduleRoutineDurationHours(bestMatch.routine),
|
||||||
|
path: options.pathsById?.get(bestMatch.pathEffect.pathId) ?? null
|
||||||
|
});
|
||||||
|
|
||||||
|
if (resolvedPath === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
pathEffect: cloneControlEffect(bestMatch.pathEffect),
|
||||||
|
resolvedPath
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveRuntimeActorScheduleState(options: {
|
export function resolveRuntimeActorScheduleState(options: {
|
||||||
scheduler: ProjectScheduler;
|
scheduler: ProjectScheduler;
|
||||||
sequences: ProjectSequenceLibrary;
|
sequences: ProjectSequenceLibrary;
|
||||||
@@ -432,6 +530,15 @@ export function resolveRuntimeActorScheduleState(options: {
|
|||||||
) ?? null;
|
) ?? null;
|
||||||
|
|
||||||
if (activeRoutine === null) {
|
if (activeRoutine === null) {
|
||||||
|
const completedPathState = resolveMostRecentCompletedActorPathState({
|
||||||
|
actorRules,
|
||||||
|
sequences: options.sequences,
|
||||||
|
actorId: options.actorId,
|
||||||
|
dayNumber: options.dayNumber,
|
||||||
|
timeOfDayHours: options.timeOfDayHours,
|
||||||
|
pathsById: options.pathsById
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
actorId: options.actorId,
|
actorId: options.actorId,
|
||||||
hasRules: actorRules.length > 0,
|
hasRules: actorRules.length > 0,
|
||||||
@@ -440,8 +547,8 @@ export function resolveRuntimeActorScheduleState(options: {
|
|||||||
activeRoutineTitle: null,
|
activeRoutineTitle: null,
|
||||||
presenceEffect: null,
|
presenceEffect: null,
|
||||||
animationEffect: null,
|
animationEffect: null,
|
||||||
pathEffect: null,
|
pathEffect: completedPathState?.pathEffect ?? null,
|
||||||
resolvedPath: null
|
resolvedPath: completedPathState?.resolvedPath ?? null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user