Saturday, September 6, 2014

Binary Tree using HTML5 Canvas and JavaScript

Hi Guys -

I was just playing around with HTML5 Canvas and thought it will be fun to create a binary tree implementation using JavaScript.

I tried this a few years ago with Java and applets. Well, yeah u guessed it, it was a PITA.

With JavaScript and Canvas, it was a smooth ride.

The code below is only for the purpose of demo. Some nodes might overlap if the tree has a lot
of nodes.

Tested on Google Chrome

1 - Create a file index.html and add the below code to it.
      It contains an
      a - Input box where the user will enter the number to be added
      b - A button to add entered number
      c - A canvas element
      d - A script tag

<!DOCTYPE html>
<html>
<head>
<style>
.center {margin: auto; width: 50%;}
<style>
</head>
<body>
<div class='input-box'>
<input id='tree-input' type='number' placeholder='Enter number'>
<button id='add-to-tree' onclick="addToTree()">Add To Tree</button>
</div>
<div class="tree center">
<canvas id='my-canvas' width="400" height="400">
Your browser doesnot support canvas
</canvas>
</div>
<script>
</script>
</body>
</html>
view raw index.html hosted with ❤ by GitHub

     
2 - Next we will add a node object. Node, as the name suggests, represent a node in the tree
     Add the below code in the script tag of the index.html

// Represents the node in the tree. Will be displayed as a small circle in the browser.
// x, y --> x, y co-ordinates of the center of circle
// r --> radius of the circle
// ctx --> context of the canvas
// data --> data to be displayed (Only number)
var Node = function(x,y,r, ctx, data) {
// left child of a node
this.leftNode = null;
// right child of a node
this.rightNode = null;
// draw function. Responsible for drawing the node
this.draw = function() {
ctx.beginPath();
ctx.arc(x, y, r, 0, 2*Math.PI);
ctx.stroke();
ctx.closePath();
ctx.strokeText(data, x, y);
};
// Simple getters
this.getData = function() { return data; };
this.getX = function() { return x; };
this.getY = function() { return y; };
this.getRadius = function() { return r; };
// Returns coordinate for the left child
// Go back 3 times radius in x axis and
// go down 3 times radius in y axis
this.leftCoordinate = function() {
return {cx: (x - (3*r)), cy: (y + (3*r))}
};
// Same concept as above but for right child
this.rightCoordinate = function() {
return {cx: (x + (3*r)), cy: (y+(3*r))}
};
};
view raw node.js hosted with ❤ by GitHub
   

3 - Next we will add code to draw a line from parent to child. Add the below code to the script tag    
   
// Draws a line from one circle(node) to another circle (node)
var Line = function() {
// Takes
// x,y - starting x,y coordinate
// toX, toY - ending x,y coordinate
this.draw = function(x, y, toX, toY, r, ctx) {
var moveToX = x;
var moveToY = y + r;
var lineToX = toX;
var lineToY = toY - r;
ctx.beginPath();
ctx.moveTo(moveToX, moveToY);
ctx.lineTo(lineToX, lineToY);
ctx.stroke();
};
};
view raw line.js hosted with ❤ by GitHub



4 - Next we add the core logic of a binary tree. To understand that logic, you should know how
     a binary tree works. Add the blow code the script tag

   
// Represents the btree logic
var BTree = function() {
var c = document.getElementById('my-canvas');
var ctx = c.getContext('2d');
var line = new Line();
this.root = null;
var self = this;
// Getter for root
this.getRoot = function() { return this.root; };
// Adds element to the tree
this.add = function( data) {
// If root exists, then recursively find the place to add the new node
if(this.root) {
this.recursiveAddNode(this.root, null, null, data);
} else {
// If not, the add the element as a root
this.root = this.addAndDisplayNode(200, 20, 15, ctx, data);
return;
}
};
// Recurively traverse the tree and find the place to add the node
this.recursiveAddNode = function(node, prevNode, coordinateCallback, data) {
if(!node) {
// This is either node.leftCoordinate or node.rightCoordinate
var xy = coordinateCallback();
var newNode = this.addAndDisplayNode(xy.cx, xy.cy, 15, ctx, data);
line.draw(prevNode.getX(), prevNode.getY(), xy.cx, xy.cy, prevNode.getRadius(), ctx)
return newNode;
}
else {
if(data <= node.getData()) {
node.left = this.recursiveAddNode(node.left, node, node.leftCoordinate, data);
}
else {
node.right = this.recursiveAddNode(node.right, node, node.rightCoordinate, data);
}
return node;
}
};
// Adds the node to the tree and calls the draw function
this.addAndDisplayNode = function(x, y, r, ctx, data) {
var node = new Node(x, y, r, ctx, data);
node.draw();
return node;
};
};
view raw btree.js hosted with ❤ by GitHub


