diff --git a/.gitmodules b/.gitmodules
index a53596f..a5a3134 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,15 @@
-[submodule "homepage/materialize"]
- path = homepage/materialize
- url = https://github.com/materializecss/materialize.git
-[submodule "homepage/redesign2018/markdownExperiment/zopfli"]
- path = homepage/redesign2018/markdownExperiment/zopfli
+[submodule "submodules/zopfli"]
+ path = submodules/zopfli
url = https://github.com/google/zopfli.git
+[submodule "submodules/parsedown"]
+ path = submodules/parsedown
+ url = https://github.com/erusev/parsedown
+[submodule "submodules/spyc"]
+ path = submodules/spyc
+ url = https://github.com/mustangostang/spyc.git
+[submodule "submodules/lite-youtube-embed"]
+ path = submodules/lite-youtube-embed
+ url = https://github.com/paulirish/lite-youtube-embed.git
+[submodule "submodules/materialize"]
+ path = submodules/materialize
+ url = https://github.com/materializecss/materialize.git
diff --git a/DieJudoGürtelprüfung/.htaccess b/DieJudoGürtelprüfung/.htaccess
new file mode 100644
index 0000000..80d6edc
--- /dev/null
+++ b/DieJudoGürtelprüfung/.htaccess
@@ -0,0 +1,6 @@
+RewriteEngine On
+RewriteBase /
+
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteCond %{REQUEST_FILENAME}\.php -f
+RewriteRule ^(.+)$ $1.php [L]
diff --git a/DieJudoGürtelprüfung/Kyu5.json b/DieJudoGürtelprüfung/Kyu5.json
new file mode 100644
index 0000000..d78d853
--- /dev/null
+++ b/DieJudoGürtelprüfung/Kyu5.json
@@ -0,0 +1,74 @@
+[
+ {
+ "source": "http://mmurl.de/judo52",
+ "target": "videos/5terKyu/Ukemi/MaeMawari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo53",
+ "target": "videos/5terKyu/NageWaza/MoroteSeoiNage.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo54",
+ "target": "videos/5terKyu/NageWaza/SasaeTsuriKomiAshiHizaGuruma.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo55",
+ "target": "videos/5terKyu/NageWaza/OkuriAshiBarei.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo56",
+ "target": "videos/5terKyu/NageWaza/OSotoGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo57",
+ "target": "videos/5terKyu/NageWaza/HaraiGoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo58",
+ "target": "videos/5terKyu/KansetsuWaza/JujiGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo59",
+ "target": "videos/5terKyu/KansetsuWaza/UdeGarami.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo60",
+ "target": "videos/5terKyu/TachiWaza/KonterEindreh.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo61",
+ "target": "videos/5terKyu/TachiWaza/KonterFuss.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo62",
+ "target": "videos/5terKyu/TachiWaza/KombiEindreh.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo63",
+ "target": "videos/5terKyu/TachiWaza/KombiFuss.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo64",
+ "target": "videos/5terKyu/NeWaza/UkesBefreiungZuJujiGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo65",
+ "target": "videos/5terKyu/NeWaza/UkesBefreiungZuUdeGarami.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo66",
+ "target": "videos/5terKyu/NeWaza/BefreiungDurchBeinklammer.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo67",
+ "target": "videos/5terKyu/NeWaza/BefreiungAusBeinklammer.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo68",
+ "target": "videos/5terKyu/NeWaza/JujiGgBank.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo69",
+ "target": "videos/5terKyu/Randori/Randori.webm"
+ }
+]
\ No newline at end of file
diff --git a/DieJudoGürtelprüfung/Kyu6.json b/DieJudoGürtelprüfung/Kyu6.json
new file mode 100644
index 0000000..e230e38
--- /dev/null
+++ b/DieJudoGürtelprüfung/Kyu6.json
@@ -0,0 +1,82 @@
+[
+ {
+ "source": "http://mmurl.de/judo32",
+ "target": "videos/6terKyu/Ukemi/MaeMawariUkemi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo33",
+ "target": "videos/6terKyu/NageWaza/IpponSeoiNage.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo34",
+ "target": "videos/6terKyu/NageWaza/TaiOtoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo35",
+ "target": "videos/6terKyu/NageWaza/KoUchiGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo36",
+ "target": "videos/6terKyu/NageWaza/KoSotoGakeKoSotoGake.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo37",
+ "target": "videos/6terKyu/NageWaza/DeAshiBarei.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo38",
+ "target": "videos/6terKyu/NeWaza/KesaGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo39",
+ "target": "videos/6terKyu/NeWaza/YokoShioGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo40",
+ "target": "videos/6terKyu/NeWaza/TateShioGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo41",
+ "target": "videos/6terKyu/NeWaza/KamiShioGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo42",
+ "target": "videos/6terKyu/AnwendungTachiWaza/IpponSeoiNage.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo43",
+ "target": "videos/6terKyu/AnwendungTachiWaza/TaiOtoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo44",
+ "target": "videos/6terKyu/AnwendungTachiWaza/KoUchiGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo45",
+ "target": "videos/6terKyu/AnwendungTachiWaza/DeAshiBarei.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo46",
+ "target": "videos/6terKyu/AnwendungTachiWaza/Ausweichen.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo47",
+ "target": "videos/6terKyu/AnwendungNeWaza/OUchiGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo48",
+ "target": "videos/6terKyu/AnwendungNeWaza/KoUchiGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo49",
+ "target": "videos/6terKyu/AnwendungNeWaza/Befreiungsprinzipien.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo50",
+ "target": "videos/6terKyu/AnwendungNeWaza/AngriffOberlage.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo51",
+ "target": "videos/6terKyu/AnwendungNeWaza/AngriffUnterlage.webm"
+ }
+]
\ No newline at end of file
diff --git a/DieJudoGürtelprüfung/Kyu7.json b/DieJudoGürtelprüfung/Kyu7.json
new file mode 100644
index 0000000..9e7f147
--- /dev/null
+++ b/DieJudoGürtelprüfung/Kyu7.json
@@ -0,0 +1,78 @@
+[
+ {
+ "source": "http://mmurl.de/judo13",
+ "target": "videos/7terKyu/Ukemi/MaeMawari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo14",
+ "target": "videos/7terKyu/NageWaza/OGoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo15",
+ "target": "videos/7terKyu/NageWaza/UkiGoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo16",
+ "target": "videos/7terKyu/NageWaza/OUchiGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo17",
+ "target": "videos/7terKyu/NageWaza/SeoiOtoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo18",
+ "target": "videos/7terKyu/OsaeKomiWaza/KesaGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo19",
+ "target": "videos/7terKyu/OsaeKomiWaza/YokoShioGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo20",
+ "target": "videos/7terKyu/OsaeKomiWaza/TateShioGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo21",
+ "target": "videos/7terKyu/OsaeKomiWaza/KamiShioGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo22",
+ "target": "videos/7terKyu/TachiWaza/SeoiOtoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo23",
+ "target": "videos/7terKyu/TachiWaza/OUchiGari.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo24",
+ "target": "videos/7terKyu/NeWaza/KesaGatame-Befreiung.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo25",
+ "target": "videos/7terKyu/NeWaza/YokoShioGatame-Befreiung.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo26",
+ "target": "videos/7terKyu/NeWaza/TateShioGatame-Befreiung.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo27",
+ "target": "videos/7terKyu/NeWaza/KamiShioGatame-Befreiung.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo28",
+ "target": "videos/7terKyu/NeWaza/AngriffGgBank.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo29",
+ "target": "videos/7terKyu/NeWaza/AngriffGgBauch.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo30",
+ "target": "videos/7terKyu/NeWaza/Haltegriffwechsel.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo31",
+ "target": "videos/7terKyu/Randori/Randori.webm"
+ }
+]
diff --git a/DieJudoGürtelprüfung/Kyu8.json b/DieJudoGürtelprüfung/Kyu8.json
new file mode 100644
index 0000000..f39afe6
--- /dev/null
+++ b/DieJudoGürtelprüfung/Kyu8.json
@@ -0,0 +1,50 @@
+[
+ {
+ "source": "http://download.m-m-sports.com/extras/judo_guertelpruefung/1_8%20fallrw.mp4",
+ "target": "videos/8terKyu/Ukemi/Ushiro.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo02",
+ "target": "videos/8terKyu/Ukemi/Yoko.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo03",
+ "target": "videos/8terKyu/NageWaza/OGoshiUkiGoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo04",
+ "target": "videos/8terKyu/NageWaza/BeidbeinigeEindrehtechnik.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo05",
+ "target": "videos/8terKyu/NageWaza/OSotoOtoshi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo06",
+ "target": "videos/8terKyu/OsaeKomiWaza/KesaGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo07",
+ "target": "videos/8terKyu/OsaeKomiWaza/MuneGatame.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo08",
+ "target": "videos/8terKyu/TachiWaza/EindrehtechnikUkeSchiebt.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo09",
+ "target": "videos/8terKyu/TachiWaza/OSotoOtoshiUkeZieht.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo10",
+ "target": "videos/8terKyu/TachiWaza/UebergangStandBoden.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo11",
+ "target": "videos/8terKyu/NeWaza/BefreiungOsaeKomi.webm"
+ },
+ {
+ "source": "http://mmurl.de/judo12",
+ "target": "videos/8terKyu/Randori/Randori.webm"
+ }
+]
\ No newline at end of file
diff --git a/DieJudoGürtelprüfung/Makefile b/DieJudoGürtelprüfung/Makefile
new file mode 100644
index 0000000..6e97671
--- /dev/null
+++ b/DieJudoGürtelprüfung/Makefile
@@ -0,0 +1,73 @@
+kyu8-sourceFiles = \
+ kyu8-Grundform-Wurftechniken.md \
+ kyu8-Grundform-Bodentechniken.md \
+ kyu8-Anwendungsaufgaben-Stand.md \
+ kyu8-Anwendungsaufgaben-Boden.md \
+ kyu8-BodenRandoriNachWurf.md \
+ kyu8-Lexikon.md \
+
+kyu7-sourceFiles = \
+ kyu7-Grundform-Wurftechniken.md \
+ kyu7-Grundform-Bodentechniken.md \
+ kyu7-Anwendungsaufgaben-Stand.md \
+ kyu7-Anwendungsaufgaben-Boden.md \
+ kyu7-BodenRandoriNachWurf.md \
+ kyu7-Lexikon.md \
+
+kyu6-sourceFiles = \
+ Kyu6.md \
+ Kyu6-Ukemi.md \
+ Kyu6-NageWaza.md \
+ Kyu6-Anwendung-TachiWaza.md \
+ Kyu6-Anwendung-NeWaza.md \
+ Kyu6-Randori.md \
+ Kyu6-Lexikon.md
+
+.PHONY: all
+all: kyu8 kyu7
+
+.PHONY: kyu7 kyu8 kyu6
+kyu8: kyu8.html
+kyu7: kyu7.html
+kyu6: kyu6.html
+
+kyu8.html: $(kyu8-sourceFiles)
+ pandoc -i --section-divs -t revealjs -s -o kyu7.html $(kyu7-sourceFiles)
+
+kyu7.html: $(kyu7-sourceFiles)
+ pandoc -i --section-divs -t revealjs -s -o kyu7.html $(kyu7-sourceFiles)
+
+kyu6.html: $(kyu6-sourceFiles)
+ pandoc -i --section-divs -t revealjs -s -o kyu6.html $(kyu6-sourceFiles)
+ ./yt-clipper.py Kyu6.json
+
+.PHONY: directoryStructure
+directoryStructure:
+ mkdir -p videos/8terKyu/Ukemi
+ mkdir -p videos/8terKyu/NageWaza
+ mkdir -p videos/8terKyu/OsaeKomiWaza
+ mkdir -p videos/8terKyu/TachiWaza
+ mkdir -p videos/8terKyu/NeWaza
+ mkdir -p videos/8terKyu/Randori
+ mkdir -p videos/7terKyu/Ukemi
+ mkdir -p videos/7terKyu/NageWaza
+ mkdir -p videos/7terKyu/OsaeKomiWaza
+ mkdir -p videos/7terKyu/TachiWaza
+ mkdir -p videos/7terKyu/NeWaza
+ mkdir -p videos/7terKyu/Randori
+ mkdir -p videos/6terKyu/Ukemi
+ mkdir -p videos/6terKyu/NageWaza
+ mkdir -p videos/6terKyu/OsaeKomiWaza
+ mkdir -p videos/6terKyu/TachiWaza
+ mkdir -p videos/6terKyu/NeWaza
+ mkdir -p videos/6terKyu/Randori
+ mkdir -p videos/5terKyu/Ukemi
+ mkdir -p videos/5terKyu/NageWaza
+ mkdir -p videos/5terKyu/KansetsuWaza
+ mkdir -p videos/5terKyu/TachiWaza
+ mkdir -p videos/5terKyu/NeWaza
+ mkdir -p videos/5terKyu/Randori
+
+.PHONY: clean
+clean:
+ rm kyu6.html
diff --git a/DieJudoGürtelprüfung/clipper b/DieJudoGürtelprüfung/clipper
new file mode 100755
index 0000000..9f21a66
--- /dev/null
+++ b/DieJudoGürtelprüfung/clipper
@@ -0,0 +1,127 @@
+#! /usr/bin/env python3
+
+import youtube_dl
+import json
+import ffmpeg
+import subprocess
+import glob
+import sys
+import argparse
+
+config = {
+ 'vcodec': "vp9",
+ 'acodec': "libopus"
+}
+
+
+argParser = argparse.ArgumentParser()
+
+
+jsonFileName = sys.argv[1]
+
+clipDict = {}
+with open(jsonFileName) as jf:
+ clipDict = json.load(jf)
+
+ydl_opts = {"outtmpl": "%(id)s"}
+
+for clip in clipDict:
+ infoDict = None
+ with youtube_dl.YoutubeDL(ydl_opts) as ydl:
+ infoDict = ydl.extract_info(clip['source'], download=False)
+ ydl.download([clip['source']])
+
+ if infoDict is not None:
+ if 'from' in clip and 'to' in clip:
+ stream = ffmpeg.input(
+ # @todo This is a very bad hack because the outtmpl options doesn't seem to be working if the file gets reencoded
+ glob.glob(infoDict['id']+"*")[0],
+ ss=clip['from'],
+ to=clip['to'],
+ )
+ else:
+ stream = ffmpeg.input(
+ glob.glob(infoDict['id']+"*")[0],
+ )
+
+ video = stream.video
+ audio = stream.audio
+
+ if 'crop' in clip:
+ stream = ffmpeg.filter(stream,
+ "crop",
+ x=clip['crop']['x'],
+ y=clip['crop']['y'],
+ w=clip['crop']['w'],
+ h=clip['crop']['h']
+ )
+
+ h = 480
+ w = -2
+ if 'scale' in clip:
+ h = clip['scale']['h'] if 'h' in clip['scale'] else 480
+ w = clip['scale']['w'] if 'w' in clip['scale'] else -2
+ stream = ffmpeg.filter(stream, "scale", height=h, width=w )
+
+ stream = ffmpeg.output(stream,
+ clip['target'],
+ vcodec=config['vcodec'],
+ **{
+ # "an":None,
+ "y":None,
+ "pass":"1",
+ "b:v":"512k", "minrate":"375k", "maxrate":"1088k",
+ "quality":"good",
+ }
+ )
+ try:
+ ffmpeg.run(stream)
+ except:
+ print(infoDict)
+
+
+ if 'from' in clip and 'to' in clip:
+ stream = ffmpeg.input(
+ glob.glob(infoDict['id']+"*")[0],
+ ss=clip['from'],
+ to=clip['to'],
+ )
+ else:
+ stream = ffmpeg.input(
+ glob.glob(infoDict['id']+"*")[0]
+ )
+ if 'crop' in clip:
+ stream = ffmpeg.filter(stream,
+ "crop",
+ x=clip['crop']['x'],
+ y=clip['crop']['y'],
+ w=clip['crop']['w'],
+ h=clip['crop']['h']
+ )
+
+ h = 480
+ w = -2
+ if 'scale' in clip:
+ h = clip['scale']['h'] if 'h' in clip['scale'] else 480
+ w = clip['scale']['w'] if 'w' in clip['scale'] else -2
+ stream = ffmpeg.filter(stream, "scale", height=h, width=w )
+
+ stream = ffmpeg.output(stream, audio,
+ clip['target'],
+ vcodec=config['vcodec'],
+ **{
+ # "an":None,
+ "y":None,
+ "pass":"2",
+ "b:v":"512k", "minrate":"375k", "maxrate":"1088k",
+ "quality":"good",
+ "acodec": config['acodec'],
+ }
+ )
+ try:
+ ffmpeg.run(stream)
+ except:
+ print(infoDict)
+
+
+#640x480p @ 24,25,30 512 (LQ), 750 (MQ) 256 (LQ) 375 (MQ) 742 (LQ) 1088 (MQ)
diff --git a/DieJudoGürtelprüfung/kyu.php b/DieJudoGürtelprüfung/kyu.php
new file mode 100644
index 0000000..9510474
--- /dev/null
+++ b/DieJudoGürtelprüfung/kyu.php
@@ -0,0 +1,254 @@
+array(..), 'mdText'=>string)
+function loadMarkdownFile($fileName){
+ $fileText = file_get_contents($fileName);
+
+ $fileParts = preg_split('/[\n]*[-]{3}[\n]/', $fileText, 3);
+
+ return array(
+ 'yaml' => Spyc::YAMLLoadString($fileParts[1])
+ , 'mdText' => preg_replace("/^#(.*)$/m", "", $fileParts[2])
+ );
+}
+
+/// @brief Gibt die URL der gerade aufgerufenen Seite zurück
+function getCurPagesUrl(){
+ $pageURL = 'http';
+ if ($_SERVER["HTTPS"] == "on"){
+ $pageURL .= "s";
+ }
+ $pageURL .= "://";
+ if($_SERVER["SERVER_PORT"] != "80"){
+ $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
+ }
+ else{
+ $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
+ }
+return $pageURL;
+}
+
+function htmlCardCode($article, $Parsedown){
+ if(
+ empty($article['yaml'])
+ && empty($article['mdText'])
+ ) return "";
+ $videoFrame = (
+ array_key_exists('yaml', $article)
+ ?(
+ array_key_exists('video', $article['yaml'])
+ ?(
+ "
".html5VideoFrame($article['yaml']['video'])."
"
+ )
+ :""
+ )
+ :""
+ );
+ $ytVideoFrame = (
+ array_key_exists('yaml', $article)
+ ?(
+ array_key_exists('youtube', $article['yaml'])
+ ?(
+ ytLightEmbed($article['yaml']['youtube'])
+ )
+ :""
+ )
+ :""
+ );
+return
+ ""
+ ."
"
+ ."
"
+ .(!empty($videoFrame)?$videoFrame:$ytVideoFrame)
+ ."
"
+ ."
"
+ .""
+ .$article['yaml']['title']
+ ."more_vert"
+ .""
+ ."
"
+ ."
"
+ .""
+ .$article['yaml']['title']
+ ."close"
+ .""
+ .$Parsedown->text($article['mdText'])
+ ."
"
+ ."
"
+ ."
";
+}
+
+//! create the