85 lines
2.4 KiB
JavaScript
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,
|
|
);
|
|
}
|
|
}
|
|
}
|