Tuesday, October 19, 2010

jQuery & JSON to draw single-elimination tournament bracket

Often I see sites that present tournament brackets as an image (even on fairly technical sites, eg http://us.battle.net/sc2/en/blog/936927#blog). Purely out of curiosity, I decided to see what would be involved in merely providing the data from the server and letting an HTML UI build up on the fly using jQuery. To avoid needing to produce a server for this I simply hard-coded in JSON that might have been returned from a server with (very) basic information about the tournament:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
  <title>MyTournamentName</title>
 <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js' type='text/javascript'>
 </script>
 <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js' type='text/javascript'>
 </script>  
  <script type="text/javascript">  
    var matchInfo = {
      "rounds" : [
        { "name": "Round1",
          "matches" : [
            { "id" : 1, "p1" : "mTwDeMuslim", "p2" : "Luffy" },
            { "id" : 2, "p1" : "SeleCT", "p2" : "NEXGenius" },
            { "id" : 3, "p1" : "Fenix", "p2" : "SoftBall" },
            { "id" : 4, "p1" : "White-Ra", "p2" : "Ice" },
            { "id" : 5, "p1" : "HuK", "p2" : "RedArchon" },
            { "id" : 6, "p1" : "Capoch", "p2" : "Loner" },
            { "id" : 7, "p1" : "mTwDIMAGA", "p2" : "MakaPrime" },
            { "id" : 8, "p1" : "TLAF-Liquid`TLO", "p2" : "SEN" }
          ]
        },
        { "name": "Round2",
          "matches" : [
            { "id" : 9, "p1" : null, "p2" : null },
            { "id" : 10, "p1" : null, "p2" : null },
            { "id" : 11, "p1" : null, "p2" : null },
            { "id" : 12, "p1" : null, "p2" : null }
          ]
        },
        { "name": "Round3",
          "matches" : [
            { "id" : 13, "p1" : null, "p2" : null },
            { "id" : 14, "p1" : null, "p2" : null },
          ]
        },
        { "name": "Round4",
          "matches" : [
            { "id" : 15, "p1" : null, "p2" : null },
          ]
        }                
      ]
    };
  </script>
</head>
<body>
  <div>blah blah blah</div>
  <div id="writeHere" class="tournament"></div>
  <div>blah blah blah</div>
</body>
</html>
Next we need to write some jQuery code to fill in the div with id="writeHere" with our purely html-based tournament bracket. Easy enough to do (note that some rudimentary css has been slapped in to show us where which bits are):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
  <title>MyTournamentName</title>
 <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js' type='text/javascript'>
 </script>
 <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js' type='text/javascript'>
 </script>  
  <style type="text/css">
  .tournament {    
    background-color: #F0F0F0;
    border: dashed 1px solid;
    overflow: auto;
  }
  .tournament .bracket {
    background-color: #DFDFDF;
    min-width: 100px;    
    vertical-align: top;
    float: left;
  }
  
  .tournament .bracket .match {
    background-color: #D0D0D0;
    border-top: 1px solid;
    border-right: 1px solid;
    border-bottom: 1px solid;  
  }
  .tournament .bracket .match .p1 {    
    height: 20px;
  }
  .tournament .bracket .match .p2 {
    height: 20px;
  }    
  .tournament .bracket .match .spacer {
    background-color: #DFDFDF;
    height: 38px;
  }
  .tournament .bracket .spacer {
    height: 80px;
  }
  .tournament .bracket .half-spacer {
    height: 40px;
  }
  .tournament .bracket .small-spacer {
    height: 10px;
    background-color: #F1F1F1;
  }
  
  .left-line {
    border-left: 1px solid;
  }
  
  .tournament .cell {
    min-width: 100px;
    height: 20px;
    float: left;
    background-color: #DFDFDF;    
  }   
  .tournament .l2 {
    background-color: #D0D0D0;
  }     
  .tournament .lmax {
    width: 0px;
    clear: both;
  }    
  </style>
  <script type="text/javascript">
  
    var matchInfo = {
      "rounds" : [
        { "name": "Round1",
          "matches" : [
            { "id" : 1, "p1" : "mTwDeMuslim", "p2" : "Luffy" },
            { "id" : 2, "p1" : "SeleCT", "p2" : "NEXGenius" },
            { "id" : 3, "p1" : "Fenix", "p2" : "SoftBall" },
            { "id" : 4, "p1" : "White-Ra", "p2" : "Ice" },
            { "id" : 5, "p1" : "HuK", "p2" : "RedArchon" },
            { "id" : 6, "p1" : "Capoch", "p2" : "Loner" },
            { "id" : 7, "p1" : "mTwDIMAGA", "p2" : "MakaPrime" },
            { "id" : 8, "p1" : "TLAF-Liquid`TLO", "p2" : "SEN" }
          ]
        },
        { "name": "Round2",
          "matches" : [
            { "id" : 9, "p1" : null, "p2" : null },
            { "id" : 10, "p1" : null, "p2" : null },
            { "id" : 11, "p1" : null, "p2" : null },
            { "id" : 12, "p1" : null, "p2" : null }
          ]
        },
        { "name": "Round3",
          "matches" : [
            { "id" : 13, "p1" : null, "p2" : null },
            { "id" : 14, "p1" : null, "p2" : null },
          ]
        },
        { "name": "Round4",
          "matches" : [
            { "id" : 15, "p1" : null, "p2" : null },
          ]
        }                
      ]
    };
  
    $(document).ready(function($) {       
      var base = $('#writeHere');
      var numTeams = 16;
      var matchesByRound = setupMatchboxes(numTeams);
      
      for (var lvl=0; lvl<matchesByRound.length; lvl++) {                
        var matchBoxes = matchesByRound[lvl];        
        var bracket = checkedAppend('<div class="bracket"></div>', base);
        
        for (var i=0; i<matchBoxes.length; i++) {                     
          var match = matchInfo.rounds[lvl].matches[i];
          var matchHtml = '<div class="match" id="match' + match.id + '">'
            + '<div class="p1">' + fmtName(match.p1) + '</div>'
            + '<div class="spacer"></div>'
            + '<div class="p2">' + fmtName(match.p2) + '</div>';
          checkedAppend(matchHtml, bracket);  
        }
      }      
    });
    
    function fmtName(name) {
      return null != name ? name : '?';
    }
    
    function setupMatchboxes(numTeams) {
      var numLevels = Math.log(numTeams)/Math.LN2;
      var numMatchesForLevel = numTeams / 2;
      var matchBoxes = [];
      
      do {
        var matchesForLevel = [];        
        matchBoxes.push(matchesForLevel);
        
        for (var match=0; match<numMatchesForLevel; match++) {
          matchesForLevel.push(match);
        }
        
        numMatchesForLevel = numMatchesForLevel / 2;
      } while(numMatchesForLevel >= 1);
      return matchBoxes;
    }
    
    function checkedAppend(rawHtml, appendTo) {
      var html = $(rawHtml);
      if (0 == html.length) {
        throw "Built ourselves bad html : " + rawHtml;
      }
      html.appendTo(appendTo);      
      return html;
    }
  </script>
</head>
<body>
  <div>blah blah blah</div>
  <div id="writeHere" class="tournament"></div>
  <div>blah blah blah</div>
</body>
</html>
However, this doesn't line things up quite as nicely as one might hope (to say the least):

We have a couple of clear problems:

  1. We probably want a small vertical space between the first row of matches.
  2. For rows 2..N, a match needs to line up such that its top is at the center of one of the matches on the previous row and its bottom is at the center of another. The specific offset helpfully changes from row to row. It turns out to be a bit of a pain to write css for this so instead we'll just write jQuery code to manually size elements for our first pass. Eg we want something like this (note inconsistent sizing and positioning row to row):
Luckily jQuery provides convenient accessors for height and position so we can write code that literally says "make a vertical spacing div that is half the size of that div and make my div tall enough to stretch from there to there". The main thing that will need an update is that we'll need to keep references to the divs as we go along row by row. This will let us easily set things relative to other things similar to:
var newH = stretchTo.position().top + stretchTo.height()/2 - matchDiv.position().top;
This will ultimately yield the following javascript gibberish:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
  <title>MyTournamentName</title>
 <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js' type='text/javascript'>
 </script>
 <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js' type='text/javascript'>
 </script>  
  <style type="text/css">
  .tournament {    
    background-color: #F0F0F0;
    border: dashed 1px solid;
    overflow: auto;
  }
  .tournament .bracket {
    background-color: #DFDFDF;
    min-width: 100px;    
    vertical-align: top;
    float: left;
  }
  
  .tournament .bracket .match {
    background-color: #D0D0D0;
    border-top: 1px solid;
    border-right: 1px solid;
    border-bottom: 1px solid;  
  }
  .tournament .bracket .match .p1 {    
    height: 20px;
  }
  .tournament .bracket .match .p2 {
    height: 20px;
  }    
  .tournament .bracket .match .spacer {
    background-color: #DFDFDF;
    height: 38px;
  }
  .tournament .bracket .spacer {
    height: 80px;
  }
  .tournament .bracket .half-spacer {
    height: 40px;
  }
  .tournament .bracket .small-spacer {
    height: 10px;
    background-color: #F1F1F1;
  }
  
  .left-line {
    border-left: 1px solid;
  }
  
  .tournament .cell {
    min-width: 100px;
    height: 20px;
    float: left;
    background-color: #DFDFDF;    
  }   
  .tournament .l2 {
    background-color: #D0D0D0;
  }     
  .tournament .lmax {
    width: 0px;
    clear: both;
  }    
  </style>
  <script type="text/javascript">
  
    var matchInfo = {
      "rounds" : [
        { "name": "Round1",
          "matches" : [
            { "id" : 1, "p1" : "mTwDeMuslim", "p2" : "Luffy" },
            { "id" : 2, "p1" : "SeleCT", "p2" : "NEXGenius" },
            { "id" : 3, "p1" : "Fenix", "p2" : "SoftBall" },
            { "id" : 4, "p1" : "White-Ra", "p2" : "Ice" },
            { "id" : 5, "p1" : "HuK", "p2" : "RedArchon" },
            { "id" : 6, "p1" : "Capoch", "p2" : "Loner" },
            { "id" : 7, "p1" : "mTwDIMAGA", "p2" : "MakaPrime" },
            { "id" : 8, "p1" : "TLAF-Liquid`TLO", "p2" : "SEN" }
          ]
        },
        { "name": "Round2",
          "matches" : [
            { "id" : 9, "p1" : null, "p2" : null },
            { "id" : 10, "p1" : null, "p2" : null },
            { "id" : 11, "p1" : null, "p2" : null },
            { "id" : 12, "p1" : null, "p2" : null }
          ]
        },
        { "name": "Round3",
          "matches" : [
            { "id" : 13, "p1" : null, "p2" : null },
            { "id" : 14, "p1" : null, "p2" : null },
          ]
        },
        { "name": "Round4",
          "matches" : [
            { "id" : 15, "p1" : null, "p2" : null },
          ]
        }                
      ]
    };
  
    $(document).ready(function($) {       
      var base = $('#writeHere');
      var numTeams = 16;
      var matchesByRound = setupMatchboxes(numTeams);
      var matchDivsByRound = [];
      
      for (var lvl=0; lvl<matchesByRound.length; lvl++) {                
        var matchBoxes = matchesByRound[lvl];        
        var bracket = checkedAppend('<div class="bracket"></div>', base);
        var matchDivs = [];
        matchDivsByRound.push(matchDivs);
        
        for (var i=0; i<matchBoxes.length; i++) {                     
          var vOffset = checkedAppend('<div></div>', bracket);
        
          var match = matchInfo.rounds[lvl].matches[i];
          var matchHtml = '<div class="match" id="match' + match.id + '">'
            + '<div class="p1">' + fmtName(match.p1) + '</div>'
            + '<div class="spacer"></div>'
            + '<div class="p2">' + fmtName(match.p2) + '</div>';
          matchDiv = checkedAppend(matchHtml, bracket);
          matchDivs.push(matchDiv);
          
          if (lvl > 0) {
            //row 2+; line up with previous row
            var alignTo = matchDivsByRound[lvl-1][i*2];
            //offset to line up tops
            var desiredOffset = alignTo.position().top - matchDiv.position().top;
            
            //offset by half the previous match-height
            desiredOffset += alignTo.height() / 2;
            vOffset.height(desiredOffset);            
          } else {
            checkedAppend('<div class="small-spacer"></div>', bracket);
          }
          
          if (lvl > 0) {
            //tweak our size so we stretch to the middle of the appropriate element
            var stretchTo = matchDivsByRound[lvl-1][i*2+1];
            var newH = stretchTo.position().top + stretchTo.height()/2 - matchDiv.position().top;            
            var deltaH = newH - matchDiv.height();
            matchDiv.height(newH);
            var spacer = matchDiv.find('.spacer');
            spacer.height(spacer.height() + deltaH);
          }          
        }
      }      
    });
    
    function fmtName(name) {
      return null != name ? name : '?';
    }
    
    function setupMatchboxes(numTeams) {
      var numLevels = Math.log(numTeams)/Math.LN2;
      var numMatchesForLevel = numTeams / 2;
      var matchBoxes = [];
      
      do {
        var matchesForLevel = [];        
        matchBoxes.push(matchesForLevel);
        
        for (var match=0; match<numMatchesForLevel; match++) {
          matchesForLevel.push(match);
        }
        
        numMatchesForLevel = numMatchesForLevel / 2;
      } while(numMatchesForLevel >= 1);
      return matchBoxes;
    }
    
    function checkedAppend(rawHtml, appendTo) {
      var html = $(rawHtml);
      if (0 == html.length) {
        throw "Built ourselves bad html : " + rawHtml;
      }
      html.appendTo(appendTo);      
      return html;
    }
  </script>
</head>
<body>
  <div>blah blah blah</div>
  <div id="writeHere" class="tournament"></div>
  <div>blah blah blah</div>
</body>
</html>
On nice modern browsers this yields something like this:

Last of all lets clean up our javascript slightly, in particular making our code a little more directly based on the JSON and a little less on hard-coded test variables like numTeams. And lets add a spot for the final victor:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us">
<head>
  <title>MyTournamentName</title>
 <script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js' type='text/javascript'>
 </script>
 <script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js' type='text/javascript'>
 </script>  
  <style type="text/css">
  .tournament {    
    background-color: #F0F0F0;
    border: dashed 1px solid;
    overflow: auto;
  }
  .tournament .bracket {
    background-color: #DFDFDF;
    min-width: 100px;    
    vertical-align: top;
    float: left;
  }
  
  .tournament .bracket .match {
    background-color: #D0D0D0;
    border-top: 1px solid;
    border-right: 1px solid;
    border-bottom: 1px solid;  
  }
  .tournament .bracket .match .p1 {    
    height: 20px;
  }
  .tournament .bracket .match .p2 {
    height: 20px;
  }    
  .tournament .bracket .match .spacer {
    background-color: #DFDFDF;
    height: 38px;
  }
  .tournament .bracket .spacer {
    height: 80px;
  }
  .tournament .bracket .half-spacer {
    height: 40px;
  }
  .tournament .bracket .small-spacer {
    height: 10px;
    background-color: #F1F1F1;
  }
  .tournament .bracket .winner {
    border-bottom: 1px solid;
  }
  
  .left-line {
    border-left: 1px solid;
  }
  
  .tournament .cell {
    min-width: 100px;
    height: 20px;
    float: left;
    background-color: #DFDFDF;    
  }   
  .tournament .l2 {
    background-color: #D0D0D0;
  }     
  .tournament .lmax {
    width: 0px;
    clear: both;
  }    
  </style>
  <script type="text/javascript">
  
    var matchInfo = {
      "rounds" : [
        { "name": "Round1",
          "matches" : [
            { "id" : 1, "p1" : "mTwDeMuslim", "p2" : "Luffy" },
            { "id" : 2, "p1" : "SeleCT", "p2" : "NEXGenius" },
            { "id" : 3, "p1" : "Fenix", "p2" : "SoftBall" },
            { "id" : 4, "p1" : "White-Ra", "p2" : "Ice" },
            { "id" : 5, "p1" : "HuK", "p2" : "RedArchon" },
            { "id" : 6, "p1" : "Capoch", "p2" : "Loner" },
            { "id" : 7, "p1" : "mTwDIMAGA", "p2" : "MakaPrime" },
            { "id" : 8, "p1" : "TLAF-Liquid`TLO", "p2" : "SEN" }
          ]
        },
        { "name": "Round2",
          "matches" : [
            { "id" : 9, "p1" : null, "p2" : null },
            { "id" : 10, "p1" : null, "p2" : null },
            { "id" : 11, "p1" : null, "p2" : null },
            { "id" : 12, "p1" : null, "p2" : null }
          ]
        },
        { "name": "Round3",
          "matches" : [
            { "id" : 13, "p1" : null, "p2" : null },
            { "id" : 14, "p1" : null, "p2" : null },
          ]
        },
        { "name": "Round4",
          "matches" : [
            { "id" : 15, "p1" : null, "p2" : null },
          ]
        } 
      ]
    };
  
    $(document).ready(function($) {       
      var base = $('#writeHere');
      var matchDivsByRound = [];
      
      for (var roundIndex=0; roundIndex<matchInfo.rounds.length; roundIndex++) {    
        var round = matchInfo.rounds[roundIndex];
        var bracket = checkedAppend('<div class="bracket"></div>', base);
        var matchDivs = [];
        matchDivsByRound.push(matchDivs);
        
        //setup the match boxes round by round
        for (var i=0; i<round.matches.length; i++) {                     
          var vOffset = checkedAppend('<div></div>', bracket);
        
          var match = round.matches[i];
          var matchHtml = '<div class="match" id="match' + match.id + '">'
            + '<div class="p1">' + fmtName(match.p1) + '</div>'
            + '<div class="spacer"></div>'
            + '<div class="p2">' + fmtName(match.p2) + '</div>';
          matchDiv = checkedAppend(matchHtml, bracket);
          matchDivs.push(matchDiv);
          
          if (roundIndex > 0) {
            //row 2+; line up with previous row
            var alignTo = matchDivsByRound[roundIndex-1][i*2];
            //offset to line up tops
            var desiredOffset = alignTo.position().top - matchDiv.position().top;
            
            //offset by half the previous match-height
            desiredOffset += alignTo.height() / 2;
            vOffset.height(desiredOffset);            
          } else {
            checkedAppend('<div class="small-spacer"></div>', bracket);
          }
          
          if (roundIndex > 0) {
            //tweak our size so we stretch to the middle of the appropriate element
            var stretchTo = matchDivsByRound[roundIndex-1][i*2+1];
            var newH = stretchTo.position().top + stretchTo.height()/2 - matchDiv.position().top;            
            var deltaH = newH - matchDiv.height();
            matchDiv.height(newH);
            var spacer = matchDiv.find('.spacer');
            spacer.height(spacer.height() + deltaH);
          }          
        }                
      }
      //setup the final winners box; just a space for a name whose bottom is centrally aligned with the last match
      bracket = checkedAppend('<div class="bracket"></div>', base);
      var vOffset = checkedAppend('<div></div>', bracket);
      var alignTo = matchDivsByRound[matchInfo.rounds.length - 1][0]; //only 1 match in the last round
      var html = '<div class="winner">?</div>';
      var winnerDiv = checkedAppend(html, bracket);      
      vOffset.height(alignTo.position().top - winnerDiv.position().top + alignTo.height() / 2 - winnerDiv.height());
    });
    
    function fmtName(name) {
      return null != name ? name : '?';
    }
    
    function checkedAppend(rawHtml, appendTo) {
      var html = $(rawHtml);
      if (0 == html.length) {
        throw "Built ourselves bad html : " + rawHtml;
      }
      html.appendTo(appendTo);      
      return html;
    }
  </script>
</head>
<body>
  <div>blah blah blah</div>
  <div id="writeHere" class="tournament"></div>
  <div>blah blah blah</div>
</body>
</html>

Ugly, but sized and positioned the way we want, ready to actually talk to a server and/or get some dynamic elements (eg the ability to designate a winner and have them promote through the tournament).

Ultimately this will hopefully get rolled up into a practicum project involving tournament management.

523 comments:

«Oldest   ‹Older   401 – 523 of 523
kalyani said...

Through this post, I know that your good knowledge in playing with all the pieces was very helpful. I notify that this is the first place where I find issues I've been searching for. You have a clever yet attractive way of writing on Msbi online training
Msbi online training Hyderabad
Msbi online training India
Msbi online course
Msbi course
Msbi training
Msbi certification training

anand said...

nice post
Software Testing Training in Chennai | Certification | Online
Courses



Software Testing Training in Chennai

Software Testing Online Training in Chennai

Software Testing Courses in Chennai

Software Testing Training in Bangalore

Software Testing Training in Hyderabad

Software Testing Training in Coimbatore

Software Testing Training

Software Testing Online Training

Sonu Kabir said...


Thanks for sharing information awesome blog post Online Education Quiz website Gk in Hindi

ramesh said...


I am really enjoyed a lot when reading your well-written posts. It shows like you spend more effort and time to write this blog. I have saved it for my future reference. Keep it up the good work

Azure Training in Chennai

Azure Training in Bangalore

Azure Training in Hyderabad

Azure Training in Pune

Azure Training | microsoft azure certification | Azure Online Training Course

Azure Online Training

un known said...

Thanks for sharing this information. I really Like Very Much.
angular js online training

aravind said...

This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.Really you have done great job,There are may person searching about that now they will find enough resources by your post.
DevOps Training in Chennai

DevOps Online Training in Chennai

DevOps Training in Bangalore

DevOps Training in Hyderabad

DevOps Training in Coimbatore

DevOps Training

DevOps Online Training

Radley Co Tad said...

Great Article
Cloud Computing Projects


Networking Projects

Final Year Projects for CSE


JavaScript Training in Chennai

JavaScript Training in Chennai

The Angular Training covers a wide range of topics including Components, Angular Directives, Angular Services, Pipes, security fundamentals, Routing, and Angular programmability. The new Angular TRaining will lay the foundation you need to specialise in Single Page Application developer. Angular Training

dhinesh said...

Great site and a great topic as well I really get amazed to read this.This is incredible,I feel really happy to have seen your webpage.I gained many unknown information, the way you have clearly explained is really fantastic.keep posting such useful information.
Full Stack Training in Chennai | Certification | Online Training Course
Full Stack Training in Bangalore | Certification | Online Training Course

Full Stack Training in Hyderabad | Certification | Online Training Course
Full Stack Developer Training in Chennai | Mean Stack Developer Training in Chennai
Full Stack Training

Full Stack Online Training




Rashika said...

Nice article I was really impressed by seeing this blog, it was very interesting and it is very useful for me.

Digital Marketing Training in Chennai

Digital Marketing Course in Chennai

SEO Training in Chennai

Digital Marketing Training in Bangalore

Digital Marketing Training in Hyderabad

Digital Marketing Training in Coimbatore

Digital Marketing Training

Digital Marketing Course

Digital Marketing Online Training

devi said...

Excellent Blog! I would Thanks for sharing this wonderful content.its very useful to us.This is incredible,I feel really happy to have seen your webpage.I gained many unknown information, the way you have clearly explained is really fantastic.
Data Science Training In Chennai

Data Science Online Training In Chennai

Data Science Training In Bangalore

Data Science Training In Hyderabad

Data Science Training In Coimbatore

Data Science Training

Data Science Online Training

swaroop said...

This is a very useful blog.we are knowing a great content and also lots of information.

Web Designing Training in Chennai

Web Designing Course in Chennai

Web Designing Training in Bangalore

Web Designing Course in Bangalore

Web Designing Training in Hyderabad

Web Designing Course in Hyderabad

Web Designing Training in Coimbatore

Web Designing Training

Web Designing Online Training

Revathi said...

I feel really happy to have seen your webpage.I am feeling grateful to read this.you gave a nice information for us.please updating more stuff content...keep up!!

Android Training in Chennai

Android Online Training in Chennai

Android Training in Bangalore

Android Training in Hyderabad

Android Training in Coimbatore

Android Training

Android Online Training

Anonymous said...

python training in bangalore | python online Training
artificial intelligence training in bangalore | artificial intelligence online training
machine learning training in bangalore | machine learning online training
uipath-training-in-bangalore | uipath online training
blockchain training in bangalore | blockchain online training

prabhu said...

very nice blogs!!! i have to learning for lot of information for this sites...Sharing for wonderful information.Thanks for sharing this valuable information to our vision. You have posted a trust worthy blog keep sharing.
IELTS Coaching in chennai

German Classes in Chennai

GRE Coaching Classes in Chennai

TOEFL Coaching in Chennai

spoken english classes in chennai | Communication training


Anonymous said...

python training in bangalore | python online Training
artificial intelligence training in bangalore | artificial intelligence online training
machine learning training in bangalore | machine learning online training
uipath-training-in-bangalore | uipath online training
blockchain training in bangalore | blockchain online training
aws training in Bangalore | aws online training
data science training in bangalore | data science online training

vivekvedha said...

thanks for sharing such a nice info.I hope you will share more information like this. please keep on sharing!
acte reviews

acte velachery reviews

acte tambaram reviews

acte anna nagar reviews

acte porur reviews

acte omr reviews

acte chennai reviews

acte student reviews

radhika said...

Thank you for taking the time and sharing this information with us. It was indeed very helpful and insightful while being straight forward and to the point...

AWS Course in Bangalore

AWS Course in Hyderabad

AWS Course in Coimbatore

AWS Course

AWS Certification Course

AWS Certification Training

AWS Online Training

AWS Training


Anonymous said...

python training in bangalore | python online Training
artificial intelligence training in bangalore | artificial intelligence online training
machine learning training in bangalore | machine learning online training
uipath-training-in-bangalore | uipath online training
blockchain training in bangalore | blockchain online training
aws training in Bangalore | aws online training
data science training in bangalore | data science online training

Best laptops Under 30000 said...

Best 2 3 4 burner gas stove in india
laptops under 30000 with i7 processor
best-foldable-keyboards

svrtechnologies said...


That is nice article from you , this is informative stuff . Hope more articles from you . I also want to share some information about devops training in pune

Latest School News Nigeria Portal said...

Hi Thank you for sharing this wonderful article. Do well to visit Latest School News to apply for Jamb Registration Form. You can always check your Jamb Result and Neco Result Checker here.
Do well to check your Admission Status using Jamb Caps.

Anonymous said...

hadoop training in bangalore | hadoop online training
iot training in bangalore | iot online training
devops training in banaglore | devops online training

BTree Systems, Software (IT) Training Institute said...

btreesystems

sindhuja cynixit said...

Thank you for sharing the valuable information.
pega robotic process automation training
pega robotic process automation course
learn pega rpa
pega rpa course
pega rpa training
pega rpa

sindhuja cynixit said...

Thank you for the sharing the valuable information.
pega cssa certification course
pega cssa certification online course
pega cssa certification online training
pega cssa certification training
pega cssa online training
pega csa training
learn pega cssa
pega cssa course

Python said...

Thanks for Sharing.
Data Science Online Training

un known said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
devops online training
best devops online training
top devops online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Unknown said...

I just loved your article on the beginners guide to starting a blog.If somebody take this blog article seriously in their life, he/she can earn his living by doing blogging.thank you for thizs article. python online training , best python online training ,
top python online training

Vijayakash said...

"Valuable one...thanks for sharing..
digital marketing interview questions and answers
interview questions on digital marketing
java interview questions for experienced
selenium interview questions and answers for experienced
hadoop interview questions and answers for experienced
oracle dba interview questions
data scientist interview questions and answers pdf

Vijayakash said...

This is good site and nice point of view.I learnt lots of useful information.
hadoop interview questions and answers
hadoop interview questions and answers for experienced
java interview questions for experienced
selenium interview questions and answers for experienced
digital marketing interview questions and answers pdf
oracle pl sql interview questions
data scientist interview questions and answers
python interview questions and answers for experienced

Anurag Mohapatra said...

Very nice blog about json
Best python training in Bangalore BTM

Anurag Mohapatra said...

Very nice blog about json
Best python training in Bangalore

Python said...

Thanks for Sharing.
python Online Training

Python said...

Very useful information, the post shared was very nice.
python Online Training

Unknown said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
devops online training
best devops online training
top devops online training

Digital Marketing said...

Best Training institute for AWS http://www.greenstechnologys.com/AWS-training-chennai.html

Python said...

Thanks for Sharing.
python Online Training

Python said...

Very good content.Thanks for sharing
Data Science Online Training

Python said...

Very good content.Thanks for sharing
Data Science Online Training

Watson Hs said...

Thanks for the marvelous posting! I genuinely enjooyed reading it, I want to
encourage that you continue your great writing, have a nice day!

UI Development Training in Bangalore
Python Training in Bangalore
AWS Training in Bangalore
Machine Learning With R Training in Bangalore
Machine Learning with Python Training in Bangalore
Hadoop Training in Bangalore

shakunthala said...

thanks for sharing this post with us.
keep sharing.
best training institute in bangalore
best software training institutes in bangalore

Vijayakash said...

"Valuable one...thanks for sharing..
pega developer interview questions
pega interview questions for freshers
java interview questions and answers for freshers
selenium automation framework interview questions and answers
digital marketing interview questions and answers pdf
hadoop testing interview questions and answers for experienced
oracle pl sql interview questions
devops interview questions and answers pdf

Unknown said...

https://zulqarnainbharwana.com/barnsley-f-c/

un known said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
devops online training
best angularjs online training
top angularjs online training

Unknown said...

https://zulqarnainbharwana.com/los-angeles-lakers/

Unknown said...

https://zulqarnainbharwana.com/los-angeles-lakers/

Tohindi said...

imageji

Tohindi said...

imageji

un known said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
devops online training
best devops online training
top devops online training

un known said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
angular js online training
best angular js online training
top angular js online training

ICSS Bangalore said...

Nice Blog. Check this python classroom training in bangalore

Mahawar Alloys said...

Digital Marketing Course in Patiala
Web designing course in Patiala
Graphic designing course in Patiala
Seo course in Patiala
App development course in Patiala
Social media marketing course in Patiala
Web development course in Patiala
Ppc course in Patiala
Computer centre in patiala

Mahawar Alloys said...

Digital Marketing Course in Patiala
Web designing course in Patiala
Graphic designing course in Patiala
Seo course in Patiala
App development course in Patiala
Social media marketing course in Patiala
Web development course in Patiala
Ppc course in Patiala
Computer centre in patiala

Deepak kumar said...

हेलो सर मुझे आपका पोस्ट काफी अच्छा लगा आपने इस पोस्ट के माध्यम से बहुत अच्छी जानकारियां दी हैं मैं आशा करता हूं कि आप और भी जानकारियां लेटेस्ट लेटेस्ट अपने वेबसाइट पर पोस्ट करेंगे
Deepak yadav

Watson Hs said...

Thanks! For sharing your views regarding this topic. I really enjoyed your post.
Hadoop Training in Bangalore
Python Training in Bangalore
AWS Training in Bangalore
UI Development training in Bangalore
Machine Learning Training in Bangalore
Machine Learning Training with Python in Bangalore

Python said...

Very good content.Thanks for sharing
Data Science Online Training
Python Online Training

ghochu singh said...

Andhaghaaram full movie download hindi dubbed
sarileru neekevvaru full movie
Download Bheesma full movie in hindi
Download Malang (2020) Hindi Movie
Psycho tamil movie Download
Ala Vaikunthapurramuloo movie

Free fire Diamond said...

Modern Combat 5 mod apk latest
Nova legacy mod apk latest

Free fire Diamond said...

Modern Combat 5 mod apk latest
Nova legacy mod apk latest

Fresh Talk said...

camscanner app
meitu app
shein app
youku app
sd movies point
uwatchfree

un known said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
devops online training
best devops online training
top devops online training

Free fire Diamond said...

soul knight mod apk

my talking angela mod apk

nova legacy mod apk

modern combat 5 mod apk
shadow fight 3 mod apk

ICSS Bangalore said...

Nice post. Check this machine learning training in bangalore

dhankesariresults.in said...

Dhankesari lottery sambad result conjointly called Nagaland state lottery lately. Click on the link on top of have to be compelled to nowadays eight PM Dhankesari lottery result on-line. Nagaland lately lottery result pdf file on-line. you’ll check nagaland state lottery morning here Dhankesari Today Result on-line.

Python said...

Thanks for sharing all the information with us all.
Data Science Online Training
Python Online Training

Python said...

Thanks for sharing an information to us.
Data Science Online Training
Python Online Training

suresh said...

Really useful information. Thank you so much for sharing.It will help everyone.Keep Post.
DevOps Training in Chennai

DevOps Course in Chennai

richard bryan said...

great java tips At SynergisticIT we offer the best aws training

SUTAPA said...

affair|after marriage|অ্যারেঞ্জ ম্যারেজ
Love Story|Sad Love Story
অদ্ভুত ভালোবাসা | single mother
working woman|অসম্পর্ণ
অসম্পর্ণ ভালোবাসা | ভালোবাসা | affair

Gift Cards 2021 said...

outstanding article written thanks Gift Cards 2021

jhansi said...

SAP stands for Systems Applications and Products in Data Processing. SAP, by definition, is also the name of the ERP (Enterprise Resource Planning) software as well as the name of the company.
tally training in chennai

hadoop training in chennai

sap training in chennai

oracle training in chennai

angular js training in chennai

Python said...

Thank you for sharing.
Data Science Online Training
Python Online Training
Salesforce Online Training

Anurag Mohapatra said...

Python training in bangalore
Machine learning course in bangalore
Data Science Online Course in Bangalore

Learn Storage Automation (Using Python) in Bangalore BTM
Cloud Computing Training in Bangalore BTM

Anurag Mohapatra said...

Python training in bangalore
Machine learning course in bangalore
Data Science Online Course in Bangalore

Learn Storage Automation (Using Python) in Bangalore BTM
Cloud Computing Training in Bangalore BTM

shakunthala said...

thanks for sharing this information with us
job guaranteed courses in bangalore

full stack developer course

Prashant Baghel said...

Thank you for writing can I say something for those people who are looking for one of the best website to find details about latest update
Mobile And Computer Par Gmail Se Message Kaise Bhejte Hai

Afsana said...


Thanks for sharing your views about the concept which you know much better. Its easy to read and understand by the way you wrote the blog contents.

data science training in chennai
python institute in chennai
machine learning training in chennai

Python said...

Thank you for sharing.
Data Science Online Training
Python Online Training
Salesforce Online Training

savas said...

I think this is among the most vital information for me. And i am glad reading your article.
Thanks!
visit my sites Please.

1) http://wildflowersea.co.kr/bbs/board.php?bo_table=0602&wr_id=344874
2) http://xn--6j1bj2g886a.com/www/bbs/board.php?bo_table=free&wr_id=4795
3) http://teraene.com/bbs/board.php?bo_table=0601&wr_id=52149
4) http://www.freeinfo.co.kr/bbs/board.php?bo_table=freeboard&wr_id=63055
5) http://www.powerline-g.com/bbs/board.php?bo_table=customer&wr_id=560153&page=0&sca=&sfl=&stx=&sst=&sod=&spt=0&page=0

