// Global error capture for bug reports window.capturedErrors = []; window.onerror = function (message, source, lineno, colno, error) { window.capturedErrors.push({ type: 'error', message: message, source: source, line: lineno, col: colno, stack: error ? error.stack : null, timestamp: new Date().toISOString() }); // Keep only last 20 errors if (window.capturedErrors.length > 20) window.capturedErrors.shift(); }; window.onunhandledrejection = function (event) { window.capturedErrors.push({ type: 'unhandledrejection', message: event.reason ? event.reason.message || String(event.reason) : 'Unknown', stack: event.reason ? event.reason.stack : null, timestamp: new Date().toISOString() }); if (window.capturedErrors.length > 20) window.capturedErrors.shift(); }; // Preload all texticon images at startup for instant tooltip display const isStaticHost = window.location.hostname.includes('github.io'); // Helper to get the base URL (handles GitHub Pages subdirectories) const getAppBaseUrl = () => { const loc = window.location; // If on github.io and has a path like /reponame/, use that if (loc.hostname.includes('github.io')) { const parts = loc.pathname.split('/'); if (parts.length > 2 && parts[1]) { return `/${parts[1]}/`; } } return '/'; }; const fixImg = (path) => { if (!path) return 'img/icon_blade.png'; let url = path; // Normalize: remove leading slash if (url.startsWith('/')) url = url.substring(1); // Check if it already starts with img/ to avoid double prefixing if (!url.startsWith('img/') && !url.startsWith('http')) { url = 'img/' + url; } // Robust static host detection const isGithub = window.location.hostname.includes('github') || window.location.hostname.includes('lovecasim'); if (isGithub && url.toLowerCase().endsWith('.png')) { url = url.replace(/\.png$/i, '.webp'); } // Prefix with application base URL to handle subdirectories correctly const base = getAppBaseUrl(); if (base !== '/' && !url.startsWith('http')) { url = base + url; } return url; }; const ICON_DATA_URIs = { "center": "data:image/png;base64,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", "heart_00": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAACzVJREFUeNrsnT1QHDkahjVEJjrKoQluXHaIa3HAhTATcZmHbB0t43AvWFN7ue26DW/LbLAOFxzhzLPZEXkgNAFcmXAoSCAENvJmXL996t1m3POrT2pJ/T5VXQPYNKPR098nqdWSUoQQQgghhBBCCCGEEEIIIYQQQgghhBBCCAmdWghv8ubmZjF5qScHXv+qv1b6+7mCX+nmvt5LjuvkOEqOs1qtdhZQmVG2RnL8RZdV6Z8tFvzKmT6ULutv+nPwusw1jz/8VnKs6AqQJJMRYnaTyul6UN5MtBUtl40yd3WZOz4JWfNIOgj3RIs35/BPZ5Xzq66ca0flreuyPrEg3CggYCc53iblPaps/seVnxwvk+P0xh/e64vBVnnXk+PQo/LivaxXTbx6cmzd+M2pvjjmBMt75XF5r6TKS/Hk2dIpc9LyNpLjQ2BljVNEXairm7AZS8RAxSvKAC3bXtQciIde3daAoYMQQSflp+TY7O+waDlfJEdMbSp0VtquOmc2ol6s3IoQkUT4YWm5FUwE1O2H9yUML5QVIeoRRfhhIOpveC2gTrkfHI/lEXdg3LAplZJnhOVbp3zRgwBzqAONPxFQy7fF+qkM1zoSHpUuIOWjhKUJSPkooYmENcpHypSwZiAfxoXeuyrh5eWlOumdqPOLc3VxfpF+j2MQDx8+TF8fPHyg5u/Nq3vz99Tdu3eDqtXz8/+XNSvz58+f058NYn5+Xs3Ozv5RZrzie4cSPp50qldtSvmcDLXgwz44OFDHn46HyjYuEBCV8mjhkVp4tOCdcBAMZf10/Cm92PC9KZByaWkpLa+DC3DiIZraFPJBukP156xkcQ4+Hqj9/f2hV7spiAyolOXl5bSSygTSfTz4mL7aBOVdWV5JL0KLYE7lmk0BkXZbtsTb3d0ViXaTgHSNKLH0tyWn0S670Moo7+rqqk0RNxIJN8UFTOR7nry8ttG+e7fzTvV6vVIjEVIUKsamiBAP0u3v7YukWBOWV5bT8lpqJz4ep1NSm0C+uk69ou0+VASiXtmV0R8hnrSeiKdmpNhOp+M84o266J4+fWojGh4lAj6WFBCdjoZkJEBlIA35ilSE8CXCD6PVaqXlFeZVIuFLYwGlUy/ke/PzG6udDF8ihI8RfhBoeqCsLlNxbQz5kHJPpVIvosHWL1tByJdn9e+raTSc5CLb2dmx3rMNQEI8+to0ERCR77lU5PvhXz8EEQ0GDWOgckalZFxcSLmhXWT5cj579kzylGuJhJ2JBdQdj9Oqpd1hoGPy7T++HSghyodyhnqRWYqEWJ3hftE/jJoP+ELqHcQgXybYj//+sbAs6FDFIF9WFnQShagPeva45iL6oS3kc293GhABEQmzoRqUD+WMDURBoXHRwig4LAJ+J/FX0QiPTb7+JkWs8gHBcct60YNNNZs9X7xxpKsYUtKwNiHKGXsZv//n91Z6xIMioMgCQbh6Yq6YrE1YhTJiPFOARv+D/TO20i+mE4U2BkYGIziY/t1QAbWhxk88xdomqirZrVMBWqMioPFUKzTKfbrhTmQQqtd6/pHOIgG/kQjXJN5ULMA3hQLq3q9R+kXbj9EvXtCuF2gLNgZFwIbpmff291hLkbcFBcZ1F7P1B/sFXDF9c+z5VqAteCByY6EhHgEpXzXAuKBAM2ulSECj9h8eJyTVaQuapuFbAmJZWdMzogNCqkHvxPjxgi9ScN1UvthvSRHZ5hZueogJGMNcP+K8zm8J+JXRm7mggFUD69WYtgPzAhrNfrm6vGKNVIzLK+Oe8JzYEr1MwUzB0zDT3yuZFnZAqsfvn383PcXKDD9GUiYUkFBAQgEJoYCEAhJSmoBH/DiIY47yAhptPpdti0Cqg8Cqqr+JpeA7s3dYIxVj9o752tJ5AY0e5ih7qwPiHoE678ql4AdMwUzBE3Mt1gnBVliE0W8SsHa0mIBYL49pmNFvkh7wrTag3t/rzOSM2G2IVAOBuj7q74SkjUKTM/q4ASCRB1tXCGS7vSIB/+vBGyOeIxRoCiOg8fpb2H2SxI1AHZ9lm9fM9PVKzkzbgbg6HG6STByDO14C+w7/0dQruhNiFAUhn4U9x4gnTLJb1BB+HSbgW4kQzSgYZ/STGHzO75r0hYA6NxulYcgndKUQj8AWtgLcyrCDJiOYR8EkDbNHHFHHQ64+344j4LbEX/r66desuQjIdpIXAL3f7kgBdW/YWEJcMdjmlITNODuEjsmr/h/MjBsqTXpNTMVhp16Bjkfa+VAFIywDBdShsivxl4dtb0r87vW2Wi2p0/2k5xuMHQELQ+a0vWJKGBbIWu1nbanTQbzNon8YKqBkFESBBK8mYhEECnQgBQNGYfRLHRv1m5L7BoOYtzaNRb78PshCPd/7g/5x5ENJuke8KfVusPkxb9X53eMV7jRuDPVrnDPoTUUOleEyvnli3EU9BvmEdkfP6CQBbM1YQC1hI3n5IPnuKGHU8qHNd39Q22/sFNzXIdmULjQfaC8f3CwQlg+0R8k3kYAaDMuILuGBrj4HqssD4lmYOLKdn/EikoJzqXhRp+I5qXeL5X3f/PyG60yXIB+ykDAIUM1xot80ETCbrrXhedeflCPf9bipd2oBtYTbSuguCSWMRj6wlj3rYVVALeFLJTRtixJGIV+7f6qVlTZgQZsQ44OLkiVhmzA4+TYT+aZqlkksz9aU7hkzEgYl3/a08olEQB0F0SM+lewZMxIGIV83ka9pcgKRBSp1r6epDJd4YyQMSj5kvTVjdyTfkY0xQkZCb+VrTjLc4kRASkj5ShdQS9hQwhMXKKEX8o01wcB5G7CgTdhNXtrS52WbsHT5mpLyWYuAuUi4nrxsMRJGI5/4XjI12x+KTQk7nQ7nE2rwvI2lmebW5HMioE0JASe1WplM6kQ+ZwJSQspXuoCUkPKVLqBtCXd3d9Xuf3ajFw+jAZDP0qLwzuQrRUDbEsb+3LHloSin8pUmICWkfKUL6EJCDNNguCYGsEafxQe4SpGvdAFtS4iBagxYhy4hpLO4uFNp8nkhICWsrnzeCKglbCQv75XwLJpMwnc774K7dYderuDqpP2k8/n02j+q8gJqCa1M5QKh3T+2eF83k098YkHwArqQcOuXLdXr9byWD/d0La6l6I18XgpoW0Lg810Ti3c3vJPPWwFdSIghmv29fW/Ki3Yeol6V5PNaQC1hXXdMFm2c35cBawcTbbeTY8M3+bwXUEs4pyOhNQnLHLC2PMCcypeI1/a1fr0X0IWEZY0VWh7j816+YATMSYjB6pYtCV2OFVoe4wOv9Po9igLKiggJ122c29VYoeUxPtDWK5gpChiYhMDmMI3lYZag5AtWQC0h0ssLW+eXntxqeRIpyBaH7IRUj8EKqCVcV5YmMYCT3kkaDS8vL43Og4XYsfMQerwW5St1UkElBcxJ+FpZGrAGSMeIiJOKCPGwALjQbpODOFNTrExKAWUltHrXJOP407HqnfTUxflF4f1kpFkMrUC4hYUFFys4eHl3o3ICupTQI4KXD8zEUhs6Bd1Xwqu1egoGmB+HLl9UETAXCa3eNfFEvnYshZmJrXYQFRAdlPAK/p7Qjkm+KAXMiYiK2oykONkYX3QXVU1Fju2xQkfyNUMdZqm8gFrChrL0wJODnm7pDw5RQBkJQxumiWKYpbJtwII2YUjDNNEMs5AvI+EcZtPc+Mtz1lI1RGwlx5VH4h3qZgKpWDR8XbJ4V3pqGamwiPUS0nIqnr5zQ8gtEW2m5lOKR8ZtI0rJeKpTPdt4/aMT/AjGkhHi4PhK/TnJoVHwX69zwzx7+uujmAeSCSGEEEIIIYQQQgghZBT/E2AAqPZqjHO+k1YAAAAASUVORK5CYII=", "heart_01": "data:image/png;base64,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", "heart_02": "data:image/png;base64,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", "heart_03": "data:image/png;base64,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", "heart_04": "data:image/png;base64,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", "heart_05": "data:image/png;base64,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", "heart_06": "data:image/png;base64,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", "icon_all": "data:image/png;base64,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", "icon_blade": "data:image/png;base64,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", "icon_b_all": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAACgCAYAAACLz2ctAAAjbUlEQVR4Ae1dB3wc5ZX/z8x29Wpj2XKvwrjigjEdbAzGmNDJGUjoNXcJCZBccoGESyHkOHoSIEASklwIJRhM6N0xzYAblnuTbVldWm2Zcu/N7FraPpJ2Vyt7/j8/r7Q7s5ryn/e99r0PsGDBggULFixYsGDBggULFixYsGDBggULFixYsGDBggULFixYsGDBggULFixYsGDBggULFixYsGDBggULFixYsGDBggULFixYyFUIGGDQNM1GL5NIppNMJBlNcgTJYBIxanMfyZ6QbCVZQ/IxyTZBEFTkAOh8+B4MIZkG43xGkQwnqSApj7PLAZK9JNtI1pKsZqHz8WEAYkAQkG4S34zzSBaQnEBSiL6hgeRDktdJXiKppRuoIUug8+GHZTHJSSTHwSBgX8Dk+4DkFZIX6Fw2wELfwJqOZBHJsyR+LbPYQPJfJKORIdB355NcQfIqSVDLHBSST0huIimFhZ6BLpqD5DKSr7TsQyZ5jeQszRjq03E+U0keJunUso8GkntIhsJCcmiGxjtf6x/ixQMfBz8IDvQCtN+xmqG9cwEtJHeQFMNCLOjCjCFZoeUm1pEs1UxqRNpugpY7xIvGVs3Q7iIsHNR63yRp1nIf/IAcmeRc2Mb7Hy2z9l06wMf3W+1w14Z0AYpIHtUGFtpIbolzLmeS7NQGFj7TkjxQ2UK/hGHoxI+il9+QzEZfoGnQfAFofhlaUIHWoRz8SHAJEOwSvdoBpw2CLS0+RRgcuvkeSRPJ90muRZqgKRSe1M8pSOekQuvsClcKbpHOSdTPSXA5KerZ59vH8cTLKWyzAv2ErBOQyHcyvTwFI3jc052htndC3deOwBfbEXhvB5TNjZD3NUM90Aa1jsJh3hAJ8ySIQ9wQS/IgVRbBNqYMjpNGwlEzDNKQYrqBvfItuqORpIVkJPoALSjrxx5YuxuBlVshf1YPpZ7Op57Op9EPbb/f2NBGD1SVG1KRE+LgEtiqSuA4dQQcM0fBVl0GwWlHL9FOcj3JU9mMhYaRVQIS+U6hl6cRP8KfFPKWevjeXA/fc+sQ+HA7tIYAegWPBPvMIXCeNhrus6bCPnawoSWzCE2WIW89AN+KL+FfXovAxzt7fz52AfYZg+FaMgnuC2bCPoJi9kKPbysHslmT/zrbJMwaAYl8J9LLX9FD8in7W9DxxAfoeHgV1C2tSCucIhyzq+D55tFwLToKUnkBMgmt0w//ys3oePAD+FfUQmuXkU4IhXY4l0xEwXdP1DV9D4nIJLyaCPgksoisEJDIN5lelpMMM71PZwAdf1qJtrveTD/x4kAaVYi86+bAc+lcImJfM32RYOJ1vrYOHf/7PgKvbUWmIbhtcH9jKgp/eDqZHz1ydnk4vohI+CKyhIwTkMg3iF5eJZlsdp/gxjq0fPtZ+F/cjGxDGl2EgttPgOfC2RA8TvQFmqwgsGoLWn/0SlaIFw1pTBEK7zkTnjOn9UQb7iNZSCRcjSwgowTUjIDnQyRXmdwB3n98ipbrX4C6qx39Cftxw1D0yzPhPHp0b2wqKHVNaL3rFXgf+ZieqKzb9l0gMyPvlrko+sHinjgqTL7TiIT1yDAyTcBzYNh9UsqNSVu0PfIW2m79Z9pto96Cbar8W+aj4Nun0LBmThtyGMX3xlp6iJ6DUtuMnACpAdfZE1Hy+4shFnjM7vU4yVVEwozejIwRkMjHYZZPYdTpJQeRr+WOl9B+19ukOvpRWySAc8kYFN93PmzDypJup/n8aPvla2i7883+1XoJ4Fw0BqV/vtQsCZl4y4iATyODyAgBQ0Mvx/ouTrkxaYzWO5ej7Se5Sb4wpHElKHnyQjhnj4n7udrQjqYbn4bv6dwuxeshCdlwnUckrEOGkKmkNMf7Lki5Fdl87Y++g7afvZPT5GMoG5vQuPgJdL76Zexnuxtx4PSHc558DP9Lm9C07I96ANwEOMj+fS2DxQtp/2LNKF/6OUzYfZ2vr0XrLZQF8udEdXxKqPVeunl/gf9ftQffC27cg/qTH0Lwo4wpibTD98IGtPzwBV0BmMClJFORIWSC2TzspjxgeWcDWq58BlprEAMJ2t5ONJz9hE5CZVcDGhY9BuWrRgwo0PPu/Z+V8D73iZmt80lu09JUoBuNtNqAIe3HY9S4pNuR+m+89AkastZhoEIY7CanpHhAab5oSMMLULn6OxCL81NtylmSE8gW/BfSjHRrwCVIQT6G9++fwPfX9RjIYE04kMnHULa3oe2e18wMxS6SazNhC6btCzVjeuF1qbZTGtvQ/uNXc97pOFzQcd+/EFi/28ymZ6OPlT/xkE5GjyeZn2qjjsc/gLy+CRZyA1pzAO2/eM2oQ0yOIpJzkWakk4DLkMLzVepb4H1wJSzkFnzPrEdw7U4zm15KI920dDokaSFg6IAuSbVdx5MroWShssVCz8Cpz45739Ory+NvoIVNJu7c8B7Jy3TPF5PkoY9IixdMBzKLXpJ6SHxy+4/+FeQ1B2Ah9yAOcqPi3RthGzvIeINIp9S3wffJNih1LXplj1SWD9fUalWqLhMEu9RGW1EwEfeTfNLbnHG6VOkpqTbwf7wF8toGWMhNqPs60fnPtShgAhL5/ES8znc2QvX69Vw9z0+RN+2n97cLjpoq2TV/bL59WOklEIQTaHeeeP8QkbDHAdF02YDHp9qg8+9rzEbeLfQHBAFivlHxE9hYB+9bG6AFOEmg6f/0e8f/vAHB/+Eme9uDb2kdz69WSUtyX5s7SbjlyDkkrh79WfQRIfuPVVvCMmKNnqL9x94D+bP+G36FfBts4yogjS/V51/wpB95fT2ZBoq5/ctcsFUXQ+3w63nhXh1DoR22UaWkbjQENzV0TaDKAdjnDEbFmzeDKdH2xw+hNHXoMw3D2g/8M888lPlVJXIav9uqSlTPosmqY/YoUbCJPAz/k+SnJKvMdCBLxxA8Aim6VSl1zWT79V+6SjqyDIV3nQ73gskQHMYpK/ua4H3mc7T//C2oO9qS7u+6oAaFdy6ANKQUKt0Y70MfoO3nPSugsE0pR/GD58E+abA+jdT/Vi1ab30ZyrYW9DscIgruWKgXrHa+Xwu1tTM0WnXXft1+V8PvEwe3Nogt974pOiZvVPIunCnYx1aeQZ8cS/IYKacfEQmTVhang4ApJzf7v9yhPzX9AXGQByUPfw3OeeMj3pcGlaDg2uMh0MVsvW1FwiJYaWwxih86D1KJMWFJzHOj4MdnwP/pTgRWbIFZFD9ExzC3q5TLc+4MPSjfet1y9DecZ42F66QaKA3tCHy5k0c1RA+9iOLgQVIyGWWVcuPbpMBnu0X3iWOC7gtnFtoqCv6Dtqqk77oyWe/CdNiAY1JtIH/Rfykr1/mT4JgzNv6HZPd4ls2GbVJFwv0d06shReVKBZsE59GjYBZCmQPO6GOQRLiOn4T+hlDkQOEdi+hSCPB/tMUYbkNE65KQpo/QhlGf8782n9Dxty8czTc/o8k7GnlC89dJbkj299NBwOFJP1VVKF/2n/frOnEiBCnxaYqFHjhOTtwWUC/FjzcnRDJ/6cRh7rjfIXr6PDm+z/BcPh2OCVUI7m5EcFtjkqG3m6hdb8XTlPLWJqn5+/+wIcgGI76nJelDkw4CJp3nqwVkUu39E3wWyp0U10o9Ddk+ZrDeeeBwA5snBbedSo4FDaGrtkJTmS+R5NNitCEQQUgVXeRTtYM/y7WNUuebG/lTvgEJw3TpIGDSOR/sNbEX3B+QKvIhVuSn3m5cMXnJ2e2OkAtwXzZNnzccrK3Tg87dSaZFkA2RGjBC44VISuQLbx6Gf+X2sO1Xk+gYMt8njjUgeY79AbE0X5fu0Do6Y7azjaigobb/h8NswjauFPnXztczVP7Pd0WSK9rj0EmmIa5tGNZ8QKS9CN0mDMeZEg5DGSegpmpdB5hlSJNLIdgjHX3/hp1656mI7UgLiIU9ip8ObJC54bl+DsU1yxFYswtqOysq4x5pEVoOMUOvFqEN0aXxwkTsFuwQKwrCw0pCL/SQ7pRpnzQo5j3/+xtiku4cG5SOPHz6NdpnDUHe12dT6MmPwPq9CckWNwYYQ84oLdgNrhPHhCdTr0p0LJknIHl/Ql7fWlz0FvZRUR3g6GIFVmwjmzR2Hop9Yl9XShgY4L4x+becqLet839Vd3B23EHNhjheMKfpij1Rdl98ezCsER0zhyrOmcOZXzxV8J1Ex5MOAibtKyY4bTS8uZFtsAcsDY/UakpLh54OVFti46K2kZWHhSfM84LdC2ugNnYguLkesaEWRDoXlJpzTKQHWZK62XhaN2elG/nCwy9dx4Kb5itEXObXjynGmJAj6SDgnmQfctBWLMls27N4iOcBq/uaafgNQt4dm5M+HDxhkfLZ+d85kdS9Hf71u43usvxBPOKFfnZMGaZrP3V/a9Lht5vvQQSfELSPG8xe3fskf0t6TOg7diX7kDuRSlXpbXdmBmJ5YYwHrGxq0FNu8oZYm9g+ZtAh7wnn3TxH76iq7DgAeVdTLJnC42dIKzqnDYejpgq+DzcjIvDcPfYXoQE1CCVureBb3ApSHxmvSVUnmA4C1qbawDZjELIN24yyGA9Y3tKk5y3lTw4gujRMrCBPuPTQ9YTtM4+A5+JZeolVoHafHnyOGH7RzQ6kf46p1fCcPAmdr641qmKS2nxdmjH/qjmymK+34XqEyLcm1XGlg4Ap+1E4p45AtmEbHxsfl3caQ69S3xoTiuF0ne2o5M2HBiycIjxXz4JtVCXkbQegkP3XPZ+rRZBKgJOG3bxFUyg+uBPK3uZYuw9AvFCNbXSJnLd4Mj/1XPp0h5lDSwcBeXZ50sI224gyiCP6PH2gR7CPiNW68qZ9+qsSsgWjYRvf877pAwHOk0bAfdYUcr46Edx+IKKcqrtmE0Qi39zR8Cw8igtP4Xu/9mDeN2L76P1DQ3LBTcepsEnsyf2UtJ+p4s8+EzBU75V0lrlYnAfH0SOQLYhDPZCGRtmdXBTxhdGvj2vwtI44oZhDMCcsFDuQd+08ve1wcGs9ZSc4LapFhlJ4O4cd7lNq4Jk/jhxHEf7VO5LUBSLCA+ZX57wRQefMkTz0MhceNHt86YoDvpP0Uy49OmcisgU9BRftAbd69WpmhlbvpzBEbBGqNLbokPOEXedMguukCVAOtJL33xRBOh0U43PQ0Jx/3kw4Jw81qnZIw3GGJFERauTv5Hg4JBReO1+FqJf83NqTtYvTNSmJe0An7YrgOn4ihEoXtP2ZX1dZLMqL8YDV5o6IYTe4vR72yZE90zk1xZ4wT9Y+FCBV5SP/imN07RZct8ewezkx4KEYqcsOicIrttGVFDEo0IffMHg7PT2nIXER6sHf9bBLQBpexiGE12A0ozeNdBHwTRLO8ieMOEuDi+BaWoPOR0x1ZOoT4nnA6v7OiKpn+SuyB8+M3C/sCat1/dufOl3gahf70cOhsW1HD5tzUpXxgUgDn2SsJBW31pHJSaRUG71xh94ID9hp0zxnT+Ev4af7NtJ+PZrokpYhmP4oT2xYkWIj5H1zju6RZRrxPGB1X6segglD+bIpJn95KHnCtpoKeC6l6y1rCG7Yq2s0wePQ06KC227MjUnQfJ2roz3kBdtHhopYDjoasbFA98KJQdvIcn7anyDpsXZJJxv+mmoDBwU2ORWUacTzgIO7Ip0yXgBH88cOtYeEJ0zaLe+GuXpwXd7VgOCW/fC9uxG+lZuh+sz1Y7QdUYSCZfOQf9FsfbK6wM5t9yJUIqFUmqfkXTCDOcTTBO/ozSpL6Ww6yLPk95NUJtqA03IF3z0J/le3ABnqhB/XAwZX6O6L/H2vEYqJ7n5/0BOWe3wtcwaO+cPgXjJFn1Qu76HzVI2gc3Bnoz4KuOaNTbnQIVey69mQSUN0Tag2e8kx2YPA57shb9wHNaDAfc4UVSrTvbb7iXy7enOsaSMgHYCXPCxWw7ck247X3XBfNBmdv/0MmUA8D9gIwUTO5VW3ciiGLnJJ5KZhT3jAOiL5NuTdNJ9s7mIENuyhodcfYbcpTe16Djh6ER4uGpY379fjhPLuZr1US5+gJIfmA7O5ovDqpLKuYW3DSlT3ghpuRsVP9uPoJdLddpXjPzy7OXFSleysov88HYEVm6DsbEO6EdcD5hBMS2QltNYcJO3QSNoysmJmoHvCrjMnwH3qRJ1oyr6Wbs5DyGmgUQhiVxMztc2nD806WVt9ERPRD05MD3SbmM4/kxbNv2G2InocrP1+RcpnG3qJtBKQD4S0IK8rcWmy7aRhZSi4eyGalz2T9gbl8TxgnvlW8tQFdIEjSWWvibX3BrInLA52I//6+bpZIW/dbdh7YY8VxqtUWQjBaRAwSGk57xvroDZ5DU1nsgjVMWWo7JhezRd5Lcnv0AdkovH0XSRfg9HcOiHyzjkawXe2o+OBVUgn4nnAHHawTxgKMwh7wvLagdfFy33JVDhmjYDS0KavQdydNByAZs2uL+dKvwfW7Ybv4608bwOIV4QaHW4JZ04o6Jx30UyN7Hl+9yekdPrUbTTtMRE6oI0wVkNPDhoKCu9aDMep1Ugn4nnAPcVA9ISlCaUU5pqr/xzc1WRUu4C500UoW3WpXtsX+HIXfB9tCdmHkWTrXpUVU6rFQedjRwfsowex4nqb5Dn0EZkKyrEWTOkV8dBY+ttL9FWI0oFEHnBPMeBywhx2uYbCJeOH6HafxvZulDbjzlf2kZUUE9wD/xc7DGciHvEiqqMjtaFY6FI951LYRQDnNH/Qk5RbImSEgHRg3ArhGjPbSsPLUfq3yyCN7jsJdQ94cN8JKE0sHVA5YcdxQ5F34Syyp8mxqjPCLhHTKOlZcpBWlyn96P9iF1R/KAQWpwjV+BndCg1Cb5BCzVsyNUhhl3DQOS29ljOy+AiDSLicTuJeGF5xUjgoCV767DIcOO03+vIHvQV7wFJJlOlJV7Dt129A3hR/5dGiOxdDLIssFbMNKx04njDxIf+2UyBWFiBQW6eXUXXBYJCtqkSvbGG7T2+r1k3TaTFORvTPoeF7ZLnsPH4cRze4pf6dZlqvmUHGCBjCrTCaV6ZcOckxuRqlz/wbGhf/Hlpj7268bd6gmJ4tapsXnX/4FMHP9sbdh9ODjigCShUl5A27B4Qn7DprPFzHT9AJph7oOFigfLDGz+XQc76BjXuNWB5CG3RzUKLtvBgvmNOo501XRbfe2+6/iXym1nUwg4wSkG0E0oI8FHOVRMoeGa6541DyxHlouuQv0Fp7ninRbbco6DHAtsRaNbh1LxwzRsS8b5tWCfmLxOs1e64+Gs6zEjc14ooS729WofPxLxJuIw4pRPmn1yb8nFcS9b38FTrufi/iegge0no/OxmuE8bqbebYcw/uajSWWojyXLm2j+sA9V6G3QinaVF2XoKQix52mV4dtE84gm0SzvX+AWlEpjUgg+MsPAyzZ5x8AUN60txnTCMLQ0Pj+X/ucU9BW3VsFlA94NUlERINzZxH9elhrgR/a3CpLsngmjMR9XX3Q9kbvzknFwQ4pyXPjTtnjNOntbZ+62XjDVLwebfNR+GNp4XNOyjNXj2gHB3z038lzagpXY6FFl3Zgki/I0IbqtBr/fKXTOOwC9+MO0OFJ2lDxktTQgnqJ0l+ZnIHuM+ahqL7FxMLzB+eMNhFAe7Ysn91d5ue9UgEdU0roicoMWxDE6a0ewT3BVPQJxDD3IuOOvgrRwzyrzsenZSr9oXy1awBRU6tRWc9tOghNYQooiJJANo1f4xfOqKItd9LMNrvphVZac0Rmpr3ExjeU2pQ4Dj/imN7TMJ4CG7fn/Rzua4BWmds965wxwC1qc1IzPcWlOlRVreYXZ83PsKrGHEr3e+fBKGkAB/X+fDCdj82tsjQ8l26I+eYcITeCEDrZuqFyaTFOBYhbRhn6A2/LRZ5FM/Co4jdAneX4mqX3nuICZC13jChmBF3y3zF1A49JCGX2cu1kdkLJo7/xeST9oIrdyH4VayD4v/YmG3qf3cL/J9sRq9AxPE+ZmR62u5/Hb0ChVQ6/mR8h33OEHjOn4X9HTI2ezV4SQO+vzeIl4iIdZ0qxEFFcM8eA/voym7lU7xnd82oITbQjCitaPzsXlAji0XucNhlNTKArEdb6aljw+lFkrmmdqAb0P6799By3Qspm4Lbxpeg+NFz4ZwzTm/D0fbzf6Ljng9TllbZplSi+OGz4Zw1jgK0frQ99g7av/s6aUZDawkVLuTfdAzsx1aTVjDXZoRtS+8jqxB4fcfB9zxXzoDzaxP0fKwZcM8+/wsbyJn5VM/flj6/DLbjJ+L1HZ3YE4i8dfzb8AIJ08ttKCJNyaVYgbV7KPZ3QC8q0LvbU3bE+FkNFR0oXa/dO+Bz9/vKQrno5lMlwePgape5fSk4SIZ+CfcTCTn/xiScbGoH0iRNN/wV3oc/wuEK19drUPbE5dhM9uw79Ymr3lnxTSi2YUoZOTj0i3KgHf7V2/W6QJ1sIRLGElCNIGDh5fNkxxS94IBDab/oTbGpGfRLezY6GVYLZ5FsMrUDGdnF9ywlDTIdhyPEMjcK/3OBXji0tjn5lAseJNY2yXh2qx8b6BVl+XqHAzdPtyRbMXpuR5cZ2GUL2icdoThqqjhiwYuP/yZT5NPPDf2EkErnqpkdprZ3O1F877kUgjjWeMwPIwgFbtjHVenD1SnVLowtlBJN5ziITmLih/uDeJHsw91elTIZFShYSibAzJHGZKREXjA97HmLjgpPML+jr9UuqdDvd5KGY44x/IPEXFkMDRMtd7yE9rvePmwWveb6xPK3r4b9yK5LdMCn6g5Io4l6Sr7Jw/IlzCD7sNgpGkWoH9TC/+UufdGc7kWorlkj5bylMyTyfDl5cDZXuiODyAlVYpEwNTzfnouSu89FLYVdFE3AuCIjpr+xRcHnDUHdI06FaPtQ3tME7/LPjRJ8Ih8FxrXim08N6s0ogROJfB8gw8iZsSy05CuH+0tN7XAYkVCsLkTFyhvgKy/F8m2d8KoCSkmTHTPIjgq3CG4F/gWRcEOzbOpSuIl8U4mEY4mMIg27gY+3wvvqOriOHaO5Ka9MeAwmWqulAzllTBEJT6KX/4NFwi5wt9FfLkDBzadi1V4f1rV2nScb8CPJHpxWbkeBXUBLQMMn9UHsaFdg5mqUhEhcSSTW+2bb7Ub8ELiM5MlMOh9h5Jw13xsStj3wOlpvfy2nVp9MF2wzK1Hxxo1olhx4aYcfQSHWb+Q4/ZElNkwqtVGyREAdOR0fEREbfCbsQ2LAyAK2D+3Itx+kAyfIpxABM77GWk66kyES/pZklMkd0PHHD9Fy/fO9qqLJVXDVS8lfLoadcsFv7vBhV4r1fphANUTEMWQf2ohZW1oVCtvIaDRBRDsRd0qZXR1bLGkuUW+7PDsbBMzJZRroxN+glwtJPja5A/IuISP96Yv05uSHClznTID79MnY3hzAbn/q0bA9qOFfFHr5B4VetrUpGE3D8xnVTsyttMOTYopBkDtiqapCozJz4j4Y830zjpwOqJEmZIv4cZI5ZvfxrdyIxqVP9qmyOhfAC2RXvH0t1PFDsHy7Dy1yz24Vbz3IY4Re2MbjuOCaRpmC0wplJmPJXGgT5AXVTom0KBcwnp4N7cfISQ0YBl0EriS4HD2Yf+CiPHDZ85dBHJb9zvzpRN41M2GvGUqerdJj8jGYYnvJJl6x04/36gJ6Qc3RFXYsHu5AdX5kIJvLFiaV2QQiHxvRv8gW+UJ/O/cR0oRcRWN6DmdwYx0aFj0KZXNGA/kZgTScwi6rvgVvSaGeyfClwcN3kXc7kcIuE0sk3VHZQ+T85IBhH1IoRzmlyik6Jb3D2YVEwKwtbzpgclqhYPWzMOuYgLvi70fjeU8g+OleDBjQmFT8yBJ4rjgOH+wN6IHmdKLQQTHAUjtGkH3ItF7bKGvlRMAqj8guziIi3zvIInJ6CO4OujBsm5wII0FuCtwVvmz5lbAfU4WBAl7HzXPRLD3Vtrk1/WGlVooVvkvE5qA1+yXsNQ/x6M1i/owka7plCgOGgIxQFQ33NTVNQu4SVf7SNXAuzXxfwr5CGluCkscuhuZx4VOK42Uqtp5nF9RBbpFjM202SqQIBvF+kY6J5j3FgCIgI0TChSTvmt1HLPKg7KnL4VwyGrkKW00ZOU/fgH3iEXomg4PJmYBAxsyoAlErc4msXn9JcjrJ4lBLlaxjwBGQQReLA6Vnw+hNbW6fPBdKf78M7m+knKKcddiPq0L5K9foK3ZybehqyutmKgdW7BS18cV2Nv55iuWjdC3fJqlHP2FAEpBBF43nOp5D8ozZfcTifJTcfz7yvj0vZ2oKnUvHovzZKyFVGZlHnmTU5M8M/cj51SYU21QKt/BQ+2DoQe5XDFgCMugC8sozy9CDydJc2Fr0syUo+OnJgEdCv4EbgV8xDaVPXgqx1IhZciZjTVPmUomVNOyOKtRTIjxyPI8cwIAmICNUMHkFya9M78Ot4b67EMUPLIZQ1A9NiCjflX/7fBTfdz7E/K5JThvJM/VmqDe1XYRaoxcrgBtH3ZvNWF8yDHgCMuhicgzrdpIfIsW6dd12Qt5lRII/XQihwoNsQSDyFfz4BBT+15l635YwuCB5V0fmqnmG5UlKVR6vOq03k38LOYJDgoCM0Krc3JfwWyR+s/t5Fk1F+YuXQxpdjExDyLMj/54FKLxlka6Fu0NWNcrXIiPIkwR5UolNJLN3KwzbL2dKhg4ZAjJCq/Q8AKOg0nRrK8esUSh/+SrY52auM6o4yI3ip85D4XWnJFwiIRM3g/O8IyjsQuk2Htt/T9coM8sT9BKHFAEZoSrev5AsJTHd6JkXYyl77grdK003xPHFKH32MniWzki4DdfjFWdgFakih6hMKNFbS3wOs61RsohDjoAMJiEJz+riICtfeFOWvVRJRPnDZfrS9kJJelZPd54xhob4K+GcmzwTQxkJvX4vndEhkYLOE0ttKuV/2ST5dSiIn1M4JAkYBl1wLmhlTciTnUylFkRKgxXdfQ6K7j0T0qQ+rBvHnUtvmYfSP18Wt29hPPDUyVCQOC1pkMEeKTi6QGQ3nyuJnkUO4rCY4a1pGvdau5vkIvSgJ2Jg9Q60P/Ie/Ms3QjW7qA4No47jqlHwPW4gOSGmY2sK+P2K5ljfLAe/apZtXrn3CoKiferJQ53KEI/I/fw41ZaWns7pxmHTYoBIyB2B/pfkAhLT4yt32NKXNXh1HQIvbYK8s5HI2B4xC497E9oGF8HGlSznTYdz3uiYNehM4EMYudmrySE+tcmvauubFW1rmyzKas+JOLbI7p832OYQjHP+Ti55vt1xWPW4IBJyrOUHJFeS9LidvtrRqS+DoO7hpb8o/k3kFEsKIHJzTCIgp/p6CR4er+D0Ih3jEPr563yMFJoZvbdTU9c0BrW9XpXdWFNEdElQFw5zaiVOkW2+BfS9tchRHF5NVqCTkLUfxwr/HUlW9swS2NbjsNGt3Vtg0DEy0Y4kuYrkAp+ilW1vU9T1TYrWFFCTmhDseEwtd8hHldpEirVzZ6tfZWN+b29x2BGQEbrB/0byI5KR6B+wZ3obyQOhIHoM6Dh5HJ9HciMxaGG7rNk3NitqbUtQ7JRj+21zscGYQpt/VqXdSYEXrmz+WmjNlpzFYUnAMOgGnwajdzXXaGXzWnARBZsBfzez3kbIdOB2djeQfTi9kezDDU2KvNer2HwqZLsAscAhiOOKbRR0lmzkgKyjbZfRd38KC7kNurnTSF4g4SUlsoGtoYn3vTnWESS3k9Sq9F9HUAk2+FRfa0D1y4qmv0XyN5JJGCA4rDVgGHTDyunlehhTQIcjM+AaPHY2fkiayVxjzjigY+Whl2cJMol5jkxJ6Ls5xcZd7FdluqWahQyA7UKSOSSPkuzR0ocgyXskZ5M4YMFCMjBJSI4huY/kS633Q3MdyXMh4vU6PnOowxqCk4CIMwJGI/WTYTgqXC5TGpLuMTl2KrjAkxcl4eWV3oLRzWFTrgaAcwUWAU1CM+KHHDdk8nEQOy4BiXC5v8KhBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBQsWLFiwYMGCBRP4f2skWuXMOiezAAAAAElFTkSuQmCC", "icon_draw": "data:image/png;base64,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", "icon_energy": "data:image/png;base64,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", "icon_score": "data:image/png;base64,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", "jidou": "data:image/png;base64,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", "jyouji": "data:image/png;base64,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", "kidou": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAXoAAACgCAYAAAACcqdtAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAFP5JREFUeNrsnU1sHdUZhocGEzu9TghVSAgLUuFILBLVWdAFwiWom2RVKjXdlrBPgKXDomUBWRbCnqTbFql0lexq5IgFLOyqWSDZVd1F84cUHNuFJE6g8869AzfX92fOzJmZc848j3RlwPjeO2fOvOc73/l+oggAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoACPMASjmbn05YH4h15HO//ppc7P9L8DAFTBy/PH9syZ/tGjjFtfUZ/uiPl0l7gDAHgJQt8W91c6wv4KFjoAIPRhifuvOuL+OFMBABD6MMRdrpjXEXcAQOjDE/hX4x+/i/C3AwBCH6TA/z7C7w4ACD0CDwCA0Psh8EfjH+cReACAwIS+E/sugT/KLQUAeJgfBSDyf4h//BuRBwAIzKLvhErKip/mNgIABGbRxyL/RvxjAZEHAAjMoo8F/vGOFf8Ktw4AIDCh77hq/hoRUQMAEJ7Qd+Li/xg1qGxB69FHoiNPjEVTO9u3aGPzu2j+5r3o+jcPmLVQ25yc2bs92jfR9vhe/+bbaP7G3Wjj/ncMjuM4X4++I/Lnm3RTjj89Hp167sfJg9XLxf/ejT74YoOHCyrl5NSO6OSzO/r+7vy/vo7OL3/NIFVDePXoY5GXwL/aNJGfPdQa8vvtUWvskeithTWmPERTk49Gk/F8mI53fzIMDsb/rn8W2gF+9J9vooVbm6WJfPL7+Hfacf4l/ixwE2eFvokiL2TJjxybJx9LHvDl9fvM4EBJRLvjtts3se17d8mR3W0Rl0uv346vd57odfbKRrwTvJP7ewwT+e7FAKFH6BH5jNbZqIf3+zHa+xhC74Gl3UtqbT/0/3XuuXZq+nfbaIeos508ln262GRZEHSmVHT3AA0R+qaKvOgnDFWL0+l4R9ErRq6gcwkJyeWb93JbqCZIuI7tH4+emng43SSLNe0av3lmAhFG6BH5piNRe//5Xc67M1J3hNwJZxbWStvVjDor8Q2NGTQXZzJjO9muiHxNzB6a9Or7ymd97ue7SnF1yCceksgDOCH0XXHyUJM1v2/Cv2oYsvBPZzi8NrfmtzMpAKG3LPJpcTKoCVd98lm/u22rPo1sCQklNwFCX5fIK9P179wGKDSP9tr1P18LTBR1iH2GvItGU/dhrGrXPM5twNorgm2LfvGrzSDcN7qvF6/eif6y8g2Z1Ah9bdb8H6IAm4XIb3ziwESu7X/LILzy+P5xo89YiMVr0APve9jdpOVQR9VvGVSCwkUUeaTMVO1Ert95EC3G93Np7T7iDvUKfae36+9DG0xFa5x7flclB5v6DJPPkS9bIXanP7u9RQCUTKMaOhxCttH4nP3nevTOkZ21fofltXboaCrgiah3CThx8eCs0HfVlA+OM4daTkevyMXxbixepz+/veV3KpSmxCCfD2atWvU370WvfboanXhmIjkD6Lbu5RIZVUV0XULdE+O/b3xb5sVUgt7vPpU1Lwadc+g7Z0XJZabzJx1LFq3wLHpZ8gdCG8iprmJSLjOdhFJu2yJUshIlLEoUmt49tiUbtPLxdCD7VEJ99sp6/LLzfgpjdWnXpPHVwm9r3ha5Ns2/+Rv3kkqYlOL2XOg7oZRvhDiQRzyyhCXigx4mlRaoorxAloXzwxc4py+T2cOTzhgnWnS0UGhnIfcidZzsUrXZFmy8fGvMn9onPuw8eNDLRbs6F8siSPDLynhG6Kux5l+NAm7mragHX1jEH9p4XK59U1bGc5OpZNnsHMAGXeLAp8Oka2RJDrV0TzwznjTwqHPXpzOKcyUUmbt49W7imnN9BzroLAkcFvqo7ZcP2uEqV4MsZdfdIvqOPDwDxDUWd7kNXIif13coYy7pPXXYnoZruozOvS7+l7lqg9JdNx1r/vUmDOa7V9zu5arvpu8IA+7fkZ3e1ZnPQ3Lo6UHZYh8L7TVW6JtgzafIUv7tJ7eS5COXygpot6E2b/puWPODrUeExb0dFtih1JFskjXfbTUr9jqv2GRt/qF44/PLXzODLdG0RDEFDygpzGXLfrIBu6tQLPrGWPPg+26seQfUKvMgsQcs+qL8jiEGH2haCr4EXrvPtxbWEheJdpP9InFUOC/rbidxWY445E3KLdDWMByh78TNH2CIwQ+LvjmF3STw3dnPOsMZlKA2ZVDYLUv5gqTv7y9/woSrmDJdN79ieMEnVNhNh9ZhL2jf9q1gOggTP3mWg35KJwdk0cfWvCz5Vxhe8M3S/eCL/8Vif6eUKByT6pVp0xCbqCImPnmE3iaIPHhs9T4oJVHHpHqlvgNRVWCLslw3HMICAIQq9B23zTRDCwAQrkWP2wYAwCHK8NETbQPBkIQD7t1upetW1dUr1c5QRex0AEvpC4TeGp2SB0ebOJDD+m5mxaQ/pxJZoqkdxp+h1HfFULsc5iZxPXFgovbvoX6xJ+MxrqPQma3qlUpOOvXcj5McAYWPmt53LTiA0PfSSJGfPTRZeaJNUm42pxBIvEalv6d12RUp0sTiUnXc0zLRtRzcuc0ohj5dcLJwnR4HTmPbR9+4Q1iJpm+CoIdX/UIl5oOu6c+/2J1YtE0UedeaeNvcdZ7MsQvMJvS4hpok9C81bQAlhj6SuEdii70XbfNPPruj0Q9FyNev+dqiKiRCX5CjTbP8fH5oetvl6Xp8XbhsLoChlyw+0rCSzGBR6GcufUnsvGf0Ctqx/eNeXsfSgIJcuRa/Bhw+Zj1gpfEHQt+PAwynX/QeyhWNGqqL5XX8wyZkje6aHMPFEwo2l+zGWfTXPI806K7BroNZH91QWqzmb9yt/HMVZZInXDFrBzEVV1s23KloR5blEPmpElom2txVgdtC/7OmDZ4iDZSQ4qtP93JXeOVTnvZLVVnhOnICVFmyzEqQEnnTZigyPOqKFqL8sNvYfLob2TLwXGx5+TjJtUB1N5/wESUBUeHxYcPDJvjoEfp+NPIwVpaXklAWPWpFJyv4zMKat2OuhVXdjPI2YYdstPDRB4PNJbuxTcATsf/8duLjLhK1IQtKcexZrdlLho0p1je/M/b7DrtmlVOoCrkl1I+U5hmOPgNr+OibIvSNR5ZmVU2mJXp1NbTW7kULG4SNSe2lrO5Lkxj+ha82uQkuCf3MpS+PMpTNgQcwio7vH28XlisJ7eyq3DH1w9cDesCiB7Bj7cYiuK9EIfTtIHR9k6gbl2HJBoD+i43BedMycfQIPQD4B8XPEHoAQOQTSJZC6AHAQ0zChAmtrJRFhB4AKrfooTrmj+1ZzfN3RN2UhIqEddcdUREsFd9imxuIWXVrM1eYadamJkqIU65EWe8/CpODWAqauQ9CXwLHnx6PZg+1tvx3xUarNotKEEDxhTSN87aZ8ZsViXyeOjtZhVhZz3kS4mwJPT56hB6GoMy/fiKfPjxpiQPEPr8AnXqutaVKo3ZMGlPG1Q4HDeL4aQzuPvjoLfPik6Obd6hBMz7QfCJ/7ue7+pbiVfKSFtHZQ5MMlKUdU3ahp/ELFj2WUF/BUlRDkVo1eVLwL16963Vp4hMHJkZmjGoRkBsHy76o0Ge3Aa9h0VfFHELfwAfRNAV/Omn+PR699umql9d8PGNPWzU4b6LQm1jhwzAtv4BF7z64bhqGHmK5jnxDu6CsC5v+v7Jrxcw8+ZhT9Wg0PrYOYk2KmVH6oFIW8/4hFn0DkcXrW2cm0zr/ZTe2lsh/+EJ5LRiy9pbNwyhXi0lo5QbFzKokd21wLPoG0raOt3n3ncEOo+LzTXYqlKz2w6JH6BuKb7XGpwwt+qWcaflLDUjnH1WygNBKZ1lB6B3BF0vZt0gJk25HiUshZxKP/i70VoXDor1MzkLaQs9BbFXMH9uDRe+O0Ls/pBIz3x7QgzuzC33RRu0fBRyxo2ikYYug6VlIXe0sG8hckT9G6BtoUfsYemjiN14vmJIv8VKtmdBQhMyoQ/hpg56uuG0qZbHIHyP0NVGXRZ0kE634JfQzGbKNe6+xKGevrEfn//V1MPNN7qjTn90e6dIyWVDzFDMzeX/KHz/EP4r8MeGVFnE5MkTip4fdRlhl1df54pPbzUwfS+4EjZUsey00erXGHvGml6usbRkTEmNdQ9bF74iBRZ9nQW2NUSwtJ3MIvSOY+jcLiVBsbdYVC28iBjYWlZm9Zha9zcgZiaWtYmkat6zx8VqsTn9+u9L7qkXMZBFfxD9fFSvzx/asFHkDXDeQSxCqsmxnD08aiY8sWSzBahbwJVwrVfFx0TdA6C2SNbTSRSEyfWjPHG6VatlL3N85stPYP08USH6mDd02LKiV8UnRN8B1Y1Xos62bLqaNmz60sujlhtADL3HV328UaAAiYU+TolSVczrnIrJIpmYlFv3SGvHzFbE6f2xPYYseoa9pQVDt9A+++J9T30sibeqSqdKNkwW1a4R8Im/kn2dBrYqPbbwJQm/zYTGoD6/CYpdv3nPK1SArzZeokr4iH4+nbXeCxsNWgTSTsVV0ii3XWJY59mJFLjKTZ4Q69wl/Q+g9Rz5o1YZ3JUv18s27fbs3+cIli01VZN2+G9+f6QojjHoXBVsVLLX4nf3n+tDSDjMGIaxp6GbZUF7BjttGcBhrEVNRaIvJpDPx92VYxFUh8bFZo0YtC+sSedukB9uDdghaVExKd8zfxD1WERdsvRFCb/Fhymu5yXJ0BV87MymT1RbHnx732oU1iN88MzHgeutJSIORvI/QO0aRZClZjq40tVYSlm9dg5T5afOsY3r3WJBzdFCo6oxh5nGRnVMou6QKmCuaJIXQl0DR8sSyqhSJ4wJnFta9ceFoUfrgiw2r7+lbrf4iyJ1j5rappoQzu4bobZtvhtBbE/riQ+mKu0CHYL/95Jbzln3WQl2mhNo1qd84HcvYcD3lcgGhp0tYZlTyYM7mGxJ1Y8syCmy7L1FQRJD81Wo67VKdfR28qtbPRYtRNlusyWfDm6PzN+5tEV5T/3yRPIUqa0FhzSP0pTAV6CSWmOol/678q9rq17HzSDNwJcJluw/0OTqUPjHg8NJH+rm4tIib7qCqcuktrTe2jo6s+QsIvYPIPx/6tlQPebfA6ppTX3ZS9XDM3vWrDnkqKOsFyioUQVnLy+sPouP7t3t9gJiWp1YPgl6RNl3ILhdcYE3GscF1dN4u400RegscnNzWuGuWHz9NaAm1kFi6m7GFS2WKZc2buOMkvEXHwrTvbwOZK8OaFxzGWmAK3yN4hnYqRju6G8XdZSbRTA2Nunm7rDdG6G1YagYHsbb8y0QwQJGdhak7ykYiHTH0Q7lgO9IGobeMyQRWzREbPmf5V889v8v4QA1AUVQmaL4WnbOmBdoa1ldgNX69WeYH4HMoiEkEymKnbrtiv1VLpWj0ynTHMlOiVduffNe7rFYo33rvPizXTtDcmi9+TmFSHbOBB7Fvx9b8KkLv+IOUlTRkzKbYpw+vLHy9FGMua0iVKNOGIBAeuudpXLoioNKD1dSNaMtNovlU9BC2Ha+ffee53KwWhTqAfa/sD0HoC2LS6k7het1Wi8T+1HMtq6WB9cDr/dL3lIWvOvPp9ntpzc8WcOmCmoqaIji6D/dUu/zS1TvBbPl1nSendjwk3jYFPCsXrxa35k8cmDA6U2pQDL2s+F9X8UEIfUGmjdqv3d+yRVXVxet3Hhj7TbPyQweo7Q99rqym9fs/xKj3qzF+LWfd8ay7nH7x992i1m2pjrwPUbtekOLfy6rA2W1F94pyv+/Ze0hvkmug9ytrTpi4UBR/X3SBNr2O681pOHKybJcNQl+xNb9xf3DijypGyn+vmuFVRNN0+2lNm2+7js4rtDjliW7SwiP318Gd24IsU2yKFsx095fsMGLB7t19at4uJbvFdl5FasxoQVQdnTy71YYcxL5nq6kIQl8yLxqUdx3ld9TkViGx2cOTwYlv9WLfioX+ltHfyIc8e6jF4PWx5rXo6TypnxEy/cSYdXdSAwIKFmORf7PKDyS8suC2NLOVkqEioh6utxbWktd1+mXmRm4Po/6ssYC5UiLaRWv+dDw2VeVtVFUGuUbkqnm56g9F6HNi3H7NILNQk/21T79KKjQSNZMPk4beM3u3k4A2wJqXy6bKA+DLYQt9IvJV+eUReguYFIQa5p8f9jfy3cudg+CXvwOAH9CBdjrfqm7CUqQMsge8GYv8Yh0fzAzPyczexwwmb34rpVvwz17ZwKWTkaU1EsfyIIOkrDr/WXayARs0J8sqWJYFDmNzYrLVV/KSje10Wk0xjQ7RYoPLYSvKEDYRjBAajUigNza/SyJg0vBZBQuYRr3Imq+LjzxtTO+6yCP0FSAL3PYBkx5qxd+fvRJ93xBEDZ5xQeTrIauIJ90nF8evO78hFfGNrhr9w0IR232Mswt9vybrVe2MtNgGGlZZu8gj9AUt7CzWtI3MwlHbXb1kienBTioT7h5rZCy4hEoin2f7r4Uza614W8LdnbDWLd62mq1oXmSNJtKY9Vsg2zvJu1azt/t9xrtXNkKckk6IPEJf5CG6cW/k5LeRWWgmIg/ih/LBQz7W7qJWytTUzxAWgNRVIbFM2wvmyeLtturVI/fM4dbI8enNIl7vOWzv/X1dZSf0HbK2RFRV1UHfUcEAZboJ9dlF7h0iPxord27m0pdH4x9/b5LQy3r+8IXHh05+xcO7HBec5gHoGvo1Tymz4XlSXuHOg5Hb+V4xrureptEmvtYG6mb20ORQo0RzVHN1GMOSpopY8hL5wGLnVzsi/7FLXwqhL4CyKU8NSCbRdlfuAAAnzMupHYll3ztXTdxdaRkEGQhFzzOKuNkcF/mX6wqhROhLtv40+dOtrbbwCodsQIYfeIbmZ+LK6+ze5H4schYgK1+JaWlC1aAqm6mbTbu4xa82k1j5AMMoF6OakqEQegCA8nmv6to1pnAYCwCQDyf98f0g8BoAwByJ+099EHksegCAQK14LHoAAHMu+GTFY9EDAGRnLqqx8iRCDwBQHitR200z5/uFIPQAAFst+D+5VMIAoQcAsIN87++HYMEj9AAAP7Ai6z1+XYgFfiXUi0ToAaBprHas9z+FaL0j9ADQVBQxM9cR98WmXTxCDwAhWuwS809SgXe12BhCDwAw3EJf7bz+0SXuKyH72gEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAauH/AgwAZaYgRe0Pgn0AAAAASUVORK5CYII=", "live_start": "data:image/png;base64,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", "live_success": "data:image/png;base64,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", "toujyou": "data:image/png;base64,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", "turn1": "data:image/png;base64,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" }; // Phase enum from game_state.py // Phase enum from logic.rs (Rust) const Phase = { SETUP: -2, "-2": "SETUP", MULLIGAN_P1: -1, "-1": "MULLIGAN_P1", MULLIGAN_P2: 0, "0": "MULLIGAN_P2", ACTIVE: 1, "1": "ACTIVE", ENERGY: 2, "2": "ENERGY", DRAW: 3, "3": "DRAW", MAIN: 4, "4": "MAIN", LIVE_SET: 5, "5": "LIVE_SET", PERFORMANCE_P1: 6, "6": "PERFORMANCE_P1", PERFORMANCE_P2: 7, "7": "PERFORMANCE_P2", LIVE_RESULT: 8, "8": "LIVE_RESULT", TERMINAL: 9, "9": "TERMINAL" }; let offlineMode = false; let wasmAdapter = null; let selectedIndices = []; // For multiphase selection (Mulligan, Choice) let selectedPerfTurn = -1; // -1 means current/latest, otherwise specific turn number let currentLang = 'jp'; // Default Japanese let hotseatMode = false; let perspectivePlayer = 0; // 0 or 1 let roomCode = localStorage.getItem('lovelive_room_code'); let sessionToken = null; let showFriendlyAbilities = localStorage.getItem('lovelive_friendly_abilities') !== 'false'; // Default ON /** * Centrally manages how ability text is displayed based on Language and "Friendly" settings. */ function getEffectiveAbilityText(card) { if (!card) return ""; const rawText = card.text || ""; const originalText = card.original_text; // Do not fallback to rawText here yet let effectiveText = ""; if (currentLang === 'en') { // English mode: Always show simplified pseudocode (translated) effectiveText = window.translateAbility ? window.translateAbility(rawText, 'en') : rawText; } else if (showFriendlyAbilities) { // Japanese mode (Friendly ON): Show simplified pseudocode (translated to Japanese) effectiveText = window.translateAbility ? window.translateAbility(rawText, 'jp') : rawText; } else { // Japanese mode (Friendly OFF): Show official original Japanese text if available if (originalText) { effectiveText = originalText; } else { // Fallback: If no official text, force friendly translation to avoid raw pseudocode effectiveText = window.translateAbility ? window.translateAbility(rawText, 'jp') : rawText; } } // Apply icon enrichment (e.g. [Auto] -> ) return enrichAbilityText(effectiveText); } function getEffectiveActionText(action) { if (!action) return ""; const rawText = action.raw_text || action.text || ""; let effectiveText = rawText; // If we want friendly/English, use the translator on the raw pseudocode if ((currentLang === 'en' || showFriendlyAbilities) && window.translateAbility) { effectiveText = window.translateAbility(rawText, currentLang); } // Otherwise in Japanese mode without friendly abilities, try to get original Japanese text else if (currentLang === 'jp') { const srcCard = resolveCardData(action.source_card_id); if (srcCard && srcCard.original_text) { effectiveText = srcCard.original_text; } else { // Fallback: Force translation if no original text found (to avoid raw variable names) if (window.translateAbility) { effectiveText = window.translateAbility(rawText, 'jp'); } } } // Apply icon enrichment let text = enrichAbilityText(effectiveText); // Final cleanup: strip technical prefixes if they persist in the summary text = text.replace(/TRIGGER:\s*/g, ''); text = text.replace(/\[TRIGGER\]\s*/g, ''); return text; } function getActionTags(action, vertical = false) { if (!action || !action.triggers) return ""; const tags = []; if (action.triggers.includes(1)) tags.push(`[登場時]`); if (action.triggers.includes(2)) tags.push(`[開始時]`); if (action.triggers.includes(7)) tags.push(`[起動]`); if (action.triggers.includes(6)) tags.push(`[常時]`); if (tags.length === 0) return ""; if (vertical) { return `
${tags.join('')}
`; } return `
${tags.join('')}
`; } // Helper to get common headers function getHeaders() { const headers = { 'Content-Type': 'application/json' }; if (roomCode) { headers['X-Room-Id'] = roomCode; // console.log(`[DEBUG] Sending X-Room-Id: ${roomCode}, X-Player-Idx: ${perspectivePlayer}`); } else { console.warn("[DEBUG] No roomCode set for getHeaders!"); } headers['X-Player-Idx'] = perspectivePlayer; return headers; } function updateRoomDisplay() { const display = document.getElementById('room-code-header'); if (display) display.innerText = roomCode || "---"; } function saveSession(room, sessionData) { if (!sessionData) return; const key = `lovelive_session_${room}`; localStorage.setItem(key, sessionData.session_id); sessionToken = sessionData.session_id; // Auto-set perspective if (sessionData.player_id !== undefined && sessionData.player_id !== -1) { perspectivePlayer = sessionData.player_id; console.log(`Assigned as Player ${perspectivePlayer}`); } } function loadSession(room) { const key = `lovelive_session_${room}`; sessionToken = localStorage.getItem(key); } async function createRoom(mode = 'pve') { console.log(`[DEBUG] Creating room with mode: ${mode}`); const isPublic = document.getElementById('public-room-check')?.checked || false; try { const res = await fetch('api/rooms/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ mode: mode, public: isPublic }) }); if (!res.ok) { const text = await res.text(); alert("Server Error: " + res.status + " - " + text); return; } const data = await res.json(); console.log("[DEBUG] Create Response:", data); if (data.success) { setRoom(data.room_id); // Host is always P1 (Idx 0) perspectivePlayer = 0; document.getElementById('room-modal').style.display = 'none'; // Auto-refresh to get state fetchState(); } else { alert("Failed to create room: " + data.error); } } catch (e) { console.error(e); alert("Network error creating room: " + e.message); } } async function joinRoom(code = null) { if (!code) { const input = document.getElementById('room-code-input'); code = input.value.trim().toUpperCase(); } if (!code) return; console.log(`[DEBUG] Joining room: ${code}`); try { const res = await fetch('api/rooms/join', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ room_id: code }) }); const data = await res.json(); console.log("[DEBUG] Join Response:", data); if (data.success) { setRoom(code); document.getElementById('room-modal').style.display = 'none'; if (data.mode === 'pvp') { console.log("[DEBUG] PvP Mode detected, showing perspective modal"); // Joiner defaults to P2 (Idx 1) perspectivePlayer = 1; document.getElementById('perspective-modal').style.display = 'flex'; } else { console.log("[DEBUG] PvE Mode, fetching state directly"); fetchState(); } } else { alert("Room not found or invalid: " + data.error); } } catch (e) { console.error(e); alert("Network error joining room: " + e.message); } } async function fetchPublicRooms() { const listEl = document.getElementById('public-rooms-list'); if (!listEl) return; if (isStaticHost) { listEl.innerHTML = '
Public rooms are only available in Online Mode.
Please use Start Offline below.
'; return; } listEl.innerHTML = '
Loading...
'; try { const res = await fetch('api/rooms/list'); const data = await res.json(); if (data.success) { const rooms = data.rooms || []; if (rooms.length === 0) { listEl.innerHTML = '
No public rooms found.
'; return; } let html = ''; rooms.forEach(r => { const modeLabel = r.mode === 'pvp' ? '⚔️ PvP' : '🤖 PvE'; const timeStr = r.created_at ? new Date(r.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : ''; const phaseStr = r.phase === '?' ? '' : `(T${r.turn})`; html += `
${r.room_id} ${modeLabel}
${timeStr} ${phaseStr} • ${r.players} Player(s)
`; }); listEl.innerHTML = html; } else { listEl.innerHTML = '
Failed to load list.
'; } } catch (e) { console.error("Fetch rooms error", e); listEl.innerHTML = '
Network Error
'; } } function setRoom(code) { roomCode = code; localStorage.setItem('lovelive_room_code', code); loadSession(code); updateRoomDisplay(); } function leaveRoom() { if (!confirm(currentLang === 'jp' ? "ロビーに戻りますか?現在のゲーム状態は失われませんが、再参加にはルームコードが必要です。" : "Return to lobby? The game state will be preserved, but you will need the code to re-join.")) return; roomCode = null; state = null; localStorage.removeItem('lovelive_room_code'); updateRoomDisplay(); document.getElementById('room-modal').style.display = 'flex'; fetchPublicRooms(); } window.startOffline = async function (userInitiated = true) { console.log("[OFFLINE] Starting Offline Mode. userInitiated:", userInitiated, "location:", window.location.href); offlineMode = true; hotseatMode = true; // Offline implies local hotseat or PvE document.getElementById('room-display').style.display = 'none'; // Load WASM Adapter dynamically - use absolute path from base for reliability try { const base = getAppBaseUrl(); console.log(`[OFFLINE] Importing ${base}js/wasm_adapter.js...`); // Using base ensures this works on both localhost and GitHub Pages subfolders const mod = await import(`${base}js/wasm_adapter.js`); wasmAdapter = mod.wasmAdapter; console.log("[OFFLINE] Initializing wasmAdapter..."); await wasmAdapter.init(); if (userInitiated) { document.getElementById('room-modal').style.display = 'none'; } fetchState(); } catch (e) { console.error("[OFFLINE] Failed to load engine:", e); alert("Failed to load Offline Engine: " + e + "\n(Check console for more details)"); offlineMode = false; } } // Initial Check window.addEventListener('DOMContentLoaded', () => { updateLanguage(); // Auto-detect static hosting (GitHub Pages) and fallback to Offline WASM if (isStaticHost && !roomCode) { console.log("[ENV] Static host detected, auto-starting Offline Mode."); startOffline(false); // Initialize but don't hide lobby } fetchAndPopulateDecks(); // Fetch dynamic decks if (roomCode) { loadSession(roomCode); document.getElementById('room-modal').style.display = 'none'; updateRoomDisplay(); fetchState(); } else { document.getElementById('room-modal').style.display = 'flex'; fetchPublicRooms(); } }); // --- Game Setup / Deck Selection Logic --- let setupMode = 'pve'; let deckPresets = []; let pvpJoinPid = 1; async function fetchAndPopulateDecks() { console.log("Fetching decks..."); try { let data = null; // Try API first if NOT on a static host (like GitHub Pages) if (!isStaticHost) { try { let response = await fetch('api/get_test_deck'); if (response.ok) { data = await response.json(); } } catch (apiErr) { console.warn("API deck fetch failed, falling back to static:", apiErr); } } if (!data) { // Fallback to static JSON console.log("Using static decks/list.json"); const response = await fetch('decks/list.json'); if (response.ok) { data = await response.json(); } else { console.error("Failed to load static deck list:", response.status); } } if (!data || data.error) { console.error("Error fetching decks:", data ? data.error : "No data"); return; } const mainDecks = data.available_decks || data.main_decks || []; // const energyDecks = data.energy_decks || []; // Not used in UI yet populateDeckSelect('p0-deck-select', mainDecks); populateDeckSelect('p1-deck-select', mainDecks); } catch (e) { console.error("Failed to fetch decks:", e); } } function populateDeckSelect(elementId, decks) { const select = document.getElementById(elementId); if (!select) return; // Clear and rebuild options select.innerHTML = ''; // Add Random Option const randomOption = document.createElement('option'); randomOption.value = 'random'; randomOption.textContent = '🎲 Random Deck'; select.appendChild(randomOption); // Add Paste Option const pasteOption = document.createElement('option'); pasteOption.value = 'paste'; pasteOption.textContent = '📋 Paste Deck List...'; select.appendChild(pasteOption); decks.forEach(deck => { const option = document.createElement('option'); option.value = deck; option.textContent = deck; select.appendChild(option); }); } // Global handler for select changes window.onDeckSelectChange = function (playerId) { const selectId = playerId === 0 ? 'p0-deck-select' : 'p1-deck-select'; const select = document.getElementById(selectId); if (!select) return; const val = select.value; const pasteArea = document.getElementById(playerId === 0 ? 'p0-paste-area' : 'p1-paste-area'); if (val === 'paste') { if (pasteArea) pasteArea.style.display = 'block'; } else { if (pasteArea) pasteArea.style.display = 'none'; console.log(`Player ${playerId} Deck Selected: ${val}`); } }; window.openGameSetup = function (mode) { setupMode = mode; document.getElementById('setup-mode-display').textContent = mode === 'pve' ? 'Mode: Solo (PvE)' : 'Mode: PvP (Multiplayer)'; document.getElementById('setup-modal').style.display = 'flex'; document.getElementById('room-modal').style.display = 'none'; // Hide lobby const p0Col = document.querySelector('.setup-column:nth-child(1)'); // Player 1 const p1Col = document.getElementById('p2-setup-column'); // Player 2 const startBtn = document.querySelector('#setup-modal .btn'); // Reset styles p0Col.style.display = 'block'; p1Col.style.display = 'block'; startBtn.onclick = submitGameSetup; startBtn.textContent = mode === 'pve' ? '🚀 Start Game' : '🚀 Create Room'; if (mode === 'pve') { p1Col.style.opacity = '1'; p1Col.style.pointerEvents = 'auto'; p1Col.querySelector('h4').textContent = '🤖 Player 2 (AI)'; } else { // In PvP Create, only P1 sets their deck p1Col.style.opacity = '0.3'; p1Col.style.pointerEvents = 'none'; p1Col.querySelector('h4').textContent = '👤 Player 2 (Waiting...)'; } // Init Dropdowns fetchAndPopulateDecks(); }; window.closeSetupModal = function () { document.getElementById('setup-modal').style.display = 'none'; if (!roomCode) { document.getElementById('room-modal').style.display = 'flex'; // Show lobby if not in game } }; window.onDeckSelectChange = function (pid) { const select = document.getElementById(`p${pid}-deck-select`); const pasteArea = document.getElementById(`p${pid}-paste-area`); const val = select.value; if (val === 'paste') { pasteArea.style.display = 'block'; } else { pasteArea.style.display = 'none'; } const preview = document.getElementById(`p${pid}-deck-preview`); const namedDecks = { 'muse_cup': "μ's Cup tournament deck", 'aqours_cup': "Aqours Cup tournament deck", 'nijigaku_cup': "Nijigaku Cup tournament deck", 'liella_cup': "Liella! Cup tournament deck", 'hasunosora_cup': "Hasunosora Cup tournament deck" }; if (namedDecks[val]) { preview.textContent = namedDecks[val]; } else if (val.startsWith('preset-')) { const idx = parseInt(val.split('-')[1]); const p = deckPresets[idx]; preview.textContent = p ? p.description : ''; } else if (val === 'random') { preview.textContent = "A random valid deck will be generated."; } else if (val === 'paste') { preview.textContent = "Paste a list of PL! IDs below."; } else { // Any other value is likely a named deck from ai/decks preview.textContent = `Deck file: ${val}.txt`; } }; function getDeckConfig(pid) { const select = document.getElementById(`p${pid}-deck-select`); const val = select.value; if (val === 'paste') { const text = document.getElementById(`p${pid}-deck-paste`).value; if (!text.trim()) { return { main: [], energy: [], type: 'random' }; // Fallback to empty (random) if empty paste } // Extract PL! IDs const matches = text.match(/(PL![A-Za-z0-9\-]+)/g); if (!matches || matches.length === 0) { alert(`No valid card IDs found in Player ${pid + 1} deck paste.`); return null; } return { main: matches, energy: [] }; } if (val.startsWith('preset-')) { const idx = parseInt(val.split('-')[1]); const p = deckPresets[idx]; return { main: p.cards, energy: [] }; } if (val === 'random') { return { main: [], energy: [], type: 'random' }; } // Default to 'named' for anything else (assumed from ai/decks/) return { main: [], energy: [], type: 'named', deckName: val }; } window.submitGameSetup = async function () { const p0Deck = getDeckConfig(0); if (!p0Deck) return; // Resolve named decks async function resolveDeck(config) { if (config.type === 'named' && config.deckName) { try { // Try API first let res = await fetch(`api/get_test_deck?deck=${config.deckName}`); let data; if (res.ok) { data = await res.json(); } else { // Fallback to static console.log(`API not found for deck ${config.deckName}, trying static decks/${config.deckName}.txt`); res = await fetch(`decks/${config.deckName}.txt`); if (res.ok) { const text = await res.text(); const matches = text.match(/(PL![A-Za-z0-9\-]+)/g); data = { success: true, main_deck: matches || [], energy_deck: [] }; } else { data = { success: false, error: "Static deck file not found" }; } } if (data.success && data.main_deck) { return { main: data.main_deck, energy: data.energy_deck || [] }; } else { alert(`Failed to load deck '${config.deckName}': ${data.error || 'Unknown error'}`); return null; } } catch (e) { alert(`Error fetching deck '${config.deckName}': ${e.message}`); return null; } } return config; } const resolvedP0 = await resolveDeck(p0Deck); if (!resolvedP0) return; const payload = { mode: setupMode, public: document.getElementById('public-room-check')?.checked || false, decks: { 0: resolvedP0 } }; if (setupMode === 'pve') { const p1Deck = getDeckConfig(1); if (!p1Deck) return; const resolvedP1 = await resolveDeck(p1Deck); if (!resolvedP1) return; payload.decks[1] = resolvedP1; } console.log("Creating room with decks:", payload); if (offlineMode && wasmAdapter) { console.log("[OFFLINE] Creating local game..."); try { // Ensure WASM is ready before proceeding await wasmAdapter.init(); const p0Config = await wasmAdapter.resolveDeckList(resolvedP0.main); const p1Config = payload.decks[1] ? await wasmAdapter.resolveDeckList(payload.decks[1].main) : null; const res = await wasmAdapter.createGameWithDecks(p0Config, p1Config); if (res.success) { state = res.state; document.getElementById('setup-modal').style.display = 'none'; render(); } else { alert("Offline game creation failed: " + res.error); } } catch (e) { console.error("Offline setup error:", e); alert("Error in Offline Engine: " + e.message); } return; // Important: Don't fall through to API call } try { const res = await fetch('api/rooms/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); const data = await res.json(); if (data.success) { setRoom(data.room_id); // Assuming Creator is always P0 perspectivePlayer = 0; saveSession(data.room_id, data.session); document.getElementById('setup-modal').style.display = 'none'; fetchState(); } else { alert("Failed to start game: " + data.error); } } catch (e) { console.error(e); alert("Error starting game: " + e.message); } }; window.openDeckSelectionForPvP = function (pid) { pvpJoinPid = pid; document.getElementById('setup-mode-display').textContent = 'PvP: Select Your Deck'; document.getElementById('setup-modal').style.display = 'flex'; document.getElementById('room-modal').style.display = 'none'; const p0Col = document.querySelector('.setup-column:nth-child(1)'); const p1Col = document.getElementById('p2-setup-column'); const startBtn = document.querySelector('#setup-modal .btn'); // Hide the other player's column if (pid === 0) { p0Col.style.display = 'block'; p1Col.style.display = 'none'; document.querySelector('#p0-deck-select').closest('div').querySelector('h4').textContent = '👤 Your Deck'; } else { p0Col.style.display = 'none'; p1Col.style.display = 'block'; p1Col.style.opacity = '1'; p1Col.style.pointerEvents = 'auto'; p1Col.querySelector('h4').textContent = '👤 Your Deck'; } startBtn.textContent = '✅ Submit Deck & Join'; startBtn.onclick = submitPvPDeck; fetchAndPopulateDecks(); }; window.submitPvPDeck = async function () { const deck = getDeckConfig(pvpJoinPid); if (!deck) return; console.log(`Submitting deck for P${pvpJoinPid}...`); // Call set_deck try { const res = await fetch('api/set_deck', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }, body: JSON.stringify({ player: pvpJoinPid, deck: deck.main, energy_deck: deck.energy }) }); const data = await res.json(); if (data.status === 'ok') { document.getElementById('setup-modal').style.display = 'none'; fetchState(); // Maybe show a waiting toast? alert("Deck Submitted! Waiting for host to start/reset game."); } else { alert("Failed to submit deck: " + (data.error || "Unknown error")); } } catch (e) { console.error(e); alert("Error submitting deck: " + e.message); } }; function openSettingsModal() { document.getElementById('settings-modal').style.display = 'flex'; } function closeSettingsModal() { document.getElementById('settings-modal').style.display = 'none'; } const translations = { 'jp': { 'turn': 'ターン', 'phase': 'フェーズ', 'score': 'スコア', 'update': '🔄 更新', 'reset': 'リセット', 'deck_creator': '🛠 デッキ作成', 'set_deck': '🎴 デッキ設定', 'friendly_abilities': '読みやすい能力テキスト', 'report': '不具合報告', 'live_watch': '🔴 ライブ監視', 'open_file': '📂 ファイルを開く', 'paste': '📋 貼り付け', 'load_server': '☁️ サーバーから読込', 'replay_mode': '🎬 リプレイモード', 'live_guide': '🌟 ライブガイド', 'looked_cards': '👁️ 確認済みカード', 'rule_log': '📜 ルールログ', 'logs': '📜 ログ', 'last_perf': '前回のパフォーマンス', 'god_mode': '🔧 デバッグモード', 'force': '強制実行', 'exec': '実行', 'wait': '待機', 'mulligan_you': 'マリガン (自分)', 'mulligan_opp': 'マリガン (相手)', 'active': '通常', 'energy': 'エナジー', 'draw': 'ドロー', 'main': 'メイン', 'live_set': 'ライブセット', 'perf_p1': 'パフォーマンス (P1)', 'perf_p2': 'パフォーマンス (P2)', 'live_result': 'ライブ結果', 'setup': 'セットアップ', 'act_ability': '能力発動', 'perform_live': 'ライブ開催' }, 'en': { 'turn': 'Turn', 'phase': 'Phase', 'score': 'Score', 'update': '🔄 Update', 'reset': 'RESET', 'deck_creator': '🛠 Deck Creator', 'set_deck': '🎴 Set Deck', 'report': 'Report Issue', 'live_watch': '🔴 Live Monitor', 'open_file': '📂 Open File', 'paste': '📋 Paste', 'load_server': '☁️ Load Server', 'replay_mode': '🎬 Replay Mode', 'live_guide': '🌟 Live Guide', 'looked_cards': '👁️ Looked Cards', 'rule_log': '📜 Rule Log', 'logs': '📜 Logs', 'last_perf': 'Last Performance', 'god_mode': '🔧 God Mode', 'force': 'Force Exec', 'exec': 'Run Code', 'wait': 'Wait', 'mulligan_you': 'Mulligan (You)', 'mulligan_opp': 'Mulligan (Opp)', 'active': 'Active', 'energy': 'Energy', 'draw': 'Draw', 'main': 'Main', 'live_set': 'Live Set', 'perf_p1': 'Performance (P1)', 'perf_p2': 'Performance (P2)', 'live_result': 'Live Result', 'setup': 'Setup', 'friendly_abilities': 'Friendly Abilities', 'act_ability': 'Activate Ability', 'perform_live': 'Perform Live' } }; function toggleLang() { currentLang = currentLang === 'jp' ? 'en' : 'jp'; updateLanguage(); } function toggleHotseat() { hotseatMode = !hotseatMode; fetchState(); } function toggleFriendlyAbilities() { showFriendlyAbilities = !showFriendlyAbilities; localStorage.setItem('lovelive_friendly_abilities', showFriendlyAbilities); updateLanguage(); render(); } window.setPerspective = function (idx) { perspectivePlayer = idx; document.getElementById('perspective-modal').style.display = 'none'; const btn = document.getElementById('switch-btn'); if (btn) btn.textContent = `View: P${perspectivePlayer + 1}`; // Refresh headers and state getHeaders(); render(); fetchState(); }; function togglePerspective() { perspectivePlayer = 1 - perspectivePlayer; render(); } function updateLanguage() { const t = translations[currentLang]; document.querySelectorAll('[data-i18n]').forEach(el => { const key = el.getAttribute('data-i18n'); if (t[key]) { if (key === 'live_watch') { let text = t[key]; if (isLiveWatchOn) { text = text.replace('🔴', '🟢').replace('OFF', 'ON'); } el.textContent = text; } else if (key === 'friendly_abilities') { let text = t[key]; text += showFriendlyAbilities ? ': ON' : ': OFF'; el.textContent = text; } else { el.textContent = t[key]; } } }); // Toggle Button Text const btn = document.getElementById('lang-btn'); if (btn) btn.textContent = currentLang === 'jp' ? 'English' : '日本語'; // Refresh render if state exists if (state) render(); } let state = null; let lastStateJson = null; // To avoid redundant renders let logs = []; let lastPerformanceData = null; // Store for re-viewing let selectedTurn = -1; // -1 means "All" let selectedHandIdx = -1; // -1 means no selection let showingFullLog = false; let lastPerformanceTurn = -1; // Track popup state let fullLogData = null; let lastActionsHash = null; // To avoid redundant action list wipes const feedItems = []; function log(msg, type = 'normal') { const timestamp = new Date().toLocaleTimeString(); logs.unshift({ timestamp, msg, type }); if (logs.length > 100) logs.pop(); // Also add to game feed if it's an interesting human action if (type === 'action' || type === 'score') { addToFeed(msg, type); } } function addToFeed(msg, type) { const icons = { 'action': '🎫', 'score': '✨', 'effect': '🪄', 'turn': '📅' }; feedItems.unshift({ msg, icon: icons[type] || '📝', timestamp: Date.now() }); if (feedItems.length > 20) feedItems.shift(); renderFeed(); } function renderFeed() { const feedEl = document.getElementById('game-feed'); if (!feedEl) return; feedEl.innerHTML = feedItems.map(item => `
${item.icon} ${item.msg}
`).join(''); feedEl.scrollTop = 0; } async function fetchState() { try { if (replayMode) return; // Stop polling while watching replay if (offlineMode) { if (!wasmAdapter) return; const res = await wasmAdapter.fetchState(); if (res.success) { // Check change const raw = JSON.stringify(res.state); if (raw === lastStateJson) return; lastStateJson = raw; state = res.state; render(); } return; } if (!roomCode) return; // Wait for room // Pause updates if Performance Modal is open const perfModal = document.getElementById('performance-modal'); if (perfModal && perfModal.style.display !== 'none') return; const headers = { 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; const res = await fetch('api/state?viewer=' + perspectivePlayer, { headers: headers }); if (res.status === 404) { // Room invalid or expired console.warn("Room not found (404). Resetting."); roomCode = null; state = null; localStorage.removeItem('lovelive_room_code'); document.getElementById('room-modal').style.display = 'flex'; console.log("DEBUG: Room 404 Reset"); updateRoomDisplay(); return; } const raw = await res.text(); if (raw === lastStateJson) return; // Skip if no change lastStateJson = raw; const data = JSON.parse(raw); if (data.success) { state = data.state; console.log("[DEBUG] State Mode:", state.mode); } else { console.error("State fetch unsuccessful:", data.error); return; } // Auto-sync perspective if authenticated if (state.my_player_id !== undefined && state.my_player_id !== -1 && !hotseatMode) { perspectivePlayer = state.my_player_id; } // Keep track of last performance for review if (state.performance_results && Object.keys(state.performance_results).length > 0) { lastPerformanceData = state.performance_results; } if (state.last_performance_results && Object.keys(state.last_performance_results).length > 0) { lastPerformanceData = state.last_performance_results; } render(); } catch (e) { console.error("Fetch Error:", e); } } let renderRequested = false; function render() { if (renderRequested) return; renderRequested = true; requestAnimationFrame(() => { renderInternal(); renderRequested = false; }); } function renderInternal() { if (!state || !state.players) return; // --- Proactive Pre-loading --- const assetsToLoad = []; state.players.forEach(p => { if (p.hand) p.hand.forEach(c => { if (c.img) assetsToLoad.push(fixImg(c.img)); }); if (p.stage) p.stage.forEach(c => { if (c && c.img) assetsToLoad.push(fixImg(c.img)); }); }); if (state.legal_actions) { state.legal_actions.forEach(a => { if (a.img) assetsToLoad.push(fixImg(a.img)); }); } // Check if assets actually changed to avoid redundant work const assetsHash = assetsToLoad.join('|'); if (window.lastAssetsHash !== assetsHash) { preloadAssets(assetsToLoad); window.lastAssetsHash = assetsHash; } // ---------------------------- if (hotseatMode && state.active_player !== undefined) { // In hotseat, view whoever's turn it is perspectivePlayer = state.active_player; } const p0 = state.players[perspectivePlayer] || state.players[0]; const p1 = state.players[1 - (state.players.indexOf(p0) === -1 ? 0 : state.players.indexOf(p0))] || state.players[1]; // Alias looked_cards for helper functions (renderSelectionModal, resolves) if (p0) state.looked_cards = p0.looked_cards || []; if (!p0 || !p1) return; // Final safety // Update Mode Buttons // Use Actual mode from server state if available, otherwise fallback to local hotseat toggle const isPvP = state.mode === "pvp" || hotseatMode; const pvpBtn = document.getElementById('pvp-btn'); if (pvpBtn) { pvpBtn.textContent = isPvP ? "PvP (vs Human)" : "Solo (vs AI)"; pvpBtn.style.background = isPvP ? "linear-gradient(135deg, #ec4899, #be185d)" : "linear-gradient(135deg, #2ecc71, #27ae60)"; } // Update Debug Info Header const debugInfo = document.getElementById('header-debug-info'); if (debugInfo) { let debugText = isPvP ? "PvP" : "PvE"; if (state.is_pvp) debugText += " (Network)"; else if (hotseatMode) debugText += " (Hotseat)"; // Show Perspective debugText += ` | View: P${perspectivePlayer + 1}`; debugInfo.textContent = debugText; // Color code if (isPvP) debugInfo.style.borderColor = "#ec4899"; else debugInfo.style.borderColor = "#2ecc71"; } const switchBtn = document.getElementById('switch-btn'); if (switchBtn) { switchBtn.style.display = hotseatMode ? 'inline-block' : 'none'; switchBtn.textContent = `View: P${perspectivePlayer + 1}`; } // Header info const t = translations[currentLang]; let phaseKey = 'wait'; if (state.phase === Phase.SETUP) phaseKey = 'setup'; if (state.phase === Phase.MULLIGAN_P1) phaseKey = (perspectivePlayer === 0) ? 'mulligan_you' : 'mulligan_opp'; if (state.phase === Phase.MULLIGAN_P2) phaseKey = (perspectivePlayer === 1) ? 'mulligan_you' : 'mulligan_opp'; if (state.phase === Phase.ACTIVE) phaseKey = 'active'; if (state.phase === Phase.ENERGY) phaseKey = 'energy'; if (state.phase === Phase.DRAW) phaseKey = 'draw'; if (state.phase === Phase.MAIN) phaseKey = 'main'; if (state.phase === Phase.LIVE_SET) phaseKey = 'live_set'; if (state.phase === Phase.PERFORMANCE_P1) phaseKey = (perspectivePlayer === 0) ? 'perf_p1' : 'perf_p2'; // perf_p1 text is "(P1)", perf_p2 is "(P2)" if (state.phase === Phase.PERFORMANCE_P2) phaseKey = (perspectivePlayer === 1) ? 'perf_p1' : 'perf_p2'; // Wait, language keys are 'perf_p1'='Performance (P1)'. // Improved Logic: // If language key is literal "Performance (P1)", then we want to start consistently using that or "Your Performance"? // The previous keys were 'perf_p1': 'Performance (P1)', 'perf_p2': 'Performance (P2)'. // If user wants generic "Your Performance", we might need new keys. // For now, let's stick to literal P1/P2 for performance to avoid ambiguity, // BUT fix Mulligan which says "(You)". if (state.phase === Phase.PERFORMANCE_P1) phaseKey = 'perf_p1'; if (state.phase === Phase.PERFORMANCE_P2) phaseKey = 'perf_p2'; if (state.phase === Phase.LIVE_RESULT) phaseKey = 'live_result'; // Update header stats const turnEl = document.getElementById('turn'); if (turnEl) { turnEl.textContent = state.turn_number || state.turn || 1; const turnLabel = turnEl.parentElement.querySelector('.stat-label'); if (turnLabel) { turnLabel.style.display = 'none'; // Remove the colon text node Array.from(turnEl.parentElement.childNodes).forEach(node => { if (node.nodeType === 3 && node.textContent.includes(':')) node.textContent = ''; }); } } const phaseEl = document.getElementById('phase'); if (phaseEl) { phaseEl.textContent = t[phaseKey] || state.phase; const phaseLabel = phaseEl.parentElement.querySelector('.stat-label'); if (phaseLabel) { phaseLabel.style.display = 'none'; Array.from(phaseEl.parentElement.childNodes).forEach(node => { if (node.nodeType === 3 && node.textContent.includes(':')) node.textContent = ''; }); } } const scoreEl = document.getElementById('score'); if (scoreEl) { scoreEl.textContent = `${state.players[0].score} - ${state.players[1].score}`; const scoreLabel = scoreEl.parentElement.querySelector('.stat-label'); if (scoreLabel) { scoreLabel.style.display = 'none'; Array.from(scoreEl.parentElement.childNodes).forEach(node => { if (node.nodeType === 3 && node.textContent.includes(':')) node.textContent = ''; }); } } // Header Energy & Hearts (Space Efficient) if (p0) { const infoBar = document.querySelector('.header .info-bar'); if (infoBar) { // Update Energy directly const current = p0.energy_untapped || 0; const total = p0.energy_count || 0; const energyEl = document.getElementById('header-energy'); if (energyEl) { energyEl.textContent = `${current}/${total}`; energyEl.parentElement.style.color = current > 0 ? 'var(--accent-gold)' : '#888'; // Hide label to save space const label = energyEl.parentElement.querySelector('.stat-label'); if (label) { label.style.display = 'none'; Array.from(energyEl.parentElement.childNodes).forEach(node => { if (node.nodeType === 3 && node.textContent.includes(':')) node.textContent = ''; }); } } // Update Hearts (Compact Bar) let totalHearts = document.getElementById('total-hearts-summary'); if (!totalHearts) { totalHearts = document.createElement('span'); totalHearts.id = 'total-hearts-summary'; totalHearts.className = 'stat hearts-stat'; totalHearts.title = "Total Hearts"; // Insert after energy const energyStat = document.querySelector('.stat[title="Energy"]'); if (energyStat) { energyStat.after(totalHearts); } else { infoBar.appendChild(totalHearts); } } if (p0.total_hearts) { // Python Order: Pink, Red, Yellow, Green, Blue, Purple, Any // Asset Order: heart_01 (Pink) ... heart_06 (Purple), icon_all (Any) let html = ''; p0.total_hearts.forEach((count, idx) => { const iconName = idx < 6 ? `heart_0${idx + 1}.png` : 'icon_all.png'; html += ` heart ${count} `; }); totalHearts.innerHTML = html; } // Update Yells (Compact Total) let totalYells = document.getElementById('total-yells-header'); if (!totalYells) { totalYells = document.createElement('span'); totalYells.id = 'total-yells-header'; totalYells.className = 'stat yells-stat'; totalYells.title = "Total Yells (Score potential)"; // Insert after hearts totalHearts.after(totalYells); } const yellCount = p0.total_blades || 0; totalYells.innerHTML = ` ${yellCount}`; } } // Agent Names const myAgentKey = perspectivePlayer === 0 ? 'p0_agent' : 'p1_agent'; const oppAgentKey = perspectivePlayer === 0 ? 'p1_agent' : 'p0_agent'; const myDefault = perspectivePlayer === 0 ? 'Player 1' : 'Player 2'; const oppDefault = perspectivePlayer === 0 ? 'Player 2' : 'Player 1'; document.getElementById('my-agent-name').textContent = state[myAgentKey] ? `(${state[myAgentKey]})` : `(${myDefault})`; document.getElementById('opp-agent-name').textContent = state[oppAgentKey] ? `(${state[oppAgentKey]})` : `(${oppDefault})`; // Opponent document.getElementById('opp-score').textContent = `${p1.score} ライブ`; document.getElementById('opp-deck').textContent = p1.deck_count; document.getElementById('opp-energy-deck').textContent = 12 - p1.energy_count; document.getElementById('opp-energy-count').textContent = p1.energy_count; document.getElementById('opp-hand-count').textContent = p1.hand_count; document.getElementById('opp-discard-count').textContent = p1.discard_count; renderEnergy('opp-energy', p1.energy); renderStage('opp-stage', p1.stage, false); renderCards('opp-hand', p1.hand, false, true); renderCards('opp-discard', p1.discard, false, true); renderCards('opp-success', p1.success_lives, false, true); // Player document.getElementById('my-score').textContent = `${p0.score} ライブ`; document.getElementById('my-deck').textContent = p0.deck_count; document.getElementById('my-energy-deck').textContent = 12 - p0.energy_count; document.getElementById('my-energy-count').textContent = `${p0.energy_untapped}/${p0.energy_count}`; document.getElementById('my-hand-count').textContent = p0.hand_count; document.getElementById('my-discard-count').textContent = p0.discard_count; renderEnergy('my-energy', p0.energy); renderStage('my-stage', p0.stage, true); // Render Hand // Mulligan selection OR standard selection let selectedIndices = []; if (state.phase === Phase.MULLIGAN_P1 || state.phase === Phase.MULLIGAN_P2) { // In mulligan phase, P0 might have selection selectedIndices = Array.from(p0.mulligan_selection || []); } else { if (selectedHandIdx !== -1) selectedIndices = [selectedHandIdx]; } // For live set, we also allow multiple selection visualization technically, but currently only one active choice // Actually, live set is one by one. renderCards('my-hand', p0.hand, true, false, selectedIndices); renderCards('my-discard', p0.discard); renderCards('my-success', p0.success_lives, true); // Made clickable renderLiveZone('my-live', p0.live_zone, p0.live_zone_revealed); renderPerformanceGuide(); renderLookedCards(); renderSelectionModal(); renderLogs(); renderActiveAbilities(p0); // Check for performance popup logic... const modal = document.getElementById('performance-modal'); const perfResults = state.performance_results || {}; // DEBUG: Log phase and results for persistent "not popping up" issue // console.log(`[Render] Phase: ${state.phase}, PerfResults: ${Object.keys(perfResults).length}`); // Prevent duplicate auto-shows using a simple content hash const currentPerfHash = JSON.stringify(perfResults); // Auto-show Performance Result (at start of next turn) // Check if we have results and if we haven't shown them for this turn yet if (state.turn > lastPerformanceTurn) { const resultsToShow = lastPerformanceData || perfResults; if (resultsToShow && Object.keys(resultsToShow).length > 0) { const hash = JSON.stringify(resultsToShow); if (window.lastShownPerformanceHash !== hash) { renderPerformanceResult(resultsToShow); modal.style.display = 'flex'; window.lastShownPerformanceHash = hash; lastPerformanceTurn = state.turn; } } } // No auto-hide needed really, user dismisses it. // Check for game over if (state.game_over) { const actionsDiv = document.getElementById('actions'); if (actionsDiv) { let winnerText = ''; if (state.winner === 0) winnerText = '🎉 P0 (あなた) Wins!'; else if (state.winner === 1) winnerText = '🎉 P1 (相手) Wins!'; else if (state.winner === -2) winnerText = '❌ Illegal Move (Error)'; else winnerText = '⚖️ Draw (引き分け)'; actionsDiv.innerHTML = `

