Output website template from postprocessor
This commit is contained in:
parent
2acb7c7e3c
commit
fb6081d4d6
1 changed files with 163 additions and 166 deletions
|
@ -70,182 +70,179 @@ for row in raw_data_object["data"]:
|
||||||
for row in raw_data_object["notes"]:
|
for row in raw_data_object["notes"]:
|
||||||
notes_by_type[(row["chemistry"], row["format"], row["subformat"])] = row["note"]
|
notes_by_type[(row["chemistry"], row["format"], row["subformat"])] = row["note"]
|
||||||
|
|
||||||
|
acc = """---
|
||||||
|
title: "Film Development Price Comparison"
|
||||||
|
hideAside: true
|
||||||
|
asDirectory: false
|
||||||
|
---
|
||||||
|
{% extends "_layouts/base.html" %}
|
||||||
|
{% block head %}
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css" />
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest"></script>
|
||||||
|
<style>
|
||||||
|
nav.datatable-pagination {
|
||||||
|
all: unset !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main %}
|
||||||
|
"""
|
||||||
|
|
||||||
doc, tag, text, line = Doc().ttl()
|
doc, tag, text, line = Doc().ttl()
|
||||||
|
|
||||||
doc.asis("<!DOCTYPE html>")
|
with tag("div", klass="container pt-3"):
|
||||||
with tag("html"):
|
|
||||||
with tag("head"):
|
line("a", "Back to photography", href="https://www.akpain.net/photography/")
|
||||||
line("title", "Film Development Price Comparison :: abi abi")
|
|
||||||
doc.stag("meta", charset="utf-8")
|
line("h1", "Film Development Price Comparison")
|
||||||
doc.stag("meta", name="viewport", content="width=device-width, initial-scale=1")
|
|
||||||
doc.stag(
|
line("p", "This is my attempt to work out the best value for money film developing and scanning service that's available in the UK. Labs are compared as like-for-like as possible, but some variation (especially in scan size) is inevitable.")
|
||||||
"link",
|
with tag("p"):
|
||||||
rel="stylesheet",
|
text("If your favourite/local/whatever lab isn't listed here, ")
|
||||||
href="https://www.akpain.net/assets/css/risotto.css",
|
line("a", "let me know", href="https://www.akpain.net#contact")
|
||||||
|
text(" and I'll add it! Likewise, if you want to see E6, ECN2, half frame, 120 or anything else here, please do tell me.")
|
||||||
|
|
||||||
|
with tag("p"):
|
||||||
|
text(
|
||||||
|
"Development costs last updated "
|
||||||
|
+ datetime.datetime.utcfromtimestamp(raw_data_object["time"]).strftime(
|
||||||
|
"%Y-%m-%d %H:%M:%S"
|
||||||
)
|
)
|
||||||
doc.stag(
|
+ ". Price per pixel figures do not include estimates for outbound or return shipping. "
|
||||||
"link",
|
|
||||||
rel="stylesheet",
|
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css",
|
|
||||||
)
|
)
|
||||||
doc.stag(
|
line("a", "Raw data available here", href="rawdata.json")
|
||||||
"link",
|
text(". ")
|
||||||
rel="stylesheet",
|
line("a", "Git repo", href="https://git.tdpain.net/codemicro/film-dev-cost-scraper")
|
||||||
href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css",
|
text(".")
|
||||||
|
|
||||||
|
|
||||||
|
with tag("div", klass="toc-container", style="width: 18rem;"):
|
||||||
|
with tag("div", klass="header"):
|
||||||
|
line("span", "On this page", klass="h4 font--monospace-bold")
|
||||||
|
with tag("div", klass="content"):
|
||||||
|
with tag("ul"):
|
||||||
|
for key in entries_by_type:
|
||||||
|
chemistry, format, subformat = key
|
||||||
|
slug = slugify(chemistry + format + subformat)
|
||||||
|
with tag("li"):
|
||||||
|
line("a", f"{chemistry} {format} ({subformat})", href=f"#{slug}-title")
|
||||||
|
|
||||||
|
slugs = []
|
||||||
|
|
||||||
|
for key in entries_by_type:
|
||||||
|
chemistry, format, subformat = key
|
||||||
|
|
||||||
|
slug = slugify(chemistry + format + subformat)
|
||||||
|
slugs.append(slug)
|
||||||
|
|
||||||
|
line(
|
||||||
|
"h2",
|
||||||
|
f"{chemistry} {format} ({subformat})",
|
||||||
|
id=slug + "-title",
|
||||||
)
|
)
|
||||||
with tag("script", src="https://cdn.jsdelivr.net/npm/simple-datatables@latest"):
|
|
||||||
doc.asis("")
|
|
||||||
|
|
||||||
with tag("body"):
|
if key in notes_by_type:
|
||||||
with tag("div", klass="container pt-3"):
|
line("p", notes_by_type[key])
|
||||||
|
|
||||||
line("a", "[abi abi] $", klass="pe-3", href="https://www.akpain.net")
|
cols = [
|
||||||
line("a", "back to photography", href="https://www.akpain.net/photography/")
|
("lab", lambda x: x["lab"]),
|
||||||
|
(
|
||||||
line("h1", "Film Development Price Comparison", klass="pt-2")
|
"outboundShipping",
|
||||||
|
lambda x: "×"
|
||||||
line("p", "This is my attempt to work out the best value for money film developing and scanning service that's available in the UK. Labs are compared as like-for-like as possible, but some variation (especially in scan size) is inevitable.")
|
if x["includesSendShipping"].lower() == "no"
|
||||||
with tag("p"):
|
else x["sendShippingType"],
|
||||||
text("If your favourite/local/whatever lab isn't listed here, ")
|
),
|
||||||
line("a", "let me know", href="https://www.akpain.net#contact")
|
(
|
||||||
text(" and I'll add it! Likewise, if you want to see E6, ECN2, half frame, 120 or anything else here, please do tell me.")
|
"returnShipping",
|
||||||
|
lambda x: (
|
||||||
with tag("p"):
|
"Free"
|
||||||
text(
|
if (c := float(x["returnShippingCost"])) == 0
|
||||||
"Development costs last updated "
|
else _format_price(c)
|
||||||
+ datetime.datetime.utcfromtimestamp(raw_data_object["time"]).strftime(
|
|
||||||
"%Y-%m-%d %H:%M:%S"
|
|
||||||
)
|
)
|
||||||
+ ". Price per pixel figures do not include estimates for outbound or return shipping. "
|
+ f" ({x['returnShippingType']})",
|
||||||
)
|
),
|
||||||
line("a", "Raw data available here", href="rawdata.json")
|
("cost", lambda x: _format_price(float(x["cost"]))),
|
||||||
text(". ")
|
(
|
||||||
line("a", "Git repo", href="https://git.tdpain.net/codemicro/film-dev-cost-scraper")
|
"renderResolution",
|
||||||
text(".")
|
lambda x: f"{x['resolution']} ({repr(x['resolutionName'])})",
|
||||||
|
),
|
||||||
|
(
|
||||||
with tag("div", klass="card", style="width: 18rem;"):
|
"pricePerPixel",
|
||||||
with tag("div", klass="card-body"):
|
lambda x: "{:.5f}p".format(
|
||||||
line("div", "Contents", klass="card-title", style="font-family: var(--font-monospace)")
|
float(x["cost"])
|
||||||
with tag("ul", klass="card-text"):
|
* 100
|
||||||
for key in entries_by_type:
|
/ reduce(
|
||||||
chemistry, format, subformat = key
|
lambda y, z: y * z,
|
||||||
slug = slugify(chemistry + format + subformat)
|
map(int, x["resolution"].split("x")),
|
||||||
with tag("li"):
|
1,
|
||||||
line("a", f"{chemistry} {format} ({subformat})", href=f"#{slug}-title")
|
|
||||||
|
|
||||||
slugs = []
|
|
||||||
|
|
||||||
for key in entries_by_type:
|
|
||||||
chemistry, format, subformat = key
|
|
||||||
|
|
||||||
slug = slugify(chemistry + format + subformat)
|
|
||||||
slugs.append(slug)
|
|
||||||
|
|
||||||
line(
|
|
||||||
"h2",
|
|
||||||
f"{chemistry} {format} ({subformat})",
|
|
||||||
klass="h3 pt-4",
|
|
||||||
id=slug + "-title",
|
|
||||||
)
|
|
||||||
|
|
||||||
if key in notes_by_type:
|
|
||||||
line("p", notes_by_type[key])
|
|
||||||
|
|
||||||
cols = [
|
|
||||||
("lab", lambda x: x["lab"]),
|
|
||||||
(
|
|
||||||
"outboundShipping",
|
|
||||||
lambda x: "×"
|
|
||||||
if x["includesSendShipping"].lower() == "no"
|
|
||||||
else x["sendShippingType"],
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"returnShipping",
|
|
||||||
lambda x: (
|
|
||||||
"Free"
|
|
||||||
if (c := float(x["returnShippingCost"])) == 0
|
|
||||||
else _format_price(c)
|
|
||||||
)
|
|
||||||
+ f" ({x['returnShippingType']})",
|
|
||||||
),
|
|
||||||
("cost", lambda x: _format_price(float(x["cost"]))),
|
|
||||||
(
|
|
||||||
"renderResolution",
|
|
||||||
lambda x: f"{x['resolution']} ({repr(x['resolutionName'])})",
|
|
||||||
),
|
|
||||||
(
|
|
||||||
"pricePerPixel",
|
|
||||||
lambda x: "{:.5f}p".format(
|
|
||||||
float(x["cost"])
|
|
||||||
* 100
|
|
||||||
/ reduce(
|
|
||||||
lambda y, z: y * z,
|
|
||||||
map(int, x["resolution"].split("x")),
|
|
||||||
1,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
("link", lambda x: _render_line("a", "Link", href=x["url"])),
|
|
||||||
]
|
|
||||||
|
|
||||||
# begin working out price per pixel colour scales
|
|
||||||
pppfn = None
|
|
||||||
for i, item in enumerate(cols):
|
|
||||||
if item[0] == "pricePerPixel":
|
|
||||||
pppfn = item[1]
|
|
||||||
break
|
|
||||||
assert pppfn is not None
|
|
||||||
pppcolours = {pppfn(data): "" for data in entries_by_type[key]}
|
|
||||||
coldiff = (
|
|
||||||
int(120 / (len(pppcolours) - 1)) if len(pppcolours) - 1 != 0 else 0
|
|
||||||
)
|
|
||||||
for i, (val, rawval) in enumerate(
|
|
||||||
sorted(
|
|
||||||
map(lambda x: (float(x[:-1]), x), pppcolours.keys()),
|
|
||||||
key=lambda y: y[0],
|
|
||||||
)
|
)
|
||||||
):
|
),
|
||||||
pppcolours[rawval] = f"hsl({120 - (i * coldiff)}, 71%, 73%)"
|
),
|
||||||
# end
|
("link", lambda x: _render_line("a", "Link", href=x["url"])),
|
||||||
|
]
|
||||||
|
|
||||||
with tag("table", klass="table table-hover", id=slug):
|
# begin working out price per pixel colour scales
|
||||||
with tag("thead"):
|
pppfn = None
|
||||||
with tag("tr"):
|
for i, item in enumerate(cols):
|
||||||
for t, _ in cols:
|
if item[0] == "pricePerPixel":
|
||||||
line("th", col_titles[t], scope="col")
|
pppfn = item[1]
|
||||||
|
break
|
||||||
with tag("tbody"):
|
assert pppfn is not None
|
||||||
for data in sorted(
|
pppcolours = {pppfn(data): "" for data in entries_by_type[key]}
|
||||||
entries_by_type[key], key=lambda x: x["lab"]
|
coldiff = (
|
||||||
):
|
int(120 / (len(pppcolours) - 1)) if len(pppcolours) - 1 != 0 else 0
|
||||||
with tag("tr"):
|
)
|
||||||
for i, (key, fn) in enumerate(cols):
|
for i, (val, rawval) in enumerate(
|
||||||
if i == 0:
|
sorted(
|
||||||
line("th", fn(data), scope="row")
|
map(lambda x: (float(x[:-1]), x), pppcolours.keys()),
|
||||||
else:
|
key=lambda y: y[0],
|
||||||
with tag("td"):
|
)
|
||||||
val = fn(data)
|
|
||||||
doc.asis(val)
|
|
||||||
|
|
||||||
if key == "pricePerPixel":
|
|
||||||
doc.attr(
|
|
||||||
style="background-color: "
|
|
||||||
+ pppcolours[val]
|
|
||||||
)
|
|
||||||
|
|
||||||
with tag("script"):
|
|
||||||
doc.asis("const slugs = ")
|
|
||||||
doc.asis(json.dumps(slugs))
|
|
||||||
doc.asis(";\n")
|
|
||||||
with open(Path(__file__).resolve().parent / "page.js") as f:
|
|
||||||
doc.asis(f.read())
|
|
||||||
|
|
||||||
with tag(
|
|
||||||
"script",
|
|
||||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js",
|
|
||||||
):
|
):
|
||||||
doc.asis()
|
pppcolours[rawval] = f"hsl({120 - (i * coldiff)}, 71%, 73%)"
|
||||||
|
# end
|
||||||
|
|
||||||
|
with tag("table", klass="table table-hover", id=slug):
|
||||||
|
with tag("thead"):
|
||||||
|
with tag("tr"):
|
||||||
|
for t, _ in cols:
|
||||||
|
line("th", col_titles[t], scope="col")
|
||||||
|
|
||||||
|
with tag("tbody"):
|
||||||
|
for data in sorted(
|
||||||
|
entries_by_type[key], key=lambda x: x["lab"]
|
||||||
|
):
|
||||||
|
with tag("tr"):
|
||||||
|
for i, (key, fn) in enumerate(cols):
|
||||||
|
if i == 0:
|
||||||
|
line("th", fn(data), scope="row")
|
||||||
|
else:
|
||||||
|
with tag("td"):
|
||||||
|
val = fn(data)
|
||||||
|
doc.asis(val)
|
||||||
|
|
||||||
|
if key == "pricePerPixel":
|
||||||
|
doc.attr(
|
||||||
|
style="background-color: "
|
||||||
|
+ pppcolours[val]
|
||||||
|
)
|
||||||
|
|
||||||
|
with tag("script"):
|
||||||
|
doc.asis("const slugs = ")
|
||||||
|
doc.asis(json.dumps(slugs))
|
||||||
|
doc.asis(";\n")
|
||||||
|
with open(Path(__file__).resolve().parent / "page.js") as f:
|
||||||
|
doc.asis(f.read())
|
||||||
|
|
||||||
|
with tag(
|
||||||
|
"script",
|
||||||
|
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js",
|
||||||
|
):
|
||||||
|
doc.asis()
|
||||||
|
|
||||||
|
acc += doc.getvalue()
|
||||||
|
acc += """
|
||||||
|
{% endblock %}"""
|
||||||
|
|
||||||
with open(OUTPUTFILE, "w") as f:
|
with open(OUTPUTFILE, "w") as f:
|
||||||
f.write(doc.getvalue())
|
f.write(acc)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue