Progress in forum implementation
This commit is contained in:
parent
cfa445471f
commit
b644d6c119
|
@ -75,3 +75,11 @@ We can support dynamic reevaluation if the reputation contract
|
||||||
It can verify a signature...
|
It can verify a signature...
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
Tokens staked for and against a post.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Token loss ratio
|
||||||
|
|
||||||
|
---
|
||||||
|
|
|
@ -28,28 +28,33 @@ export class Availability extends Actor {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register(reputationPublicKey, stake) {
|
register(reputationPublicKey, stake, __duration) {
|
||||||
|
// TODO: expire after duration
|
||||||
// ? Is a particular stake amount required?
|
// ? Is a particular stake amount required?
|
||||||
const worker = this.workers.get(reputationPublicKey) ?? new Worker(reputationPublicKey);
|
const worker = this.workers.get(reputationPublicKey) ?? new Worker(reputationPublicKey);
|
||||||
if (!worker.available) {
|
if (!worker.available) {
|
||||||
throw new Error('Worker is already registered and busy. Cannot increase stake.');
|
throw new Error('Worker is already registered and busy. Cannot increase stake.');
|
||||||
}
|
}
|
||||||
worker.stake += stake;
|
worker.stake += stake;
|
||||||
// ? Interact with Bench contract to encumber reputation?
|
// TODO: Interact with Bench contract to encumber reputation?
|
||||||
this.workers.set(reputationPublicKey, worker);
|
this.workers.set(reputationPublicKey, worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unregister() { }
|
||||||
|
|
||||||
get availableWorkers() {
|
get availableWorkers() {
|
||||||
return Array.from(this.workers.values()).filter(({ available }) => !!available);
|
return Array.from(this.workers.values()).filter(({ available }) => !!available);
|
||||||
}
|
}
|
||||||
|
|
||||||
async assignWork(requestId) {
|
async assignWork(requestId) {
|
||||||
// Get random worker
|
// Get random worker
|
||||||
|
// TODO: Probability proportional to stakes
|
||||||
const index = Math.floor(Math.random() * this.availableWorkers.length);
|
const index = Math.floor(Math.random() * this.availableWorkers.length);
|
||||||
const worker = this.availableWorkers[index];
|
const worker = this.availableWorkers[index];
|
||||||
worker.available = false;
|
worker.available = false;
|
||||||
worker.assignedRequestId = requestId;
|
worker.assignedRequestId = requestId;
|
||||||
// TODO: Notify assignee
|
// TODO: Notify assignee
|
||||||
|
return worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAssignedWork(reputationPublicKey) {
|
async getAssignedWork(reputationPublicKey) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { Action } from './action.js';
|
import { Action } from './action.js';
|
||||||
import { Actor } from './actor.js';
|
import { Actor } from './actor.js';
|
||||||
import { CryptoUtil } from './crypto.js';
|
import { CryptoUtil } from './crypto.js';
|
||||||
import { PostContent } from './post.js';
|
import { PostContent } from './post-content.js';
|
||||||
|
|
||||||
class Request {
|
class Request {
|
||||||
constructor(fee, content) {
|
constructor(fee, content) {
|
||||||
|
@ -34,7 +34,7 @@ export class Business extends Actor {
|
||||||
const request = new Request(fee, content);
|
const request = new Request(fee, content);
|
||||||
this.requests.set(request.id, request);
|
this.requests.set(request.id, request);
|
||||||
this.actions.assignWork.log(this, this.availability);
|
this.actions.assignWork.log(this, this.availability);
|
||||||
await this.availability.assignWork(request.id);
|
this.worker = await this.availability.assignWork(request.id);
|
||||||
return request.id;
|
return request.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,19 +55,20 @@ export class Business extends Actor {
|
||||||
workEvidence,
|
workEvidence,
|
||||||
});
|
});
|
||||||
this.actions.submitPost.log(this, this.forum);
|
this.actions.submitPost.log(this, this.forum);
|
||||||
await this.forum.addPost(reputationPublicKey, post);
|
const postId = await this.forum.addPost(reputationPublicKey, post);
|
||||||
|
|
||||||
// Initiate a validation pool for this work evidence.
|
// Initiate a validation pool for this work evidence.
|
||||||
// Validation pool supports secret ballots but we aren't using that here, since we want
|
// Validation pool supports secret ballots but we aren't using that here, since we want
|
||||||
// the post to be attributable to the reputation holder.
|
// the post to be attributable to the reputation holder.
|
||||||
this.actions.initiateValidationPool.log(this, this.bench);
|
this.actions.initiateValidationPool.log(this, this.bench);
|
||||||
const pool = await this.bench.initiateValidationPool({
|
const pool = await this.bench.initiateValidationPool({
|
||||||
postId: post.id,
|
postId,
|
||||||
fee: request.fee,
|
fee: request.fee,
|
||||||
duration,
|
duration,
|
||||||
tokenLossRatio,
|
tokenLossRatio,
|
||||||
signingPublicKey: reputationPublicKey,
|
signingPublicKey: reputationPublicKey,
|
||||||
anonymous: false,
|
anonymous: false,
|
||||||
|
authorStake: this.worker.stake,
|
||||||
});
|
});
|
||||||
|
|
||||||
// When the validation pool concludes,
|
// When the validation pool concludes,
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
import { Actor } from './actor.js';
|
import { Actor } from './actor.js';
|
||||||
import { Graph } from './graph.js';
|
import { Graph } from './graph.js';
|
||||||
|
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 { Action } from './action.js';
|
|
||||||
|
|
||||||
class Post extends Actor {
|
class Post extends Actor {
|
||||||
constructor(forum, authorId, postContent) {
|
constructor(forum, authorPublicKey, postContent) {
|
||||||
const index = forum.posts.countVertices();
|
const index = forum.posts.countVertices();
|
||||||
const name = `Post${index + 1}`;
|
const name = `Post${index + 1}`;
|
||||||
super(name, forum.scene);
|
super(name, forum.scene);
|
||||||
this.id = postContent.id ?? CryptoUtil.randomUUID();
|
this.id = postContent.id ?? CryptoUtil.randomUUID();
|
||||||
this.authorId = authorId;
|
this.authorPublicKey = authorPublicKey;
|
||||||
this.value = 0;
|
this.value = 0;
|
||||||
this.citations = postContent.citations;
|
this.citations = postContent.citations;
|
||||||
|
this.totalCitationWeight = this.citations.reduce((total, { weight }) => total += weight, 0);
|
||||||
|
if (this.totalCitationWeight > params.revaluationLimit) {
|
||||||
|
throw new Error('Post total citation weight exceeds revaluation limit '
|
||||||
|
+ `(${this.totalCitationWeight} > ${params.revaluationLimit})`);
|
||||||
|
}
|
||||||
|
if (this.citations.some(({ weight }) => Math.abs(weight) > 1)) {
|
||||||
|
throw new Error('Each citation weight must be in the range [-1, 1]');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPostValue(value) {
|
setPostValue(value) {
|
||||||
|
@ -55,34 +63,32 @@ export class Forum extends Actor {
|
||||||
return this.posts.getVertices();
|
return this.posts.getVertices();
|
||||||
}
|
}
|
||||||
|
|
||||||
distributeReputation(post, amount, depth = 0) {
|
propagateValue(postId, increment, depth = 0) {
|
||||||
console.log('distributeReputation', { post, amount, depth });
|
if (depth > params.maxPropagationDepth) {
|
||||||
// Add the given value to the current post
|
return [];
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
const post = this.getPost(postId);
|
||||||
|
const rewards = new Map();
|
||||||
|
const addReward = (id, value) => rewards.set(id, (rewards.get(id) ?? 0) + value);
|
||||||
|
const addRewards = (r) => {
|
||||||
|
for (const [id, value] of r) {
|
||||||
|
addReward(id, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Increment the value of the given post
|
||||||
|
const postValue = post.getPostValue();
|
||||||
|
post.setPostValue(postValue + increment);
|
||||||
|
|
||||||
|
// Award reputation to post author
|
||||||
|
console.log('reward for post author', post.authorPublicKey, increment);
|
||||||
|
addReward(post.authorPublicKey, increment);
|
||||||
|
|
||||||
|
// Recursively distribute reputation to citations, according to weights
|
||||||
|
for (const { postId: citedPostId, weight } of post.citations) {
|
||||||
|
addRewards(this.propagateValue(citedPostId, weight * increment, depth + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rewards;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { CryptoUtil } from './crypto.js';
|
import { CryptoUtil } from './crypto.js';
|
||||||
import { PostContent } from './post.js';
|
import { PostContent } from './post-content.js';
|
||||||
|
|
||||||
export class Message {
|
export class Message {
|
||||||
constructor(content) {
|
constructor(content) {
|
||||||
|
|
|
@ -2,9 +2,9 @@ const params = {
|
||||||
/* Validation Pool parameters */
|
/* Validation Pool parameters */
|
||||||
mintingRatio: 1, // c1
|
mintingRatio: 1, // c1
|
||||||
stakeForWin: 0.5, // c2
|
stakeForWin: 0.5, // c2
|
||||||
// stakeForAuthor: 0.5, // c3 - For now we keep the default that stakeForAuthor = stakeForWin
|
stakeForAuthor: 0.5, // c3
|
||||||
winningRatio: 0.5, // c4
|
winningRatio: 0.5, // c4
|
||||||
quorum: 0.5, // c5
|
quorum: 0, // c5
|
||||||
activeVoterThreshold: null, // c6
|
activeVoterThreshold: null, // c6
|
||||||
voteDuration: {
|
voteDuration: {
|
||||||
// c7
|
// c7
|
||||||
|
@ -20,7 +20,8 @@ const params = {
|
||||||
|
|
||||||
/* Forum parameters */
|
/* Forum parameters */
|
||||||
initialPostValue: () => 1, // q1
|
initialPostValue: () => 1, // q1
|
||||||
citationFraction: 0.3, // q2
|
revaluationLimit: 1, // q2
|
||||||
|
maxPropagationDepth: 3, // q3
|
||||||
};
|
};
|
||||||
|
|
||||||
export default params;
|
export default params;
|
||||||
|
|
|
@ -30,6 +30,9 @@ export class Scene {
|
||||||
primaryTextColor: '#b6b6b6',
|
primaryTextColor: '#b6b6b6',
|
||||||
noteBkgColor: '#516f77',
|
noteBkgColor: '#516f77',
|
||||||
noteTextColor: '#cecece',
|
noteTextColor: '#cecece',
|
||||||
|
activationBkgColor: '#1d3f49',
|
||||||
|
activationBorderColor: '#569595',
|
||||||
|
signalColor: '#57747d',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.dateLastRender = null;
|
this.dateLastRender = null;
|
||||||
|
|
|
@ -53,13 +53,13 @@ export class ValidationPool extends Actor {
|
||||||
}]; got ${duration}`,
|
}]; got ${duration}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
this.bench = bench;
|
||||||
this.forum = forum;
|
this.forum = forum;
|
||||||
this.postId = postId;
|
this.postId = postId;
|
||||||
this.state = ValidationPoolStates.OPEN;
|
this.state = ValidationPoolStates.OPEN;
|
||||||
this.setStatus('Open');
|
this.setStatus('Open');
|
||||||
this.votes = new Map();
|
this.votes = new Map();
|
||||||
this.voters = new Map();
|
this.voters = new Map();
|
||||||
this.bench = bench;
|
|
||||||
this.id = CryptoUtil.randomUUID();
|
this.id = CryptoUtil.randomUUID();
|
||||||
this.dateStart = new Date();
|
this.dateStart = new Date();
|
||||||
this.authorSigningPublicKey = signingPublicKey;
|
this.authorSigningPublicKey = signingPublicKey;
|
||||||
|
@ -70,14 +70,14 @@ export class ValidationPool extends Actor {
|
||||||
this.contentiousDebate = contentiousDebate;
|
this.contentiousDebate = contentiousDebate;
|
||||||
this.tokensMinted = fee * params.mintingRatio;
|
this.tokensMinted = fee * params.mintingRatio;
|
||||||
this.tokens = {
|
this.tokens = {
|
||||||
for: fee * params.mintingRatio * params.stakeForWin,
|
for: this.tokensMinted * params.stakeForWin,
|
||||||
against: fee * params.mintingRatio * (1 - params.stakeForWin),
|
against: this.tokensMinted * (1 - params.stakeForWin),
|
||||||
};
|
};
|
||||||
// tokens minted "for" the post go toward stake of author voting for their own post
|
// Tokens minted "for" the post go toward stake of author voting for their own post.
|
||||||
// also, author can provide additional stakes, e.g. availability stakes for work evidence post
|
// Also, author can provide additional stakes, e.g. availability stakes for work evidence post.
|
||||||
this.castVote(signingPublicKey, {
|
this.castVote(signingPublicKey, {
|
||||||
position: true,
|
position: true,
|
||||||
stake: this.tokens.for + authorStake,
|
stake: this.tokensMinted * params.stakeForAuthor + authorStake,
|
||||||
anonymous,
|
anonymous,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ export class ValidationPool extends Actor {
|
||||||
|
|
||||||
listVotes(position) {
|
listVotes(position) {
|
||||||
return new Map(
|
return new Map(
|
||||||
Array.from(this.votes.entries()).filter(
|
Array.from(this.votes).filter(
|
||||||
([_, vote]) => vote.position === position,
|
([_, vote]) => vote.position === position,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -148,7 +148,7 @@ export class ValidationPool extends Actor {
|
||||||
for (const [
|
for (const [
|
||||||
signingPublicKey,
|
signingPublicKey,
|
||||||
{ stake, lockingTime },
|
{ stake, lockingTime },
|
||||||
] of this.votes.entries()) {
|
] of this.votes) {
|
||||||
const voter = this.voters.get(signingPublicKey);
|
const voter = this.voters.get(signingPublicKey);
|
||||||
this.bench.reputations.lockTokens(
|
this.bench.reputations.lockTokens(
|
||||||
voter.reputationPublicKey,
|
voter.reputationPublicKey,
|
||||||
|
@ -185,71 +185,76 @@ export class ValidationPool extends Actor {
|
||||||
const votePasses = upvoteValue >= params.winningRatio * downvoteValue;
|
const votePasses = upvoteValue >= params.winningRatio * downvoteValue;
|
||||||
const quorumMet = upvoteValue + downvoteValue >= params.quorum * activeAvailableReputation;
|
const quorumMet = upvoteValue + downvoteValue >= params.quorum * activeAvailableReputation;
|
||||||
|
|
||||||
const result = quorumMet ? votePasses : null;
|
const result = {
|
||||||
|
votePasses,
|
||||||
|
upvoteValue,
|
||||||
|
downvoteValue,
|
||||||
|
};
|
||||||
|
|
||||||
if (result === null) {
|
if (quorumMet) {
|
||||||
this.setStatus('Resolved - Quorum not met');
|
|
||||||
this.scene.log(`note over ${this.name} : Quorum not met`);
|
|
||||||
} else {
|
|
||||||
this.setStatus(`Resolved - ${result ? 'Won' : 'Lost'}`);
|
this.setStatus(`Resolved - ${result ? 'Won' : 'Lost'}`);
|
||||||
this.scene.log(`note over ${this.name} : ${result ? 'Win' : 'Lose'}`);
|
this.scene.log(`note over ${this.name} : ${result ? 'Win' : 'Lose'}`);
|
||||||
this.applyTokenLocking();
|
this.applyTokenLocking();
|
||||||
this.distributeTokens(result);
|
this.distributeTokens(result);
|
||||||
|
} else {
|
||||||
|
this.setStatus('Resolved - Quorum not met');
|
||||||
|
this.scene.log(`note over ${this.name} : Quorum not met`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.deactivate();
|
this.deactivate();
|
||||||
this.state = ValidationPoolStates.RESOLVED;
|
this.state = ValidationPoolStates.RESOLVED;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
propagateValue(nextPost, increment) {
|
distributeTokens({ votePasses }) {
|
||||||
const postValue = nextPost.getPostValue();
|
const rewards = new Map();
|
||||||
nextPost.setPostValue(postValue + increment);
|
const addReward = (id, value) => rewards.set(id, (rewards.get(id) ?? 0) + value);
|
||||||
for (const { postId: citedPostId, weight } of nextPost.citations) {
|
|
||||||
console.log('citedPostId', citedPostId);
|
|
||||||
const citedPost = this.forum.getPost(citedPostId);
|
|
||||||
this.propagateValue(citedPost, weight * increment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
distributeTokens(result) {
|
|
||||||
const authorReputationPublicKey = this.anonymous
|
|
||||||
? this.voters.get(this.authorSigningPublicKey).reputationPublicKey
|
|
||||||
: this.authorSigningPublicKey;
|
|
||||||
|
|
||||||
// TODO: Take tokenLossRatio into account
|
// TODO: Take tokenLossRatio into account
|
||||||
|
const getTotalStaked = (position) => Array.from(this.listVotes(position).values())
|
||||||
|
.map(({ stake }) => stake)
|
||||||
|
.reduce((acc, cur) => (acc += cur), 0);
|
||||||
|
const tokensForWinners = votePasses ? (this.tokens.for + getTotalStaked(false))
|
||||||
|
: (this.tokens.against + getTotalStaked(true));
|
||||||
|
const winningVotes = this.listVotes(votePasses);
|
||||||
|
|
||||||
if (result === true) {
|
// Reward the winning voters, in proportion to their stakes
|
||||||
// Take initialValue into account
|
for (const [signingPublicKey, { stake }] of winningVotes) {
|
||||||
const initialPostValue = params.initialPostValue() * this.tokensMinted;
|
const { reputationPublicKey } = this.voters.get(signingPublicKey);
|
||||||
const tokensForAuthor = initialPostValue * params.stakeForWin;
|
const reward = (tokensForWinners * stake) / getTotalStaked(votePasses);
|
||||||
const tokensForWinners = initialPostValue * (1 - params.stakeForWin);
|
addReward(reputationPublicKey, reward);
|
||||||
|
console.log('reward for winning voter', reputationPublicKey, reward);
|
||||||
// Reward the author
|
|
||||||
this.bench.reputations.addTokens(authorReputationPublicKey, tokensForAuthor);
|
|
||||||
|
|
||||||
// Reward the vote winners, in proportion to their stakes
|
|
||||||
const winningVotes = this.listVotes(result);
|
|
||||||
const totalStakes = Array.from(winningVotes.values())
|
|
||||||
.map(({ stake }) => stake)
|
|
||||||
.reduce((acc, cur) => (acc += cur), 0);
|
|
||||||
if (!totalStakes) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const [signingPublicKey, { stake }] of winningVotes.entries()) {
|
|
||||||
const { reputationPublicKey } = this.voters.get(signingPublicKey);
|
|
||||||
const reward = (tokensForWinners * stake) / totalStakes;
|
|
||||||
this.bench.reputations.addTokens(reputationPublicKey, reward);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the forum post to set its (initial) value
|
|
||||||
const post = this.forum.getPost(this.postId);
|
|
||||||
|
|
||||||
// Recursively update values of referenced posts
|
|
||||||
this.propagateValue(post, initialPostValue);
|
|
||||||
} else {
|
|
||||||
// TODO: If the vote fails, distribute tokens.author among winning voters.
|
|
||||||
throw new Error("Vote did not pass -- we don't currently handle that!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const awardsFromVoting = Array.from(rewards.values()).reduce((total, value) => total += value, 0);
|
||||||
|
console.log('awardsFromVoting', awardsFromVoting);
|
||||||
|
|
||||||
|
if (votePasses && !!this.forum) {
|
||||||
|
// Recurse through forum to determine reputation effects
|
||||||
|
const forumReputationEffects = this.forum.propagateValue(this.postId, this.tokensMinted);
|
||||||
|
for (const [id, value] of forumReputationEffects) {
|
||||||
|
addReward(id, value);
|
||||||
|
}
|
||||||
|
const awardsFromForum = Array.from(forumReputationEffects.values()).reduce((total, value) => total += value, 0);
|
||||||
|
console.log('awardsFromForum', awardsFromForum);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow for possible attenuation of total value of post, e.g. based on degree of contention
|
||||||
|
const initialPostValue = this.tokensMinted * params.initialPostValue();
|
||||||
|
|
||||||
|
// Scale all rewards so that the total is correct
|
||||||
|
// TODO: Add more precise assertions; otherwise this operation could mask errors.
|
||||||
|
const currentTotal = Array.from(rewards.values()).reduce((total, value) => total += value, 0);
|
||||||
|
console.log('currentTotal', currentTotal);
|
||||||
|
for (const [id, value] of rewards) {
|
||||||
|
rewards.set(id, (value * initialPostValue) / currentTotal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply computed rewards
|
||||||
|
for (const [id, value] of rewards) {
|
||||||
|
this.bench.reputations.addTokens(id, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('pool complete');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Forum Graph: Debounce test</title>
|
|
||||||
<link type="text/css" rel="stylesheet" href="/index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="debounce-test"></div>
|
|
||||||
</body>
|
|
||||||
<script type="module">
|
|
||||||
import { Box } from "/classes/box.js";
|
|
||||||
import { Scene } from "/classes/scene.js";
|
|
||||||
import { debounce, delay } from "/util.js";
|
|
||||||
|
|
||||||
const rootElement = document.getElementById("debounce-test");
|
|
||||||
const rootBox = new Box("rootBox", rootElement).flex();
|
|
||||||
|
|
||||||
const scene = (window.scene = new Scene("Debounce test", rootBox));
|
|
||||||
|
|
||||||
const log = () => scene.log("event");
|
|
||||||
debounce(log, 500);
|
|
||||||
debounce(log, 500);
|
|
||||||
await delay(500);
|
|
||||||
debounce(log, 500);
|
|
||||||
debounce(log, 500);
|
|
||||||
</script>
|
|
|
@ -9,7 +9,7 @@
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { Box } from "/classes/box.js";
|
import { Box } from "/classes/box.js";
|
||||||
import { Scene } from "/classes/scene.js";
|
import { Scene } from "/classes/scene.js";
|
||||||
import { PostContent } from "/classes/post.js";
|
import { PostContent } from "/classes/post-content.js";
|
||||||
import { Expert } from "/classes/expert.js";
|
import { Expert } from "/classes/expert.js";
|
||||||
import { ForumNode } from "/classes/forum-node.js";
|
import { ForumNode } from "/classes/forum-node.js";
|
||||||
import { ForumNetwork } from "/classes/forum-network.js";
|
import { ForumNetwork } from "/classes/forum-network.js";
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
import { delay } from "/util.js";
|
import { delay } from "/util.js";
|
||||||
import { Forum } from "/classes/forum.js";
|
import { Forum } from "/classes/forum.js";
|
||||||
import { Public } from "/classes/public.js";
|
import { Public } from "/classes/public.js";
|
||||||
import { PostContent } from "/classes/post.js";
|
import { PostContent } from "/classes/post-content.js";
|
||||||
|
|
||||||
const DELAY_INTERVAL = 500;
|
const DEFAULT_DELAY_INTERVAL = 500;
|
||||||
|
|
||||||
const rootElement = document.getElementById("forum-test");
|
const rootElement = document.getElementById("forum-test");
|
||||||
const rootBox = new Box("rootBox", rootElement).flex();
|
const rootBox = new Box("rootBox", rootElement).flex();
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
const expert1 = await newExpert();
|
const expert1 = await newExpert();
|
||||||
const expert2 = await newExpert();
|
const expert2 = await newExpert();
|
||||||
await newExpert();
|
const expert3 = await newExpert();
|
||||||
const forum = (window.forum = new Forum("Forum", scene));
|
const forum = (window.forum = new Forum("Forum", scene));
|
||||||
const bench = (window.bench = new Bench(forum, "Bench", scene));
|
const bench = (window.bench = new Bench(forum, "Bench", scene));
|
||||||
|
|
||||||
|
@ -53,9 +53,9 @@
|
||||||
await scene.renderSequenceDiagram();
|
await scene.renderSequenceDiagram();
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateDisplayValuesAndDelay = async () => {
|
const updateDisplayValuesAndDelay = async (delayMs) => {
|
||||||
await updateDisplayValues();
|
await updateDisplayValues();
|
||||||
await delay(DELAY_INTERVAL);
|
await delay(delayMs ?? DEFAULT_DELAY_INTERVAL);
|
||||||
};
|
};
|
||||||
|
|
||||||
await updateDisplayValuesAndDelay();
|
await updateDisplayValuesAndDelay();
|
||||||
|
@ -70,15 +70,15 @@
|
||||||
tokenLossRatio: 1,
|
tokenLossRatio: 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
await updateDisplayValuesAndDelay();
|
await updateDisplayValuesAndDelay(1000);
|
||||||
|
|
||||||
await expert2.castVote(pool1, { position: true, stake: 1, anonymous: false });
|
// await expert2.castVote(pool1, { position: true, stake: 1, anonymous: false });
|
||||||
await updateDisplayValuesAndDelay();
|
// await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
await pool1.evaluateWinningConditions();
|
await pool1.evaluateWinningConditions();
|
||||||
await updateDisplayValuesAndDelay();
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
const { pool: pool2 } = await expert2.submitPostWithFee(
|
const { postId: postId2, pool: pool2 } = await expert2.submitPostWithFee(
|
||||||
bench,
|
bench,
|
||||||
forum,
|
forum,
|
||||||
new PostContent({ hello: "to you as well" }).addCitation(postId1, 0.5),
|
new PostContent({ hello: "to you as well" }).addCitation(postId1, 0.5),
|
||||||
|
@ -88,11 +88,29 @@
|
||||||
tokenLossRatio: 1,
|
tokenLossRatio: 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
await updateDisplayValuesAndDelay();
|
await updateDisplayValuesAndDelay(1000);
|
||||||
|
|
||||||
await expert1.castVote(pool2, { position: true, stake: 1, anonymous: false });
|
// await expert1.castVote(pool2, { position: true, stake: 1, anonymous: false });
|
||||||
await updateDisplayValuesAndDelay();
|
// await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
await pool2.evaluateWinningConditions();
|
await pool2.evaluateWinningConditions();
|
||||||
await updateDisplayValuesAndDelay();
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
const { pool: pool3 } = await expert3.submitPostWithFee(
|
||||||
|
bench,
|
||||||
|
forum,
|
||||||
|
new PostContent({ hello: "y'all" }).addCitation(postId2, 0.5),
|
||||||
|
{
|
||||||
|
fee: 10,
|
||||||
|
duration: 1000,
|
||||||
|
tokenLossRatio: 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
await updateDisplayValuesAndDelay(1000);
|
||||||
|
|
||||||
|
// await expert1.castVote(pool3, { position: true, stake: 1, anonymous: false });
|
||||||
|
// await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
|
await pool3.evaluateWinningConditions();
|
||||||
|
await updateDisplayValuesAndDelay();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Forum Graph</title>
|
|
||||||
<link type="text/css" rel="stylesheet" href="/index.css" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="graph-test"></div>
|
|
||||||
</body>
|
|
||||||
<script type="module">
|
|
||||||
import { Box } from "/classes/box.js";
|
|
||||||
import { Scene } from "/classes/scene.js";
|
|
||||||
import { Graph } from "/classes/graph.js";
|
|
||||||
|
|
||||||
const rootElement = document.getElementById("graph-test");
|
|
||||||
const rootBox = new Box("rootBox", rootElement).flex();
|
|
||||||
|
|
||||||
window.scene = new Scene("Graph test", rootBox);
|
|
||||||
|
|
||||||
window.graph = new Graph();
|
|
||||||
|
|
||||||
window.v = [];
|
|
||||||
function addVertex() {
|
|
||||||
const vertex = window.graph.addVertex({ seq: window.v.length });
|
|
||||||
window.v.push(vertex);
|
|
||||||
}
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
addVertex();
|
|
||||||
|
|
||||||
window.graph.addEdge("e1", 0, 1);
|
|
||||||
</script>
|
|
|
@ -1,28 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<head>
|
|
||||||
<title>Mermaid test</title>
|
|
||||||
<link type="text/css" rel="stylesheet" href="/index.css" />
|
|
||||||
|
|
||||||
<script type="module" defer>
|
|
||||||
// import mermaid from './mermaid.mjs';
|
|
||||||
import mermaid from "https://unpkg.com/mermaid@9.2.2/dist/mermaid.esm.mjs";
|
|
||||||
mermaid.mermaidAPI.initialize({ startOnLoad: false });
|
|
||||||
// Example of using the API var
|
|
||||||
const element = document.querySelector("#graphDiv");
|
|
||||||
const insertSvg = function (svgCode, bindFunctions) {
|
|
||||||
element.innerHTML = svgCode;
|
|
||||||
};
|
|
||||||
const graphDefinition = "graph TB\na-->b";
|
|
||||||
const graph = await mermaid.mermaidAPI.render(
|
|
||||||
"graphDiv",
|
|
||||||
graphDefinition,
|
|
||||||
insertSvg
|
|
||||||
);
|
|
||||||
const div = document.createElement("div");
|
|
||||||
div.innerHTML = graph;
|
|
||||||
document.body.append(div);
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="graphDiv"></div>
|
|
||||||
</body>
|
|
|
@ -11,6 +11,7 @@
|
||||||
import { Scene } from "/classes/scene.js";
|
import { Scene } from "/classes/scene.js";
|
||||||
import { Expert } from "/classes/expert.js";
|
import { Expert } from "/classes/expert.js";
|
||||||
import { Bench } from "/classes/bench.js";
|
import { Bench } from "/classes/bench.js";
|
||||||
|
import { Forum } from "/classes/forum.js";
|
||||||
import { delay } from "/util.js";
|
import { delay } from "/util.js";
|
||||||
|
|
||||||
const rootElement = document.getElementById("validation-pool");
|
const rootElement = document.getElementById("validation-pool");
|
||||||
|
@ -27,7 +28,7 @@
|
||||||
"Expert2",
|
"Expert2",
|
||||||
scene
|
scene
|
||||||
).initialize());
|
).initialize());
|
||||||
const bench = (window.bench = new Bench("Bench", scene));
|
const bench = (window.bench = new Bench(undefined, "Bench", scene));
|
||||||
|
|
||||||
const updateDisplayValues = async () => {
|
const updateDisplayValues = async () => {
|
||||||
expert1.setValue(
|
expert1.setValue(
|
||||||
|
|
Loading…
Reference in New Issue