<commit_before>const config = require('./config');

const port = config.common.api.port || 8080;

module.exports = {
  openapi: '3.0.1',
  info: {
    version: '0.1.0',
    title: '<%= projectName %>',
    description: '<%= projectDescription %>',
    termsOfService: '',
    contact: {
      name: 'Wolox',
      email: 'tls@wolox.com.ar',
      url: 'https://www.wolox.com.ar/'
    },
    license: {
      name: 'MIT'
    }
  },
  servers: [
    {
      url: `http://localhost:${port}/`,
      description: 'Local server'
    },
    {
      url: 'https://api_url_testing',
      description: 'Testing server'
    }
  ],
  security: [],
  tags: [
    {
      name: 'CRUD operations'
    }
  ],
  paths: {
    '/users': {
      get: {
        tags: ['CRUD operations'],
        description: 'Get users',
        operationId: 'getUsers',
        parameters: [
          {
            name: 'page',
            in: 'query',
            schema: {
              type: 'integer',
              default: 1
            },
            required: false
          }
        ],
        responses: {
          '200': {
            description: 'Users were obtained',
            content: {
              'application/json': {
                schema: {
                  $ref: '#/components/schemas/Users'
                }
              }
            }
          }
        }
      }
    }
  },
  components: {
    schemas: {
      userId: {
        type: 'integer',
        example: 7
      },
      username: {
        type: 'string',
        example: 'tom99'
      },
      userEmail: {
        type: 'string',
        example: 'tom.engels@wolox.com.ar'
      },
      User: {
        type: 'object',
        properties: {
          id: {
            $ref: '#/components/schemas/userId'
          },
          username: {
            $ref: '#/components/schemas/username'
          },
          email: {
            $ref: '#/components/schemas/userEmail'
          },
        }
      },
      Users: {
        type: 'object',
        properties: {
          users: {
            type: 'array',
            items: {
              $ref: '#/components/schemas/User'
            }
          }
        }
      }
    }
  }
};
  <commit_msg>adding security schemes<commit_after>const config = require('./config');

const port = config.common.api.port || 8080;

module.exports = {
  openapi: '3.0.1',
  info: {
    version: '0.1.0',
    title: '<%= projectName %>',
    description: '<%= projectDescription %>',
    termsOfService: '',
    contact: {
      name: 'Wolox',
      email: 'tls@wolox.com.ar',
      url: 'https://www.wolox.com.ar/'
    },
    license: {
      name: 'MIT'
    }
  },
  servers: [
    {
      url: `http://localhost:${port}/`,
      description: 'Local server'
    },
    {
      url: 'https://api_url_testing',
      description: 'Testing server'
    }
  ],
  security: [],
  tags: [
    {
      name: 'CRUD operations'
    }
  ],
  paths: {
    '/users': {
      get: {
        tags: ['CRUD operations'],
        description: 'Get users',
        operationId: 'getUsers',
        parameters: [
          {
            name: 'page',
            in: 'query',
            schema: {
              type: 'integer',
              default: 1
            },
            required: false
          }
        ],
        responses: {
          '200': {
            description: 'Users were obtained',
            content: {
              'application/json': {
                schema: {
                  $ref: '#/components/schemas/Users'
                }
              }
            }
          }
        }
      }
    }
  },
  components: {
    schemas: {
      userId: {
        type: 'integer',
        example: 7
      },
      username: {
        type: 'string',
        example: 'tom99'
      },
      userEmail: {
        type: 'string',
        example: 'tom.engels@wolox.com.ar'
      },
      User: {
        type: 'object',
        properties: {
          id: {
            $ref: '#/components/schemas/userId'
          },
          username: {
            $ref: '#/components/schemas/username'
          },
          email: {
            $ref: '#/components/schemas/userEmail'
          },
        }
      },
      Users: {
        type: 'object',
        properties: {
          users: {
            type: 'array',
            items: {
              $ref: '#/components/schemas/User'
            }
          }
        }
      }
    },
    securitySchemes: {}
  }
};
  <|endoftext|>


<commit_before>import { Platform } from 'react-native';

const navbarOffset = Platform.OS ? 20 : 0 === 'ios';
const navbarBaseHeight = Platform.OS ? 44 : 54 === 'ios';

export const appStyle = {
  navbar: {
    offset: navbarOffset,
    baseHeight: navbarBaseHeight,
    height: navbarBaseHeight + navbarOffset,
  },
  font: {
    fontSize: {
      small: 11,
      default: 13,
      big: 15,
      large: 17,
      huge: 20,
    },
  },
  colors: {
    primary: '#05A5D1',
    lightText: '#FAFAFA',
    background: '#F5FCFF',
  },
  margins: {
    inner: 10,
    outer: 25,
  },
  dimensions: {
    touchableHeight: 48,
    visibleButtonHeight: 36,
  },
};

export default appStyle;
<commit_msg>Fix platform ternary<commit_after>import { Platform } from 'react-native';

const navbarOffset = Platform.OS === 'ios' ? 20 : 0;
const navbarBaseHeight = Platform.OS === 'ios' ? 44 : 54;

export const appStyle = {
  navbar: {
    offset: navbarOffset,
    baseHeight: navbarBaseHeight,
    height: navbarBaseHeight + navbarOffset,
  },
  font: {
    fontSize: {
      small: 11,
      default: 13,
      big: 15,
      large: 17,
      huge: 20,
    },
  },
  colors: {
    primary: '#05A5D1',
    lightText: '#FAFAFA',
    background: '#F5FCFF',
  },
  margins: {
    inner: 10,
    outer: 25,
  },
  dimensions: {
    touchableHeight: 48,
    visibleButtonHeight: 36,
  },
};

export default appStyle;
<|endoftext|>


<commit_before>import syllable from 'syllable';
import _ from 'lodash';
import wordnet from 'wordnet';
var $ = require('jquery-deferred');
import stopwords from './data/stopwords.js';
import descriptors from './data/descriptors.js';
import cusseth from './data/cusseth.js';
import nouns from './data/nouns.js';
import thesaurus from './data/thesaurus.js';

let adjectives = descriptors.map(word => [word, syllable(word)]);
let curses = cusseth.map(word => [word, syllable(word)]);

const HAIKU_LENGTH = 17;
const separator = '//';
const FOUL = false;

// Chrys' Domain
function addModifier(phrase, length, mod) {
  let tokens = phrase.split(/\W/);
  let nounList = tokens.map(word => _.contains(nouns, word));

  for (var i in nounList) {
    if (nounList[i]) {
      tokens.splice(i, 0, mod);
      return tokens.join(' ');
    }
  }

  return mod + ' ' + phrase;
}

export function addExpletive(phrase, length) {
  var curse = _.sample(curses.filter(tuple => tuple[1] === length));
  if (!curse) {
    return addExpletive(addExpletive(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, curse[0]);
}

export function addAdjective(phrase, length) {
  var adj = _.sample(adjectives.filter(tuple => tuple[1] === length));
  if (!adj) {
    return addAdjective(addAdjective(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, adj[0]);
}

export function removeWords(phrase, length) {
  length *= -1;
  let tokens = phrase.split(/\W/);
  let newTokens = [];
  tokens.forEach(function(token) {
    if (length && _.contains(stopwords, token)) {
      length -= syllable(token);
    } else {
      newTokens.push(token);
    }
  });

  return newTokens.join(' ');
}

function addWords(phrase, length) {
  if (FOUL) {
    return addExpletive(phrase, length);
  } else {
    return addAdjective(phrase, length);
  }
}

// Nicole WUZ HERE
export function shortenWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);

  adjustment = -adjustment;

  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)) {
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);

    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    }

    else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables > adjustment) && (synonym[1] < currentWordSyllables)).sort(function(a, b) {return a[1]-b[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }

}

function possibleSynonymArray(word) {
  if (thesaurus[word]) {
    return thesaurus[word];
  }
}

function possibleSynonymArrayAsync(word) {
  var promise = $.Deferred();

  var possibleNewWords = [];
  wordnet.lookup(word, function(err, definitions) {
    if (definitions) {
      definitions.forEach(function(definition) {
        var words = definition.meta.words;
        words.forEach(function(word) {
          if (!_.includes(possibleNewWords, word.word)) {
            possibleNewWords.push(word.word);
          }
        });
      });
    }
    promise.resolve(possibleNewWords);
  });
  return promise;
}

export function expandWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);
  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)){
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);
    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    } else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables < adjustment) && (synonym[1] > currentWordSyllables)).sort(function(a, b) {return b[1]-a[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }
}

let countSyllables = function(phrase) {
  let tokens = phrase.split(/\W/);
  return _.sum(tokens.map(syllable));
};

function adjustWord(word, adjustment) {
  if (adjustment > 0) {
    return expandWord(word, adjustment);
  } else if (adjustment < 0) {
    return shortenWord(word, adjustment);
  } else {
    return word;
  }
}

export function adjustPhrase(phrase, adjustment) {
  if (adjustment > 0) {
    return addWords(phrase, adjustment);
  } else if (adjustment < 0) {
    return removeWords(phrase, adjustment);
  } else {
    return phrase;
  }
}

function adjustSyllables(lines, adjustment) {
  let line = 0;
  let idx = 0;
  let token = lines[line][idx];

  // First loop to make small adjustments to existing words' lengths.
  while (adjustment !== 0 && line < 3) {
    let newWord = adjustWord(token, adjustment);
    console.log(newWord);

    if (newWord) {
      lines[line][idx] = newWord;
      adjustment -= (syllable(newWord) - syllable(token));
    }

    idx++;
    token = lines[line][idx];
    if (!token) {
      line++;
      idx = 0;
      if (line > 2) {
        break;
      }
      token = lines[line][idx];

    }
  }

  var joined = lines.map(line => line.join(' '));
  line = 0;
  console.log(adjustment);

  // Second while loop to add / remove extraneous words
  while (adjustment !== 0 && line < 3) {
    let oldPhrase = joined[line];
    let lineCount = countSyllables(oldPhrase);

    if (lineCount === (line === 1 ? 7 : 5)) {
      line++;
    } else {
      var newPhrase;
      var maxLineAdjustment = (line === 1) ? 7 : 5;
      var lineAdjustment;

      if (adjustment < 0) {
        maxLineAdjustment *= -1;
        lineAdjustment = adjustment < maxLineAdjustment ?  maxLineAdjustment : adjustment;
        // lineAdjustment += lineCount;
      } else if (adjustment > 0) {
        console.log(maxLineAdjustment);
        lineAdjustment = adjustment > maxLineAdjustment ? maxLineAdjustment : adjustment;
        lineAdjustment -= lineCount;
      }

      console.log(oldPhrase, adjustment, lineAdjustment);

      newPhrase = adjustPhrase(oldPhrase, lineAdjustment);

      joined[line] = newPhrase;
      adjustment -= (countSyllables(newPhrase) - countSyllables(oldPhrase));
      line++;
    }

  }

  return joined.join(' ' + separator + ' ');
}

export function isHaiku(msg) {
  return countSyllables(msg, separator) === HAIKU_LENGTH;
}

export function breakIntoHaiku(msg) {
  var tokens = msg.trim().split(/\W/);
  var rows = [[], [], []];
  var rowSyllables = 0;
  var line = 0;
  while (tokens.length) {
    let token = tokens.shift();
    let tokenLength = syllable(token);

    if (line === 0) {
      var diff = (rowSyllables + tokenLength) - 5;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    } else if (line === 1) {

      var diff = (rowSyllables + tokenLength) - 7;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    }

    rowSyllables += tokenLength;
    rows[line].push(token);

  }

  return rows;
}

/**
 * steps to check if it is a haiku
 * 1. check syllable length of commit
 * 2. if longer - > check for haikus in commit..
 *  a) if haiku -> print done !
 *  b) if not -> get most of haiku and continue? choose key words and continue?
 * 3. if shorter -> check syllable counts?
 * for what is missing -> fill in rhyme etc. to make up length ?? nonsensical ??
 */
 export function makeHaiku(msg) {
  let syllables = countSyllables(msg);
  let difference = HAIKU_LENGTH - syllables;

  msg = breakIntoHaiku(msg);
  return adjustSyllables(msg, difference);
}<commit_msg>added new feature // for my convertible // incorrigible<commit_after>import syllable from 'syllable';
import _ from 'lodash';
import wordnet from 'wordnet';
var $ = require('jquery-deferred');
import stopwords from './data/stopwords.js';
import descriptors from './data/descriptors.js';
import cusseth from './data/cusseth.js';
import nouns from './data/nouns.js';
import thesaurus from './data/thesaurus.js';

let adjectives = descriptors.map(word => [word, syllable(word)]);
let curses = cusseth.map(word => [word, syllable(word)]);

const HAIKU_LENGTH = 17;
const separator = '//';
const FOUL = false;

// Chrys' Domain
function addModifier(phrase, length, mod) {
  let tokens = phrase.split(/\W/);
  let nounList = tokens.map(word => _.contains(nouns, word));

  for (var i in nounList) {
    if (nounList[i]) {
      tokens.splice(i, 0, mod);
      return tokens.join(' ');
    }
  }

  return mod + ' ' + phrase;
}

export function addExpletive(phrase, length) {
  var curse = _.sample(curses.filter(tuple => tuple[1] === length));
  if (!curse) {
    return addExpletive(addExpletive(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, curse[0]);
}

export function addAdjective(phrase, length) {
  var adj = _.sample(adjectives.filter(tuple => tuple[1] === length));
  if (!adj) {
    return addAdjective(addAdjective(phrase, length - 1), 1);
  }

  return addModifier(phrase, length, adj[0]);
}

export function removeWords(phrase, length) {
  length *= -1;
  let tokens = phrase.split(/\W/);
  let newTokens = [];
  tokens.forEach(function(token) {
    if (length && _.contains(stopwords, token)) {
      length -= syllable(token);
    } else {
      newTokens.push(token);
    }
  });

  return newTokens.join(' ');
}

function addWords(phrase, length) {
  if (FOUL) {
    return addExpletive(phrase, length);
  } else {
    return addAdjective(phrase, length);
  }
}

// Nicole WUZ HERE
export function shortenWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);

  adjustment = -adjustment;

  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)) {
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);

    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    }

    else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables > adjustment) && (synonym[1] < currentWordSyllables)).sort(function(a, b) {return a[1]-b[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }

}

function possibleSynonymArray(word) {
  if (thesaurus[word]) {
    return thesaurus[word];
  }
}

function possibleSynonymArrayAsync(word) {
  var promise = $.Deferred();

  var possibleNewWords = [];
  wordnet.lookup(word, function(err, definitions) {
    if (definitions) {
      definitions.forEach(function(definition) {
        var words = definition.meta.words;
        words.forEach(function(word) {
          if (!_.includes(possibleNewWords, word.word)) {
            possibleNewWords.push(word.word);
          }
        });
      });
    }
    promise.resolve(possibleNewWords);
  });
  return promise;
}

export function expandWord(word, adjustment) {
  let possibleNewWord = [];
  let theNewWord;
  let newWordSyllables;
  let adjustedList;
  let otheradjustednotasgoodList;
  let currentWordSyllables = syllable(word);
  let list = []

  var response = possibleSynonymArray(word);

  if (!_.isEmpty(response)){
    for (let x=0; x<response.length; x++) {
      list[x] = [response[x], syllable(response[x])]
    }

    adjustedList = list.filter(synonym => synonym[1] - currentWordSyllables === adjustment);
    if (!_.isEmpty(adjustedList)) {
      return adjustedList[0][0];
    } else {
      otheradjustednotasgoodList = list.filter(synonym => (synonym[1] - currentWordSyllables < adjustment) && (synonym[1] > currentWordSyllables)).sort(function(a, b) {return b[1]-a[1]});
    }

    if (!_.isEmpty(otheradjustednotasgoodList)) {
      return otheradjustednotasgoodList[0][0]
    } else {
      return word;
    }
  } else {
    return word;
  }
}

let countSyllables = function(phrase) {
  let tokens = phrase.split(/\W/);
  return _.sum(tokens.map(syllable));
};

function adjustWord(word, adjustment) {
  if (adjustment > 0) {
    return expandWord(word, adjustment);
  } else if (adjustment < 0) {
    return shortenWord(word, adjustment);
  } else {
    return word;
  }
}

export function adjustPhrase(phrase, adjustment) {
  if (adjustment > 0) {
    return addWords(phrase, adjustment);
  } else if (adjustment < 0) {
    return removeWords(phrase, adjustment);
  } else {
    return phrase;
  }
}

function adjustSyllables(lines, adjustment) {
  let line = 0;
  let idx = 0;
  let token = lines[line][idx];

  // First loop to make small adjustments to existing words' lengths.
  while (adjustment !== 0 && line < 3) {
    let newWord = adjustWord(token, adjustment);
    console.log(newWord);

    if (newWord) {
      lines[line][idx] = newWord;
      adjustment -= (syllable(newWord) - syllable(token));
    }

    idx++;
    token = lines[line][idx];
    if (!token) {
      line++;
      idx = 0;
      if (line > 2) {
        break;
      }
      token = lines[line][idx];

    }
  }

  var joined = lines.map(line => line.join(' '));
  line = 0;
  console.log(adjustment);

  // Second while loop to add / remove extraneous words
  while (adjustment !== 0 && line < 3) {
    let oldPhrase = joined[line];
    let lineCount = countSyllables(oldPhrase);

    if (lineCount === (line === 1 ? 7 : 5)) {
      line++;
    } else {
      var newPhrase;
      var maxLineAdjustment = (line === 1) ? 7 : 5;
      var lineAdjustment;

      if (adjustment < 0) {
        maxLineAdjustment *= -1;
        lineAdjustment = adjustment < maxLineAdjustment ?  maxLineAdjustment : adjustment;
        // lineAdjustment += lineCount;
      } else if (adjustment > 0) {
        console.log(maxLineAdjustment, lineCount);
        lineAdjustment = adjustment > maxLineAdjustment ? maxLineAdjustment : adjustment;
        lineAdjustment -= lineCount;
      }

      console.log(oldPhrase, adjustment, lineAdjustment);

      newPhrase = adjustPhrase(oldPhrase, lineAdjustment);

      joined[line] = newPhrase;
      adjustment -= (countSyllables(newPhrase) - countSyllables(oldPhrase));
      line++;
    }

  }

  return joined.join(' ' + separator + ' ');
}

export function isHaiku(msg) {
  return countSyllables(msg, separator) === HAIKU_LENGTH;
}

export function breakIntoHaiku(msg) {
  var tokens = msg.trim().split(/\W/);
  var rows = [[], [], []];
  var rowSyllables = 0;
  var line = 0;
  while (tokens.length) {
    let token = tokens.shift();
    let tokenLength = syllable(token);

    if (line === 0) {
      var diff = (rowSyllables + tokenLength) - 5;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    } else if (line === 1) {

      var diff = (rowSyllables + tokenLength) - 7;
      if (diff > 0) {
        line += 1;
        rowSyllables = 0;
      }

    }

    rowSyllables += tokenLength;
    rows[line].push(token);

  }

  return rows;
}

/**
 * steps to check if it is a haiku
 * 1. check syllable length of commit
 * 2. if longer - > check for haikus in commit..
 *  a) if haiku -> print done !
 *  b) if not -> get most of haiku and continue? choose key words and continue?
 * 3. if shorter -> check syllable counts?
 * for what is missing -> fill in rhyme etc. to make up length ?? nonsensical ??
 */
 export function makeHaiku(msg) {
  let syllables = countSyllables(msg);
  let difference = HAIKU_LENGTH - syllables;

  msg = breakIntoHaiku(msg);
  return adjustSyllables(msg, difference);
}<|endoftext|>


<commit_before>// https://github.com/MohammadYounes/grunt-rtlcss
module.exports = {
	options: {
		swapLeftRightInUrl: false,
		swapLtrRtlInUrl: false,
		autoRename: false,
		preserveDirectives: true
	},
	plugin: {
		expand: true,
		cwd: '<%= paths.tmp %>',
		src: [
			'*.css',
			'!*.min.css'
		],
		dest: '<%= paths.tmp %>',
		ext: '.css',
		extDot: 'last'
	}
};
<commit_msg>Sigh...<commit_after>// https://github.com/MohammadYounes/grunt-rtlcss
module.exports = {
	options: {
		swapLeftRightInUrl: false,
		swapLtrRtlInUrl: false,
		autoRename: false,
		preserveDirectives: true
	},
	plugin: {
		expand: true,
		cwd: '<%= paths.tmp %>',
		src: [
			'*.css',
			'!*.rtl.css',
			'!*.min.css'
		],
		dest: '<%= paths.tmp %>',
		ext: '-rtl.css',
		extDot: 'last'
	}
};
<|endoftext|>


<commit_before>/// hashmap.js --- Simple hash-map implementation
//
// Copyright (c) 2012 Quildreen Motta
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/// Module khaos.collection.structs.hashmap

var Base = require('boo').Base
var map  = require('../map')

function traversable_p(subject) {
  return subject
  &&     typeof subject.each == 'function' }

module.exports = Base.derive({
  init:
  function _init(dictionary) {
    this._key_prefix = '@'
    this._dictionary = {}
    this.update(dictionary)
    return this }

, each:
  function _each(iterator) {
    var self = this
    map.each(this._dictionary, function(value, key) {
                                 iterator(value, key.slice(1), self) })
    return this }

, put:
  function _put(key, value) {
    this._dictionary[this._key_prefix + key] = value
    return this }

, remove:
  function _remove(key) {
    delete this._dictionary[this._key_prefix + key]
    return this }

, replace:
  function _replace(value, replacement) {
    map.replace(this._dictionary, value, replacement)
    return this }

, update:
  function _update(dictionary) {
    var self    = this
    var fix_key = key_mapping(Object(dictionary))

      traversable_p(dictionary)?  dictionary.each(import_data)
    : /* otherwise */             map.each(dictionary, import_data)

    function import_data(value, key, map) { self.put(fix_key(key), value) }
    function key_mapping(map) {
      return '_key_prefix' in map? function(key){ return key.slice(map._key_prefix.length) }
      :      /* otherwise */       function(key){ return key                               }}

    return this }

, clear:
  function _clear() {
    map.clear(this._dictionary)
    return this }

, at:
  function _at(key, _default) {
    return map.at(this._dictionary, this._key_prefix + key, _default) }

, size:
  function _size() {
    return map.size(this._dictionary) }

, empty_p:
  function _empty_p() {
    return map.empty_p(this._dictionary) }

, has_key_p:
  function _has_key_p(key) {
    return map.has_key_p(this._dictionary, this._key_prefix + key) }

, keys:
  function _keys() {
    return map.keys(this._dictionary)
              .map(function(key) { return key.slice(1) }) }

, values:
  function _values() {
    return map.values(this._dictionary) }

, items:
  function _items() {
    return this.reduce([], function(result, item, key) {
                             result.push([key, item])
                             return result })}

, reduce:
  function _reduce(value, folder) {
    var self = this
    return map.reduce(this._dictionary, value, function(result, value, key) {
                                                 return folder(result, value, key.slice(1), self) })}

, every:
  function _every(predicate) {
    var self = this
    return map.every(this._dictionary, function(value, key) {
                                         return predicate(value, key.slice(1), self) })}

, some:
  function _some(predicate) {
    var self = this
    return map.some(this._dictionary, function(value, key) {
                                        return predicate(value, key.slice(1), self) })}

, filter:
  function _filter(predicate) {
    var self = this
    this._dictionary = map.filter(this._dictionary, function(value, key) {
                                                      return predicate(value, key.slice(1), self) })
    return this }

, map:
  function _map(mapper) {
    var self = this
    this._dictionary = map.map(this._dictionary, function(value, key) {
                                                   return mapper(value, key.slice(1), self) })
    return this }
})<commit_msg>Uses `_key_prefix' for key slicing.<commit_after>/// hashmap.js --- Simple hash-map implementation
//
// Copyright (c) 2012 Quildreen Motta
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software,
// and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

/// Module khaos.collection.structs.hashmap

var Base = require('boo').Base
var map  = require('../map')

function traversable_p(subject) {
  return subject
  &&     typeof subject.each == 'function' }

module.exports = Base.derive({
  init:
  function _init(dictionary) {
    this._key_prefix = '@'
    this._dictionary = {}
    this.update(dictionary)
    return this }

, each:
  function _each(iterator) {
    var self = this
    map.each(this._dictionary, function(value, key) {
                                 iterator( value
                                         , key.slice(this._key_prefix.length)
                                         , self) })
    return this }

, put:
  function _put(key, value) {
    this._dictionary[this._key_prefix + key] = value
    return this }

, remove:
  function _remove(key) {
    delete this._dictionary[this._key_prefix + key]
    return this }

, replace:
  function _replace(value, replacement) {
    map.replace(this._dictionary, value, replacement)
    return this }

, update:
  function _update(dictionary) {
    var self    = this
    var fix_key = key_mapping(Object(dictionary))

      traversable_p(dictionary)?  dictionary.each(import_data)
    : /* otherwise */             map.each(dictionary, import_data)

    function import_data(value, key, map) { self.put(fix_key(key), value) }
    function key_mapping(map) {
      return '_key_prefix' in map? function(key){ return key.slice(map._key_prefix.length) }
      :      /* otherwise */       function(key){ return key                               }}

    return this }

, clear:
  function _clear() {
    map.clear(this._dictionary)
    return this }

, at:
  function _at(key, _default) {
    return map.at(this._dictionary, this._key_prefix + key, _default) }

, size:
  function _size() {
    return map.size(this._dictionary) }

, empty_p:
  function _empty_p() {
    return map.empty_p(this._dictionary) }

, has_key_p:
  function _has_key_p(key) {
    return map.has_key_p(this._dictionary, this._key_prefix + key) }

, keys:
  function _keys() {
    return map.keys(this._dictionary)
              .map(function(key) { return key.slice(this._key_prefix.length) }) }

, values:
  function _values() {
    return map.values(this._dictionary) }

, items:
  function _items() {
    return this.reduce([], function(result, item, key) {
                             result.push([key, item])
                             return result })}

, reduce:
  function _reduce(value, folder) {
    var self = this
    return map.reduce(this._dictionary, value, function(result, value, key) {
                                                 return folder( result
                                                              , value
                                                              , key.slice(this._key_prefix.length)
                                                              , self) })}

, every:
  function _every(predicate) {
    var self = this
    return map.every(this._dictionary, function(value, key) {
                                         return predicate( value
                                                         , key.slice(this._key_prefix.length)
                                                         , self) })}

, some:
  function _some(predicate) {
    var self = this
    return map.some(this._dictionary, function(value, key) {
                                        return predicate( value
                                                        , key.slice(this._key_prefix.length)
                                                        , self) })}

, filter:
  function _filter(predicate) {
    var self = this
    this._dictionary = map.filter(this._dictionary, function(value, key) {
                                                      return predicate( value
                                                                      , key.slice(this._key_prefix.length)
                                                                      , self) })
    return this }

, map:
  function _map(mapper) {
    var self = this
    this._dictionary = map.map(this._dictionary, function(value, key) {
                                                   return mapper( value
                                                                , key.slice(this._key_prefix.length)
                                                                , self) })
    return this }
})<|endoftext|>


<commit_before>let debug             = require('debug')('purge-cache');
let assert            = require('assert');
let path              = require('path');
let _                 = require('lodash');
let config            = require('typed-env-config');
let loader            = require('taskcluster-lib-loader');
let monitor           = require('taskcluster-lib-monitor');
let validate          = require('taskcluster-lib-validate');
let server            = require('taskcluster-lib-app');
let docs              = require('taskcluster-lib-docs');
let taskcluster       = require('taskcluster-client');
let api               = require('./api');
let exchanges         = require('./exchanges');
let data              = require('./data');

let load = loader({
  cfg: {
    requires: ['profile'],
    setup: ({profile}) => config({profile}),
  },
  validator: {
    requires: ['cfg'],
    setup: ({cfg}) => validate({
      prefix:   'purge-cache/v1/',
      publish:  cfg.app.publishMetaData,
      aws:      cfg.aws,
    }),
  },
  monitor: {
    requires: ['process', 'profile', 'cfg'],
    setup: ({process, profile, cfg}) => monitor({
      project: cfg.monitoring.project || 'tc-purge-cache',
      enable: cfg.monitoring.enable,
      credentials: cfg.taskcluster.credentials,
      mock: profile === 'test',
      process,
    }),
  },

  CachePurge: {
    requires: ['cfg', 'monitor'],
    setup: async ({cfg, monitor}) => data.CachePurge.setup({
      account: cfg.azure.account,
      table: cfg.app.cachePurgeTableName,
      credentials: cfg.taskcluster.credentials,
      monitor: monitor.prefix('table.purgecaches'),
    }),
  },

  'expire-cache-purges': {
    requires: ['cfg', 'CachePurge', 'monitor'],
    setup: async ({cfg, CachePurge, monitor}) => {
      let now = taskcluster.fromNow(cfg.app.cachePurgeExpirationDelay);
      assert(!_.isNaN(now), 'Can\'t have NaN as now');

      // Expire task-groups using delay
      debug('Expiring cache-purges at: %s, from before %s', new Date(), now);
      let count = await CachePurge.expire(now);
      debug('Expired %s cache-purges', count);

      monitor.count('expire-cache-purges.done');
      monitor.stopResourceMonitoring();
      await monitor.flush();
    },
  },

  publisher: {
    requires: ['cfg', 'validator', 'monitor'],
    setup: ({cfg, validator, monitor}) =>
      exchanges.setup({
        credentials:        cfg.pulse,
        exchangePrefix:     cfg.app.exchangePrefix,
        validator:          validator,
        referencePrefix:    'purge-cache/v1/exchanges.json',
        publish:            cfg.app.publishMetaData,
        aws:                cfg.aws,
        monitor:            monitor.prefix('publisher'),
      }),
  },

  api: {
    requires: ['cfg', 'monitor', 'validator', 'publisher', 'CachePurge'],
    setup: ({cfg, monitor, validator, publisher, CachePurge}) => api.setup({
      context:          {cfg, publisher, CachePurge, cachePurgeCache: {}},
      validator:        validator,
      publish:          cfg.app.publishMetaData,
      baseUrl:          cfg.server.publicUrl + '/v1',
      aws:              cfg.aws,
      referencePrefix:  'purge-cache/v1/api.json',
      monitor:          monitor.prefix('api'),
    }),
  },

  reference: {
    requires: ['cfg'],
    setup: ({cfg}) => exchanges.reference({
      exchangePrefix:   cfg.app.exchangePrefix,
      credentials:      cfg.pulse,
    }),
  },

  docs: {
    requires: ['cfg', 'validator', 'reference'],
    setup: ({cfg, validator, reference}) => docs.documenter({
      project: 'purge-cache',
      credentials: cfg.taskcluster.credentials,
      tier: 'core',
      schemas: validator.schemas,
      references: [
        {
          name: 'api',
          reference: api.reference({baseUrl: cfg.server.publicUrl + '/v1'}),
        }, {
          name: 'events',
          reference: reference,
        },
      ],
    }),
  },

  writeDocs: {
    requires: ['docs'],
    setup: ({docs}) => docs.write({docsDir: process.env['DOCS_OUTPUT_DIR']}),
  },

  server: {
    requires: ['cfg', 'api', 'docs'],
    setup: ({cfg, api, docs}) => {

      debug('Launching server.');
      let app = server(cfg.server);
      app.use('/v1', api);
      return app.createServer();
    },
  },
}, ['profile', 'process']);

if (!module.parent) {
  load(process.argv[2], {
    process: process.argv[2],
    profile: process.env.NODE_ENV,
  }).catch(err => {
    console.log(err.stack);
    process.exit(1);
  });
}

// Export load for tests
module.exports = load;
<commit_msg>don't publish metadata unless required<commit_after>let debug             = require('debug')('purge-cache');
let assert            = require('assert');
let path              = require('path');
let _                 = require('lodash');
let config            = require('typed-env-config');
let loader            = require('taskcluster-lib-loader');
let monitor           = require('taskcluster-lib-monitor');
let validate          = require('taskcluster-lib-validate');
let server            = require('taskcluster-lib-app');
let docs              = require('taskcluster-lib-docs');
let taskcluster       = require('taskcluster-client');
let api               = require('./api');
let exchanges         = require('./exchanges');
let data              = require('./data');

let load = loader({
  cfg: {
    requires: ['profile'],
    setup: ({profile}) => config({profile}),
  },
  validator: {
    requires: ['cfg'],
    setup: ({cfg}) => validate({
      prefix:   'purge-cache/v1/',
      publish:  cfg.app.publishMetaData,
      aws:      cfg.aws,
    }),
  },
  monitor: {
    requires: ['process', 'profile', 'cfg'],
    setup: ({process, profile, cfg}) => monitor({
      project: cfg.monitoring.project || 'tc-purge-cache',
      enable: cfg.monitoring.enable,
      credentials: cfg.taskcluster.credentials,
      mock: profile === 'test',
      process,
    }),
  },

  CachePurge: {
    requires: ['cfg', 'monitor'],
    setup: async ({cfg, monitor}) => data.CachePurge.setup({
      account: cfg.azure.account,
      table: cfg.app.cachePurgeTableName,
      credentials: cfg.taskcluster.credentials,
      monitor: monitor.prefix('table.purgecaches'),
    }),
  },

  'expire-cache-purges': {
    requires: ['cfg', 'CachePurge', 'monitor'],
    setup: async ({cfg, CachePurge, monitor}) => {
      let now = taskcluster.fromNow(cfg.app.cachePurgeExpirationDelay);
      assert(!_.isNaN(now), 'Can\'t have NaN as now');

      // Expire task-groups using delay
      debug('Expiring cache-purges at: %s, from before %s', new Date(), now);
      let count = await CachePurge.expire(now);
      debug('Expired %s cache-purges', count);

      monitor.count('expire-cache-purges.done');
      monitor.stopResourceMonitoring();
      await monitor.flush();
    },
  },

  publisher: {
    requires: ['cfg', 'validator', 'monitor'],
    setup: ({cfg, validator, monitor}) =>
      exchanges.setup({
        credentials:        cfg.pulse,
        exchangePrefix:     cfg.app.exchangePrefix,
        validator:          validator,
        referencePrefix:    'purge-cache/v1/exchanges.json',
        publish:            cfg.app.publishMetaData,
        aws:                cfg.aws,
        monitor:            monitor.prefix('publisher'),
      }),
  },

  api: {
    requires: ['cfg', 'monitor', 'validator', 'publisher', 'CachePurge'],
    setup: ({cfg, monitor, validator, publisher, CachePurge}) => api.setup({
      context:          {cfg, publisher, CachePurge, cachePurgeCache: {}},
      validator:        validator,
      publish:          cfg.app.publishMetaData,
      baseUrl:          cfg.server.publicUrl + '/v1',
      aws:              cfg.aws,
      referencePrefix:  'purge-cache/v1/api.json',
      monitor:          monitor.prefix('api'),
    }),
  },

  reference: {
    requires: ['cfg'],
    setup: ({cfg}) => exchanges.reference({
      exchangePrefix:   cfg.app.exchangePrefix,
      credentials:      cfg.pulse,
    }),
  },

  docs: {
    requires: ['cfg', 'validator', 'reference'],
    setup: ({cfg, validator, reference}) => docs.documenter({
      project: 'purge-cache',
      credentials: cfg.taskcluster.credentials,
      tier: 'core',
      schemas: validator.schemas,
      publish: cfg.app.publishMetaData,
      references: [
        {
          name: 'api',
          reference: api.reference({baseUrl: cfg.server.publicUrl + '/v1'}),
        }, {
          name: 'events',
          reference: reference,
        },
      ],
    }),
  },

  writeDocs: {
    requires: ['docs'],
    setup: ({docs}) => docs.write({docsDir: process.env['DOCS_OUTPUT_DIR']}),
  },

  server: {
    requires: ['cfg', 'api', 'docs'],
    setup: ({cfg, api, docs}) => {

      debug('Launching server.');
      let app = server(cfg.server);
      app.use('/v1', api);
      return app.createServer();
    },
  },
}, ['profile', 'process']);

if (!module.parent) {
  load(process.argv[2], {
    process: process.argv[2],
    profile: process.env.NODE_ENV,
  }).catch(err => {
    console.log(err.stack);
    process.exit(1);
  });
}

// Export load for tests
module.exports = load;
<|endoftext|>


<commit_before>/*
 * printThis v1.16.0
 * @desc Printing plug-in for jQuery
 * @author Jason Day
 *
 * Resources (based on):
 * - jPrintArea: http://plugins.jquery.com/project/jPrintArea
 * - jqPrint: https://github.com/permanenttourist/jquery.jqprint
 * - Ben Nadal: http://www.bennadel.com/blog/1591-Ask-Ben-Print-Part-Of-A-Web-Page-With-jQuery.htm
 *
 * Licensed under the MIT licence:
 *              http://www.opensource.org/licenses/mit-license.php
 *
 * (c) Jason Day 2015-2019
 *
 * Usage:
 *
 *  $("#mySelector").printThis({
 *      debug: false,                   // show the iframe for debugging
 *      importCSS: true,                // import parent page css
 *      importStyle: false,             // import style tags
 *      printContainer: true,           // grab outer container as well as the contents of the selector
 *      loadCSS: "path/to/my.css",      // path to additional css file - use an array [] for multiple
 *      pageTitle: "",                  // add title to print page
 *      removeInline: false,            // remove all inline styles from print elements
 *      removeInlineSelector: "body *", // custom selectors to filter inline styles. removeInline must be true
 *      printDelay: 333,                // variable print delay
 *      header: null,                   // prefix to html
 *      footer: null,                   // postfix to html
 *      base: false,                    // preserve the BASE tag, or accept a string for the URL
 *      formValues: true,               // preserve input/form values
 *      canvas: false,                  // copy canvas elements
 *      doctypeString: '...',           // enter a different doctype for older markup
 *      removeScripts: false,           // remove script tags from print content
 *      copyTagClasses: false           // copy classes from the html & body tag
 *      copyTagStyles: false,           // copy styles from html & body tag (for CSS Variables)
 *      beforePrintEvent: null,         // callback function for printEvent in iframe
 *      beforePrint: null,              // function called before iframe is filled
 *      afterPrint: null                // function called before iframe is removed
 *  });
 *
 * Notes:
 *  - the loadCSS will load additional CSS (with or without @media print) into the iframe, adjusting layout
 */
;
(function($) {

    function appendContent($el, content) {
        if (!content) return;

        // Simple test for a jQuery element
        $el.append(content.jquery ? content.clone() : content);
    }

    function appendBody($body, $element, opt) {
        // Clone for safety and convenience
        // Calls clone(withDataAndEvents = true) to copy form values.
        var $content = $element.clone(opt.formValues);

        if (opt.formValues) {
            // Copy original select and textarea values to their cloned counterpart
            // Makes up for inability to clone select and textarea values with clone(true)
            copyValues($element, $content, 'select, textarea');
        }

        if (opt.removeScripts) {
            $content.find('script').remove();
        }

        if (opt.printContainer) {
            // grab $.selector as container
            $content.appendTo($body);
        } else {
            // otherwise just print interior elements of container
            $content.each(function() {
                $(this).children().appendTo($body)
            });
        }
    }

    // Copies values from origin to clone for passed in elementSelector
    function copyValues(origin, clone, elementSelector) {
        var $originalElements = origin.find(elementSelector);

        clone.find(elementSelector).each(function(index, item) {
            $(item).val($originalElements.eq(index).val());
        });
    }

    var opt;
    $.fn.printThis = function(options) {
        opt = $.extend({}, $.fn.printThis.defaults, options);
        var $element = this instanceof jQuery ? this : $(this);

        var strFrameName = "printThis-" + (new Date()).getTime();

        if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) {
            // Ugly IE hacks due to IE not inheriting document.domain from parent
            // checks if document.domain is set by comparing the host name against document.domain
            var iframeSrc = "javascript:document.write(\"


<commit_before>// Allows us to use ES6 in our migrations and tests.
require('babel-register')

module.exports = {
  networks: {
    development: {
      host: 'localhost',
      port: 8545,
      network_id: '*' // Match any network id
    }
  }
}
<commit_msg>Add ropsten to truffle.js<commit_after>// Allows us to use ES6 in our migrations and tests.
require('babel-register')

module.exports = {
  networks: {
    development: {
      host: 'localhost',
      port: 8545,
      network_id: '*' // Match any network id
    },
    ropsten: {
      host: 'localhost',
      port: 8545,
      network_id: '3',
      gas: 4000000,
      from: '0xa8b56F0940b69e87a3b856f6416439AEc022C220'
    }
  }
}
<|endoftext|>


<commit_before>var css = require('css')
css.load('theme/default/main.css')

var Editor = require('editor')
exports = new Editor().start()

Hooks.getData = exports.getData.bind(exports)
Hooks.loadData = exports.loadData.bind(exports)

Native.done()
<commit_msg>Only start editor after CSS finishes loading<commit_after>var Editor = require('editor')
var css = require('css')
require('promise-extra')

exports = new Editor()
Hooks.getData = exports.getData.bind(exports)
Hooks.loadData = exports.loadData.bind(exports)

css.load('theme/default/main.css').then(function() {
  exports.start()
}).done()

Native.done()
<|endoftext|>


<commit_before>'use strict';

console.log("#############################");
console.log("Brainfuck Telegram Bot Server");
console.log("#############################\n");

const teleBot = require('teleBot');
const brainfuck = require('brainfuck-javascript');
const fs = require('fs');

// load Telegram bot token from file and create bot
var token = fs.readFileSync('telegram_token.secret').toString().replace(/\n$/, '');
console.log('------ Secret Token: [' + token + "]");
const bot = new teleBot(token);

/*
* Handles the /start command.
* Sends the user a welcome message.
*/
bot.on('/start', msg => {
  let chatId = msg.chat.id;
  let firstName = msg.from.first_name;
  let reply = msg.message_id;
  let text = msg.text;
  return bot.sendMessage(chatId, `Welcome, ${ firstName }!\nUse /help to see what this bot is all about.`, { reply });
});

/*
* Handles the /help command.
* Sends the user a help message with a list of all available commands.
*/
bot.on('/help', msg => {
  let chatId = msg.chat.id;
  let username = msg.from.username;
  console.log(" => send help.txt to user #" + chatId + " : " + username);
  var helpmessage = fs.readFileSync('src/text/help.txt').toString();
  return bot.sendMessage(chatId, helpmessage);
});

/*
* Handles the /brainfuck command.
* Sends the brainfuck command list to the user.
*/
bot.on('/brainfuck', msg => {
  let chatId = msg.chat.id;
  let username = msg.from.username;
  console.log(" => send brainfuck_info.txt to user #" + chatId + " : " + username);
  var infoMessage = fs.readFileSync('src/text/brainfuck_info.txt').toString();
  // TODO: use markdown to make commands bold
  return bot.sendMessage(chatId, infoMessage);
});

/*
* Handles the /minify command.
* Removes all clutter from the received code and returns plain brainfuck code.
*/
bot.on('/minify', msg => {
  let chatId = msg.chat.id;
  let brainfuckCode = minify(msg.text);
  bot.sendMessage(chatId, 'Minified code:');
  return bot.sendMessage(chatId, brainfuckCode);
});

/*
* Handles the /run command.
* Parses the brainfuck code and returns the output to the user as ASCII characters.
*/
bot.on('/run', msg => {
  let chatId = msg.chat.id;
  let brainfuckCode = minify(msg.text);

  // check if there is any brianfuck code in the input.
  if (brainfuckCode) {
    let text = brainfuck.text(brainfuckCode);

    // check if the output contains any displayable characters.
    if (text && /\s/.test(text)) {
      return bot.sendMessage(chatId, text);
    } else {
      return bot.sendMessage(chatId, "Error! Your code did not produce any output. Use /debug to see memory values.");
    }
  } else {
    return bot.sendMessage(chatId, "Error! You did not provide any brainfuck code. Use /brainfuck to get more information.")
  }
});

/*
* Handles the /debug command.
* Parses the brainfuck code and returns the output to the user as decimal numbers.
*/
bot.on('/debug', msg => {
  let chatId = msg.chat.id;
  let brainfuckCode = minify(msg.text);
  let data = brainfuck(brainfuckCode);
  return bot.sendMessage(chatId, data.toString());
});

/*
* Takes a string and removes all characters which are not brainfuck code.
* @param code: A string that contains brainfuck code.
*/
function minify(code) {
  // Regex selects all characters that are relevant for brainfuck: < > . , [ ] - +
  // the match() returns an array which is converted into a string by the join()-method with no sepparator.
  let minifiedCodeArray = code.match(/(<|>|\.|,|\[|\]|-|\+)/g);
  let minifiedCode = minifiedCodeArray ? minifiedCodeArray.join('') : null;
  console.log(` => minified code: ${ minifiedCode }`);
  return minifiedCode;
}

// start the bot
bot.connect();
console.log('------ Bot is now running..');
<commit_msg>corrected spelling of telebot module<commit_after>'use strict';

console.log("#############################");
console.log("Brainfuck Telegram Bot Server");
console.log("#############################\n");

const teleBot = require('TeleBot');
const brainfuck = require('brainfuck-javascript');
const fs = require('fs');

// load Telegram bot token from file and create bot
var token = fs.readFileSync('telegram_token.secret').toString().replace(/\n$/, '');
console.log('------ Secret Token: [' + token + "]");
const bot = new teleBot(token);

/*
* Handles the /start command.
* Sends the user a welcome message.
*/
bot.on('/start', msg => {
  let chatId = msg.chat.id;
  let firstName = msg.from.first_name;
  let reply = msg.message_id;
  let text = msg.text;
  return bot.sendMessage(chatId, `Welcome, ${ firstName }!\nUse /help to see what this bot is all about.`, { reply });
});

/*
* Handles the /help command.
* Sends the user a help message with a list of all available commands.
*/
bot.on('/help', msg => {
  let chatId = msg.chat.id;
  let username = msg.from.username;
  console.log(" => send help.txt to user #" + chatId + " : " + username);
  var helpmessage = fs.readFileSync('src/text/help.txt').toString();
  return bot.sendMessage(chatId, helpmessage);
});

/*
* Handles the /brainfuck command.
* Sends the brainfuck command list to the user.
*/
bot.on('/brainfuck', msg => {
  let chatId = msg.chat.id;
  let username = msg.from.username;
  console.log(" => send brainfuck_info.txt to user #" + chatId + " : " + username);
  var infoMessage = fs.readFileSync('src/text/brainfuck_info.txt').toString();
  // TODO: use markdown to make commands bold
  return bot.sendMessage(chatId, infoMessage);
});

/*
* Handles the /minify command.
* Removes all clutter from the received code and returns plain brainfuck code.
*/
bot.on('/minify', msg => {
  let chatId = msg.chat.id;
  let brainfuckCode = minify(msg.text);
  bot.sendMessage(chatId, 'Minified code:');
  return bot.sendMessage(chatId, brainfuckCode);
});

/*
* Handles the /run command.
* Parses the brainfuck code and returns the output to the user as ASCII characters.
*/
bot.on('/run', msg => {
  let chatId = msg.chat.id;
  let brainfuckCode = minify(msg.text);

  // check if there is any brianfuck code in the input.
  if (brainfuckCode) {
    let text = brainfuck.text(brainfuckCode);

    // check if the output contains any displayable characters.
    if (text && /\s/.test(text)) {
      return bot.sendMessage(chatId, text);
    } else {
      return bot.sendMessage(chatId, "Error! Your code did not produce any output. Use /debug to see memory values.");
    }
  } else {
    return bot.sendMessage(chatId, "Error! You did not provide any brainfuck code. Use /brainfuck to get more information.")
  }
});

/*
* Handles the /debug command.
* Parses the brainfuck code and returns the output to the user as decimal numbers.
*/
bot.on('/debug', msg => {
  let chatId = msg.chat.id;
  let brainfuckCode = minify(msg.text);
  let data = brainfuck(brainfuckCode);
  return bot.sendMessage(chatId, data.toString());
});

/*
* Takes a string and removes all characters which are not brainfuck code.
* @param code: A string that contains brainfuck code.
*/
function minify(code) {
  // Regex selects all characters that are relevant for brainfuck: < > . , [ ] - +
  // the match() returns an array which is converted into a string by the join()-method with no sepparator.
  let minifiedCodeArray = code.match(/(<|>|\.|,|\[|\]|-|\+)/g);
  let minifiedCode = minifiedCodeArray ? minifiedCodeArray.join('') : null;
  console.log(` => minified code: ${ minifiedCode }`);
  return minifiedCode;
}

// start the bot
bot.connect();
console.log('------ Bot is now running..');
<|endoftext|>


<commit_before>define([
    'streamhub-sdk/jquery',
    'streamhub-sdk/content/views/content-list-view',
    'streamhub-sdk/content/views/content-view',
    'text!streamhub-wall/style.css',
    'inherits'
], function($, ContentListView, ContentView, MEDIA_WALL_CSS, inherits) {
    'use strict';

    var MEDIA_WALL_STYLE_EL;

    /**
     * A view that displays Content in a media wall.
     * @param opts {Object} A set of options to config the view with
     * @param opts.el {HTMLElement} The element in which to render the streamed content
     * @param opts.relayoutWait {number} The number of milliseconds to wait when debouncing
     *        .relayout(). Defaults to 200ms.
     * @param opts.css {boolean} Whether to insert default media wall css. Default true.
     * @constructor
     */
    var MediaWallView = function(opts) {
        var self = this;
        opts = opts || {};

        this._id = new Date().getTime();
        this._autoFitColumns = true;
        this._contentWidth = opts.minContentWidth || 300;
        this._columnViews = [];
        this._containerInnerWidth = 0;
        this._columnHeights = {};
        this._animate = opts.animate === undefined ? true : opts.animate;

        this._pickColumnIndex = opts.pickColumn || MediaWallView.columnPickers.shortestColumn;

        this.debouncedRelayout = debounce(function () {
            self.fitColumns();
            self.relayout();
        }, opts.debounceRelayout || 200);

        if (opts.columns && typeof opts.columns === 'number') {
            this._autoFitColumns = false;
            this.setColumns(opts.columns);
        } else {
            this.setColumns(1);
        }

        ContentListView.call(this, opts);

        $(window).resize(function(e) {
            if (self._autoFitColumns) {
                self.debouncedRelayout();
            }
        });

        opts.css = (typeof opts.css === 'undefined') ? true : opts.css;
        if (!MEDIA_WALL_STYLE_EL && opts.css) {
            MEDIA_WALL_STYLE_EL = $('<style>'+MEDIA_WALL_CSS+'</style>').prependTo('head');
        }
        if (this._autoFitColumns) {
            this.fitColumns();
        }
    };
    inherits(MediaWallView, ContentListView);

    MediaWallView.prototype.mediaWallClassName = 'streamhub-media-wall-view';
    MediaWallView.prototype.columnClassName = 'hub-wall-column';

    MediaWallView.columnPickers = {
        roundRobin: function (contentView, forcedIndex) {
            if (this._roundRobinInsertIndex === undefined) {
                this._roundRobinInsertIndex = -1;
            }
            this._roundRobinInsertIndex++;
            this._roundRobinInsertIndex = this._roundRobinInsertIndex % this._numberOfColumns;
            return this._roundRobinInsertIndex;
        },
        shortestColumn: function (contentView, forcedIndex) {
            if (this._shortestColInsertIndex === undefined) {
                this._shortestColInsertIndex = 0;
            }
            var newContentViewIndex = forcedIndex || this.views.indexOf(contentView);
            if (newContentViewIndex === 0 || this.views.length <= this._columnViews.length) {
                return MediaWallView.columnPickers.roundRobin.apply(this, arguments);
            }

            var targetColIndex = this._shortestColInsertIndex;
            var shortestHeight;
            for (var i=0; i < this._columnViews.length; i++) {
                var colHeight = this._columnHeights[i];

                if (shortestHeight === undefined) {
                    shortestHeight = colHeight;
                    targetColIndex = i;
                    continue;
                }

                if (colHeight < shortestHeight) {
                    shortestHeight = colHeight;
                    targetColIndex = i;
                } else if (colHeight == shortestHeight) {
                    break;
                }
            }

            targetColIndex = targetColIndex >= this._columnViews.length ? 0 : targetColIndex;
            this._shortestColInsertIndex = targetColIndex;
            return targetColIndex;
        }
    };

    MediaWallView.prototype.events = ContentListView.prototype.events.extended({
        'imageLoaded.hub': function (e, opts) {
            opts = opts || {};
            for (var i=0; i < this._columnViews.length; i++) {
                if (opts.contentView && this._columnViews[i].views.indexOf(opts.contentView) > -1) {
                    this._columnHeights[i] = this._columnViews[i].$el.height();
                    break;
                }
            }
        }
    });

    /**
     * Gets the style element associated with this instance of MediaWallView
     * @returns {HTMLElement} The style element for this MediaWallView
     */
    MediaWallView.prototype._getWallStyleEl = function () {
        var $wallStyleEl = $('#wall-style-' + this._id);
        if ($wallStyleEl) {
            return $wallStyleEl;
        }
    };

    /**
     * Sets the column width in the style element for this MediaWallView
     * instance.
     * @returns {Number} The width of the column in pixels
     */
    MediaWallView.prototype._setColumnWidth = function (width) {
        var $wallStyleEl = this._getWallStyleEl();
        if ($wallStyleEl) {
            $wallStyleEl.remove();
        }
        var wallCss = '.streamhub-media-wall-'+this._id+' .hub-wall-column { width: ' + width + '; }';
        $wallStyleEl = $('<style id="wall-style-' + this._id + '">'+wallCss+'</style>');
        $wallStyleEl.appendTo('head');
    };

    /**
     * Gets the column width
     * @returns {Number} The width of the column in pixels
     */
    MediaWallView.prototype._getColumnWidth = function () {
        var $contentContainerEl = this.$el.find('.'+this.columnClassName);
        if ($contentContainerEl.length) {
            this._columnWidth = $contentContainerEl[0].getBoundingClientRect().width;
            return this._columnWidth;
        }
        return 0;
    };

    /**
     * Set the element that this ContentListView renders in
     * @param element {HTMLElement} The element to render the ContentListView in
     */
    MediaWallView.prototype.setElement = function (el) {
        var prevEl = this.el;
        ContentListView.prototype.setElement.call(this, el);
        this.$el
            .addClass(this.mediaWallClassName)
            .addClass('streamhub-media-wall-' + this._id);

        // If you're changing to a new element, it could have diff dimensions
        // and thus need a diff number of columns
        if (prevEl && this._autoFitColumns) {
            this.fitColumns();
        }
    };

    MediaWallView.prototype.render = function () {
        ContentListView.prototype.render.call(this);

        var columnView;

        if (this._columnViews.length === 0) {
            for (var i=0; i < this._numberOfColumns; i++) {
                columnView = this._createColumnView();
                this._attachColumnView(columnView);
                columnView.render();
            }
        } else {
            for (var i=0; i < this._columnViews.length; i++) {
                this._attachColumnView(this._columnViews[i]);
            }
        }
    };

    /**
     * Determines the number columns based on the configured #_contentWidth.
     * Initiates relayout logic for the determined number of columns.
     * @param opts {Object}
     */
    MediaWallView.prototype.fitColumns = function (opts) {
        if (this._containerInnerWidth === this.$el.innerWidth()) {
            return;
        }
        var latestWidth = this.$el.innerWidth();
        // If width hasn't changed, do nothing
        if (latestWidth === this._containerInnerWidth) {
            return;
        }

        this._containerInnerWidth = latestWidth;
        var numColumns = parseInt(this._containerInnerWidth / this._contentWidth, 10) || 1;
        this.setColumns(numColumns);
    };

    /**
     * Creates a column view for the number of columns specified. Triggers
     * relayout.
     * @param numColumns {Number} The number of columns the MediaWallView should be composed of
     */
    MediaWallView.prototype.setColumns = function (numColumns) {
        this._numberOfColumns = numColumns;
        var $wallStyleEl = this._getWallStyleEl();
        if ($wallStyleEl) {
            $wallStyleEl.remove();
        }
        $wallStyleEl = $('<style id="wall-style-' + this._id + '"></style');
        this._setColumnWidth((100/this._numberOfColumns) + '%');

        for (var i=0; i < numColumns; i++) {
            if (this._columnHeights[i] === undefined) {
                this._columnHeights[i] = 0;
            }
        }

        this._moreAmount = this._moreAmount || numColumns * 2; // Show more displays 2 new rows
    };

    /**
     * Gets the number of maximum visible items for a given column view
     * @returns {Number} The number of maximum visible items for a given column view
     */
    MediaWallView.prototype._getMaxVisibleItemsForColumn = function () {
        return this._maxVisibleItems/this._numberOfColumns;
    };

    MediaWallView.prototype._attachColumnView = function (columnView) {
        if (this._columnViews.indexOf(columnView) === -1) {
            this._columnViews.push(columnView);
        }
        this.$listEl.append(columnView.$el);
    };

    /**
     * Creates a column view and appends it into the DOM
     * @returns {View} The view representing a column in the MediaWall. Often a type of ListView.
     */
    MediaWallView.prototype._createColumnView = function () {
        if (this._columnViews.length >= this._numberOfColumns) {
            return;
        }
        var columnView = new ContentListView({
            maxVisibleItems: this._getMaxVisibleItemsForColumn(),
            stash: this.more,
            animate: this._animate,
            autoRender: false
        });
        columnView.$el.addClass(this.columnClassName);
        return columnView;
    };

    /**
     * Removes column views from the MediaWallView
     */
    MediaWallView.prototype._clearColumns = function () {
        for (var i=0; i < this._columnViews.length; i++) {
            var columnView = this._columnViews[i];
            columnView.detach();
            columnView.destroy();
        }
        this._columnViews = [];
    };

    /**
     * Insert a contentView into the Media Wall's column ContentListViews
     * @protected
     * @param view {View} The view to add to this.el
     * @param [forcedIndex] {number} Index of the view in this.views
     */
    MediaWallView.prototype._insert = function (contentView, forcedIndex) {
        var targetColumnIndex = this._pickColumnIndex(contentView, forcedIndex);
        var targetColumnView = this._columnViews[targetColumnIndex];

        if (typeof(forcedIndex) === 'number') {
            forcedIndex = Math.min(
                    Math.ceil(forcedIndex / this._columnViews.length),
                    targetColumnView.views.length);
        }

        targetColumnView.add(contentView, forcedIndex);

        // IE8 will not automatically push the 'show more' button down as the
        // wall grows. Adding and removing a random class will force a repaint
        var randomClass = String(Math.floor(Math.random()));
        this.$el.addClass(randomClass);
        this.$el.removeClass(randomClass);
        this._columnHeights[targetColumnIndex] = targetColumnView.$el.height();
    };

    MediaWallView.prototype.relayout = function (opts) {
        opts = opts || {};

        this._clearColumns();
        for (var i=0; i < this._numberOfColumns; i++) {
            var columnView = this._createColumnView();
            this._attachColumnView(columnView);
            columnView.render();
        }

        // Reset column insert state
        for (var i=0; i < this._columnViews.length; i++) {
            this._columnHeights[i] = 0;
        }
        this._roundRobinInsertIndex = -1;

        // Re-insert all content views
        for (var i=0; i < this.views.length; i++) {
            var contentView = this.views[i];
            var index = this._isIndexedView(contentView) ? i : undefined;
            this._insert(contentView, index);
        }
    };

    /**
     * Show More content.
     * ContentListView keeps track of an internal ._newContentGoal
     *     which is how many more items he wishes he had.
     *     This increases that goal and marks the Writable
     *     side of ContentListView as ready for more writes.
     * @param numToShow {number} The number of items to try to add
     */
    MediaWallView.prototype.showMore = function (numToShow) {
        // When fetching more content from the archive, remove the bounded
        // visible limit
        for (var i=0; i < this._columnViews.length; i++) {
            this._columnViews[i].bounded(false);
        }
        ContentListView.prototype.showMore.call(this, numToShow);
    };

    /**
     * Returns a function, that, as long as it continues to be invoked, will not be triggered.
     * The function will be called after it stops being called for N milliseconds.
     * Copied from Underscore.js (MIT License) http://underscorejs.org/docs/underscore.html#section-65
     * @param func {function} The function to debounce
     * @param wait {number} The number of milliseconds to wait for execution of func
     * @param immediate {boolean} trigger the function on the leading edge, instead of the trailing.
     * @return {function} A debounced version of the passed `func`
     */
    function debounce(func, wait, immediate) {
        var timeout, result;
        return function() {
            var context = this,
                args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) {
                    result = func.apply(context, args);
                }
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) {
                result = func.apply(context, args);
            }
            return result;
        };
    }

    MediaWallView.prototype.destroy = function () {
        this._clearColumns();
        this._columnViews = null;
        ContentListView.prototype.destroy.call(this);
    };

    return MediaWallView;
});
<commit_msg>Make tests pass, improved logic to ensure there are never 0 columns<commit_after>define([
    'streamhub-sdk/jquery',
    'streamhub-sdk/content/views/content-list-view',
    'streamhub-sdk/content/views/content-view',
    'text!streamhub-wall/style.css',
    'inherits'
], function($, ContentListView, ContentView, MEDIA_WALL_CSS, inherits) {
    'use strict';

    var MEDIA_WALL_STYLE_EL;

    /**
     * A view that displays Content in a media wall.
     * @param opts {Object} A set of options to config the view with
     * @param opts.el {HTMLElement} The element in which to render the streamed content
     * @param opts.relayoutWait {number} The number of milliseconds to wait when debouncing
     *        .relayout(). Defaults to 200ms.
     * @param opts.css {boolean} Whether to insert default media wall css. Default true.
     * @constructor
     */
    var MediaWallView = function(opts) {
        var self = this;
        opts = opts || {};

        this._id = new Date().getTime();
        this._autoFitColumns = true;
        this._contentWidth = opts.minContentWidth || 300;
        this._columnViews = [];
        this._containerInnerWidth = null;
        this._columnHeights = {};
        this._numberOfColumns = null;
        this._animate = opts.animate === undefined ? true : opts.animate;

        this._pickColumnIndex = opts.pickColumn || MediaWallView.columnPickers.shortestColumn;

        this.debouncedRelayout = debounce(function () {
            self.fitColumns();
            self.relayout();
        }, opts.debounceRelayout || 200);

        if (opts.columns && typeof opts.columns === 'number') {
            this._autoFitColumns = false;
            this.setColumns(opts.columns);
        }

        ContentListView.call(this, opts);

        $(window).resize(function(e) {
            if (self._autoFitColumns) {
                self.debouncedRelayout();
            }
        });

        opts.css = (typeof opts.css === 'undefined') ? true : opts.css;
        if (!MEDIA_WALL_STYLE_EL && opts.css) {
            MEDIA_WALL_STYLE_EL = $('<style>'+MEDIA_WALL_CSS+'</style>').prependTo('head');
        }
        if (this._autoFitColumns) {
            this.fitColumns();
        }
    };
    inherits(MediaWallView, ContentListView);

    MediaWallView.prototype.mediaWallClassName = 'streamhub-media-wall-view';
    MediaWallView.prototype.columnClassName = 'hub-wall-column';

    MediaWallView.columnPickers = {
        roundRobin: function (contentView, forcedIndex) {
            if (this._roundRobinInsertIndex === undefined) {
                this._roundRobinInsertIndex = -1;
            }
            this._roundRobinInsertIndex++;
            this._roundRobinInsertIndex = this._roundRobinInsertIndex % this._numberOfColumns;
            return this._roundRobinInsertIndex;
        },
        shortestColumn: function (contentView, forcedIndex) {
            if (this._shortestColInsertIndex === undefined) {
                this._shortestColInsertIndex = 0;
            }
            var newContentViewIndex = forcedIndex || this.views.indexOf(contentView);
            if (newContentViewIndex === 0 || this.views.length <= this._columnViews.length) {
                return MediaWallView.columnPickers.roundRobin.apply(this, arguments);
            }

            var targetColIndex = this._shortestColInsertIndex;
            var shortestHeight;
            for (var i=0; i < this._columnViews.length; i++) {
                var colHeight = this._columnHeights[i];

                if (shortestHeight === undefined) {
                    shortestHeight = colHeight;
                    targetColIndex = i;
                    continue;
                }

                if (colHeight < shortestHeight) {
                    shortestHeight = colHeight;
                    targetColIndex = i;
                } else if (colHeight == shortestHeight) {
                    break;
                }
            }

            targetColIndex = targetColIndex >= this._columnViews.length ? 0 : targetColIndex;
            this._shortestColInsertIndex = targetColIndex;
            return targetColIndex;
        }
    };

    MediaWallView.prototype.events = ContentListView.prototype.events.extended({
        'imageLoaded.hub': function (e, opts) {
            opts = opts || {};
            for (var i=0; i < this._columnViews.length; i++) {
                if (opts.contentView && this._columnViews[i].views.indexOf(opts.contentView) > -1) {
                    this._columnHeights[i] = this._columnViews[i].$el.height();
                    break;
                }
            }
        }
    });

    /**
     * Gets the style element associated with this instance of MediaWallView
     * @returns {HTMLElement} The style element for this MediaWallView
     */
    MediaWallView.prototype._getWallStyleEl = function () {
        var $wallStyleEl = $('#wall-style-' + this._id);
        if ($wallStyleEl) {
            return $wallStyleEl;
        }
    };

    /**
     * Sets the column width in the style element for this MediaWallView
     * instance.
     * @returns {Number} The width of the column in pixels
     */
    MediaWallView.prototype._setColumnWidth = function (width) {
        var $wallStyleEl = this._getWallStyleEl();
        if ($wallStyleEl) {
            $wallStyleEl.remove();
        }
        var wallCss = '.streamhub-media-wall-'+this._id+' .hub-wall-column { width: ' + width + '; }';
        $wallStyleEl = $('<style id="wall-style-' + this._id + '">'+wallCss+'</style>');
        $wallStyleEl.appendTo('head');
    };

    /**
     * Gets the column width
     * @returns {Number} The width of the column in pixels
     */
    MediaWallView.prototype._getColumnWidth = function () {
        var $contentContainerEl = this.$el.find('.'+this.columnClassName);
        if ($contentContainerEl.length) {
            this._columnWidth = $contentContainerEl[0].getBoundingClientRect().width;
            return this._columnWidth;
        }
        return 0;
    };

    /**
     * Set the element that this ContentListView renders in
     * @param element {HTMLElement} The element to render the ContentListView in
     */
    MediaWallView.prototype.setElement = function (el) {
        var prevEl = this.el;
        ContentListView.prototype.setElement.call(this, el);
        this.$el
            .addClass(this.mediaWallClassName)
            .addClass('streamhub-media-wall-' + this._id);

        // If you're changing to a new element, it could have diff dimensions
        // and thus need a diff number of columns
        if (prevEl && this._autoFitColumns) {
            this.fitColumns();
        }
    };

    MediaWallView.prototype.render = function () {
        ContentListView.prototype.render.call(this);

        if (this._numberOfColumns === null && this._autoFitColumns) {
            this.fitColumns();
        }

        var columnView;

        if (this._columnViews.length !== this._numberOfColumns) {
            for (var i=0; i < this._numberOfColumns; i++) {
                columnView = this._createColumnView();
                this._attachColumnView(columnView);
                columnView.render();
            }
        } else {
            for (var i=0; i < this._columnViews.length; i++) {
                this._attachColumnView(this._columnViews[i]);
            }
        }
    };

    /**
     * Determines the number columns based on the configured #_contentWidth.
     * Initiates relayout logic for the determined number of columns.
     * @param opts {Object}
     */
    MediaWallView.prototype.fitColumns = function (opts) {
        if (this._containerInnerWidth === this.$el.innerWidth()) {
            return;
        }
        var latestWidth = this.$el.innerWidth();
        // If width hasn't changed, do nothing
        if (latestWidth === this._containerInnerWidth) {
            return;
        }

        this._containerInnerWidth = latestWidth;
        var numColumns = parseInt(this._containerInnerWidth / this._contentWidth, 10);
        // Always set to at least one column
        this.setColumns(numColumns || 1);
    };

    /**
     * Creates a column view for the number of columns specified. Triggers
     * relayout.
     * @param numColumns {Number} The number of columns the MediaWallView should be composed of
     */
    MediaWallView.prototype.setColumns = function (numColumns) {
        this._numberOfColumns = numColumns;
        var $wallStyleEl = this._getWallStyleEl();
        if ($wallStyleEl) {
            $wallStyleEl.remove();
        }
        $wallStyleEl = $('<style id="wall-style-' + this._id + '"></style');
        this._setColumnWidth((100/this._numberOfColumns) + '%');

        for (var i=0; i < numColumns; i++) {
            if (this._columnHeights[i] === undefined) {
                this._columnHeights[i] = 0;
            }
        }

        this._moreAmount = this._moreAmount || numColumns * 2; // Show more displays 2 new rows
    };

    /**
     * Gets the number of maximum visible items for a given column view
     * @returns {Number} The number of maximum visible items for a given column view
     */
    MediaWallView.prototype._getMaxVisibleItemsForColumn = function () {
        return this._maxVisibleItems/this._numberOfColumns;
    };

    MediaWallView.prototype._attachColumnView = function (columnView) {
        if (this._columnViews.indexOf(columnView) === -1) {
            this._columnViews.push(columnView);
        }
        this.$listEl.append(columnView.$el);
    };

    /**
     * Creates a column view and appends it into the DOM
     * @returns {View} The view representing a column in the MediaWall. Often a type of ListView.
     */
    MediaWallView.prototype._createColumnView = function () {
        if (this._columnViews.length >= this._numberOfColumns) {
            return;
        }
        var columnView = new ContentListView({
            maxVisibleItems: this._getMaxVisibleItemsForColumn(),
            stash: this.more,
            animate: this._animate,
            autoRender: false
        });
        columnView.$el.addClass(this.columnClassName);
        return columnView;
    };

    /**
     * Removes column views from the MediaWallView
     */
    MediaWallView.prototype._clearColumns = function () {
        for (var i=0; i < this._columnViews.length; i++) {
            var columnView = this._columnViews[i];
            columnView.detach();
            columnView.destroy();
        }
        this._columnViews = [];
    };

    /**
     * Insert a contentView into the Media Wall's column ContentListViews
     * @protected
     * @param view {View} The view to add to this.el
     * @param [forcedIndex] {number} Index of the view in this.views
     */
    MediaWallView.prototype._insert = function (contentView, forcedIndex) {
        var targetColumnIndex = this._pickColumnIndex(contentView, forcedIndex);
        var targetColumnView = this._columnViews[targetColumnIndex];

        if (typeof(forcedIndex) === 'number') {
            forcedIndex = Math.min(
                    Math.ceil(forcedIndex / this._columnViews.length),
                    targetColumnView.views.length);
        }

        targetColumnView.add(contentView, forcedIndex);

        // IE8 will not automatically push the 'show more' button down as the
        // wall grows. Adding and removing a random class will force a repaint
        var randomClass = String(Math.floor(Math.random()));
        this.$el.addClass(randomClass);
        this.$el.removeClass(randomClass);
        this._columnHeights[targetColumnIndex] = targetColumnView.$el.height();
    };

    MediaWallView.prototype.relayout = function (opts) {
        opts = opts || {};

        this._clearColumns();
        for (var i=0; i < this._numberOfColumns; i++) {
            var columnView = this._createColumnView();
            this._attachColumnView(columnView);
            columnView.render();
        }

        // Reset column insert state
        for (var i=0; i < this._columnViews.length; i++) {
            this._columnHeights[i] = 0;
        }
        this._roundRobinInsertIndex = -1;

        // Re-insert all content views
        for (var i=0; i < this.views.length; i++) {
            var contentView = this.views[i];
            var index = this._isIndexedView(contentView) ? i : undefined;
            this._insert(contentView, index);
        }
    };

    /**
     * Show More content.
     * ContentListView keeps track of an internal ._newContentGoal
     *     which is how many more items he wishes he had.
     *     This increases that goal and marks the Writable
     *     side of ContentListView as ready for more writes.
     * @param numToShow {number} The number of items to try to add
     */
    MediaWallView.prototype.showMore = function (numToShow) {
        // When fetching more content from the archive, remove the bounded
        // visible limit
        for (var i=0; i < this._columnViews.length; i++) {
            this._columnViews[i].bounded(false);
        }
        ContentListView.prototype.showMore.call(this, numToShow);
    };

    /**
     * Returns a function, that, as long as it continues to be invoked, will not be triggered.
     * The function will be called after it stops being called for N milliseconds.
     * Copied from Underscore.js (MIT License) http://underscorejs.org/docs/underscore.html#section-65
     * @param func {function} The function to debounce
     * @param wait {number} The number of milliseconds to wait for execution of func
     * @param immediate {boolean} trigger the function on the leading edge, instead of the trailing.
     * @return {function} A debounced version of the passed `func`
     */
    function debounce(func, wait, immediate) {
        var timeout, result;
        return function() {
            var context = this,
                args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) {
                    result = func.apply(context, args);
                }
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) {
                result = func.apply(context, args);
            }
            return result;
        };
    }

    MediaWallView.prototype.destroy = function () {
        this._clearColumns();
        this._columnViews = null;
        ContentListView.prototype.destroy.call(this);
    };

    return MediaWallView;
});
<|endoftext|>