<commit_before>'use strict';

/**
 * @ngdoc function
 * @name groongaAdminApp.controller:TableSearchController
 * @description
 * # TableSearchController
 * Controller of the groongaAdminApp
 */
angular.module('groongaAdminApp')
  .controller('TableSearchController', function ($scope, $routeParams, $location, $http) {
    var client = new GroongaClient($http);

    function computeCurrentPage(offset) {
      return Math.ceil((parseInt(offset) + 1) / $scope.nRecordsInPage);
    }

    function initialize() {
      $scope.table = $routeParams.table;
      $scope.style = 'table';
      $scope.response = {
        rawData: [],
        columns: [],
        records: [],
        drilldowns: [],
        elapsedTimeInMilliseconds: 0,
        nTotalRecords: 0
      };
      $scope.indexedColumns = [];
      $scope.allColumns = [];
      $scope.commandLine = '';
      $scope.message = '';
      $scope.currentPage = 1;
      $scope.nRecordsInPage = 10;
      $scope.maxNPages = 10;
      $scope.parameters = angular.copy($location.search());

      $scope.search = search;
      $scope.clear  = clear;
      $scope.toggleSort = toggleSort;
      $scope.selectDrilldown = selectDrilldown;
    }

    function packColumns(columns, filterFunction) {
      var targetColumnNames = columns
          .filter(filterFunction)
          .map(function(column) {
            return column.name;
          });
      return targetColumnNames.join(',');
    }

    function search() {
      var parameters = angular.copy($scope.parameters);
      parameters.match_columns =
        packColumns($scope.indexedColumns, function(column) {
          return column.inUse;
        });
      parameters.output_columns =
        packInUseColumns($scope.allColumns, function(column) {
          return column.inUse;
        });
      parameters.offset = ($scope.currentPage - 1) * $scope.nRecordsInPage;
      parameters.limit = $scope.nRecordsInPage;
      var sortKeys = $scope.columns.filter(function(column) {
        return column.sort;
      }).map(function(column) {
        if (column.sort === 'ascending') {
          return column.name;
        } else {
          return '-' + column.name;
        }
      }).join(',');
      parameters.sortby = sortKeys;
      $location.search(parameters);
    }

    function clear() {
      $location.search({});
    }

    function setColumnSort(column, sort) {
      column.sort = sort;
      switch (column.sort) {
      case 'ascending':
        column.iconClass = 'glyphicon-sort-by-attributes';
        break;
      case 'descending':
        column.iconClass = 'glyphicon-sort-by-attributes-alt';
        break;
      default:
        column.iconClass = 'glyphicon-sort';
        break;
      }
    }

    function toggleSort(column) {
      var sort;
      switch (column.sort) {
      case 'ascending':
        sort = 'descending';
        break;
      case 'descending':
        sort = null;
        break;
      default:
        sort = 'ascending';
        break;
      }
      setColumnSort(column, sort);
      search();
    }

    function selectDrilldown(key, value) {
      var query = $scope.parameters.query || '';
      if (query.length > 0) {
        query += ' ';
      }
      $scope.parameters.query = query + key + ':' + value;

      var drilldowns = ($scope.parameters.drilldown || '').split(/\s*,\s*/);
      drilldowns = drilldowns.filter(function(drilldown) {
        return drilldown !== key;
      });
      $scope.parameters.drilldown = drilldowns.join(',');

      search();
    }

    function createColumnInfo(name) {
      var outputColumns = $scope.parameters.output_columns;
      var inUse = true;
      if (outputColumns) {
        inUse = outputColumns.indexOf(name) !== -1;
      }
      var drilldown = false;
      return {
        name: name,
        inUse: inUse,
        drilldown: drilldown
      };
    }

    function extractColumnsInfo(table, columns) {
      if (table.name === $scope.table) {
        columns.forEach(function(column) {
          if (column.isIndex) {
            return;
          }
          $scope.allColumns.push(createColumnInfo(column.name));
        });
      }

      columns.forEach(function(column) {
        if (!column.isIndex) {
          return;
        }
        if (column.range !== $scope.table) {
          return;
        }
        var matchColumns = $scope.parameters.match_columns;
        column.sources.forEach(function(source) {
          var localName;
          if (source.indexOf('.') === -1) {
            localName = '_key';
          } else {
            localName = source.split('.')[1];
          }
          var inUse = true;
          if (matchColumns) {
            inUse = matchColumns.indexOf(localName) !== -1;
          }
          var drilldown = false;
          $scope.indexedColumns.push({
            name: localName,
            inUse: inUse,
            drilldown: drilldown
          });
        });
      });
    }

    function extractTableInfo(table) {
      if (table.name === $scope.table) {
        $scope.allColumns.push(createColumnInfo('_id'));
      }

      client.execute('column_list', {table: table.name})
        .success(function(response) {
          extractColumnsInfo(table, response.columns());
        });
    }

    function fillOptions() {
      client.execute('table_list')
        .success(function(response) {
          response.tables().forEach(function(table) {
            extractTableInfo(table);
          });
        });
    }

    function select() {
      var parameters = {
        table: $scope.table
      };
      angular.forEach($scope.parameters, function(value, key) {
        if (key in parameters) {
          return;
        }
        parameters[key] = value;
      });
      var request = client.execute('select', parameters);
      request.success(function(response) {
        $scope.response.rawData = response.rawData();
        $scope.commandLine = request.commandLine();
        $scope.response.elapsedTimeInMilliseconds =
          response.elapsedTime() * 1000;
        if (!response.isSuccess()) {
          $scope.message =
            'Failed to call "select" command: ' + response.errorMessage();
          $scope.response.nTotalRecords = 0;
          return;
        }
        $scope.currentPage = computeCurrentPage(parameters.offset || 0);
        $scope.response.nTotalRecords = response.nTotalRecords();
        var sortKeys = ($scope.parameters.sortby || '').split(/\s*,\s*/);
        $scope.response.columns = response.columns().map(function(column) {
          var sort = null;
          if (sortKeys.indexOf(column.name) !== -1) {
            sort = 'ascending';
          } else if (sortKeys.indexOf('-' + column.name) !== -1) {
            sort = 'descending';
          }
          setColumnSort(column, sort);
          return column;
        });
        $scope.response.records = response.records().map(function(record) {
          return record.map(function(value, index) {
            return {
              value: value,
              column: $scope.response.columns[index]
            };
          });
        });
        $scope.response.drilldowns = response.drilldowns();
        ($scope.parameters.drilldown || '')
          .split(/\s*,\s*/)
          .filter(function(drilldown) {
            return drilldown.length > 0;
          })
          .forEach(function(drilldown, i) {
            $scope.response.drilldowns[i].key = drilldown;
          });
      });
    }

    initialize();
    fillOptions();
    select();
  });
<commit_msg>Use "output" instead of "inUse" for output column flag<commit_after>'use strict';

/**
 * @ngdoc function
 * @name groongaAdminApp.controller:TableSearchController
 * @description
 * # TableSearchController
 * Controller of the groongaAdminApp
 */
