<commit_before>/**
 * Promise wrapper for superagent
 */

function wrap(superagent, Promise) {
  /**
   * Request object similar to superagent.Request, but with end() returning
   * a promise.
   */
  function PromiseRequest() {
    superagent.Request.apply(this, arguments);
  }

  // Inherit form superagent.Request
  PromiseRequest.prototype = Object.create(superagent.Request.prototype);

  /** Send request and get a promise that `end` was emitted */
  PromiseRequest.prototype.end = function(cb) {
    var _end = superagent.Request.prototype.end;
    var self = this;

    return new Promise(function(accept, reject) {
      _end.call(self, function(err, response) {
        if (cb) {
          cb(err, response);
        }

        if (err) {
          reject(err);
        } else {
          accept(response);
        }
      });
    });
  };

  /** Provide a more promise-y interface */
  PromiseRequest.prototype.then = function(resolve, reject) {
    var _end = superagent.Request.prototype.end;
    var self = this;

    return new Promise(function(accept, reject) {
      _end.call(self, function(err, response) {
        if (err) {
          reject(err);
        } else {
          accept(response);
        }
      });
    }).then(resolve, reject);
  };

  /**
   * Request builder with same interface as superagent.
   * It is convenient to import this as `request` in place of superagent.
   */
  var request = function(method, url) {
    return new PromiseRequest(method, url);
  };

  /** Helper for making an options request */
  request.options = function(url) {
    return request('OPTIONS', url);
  }

  /** Helper for making a head request */
  request.head = function(url, data) {
    var req = request('HEAD', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a get request */
  request.get = function(url, data) {
    var req = request('GET', url);
    if (data) {
      req.query(data);
    }
    return req;
  };

  /** Helper for making a post request */
  request.post = function(url, data) {
    var req = request('POST', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a put request */
  request.put = function(url, data) {
    var req = request('PUT', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a patch request */
  request.patch = function(url, data) {
    var req = request('PATCH', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a delete request */
  request.del = function(url) {
    return request('DELETE', url);
  };

  // Export the request builder
  return request;
}

module.exports = wrap;
<commit_msg>add response to err<commit_after>/**
 * Promise wrapper for superagent
 */

function wrap(superagent, Promise) {
  /**
   * Request object similar to superagent.Request, but with end() returning
   * a promise.
   */
  function PromiseRequest() {
    superagent.Request.apply(this, arguments);
  }

  // Inherit form superagent.Request
  PromiseRequest.prototype = Object.create(superagent.Request.prototype);

  /** Send request and get a promise that `end` was emitted */
  PromiseRequest.prototype.end = function(cb) {
    var _end = superagent.Request.prototype.end;
    var self = this;

    return new Promise(function(accept, reject) {
      _end.call(self, function(err, response) {
        if (cb) {
          cb(err, response);
        }

        if (err) {
          err.response = response;
          reject(err);
        } else {
          accept(response);
        }
      });
    });
  };

  /** Provide a more promise-y interface */
  PromiseRequest.prototype.then = function(resolve, reject) {
    var _end = superagent.Request.prototype.end;
    var self = this;

    return new Promise(function(accept, reject) {
      _end.call(self, function(err, response) {
        if (err) {
          err.response = response;
          reject(err);
        } else {
          accept(response);
        }
      });
    }).then(resolve, reject);
  };

  /**
   * Request builder with same interface as superagent.
   * It is convenient to import this as `request` in place of superagent.
   */
  var request = function(method, url) {
    return new PromiseRequest(method, url);
  };

  /** Helper for making an options request */
  request.options = function(url) {
    return request('OPTIONS', url);
  }

  /** Helper for making a head request */
  request.head = function(url, data) {
    var req = request('HEAD', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a get request */
  request.get = function(url, data) {
    var req = request('GET', url);
    if (data) {
      req.query(data);
    }
    return req;
  };

  /** Helper for making a post request */
  request.post = function(url, data) {
    var req = request('POST', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a put request */
  request.put = function(url, data) {
    var req = request('PUT', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a patch request */
  request.patch = function(url, data) {
    var req = request('PATCH', url);
    if (data) {
      req.send(data);
    }
    return req;
  };

  /** Helper for making a delete request */
  request.del = function(url) {
    return request('DELETE', url);
  };

  // Export the request builder
  return request;
}

module.exports = wrap;
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');

var generateBoyResponse = require('./src/generateBoyResponse');

var app = express();

var verify_token = process.env.VERIFY_TOKEN;
var token = process.env.PAGE_ACCESS_TOKEN;
var PORT = process.env.PORT || 1337;

app.use(bodyParser.json());

app.get('/', function (req, res) {

  res.send('Hello World! This is the bot\'s root endpoint!');

});

app.get('/webhook/', function (req, res) {

  if (req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === verify_token) {
    console.log("Validating webhook");
    res.status(200).send(req.query['hub.challenge']);
  } else {
    console.error("Failed validation. Make sure the validation tokens match.");
    res.sendStatus(403);
  }
});

app.post('/webhook/', function (req, res) {
  var data = req.body;

  // Make sure this is a page subscription
  if (data.object == 'page') {
    // Iterate over each entry
    // There may be multiple if batched
    data.entry.forEach(function(pageEntry) {
      pageEntry.messaging.forEach(function(messagingEvent) {
        if (messagingEvent.message) {
          console.log(messagingEvent);
          handleMessageEvent(messagingEvent);
        } else {
          console.log("Received messaging event that isn't handled", messagingEvent);
        }
      });
    });
  }

  res.sendStatus(200);

});

app.listen(PORT, function () {
  console.log('Facebook Messenger echoing bot started on port:' + PORT);
});

// Handles FB messaging events of type 'message'
function handleMessageEvent(event) {
  var senderId = event.sender.id;
  var message = event.message;
  // for now, only handle text messages
  var messageText = message.text;

  var botResponse = generateBoyResponse(messageText);
  var textMessage = formatTextMessage(senderId, botResponse);
  callSendAPI(textMessage);
}

function formatTextMessage(recipientId, messageText) {
  return {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: token },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s",
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(error);
    }
  });
}
<commit_msg>Fix api of generateBoyResponse<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');

var generateBoyResponse = require('./src/generateBoyResponse');

var app = express();

var verify_token = process.env.VERIFY_TOKEN;
var token = process.env.PAGE_ACCESS_TOKEN;
var PORT = process.env.PORT || 1337;

app.use(bodyParser.json());

app.get('/', function (req, res) {

  res.send('Hello World! This is the bot\'s root endpoint!');

});

app.get('/webhook/', function (req, res) {

  if (req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === verify_token) {
    console.log("Validating webhook");
    res.status(200).send(req.query['hub.challenge']);
  } else {
    console.error("Failed validation. Make sure the validation tokens match.");
    res.sendStatus(403);
  }
});

app.post('/webhook/', function (req, res) {
  var data = req.body;

  // Make sure this is a page subscription
  if (data.object == 'page') {
    // Iterate over each entry
    // There may be multiple if batched
    data.entry.forEach(function(pageEntry) {
      pageEntry.messaging.forEach(function(messagingEvent) {
        if (messagingEvent.message) {
          console.log(messagingEvent);
          handleMessageEvent(messagingEvent);
        } else {
          console.log("Received messaging event that isn't handled", messagingEvent);
        }
      });
    });
  }

  res.sendStatus(200);

});

app.listen(PORT, function () {
  console.log('Facebook Messenger echoing bot started on port:' + PORT);
});

// Handles FB messaging events of type 'message'
function handleMessageEvent(event) {
  var senderId = event.sender.id;
  var message = event.message;
  // for now, only handle text messages
  var messageText = message.text;

  var botResponse = generateBoyResponse(senderId, messageText);
  var textMessage = formatTextMessage(senderId, botResponse);
  callSendAPI(textMessage);
}

function formatTextMessage(recipientId, messageText) {
  return {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: token },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s",
        messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(error);
    }
  });
}
<|endoftext|>


<commit_before>// All values and structures referenced from:
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/
//
// DX10 Cubemap support based on
// https://github.com/dariomanesku/cmft/issues/7#issuecomment-69516844
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb943983(v=vs.85).aspx
// https://github.com/playcanvas/engine/blob/master/src/resources/resources_texture.js

var DDS_MAGIC = 0x20534444
var DDSD_MIPMAPCOUNT = 0x20000
var DDPF_FOURCC = 0x4

var FOURCC_DXT1 = fourCCToInt32('DXT1')
var FOURCC_DXT3 = fourCCToInt32('DXT3')
var FOURCC_DXT5 = fourCCToInt32('DXT5')
var FOURCC_DX10 = fourCCToInt32('DX10')
var FOURCC_FP32F = 116 //DXGI_FORMAT_R32G32B32A32_FLOAT

var DDSCAPS2_CUBEMAP = 0x200
var D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3;
var DXGI_FORMAT_R32G32B32A32_FLOAT = 2;

// The header length in 32 bit ints
var headerLengthInt = 31

// Offsets into the header array
var off_magic = 0
var off_size = 1
var off_flags = 2
var off_height = 3
var off_width = 4
var off_mipmapCount = 7
var off_pfFlags = 20
var off_pfFourCC = 21
var off_caps2 = 28

module.exports = parseHeaders

function parseHeaders (arrayBuffer) {
  var header = new Int32Array(arrayBuffer, 0, headerLengthInt)

  if (header[off_magic] !== DDS_MAGIC) {
    throw new Error('Invalid magic number in DDS header')
  }

  if (!header[off_pfFlags] & DDPF_FOURCC) {
    throw new Error('Unsupported format, must contain a FourCC code')
  }

  var blockBytes
  var format
  var fourCC = header[off_pfFourCC]
  switch (fourCC) {
    case FOURCC_DXT1:
      blockBytes = 8
      format = 'dxt1'
      break
    case FOURCC_DXT3:
      blockBytes = 16
      format = 'dxt3'
      break
    case FOURCC_DXT5:
      blockBytes = 16
      format = 'dxt5'
      break
    case FOURCC_FP32F:
      format = 'rgba32f'
      break
    case FOURCC_DX10:
      var dx10Header = new Uint32Array(arrayBuffer.slice(128, 128 + 20));
      var format = dx10Header[0];
      var resourceDimension = dx10Header[1];
      var miscFlag = dx10Header[2];
      var arraySize = dx10Header[3];
      var miscFlags2 = dx10Header[4];

      if (resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D && format == DXGI_FORMAT_R32G32B32A32_FLOAT) {
        format = 'rgba32f'
      }
      else {
        throw new Error('Unsupported DX10 texture format ' + format)
      }
      break
    default:
      throw new Error('Unsupported FourCC code: ' + int32ToFourCC(fourCC))
  }

  var flags = header[off_flags]
  var mipmapCount = 1

  if (flags & DDSD_MIPMAPCOUNT) {
    mipmapCount = Math.max(1, header[off_mipmapCount])
  }

  var cubemap = false
  var caps2 = header[off_caps2]
  if (caps2 & DDSCAPS2_CUBEMAP) {
    cubemap = true
  }

  var width = header[off_width]
  var height = header[off_height]
  var dataOffset = header[off_size] + 4
  var texWidth = width
  var texHeight = height
  var images = []
  var dataLength

  if (fourCC == FOURCC_DX10) {
      dataOffset += 20
  }

  if (cubemap) {
    for(var f = 0; f < 6; f++) {
      if (format != 'rgba32f') {
          throw new Error('Only RGBA32f cubemaps are supported')
      }
      var bpp =  4 * 32 / 8

      width = texWidth
      height = texHeight

      //cubemap should have all mipmap levels defined
      //Math.log2(width) + 1
      requiredMipLevels = Math.log(width) / Math.log(2) + 1

      for (var i = 0; i < requiredMipLevels; i++) {
        dataLength = width * height * bpp
        images.push({
          offset: dataOffset,
          length: dataLength,
          shape: [ width, height ]
        })
        //reuse data from the previous level if we are beyond mipmapCount
        if (i < mipmapCount) {
            dataOffset += dataLength
        }
        width = Math.floor(width / 2)
        height = Math.floor(height / 2)
      }
    }
  }
  else {
    for (var i = 0; i < mipmapCount; i++) {
      dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes

      images.push({
        offset: dataOffset,
        length: dataLength,
        shape: [ width, height ]
      })
      dataOffset += dataLength
      width = Math.floor(width / 2)
      height = Math.floor(height / 2)
    }
  }

  return {
    shape: [ texWidth, texHeight ],
    images: images,
    format: format,
    flags: flags
  }
}

function fourCCToInt32 (value) {
  return value.charCodeAt(0) +
    (value.charCodeAt(1) << 8) +
    (value.charCodeAt(2) << 16) +
    (value.charCodeAt(3) << 24)
}

function int32ToFourCC (value) {
  return String.fromCharCode(
    value & 0xff,
    (value >> 8) & 0xff,
    (value >> 16) & 0xff,
    (value >> 24) & 0xff
  )
}
<commit_msg>Added more info about missing mipmaps fix<commit_after>// All values and structures referenced from:
// http://msdn.microsoft.com/en-us/library/bb943991.aspx/
//
// DX10 Cubemap support based on
// https://github.com/dariomanesku/cmft/issues/7#issuecomment-69516844
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb943983(v=vs.85).aspx
// https://github.com/playcanvas/engine/blob/master/src/resources/resources_texture.js

var DDS_MAGIC = 0x20534444
var DDSD_MIPMAPCOUNT = 0x20000
var DDPF_FOURCC = 0x4

var FOURCC_DXT1 = fourCCToInt32('DXT1')
var FOURCC_DXT3 = fourCCToInt32('DXT3')
var FOURCC_DXT5 = fourCCToInt32('DXT5')
var FOURCC_DX10 = fourCCToInt32('DX10')
var FOURCC_FP32F = 116 //DXGI_FORMAT_R32G32B32A32_FLOAT

var DDSCAPS2_CUBEMAP = 0x200
var D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3;
var DXGI_FORMAT_R32G32B32A32_FLOAT = 2;

// The header length in 32 bit ints
var headerLengthInt = 31

// Offsets into the header array
var off_magic = 0
var off_size = 1
var off_flags = 2
var off_height = 3
var off_width = 4
var off_mipmapCount = 7
var off_pfFlags = 20
var off_pfFourCC = 21
var off_caps2 = 28

module.exports = parseHeaders

function parseHeaders (arrayBuffer) {
  var header = new Int32Array(arrayBuffer, 0, headerLengthInt)

  if (header[off_magic] !== DDS_MAGIC) {
    throw new Error('Invalid magic number in DDS header')
  }

  if (!header[off_pfFlags] & DDPF_FOURCC) {
    throw new Error('Unsupported format, must contain a FourCC code')
  }

  var blockBytes
  var format
  var fourCC = header[off_pfFourCC]
  switch (fourCC) {
    case FOURCC_DXT1:
      blockBytes = 8
      format = 'dxt1'
      break
    case FOURCC_DXT3:
      blockBytes = 16
      format = 'dxt3'
      break
    case FOURCC_DXT5:
      blockBytes = 16
      format = 'dxt5'
      break
    case FOURCC_FP32F:
      format = 'rgba32f'
      break
    case FOURCC_DX10:
      var dx10Header = new Uint32Array(arrayBuffer.slice(128, 128 + 20));
      var format = dx10Header[0];
      var resourceDimension = dx10Header[1];
      var miscFlag = dx10Header[2];
      var arraySize = dx10Header[3];
      var miscFlags2 = dx10Header[4];

      if (resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D && format == DXGI_FORMAT_R32G32B32A32_FLOAT) {
        format = 'rgba32f'
      }
      else {
        throw new Error('Unsupported DX10 texture format ' + format)
      }
      break
    default:
      throw new Error('Unsupported FourCC code: ' + int32ToFourCC(fourCC))
  }

  var flags = header[off_flags]
  var mipmapCount = 1

  if (flags & DDSD_MIPMAPCOUNT) {
    mipmapCount = Math.max(1, header[off_mipmapCount])
  }

  var cubemap = false
  var caps2 = header[off_caps2]
  if (caps2 & DDSCAPS2_CUBEMAP) {
    cubemap = true
  }

  var width = header[off_width]
  var height = header[off_height]
  var dataOffset = header[off_size] + 4
  var texWidth = width
  var texHeight = height
  var images = []
  var dataLength

  if (fourCC == FOURCC_DX10) {
      dataOffset += 20
  }

  if (cubemap) {
    for(var f = 0; f < 6; f++) {
      if (format != 'rgba32f') {
          throw new Error('Only RGBA32f cubemaps are supported')
      }
      var bpp =  4 * 32 / 8

      width = texWidth
      height = texHeight

      //cubemap should have all mipmap levels defined
      //Math.log2(width) + 1
      requiredMipLevels = Math.log(width) / Math.log(2) + 1

      for (var i = 0; i < requiredMipLevels; i++) {
        dataLength = width * height * bpp
        images.push({
          offset: dataOffset,
          length: dataLength,
          shape: [ width, height ]
        })
        //Reuse data from the previous level if we are beyond mipmapCount
        //This is hack for CMFT not publishing full mipmap chain https://github.com/dariomanesku/cmft/issues/10
        if (i < mipmapCount) {
            dataOffset += dataLength
        }
        width = Math.floor(width / 2)
        height = Math.floor(height / 2)
      }
    }
  }
  else {
    for (var i = 0; i < mipmapCount; i++) {
      dataLength = Math.max(4, width) / 4 * Math.max(4, height) / 4 * blockBytes

      images.push({
        offset: dataOffset,
        length: dataLength,
        shape: [ width, height ]
      })
      dataOffset += dataLength
      width = Math.floor(width / 2)
      height = Math.floor(height / 2)
    }
  }

  return {
    shape: [ texWidth, texHeight ],
    images: images,
    format: format,
    flags: flags
  }
}

function fourCCToInt32 (value) {
  return value.charCodeAt(0) +
    (value.charCodeAt(1) << 8) +
    (value.charCodeAt(2) << 16) +
    (value.charCodeAt(3) << 24)
}

function int32ToFourCC (value) {
  return String.fromCharCode(
    value & 0xff,
    (value >> 8) & 0xff,
    (value >> 16) & 0xff,
    (value >> 24) & 0xff
  )
}
<|endoftext|>


<commit_before>'use strict'

const transformFileSync = require('babel-core').transformFileSync
const transform = require('buble').transform
const babelPlugin = require('babel-plugin-transform-es2015-modules-commonjs')

const babelOpts = {
  plugins: [ babelPlugin ]
}

const bubleOpts = {
  transforms: {
    dangerousForOf: true,
    generator: false
  }
}

const transformFile = function (filename, options) {
  options = options || {}
  const babelOptions = Object.assign({}, babelOpts, options.babel)
  const bubleOptions = Object.assign({}, bubleOpts, options.buble)

  try {
    const output = transform(transformFileSync(filename, babelOptions).code, bubleOptions)
    return output
  } catch (e) {
    console.error('Failed to transform file :', filename, e)
  }
}

module.exports = {
transformFile}
<commit_msg>fix spacing again<commit_after>'use strict'

const transformFileSync = require('babel-core').transformFileSync
const transform = require('buble').transform
const babelPlugin = require('babel-plugin-transform-es2015-modules-commonjs')

const babelOpts = {
  plugins: [ babelPlugin ]
}

const bubleOpts = {
  transforms: {
    dangerousForOf: true,
    generator: false
  }
}

const transformFile = function (filename, options) {
  options = options || {}
  const babelOptions = Object.assign({}, babelOpts, options.babel)
  const bubleOptions = Object.assign({}, bubleOpts, options.buble)

  try {
    const output = transform(transformFileSync(filename, babelOptions).code, bubleOptions)
    return output
  } catch (e) {
    console.error('Failed to transform file :', filename, e)
  }
}

module.exports = {
  transformFile
}
<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();

let Wit = null;
let log = null;
try {
  // if running from repo
  Wit = require('../').Wit;
  log = require('../').log;
} catch (e) {
  Wit = require('node-wit').Wit;
  log = require('node-wit').log;
}

// Variables are defined in Heroku
const WIT_TOKEN = process.env.WIT_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
const PORT = process.env.PORT;
//Needs feature Dyno Metadata (https://stackoverflow.com/questions/7917523/how-do-i-access-the-current-heroku-release-version-programmatically)
const VERSION = process.env.HEROKU_RELEASE_VERSION;

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen(PORT);
console.log('Listening on :' + PORT + '...');

// Server frontpage
app.get('/', function (req, res) {
    res.send('This is TestBot Server');
});

// Facebook Webhook
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'luzbot_hans') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// handler receiving messages
app.post('/webhook', function (req, res) {
    var events = req.body.entry[0].messaging;
    for (var i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {

			// Yay! We got a new message!
			// We retrieve the Facebook user ID of the sender
			const sender = event.sender.id;

			// We retrieve the user's current session, or create one if it doesn't exist
			// This is needed for our bot to figure out the conversation history
			const sessionId = findOrCreateSession(sender);

			var question = event.message.text;

			if(question.toUpperCase() == "HI") {
				answer = "Hi. How are you?";
				sendMessage(event.sender.id, answer);
			}
			else if(question.toUpperCase() == "VERSION") {
				answer = "Aktuelle Version ist " + VERSION;
				sendMessage(event.sender.id, answer);
			}
			else {
				//forward question to wit framework
				console.log('New message detected, text: ' + msg);
				console.log('New message detected, sender: ' + sender);
				console.log('New message detected, sessionId: ' + sessionId);

				wit.message(usersMessage, {})
					.then((data) =>
					{
						var body = JSON.stringify(data);
						console.log('Yay, got Wit.ai response: ' + body);
						var answer = getAnswer(body);
						sendMessage(event.sender.id, answer);
					})
				.catch(console.error);

			}

			// Let's forward the message to the Wit.ai Bot Engine
            // This will run all actions until our bot has nothing left to do
            /*wit.runActions(
              sessionId, // the user's current session
              text, // the user's message
              sessions[sessionId].context // the user's current session state
            ).then((context) => {
              // Our bot did everything it has to do.
              // Now it's waiting for further messages to proceed.
              console.log('Waiting for next user messages');

              // Based on the session state, you might want to reset the session.
              // This depends heavily on the business logic of your bot.
              // Example:
              // if (context['done']) {
              //   delete sessions[sessionId];
              // }

              // Updating the user's current session state
              sessions[sessionId].context = context;
            })
            .catch((err) => {
              console.error('Oops! Got an error from Wit: ', err.stack || err);
            })
			*/

        }
    }
    res.sendStatus(200);
});

//witJSON answer of WIT Engine, i.e.
/*
{
	"_text":"Zeige mir Restaurants"
	,"entities":{"intent":[{"confidence":0.78031343410165,"value":"restaurant"}]}
	,"msg_id":"0xaoNXhmAyWix0sms"
}
*/
function getAnswer(witJSON) {
	var answer = witJSON;
	//Process JSON for correct answer

    return answer;
}

// generic function sending messages
function sendMessage(recipientId, msg) {
	var message = {text: msg};
    request({
        url: 'https://graph.facebook.com/v2.10/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};

// ----------------------------------------------------------------------------
// Messenger API specific code

// See the Send API reference
// https://developers.facebook.com/docs/messenger-platform/send-api-reference

const fbMessage = (id, text) => {
  const body = JSON.stringify({
    recipient: { id },
    message: { text },
  });
  const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
  return fetch('https://graph.facebook.com/me/messages?' + qs, {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body,
  })
  .then(rsp => rsp.json())
  .then(json => {
    if (json.error && json.error.message) {
      throw new Error(json.error.message);
    }
    return json;
  });
};

// ----------------------------------------------------------------------------
// Wit.ai bot specific code

// This will contain all user sessions.
// Each session has an entry:
// sessionId -> {fbid: facebookUserId, context: sessionState}
const sessions = {};

const findOrCreateSession = (fbid) => {
  let sessionId;
  // Let's see if we already have a session for the user fbid
  Object.keys(sessions).forEach(k => {
    if (sessions[k].fbid === fbid) {
      // Yep, got it!
      sessionId = k;
    }
  });
  if (!sessionId) {
    // No session found for user fbid, let's create a new one
    sessionId = new Date().toISOString();
    sessions[sessionId] = {fbid: fbid, context: {}};
  }
  return sessionId;
};

// Our bot actions
const actions = {
  send({sessionId}, {text}) {
	console.log('Our bot has something to say!');
    // Our bot has something to say!
    // Let's retrieve the Facebook user whose session belongs to
    const recipientId = sessions[sessionId].fbid;
	console.log('Our bot has something to say!' + recipientId);
    if (recipientId) {
		console.log('// Yay, we found our recipient!');
      // Yay, we found our recipient!
      // Let's forward our bot response to her.
      // We return a promise to let our bot know when we're done sending
      return fbMessage(recipientId, text)
      .then(() => null)
      .catch((err) => {
        console.error(
          'Oops! An error occurred while forwarding the response to',
          recipientId,
          ':',
          err.stack || err
        );
      });
    } else {
      console.error('Oops! Couldn\'t find user for session:', sessionId);
      // Giving the wheel back to our bot
      return Promise.resolve()
    }
  },
  // You should implement your custom actions here
  // See https://wit.ai/docs/quickstart
};

// Setting up our bot
const wit = new Wit({
  accessToken: WIT_TOKEN,
  actions,
  logger: new log.Logger(log.INFO)
});
<commit_msg>answer not defined<commit_after>'use strict';

var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();

let Wit = null;
let log = null;
try {
  // if running from repo
  Wit = require('../').Wit;
  log = require('../').log;
} catch (e) {
  Wit = require('node-wit').Wit;
  log = require('node-wit').log;
}

// Variables are defined in Heroku
const WIT_TOKEN = process.env.WIT_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.PAGE_ACCESS_TOKEN;
const PORT = process.env.PORT;
//Needs feature Dyno Metadata (https://stackoverflow.com/questions/7917523/how-do-i-access-the-current-heroku-release-version-programmatically)
const VERSION = process.env.HEROKU_RELEASE_VERSION;

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.listen(PORT);
console.log('Listening on :' + PORT + '...');

// Server frontpage
app.get('/', function (req, res) {
    res.send('This is TestBot Server');
});

// Facebook Webhook
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'luzbot_hans') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// handler receiving messages
app.post('/webhook', function (req, res) {
    var events = req.body.entry[0].messaging;
    for (var i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {

			// Yay! We got a new message!
			// We retrieve the Facebook user ID of the sender
			const sender = event.sender.id;

			// We retrieve the user's current session, or create one if it doesn't exist
			// This is needed for our bot to figure out the conversation history
			const sessionId = findOrCreateSession(sender);

			var question = event.message.text;

			if(question.toUpperCase() == "HI") {
				var answer = "Hi. How are you?";
				sendMessage(event.sender.id, answer);
			}
			else if(question.toUpperCase() == "VERSION") {
				var answer = "Aktuelle Version ist " + VERSION;
				sendMessage(event.sender.id, answer);
			}
			else {
				//forward question to wit framework
				console.log('New message detected, text: ' + msg);
				console.log('New message detected, sender: ' + sender);
				console.log('New message detected, sessionId: ' + sessionId);

				wit.message(usersMessage, {})
					.then((data) =>
					{
						var body = JSON.stringify(data);
						console.log('Yay, got Wit.ai response: ' + body);
						var answer = getAnswer(body);
						sendMessage(event.sender.id, answer);
					})
				.catch(console.error);

			}

			// Let's forward the message to the Wit.ai Bot Engine
            // This will run all actions until our bot has nothing left to do
            /*wit.runActions(
              sessionId, // the user's current session
              text, // the user's message
              sessions[sessionId].context // the user's current session state
            ).then((context) => {
              // Our bot did everything it has to do.
              // Now it's waiting for further messages to proceed.
              console.log('Waiting for next user messages');

              // Based on the session state, you might want to reset the session.
              // This depends heavily on the business logic of your bot.
              // Example:
              // if (context['done']) {
              //   delete sessions[sessionId];
              // }

              // Updating the user's current session state
              sessions[sessionId].context = context;
            })
            .catch((err) => {
              console.error('Oops! Got an error from Wit: ', err.stack || err);
            })
			*/

        }
    }
    res.sendStatus(200);
});

//witJSON answer of WIT Engine, i.e.
/*
{
	"_text":"Zeige mir Restaurants"
	,"entities":{"intent":[{"confidence":0.78031343410165,"value":"restaurant"}]}
	,"msg_id":"0xaoNXhmAyWix0sms"
}
*/
function getAnswer(witJSON) {
	var answer = witJSON;
	//Process JSON for correct answer

    return answer;
}

// generic function sending messages
function sendMessage(recipientId, msg) {
	var message = {text: msg};
    request({
        url: 'https://graph.facebook.com/v2.10/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};

// ----------------------------------------------------------------------------
// Messenger API specific code

// See the Send API reference
// https://developers.facebook.com/docs/messenger-platform/send-api-reference

const fbMessage = (id, text) => {
  const body = JSON.stringify({
    recipient: { id },
    message: { text },
  });
  const qs = 'access_token=' + encodeURIComponent(FB_PAGE_ACCESS_TOKEN);
  return fetch('https://graph.facebook.com/me/messages?' + qs, {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body,
  })
  .then(rsp => rsp.json())
  .then(json => {
    if (json.error && json.error.message) {
      throw new Error(json.error.message);
    }
    return json;
  });
};

// ----------------------------------------------------------------------------
// Wit.ai bot specific code

// This will contain all user sessions.
// Each session has an entry:
// sessionId -> {fbid: facebookUserId, context: sessionState}
const sessions = {};

const findOrCreateSession = (fbid) => {
  let sessionId;
  // Let's see if we already have a session for the user fbid
  Object.keys(sessions).forEach(k => {
    if (sessions[k].fbid === fbid) {
      // Yep, got it!
      sessionId = k;
    }
  });
  if (!sessionId) {
    // No session found for user fbid, let's create a new one
    sessionId = new Date().toISOString();
    sessions[sessionId] = {fbid: fbid, context: {}};
  }
  return sessionId;
};

// Our bot actions
const actions = {
  send({sessionId}, {text}) {
	console.log('Our bot has something to say!');
    // Our bot has something to say!
    // Let's retrieve the Facebook user whose session belongs to
    const recipientId = sessions[sessionId].fbid;
	console.log('Our bot has something to say!' + recipientId);
    if (recipientId) {
		console.log('// Yay, we found our recipient!');
      // Yay, we found our recipient!
      // Let's forward our bot response to her.
      // We return a promise to let our bot know when we're done sending
      return fbMessage(recipientId, text)
      .then(() => null)
      .catch((err) => {
        console.error(
          'Oops! An error occurred while forwarding the response to',
          recipientId,
          ':',
          err.stack || err
        );
      });
    } else {
      console.error('Oops! Couldn\'t find user for session:', sessionId);
      // Giving the wheel back to our bot
      return Promise.resolve()
    }
  },
  // You should implement your custom actions here
  // See https://wit.ai/docs/quickstart
};

// Setting up our bot
const wit = new Wit({
  accessToken: WIT_TOKEN,
  actions,
  logger: new log.Logger(log.INFO)
});
<|endoftext|>


<commit_before>var __slice = [].slice;
/*
function die () {
  console.log.apply(console, __slice.call(arguments, 0));
  process.exit(1);
}

function say () { console.log.apply(console, __slice.call(arguments, 0)) }
*/
function cadence () {
  var steps = __slice.call(arguments, 0);

  function begin (steps, vargs, callback) {
    var invocation = {
      callbacks: [{ results: [[invoke].concat(vargs)] }]
    };
    invoke.call(this, steps, 0, invocation, callback);
  }

  // Execute is the function returned to the user. It represents the constructed
  // cadence. When the user invokes it with no arguments, a default error
  // throwing callback is used for the cadence callback. If the user provides
  // any arguments, the user must also provide a callback.
  function execute () {
    var vargs = __slice.call(arguments, 0),
        callback = function (error) { if (error) throw error };
    if (vargs.length) callback = vargs.pop();
    begin.call(this, steps, [async].concat(vargs), callback);
  }

  // To use the same `step` function throughout while supporting reentrancy,
  // we keep a stack of invocation objects. The stack is reversed; top is 0.
  // The `step` function is synchronous and will return immediately.
  //
  // It is possible for the user to invoke `step` outside of a step in a
  // cadence, we can't prevent it, nor really even detect it. Imagine the user
  // invoking `setTimeout` with a callback that calls `step` five minutes
  // later, long after the cadence has ended. Mayhem, but what can you do?
  var invocations = [];

  // We give this function to the caller to build control flow. In the
  // debugger, I often want to step into a function that takes a step
  // callback, so I'm often stepping into this function, only to step right
  // back out again. Step out is a two finger chord in the Chrome debugger,
  // but step over is a single function key, so I want to have the option to
  // step over the body of this function, instead of having to find the
  // control key when I'm in it. That is the only reason for the separate
  // async function.

  //
  function async () { return _async.apply(null, arguments) }

  function _async() {
    var vargs = __slice.call(arguments, 0), i = -1;

    // The caller as invoked the async function directly as an explicit early
    // return to exit the entire cadence.
    if (vargs[0] === null || vargs[0] instanceof Error) {
      invocations[0].count = Number.MAX_VALUE;
      invocations[0].callback.apply(null, vargs);
      return;
    }

    // If our first argument is a function, we check to see if it is a jump
    // instruction. If the function is a member of the current cadence, we
    // will inovke that function with the results of this step.

    // Search for the function in the current cadence.
    if (vargs.length == 1 && typeof vargs[0] == "function") {
      for (i = invocations[0].args[0].length - 1;
           i > -1 && invocations[0].args[0][i] !== vargs[0]; i--) {}
    }

    // If we find the function in the current cadence, we set the index of
    // next step function to execute; then remove the function argument and
    // procede.
    if (~i) {
      invocations[0].args[1] = i;
      vargs.shift();
    }

    var callback = { errors: [], results: [] };
    invocations[0].callbacks.push(callback);

    var fixup;
    if (fixup = (vargs[0] === async)) {
      vargs.shift();
    }
    if (!isNaN(parseInt(vargs[0], 10))) {
      callback.arity = +(vargs.shift());
    }
    if (Array.isArray(vargs[0]) && vargs[0].length == 0) {
      callback.arrayed = !! vargs.shift();
    }
    if (Error === vargs[0]) {
      invocations[0].catchable = callback.catchable = !! vargs.shift();
    }
    if (Array.prototype.shift === vargs[0]) {
      callback.shifted = !! vargs.shift();
    }
    callback.cadence = vargs;
    if (vargs.length) {
      if (!vargs.every(function (arg) { return typeof arg == "function" })) {
        throw new Error("invalid arguments");
      }
      if (!fixup) return createCadence(invocations[0], callback);
    }
    if (callback.arrayed) return createArray(invocations[0], callback);
    return createCallback(invocations[0], callback, 0);
  }

  function createCadence (invocation, callback) {
    var index = 0;
    callback.run = ! callback.arrayed;
    return function () {
      var vargs = __slice.call(arguments);
      runSubCadence(invocation, callback, index++, vargs);
    }
  }

  function createArray (invocation, callback) {
    var index = 0;
    return function () {
      var vargs = __slice.call(arguments);
      if (index < 0) throw new Error("zero-to-many already determined");
      if (Array.isArray(vargs[0])) {
        index = -2;
      }
      return createCallback(invocation, callback, index++);
    }
  }

  function createCallback (invocation, callback, index) {
    if (-1 < index) invocation.count++;
    return function () {
      var vargs = __slice.call(arguments, 0), error;
      if (!callback.shifted) error = vargs.shift();
      if (error) {
        thrown(invocation, error, callback);
      } else {
        if (index < 0) callback.results.push(vargs);
        else callback.results[index] = vargs;
        if (callback.cadence.length) {
          invocation.count++;
          begin.call(invocation.self, callback.cadence, callback.results[index], function (error, result) {
            if (error) {
              thrown(invocation, error, callback);
            } else {
              callback.results[index] = __slice.call(arguments, 1);
            }
            if (-1 < index && ++invocation.called == invocation.count) {
              invoke.apply(invocation.self, invocation.args);
            }
          });
        }
        // Indicates that the function has completed, so we need create
        // the callbacks for parallel cadences now, the next increment of
        // the called counter, which may be the last.
        if (vargs[0] == invoke) {
          invocation.callbacks.filter(function (callback) { return callback.run }).forEach(function (callback) {
            runSubCadence(invocation, callback, 0, []);
          });
        }
      }
      if (index > -1 && ++invocation.called == invocation.count) {
        invoke.apply(invocation.self, invocation.args);
      }
    }
  }

  function runSubCadence (invocation, callback, index, vargs) {
    delete callback.run;
    var steps = callback.cadence;
    invocation.count++;
    begin.call(invocation.self, steps, vargs, function (error) {
      var vargs = __slice.call(arguments, 1);
      if (error) {
        thrown(invocation, error, callback);
      } else {
        callback.results[index] = vargs;
      }
      if (++invocation.called == invocation.count) {
        invoke.apply(invocation.self, invocation.args);
      }
    });
  }

  function thrown (invocation, error, callback) {
    var steps = invocation.args[0], next = steps[invocation.index + 1];
    if (next && callback.catchable) {
      callback.errors = [ error ];
    } else {
      invocation.abended = true;
      invocation.callback(error);
    }
  }

  // Parallel arrays make the most sense, really. If the paralleled function
  // is better off returning a map, it can be shimmed.
  function contextualize (step, callbacks) {
    var index, vargs = [], arg, callback, arity;

    arg = 0;
    while (callbacks.length) {
      callback = callbacks.shift();
      if (callback.arrayed) {
        callback.results = callback.results.filter(function (vargs) { return vargs.length });
      }
      if ('arity' in callback) {
        arity = callback.arity;
      } else {
        arity = callback.arrayed ? 1 : 0;
        callback.results.forEach(function (result) {
          arity = Math.max(arity, result.length);
        });
      }
      for (index = 0; index < arity; index++) {
        vargs.push({ values: [],
                     arrayed: ('arrayed' in callback) ? callback.arrayed : callback.results.length > 1 });
      }
      callback.results.forEach(function (result) {
        for (var i = 0; i < arity; i++) {
          vargs[arg + i].values.push(result[i]);
        }
      });
      arg += arity;
    }

    return vargs.map(function (vargs) { return vargs.arrayed ? vargs.values : vargs.values.shift() });
  }

  function invoke (steps, index, previous, callback) {
    var callbacks = previous.callbacks, args = [], arg, step, result, hold;

    if (previous.thrown) {
      callback(previous.thrown);
      return;
    }
    if (previous.abended) return;

    var caught = [];
    if (previous.catchable) {
      var caught = callbacks.filter(function (callback) { return callback.errors.length });
    }

    if (steps[index] && previous.catchable && !caught.length) {
      previous.catchable = false;
      invoke.call(this, steps, index + 1, previous, callback);
    } else {
      // No callbacks means that we use the function return value, if any.
      if (callbacks.length == 1) {
        callbacks[0].results[0].shift()
        if (!callbacks[0].results[0].length) {
          callbacks.shift();
        }
      } else {
        callbacks.shift();
      }

      // Filter out the return value, if there are callbacks left, then
      // `contextualize` will process them.
      if (caught.length) {
        args = callbacks.filter(function (callback) {
          return callback.catchable;
        }).map(function (callback) {
          return callback.errors.shift();
        });
      } else {
        if (callbacks.length) {
          args = contextualize(step, callbacks);
        } else {
          args = [];
        }
      }

      if (steps.length == index) {
        callback.apply(null, [ null ].concat(args));
        return;
      }

      // Get the next step.
      step = steps[index];

      invocations.unshift({ callbacks: [], count: 0 , called: 0, index: index,
                            callback: callback, self: this });
      invocations[0].args = [ steps, index + 1, invocations[0], callback ]

      hold = async();
      try {
        result = step.apply(this, args);
      } catch (error) {
        // We're not a replacement for try/catch, so set up the next step for
        // failure, ensure that our hold function invokes the next step.
        invocations[0].thrown = error;
        invocations[0].called = invocations[0].count - 1;
      }
      invocations.shift();
      hold.apply(this, [ null, invoke ].concat(result === void(0) ? [] : [ result ]));
    }
  }

  return execute;
}

module.exports = cadence;
<commit_msg>Add a few comments to constructor functions.<commit_after>var __slice = [].slice;
/*
function die () {
  console.log.apply(console, __slice.call(arguments, 0));
  process.exit(1);
}

function say () { console.log.apply(console, __slice.call(arguments, 0)) }
*/
function cadence () {
  var steps = __slice.call(arguments, 0);

  function begin (steps, vargs, callback) {
    var invocation = {
      callbacks: [{ results: [[invoke].concat(vargs)] }]
    };
    invoke.call(this, steps, 0, invocation, callback);
  }

  // Execute is the function returned to the user. It represents the constructed
  // cadence. When the user invokes it with no arguments, a default error
  // throwing callback is used for the cadence callback. If the user provides
  // any arguments, the user must also provide a callback.
  function execute () {
    var vargs = __slice.call(arguments, 0),
        callback = function (error) { if (error) throw error };
    if (vargs.length) callback = vargs.pop();
    begin.call(this, steps, [async].concat(vargs), callback);
  }

  // To use the same `step` function throughout while supporting reentrancy,
  // we keep a stack of invocation objects. The stack is reversed; top is 0.
  // The `step` function is synchronous and will return immediately.
  //
  // It is possible for the user to invoke `step` outside of a step in a
  // cadence, we can't prevent it, nor really even detect it. Imagine the user
  // invoking `setTimeout` with a callback that calls `step` five minutes
  // later, long after the cadence has ended. Mayhem, but what can you do?
  var invocations = [];

  // We give this function to the caller to build control flow. In the
  // debugger, I often want to step into a function that takes a step
  // callback, so I'm often stepping into this function, only to step right
  // back out again. Step out is a two finger chord in the Chrome debugger,
  // but step over is a single function key, so I want to have the option to
  // step over the body of this function, instead of having to find the
  // control key when I'm in it. That is the only reason for the separate
  // async function.

  //
  function async () { return _async.apply(null, arguments) }

  function _async() {
    var vargs = __slice.call(arguments, 0), i = -1;

    // The caller as invoked the async function directly as an explicit early
    // return to exit the entire cadence.
    if (vargs[0] === null || vargs[0] instanceof Error) {
      invocations[0].count = Number.MAX_VALUE;
      invocations[0].callback.apply(null, vargs);
      return;
    }

    // If our first argument is a function, we check to see if it is a jump
    // instruction. If the function is a member of the current cadence, we
    // will inovke that function with the results of this step.

    // Search for the function in the current cadence.
    if (vargs.length == 1 && typeof vargs[0] == "function") {
      for (i = invocations[0].args[0].length - 1;
           i > -1 && invocations[0].args[0][i] !== vargs[0]; i--) {}
    }

    // If we find the function in the current cadence, we set the index of
    // next step function to execute; then remove the function argument and
    // procede.
    if (~i) {
      invocations[0].args[1] = i;
      vargs.shift();
    }

    var callback = { errors: [], results: [] };
    invocations[0].callbacks.push(callback);

    var fixup;
    if (fixup = (vargs[0] === async)) {
      vargs.shift();
    }
    if (!isNaN(parseInt(vargs[0], 10))) {
      callback.arity = +(vargs.shift());
    }
    if (Array.isArray(vargs[0]) && vargs[0].length == 0) {
      callback.arrayed = !! vargs.shift();
    }
    if (Error === vargs[0]) {
      invocations[0].catchable = callback.catchable = !! vargs.shift();
    }
    if (Array.prototype.shift === vargs[0]) {
      callback.shifted = !! vargs.shift();
    }
    callback.cadence = vargs;
    if (vargs.length) {
      if (!vargs.every(function (arg) { return typeof arg == "function" })) {
        throw new Error("invalid arguments");
      }
      if (!fixup) return createCadence(invocations[0], callback);
    }
    if (callback.arrayed) return createArray(invocations[0], callback);
    return createCallback(invocations[0], callback, 0);
  }

  // Create a sub-cadence.
  function createCadence (invocation, callback) {
    var index = 0;
    callback.run = ! callback.arrayed;
    return function () {
      var vargs = __slice.call(arguments);
      runSubCadence(invocation, callback, index++, vargs);
    }
  }

  // Create an an arryed callback.
  function createArray (invocation, callback) {
    var index = 0;
    return function () {
      var vargs = __slice.call(arguments);
      if (index < 0) throw new Error("zero-to-many already determined");
      if (Array.isArray(vargs[0])) {
        index = -2;
      }
      return createCallback(invocation, callback, index++);
    }
  }

  // Create a scalar callback.
  function createCallback (invocation, callback, index) {
    if (-1 < index) invocation.count++;
    return function () {
      var vargs = __slice.call(arguments, 0), error;
      if (!callback.shifted) error = vargs.shift();
      if (error) {
        thrown(invocation, error, callback);
      } else {
        if (index < 0) callback.results.push(vargs);
        else callback.results[index] = vargs;
        if (callback.cadence.length) {
          invocation.count++;
          begin.call(invocation.self, callback.cadence, callback.results[index], function (error, result) {
            if (error) {
              thrown(invocation, error, callback);
            } else {
              callback.results[index] = __slice.call(arguments, 1);
            }
            if (-1 < index && ++invocation.called == invocation.count) {
              invoke.apply(invocation.self, invocation.args);
            }
          });
        }
        // Indicates that the function has completed, so we need create
        // the callbacks for parallel cadences now, the next increment of
        // the called counter, which may be the last.
        if (vargs[0] == invoke) {
          invocation.callbacks.filter(function (callback) { return callback.run }).forEach(function (callback) {
            runSubCadence(invocation, callback, 0, []);
          });
        }
      }
      if (index > -1 && ++invocation.called == invocation.count) {
        invoke.apply(invocation.self, invocation.args);
      }
    }
  }

  // Run a sub-cadence.
  function runSubCadence (invocation, callback, index, vargs) {
    delete callback.run;
    var steps = callback.cadence;
    invocation.count++;
    begin.call(invocation.self, steps, vargs, function (error) {
      var vargs = __slice.call(arguments, 1);
      if (error) {
        thrown(invocation, error, callback);
      } else {
        callback.results[index] = vargs;
      }
      if (++invocation.called == invocation.count) {
        invoke.apply(invocation.self, invocation.args);
      }
    });
  }

  function thrown (invocation, error, callback) {
    var steps = invocation.args[0], next = steps[invocation.index + 1];
    if (next && callback.catchable) {
      callback.errors = [ error ];
    } else {
      invocation.abended = true;
      invocation.callback(error);
    }
  }

  // Parallel arrays make the most sense, really. If the paralleled function
  // is better off returning a map, it can be shimmed.
  function contextualize (step, callbacks) {
    var index, vargs = [], arg, callback, arity;

    arg = 0;
    while (callbacks.length) {
      callback = callbacks.shift();
      if (callback.arrayed) {
        callback.results = callback.results.filter(function (vargs) { return vargs.length });
      }
      if ('arity' in callback) {
        arity = callback.arity;
      } else {
        arity = callback.arrayed ? 1 : 0;
        callback.results.forEach(function (result) {
          arity = Math.max(arity, result.length);
        });
      }
      for (index = 0; index < arity; index++) {
        vargs.push({ values: [],
                     arrayed: ('arrayed' in callback) ? callback.arrayed : callback.results.length > 1 });
      }
      callback.results.forEach(function (result) {
        for (var i = 0; i < arity; i++) {
          vargs[arg + i].values.push(result[i]);
        }
      });
      arg += arity;
    }

    return vargs.map(function (vargs) { return vargs.arrayed ? vargs.values : vargs.values.shift() });
  }

  function invoke (steps, index, previous, callback) {
    var callbacks = previous.callbacks, args = [], arg, step, result, hold;

    if (previous.thrown) {
      callback(previous.thrown);
      return;
    }
    if (previous.abended) return;

    var caught = [];
    if (previous.catchable) {
      var caught = callbacks.filter(function (callback) { return callback.errors.length });
    }

    if (steps[index] && previous.catchable && !caught.length) {
      previous.catchable = false;
      invoke.call(this, steps, index + 1, previous, callback);
    } else {
      // No callbacks means that we use the function return value, if any.
      if (callbacks.length == 1) {
        callbacks[0].results[0].shift()
        if (!callbacks[0].results[0].length) {
          callbacks.shift();
        }
      } else {
        callbacks.shift();
      }

      // Filter out the return value, if there are callbacks left, then
      // `contextualize` will process them.
      if (caught.length) {
        args = callbacks.filter(function (callback) {
          return callback.catchable;
        }).map(function (callback) {
          return callback.errors.shift();
        });
      } else {
        if (callbacks.length) {
          args = contextualize(step, callbacks);
        } else {
          args = [];
        }
      }

      if (steps.length == index) {
        callback.apply(null, [ null ].concat(args));
        return;
      }

      // Get the next step.
      step = steps[index];

      invocations.unshift({ callbacks: [], count: 0 , called: 0, index: index,
                            callback: callback, self: this });
      invocations[0].args = [ steps, index + 1, invocations[0], callback ]

      hold = async();
      try {
        result = step.apply(this, args);
      } catch (error) {
        // We're not a replacement for try/catch, so set up the next step for
        // failure, ensure that our hold function invokes the next step.
        invocations[0].thrown = error;
        invocations[0].called = invocations[0].count - 1;
      }
      invocations.shift();
      hold.apply(this, [ null, invoke ].concat(result === void(0) ? [] : [ result ]));
    }
  }

  return execute;
}

module.exports = cadence;
<|endoftext|>


<commit_before>(function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?void(this._wrapped=n):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.6.0";var A=j.each=j.forEach=function(n,t,e){if(null==n)return n;if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return;return n};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var O="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},j.find=j.detect=function(n,t,r){var e;return k(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var k=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:k(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,j.property(t))},j.where=function(n,t){return j.filter(n,j.matches(t))},j.findWhere=function(n,t){return j.find(n,j.matches(t))},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-1/0,u=-1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;o>u&&(e=n,u=o)}),e},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return A(n,function(n,i,a){var o=t?t.call(r,n,i,a):n;u>o&&(e=n,u=o)}),e},j.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=j.random(r++),e[r-1]=e[t],e[t]=n}),e},j.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=j.values(n)),n[j.random(n.length-1)]):j.shuffle(n).slice(0,Math.max(0,t))};var E=function(n){return null==n?j.identity:j.isFunction(n)?n:j.property(n)};j.sortBy=function(n,t,r){return t=E(t),j.pluck(j.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={};return r=E(r),A(t,function(i,a){var o=r.call(e,i,a,t);n(u,o,i)}),u}};j.groupBy=F(function(n,t,r){j.has(n,t)?n[t].push(r):n[t]=[r]}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=E(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])<u?i=o+1:a=o}return i},j.toArray=function(n){return n?j.isArray(n)?o.call(n):n.length===+n.length?j.map(n,j.identity):j.values(n):[]},j.size=function(n){return null==n?0:n.length===+n.length?n.length:j.keys(n).length},j.first=j.head=j.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:0>t?[]:o.call(n,0,t)},j.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},j.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},j.rest=j.tail=j.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},j.compact=function(n){return j.filter(n,j.identity)};var M=function(n,t,r){return t&&j.every(n,j.isArray)?c.apply(r,n):(A(n,function(n){j.isArray(n)||j.isArguments(n)?t?a.apply(r,n):M(n,t,r):r.push(n)}),r)};j.flatten=function(n,t){return M(n,t,[])},j.without=function(n){return j.difference(n,o.call(arguments,1))},j.partition=function(n,t){var r=[],e=[];return A(n,function(n){(t(n)?r:e).push(n)}),[r,e]},j.uniq=j.unique=function(n,t,r,e){j.isFunction(t)&&(e=r,r=t,t=!1);var u=r?j.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:j.contains(a,r))||(a.push(r),i.push(n[e]))}),i},j.union=function(){return j.uniq(j.flatten(arguments,!0))},j.intersection=function(n){var t=o.call(arguments,1);return j.filter(j.uniq(n),function(n){return j.every(t,function(t){return j.contains(t,n)})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===j&&(e[u]=arguments[r++]);for(;r<arguments.length;)e.push(arguments[r++]);return n.apply(this,e)}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:j.now(),a=null,i=n.apply(e,u),e=u=null};return function(){var l=j.now();o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u),e=u=null):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o,c=function(){var l=j.now()-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u),i=u=null))};return function(){i=this,u=arguments,a=j.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u),i=u=null),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return j.partial(t,n)},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=function(n){if(!j.isObject(n))return[];if(w)return w(n);var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o)&&"constructor"in n&&"constructor"in t)return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.constant=function(n){return function(){return n}},j.property=function(n){return function(t){return t[n]}},j.matches=function(n){return function(t){if(t===n)return!0;for(var r in n)if(n[r]!==t[r])return!1;return!0}},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},j.now=Date.now||function(){return(new Date).getTime()};var T={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};T.unescape=j.invert(T.escape);var I={escape:new RegExp("["+j.keys(T.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(T.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(I[n],function(t){return T[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n","	":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return j})}).call(this);
//simply.scrollable(true);
simply.style('small');

var text = '';

var cats = [];

var listings = {};

var popCats = function(data, st, req) {
	cats = data.Data;
};

var popLists = function(data, st, req) {
	var lists = data.Data;
	var t = '';
	for (var j = 0; j < lists.length; j++) {
		listings.push({title:lists[j].Title,guid:lists[j].CategoryGuid});
	}
};

function populateData(opts) {
	ajax({
		url: opts.address,
		type: 'json',
		method: opts.method || 'get'
	}, opts.callback);
};

function setText(opts) {
	simply.text(opts, true);
};

var count = parseInt(localStorage.getItem('count')) || 1;

simply.on('singleClick', function(e) {

	if (e.button === 'up') {
		--count;
	} else if (e.button === 'down') {
		++count;
	}

	if (count <= 1) {
		count = 1;
	}
	if (count >= cats.length) {
		count = cats.length;
	}

	setText({
		title: 'Category (' + count + '/' + cats.length + ')',
		body: cats[count - 1].Name
	})

	localStorage.setItem('count', count);

	if (e.button === 'select') {

	}

	if (e.button === 'back') {

	}

});

populateData({
	address: 'http://ec2-54-76-161-40.eu-west-1.compute.amazonaws.com/zanduli2/MobileService.svc/V2/en/AllCategory',
	callback: popCats
});

populateData({
	address: 'http://ec2-54-76-161-40.eu-west-1.compute.amazonaws.com/zanduli2/MobileService.svc/V2/en/AllListing',
	callback: popLists
});

if (_.isEmpty(cats)){
	simply.title('Zanduli');
} else {
	simply.title('Zulu');
}

<commit_msg>maybe now?<commit_after>//simply.scrollable(true);
simply.style('small');

var text = '';

var cats = [];

var listings = {};

var popCats = function(data, st, req) {
	cats = data.Data;
};

var popLists = function(data, st, req) {
	var lists = data.Data;
	var t = '';
	for (var j = 0; j < lists.length; j++) {
		listings.push({
			title: lists[j].Title,
			guid: lists[j].CategoryGuid
		});
	}
};

function populateData(opts) {
	ajax({
		url: opts.address,
		type: 'json',
		method: opts.method || 'get'
	}, opts.callback);
};

function setText(opts) {
	simply.text(opts, true);
};

var count = parseInt(localStorage.getItem('count')) || 1;

simply.on('singleClick', function(e) {

	if (e.button === 'up') {
		--count;
	} else if (e.button === 'down') {
		++count;
	}

	if (count <= 1) {
		count = 1;
	}
	if (count >= cats.length) {
		count = cats.length;
	}

	setText({
		title: 'Category (' + count + '/' + cats.length + ')',
		body: cats[count - 1].Name
	})

	localStorage.setItem('count', count);

	if (e.button === 'select') {
		var text = '';
		for (var t = 0; t < lists.length; t++) {
			if (listings[t].CategoryGuid === cats[count - 1].Guid) {
				text += listings[t].Title + '\r\n';
			}
		}
		setText({
			title: cats[count - 1].Name,
			body: text
		});
	}

	if (e.button === 'back') {

	}

});

populateData({
	address: 'http://ec2-54-76-161-40.eu-west-1.compute.amazonaws.com/zanduli2/MobileService.svc/V2/en/AllCategory',
	callback: popCats
});

populateData({
	address: 'http://ec2-54-76-161-40.eu-west-1.compute.amazonaws.com/zanduli2/MobileService.svc/V2/en/AllListing',
	callback: popLists
});

simply.title('Zanduli');<|endoftext|>