Files
MultiRoombaRover/server/src/rewards/definitions/darkness.js
T
2026-04-18 19:42:12 -04:00

98 lines
3.0 KiB
JavaScript

const DURATION_MS = 60 * 1000;
let activeTimer = null;
async function stopDarkness(ctx, effect = {}) {
if (activeTimer) {
clearTimeout(activeTimer);
activeTimer = null;
}
const prevLights = Array.isArray(effect.prevLights) ? effect.prevLights : [];
await Promise.all(
prevLights.map(async (entry) => {
try {
await ctx.setHomeAssistantEntityState(entry.id, entry.state === 'on' ? 'on' : 'off');
} catch (err) {
ctx.logger.warn('darkness restore light failed', { entityId: entry.id, error: err.message });
}
}),
);
const prevNightVision = effect.prevNightVision && typeof effect.prevNightVision === 'object'
? effect.prevNightVision
: {};
Object.entries(prevNightVision).forEach(([roverId, wasOn]) => {
try {
ctx.issueCommand(String(roverId), {
type: 'nightVision',
nightVision: { action: wasOn ? 'on' : 'off' },
});
} catch (err) {
ctx.logger.warn('darkness restore nightVision failed', { roverId, error: err.message });
}
});
ctx.clearEffect('darkness');
}
function startDarkness(ctx, effect) {
if (activeTimer) {
clearTimeout(activeTimer);
activeTimer = null;
}
const endsAt = Number(effect.endsAt || Date.now() + DURATION_MS);
const remaining = Math.max(0, endsAt - Date.now());
ctx.saveEffect('darkness', effect);
activeTimer = setTimeout(() => {
stopDarkness(ctx, effect).catch((err) => {
ctx.logger.warn('darkness stop failed', { error: err.message });
});
}, remaining);
}
module.exports = {
id: 'darkness',
name: 'Darkness',
goal: 650,
async run(ctx) {
const entities = ctx.getHomeAssistantEntities();
const prevLights = entities.map((entity) => ({ id: entity.id, state: entity.state === 'on' ? 'on' : 'off' }));
await Promise.all(
entities.map(async (entity) => {
try {
await ctx.setHomeAssistantEntityState(entity.id, 'off');
} catch (err) {
ctx.logger.warn('darkness light off failed', { entityId: entity.id, error: err.message });
}
}),
);
const prevNightVision = {};
ctx.listOnlineRovers().forEach((rover) => {
const state = rover?.nightVision?.state;
const nightVisionOn = Boolean(state && state.nightVisionOn === true);
prevNightVision[String(rover.id)] = nightVisionOn;
try {
ctx.issueCommand(String(rover.id), {
type: 'nightVision',
nightVision: { action: 'off' },
});
} catch (err) {
ctx.logger.warn('darkness nightVision off failed', { roverId: rover.id, error: err.message });
}
});
const effect = { endsAt: Date.now() + DURATION_MS, prevLights, prevNightVision };
startDarkness(ctx, effect);
ctx.sendAlert({ color: '#212121', title: 'Darkness', message: 'Darkness effect active for 60 seconds.' });
},
async recover(ctx, effect) {
if (!effect || Number(effect.endsAt || 0) <= Date.now()) {
await stopDarkness(ctx, effect || {});
return;
}
startDarkness(ctx, effect);
},
};