Improve forum graph rendering

This commit is contained in:
Ladd Hoffman 2023-01-28 10:19:26 -06:00
parent d1570e7672
commit 5834f89882
7 changed files with 73 additions and 37 deletions

View File

@ -1,3 +1,5 @@
import { displayNumber } from '../util.js';
export class Actor { export class Actor {
constructor(name, scene) { constructor(name, scene) {
this.name = name; this.name = name;
@ -60,8 +62,8 @@ export class Actor {
} }
async setValue(label, value) { async setValue(label, value) {
if (typeof value === 'number' && value.toString().length > 6) { if (typeof value === 'number') {
value = value.toFixed(2); value = displayNumber(value);
} }
let displayValue = this.values.get(label); let displayValue = this.values.get(label);
if (!displayValue) { if (!displayValue) {
@ -79,8 +81,8 @@ export class Actor {
for (const [label, fn] of this.valueFunctions.entries()) { for (const [label, fn] of this.valueFunctions.entries()) {
const displayValue = this.values.get(label); const displayValue = this.values.get(label);
let value = fn(); let value = fn();
if (typeof value === 'number' && value.toString().length > 6) { if (typeof value === 'number') {
value = value.toFixed(2); value = displayNumber(value);
} }
if (value !== displayValue.get()) { if (value !== displayValue.get()) {
await this.scene.sequence.log(`note over ${this.name} : ${label} = ${value}`); await this.scene.sequence.log(`note over ${this.name} : ${label} = ${value}`);

View File

@ -50,10 +50,6 @@ export class Box {
return this; return this;
} }
getInnerText() {
return this.el.innerText;
}
getId() { getId() {
return this.el.id; return this.el.id;
} }

View File

@ -4,6 +4,7 @@ import { Action } from './action.js';
import { CryptoUtil } from './crypto.js'; import { CryptoUtil } from './crypto.js';
import params from '../params.js'; import params from '../params.js';
import { ReputationHolder } from './reputation-holder.js'; import { ReputationHolder } from './reputation-holder.js';
import { displayNumber } from '../util.js';
class Post extends Actor { class Post extends Actor {
constructor(forum, authorPublicKey, postContent) { constructor(forum, authorPublicKey, postContent) {
@ -13,6 +14,7 @@ class Post extends Actor {
this.id = postContent.id ?? `post_${CryptoUtil.randomUUID()}`; this.id = postContent.id ?? `post_${CryptoUtil.randomUUID()}`;
this.authorPublicKey = authorPublicKey; this.authorPublicKey = authorPublicKey;
this.value = 0; this.value = 0;
this.initialValue = 0;
this.citations = postContent.citations; this.citations = postContent.citations;
this.title = postContent.title; this.title = postContent.title;
const revaluationTotal = this.citations.reduce((total, { weight }) => total += Math.abs(weight), 0); const revaluationTotal = this.citations.reduce((total, { weight }) => total += Math.abs(weight), 0);
@ -24,6 +26,18 @@ class Post extends Actor {
throw new Error('Each citation weight must be in the range [-1, 1]'); throw new Error('Each citation weight must be in the range [-1, 1]');
} }
} }
getLabel() {
return `${this.name}
<table><tr>
<td>initial</td>
<td>${displayNumber(this.initialValue)}</td>
</tr><tr>
<td>value</td>
<td>${displayNumber(this.value)}</td>
</tr></table>`
.replaceAll(/\n\s*/g, '');
}
} }
/** /**
@ -44,15 +58,9 @@ export class Forum extends ReputationHolder {
async addPost(authorId, postContent) { async addPost(authorId, postContent) {
const post = new Post(this, authorId, postContent); const post = new Post(this, authorId, postContent);
await this.actions.addPost.log(this, post); await this.actions.addPost.log(this, post);
this.posts.addVertex(post.id, post, post.title); this.posts.addVertex(post.id, post, post.getLabel());
if (this.scene.flowchart) {
this.scene.flowchart.log(`${post.id} -- value --> ${post.id}_value[0]`);
}
for (const { postId: citedPostId, weight } of post.citations) { for (const { postId: citedPostId, weight } of post.citations) {
this.posts.addEdge('citation', post.id, citedPostId, { weight }); this.posts.addEdge('citation', post.id, citedPostId, { weight });
if (this.scene.flowchart) {
this.scene.flowchart.log(`${post.id} -- ${weight} --> ${citedPostId}`);
}
} }
return post.id; return post.id;
} }
@ -68,9 +76,7 @@ export class Forum extends ReputationHolder {
async setPostValue(post, value) { async setPostValue(post, value) {
post.value = value; post.value = value;
await post.setValue('value', value); await post.setValue('value', value);
if (this.scene.flowchart) { this.posts.setVertexLabel(post.id, post.getLabel());
this.scene.flowchart.log(`${post.id}_value[${value}]`);
}
} }
getTotalValue() { getTotalValue() {
@ -82,13 +88,10 @@ export class Forum extends ReputationHolder {
}) { }) {
this.activate(); this.activate();
const initialValue = bench.reputation.valueOf(tokenId); const initialValue = bench.reputation.valueOf(tokenId);
if (this.scene.flowchart) {
this.scene.flowchart.log(`${postId}_initial_value[${initialValue}] -- initial value --> ${postId}`);
}
const post = this.getPost(postId); const post = this.getPost(postId);
post.setStatus('Validated'); post.setStatus('Validated');
post.initialValue = initialValue;
this.posts.setVertexLabel(post.id, post.getLabel());
// Store a reference to the reputation token associated with this post, // Store a reference to the reputation token associated with this post,
// so that its value can be updated by future validated posts. // so that its value can be updated by future validated posts.

View File

@ -1,5 +1,6 @@
export class Vertex { class Vertex {
constructor(data) { constructor(id, data) {
this.id = id;
this.data = data; this.data = data;
this.edges = { this.edges = {
from: [], from: [],
@ -14,7 +15,7 @@ export class Vertex {
} }
} }
export class Edge { class Edge {
constructor(label, from, to, data) { constructor(label, from, to, data) {
this.from = from; this.from = from;
this.to = to; this.to = to;
@ -23,8 +24,6 @@ export class Edge {
} }
} }
export class CategorizedEdges {}
export class Graph { export class Graph {
constructor(scene) { constructor(scene) {
this.scene = scene; this.scene = scene;
@ -42,7 +41,7 @@ export class Graph {
if (this.vertices.has(id)) { if (this.vertices.has(id)) {
throw new Error(`Vertex already exists with id: ${id}`); throw new Error(`Vertex already exists with id: ${id}`);
} }
const vertex = new Vertex(data); const vertex = new Vertex(id, data);
this.vertices.set(id, vertex); this.vertices.set(id, vertex);
if (this.scene && this.scene.flowchart) { if (this.scene && this.scene.flowchart) {
this.scene.flowchart.log(`${id}[${label ?? id}]`); this.scene.flowchart.log(`${id}[${label ?? id}]`);
@ -50,6 +49,12 @@ export class Graph {
return this; return this;
} }
setVertexLabel(id, label) {
if (this.scene && this.scene.flowchart) {
this.scene.flowchart.log(`${id}[${label}]`);
}
}
getVertex(id) { getVertex(id) {
return this.vertices.get(id); return this.vertices.get(id);
} }
@ -82,8 +87,13 @@ export class Graph {
} }
const edge = new Edge(label, from, to, data); const edge = new Edge(label, from, to, data);
this.setEdge(label, from, to, edge); this.setEdge(label, from, to, edge);
this.getVertex(from).edges.from.push(edge); const fromVertex = this.getVertex(from);
this.getVertex(to).edges.to.push(edge); fromVertex.edges.from.push(edge);
const toVertex = this.getVertex(to);
toVertex.edges.to.push(edge);
if (this.scene && this.scene.flowchart) {
this.scene.flowchart.log(`${fromVertex.id} -- ${data.weight} --> ${toVertex.id}`);
}
return this; return this;
} }

View File

@ -10,12 +10,12 @@ class MermaidDiagram {
this.element = this.box.addBox('Element'); this.element = this.box.addBox('Element');
this.renderBox = this.box.addBox('Render'); this.renderBox = this.box.addBox('Render');
this.box.addBox('Spacer').setInnerHTML('&nbsp;'); this.box.addBox('Spacer').setInnerHTML('&nbsp;');
this.logBox = logBox; this.logBoxPre = logBox.el.appendChild(document.createElement('pre'));
this.inSection = 0; this.inSection = 0;
} }
async log(msg, render = true) { async log(msg, render = true) {
this.logBox.addBox().setInnerHTML(msg).monospace(); this.logBoxPre.textContent = `${this.logBoxPre.textContent}\n${msg}`;
if (render) { if (render) {
await this.render(); await this.render();
} }
@ -24,13 +24,13 @@ class MermaidDiagram {
async render() { async render() {
const render = async () => { const render = async () => {
let innerText = this.logBox.getInnerText(); let text = this.logBoxPre.textContent;
for (let i = 0; i < this.inSection; i++) { for (let i = 0; i < this.inSection; i++) {
innerText += '\nend'; text += '\nend';
} }
const graph = await mermaid.mermaidAPI.render( const graph = await mermaid.mermaidAPI.render(
this.element.getId(), this.element.getId(),
innerText, text,
); );
this.renderBox.setInnerHTML(graph); this.renderBox.setInnerHTML(graph);
}; };

View File

@ -113,7 +113,7 @@
forum, forum,
new PostContent({ hello: "y'all" }) new PostContent({ hello: "y'all" })
.setTitle('Post 3') .setTitle('Post 3')
.addCitation(postId2, -0.5), .addCitation(postId1, -0.5),
{ {
fee: 100, fee: 100,
duration: 1000, duration: 1000,
@ -128,5 +128,28 @@
await pool3.evaluateWinningConditions(); await pool3.evaluateWinningConditions();
await updateDisplayValuesAndDelay(); await updateDisplayValuesAndDelay();
await scene.endSection();
await scene.startSection();
const { pool: pool4 } = await expert3.submitPostWithFee(
bench,
forum,
new PostContent({ hello: "y'all" })
.setTitle('Post 4')
.addCitation(postId2, -0.5),
{
fee: 100,
duration: 1000,
tokenLossRatio: 1,
},
);
await updateDisplayValuesAndDelay(1000);
// await expert1.stake(pool3, { position: true, amount 1});
// await updateDisplayValuesAndDelay();
await pool4.evaluateWinningConditions();
await updateDisplayValuesAndDelay();
await scene.endSection(); await scene.endSection();
</script> </script>

View File

@ -28,3 +28,5 @@ export const hexToRGB = (input) => {
const b = parseInt(`${input[4]}${input[5]}`, 16); const b = parseInt(`${input[4]}${input[5]}`, 16);
return { r, g, b }; return { r, g, b };
}; };
export const displayNumber = (value) => (value.toString().length > 6 ? value.toFixed(2) : value);