${winnerText}

Game Over - Final Score: ${state.players[0].score} - ${state.players[1].score}

`; } } else { renderActions(); } // Highlight source card of pending choice highlightPendingSource(); } function renderLogs() { const ruleLogEl = document.getElementById('rule-log'); if (ruleLogEl) { let logData = state.rule_log || []; // Apply filtering if (selectedTurn !== -1) { const turnStr = `[Turn ${selectedTurn}]`; logData = logData.filter(entry => entry.includes(turnStr)); } ruleLogEl.innerHTML = ''; logData.forEach(entry => { const div = document.createElement('div'); div.className = 'log-entry'; let displayText = entry; let isAbility = false; // Detect and translate absolute ability logs: [TRIGGER:ID]CardName: Pseudocode // Regex to handle optional turn prefix: (?:\[Turn \d+\] )?\[TRIGGER:(\d+)\](.*?): (.*) const abilityMatch = entry.match(/(?:\[Turn \d+\] )?\[TRIGGER:(\d+)\](.*?): (.*)/); if (abilityMatch) { isAbility = true; const triggerId = parseInt(abilityMatch[1]); const cardName = abilityMatch[2].trim(); const pseudocode = abilityMatch[3].trim(); // Translate Trigger let triggerLabel = `[${triggerId}]`; if (window.Translations && currentLang && window.Translations[currentLang]) { const t = window.Translations[currentLang]; if (t.triggers && t.triggers[triggerId]) { triggerLabel = t.triggers[triggerId]; } } // Translate Effect Pseudocode let translatedEffect = pseudocode; const shouldTranslate = (currentLang === 'en' || showFriendlyAbilities); if (shouldTranslate && window.translateAbility) { // Prepend "EFFECT:" so translateAbility treats it as a pseudo-line translatedEffect = window.translateAbility("EFFECT: " + pseudocode, currentLang); // Remove the "→ " or "Effect: " prefix added by translator if we want a clean line translatedEffect = translatedEffect.replace(/^.*?: /, '').replace(/^→ /, ''); } else if (currentLang === 'jp' && !showFriendlyAbilities) { // If Japanese and Friendly OFF, try to find original text from state const srcCard = resolveCardDataByName(cardName); if (srcCard && srcCard.original_text) { translatedEffect = srcCard.original_text; } } // Translate Card Name if it's in our map (optional, usually card names are kept JP or from DB) let displayCardName = cardName; if (currentLang === 'en' && window.NAME_MAP && window.NAME_MAP[cardName]) { displayCardName = window.NAME_MAP[cardName]; } // Reconstruct (preserve Turn number if present) const turnMatch = entry.match(/^\[Turn \d+\]/); const turnPrefix = turnMatch ? turnMatch[0] + " " : ""; displayText = `${turnPrefix}${triggerLabel} ${displayCardName}: ${translatedEffect}`; } // Apply semantic classes for color-coding if (entry.includes('PLAYS')) div.classList.add('action'); else if (entry.includes('EFFECT') && !isAbility) div.classList.add('effect'); else if (entry.includes('SCORE')) div.classList.add('score'); else if (entry.includes('[Turn') && !isAbility) div.classList.add('turn'); else if (isAbility) div.classList.add('ability'); div.textContent = displayText; ruleLogEl.appendChild(div); }); if (!showingFullLog) ruleLogEl.scrollTop = ruleLogEl.scrollHeight; } // Legacy simple log for sidebar if exists const simpleLogEl = document.getElementById('log'); if (simpleLogEl) { simpleLogEl.innerHTML = logs.map(l => `
[${l.timestamp}] ${l.msg}
`).join(''); } } function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { log(`Copied ID: ${text}`); }).catch(err => { console.error('Failed to copy: ', err); }); if (event) event.stopPropagation(); } function renderActiveAbilities(player) { const listEl = document.getElementById('active-abilities-list'); const panelEl = document.getElementById('active-abilities-panel'); if (!listEl || !panelEl) return; const effects = player.active_effects || []; if (effects.length === 0) { panelEl.style.display = 'none'; return; } panelEl.style.display = 'block'; listEl.innerHTML = effects.map(eff => { const enrichedDesc = enrichAbilityText(eff.description); return `
[${eff.source}] Expires: ${eff.expiry}
${enrichedDesc}
`; }).join(''); } function enrichAbilityText(text) { if (!text) return ""; const iconMap = { '登場時': 'texticon/toujyou.png', '自動': 'texticon/jidou.png', '永続': 'texticon/jyouji.png', '起動': 'texticon/kidou.png', 'ターン1': 'texticon/turn1.png', 'ライブスタート': 'texticon/live_start.png', 'LIVE START': 'texticon/live_start.png', 'オール': 'texticon/icon_all.png', 'ブレード': 'texticon/icon_blade.png', 'エナジー': 'texticon/icon_energy.png' }; for (const [key, path] of Object.entries(iconMap)) { const regex = new RegExp(`\\[${key}\\]`, 'g'); let style = ""; if (path.includes('live_start') || path.includes('live_success')) { style = ' style="min-width: 3.5em;"'; } else if (path.includes('turn1')) { style = ' style="min-width: 2em;"'; } let src = `img/${path}`; if (typeof ICON_DATA_URIs !== 'undefined' && ICON_DATA_URIs[key]) { src = ICON_DATA_URIs[key]; } text = text.replace(regex, `${key}`); } text = text.replace(/{{(.*?)\|(.*?)}}/g, (match, img, alt) => { let src = "img/" + img; if (img.endsWith('.png') && !img.includes('/')) { src = "img/texticon/" + img; } let style = ""; if (img.includes('live_start') || img.includes('live_success')) { style = ' min-width: 3.5em;'; } const iconKey = img.replace('.png', ''); if (typeof ICON_DATA_URIs !== 'undefined' && ICON_DATA_URIs[iconKey]) { src = ICON_DATA_URIs[iconKey]; } return `${alt}${alt}`; }); text = text.replace(/\\n/g, '
'); return text; } function renderSelectionModal() { const modal = document.getElementById('selection-modal'); const choice = state.pending_choice; // Should we show selection modal? // Types that involve picking from a list of cards const selectionTypes = ["SELECT_FROM_LIST", "SELECT_FROM_DISCARD", "SELECT_SUCCESS_LIVE", "SELECT_SWAP_SOURCE", "SELECT_FORMATION_SLOT", "ORDER_DECK"]; const isSelectionChoice = choice && selectionTypes.includes(choice.type); const hasLookedCards = state.looked_cards && state.looked_cards.length > 0; if (!isSelectionChoice && !hasLookedCards) { modal.style.display = 'none'; return; } // If it's a selection choice, but for the AI, don't show it? // Actually, we should show it if we are WATCHING, but normally solo means user is P0. if (choice && choice.params && choice.params.player_id !== 0 && !hasLookedCards) { modal.style.display = 'none'; return; } modal.style.display = 'flex'; const titleEl = document.getElementById('selection-title'); const descEl = document.getElementById('selection-description'); const contentEl = document.getElementById('selection-content'); const footerEl = document.getElementById('selection-footer'); if (isSelectionChoice) { titleEl.textContent = choice.source_member ? `${choice.source_member} の効果` : "カード選択"; descEl.textContent = choice.description || "対象のカードを選択してください。"; if (choice.type === "ORDER_DECK") { // ORDER_DECK is now iterative in the backend. // We use the general selection logic below, but we'll add a 'Done' button if legal. // (The general logic handles IDs 600-659, which is where ORDER_DECK selection actions live) } // Find legal actions in that range let actionRange = [600, 659]; if (choice.type === "SELECT_FROM_DISCARD") actionRange = [660, 719]; if (choice.type === "SELECT_FORMATION_SLOT") actionRange = [720, 759]; if (choice.type === "SELECT_SUCCESS_LIVE") actionRange = [760, 819]; if (choice.type === "TARGET_LIVE") actionRange = [820, 829]; if (choice.type === "TARGET_ENERGY") actionRange = [830, 849]; if (choice.type === "TARGET_REMOVED") actionRange = [850, 909]; if (choice.type === "ORDER_DECK") actionRange = [600, 659]; const legalOptions = state.legal_actions.filter(a => a.id >= actionRange[0] && a.id <= actionRange[1]); const canPass = state.legal_actions.some(a => a.id === 0); // Auto-select if only one option and forced (cannot pass) // This makes forced discards/selections "automatic" if (legalOptions.length === 1 && !canPass) { console.log("Auto-selecting single forced option:", legalOptions[0].id); // Use setTimeout to allow render to finish or at least not block setTimeout(() => doAction(legalOptions[0].id), 10); modal.style.display = 'none'; // Hide modal immediately return; } let html = ''; const params = choice.params || {}; const cards = params.cards || params.available_members || []; cards.forEach((cId, idx) => { const absId = actionRange[0] + idx; const action = state.legal_actions.find(a => a.id === absId); const isLegal = !!action; // Use enriched data from action if available, otherwise resolveCardData let card = resolveCardData(cId); if (action && action.name) { card = { ...card, name: action.name, img: action.img || card.img }; } const isLive = card.type === 'live'; const tooltip = getEffectiveAbilityText(card); html += `
${card.name}
`; }); contentEl.innerHTML = html; // Footer (Pass button OR Done button) const doneAction = state.legal_actions.find(a => a.id === actionRange[0] + cards.length); if (choice.type === "ORDER_DECK") { // Relabel Skip to "Discard Rest" and hide redundant Done button footerEl.innerHTML = ``; } else if (doneAction) { footerEl.innerHTML = ``; } else if (canPass) { footerEl.innerHTML = ``; } else { footerEl.innerHTML = ''; } } else if (hasLookedCards) { const currentLookedHash = JSON.stringify(state.looked_cards.map(c => c.id)); if (window.dismissedLookedCardsHash === currentLookedHash) { if (modal.style.display === 'flex') modal.style.display = 'none'; return; } titleEl.textContent = "確認したカード"; descEl.textContent = "現在公開されているカードです。"; let html = ''; state.looked_cards.forEach(card => { const isLive = card.type === 'live'; const tooltip = getEffectiveAbilityText(card); html += `
${card.name}
`; }); contentEl.innerHTML = html; // Store hash in a data attribute or global for the onclick handler window.currentLookedCardsHashToDismiss = currentLookedHash; footerEl.innerHTML = ``; } // Highlight source card in the board if applicable highlightPendingSource(); } // Helper to resolve card info from cardName function resolveCardDataByName(name) { if (!state) return null; for (const p of state.players) { if (!p) continue; const allZones = [(p.hand || []), (p.stage || []), (p.live_zone || []), (p.energy || []), (p.discard || []), (p.success_zone || [])]; for (const zone of allZones) { for (const c of zone) { const card = (typeof c === 'object' && c !== null) ? (c.card || c) : null; if (card && card.name === name) return card; } } } if (state.looked_cards) { const found = state.looked_cards.find(c => c.name === name); if (found) return found; } return null; } // Helper to resolve card info from state caches if possible function resolveCardData(cid) { if (cid === null || cid === undefined || cid < 0) return null; // First try to look in the looked_cards if it's there if (state && state.looked_cards) { const found = state.looked_cards.find(c => c.id === cid); if (found) return found; } // Fallback to basic (we might not have full info if it's just an ID) return { id: cid, name: `Card ${cid}`, img: 'icon_blade.png', text: "", original_text: "" }; } function renderActions() { const actionsDiv = document.getElementById('actions'); if (!actionsDiv || !state) return; // Check if relevant action state changed to avoid redundant wipes const actionsHash = JSON.stringify({ actions: state.legal_actions, active: state.active_player, phase: state.phase, choice: state.pending_choice, perspective: perspectivePlayer, lang: currentLang, friendly: showFriendlyAbilities }); if (actionsHash === lastActionsHash) { return; // No change, skip wipe to preserve hover/tooltips } lastActionsHash = actionsHash; actionsDiv.innerHTML = ''; const mobileActionBar = document.getElementById('mobile-action-bar'); if (mobileActionBar) mobileActionBar.innerHTML = ''; // Check if it's our turn const isOurTurn = (state.active_player === perspectivePlayer); if (!isOurTurn && !hotseatMode) { const turnBanner = document.createElement('div'); turnBanner.className = 'turn-banner waiting'; turnBanner.innerHTML = ` OPPONENT'S TURN (P${state.active_player + 1})`; turnBanner.style.background = 'rgba(239, 83, 80, 0.15)'; turnBanner.style.border = '1px solid #ef5350'; turnBanner.style.color = '#ef5350'; turnBanner.style.padding = '10px'; turnBanner.style.marginBottom = '10px'; turnBanner.style.textAlign = 'center'; turnBanner.style.borderRadius = '6px'; turnBanner.style.fontWeight = 'bold'; actionsDiv.appendChild(turnBanner); // Selection safety: clear selection if it's not our turn selectedHandIdx = -1; return; // Hiding Opponent's Actions } // 0. Mulligan Phase Indicator if (state.phase === Phase.MULLIGAN_P1 || state.phase === Phase.MULLIGAN_P2) { const isP1 = state.phase === Phase.MULLIGAN_P1; const phaseName = currentLang === 'en' ? `Mulligan Phase (${isP1 ? 'P1' : 'P2'})` : `マリガンフェーズ (${isP1 ? 'P1' : 'P2'})`; const helpText = currentLang === 'en' ? "Tap cards in your hand to select for swapping, then press 'DONE'." : "交換したいカードをタップして選択してください。
「完了」を押すと確定します。"; const mulliganDiv = document.createElement('div'); mulliganDiv.className = 'mulligan-indicator'; mulliganDiv.innerHTML = `

