diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file
diff --git a/example.png b/example.png
new file mode 100755
index 0000000..c8851f9
--- /dev/null
+++ b/example.png
Binary files differ

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file
diff --git a/example.png b/example.png
new file mode 100755
index 0000000..c8851f9
--- /dev/null
+++ b/example.png
Binary files differ
diff --git a/index.php b/index.php
new file mode 100755
index 0000000..fb41358
--- /dev/null
+++ b/index.php
@@ -0,0 +1,612 @@
+<?php
+/*
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+*/
+session_start();
+include('config.php');
+$error = "";
+
+if(isset($_REQUEST['password']) && md5($_REQUEST['password']) == $password){
+	$_SESSION['loggedin'] = true;
+}
+
+if(!isset($_SESSION['loggedin']) || isset($_GET['logout'])){
+	if(isset($_SESSION['loggedin']))
+		unset($_SESSION['loggedin']);
+	include('login.html');
+	die();
+}
+
+/***
+ * actions here for API / AJAX 
+ */
+if(isset($_GET['action'])){
+	switch ($_GET['action']) {
+		case 'main_cal': // get unfiltered main cal averages - output JSON
+			header('Content-Type: application/json');
+			$result = main_cal();
+			echo "{".$result."}";
+			break;
+		case 'filtered_cal': // get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+			header('Content-Type: application/json');
+			if(isset($_GET['filter'])){
+				$result = filtered_cal($_GET['filter']);
+				echo "{".$result."}";
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date': // get specific date's log - output HTML
+			if(isset($_GET['date'])){
+				$result = today($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date_average': // get specific date's average - output no.
+			if(isset($_GET['date'])){
+				$result = day_avg($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'latest': // get latest 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = latest($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'top': // get top 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = toptag($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'alltag': // get all tags in popularity order - output JSON
+			$result = alltag();
+			echo $result;
+			break;
+		case 'save':
+			if(isset($_GET['log'])){ // save a new moodlog
+				$result = new_log($_GET['log']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		default:
+			# code...
+			break;
+	}
+	die();
+}
+
+//$result = today("2018-09-13");
+//echo $result;
+
+function today($ymd){
+	global $moodlog;
+	$ymd = strtotime($ymd);
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$ymd2 = date("Y-m-d", strtotime("$date"));
+//echo $ymd2;
+
+	$returnstring = "<div class=\"sub-header\">$justdate</div>\n";
+	$count = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("$ymd2 -0 day")));
+
+	     	$newpos = array();
+	     	$newneg = array();
+	     	$newcon = array();
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = $word;
+		        			break;
+		        		case '-':
+		        			$newneg[] = $word;
+		        			break;
+		        		case '@':
+		        			$newcon[] = $word;
+		        			break;
+		        		default:
+		        			$newstr .= " $word";
+		        			break;
+		        	}
+		        }
+	        }
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+	        $justdate = date("Y-m-d", strtotime($datetime));
+	        if(strtotime($ymd2) == strtotime($justdate)){
+	        	$count++;
+		        $mood = $split2[0];
+		        $fulldate = date("Y-m-d H:i", strtotime($datetime));
+				$returnstring .= "<span class=\"datehist\">$fulldate</span>\n<span class=\"hpyhist\">[$mood]</span><span class=\"pretexthist\">$newstr</span>\n";
+
+				foreach($newpos as $pos)
+		       		$returnstring .= "<span class=\"preposhist\" onclick=\"addFilterPos($(this).text());\">$pos</span>\n";
+		       	foreach($newneg as $neg)
+		       		$returnstring .= "<span class=\"preneghist\" onclick=\"addFilterNeg($(this).text());\">$neg</span>\n";
+		       	foreach($newcon as $con)
+		       		$returnstring .= "<span class=\"preconhist\" onclick=\"addFilterCon($(this).text());\">$con</span>\n";
+		       	$returnstring .= "<br />";
+	     	}
+	       	
+	    }
+	    fclose($moodfile);
+	    return ($count > 0)? $returnstring : "0";
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function main_cal(){
+	global $moodlog;
+	$toreturn = "";
+	
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        //$justdate = date("Y-m-d", strtotime($datetime));
+	         //$dt2 = explode("-", $datetime);
+		 //$dtd = explode(" ", $dt2[2]);
+		 //$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+		 //$dateTime->setDate($dt2[0], $dt2[1], $dtd[0]);
+		 //$justdate = $dateTime->format('Y-m-d');
+		$dtd = explode(" ", $datetime);
+		$justdate = $dtd[0];
+
+		$newtimes[$justdate][] = $mood;
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	
+//$datetime = strtotime($date);
+		$dt22 = explode("-", $date);
+                $dtd2 = explode(" ", $dt22[2]);
+                $dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+                $dateTime->setDate($dt22[0], $dt22[1], $dtd2[0]);
+                $justdate2 = $dateTime->getTimestamp();
+
+	    	$toreturn .= "\"$justdate2\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function filtered_cal($filter){
+	global $moodlog;
+	$toreturn = "";
+
+	$pattern = '/(?=[+-@][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY;
+	$tags = preg_split ($pattern, $filter, $limit, $flags);
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        $justdate = date("Y-m-d", strtotime($datetime));
+
+	        $words = explode(" ", $split2[1]);
+	        
+	        foreach($words as $word){
+	        	$word = trim($word);
+	        	if (in_array($word, $tags, true))
+	        		$newtimes[$justdate][] = $mood;
+	        }
+	        
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	$datetime = strtotime("$date");
+	    	$toreturn .= "\"$datetime\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function day_avg($ymd){
+	global $moodlog;
+	$mood = array();
+	$average = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	//$date = date("Y-m-d", $ymd);
+	//$date = date("Y-m-d", strtotime("$date +1 day"));
+
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$date = date("Y-m-d", strtotime("$date"));
+
+	//$currentTime = new DateTime();
+	//$currentTime = DateTime::createFromFormat( 'U', $ymd );
+	//$date = $currentTime->format( 'c' );
+
+	$cutoff = strtotime("$date -0 day");
+	
+	//echo $date." cutoff: ".$cutoff;
+	//$date = new DateTime();
+	//$date->setTimestamp($ymd);
+	//echo $date->format('U = Y-m-d H:i:s') . "\n";
+
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        if(strncmp($date, $datetime, 10) == 0 )
+		        $mood[] = $split2[0];	
+	    }
+	 //   echo "$ymd ";
+	 //   echo $date;
+	 //   print_r($mood);
+	    if($mood)
+	    	$average = round(array_sum($mood) / count($mood));
+	    return $average;
+	} else {
+	    return "0";
+	} 
+}
+
+function latest($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$newpos = array_unique($newpos);
+				$newArray = array_slice($newpos, 0, 5, false);
+				break;
+			case 'neg':
+				$newneg = array_unique($newneg);
+				$newArray = array_slice($newneg, 0, 5, false);
+				break;
+			case 'con':
+				$newcon = array_unique($newcon);
+				$newArray = array_slice($newcon, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function toptag($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$acv=array_count_values($newpos); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'neg':
+				$acv=array_count_values($newneg); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'con':
+				$acv=array_count_values($newcon); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function alltag(){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newtag= array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newtag[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }  	
+	    }
+	    fclose($moodfile);
+	    
+		$acv=array_count_values($newtag); 
+		arsort($acv); 
+		$result=array_keys($acv); 
+		
+		return json_encode($result);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function new_log($log){
+	global $moodlog;
+	$pattern = '/(?=[+-@|][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
+	$result = preg_split ($pattern, $log, $limit, $flags);
+	//print_r($result);
+
+	$timestamp = date("Y-m-d H:i");
+	$no = rtrim($result[0], "|");
+	$msg = "";
+	$pos = "";
+	$neg = "";
+	$con = "";
+
+	foreach($result as $item){
+		switch ($item[0]) {
+			case '|':
+				$msg .= substr($item, 1)." ";
+				break;
+			case '+':
+				$pos .= "$item ";
+				break;
+			case '-':
+				$neg .= "$item ";
+				break;
+			case '@':
+				$con .= "$item ";
+				break;
+		}
+	}
+	$toadd = "$timestamp [$no] ".$msg.$pos.$neg.$con."\n";
+	$toadd .= file_get_contents($moodlog);
+	file_put_contents($moodlog, $toadd);
+	echo "1";
+}
+
+?>
+
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+	</head>
+	<body>
+		
+		<center>
+			<?php if($error <> ""){echo $error; } ?>
+
+			<div class="banner">
+				<div class="header"><a href="/?logout"><i class="fas fa-heartbeat" ></i></a> moodlog.txt</div>
+
+				<div class="new-log">
+					
+					  <input type="range" id="happyval" value="5" min="1" max="10"/>
+					  <input  class="input" id="tags" placeholder="(+,-,@) description"/>
+					  <input type="button" value="+" onClick="updatePretext();"/>
+					  <input type="button" value="add" class="add" onClick="submitMood();"/>
+					
+				</div>
+				<div class="preview">
+					<span class="date">2018-09-11 20:27</span><span class="hpyno">[5]</span><span class="pretext" onClick="updatePretext();"></span></div>
+
+				<div class="filter" style="display:none">
+					<span class="filtitle">Filters:</span>
+					<span class="fas fa-search" style="float:right;font-size:15px;" onclick="applyFilters();"></span>
+				</div>
+			</div>
+
+			<div id="cal-heatmap"></div>
+
+			<div class="top10s">
+				<div class="toppos">
+					<div class="sub-header">Top 5 positive</div>
+				</div>
+				<div class="topneg">
+					<div class="sub-header">Top 5 negative</div>
+				</div>
+				<div class="topcon">
+					<div class="sub-header">Top 5 context</div>
+				</div>
+				<div class="latpos">
+					<div class="sub-header">Latest 5 positive</div>
+				</div>
+				<div class="latneg">
+					<div class="sub-header">Latest 5 negative</div>
+				</div>
+				<div class="latcon">
+					<div class="sub-header">Latest 5 context</div>
+				</div>
+			</div>
+
+			<div class="fullday">
+				<div class="previewhist">
+					
+					<?php
+						$result = today(date("Y-m-d"));
+						if($result != "0")
+							echo $result;
+					?>
+					
+				</div>
+			</div>
+		</center>
+
+		<script src="script.js"></script>
+ 
+	</body>
+</html>

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file
diff --git a/example.png b/example.png
new file mode 100755
index 0000000..c8851f9
--- /dev/null
+++ b/example.png
Binary files differ
diff --git a/index.php b/index.php
new file mode 100755
index 0000000..fb41358
--- /dev/null
+++ b/index.php
@@ -0,0 +1,612 @@
+<?php
+/*
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+*/
+session_start();
+include('config.php');
+$error = "";
+
+if(isset($_REQUEST['password']) && md5($_REQUEST['password']) == $password){
+	$_SESSION['loggedin'] = true;
+}
+
+if(!isset($_SESSION['loggedin']) || isset($_GET['logout'])){
+	if(isset($_SESSION['loggedin']))
+		unset($_SESSION['loggedin']);
+	include('login.html');
+	die();
+}
+
+/***
+ * actions here for API / AJAX 
+ */
+if(isset($_GET['action'])){
+	switch ($_GET['action']) {
+		case 'main_cal': // get unfiltered main cal averages - output JSON
+			header('Content-Type: application/json');
+			$result = main_cal();
+			echo "{".$result."}";
+			break;
+		case 'filtered_cal': // get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+			header('Content-Type: application/json');
+			if(isset($_GET['filter'])){
+				$result = filtered_cal($_GET['filter']);
+				echo "{".$result."}";
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date': // get specific date's log - output HTML
+			if(isset($_GET['date'])){
+				$result = today($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date_average': // get specific date's average - output no.
+			if(isset($_GET['date'])){
+				$result = day_avg($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'latest': // get latest 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = latest($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'top': // get top 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = toptag($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'alltag': // get all tags in popularity order - output JSON
+			$result = alltag();
+			echo $result;
+			break;
+		case 'save':
+			if(isset($_GET['log'])){ // save a new moodlog
+				$result = new_log($_GET['log']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		default:
+			# code...
+			break;
+	}
+	die();
+}
+
+//$result = today("2018-09-13");
+//echo $result;
+
+function today($ymd){
+	global $moodlog;
+	$ymd = strtotime($ymd);
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$ymd2 = date("Y-m-d", strtotime("$date"));
+//echo $ymd2;
+
+	$returnstring = "<div class=\"sub-header\">$justdate</div>\n";
+	$count = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("$ymd2 -0 day")));
+
+	     	$newpos = array();
+	     	$newneg = array();
+	     	$newcon = array();
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = $word;
+		        			break;
+		        		case '-':
+		        			$newneg[] = $word;
+		        			break;
+		        		case '@':
+		        			$newcon[] = $word;
+		        			break;
+		        		default:
+		        			$newstr .= " $word";
+		        			break;
+		        	}
+		        }
+	        }
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+	        $justdate = date("Y-m-d", strtotime($datetime));
+	        if(strtotime($ymd2) == strtotime($justdate)){
+	        	$count++;
+		        $mood = $split2[0];
+		        $fulldate = date("Y-m-d H:i", strtotime($datetime));
+				$returnstring .= "<span class=\"datehist\">$fulldate</span>\n<span class=\"hpyhist\">[$mood]</span><span class=\"pretexthist\">$newstr</span>\n";
+
+				foreach($newpos as $pos)
+		       		$returnstring .= "<span class=\"preposhist\" onclick=\"addFilterPos($(this).text());\">$pos</span>\n";
+		       	foreach($newneg as $neg)
+		       		$returnstring .= "<span class=\"preneghist\" onclick=\"addFilterNeg($(this).text());\">$neg</span>\n";
+		       	foreach($newcon as $con)
+		       		$returnstring .= "<span class=\"preconhist\" onclick=\"addFilterCon($(this).text());\">$con</span>\n";
+		       	$returnstring .= "<br />";
+	     	}
+	       	
+	    }
+	    fclose($moodfile);
+	    return ($count > 0)? $returnstring : "0";
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function main_cal(){
+	global $moodlog;
+	$toreturn = "";
+	
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        //$justdate = date("Y-m-d", strtotime($datetime));
+	         //$dt2 = explode("-", $datetime);
+		 //$dtd = explode(" ", $dt2[2]);
+		 //$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+		 //$dateTime->setDate($dt2[0], $dt2[1], $dtd[0]);
+		 //$justdate = $dateTime->format('Y-m-d');
+		$dtd = explode(" ", $datetime);
+		$justdate = $dtd[0];
+
+		$newtimes[$justdate][] = $mood;
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	
+//$datetime = strtotime($date);
+		$dt22 = explode("-", $date);
+                $dtd2 = explode(" ", $dt22[2]);
+                $dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+                $dateTime->setDate($dt22[0], $dt22[1], $dtd2[0]);
+                $justdate2 = $dateTime->getTimestamp();
+
+	    	$toreturn .= "\"$justdate2\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function filtered_cal($filter){
+	global $moodlog;
+	$toreturn = "";
+
+	$pattern = '/(?=[+-@][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY;
+	$tags = preg_split ($pattern, $filter, $limit, $flags);
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        $justdate = date("Y-m-d", strtotime($datetime));
+
+	        $words = explode(" ", $split2[1]);
+	        
+	        foreach($words as $word){
+	        	$word = trim($word);
+	        	if (in_array($word, $tags, true))
+	        		$newtimes[$justdate][] = $mood;
+	        }
+	        
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	$datetime = strtotime("$date");
+	    	$toreturn .= "\"$datetime\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function day_avg($ymd){
+	global $moodlog;
+	$mood = array();
+	$average = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	//$date = date("Y-m-d", $ymd);
+	//$date = date("Y-m-d", strtotime("$date +1 day"));
+
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$date = date("Y-m-d", strtotime("$date"));
+
+	//$currentTime = new DateTime();
+	//$currentTime = DateTime::createFromFormat( 'U', $ymd );
+	//$date = $currentTime->format( 'c' );
+
+	$cutoff = strtotime("$date -0 day");
+	
+	//echo $date." cutoff: ".$cutoff;
+	//$date = new DateTime();
+	//$date->setTimestamp($ymd);
+	//echo $date->format('U = Y-m-d H:i:s') . "\n";
+
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        if(strncmp($date, $datetime, 10) == 0 )
+		        $mood[] = $split2[0];	
+	    }
+	 //   echo "$ymd ";
+	 //   echo $date;
+	 //   print_r($mood);
+	    if($mood)
+	    	$average = round(array_sum($mood) / count($mood));
+	    return $average;
+	} else {
+	    return "0";
+	} 
+}
+
+function latest($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$newpos = array_unique($newpos);
+				$newArray = array_slice($newpos, 0, 5, false);
+				break;
+			case 'neg':
+				$newneg = array_unique($newneg);
+				$newArray = array_slice($newneg, 0, 5, false);
+				break;
+			case 'con':
+				$newcon = array_unique($newcon);
+				$newArray = array_slice($newcon, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function toptag($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$acv=array_count_values($newpos); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'neg':
+				$acv=array_count_values($newneg); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'con':
+				$acv=array_count_values($newcon); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function alltag(){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newtag= array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newtag[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }  	
+	    }
+	    fclose($moodfile);
+	    
+		$acv=array_count_values($newtag); 
+		arsort($acv); 
+		$result=array_keys($acv); 
+		
+		return json_encode($result);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function new_log($log){
+	global $moodlog;
+	$pattern = '/(?=[+-@|][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
+	$result = preg_split ($pattern, $log, $limit, $flags);
+	//print_r($result);
+
+	$timestamp = date("Y-m-d H:i");
+	$no = rtrim($result[0], "|");
+	$msg = "";
+	$pos = "";
+	$neg = "";
+	$con = "";
+
+	foreach($result as $item){
+		switch ($item[0]) {
+			case '|':
+				$msg .= substr($item, 1)." ";
+				break;
+			case '+':
+				$pos .= "$item ";
+				break;
+			case '-':
+				$neg .= "$item ";
+				break;
+			case '@':
+				$con .= "$item ";
+				break;
+		}
+	}
+	$toadd = "$timestamp [$no] ".$msg.$pos.$neg.$con."\n";
+	$toadd .= file_get_contents($moodlog);
+	file_put_contents($moodlog, $toadd);
+	echo "1";
+}
+
+?>
+
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+	</head>
+	<body>
+		
+		<center>
+			<?php if($error <> ""){echo $error; } ?>
+
+			<div class="banner">
+				<div class="header"><a href="/?logout"><i class="fas fa-heartbeat" ></i></a> moodlog.txt</div>
+
+				<div class="new-log">
+					
+					  <input type="range" id="happyval" value="5" min="1" max="10"/>
+					  <input  class="input" id="tags" placeholder="(+,-,@) description"/>
+					  <input type="button" value="+" onClick="updatePretext();"/>
+					  <input type="button" value="add" class="add" onClick="submitMood();"/>
+					
+				</div>
+				<div class="preview">
+					<span class="date">2018-09-11 20:27</span><span class="hpyno">[5]</span><span class="pretext" onClick="updatePretext();"></span></div>
+
+				<div class="filter" style="display:none">
+					<span class="filtitle">Filters:</span>
+					<span class="fas fa-search" style="float:right;font-size:15px;" onclick="applyFilters();"></span>
+				</div>
+			</div>
+
+			<div id="cal-heatmap"></div>
+
+			<div class="top10s">
+				<div class="toppos">
+					<div class="sub-header">Top 5 positive</div>
+				</div>
+				<div class="topneg">
+					<div class="sub-header">Top 5 negative</div>
+				</div>
+				<div class="topcon">
+					<div class="sub-header">Top 5 context</div>
+				</div>
+				<div class="latpos">
+					<div class="sub-header">Latest 5 positive</div>
+				</div>
+				<div class="latneg">
+					<div class="sub-header">Latest 5 negative</div>
+				</div>
+				<div class="latcon">
+					<div class="sub-header">Latest 5 context</div>
+				</div>
+			</div>
+
+			<div class="fullday">
+				<div class="previewhist">
+					
+					<?php
+						$result = today(date("Y-m-d"));
+						if($result != "0")
+							echo $result;
+					?>
+					
+				</div>
+			</div>
+		</center>
+
+		<script src="script.js"></script>
+ 
+	</body>
+</html>
diff --git a/login.html b/login.html
new file mode 100755
index 0000000..cf5481b
--- /dev/null
+++ b/login.html
@@ -0,0 +1,35 @@
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+		<style>
+			.login_form{
+			  height: 100%;
+			  width:100%;
+			  display: flex;
+			  align-items: center
+			}
+		</style>
+	</head>
+	<body>
+		
+		<div class="login_form">
+			<form method="POST" action="/" style="width:auto">
+				<input type="password" name="password" id="password" placeholder="password" style="text-align:center;"/>
+			</form>
+		</div>
+
+		<script src="script.js"></script>
+
+		<script>$("#password").focus();</script>
+ 
+	</body>
+</html>
\ No newline at end of file

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file
diff --git a/example.png b/example.png
new file mode 100755
index 0000000..c8851f9
--- /dev/null
+++ b/example.png
Binary files differ
diff --git a/index.php b/index.php
new file mode 100755
index 0000000..fb41358
--- /dev/null
+++ b/index.php
@@ -0,0 +1,612 @@
+<?php
+/*
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+*/
+session_start();
+include('config.php');
+$error = "";
+
+if(isset($_REQUEST['password']) && md5($_REQUEST['password']) == $password){
+	$_SESSION['loggedin'] = true;
+}
+
+if(!isset($_SESSION['loggedin']) || isset($_GET['logout'])){
+	if(isset($_SESSION['loggedin']))
+		unset($_SESSION['loggedin']);
+	include('login.html');
+	die();
+}
+
+/***
+ * actions here for API / AJAX 
+ */
+if(isset($_GET['action'])){
+	switch ($_GET['action']) {
+		case 'main_cal': // get unfiltered main cal averages - output JSON
+			header('Content-Type: application/json');
+			$result = main_cal();
+			echo "{".$result."}";
+			break;
+		case 'filtered_cal': // get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+			header('Content-Type: application/json');
+			if(isset($_GET['filter'])){
+				$result = filtered_cal($_GET['filter']);
+				echo "{".$result."}";
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date': // get specific date's log - output HTML
+			if(isset($_GET['date'])){
+				$result = today($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date_average': // get specific date's average - output no.
+			if(isset($_GET['date'])){
+				$result = day_avg($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'latest': // get latest 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = latest($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'top': // get top 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = toptag($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'alltag': // get all tags in popularity order - output JSON
+			$result = alltag();
+			echo $result;
+			break;
+		case 'save':
+			if(isset($_GET['log'])){ // save a new moodlog
+				$result = new_log($_GET['log']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		default:
+			# code...
+			break;
+	}
+	die();
+}
+
+//$result = today("2018-09-13");
+//echo $result;
+
+function today($ymd){
+	global $moodlog;
+	$ymd = strtotime($ymd);
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$ymd2 = date("Y-m-d", strtotime("$date"));
+//echo $ymd2;
+
+	$returnstring = "<div class=\"sub-header\">$justdate</div>\n";
+	$count = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("$ymd2 -0 day")));
+
+	     	$newpos = array();
+	     	$newneg = array();
+	     	$newcon = array();
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = $word;
+		        			break;
+		        		case '-':
+		        			$newneg[] = $word;
+		        			break;
+		        		case '@':
+		        			$newcon[] = $word;
+		        			break;
+		        		default:
+		        			$newstr .= " $word";
+		        			break;
+		        	}
+		        }
+	        }
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+	        $justdate = date("Y-m-d", strtotime($datetime));
+	        if(strtotime($ymd2) == strtotime($justdate)){
+	        	$count++;
+		        $mood = $split2[0];
+		        $fulldate = date("Y-m-d H:i", strtotime($datetime));
+				$returnstring .= "<span class=\"datehist\">$fulldate</span>\n<span class=\"hpyhist\">[$mood]</span><span class=\"pretexthist\">$newstr</span>\n";
+
+				foreach($newpos as $pos)
+		       		$returnstring .= "<span class=\"preposhist\" onclick=\"addFilterPos($(this).text());\">$pos</span>\n";
+		       	foreach($newneg as $neg)
+		       		$returnstring .= "<span class=\"preneghist\" onclick=\"addFilterNeg($(this).text());\">$neg</span>\n";
+		       	foreach($newcon as $con)
+		       		$returnstring .= "<span class=\"preconhist\" onclick=\"addFilterCon($(this).text());\">$con</span>\n";
+		       	$returnstring .= "<br />";
+	     	}
+	       	
+	    }
+	    fclose($moodfile);
+	    return ($count > 0)? $returnstring : "0";
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function main_cal(){
+	global $moodlog;
+	$toreturn = "";
+	
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        //$justdate = date("Y-m-d", strtotime($datetime));
+	         //$dt2 = explode("-", $datetime);
+		 //$dtd = explode(" ", $dt2[2]);
+		 //$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+		 //$dateTime->setDate($dt2[0], $dt2[1], $dtd[0]);
+		 //$justdate = $dateTime->format('Y-m-d');
+		$dtd = explode(" ", $datetime);
+		$justdate = $dtd[0];
+
+		$newtimes[$justdate][] = $mood;
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	
+//$datetime = strtotime($date);
+		$dt22 = explode("-", $date);
+                $dtd2 = explode(" ", $dt22[2]);
+                $dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+                $dateTime->setDate($dt22[0], $dt22[1], $dtd2[0]);
+                $justdate2 = $dateTime->getTimestamp();
+
+	    	$toreturn .= "\"$justdate2\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function filtered_cal($filter){
+	global $moodlog;
+	$toreturn = "";
+
+	$pattern = '/(?=[+-@][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY;
+	$tags = preg_split ($pattern, $filter, $limit, $flags);
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        $justdate = date("Y-m-d", strtotime($datetime));
+
+	        $words = explode(" ", $split2[1]);
+	        
+	        foreach($words as $word){
+	        	$word = trim($word);
+	        	if (in_array($word, $tags, true))
+	        		$newtimes[$justdate][] = $mood;
+	        }
+	        
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	$datetime = strtotime("$date");
+	    	$toreturn .= "\"$datetime\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function day_avg($ymd){
+	global $moodlog;
+	$mood = array();
+	$average = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	//$date = date("Y-m-d", $ymd);
+	//$date = date("Y-m-d", strtotime("$date +1 day"));
+
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$date = date("Y-m-d", strtotime("$date"));
+
+	//$currentTime = new DateTime();
+	//$currentTime = DateTime::createFromFormat( 'U', $ymd );
+	//$date = $currentTime->format( 'c' );
+
+	$cutoff = strtotime("$date -0 day");
+	
+	//echo $date." cutoff: ".$cutoff;
+	//$date = new DateTime();
+	//$date->setTimestamp($ymd);
+	//echo $date->format('U = Y-m-d H:i:s') . "\n";
+
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        if(strncmp($date, $datetime, 10) == 0 )
+		        $mood[] = $split2[0];	
+	    }
+	 //   echo "$ymd ";
+	 //   echo $date;
+	 //   print_r($mood);
+	    if($mood)
+	    	$average = round(array_sum($mood) / count($mood));
+	    return $average;
+	} else {
+	    return "0";
+	} 
+}
+
+function latest($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$newpos = array_unique($newpos);
+				$newArray = array_slice($newpos, 0, 5, false);
+				break;
+			case 'neg':
+				$newneg = array_unique($newneg);
+				$newArray = array_slice($newneg, 0, 5, false);
+				break;
+			case 'con':
+				$newcon = array_unique($newcon);
+				$newArray = array_slice($newcon, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function toptag($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$acv=array_count_values($newpos); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'neg':
+				$acv=array_count_values($newneg); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'con':
+				$acv=array_count_values($newcon); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function alltag(){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newtag= array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newtag[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }  	
+	    }
+	    fclose($moodfile);
+	    
+		$acv=array_count_values($newtag); 
+		arsort($acv); 
+		$result=array_keys($acv); 
+		
+		return json_encode($result);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function new_log($log){
+	global $moodlog;
+	$pattern = '/(?=[+-@|][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
+	$result = preg_split ($pattern, $log, $limit, $flags);
+	//print_r($result);
+
+	$timestamp = date("Y-m-d H:i");
+	$no = rtrim($result[0], "|");
+	$msg = "";
+	$pos = "";
+	$neg = "";
+	$con = "";
+
+	foreach($result as $item){
+		switch ($item[0]) {
+			case '|':
+				$msg .= substr($item, 1)." ";
+				break;
+			case '+':
+				$pos .= "$item ";
+				break;
+			case '-':
+				$neg .= "$item ";
+				break;
+			case '@':
+				$con .= "$item ";
+				break;
+		}
+	}
+	$toadd = "$timestamp [$no] ".$msg.$pos.$neg.$con."\n";
+	$toadd .= file_get_contents($moodlog);
+	file_put_contents($moodlog, $toadd);
+	echo "1";
+}
+
+?>
+
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+	</head>
+	<body>
+		
+		<center>
+			<?php if($error <> ""){echo $error; } ?>
+
+			<div class="banner">
+				<div class="header"><a href="/?logout"><i class="fas fa-heartbeat" ></i></a> moodlog.txt</div>
+
+				<div class="new-log">
+					
+					  <input type="range" id="happyval" value="5" min="1" max="10"/>
+					  <input  class="input" id="tags" placeholder="(+,-,@) description"/>
+					  <input type="button" value="+" onClick="updatePretext();"/>
+					  <input type="button" value="add" class="add" onClick="submitMood();"/>
+					
+				</div>
+				<div class="preview">
+					<span class="date">2018-09-11 20:27</span><span class="hpyno">[5]</span><span class="pretext" onClick="updatePretext();"></span></div>
+
+				<div class="filter" style="display:none">
+					<span class="filtitle">Filters:</span>
+					<span class="fas fa-search" style="float:right;font-size:15px;" onclick="applyFilters();"></span>
+				</div>
+			</div>
+
+			<div id="cal-heatmap"></div>
+
+			<div class="top10s">
+				<div class="toppos">
+					<div class="sub-header">Top 5 positive</div>
+				</div>
+				<div class="topneg">
+					<div class="sub-header">Top 5 negative</div>
+				</div>
+				<div class="topcon">
+					<div class="sub-header">Top 5 context</div>
+				</div>
+				<div class="latpos">
+					<div class="sub-header">Latest 5 positive</div>
+				</div>
+				<div class="latneg">
+					<div class="sub-header">Latest 5 negative</div>
+				</div>
+				<div class="latcon">
+					<div class="sub-header">Latest 5 context</div>
+				</div>
+			</div>
+
+			<div class="fullday">
+				<div class="previewhist">
+					
+					<?php
+						$result = today(date("Y-m-d"));
+						if($result != "0")
+							echo $result;
+					?>
+					
+				</div>
+			</div>
+		</center>
+
+		<script src="script.js"></script>
+ 
+	</body>
+</html>
diff --git a/login.html b/login.html
new file mode 100755
index 0000000..cf5481b
--- /dev/null
+++ b/login.html
@@ -0,0 +1,35 @@
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+		<style>
+			.login_form{
+			  height: 100%;
+			  width:100%;
+			  display: flex;
+			  align-items: center
+			}
+		</style>
+	</head>
+	<body>
+		
+		<div class="login_form">
+			<form method="POST" action="/" style="width:auto">
+				<input type="password" name="password" id="password" placeholder="password" style="text-align:center;"/>
+			</form>
+		</div>
+
+		<script src="script.js"></script>
+
+		<script>$("#password").focus();</script>
+ 
+	</body>
+</html>
\ No newline at end of file
diff --git a/moodlog.txt b/moodlog.txt
new file mode 100755
index 0000000..4048a5c
--- /dev/null
+++ b/moodlog.txt
@@ -0,0 +1,25 @@
+2018-09-21 19:45 [8] nearly finished webapp +code +moodlog 
+2018-09-21 15:20 [7] moodlog web, new challenge coins +code @personal
+2018-09-21 13:30 [5] waiting for client -waiting +phishing @work
+2018-09-20 17:30 [7] tricky moodlog JS +code @personal
+2018-09-20 10:00 [7] tricky phishing setup +phishing +code @work
+2018-09-19 12:00 [5] -ansa @work
+2018-09-18 22:00 [8] +moodlog +code @personal
+2018-09-18 17:00 [6] -reporting +chill @work
+2018-09-17 23:30 [7] sniper elite 4 +gaming @personal
+2018-09-17 12:30 [3] -onsite @bristol
+2018-09-16 20:00 [8] +newpc @personal
+2018-09-15 21:00 [7] -hangover +chill +adam @personal
+2018-09-14 21:00 [9] +pissup +adam +james @personal
+2018-09-13 07:24 [7] new computer +excited +pissup +adam +james @personal
+2018-09-13 10:22 [6] write presentation -work @work
+2018-09-12 09:18 [5] +code -waiting @work
+2018-09-11 18:00 [4] -knackered @work
+2018-09-11 09:00 [4] -ansa @work
+2018-09-10 21:00 [9] mate here +gaming @personal
+2018-09-10 18:00 [8] moodlog webapp +code @personal
+2018-09-10 11:30 [9] pwn3d +phishing @work
+2018-09-10 08:00 [6] +phishing -earlystart -support @work
+2018-09-09 23:00 [9] modlog sublime-syntax finished +code @personal
+2018-09-09 15:30 [8] moodlog concept +ideas @personal 
+2018-09-09 13:00 [7] chilled sunday +tv +chill @personal
\ No newline at end of file

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file
diff --git a/example.png b/example.png
new file mode 100755
index 0000000..c8851f9
--- /dev/null
+++ b/example.png
Binary files differ
diff --git a/index.php b/index.php
new file mode 100755
index 0000000..fb41358
--- /dev/null
+++ b/index.php
@@ -0,0 +1,612 @@
+<?php
+/*
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+*/
+session_start();
+include('config.php');
+$error = "";
+
+if(isset($_REQUEST['password']) && md5($_REQUEST['password']) == $password){
+	$_SESSION['loggedin'] = true;
+}
+
+if(!isset($_SESSION['loggedin']) || isset($_GET['logout'])){
+	if(isset($_SESSION['loggedin']))
+		unset($_SESSION['loggedin']);
+	include('login.html');
+	die();
+}
+
+/***
+ * actions here for API / AJAX 
+ */
+if(isset($_GET['action'])){
+	switch ($_GET['action']) {
+		case 'main_cal': // get unfiltered main cal averages - output JSON
+			header('Content-Type: application/json');
+			$result = main_cal();
+			echo "{".$result."}";
+			break;
+		case 'filtered_cal': // get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+			header('Content-Type: application/json');
+			if(isset($_GET['filter'])){
+				$result = filtered_cal($_GET['filter']);
+				echo "{".$result."}";
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date': // get specific date's log - output HTML
+			if(isset($_GET['date'])){
+				$result = today($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date_average': // get specific date's average - output no.
+			if(isset($_GET['date'])){
+				$result = day_avg($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'latest': // get latest 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = latest($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'top': // get top 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = toptag($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'alltag': // get all tags in popularity order - output JSON
+			$result = alltag();
+			echo $result;
+			break;
+		case 'save':
+			if(isset($_GET['log'])){ // save a new moodlog
+				$result = new_log($_GET['log']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		default:
+			# code...
+			break;
+	}
+	die();
+}
+
+//$result = today("2018-09-13");
+//echo $result;
+
+function today($ymd){
+	global $moodlog;
+	$ymd = strtotime($ymd);
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$ymd2 = date("Y-m-d", strtotime("$date"));
+//echo $ymd2;
+
+	$returnstring = "<div class=\"sub-header\">$justdate</div>\n";
+	$count = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("$ymd2 -0 day")));
+
+	     	$newpos = array();
+	     	$newneg = array();
+	     	$newcon = array();
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = $word;
+		        			break;
+		        		case '-':
+		        			$newneg[] = $word;
+		        			break;
+		        		case '@':
+		        			$newcon[] = $word;
+		        			break;
+		        		default:
+		        			$newstr .= " $word";
+		        			break;
+		        	}
+		        }
+	        }
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+	        $justdate = date("Y-m-d", strtotime($datetime));
+	        if(strtotime($ymd2) == strtotime($justdate)){
+	        	$count++;
+		        $mood = $split2[0];
+		        $fulldate = date("Y-m-d H:i", strtotime($datetime));
+				$returnstring .= "<span class=\"datehist\">$fulldate</span>\n<span class=\"hpyhist\">[$mood]</span><span class=\"pretexthist\">$newstr</span>\n";
+
+				foreach($newpos as $pos)
+		       		$returnstring .= "<span class=\"preposhist\" onclick=\"addFilterPos($(this).text());\">$pos</span>\n";
+		       	foreach($newneg as $neg)
+		       		$returnstring .= "<span class=\"preneghist\" onclick=\"addFilterNeg($(this).text());\">$neg</span>\n";
+		       	foreach($newcon as $con)
+		       		$returnstring .= "<span class=\"preconhist\" onclick=\"addFilterCon($(this).text());\">$con</span>\n";
+		       	$returnstring .= "<br />";
+	     	}
+	       	
+	    }
+	    fclose($moodfile);
+	    return ($count > 0)? $returnstring : "0";
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function main_cal(){
+	global $moodlog;
+	$toreturn = "";
+	
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        //$justdate = date("Y-m-d", strtotime($datetime));
+	         //$dt2 = explode("-", $datetime);
+		 //$dtd = explode(" ", $dt2[2]);
+		 //$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+		 //$dateTime->setDate($dt2[0], $dt2[1], $dtd[0]);
+		 //$justdate = $dateTime->format('Y-m-d');
+		$dtd = explode(" ", $datetime);
+		$justdate = $dtd[0];
+
+		$newtimes[$justdate][] = $mood;
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	
+//$datetime = strtotime($date);
+		$dt22 = explode("-", $date);
+                $dtd2 = explode(" ", $dt22[2]);
+                $dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+                $dateTime->setDate($dt22[0], $dt22[1], $dtd2[0]);
+                $justdate2 = $dateTime->getTimestamp();
+
+	    	$toreturn .= "\"$justdate2\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function filtered_cal($filter){
+	global $moodlog;
+	$toreturn = "";
+
+	$pattern = '/(?=[+-@][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY;
+	$tags = preg_split ($pattern, $filter, $limit, $flags);
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        $justdate = date("Y-m-d", strtotime($datetime));
+
+	        $words = explode(" ", $split2[1]);
+	        
+	        foreach($words as $word){
+	        	$word = trim($word);
+	        	if (in_array($word, $tags, true))
+	        		$newtimes[$justdate][] = $mood;
+	        }
+	        
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	$datetime = strtotime("$date");
+	    	$toreturn .= "\"$datetime\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function day_avg($ymd){
+	global $moodlog;
+	$mood = array();
+	$average = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	//$date = date("Y-m-d", $ymd);
+	//$date = date("Y-m-d", strtotime("$date +1 day"));
+
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$date = date("Y-m-d", strtotime("$date"));
+
+	//$currentTime = new DateTime();
+	//$currentTime = DateTime::createFromFormat( 'U', $ymd );
+	//$date = $currentTime->format( 'c' );
+
+	$cutoff = strtotime("$date -0 day");
+	
+	//echo $date." cutoff: ".$cutoff;
+	//$date = new DateTime();
+	//$date->setTimestamp($ymd);
+	//echo $date->format('U = Y-m-d H:i:s') . "\n";
+
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        if(strncmp($date, $datetime, 10) == 0 )
+		        $mood[] = $split2[0];	
+	    }
+	 //   echo "$ymd ";
+	 //   echo $date;
+	 //   print_r($mood);
+	    if($mood)
+	    	$average = round(array_sum($mood) / count($mood));
+	    return $average;
+	} else {
+	    return "0";
+	} 
+}
+
+function latest($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$newpos = array_unique($newpos);
+				$newArray = array_slice($newpos, 0, 5, false);
+				break;
+			case 'neg':
+				$newneg = array_unique($newneg);
+				$newArray = array_slice($newneg, 0, 5, false);
+				break;
+			case 'con':
+				$newcon = array_unique($newcon);
+				$newArray = array_slice($newcon, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function toptag($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$acv=array_count_values($newpos); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'neg':
+				$acv=array_count_values($newneg); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'con':
+				$acv=array_count_values($newcon); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function alltag(){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newtag= array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newtag[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }  	
+	    }
+	    fclose($moodfile);
+	    
+		$acv=array_count_values($newtag); 
+		arsort($acv); 
+		$result=array_keys($acv); 
+		
+		return json_encode($result);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function new_log($log){
+	global $moodlog;
+	$pattern = '/(?=[+-@|][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
+	$result = preg_split ($pattern, $log, $limit, $flags);
+	//print_r($result);
+
+	$timestamp = date("Y-m-d H:i");
+	$no = rtrim($result[0], "|");
+	$msg = "";
+	$pos = "";
+	$neg = "";
+	$con = "";
+
+	foreach($result as $item){
+		switch ($item[0]) {
+			case '|':
+				$msg .= substr($item, 1)." ";
+				break;
+			case '+':
+				$pos .= "$item ";
+				break;
+			case '-':
+				$neg .= "$item ";
+				break;
+			case '@':
+				$con .= "$item ";
+				break;
+		}
+	}
+	$toadd = "$timestamp [$no] ".$msg.$pos.$neg.$con."\n";
+	$toadd .= file_get_contents($moodlog);
+	file_put_contents($moodlog, $toadd);
+	echo "1";
+}
+
+?>
+
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+	</head>
+	<body>
+		
+		<center>
+			<?php if($error <> ""){echo $error; } ?>
+
+			<div class="banner">
+				<div class="header"><a href="/?logout"><i class="fas fa-heartbeat" ></i></a> moodlog.txt</div>
+
+				<div class="new-log">
+					
+					  <input type="range" id="happyval" value="5" min="1" max="10"/>
+					  <input  class="input" id="tags" placeholder="(+,-,@) description"/>
+					  <input type="button" value="+" onClick="updatePretext();"/>
+					  <input type="button" value="add" class="add" onClick="submitMood();"/>
+					
+				</div>
+				<div class="preview">
+					<span class="date">2018-09-11 20:27</span><span class="hpyno">[5]</span><span class="pretext" onClick="updatePretext();"></span></div>
+
+				<div class="filter" style="display:none">
+					<span class="filtitle">Filters:</span>
+					<span class="fas fa-search" style="float:right;font-size:15px;" onclick="applyFilters();"></span>
+				</div>
+			</div>
+
+			<div id="cal-heatmap"></div>
+
+			<div class="top10s">
+				<div class="toppos">
+					<div class="sub-header">Top 5 positive</div>
+				</div>
+				<div class="topneg">
+					<div class="sub-header">Top 5 negative</div>
+				</div>
+				<div class="topcon">
+					<div class="sub-header">Top 5 context</div>
+				</div>
+				<div class="latpos">
+					<div class="sub-header">Latest 5 positive</div>
+				</div>
+				<div class="latneg">
+					<div class="sub-header">Latest 5 negative</div>
+				</div>
+				<div class="latcon">
+					<div class="sub-header">Latest 5 context</div>
+				</div>
+			</div>
+
+			<div class="fullday">
+				<div class="previewhist">
+					
+					<?php
+						$result = today(date("Y-m-d"));
+						if($result != "0")
+							echo $result;
+					?>
+					
+				</div>
+			</div>
+		</center>
+
+		<script src="script.js"></script>
+ 
+	</body>
+</html>
diff --git a/login.html b/login.html
new file mode 100755
index 0000000..cf5481b
--- /dev/null
+++ b/login.html
@@ -0,0 +1,35 @@
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+		<style>
+			.login_form{
+			  height: 100%;
+			  width:100%;
+			  display: flex;
+			  align-items: center
+			}
+		</style>
+	</head>
+	<body>
+		
+		<div class="login_form">
+			<form method="POST" action="/" style="width:auto">
+				<input type="password" name="password" id="password" placeholder="password" style="text-align:center;"/>
+			</form>
+		</div>
+
+		<script src="script.js"></script>
+
+		<script>$("#password").focus();</script>
+ 
+	</body>
+</html>
\ No newline at end of file
diff --git a/moodlog.txt b/moodlog.txt
new file mode 100755
index 0000000..4048a5c
--- /dev/null
+++ b/moodlog.txt
@@ -0,0 +1,25 @@
+2018-09-21 19:45 [8] nearly finished webapp +code +moodlog 
+2018-09-21 15:20 [7] moodlog web, new challenge coins +code @personal
+2018-09-21 13:30 [5] waiting for client -waiting +phishing @work
+2018-09-20 17:30 [7] tricky moodlog JS +code @personal
+2018-09-20 10:00 [7] tricky phishing setup +phishing +code @work
+2018-09-19 12:00 [5] -ansa @work
+2018-09-18 22:00 [8] +moodlog +code @personal
+2018-09-18 17:00 [6] -reporting +chill @work
+2018-09-17 23:30 [7] sniper elite 4 +gaming @personal
+2018-09-17 12:30 [3] -onsite @bristol
+2018-09-16 20:00 [8] +newpc @personal
+2018-09-15 21:00 [7] -hangover +chill +adam @personal
+2018-09-14 21:00 [9] +pissup +adam +james @personal
+2018-09-13 07:24 [7] new computer +excited +pissup +adam +james @personal
+2018-09-13 10:22 [6] write presentation -work @work
+2018-09-12 09:18 [5] +code -waiting @work
+2018-09-11 18:00 [4] -knackered @work
+2018-09-11 09:00 [4] -ansa @work
+2018-09-10 21:00 [9] mate here +gaming @personal
+2018-09-10 18:00 [8] moodlog webapp +code @personal
+2018-09-10 11:30 [9] pwn3d +phishing @work
+2018-09-10 08:00 [6] +phishing -earlystart -support @work
+2018-09-09 23:00 [9] modlog sublime-syntax finished +code @personal
+2018-09-09 15:30 [8] moodlog concept +ideas @personal 
+2018-09-09 13:00 [7] chilled sunday +tv +chill @personal
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100755
index 0000000..255dcc1
--- /dev/null
+++ b/script.js
@@ -0,0 +1,431 @@
+/*var datas = [
+	{date: "2018-09-09", value: 10},
+	{date: "2018-09-08", value: 5},
+	{date: "2018-09-07", value: 8},
+	{date: "2018-09-07", value: 7},
+	{date: "2018-09-06", value: 9},
+	{date: "2018-09-05", value: 6},
+	{date: "2018-09-04", value: 5},
+	{date: "2018-09-03", value: 4},
+	{date: "2018-09-02", value: 7},
+	{date: "2018-08-02", value: 1}
+]
+
+/*
+var parser = function(data) {
+	var stats = {};
+	console.log(data);
+	for (var d in data) {
+		console.log(data[d].date);
+		var dateTime = new Date(data[d].date).toISOString();
+		var timestamp = Math.floor(dateTime / 1000);
+		let toTimestamp = strDate => Date.parse(data[d].date);
+		stats[timestamp] = data[d].value;
+	}
+	console.log(stats);
+	return stats;
+
+};
+*/
+/*
+var stats = {};
+var parser = function(data) {
+	//console.log(data);
+	for (var d in data) {
+		//console.log("date:"+data[d]);
+		//var date = new Date(data[d].date); // Date of activity 
+    	//var sec = date.getTime()/1000; // Convert to sec
+		stats[d] = data[d];
+		//cal.subDomainTextFormat(d, data[d]);
+	}
+
+	return stats;	
+};
+*/
+//var mainurl = "http://localhost:8080/test.json";
+var mainurl = "/?action=main_cal";
+var cal = new CalHeatMap();
+
+setUpCal();
+function setUpCal(){
+	var datethen = new Date();
+	datethen.setMonth(datethen.getMonth() - 9);
+
+	cal.init({
+		//data: "http://localhost:8080/index.php?action=main_cal",
+		data: mainurl,
+		dataType: "json",
+			//afterLoadData: parser,
+		start: datethen,
+		id : "graph",
+		domain : "month",			// Group data by month
+		subDomain : "day",			// Split each month by days
+		cellSize: 15,
+		cellPadding: 2,
+		cellRadius: 3,
+		domainGutter:2,
+		subDomainTitleFormat: {
+	        empty: "{date}",
+	        filled: "{count} - {date}"
+	    },
+	    //itemSelector: "#cal-heatmap",
+		range : 10,					// Just display 10 months
+		legend: [2,3,4,5,6,7,8,9], 	// Custom threshold for the scale
+		tooltip: false,
+		displayLegend: false,
+		label: {
+			position: "bottom",
+			align: "center",
+			offset: {x:0,y:-10},
+		},
+		considerMissingDataAsZero: true,
+		legendHorizontalPosition: "center",
+		legendColors: {
+			min: "#6b6de5",
+			max: "#46e260",
+		},
+		subDomainTextFormat: function(date ,value) {
+			var origdate = ""+date;
+			date =  origdate.split('00:00:00')[0]+'00:00:00';
+			var date = parseInt((new Date(date).getTime() /1000 ).toFixed(0))
+			var finval = 0;
+
+			/***
+			 * All of this cos of a damn bug! 
+			 * https://github.com/wa0x6e/cal-heatmap/issues/257
+			 */
+			$.ajax({
+				url: "/?action=date_average&date="+date,
+				async: false,
+				dataType: 'html',
+				success: function (response) {
+					//console.log(response);
+					finval = response;
+					console.log("origdate: "+origdate+" date: "+date+" val:"+response);
+				}
+			});
+
+			if (finval == 0){finval = "";}
+			return finval;
+		},
+		highlight: "now",
+		onClick: function(date, count) {
+			//alert("Oh gosh, " + count + " things occured on " + date.toISOString());
+			updateDayLog(date.toISOString().slice(0, 19).replace('T', ' '));
+		}
+	});
+}
+
+
+function checkStats(timestamp){
+	var finval = 0;
+	$.getJSON('test.json', function (data) {
+		$.each(data, function(i, field){
+			//console.log(field);
+			if(timestamp == i){
+				console.log("found: "+field);
+        		finval = field;
+        	}
+
+     	});
+     	//if (finval == 0){finval = "";}
+		return finval;
+	});
+
+}
+
+var availableTags = [
+	  "-ansa",
+	  "+phishing",
+	  "+chill",
+	  "@home",
+];
+$( function() {
+
+    $( "#tags" ).autocomplete({
+      source: availableTags
+    });
+} );
+
+function updateTime() {
+    var now = new Date();
+    var datestring = now.getFullYear() + "-" + ("0"+(now.getMonth()+1)).slice(-2) + "-" + ("0" + now.getDate()).slice(-2) + " " + ("0" + now.getHours()).slice(-2) + ":" + ("0" + now.getMinutes()).slice(-2);
+    $("span.date").html(datestring.toString());        
+}
+
+$("#happyval").on("input change", function() {
+    $(".hpyno").html("[" + $("#happyval").val() + "]");
+});
+removespan = function(span) {
+	span.remove();
+}
+
+/***
+ * filter adding and removing code
+ */
+var filter = 0;
+function addFilterPos(word){
+	filter++;
+	$('.filtitle').after('<span class="filpos" onclick="removefilter(this);">'+word+'</span>');
+	$(".filter").show();
+}
+function addFilterNeg(word){
+	filter++;
+	$('.filtitle').after('<span class="filneg" onclick="removefilter(this);">'+word+'</span>');
+	$(".filter").show();
+}
+function addFilterCon(word){
+	filter++;
+	$('.filtitle').after('<span class="filcon" onclick="removefilter(this);">'+word+'</span>');
+	$(".filter").show();
+}
+removefilter = function(span) {
+	filter--;
+	span.remove();
+	if(filter == 0){ 
+		$(".filter").hide(); 
+		updateCal("/?action=main_cal");
+	}
+}
+
+/***
+ * updating description 
+ */
+function updatePretext(){
+ 	var toadd = $("#tags").val();
+ 	switch(toadd.charAt(0)){
+ 		case "+":
+ 			$('.pretext').after('<span class="prepos" onclick="removespan(this);">'+toadd+'</span>');
+ 			break;
+ 		case "-":
+ 			$('.pretext').after('<span class="preneg" onclick="removespan(this);">'+toadd+'</span>');
+ 			break;
+ 		case "@":
+ 			$('.preview').append('<span class="precon" onclick="removespan(this);">'+toadd+'</span>');
+ 			break;
+ 		default:
+ 			$(".pretext").html( toadd );
+ 	}
+ 	$("#tags").val("");
+ 	//$(".pretext").html(  );
+ }
+
+  function submitMood(){
+ 	var toadd = $(".preview").text();
+
+ 	console.log(toadd);
+ }
+
+/***
+ * update main calendar values
+ */
+function updateCal(url){ //updateCal("/?action=main_cal");
+	mainurl = url;
+	cal.destroy(function(){
+		cal = new CalHeatMap();
+		setUpCal();
+	});
+}
+
+/***
+ * update specific day log
+ */
+function updateDayLog(date){
+	$.ajax({
+		url: "/?action=date&date="+date,
+		async: true,
+		dataType: 'html',
+		success: function (response) {
+			//console.log(response);
+			if(response != "0"){
+				$(".previewhist").html(response);
+			}
+		}
+	});
+}
+
+/***
+ * update latest tags
+ */
+function updateLatest(tag){
+	var string = "";
+	switch(tag) {
+		case "pos":
+			string = "<div class=\"sub-header\">Latest 5 positive</div>";
+			break;
+		case "neg":
+			string = "<div class=\"sub-header\">Latest 5 negative</div>";
+			break;
+		case "con":
+			string = "<div class=\"sub-header\">Latest 5 context</div>";
+			break;
+	}
+	$.ajax({
+		url: "/?action=latest&tag="+tag,
+		async: true,
+		dataType: 'json',
+		success: function (response) {
+			if(response != "0"){
+
+				$.each(response, function(i, item) {
+					var ntag = tag.charAt(0).toUpperCase() + tag.substr(1);
+				    string += "<span onclick=\"addFilter"+ntag+"($(this).text());\">"+item+"</span><br />";
+				 });
+
+				//console.log(response);
+				$(".lat"+tag).html(string);
+			}
+		}
+	});
+}
+
+/***
+ * update top tags
+ */
+function updateTop(tag){
+	var string = "";
+	switch(tag) {
+		case "pos":
+			string = "<div class=\"sub-header\">Top 5 positive</div>";
+			break;
+		case "neg":
+			string = "<div class=\"sub-header\">Top 5 negative</div>";
+			break;
+		case "con":
+			string = "<div class=\"sub-header\">Top 5 context</div>";
+			break;
+	}
+	$.ajax({
+		url: "/?action=top&tag="+tag,
+		async: true,
+		dataType: 'json',
+		success: function (response) {
+			if(response != "0"){
+
+				$.each(response, function(i, item) {
+					//console.log(item);
+					var ntag = tag.charAt(0).toUpperCase() + tag.substr(1);
+				    string += "<span onclick=\"addFilter"+ntag+"($(this).text());\">"+item+"</span><br />";
+				 });
+
+				//console.log(response);
+				$(".top"+tag).html(string);
+			}
+		}
+	});
+}
+
+/***
+ * update available tags
+ */
+function updateAvailable(){
+	$.ajax({
+		url: "/?action=alltag",
+		async: true,
+		dataType: 'json',
+		success: function (response) {
+			if(response != "0"){
+				availableTags = response;
+				    $( "#tags" ).autocomplete({
+				      source: availableTags
+				    });
+			}
+		}
+	});
+}
+
+/***
+ * display filtered calendar
+ */
+function applyFilters(){
+	var filttstring ="";
+	$(".filter").find("span").each(function() {
+    	filttstring += $(this).html();
+ 	});
+ 	filttstring = filttstring.slice(8);
+ 	filttstring = filttstring.replace(/\s+/g, '');
+ 	filttstring = filttstring.replace(/\+/g , "%2B");
+ 	//filttstring = encodeURIComponent(filttstring);
+	//console.log(filttstring);
+	updateCal("/?action=filtered_cal&filter="+filttstring);
+}
+
+/***
+ * save to moodlog
+ */
+function submitMood(){
+	var filttstring = [];
+	var sendString = "";
+	$(".preview").find("span").each(function() {
+    	filttstring.push( $(this).html() );
+ 	});
+ 	
+ 	filttstring.shift(); // remove date
+ 	filttstring[0] = filttstring[0].replace(/\[/g, ''); //fix no.
+ 	filttstring[0] = filttstring[0].replace(/\]/g, '|'); //fix no.
+
+ 	for (var i = 0, len = filttstring.length; i < len; i++) { //tidy for URL
+  		filttstring[i] = filttstring[i].replace(/\+/g , "%2B");
+  		filttstring[i] = filttstring[i].replace(/ /g , "%20");
+  		sendString += filttstring[i]
+	}
+
+	console.log(sendString);
+	$.ajax({
+		url: "/?action=save&log="+sendString,
+		async: true,
+		dataType: 'html',
+		success: function (response) {
+			if(response != "0"){
+
+				var now = new Date();
+    			var datestring = now.getFullYear() + "-" + ("0"+(now.getMonth()+1)).slice(-2) + "-" + ("0" + now.getDate()).slice(-2);
+    			var fulldatestring = now.getFullYear() + "-" + ("0"+(now.getMonth()+1)).slice(-2) + "-" + ("0" + now.getDate()).slice(-2) + " " + ("0" + now.getHours()).slice(-2) + ":" + ("0" + now.getMinutes()).slice(-2);
+
+    			$(".preview").html("<span class=\"date\">"+fulldatestring+"</span><span class=\"hpyno\">[5]</span><span class=\"pretext\" onclick=\"updatePretext();\"></span></div>")
+    			$("#happyval").val(5);
+				updateCal("/?action=main_cal");
+				updateDayLog(datestring);
+				updateTop("pos"); 
+				updateTop("neg"); 
+				updateTop("con"); 
+				updateLatest("pos"); 
+				updateLatest("neg"); 
+				updateLatest("con");
+			}
+		}
+	});
+	
+
+}
+
+/***
+ * once app loaded
+ */
+$(document).ready(function(){
+
+    $('#tags').keypress(function(e){
+		if(e.keyCode==13)
+			updatePretext();
+	});
+
+    updateTop("pos");
+    updateTop("neg");
+    updateTop("con");
+    updateLatest("pos");
+    updateLatest("neg");
+    updateLatest("con");
+
+    updateAvailable();
+
+	updateTime();
+    setInterval(updateTime, 5000); // 5 * 1000 miliseconds
+    var interval1 = setInterval(function () { updateCal(mainurl); }, 300000); // update every 5 mins (300000) 
+
+    var interval1 = setInterval(function () { updateTop("pos"); }, 300000);
+    var interval1 = setInterval(function () { updateTop("neg"); }, 300000);
+    var interval1 = setInterval(function () { updateTop("con"); }, 300000);
+    var interval1 = setInterval(function () { updateLatest("pos"); }, 300000);
+    var interval1 = setInterval(function () { updateLatest("neg"); }, 300000);
+    var interval1 = setInterval(function () { updateLatest("con"); }, 300000);
+});

diff --git a/README.md b/README.md
index 5820176..9df3369 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,63 @@
 moodlog_web
 ===============
 
-PHP web application for use with moodlog.txt
\ No newline at end of file
+PHP web application for use with moodlog.txt
+
+**<u>Installation</u>**
+
+clone this into web root
+
+edit config.php to contain:
+
+1) md5 hash of login password
+
+2) location of you moodlog.txt
+
+**<u>Screenshot</u>**
+![screenshott](http://swin.es/g/NaN/moodlog_web/raw/381e772a3ddb6e2a83e09c705d84aa52bfb06873/example.png)
+
+**<u>API</u>**
+
+There is a sort-of API with this, it's super basic and crappy.
+
+Use GET requests to /index.php
+
+Always include &password=[your password here]
+
+here are the basic functtions:
+
+**&action=main_cal**
+
+get unfiltered main cal averages - output JSON
+
+**&action=filtered_cal&filter=**
+
+get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+
+**&action=date&date=[specific date]**
+
+get specific date's log - output HTML
+
+**&action=date_average&date=[specific date]**
+
+get specific date's average - output no.
+
+**&action=latest&tag=[pos,neg or con]**
+
+get latest 5 tags - output JSON
+
+**&action=top&tag=[pos,neg or con]**
+
+get top 5 tags - output JSON
+
+**&action=alltag**
+
+get all tags in popularity order - output JSON
+
+**&action=save&log=[your log to save]**
+
+save a new moodlog
+
+the log format should be: *no|small description+tag-tag+tag@context*
+
+however as simple single number will also work
\ No newline at end of file
diff --git a/config.php b/config.php
new file mode 100755
index 0000000..f4e88b2
--- /dev/null
+++ b/config.php
@@ -0,0 +1,4 @@
+<?php
+$password = "098f6bcd4621d373cade4e832627b4f6"; // MD5 of your password here (default = test)
+$moodlog = "moodlog.txt"; // Location of you moodlog.txt
+?>
\ No newline at end of file
diff --git a/example.png b/example.png
new file mode 100755
index 0000000..c8851f9
--- /dev/null
+++ b/example.png
Binary files differ
diff --git a/index.php b/index.php
new file mode 100755
index 0000000..fb41358
--- /dev/null
+++ b/index.php
@@ -0,0 +1,612 @@
+<?php
+/*
+ini_set('display_errors', 1);
+ini_set('display_startup_errors', 1);
+error_reporting(E_ALL);
+*/
+session_start();
+include('config.php');
+$error = "";
+
+if(isset($_REQUEST['password']) && md5($_REQUEST['password']) == $password){
+	$_SESSION['loggedin'] = true;
+}
+
+if(!isset($_SESSION['loggedin']) || isset($_GET['logout'])){
+	if(isset($_SESSION['loggedin']))
+		unset($_SESSION['loggedin']);
+	include('login.html');
+	die();
+}
+
+/***
+ * actions here for API / AJAX 
+ */
+if(isset($_GET['action'])){
+	switch ($_GET['action']) {
+		case 'main_cal': // get unfiltered main cal averages - output JSON
+			header('Content-Type: application/json');
+			$result = main_cal();
+			echo "{".$result."}";
+			break;
+		case 'filtered_cal': // get filtered main cal averages (filter=+test-test@test-test...) - output JSON
+			header('Content-Type: application/json');
+			if(isset($_GET['filter'])){
+				$result = filtered_cal($_GET['filter']);
+				echo "{".$result."}";
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date': // get specific date's log - output HTML
+			if(isset($_GET['date'])){
+				$result = today($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'date_average': // get specific date's average - output no.
+			if(isset($_GET['date'])){
+				$result = day_avg($_GET['date']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'latest': // get latest 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = latest($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'top': // get top 5 tags - output JSON
+			if(isset($_GET['tag'])){
+				$result = toptag($_GET['tag']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		case 'alltag': // get all tags in popularity order - output JSON
+			$result = alltag();
+			echo $result;
+			break;
+		case 'save':
+			if(isset($_GET['log'])){ // save a new moodlog
+				$result = new_log($_GET['log']);
+				echo $result;
+			}else{
+				echo "0";
+			}
+			break;
+		default:
+			# code...
+			break;
+	}
+	die();
+}
+
+//$result = today("2018-09-13");
+//echo $result;
+
+function today($ymd){
+	global $moodlog;
+	$ymd = strtotime($ymd);
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$ymd2 = date("Y-m-d", strtotime("$date"));
+//echo $ymd2;
+
+	$returnstring = "<div class=\"sub-header\">$justdate</div>\n";
+	$count = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("$ymd2 -0 day")));
+
+	     	$newpos = array();
+	     	$newneg = array();
+	     	$newcon = array();
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = $word;
+		        			break;
+		        		case '-':
+		        			$newneg[] = $word;
+		        			break;
+		        		case '@':
+		        			$newcon[] = $word;
+		        			break;
+		        		default:
+		        			$newstr .= " $word";
+		        			break;
+		        	}
+		        }
+	        }
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+	        $justdate = date("Y-m-d", strtotime($datetime));
+	        if(strtotime($ymd2) == strtotime($justdate)){
+	        	$count++;
+		        $mood = $split2[0];
+		        $fulldate = date("Y-m-d H:i", strtotime($datetime));
+				$returnstring .= "<span class=\"datehist\">$fulldate</span>\n<span class=\"hpyhist\">[$mood]</span><span class=\"pretexthist\">$newstr</span>\n";
+
+				foreach($newpos as $pos)
+		       		$returnstring .= "<span class=\"preposhist\" onclick=\"addFilterPos($(this).text());\">$pos</span>\n";
+		       	foreach($newneg as $neg)
+		       		$returnstring .= "<span class=\"preneghist\" onclick=\"addFilterNeg($(this).text());\">$neg</span>\n";
+		       	foreach($newcon as $con)
+		       		$returnstring .= "<span class=\"preconhist\" onclick=\"addFilterCon($(this).text());\">$con</span>\n";
+		       	$returnstring .= "<br />";
+	     	}
+	       	
+	    }
+	    fclose($moodfile);
+	    return ($count > 0)? $returnstring : "0";
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function main_cal(){
+	global $moodlog;
+	$toreturn = "";
+	
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        //$justdate = date("Y-m-d", strtotime($datetime));
+	         //$dt2 = explode("-", $datetime);
+		 //$dtd = explode(" ", $dt2[2]);
+		 //$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+		 //$dateTime->setDate($dt2[0], $dt2[1], $dtd[0]);
+		 //$justdate = $dateTime->format('Y-m-d');
+		$dtd = explode(" ", $datetime);
+		$justdate = $dtd[0];
+
+		$newtimes[$justdate][] = $mood;
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	
+//$datetime = strtotime($date);
+		$dt22 = explode("-", $date);
+                $dtd2 = explode(" ", $dt22[2]);
+                $dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+                $dateTime->setDate($dt22[0], $dt22[1], $dtd2[0]);
+                $justdate2 = $dateTime->getTimestamp();
+
+	    	$toreturn .= "\"$justdate2\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function filtered_cal($filter){
+	global $moodlog;
+	$toreturn = "";
+
+	$pattern = '/(?=[+-@][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY;
+	$tags = preg_split ($pattern, $filter, $limit, $flags);
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+		$newtimes = array();
+	    while (($line = fgets($moodfile)) !== false) {
+	    	/***
+	    	 * if date < cutoff stop adding
+	    	 */
+	    	$cutoff = $date = strtotime(date("Y-m-d", strtotime("-10 month")));
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        $mood = $split2[0];
+	        $justdate = date("Y-m-d", strtotime($datetime));
+
+	        $words = explode(" ", $split2[1]);
+	        
+	        foreach($words as $word){
+	        	$word = trim($word);
+	        	if (in_array($word, $tags, true))
+	        		$newtimes[$justdate][] = $mood;
+	        }
+	        
+	    }
+	    fclose($moodfile);
+	    foreach($newtimes as $date=>$md){
+	    	$average = round(array_sum($md) / count($md));
+	    	$datetime = strtotime("$date");
+	    	$toreturn .= "\"$datetime\":$average,";
+	    }
+
+	    return substr($toreturn, 0, -1);
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function day_avg($ymd){
+	global $moodlog;
+	$mood = array();
+	$average = 0;
+
+	$moodfile = @fopen($moodlog, "r");
+	//$date = date("Y-m-d", $ymd);
+	//$date = date("Y-m-d", strtotime("$date +1 day"));
+
+	$dateTime = new \DateTime(null, new DateTimeZone('Europe/London'));
+	$dateTime->setTimestamp($ymd);
+	$date = $dateTime->format('Y-m-d');
+	$date = date("Y-m-d", strtotime("$date"));
+
+	//$currentTime = new DateTime();
+	//$currentTime = DateTime::createFromFormat( 'U', $ymd );
+	//$date = $currentTime->format( 'c' );
+
+	$cutoff = strtotime("$date -0 day");
+	
+	//echo $date." cutoff: ".$cutoff;
+	//$date = new DateTime();
+	//$date->setTimestamp($ymd);
+	//echo $date->format('U = Y-m-d H:i:s') . "\n";
+
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+
+	        $datetime = $split1[0];
+	        if(strtotime($datetime) < $cutoff)
+	        	break;
+
+	        if(strncmp($date, $datetime, 10) == 0 )
+		        $mood[] = $split2[0];	
+	    }
+	 //   echo "$ymd ";
+	 //   echo $date;
+	 //   print_r($mood);
+	    if($mood)
+	    	$average = round(array_sum($mood) / count($mood));
+	    return $average;
+	} else {
+	    return "0";
+	} 
+}
+
+function latest($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$newpos = array_unique($newpos);
+				$newArray = array_slice($newpos, 0, 5, false);
+				break;
+			case 'neg':
+				$newneg = array_unique($newneg);
+				$newArray = array_slice($newneg, 0, 5, false);
+				break;
+			case 'con':
+				$newcon = array_unique($newcon);
+				$newArray = array_slice($newcon, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function toptag($tag){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newpos = array();
+ 	$newneg = array();
+ 	$newcon = array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newpos[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newneg[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newcon[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }
+
+	       
+	       	
+	    }
+	    fclose($moodfile);
+	    switch ($tag) {
+			case 'pos':
+				$acv=array_count_values($newpos); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'neg':
+				$acv=array_count_values($newneg); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			case 'con':
+				$acv=array_count_values($newcon); 
+				arsort($acv); 
+				$result=array_keys($acv); 
+				$newArray = array_slice($result, 0, 5, false);
+				break;
+			default:
+				return 0;
+				break;
+		}
+		return json_encode($newArray);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function alltag(){
+	global $moodlog;
+	$count = 0;
+	
+
+	$newtag= array();
+
+	$moodfile = @fopen($moodlog, "r");
+	if ($moodfile) {
+	    while (($line = fgets($moodfile)) !== false) {
+
+	     	$newstr = "";
+
+	        $split1 = explode("[", $line);
+	        $split2 = explode("]", $split1[1]);
+	        $words = explode(" ", $split2[1]);
+	        foreach($words as $word){
+	        	if($word <> ""){
+		        	switch (mb_substr($word[0], 0, 1)) {
+		        		case '+':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '-':
+		        			$newtag[] = trim($word);
+		        			break;
+		        		case '@':
+		        			$newtag[] = trim($word);
+		        			break;
+		        	}
+		        }
+	        }  	
+	    }
+	    fclose($moodfile);
+	    
+		$acv=array_count_values($newtag); 
+		arsort($acv); 
+		$result=array_keys($acv); 
+		
+		return json_encode($result);
+	    
+	} else {
+	    return "!ERROR! File: ".$moodfile." doesn't exist. !ERROR!<br />";
+	} 
+}
+
+function new_log($log){
+	global $moodlog;
+	$pattern = '/(?=[+-@|][a-zA-Z0-9])/';
+	$limit = -1;
+	$flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE;
+	$result = preg_split ($pattern, $log, $limit, $flags);
+	//print_r($result);
+
+	$timestamp = date("Y-m-d H:i");
+	$no = rtrim($result[0], "|");
+	$msg = "";
+	$pos = "";
+	$neg = "";
+	$con = "";
+
+	foreach($result as $item){
+		switch ($item[0]) {
+			case '|':
+				$msg .= substr($item, 1)." ";
+				break;
+			case '+':
+				$pos .= "$item ";
+				break;
+			case '-':
+				$neg .= "$item ";
+				break;
+			case '@':
+				$con .= "$item ";
+				break;
+		}
+	}
+	$toadd = "$timestamp [$no] ".$msg.$pos.$neg.$con."\n";
+	$toadd .= file_get_contents($moodlog);
+	file_put_contents($moodlog, $toadd);
+	echo "1";
+}
+
+?>
+
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+	</head>
+	<body>
+		
+		<center>
+			<?php if($error <> ""){echo $error; } ?>
+
+			<div class="banner">
+				<div class="header"><a href="/?logout"><i class="fas fa-heartbeat" ></i></a> moodlog.txt</div>
+
+				<div class="new-log">
+					
+					  <input type="range" id="happyval" value="5" min="1" max="10"/>
+					  <input  class="input" id="tags" placeholder="(+,-,@) description"/>
+					  <input type="button" value="+" onClick="updatePretext();"/>
+					  <input type="button" value="add" class="add" onClick="submitMood();"/>
+					
+				</div>
+				<div class="preview">
+					<span class="date">2018-09-11 20:27</span><span class="hpyno">[5]</span><span class="pretext" onClick="updatePretext();"></span></div>
+
+				<div class="filter" style="display:none">
+					<span class="filtitle">Filters:</span>
+					<span class="fas fa-search" style="float:right;font-size:15px;" onclick="applyFilters();"></span>
+				</div>
+			</div>
+
+			<div id="cal-heatmap"></div>
+
+			<div class="top10s">
+				<div class="toppos">
+					<div class="sub-header">Top 5 positive</div>
+				</div>
+				<div class="topneg">
+					<div class="sub-header">Top 5 negative</div>
+				</div>
+				<div class="topcon">
+					<div class="sub-header">Top 5 context</div>
+				</div>
+				<div class="latpos">
+					<div class="sub-header">Latest 5 positive</div>
+				</div>
+				<div class="latneg">
+					<div class="sub-header">Latest 5 negative</div>
+				</div>
+				<div class="latcon">
+					<div class="sub-header">Latest 5 context</div>
+				</div>
+			</div>
+
+			<div class="fullday">
+				<div class="previewhist">
+					
+					<?php
+						$result = today(date("Y-m-d"));
+						if($result != "0")
+							echo $result;
+					?>
+					
+				</div>
+			</div>
+		</center>
+
+		<script src="script.js"></script>
+ 
+	</body>
+</html>
diff --git a/login.html b/login.html
new file mode 100755
index 0000000..cf5481b
--- /dev/null
+++ b/login.html
@@ -0,0 +1,35 @@
+<html>
+	<head>
+
+		<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
+		<script type="text/javascript" src="https://d3js.org/d3.v3.min.js"></script>
+		<script type="text/javascript" src="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.min.js"></script>
+		<link rel="stylesheet" href="https://cdn.jsdelivr.net/cal-heatmap/3.3.10/cal-heatmap.css" />
+		<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:400,700" rel="stylesheet">
+		<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
+  		<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
+  		<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
+		<link rel="stylesheet" href="style.css" >
+		<style>
+			.login_form{
+			  height: 100%;
+			  width:100%;
+			  display: flex;
+			  align-items: center
+			}
+		</style>
+	</head>
+	<body>
+		
+		<div class="login_form">
+			<form method="POST" action="/" style="width:auto">
+				<input type="password" name="password" id="password" placeholder="password" style="text-align:center;"/>
+			</form>
+		</div>
+
+		<script src="script.js"></script>
+
+		<script>$("#password").focus();</script>
+ 
+	</body>
+</html>
\ No newline at end of file
diff --git a/moodlog.txt b/moodlog.txt
new file mode 100755
index 0000000..4048a5c
--- /dev/null
+++ b/moodlog.txt
@@ -0,0 +1,25 @@
+2018-09-21 19:45 [8] nearly finished webapp +code +moodlog 
+2018-09-21 15:20 [7] moodlog web, new challenge coins +code @personal
+2018-09-21 13:30 [5] waiting for client -waiting +phishing @work
+2018-09-20 17:30 [7] tricky moodlog JS +code @personal
+2018-09-20 10:00 [7] tricky phishing setup +phishing +code @work
+2018-09-19 12:00 [5] -ansa @work
+2018-09-18 22:00 [8] +moodlog +code @personal
+2018-09-18 17:00 [6] -reporting +chill @work
+2018-09-17 23:30 [7] sniper elite 4 +gaming @personal
+2018-09-17 12:30 [3] -onsite @bristol
+2018-09-16 20:00 [8] +newpc @personal
+2018-09-15 21:00 [7] -hangover +chill +adam @personal
+2018-09-14 21:00 [9] +pissup +adam +james @personal
+2018-09-13 07:24 [7] new computer +excited +pissup +adam +james @personal
+2018-09-13 10:22 [6] write presentation -work @work
+2018-09-12 09:18 [5] +code -waiting @work
+2018-09-11 18:00 [4] -knackered @work
+2018-09-11 09:00 [4] -ansa @work
+2018-09-10 21:00 [9] mate here +gaming @personal
+2018-09-10 18:00 [8] moodlog webapp +code @personal
+2018-09-10 11:30 [9] pwn3d +phishing @work
+2018-09-10 08:00 [6] +phishing -earlystart -support @work
+2018-09-09 23:00 [9] modlog sublime-syntax finished +code @personal
+2018-09-09 15:30 [8] moodlog concept +ideas @personal 
+2018-09-09 13:00 [7] chilled sunday +tv +chill @personal
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100755
index 0000000..255dcc1
--- /dev/null
+++ b/script.js
@@ -0,0 +1,431 @@
+/*var datas = [
+	{date: "2018-09-09", value: 10},
+	{date: "2018-09-08", value: 5},
+	{date: "2018-09-07", value: 8},
+	{date: "2018-09-07", value: 7},
+	{date: "2018-09-06", value: 9},
+	{date: "2018-09-05", value: 6},
+	{date: "2018-09-04", value: 5},
+	{date: "2018-09-03", value: 4},
+	{date: "2018-09-02", value: 7},
+	{date: "2018-08-02", value: 1}
+]
+
+/*
+var parser = function(data) {
+	var stats = {};
+	console.log(data);
+	for (var d in data) {
+		console.log(data[d].date);
+		var dateTime = new Date(data[d].date).toISOString();
+		var timestamp = Math.floor(dateTime / 1000);
+		let toTimestamp = strDate => Date.parse(data[d].date);
+		stats[timestamp] = data[d].value;
+	}
+	console.log(stats);
+	return stats;
+
+};
+*/
+/*
+var stats = {};
+var parser = function(data) {
+	//console.log(data);
+	for (var d in data) {
+		//console.log("date:"+data[d]);
+		//var date = new Date(data[d].date); // Date of activity 
+    	//var sec = date.getTime()/1000; // Convert to sec
+		stats[d] = data[d];
+		//cal.subDomainTextFormat(d, data[d]);
+	}
+
+	return stats;	
+};
+*/
+//var mainurl = "http://localhost:8080/test.json";
+var mainurl = "/?action=main_cal";
+var cal = new CalHeatMap();
+
+setUpCal();
+function setUpCal(){
+	var datethen = new Date();
+	datethen.setMonth(datethen.getMonth() - 9);
+
+	cal.init({
+		//data: "http://localhost:8080/index.php?action=main_cal",
+		data: mainurl,
+		dataType: "json",
+			//afterLoadData: parser,
+		start: datethen,
+		id : "graph",
+		domain : "month",			// Group data by month
+		subDomain : "day",			// Split each month by days
+		cellSize: 15,
+		cellPadding: 2,
+		cellRadius: 3,
+		domainGutter:2,
+		subDomainTitleFormat: {
+	        empty: "{date}",
+	        filled: "{count} - {date}"
+	    },
+	    //itemSelector: "#cal-heatmap",
+		range : 10,					// Just display 10 months
+		legend: [2,3,4,5,6,7,8,9], 	// Custom threshold for the scale
+		tooltip: false,
+		displayLegend: false,
+		label: {
+			position: "bottom",
+			align: "center",
+			offset: {x:0,y:-10},
+		},
+		considerMissingDataAsZero: true,
+		legendHorizontalPosition: "center",
+		legendColors: {
+			min: "#6b6de5",
+			max: "#46e260",
+		},
+		subDomainTextFormat: function(date ,value) {
+			var origdate = ""+date;
+			date =  origdate.split('00:00:00')[0]+'00:00:00';
+			var date = parseInt((new Date(date).getTime() /1000 ).toFixed(0))
+			var finval = 0;
+
+			/***
+			 * All of this cos of a damn bug! 
+			 * https://github.com/wa0x6e/cal-heatmap/issues/257
+			 */
+			$.ajax({
+				url: "/?action=date_average&date="+date,
+				async: false,
+				dataType: 'html',
+				success: function (response) {
+					//console.log(response);
+					finval = response;
+					console.log("origdate: "+origdate+" date: "+date+" val:"+response);
+				}
+			});
+
+			if (finval == 0){finval = "";}
+			return finval;
+		},
+		highlight: "now",
+		onClick: function(date, count) {
+			//alert("Oh gosh, " + count + " things occured on " + date.toISOString());
+			updateDayLog(date.toISOString().slice(0, 19).replace('T', ' '));
+		}
+	});
+}
+
+
+function checkStats(timestamp){
+	var finval = 0;
+	$.getJSON('test.json', function (data) {
+		$.each(data, function(i, field){
+			//console.log(field);
+			if(timestamp == i){
+				console.log("found: "+field);
+        		finval = field;
+        	}
+
+     	});
+     	//if (finval == 0){finval = "";}
+		return finval;
+	});
+
+}
+
+var availableTags = [
+	  "-ansa",
+	  "+phishing",
+	  "+chill",
+	  "@home",
+];
+$( function() {
+
+    $( "#tags" ).autocomplete({
+      source: availableTags
+    });
+} );
+
+function updateTime() {
+    var now = new Date();
+    var datestring = now.getFullYear() + "-" + ("0"+(now.getMonth()+1)).slice(-2) + "-" + ("0" + now.getDate()).slice(-2) + " " + ("0" + now.getHours()).slice(-2) + ":" + ("0" + now.getMinutes()).slice(-2);
+    $("span.date").html(datestring.toString());        
+}
+
+$("#happyval").on("input change", function() {
+    $(".hpyno").html("[" + $("#happyval").val() + "]");
+});
+removespan = function(span) {
+	span.remove();
+}
+
+/***
+ * filter adding and removing code
+ */
+var filter = 0;
+function addFilterPos(word){
+	filter++;
+	$('.filtitle').after('<span class="filpos" onclick="removefilter(this);">'+word+'</span>');
+	$(".filter").show();
+}
+function addFilterNeg(word){
+	filter++;
+	$('.filtitle').after('<span class="filneg" onclick="removefilter(this);">'+word+'</span>');
+	$(".filter").show();
+}
+function addFilterCon(word){
+	filter++;
+	$('.filtitle').after('<span class="filcon" onclick="removefilter(this);">'+word+'</span>');
+	$(".filter").show();
+}
+removefilter = function(span) {
+	filter--;
+	span.remove();
+	if(filter == 0){ 
+		$(".filter").hide(); 
+		updateCal("/?action=main_cal");
+	}
+}
+
+/***
+ * updating description 
+ */
+function updatePretext(){
+ 	var toadd = $("#tags").val();
+ 	switch(toadd.charAt(0)){
+ 		case "+":
+ 			$('.pretext').after('<span class="prepos" onclick="removespan(this);">'+toadd+'</span>');
+ 			break;
+ 		case "-":
+ 			$('.pretext').after('<span class="preneg" onclick="removespan(this);">'+toadd+'</span>');
+ 			break;
+ 		case "@":
+ 			$('.preview').append('<span class="precon" onclick="removespan(this);">'+toadd+'</span>');
+ 			break;
+ 		default:
+ 			$(".pretext").html( toadd );
+ 	}
+ 	$("#tags").val("");
+ 	//$(".pretext").html(  );
+ }
+
+  function submitMood(){
+ 	var toadd = $(".preview").text();
+
+ 	console.log(toadd);
+ }
+
+/***
+ * update main calendar values
+ */
+function updateCal(url){ //updateCal("/?action=main_cal");
+	mainurl = url;
+	cal.destroy(function(){
+		cal = new CalHeatMap();
+		setUpCal();
+	});
+}
+
+/***
+ * update specific day log
+ */
+function updateDayLog(date){
+	$.ajax({
+		url: "/?action=date&date="+date,
+		async: true,
+		dataType: 'html',
+		success: function (response) {
+			//console.log(response);
+			if(response != "0"){
+				$(".previewhist").html(response);
+			}
+		}
+	});
+}
+
+/***
+ * update latest tags
+ */
+function updateLatest(tag){
+	var string = "";
+	switch(tag) {
+		case "pos":
+			string = "<div class=\"sub-header\">Latest 5 positive</div>";
+			break;
+		case "neg":
+			string = "<div class=\"sub-header\">Latest 5 negative</div>";
+			break;
+		case "con":
+			string = "<div class=\"sub-header\">Latest 5 context</div>";
+			break;
+	}
+	$.ajax({
+		url: "/?action=latest&tag="+tag,
+		async: true,
+		dataType: 'json',
+		success: function (response) {
+			if(response != "0"){
+
+				$.each(response, function(i, item) {
+					var ntag = tag.charAt(0).toUpperCase() + tag.substr(1);
+				    string += "<span onclick=\"addFilter"+ntag+"($(this).text());\">"+item+"</span><br />";
+				 });
+
+				//console.log(response);
+				$(".lat"+tag).html(string);
+			}
+		}
+	});
+}
+
+/***
+ * update top tags
+ */
+function updateTop(tag){
+	var string = "";
+	switch(tag) {
+		case "pos":
+			string = "<div class=\"sub-header\">Top 5 positive</div>";
+			break;
+		case "neg":
+			string = "<div class=\"sub-header\">Top 5 negative</div>";
+			break;
+		case "con":
+			string = "<div class=\"sub-header\">Top 5 context</div>";
+			break;
+	}
+	$.ajax({
+		url: "/?action=top&tag="+tag,
+		async: true,
+		dataType: 'json',
+		success: function (response) {
+			if(response != "0"){
+
+				$.each(response, function(i, item) {
+					//console.log(item);
+					var ntag = tag.charAt(0).toUpperCase() + tag.substr(1);
+				    string += "<span onclick=\"addFilter"+ntag+"($(this).text());\">"+item+"</span><br />";
+				 });
+
+				//console.log(response);
+				$(".top"+tag).html(string);
+			}
+		}
+	});
+}
+
+/***
+ * update available tags
+ */
+function updateAvailable(){
+	$.ajax({
+		url: "/?action=alltag",
+		async: true,
+		dataType: 'json',
+		success: function (response) {
+			if(response != "0"){
+				availableTags = response;
+				    $( "#tags" ).autocomplete({
+				      source: availableTags
+				    });
+			}
+		}
+	});
+}
+
+/***
+ * display filtered calendar
+ */
+function applyFilters(){
+	var filttstring ="";
+	$(".filter").find("span").each(function() {
+    	filttstring += $(this).html();
+ 	});
+ 	filttstring = filttstring.slice(8);
+ 	filttstring = filttstring.replace(/\s+/g, '');
+ 	filttstring = filttstring.replace(/\+/g , "%2B");
+ 	//filttstring = encodeURIComponent(filttstring);
+	//console.log(filttstring);
+	updateCal("/?action=filtered_cal&filter="+filttstring);
+}
+
+/***
+ * save to moodlog
+ */
+function submitMood(){
+	var filttstring = [];
+	var sendString = "";
+	$(".preview").find("span").each(function() {
+    	filttstring.push( $(this).html() );
+ 	});
+ 	
+ 	filttstring.shift(); // remove date
+ 	filttstring[0] = filttstring[0].replace(/\[/g, ''); //fix no.
+ 	filttstring[0] = filttstring[0].replace(/\]/g, '|'); //fix no.
+
+ 	for (var i = 0, len = filttstring.length; i < len; i++) { //tidy for URL
+  		filttstring[i] = filttstring[i].replace(/\+/g , "%2B");
+  		filttstring[i] = filttstring[i].replace(/ /g , "%20");
+  		sendString += filttstring[i]
+	}
+
+	console.log(sendString);
+	$.ajax({
+		url: "/?action=save&log="+sendString,
+		async: true,
+		dataType: 'html',
+		success: function (response) {
+			if(response != "0"){
+
+				var now = new Date();
+    			var datestring = now.getFullYear() + "-" + ("0"+(now.getMonth()+1)).slice(-2) + "-" + ("0" + now.getDate()).slice(-2);
+    			var fulldatestring = now.getFullYear() + "-" + ("0"+(now.getMonth()+1)).slice(-2) + "-" + ("0" + now.getDate()).slice(-2) + " " + ("0" + now.getHours()).slice(-2) + ":" + ("0" + now.getMinutes()).slice(-2);
+
+    			$(".preview").html("<span class=\"date\">"+fulldatestring+"</span><span class=\"hpyno\">[5]</span><span class=\"pretext\" onclick=\"updatePretext();\"></span></div>")
+    			$("#happyval").val(5);
+				updateCal("/?action=main_cal");
+				updateDayLog(datestring);
+				updateTop("pos"); 
+				updateTop("neg"); 
+				updateTop("con"); 
+				updateLatest("pos"); 
+				updateLatest("neg"); 
+				updateLatest("con");
+			}
+		}
+	});
+	
+
+}
+
+/***
+ * once app loaded
+ */
+$(document).ready(function(){
+
+    $('#tags').keypress(function(e){
+		if(e.keyCode==13)
+			updatePretext();
+	});
+
+    updateTop("pos");
+    updateTop("neg");
+    updateTop("con");
+    updateLatest("pos");
+    updateLatest("neg");
+    updateLatest("con");
+
+    updateAvailable();
+
+	updateTime();
+    setInterval(updateTime, 5000); // 5 * 1000 miliseconds
+    var interval1 = setInterval(function () { updateCal(mainurl); }, 300000); // update every 5 mins (300000) 
+
+    var interval1 = setInterval(function () { updateTop("pos"); }, 300000);
+    var interval1 = setInterval(function () { updateTop("neg"); }, 300000);
+    var interval1 = setInterval(function () { updateTop("con"); }, 300000);
+    var interval1 = setInterval(function () { updateLatest("pos"); }, 300000);
+    var interval1 = setInterval(function () { updateLatest("neg"); }, 300000);
+    var interval1 = setInterval(function () { updateLatest("con"); }, 300000);
+});
diff --git a/style.css b/style.css
new file mode 100755
index 0000000..8ae59d5
--- /dev/null
+++ b/style.css
@@ -0,0 +1,134 @@
+body{
+	background-color:#333;
+	font-family: 'Source Code Pro', monospace;
+	color:#ccc;
+}
+
+
+form{
+  width:600px;
+  height:20px;
+  margin:0 auto;
+}
+input{
+	display: inline-block;
+	outline: none;
+}
+input[type="range"]{
+  -webkit-appearance:none;
+  width:250px;
+  height:10px;
+  margin:10px 10px;
+  background: linear-gradient(to right, #6b6de5 0%, #46e260 100%);
+  background-size:250px 2px;
+  background-position:center;
+  background-repeat:no-repeat;
+  overflow:hidden;
+  outline: none;
+}
+
+input[type="range"]:first-of-type{
+  margin-top:0px;
+}
+
+input[type="range"]::-webkit-slider-thumb{
+  -webkit-appearance:none;
+  width:20px;
+  height:20px;
+  background:#ddd;
+  position:relative;
+  z-index:3;
+  box-shadow:0 0 5px 0 rgba(0,0,0,0.3);
+}
+
+input[type="range"]::-webkit-slider-thumb:after{
+  content:" ";
+  width:20px;
+  height:10px;
+  position:absolute;
+  z-index:1;
+  right:20px;
+  top:5px;
+  background: #ff5b32;
+  background: linear-gradient(to right, #6b6de5 1%, #46e260 70%);
+}
+.input{
+	margin-left:20px;
+}
+.add{
+	margin-left:20px
+}
+.preview, .previewhist{
+	font-weight:100;
+	font-size:0.7em;
+	padding-bottom: 10px;
+}
+.date, .datehist{color: #9f00ca; margin-right:5px;}
+.hpyno, .hpyhist{color:#efe23e; margin-right:5px;}
+.pretext, .pretexthist{color:#ece5e5; margin-right:5px;}
+.prepos, .preposhist{ color: #58e81b; margin-right:5px;}
+.preneg, .preneghist{ color: #e81b1b; margin-right:5px;}
+.precon, .preconhist{ color: #999; margin-right:5px;}
+
+.filter{
+	background-color:#555;
+	width:880px;
+	font-weight:100;
+	font-size:0.7em;
+	padding:10px;
+	border-radius: 2px;
+}
+.filtitle{font-weight:700; margin-right:5px;}
+.filpos{ background-color: #58e81b; border-radius: 2px; padding:2px 5px; color:#222; margin-right:5px;}
+.filneg{ background-color: #e81b1b; border-radius: 2px; padding:2px 5px; color:#222; margin-right:5px;}
+.filcon{ background-color: #999; border-radius: 2px; padding:2px 5px; color:#222; margin-right:5px;}
+
+rect.r0 {
+    fill: #ededed;
+    fill: #000;
+}
+.highlight, rect.now, rect.now:hover{
+	stroke: #999;
+}
+.graph, .graph-legend rect {
+    shape-rendering: auto;
+}
+.subdomain-text{ fill:#111; font-weight:700;}
+.banner, .top10s, .fullday{
+	width:950px;
+	color:#ccc;
+	text-align:left;
+	font-weight:700;
+	margin-bottom:10px;
+	margin-left: 50px;
+}
+.header{
+	width:140px;
+	display:inline-block;
+	margin-right:197px;
+}
+.header a:link, .header a:hover, .header a:visited, .header a:active{
+	text-decoration: none;
+	color:#ccc;
+}
+.fullday{
+	padding-top:10px;
+}
+.new-log{
+	width:600px; 
+	display:inline-block;
+	vertical-align:top;
+}
+.sub-header{
+	font-weight:700;
+	color:#ccc;
+}
+.toppos, .latpos, .topneg, .latneg, .topcon, .latcon{ 
+	width:150px;
+	display: inline-block;
+	font-weight:100;
+	font-size:0.7em;
+}
+.toppos, .latpos{ color: #58e81b; vertical-align: top;}
+.topneg, .latneg{ color: #e81b1b; vertical-align: top;}
+.topcon, .latcon{ color: #999; vertical-align: top;}