Added table view
This commit is contained in:
parent
acda73fff4
commit
4c9cee9963
|
@ -48,3 +48,5 @@ If this is the only scenario in which new rep tokens are minted, and from then o
|
||||||
then we probably want each token to store information about the history of its value.
|
then we probably want each token to store information about the history of its value.
|
||||||
At a minimum this can be a list where each item includes the identifier of the corresponding validation pool, and the resulting increment/decrement of token value.
|
At a minimum this can be a list where each item includes the identifier of the corresponding validation pool, and the resulting increment/decrement of token value.
|
||||||
Each validation pool can then keep a record of the reputation staked by each voter, and the identifier of the corresponding post.
|
Each validation pool can then keep a record of the reputation staked by each voter, and the identifier of the corresponding post.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
|
@ -6,6 +6,7 @@ export class Actor {
|
||||||
this.status = this.scene.addDisplayValue(`${this.name} status`);
|
this.status = this.scene.addDisplayValue(`${this.name} status`);
|
||||||
this.status.set('Created');
|
this.status.set('Created');
|
||||||
this.values = new Map();
|
this.values = new Map();
|
||||||
|
this.valueFunctions = new Map();
|
||||||
this.active = 0;
|
this.active = 0;
|
||||||
this.scene.registerActor(this);
|
this.scene.registerActor(this);
|
||||||
}
|
}
|
||||||
|
@ -50,13 +51,16 @@ export class Actor {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addValue(label) {
|
addValue(label, fn) {
|
||||||
this.values.set(label, this.scene.addDisplayValue(`${this.name} ${label}`));
|
this.values.set(label, this.scene.addDisplayValue(`${this.name} ${label}`));
|
||||||
|
if (fn) {
|
||||||
|
this.valueFunctions.set(label, fn);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setValue(label, value) {
|
async setValue(label, value) {
|
||||||
if (typeof value === 'number') {
|
if (typeof value === 'number' && value.toString().length > 6) {
|
||||||
value = value.toFixed(2);
|
value = value.toFixed(2);
|
||||||
}
|
}
|
||||||
let displayValue = this.values.get(label);
|
let displayValue = this.values.get(label);
|
||||||
|
@ -70,4 +74,26 @@ export class Actor {
|
||||||
displayValue.set(value);
|
displayValue.set(value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async computeValues() {
|
||||||
|
for (const [label, fn] of this.valueFunctions.entries()) {
|
||||||
|
const displayValue = this.values.get(label);
|
||||||
|
let value = fn();
|
||||||
|
if (typeof value === 'number' && value.toString().length > 6) {
|
||||||
|
value = value.toFixed(2);
|
||||||
|
}
|
||||||
|
if (value !== displayValue.get()) {
|
||||||
|
await this.scene.sequence.log(`note over ${this.name} : ${label} = ${value}`);
|
||||||
|
}
|
||||||
|
displayValue.set(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getValuesMap() {
|
||||||
|
return new Map(Array.from(this.values.entries())
|
||||||
|
.map(([key, displayValue]) => [key, {
|
||||||
|
name: displayValue.getName(),
|
||||||
|
value: displayValue.get(),
|
||||||
|
}]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,8 @@ export class DisplayValue {
|
||||||
get() {
|
get() {
|
||||||
return this.value;
|
return this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,50 @@ class MermaidDiagram {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Table {
|
||||||
|
constructor(box) {
|
||||||
|
this.box = box;
|
||||||
|
this.columns = [];
|
||||||
|
this.rows = [];
|
||||||
|
this.table = box.el.appendChild(document.createElement('table'));
|
||||||
|
this.headings = this.table.appendChild(document.createElement('tr'));
|
||||||
|
}
|
||||||
|
|
||||||
|
setColumns(columns) {
|
||||||
|
if (JSON.stringify(columns) === JSON.stringify(this.columns)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.columns.length) {
|
||||||
|
this.table.innerHTML = '';
|
||||||
|
this.headings = this.table.appendChild(document.createElement('tr'));
|
||||||
|
this.columns = [];
|
||||||
|
}
|
||||||
|
this.columns = columns;
|
||||||
|
for (const { title } of columns) {
|
||||||
|
const heading = document.createElement('th');
|
||||||
|
this.headings.appendChild(heading);
|
||||||
|
heading.innerHTML = title ?? '';
|
||||||
|
}
|
||||||
|
if (this.rows.length) {
|
||||||
|
const { rows } = this;
|
||||||
|
this.rows = [];
|
||||||
|
for (const row of rows) {
|
||||||
|
this.addRow(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addRow(rowMap) {
|
||||||
|
this.rows.push(rowMap);
|
||||||
|
const row = this.table.appendChild(document.createElement('tr'));
|
||||||
|
for (const { key } of this.columns) {
|
||||||
|
const value = rowMap.get(key);
|
||||||
|
const cell = row.appendChild(document.createElement('td'));
|
||||||
|
cell.innerHTML = value ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Scene {
|
export class Scene {
|
||||||
constructor(name, rootBox) {
|
constructor(name, rootBox) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
@ -46,6 +90,7 @@ export class Scene {
|
||||||
this.box.addBox('Spacer').setInnerHTML(' ');
|
this.box.addBox('Spacer').setInnerHTML(' ');
|
||||||
this.topSection = this.box.addBox('Top section').flex();
|
this.topSection = this.box.addBox('Top section').flex();
|
||||||
this.displayValuesBox = this.topSection.addBox('Values');
|
this.displayValuesBox = this.topSection.addBox('Values');
|
||||||
|
this.middleSection = this.box.addBox('Middle section').flex();
|
||||||
this.box.addBox('Spacer').setInnerHTML(' ');
|
this.box.addBox('Spacer').setInnerHTML(' ');
|
||||||
this.actors = new Set();
|
this.actors = new Set();
|
||||||
|
|
||||||
|
@ -86,6 +131,16 @@ export class Scene {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withTable() {
|
||||||
|
if (this.table) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
const box = this.middleSection.addBox('Table');
|
||||||
|
this.box.addBox('Spacer').setInnerHTML(' ');
|
||||||
|
this.table = new Table(box);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
async addActor(name) {
|
async addActor(name) {
|
||||||
const actor = new Actor(name, this);
|
const actor = new Actor(name, this);
|
||||||
if (this.sequence) {
|
if (this.sequence) {
|
||||||
|
@ -130,4 +185,22 @@ export class Scene {
|
||||||
this.sequence.inSection--;
|
this.sequence.inSection--;
|
||||||
this.sequence.log('end');
|
this.sequence.log('end');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stateToTable(label) {
|
||||||
|
const row = new Map();
|
||||||
|
const columns = [];
|
||||||
|
columns.push({ key: 'seqNum', title: '#' });
|
||||||
|
row.set('seqNum', this.table.rows.length + 1);
|
||||||
|
row.set('label', label);
|
||||||
|
for (const actor of this.actors) {
|
||||||
|
for (const [aKey, { name, value }] of actor.getValuesMap()) {
|
||||||
|
const key = `${actor.name}:${aKey}`;
|
||||||
|
columns.push({ key, title: name });
|
||||||
|
row.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
columns.push({ key: 'label', title: '' });
|
||||||
|
this.table.setColumns(columns);
|
||||||
|
this.table.addRow(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,11 @@ export class ValidationPool extends ReputationHolder {
|
||||||
amount: this.mintedValue * (1 - params.stakeForAuthor),
|
amount: this.mintedValue * (1 - params.stakeForAuthor),
|
||||||
tokenId: this.tokenId,
|
tokenId: this.tokenId,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Keep a record of voters and their votes
|
||||||
|
const voter = this.bench.voters.get(reputationPublicKey) ?? new Voter(reputationPublicKey);
|
||||||
|
voter.addVoteRecord(this);
|
||||||
|
this.bench.voters.set(reputationPublicKey, voter);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTokenLossRatio() {
|
getTokenLossRatio() {
|
||||||
|
@ -171,6 +176,12 @@ export class ValidationPool extends ReputationHolder {
|
||||||
voter.addVoteRecord(this);
|
voter.addVoteRecord(this);
|
||||||
this.bench.voters.set(reputationPublicKey, voter);
|
this.bench.voters.set(reputationPublicKey, voter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update computed display values
|
||||||
|
for (const voter of this.bench.voters.values()) {
|
||||||
|
const actor = this.scene.findActor((a) => a.reputationPublicKey === voter.reputationPublicKey);
|
||||||
|
await actor.computeValues();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyTokenLocking() {
|
applyTokenLocking() {
|
||||||
|
@ -266,5 +277,17 @@ export class ValidationPool extends ReputationHolder {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('pool complete');
|
console.log('pool complete');
|
||||||
|
|
||||||
|
// Update computed display values
|
||||||
|
for (const voter of this.bench.voters.values()) {
|
||||||
|
const actor = this.scene.findActor((a) => a.reputationPublicKey === voter.reputationPublicKey);
|
||||||
|
await actor.computeValues();
|
||||||
|
}
|
||||||
|
await this.bench.computeValues();
|
||||||
|
if (this.forum) {
|
||||||
|
await this.forum.computeValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scene.stateToTable(`validation pool ${this.name} complete`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,10 @@ a:visited {
|
||||||
svg {
|
svg {
|
||||||
width: 800px;
|
width: 800px;
|
||||||
}
|
}
|
||||||
.hidden {
|
th {
|
||||||
/* display: none; */
|
text-align: left;
|
||||||
/* visibility: hidden; */
|
padding: 10px;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
background-color: #0c2025;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
const scene = (window.scene = new Scene('Availability test', rootBox));
|
const scene = (window.scene = new Scene('Availability test', rootBox));
|
||||||
scene.withSequenceDiagram();
|
scene.withSequenceDiagram();
|
||||||
scene.withFlowchart();
|
scene.withFlowchart();
|
||||||
|
scene.withTable();
|
||||||
|
|
||||||
const experts = (window.experts = []);
|
const experts = (window.experts = []);
|
||||||
const newExpert = async () => {
|
const newExpert = async () => {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
const scene = (window.scene = new Scene('Forum test', rootBox));
|
const scene = (window.scene = new Scene('Forum test', rootBox));
|
||||||
scene.withSequenceDiagram();
|
scene.withSequenceDiagram();
|
||||||
scene.withFlowchart();
|
scene.withFlowchart();
|
||||||
|
scene.withTable();
|
||||||
|
|
||||||
scene.addDisplayValue('c3. stakeForAuthor').set(params.stakeForAuthor);
|
scene.addDisplayValue('c3. stakeForAuthor').set(params.stakeForAuthor);
|
||||||
scene.addDisplayValue('q2. revaluationLimit').set(params.revaluationLimit);
|
scene.addDisplayValue('q2. revaluationLimit').set(params.revaluationLimit);
|
||||||
|
@ -48,22 +49,19 @@
|
||||||
const expert2 = await newExpert();
|
const expert2 = await newExpert();
|
||||||
const expert3 = await newExpert();
|
const expert3 = await newExpert();
|
||||||
|
|
||||||
const updateDisplayValues = async () => {
|
bench.addValue('total rep', () => bench.reputation.getTotal());
|
||||||
|
forum.addValue('total value', () => forum.getTotalValue());
|
||||||
|
|
||||||
for (const expert of experts) {
|
for (const expert of experts) {
|
||||||
await expert.setValue(
|
expert.addValue('rep', () => bench.reputation.valueOwnedBy(expert.reputationPublicKey));
|
||||||
'rep',
|
|
||||||
bench.reputation.valueOwnedBy(expert.reputationPublicKey),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
await bench.setValue('total rep', bench.reputation.getTotal());
|
|
||||||
await forum.setValue('total value', forum.getTotalValue());
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateDisplayValuesAndDelay = async (delayMs) => {
|
const updateDisplayValuesAndDelay = async (delayMs) => {
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(delayMs ?? DEFAULT_DELAY_INTERVAL);
|
await delay(delayMs ?? DEFAULT_DELAY_INTERVAL);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
scene.stateToTable('Initial state');
|
||||||
|
|
||||||
await updateDisplayValuesAndDelay();
|
await updateDisplayValuesAndDelay();
|
||||||
|
|
||||||
await scene.startSection();
|
await scene.startSection();
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
const rootBox = new Box('rootBox', rootElement).flex();
|
const rootBox = new Box('rootBox', rootElement).flex();
|
||||||
|
|
||||||
const scene = (window.scene = new Scene('Validation Pool test', rootBox));
|
const scene = (window.scene = new Scene('Validation Pool test', rootBox));
|
||||||
await scene.withSequenceDiagram();
|
scene.withSequenceDiagram();
|
||||||
|
scene.withTable();
|
||||||
const expert1 = (window.expert1 = await new Expert(
|
const expert1 = (window.expert1 = await new Expert(
|
||||||
'Expert1',
|
'Expert1',
|
||||||
scene,
|
scene,
|
||||||
|
@ -31,25 +32,6 @@
|
||||||
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));
|
||||||
|
|
||||||
const updateDisplayValues = async () => {
|
|
||||||
await expert1.setValue(
|
|
||||||
'rep',
|
|
||||||
bench.reputation.valueOwnedBy(expert1.reputationPublicKey),
|
|
||||||
);
|
|
||||||
await expert2.setValue(
|
|
||||||
'rep',
|
|
||||||
bench.reputation.valueOwnedBy(expert2.reputationPublicKey),
|
|
||||||
);
|
|
||||||
await bench.setValue('total rep', bench.reputation.getTotal());
|
|
||||||
// With params.lockingTimeExponent = 0 and params.activeVoterThreshold = null,
|
|
||||||
// these next 3 propetries are all equal to total rep
|
|
||||||
// await bench.setValue('available rep', bench.reputation.getTotalAvailable());
|
|
||||||
// await bench.setValue('active rep', bench.getActiveReputation());
|
|
||||||
// await bench.setValue('active available rep', bench.getActiveAvailableReputation());
|
|
||||||
await scene.sequence.render();
|
|
||||||
};
|
|
||||||
|
|
||||||
updateDisplayValues();
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
|
|
||||||
// First expert can self-approve
|
// First expert can self-approve
|
||||||
|
@ -75,7 +57,6 @@
|
||||||
}
|
}
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
await pool.evaluateWinningConditions(); // Vote passes
|
await pool.evaluateWinningConditions(); // Vote passes
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +69,6 @@
|
||||||
});
|
});
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
await pool.evaluateWinningConditions(); // Quorum not met!
|
await pool.evaluateWinningConditions(); // Quorum not met!
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message.match(/Quorum is not met/)) {
|
if (e.message.match(/Quorum is not met/)) {
|
||||||
|
@ -113,13 +93,8 @@
|
||||||
});
|
});
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
await pool.evaluateWinningConditions(); // Stake passes
|
await pool.evaluateWinningConditions(); // Stake passes
|
||||||
await updateDisplayValues();
|
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
await updateDisplayValues();
|
|
||||||
|
|
||||||
scene.deactivateAll();
|
scene.deactivateAll();
|
||||||
|
|
||||||
await updateDisplayValues();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue