Anders and Briegel in Python
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
3.2KB

  1. from flask import Flask, request, render_template, jsonify, g
  2. from werkzeug.contrib.cache import SimpleCache
  3. import json
  4. import abp
  5. import argparse
  6. #TODO: only send deltas
  7. #graphstate = abp.GraphState()
  8. cache = SimpleCache(default_timeout = 10000)
  9. cache.set("state", abp.GraphState())
  10. app = Flask(__name__)
  11. class InvalidUsage(Exception):
  12. status_code = 400
  13. def __init__(self, message, status_code=None, payload=None):
  14. Exception.__init__(self)
  15. self.message = message
  16. if status_code is not None:
  17. self.status_code = status_code
  18. self.payload = payload
  19. def to_dict(self):
  20. rv = dict(self.payload or ())
  21. rv['message'] = self.message
  22. return rv
  23. @app.errorhandler(InvalidUsage)
  24. def handle_invalid_usage(error):
  25. response = jsonify(error.to_dict())
  26. response.status_code = error.status_code
  27. return response
  28. @app.before_request
  29. def before_request():
  30. g.state = cache.get("state")
  31. @app.after_request
  32. def after_request(response):
  33. cache.set("state", g.state)
  34. return response
  35. @app.route("/")
  36. def index():
  37. return render_template("index.html")
  38. @app.route("/state", methods = ["GET", "POST"])
  39. def state():
  40. if request.method == "GET":
  41. output = g.state.to_json()
  42. output["needs_update"] = cache.get("needs_update")
  43. cache.set("needs_update", False)
  44. return jsonify(output)
  45. elif request.method == "POST":
  46. g.state = abp.GraphState()
  47. g.state.from_json(json.loads(request.data))
  48. cache.set("needs_update", True)
  49. return jsonify({"update": "ok"})
  50. @app.route("/add_node/<int:node>")
  51. def add_node(node):
  52. """ Add a node to the graph """
  53. if node in g.state.vops:
  54. raise InvalidUsage("Node {} is already in the graph".format(node))
  55. g.state.add_node(node)
  56. g.state.layout()
  57. cache.set("needs_update", True)
  58. return jsonify({"add_node": "okay"})
  59. @app.route("/act_local_rotation/<int:node>/<int:operation>")
  60. def act_local_rotation(node, operation):
  61. """ Add a node to the graph """
  62. # TODO: try to lookup the operation first
  63. if not node in g.state.vops:
  64. raise InvalidUsage("Node {} does not exist".format(node))
  65. if not operation in range(24):
  66. raise InvalidUsage("Invalid local rotation {}".format(operation))
  67. g.state.act_local_rotation(node, operation)
  68. cache.set("needs_update", True)
  69. return jsonify({"act_local_rotation": "okay"})
  70. @app.route("/act_cz/<int:a>/<int:b>")
  71. def act_cz(a, b):
  72. """ Add a node to the graph """
  73. for node in (a, b):
  74. if not node in g.state.vops:
  75. raise InvalidUsage("Node {} does not exist".format(node))
  76. g.state.act_cz(a, b)
  77. g.state.layout()
  78. cache.set("needs_update", True)
  79. return jsonify({"act_cz": "okay"})
  80. @app.route("/clear")
  81. def clear():
  82. """ Clear the current state """
  83. g.state = abp.GraphState()
  84. cache.set("needs_update", True)
  85. return jsonify({"clear": "okay"})
  86. if __name__ == "__main__":
  87. parser = argparse.ArgumentParser()
  88. parser.add_argument("-d", "--debug", help="Run in debug mode", action="store_true", default=False)
  89. args = parser.parse_args()
  90. app.debug = args.debug
  91. app.run(host="0.0.0.0")