Scoring system

Hi everyone, here I am again. :smiley: :smiley:

Thank you to this community help (And Wallace thank you again for your incredible patience :pray: :pray: :pray: :pray:) 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 ()
2 Likes

Dear Alex,

Thank you ever so much for your answer. :pray: :pray: :pray: That is exactly what I am trying to do. Now, I have so so much material to work on and learn from your template!!! :smiley:

Thank you ever so so much, you really made my day. :smiley: This help from the community is invaluable to me !!! :pray: :pray: :pray: