Compare commits

..

No commits in common. "b0ab6a4f5b2f974d29ecfbf2c095ced06c4a59c6" and "6bbb6926da499af292962ec395c299f0de1236be" have entirely different histories.

13 changed files with 22 additions and 327 deletions

View file

@ -5,5 +5,4 @@ pass = ""
[databases]
vlw = ""
playground = ""
battlestation = ""

View file

@ -1,40 +0,0 @@
<?php
use Reflect\Path;
use Reflect\Response;
use ReflectRules\Type;
use ReflectRules\Rules;
use ReflectRules\Ruleset;
use const VLW\API\RESP_DELETE_OK;
use VLW\API\Databases\VLWdb\{
VLWdb,
Databases
};
use VLW\API\Databases\VLWdb\Models\Playground\Coffee\CoffeeModel;
require_once Path::root("src/databases/VLWdb.php");
require_once Path::root("src/databases/models/Playground/Coffee/Coffee.php");
class DELETE_PlaygroundCoffee extends VLWdb {
protected Ruleset $ruleset;
public function __construct() {
parent::__construct();
$this->ruleset = new Ruleset(strict: true);
$this->ruleset->GET([
(new Rules(CoffeeModel::ID->value))
->required()
->type(Type::NUMBER)
]);
parent::__construct(Databases::PLAYGROUND, $this->ruleset);
}
public function main(): Response {
return $this->db->for(WorkActionsModel::TABLE)->delete($_POST) === true
? new Response(RESP_DELETE_OK)
: new Response("D:", 500);
}
}

View file

@ -1,40 +0,0 @@
<?php
use Reflect\Path;
use Reflect\Response;
use ReflectRules\Type;
use ReflectRules\Rules;
use ReflectRules\Ruleset;
use VLW\API\Databases\VLWdb\{
VLWdb,
Databases
};
use VLW\API\Databases\VLWdb\Models\Playground\Coffee\CoffeeModel;
require_once Path::root("src/databases/VLWdb.php");
require_once Path::root("src/databases/models/Playground/Coffee/Coffee.php");
class GET_PlaygroundCoffee extends VLWdb {
protected Ruleset $ruleset;
public function __construct() {
$this->ruleset = new Ruleset(strict: true);
parent::__construct(Databases::PLAYGROUND, $this->ruleset);
}
public function main(): Response {
$result = $this->db
->for(CoffeeModel::TABLE)
->order([CoffeeModel::ID->value => "DESC"])
->select([
CoffeeModel::ID->value
]);
return $result->num_rows > 0
// Return entries as sequential array of integer timestamps
? new Response(array_map(fn(array $value): int => $value[0], $result->fetch_all(MYSQLI_NUM)))
: new Response([], 404);
}
}

View file

@ -1,38 +0,0 @@
<?php
use Reflect\Path;
use Reflect\Response;
use ReflectRules\Type;
use ReflectRules\Rules;
use ReflectRules\Ruleset;
use VLW\API\Databases\VLWdb\{
VLWdb,
Databases
};
use VLW\API\Databases\VLWdb\Models\Playground\Coffee\CoffeeModel;
require_once Path::root("src/databases/VLWdb.php");
require_once Path::root("src/databases/models/Playground/Coffee/Coffee.php");
class POST_PlaygroundCoffee extends VLWdb {
protected Ruleset $ruleset;
public function __construct() {
$this->ruleset = new Ruleset(strict: true);
$this->ruleset->GET([
(new Rules(CoffeeModel::ID->value))
->type(Type::NUMBER)
->default(time())
]);
parent::__construct(Databases::PLAYGROUND, $this->ruleset);
}
public function main(): Response {
return $this->db->for(CoffeeModel::TABLE)->insert($_POST) === true
? new Response($_POST[CoffeeModel::ID->value], 201)
: new Response(":(", 500);
}
}

View file

@ -15,8 +15,6 @@
case WORK_TAGS = "/work/tags";
case WORK_ACTIONS = "/work/actions";
case PLAYGROUND_COFFEE = "/playground/coffee";
case BATTLESTATION = "/battlestation";
case BATTLESTATION_MB = "/battlestation/mb";
case BATTLESTATION_CPU = "/battlestation/cpu";

View file

@ -11,7 +11,6 @@
enum Databases: string {
case VLW = "vlw";
case PLAYGROUND = "playground";
case BATTLESTATION = "battlestation";
}

View file

@ -1,9 +0,0 @@
<?php
namespace VLW\API\Databases\VLWdb\Models\Playground\Coffee;
enum CoffeeModel: string {
const TABLE = "coffee";
case ID = "id";
}

View file

