@@ -3,16 +3,23 @@ from flask_redis import FlaskRedis | |||
import json, abp, markdown | |||
from pprint import pprint | |||
import raussendorf | |||
import humanhash | |||
DAY = 60*60*24 | |||
app = Flask(__name__) | |||
redis = FlaskRedis(app) | |||
@app.route("/") | |||
def index(): | |||
return render_template("index.html") | |||
secret, uuid = humanhash.uuid() | |||
return redirect("/{}".format(secret)) | |||
@app.route("/graph", methods=["GET", "POST"]) | |||
def graph(): | |||
@app.route("/<uuid>") | |||
def main(uuid): | |||
return render_template("index.html", uuid=uuid) | |||
@app.route("/<uuid>/graph", methods=["GET", "POST"]) | |||
def graph(uuid): | |||
if request.method == 'POST': | |||
# Convert the data to a graph state | |||
g = abp.GraphState() | |||
@@ -22,21 +29,24 @@ def graph(): | |||
data = json.dumps(g.to_json(stringify=True)) | |||
# Insert into the database | |||
redis.execute_command("SET", "graph", data) | |||
redis.setex(uuid, data, DAY) | |||
# Return success | |||
return "Posted {} bytes OK".format(len(data)) | |||
elif redis.exists(uuid): | |||
return redis.get(uuid) | |||
else: | |||
# Get from the database | |||
return redis.get("graph") | |||
g = abp.GraphState() | |||
data = json.dumps(g.to_json(stringify=True)) | |||
redis.setex(uuid, DAY, data) | |||
return data | |||
@app.route("/edit", methods=["POST"]) | |||
def edit(): | |||
@app.route("/<uuid>/edit", methods=["POST"]) | |||
def edit(uuid): | |||
# Load the graph from the database | |||
g = abp.GraphState() | |||
g.from_json(json.loads(redis.get("graph"))) | |||
g.from_json(json.loads(redis.get(uuid))) | |||
# Apply the edit to the graph | |||
edit = json.loads(request.data) | |||
@@ -66,7 +76,7 @@ def edit(): | |||
# New state into JSON and database | |||
data = json.dumps(g.to_json(stringify=True)) | |||
redis.execute_command("SET", "graph", data) | |||
redis.setex(uuid, DAY, data) | |||
return data | |||
@@ -1,4 +1,5 @@ | |||
html, body { margin: 0; padding: 0; overflow: hidden; font-size: 10pt; font-family: monospace; } | |||
html, body { margin: 0; padding: 0; overflow: hidden; font-size: 10pt; | |||
font-family: monospace; } | |||
#node_info { | |||
background: rgba(0, 0, 0, .8); | |||
color:white; | |||
@@ -7,23 +8,20 @@ html, body { margin: 0; padding: 0; overflow: hidden; font-size: 10pt; font-fam | |||
position: absolute; | |||
top:5px; | |||
left:5px; | |||
font-family: monospace; | |||
/*font-family: monospace;*/ | |||
text-align: center; | |||
font-size:9pt; | |||
/*height:15px;*/ | |||
border-radius:3px; | |||
pointer-events: none; | |||
} | |||
#server_info { | |||
background-color: black; | |||
background-color: rgba(0, 0, 0, .8); | |||
color:white; | |||
padding: 10px; | |||
font-family: monospace; | |||
position: absolute; | |||
top: 10px; | |||
right: 10px; | |||
font-size: 9pt; | |||
} | |||
#node_name { | |||
@@ -31,25 +29,21 @@ html, body { margin: 0; padding: 0; overflow: hidden; font-size: 10pt; font-fam | |||
} | |||
#node_data { | |||
background-color: black; | |||
background-color: rgba(0, 0, 0, .8); | |||
color:white; | |||
padding: 10px; | |||
font-family: monospace; | |||
position: absolute; | |||
top: 10px; | |||
left: 10px; | |||
font-size: 9pt; | |||
} | |||
#controls { | |||
background-color: black; | |||
background-color: rgba(0, 0, 0, .8); | |||
color:white; | |||
padding: 10px; | |||
font-family: monospace; | |||
position: absolute; | |||
bottom: 10px; | |||
left: 10px; | |||
font-size: 9pt; | |||
} | |||
#controls a { | |||
@@ -60,6 +54,7 @@ html, body { margin: 0; padding: 0; overflow: hidden; font-size: 10pt; font-fam | |||
margin: 1px; | |||
display: inline-block; | |||
text-decoration: none; | |||
cursor: pointer; | |||
} | |||
#node_data a { | |||
@@ -70,31 +65,29 @@ html, body { margin: 0; padding: 0; overflow: hidden; font-size: 10pt; font-fam | |||
margin: 1px; | |||
display: inline-block; | |||
text-decoration: none; | |||
cursor: pointer; | |||
} | |||
#version { | |||
color:black; | |||
padding: 10px; | |||
font-family: monospace; | |||
position: absolute; | |||
bottom: 10px; | |||
left: 10px; | |||
font-size: 9pt; | |||
} | |||
#help { | |||
color:black; | |||
background-color: rgba(0, 0, 0, .8); | |||
color:white; | |||
padding: 10px; | |||
font-family: monospace; | |||
position: absolute; | |||
bottom: 10px; | |||
right: 10px; | |||
font-size: 9pt; | |||
} | |||
#help a{ | |||
color: black; | |||
color: white; | |||
} | |||
@@ -11,7 +11,7 @@ api.poll = function() { | |||
}; | |||
// Send the request | |||
xmlhttp.open("GET", "/graph", true); | |||
xmlhttp.open("GET", window.location.href+"/graph", true); | |||
xmlhttp.send(); | |||
}; | |||
@@ -32,7 +32,7 @@ api.edit = function(edit) { | |||
}; | |||
// Send the request | |||
xmlhttp.open("POST", "/edit", true); | |||
xmlhttp.open("POST", window.location.href+"/edit", true); | |||
xmlhttp.setRequestHeader("Content-Type", "application/json"); | |||
xmlhttp.send(JSON.stringify(edit)); | |||
} | |||
@@ -6,5 +6,6 @@ window.onload = function() { | |||
gui.prepare(); | |||
mouse.prepare(); | |||
editor.prepare(); | |||
api.poll(); | |||
gui.loop(); | |||
}; |
@@ -24,45 +24,33 @@ | |||
<div id=node_info class=hidden> </div> | |||
<div id=server_info class=hidden> </div> | |||
<!--<div id=version>ABP version 0.4.27</div>--> | |||
<div id=node_data class=hidden> | |||
<div id=node_name></div> | |||
<ul> | |||
<li id=node_vop></li> | |||
<li>Measure in | |||
<a href="#" onclick="editor.measureX()">X</a> / | |||
<a href="#" onclick="editor.measureY()">Y</a> / | |||
<a href="#" onclick="editor.measureZ()">Z</a></li> | |||
<a onclick="editor.measureX()">X</a> / | |||
<a onclick="editor.measureY()">Y</a> / | |||
<a onclick="editor.measureZ()">Z</a></li> | |||
<li>Act | |||
<a href="#" onclick="editor.hadamard()">Hadamard</a> / | |||
<a href="#" onclick="editor.phase()">Phase</a></li> | |||
<li><a href="#" onclick="editor.localComplementation()">Invert neighbourhood</a></li> | |||
<li><a href="#" onclick="editor.deleteNode()">Delete</a></li> | |||
<a onclick="editor.hadamard()">Hadamard</a> / | |||
<a onclick="editor.phase()">Phase</a></li> | |||
<li><a onclick="editor.localComplementation()">Invert neighbourhood</a></li> | |||
<li><a onclick="editor.deleteNode()">Delete</a></li> | |||
</ul> | |||
</div> | |||
<div id=controls> | |||
<ul> | |||
<li><a href="#" onclick="editor.clear()">Clear graph</a></li> | |||
<li><a href="#" onclick="editor.raussendorf()">Replace with Raussendorf</a></li> | |||
<li><a onclick="editor.clear()">Clear graph</a></li> | |||
<li><a onclick="editor.raussendorf()">Raussendorf</a></li> | |||
<li><a onclick="editor.raussendorf()">Share</a></li> | |||
</ul> | |||
</div> | |||
<div id=help> | |||
<h3>Usage:</h3> | |||
Click on the grid to make a new node<br/> | |||
Ctrl-click a node to do a Hadamard<br/> | |||
Select a node, then shift-click another node to do a CZ<br/> | |||
Press space to rotate the grid<br/> | |||
<h3>API usage:</h3> | |||
GET https://abv.peteshadbolt.co.uk/graph -> JSON<br/> | |||
POST JSON -> https://abv.peteshadbolt.co.uk/graph<br/> | |||
POST JSON -> https://abv.peteshadbolt.co.uk/edit | |||
<p>See <a href="/doc">here</a> for docs.</p> | |||
<a href="/doc">Help</a> | |||
</div> | |||
</body> | |||