first commit

This commit is contained in:
Flummi 2022-12-20 12:21:31 +01:00
commit 1b4073b3a4
17 changed files with 507 additions and 0 deletions

3
.htaccess Normal file
View File

@ -0,0 +1,3 @@
RewriteEngine on
RewriteRule ^doppelklinge/? /?p=doppelklinge [L]
RewriteRule ^vermessung/? /?p=vermessung [L]

0
README.md Normal file
View File

7
css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

71
css/style.css Normal file
View File

@ -0,0 +1,71 @@
body {
counter-reset: toplist;
font-size: .875rem;
}
/* Sidebar */
.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: 0;
z-index: 100;
padding: 48px 0 0;
}
@media (max-width: 767.98px) {
.sidebar {
top: 4rem;
}
}
.sidebar-sticky {
height: calc(100vh - 48px);
overflow-x: hidden;
overflow-y: auto;
}
.sidebar .nav-link {
font-weight: 500;
color: #333;
}
.sidebar .nav-link {
margin-right: 4px;
color: #727272;
}
.sidebar .nav-link.active {
color: #2470dc;
}
.sidebar .nav-link:hover,
.sidebar .nav-link.active {
color: inherit;
}
.sidebar-heading {
font-size: .75rem;
}
/* Navbar */
.navbar-brand {
padding-top: .75rem;
padding-bottom: .75rem;
background-color: rgba(0, 0, 0, .25);
}
.navbar .navbar-toggler {
top: .25rem;
right: 1rem;
}
.navbar .form-control {
padding: .75rem 1rem;
}
/* custom */
ul.list-top > li::before {
counter-increment: toplist;
content: "# " counter(toplist) ": ";
}

BIN
img/logo-big.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

15
inc/router.inc.php Normal file
View File

@ -0,0 +1,15 @@
<?php
$routes = [
'doppelklinge' => 'doppelklinge',
'vermessung' => 'vermessung',
'default' => 'default'
];
ob_start();
if(array_key_exists($_page, $routes))
require_once("./pages/{$routes[$_page]}.page.php");
else
require_once("./pages/{$routes['default']}.page.php");
$_content = ob_get_contents();
ob_end_clean();

77
inc/tpl.class.php Normal file
View File

@ -0,0 +1,77 @@
<?php
class tpl {
static $blocks = array();
static $cache_path = '/home/users/flumm/tmp/';
static function view($file, $data = array()) {
$cached_file = self::cache($file);
extract($data, EXTR_SKIP);
require $cached_file;
unlink($cached_file);
}
static function cache($file) {
if(!file_exists(self::$cache_path))
mkdir(self::$cache_path, 0744);
$cached_file = self::$cache_path . str_replace(array('/', '.html'), array('_', ''), $file . '.php');
if(!file_exists($cached_file) || filemtime($cached_file) < filemtime($file)) {
$code = self::includeFiles($file);
$code = self::compileCode($code);
file_put_contents($cached_file, '<?php class_exists(\'' . __CLASS__ . '\') or exit; ?>' . PHP_EOL . $code);
}
return $cached_file;
}
static function compileCode($code) {
$code = self::compileBlock($code);
$code = self::compileYield($code);
$code = self::compileEscapedEchos($code);
$code = self::compileEchos($code);
$code = self::compilePHP($code);
return $code;
}
static function includeFiles($file) {
$code = file_get_contents($file);
preg_match_all('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', $code, $matches, PREG_SET_ORDER);
foreach($matches as $value)
$code = str_replace($value[0], self::includeFiles($value[2]), $code);
$code = preg_replace('/{% ?(extends|include) ?\'?(.*?)\'? ?%}/i', '', $code);
return $code;
}
static function compilePHP($code) {
return preg_replace('~\{%\s*(.+?)\s*\%}~is', '<?php $1 ?>', $code);
}
static function compileEchos($code) {
return preg_replace('~\{{\s*(.+?)\s*\}}~is', '<?php echo $1 ?>', $code);
}
static function compileEscapedEchos($code) {
return preg_replace('~\{{{\s*(.+?)\s*\}}}~is', '<?php echo htmlentities($1, ENT_QUOTES, \'UTF-8\') ?>', $code);
}
static function compileBlock($code) {
preg_match_all('/{% ?block ?(.*?) ?%}(.*?){% ?endblock ?%}/is', $code, $matches, PREG_SET_ORDER);
foreach($matches as $value) {
if(!array_key_exists($value[1], self::$blocks))
self::$blocks[$value[1]] = '';
if(strpos($value[2], '@parent') === false)
self::$blocks[$value[1]] = $value[2];
else
self::$blocks[$value[1]] = str_replace('@parent', self::$blocks[$value[1]], $value[2]);
$code = str_replace($value[0], '', $code);
}
return $code;
}
static function compileYield($code) {
foreach(self::$blocks as $block => $value) {
$code = preg_replace('/{% ?yield ?' . $block . ' ?%}/', $value, $code);
}
$code = preg_replace('/{% ?yield ?(.*?) ?%}/i', '', $code);
return $code;
}
}
?>

