diff --git a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json index ce213c04b..32e9c885a 100644 --- a/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json +++ b/Projects/Governance/Plugins/User-Profiles/Luis-Fernando-Molina.json @@ -287,7 +287,7 @@ "floatingObject": { "isPinned": false, "isFrozen": false, - "isCollapsed": false, + "isCollapsed": true, "angleToParent": 1, "distanceToParent": 3, "arrangementStyle": 0 @@ -313,7 +313,7 @@ { "type": "Feature Claims Folder", "name": "Data Mining Feature Class", - "config": "{}", + "config": "{\n \"percentage\": 70\n}", "project": "Governance", "featureClaimsFolders": [], "featureContributionClaims": [ @@ -325,12 +325,12 @@ "id": "edf1a5c9-7802-4856-918c-3cd5a7a9caf7", "savedPayload": { "position": { - "x": 30339.990954013265, - "y": 24468.938639855496 + "x": 30718.661945753065, + "y": 24284.862061411382 }, "targetPosition": { - "x": 30197.830355271366, - "y": 24204.759980298473 + "x": 30463.457926046864, + "y": 24127.15693046823 }, "floatingObject": { "isPinned": false, @@ -352,12 +352,12 @@ "id": "ebad23ed-1a02-4edf-a9d7-fc4b2fd0dacb", "savedPayload": { "position": { - "x": 30197.830355271366, - "y": 24204.759980298473 + "x": 30463.457926046864, + "y": 24127.15693046823 }, "targetPosition": { - "x": 30055.669756529467, - "y": 23940.58132074145 + "x": 30208.253906340662, + "y": 23969.45179952508 }, "floatingObject": { "isPinned": false, @@ -387,12 +387,12 @@ "id": "e745f3cd-4cd9-421b-b9ab-f62650fb56f8", "savedPayload": { "position": { - "x": 30015.399776784172, - "y": 24237.866249271832 + "x": 30322.02154513654, + "y": 24247.043089667277 }, "targetPosition": { - "x": 30055.669756529467, - "y": 23940.58132074145 + "x": 30208.253906340662, + "y": 23969.45179952508 }, "floatingObject": { "isPinned": false, @@ -422,12 +422,12 @@ "id": "3ae7f0f9-be37-4e6c-b3b1-4343e51f80a9", "savedPayload": { "position": { - "x": 29848.350961833406, - "y": 24157.419779889668 + "x": 30137.12979302601, + "y": 24260.89881101294 }, "targetPosition": { - "x": 30055.669756529467, - "y": 23940.58132074145 + "x": 30208.253906340662, + "y": 23969.45179952508 }, "floatingObject": { "isPinned": false, @@ -457,12 +457,12 @@ "id": "d8ab7844-f98f-4ce1-a634-c0ff98af28ca", "savedPayload": { "position": { - "x": 29760.490879949877, - "y": 23994.148389181042 + "x": 29979.405034781983, + "y": 24163.431679889818 }, "targetPosition": { - "x": 30055.669756529467, - "y": 23940.58132074145 + "x": 30208.253906340662, + "y": 23969.45179952508 }, "floatingObject": { "isPinned": false, @@ -487,8 +487,8 @@ "id": "f8a482c4-dee0-475a-831b-7514fd255ba6", "savedPayload": { "position": { - "x": 30055.669756529467, - "y": 23940.58132074145 + "x": 30208.253906340662, + "y": 23969.45179952508 }, "targetPosition": { "x": 30185.834878264734, @@ -498,7 +498,7 @@ "isPinned": false, "isFrozen": false, "isCollapsed": false, - "angleToParent": 1, + "angleToParent": 2, "distanceToParent": 3, "arrangementStyle": 0 }, @@ -514,6 +514,31 @@ } ], "positionClaimsFolders": [], + "tokensAwarded": { + "type": "Tokens Awarded", + "name": "New Tokens Awarded", + "project": "Governance", + "id": "5011109c-3f87-471a-b786-5fd371f53853", + "savedPayload": { + "position": { + "x": 29937.963245969935, + "y": 23839.28667778981 + }, + "targetPosition": { + "x": 30185.834878264734, + "y": 23670.290660370723 + }, + "floatingObject": { + "isPinned": false, + "isFrozen": false, + "isCollapsed": false, + "angleToParent": 2, + "distanceToParent": 3, + "arrangementStyle": 0 + }, + "uiObject": {} + } + }, "id": "796dd30f-c90d-4b8d-a63d-89867347407b", "savedPayload": { "position": { diff --git a/Projects/Governance/UI/Function-Libraries/Claims.js b/Projects/Governance/UI/Function-Libraries/ClaimsProgram.js similarity index 55% rename from Projects/Governance/UI/Function-Libraries/Claims.js rename to Projects/Governance/UI/Function-Libraries/ClaimsProgram.js index 0674b44c0..1e80fe46f 100644 --- a/Projects/Governance/UI/Function-Libraries/Claims.js +++ b/Projects/Governance/UI/Function-Libraries/ClaimsProgram.js @@ -31,19 +31,30 @@ function newGovernanceFunctionLibraryClaimsProgram() { resetClaims(positionsNode) } + /* Reset this Program */ + for (let i = 0; i < userProfiles.length; i++) { + let userProfile = userProfiles[i] + + if (userProfile.tokenPowerSwitch === undefined) { continue } + if (userProfile.tokenPowerSwitch.claimsProgram === undefined) { continue } + if (userProfile.tokenPowerSwitch.claimsProgram.payload === undefined) { continue } + + resetProgram(userProfile.tokenPowerSwitch.claimsProgram) + } + /* Claim Count Follows */ for (let i = 0; i < userProfiles.length; i++) { let userProfile = userProfiles[i] if (userProfile.payload === undefined) { continue } if (userProfile.tokenPowerSwitch === undefined) { continue } if (userProfile.tokenPowerSwitch.claimsProgram === undefined) { continue } - userProfile.payload.claims = { + userProfile.payload.claimsProgram = { awarded: { tokens: 0 }, count: 0 } - countForNode(userProfile.tokenPowerSwitch.claimsProgram) + countProgram(userProfile.tokenPowerSwitch.claimsProgram) } /* Claim Calculation Follows */ @@ -52,7 +63,7 @@ function newGovernanceFunctionLibraryClaimsProgram() { if (userProfile.payload === undefined) { continue } if (userProfile.tokenPowerSwitch === undefined) { continue } if (userProfile.tokenPowerSwitch.claimsProgram === undefined) { continue } - calculateForNode(userProfile.tokenPowerSwitch.claimsProgram, userProfile) + distributeProgram(userProfile.tokenPowerSwitch.claimsProgram, userProfile) } function resetClaims(node) { @@ -65,7 +76,7 @@ function newGovernanceFunctionLibraryClaimsProgram() { node.type !== 'Position Class' ) { if (node.payload.votes !== undefined) { - node.payload.claims = { + node.payload.claimsProgram = { count: 0, votes: 0 } @@ -99,44 +110,19 @@ function newGovernanceFunctionLibraryClaimsProgram() { } } - function countForNode(node) { + function resetProgram(node) { if (node === undefined) { return } if (node.payload === undefined) { return } - if ( - node.type !== 'Asset Claims Folder' && - node.type !== 'Feature Claims Folder' && - node.type !== 'Position Claims Folder' && - node.type !== 'Claims Program' - ) { - if (node.payload.claims === undefined) { - node.payload.claims = { - count: 0, - awarded: { - tokens: 0, - percentage: 0 - }, - share: { - count: 0, - percentage: 0 - } - } - } - - if ( - node.payload.votes !== undefined && - node.payload.votes > 0 && - node.payload.referenceParent !== undefined && - node.payload.referenceParent.payload !== undefined && - node.payload.referenceParent.payload.votes !== undefined && - node.payload.referenceParent.payload.votes > 0 && - node.payload.referenceParent.payload.weight !== undefined && - node.payload.referenceParent.payload.weight > 0 && - node.payload.referenceParent.payload.claims.count !== undefined && - node.payload.referenceParent.payload.claims.votes !== undefined - ) { - node.payload.referenceParent.payload.claims.count++ - node.payload.referenceParent.payload.claims.votes = node.payload.referenceParent.payload.claims.votes + node.payload.votes + node.payload.claimsProgram = { + count: 0, + awarded: { + tokens: 0, + percentage: 0 + }, + share: { + count: 0, + percentage: 0 } } @@ -149,7 +135,7 @@ function newGovernanceFunctionLibraryClaimsProgram() { switch (property.type) { case 'node': { let childNode = node[property.name] - countForNode(childNode) + resetProgram(childNode) } break case 'array': { @@ -157,7 +143,7 @@ function newGovernanceFunctionLibraryClaimsProgram() { if (propertyArray !== undefined) { for (let m = 0; m < propertyArray.length; m++) { let childNode = propertyArray[m] - countForNode(childNode) + resetProgram(childNode) } } break @@ -167,7 +153,7 @@ function newGovernanceFunctionLibraryClaimsProgram() { } } - function calculateForNode(node, userProfile) { + function countProgram(node) { if (node === undefined) { return } if (node.payload === undefined) { return } @@ -178,7 +164,6 @@ function newGovernanceFunctionLibraryClaimsProgram() { node.type !== 'Claims Program' ) { if ( - node.payload.claims !== undefined && node.payload.votes !== undefined && node.payload.votes > 0 && node.payload.referenceParent !== undefined && @@ -187,8 +172,83 @@ function newGovernanceFunctionLibraryClaimsProgram() { node.payload.referenceParent.payload.votes > 0 && node.payload.referenceParent.payload.weight !== undefined && node.payload.referenceParent.payload.weight > 0 && - node.payload.referenceParent.payload.claims.count !== undefined && - node.payload.referenceParent.payload.claims.votes !== undefined + node.payload.referenceParent.payload.claimsProgram.count !== undefined && + node.payload.referenceParent.payload.claimsProgram.votes !== undefined + ) { + node.payload.referenceParent.payload.claimsProgram.count++ + node.payload.referenceParent.payload.claimsProgram.votes = node.payload.referenceParent.payload.claimsProgram.votes + node.payload.votes + } + } + + let schemaDocument = getSchemaDocument(node) + if (schemaDocument === undefined) { return } + + if (schemaDocument.childrenNodesProperties !== undefined) { + for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) { + let property = schemaDocument.childrenNodesProperties[i] + switch (property.type) { + case 'node': { + let childNode = node[property.name] + countProgram(childNode) + } + break + case 'array': { + let propertyArray = node[property.name] + if (propertyArray !== undefined) { + for (let m = 0; m < propertyArray.length; m++) { + let childNode = propertyArray[m] + countProgram(childNode) + } + } + break + } + } + } + } + } + + function distributeProgram(programNode, userProfile) { + if (programNode === undefined || programNode.payload === undefined) { return } + /* + Here we will convert Token Power into programPower. + As per system rules programPower = tokensPower + */ + let programPower = programNode.payload.tokenPower + /* + The Own Power is the power generated by the same User Profile tokens, not inherited from others. + */ + programNode.payload.claimsProgram.ownPower = programPower + + distributeProgramPower(programNode, programPower, userProfile) + } + + function distributeProgramPower( + node, + programPower, + userProfile, + percentage + ) { + if (node === undefined) { return } + if (node.payload === undefined) { return } + + if ( + node.type !== 'Asset Claims Folder' && + node.type !== 'Feature Claims Folder' && + node.type !== 'Position Claims Folder' && + node.type !== 'Claims Program' + ) { + if ( + node.payload.claimsProgram !== undefined && + node.payload.votes !== undefined && + node.payload.votes > 0 && + node.payload.referenceParent !== undefined && + node.payload.referenceParent.payload !== undefined && + node.payload.referenceParent.payload.votes !== undefined && + node.payload.referenceParent.payload.votes > 0 && + node.payload.referenceParent.payload.weight !== undefined && + node.payload.referenceParent.payload.weight > 0 && + node.payload.referenceParent.payload.claimsProgram.count !== undefined && + node.payload.referenceParent.payload.claimsProgram.votes !== undefined ) { /* We will use the concept of Vote Reward Claims Ratio for the situation in which the @@ -196,69 +256,165 @@ function newGovernanceFunctionLibraryClaimsProgram() { the Votes Rewards Claims Ratio will be used to redude the amount of tokens awarded proportionally to how much was exeeded. */ - let votesRatio = node.payload.referenceParent.payload.votes / node.payload.referenceParent.payload.claims.votes + let votesRatio = node.payload.referenceParent.payload.votes / node.payload.referenceParent.payload.claimsProgram.votes if (votesRatio > 1) { votesRatio = 1 } /* Share Count means the amount to claims pointing to the same potential tokens reward. */ - node.payload.claims.share.count = node.payload.referenceParent.payload.claims.count - node.payload.claims.share.percentage = node.payload.votes * 100 / node.payload.referenceParent.payload.claims.votes - node.payload.claims.awarded.tokens = + node.payload.claimsProgram.share.count = node.payload.referenceParent.payload.claimsProgram.count + node.payload.claimsProgram.share.percentage = node.payload.votes * 100 / node.payload.referenceParent.payload.claimsProgram.votes + node.payload.claimsProgram.awarded.tokens = Math.min( node.payload.votes / node.payload.referenceParent.payload.votes * node.payload.referenceParent.payload.tokens * votesRatio, node.payload.votes ) - node.payload.claims.awarded.percentage = node.payload.claims.awarded.tokens / node.payload.referenceParent.payload.tokens * 100 + node.payload.claimsProgram.awarded.percentage = node.payload.claimsProgram.awarded.tokens / node.payload.referenceParent.payload.tokens * 100 - userProfile.payload.claims.awarded.tokens = userProfile.payload.claims.awarded.tokens + node.payload.claims.awarded.tokens - userProfile.payload.claims.count++ + userProfile.payload.claimsProgram.awarded.tokens = userProfile.payload.claimsProgram.awarded.tokens + node.payload.claimsProgram.awarded.tokens + userProfile.payload.claimsProgram.count++ drawClaims(node, userProfile) + drawProgramPower(node, programPower, percentage) } + } else { + if (node.type === 'Claims Program') { + drawProgram(node) + } else { + drawProgramPower(node, programPower, percentage) + } + } let schemaDocument = getSchemaDocument(node) if (schemaDocument === undefined) { return } - - if (schemaDocument.childrenNodesProperties !== undefined) { - for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) { - let property = schemaDocument.childrenNodesProperties[i] - switch (property.type) { - case 'node': { - let childNode = node[property.name] - calculateForNode(childNode, userProfile) + if (schemaDocument.childrenNodesProperties === undefined) { return } + /* + Before distributing the claim 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 < schemaDocument.childrenNodesProperties.length; i++) { + let property = schemaDocument.childrenNodesProperties[i] + switch (property.type) { + case 'node': { + let childNode = node[property.name] + if (childNode === undefined) { continue } + let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') + if (percentage !== undefined && isNaN(percentage) !== true) { + totalPercentage = totalPercentage + percentage + } else { + totalNodesWithoutPercentage++ } - break - case 'array': { - let propertyArray = node[property.name] - if (propertyArray !== undefined) { - for (let m = 0; m < propertyArray.length; m++) { - let childNode = propertyArray[m] - calculateForNode(childNode, userProfile) + } + break + case 'array': { + let propertyArray = node[property.name] + if (propertyArray !== undefined) { + for (let m = 0; m < propertyArray.length; m++) { + let childNode = propertyArray[m] + if (childNode === undefined) { continue } + let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') + if (percentage !== undefined && isNaN(percentage) !== true) { + totalPercentage = totalPercentage + percentage + } else { + totalNodesWithoutPercentage++ } } - break } + break + } + } + } + if (totalPercentage > 100) { + node.payload.uiObject.setErrorMessage('Claim Power Switching Error. Total Percentage of children nodes is grater that 100.') + return + } + let defaultPercentage = 0 + if (totalNodesWithoutPercentage > 0) { + defaultPercentage = (100 - totalPercentage) / totalNodesWithoutPercentage + } + for (let i = 0; i < schemaDocument.childrenNodesProperties.length; i++) { + let property = schemaDocument.childrenNodesProperties[i] + switch (property.type) { + case 'node': { + let childNode = node[property.name] + if (childNode === undefined) { continue } + let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') + if (percentage === undefined || isNaN(percentage) === true) { + percentage = defaultPercentage + } + distributeProgramPower(childNode, programPower * percentage / 100, userProfile, percentage) + } + break + case 'array': { + let propertyArray = node[property.name] + if (propertyArray !== undefined) { + for (let m = 0; m < propertyArray.length; m++) { + let childNode = propertyArray[m] + if (childNode === undefined) { continue } + let percentage = UI.projects.foundations.utilities.nodeConfig.loadConfigProperty(childNode.payload, 'percentage') + if (percentage === undefined || isNaN(percentage) === true) { + percentage = defaultPercentage + } + distributeProgramPower(childNode, programPower * percentage / 100, userProfile, percentage) + } + } + break } } } } function drawClaims(node, userProfile) { - let satatus = - new Intl.NumberFormat().format(node.payload.claims.awarded.tokens) + + let status = + new Intl.NumberFormat().format(node.payload.claimsProgram.awarded.tokens) + ' ' + 'SA Tokens Awarded' + ' - ' + - 'From Reward: ' + node.payload.claims.awarded.percentage.toFixed(2) + '%' + ' - ' + - 'Shared Between: ' + node.payload.claims.share.count + ' claims' + ' - ' + - 'Share of Claims: ' + node.payload.claims.share.percentage.toFixed(2) + '%' + 'From Reward: ' + node.payload.claimsProgram.awarded.percentage.toFixed(2) + '%' + ' - ' + + 'Shared Between: ' + node.payload.claimsProgram.share.count + ' claims' + ' - ' + + 'Share of Claims: ' + node.payload.claimsProgram.share.percentage.toFixed(2) + '%' - node.payload.uiObject.setStatus(satatus) + node.payload.uiObject.setStatus(status) + } - satatus = new Intl.NumberFormat().format(userProfile.payload.claims.awarded.tokens) + - ' ' + 'SA Tokens Awarded' + - ' from ' + userProfile.payload.claims.count + ' Claims' + function drawProgram(node) { + if (node.payload !== undefined) { - userProfile.payload.uiObject.setValue(satatus) + const ownPowerText = new Intl.NumberFormat().format(node.payload.claimsProgram.ownPower) + + node.payload.uiObject.statusAngleOffset = 0 + node.payload.uiObject.statusAtAngle = false + + node.payload.uiObject.setStatus(ownPowerText + ' Claims Power') + } + if (node.tokensAwarded !== undefined && node.tokensAwarded.payload !== undefined) { + + const tokensAwardedText = new Intl.NumberFormat().format(node.payload.claimsProgram.awarded.tokens) + + node.tokensAwarded.payload.uiObject.valueAngleOffset = 0 + node.tokensAwarded.payload.uiObject.valueAtAngle = false + + node.tokensAwarded.payload.uiObject.setValue(tokensAwardedText + ' SA Tokens') + } + } + + function drawProgramPower(node, programPower, percentage) { + const programPowerText = new Intl.NumberFormat().format(programPower) + ' ' + 'Claim Power' + if (node.payload !== undefined) { + + node.payload.uiObject.valueAngleOffset = 180 + node.payload.uiObject.valueAtAngle = true + node.payload.uiObject.percentageAngleOffset = 180 + node.payload.uiObject.percentageAtAngle = true + + node.payload.uiObject.setValue(programPowerText) + + if (percentage !== undefined) { + node.payload.uiObject.setPercentage(percentage.toFixed(2)) + } + } } } diff --git a/Projects/Governance/UI/Function-Libraries/Votes.js b/Projects/Governance/UI/Function-Libraries/Votes.js index 8fd3e57ae..11b7c034d 100644 --- a/Projects/Governance/UI/Function-Libraries/Votes.js +++ b/Projects/Governance/UI/Function-Libraries/Votes.js @@ -129,14 +129,14 @@ function newGovernanceFunctionLibraryVotes() { function distributeVotingProgram(votingProgram) { if (votingProgram.payload === undefined) { return } let votes = votingProgram.payload.votes - distributeVotes(votingProgram, votes) + distributeProgramPower(votingProgram, votes) } - function distributeVotes(node, votes, switchPercentage) { + function distributeProgramPower(node, votes, percentage) { if (node === undefined) { return } if (node.payload === undefined) { return } node.payload.votes = node.payload.votes + votes - drawVotes(node, node.payload.votes, switchPercentage) + drawVotes(node, node.payload.votes, percentage) /* When we reach certain node types, we will halt the distribution, because these are targets for voting power. @@ -161,7 +161,7 @@ function newGovernanceFunctionLibraryVotes() { node.type !== 'Weight Votes Switch' && node.type !== 'User Profile Votes Switch' ) { - distributeVotes(node.payload.referenceParent, votes) + distributeProgramPower(node.payload.referenceParent, votes) return } /* @@ -241,7 +241,7 @@ function newGovernanceFunctionLibraryVotes() { if (percentage === undefined || isNaN(percentage) === true) { percentage = defaultPercentage } - distributeVotes(childNode, votes * percentage / 100, percentage) + distributeProgramPower(childNode, votes * percentage / 100, percentage) } } break @@ -255,7 +255,7 @@ function newGovernanceFunctionLibraryVotes() { if (percentage === undefined || isNaN(percentage) === true) { percentage = defaultPercentage } - distributeVotes(childNode, votes * percentage / 100, percentage) + distributeProgramPower(childNode, votes * percentage / 100, percentage) } } break diff --git a/Projects/Governance/UI/Utilities/MandatoryProgram.js b/Projects/Governance/UI/Utilities/MandatoryProgram.js index 5e4e9ab3f..348128590 100644 --- a/Projects/Governance/UI/Utilities/MandatoryProgram.js +++ b/Projects/Governance/UI/Utilities/MandatoryProgram.js @@ -164,8 +164,8 @@ function newFoundationsUtilitiesMandatoryProgram() { function distributeProgram(programNode) { if (programNode === undefined || programNode.payload === undefined) { return } /* - Here we will convert Token Power into programPowerName. - As per system rules programPowerName = tokensPower + Here we will convert Token Power into programPower. + As per system rules programPower = tokensPower */ let programPower = programNode.payload.tokenPower /*