Gurjeet Singh said...

Wonderful blog, Get the best Pay Per Click Services by Web Solution Centre in Delhi, India.
Best Website Designing Company West Delhi

Mahnoor tech said...

Wow. This is amazing site for me. Good work on this webpage. Here is a detailed article on Earn money from youtube. Thanks.

Mahnoor tech said...

Thanks for Sharing such an amazing article. Keep working. Here is a detailed article on Earn money on fiverr . Thankyou.

shakunthala said...

thanks for sharing this blog with us .
keep sharing .
job guaranteed courses in bangalore

shakunthala said...

mlcmv

Content Writing Services In Delhi said...

Boost engagement and generate leads with our high-quality Content Writing Services In Delhi! iWrite India uses fresh, SEO-friendly language to present your ideas to the world! Content Writing Services In India | Content Writing Agency

Jegadish kumar said...

Had read complete blog which was helpful for me career and i also check my blog if anyone interested on the books.

Top 10 phenomenal books to read before marriage 2021

Jegadish kumar said...

https://searchjegadishbooks.blogspot.com/2021/01/top-10-phenomenal-books-to-read-before_18.html

Jegadish kumar said...

Has I visited besent 3 Months ago I have learned digital Marketing Now Iam The best Blogger Thank you For The Best Training
Top 10 phenomenal books to read before marriage 2021

