summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinteck <contact@minteck.org>2023-01-02 20:29:01 +0100
committerMinteck <contact@minteck.org>2023-01-02 20:29:01 +0100
commite72d0adbcd7e69928a1ef380c7a841c160284c68 (patch)
tree1b9b9c29bb4fd39b6bdf577375bb91be3b9d6be1
parentc9de96328e59816ff4867abf5feab9fb9bf29511 (diff)
downloadpluralconnect-e72d0adbcd7e69928a1ef380c7a841c160284c68.tar.gz
pluralconnect-e72d0adbcd7e69928a1ef380c7a841c160284c68.tar.bz2
pluralconnect-e72d0adbcd7e69928a1ef380c7a841c160284c68.zip
Update
-rw-r--r--TODO.md19
-rw-r--r--api/desktop-app.php76
-rw-r--r--app.php6
-rw-r--r--app/fronters/profiles/auvwc.pngbin504733 -> 272775 bytes
-rw-r--r--app/fronters/profiles/bbrig.pngbin148262 -> 148246 bytes
-rw-r--r--app/fronters/profiles/ckqsw.pngbin1559833 -> 1559817 bytes
-rw-r--r--app/fronters/profiles/dogwu.pngbin2055 -> 2039 bytes
-rw-r--r--app/fronters/profiles/eebmh.pngbin570974 -> 570958 bytes
-rw-r--r--app/fronters/profiles/erefx.pngbin826530 -> 826514 bytes
-rw-r--r--app/fronters/profiles/erknz.pngbin56915 -> 56915 bytes
-rw-r--r--app/fronters/profiles/exudo.pngbin298183 -> 298167 bytes
-rw-r--r--app/fronters/profiles/fdaay.pngbin181311 -> 181295 bytes
-rw-r--r--app/fronters/profiles/gevde.pngbin218853 -> 218837 bytes
-rw-r--r--app/fronters/profiles/gfhsr.pngbin2283131 -> 2283131 bytes
-rw-r--r--app/fronters/profiles/ghrby.pngbin167497 -> 376305 bytes
-rw-r--r--app/fronters/profiles/hpwyq.pngbin2770 -> 2754 bytes
-rw-r--r--app/fronters/profiles/irxyh.pngbin26543 -> 26527 bytes
-rw-r--r--app/fronters/profiles/jjzcb.pngbin0 -> 299715 bytes
-rw-r--r--app/fronters/profiles/jnbae.pngbin60223 -> 60207 bytes
-rw-r--r--app/fronters/profiles/khsbb.pngbin249236 -> 249220 bytes
-rw-r--r--app/fronters/profiles/kkhbw.pngbin40300 -> 40284 bytes
-rw-r--r--app/fronters/profiles/lllfw.pngbin324334 -> 324269 bytes
-rw-r--r--app/fronters/profiles/lqolg.pngbin0 -> 13673 bytes
-rw-r--r--app/fronters/profiles/lzlaq.pngbin26543 -> 26527 bytes
-rw-r--r--app/fronters/profiles/mglyq.pngbin91476 -> 91460 bytes
-rw-r--r--app/fronters/profiles/mhnqy.pngbin27452 -> 27436 bytes
-rw-r--r--app/fronters/profiles/mvaws.pngbin473421 -> 473421 bytes
-rw-r--r--app/fronters/profiles/pabmo.pngbin180390 -> 180374 bytes
-rw-r--r--app/fronters/profiles/qbzxm.pngbin2843 -> 2827 bytes
-rw-r--r--app/fronters/profiles/qcemf.pngbin370856 -> 370840 bytes
-rw-r--r--app/fronters/profiles/qraku.pngbin45898 -> 45882 bytes
-rw-r--r--app/fronters/profiles/rdstg.pngbin16881 -> 16881 bytes
-rw-r--r--app/fronters/profiles/rirgf.pngbin156974 -> 156958 bytes
-rw-r--r--app/fronters/profiles/rpjok.pngbin1542918 -> 1542902 bytes
-rw-r--r--app/fronters/profiles/sbxze.pngbin50554 -> 50538 bytes
-rw-r--r--app/fronters/profiles/sehke.pngbin1947 -> 1931 bytes
-rw-r--r--app/fronters/profiles/sjuao.pngbin1045570 -> 1045570 bytes
-rw-r--r--app/fronters/profiles/tfbob.pngbin14049 -> 14033 bytes
-rw-r--r--app/fronters/profiles/ufadt.pngbin339704 -> 339688 bytes
-rw-r--r--app/fronters/profiles/umbyl.pngbin0 -> 574344 bytes
-rw-r--r--app/fronters/profiles/vncoa.pngbin46475 -> 46459 bytes
-rw-r--r--app/fronters/profiles/vvsxf.pngbin61010 -> 60994 bytes
-rw-r--r--app/fronters/profiles/xbvwt.pngbin70342 -> 70326 bytes
-rw-r--r--app/fronters/profiles/xcjhj.pngbin107053 -> 107037 bytes
-rw-r--r--app/fronters/profiles/yhbrc.pngbin494559 -> 494543 bytes
-rw-r--r--app/fronters/profiles/zajrk.pngbin2097 -> 2081 bytes
-rw-r--r--app/fronters/profiles/zdtsg.pngbin1628 -> 1612 bytes
-rw-r--r--app/fronters/profiles/zhtzs.pngbin673763 -> 673763 bytes
-rw-r--r--app/fronters/profiles/ztfjz.pngbin184686 -> 184670 bytes
-rw-r--r--app/fronters/profiles/zzise.pngbin69145 -> 69129 bytes
-rw-r--r--app/sw.js5
-rw-r--r--assets/logo/custom.css56
-rw-r--r--assets/uploads/pt-cinnamonfire.pngbin0 -> 4749 bytes
-rw-r--r--assets/uploads/pt-cozyglow.pngbin0 -> 6561 bytes
-rw-r--r--assets/uploads/pt-creamychocolate.pngbin0 -> 5227 bytes
-rw-r--r--includes/Parsedown.php1994
-rw-r--r--includes/banner.inc8
-rw-r--r--includes/bitset.inc65
-rw-r--r--includes/details.inc112
-rw-r--r--includes/footer.inc3
-rw-r--r--includes/fullbanner.inc63
-rw-r--r--includes/functions.inc13
-rw-r--r--includes/maintenance/clearUnused.php34
-rw-r--r--includes/member.inc66
-rw-r--r--includes/navigation.inc13
-rw-r--r--includes/pages.json13
-rw-r--r--includes/planner.inc132
-rw-r--r--includes/refresh.php22
-rw-r--r--includes/sysbanner.inc2
-rw-r--r--includes/system/species.inc4
-rw-r--r--pages/bitset.inc440
-rw-r--r--pages/page.inc4
-rw-r--r--pages/relations.inc10
-rw-r--r--pages/rules-old.inc253
-rw-r--r--pages/rules.inc251
-rw-r--r--pages/stats.inc226
-rw-r--r--spec.md253
77 files changed, 3114 insertions, 1029 deletions
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..a9c7970
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,19 @@
+# TODO
+
+- [ ] Make all pony heads the same size (square)
+- [ ] Add a "similar pages" section in the navigation bar
+
+----
+
+- [x] <s>Remove "Sensitivity" item</s>
+- [x] <s>Rename "Sexually active" to "Preemptive sexual consent"</s>
+- [x] <s>Add romantic/sexual alignments</s>
+ - [x] <s>Aromantic/asexual (default), straight, gay/lesbian (pick automatically depending on gender), bi, pan</s>
+ - [x] <s>Leave some bits for potentially more options</s>
+- [x] <s>Toggles for sexual polyamory, romantic polyamory, or both</s>
+- [x] <s>Actually remove deprecated values</s>
+- [x] <s>Allow caretakers for younger ponies (not just littles)</s>
+- [x] <s>Redesign the "systems rules" page</s>
+- [x] <s>Add Markdown support</s>
+- [x] <s>Redesign the bitset calculator</s>
+- [x] <s>Redesign the "front planner" page</s> \ No newline at end of file
diff --git a/api/desktop-app.php b/api/desktop-app.php
new file mode 100644
index 0000000..20b1da9
--- /dev/null
+++ b/api/desktop-app.php
@@ -0,0 +1,76 @@
+<?php
+
+require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/bitset.inc";
+
+if (!isset($_GET["id"])) die();
+
+if (isset($_GET["config"])) {
+ $data = [];
+
+ $keys = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/permitted.json"), true);
+ $proceed = false;
+
+ if (in_array($_GET["id"], array_keys($keys))) {
+ $proceed = true;
+ $fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $keys[$_GET["id"]]["system"] . "/fronters.json"), true)["members"];
+
+ if (count($fronters) > 0) {
+ $fronter = $fronters[0];
+ $info = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $fronter["id"] . ".json"), true);
+ $info = parseMetadata($info);
+
+ if (isset($info["birth"]["age"]) && $info["birth"]["age"] < 16 && $info["birth"]["age"] > 0) {
+ $proceed = false;
+ } else if (isset($info["birth"]["year"]) && $info["birth"]["year"] > 1900) {
+ if (!isset($info["birth"]["date"])) $info["birth"]["date"] = "01-01";
+
+ $age = (int)date('Y') - $info["birth"]["year"] + (strtotime(date('Y') . "-" . $info["birth"]["date"]) <= time() ? 0 : -1);
+
+ if ($age < 16) {
+ $proceed = false;
+ }
+ }
+ }
+ }
+
+ if ($proceed) {
+ $data = $keys[$_GET["id"]]["config"] ?? [];
+ }
+} else {
+ $data = [
+ "success" => true,
+ "valid" => false,
+ "underage" => false,
+ "normal" => false
+ ];
+
+ $keys = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/permitted.json"), true);
+
+ if (in_array($_GET["id"], array_keys($keys))) {
+ $data["valid"] = true;
+
+ $fronters = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . $keys[$_GET["id"]]["system"] . "/fronters.json"), true)["members"];
+
+ if (count($fronters) > 0) {
+ $fronter = $fronters[0];
+ $info = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $fronter["id"] . ".json"), true);
+ $info = parseMetadata($info);
+
+ $data["normal"] = $info["sexually_active"];
+
+ if (isset($info["birth"]["age"]) && $info["birth"]["age"] < 16 && $info["birth"]["age"] > 0) {
+ $data["underage"] = true;
+ } else if (isset($info["birth"]["year"]) && $info["birth"]["year"] > 1900) {
+ if (!isset($info["birth"]["date"])) $info["birth"]["date"] = "01-01";
+
+ $age = (int)date('Y') - $info["birth"]["year"] + (strtotime(date('Y') . "-" . $info["birth"]["date"]) <= time() ? 0 : -1);
+
+ if ($age < 16) {
+ $data["underage"] = true;
+ }
+ }
+ }
+ }
+}
+
+die(json_encode($data)); \ No newline at end of file
diff --git a/app.php b/app.php
index d4ed154..7bfbe29 100644
--- a/app.php
+++ b/app.php
@@ -18,6 +18,7 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) {
header("Location: /?error=" . $lang["app"]["file"]) and die();
}
} elseif ($toplevel === "") {
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/home.inc";
require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/home.inc";
} else {
if ($toplevel === "-") {
@@ -25,12 +26,14 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) {
$toplevel = explode("/", $pagename)[0];
if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc")) {
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc";
require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc";
} else {
header("Location: /?error=" . $lang["app"]["page"] . " " . strip_tags($pagename)) and die();
}
} else if ($toplevel === "api") {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc")) {
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc";
require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc";
}
} else if ($toplevel === "cloudburst" || $toplevel === "raindrops") {
@@ -50,6 +53,7 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) {
die();
}
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc";
require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc";
} else {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/pages/" . $toplevel . ".inc")) {
@@ -63,9 +67,11 @@ if (in_array($toplevel, ["editor", "icons", "species", "uploads"])) {
}, json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/gdapd/members.json"), true)), "unknown-rd"];
if ((in_array($toplevel, $namesCloudburst) || in_array($toplevel, $namesRaindrops)) && $toplevel !== "unknown") {
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc";
require_once $_SERVER['DOCUMENT_ROOT'] . "/pages/page.inc";
} else {
global $toplevel;
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . "/includes/short.inc";
require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/short.inc";
}
}
diff --git a/app/fronters/profiles/auvwc.png b/app/fronters/profiles/auvwc.png
index ac404f7..8eeb044 100644
--- a/app/fronters/profiles/auvwc.png
+++ b/app/fronters/profiles/auvwc.png
Binary files differ
diff --git a/app/fronters/profiles/bbrig.png b/app/fronters/profiles/bbrig.png
index 8dc8c32..138d98f 100644
--- a/app/fronters/profiles/bbrig.png
+++ b/app/fronters/profiles/bbrig.png
Binary files differ
diff --git a/app/fronters/profiles/ckqsw.png b/app/fronters/profiles/ckqsw.png
index 83acb02..b6aec17 100644
--- a/app/fronters/profiles/ckqsw.png
+++ b/app/fronters/profiles/ckqsw.png
Binary files differ
diff --git a/app/fronters/profiles/dogwu.png b/app/fronters/profiles/dogwu.png
index 60302f5..d0ad4cc 100644
--- a/app/fronters/profiles/dogwu.png
+++ b/app/fronters/profiles/dogwu.png
Binary files differ
diff --git a/app/fronters/profiles/eebmh.png b/app/fronters/profiles/eebmh.png
index 07cb4fc..b09a6c8 100644
--- a/app/fronters/profiles/eebmh.png
+++ b/app/fronters/profiles/eebmh.png
Binary files differ
diff --git a/app/fronters/profiles/erefx.png b/app/fronters/profiles/erefx.png
index 3c9be5f..0b908c1 100644
--- a/app/fronters/profiles/erefx.png
+++ b/app/fronters/profiles/erefx.png
Binary files differ
diff --git a/app/fronters/profiles/erknz.png b/app/fronters/profiles/erknz.png
index 96e6dc8..6b08bd7 100644
--- a/app/fronters/profiles/erknz.png
+++ b/app/fronters/profiles/erknz.png
Binary files differ
diff --git a/app/fronters/profiles/exudo.png b/app/fronters/profiles/exudo.png
index 9118868..0a90596 100644
--- a/app/fronters/profiles/exudo.png
+++ b/app/fronters/profiles/exudo.png
Binary files differ
diff --git a/app/fronters/profiles/fdaay.png b/app/fronters/profiles/fdaay.png
index 602a400..6631d16 100644
--- a/app/fronters/profiles/fdaay.png
+++ b/app/fronters/profiles/fdaay.png
Binary files differ
diff --git a/app/fronters/profiles/gevde.png b/app/fronters/profiles/gevde.png
index 11837f5..677e598 100644
--- a/app/fronters/profiles/gevde.png
+++ b/app/fronters/profiles/gevde.png
Binary files differ
diff --git a/app/fronters/profiles/gfhsr.png b/app/fronters/profiles/gfhsr.png
index b8a7eec..7132071 100644
--- a/app/fronters/profiles/gfhsr.png
+++ b/app/fronters/profiles/gfhsr.png
Binary files differ
diff --git a/app/fronters/profiles/ghrby.png b/app/fronters/profiles/ghrby.png
index 2e7fd08..b176521 100644
--- a/app/fronters/profiles/ghrby.png
+++ b/app/fronters/profiles/ghrby.png
Binary files differ
diff --git a/app/fronters/profiles/hpwyq.png b/app/fronters/profiles/hpwyq.png
index 6ad6c22..87b3078 100644
--- a/app/fronters/profiles/hpwyq.png
+++ b/app/fronters/profiles/hpwyq.png
Binary files differ
diff --git a/app/fronters/profiles/irxyh.png b/app/fronters/profiles/irxyh.png
index cee8265..a77bec6 100644
--- a/app/fronters/profiles/irxyh.png
+++ b/app/fronters/profiles/irxyh.png
Binary files differ
diff --git a/app/fronters/profiles/jjzcb.png b/app/fronters/profiles/jjzcb.png
new file mode 100644
index 0000000..0800abb
--- /dev/null
+++ b/app/fronters/profiles/jjzcb.png
Binary files differ
diff --git a/app/fronters/profiles/jnbae.png b/app/fronters/profiles/jnbae.png
index a7e8a6e..dc71f43 100644
--- a/app/fronters/profiles/jnbae.png
+++ b/app/fronters/profiles/jnbae.png
Binary files differ
diff --git a/app/fronters/profiles/khsbb.png b/app/fronters/profiles/khsbb.png
index d7a0595..34998de 100644
--- a/app/fronters/profiles/khsbb.png
+++ b/app/fronters/profiles/khsbb.png
Binary files differ
diff --git a/app/fronters/profiles/kkhbw.png b/app/fronters/profiles/kkhbw.png
index e943fa5..c461040 100644
--- a/app/fronters/profiles/kkhbw.png
+++ b/app/fronters/profiles/kkhbw.png
Binary files differ
diff --git a/app/fronters/profiles/lllfw.png b/app/fronters/profiles/lllfw.png
index 64fe05d..98526b2 100644
--- a/app/fronters/profiles/lllfw.png
+++ b/app/fronters/profiles/lllfw.png
Binary files differ
diff --git a/app/fronters/profiles/lqolg.png b/app/fronters/profiles/lqolg.png
new file mode 100644
index 0000000..beace78
--- /dev/null
+++ b/app/fronters/profiles/lqolg.png
Binary files differ
diff --git a/app/fronters/profiles/lzlaq.png b/app/fronters/profiles/lzlaq.png
index 98846f5..01ccf00 100644
--- a/app/fronters/profiles/lzlaq.png
+++ b/app/fronters/profiles/lzlaq.png
Binary files differ
diff --git a/app/fronters/profiles/mglyq.png b/app/fronters/profiles/mglyq.png
index 52c60f4..17b3156 100644
--- a/app/fronters/profiles/mglyq.png
+++ b/app/fronters/profiles/mglyq.png
Binary files differ
diff --git a/app/fronters/profiles/mhnqy.png b/app/fronters/profiles/mhnqy.png
index c3e1d43..7966132 100644
--- a/app/fronters/profiles/mhnqy.png
+++ b/app/fronters/profiles/mhnqy.png
Binary files differ
diff --git a/app/fronters/profiles/mvaws.png b/app/fronters/profiles/mvaws.png
index 3d152a9..ae45fef 100644
--- a/app/fronters/profiles/mvaws.png
+++ b/app/fronters/profiles/mvaws.png
Binary files differ
diff --git a/app/fronters/profiles/pabmo.png b/app/fronters/profiles/pabmo.png
index 7f8f020..117a75f 100644
--- a/app/fronters/profiles/pabmo.png
+++ b/app/fronters/profiles/pabmo.png
Binary files differ
diff --git a/app/fronters/profiles/qbzxm.png b/app/fronters/profiles/qbzxm.png
index 3679f54..e2848ad 100644
--- a/app/fronters/profiles/qbzxm.png
+++ b/app/fronters/profiles/qbzxm.png
Binary files differ
diff --git a/app/fronters/profiles/qcemf.png b/app/fronters/profiles/qcemf.png
index 609d535..debf1a7 100644
--- a/app/fronters/profiles/qcemf.png
+++ b/app/fronters/profiles/qcemf.png
Binary files differ
diff --git a/app/fronters/profiles/qraku.png b/app/fronters/profiles/qraku.png
index 10858a6..50d25b5 100644
--- a/app/fronters/profiles/qraku.png
+++ b/app/fronters/profiles/qraku.png
Binary files differ
diff --git a/app/fronters/profiles/rdstg.png b/app/fronters/profiles/rdstg.png
index 2fbc54c..e1f15af 100644
--- a/app/fronters/profiles/rdstg.png
+++ b/app/fronters/profiles/rdstg.png
Binary files differ
diff --git a/app/fronters/profiles/rirgf.png b/app/fronters/profiles/rirgf.png
index 152c8e2..36a45d6 100644
--- a/app/fronters/profiles/rirgf.png
+++ b/app/fronters/profiles/rirgf.png
Binary files differ
diff --git a/app/fronters/profiles/rpjok.png b/app/fronters/profiles/rpjok.png
index c38ba39..950a4fa 100644
--- a/app/fronters/profiles/rpjok.png
+++ b/app/fronters/profiles/rpjok.png
Binary files differ
diff --git a/app/fronters/profiles/sbxze.png b/app/fronters/profiles/sbxze.png
index 2744fff..6d7b24a 100644
--- a/app/fronters/profiles/sbxze.png
+++ b/app/fronters/profiles/sbxze.png
Binary files differ
diff --git a/app/fronters/profiles/sehke.png b/app/fronters/profiles/sehke.png
index 0e6f956..0d2c424 100644
--- a/app/fronters/profiles/sehke.png
+++ b/app/fronters/profiles/sehke.png
Binary files differ
diff --git a/app/fronters/profiles/sjuao.png b/app/fronters/profiles/sjuao.png
index 12f5b33..b19ce07 100644
--- a/app/fronters/profiles/sjuao.png
+++ b/app/fronters/profiles/sjuao.png
Binary files differ
diff --git a/app/fronters/profiles/tfbob.png b/app/fronters/profiles/tfbob.png
index 4cc390a..ea78bea 100644
--- a/app/fronters/profiles/tfbob.png
+++ b/app/fronters/profiles/tfbob.png
Binary files differ
diff --git a/app/fronters/profiles/ufadt.png b/app/fronters/profiles/ufadt.png
index 4af6c47..b0a09a8 100644
--- a/app/fronters/profiles/ufadt.png
+++ b/app/fronters/profiles/ufadt.png
Binary files differ
diff --git a/app/fronters/profiles/umbyl.png b/app/fronters/profiles/umbyl.png
new file mode 100644
index 0000000..119321c
--- /dev/null
+++ b/app/fronters/profiles/umbyl.png
Binary files differ
diff --git a/app/fronters/profiles/vncoa.png b/app/fronters/profiles/vncoa.png
index 9636278..bdf4e80 100644
--- a/app/fronters/profiles/vncoa.png
+++ b/app/fronters/profiles/vncoa.png
Binary files differ
diff --git a/app/fronters/profiles/vvsxf.png b/app/fronters/profiles/vvsxf.png
index 74f542e..95a1b4b 100644
--- a/app/fronters/profiles/vvsxf.png
+++ b/app/fronters/profiles/vvsxf.png
Binary files differ
diff --git a/app/fronters/profiles/xbvwt.png b/app/fronters/profiles/xbvwt.png
index 4b6c8d3..f8fb01a 100644
--- a/app/fronters/profiles/xbvwt.png
+++ b/app/fronters/profiles/xbvwt.png
Binary files differ
diff --git a/app/fronters/profiles/xcjhj.png b/app/fronters/profiles/xcjhj.png
index 4ab828d..ada7641 100644
--- a/app/fronters/profiles/xcjhj.png
+++ b/app/fronters/profiles/xcjhj.png
Binary files differ
diff --git a/app/fronters/profiles/yhbrc.png b/app/fronters/profiles/yhbrc.png
index 8b07487..e7949d1 100644
--- a/app/fronters/profiles/yhbrc.png
+++ b/app/fronters/profiles/yhbrc.png
Binary files differ
diff --git a/app/fronters/profiles/zajrk.png b/app/fronters/profiles/zajrk.png
index e6cfa68..6ab4b18 100644
--- a/app/fronters/profiles/zajrk.png
+++ b/app/fronters/profiles/zajrk.png
Binary files differ
diff --git a/app/fronters/profiles/zdtsg.png b/app/fronters/profiles/zdtsg.png
index 6ec0b3c..2e62832 100644
--- a/app/fronters/profiles/zdtsg.png
+++ b/app/fronters/profiles/zdtsg.png
Binary files differ
diff --git a/app/fronters/profiles/zhtzs.png b/app/fronters/profiles/zhtzs.png
index b65fd37..a5aee05 100644
--- a/app/fronters/profiles/zhtzs.png
+++ b/app/fronters/profiles/zhtzs.png
Binary files differ
diff --git a/app/fronters/profiles/ztfjz.png b/app/fronters/profiles/ztfjz.png
index 7765304..0308b63 100644
--- a/app/fronters/profiles/ztfjz.png
+++ b/app/fronters/profiles/ztfjz.png
Binary files differ
diff --git a/app/fronters/profiles/zzise.png b/app/fronters/profiles/zzise.png
index 76b1996..46ad36e 100644
--- a/app/fronters/profiles/zzise.png
+++ b/app/fronters/profiles/zzise.png
Binary files differ
diff --git a/app/sw.js b/app/sw.js
index e002932..5a17da4 100644
--- a/app/sw.js
+++ b/app/sw.js
@@ -127,6 +127,7 @@ let filesToCache = [
"/app/fronters/profiles/hpwyq.png",
"/app/fronters/profiles/irxyh.png",
"/app/fronters/profiles/jhemc.png",
+ "/app/fronters/profiles/jjzcb.png",
"/app/fronters/profiles/jlpjf.png",
"/app/fronters/profiles/jmasq.png",
"/app/fronters/profiles/jnbae.png",
@@ -137,6 +138,7 @@ let filesToCache = [
"/app/fronters/profiles/kzfjn.png",
"/app/fronters/profiles/lllfw.png",
"/app/fronters/profiles/lqahp.png",
+ "/app/fronters/profiles/lqolg.png",
"/app/fronters/profiles/lyotd.png",
"/app/fronters/profiles/lzlaq.png",
"/app/fronters/profiles/mglyq.png",
@@ -179,6 +181,7 @@ let filesToCache = [
"/app/fronters/profiles/ughya.png",
"/app/fronters/profiles/uhfic.png",
"/app/fronters/profiles/uicxr.png",
+ "/app/fronters/profiles/umbyl.png",
"/app/fronters/profiles/vahcl.png",
"/app/fronters/profiles/vaxyy.png",
"/app/fronters/profiles/vncoa.png",
@@ -230,8 +233,10 @@ let filesToCache = [
"/assets/uploads/pt-applebloom.png",
"/assets/uploads/pt-babsseed.png",
"/assets/uploads/pt-blueberrycloud.png",
+ "/assets/uploads/pt-cinnamonfire.png",
"/assets/uploads/pt-cloudydreams.png",
"/assets/uploads/pt-coral.png",
+ "/assets/uploads/pt-cozyglow.png",
"/assets/uploads/pt-dahlia.png",
"/assets/uploads/pt-duskrainbow.png",
"/assets/uploads/pt-floralorchid.png",
diff --git a/assets/logo/custom.css b/assets/logo/custom.css
index 76ad1d5..11f29f9 100644
--- a/assets/logo/custom.css
+++ b/assets/logo/custom.css
@@ -119,15 +119,15 @@ body {
}
.dropdown-menu {
- background-color: #222;
+ background-color: #222 !important;
}
.dropdown-item:hover {
- background-color: rgba(255, 255, 255, .1);
+ background-color: rgba(255, 255, 255, .1) !important;
}
.dropdown-item:active, .dropdown-item:focus {
- background-color: rgba(255, 255, 255, .2);
+ background-color: rgba(255, 255, 255, .2) !important;
}
.dropdown-item {
@@ -135,16 +135,16 @@ body {
}
.dropdown-icon {
- filter: invert(1);
+ filter: invert(1) !important;
}
.dropdown-toggle .dropdown-icon {
- opacity: .5;
- transition: 200ms opacity;
+ opacity: .5; !important;
+ transition: 200ms opacity !important;
}
.dropdown-toggle:hover .dropdown-icon, .dropdown-toggle:active .dropdown-icon, .dropdown-toggle:focus .dropdown-icon {
- opacity: .75;
+ opacity: .75 !important;
}
dd {
@@ -596,7 +596,7 @@ peh-muted {
}
.dropdown-toggle::after {
- margin-bottom: -3px;
+ margin-bottom: -3px !important;
}
.navbar-nav {
@@ -621,10 +621,27 @@ peh-muted {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
display: grid;
- grid-template-columns: repeat(6, 1fr);
+ grid-template-columns: repeat(5, 1fr);
text-align: center;
}
+#member-details.member-details-loggedIn {
+ border-radius: 0;
+ padding-bottom: 0 !important;
+}
+
+#member-details-2 {
+ border-bottom-left-radius: 10px;
+ border-bottom-right-radius: 10px;
+ padding: 10px 20px;
+ text-align: center;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ background: rgba(255, 255, 255, .1);
+ border: 1px solid transparent;
+ border-top: none;
+}
+
.navbar-collapse.show {
z-index: 99999;
}
@@ -646,6 +663,27 @@ peh-muted {
grid-template-columns: repeat(2, 1fr) !important;
text-align: left;
}
+
+ #member-details-2 {
+ grid-template-columns: repeat(2, 1fr) !important;
+ text-align: left;
+ }
+
+ .member-detail-desktop {
+ display: none !important;
+ }
+
+ .member-detail-mobile {
+ display: initial !important;
+ }
+}
+
+.member-detail-desktop {
+ display: initial;
+}
+
+.member-detail-mobile {
+ display: none;
}
.linked-card {
diff --git a/assets/uploads/pt-cinnamonfire.png b/assets/uploads/pt-cinnamonfire.png
new file mode 100644
index 0000000..c23c1ad
--- /dev/null
+++ b/assets/uploads/pt-cinnamonfire.png
Binary files differ
diff --git a/assets/uploads/pt-cozyglow.png b/assets/uploads/pt-cozyglow.png
new file mode 100644
index 0000000..4f65ee9
--- /dev/null
+++ b/assets/uploads/pt-cozyglow.png
Binary files differ
diff --git a/assets/uploads/pt-creamychocolate.png b/assets/uploads/pt-creamychocolate.png
new file mode 100644
index 0000000..1cb2699
--- /dev/null
+++ b/assets/uploads/pt-creamychocolate.png
Binary files differ
diff --git a/includes/Parsedown.php b/includes/Parsedown.php
new file mode 100644
index 0000000..3e29589
--- /dev/null
+++ b/includes/Parsedown.php
@@ -0,0 +1,1994 @@
+<?php
+
+#
+#
+# Parsedown
+# http://parsedown.org
+#
+# (c) Emanuil Rusev
+# http://erusev.com
+#
+# For the full license information, view the LICENSE file that was distributed
+# with this source code.
+#
+#
+
+class Parsedown
+{
+ # ~
+
+ const version = '1.8.0-beta-7';
+
+ # ~
+
+ function text($text)
+ {
+ $Elements = $this->textElements($text);
+
+ # convert to markup
+ $markup = $this->elements($Elements);
+
+ # trim line breaks
+ $markup = trim($markup, "\n");
+
+ return $markup;
+ }
+
+ protected function textElements($text)
+ {
+ # make sure no definitions are set
+ $this->DefinitionData = array();
+
+ # standardize line breaks
+ $text = str_replace(array("\r\n", "\r"), "\n", $text);
+
+ # remove surrounding line breaks
+ $text = trim($text, "\n");
+
+ # split text into lines
+ $lines = explode("\n", $text);
+
+ # iterate through lines to identify blocks
+ return $this->linesElements($lines);
+ }
+
+ #
+ # Setters
+ #
+
+ function setBreaksEnabled($breaksEnabled)
+ {
+ $this->breaksEnabled = $breaksEnabled;
+
+ return $this;
+ }
+
+ protected $breaksEnabled;
+
+ function setMarkupEscaped($markupEscaped)
+ {
+ $this->markupEscaped = $markupEscaped;
+
+ return $this;
+ }
+
+ protected $markupEscaped;
+
+ function setUrlsLinked($urlsLinked)
+ {
+ $this->urlsLinked = $urlsLinked;
+
+ return $this;
+ }
+
+ protected $urlsLinked = true;
+
+ function setSafeMode($safeMode)
+ {
+ $this->safeMode = (bool) $safeMode;
+
+ return $this;
+ }
+
+ protected $safeMode;
+
+ function setStrictMode($strictMode)
+ {
+ $this->strictMode = (bool) $strictMode;
+
+ return $this;
+ }
+
+ protected $strictMode;
+
+ protected $safeLinksWhitelist = array(
+ 'http://',
+ 'https://',
+ 'ftp://',
+ 'ftps://',
+ 'mailto:',
+ 'tel:',
+ 'data:image/png;base64,',
+ 'data:image/gif;base64,',
+ 'data:image/jpeg;base64,',
+ 'irc:',
+ 'ircs:',
+ 'git:',
+ 'ssh:',
+ 'news:',
+ 'steam:',
+ );
+
+ #
+ # Lines
+ #
+
+ protected $BlockTypes = array(
+ '#' => array('Header'),
+ '*' => array('Rule', 'List'),
+ '+' => array('List'),
+ '-' => array('SetextHeader', 'Table', 'Rule', 'List'),
+ '0' => array('List'),
+ '1' => array('List'),
+ '2' => array('List'),
+ '3' => array('List'),
+ '4' => array('List'),
+ '5' => array('List'),
+ '6' => array('List'),
+ '7' => array('List'),
+ '8' => array('List'),
+ '9' => array('List'),
+ ':' => array('Table'),
+ '<' => array('Comment', 'Markup'),
+ '=' => array('SetextHeader'),
+ '>' => array('Quote'),
+ '[' => array('Reference'),
+ '_' => array('Rule'),
+ '`' => array('FencedCode'),
+ '|' => array('Table'),
+ '~' => array('FencedCode'),
+ );
+
+ # ~
+
+ protected $unmarkedBlockTypes = array(
+ 'Code',
+ );
+
+ #
+ # Blocks
+ #
+
+ protected function lines(array $lines)
+ {
+ return $this->elements($this->linesElements($lines));
+ }
+
+ protected function linesElements(array $lines)
+ {
+ $Elements = array();
+ $CurrentBlock = null;
+
+ foreach ($lines as $line)
+ {
+ if (chop($line) === '')
+ {
+ if (isset($CurrentBlock))
+ {
+ $CurrentBlock['interrupted'] = (isset($CurrentBlock['interrupted'])
+ ? $CurrentBlock['interrupted'] + 1 : 1
+ );
+ }
+
+ continue;
+ }
+
+ while (($beforeTab = strstr($line, "\t", true)) !== false)
+ {
+ $shortage = 4 - mb_strlen($beforeTab, 'utf-8') % 4;
+
+ $line = $beforeTab
+ . str_repeat(' ', $shortage)
+ . substr($line, strlen($beforeTab) + 1)
+ ;
+ }
+
+ $indent = strspn($line, ' ');
+
+ $text = $indent > 0 ? substr($line, $indent) : $line;
+
+ # ~
+
+ $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
+
+ # ~
+
+ if (isset($CurrentBlock['continuable']))
+ {
+ $methodName = 'block' . $CurrentBlock['type'] . 'Continue';
+ $Block = $this->$methodName($Line, $CurrentBlock);
+
+ if (isset($Block))
+ {
+ $CurrentBlock = $Block;
+
+ continue;
+ }
+ else
+ {
+ if ($this->isBlockCompletable($CurrentBlock['type']))
+ {
+ $methodName = 'block' . $CurrentBlock['type'] . 'Complete';
+ $CurrentBlock = $this->$methodName($CurrentBlock);
+ }
+ }
+ }
+
+ # ~
+
+ $marker = $text[0];
+
+ # ~
+
+ $blockTypes = $this->unmarkedBlockTypes;
+
+ if (isset($this->BlockTypes[$marker]))
+ {
+ foreach ($this->BlockTypes[$marker] as $blockType)
+ {
+ $blockTypes []= $blockType;
+ }
+ }
+
+ #
+ # ~
+
+ foreach ($blockTypes as $blockType)
+ {
+ $Block = $this->{"block$blockType"}($Line, $CurrentBlock);
+
+ if (isset($Block))
+ {
+ $Block['type'] = $blockType;
+
+ if ( ! isset($Block['identified']))
+ {
+ if (isset($CurrentBlock))
+ {
+ $Elements[] = $this->extractElement($CurrentBlock);
+ }
+
+ $Block['identified'] = true;
+ }
+
+ if ($this->isBlockContinuable($blockType))
+ {
+ $Block['continuable'] = true;
+ }
+
+ $CurrentBlock = $Block;
+
+ continue 2;
+ }
+ }
+
+ # ~
+
+ if (isset($CurrentBlock) and $CurrentBlock['type'] === 'Paragraph')
+ {
+ $Block = $this->paragraphContinue($Line, $CurrentBlock);
+ }
+
+ if (isset($Block))
+ {
+ $CurrentBlock = $Block;
+ }
+ else
+ {
+ if (isset($CurrentBlock))
+ {
+ $Elements[] = $this->extractElement($CurrentBlock);
+ }
+
+ $CurrentBlock = $this->paragraph($Line);
+
+ $CurrentBlock['identified'] = true;
+ }
+ }
+
+ # ~
+
+ if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))
+ {
+ $methodName = 'block' . $CurrentBlock['type'] . 'Complete';
+ $CurrentBlock = $this->$methodName($CurrentBlock);
+ }
+
+ # ~
+
+ if (isset($CurrentBlock))
+ {
+ $Elements[] = $this->extractElement($CurrentBlock);
+ }
+
+ # ~
+
+ return $Elements;
+ }
+
+ protected function extractElement(array $Component)
+ {
+ if ( ! isset($Component['element']))
+ {
+ if (isset($Component['markup']))
+ {
+ $Component['element'] = array('rawHtml' => $Component['markup']);
+ }
+ elseif (isset($Component['hidden']))
+ {
+ $Component['element'] = array();
+ }
+ }
+
+ return $Component['element'];
+ }
+
+ protected function isBlockContinuable($Type)
+ {
+ return method_exists($this, 'block' . $Type . 'Continue');
+ }
+
+ protected function isBlockCompletable($Type)
+ {
+ return method_exists($this, 'block' . $Type . 'Complete');
+ }
+
+ #
+ # Code
+
+ protected function blockCode($Line, $Block = null)
+ {
+ if (isset($Block) and $Block['type'] === 'Paragraph' and ! isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if ($Line['indent'] >= 4)
+ {
+ $text = substr($Line['body'], 4);
+
+ $Block = array(
+ 'element' => array(
+ 'name' => 'pre',
+ 'element' => array(
+ 'name' => 'code',
+ 'text' => $text,
+ ),
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockCodeContinue($Line, $Block)
+ {
+ if ($Line['indent'] >= 4)
+ {
+ if (isset($Block['interrupted']))
+ {
+ $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']);
+
+ unset($Block['interrupted']);
+ }
+
+ $Block['element']['element']['text'] .= "\n";
+
+ $text = substr($Line['body'], 4);
+
+ $Block['element']['element']['text'] .= $text;
+
+ return $Block;
+ }
+ }
+
+ protected function blockCodeComplete($Block)
+ {
+ return $Block;
+ }
+
+ #
+ # Comment
+
+ protected function blockComment($Line)
+ {
+ if ($this->markupEscaped or $this->safeMode)
+ {
+ return;
+ }
+
+ if (strpos($Line['text'], '<!--') === 0)
+ {
+ $Block = array(
+ 'element' => array(
+ 'rawHtml' => $Line['body'],
+ 'autobreak' => true,
+ ),
+ );
+
+ if (strpos($Line['text'], '-->') !== false)
+ {
+ $Block['closed'] = true;
+ }
+
+ return $Block;
+ }
+ }
+
+ protected function blockCommentContinue($Line, array $Block)
+ {
+ if (isset($Block['closed']))
+ {
+ return;
+ }
+
+ $Block['element']['rawHtml'] .= "\n" . $Line['body'];
+
+ if (strpos($Line['text'], '-->') !== false)
+ {
+ $Block['closed'] = true;
+ }
+
+ return $Block;
+ }
+
+ #
+ # Fenced Code
+
+ protected function blockFencedCode($Line)
+ {
+ $marker = $Line['text'][0];
+
+ $openerLength = strspn($Line['text'], $marker);
+
+ if ($openerLength < 3)
+ {
+ return;
+ }
+
+ $infostring = trim(substr($Line['text'], $openerLength), "\t ");
+
+ if (strpos($infostring, '`') !== false)
+ {
+ return;
+ }
+
+ $Element = array(
+ 'name' => 'code',
+ 'text' => '',
+ );
+
+ if ($infostring !== '')
+ {
+ /**
+ * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes
+ * Every HTML element may have a class attribute specified.
+ * The attribute, if specified, must have a value that is a set
+ * of space-separated tokens representing the various classes
+ * that the element belongs to.
+ * [...]
+ * The space characters, for the purposes of this specification,
+ * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
+ * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and
+ * U+000D CARRIAGE RETURN (CR).
+ */
+ $language = substr($infostring, 0, strcspn($infostring, " \t\n\f\r"));
+
+ $Element['attributes'] = array('class' => "language-$language");
+ }
+
+ $Block = array(
+ 'char' => $marker,
+ 'openerLength' => $openerLength,
+ 'element' => array(
+ 'name' => 'pre',
+ 'element' => $Element,
+ ),
+ );
+
+ return $Block;
+ }
+
+ protected function blockFencedCodeContinue($Line, $Block)
+ {
+ if (isset($Block['complete']))
+ {
+ return;
+ }
+
+ if (isset($Block['interrupted']))
+ {
+ $Block['element']['element']['text'] .= str_repeat("\n", $Block['interrupted']);
+
+ unset($Block['interrupted']);
+ }
+
+ if (($len = strspn($Line['text'], $Block['char'])) >= $Block['openerLength']
+ and chop(substr($Line['text'], $len), ' ') === ''
+ ) {
+ $Block['element']['element']['text'] = substr($Block['element']['element']['text'], 1);
+
+ $Block['complete'] = true;
+
+ return $Block;
+ }
+
+ $Block['element']['element']['text'] .= "\n" . $Line['body'];
+
+ return $Block;
+ }
+
+ protected function blockFencedCodeComplete($Block)
+ {
+ return $Block;
+ }
+
+ #
+ # Header
+
+ protected function blockHeader($Line)
+ {
+ $level = strspn($Line['text'], '#');
+
+ if ($level > 6)
+ {
+ return;
+ }
+
+ $text = trim($Line['text'], '#');
+
+ if ($this->strictMode and isset($text[0]) and $text[0] !== ' ')
+ {
+ return;
+ }
+
+ $text = trim($text, ' ');
+
+ $Block = array(
+ 'element' => array(
+ 'name' => 'h' . $level,
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => $text,
+ 'destination' => 'elements',
+ )
+ ),
+ );
+
+ return $Block;
+ }
+
+ #
+ # List
+
+ protected function blockList($Line, array $CurrentBlock = null)
+ {
+ list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]{1,9}+[.\)]');
+
+ if (preg_match('/^('.$pattern.'([ ]++|$))(.*+)/', $Line['text'], $matches))
+ {
+ $contentIndent = strlen($matches[2]);
+
+ if ($contentIndent >= 5)
+ {
+ $contentIndent -= 1;
+ $matches[1] = substr($matches[1], 0, -$contentIndent);
+ $matches[3] = str_repeat(' ', $contentIndent) . $matches[3];
+ }
+ elseif ($contentIndent === 0)
+ {
+ $matches[1] .= ' ';
+ }
+
+ $markerWithoutWhitespace = strstr($matches[1], ' ', true);
+
+ $Block = array(
+ 'indent' => $Line['indent'],
+ 'pattern' => $pattern,
+ 'data' => array(
+ 'type' => $name,
+ 'marker' => $matches[1],
+ 'markerType' => ($name === 'ul' ? $markerWithoutWhitespace : substr($markerWithoutWhitespace, -1)),
+ ),
+ 'element' => array(
+ 'name' => $name,
+ 'elements' => array(),
+ ),
+ );
+ $Block['data']['markerTypeRegex'] = preg_quote($Block['data']['markerType'], '/');
+
+ if ($name === 'ol')
+ {
+ $listStart = ltrim(strstr($matches[1], $Block['data']['markerType'], true), '0') ?: '0';
+
+ if ($listStart !== '1')
+ {
+ if (
+ isset($CurrentBlock)
+ and $CurrentBlock['type'] === 'Paragraph'
+ and ! isset($CurrentBlock['interrupted'])
+ ) {
+ return;
+ }
+
+ $Block['element']['attributes'] = array('start' => $listStart);
+ }
+ }
+
+ $Block['li'] = array(
+ 'name' => 'li',
+ 'handler' => array(
+ 'function' => 'li',
+ 'argument' => !empty($matches[3]) ? array($matches[3]) : array(),
+ 'destination' => 'elements'
+ )
+ );
+
+ $Block['element']['elements'] []= & $Block['li'];
+
+ return $Block;
+ }
+ }
+
+ protected function blockListContinue($Line, array $Block)
+ {
+ if (isset($Block['interrupted']) and empty($Block['li']['handler']['argument']))
+ {
+ return null;
+ }
+
+ $requiredIndent = ($Block['indent'] + strlen($Block['data']['marker']));
+
+ if ($Line['indent'] < $requiredIndent
+ and (
+ (
+ $Block['data']['type'] === 'ol'
+ and preg_match('/^[0-9]++'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches)
+ ) or (
+ $Block['data']['type'] === 'ul'
+ and preg_match('/^'.$Block['data']['markerTypeRegex'].'(?:[ ]++(.*)|$)/', $Line['text'], $matches)
+ )
+ )
+ ) {
+ if (isset($Block['interrupted']))
+ {
+ $Block['li']['handler']['argument'] []= '';
+
+ $Block['loose'] = true;
+
+ unset($Block['interrupted']);
+ }
+
+ unset($Block['li']);
+
+ $text = isset($matches[1]) ? $matches[1] : '';
+
+ $Block['indent'] = $Line['indent'];
+
+ $Block['li'] = array(
+ 'name' => 'li',
+ 'handler' => array(
+ 'function' => 'li',
+ 'argument' => array($text),
+ 'destination' => 'elements'
+ )
+ );
+
+ $Block['element']['elements'] []= & $Block['li'];
+
+ return $Block;
+ }
+ elseif ($Line['indent'] < $requiredIndent and $this->blockList($Line))
+ {
+ return null;
+ }
+
+ if ($Line['text'][0] === '[' and $this->blockReference($Line))
+ {
+ return $Block;
+ }
+
+ if ($Line['indent'] >= $requiredIndent)
+ {
+ if (isset($Block['interrupted']))
+ {
+ $Block['li']['handler']['argument'] []= '';
+
+ $Block['loose'] = true;
+
+ unset($Block['interrupted']);
+ }
+
+ $text = substr($Line['body'], $requiredIndent);
+
+ $Block['li']['handler']['argument'] []= $text;
+
+ return $Block;
+ }
+
+ if ( ! isset($Block['interrupted']))
+ {
+ $text = preg_replace('/^[ ]{0,'.$requiredIndent.'}+/', '', $Line['body']);
+
+ $Block['li']['handler']['argument'] []= $text;
+
+ return $Block;
+ }
+ }
+
+ protected function blockListComplete(array $Block)
+ {
+ if (isset($Block['loose']))
+ {
+ foreach ($Block['element']['elements'] as &$li)
+ {
+ if (end($li['handler']['argument']) !== '')
+ {
+ $li['handler']['argument'] []= '';
+ }
+ }
+ }
+
+ return $Block;
+ }
+
+ #
+ # Quote
+
+ protected function blockQuote($Line)
+ {
+ if (preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches))
+ {
+ $Block = array(
+ 'element' => array(
+ 'name' => 'blockquote',
+ 'handler' => array(
+ 'function' => 'linesElements',
+ 'argument' => (array) $matches[1],
+ 'destination' => 'elements',
+ )
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockQuoteContinue($Line, array $Block)
+ {
+ if (isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if ($Line['text'][0] === '>' and preg_match('/^>[ ]?+(.*+)/', $Line['text'], $matches))
+ {
+ $Block['element']['handler']['argument'] []= $matches[1];
+
+ return $Block;
+ }
+
+ if ( ! isset($Block['interrupted']))
+ {
+ $Block['element']['handler']['argument'] []= $Line['text'];
+
+ return $Block;
+ }
+ }
+
+ #
+ # Rule
+
+ protected function blockRule($Line)
+ {
+ $marker = $Line['text'][0];
+
+ if (substr_count($Line['text'], $marker) >= 3 and chop($Line['text'], " $marker") === '')
+ {
+ $Block = array(
+ 'element' => array(
+ 'name' => 'hr',
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ #
+ # Setext
+
+ protected function blockSetextHeader($Line, array $Block = null)
+ {
+ if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if ($Line['indent'] < 4 and chop(chop($Line['text'], ' '), $Line['text'][0]) === '')
+ {
+ $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
+
+ return $Block;
+ }
+ }
+
+ #
+ # Markup
+
+ protected function blockMarkup($Line)
+ {
+ if ($this->markupEscaped or $this->safeMode)
+ {
+ return;
+ }
+
+ if (preg_match('/^<[\/]?+(\w*)(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+(\/)?>/', $Line['text'], $matches))
+ {
+ $element = strtolower($matches[1]);
+
+ if (in_array($element, $this->textLevelElements))
+ {
+ return;
+ }
+
+ $Block = array(
+ 'name' => $matches[1],
+ 'element' => array(
+ 'rawHtml' => $Line['text'],
+ 'autobreak' => true,
+ ),
+ );
+
+ return $Block;
+ }
+ }
+
+ protected function blockMarkupContinue($Line, array $Block)
+ {
+ if (isset($Block['closed']) or isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ $Block['element']['rawHtml'] .= "\n" . $Line['body'];
+
+ return $Block;
+ }
+
+ #
+ # Reference
+
+ protected function blockReference($Line)
+ {
+ if (strpos($Line['text'], ']') !== false
+ and preg_match('/^\[(.+?)\]:[ ]*+<?(\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*+$/', $Line['text'], $matches)
+ ) {
+ $id = strtolower($matches[1]);
+
+ $Data = array(
+ 'url' => $matches[2],
+ 'title' => isset($matches[3]) ? $matches[3] : null,
+ );
+
+ $this->DefinitionData['Reference'][$id] = $Data;
+
+ $Block = array(
+ 'element' => array(),
+ );
+
+ return $Block;
+ }
+ }
+
+ #
+ # Table
+
+ protected function blockTable($Line, array $Block = null)
+ {
+ if ( ! isset($Block) or $Block['type'] !== 'Paragraph' or isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if (
+ strpos($Block['element']['handler']['argument'], '|') === false
+ and strpos($Line['text'], '|') === false
+ and strpos($Line['text'], ':') === false
+ or strpos($Block['element']['handler']['argument'], "\n") !== false
+ ) {
+ return;
+ }
+
+ if (chop($Line['text'], ' -:|') !== '')
+ {
+ return;
+ }
+
+ $alignments = array();
+
+ $divider = $Line['text'];
+
+ $divider = trim($divider);
+ $divider = trim($divider, '|');
+
+ $dividerCells = explode('|', $divider);
+
+ foreach ($dividerCells as $dividerCell)
+ {
+ $dividerCell = trim($dividerCell);
+
+ if ($dividerCell === '')
+ {
+ return;
+ }
+
+ $alignment = null;
+
+ if ($dividerCell[0] === ':')
+ {
+ $alignment = 'left';
+ }
+
+ if (substr($dividerCell, - 1) === ':')
+ {
+ $alignment = $alignment === 'left' ? 'center' : 'right';
+ }
+
+ $alignments []= $alignment;
+ }
+
+ # ~
+
+ $HeaderElements = array();
+
+ $header = $Block['element']['handler']['argument'];
+
+ $header = trim($header);
+ $header = trim($header, '|');
+
+ $headerCells = explode('|', $header);
+
+ if (count($headerCells) !== count($alignments))
+ {
+ return;
+ }
+
+ foreach ($headerCells as $index => $headerCell)
+ {
+ $headerCell = trim($headerCell);
+
+ $HeaderElement = array(
+ 'name' => 'th',
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => $headerCell,
+ 'destination' => 'elements',
+ )
+ );
+
+ if (isset($alignments[$index]))
+ {
+ $alignment = $alignments[$index];
+
+ $HeaderElement['attributes'] = array(
+ 'style' => "text-align: $alignment;",
+ );
+ }
+
+ $HeaderElements []= $HeaderElement;
+ }
+
+ # ~
+
+ $Block = array(
+ 'alignments' => $alignments,
+ 'identified' => true,
+ 'element' => array(
+ 'name' => 'table',
+ 'elements' => array(),
+ ),
+ );
+
+ $Block['element']['elements'] []= array(
+ 'name' => 'thead',
+ );
+
+ $Block['element']['elements'] []= array(
+ 'name' => 'tbody',
+ 'elements' => array(),
+ );
+
+ $Block['element']['elements'][0]['elements'] []= array(
+ 'name' => 'tr',
+ 'elements' => $HeaderElements,
+ );
+
+ return $Block;
+ }
+
+ protected function blockTableContinue($Line, array $Block)
+ {
+ if (isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ if (count($Block['alignments']) === 1 or $Line['text'][0] === '|' or strpos($Line['text'], '|'))
+ {
+ $Elements = array();
+
+ $row = $Line['text'];
+
+ $row = trim($row);
+ $row = trim($row, '|');
+
+ preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]++`|`)++/', $row, $matches);
+
+ $cells = array_slice($matches[0], 0, count($Block['alignments']));
+
+ foreach ($cells as $index => $cell)
+ {
+ $cell = trim($cell);
+
+ $Element = array(
+ 'name' => 'td',
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => $cell,
+ 'destination' => 'elements',
+ )
+ );
+
+ if (isset($Block['alignments'][$index]))
+ {
+ $Element['attributes'] = array(
+ 'style' => 'text-align: ' . $Block['alignments'][$index] . ';',
+ );
+ }
+
+ $Elements []= $Element;
+ }
+
+ $Element = array(
+ 'name' => 'tr',
+ 'elements' => $Elements,
+ );
+
+ $Block['element']['elements'][1]['elements'] []= $Element;
+
+ return $Block;
+ }
+ }
+
+ #
+ # ~
+ #
+
+ protected function paragraph($Line)
+ {
+ return array(
+ 'type' => 'Paragraph',
+ 'element' => array(
+ 'name' => 'p',
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => $Line['text'],
+ 'destination' => 'elements',
+ ),
+ ),
+ );
+ }
+
+ protected function paragraphContinue($Line, array $Block)
+ {
+ if (isset($Block['interrupted']))
+ {
+ return;
+ }
+
+ $Block['element']['handler']['argument'] .= "\n".$Line['text'];
+
+ return $Block;
+ }
+
+ #
+ # Inline Elements
+ #
+
+ protected $InlineTypes = array(
+ '!' => array('Image'),
+ '&' => array('SpecialCharacter'),
+ '*' => array('Emphasis'),
+ ':' => array('Url'),
+ '<' => array('UrlTag', 'EmailTag', 'Markup'),
+ '[' => array('Link'),
+ '_' => array('Emphasis'),
+ '`' => array('Code'),
+ '~' => array('Strikethrough'),
+ '\\' => array('EscapeSequence'),
+ );
+
+ # ~
+
+ protected $inlineMarkerList = '!*_&[:<`~\\';
+
+ #
+ # ~
+ #
+
+ public function line($text, $nonNestables = array())
+ {
+ return $this->elements($this->lineElements($text, $nonNestables));
+ }
+
+ protected function lineElements($text, $nonNestables = array())
+ {
+ # standardize line breaks
+ $text = str_replace(array("\r\n", "\r"), "\n", $text);
+
+ $Elements = array();
+
+ $nonNestables = (empty($nonNestables)
+ ? array()
+ : array_combine($nonNestables, $nonNestables)
+ );
+
+ # $excerpt is based on the first occurrence of a marker
+
+ while ($excerpt = strpbrk($text, $this->inlineMarkerList))
+ {
+ $marker = $excerpt[0];
+
+ $markerPosition = strlen($text) - strlen($excerpt);
+
+ $Excerpt = array('text' => $excerpt, 'context' => $text);
+
+ foreach ($this->InlineTypes[$marker] as $inlineType)
+ {
+ # check to see if the current inline type is nestable in the current context
+
+ if (isset($nonNestables[$inlineType]))
+ {
+ continue;
+ }
+
+ $Inline = $this->{"inline$inlineType"}($Excerpt);
+
+ if ( ! isset($Inline))
+ {
+ continue;
+ }
+
+ # makes sure that the inline belongs to "our" marker
+
+ if (isset($Inline['position']) and $Inline['position'] > $markerPosition)
+ {
+ continue;
+ }
+
+ # sets a default inline position
+
+ if ( ! isset($Inline['position']))
+ {
+ $Inline['position'] = $markerPosition;
+ }
+
+ # cause the new element to 'inherit' our non nestables
+
+
+ $Inline['element']['nonNestables'] = isset($Inline['element']['nonNestables'])
+ ? array_merge($Inline['element']['nonNestables'], $nonNestables)
+ : $nonNestables
+ ;
+
+ # the text that comes before the inline
+ $unmarkedText = substr($text, 0, $Inline['position']);
+
+ # compile the unmarked text
+ $InlineText = $this->inlineText($unmarkedText);
+ $Elements[] = $InlineText['element'];
+
+ # compile the inline
+ $Elements[] = $this->extractElement($Inline);
+
+ # remove the examined text
+ $text = substr($text, $Inline['position'] + $Inline['extent']);
+
+ continue 2;
+ }
+
+ # the marker does not belong to an inline
+
+ $unmarkedText = substr($text, 0, $markerPosition + 1);
+
+ $InlineText = $this->inlineText($unmarkedText);
+ $Elements[] = $InlineText['element'];
+
+ $text = substr($text, $markerPosition + 1);
+ }
+
+ $InlineText = $this->inlineText($text);
+ $Elements[] = $InlineText['element'];
+
+ foreach ($Elements as &$Element)
+ {
+ if ( ! isset($Element['autobreak']))
+ {
+ $Element['autobreak'] = false;
+ }
+ }
+
+ return $Elements;
+ }
+
+ #
+ # ~
+ #
+
+ protected function inlineText($text)
+ {
+ $Inline = array(
+ 'extent' => strlen($text),
+ 'element' => array(),
+ );
+
+ $Inline['element']['elements'] = self::pregReplaceElements(
+ $this->breaksEnabled ? '/[ ]*+\n/' : '/(?:[ ]*+\\\\|[ ]{2,}+)\n/',
+ array(
+ array('name' => 'br'),
+ array('text' => "\n"),
+ ),
+ $text
+ );
+
+ return $Inline;
+ }
+
+ protected function inlineCode($Excerpt)
+ {
+ $marker = $Excerpt['text'][0];
+
+ if (preg_match('/^(['.$marker.']++)[ ]*+(.+?)[ ]*+(?<!['.$marker.'])\1(?!'.$marker.')/s', $Excerpt['text'], $matches))
+ {
+ $text = $matches[2];
+ $text = preg_replace('/[ ]*+\n/', ' ', $text);
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'code',
+ 'text' => $text,
+ ),
+ );
+ }
+ }
+
+ protected function inlineEmailTag($Excerpt)
+ {
+ $hostnameLabel = '[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?';
+
+ $commonMarkEmail = '[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]++@'
+ . $hostnameLabel . '(?:\.' . $hostnameLabel . ')*';
+
+ if (strpos($Excerpt['text'], '>') !== false
+ and preg_match("/^<((mailto:)?$commonMarkEmail)>/i", $Excerpt['text'], $matches)
+ ){
+ $url = $matches[1];
+
+ if ( ! isset($matches[2]))
+ {
+ $url = "mailto:$url";
+ }
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'a',
+ 'text' => $matches[1],
+ 'attributes' => array(
+ 'href' => $url,
+ ),
+ ),
+ );
+ }
+ }
+
+ protected function inlineEmphasis($Excerpt)
+ {
+ if ( ! isset($Excerpt['text'][1]))
+ {
+ return;
+ }
+
+ $marker = $Excerpt['text'][0];
+
+ if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))
+ {
+ $emphasis = 'strong';
+ }
+ elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))
+ {
+ $emphasis = 'em';
+ }
+ else
+ {
+ return;
+ }
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => $emphasis,
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => $matches[1],
+ 'destination' => 'elements',
+ )
+ ),
+ );
+ }
+
+ protected function inlineEscapeSequence($Excerpt)
+ {
+ if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))
+ {
+ return array(
+ 'element' => array('rawHtml' => $Excerpt['text'][1]),
+ 'extent' => 2,
+ );
+ }
+ }
+
+ protected function inlineImage($Excerpt)
+ {
+ if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')
+ {
+ return;
+ }
+
+ $Excerpt['text']= substr($Excerpt['text'], 1);
+
+ $Link = $this->inlineLink($Excerpt);
+
+ if ($Link === null)
+ {
+ return;
+ }
+
+ $Inline = array(
+ 'extent' => $Link['extent'] + 1,
+ 'element' => array(
+ 'name' => 'img',
+ 'attributes' => array(
+ 'src' => $Link['element']['attributes']['href'],
+ 'alt' => $Link['element']['handler']['argument'],
+ ),
+ 'autobreak' => true,
+ ),
+ );
+
+ $Inline['element']['attributes'] += $Link['element']['attributes'];
+
+ unset($Inline['element']['attributes']['href']);
+
+ return $Inline;
+ }
+
+ protected function inlineLink($Excerpt)
+ {
+ $Element = array(
+ 'name' => 'a',
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => null,
+ 'destination' => 'elements',
+ ),
+ 'nonNestables' => array('Url', 'Link'),
+ 'attributes' => array(
+ 'href' => null,
+ 'title' => null,
+ ),
+ );
+
+ $extent = 0;
+
+ $remainder = $Excerpt['text'];
+
+ if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
+ {
+ $Element['handler']['argument'] = $matches[1];
+
+ $extent += strlen($matches[0]);
+
+ $remainder = substr($remainder, $extent);
+ }
+ else
+ {
+ return;
+ }
+
+ if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*+"|\'[^\']*+\'))?\s*+[)]/', $remainder, $matches))
+ {
+ $Element['attributes']['href'] = $matches[1];
+
+ if (isset($matches[2]))
+ {
+ $Element['attributes']['title'] = substr($matches[2], 1, - 1);
+ }
+
+ $extent += strlen($matches[0]);
+ }
+ else
+ {
+ if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
+ {
+ $definition = strlen($matches[1]) ? $matches[1] : $Element['handler']['argument'];
+ $definition = strtolower($definition);
+
+ $extent += strlen($matches[0]);
+ }
+ else
+ {
+ $definition = strtolower($Element['handler']['argument']);
+ }
+
+ if ( ! isset($this->DefinitionData['Reference'][$definition]))
+ {
+ return;
+ }
+
+ $Definition = $this->DefinitionData['Reference'][$definition];
+
+ $Element['attributes']['href'] = $Definition['url'];
+ $Element['attributes']['title'] = $Definition['title'];
+ }
+
+ return array(
+ 'extent' => $extent,
+ 'element' => $Element,
+ );
+ }
+
+ protected function inlineMarkup($Excerpt)
+ {
+ if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)
+ {
+ return;
+ }
+
+ if ($Excerpt['text'][1] === '/' and preg_match('/^<\/\w[\w-]*+[ ]*+>/s', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'element' => array('rawHtml' => $matches[0]),
+ 'extent' => strlen($matches[0]),
+ );
+ }
+
+ if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?+[^-])*-->/s', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'element' => array('rawHtml' => $matches[0]),
+ 'extent' => strlen($matches[0]),
+ );
+ }
+
+ if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\w[\w-]*+(?:[ ]*+'.$this->regexHtmlAttribute.')*+[ ]*+\/?>/s', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'element' => array('rawHtml' => $matches[0]),
+ 'extent' => strlen($matches[0]),
+ );
+ }
+ }
+
+ protected function inlineSpecialCharacter($Excerpt)
+ {
+ if (substr($Excerpt['text'], 1, 1) !== ' ' and strpos($Excerpt['text'], ';') !== false
+ and preg_match('/^&(#?+[0-9a-zA-Z]++);/', $Excerpt['text'], $matches)
+ ) {
+ return array(
+ 'element' => array('rawHtml' => '&' . $matches[1] . ';'),
+ 'extent' => strlen($matches[0]),
+ );
+ }
+
+ return;
+ }
+
+ protected function inlineStrikethrough($Excerpt)
+ {
+ if ( ! isset($Excerpt['text'][1]))
+ {
+ return;
+ }
+
+ if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\S)(.+?)(?<=\S)~~/', $Excerpt['text'], $matches))
+ {
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'del',
+ 'handler' => array(
+ 'function' => 'lineElements',
+ 'argument' => $matches[1],
+ 'destination' => 'elements',
+ )
+ ),
+ );
+ }
+ }
+
+ protected function inlineUrl($Excerpt)
+ {
+ if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')
+ {
+ return;
+ }
+
+ if (strpos($Excerpt['context'], 'http') !== false
+ and preg_match('/\bhttps?+:[\/]{2}[^\s<]+\b\/*+/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)
+ ) {
+ $url = $matches[0][0];
+
+ $Inline = array(
+ 'extent' => strlen($matches[0][0]),
+ 'position' => $matches[0][1],
+ 'element' => array(
+ 'name' => 'a',
+ 'text' => $url,
+ 'attributes' => array(
+ 'href' => $url,
+ ),
+ ),
+ );
+
+ return $Inline;
+ }
+ }
+
+ protected function inlineUrlTag($Excerpt)
+ {
+ if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\w++:\/{2}[^ >]++)>/i', $Excerpt['text'], $matches))
+ {
+ $url = $matches[1];
+
+ return array(
+ 'extent' => strlen($matches[0]),
+ 'element' => array(
+ 'name' => 'a',
+ 'text' => $url,
+ 'attributes' => array(
+ 'href' => $url,
+ ),
+ ),
+ );
+ }
+ }
+
+ # ~
+
+ protected function unmarkedText($text)
+ {
+ $Inline = $this->inlineText($text);
+ return $this->element($Inline['element']);
+ }
+
+ #
+ # Handlers
+ #
+
+ protected function handle(array $Element)
+ {
+ if (isset($Element['handler']))
+ {
+ if (!isset($Element['nonNestables']))
+ {
+ $Element['nonNestables'] = array();
+ }
+
+ if (is_string($Element['handler']))
+ {
+ $function = $Element['handler'];
+ $argument = $Element['text'];
+ unset($Element['text']);
+ $destination = 'rawHtml';
+ }
+ else
+ {
+ $function = $Element['handler']['function'];
+ $argument = $Element['handler']['argument'];
+ $destination = $Element['handler']['destination'];
+ }
+
+ $Element[$destination] = $this->{$function}($argument, $Element['nonNestables']);
+
+ if ($destination === 'handler')
+ {
+ $Element = $this->handle($Element);
+ }
+
+ unset($Element['handler']);
+ }
+
+ return $Element;
+ }
+
+ protected function handleElementRecursive(array $Element)
+ {
+ return $this->elementApplyRecursive(array($this, 'handle'), $Element);
+ }
+
+ protected function handleElementsRecursive(array $Elements)
+ {
+ return $this->elementsApplyRecursive(array($this, 'handle'), $Elements);
+ }
+
+ protected function elementApplyRecursive($closure, array $Element)
+ {
+ $Element = call_user_func($closure, $Element);
+
+ if (isset($Element['elements']))
+ {
+ $Element['elements'] = $this->elementsApplyRecursive($closure, $Element['elements']);
+ }
+ elseif (isset($Element['element']))
+ {
+ $Element['element'] = $this->elementApplyRecursive($closure, $Element['element']);
+ }
+
+ return $Element;
+ }
+
+ protected function elementApplyRecursiveDepthFirst($closure, array $Element)
+ {
+ if (isset($Element['elements']))
+ {
+ $Element['elements'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['elements']);
+ }
+ elseif (isset($Element['element']))
+ {
+ $Element['element'] = $this->elementsApplyRecursiveDepthFirst($closure, $Element['element']);
+ }
+
+ $Element = call_user_func($closure, $Element);
+
+ return $Element;
+ }
+
+ protected function elementsApplyRecursive($closure, array $Elements)
+ {
+ foreach ($Elements as &$Element)
+ {
+ $Element = $this->elementApplyRecursive($closure, $Element);
+ }
+
+ return $Elements;
+ }
+
+ protected function elementsApplyRecursiveDepthFirst($closure, array $Elements)
+ {
+ foreach ($Elements as &$Element)
+ {
+ $Element = $this->elementApplyRecursiveDepthFirst($closure, $Element);
+ }
+
+ return $Elements;
+ }
+
+ protected function element(array $Element)
+ {
+ if ($this->safeMode)
+ {
+ $Element = $this->sanitiseElement($Element);
+ }
+
+ # identity map if element has no handler
+ $Element = $this->handle($Element);
+
+ $hasName = isset($Element['name']);
+
+ $markup = '';
+
+ if ($hasName)
+ {
+ $markup .= '<' . $Element['name'];
+
+ if (isset($Element['attributes']))
+ {
+ foreach ($Element['attributes'] as $name => $value)
+ {
+ if ($value === null)
+ {
+ continue;
+ }
+
+ $markup .= " $name=\"".self::escape($value).'"';
+ }
+ }
+ }
+
+ $permitRawHtml = false;
+
+ if (isset($Element['text']))
+ {
+ $text = $Element['text'];
+ }
+ // very strongly consider an alternative if you're writing an
+ // extension
+ elseif (isset($Element['rawHtml']))
+ {
+ $text = $Element['rawHtml'];
+
+ $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
+ $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
+ }
+
+ $hasContent = isset($text) || isset($Element['element']) || isset($Element['elements']);
+
+ if ($hasContent)
+ {
+ $markup .= $hasName ? '>' : '';
+
+ if (isset($Element['elements']))
+ {
+ $markup .= $this->elements($Element['elements']);
+ }
+ elseif (isset($Element['element']))
+ {
+ $markup .= $this->element($Element['element']);
+ }
+ else
+ {
+ if (!$permitRawHtml)
+ {
+ $markup .= self::escape($text, true);
+ }
+ else
+ {
+ $markup .= $text;
+ }
+ }
+
+ $markup .= $hasName ? '</' . $Element['name'] . '>' : '';
+ }
+ elseif ($hasName)
+ {
+ $markup .= ' />';
+ }
+
+ return $markup;
+ }
+
+ protected function elements(array $Elements)
+ {
+ $markup = '';
+
+ $autoBreak = true;
+
+ foreach ($Elements as $Element)
+ {
+ if (empty($Element))
+ {
+ continue;
+ }
+
+ $autoBreakNext = (isset($Element['autobreak'])
+ ? $Element['autobreak'] : isset($Element['name'])
+ );
+ // (autobreak === false) covers both sides of an element
+ $autoBreak = !$autoBreak ? $autoBreak : $autoBreakNext;
+
+ $markup .= ($autoBreak ? "\n" : '') . $this->element($Element);
+ $autoBreak = $autoBreakNext;
+ }
+
+ $markup .= $autoBreak ? "\n" : '';
+
+ return $markup;
+ }
+
+ # ~
+
+ protected function li($lines)
+ {
+ $Elements = $this->linesElements($lines);
+
+ if ( ! in_array('', $lines)
+ and isset($Elements[0]) and isset($Elements[0]['name'])
+ and $Elements[0]['name'] === 'p'
+ ) {
+ unset($Elements[0]['name']);
+ }
+
+ return $Elements;
+ }
+
+ #
+ # AST Convenience
+ #
+
+ /**
+ * Replace occurrences $regexp with $Elements in $text. Return an array of
+ * elements representing the replacement.
+ */
+ protected static function pregReplaceElements($regexp, $Elements, $text)
+ {
+ $newElements = array();
+
+ while (preg_match($regexp, $text, $matches, PREG_OFFSET_CAPTURE))
+ {
+ $offset = $matches[0][1];
+ $before = substr($text, 0, $offset);
+ $after = substr($text, $offset + strlen($matches[0][0]));
+
+ $newElements[] = array('text' => $before);
+
+ foreach ($Elements as $Element)
+ {
+ $newElements[] = $Element;
+ }
+
+ $text = $after;
+ }
+
+ $newElements[] = array('text' => $text);
+
+ return $newElements;
+ }
+
+ #
+ # Deprecated Methods
+ #
+
+ function parse($text)
+ {
+ $markup = $this->text($text);
+
+ return $markup;
+ }
+
+ protected function sanitiseElement(array $Element)
+ {
+ static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
+ static $safeUrlNameToAtt = array(
+ 'a' => 'href',
+ 'img' => 'src',
+ );
+
+ if ( ! isset($Element['name']))
+ {
+ unset($Element['attributes']);
+ return $Element;
+ }
+
+ if (isset($safeUrlNameToAtt[$Element['name']]))
+ {
+ $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
+ }
+
+ if ( ! empty($Element['attributes']))
+ {
+ foreach ($Element['attributes'] as $att => $val)
+ {
+ # filter out badly parsed attribute
+ if ( ! preg_match($goodAttribute, $att))
+ {
+ unset($Element['attributes'][$att]);
+ }
+ # dump onevent attribute
+ elseif (self::striAtStart($att, 'on'))
+ {
+ unset($Element['attributes'][$att]);
+ }
+ }
+ }
+
+ return $Element;
+ }
+
+ protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
+ {
+ foreach ($this->safeLinksWhitelist as $scheme)
+ {
+ if (self::striAtStart($Element['attributes'][$attribute], $scheme))
+ {
+ return $Element;
+ }
+ }
+
+ $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
+
+ return $Element;
+ }
+
+ #
+ # Static Methods
+ #
+
+ protected static function escape($text, $allowQuotes = false)
+ {
+ return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
+ }
+
+ protected static function striAtStart($string, $needle)
+ {
+ $len = strlen($needle);
+
+ if ($len > strlen($string))
+ {
+ return false;
+ }
+ else
+ {
+ return strtolower(substr($string, 0, $len)) === strtolower($needle);
+ }
+ }
+
+ static function instance($name = 'default')
+ {
+ if (isset(self::$instances[$name]))
+ {
+ return self::$instances[$name];
+ }
+
+ $instance = new static();
+
+ self::$instances[$name] = $instance;
+
+ return $instance;
+ }
+
+ private static $instances = array();
+
+ #
+ # Fields
+ #
+
+ protected $DefinitionData;
+
+ #
+ # Read-Only
+
+ protected $specialCharacters = array(
+ '\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|', '~'
+ );
+
+ protected $StrongRegex = array(
+ '*' => '/^[*]{2}((?:\\\\\*|[^*]|[*][^*]*+[*])+?)[*]{2}(?![*])/s',
+ '_' => '/^__((?:\\\\_|[^_]|_[^_]*+_)+?)__(?!_)/us',
+ );
+
+ protected $EmRegex = array(
+ '*' => '/^[*]((?:\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',
+ '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\b/us',
+ );
+
+ protected $regexHtmlAttribute = '[a-zA-Z_:][\w:.-]*+(?:\s*+=\s*+(?:[^"\'=<>`\s]+|"[^"]*+"|\'[^\']*+\'))?+';
+
+ protected $voidElements = array(
+ 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',
+ );
+
+ protected $textLevelElements = array(
+ 'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',
+ 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',
+ 'i', 'rp', 'del', 'code', 'strike', 'marquee',
+ 'q', 'rt', 'ins', 'font', 'strong',
+ 's', 'tt', 'kbd', 'mark',
+ 'u', 'xm', 'sub', 'nobr',
+ 'sup', 'ruby',
+ 'var', 'span',
+ 'wbr', 'time',
+ );
+} \ No newline at end of file
diff --git a/includes/banner.inc b/includes/banner.inc
index 1d33b43..4ad0583 100644
--- a/includes/banner.inc
+++ b/includes/banner.inc
@@ -367,14 +367,6 @@ function getMemberBannerData(string $id, string $system, bool $french = false) {
];
}
- if (($metadata["sexually_active"] ?? false) && !$french && $isLoggedIn) {
- $badges[] = [
- "id" => "sexually_active",
- "color" => "d6a833",
- "html" => '<span data-bs-toggle="tooltip" data-bs-html="true" title="<b>Sexually active</b><br>' . ucfirst(getMemberPronouns($member['pronouns'])["subjective"]) . ' ' . (getMemberPronouns($member['pronouns'])["third"] ? "is" : "are") . ' doing sexual acts and would pleasure ' . getMemberPronouns($member['pronouns'])["possessive_det"] . ' marefriend·s IRL if ' . ucfirst(getMemberPronouns($member['pronouns'])["subjective"]) . ' had the chance." class="badge rounded-pill" style="background-color:#d68f33;">Sexually active</span>'
- ];
- }
-
if (($metadata["leader"] ?? false) && $isLoggedIn) {
$badges[] = [
"id" => "leader",
diff --git a/includes/bitset.inc b/includes/bitset.inc
index 96c6bfd..f45beb1 100644
--- a/includes/bitset.inc
+++ b/includes/bitset.inc
@@ -4,27 +4,23 @@ function parseBitset ($bitset) {
$bin = str_repeat("0", 48 - strlen(decbin($bitset))) . decbin($bitset);
$sharedMemory = bindec(substr($bin, 24, 2));
- $median = substr($bin, 26, 1) !== "0";
$little = bindec(substr($bin, 27, 2));
$food = bindec(substr($bin, 16, 2));
$nonverbal = substr($bin, 15, 1) !== "0";
$lessFrequent = substr($bin, 14, 1) !== "0";
$sexuallyActive = substr($bin, 13, 1) !== "0";
- $ageRegressor = substr($bin, 12, 1) !== "0";
$leader = substr($bin, 11, 1) !== "0";
$persecutor = substr($bin, 10, 1) !== "0";
- $magic = bindec(substr($bin, 18, 3));
- $sensitivity = bindec(substr($bin, 21, 3));
$protector = substr($bin, 29, 1) !== "0";
$fictive = substr($bin, 30, 1) !== "0";
- $notTalking = substr($bin, 31, 1) !== "0";
- $host = substr($bin, 32, 1) !== "0";
$robot = substr($bin, 45, 1) !== "0";
$plush = substr($bin, 46, 1) !== "0";
- $age = substr($bin, 47, 1) !== "0";
+ $polyamorous1 = substr($bin, 18, 1) !== "0";
+ $polyamorous2 = substr($bin, 19, 1) !== "0";
$species1 = substr($bin, 33, 4);
$species2 = substr($bin, 37, 4);
- $species3 = substr($bin, 41, 4);
+ $alignment1 = substr($bin, 41, 4);
+ $alignment2 = substr($bin, 20, 4);
$species1 = match ($species1) {
"0001" => "earth",
@@ -48,46 +44,57 @@ function parseBitset ($bitset) {
default => null,
};
- $species3 = match ($species3) {
- "0001" => "earth",
- "0010" => "unicorn",
- "0011" => "pegasus",
- "0100" => "alicorn",
- "0101" => "batpony",
- "0110" => "crystal",
- "0111" => "changeling",
+ $alignment1 = match ($alignment1) {
+ "0000" => "aroace",
+ "0001" => "hetero",
+ "0010" => "homo",
+ "0011" => "bi",
+ "0100" => "pan",
default => null,
};
- if ($little === 1) {
- $ageRegressor = true;
- $little = 0;
- }
+ $alignment2 = match ($alignment2) {
+ "0000" => "aroace",
+ "0001" => "hetero",
+ "0010" => "homo",
+ "0011" => "bi",
+ "0100" => "pan",
+ default => null,
+ };
+
+ if ($little === 1) $little = 0;
return [
'shared_memory' => $sharedMemory,
- 'median' => $median,
+ 'median' => false,
'protector' => $protector,
'fictive' => $fictive,
'little' => $little,
- 'not_talking' => $notTalking,
- 'host' => $host,
+ 'not_talking' => false,
+ 'host' => false,
'robot' => $robot,
- 'magic' => $magic,
- 'sensitivity' => $sensitivity,
+ 'magic' => 0,
+ 'sensitivity' => 0,
'food' => $food,
'plush' => $plush,
'nonverbal' => $nonverbal,
'less_frequent' => $lessFrequent,
- 'age_spells' => $age,
- 'age_regressor' => $ageRegressor,
+ 'age_spells' => false,
+ 'age_regressor' => false,
'leader' => $leader,
'persecutor' => $persecutor,
'sexually_active' => $sexuallyActive,
+ 'polyamorous' => [
+ 'romantic' => $polyamorous1,
+ 'sexual' => $polyamorous2
+ ],
+ 'alignment' => [
+ 'romantic' => $alignment1,
+ 'sexual' => $alignment2
+ ],
'species' => array_filter([
$species1,
- $species2,
- $species3
+ $species2
], function ($i) {
return isset($i);
})
diff --git a/includes/details.inc b/includes/details.inc
index 8fee082..08ba52a 100644
--- a/includes/details.inc
+++ b/includes/details.inc
@@ -1,40 +1,32 @@
-<?php global $isLoggedIn; global $metadata; global $memberData; global $lang; global $pages; ?>
+<?php global $isLoggedIn; global $metadata; global $memberData; global $lang; global $pages; $pronouns = getMemberPronouns($memberData['pronouns']); ?>
<div id="member-details" class="<?= $isLoggedIn ? 'member-details-loggedIn' : '' ?>" style="<?php if (!$isLoggedIn): ?>grid-template-columns: repeat(3, 1fr);<?php endif; ?> background-color: <?= isset($memberData["color"]) ? '#' . $memberData["color"] . "33" : "transparent" ?>; margin-left: -20px; margin-right: -20px;">
<div>
<b><?= $lang["details"]["food"] ?></b><span class="member-small-separator"><br></span>
<?= match ($metadata["food"]) {
- 0 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"])) . " species indicates that " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["subjective"]) . ' ' . (getMemberPronouns($memberData["pronouns"])["third"] ? "doesn&apos;t" : "don&apos;t") . " need to eat food, therefore " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["subjective"]) . " can eat all foods.'>" . $lang["details"]["food_states"][0] . "</span>",
- 1 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["subjective"])) . " can&apos;t eat fish or meat.'>" . $lang["details"]["food_states"][1] . "</span>",
- 2 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["subjective"])) . " can&apos;t eat meat, but can eat fish.'>" . $lang["details"]["food_states"][2] . "</span>",
- 3 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["subjective"])) . " can eat all foods, meat and fish included.'>" . $lang["details"]["food_states"][3] . "</span>",
+ 0 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", $pronouns["possessive_det"])) . " species indicates that " . str_replace("'", "&apos;", $pronouns["subjective"]) . ' ' . ($pronouns["third"] ? "doesn&apos;t" : "don&apos;t") . " need to eat food, therefore " . str_replace("'", "&apos;", $pronouns["subjective"]) . " can eat all foods.'>" . $lang["details"]["food_states"][0] . "</span>",
+ 1 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", $pronouns["subjective"])) . " can&apos;t eat fish or meat.'>" . $lang["details"]["food_states"][1] . "</span>",
+ 2 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", $pronouns["subjective"])) . " can&apos;t eat meat, but can eat fish.'>" . $lang["details"]["food_states"][2] . "</span>",
+ 3 => "<span data-bs-toggle='tooltip' title='" . ucfirst(str_replace("'", "&apos;", $pronouns["subjective"])) . " can eat all foods, meat and fish included.'>" . $lang["details"]["food_states"][3] . "</span>",
} ?>
</div>
<div>
<b><?= $lang["details"]["memory"] ?></b><span class="member-small-separator"><br></span>
<?= match ($metadata["shared_memory"]) {
- 0 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " doesn&apos;t directly share" : " don&apos;t directly share") . " memory with " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " headmates, but is able to (slowly) query it if that is needed.'>" . $lang["details"]["memory_states"][0] . "</span>",
- 1 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " doesn&apos;t directly shares" : " don&apos;t directly share") . " all memories with " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " headmates, but may be able to share certain memories and/or share memories at will.'>" . $lang["details"]["memory_states"][1] . "</span>",
- 2 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " shares" : " share") . " all memories with " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " headmates.'>" . $lang["details"]["memory_states"][2] . "</span>",
+ 0 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst($pronouns["subjective"])) . ($pronouns["third"] ? " doesn&apos;t directly share" : " don&apos;t directly share") . " memory with " . str_replace("'", "&apos;", $pronouns["possessive_det"]) . " headmates, but is able to (slowly) query it if that is needed.'>" . $lang["details"]["memory_states"][0] . "</span>",
+ 1 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst($pronouns["subjective"])) . ($pronouns["third"] ? " doesn&apos;t directly shares" : " don&apos;t directly share") . " all memories with " . str_replace("'", "&apos;", $pronouns["possessive_det"]) . " headmates, but may be able to share certain memories and/or share memories at will.'>" . $lang["details"]["memory_states"][1] . "</span>",
+ 2 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst($pronouns["subjective"])) . ($pronouns["third"] ? " shares" : " share") . " all memories with " . str_replace("'", "&apos;", $pronouns["possessive_det"]) . " headmates.'>" . $lang["details"]["memory_states"][2] . "</span>",
} ?>
</div>
<?php if ($isLoggedIn): ?>
<div>
- <b>Sensitivity:</b><span class="member-small-separator"><br></span>
- <?= match ($metadata["sensitivity"]) {
- 0 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " does" : " do") . " not have sensitive spots on " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " body.'>None</span>",
- 1 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . " may have (a) sensitive spot·s on " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " body.'>Maybe</span>",
- 2 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " has" : " have") . " (a) sensitive spot·s on " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " body, and playing with it/them will make " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["object"]) . " feel affectionate: extremely safe and cared for.'>Affectionate</span>",
- 3 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " has" : " have") . " (a) sensitive spot·s on " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " body, and playing with it/them will make " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["object"]) . " feel sexually pleasured.'>Sexual</span>",
- 4 => "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . (getMemberPronouns($memberData["pronouns"])["third"] ? " has" : " have") . " (a) sensitive spot·s on " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " body, and playing with it/them will make " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["object"]) . " feel affectionate or sexually pleasured.'>Affectionate and sexual</span>",
- } ?>
- </div>
- <div>
<b>Age:</b><span class="member-small-separator"><br></span>
<?php if (!isset($metadata["birth"]["year"])): ?>
- <?php if ($metadata["birth"]["age"] <= 0): ?>
+ <?php if ($metadata["birth"]["age"] === -1): $age = abs(log(0)); // => INF ?>
+ <?= "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst($pronouns["subjective"])) . " never age" . str_replace("'", "&apos;", $pronouns["third"] ? "s" : "") . " and " . str_replace("'", "&apos;", $pronouns["third"] ? "doesn't" : "don't") . " have a defined age, making " . str_replace("'", "&apos;", $pronouns["object"]) . " pretty much eternal.'>Eternal</span>" ?>
+ <?php elseif ($metadata["birth"]["age"] <= 0): ?>
-
- <?php else: ?>
- <?= "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . str_replace("'", "&apos;", getMemberPronouns($memberData["pronouns"])["third"] ? " doesn't" : " don't") . " age like the body does, making " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["object"]) . " stay " . $metadata["birth"]["age"] . " years old for " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["possessive_det"]) . " entire life.'>" . $metadata["birth"]["age"] . "* years old</span>" ?>
+ <?php else: $age = $metadata["birth"]["age"]; ?>
+ <?= "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst($pronouns["subjective"])) . str_replace("'", "&apos;", $pronouns["third"] ? " doesn't" : " don't") . " age like the body does, making " . str_replace("'", "&apos;", $pronouns["object"]) . " stay " . $metadata["birth"]["age"] . " years old for " . str_replace("'", "&apos;", $pronouns["possessive_det"]) . " entire life.'>" . $metadata["birth"]["age"] . "* years old</span>" ?>
<?php endif; ?>
<?php else: ?>
<?php if ($metadata["birth"]["year"] <= 1900): ?>
@@ -47,7 +39,8 @@
$birthdate = $metadata["birth"]["year"] . "-" . $metadata["birth"]["date"];
}
- $age = floor((time() - strtotime($birthdate)) / 31557600);
+ $age = (int)date('Y') - $metadata["birth"]["year"] + (strtotime(date('Y') . "-" . $metadata["birth"]["date"]) <= time() ? 0 : -1);
+ $age2 = floor((time() - strtotime($birthdate)) / 31557600);
$birthday = "as time passes";
if (isset($metadata["birth"]["date"]) && trim($metadata["birth"]["date"]) !== "" && $metadata["birth"]["date"] !== "01-01") {
@@ -55,7 +48,7 @@
}
?>
- <?= "<span data-bs-toggle='tooltip' title='" . str_replace("'", "&apos;", ucfirst(getMemberPronouns($memberData['pronouns'])["subjective"])) . " age" . str_replace("'", "&apos;", getMemberPronouns($memberData["pronouns"])["third"] ? "s" : "") . " like the body does, making " . str_replace("'", "&apos;", getMemberPronouns($memberData['pronouns'])["object"]) . " stay " . $age . " years old for now, having this age change $birthday.'>" . $age . " years old</span>" ?>
+ <?= "<span data-bs-toggle='tooltip' title='$age2 with the old algorithm | " . str_replace("'", "&apos;", ucfirst($pronouns["subjective"])) . " age" . str_replace("'", "&apos;", $pronouns["third"] ? "s" : "") . " like the body does, making " . str_replace("'", "&apos;", $pronouns["object"]) . " stay " . $age . " years old for now, having this age change $birthday.'>" . $age . " years old</span>" ?>
<?php endif; ?>
<?php endif; ?>
</div>
@@ -76,4 +69,75 @@
-
<?php endif; ?>
</div>
-</div> \ No newline at end of file
+</div>
+<?php if ($isLoggedIn): ?>
+<div id="member-details-2" style="background-color: <?= isset($memberData["color"]) ? '#' . $memberData["color"] . "33" : "transparent" ?>; margin-left: -20px; margin-right: -20px;">
+ <?php if ((isset($age) && $age >= 16 && $metadata["little"] === 0) || (!isset($age) && $metadata["little"] === 0)): ?>
+ <div>
+ <b>Sexual consent:</b><span class="member-small-separator"><br></span>
+ <?php if ($metadata["sexually_active"]): ?>
+ <span title="Consent is assumed when having sex with <?= $pronouns["object"] ?>, however <?= $pronouns["subjective"] ?> may ask to not have sex at the moment and such request must be honored." data-bs-toggle="tooltip">Preemptive</span>
+ <?php else: ?>
+ <span title="Consent is absolutely required every time when having sex with <?= $pronouns["object"] ?>." data-bs-toggle="tooltip">Required</span>
+ <?php endif; ?>
+ </div>
+ <div>
+ <b><span class="member-detail-desktop">Sexual alignment</span><span class="member-detail-mobile">Sex. algn.</span>:</b><span class="member-small-separator"><br></span>
+ <?php switch ($metadata["alignment"]["sexual"]) {
+ case "aroace":
+ echo "Asexual";
+ break;
+ case "hetero":
+ echo "Straight";
+ break;
+ case "homo":
+ echo $pronouns["subjective"] === "she" ? "Lesbian" : ($pronouns["subjective"] === "he" ? "Gay" : "Homosexual");
+ break;
+ case "bi":
+ echo "Bisexual";
+ break;
+ case "pan":
+ echo "Pansexual";
+ break;
+ } ?><?php if ($metadata["polyamorous"]["sexual"]): ?> (poly)<?php endif; ?>
+ </div>
+ <?php else: ?>
+ <div>
+ <style>
+ #member-details-2 {
+ grid-template-columns: 2fr 1fr;
+ }
+ </style>
+ <div style="display: flex; align-items: center; justify-content: center; height: 100%;opacity:.5;">This member is too young to have a sexual relationship.</div>
+ </div>
+ <?php endif; ?>
+ <div>
+ <b><span class="member-detail-desktop">Romantic alignment</span><span class="member-detail-mobile">Rom. algn.</span>:</b><span class="member-small-separator"><br></span>
+ <?php switch ($metadata["alignment"]["romantic"]) {
+ case "aroace":
+ echo "Aromantic";
+ break;
+ case "hetero":
+ echo "Heteroromantic";
+ break;
+ case "homo":
+ echo $pronouns["subjective"] === "she" ? "Lesbiromantic" : ($pronouns["subjective"] === "he" ? "Gay" : "Homoromantic");
+ break;
+ case "bi":
+ echo "Biromantic";
+ break;
+ case "pan":
+ echo "Panromantic";
+ break;
+ } ?><?php if ($metadata["polyamorous"]["romantic"]): ?> (poly)<?php endif; ?>
+ </div>
+ <!--<div>
+ <b>Item 4:</b><span class="member-small-separator"><br></span>
+ Value 4
+ </div>
+ <div>
+ <b>Item 5:</b><span class="member-small-separator"><br></span>
+ Value 5
+ </div>-->
+</div>
+<?php endif; ?>
diff --git a/includes/footer.inc b/includes/footer.inc
index b95ea78..cd1bb89 100644
--- a/includes/footer.inc
+++ b/includes/footer.inc
@@ -1,5 +1,6 @@
<?php
+global $pageFile;
require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.inc";
?>
@@ -16,7 +17,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/functions.inc";
global $lang; global $pages;
?>
- © <?= date("Y") ?> <a href="https://equestria.horse" target="_blank" class="text-muted"><?= $lang["footer"]["copyright"] ?></a> · version 2.<?= $version["build"] ?>.<?= hexdec(substr($version["hash"], 0, 4)) ?>.<?= $version["revision"] ?><br>
+ © <?= date("Y") ?> <a href="https://equestria.horse" target="_blank" class="text-muted"><?= $lang["footer"]["copyright"] ?></a> · version 2.<?= $version["build"] ?>.<?= $version["revision"] ?> · node <?= strtoupper(dechex(fileinode($pageFile))) ?><br>
<a href="/-/debug" class="text-muted" style="text-decoration: none;"><?= $lang["footer"]["update"] ?> <?= trim(timeAgo($refresh["timestamp"], $lang["_french"])) ?> (<?php if (time() - $refresh["timestamp"] > 360): ?><?= $lang["footer"]["no_update"] ?><?= $lang["footer"]["separator"] ?>; <?php endif; ?><?= date('D j M, G:i:s T', (int)$refresh["timestamp"]) ?><?= $lang["footer"]["separator"] ?>; <?= $lang["footer"]["took"] ?> <?= round($refresh["duration"] * 1000) ?> ms, <?= count($refresh["restored"]) > 0 ? (count($refresh["restored"]) > 1 ? $lang["footer"]["failures"][0] . count($refresh["restored"]) . $lang["footer"]["failures"][1] : $lang["footer"]["failure"]) : $lang["footer"]["no_failure"] ?>)</a>
<br><br><br><br><br>
</div>
diff --git a/includes/fullbanner.inc b/includes/fullbanner.inc
index 24e0295..c50ad5f 100644
--- a/includes/fullbanner.inc
+++ b/includes/fullbanner.inc
@@ -20,69 +20,6 @@
<b>This member's metadata needs an update.</b> It still uses the old JSON metadata system instead of the new 24bit integer-based system. Contact a developer to request an update. (only administrators can see this; file: <code><?= $_SERVER['DOCUMENT_ROOT'] ?>/includes/data/metadata/<?= $memberID ?>.json</code>)
</div>
<?php endif; ?>
- <div class="alert alert-dark">
- <details>
- <summary>Private administrator information</summary>
- <ul style="margin-bottom:0;">
- <li><b>ID:</b> <code><?= $memberID ?></code> (<code><?= $systemID . "/" . $memberID ?></code>, <?= $memberData["name"] ?>)</li>
- <li><b>Files:</b>
- <ul>
- <li><code><?= $_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$memberID.json" ?></code> (<?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$memberID.json") ? filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$memberID.json") . " bytes" : "not found" ?>)</li>
- <li><code><?= $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID.html" ?></code> (<?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID.html") ? filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID.html") . " bytes" : "not found" ?>)</li>
- <li><code><?= $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html" ?></code> (<?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html") ? filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html") . " bytes" : "not found" ?>)</li>
- </ul>
- </li>
- <li><b>Date added:</b> <?= date('l j F Y', strtotime($memberData["created"])) ?> (<?= timeAgo($memberData["created"]) ?>, <code><?= $memberData["created"] ?></code>)</li>
- <li><b>Pronouns:</b> <?= implode(", ", getPronounsFromMark($memberData['pronouns'])) ?></li>
- <li><b>Pronouns usage:</b> <ul><?php
-
- foreach (getMemberPronouns($memberData['pronouns']) as $type => $usage) {
- if (is_string($usage) && $type !== "color") {
- echo("<li><b>" . $type . ":</b> " . $usage . "</li>");
- }
- }
-
- ?></ul></li>
- <li><b>Color:</b> <span style="border:1px solid rgba(255, 255, 255, .5);background-color:#<?= $memberData["color"] ?? "ffffff" ?>;display:inline-block;width:16px;height:16px;border-radius:5px;vertical-align: middle;filter: invert(1) hue-rotate(180deg);"></span> <span style="vertical-align: middle;"><code>#<?= $memberData["color"] ?? "ffffff" ?></code></span>
- <li><b>Bitset:</b><?php if (isset($metadata["bitset"])): ?> <code><?= str_repeat("0", 48 - strlen(decbin($metadata["bitset"]))) . decbin($metadata["bitset"]) ?></code> (0x<?= str_repeat("0", 12 - strlen(dechex($metadata["bitset"]))) . dechex($metadata["bitset"]) ?>, <?= $metadata["bitset"] ?>)</li><?php else: ?> <span class="text-warning" style="filter:invert(1) hue-rotate(180deg);">Not using bitset; please update.</span><?php endif; ?>
- <li><b>Reduced name:</b> <?= getMiniName($memberData["display_name"] ?? $member["name"]) ?></li>
- <li><b>Shared memory access:</b> <code><?= $metadata["shared_memory"] ?></code> (<?= $metadata["shared_memory"] === 2 ? "Full direct access" : ($metadata["shared_memory"] === 0 ? "No direct access" : "Partial direct access") ?>)</li>
- <li><b>Protector:</b> <code><?= $metadata["protector"] ? "1" : "0" ?></code> (<?= $metadata["protector"] ? "Yes" : "No" ?>)</li>
- <li><b>Little:</b> <code><?= $metadata["little"] ?></code> (<?= $metadata["little"] === 2 ? "Is a little" : ($metadata["little"] === 1 ? "Is an age regressor" : ($metadata["little"] === 3 ? "Not a little, but younger" : "No")) ?>)</li>
- <li><b>Relations count:</b> <code><?= count($metadata["marefriends"]) + count($metadata["sisters"]) ?></code></li>
- <?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; $score = calculateScore($metadata, $memberData["display_name"] ?? $memberData["name"]); ?>
- <li>
- <b>Score breakdown:</b> <code><?= $score["total"] ?></code>
- <ul><?php
-
- foreach ($metadata as $type => $usage) {
- if (is_string($usage)) {
- echo("<li><b>" . $type . ":</b> " . $usage . "</li>");
- } else if (is_array($usage)) {
- if (count($usage) === 0) {
- echo("<li><b>" . $type . ":</b> []</li>");
- } else {
- echo("<li><b>" . $type . ":</b><ul>");
-
- foreach ($usage as $key => $item) {
- if (is_string($item)) {
- echo("<li><b>" . $key . ":</b> " . $item . "</li>");
- } else {
- echo("<li><b>" . $key . ":</b> " . json_encode($item, JSON_UNESCAPED_SLASHES) . "</li>");
- }
- }
-
- echo("</ul></li>");
- }
- } else {
- echo("<li><b>" . $type . ":</b> " . json_encode($usage, JSON_UNESCAPED_SLASHES) . "</li>");
- }
- }
-
- ?></ul></li>
- </ul>
- </details>
- </div>
<?php endif; ?>
<?php if ($travelling[$memberID]['travelling'] && !$travelling[$memberID]['equestria']): ?>
<div class="alert alert-primary">
diff --git a/includes/functions.inc b/includes/functions.inc
index 915d41b..bdc961b 100644
--- a/includes/functions.inc
+++ b/includes/functions.inc
@@ -196,18 +196,7 @@ if (!function_exists("getMiniName")) {
if (!function_exists("withCaretakersDown")) {
function withCaretakersDown(array $ordered): array {
- $caretakersNo = [];
- $caretakersYes = [];
-
- foreach ($ordered as $item) {
- if ($item["_metadata"]["little"] === 2) {
- $caretakersYes[] = $item;
- } else {
- $caretakersNo[] = $item;
- }
- }
-
- return [...$caretakersNo, ...$caretakersYes];
+ return $ordered;
}
}
diff --git a/includes/maintenance/clearUnused.php b/includes/maintenance/clearUnused.php
new file mode 100644
index 0000000..99b6ca4
--- /dev/null
+++ b/includes/maintenance/clearUnused.php
@@ -0,0 +1,34 @@
+<?php
+
+$_SERVER['DOCUMENT_ROOT'] = "../..";
+
+foreach (array_filter(scandir($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata"), function ($i) { return !str_starts_with($i, "."); }) as $file) {
+ $data = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$file"), true);
+ echo("$file\n");
+
+ if (!isset($data["bitset"])) {
+ die(" No bitset?? wtf\n");
+ } else {
+ $bits = str_split(substr(str_repeat("0", 48), 0, 48 - strlen(decbin($data["bitset"]))) . decbin($data["bitset"]));
+ echo(" Old:\n");
+ echo(" " . str_replace("+", "\e[92m1\e[39m", str_replace("-", "\e[31m0\e[39m", implode("", str_replace("0", "-", str_replace("1", "+", $bits))))) . "\n");
+ echo(" XXXXXXXXXX X XXXXXX X XX XXXX X\n");
+
+ $bitsOld = implode("", $bits);
+ foreach ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 18, 19, 20, 21, 22, 23, 26, 31, 32, 41, 42, 43, 44, 47] as $bit) {
+ $bits[$bit] = "0";
+ }
+
+ echo(" New:\n");
+ echo(" " . str_replace("+", "\e[92m1\e[39m", str_replace("-", "\e[31m0\e[39m", implode("", str_replace("0", "-", str_replace("1", "+", $bits))))) . "\n");
+ echo(" XXXXXXXXXX X XXXXXX X XX XXXX X\n");
+ echo(" Changed " . levenshtein($bitsOld, implode("", $bits)) . " bit(s)\n");
+
+ echo(" Backup made in " . substr($file, 0, -5) . "-old.json\n");
+ copy($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$file", $_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . substr($file, 0, -5) . "-old.json");
+
+ $data["bitset"] = bindec(implode("", $bits));
+ echo(" Saved to " . $file . "\n");
+ file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$file", json_encode($data));
+ }
+} \ No newline at end of file
diff --git a/includes/member.inc b/includes/member.inc
index 8734471..e984861 100644
--- a/includes/member.inc
+++ b/includes/member.inc
@@ -78,7 +78,71 @@ if ($memberData["name"] === "fusion") {
</div>
<?php else: ?>
<?php global $isLoggedIn; if ($isLoggedIn): ?>
- <small style="opacity:.5;display:block;">(edit: <a href="/-/metadata/<?= $system ?>/<?= $memberData['name'] ?>">metadata</a>, <a href="/-/edit/<?= $system ?>/<?= $memberData['name'] ?>">public</a>, <a href="/-/edit-private/<?= $system ?>/<?= $memberData['name'] ?>">private</a>)</small>
+ <details>
+ <summary style="list-style: none;">
+ <small style="opacity:.5;display:block;">(edit: <a href="/-/metadata/<?= $system ?>/<?= $memberData['name'] ?>">metadata</a>, <a href="/-/edit/<?= $system ?>/<?= $memberData['name'] ?>">public</a>, <a href="/-/edit-private/<?= $system ?>/<?= $memberData['name'] ?>">private</a>)</small>
+ </summary>
+ <div class="alert alert-dark">
+ <ul style="margin-bottom:0;">
+ <li><b>ID:</b> <code><?= $memberID ?></code> (<code><?= $systemID . "/" . $memberID ?></code>, <?= $memberData["name"] ?>)</li>
+ <li><b>Files:</b>
+ <ul>
+ <li><code><?= $_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$memberID.json" ?></code> (<?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$memberID.json") ? filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/$memberID.json") . " bytes" : "not found" ?>)</li>
+ <li><code><?= $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID.html" ?></code> (<?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID.html") ? filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID.html") . " bytes" : "not found" ?>)</li>
+ <li><code><?= $_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html" ?></code> (<?= file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html") ? filesize($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html") . " bytes" : "not found" ?>)</li>
+ </ul>
+ </li>
+ <li><b>Date added:</b> <?= date('l j F Y', strtotime($memberData["created"])) ?> (<?= timeAgo($memberData["created"]) ?>, <code><?= $memberData["created"] ?></code>)</li>
+ <li><b>Pronouns:</b> <?= implode(", ", getPronounsFromMark($memberData['pronouns'])) ?></li>
+ <li><b>Pronouns usage:</b> <ul><?php
+
+ foreach (getMemberPronouns($memberData['pronouns']) as $type => $usage) {
+ if (is_string($usage) && $type !== "color") {
+ echo("<li><b>" . $type . ":</b> " . $usage . "</li>");
+ }
+ }
+
+ ?></ul></li>
+ <li><b>Color:</b> <span style="border:1px solid rgba(255, 255, 255, .5);background-color:#<?= $memberData["color"] ?? "ffffff" ?>;display:inline-block;width:16px;height:16px;border-radius:5px;vertical-align: middle;filter: invert(1) hue-rotate(180deg);"></span> <span style="vertical-align: middle;"><code>#<?= $memberData["color"] ?? "ffffff" ?></code></span>
+ <li><b>Bitset:</b><?php if (isset($metadata["bitset"])): ?> <code><?= str_repeat("0", 48 - strlen(decbin($metadata["bitset"]))) . decbin($metadata["bitset"]) ?></code> (0x<?= str_repeat("0", 12 - strlen(dechex($metadata["bitset"]))) . dechex($metadata["bitset"]) ?>, <?= $metadata["bitset"] ?>)</li><?php else: ?> <span class="text-warning" style="filter:invert(1) hue-rotate(180deg);">Not using bitset; please update.</span><?php endif; ?>
+ <li><b>Reduced name:</b> <?= getMiniName($memberData["display_name"] ?? $member["name"]) ?></li>
+ <li><b>Shared memory access:</b> <code><?= $metadata["shared_memory"] ?></code> (<?= $metadata["shared_memory"] === 2 ? "Full direct access" : ($metadata["shared_memory"] === 0 ? "No direct access" : "Partial direct access") ?>)</li>
+ <li><b>Protector:</b> <code><?= $metadata["protector"] ? "1" : "0" ?></code> (<?= $metadata["protector"] ? "Yes" : "No" ?>)</li>
+ <li><b>Little:</b> <code><?= $metadata["little"] ?></code> (<?= $metadata["little"] === 2 ? "Is a little" : ($metadata["little"] === 1 ? "Is an age regressor" : ($metadata["little"] === 3 ? "Not a little, but younger" : "No")) ?>)</li>
+ <li><b>Relations count:</b> <code><?= count($metadata["marefriends"]) + count($metadata["sisters"]) ?></code></li>
+ <?php require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/score.inc"; $score = calculateScore($metadata, $memberData["display_name"] ?? $memberData["name"]); ?>
+ <li>
+ <b>Score breakdown:</b> <code><?= $score["total"] ?></code>
+ <ul><?php
+
+ foreach ($metadata as $type => $usage) {
+ if (is_string($usage)) {
+ echo("<li><b>" . $type . ":</b> " . $usage . "</li>");
+ } else if (is_array($usage)) {
+ if (count($usage) === 0) {
+ echo("<li><b>" . $type . ":</b> []</li>");
+ } else {
+ echo("<li><b>" . $type . ":</b><ul>");
+
+ foreach ($usage as $key => $item) {
+ if (is_string($item)) {
+ echo("<li><b>" . $key . ":</b> " . $item . "</li>");
+ } else {
+ echo("<li><b>" . $key . ":</b> " . json_encode($item, JSON_UNESCAPED_SLASHES) . "</li>");
+ }
+ }
+
+ echo("</ul></li>");
+ }
+ } else {
+ echo("<li><b>" . $type . ":</b> " . json_encode($usage, JSON_UNESCAPED_SLASHES) . "</li>");
+ }
+ }
+
+ ?></ul></li>
+ </ul>
+ </div>
+ </details>
<?php endif; ?>
<?php if (file_exists($_SERVER['DOCUMENT_ROOT'] . "/includes/data/content/$memberID-private.html") && $isLoggedIn): ?>
diff --git a/includes/navigation.inc b/includes/navigation.inc
index bdafe99..fe1c9ee 100644
--- a/includes/navigation.inc
+++ b/includes/navigation.inc
@@ -54,13 +54,6 @@ $navigation_admin = [
"minimal" => false,
"items" => [
[
- "name" => $pages["dashboard"]["name"][$lang["_name"]],
- "icon" => "/assets/icons/dashboard.svg",
- "invert" => true,
- "link" => "/-/dashboard",
- "stepped" => null
- ],
- [
"name" => $pages["about"]["name"][$lang["_name"]],
"icon" => "/assets/icons/about.svg",
"invert" => true,
@@ -89,10 +82,10 @@ $navigation_admin = [
"stepped" => null
],
[
- "name" => $pages["rules-old"]["name"][$lang["_name"]],
- "icon" => "/assets/icons/rules-old.svg",
+ "name" => $pages["rules"]["name"][$lang["_name"]],
+ "icon" => "/assets/icons/rules.svg",
"invert" => true,
- "link" => "/-/rules-old",
+ "link" => "/-/rules",
"stepped" => null
],
[
diff --git a/includes/pages.json b/includes/pages.json
index 4c6fcf5..a55c748 100644
--- a/includes/pages.json
+++ b/includes/pages.json
@@ -235,22 +235,13 @@
},
"rules": {
"name": {
- "en": "General rules",
- "fr": "General rules"
+ "en": "Rules",
+ "fr": "Rules"
},
"short": "Rules",
"admin": true,
"rail": true
},
- "rules-old": {
- "name": {
- "en": "Systems rules (legacy)",
- "fr": "Systems rules (legacy)"
- },
- "short": "Rules (old)",
- "admin": true,
- "rail": true
- },
"s:compare": {
"name": {
"en": "Compare members",
diff --git a/includes/planner.inc b/includes/planner.inc
index 225fca4..a5782a5 100644
--- a/includes/planner.inc
+++ b/includes/planner.inc
@@ -84,7 +84,9 @@ function day($display, $diff): void { if ($diff < 0) $disabled = true; else $dis
?>
<tr class="planner-day" id="planner-header-<?= $diff ?>" <?php if ($disabled): ?>style="opacity: .75; pointer-events: none;"<?php endif; ?>>
- <td colspan="10"><?= $display ?></td>
+ <td colspan="10" style="border:none;padding:0;">
+ <div style="padding:5px 10px;margin:-0.5px;border-top:1px solid #404040;border-left:1px solid #404040;border-right:1px solid #404040;border-top-left-radius: 10px; border-top-right-radius: 10px;"><?= $display ?></div>
+ </td>
<?php
if (!isset($cloudburst[date('Y-m-d', time() + (86400 * $diff))])) $cloudburst[date('Y-m-d', time() + (86400 * $diff))] = [];
@@ -100,96 +102,110 @@ function day($display, $diff): void { if ($diff < 0) $disabled = true; else $dis
?>
</tr>
<tr class="planner-header" <?php if ($disabled): ?>style="opacity: .75; pointer-events: none;"<?php endif; ?>>
- <td colspan="5">Cloudburst System</td>
- <td colspan="5">Raindrops System</td>
+ <td colspan="5" style="border-top-color:transparent;border-right-color: transparent;">Cloudburst System</td>
+ <td colspan="5" style="border-top-color:transparent;border-left-color: transparent;">Raindrops System</td>
</tr>
<?php for ($i = 0; $i <= $biggest; $i++): ?>
<tr class="planner-member" <?php if ($disabled): ?>style="opacity: .75; pointer-events: none;"<?php endif; ?>>
<?php if (isset($dayCloudburst[$index])): ?>
- <td class="planner-member-id">
+ <td class="planner-member-id" style="border-right-color: transparent;border-bottom-color: transparent;">
<?= $index + 1 ?>
</td>
- <td class="planner-link" style="width:50vw;" <?php if (!isset($dayCloudburst[$index][1])): ?>colspan="3" <?php else: ?>colspan="2"<?php endif; ?>>
+ <td class="planner-link" style="width:50vw;border-right-color: transparent;border-bottom-color: transparent;" <?php if (!isset($dayCloudburst[$index][1])): ?>colspan="3" <?php else: ?>colspan="2"<?php endif; ?>>
<?php $member = getMemberWithoutSystem($dayCloudburst[$index][0]); ?>
<?php if ($member["name"] === "fusion"): ?>
- <a class="member-link" onclick="openEditFronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="/assets/logo/logo.png" style="width:24px;"> <span class="member-link-text"><span class="text-muted merge-desktop">Multiple merged members</span><span class="text-muted merge-mobile">Merge</span></span></a>
+ <a class="member-link" onclick="openEditFronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Multiple merged members</span></span></span></a>
+ <?php elseif ($member["name"] === "unknown"): ?>
+ <a class="member-link" onclick="openEditFronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Other/unknown/fallback pony</span></span></span></a>
<?php else: ?>
- <a class="member-link" onclick="openEditFronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></span></a>
+ <a class="member-link" onclick="openEditFronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= !isset($dayCloudburst[$index][1]) ? $member["display_name"] ?? $member["name"] : getMiniName($member["display_name"] ?? $member["name"]) ?></span></span></a>
<?php endif; ?>
</td>
<?php if (!isset($dayCloudburst[$index][1])): ?>
- <td class="planner-cofronter-inner planner-link" style="width:5%;text-align:center;">
- <a onclick="addCofronter('cloudburst', <?= $diff ?>, <?= $index ?>);" class="planner-add-link">
- <img src="/assets/icons/add.svg" alt="" class="planner-add-icon">
+ <td class="planner-cofronter-inner planner-link" style="width:5%;text-align:center;border-left-color: transparent;border-bottom-color: transparent;">
+ <a onclick="addCofronter('cloudburst', <?= $diff ?>, <?= $index ?>);" class="planner-add-link planner-add-link-cofronter">
+ <span class="planner-add-link-cofronter-inner"><img src="/assets/icons/add.svg" alt="" class="planner-add-icon"></span>
</a>
</td>
<?php else: ?>
- <td class="planner-link" style="width:41.35vw;" colspan="2">
+ <td class="planner-link" style="border-bottom-color: transparent;width:41.35vw;" colspan="2">
<?php $member = getMemberWithoutSystem($dayCloudburst[$index][1]); ?>
<?php if ($member["name"] === "fusion"): ?>
- <a class="member-link" onclick="openEditCofronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="/assets/logo/logo.png" style="width:24px;"> <span class="member-link-text"><span class="text-muted merge-desktop">Multiple merged members</span><span class="text-muted merge-mobile">Merge</span></span></a>
+ <a class="member-link" onclick="openEditCofronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Multiple merged members</span></span></span></a>
+ <?php elseif ($member["name"] === "unknown"): ?>
+ <a class="member-link" onclick="openEditCofronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Other/unknown/fallback pony</span></span></span></a>
<?php else: ?>
- <a class="member-link" onclick="openEditCofronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></span></a>
+ <a class="member-link" onclick="openEditCofronter('cloudburst', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= !isset($dayCloudburst[$index][1]) ? $member["display_name"] ?? $member["name"] : getMiniName($member["display_name"] ?? $member["name"]) ?></span></span></a>
<?php endif; ?>
</td>
<?php endif; ?>
<?php elseif ($index === count($dayCloudburst)): ?>
- <td class="planner-add-inner planner-link" colspan="5">
+ <td class="planner-add-inner planner-link" colspan="5" style="border-top-color: transparent;border-bottom-color: transparent;">
<a onclick="addFronter('cloudburst', <?= $diff ?>, <?= $index ?>);" id="planner-add-link-cloudburst-<?= $diff ?>" class="planner-add-link">
- <img src="/assets/icons/add.svg" alt="" class="planner-add-icon">
- <span class="planner-add-text">Add new fronter</span>
+ <div class="planner-add-link-inner">
+ <img src="/assets/icons/add.svg" alt="" class="planner-add-icon">
+ <span class="planner-add-text">Add new fronter</span>
+ </div>
</a>
</td>
<?php else: ?>
- <td colspan="5" class="planner-empty"></td>
+ <td colspan="5" class="planner-empty" style="border-top-color:transparent;border-bottom-color:transparent;"></td>
<?php endif; ?>
<?php if (isset($dayRaindrops[$index])): ?>
- <td class="planner-member-id">
+ <td class="planner-member-id" style="border-bottom-color: transparent;border-right-color: transparent;">
<?= $index + 1 ?>
</td>
<?php $member = getMemberWithoutSystem($dayRaindrops[$index][0]); ?>
- <td class="planner-link" style="width:50vw;" <?php if (!isset($dayRaindrops[$index][1])): ?>colspan="3" <?php else: ?>colspan="2"<?php endif; ?>>
+ <td class="planner-link" style="border-right-color:transparent;border-bottom-color: transparent;width:50vw;" <?php if (!isset($dayRaindrops[$index][1])): ?>colspan="3" <?php else: ?>colspan="2"<?php endif; ?>>
<?php if ($member["name"] === "fusion"): ?>
- <a class="member-link" onclick="openEditFronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="/assets/logo/logo.png" style="width:24px;"> <span class="member-link-text"><span class="text-muted merge-desktop">Multiple merged members</span><span class="text-muted merge-mobile">Merge</span></span></a>
+ <a class="member-link" onclick="openEditFronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Multiple merged members</span></span></span></a>
+ <?php elseif ($member["name"] === "unknown"): ?>
+ <a class="member-link" onclick="openEditFronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Other/unknown/fallback pony</span></span></span></a>
<?php else: ?>
- <a class="member-link" onclick="openEditFronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></span></a>
+ <a class="member-link" onclick="openEditFronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= !isset($dayRaindrops[$index][1]) ? $member["display_name"] ?? $member["name"] : getMiniName($member["display_name"] ?? $member["name"]) ?></span></span></a>
<?php endif; ?>
</td>
<?php if (!isset($dayRaindrops[$index][1])): ?>
- <td class="planner-cofronter-inner planner-link" style="width:5%;text-align:center;">
- <a onclick="addCofronter('raindrops', <?= $diff ?>, <?= $index ?>);" class="planner-add-link">
- <img src="/assets/icons/add.svg" alt="" class="planner-add-icon">
+ <td class="planner-cofronter-inner planner-link" style="border-bottom-color: transparent;border-left-color: transparent;width:5%;text-align:center;">
+ <a onclick="addCofronter('raindrops', <?= $diff ?>, <?= $index ?>);" class="planner-add-link planner-add-link-cofronter">
+ <span class="planner-add-link-cofronter-inner"><img src="/assets/icons/add.svg" alt="" class="planner-add-icon"></span>
</a>
</td>
<?php else: ?>
<td class="planner-link" style="width:41.35vw;" colspan="2">
<?php $member = getMemberWithoutSystem($dayRaindrops[$index][1]); ?>
<?php if ($member["name"] === "fusion"): ?>
- <a class="member-link" onclick="openEditCofronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="/assets/logo/logo.png" style="width:24px;"> <span class="member-link-text"><span class="text-muted merge-desktop">Multiple merged members</span><span class="text-muted merge-mobile">Merge</span></span></a>
+ <a class="member-link" onclick="openEditCofronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Multiple merged members</span></span></span></a>
+ <?php elseif ($member["name"] === "unknown"): ?>
+ <a class="member-link" onclick="openEditCofronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span class="member-link-text"><span class="merge-desktop" style="opacity:.75;">Other/unknown/fallback pony</span></span></span></a>
<?php else: ?>
- <a class="member-link" onclick="openEditCofronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= getMiniName($member["display_name"] ?? $member["name"]) ?></span></a>
+ <a class="member-link" onclick="openEditCofronter('raindrops', <?= $index ?>, '<?= date('Y-m-d', time() + (86400 * $diff)) ?>')"><span class="member-link-inner"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <span class="member-link-text"><?= !isset($dayRaindrops[$index][1]) ? $member["display_name"] ?? $member["name"] : getMiniName($member["display_name"] ?? $member["name"]) ?></span></span></a>
<?php endif; ?>
</td>
<?php endif; ?>
<?php elseif ($index === count($dayRaindrops)): ?>
- <td class="planner-add-inner planner-link" colspan="5">
+ <td class="planner-add-inner planner-link" colspan="5" style="border-top-color: transparent;border-bottom-color: transparent;">
<a onclick="addFronter('raindrops', <?= $diff ?>, <?= $index ?>);" id="planner-add-link-raindrops-<?= $diff ?>" class="planner-add-link">
- <img src="/assets/icons/add.svg" alt="" class="planner-add-icon">
- <span class="planner-add-text">Add new fronter</span>
+ <div class="planner-add-link-inner">
+ <img src="/assets/icons/add.svg" alt="" class="planner-add-icon">
+ <span class="planner-add-text">Add new fronter</span>
+ </div>
</a>
</td>
<?php else: ?>
- <td colspan="5" class="planner-empty"></td>
+ <td colspan="5" class="planner-empty" style="border-top-color:transparent;border-bottom-color:transparent;"></td>
<?php endif; ?>
</tr>
<?php $index++; endfor; ?>
<tr class="planner-day planner-end-of-day" <?php if ($disabled): ?>style="opacity: .75; pointer-events: none;"<?php endif; ?>>
- <td colspan="10">
- <?php if (count($dayCloudburst) > 0 && count($dayRaindrops) > 0): ?>
- <?= getMiniName(getMemberWithoutSystem($dayCloudburst[count($dayCloudburst) - 1][0])["display_name"] ?? getMemberWithoutSystem($dayCloudburst[count($dayCloudburst) - 1][0])["name"]) ?> will sleep with <?= getMiniName(getMemberWithoutSystem($dayRaindrops[count($dayRaindrops) - 1][0])["display_name"] ?? getMemberWithoutSystem($dayRaindrops[count($dayRaindrops) - 1][0])["name"]) ?>
- <?php else: ?>
- Unable to calculate who will sleep with who
- <?php endif; ?>
+ <td colspan="10" style="padding: 0;border:none;">
+ <div style="padding: 5px 10px;border: 1px solid #404040;margin:-1px;border-bottom-left-radius: 10px;border-bottom-right-radius: 10px;">
+ <?php if (count($dayCloudburst) > 0 && count($dayRaindrops) > 0): ?>
+ <?= getMiniName(getMemberWithoutSystem($dayCloudburst[count($dayCloudburst) - 1][0])["display_name"] ?? getMemberWithoutSystem($dayCloudburst[count($dayCloudburst) - 1][0])["name"]) ?> will sleep with <?= getMiniName(getMemberWithoutSystem($dayRaindrops[count($dayRaindrops) - 1][0])["display_name"] ?? getMemberWithoutSystem($dayRaindrops[count($dayRaindrops) - 1][0])["name"]) ?>
+ <?php else: ?>
+ Unable to calculate who will sleep with who
+ <?php endif; ?>
+ </div>
</td>
</tr>
<tr class="planner-separator"></tr>
@@ -358,6 +374,33 @@ function day($display, $diff): void { if ($diff < 0) $disabled = true; else $dis
}
}
+ .member-link, .planner-link {
+ background-color: transparent !important;
+ }
+
+ .member-link-inner, .planner-add-link-inner, .planner-add-link-cofronter-inner {
+ display: block;
+ padding: 3px 7px;
+ border-radius: 5px;
+ }
+
+ .planner-add-link-cofronter-inner {
+ border-radius: 100%;
+ }
+
+ .planner-add-link-cofronter-inner .planner-add-icon {
+ margin-top: -2px;
+ }
+
+ .member-link, .planner-add-link-inner, .planner-add-link-cofronter-inner {
+ padding: 2px 3px !important;
+ }
+
+ .member-link:hover .member-link-inner, .planner-add-link:hover .planner-add-link-inner, .planner-add-link-cofronter:hover .planner-add-link-cofronter-inner {
+ background-color: rgba(255, 255, 255, .125);
+ /*background-color: rgba(255, 255, 255, .25);*/
+ }
+
</style>
<!--suppress JSUnresolvedVariable, JSUnresolvedFunction -->
@@ -394,14 +437,16 @@ function day($display, $diff): void { if ($diff < 0) $disabled = true; else $dis
let otherPony = window.fronting[window.addSystem === "gdapd" ? "cloudburst" : "raindrops"][window.currentWorkingDate][window.addIndex][0];
let availablePonies = window.relations[window.fronting[window.addSystem === "gdapd" ? "cloudburst" : "raindrops"][window.currentWorkingDate][window.addIndex][0]];
- document.getElementById("associated-results").innerHTML = "";
+ if (availablePonies) {
+ document.getElementById("associated-results").innerHTML = "";
- for (let pony of availablePonies) {
- document.getElementById("associated-results").innerHTML += document.getElementById("list-pony-" + pony).outerHTML;
- }
+ for (let pony of availablePonies) {
+ document.getElementById("associated-results").innerHTML += document.getElementById("list-pony-" + pony).outerHTML;
+ }
- document.getElementById("list").style.display = "none";
- document.getElementById("associated-results").style.display = "";
+ document.getElementById("list").style.display = "none";
+ document.getElementById("associated-results").style.display = "";
+ }
}
}
@@ -687,7 +732,8 @@ function day($display, $diff): void { if ($diff < 0) $disabled = true; else $dis
<?php foreach (scoreOrderGlobal() as $member): ?>
<a id="list-pony-<?= $member['id'] ?>" onclick="confirmFronterAdd(window.addSystem, '<?= $member['id'] ?>');" class="new-fronter-link member-link list-group-item list-group-item-action"><img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <?= getMiniName($member["display_name"] ?? $member["name"]) ?><peh-schedule-add></peh-schedule-add></a>
<?php endforeach; $member = getSystemMember("gdapd", "irxyh") ?>
- <a onclick="confirmFronterAdd(window.addSystem, 'irxyh');" class="new-fronter-link member-link list-group-item list-group-item-action"><img src="/assets/logo/logo.png" style="width:24px;"> <span class="text-muted">Multiple merged members</span></a>
+ <a onclick="confirmFronterAdd(window.addSystem, 'irxyh');" class="new-fronter-link member-link list-group-item list-group-item-action"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span style="opacity:.75">Multiple merged members</span></a>
+ <a onclick="confirmFronterAdd(window.addSystem, 'zdtsg');" class="new-fronter-link member-link list-group-item list-group-item-action"><img src="/assets/logo/newlogo.png" style="filter:grayscale(1);width:24px;"> <span style="opacity:.75">Other/unknown/fallback pony</span></a>
</div>
</div>
diff --git a/includes/refresh.php b/includes/refresh.php
index 18c01ed..fe01414 100644
--- a/includes/refresh.php
+++ b/includes/refresh.php
@@ -161,19 +161,31 @@ function getSystem(string $id) {
echo(" Switches\n");
$currentOpStart = microtime(true);
- echo(" Part 1/3\n");
+ echo(" Part 1/6\n");
$switches1 = json_decode(file_get_contents("https://pluralkit.equestria.dev/v2/systems/$id/switches"), true);
$oldest = $switches1[count($switches1) - 1]["timestamp"];
- echo(" Part 2/3\n");
+ echo(" Part 2/6\n");
$switches2 = json_decode(file_get_contents("https://pluralkit.equestria.dev/v2/systems/$id/switches?before=$oldest"), true);
$oldest = $switches2[count($switches2) - 1]["timestamp"];
- echo(" Part 3/3\n");
+ echo(" Part 3/6\n");
$switches3 = json_decode(file_get_contents("https://pluralkit.equestria.dev/v2/systems/$id/switches?before=$oldest"), true);
+ $oldest = $switches3[count($switches3) - 1]["timestamp"];
- if ($switches1 !== null && $switches2 !== null && $switches3 !== null) {
- file_put_contents("./data/$id/switches.json", json_encode([...$switches1, ...$switches2, ...$switches3], JSON_PRETTY_PRINT));
+ echo(" Part 4/6\n");
+ $switches4 = json_decode(file_get_contents("https://pluralkit.equestria.dev/v2/systems/$id/switches?before=$oldest"), true);
+ $oldest = $switches4[count($switches4) - 1]["timestamp"];
+
+ echo(" Part 5/6\n");
+ $switches5 = json_decode(file_get_contents("https://pluralkit.equestria.dev/v2/systems/$id/switches?before=$oldest"), true);
+ $oldest = $switches5[count($switches5) - 1]["timestamp"];
+
+ echo(" Part 6/6\n");
+ $switches6 = json_decode(file_get_contents("https://pluralkit.equestria.dev/v2/systems/$id/switches?before=$oldest"), true);
+
+ if ($switches1 !== null && $switches2 !== null && $switches3 !== null && $switches4 !== null && $switches5 !== null && $switches6 !== null) {
+ file_put_contents("./data/$id/switches.json", json_encode([...$switches1, ...$switches2, ...$switches3, ...$switches4, ...$switches5, ...$switches6], JSON_PRETTY_PRINT));
$times["system-switches-$id"] = microtime(true) - $currentOpStart;
}
}
diff --git a/includes/sysbanner.inc b/includes/sysbanner.inc
index bafb10d..f9feb5c 100644
--- a/includes/sysbanner.inc
+++ b/includes/sysbanner.inc
@@ -82,7 +82,7 @@ $pages = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/pa
<?php
$travellers = array_filter(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . ($systemID === "gdapd" ? "ynmuc" : "gdapd") . "/members.json"), true), function ($i) use ($travelling) {
- return $travelling[$i['id']]['travelling'];
+ return $travelling[$i['id']]['travelling'] && !$travelling[$i['id']]['equestria'];
});
?>
diff --git a/includes/system/species.inc b/includes/system/species.inc
index 41b06fe..8f4368e 100644
--- a/includes/system/species.inc
+++ b/includes/system/species.inc
@@ -9,11 +9,11 @@ function species(array $members, string $id, string $name) { global $systemID; g
$members = [
...array_map(function ($i) use ($systemID) { $i["_system"] = $systemID; return $i; },array_filter($members, function ($i) use ($systemID) {
global $travelling;
- return !$travelling[$i['id']]['travelling'];
+ return !($travelling[$i['id']]['travelling'] || (isset($travelling[$i['id']]['equestria']) && $travelling[$i['id']]['equestria']));
})),
...array_map(function ($i) use ($systemID) { $i["_system"] = $systemID === "gdapd" ? "ynmuc" : "gdapd"; return $i; }, array_filter(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/" . ($systemID === "gdapd" ? "ynmuc" : "gdapd") . "/members.json"), true), function ($i) use ($id, $systemID) {
global $travelling;
- return $travelling[$i['id']]['travelling'] && in_array($id, parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $i['id'] . ".json"), true))["species"]);
+ return $travelling[$i['id']]['travelling'] && !$travelling[$i['id']]['equestria'] && in_array($id, parseMetadata(json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/metadata/" . $i['id'] . ".json"), true))["species"]);
}))
];
diff --git a/pages/bitset.inc b/pages/bitset.inc
index d4239a7..c74fe64 100644
--- a/pages/bitset.inc
+++ b/pages/bitset.inc
@@ -31,7 +31,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
<br>
<div class="container">
<div id="page-content">
- <h2>Bitset calculator</h2>
+ <h2 oncontextmenu="document.getElementById('deprecated-options').style.display='block';">Bitset calculator</h2>
</div>
<div style="display:grid; grid-template-columns: repeat(48, 1fr);">
<div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-1" class="font-monospace tooltip-nohelp text-muted" style="text-align: center;cursor: pointer;">0</div>
@@ -46,27 +46,27 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
<div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-10" class="font-monospace tooltip-nohelp text-muted" style="text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Persecutor" id="binary-bit-11" class="font-monospace tooltip-nohelp" style="color:#197387;text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Leader" id="binary-bit-12" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#877e19;">0</div>
- <div data-bs-toggle="tooltip" title="Age regressor (deprecated)" id="binary-bit-13" class="font-monospace tooltip-nohelp" style="color: #383838;text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Sexually active" id="binary-bit-14" class="font-monospace tooltip-nohelp" style="color: rgb(59,196,46);text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-13" class="text-muted font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Preemptive sexual consent" id="binary-bit-14" class="font-monospace tooltip-nohelp" style="color: rgb(59,196,46);text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Fronts less frequently" id="binary-bit-15" class="font-monospace tooltip-nohelp" style="color: #198754;text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Non verbal in real life" id="binary-bit-16" class="font-monospace tooltip-nohelp" style="color: #20c997;text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Eatable food" id="binary-bit-17" class="font-monospace tooltip-nohelp" style="color: #d63384;text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Eatable food" id="binary-bit-18" class="font-monospace tooltip-nohelp" style="color: #d63384;text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Ability to use magic" id="binary-bit-19" class="font-monospace tooltip-nohelp" style="color: #fd7e14;text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Ability to use magic" id="binary-bit-20" class="font-monospace tooltip-nohelp" style="color: #fd7e14;text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Ability to use magic" id="binary-bit-21" class="font-monospace tooltip-nohelp" style="color: #fd7e14;text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Affectionative or sexual sensitivity" id="binary-bit-22" class="font-monospace tooltip-nohelp" style="color:#3340d0; text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Affectionative or sexual sensitivity" id="binary-bit-23" class="font-monospace tooltip-nohelp" style="color:#3340d0; text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Affectionative or sexual sensitivity" id="binary-bit-24" class="font-monospace tooltip-nohelp" style="color:#3340d0; text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Polyamory (romantic)" id="binary-bit-19" class="font-monospace tooltip-nohelp" style="color: #eeb8b8; text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Polyamory (sexual)" id="binary-bit-20" class="font-monospace tooltip-nohelp" style="color: #e2b8ee; text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Sexual alignment" id="binary-bit-21" class="font-monospace tooltip-nohelp" style="color: #5fff4d; text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Sexual alignment" id="binary-bit-22" class="font-monospace tooltip-nohelp" style="color: #5fff4d; text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Sexual alignment" id="binary-bit-23" class="font-monospace tooltip-nohelp" style="color: #5fff4d; text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Sexual alignment" id="binary-bit-24" class="font-monospace tooltip-nohelp" style="color: #5fff4d; text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Shared memory access" id="binary-bit-25" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#fa77ef;">0</div>
<div data-bs-toggle="tooltip" title="Shared memory access" id="binary-bit-26" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#fa77ef;">0</div>
- <div data-bs-toggle="tooltip" title="Median system" id="binary-bit-27" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color: #a14700;">0</div>
+ <div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-27" class="text-muted font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Little/younger" id="binary-bit-28" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#b277fa;">0</div>
<div data-bs-toggle="tooltip" title="Little/younger" id="binary-bit-29" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#b277fa;">0</div>
<div data-bs-toggle="tooltip" title="Protector" id="binary-bit-30" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#77faab;">0</div>
<div data-bs-toggle="tooltip" title="Fictive" id="binary-bit-31" class="font-monospace tooltip-nohelp text-info" style="text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Not talking" id="binary-bit-32" class="font-monospace tooltip-nohelp text-danger" style="text-align: center;cursor: pointer;">0</div>
- <div data-bs-toggle="tooltip" title="Most common fronter (deprecated)" id="binary-bit-33" class="font-monospace tooltip-nohelp" style="color:#383838;text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-32" class="text-muted font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-33" class="text-muted font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="1st species" id="binary-bit-34" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#fab277;">0</div>
<div data-bs-toggle="tooltip" title="1st species" id="binary-bit-35" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#fab277;">0</div>
<div data-bs-toggle="tooltip" title="1st species" id="binary-bit-36" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#fab277;">0</div>
@@ -75,18 +75,18 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
<div data-bs-toggle="tooltip" title="2nd species" id="binary-bit-39" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#faf377;">0</div>
<div data-bs-toggle="tooltip" title="2nd species" id="binary-bit-40" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#faf377;">0</div>
<div data-bs-toggle="tooltip" title="2nd species" id="binary-bit-41" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#faf377;">0</div>
- <div data-bs-toggle="tooltip" title="3rd species" id="binary-bit-42" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#abfa77;">0</div>
- <div data-bs-toggle="tooltip" title="3rd species" id="binary-bit-43" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#abfa77;">0</div>
- <div data-bs-toggle="tooltip" title="3rd species" id="binary-bit-44" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#abfa77;">0</div>
- <div data-bs-toggle="tooltip" title="3rd species" id="binary-bit-45" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#abfa77;">0</div>
+ <div data-bs-toggle="tooltip" title="Romantic alignment" id="binary-bit-42" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color: #4d5cff;">0</div>
+ <div data-bs-toggle="tooltip" title="Romantic alignment" id="binary-bit-43" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color: #4d5cff;">0</div>
+ <div data-bs-toggle="tooltip" title="Romantic alignment" id="binary-bit-44" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color: #4d5cff;">0</div>
+ <div data-bs-toggle="tooltip" title="Romantic alignment" id="binary-bit-45" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color: #4d5cff;">0</div>
<div data-bs-toggle="tooltip" title="Robot" id="binary-bit-46" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;">0</div>
<div data-bs-toggle="tooltip" title="Plush" id="binary-bit-47" class="font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;color:#6610f2;">0</div>
- <div data-bs-toggle="tooltip" title="Affected by age spells (deprecated)" id="binary-bit-48" class="font-monospace tooltip-nohelp" style="color:#383838;text-align: center;cursor: pointer;">0</div>
+ <div data-bs-toggle="tooltip" title="Value reserved for future use" id="binary-bit-48" class="text-muted font-monospace tooltip-nohelp" style="text-align: center;cursor: pointer;">0</div>
</div>
<br>
<p>
- <b>Input:</b> <input onchange="calculateInput();" onkeydown="calculateInput()" onkeyup="calculateInput()" value="2048" id="input" type="number" class="form-control" style="width:256px;display: inline-block;color:white;background:#111;border-color:#222;" maxlength="15" max="281474976710655" min="2048"><br>
- <b>Output:</b> <code id="output-bin">0b000000000000000000000000000000000000100000000000</code>, <code id="output-hex">0x000008000000</code>, <code id="output-dec">2048</code>
+ <input onchange="calculateInput();" onkeydown="calculateInput()" onkeyup="calculateInput()" value="2048" id="input" type="number" class="form-control" style="width:256px;display: inline-block;color:white;background:#111;border-color:#222;" maxlength="15" max="281474976710655" min="2048"><br>
+ <code id="output-bin">0b000000000000000000000000000000000000100000000000</code>, <code id="output-hex">0x000008000000</code>, <code id="output-dec">2048</code>
</p>
<script>
for (let i = 1; i <= 48; i++) {
@@ -113,130 +113,112 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
}
}
- let sharedMemory = parseInt(binString.substring(8 + 16, 10 + 16), 2);
- let median = binString.substring(10 + 16, 11 + 16) !== "0";
- let little = parseInt(binString.substring(11 + 16, 13 + 16), 2);
- let protector = binString.substring(13 + 16, 14 + 16) !== "0";
- let fictive = binString.substring(14 + 16, 15 + 16) !== "0";
- let notTalking = binString.substring(15 + 16, 16 + 16) !== "0";
- let host = binString.substring(16 + 16, 17 + 16) !== "0";
- let robot = binString.substring(29 + 16, 30 + 16) !== "0";
- let plush = binString.substring(30 + 16, 31 + 16) !== "0";
- let species1 = binString.substring(17 + 16, 21 + 16);
- let species2 = binString.substring(21 + 16, 25 + 16);
- let species3 = binString.substring(25 + 16, 29 + 16);
- let food = parseInt(binString.substring(16, 2 + 16), 2);
- let magic = parseInt(binString.substring(2 + 16, 5 + 16), 2);
- let sensitivity = parseInt(binString.substring(5 + 16, 8 + 16), 2);
- let ageSpells = binString.substring(31 + 16, 32 + 16) !== "0";
- let nonverbal = binString.substring(15, 16) !== "0";
- let lessFrequent = binString.substring(14, 15) !== "0";
- let sexuallyActive = binString.substring(13, 14) !== "0";
- let ageRegressor = binString.substring(12, 13) !== "0";
- let leader = binString.substring(11, 12) !== "0";
- let persecutor = binString.substring(10, 11) !== "0";
-
- document.getElementById("value-0").value = sharedMemory;
- document.getElementById("value-1").value = little;
- document.getElementById("value-2").value = species1;
- document.getElementById("value-3").value = species2;
- document.getElementById("value-4").checked = median;
- document.getElementById("value-5").checked = protector;
- document.getElementById("value-6").checked = fictive;
- document.getElementById("value-7").checked = notTalking;
- document.getElementById("value-8").checked = host;
- document.getElementById("value-9").checked = robot;
- document.getElementById("value-10").checked = plush;
- document.getElementById("value-11").value = food;
- document.getElementById("value-12").value = magic;
- document.getElementById("value-13").value = sensitivity;
- document.getElementById("value-14").value = species3;
- document.getElementById("value-15").checked = ageSpells;
- document.getElementById("value-16").checked = nonverbal;
- document.getElementById("value-17").checked = lessFrequent;
- document.getElementById("value-18").checked = sexuallyActive;
- document.getElementById("value-19").checked = ageRegressor;
- document.getElementById("value-20").checked = leader;
- document.getElementById("value-21").checked = persecutor;
+ display(binString);
+ setColors();
}
- }
-
- function calculateOutput() {
- let bin = [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null].map((_, i) => {
- let e = i + 1;
- return document.getElementById("binary-bit-" + e).innerText;
- }).join("");
- document.getElementById("output-bin").innerText = "0b" + bin;
-
- let hex = parseInt(bin, 2).toString(16);
-
- document.getElementById("output-hex").innerText = "0x" + "0".repeat(12 - hex.length) + hex;
- document.getElementById("output-dec").innerText = parseInt(bin, 2).toString();
- document.getElementById("input").value = parseInt(bin, 2).toString();
+ setColors()
}
- function calculateInput() {
- if (parseInt(document.getElementById("input").value).toString().length > 15) return;
-
- let binString = ("0".repeat(48 - parseInt(document.getElementById("input").value).toString(2).length)) + parseInt(document.getElementById("input").value).toString(2);
- let bin = binString.split("").map((i) => parseInt(i));
-
+ function setColors() {
for (let i = 1; i <= 48; i++) {
- if (bin[i - 1]) {
- document.getElementById("binary-bit-" + i).innerText = bin[i - 1].toString();
+ let e = document.getElementById("binary-bit-" + i);
+ if (e.title !== "Value reserved for future use") {
+ e.style.color = "";
+
+ e.classList.remove("text-info");
+ e.classList.remove("text-warning");
+ e.classList.remove("text-light");
+ e.classList.remove("text-dark");
+
+ if (e.innerText === "0") {
+ e.classList.remove("text-success");
+ e.classList.add("text-danger");
+ } else {
+ e.classList.add("text-success");
+ e.classList.remove("text-danger");
+ }
} else {
- document.getElementById("binary-bit-" + i).innerText = "0";
+ e.style.cursor = "not-allowed";
+ e.onclick = null;
}
}
+ }
+ function display(binString) {
let sharedMemory = parseInt(binString.substring(8 + 16, 10 + 16), 2);
- let median = binString.substring(10 + 16, 11 + 16) !== "0";
let little = parseInt(binString.substring(11 + 16, 13 + 16), 2);
let protector = binString.substring(13 + 16, 14 + 16) !== "0";
let fictive = binString.substring(14 + 16, 15 + 16) !== "0";
- let notTalking = binString.substring(15 + 16, 16 + 16) !== "0";
- let host = binString.substring(16 + 16, 17 + 16) !== "0";
let robot = binString.substring(29 + 16, 30 + 16) !== "0";
let plush = binString.substring(30 + 16, 31 + 16) !== "0";
- let ageSpells = binString.substring(31 + 16, 32 + 16) !== "0";
let species1 = binString.substring(17 + 16, 21 + 16);
let species2 = binString.substring(21 + 16, 25 + 16);
- let species3 = binString.substring(25 + 16, 29 + 16);
let food = parseInt(binString.substring(16, 2 + 16), 2);
let nonverbal = binString.substring(15, 16) !== "0";
let lessFrequent = binString.substring(14, 15) !== "0";
- let magic = parseInt(binString.substring(2 + 16, 5 + 16), 2);
- let sensitivity = parseInt(binString.substring(5 + 16, 8 + 16), 2);
let sexuallyActive = binString.substring(13, 14) !== "0";
- let ageRegressor = binString.substring(12, 13) !== "0";
let leader = binString.substring(11, 12) !== "0";
let persecutor = binString.substring(10, 11) !== "0";
+ let polyamorous1 = binString.substring(18, 19) !== "0";
+ let polyamorous2 = binString.substring(19, 20) !== "0";
+ let alignment1 = binString.substring(20, 24);
+ let alignment2 = binString.substring(25 + 16, 29 + 16);
document.getElementById("value-0").value = sharedMemory;
document.getElementById("value-1").value = little;
document.getElementById("value-2").value = species1;
document.getElementById("value-3").value = species2;
- document.getElementById("value-11").value = food;
- document.getElementById("value-12").value = magic;
- document.getElementById("value-13").value = sensitivity;
- document.getElementById("value-4").checked = median;
document.getElementById("value-5").checked = protector;
document.getElementById("value-6").checked = fictive;
- document.getElementById("value-7").checked = notTalking;
- document.getElementById("value-8").checked = host;
document.getElementById("value-9").checked = robot;
document.getElementById("value-10").checked = plush;
- document.getElementById("value-14").value = species3;
- document.getElementById("value-15").checked = ageSpells;
+ document.getElementById("value-11").value = food;
document.getElementById("value-16").checked = nonverbal;
document.getElementById("value-17").checked = lessFrequent;
document.getElementById("value-18").checked = sexuallyActive;
- document.getElementById("value-19").checked = ageRegressor;
document.getElementById("value-20").checked = leader;
document.getElementById("value-21").checked = persecutor;
+ document.getElementById("value-22").checked = polyamorous1;
+ document.getElementById("value-23").checked = polyamorous2;
+ document.getElementById("value-24").value = alignment1;
+ document.getElementById("value-25").value = alignment2;
+
+ setColors();
+ }
+
+ function calculateOutput() {
+ let bin = [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null].map((_, i) => {
+ let e = i + 1;
+ return document.getElementById("binary-bit-" + e).innerText;
+ }).join("");
+
+ document.getElementById("output-bin").innerText = "0b" + bin;
+
+ let hex = parseInt(bin, 2).toString(16);
+
+ document.getElementById("output-hex").innerText = "0x" + "0".repeat(12 - hex.length) + hex;
+ document.getElementById("output-dec").innerText = parseInt(bin, 2).toString();
+ document.getElementById("input").value = parseInt(bin, 2).toString();
+ }
+ function calculateInput() {
+ if (parseInt(document.getElementById("input").value).toString().length > 15) return;
+
+ let binString = ("0".repeat(48 - parseInt(document.getElementById("input").value).toString(2).length)) + parseInt(document.getElementById("input").value).toString(2);
+ let bin = binString.split("").map((i) => parseInt(i));
+
+ for (let i = 1; i <= 48; i++) {
+ if (bin[i - 1]) {
+ document.getElementById("binary-bit-" + i).innerText = bin[i - 1].toString();
+ } else {
+ document.getElementById("binary-bit-" + i).innerText = "0";
+ }
+ }
+
+ display(binString);
calculateOutput();
+ setColors();
return bin;
}
@@ -246,24 +228,20 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
let val1 = document.getElementById("value-1").value;
let val2 = document.getElementById("value-2").value;
let val3 = document.getElementById("value-3").value;
- let val4 = document.getElementById("value-4").checked;
let val5 = document.getElementById("value-5").checked;
let val6 = document.getElementById("value-6").checked;
- let val7 = document.getElementById("value-7").checked;
- let val8 = document.getElementById("value-8").checked;
let val9 = document.getElementById("value-9").checked;
let val10 = document.getElementById("value-10").checked;
let val11 = document.getElementById("value-11").value;
- let val12 = document.getElementById("value-12").value;
- let val13 = document.getElementById("value-13").value;
- let val14 = document.getElementById("value-14").value;
- let val15 = document.getElementById("value-15").checked;
let val16 = document.getElementById("value-16").checked;
let val17 = document.getElementById("value-17").checked;
let val18 = document.getElementById("value-18").checked;
- let val19 = document.getElementById("value-19").checked;
let val20 = document.getElementById("value-20").checked;
let val21 = document.getElementById("value-21").checked;
+ let val22 = document.getElementById("value-22").checked;
+ let val23 = document.getElementById("value-23").checked;
+ let val24 = document.getElementById("value-24").value;
+ let val25 = document.getElementById("value-25").value;
let val0bin = parseInt(val0).toString(2);
val0bin = val0bin.length === 1 ? "0" + val0bin : val0bin;
@@ -274,32 +252,30 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
let val11bin = parseInt(val11).toString(2);
val11bin = val11bin.length === 1 ? "0" + val11bin : val11bin;
- let val12bin = parseInt(val12).toString(2);
- val12bin = val12bin.length === 1 ? "00" + val12bin : (val12bin.length === 2 ? "0" + val12bin : val12bin);
-
- let val13bin = parseInt(val13).toString(2);
- val13bin = val13bin.length === 1 ? "00" + val13bin : (val13bin.length === 2 ? "0" + val13bin : val13bin);
-
let val2bin = val2;
let val3bin = val3;
- let val14bin = val14;
+ let val24bin = val24;
+ let val25bin = val25;
+
+ let val4bin = "0";
+ let val7bin = "0";
+ let val8bin = "0";
+ let val15bin = "0";
+ let val19bin = "0";
- let val4bin = val4 ? "1" : "0";
let val5bin = val5 ? "1" : "0";
let val6bin = val6 ? "1" : "0";
- let val7bin = val7 ? "1" : "0";
- let val8bin = val8 ? "1" : "0";
let val9bin = val9 ? "1" : "0";
let val10bin = val10 ? "1" : "0";
- let val15bin = val15 ? "1" : "0";
let val16bin = val16 ? "1" : "0";
let val17bin = val17 ? "1" : "0";
let val18bin = val18 ? "1" : "0";
- let val19bin = val19 ? "1" : "0";
let val20bin = val20 ? "1" : "0";
let val21bin = val21 ? "1" : "0";
+ let val22bin = val22 ? "1" : "0";
+ let val23bin = val23 ? "1" : "0";
- let bin = "0000000000" + val21bin + val20bin + val19bin + val18bin + val17bin + val16bin + val11bin + val12bin + val13bin + val0bin + val4bin + val1bin + val5bin + val6bin + val7bin + val8bin + val2bin + val3bin + val14bin + val9bin + val10bin + val15bin;
+ let bin = "0000000000" + val21bin + val20bin + val19bin + val18bin + val17bin + val16bin + val11bin + val22bin + val23bin + val24bin + val0bin + val4bin + val1bin + val5bin + val6bin + val7bin + val8bin + val2bin + val3bin + val25bin + val9bin + val10bin + val15bin;
console.log(bin, parseInt(bin, 2));
@@ -314,85 +290,107 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
}
calculateOutput();
+ setColors();
}
</script>
+ <table style="margin-bottom: 1rem;">
+ <tbody>
+ <tr>
+ <td style="padding-right: 10px; text-align: right;">
+ <b>Shared memory access: </b>
+ </td>
+ <td>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-0" onchange="updateFromSelection();">
+ <option value="2">Full direct access</option>
+ <option value="1">Partial direct access</option>
+ <option value="0" selected>No direct access</option>
+ </select>
+ </td>
+ </tr><tr>
+ <td style="padding-right: 10px; text-align: right;">
+ <b>Food: </b>
+ </td>
+ <td>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-11" onchange="updateFromSelection();">
+ <option value="0" selected>Doesn't need to eat</option>
+ <option value="1">Can't eat fish or meat</option>
+ <option value="2">Can't eat meat</option>
+ <option value="3">Can eat everything</option>
+ </select>
+ </td>
+ </tr><tr>
+ <td style="padding-right: 10px; text-align: right;">
+ <b>Little/younger: </b>
+ </td>
+ <td>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-1" onchange="updateFromSelection();">
+ <option value="0" selected>None</option>
+ <option value="2">Little</option>
+ <option value="3">Younger</option>
+ <option value="1" disabled>Age regressor (old)</option>
+ </select>
+ </td>
+ </tr><tr>
+ <td style="padding-right: 10px; text-align: right;">
+ <b>Species: </b>
+ </td>
+ <td>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-2" onchange="updateFromSelection();">
+ <option value="0000" disabled>None</option>
+ <option value="0001">Earth pony</option>
+ <option value="0010">Unicorn</option>
+ <option value="0011">Pegasus</option>
+ <option value="0100">Alicorn</option>
+ <option value="0101">Bat pony</option>
+ <option value="0110">Crystal pony</option>
+ <option value="0111">Changeling</option>
+ </select>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-3" onchange="updateFromSelection();">
+ <option value="0000">None</option>
+ <option value="0001">Earth pony</option>
+ <option value="0010">Unicorn</option>
+ <option value="0011">Pegasus</option>
+ <option value="0100">Alicorn</option>
+ <option value="0101">Bat pony</option>
+ <option value="0110">Crystal pony</option>
+ <option value="0111">Changeling</option>
+ </select>
+ <select class="tooltip-nohelp form-select" style='display:none;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-14" onchange="updateFromSelection();">
+ <option value="0000">None</option>
+ <option value="0001">Earth pony</option>
+ <option value="0010">Unicorn</option>
+ <option value="0011">Pegasus</option>
+ <option value="0100">Alicorn</option>
+ <option value="0101">Bat pony</option>
+ <option value="0110">Crystal pony</option>
+ <option value="0111">Changeling</option>
+ </select>
+ </td>
+ </tr><tr>
+ <td style="padding-right: 10px; text-align: right;">
+ <b>Alignment: </b>
+ </td>
+ <td>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-24" onchange="updateFromSelection();">
+ <option value="0000">Asexual</option>
+ <option value="0001">Heterosexual</option>
+ <option value="0010">Homosexual</option>
+ <option value="0011">Bisexual</option>
+ <option value="0100">Pansexual</option>
+ </select>
+ <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-25" onchange="updateFromSelection();">
+ <option value="0000">Aromantic</option>
+ <option value="0001">Heteroromantic</option>
+ <option value="0010">Homoromantic</option>
+ <option value="0011">Biromantic</option>
+ <option value="0100">Panromantic</option>
+ </select>
+ </td>
+ </tr>
+ </tbody>
+ </table>
<p>
- <b>Shared memory access: </b><select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-0" onchange="updateFromSelection();">
- <option value="2">Full direct access</option>
- <option value="1">Partial direct access</option>
- <option value="0" selected>No direct access</option>
- </select>
- <br>
- <b>Food: </b><select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-11" onchange="updateFromSelection();">
- <option value="0" selected>Doesn't need to eat</option>
- <option value="1">Can't eat fish or meat</option>
- <option value="2">Can't eat meat</option>
- <option value="3">Can eat everything</option>
- </select>
- <br>
- <b>Little/younger: </b><select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-1" onchange="updateFromSelection();">
- <option value="0" selected>None</option>
- <option value="2">Little</option>
- <option value="3">Younger</option>
- <option value="1" disabled>Age regressor (old)</option>
- </select>
- <br>
- <b>Species: </b><select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-2" onchange="updateFromSelection();">
- <option value="0000" disabled>None</option>
- <option value="0001">Earth pony</option>
- <option value="0010">Unicorn</option>
- <option value="0011">Pegasus</option>
- <option value="0100">Alicorn</option>
- <option value="0101">Bat pony</option>
- <option value="0110">Crystal pony</option>
- <option value="0111">Changeling</option>
- </select>
- <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-3" onchange="updateFromSelection();">
- <option value="0000">None</option>
- <option value="0001">Earth pony</option>
- <option value="0010">Unicorn</option>
- <option value="0011">Pegasus</option>
- <option value="0100">Alicorn</option>
- <option value="0101">Bat pony</option>
- <option value="0110">Crystal pony</option>
- <option value="0111">Changeling</option>
- </select>
- <select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-14" onchange="updateFromSelection();">
- <option value="0000">None</option>
- <option value="0001">Earth pony</option>
- <option value="0010">Unicorn</option>
- <option value="0011">Pegasus</option>
- <option value="0100">Alicorn</option>
- <option value="0101">Bat pony</option>
- <option value="0110">Crystal pony</option>
- <option value="0111">Changeling</option>
- </select>
- <br>
- <div style="display: none;">
- <b>Magic: </b><select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-12" onchange="updateFromSelection();">
- <option value="0" selected>Can't use magic</option>
- <option value="1" disabled>Can use magic in some cases (deprecated)</option>
- <option value="2">Can use magic with a horn</option>
- <option value="3">Can use magic with wings</option>
- <option value="4">Can use magic with wings and a horn</option>
- <option value="5">Can use magic with another part of the body</option>
- </select>
- <br>
- </div>
- <b>Sensitivity: </b><select class="tooltip-nohelp form-select" style='display:inline-block;width:max-content;color:white;background-color:#111;border-color:#222;background-image:url("data:image/svg+xml,%3csvg xmlns=&apos;http://www.w3.org/2000/svg&apos; viewBox=&apos;0 0 16 16&apos;%3e%3cpath fill=&apos;none&apos; stroke=&apos;%23ffffff&apos; stroke-linecap=&apos;round&apos; stroke-linejoin=&apos;round&apos; stroke-width=&apos;2&apos; d=&apos;M2 5l6 6 6-6&apos;/%3e%3c/svg%3e");' id="value-13" onchange="updateFromSelection();">
- <option value="0" selected>None</option>
- <option value="1" disabled>May be sensitive (deprecated)</option>
- <option value="2">Affectionately sensitive</option>
- <option value="3">Sexually sensitive</option>
- <option value="4" disabled>Sensitive in both ways (deprecated)</option>
- </select>
- </p>
- <p>
- <label style="margin-bottom:5px;">
- <input type="checkbox" id="value-4" onchange="updateFromSelection();">
- Part of a median system
- </label><br>
<label style="margin-bottom:5px;">
<input type="checkbox" id="value-5" onchange="updateFromSelection();">
Protector
@@ -407,11 +405,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
</label><br>
<label style="margin-bottom:5px;">
<input type="checkbox" id="value-18" onchange="updateFromSelection();">
- Sexually active
- </label><br>
- <label style="margin-bottom:5px;">
- <input type="checkbox" id="value-7" onchange="updateFromSelection();">
- Not talking
+ Preemptive sexual consent
</label><br>
<label style="margin-bottom:5px;">
<input type="checkbox" id="value-9" onchange="updateFromSelection();">
@@ -422,6 +416,14 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
Plush
</label><br>
<label style="margin-bottom:5px;">
+ <input type="checkbox" id="value-22" onchange="updateFromSelection();">
+ Polyamorous (romantic)
+ </label><br>
+ <label style="margin-bottom:5px;">
+ <input type="checkbox" id="value-23" onchange="updateFromSelection();">
+ Polyamorous (sexual)
+ </label><br>
+ <label style="margin-bottom:5px;">
<input type="checkbox" id="value-16" onchange="updateFromSelection();">
Non verbal in real life
</label><br>
@@ -435,26 +437,14 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
</label><br>
</p>
- <hr>
- <details>
- <summary>Show deprecated options</summary>
-
- <br>
- <p>
- <label style="margin-bottom:5px;">
- <input type="checkbox" id="value-8" onchange="updateFromSelection();">
- Most common fronter
- </label><img alt="" src="/assets/icons/visibility-public.svg" style="filter:invert(1);width:24px;margin-left:5px;margin-top:-5px;" title="This information will be shown publicly" data-bs-toggle="tooltip"><br>
- <label style="margin-bottom:5px;">
- <input type="checkbox" id="value-15" onchange="updateFromSelection();">
- Affected by age spells
- </label><img alt="" src="/assets/icons/visibility-private.svg" style="filter:invert(1);width:24px;margin-left:5px;margin-top:-5px;" title="This information will remain private" data-bs-toggle="tooltip"><br>
- <label style="margin-bottom:5px;">
- <input type="checkbox" id="value-19" onchange="updateFromSelection();">
- Age regressor
- </label><img alt="" src="/assets/icons/visibility-public.svg" style="filter:invert(1);width:24px;margin-left:5px;margin-top:-5px;" title="This information will be shown publicly" data-bs-toggle="tooltip"><br>
- </p>
- </details>
+ <div id="deprecated-options" style="display: none;">
+ <hr>
+ <details>
+ <summary>Show deprecated options</summary>
+
+ <p>Nothing here lol</p>
+ </details>
+ </div>
</div>
<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?>
diff --git a/pages/page.inc b/pages/page.inc
index d13dd2f..f3859d3 100644
--- a/pages/page.inc
+++ b/pages/page.inc
@@ -38,11 +38,13 @@ $systemID = $system === "cloudburst" ? "ynmuc" : "gdapd";
if ($member === null) {
global $_SystemName;
$_SystemName = $system;
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . '/includes/system.inc';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/system.inc';
} else if ($member === "-" && isset($parts[2])) {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/includes/system/' . $parts[2] . '.inc')) {
global $_SystemPage;
$_SystemPage = $parts[2];
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . '/includes/system/' . $parts[2] . '.inc';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/system/' . $parts[2] . '.inc';
} else {
header("Location: /?error=" . $lang["page"]["system"] . " " . $parts[2]) and die();
@@ -89,6 +91,7 @@ if ($member === null) {
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/includes/member/' . $parts[3] . '.inc')) {
global $_MemberPage;
$_MemberPage = $parts[3];
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . '/includes/member/' . $parts[3] . '.inc';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/member/' . $parts[3] . '.inc';
} else {
header("Location: /?error=" . $lang["page"]["system"] . " " . $parts[3]) and die();
@@ -98,6 +101,7 @@ if ($member === null) {
global $_MemberName;
$_MemberName = $member;
+ $pageFile = $_SERVER['DOCUMENT_ROOT'] . '/includes/member.inc';
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/member.inc';
}
diff --git a/pages/relations.inc b/pages/relations.inc
index ce0d65c..8d14fe7 100644
--- a/pages/relations.inc
+++ b/pages/relations.inc
@@ -15,8 +15,8 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
} else {
return true;
}
- })) as $member): if (count($member["_metadata"]["marefriends"]) > 0 || count($member["_metadata"]["sisters"]) > 0 || count($member["_metadata"]["caretakers"]) > 0): ?>
- <div class="relation" style="background-color:rgba(255, 255, 255, .1);margin-bottom:10px;padding:10px;border-radius:10px;display:grid;grid-template-columns: 1.5fr <?= $member["_metadata"]["little"] === 2 ? "2fr 2fr 2fr" : "3fr 3fr" ?>;">
+ })) as $member): ?>
+ <div class="relation" style="background-color:rgba(255, 255, 255, .1);margin-bottom:10px;padding:10px;border-radius:10px;display:grid;grid-template-columns: 1.5fr 2fr 2fr 2fr;">
<a class="relation-intro" style="background-color:rgba(255, 255, 255, .05);border-right:1px solid rgba(255, 255, 255, .1);margin:-10px;padding:10px;border-top-left-radius:10px;border-bottom-left-radius:10px;color: white;text-decoration: none;" href="/<?= $member["name"] ?>">
<img src="<?= getAsset($member["system"], $member["id"], "heads") ?>" style="width:24px;"> <?= $member["display_name"] ?? $member["name"] ?>
</a>
@@ -55,8 +55,8 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
</tr></tbody>
</table>
- <?php if ($member["_metadata"]["little"] === 2): ?>
- <table class="relation-item relation-item-sisters" style="padding:0 20px;">
+ <?php if ($member["_metadata"]["little"] >= 2): ?>
+ <table class="relation-item relation-item-caretakers" style="padding:0 20px;">
<tbody><tr>
<td style="width: 50%;text-align:right;">
<b style="padding-right:5px;"><?= $lang["relations"]["caretakers"] ?></b><span class="list-separator-mobile"><br></span>
@@ -74,7 +74,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
</table>
<?php endif; ?>
</div>
- <?php endif; endforeach; ?>
+ <?php endforeach; ?>
</div>
<style>
diff --git a/pages/rules-old.inc b/pages/rules-old.inc
index 1fd7f94..a567bc5 100644
--- a/pages/rules-old.inc
+++ b/pages/rules-old.inc
@@ -1,253 +1,4 @@
<?php
-require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages;
-
-if (isset($_POST["updateRules"])) {
- header("Content-Type: text/plain");
-
- if (!isset($_POST['payload'])) {
- header("Location: /-/rules");
- die();
- }
-
- foreach ($_POST['payload'] as $index => $rule) {
- if (!isset($rule["name"]) || !isset($rule["content"]) && !is_numeric($index)) {
- header("Location: /-/rules");
- die();
- }
-
- if (trim($rule["name"]) === "") {
- unset($_POST["payload"][$index]);
- continue;
- }
-
- if (!isset($rule["approved"])) $rule["approved"] = [];
- if (isset($rule["approved"][0])) $rule["approved"][0] = true; else $rule["approved"][0] = false;
- if (isset($rule["approved"][1])) $rule["approved"][1] = true; else $rule["approved"][1] = false;
-
- $_POST["payload"][$index] = $rule;
- }
-
- file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/rules/rules.json", utf8_encode(json_encode($_POST["payload"])));
-
- header("Location: /-/rules");
- die();
-}
-
-require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
-
-?>
-
-<br>
-<div class="container">
- <div id="page-content">
- <h2>Systems rules</h2>
- <p>Click on a rule to view additional details. <a onclick="event.target.blur();" href="#" data-bs-toggle="modal" data-bs-target="#editor">Edit rules</a></p>
-
- <?php
-
- $rules = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/rules/rules.json"), true);
-
- $protectorCloudburst = array_values(array_filter(scoreOrderGlobal(), function ($i) {
- return $i["_system"] === "ynmuc" && $i["_metadata"]["protector"];
- }))[0];
- $protectorRaindrops = array_values(array_filter(scoreOrderGlobal(), function ($i) {
- return $i["_system"] === "gdapd" && $i["_metadata"]["protector"];
- }))[0];
-
- $pcName = getMiniName($protectorCloudburst["display_name"] ?? $protectorCloudburst["name"]);
- $prName = getMiniName($protectorRaindrops["display_name"] ?? $protectorRaindrops["name"]);
-
- ?>
-
- <ul class="list-group">
- <?php $index = 1; foreach ($rules as $rule): ?>
- <li class="list-group-item rule-outer">
- <details>
- <summary class="rule">
- <b><?= $index ?>. <?= strip_tags($rule["name"]) ?></b>
- <?php if (in_array(false, $rule["approved"])): ?>
- <span class="badge bg-warning text-black rounded-pill">Unapproved</span>
- <?php endif; ?>
- </summary>
- <?php if (in_array(false, $rule["approved"])): ?>
- <div style="margin-top:10px;" class="alert alert-warning">
- <b>This rule has not yet been approved.</b> All rules need to be approved by the leaders from both systems. This rule is still missing approval from <?php
-
- if ($rule["approved"][0] === false) {
- if ($rule["approved"][1] === false) {
- echo($pcName . " and " . $prName);
- } else {
- echo($pcName);
- }
- } else if ($rule["approved"][1] === false) {
- echo($prName);
- }
-
- ?>.
- </div>
- <?php endif; ?>
- <div <?= !in_array(false, $rule["approved"]) ? 'style="margin-top:10px;"' : '' ?> class="list-group-item">
- <?= strip_tags($rule["content"]) ?>
- </div>
- </details>
- </li>
- <?php $index++; endforeach; ?>
- </ul>
- </div>
-</div>
-
-<div class="modal fade" id="editor">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <h4 class="modal-title">Rules editor</h4>
- <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
- </div>
-
- <div class="modal-body">
- <p>Rules with an empty name are automatically deleted. Buttons to add new rules and save the changes are at the bottom of the list.</p>
- <hr>
- <form method="post">
- <div id="rules-editor">
- <?php $index = 1; foreach ($rules as $rule): ?>
- <div <?= $index === 1 ? 'id="default-rule"' : '' ?>>
- <p><b <?= $index === 1 ? 'id="default-rule--number"' : '' ?>>Rule #<?= $index ?>:</b></p>
- <input <?= $index === 1 ? 'id="default-rule--name"' : '' ?> type="text" placeholder="Rule name" class="form-control" style="margin-bottom:15px;color:white;background:#111;border-color:#222;" name="payload[<?= $index - 1 ?>][name]" value="<?= str_replace('"', "&quot;", strip_tags($rule["name"])) ?>">
-
- <textarea <?= $index === 1 ? 'id="default-rule--content"' : '' ?> name="payload[<?= $index - 1 ?>][content]" class="form-control" style="resize: none;color:white;background:#111;border-color:#222;" placeholder="Rule details"><?= strip_tags($rule["content"] ?? "") ?></textarea>
-
- <label style="margin-top:10px;margin-left:5px;">
- <input <?= $index === 1 ? 'id="default-rule--approval-1"' : '' ?> <?= ($rule["approved"][0] ?? false) ? "checked" : "" ?> type="checkbox" name="payload[<?= $index - 1 ?>][approved][0]">
- Approved by <?= $pcName ?>
- </label><br>
- <label style="margin-left:5px;">
- <input <?= $index === 1 ? 'id="default-rule--approval-2"' : '' ?> <?= ($rule["approved"][1] ?? false) ? "checked" : "" ?> type="checkbox" name="payload[<?= $index - 1 ?>][approved][1]">
- Approved by <?= $prName ?>
- </label><br>
-
- <hr>
- </div>
- <?php $index++; endforeach; ?>
- </div>
- <input type="submit" value="Save" class="btn btn-primary">
- <a onclick="editorNewRule();" class="btn btn-secondary">New rule</a>
- <input type="hidden" name="updateRules">
- </form>
- </div>
- </div>
- </div>
-</div>
-
-<script>
- window.numberOfRules = <?= count($rules) ?>;
-
- Array.from(document.getElementsByClassName("rule-outer")).forEach((el) => {
- let details = el.children[0];
-
- el.onclick = () => {
- Array.from(document.getElementsByClassName("rule-outer")).forEach((sel) => {
- if (el === sel) return;
- sel.children[0].open = false;
- sel.classList.remove("open");
- });
-
- details.open = !details.open;
-
- if (details.open) {
- el.classList.add("open");
- } else {
- el.classList.remove("open");
- }
- }
- })
-
- function editorNewRule() {
- let id = Math.random(36).toString().split(".")[1];
-
- document.getElementById("default-rule").id = "added-" + id + "-1";
- document.getElementById("default-rule--number").id = "added-" + id + "-2";
- document.getElementById("default-rule--name").id = "added-" + id + "-3";
- document.getElementById("default-rule--content").id = "added-" + id + "-4";
- document.getElementById("default-rule--approval-1").id = "added-" + id + "-5";
- document.getElementById("default-rule--approval-2").id = "added-" + id + "-6";
-
- let child = document.createElement("div");
- child.id = "temp-" + id;
- window.numberOfRules++;
-
- document.getElementById("rules-editor").appendChild(child);
- document.getElementById("temp-" + id).outerHTML = document.getElementById("added-" + id + "-1").outerHTML;
-
- document.getElementById("added-" + id + "-1").id = "default-rule";
- document.getElementById("added-" + id + "-2").id = "default-rule--number";
- document.getElementById("added-" + id + "-3").id = "default-rule--name";
- document.getElementById("added-" + id + "-4").id = "default-rule--content";
- document.getElementById("added-" + id + "-5").id = "default-rule--approval-1";
- document.getElementById("added-" + id + "-6").id = "default-rule--approval-2";
-
- document.getElementById("added-" + id + "-3").name = "payload[" + (numberOfRules - 1) + "][name]";
- document.getElementById("added-" + id + "-4").name = "payload[" + (numberOfRules - 1) + "][content]";
- document.getElementById("added-" + id + "-5").name = "payload[" + (numberOfRules - 1) + "][approved][0]";
- document.getElementById("added-" + id + "-6").name = "payload[" + (numberOfRules - 1) + "][approved][1]";
-
- document.getElementById("added-" + id + "-5").checked = false;
- document.getElementById("added-" + id + "-6").checked = false;
- document.getElementById("added-" + id + "-3").value = "";
- document.getElementById("added-" + id + "-4").value = "";
- document.getElementById("added-" + id + "-2").innerText = "Rule #" + numberOfRules + ":";
- }
-</script>
-
-<style>
- .list-group-item {
- color: #fff;
- background-color: #222;
- border: 1px solid rgba(255, 255, 255, .125);
- }
-
- .list-group-item.disabled {
- color: #fff;
- background-color: #222;
- border-color: rgba(255, 255, 255, .125);
- opacity: .75;
- }
-
- .rule-outer:hover {
- background-color: #252525;
- color: #ddd;
- }
-
- .rule-outer:active, .rule-outer:focus {
- background-color: #272727;
- color: #bbb;
- }
-
- .rule-outer.open {
- background-color: #333;
- }
-
- .rule {
- list-style: none;
- pointer-events: none;
- }
-
- .rule-outer {
- cursor: pointer;
- }
-
- .modal-header {
- border-bottom: 1px solid #353738;
- }
-
- .modal-content {
- border: 1px solid rgba(255, 255, 255, .2);
- background-color: #111;
- }
-
- .btn-close {
- filter: invert(1);
- }
-</style>
-
-<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.inc'; ?>
+header("Location: /-/rules");
+die(); \ No newline at end of file
diff --git a/pages/rules.inc b/pages/rules.inc
index cf88eb1..2268e75 100644
--- a/pages/rules.inc
+++ b/pages/rules.inc
@@ -1,6 +1,40 @@
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/init.inc"; global $title; global $isLoggedIn; global $lang; global $pages;
+require_once $_SERVER['DOCUMENT_ROOT'] . "/includes/Parsedown.php"; $Parsedown = new Parsedown();
+
+if (isset($_POST["updateRules"])) {
+ header("Content-Type: text/plain");
+
+ if (!isset($_POST['payload'])) {
+ header("Location: /-/rules");
+ die();
+ }
+
+ foreach ($_POST['payload'] as $index => $rule) {
+ if (!isset($rule["name"]) || !isset($rule["content"]) && !is_numeric($index)) {
+ header("Location: /-/rules");
+ die();
+ }
+
+ if (trim($rule["name"]) === "") {
+ unset($_POST["payload"][$index]);
+ continue;
+ }
+
+ if (!isset($rule["approved"])) $rule["approved"] = [];
+ if (isset($rule["approved"][0])) $rule["approved"][0] = true; else $rule["approved"][0] = false;
+ if (isset($rule["approved"][1])) $rule["approved"][1] = true; else $rule["approved"][1] = false;
+
+ $_POST["payload"][$index] = $rule;
+ }
+
+ file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/rules/rules.json", utf8_encode(json_encode($_POST["payload"])));
+
+ header("Location: /-/rules");
+ die();
+}
+
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
?>
@@ -8,95 +42,159 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
<br>
<div class="container">
<div id="page-content">
- <h2>General rules</h2>
- <p>Click on a rule in the list to view the history of that rule, including all amendments. Note that older versions of a rule cannot be enforced anymore and are provided only for informational purposes.</p>
+ <h2>Rules</h2>
+ <p><a onclick="event.target.blur();" href="#" data-bs-toggle="modal" data-bs-target="#editor">Edit rules</a></p>
<?php
- $rules = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/rules/newrules.json"), true);
-
- $catindex = 0;
- foreach ($rules as $category): ?>
-
- <?php if ($catindex === 0): ?>
+ $rules = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] . "/includes/data/rules/rules.json"), true);
- <ul class="list-group">
- <li class="list-group-item rule-outer">
- <details>
- <summary class="rule">
- <b><?= $category['title'] ?><?php if (count($category['rules'][0]['amendments']) > 0): ?>-<?= $category['rules'][0]['amendments'][count($category['rules'][0]['amendments']) - 1]['id'] ?>:</b> <?= $category['rules'][0]['amendments'][count($category['rules'][0]['amendments']) - 1]['text'] ?><?php else: ?>:</b> <?= $category['rules'][0]['text'] ?><?php endif; ?>
- </summary>
+ $protectorCloudburst = array_values(array_filter(scoreOrderGlobal(), function ($i) {
+ return $i["_system"] === "ynmuc" && $i["_metadata"]["protector"];
+ }))[0];
+ $protectorRaindrops = array_values(array_filter(scoreOrderGlobal(), function ($i) {
+ return $i["_system"] === "gdapd" && $i["_metadata"]["protector"];
+ }))[0];
- <ul class="list-group" style="margin-top:10px;">
- <?php if (count($category['rules'][0]['amendments']) > 0): ?>
- <?php $aindex = 0; foreach (array_reverse($category['rules'][0]['amendments']) as $amendment): ?>
+ $pcName = getMiniName($protectorCloudburst["display_name"] ?? $protectorCloudburst["name"]);
+ $prName = getMiniName($protectorRaindrops["display_name"] ?? $protectorRaindrops["name"]);
- <?php if ($aindex === 0): ?>
- <li class="list-group-item"><b>Curent version:</b> <?= $amendment['text'] ?></li>
- <?php else: ?>
- <li class="list-group-item"><b>Amendment Preamble-<?= $amendment['id'] ?>:</b> <?= $amendment['text'] ?></li>
- <?php endif; ?>
+ ?>
- <?php $aindex++; endforeach; ?>
- <li class="list-group-item"><b>Original rule:</b> <?= $category['rules'][0]['text'] ?></li>
- <?php else: ?>
- <li class="list-group-item">
- <i>This rule was never amended.</i>
- </li>
- <?php endif; ?>
- </ul>
- </details>
- </li>
- </ul>
-
- <?php else:
-
- if ($category["title"] === "@punishments") {
- $catindex = "P";
- $category["title"] = "Planned punishments";
- }
-
- ?>
-
- <h4 style="margin-top: 15px;">Articles <?= $catindex ?>.1 to <?= $catindex ?>.<?= count($category['rules']) ?>: <?= $category["title"] ?></h4>
-
- <ul class="list-group">
- <?php $ruleindex = 1; foreach ($category['rules'] as $rule): ?>
- <li class="list-group-item rule-outer">
- <details>
- <summary class="rule">
- <b>Article <?= $catindex ?>.<?= $ruleindex ?><?php if (count($rule['amendments']) > 0): ?>-<?= $rule['amendments'][count($rule['amendments']) - 1]['id'] ?>:</b> <?= $rule['amendments'][count($rule['amendments']) - 1]['text'] ?><?php else: ?>:</b> <?= $rule['text'] ?><?php endif; ?>
- </summary>
-
- <ul class="list-group" style="margin-top:10px;">
- <?php if (count($rule['amendments']) > 0): ?>
- <?php $aindex = 0; foreach (array_reverse($rule['amendments']) as $amendment): ?>
-
- <?php if ($aindex === 0): ?>
- <li class="list-group-item"><b>Curent version:</b> <?= $amendment['text'] ?></li>
- <?php else: ?>
- <li class="list-group-item"><b>Amendment Preamble-<?= $amendment['id'] ?>:</b> <?= $amendment['text'] ?></li>
- <?php endif; ?>
-
- <?php $aindex++; endforeach; ?>
- <li class="list-group-item"><b>Original rule:</b> <?= $rule['text'] ?></li>
- <?php else: ?>
- <li class="list-group-item">
- <i>This rule was never amended.</i>
- </li>
+ <?php $index = 1; foreach ($rules as $rule): ?>
+ <h4 style="margin-top: 20px;">
+ <b>Rule <?= $index ?>: <?= strip_tags($rule["name"]) ?></b>
+ <?php if (in_array(false, $rule["approved"])): ?>
+ <span class="badge bg-warning text-black rounded-pill">Unapproved</span>
<?php endif; ?>
- </ul>
- </details>
+ </h4>
+ <?php if (in_array(false, $rule["approved"])): ?>
+ <div style="margin-top:10px;" class="alert alert-warning">
+ <b>This rule has not yet been approved.</b> All rules need to be approved by the leaders from both systems. This rule is still missing approval from <?php
+
+ if ($rule["approved"][0] === false) {
+ if ($rule["approved"][1] === false) {
+ echo($pcName . " and " . $prName);
+ } else {
+ echo($pcName);
+ }
+ } else if ($rule["approved"][1] === false) {
+ echo($prName);
+ }
+
+ ?>.
+ </div>
+ <?php endif; ?>
+ <div>
+ <p><?= $Parsedown->text(strip_tags($rule["content"])) ?></p>
+ </div>
</li>
- <?php $ruleindex++; endforeach; ?>
- </ul>
-
- <?php endif; ?>
+ <?php $index++; endforeach; ?>
+ </div>
+</div>
- <?php $catindex++; endforeach; ?>
+<div class="modal fade" id="editor">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title">Rules editor</h4>
+ <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
+ </div>
+
+ <div class="modal-body">
+ <p>Rules with an empty name are automatically deleted. Buttons to add new rules and save the changes are at the bottom of the list.</p>
+ <hr>
+ <form method="post">
+ <div id="rules-editor">
+ <?php $index = 1; foreach ($rules as $rule): ?>
+ <div <?= $index === 1 ? 'id="default-rule"' : '' ?>>
+ <p><b <?= $index === 1 ? 'id="default-rule--number"' : '' ?>>Rule #<?= $index ?>:</b></p>
+ <input <?= $index === 1 ? 'id="default-rule--name"' : '' ?> type="text" placeholder="Rule name" class="form-control" style="margin-bottom:15px;color:white;background:#111;border-color:#222;" name="payload[<?= $index - 1 ?>][name]" value="<?= str_replace('"', "&quot;", strip_tags($rule["name"])) ?>">
+
+ <textarea <?= $index === 1 ? 'id="default-rule--content"' : '' ?> name="payload[<?= $index - 1 ?>][content]" rows="5" class="form-control" style="resize: none;color:white;background:#111;border-color:#222;" placeholder="Rule details"><?= strip_tags($rule["content"] ?? "") ?></textarea>
+
+ <label style="margin-top:10px;margin-left:5px;">
+ <input <?= $index === 1 ? 'id="default-rule--approval-1"' : '' ?> <?= ($rule["approved"][0] ?? false) ? "checked" : "" ?> type="checkbox" name="payload[<?= $index - 1 ?>][approved][0]">
+ Approved by <?= $pcName ?>
+ </label><br>
+ <label style="margin-left:5px;">
+ <input <?= $index === 1 ? 'id="default-rule--approval-2"' : '' ?> <?= ($rule["approved"][1] ?? false) ? "checked" : "" ?> type="checkbox" name="payload[<?= $index - 1 ?>][approved][1]">
+ Approved by <?= $prName ?>
+ </label><br>
+
+ <hr>
+ </div>
+ <?php $index++; endforeach; ?>
+ </div>
+ <input type="submit" value="Save" class="btn btn-primary">
+ <a onclick="editorNewRule();" class="btn btn-secondary">New rule</a>
+ <input type="hidden" name="updateRules">
+ </form>
+ </div>
+ </div>
</div>
</div>
+<script>
+ window.numberOfRules = <?= count($rules) ?>;
+
+ Array.from(document.getElementsByClassName("rule-outer")).forEach((el) => {
+ let details = el.children[0];
+
+ el.onclick = () => {
+ Array.from(document.getElementsByClassName("rule-outer")).forEach((sel) => {
+ if (el === sel) return;
+ sel.children[0].open = false;
+ sel.classList.remove("open");
+ });
+
+ details.open = !details.open;
+
+ if (details.open) {
+ el.classList.add("open");
+ } else {
+ el.classList.remove("open");
+ }
+ }
+ })
+
+ function editorNewRule() {
+ let id = Math.random(36).toString().split(".")[1];
+
+ document.getElementById("default-rule").id = "added-" + id + "-1";
+ document.getElementById("default-rule--number").id = "added-" + id + "-2";
+ document.getElementById("default-rule--name").id = "added-" + id + "-3";
+ document.getElementById("default-rule--content").id = "added-" + id + "-4";
+ document.getElementById("default-rule--approval-1").id = "added-" + id + "-5";
+ document.getElementById("default-rule--approval-2").id = "added-" + id + "-6";
+
+ let child = document.createElement("div");
+ child.id = "temp-" + id;
+ window.numberOfRules++;
+
+ document.getElementById("rules-editor").appendChild(child);
+ document.getElementById("temp-" + id).outerHTML = document.getElementById("added-" + id + "-1").outerHTML;
+
+ document.getElementById("added-" + id + "-1").id = "default-rule";
+ document.getElementById("added-" + id + "-2").id = "default-rule--number";
+ document.getElementById("added-" + id + "-3").id = "default-rule--name";
+ document.getElementById("added-" + id + "-4").id = "default-rule--content";
+ document.getElementById("added-" + id + "-5").id = "default-rule--approval-1";
+ document.getElementById("added-" + id + "-6").id = "default-rule--approval-2";
+
+ document.getElementById("added-" + id + "-3").name = "payload[" + (numberOfRules - 1) + "][name]";
+ document.getElementById("added-" + id + "-4").name = "payload[" + (numberOfRules - 1) + "][content]";
+ document.getElementById("added-" + id + "-5").name = "payload[" + (numberOfRules - 1) + "][approved][0]";
+ document.getElementById("added-" + id + "-6").name = "payload[" + (numberOfRules - 1) + "][approved][1]";
+
+ document.getElementById("added-" + id + "-5").checked = false;
+ document.getElementById("added-" + id + "-6").checked = false;
+ document.getElementById("added-" + id + "-3").value = "";
+ document.getElementById("added-" + id + "-4").value = "";
+ document.getElementById("added-" + id + "-2").innerText = "Rule #" + numberOfRules + ":";
+ }
+</script>
+
<style>
.list-group-item {
color: #fff;
@@ -127,6 +225,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.inc';
.rule {
list-style: none;
+ pointer-events: none;
}
.rule-outer {
diff --git a/pages/stats.inc b/pages/stats.inc
index 75b9e9d..510c317 100644
--- a/pages/stats.inc
+++ b/pages/stats.inc
@@ -263,6 +263,232 @@ $switchesCloudburst = json_decode(file_get_contents($_SERVER['DOCUMENT_ROOT'] .
}
});
</script>
+
+ <h3 style="margin-top: 15px;">Average switches per day of the week</h3>
+ <canvas id="graph-01" style="width: 100%; height: 300px; max-height: 100%;"></canvas>
+ <?php
+
+ $switchesDaysRaindrops = [0, 0, 0, 0, 0, 0, 0];
+ $amountDaysRaindrops = [0, 0, 0, 0, 0, 0, 0];
+ $switchDoWRaindrops = [0, 0, 0, 0, 0, 0, 0];
+ $daysRaindrops = [];
+
+ $switchesDaysCloudburst = [0, 0, 0, 0, 0, 0, 0];
+ $amountDaysCloudburst = [0, 0, 0, 0, 0, 0, 0];
+ $switchDoWCloudburst = [0, 0, 0, 0, 0, 0, 0];
+ $daysCloudburst = [];
+
+ foreach ($switchesCloudburst as $switch) {
+ if (!in_array(date("Y-m-d", strtotime($switch["timestamp"])), $daysCloudburst)) {
+ $daysCloudburst[] = date("Y-m-d", strtotime($switch["timestamp"]));
+ $amountDaysCloudburst[(int)date('N', strtotime($switch["timestamp"])) - 1]++;
+ }
+
+ $switchesDaysCloudburst[(int)date('N', strtotime($switch["timestamp"])) - 1]++;
+ }
+
+ $switchDoWCloudburst = [
+ $switchesDaysCloudburst[0] / $amountDaysCloudburst[0],
+ $switchesDaysCloudburst[1] / $amountDaysCloudburst[1],
+ $switchesDaysCloudburst[2] / $amountDaysCloudburst[2],
+ $switchesDaysCloudburst[3] / $amountDaysCloudburst[3],
+ $switchesDaysCloudburst[4] / $amountDaysCloudburst[4],
+ $switchesDaysCloudburst[5] / $amountDaysCloudburst[5],
+ $switchesDaysCloudburst[6] / $amountDaysCloudburst[6]
+ ];
+
+ foreach ($switchesRaindrops as $switch) {
+ if (!in_array(date("Y-m-d", strtotime($switch["timestamp"])), $daysRaindrops)) {
+ $daysRaindrops[] = date("Y-m-d", strtotime($switch["timestamp"]));
+ $amountDaysRaindrops[(int)date('N', strtotime($switch["timestamp"])) - 1]++;
+ }
+
+ $switchesDaysRaindrops[(int)date('N', strtotime($switch["timestamp"])) - 1]++;
+ }
+
+ $switchDoWRaindrops = [
+ $switchesDaysRaindrops[0] / $amountDaysRaindrops[0],
+ $switchesDaysRaindrops[1] / $amountDaysRaindrops[1],
+ $switchesDaysRaindrops[2] / $amountDaysRaindrops[2],
+ $switchesDaysRaindrops[3] / $amountDaysRaindrops[3],
+ $switchesDaysRaindrops[4] / $amountDaysRaindrops[4],
+ $switchesDaysRaindrops[5] / $amountDaysRaindrops[5],
+ $switchesDaysRaindrops[6] / $amountDaysRaindrops[6]
+ ];
+
+ $switchDoW = [
+ $switchDoWCloudburst[0] + $switchDoWRaindrops[0],
+ $switchDoWCloudburst[1] + $switchDoWRaindrops[1],
+ $switchDoWCloudburst[2] + $switchDoWRaindrops[2],
+ $switchDoWCloudburst[3] + $switchDoWRaindrops[3],
+ $switchDoWCloudburst[4] + $switchDoWRaindrops[4],
+ $switchDoWCloudburst[5] + $switchDoWRaindrops[5],
+ $switchDoWCloudburst[6] + $switchDoWRaindrops[6]
+ ];
+
+ ?>
+ <script>
+ const ctx1 = document.getElementById('graph-01').getContext('2d');
+ window.chart01 = [
+ {
+ label: "Switches per week",
+ data: JSON.parse(`<?= json_encode($switchDoW) ?>`),
+ backgroundColor: [
+ 'rgba(255, 99, 132, 0.2)',
+ 'rgba(255, 159, 64, 0.2)',
+ 'rgba(255, 205, 86, 0.2)',
+ 'rgba(75, 192, 192, 0.2)',
+ 'rgba(54, 162, 235, 0.2)',
+ 'rgba(153, 102, 255, 0.2)',
+ 'rgba(201, 203, 207, 0.2)'
+ ],
+ borderColor: [
+ 'rgb(255, 99, 132)',
+ 'rgb(255, 159, 64)',
+ 'rgb(255, 205, 86)',
+ 'rgb(75, 192, 192)',
+ 'rgb(54, 162, 235)',
+ 'rgb(153, 102, 255)',
+ 'rgb(201, 203, 207)'
+ ],
+ borderWidth: 1
+ }
+ ];
+ const graph1 = new Chart(ctx1, {
+ type: 'bar',
+ data: {
+ labels: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"],
+ datasets: window.chart01
+ },
+ options: {
+ animation: {
+ duration: 0
+ },
+ scales: {
+ y: {
+ grid: {
+ color: "rgba(255,255,255,0.25)"
+ }
+ }
+ },
+ plugins: {
+ legend: {
+ display: false
+ },
+ tooltip: {
+ intersect: false
+ }
+ }
+ }
+ });
+ </script>
+
+ <h3 style="margin-top: 15px;">Switches per hour of the day</h3>
+ <canvas id="graph-02" style="width: 100%; height: 300px; max-height: 100%;"></canvas>
+ <?php
+
+ $switchHoursRaindrops = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+ $switchHoursCloudburst = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+ foreach ($switchesCloudburst as $switch) {
+ $switchHoursCloudburst[(int)date('G', strtotime($switch["timestamp"]))]++;
+ }
+
+ foreach ($switchesRaindrops as $switch) {
+ $switchHoursRaindrops[(int)date('G', strtotime($switch["timestamp"]))]++;
+ }
+
+ $switchHours = [
+ $switchHoursRaindrops[0] + $switchHoursCloudburst[0],
+ $switchHoursRaindrops[1] + $switchHoursCloudburst[1],
+ $switchHoursRaindrops[2] + $switchHoursCloudburst[2],
+ $switchHoursRaindrops[3] + $switchHoursCloudburst[3],
+ $switchHoursRaindrops[4] + $switchHoursCloudburst[4],
+ $switchHoursRaindrops[5] + $switchHoursCloudburst[5],
+ $switchHoursRaindrops[6] + $switchHoursCloudburst[6],
+ $switchHoursRaindrops[7] + $switchHoursCloudburst[7],
+ $switchHoursRaindrops[8] + $switchHoursCloudburst[8],
+ $switchHoursRaindrops[9] + $switchHoursCloudburst[9],
+ $switchHoursRaindrops[10] + $switchHoursCloudburst[10],
+ $switchHoursRaindrops[11] + $switchHoursCloudburst[11],
+ $switchHoursRaindrops[12] + $switchHoursCloudburst[12],
+ $switchHoursRaindrops[13] + $switchHoursCloudburst[13],
+ $switchHoursRaindrops[14] + $switchHoursCloudburst[14],
+ $switchHoursRaindrops[15] + $switchHoursCloudburst[15],
+ $switchHoursRaindrops[16] + $switchHoursCloudburst[16],
+ $switchHoursRaindrops[17] + $switchHoursCloudburst[17],
+ $switchHoursRaindrops[18] + $switchHoursCloudburst[18],
+ $switchHoursRaindrops[19] + $switchHoursCloudburst[19],
+ $switchHoursRaindrops[20] + $switchHoursCloudburst[20],
+ $switchHoursRaindrops[21] + $switchHoursCloudburst[21],
+ $switchHoursRaindrops[22] + $switchHoursCloudburst[22],
+ $switchHoursRaindrops[23] + $switchHoursCloudburst[23],
+ ];
+
+ ?>
+ <script>
+ const ctx2 = document.getElementById('graph-02').getContext('2d');
+ window.chart02 = [
+ {
+ label: "Switches per hour of day",
+ data: JSON.parse(`<?= json_encode($switchHours) ?>`),
+ borderColor: "rgb(160,255,153)"
+ }
+ ];
+ const graph2 = new Chart(ctx2, {
+ type: 'line',
+ data: {
+ labels: [
+ "12am",
+ "1am",
+ "2am",
+ "3am",
+ "4am",
+ "5am",
+ "6am",
+ "7am",
+ "8am",
+ "9am",
+ "10am",
+ "11am",
+ "12pm",
+ "1pm",
+ "2pm",
+ "3pm",
+ "4pm",
+ "5pm",
+ "6pm",
+ "7pm",
+ "8pm",
+ "9pm",
+ "10pm",
+ "11pm"
+ ],
+ datasets: window.chart02
+ },
+ options: {
+ animation: {
+ duration: 0
+ },
+ scales: {
+ y: {
+ beginAtZero: true,
+ grid: {
+ color: "rgba(255,255,255,0.25)"
+ }
+ }
+ },
+ plugins: {
+ legend: {
+ display: false
+ },
+ tooltip: {
+ intersect: false
+ }
+ }
+ }
+ });
+ </script>
</div>
</div>
diff --git a/spec.md b/spec.md
deleted file mode 100644
index 43195f1..0000000
--- a/spec.md
+++ /dev/null
@@ -1,253 +0,0 @@
-# ponies.equestria.horse
-
-## Metadata Bits
-48bit bitsets are now used to define metadata that doesn't require a string input, they were 24bit in the past but were changed to 48bit after adding additional metadata. A lot of reserved values remain for future use.
-
-```
-...............0................................
- => Is mostly verbal in real life.
-
-...............1................................
- => Is mostly non verbal in real life.
-
-..............0.................................
- => Fronts frequently.
-
-..............1.................................
- => Fronts less frequently.
-
-.............0..................................
- => Is not sexually active.
-
-.............1..................................
- => Is sexually active.
-
-................00..............................
- => Doesn't need to eat food.
-
-................01..............................
- => Can't eat fish or meat.
-
-................10..............................
- => Can't eat meat.
-
-................11..............................
- => Can eat everything.
-
-..................000...........................
- => Can't use magic at all.
-
-..................001...........................
- => Magic in some cases.
-
-..................010...........................
- => Magic using a horn.
-
-..................011...........................
- => Magic using wings.
-
-..................100...........................
- => Magic using wings + horn.
-
-..................101...........................
- => Magic using another part.
-
-.....................000........................
- => Does not have sensitive spots at all.
-
-.....................001........................
- => May have one or more sensitive spot·s.
-
-.....................010........................
- => Has affectionately sensitive spots.
-
-.....................011........................
- => Has sexually sensitive spots.
-
-.....................100........................
- => Has both types of sensitive spots
-
-........................00......................
- => No direct shared memory.
-
-........................01......................
- => Partial direct shared memory.
-
-........................10......................
- => Full direct shared memory.
-
-..........................0.....................
- => Not part of a median system.
-
-..........................1.....................
- => Part of a median system.
-
-...........................00...................
- => Not a little.
-
-...........................01...................
- => Age regressor.
-
-...........................10...................
- => Little.
-
-...........................11...................
- => Not a little, but younger.
-
-.............................0..................
- => Not a protector.
-
-.............................1..................
- => Protector.
-
-..............................0.................
- => Not a fictive.
-
-..............................1.................
- => Fictive.
-
-...............................0................
- => No "Not talking" attribute.
-
-...............................1................
- => "Not talking" attribute.
-
-................................0...............
- => Not an host.
-
-................................1...............
- => Host.
-
-.............................................0..
- => Not a robot
-
-.............................................1..
- => Robot
-
-..............................................0.
- => Not a plush
-
-..............................................1.
- => Plush
-
-...............................................0
- => Not affected by age spells
-
-...............................................1
- => Affected by age spells
-
-.................................0001...........
- => 1st species: Earth pony.
-
-.................................0010...........
- => 1st species: Unicorn.
-
-.................................0011...........
- => 1st species: Pegasus.
-
-.................................0100...........
- => 1st species: Alicorn.
-
-.................................0101...........
- => 1st species: Bat pony.
-
-.................................0110...........
- => 1st species: Crystal pony.
-
-.....................................0000.......
- => 2nd species: <none>
-
-.....................................0001.......
- => 2nd species: Earth pony.
-
-.....................................0010.......
- => 2nd species: Unicorn.
-
-.....................................0011.......
- => 2nd species: Pegasus.
-
-.....................................0100.......
- => 2nd species: Alicorn.
-
-.....................................0101.......
- => 2nd species: Bat pony.
-
-.....................................0110.......
- => 2nd species: Crystal pony.
-
-.........................................0000...
- => 3rd species: <none>
-
-.........................................0001...
- => 3rd species: Earth pony.
-
-.........................................0010...
- => 3rd species: Unicorn.
-
-.........................................0011...
- => 3rd species: Pegasus.
-
-.........................................0100...
- => 3rd species: Alicorn.
-
-.........................................0101...
- => 3rd species: Bat pony.
-
-.........................................0110...
- => 3rd species: Crystal pony.
-
-```
-<details>
-<summary>List of reserved bits</summary>
-
-The following bits are reserved for future use or for technical reasons:
-```
-xxxxxxxxxxxxxxxx................................ <(1)>
-..................110........................... <(2)>
-..................111........................... <(2)>
-.....................101........................ <(2)>
-.....................110........................ <(2)>
-.....................111........................ <(2)>
-........................11...................... <(2)>
-...........................11................... <(2)>
-.................................0000........... <(3)>
-.................................0111........... <(3)>
-.................................1000........... <(3)>
-.................................1001........... <(3)>
-.................................1010........... <(3)>
-.................................1011........... <(3)>
-.................................1100........... <(3)>
-.................................1101........... <(3)>
-.................................1110........... <(3)>
-.................................1111........... <(3)>
-.....................................0111....... <(3)>
-.....................................1000....... <(3)>
-.....................................1001....... <(3)>
-.....................................1010....... <(3)>
-.....................................1011....... <(3)>
-.....................................1100....... <(3)>
-.....................................1101....... <(3)>
-.....................................1110....... <(3)>
-.....................................1111....... <(3)>
-.........................................0111... <(3)>
-.........................................1000... <(3)>
-.........................................1001... <(3)>
-.........................................1010... <(3)>
-.........................................1011... <(3)>
-.........................................1100... <(3)>
-.........................................1101... <(3)>
-.........................................1110... <(3)>
-.........................................1111... <(3)>
-...............................................0 <(4)>
-...............................................1 <(4)>
-```
-
-`(1)` Reserved for extended metadata<br>
-`(2)` Reserved for additional value state<br>
-`(3)` Reserved for additional supported species<br>
-`(4)` Reserved for additional metadata
-
-</details>
-
-The minimum value of the bitset is 0 and the maximum value 281474976710655.
-For example, for Scoots, the value would be `000000000000000000000000100010101010000110000000` (9085312) \ No newline at end of file