@snapshot-labs/snapshot.js 0.12.52 → 0.12.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3976,36 +3976,46 @@ class CopelandVoting {
3976
3976
  const validVotes = this.getValidVotes();
3977
3977
  const choicesCount = this.proposal.choices.length;
3978
3978
  const pairwiseComparisons = Array.from({ length: choicesCount }, () => Array(choicesCount).fill(0));
3979
+ const totalVotingPower = this.getScoresTotal();
3979
3980
  // Calculate pairwise comparisons
3980
3981
  for (const vote of validVotes) {
3981
- for (let i = 0; i < vote.choice.length; i++) {
3982
- for (let j = i + 1; j < vote.choice.length; j++) {
3983
- const winner = vote.choice[i] - 1;
3984
- const loser = vote.choice[j] - 1;
3985
- pairwiseComparisons[winner][loser] += vote.balance;
3986
- pairwiseComparisons[loser][winner] -= vote.balance;
3982
+ for (let currentRank = 0; currentRank < vote.choice.length; currentRank++) {
3983
+ for (let nextRank = currentRank + 1; nextRank < vote.choice.length; nextRank++) {
3984
+ const preferredChoice = vote.choice[currentRank] - 1;
3985
+ const lowerChoice = vote.choice[nextRank] - 1;
3986
+ pairwiseComparisons[preferredChoice][lowerChoice] += vote.balance;
3987
+ pairwiseComparisons[lowerChoice][preferredChoice] -= vote.balance;
3987
3988
  }
3988
3989
  }
3989
3990
  }
3990
3991
  // Calculate Copeland scores
3991
3992
  const scores = Array(choicesCount).fill(0);
3992
- for (let i = 0; i < choicesCount; i++) {
3993
- for (let j = 0; j < choicesCount; j++) {
3994
- if (i !== j) {
3995
- if (pairwiseComparisons[i][j] > 0) {
3996
- scores[i]++;
3993
+ let totalCopelandScore = 0;
3994
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
3995
+ for (let opponentIndex = 0; opponentIndex < choicesCount; opponentIndex++) {
3996
+ if (choiceIndex !== opponentIndex) {
3997
+ const comparison = pairwiseComparisons[choiceIndex][opponentIndex];
3998
+ if (comparison > 0) {
3999
+ scores[choiceIndex]++;
3997
4000
  }
3998
- else if (pairwiseComparisons[i][j] < 0) {
3999
- scores[j]++;
4001
+ else if (comparison < 0) {
4002
+ scores[opponentIndex]++;
4000
4003
  }
4001
4004
  else {
4002
- scores[i] += 0.5;
4003
- scores[j] += 0.5;
4005
+ scores[choiceIndex] += 0.5;
4006
+ scores[opponentIndex] += 0.5;
4004
4007
  }
4005
4008
  }
4006
4009
  }
4007
4010
  }
4008
- return scores;
4011
+ // Calculate total Copeland score for normalization
4012
+ totalCopelandScore = scores.reduce((sum, score) => sum + score, 0);
4013
+ // Normalize scores to distribute voting power
4014
+ if (totalCopelandScore > 0) {
4015
+ return scores.map((score) => (score / totalCopelandScore) * totalVotingPower);
4016
+ }
4017
+ // If no clear winners, distribute power equally
4018
+ return scores.map(() => totalVotingPower / choicesCount);
4009
4019
  }
4010
4020
  // Calculates the Copeland scores for each choice, broken down by strategy
4011
4021
  getScoresByStrategy() {
@@ -4013,40 +4023,74 @@ class CopelandVoting {
4013
4023
  const choicesCount = this.proposal.choices.length;
4014
4024
  const strategiesCount = this.strategies.length;
4015
4025
  const pairwiseComparisons = Array.from({ length: choicesCount }, () => Array.from({ length: choicesCount }, () => Array(strategiesCount).fill(0)));
4026
+ // Calculate total voting power per strategy
4027
+ const strategyTotals = Array(strategiesCount).fill(0);
4028
+ for (const vote of validVotes) {
4029
+ for (let i = 0; i < strategiesCount; i++) {
4030
+ strategyTotals[i] += vote.scores[i];
4031
+ }
4032
+ }
4016
4033
  // Calculate pairwise comparisons for each strategy
4017
4034
  for (const vote of validVotes) {
4018
- for (let i = 0; i < vote.choice.length; i++) {
4019
- for (let j = i + 1; j < vote.choice.length; j++) {
4020
- const winner = vote.choice[i] - 1;
4021
- const loser = vote.choice[j] - 1;
4022
- for (let s = 0; s < strategiesCount; s++) {
4023
- pairwiseComparisons[winner][loser][s] += vote.scores[s];
4024
- pairwiseComparisons[loser][winner][s] -= vote.scores[s];
4035
+ for (let currentRank = 0; currentRank < vote.choice.length; currentRank++) {
4036
+ for (let nextRank = currentRank + 1; nextRank < vote.choice.length; nextRank++) {
4037
+ const preferredChoice = vote.choice[currentRank] - 1;
4038
+ const lowerChoice = vote.choice[nextRank] - 1;
4039
+ for (let strategyIndex = 0; strategyIndex < strategiesCount; strategyIndex++) {
4040
+ pairwiseComparisons[preferredChoice][lowerChoice][strategyIndex] +=
4041
+ vote.scores[strategyIndex];
4042
+ pairwiseComparisons[lowerChoice][preferredChoice][strategyIndex] -=
4043
+ vote.scores[strategyIndex];
4025
4044
  }
4026
4045
  }
4027
4046
  }
4028
4047
  }
4029
4048
  // Calculate Copeland scores for each strategy
4030
4049
  const scores = Array.from({ length: choicesCount }, () => Array(strategiesCount).fill(0));
4031
- for (let i = 0; i < choicesCount; i++) {
4032
- for (let j = 0; j < choicesCount; j++) {
4033
- if (i !== j) {
4034
- for (let s = 0; s < strategiesCount; s++) {
4035
- if (pairwiseComparisons[i][j][s] > 0) {
4036
- scores[i][s]++;
4050
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4051
+ for (let opponentIndex = 0; opponentIndex < choicesCount; opponentIndex++) {
4052
+ if (choiceIndex !== opponentIndex) {
4053
+ for (let strategyIndex = 0; strategyIndex < strategiesCount; strategyIndex++) {
4054
+ const comparison = pairwiseComparisons[choiceIndex][opponentIndex][strategyIndex];
4055
+ if (comparison > 0) {
4056
+ scores[choiceIndex][strategyIndex]++;
4037
4057
  }
4038
- else if (pairwiseComparisons[i][j][s] < 0) {
4039
- scores[j][s]++;
4058
+ else if (comparison < 0) {
4059
+ scores[opponentIndex][strategyIndex]++;
4040
4060
  }
4041
4061
  else {
4042
- scores[i][s] += 0.5;
4043
- scores[j][s] += 0.5;
4062
+ scores[choiceIndex][strategyIndex] += 0.5;
4063
+ scores[opponentIndex][strategyIndex] += 0.5;
4044
4064
  }
4045
4065
  }
4046
4066
  }
4047
4067
  }
4048
4068
  }
4049
- return scores;
4069
+ // Normalize scores by strategy to distribute voting power
4070
+ const normalizedScores = Array.from({ length: choicesCount }, () => Array(strategiesCount).fill(0));
4071
+ for (let strategyIndex = 0; strategyIndex < strategiesCount; strategyIndex++) {
4072
+ // Calculate total Copeland score for this strategy
4073
+ let totalCopelandScore = 0;
4074
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4075
+ totalCopelandScore += scores[choiceIndex][strategyIndex];
4076
+ }
4077
+ // Normalize scores to distribute voting power for this strategy
4078
+ if (totalCopelandScore > 0) {
4079
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4080
+ normalizedScores[choiceIndex][strategyIndex] =
4081
+ (scores[choiceIndex][strategyIndex] / totalCopelandScore) *
4082
+ strategyTotals[strategyIndex];
4083
+ }
4084
+ }
4085
+ else if (strategyTotals[strategyIndex] > 0) {
4086
+ // If no clear winners, distribute power equally for this strategy
4087
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4088
+ normalizedScores[choiceIndex][strategyIndex] =
4089
+ strategyTotals[strategyIndex] / choicesCount;
4090
+ }
4091
+ }
4092
+ }
4093
+ return normalizedScores;
4050
4094
  }
4051
4095
  // Calculates the total score (sum of all valid vote balances)
4052
4096
  getScoresTotal() {
@@ -3966,36 +3966,46 @@ class CopelandVoting {
3966
3966
  const validVotes = this.getValidVotes();
3967
3967
  const choicesCount = this.proposal.choices.length;
3968
3968
  const pairwiseComparisons = Array.from({ length: choicesCount }, () => Array(choicesCount).fill(0));
3969
+ const totalVotingPower = this.getScoresTotal();
3969
3970
  // Calculate pairwise comparisons
3970
3971
  for (const vote of validVotes) {
3971
- for (let i = 0; i < vote.choice.length; i++) {
3972
- for (let j = i + 1; j < vote.choice.length; j++) {
3973
- const winner = vote.choice[i] - 1;
3974
- const loser = vote.choice[j] - 1;
3975
- pairwiseComparisons[winner][loser] += vote.balance;
3976
- pairwiseComparisons[loser][winner] -= vote.balance;
3972
+ for (let currentRank = 0; currentRank < vote.choice.length; currentRank++) {
3973
+ for (let nextRank = currentRank + 1; nextRank < vote.choice.length; nextRank++) {
3974
+ const preferredChoice = vote.choice[currentRank] - 1;
3975
+ const lowerChoice = vote.choice[nextRank] - 1;
3976
+ pairwiseComparisons[preferredChoice][lowerChoice] += vote.balance;
3977
+ pairwiseComparisons[lowerChoice][preferredChoice] -= vote.balance;
3977
3978
  }
3978
3979
  }
3979
3980
  }
3980
3981
  // Calculate Copeland scores
3981
3982
  const scores = Array(choicesCount).fill(0);
3982
- for (let i = 0; i < choicesCount; i++) {
3983
- for (let j = 0; j < choicesCount; j++) {
3984
- if (i !== j) {
3985
- if (pairwiseComparisons[i][j] > 0) {
3986
- scores[i]++;
3983
+ let totalCopelandScore = 0;
3984
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
3985
+ for (let opponentIndex = 0; opponentIndex < choicesCount; opponentIndex++) {
3986
+ if (choiceIndex !== opponentIndex) {
3987
+ const comparison = pairwiseComparisons[choiceIndex][opponentIndex];
3988
+ if (comparison > 0) {
3989
+ scores[choiceIndex]++;
3987
3990
  }
3988
- else if (pairwiseComparisons[i][j] < 0) {
3989
- scores[j]++;
3991
+ else if (comparison < 0) {
3992
+ scores[opponentIndex]++;
3990
3993
  }
3991
3994
  else {
3992
- scores[i] += 0.5;
3993
- scores[j] += 0.5;
3995
+ scores[choiceIndex] += 0.5;
3996
+ scores[opponentIndex] += 0.5;
3994
3997
  }
3995
3998
  }
3996
3999
  }
3997
4000
  }
3998
- return scores;
4001
+ // Calculate total Copeland score for normalization
4002
+ totalCopelandScore = scores.reduce((sum, score) => sum + score, 0);
4003
+ // Normalize scores to distribute voting power
4004
+ if (totalCopelandScore > 0) {
4005
+ return scores.map((score) => (score / totalCopelandScore) * totalVotingPower);
4006
+ }
4007
+ // If no clear winners, distribute power equally
4008
+ return scores.map(() => totalVotingPower / choicesCount);
3999
4009
  }
4000
4010
  // Calculates the Copeland scores for each choice, broken down by strategy
4001
4011
  getScoresByStrategy() {
@@ -4003,40 +4013,74 @@ class CopelandVoting {
4003
4013
  const choicesCount = this.proposal.choices.length;
4004
4014
  const strategiesCount = this.strategies.length;
4005
4015
  const pairwiseComparisons = Array.from({ length: choicesCount }, () => Array.from({ length: choicesCount }, () => Array(strategiesCount).fill(0)));
4016
+ // Calculate total voting power per strategy
4017
+ const strategyTotals = Array(strategiesCount).fill(0);
4018
+ for (const vote of validVotes) {
4019
+ for (let i = 0; i < strategiesCount; i++) {
4020
+ strategyTotals[i] += vote.scores[i];
4021
+ }
4022
+ }
4006
4023
  // Calculate pairwise comparisons for each strategy
4007
4024
  for (const vote of validVotes) {
4008
- for (let i = 0; i < vote.choice.length; i++) {
4009
- for (let j = i + 1; j < vote.choice.length; j++) {
4010
- const winner = vote.choice[i] - 1;
4011
- const loser = vote.choice[j] - 1;
4012
- for (let s = 0; s < strategiesCount; s++) {
4013
- pairwiseComparisons[winner][loser][s] += vote.scores[s];
4014
- pairwiseComparisons[loser][winner][s] -= vote.scores[s];
4025
+ for (let currentRank = 0; currentRank < vote.choice.length; currentRank++) {
4026
+ for (let nextRank = currentRank + 1; nextRank < vote.choice.length; nextRank++) {
4027
+ const preferredChoice = vote.choice[currentRank] - 1;
4028
+ const lowerChoice = vote.choice[nextRank] - 1;
4029
+ for (let strategyIndex = 0; strategyIndex < strategiesCount; strategyIndex++) {
4030
+ pairwiseComparisons[preferredChoice][lowerChoice][strategyIndex] +=
4031
+ vote.scores[strategyIndex];
4032
+ pairwiseComparisons[lowerChoice][preferredChoice][strategyIndex] -=
4033
+ vote.scores[strategyIndex];
4015
4034
  }
4016
4035
  }
4017
4036
  }
4018
4037
  }
4019
4038
  // Calculate Copeland scores for each strategy
4020
4039
  const scores = Array.from({ length: choicesCount }, () => Array(strategiesCount).fill(0));
4021
- for (let i = 0; i < choicesCount; i++) {
4022
- for (let j = 0; j < choicesCount; j++) {
4023
- if (i !== j) {
4024
- for (let s = 0; s < strategiesCount; s++) {
4025
- if (pairwiseComparisons[i][j][s] > 0) {
4026
- scores[i][s]++;
4040
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4041
+ for (let opponentIndex = 0; opponentIndex < choicesCount; opponentIndex++) {
4042
+ if (choiceIndex !== opponentIndex) {
4043
+ for (let strategyIndex = 0; strategyIndex < strategiesCount; strategyIndex++) {
4044
+ const comparison = pairwiseComparisons[choiceIndex][opponentIndex][strategyIndex];
4045
+ if (comparison > 0) {
4046
+ scores[choiceIndex][strategyIndex]++;
4027
4047
  }
4028
- else if (pairwiseComparisons[i][j][s] < 0) {
4029
- scores[j][s]++;
4048
+ else if (comparison < 0) {
4049
+ scores[opponentIndex][strategyIndex]++;
4030
4050
  }
4031
4051
  else {
4032
- scores[i][s] += 0.5;
4033
- scores[j][s] += 0.5;
4052
+ scores[choiceIndex][strategyIndex] += 0.5;
4053
+ scores[opponentIndex][strategyIndex] += 0.5;
4034
4054
  }
4035
4055
  }
4036
4056
  }
4037
4057
  }
4038
4058
  }
4039
- return scores;
4059
+ // Normalize scores by strategy to distribute voting power
4060
+ const normalizedScores = Array.from({ length: choicesCount }, () => Array(strategiesCount).fill(0));
4061
+ for (let strategyIndex = 0; strategyIndex < strategiesCount; strategyIndex++) {
4062
+ // Calculate total Copeland score for this strategy
4063
+ let totalCopelandScore = 0;
4064
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4065
+ totalCopelandScore += scores[choiceIndex][strategyIndex];
4066
+ }
4067
+ // Normalize scores to distribute voting power for this strategy
4068
+ if (totalCopelandScore > 0) {
4069
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4070
+ normalizedScores[choiceIndex][strategyIndex] =
4071
+ (scores[choiceIndex][strategyIndex] / totalCopelandScore) *
4072
+ strategyTotals[strategyIndex];
4073
+ }
4074
+ }
4075
+ else if (strategyTotals[strategyIndex] > 0) {
4076
+ // If no clear winners, distribute power equally for this strategy
4077
+ for (let choiceIndex = 0; choiceIndex < choicesCount; choiceIndex++) {
4078
+ normalizedScores[choiceIndex][strategyIndex] =
4079
+ strategyTotals[strategyIndex] / choicesCount;
4080
+ }
4081
+ }
4082
+ }
4083
+ return normalizedScores;
4040
4084
  }
4041
4085
  // Calculates the total score (sum of all valid vote balances)
4042
4086
  getScoresTotal() {