From c4e6dfc239b11630b175a5166aac29e84050d888 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Tue, 2 Aug 2022 00:43:09 +0200 Subject: [PATCH 01/10] Implement --minimum_consensus parameter for vca reward command Value in range [0.5, 1] The minimum consensus for a vCA ranking to be excluded from eligible rankings when in disagreement from simple majority. Simple majority is 50%. Qualified majority is 70%. Using 70% avoids punishing vCAs where the consensus is not clear. 70% is because when #vca == 3 consensus is only 66% and thus in this case, where there is just 1 vote in disagreement, all 3 vCAs get rewarded. --- .../src/bin/cli/rewards/veterans.rs | 14 +++ catalyst-toolbox/src/rewards/veterans.rs | 98 ++++++++++++++++--- 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs index 8c2c157e..c82687d7 100644 --- a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs +++ b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs @@ -62,6 +62,14 @@ pub struct VeteransRewards { /// if the first cutoff is selected then the first modifier is used. #[structopt(long, required = true)] reputation_agreement_rate_modifiers: Vec, + + /// Value in range [0.5, 1] + /// The minimum consensus for a vCA ranking to be excluded from eligible rankings when in disagreement from simple majority. + /// Simple majority is 50%. + /// Qualified majority is 70%. Using 70% avoids punishing vCAs where the consensus is not clear. + /// 70% is because when #vca == 3 consensus is only 66% and thus in this case, where there is just 1 vote in disagreement, all 3 vCAs get rewarded. + #[structopt(long = "minimum_consensus")] + minimum_consensus: Decimal, } impl VeteransRewards { @@ -77,6 +85,7 @@ impl VeteransRewards { rewards_agreement_rate_modifiers, reputation_agreement_rate_cutoffs, reputation_agreement_rate_modifiers, + minimum_consensus, } = self; let reviews: Vec = csv::load_data_from_csv::<_, b','>(&from)?; @@ -100,6 +109,10 @@ impl VeteransRewards { bail!("Expected rewards_agreement_rate_cutoffs to be descending"); } + if minimum_consensus < Decimal::new(5,1) || minimum_consensus > Decimal::ONE { + bail!("Expected minimum_consensus to range between .5 and 1"); + } + let results = veterans::calculate_veteran_advisors_incentives( &reviews, total_rewards, @@ -113,6 +126,7 @@ impl VeteransRewards { .into_iter() .zip(reputation_agreement_rate_modifiers.into_iter()) .collect(), + Decimal::from(minimum_consensus), ); csv::dump_data_to_csv(rewards_to_csv_data(results).iter(), &to).unwrap(); diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index 76cc9d3a..982c4597 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -77,6 +77,27 @@ fn calc_final_eligible_rankings( .collect() } +fn calc_final_ranking_consensus_per_review(rankings: &[impl Borrow]) -> Decimal { + let rankings_majority = Decimal::from(rankings.len()) / Decimal::from(2); + let ranks = rankings.iter().counts_by(|r| r.borrow().score()); + + match (ranks.get(&FilteredOut), ranks.get(&Excellent), ranks.get(&Good)) { + (Some(filtered_out), _, _) if Decimal::from(*filtered_out) >= rankings_majority => { + Decimal::from(*filtered_out) / Decimal::from(rankings.len()) + } + (_, Some(excellent), _) if Decimal::from(*excellent) > rankings_majority => { + Decimal::from(*excellent) / Decimal::from(rankings.len()) + } + (_, Some(excellent), Some(good)) => { + (Decimal::from(*excellent) + Decimal::from(*good)) / Decimal::from(rankings.len()) + } + (_, _, Some(good)) => { + Decimal::from(*good) / Decimal::from(rankings.len()) + } + _ => Decimal::ONE, + } +} + pub fn calculate_veteran_advisors_incentives( veteran_rankings: &[VeteranRankingRow], total_rewards: Rewards, @@ -84,6 +105,7 @@ pub fn calculate_veteran_advisors_incentives( reputation_thresholds: EligibilityThresholds, rewards_mod_args: Vec<(Decimal, Decimal)>, reputation_mod_args: Vec<(Decimal, Decimal)>, + minimum_consensus: Decimal, ) -> HashMap { let final_rankings_per_review = veteran_rankings .iter() @@ -92,6 +114,13 @@ pub fn calculate_veteran_advisors_incentives( .map(|(review, rankings)| (review, calc_final_ranking_per_review(&rankings))) .collect::>(); + let final_rankings_consensus_per_review = veteran_rankings + .iter() + .into_group_map_by(|ranking| ranking.review_id()) + .into_iter() + .map(|(review, rankings)| (review, calc_final_ranking_consensus_per_review(&rankings))) + .collect::>(); + let rankings_per_vca = veteran_rankings .iter() .counts_by(|ranking| ranking.vca.clone()); @@ -103,7 +132,7 @@ pub fn calculate_veteran_advisors_incentives( .get(&ranking.review_id()) .unwrap() .is_positive() - == ranking.score().is_positive() + == ranking.score().is_positive() || *final_rankings_consensus_per_review.get(&ranking.review_id()).unwrap() < minimum_consensus }) .counts_by(|ranking| ranking.vca.clone()); @@ -156,6 +185,8 @@ mod tests { const VCA_1: &str = "vca1"; const VCA_2: &str = "vca2"; const VCA_3: &str = "vca3"; + const SIMPLE_MINIMUM_CONSENSUS: Decimal = dec!(.5); + const QUALIFIED_MINIMUM_CONSENSUS: Decimal = dec!(.7); struct RandomIterator; impl Iterator for RandomIterator { @@ -231,6 +262,7 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), + SIMPLE_MINIMUM_CONSENSUS, ); assert!(results.get(VCA_1).is_none()); let res = results.get(VCA_2).unwrap(); @@ -260,6 +292,7 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), + SIMPLE_MINIMUM_CONSENSUS, ); let res1 = results.get(VCA_1).unwrap(); assert_eq!(res1.reputation, 1); @@ -283,12 +316,12 @@ mod tests { (Rewards::new(8, 1), Rewards::ONE, Rewards::ONE), (Rewards::new(9, 1), Rewards::new(125, 2), Rewards::ONE), ]; - for (agreement, reward_modifier, reputation_modifier) in inputs { + for (vca3_agreement, reward_modifier, reputation_modifier) in inputs { let rankings = (0..100) .flat_map(|i| { let vcas = vec![VCA_1.to_owned(), VCA_2.to_owned(), VCA_3.to_owned()].into_iter(); - let (good, filtered_out) = if Rewards::from(i) < agreement * Rewards::from(100) + let (good, filtered_out) = if Rewards::from(i) < vca3_agreement * Rewards::from(100) { (3, 0) } else { @@ -297,7 +330,7 @@ mod tests { gen_dummy_rankings(i.to_string(), 0, good, filtered_out, vcas).into_iter() }) .collect::>(); - let results = calculate_veteran_advisors_incentives( + let results_simple_consensus = calculate_veteran_advisors_incentives( &rankings, total_rewards, 1..=200, @@ -310,21 +343,58 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), + SIMPLE_MINIMUM_CONSENSUS, ); - let expected_reward_portion = agreement * Rewards::from(100) * reward_modifier; - dbg!(expected_reward_portion); - dbg!(agreement, reward_modifier, reputation_modifier); - let expected_rewards = total_rewards - / (Rewards::from(125 * 2) + expected_reward_portion) - * expected_reward_portion; - let res = results.get(VCA_3).unwrap(); + let vca3_expected_reward_portion_simple_consensus = vca3_agreement * Rewards::from(100) * reward_modifier; + dbg!(vca3_expected_reward_portion_simple_consensus); + dbg!(vca3_agreement, reward_modifier, reputation_modifier); + let vca3_expected_rewards_simple_consensus = total_rewards + / (Rewards::from(125 * 2) + vca3_expected_reward_portion_simple_consensus) + * vca3_expected_reward_portion_simple_consensus; + let res_vca3_simple_consensus = results_simple_consensus.get(VCA_3).unwrap(); + assert_eq!( + res_vca3_simple_consensus.reputation, + (Rewards::from(100) * vca3_agreement * reputation_modifier) + .to_u64() + .unwrap() + ); + assert!(are_close(res_vca3_simple_consensus.rewards, vca3_expected_rewards_simple_consensus)); + + + let results_qualified_consensus = calculate_veteran_advisors_incentives( + &rankings, + total_rewards, + 1..=200, + 1..=200, + THRESHOLDS + .into_iter() + .zip(REWARDS_DISAGREEMENT_MODIFIERS.into_iter()) + .collect(), + THRESHOLDS + .into_iter() + .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) + .collect(), + QUALIFIED_MINIMUM_CONSENSUS, + ); + + let vca3_expected_reward_portion_qualified_consensus = Rewards::from(100) * dec!(1.25); // low consensus so max reward modifier, agreement ratio doesn't count as all and rankings are all eligible + dbg!(vca3_expected_reward_portion_qualified_consensus); + dbg!(vca3_agreement, reward_modifier, reputation_modifier); + + let vca3_expected_rewards_qualified_consensus = total_rewards + / (Rewards::from(125 * 2) + vca3_expected_reward_portion_qualified_consensus) + * vca3_expected_reward_portion_qualified_consensus; // 1/3 of the reward + + let res_vca3_qualified_consensus = results_qualified_consensus.get(VCA_3).unwrap(); + + assert_eq!( - res.reputation, - (Rewards::from(100) * agreement * reputation_modifier) + res_vca3_qualified_consensus.reputation, + (Rewards::from(100)) // all assessment are valid since consensus is low (2/3 < 0.7) .to_u64() .unwrap() ); - assert!(are_close(res.rewards, expected_rewards)); + assert!(are_close(res_vca3_qualified_consensus.rewards, vca3_expected_rewards_qualified_consensus)); } } } From 3917c88df3133c6642d6615e2b1d339417103d05 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Tue, 2 Aug 2022 17:52:43 +0200 Subject: [PATCH 02/10] Fix kebap-case for new parameter and remove unnecessary conversion --- catalyst-toolbox/src/bin/cli/rewards/veterans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs index c82687d7..d5314cbe 100644 --- a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs +++ b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs @@ -68,7 +68,7 @@ pub struct VeteransRewards { /// Simple majority is 50%. /// Qualified majority is 70%. Using 70% avoids punishing vCAs where the consensus is not clear. /// 70% is because when #vca == 3 consensus is only 66% and thus in this case, where there is just 1 vote in disagreement, all 3 vCAs get rewarded. - #[structopt(long = "minimum_consensus")] + #[structopt(long)] minimum_consensus: Decimal, } @@ -126,7 +126,7 @@ impl VeteransRewards { .into_iter() .zip(reputation_agreement_rate_modifiers.into_iter()) .collect(), - Decimal::from(minimum_consensus), + minimum_consensus, ); csv::dump_data_to_csv(rewards_to_csv_data(results).iter(), &to).unwrap(); From 74a5544be4775f97457941c588ac1d503476a081 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Tue, 2 Aug 2022 18:03:36 +0200 Subject: [PATCH 03/10] Combine case, and use unreachable!() --- catalyst-toolbox/src/rewards/veterans.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index 982c4597..74e97a98 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -88,13 +88,11 @@ fn calc_final_ranking_consensus_per_review(rankings: &[impl Borrow rankings_majority => { Decimal::from(*excellent) / Decimal::from(rankings.len()) } - (_, Some(excellent), Some(good)) => { - (Decimal::from(*excellent) + Decimal::from(*good)) / Decimal::from(rankings.len()) + (_, maybe_excellent, Some(good)) => { + (maybe_excellent.map(|excellent| Decimal::from(*excellent)).unwrap_or_default() + + Decimal::from(*good)) / Decimal::from(rankings.len()) } - (_, _, Some(good)) => { - Decimal::from(*good) / Decimal::from(rankings.len()) - } - _ => Decimal::ONE, + _ => unreachable!(), } } From 6d47932d3a6bffd240688509e27771d8410bc5a0 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Tue, 2 Aug 2022 19:53:41 +0200 Subject: [PATCH 04/10] Combine calc_final_ranking_per_review() and calc_final_ranking_consensus_per_review() into calc_final_ranking_with_consensus_per_review() This also fixes a small bug where the consensus was lowered on Excellent assessments because the Good ones count was not taken into account, This had a low impact since Excellent assessments are much rarer. (The final_ranking_is_correct test caught this.) --- catalyst-toolbox/src/rewards/veterans.rs | 106 +++++++++++++---------- 1 file changed, 60 insertions(+), 46 deletions(-) diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index 74e97a98..ea1e4a81 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -16,6 +16,11 @@ pub struct VeteranAdvisorIncentive { pub reputation: u64, } +pub struct FinalRankingWithConsensus { + pub review_ranking: ReviewRanking, + pub consensus: Decimal, +} + pub type VcaRewards = HashMap; pub type EligibilityThresholds = std::ops::RangeInclusive; @@ -25,18 +30,34 @@ pub type EligibilityThresholds = std::ops::RangeInclusive; // e.g. something like an expanded version of a AdvisorReviewRow // [proposal_id, advisor, ratings, ..(other fields from AdvisorReviewRow).., ranking (good/excellent/filtered out), vca] -fn calc_final_ranking_per_review(rankings: &[impl Borrow]) -> ReviewRanking { +// note that the consensus returned here is either FO/total or ((E+G)/total) because for now we do +// not discriminate between Excellent and Good... +fn calc_final_ranking_with_consensus_per_review(rankings: &[impl Borrow]) -> FinalRankingWithConsensus { let rankings_majority = Decimal::from(rankings.len()) / Decimal::from(2); let ranks = rankings.iter().counts_by(|r| r.borrow().score()); - match (ranks.get(&FilteredOut), ranks.get(&Excellent)) { - (Some(filtered_out), _) if Decimal::from(*filtered_out) >= rankings_majority => { - ReviewRanking::FilteredOut + match (ranks.get(&Excellent), ranks.get(&Good), ranks.get(&FilteredOut)) { + (_, _, Some(filtered_out)) if Decimal::from(*filtered_out) >= rankings_majority => { + FinalRankingWithConsensus { + review_ranking: FilteredOut, + consensus: Decimal::from(*filtered_out) / Decimal::from(rankings.len()), + } } - (_, Some(excellent)) if Decimal::from(*excellent) > rankings_majority => { - ReviewRanking::Excellent + (Some(excellent), maybe_good, _) if Decimal::from(*excellent) > rankings_majority => { + FinalRankingWithConsensus { + review_ranking: Excellent, + consensus: (maybe_good.map(|good| Decimal::from(*good)).unwrap_or_default() + + Decimal::from(*excellent)) / Decimal::from(rankings.len()), + } + } + (maybe_excellent, Some(good), _) => { + FinalRankingWithConsensus { + review_ranking: Good, + consensus: (maybe_excellent.map(|excellent| Decimal::from(*excellent)).unwrap_or_default() + + Decimal::from(*good)) / Decimal::from(rankings.len()), + } } - _ => ReviewRanking::Good, + _ => unreachable!(), } } @@ -77,24 +98,6 @@ fn calc_final_eligible_rankings( .collect() } -fn calc_final_ranking_consensus_per_review(rankings: &[impl Borrow]) -> Decimal { - let rankings_majority = Decimal::from(rankings.len()) / Decimal::from(2); - let ranks = rankings.iter().counts_by(|r| r.borrow().score()); - - match (ranks.get(&FilteredOut), ranks.get(&Excellent), ranks.get(&Good)) { - (Some(filtered_out), _, _) if Decimal::from(*filtered_out) >= rankings_majority => { - Decimal::from(*filtered_out) / Decimal::from(rankings.len()) - } - (_, Some(excellent), _) if Decimal::from(*excellent) > rankings_majority => { - Decimal::from(*excellent) / Decimal::from(rankings.len()) - } - (_, maybe_excellent, Some(good)) => { - (maybe_excellent.map(|excellent| Decimal::from(*excellent)).unwrap_or_default() - + Decimal::from(*good)) / Decimal::from(rankings.len()) - } - _ => unreachable!(), - } -} pub fn calculate_veteran_advisors_incentives( veteran_rankings: &[VeteranRankingRow], @@ -105,18 +108,11 @@ pub fn calculate_veteran_advisors_incentives( reputation_mod_args: Vec<(Decimal, Decimal)>, minimum_consensus: Decimal, ) -> HashMap { - let final_rankings_per_review = veteran_rankings - .iter() - .into_group_map_by(|ranking| ranking.review_id()) - .into_iter() - .map(|(review, rankings)| (review, calc_final_ranking_per_review(&rankings))) - .collect::>(); - - let final_rankings_consensus_per_review = veteran_rankings + let final_rankings_with_consensus_per_review = veteran_rankings .iter() .into_group_map_by(|ranking| ranking.review_id()) .into_iter() - .map(|(review, rankings)| (review, calc_final_ranking_consensus_per_review(&rankings))) + .map(|(review, rankings)| (review, calc_final_ranking_with_consensus_per_review(&rankings))) .collect::>(); let rankings_per_vca = veteran_rankings @@ -126,11 +122,13 @@ pub fn calculate_veteran_advisors_incentives( let eligible_rankings_per_vca = veteran_rankings .iter() .filter(|ranking| { - final_rankings_per_review + let final_ranking_with_consensus = final_rankings_with_consensus_per_review .get(&ranking.review_id()) - .unwrap() - .is_positive() - == ranking.score().is_positive() || *final_rankings_consensus_per_review.get(&ranking.review_id()).unwrap() < minimum_consensus + .unwrap(); + + final_ranking_with_consensus.review_ranking + .is_positive() == ranking.score().is_positive() + || final_ranking_with_consensus.consensus < minimum_consensus }) .counts_by(|ranking| ranking.vca.clone()); @@ -217,23 +215,39 @@ mod tests { #[test] fn final_ranking_is_correct() { assert!(matches!( - calc_final_ranking_per_review(&gen_dummy_rankings("".into(), 5, 5, 5, RandomIterator),), - ReviewRanking::Good + calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 5, 5, 5, RandomIterator)), + FinalRankingWithConsensus { + review_ranking: Good, + consensus + } if consensus == (dec!(10) / dec!(15)) )); assert!(matches!( - calc_final_ranking_per_review(&gen_dummy_rankings("".into(), 4, 2, 5, RandomIterator)), - ReviewRanking::Good + calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 2, 5, RandomIterator)), + FinalRankingWithConsensus { + review_ranking: Good, + consensus + } if consensus == (dec!(6) / dec!(11)) + )); assert!(matches!( - calc_final_ranking_per_review(&gen_dummy_rankings("".into(), 4, 1, 5, RandomIterator)), - ReviewRanking::FilteredOut + calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 1, 5, RandomIterator)), + FinalRankingWithConsensus { + review_ranking: FilteredOut, + consensus, + } if consensus == (dec!(5) / dec!(10)) )); + let excellent_final =calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)); + + dbg!(excellent_final.consensus); assert!(matches!( - calc_final_ranking_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), - ReviewRanking::Excellent + calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), + FinalRankingWithConsensus { + review_ranking: Excellent, + consensus, + } if consensus == (dec!(4) / dec!(5)) )); } From c5216d1960684b2bd9938f1b166e4e9115dc1f62 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Wed, 3 Aug 2022 12:33:56 +0200 Subject: [PATCH 05/10] ... remove leftover debug --- catalyst-toolbox/src/rewards/veterans.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index ea1e4a81..d485e5dd 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -239,9 +239,6 @@ mod tests { } if consensus == (dec!(5) / dec!(10)) )); - let excellent_final =calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)); - - dbg!(excellent_final.consensus); assert!(matches!( calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), FinalRankingWithConsensus { From 1ad74bea7bb9fa153d3efa8eaf51b85b40ebf128 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Wed, 3 Aug 2022 12:48:29 +0200 Subject: [PATCH 06/10] simplify expressions using .copied() instead of a map --- catalyst-toolbox/src/rewards/veterans.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index d485e5dd..bfcb78ef 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -46,14 +46,14 @@ fn calc_final_ranking_with_consensus_per_review(rankings: &[impl Borrow rankings_majority => { FinalRankingWithConsensus { review_ranking: Excellent, - consensus: (maybe_good.map(|good| Decimal::from(*good)).unwrap_or_default() + consensus: (Decimal::from(maybe_good.copied().unwrap_or_default()) + Decimal::from(*excellent)) / Decimal::from(rankings.len()), } } (maybe_excellent, Some(good), _) => { FinalRankingWithConsensus { review_ranking: Good, - consensus: (maybe_excellent.map(|excellent| Decimal::from(*excellent)).unwrap_or_default() + consensus: (Decimal::from(maybe_excellent.copied().unwrap_or_default()) + Decimal::from(*good)) / Decimal::from(rankings.len()), } } From 8732431f46df633c3e9ddda3727272acb0823e72 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Wed, 3 Aug 2022 13:23:40 +0200 Subject: [PATCH 07/10] ... formatting --- .../src/bin/cli/rewards/veterans.rs | 2 +- catalyst-toolbox/src/rewards/veterans.rs | 65 ++++++++++++------- 2 files changed, 41 insertions(+), 26 deletions(-) diff --git a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs index d5314cbe..e7eeb07e 100644 --- a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs +++ b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs @@ -109,7 +109,7 @@ impl VeteransRewards { bail!("Expected rewards_agreement_rate_cutoffs to be descending"); } - if minimum_consensus < Decimal::new(5,1) || minimum_consensus > Decimal::ONE { + if minimum_consensus < Decimal::new(5, 1) || minimum_consensus > Decimal::ONE { bail!("Expected minimum_consensus to range between .5 and 1"); } diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index bfcb78ef..c06da589 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -32,11 +32,17 @@ pub type EligibilityThresholds = std::ops::RangeInclusive; // note that the consensus returned here is either FO/total or ((E+G)/total) because for now we do // not discriminate between Excellent and Good... -fn calc_final_ranking_with_consensus_per_review(rankings: &[impl Borrow]) -> FinalRankingWithConsensus { +fn calc_final_ranking_with_consensus_per_review( + rankings: &[impl Borrow], +) -> FinalRankingWithConsensus { let rankings_majority = Decimal::from(rankings.len()) / Decimal::from(2); let ranks = rankings.iter().counts_by(|r| r.borrow().score()); - match (ranks.get(&Excellent), ranks.get(&Good), ranks.get(&FilteredOut)) { + match ( + ranks.get(&Excellent), + ranks.get(&Good), + ranks.get(&FilteredOut), + ) { (_, _, Some(filtered_out)) if Decimal::from(*filtered_out) >= rankings_majority => { FinalRankingWithConsensus { review_ranking: FilteredOut, @@ -47,16 +53,16 @@ fn calc_final_ranking_with_consensus_per_review(rankings: &[impl Borrow { - FinalRankingWithConsensus { - review_ranking: Good, - consensus: (Decimal::from(maybe_excellent.copied().unwrap_or_default()) - + Decimal::from(*good)) / Decimal::from(rankings.len()), + + Decimal::from(*excellent)) + / Decimal::from(rankings.len()), } } + (maybe_excellent, Some(good), _) => FinalRankingWithConsensus { + review_ranking: Good, + consensus: (Decimal::from(maybe_excellent.copied().unwrap_or_default()) + + Decimal::from(*good)) + / Decimal::from(rankings.len()), + }, _ => unreachable!(), } } @@ -98,7 +104,6 @@ fn calc_final_eligible_rankings( .collect() } - pub fn calculate_veteran_advisors_incentives( veteran_rankings: &[VeteranRankingRow], total_rewards: Rewards, @@ -112,7 +117,12 @@ pub fn calculate_veteran_advisors_incentives( .iter() .into_group_map_by(|ranking| ranking.review_id()) .into_iter() - .map(|(review, rankings)| (review, calc_final_ranking_with_consensus_per_review(&rankings))) + .map(|(review, rankings)| { + ( + review, + calc_final_ranking_with_consensus_per_review(&rankings), + ) + }) .collect::>(); let rankings_per_vca = veteran_rankings @@ -126,8 +136,8 @@ pub fn calculate_veteran_advisors_incentives( .get(&ranking.review_id()) .unwrap(); - final_ranking_with_consensus.review_ranking - .is_positive() == ranking.score().is_positive() + final_ranking_with_consensus.review_ranking.is_positive() + == ranking.score().is_positive() || final_ranking_with_consensus.consensus < minimum_consensus }) .counts_by(|ranking| ranking.vca.clone()); @@ -330,12 +340,12 @@ mod tests { .flat_map(|i| { let vcas = vec![VCA_1.to_owned(), VCA_2.to_owned(), VCA_3.to_owned()].into_iter(); - let (good, filtered_out) = if Rewards::from(i) < vca3_agreement * Rewards::from(100) - { - (3, 0) - } else { - (2, 1) - }; + let (good, filtered_out) = + if Rewards::from(i) < vca3_agreement * Rewards::from(100) { + (3, 0) + } else { + (2, 1) + }; gen_dummy_rankings(i.to_string(), 0, good, filtered_out, vcas).into_iter() }) .collect::>(); @@ -354,7 +364,8 @@ mod tests { .collect(), SIMPLE_MINIMUM_CONSENSUS, ); - let vca3_expected_reward_portion_simple_consensus = vca3_agreement * Rewards::from(100) * reward_modifier; + let vca3_expected_reward_portion_simple_consensus = + vca3_agreement * Rewards::from(100) * reward_modifier; dbg!(vca3_expected_reward_portion_simple_consensus); dbg!(vca3_agreement, reward_modifier, reputation_modifier); let vca3_expected_rewards_simple_consensus = total_rewards @@ -367,8 +378,10 @@ mod tests { .to_u64() .unwrap() ); - assert!(are_close(res_vca3_simple_consensus.rewards, vca3_expected_rewards_simple_consensus)); - + assert!(are_close( + res_vca3_simple_consensus.rewards, + vca3_expected_rewards_simple_consensus + )); let results_qualified_consensus = calculate_veteran_advisors_incentives( &rankings, @@ -396,14 +409,16 @@ mod tests { let res_vca3_qualified_consensus = results_qualified_consensus.get(VCA_3).unwrap(); - assert_eq!( res_vca3_qualified_consensus.reputation, (Rewards::from(100)) // all assessment are valid since consensus is low (2/3 < 0.7) .to_u64() .unwrap() ); - assert!(are_close(res_vca3_qualified_consensus.rewards, vca3_expected_rewards_qualified_consensus)); + assert!(are_close( + res_vca3_qualified_consensus.rewards, + vca3_expected_rewards_qualified_consensus + )); } } } From b4e3b49eeec6b1aabd8a1a6aa451712acb7e1035 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Wed, 3 Aug 2022 14:06:33 +0200 Subject: [PATCH 08/10] Rename consensus to negative_or_positive_consensus and document it for clarity --- catalyst-toolbox/src/rewards/veterans.rs | 39 +++++++++++++----------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index c06da589..9c4d0850 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -18,7 +18,11 @@ pub struct VeteranAdvisorIncentive { pub struct FinalRankingWithConsensus { pub review_ranking: ReviewRanking, - pub consensus: Decimal, + + /// This is to be used in conjunction with `ReviewRanking::is_positive()` to assess the + /// consensus of the boolean reply. It is either `#FO / #Rankings` or `(#Excellent + #Good) / #Rankings`. + /// For now we do not discriminate between Good and Excellent but this might change in the future. + pub negative_or_positive_consensus: Decimal, } pub type VcaRewards = HashMap; @@ -30,8 +34,6 @@ pub type EligibilityThresholds = std::ops::RangeInclusive; // e.g. something like an expanded version of a AdvisorReviewRow // [proposal_id, advisor, ratings, ..(other fields from AdvisorReviewRow).., ranking (good/excellent/filtered out), vca] -// note that the consensus returned here is either FO/total or ((E+G)/total) because for now we do -// not discriminate between Excellent and Good... fn calc_final_ranking_with_consensus_per_review( rankings: &[impl Borrow], ) -> FinalRankingWithConsensus { @@ -46,21 +48,24 @@ fn calc_final_ranking_with_consensus_per_review( (_, _, Some(filtered_out)) if Decimal::from(*filtered_out) >= rankings_majority => { FinalRankingWithConsensus { review_ranking: FilteredOut, - consensus: Decimal::from(*filtered_out) / Decimal::from(rankings.len()), + negative_or_positive_consensus: Decimal::from(*filtered_out) + / Decimal::from(rankings.len()), } } (Some(excellent), maybe_good, _) if Decimal::from(*excellent) > rankings_majority => { FinalRankingWithConsensus { review_ranking: Excellent, - consensus: (Decimal::from(maybe_good.copied().unwrap_or_default()) - + Decimal::from(*excellent)) + negative_or_positive_consensus: (Decimal::from( + maybe_good.copied().unwrap_or_default(), + ) + Decimal::from(*excellent)) / Decimal::from(rankings.len()), } } (maybe_excellent, Some(good), _) => FinalRankingWithConsensus { review_ranking: Good, - consensus: (Decimal::from(maybe_excellent.copied().unwrap_or_default()) - + Decimal::from(*good)) + negative_or_positive_consensus: (Decimal::from( + maybe_excellent.copied().unwrap_or_default(), + ) + Decimal::from(*good)) / Decimal::from(rankings.len()), }, _ => unreachable!(), @@ -138,7 +143,7 @@ pub fn calculate_veteran_advisors_incentives( final_ranking_with_consensus.review_ranking.is_positive() == ranking.score().is_positive() - || final_ranking_with_consensus.consensus < minimum_consensus + || final_ranking_with_consensus.negative_or_positive_consensus < minimum_consensus }) .counts_by(|ranking| ranking.vca.clone()); @@ -228,16 +233,16 @@ mod tests { calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 5, 5, 5, RandomIterator)), FinalRankingWithConsensus { review_ranking: Good, - consensus - } if consensus == (dec!(10) / dec!(15)) + negative_or_positive_consensus + } if negative_or_positive_consensus == (dec!(10) / dec!(15)) )); assert!(matches!( calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 2, 5, RandomIterator)), FinalRankingWithConsensus { review_ranking: Good, - consensus - } if consensus == (dec!(6) / dec!(11)) + negative_or_positive_consensus + } if negative_or_positive_consensus == (dec!(6) / dec!(11)) )); @@ -245,16 +250,16 @@ mod tests { calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 1, 5, RandomIterator)), FinalRankingWithConsensus { review_ranking: FilteredOut, - consensus, - } if consensus == (dec!(5) / dec!(10)) + negative_or_positive_consensus, + } if negative_or_positive_consensus == (dec!(5) / dec!(10)) )); assert!(matches!( calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), FinalRankingWithConsensus { review_ranking: Excellent, - consensus, - } if consensus == (dec!(4) / dec!(5)) + negative_or_positive_consensus, + } if negative_or_positive_consensus == (dec!(4) / dec!(5)) )); } From a68edef8d0250e95182ca496219916d2bdd061c7 Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Wed, 3 Aug 2022 15:07:25 +0200 Subject: [PATCH 09/10] Rename `negative_or_positive_consensus` to just `confidence` The documentation added is enough to clear any doubts and "confidence" does not imply as much as does the term "consensus" which prevent false assumptions. --- catalyst-toolbox/src/rewards/veterans.rs | 39 +++++++++++------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index 9c4d0850..87bd77b4 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -16,13 +16,13 @@ pub struct VeteranAdvisorIncentive { pub reputation: u64, } -pub struct FinalRankingWithConsensus { - pub review_ranking: ReviewRanking, +struct FinalRankingWithConsensus { + review_ranking: ReviewRanking, /// This is to be used in conjunction with `ReviewRanking::is_positive()` to assess the - /// consensus of the boolean reply. It is either `#FO / #Rankings` or `(#Excellent + #Good) / #Rankings`. + /// confidence of the boolean reply. It is either `#FO / #Rankings` or `(#Excellent + #Good) / #Rankings`. /// For now we do not discriminate between Good and Excellent but this might change in the future. - pub negative_or_positive_consensus: Decimal, + confidence: Decimal, } pub type VcaRewards = HashMap; @@ -48,24 +48,21 @@ fn calc_final_ranking_with_consensus_per_review( (_, _, Some(filtered_out)) if Decimal::from(*filtered_out) >= rankings_majority => { FinalRankingWithConsensus { review_ranking: FilteredOut, - negative_or_positive_consensus: Decimal::from(*filtered_out) - / Decimal::from(rankings.len()), + confidence: Decimal::from(*filtered_out) / Decimal::from(rankings.len()), } } (Some(excellent), maybe_good, _) if Decimal::from(*excellent) > rankings_majority => { FinalRankingWithConsensus { review_ranking: Excellent, - negative_or_positive_consensus: (Decimal::from( - maybe_good.copied().unwrap_or_default(), - ) + Decimal::from(*excellent)) + confidence: (Decimal::from(maybe_good.copied().unwrap_or_default()) + + Decimal::from(*excellent)) / Decimal::from(rankings.len()), } } (maybe_excellent, Some(good), _) => FinalRankingWithConsensus { review_ranking: Good, - negative_or_positive_consensus: (Decimal::from( - maybe_excellent.copied().unwrap_or_default(), - ) + Decimal::from(*good)) + confidence: (Decimal::from(maybe_excellent.copied().unwrap_or_default()) + + Decimal::from(*good)) / Decimal::from(rankings.len()), }, _ => unreachable!(), @@ -143,7 +140,7 @@ pub fn calculate_veteran_advisors_incentives( final_ranking_with_consensus.review_ranking.is_positive() == ranking.score().is_positive() - || final_ranking_with_consensus.negative_or_positive_consensus < minimum_consensus + || final_ranking_with_consensus.confidence < minimum_consensus }) .counts_by(|ranking| ranking.vca.clone()); @@ -233,16 +230,16 @@ mod tests { calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 5, 5, 5, RandomIterator)), FinalRankingWithConsensus { review_ranking: Good, - negative_or_positive_consensus - } if negative_or_positive_consensus == (dec!(10) / dec!(15)) + confidence + } if confidence == (dec!(10) / dec!(15)) )); assert!(matches!( calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 2, 5, RandomIterator)), FinalRankingWithConsensus { review_ranking: Good, - negative_or_positive_consensus - } if negative_or_positive_consensus == (dec!(6) / dec!(11)) + confidence + } if confidence == (dec!(6) / dec!(11)) )); @@ -250,16 +247,16 @@ mod tests { calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 1, 5, RandomIterator)), FinalRankingWithConsensus { review_ranking: FilteredOut, - negative_or_positive_consensus, - } if negative_or_positive_consensus == (dec!(5) / dec!(10)) + confidence, + } if confidence == (dec!(5) / dec!(10)) )); assert!(matches!( calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), FinalRankingWithConsensus { review_ranking: Excellent, - negative_or_positive_consensus, - } if negative_or_positive_consensus == (dec!(4) / dec!(5)) + confidence, + } if confidence == (dec!(4) / dec!(5)) )); } From 63ba8c9a113c960e495e4f4c43fd199e0fd3ae5d Mon Sep 17 00:00:00 2001 From: John Wellesz Date: Wed, 3 Aug 2022 15:59:09 +0200 Subject: [PATCH 10/10] Replace consensus with confidence everywhere else, including parameter name. --- .../src/bin/cli/rewards/veterans.rs | 18 ++-- catalyst-toolbox/src/rewards/veterans.rs | 96 +++++++++---------- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs index e7eeb07e..6077aaa0 100644 --- a/catalyst-toolbox/src/bin/cli/rewards/veterans.rs +++ b/catalyst-toolbox/src/bin/cli/rewards/veterans.rs @@ -64,12 +64,12 @@ pub struct VeteransRewards { reputation_agreement_rate_modifiers: Vec, /// Value in range [0.5, 1] - /// The minimum consensus for a vCA ranking to be excluded from eligible rankings when in disagreement from simple majority. - /// Simple majority is 50%. - /// Qualified majority is 70%. Using 70% avoids punishing vCAs where the consensus is not clear. - /// 70% is because when #vca == 3 consensus is only 66% and thus in this case, where there is just 1 vote in disagreement, all 3 vCAs get rewarded. + /// The minimum confidence for a vCA ranking to be excluded from eligible rankings when in disagreement from simple majority. + /// Confidence is either `#FO / #Rankings` or `(#Excellent + #Good) / #Rankings` depending on the final ranking. + /// Simple majority is 50%. Qualified majority is 70%. Using 70% avoids punishing vCAs where this confidence is not clear. + /// 70% is because when #vCA == 3 confidence is only 66% and thus in this case, where there is just 1 vote in disagreement, all 3 vCAs get rewarded. #[structopt(long)] - minimum_consensus: Decimal, + minimum_confidence: Decimal, } impl VeteransRewards { @@ -85,7 +85,7 @@ impl VeteransRewards { rewards_agreement_rate_modifiers, reputation_agreement_rate_cutoffs, reputation_agreement_rate_modifiers, - minimum_consensus, + minimum_confidence, } = self; let reviews: Vec = csv::load_data_from_csv::<_, b','>(&from)?; @@ -109,8 +109,8 @@ impl VeteransRewards { bail!("Expected rewards_agreement_rate_cutoffs to be descending"); } - if minimum_consensus < Decimal::new(5, 1) || minimum_consensus > Decimal::ONE { - bail!("Expected minimum_consensus to range between .5 and 1"); + if minimum_confidence < Decimal::new(5, 1) || minimum_confidence > Decimal::ONE { + bail!("Expected minimum_confidence to range between .5 and 1"); } let results = veterans::calculate_veteran_advisors_incentives( @@ -126,7 +126,7 @@ impl VeteransRewards { .into_iter() .zip(reputation_agreement_rate_modifiers.into_iter()) .collect(), - minimum_consensus, + minimum_confidence, ); csv::dump_data_to_csv(rewards_to_csv_data(results).iter(), &to).unwrap(); diff --git a/catalyst-toolbox/src/rewards/veterans.rs b/catalyst-toolbox/src/rewards/veterans.rs index 87bd77b4..817640d7 100644 --- a/catalyst-toolbox/src/rewards/veterans.rs +++ b/catalyst-toolbox/src/rewards/veterans.rs @@ -16,11 +16,11 @@ pub struct VeteranAdvisorIncentive { pub reputation: u64, } -struct FinalRankingWithConsensus { +struct FinalRankingWithConfidence { review_ranking: ReviewRanking, /// This is to be used in conjunction with `ReviewRanking::is_positive()` to assess the - /// confidence of the boolean reply. It is either `#FO / #Rankings` or `(#Excellent + #Good) / #Rankings`. + /// confidence of the boolean reply. It is either `#FO / #Rankings` or `(#Excellent + #Good) / #Rankings` depending on the final ranking. /// For now we do not discriminate between Good and Excellent but this might change in the future. confidence: Decimal, } @@ -34,9 +34,9 @@ pub type EligibilityThresholds = std::ops::RangeInclusive; // e.g. something like an expanded version of a AdvisorReviewRow // [proposal_id, advisor, ratings, ..(other fields from AdvisorReviewRow).., ranking (good/excellent/filtered out), vca] -fn calc_final_ranking_with_consensus_per_review( +fn calc_final_ranking_with_confidence_per_review( rankings: &[impl Borrow], -) -> FinalRankingWithConsensus { +) -> FinalRankingWithConfidence { let rankings_majority = Decimal::from(rankings.len()) / Decimal::from(2); let ranks = rankings.iter().counts_by(|r| r.borrow().score()); @@ -46,20 +46,20 @@ fn calc_final_ranking_with_consensus_per_review( ranks.get(&FilteredOut), ) { (_, _, Some(filtered_out)) if Decimal::from(*filtered_out) >= rankings_majority => { - FinalRankingWithConsensus { + FinalRankingWithConfidence { review_ranking: FilteredOut, confidence: Decimal::from(*filtered_out) / Decimal::from(rankings.len()), } } (Some(excellent), maybe_good, _) if Decimal::from(*excellent) > rankings_majority => { - FinalRankingWithConsensus { + FinalRankingWithConfidence { review_ranking: Excellent, confidence: (Decimal::from(maybe_good.copied().unwrap_or_default()) + Decimal::from(*excellent)) / Decimal::from(rankings.len()), } } - (maybe_excellent, Some(good), _) => FinalRankingWithConsensus { + (maybe_excellent, Some(good), _) => FinalRankingWithConfidence { review_ranking: Good, confidence: (Decimal::from(maybe_excellent.copied().unwrap_or_default()) + Decimal::from(*good)) @@ -113,16 +113,16 @@ pub fn calculate_veteran_advisors_incentives( reputation_thresholds: EligibilityThresholds, rewards_mod_args: Vec<(Decimal, Decimal)>, reputation_mod_args: Vec<(Decimal, Decimal)>, - minimum_consensus: Decimal, + minimum_confidence: Decimal, ) -> HashMap { - let final_rankings_with_consensus_per_review = veteran_rankings + let final_rankings_with_confidence_per_review = veteran_rankings .iter() .into_group_map_by(|ranking| ranking.review_id()) .into_iter() .map(|(review, rankings)| { ( review, - calc_final_ranking_with_consensus_per_review(&rankings), + calc_final_ranking_with_confidence_per_review(&rankings), ) }) .collect::>(); @@ -134,13 +134,13 @@ pub fn calculate_veteran_advisors_incentives( let eligible_rankings_per_vca = veteran_rankings .iter() .filter(|ranking| { - let final_ranking_with_consensus = final_rankings_with_consensus_per_review + let final_ranking_with_confidence = final_rankings_with_confidence_per_review .get(&ranking.review_id()) .unwrap(); - final_ranking_with_consensus.review_ranking.is_positive() + final_ranking_with_confidence.review_ranking.is_positive() == ranking.score().is_positive() - || final_ranking_with_consensus.confidence < minimum_consensus + || final_ranking_with_confidence.confidence < minimum_confidence }) .counts_by(|ranking| ranking.vca.clone()); @@ -193,8 +193,8 @@ mod tests { const VCA_1: &str = "vca1"; const VCA_2: &str = "vca2"; const VCA_3: &str = "vca3"; - const SIMPLE_MINIMUM_CONSENSUS: Decimal = dec!(.5); - const QUALIFIED_MINIMUM_CONSENSUS: Decimal = dec!(.7); + const SIMPLE_MAJORITY_CONFIDENCE: Decimal = dec!(.5); + const QUALIFIED_MAJORITY_CONFIDENCE: Decimal = dec!(.7); struct RandomIterator; impl Iterator for RandomIterator { @@ -227,16 +227,16 @@ mod tests { #[test] fn final_ranking_is_correct() { assert!(matches!( - calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 5, 5, 5, RandomIterator)), - FinalRankingWithConsensus { + calc_final_ranking_with_confidence_per_review(&gen_dummy_rankings("".into(), 5, 5, 5, RandomIterator)), + FinalRankingWithConfidence { review_ranking: Good, confidence } if confidence == (dec!(10) / dec!(15)) )); assert!(matches!( - calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 2, 5, RandomIterator)), - FinalRankingWithConsensus { + calc_final_ranking_with_confidence_per_review(&gen_dummy_rankings("".into(), 4, 2, 5, RandomIterator)), + FinalRankingWithConfidence { review_ranking: Good, confidence } if confidence == (dec!(6) / dec!(11)) @@ -244,16 +244,16 @@ mod tests { )); assert!(matches!( - calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 4, 1, 5, RandomIterator)), - FinalRankingWithConsensus { + calc_final_ranking_with_confidence_per_review(&gen_dummy_rankings("".into(), 4, 1, 5, RandomIterator)), + FinalRankingWithConfidence { review_ranking: FilteredOut, confidence, } if confidence == (dec!(5) / dec!(10)) )); assert!(matches!( - calc_final_ranking_with_consensus_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), - FinalRankingWithConsensus { + calc_final_ranking_with_confidence_per_review(&gen_dummy_rankings("".into(), 3, 1, 1, RandomIterator)), + FinalRankingWithConfidence { review_ranking: Excellent, confidence, } if confidence == (dec!(4) / dec!(5)) @@ -283,7 +283,7 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), - SIMPLE_MINIMUM_CONSENSUS, + SIMPLE_MAJORITY_CONFIDENCE, ); assert!(results.get(VCA_1).is_none()); let res = results.get(VCA_2).unwrap(); @@ -313,7 +313,7 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), - SIMPLE_MINIMUM_CONSENSUS, + SIMPLE_MAJORITY_CONFIDENCE, ); let res1 = results.get(VCA_1).unwrap(); assert_eq!(res1.reputation, 1); @@ -351,7 +351,7 @@ mod tests { gen_dummy_rankings(i.to_string(), 0, good, filtered_out, vcas).into_iter() }) .collect::>(); - let results_simple_consensus = calculate_veteran_advisors_incentives( + let results_simple_confidence = calculate_veteran_advisors_incentives( &rankings, total_rewards, 1..=200, @@ -364,28 +364,28 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), - SIMPLE_MINIMUM_CONSENSUS, + SIMPLE_MAJORITY_CONFIDENCE, ); - let vca3_expected_reward_portion_simple_consensus = + let vca3_expected_reward_portion_simple_confidence = vca3_agreement * Rewards::from(100) * reward_modifier; - dbg!(vca3_expected_reward_portion_simple_consensus); + dbg!(vca3_expected_reward_portion_simple_confidence); dbg!(vca3_agreement, reward_modifier, reputation_modifier); - let vca3_expected_rewards_simple_consensus = total_rewards - / (Rewards::from(125 * 2) + vca3_expected_reward_portion_simple_consensus) - * vca3_expected_reward_portion_simple_consensus; - let res_vca3_simple_consensus = results_simple_consensus.get(VCA_3).unwrap(); + let vca3_expected_rewards_simple_confidence = total_rewards + / (Rewards::from(125 * 2) + vca3_expected_reward_portion_simple_confidence) + * vca3_expected_reward_portion_simple_confidence; + let res_vca3_simple_confidence = results_simple_confidence.get(VCA_3).unwrap(); assert_eq!( - res_vca3_simple_consensus.reputation, + res_vca3_simple_confidence.reputation, (Rewards::from(100) * vca3_agreement * reputation_modifier) .to_u64() .unwrap() ); assert!(are_close( - res_vca3_simple_consensus.rewards, - vca3_expected_rewards_simple_consensus + res_vca3_simple_confidence.rewards, + vca3_expected_rewards_simple_confidence )); - let results_qualified_consensus = calculate_veteran_advisors_incentives( + let results_qualified_confidence = calculate_veteran_advisors_incentives( &rankings, total_rewards, 1..=200, @@ -398,28 +398,28 @@ mod tests { .into_iter() .zip(REPUTATION_DISAGREEMENT_MODIFIERS.into_iter()) .collect(), - QUALIFIED_MINIMUM_CONSENSUS, + QUALIFIED_MAJORITY_CONFIDENCE, ); - let vca3_expected_reward_portion_qualified_consensus = Rewards::from(100) * dec!(1.25); // low consensus so max reward modifier, agreement ratio doesn't count as all and rankings are all eligible - dbg!(vca3_expected_reward_portion_qualified_consensus); + let vca3_expected_reward_portion_qualified_confidence = Rewards::from(100) * dec!(1.25); // low confidence so max reward modifier, agreement ratio doesn't count as all and rankings are all eligible + dbg!(vca3_expected_reward_portion_qualified_confidence); dbg!(vca3_agreement, reward_modifier, reputation_modifier); - let vca3_expected_rewards_qualified_consensus = total_rewards - / (Rewards::from(125 * 2) + vca3_expected_reward_portion_qualified_consensus) - * vca3_expected_reward_portion_qualified_consensus; // 1/3 of the reward + let vca3_expected_rewards_qualified_confidence = total_rewards + / (Rewards::from(125 * 2) + vca3_expected_reward_portion_qualified_confidence) + * vca3_expected_reward_portion_qualified_confidence; // 1/3 of the reward - let res_vca3_qualified_consensus = results_qualified_consensus.get(VCA_3).unwrap(); + let res_vca3_qualified_confidence = results_qualified_confidence.get(VCA_3).unwrap(); assert_eq!( - res_vca3_qualified_consensus.reputation, - (Rewards::from(100)) // all assessment are valid since consensus is low (2/3 < 0.7) + res_vca3_qualified_confidence.reputation, + (Rewards::from(100)) // all assessment are valid since confidence is low (2/3 < 0.7) .to_u64() .unwrap() ); assert!(are_close( - res_vca3_qualified_consensus.rewards, - vca3_expected_rewards_qualified_consensus + res_vca3_qualified_confidence.rewards, + vca3_expected_rewards_qualified_confidence )); } }