24
index.php Normal file
View File

@ -0,0 +1,24 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
$_page = isset($_GET['p']) ? $_GET['p'] : '';
require_once('./inc/tpl.class.php');
require_once('./inc/router.inc.php');
$tpl = (object)$tpl;
if(!@$tpl->debug) {
tpl::view('tpl/' . $tpl->file,
array_merge([
'page' => $_page
],
gettype($tpl->data) !== 'string' ? $tpl->data : [])
);
}
else {
echo "<pre>";
print_r($_content);
echo "</pre>";
}

2
info.php Normal file
View File

@ -0,0 +1,2 @@
<?php
phpinfo();

2
js/bootstrap-native.min.js vendored Normal file

File diff suppressed because one or more lines are too long

3
pages/default.page.php Normal file
View File

@ -0,0 +1,3 @@
<?php
$tpl['file'] = 'default.html';
$tpl['data'] = '';

View File

@ -0,0 +1,41 @@
<?php
$tpl['file'] = 'doppelklinge.html';
$tpl['data'] = [];
$progress = !empty($_POST['progress']) ? $_POST['progress'] : '';
if(!empty($progress)) {
$list = [];
preg_match_all("/(?<task>.*): (?<act>.*) \/ (?<max>.*)/m", $progress, $tmp);
for($i = 0; $i < count($tmp[0]); $i++) {
$list[$i] = (object)[
'task' => trim($tmp['task'][$i]),
'act' => (int)str_replace('.', '', $tmp['act'][$i]),
'max' => (int)str_replace('.', '', $tmp['max'][$i])
];
$list[$i]->percent = round($list[$i]->act / $list[$i]->max * 100, 2);
}
usort($list, function($a, $b) { return $b->percent <=> $a->percent; });
$act = $max = $avg = 0;
for($i = 0; $i < 5; $i++) {
$act += $list[$i]->act;
$max += $list[$i]->max;
$avg += $list[$i]->percent;
}
$percent = round($act / $max * 100, 2);
$tpl['data'] = [
'progress' => $progress,
'list' => $list,
'percent' => $percent,
'avg' => round($avg / 5, 2)
];
}
else {
$tpl['data'] = [
'progress' => ''
];
}

60
pages/vermessung.page.php Normal file
View File

@ -0,0 +1,60 @@
<?php
$tpl['file'] = 'vermessung.html';
$tpl['data'] = [];
$tpl['debug'] = false;
$protocol = !empty($_POST['protocol']) ? $_POST['protocol'] : '';
if(!empty($protocol)) {
preg_match_all("/(?<datetime>.*)\t(?<amt>.*) führt mit (?<laeufer>.*) eine.*erwirtschaftet (?<gm>.*) Goldmünzen/m", $protocol, $res);
$dtact = date('m.Y');
$vms = $newest = [];
for($i = 0; $i < count($res['datetime']); $i++) {
$tmpdt = date('m.Y', strtotime($res['datetime'][$i]));
if(!array_key_exists($tmpdt, $vms)) {
$vms[$tmpdt] = [
'user' => [],
'gm' => 0,
'list' => [],
'dtact' => $tmpdt
];
}
if(!array_key_exists($res['amt'][$i], $vms[$tmpdt]['user']))
$vms[$tmpdt]['user'][$res['amt'][$i]] = 1;
else
$vms[$tmpdt]['user'][$res['amt'][$i]] += 1;
$laeufer = explode(', ', str_replace(' und ', ', ', trim($res['laeufer'][$i], ',')));
foreach($laeufer as $tmp) {
if(!array_key_exists($tmp, $vms[$tmpdt]['user']))
$vms[$tmpdt]['user'][$tmp] = 1;
else
$vms[$tmpdt]['user'][$tmp] += 1;
}
arsort($vms[$tmpdt]['user']);
$vms[$tmpdt]['gm'] += (int)str_replace('.', '', $res['gm'][$i]);
$vms[$tmpdt]['list'][] = [
'datum' => $res['datetime'][$i],
'gold' => (int)str_replace('.', '', $res['gm'][$i]),
'amt' => $res['amt'][$i],
'laeufer' => $laeufer
];
}
$tpl['data'] = [
'protocol' => $protocol,
'vms' => $vms,
'newest' => array_shift($vms)
];
}
else {
$tpl['data'] = [
'protocol' => $protocol
];
}

