Node Test Task
const WebSocket = require('ws');
const ws = new WebSocket('ws://nuclear.t.javascript.ninja');
const coincidences = {};
const states = {};
const historyLimit = 5;
ws.on('open', () => console.log('Launched'));
ws.on('error', e => console.log(e));
ws.on('message', data => {
const response = JSON.parse(data);
console.log(response);
if (response.action == "check") initiateCoincedense(response.stateId, response.lever2, response.same);
if (Number.isInteger(response.pulled)) {
if (Object.keys(states).length) {
updateState(response.stateId, response.pulled);
} else {
updateCoincedense(response.stateId, response.pulled);
let fillUp = coincidences[response.stateId].indexOf(null);
fillUp !== -1 && requestCoincedense(response.stateId, fillUp + 1);
}
}
if (response.newState == "poweredOff") ws.close();
});
function powerOff(stateId) {
if (Object.keys(states).length === 0) {
// other data structure initiation for probable next switch
states[stateId] = [false, false, false, false];
}
ws.send(JSON.stringify({action: "powerOff", stateId}));
}
function check(hash, stateId) {
if (hash[stateId].every(i => i === true)) powerOff(stateId);
}
function requestCoincedense(stateId, lever2) {
// 1th leverage is determinant
ws.send(JSON.stringify({action: "check", "lever1": 0, lever2, stateId}));
}
function initiateCoincedense(stateId, lever2, same) {
coincidences[stateId][lever2 - 1] = same;
if (Object.keys(coincidences[stateId]).length === 3) check(coincidences, stateId);
}
function updateCoincedense(stateId, pulled) {
let newState;
if (Object.keys(coincidences).length === 0) {
// initiation
coincidences[stateId] = [null, null, null];
return;
} else {
newState = coincidences[stateId - 1].slice();
delete coincidences[stateId - historyLimit];
}
if (pulled == 0) {
coincidences[stateId] = newState.map(i => i === null ? null : !i);
} else {
newState[pulled - 1] = newState[pulled - 1] === null ? null : !newState[pulled - 1];
coincidences[stateId] = newState;
check(coincidences, stateId);
}
}
function updateState(stateId, pulled) {
const newState = states[stateId - 1].slice();
newState[pulled] = !newState[pulled];
delete states[stateId - historyLimit];
states[stateId] = newState;
check(states, stateId);
}