dao-governance-framework/forum-network/public/classes/forum.js

85 lines
2.4 KiB
JavaScript

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,
);
}
}
}