Ignore:
Timestamp:
10/06/20 13:12:20 (4 years ago)
Author:
bart
Message:

Fixes an issue with processing maxPower of a vote. Javadoc maven plugin now uses latest version.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • protocol/src/main/java/geniusweb/protocol/session/mopac/MOPACState.java

    r23 r24  
    1717import geniusweb.progress.Progress;
    1818import geniusweb.progress.ProgressRounds;
     19import geniusweb.protocol.NegoProtocol;
    1920import geniusweb.protocol.ProtocolException;
    20 import geniusweb.protocol.partyconnection.ProtocolToPartyConn;
    21 import geniusweb.protocol.partyconnection.ProtocolToPartyConnections;
    2221import geniusweb.protocol.session.SessionResult;
    2322import geniusweb.protocol.session.SessionState;
     
    2726import geniusweb.protocol.session.saop.SAOPSettings;
    2827import geniusweb.references.PartyWithProfile;
    29 import geniusweb.voting.VotingEvaluator;
    30 
     28
     29/**
     30 * Keeps track of the current {@link Phase}. Adds initializing stuff and
     31 * time/deadline checking. This state does not contain connections, this assumes
     32 * that someone else handles (i.e. {@link NegoProtocol} that and the connections
     33 * with the parties and that negotiation events are just pumped in from there.
     34 * <p>
     35 * This object is a bit tricky. It has two states
     36 * <ol>
     37 * <li>The initial state, where phase=null and connections are being made to all
     38 * parties. At this point, problems can not be handled nicely yet because there
     39 * are no PartyId's for problematic parties
     40 * <li>The working state, where all parties are connected and all problems can
     41 * be connected to an offending party.
     42 * </ol>
     43 */
    3144public class MOPACState implements SessionState {
    3245
    33         private final Phase phase;
     46        private final Phase phase; // maybe null while initializing
    3447        private final MOPACSettings settings;
    3548        private final Map<PartyId, PartyWithProfile> partyprofiles;
    36         private final ProtocolToPartyConnections connections;
    3749        private final List<Action> actions;
    3850        private final Progress progress;
     
    4456         */
    4557        public MOPACState(MOPACSettings settings) {
    46                 this(null, Arrays.asList(),
    47                                 new ProtocolToPartyConnections(Collections.emptyList()), null,
    48                                 settings, Collections.emptyMap());
     58                this(null, Arrays.asList(), null, settings, Collections.emptyMap());
    4959
    5060        }
     
    5464         *                      set something only after we have connections.
    5565         * @param actions       the legal actions that have been done in the
    56          *                      negotiation. A new-sub-list is added for each phase
    57          *                      change. It is assumed that the last element of the
    58          *                      list is the list with actions taken in the current
    59          *                      phase. first action in first list is the oldest.
    60          *                      This MUST NOT contain illegal actions. Parties doing
    61          *                      illegal actions are killed and the offending action
    62          *                      ends up in the stacktrace. Previous actions of
    63          *                      crashed parties remain standing and valid.
    64          * @param conns         the existing party connections. we assume ownership
    65          *                      of this so it should not be modified although
    66          *                      connections may of course break.
     66         *                      negotiation. {@link PartyStates#getActions()} is
     67         *                      called to collect the actions after the phase is
     68         *                      finished.first action in list is the oldest. This
     69         *                      will not contain actions that immediately led to an
     70         *                      agreement, because {@link PartyStates} removes the
     71         *                      actions that led to an agreement. This MUST NOT
     72         *                      contain illegal actions. Parties doing illegal
     73         *                      actions are killed and the offending action ends up
     74         *                      in the stacktrace. Previous actions of crashed
     75         *                      parties remain standing and valid.
    6776         * @param progress      the {@link Progress} line. can be null if not yet
    68          *                      known. This happens because during setup we first
    69          *                      add all connections, and only when we have that we
    70          *                      set the correct deadline.
     77         *                      known. null happens because during initialization
     78         *                      phase the protocol first add all connections. During
     79         *                      this time, parties may already enter the
     80         *                      failed/exception state.
    7181         * @param settings      the {@link SAOPSettings}
    7282         * @param partyprofiles map with the {@link PartyWithProfile} for connected
    7383         *                      parties. null is equivalent to an empty map.
    74          * @param evaluator     the {@link VotingEvaluator}
    7584         */
    7685        @JsonCreator
    7786        protected MOPACState(@JsonProperty("phase") Phase phase,
    7887                        @JsonProperty("actions") List<Action> actions,
    79                         @JsonProperty("connections") ProtocolToPartyConnections conns,
    8088                        @JsonProperty("progress") Progress progress,
    8189                        @JsonProperty("settings") MOPACSettings settings,
     
    8391                this.phase = phase;
    8492                this.actions = actions;
    85                 this.connections = conns;
    8693                this.progress = progress;
    8794                this.settings = settings;
     
    9097
    9198        /**
    92          * Can be called after all connections are initialized.
    93          *
    94          * @param now current time ms since 1970
    95          *
    96          * @return state with the initial partystates set.
    97          */
    98         public MOPACState initPhase(long now) {
    99                 PartyStates partyStates = new PartyStates(getPowers());
    100                 Phase firstPhase = new OfferPhase(null, partyStates,
    101                                 now + getAvailablePhaseTime(now),
    102                                 settings.getVotingEvaluation());
    103                 return new MOPACState(firstPhase, actions, connections, progress,
    104                                 settings, partyprofiles);
    105         }
    106 
    107         @Override
    108         public List<Action> getActions() {
    109                 return Collections.unmodifiableList(actions);
    110         }
    111 
    112         @Override
    113         public Progress getProgress() {
    114                 return progress;
    115         }
    116 
    117         public Map<PartyId, PartyWithProfile> getPartyProfiles() {
    118                 return Collections.unmodifiableMap(partyprofiles);
    119         }
    120 
    121         /**
    122          * @return all current/remaining active party connections. Finished/crashed
    123          *         parties should be removed immediately.
    124          */
    125         public ProtocolToPartyConnections getConnections() {
    126                 return connections;
    127         }
    128 
    129         /**
    130          * @param now current time ms since 1970
    131          * @return the max possible duration in ms of the NEXT phase. Maybe 0 or
    132          *         negative if past deadline.
    133          */
    134         private Long getAvailablePhaseTime(long now) {
    135                 // explicit check, to check also the round counts.
    136                 if (incrementProgress().isPastDeadline(now + Phase.PHASE_MINTIME))
    137                         return 0l;
    138                 return Math.min(progress.getTerminationTime().getTime() - now,
    139                                 Phase.PHASE_MAXTIME);
    140         }
    141 
    142         /**
    143          *
    144          * @param connection   the new {@link ProtocolToPartyConn}
    145          * @param partyprofile the {@link PartyWithProfile} that is associated with
    146          *                     this state
    147          * @return new {@link MOPACState} with the new connection added. This call
    148          *         ignores the progress (does not check isFinal) because we uses
    149          *         this during the setup where the deadline is not yet relevant.
    150          */
    151         protected MOPACState with(ProtocolToPartyConn connection,
    152                         PartyWithProfile partyprofile) {
    153                 if (phase != null)
    154                         throw new IllegalStateException(
    155                                         "Adding connections only allowed while initializing");
    156 
    157                 ProtocolToPartyConnections newconns = getConnections().with(connection);
    158                 Map<PartyId, PartyWithProfile> newprofiles = new HashMap<>(
    159                                 partyprofiles);
    160                 newprofiles.put(connection.getParty(), partyprofile);
    161                 return new MOPACState(null, actions, newconns, progress, settings,
    162                                 newprofiles);
    163         }
    164 
    165         /**
    166          * @param id the {@link PartyId} of the party that failed.
    167          * @param e  the {@link ProtocolException} that occurred in the party
    168          * @return a new state with the error set.
    169          */
    170         public MOPACState with(ProtocolException e) {
    171                 return new MOPACState(phase.with(e), actions, connections, progress,
    172                                 settings, partyprofiles);
    173         }
    174 
    175         /**
    176          * Sets the progress for this session. Can be set only if progress=null.
    177          * Should be set in INIT phase.
    178          *
    179          * @param newprogress the new progress
    180          * @return new {@link MOPACState} with the progress set
    181          */
    182         public MOPACState with(Progress newprogress) {
     99         * Sets the progress for this session and initial phase. Must be called
     100         * after all parties have been connected with
     101         * {@link #with(PartyId, PartyWithProfile)}.
     102         *
     103         * @param newprogress the initial {@link Progress} typically matching the
     104         *                    settings deadline object
     105         * @param now         current time ms since 1970
     106         *
     107         * @return state with the initial partystates , progress set.
     108         */
     109        public MOPACState initPhase(Progress newprogress, long now) {
    183110                if (progress != null || newprogress == null || phase != null) {
    184111                        throw new IllegalArgumentException(
    185112                                        "progress must be null, newprogress must be not null and phase must be INIT");
    186113                }
    187                 return new MOPACState(phase, actions, connections, newprogress,
    188                                 getSettings(), partyprofiles);
     114
     115                PartyStates partyStates = new PartyStates(getPowers());
     116                Phase firstPhase = new OfferPhase(partyStates,
     117                                now + getAvailablePhaseTime(newprogress, now),
     118                                settings.getVotingEvaluation());
     119                return new MOPACState(firstPhase, actions, newprogress, settings,
     120                                partyprofiles);
     121        }
     122
     123        @Override
     124        public List<Action> getActions() {
     125                return Collections.unmodifiableList(actions);
     126        }
     127
     128        @Override
     129        public Progress getProgress() {
     130                return progress;
     131        }
     132
     133        @Override
     134        public Agreements getAgreements() {
     135                return phase.getPartyStates().getAgreements();
     136        }
     137
     138        @Override
     139        public MOPACSettings getSettings() {
     140                return settings;
     141        }
     142
     143        public Map<PartyId, PartyWithProfile> getPartyProfiles() {
     144                return Collections.unmodifiableMap(partyprofiles);
     145        }
     146
     147        @Override
     148        public boolean isFinal(long now) {
     149                return phase != null && phase.isFinal(now) && !isNewPhasePossible(now);
     150        }
     151
     152        @Override
     153        public SessionResult getResult() {
     154                return new SessionResult(partyprofiles, getAgreements(),
     155                                Collections.emptyMap(), null);
     156        }
     157
     158        /**
     159         * @param progress the Progress that needs to be checked
     160         * @param now      current time ms since 1970
     161         * @return the max possible duration in ms of a phase considering the
     162         *         progress.
     163         */
     164        private static Long getAvailablePhaseTime(Progress aprogress, long now) {
     165                return Math.min(aprogress.getTerminationTime().getTime() - now,
     166                                Phase.PHASE_MAXTIME);
     167        }
     168
     169        /**
     170         * @param id           the new {@link PartyId}
     171         * @param partyprofile the {@link PartyWithProfile} that is associated with
     172         *                     this state
     173         * @return new {@link MOPACState} with the new party added. This call
     174         *         ignores the progress (does not check isFinal) because we uses
     175         *         this during the setup where the deadline is not yet relevant.
     176         */
     177        protected MOPACState with(PartyId id, PartyWithProfile partyprofile) {
     178                if (phase != null)
     179                        throw new IllegalStateException(
     180                                        "Adding connections only allowed while initializing");
     181
     182                Map<PartyId, PartyWithProfile> newprofiles = new HashMap<>(
     183                                partyprofiles);
     184                newprofiles.put(id, partyprofile);
     185                return new MOPACState(null, actions, progress, settings, newprofiles);
     186        }
     187
     188        /**
     189         * @param e the {@link ProtocolException} that occured
     190         * @return a new state with the error set. You MUST have called
     191         *         {@link #initPhase(Progress, long)} before using this
     192         */
     193        public MOPACState with(ProtocolException e) {
     194                return new MOPACState(phase.with(e), actions, progress, settings,
     195                                partyprofiles);
    189196        }
    190197
     
    202209                                Math.min(remainingNegoTime, Phase.PHASE_MAXTIME));
    203210
    204                 return new MOPACState(newphase, actions, connections,
    205                                 incrementProgress(), getSettings(), partyprofiles);
    206         }
    207 
    208         /**
    209          *
    210          * @return the next progress. Progress round advances if phase is
    211          *         {@link OptIn}.
    212          */
    213         private Progress incrementProgress() {
    214                 if (progress instanceof ProgressRounds && phase instanceof OptInPhase)
    215                         return ((ProgressRounds) progress).advance();
    216                 return progress;
    217         }
    218 
    219         @Override
    220         public boolean isFinal(long now) {
    221                 return phase != null && phase.isFinal(now) && !isNewPhasePossible(now);
     211                return new MOPACState(newphase, actions, increment(progress, phase),
     212                                getSettings(), partyprofiles);
    222213        }
    223214
     
    225216         * When this is called, all parties should have acted.
    226217         *
    227          * @param now
    228          * @return
     218         * @param now current time
     219         * @return true if there are still &gt;2 parties active and we have enough
     220         *         time for a new phase.
    229221         */
    230222        public boolean isNewPhasePossible(long now) {
    231223                // System.out.println("phase=" + phase);
    232                 boolean a = phase.getPartyStates().getNegotiatingParties().size() >= 2
    233                                 && getAvailablePhaseTime(now) > Phase.PHASE_MINTIME;
    234                 // System.out.println("newstate possible:" + a);
    235                 return a;
    236         }
    237 
    238         @Override
    239         public Agreements getAgreements() {
    240                 return phase.getPartyStates().getAgreements();
    241         }
    242 
    243         @Override
    244         public MOPACSettings getSettings() {
    245                 return settings;
     224                Progress newprogress = increment(progress, phase);
     225                if (newprogress.isPastDeadline(now + Phase.PHASE_MINTIME))
     226                        return false;
     227
     228                return phase.getPartyStates().getNegotiatingParties().size() >= 2
     229                                && getAvailablePhaseTime(newprogress,
     230                                                now) > Phase.PHASE_MINTIME;
    246231        }
    247232
     
    261246         * @param now    the current time in ms since 1970, see
    262247         *               {@link System#currentTimeMillis()}
     248         * @return new {@link MOPACState} with the action checked and registered. If
     249         *         the action is not allowed, the new state may be that the actor is
     250         *         in the exception list.
    263251         */
    264252
    265253        public MOPACState with(PartyId actor, Action action, long now) {
    266                 return new MOPACState(phase.with(actor, action, now), actions,
    267                                 connections, progress, settings, partyprofiles);
    268         }
    269 
    270         @Override
    271         public SessionResult getResult() {
    272                 return new SessionResult(partyprofiles, getAgreements(),
    273                                 Collections.emptyMap(), null);
     254                return new MOPACState(phase.with(actor, action, now), actions, progress,
     255                                settings, partyprofiles);
     256        }
     257
     258        /**
     259         * @param aprogress the progress that might need to be advanced
     260         * @param aphase    the phase
     261         * @return the next progress. Progress round advances if phase is
     262         *         {@link OptIn}.
     263         */
     264        private static Progress increment(Progress aprogress, Phase aphase) {
     265                if (aprogress instanceof ProgressRounds && aphase instanceof OptInPhase)
     266                        return ((ProgressRounds) aprogress).advance();
     267                return aprogress;
    274268        }
    275269
     
    294288        public String toString() {
    295289                return "MOPACState[" + phase + "," + settings + "," + partyprofiles
    296                                 + "," + connections + "," + progress + "," + "]";
     290                                + "," + progress + "]";
    297291        }
    298292
     
    306300                LinkedList<Action> newactions = new LinkedList<Action>(actions);
    307301                newactions.addAll(newphase.getPartyStates().getActions());
    308                 return new MOPACState(newphase, newactions, connections, progress,
    309                                 settings, partyprofiles);
     302                return new MOPACState(newphase, newactions, progress, settings,
     303                                partyprofiles);
     304        }
     305
     306        @Override
     307        public int hashCode() {
     308                final int prime = 31;
     309                int result = 1;
     310                result = prime * result + ((actions == null) ? 0 : actions.hashCode());
     311                result = prime * result
     312                                + ((partyprofiles == null) ? 0 : partyprofiles.hashCode());
     313                result = prime * result + ((phase == null) ? 0 : phase.hashCode());
     314                result = prime * result
     315                                + ((progress == null) ? 0 : progress.hashCode());
     316                result = prime * result
     317                                + ((settings == null) ? 0 : settings.hashCode());
     318                return result;
     319        }
     320
     321        @Override
     322        public boolean equals(Object obj) {
     323                if (this == obj)
     324                        return true;
     325                if (obj == null)
     326                        return false;
     327                if (getClass() != obj.getClass())
     328                        return false;
     329                MOPACState other = (MOPACState) obj;
     330                if (actions == null) {
     331                        if (other.actions != null)
     332                                return false;
     333                } else if (!actions.equals(other.actions))
     334                        return false;
     335                if (partyprofiles == null) {
     336                        if (other.partyprofiles != null)
     337                                return false;
     338                } else if (!partyprofiles.equals(other.partyprofiles))
     339                        return false;
     340                if (phase == null) {
     341                        if (other.phase != null)
     342                                return false;
     343                } else if (!phase.equals(other.phase))
     344                        return false;
     345                if (progress == null) {
     346                        if (other.progress != null)
     347                                return false;
     348                } else if (!progress.equals(other.progress))
     349                        return false;
     350                if (settings == null) {
     351                        if (other.settings != null)
     352                                return false;
     353                } else if (!settings.equals(other.settings))
     354                        return false;
     355                return true;
    310356        }
    311357
Note: See TracChangeset for help on using the changeset viewer.