<commit_before>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const tar = require('tar')
const zlib = require('zlib')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.11.0',
  build: '6',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

function formatPlatform(platform) {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  if (platform === 'linux') {
    return 'ubuntu'
  }
  return platform
}

config.fileName = `git-kitchen-sink-${formatPlatform(process.platform)}-v${config.version}-${config.build}.tgz`

// TODO: swap these out for official release URLs when we make the repository public

if (process.platform === 'darwin') {
  config.source = `https://www.dropbox.com/s/qcj0qdnorjlm3rz/${config.fileName}?dl=1`
  config.checksum = 'd1998417ba8d85c5c9b8fff9b75f2c9f50c9c5729892f73e0dca550df056de69'
} else if (process.platform === 'win32') {
  config.source = `https://www.dropbox.com/s/56cep29cssjvekx/${config.fileName}?dl=1`
  config.checksum = '445846a029e824c2bc3a1c8cdee4f4d4c014248530ece3464351f4355bb6e266'
} else if (process.platform === 'linux') {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  config.fileName = `git-kitchen-sink-ubuntu-v${config.version}-${config.build}.tgz`
  config.source = `https://www.dropbox.com/s/mr9bawuzof7360s/${config.fileName}?dl=1`
  config.checksum = '01fbe5496ac7ded5cc3487ffd82d30b3a1f94f101ff2a3cc86f12c0f988bbdb6'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function extract (source, callback) {
  if (path.extname(source) === '.zip') {
    const result = decompress(source, config.outputPath)
    result
      .then(() => {
        callback(null)
      })
      .catch(err => {
        callback(err)
      })

  } else {
    const extractor = tar.Extract({path: config.outputPath})
      .on('error', function (error) { callback(error) })
      .on('end', function () { callback() })

    fs.createReadStream(source)
      .on('error', function (error) { callback(error) })
      .pipe(zlib.Gunzip())
      .pipe(extractor)
  }
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    const isValid = hash === config.checksum
    if (!isValid) {
      console.log(`DEBUG: expected checksums to be equal: ${hash} === ${config.checksum}`)
    }
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  extract(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  downloadAndUnpack()
})
<commit_msg>tag new builds<commit_after>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const tar = require('tar')
const zlib = require('zlib')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.11.0',
  build: '7',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

function formatPlatform(platform) {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  if (platform === 'linux') {
    return 'ubuntu'
  }
  return platform
}

config.fileName = `git-kitchen-sink-${formatPlatform(process.platform)}-v${config.version}-${config.build}.tgz`

// TODO: swap these out for official release URLs when we make the repository public

if (process.platform === 'darwin') {
  config.source = `https://www.dropbox.com/s/uie0f4iopug2zfb/${config.fileName}?dl=1`
  config.checksum = 'f63307e1b0ed3a6a4a607b30f801cc6ba99d6ee6dc25a0056e79e102c521a6eb'
} else if (process.platform === 'win32') {
  config.source = `https://www.dropbox.com/s/yf33r47e3zby8mo/${config.fileName}?dl=1`
  config.checksum = '0aab55d5fbd9185052bd3f10292562d24650d44ce3e0b462cc8f1a53b5e70867'
} else if (process.platform === 'linux') {
  config.source = `https://www.dropbox.com/s/0ncude55tc2d8i5/${config.fileName}?dl=1`
  config.checksum = '49dd340c7fe813aeb039122a400e852caf0e393aca5cb61dba2c6b36c3d44b8b'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function extract (source, callback) {
  if (path.extname(source) === '.zip') {
    const result = decompress(source, config.outputPath)
    result
      .then(() => {
        callback(null)
      })
      .catch(err => {
        callback(err)
      })

  } else {
    const extractor = tar.Extract({path: config.outputPath})
      .on('error', function (error) { callback(error) })
      .on('end', function () { callback() })

    fs.createReadStream(source)
      .on('error', function (error) { callback(error) })
      .pipe(zlib.Gunzip())
      .pipe(extractor)
  }
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    const isValid = hash === config.checksum
    if (!isValid) {
      console.log(`DEBUG: expected checksums to be equal: ${hash} === ${config.checksum}`)
    }
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  extract(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  downloadAndUnpack()
})
<|endoftext|>


<commit_before>var EventEmitter = require('events'),
events = new EventEmitter();
var average = [];
var lastAverage;
var averageNumber = 600;
var averageCount =0;
var signalMax = 0;
var signalMin = 4096;
var peakToPeak;
var localSpi;
var sampleinterval;
var averageinterval;
var audioArray = [];
var eventIntervalTime = 60000; //120000
var eventInterval;
var audioDataIntervalTime = 30000;
var audioDataInterval;
var maxPeak = 0;
var minPeak = 4096;

var txbuf = new Buffer([ 0x23, 0x48, 0xAF, 0x19, 0x19, 0x19 ]);
var rxbuf = new Buffer([ 0x00, 0x00, 0x00]);
exports.events = events;
exports.setup = function(SPI,spi_bus,callback){
  localSpi = new SPI.Spi(spi_bus, {
      'mode': SPI.MODE['MODE_0'],  // always set mode as the first option
      'chipSelect': SPI.CS['none'] // 'none', 'high' - defaults to low
    }, function(s){
      s.maxSpeed(6000000);
      s.open();
    });
  checkValues(callback);
  //startReadings();
}
function checkValues(callback){
  localSpi.read(rxbuf, function(device, buf) {
    var sample = buf.readUInt16BE(0);
    if(sample >0 || sample < 4096){
      startReadings();
      callback(true);
    }else{
      callback(false);
    }
  });
}

function startReadings(){
  sampleinterval = setInterval(function(){
    localSpi.read(rxbuf, function(device, buf) {
      //console.log(buf.readUInt16BE(0));
      var sample = buf.readUInt16BE(0);
      if (sample > signalMax)
           {
              signalMax = sample;  // save just the max levels
           }
           else if (sample < signalMin)
           {
              signalMin = sample;  // save just the min levels
           }
    });
  },1);
  averageinterval = setInterval(function(){
   peakToPeak = 0;
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   if(peakToPeak > maxPeak){
     maxPeak = peakToPeak;
   }
   if(peakToPeak < minPeak){
     minPeak = peakToPeak;
   }
   average.push(peakToPeak);
   if(average.length == averageNumber){
     var first = average.shift();
   }
   signalMax = 0;
   signalMin = 4096;
  },50);
  eventInterval = setInterval(function(){
    events.emit('data',audioArray.slice(0));
    audioArray = [];
  },eventIntervalTime);
  audioDataInterval = setInterval(function(){
    var value = medianFun(average.slice(0));
    var outString = "median value is " + value;
    for(var i = 0; i<maxPeak/10;i++){
     outString += " ";
    }
    outString += "*";
    maxPeak = 0;
    minPeak = 4096;
    average = [];
    console.log(outString);
    var micData = {"average":value,"max":maxPeak,"min":minPeak};
    audioArray.push(micData);
  },audioDataIntervalTime)
}

// setInterval(function(){
//   spi.read(rxbuf, function(device, buf) {
//     //console.log(buf.readUInt16BE(0));
//     var sample = buf.readUInt16BE(0);
//     if (sample > signalMax)
//          {
//             signalMax = sample;  // save just the max levels
//          }
//          else if (sample < signalMin)
//          {
//             signalMin = sample;  // save just the min levels
//          }
//   });
// },1);

// setInterval(function(){
//  peakToPeak = 0;
//  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
//  average.push(peakToPeak);
//  if(average.length == 20){
//    var first = average.shift();
//  }
//  var value = medianFun(average.slice(0));
//  var outString = "median value is " + value;
//  //var outString = "";
//  for(var i = 0; i<peakToPeak/10;i++){
//    outString += " ";
//  }
//  outString += "*";
//  //var averageToMedian = average.slice(0);
//  //averageToMedian = average
//  console.log(outString);
//  signalMax = 0;
//  signalMin = 4096;
// },50);

function medianFun(values) {

    values.sort( function(a,b) {return a - b;} );

    var half = Math.floor(values.length/2);

    if(values.length % 2)
        return values[half];
    else
        return (values[half-1] + values[half]) / 2.0;
}
<commit_msg>added spi config<commit_after>var EventEmitter = require('events'),
events = new EventEmitter();
var average = [];
var lastAverage;
var averageNumber = 600;
var averageCount =0;
var signalMax = 0;
var signalMin = 4096;
var peakToPeak;
var localSpi;
var sampleinterval;
var averageinterval;
var audioArray = [];
var eventIntervalTime = 60000; //120000
var eventInterval;
var audioDataIntervalTime = 30000;
var audioDataInterval;
var maxPeak = 0;
var minPeak = 4096;

var txbuf = new Buffer([ 0x23, 0x48, 0xAF, 0x19, 0x19, 0x19 ]);
var rxbuf = new Buffer([ 0x00, 0x00, 0x00]);
exports.events = events;
exports.setup = function(SPI,spi_bus,callback){
  localSpi = new SPI.Spi(spi_bus, {
      'mode': SPI.MODE['MODE_0'],  // always set mode as the first option
      'chipSelect': SPI.CS['none'] // 'none', 'high' - defaults to low
    }, function(s){
      s.maxSpeed(6000000);
      try{
        s.open();
      }catch(e){
        console.error("MIC SPI error")
        callback(false)
      }

    });
  checkValues(callback);
  //startReadings();
}
function checkValues(callback){
  localSpi.read(rxbuf, function(device, buf) {
    var sample = buf.readUInt16BE(0);
    if(sample >0 || sample < 4096){
      startReadings();
      callback(true);
    }else{
      callback(false);
    }
  });
}

function startReadings(){
  sampleinterval = setInterval(function(){
    localSpi.read(rxbuf, function(device, buf) {
      //console.log(buf.readUInt16BE(0));
      var sample = buf.readUInt16BE(0);
      if (sample > signalMax)
           {
              signalMax = sample;  // save just the max levels
           }
           else if (sample < signalMin)
           {
              signalMin = sample;  // save just the min levels
           }
    });
  },1);
  averageinterval = setInterval(function(){
   peakToPeak = 0;
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   if(peakToPeak > maxPeak){
     maxPeak = peakToPeak;
   }
   if(peakToPeak < minPeak){
     minPeak = peakToPeak;
   }
   average.push(peakToPeak);
   if(average.length == averageNumber){
     var first = average.shift();
   }
   signalMax = 0;
   signalMin = 4096;
  },50);
  eventInterval = setInterval(function(){
    events.emit('data',audioArray.slice(0));
    audioArray = [];
  },eventIntervalTime);
  audioDataInterval = setInterval(function(){
    var value = medianFun(average.slice(0));
    var outString = "median value is " + value;
    for(var i = 0; i<maxPeak/10;i++){
     outString += " ";
    }
    outString += "*";
    maxPeak = 0;
    minPeak = 4096;
    average = [];
    console.log(outString);
    var micData = {"average":value,"max":maxPeak,"min":minPeak};
    audioArray.push(micData);
  },audioDataIntervalTime)
}

// setInterval(function(){
//   spi.read(rxbuf, function(device, buf) {
//     //console.log(buf.readUInt16BE(0));
//     var sample = buf.readUInt16BE(0);
//     if (sample > signalMax)
//          {
//             signalMax = sample;  // save just the max levels
//          }
//          else if (sample < signalMin)
//          {
//             signalMin = sample;  // save just the min levels
//          }
//   });
// },1);

// setInterval(function(){
//  peakToPeak = 0;
//  peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
//  average.push(peakToPeak);
//  if(average.length == 20){
//    var first = average.shift();
//  }
//  var value = medianFun(average.slice(0));
//  var outString = "median value is " + value;
//  //var outString = "";
//  for(var i = 0; i<peakToPeak/10;i++){
//    outString += " ";
//  }
//  outString += "*";
//  //var averageToMedian = average.slice(0);
//  //averageToMedian = average
//  console.log(outString);
//  signalMax = 0;
//  signalMin = 4096;
// },50);

function medianFun(values) {

    values.sort( function(a,b) {return a - b;} );

    var half = Math.floor(values.length/2);

    if(values.length % 2)
        return values[half];
    else
        return (values[half-1] + values[half]) / 2.0;
}
<|endoftext|>


<commit_before>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const tar = require('tar')
const zlib = require('zlib')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.11.0',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

config.fileName = `git-kitchen-sink-${process.platform}-v${config.version}-2.tgz`

// TODO: swap these out for official release URLs when we make the repository public

if (process.platform === 'darwin') {
  config.source = `https://www.dropbox.com/s/pd1q8gqttvhgm59/${config.fileName}?dl=1`
  config.checksum = '0416eefdf160b7f176b1cdd5f5bb36a07968240769b76645f7959a3b91906f98'
} else if (process.platform === 'win32') {
  config.source = `https://www.dropbox.com/s/wjbs9p8959nt8w4/${config.fileName}?dl=1`
  config.checksum = '8723719b1dfb461715b39f88f048dfc1444b617fa1673dde0c17bdf6e70605ae'
} else if (process.platform === 'linux') {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  config.fileName = `git-kitchen-sink-ubuntu-v${config.version}-2.tgz`
  config.source = `https://www.dropbox.com/s/cm69onplkfixwfy/${config.fileName}?dl=1`
  config.checksum = 'd05e382548a7fa1d94e61fa1faf83e7bca8fd2041a365dea726629d5882cef71'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function extract (source, callback) {
  if (path.extname(source) === '.zip') {
    const result = decompress(source, config.outputPath)
    result
      .then(() => {
        callback(null)
      })
      .catch(err => {
        callback(err)
      })

  } else {
    const extractor = tar.Extract({path: config.outputPath})
      .on('error', function (error) { callback(error) })
      .on('end', function () { callback() })

    fs.createReadStream(source)
      .on('error', function (error) { callback(error) })
      .pipe(zlib.Gunzip())
      .pipe(extractor)
  }
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    const isValid = hash === config.checksum
    if (!isValid) {
      console.log(`DEBUG: expected checksums to be equal: ${hash} === ${config.checksum}`)
    }
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  extract(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  downloadAndUnpack()
})
<commit_msg>bump packages to install<commit_after>const decompress = require('decompress')
const request = require('request')
const ProgressBar = require('progress')
const tmpdir = require('os-tmpdir')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const checksum = require('checksum')
const rimraf = require('rimraf')

const tar = require('tar')
const zlib = require('zlib')

const config = {
  outputPath: path.join(__dirname, '..', 'git'),
  version: '2.11.0',
  source: '',
  checksum: '',
  upstreamVersion: '',
  fileName: ''
}

config.fileName = `git-kitchen-sink-${process.platform}-v${config.version}-3.tgz`

// TODO: swap these out for official release URLs when we make the repository public

if (process.platform === 'darwin') {
  config.source = `https://www.dropbox.com/s/7jwwjw8cj1q5wad/${config.fileName}?dl=1`
  config.checksum = '943c9cbb6b124aa8b49d7fba57e07d449ac24f47897712dc7be98b6be4cf32be'
} else if (process.platform === 'win32') {
  config.source = `https://www.dropbox.com/s/ugcvpqpyxifyuma/${config.fileName}?dl=1`
  config.checksum = 'bd1d27888989b18075da236d827956f07e0637afd41587f38ae7077452291cb5'
} else if (process.platform === 'linux') {
  // switching this to Ubuntu to ensure it's clear what we're installing here
  config.fileName = `git-kitchen-sink-ubuntu-v${config.version}-3.tgz`
  config.source = `https://www.dropbox.com/s/bdkz2ly44b4meei/${config.fileName}?dl=1`
  config.checksum = '6c5284f97a9a5d9bc32a1db51395027a25fa8c2ebcbb4e2a1df88c31d225090b'
}
const fullUrl = config.source

function handleError (url, error) {
  if (!error) {
    return
  }

  const message = error.message || error
  console.error(`Downloading ${url} failed: ${message}`)
  process.exit(1)
}

function extract (source, callback) {
  if (path.extname(source) === '.zip') {
    const result = decompress(source, config.outputPath)
    result
      .then(() => {
        callback(null)
      })
      .catch(err => {
        callback(err)
      })

  } else {
    const extractor = tar.Extract({path: config.outputPath})
      .on('error', function (error) { callback(error) })
      .on('end', function () { callback() })

    fs.createReadStream(source)
      .on('error', function (error) { callback(error) })
      .pipe(zlib.Gunzip())
      .pipe(extractor)
  }
}

const dir = tmpdir()
const temporaryFile = path.join(dir, config.fileName)

const verifyFile = function (file, callback) {
  checksum.file(file, { algorithm: 'sha256' }, (_, hash) => {
    const isValid = hash === config.checksum
    if (!isValid) {
      console.log(`DEBUG: expected checksums to be equal: ${hash} === ${config.checksum}`)
    }
    callback(hash === config.checksum)
  })
}

const unpackFile = function (file) {
  extract(file, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }
  })
}

const downloadCallback = function (error, response, body) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (response.statusCode !== 200) {
    return handleError(fullUrl, Error(`Non-200 response (${response.statusCode})`))
  }

  fs.createWriteStream(temporaryFile).write(body, function (error) {
    if (error) {
      return handleError(fullUrl, error)
    }

    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        process.exit(1)
      }
    })
  })
}

