package geniusweb.protocol.tournament.allpermutationslearn; import java.math.BigInteger; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import geniusweb.actions.FileLocation; import geniusweb.protocol.session.SessionSettings; import geniusweb.protocol.session.TeamInfo; import geniusweb.protocol.session.learn.LearnSettings; import geniusweb.protocol.tournament.ProfileList; import geniusweb.protocol.tournament.Team; import geniusweb.protocol.tournament.TournamentProtocol; import geniusweb.protocol.tournament.allpermutations.AllPermutationsSettings; import geniusweb.references.Parameters; import geniusweb.references.PartyWithProfile; import geniusweb.references.ProfileRef; import tudelft.utilities.immutablelist.FixedList; import tudelft.utilities.immutablelist.ImmutableList; import tudelft.utilities.immutablelist.JoinedList; import tudelft.utilities.immutablelist.MapThreadList; import tudelft.utilities.logging.Reporter; /** * Almost the same as AllPermutationsSettings. *

* The only additional field is the additional learnTime. This has a maximum to * the maximum number of sessions, {@link #MAX_SESSIONS}. This is because we * need to store all the {@link FileLocation}s explicitly. *

* Only the first team member is actually getting the learn time. *

* We assume that all parties have the proper persistentstate parameter already. * This is assumed to be set in the {@link Team} settings */ public class AllPermutationsLearnSettings extends AllPermutationsSettings { /** * MAX_SESSIONS is the maximum number of sessions in a tournament. It is * depending on a number of factors: *

* The MAX_MESSAGE_SIZE of the partyserver currently is 20MB. A single UUID * is about 45 bytes including double quotes and commas * */ private final static int MAX_SESSIONS = 400000; private final static ObjectMapper jackson = new ObjectMapper(); private final LearnSettings learnSettings; /** * * @param teams a list of {@link Team}s. Must contain at least * {@link #teamsPerSession} elements. The * {@link #teamsPerSession} must match the protocol: * (SAOP:1, SHAOP:2) * @param reuseTeams if true, we use PermutationsWithReturn, if false * we use PermutationsWithoutReturn to create the * teams. * @param plists list of available {@link ProfileList}s to be * permutated over the teams. Each * {@link ProfileList} must contain * {@link #teamsPerSession} elements. * @param teamsPerSession number of parties per session, must be at least 2. * @param sesettings The generic {@link SessionSettings}. * {@link SessionSettings#with(TeamInfo)} will be * used to add the required {@link TeamInfo}s. All * settings must contain a 'persistentstate' * parameter with a {@link FileLocation}. * @param nTournaments the number of times the tournament should be run. * @param learnSet the {@link LearnSettings} to be used for the * learning phase. The participants list should be * empty as this will be filled up from the teams * provided above. Only the deadline is used. */ @JsonCreator public AllPermutationsLearnSettings(@JsonProperty("teams") List teams, @JsonProperty("profileslists") List plists, @JsonProperty("reuseTeams") boolean reuseTeams, @JsonProperty("teamsPerSession") int teamsPerSession, @JsonProperty("sessionsettings") SessionSettings sesettings, @JsonProperty("numberTournaments") int nTournaments, @JsonProperty("learnSettings") LearnSettings learnSet) { super(teams, plists, reuseTeams, teamsPerSession, sesettings, nTournaments); this.learnSettings = learnSet; } @Override public TournamentProtocol getProtocol(Reporter logger) { AllPermutationsLearnState state = new AllPermutationsLearnState(this, permutations(), Collections.emptyList()); return new AllPermutationsLearnProtocol(state, logger); } @Override public Double getMaxRunTime() { return super.permutations().size().doubleValue() * (sessionsettings.getMaxRunTime() + 2d) + learnSettings.getMaxRunTime(); } /** * @return {@link ImmutableList} containing all {@link SessionSettings} for * all Sessions in the correct order. */ @Override public ImmutableList permutations() { ImmutableList allsessionsettings = super.permutations(); if (allsessionsettings.size() .compareTo(BigInteger.valueOf(MAX_SESSIONS)) > 0) throw new IllegalArgumentException( "learn-tournament exceeds max number of sessions " + MAX_SESSIONS); FixedList> filelocs = createFileLocations( allsessionsettings.size().longValue()); ImmutableList> partylistlist; ImmutableList partieslist = new FixedList(teams); ImmutableList profileslist = new FixedList( profileslists); partylistlist = getParticipants(partieslist, profileslist, teamsPerSession, reuseTeams); ImmutableList settings = new MapThreadList<>( (parties, flocs) -> createSetting(parties, flocs), partylistlist, filelocs); return new JoinedList(settings, getLearnSessions(filelocs, partylistlist)); } @Override public String toString() { return "AllPermutationsLearnSettings[" + contentString() + "," + learnSettings + "]"; } /** * * @param numsessions the number of sessions in the tournament * @return A list of list of {@link FileLocation}s. The outer list has one * entry for each session, the inner list has one * {@link FileLocation} per party. */ private FixedList> createFileLocations( long numsessions) { // like before, but all sessions need a new negotiationdata List> filelocations = new ArrayList<>(); for (long sessionnr = 0; sessionnr < numsessions; sessionnr++) { List locs = new ArrayList<>(); for (int teamnr = 0; teamnr < teamsPerSession; teamnr++) { locs.add(new FileLocation()); } filelocations.add(new FixedList<>(locs)); } FixedList> filelocs = new FixedList<>( filelocations); return filelocs; } /** * @param allsessionsettings the 'traditional session settings. * @param filelocs the {@link FileLocation}s for each session, for * each party * @param partylistlist the lists of all teams for the sessions, with * unaltered parameters matching the * {@link #teams} list * @return the final sessions, doing learning for all parties. In this * session, the number of parties may be larger than * {@link #teamsPerSession}. Learning may be spread over multiple * sessions, although we don't do this currently. */ private ImmutableList getLearnSessions( FixedList> filelocs, ImmutableList> partylistlist) { try { ProfileRef NOPROFILE = new ProfileRef("not://aprofile"); SessionSettings session = learnSettings; // add all the teams, with updated parameters, to the session for (Team team : teams) { List files = getNegoData(team, filelocs, partylistlist); // Tricky: correct parameter is list of UUID strings List filesstrings = files.stream() .map(file -> file.getUUIDString()) .collect(Collectors.toList()); Parameters parameters = new Parameters().with("negotiationdata", filesstrings); // add all the FileLocations and NOPROFILE to all team members List teaminfo = team.getParties().stream() .map(pwp -> new PartyWithProfile(pwp.with(parameters), NOPROFILE)) .collect(Collectors.toList()); session = session.with(new TeamInfo(teaminfo)); } return new FixedList(Arrays.asList(session)); } catch (URISyntaxException e) { throw new RuntimeException("Failed creating learn session", e); } } /** * @param team the team for which the {@link FileLocation}s are needed * @param filelocs the used {@link FileLocation}s for all sessions, all * teams. * @param TeamInfo the TeamInfo used for each session, team. Same dimensions * as filelocs * @return the list of FileLocations that were provided to the given team in * the negotiation sessions. */ private List getNegoData(Team team, FixedList> filelocs, ImmutableList> partylistlist) { List locs = new ArrayList<>(); for (long sessionnr = 0; sessionnr < filelocs.size() .longValue(); sessionnr++) { for (int teamnr = 0; teamnr < teamsPerSession; teamnr++) { if (team.equals( partylistlist.get(sessionnr).get(teamnr).getTeam())) locs.add(filelocs.get(sessionnr).get(teamnr)); } } return locs; } /** * * @param partyproflist a list of {@link PartyWithProfile} settings. Now, * each party gets a new negotiationdata object in * every session. * @param locs the FileLocations for the negotiationdata for all * teams * @return {@link SessionSettings}, with each party parameters extended with * its {@link FileLocation} */ private SessionSettings createSetting(ImmutableList partyproflist, ImmutableList locs) { SessionSettings settings = sessionsettings; for (int teamnr = 0; teamnr < partyproflist.size() .intValue(); teamnr++) { Parameters extraparams = new Parameters().with("negotiationdata", Arrays.asList(locs.get(teamnr))); TeamInfo teaminfo = partyproflist.get(teamnr).with(extraparams); settings = settings.with(teaminfo); } return settings; } }