const preact = require('preact'); const range = require('lodash/range'); const countBy = require('lodash/countBy'); const without = require('lodash/without'); const { connect } = require('preact-redux'); const { removeTier } = require('../utils'); const shapes = require('./shapes'); const actions = require('../actions'); const buttons = require('./buttons'); const addState = connect( function receiveState(state) { const { ws, instance, player, combiner, reclaiming, vboxSelected, itemInfo, itemUnequip, navInstance, info, } = state; function sendVboxDiscard() { return ws.sendVboxDiscard(instance.id); } function sendVboxAccept(group, index) { return ws.sendVboxAccept(instance.id, group, index); } function sendVboxCombine() { return ws.sendVboxCombine(instance.id, combiner); } function sendVboxReclaim(i) { return ws.sendVboxReclaim(instance.id, i); } function sendItemUnequip([constructId, item]) { return ws.sendVboxUnequip(instance.id, constructId, item); } return { combiner, instance, player, reclaiming, sendVboxAccept, sendVboxCombine, sendVboxDiscard, sendVboxReclaim, vboxSelected, itemInfo, itemUnequip, sendItemUnequip, navInstance, info, }; }, function receiveDispatch(dispatch) { function setCombiner(c) { return dispatch(actions.setCombiner(c)); } function setReclaiming(v) { return dispatch(actions.setReclaiming(v)); } function setInfo(item) { return dispatch(actions.setInfo(item)); } function setVboxSelected(v) { return dispatch(actions.setVboxSelected(v)); } function setItemEquip(v) { return dispatch(actions.setItemEquip(v)); } return { setCombiner, setReclaiming, setInfo, setVboxSelected, setItemEquip, }; } ); function Vbox(args) { const { combiner, navInstance, instance, itemInfo, player, reclaiming, sendVboxAccept, sendVboxCombine, sendVboxDiscard, sendVboxReclaim, setCombiner, setInfo, vboxSelected, setVboxSelected, setItemEquip, itemUnequip, sendItemUnequip, setReclaiming, info, } = args; if (!player) return false; const { vbox } = player; const vboxSelecting = vboxSelected.length; function combinerChange(newCombiner) { setCombiner(newCombiner); if (newCombiner.length === 1) { setItemEquip(newCombiner[0]); } else { setItemEquip(null); } return true; } // // VBOX // function vboxHover(e, v) { if (v) { if (info !== v) setInfo(v); e.stopPropagation(); } return true; } function clearVboxSelected() { setVboxSelected([]); } function vboxBuySelected() { if (!vboxSelecting) return false; document.activeElement.blur(); clearVboxSelected(); sendVboxAccept(vboxSelected[0], vboxSelected[1]); return true; } function availableBtn(v, group, index) { if (!v) return ; const tutorial = instance.time_control === 'Practice' && instance.rounds.length === 1 && group === 0 && combiner.length === 0 && vboxSelected.length === 0 && vbox.bits > 10 && vbox.free[0].filter(c => c).length > 4 ? 'combo-border' : null; const selected = vboxSelected[0] === group && vboxSelected[1] === index; // state not yet set in double click handler function onDblClick(e) { clearVboxSelected(); sendVboxAccept(group, index); e.stopPropagation(); } function onClick(e) { e.stopPropagation(); setItemEquip(null); setCombiner([]); if (selected) return clearVboxSelected(); return setVboxSelected([group, index]); } const combinerItems = combiner.map(j => vbox.bound[j]); const combinerCount = countBy(combinerItems, co => co); const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => { if (combo.components.includes(v)) { return combinerItems.every(c => { if (!combo.components.includes(c)) return false; const comboCount = countBy(combo.components, co => co); if (combinerCount[c] > comboCount[c]) return false; if (c === v && combinerCount[c] + 1 > comboCount[c]) return false; return true; }); } return false; }) ? 'combo-border' : ''; const classes = `${v.toLowerCase()} ${selected ? 'highlight' : ''} ${comboHighlight} ${tutorial}`; if (shapes[v]) { return ( ); } return ( ); } function vboxElement() { return (
setReclaiming(false)} onClick={e => e.stopPropagation()} onMouseOver={e => hoverInfo(e, 'vbox')}>