const downloadAndUnpack = () => {
  console.log(`Downloading Git from: ${fullUrl}`)

  const req = request.get(fullUrl, { encoding: null }, downloadCallback)

  req.on('response', function (res) {
    const len = parseInt(res.headers['content-length'], 10)

    console.log()
    const bar = new ProgressBar('Downloading Git [:bar] :percent :etas', {
      complete: '=',
      incomplete: ' ',
      width: 50,
      total: len
    })

    res.on('data', function (chunk) {
      bar.tick(chunk.length)
    })

    res.on('end', function () {
      console.log('\n')
    })
  })
}

mkdirp(config.outputPath, function (error) {
  if (error) {
    return handleError(fullUrl, error)
  }

  if (fs.existsSync(config.outputPath)) {
    try {
      rimraf.sync(config.outputPath)
    } catch (err) {
      console.error(err)
      return
    }
  }

  if (fs.existsSync(temporaryFile)) {
    verifyFile(temporaryFile, valid => {
      if (valid) {
        unpackFile(temporaryFile)
      } else {
        rimraf.sync(temporaryFile)
        downloadAndUnpack()
      }
    })
    return
  }

  downloadAndUnpack()
})
<|endoftext|>


<commit_before>var assert = require('assert');
var { AuthFilter } = require('../src/api/middleware/filters/authFilter');

describe('Filters', function() {
  describe('Pre Middleware', function() {
    const authFilter = new AuthFilter();

    it('should add authHeader to req and call next', function() {
      const middleware = [];

      // Create Mock App
      const app = {
        use: f => {
          middleware.push(f);
        }
      };

      // Add the middleware
      authFilter.init(app);

      // Create the mock request
      const req = {
        headers: {
          authorization: 'Bearer header.body.signature'
        }
      };

      const res = {};

      // Execute the auth middleware
      middleware[0](req, res, () => {
        assert.equal(req.headers.authorization, req.token);
      });
    });
  });
});
<commit_msg>created test for auth header not present.<commit_after>var assert = require('assert');
var { AuthFilter } = require('../src/api/middleware/filters/authFilter');

