인터랙티브 아트워크 30종과 시간 기반 전환 및 개발 문서 추가
This commit is contained in:
50
artwork-schedule.js
Normal file
50
artwork-schedule.js
Normal file
@@ -0,0 +1,50 @@
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
const SLOT_DURATION = 137 * 60 * 1000;
|
||||
|
||||
// Mulberry32: 같은 Seed는 항상 0 이상 1 미만의 동일한 난수열을 생성합니다.
|
||||
function createRandom(seed) {
|
||||
let state = seed >>> 0;
|
||||
return () => {
|
||||
state = (state + 0x6D2B79F5) >>> 0;
|
||||
let value = Math.imul(state ^ (state >>> 15), state | 1);
|
||||
value ^= value + Math.imul(value ^ (value >>> 7), value | 61);
|
||||
return ((value ^ (value >>> 14)) >>> 0) / 4294967296;
|
||||
};
|
||||
}
|
||||
|
||||
function rawOrder(loop, count) {
|
||||
const random = createRandom(loop);
|
||||
const order = Array.from({ length: count }, (_, index) => index);
|
||||
for (let index = count - 1; index > 0; index--) {
|
||||
const other = Math.floor(random() * (index + 1));
|
||||
[order[index], order[other]] = [order[other], order[index]];
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
function orderForLoop(loop, count = 30) {
|
||||
if (!Number.isInteger(count) || count < 3) throw new RangeError('At least three artworks are required.');
|
||||
if (!Number.isSafeInteger(loop) || loop < 0) throw new RangeError('Invalid loop number.');
|
||||
const order = rawOrder(loop, count);
|
||||
if (loop > 0) {
|
||||
// 항목이 3개 이상이면 첫 두 위치를 교환해도 마지막 항목은 바뀌지 않습니다.
|
||||
// 따라서 이전 루프의 보정 전 마지막 항목을 그대로 비교할 수 있습니다.
|
||||
// 재귀 호출, 상태 저장, 과거 루프 전체 순회는 필요하지 않습니다.
|
||||
const previousLast = rawOrder(loop - 1, count)[count - 1];
|
||||
if (order[0] === previousLast) [order[0], order[1]] = [order[1], order[0]];
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
function selectionAt(time, count = 30) {
|
||||
if (!Number.isFinite(time) || time < 0) throw new RangeError('Invalid timestamp.');
|
||||
const slot = Math.floor(time / SLOT_DURATION);
|
||||
const loop = Math.floor(slot / count);
|
||||
const position = slot % count;
|
||||
return { slot, loop, position, variant: orderForLoop(loop, count)[position] };
|
||||
}
|
||||
|
||||
globalThis.NNCArtworkSchedule = Object.freeze({ SLOT_DURATION, createRandom, orderForLoop, selectionAt });
|
||||
})();
|
||||
Reference in New Issue
Block a user