@ -20,8 +20,6 @@ header {
}
img {
user-select: none;
pointer-events: none;
image-rendering: pixelated;
}
@ -30,20 +28,20 @@ img {
/* ## Title */
section.title {
gap: var(--padding);
display: grid;
align-items: center;
justify-items: center;
min-height: 50vw;
grid-template-columns: repeat(5, 1fr);
padding-bottom: var(--padding);
grid-template-columns: repeat(10, 1fr);
min-height: 30vh;
}
section.title img {
--outline-width: 5px;
--outline-color: black;
width: 10vw;
transform: translateY(-1vw);
width: 100%;
transform: translateY(-10px);
animation: bouncy 1s infinite alternate ease-in-out;
filter:
drop-shadow(0 10px 0 blue)
@ -55,47 +53,17 @@ section.title img {
}
@keyframes bouncy {
25% { transform: translateY(0); }
100% { transform: translateY(0); }
}
/* ### Super Secret Settings */
section.sss {
border-radius: 6px;
padding: var(--padding);
margin: var(--padding) 0;
background-color: rgba(255, 255, 255, .1);
}
section.sss button {
margin-top: var(--padding);
25% { transform: translateY(10px); }
100% { transform: translateY(10px); }
}
/* ## Coffee */
section.coffee {
display: grid;
gap: var(--padding);
grid-template-columns: 100px 1fr;
}
section.coffee img {
width: 100%;
}
/* # Size queries */
@media (min-width: 700px) {
section.title {
gap: var(--padding);
margin: 50px 0;
min-height: unset;
grid-template-columns: repeat(10, 1fr);
}
section.title img {
width: 100%;
transform: translateY(-10px);
}
height: 100%;
}

View file

@ -1,11 +1,9 @@
/* # Sections */
super-secret-settings {
--border-width: 5px;
position: fixed;
top: var(--border-width);
left: var(--border-width);
top: 5px;
left: 5px;
width: 400px;
fill: white;
color: white;
@ -13,8 +11,8 @@ super-secret-settings {
border: solid 1px white;
background-color: rgb(0, 102, 204);
box-shadow:
0 0 0 var(--border-width) black,
0 0 40px calc(var(--border-width) * 2) rgba(0, 0, 0, .4);
0 0 0 5px black,
0 0 40px 10px rgba(0, 0, 0, .4);
}
/* ## Header */
@ -22,15 +20,12 @@ super-secret-settings {
super-secret-settings section.header {
display: grid;
align-items: center;
border-bottom: solid 1px white;
grid-template-columns: 1fr repeat(2, var(--running-size));
height: var(--running-size);
cursor: grab;
}
super-secret-settings:not(.collapsed) section.header {
border-bottom: solid 1px white;
}
super-secret-settings section.header:active {
cursor: grabbing;
}
@ -47,30 +42,11 @@ super-secret-settings section.header svg {
super-secret-settings section.header button {
height: 100%;
border-left: solid 1px white;
}
super-secret-settings.collapsed section.header button.collapse svg {
transform: rotate(-90deg);
border-left: solid 1px var(--border-color);
}
/* ## Body */
super-secret-settings section.body {
padding: var(--padding);
}
super-secret-settings.collapsed section.body {
display: none;
}
/* # Size queries */
@media not (hover: hover), (max-width: 900px) {
super-secret-settings {
top: unset;
bottom: 5px;
width: calc(100% - (var(--border-width) * 2));
transform: translate(0, 0) !important;
}
}

View file

@ -1,6 +1,6 @@
import { Elevent } from "/assets/js/modules/npm/Elevent.mjs";
new Elevent("click", document.querySelector("section.sss button"), (event) => {
new Elevent("click", document.querySelector("section.sss button"), () => {
const SSS_TAG_NAME = "super-secret-settings";
let sssElement = document.querySelector(SSS_TAG_NAME);
@ -11,13 +11,6 @@ new Elevent("click", document.querySelector("section.sss button"), (event) => {
document.body.appendChild(sssElement);
}
const size = event.target.getBoundingClientRect();
// Set initial window position above button
const y = size.top;
const x = size.left + size.width;
sssElement.style.transform = `translate(${x}px, ${y}px)`
// Navigate SSS element to playground page
new vegvisir.Navigation("/playground/super-secret-settings").navigate(sssElement);
});

View file

@ -8,7 +8,6 @@ const clampRight = (window.innerWidth - sssElement._size.width) - (borderWidth *
const clampBottom = (window.innerHeight - sssElement._size.height) - (borderWidth * 3);
const moveWindow = new Elevent("mousemove", null, (event) => {
// Clamp window to viewport
const y = Math.max(borderWidth, Math.min(clampBottom, (event.clientY - 40)));
const x = Math.max(borderWidth, Math.min(clampRight, event.clientX - (sssElement._size.width / 2)));
@ -35,5 +34,4 @@ new Elevent("mousedown", sssElement.querySelector(".header"), (event) => {
});
});
new Elevent("click", sssElement.querySelector(".header button.close"), () => sssElement.remove());
new Elevent("click", sssElement.querySelector(".header button.collapse"), () => sssElement.classList.toggle("collapsed"));
new Elevent("click", sssElement.querySelector(".header button"), () => sssElement.remove());

View file

@ -1,129 +1,20 @@
<?php
use Reflect\Response;
use VLW\Client\API;
use VLW\API\Endpoints;
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
require_once VV::root("src/client/API.php");
require_once VV::root("api/src/Endpoints.php");
function to_plural(int $value): string {
return $value !== 1 ? "s" : "";
}
$time = new class extends DateTimeImmutable {
public function __construct() {
parent::__construct("now", new DateTimeZone($_ENV["time"]["date_time_zone"]));
}
public function hours(): int {
return (int) $this->format("G");
}
public function minutes(): int {
return (int) $this->format("i");
}
public function since_midnight_str(): string {
$hours = $this->hours();
$minutes = $this->minutes();
// Show minutes if we're not into the first hour yet
if ($hours < 1) {
return $minutes . " minute" . to_plural($minutes);
}
// Round up to the nearest hour
return ($minutes < 45 ? $hours : $hours + 1) . " hour" . to_plural($hours);
}
};
$coffee = new class extends API {
const THRESHOLDS = [
[-10, "a lot less than"],
[-5, "a bit less than"],
[0, "average"],
[5, "a bit more than"],
[10, "a lot more than"]
];
private readonly int $now;
private readonly Response $resp;
public function __construct() {
parent::__construct();
$this->now = time();
$this->resp = $this->call(Endpoints::PLAYGROUND_COFFEE->value)->get();
}
private function get_until_timestamp(int $offset = 0): array {
return array_filter($this->resp->json(), fn(int $timestamp): int => $timestamp > $offset);
}
private function get_average_month(): int {
$days = [0];
foreach ($this->get_until_timestamp(2592000) as $timestamp) {
// Append new value for next 24 hours
if ($timestamp % 86400 === 0) {
$days[] = 0;
}
$days[count($days) - 1]++;
}
// Count the average for each day
return array_sum($days) / count($days);
}
// Return the number of cups within the last 24 hours
public function get_today(): int {
return $this->resp->ok ? count($this->get_until_timestamp(86400)) : 0;
}
public function get_average_month_str(): string {
$diff = $this->get_today() - $this->get_average_month();
// Check diff of today against monthyl average thresholds
foreach (self::THRESHOLDS as $threshold) {
[$limit, $msg] = $threshold;
// Bail out if diff is less than threshold limit
if ($diff < $limit) {
return $msg;
}
}
// Return last entry if diff is more than last threshold limit
return self::THRESHOLDS[count(self::THRESHOLDS) - 1][1];
}
};
?>
<style><?= VV::css("public/assets/css/pages/playground/index") ?></style>
<section class="title">
<!-- I was listening to https://www.youtube.com/watch?v=DsUb4Lq6DBE when I made the dancing letters -->
<?php // I was listening to https://www.youtube.com/watch?v=DsUb4Lq6DBE when I made the dancing letters ?>
<?php foreach (str_split("playground") as $idx => $char): ?>
<img src="data:image/gif;base64,<?= base64_encode(VV::embed("public/assets/media/playground/{$char}.gif")) ?>" style="animation-delay:<?= ($idx % rand(2, 4)) * 500 ?>ms">
<?php endforeach; ?>
</section>
<section class="sss">
<h1>I'm so bored.</h1>
<p>Don't like the way my website looks? These oficially very Super Secret Settings<sup><a href="https://minecraft-archive.fandom.com/wiki/Super_Secret_Settings">&#8482;</a></sup> will give you something else to look at!</p>
<button class="inline">Try it</button>
<button class="inline">Super Secret Settings</button>
</section>
<section class="coffee">
<img src="data:image/gif;base64,<?= base64_encode(VV::embed("public/assets/media/playground/coffee.gif")) ?>">
<div>
<h1>What else.. I've had <?= $coffee->get_today() ?> cup<?= to_plural($coffee->get_today()) ?> of coffee today!</h1>
<p>That's <?= $coffee->get_average_month_str() ?> the daily average for me (last 30 days). Here I'm counting how many ~300ml cups of coffee I've had since midnight for my timezone <?= $_ENV["time"]["date_time_zone"] ?>, that was <?= $time->since_midnight_str() ?> ago.</p>
<p>How much coffee is enough coffee? <a href="<?= $_ENV["api"]["base_url"] . Endpoints::PLAYGROUND_COFFEE->value ?>">Click here to see my answer!!</a> (NOT CLICKBAIT). Each array value is a UNIX timestamp that represents a single cup of coffee.</p>
<h1>How much coffee is enough coffee?</h1>
<p>Woah, I 've had 4 cups of coffee today (counting from and to midnight). That's about the average amount for me (from the last 30 days)</p>
</div>
</section>
<script type="module"><?= VV::js("public/assets/js/pages/playground/index") ?></script>

View file

@ -1,8 +1,8 @@
<style><?= VV::css("public/assets/css/pages/playground/super-secret-settings") ?></style>
<section class="header">
<p>Super Secret Settings</p>
<button class="collapse"><?= VV::embed("public/assets/media/icons/chevron.svg") ?></button>
<button class="close"><?= VV::embed("public/assets/media/icons/close.svg") ?></button>
<button><?= VV::embed("public/assets/media/icons/chevron.svg") ?></button>
<button><?= VV::embed("public/assets/media/icons/close.svg") ?></button>
</section>
<section class="body">
<p>Do you have what it takes to click this button?</p>