describe('Filters', function() {
  describe('Pre Middleware', function() {
    const authFilter = new AuthFilter();

    it('should add token to req and call next', function() {
      const middleware = [];

      // Create Mock App
      const app = {
        use: f => {
          middleware.push(f);
        }
      };

      // Add the middleware
      authFilter.init(app);

      // Create the mock request
      const req = {
        headers: {
          authorization: 'Bearer header.body.signature'
        }
      };

      const res = {};

      // Execute the auth middleware
      middleware[0](req, res, () => {
        assert.equal(req.headers.authorization, req.token);
      });
    });

    it('should bypass add auth token if auth header not present and call next', function() {
      const middleware = [];

      // Create Mock App
      const app = {
        use: f => {
          middleware.push(f);
        }
      };

      // Add the middleware
      authFilter.init(app);

      // Create the mock request
      const req = {
        headers: {
          authorization: 'Bearer header.body.signature'
        }
      };

      const res = {};

      // Execute the auth middleware
      middleware[0](req, res, () => {
        assert.equal(req.headers.authorization, req.token);
      });
    });
  });
});
<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')

const ROOT = path.join(__dirname, '/../')

const config = {
  mode: process.env.NODE_ENV,
  entry: {
    bundled: [
      'jquery',
      'bootstrap-sass',
      'inline-attachment/src/inline-attachment.js',
      'jquery.cookie',
      'jquery.selection.js',
      'babel-polyfill',
    ],
    app: path.join(ROOT, 'client/app.js'),
    crowi: path.join(ROOT, 'client/crowi.js'),
    presentation: path.join(ROOT, 'client/crowi-presentation.js'),
    form: path.join(ROOT, 'client/crowi-form.js'),
    admin: path.join(ROOT, 'client/crowi-admin.js'),
  },
  output: {
    path: path.join(ROOT, 'public/js'),
    filename: '[name].js',
  },
  devtool: 'inline-source-map',
  resolve: {
    modules: ['./node_modules', './client/thirdparty-js'],
  },
  module: {
    rules: [
      {
        test: /\.ya?ml$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'json-loader',
          },
          {
            loader: 'yaml-loader',
          },
        ],
      },
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
          },
        ],
      },
    ],
  },
  optimization: {
    runtimeChunk: 'single',
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),
    new CopyWebpackPlugin([
      { from: path.join(ROOT, 'node_modules/reveal.js/css'), to: path.join(ROOT, 'public/css/reveal/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/css'), to: path.join(ROOT, 'public/js/reveal/lib/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/js'), to: path.join(ROOT, 'public/js/reveal/lib/js') },
      { from: path.join(ROOT, 'node_modules/reveal.js/plugin'), to: path.join(ROOT, 'public/js/reveal/plugin/') },
    ]),
  ],
}

module.exports = config
<commit_msg>Use source-map<commit_after>const path = require('path')
const webpack = require('webpack')
const CopyWebpackPlugin = require('copy-webpack-plugin')

const ROOT = path.join(__dirname, '/../')

const config = {
  mode: process.env.NODE_ENV,
  entry: {
    bundled: [
      'jquery',
      'bootstrap-sass',
      'inline-attachment/src/inline-attachment.js',
      'jquery.cookie',
      'jquery.selection.js',
      'babel-polyfill',
    ],
    app: path.join(ROOT, 'client/app.js'),
    crowi: path.join(ROOT, 'client/crowi.js'),
    presentation: path.join(ROOT, 'client/crowi-presentation.js'),
    form: path.join(ROOT, 'client/crowi-form.js'),
    admin: path.join(ROOT, 'client/crowi-admin.js'),
  },
  output: {
    path: path.join(ROOT, 'public/js'),
    filename: '[name].js',
  },
  devtool: 'source-map',
  resolve: {
    modules: ['./node_modules', './client/thirdparty-js'],
  },
  module: {
    rules: [
      {
        test: /\.ya?ml$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'json-loader',
          },
          {
            loader: 'yaml-loader',
          },
        ],
      },
      {
        test: /.jsx?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
          },
        ],
      },
    ],
  },
  optimization: {
    runtimeChunk: 'single',
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery',
    }),
    new CopyWebpackPlugin([
      { from: path.join(ROOT, 'node_modules/reveal.js/css'), to: path.join(ROOT, 'public/css/reveal/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/css'), to: path.join(ROOT, 'public/js/reveal/lib/css') },
      { from: path.join(ROOT, 'node_modules/reveal.js/lib/js'), to: path.join(ROOT, 'public/js/reveal/lib/js') },
      { from: path.join(ROOT, 'node_modules/reveal.js/plugin'), to: path.join(ROOT, 'public/js/reveal/plugin/') },
    ]),
  ],
}

module.exports = config
<|endoftext|>


<commit_before>/* @flow */

import { MailParser }  from 'mailparser'
import { List, Map }   from 'immutable'
import assign          from 'object-assign'
import * as Kefir      from 'kefir'
import * as imap       from '../imap'
import { putIfAbsent } from './util'

import type { ReadStream } from 'fs'
import type { PouchDB }    from 'pouchdb'
import type { IndexedSeq } from 'immutable'
import type { Message, Thread, ThreadDoc, QueryResponseWithDoc } from './types'

function record(message: Message, db: PouchDB): Promise<ThreadDoc[]> {
  const _id = message.messageId
  const refs = (message.references || []).concat(_id)

  return Promise.all([
    db.query('indexes/byDanglingReference', { keys: refs, include_docs: true, limit: 999 }),
    db.query('indexes/byMessageId',         { keys: refs, include_docs: true, limit: 999 })
  ])
  .then(([dangling, convs]: [QueryResponseWithDoc<any,ThreadDoc>, QueryResponseWithDoc<any,ThreadDoc>]) => {
    if (dangling.total_rows + convs.total_rows < 1) {
      return db.post(newThread(message))
    }
    // else if (dangling.rows.length < dangling.total_rows || convs.rows.length < convs.total_rows) {
    //   throw new Error('handling paginated result sets is not handled yet')
    // }

    const docs = uniqBy(doc => doc._id, dangling.rows.concat(convs.rows).map(row => row.doc))
    return Promise.all(docs.map(doc => (
      db.put(insertMessage(message, doc))
    )))
  })
}

function parseMessage(messageStream: ReadStream): Stream<Object> {
  return Kefir.stream(emitter => {
    const mailparser = new MailParser({ includeMimeTree: true, streamAttachments: true })
    mailparser.on('end', mail => {
      emitter.emit(mail)
      emitter.end()
    })
    mailparser.on('error', err => {
      emitter.error(err)
    })
    messageStream.pipe(mailparser)
  })
}

function newThread(message: Message): { thread: Thread, type: 'thread' } {
  return {
    thread: [[message, []]],
    type: 'thread',
  }
}

function insertMessage(message: Message, doc: ThreadDoc): ThreadDoc {
  const msgs = uniqBy(
    m => m.messageId,
    List(doc.thread).flatMap(messages).push(message)
  )
  let [toplevel, replies] = partition(msg => (
    !msgs.some(m => ancestorOf(msg, m))
  ), msgs)
  const thread = toplevel.map(msg => assembleTree(msg, replies)).toArray()
  return assign({}, doc, { thread })
}

function assembleTree(message: Message, messages: List<Message>): [Message, Thread] {
  const replies = messages.filter(msg => msg !== message && ancestorOf(msg, message))
  const subthread = replies.map(msg => assembleTree(msg, replies))
  return [message, sortReplies(subthread).toArray()]
}

function messages([message, replies]: Thread): List<Message> {
  return List.of(message).concat(
    List(replies).flatMap(messages)
  )
}

function parentOf(msg: Message, msg_: Message): boolean {
  return !!msg.inReplyTo && msg.inReplyTo.some(ref => ref === msg_.messageId)
}

function ancestorOf(msg: Message, msg_: Message): boolean {
  return !!msg.references && msg.references.some(ref => ref === msg_.messageId)
}

function hasReferences(message: Message): boolean {
  return !!message.references && message.references.length > 0
}

type ImmutableThread = List<[Message, ImmutableThread]>

function sortReplies(replies: ImmutableThread): ImmutableThread {
  return replies.sortBy(([msg, _]) => msg.receivedDate)
}

function partition<T>(fn: (_: T) => boolean, xs: List<T>): [List<T>, List<T>] {
  const grouped = xs.groupBy(x => fn(x) ? 1 : 0)
  return [grouped.get(1, List()), grouped.get(0, List())]
}

function uniqBy<T,U>(fn: (_: T) => U, xs: IndexedSeq<T> | T[]): IndexedSeq<T> {
  const map: Map<U,T> = xs.reduce((m, x) => (
    m.set(fn(x), x)
  ), Map())
  return map.valueSeq()
}

export {
  parseMessage,
  record,
}
<commit_msg>Test row lengths in query responses, not total_rows count<commit_after>/* @flow */

import { MailParser }  from 'mailparser'
import { List, Map }   from 'immutable'
import assign          from 'object-assign'
import * as Kefir      from 'kefir'
import * as imap       from '../imap'
import { putIfAbsent } from './util'

import type { ReadStream } from 'fs'
import type { PouchDB }    from 'pouchdb'
import type { IndexedSeq } from 'immutable'
import type { Message, Thread, ThreadDoc, QueryResponseWithDoc } from './types'

