<div id="lockers"></div>
<div id="status">
<button onClick="startReplay()">Start Replay</button>
<button onClick="stopReplay()">Stop Replay</button>
<button onClick="previousReplay()">
< Previous Student</button>
<button onClick="nextReplay()">Next Student ></button>
<div id="studentStatus"></div>
<div id="openLockers"></div>
</div>
#lockers, #status {
width: 75%;
margin: 0 auto;
margin-top: 1em;
text-align: center;
}
#lockers .fa-door-open, #lockers .fa-door-closed {
padding-bottom: .4em;
font-size: 2em;
opacity: .5;
}
#lockers .fa-door-open {
color: green;
}
#lockers .fa-door-closed {
color: red;
}
button {
margin-bottom: 10px;
}
function initLockerUI(n) {
// render the lockers to the DOM
for (var i = 0; i < n; i++) {
var tag = document.createElement("i");
tag.classList.add("fa");
tag.classList.add("fa-door-closed");
var element = document.getElementById("lockers");
element.appendChild(tag);
}
}
const lockerCount = 100;
const studentCount = lockerCount;
// create UI for bank of lockers
initLockerUI(lockerCount);
// set up bank of lockers, initialized to false (closed)
let lockers = Array(lockerCount).fill(false);
let lockerStates = [];
let mischievousStudents = 0;
while (mischievousStudents < studentCount) {
// add one more mischievous student to the ranks!
mischievousStudents++;
switch(mischievousStudents) {
case 1:
// the first mischievous student will open all the lockers
lockers = lockers.map(function(state, i) {
return true; // true = open, false = closed
});
break;
case 2:
// mischievous student 2 will close every other locker, starting at 2
lockers = lockers.map(function(state, i) {
return (i+1) % 2 === 0 ? false : state;
});
break;
default:
// student n will *invert* every nth locker
lockers = lockers.map(function(state, i) {
return (i+1) % this.student === 0 ? !state : state;
}, {
student: mischievousStudents
});
}
// we'll save the current locker state for replay later
lockerStates.push(lockers);
} // end student traversal
// replay code
let replayIntervalTimer;
let currentLockerReplay = 0;
let replaying = false;
function getOpenLockers(lockers) {
let openLockers = [];
lockers.forEach(function(x, index) {
x && openLockers.push(index + 1);
});
return openLockers.join(", ");
}
function incrementOrStop() {
if (currentLockerReplay < lockerCount - 1) {
currentLockerReplay++;
} else {
currentLockerReplay = 0;
clearInterval(replayIntervalTimer);
}
}
function updateLockerUIStates() {
lockers = lockerStates[currentLockerReplay];
const lockerDoors = document.querySelectorAll(".fa-w-20");
for (var i = 0; i < lockerDoors.length; i++) {
lockerDoors[i].classList.remove("fa-door-closed");
lockerDoors[i].classList.remove("fa-door-open");
lockerDoors[i].classList.add(lockers[i] ? "fa-door-open" : "fa-door-closed");
}
// output statistics
document.getElementById("studentStatus").innerHTML = "Student: " + (currentLockerReplay + 1) + " of " + studentCount;
document.getElementById("openLockers").innerHTML = "Open Lockers: " + getOpenLockers(lockers);
// increment or stop
incrementOrStop();
}
function startReplay() {
if (!replaying) {
replayIntervalTimer = setInterval(updateLockerUIStates, 100);
replaying = true;
}
}
function stopReplay() {
clearInterval(replayIntervalTimer);
replaying = false;
}
function nextReplay() {
stopReplay();
updateLockerUIStates();
}
function previousReplay() {
stopReplay();
currentLockerReplay = currentLockerReplay > 1 ?
currentLockerReplay - 2 :
0;
updateLockerUIStates();
}
View Compiled
This Pen doesn't use any external CSS resources.