+ Start a Discussion
Andrew Hoban 6Andrew Hoban 6 

Storing a contact so it cannot be picked again math.random

Hi all,

I have a controller that allows a contact in a specific campaign to be generated with a click of a button. Every time the button is clicked a new contact will be generated.

I now need a way making sure that contact cant be selected again. Ideally there would be another button that has a list of the contacts that have been generated.

Any help on this would be much appreciated. Thank you

Controller:
public class MascotController 
{
   public List<Contact> contacts{get;set;}

   public MascotController()
   {
        getContacts();
   }

   public void getContacts()
   {
        Integer count = [SELECT COUNT() FROM Contact];
        Integer rand = Math.floor(Math.random() * count).intValue();
        Set<Id> contactIds = new Set<Id>();
        contacts = new List<Contact>();

        for(CampaignMember cm : [Select Id, ContactId from CampaignMember where Status = 'To be Called' and Campaign.Name = '2014/15 Mascot Data'])
        {
           contactIds.add(cm.ContactId);
        }
        List<String> orderBys = new List<String>{'Email Asc','Email Desc','Lastname Asc','Firstname Desc','LastModifiedDate Desc','LastModifiedDate Asc','CreatedDate Asc','CreatedDate Desc','Id Asc','Id Desc'};

        String orderBy = orderBys.get(Math.mod(rand,orderBys.size()));

        contacts = Database.query('Select Name From Contact where ID in :contactIds Order By ' + orderBy + ' Limit 1 OFFSET :rand');
    }
}

VF Page:
<apex:page showHeader="true" sideBar="true" controller="MascotController">
   <apex:form >
      <apex:pageblock id="pb" title="Mascot Winner">
         <apex:commandButton value="Generate Winner" action="{!getContacts}" rerender="randomContacts"/> 
         <apex:outputPanel id="randomContacts">
          <apex:pageblock > 
              <apex:PageBlockTable value="{!contacts}" var="item">
                  <apex:column headerValue="Contact Name" value="{!item.Name}"/>
              </apex:PageBlockTable>  
           </apex:pageblock> 
         </apex:outputPanel>
      </apex:pageBlock>
   </apex:form>
</apex:page>

 
Best Answer chosen by Andrew Hoban 6
Suneel#8Suneel#8
Sorry my bad.Please try this :)
public class MascotController 
{
   public List<Contact> contacts{get;set;}
   Set<Id> storeContacts = new Set<Id>();
   public MascotController()
   {
        getContacts();
   }
   public void getContacts()
   {
        List<CampaignMember> cList=[Select Id, ContactId from CampaignMember where Status = 'To be Called' and Campaign.Name = '2014/15 Mascot Data'];
	Id selectedContact;
	Integer contactSize=[Select ContactId from CampaignMember where Status = 'To be Called' and Campaign.Name = '2014/15 Mascot Data' group by contactId].size();

        while(storeContacts.size()<=contactSize){
            CampaignMember c=cList.get(Integer.valueOf(Math.floor(Math.random() * cList.size())));
            if(!storeContacts.contains(c.ContactId)){
		selectedContact=c.ContactId;
                storeContacts.add(c.ContactId);
                break;
            }
        }
	Contact c=[select Id,Name from contact where id=:selectedContact];
   }
}

 

All Answers

Suneel#8Suneel#8
You can try below code
 
public class MascotController 
{
   public List<Contact> contacts{get;set;}
    Set<Id> storeContacts = new Set<Id>();
   public MascotController()
   {
        getContacts();
   }
   public void getContacts()
   {
        List<Contact> cList=[Select Id, ContactId from CampaignMember where Status = 'To be Called' and Campaign.Name = '2014/15 Mascot Data'];
	Id selectedContact;

        while(storeContacts.size()<=cList.size()){
            Contact c=cList.get(Integer.valueOf(Math.floor(Math.random() * cList.size())));
            if(!storeContacts.contains(c.id)){
		selectedContact=c.id;
                storeContacts.add(c.id);
                System.debug('-->'+c.lastName);
                break;
            }
        }
	Contact c=[select Id,Name from contact where id=:selectedContact];
   }
}

 
Andrew Hoban 6Andrew Hoban 6
Thank you for the reply.

