summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app.py102
-rw-r--r--captcha.py19
-rw-r--r--static/script/captcha.js1
-rw-r--r--static/style/eguide.css12
-rw-r--r--static/style/style.css4
-rw-r--r--templates/eguide.html23
6 files changed, 159 insertions, 2 deletions
diff --git a/app.py b/app.py
index 6a98763..af687e4 100644
--- a/app.py
+++ b/app.py
@@ -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:
diff --git a/captcha.py b/captcha.py
index e5fe28c..4011bbd 100644
--- a/captcha.py
+++ b/captcha.py
@@ -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