uraniumanchor

Crystalis Randomizer Graph

Mar 14th, 2025
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function recurse(nodes) {
  2.     return (reqs, r) => {
  3.         nodes[r]?.forEach(sr => {
  4.             if (!reqs.includes(sr)) {
  5.                 reqs = [...reqs, sr];
  6.             }
  7.         });
  8.         return reqs;
  9.     };
  10. }
  11.  
  12. function setVizNode(graph) {
  13.     window.Viz.instance().then(viz => {
  14.         let spoiler = document.querySelector('.if-spoiled.expanded');
  15.         if (spoiler) {
  16.             let node = spoiler.querySelector('div#graph');
  17.             if (node && spoiler.contains(node)) {
  18.                 spoiler.removeChild(node);
  19.             }
  20.             node = document.createElement('div');
  21.             node.id = 'graph';
  22.             spoiler.appendChild(node);
  23.             let svg = viz.renderSVGElement(graph);
  24.             let xml = new XMLSerializer().serializeToString(svg);
  25.             let data = btoa(xml);
  26.             let img = new Image();
  27.             img.width = 640;
  28.             img.src = 'data:image/svg+xml;name=spoiler_graph.svg;base64,' + data;
  29.             node.appendChild(img);
  30.         }
  31.     });
  32. }
  33.  
  34. function depthSort(depth) {
  35.     return (a, b) => {
  36.         if (Array.isArray(a)) {
  37.             a = a[0];
  38.             b = b[0];
  39.         }
  40.         return (depth[b] ?? 0) - (depth[a] ?? 0);
  41.     };
  42. }
  43.  
  44. if (!window.buttonsListened) {
  45.     document.querySelector('a#generate').addEventListener('click', () => {
  46.         document.querySelector('div#graph')?.remove();     
  47.     });
  48.     document.querySelector('a#spoiler').addEventListener('click', () => {
  49.         setTimeout(parseTree, 1000);
  50.     });
  51.     window.buttonsListened = true;
  52. }
  53.  
  54. function parseTree() {
  55.     let viz = document.querySelector('script[src="https://unpkg.com/@viz-js/[email protected]/lib/viz-standalone.js"');
  56.     if (viz == null) {
  57.         viz = document.createElement('script');
  58.         viz.src = 'https://unpkg.com/@viz-js/[email protected]/lib/viz-standalone.js';
  59.         viz.integrity = 'sha256-gXCCx2fSZS8HWKcJspr35g7dpDiFy2nJX8Fse2OCeXo=';
  60.         viz.crossOrigin = 'anonymous';
  61.         document.querySelector('head').appendChild(viz);
  62.     }
  63.     let nodes = {};
  64.     let depth = {};
  65.     let ul = document.querySelector('ul#spoiler-route');
  66.     ul.querySelectorAll('li').forEach(li => {
  67.         let [all, nameOrItem, item, reqs] = /([^()]+)(?: \(([^)]+)\))?: \[(.*)\]/.exec(li.textContent);
  68.         reqs = reqs.split(', ').map(r => r.trim()).filter(r => !!r);
  69.         if (nameOrItem === 'Draygon 2') {
  70.             ['Kelbesque 1', 'Sabera 1', 'Mado 1', 'Kelbesque 2', 'Sabera 2', 'Mado 2', 'Karmine', 'Sword of Wind', 'Sword of Fire', 'Sword of Water', 'Sword of Thunder'].forEach(r => {
  71.                 if (!reqs.includes(r)) {
  72.                     reqs.push(r);
  73.                 }
  74.             });
  75.         }
  76.         nodes[nameOrItem] = reqs;
  77.         depth[nameOrItem] = Math.max(...[0, ...reqs.map(r => depth[r] || 0)]) + 1;
  78.         if (item) {
  79.             nodes[item] = [nameOrItem, ...reqs];
  80.             depth[item] = Math.max(...[0, depth[nameOrItem], ...reqs.map(r => depth[r] || 0)]) + 1;
  81.         }
  82.         if (nameOrItem.startsWith('Karmine ') && nodes['Karmine'] == null) {
  83.             nodes['Karmine'] = reqs.includes('Shooting Statue') ? reqs : [...reqs, 'Shooting Statue'];
  84.             depth['Karmine'] = Math.max(...[0, ...nodes['Karmine'].map(r => depth[r] || 0)]) + 1;
  85.         }
  86.     });
  87.    
  88.     Object.entries(nodes).sort(depthSort(depth)).reverse().forEach(([req, reqs], n, entries) => {
  89.         nodes[req] = reqs.reduce(recurse(nodes), reqs).sort(depthSort(depth));
  90.     });
  91.        
  92.     Object.values(nodes).forEach(reqs => {
  93.         reqs.sort(depthSort(depth));
  94.     });
  95.    
  96.     let graph = 'digraph G {\n';
  97.     graph +=
  98. `  subgraph cluster_0 {
  99.     node [style=filled, color=lightgreen];
  100.     "Crystalis";
  101. `;
  102.    
  103.     Object.entries(nodes).forEach(([req, reqs]) => {
  104.         if (nodes['Crystalis'].includes(req)) {
  105.             let implied = [];
  106.             reqs.forEach(v => {
  107.                 if (!implied.includes(v)) {
  108.                     implied = [...implied, ...(nodes[v] || [])];
  109.                     graph += `    "${v}" -> "${req}";\n`;
  110.                     console.log(`adding "${v}" -> "${req}"`);
  111.                 } else {
  112.                     console.log(`skipping "${v}" -> "${req}"`);
  113.                 }
  114.             });
  115.         }
  116.     });
  117.     graph += `  }\n`;
  118.  
  119.     Object.entries(nodes).forEach(([req, reqs]) => {
  120.         if (!nodes['Crystalis'].includes(req)) {
  121.             if (reqs.length === 0) {
  122.                 graph += `  "${req}";\n`;
  123.             } else {
  124.                 let implied = [];
  125.                 reqs.forEach(v => {
  126.                     if (!implied.includes(v)) {
  127.                         implied = [...implied, ...(nodes[v] || [])];
  128.                         graph += `  "${v}" -> "${req}";\n`;
  129.                         console.log(`adding "${v}" -> "${req}"`);
  130.                     } else {
  131.                         console.log(`skipping "${v}" -> "${req}"`);
  132.                     }
  133.                 });
  134.             }
  135.         }
  136.     });
  137.    
  138.     graph += '}';
  139.    
  140.     if (!window.Viz) {
  141.         viz.addEventListener('load', () => {
  142.             setVizNode(graph);
  143.         });
  144.     } else {
  145.         setVizNode(graph);
  146.     }
  147.    
  148.     return [nodes, depth, graph];
  149. }
  150.  
Add Comment
Please, Sign In to add comment