function record(message: Message, db: PouchDB): Promise<ThreadDoc[]> {
  const _id = message.messageId
  const refs = (message.references || []).concat(_id)

  return Promise.all([
    db.query('indexes/byDanglingReference', { keys: refs, include_docs: true, limit: 999 }),
    db.query('indexes/byMessageId',         { keys: refs, include_docs: true, limit: 999 })
  ])
  .then(([dangling, convs]: [QueryResponseWithDoc<any,ThreadDoc>, QueryResponseWithDoc<any,ThreadDoc>]) => {
    if (dangling.rows.length + convs.rows.length < 1) {
      return db.post(newThread(message))
    }
    // TODO
    // else if (dangling.rows.length < dangling.total_rows || convs.rows.length < convs.total_rows) {
    //   throw new Error('handling paginated result sets is not handled yet')
    // }

    const docs = uniqBy(doc => doc._id, dangling.rows.concat(convs.rows).map(row => row.doc))
    return Promise.all(docs.map(doc => (
      db.put(insertMessage(message, doc))
    )))
  })
}

function parseMessage(messageStream: ReadStream): Stream<Object> {
  return Kefir.stream(emitter => {
    const mailparser = new MailParser({ includeMimeTree: true, streamAttachments: true })
    mailparser.on('end', mail => {
      emitter.emit(mail)
      emitter.end()
    })
    mailparser.on('error', err => {
      emitter.error(err)
    })
    messageStream.pipe(mailparser)
  })
}

function newThread(message: Message): { thread: Thread, type: 'thread' } {
  return {
    thread: [[message, []]],
    type: 'thread',
  }
}

function insertMessage(message: Message, doc: ThreadDoc): ThreadDoc {
  const msgs = uniqBy(
    m => m.messageId,
    List(doc.thread).flatMap(messages).push(message)
  )
  let [toplevel, replies] = partition(msg => (
    !msgs.some(m => ancestorOf(msg, m))
  ), msgs)
  const thread = toplevel.map(msg => assembleTree(msg, replies)).toArray()
  return assign({}, doc, { thread })
}

function assembleTree(message: Message, messages: List<Message>): [Message, Thread] {
  const replies = messages.filter(msg => msg !== message && ancestorOf(msg, message))
  const subthread = replies.map(msg => assembleTree(msg, replies))
  return [message, sortReplies(subthread).toArray()]
}

function messages([message, replies]: Thread): List<Message> {
  return List.of(message).concat(
    List(replies).flatMap(messages)
  )
}

function parentOf(msg: Message, msg_: Message): boolean {
  return !!msg.inReplyTo && msg.inReplyTo.some(ref => ref === msg_.messageId)
}

function ancestorOf(msg: Message, msg_: Message): boolean {
  return !!msg.references && msg.references.some(ref => ref === msg_.messageId)
}

function hasReferences(message: Message): boolean {
  return !!message.references && message.references.length > 0
}

type ImmutableThread = List<[Message, ImmutableThread]>

function sortReplies(replies: ImmutableThread): ImmutableThread {
  return replies.sortBy(([msg, _]) => msg.receivedDate)
}

function partition<T>(fn: (_: T) => boolean, xs: List<T>): [List<T>, List<T>] {
  const grouped = xs.groupBy(x => fn(x) ? 1 : 0)
  return [grouped.get(1, List()), grouped.get(0, List())]
}

function uniqBy<T,U>(fn: (_: T) => U, xs: IndexedSeq<T> | T[]): IndexedSeq<T> {
  const map: Map<U,T> = xs.reduce((m, x) => (
    m.set(fn(x), x)
  ), Map())
  return map.valueSeq()
}

export {
  parseMessage,
  record,
}
<|endoftext|>


<commit_before>//******************** MODEL ********************//
function Board(){
	this.rows = [[],[],[],[],[],[]];
	this.columns = [[],[],[],[],[],[],[]];
	this.players = [];
};

Board.prototype = {
	addPiece: function(column){
		// debugger
		var newPiece
		if (this.columns[column].length >= 6){
			console.log("adios")
		}
		else {
			console.log("whatup");
			newPiece = new Piece(currentColor)
			this.rows[this.columns[column].length].push(newPiece)
			this.columns[column].push(newPiece);

			if (currentColor === "red"){
				currentColor = "black";
			}	else {
				currentColor = "red";
			}

		}
	}
}

function Piece(color){
	this.color = color;
};

//************************************************//

//********************* VIEW *********************//

