import { Actor } from './actor.js'; import { Graph } from './graph.js'; import { CryptoUtil } from './crypto.js'; import params from './params.js'; import { Action } from './action.js'; class Post extends Actor { constructor(forum, authorId, postContent) { const index = forum.posts.countVertices(); const name = `Post${index + 1}`; super(name, forum.scene); this.id = postContent.id ?? CryptoUtil.randomUUID(); this.authorId = authorId; this.value = 0; } } /** * 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(); this.actions = { addPost: new Action('add post', scene), }; } async addPost(authorId, postContent) { const post = new Post(this, authorId, postContent); this.actions.addPost.log(this, post); this.posts.addVertex(post.id, post); for (const { postId: citedPostId, weight } of postContent.citations) { this.posts.addEdge('citation', post.id, citedPostId, { weight }); } return post.id; } getPost(postId) { return this.posts.getVertexData(postId); } getPosts() { return this.posts.getVertices(); } onValidate({ tokensMinted }) { const initialValue = params.initialPostValueFunction({ tokensMinted }); this.distributeReputation(this, initialValue); } 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, ); } } }