${phaseName}

${helpText}

`; actionsDiv.appendChild(mulliganDiv); } // 0.1 Pending Choice Indicator // Suppress if in Main phase and the choice is likely a board-driven selection (1000-1999 range) const isSpecialSelect = state.pending_choice && (state.pending_choice.type === 'SELECT_FROM_LIST' || state.pending_choice.type === 'SELECT_MODE'); if (state.pending_choice && !(state.phase === Phase.MAIN && isSpecialSelect)) { const choiceDiv = document.createElement('div'); choiceDiv.className = 'pending-choice-indicator'; choiceDiv.style.padding = '10px'; choiceDiv.style.marginBottom = '15px'; choiceDiv.style.background = 'rgba(255, 215, 0, 0.08)'; choiceDiv.style.border = '1px solid var(--accent-gold)'; choiceDiv.style.borderRadius = '8px'; const desc = state.pending_choice.description || '選択してください'; const member = state.pending_choice.source_member || 'Unknown Source'; const ability = state.pending_choice.source_ability ? `[${state.pending_choice.source_ability}]` : ''; let stepInfo = ''; if (state.pending_choice.params && state.pending_choice.params.step_progress) { const steps = state.pending_choice.params.step_progress; if (steps !== '?') { let label = (steps === 'Cost') ? 'Paying Cost' : `Step ${steps}`; stepInfo = `(${label})`; } } const imgPath = state.pending_choice.source_img ? fixImg(state.pending_choice.source_img) : null; const imgHtml = imgPath ? `` : ''; choiceDiv.onmouseenter = () => highlightPendingSource(); choiceDiv.onmouseleave = () => clearHighlights(); choiceDiv.innerHTML = `
${imgHtml}
${member} ${ability} ${stepInfo}
${desc}
`; actionsDiv.appendChild(choiceDiv); } if (!state.legal_actions || state.legal_actions.length === 0) { // Diagnostic data for debugging missing actions const diag = { phase: state.phase, phase_name: Phase[state.phase] || 'Unknown', turn: state.turn || state.turn_number, active: state.active_player }; console.warn('[UI] Empty actions:', diag); if (state.phase === Phase.LIVE_SET) { console.error('[DIAG] Stuck in LIVE_SET with no actions. Perspective:', perspectivePlayer, 'Active:', state.active_player); } actionsDiv.innerHTML += `
⚠️ No actions available
`; return; } if (state.phase === Phase.LIVE_SET) { console.log('[DIAG] LIVE_SET Phase. Legal actions:', state.legal_actions); } // 1. Render Action List Container const listDiv = document.createElement('div'); listDiv.className = 'action-list'; actionsDiv.appendChild(listDiv); const myStage = (state.players && state.players[perspectivePlayer]) ? state.players[perspectivePlayer].stage : null; // 0. Pin "Pass" / "Confirm" Action (ID 0) to TOP const passAction = state.legal_actions.find(a => a.id === 0); if (passAction) { const btn = document.createElement('button'); btn.className = 'action-btn pass'; // Always pass style for top button if (state.phase === Phase.MULLIGAN_P1 || state.phase === Phase.MULLIGAN_P2) { btn.classList.add('confirm'); btn.innerHTML = `${currentLang === 'en' ? 'DONE (Mulligan)' : 'マリガン完了'}`; } else if (state.phase === Phase.LIVE_RESULT) { btn.classList.add('confirm'); btn.innerHTML = `${currentLang === 'en' ? 'CONFIRM' : '確認して次へ'}`; } else if (state.phase === Phase.LIVE_SET) { btn.classList.add('confirm'); btn.innerHTML = `${currentLang === 'en' ? 'CONFIRM LIVE SET' : 'ライブセット完了'}`; } else if (state.pending_choice) { btn.innerHTML = `${currentLang === 'en' ? 'SKIP OPTIONAL' : '能力を使用しない (Skip)'}`; } else { btn.innerHTML = `${currentLang === 'en' ? 'END PHASE' : 'フェイズ終了'}`; } btn.style.marginBottom = '10px'; btn.style.justifyContent = 'center'; btn.onclick = () => doAction(0); btn.onmouseenter = () => { clearHighlights(); hideTooltip(); }; btn.onmouseleave = () => clearHighlights(); listDiv.appendChild(btn); // Mirror to mobile action bar if (mobileActionBar && window.innerWidth <= 768) { const mBtn = btn.cloneNode(true); mBtn.onclick = btn.onclick; // cloneNode doesn't copy listeners mobileActionBar.appendChild(mBtn); } } // Group actions: Key = "type-handIdx-name" or similar, Value = [actions] const groups = {}; const abilityActions = []; const otherActions = []; state.legal_actions.forEach(action => { if (action.id === 0) return; // Already handled if (action.type === 'ABILITY') { abilityActions.push(action); } else if (action.type === 'PLAY') { // Group PLAY actions by the card they are playing (hand_idx) const key = `PLAY-${action.hand_idx}`; if (!groups[key]) groups[key] = { type: 'PLAY', actions: [], main: action }; groups[key].actions.push(action); } else if (action.type === 'SELECT_STAGE' && state.phase === Phase.RESPONSE) { // Group SELECT_STAGE actions by the card they are placing (source_card_id) const key = `SELECT_STAGE-${action.source_card_id || 'unknown'}`; if (!groups[key]) groups[key] = { type: 'SELECT_STAGE', actions: [], main: action }; groups[key].actions.push(action); } else { otherActions.push(action); } }); // 1. Render Ability Actions (Below Pass, Above Play) abilityActions.forEach(action => { const btn = document.createElement('button'); btn.className = 'action-btn'; // Premium "Golden Action" styling for activated abilities if (action.location === 'discard' || (action.id >= 200 && action.id < 300) || (action.id >= 2000 && action.id < 3000)) { btn.classList.add('golden'); } btn.style.marginBottom = '4px'; btn.style.padding = '6px'; btn.style.textAlign = 'left'; let imgHtml = ''; if (action.img) { imgHtml = ``; } const abilityTagsHtml = getActionTags(action); const translatedText = getEffectiveActionText(action); const lines = translatedText.split('\n'); // Extract the effect part from translated text const translatedEffect = (lines.length > 1 ? lines.slice(lines[0].includes('【') || lines[0].includes('[') ? 1 : 0).join('
') : lines[0] || ''); // Prioritize translated text if in friendly/EN mode, otherwise fallback to backend 'description' const isFriendly = currentLang === 'en' || showFriendlyAbilities; let displayBody = (isFriendly && translatedEffect) ? translatedEffect : (action.description || translatedEffect || 'Ability'); btn.innerHTML = ` ${imgHtml}
${action.name}
${displayBody}
${abilityTagsHtml}
`; btn.setAttribute('data-text', translatedText || action.text || action.description || ""); btn.setAttribute('data-slot-idx', action.area_idx); btn.onmouseenter = () => highlightAction(action); btn.onmouseleave = () => clearHighlights(); btn.onclick = () => doAction(action.id); listDiv.appendChild(btn); // Mirror to mobile action bar if (mobileActionBar && window.innerWidth <= 768) { const mBtn = btn.cloneNode(true); mBtn.onclick = btn.onclick; mBtn.onmouseenter = btn.onmouseenter; mBtn.onmouseleave = btn.onmouseleave; mobileActionBar.appendChild(mBtn); } }); // 2. Render Grouped Actions (PLAY / SELECT_STAGE) Object.values(groups).forEach(group => { const btn = document.createElement('div'); btn.className = 'action-group'; btn.style.background = 'rgba(255, 255, 255, 0.05)'; btn.style.border = '1px solid var(--border)'; btn.style.borderRadius = '6px'; btn.style.padding = '5px'; btn.style.marginBottom = '6px'; const mainAction = group.main; const tooltipText = getEffectiveActionText(mainAction); btn.setAttribute('data-text', tooltipText); btn.onmouseenter = () => highlightAction(mainAction); btn.onmouseleave = () => clearHighlights(); let displayImg = mainAction.img || "icon_blade.png"; let titleText = mainAction.name || "Action Group"; let subTitle = "登場させる先を選択"; if (group.type === 'SELECT_STAGE') { titleText = mainAction.source_name || mainAction.name || "メンバーの登場先選択"; displayImg = mainAction.source_img || mainAction.img || "icon_blade.png"; subTitle = "に置く場所を選択"; } // Clean up title text (strip technical prefixes) titleText = titleText.replace(/TRIGGER:\s*/g, ''); const abilityTagsHtml = getActionTags(mainAction, true); const displayBase = mainAction.base_cost !== undefined ? mainAction.base_cost : mainAction.cost; const baseCostHtml = displayBase !== undefined ? `${displayBase}` : ''; let content = `
${titleText}${abilityTagsHtml}${baseCostHtml}
${subTitle}
`; content += `
`; for (let i = 0; i < 3; i++) { const subAct = group.actions.find(a => a.area_idx === i); if (subAct) { let displayCost = ""; let extraInfo = ""; if (group.type === 'PLAY') { const finalCost = typeof subAct.cost === 'number' ? subAct.cost : 0; if (myStage && myStage[i] && myStage[i].id !== -1) { const stageCard = myStage[i]; displayCost = finalCost === 0 ? `0` : `-${finalCost}`; if (finalCost > 0) { displayCost = `${displayCost}`; extraInfo = `
BATON ▲
`; } else { const handBase = mainAction.base_cost !== undefined ? mainAction.base_cost : (mainAction.cost || 0); const targetCost = stageCard.cost || 0; if (handBase < targetCost) { displayCost = `${displayCost}`; extraInfo = `
BATON ▼
`; } else { displayCost = `${displayCost}`; extraInfo = `
BATON =
`; } } } else { displayCost = finalCost === 0 ? `0` : `-${finalCost}`; extraInfo = `
PLACE
`; if (finalCost > 0) { displayCost = `${displayCost}`; } else { displayCost = `${displayCost}`; } } } else if (group.type === 'SELECT_STAGE') { displayCost = `[${["左", "中", "右"][i]}]`; } const subTooltip = getEffectiveActionText(subAct); content += ` `; } else { content += `
`; } } content += `
`; btn.innerHTML = content; listDiv.appendChild(btn); // Mirror to mobile action bar if (mobileActionBar && window.innerWidth <= 768) { const mBtn = document.createElement('div'); mBtn.className = 'mobile-action-group-container'; mBtn.style.display = 'flex'; mBtn.style.gap = '4px'; // For grouped actions, we want to mirror the sub-actions as individual buttons on mobile // or at least make them accessible. Mirroring the whole group might be too bulky. // Let's mirror the individual sub-buttons if they exist. const subButtons = btn.querySelectorAll('.sub-action'); subButtons.forEach(sb => { const clonedSb = sb.cloneNode(true); clonedSb.onclick = (e) => { e.stopPropagation(); const actionIdAttr = sb.getAttribute('onclick').match(/doAction\((\d+)\)/); if (actionIdAttr) doAction(parseInt(actionIdAttr[1])); }; // Copy labels/costs for mobile context if needed, but clonedSb should have them mBtn.appendChild(clonedSb); }); if (mBtn.children.length > 0) { mobileActionBar.appendChild(mBtn); } } }); // 2. Render Other Actions (Standard) - BUT filtering out Action 0 (Pass) to pin it const nonPassActions = otherActions.filter(a => a.id !== 0); // MULLIGAN SPECIAL: If in mulligan, we want to show actions for cards even if they are already selected // (if they aren't in legal_actions anymore) if (state.phase === Phase.MULLIGAN_P1 || state.phase === Phase.MULLIGAN_P2) { const p0 = state.players[perspectivePlayer]; const selectedMulliganIndices = p0.mulligan_selection || []; // Show all hand cards as potential mulligan actions if (p0.hand) { p0.hand.forEach((card, idx) => { const actionId = 300 + idx; const isSelected = selectedMulliganIndices.includes(idx); const actionInLegal = state.legal_actions.find(a => a.id === actionId); // If it's already selected OR in legal actions, we show it if (isSelected || actionInLegal) { const btn = document.createElement('button'); btn.className = 'action-btn'; if (isSelected) { btn.style.opacity = '0.8'; // btn.style.border = '2px solid var(--accent-pink)'; } const cardName = card.name || `Card ${idx}`; // Toggle Text const actionText = isSelected ? `Return: ${cardName}` : `Mulligan: ${cardName}`; const icon = isSelected ? '↩️ ' : ''; btn.innerHTML = `${icon}${actionText}`; // FIX: Ensure Mulligan buttons use standardized tooltip logic if (card) { btn.setAttribute('data-text', getEffectiveAbilityText(card)); } btn.onclick = () => doAction(actionId); btn.onmouseenter = () => highlightAction(actionInLegal || { id: actionId, type: 'MULLIGAN', hand_idx: idx }); btn.onmouseleave = () => clearHighlights(); listDiv.appendChild(btn); } }); } } else { nonPassActions.forEach(action => { const btn = document.createElement('button'); btn.className = 'action-btn'; // Content construction let content = ''; // Add source image if available (Ability/Play) if (action.img) { content += ``; } content += `
`; if (action.type === 'COLOR_SELECT') { const colors = { 'Pink': '#ff80ab', 'Blue': '#42a5f5', 'Green': '#66bb6a', 'Yellow': '#fdd835', 'Red': '#ef5350', 'Purple': '#ab47bc', 'All': 'linear-gradient(45deg, #ff80ab, #42a5f5, #66bb6a, #fdd835, #ef5350, #ab47bc)', 'None': '#757575' }; const bg = colors[action.color] || '#555'; btn.style.background = bg; // Text color contrast btn.style.color = (['Yellow', 'Pink', 'All'].includes(action.color)) ? '#333' : '#fff'; btn.style.fontWeight = 'bold'; btn.style.textAlign = 'center'; btn.innerHTML = `${action.name}`; } else if (action.type === 'SELECT_MODE') { const displayTitle = action.description || action.name; btn.style.borderLeft = '4px solid var(--accent-gold)'; content += `${displayTitle}`; const tooltipText = getEffectiveActionText(action); btn.setAttribute('data-text', tooltipText); } else if (action.type === 'ABILITY' && action.name) { let actionTitle = action.name; if (actionTitle.startsWith('【能力】')) { content += `${getEffectiveActionText(action)}`; } else { content += `Ability: ${getEffectiveActionText(action)}`; } const tooltipText = getEffectiveActionText(action); btn.setAttribute('data-text', tooltipText); } else if (action.type === 'PLAY' && action.name) { content += `Play: ${getEffectiveActionText(action)}`; const tooltipText = getEffectiveActionText(action); btn.setAttribute('data-text', tooltipText); } else if ((action.type === 'SELECT' || action.type === 'SELECT_HAND' || action.type === 'SELECT_STAGE' || action.type === 'SELECT_DISCARD' || action.type === 'TARGET_OPPONENT' || action.type === 'SELECT_LIVE') && action.name) { // Actions enriched with card/slot metadata let actionPrefix = ""; if (action.type === 'SELECT') actionPrefix = "Top: "; if (action.type === 'SELECT_HAND') actionPrefix = "Hand: "; if (action.type === 'SELECT_DISCARD') actionPrefix = "Discard: "; if (action.type === 'SELECT_STAGE') actionPrefix = "Stage: "; if (action.type === 'TARGET_OPPONENT') actionPrefix = "Target: "; if (action.type === 'SELECT_LIVE') actionPrefix = "Performance: "; content += `${actionPrefix}${getEffectiveActionText(action)}`; const tooltipText = getEffectiveActionText(action); btn.setAttribute('data-text', tooltipText); if (action.img) { // Update content to include image if not already added by general logic if (!content.includes('` + content; } } } else { const displayTitle = action.description || action.desc || action.name || 'Action'; content += `${displayTitle}`; btn.setAttribute('data-text', displayTitle); } content += `
`; btn.innerHTML = content; btn.onclick = () => doAction(action.id); // Source Highlighting logic btn.onmouseenter = () => highlightAction(action); btn.onmouseleave = () => clearHighlights(); listDiv.appendChild(btn); }); } } function highlightStageCard(areaIdx) { const myStage = document.getElementById('my-stage'); if (!myStage) return; // The stage has 3 slots, standard naming logic matches areaIdx usually 0-2 const slot = myStage.children[areaIdx]; if (slot) { // Find inner member-slot or apply to wrapper const memberSlot = slot.querySelector('.member-slot') || slot; memberSlot.classList.add('highlight-source'); } } function clearHighlights() { document.querySelectorAll('.highlight-source').forEach(el => el.classList.remove('highlight-source')); document.querySelectorAll('.highlight-target').forEach(el => el.classList.remove('highlight-target')); // hideTooltip() removed from here to prevent flickering during highlightAction transitions. // Tooltips are managed via global mouseover/mouseout listeners. } async function toggleFullLog() { showingFullLog = !showingFullLog; if (showingFullLog) { try { const btn = document.getElementById('full-log-btn'); if (btn) btn.textContent = 'Loading...'; const res = await fetch('api/full_log'); const data = await res.json(); fullLogData = data.log; render(); } catch (e) { console.error("Failed to fetch full log", e); showingFullLog = false; render(); } } else { render(); } } function playCard(idx) { // Check if this card can be toggled for Mulligan by looking at legal_actions // IMPORTANT: Backend uses 301-360 for Mulligan (300 + index + 1) const mulliganActionId = 301 + idx; const isMulliganAction = state.legal_actions && state.legal_actions.find(a => a.id === mulliganActionId); if (isMulliganAction) { // We're in Mulligan phase and this is a valid toggle action doAction(mulliganActionId); return; } // Standard Phase: Select card for later placement if (state.phase === Phase.LIVE_SET) { // If we have a valid action for setting this card as a live card const liveSetActionId = 400 + idx; const isLiveSetAction = state.legal_actions && state.legal_actions.find(a => a.id === liveSetActionId); if (isLiveSetAction) { doAction(liveSetActionId); return; } } if (selectedHandIdx === idx) { selectedHandIdx = -1; // Deselect } else { selectedHandIdx = idx; // Select } render(); // Re-render to show selection } function onStageSlotClick(areaIdx) { console.log('[DEBUG] Stage clicked:', areaIdx, 'selectedHandIdx:', selectedHandIdx); // Check for TARGET_MEMBER / MEMBER_SELECT (Action 560-562) const selectActionId = 560 + areaIdx; if (state.legal_actions && state.legal_actions.find(a => a.id === selectActionId)) { doAction(selectActionId); return; } if (selectedHandIdx === -1) { // If clicking an existing member, maybe use ability? (Actions 200-202) const actionId = 200 + areaIdx; const action = state.legal_actions.find(a => a.id === actionId); if (action) { doAction(actionId); } else { console.log(`No ability available for slot ${areaIdx}`); } return; } // Try to play selected card to this area const actionId = 1 + (selectedHandIdx * 3) + areaIdx; const action = state.legal_actions.find(a => a.id === actionId); if (action) { doAction(actionId); selectedHandIdx = -1; } } function onLiveSlotClick(idx) { console.log('[DEBUG] Live slot clicked:', idx); // Check for Performance (900-902) const perfActionId = 900 + idx; if (state.legal_actions && state.legal_actions.find(a => a.id === perfActionId)) { doAction(perfActionId); return; } // Check for TARGET_LIVE (820-822) const liveSelectId = 820 + idx; if (state.legal_actions && state.legal_actions.find(a => a.id === liveSelectId)) { doAction(liveSelectId); return; } } function onEnergySlotClick(idx) { console.log('[DEBUG] Energy clicked:', idx); const actionId = 830 + idx; // TARGET_ENERGY_ZONE if (state.legal_actions && state.legal_actions.find(a => a.id === actionId)) { doAction(actionId); } } function onSuccessSlotClick(idx) { console.log('[DEBUG] Success slot clicked:', idx); const actionId = 760 + idx; // TARGET_SUCCESS_LIVES if (state.legal_actions && state.legal_actions.find(a => a.id === actionId)) { doAction(actionId); } } function renderCards(containerId, cards, clickable = false, mini = false, selectedIndices = []) { const el = document.getElementById(containerId); if (!el) return; el.innerHTML = ''; if (!cards) return; // Null safety cards.forEach((card, idx) => { const div = document.createElement('div'); const isSelected = selectedIndices.includes(idx); // Logic for highlighting: Pink for mulligan, Gold for standard selection let highlightClass = ''; if (isSelected) { highlightClass = (state.phase === Phase.MULLIGAN_P1 || state.phase === Phase.MULLIGAN_P2) ? ' mulligan-selected' : ' selected'; } if (card.is_new) { highlightClass += ' new-card'; } div.className = 'card' + (card.hidden ? ' hidden' : '') + (card.type === 'live' ? ' type-live' : '') + (mini ? ' card-mini' : '') + highlightClass; div.id = `${containerId}-card-${idx}`; // Hand card lock logic const isMulligan = (state.phase === Phase.MULLIGAN_P1 || state.phase === Phase.MULLIGAN_P2); if (containerId === 'my-hand' && card.type === 'member' && !isMulligan) { if (state.phase !== 5 && card.valid_actions) { const playActions = card.valid_actions.filter(aid => aid >= 1 && aid <= 180); if (playActions.length === 0) { div.classList.add('card-locked'); } else { const emptySlots = []; const myStage = (state.players && state.players[perspectivePlayer]) ? state.players[perspectivePlayer].stage : null; if (myStage) { for (let s = 0; s < 3; s++) { if (myStage[s] === -1) emptySlots.push(s); } } const canPlayToEmpty = playActions.some(aid => { const areaIdx = (aid - 1) % 3; return emptySlots.includes(areaIdx); }); if (canPlayToEmpty) div.classList.add('card-playable'); else div.classList.add('card-baton-playable'); } } } if (containerId === 'my-hand') div.setAttribute('draggable', 'true'); const isLiveSet = state.phase === Phase.LIVE_SET; const tooltip = isLiveSet ? getEffectiveAbilityText(card) : getEffectiveAbilityText(card); // During Live Set, we want the tooltip to be very prominent if it's a Live card if (tooltip) div.setAttribute('data-text', tooltip); if (!card.hidden) { let imgPath = card.img || card.img_path || ''; const imgHtml = imgPath ? `` : ''; let heartPipsHtml = ''; if (card.type === 'member' && card.hearts) { const colorNames = ['Red', 'Blue', 'Green', 'Yellow', 'Purple', 'Pink']; let pips = ''; for (let c = 0; c < 6; c++) { for (let h = 0; h < (card.hearts[c] || 0); h++) { pips += `
`; } } if (pips) heartPipsHtml = `
${pips}
`; } if (card.type === 'live' && card.required_hearts) { const colorNames = ['Red', 'Blue', 'Green', 'Yellow', 'Purple', 'Pink', 'Any']; let pips = ''; const filled = card.filled_hearts || [0, 0, 0, 0, 0, 0, 0]; const req = card.required_hearts || [0, 0, 0, 0, 0, 0, 0]; let totalFilled = 0; let totalReq = 0; for (let c = 0; c < 7; c++) { const r = req[c] || 0; const f = filled[c] || 0; totalReq += r; for (let i = 0; i < r; i++) { const isFilled = i < f; const colorClass = c === 6 ? 'color-any' : `color-${c}`; const fillClass = isFilled ? 'filled' : 'empty'; pips += `
`; } totalFilled += Math.min(f, r); } if (pips) { const progressText = `
${totalFilled}/${totalReq}
`; heartPipsHtml = `
${progressText}
${pips}
`; } } let bladeHeartsHtml = ''; if (card.type === 'member' && card.blade_hearts) { let pips = ''; for (let c = 0; c < 6; c++) { for (let h = 0; h < (card.blade_hearts[c] || 0); h++) { pips += `
`; } } if (pips) bladeHeartsHtml = `
${pips}
`; } let modifiersHtml = ''; if (card.modifiers && card.modifiers.length > 0) { let modLines = ''; card.modifiers.forEach(mod => { let expiryIcon = mod.expiry === 'TURN_END' ? '⏳' : (mod.expiry === 'CONSTANT' ? '♾️' : (mod.expiry === 'LIVE_END' ? '🏁' : '⏲️')); modLines += `
${expiryIcon} ${mod.description}
`; }); modifiersHtml = `
${modLines}
`; } const displayId = card.card_no || card.id; const idHtml = `
ID:${displayId}
`; div.innerHTML = `${imgHtml}${card.cost !== undefined ? card.cost : '★'} ${bladeHeartsHtml}${heartPipsHtml}
${card.name || ''}
${modifiersHtml}${idHtml}`; } else { div.innerHTML = ``; } if (clickable) { div.style.cursor = 'pointer'; div.onclick = () => { if (containerId === 'my-success') onSuccessSlotClick(idx); else playCard(idx); }; } el.appendChild(div); }); } function renderStage(containerId, stage, clickable) { const el = document.getElementById(containerId); if (!el) return; el.innerHTML = ''; const labels = ['左', 'C', '右']; for (let i = 0; i < 3; i++) { const slot = stage[i]; const area = document.createElement('div'); area.className = 'member-area board-slot-container'; // Check for Opponent Target Actions (600-602) let isOppTarget = false; let oppActionId = -1; if (containerId === 'opp-stage') { oppActionId = 600 + i; if (state && state.legal_actions) { isOppTarget = state.legal_actions.some(a => a.id === oppActionId); } } // Check for Activated Ability (200-202) let abilityAction = null; if (containerId === 'my-stage' && state.legal_actions) { abilityAction = state.legal_actions.find(a => a.id === (200 + i)); } if (clickable) { area.style.cursor = 'pointer'; area.onclick = () => onStageSlotClick(i); } else if (isOppTarget) { area.style.cursor = 'pointer'; area.onclick = () => doAction(oppActionId); area.classList.add('highlight-target'); } const slotDiv = document.createElement('div'); slotDiv.className = 'member-slot' + (slot ? ' filled' : '') + (slot?.tapped ? ' tapped' : ''); slotDiv.id = `${containerId}-slot-${i}`; if (clickable && selectedHandIdx !== -1) { const actionId = 1 + (selectedHandIdx * 3) + i; const isValid = state.legal_actions.some(a => a.id === actionId); if (isValid) { slotDiv.style.borderColor = 'var(--accent-green)'; slotDiv.style.boxShadow = '0 0 10px var(--accent-green)'; } } else if (isOppTarget) { slotDiv.style.borderColor = 'var(--accent-pink)'; slotDiv.style.boxShadow = '0 0 10px var(--accent-pink)'; } if (slot) { if (slot.locked) { slotDiv.classList.add('locked'); const lockIcon = document.createElement('div'); lockIcon.className = 'lock-overlay'; lockIcon.innerHTML = '🔒'; slotDiv.appendChild(lockIcon); } let imgPath = slot.img || slot.img_path || ''; const imgHtml = imgPath ? `${slot.name}` : ''; let heartPipsHtml = ''; if (slot.hearts) { const colorNames = ['Red', 'Blue', 'Green', 'Yellow', 'Purple', 'Pink']; let pips = ''; for (let c = 0; c < 6; c++) { for (let h = 0; h < (slot.hearts[c] || 0); h++) { pips += `
`; } } if (pips) heartPipsHtml = `
${pips}
`; } let bladeHeartsHtml = ''; if (slot.blade_hearts) { let pips = ''; for (let c = 0; c < 6; c++) { for (let h = 0; h < (slot.blade_hearts[c] || 0); h++) { pips += `
`; } } if (pips) bladeHeartsHtml = `
${pips}
`; } const displayId = slot.card_no || slot.id; const idHtml = `
ID:${displayId}
`; let modifiersHtml = ''; if (slot.modifiers && slot.modifiers.length > 0) { let modLines = ''; slot.modifiers.forEach(mod => { let expiryIcon = mod.expiry === 'TURN_END' ? '⏳' : (mod.expiry === 'CONSTANT' ? '♾️' : (mod.expiry === 'LIVE_END' ? '🏁' : '⏲️')); modLines += `
${expiryIcon} ${mod.description}
`; }); modifiersHtml = `
${modLines}
`; } slotDiv.innerHTML = `${imgHtml} ${slot.cost}${bladeHeartsHtml}${heartPipsHtml}
${slot.name}
${modifiersHtml}${idHtml}`; const tooltipText = getEffectiveAbilityText(slot); if (tooltipText) slotDiv.setAttribute('data-text', tooltipText); } const label = document.createElement('div'); label.className = 'area-label'; label.textContent = labels[i]; const energyDiv = document.createElement('div'); energyDiv.className = 'attached-energy'; if (slot && slot.energy > 0) { for (let e = 0; e < slot.energy; e++) { const pip = document.createElement('div'); pip.className = 'energy-mini'; pip.style.background = 'var(--accent-gold)'; pip.style.boxShadow = '0 0 5px var(--accent-gold)'; energyDiv.appendChild(pip); } } area.appendChild(slotDiv); area.appendChild(label); area.appendChild(energyDiv); if (abilityAction) { const actBtn = document.createElement('button'); actBtn.className = 'slot-action-btn'; actBtn.textContent = translations[currentLang]['act_ability'] || '能力発動'; actBtn.onclick = (e) => { e.stopPropagation(); doAction(abilityAction.id); }; // Tooltip for the button as well actBtn.setAttribute('data-text', getEffectiveActionText(abilityAction)); area.appendChild(actBtn); } el.appendChild(area); } } function renderEnergy(containerId, energy) { const el = document.getElementById(containerId); if (!el) return; el.innerHTML = ''; if (!energy || !Array.isArray(energy)) return; energy.forEach((e, i) => { const div = document.createElement('div'); // Check if we have card data if (e.card && e.card.img) { div.className = 'card card-mini' + (e.tapped ? ' tapped' : ''); // Customize size for energy zone to fit more div.style.width = '45px'; div.style.height = '63px'; div.style.marginRight = '4px'; div.id = `${containerId}-slot-${i}`; const imgPath = fixImg(e.card.img || e.card.img_path); const imgHtml = ``; // Overlay "Tapped" visual const tapOverlay = e.tapped ? '
' : ''; div.innerHTML = imgHtml + tapOverlay; let tooltipText = `Energy #${i + 1}: ${e.card.name}`; const abilityText = getEffectiveAbilityText(e.card); if (abilityText) tooltipText += `\n\n${abilityText}`; div.setAttribute('data-text', tooltipText); // Interaction div.style.cursor = 'pointer'; div.onclick = () => onEnergySlotClick(i); } else { // Fallback to pip if no card data div.className = 'energy-pip' + (e.tapped ? ' tapped' : ''); div.textContent = i + 1; } el.appendChild(div); }); } function renderRuleLog(log, containerId = 'log-content') { const el = document.getElementById(containerId); if (!el) return; // Optimization: Only render the last 200 entries to prevent DOM slowdown // The full log is still available in memory if we need it, but for display 200 is plenty. const renderLimit = 200; const logToRender = log.length > renderLimit ? log.slice(-renderLimit) : log; // Use a DocumentFragment for batch appending const fragment = document.createDocumentFragment(); if (log.length > renderLimit) { const warning = document.createElement('div'); warning.className = 'log-entry'; warning.style.color = '#777'; warning.style.fontStyle = 'italic'; warning.textContent = `... (Oldest ${log.length - renderLimit} entries hidden) ...`; fragment.appendChild(warning); } logToRender.forEach(entry => { const div = document.createElement('div'); div.className = 'log-entry'; // Highlight error/warning if (entry.includes('Error')) div.style.color = '#ff6b6b'; if (entry.includes('Warning')) div.style.color = '#ffd93d'; div.textContent = entry; fragment.appendChild(div); }); el.innerHTML = ''; el.appendChild(fragment); // Auto-scroll to bottom el.scrollTop = el.scrollHeight; } function renderLiveZone(containerId, liveCards, clickable) { const el = document.getElementById(containerId); if (!el) return; el.innerHTML = ''; // Always show 3 slots for (let i = 0; i < 3; i++) { const card = liveCards[i]; const prefix = containerId.split('-')[0]; // 'my' or 'opp' const area = document.createElement('div'); area.className = 'board-slot-container'; const slot = document.createElement('div'); const isHidden = card && card.hidden && !card.face_down; slot.className = 'card card-mini' + (card ? ' type-live' : '') + (isHidden ? ' hidden' : ''); slot.id = `${prefix}-live-slot-${i}`; // Check for Performance Action (900-902) let perfAction = null; if (prefix === 'my' && state.legal_actions) { perfAction = state.legal_actions.find(a => a.id === (900 + i)); } if (card) { let imgPath = card.img || card.img_path || ''; const imgHtml = imgPath ? `` : ''; let reqHtml = '
'; if (card.required_hearts) { for (let c = 0; c < 6; c++) { const count = card.required_hearts[c]; for (let k = 0; k < count; k++) { reqHtml += `
`; } } if (card.required_hearts.length > 6) { const anyCount = card.required_hearts[6]; for (let k = 0; k < anyCount; k++) { reqHtml += `
`; } } } reqHtml += '
'; const opacityStyle = card.face_down ? 'opacity: 0.6; border: 2px dashed var(--accent-gold);' : ''; const peekLabel = card.face_down ? '
PEEK
' : ''; slot.innerHTML = `${peekLabel}${imgHtml}
${card.score || 0}
${reqHtml}
${card.name || ''}
`; if (card.face_down) slot.style.cssText += opacityStyle; const tooltipText = getEffectiveAbilityText(card); if (tooltipText) slot.setAttribute('data-text', tooltipText); } else { slot.style.border = '2px dashed #555'; slot.style.opacity = '0.5'; slot.innerHTML = `
空き ${i + 1}
`; } slot.style.cursor = 'pointer'; slot.onclick = () => onLiveSlotClick(i); area.appendChild(slot); if (perfAction) { const perfBtn = document.createElement('button'); perfBtn.className = 'slot-action-btn btn-perform'; perfBtn.textContent = translations[currentLang]['perform_live'] || 'ライブ開催'; perfBtn.onclick = (e) => { e.stopPropagation(); doAction(perfAction.id); }; perfBtn.setAttribute('data-text', getEffectiveActionText(perfAction)); area.appendChild(perfBtn); } el.appendChild(area); } } // Tooltip Logic let tooltipTimeout = null; let tooltipHideTimeout = null; let currentTooltipTarget = null; let currentTooltipSidebarTarget = null; function showTooltip(target, e, forceTarget = null, useSidebar = false, explicitText = null) { const effectiveTarget = forceTarget || target; const descPanel = document.getElementById('card-desc-panel'); const descContent = document.getElementById('card-desc-content'); const textRaw = explicitText || (target && target.dataset ? target.dataset.text : null); if (!textRaw || !descPanel || !descContent) return; // Reliability check: if we are hovering a new instance of the same button (due to re-render), // or if the content is exactly the same, skip to avoid flicker. if (descContent.dataset.rawText === textRaw && descPanel.style.display === 'block') { currentTooltipTarget = effectiveTarget; return; } if (currentTooltipTarget === effectiveTarget && !explicitText) return; currentTooltipTarget = effectiveTarget; let text = enrichAbilityText(textRaw); descContent.innerHTML = text; descContent.dataset.rawText = textRaw; // Store to prevent redundant renders descPanel.style.display = 'flex'; } function hideTooltip(immediate = false) { clearTimeout(tooltipTimeout); tooltipTimeout = null; if (immediate) { clearTimeout(tooltipHideTimeout); tooltipHideTimeout = null; currentTooltipTarget = null; currentTooltipSidebarTarget = null; const descPanel = document.getElementById('card-desc-panel'); if (descPanel) descPanel.style.display = 'none'; return; } if (tooltipHideTimeout) return; tooltipHideTimeout = setTimeout(() => { tooltipHideTimeout = null; currentTooltipTarget = null; currentTooltipSidebarTarget = null; const descPanel = document.getElementById('card-desc-panel'); if (descPanel) descPanel.style.display = 'none'; }, 100); // 100ms grace period for movement } document.body.addEventListener('mouseover', (e) => { const selector = '.card, .member-slot, .modifier-line, .action-btn, .action-group, .btn, .modal-content'; const target = e.target.closest(selector); if (target) { // Only trigger tooltip update if the target has text attribute. // If it doesn't (like a pass button without desc), we skip hideTooltip() // to prevent closing tooltips manually triggered by onmouseenter (highlightAction). if (target.dataset.text) { // Cancel any pending hide if (tooltipHideTimeout) { clearTimeout(tooltipHideTimeout); tooltipHideTimeout = null; } showTooltip(target, e, null, false); } } else { // If mouse is definitely NOT on any valid target, then hide it. hideTooltip(); } }); document.body.addEventListener('mouseout', (e) => { const selector = '.card, .member-slot, .modifier-line, .action-btn, .action-group, .btn, .modal-content'; const target = e.target.closest(selector); if (target) { // Only hide if we are actually leaving the descriptive area entirely. // If we move from a button to its container (action-group), keep it. const nextTarget = e.relatedTarget ? e.relatedTarget.closest(selector) : null; if (!nextTarget) { hideTooltip(); } } }); // Hide tooltip globally on click or scroll to prevent "stuck" tooltips window.addEventListener('scroll', () => hideTooltip(true), { passive: true }); window.addEventListener('click', () => hideTooltip(true)); // Shared helper for highlighting elements function addHighlight(id, className) { const el = document.getElementById(id); if (el) { el.classList.add(className); // Auto-scroll logic for hand cards to bring them into view if (el.closest('.card-area.hand')) { el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } console.log(`[DEBUG] Added ${className} to ${id} `); } } function highlightAction(a) { console.log('[DEBUG] Highlighting action:', a); clearHighlights(); // Don't hideTooltip() here, as mouseover listener already showed the action tooltip. // If we have a sub-target card, showTooltip will just update the content. const selfPrefix = (state.active_player === perspectivePlayer ? 'my' : 'opp'); const oppPrefix = (state.active_player === perspectivePlayer ? 'opp' : 'my'); // PLAY (1-180) or LIVE_SET (400-459) or MULLIGAN (300-359) if (a.type === 'PLAY') { if (a.hand_idx !== undefined) { addHighlight(`${selfPrefix}-hand-card-${a.hand_idx}`, 'highlight-source'); // NO showTooltip here if we are already hovering an action button } if (a.area_idx !== undefined) addHighlight(`${selfPrefix}-stage-slot-${a.area_idx}`, 'highlight-target'); } else if (a.type === 'LIVE_SET') { if (a.hand_idx !== undefined) { addHighlight(`${selfPrefix}-hand-card-${a.hand_idx}`, 'highlight-source'); } addHighlight(`${selfPrefix}-live-zone`, 'highlight-target'); } else if (a.type === 'ABILITY') { if (a.area_idx !== undefined) { addHighlight(`${selfPrefix}-stage-slot-${a.area_idx}`, 'highlight-source'); } } else if (a.type === 'MULLIGAN') { if (a.hand_idx !== undefined) { addHighlight(`${selfPrefix}-hand-card-${a.hand_idx}`, 'highlight-target'); } } else if (a.type === 'SELECT_HAND') { const prefix = (a.player_id !== undefined ? (a.player_id === perspectivePlayer ? 'my' : 'opp') : selfPrefix); const id = `${prefix}-hand-card-${a.hand_idx}`; addHighlight(id, 'highlight-source'); const card = document.getElementById(id); if (card && card.dataset.text) { showTooltip(card, { clientX: card.getBoundingClientRect().right + 10, clientY: card.getBoundingClientRect().top }); } } else if (a.type === 'SELECT_STAGE') { const prefix = (a.player_id !== undefined ? (a.player_id === perspectivePlayer ? 'my' : 'opp') : selfPrefix); const id = `${prefix}-stage-slot-${a.area_idx}`; addHighlight(id, 'highlight-target'); const slot = document.getElementById(id); if (slot && slot.dataset.text) { showTooltip(slot, { clientX: slot.getBoundingClientRect().right + 10, clientY: slot.getBoundingClientRect().top }); } } else if (a.type === 'SELECT') { if (state.pending_choice && state.pending_choice.type === 'TARGET_OPPONENT_MEMBER') { const prefix = (a.player_id !== undefined ? (a.player_id === perspectivePlayer ? 'my' : 'opp') : oppPrefix); const id = `${prefix}-stage-slot-${a.index}`; addHighlight(id, 'highlight-target'); const slot = document.getElementById(id); if (slot && slot.dataset.text) { showTooltip(slot, { clientX: slot.getBoundingClientRect().right + 10, clientY: slot.getBoundingClientRect().top }); } } else { addHighlight(`select-list-item-${a.index}`, 'highlight-target'); } } else if (a.type === 'SELECT_DISCARD') { const prefix = (a.player_id !== undefined ? (a.player_id === perspectivePlayer ? 'my' : 'opp') : selfPrefix); addHighlight(`${prefix}-discard`, 'highlight-target'); } else if (a.type === 'SELECT_LIVE') { const prefix = (a.player_id !== undefined ? (a.player_id === perspectivePlayer ? 'my' : 'opp') : selfPrefix); const id = `${prefix}-live-slot-${a.area_idx}`; addHighlight(id, 'highlight-target'); const slot = document.getElementById(id); if (slot && slot.dataset.text) { showTooltip(slot, { clientX: slot.getBoundingClientRect().right + 10, clientY: slot.getBoundingClientRect().top }); } } // Fallback: Highlight source card by ID if provided and not highlighted by index if (a.source_card_id !== undefined && a.source_card_id !== -1) { highlightCardById(a.source_card_id); } } function highlightPendingSource() { if (!state || !state.pending_choice) return; const srcId = state.pending_choice.source_card_id; if (srcId === undefined || srcId === -1) return; highlightCardById(srcId); } function highlightCardById(srcId) { if (!state) return; // Search both "my" and "opp" zones based on perspective const playersMap = [ { id: perspectivePlayer, prefix: 'my' }, { id: 1 - perspectivePlayer, prefix: 'opp' } ]; playersMap.forEach(pMap => { const p = state.players[pMap.id]; if (!p) return; // Stage if (p.stage) { p.stage.forEach((card, idx) => { const cid = card ? card.id : -1; if (cid === srcId) { const id = `${pMap.prefix}-stage-slot-${idx}`; addHighlight(id, 'highlight-source'); const slot = document.getElementById(id); if (slot) { // showTooltip removed to prevent conflict with action button tooltip } } }); } // Hand if (p.hand) { p.hand.forEach((card, idx) => { const cid = card ? card.id : -1; if (cid === srcId) { const id = `${pMap.prefix}-hand-card-${idx}`; addHighlight(id, 'highlight-source'); const cardEl = document.getElementById(id); if (cardEl) { // showTooltip removed } } }); } // Live if (p.live_zone) { p.live_zone.forEach((cardObj, idx) => { const cid = cardObj ? cardObj.id : -1; if (cid === srcId) { addHighlight(`${pMap.prefix}-live-slot-${idx}`, 'highlight-source'); } }); } // Discard if (p.discard && p.discard.some(c => (typeof c === 'object' ? c.id === srcId : c === srcId))) { addHighlight(`${pMap.prefix}-discard`, 'highlight-source'); } // Energy if (p.energy) { p.energy.forEach((e, idx) => { const cid = (e && e.card) ? e.card.id : -1; if (cid === srcId) { addHighlight(`${pMap.prefix}-energy-slot-${idx}`, 'highlight-source'); } }); } }); } function clearHighlight() { // Alias to plural for compatibility clearHighlights(); } async function doAction(id) { if (state.active_player !== perspectivePlayer && !hotseatMode) { console.warn("[UI] Action blocked: Not your turn."); return; } if (window.pendingAction) return; window.pendingAction = true; // Visual feedback document.body.classList.add('action-pending'); log(`Action: ${id} `); try { if (offlineMode) { const res = await wasmAdapter.doAction(id); if (res.success) { state = res.state; lastStateJson = JSON.stringify(state); render(); log('Action completed'); } else { alert(res.error); } return; } const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; // Fast Poll: set polling to fast mode immediately on user action setPollingInterval(500); const res = await fetch('api/action', { method: 'POST', headers: headers, body: JSON.stringify({ action_id: id }) }); const text = await res.text(); lastStateJson = text; const data = JSON.parse(text); if (data.success) { state = data.state; render(); log('Action completed'); setTimeout(() => updateAdaptivePolling(), 2000); } else { alert(data.error || 'Unknown error'); updateAdaptivePolling(); } } finally { window.pendingAction = false; document.body.classList.remove('action-pending'); } } async function changeAI() { const aiMode = document.getElementById('ai-selector').value; console.log(`Switching AI to ${aiMode} `); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; try { const res = await fetch('api/set_ai', { method: 'POST', headers: headers, body: JSON.stringify({ ai_mode: aiMode }) }); const data = await res.json(); if (data.success) { console.log(`AI switched to ${aiMode} `); } else { alert('Failed to switch AI: ' + data.error); } } catch (e) { console.error("AI Switch failed", e); } } async function forceAction() { const id = parseInt(document.getElementById('force-id').value); console.log(`Force action: ${id} `); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; const res = await fetch('api/action', { method: 'POST', headers: headers, body: JSON.stringify({ action_id: id, force: true }) }); const text = await res.text(); lastStateJson = text; const data = JSON.parse(text); if (data.success) { state = data.state; render(); console.log('Forced'); } else { console.log('Error: ' + data.error); } } function showLastPerformance() { const modal = document.getElementById('performance-modal'); if (!modal) return; selectedPerfTurn = -1; // Reset to latest // Try to render using current performance results first let results = null; if (state && state.performance_results && Object.keys(state.performance_results).length > 0) { results = state.performance_results; } else if (state && state.last_performance_results && Object.keys(state.last_performance_results).length > 0) { results = state.last_performance_results; } else if (lastPerformanceData) { results = lastPerformanceData; } const titleEl = document.getElementById('perf-title'); if (titleEl) titleEl.textContent = "Performance Result"; if (results || (state && state.performance_history && state.performance_history.length > 0)) { renderPerformanceResult(results); modal.style.display = 'flex'; } else { console.log("No performance data available yet."); } } function selectHistoryTurn(turn) { selectedPerfTurn = turn; renderPerformanceResult(null); // Will use selectedPerfTurn internally } function showMatchHistory() { const modal = document.getElementById('performance-modal'); if (!modal || !state || !state.performance_history) return; const content = document.getElementById('perf-content'); const titleEl = document.getElementById('perf-title'); if (titleEl) titleEl.textContent = "Match Performance History"; if (state.performance_history.length === 0) { content.innerHTML = '
履歴がありません
'; } else { let html = '
'; // Sort by turn descending const sorted = [...state.performance_history].reverse(); sorted.forEach((res, idx) => { html += `< div style = "border-bottom: 2px dashed rgba(255,255,255,0.1); padding-bottom:30px;" >

Turn ${res.turn} - Player ${res.player_id === 0 ? 'P0 (You)' : 'P1 (Opp)'}

`; // We temporarily wrap one result to reuse renderPerformanceResult logic partly // or just manually render a mini version. // Let's do a simplified manual render for history list. html += `< div style = "display:flex; flex-wrap:wrap; gap:10px; margin-bottom:15px;" > `; res.lives.forEach(live => { const opacity = live.passed ? 1 : 0.4; const borderColor = live.passed ? 'var(--accent-green)' : '#555'; html += ` < div style = "width:120px; text-align:center; opacity:${opacity}; border:1px solid ${borderColor}; padding:5px; border-radius:6px; background:rgba(255,255,255,0.05);" >
${live.name}
${live.passed ? 'SUCCESS' : 'FAILED'}
`; }); html += ` `; html += ` `; }); html += ''; content.innerHTML = html; } modal.style.display = 'flex'; } function dismissPerformanceModal() { document.getElementById('performance-modal').style.display = 'none'; } async function forcedTurnEnd() { const headers = { 'X-Room-Id': roomCode }; // Simple endpoint, might need session? if (sessionToken) headers['X-Session-Token'] = sessionToken; const res = await fetch('api/force_turn_end', { method: 'POST', headers: headers }); fetchState(); } async function execCode() { const code = document.getElementById('god-code').value; console.log(`Exec: ${code.substring(0, 30)}...`); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; const res = await fetch('api/exec', { method: 'POST', headers: headers, body: JSON.stringify({ code: code }) }); const text = await res.text(); lastStateJson = text; const data = JSON.parse(text); if (data.success) { state = data.state; render(); log('Code executed'); } else { log('Error: ' + data.error); } } async function resetGame() { log('Resetting game...'); if (offlineMode) { const res = await wasmAdapter.resetGame(); if (res.success) { state = res.state; window.lastShownPerformanceHash = ""; render(); log('New game started'); } return; } const modeToUse = (state && state.mode) ? state.mode : (hotseatMode ? "pvp" : "pve"); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; try { const res = await fetch('api/reset', { method: 'POST', headers: headers, body: JSON.stringify({ mode: modeToUse }) }); if (!res.ok) { const errorText = await res.text(); log(`Reset failed: ${res.status} - ${errorText} `); console.error('Reset error:', errorText); return; } const text = await res.text(); lastStateJson = text; const data = JSON.parse(text); if (data.success) { state = data.state; window.lastShownPerformanceHash = ""; // Reset hash on new game render(); log('New game started'); fetchState(); } else { log(`Reset failed: ${data.error || 'Unknown error'} `); } } catch (error) { log(`Reset error: ${error.message} `); console.error('Reset exception:', error); } } // (Removed duplicate showLastPerformance) function selectLogTurn(t) { selectedTurn = t; render(); } // ===== REPLAY SYSTEM ===== let replayMode = false; let replayData = null; let currentFrame = 0; let playInterval = null; window.toggleReplayMode = function () { replayMode = !replayMode; const controls = document.getElementById('replay-controls'); if (controls) controls.style.display = replayMode ? 'flex' : 'none'; if (!replayMode && playInterval) stopPlay(); }; window.loadReplay = async function () { const filename = (document.getElementById('replay-file')?.value || 'ai_match.json').trim(); try { const res = await fetch(`/ api / replay / ${filename}?t = ${Date.now()} `); replayData = await res.json(); currentFrame = 0; const totalEl = document.getElementById('total-frames'); if (totalEl) totalEl.textContent = replayData.states.length; displayReplayFrame(); log(`Loaded: Game ${replayData.game_id + 1}, Winner: ${replayData.winner}, Phase: ${replayData.states[0]?.phase}, Frames: ${replayData.states.length} `); } catch (e) { log('Failed to load replay: ' + e.message); } }; window.loadReplayFromFile = function (input) { if (!input.files || !input.files[0]) return; const file = input.files[0]; const reader = new FileReader(); reader.onload = function (e) { try { const json = JSON.parse(e.target.result); // Basic validation if (!json.states || !Array.isArray(json.states)) { throw new Error("Invalid replay format: missing 'states' array"); } replayData = json; currentFrame = 0; const totalEl = document.getElementById('total-frames'); if (totalEl) totalEl.textContent = replayData.states.length; displayReplayFrame(); log(`Loaded File: ${file.name} (Phase: ${replayData.states[0]?.phase}, Frames: ${replayData.states.length})`); // Stop auto-play if running if (playInterval) stopPlay(); // Ensure replay mode UI is active if (!replayMode) toggleReplayMode(); } catch (err) { log('Error reading replay file: ' + err.message); console.error(err); alert('Error loading replay: ' + err.message); } }; reader.readAsText(file); input.value = ''; // Reset }; window.openPasteReplayModal = function () { document.getElementById('paste-replay-modal').style.display = 'flex'; const input = document.getElementById('paste-replay-input'); input.value = ''; input.focus(); }; window.closePasteReplayModal = function () { document.getElementById('paste-replay-modal').style.display = 'none'; }; window.submitPasteReplay = function () { const text = document.getElementById('paste-replay-input').value; if (!text.trim()) return; try { const json = JSON.parse(text); if (!json.states || !Array.isArray(json.states)) throw new Error("Invalid replay format: missing 'states'"); replayData = json; currentFrame = 0; const totalEl = document.getElementById('total-frames'); if (totalEl) totalEl.textContent = replayData.states.length; displayReplayFrame(); log(`Loaded from Clipboard(Phase: ${replayData.states[0]?.phase}, Frames: ${replayData.states.length})`); if (playInterval) stopPlay(); if (!replayMode) toggleReplayMode(); closePasteReplayModal(); } catch (e) { alert("Invalid JSON: " + e.message); } }; window.jumpToFrame = function (val) { const n = parseInt(val); if (replayData && !isNaN(n) && n >= 0 && n < replayData.states.length) { currentFrame = n; displayReplayFrame(); } }; // Keyboard Navigation for Replay window.addEventListener('keydown', (e) => { if (!replayMode) return; if (document.activeElement.tagName === 'INPUT') return; // Don't trigger when typing in boxes if (e.key === 'ArrowLeft') { replayPrev(); } else if (e.key === 'ArrowRight') { replayNext(); } }); function displayReplayFrame() { if (!replayData || currentFrame >= replayData.states.length) return; const frame = replayData.states[currentFrame]; const frameEl = document.getElementById('frame-num'); if (frameEl) frameEl.textContent = currentFrame; const jumpInput = document.getElementById('jump-frame'); if (jumpInput) jumpInput.value = currentFrame; // If we have full state data, render it completely if (frame.players && frame.players.length >= 2) { state = frame; // Set global state to the replay frame render(); // Use the existing render function log(`Frame ${currentFrame}: T${frame.turn} ${frame.phase} P${frame.current_player} (Act: ${frame.action_taken || 0})`); } else { // Fallback to minimal display document.getElementById('turn').textContent = frame.turn; document.getElementById('phase').textContent = frame.phase_name || frame.phase; document.getElementById('score').textContent = `${frame.p0_score} - ${frame.p1_score} `; log(`Frame ${currentFrame}: T${frame.turn} ${frame.phase_name} ${frame.p0_score} - ${frame.p1_score} `); } } window.replayPrev = function () { if (currentFrame > 0) { currentFrame--; displayReplayFrame(); } }; window.replayNext = function () { if (replayData && currentFrame < replayData.states.length - 1) { currentFrame++; displayReplayFrame(); } else if (playInterval) stopPlay(); }; window.replayPrevTurn = function () { if (!replayData || currentFrame <= 0) return; const currentTurn = replayData.states[currentFrame].turn; let i = currentFrame - 1; // Go back to the start of the current turn or to the previous turn while (i > 0 && replayData.states[i].turn === currentTurn) i--; currentFrame = i; displayReplayFrame(); }; window.replayNextTurn = function () { if (!replayData || currentFrame >= replayData.states.length - 1) return; const currentTurn = replayData.states[currentFrame].turn; let i = currentFrame + 1; while (i < replayData.states.length && replayData.states[i].turn === currentTurn) i++; if (i < replayData.states.length) currentFrame = i; displayReplayFrame(); }; window.replayPrevPhase = function () { if (!replayData || currentFrame <= 0) return; const currentPhase = replayData.states[currentFrame].phase; const currentTurn = replayData.states[currentFrame].turn; let i = currentFrame - 1; while (i > 0 && replayData.states[i].phase === currentPhase && replayData.states[i].turn === currentTurn) i--; currentFrame = i; displayReplayFrame(); }; window.replayNextPhase = function () { if (!replayData || currentFrame >= replayData.states.length - 1) return; const currentPhase = replayData.states[currentFrame].phase; const currentTurn = replayData.states[currentFrame].turn; let i = currentFrame + 1; while (i < replayData.states.length && replayData.states[i].phase === currentPhase && replayData.states[i].turn === currentTurn) i++; if (i < replayData.states.length) currentFrame = i; displayReplayFrame(); }; window.togglePlay = function () { playInterval ? stopPlay() : startPlay(); }; function startPlay() { const btn = document.getElementById('play-btn'); if (btn) btn.textContent = '⏸ Pause'; playInterval = setInterval(window.replayNext, 500); } function stopPlay() { if (playInterval) { clearInterval(playInterval); playInterval = null; const btn = document.getElementById('play-btn'); if (btn) btn.textContent = '▶ Play'; } } async function forceAdvance() { log('Forcing advance...'); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; try { const res = await fetch('api/advance', { method: 'POST', headers: headers, body: JSON.stringify({}) }); if (res.ok) { const data = await res.json(); if (data.success) { console.log("Fetched state:", data.state); state = data.state; render(); log('Advance complete'); } else { log('Advance error: ' + data.error); } } else { console.warn("Advance failed with status:", res.status); log('Advance failed: Server responded with status ' + res.status); } } catch (e) { log('Advance failed: ' + e.message); } } async function dismissPerformanceModal() { try { console.log("Dismissing performance modal..."); document.getElementById('performance-modal').style.display = 'none'; // No auto-action. Just close. } catch (e) { console.error("Error clearing performance:", e); } } function renderPerformanceResult(results) { const content = document.getElementById('perf-content'); if (!content) return; let html = ''; // Add History Selector at the top (grouped by turn) if (state && state.performance_history && state.performance_history.length > 0) { // Extract unique turns const availableTurns = [...new Set(state.performance_history.map(h => h.turn))].sort((a, b) => b - a); html += '
'; html += ``; availableTurns.forEach(t => { html += ``; }); html += '
'; } // Determine what to display let displayResults = results; if (selectedPerfTurn >= 0) { // Group by player for the selected turn displayResults = {}; if (state && state.performance_history) { state.performance_history.forEach(h => { if (h.turn === selectedPerfTurn) { displayResults[h.player_id] = h; } }); } } else if (!displayResults) { // Fallback for current if none passed (e.g. from selectHistoryTurn) if (state && state.performance_results && Object.keys(state.performance_results).length > 0) { displayResults = state.performance_results; } else if (state && state.last_performance_results && Object.keys(state.last_performance_results).length > 0) { displayResults = state.last_performance_results; } else { displayResults = lastPerformanceData; } } // Safety fallback to prevent crashes on [0, 1].forEach if (!displayResults) displayResults = {}; html += '
'; const fixImg = (path) => { if (!path) return 'icon_blade.png'; if (path.startsWith('/') || path.startsWith('http')) return path; return 'img/' + path; }; // Iterate over all players who might have performed [0, 1].forEach(pid => { const res = displayResults[pid]; const playerName = pid === 0 ? "Player (You)" : "Opponent (AI)"; // Use a darker, more premium background const bgColor = pid === 0 ? "rgba(255,105,180,0.15)" : "rgba(100,200,255,0.15)"; const borderColor = pid === 0 ? "#ff69b4" : "#64c8ff"; if (!res) { html += `

