diff --git a/www/data/css/styles.css b/www/data/css/styles.css
index 9b1a79d..1e1868d 100644
--- a/www/data/css/styles.css
+++ b/www/data/css/styles.css
@@ -89,6 +89,19 @@ body {
width: 0 !important;
height: 0 !important; }
+.boxedcontent {
+ color: #333;
+ border: 1px solid black;
+ background-color: #E0E0E0;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto; }
+ .boxedcontent .bc_header {
+ background-color: #BBB;
+ padding: 0 4px; }
+ .boxedcontent .bc_data {
+ padding: 8px; }
+
/* 400px */
#headerdiv {
z-index: 999;
@@ -265,21 +278,6 @@ html, body {
.ble_title {
font-size: 1.25em; } }
/* 400px */
-.blogcontent {
- color: #333;
- border: 1px solid black;
- background-color: #E0E0E0;
- width: 90%;
- margin-left: auto;
- margin-right: auto; }
-
-.bc_header {
- background-color: #BBB;
- padding: 0 4px; }
-
-.bc_data {
- padding: 8px; }
-
.base_markdown code {
font-family: Consolas, Monaco, "Courier New", Menlo, monospace;
direction: ltr;
@@ -348,6 +346,9 @@ html, body {
border: none !important;
background: transparent !important; }
+.blogcontent_euler, .blogcontent_markdown, .blogcontent_plain {
+ width: 90%; }
+
/* 400px */
#PEB_tableProblems .PEB_tablerowProblems:hover {
background-color: #888; }
@@ -796,6 +797,97 @@ html, body {
#prgv_header h1 {
font-size: 28pt; } }
/* 400px */
+.aboutcontent {
+ display: block;
+ width: 100%; }
+
+.aboutcontent .boxedcontent {
+ margin-bottom: 20px; }
+
+.about_egh_container {
+ display: flex;
+ flex-direction: column;
+ align-items: center; }
+
+.git_list {
+ display: inline-block;
+ width: 715px;
+ height: 115px;
+ overflow: visible; }
+
+@media (max-width: 991px) {
+ .git_list {
+ width: 100%;
+ height: auto; }
+
+ .extGitGraphContainer {
+ width: 95%;
+ width: calc(100% - 16px); } }
+.git_list text.caption {
+ font-size: 10px;
+ fill: #666; }
+
+.git_list text.caption_month {
+ font-size: 8px;
+ fill: #BBB; }
+
+.git_list text.caption_day {
+ font-size: 8px;
+ fill: #BBB; }
+
+.svg-tip:after {
+ box-sizing: border-box;
+ position: absolute;
+ left: 50%;
+ height: 5px;
+ width: 5px;
+ bottom: -10px;
+ margin: 0 0 0px -5px;
+ content: " ";
+ border: 5px solid transparent;
+ border-top-color: rgba(0, 0, 0, 0.8);
+ -moz-border-top-colors: none;
+ -moz-border-right-colors: none;
+ -moz-border-bottom-colors: none;
+ -moz-border-left-colors: none;
+ border-image: none; }
+
+.svg-tip {
+ padding: 5px;
+ background: none repeat scroll 0 0 rgba(0, 0, 0, 0.8);
+ color: #BBB;
+ font-size: 12px;
+ position: absolute;
+ z-index: 99999;
+ text-align: center;
+ border-radius: 3px;
+ box-sizing: border-box;
+ opacity: 0; }
+
+.extGitGraphContainer {
+ background-color: #FCFCFC;
+ margin: 10px;
+ display: inline-block;
+ border: 1px solid #222;
+ border-radius: 0;
+ box-shadow: 0 0 1px rgba(0, 0, 0, 0.25) inset; }
+
+.egg_footer {
+ margin-top: 5px;
+ text-align: right;
+ margin-right: 5px;
+ margin-bottom: 5px;
+ color: #888; }
+
+.egg_footer > a {
+ text-decoration: none;
+ color: inherit; }
+
+.egg_footer > a:hover {
+ text-decoration: none;
+ color: #22F; }
+
+/* 400px */
.euler_pnl_base {
display: inline-flex;
flex-direction: column;
diff --git a/www/data/css/styles.min.css b/www/data/css/styles.min.css
index 8a931c2..2922168 100644
--- a/www/data/css/styles.min.css
+++ b/www/data/css/styles.min.css
@@ -18,6 +18,9 @@ body{background-color:#EEE;color:#CCC;font-family:serif}
.blockcontent{display:block;width:100%}
.generic_hidden{visibility:hidden !important}
.generic_collapsed{visibility:collapse !important;display:none !important;width:0 !important;height:0 !important}
+.boxedcontent{color:#333;border:1px solid black;background-color:#e0e0e0;width:100%;margin-left:auto;margin-right:auto}
+.boxedcontent .bc_header{background-color:#BBB;padding:0 4px}
+.boxedcontent .bc_data{padding:8px}
#headerdiv{z-index:999;background-color:#333;display:flex;border-bottom:1px solid #111;box-shadow:0 0 8px #000;position:fixed;width:100%}
#headerdiv .logowrapper{flex:initial;margin:0;padding:0;height:42px}
#headerdiv .logowrapper .logo{height:30px;margin:4px 0 8px 6px;flex:initial}
@@ -58,9 +61,6 @@ html,body{margin:0;padding:0;height:100%}
.ble_date{background-color:#AAA;padding:2px;font-size:.8em;font-style:italic}
.ble_title{font-weight:bold;font-size:1.2em;text-align:left;margin:2px 0 2px 10px}
@media(max-width:767px){.ble_title{font-size:1.25em}}
-.blogcontent{color:#333;border:1px solid black;background-color:#e0e0e0;width:90%;margin-left:auto;margin-right:auto}
-.bc_header{background-color:#BBB;padding:0 4px}
-.bc_data{padding:8px}
.base_markdown code{font-family:Consolas,Monaco,"Courier New",Menlo,monospace;direction:ltr;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;-moz-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}
.base_markdown pre{font-size:14px;display:block;padding:9.5px;margin:0 0 10px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre-wrap;background-color:#f8f8f8;color:black;border:1px solid rgba(0,0,0,0.15);border-radius:2px}
.base_markdown blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #CCC}
@@ -77,6 +77,7 @@ html,body{margin:0;padding:0;height:100%}
.mdtable_container{overflow-x:auto}
.notable{width:unset !important;border:none !important}
.notable th,.notable td,.notable tr{border:none !important;background:transparent !important}
+.blogcontent_euler,.blogcontent_markdown,.blogcontent_plain{width:90%}
#PEB_tableProblems .PEB_tablerowProblems:hover{background-color:#888}
#PEB_tableProblems .PEB_TC_Value{font-family:Consolas,Monaco,"Courier New",Menlo,monospace}
#PEB_tableProblems .PEB_TC_Value:not(:hover){color:transparent;-o-transition:.5s;-ms-transition:.5s;-moz-transition:.5s;-webkit-transition:.5s;transition:.5s}
@@ -203,6 +204,23 @@ html,body{margin:0;padding:0;height:100%}
.prgv_right_lang{justify-content:space-evenly}
#prgv_header h1{font-size:28pt}
}
+.aboutcontent{display:block;width:100%}
+.aboutcontent .boxedcontent{margin-bottom:20px}
+.about_egh_container{display:flex;flex-direction:column;align-items:center}
+.git_list{display:inline-block;width:715px;height:115px;overflow:visible}
+@media(max-width:991px){
+ .git_list{width:100%;height:auto}
+ .extGitGraphContainer{width:95%;width:calc(100% - 16px)}
+}
+.git_list text.caption{font-size:10px;fill:#666}
+.git_list text.caption_month{font-size:8px;fill:#BBB}
+.git_list text.caption_day{font-size:8px;fill:#BBB}
+.svg-tip:after{box-sizing:border-box;position:absolute;left:50%;height:5px;width:5px;bottom:-10px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,0.8);-moz-border-top-colors:none;-moz-border-right-colors:none;-moz-border-bottom-colors:none;-moz-border-left-colors:none;border-image:none}
+.svg-tip{padding:5px;background:none repeat scroll 0 0 rgba(0,0,0,0.8);color:#BBB;font-size:12px;position:absolute;z-index:99999;text-align:center;border-radius:3px;box-sizing:border-box;opacity:0}
+.extGitGraphContainer{background-color:#fcfcfc;margin:10px;display:inline-block;border:1px solid #222;border-radius:0;box-shadow:0 0 1px rgba(0,0,0,0.25) inset}
+.egg_footer{margin-top:5px;text-align:right;margin-right:5px;margin-bottom:5px;color:#888}
+.egg_footer>a{text-decoration:none;color:inherit}
+.egg_footer>a:hover{text-decoration:none;color:#22F}
.euler_pnl_base{display:inline-flex;flex-direction:column;border:1px solid #AAA;border-radius:5px 5px 0 0;margin:15px}
.euler_pnl_header{display:flex;align-items:center;justify-content:center;padding:4px;background:#AAA}
.euler_pnl_header a{color:#222;text-decoration:none;font-family:Lato,"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:22px;font-weight:900}
diff --git a/www/data/css/styles.scss b/www/data/css/styles.scss
index 8d127d8..9e062be 100644
--- a/www/data/css/styles.scss
+++ b/www/data/css/styles.scss
@@ -9,6 +9,7 @@
@import 'styles_errorview';
@import 'styles_programslist';
@import 'styles_programsview';
+@import 'styles_about';
@import 'styles_eulerpanel';
@import 'styles_programspanel';
diff --git a/www/data/css/styles_about.scss b/www/data/css/styles_about.scss
new file mode 100644
index 0000000..467880c
--- /dev/null
+++ b/www/data/css/styles_about.scss
@@ -0,0 +1,104 @@
+@import 'styles_config';
+
+.aboutcontent {
+ display: block;
+ width: 100%;
+}
+
+.aboutcontent .boxedcontent{
+ margin-bottom: 20px;
+}
+
+.about_egh_container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.git_list {
+ display: inline-block;
+ width: 715px;
+ height: 115px;
+ overflow: visible;
+}
+
+@include rdmedia_range(0,2) {
+ .git_list { width: 100%; height: auto; }
+ .extGitGraphContainer { width: 95%; width: calc(100% - 16px); }
+}
+
+.git_list text.caption {
+ font-size: 10px;
+ fill: #666;
+}
+
+.git_list text.caption_month {
+ font-size: 8px;
+ fill: #BBB;
+}
+
+.git_list text.caption_day {
+ font-size: 8px;
+ fill: #BBB;
+}
+
+.svg-tip:after {
+ box-sizing: border-box;
+ position: absolute;
+ left: 50%;
+ height: 5px;
+ width: 5px;
+ bottom: -10px;
+ margin: 0 0 0px -5px;
+ content: " ";
+ border: 5px solid transparent;
+ border-top-color: rgba(0, 0, 0, 0.8);
+ -moz-border-top-colors: none;
+ -moz-border-right-colors: none;
+ -moz-border-bottom-colors: none;
+ -moz-border-left-colors: none;
+ border-image: none;
+}
+
+.svg-tip {
+ padding: 5px;
+ background: none repeat scroll 0 0 rgba(0, 0, 0, 0.8);
+ color: #BBB;
+ font-size: 12px;
+ position: absolute;
+ z-index: 99999;
+ text-align: center;
+ border-radius: 3px;
+ box-sizing: border-box;
+ opacity: 0;
+}
+
+.extGitGraphContainer {
+ background-color: #FCFCFC;
+ margin: 10px;
+ display: inline-block;
+
+ border: 1px solid #222;
+ border-radius: 0;
+ box-shadow: 0 0 1px rgba(0, 0, 0, 0.25) inset;
+}
+
+.egg_footer {
+ margin-top: 5px;
+
+ text-align: right;
+ margin-right: 5px;
+ margin-bottom: 5px;
+
+ color: #888;
+}
+
+.egg_footer > a {
+ text-decoration: none;
+ color: inherit;
+}
+
+.egg_footer > a:hover {
+ text-decoration: none;
+ color: #22F;
+}
\ No newline at end of file
diff --git a/www/data/css/styles_blogview.scss b/www/data/css/styles_blogview.scss
index 5cb3108..822c0b3 100644
--- a/www/data/css/styles_blogview.scss
+++ b/www/data/css/styles_blogview.scss
@@ -1,23 +1,5 @@
@import 'styles_config';
-.blogcontent {
- color: $COL_TEXT_DARK;
- border: 1px solid black;
- background-color: $COL_BACKGROUND_2;
- width: 90%;
- margin-left: auto;
- margin-right: auto;
-}
-
-.bc_header {
- background-color: #BBB;
- padding: 0 4px;
-}
-
-.bc_data {
- padding: 8px;
-}
-
.base_markdown {
code {
@@ -115,3 +97,5 @@
background: transparent !important;
}
}
+
+.blogcontent_euler, .blogcontent_markdown, .blogcontent_plain { width: 90%;}
diff --git a/www/data/css/styles_global.scss b/www/data/css/styles_global.scss
index 020e6cd..fef109e 100644
--- a/www/data/css/styles_global.scss
+++ b/www/data/css/styles_global.scss
@@ -86,3 +86,21 @@ body {
width:0 !important;
height:0 !important;
}
+
+.boxedcontent {
+ color: $COL_TEXT_DARK;
+ border: 1px solid black;
+ background-color: $COL_BACKGROUND_2;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+
+ .bc_header {
+ background-color: #BBB;
+ padding: 0 4px;
+ }
+
+ .bc_data {
+ padding: 8px;
+ }
+}
\ No newline at end of file
diff --git a/www/data/javascript/egh.js b/www/data/javascript/egh.js
new file mode 100644
index 0000000..b1469e2
--- /dev/null
+++ b/www/data/javascript/egh.js
@@ -0,0 +1,57 @@
+function formatDate(date) {
+ const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+ const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+
+ let wday = days[date.getDay()];
+ let day = date.getDate();
+ let monthIndex = date.getMonth();
+ let year = date.getFullYear();
+
+ let suffix = 'th';
+ if (day === 1) suffix = 'st';
+ if (day === 2) suffix = 'nd';
+ if (day === 3) suffix = 'rd';
+
+ return wday + ' ' + day + suffix + ' ' + monthNames[monthIndex] + ', ' + year;
+}
+
+window.onload = function ()
+{
+ let svgtips = document.getElementsByClassName("svg-tip");
+ let rects = document.getElementsByClassName("egg_rect");
+
+ let masterTip = null;
+
+ for (let tip of svgtips)
+ {
+ tip.style.opacity = '1';
+ tip.style.display = 'none';
+
+ masterTip = tip;
+ }
+
+ let masterTipHeader = masterTip.getElementsByTagName('strong')[0];
+ let masterTipContent = masterTip.getElementsByTagName('span')[0];
+
+ for (let rect of rects)
+ {
+ rect.addEventListener("mouseenter", function(event)
+ {
+ let datesplit = event.target.getAttribute('data-date').split('-');
+ let count = event.target.getAttribute('data-count');
+ let date = new Date(Number(datesplit[0]), Number(datesplit[1])-1, Number(datesplit[2]));
+
+ masterTip.style.display = 'block';
+
+ masterTipHeader.innerHTML = count + ' commits';
+ masterTipContent.innerHTML = ' on ' + formatDate(date);
+
+ masterTip.style.left = (window.pageXOffset + event.target.getBoundingClientRect().left - masterTip.getBoundingClientRect().width /2 - 3.5 + 9) + 'px';
+ masterTip.style.top = (window.pageYOffset + event.target.getBoundingClientRect().top - masterTip.getBoundingClientRect().height -10) + 'px';
+ });
+ rect.addEventListener("mouseleave", function(event)
+ {
+ masterTip.style.display = 'none';
+ });
+ }
+};
\ No newline at end of file
diff --git a/www/dynamic/.gitignore b/www/dynamic/.gitignore
new file mode 100644
index 0000000..0318876
--- /dev/null
+++ b/www/dynamic/.gitignore
@@ -0,0 +1,3 @@
+*
+!.gitignore
+!.gitkeep
\ No newline at end of file
diff --git a/www/dynamic/.gitkeep b/www/dynamic/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/www/extern/egh/ConnectionGitea.php b/www/extern/egh/ConnectionGitea.php
new file mode 100644
index 0000000..922c7b0
--- /dev/null
+++ b/www/extern/egh/ConnectionGitea.php
@@ -0,0 +1,39 @@
+owner = $owner;
+ }
+
+ public function setURL($giteaurl) {
+ $this->url = $giteaurl;
+ }
+
+ /* @return SingleCommitInfo[] */
+ public function getDataUser($cfg)
+ {
+ $result = []; //TODO
+
+ return $result;
+ }
+
+ /* @return SingleCommitInfo[] */
+ public function getDataRepository($cfg)
+ {
+ $result = []; //TODO
+
+ return $result;
+ }
+}
\ No newline at end of file
diff --git a/www/extern/egh/ConnectionGithub.php b/www/extern/egh/ConnectionGithub.php
new file mode 100644
index 0000000..bd2aa3c
--- /dev/null
+++ b/www/extern/egh/ConnectionGithub.php
@@ -0,0 +1,166 @@
+owner = $owner;
+ }
+
+ public function setAPIToken($token) {
+ $this->token = $token;
+ }
+
+ public function queryAPIToken($client_id, $client_secret) {
+ $url = Utils::sharpFormat(self::URL_OAUTH_TOKEN, ['id'=>$client_id, 'secret'=>$client_secret, 'code'=>'egh']);
+ $result = file_get_contents($url);
+
+ $result = str_replace('access_token=', '', $result);
+ $result = str_replace('&scope=&token_type=bearer', '', $result);
+
+ $this->setAPIToken($result);
+ }
+
+ /**
+ * @param $cfg EGHRemoteConfig
+ * @return SingleCommitInfo[]
+ */
+ public function getDataUser($cfg)
+ {
+ $repos = $this->listRepositoriesByUser($cfg->Param);
+
+ $result = [];
+ foreach ($repos as $repo)
+ {
+ $commits = $this->listCommitsFromRepo($repo, $cfg->Author);
+ foreach ($commits as $c) $result []= $c;
+ }
+
+ return $result;
+ }
+
+
+ /**
+ * @param $cfg EGHRemoteConfig
+ * @return SingleCommitInfo[]
+ */
+ public function getDataRepository($cfg)
+ {
+ return $this->listCommitsFromRepo($cfg->Param, $cfg->Author);
+ }
+
+ /**
+ * @param $user string
+ * @return string[]
+ */
+ private function listRepositoriesByUser($user)
+ {
+ $result = [];
+
+ $page = 1;
+ $url = Utils::sharpFormat(self::API_REPOSITORIESLIST, ['user'=>$user, 'page'=>$page, 'token'=>$this->token]);
+
+ $json = $this->getJSON($url);
+
+ while (! empty($json)) {
+ foreach ($json as $result_repo) {
+ $result []= $result_repo->{'full_name'};
+ $this->owner->out("Found Repo: " . $result_repo->{'full_name'});
+ }
+
+ $page++;
+ $url = Utils::sharpFormat(self::API_REPOSITORIESLIST, ['user'=>$user, 'page'=>$page, 'token'=>$this->token]);
+ $json = $this->getJSON($url);
+ }
+
+ return $result;
+ }
+
+ /**
+ * @param $repo string
+ * @param $user string
+ * @return SingleCommitInfo[]
+ */
+ private function listCommitsFromRepo($repo, $user)
+ {
+ $page = 1;
+ $url = Utils::sharpFormat(self::API_COMMITSLIST, ['repo'=>$repo, 'author'=>$user, 'page'=>$page, 'token'=>$this->token]);
+
+ $result = $this->getJSON($url);
+
+ $commit_list = [];
+
+ while (! empty($result)) {
+ foreach ($result as $rc) $commit_list[] = new SingleCommitInfo(DateTime::createFromFormat(DateTime::ISO8601, $rc->{'commit'}->{'author'}->{'date'}), 'github', $user, $repo);
+ $this->owner->out("Found " . count($result) . " Commits in " . $repo);
+
+ $page++;
+ $url = Utils::sharpFormat(self::API_COMMITSLIST, [ 'repo'=>$repo, 'author'=>$user, 'page'=>$page, 'token'=>$this->token ]);
+ $result = $this->getJSON($url);
+ }
+
+ return $commit_list;
+ }
+ public function getJSON($url) {
+ if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
+ $options =
+ [
+ 'http' =>
+ [
+ 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
+ 'header' => 'Authorization: token ' . $this->token,
+ ],
+ 'https' =>
+ [
+ 'user_agent' => $_SERVER['HTTP_USER_AGENT'],
+ 'header' => 'Authorization: token ' . $this->token,
+ ],
+ ];
+ } else {
+ $options =
+ [
+ 'http' =>
+ [
+ 'user_agent' => 'ExtendedGitGraph_for_mikescher.com',
+ 'header' => 'Authorization: token ' . $this->token,
+ ],
+ 'https' =>
+ [
+ 'user_agent' => 'ExtendedGitGraph_for_mikescher.com',
+ 'header' => 'Authorization: token ' . $this->token,
+ ],
+ ];
+ }
+
+ $context = stream_context_create($options);
+
+ $response = @file_get_contents($url, false, $context);
+
+ if ($response === false)
+ {
+ $this->owner->out("Error recieving json: '" . $url . "'");
+ return [];
+ }
+
+ return json_decode($response);
+ }
+
+}
\ No newline at end of file
diff --git a/www/extern/egh/EGHRemoteConfig.php b/www/extern/egh/EGHRemoteConfig.php
new file mode 100644
index 0000000..1a11566
--- /dev/null
+++ b/www/extern/egh/EGHRemoteConfig.php
@@ -0,0 +1,27 @@
+Type = $typ;
+ $this->URL = $url;
+ $this->Author = $usr;
+ $this->Param = $param;
+ }
+
+}
\ No newline at end of file
diff --git a/www/extern/egh/EGHRenderer.php b/www/extern/egh/EGHRenderer.php
new file mode 100644
index 0000000..6258fad
--- /dev/null
+++ b/www/extern/egh/EGHRenderer.php
@@ -0,0 +1,224 @@
+ ['#F5F5F5', '#DBDEE0', '#C2C7CB', '#AAB0B7', '#9099A2', '#77828E', '#5E6B79', '#455464', '#2C3E50'],
+ 'standard' => ["#ebedf0", "#c6e48b", "#7bc96f", "#239a3b", "#196127"],
+ 'modern' => ["#afaca8", "#d6e685", "#8cc665", "#44a340", "#1e6823"],
+ 'gray' => ["#eeeeee", "#bdbdbd", "#9e9e9e", "#616161", "#212121"],
+ 'red' => ["#eeeeee", "#ff7171", "#ff0000", "#b70000", "#830000"],
+ 'blue' => ["#eeeeee", "#6bcdff", "#00a1f3", "#0079b7", "#003958"],
+ 'purple' => ["#eeeeee", "#d2ace6", "#aa66cc", "#660099", "#4f2266"],
+ 'orange' => ["#eeeeee", "#ffcc80", "#ffa726", "#fb8c00", "#e65100"],
+ 'halloween' => ["#eeeeee", "#ffee4a", "#ffc501", "#fe9600", "#03001c"],
+ ];
+
+ const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ const DAYS = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
+
+ /* @var ExtendedGitGraph */
+ private $owner;
+ /* @var SingleCommitInfo[] */
+ public $data;
+ /* @var string */
+ public $colorScheme = 'standard';
+ /* @var int[] */
+ public $yearList;
+ /* @var array */
+ public $commitMap; // date('Y-m-d') -> count
+
+ public function __construct($egh) {
+ $this->owner = $egh;
+ }
+
+ /**
+ * @param $data SingleCommitInfo[]
+ */
+ public function init($data)
+ {
+ $this->data = $data;
+
+ $this->yearList = $this->getYears($data);
+ $this->owner->out("Found " . count($this->yearList) . " year to generate.");
+
+ $this->commitMap = $this->generateCommitMap($data, $this->yearList);
+ $this->owner->out("Commitmap with ".count($this->commitMap)." entries generated.");
+ }
+
+ /**
+ * @param $data SingleCommitInfo[]
+ * @return int[]
+ */
+ public function getYears($data) {
+ $years = array();
+
+ foreach ($data as $commit) {
+ if(! in_array($commit->Timestamp->format('Y'), $years))
+ $years[] = intval($commit->Timestamp->format('Y'));
+ }
+
+ asort($years);
+
+ return $years;
+ }
+
+ /**
+ * @param $data SingleCommitInfo[]
+ * @param $yearList int[]
+ * @return array
+ */
+ private function generateCommitMap($data, $yearList)
+ {
+ $result = [];
+
+ foreach ($yearList as $year)
+ {
+ $ymap = [];
+
+ $date = new DateTime($year . '-01-01');
+ while($date->format('Y') == $year)
+ {
+ $ymap[$date->format('Y-m-d')] = 0;
+ $date = $date->modify("+1 day");
+ }
+
+ foreach ($data as $commit)
+ {
+ if(array_key_exists($commit->Timestamp->format('Y-m-d'), $ymap)) $ymap[$commit->Timestamp->format('Y-m-d')]++;
+ }
+
+ $result = array_merge($result, $ymap);
+ }
+
+
+ return $result;
+ }
+
+ /**
+ * @param $year int
+ * @return int
+ */
+ private function getMaxCommitCount($year)
+ {
+ $max = 0;
+ foreach ($this->commitMap as $date => $count) if (Utils::startsWith($date, strval($year))) $max = max($max, $count);
+ return $max;
+ }
+
+ /**
+ * @param $year int
+ * @return string
+ */
+ public function render($year)
+ {
+ $now = new DateTime();
+ $date = new DateTime($year . '-01-01');
+ $monthlist = array_fill(0, 12, [0, 0]);
+ $colors = self::COLOR_SCHEMES[$this->colorScheme];
+
+ $ymapmax = $this->getMaxCommitCount($year);
+ $exponent = log(0.98/(count($colors)-1), 1/$ymapmax); // (1/max)^n = 0.98 // => 1 commit erreicht immer genau die erste stufe
+
+ $html = '';
+
+ $html .= '
' . "\n";
+ $html .= '
' . "\n";
+ $html .= '
' . "\n";
+ $html .= ' ' . "\n";
+ $html .= '
' . "\n";
+ $html .= '' . "\n";
+ $html .= '
' . "\n";
+
+
+ return $html;
+ }
+}
\ No newline at end of file
diff --git a/www/extern/egh/ExtendedGitGraph.php b/www/extern/egh/ExtendedGitGraph.php
new file mode 100644
index 0000000..9e16726
--- /dev/null
+++ b/www/extern/egh/ExtendedGitGraph.php
@@ -0,0 +1,184 @@
+filenamecache = $filename_cache;
+ $this->remoteconfigs = [];
+ $this->ConnectionGithub = new ConnectionGithub($this);
+ $this->ConnectionGitea = new ConnectionGitea($this);
+ $this->outputMode = $outmode;
+ $this->logFilePath = $logfile;
+ }
+
+ public function addRemote($type, $url, $user, $param) {
+ $this->remoteconfigs []= new EGHRemoteConfig($type, $url, $user, $param);
+ }
+
+ public function setColorScheme($s) {
+ $this->colorScheme = $s;
+ }
+
+ public function out($txt)
+ {
+ if ($txt !== '') $txt = '[' . date('H:i:s') . '] ' . $txt;
+
+ if ($this->outputMode === self::OUT_SESSION)
+ {
+ if (session_status() !== PHP_SESSION_ACTIVE) session_start();
+
+ $_SESSION[self::PROGRESS_SESSION_COOKIE] .= $txt . "\r\n";
+ session_commit();
+ }
+ else if ($this->outputMode === self::OUT_STDOUT)
+ {
+ print $txt;
+ print "\r\n";
+ }
+
+ $logfile = Utils::sharpFormat($this->logFilePath, ['num'=>'']);
+ file_put_contents($logfile, $txt.PHP_EOL , FILE_APPEND | LOCK_EX);
+ }
+
+ public function init()
+ {
+ if ($this->outputMode === self::OUT_SESSION)
+ {
+ if (session_status() !== PHP_SESSION_ACTIVE) session_start();
+ $_SESSION[self::PROGRESS_SESSION_COOKIE] = '';
+ session_commit();
+ }
+
+ $f3 = Utils::sharpFormat($this->logFilePath, ['num'=>'_3']);
+ $f2 = Utils::sharpFormat($this->logFilePath, ['num'=>'_2']);
+ $f1 = Utils::sharpFormat($this->logFilePath, ['num'=>'_1']);
+ $f0 = Utils::sharpFormat($this->logFilePath, ['num'=>'' ]);
+
+ if (file_exists($f3)) @unlink($f3);
+ if (file_exists($f2)) @rename($f2, $f3);
+ if (file_exists($f1)) @rename($f1, $f2);
+ if (file_exists($f0)) @rename($f0, $f1);
+ if (file_exists($f0)) @unlink($f0);
+
+ $this->out('EXTENDED_GIT_GRAPH started');
+ $this->out('');
+ }
+
+ public function updateFromRemotes()
+ {
+ $data = [];
+
+ foreach ($this->remoteconfigs as $cfg)
+ {
+ if ($cfg->Type === 'github-user')
+ $data = array_merge($data, $this->ConnectionGithub->getDataUser($cfg));
+ else if ($cfg->Type === 'github-repository')
+ $data = array_merge($data, $this->ConnectionGithub->getDataRepository($cfg));
+ else if ($cfg->Type === 'gitea-user')
+ $data = array_merge($data, $this->ConnectionGitea->getDataUser($cfg));
+ else if ($cfg->Type === 'gitea-repository')
+ $data = array_merge($data, $this->ConnectionGitea->getDataRepository($cfg));
+ else
+ $this->out("Unknown type: " . $cfg->Type);
+ }
+
+ $this->out("Found " . count($data) . " commits.");
+
+ file_put_contents($this->filenamecache, serialize($data));
+
+ $this->queriedData = $data;
+
+ }
+
+ public function updateFromCache()
+ {
+ if (file_exists($this->filenamecache))
+ $this->queriedData = unserialize(file_get_contents($this->filenamecache));
+ else
+ $this->queriedData = [];
+ }
+
+ public function generate()
+ {
+ $renderer = new EGHRenderer($this);
+ $renderer->colorScheme = $this->colorScheme;
+
+ $renderer->init($this->queriedData);
+
+ $this->renderedHTML = [];
+ foreach ($renderer->yearList as $y) $this->renderedHTML[$y] = $renderer->render($y);
+ }
+
+ /**
+ * @param $url string
+ * @return array|mixed
+ */
+ public function getJSON($url) {
+ if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
+ $options =
+ [
+ 'http' => ['user_agent'=> $_SERVER['HTTP_USER_AGENT']],
+ 'https' => ['user_agent'=> $_SERVER['HTTP_USER_AGENT']],
+ ];
+ } else {
+ $options =
+ [
+ 'http' => ['user_agent'=> 'ExtendedGitGraph_for_mikescher.com'],
+ 'https' => ['user_agent'=> 'ExtendedGitGraph_for_mikescher.com'],
+ ];
+ }
+
+ $context = stream_context_create($options);
+
+ $response = @file_get_contents($url, false, $context);
+
+ if ($response === false)
+ {
+ $this->out("Error recieving json: '" . $url . "'");
+ return [];
+ }
+
+ return json_decode($response);
+ }
+
+ public function get()
+ {
+ return $this->renderedHTML;
+ }
+}
\ No newline at end of file
diff --git a/www/extern/egh/SingleCommitInfo.php b/www/extern/egh/SingleCommitInfo.php
new file mode 100644
index 0000000..8da17bb
--- /dev/null
+++ b/www/extern/egh/SingleCommitInfo.php
@@ -0,0 +1,31 @@
+Timestamp = $ts;
+ $this->SourcePlatform = $src;
+ $this->SourceUser = $usr;
+ $this->SourceRepository = $repo;
+ }
+
+
+}
\ No newline at end of file
diff --git a/www/extern/egh/Utils.php b/www/extern/egh/Utils.php
new file mode 100644
index 0000000..99ddaea
--- /dev/null
+++ b/www/extern/egh/Utils.php
@@ -0,0 +1,19 @@
+ $val)
+ {
+ $str = str_replace('{'.$key.'}', $val, $str);
+ }
+ return $str;
+ }
+
+ public static function startsWith($haystack, $needle)
+ {
+ $length = strlen($needle);
+ return (substr($haystack, 0, $length) === $needle);
+ }
+}
\ No newline at end of file
diff --git a/www/fragments/befunge93_runner.php b/www/fragments/befunge93_runner.php
index 914bdc2..f7fe09d 100644
--- a/www/fragments/befunge93_runner.php
+++ b/www/fragments/befunge93_runner.php
@@ -58,7 +58,7 @@ if ($interactive) {
$result .= ' ' . "\n";
$result .= '' . "\n";
- $result .= includeScriptOnce("/data/javascript/blogpost_bef93runner.js", false) . "\n";
+ $result .= includeScriptOnce("/data/javascript/blogpost_bef93runner.js", false, '') . "\n";
}
else
{
diff --git a/www/fragments/bfjoust_runner.php b/www/fragments/bfjoust_runner.php
index d7d5a23..c643738 100644
--- a/www/fragments/bfjoust_runner.php
+++ b/www/fragments/bfjoust_runner.php
@@ -35,6 +35,6 @@ $result .= '' . "\n";
$result .= '' . "\n";
-$result .= includeScriptOnce("/data/javascript/blogpost_BFJoustBot_script.js", false) . "\n";
+$result .= includeScriptOnce("/data/javascript/blogpost_BFJoustBot_script.js", false, '') . "\n";
return $result;
\ No newline at end of file
diff --git a/www/fragments/blogview_euler_list.php b/www/fragments/blogview_euler_list.php
index ad465f6..04a5345 100644
--- a/www/fragments/blogview_euler_list.php
+++ b/www/fragments/blogview_euler_list.php
@@ -8,7 +8,7 @@ $problems = Euler::listAll();
?>
-