Jegadish kumar said...

Top10phenomenalbookstoreadbeforemarriage2021

Admim DS said...

The Best Result Driven Digital Marketing
Agency in Chennai https://techsv.in/

un known said...

Thanks for Sharing This Article.It is very so much valuable content. I hope these Commenting lists will help to my website
devops online training
best devops online training
top devops online training

Python said...

Thanks for this wonderful post.
Data Science Online Training
Python Online Training
Salesforce Online Training

Durco Pump Parts said...

Real Goulds Pump Parts are obligatory to guarantee your pumps remain performing at top performance as well as maintain their service warranty standing. Goulds and also Durco Pump Parts have been particularly designed for your pump version. All Goulds Pump Parts as well as A-C Pump components have been made to the strictest requirements in an ISO accredited facility. Gorman Rupp Pump Parts

KashiMART said...

Great read I must say. You have beautifully portrayed your thoughts and ideas through this article. Great insight on the topic and value addition. Keep posting more articles like this!
kashimart

KashiMART said...

Great read I must say. You have beautifully portrayed your thoughts and ideas through this article. Great insight on the topic and value addition. Keep posting more articles like this!
kashimart

KashiMART said...

Great read I must say. You have beautifully portrayed your thoughts and ideas through this article. Great insight on the topic and value addition. Keep posting more articles like this!
kashimart

