| @@ -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> | |||