From 476a1798f6073796d0a6daf6a042614d971cf8b6 Mon Sep 17 00:00:00 2001 From: Luis Fernando Molina Date: Tue, 20 Jul 2021 14:42:54 +0200 Subject: [PATCH] Bonus Program Bug Fixed for Descendants Program --- .../Plugins/User-Profiles/Julian-Molina.json | 8 +- .../User-Profiles/Luis-Fernando-Molina.json | 15 +- .../UI/Function-Libraries/ReferralProgram.js | 17 +- .../Governance/UI/Utilities/BonusProgram.js | 15 +- .../UI/Utilities/DecendentProgram.js | 202 ++++++++++-------- 5 files changed, 133 insertions(+), 124 deletions(-) diff --git a/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json b/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json index 72a7a2e99..97150731e 100644 --- a/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Julian-Molina.json @@ -12,12 +12,12 @@ "referralProgram": { "type": "Referral Program", "name": "New Referral Program", - "config": "{\n \"percentage\": 60\n}", + "config": "{\n \"percentage\": 2}", "project": "Governance", "userReferrers": [ { "type": "User Referrer", - "name": "Jeremy", + "name": "Luis-Fernando-Molina", "config": "{}", "project": "Governance", "id": "0aa9db01-7605-4a51-abd9-e233de6721d6", @@ -43,8 +43,8 @@ }, "referenceParent": { "type": "User Profile", - "name": "Jeremy", - "id": "759e9012-c995-47ed-92f1-7d204bf2b58e" + "name": "Luis-Fernando-Molina", + "id": "148911b3-b2f3-44fb-8cb4-017991789132" } } } diff --git a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json index 6387faa0f..373c7b7ae 100644 --- a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json @@ -18,12 +18,12 @@ "referralProgram": { "type": "Referral Program", "name": "New Referral Program", - "config": "{\n \"percentage\": 80\n}", + "config": "{\n \"percentage\": 0\n}", "project": "Governance", "userReferrers": [ { "type": "User Referrer", - "name": "Julian-Molina", + "name": "Jeremy", "config": "{}", "project": "Governance", "id": "fb0a076c-b0a8-4f16-9a47-10a3f3489a0a", @@ -49,8 +49,8 @@ }, "referenceParent": { "type": "User Profile", - "name": "Julian-Molina", - "id": "1fd95e41-4b22-48d5-be3a-904c37afcb11" + "name": "Jeremy", + "id": "759e9012-c995-47ed-92f1-7d204bf2b58e" } } } @@ -3936,7 +3936,7 @@ "userDelegates": [ { "type": "User Delegate", - "name": "Julian-Molina", + "name": "", "config": "{}", "project": "Governance", "id": "d684a95b-fc8a-4545-8db5-601128a924cf", @@ -3959,11 +3959,6 @@ }, "uiObject": { "isRunning": false - }, - "referenceParent": { - "type": "User Profile", - "name": "Julian-Molina", - "id": "1fd95e41-4b22-48d5-be3a-904c37afcb11" } } }, diff --git a/Projects/Governance/UI/Function-Libraries/ReferralProgram.js b/Projects/Governance/UI/Function-Libraries/ReferralProgram.js index 028ee9a57..9ebd8fef8 100644 --- a/Projects/Governance/UI/Function-Libraries/ReferralProgram.js +++ b/Projects/Governance/UI/Function-Libraries/ReferralProgram.js @@ -9,15 +9,6 @@ function newGovernanceFunctionLibraryReferralProgram() { pools, userProfiles ) { - - UI.projects.governance.utilities.bonusProgram.run( - pools, - userProfiles, - "referralProgram", - "Referrals-Bonus", - "Referral Program" - ) - UI.projects.governance.utilities.decendentProgram.run( pools, userProfiles, @@ -28,5 +19,13 @@ function newGovernanceFunctionLibraryReferralProgram() { "userReferrers", "User Referrer" ) + + UI.projects.governance.utilities.bonusProgram.run( + pools, + userProfiles, + "referralProgram", + "Referrals-Bonus", + "Referral Program" + ) } } \ No newline at end of file diff --git a/Projects/Governance/UI/Utilities/BonusProgram.js b/Projects/Governance/UI/Utilities/BonusProgram.js index 30424c290..bf394da2f 100644 --- a/Projects/Governance/UI/Utilities/BonusProgram.js +++ b/Projects/Governance/UI/Utilities/BonusProgram.js @@ -15,7 +15,7 @@ function newGovernanceUtilitiesBonusProgram() { let programPoolTokenReward /* In order to be able to calculate the share of the Program Pool for each User Profile, - we need to accumulate all the Participation Power that each User Profile at their Program + we need to accumulate all the Bonus Power that each User Profile at their Program node has, because with that Power is that each Program node gets a share of the pool. */ let accumulatedProgramPower = 0 @@ -108,13 +108,12 @@ function newGovernanceUtilitiesBonusProgram() { function distributeProgram(programNode) { if (programNode === undefined || programNode.payload === undefined) { return } /* - Here we will convert Token Power into Participation Power. - As per system rules Participation Powar = tokensPower + To get into the Bonus Sub-Program we will use the usedPower previously calculated by the Program. + That means that only token power effectively used at the program (not just directed to it) will + be used to compute Bonuses. */ - let programPower = programNode.payload.tokenPower - programNode.payload[programPropertyName].bonusPower = programPower - - accumulatedProgramPower = accumulatedProgramPower + programPower + programNode.payload[programPropertyName].bonusPower = programNode.payload[programPropertyName].usedPower | 0 + accumulatedProgramPower = accumulatedProgramPower + programNode.payload[programPropertyName].bonusPower } function calculateProgram(programNode) { @@ -135,7 +134,7 @@ function newGovernanceUtilitiesBonusProgram() { if (totalPowerRewardRatio < 1) { totalPowerRewardRatio = 1 } if (programNode.tokensBonus === undefined || programNode.tokensBonus.payload === undefined) { - programNode.payload.uiObject.setErrorMessage("Tokens Bonus Node is needed in order for this Program to get Tokens from the Program Pool.") + programNode.payload.uiObject.setErrorMessage("Tokens Bonus Node is needed in order for this Program to get Tokens from the Bonus Program Pool.") return } programNode.payload[programPropertyName].bonus.tokens = programNode.payload[programPropertyName].bonusPower * totalPowerRewardRatio diff --git a/Projects/Governance/UI/Utilities/DecendentProgram.js b/Projects/Governance/UI/Utilities/DecendentProgram.js index 92845a712..37c037e24 100644 --- a/Projects/Governance/UI/Utilities/DecendentProgram.js +++ b/Projects/Governance/UI/Utilities/DecendentProgram.js @@ -1,4 +1,9 @@ function newGovernanceUtilitiesDecendentProgram() { + /* + This Utility Module is intended to be used by all programs that have the + concept of Decendents, and when the program requires to compute recursively + all decendents. + */ let thisObject = { run: run } @@ -91,6 +96,7 @@ function newGovernanceUtilitiesDecendentProgram() { outgoingPower: 0, ownPower: 0, incomingPower: 0, + usedPower: 0, awarded: { tokens: 0, percentage: 0 @@ -102,6 +108,7 @@ function newGovernanceUtilitiesDecendentProgram() { node.payload[programPropertyName].outgoingPower = 0 node.payload[programPropertyName].ownPower = 0 node.payload[programPropertyName].incomingPower = 0 + node.payload[programPropertyName].usedPower = 0 node.payload[programPropertyName].awarded = { tokens: 0, percentage: 0 @@ -193,109 +200,118 @@ function newGovernanceUtilitiesDecendentProgram() { */ programNode.payload[programPropertyName].ownPower = programPower - distributeProgramPower(programNode, programPower, count) - } + distributeProgramPower(programNode, programNode, programPower, count) - function distributeProgramPower( - node, - programPower, - count, - percentage - ) { - if (node === undefined) { return } - if (node.payload === undefined) { return } - if (node.payload[programPropertyName] === undefined) { return } + function distributeProgramPower( + currentProgramNode, + node, + programPower, + count, + percentage + ) { + if (node === undefined) { return } + if (node.payload === undefined) { return } + if (node.payload[programPropertyName] === undefined) { return } - switch (node.type) { - case programNodeType: { - /* - This is the point where we increase to our local count of descendents whatever it comes - at the count parameters. If we are processing the User Profile of this Program - then we will add zero, otherwise, 1. - */ - node.payload[programPropertyName].count = node.payload[programPropertyName].count + count - /* - The outgoingPower of this node will be accumulating all the programPower flowing - through it, no matter from where it comes. - */ - node.payload[programPropertyName].outgoingPower = node.payload[programPropertyName].outgoingPower + programPower - /* - We need to adjust the balance that holds the accumulationt of all incomingPower of all Program - nodes. To do this we will substratct the current incomingPower, bacause it is going to be recalculated - inmediatelly after this, and then we will add it again after the recalcualtion. - */ - accumulatedIncomingProgramPower = accumulatedIncomingProgramPower - node.payload[programPropertyName].incomingPower - /* - At any point in time, the incomingPower will be equal to the total of the outgoingPower minus - the ownPower. This is like this because the outgoingPower is the accumulation of all the - power flow that is leaving this node, which includes the ownPower. That means that if we - substract the ownPower, we will have the accumulation of all the incomingPower, which - means all the power coming from other User Profiles referencing this one. - */ - node.payload[programPropertyName].incomingPower = node.payload[programPropertyName].outgoingPower - node.payload[programPropertyName].ownPower - /* - Now that we have the incomingPower calculated again, we can add it again to the balance of all the incomingPower - of all Program nodes. - */ - accumulatedIncomingProgramPower = accumulatedIncomingProgramPower + node.payload[programPropertyName].incomingPower - - if (node[usersArrayPropertyName] !== undefined) { + switch (node.type) { + case programNodeType: { /* - Before distributing the program power, we will calculate how the power - is going to be switched between all nodes. The first pass is about - scanning all sibling nodes to see which ones have a percentage defined - at their config, and check that all percentages don't add more than 100. + This is the point where we increase to our local count of descendents whatever it comes + at the count parameters. If we are processing the User Profile of this Program + then we will add zero, otherwise, 1. */ - let totalPercentage = 0 - let totalNodesWithoutPercentage = 0 - for (let i = 0; i < node[usersArrayPropertyName].length; i++) { - let childNode = node[usersArrayPropertyName][i] - let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') - if (percentage !== undefined && isNaN(percentage) !== true) { - totalPercentage = totalPercentage + percentage - } else { - totalNodesWithoutPercentage++ + node.payload[programPropertyName].count = node.payload[programPropertyName].count + count + /* + The outgoingPower of this node will be accumulating all the programPower flowing + through it, no matter from where it comes. + */ + node.payload[programPropertyName].outgoingPower = node.payload[programPropertyName].outgoingPower + programPower + /* + We need to adjust the balance that holds the accumulationt of all incomingPower of all Program + nodes. To do this we will substratct the current incomingPower, bacause it is going to be recalculated + inmediatelly after this, and then we will add it again after the recalcualtion. + */ + accumulatedIncomingProgramPower = accumulatedIncomingProgramPower - node.payload[programPropertyName].incomingPower + /* + At any point in time, the incomingPower will be equal to the total of the outgoingPower minus + the ownPower. This is like this because the outgoingPower is the accumulation of all the + power flow that is leaving this node, which includes the ownPower. That means that if we + substract the ownPower, we will have the accumulation of all the incomingPower, which + means all the power coming from other User Profiles referencing this one. + */ + node.payload[programPropertyName].incomingPower = node.payload[programPropertyName].outgoingPower - node.payload[programPropertyName].ownPower + /* + Now that we have the incomingPower calculated again, we can add it again to the balance of all the incomingPower + of all Program nodes. + */ + accumulatedIncomingProgramPower = accumulatedIncomingProgramPower + node.payload[programPropertyName].incomingPower + + if (node[usersArrayPropertyName] !== undefined) { + /* + Before distributing the program power, we will calculate how the power + is going to be switched between all nodes. The first pass is about + scanning all sibling nodes to see which ones have a percentage defined + at their config, and check that all percentages don't add more than 100. + */ + let totalPercentage = 0 + let totalNodesWithoutPercentage = 0 + for (let i = 0; i < node[usersArrayPropertyName].length; i++) { + let childNode = node[usersArrayPropertyName][i] + let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') + if (percentage !== undefined && isNaN(percentage) !== true) { + totalPercentage = totalPercentage + percentage + } else { + totalNodesWithoutPercentage++ + } + } + if (totalPercentage > 100) { + node.payload.uiObject.setErrorMessage('Program Power Switching Error. Total Percentage of children nodes is grater that 100.') + return + } + let defaultPercentage = 0 + if (totalNodesWithoutPercentage > 0) { + defaultPercentage = (100 - totalPercentage) / totalNodesWithoutPercentage + } + /* + Here we do the actual distribution. + */ + for (let i = 0; i < node[usersArrayPropertyName].length; i++) { + let childNode = node[usersArrayPropertyName][i] + let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') + if (percentage === undefined || isNaN(percentage) === true) { + percentage = defaultPercentage + } + distributeProgramPower(currentProgramNode, childNode, programPower * percentage / 100, 0, percentage) } } - if (totalPercentage > 100) { - node.payload.uiObject.setErrorMessage('Program Power Switching Error. Total Percentage of children nodes is grater that 100.') - return - } - let defaultPercentage = 0 - if (totalNodesWithoutPercentage > 0) { - defaultPercentage = (100 - totalPercentage) / totalNodesWithoutPercentage - } - /* - Here we do the actual distribution. - */ - for (let i = 0; i < node[usersArrayPropertyName].length; i++) { - let childNode = node[usersArrayPropertyName][i] - let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') - if (percentage === undefined || isNaN(percentage) === true) { - percentage = defaultPercentage - } - distributeProgramPower(childNode, programPower * percentage / 100, 0, percentage) - } + return } - return - } - case userNodeType: { - node.payload[programPropertyName].outgoingPower = node.payload.parentNode.payload[programPropertyName].outgoingPower * percentage / 100 + case userNodeType: { + let previousOutgoing = node.payload[programPropertyName].outgoingPower + node.payload[programPropertyName].outgoingPower = node.payload.parentNode.payload[programPropertyName].outgoingPower * percentage / 100 - drawUserNode(node, percentage) - if (node.payload.referenceParent !== undefined) { - distributeProgramPower(node.payload.referenceParent, programPower / 10, 0) + drawUserNode(node, percentage) + if (node.payload.referenceParent !== undefined) { + /* + We want to accumulate the usedPower, but to keep the right balance, everytime we add to it the outgoingPower + we need to substract the previous one, since this migth be executed at every user profile and also recurisvely. + */ + currentProgramNode.payload[programPropertyName].usedPower = currentProgramNode.payload[programPropertyName].usedPower - previousOutgoing + currentProgramNode.payload[programPropertyName].usedPower = currentProgramNode.payload[programPropertyName].usedPower + node.payload[programPropertyName].outgoingPower + + distributeProgramPower(currentProgramNode, node.payload.referenceParent, programPower / 10, 0) + } + return } - return - } - case 'User Profile': { - let program = UI.projects.governance.utilities.validations.onlyOneProgram(node, programNodeType) - if (program === undefined) { return } - if (program.payload === undefined) { return } - if (program.payload[programPropertyName].isActive === false) { return } + case 'User Profile': { + let program = UI.projects.governance.utilities.validations.onlyOneProgram(node, programNodeType) + if (program === undefined) { return } + if (program.payload === undefined) { return } + if (program.payload[programPropertyName].isActive === false) { return } - distributeProgramPower(program, programPower, 0) - return + distributeProgramPower(program, program, programPower, 0) + return + } } } }