Arefa Akter said...

Whatsapp Number Call us Now! 01537587949
please visit us: Graphic Design Training
sex video: Dropped phone repair Erie
pone video usa: mobile phone repair in West Des Moines
pone video usa: Social Bookmarking Sites List 2021

Best Training Institute said...

Nice Blog. We are making the Best Software training in bangalore.
J2ee training in bangalore
learn J2ee in bangalore

shakunthala said...

thanks for sharing this blog with us
job guaranteed courses in bangalore
full stack developer course

Jyothi Matha said...

i really liked your blog it was so informative. i recently started writing blogs please do visit my website cibus point

Ruger LCP Laser said...

Ruger LCP 2 : Seeking one of the most efficient Ruger LC9S Accessories? Ruger Laser, the leader in Ruger LCP Laser at Affordable Cost. All the Devices provided by us are taken a look at as well as likewise inspected by our extremely enlightened experts so pertaining to guarantee you with secure along with safe and likewise safe and also protected driving. Ruger LCP

shakunthala said...

thanks for sharing blog with us
job guaranteed courses in bangalore
full stack developer course

Daniel said...

Very useful content. I will have look completely later on.

View my blog: Java training center in chennai

Kevinlincy said...
This comment has been removed by the author.
Kevinlincy said...
This comment has been removed by the author.
Linkfeeder said...