10
tpl/default.html Normal file
View File

@ -0,0 +1,10 @@
{% extends tpl/layout.html %}
{% block title %}Willkommen auf fwtrash.de!{% endblock %}
{% block content %}
<p>Wir sind stolz darauf, Ihnen eine Vielzahl von nützlichen Tools und Ressourcen für das Onlinespiel Freewar zur Verfügung zu stellen. Unser Ziel ist es, Ihnen das Spielen von Freewar zu erleichtern und Ihnen zu helfen, das Beste aus dem Spiel herauszuholen.</p>
<p>Auf unserer Webseite finden Sie alles, von praktischen Rechnern und Simulatoren bis hin zu umfassenden Anleitungen und Strategieguides. Wir sind ständig bemüht, unser Angebot zu erweitern und zu verbessern, um Ihnen die bestmögliche Unterstützung zu bieten.</p>
<p>Schauen Sie sich um und entdecken Sie alles, was fwtrash.de zu bieten hat. Wir hoffen, dass Sie viel Freude beim Stöbern und Nutzen unserer Tools haben werden.</p>
<strong>Viel Spaß beim Erkunden und Happy Gaming!</strong>
{% endblock %}

37
tpl/doppelklinge.html Normal file
View File

@ -0,0 +1,37 @@
{% extends tpl/layout.html %}
{% block title %}irgendwas mit Doppelklinge{% endblock %}
{% block content %}
<form action="/doppelklinge" method="post">
<p>Gesamten Mainframe von Position X: 80 Y: 126 einfügen (strg-a, strg-c):</p>
<textarea name="progress" rows="4" cols="60">{{ $progress }}</textarea>
<br />
<input type="submit" value="abschnalzen" />
</form>
{% if(isset($list)): %}
<hr />
<table class="table table-sm table-striped">
<thead>
<tr>
<th>Aufgabe</th>
<th>Fortschritt</th>
<th>Ziel</th>
<th>Prozent</th>
</tr>
</thead>
<tbody>
{% for($i = 0; $i < count($list); $i++): %}
<tr style="background-color: {{ $i >= 5 ? 'red' : 'white' }}">
<td>{{ $list[$i]->task }}</td>
<td>{{ $list[$i]->act }}</td>
<td>{{ $list[$i]->max }}</td>
<td>{{ $list[$i]->percent }}</td>
</tr>
{% endfor; %}
</tbody>
</table>
insgesamt {{ $percent }}% erledigt (&oslash; {{ $avg }}%).
{% endif; %}
{% endblock %}

46
tpl/layout.html Normal file
View File

@ -0,0 +1,46 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<base href="https://fwtrash.de/" />
<title>{% yield title %}</title>
<link rel="stylesheet" type="text/css" href="./css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="./css/style.css" />
</head>
<body>
<header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-3 col-lg-2 me-0 px-3 fs-6" href="./">
<img src="./img/logo-big.png" style="height: 38px;" />
&nbsp;fwtrash.de
</a>
<button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="navbar-nav">
<div class="nav-item text-nowrap">&nbsp;</div>
</div>
</header>
<div class="container-fluid">
<div class="row">
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div class="position-sticky pt-3 sidebar-sticky">
<ul class="nav flex-column">
<li class="nav-item"><a class="nav-link{% if(empty($page)): %} active{% endif; %}" href="/">Home</a></li>
<li class="nav-item"><a class="nav-link{% if($page == 'doppelklinge'): %} active{% endif; %}" href="/doppelklinge">Doppelklinge</a></li>
<li class="nav-item"><a class="nav-link{% if($page == 'vermessung'): %} active{% endif; %}" href="/vermessung">Vermessungen</a></li>
</ul>
</div>
</nav>
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
<h1 class="h2">{% yield title %}</h1>
<hr />
{% yield content %}
</main>
</div>
</div>
<script src="./js/bootstrap-native.min.js" defer></script>
</body>
</html>

