package geniusweb.boa; import java.lang.reflect.Parameter; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import geniusweb.actions.Action; import geniusweb.actions.ActionWithBid; import geniusweb.actions.PartyId; import geniusweb.boa.acceptancestrategy.AcceptanceStrategy; import geniusweb.boa.biddingstrategy.BiddingStrategy; import geniusweb.issuevalue.Bid; import geniusweb.party.inform.Settings; import geniusweb.profile.Profile; import geniusweb.progress.Progress; import tudelft.utilities.logging.Reporter; /** * Stores the current state of the negotiation for a {@link BoaParty}, including * the state of the opponent models * */ public class NegoState { private final Settings settings; private final Profile profile; private final Progress progress; private final Class opponentModelClass; private final AcceptanceStrategy acceptanceStrat; private final Bid lastReceivedBid; private final Map opponentModels; private final Reporter reporter; public NegoState() { this(null, null, null, null, null, null, new HashMap<>(), null); } public NegoState(Settings settings, Profile profile, Progress progr, Class omClass, AcceptanceStrategy as, Bid lastRcBid, Map oppMods, Reporter reporter) { this.settings = settings; this.profile = profile; this.progress = progr; this.opponentModelClass = omClass; this.acceptanceStrat = as; this.lastReceivedBid = lastRcBid; this.opponentModels = oppMods; this.reporter = reporter; } /** * Initialize the component. Must be called first. * * @param progress the progress to use * @param myId the Id of this party * @param as the acceptance strategy class * @param om the Class of the OpponentModels * @param reporter a {@link Reporter} to log messages and errors to * @return initialized {@link BiddingStrategy} * @throws InstantiationFailedException if one of provided classes can not * be instantiated. */ public NegoState with(Progress progr, PartyId myId, Class asClass, Class omClass, Reporter reporter) throws InstantiationFailedException { AcceptanceStrategy as; try { as = asClass.newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new InstantiationFailedException( "Failed to create " + asClass, e); } return new NegoState(settings, profile, progr, omClass, as, lastReceivedBid, opponentModels, reporter); } /** * * @param profile the profile that we use. Must be called second (after the * init call above). Can be called multiple times, if a * profile changes * @throws InstantiationFailedException if one of provided classes can not * be instantiated. */ public NegoState with(Profile prof) { if (profile != null) reporter.log(Level.WARNING, "DefaultBiddingStrategy does not support profile changes. Ignored the change."); return new NegoState(settings, prof, progress, opponentModelClass, acceptanceStrat, lastReceivedBid, opponentModels, reporter); } /** * * @return the settings for this negotiation, includes my {@link PartyId}, * {@link Parameter}, {@link Profile} etc. */ public Settings getSettings() { return settings; } /** * * @return the {@link Profile} as fetched from the profiles server, or null * if no profile was received yet. */ public Profile getProfile() { return profile; } /** * * @param action the action that was done by some participant. * @return new BoaState that includes action.getBid as last bid (if action * contains a bid), and with updated opponentmodel of that * participant. * @throws InstantiationFailedException if one of provided classes can not * be instantiated. */ public NegoState with(Action action) throws InstantiationFailedException { try { Map newmodels = updateModels(action); } catch (InstantiationException | IllegalAccessException e) { throw new InstantiationFailedException("Updating the models failed:" + e.getMessage() + ". Ignoring the action", e); } Bid lastbid = action instanceof ActionWithBid ? ((ActionWithBid) action).getBid() : lastReceivedBid; return new NegoState(settings, profile, progress, opponentModelClass, acceptanceStrat, lastbid, opponentModels, reporter); } /** * Must be called every time a 'round' as been made and the progress needs * to be incremented. * * @param progress the new value of the progress * @return new state * @throws InstantiationFailedException if one of provided classes can not * be instantiated. */ public NegoState with(Progress prog) { return new NegoState(settings, profile, prog, opponentModelClass, acceptanceStrat, lastReceivedBid, opponentModels, reporter); } /** * @param action * @return the map with the opponentmodels, with the party that did the * action updated. * @throws InstantiationException * @throws IllegalAccessException */ private Map updateModels(Action action) throws InstantiationException, IllegalAccessException { PartyId actor = action.getActor(); Map updated = extendedOpponentModels(actor); updated.put(actor, updated.get(actor).with(action, progress)); return updated; } /** * Get the current opponent model, extended with newparty if there is no * model yet for newparty. * * @param newparty a possibly new party * @return a (possibly new) opponentModels map * @throws InstantiationException * @throws IllegalAccessException */ private Map extendedOpponentModels(PartyId newparty) throws InstantiationException, IllegalAccessException { // check if this is new party if (opponentModels.containsKey(newparty)) return opponentModels; Map newmodels = new HashMap<>(opponentModels); OpponentModel newmodel = opponentModelClass.newInstance(); newmodel = newmodel.with(profile.getDomain()); newmodels.put(newparty, newmodel); return newmodels; } }