The content on your blog was really helpful and informative. Thakyou. # BOOST Your GOOGLE RANKING.It’s Your Time To Be On #1st Page
Our Motive is not just to create links but to get them indexed as will
Increase Domain Authority (DA).We’re on a mission to increase DA PA of your domain
High Quality Backlink Building Service
1000 Backlink at cheapest
50 High Quality Backlinks for just 50 INR
2000 Backlink at cheapest
5000 Backlink at cheapest

Best Glock Accessories - Glock Laser said...

The Glock 19 Laser is an incredibly popular 9mm hand gun that is excellent for self-defense or competitive shooting. While the Glock 19 is heavier than various other pistols on this list, it is still light adequate to manage easily at 21.5 ounces without the magazine. Glock 43 Laser With a total length of 7.28 inches and also barrel length of 4.02 inches, the Glock 19 is little sufficient to bring hidden, yet huge sufficient to fire properly. Glock Light | Weapon Lights

lkrasilnikovaludmila1976 said...

Thankyou for the wonderful content and knowledge. It was really Helpful. # BOOST Your GOOGLE RANKING.It’s Your Time To Be On #1st Page
Our Motive is not just to create links but to get them indexed as will
Increase Domain Authority (DA).We’re on a mission to increase DA PA of your domain
High Quality Backlink Building Service
1000 Backlink at cheapest
50 High Quality Backlinks for just 50 INR
2000 Backlink at cheapest
5000 Backlink at cheapest

