diff options
| author | Morgana <Morgana@icolotl.com> | 2026-10-03 16:37:05 -0500 |
|---|---|---|
| committer | Morgana <Morgana@icolotl.com> | 2026-10-03 16:37:05 -0500 |
| commit | 65128ee7a55e0f0b5997bb2932582a0a1a0ae779 (patch) | |
| tree | 938f7d3d484dcc22d7db8ea6bfa4792bfe185cd9 | |
| parent | dfe2069c1dd4eb14d44a57d35d76afdc47d1598e (diff) | |
Implement eGuide
| -rw-r--r-- | app.py | 102 | ||||
| -rw-r--r-- | captcha.py | 19 | ||||
| -rw-r--r-- | static/script/captcha.js | 1 | ||||
| -rw-r--r-- | static/style/eguide.css | 12 | ||||
| -rw-r--r-- | static/style/style.css | 4 | ||||
| -rw-r--r-- | templates/eguide.html | 23 |
6 files changed, 159 insertions, 2 deletions
@@ -25,6 +25,99 @@ GUEST_CAPTCHA = Captcha.from_string( 5, "m...cena....m...ebneb.clm", ".........................", True ) +GUIDE_CAPTCHAS = { + "Layer 01": [ + Captcha.from_string(2, "a...", "...."), + Captcha.from_string(2, "aaa.", "01.."), + Captcha.from_string(2, "aaaa", "...."), + ], + "Layer 02": [ + Captcha.from_string(2, "b...", "...."), + Captcha.from_string(2, "b.b.", "0.1."), + Captcha.from_string(2, "bbbb", "00.."), + ], + "Layer 03": [ + Captcha.from_string(2, "c...", "...."), + Captcha.from_string(2, "c...", ".11."), + Captcha.from_string(2, "c.c.", "1.1."), + ], + "Layer 04": [ + Captcha.from_string(2, "ac..", "01.."), + Captcha.from_string(2, "ab..", "...."), + Captcha.from_string(2, "bba.", "...."), + ], + "Layer 05": [ + Captcha.from_string(2, "d...", "1..."), + Captcha.from_string(2, "d...", "..1."), + Captcha.from_string(2, "d..d", "...1"), + ], + "Layer 06": [ + Captcha.from_string(3, "c.c.c.c.c", "........."), + Captcha.from_string(3, "c.b...b.a", "........."), + Captcha.from_string(3, "d...d...d", "........."), + ], + "Layer 11": [ + Captcha.from_string(3, "m.m......", "10.10.00."), + Captcha.from_string(3, "m.......m", "10.10.01."), + Captcha.from_string(3, "m.m...m.m", "1.1...2.2"), + ], + "Layer 12": [ + Captcha.from_string(3, "m.m...n.n", "1.1...2.2"), + Captcha.from_string(3, "m.n...n.m", "1.1...2.2"), + Captcha.from_string(3, "m.m...n.n", "1.2....0."), + ], + "Layer 13": [ + Captcha.from_string(4, "m....m..........", "11..10.........."), + Captcha.from_string(4, "mmnn......cc...c", "01230...0...0..."), + Captcha.from_string(4, "mn............nm", "1...11.........."), + Captcha.from_string(4, "mn..nm........nm", "................"), + ], + "Layer 14": [ + Captcha.from_string(4, "m..a.m.........d", "11..10.......0.."), + Captcha.from_string(4, "m..a.m.........d", "11..10.......2.."), + Captcha.from_string(4, "m..a.md........d", "11..10.......0.."), + Captcha.from_string(4, "m.bn.mc.....n..d", "11..10.......2.."), + ], + "Layer 21": [ + Captcha.from_string(3, "....v....", "0101.10.0"), + Captcha.from_string(3, "....v....", "1101.10.0"), + Captcha.from_string(3, "v.......v", "1101020.."), + ], + "Layer 22": [ + Captcha.from_string(3, "v....v.v.", "0......1."), + Captcha.from_string(3, "vm.....m.", ".1.....0."), + Captcha.from_string(3, "v..m.m.v.", ".....1.0."), + ], + "Layer 23": [ + Captcha.from_string(3, "....l....", "...010..."), + Captcha.from_string(3, ".l..l..l.", ".1..0..1."), + Captcha.from_string(3, "..l.l.l..", ".1011...."), + ], + "Layer 24": [ + Captcha.from_string(3, "...cl...d", "....1...."), + Captcha.from_string(3, "l...d...l", "........."), + Captcha.from_string(3, "l...a.b.l", "........."), + ], + "Layer 31": [ + Captcha.from_string(3, "r...c...r", "31.312.1."), + Captcha.from_string(3, "r.b.c.b.r", "........."), + Captcha.from_string(3, "raa.d.a.r", "........."), + ], + "Layer 32": [ + Captcha.from_string(3, "....e....", "0001020.0"), + Captcha.from_string(3, "....e....", "....2...."), + Captcha.from_string(3, "e.e...e.e", "........."), + ], + "Layer 33": [ + Captcha.from_string(3, "ebebb.e.e", ".1.23...."), + Captcha.from_string(3, "eaeac.e.e", "........."), + Captcha.from_string(3, "eaebede.e", "........."), + ], + "Layer 34": [ + Captcha.from_string(4, "er...em..me.dbre", "................"), + ], +} + def get_db(): if "db" not in g: @@ -45,7 +138,9 @@ def has_captcha(captcha_id): def add_captcha(captcha_id): if "captcha" not in session: session["captcha"] = [] - session["captcha"].append(captcha_id) + if captcha_id not in session["captcha"]: + session["captcha"].append(captcha_id) + session.modified = True app = Flask(__name__) @@ -134,6 +229,11 @@ def guest_login(): return render_template("guest.html", captcha=GUEST_CAPTCHA) +@app.route("/eguide") +def eguide(): + return render_template("eguide.html", captchas=GUIDE_CAPTCHAS) + + @app.route("/logout") def logout(): if "username" in session: @@ -24,6 +24,22 @@ def adj(grid, x: int, y: int, orth=False, center=False) -> list[int]: return [v for v in base if v is not None] +def across(grid, x: int, y: int) -> bool: + side_length = int(len(grid) ** 0.5) + cell = value(grid, x, y) + for nx in range(0, side_length): + if value(grid, nx, y) != cell: + break + else: + return True + for ny in range(0, side_length): + if value(grid, x, ny) != cell: + break + else: + return True + return False + + class Shape: def __init__(self, grid, x: int, y: int) -> None: self.value = value(grid, x, y) @@ -130,6 +146,9 @@ class Captcha: near = adj(answer, x, y, True, False) if len(near) != len(set(near)): return False + case "l": + if not across(answer, x, y): + return False case "m": shape = Shape(answer, x, y) if shape_match_m: diff --git a/static/script/captcha.js b/static/script/captcha.js index 78dcb3d..69667dd 100644 --- a/static/script/captcha.js +++ b/static/script/captcha.js @@ -71,7 +71,6 @@ class DroseraCaptcha extends HTMLElement { this.outer.disabled = true; window.fetch(request).then(response => { if (response.ok) { - this.outer.disabled = false; this.outer.dataset.solved = ""; if (this.reload) { location.reload(); diff --git a/static/style/eguide.css b/static/style/eguide.css new file mode 100644 index 0000000..85282ca --- /dev/null +++ b/static/style/eguide.css @@ -0,0 +1,12 @@ +details { + >summary { + font-variant: small-caps; + } + + >div { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + } +}
\ No newline at end of file diff --git a/static/style/style.css b/static/style/style.css index 3e7e850..b16b5fd 100644 --- a/static/style/style.css +++ b/static/style/style.css @@ -104,6 +104,10 @@ main.centered { margin: auto; } +main.padded { + padding: 1em; +} + #flashes { font-size: 0.8em; position: absolute; diff --git a/templates/eguide.html b/templates/eguide.html new file mode 100644 index 0000000..c957c84 --- /dev/null +++ b/templates/eguide.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% block head %} +<script src="{{ url_for('static', filename='script/captcha.js') }}" defer></script> +<link rel="stylesheet" href="{{ url_for('static', filename='style/eguide.css') }}"> +{% endblock %} + +{% block content %} +<main class="padded"> + <h2>Drosera Springs eGuide</h2> + <p>The following captchas are provided for your convinience.</p> + {% for section in captchas %} + <details> + <summary>{{ section }}</summary> + <div> + {% for captcha in captchas[section] %} + {{ render_captcha(captcha) }} + {% endfor %} + </div> + </details> + {% endfor %} +</main> +{% endblock %}
\ No newline at end of file |