import { Actor } from './actor.js'; import { Graph, Vertex } from './graph.js'; import params from './params.js'; class PostVertex extends Vertex { constructor(forum, authorId, postContent) { super(); this.forum = forum; this.id = postContent.id; this.authorId = authorId; this.citations = postContent.citations; this.value = 0; } onValidate({ tokensMinted }) { this.value = params.initialPostValueFunction({ tokensMinted }); this.forum.distributeReputation(this, this.value); } } /** * Purpose: Maintain a directed, acyclic, weighted graph of posts referencing other posts */ export class Forum extends Actor { constructor(bench, name, scene) { super(name, scene); this.bench = bench; this.posts = new Graph(); } async addPost(authorId, postContent) { const post = new PostVertex(this, authorId, postContent); this.posts.addVertex(post.id, post); for (const { postId: citedPostId, weight } of postContent.citations) { this.posts.addEdge('citation', post.id, citedPostId, { weight }); } } getPost(postId) { return this.posts.getVertexData(postId); } getPosts() { return this.posts.getVertices(); } distributeReputation(post, amount, depth = 0) { console.log('distributeReputation', { post, amount, depth }); // Add the given value to the current post post.value += amount; // Distribute a fraction of the added value among cited posts const distributeAmongCitations = amount * params.citationFraction; // Here we allow an arbitrary scale for the amount of the citations. // We normalize by dividing each by the total. const totalWeight = post.citations ?.map(({ weight }) => weight) .reduce((acc, cur) => (acc += cur), 0); for (const { to: citedPostId, data: { weight }, } of post.getEdges('citation', true)) { const citedPost = this.getPost(citedPostId); if (!citedPost) { throw new Error( `Post ${post.postId} cites unknown post ${citedPostId}`, ); } this.distributeReputation( citedPost, (weight / totalWeight) * distributeAmongCitations, depth + 1, ); } } }