Scoring system
Hi everyone, here I am again.
![]()
Thank you to this community help (And Wallace thank you again for your incredible patience
) I managed to create the first part of my code and I have now started the second part.
I am trying to create a scoring system, on some assets that I created. I saw that there is a good example in Daml examples (Voting example) and I was following that. However, my problem is slightly different as I have to create a score not to express a vote. I wrote the code below, where I am trying to do the following:
1- I want to send some parties a contract to express a score
2- I want use use THAT score to create a template with the score calculation
3- I would like it to work even with 1 party giving the score (the requirement is minimum of 1, up to 5). The score must between 1 and 5.
My code below complies. However, the template where the parties express the score is not linked to the score calculation template. Could please someone help me with the above? I would be extremely grateful for your help and patience.
module AABCVotingSystem where
import DA.Set as S
import DA.List as L
import Daml.Script
import DA.Math
type ScoreComputationId = ContractId ScoreComputation
type Voting1Id = ContractId Voting1
type Voting2Id = ContractId Voting2
{-data AssetProposal = AssetProposal
with
proposer : Party
text : Text
deriving (Eq, Show)-}
template ScoreComputation
with
assetidCode :Text
scoreCalculator: Party
calculatedScore :Int
scoreVoter1: Int
scoreVoter2: Int
scoreVoter3: Int
scoreVoter4: Int
scoreVoter5: Int
where
ensure (scoreVoter1 >= 1) && (scoreVoter1<= 5)
&& (scoreVoter2 >= 1) && (scoreVoter2<= 5)
&& (scoreVoter3 >= 1) && (scoreVoter3<= 5)
&& (scoreVoter4 >= 1) && (scoreVoter4<= 5)
&& (scoreVoter5 >= 1) && (scoreVoter5<= 5)
signatory scoreCalculator
choice MakeScoreCalutation
: ScoreComputationId
with
score1 : Int
score2 : Int
score3 : Int
score4 : Int
score5 : Int
controller scoreCalculator
do
create this with
calculatedScore = (score1 + score2 + score3 + score4 + score5)/5
scoreVoter1= score1
scoreVoter2= score2
scoreVoter3= score3
scoreVoter4= score4
scoreVoter5= score5
template Voting1
with
assetIdcode :Text
solicitor1 :Party
score1 :Int
notes : Text
where
signatory solicitor1
template Voting2
with
assetIdcode :Text
solicitor2 :Party
score2 :Int
notes : Text
where
signatory solicitor2
I’m not sure I fully understand the requirements and constraints from the description you gave. But based on my interpretation of your requirements, I think you can achieve what you’re looking for with a single template. Here’s the workflow I propose. When the score calculator party initially creates the Score contract, they set the calculatedScore to zero and specify the set of parties that can submit their votes for the score. These parties can submit their individual scores by exercising Score_Vote choice on the contract. Every time the choice is exercised, calculatedScore is updated with the average value of all individual scores submitted thus far. To prevent voters from voting more than once the choice also removes the voting party from the set of allowed voters and adds it to the set of parties that already voted. Keeping the list of parties that already voted also helps in calculating the average score. In this design the score calculator party can access the Score contract at any time. If calculatedScore is zero, no votes have been submitted. If it’s more than zero, then at least one voter submitted their individual score.
Here’s the template with the test script for the happy path
import Daml.Script
import DA.Set as Set
import DA.Action
import DA.List
template Score
with
assetidCode: Text
scoreCalculator: Party
calculatedScore: Decimal
scoreVoters: Set Party
alreadyVoted: Set Party
where
signatory scoreCalculator
observer scoreVoters
ensure (intersection scoreVoters alreadyVoted == Set.empty) &&
(alreadyVoted /= Set.empty || calculatedScore == 0.0)
choice Score_Vote: ContractId Score
with
scoreVoter: Party
score: Int
controller scoreVoter
do
assertMsg "The score must be an integer between 1 & 5" $
(score>=1 && score<=5)
assertMsg "The voter is not on the list of allowed voters" $
(Set.member scoreVoter scoreVoters)
create this with
calculatedScore = (intToDecimal score + calculatedScore * intToDecimal (size alreadyVoted))
/ (intToDecimal (size alreadyVoted) + 1.0)
scoreVoters = Set.delete scoreVoter scoreVoters
alreadyVoted = Set.insert scoreVoter alreadyVoted
testScore = script do
pSC <- allocateParty "Score Calculator"
p1 <- allocateParty "Party1"
p2 <- allocateParty "Party2"
p3 <- allocateParty "Party3"
p4 <- allocateParty "Party4"
p5 <- allocateParty "Party5"
s <- submit pSC do
createCmd Score with
assetidCode = "XXX"
scoreCalculator = pSC
calculatedScore = 0.0
scoreVoters = Set.fromList [p1,p2,p3,p4,p5]
alreadyVoted = Set.empty
let counterList = [0..4]
let scoresList = [1,2,3,4,5]
let partiesList = [p1,p2,p3,p4,p5]
foldlA (\s x -> submit (partiesList !! x) do
exerciseCmd s Score_Vote with
scoreVoter = partiesList !! x
score = scoresList !! x)
s counterList
return ()
Dear Alex,
Thank you ever so much for your answer.
That is exactly what I am trying to do. Now, I have so so much material to work on and learn from your template!!! ![]()
Thank you ever so so much, you really made my day.
This help from the community is invaluable to me !!!
![]()