Python said...

Keep sharing this kind of post.
Python Online Training

MOHD KAIF said...

I want you to thank for your time of this wonderful read!!!
I definately enjoy every little bit of it and I have you bookmarked to check out new stuff of your blog a must read blog!
you can visite my website.

सराजस्थान भामाशाह कार्ड योजना

MOHD KAIF said...

Very nicely done. Your show schedule gave me the info on some shows I was wondering about.
I visited your web site today and found it very interesting and well done.
I can tell you have put a lot of work into it.
Thank you for the listing on your web page.
You have a good looking web site Your site is exactly what I have looking for!! Keep up with the good work.

Applcation Mod

MOHD KAIF said...

Thanks a lot for sharing this good blog post.. i hope keep more post for sharing thanks.
I have found this source very genuine and very worthy to complete my assignments.
Thanks a lot for the same. my website as it you can visite it.

Govt.Schemes

MOHD KAIF said...

want you to thank for your time of this wonderful read!!!
I definately enjoy every little bit of it and I have you bookmarked to check out new stuff of your blog a must read blog!
you can visite my website.

सराजस्थान भामाशाह कार्ड योजना

MOHD KAIF said...

Very nicely done. Your show schedule gave me the info on some shows I was wondering about.
I visited your web site today and found it very interesting and well done.
I can tell you have put a lot of work into it.
Thank you for the listing on your web page.
You have a good looking web site Your site is exactly what I have looking for!! Keep up with the good work.

Applcation Mod

MOHD KAIF said...

Thanks a lot for sharing this good blog post.. i hope keep more post for sharing thanks.
I have found this source very genuine and very worthy to complete my assignments.
Thanks a lot for the same. my website as it you can visite it.

Govt.Schemes

Digital Marketing Service said...

Nice Post. You are Share great post and keep posting.
Weight Loss Doctor in Meerut
Diabetes Management in Meerut
Software Development Company in Delhi
SEO Services in Hapur
Top 10 CBSC Schools in Meerut
Digital Marketing Services in Noida
SEO Company in Meerut
Top Automotive battery seller in Meerut

Unknown said...

I will have a look on the complete blog later on. Which is useful for me and i bookmarked it. Keep post more blog. Football blog

«Oldest ‹Older   401 – 523 of 523   Newer› Newest»

Post a Comment