angular.module('groongaAdminApp')
  .controller('TableSearchController', function ($scope, $routeParams, $location, $http) {
    var client = new GroongaClient($http);

    function computeCurrentPage(offset) {
      return Math.ceil((parseInt(offset) + 1) / $scope.nRecordsInPage);
    }

    function initialize() {
      $scope.table = $routeParams.table;
      $scope.style = 'table';
      $scope.response = {
        rawData: [],
        columns: [],
        records: [],
        drilldowns: [],
        elapsedTimeInMilliseconds: 0,
        nTotalRecords: 0
      };
      $scope.indexedColumns = [];
      $scope.allColumns = [];
      $scope.commandLine = '';
      $scope.message = '';
      $scope.currentPage = 1;
      $scope.nRecordsInPage = 10;
      $scope.maxNPages = 10;
      $scope.parameters = angular.copy($location.search());

      $scope.search = search;
      $scope.clear  = clear;
      $scope.toggleSort = toggleSort;
      $scope.selectDrilldown = selectDrilldown;
    }

    function packColumns(columns, filterFunction) {
      var targetColumnNames = columns
          .filter(filterFunction)
          .map(function(column) {
            return column.name;
          });
      return targetColumnNames.join(',');
    }

    function search() {
      var parameters = angular.copy($scope.parameters);
      parameters.match_columns =
        packColumns($scope.indexedColumns, function(column) {
          return column.inUse;
        });
      parameters.output_columns =
        packColumns($scope.allColumns, function(column) {
          return column.output;
        });
      parameters.offset = ($scope.currentPage - 1) * $scope.nRecordsInPage;
      parameters.limit = $scope.nRecordsInPage;
      var sortKeys = $scope.columns.filter(function(column) {
        return column.sort;
      }).map(function(column) {
        if (column.sort === 'ascending') {
          return column.name;
        } else {
          return '-' + column.name;
        }
      }).join(',');
      parameters.sortby = sortKeys;
      $location.search(parameters);
    }

    function clear() {
      $location.search({});
    }

    function setColumnSort(column, sort) {
      column.sort = sort;
      switch (column.sort) {
      case 'ascending':
        column.iconClass = 'glyphicon-sort-by-attributes';
        break;
      case 'descending':
        column.iconClass = 'glyphicon-sort-by-attributes-alt';
        break;
      default:
        column.iconClass = 'glyphicon-sort';
        break;
      }
    }

    function toggleSort(column) {
      var sort;
      switch (column.sort) {
      case 'ascending':
        sort = 'descending';
        break;
      case 'descending':
        sort = null;
        break;
      default:
        sort = 'ascending';
        break;
      }
      setColumnSort(column, sort);
      search();
    }

    function selectDrilldown(key, value) {
      var query = $scope.parameters.query || '';
      if (query.length > 0) {
        query += ' ';
      }
      $scope.parameters.query = query + key + ':' + value;

      var drilldowns = ($scope.parameters.drilldown || '').split(/\s*,\s*/);
      drilldowns = drilldowns.filter(function(drilldown) {
        return drilldown !== key;
      });
      $scope.parameters.drilldown = drilldowns.join(',');

      search();
    }

    function createColumnInfo(name) {
      var outputColumns = $scope.parameters.output_columns;
      var output = true;
      if (outputColumns) {
        output = outputColumns.indexOf(name) !== -1;
      }
      var drilldown = false;
      return {
        name: name,
        output: output,
        drilldown: drilldown
      };
    }

    function extractColumnsInfo(table, columns) {
      if (table.name === $scope.table) {
        columns.forEach(function(column) {
          if (column.isIndex) {
            return;
          }
          $scope.allColumns.push(createColumnInfo(column.name));
        });
      }

      columns.forEach(function(column) {
        if (!column.isIndex) {
          return;
        }
        if (column.range !== $scope.table) {
          return;
        }
        var matchColumns = $scope.parameters.match_columns;
        column.sources.forEach(function(source) {
          var localName;
          if (source.indexOf('.') === -1) {
            localName = '_key';
          } else {
            localName = source.split('.')[1];
          }
          var inUse = true;
          if (matchColumns) {
            inUse = matchColumns.indexOf(localName) !== -1;
          }
          $scope.indexedColumns.push({
            name: localName,
            inUse: inUse
          });
        });
      });
    }

    function extractTableInfo(table) {
      if (table.name === $scope.table) {
        $scope.allColumns.push(createColumnInfo('_id'));
      }

      client.execute('column_list', {table: table.name})
        .success(function(response) {
          extractColumnsInfo(table, response.columns());
        });
    }

    function fillOptions() {
      client.execute('table_list')
        .success(function(response) {
          response.tables().forEach(function(table) {
            extractTableInfo(table);
          });
        });
    }

    function select() {
      var parameters = {
        table: $scope.table
      };
      angular.forEach($scope.parameters, function(value, key) {
        if (key in parameters) {
          return;
        }
        parameters[key] = value;
      });
      var request = client.execute('select', parameters);
      request.success(function(response) {
        $scope.response.rawData = response.rawData();
        $scope.commandLine = request.commandLine();
        $scope.response.elapsedTimeInMilliseconds =
          response.elapsedTime() * 1000;
        if (!response.isSuccess()) {
          $scope.message =
            'Failed to call "select" command: ' + response.errorMessage();
          $scope.response.nTotalRecords = 0;
          return;
        }
        $scope.currentPage = computeCurrentPage(parameters.offset || 0);
        $scope.response.nTotalRecords = response.nTotalRecords();
        var sortKeys = ($scope.parameters.sortby || '').split(/\s*,\s*/);
        $scope.response.columns = response.columns().map(function(column) {
          var sort = null;
          if (sortKeys.indexOf(column.name) !== -1) {
            sort = 'ascending';
          } else if (sortKeys.indexOf('-' + column.name) !== -1) {
            sort = 'descending';
          }
          setColumnSort(column, sort);
          return column;
        });
        $scope.response.records = response.records().map(function(record) {
          return record.map(function(value, index) {
            return {
              value: value,
              column: $scope.response.columns[index]
            };
          });
        });
        $scope.response.drilldowns = response.drilldowns();
        ($scope.parameters.drilldown || '')
          .split(/\s*,\s*/)
          .filter(function(drilldown) {
            return drilldown.length > 0;
          })
          .forEach(function(drilldown, i) {
            $scope.response.drilldowns[i].key = drilldown;
          });
      });
    }

    initialize();
    fillOptions();
    select();
  });
<|endoftext|>


<commit_before>import { ZONE_MAIN, ZONE_SIDEBOARD } from "../zones";

export default {
  name: "MTGO",
  download,
  downloadExtension: ".mtgo.txt"
  /* If mtgo later supports clipboard import, enable this: */
  // copy
};

function download (name, deck) {
  return [
    ...deck[ZONE_MAIN].map(renderDownloadCard),

    ...(deck[ZONE_SIDEBOARD].length ? ["", "Sideboard"] : []),

    ...deck[ZONE_SIDEBOARD].map(renderDownloadCard)
  ].join("\n");
}

function renderDownloadCard ({ card, count }) {
  return `${count} ${correctName(card)}`;
}

function correctName (card) {
  switch (card.layout) {
  case "split":
  case "aftermath":
    return card.name.replace(/\s\/\/\s/g, "/");

  case "flip":
  case "transform":
  case "meld":
  case "adventure":
  case "modal_dfc":
    return card.faceName || card.name.replace(/\s\/\/.*$/, "");

  default:
    return card.name;
  }
}

// NOTE: the following was abandoned because supporting .dek was hard
// and MTGO seems to handle a lot of tricky edge cases with .txt import

// function download (name, deck) {
//   return `<?xml version="1.0" encoding="UTF-8"?>
// <Deck xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
//   <NetDeckID>0</NetDeckID>
//   <PreconstructedDeckID>0</PreconstructedDeckID>

// ${
//   deck[ZONE_MAIN]
//     .map(renderDownloadCard)
//     .filter(Boolean)
//     .join("\n")
// }

// ${
//   deck[ZONE_SIDEBOARD]
//     .map(renderDownloadCard)
//     .filter(Boolean)
//     .join("\n")
// }
// </Deck>
// `;
// }

// function renderDownloadCard ({ card, count, sideboard = false }) {
//   if (!card.identifiers.mtgoId) {
//     console.warn(`Exporting ${card.name} to .dek, it lacks an mtgoId, which may cause error on importing`);
//     return `  <Cards Quantity="${count}" Sideboard="${sideboard}" Name="${correctName(card)}" Annotation="0" />`;