I am getting the error message
"Error: MascotController Compile Error: Illegal assignment from LIST<CampaignMember> to LIST<Contact> at line 11 column 9"

Thanks
Suneel#8Suneel#8
Sorry my bad.Please try this :)
public class MascotController 
{
   public List<Contact> contacts{get;set;}
   Set<Id> storeContacts = new Set<Id>();
   public MascotController()
   {
        getContacts();
   }
   public void getContacts()
   {
        List<CampaignMember> cList=[Select Id, ContactId from CampaignMember where Status = 'To be Called' and Campaign.Name = '2014/15 Mascot Data'];
	Id selectedContact;
	Integer contactSize=[Select ContactId from CampaignMember where Status = 'To be Called' and Campaign.Name = '2014/15 Mascot Data' group by contactId].size();

        while(storeContacts.size()<=contactSize){
            CampaignMember c=cList.get(Integer.valueOf(Math.floor(Math.random() * cList.size())));
            if(!storeContacts.contains(c.ContactId)){
		selectedContact=c.ContactId;
                storeContacts.add(c.ContactId);
                break;
            }
        }
	Contact c=[select Id,Name from contact where id=:selectedContact];
   }
}

 
This was selected as the best answer
Andrew Hoban 6Andrew Hoban 6
Thank you.

When i run the code, I am getting no errors, however no records are appearing when i press the button. 

User-added image
Suneel#8Suneel#8
Can you change the last line in getContacts method as below and check.If you don't see even then.Please check by keeping System.debug statements and see where code is breaking

contacts=[select Id,Name from contact where id=:selectedContact];
Andrew Hoban 6Andrew Hoban 6
Thank you that has worked. It will cycle through all the people and without repetition. 

Is there a way of removing the contacts that have been selected so they can never be selected again at all? If i refresh the page I am still able to generate the contact.

Thanks again for you help!
Suneel#8Suneel#8
Sorry,I didn't get you.Do you want to remove the contact from Campaign Member related list permanently so that it won't be generated even after you refresh the page. Say you have 100 campaign members,if you generate/click the button 100 times, then campaign will have 0 Campaign Members.Is it what you want?
Andrew Hoban 6Andrew Hoban 6
Hi,

No sorry, I want the contacts to remain in the campaign group. 

When the generate mascot button is clicked, I need a way of knowing that that contact has been selected. I do not want that contact to be availible again. 

At the minute, when the page is refreshed the contact can been generated again. 

I need a way of knowing that the contact has been selected before, and that it connot be selected again. 

The button is a way of picking a mascot for a particular game, and that person can only be selected once.

Thanks for your help.
Suneel#8Suneel#8
Yes below is the page block table to display already picked data
<apex:pageBlock title="Generated Contacts" rendered="{!displayList<>''}">
<apex:pageBlockTable value="{!displayList}" var="c">
    <apex:column value="{!c.name}"/>
</apex:pageBlockTable>
</apex:pageBlock>
    public List<Contact> displayList{get;set;}

Add above line in the controller and below line as the last line of the method getContacts method

    displayList=[select name from Contact where id in:storeContacts];

Please mark this as Solved if this answers your query
Andrew Hoban 6Andrew Hoban 6
Brilliant mate that works!

Wihtout being a pain, is there a way of saving the 'generated contacts' even when the page is refreshed at all? 

So when i re-enter the page, there will be a list of previously generated contacts?

Thank you
Suneel#8Suneel#8
In order to save the data you need to insert them into some object in database.Where are you planning to store them?
Suneel#8Suneel#8
Else you can create a checkbox field on campaign member object and use it to identify if this contact has been already generated.Is that fine?
Andrew Hoban 6Andrew Hoban 6
Thank you for your help.