async fn vote(&self, context: Context, msg: &Message, args: String) {
        // Extract the n and topic ID from the arguments
        if let Ok(nargs) = args
            .split(" ")
            .map(|s| s.parse())
            .collect::<Result<Vec<usize>, ParseIntError>>()
        {
            let (n, candidate_id) = (nargs[0], nargs[1]);

            if let Some(guild) = msg.guild(&context).await {
                let g = &guild.id;

                // Reference to an atomic uint storing the user's vote count for the candidate
                if let Some(candidate_votes) =
                    self.votes.get(g).unwrap().read().await.get(&candidate_id)
                {
                    // Each user starts with STARTING_POINTS points
                    if !self
                        .points
                        .get(g)
                        .unwrap()
                        .read()
                        .await
                        .contains_key(&msg.author.id)
                    {
                        self.points
                            .get(g)
                            .unwrap()
                            .write()
                            .await
                            .insert(msg.author.id, AtomicUsize::new(STARTING_POINTS));
                    }

                    if let Some(existing_votes) = candidate_votes.2.get(&msg.author.id) {
                        // The user will be refunded the points they've already spent on this candidate.
                        // Calculate conversions from votes to points accordingly
                        let can_spend = self
                            .points
                            .get(g)
                            .unwrap()
                            .read()
                            .await
                            .get(&msg.author.id)
                            .unwrap()
                            .load(Ordering::Relaxed)
                            + existing_votes.load(Ordering::Relaxed).pow(2);
                        let req_points = n.pow(2);

                        // The user cannot continue if they lack the requisite points
                        if can_spend < req_points {
                            msg.author.dm(&context, |m| m.content(format!("Insufficient points to cast votes: {} votes cost {} points, but you can only spend {}.", n, req_points, can_spend))).await.expect("discord API error");

                            return;
                        }

                        // Refund the user's votes previously delegated to the candidate
                        let prev_votes = candidate_votes
                            .2
                            .get(&msg.author.id)
                            .unwrap()
                            .swap(n, Ordering::Relaxed);

                        // Remove old votes for the candidate
                        candidate_votes.1.fetch_sub(prev_votes, Ordering::Relaxed);

                        // Refund the user's points
                        self.points
                            .get(g)
                            .unwrap()
                            .read()
                            .await
                            .get(&msg.author.id)
                            .unwrap()
                            .fetch_add(prev_votes, Ordering::Relaxed);
                    }

                    // Subtract the user's spent points and allocate the votes
                    candidate_votes.1.fetch_add(n, Ordering::Relaxed);
                    self.points
                        .get(g)
                        .unwrap()
                        .read()
                        .await
                        .get(&msg.author.id)
                        .unwrap()
                        .fetch_sub(n, Ordering::Relaxed);

                    // Recalculate the vote balance announcement
                    self.poll_votes(context, g).await;
                }
            }
        } else {
            msg.author
                .dm(&context, |m| {
                    m.content("Missing parameters. Usage: ```\n!vote <n>, <topic id>\n```")
                })
                .await
                .expect("discord API error");
        }
    }
