From 906444ddac23b5f78766625db36457b850b13055 Mon Sep 17 00:00:00 2001 From: Pete Shadbolt Date: Sun, 15 Oct 2017 22:50:47 -0700 Subject: [PATCH] Really simple docs --- app.py | 6 +- static/doc.css | 110 +++++++++++++++++++++++++++++++++++++ static/main.css | 1 + templates/boilerplate.html | 13 +++++ templates/doc.md | 51 +++++++++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 static/doc.css create mode 100644 templates/boilerplate.html create mode 100644 templates/doc.md diff --git a/app.py b/app.py index fae02ca..ab78aeb 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,6 @@ from flask import Flask, request, redirect, url_for, make_response, render_template, Markup, send_from_directory, send_file from flask_redis import FlaskRedis -import json, abp +import json, abp, markdown app = Flask(__name__) redis = FlaskRedis(app) @@ -29,4 +29,8 @@ def graph(): # Get from the database return redis.get("graph") +@app.route("/doc") +def doc(): + body = Markup(markdown.markdown(render_template("doc.md"), extensions=["markdown.extensions.codehilite"])) + return render_template("boilerplate.html", body=body) diff --git a/static/doc.css b/static/doc.css new file mode 100644 index 0000000..dafa369 --- /dev/null +++ b/static/doc.css @@ -0,0 +1,110 @@ +body { + margin: 40px auto; + max-width: 650px; + padding: 0 10px; + font-family: monospace; + font-size: 11pt; +} + +code { + overflow: scroll; + color: #aa0000; +} + +pre{ + padding: 2em; + background-color: #fafafa; + border: 1px solid #eeeeee; + overflow-x: auto; +} + +form{ + padding: 1em; + background-color: #fafafa; + border: 1px solid #eeeeee; +} + +input +{ + font-size: 11pt; + margin: .5em; +} + +input[type=file] { + white-space: nowrap; + overflow: hidden; + width: 300px; + font-family: monospace; + color: gray; +} + + +.codehilite .hll { background-color: #ffffcc } +.codehilite { background: #f8f8f8; } +.codehilite .c { color: #408080; font-style: italic } /* Comment */ +.codehilite .err { border: 1px solid #FF0000 } /* Error */ +.codehilite .k { color: #008000; font-weight: bold } /* Keyword */ +.codehilite .o { color: #666666 } /* Operator */ +.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */ +.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */ +.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */ +.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */ +.codehilite .gd { color: #A00000 } /* Generic.Deleted */ +.codehilite .ge { font-style: italic } /* Generic.Emph */ +.codehilite .gr { color: #FF0000 } /* Generic.Error */ +.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.codehilite .gi { color: #00A000 } /* Generic.Inserted */ +.codehilite .go { color: #888888 } /* Generic.Output */ +.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.codehilite .gs { font-weight: bold } /* Generic.Strong */ +.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.codehilite .gt { color: #0044DD } /* Generic.Traceback */ +.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.codehilite .kp { color: #008000 } /* Keyword.Pseudo */ +.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.codehilite .kt { color: #B00040 } /* Keyword.Type */ +.codehilite .m { color: #666666 } /* Literal.Number */ +.codehilite .s { color: #BA2121 } /* Literal.String */ +.codehilite .na { color: #7D9029 } /* Name.Attribute */ +.codehilite .nb { color: #008000 } /* Name.Builtin */ +.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.codehilite .no { color: #880000 } /* Name.Constant */ +.codehilite .nd { color: #AA22FF } /* Name.Decorator */ +.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.codehilite .nf { color: #0000FF } /* Name.Function */ +.codehilite .nl { color: #A0A000 } /* Name.Label */ +.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.codehilite .nv { color: #19177C } /* Name.Variable */ +.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.codehilite .w { color: #bbbbbb } /* Text.Whitespace */ +.codehilite .mb { color: #666666 } /* Literal.Number.Bin */ +.codehilite .mf { color: #666666 } /* Literal.Number.Float */ +.codehilite .mh { color: #666666 } /* Literal.Number.Hex */ +.codehilite .mi { color: #666666 } /* Literal.Number.Integer */ +.codehilite .mo { color: #666666 } /* Literal.Number.Oct */ +.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */ +.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */ +.codehilite .sc { color: #BA2121 } /* Literal.String.Char */ +.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */ +.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */ +.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.codehilite .sx { color: #008000 } /* Literal.String.Other */ +.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */ +.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */ +.codehilite .ss { color: #19177C } /* Literal.String.Symbol */ +.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.codehilite .fm { color: #0000FF } /* Name.Function.Magic */ +.codehilite .vc { color: #19177C } /* Name.Variable.Class */ +.codehilite .vg { color: #19177C } /* Name.Variable.Global */ +.codehilite .vi { color: #19177C } /* Name.Variable.Instance */ +.codehilite .vm { color: #19177C } /* Name.Variable.Magic */ +.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/static/main.css b/static/main.css index dfb3a4a..7961aa8 100644 --- a/static/main.css +++ b/static/main.css @@ -101,3 +101,4 @@ h3 { margin-top: 2px; margin-bottom: 2px; } + diff --git a/templates/boilerplate.html b/templates/boilerplate.html new file mode 100644 index 0000000..b177285 --- /dev/null +++ b/templates/boilerplate.html @@ -0,0 +1,13 @@ + + + + + abp + + + + + + {{body}} + + diff --git a/templates/doc.md b/templates/doc.md new file mode 100644 index 0000000..5e2c11c --- /dev/null +++ b/templates/doc.md @@ -0,0 +1,51 @@ +# ABP + +This server does a few things: + +- Keeps a graph state in memory using a data structure that is compatible with `abp` +- Serves a JSON representation of that object +- Accepts updates to that object via POST requests +- Displays a 3D representation of the state +- Randomly updates the state every five seconds + +## Endpoints + +- `/`: Displays the state using Three.js +- `graph/`: + - `GET` returns JSON representing the state + - `POST` accepts JSON in the same format and overwrites the state in memory +- `doc/`: Shows this page + + +## Data format + +If you do an HTTPS GET against `graph/`, you will receive some JSON. + + :::bash + $ curl https://abv.peteshadbolt.co.uk/graph + +outputs + + :::python + {"node": {"30": {"position": {"y": 3.245091885135617, "x": -1.0335390368621762, "z": 0.12485495696298532}, "vop": 0}, "28": {"position": {"y": 0.1811335599620998, "x": 3.7102305790943295, "z": 0.3375519427305571}, "vop": 0}, "29": {"position": {"y": -1.834182888403804, "x": 1.5968911365745622, "z": 2.8585980299131886 ... + +The top-level keys are `node` and `adj`. These model the node metadata and adjacency matrix respectively. + +Each `node` has + +- a `position` (`{x:<> y:<> z:<>}`) +- a `vop` (integer, ignore for now) +- and could also have a `color`, `label`, etc. + +`adj` uses the same data structure as `networkx` to efficiently represent sparse adjacency matrices. For each key `i` in `adj`, the value of `adj[i]` is itself a map whose keys `j` correspond to the ids of nodes connected to `i`. The value of `adj[i][j]` is a map which is usually empty but which could be used to store metadata about the edge. + +Here's an example of a graph `(A-B C)`: + + :::python + {'adj': {0: {1: {}}, 1: {0: {}}, 2: {}}, + 'node': { + 0: {'position': {'x': 0, 'y': 0, 'z': 0}, 'vop': 0}, + 1: {'position': {'x': 1, 'y': 0, 'z': 0}, 'vop': 0}, + 2: {'position': {'x': 2, 'y': 0, 'z': 0}, 'vop': 10}}} + +