summaryrefslogtreecommitdiff
path: root/views/http
diff options
context:
space:
mode:
authorDaniel Weipert <git@mail.dweipert.de>2024-01-02 20:42:01 +0100
committerDaniel Weipert <git@mail.dweipert.de>2024-01-05 12:33:59 +0100
commitb21316248572cb27ed1f504529ad6680a473022e (patch)
treef8a2f81258cae3b1d2429fb7df5a3287954b683a /views/http
parentf621d95f89ded05a2e916c5ee363bfe75ea37482 (diff)
gemini
Diffstat (limited to 'views/http')
-rw-r--r--views/http/base.twig32
-rw-r--r--views/http/components/timer.twig26
-rw-r--r--views/http/error.twig8
-rw-r--r--views/http/login.twig17
-rw-r--r--views/http/map.twig42
-rw-r--r--views/http/root.twig12
-rw-r--r--views/http/village.twig361
-rw-r--r--views/http/villages.twig38
8 files changed, 536 insertions, 0 deletions
diff --git a/views/http/base.twig b/views/http/base.twig
new file mode 100644
index 0000000..15ddafd
--- /dev/null
+++ b/views/http/base.twig
@@ -0,0 +1,32 @@
+{% extends 'root.twig' %}
+
+{% block body %}
+<div class="wrap">
+ <header>
+ <nav>
+ <a href="/villages">Overview</a>
+ <a href="/logout">Logout</a>
+ </nav>
+ <span>Logged in as {{ session.user.username }}</span>
+ </header>
+
+ <main>
+ {% block main %}{% endblock %}
+ </main>
+
+ <footer></footer>
+
+ <div class="global-timer"></div>
+ <script>
+ const timer = document.querySelectorAll('.global-timer');
+ function setTime () {
+ const now = new Date();
+ for (const t of timer) {
+ t.innerHTML = now;
+ }
+ }
+ setTime();
+ setInterval(setTime, 1000);
+ </script>
+</div>
+{% endblock %}
diff --git a/views/http/components/timer.twig b/views/http/components/timer.twig
new file mode 100644
index 0000000..ccb31a7
--- /dev/null
+++ b/views/http/components/timer.twig
@@ -0,0 +1,26 @@
+<span class="timer" data-time="{{ time }}">
+ <span class="timer__time"></span>
+</span>
+<script>
+document.addEventListener('DOMContentLoaded', function (ev) {
+ const timer = document.querySelector('.timer[data-time="{{ time }}"] .timer__time');
+ const time = new Date('{{ time }}');
+
+ const interval = setInterval(setTime, 1000);
+ function setTime() {
+ let diff = time - new Date();
+ if (diff <= 0) {
+ clearInterval(interval);
+ window.location.reload();
+ }
+
+ const hh = Math.floor(diff/1000/60/60);
+ diff -= hh*1000*60*60;
+ const mm = Math.floor(diff/1000/60);
+ diff -= mm*1000*60;
+ const ss = Math.floor(diff/1000);
+ timer.innerHTML = `${('00' + hh).slice(-2)}:${('00' + mm).slice(-2)}:${('00' + ss).slice(-2)}`;
+ }
+ setTime();
+});
+</script>
diff --git a/views/http/error.twig b/views/http/error.twig
new file mode 100644
index 0000000..f9d70cd
--- /dev/null
+++ b/views/http/error.twig
@@ -0,0 +1,8 @@
+{% extends 'root.twig' %}
+
+{% block body %}
+<div class="wrap">
+ {{ message }}
+ <a href="javascript:history.back()">Back</a>
+</div>
+{% endblock %}
diff --git a/views/http/login.twig b/views/http/login.twig
new file mode 100644
index 0000000..723d5d2
--- /dev/null
+++ b/views/http/login.twig
@@ -0,0 +1,17 @@
+{% extends 'root.twig' %}
+
+{% block body %}
+<div class="wrap">
+ <form action="/login" method="post">
+ <label>
+ E-Mail:
+ <input type="text" name="email" placeholder="or Username">
+ </label>
+ <label>
+ Password:
+ <input type="password" name="password">
+ </label>
+ <button>Login</button>
+ </form>
+</div>
+{% endblock %}
diff --git a/views/http/map.twig b/views/http/map.twig
new file mode 100644
index 0000000..29f0294
--- /dev/null
+++ b/views/http/map.twig
@@ -0,0 +1,42 @@
+{% extends 'base.twig' %}
+
+{% block main %}
+<div class="map">
+ <div class="map__up">
+ <a href="/map/{{ x }}/{{ y - 1 }}">
+ <i class="icon icon-arrow-up"></i>
+ </a>
+ </div>
+ <div>
+ <div class="map__left">
+ <a href="/map/{{ x - 1 }}/{{ y }}">
+ <i class="icon icon-arrow-left"></i>
+ </a>
+ </div>
+ <div class="map__villages" style="grid-template-columns: repeat({{ range*2+1 }}, 1fr); grid-template-rows: repeat({{ range*2+1 }}, 1fr);">
+ {% for row in range(-range, range) %}
+ {% for column in range(-range, range) %}
+ {% set village = map[x + column][y + row] %}
+ <div class="map__village">
+ {% if village %}
+ <a href="/village/{{ village.x }}/{{ village.y }}">
+ {{ map[x + column][y + row].name }}
+ </a>
+ {% endif %}
+ </div>
+ {% endfor %}
+ {% endfor %}
+ </div>
+ <div class="map__right">
+ <a href="/map/{{ x + 1 }}/{{ y }}">
+ <i class="icon icon-arrow-right"></i>
+ </a>
+ </div>
+ </div>
+ <div class="map__down">
+ <a href="/map/{{ x }}/{{ y + 1 }}">
+ <i class="icon icon-arrow-down"></i>
+ </a>
+ </div>
+</div>
+{% endblock %}
diff --git a/views/http/root.twig b/views/http/root.twig
new file mode 100644
index 0000000..35399c0
--- /dev/null
+++ b/views/http/root.twig
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <link rel="stylesheet" href="/assets/style.css">
+</head>
+<body>
+ {% block body %}{% endblock %}
+</body>
+</html>
diff --git a/views/http/village.twig b/views/http/village.twig
new file mode 100644
index 0000000..c72018c
--- /dev/null
+++ b/views/http/village.twig
@@ -0,0 +1,361 @@
+{% extends 'base.twig' %}
+
+{% block main %}
+<div class="village">
+
+ <div class="village__top">
+ <div>
+ <span>
+ <a href="/map/{{ village.x }}/{{ village.y }}">
+ {{ village.x }} x {{ village.y }}
+ </a>
+ </span>
+ &mdash;
+ {{ village.name }}
+ </div>
+
+ <div class="resources">
+ <div>
+ <i class="icon icon-wood"></i>
+ <span>{{ village.wood }} / {{ village.getStorage(village.id).getResourceCapacity('wood') }}</span>
+ <i class="icon icon-per-increment"></i>
+ <span>{{ village.getBuilding(village.id, 'WoodCutter').getResourceIncrementor() }}</span>
+ </div>
+ <div>
+ <i class="icon icon-clay"></i>
+ <span>{{ village.clay }} / {{ village.getStorage(village.id).getResourceCapacity('clay') }}</span>
+ <i class="icon icon-per-increment"></i>
+ <span>{{ village.getBuilding(village.id, 'ClayPit').getResourceIncrementor() }}</span>
+ </div>
+ <div>
+ <i class="icon icon-iron"></i>
+ <span>{{ village.iron }} / {{ village.getStorage(village.id).getResourceCapacity('iron') }}</span>
+ <i class="icon icon-per-increment"></i>
+ <span>{{ village.getBuilding(village.id, 'IronMine').getResourceIncrementor() }}</span>
+ </div>
+ <div>
+ <i class="icon icon-food"></i>
+ <span>{{ village.food }} / {{ village.getStorage(village.id).getResourceCapacity('food') }}</span>
+ <i class="icon icon-per-increment"></i>
+ <span>{{ village.getBuilding(village.id, 'Farm').getResourceIncrementor() }}</span>
+ </div>
+
+ <div onclick="javascript:this.nextElementSibling.showModal()">
+ <i class="icon icon-storage"></i>
+ <span>{{ village.getStorage(village.id).getCapacity() }}</span>
+ </div>
+ <dialog>
+ <button onclick="javascript:this.parentNode.close()">Close</button>
+ <h3 align="center">Storage Config</h3>
+ <form method="post" action="/village/{{ village.x }}/{{ village.y }}/storage/config">
+ <label>
+ <i class="icon icon-wood"></i>
+ <input type="text" name="wood" value="{{ village.getStorageConfig(village.id).wood }}">
+ </label>
+ <label>
+ <i class="icon icon-clay"></i>
+ <input type="text" name="clay" value="{{ village.getStorageConfig(village.id).clay }}">
+ </label>
+ <label>
+ <i class="icon icon-iron"></i>
+ <input type="text" name="iron" value="{{ village.getStorageConfig(village.id).iron }}">
+ </label>
+ <label>
+ <i class="icon icon-food"></i>
+ <input type="text" name="food" value="{{ village.getStorageConfig(village.id).food }}">
+ </label>
+ <button>Save</button>
+ </form>
+ </dialog>
+ </div>
+ </div>
+
+ <div class="village__events">
+ <h3>Events</h3>
+
+ {% if events['UpgradeBuilding'] %}
+ <h4>Upgrade Buildings</h4>
+ <table>
+ <thead>
+ <tr>
+ <th>Building</th>
+ <th>Time</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for typeEvents in events['UpgradeBuilding'] %}
+ {% for event in typeEvents %}
+ <tr>
+ <td>{{ event.type }}</td>
+ <td class="timer">
+ {% include 'components/timer.twig' with { 'time': event.event.time|date('c') } %}
+ </td>
+ <td>
+ <a class="btn" href="/village/{{ village.x }}/{{ village.y }}/building/UpgradeBuilding/build/cancel">
+ Cancel
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+
+ {% if events['TrainUnits'] %}
+ <h4>Train Units</h4>
+ <table>
+ <thead>
+ <tr>
+ <th>Unit</th>
+ <th>Time</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for event in events['TrainUnits'] %}
+ <tr>
+ <td>{{ event.type }}</td>
+ <td class="timer">
+ {% include 'components/timer.twig' with { 'time': event.event.time|date('c') } %}
+ </td>
+ <td>
+ <a class="btn" href="/village/{{ village.x }}/{{ village.y }}/unit/train/cancel">
+ Cancel
+ </a>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+
+ {% if events['SendUnits'] %}
+ <h4>Send Resources / Units</h4>
+ <table>
+ <thead>
+ <tr>
+ <th>Type</th>
+ <th>Unit</th>
+ <th>Amount</th>
+ <th>Origin</th>
+ <th>Destination</th>
+ <th>Time</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for event in events['SendUnits'] %}
+ <tr>
+ <td>{{ event.type }}</td>
+ <td>{{ event.unit }}</td>
+ <td>{{ event.amount }}</td>
+ <td>{{ village.get(event.source).name }}</td>
+ <td>{{ village.get(event.destination).name }}</td>
+ <td class="timer">
+ {% include 'components/timer.twig' with { 'time': event.event.time|date('c') } %}
+ </td>
+ <td>
+ {% if event.isCanceled %}
+ Canceled
+ {% else %}
+ {% if event.event.villageId == village.id %}
+ <form action="/event/{{ event.event.id }}/cancel" method="post">
+ <input type="submit" value="Cancel">
+ </form>
+ {% endif %}
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ </div>
+
+ <div class="village__main">
+ <div class="village__buildings">
+ <h3>Buildings</h3>
+ <table>
+ <thead>
+ <tr>
+ <th>Type</th>
+ <th>Level</th>
+ <th>Build Time</th>
+ <th>Resources</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for building in buildings %}
+ <tr class="village__buildings__row">
+ <td>{{ building.type | default(type) }}</td>
+ <td>{{ building.level | default(0) }}</td>
+ <td>{{ building.getBuildTimeForLevel(building.getEffectiveLevel() + 1) | buildTime }}</td>
+ <td class="resources">
+ <span>
+ <i class="icon icon-wood"></i>
+ {{ building.getResourceRequirementsForLevel(building.getEffectiveLevel() + 1)['wood'] }}
+ </span>
+ &nbsp;
+ <span>
+ <i class="icon icon-clay"></i>
+ {{ building.getResourceRequirementsForLevel(building.getEffectiveLevel() + 1)['clay'] }}
+ </span>
+ &nbsp;
+ <span>
+ <i class="icon icon-iron"></i>
+ {{ building.getResourceRequirementsForLevel(building.getEffectiveLevel() + 1)['iron'] }}
+ </span>
+ </td>
+ <td>
+ <form action="/village/{{ village.x }}/{{ village.y }}/building/{{ building.type }}/level-up" method="post">
+ <input type="submit" value="Level up" {{ village.canBuild(village, building) ? '' : 'disabled' }}>
+ </form>
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ </div>
+
+ <div class="village_units">
+ <h3>Units</h3>
+ <table>
+ <thead>
+ <tr>
+ <th></th>
+ <th>Type</th>
+ <th>Amount</th>
+ <th>Build Time</th>
+ <th>Resources</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for unit in village.getUnits(village.id, 1, 3) %}
+ <tr>
+ <td><i class="icon icon-{{ unit.type|lower }}"></i></td>
+ <td>{{ unit.type }}</td>
+ <td>{{ unit.amount }}</td>
+ {% if not unit.isTraveling %}
+ <td>
+ {{ unit.getBuildTime(1) | buildTime }}
+ </td>
+ <td>
+ <span>
+ <i class="icon icon-wood"></i>
+ {{ unit.getResourceRequirements(unit, 1)['wood'] }}
+ </span>
+ &nbsp;
+ <span>
+ <i class="icon icon-clay"></i>
+ {{ unit.getResourceRequirements(unit, 1)['clay'] }}
+ </span>
+ &nbsp;
+ <span>
+ <i class="icon icon-iron"></i>
+ {{ unit.getResourceRequirements(unit, 1)['iron'] }}
+ </span>
+ &nbsp;
+ <span>
+ <i class="icon icon-food"></i>
+ {{ unit.getResourceRequirements(unit, 1)['food'] ?? 0 }}
+ </span>
+ </td>
+ <td>
+ <form action="/village/{{ village.x }}/{{ village.y }}/unit/{{ unit.type }}/create" method="post" class="inline">
+ <input type="number" min="0" name="amount" placeholder="Amount">
+ <input type="submit" value="Train" {{ village.canTrain(village, unit, 1) ? '' : 'disabled' }}>
+ </form>
+ </td>
+ {% else %}
+ <td>~traveling~</td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+
+ <h4>Supporting Units</h4>
+ <table>
+ <thead>
+ <tr>
+ <th></th>
+ <th>Type</th>
+ <th>Amount</th>
+ <th>Origin</th>
+ <th>Location</th>
+ <th>Travel Time</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for unit in village.getUnits(village.id, 2) | merge(village.getUnits(village.id, 3)) %}
+ <tr>
+ <td><i class="icon icon-{{ unit.type|lower }}"></i></td>
+ <td>{{ unit.type }}</td>
+ <td>{{ unit.amount }}</td>
+ <td>{{ village.get(unit.homeVillageId).name }}</td>
+ <td>{{ not unit.isTraveling ? village.get(unit.residenceVillageId).name : '~traveling~' }}</td>
+ <td>{{ unit.getTravelTime(unit, village.getDistance(unit.getHomeVillage().x, unit.getHomeVillage().x, unit.getResidenceVillage().x, unit.getResidenceVillage().y)) | buildTime }}</td>
+ <td>
+ {% if not unit.isTraveling %}
+ {% if unit.homeVillageId == village.id %}
+ <form action="/village/{{ village.x }}/{{ village.y }}/unit/{{ unit.type }}/location/{{ unit.getResidenceVillage().x }}/{{ unit.getResidenceVillage().y }}/recall" method="post">
+ <input type="number" min="1" max="{{ unit.amount }}" name="amount" placeholder="Amount" required>
+ <input type="submit" value="Recall Home">
+ </form>
+ {% else %}
+ <form action="/village/{{ village.x }}/{{ village.y }}/unit/{{ unit.type }}/location/{{ unit.getHomeVillage().x }}/{{ unit.getHomeVillage().y }}/send-back" method="post">
+ <input type="number" min="1" max="{{ unit.amount }}" name="amount" placeholder="Amount" required>
+ <input type="submit" value="Send Back">
+ </form>
+ {% endif %}
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+
+ <h4>Send Units</h4>
+ <form action="/village/{{ village.x }}/{{ village.y }}/send-units" method="post">
+ <select name="unit">
+ {% for unit in village.getUnits(village.id, 1) %}
+ <option>{{ unit.type }}</option>
+ {% endfor %}
+ </select>
+ <input type="number" min="1" name="amount" placeholder="Amount" required>
+ <select name="village">
+ {% for v in villages %}
+ <option value="{{ v.id }}">{{ v.name }}</option>
+ {% endfor %}
+ </select>
+ <select name="type">
+ <option>Borrow</option>
+ <option>Gift</option>
+ </select>
+ <button>Send</button>
+ </form>
+ </div>
+
+ {% if village.getBuilding(village.id, 'Marketplace') %}
+ <h3>Send Resources</h3>
+ <form action="/village/{{ village.x }}/{{ village.y }}/send-resources" method="post">
+ <input type="number" min="1" name="wood" placeholder="Amount Wood" required>
+ <input type="number" min="1" name="clay" placeholder="Amount Clay" required>
+ <input type="number" min="1" name="iron" placeholder="Amount Iron" required>
+ <input type="number" min="1" name="food" placeholder="Amount Food" required>
+ <select name="village">
+ {% for v in villages %}
+ <option value="{{ v.id }}">{{ v.name }}</option>
+ {% endfor %}
+ </select>
+ <button>Send</button>
+ </form>
+ {% endif %}
+ </div>
+</div>
+{% endblock %}
diff --git a/views/http/villages.twig b/views/http/villages.twig
new file mode 100644
index 0000000..bdb87be
--- /dev/null
+++ b/views/http/villages.twig
@@ -0,0 +1,38 @@
+{% extends 'base.twig' %}
+
+{% block main %}
+<table>
+ <thead>
+ <tr>
+ <td>Name</td>
+ <td>Coordinates</td>
+ <td>Wood</td>
+ <td>Clay</td>
+ <td>Iron</td>
+ <td>Food</td>
+ <td>Storage</td>
+ <td>Satisfaction</td>
+ </tr>
+ </thead>
+ <tbody>
+ {% for village in villages %}
+ <tr>
+ <td>
+ <a href="/village/{{ village.x}}/{{ village.y }}">
+ {{ village.name }}
+ </a>
+ </td>
+ <td>
+ { x: {{ village.x }}, y: {{ village.y }} }
+ </td>
+ <td>{{ village.wood }}</td>
+ <td>{{ village.clay }}</td>
+ <td>{{ village.iron }}</td>
+ <td>{{ village.food }}</td>
+ <td>{{ village.getStorage(village.id).getCapacity() * (25 / 100) }}</td>
+ <td>{{ village.satisfaction }}</td>
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+{% endblock %}