1 | from abc import ABC
|
---|
2 | from typing import List, Any
|
---|
3 |
|
---|
4 | from pyson.JsonSubTypes import JsonSubTypes
|
---|
5 | from pyson.JsonTypeInfo import JsonTypeInfo, Id, As
|
---|
6 |
|
---|
7 | from geniusweb.actions.Action import Action
|
---|
8 | from geniusweb.actions.PartyId import PartyId
|
---|
9 | from geniusweb.inform.Inform import Inform
|
---|
10 | from geniusweb.protocol.ProtocolException import ProtocolException
|
---|
11 | from geniusweb.protocol.session.mopac.PartyStates import PartyStates
|
---|
12 | from geniusweb.voting.VotingEvaluator import VotingEvaluator
|
---|
13 |
|
---|
14 |
|
---|
15 | PHASE_MAXTIME = 30000 # 30sec
|
---|
16 | PHASE_MINTIME = 100 # 100 millisec
|
---|
17 |
|
---|
18 |
|
---|
19 | @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT)
|
---|
20 | @JsonSubTypes(["geniusweb.protocol.session.mopac.phase.OfferPhase.OfferPhase",
|
---|
21 | "geniusweb.protocol.session.mopac.phase.OptInPhase.OptInPhase",
|
---|
22 | "geniusweb.protocol.session.mopac.phase.VotingPhase.VotingPhase"])
|
---|
23 | class Phase(ABC):
|
---|
24 | '''
|
---|
25 | A Phase is a part of the round structure. In each round parties have to take
|
---|
26 | multiple actions. Each action is part of a phase.
|
---|
27 |
|
---|
28 | Invariant: A phase object handles negotiation events, ensuring that the
|
---|
29 | events are handled according to the possible actions in this phase. A phase
|
---|
30 | object must always remain in a consistent state. It does so by modifying the
|
---|
31 | contained {@link PartyStates} as needed.
|
---|
32 | <p>
|
---|
33 | The standard exception handling is assumed: unchecked exceptions are thrown
|
---|
34 | only if there is a bug in the protocol. Because none of the functions in this
|
---|
35 | interface throws, any error must be either ignored or the party must be
|
---|
36 | kicked.
|
---|
37 | '''
|
---|
38 |
|
---|
39 | def With(self, actor:PartyId ,action: Action ,now:int)->"Phase" :
|
---|
40 | '''
|
---|
41 | Handle an actor's action. If a {@link ProtocolException} occurs, this is
|
---|
42 | handled by updating the PartyStates
|
---|
43 |
|
---|
44 | @param actor the real actor (may differ from the actor contained in the
|
---|
45 | action)
|
---|
46 | @param action the action submitted by actor, which this phase can really
|
---|
47 | handle.
|
---|
48 | @param now the current time
|
---|
49 | @return new VotingPhase
|
---|
50 | '''
|
---|
51 |
|
---|
52 | def WithException(self, e:ProtocolException)->"Phase" :
|
---|
53 | '''
|
---|
54 | @param e a {@link ProtocolException}
|
---|
55 | @return new Phase with a party disabled because it violated a protocol eg
|
---|
56 | breaking a websocket link.
|
---|
57 | '''
|
---|
58 |
|
---|
59 | def getInform(self)->Inform :
|
---|
60 | '''
|
---|
61 | @return the inform object to send to all parties at start of phase.
|
---|
62 | '''
|
---|
63 |
|
---|
64 | def isFinal(self, now:int) -> bool:
|
---|
65 | '''
|
---|
66 | @param now the current time
|
---|
67 | @return true iff past deadline or no more actions are allowed anyway.
|
---|
68 | (which usually means, all parties have done exactly one act).
|
---|
69 | Notice, this is the main reason that it is desirable to require
|
---|
70 | all parties to act exactly once in each phase. Without such a
|
---|
71 | rule, the protocol will always have to wait till the deadline.
|
---|
72 | '''
|
---|
73 |
|
---|
74 | def finish(self)->"Phase" :
|
---|
75 | '''
|
---|
76 | @return finished state. That means, all parties that did not act have
|
---|
77 | been kicked, new agreements have been computed, etc.
|
---|
78 | '''
|
---|
79 |
|
---|
80 | def next(self, now:int, duration:int) -> "Phase" :
|
---|
81 | '''
|
---|
82 | Determines the next phase. Resets the actions field. Can only be called
|
---|
83 | after {@link #finish()}
|
---|
84 |
|
---|
85 | @param now the current time
|
---|
86 | @param duration the max duration (ms) of the next phase. Must be between
|
---|
87 | {@link #PHASE_MINTIME} and {@link #PHASE_MAXTIME}. Also
|
---|
88 | make sure that now+duration is at most at the total
|
---|
89 | negotiation deadline.
|
---|
90 | @return the next phase, or null if negotiation is complete.
|
---|
91 | '''
|
---|
92 |
|
---|
93 | def getEvaluator(self)->VotingEvaluator :
|
---|
94 | '''
|
---|
95 | @return the voting evaluator
|
---|
96 | '''
|
---|
97 |
|
---|
98 | def getDeadline(self)->int:
|
---|
99 | '''
|
---|
100 | @return time (ms since 1970) at which phase ends. The phase may end
|
---|
101 | before, but never after this.
|
---|
102 | '''
|
---|
103 |
|
---|
104 | def getPartyStates(self)->PartyStates :
|
---|
105 | '''
|
---|
106 | @return the party states. Notice that someone must call
|
---|
107 | {@link PartyStates#finish()} if passed the deadline.
|
---|
108 | '''
|
---|
109 |
|
---|
110 | def getAllowedActions(self) -> List[Any]: # Class<? extends Action>...
|
---|
111 | '''
|
---|
112 | @return the allowed actinos in this phase
|
---|
113 | '''
|
---|