const rootElement = document.getElementById('forum-network'); const rootBox = new Box('rootBox', rootElement).flex(); function randomDelay(min, max) { const delayMs = min + Math.random() * max; return delayMs; } function delay(min, max = min) { const delayMs = min + Math.random() * (max - min); return new Promise((resolve) => setTimeout(resolve, delayMs)); } if (true) { const scene = new Scene('Scene 1', rootBox); const webClientStatus = scene.addDisplayValue('WebClient Status'); const node1Status = scene.addDisplayValue('Node 1 Status'); const blockchainStatus = scene.addDisplayValue('Blockchain Status'); const webClient = scene.addActor('web client'); const node1 = scene.addActor('node 1'); const blockchain = scene.addActor('blockchain'); const requestForumPage = scene.addAction('requestForumPage'); const readBlockchainData = scene.addAction('readBlockchainData'); const blockchainData = scene.addAction('blockchainData'); const forumPage = scene.addAction('forumPage'); webClientStatus.set('Initialized'); node1Status.set('Idle'); blockchainStatus.set('Idle'); node1.on(requestForumPage, (src, detail) => { node1Status.set('Processing request'); node1.on(blockchainData, (_src, data) => { node1Status.set('Processing response'); setTimeout(() => { node1.send(src, forumPage, data); node1Status.set('Idle'); }, randomDelay(500, 1000)); }); setTimeout(() => { node1.send(blockchain, readBlockchainData, detail); }, randomDelay(500, 1500)); }); blockchain.on(readBlockchainData, (src, detail) => { blockchainStatus.set('Processing request'); setTimeout(() => { blockchain.send(src, blockchainData, {}); blockchainStatus.set('Idle'); }, randomDelay(500, 1500)); }); webClient.on(forumPage, (_src, _detail) => { webClientStatus.set('Received forum page'); }); setInterval(() => { webClient.send(node1, requestForumPage); webClientStatus.set('Requested forum page'); }, randomDelay(6000, 12000)); } (async function () { const scene = new Scene('Scene 2', rootBox); const webClient = scene.addActor('webClient'); const nodes = []; const memories = []; const storages = []; function addNode() { const idx = nodes.length; const node = scene.addActor(`node${idx}`); const memory = scene.addActor(`memory${idx}`); const storage = scene.addActor(`storage${idx}`); node.memory = memory; node.storage = storage; nodes.push(node); memories.push(memory); storages.push(storage); return node; } function getPeer(node) { const peers = nodes.filter((peer) => peer !== node); const idx = Math.floor(Math.random() * peers.length); return peers[idx]; } addNode(); addNode(); const [ seekTruth, considerInfo, evaluateConfidence, chooseResponse, qualifiedOpinions, requestMemoryData, memoryData, requestStorageData, storageData, ] = [ 'seek truth', 'consider available information', 'evaluate confidence', 'choose response', 'qualified opinions', 'request in-memory data', 'in-memory data', 'request storage data', 'storage data', ].map((name) => scene.addAction(name)); memories.forEach((memory) => { memory.setStatus('Idle'); memory.on(requestMemoryData, async (src, _detail) => { memory.setStatus('Retrieving data'); await delay(1000); memory.send(src, memoryData, {}); memory.setStatus('Idle'); }); }); storages.forEach((storage) => { storage.setStatus('Idle'); storage.on(requestStorageData, async (src, _detail) => { storage.setStatus('Retrieving data'); await delay(1000); storage.send(src, storageData, {}); storage.setStatus('Idle'); }); }); nodes.forEach((node) => { node.setStatus('Idle'); node.on(seekTruth, async (seeker, detail) => { node.setStatus('Processing request'); node.on(chooseResponse, async (_src, _info) => { node.setStatus('Choosing response'); await delay(1000); node.send(seeker, qualifiedOpinions, {}); node.setStatus('Idle'); }); node.on(evaluateConfidence, async (_src, _info) => { node.setStatus('Evaluating confidence'); await delay(1000); node.send(node, chooseResponse); }); node.on(considerInfo, async (_src, _info) => { node.setStatus('Considering info'); await delay(1000); node.send(node, evaluateConfidence); }); node.on(memoryData, (_src, _data) => { node.on(storageData, (_src, _data) => { if (detail?.readConcern === 'single') { node.send(node, considerInfo, {}); } else { const peer = getPeer(node); node.on(qualifiedOpinions, (_src, info) => { node.send(node, considerInfo, info); }); node.send(peer, seekTruth, { readConcern: 'single' }); } }); node.send(node.storage, requestStorageData); }); await delay(1000); node.send(node.memory, requestMemoryData); }); }); webClient.on(qualifiedOpinions, (_src, _detail) => { webClient.setStatus('Received opinions and qualifications'); }); await delay(1000); webClient.setStatus('Seek truth'); webClient.send(nodes[0], seekTruth); }());