${playerName}

No Performance / Skip
`; return; } html += `
`; // Header (Status) const statusColor = res.success ? '#4f4' : '#f44'; const statusIcon = res.success ? '🎉 SUCCESS' : '💔 FAILURE'; const statusBg = res.success ? 'rgba(76, 175, 80, 0.2)' : 'rgba(244, 67, 54, 0.2)'; html += `

${playerName}

${statusIcon} ${Array.isArray(res.lives) ? `(+${res.lives.reduce((acc, l) => acc + (l.passed ? (l.score || 0) : 0), 0)} PTS)` : ''}
`; // Main Layout: 3 Columns (Sources -> Total -> Goal) html += `
`; // 1. SOURCES (Detailed Breakdown) html += `
Source Logs
BLADE LOG:
${res.breakdown && res.breakdown.blades ? res.breakdown.blades.map(b => { const isInactive = b.type === 'inactive' || b.type === 'empty'; const opacity = isInactive ? '0.5' : '1'; const srcCard = resolveCardData(b.source_id); const tooltipText = srcCard ? getEffectiveAbilityText(srcCard) : b.source; return `
${b.source_id && b.source_id >= 0 ? `` : ''} ${b.source}
${b.value > 0 ? '+' : ''}${b.value}
`; }).join('') : '
No voltage sources
'}
HEART LOG:
${res.breakdown && res.breakdown.hearts ? res.breakdown.hearts.map(h => { if (h.type === 'transform') { return `
${h.source}: ${h.desc || h.text}
`; } const isInactive = h.type === 'inactive' || h.type === 'empty'; const opacity = isInactive ? '0.5' : '1'; const srcCard = resolveCardData(h.source_id); const tooltipText = srcCard ? getEffectiveAbilityText(srcCard) : h.source; return `
${h.source_id && h.source_id >= 0 ? `` : ''} ${h.source}
${renderHeartsCompact(h.value)}
`; }).join('') : '
No heart sources
'}
${res.breakdown && (res.breakdown.requirements || res.breakdown.transforms) ? `
GLOBAL / REQ LOG:
${res.breakdown.transforms ? res.breakdown.transforms.map(t => `
${t.desc}
` ).join('') : ''} ${res.breakdown.requirements ? res.breakdown.requirements.map(r => (r.type === 'req_mod') ? `
${r.source} (Req) ${renderHeartsCompact(r.value)}
` : '' ).join('') : ''}
` : ''}
Judgment Score:
Base (Live Cards) ${res.lives.reduce((acc, l) => acc + (l.passed ? (l.score || 0) : 0), 0)}
Score Icons (Notes) +${res.yell_score_bonus || 0}
${res.breakdown && res.breakdown.score_modifiers && res.breakdown.score_modifiers.length > 0 ? res.breakdown.score_modifiers.map(m => `
${m.source} +${m.value}
`).join('') : ''}
TOTAL ${res.lives.reduce((acc, l) => acc + (l.passed ? (l.score || 0) : 0), 0) + (res.yell_score_bonus || 0) + (res.breakdown && res.breakdown.score_modifiers ? res.breakdown.score_modifiers.reduce((acc, m) => acc + m.value, 0) : 0)}
${res.member_contributions && res.member_contributions.length > 0 ? `
MEMBER CONTRIBUTIONS:
${res.member_contributions.map(m => { const hasValue = m.hearts.some(v => v > 0) || m.blades > 0; if (!hasValue) return ''; return `
${m.source}
${m.volume_icons > 0 ? `${m.volume_icons}` : ''} ${m.draw_icons > 0 ? `${m.draw_icons}` : ''} ${m.blades > 0 ? `${m.blades}` : ''} ${renderHeartsCompact(m.hearts)}
`; }).join('')}
` : ''}
${res.yell_cards.length > 0 ? `
Yell Cards:
${res.yell_cards.map(y => { const hasHearts = y.blade_hearts && y.blade_hearts.some(h => h > 0); const hasVol = y.volume_icons > 0; const hasDraw = y.draw_icons > 0; return `
${hasHearts ? `
${renderBladeHeartsCompact(y.blade_hearts)}
` : ''} ${hasVol ? `
` : ''} ${hasDraw ? `
` : ''}
`; }).join('')}
` : ''}
`; // Arrow html += `
`; // 2. TOTAL (The Bank) html += `
Total Hearts
${renderTotalHeartsBreakdown(res.total_hearts)}
`; // Arrow html += `
`; // 3. GOAL (Live Cards) html += `
Live Requirements
`; res.lives.forEach(l => { const lColor = l.passed ? '#4f4' : '#f44'; const lBg = l.passed ? 'rgba(76, 175, 80, 0.1)' : 'rgba(244, 67, 54, 0.1)'; html += `
${l.name}
Progress:
${renderHeartProgress(l.filled, l.required)}
${l.reason ? `
${l.reason}
` : ''}
${l.passed ? '✓' : '✗'}
${l.passed ? 'PASSED' : 'FAILED'}
${l.passed ? `
+${l.score} PTS
` : ''}
`; }); html += `
`; // End Goals html += `
`; // End Flex Row html += `
`; // End Player Box }); html += ''; content.innerHTML = html; } function renderHeartProgress(filled, required) { if (!required) return ''; const safeFilled = [...(filled || new Array(7).fill(0))]; const safeReq = [...required]; let html = '
'; // 1. Process specific requirements (0-5) for (let idx = 0; idx < 6; idx++) { const reqCount = safeReq[idx]; if (reqCount > 0) { const fillCount = Math.min(reqCount, safeFilled[idx]); safeFilled[idx] -= fillCount; // Keep track of remaining for 'Any' const colorClass = `color-${idx}`; html += `
`; for (let i = 0; i < fillCount; i++) html += `
`; for (let i = 0; i < (reqCount - fillCount); i++) html += `
`; html += `
`; } } // 2. Process 'Any' requirements (6) const anyReqCount = safeReq[6] || 0; if (anyReqCount > 0) { html += `
`; let remainingAny = anyReqCount; // Show specific colors that satisfied 'Any' for (let idx = 0; idx < 7; idx++) { const colorClass = idx === 6 ? 'color-any' : `color-${idx}`; const fillCount = Math.min(remainingAny, safeFilled[idx]); for (let i = 0; i < fillCount; i++) { html += `
`; remainingAny--; } } // Remaining empty slots for (let i = 0; i < remainingAny; i++) { html += `
`; } html += `
`; } html += '
'; return html; } function renderHeartsCompact(hearts) { // Renders hearts as grouped numbers (e.g. [Pink Icon]x2) instead of individual pips if (!hearts) return ''; let html = '
'; let hasAny = false; hearts.forEach((count, idx) => { if (count > 0) { hasAny = true; const isAny = idx === 6; const colorClass = isAny ? 'color-any' : `color-${idx}`; const iconHtml = isAny ? `` : `
`; html += `
${iconHtml} ${count}
`; } }); if (!hasAny) return '-'; html += '
'; return html; } function renderBladeHeartsCompact(hearts) { return renderHeartsCompact(hearts).replace(/border-radius:50%/g, 'clip-path: polygon(50% 0%, 100% 85%, 50% 100%, 0% 85%)'); // Crude blade shape } function renderTotalHeartsBreakdown(hearts) { if (!hearts) return ''; let html = ''; // Python Order: Pink, Red, Yellow, Green, Blue, Purple const colors = ['Pink', 'Red', 'Yellow', 'Green', 'Blue', 'Purple', 'Any']; const colorCodes = ['#ff8da1', '#ef5350', '#ffd32a', '#76d672', '#4aaef7', '#ba68c8', 'white']; hearts.forEach((count, idx) => { if (count > 0) { html += `
${colors[idx]}
${count}
`; } }); if (html === '') return '
None
'; return html; } // Render Report Modal function renderReportModal() { // ... existing report modal code if present or just placeholder } function renderPerformanceGuide() { const p0 = state.players[perspectivePlayer] || state.players[0]; // Respect perspective const guide = p0.performance_guide; const panel = document.getElementById('perf-guide-panel'); if (!guide || guide.lives.length === 0) { panel.style.display = 'none'; return; } panel.style.display = 'block'; let html = `
Blades: ${guide.total_blades} Hearts: ${renderHeartsCompact(guide.total_hearts)}
`; guide.lives.forEach(l => { const color = l.passed ? '#4f4' : '#f44'; html += `
${l.name} (${l.score}pts)
${renderHeartProgress(l.filled, l.required)}
${!l.passed ? `
${l.reason}
` : ''}
${l.passed ? '✓' : '✗'}
`; }); // Add Detailed Breakdown Log if (guide.breakdown) { html += `
`; // Detailed log content (Voltage) html += `
BLADE LOG
${guide.breakdown.blades ? guide.breakdown.blades.map(b => { const isInactive = b.type === 'inactive' || b.type === 'empty'; const srcCard = resolveCardData(b.source_id); const tooltipText = srcCard ? getEffectiveAbilityText(srcCard) : b.source; return `
${b.source} ${b.value > 0 ? '+' : ''}${b.value}
`; }).join('') : '' }
`; // Detailed log content (Hearts) html += `
HEART LOG
${guide.breakdown.hearts ? guide.breakdown.hearts.map(h => { if (h.type === 'transform') { return `
${h.desc || h.text}
`; } const isInactive = h.type === 'inactive' || h.type === 'empty'; const srcCard = resolveCardData(h.source_id); const tooltipText = srcCard ? getEffectiveAbilityText(srcCard) : h.source; return `
${h.source} ${renderHeartsCompact(h.value)}
`; }).join('') : '' }
`; // Requirements / Global Log if (guide.breakdown.requirements || guide.breakdown.transforms) { html += `
GLOBAL / REQUIREMENTS
${guide.breakdown.transforms ? guide.breakdown.transforms.map(t => `
${t.desc}
` ).join('') : '' } ${guide.breakdown.requirements ? guide.breakdown.requirements.map(r => (r.type === 'req_mod') ? `
${r.source} (Req Reduced) ${renderHeartsCompact(r.value)}
` : '' ).join('') : '' }
`; } html += `
`; } document.getElementById('perf-guide-content').innerHTML = html; } function renderLookedCards() { const panel = document.getElementById('looked-cards-panel'); const content = document.getElementById('looked-cards-content'); const cards = state.looked_cards || []; if (cards.length === 0) { panel.style.display = 'none'; return; } panel.style.display = 'block'; let html = ''; cards.forEach((c, idx) => { const actionId = 600 + idx; // SELECT action IDs start at 600 const isLive = c.type === 'live'; const tooltip = getEffectiveAbilityText(c); html += `
${c.name}
`; }); content.innerHTML = html; } async function fetchState() { try { if (replayMode) return; // Stop polling while watching replay if (offlineMode) { if (!wasmAdapter) return; const res = await wasmAdapter.fetchState(); if (res.success) { // Check change const raw = JSON.stringify(res.state); if (raw === lastStateJson) return; lastStateJson = raw; state = res.state; render(); } return; } if (!roomCode) return; // Wait for room // Pause updates if Performance Modal is open const perfModal = document.getElementById('performance-modal'); if (perfModal && perfModal.style.display !== 'none') return; const headers = { 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; const res = await fetch('api/state?viewer=' + perspectivePlayer, { headers: headers }); if (res.status === 404) { // Room invalid or expired console.warn("Room not found (404). Resetting."); roomCode = null; state = null; localStorage.removeItem('lovelive_room_code'); document.getElementById('room-modal').style.display = 'flex'; console.log("DEBUG: Room 404 Reset"); updateRoomDisplay(); return; } const raw = await res.text(); if (raw === lastStateJson) return; // Skip if no change lastStateJson = raw; // Check if raw is HTML (typical for 404 or errors not handled by status check) if (raw.trim().startsWith('<')) { console.error("Received HTML instead of JSON state. API might be down or path incorrect."); return; } const data = JSON.parse(raw); if (data.success) { state = data.state; console.log("[DEBUG] State Mode:", state.mode); } else { console.error("State fetch unsuccessful:", data.error); return; } // Auto-sync perspective if authenticated if (state.my_player_id !== undefined && state.my_player_id !== -1 && !hotseatMode) { perspectivePlayer = state.my_player_id; } // Keep track of last performance for review if (state.performance_results && Object.keys(state.performance_results).length > 0) { lastPerformanceData = state.performance_results; } if (state.last_performance_results && Object.keys(state.last_performance_results).length > 0) { lastPerformanceData = state.last_performance_results; } render(); } catch (e) { console.error("Fetch Error:", e); } } // Initial setup fetchState(); setInterval(fetchState, 200); // Polling every 200ms (near-instant phase detection) // Extended logic for reporting let actionHistory = []; window.openReportModal = function () { document.getElementById('report-modal').style.display = 'flex'; document.getElementById('report-explanation').focus(); }; window.closeReportModal = function () { document.getElementById('report-modal').style.display = 'none'; }; window.downloadReport = function () { const explanation = document.getElementById('report-explanation').value; // Use current global state const reportData = { timestamp: new Date().toISOString(), explanation: explanation, state: state, history: actionHistory, errors: window.capturedErrors || [], navigator: navigator.userAgent }; const blob = new Blob([JSON.stringify(reportData, null, 2)], { type: 'application/json' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; // Format: report_YYYYMMDD_HHMMSS.json const dateStr = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 19); a.download = `loveca_report_${dateStr}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; window.submitReport = async function () { const explanation = document.getElementById('report-explanation').value; if (!explanation.trim()) { alert("Please provide an explanation."); return; } console.log("Submitting report..."); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; try { const res = await fetch('api/report_issue', { method: 'POST', headers: headers, body: JSON.stringify({ explanation: explanation, state: state, history: actionHistory }) }); const data = await res.json(); if (data.success) { console.log(`Report saved: ${data.filename} `); alert(`Bug report saved to ${data.filename}.\n\nPlease include this path when asking for a fix!`); closeReportModal(); } else { console.log(`Report failed: ${data.error} `); alert(`Failed to save report: ${data.error} `); } } catch (e) { console.log(`Report error: ${e.message} `); alert(`Error submitting report: ${e.message} `); } }; // Update doAction to track history const originalDoAction = window.doAction; window.doAction = async function (id) { actionHistory.push({ action_id: id, timestamp: new Date().toISOString(), phase: state ? state.phase : 'unknown', legal_actions: state ? state.legal_actions : [] }); // Keep only last 50 actions if (actionHistory.length > 50) actionHistory.shift(); return originalDoAction(id); }; // Deck Modal Functions window.openDeckModal = function () { document.getElementById('deck-modal').style.display = 'flex'; document.getElementById('deck-html-input').value = ''; document.getElementById('deck-preview').textContent = ''; }; // --- Perspective Switching --- window.setPerspective = function (pid) { perspectivePlayer = pid; document.getElementById('perspective-modal').style.display = 'none'; fetchState(); // Update labels const myName = document.getElementById('my-agent-name'); const oppName = document.getElementById('opp-agent-name'); if (pid === 0) { if (myName) myName.innerText = "(Player 1)"; if (oppName) oppName.innerText = "(Player 2)"; } else { if (myName) myName.innerText = "(Player 2)"; if (oppName) oppName.innerText = "(Player 1)"; } }; window.closeDeckModal = function () { document.getElementById('deck-modal').style.display = 'none'; }; window.submitDeck = async function () { const playerVal = document.getElementById('deck-player-select').value; let content = ''; const fileInput = document.getElementById('deck-file-input'); const file = fileInput.files[0]; const textInput = document.getElementById('deck-html-input').value; if (file) { try { content = await file.text(); } catch (e) { alert("Failed to read file: " + e.message); return; } } else if (textInput.trim()) { content = textInput; } else { alert('Please select a file or paste deck HTML.'); return; } const playerIds = (playerVal === 'both') ? [0, 1] : [parseInt(playerVal)]; if (offlineMode) { for (const pid of playerIds) { const res = await wasmAdapter.uploadDeck(pid, content); if (res.success) { console.log(`[Offline] Deck loaded for P${pid}: ${res.message}`); } else { alert(`Failed to load deck for P${pid}: ${res.error}`); } } closeDeckModal(); fetchState(); return; } console.log("Uploading deck..."); const headers = { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }; if (sessionToken) headers['X-Session-Token'] = sessionToken; for (const pid of playerIds) { try { const resp = await fetch('api/upload_deck', { method: 'POST', headers: headers, body: JSON.stringify({ player: pid, content: content }) }); const result = await resp.json(); if (result.success) { alert(`Deck set for Player ${pid + 1}: ${result.message} `); closeDeckModal(); // Refresh state to see new deck fetchState(); } else { alert(`Failed to set deck for P${pid + 1}: ` + (result.error || 'Unknown error')); } } catch (e) { alert(`Error submitting deck for P${pid + 1}: ` + e.message); } } }; // Load Test Deck Preset window.loadTestDeck = async function () { const playerVal = document.getElementById('deck-player-select').value; const playerIds = (playerVal === 'both') ? [0, 1] : [parseInt(playerVal)]; if (!confirm(`Load 'Test Deck'(doubled quantities) for Player ${playerVal === 'both' ? 'Both' : parseInt(playerVal) + 1}?`)) return; try { // 1. Get the compiled deck list from server const res = await fetch('api/get_test_deck'); const data = await res.json(); if (!data.success) { alert("Failed to load test deck: " + data.error); return; } const cards = data.content; // Array of strings e.g. ["PL!...", "PL!..."] // 2. Upload this list as a "custom deck" // We reuse upload_deck but pass JSON content console.log(`Uploading test deck(${cards.length} cards)...`); for (const pid of playerIds) { const resp = await fetch('api/upload_deck', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }, body: JSON.stringify({ player: pid, content: JSON.stringify(cards) // Send as JSON string of list }) }); const result = await resp.json(); if (result.success) { alert(`Test Deck loaded for P${pid + 1}: ${result.message} `); closeDeckModal(); fetchState(); } else { alert(`Failed to load P${pid + 1}: ` + result.error); } } } catch (e) { console.error(e); alert("Error loading test deck: " + e.message); } }; // Help Modal window.openHelpModal = function () { document.getElementById('help-modal').style.display = 'flex'; }; window.closeHelpModal = function () { document.getElementById('help-modal').style.display = 'none'; }; // Load Random Deck window.loadRandomDeck = async function () { const playerVal = document.getElementById('deck-player-select').value; const playerIds = (playerVal === 'both') ? [0, 1] : [parseInt(playerVal)]; if (!confirm(`Generate Random Deck for Player ${playerVal === 'both' ? 'Both' : parseInt(playerVal) + 1}?`)) return; try { const res = await fetch('api/get_random_deck'); const data = await res.json(); if (!data.success) { alert("Failed to generate deck: " + data.error); return; } const cards = data.content; console.log(`Uploading random deck(${cards.length} cards)...`); for (const pid of playerIds) { const resp = await fetch('api/upload_deck', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Room-Id': roomCode }, body: JSON.stringify({ player: pid, content: JSON.stringify(cards) }) }); const result = await resp.json(); if (result.success) { alert(`Random Deck Loaded for P${pid + 1}`); closeDeckModal(); fetchState(); } else { alert(`Failed to load P${pid + 1}: ` + result.error); } } } catch (e) { console.error(e); alert("Error loading random deck: " + e.message); } }; // Preview deck as user types - validates card IDs against database let previewTimeout = null; const deckHtmlInput = document.getElementById('deck-html-input'); if (deckHtmlInput) { deckHtmlInput.addEventListener('input', function () { const html = this.value; const regex = /title="([^"]+?) :[^"]*"[^>]*>.*?class="num">(\d+)<\/span>/gs; const cards = {}; let count = 0; let match; while ((match = regex.exec(html)) !== null) { const cardId = match[1].trim(); const qty = parseInt(match[2], 10); cards[cardId] = (cards[cardId] || 0) + qty; count += qty; } if (count === 0) { document.getElementById('deck-preview').textContent = ''; return; } // Debounce validation API call clearTimeout(previewTimeout); previewTimeout = setTimeout(async () => { const cardIds = Object.keys(cards); try { const resp = await fetch('api/validate_cards', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ card_ids: cardIds, card_counts: cards }) }); const result = await resp.json(); const unknownSet = new Set(result.unknown); const breakdown = result.breakdown || { member: 0, live: 0, energy: 0 }; // Build card list with known/unknown highlighting and names const cardList = Object.entries(cards) .sort((a, b) => a[0].localeCompare(b[0])) .map(([id, n]) => { const isUnknown = unknownSet.has(id); const info = result.card_info?.[id]; const name = info?.name || ''; const type = info?.type || ''; const typeColor = type === 'Member' ? '#4CAF50' : type === 'Live' ? '#2196F3' : type === 'Energy' ? '#FF9800' : '#888'; const style = isUnknown ? 'color: #ff4444; font-weight: bold;' : ''; const badge = isUnknown ? ' ⚠️' : ''; const typeTag = type ? `${type}` : ''; return `
${id} x${n}${typeTag} ${name}${badge}
`; }) .join(''); document.getElementById('deck-preview').innerHTML = `Detected ${count} cards(${cardIds.length} unique):
👤 ${breakdown.member} Member 🎵 ${breakdown.live} Live ● ${breakdown.energy} Energy
${result.unknown_count > 0 ? `
⚠️ ${result.unknown_count} NOT in database
` : ''}
${cardList}
`; } catch (e) { console.error('Validation error:', e); } }, 300); }); } // Live Watch Logic let liveWatchInterval = null; let isLiveWatchOn = false; function toggleLiveWatch() { const btn = document.getElementById('live-watch-btn'); if (isLiveWatchOn) { // Turn OFF isLiveWatchOn = false; if (liveWatchInterval) { clearInterval(liveWatchInterval); liveWatchInterval = null; } btn.style.background = 'linear-gradient(135deg, #cc4444, #882222)'; console.log('Live Watch Disabled'); } else { // Turn ON isLiveWatchOn = true; btn.style.background = 'linear-gradient(135deg, #44cc44, #228822)'; console.log('Live Watch Enabled - Polling /api/state'); liveWatchInterval = setInterval(() => { fetchState(); }, 1000); } if (typeof updateLanguage === 'function') updateLanguage(); } // Init Language if (typeof updateLanguage === 'function') updateLanguage(); // --- Mobile Sidebar Logic --- function toggleSidebar() { const sidebar = document.querySelector('.sidebar'); const btn = document.getElementById('mobile-sidebar-toggle'); sidebar.classList.toggle('active'); document.body.classList.toggle('sidebar-open'); if (sidebar.classList.contains('active')) { btn.textContent = '✕'; btn.style.background = '#444'; } else { btn.textContent = '☰'; btn.style.background = 'var(--accent-pink)'; } } // --- Drag and Drop Logic --- let draggedCardIdx = -1; function initDragAndDrop() { // This function will be called after render to attach events // But since we render dynamically, we can attach inline or delegate. // Let's attach via delegation or re-attach in render functions. // Actually, simplest is to add attributes in renderCards and global listeners. } document.addEventListener('dragstart', (e) => { if (e.target.classList.contains('card') && e.target.closest('#my-hand')) { const idParts = e.target.id.split('-'); // id is 'my-hand-card-X' draggedCardIdx = parseInt(idParts[3]); e.dataTransfer.setData('text/plain', draggedCardIdx); e.dataTransfer.effectAllowed = 'move'; e.target.style.opacity = '0.4'; } }); document.addEventListener('dragend', (e) => { if (e.target.classList.contains('card')) { e.target.style.opacity = '1'; draggedCardIdx = -1; document.querySelectorAll('.member-slot').forEach(el => el.classList.remove('drag-over')); } }); document.addEventListener('dragover', (e) => { const slot = e.target.closest('.member-slot'); if (slot && draggedCardIdx !== -1) { e.preventDefault(); // Allow dropping e.dataTransfer.dropEffect = 'move'; slot.classList.add('drag-over'); } }); document.addEventListener('dragleave', (e) => { const slot = e.target.closest('.member-slot'); if (slot) { slot.classList.remove('drag-over'); } }); document.addEventListener('drop', (e) => { const slot = e.target.closest('.member-slot'); if (slot && draggedCardIdx !== -1) { e.preventDefault(); slot.classList.remove('drag-over'); // Identify Area Index const slotIdParts = slot.id.split('-'); // id is 'my-stage-slot-X' if (slotIdParts[1] === 'stage') { const areaIdx = parseInt(slotIdParts[3]); handleCardDrop(draggedCardIdx, areaIdx); } } }); function handleCardDrop(handIdx, areaIdx) { console.log(`[DnD] Dropped Hand[${handIdx}] onto Area[${areaIdx}]`); // Logic similar to onStageSlotClick but triggered by drop // Calculate Action ID: 1 + (hand_idx * 3) + area_idx const actionId = 1 + (handIdx * 3) + areaIdx; // Check legality const action = state.legal_actions.find(a => a.id === actionId); if (action) { log(`Playing Hand[${handIdx}] to Area ${areaIdx} (DnD)`); doAction(actionId); } else { log(`Cannot play Hand[${handIdx}] to Area ${areaIdx} (Invalid Move)`); // Maybe visual shake effect? } } // Game Loop (Adaptive Polling) let pollingTimer = null; let currentPollingInterval = 2000; function setPollingInterval(ms) { if (currentPollingInterval === ms && pollingTimer) return; console.log(`[POLLING] Changing interval to ${ms}ms`); currentPollingInterval = ms; if (pollingTimer) clearInterval(pollingTimer); pollingTimer = setInterval(() => { if (roomCode && document.getElementById('room-modal').style.display === 'none') { fetchState(); updateAdaptivePolling(); // Periodically re-evaluate } }, ms); } function updateAdaptivePolling() { if (!state) return; const isOurTurn = (state.active_player === perspectivePlayer); const isAutoPhase = [Phase.ACTIVE, Phase.ENERGY, Phase.DRAW, Phase.PERFORMANCE_P1, Phase.PERFORMANCE_P2, Phase.LIVE_RESULT].includes(state.phase); if (!isOurTurn || isAutoPhase) { // Fast poll when waiting for AI or auto-advance setPollingInterval(500); } else { // Slow poll when user is thinking to reduce server load setPollingInterval(2000); } } // Initial Start setPollingInterval(2000); // --- Image Pre-loading for Instant Tooltips --- const preloadedUrls = new Set(); function preloadAssets(additionalUrls = []) { // Icons are now inlined as Base64 in ICON_DATA_URIs additionalUrls.forEach(url => { if (url && !preloadedUrls.has(url)) { const img = new Image(); img.src = fixImg(url); preloadedUrls.add(url); } }); } // Initial run preloadAssets(); // Global Image Preloading (PRO) async function preloadAllCards() { console.log("[PRELOAD] Starting background card image preloading..."); try { const res = await fetch('data/cards_compiled.json'); if (!res.ok) return; const data = await res.json(); const cards = data.member_db || {}; const urls = []; for (const key in cards) { const card = cards[key]; const imgPath = card.img_path || card.img || card._img; if (imgPath) { urls.push(imgPath); } } console.log(`[PRELOAD] Found ${urls.length} card images to preload.`); // Chunk preloading to avoid flooding the network const chunkSize = 20; for (let i = 0; i < urls.length; i += chunkSize) { const chunk = urls.slice(i, i + chunkSize); await Promise.all(chunk.map(url => { return new Promise((resolve) => { const img = new Image(); img.onload = () => resolve(); img.onerror = () => resolve(); // Skip failures img.src = fixImg(url); }); })); if (i % 100 === 0 && i > 0) console.log(`[PRELOAD] Progress: ${i}/${urls.length}...`); } console.log("[PRELOAD] All card images cached."); } catch (e) { console.warn("[PRELOAD] Failed to preload cards:", e); } } preloadAllCards(); // Initial debug console.log("Main.js loaded v4 (Settings Fixed)"); updateLanguage(); preloadAssets(); fetchAndPopulateDecks(); // --- End of main.js ---