aboutsummaryrefslogtreecommitdiff
path: root/diplomacy
diff options
context:
space:
mode:
Diffstat (limited to 'diplomacy')
-rw-r--r--diplomacy/daide/requests.py779
-rw-r--r--diplomacy/daide/tests/test_requests.py886
-rw-r--r--diplomacy/utils/strings.py8
3 files changed, 1673 insertions, 0 deletions
diff --git a/diplomacy/daide/requests.py b/diplomacy/daide/requests.py
new file mode 100644
index 0000000..0a47a52
--- /dev/null
+++ b/diplomacy/daide/requests.py
@@ -0,0 +1,779 @@
+# ==============================================================================
+# Copyright (C) 2019 - Philip Paquette
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <https://www.gnu.org/licenses/>.
+# ==============================================================================
+""" Daide Requests - Contains a list of requests sent by client to server """
+from diplomacy.communication.requests import _AbstractGameRequest
+from diplomacy.daide.clauses import String, Number, Power, Order, Turn, SingleToken, strip_parentheses, \
+ break_next_group, parse_bytes
+from diplomacy.daide import tokens
+from diplomacy.daide.tokens import Token, is_ascii_token
+from diplomacy.utils import parsing, strings
+
+class RequestBuilder():
+ """ Builds DaideRequest from bytes or tokens """
+ @staticmethod
+ def from_bytes(daide_bytes, **kwargs):
+ """ Builds a request from DAIDE bytes
+ :param daide_bytes: The bytes representation of a request
+ :return: The DaideRequest built from the bytes
+ """
+ if len(daide_bytes) < 2:
+ return None
+ initial_bytes = daide_bytes[:2]
+ if initial_bytes not in __REQUEST_CONSTRUCTORS__:
+ raise ValueError('Unable to find a constructor for %s' % str(Token(from_bytes=initial_bytes)))
+ request = __REQUEST_CONSTRUCTORS__[initial_bytes](**kwargs) # type: DaideRequest
+ request.parse_bytes(daide_bytes)
+ return request
+
+class DaideRequest(_AbstractGameRequest):
+ """ Represents a DAIDE request. """
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self._bytes = b''
+ self._str = ''
+ super(DaideRequest, self).__init__(token='',
+ game_id='',
+ game_role='',
+ phase='',
+ **kwargs)
+
+ def __bytes__(self):
+ """ Returning the bytes representation of the request """
+ return self._bytes
+
+ def __str__(self):
+ """ Returning the string representation of the request """
+ return self._str
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ assert len(daide_bytes) % 2 == 0, 'Expected request to have an even number of bytes. Got %d' % len(daide_bytes)
+ self._bytes = daide_bytes
+
+ # Building str representation
+ while daide_bytes:
+ token = Token(from_bytes=(daide_bytes[0], daide_bytes[1]))
+ new_str = str(token)
+ daide_bytes = daide_bytes[2:]
+ pad = '' if (not self._str
+ or self._str[-1] == '('
+ or new_str == ')'
+ or (is_ascii_token(token) and new_str != '(')) else ' '
+ self._str = self._str + pad + new_str
+
+
+# ====================
+# Connection requests
+# ====================
+
+class NameRequest(DaideRequest):
+ """ Represents a NME DAIDE request. Can be sent by the client as soon as it connects to the server.
+ Syntax:
+ NME ('name') ('version')
+ """
+ __slots__ = ['client_name', 'client_version']
+ params = {
+ strings.CLIENT_NAME: str,
+ strings.CLIENT_VERSION: str
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.client_name = ''
+ self.client_version = ''
+ super(NameRequest, self).__init__(client_name='', client_version='', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(NameRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ client_name, daide_bytes = parse_bytes(String, daide_bytes)
+ client_version, daide_bytes = parse_bytes(String, daide_bytes)
+ assert str(lead_token) == 'NME', 'Expected NME request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.client_name = str(client_name)
+ self.client_version = str(client_version)
+
+class ObserverRequest(DaideRequest):
+ """ Represents a NME DAIDE request. Can be sent by the client as soon as it connects to the server.
+ Syntax:
+ OBS
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(ObserverRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'OBS', 'Expected OBS request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+class IAmRequest(DaideRequest):
+ """ Represents a IAM DAIDE request. Can be sent by the client at anytime to rejoin the game.
+ Syntax:
+ IAM (power) (passcode)
+ """
+ __slots__ = ['power_name', 'passcode']
+ params = {
+ strings.POWER_NAME: str,
+ strings.PASSCODE: parsing.OptionalValueType(int)
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.power_name = ''
+ self.passcode = 0
+ super(IAmRequest, self).__init__(power_name='', passcode=0, **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(IAmRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'IAM', 'Expected IAM request'
+
+ # Power
+ power_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ power_group_bytes = strip_parentheses(power_group_bytes)
+ power, power_group_bytes = parse_bytes(Power, power_group_bytes)
+ assert not power_group_bytes, '%s bytes remaining in power group. Request is malformed' % len(power_group_bytes)
+
+ # Passcode
+ passcode_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ passcode_group_bytes = strip_parentheses(passcode_group_bytes)
+ passcode, passcode_group_bytes = parse_bytes(SingleToken, passcode_group_bytes)
+ assert not passcode_group_bytes, '%s bytes remaining in passcode group. Req. error' % len(passcode_group_bytes)
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.power_name = str(power)
+ self.passcode = str(passcode)
+
+class HelloRequest(DaideRequest):
+ """ Represents a HLO DAIDE request. Sent by the client to request a copy of the HLO message.
+ Syntax:
+ HLO
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(HelloRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'HLO', 'Expected HLO request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+class MapRequest(DaideRequest):
+ """ Represents a MAP DAIDE request. Sent by the client to request a copy of the MAP message.
+ Syntax:
+ MAP
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(MapRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'MAP', 'Expected MAP request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+class MapDefinitionRequest(DaideRequest):
+ """ Represents a MDF DAIDE request. Sent by the client to request the map definition of the game.
+ Syntax:
+ MDF
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(MapDefinitionRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'MDF', 'Expected MDF request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+
+# ====================
+# Game updates
+# ====================
+
+class SupplyCentreOwnershipRequest(DaideRequest):
+ """ Represents a SCO DAIDE request. Sent by the client to request a copy of the last SCO message.
+ Syntax:
+ SCO
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(SupplyCentreOwnershipRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'SCO', 'Expected SCO request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+class CurrentPositionRequest(DaideRequest):
+ """ Represents a NOW DAIDE request. Sent by the client to request a copy of the last NOW message.
+ Syntax:
+ NOW
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(CurrentPositionRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'NOW', 'Expected NOW request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+class HistoryRequest(DaideRequest):
+ """ Represents a HST DAIDE request. Sent by the client to request a copy of a previous ORD, SCO and NOW messages.
+ Syntax:
+ HST (turn)
+ """
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.phase = ''
+ super(HistoryRequest, self).__init__(**kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(HistoryRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'HST', 'Expected HST request'
+
+ # Turn
+ turn, daide_bytes = parse_bytes(Turn, daide_bytes)
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.phase = str(turn)
+
+
+# ====================
+# Orders
+# ====================
+
+class SubmitOrdersRequest(DaideRequest):
+ """ Represents a SUB DAIDE request. Sent by the client to submit orders.
+ Syntax:
+ SUB (order) (order) ...
+ SUB (turn) (order) (order) ...
+ order syntax:
+ (unit) HLD # Hold
+ (unit) MTO province # Move to
+ (unit) SUP (unit) # Support
+ (unit) SUP (unit) MTO (prov_no_coast) # Support to move
+ (unit) CVY (unit) CTO province # Convoy
+ (unit) CTO province VIA (sea_prov sea_prov ...) # Convoy to via provinces
+ (unit) RTO province # Retreat to
+ (unit) DSB # Disband (R phase)
+ (unit) BLD # Build
+ (unit) REM # Remove (A phase)
+ (unit) WVE # Waive
+ """
+ __slots__ = ['power_name', 'orders']
+ params = {
+ strings.POWER_NAME: parsing.OptionalValueType(str),
+ strings.ORDERS: parsing.SequenceType(str)
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.power_name = None
+ self.phase = ''
+ self.orders = []
+ super(SubmitOrdersRequest, self).__init__(power_name='', orders=[], **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(SubmitOrdersRequest, self).parse_bytes(daide_bytes)
+ orders = []
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ turn, daide_bytes = parse_bytes(Turn, daide_bytes, on_error='ignore')
+ while daide_bytes:
+ order, daide_bytes = parse_bytes(Order, daide_bytes)
+ orders += [order]
+ assert str(lead_token) == 'SUB', 'Expected SUB request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.phase = '' if not turn else str(turn)
+ self.power_name = None if not orders or not orders[0].power_name else str(orders[0].power_name)
+ self.orders = [str(order) for order in orders]
+
+class MissingOrdersRequest(DaideRequest):
+ """ Represents a MIS DAIDE request. Sent by the client to request a copy of the current MIS message.
+ Syntax:
+ MIS
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(MissingOrdersRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'MIS', 'Expected MIS request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+class GoFlagRequest(DaideRequest):
+ """ Represents a GOF DAIDE request. Sent by the client to notify that the client is ready to process the turn.
+ Syntax:
+ GOF
+ """
+ __slots__ = []
+ params = {}
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(GoFlagRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'GOF', 'Expected GOF request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+
+# ====================
+# Deadline
+# ====================
+
+class TimeToDeadlineRequest(DaideRequest):
+ """ Represents a TME DAIDE request. Sent by the client to request a TME message or to request it at a later time.
+ Syntax:
+ TME
+ TME (seconds)
+ """
+ __slots__ = ['seconds']
+ params = {
+ strings.SECONDS: parsing.OptionalValueType(int)
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.seconds = None
+ super(TimeToDeadlineRequest, self).__init__(seconds=0, **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(TimeToDeadlineRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ seconds_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ assert str(lead_token) == 'TME', 'Expected TME request'
+
+ # Seconds
+ if seconds_group_bytes:
+ seconds_group_bytes = strip_parentheses(seconds_group_bytes)
+ seconds, daide_bytes = parse_bytes(Number, seconds_group_bytes)
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.seconds = None if not seconds_group_bytes else int(seconds)
+
+
+# ====================
+# End of the game
+# ====================
+
+class DrawRequest(DaideRequest):
+ """ Represents a DRW DAIDE request. Sent by the client to notify that the client would accept a draw.
+ Syntax:
+ DRW
+ LVL 10:
+ DRW (power power ...)
+ """
+ __slots__ = ['powers']
+ params = {
+ strings.POWERS: parsing.SequenceType(str)
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.powers = []
+ super(DrawRequest, self).__init__(powers=[], **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(DrawRequest, self).parse_bytes(daide_bytes)
+ powers = []
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'DRW', 'Expected DRW request'
+
+ # Powers
+ powers_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ if powers_group_bytes:
+ powers_group_bytes = strip_parentheses(powers_group_bytes)
+ while powers_group_bytes:
+ power, powers_group_bytes = parse_bytes(Power, powers_group_bytes)
+ powers += [power]
+
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.powers = [str(power) for power in powers]
+
+
+# ====================
+# Messaging
+# ====================
+
+class SendMessageRequest(DaideRequest):
+ """ Represents a SND DAIDE request
+ Syntax:
+ SND (power ...) (press_message)
+ SND (power ...) (reply)
+ SND (turn) (power ...) (press_message)
+ SND (turn) (power ...) (reply)
+ Press message syntax:
+ PRP (arrangement)
+ CCL (press_message)
+ FCT (arrangement)
+ TRY (tokens)
+ Reply syntax:
+ YES (press_message)
+ REJ (press_message)
+ BWX (press_message)
+ HUH (press_message)
+ """
+ __slots__ = ['powers', 'message_bytes']
+ params = {
+ strings.POWERS: parsing.SequenceType(str),
+ strings.MESSAGE_BYTES: parsing.OptionalValueType(str),
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.phase = ''
+ self.powers = []
+ self.message_bytes = None
+ super(SendMessageRequest, self).__init__(powers=[], press_message='', reply='', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(SendMessageRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ assert str(lead_token) == 'SND', 'Expected SND request'
+
+ # Turn
+ turn, daide_bytes = parse_bytes(Turn, daide_bytes, on_error='ignore')
+
+ # Powers
+ powers = []
+ powers_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ powers_group_bytes = strip_parentheses(powers_group_bytes)
+ while powers_group_bytes:
+ power, powers_group_bytes = parse_bytes(Power, powers_group_bytes)
+ powers += [power]
+ assert powers, 'Expected a group of `power`. Request is malformed'
+
+ # Press message or reply
+ message_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ message_group_bytes = strip_parentheses(message_group_bytes)
+ assert message_group_bytes, 'Expected a `press_message` or a `reply`. Request is malformed'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.phase = '' if not turn else str(turn)
+ self.powers = [str(power) for power in powers]
+ self.message_bytes = message_group_bytes
+
+# ====================
+# Cancel Request
+# ====================
+
+class NotRequest(DaideRequest):
+ """ Represents a NOT DAIDE request. Sent by the client to cancel a previous request.
+ Syntax:
+ NOT (SUB) # Cancel all submitted orders
+ NOT (SUB (order)) # Cancel specific submitted order
+ NOT (GOF) # Do not process orders until the deadline
+ NOT (TME) # Cancel all requested time messages
+ NOT (TME (seconds)) # Cancel specific requested time message
+ NOT (DRW) # Cancel all draw requests
+ """
+ __slots__ = ['request']
+ params = {
+ strings.REQUEST: parsing.JsonableClassType(DaideRequest)
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.request = None # type: DaideRequest
+ super(NotRequest, self).__init__(request=DaideRequest(), **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(NotRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ request_group_bytes, daide_bytes = break_next_group(daide_bytes)
+ assert str(lead_token) == 'NOT', 'Expected NOT request'
+
+ # Request
+ request_group_bytes = strip_parentheses(request_group_bytes)
+ request = RequestBuilder.from_bytes(request_group_bytes)
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.request = request
+
+# ========================
+# Accept / Reject Response
+# ========================
+
+class AcceptRequest(DaideRequest):
+ """ Represents a YES DAIDE request.
+ Syntax:
+ YES (MAP ('name'))
+ YES (SVE ('gamename'))
+ """
+ __slots__ = ['response_bytes']
+ params = {
+ strings.RESPONSE_BYTES: bytes
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.response_bytes = b''
+ super(AcceptRequest, self).__init__(response_bytes=b'', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(AcceptRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ response_bytes, daide_bytes = break_next_group(daide_bytes)
+ response_bytes = strip_parentheses(response_bytes)
+ assert str(lead_token) == 'YES', 'Expected YES request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.response_bytes = response_bytes
+
+class RejectRequest(DaideRequest):
+ """ Represents a REJ DAIDE request.
+ Syntax:
+ REJ (SVE ('gamename'))
+ """
+ __slots__ = ['response_bytes']
+ params = {
+ strings.RESPONSE_BYTES: bytes
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.response_bytes = b''
+ super(RejectRequest, self).__init__(response_bytes=b'', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(RejectRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ response_bytes, daide_bytes = break_next_group(daide_bytes)
+ response_bytes = strip_parentheses(response_bytes)
+ assert str(lead_token) == 'REJ', 'Expected REJ request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.response_bytes = response_bytes
+
+# ====================
+# Errors
+# ====================
+
+class ParenthesisErrorRequest(DaideRequest):
+ """ Represents a PRN DAIDE request. Sent by the client to specify an error in the set of parenthesis.
+ Syntax:
+ PRN (message)
+ """
+ __slots__ = ['message_bytes']
+ params = {
+ strings.MESSAGE_BYTES: bytes
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.message_bytes = b''
+ super(ParenthesisErrorRequest, self).__init__(message_bytes=b'', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(ParenthesisErrorRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ message_bytes, daide_bytes = break_next_group(daide_bytes)
+ if message_bytes:
+ message_bytes = strip_parentheses(message_bytes)
+ else:
+ message_bytes = strip_parentheses(daide_bytes)
+ daide_bytes = b''
+ assert str(lead_token) == 'PRN', 'Expected PRN request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.message_bytes = message_bytes
+
+class SyntaxErrorRequest(DaideRequest):
+ """ Represents a HUH DAIDE request. Sent by the client to specify an error in a message.
+ Syntax:
+ HUH (message)
+ """
+ __slots__ = ['message_bytes']
+ params = {
+ strings.MESSAGE_BYTES: bytes
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.message_bytes = b''
+ super(SyntaxErrorRequest, self).__init__(message_bytes=b'', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(SyntaxErrorRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ message_bytes, daide_bytes = break_next_group(daide_bytes)
+ message_bytes = strip_parentheses(message_bytes)
+ assert str(lead_token) == 'HUH', 'Expected HUH request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.message_bytes = message_bytes
+
+
+# ====================
+# Admin Messages
+# ====================
+
+class AdminMessageRequest(DaideRequest):
+ """ Represents a ADM DAIDE request. Can be sent by the client to send a message to all clients.
+ Should not be used for negotiation.
+
+ Syntax:
+ ADM ('message')
+ """
+ __slots__ = ['adm_message']
+ params = {
+ strings.ADM_MESSAGE: str
+ }
+
+ def __init__(self, **kwargs):
+ """ Constructor """
+ self.adm_message = ''
+ super(AdminMessageRequest, self).__init__(adm_message='', **kwargs)
+
+ def parse_bytes(self, daide_bytes):
+ """ Builds the request from DAIDE bytes """
+ super(AdminMessageRequest, self).parse_bytes(daide_bytes)
+
+ # Parsing
+ lead_token, daide_bytes = parse_bytes(SingleToken, daide_bytes)
+ adm_message, daide_bytes = parse_bytes(String, daide_bytes)
+ assert str(lead_token) == 'ADM', 'Expected ADM request'
+ assert not daide_bytes, '%s bytes remaining. Request is malformed' % len(daide_bytes)
+
+ # Setting properties
+ self.adm_message = str(adm_message)
+
+# =====================
+# Constants and aliases
+# =====================
+NME = NameRequest
+OBS = ObserverRequest
+IAM = IAmRequest
+HLO = HelloRequest
+MAP = MapRequest
+MDF = MapDefinitionRequest
+SCO = SupplyCentreOwnershipRequest
+NOW = CurrentPositionRequest
+HST = HistoryRequest
+SUB = SubmitOrdersRequest
+MIS = MissingOrdersRequest
+GOF = GoFlagRequest
+TME = TimeToDeadlineRequest
+DRW = DrawRequest
+SND = SendMessageRequest
+NOT = NotRequest
+YES = AcceptRequest
+REJ = RejectRequest
+PRN = ParenthesisErrorRequest
+HUH = SyntaxErrorRequest
+ADM = AdminMessageRequest
+
+# Constants
+__REQUEST_CONSTRUCTORS__ = {bytes(tokens.NME): NME,
+ bytes(tokens.OBS): OBS,
+ bytes(tokens.IAM): IAM,
+ bytes(tokens.HLO): HLO,
+ bytes(tokens.MAP): MAP,
+ bytes(tokens.MDF): MDF,
+ bytes(tokens.SCO): SCO,
+ bytes(tokens.NOW): NOW,
+ bytes(tokens.HST): HST,
+ bytes(tokens.SUB): SUB,
+ bytes(tokens.MIS): MIS,
+ bytes(tokens.GOF): GOF,
+ bytes(tokens.TME): TME,
+ bytes(tokens.DRW): DRW,
+ bytes(tokens.SND): SND,
+ bytes(tokens.NOT): NOT,
+ bytes(tokens.YES): YES,
+ bytes(tokens.REJ): REJ,
+ bytes(tokens.PRN): PRN,
+ bytes(tokens.HUH): HUH,
+ bytes(tokens.ADM): ADM}
diff --git a/diplomacy/daide/tests/test_requests.py b/diplomacy/daide/tests/test_requests.py
new file mode 100644
index 0000000..96e50e6
--- /dev/null
+++ b/diplomacy/daide/tests/test_requests.py
@@ -0,0 +1,886 @@
+# ==============================================================================
+# Copyright (C) 2019 - Philip Paquette
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <https://www.gnu.org/licenses/>.
+# ==============================================================================
+""" Tests for request objects """
+from diplomacy.daide import requests, tokens
+from diplomacy.daide.requests import RequestBuilder
+from diplomacy.daide.utils import str_to_bytes
+
+def test_nme_001():
+ """ Tests the NME request """
+ daide_str = 'NME ( A l b e r t ) ( v 6 . 0 . 1 )'
+ expected_str = 'NME (Albert) (v6.0.1)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NME), 'Expected a NME request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.client_name == 'Albert'
+ assert request.client_version == 'v6.0.1'
+
+def test_nme_002():
+ """ Tests the NME request """
+ daide_str = 'NME ( J o h n D o e ) ( v 1 . 2 )'
+ expected_str = 'NME (JohnDoe) (v1.2)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NME), 'Expected a NME request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.client_name == 'JohnDoe'
+ assert request.client_version == 'v1.2'
+
+def test_obs():
+ """ Test the OBS request """
+ daide_str = 'OBS'
+ expected_str = 'OBS'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.OBS), 'Expected a OBS request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_iam():
+ """ Test the IAM request """
+ daide_str = 'IAM ( FRA ) ( #1234 )'
+ expected_str = 'IAM (FRA) (1234)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.IAM), 'Expected a IAM request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.power_name == 'FRANCE'
+ assert request.passcode == '1234'
+
+def test_hlo():
+ """ Test the HLO request """
+ daide_str = 'HLO'
+ expected_str = 'HLO'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.HLO), 'Expected a HLO request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_map():
+ """ Test the MAP request """
+ daide_str = 'MAP'
+ expected_str = 'MAP'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.MAP), 'Expected a MAP request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_mdf():
+ """ Test the MDF request """
+ daide_str = 'MDF'
+ expected_str = 'MDF'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.MDF), 'Expected a MDF request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_sco():
+ """ Test the SCO request """
+ daide_str = 'SCO'
+ expected_str = 'SCO'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SCO), 'Expected a SCO request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_now():
+ """ Test the NOW request """
+ daide_str = 'NOW'
+ expected_str = 'NOW'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOW), 'Expected a NOW request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_hst_spr():
+ """ Tests the HST request """
+ daide_str = 'HST ( SPR #1901 )'
+ expected_str = 'HST (SPR 1901)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.HST), 'Expected a HST request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'S1901M'
+
+def test_sub_spr_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( SPR #1901 ) ( ( ENG AMY LVP ) HLD )'
+ expected_str = 'SUB (SPR 1901) ((ENG AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'S1901M'
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H']
+
+def test_sub_sum_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( SUM #1902 ) ( ( ENG AMY LVP ) HLD )'
+ expected_str = 'SUB (SUM 1902) ((ENG AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'S1902R'
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H']
+
+def test_sub_fal_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( FAL #1903 ) ( ( ENG AMY LVP ) HLD )'
+ expected_str = 'SUB (FAL 1903) ((ENG AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'F1903M'
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H']
+
+def test_sub_aut_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( AUT #1904 ) ( ( ENG AMY LVP ) HLD )'
+ expected_str = 'SUB (AUT 1904) ((ENG AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'F1904R'
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H']
+
+def test_sub_win_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( WIN #1905 ) ( ( ENG AMY LVP ) HLD )'
+ expected_str = 'SUB (WIN 1905) ((ENG AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'W1905A'
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H']
+
+def test_sub_austria_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( AUS AMY LVP ) HLD )'
+ expected_str = 'SUB ((AUS AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'AUSTRIA'
+ assert request.orders == ['A LVP H']
+
+def test_sub_english_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG AMY LVP ) HLD )'
+ expected_str = 'SUB ((ENG AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H']
+
+def test_sub_france_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( FRA AMY LVP ) HLD )'
+ expected_str = 'SUB ((FRA AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'FRANCE'
+ assert request.orders == ['A LVP H']
+
+def test_sub_germany_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( GER AMY LVP ) HLD )'
+ expected_str = 'SUB ((GER AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'GERMANY'
+ assert request.orders == ['A LVP H']
+
+def test_sub_italy_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ITA AMY LVP ) HLD )'
+ expected_str = 'SUB ((ITA AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ITALY'
+ assert request.orders == ['A LVP H']
+
+def test_sub_russia_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( RUS AMY LVP ) HLD )'
+ expected_str = 'SUB ((RUS AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'RUSSIA'
+ assert request.orders == ['A LVP H']
+
+def test_sub_turkey_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( TUR AMY LVP ) HLD )'
+ expected_str = 'SUB ((TUR AMY LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'TURKEY'
+ assert request.orders == ['A LVP H']
+
+def test_sub_fleet_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT LVP ) HLD )'
+ expected_str = 'SUB ((ENG FLT LVP) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F LVP H']
+
+def test_sub_eng_ech_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( FRA FLT ECH ) HLD )'
+ expected_str = 'SUB ((FRA FLT ECH) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'FRANCE'
+ assert request.orders == ['F ENG H']
+
+def test_sub_gob_bot_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( FRA FLT GOB ) HLD )'
+ expected_str = 'SUB ((FRA FLT GOB) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'FRANCE'
+ assert request.orders == ['F BOT H']
+
+def test_sub_gol_lyo_hold():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( FRA FLT GOL ) HLD )'
+ expected_str = 'SUB ((FRA FLT GOL) HLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'FRANCE'
+ assert request.orders == ['F LYO H']
+
+def test_sub_move():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT LON ) MTO NTH )'
+ expected_str = 'SUB ((ENG FLT LON) MTO NTH)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F LON - NTH']
+
+def test_sub_move_coast():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT BAR ) MTO ( STP NCS ) )'
+ expected_str = 'SUB ((ENG FLT BAR) MTO (STP NCS))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F BAR - STP/NC']
+
+def test_sub_support_hold_001():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT EDI ) SUP ( ENG FLT LON ) )'
+ expected_str = 'SUB ((ENG FLT EDI) SUP (ENG FLT LON))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F EDI S F LON']
+
+def test_sub_support_hold_002():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT NWY ) SUP ( ENG FLT BAR ) )'
+ expected_str = 'SUB ((ENG FLT NWY) SUP (ENG FLT BAR))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F NWY S F BAR']
+
+def test_sub_support_hold_003():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) )'
+ expected_str = 'SUB ((ENG FLT NWG) SUP (ENG AMY YOR))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F NWG S A YOR']
+
+def test_sub_support_move_001():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH )'
+ expected_str = 'SUB ((ENG FLT EDI) SUP (ENG FLT LON) MTO NTH)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F EDI S F LON - NTH']
+
+def test_sub_support_move_002():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT NWY ) SUP ( ENG FLT BAR ) MTO STP )'
+ expected_str = 'SUB ((ENG FLT NWY) SUP (ENG FLT BAR) MTO STP)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F NWY S F BAR - STP']
+
+def test_sub_support_move_003():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) MTO NWY )'
+ expected_str = 'SUB ((ENG FLT NWG) SUP (ENG AMY YOR) MTO NWY)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F NWG S A YOR - NWY']
+
+def test_sub_move_via_001():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ITA AMY TUN ) CTO SYR VIA ( ION EAS ) )'
+ expected_str = 'SUB ((ITA AMY TUN) CTO SYR VIA (ION EAS))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ITALY'
+ assert request.orders == ['A TUN - SYR VIA']
+
+def test_sub_move_via_002():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG AMY YOR ) CTO NWY VIA ( NTH ) )'
+ expected_str = 'SUB ((ENG AMY YOR) CTO NWY VIA (NTH))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A YOR - NWY VIA']
+
+def test_sub_convoy_001():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ITA FLT ION ) CVY ( ITA AMY TUN ) CTO SYR )'
+ expected_str = 'SUB ((ITA FLT ION) CVY (ITA AMY TUN) CTO SYR)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ITALY'
+ assert request.orders == ['F ION C A TUN - SYR']
+
+def test_sub_convoy_002():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ITA FLT EAS ) CVY ( ITA AMY TUN ) CTO SYR )'
+ expected_str = 'SUB ((ITA FLT EAS) CVY (ITA AMY TUN) CTO SYR)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ITALY'
+ assert request.orders == ['F EAS C A TUN - SYR']
+
+def test_sub_convoy_003():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT NTH ) CVY ( ENG AMY YOR ) CTO STP )'
+ expected_str = 'SUB ((ENG FLT NTH) CVY (ENG AMY YOR) CTO STP)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F NTH C A YOR - STP']
+
+def test_sub_retreat():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT LON ) RTO NTH )'
+ expected_str = 'SUB ((ENG FLT LON) RTO NTH)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F LON R NTH']
+
+def test_sub_retreat_coast():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT LON ) RTO ( STP NCS ) )'
+ expected_str = 'SUB ((ENG FLT LON) RTO (STP NCS))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F LON R STP/NC']
+
+def test_sub_disband():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( RUS FLT GOB ) DSB )'
+ expected_str = 'SUB ((RUS FLT GOB) DSB)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'RUSSIA'
+ assert request.orders == ['F BOT D']
+
+def test_sub_build():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ITA FLT NAP ) BLD )'
+ expected_str = 'SUB ((ITA FLT NAP) BLD)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ITALY'
+ assert request.orders == ['F NAP B']
+
+def test_sub_remove():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( RUS FLT GOB ) REM )'
+ expected_str = 'SUB ((RUS FLT GOB) REM)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'RUSSIA'
+ assert request.orders == ['F BOT D']
+
+def test_sub_waive():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ENG WVE )'
+ expected_str = 'SUB (ENG WVE)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['WAIVE']
+
+def test_sub_multi_001():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG AMY LVP ) HLD ) ' \
+ '( ( ENG FLT LON ) MTO NTH ) ' \
+ '( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH )'
+ expected_str = 'SUB ((ENG AMY LVP) HLD) ' \
+ '((ENG FLT LON) MTO NTH) ' \
+ '((ENG FLT EDI) SUP (ENG FLT LON) MTO NTH)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A LVP H', 'F LON - NTH', 'F EDI S F LON - NTH']
+
+def test_sub_multi_002():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG FLT BAR ) MTO ( STP NCS ) ) ' \
+ '( ( ITA FLT NWY ) SUP ( ENG FLT BAR ) MTO STP )'
+ expected_str = 'SUB ((ENG FLT BAR) MTO (STP NCS)) ' \
+ '((ITA FLT NWY) SUP (ENG FLT BAR) MTO STP)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['F BAR - STP/NC', 'F NWY S F BAR - STP']
+
+def test_sub_multi_003():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ITA AMY TUN ) CTO SYR VIA ( ION EAS ) ) ' \
+ '( ( ITA FLT ION ) CVY ( ITA AMY TUN ) CTO SYR ) ' \
+ '( ( ITA FLT EAS ) CVY ( ITA AMY TUN ) CTO SYR )'
+ expected_str = 'SUB ((ITA AMY TUN) CTO SYR VIA (ION EAS)) ' \
+ '((ITA FLT ION) CVY (ITA AMY TUN) CTO SYR) ' \
+ '((ITA FLT EAS) CVY (ITA AMY TUN) CTO SYR)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ITALY'
+ assert request.orders == ['A TUN - SYR VIA', 'F ION C A TUN - SYR', 'F EAS C A TUN - SYR']
+
+def test_sub_multi_004():
+ """ Tests the SUB request """
+ daide_str = 'SUB ( ( ENG AMY YOR ) CTO NWY VIA ( NTH ) ) ' \
+ '( ( ENG FLT NTH ) CVY ( ENG AMY YOR ) CTO NWY ) ' \
+ '( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) MTO NWY )'
+ expected_str = 'SUB ((ENG AMY YOR) CTO NWY VIA (NTH)) ' \
+ '((ENG FLT NTH) CVY (ENG AMY YOR) CTO NWY) ' \
+ '((ENG FLT NWG) SUP (ENG AMY YOR) MTO NWY)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SUB), 'Expected a SUB request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.power_name == 'ENGLAND'
+ assert request.orders == ['A YOR - NWY VIA', 'F NTH C A YOR - NWY', 'F NWG S A YOR - NWY']
+
+def test_mis():
+ """ Test the MIS request """
+ daide_str = 'MIS'
+ expected_str = 'MIS'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.MIS), 'Expected a MIS request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_gof():
+ """ Test the GOF request """
+ daide_str = 'GOF'
+ expected_str = 'GOF'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.GOF), 'Expected a GOF request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+
+def test_tme():
+ """ Tests the TME request """
+ daide_str = 'TME'
+ expected_str = 'TME'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.TME), 'Expected a TME request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.seconds is None
+
+def test_tme_sec():
+ """ Tests the TME request """
+ daide_str = 'TME ( #60 )'
+ expected_str = 'TME (60)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.TME), 'Expected a TME request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.seconds == 60
+
+def test_drw_001():
+ """ Test the DRW request """
+ daide_str = 'DRW'
+ expected_str = 'DRW'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.DRW), 'Expected a DRW request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.powers == []
+
+def test_drw_002():
+ """ Test the DRW request """
+ daide_str = 'DRW ( FRA ENG ITA )'
+ expected_str = 'DRW (FRA ENG ITA)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.DRW), 'Expected a DRW request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.powers == ['FRANCE', 'ENGLAND', 'ITALY']
+
+def test_snd_001():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA ENG ) ( PRP ( PCE ( FRA ENG GER ) ) )'
+ expected_str = 'SND (FRA ENG) (PRP (PCE (FRA ENG GER)))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'ENGLAND']
+ assert request.message_bytes == str_to_bytes('PRP ( PCE ( FRA ENG GER ) )')
+
+def test_snd_002():
+ """ Tests the SND request """
+ daide_str = 'SND ( SPR #1901 ) ( FRA ENG ) ( PRP ( PCE ( FRA ENG GER ) ) )'
+ expected_str = 'SND (SPR 1901) (FRA ENG) (PRP (PCE (FRA ENG GER)))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == 'S1901M'
+ assert request.powers == ['FRANCE', 'ENGLAND']
+ assert request.message_bytes == str_to_bytes('PRP ( PCE ( FRA ENG GER ) )')
+
+def test_snd_003():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA ENG ) ( CCL ( PRP ( PCE ( FRA ENG GER ) ) ) )'
+ expected_str = 'SND (FRA ENG) (CCL (PRP (PCE (FRA ENG GER))))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'ENGLAND']
+ assert request.message_bytes == str_to_bytes('CCL ( PRP ( PCE ( FRA ENG GER ) ) )')
+
+def test_snd_004():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA ENG ) ( FCT ( PCE ( FRA ENG GER ) ) )'
+ expected_str = 'SND (FRA ENG) (FCT (PCE (FRA ENG GER)))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'ENGLAND']
+ assert request.message_bytes == str_to_bytes('FCT ( PCE ( FRA ENG GER ) )')
+
+def test_snd_005():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA ENG ) ( TRY ( PRP PCE ALY VSS DRW SLO NOT YES REJ BWX ) )'
+ expected_str = 'SND (FRA ENG) (TRY (PRP PCE ALY VSS DRW SLO NOT YES REJ BWX))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'ENGLAND']
+ assert request.message_bytes == str_to_bytes('TRY ( PRP PCE ALY VSS DRW SLO NOT YES REJ BWX )')
+
+def test_snd_006():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA GER ) ( YES ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )'
+ expected_str = 'SND (FRA GER) (YES (PRP (ALY (FRA ENG GER) VSS (ITA))))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'GERMANY']
+ assert request.message_bytes == str_to_bytes('YES ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )')
+
+def test_snd_007():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA GER ) ( REJ ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )'
+ expected_str = 'SND (FRA GER) (REJ (PRP (ALY (FRA ENG GER) VSS (ITA))))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'GERMANY']
+ assert request.message_bytes == str_to_bytes('REJ ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )')
+
+def test_snd_008():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA GER ) ( BWX ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )'
+ expected_str = 'SND (FRA GER) (BWX (PRP (ALY (FRA ENG GER) VSS (ITA))))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'GERMANY']
+ assert request.message_bytes == str_to_bytes('BWX ( PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )')
+
+def test_snd_009():
+ """ Tests the SND request """
+ daide_str = 'SND ( FRA GER ) ( HUH ( ERR PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) ) )'
+ expected_str = 'SND (FRA GER) (HUH (ERR PRP (ALY (FRA ENG GER) VSS (ITA))))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.SND), 'Expected a SND request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.phase == ''
+ assert request.powers == ['FRANCE', 'GERMANY']
+ assert request.message_bytes == str_to_bytes('HUH ( ERR PRP ( ALY ( FRA ENG GER ) VSS ( ITA ) ) )')
+
+def test_not_sub():
+ """ Tests the NOT request """
+ daide_str = 'NOT ( SUB )'
+ expected_str = 'NOT (SUB)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOT), 'Expected a NOT request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert isinstance(request.request, requests.SUB), 'Expected a SUB not request'
+
+def test_not_sub_orders():
+ """ Tests the NOT request """
+ daide_str = 'NOT ( SUB ( ( ENG AMY YOR ) CTO NWY VIA ( NTH ) ) ' \
+ '( ( ENG FLT NTH ) CVY ( ENG AMY YOR ) CTO NWY ) ' \
+ '( ( ENG FLT NWG ) SUP ( ENG AMY YOR ) MTO NWY ) )'
+ expected_str = 'NOT (SUB ((ENG AMY YOR) CTO NWY VIA (NTH)) ' \
+ '((ENG FLT NTH) CVY (ENG AMY YOR) CTO NWY) ' \
+ '((ENG FLT NWG) SUP (ENG AMY YOR) MTO NWY))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOT), 'Expected a NOT request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert isinstance(request.request, requests.SUB), 'Expected a SUB not request'
+
+def test_not_gof():
+ """ Tests the NOT request """
+ daide_str = 'NOT ( GOF )'
+ expected_str = 'NOT (GOF)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOT), 'Expected a NOT request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert isinstance(request.request, requests.GOF), 'Expected a GOF not request'
+
+def test_not_tme():
+ """ Tests the NOT request """
+ daide_str = 'NOT ( TME )'
+ expected_str = 'NOT (TME)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOT), 'Expected a NOT request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert isinstance(request.request, requests.TME), 'Expected a TME not request'
+
+def test_not_tme_sec():
+ """ Tests the NOT request """
+ daide_str = 'NOT ( TME ( #60 ) )'
+ expected_str = 'NOT (TME (60))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOT), 'Expected a NOT request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert isinstance(request.request, requests.TME), 'Expected a TME not request'
+
+def test_not_drw():
+ """ Tests the NOT request """
+ daide_str = 'NOT ( DRW )'
+ expected_str = 'NOT (DRW)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.NOT), 'Expected a NOT request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert isinstance(request.request, requests.DRW), 'Expected a DRW not request'
+
+def test_yes():
+ """ Tests the YES request """
+ daide_str = 'YES ( MAP ( s t a n d a r d ) )'
+ expected_str = 'YES (MAP (standard))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.YES), 'Expected a YES request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert tokens.Token(from_bytes=request.response_bytes[:2]) == tokens.MAP
+
+def test_rej():
+ """ Tests the REJ request """
+ daide_str = 'REJ ( SVE ( g a m e n a m e ) )'
+ expected_str = 'REJ (SVE (gamename))'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.REJ), 'Expected a REJ request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert tokens.Token(from_bytes=request.response_bytes[:2]) == tokens.SVE
+
+def test_prn_sub():
+ """ Tests the PRN request """
+ daide_str = 'PRN ( SUB ( ( ENG AMY LVP ) HLD ) ' \
+ '( ( ENG FLT LON ) MTO NTH ) ' \
+ '( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH )'
+ request_message_daide_str = 'SUB ( ( ENG AMY LVP ) HLD ) ' \
+ '( ( ENG FLT LON ) MTO NTH ) ' \
+ '( ( ENG FLT EDI ) SUP ( ENG FLT LON ) MTO NTH'
+ expected_str = 'PRN (SUB ((ENG AMY LVP) HLD) ' \
+ '((ENG FLT LON) MTO NTH) ' \
+ '((ENG FLT EDI) SUP (ENG FLT LON) MTO NTH)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.PRN), 'Expected a PRN request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.message_bytes == str_to_bytes(request_message_daide_str)
+
+def test_huh_sub():
+ """ Tests the HUH request """
+ daide_str = 'HUH ( )'
+ expected_str = 'HUH ()'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.HUH), 'Expected a HUH request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.message_bytes == b''
+
+def test_adm():
+ """ Tests the ADM request """
+ daide_str = 'ADM ( I \' m h a v i n g c o n n e c t i o n p r o b l e m s )'
+ expected_str = 'ADM (I\'m having connection problems)'
+ request = RequestBuilder.from_bytes(str_to_bytes(daide_str))
+ assert isinstance(request, requests.ADM), 'Expected a ADM request'
+ assert bytes(request) == str_to_bytes(daide_str)
+ assert str(request) == expected_str
+ assert request.adm_message == 'I\'m having connection problems'
diff --git a/diplomacy/utils/strings.py b/diplomacy/utils/strings.py
index 2a74a03..19823a8 100644
--- a/diplomacy/utils/strings.py
+++ b/diplomacy/utils/strings.py
@@ -19,6 +19,7 @@
ABBREV = 'abbrev'
ACTIVE = 'active'
ADJUST = 'adjust'
+ADM_MESSAGE = 'adm_message'
ADMIN = 'admin'
ADMINISTRATORS = 'administrators'
ALL_POSSIBLE_ORDERS = 'all_possible_orders'
@@ -39,6 +40,8 @@ CENTERS = 'centers'
CHANNEL = 'channel'
CIVIL_DISORDER = 'civil_disorder'
CLEAR_INVALID_STATE_HISTORY = 'clear_invalid_state_history'
+CLIENT_NAME = 'client_name'
+CLIENT_VERSION = 'client_version'
COMPLETED = 'completed'
CONTENT = 'content'
CONTROLLED_POWERS = 'controlled_powers'
@@ -90,6 +93,7 @@ MAPS_MTIME = 'maps_mtime'
MASTER_TYPE = 'master_type'
MAX_GAMES = 'max_games'
MESSAGE = 'message'
+MESSAGE_BYTES = 'message_bytes'
MESSAGE_HISTORY = 'message_history'
MESSAGES = 'messages'
META_RULES = 'meta_rules'
@@ -125,6 +129,7 @@ ORDERS_STATUSES = 'orders_statuses'
OTHER_PLAYERS = 'other_players'
OUTCOME = 'outcome'
PARAMETERS = 'parameters'
+PASSCODE = 'passcode'
PASSWORD = 'password'
PASSWORD_HASH = 'password_hash'
PAUSED = 'paused'
@@ -160,13 +165,16 @@ REGISTER = 'register'
REGISTRATION_PASSWORD = 'registration_password'
REMOVE_CANCELED_GAMES = 'remove_canceled_games'
REMOVE_ENDED_GAMES = 'remove_ended_games'
+REQUEST = 'request'
REQUEST_ID = 'request_id'
+RESPONSE_BYTES = 'response_bytes'
RESULT = 'result'
RESULT_HISTORY = 'result_history'
RESULTS = 'results'
RETREATS = 'retreats'
ROLE = 'role'
RULES = 'rules'
+SECONDS = 'seconds'
SENDER = 'sender'
SERVER_TYPE = 'server_type'
SET_ORDER = 'set_order'