1 | package geniusweb.logconverter;
|
---|
2 |
|
---|
3 | import java.io.IOException;
|
---|
4 | import java.math.BigDecimal;
|
---|
5 | import java.util.ArrayList;
|
---|
6 | import java.util.HashMap;
|
---|
7 | import java.util.List;
|
---|
8 | import java.util.Map;
|
---|
9 | import java.util.Objects;
|
---|
10 | import java.util.logging.Level;
|
---|
11 |
|
---|
12 | import javax.websocket.DeploymentException;
|
---|
13 |
|
---|
14 | import com.fasterxml.jackson.annotation.JsonProperty;
|
---|
15 |
|
---|
16 | import geniusweb.actions.PartyId;
|
---|
17 | import geniusweb.inform.Agreements;
|
---|
18 | import geniusweb.issuevalue.Bid;
|
---|
19 | import geniusweb.profile.PartialOrdering;
|
---|
20 | import geniusweb.profile.utilityspace.UtilitySpace;
|
---|
21 | import geniusweb.profileconnection.ProfileConnectionFactory;
|
---|
22 | import geniusweb.profileconnection.ProfileInterface;
|
---|
23 | import geniusweb.protocol.session.SessionResult;
|
---|
24 | import geniusweb.references.PartyWithProfile;
|
---|
25 | import geniusweb.references.ProfileRef;
|
---|
26 | import tudelft.utilities.logging.Reporter;
|
---|
27 |
|
---|
28 | /**
|
---|
29 | * Contains SessionResult including the utilities.
|
---|
30 | */
|
---|
31 | public class SessionResultWithUtils extends SessionResult {
|
---|
32 |
|
---|
33 | private final Map<PartyId, BigDecimal> utilities;
|
---|
34 | private final static transient Map<ProfileRef, UtilitySpace> profilecache = new HashMap<>();;
|
---|
35 |
|
---|
36 | /**
|
---|
37 | *
|
---|
38 | * @param res a {@link SessionResult}
|
---|
39 | * @param utils a map of the netto utility (including penalty) by each
|
---|
40 | * party. 0 if not known or invalid.
|
---|
41 | */
|
---|
42 | public SessionResultWithUtils(
|
---|
43 | @JsonProperty("participants") Map<PartyId, PartyWithProfile> participants,
|
---|
44 | @JsonProperty("agreements") Agreements agreements,
|
---|
45 | @JsonProperty("penalties") Map<PartyId, Double> penalties,
|
---|
46 | @JsonProperty("error") Throwable error,
|
---|
47 | @JsonProperty("utilities") Map<PartyId, BigDecimal> utils) {
|
---|
48 | super(participants, agreements, penalties, error);
|
---|
49 | this.utilities = new HashMap<>(utils);
|
---|
50 | List<PartyId> missed = new ArrayList<PartyId>(participants.keySet());
|
---|
51 | missed.removeAll(utils.keySet());
|
---|
52 | if (!missed.isEmpty())
|
---|
53 | throw new IllegalArgumentException(
|
---|
54 | "participants " + missed + " must also get a utility");
|
---|
55 |
|
---|
56 | }
|
---|
57 |
|
---|
58 | /**
|
---|
59 | * adds utility values to a standard SessionResult.
|
---|
60 | *
|
---|
61 | * @param res the standard {@link SessionResult}
|
---|
62 | * @return a {@link SessionResultWithUtils}. The utilities for of the
|
---|
63 | * agreement are computed using the profile available in the given
|
---|
64 | * {@link SessionResult}. The penalty will be subtracted from this.
|
---|
65 | * Notice that the final value thus can be negative.
|
---|
66 | * <p>
|
---|
67 | * If there is no agreement, the utility of the reservation bid will
|
---|
68 | * be used. If there is no reservation bid, utility is 0.
|
---|
69 | * <p>
|
---|
70 | * If a profile is not a {@link UtilitySpace}, eg the profile is a
|
---|
71 | * {@link PartialOrdering} or is unavailable (eg security
|
---|
72 | * restrictions or server down), the utility will be set to 0.
|
---|
73 | * <p>
|
---|
74 | * Any penalty will be subtracted "as is", so if the penalty is 0.2
|
---|
75 | */
|
---|
76 | public static SessionResultWithUtils create(SessionResult res,
|
---|
77 | Reporter reporter) {
|
---|
78 | Map<PartyId, UtilitySpace> profiles = new HashMap<>();
|
---|
79 | Map<PartyId, BigDecimal> utils = new HashMap<>();
|
---|
80 | Map<PartyId, Bid> agreements = res.getAgreements().getMap();
|
---|
81 |
|
---|
82 | for (PartyId party : res.getParticipants().keySet()) {
|
---|
83 | BigDecimal util = BigDecimal.ZERO;
|
---|
84 | UtilitySpace prof = getProfile(
|
---|
85 | res.getParticipants().get(party).getProfile(), reporter);
|
---|
86 | if (prof != null) {
|
---|
87 | Bid bid = agreements.get(party);
|
---|
88 | if (bid == null) {
|
---|
89 | if (prof.getReservationBid() != null)
|
---|
90 | util = prof.getUtility(prof.getReservationBid());
|
---|
91 | } else {
|
---|
92 | // check we have profile to avoid repeated errors
|
---|
93 | util = prof.getUtility(bid);
|
---|
94 | Double penalty = res.getPenalties().get(party);
|
---|
95 | if (penalty != null) {
|
---|
96 | util = util
|
---|
97 | .subtract(new BigDecimal(penalty.toString()));
|
---|
98 | }
|
---|
99 | }
|
---|
100 | }
|
---|
101 | utils.put(party, util);
|
---|
102 | }
|
---|
103 | return new SessionResultWithUtils(res.getParticipants(),
|
---|
104 | res.getAgreements(), res.getPenalties(), res.getError(), utils);
|
---|
105 | }
|
---|
106 |
|
---|
107 | /**
|
---|
108 | * @param profileref
|
---|
109 | * @param reporter
|
---|
110 | * @return profile {@link UtilitySpace}, or null if profile can't be
|
---|
111 | * fetched. Profiles are cached to avoid repeated fetching.
|
---|
112 | */
|
---|
113 | private static UtilitySpace getProfile(ProfileRef profileref,
|
---|
114 | Reporter reporter) {
|
---|
115 | UtilitySpace us = null;
|
---|
116 | if (!profilecache.containsKey(profileref)) {
|
---|
117 | try {
|
---|
118 | ProfileInterface interf = ProfileConnectionFactory
|
---|
119 | .create(profileref.getURI(), reporter);
|
---|
120 | us = (UtilitySpace) interf.getProfile();
|
---|
121 | } catch (IOException | DeploymentException e) {
|
---|
122 | e.printStackTrace();
|
---|
123 | reporter.log(Level.WARNING,
|
---|
124 | "Failed to get profile:" + e.getMessage(), e);
|
---|
125 | }
|
---|
126 | profilecache.put(profileref, us);
|
---|
127 | }
|
---|
128 | return profilecache.get(profileref);
|
---|
129 | }
|
---|
130 |
|
---|
131 | /**
|
---|
132 | *
|
---|
133 | * @return the netto utility achieved by each party.
|
---|
134 | */
|
---|
135 | public Map<PartyId, BigDecimal> getUtilities() {
|
---|
136 | return utilities;
|
---|
137 | }
|
---|
138 |
|
---|
139 | @Override
|
---|
140 | public String toString() {
|
---|
141 | // not so important as toString is mainly for debugging.
|
---|
142 | return "SessionResultWithUtils[" + super.toString() + "," + utilities
|
---|
143 | + "]";
|
---|
144 | }
|
---|
145 |
|
---|
146 | @Override
|
---|
147 | public int hashCode() {
|
---|
148 | final int prime = 31;
|
---|
149 | int result = super.hashCode();
|
---|
150 | result = prime * result + Objects.hash(utilities);
|
---|
151 | return result;
|
---|
152 | }
|
---|
153 |
|
---|
154 | @Override
|
---|
155 | public boolean equals(Object obj) {
|
---|
156 | if (this == obj)
|
---|
157 | return true;
|
---|
158 | if (!super.equals(obj))
|
---|
159 | return false;
|
---|
160 | if (getClass() != obj.getClass())
|
---|
161 | return false;
|
---|
162 | SessionResultWithUtils other = (SessionResultWithUtils) obj;
|
---|
163 | return Objects.equals(utilities, other.utilities);
|
---|
164 | }
|
---|
165 |
|
---|
166 | }
|
---|