aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--pyenet/enet.pyx620
-rw-r--r--pyenet/setup.py50
3 files changed, 0 insertions, 672 deletions
diff --git a/README b/README
index 58fa33f..f56cfde 100644
--- a/README
+++ b/README
@@ -12,5 +12,3 @@ aclocal && automake -a -c --foreign && autoconf
./configure && make && make install
-See pyenet/readme.txt for further information on Ling Lo's Python wrapper for
-ENet.
diff --git a/pyenet/enet.pyx b/pyenet/enet.pyx
deleted file mode 100644
index cb61258..0000000
--- a/pyenet/enet.pyx
+++ /dev/null
@@ -1,620 +0,0 @@
-# enet.pyx
-#
-# DESCRIPTION
-#
-# Python ENET Wrapper implemented in pyrexc.
-#
-# RATIONALE
-#
-# Ling Lo's pyenet.c module had a problem with dropping a connection after
-# a short amount of time. Having seen other Python <-> C interfaces
-# defined in pyrexc, I decided it probably has a much better time of
-# surviving time.
-#
-# Hopefully no one will be too mad with the option of choice?
-#
-# LICENSE
-#
-# Copyright (C) 2003, Scott Robinson ([email protected])
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# The names of its contributors may not be used to endorse or promote
-# products derived from this software without specific prior written
-# permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
-# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
-# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# CHANGELOG
-#
-# Sat Nov 1 00:36:02 PST 2003 Scott Robinson <[email protected]>
-# Began developing test interface after a day of coding...
-#
-# Mon Nov 3 08:46:33 PST 2003 Scott Robinson <[email protected]>
-# Added documentation to all classes, functions, and attributes.
-# While adding documentation, added accessors to a few more attributes.
-# Cleaned up a few methods to match proper pyrex behavior.
-# Removed a few, and added a couple of obvious todos for the future.
-# Fixed Address.__getattr__ extra \0s in the case .host.
-#
-# Fri Feb 13 18:18:04 PST 2004 Scott Robinson <[email protected]>
-# Added Socket class for use with select and poll.
-#
-
-import atexit
-
-# SECTION
-# C declarations and definitions for the interface.
-
-cdef extern from "Python.h" :
- object PyBuffer_FromMemory (void *ptr, int size)
- object PyString_FromString (char *v)
- object PyString_FromStringAndSize (char *v, int len)
-
-cdef extern from "enet/types.h" :
- ctypedef unsigned char enet_uint8
- ctypedef unsigned short enet_uint16
- ctypedef unsigned int enet_uint32
- ctypedef unsigned int size_t
-
-cdef extern from "enet/enet.h" :
- cdef enum :
- ENET_HOST_ANY = 0
-
- # TODO: Handle Windows situation.
- ctypedef int ENetSocket
-
- ctypedef struct ENetAddress :
- enet_uint32 host
- enet_uint16 port
-
- ctypedef enum ENetPacketFlag :
- ENET_PACKET_FLAG_RELIABLE = (1 << 0)
-
- ctypedef struct ENetPacket :
- size_t referenceCount
- enet_uint32 flags
- enet_uint8 *data
- size_t dataLength
-
- ctypedef enum ENetPeerState :
- ENET_PEER_STATE_DISCONNECTED = 0
- ENET_PEER_STATE_CONNECTING = 1
- ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2
- ENET_PEER_STATE_CONNECTED = 3
- ENET_PEER_STATE_DISCONNECTING = 4
- ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 5
- ENET_PEER_STATE_ZOMBIE = 6
-
- cdef enum :
- ENET_PEER_PACKET_LOSS_SCALE = (1 << 16)
-
- ctypedef struct ENetPeer :
- ENetAddress address
- ENetPeerState state
- enet_uint32 packetLoss
- enet_uint32 packetThrottleAcceleration
- enet_uint32 packetThrottleDeceleration
- enet_uint32 packetThrottleInterval
- enet_uint32 roundTripTime
-
- ctypedef struct ENetHost :
- ENetSocket socket
- ENetAddress address
-
- ctypedef enum ENetEventType :
- ENET_EVENT_TYPE_NONE = 0
- ENET_EVENT_TYPE_CONNECT = 1
- ENET_EVENT_TYPE_DISCONNECT = 2
- ENET_EVENT_TYPE_RECEIVE = 3
-
- ctypedef struct ENetEvent :
- ENetEventType type
- ENetPeer *peer
- enet_uint8 channelID
- ENetPacket *packet
-
- int enet_initialize ()
- void enet_deinitialize ()
-
- int enet_address_set_host (ENetAddress *address, char *hostName)
- int enet_address_get_host (ENetAddress *address, char *hostName, size_t nameLength)
-
- ENetPacket * enet_packet_create (void *dataContents, size_t dataLength, enet_uint32 flags)
- void enet_packet_destroy (ENetPacket *packet)
- int enet_packet_resize (ENetPacket *packet, size_t dataLength)
-
- ENetHost * enet_host_create (ENetAddress *address, size_t peerCount, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
- void enet_host_destroy (ENetHost *host)
- ENetPeer * enet_host_connect (ENetHost *host, ENetAddress *address, size_t channelCount)
- int enet_host_service (ENetHost *host, ENetEvent *event, enet_uint32 timeout)
- void enet_host_flush (ENetHost *host)
- void enet_host_broadcast (ENetHost *host, enet_uint8 channelID, ENetPacket *packet)
- void enet_host_bandwidth_limit (ENetHost *host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
-
- int enet_peer_send (ENetPeer *peer, enet_uint8 channelID, ENetPacket *packet)
- ENetPacket * enet_peer_receive (ENetPeer *peer, enet_uint8 channelID)
- void enet_peer_ping (ENetPeer *peer)
- void enet_peer_reset (ENetPeer *peer)
- void enet_peer_disconnect (ENetPeer *peer)
- void enet_peer_disconnect_now (ENetPeer *peer)
- void enet_peer_throttle_configure (ENetPeer *peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deacceleration)
-
-# SECTION
-# Enumerations and constants.
-
-HOST_ANY = ENET_HOST_ANY
-
-PACKET_FLAG_RELIABLE = ENET_PACKET_FLAG_RELIABLE
-
-PEER_STATE_DISCONNECT = ENET_PEER_STATE_DISCONNECTED
-PEER_STATE_CONNECTING = ENET_PEER_STATE_CONNECTING
-PEER_STATE_ACKNOWLEDGING_CONNECT = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT
-PEER_STATE_CONNECTED = ENET_PEER_STATE_CONNECTED
-PEER_STATE_DISCONNECTING = ENET_PEER_STATE_DISCONNECTING
-PEER_STATE_ACKNOWLEDGING_DISCONNECT = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT
-PEER_STATE_ZOMBIE = ENET_PEER_STATE_ZOMBIE
-
-PEER_PACKET_LOSS_SCALE = ENET_PEER_PACKET_LOSS_SCALE
-
-EVENT_TYPE_NONE = ENET_EVENT_TYPE_NONE
-EVENT_TYPE_CONNECT = ENET_EVENT_TYPE_CONNECT
-EVENT_TYPE_DISCONNECT = ENET_EVENT_TYPE_DISCONNECT
-EVENT_TYPE_RECEIVE = ENET_EVENT_TYPE_RECEIVE
-
-# SECTION
-# Python exposed class definitions.
-
-cdef class Socket :
- """Socket (int socket)
-
- DESCRIPTION
-
- An ENet socket.
-
- Can be used with select and poll."""
-
- cdef ENetSocket _enet_socket
-
- def fileno (self) :
- return self._enet_socket
-
-cdef class Address :
- """Address (str address, int port)
-
- ATTRIBUTES
-
- str host Hostname referred to by the Address.
- int port Port referred to by the Address.
-
- DESCRIPTION
-
- An ENet address and port pair.
-
- When instantiated, performs a resolution upon 'address'. However, if 'address' is None, enet.HOST_ANY is assumed."""
-
- cdef ENetAddress _enet_address
-
- def __init__ (self, address, port) :
- self.host = address
- self.port = port
-
- def __getattr__ (self, name) :
- if name == "host" :
- if self._enet_address.host == ENET_HOST_ANY :
- return "*"
- elif self._enet_address.host :
- maxhostname = 257 # We'll follow Solaris' standard.
- host = PyString_FromStringAndSize (NULL, maxhostname)
-
- if enet_address_get_host (&self._enet_address, host, maxhostname) :
- raise IOError ("Resolution failure!")
-
- return PyString_FromString (host)
- else :
- assert (not ENET_HOST_ANY)
- elif name == "port" :
- return self._enet_address.port
- else :
- return AttributeError ("Address object has no attribute '" + name + "'")
-
- def __setattr__ (self, name, value) :
- if name == "host" :
- if not value or value == "*":
- self._enet_address.host = ENET_HOST_ANY
- else :
- if enet_address_set_host (&self._enet_address, value) :
- raise IOError ("Resolution failure!")
- elif name == "port" :
- self._enet_address.port = value
- else :
- return AttributeError ("Address object has no attribute '" + name + "'")
-
- def __str__ (self) :
- return "%s:%u" % (self.host, self.port)
-
-cdef class Packet :
- """Packet ([dataContents, int flags])
-
- ATTRIBUTES
-
- str data Contains the data for the packet.
- int flags Flags modifying delivery of the Packet:
- enet.PACKET_FLAG_RELIABLE Packet must be received by the target peer and resend attempts should be made until the packet is delivered.
-
- DESCRIPTION
-
- An ENet data packet that may be sent to or received from a peer."""
-
- cdef ENetPacket *_enet_packet
-
- def __init__ (self, char *dataContents = "", flags = 0) :
- if dataContents or flags :
- self._enet_packet = enet_packet_create (dataContents, len (dataContents), flags)
-
- if not self._enet_packet :
- raise MemoryError ("Unable to create packet structure!")
-
- def __dealloc__ (self) :
- if self._enet_packet and not self._enet_packet.referenceCount :
- # WARNING: referenceCount is an internal structure. Is there a better way of doing this?
- enet_packet_destroy (self._enet_packet)
-
- def __getattr__ (self, name) :
- if self._enet_packet :
- if name == "flags" :
- return self._enet_packet.flags
- elif name == "data" :
- # TODO: Find out why the PyBuffer interface is cutting off data!
- #return PyBuffer_FromMemory (self._enet_packet.data, self._enet_packet.dataLength)
- return PyString_FromStringAndSize (<char *> self._enet_packet.data, self._enet_packet.dataLength)
- elif name == "dataLength" :
- return len (self.data)
- else :
- raise AttributeError ("Packet object has no attribute '" + name + "'")
- else :
- raise MemoryError ("Empty Packet object accessed!")
-
-cdef class Peer :
- """Peer ()
-
- ATTRIBUTES
-
- Address address
- int state The peer's current state.
- enet.PEER_STATE_DISCONNECT
- .PEER_STATE_CONNECTING
- .PEER_STATE_CONNECTED
- .PEER_STATE_DISCONNECTING
- .PEER_STATE_ACKNOWLEDGING_DISCONNECT
- .PEER_STATE_ZOMBIE
- int packetLoss Mean packet loss of reliable packets as a ratio with respect to the constant enet.PEER_PACKET_LOSS_SCALE.
- int packetThrottleAcceleration
- int packetThrottleDeceleration
- int packetThrottleInterval
- int roundTripTime Mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement.
-
- DESCRIPTION
-
- An ENet peer which data packets may be sent or received from.
-
- This class should never be instantiated directly, but rather via enet.Host.connect or enet.Event.Peer."""
-
- cdef ENetPeer *_enet_peer
-
- def send (self, channelID, Packet packet) :
- """send (int channelID, Packet packet)
-
- Queues a packet to be sent."""
-
- if self._enet_peer and packet._enet_packet :
- return enet_peer_send (self._enet_peer, channelID, packet._enet_packet)
-
- def receive (self, channelID) :
- """receive (int channelID)
-
- Attempts to dequeue any incoming queued packet."""
-
- if self._enet_peer :
- packet = Packet ()
- (<Packet> packet)._enet_packet = enet_peer_receive (self._enet_peer, channelID)
-
- if packet._enet_packet :
- return packet
- else :
- return None
-
- def reset (self) :
- """reset ()
-
- Forcefully disconnects a peer."""
-
- if self._enet_peer :
- enet_peer_reset (self._enet_peer)
-
- def ping (self) :
- """ping ()
-
- Sends a ping request to a peer."""
-
- if self._enet_peer :
- enet_peer_ping (self._enet_peer)
-
- def disconnect (self) :
- """disconnect ()
-
- Request a disconnection from a peer."""
-
- if self._enet_peer :
- enet_peer_disconnect (self._enet_peer)
-
- def __getattr__ (self, name) :
- if self._enet_peer :
- if name == "address" :
- address = Address (0, 0)
- (<Address> address)._enet_address = self._enet_peer.address
-
- return address
- elif name == "state" :
- return self._enet_peer.state
- elif name == "packetLoss" :
- return self._enet_peer.packetLoss
- elif name == "packetThrottleInterval" :
- return self._enet_peer.packetThrottleInterval
- elif name == "packetThrottleAcceleration" :
- return self._enet_peer.packetThrottleAcceleration
- elif name == "packetThrottleDeceleration" :
- return self._enet_peer.packetThrottleDeceleration
- elif name == "roundTripTime" :
- return self._enet_peer.roundTripTime
- else :
- raise AttributeError ("Peer object has no attribute '" + name + "'")
- else :
- raise MemoryError ("Empty Peer object accessed!")
-
- def __setattr__ (self, name, value) :
- if self._enet_peer :
- if name == "packetThrottleInterval" :
- enet_peer_throttle_configure (self._enet_peer, value, self._enet_peer.packetThrottleAcceleration, self._enet_peer.packetThrottleDeceleration)
- elif name == "packetThrottleAcceleration" :
- enet_peer_throttle_configure (self._enet_peer, self._enet_peer.packetThrottleInterval, value, self._enet_peer.packetThrottleDeceleration)
- elif name == "packetThrottleDeceleration" :
- enet_peer_throttle_configure (self._enet_peer, self._enet_peer.packetThrottleInterval, self._enet_peer.packetThrottleAcceleration, value)
- else :
- raise AttributeError ("Peer object has no attribute '" + name + "'")
- else :
- raise MemoryError ("Empty Peer object accessed!")
-
-cdef class Event :
- """Event ()
-
- ATTRIBUTES
-
- int type Type of the event.
- enet.EVENT_TYPE_NONE
- .EVENT_TYPE_CONNECT
- .EVENT_TYPE_DISCONNECT
- .EVENT_TYPE_RECEIVE
- Peer peer Peer that generated a connect, disconnect or receive event.
- int channelID
- Packet packet
-
- DESCRIPTION
-
- An ENet event as returned by enet.Host.service.
-
- This class should never be instantiated directly."""
-
- cdef ENetEvent _enet_event
-
- def __getattr__ (self, name) :
- if name == "type" :
- return self._enet_event.type
- elif name == "peer" :
- peer = Peer ()
- (<Peer> peer)._enet_peer = self._enet_event.peer
-
- return peer
- elif name == "channelID" :
- return self._enet_event.channelID
- elif name == "packet" :
- packet = Packet ()
- (<Packet> packet)._enet_packet = self._enet_event.packet
-
- return packet
- else :
- raise AttributeError ("Event object has no attribute '" + name + "'")
-
- def __setattr__ (self, name, value) :
- if name == "type" or name == "peer" or name == "channelID" or name == "packet" :
- raise AttributeError ("Attribute '" + name +"' on Event object is read-only.")
- else :
- raise AttributeError ("Event object has no attribute '" + name + "'")
-
-cdef class Host :
- """Host (Address address, int peerCount, int incomingBandwidth, int outgoingBandwidth)
-
- ATTRIBUTES
-
- Address address Internet address of the host.
- Socket socket The socket the host services.
- int incomingBandwidth Downstream bandwidth of the host.
- int outgoingBandwidth Upstream bandwidth of the host.
-
- DESCRIPTION
-
- An ENet host for communicating with peers.
-
- If 'address' is None, then the Host will be client only."""
-
- cdef ENetHost *_enet_host
- cdef enet_uint32 _enet_incomingBandwidth
- cdef enet_uint32 _enet_outgoingBandwidth
-
- def __init__ (self, Address address = None, peerCount = 0, incomingBandwidth = 0, outgoingBandwidth = 0) :
- (self._enet_incomingBandwidth, self._enet_outgoingBandwidth) = (incomingBandwidth, outgoingBandwidth)
-
- if address :
- self._enet_host = enet_host_create (&address._enet_address, peerCount, incomingBandwidth, outgoingBandwidth)
- else :
- self._enet_host = enet_host_create (NULL, peerCount, incomingBandwidth, outgoingBandwidth)
-
- if not self._enet_host :
- raise MemoryError ("Unable to create host structure!")
-
- def __dealloc__ (self) :
- if self._enet_host :
- enet_host_destroy (self._enet_host)
-
- def connect (self, Address address, channelCount) :
- """Peer connect (Address address, int channelCount)
-
- Initiates a connection to a foreign host."""
-
- if self._enet_host :
- peer = Peer ()
- (<Peer> peer)._enet_peer = enet_host_connect (self._enet_host, &address._enet_address, channelCount)
-
- if not (<Peer> peer)._enet_peer :
- raise IOError ("Connection failure!")
-
- return peer
-
- def service (self, timeout) :
- """Event service (int timeout)
-
- Waits for events on the host specified and shuttles packets between the host and its peers."""
-
- if self._enet_host :
- event = Event ()
- result = enet_host_service (self._enet_host, &(<Event> event)._enet_event, timeout)
-
- if result < 0 :
- raise IOError ("Servicing error - probably disconnected.")
- else :
- return event
-
- def flush (self) :
- """flush ()
-
- Sends any queued packets on the host specified to its designated peers."""
-
- if self._enet_host :
- enet_host_flush (self._enet_host)
-
- def broadcast (self, channelID, Packet packet) :
- """broadcast (int channelID, Packet packet)
-
- Queues a packet to be sent to all peers associated with the host."""
-
- if self._enet_host and packet._enet_packet :
- enet_host_broadcast (self._enet_host, channelID, packet._enet_packet)
-
- def __getattr__ (self, name) :
- # TODO: Add 'peers'.
- if name == "address" and self._enet_host :
- address = Address (0, 0)
- (<Address> address)._enet_address = self._enet_host.address
-
- return address
- elif name == "incomingBandwidth" :
- return self._enet_incomingBandwidth
- elif name == "outgoingBandwidth" :
- return self._enet_outgoingBandwidth
- elif name == "socket" :
- socket = Socket ()
- (<Socket> socket)._enet_socket = self._enet_host.socket
-
- return socket
- else :
- raise AttributeError ("Host object has no attribute '" + name + "'")
-
- def __setattr__ (self, name, value) :
- if name == "incomingBandwidth" :
- self._enet_incomingBandwidth = value
- enet_host_bandwidth_limit (self._enet_host, self._enet_incomingBandwidth, self._enet_outgoingBandwidth)
- elif name == "outgoingBandwidth" :
- self._enet_outgoingBandwidth = value
- enet_host_bandwidth_limit (self._enet_host, self._enet_incomingBandwidth, self._enet_outgoingBandwidth)
- else :
- raise AttributeError ("Host object has no attribute '" + name + "'")
-
-# SECTION
-# Testing
-#
-# TODO
-# Switch to using the unittest framework.
-
-class test :
- """test ()
-
- DESCRIPTION
-
- A very simple testing class that will change between releases. This is for the maintainer only."""
-
- def check (self, host) :
-
- event = host.service (0)
-
- if event.type == EVENT_TYPE_NONE :
- pass
- elif event.type == EVENT_TYPE_CONNECT :
- print "%s connected to %s via %s." % (host, event.peer.address, event.peer)
- elif event.type == EVENT_TYPE_DISCONNECT :
- print "%s disconnected from %s via %s." % (host, event.peer.address, event.peer)
- elif event.type == EVENT_TYPE_RECEIVE :
- print "%s received %s containing '%s' from %s via %s." % (host, event.packet, event.packet.data, event.peer.address, event.peer)
- else :
- print "%s received invalid event %s of type %u." % (host, event, event.type)
-
- def test (self) :
- print "Starting services..."
-
- host1 = Host (None, 1, 0, 0)
- host2 = Host (Address ("localhost", 6666), 1, 0, 0)
-
- print "Connecting %s (client) to %s (server)..." % (host1, host2)
-
- peer1 = host1.connect (Address ("localhost", 6666), 1)
-
- print "Entering service loop..."
-
- count = 0
-
- while 1 :
- self.check (host1)
- self.check (host2)
-
- count = count + 1
-
- if not (count % 10000) :
- print "Sending broadcast..."
- host1.broadcast (0, Packet ("SuperJoe"))
-
-# SECTION
-# Ensure ENET is properly initialized and de-initialized.
-
-def _enet_atexit () :
- enet_deinitialize ()
-
-enet_initialize ()
-atexit.register (_enet_atexit)
diff --git a/pyenet/setup.py b/pyenet/setup.py
deleted file mode 100644
index 1616898..0000000
--- a/pyenet/setup.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/usr/bin/env python
-
-# see http://www.python.org/doc/current/dist/setup-script.html
-# for distutil options.
-#
-# Original version by Rene Dudfield <[email protected]>
-import sys, os, os.path
-from distutils.core import setup, Extension
-
-source_dirs = ['..']
-define_macros = [('HAS_GETHOSTBYNAME_R', None),
- ('HAS_GETHOSTBYADDR_R', None),
- ('HAS_POLL', None),
- ('HAS_FCNTL', None),
- ('HAS_MSGHDR_FLAGS', None) ]
-
-libraries = []
-
-# For enet.pyx
-
-os.system("pyrexc enet.pyx")
-source_files = ['enet.c']
-
-# For pyenet
-
-#source_files = ['pyenet.c']
-
-# Build a list of all the source files
-for dir in source_dirs:
- for file in os.listdir(dir):
- if '.c' == os.path.splitext(file)[1]:
- source_files.append(dir + '/' + file)
-
-# Additional Windows dependencies
-if sys.platform == 'win32':
- define_macros.append(('WIN32', None))
- libraries.append('ws2_32')
-
-# Go force and multiply
-setup(name="enet", version="0.1",
- ext_modules=[Extension("enet",
- source_files,
- include_dirs=["../include/"],
- define_macros=define_macros,
- libraries=libraries,
- library_dirs=[]
- )
- ]
- )
-