5 - Now we  need to create a binary tree object to which we can add node
 
     Add the below code to the script tag

     var btree = new BTree();

6 - Ok. We are almost done. We just need to wire the input box and add to tree button
     Add the below code to the script tag

var addToTree = function() {
input = document.getElementById('tree-input');
value = parseInt(input.value);
if(value)
btree.add(value);
else
alert("Wrong input");
};
view raw addToTree.js hosted with ❤ by GitHub

    

Thursday, August 21, 2014

Elasticsearch 101 - How secure is it ?

So, I wanted to add full text search functionality to one of my projects and after doing some research I decided to go with Elasticsearch.

While reading the docs, I came across two RESTful apis which were good but also dangerously exploitable.

So what are those apis - (assuming that a local instance is running on port - 9200 )

1 - curl XGET 'http://localhost:9200/_nodes?pretty=true'
   
     Run this command from your terminal and you will see a lot of details about your machine

  • Paths - 
    • logs: /Users/I/am/a/hacker/logs
    • home: /Users/I/can/see/your/home
  • OS info -
    • cpu details
    • memory details
    • and yeah JVM details
  • Network info - 
    • IP address
    • mac address

2 - curl -XPOST 'http://localhost:9200/_cluster/nodes/_master/_shutdown'   or
     curl -XPOST 'http://localhost:9200/_shutdown'

     Any user can execute the above command and bring down your whole cluster. 
     Still most big companies have pretty good firewall setup so its hard to get access to a machine but
     still, imo, there should be some kind of permission to execute these commands


Anyways these are some interesting things which I came across while reading the docs.


Sunday, April 6, 2014

Connecting To MongoDB From Node.js Beginner's Basic

Ok guys - Here we will create a simple file that will connect to a local instance of Mongo and read data from the 'test' database.

Assumptions - 
1 - A local Mongo server is running at port 27017 (default port)

Step 0 - Create a directory called 'testing' and cd into it.

Step 1 - Connect to mongo using a mongo shell
Step 2 -  Add some data to a collection named 'heroes' in the test db.
              use test
             db.heroes.insert([{name: 'Super Man'}, {name: 'Bat Man'}]) 

Step 3 - Create a file called simple_connect.js and the following content to the file

             
var MongoClient = require('mongodb').MongoClient;
var connectionString = 'mongodb://localhost:27017/test';
// connect to test db
MongoClient.connect(connectionString, function(err, db) {
if(err) throw err;
console.log("CONNECTED");
var q = {name: 'Super Man'};
// query superheroes collection and display result
db.collection('heroes').findOne(q,function(err, doc) {
if(err) throw err;
console.dir(doc);
db.close();
});
});

Step 4 - If you haven't already installed the 'mongodb' module, run
             npm install mongodb

Step 4 - Run
             node simple_connect.js

             

Friday, March 28, 2014

Rails Default Scope Affects Model Initialization

Hi Guys - Ran into this while working on a project.  Now, default scope works fine for most of the stuff but it also has a secret to itself which I didn't realize (my bad).

Lets consider two cases,  one in which default scope affect is realized and other one in which it isn't.

------------
class ModelNotAffected < ActiveRecord::Base
  attr_accessible :name, :is_deleted

  default_scope where(:is_deleted => 0)
end

------------

class ModelAffected < ActiveRecord::Base
  attr_accessible :stall, :is_active

  default_scope where(:is_active => 1)
end

------------

How ?

ModelNotAffected.new({:name => 'Spider Man'})
# => {:name => 'Spider Man', :is_deleted => 0}
# This is what u kind of want