/// !vote <n>, <topic>: Cast n votes for the selected topic
vote , : Cast n votes for the selected topic
vote : Cast n votes for the selected topic
async fn vote(&self, context: Context, msg: &Message, args: String) {
        // Extract the n and topic ID from the arguments
        if let Ok(nargs) = args
            .split(" ")
            .map(|s| s.parse())
            .collect::<Result<Vec<usize>, ParseIntError>>()
        {
            let (n, candidate_id) = (nargs[0], nargs[1]);
            if let Some(guild) = msg.guild(&context).await {
                let g = &guild.id;
                // Reference to an atomic uint storing the user's vote count for the candidate
                if let Some(candidate_votes) =
                    self.votes.get(g).unwrap().read().await.get(&candidate_id)
                {
                    // Each user starts with STARTING_POINTS points
                    if !self
                        .points
                        .get(g)
                        .unwrap()
                        .read()
                        .await
                        .contains_key(&msg.author.id)
                    {
                        self.points
                            .get(g)
                            .unwrap()
                            .write()
                            .await
                            .insert(msg.author.id, AtomicUsize::new(STARTING_POINTS));
                    }
                    if let Some(existing_votes) = candidate_votes.2.get(&msg.author.id) {
                        // The user will be refunded the points they've already spent on this candidate.
                        // Calculate conversions from votes to points accordingly
                        let can_spend = self
                            .points
                            .get(g)
                            .unwrap()
                            .read()
                            .await
                            .get(&msg.author.id)
                            .unwrap()
                            .load(Ordering::Relaxed)
                            + existing_votes.load(Ordering::Relaxed).pow(2);
                        let req_points = n.pow(2);
                        // The user cannot continue if they lack the requisite points
                        if can_spend < req_points {
                            msg.author.dm(&context, |m| m.content(format!("Insufficient points to cast votes: {} votes cost {} points, but you can only spend {}.", n, req_points, can_spend))).await.expect("discord API error");
                            return;
                        }
                        // Refund the user's votes previously delegated to the candidate
                        let prev_votes = candidate_votes
                            .2
                            .get(&msg.author.id)
                            .unwrap()
                            .swap(n, Ordering::Relaxed);
                        // Remove old votes for the candidate
                        candidate_votes.1.fetch_sub(prev_votes, Ordering::Relaxed);
                        // Refund the user's points
                        self.points
                            .get(g)
                            .unwrap()
                            .read()
                            .await
                            .get(&msg.author.id)
                            .unwrap()
                            .fetch_add(prev_votes, Ordering::Relaxed);
                    }
                    // Subtract the user's spent points and allocate the votes
                    candidate_votes.1.fetch_add(n, Ordering::Relaxed);
                    self.points
                        .get(g)
                        .unwrap()
                        .read()
                        .await
                        .get(&msg.author.id)
                        .unwrap()
                        .fetch_sub(n, Ordering::Relaxed);
                    // Recalculate the vote balance announcement
                    self.poll_votes(context, g).await;
                }
            }
        } else {
            msg.author
                .dm(&context, |m| {
                    m.content("Missing parameters. Usage: ```\n!vote <n>, <topic id>\n```")
                })
                .await
                .expect("discord API error");
        }
    }
async fn vote ( & self , context : Context , msg : & Message , args : String ) { // Extract the n and topic ID from the arguments if let Ok ( nargs ) = args . split ( " " ) . map ( | s | s . parse ( ) ) . collect :: < Result < Vec < usize > , ParseIntError > > ( ) { let ( n , candidate_id ) = ( nargs [ 0 ] , nargs [ 1 ] ) ; if let Some ( guild ) = msg . guild ( & context ) . await { let g = & guild . id ; // Reference to an atomic uint storing the user's vote count for the candidate if let Some ( candidate_votes ) = self . votes . get ( g ) . unwrap ( ) . read ( ) . await . get ( & candidate_id ) { // Each user starts with STARTING_POINTS points if ! self . points . get ( g ) . unwrap ( ) . read ( ) . await . contains_key ( & msg . author . id ) { self . points . get ( g ) . unwrap ( ) . write ( ) . await . insert ( msg . author . id , AtomicUsize :: new ( STARTING_POINTS ) ) ; } if let Some ( existing_votes ) = candidate_votes . 2 . get ( & msg . author . id ) { // The user will be refunded the points they've already spent on this candidate. // Calculate conversions from votes to points accordingly let can_spend = self . points . get ( g ) . unwrap ( ) . read ( ) . await . get ( & msg . author . id ) . unwrap ( ) . load ( Ordering :: Relaxed ) + existing_votes . load ( Ordering :: Relaxed ) . pow ( 2 ) ; let req_points = n . pow ( 2 ) ; // The user cannot continue if they lack the requisite points if can_spend < req_points { msg . author . dm ( & context , | m | m . content ( format ! ( " " n req_points can_spend ) ) ) . await . expect ( " " ) ; return ; } // Refund the user's votes previously delegated to the candidate let prev_votes = candidate_votes . 2 . get ( & msg . author . id ) . unwrap ( ) . swap ( n , Ordering :: Relaxed ) ; // Remove old votes for the candidate candidate_votes . 1 . fetch_sub ( prev_votes , Ordering :: Relaxed ) ; // Refund the user's points self . points . get ( g ) . unwrap ( ) . read ( ) . await . get ( & msg . author . id ) . unwrap ( ) . fetch_add ( prev_votes , Ordering :: Relaxed ) ; } // Subtract the user's spent points and allocate the votes candidate_votes . 1 . fetch_add ( n , Ordering :: Relaxed ) ; self . points . get ( g ) . unwrap ( ) . read ( ) . await . get ( & msg . author . id ) . unwrap ( ) . fetch_sub ( n , Ordering :: Relaxed ) ; // Recalculate the vote balance announcement self . poll_votes ( context , g ) . await ; } } } else { msg . author . dm ( & context , | m | { m . content ( " \n \n " ) } ) . await . expect ( " " ) ; } }
vote <n>, <topic>: Cast n votes for the selected topic
vote <n > <topic > : Cast n votes for the selected topic
&self
context
Context
msg
&Message
args
String
&self
context
Context
msg
&Message
args
String