e.target.scrollIntoView(true)}>VBOX

hoverInfo(e, 'bits')} >{vbox.bits}b
{range(0, 6).map(i => availableBtn(vbox.free[0][i], 0, i))}
{range(0, 3).map(i => availableBtn(vbox.free[1][i], 1, i))} {range(0, 3).map(i => availableBtn(vbox.free[2][i], 2, i))}
); } // // INVENTORY // function reclaimClick(e) { e.stopPropagation(); return setReclaiming(!reclaiming); } const inventoryClass = `vbox-section ${reclaiming ? 'reclaiming' : ''}`; function inventoryBtn(v, i) { const inventoryHighlight = vboxSelecting || itemUnequip.length; if (!v && v !== 0) { return ; } const tutorial = instance.time_control === 'Practice' && instance.rounds.length === 1 && i === 0 && combiner.length === 0 && vboxSelected.length === 0 && vbox.bits === 16 && vbox.bound.length === 5 && vbox.free[0].filter(c => c).length === 4 ? 'combo-border' : null; const combinerItems = combiner.map(j => vbox.bound[j]); const combinerCount = countBy(combinerItems, co => co); const comboHighlight = combinerItems.length > 0 && itemInfo.combos.some(combo => { if (combo.components.includes(v)) { return combinerItems.every(c => { if (!combo.components.includes(c)) return false; const comboCount = countBy(combo.components, co => co); if (combinerCount[c] > comboCount[c]) return false; if (c === v && combinerCount[c] + 1 > comboCount[c]) return false; return true; }); } return false; }) ? 'combo-border' : ''; function onClick(e) { if (vboxSelecting) clearVboxSelected(); if (reclaiming) return sendVboxReclaim(i); // 4 things selected if (combiner.length > 2) return combinerChange([i]); // removing const combinerIndex = combiner.indexOf(i); if (combinerIndex > -1) { return combinerChange(without(combiner, i)); } combiner.push(i); if (!comboHighlight) { return combinerChange([i]); } return combinerChange(combiner); } const highlighted = combiner.indexOf(i) > -1; const border = buttons[removeTier(v)] ? buttons[removeTier(v)]() : ''; const classes = `${highlighted ? 'highlight' : border} ${comboHighlight} ${tutorial}`; if (shapes[v]) { return ( ); } return ( ); } function combinerBtn() { let text = ''; let comboItem = ''; if (combiner.length < 3) { for (let i = 0; i < 3; i++) { if (combiner.length > i) { text += '■ '; } else { text += '▫ '; } } } else { // Since theres 3 items in combiner and you can't have invalid combos we can preview it const combinerItems = combiner.map(j => vbox.bound[j]); const combinerCount = countBy(combinerItems, co => co); const comboItemObj = itemInfo.combos.find(combo => combinerItems.every(c => { if (!combo.components.includes(c)) return false; const comboCount = countBy(combo.components, co => co); if (combinerCount[c] > comboCount[c]) return false; return true; })); comboItem = comboItemObj ? comboItemObj.item : 'refine'; comboItem = comboItem.replace('Plus', '+'); text = `Combine - ${comboItem}`; } return ( ); } function inventoryElement() { function inventoryClick(e) { e.stopPropagation(); setReclaiming(false); if (vboxSelecting) return vboxBuySelected(); if (itemUnequip.length) return sendItemUnequip(itemUnequip); return true; } return (
e.stopPropagation()} style={vboxSelecting || itemUnequip.length ? { cursor: 'pointer' } : null} onMouseOver={e => hoverInfo(e, 'inventory')}>

e.target.scrollIntoView(true)}>INVENTORY

{range(0, 9).map(i => inventoryBtn(vbox.bound[i], i))}
{combinerBtn()}
); } // // EVERYTHING // function hoverInfo(e, newInfo) { e.stopPropagation(); if (info === newInfo) return true; return setInfo(newInfo); } const classes = `vbox ${navInstance === 0 ? 'visible' : ''}`; return (
{vboxElement()}
{inventoryElement()}
); } module.exports = addState(Vbox);