//     // NOTE failing to have an mtgoId seems to mainly be because a set isn't present in MTGO.
//     // There are two cases so far known
//     // 1. it's a card that was never in mtgo - e.g. any unset card
//     //   - them import of any .dek containing this card will fail
//     //
//     // 2. it's a card that exists in mtgo, just not this printing - e.g. some promo Ancestral Recall
//     //   - exporting this card without a CatId leads MTGO to select another printing of the card
//     //   - the import of the .dek file works fine
//   }

//   return `  <Cards CatID="${card.identifiers.mtgoId}" Quantity="${count}" Sideboard="${sideboard}" Name="${correctName(card)}" Annotation="0" />`;
// }

<commit_msg>mtgo export .txt (not .mtgo.txt)<commit_after>import { ZONE_MAIN, ZONE_SIDEBOARD } from "../zones";

export default {
  name: "MTGO",
  download,
  downloadExtension: ".txt"
  /* If mtgo later supports clipboard import, enable this: */
  // copy
};

function download (name, deck) {
  return [
    ...deck[ZONE_MAIN].map(renderDownloadCard),

    ...(deck[ZONE_SIDEBOARD].length ? ["", "Sideboard"] : []),

    ...deck[ZONE_SIDEBOARD].map(renderDownloadCard)
  ].join("\n");
}

function renderDownloadCard ({ card, count }) {
  return `${count} ${correctName(card)}`;
}

function correctName (card) {
  switch (card.layout) {
  case "split":
  case "aftermath":
    return card.name.replace(/\s\/\/\s/g, "/");

  case "flip":
  case "transform":
  case "meld":
  case "adventure":
  case "modal_dfc":
    return card.faceName || card.name.replace(/\s\/\/.*$/, "");

  default:
    return card.name;
  }
}

// NOTE: the following was abandoned because supporting .dek was hard
// and MTGO seems to handle a lot of tricky edge cases with .txt import

// function download (name, deck) {
//   return `<?xml version="1.0" encoding="UTF-8"?>
// <Deck xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
//   <NetDeckID>0</NetDeckID>
//   <PreconstructedDeckID>0</PreconstructedDeckID>

// ${
//   deck[ZONE_MAIN]
//     .map(renderDownloadCard)
//     .filter(Boolean)
//     .join("\n")
// }

// ${
//   deck[ZONE_SIDEBOARD]
//     .map(renderDownloadCard)
//     .filter(Boolean)
//     .join("\n")
// }
// </Deck>
// `;
// }

// function renderDownloadCard ({ card, count, sideboard = false }) {
//   if (!card.identifiers.mtgoId) {
//     console.warn(`Exporting ${card.name} to .dek, it lacks an mtgoId, which may cause error on importing`);
//     return `  <Cards Quantity="${count}" Sideboard="${sideboard}" Name="${correctName(card)}" Annotation="0" />`;

//     // NOTE failing to have an mtgoId seems to mainly be because a set isn't present in MTGO.
//     // There are two cases so far known
//     // 1. it's a card that was never in mtgo - e.g. any unset card
//     //   - them import of any .dek containing this card will fail
//     //
//     // 2. it's a card that exists in mtgo, just not this printing - e.g. some promo Ancestral Recall
//     //   - exporting this card without a CatId leads MTGO to select another printing of the card
//     //   - the import of the .dek file works fine
//   }

//   return `  <Cards CatID="${card.identifiers.mtgoId}" Quantity="${count}" Sideboard="${sideboard}" Name="${correctName(card)}" Annotation="0" />`;
// }

<|endoftext|>


<commit_before>var webdriver = require('selenium-webdriver');
var cssParser = require('css');
var mediaTypeParser = require('media-type');
var cssPrefixes = rootRequire('lib/css-prefixes.json');

var self = this;

