@@ -1,72 +0,0 @@ | |||||
''' | |||||
The MIT License (MIT) | |||||
Copyright (c) 2013 Dave P. | |||||
''' | |||||
import signal | |||||
import sys | |||||
import ssl | |||||
from SimpleWebSocketServer import WebSocket, SimpleWebSocketServer, SimpleSSLWebSocketServer | |||||
from optparse import OptionParser | |||||
class SimpleEcho(WebSocket): | |||||
def handleMessage(self): | |||||
print self.data | |||||
self.sendMessage(self.data) | |||||
def handleConnected(self): | |||||
pass | |||||
def handleClose(self): | |||||
pass | |||||
clients = [] | |||||
class SimpleChat(WebSocket): | |||||
def handleMessage(self): | |||||
for client in clients: | |||||
if client != self: | |||||
client.sendMessage(self.address[0] + u' - ' + self.data) | |||||
def handleConnected(self): | |||||
print (self.address, 'connected') | |||||
for client in clients: | |||||
client.sendMessage(self.address[0] + u' - connected') | |||||
clients.append(self) | |||||
def handleClose(self): | |||||
clients.remove(self) | |||||
print (self.address, 'closed') | |||||
for client in clients: | |||||
client.sendMessage(self.address[0] + u' - disconnected') | |||||
if __name__ == "__main__": | |||||
parser = OptionParser(usage="usage: %prog [options]", version="%prog 1.0") | |||||
parser.add_option("--host", default='', type='string', action="store", dest="host", help="hostname (localhost)") | |||||
parser.add_option("--port", default=8000, type='int', action="store", dest="port", help="port (8000)") | |||||
parser.add_option("--example", default='echo', type='string', action="store", dest="example", help="echo, chat") | |||||
parser.add_option("--ssl", default=0, type='int', action="store", dest="ssl", help="ssl (1: on, 0: off (default))") | |||||
parser.add_option("--cert", default='./cert.pem', type='string', action="store", dest="cert", help="cert (./cert.pem)") | |||||
parser.add_option("--ver", default=ssl.PROTOCOL_TLSv1, type=int, action="store", dest="ver", help="ssl version") | |||||
(options, args) = parser.parse_args() | |||||
cls = SimpleEcho | |||||
if options.example == 'chat': | |||||
cls = SimpleChat | |||||
if options.ssl == 1: | |||||
server = SimpleSSLWebSocketServer(options.host, options.port, cls, options.cert, options.cert, version=options.ver) | |||||
else: | |||||
server = SimpleWebSocketServer(options.host, options.port, cls) | |||||
def close_sig_handler(signal, frame): | |||||
server.close() | |||||
sys.exit() | |||||
signal.signal(signal.SIGINT, close_sig_handler) | |||||
server.serveforever() |
@@ -1,694 +0,0 @@ | |||||
''' | |||||
The MIT License (MIT) | |||||
Copyright (c) 2013 Dave P. | |||||
''' | |||||
import sys | |||||
VER = sys.version_info[0] | |||||
if VER >= 3: | |||||
import socketserver | |||||
from http.server import BaseHTTPRequestHandler | |||||
from io import StringIO, BytesIO | |||||
else: | |||||
import SocketServer | |||||
from BaseHTTPServer import BaseHTTPRequestHandler | |||||
from StringIO import StringIO | |||||
import hashlib | |||||
import base64 | |||||
import socket | |||||
import struct | |||||
import ssl | |||||
import errno | |||||
import codecs | |||||
from collections import deque | |||||
from select import select | |||||
__all__ = ['WebSocket', | |||||
'SimpleWebSocketServer', | |||||
'SimpleSSLWebSocketServer'] | |||||
def _check_unicode(val): | |||||
if VER >= 3: | |||||
return isinstance(val, str) | |||||
else: | |||||
return isinstance(val, unicode) | |||||
class HTTPRequest(BaseHTTPRequestHandler): | |||||
def __init__(self, request_text): | |||||
if VER >= 3: | |||||
self.rfile = BytesIO(request_text) | |||||
else: | |||||
self.rfile = StringIO(request_text) | |||||
self.raw_requestline = self.rfile.readline() | |||||
self.error_code = self.error_message = None | |||||
self.parse_request() | |||||
_VALID_STATUS_CODES = [1000, 1001, 1002, 1003, 1007, 1008, | |||||
1009, 1010, 1011, 3000, 3999, 4000, 4999] | |||||
HANDSHAKE_STR = ( | |||||
"HTTP/1.1 101 Switching Protocols\r\n" | |||||
"Upgrade: WebSocket\r\n" | |||||
"Connection: Upgrade\r\n" | |||||
"Sec-WebSocket-Accept: %(acceptstr)s\r\n\r\n" | |||||
) | |||||
GUID_STR = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11' | |||||
STREAM = 0x0 | |||||
TEXT = 0x1 | |||||
BINARY = 0x2 | |||||
CLOSE = 0x8 | |||||
PING = 0x9 | |||||
PONG = 0xA | |||||
HEADERB1 = 1 | |||||
HEADERB2 = 3 | |||||
LENGTHSHORT = 4 | |||||
LENGTHLONG = 5 | |||||
MASK = 6 | |||||
PAYLOAD = 7 | |||||
MAXHEADER = 65536 | |||||
MAXPAYLOAD = 33554432 | |||||
class WebSocket(object): | |||||
def __init__(self, server, sock, address): | |||||
self.server = server | |||||
self.client = sock | |||||
self.address = address | |||||
self.handshaked = False | |||||
self.headerbuffer = bytearray() | |||||
self.headertoread = 2048 | |||||
self.fin = 0 | |||||
self.data = bytearray() | |||||
self.opcode = 0 | |||||
self.hasmask = 0 | |||||
self.maskarray = None | |||||
self.length = 0 | |||||
self.lengtharray = None | |||||
self.index = 0 | |||||
self.request = None | |||||
self.usingssl = False | |||||
self.frag_start = False | |||||
self.frag_type = BINARY | |||||
self.frag_buffer = None | |||||
self.frag_decoder = codecs.getincrementaldecoder('utf-8')(errors='strict') | |||||
self.closed = False | |||||
self.sendq = deque() | |||||
self.state = HEADERB1 | |||||
# restrict the size of header and payload for security reasons | |||||
self.maxheader = MAXHEADER | |||||
self.maxpayload = MAXPAYLOAD | |||||
def handleMessage(self): | |||||
""" | |||||
Called when websocket frame is received. | |||||
To access the frame data call self.data. | |||||
If the frame is Text then self.data is a unicode object. | |||||
If the frame is Binary then self.data is a bytearray object. | |||||
""" | |||||
pass | |||||
def handleConnected(self): | |||||
""" | |||||
Called when a websocket client connects to the server. | |||||
""" | |||||
pass | |||||
def handleClose(self): | |||||
""" | |||||
Called when a websocket server gets a Close frame from a client. | |||||
""" | |||||
pass | |||||
def _handlePacket(self): | |||||
if self.opcode == CLOSE: | |||||
pass | |||||
elif self.opcode == STREAM: | |||||
pass | |||||
elif self.opcode == TEXT: | |||||
pass | |||||
elif self.opcode == BINARY: | |||||
pass | |||||
elif self.opcode == PONG or self.opcode == PING: | |||||
if len(self.data) > 125: | |||||
raise Exception('control frame length can not be > 125') | |||||
else: | |||||
# unknown or reserved opcode so just close | |||||
raise Exception('unknown opcode') | |||||
if self.opcode == CLOSE: | |||||
status = 1000 | |||||
reason = u'' | |||||
length = len(self.data) | |||||
if length == 0: | |||||
pass | |||||
elif length >= 2: | |||||
status = struct.unpack_from('!H', self.data[:2])[0] | |||||
reason = self.data[2:] | |||||
if status not in _VALID_STATUS_CODES: | |||||
status = 1002 | |||||
if len(reason) > 0: | |||||
try: | |||||
reason = reason.decode('utf8', errors='strict') | |||||
except: | |||||
status = 1002 | |||||
else: | |||||
status = 1002 | |||||
self.close(status, reason) | |||||
return | |||||
elif self.fin == 0: | |||||
if self.opcode != STREAM: | |||||
if self.opcode == PING or self.opcode == PONG: | |||||
raise Exception('control messages can not be fragmented') | |||||
self.frag_type = self.opcode | |||||
self.frag_start = True | |||||
self.frag_decoder.reset() | |||||
if self.frag_type == TEXT: | |||||
self.frag_buffer = [] | |||||
utf_str = self.frag_decoder.decode(self.data, final = False) | |||||
if utf_str: | |||||
self.frag_buffer.append(utf_str) | |||||
else: | |||||
self.frag_buffer = bytearray() | |||||
self.frag_buffer.extend(self.data) | |||||
else: | |||||
if self.frag_start is False: | |||||
raise Exception('fragmentation protocol error') | |||||
if self.frag_type == TEXT: | |||||
utf_str = self.frag_decoder.decode(self.data, final = False) | |||||
if utf_str: | |||||
self.frag_buffer.append(utf_str) | |||||
else: | |||||
self.frag_buffer.extend(self.data) | |||||
else: | |||||
if self.opcode == STREAM: | |||||
if self.frag_start is False: | |||||
raise Exception('fragmentation protocol error') | |||||
if self.frag_type == TEXT: | |||||
utf_str = self.frag_decoder.decode(self.data, final = True) | |||||
self.frag_buffer.append(utf_str) | |||||
self.data = u''.join(self.frag_buffer) | |||||
else: | |||||
self.frag_buffer.extend(self.data) | |||||
self.data = self.frag_buffer | |||||
self.handleMessage() | |||||
self.frag_decoder.reset() | |||||
self.frag_type = BINARY | |||||
self.frag_start = False | |||||
self.frag_buffer = None | |||||
elif self.opcode == PING: | |||||
self._sendMessage(False, PONG, self.data) | |||||
elif self.opcode == PONG: | |||||
pass | |||||
else: | |||||
if self.frag_start is True: | |||||
raise Exception('fragmentation protocol error') | |||||
if self.opcode == TEXT: | |||||
try: | |||||
self.data = self.data.decode('utf8', errors='strict') | |||||
except Exception as exp: | |||||
raise Exception('invalid utf-8 payload') | |||||
self.handleMessage() | |||||
def _handleData(self): | |||||
# do the HTTP header and handshake | |||||
if self.handshaked is False: | |||||
data = self.client.recv(self.headertoread) | |||||
if not data: | |||||
raise Exception('remote socket closed') | |||||
else: | |||||
# accumulate | |||||
self.headerbuffer.extend(data) | |||||
if len(self.headerbuffer) >= self.maxheader: | |||||
raise Exception('header exceeded allowable size') | |||||
# indicates end of HTTP header | |||||
if b'\r\n\r\n' in self.headerbuffer: | |||||
self.request = HTTPRequest(self.headerbuffer) | |||||
# handshake rfc 6455 | |||||
try: | |||||
key = self.request.headers['Sec-WebSocket-Key'] | |||||
k = key.encode('ascii') + GUID_STR.encode('ascii') | |||||
k_s = base64.b64encode(hashlib.sha1(k).digest()).decode('ascii') | |||||
hStr = HANDSHAKE_STR % {'acceptstr': k_s} | |||||
self.sendq.append((BINARY, hStr.encode('ascii'))) | |||||
self.handshaked = True | |||||
self.handleConnected() | |||||
except Exception as e: | |||||
raise Exception('handshake failed: %s', str(e)) | |||||
# else do normal data | |||||
else: | |||||
data = self.client.recv(8192) | |||||
if not data: | |||||
raise Exception("remote socket closed") | |||||
if VER >= 3: | |||||
for d in data: | |||||
self._parseMessage(d) | |||||
else: | |||||
for d in data: | |||||
self._parseMessage(ord(d)) | |||||
def close(self, status = 1000, reason = u''): | |||||
""" | |||||
Send Close frame to the client. The underlying socket is only closed | |||||
when the client acknowledges the Close frame. | |||||
status is the closing identifier. | |||||
reason is the reason for the close. | |||||
""" | |||||
try: | |||||
if self.closed is False: | |||||
close_msg = bytearray() | |||||
close_msg.extend(struct.pack("!H", status)) | |||||
if _check_unicode(reason): | |||||
close_msg.extend(reason.encode('utf-8')) | |||||
else: | |||||
close_msg.extend(reason) | |||||
self._sendMessage(False, CLOSE, close_msg) | |||||
finally: | |||||
self.closed = True | |||||
def _sendBuffer(self, buff): | |||||
size = len(buff) | |||||
tosend = size | |||||
already_sent = 0 | |||||
while tosend > 0: | |||||
try: | |||||
# i should be able to send a bytearray | |||||
sent = self.client.send(buff[already_sent:]) | |||||
if sent == 0: | |||||
raise RuntimeError('socket connection broken') | |||||
already_sent += sent | |||||
tosend -= sent | |||||
except socket.error as e: | |||||
# if we have full buffers then wait for them to drain and try again | |||||
if e.errno in [errno.EAGAIN, errno.EWOULDBLOCK]: | |||||
return buff[already_sent:] | |||||
else: | |||||
raise e | |||||
return None | |||||
def sendFragmentStart(self, data): | |||||
""" | |||||
Send the start of a data fragment stream to a websocket client. | |||||
Subsequent data should be sent using sendFragment(). | |||||
A fragment stream is completed when sendFragmentEnd() is called. | |||||
If data is a unicode object then the frame is sent as Text. | |||||
If the data is a bytearray object then the frame is sent as Binary. | |||||
""" | |||||
opcode = BINARY | |||||
if _check_unicode(data): | |||||
opcode = TEXT | |||||
self._sendMessage(True, opcode, data) | |||||
def sendFragment(self, data): | |||||
""" | |||||
see sendFragmentStart() | |||||
If data is a unicode object then the frame is sent as Text. | |||||
If the data is a bytearray object then the frame is sent as Binary. | |||||
""" | |||||
self._sendMessage(True, STREAM, data) | |||||
def sendFragmentEnd(self, data): | |||||
""" | |||||
see sendFragmentEnd() | |||||
If data is a unicode object then the frame is sent as Text. | |||||
If the data is a bytearray object then the frame is sent as Binary. | |||||
""" | |||||
self._sendMessage(False, STREAM, data) | |||||
def sendMessage(self, data): | |||||
""" | |||||
Send websocket data frame to the client. | |||||
If data is a unicode object then the frame is sent as Text. | |||||
If the data is a bytearray object then the frame is sent as Binary. | |||||
""" | |||||
opcode = BINARY | |||||
if _check_unicode(data): | |||||
opcode = TEXT | |||||
self._sendMessage(False, opcode, data) | |||||
def _sendMessage(self, fin, opcode, data): | |||||
payload = bytearray() | |||||
b1 = 0 | |||||
b2 = 0 | |||||
if fin is False: | |||||
b1 |= 0x80 | |||||
b1 |= opcode | |||||
if _check_unicode(data): | |||||
data = data.encode('utf-8') | |||||
length = len(data) | |||||
payload.append(b1) | |||||
if length <= 125: | |||||
b2 |= length | |||||
payload.append(b2) | |||||
elif length >= 126 and length <= 65535: | |||||
b2 |= 126 | |||||
payload.append(b2) | |||||
payload.extend(struct.pack("!H", length)) | |||||
else: | |||||
b2 |= 127 | |||||
payload.append(b2) | |||||
payload.extend(struct.pack("!Q", length)) | |||||
if length > 0: | |||||
payload.extend(data) | |||||
self.sendq.append((opcode, payload)) | |||||
def _parseMessage(self, byte): | |||||
# read in the header | |||||
if self.state == HEADERB1: | |||||
self.fin = byte & 0x80 | |||||
self.opcode = byte & 0x0F | |||||
self.state = HEADERB2 | |||||
self.index = 0 | |||||
self.length = 0 | |||||
self.lengtharray = bytearray() | |||||
self.data = bytearray() | |||||
rsv = byte & 0x70 | |||||
if rsv != 0: | |||||
raise Exception('RSV bit must be 0') | |||||
elif self.state == HEADERB2: | |||||
mask = byte & 0x80 | |||||
length = byte & 0x7F | |||||
if self.opcode == PING and length > 125: | |||||
raise Exception('ping packet is too large') | |||||
if mask == 128: | |||||
self.hasmask = True | |||||
else: | |||||
self.hasmask = False | |||||
if length <= 125: | |||||
self.length = length | |||||
# if we have a mask we must read it | |||||
if self.hasmask is True: | |||||
self.maskarray = bytearray() | |||||
self.state = MASK | |||||
else: | |||||
# if there is no mask and no payload we are done | |||||
if self.length <= 0: | |||||
try: | |||||
self._handlePacket() | |||||
finally: | |||||
self.state = self.HEADERB1 | |||||
self.data = bytearray() | |||||
# we have no mask and some payload | |||||
else: | |||||
#self.index = 0 | |||||
self.data = bytearray() | |||||
self.state = PAYLOAD | |||||
elif length == 126: | |||||
self.lengtharray = bytearray() | |||||
self.state = LENGTHSHORT | |||||
elif length == 127: | |||||
self.lengtharray = bytearray() | |||||
self.state = LENGTHLONG | |||||
elif self.state == LENGTHSHORT: | |||||
self.lengtharray.append(byte) | |||||
if len(self.lengtharray) > 2: | |||||
raise Exception('short length exceeded allowable size') | |||||
if len(self.lengtharray) == 2: | |||||
self.length = struct.unpack_from('!H', self.lengtharray)[0] | |||||
if self.hasmask is True: | |||||
self.maskarray = bytearray() | |||||
self.state = MASK | |||||
else: | |||||
# if there is no mask and no payload we are done | |||||
if self.length <= 0: | |||||
try: | |||||
self._handlePacket() | |||||
finally: | |||||
self.state = HEADERB1 | |||||
self.data = bytearray() | |||||
# we have no mask and some payload | |||||
else: | |||||
#self.index = 0 | |||||
self.data = bytearray() | |||||
self.state = PAYLOAD | |||||
elif self.state == LENGTHLONG: | |||||
self.lengtharray.append(byte) | |||||
if len(self.lengtharray) > 8: | |||||
raise Exception('long length exceeded allowable size') | |||||
if len(self.lengtharray) == 8: | |||||
self.length = struct.unpack_from('!Q', self.lengtharray)[0] | |||||
if self.hasmask is True: | |||||
self.maskarray = bytearray() | |||||
self.state = MASK | |||||
else: | |||||
# if there is no mask and no payload we are done | |||||
if self.length <= 0: | |||||
try: | |||||
self._handlePacket() | |||||
finally: | |||||
self.state = HEADERB1 | |||||
self.data = bytearray() | |||||
# we have no mask and some payload | |||||
else: | |||||
#self.index = 0 | |||||
self.data = bytearray() | |||||
self.state = PAYLOAD | |||||
# MASK STATE | |||||
elif self.state == MASK: | |||||
self.maskarray.append(byte) | |||||
if len(self.maskarray) > 4: | |||||
raise Exception('mask exceeded allowable size') | |||||
if len(self.maskarray) == 4: | |||||
# if there is no mask and no payload we are done | |||||
if self.length <= 0: | |||||
try: | |||||
self._handlePacket() | |||||
finally: | |||||
self.state = HEADERB1 | |||||
self.data = bytearray() | |||||
# we have no mask and some payload | |||||
else: | |||||
#self.index = 0 | |||||
self.data = bytearray() | |||||
self.state = PAYLOAD | |||||
# PAYLOAD STATE | |||||
elif self.state == PAYLOAD: | |||||
if self.hasmask is True: | |||||
self.data.append( byte ^ self.maskarray[self.index % 4] ) | |||||
else: | |||||
self.data.append( byte ) | |||||
# if length exceeds allowable size then we except and remove the connection | |||||
if len(self.data) >= self.maxpayload: | |||||
raise Exception('payload exceeded allowable size') | |||||
# check if we have processed length bytes; if so we are done | |||||
if (self.index+1) == self.length: | |||||
try: | |||||
self._handlePacket() | |||||
finally: | |||||
#self.index = 0 | |||||
self.state = HEADERB1 | |||||
self.data = bytearray() | |||||
else: | |||||
self.index += 1 | |||||
class SimpleWebSocketServer(object): | |||||
def __init__(self, host, port, websocketclass, selectInterval = 0.1): | |||||
self.websocketclass = websocketclass | |||||
self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |||||
self.serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |||||
self.serversocket.bind((host, port)) | |||||
self.serversocket.listen(5) | |||||
self.selectInterval = selectInterval | |||||
self.connections = {} | |||||
self.listeners = [self.serversocket] | |||||
def _decorateSocket(self, sock): | |||||
return sock | |||||
def _constructWebSocket(self, sock, address): | |||||
return self.websocketclass(self, sock, address) | |||||
def close(self): | |||||
self.serversocket.close() | |||||
for desc, conn in self.connections.items(): | |||||
conn.close() | |||||
conn.handleClose() | |||||
def serveforever(self): | |||||
while True: | |||||
writers = [] | |||||
for fileno in self.listeners: | |||||
if fileno == self.serversocket: | |||||
continue | |||||
client = self.connections[fileno] | |||||
if client.sendq: | |||||
writers.append(fileno) | |||||
if self.selectInterval: | |||||
rList, wList, xList = select(self.listeners, writers, self.listeners, self.selectInterval) | |||||
else: | |||||
rList, wList, xList = select(self.listeners, writers, self.listeners) | |||||
for ready in wList: | |||||
client = self.connections[ready] | |||||
try: | |||||
while client.sendq: | |||||
opcode, payload = client.sendq.popleft() | |||||
remaining = client._sendBuffer(payload) | |||||
if remaining is not None: | |||||
client.sendq.appendleft((opcode, remaining)) | |||||
break | |||||
else: | |||||
if opcode == CLOSE: | |||||
raise Exception('received client close') | |||||
except Exception as n: | |||||
client.client.close() | |||||
client.handleClose() | |||||
del self.connections[ready] | |||||
self.listeners.remove(ready) | |||||
for ready in rList: | |||||
if ready == self.serversocket: | |||||
try: | |||||
sock, address = self.serversocket.accept() | |||||
newsock = self._decorateSocket(sock) | |||||
newsock.setblocking(0) | |||||
fileno = newsock.fileno() | |||||
self.connections[fileno] = self._constructWebSocket(newsock, address) | |||||
self.listeners.append(fileno) | |||||
except Exception as n: | |||||
if sock is not None: | |||||
sock.close() | |||||
else: | |||||
if ready not in self.connections: | |||||
continue | |||||
client = self.connections[ready] | |||||
try: | |||||
client._handleData() | |||||
except Exception as n: | |||||
client.client.close() | |||||
client.handleClose() | |||||
del self.connections[ready] | |||||
self.listeners.remove(ready) | |||||
for failed in xList: | |||||
if failed == self.serversocket: | |||||
self.close() | |||||
raise Exception('server socket failed') | |||||
else: | |||||
if failed not in self.connections: | |||||
continue | |||||
client = self.connections[failed] | |||||
client.client.close() | |||||
client.handleClose() | |||||
del self.connections[failed] | |||||
self.listeners.remove(failed) | |||||
class SimpleSSLWebSocketServer(SimpleWebSocketServer): | |||||
def __init__(self, host, port, websocketclass, certfile, | |||||
keyfile, version = ssl.PROTOCOL_TLSv1, selectInterval = 0.1): | |||||
SimpleWebSocketServer.__init__(self, host, port, | |||||
websocketclass, selectInterval) | |||||
self.context = ssl.SSLContext(version) | |||||
self.context.load_cert_chain(certfile, keyfile) | |||||
def close(self): | |||||
super(SimpleSSLWebSocketServer, self).close() | |||||
def _decorateSocket(self, sock): | |||||
sslsock = self.context.wrap_socket(sock, server_side=True) | |||||
return sslsock | |||||
def _constructWebSocket(self, sock, address): | |||||
ws = self.websocketclass(self, sock, address) | |||||
ws.usingssl = True | |||||
return ws | |||||
def serveforever(self): | |||||
super(SimpleSSLWebSocketServer, self).serveforever() |
@@ -0,0 +1,199 @@ | |||||
""" | |||||
Copied from Anders' original C++ implementation | |||||
S. Anders, H. J. Briegel: Fast Simulation of Stabilizer Circuits using a Graph State Formalism quant-ph/0504117 | |||||
""" | |||||
import numpy as np | |||||
cz_table = ((((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
(1, 0, 6), (1, 0, 6), (0, 3, 8), (0, 3, 8), (0, 0, 10), (0, 0, 10), | |||||
(1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
(1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 3, 8), (0, 3, 8)), | |||||
((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
(1, 0, 6), (1, 0, 6), (0, 2, 8), (0, 2, 8), (0, 0, 10), (0, 0, 10), | |||||
(1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
(1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 2, 8), (0, 2, 8)), | |||||
((1, 2, 3), (1, 0, 1), (1, 0, 2), (1, 2, 0), (1, 0, 4), (1, 2, 6), | |||||
(1, 2, 5), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 2, 10), (0, 2, 10), | |||||
(1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
(1, 0, 4), (1, 0, 4), (0, 2, 10), (0, 2, 10), (0, 0, 8), (0, 0, 8)), | |||||
((1, 3, 0), (1, 0, 1), (1, 0, 2), (1, 3, 3), (1, 0, 4), (1, 3, 5), | |||||
(1, 3, 6), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 3, 10), (0, 3, 10), | |||||
(1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
(1, 0, 4), (1, 0, 4), (0, 3, 10), (0, 3, 10), (0, 0, 8), (0, 0, 8)), | |||||
((1, 4, 3), (1, 4, 3), (1, 4, 0), (1, 4, 0), (1, 4, 6), (1, 4, 6), | |||||
(1, 4, 5), (1, 4, 5), (0, 6, 8), (0, 6, 8), (0, 4, 10), (0, 4, 10), | |||||
(1, 4, 0), (1, 4, 0), (1, 4, 3), (1, 4, 3), (1, 4, 5), (1, 4, 5), | |||||
(1, 4, 6), (1, 4, 6), (0, 4, 10), (0, 4, 10), (0, 6, 8), (0, 6, 8)), | |||||
((1, 5, 0), (1, 5, 0), (1, 5, 3), (1, 5, 3), (1, 5, 5), (1, 5, 5), | |||||
(1, 5, 6), (1, 5, 6), (0, 6, 8), (0, 6, 8), (0, 5, 10), (0, 5, 10), | |||||
(1, 5, 3), (1, 5, 3), (1, 5, 0), (1, 5, 0), (1, 5, 6), (1, 5, 6), | |||||
(1, 5, 5), (1, 5, 5), (0, 5, 10), (0, 5, 10), (0, 6, 8), (0, 6, 8)), | |||||
((1, 6, 0), (1, 5, 1), (1, 5, 2), (1, 6, 3), (1, 5, 4), (1, 6, 5), | |||||
(1, 6, 6), (1, 5, 7), (0, 5, 8), (0, 5, 8), (0, 6, 10), (0, 6, 10), | |||||
(1, 5, 2), (1, 5, 2), (1, 5, 1), (1, 5, 1), (1, 5, 7), (1, 5, 7), | |||||
(1, 5, 4), (1, 5, 4), (0, 6, 10), (0, 6, 10), (0, 5, 8), (0, 5, 8)), | |||||
((1, 6, 0), (1, 4, 2), (1, 4, 1), (1, 6, 3), (1, 4, 7), (1, 6, 5), | |||||
(1, 6, 6), (1, 4, 4), (0, 4, 8), (0, 4, 8), (0, 6, 10), (0, 6, 10), | |||||
(1, 4, 1), (1, 4, 1), (1, 4, 2), (1, 4, 2), (1, 4, 4), (1, 4, 4), | |||||
(1, 4, 7), (1, 4, 7), (0, 6, 10), (0, 6, 10), (0, 4, 8), (0, 4, 8)), | |||||
((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
(0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
(0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
(0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8)), | |||||
((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
(0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
(0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
(0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8)), | |||||
((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
(0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
(0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
(0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
(0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
(0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
(0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
((1, 2, 3), (1, 0, 1), (1, 0, 2), (1, 2, 0), (1, 0, 4), (1, 2, 6), | |||||
(1, 2, 5), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 2, 10), (0, 2, 10), | |||||
(1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
(1, 0, 4), (1, 0, 4), (0, 2, 10), (0, 2, 10), (0, 0, 8), (0, 0, 8)), | |||||
((1, 2, 3), (1, 0, 1), (1, 0, 2), (1, 2, 0), (1, 0, 4), (1, 2, 6), | |||||
(1, 2, 5), (1, 0, 7), (0, 0, 8), (0, 0, 8), (0, 2, 10), (0, 2, 10), | |||||
(1, 0, 2), (1, 0, 2), (1, 0, 1), (1, 0, 1), (1, 0, 7), (1, 0, 7), | |||||
(1, 0, 4), (1, 0, 4), (0, 2, 10), (0, 2, 10), (0, 0, 8), (0, 0, 8)), | |||||
((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
(1, 0, 6), (1, 0, 6), (0, 2, 8), (0, 2, 8), (0, 0, 10), (0, 0, 10), | |||||
(1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
(1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 2, 8), (0, 2, 8)), | |||||
((1, 0, 0), (1, 0, 0), (1, 0, 3), (1, 0, 3), (1, 0, 5), (1, 0, 5), | |||||
(1, 0, 6), (1, 0, 6), (0, 2, 8), (0, 2, 8), (0, 0, 10), (0, 0, 10), | |||||
(1, 0, 3), (1, 0, 3), (1, 0, 0), (1, 0, 0), (1, 0, 6), (1, 0, 6), | |||||
(1, 0, 5), (1, 0, 5), (0, 0, 10), (0, 0, 10), (0, 2, 8), (0, 2, 8)), | |||||
((1, 6, 0), (1, 4, 2), (1, 4, 1), (1, 6, 3), (1, 4, 7), (1, 6, 5), | |||||
(1, 6, 6), (1, 4, 4), (0, 4, 8), (0, 4, 8), (0, 6, 10), (0, 6, 10), | |||||
(1, 4, 1), (1, 4, 1), (1, 4, 2), (1, 4, 2), (1, 4, 4), (1, 4, 4), | |||||
(1, 4, 7), (1, 4, 7), (0, 6, 10), (0, 6, 10), (0, 4, 8), (0, 4, 8)), | |||||
((1, 6, 0), (1, 4, 2), (1, 4, 1), (1, 6, 3), (1, 4, 7), (1, 6, 5), | |||||
(1, 6, 6), (1, 4, 4), (0, 4, 8), (0, 4, 8), (0, 6, 10), (0, 6, 10), | |||||
(1, 4, 1), (1, 4, 1), (1, 4, 2), (1, 4, 2), (1, 4, 4), (1, 4, 4), | |||||
(1, 4, 7), (1, 4, 7), (0, 6, 10), (0, 6, 10), (0, 4, 8), (0, 4, 8)), | |||||
((1, 4, 3), (1, 4, 3), (1, 4, 0), (1, 4, 0), (1, 4, 6), (1, 4, 6), | |||||
(1, 4, 5), (1, 4, 5), (0, 6, 8), (0, 6, 8), (0, 4, 10), (0, 4, 10), | |||||
(1, 4, 0), (1, 4, 0), (1, 4, 3), (1, 4, 3), (1, 4, 5), (1, 4, 5), | |||||
(1, 4, 6), (1, 4, 6), (0, 4, 10), (0, 4, 10), (0, 6, 8), (0, 6, 8)), | |||||
((1, 4, 3), (1, 4, 3), (1, 4, 0), (1, 4, 0), (1, 4, 6), (1, 4, 6), | |||||
(1, 4, 5), (1, 4, 5), (0, 6, 8), (0, 6, 8), (0, 4, 10), (0, 4, 10), | |||||
(1, 4, 0), (1, 4, 0), (1, 4, 3), (1, 4, 3), (1, 4, 5), (1, 4, 5), | |||||
(1, 4, 6), (1, 4, 6), (0, 4, 10), (0, 4, 10), (0, 6, 8), (0, 6, 8)), | |||||
((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
(0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
(0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
(0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
((0, 10, 0), (0, 10, 0), (0, 10, 2), (0, 10, 3), (0, 10, 4), (0, 10, 5), | |||||
(0, 10, 6), (0, 10, 6), (0, 10, 8), (0, 10, 8), (0, 10, 10), (0, 10, 10), | |||||
(0, 10, 2), (0, 10, 2), (0, 10, 0), (0, 10, 0), (0, 10, 6), (0, 10, 6), | |||||
(0, 10, 4), (0, 10, 4), (0, 10, 10), (0, 10, 10), (0, 10, 8), (0, 10, 8)), | |||||
((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
(0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
(0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
(0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8)), | |||||
((0, 8, 3), (0, 8, 2), (0, 8, 0), (0, 8, 0), (0, 8, 6), (0, 8, 6), | |||||
(0, 8, 5), (0, 8, 4), (0, 8, 8), (0, 8, 8), (0, 8, 10), (0, 8, 10), | |||||
(0, 8, 0), (0, 8, 0), (0, 8, 2), (0, 8, 2), (0, 8, 4), (0, 8, 4), | |||||
(0, 8, 6), (0, 8, 6), (0, 8, 10), (0, 8, 10), (0, 8, 8), (0, 8, 8))), | |||||
(((0, 0, 0), (0, 3, 0), (0, 3, 2), (0, 0, 3), (0, 3, 4), (0, 0, 5), | |||||
(0, 0, 6), (0, 3, 6), (1, 5, 23), (1, 5, 22), (1, 5, 21), (1, 5, 20), | |||||
(0, 5, 2), (0, 6, 2), (0, 5, 0), (0, 6, 0), (0, 6, 6), (0, 5, 6), | |||||
(0, 6, 4), (0, 5, 4), (1, 5, 10), (1, 5, 11), (1, 5, 8), (1, 5, 9)), | |||||
((0, 0, 3), (0, 2, 2), (0, 2, 0), (0, 0, 0), (0, 2, 6), (0, 0, 6), | |||||
(0, 0, 5), (0, 2, 4), (1, 4, 23), (1, 4, 22), (1, 4, 21), (1, 4, 20), | |||||
(0, 6, 0), (0, 4, 0), (0, 6, 2), (0, 4, 2), (0, 4, 4), (0, 6, 4), | |||||
(0, 4, 6), (0, 6, 6), (1, 4, 10), (1, 4, 11), (1, 4, 8), (1, 4, 9)), | |||||
((0, 2, 3), (0, 0, 2), (0, 0, 0), (0, 2, 0), (0, 0, 6), (0, 2, 6), | |||||
(0, 2, 5), (0, 0, 4), (1, 4, 22), (1, 4, 23), (1, 4, 20), (1, 4, 21), | |||||
(0, 4, 0), (0, 6, 0), (0, 4, 2), (0, 6, 2), (0, 6, 4), (0, 4, 4), | |||||
(0, 6, 6), (0, 4, 6), (1, 4, 11), (1, 4, 10), (1, 4, 9), (1, 4, 8)), | |||||
((0, 3, 0), (0, 0, 0), (0, 0, 2), (0, 3, 3), (0, 0, 4), (0, 3, 5), | |||||
(0, 3, 6), (0, 0, 6), (1, 5, 22), (1, 5, 23), (1, 5, 20), (1, 5, 21), | |||||
(0, 6, 2), (0, 5, 2), (0, 6, 0), (0, 5, 0), (0, 5, 6), (0, 6, 6), | |||||
(0, 5, 4), (0, 6, 4), (1, 5, 11), (1, 5, 10), (1, 5, 9), (1, 5, 8)), | |||||
((0, 4, 3), (0, 6, 2), (0, 6, 0), (0, 4, 0), (0, 6, 6), (0, 4, 6), | |||||
(0, 4, 5), (0, 6, 4), (1, 0, 21), (1, 0, 20), (1, 0, 23), (1, 0, 22), | |||||
(0, 0, 0), (0, 2, 0), (0, 0, 2), (0, 2, 2), (0, 2, 4), (0, 0, 4), | |||||
(0, 2, 6), (0, 0, 6), (1, 0, 8), (1, 0, 9), (1, 0, 10), (1, 0, 11)), | |||||
((0, 5, 0), (0, 6, 0), (0, 6, 2), (0, 5, 3), (0, 6, 4), (0, 5, 5), | |||||
(0, 5, 6), (0, 6, 6), (1, 0, 22), (1, 0, 23), (1, 0, 20), (1, 0, 21), | |||||
(0, 3, 2), (0, 0, 2), (0, 3, 0), (0, 0, 0), (0, 0, 6), (0, 3, 6), | |||||
(0, 0, 4), (0, 3, 4), (1, 0, 11), (1, 0, 10), (1, 0, 9), (1, 0, 8)), | |||||
((0, 6, 0), (0, 5, 0), (0, 5, 2), (0, 6, 3), (0, 5, 4), (0, 6, 5), | |||||
(0, 6, 6), (0, 5, 6), (1, 0, 23), (1, 0, 22), (1, 0, 21), (1, 0, 20), | |||||
(0, 0, 2), (0, 3, 2), (0, 0, 0), (0, 3, 0), (0, 3, 6), (0, 0, 6), | |||||
(0, 3, 4), (0, 0, 4), (1, 0, 10), (1, 0, 11), (1, 0, 8), (1, 0, 9)), | |||||
((0, 6, 3), (0, 4, 2), (0, 4, 0), (0, 6, 0), (0, 4, 6), (0, 6, 6), | |||||
(0, 6, 5), (0, 4, 4), (1, 0, 20), (1, 0, 21), (1, 0, 22), (1, 0, 23), | |||||
(0, 2, 0), (0, 0, 0), (0, 2, 2), (0, 0, 2), (0, 0, 4), (0, 2, 4), | |||||
(0, 0, 6), (0, 2, 6), (1, 0, 9), (1, 0, 8), (1, 0, 11), (1, 0, 10)), | |||||
((1, 22, 6), (1, 20, 5), (1, 20, 6), (1, 22, 5), (1, 20, 3), (1, 22, 0), | |||||
(1, 22, 3), (1, 20, 0), (0, 0, 0), (0, 0, 2), (0, 2, 2), (0, 2, 0), | |||||
(0, 6, 6), (0, 4, 4), (0, 6, 4), (0, 4, 6), (0, 4, 2), (0, 6, 0), | |||||
(0, 4, 0), (0, 6, 2), (0, 2, 4), (0, 2, 6), (0, 0, 6), (0, 0, 4)), | |||||
((1, 22, 5), (1, 20, 6), (1, 20, 5), (1, 22, 6), (1, 20, 0), (1, 22, 3), | |||||
(1, 22, 0), (1, 20, 3), (0, 2, 0), (0, 2, 2), (0, 0, 2), (0, 0, 0), | |||||
(0, 4, 6), (0, 6, 4), (0, 4, 4), (0, 6, 6), (0, 6, 2), (0, 4, 0), | |||||
(0, 6, 0), (0, 4, 2), (0, 0, 4), (0, 0, 6), (0, 2, 6), (0, 2, 4)), | |||||
((1, 20, 6), (1, 20, 7), (1, 20, 4), (1, 20, 5), (1, 20, 1), (1, 20, 0), | |||||
(1, 20, 3), (1, 20, 2), (0, 2, 2), (0, 2, 0), (0, 0, 0), (0, 0, 2), | |||||
(0, 6, 4), (0, 4, 6), (0, 6, 6), (0, 4, 4), (0, 4, 0), (0, 6, 2), | |||||
(0, 4, 2), (0, 6, 0), (0, 0, 6), (0, 0, 4), (0, 2, 4), (0, 2, 6)), | |||||
((1, 20, 5), (1, 20, 4), (1, 20, 7), (1, 20, 6), (1, 20, 2), (1, 20, 3), | |||||
(1, 20, 0), (1, 20, 1), (0, 0, 2), (0, 0, 0), (0, 2, 0), (0, 2, 2), | |||||
(0, 4, 4), (0, 6, 6), (0, 4, 6), (0, 6, 4), (0, 6, 0), (0, 4, 2), | |||||
(0, 6, 2), (0, 4, 0), (0, 2, 6), (0, 2, 4), (0, 0, 4), (0, 0, 6)), | |||||
((0, 2, 5), (0, 0, 6), (0, 0, 4), (0, 2, 6), (0, 0, 0), (0, 2, 3), | |||||
(0, 2, 0), (0, 0, 2), (0, 6, 6), (0, 6, 4), (0, 4, 6), (0, 4, 4), | |||||
(1, 16, 18), (1, 16, 19), (1, 16, 16), (1, 16, 17), (1, 16, 12), | |||||
(1, 16, 13), (1, 16, 14), (1, 16, 15), (0, 4, 2), (0, 4, 0), (0, 6, 2), | |||||
(0, 6, 0)), ((0, 2, 6), (0, 0, 4), (0, 0, 6), (0, 2, 5), (0, 0, 2), | |||||
(0, 2, 0), (0, 2, 3), (0, 0, 0), (0, 4, 4), (0, 4, 6), (0, 6, 4), | |||||
(0, 6, 6), (1, 16, 17), (1, 16, 16), (1, 16, 19), (1, 16, 18), | |||||
(1, 16, 15), (1, 16, 14), (1, 16, 13), (1, 16, 12), (0, 6, 0), (0, 6, 2), | |||||
(0, 4, 0), (0, 4, 2)), ((0, 0, 5), (0, 2, 6), (0, 2, 4), (0, 0, 6), | |||||
(0, 2, 0), (0, 0, 3), (0, 0, 0), (0, 2, 2), (0, 4, 6), (0, 4, 4), | |||||
(0, 6, 6), (0, 6, 4), (1, 16, 16), (1, 16, 17), (1, 16, 18), (1, 16, 19), | |||||
(1, 16, 14), (1, 16, 15), (1, 16, 12), (1, 16, 13), (0, 6, 2), (0, 6, 0), | |||||
(0, 4, 2), (0, 4, 0)), ((0, 0, 6), (0, 2, 4), (0, 2, 6), (0, 0, 5), | |||||
(0, 2, 2), (0, 0, 0), (0, 0, 3), (0, 2, 0), (0, 6, 4), (0, 6, 6), | |||||
(0, 4, 4), (0, 4, 6), (1, 16, 19), (1, 16, 18), (1, 16, 17), (1, 16, 16), | |||||
(1, 16, 13), (1, 16, 12), (1, 16, 15), (1, 16, 14), (0, 4, 0), (0, 4, 2), | |||||
(0, 6, 0), (0, 6, 2)), ((0, 6, 6), (0, 4, 4), (0, 4, 6), (0, 6, 5), | |||||
(0, 4, 2), (0, 6, 0), (0, 6, 3), (0, 4, 0), (0, 2, 4), (0, 2, 6), | |||||
(0, 0, 4), (0, 0, 6), (1, 12, 16), (1, 12, 17), (1, 12, 18), (1, 12, 19), | |||||
(1, 12, 14), (1, 12, 15), (1, 12, 12), (1, 12, 13), (0, 0, 0), (0, 0, 2), | |||||
(0, 2, 0), (0, 2, 2)), ((0, 6, 5), (0, 4, 6), (0, 4, 4), (0, 6, 6), | |||||
(0, 4, 0), (0, 6, 3), (0, 6, 0), (0, 4, 2), (0, 0, 6), (0, 0, 4), | |||||
(0, 2, 6), (0, 2, 4), (1, 12, 19), (1, 12, 18), (1, 12, 17), (1, 12, 16), | |||||
(1, 12, 13), (1, 12, 12), (1, 12, 15), (1, 12, 14), (0, 2, 2), (0, 2, 0), | |||||
(0, 0, 2), (0, 0, 0)), ((0, 4, 6), (0, 6, 4), (0, 6, 6), (0, 4, 5), | |||||
(0, 6, 2), (0, 4, 0), (0, 4, 3), (0, 6, 0), (0, 0, 4), (0, 0, 6), | |||||
(0, 2, 4), (0, 2, 6), (1, 12, 18), (1, 12, 19), (1, 12, 16), (1, 12, 17), | |||||
(1, 12, 12), (1, 12, 13), (1, 12, 14), (1, 12, 15), (0, 2, 0), (0, 2, 2), | |||||
(0, 0, 0), (0, 0, 2)), ((0, 4, 5), (0, 6, 6), (0, 6, 4), (0, 4, 6), | |||||
(0, 6, 0), (0, 4, 3), (0, 4, 0), (0, 6, 2), (0, 2, 6), (0, 2, 4), | |||||
(0, 0, 6), (0, 0, 4), (1, 12, 17), (1, 12, 16), (1, 12, 19), (1, 12, 18), | |||||
(1, 12, 15), (1, 12, 14), (1, 12, 13), (1, 12, 12), (0, 0, 2), (0, 0, 0), | |||||
(0, 2, 2), (0, 2, 0)), ((1, 10, 5), (1, 8, 6), (1, 8, 5), (1, 10, 6), | |||||
(1, 8, 0), (1, 10, 3), (1, 10, 0), (1, 8, 3), (0, 4, 2), (0, 4, 0), | |||||
(0, 6, 0), (0, 6, 2), (0, 2, 4), (0, 0, 6), (0, 2, 6), (0, 0, 4), | |||||
(0, 0, 0), (0, 2, 2), (0, 0, 2), (0, 2, 0), (0, 6, 6), (0, 6, 4), | |||||
(0, 4, 4), (0, 4, 6)), ((1, 10, 6), (1, 8, 5), (1, 8, 6), (1, 10, 5), | |||||
(1, 8, 3), (1, 10, 0), (1, 10, 3), (1, 8, 0), (0, 6, 2), (0, 6, 0), | |||||
(0, 4, 0), (0, 4, 2), (0, 0, 4), (0, 2, 6), (0, 0, 6), (0, 2, 4), | |||||
(0, 2, 0), (0, 0, 2), (0, 2, 2), (0, 0, 0), (0, 4, 6), (0, 4, 4), | |||||
(0, 6, 4), (0, 6, 6)), ((1, 8, 5), (1, 8, 4), (1, 8, 7), (1, 8, 6), | |||||
(1, 8, 2), (1, 8, 3), (1, 8, 0), (1, 8, 1), (0, 6, 0), (0, 6, 2), | |||||
(0, 4, 2), (0, 4, 0), (0, 2, 6), (0, 0, 4), (0, 2, 4), (0, 0, 6), | |||||
(0, 0, 2), (0, 2, 0), (0, 0, 0), (0, 2, 2), (0, 4, 4), (0, 4, 6), | |||||
(0, 6, 6), (0, 6, 4)), ((1, 8, 6), (1, 8, 7), (1, 8, 4), (1, 8, 5), | |||||
(1, 8, 1), (1, 8, 0), (1, 8, 3), (1, 8, 2), (0, 4, 0), (0, 4, 2), | |||||
(0, 6, 2), (0, 6, 0), (0, 0, 6), (0, 2, 4), (0, 0, 4), (0, 2, 6), | |||||
(0, 2, 2), (0, 0, 0), (0, 2, 0), (0, 0, 2), (0, 6, 4), (0, 6, 6), | |||||
(0, 4, 6), (0, 4, 4)))) | |||||
cz_table = np.array(cz_table, dtype = int) |
@@ -1,92 +0,0 @@ | |||||
import urlparse | |||||
from BaseHTTPServer import BaseHTTPRequestHandler | |||||
from SimpleHTTPServer import SimpleHTTPRequestHandler | |||||
import SocketServer | |||||
import sys | |||||
import json | |||||
import threading | |||||
import time | |||||
import os | |||||
from graphstate import GraphState | |||||
class VizHandler(SimpleHTTPRequestHandler): | |||||
""" Handles requests to the server """ | |||||
def __init__(self, *args, **kwargs): | |||||
SimpleHTTPRequestHandler.__init__(self, *args, **kwargs) | |||||
def get_state(self): | |||||
""" Get the current graphstate state """ | |||||
self.send_response(200) | |||||
self.send_header('Content-Type', 'application/json') | |||||
self.end_headers() | |||||
state = self.server.state | |||||
self.wfile.write(state.to_json()) | |||||
def do_GET(self, *args, **kwargs): | |||||
""" Someone belled the server """ | |||||
parsed_path = urlparse.urlparse(self.path) | |||||
if parsed_path.path == "/state": | |||||
return self.get_state() | |||||
else: | |||||
return SimpleHTTPRequestHandler.do_GET(self, *args, **kwargs) | |||||
class Server(SocketServer.TCPServer): | |||||
""" Serves the good stuff """ | |||||
allow_reuse_address = True | |||||
def __init__(self, port=8000): | |||||
self.port = port | |||||
self.state = None | |||||
SocketServer.TCPServer.__init__( | |||||
self, ("127.0.0.1", self.port), VizHandler) | |||||
def update(self, state): | |||||
""" Update the in-memory state """ | |||||
self.state = state | |||||
def run(self): | |||||
""" Run in such a way that keyboard interrupts are caught properly """ | |||||
try: | |||||
self.serve_forever() | |||||
except KeyboardInterrupt: | |||||
self.shutdown() | |||||
def start(self): | |||||
""" Start in a new thread """ | |||||
thread = threading.Thread(None, self.run) | |||||
thread.daemon = True | |||||
thread.start() | |||||
print "Server running at http://localhost:{}/".format(self.port) | |||||
def demograph(): | |||||
""" A graph for testing with """ | |||||
g = GraphState() | |||||
g.add_edge(0, 1) | |||||
g.add_edge(1, 2) | |||||
g.add_edge(2, 0) | |||||
g.add_edge(0, 3) | |||||
g.add_edge(100, 200) | |||||
return g | |||||
if __name__ == '__main__': | |||||
where = os.path.join(sys.path[0], "../static") | |||||
os.chdir(where) | |||||
server = Server() | |||||
server.start() | |||||
g = demograph() | |||||
g.layout() | |||||
while True: | |||||
server.update(g) | |||||
time.sleep(1) | |||||
server.shutdown() |
@@ -1,26 +0,0 @@ | |||||
import networkx as nx | |||||
from matplotlib import pyplot as plt | |||||
import clifford | |||||
import numpy as np | |||||
from graphstate import GraphState | |||||
VOP_COLORS = ["red", "green", "blue", "orange", "yellow", "purple", "black", "white"] | |||||
def draw(state, filename="out.pdf", pos=None, ns=500): | |||||
""" Draw a graph with networkx layout """ | |||||
plt.clf() | |||||
graph = nx.from_edgelist(state.edgelist()) | |||||
pos = nx.spring_layout(graph) if pos==None else pos | |||||
colors = [VOP_COLORS[vop % len(VOP_COLORS)] for vop in state.vops.values()] | |||||
nx.draw_networkx_nodes(graph, pos, node_color="white", node_size=ns) | |||||
nx.draw_networkx_nodes(graph, pos, node_color=colors, node_size=ns, alpha=.4) | |||||
nx.draw_networkx_edges(graph, pos, edge_color="gray") | |||||
nx.draw_networkx_labels(graph, pos, font_family="FreeSans") | |||||
# tables.name_of(v) | |||||
labels = {i: "no name" for i, v in state.vops.items()} | |||||
pos = {k: v + np.array([0, -.1]) for k, v in pos.items()} | |||||
nx.draw_networkx_labels(graph, pos, labels, font_family="FreeSans") | |||||
plt.axis('off') | |||||
plt.savefig(filename) | |||||
return pos |
@@ -1,13 +0,0 @@ | |||||
from abp.graphstate import GraphState | |||||
from abp import viz | |||||
def test_viz(): | |||||
g = GraphState(range(4)+[100, 200]) | |||||
g.add_edge(0, 1) | |||||
g.add_edge(1, 2) | |||||
g.add_edge(2, 0) | |||||
g.add_edge(0, 3) | |||||
g.add_edge(100, 200) | |||||
# g.remove_vop(0, 1) | |||||
viz.draw(g) |