Browse Source

Add more fills to the council report

Ricardo Maltez 4 years ago
parent
commit
b766f788e5

+ 2 - 1
council/report-generator/.gitignore

@@ -1,4 +1,5 @@
 .idea/*
 lib/*
 node_modules
-yarn.lock
+yarn.lock
+report.md

+ 19 - 19
council/report-generator/report-template.md

@@ -2,8 +2,8 @@
 This is a report which explains the current state of the Joystream network in numbers. It pulls figures from the chain and tries to provide a basic level of information about the network, tokens and more. 
 
 ## 1.0 Basic Information
-* Date Range: DD/MM/YYYY - DD/MM/YYYY
-* Council session #: XX
+* Date Range: {dateStart} - {dateEnd}
+* Council session #: {councilRound}
 * Starting block: {startBlock}
 * Block range: {startBlock} - {endBlock}
 
@@ -17,23 +17,23 @@ This is a report which explains the current state of the Joystream network in nu
 ### 1.2 Token + USD Information
 | Property       | This Session | All Sessions | % Change |
 |----------------|--------------|--------------|----------|
-| Token Issuance | {newIssuance}|              |          |
-| Token Burn     | {newTokensBurn}    |              |          |
-| USD Backing    | {usdBacking} |              |          |
+| Token Issuance | {newIssuance}   | {totalIssuance}| {percNewIssuance}|
+| Token Burn     | {newTokensBurn} |              |          |
+| USD Backing    |                 |              |          |
 
 ### 1.3 Membership Information
 | Property          | This Session | All Sessions | % Change |
 |-------------------|--------------|--------------|----------|
-| Number of members | {NR_MEMBERS}             |              |          |
+| Number of members |{newMembers}  |{totalMembers}|{percNewMembers}|
 
 ## 2.0 Tokenomics
 ### 2.1 Token generation breakdown
 | Property                    | This Session | All Sessions | % Change |
 |-----------------------------|--------------|--------------|----------|
-| Total Tokens Minted        |              |              |          |
-| Validator Role        |              |              |          |
-| Storage Role       |              |              |          |
-| Council Role |              |              |          |
+| Total Tokens Minted         |              |              |          |
+| Validator Role              |              |              |          |
+| Storage Role                |              |              |          |
+| Council Role                |              |              |          |
 
 ### 2.2 Mints 
 | Property                    | This Session | All Sessions | % Change |
@@ -44,16 +44,16 @@ This is a report which explains the current state of the Joystream network in nu
 | Curator Mint Total Minted |              |              |          |
 
 ## 3.0 Council
-* Council session #: XX
-* Number of council members:
-* Total number of proposals:
+* Council session #: {councilRound}
+* Number of council members: {councilMembers}
+* Total number of proposals: {newProposals}
 ### 3.1 Elections
 | Property                    | This Session | All Sessions | % Change |
 |-----------------------------|--------------|--------------|----------|
-| Total Applicants       |              |              |          |
-| Total Applicant Stake       |              |              |          |
-| Total Votes       |              |              |          |
-| Avg Votes per Applicant       |              |              |          |
+| Total Applicants            |{councilApplicants}|{councilAvgApplicants}||
+| Total Applicant Stake       |{councilApplicants}|              |          |
+| Total Votes                 |                   |              |          |
+| Avg Votes per Applicant     |                   |              |          |
 
 ### 3.2 Proposals
 | Proposal Type                           | # of proposals during this session | Total number of proposal type |
@@ -109,8 +109,8 @@ This is a report which explains the current state of the Joystream network in nu
 ### 5.2 Forum Activity
 | Property          | This Session | All Sessions | % Change |
 |-------------------|--------------|--------------|----------|
-| Number of threads | {newThreads} |{totalThreads}|          |
-| Number of posts   | {newPosts}   |{totalPosts}  |          |
+| Number of threads | {newThreads} |{totalThreads}| {percNewThreads}|
+| Number of posts   | {newPosts}   |{totalPosts}  | {percNewPosts}|
 
 ## 6 Todo / Ideas
 * Video duration

+ 29 - 3
council/report-generator/src/StatisticsData.ts

@@ -1,16 +1,42 @@
 export class StatisticsData {
+    councilRound: number;
+    councilMembers: number;
+
+    councilApplicants: number;
+    councilAvgApplicants: number;
+    perCouncilApplicants: number;
+
+    dateStart: string;
+    dateEnd: string;
+
     startBlock: number;
     endBlock: number;
     percNewBlocks: number
 
+    newIssuance: number;
+    totalIssuance: number;
+    percNewIssuance: number;
+
+    newMembers: number;
+    totalMembers: number;
+    percNewMembers: number;
+
+
+
     newBlocks: number;
     avgBlockProduction: number;
     nrValidators: number;
-    newPosts: number;
+
     newThreads: number;
+    totalThreads: number;
+    percNewThreads: number;
+
+    newPosts: number;
+    totalPosts: number;
+    percNewPosts: number;
+
     newCategories: number;
-    totalIssuance: number;
-    newMembers: number;
+
     newProposals: number;
     newMedia: number;
     deletedMedia: number;

+ 87 - 0
council/report-generator/src/block-interval.ts

@@ -0,0 +1,87 @@
+import {ApiPromise, WsProvider} from "@polkadot/api";
+import {Hash, Header} from "@polkadot/types/interfaces/runtime";
+import {registerJoystreamTypes} from "@joystream/types/lib";
+
+async function main() {
+    let startDate = new Date(2020, 4, 20, 13, 0);
+    let endDate = new Date(2020, 4, 29, 23, 59);
+
+    // Initialise the provider to connect to the local node
+    const provider = new WsProvider('wss://rome-rpc-endpoint.joystream.org:9944');
+
+    // register types before creating the api
+    registerJoystreamTypes();
+
+    // Create the API and wait until ready
+    const api = await ApiPromise.create({provider});
+
+    let blockInterval = await getBlockInterval(api, startDate.getTime(), endDate.getTime());
+
+}
+
+async function getBlockInterval(api: ApiPromise, startTimestamp: number, endTimestamp: number) {
+
+    let approximateStartBlockHash = await getApproximatedBlockHash(api, startTimestamp);
+    let startBlock = await adjustApproximatedBlockHash(api, startTimestamp, approximateStartBlockHash);
+
+    let approximateEndBlockHash = await getApproximatedBlockHash(api, endTimestamp);
+    let endBlock = await adjustApproximatedBlockHash(api, endTimestamp, approximateEndBlockHash);
+
+    let startBlockHeader = await api.rpc.chain.getHeader(startBlock) as Header;
+    let endBlockHeader = await api.rpc.chain.getHeader(endBlock) as Header;
+
+    return {
+        'startBlock':
+            startBlockHeader.number.unwrap().toNumber(),
+        'endBlock':
+            endBlockHeader.number.unwrap().toNumber()
+    };
+}
+
+async function getApproximatedBlockHash(api: ApiPromise, timestampToFound: number): Promise<Hash> {
+    let lastHeader = await api.rpc.chain.getHeader();
+    let lastHash = lastHeader.hash.toString();
+    let lastTimestamp = parseInt((await api.query.timestamp.now.at(lastHash)).toString());
+
+    let prevousBlockHash = lastHeader.parentHash;
+    let previousBlockTimestamp = parseInt((await api.query.timestamp.now.at(prevousBlockHash)).toString());
+
+    let secondsPerBlock = lastTimestamp - previousBlockTimestamp;
+
+    let blocksDiff = Math.floor((lastTimestamp - timestampToFound) / secondsPerBlock);
+    let lastBlockNumber = lastHeader.number.unwrap();
+    let approximatedBlockNr = lastBlockNumber.toNumber() - blocksDiff;
+    return await api.rpc.chain.getBlockHash(approximatedBlockNr);
+}
+
+async function adjustApproximatedBlockHash(api: ApiPromise, timestamp: number, hash: Hash) {
+    let approximatedBlockTimestamp = parseInt((await api.query.timestamp.now.at(hash)).toString());
+
+    if (timestamp == approximatedBlockTimestamp) {
+        return hash;
+    }
+
+    let step = 1;
+    if (timestamp < approximatedBlockTimestamp) {
+        step = -1;
+    }
+
+    let approximatedBlockHeader = await api.rpc.chain.getHeader(hash);
+    let blockNumber = approximatedBlockHeader.number.unwrap().toNumber();
+    let lastHashFound = hash;
+    do {
+        blockNumber += step;
+        let nextBlockHash = await api.rpc.chain.getBlockHash(blockNumber);
+        let nextBlockTimeStamp = parseInt((await api.query.timestamp.now.at(nextBlockHash)).toString());
+
+        if (Math.abs(approximatedBlockTimestamp - timestamp) < Math.abs(nextBlockTimeStamp - timestamp)) {
+            return lastHashFound;
+        }
+
+        approximatedBlockTimestamp = nextBlockTimeStamp;
+        lastHashFound = nextBlockHash;
+
+    } while (true);
+}
+
+main();

+ 43 - 12
council/report-generator/src/statistics.ts

@@ -1,7 +1,7 @@
 import {rpc} from "@polkadot/types/interfaces/definitions";
 import {ApiPromise, WsProvider} from "@polkadot/api";
 import {registerJoystreamTypes} from '@joystream/types';
-import {Balance, Hash, Moment} from "@polkadot/types/interfaces";
+import {AccountId, Balance, Hash, Moment} from "@polkadot/types/interfaces";
 import {ClassId, ClassPropertyValue, Entity} from "@joystream/types/lib/versioned-store";
 import {Mint} from "@joystream/types/lib/mint";
 import {Option, u32, Vec} from "@polkadot/types";
@@ -12,9 +12,11 @@ import {CategoryId, PostId, ThreadId} from "@joystream/types/lib/forum";
 import {MemberId} from "@joystream/types/lib/members";
 import number from "@polkadot/util/is/number";
 import {StatisticsData} from "./StatisticsData";
+import {Seats} from "@joystream/types/lib/proposals";
 
 const BURN_ADDRESS = '5D5PhZQNJzcJXVBxwJxZcsutjKPqUPydrvpu6HeiBfMaeKQu';
 
+const FIRST_COUNCIL_BLOCK = 908796;
 
 class Media {
 
@@ -26,23 +28,51 @@ export class StatisticsCollector {
     static async getStatistics(startBlock: number, endBlock: number): Promise<StatisticsData> {
 
         // Initialise the provider to connect to the local node
-        const provider = new WsProvider('wss://rome-rpc-endpoint.joystream.org:9944');
+        // const provider = new WsProvider('ws://127.0.0.1:9944');
 
+        const provider = new WsProvider('ws://127.0.0.1:9944');
         // register types before creating the api
         registerJoystreamTypes();
 
         // Create the API and wait until ready
         const api = await ApiPromise.create({provider});
 
+        let startHash = await api.rpc.chain.getBlockHash(startBlock);
+        let endHash = await api.rpc.chain.getBlockHash(endBlock);
+
         let statistics = new StatisticsData();
 
+        statistics.councilRound = (await api.query.councilElection.round.at(startHash) as u32).toNumber() - 5;
+        let seats = await api.query.council.activeCouncil.at(startHash) as Seats;
+
+        statistics.councilMembers = seats.length;
+        let applicants = await api.query.councilElection.applicants() as Vec<AccountId>;
+        statistics.councilApplicants = applicants.length;
+
+        let startDate = await api.query.timestamp.now.at(startHash) as Moment;
+        let endDate = await api.query.timestamp.now.at(endHash) as Moment;
+
+        statistics.dateStart = new Date(startDate.toNumber()).toLocaleDateString("en-US");
+        statistics.dateEnd = new Date(endDate.toNumber()).toLocaleDateString("en-US");
+
         statistics.startBlock = startBlock;
         statistics.endBlock = endBlock;
         statistics.newBlocks = endBlock - startBlock;
-        statistics.percNewBlocks = Number((statistics.newBlocks / endBlock * 100).toFixed(2));
+        statistics.percNewBlocks = this.convertToPercentage(statistics.newBlocks, endBlock);
+
+
+        let startIssuance = await api.query.balances.totalIssuance.at(startHash) as unknown as Balance;
+        let endIssuance = await api.query.balances.totalIssuance.at(endHash) as unknown as Balance;
+        statistics.newIssuance = endIssuance.toNumber() - startIssuance.toNumber();
+        statistics.totalIssuance = endIssuance.toNumber();
+        statistics.percNewIssuance = this.convertToPercentage(statistics.newIssuance, statistics.totalIssuance);
+
+        let startNrMembers = await api.query.members.membersCreated.at(startHash) as unknown as MemberId;
+        let endNrNumber = await api.query.members.membersCreated.at(endHash) as unknown as MemberId;
+        statistics.newMembers = endNrNumber.toNumber() - startNrMembers.toNumber();
+        statistics.totalMembers = endNrNumber.toNumber();
+        statistics.percNewMembers = this.convertToPercentage(statistics.newMembers, statistics.totalMembers);
 
-        let startHash = await api.rpc.chain.getBlockHash(startBlock);
-        let endHash = await api.rpc.chain.getBlockHash(endBlock);
 
         let startNrStakes = await api.query.stake.stakesCreated.at(startHash) as StakeId;
         let endNrStakes = await api.query.stake.stakesCreated.at(endHash) as StakeId;
@@ -110,22 +140,19 @@ export class StatisticsCollector {
         let startPostId = await api.query.forum.nextPostId.at(startHash) as unknown as PostId;
         let endPostId = await api.query.forum.nextPostId.at(endHash) as unknown as PostId;
         statistics.newPosts = endPostId.toNumber() - startPostId.toNumber();
+        statistics.totalPosts = endPostId.toNumber() - 1;
+        statistics.percNewPosts = this.convertToPercentage(statistics.newPosts, statistics.totalPosts);
 
         let startThreadId = await api.query.forum.nextThreadId.at(startHash) as unknown as ThreadId;
         let endThreadId = await api.query.forum.nextThreadId.at(endHash) as unknown as ThreadId;
         statistics.newThreads = endThreadId.toNumber() - startThreadId.toNumber();
+        statistics.totalThreads = endThreadId.toNumber() - 1;
+        statistics.percNewThreads = this.convertToPercentage(statistics.newThreads, statistics.totalThreads);
 
         let startCategoryId = await api.query.forum.nextCategoryId.at(startHash) as unknown as CategoryId;
         let endCategoryId = await api.query.forum.nextCategoryId.at(endHash) as unknown as CategoryId;
         statistics.newCategories = endCategoryId.toNumber() - startCategoryId.toNumber();
 
-        let startIssuance = await api.query.balances.totalIssuance.at(startHash) as unknown as Balance;
-        let endIssuance = await api.query.balances.totalIssuance.at(endHash) as unknown as Balance;
-        statistics.totalIssuance = Number(endIssuance.toNumber() - startIssuance.toNumber());
-
-        let startNrMembers = await api.query.members.membersCreated.at(startHash) as unknown as MemberId;
-        let endNrNumber = await api.query.members.membersCreated.at(endHash) as unknown as MemberId;
-        statistics.newMembers = endNrNumber.toNumber() - startNrMembers.toNumber();
 
         let startNrProposals = await api.query.proposalsEngine.proposalCount.at(startHash) as unknown as u32;
         let endNrProposals = await api.query.proposalsEngine.proposalCount.at(endHash) as unknown as u32;
@@ -135,6 +162,10 @@ export class StatisticsCollector {
         return statistics;
     }
 
+   static convertToPercentage(value: number, totalValue: number): number{
+        return Number((value / totalValue * 100).toFixed(2));
+    }
+
 
     static async computeUsedSpaceInBytes(api: ApiPromise, contentIds: Vec<ContentId>) {