Referral Program Re-Implemented
This commit is contained in:
1 parent
c315f1feef
commit
54efa67c9c
5 files changed
+88
-336
No files matched your search
@@ -13,37 +13,39 @@
|
||||
"name": "New Referral Program",
|
||||
"config": "{}",
|
||||
"project": "Governance",
|
||||
"userReferrer": {
|
||||
"type": "User Referrer",
|
||||
"name": "Jeremy",
|
||||
"config": "{}",
|
||||
"project": "Governance",
|
||||
"id": "0d0b04ff-034b-4b02-8351-67d621d514c0",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 25532.618466191747,
|
||||
"y": 23465.846712854385
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 25233.45732703739,
|
||||
"y": 23488.265740930314
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": false,
|
||||
"angleToParent": 2,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
},
|
||||
"uiObject": {},
|
||||
"referenceParent": {
|
||||
"type": "User Profile",
|
||||
"name": "Jeremy",
|
||||
"id": "759e9012-c995-47ed-92f1-7d204bf2b58e"
|
||||
"userReferrers": [
|
||||
{
|
||||
"type": "User Referrer",
|
||||
"name": "Jeremy",
|
||||
"config": "{}",
|
||||
"project": "Governance",
|
||||
"id": "0aa9db01-7605-4a51-abd9-e233de6721d6",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 25532.618466191747,
|
||||
"y": 23465.846712854385
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 25233.45732703739,
|
||||
"y": 23488.265740930314
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": false,
|
||||
"angleToParent": 2,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
},
|
||||
"uiObject": {},
|
||||
"referenceParent": {
|
||||
"type": "User Profile",
|
||||
"name": "Jeremy",
|
||||
"id": "759e9012-c995-47ed-92f1-7d204bf2b58e"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"tokensAwarded": {
|
||||
"type": "Tokens Awarded",
|
||||
"name": "New Tokens Awarded",
|
||||
@@ -106,12 +108,12 @@
|
||||
"id": "0e176a01-3ed2-4b02-b070-601236ea2393",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 25662.630264392985,
|
||||
"y": 23874.32824727054
|
||||
"x": 25429.475731817543,
|
||||
"y": 23702.252371245373
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 25243.737077503094,
|
||||
"y": 23709.924786305663
|
||||
"x": 25150.213607224283,
|
||||
"y": 23592.650063935456
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
@@ -137,12 +139,12 @@
|
||||
"id": "27f046ba-de7c-45a3-9086-d6f4e0ac0fd7",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 25310.806097282373,
|
||||
"y": 24154.89865810697
|
||||
"x": 25194.926287077134,
|
||||
"y": 23889.299311802995
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 25243.737077503094,
|
||||
"y": 23709.924786305663
|
||||
"x": 25150.213607224283,
|
||||
"y": 23592.650063935456
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
@@ -158,8 +160,8 @@
|
||||
"id": "362a1ecb-dce9-4ebb-9b00-a20d3631f2f3",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 25243.737077503094,
|
||||
"y": 23709.924786305663
|
||||
"x": 25150.213607224283,
|
||||
"y": 23592.650063935456
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 24963.166666666664,
|
||||
@@ -168,9 +170,9 @@
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": false,
|
||||
"isCollapsed": true,
|
||||
"angleToParent": 2,
|
||||
"distanceToParent": 4,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
},
|
||||
"uiObject": {
|
||||
|
||||
@@ -13,37 +13,39 @@
|
||||
"name": "New Referral Program",
|
||||
"config": "{}",
|
||||
"project": "Governance",
|
||||
"userReferrer": {
|
||||
"type": "User Referrer",
|
||||
"name": "Julian-Molina",
|
||||
"config": "{}",
|
||||
"project": "Governance",
|
||||
"id": "c96ae419-54ad-4d70-94fe-38833288d471",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 30660.151752050326,
|
||||
"y": 22933.690934849117
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 30550.54944474041,
|
||||
"y": 23212.953059442378
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": false,
|
||||
"angleToParent": 2,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
},
|
||||
"uiObject": {},
|
||||
"referenceParent": {
|
||||
"type": "User Profile",
|
||||
"name": "Julian-Molina",
|
||||
"id": "1fd95e41-4b22-48d5-be3a-904c37afcb11"
|
||||
"userReferrers": [
|
||||
{
|
||||
"type": "User Referrer",
|
||||
"name": "Julian-Molina",
|
||||
"config": "{}",
|
||||
"project": "Governance",
|
||||
"id": "fb0a076c-b0a8-4f16-9a47-10a3f3489a0a",
|
||||
"savedPayload": {
|
||||
"position": {
|
||||
"x": 30660.151752050326,
|
||||
"y": 22933.690934849117
|
||||
},
|
||||
"targetPosition": {
|
||||
"x": 30550.54944474041,
|
||||
"y": 23212.953059442378
|
||||
},
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": false,
|
||||
"angleToParent": 2,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
},
|
||||
"uiObject": {},
|
||||
"referenceParent": {
|
||||
"type": "User Profile",
|
||||
"name": "Julian-Molina",
|
||||
"id": "1fd95e41-4b22-48d5-be3a-904c37afcb11"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"tokensAwarded": {
|
||||
"type": "Tokens Awarded",
|
||||
"name": "New Tokens Awarded",
|
||||
@@ -82,7 +84,7 @@
|
||||
"floatingObject": {
|
||||
"isPinned": false,
|
||||
"isFrozen": false,
|
||||
"isCollapsed": true,
|
||||
"isCollapsed": false,
|
||||
"angleToParent": 1,
|
||||
"distanceToParent": 3,
|
||||
"arrangementStyle": 0
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
{
|
||||
"action": "Add UI Object",
|
||||
"actionProject": "Foundations",
|
||||
"disableIfPropertyIsDefined": true,
|
||||
"propertyToCheckFor": "userReferrer",
|
||||
"actionFunction": "payload.executeAction",
|
||||
"label": "Add User Referrer",
|
||||
"relatedUiObject": "User Referrer"
|
||||
@@ -51,8 +49,8 @@
|
||||
"propertyNameAtParent": "referralProgram",
|
||||
"childrenNodesProperties": [
|
||||
{
|
||||
"name": "userReferrer",
|
||||
"type": "node",
|
||||
"name": "userReferrers",
|
||||
"type": "array",
|
||||
"childType": "User Referrer",
|
||||
"autoAdd": true
|
||||
},
|
||||
|
||||
@@ -9,265 +9,15 @@ function newGovernanceFunctionLibraryReferralProgram() {
|
||||
pools,
|
||||
userProfiles
|
||||
) {
|
||||
/*
|
||||
Here we will store the total amount of tokens that is going to be distributed among all participants
|
||||
of the Referral Program. This will come from a Pool that is configured wiht a codeName config property
|
||||
with the value "Referral-Program"
|
||||
*/
|
||||
let referralProgramPoolTokenReward
|
||||
/*
|
||||
In order to be able to calculate the share of the Referrals Program Pool for each User Profile,
|
||||
we need to accumulate all the Icomming Referral Power that each User Profile at their Referral Program
|
||||
node has, because with that Incoming Power is that each Referral Program node gets a share of
|
||||
the pool.
|
||||
*/
|
||||
let accumulatedIncomingReferralPower = 0
|
||||
|
||||
/* Scan Pools Until finding the Referrla-Program Pool */
|
||||
for (let i = 0; i < pools.length; i++) {
|
||||
let poolsNode = pools[i]
|
||||
referralProgramPoolTokenReward = UI.projects.governance.utilities.pools.findPool(poolsNode, "Referral-Program")
|
||||
}
|
||||
if (referralProgramPoolTokenReward === undefined || referralProgramPoolTokenReward === 0) { return }
|
||||
/*
|
||||
We will first reset all the referral outgoingPower, and then distribute it.
|
||||
*/
|
||||
for (let i = 0; i < userProfiles.length; i++) {
|
||||
let userProfile = userProfiles[i]
|
||||
|
||||
if (userProfile.tokenPowerSwitch === undefined) { continue }
|
||||
if (userProfile.tokenPowerSwitch.referralProgram === undefined) { continue }
|
||||
if (userProfile.tokenPowerSwitch.referralProgram.payload === undefined) { continue }
|
||||
|
||||
reserReferralProgram(userProfile.tokenPowerSwitch.referralProgram)
|
||||
}
|
||||
for (let i = 0; i < userProfiles.length; i++) {
|
||||
let userProfile = userProfiles[i]
|
||||
|
||||
if (userProfile.tokenPowerSwitch === undefined) { continue }
|
||||
if (userProfile.tokenPowerSwitch.referralProgram === undefined) { continue }
|
||||
if (userProfile.tokenPowerSwitch.referralProgram.payload === undefined) { continue }
|
||||
|
||||
distributeReferralProgram(userProfile.tokenPowerSwitch.referralProgram)
|
||||
}
|
||||
for (let i = 0; i < userProfiles.length; i++) {
|
||||
let userProfile = userProfiles[i]
|
||||
|
||||
if (userProfile.tokenPowerSwitch === undefined) { continue }
|
||||
if (userProfile.tokenPowerSwitch.referralProgram === undefined) { continue }
|
||||
if (userProfile.tokenPowerSwitch.referralProgram.payload === undefined) { continue }
|
||||
|
||||
calculateReferralProgram(userProfile.tokenPowerSwitch.referralProgram)
|
||||
}
|
||||
|
||||
function reserReferralProgram(node) {
|
||||
if (node === undefined) { return }
|
||||
if (node.payload === undefined) { return }
|
||||
node.payload.referralProgram = {
|
||||
count: 0,
|
||||
outgoingPower: 0,
|
||||
ownPower: 0,
|
||||
incomingPower: 0,
|
||||
awarded: {
|
||||
tokens: 0,
|
||||
percentage: 0
|
||||
}
|
||||
}
|
||||
if (
|
||||
node.type === 'User Profile' &&
|
||||
node.tokenPowerSwitch !== undefined
|
||||
) {
|
||||
reserReferralProgram(node.tokenPowerSwitch)
|
||||
return
|
||||
}
|
||||
if (
|
||||
node.type === 'Token Power Switch' &&
|
||||
node.referralProgram !== undefined
|
||||
) {
|
||||
reserReferralProgram(node.referralProgram)
|
||||
return
|
||||
}
|
||||
if (
|
||||
node.type === 'Referral Program' &&
|
||||
node.userReferrer !== undefined
|
||||
) {
|
||||
reserReferralProgram(node.userReferrer)
|
||||
return
|
||||
}
|
||||
if (
|
||||
node.type === 'User Referrer' &&
|
||||
node.payload.referenceParent !== undefined
|
||||
) {
|
||||
reserReferralProgram(node.payload.referenceParent)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function distributeReferralProgram(referralProgram) {
|
||||
if (referralProgram === undefined || referralProgram.payload === undefined) { return }
|
||||
/*
|
||||
Here we will convert Token Power into Referral Power.
|
||||
As per system rules referringPower = tokensPower
|
||||
*/
|
||||
let referringPower = referralProgram.payload.tokenPower
|
||||
/*
|
||||
We will also reseet the count of referrals here.
|
||||
*/
|
||||
let count = 0
|
||||
/*
|
||||
The Own Power is the power generated by the same User Profile tokens, not inherited from others.
|
||||
*/
|
||||
referralProgram.payload.referralProgram.ownPower = referringPower
|
||||
|
||||
distributeReferralPower(referralProgram, referringPower, count)
|
||||
}
|
||||
|
||||
function distributeReferralPower(
|
||||
node,
|
||||
referringPower,
|
||||
count
|
||||
) {
|
||||
|
||||
if (node === undefined) { return }
|
||||
if (node.payload === undefined) { return }
|
||||
|
||||
switch (node.type) {
|
||||
case 'Referral Program': {
|
||||
/*
|
||||
This is the point where we increase to our local count of referrals whatever it comes
|
||||
at the count parameters. If we are processing the User Profile of this Referral Program
|
||||
then we will add zero, otherwise, 1.
|
||||
*/
|
||||
node.payload.referralProgram.count = node.payload.referralProgram.count + count
|
||||
/*
|
||||
The outgoingPower of this node will be accumulating all the referringPower flowing
|
||||
through it, no matter from where it comes.
|
||||
*/
|
||||
node.payload.referralProgram.outgoingPower = node.payload.referralProgram.outgoingPower + referringPower
|
||||
/*
|
||||
We need to adjust the balance that holds the accumulationt of all incomingPower of all Referral 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.
|
||||
*/
|
||||
accumulatedIncomingReferralPower = accumulatedIncomingReferralPower - node.payload.referralProgram.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.referralProgram.incomingPower = node.payload.referralProgram.outgoingPower - node.payload.referralProgram.ownPower
|
||||
/*
|
||||
Now that we have the incomingPower calculated again, we can add it again to the balance of all the incomingPower
|
||||
of all Referral Program nodes.
|
||||
*/
|
||||
accumulatedIncomingReferralPower = accumulatedIncomingReferralPower + node.payload.referralProgram.incomingPower
|
||||
|
||||
if (node.userReferrer !== undefined) {
|
||||
distributeReferralPower(node.userReferrer, referringPower, 0)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'User Referrer': {
|
||||
drawUserReferrer(node)
|
||||
if (node.payload.referenceParent !== undefined) {
|
||||
distributeReferralPower(node.payload.referenceParent, referringPower / 10, 0)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'User Profile': {
|
||||
if (node.tokenPowerSwitch !== undefined) {
|
||||
distributeReferralPower(node.tokenPowerSwitch, referringPower, 0)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Token Power Switch': {
|
||||
if (node.referralProgram !== undefined) {
|
||||
distributeReferralPower(node.referralProgram, referringPower, 1)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calculateReferralProgram(referralProgram) {
|
||||
/*
|
||||
Here we will calculate which share of the Referral Program Pool this user will get in tokens.
|
||||
To do that, we use the incomingPower, to see which proportion of the accumulatedIncomingReferralPower
|
||||
represents.
|
||||
*/
|
||||
if (referralProgram.payload === undefined) { return }
|
||||
/*
|
||||
If the accumulatedIncomingReferralPower is not grater the amount of tokens at the Referral Program Pool, then
|
||||
this user will get the exact amount of tokens from the pool as incomingPower he has.
|
||||
|
||||
If the accumulatedIncomingReferralPower is grater the amount of tokens at the Referral Program Pool, then
|
||||
the amount ot tokens to be received is a proportional to the share of incomingPower in accumulatedIncomingReferralPower.
|
||||
*/
|
||||
let totalPowerRewardRatio = accumulatedIncomingReferralPower / referralProgramPoolTokenReward
|
||||
if (totalPowerRewardRatio < 1) { totalPowerRewardRatio = 1 }
|
||||
|
||||
if (referralProgram.tokensAwarded === undefined || referralProgram.tokensAwarded.payload === undefined) {
|
||||
referralProgram.payload.uiObject.setErrorMessage("Tokens Awarded Node is needed in order for this Program to get Tokens from the Referral Program Pool.")
|
||||
return
|
||||
}
|
||||
referralProgram.payload.referralProgram.awarded.tokens = referralProgram.payload.referralProgram.incomingPower * totalPowerRewardRatio
|
||||
/*
|
||||
As per the system rules, the Referral Program will not give tokens to users that do not ha their own Referrer set up,
|
||||
unless it has a big amount of tokens (this last condition is for the edge case where a user it at the top of the
|
||||
referral pyramid.)
|
||||
*/
|
||||
if (
|
||||
referralProgram.payload.referralProgram.ownPower < 1000000 &&
|
||||
(referralProgram.userReferrer === undefined || referralProgram.userReferrer.payload.referenceParent === undefined)
|
||||
) {
|
||||
|
||||
referralProgram.payload.uiObject.setErrorMessage("In order to be awarded " + referralProgram.payload.referralProgram.awarded.tokens + " SA Tokens from your referrals, you need first to define yourself who your referrer is.")
|
||||
referralProgram.payload.referralProgram.awarded.tokens = 0
|
||||
}
|
||||
|
||||
drawReferralProgram(referralProgram)
|
||||
}
|
||||
|
||||
function drawUserReferrer(node) {
|
||||
if (node.payload !== undefined) {
|
||||
const ownPowerText = new Intl.NumberFormat().format(node.payload.parentNode.payload.referralProgram.ownPower)
|
||||
const incomingPowerText = new Intl.NumberFormat().format(node.payload.parentNode.payload.referralProgram.incomingPower)
|
||||
const outgoingPowerText = new Intl.NumberFormat().format(node.payload.parentNode.payload.referralProgram.outgoingPower)
|
||||
|
||||
node.payload.uiObject.valueAngleOffset = 180
|
||||
node.payload.uiObject.valueAtAngle = true
|
||||
|
||||
node.payload.uiObject.setValue(outgoingPowerText + ' ' + 'Referring Power')
|
||||
|
||||
node.payload.uiObject.statusAngleOffset = 0
|
||||
node.payload.uiObject.statusAtAngle = false
|
||||
|
||||
node.payload.uiObject.setStatus(ownPowerText + ' Own RP + ' + incomingPowerText + ' Incoming RP = ' + outgoingPowerText + ' ' + ' Outgoing RP')
|
||||
}
|
||||
}
|
||||
|
||||
function drawReferralProgram(node) {
|
||||
if (node.payload !== undefined) {
|
||||
|
||||
node.payload.uiObject.statusAngleOffset = 0
|
||||
node.payload.uiObject.statusAtAngle = false
|
||||
|
||||
node.payload.uiObject.setStatus("Referring Power = Token Power")
|
||||
}
|
||||
if (node.tokensAwarded !== undefined && node.tokensAwarded.payload !== undefined) {
|
||||
|
||||
const tokensAwardedText = new Intl.NumberFormat().format(node.payload.referralProgram.awarded.tokens)
|
||||
|
||||
node.tokensAwarded.payload.uiObject.statusAngleOffset = 0
|
||||
node.tokensAwarded.payload.uiObject.statusAtAngle = false
|
||||
node.tokensAwarded.payload.uiObject.valueAngleOffset = 0
|
||||
node.tokensAwarded.payload.uiObject.valueAtAngle = false
|
||||
|
||||
node.tokensAwarded.payload.uiObject.setValue(tokensAwardedText + ' SA Tokens')
|
||||
node.tokensAwarded.payload.uiObject.setStatus('From '+ node.payload.referralProgram.count + ' Referrals.')
|
||||
}
|
||||
}
|
||||
UI.projects.governance.utilities.mandatoryProgram.run(
|
||||
pools,
|
||||
userProfiles,
|
||||
"referralProgram",
|
||||
"Referral-Program",
|
||||
"Referral Program",
|
||||
"Referral Power",
|
||||
"userReferrers",
|
||||
"User Referrer"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -356,7 +356,7 @@ function newFoundationsUtilitiesMandatoryProgram() {
|
||||
node.tokensAwarded.payload.uiObject.valueAtAngle = false
|
||||
|
||||
node.tokensAwarded.payload.uiObject.setValue(tokensAwardedText + ' SA Tokens')
|
||||
node.tokensAwarded.payload.uiObject.setStatus('From ' + node.payload[programPropertyName].count + ' Mentees.')
|
||||
node.tokensAwarded.payload.uiObject.setStatus('From ' + node.payload[programPropertyName].count + ' Descendants.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user