109
tpl/vermessung.html Normal file
View File

@ -0,0 +1,109 @@
{% extends tpl/layout.html %}
{% block title %}irgendwas mit Vermessungen{% endblock %}
{% block content %}
<form action="/vermessung" method="post">
<p>Gesamtes Clanprotokoll einfügen (strg-a, strg-c):</p>
<textarea name="protocol" rows="4" cols="60">{{ $protocol }}</textarea>
<br />
<input type="submit" value="abschnalzen" />
</form>
{% if(isset($newest)): %}
<hr />
<span id="wao">wao, {{ number_format($newest['gm'], 0, '', '.') }} Goldm&uuml;nzen durch {{ count($newest['list']) }} Vermessungen erwirtschaftet!</span>
<select id="dtswitch">
{% foreach($vms as $vm): %}
<option>{{ $vm['dtact'] }}</option>
{% endforeach; %}
</select>
<hr />
<div class="container-fluid">
<div class="row justify-content-md-center">
<div class="col-sm-4">
<div class="card">
<h5 class="card-header">Topliste:</h5>
<div class="card-body">
<ul class="list-group list-group-flush list-top" id="toplist">
{% foreach($newest['user'] as $name => $c): %}
<li class="list-group-item d-flex justify-content-between align-items-center p-1">
{{ $name }}
<span class="badge bg-primary rounded-pill">{{ $c }} Vermessungen</span>
</li>
{% endforeach; %}
</ul>
</div>
</div>
</div>
<div class="col">
<div class="card">
<h5 class="card-header">ber&uuml;cksichtigte Messungen:</h5>
<div class="card-body">
<table class="table table-sm table-striped" style="width: 100%">
<thead>
<tr>
<th>Datum</th>
<th>Goldm&uuml;nzen</th>
<th>Amtsteher</th>
<th>L&auml;ufer</th>
</tr>
</thead>
<tbody id="vmlist">
{% foreach($newest['list'] as $tmp): %}
<tr>
<td style="vertical-align: top">{{ $tmp['datum'] }}</td>
<td style="vertical-align: top">{{ $tmp['gold'] }} gm</td>
<td style="vertical-align: top">{{ $tmp['amt'] }}</td>
<td style="vertical-align: top">{{ implode(', ', $tmp['laeufer']) }}</td>
</tr>
{% endforeach; %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script>const vms = {{ json_encode($vms) }};
(() => {
const toplist = document.querySelector('#toplist');
const vmlist = document.querySelector('#vmlist');
const wao = document.querySelector('#wao');
const dtswitch = document.querySelector('#dtswitch');
dtswitch.addEventListener('change', e => {
const vm = vms[dtswitch.value];
toplist.innerHTML = '';
vmlist.innerHTML = '';
let gm = 0;
let cvm = 0;
for(let [ user, count ] of Object.entries(vm.user)) {
// fill toplist
const li = document.createElement('li');
li.classList.add('list-group-item', 'd-flex', 'justify-content-between', 'align-items-center', 'p-1');
li.innerText = user;
const span = document.createElement('span');
span.classList.add('badge', 'bg-primary', 'rounded-pill');
span.innerText = `${count} Vermessungen`;
li.insertAdjacentElement('beforeend', span);
toplist.insertAdjacentElement('beforeend', li);
}
for(let entry of vm.list) {
// fill vmlist
const tr = document.createElement('tr');
tr.innerHTML = `<td>${entry.datum}</td><td>${entry.gold} gm</td><td>${entry.amt}</td><td>${entry.laeufer.join(', ')}</td>`;
vmlist.insertAdjacentElement('beforeend', tr);
}
wao.innerHTML = `wao, ${vm.gm.toLocaleString('de-DE')} Goldm&uuml;nzen durch ${vm.list.length} Vermessungen erwirtschaftet!`;
});
})();
</script>
{% endif; %}
{% endblock %}