1 | package geniusweb.protocol.tournament.allpermutationslearn;
|
---|
2 |
|
---|
3 | import java.math.BigInteger;
|
---|
4 | import java.net.URISyntaxException;
|
---|
5 | import java.util.ArrayList;
|
---|
6 | import java.util.Arrays;
|
---|
7 | import java.util.Collections;
|
---|
8 | import java.util.List;
|
---|
9 | import java.util.stream.Collectors;
|
---|
10 |
|
---|
11 | import com.fasterxml.jackson.annotation.JsonCreator;
|
---|
12 | import com.fasterxml.jackson.annotation.JsonProperty;
|
---|
13 | import com.fasterxml.jackson.databind.ObjectMapper;
|
---|
14 |
|
---|
15 | import geniusweb.actions.FileLocation;
|
---|
16 | import geniusweb.protocol.session.SessionSettings;
|
---|
17 | import geniusweb.protocol.session.TeamInfo;
|
---|
18 | import geniusweb.protocol.session.learn.LearnSettings;
|
---|
19 | import geniusweb.protocol.tournament.ProfileList;
|
---|
20 | import geniusweb.protocol.tournament.Team;
|
---|
21 | import geniusweb.protocol.tournament.TournamentProtocol;
|
---|
22 | import geniusweb.protocol.tournament.allpermutations.AllPermutationsSettings;
|
---|
23 | import geniusweb.references.Parameters;
|
---|
24 | import geniusweb.references.PartyWithProfile;
|
---|
25 | import geniusweb.references.ProfileRef;
|
---|
26 | import tudelft.utilities.immutablelist.FixedList;
|
---|
27 | import tudelft.utilities.immutablelist.ImmutableList;
|
---|
28 | import tudelft.utilities.immutablelist.JoinedList;
|
---|
29 | import tudelft.utilities.immutablelist.MapThreadList;
|
---|
30 | import tudelft.utilities.logging.Reporter;
|
---|
31 |
|
---|
32 | /**
|
---|
33 | * Almost the same as AllPermutationsSettings.
|
---|
34 | * <p>
|
---|
35 | * The only additional field is the additional learnTime. This has a maximum to
|
---|
36 | * the maximum number of sessions, {@link #MAX_SESSIONS}. This is because we
|
---|
37 | * need to store all the {@link FileLocation}s explicitly.
|
---|
38 | * <p>
|
---|
39 | * Only the first team member is actually getting the learn time.
|
---|
40 | * <p>
|
---|
41 | * We assume that all parties have the proper persistentstate parameter already.
|
---|
42 | * This is assumed to be set in the {@link Team} settings
|
---|
43 | */
|
---|
44 | public class AllPermutationsLearnSettings extends AllPermutationsSettings {
|
---|
45 |
|
---|
46 | /**
|
---|
47 | * MAX_SESSIONS is the maximum number of sessions in a tournament. It is
|
---|
48 | * depending on a number of factors:
|
---|
49 | * <ul>
|
---|
50 | * <li>The memory use to store all UUIDs for all parties
|
---|
51 | * <li>The MAX_MESSAGE_SIZE of a websocket message.
|
---|
52 | * </ul>
|
---|
53 | * The MAX_MESSAGE_SIZE of the partyserver currently is 20MB. A single UUID
|
---|
54 | * is about 45 bytes including double quotes and commas
|
---|
55 | * </ul>
|
---|
56 | */
|
---|
57 | private final static int MAX_SESSIONS = 400000;
|
---|
58 | private final static ObjectMapper jackson = new ObjectMapper();
|
---|
59 |
|
---|
60 | private final LearnSettings learnSettings;
|
---|
61 | private final transient ImmutableList<SessionSettings> perms2; // cache
|
---|
62 |
|
---|
63 | /**
|
---|
64 | *
|
---|
65 | * @param teams a list of {@link Team}s. Must contain at least
|
---|
66 | * {@link #teamsPerSession} elements. The
|
---|
67 | * {@link #teamsPerSession} must match the protocol:
|
---|
68 | * (SAOP:1, SHAOP:2)
|
---|
69 | * @param reuseTeams if true, we use PermutationsWithReturn, if false
|
---|
70 | * we use PermutationsWithoutReturn to create the
|
---|
71 | * teams.
|
---|
72 | * @param plists list of available {@link ProfileList}s to be
|
---|
73 | * permutated over the teams. Each
|
---|
74 | * {@link ProfileList} must contain
|
---|
75 | * {@link #teamsPerSession} elements.
|
---|
76 | * @param teamsPerSession number of parties per session, must be at least 2.
|
---|
77 | * @param sesettings The generic {@link SessionSettings}.
|
---|
78 | * {@link SessionSettings#with(TeamInfo)} will be
|
---|
79 | * used to add the required {@link TeamInfo}s. All
|
---|
80 | * settings must contain a 'persistentstate'
|
---|
81 | * parameter with a {@link FileLocation}.
|
---|
82 | * @param nTournaments the number of times the tournament should be run.
|
---|
83 | * @param learnSet the {@link LearnSettings} to be used for the
|
---|
84 | * learning phase. The participants list should be
|
---|
85 | * empty as this will be filled up from the teams
|
---|
86 | * provided above. Only the deadline is used.
|
---|
87 | */
|
---|
88 | @JsonCreator
|
---|
89 | public AllPermutationsLearnSettings(@JsonProperty("teams") List<Team> teams,
|
---|
90 | @JsonProperty("profileslists") List<ProfileList> plists,
|
---|
91 | @JsonProperty("reuseTeams") boolean reuseTeams,
|
---|
92 | @JsonProperty("teamsPerSession") int teamsPerSession,
|
---|
93 | @JsonProperty("sessionsettings") SessionSettings sesettings,
|
---|
94 | @JsonProperty("numberTournaments") int nTournaments,
|
---|
95 | @JsonProperty("learnSettings") LearnSettings learnSet) {
|
---|
96 | super(teams, plists, reuseTeams, teamsPerSession, sesettings,
|
---|
97 | nTournaments);
|
---|
98 | this.learnSettings = learnSet;
|
---|
99 | this.perms2 = permutations2();
|
---|
100 | }
|
---|
101 |
|
---|
102 | @Override
|
---|
103 | public TournamentProtocol getProtocol(Reporter logger) {
|
---|
104 | AllPermutationsLearnState state = new AllPermutationsLearnState(this,
|
---|
105 | Collections.emptyList());
|
---|
106 | return new AllPermutationsLearnProtocol(state, logger);
|
---|
107 | }
|
---|
108 |
|
---|
109 | @Override
|
---|
110 | public Double getMaxRunTime() {
|
---|
111 | return super.permutations().size().doubleValue()
|
---|
112 | * (sessionsettings.getMaxRunTime() + 2d)
|
---|
113 | + learnSettings.getMaxRunTime();
|
---|
114 | }
|
---|
115 |
|
---|
116 | @Override
|
---|
117 | public ImmutableList<SessionSettings> permutations() {
|
---|
118 | return this.perms2;
|
---|
119 | }
|
---|
120 |
|
---|
121 | /**
|
---|
122 | * @return {@link ImmutableList} containing all {@link SessionSettings} for
|
---|
123 | * all Sessions in the correct order. Overrides the parent version
|
---|
124 | * of this.
|
---|
125 | */
|
---|
126 | protected ImmutableList<SessionSettings> permutations2() {
|
---|
127 |
|
---|
128 | ImmutableList<ImmutableList<TeamInfo>> partylistlist;
|
---|
129 | ImmutableList<Team> partieslist = new FixedList<Team>(teams);
|
---|
130 | ImmutableList<ProfileList> profileslist = new FixedList<ProfileList>(
|
---|
131 | profileslists);
|
---|
132 | partylistlist = getParticipantsOneTournament(partieslist, profileslist,
|
---|
133 | teamsPerSession, reuseTeams);
|
---|
134 |
|
---|
135 | if (partylistlist.size().multiply(BigInteger.valueOf(numberTournaments))
|
---|
136 | .compareTo(BigInteger.valueOf(MAX_SESSIONS)) > 0)
|
---|
137 | throw new IllegalArgumentException(
|
---|
138 | "learn-tournament exceeds max number of sessions "
|
---|
139 | + MAX_SESSIONS);
|
---|
140 |
|
---|
141 | // we have to generate separate filelocations for each session...
|
---|
142 | ImmutableList<SessionSettings> allSettings = null;
|
---|
143 | for (int tournamentnr = 0; tournamentnr < getNrTournaments(); tournamentnr++) {
|
---|
144 | FixedList<FixedList<FileLocation>> filelocs = createFileLocations(
|
---|
145 | partylistlist.size().longValue());
|
---|
146 | ImmutableList<SessionSettings> settings = new MapThreadList<>(
|
---|
147 | (parties, flocs) -> createSetting(parties, flocs),
|
---|
148 | partylistlist, filelocs);
|
---|
149 | settings = new JoinedList<SessionSettings>(settings,
|
---|
150 | getLearnSessions(filelocs, partylistlist));
|
---|
151 | allSettings = allSettings == null ? settings
|
---|
152 | : new JoinedList<SessionSettings>(allSettings, settings);
|
---|
153 | }
|
---|
154 |
|
---|
155 | return allSettings;
|
---|
156 | }
|
---|
157 |
|
---|
158 | @Override
|
---|
159 | public String toString() {
|
---|
160 | return "AllPermutationsLearnSettings[" + contentString() + ","
|
---|
161 | + learnSettings + "]";
|
---|
162 | }
|
---|
163 |
|
---|
164 | /**
|
---|
165 | *
|
---|
166 | * @param numsessions the number of sessions in the tournament
|
---|
167 | * @return A list of list of {@link FileLocation}s. The outer list has one
|
---|
168 | * entry for each session, the inner list has one
|
---|
169 | * {@link FileLocation} per party.
|
---|
170 | */
|
---|
171 | private FixedList<FixedList<FileLocation>> createFileLocations(
|
---|
172 | long numsessions) {
|
---|
173 | // like before, but all sessions need a new negotiationdata
|
---|
174 | List<FixedList<FileLocation>> filelocations = new ArrayList<>();
|
---|
175 | for (long sessionnr = 0; sessionnr < numsessions; sessionnr++) {
|
---|
176 | List<FileLocation> locs = new ArrayList<>();
|
---|
177 | for (int teamnr = 0; teamnr < teamsPerSession; teamnr++) {
|
---|
178 | locs.add(new FileLocation());
|
---|
179 | }
|
---|
180 | filelocations.add(new FixedList<>(locs));
|
---|
181 | }
|
---|
182 | FixedList<FixedList<FileLocation>> filelocs = new FixedList<>(
|
---|
183 | filelocations);
|
---|
184 | return filelocs;
|
---|
185 | }
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * @param allsessionsettings the 'traditional session settings.
|
---|
189 | * @param filelocs the {@link FileLocation}s for each session, for
|
---|
190 | * each party
|
---|
191 | * @param partylistlist the lists of all teams for the sessions, with
|
---|
192 | * unaltered parameters matching the
|
---|
193 | * {@link #teams} list
|
---|
194 | * @return the final sessions, doing learning for all parties. In this
|
---|
195 | * session, the number of parties may be larger than
|
---|
196 | * {@link #teamsPerSession}. Learning may be spread over multiple
|
---|
197 | * sessions, although we don't do this currently.
|
---|
198 | */
|
---|
199 | private ImmutableList<SessionSettings> getLearnSessions(
|
---|
200 | FixedList<FixedList<FileLocation>> filelocs,
|
---|
201 | ImmutableList<ImmutableList<TeamInfo>> partylistlist) {
|
---|
202 | try {
|
---|
203 | ProfileRef NOPROFILE = new ProfileRef("not://aprofile");
|
---|
204 |
|
---|
205 | SessionSettings session = learnSettings;
|
---|
206 | // add all the teams, with updated parameters, to the session
|
---|
207 | for (Team team : teams) {
|
---|
208 | List<FileLocation> files = getNegoData(team, filelocs,
|
---|
209 | partylistlist);
|
---|
210 | // Tricky: correct parameter is list of UUID strings
|
---|
211 | List<String> filesstrings = files.stream()
|
---|
212 | .map(file -> file.getUUIDString())
|
---|
213 | .collect(Collectors.toList());
|
---|
214 | Parameters parameters = new Parameters().with("negotiationdata",
|
---|
215 | filesstrings);
|
---|
216 | // add all the FileLocations and NOPROFILE to all team members
|
---|
217 | List<PartyWithProfile> teaminfo = team.getParties().stream()
|
---|
218 | .map(pwp -> new PartyWithProfile(pwp.with(parameters),
|
---|
219 | NOPROFILE))
|
---|
220 | .collect(Collectors.toList());
|
---|
221 | session = session.with(new TeamInfo(teaminfo));
|
---|
222 | }
|
---|
223 |
|
---|
224 | return new FixedList<SessionSettings>(Arrays.asList(session));
|
---|
225 | } catch (URISyntaxException e) {
|
---|
226 | throw new RuntimeException("Failed creating learn session", e);
|
---|
227 | }
|
---|
228 | }
|
---|
229 |
|
---|
230 | /**
|
---|
231 | * @param team the team for which the {@link FileLocation}s are needed
|
---|
232 | * @param filelocs the used {@link FileLocation}s for all sessions, all
|
---|
233 | * teams.
|
---|
234 | * @param TeamInfo the TeamInfo used for each session, team. Same dimensions
|
---|
235 | * as filelocs
|
---|
236 | * @return the list of FileLocations that were provided to the given team in
|
---|
237 | * the negotiation sessions.
|
---|
238 | */
|
---|
239 | private List<FileLocation> getNegoData(Team team,
|
---|
240 | FixedList<FixedList<FileLocation>> filelocs,
|
---|
241 | ImmutableList<ImmutableList<TeamInfo>> partylistlist) {
|
---|
242 | List<FileLocation> locs = new ArrayList<>();
|
---|
243 | for (long sessionnr = 0; sessionnr < filelocs.size()
|
---|
244 | .longValue(); sessionnr++) {
|
---|
245 | for (int teamnr = 0; teamnr < teamsPerSession; teamnr++) {
|
---|
246 | if (team.equals(
|
---|
247 | partylistlist.get(sessionnr).get(teamnr).getTeam()))
|
---|
248 | locs.add(filelocs.get(sessionnr).get(teamnr));
|
---|
249 | }
|
---|
250 | }
|
---|
251 | return locs;
|
---|
252 |
|
---|
253 | }
|
---|
254 |
|
---|
255 | /**
|
---|
256 | *
|
---|
257 | * @param partyproflist a list of {@link PartyWithProfile} settings. Now,
|
---|
258 | * each party gets a new negotiationdata object in
|
---|
259 | * every session.
|
---|
260 | * @param locs the FileLocations for the negotiationdata for all
|
---|
261 | * teams
|
---|
262 | * @return {@link SessionSettings}, with each party parameters extended with
|
---|
263 | * its {@link FileLocation}
|
---|
264 | */
|
---|
265 | private SessionSettings createSetting(ImmutableList<TeamInfo> partyproflist,
|
---|
266 | ImmutableList<FileLocation> locs) {
|
---|
267 | SessionSettings settings = sessionsettings;
|
---|
268 | for (int teamnr = 0; teamnr < partyproflist.size()
|
---|
269 | .intValue(); teamnr++) {
|
---|
270 | Parameters extraparams = new Parameters().with("negotiationdata",
|
---|
271 | Arrays.asList(locs.get(teamnr)));
|
---|
272 | TeamInfo teaminfo = partyproflist.get(teamnr).with(extraparams);
|
---|
273 | settings = settings.with(teaminfo);
|
---|
274 | }
|
---|
275 | return settings;
|
---|
276 | }
|
---|
277 |
|
---|
278 | }
|
---|