Bracket prototyping

by goranobradovic

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-debug.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<br/>
<div class='container-fluid clearfix'>
  <div class='table table-bordered' data-bind="with:parameters">
    <fieldset class='parameters'>
      <legend>
        Bracket parameters
      </legend>
      <label for="numberOfParticipants">Number of participants</label>
      <select id="numberOfParticipants" data-bind="options: availableNumberOfParticipants,
                         value: numberOfParticipants">
      </select>
    </fieldset>
  </div>
  <div class='table table-bordered' data-bind="with:bracket">
    <fieldset>
      <legend>
        Bracket output
      </legend>
      <table class='table table-bordered'>
        <tbody data-bind="foreach:matches">
          <tr data-bind="foreach:$data">
            <td data-bind="attr:{colspan:width}" class="text-center">
              <span data-bind="text:name"></span>
            </td>
          </tr>
        </tbody>
      </table>
    </fieldset>
  </div>
</div>

JavaScript

Parameters = function() {
  var self = this;
  self.numberOfParticipants = ko.observable(0);
  var optionsForDropdown = Array.apply(null, {
    length: 64
  }).map(Number.call, Number);
  self.availableNumberOfParticipants = ko.observableArray(optionsForDropdown);
};

Match = function(name, width) {
  var self = this;
  self.left = null;
  self.right = null;
  self.name = name;
  self.width = width;
};

Bracket = function() {
  var self = this;
  self.numberOfParticipants = ko.observable();

  self.matches = ko.computed(function() {
    var n = self.numberOfParticipants();
    var bracketDepth = Math.ceil(Math.log2(n));
    var bracketWidth = Math.ceil(n / 2);
    var matchNumber = Math.pow(2, bracketDepth) - 1;
    var matches = [];
    for (i = 0; i < bracketDepth; i++) {
      var row = [];
      for (j = 0; j < Math.pow(2, i); j++) {
        row.push(new Match("Match: " + matchNumber--, Math.pow(2, bracketDepth - i)));
      }
      matches.push(row);
    }
    return matches;
  });
};

var Model = function() {
  var self = this;
  self.parameters = new Parameters();
  self.bracket = new Bracket();
  self.parameters.numberOfParticipants.subscribe(function(value) {
    self.bracket.numberOfParticipants(value);
  });
}

ko.applyBindings(Model);