Took the exam today, and earned the badge.
Web based single-page, light weight HTML editor with auto-save, using HTML, JavaScript and PHP
Source Code:
002 /**
003 * A lightweight, single page HTML editor with live preview and auto-save
004 * Author: Praveen Nair @ http://blog.ninethsense.com/
005 *
006 */
007
008 $f = $fn = "";
009 if (count($_GET) == 1) {
010 $f = key($_GET);
011 $fn = "$f.html";
012 } else {
013 die();
014 }
015
016 if ( isset($_POST["c"]) ) {
017 $content = $_POST["c"];
018 echo (file_put_contents($fn, $content))?"1":"-1";
019 die();
020 }
021
022 ?>
023 <html>
024 <head>
025 <meta http-equiv="content-type" content="text/html; charset=utf-8">
026 <style>
027 #tb {
028 margin-left: 5;
029 }
030 #editor, #preview {
031 flex: 1 0 0;
032 background:#eee;
033 margin: 5 5;
034 padding: 5 5;
035 overflow:auto;
036 }
037 #editor {
038 font-family: monospace;
039 }
040 #preview, a {
041 font-family: Arial, Helvetica, sans-serif;
042 }
043 [placeholder]:empty::before {
044 content: attr(placeholder);
045 color: #ccc;
046 }
047 #saved {
048 font-size:8pt;
049 margin-left:5px;
050 }
051 </style>
052 </head>
053 <body>
054 <div id="tb">
055 <input type="button" value="Save" onclick="Save()" /><span id="saved"></span>
056 <a href="preview.php?<?=$f?>" target="_blank" style="float:right;font-size:8pt">[Preview]</a>
057 </div>
058 <div style="display: flex;height:90%">
059
060 <div id="editor" contenteditable="true" onkeyup="LivePreview()" placeholder="Your HTML Code"></div>
061
062 <div id="preview" placeholder="Preview Area"></div>
063 </div>
064
065 <script>
066 var editor = document.getElementById("editor");
067 var preview = document.getElementById("preview");
068 var IsSaved = true;
069 editor.focus();
070 function LivePreview() {
071 preview.innerHTML = editor.innerText;
072 IsSaved = false;
073 }
074 function Save() {
075 var xhttp = new XMLHttpRequest();
076 xhttp.onreadystatechange = function() {
077 if (this.readyState == 4 && this.status == 200) {
078 if (xhttp.responseText == "1") {
079 document.getElementById("saved").style.color = 'green';
080 document.getElementById("saved").innerText = "Last saved at " + new Date() ;
081 IsSaved = true;
082 } else {
083 ShowError();
084 }
085 }
086 };
087 var formData = new FormData();
088 formData.append("c", editor.innerText);
089 xhttp.open("POST", "<?= $_SERVER["PHP_SELF"]. "?$f" ?>", true);
090 xhttp.send(formData);
091
092 }
093 setInterval(() => {
094 if (!IsSaved) {
095 Save();
096 }
097 }, 5000);
098
099 ShowError = function() {
100 var ele = document.getElementById("saved");
101 ele.style.color = 'red';
102 ele.innerText = "Couldn't Auto-save. Will retry soon" ;
103 }
104 window.onload = function() {
105 <?php
106 $content = "";
107 if ( $_SERVER['REQUEST_METHOD'] != 'POST' ) {
108 if (file_exists($fn)) {
109 $content = file_get_contents($fn);
110 }
111 echo "editor.innerText = `$content`;";
112 }
113 ?>
114 LivePreview();
115 }
116
117 </script>
118 </body>
119 </html>
120
Whitepaper on Designing an efficient Virtual Queue Management System
Recently I wrote a research paper on the said topic, and here are the links I published:
- Original, updated version @ GitHub – https://github.com/ninethsense/VirtualQueue/blob/master/README.md
- Medium – https://medium.com/@ninethsense_8477/yet-another-virtual-queue-management-system-design-44cdee123a0b
Additionally, a small excerpt in a Malayalam online news paper – https://www.janmabhumi.in/read/bevq-failure-is-a-lesson-how-to-build-the-best-virtual-queue-app/
My wp-ShowGithubFile plugin is accepted by WordPress today!
Though I wrote the plugin initially for personal use, now the same is available for you to use in your WordPress sites.
Link: https://wordpress.org/plugins/wp-showgithubfile/
You can either download it from the directory, or install directly within your WordPress installation. Here is a live demo of the plugin:
002
003 import java.util.Arrays;
004
005 public class Main {
006
007 public static void main(String[] args) {
008
009 // New Customer wants to buy a bottle
010 Customer customer = new Customer();
011
012 // Customer Registration
013 customer.RegisterMe("+919999999999", PhoneType.APP ); // App or SMS?
014
015 // Assuming Registration successful
016
017 // Customer requests the token using a mobile app, or by sending SMS
018 String CustomerToken = customer.giveMeAToken("695000"); // Pin code
019
020 if (CustomerToken != null) {
021 // Assuming Customer gets the token and he goes to the Outlet
022 } else {
023 // Seems there are no slots available. Try again later.
024 return;
025 }
026
027
028 // At the Outlet, sales guy is scanning the token
029 Boolean OutletVerification = new Outlet().isTheTokenShownByCustomerValid(CustomerToken);
030
031 if (OutletVerification) {
032 // Assuming the validation is success
033 System.out.println("Customer says: Wow, I got the bottle!");
034 } else {
035 System.out.println("Sales guy says: Get lost!");
036 }
037 }
038
039 public enum PhoneType { APP, SMS };
040
041 private static class VQServer {
042 // Database
043 public String[] tokenDB = { "A", "B","C","D","E" };
044 public String[] Outlets = {"Outlet1", "Outlet2", "Outlet3"};
045
046 public void registerCustomer(String phoneNumber, PhoneType phonetype) {
047 // Register customer
048
049 }
050 public String requestNewTokenByCustomer(String pinCode) {
051 // Logic for - Token generation logic
052 // Logic for - Find nearest outlet using pinCode
053
054 // Send token by SMS if PhoneType is SMS
055
056 return "C"; // Sample token
057 }
058
059 public Boolean validateTokenByOutlet(String token) {
060 return Arrays.asList(tokenDB).contains(token); // Validate
061 }
062 };
063
064 static VQServer vqServer = new VQServer();
065
066 private static class Customer {
067
068 public String giveMeAToken(String pinCode) {
069 return vqServer.requestNewTokenByCustomer(pinCode);
070 }
071 public void RegisterMe(String phoneNumber, PhoneType phonetype) {
072 // Customer Registration
073 vqServer.registerCustomer(phoneNumber, phonetype);
074 }
075 }
076 private static class Outlet {
077 public Boolean isTheTokenShownByCustomerValid(String token) {
078 return vqServer.validateTokenByOutlet(token);
079 }
080 }
081 }
My Groovy HelloScript contribution to community
Here goes my contribution to HelloScript project by Praseed Pai.
GitHub: https://github.com/praseedpai/HelloScript_files/blob/master/Groovy/HelloScript.groovy
Source Code:
002 * HelloScript.groovy
003 */
004
005 // A Simple Console Output
006
007 println "Hello World"
008
009 // Some more
010 print ("Hello World")
011 System.out.println("K-Mug"); // Java style also works
012
013 // Declare variables
014 def a = 100 // a number, def is about scope
015 b = 100; // another number
016 year = "Twenty Twenty" // a string
017
018 // String formatting & interpolation
019 println "This is ${a}, ${b}, and " + year;
020
021 // Reassign a variable
022 year = 2008; // dynamic typing
023
024 // if-else
025 if (year > 2008)
026 println "Welcome to the future - yes, we have flying cars!"
027 else if (year < 2008)
028 printLN "The past - please don't change anything. Don't step on any butterflies. And for the sake of all thats good and holy, stay away from your parents!"
029 else
030 println "Anything wrong with your time machine? You have not gone anywhere, kiddo."
031
032
033 // Range based for loop
034 for (i in 0..3) {
035 println "$i Hi there!"
036 }
037
038 // Copying range value to a variable
039 range_array = (0..10)
040 print range_array;
041
042 // Array demo
043 rules = ['Do no harm','Obey','Continue Living']
044 println rules;
045
046 rules << "Be Honest" // add one more item
047 println rules
048
049 // Array demo, with mixed types
050 more_rules = ['Do no harm','Obey','Continue Living', 404, 403, 500, 100f]
051 println more_rules;
052
053 // Loop through Array
054 i = 0
055 while (i < rules.size()) {
056 print "Rule " + (i + 1) + " : " + rules[i]
057 i += 1
058 }
059
060 println() // just a newline
061
062 // Associating array
063 associated = [
064 'hello' : 'world',
065 'foo' : 'bar',
066 'lorem' : 'ipsum'
067 ]
068
069 for (ele in associated) {
070 print ele.key + " : " + ele.value
071 }
072
073 println() // just a newline
074
075 // Example of a Nested Loop
076 // To calculate Pythagorean Triplets
077 n = 10
078 println "-------------------------------------"
079 for (va in (1..n)) {
080 for (vb in (va..n)) {
081 Integer c_square = va**2 + vb**2
082 Integer vc = Math.sqrt(c_square)
083 if ((c_square - vc**2) == 0) {
084 println va + " " + vb + " " + vc
085 }
086 }
087 }
088 println "----------------------------------"
089
090 // Iterating over a list using range and size
091 println "-------------------------------------"
092 fibonacci = [0,1,1,2,3,5,8,13,21]
093 for (i in (0..fibonacci.size()-1)) {
094 println i + " " + fibonacci[i]
095 }
096 println "---------------------------------------"
097
098 // Parsing a line - split and join
099 csv_values = "hello,world,how,are,you".split(",")
100 println csv_values;
101 println csv_values.join(":")
102
103 // A Single Argument Function
104 def hello(name) {
105 return "Hello ${name}!"
106 }
107 println hello("Praveen")
108
109 // A simple class
110 class Movie {
111 String name = ""
112 Integer rating = 0
113
114 def Movie(movieName) {
115 this.name = movieName
116 this.rateMovie()
117 }
118
119 def rateMovie() {
120 this.rating = (this.name.length() % 10) + 1 // IMDBs rating algorithm. True story!
121 }
122 def printMovieDetails() {
123 println "Movie : " + this.name
124 println "Rating : " + '*'.multiply(this.rating) + "(" + this.rating +")"
125 }
126 }
127
128 // Create the Object
129 ncfom = new Movie("New Country for Old Men"); // It's a sequel!
130 ncfom.printMovieDetails()
131
132 // Closures in action
133 myList = ["Hello","My","World","What's","Up"]
134 myList.each {
135 print it + "-" // it is special
136 }
137
138 // Multiplication table
139 (1..10).each {
140 println "${it} x 2 = ${it*2}"
141 }
142
143 println() // just a newline
144
145 // Tuples
146 myTuple = new Tuple(1, 'two', 3, 'four')
147 println myTuple
148
149 // File IO - Create a new file
150 myFile = new File("myfile.txt");
151 myFile.text = "Hello World! - from the file"
152 myFile.createNewFile()
153
154 // File IO - Read from file
155 println myFile.text
156
157 // File IO - With closure
158 myFile.eachLine {
159 l -> println l.toUpperCase()
160 }
161
162 // Regular Expressions
163 import java.util.regex.Pattern
164 Pattern pattern = ~/World/
165 str = "Hello World, this is Universe, not your World!"
166 println "Found " + pattern.matcher(str).size() + " mathes."
WordPress plugin – Show your source code directly from GitHub in your blog/website
Show a file, preferably source code file content in a WordPress blog post or page. This plugin shows always the latest code from GitHub.
Visit my GitHub repository to download the plugin for free – https://github.com/ninethsense/wp-ShowGithubFile
Source Code: (Live Example directly from GitHub 🙂
002 /**
003 * Plugin Name: wp-ShowGithubFile
004 * Description: Show a file, preferably source code file content in a WordPress blog post or page
005 * Version: 1.0.0
006 * Author: NinethSense
007 * Author URI: https://blog.ninethsense.com/
008 * License: GPL v2 or later
009 */
010
011
012 add_shortcode( "GitHub", "ShowGitHub" );
013 function ShowGitHub($atts) {
014 if (!isset($atts["file"]) && !strpos(strtolower($atts["file"]), "https://raw.githubusercontent.com/" )) {
015 // Also, I want only files from GitHub. Modify this to show file from any URL
016 return "[Invalid GitHub Raw file]";
017 }
018
019 $fh = @get_headers($atts["file"]);
020
021 if (strpos($fh[0],"200") == 0) {
022 return "[Invalid file]";
023 }
024
025 $fcontents = file_get_contents(trim($atts["file"]));
026 $notphp = false;
027
028 if (strpos($fcontents, "?php") == false) {
029 $fcontents = "<?php ".$fcontents;
030 $notphp = true;
031 }
032
033 // Make use of PHP syntax highlighing. Something is better than nothing.
034 $fcontents = highlight_string($fcontents, TRUE);
035
036 if ($notphp) {
037 $fcontents = str_replace("<?php ", "",$fcontents);
038 $notphp = false;
039 }
040
041 $fcontents = str_replace(["<code>", "</code>"], "",$fcontents);
042
043 $fcontents = explode("<br />",$fcontents);
044
045 $style = (isset($atts["style"])) ?$atts["style"]:"";
046 $ret = "<div style='font-family:monospace;background-color:#dcd7ca;width:100%;overflow:auto;white-space:nowrap;border:solid 1px #aaa;font-size:10pt;$style'>";
047 for ($i=0;$i<sizeof($fcontents);$i++) {
048 $line = $fcontents[$i];
049 $ret .= "<span style='font-size:10pt;display:block;width:40px;background-color:#aaa;float:left'>" .
050 str_pad($i+1, 3,'0',STR_PAD_LEFT) ." </span><span style='margin-left:10px;width:100%;inline-block'>" . $line . "</span><br />";
051 }
052 $ret .= "</div>";
053
054 file_put_contents("D:\\test.txt", $ret);
055 return $ret;
056
057
058 }
059 ?>
PHP PortPing script – check host connectivity
Here is a script in PHP I wrote to check if a remote host and port are open for you to connect. Do not mistake this as an equivalent to ping command because ping uses ICMP and I used TCP using PHP’s famous fsockopen() function, and a small piece of AJAX.
You can get the latest source code from my GitHub code share page – https://github.com/ninethsense/code-share/
PHP:
function ping($host, $port) {
$startTime = time();
if ($fs = fsockopen($host, $port, $errCode, $errStr, 1)) {
$timeTaken = (time()-$startTime)/1000;
echo "Reply from $host:$port time={$timeTaken}ms";
fclose($fs);
} else {
echo "Request timed out.";
}
echo "<br>";
}
JavaScript:
var count = 0;
var intervalID = setInterval(function PortPing() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("console").innerHTML += this.responseText;
}
};
xhttp.open("GET", "PortPing.php?source=self&host=<?=$host?>&port=<?=$port?>", true);
xhttp.send();
if (++count > <?=$t-1?>) {
clearInterval(intervalID);
}
},2);
How to setup AWS SES / Simple Email Service
This is a tutorial on how to setup AWS SES / Simple Email Service.
Step 1 – Login to your AWS Console, then choose Services –> Customer Engagement –> Simple Email Service
Step 2 – Verify a New Domain
Choose “Domains” from left navigation panel, then click –> Verify a New Domain button
Step 2.2 – Enter Domain name
Also click checkbox Generate DKIM settings, though optional, I will be using this.
You will be displayed with a list of DNS settings in the next screen.
Once you completed the Step 3, click close.
Step 3 – Edit DNS records
You will have to login to your domain control panel and add these.
I will be using cPanel for this exercise. Steps are almost same with any domain/hosting control panel.
Step 4 – Wait for the domain to get verified. Click refresh icon on the right-top whenever you are impatient.
You have nothing to do here. Just wait for some 2-5-10 minutes.
Step 4.1 – Verify Email Address
You cannot even send a test mail, unless you have a email id verified.
Choose ‘Email Addresses’ from the left-navigation panel and click “Verify a New Email Address” button.
Make sure you enter an already existing email id.
A verification mail will be sent to your inbox.
There will be a URL you are expected to click, and you are verified.
Once verified, you should be able to see the verification status updated in AWS console too.
Step 5 – Send test mail.
Go back to Domains –> “Send a Test Mail” button.
A simple Folder Watcher for windows
Here is a simple file system watcher for windows. I wrote a script to monitor a folder for a specific purpose, but then thought to make this a generic tool so someone will benefit if I host in GitHub.
Find full project at https://github.com/ninethsense/FolderWatcher
Source Code:
private void Form1_Load(object sender, EventArgs e)
{
toolStripLabel.Text = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
StartMonitoring();
}
private void StartMonitoring()
{
watcher = new FileSystemWatcher(toolStripLabel.Text)
{
IncludeSubdirectories = true,
EnableRaisingEvents = true
};
watcher.Created += Watcher_Handler;
watcher.Deleted += Watcher_Handler;
watcher.Renamed += Watcher_Handler;
watcher.Changed += Watcher_Handler;
}
private void Watcher_Handler(object sender, FileSystemEventArgs e)
{
Invoke(new Action(() =>
{
listBoxLog.Items.Add($"[{DateTime.Now}][{e.ChangeType}] {e.FullPath}");
}));
}
private void ToolStripClearButton_Click(object sender, EventArgs e)
{
listBoxLog.Items.Clear();
}
private void ToolStripChooseFolderButton_Click(object sender, EventArgs e)
{
watcher.EnableRaisingEvents = false;
folderBrowserDialog.SelectedPath = toolStripLabel.Text;
var dlg = folderBrowserDialog.ShowDialog();
if (dlg == DialogResult.OK)
{
string OldPath = toolStripLabel.Text;
try
{
watcher.Path = folderBrowserDialog.SelectedPath;
watcher.EnableRaisingEvents = true;
} catch (FileNotFoundException ex)
{
toolStripLabel.Text = OldPath;
watcher.Path = OldPath;
MessageBox.Show($"Seems you don't have permission to access folder {folderBrowserDialog.SelectedPath}. Try starting this app as Administrator\n\nDetails:\n{ex.Message}", "Error", MessageBoxButtons.OK);
watcher.EnableRaisingEvents = true;
}
toolStripLabel.Text = watcher.Path;
}
}