function drawBoard(){
	var createBoard = $('#board')
	for (var i = 1; i < 7; i++){
		createBoard.append('

')
		var newRow = $('#row' + i)
		for (var col = 1; col < 8; col++){
			newRow.append('	')
		}
	}
}

//************************************************//

//********************* CONTROLLER *********************//
$(document).ready(function() {
	drawBoard();
	gameBoard = new Board();
	currentColor = "red";

	$('.1').on("click", function(){
		gameBoard.addPiece(0);
	});
	$('.2').on("click", function(){
		gameBoard.addPiece(1);
	});
	$('.3').on("click", function(){
		gameBoard.addPiece(2);
	});
	$('.4').on("click", function(){
		gameBoard.addPiece(3);
	});
	$('.5').on("click", function(){
		gameBoard.addPiece(4);
	});
	$('.6').on("click", function(){
		gameBoard.addPiece(5);
	});
	$('.7').on("click", function(){
		gameBoard.addPiece(6);
	});

	var player_1 = prompt("Please enter the name of player 1", "type name here");
	var player_2 = prompt("Please enter the name of player 2", "type name here");
	$('#welcome').innerHTML = "Welcome to our JS Connect Four Game, " + player_1 + " and " + player_2 + ".";

});

//*****************************************************//

// add to the document.ready function above

<commit_msg>colors updating<commit_after>//******************** MODEL ********************//
function Board(){
	this.rows = [[],[],[],[],[],[]];
	this.columns = [[],[],[],[],[],[],[]];
	this.players = [];
};

Board.prototype = {
	addPiece: function(column){
		// debugger
		var newPiece
		var newRow = this.columns[column].length

		if (this.columns[column].length >= 6){
			console.log("adios")
		}
		else {
			console.log("whatup");
			newPiece = new Piece(currentColor)
			this.rows[newRow].push(newPiece)
			this.columns[column].push(newPiece);
			updateColors(newRow, column, newPiece)
			// debugger
			if (currentColor === "red"){
				currentColor = "black";
			}	else {
				currentColor = "red";
			}

		}
	}
}

function Piece(color){
	this.color = color;
	this.row = ""
	this.column = ""
};

//************************************************//

//********************* VIEW *********************//

function drawBoard(){
	var createBoard = $('#board')
	var rowClasses = ['a','b','c','d','e','f']
	for (var i = 1; i < 7; i++){
		createBoard.append('

')
		var newRow = $('#row' + i)
		for (var col = 1; col < 8; col++){
			newRow.append('	')
		}
		rowClasses.pop()
	}
}

function updateColors(row, col, object){
	var rowKeys = ['a', 'b', 'c', 'd', 'e', 'f']
	// debugger
$('.' + rowKeys[row] + '.' + (col + 1)).css('background-color', object.color)
}

//************************************************//

//********************* CONTROLLER *********************//
$(document).ready(function() {
	drawBoard();
	gameBoard = new Board();
	currentColor = "red";
	player1 = prompt("Please enter the name of player 1", "type name here");
	player2 = prompt("Please enter the name of player 2", "type name here");

	$('.1').on("click", function(){
		gameBoard.addPiece(0);
	});
	$('.2').on("click", function(){
		gameBoard.addPiece(1);
	});
	$('.3').on("click", function(){
		gameBoard.addPiece(2);
	});
	$('.4').on("click", function(){
		gameBoard.addPiece(3);
	});
	$('.5').on("click", function(){
		gameBoard.addPiece(4);
	});
	$('.6').on("click", function(){
		gameBoard.addPiece(5);
	});
	$('.7').on("click", function(){
		gameBoard.addPiece(6);
	});

	$('#welcome').innerHTML = "Welcome to our JS Connect Four Game, " + player1 + " and " + player2 + ".";

});

//*****************************************************//

// add to the document.ready function above

<|endoftext|>


<commit_before>var APILightbox = window.APILightbox ? window.APILightbox : {};

// function called by eval-ing response from Flickr
function jsonFlickrApi(response) {
  if(response.stat == 'ok') {
    APILightbox.populateResults(response);
  }
}

APILightbox = {
  flickrApiKey:      '7b491816b7ce18f1f848e52962352ee7',
  flickrRestUrlBase: 'https://www.flickr.com/services/rest/',
  searchText:        'delphinium',
  currentPhotoIndex: 0,
  maxPhotoIndex:     24,
  photos:            {},

  utils: {
    hide: function(element) {
      element.className = element.className.replace(/\sshow/i, '');
      element.className += ' hide';
    },

    show: function(element, height) {
      element.className = element.className.replace(/\shide/i, '');
      element.className += ' show';
      element.style     = "height: " + height + ";";
    },

    sanitizeInput: function(string) {
      danger = [
        /<script[^>]*?>.*?<\/script>/gi, // Strip out javascript
        /<style[^>]*?>.*?<\/style>/gi,   // Strip style tags
        /<![\s\S]*?--[ \t\n\r]*>/gi,     // Strip multi-line comments
        /<[\/\!]*?[^<>]*?>/gi            // Strip out HTML tags
      ];

      for(var i = 0; i < danger.length; i++) {
        string = string.replace(danger[i], '');
      }

      // Also collapse multiple spaces down to one
      string = string.replace(/\s+/, ' ');

      return string;
    },

    ajax: function(method, url, data, callback, type) {
      var xhr                = new XMLHttpRequest();
      xhr.onreadystatechange = readystatechange;
      xhr.responseType       = type ? type : "";
      xhr.open(method, url);
      xhr.send(data && JSON.stringify(data));

      function readystatechange() {
        if(xhr.readyState == xhr.DONE) {
          if(xhr.status == 200) {
            callback(xhr.status, xhr.response);
          } else {
            callback(xhr.status, null);
          }
        }
      }
    },

    buildUrlParams: function(options) {
      var params = "?";
      for(var key in options) {
        value = options[key];

        if(typeof key == "string" && typeof value == "string") {
          params += key + "=" + value + "&";
        }
      }
      // Remove that extraneous last '&'
      params = params.replace(/&$/, '');

      return params;
    },

    buildFlickrOptions: function(options) {
      options         = options ? options : {};

      options.format  = 'json';
      options.api_key = APILightbox.flickrApiKey;

      return options;
    },

    buildFlickrPhotoUrl: function(photo) {
      /*
      ** Flickr photo urls take the following format:
      **
      ** https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}_{size}.jpg
      */

      return "https://farm" + photo.farm +
             ".staticflickr.com/" + photo.server + "/" +
             photo.id + "_" + photo.secret + "_" + "c.jpg";
    }
  },

  getImages: function(searchText, maxCount) {
    var flickrMaxCountPerPage = 500;

    if(maxCount && typeof (maxCount * 1) == 'number' &&
       maxCount <= flickrMaxCountPerPage &&
       maxCount != APILightbox.maxPhotoIndex + 1) {
      APILightbox.maxPhotoIndex = maxCount;
    }

    if(searchText && typeof searchText == 'string') {
      APILightbox.searchText = searchText;
    }

    var flickrOptions = {
      method:       'flickr.photos.search',
      text:         searchText ? searchText : APILightbox.searchText,
      page:         1,
      per_page:     maxCount ? maxCount : APILightbox.maxPhotoIndex + 1,
      media:        'photos',
      content_type: 1
    };

    flickrOptions = APILightbox.utils.buildFlickrOptions(flickrOptions);

    var url = APILightbox.flickrRestUrlBase;

    url += APILightbox.utils.buildUrlParams(flickrOptions);

    APILightbox.utils.ajax('get', url, null, function(status, response) {
      if(status == 200) {
        eval(response);
      }
    });
  },

  populateResults: function(response) {
    var searchString = document.querySelectorAll('h1 .search-string')[0];

    if(response.photos.total * 1 > 0) {
      APILightbox.photos = response.photos;
      APILightbox.showImage(0, response.photos);
      searchString.innerText = APILightbox.searchText;
    } else {
      searchString.innerText = "No results found.";
    }
  },

  showImage: function(index) {
    var title = document.querySelectorAll('.lightbox .title')[0],
        image = document.querySelectorAll('.response .photo')[0];

    APILightbox.currentPhotoIndex = index;
    photo                         = APILightbox.photos.photo[index];
    title.innerText               = photo.title;
    image.src                     = APILightbox.utils.buildFlickrPhotoUrl(photo);
  },

  showPreviousImage: function() {
    var previousIndex = APILightbox.currentPhotoIndex - 1;
    if(previousIndex < 0) previousIndex = APILightbox.maxPhotoIndex;

    APILightbox.showImage(previousIndex);
  },

  showNextImage: function() {
    var nextIndex = APILightbox.currentPhotoIndex + 1;
    if(nextIndex > APILightbox.maxPhotoIndex) nextIndex = 0;

    APILightbox.showImage(nextIndex);
  },

  showSearchForm: function() {
    var searchForm  = document.querySelectorAll('.search-form')[0],
        searchInput = document.querySelectorAll('.search-form .search-keywords')[0];

    searchInput.value = '';
    APILightbox.utils.show(searchForm, '30px');
    searchInput.focus();
  },

  checkEnter: function(event) {
    var characterCode = event.keyCode;

    if(characterCode == 13) { // if enter key
      APILightbox.doSearch();
      return false;
    } else {
      return true;
    }
  },

  doSearch: function() {
    var searchForm   = document.querySelectorAll('.search-form')[0],
        searchString = document.querySelectorAll('.page-title .search-string')[0],
        searchInput  = document.querySelectorAll('.search-form .search-keywords')[0];

    var keywords = APILightbox.utils.sanitizeInput(searchInput.value);
    if(keywords != '' && keywords != ' ')
    {
      APILightbox.getImages(keywords);
      APILightbox.utils.hide(searchForm);
    }
  },

  initialize: function() {
    var edit        = document.querySelectorAll('.page-title .edit')[0],
        searchInput = document.querySelectorAll('.search-form .search-keywords')[0],
        search      = document.querySelectorAll('.search-form .search')[0],
        previous    = document.querySelectorAll('.lightbox .paging-controls .previous')[0],
        next        = document.querySelectorAll('.lightbox .paging-controls .next')[0];

    edit.addEventListener('click', APILightbox.showSearchForm, false);
    searchInput.addEventListener('keypress', APILightbox.checkEnter, false);
    search.addEventListener('click', APILightbox.doSearch, false);
    previous.addEventListener('click', APILightbox.showPreviousImage, false);
    next.addEventListener('click', APILightbox.showNextImage, false);
  }
};
<commit_msg>Remove fatal flaw.<commit_after>var APILightbox = window.APILightbox ? window.APILightbox : {};

// function called by eval-ing response from Flickr
function jsonFlickrApi(response) {
  if(response.stat == 'ok') {
    APILightbox.populateResults(response);
  }
}

APILightbox = {
  flickrApiKey:      '7b491816b7ce18f1f848e52962352ee7',
  flickrRestUrlBase: 'https://www.flickr.com/services/rest/',
  searchText:        'delphinium',
  currentPhotoIndex: 0,
  maxPhotoIndex:     24,
  photos:            {},

  utils: {
    hide: function(element) {
      element.className = element.className.replace(/\sshow/i, '');
      element.className += ' hide';
    },

    show: function(element, height) {
      element.className = element.className.replace(/\shide/i, '');
      element.className += ' show';
      element.style     = "height: " + height + ";";
    },

    sanitizeInput: function(string) {
      danger = [
        /<script[^>]*?>.*?<\/script>/gi, // Strip out javascript
        /<style[^>]*?>.*?<\/style>/gi,   // Strip style tags
        /<![\s\S]*?--[ \t\n\r]*>/gi,     // Strip multi-line comments
        /<[\/\!]*?[^<>]*?>/gi            // Strip out HTML tags
      ];

      for(var i = 0; i < danger.length; i++) {
        string = string.replace(danger[i], '');
      }

      // Also collapse multiple spaces down to one
      string = string.replace(/\s+/, ' ');

      return string;
    },

    ajax: function(method, url, data, callback, type) {
      var xhr                = new XMLHttpRequest();
      xhr.onreadystatechange = readystatechange;
      xhr.responseType       = type ? type : "";
      xhr.open(method, url);
      xhr.send(data && JSON.stringify(data));

      function readystatechange() {
        if(xhr.readyState == xhr.DONE) {
          if(xhr.status == 200) {
            callback(xhr.status, xhr.response);
          } else {
            callback(xhr.status, null);
          }
        }
      }
    },

    buildUrlParams: function(options) {
      var params = "?";
      for(var key in options) {
        value = options[key];

        if(typeof key == "string" && typeof value == "string") {
          params += key + "=" + value + "&";
        }
      }
      // Remove that extraneous last '&'
      params = params.replace(/&$/, '');

      return params;
    },

    buildFlickrOptions: function(options) {
      options         = options ? options : {};

      options.format  = 'json';
      options.api_key = APILightbox.flickrApiKey;

      return options;
    },

    buildFlickrPhotoUrl: function(photo) {
      /*
      ** Flickr photo urls take the following format:
      **
      ** https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}_{size}.jpg
      */

      return "https://farm" + photo.farm +
             ".staticflickr.com/" + photo.server + "/" +
             photo.id + "_" + photo.secret + "_" + "c.jpg";
    }
  },

  getImages: function(searchText, maxCount) {
    var flickrMaxCountPerPage = 500;

    if(maxCount && typeof (maxCount * 1) == 'number' &&
       maxCount <= flickrMaxCountPerPage &&
       maxCount != APILightbox.maxPhotoIndex + 1) {
      APILightbox.maxPhotoIndex = maxCount;
    }

    if(searchText && typeof searchText == 'string') {
      APILightbox.searchText = searchText;
    }

    var flickrOptions = {
      method:       'flickr.photos.search',
      text:         searchText ? searchText : APILightbox.searchText,
      page:         1,
      per_page:     maxCount ? maxCount : APILightbox.maxPhotoIndex + 1,
      media:        'photos',
      content_type: 1
    };

    flickrOptions = APILightbox.utils.buildFlickrOptions(flickrOptions);

    var url = APILightbox.flickrRestUrlBase;

    url += APILightbox.utils.buildUrlParams(flickrOptions);

    APILightbox.utils.ajax('get', url, null, function(status, response) {
      if(status == 200) {

      }
    });
  },

  populateResults: function(response) {
    var searchString = document.querySelectorAll('h1 .search-string')[0];

    if(response.photos.total * 1 > 0) {
      APILightbox.photos = response.photos;
      APILightbox.showImage(0, response.photos);
      searchString.innerText = APILightbox.searchText;
    } else {
      searchString.innerText = "No results found.";
    }
  },

  showImage: function(index) {
    var title = document.querySelectorAll('.lightbox .title')[0],
        image = document.querySelectorAll('.response .photo')[0];

    APILightbox.currentPhotoIndex = index;
    photo                         = APILightbox.photos.photo[index];
    title.innerText               = photo.title;
    image.src                     = APILightbox.utils.buildFlickrPhotoUrl(photo);
  },

  showPreviousImage: function() {
    var previousIndex = APILightbox.currentPhotoIndex - 1;
    if(previousIndex < 0) previousIndex = APILightbox.maxPhotoIndex;

    APILightbox.showImage(previousIndex);
  },

  showNextImage: function() {
    var nextIndex = APILightbox.currentPhotoIndex + 1;
    if(nextIndex > APILightbox.maxPhotoIndex) nextIndex = 0;

    APILightbox.showImage(nextIndex);
  },

  showSearchForm: function() {
    var searchForm  = document.querySelectorAll('.search-form')[0],
        searchInput = document.querySelectorAll('.search-form .search-keywords')[0];

    searchInput.value = '';
    APILightbox.utils.show(searchForm, '30px');
    searchInput.focus();
  },

  checkEnter: function(event) {
    var characterCode = event.keyCode;

    if(characterCode == 13) { // if enter key
      APILightbox.doSearch();
      return false;
    } else {
      return true;
    }
  },

  doSearch: function() {
    var searchForm   = document.querySelectorAll('.search-form')[0],
        searchString = document.querySelectorAll('.page-title .search-string')[0],
        searchInput  = document.querySelectorAll('.search-form .search-keywords')[0];

    var keywords = APILightbox.utils.sanitizeInput(searchInput.value);
    if(keywords != '' && keywords != ' ')
    {
      APILightbox.getImages(keywords);
      APILightbox.utils.hide(searchForm);
    }
  },

  initialize: function() {
    var edit        = document.querySelectorAll('.page-title .edit')[0],
        searchInput = document.querySelectorAll('.search-form .search-keywords')[0],
        search      = document.querySelectorAll('.search-form .search')[0],
        previous    = document.querySelectorAll('.lightbox .paging-controls .previous')[0],
        next        = document.querySelectorAll('.lightbox .paging-controls .next')[0];

    edit.addEventListener('click', APILightbox.showSearchForm, false);
    searchInput.addEventListener('keypress', APILightbox.checkEnter, false);
    search.addEventListener('click', APILightbox.doSearch, false);
    previous.addEventListener('click', APILightbox.showPreviousImage, false);
    next.addEventListener('click', APILightbox.showNextImage, false);
  }
};
<|endoftext|>


<commit_before>// Casino start point

import "jquery";
import "bootstrap";
import * as validate from "validator";
import * as slotMachine from "slotMachine";
import * as blackjack from "blackjack";
import * as models from "models";

var user = new models.User('Pesho');
showMenu();

export function getUserMoney() {
    return user.money;
}

export function setUserMoney(value) {
    user.money = value;
}

export function showMenu() {
    if ($("#gameField").find("#menu").length === 0) {
        $("#gameField")
            .append("

");

        $("#menu")
            .append("
Casino MOTARO
")
            .append("");
    }

    if (!validate.isUserLogged()) {
        showLoginForm();
    }

    $("#menu")
        .append(`

                        Blackjack

                        Roulette

                        Slot Machine

`)
        .append("<link rel='stylesheet' href='style/menu.css'>");

    $("#menu-item-one").on("click", function() {
        if (!validate.isUserLogged()) {
            let targetId = "#" + $(this).attr("id");
            showErrorMessage(targetId, validate.constants().USER_NOT_LOGGED_MESSAGE);
        } else {
            blackjack.loadGame();
        }

    });

    $("#menu-item-two").on("click", function() {
        if (!validate.isUserLogged()) {
            let targetId = "#" + $(this).attr("id");
            showErrorMessage(targetId, validate.constants().USER_NOT_LOGGED_MESSAGE);
        }

    });

    $("#menu-item-three").on("click", function() {
        if (!validate.isUserLogged()) {
            let targetId = "#" + $(this).attr("id");
            showErrorMessage(targetId, validate.constants().USER_NOT_LOGGED_MESSAGE);
        } else {
            slotMachine.loadGame();
        }
    });
}

function showLoginForm() {
    $("#menu")
        .append(`<form class="col-md-12">

                            <input type="text" class="form-control input-medium" placeholder="Email">

                            <input type="password" class="form-control input-medium" placeholder="Password">

                            <button class="btn btn-warning btn-medium btn-block">Sign In</button>
                            New Registration

                    </form>`);
}

function showErrorMessage(targetId, message) {
    $(targetId)
        .attr("data-toggle", "modal")
        .attr("data-target", "#errorMessage");

    let p = $("#menu").find("#errorMessage");
    if (!p.length) {
        $("#menu")
            .append(`

                                    <button type="button" class="close" data-dismiss="modal">×</button>

Error

${message}

                                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

`);
    } else {
        $("#menu .modal-body p").html(message);
    }
}<commit_msg>fixed accumulation of links after back to menu again :-)<commit_after>// Casino start point

import "jquery";
import "bootstrap";
import * as validate from "validator";
import * as slotMachine from "slotMachine";
import * as blackjack from "blackjack";
import * as models from "models";

var user = new models.User('Pesho');
showMenu();

export function getUserMoney() {
    return user.money;
}

export function setUserMoney(value) {
    user.money = value;
}

export function showMenu() {
    if ($("#gameField").find("#menu").length === 0) {
        $("#gameField")
            .append("

");

        $("#menu")
            .append("
Casino MOTARO
")
            .append("")
            .append("<link rel='stylesheet' href='style/menu.css'>");
    }

    if (!validate.isUserLogged()) {
        showLoginForm();
    }

    $("#menu")
        .append(`

                        Blackjack

                        Roulette

                        Slot Machine

`);

    $("#menu-item-one").on("click", function() {
        if (!validate.isUserLogged()) {
            let targetId = "#" + $(this).attr("id");
            showErrorMessage(targetId, validate.constants().USER_NOT_LOGGED_MESSAGE);
        } else {
            blackjack.loadGame();
        }

    });

    $("#menu-item-two").on("click", function() {
        if (!validate.isUserLogged()) {
            let targetId = "#" + $(this).attr("id");
            showErrorMessage(targetId, validate.constants().USER_NOT_LOGGED_MESSAGE);
        }

    });

    $("#menu-item-three").on("click", function() {
        if (!validate.isUserLogged()) {
            let targetId = "#" + $(this).attr("id");
            showErrorMessage(targetId, validate.constants().USER_NOT_LOGGED_MESSAGE);
        } else {
            slotMachine.loadGame();
        }
    });
}

function showLoginForm() {
    $("#menu")
        .append(`<form class="col-md-12">

                            <input type="text" class="form-control input-medium" placeholder="Email">

                            <input type="password" class="form-control input-medium" placeholder="Password">

                            <button class="btn btn-warning btn-medium btn-block">Sign In</button>
                            New Registration

                    </form>`);
}

function showErrorMessage(targetId, message) {
    $(targetId)
        .attr("data-toggle", "modal")
        .attr("data-target", "#errorMessage");

    let p = $("#menu").find("#errorMessage");
    if (!p.length) {
        $("#menu")
            .append(`

                                    <button type="button" class="close" data-dismiss="modal">×</button>

Error

${message}

                                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>

`);
    } else {
        $("#menu .modal-body p").html(message);
    }
}<|endoftext|>


<commit_before>require("es6-shim");

var TournamentGenerators = {
	RoundRobin = require('./generator-round-robin.js').RoundRobin;
};

var tournaments = {};

function usersToNames(users) {
	return users.map(function (user) { return user.name; });
}

function createTournament(name, format, generator, output) {
	var id = toId(name);
	if (tournaments[id]) {
		output.sendReply("A tournament with the same name already exists.");
		return;
	}
	if (Tools.getFormat(format).effectType !== 'Format') {
		output.sendReply(format + " is not a valid format.");
		output.sendReply("Valid formats: " + Object.keys(Tools.data.Formats).filter(function (f) { return Tools.data.Formats[f].effectType === 'Format'; }).join(", "));
		return;
	}
	if (!TournamentGenerators[generator]) {
		output.sendReply(generator + " is not a valid generator.");
		output.sendReply("Valid generators: " + Object.keys(TournamentGenerators).join(", "));
		return;
	}
	return tournaments[id] = new Tournament(name, format, new TournamentGenerators[generator](), output);
}
function deleteTournament(name, output) {
	var id = toId(name);
	var tournament = tournaments[id];
	if (!tournament)
		output.sendReply(name + " doesn't exist.");
	tournament.forceEnd(output);
	delete tournaments[id];
}
function getTournament(name, output) {
	if (tournaments[toId(name)])
		return tournaments;
}

var Tournament = (function () {
	function Tournament(name, format, generator, output) {
		this.name = toName(name);
		this.format = format;
		this.generator = generator;

		this.isBracketInvalidated = true;
		this.bracketCache = null;

		this.isTournamentStarted = false;
		this.availableMatches = null;
		this.inProgressMatches = null;

		this.isAvailableMatchesInvalidated = true;
		this.availableMatchesCache = null;

		this.pendingChallenges = null;

		output.add('|tournament|' + this.name + '|create');
		this.update(output);
	}

	Tournament.prototype.setGenerator(generator, output) {
		if (this.isTournamentStarted) {
			output.sendReply('|tournament|' + this.name + '|error|BracketFrozen');
			return;
		}

		var isErrored = false;
		this.generator.getUsers.forEach(function (user) {
			var error = generator.addUser(user);
			if (typeof error === 'string') {
				output.sendReply('|tournament|' + this.name + '|error|' + error);
				isErrored = true;
			}
		});

		if (isErrored)
			return;

		this.generator = generator;
		this.isBracketInvalidated = true;
		this.update(output);
	};

	Tournament.prototype.forceEnd(output) {
		output.add('|tournament' + this.name + '|forceend');
	};

	Tournament.prototype.update = function (output) {
		output.send('|tournament|' + this.name + '|update');
		output.send('|tournament|' + this.name + '|info|' + JSON.stringify({
			isStarted: this.isTournamentStarted,
			format: this.format,
			generator: this.generator.name
		}));

		this.getBracketData(output);

		if (this.isTournamentStarted) {
			this.getAvailableMatches(output);
			this.pendingChallenges.forEach(function (challenge, user) {
				if (challenge.to)
					user.send('|tournament|' + this.name + '|challenging|' + challenge.to.name);
				else if (challenge.from)
					user.send('|tournament|' + this.name + '|challenged|' + challenge.from.name);
			});
		}
	};

	Tournament.prototype.addUser = function (user, output) {
		var error = this.generator.addUser(user);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		output.send('|tournament|' + this.name + '|join|' + user.name);
		this.isBracketInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.removeUser = function (user, output) {
		var error = this.generator.removeUser(user);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		output.send('|tournament|' + this.name + '|leave|' + user.name);
		this.isBracketInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.replaceUser = function (user, replacementUser, output) {
		var error = this.generator.replaceUser(user, replacementUser);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		output.send('|tournament|' + this.name + '|replace|' + user.name + '|' + replacementUser.name);
		this.isBracketInvalidated = true;
		this.update(output);
	};

	Tournament.prototype.getBracketData = function (output) {
		// TODO: Add in-progress view
		if (this.isBracketInvalidated) {
			var data = this.generator.getBracketData();
			if (data.type === 'tree') {
				// TODO
			} else if (data.type === 'table') {
				data.tableHeaders.cols = usersToNames(data.tableHeaders.cols);
				data.tableHeaders.rows = usersToNames(data.tableHeaders.rows);
				data.tableContents.forEach(function (row) {
					row.forEach(function (cell) {
						if (cell)
							cell.teams = usersToNames(cell.teams);
					});
				});
				data.scores.forEach(function (score) {
					score.team = score.team.name;
				});
			}

			this.bracketCache = JSON.stringify(data);
			this.isBracketInvalidated = false;
		}

		output.send('|tournament|' + this.name + '|bracketdata|' + this.bracketCache);.
	};

	Tournament.prototype.startTournament = function (output) {
		this.generator.freezeBracket();

		this.availableMatches = new Map();
		this.inProgressMatches = new Map();
		this.pendingChallenges = new Map();
		var users = this.generator.getUsers();
		users.forEach(function (user) {
			var availableMatches = new Map();
			users.forEach(function (user) {
				availableMatches.set(user, false);
			});
			this.availableMatches.set(user, availableMatches);
			this.inProgressMatches.set(user, null);
			this.pendingChallenges.set(user, null);
		}, this);

		this.isTournamentStarted = true;
		this.isBracketInvalidated = true;
		output.add('|tournament|' + this.name + '|start');
		this.update(output);
	};
	Tournament.prototype.getAvailableMatches = function (output) {
		if (this.isAvailableMatchesInvalidated) {
			var matches = this.generator.getAvailableMatches();
			if (typeof matches === 'string') {
				output.sendReply('|tournament|' + this.name + '|error|' + error);
				return;
			}

			var users = this.generator.getUsers();
			var challenges = new Map();
			var challengeBys = new Map();

			users.forEach(function (user) {
				challenges.set(user, []);
				challengeBys.set(user, []);

				var availableMatches = this.availableMatches.get(user);
				users.forEach(function (user) {
					availableMatches.set(user, false);
				});
			}, this);

			matches.forEach(function (match) {
				challenges.get(match[0]).push(match[1]);
				challengeBys.get(match[1]).push(match[0]);

				this.availableMatches.get(match[0]).set(match[1], true);
			});

			this.availableMatchesCache = {
				challenges: challenges,
				challengeBys: challengeBys
			};
			this.isAvailableMatchesInvalidated = false;
		}

		this.availableMatchesCache.challenges.forEach(function (opponents, user) {
			if (opponents.length > 0)
				user.send('|tournament|' + this.name + '|challenges|' + usersToNames(opponents).join(','));
		});
		this.availableMatchesCache.challengeBys.forEach(function (opponents, user) {
			if (opponents.length > 0)
				user.send('|tournament|' + this.name + '|challengeBys|' + usersToNames(opponents).join(','));
		});
	};

	Tournament.prototype.disqualifyUser = function (user, output) {
		var error = this.generator.disqualifyUser(user);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		this.generator.setUserBusy(user, false);

		var challenge = this.pendingChallenges.get(user);
		if (challenge) {
			this.pendingChallenges.set(user, null);
			if (challenge.to) {
				this.generator.setUserBusy(challenge.to, false);
				this.pendingChallenges.set(challenge.to, null);
			} else if (challenge.from) {
				this.generator.setUserBusy(challenge.from, false);
				this.pendingChallenges.set(challenge.from, null);
			}
		}

		var matchFrom = this.inProgressMatches.get(user);
		if (matchFrom) {
			this.generator.setUserBusy(matchFrom.to, false);
			this.inProgressMatches.set(user, null);
			matchFrom.room.forfeit(user);
		}

		var matchTo = null;
		this.inProgressMatches.forEach(function (match, userFrom) {
			if (match && match.to === user)
				matchTo = userFrom;
		});
		if (matchTo) {
			this.generator.setUserBusy(matchTo, false);
			this.inProgressMatches.get(matchTo).room.forfeit(user);
			this.inProgressMatches.set(matchTo, null);
		}

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);
	};

	Tournament.prototype.challenge = function (from, to, output) {
		if (!this.availableMatches.get(from).get(to)) {
			output.sendReply('|tournament|' + this.name + '|error|InvalidMatch')
			return;
		}
		if (this.generator.getUserBusy(from) || this.generator.getUserBusy(to)) {
			output.add("Tournament backend breaks specifications. Please report this to an admin.");
			return;
		}

		this.generator.setUserBusy(from, true);
		this.generator.setUserBusy(to, true);
		this.pendingChallenges.set(from, {to: to});
		this.pendingChallenges.set(to, {from: from});

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.cancelChallenge = function (user, output) {
		var challenge = this.pendingChallenges.get(user);
		if (!challenge || challenge.from)
			return;

		this.generator.setUserBusy(user, false);
		this.generator.setUserBusy(challenge.to, false);
		this.pendingChallenges.set(user, null);
		this.pendingChallenges.set(challenge.to, null);

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.acceptChallenge = function (user, output) {
		var challenge = this.pendingChallenges.get(user);
		if (!challenge || !challenge.from)
			return;

		this.pendingChallenges.set(challenge.from, null);
		this.pendingChallenges.set(user, null);

		var room = Rooms.global.startBattle(challenge.from, user, this.format, true, challenge.from.team, user.team);
		this.inProgressMatches.set(challenge.from, {to: user, room: room});
		output.send('|tournament|' + this.name + '|battlestart|' + challenge.from.name + '|' + user.name + '|' + room.id);

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);

		var self = this;
		room._win = room.win;
		room.win = function (winner) {
			self.onBattleWin(this, Users.get(winner), output);
			this._win(winner);
		};
	};
	Tournament.prototype.onBattleWin = function (room, winner, output) {
		var from = Users.get(room.p1);
		var to = Users.get(room.p2);

		var result = 'draw';
		if (from === winner)
			result = 'win';
		else if (to === winner)
			result = 'loss';
		var isTournamentEnded = this.generator.setMatchResult([from, to], result, room.battle.score);
		if (typeof isTournamentEnded === 'string') {
			// Should never happen
			output.add("Unexpected " + isTournamentEnded + " from setMatchResult() in onBattleWin(" + room.id + ", " + winner.id + ", ...). Please report this to an admin.");
			return;
		}

		output.send('|tournament|' + this.name + '|battleend|' + challenge.from.name + '|' + user.name + '|' + result + '|' + room.battle.score.join(','));

		this.generator.setUserBusy(from, false);
		this.generator.setUserBusy(to, false);
		this.inProgressMatches.set(from, null);

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);

		if (isTournamentEnded)
			this.onTournamentEnd(output);
	};
	Tournament.prototype.onTournamentEnd = function (output) {
		var results = this.generator.getResults();
		output.add('|tournament|' + this.name + '|end|' + usersToNames(results[0]).join(',') + (results[1] ? usersToNames(results[1]).join(',') : ''));
	};

	return Tournament;
})();

exports.Tournament = Tournament;
exports.TournamentGenerators = TournamentGenerators;

exports.createTournament = createTournament;
exports.destroyTournament = destroyTournament;
exports.getTournament = getTournament;
exports.tournaments = tournaments;
<commit_msg>Fix some bugs<commit_after>require("es6-shim");

var TournamentGenerators = {
	RoundRobin: require('./generator-round-robin.js').RoundRobin
};

var tournaments = {};

function usersToNames(users) {
	return users.map(function (user) { return user.name; });
}

function createTournament(name, format, generator, output) {
	var id = toId(name);
	if (tournaments[id]) {
		output.sendReply("A tournament with the same name already exists.");
		return;
	}
	if (Tools.getFormat(format).effectType !== 'Format') {
		output.sendReply(format + " is not a valid format.");
		output.sendReply("Valid formats: " + Object.keys(Tools.data.Formats).filter(function (f) { return Tools.data.Formats[f].effectType === 'Format'; }).join(", "));
		return;
	}
	if (!TournamentGenerators[generator]) {
		output.sendReply(generator + " is not a valid generator.");
		output.sendReply("Valid generators: " + Object.keys(TournamentGenerators).join(", "));
		return;
	}
	return tournaments[id] = new Tournament(name, format, new TournamentGenerators[generator](), output);
}
function deleteTournament(name, output) {
	var id = toId(name);
	var tournament = tournaments[id];
	if (!tournament)
		output.sendReply(name + " doesn't exist.");
	tournament.forceEnd(output);
	delete tournaments[id];
}
function getTournament(name, output) {
	var id = toId(name);
	if (tournaments[id])
		return tournaments[id];
}

var Tournament = (function () {
	function Tournament(name, format, generator, output) {
		this.name = toName(name);
		this.format = format;
		this.generator = generator;

		this.isBracketInvalidated = true;
		this.bracketCache = null;

		this.isTournamentStarted = false;
		this.availableMatches = null;
		this.inProgressMatches = null;

		this.isAvailableMatchesInvalidated = true;
		this.availableMatchesCache = null;

		this.pendingChallenges = null;

		output.add('|tournament|' + this.name + '|create');
		this.update(output);
	}

	Tournament.prototype.setGenerator = function (generator, output) {
		if (this.isTournamentStarted) {
			output.sendReply('|tournament|' + this.name + '|error|BracketFrozen');
			return;
		}

		var isErrored = false;
		this.generator.getUsers.forEach(function (user) {
			var error = generator.addUser(user);
			if (typeof error === 'string') {
				output.sendReply('|tournament|' + this.name + '|error|' + error);
				isErrored = true;
			}
		});

		if (isErrored)
			return;

		this.generator = generator;
		this.isBracketInvalidated = true;
		this.update(output);
	};

	Tournament.prototype.forceEnd = function (output) {
		output.add('|tournament' + this.name + '|forceend');
	};

	Tournament.prototype.update = function (output) {
		output.send('|tournament|' + this.name + '|update');
		output.send('|tournament|' + this.name + '|info|' + JSON.stringify({
			isStarted: this.isTournamentStarted,
			format: this.format,
			generator: this.generator.name
		}));

		this.getBracketData(output);

		if (this.isTournamentStarted) {
			this.getAvailableMatches(output);
			this.pendingChallenges.forEach(function (challenge, user) {
				if (!challenge)
					return;
				if (challenge.to)
					user.send('|tournament|' + this.name + '|challenging|' + challenge.to.name);
				else if (challenge.from)
					user.send('|tournament|' + this.name + '|challenged|' + challenge.from.name);
			}, this);
		}
	};

	Tournament.prototype.addUser = function (user, output) {
		var error = this.generator.addUser(user);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		output.send('|tournament|' + this.name + '|join|' + user.name);
		this.isBracketInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.removeUser = function (user, output) {
		var error = this.generator.removeUser(user);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		output.send('|tournament|' + this.name + '|leave|' + user.name);
		this.isBracketInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.replaceUser = function (user, replacementUser, output) {
		var error = this.generator.replaceUser(user, replacementUser);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		output.send('|tournament|' + this.name + '|replace|' + user.name + '|' + replacementUser.name);
		this.isBracketInvalidated = true;
		this.update(output);
	};

	Tournament.prototype.getBracketData = function (output) {
		// TODO: Add in-progress view
		if (this.isBracketInvalidated) {
			var data = this.generator.getBracketData();
			if (data.type === 'tree') {
				// TODO
			} else if (data.type === 'table') {
				data.tableHeaders.cols = usersToNames(data.tableHeaders.cols);
				data.tableHeaders.rows = usersToNames(data.tableHeaders.rows);
				data.tableContents.forEach(function (row) {
					row.forEach(function (cell) {
						if (cell)
							cell.teams = usersToNames(cell.teams);
					});
				});
				data.scores.forEach(function (score) {
					score.team = score.team.name;
				});
			}

			this.bracketCache = JSON.stringify(data);
			this.isBracketInvalidated = false;
		}

		output.send('|tournament|' + this.name + '|bracketdata|' + this.bracketCache);
	};

	Tournament.prototype.startTournament = function (output) {
		this.generator.freezeBracket();

		this.availableMatches = new Map();
		this.inProgressMatches = new Map();
		this.pendingChallenges = new Map();
		var users = this.generator.getUsers();
		users.forEach(function (user) {
			var availableMatches = new Map();
			users.forEach(function (user) {
				availableMatches.set(user, false);
			});
			this.availableMatches.set(user, availableMatches);
			this.inProgressMatches.set(user, null);
			this.pendingChallenges.set(user, null);
		}, this);

		this.isTournamentStarted = true;
		this.isBracketInvalidated = true;
		output.add('|tournament|' + this.name + '|start');
		this.update(output);
	};
	Tournament.prototype.getAvailableMatches = function (output) {
		if (this.isAvailableMatchesInvalidated) {
			var matches = this.generator.getAvailableMatches();
			if (typeof matches === 'string') {
				output.sendReply('|tournament|' + this.name + '|error|' + error);
				return;
			}

			var users = this.generator.getUsers();
			var challenges = new Map();
			var challengeBys = new Map();

			users.forEach(function (user) {
				challenges.set(user, []);
				challengeBys.set(user, []);

				var availableMatches = this.availableMatches.get(user);
				users.forEach(function (user) {
					availableMatches.set(user, false);
				});
			}, this);

			matches.forEach(function (match) {
				challenges.get(match[0]).push(match[1]);
				challengeBys.get(match[1]).push(match[0]);

				this.availableMatches.get(match[0]).set(match[1], true);
			}, this);

			this.availableMatchesCache = {
				challenges: challenges,
				challengeBys: challengeBys
			};
			this.isAvailableMatchesInvalidated = false;
		}

		this.availableMatchesCache.challenges.forEach(function (opponents, user) {
			if (opponents.length > 0)
				user.send('|tournament|' + this.name + '|challenges|' + usersToNames(opponents).join(','));
		}, this);
		this.availableMatchesCache.challengeBys.forEach(function (opponents, user) {
			if (opponents.length > 0)
				user.send('|tournament|' + this.name + '|challengeBys|' + usersToNames(opponents).join(','));
		}, this);
	};

	Tournament.prototype.disqualifyUser = function (user, output) {
		var error = this.generator.disqualifyUser(user);
		if (typeof error === 'string') {
			output.sendReply('|tournament|' + this.name + '|error|' + error);
			return;
		}

		this.generator.setUserBusy(user, false);

		var challenge = this.pendingChallenges.get(user);
		if (challenge) {
			this.pendingChallenges.set(user, null);
			if (challenge.to) {
				this.generator.setUserBusy(challenge.to, false);
				this.pendingChallenges.set(challenge.to, null);
			} else if (challenge.from) {
				this.generator.setUserBusy(challenge.from, false);
				this.pendingChallenges.set(challenge.from, null);
			}
		}

		var matchFrom = this.inProgressMatches.get(user);
		if (matchFrom) {
			this.generator.setUserBusy(matchFrom.to, false);
			this.inProgressMatches.set(user, null);
			matchFrom.room.forfeit(user);
		}

		var matchTo = null;
		this.inProgressMatches.forEach(function (match, userFrom) {
			if (match && match.to === user)
				matchTo = userFrom;
		});
		if (matchTo) {
			this.generator.setUserBusy(matchTo, false);
			this.inProgressMatches.get(matchTo).room.forfeit(user);
			this.inProgressMatches.set(matchTo, null);
		}

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);
	};

	Tournament.prototype.challenge = function (from, to, output) {
		if (!this.availableMatches.get(from).get(to)) {
			output.sendReply('|tournament|' + this.name + '|error|InvalidMatch')
			return;
		}
		if (this.generator.getUserBusy(from) || this.generator.getUserBusy(to)) {
			output.add("Tournament backend breaks specifications. Please report this to an admin.");
			return;
		}

		this.generator.setUserBusy(from, true);
		this.generator.setUserBusy(to, true);
		this.pendingChallenges.set(from, {to: to});
		this.pendingChallenges.set(to, {from: from});

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.cancelChallenge = function (user, output) {
		var challenge = this.pendingChallenges.get(user);
		if (!challenge || challenge.from)
			return;

		this.generator.setUserBusy(user, false);
		this.generator.setUserBusy(challenge.to, false);
		this.pendingChallenges.set(user, null);
		this.pendingChallenges.set(challenge.to, null);

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);
	};
	Tournament.prototype.acceptChallenge = function (user, output) {
		var challenge = this.pendingChallenges.get(user);
		if (!challenge || !challenge.from)
			return;

		this.pendingChallenges.set(challenge.from, null);
		this.pendingChallenges.set(user, null);

		var room = Rooms.global.startBattle(challenge.from, user, this.format, true, challenge.from.team, user.team);
		this.inProgressMatches.set(challenge.from, {to: user, room: room});
		output.send('|tournament|' + this.name + '|battlestart|' + challenge.from.name + '|' + user.name + '|' + room.id);

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);

		var self = this;
		room._win = room.win;
		room.win = function (winner) {
			self.onBattleWin(this, Users.get(winner), output);
			this._win(winner);
		};
	};
	Tournament.prototype.onBattleWin = function (room, winner, output) {
		var from = Users.get(room.p1);
		var to = Users.get(room.p2);

		var result = 'draw';
		if (from === winner)
			result = 'win';
		else if (to === winner)
			result = 'loss';
		var isTournamentEnded = this.generator.setMatchResult([from, to], result, room.battle.score);
		if (typeof isTournamentEnded === 'string') {
			// Should never happen
			output.add("Unexpected " + isTournamentEnded + " from setMatchResult() in onBattleWin(" + room.id + ", " + winner.id + ", ...). Please report this to an admin.");
			return;
		}

		output.send('|tournament|' + this.name + '|battleend|' + from.name + '|' + to.name + '|' + result + '|' + room.battle.score.join(','));

		this.generator.setUserBusy(from, false);
		this.generator.setUserBusy(to, false);
		this.inProgressMatches.set(from, null);

		this.isBracketInvalidated = true;
		this.isAvailableMatchesInvalidated = true;
		this.update(output);

		if (isTournamentEnded)
			this.onTournamentEnd(output);
	};
	Tournament.prototype.onTournamentEnd = function (output) {
		var results = this.generator.getResults();
		output.add('|tournament|' + this.name + '|end|' + usersToNames(results[0]).join(',') + (results[1] ? '|' + usersToNames(results[1]).join(',') : ''));
	};

	return Tournament;
})();

exports.Tournament = Tournament;
exports.TournamentGenerators = TournamentGenerators;

exports.createTournament = createTournament;
exports.deleteTournament = deleteTournament;
exports.getTournament = getTournament;
exports.tournaments = tournaments;
<|endoftext|>