package genius.gui.tournament; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import genius.core.config.MultilateralTournamentConfiguration; import genius.core.listener.DefaultListenable; import genius.core.listener.Listener; import genius.core.persistent.PersistentDataType; import genius.core.repository.MultiPartyProtocolRepItem; import genius.core.repository.ParticipantRepItem; import genius.core.repository.PartyRepItem; import genius.core.repository.ProfileRepItem; import genius.gui.deadline.DeadlineModel; import genius.gui.negosession.ContentProxy; import genius.gui.panels.BooleanModel; import genius.gui.panels.NumberModel; import genius.gui.panels.SingleSelectionModel; import genius.gui.panels.SubsetSelectionModel; /** * Contains the basic elements of MultilateralTournamentConfiguration, but * mutable and the subcomponents are listenable so that we can use it for the * MVC pattern. It listens to changes in the protocol and updates the model when * necessary. * *

* You can get notified when the multitournamentmodel is complete (as indicated * by the user, he can press 'start' in the GUI). The data passed with the * notification is the {@link MultilateralTournamentConfiguration}. * * @author W.Pasman * */ public class MultiTournamentModel extends DefaultListenable { // models are all final, as they will be used to hook up the GUI. private final SubsetSelectionModel profileModel; private final SubsetSelectionModel partyModel; private final SingleSelectionModel protocolModel; private final DeadlineModel deadlineModel = new DeadlineModel(); private final SingleSelectionModel mediatorModel; private final NumberModel numTournamentsModel = new NumberModel(1, 1, 2000000000, 1); private final NumberModel numAgentsPerSessionModel = new NumberModel(1, 1, 2000000000, 1); private final BooleanModel agentRepetitionModel = new BooleanModel(false); private final BooleanModel randomSessionOrderModel = new BooleanModel( false); private final BooleanModel enablePrintModel = new BooleanModel(false); private final BilateralOptionsModel bilateralOptionsModel; private final SingleSelectionModel persistentDatatypeModel = new SingleSelectionModel( Arrays.asList(PersistentDataType.values())); public MultiTournamentModel() { // load initial models. protocolModel = new SingleSelectionModel<>( ContentProxy.fetchProtocols()); profileModel = new SubsetSelectionModel( ContentProxy.fetchProfiles()); // stubs for the partyModel and mediatorModel, will be set properly in // updateSubmodels. partyModel = new SubsetSelectionModel( new ArrayList()); mediatorModel = new SingleSelectionModel( new ArrayList()); bilateralOptionsModel = new BilateralOptionsModel(protocolModel); updateSubmodels(); updateAgentRepetition(); addConstraints(); } public SubsetSelectionModel getProfileModel() { return profileModel; } /** * @return model containing the deadline information */ public DeadlineModel getDeadlineModel() { return deadlineModel; } /** * @return model containing the parties to use in the tournament */ public SubsetSelectionModel getPartyModel() { return partyModel; } /** * @return the model containing the number of tournaments to be run. This is * also called "number of sessions" in some places. May be somethign * historic. */ public NumberModel getNumTournamentsModel() { return numTournamentsModel; } /** * @return the model containing the number of agents per session. */ public NumberModel getNumAgentsPerSessionModel() { return numAgentsPerSessionModel; } /** * @return mediator model, or null if no mediator for this protocol */ public SingleSelectionModel getMediatorModel() { return mediatorModel; } /** * @return this model, converted in a * {@link MultilateralTournamentConfiguration}. */ public MultilateralTournamentConfiguration getConfiguration() { List profilesB = new ArrayList<>(); List partiesB = new ArrayList<>(); if (!bilateralOptionsModel.getPlayBothSides().getValue()) { profilesB = bilateralOptionsModel.getProfileModelB() .getSelectedItems(); partiesB = bilateralOptionsModel.getPartyModelB() .getSelectedItems(); } return new MultilateralTournamentConfiguration( protocolModel.getSelection(), deadlineModel.getDeadline(), mediatorModel.getSelection(), partyModel.getSelectedItems(), profileModel.getSelectedItems(), partiesB, profilesB, numTournamentsModel.getValue().intValue(), numAgentsPerSessionModel.getValue().intValue(), agentRepetitionModel.getValue(), randomSessionOrderModel.getValue(), persistentDatatypeModel.getSelection(), enablePrintModel.getValue()); } /** * @return model containing the protocol */ public SingleSelectionModel getProtocolModel() { return protocolModel; } public BooleanModel getAgentRepetitionModel() { return agentRepetitionModel; } public BooleanModel getRandomSessionOrderModel() { return randomSessionOrderModel; } /** * Call this when model is completed (user clicked 'start'). TODO check that * the model is indeed complete. */ public void modelIsComplete() { notifyChange(getConfiguration()); } public BilateralOptionsModel getBilateralOptionsModel() { return bilateralOptionsModel; } public SingleSelectionModel getPersistentDatatypeModel() { return persistentDatatypeModel; } /******************* support funcs ***********************/ /** * Update the repetition setting. Must go to "true, locked" mode if * agentsPerSession is bigger than the number of available agents. */ private void updateAgentRepetition() { agentRepetitionModel.setLock(false); if (numAgentsPerSessionModel.getValue().intValue() > partyModel .getSelectedItems().size()) { agentRepetitionModel.setValue(true); agentRepetitionModel.setLock(true); } } /** * connecting listeners that check the constraints between the fields in the * model */ private void addConstraints() { // protocol has major impact on the submodels protocolModel.addListDataListener(new ListDataListener() { @Override public void intervalRemoved(ListDataEvent e) { } @Override public void intervalAdded(ListDataEvent e) { } @Override public void contentsChanged(ListDataEvent e) { updateSubmodels(); } }); // The "Agents per session" field by default equals number of profiles; // the agent repetition is depending on this too. profileModel.addListener(new Listener() { @Override public void notifyChange(ProfileRepItem data) { numAgentsPerSessionModel .setValue(profileModel.getSelectedItems().size()); updateAgentRepetition(); } }); // #parties and numAgentsPerSession -> repetition partyModel.addListener(new Listener() { @Override public void notifyChange(ParticipantRepItem data) { updateAgentRepetition(); } }); numAgentsPerSessionModel.addListener(new Listener() { @Override public void notifyChange(Number data) { updateAgentRepetition(); } }); } /** * Update the models after a protocol change. * * @param protocol * the new protocol. */ private void updateSubmodels() { MultiPartyProtocolRepItem protocol = protocolModel.getSelection(); partyModel.setAllItems(ContentProxy.fetchPartiesForProtocol(protocol)); mediatorModel .setAllItems(ContentProxy.fetchMediatorsForProtocol(protocol)); } public BooleanModel getEnablePrint() { return enablePrintModel; } }