ModelAffected.new({:stall => Art Works''})
# => {:stall => 'Art Works', :is_active => 1}
# This might not be the case. There might be some condition which would make the stall as is_active

Well note that how default scope affects model initialization.

Thanks

Thursday, March 20, 2014

Nodejs Watching a file + Spawning new processes to list file information

Hi guys - Trying to get my hands dirty with Node.js and its pretty cool.

Its so easy to do stuff. Here is a small code snippet which demonstrate watching a file and spawning a child process to list the file info.

var fs = require('fs');
var spawnProcess = require('child_process').spawn;
var filename = 'some/file'
fs.watch(filename, function() {
var list = spawnProcess('ls', ['-lh', filename]);
var info = '';
// listener get invoked every time a chunk of data is available. Data is read in chunks
list.stdout.on('data', function(chunk) {
output += chunk.toString();
});
// When child process exit, it emits the close event
list.on('close', function() {
var parts = output.split(/\s+/);
console.dir([parts[0], parts[4], parts[8]]);
});
});


Thanks


Tuesday, March 18, 2014

Truncating text or string in Ruby

Hi Guys - Today I was working on a small issue where I had to add some client side validation.

The fix was to add limit to the number of chars in a text area. The fix is as easy as adding 'maxlength=n' attribute.

But this can be circumvented easily in the client side. So what ?

In the server side, are we going to throw an error and raise an exception that the text is too long ?

Well another way is to truncate this text.

In ruby, simply do this -

MaxLength = N
valid_string = some_long_text[0,N] if some_long_text.length > N
view raw truncate.rb hosted with ❤ by GitHub


This will simply truncate the text

Thanks

Sunday, March 16, 2014

https curl POST, GET, DELETE Images or Video files

Hi guys,

So I was trying to test some api's from my terminal and I decided to use CURL for doing POST, GET and DELETE.

Now, the api's use HTTPS so I had to figure out how to do https curl. After Googling for few minutes, I was able to figure it out.

There were few things which were missing from most of the posts. Hopefully this will help someone or save someone's time.

Few points to note

#1 - Url is in double quotes
#2 - query string is encoded.

# upload image/video using POST
curl -i --trace -H --data-binary "@/some/path/to/video/or/image/file" "https://somebaseurl/action?encodedQueryString" -v

#get file using GET
curl -i --trace -H -G "https://somebaseurl/action?encodedQueryString"


# delete file
curl -i --trace -H -X DELETE "https://somebaseurl/action?encodedQueryString"

Thanks


Tuesday, February 18, 2014

jQuery - waiting for multiple AJAX requests to finish

Problem I am solving -

Wait for N or Multiple or Unknown number (Depends on some logic) of ajax request using JQuery to complete, i.e.

$.when(N ajax request).then(do something)

Lets take a look at easier version of the problem, what if we want to wait for only two calls
class Test
waitForTwoCalls: () ->
$.when(@firstCall(), @secondCall()).then () =>
doSomeThing()
firstCall: () ->
token = $.Deferred
$.ajax({
url: foo/bar,
....
success: (response) =>
token.resolve
})
secondCall: () ->
token = $.Deferred
$.ajax({
url: foo/bar,
....
success: (response) =>
token.resolve
})


Well that was easy, so what... huh

What if you wana wait for n number of calls ? You cannot do $.when(call1, call2, ....., calln).then...

Lets take a look at a use case -

Lets say there is an array of ids and for each id in the array, we gota make a call and when all the data is loaded, we want to show a big red BLINK.

Here is how we gona do this -

# Makes ajax req to fetch data
class Model
initialize(id)
@id = id
load: (token) ->
$.ajax({
url: "foo/bar/#{@id}",
....
success: (response) =>
token.resolve
})
class Test
waitForNCalls: (ids) ->
tokens = []
for id in ids
token = $.Deferred
loader = new Model(id)
loader.load(token)
tokens.push(token)
return tokens
# Here is where the magic happens, it waits for all the tokens to get resolved
$.when.apply(this, @waitForNCalls([1,2,3....N])).done( =>
# Show RED BLINK
)