exports.name = "css-prefixes";
exports.category = "compatibility";
exports.check = function (checker, browser) {
    var sink = checker.sink;
    var missingPrefixEquivalent = {};
    var mismatchPrefixEquivalent = {};
    browser.on('har', function(har) {
        if (har && har.log && har.log.entries) {
            for (var i = 0; i < har.log.entries.length ; i++) {
                var entry = har.log.entries[i];
                if (entry.response.status === 200) {
                    var media = mediaTypeParser.fromString(entry.response.content.mimeType);
                    var mediaType = mediaTypeName(media);
                    if (mediaType === "text/css") {
                        var url = entry.request.url;
                        var cssObj = cssParser.parse(entry.response.content.text, {silent: true});
                        for (var j = 0 ; j < cssObj.stylesheet.rules.length; j++) {
                            var rule = cssObj.stylesheet.rules[j];
                            var prefixedProperties = {};
                            var unprefixedProperties = {};
                            if (rule.declarations) {
                                for (var k = 0; k < rule.declarations.length; k++) {
                                    var decl = rule.declarations[k];
                                    if (hasprefix(decl.property)) {
                                        var unprefixed = unprefix(decl.property);
                                        if (!prefixedProperties[unprefixed]) {
                                            prefixedProperties[unprefixed] = {};
                                        }
                                        prefixedProperties[unprefixed][decl.property] = decl;
                                    } else {
                                        unprefixedProperties[decl.property] = decl;
                                    }
                                }
                            }
                            var prefixed = Object.keys(prefixedProperties);
                            for (k = 0 ; k < prefixed.length ; k++) {
                                // add the unprefixed decl if it exists
                                if (unprefixedProperties[prefixed[k]]) {
                                    prefixedProperties[prefixed[k]][prefixed[k]] = unprefixedProperties[prefixed[k]];
                                }
                                var props = prefixedProperties[prefixed[k]];
                                var prefixedNames = Object.keys(props);
                                var ref = props[prefixedNames[0]].value;
                                var misMatchFound = false;
                                for (var l = 1; l < prefixedNames.length; l++) {
                                    // are the various unprefixed decl the same?
                                    if (props[prefixedNames[l]].value !== ref) {
                                        misMatchFound = true;
                                        break;
                                    }
                                }
                                if (misMatchFound) {
                                    if (!mismatchPrefixEquivalent[url]) {
                                        mismatchPrefixEquivalent[url] = [];
                                    }
                                    mismatchPrefixEquivalent[url].push({
                                        rule: stringify(rule),
                                        position: rule.position.start,
                                        prop: prefixed[k],
                                        decls: values(props).map(stringify)
                                    });
                                }
                                var equivPrefixes = cssPrefixes[prefixed[k]].values;
                                if (equivPrefixes) {
                                    var missing = [];
                                    for (var l = 0 ; l < equivPrefixes.length; l++) {
                                        if (!props[equivPrefixes[l]]) {
                                            missing.push(equivPrefixes[l]);
                                        }
                                    }
                                    if (missing.length) {
                                        if (!missingPrefixEquivalent[url]) {
                                            missingPrefixEquivalent[url] = [];
                                        }
                                        missingPrefixEquivalent[url].push({
                                            rule: stringify(rule),
                                            position: rule.position.start,
                                            prop: prefixed[k],
                                            missing: missing,
                                            decls: values(props).map(stringify),
                                            value: values(props)[0].value
                                        });
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (Object.keys(missingPrefixEquivalent).length) {
	        checker.report(sink, "missing-prefixes", self.name, self.category, {missingPrefixes: missingPrefixEquivalent});
            }
            if (Object.keys(mismatchPrefixEquivalent).length) {
	        checker.report(sink, "mismatching-prefixes", self.name, self.category, {mismatchingPrefixes: mismatchPrefixEquivalent});
            }
        }
    });
};

// TODO: dup of compression
function mediaTypeName(media) {
    if (media.isValid()) {
        return media.type + '/' + media.subtype + (media.hasSuffix() ? '+' + media.suffix : '');
    }
}

function hasprefix(string) {
    return string.match(/^-[^-]*-/);
}

function unprefix(string) {
    return string.replace(/^-[^-]*-/,'');
}

function stringify(obj) {
    var stringified;
    switch(obj.type) {
        case 'rule':
        stringified = obj.selectors.join(', ') + ' {' + '\n';
        for (var i = 0; i < obj.declarations.length; i++) {
            stringified += stringify(obj.declarations[i]);
        }
        stringified += "}";
        break;
        case 'declaration':
        stringified = obj.property + ': ' +
                obj.value + ';\n'
        break;
    }
    return stringified;
}

function values(obj) {
    var vals = Object.keys(obj).map(function (key) {
        return obj[key];
    });
    return vals;
}<commit_msg>don't trip on unknown prefixed property<commit_after>var webdriver = require('selenium-webdriver');
var cssParser = require('css');
var mediaTypeParser = require('media-type');
var cssPrefixes = rootRequire('lib/css-prefixes.json');

var self = this;

exports.name = "css-prefixes";
exports.category = "compatibility";
exports.check = function (checker, browser) {
    var sink = checker.sink;
    var missingPrefixEquivalent = {};
    var mismatchPrefixEquivalent = {};
    browser.on('har', function(har) {
        if (har && har.log && har.log.entries) {
            for (var i = 0; i < har.log.entries.length ; i++) {
                var entry = har.log.entries[i];
                if (entry.response.status === 200) {
                    var media = mediaTypeParser.fromString(entry.response.content.mimeType);
                    var mediaType = mediaTypeName(media);
                    if (mediaType === "text/css") {
                        var url = entry.request.url;
                        var cssObj = cssParser.parse(entry.response.content.text, {silent: true});
                        for (var j = 0 ; j < cssObj.stylesheet.rules.length; j++) {
                            var rule = cssObj.stylesheet.rules[j];
                            var prefixedProperties = {};
                            var unprefixedProperties = {};
                            if (rule.declarations) {
                                for (var k = 0; k < rule.declarations.length; k++) {
                                    var decl = rule.declarations[k];
                                    if (hasprefix(decl.property)) {
                                        var unprefixed = unprefix(decl.property);
                                        if (!prefixedProperties[unprefixed]) {
                                            prefixedProperties[unprefixed] = {};
                                        }
                                        prefixedProperties[unprefixed][decl.property] = decl;
                                    } else {
                                        unprefixedProperties[decl.property] = decl;
                                    }
                                }
                            }
                            var prefixed = Object.keys(prefixedProperties);
                            for (k = 0 ; k < prefixed.length ; k++) {
                                // add the unprefixed decl if it exists
                                if (unprefixedProperties[prefixed[k]]) {
                                    prefixedProperties[prefixed[k]][prefixed[k]] = unprefixedProperties[prefixed[k]];
                                }
                                var props = prefixedProperties[prefixed[k]];
                                var prefixedNames = Object.keys(props);
                                var ref = props[prefixedNames[0]].value;
                                var misMatchFound = false;
                                for (var l = 1; l < prefixedNames.length; l++) {
                                    // are the various unprefixed decl the same?
                                    if (props[prefixedNames[l]].value !== ref) {
                                        misMatchFound = true;
                                        break;
                                    }
                                }
                                if (misMatchFound) {
                                    if (!mismatchPrefixEquivalent[url]) {
                                        mismatchPrefixEquivalent[url] = [];
                                    }
                                    mismatchPrefixEquivalent[url].push({
                                        rule: stringify(rule),
                                        position: rule.position.start,
                                        prop: prefixed[k],
                                        decls: values(props).map(stringify)
                                    });
                                }
                                var equivPrefixes = cssPrefixes[prefixed[k]] ? cssPrefixes[prefixed[k]].values : undefined;
                                if (equivPrefixes) {
                                    var missing = [];
                                    for (var l = 0 ; l < equivPrefixes.length; l++) {
                                        if (!props[equivPrefixes[l]]) {
                                            missing.push(equivPrefixes[l]);
                                        }
                                    }
                                    if (missing.length) {
                                        if (!missingPrefixEquivalent[url]) {
                                            missingPrefixEquivalent[url] = [];
                                        }
                                        missingPrefixEquivalent[url].push({
                                            rule: stringify(rule),
                                            position: rule.position.start,
                                            prop: prefixed[k],
                                            missing: missing,
                                            decls: values(props).map(stringify),
                                            value: values(props)[0].value
                                        });
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (Object.keys(missingPrefixEquivalent).length) {
	        checker.report(sink, "missing-prefixes", self.name, self.category, {missingPrefixes: missingPrefixEquivalent});
            }
            if (Object.keys(mismatchPrefixEquivalent).length) {
	        checker.report(sink, "mismatching-prefixes", self.name, self.category, {mismatchingPrefixes: mismatchPrefixEquivalent});
            }
        }
    });
};

// TODO: dup of compression
function mediaTypeName(media) {
    if (media.isValid()) {
        return media.type + '/' + media.subtype + (media.hasSuffix() ? '+' + media.suffix : '');
    }
}

function hasprefix(string) {
    return string.match(/^-[^-]*-/);
}

function unprefix(string) {
    return string.replace(/^-[^-]*-/,'');
}

function stringify(obj) {
    var stringified;
    switch(obj.type) {
        case 'rule':
        stringified = obj.selectors.join(', ') + ' {' + '\n';
        for (var i = 0; i < obj.declarations.length; i++) {
            stringified += stringify(obj.declarations[i]);
        }
        stringified += "}";
        break;
        case 'declaration':
        stringified = obj.property + ': ' +
                obj.value + ';\n'
        break;
    }
    return stringified;
}

function values(obj) {
    var vals = Object.keys(obj).map(function (key) {
        return obj[key];
    });
    return vals;
}<|endoftext|>


<commit_before>/* record log messages for testing */
// var logAllIds = function() {
//   var allTags = document.head.getElementsByTagName('style');
//   var ids = [];
//   for (var tg = 0; tg < allTags.length; tg++) {
//     var tag = allTags[tg];
//     if (tag.id) {
//       console.log(tag.id);
//     }
//   }
// };

var logMessages = [],
  realConsoleLog = console.log;
console.log = function(msg) {
  logMessages.push(msg);
  realConsoleLog.call(console, msg);
};

var testLessEqualsInDocument = function() {
  testLessInDocument(testSheet);
};

var testLessErrorsInDocument = function(isConsole) {
    testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet);
};

var testLessInDocument = function(testFunc) {
  var links = document.getElementsByTagName('link'),
    typePattern = /^text\/(x-)?less$/;

  for (var i = 0; i < links.length; i++) {
    if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
      (links[i].type.match(typePattern)))) {
      testFunc(links[i]);
    }
  }
};

var testSheet = function(sheet) {
  it(sheet.id + " should match the expected output", function() {
    var lessOutputId = sheet.id.replace("original-", ""),
      expectedOutputId = "expected-" + lessOutputId,
      lessOutputObj,
      lessOutput,
      expectedOutputHref = document.getElementById(expectedOutputId).href,
      expectedOutput = loadFile(expectedOutputHref);

    // Browser spec generates less on the fly, so we need to loose control
    waitsFor(function() {
      lessOutputObj = document.getElementById(lessOutputId);
      // the type condition is necessary because of inline browser tests
      return lessOutputObj !== null && lessOutputObj.type === "text/css";
    }, "generation of " + lessOutputId + "", 700);

    runs(function() {
      lessOutput = lessOutputObj.innerText;
    });

    waitsFor(function() {
      return expectedOutput.loaded;
    }, "failed to load expected outout", 10000);

    runs(function() {
      // use sheet to do testing
            expect(expectedOutput.text).toEqual(lessOutput);
    });
  });
};

//TODO: do it cleaner - the same way as in css

function extractId(href) {
  return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain
  .replace(/^\//, '') // Remove root /
  .replace(/\.[a-zA-Z]+$/, '') // Remove simple extension
  .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
  .replace(/\./g, ':'); // Replace dots with colons(for valid id)
}

var testErrorSheet = function(sheet) {
  it(sheet.id + " should match an error", function() {
    var lessHref = sheet.href,
      id = "less-error-message:" + extractId(lessHref),
      //            id = sheet.id.replace(/^original-less:/, "less-error-message:"),
      errorHref = lessHref.replace(/.less$/, ".txt"),
      errorFile = loadFile(errorHref),
      actualErrorElement,
      actualErrorMsg;

    // Less.js sets 10ms timer in order to add error message on top of page.
    waitsFor(function() {
      actualErrorElement = document.getElementById(id);
      return actualErrorElement !== null;
    }, "error message was not generated", 70);

    runs(function() {
      actualErrorMsg = actualErrorElement.innerText
        .replace(/\n\d+/g, function(lineNo) {
        return lineNo + " ";
      })
        .replace(/\n\s*in /g, " in ")
        .replace("\n\n", "\n");
    });

    waitsFor(function() {
      return errorFile.loaded;
    }, "failed to load expected outout", 10000);

    runs(function() {
      var errorTxt = errorFile.text
        .replace("{path}", "")
        .replace("{pathrel}", "")
        .replace("{pathhref}", "http://localhost:8081/test/less/errors/")
        .replace("{404status}", " (404)");
      expect(errorTxt).toEqual(actualErrorMsg);
      if (errorTxt == actualErrorMsg) {
        actualErrorElement.style.display = "none";
      }
        });
    });
};

var testErrorSheetConsole = function(sheet) {
    it(sheet.id + " should match an error", function() {
        var lessHref =  sheet.href,
            id = sheet.id.replace(/^original-less:/, "less-error-message:"),
            errorHref = lessHref.replace(/.less$/, ".txt"),
            errorFile = loadFile(errorHref),
            actualErrorElement = document.getElementById(id),
            actualErrorMsg = logMessages[logMessages.length - 1];

        describe("the error", function() {
            expect(actualErrorElement).toBe(null);

        });

        /*actualErrorMsg = actualErrorElement.innerText
            .replace(/\n\d+/g, function(lineNo) { return lineNo + " "; })
            .replace(/\n\s*in /g, " in ")
            .replace("\n\n", "\n");*/

        waitsFor(function() {
            return errorFile.loaded;
        }, "failed to load expected outout", 10000);

        runs(function() {
            var errorTxt = errorFile.text
                .replace("{path}", "")
                .replace("{pathrel}", "")
                .replace("{pathhref}", "http://localhost:8081/browser/less/")
                .replace("{404status}", " (404)")
                .trim();
            expect(errorTxt).toEqual(actualErrorMsg);
    });
  });
};

var loadFile = function(href) {
  var request = new XMLHttpRequest(),
    response = {
      loaded: false,
      text: ""
    };
  request.open('GET', href, true);
  request.onload = function(e) {
    response.text = request.response.replace(/\r/g, "");
    response.loaded = true;
  };
  request.send();
  return response;
};

(function() {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 1000;

  var htmlReporter = new jasmine.HtmlReporter();

  jasmineEnv.addReporter(htmlReporter);

  jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
  };

  var currentWindowOnload = window.onload;

  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    execJasmine();
  };

  function execJasmine() {
    setTimeout(function() {
      jasmineEnv.execute();
    }, 3000);
  }

})();<commit_msg>innerText isn't available in ff/chrome/etc so use innerHTML<commit_after>/* record log messages for testing */
// var logAllIds = function() {
//   var allTags = document.head.getElementsByTagName('style');
//   var ids = [];
//   for (var tg = 0; tg < allTags.length; tg++) {
//     var tag = allTags[tg];
//     if (tag.id) {
//       console.log(tag.id);
//     }
//   }
// };

var logMessages = [],
  realConsoleLog = console.log;
console.log = function(msg) {
  logMessages.push(msg);
  realConsoleLog.call(console, msg);
};

var testLessEqualsInDocument = function() {
  testLessInDocument(testSheet);
};

var testLessErrorsInDocument = function(isConsole) {
    testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet);
};

var testLessInDocument = function(testFunc) {
  var links = document.getElementsByTagName('link'),
    typePattern = /^text\/(x-)?less$/;

  for (var i = 0; i < links.length; i++) {
    if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
      (links[i].type.match(typePattern)))) {
      testFunc(links[i]);
    }
  }
};

var testSheet = function(sheet) {
  it(sheet.id + " should match the expected output", function() {
    var lessOutputId = sheet.id.replace("original-", ""),
      expectedOutputId = "expected-" + lessOutputId,
      lessOutputObj,
      lessOutput,
      expectedOutputHref = document.getElementById(expectedOutputId).href,
      expectedOutput = loadFile(expectedOutputHref);

    // Browser spec generates less on the fly, so we need to loose control
    waitsFor(function() {
      lessOutputObj = document.getElementById(lessOutputId);
      // the type condition is necessary because of inline browser tests
      return lessOutputObj !== null && lessOutputObj.type === "text/css";
    }, "generation of " + lessOutputId + "", 700);

    runs(function() {
      lessOutput = lessOutputObj.innerText || lessOutputObj.innerHTML;
    });

    waitsFor(function() {
      return expectedOutput.loaded;
    }, "failed to load expected outout", 10000);

    runs(function() {
      // use sheet to do testing
            expect(expectedOutput.text).toEqual(lessOutput);
    });
  });
};

//TODO: do it cleaner - the same way as in css

function extractId(href) {
  return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain
  .replace(/^\//, '') // Remove root /
  .replace(/\.[a-zA-Z]+$/, '') // Remove simple extension
  .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
  .replace(/\./g, ':'); // Replace dots with colons(for valid id)
}

var testErrorSheet = function(sheet) {
  it(sheet.id + " should match an error", function() {
    var lessHref = sheet.href,
      id = "less-error-message:" + extractId(lessHref),
      //            id = sheet.id.replace(/^original-less:/, "less-error-message:"),
      errorHref = lessHref.replace(/.less$/, ".txt"),
      errorFile = loadFile(errorHref),
      actualErrorElement,
      actualErrorMsg;

    // Less.js sets 10ms timer in order to add error message on top of page.
    waitsFor(function() {
      actualErrorElement = document.getElementById(id);
      return actualErrorElement !== null;
    }, "error message was not generated", 70);

    runs(function() {
      actualErrorMsg = actualErrorElement.innerText
        .replace(/\n\d+/g, function(lineNo) {
        return lineNo + " ";
      })
        .replace(/\n\s*in /g, " in ")
        .replace("\n\n", "\n");
    });

    waitsFor(function() {
      return errorFile.loaded;
    }, "failed to load expected outout", 10000);

    runs(function() {
      var errorTxt = errorFile.text
        .replace("{path}", "")
        .replace("{pathrel}", "")
        .replace("{pathhref}", "http://localhost:8081/test/less/errors/")
        .replace("{404status}", " (404)");
      expect(errorTxt).toEqual(actualErrorMsg);
      if (errorTxt == actualErrorMsg) {
        actualErrorElement.style.display = "none";
      }
        });
    });
};

var testErrorSheetConsole = function(sheet) {
    it(sheet.id + " should match an error", function() {
        var lessHref =  sheet.href,
            id = sheet.id.replace(/^original-less:/, "less-error-message:"),
            errorHref = lessHref.replace(/.less$/, ".txt"),
            errorFile = loadFile(errorHref),
            actualErrorElement = document.getElementById(id),
            actualErrorMsg = logMessages[logMessages.length - 1];

        describe("the error", function() {
            expect(actualErrorElement).toBe(null);

        });

        /*actualErrorMsg = actualErrorElement.innerText
            .replace(/\n\d+/g, function(lineNo) { return lineNo + " "; })
            .replace(/\n\s*in /g, " in ")
            .replace("\n\n", "\n");*/

        waitsFor(function() {
            return errorFile.loaded;
        }, "failed to load expected outout", 10000);

        runs(function() {
            var errorTxt = errorFile.text
                .replace("{path}", "")
                .replace("{pathrel}", "")
                .replace("{pathhref}", "http://localhost:8081/browser/less/")
                .replace("{404status}", " (404)")
                .trim();
            expect(errorTxt).toEqual(actualErrorMsg);
    });
  });
};

var loadFile = function(href) {
  var request = new XMLHttpRequest(),
    response = {
      loaded: false,
      text: ""
    };
  request.open('GET', href, true);
  request.onload = function(e) {
    response.text = request.response.replace(/\r/g, "");
    response.loaded = true;
  };
  request.send();
  return response;
};

(function() {
  var jasmineEnv = jasmine.getEnv();
  jasmineEnv.updateInterval = 1000;

  var htmlReporter = new jasmine.HtmlReporter();

  jasmineEnv.addReporter(htmlReporter);

  jasmineEnv.specFilter = function(spec) {
    return htmlReporter.specFilter(spec);
  };

  var currentWindowOnload = window.onload;

  window.onload = function() {
    if (currentWindowOnload) {
      currentWindowOnload();
    }
    execJasmine();
  };

  function execJasmine() {
    setTimeout(function() {
      jasmineEnv.execute();
    }, 3000);
  }

})();<|endoftext|>


<commit_before>module.exports = {
  extends: ['@commitlint/config-conventional']
};
<commit_msg>chore: commitlint settings<commit_after>module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'subject-case': [0]
  }
};
<|endoftext|>


<commit_before>import Piece from './piece';

export default class Board {
  constructor() {
    this.setBoard(this.initialUsiBoard());
  }

  initialUsiBoard() {
    return (
      [
        ['l', 'n', 's', 'g', 'k', 'g', 's', 'n', 'l'],
        ['*', 'b', '*', '*', '*', '*', '*', 'r', '*'],
        ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'],
        ['*', '*', '*', '*', '*', '*', '*', '*', '*'],
        ['*', '*', '*', '*', '*', '*', '*', '*', '*'],
        ['*', '*', '*', '*', '*', '*', '*', '*', '*'],
        ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'],
        ['*', 'B', '*', '*', '*', '*', '*', 'R', '*'],
        ['L', 'N', 'S', 'G', 'K', 'G', 'S', 'N', 'L']
      ]
    );
  }

  setBoard(board) {
    this.board = this.createBoard(board);
  }

  createBoard(board) {
    var _board = board.map((row, y) => {
      var yCor = this.transposeToCorY(y);
      var rows = row.map((type, x) => {
        var xCor = this.transposeToCorX(x);
        return (
          new Piece({ type: type, x: xCor, y: yCor })
        );
      });
      return(rows);
    });

    return _board;
  }

  movePiece(fromPiece, toPiece) {
    // if piece of argument is not match piece in the board, throw exception
    //
    if (! this.matchPiece(fromPiece)) {
      var pos = `xCor = ${fromPiece.x}, yCor = ${fromPiece.y}`;
      throw new Error(`Does not match coordinates in board. ${pos}`);
    }

    this.enhanceMovablePoint(fromPiece);

    var [toCorX, toCorY] = [toPiece.x, toPiece.y];
    var [toIdxX, toIdxY] = this.invertCor(toCorX, toCorY);
    var [fromCorX, fromCorY] = [fromPiece.x, fromPiece.y];
    var [fromIdxX, fromIdxY] = this.invertCor(fromCorX, fromCorY);

    var destPiece = this.board[toIdxY][toIdxX];

    if (typeof destPiece === 'undefined' || ! destPiece.movable) {
      return;
    }

    fromPiece.x = destPiece.x;
    fromPiece.y = destPiece.y;

    this.board[toIdxY][toIdxX] = fromPiece;
    this.board[fromIdxY][fromIdxX].type = '*';

    return;
  }

  enhanceMovablePoint(piece) {
    var moveDef = piece.moveDef();

    // if piece of argument is not match piece in the board, throw exception
    //
    if (! this.matchPiece(piece)) {
      var pos = `xCor = ${piece.x}, yCor = ${piece.y}`;
      throw new Error(`Does not match coordinates in board. ${pos}`);
    }

    // if moveDef has just property, piece moves just coordinates on board.
    //
    if (moveDef.just) {
      this.movablePointsByJust(piece);
    }

    // if moveDef has fly property, piece moves recursion on board.
    //
    if (moveDef.fly) {
      this.movablePointsByFly(piece);
    }
  }

  // if piece of argument is match in the board, return true, else return false
  //
  matchPiece(piece) {
    var [xCor, yCor] = [piece.x, piece.y];
    var [x, y] = this.invertCor(xCor, yCor);

    var isUndefined = typeof this.findPiece(x, y) === 'undefined';
    var isEqualPiece = this.findPiece(x, y).equals(
      new Piece({
        x: piece.x,
        y: piece.y,
        type: piece.type,
        movable: piece.movable
      })
    );

    return (isUndefined || isEqualPiece);
  }

  // if moveDef has just property, piece moves just coordinates on board.
  //
  movablePointsByJust(piece) {
    var [xCor, yCor] = [piece.x, piece.y];
    var moveDef = piece.moveDef();
    var [x, y] = this.invertCor(xCor, yCor);

    moveDef.just.forEach((def) => {
      var [defX, defY] = def;
      var piece = this.findPiece(x + defX, y + defY);
      if (piece) { piece.movable = true; }
    });
  }

  movablePointsByFly(piece) {
    var [xCor, yCor] = [piece.x, piece.y];
    var moveDef = piece.moveDef();
    var [x, y] = this.invertCor(xCor, yCor);

    moveDef.fly.forEach((def) => {
      var [defX, defY] = def;
      var dx, dy;

      dx = x + defX;
      dy = y + defY;

      var piece = this.findPiece(dx, dy);

      while (piece) {
        piece.movable = true;
        dx = dx + defX;
        dy = dy + defY;

        piece = this.findPiece(dx, dy);

        if (piece && piece.type !== '*') {
          piece.movable = true;
          break;
        }
      }
    });
  }

  transposeToCorX(xIndex) {
    return 10 - xIndex - 1;
  }

  transposeToCorY(yIndex) {
    return yIndex + 1;
  }

  invertToIndexX(xCor) {
    return 9 - xCor;
  }

  invertToIndexY(yCor) {
    return yCor - 1;
  }

  invertCor(xCor, yCor) {
    return [this.invertToIndexX(xCor), this.invertToIndexY(yCor)];
  }

  findPiece(xIndex, yIndex) {
    var row = this.board[yIndex];
    return row ? row[xIndex] : undefined;
  }

  fetchPiece(piece) {
    var [toCorX, toCorY] = [piece.x, piece.y];
    var [toIdxX, toIdxY] = this.invertCor(toCorX, toCorY);
    return this.findPiece(toIdxX, toIdxY);
  }

  toArray() {
    return this.board.map((row) => {
      return row.map((piece) => {
        return piece.type;
      });
    });
  }
};
<commit_msg>Use fetchPiece function<commit_after>import Piece from './piece';

export default class Board {
  constructor() {
    this.setBoard(this.initialUsiBoard());
  }

  initialUsiBoard() {
    return (
      [
        ['l', 'n', 's', 'g', 'k', 'g', 's', 'n', 'l'],
        ['*', 'b', '*', '*', '*', '*', '*', 'r', '*'],
        ['p', 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p'],
        ['*', '*', '*', '*', '*', '*', '*', '*', '*'],
        ['*', '*', '*', '*', '*', '*', '*', '*', '*'],
        ['*', '*', '*', '*', '*', '*', '*', '*', '*'],
        ['P', 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'],
        ['*', 'B', '*', '*', '*', '*', '*', 'R', '*'],
        ['L', 'N', 'S', 'G', 'K', 'G', 'S', 'N', 'L']
      ]
    );
  }

  setBoard(board) {
    this.board = this.createBoard(board);
  }

  createBoard(board) {
    var _board = board.map((row, y) => {
      var yCor = this.transposeToCorY(y);
      var rows = row.map((type, x) => {
        var xCor = this.transposeToCorX(x);
        return (
          new Piece({ type: type, x: xCor, y: yCor })
        );
      });
      return(rows);
    });

    return _board;
  }

  movePiece(fromPiece, toPiece) {
    // if piece of argument is not match piece in the board, throw exception
    //
    if (! this.matchPiece(fromPiece)) {
      var pos = `xCor = ${fromPiece.x}, yCor = ${fromPiece.y}`;
      throw new Error(`Does not match coordinates in board. ${pos}`);
    }

    this.enhanceMovablePoint(fromPiece);

    var [toCorX, toCorY] = [toPiece.x, toPiece.y];
    var [toIdxX, toIdxY] = this.invertCor(toCorX, toCorY);
    var [fromCorX, fromCorY] = [fromPiece.x, fromPiece.y];
    var [fromIdxX, fromIdxY] = this.invertCor(fromCorX, fromCorY);

    var destPiece = this.board[toIdxY][toIdxX];

    if (typeof destPiece === 'undefined' || ! destPiece.movable) {
      return;
    }

    fromPiece.x = destPiece.x;
    fromPiece.y = destPiece.y;

    this.board[toIdxY][toIdxX] = fromPiece;
    this.board[fromIdxY][fromIdxX].type = '*';

    return;
  }

  enhanceMovablePoint(piece) {
    var moveDef = piece.moveDef();

    // if piece of argument is not match piece in the board, throw exception
    //
    if (! this.matchPiece(piece)) {
      var pos = `xCor = ${piece.x}, yCor = ${piece.y}`;
      throw new Error(`Does not match coordinates in board. ${pos}`);
    }

    // if moveDef has just property, piece moves just coordinates on board.
    //
    if (moveDef.just) {
      this.movablePointsByJust(piece);
    }

    // if moveDef has fly property, piece moves recursion on board.
    //
    if (moveDef.fly) {
      this.movablePointsByFly(piece);
    }
  }

  // if piece of argument is match in the board, return true, else return false
  //
  matchPiece(piece) {
    var isUndefined = typeof this.fetchPiece(piece) === 'undefined';
    var isEqualPiece = this.fetchPiece(piece).equals(
      new Piece({
        x: piece.x,
        y: piece.y,
        type: piece.type,
        movable: piece.movable
      })
    );

    return (isUndefined || isEqualPiece);
  }

  // if moveDef has just property, piece moves just coordinates on board.
  //
  movablePointsByJust(piece) {
    var [xCor, yCor] = [piece.x, piece.y];
    var moveDef = piece.moveDef();
    var [x, y] = this.invertCor(xCor, yCor);

    moveDef.just.forEach((def) => {
      var [defX, defY] = def;
      var piece = this.findPiece(x + defX, y + defY);
      if (piece) { piece.movable = true; }
    });
  }

  movablePointsByFly(piece) {
    var [xCor, yCor] = [piece.x, piece.y];
    var moveDef = piece.moveDef();
    var [x, y] = this.invertCor(xCor, yCor);

    moveDef.fly.forEach((def) => {
      var [defX, defY] = def;
      var dx, dy;

      dx = x + defX;
      dy = y + defY;

      var piece = this.findPiece(dx, dy);

      while (piece) {
        piece.movable = true;
        dx = dx + defX;
        dy = dy + defY;

        piece = this.findPiece(dx, dy);

        if (piece && piece.type !== '*') {
          piece.movable = true;
          break;
        }
      }
    });
  }

  transposeToCorX(xIndex) {
    return 10 - xIndex - 1;
  }

  transposeToCorY(yIndex) {
    return yIndex + 1;
  }

  invertToIndexX(xCor) {
    return 9 - xCor;
  }

  invertToIndexY(yCor) {
    return yCor - 1;
  }

  invertCor(xCor, yCor) {
    return [this.invertToIndexX(xCor), this.invertToIndexY(yCor)];
  }

  findPiece(xIndex, yIndex) {
    var row = this.board[yIndex];
    return row ? row[xIndex] : undefined;
  }

  fetchPiece(piece) {
    var [toCorX, toCorY] = [piece.x, piece.y];
    var [toIdxX, toIdxY] = this.invertCor(toCorX, toCorY);
    return this.findPiece(toIdxX, toIdxY);
  }

  toArray() {
    return this.board.map((row) => {
      return row.map((piece) => {
        return piece.type;
      });
    });
  }
};
<|endoftext|>


<commit_before>describe('Output', function() {

  beforeEach("Enable WebMidi.js", function (done) {

    WebMidi.disable();

    WebMidi.enable(function() {

      if (WebMidi.outputs.length > 0) {
        done();
      } else {

        // Calling this.skip() throws an error. We catch it so it does not show up in the console
        try {
          this.skip();
        } catch (err) {
          // console.warn(err.message)
        }

      }

    }.bind(this));

  });

  describe('decrementRegisteredParameter()', function () {

    it("should throw error if registered parameter is invalid", function() {

      expect(function () {
        WebMidi.outputs[0].decrementRegisteredParameter(0);
      }).to.throw(TypeError);

      expect(function () {
        WebMidi.outputs[0].decrementRegisteredParameter('xxx');
      }).to.throw(TypeError);

    });

    // it("should call send the right amount of times", function() {
    //
    //   var spy = sinon.spy(WebMidi.outputs[0], "send");
    //
    //   // expect(function () {
    //     WebMidi.outputs[0].decrementRegisteredParameter('pitchbendrange', 1);
    //   // }).to.throw(RangeError);
    //
    //   expect(spy.callCount).to.equal(2);
    //   spy.restore(WebMidi, "send");
    //
    // });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].decrementRegisteredParameter("pitchbendrange")
      ).to.equal(WebMidi.outputs[0]);
    });

    // it("should throw error if options.time is invalid", function(done) {
    //
    // });

  });

  describe('incrementRegisteredParameter()', function () {

    it("should throw error if registered parameter is invalid", function() {

      expect(function () {
        WebMidi.outputs[0].incrementRegisteredParameter(0);
      }).to.throw(Error);

      expect(function () {
        WebMidi.outputs[0].incrementRegisteredParameter('xxx');
      }).to.throw(Error);

    });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].incrementRegisteredParameter("pitchbendrange")
      ).to.equal(WebMidi.outputs[0]);
    });

    // it("should throw error if options.time is invalid", function(done) {
    //
    //   WebMidi.enable(function() {
    //
    //     expect(function () {
    //       WebMidi.outputs[0].decrementRegisteredParameter('pitchbendrange', 1, {time: 'abc'});
    //     }).to.throw(TypeError);
    //
    //     expect(function () {
    //       WebMidi.outputs[0].decrementRegisteredParameter('pitchbendrange', 1, {time: '+abc'});
    //     }).to.throw(TypeError);
    //
    //     done();
    //
    //   });
    //
    // });

  });

  describe('playNote()', function () {

    it("should throw error if note is invalid", function() {

      ["Z-8", "R22", -1, 128, undefined, null, function() {}, ["x"]].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].playNote(param);
        }).to.throw(Error);
      });

    });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].playNote(64)
      ).to.equal(WebMidi.outputs[0]);
    });

    // it("should throw error if options.time is invalid", function(done) {
    //
    // });

  });

  describe('send()', function () {

    it("should throw error if status byte is invalid", function() {

      ["xxx", [], NaN, 127, 256, undefined, null, -1, 0, {}].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].send(param);
        }).to.throw(RangeError);
      });

    });

    it("should throw error if data bytes are invalid", function() {

      ["xxx", -1, 256, NaN, null, Infinity].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].send(64, param);
        }).to.throw(RangeError);
      });

    });

    it("should throw error if message is incomplete", function() {

      [0x80, 0x90, 0xA0].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].send(param, []);
        }).to.throw(TypeError);
      });

    });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].send(144, [64, 64])
      ).to.equal(WebMidi.outputs[0]);
    });

  });

  describe('sendActiveSensing()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendActiveSensing()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe('sendChannelAftertouch()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendChannelAftertouch()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe('sendChannelMode()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendChannelMode("allsoundoff")).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if value is out of range", function() {

      [-1, 128].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].sendChannelMode("localcontrol", param);
        }).to.throw(Error);
      });

    });

  });

  describe('sendClock()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendClock()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe('sendContinue()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendContinue()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe('sendControlChange()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendControlChange("brightness", 0)).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if value is out of range", function() {

      [-1, 120, "xxx"].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].sendControlChange("bankselectcoarse", param);
        }).to.throw(Error);
      });

    });

  });

  describe('sendKeyAftertouch()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendKeyAftertouch("C#3", 1)).to.equal(WebMidi.outputs[0]);
    });

  });

  describe('sendPitchBend()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendPitchBend(0.75)).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if bend value is out of range", function() {

      [-2, 17, NaN, Infinity].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].sendPitchBend(param);
        }).to.throw(Error);
      });

    });

  });

  describe('sendSysex()', function () {

    it("should return the Output object for method chaining");

    it("should throw an error if a data value is out of rangte");

  });

  describe('setTuningProgram()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].setTuningProgram(64, 1)).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if value is out of bounds", function() {

      [-1, 128, Infinity, NaN, -Infinity].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].setTuningProgram(param, 1);
        }).to.throw(RangeError);
      });

    });

  });

  describe('stopNote()', function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].stopNote(64)).to.equal(WebMidi.outputs[0]);
    });

  });

});
<commit_msg>Standardize on double-quoted strings<commit_after>describe("Output", function() {

  beforeEach("Enable WebMidi.js", function (done) {

    WebMidi.disable();

    WebMidi.enable(function() {

      if (WebMidi.outputs.length > 0) {
        done();
      } else {

        // Calling this.skip() throws an error. We catch it so it does not show up in the console
        try {
          this.skip();
        } catch (err) {
          // console.warn(err.message)
        }

      }

    }.bind(this));

  });

  describe("decrementRegisteredParameter()", function () {

    it("should throw error if registered parameter is invalid", function() {

      expect(function () {
        WebMidi.outputs[0].decrementRegisteredParameter(0);
      }).to.throw(TypeError);

      expect(function () {
        WebMidi.outputs[0].decrementRegisteredParameter("xxx");
      }).to.throw(TypeError);

    });

    // it("should call send the right amount of times", function() {
    //
    //   var spy = sinon.spy(WebMidi.outputs[0], "send");
    //
    //   // expect(function () {
    //     WebMidi.outputs[0].decrementRegisteredParameter("pitchbendrange", 1);
    //   // }).to.throw(RangeError);
    //
    //   expect(spy.callCount).to.equal(2);
    //   spy.restore(WebMidi, "send");
    //
    // });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].decrementRegisteredParameter("pitchbendrange")
      ).to.equal(WebMidi.outputs[0]);
    });

    // it("should throw error if options.time is invalid", function(done) {
    //
    // });

  });

  describe("incrementRegisteredParameter()", function () {

    it("should throw error if registered parameter is invalid", function() {

      expect(function () {
        WebMidi.outputs[0].incrementRegisteredParameter(0);
      }).to.throw(Error);

      expect(function () {
        WebMidi.outputs[0].incrementRegisteredParameter("xxx");
      }).to.throw(Error);

    });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].incrementRegisteredParameter("pitchbendrange")
      ).to.equal(WebMidi.outputs[0]);
    });

    // it("should throw error if options.time is invalid", function(done) {
    //
    //   WebMidi.enable(function() {
    //
    //     expect(function () {
    //       WebMidi.outputs[0].decrementRegisteredParameter("pitchbendrange", 1, {time: "abc"});
    //     }).to.throw(TypeError);
    //
    //     expect(function () {
    //       WebMidi.outputs[0].decrementRegisteredParameter("pitchbendrange", 1, {time: "+abc"});
    //     }).to.throw(TypeError);
    //
    //     done();
    //
    //   });
    //
    // });

  });

  describe("playNote()", function () {

    it("should throw error if note is invalid", function() {

      ["Z-8", "R22", -1, 128, undefined, null, function() {}, ["x"]].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].playNote(param);
        }).to.throw(Error);
      });

    });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].playNote(64)
      ).to.equal(WebMidi.outputs[0]);
    });

    // it("should throw error if options.time is invalid", function(done) {
    //
    // });

  });

  describe("send()", function () {

    it("should throw error if status byte is invalid", function() {

      ["xxx", [], NaN, 127, 256, undefined, null, -1, 0, {}].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].send(param);
        }).to.throw(RangeError);
      });

    });

    it("should throw error if data bytes are invalid", function() {

      ["xxx", -1, 256, NaN, null, Infinity].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].send(64, param);
        }).to.throw(RangeError);
      });

    });

    it("should throw error if message is incomplete", function() {

      [0x80, 0x90, 0xA0].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].send(param, []);
        }).to.throw(TypeError);
      });

    });

    it("should return the Output object for method chaining", function() {
      expect(
        WebMidi.outputs[0].send(144, [64, 64])
      ).to.equal(WebMidi.outputs[0]);
    });

  });

  describe("sendActiveSensing()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendActiveSensing()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe("sendChannelAftertouch()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendChannelAftertouch()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe("sendChannelMode()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendChannelMode("allsoundoff")).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if value is out of range", function() {

      [-1, 128].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].sendChannelMode("localcontrol", param);
        }).to.throw(Error);
      });

    });

  });

  describe("sendClock()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendClock()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe("sendContinue()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendContinue()).to.equal(WebMidi.outputs[0]);
    });

  });

  describe("sendControlChange()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendControlChange("brightness", 0)).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if value is out of range", function() {

      [-1, 120, "xxx"].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].sendControlChange("bankselectcoarse", param);
        }).to.throw(Error);
      });

    });

  });

  describe("sendKeyAftertouch()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendKeyAftertouch("C#3", 1)).to.equal(WebMidi.outputs[0]);
    });

  });

  describe("sendPitchBend()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].sendPitchBend(0.75)).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if bend value is out of range", function() {

      [-2, 17, NaN, Infinity].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].sendPitchBend(param);
        }).to.throw(Error);
      });

    });

  });

  describe("sendSysex()", function () {

    it("should return the Output object for method chaining");

    it("should throw an error if a data value is out of rangte");

  });

  describe("setTuningProgram()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].setTuningProgram(64, 1)).to.equal(WebMidi.outputs[0]);
    });

    it("should throw an error if value is out of bounds", function() {

      [-1, 128, Infinity, NaN, -Infinity].forEach(function (param) {
        expect(function () {
          WebMidi.outputs[0].setTuningProgram(param, 1);
        }).to.throw(RangeError);
      });

    });

  });

  describe("stopNote()", function () {

    it("should return the Output object for method chaining", function() {
      expect(WebMidi.outputs[0].stopNote(64)).to.equal(WebMidi.outputs[0]);
    });

  });

});
<|endoftext|>


<commit_before>'use strict';

var app = function() {
  function _init() {
    $(document).foundation();
  }

  return {
    init: _init
  };
};

$(document).ready(function() {
  app.init();
});
<commit_msg>fixed app.js<commit_after>/* globals $, document */
'use strict';

var app = (function() {
  function _init() {
    $(document).foundation();
  }

  return {
    init: _init
  };
})();

$(document).ready(function() {
  app.init();
});
<|endoftext|>