<commit_before>'use strict';

var _ = require('underscore');
var md5 = require('js-md5');
var base64 = require('base64-js');
var Promise = require('bluebird');
require('isomorphic-fetch');

var OS_CONDUCTOR = process.env.OS_PACKAGER_CONDUCTOR_HOST ||
  'http://next.openspending.org';
var defaultOptions = {
  conductorUrl: OS_CONDUCTOR + '/datastore/',
  publishUrl: OS_CONDUCTOR + '/hooks/load/api/',
  pollInterval: 3000
};
module.exports.defaultOptions = defaultOptions;

var ProcessingStatus = {
  DOWNLOADING: 'downloading',
  READING: 'reading',
  PREPARING: 'preparing',
  UPLOADING: 'uploading',
  PUBLISHING: 'publishing',
  READY: 'ready',
  FAILED: 'failed'
};
module.exports.ProcessingStatus = ProcessingStatus;

function requestViaFetch(url, options) {
  return new Promise(function(resolve, reject) {
    options.mode = 'cors';
    options.credentials = 'omit';

    if (_.isFunction(options.onUploadProgress)) {
      options.onUploadProgress(0.0); // normalized to range 0.0 .. 1.0
    }

    fetch(url, options)
      .then(resolve)
      .catch(reject);
  })
  .then(function(response) {
    if (response.status != 200) {
      throw 'Failed to load data from ' + response.url;
    }
    if (_.isFunction(options.onUploadProgress)) {
      options.onUploadProgress(1.0); // normalized to range 0.0 .. 1.0
    }
    if (_.isFunction(options.onDownloadProgress)) {
      options.onDownloadProgress(0.0); // normalized to range 0.0 .. 1.0
    }
    return response.text();
  })
  .then(function(data) {
    if (_.isFunction(options.onDownloadProgress)) {
      options.onDownloadProgress(1.0); // normalized to range 0.0 .. 1.0
    }
    return data;
  });
}

function requestViaXhr(url, options) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();

    // Upload events
    if (xhr.upload) {
      xhr.upload.onprogress = function(event) {
        if (event.lengthComputable) {
          if (_.isFunction(options.onUploadProgress)) {
            // normalized to range 0.0 .. 1.0
            options.onUploadProgress(event.loaded / event.total);
          }
        }
      };
      xhr.upload.onload = function(event) {
        if (_.isFunction(options.onUploadProgress)) {
          // normalized to range 0.0 .. 1.0
          options.onUploadProgress(1.0);
        }
      };
      xhr.upload.onerror = function(event) {
        reject('An error occurred while transferring the file.');
      };
      xhr.upload.onabort = function(event) {
        reject('The transfer has been canceled by the user.');
      };
    }

    // Download events
    xhr.onprogress = function(event) {
      var total = 0;
      var loaded = event.loaded;
      if (event.lengthComputable) {
        total = event.total;
      } else
      if (xhr.explicitTotal) {
        total = xhr.explicitTotal;
      } else {
        total = parseFloat(xhr.getResponseHeader('Content-Length'));
        if (isFinite(total)) {
          var encoding = xhr.getResponseHeader('Content-Encoding') || 'deflate';
          if (('' + encoding).toLowerCase() != 'deflate') {
            total = total * 17; // Magic number
          }
          xhr.explicitTotal = total;
        } else {
          total = 0;
        }
      }
      if ((total >= loaded) && _.isFunction(options.onDownloadProgress)) {
        // normalized to range 0.0 .. 1.0
        options.onDownloadProgress(loaded / total);
      }
    };
    xhr.onload = function(event) {
      if (_.isFunction(options.onDownloadProgress)) {
        // normalized to range 0.0 .. 1.0
        options.onDownloadProgress(1.0);
      }
      resolve(xhr.responseText);
    };
    xhr.onerror = function(event) {
      reject('An error occurred while transferring the file.');
    };
    xhr.onabort = function(event) {
      reject('The transfer has been canceled by the user.');
    };

    xhr.open(options.method || 'GET', url);

    // Set headers
    _.each(options.headers, function(value, key) {
      if (('' + key).toLowerCase() == 'content-length') {
        return;
      }
      xhr.setRequestHeader(key, value);
    });

    xhr.send(options.body);
  });
}

function requestAutoDetect(url, options) {
  if (!module.exports.disableXhr) {
    if ((typeof XMLHttpRequest != 'undefined') &&
      _.isFunction(XMLHttpRequest)) {
      return requestViaXhr(url, options);
    }
  }
  if ((typeof fetch != 'undefined') && _.isFunction(fetch)) {
    return requestViaFetch(url, options);
  }
  return Promise.reject('Both XMLHttpRequest and fetch API are not supported.');
}

function readFileBytes(fileOrBlob, options) {
  options = _.isObject(options) ? options : {};
  return new Promise(function(resolve, reject) {
    var reader = new FileReader();

    reader.addEventListener('progress', function(event) {
      if (event.lengthComputable) {
        if (_.isFunction(options.onDownloadProgress)) {
          // normalized to range 0.0 .. 1.0
          options.onDownloadProgress(event.loaded / event.total);
        }
      }
    });
    reader.addEventListener('load', function(event) {
      if (_.isFunction(options.onDownloadProgress)) {
        // normalized to range 0.0 .. 1.0
        options.onDownloadProgress(1.0);
      }
      resolve(new Uint8Array(reader.result));
    });
    reader.addEventListener('error', function(event) {
      reject('An error occurred while reading the file.');
    });
    reader.addEventListener('abort', function(event) {
      reject('Reading has been canceled by the user.');
    });

    reader.readAsArrayBuffer(fileOrBlob);
  });
}

function calculateMD5(data) {
  var hash = md5.update(data);
  return base64.fromByteArray(hash.array());
}

function uploadFile(descriptor, options) {
  var requestOptions = _.extend({}, options, {
    method: 'PUT',
    headers: _.extend({}, options.headers, {
      'Content-Length': descriptor.data.length,
      'Content-MD5': calculateMD5(descriptor.data),
      'Content-Type': 'application/octet-stream'
    }),
    body: descriptor.data,
    mode: 'cors',
    redirect: 'follow',
    credentials: 'omit'
  });

  var query = _.chain(descriptor.uploadParams)
    .map(function(value, key) {
      return encodeURIComponent(key) + '=' + encodeURIComponent(value);
    })
    .join('&')
    .value();

  return requestAutoDetect(descriptor.uploadUrl + '?' + query, requestOptions);
}

function prepareFilesForUpload(files, options) {
  options = _.extend({}, module.exports.defaultOptions, options);

  var payload = {
    metadata: {
      owner: options.owner,
      name: options.name,
      author: options.name
    },
    filedata: _.chain(files)
      .map(function(item) {
        return [
          item.name,
          {
            md5: calculateMD5(item.data),
            name: item.name,
            length: item.data.length,
            type: 'application/octet-stream'
          }
        ];
      })
      .object()
      .value()
  };

  var requestOptions = {
    method: 'POST',
    headers: {
      // jscs:disable
      'Auth-Token': options.permission_token
      // jscs:enable
    },
    body: JSON.stringify(payload),
    mode: 'cors',
    credentials: 'omit'
  };

  return fetch(options.conductorUrl, requestOptions)
    .then(function(response) {
      if (response.status != 200) {
        throw 'Failed to load data from ' + response.url;
      }
      return response.json();
    })
    .then(function(response) {
      if (_.isObject(response.filedata)) {
        return _.chain(response.filedata)
          .map(function(item, key) {
            // jscs:disable
            var uploadUrl = item.upload_url;
            var uploadParams = item.upload_query;
            // jscs:enable
            return [
              key,
              {
                uploadUrl: uploadUrl,
                uploadParams: _.chain(uploadParams)
                  .map(function(values, key) {
                    return [key, _.first(values)];
                  })
                  .object()
                  .value()
              }
            ];
          })
          .object()
          .value();
      }
      return {};
    });
}

module.exports.readContents = function(descriptor, options) {
  options = _.extend({}, defaultOptions, options, {
    onDownloadProgress: function(value) {
      descriptor.progress = value;
    }
  });
  descriptor.progress = 0.0;

  var result = null;

  if (_.isString(descriptor.url)) {
    descriptor.status = ProcessingStatus.DOWNLOADING;
    options.headers = options.header || {};
    result = requestAutoDetect(descriptor.url, options);
  } else
  if (_.isObject(descriptor.file) && (descriptor.file instanceof Blob)) {
    descriptor.status = ProcessingStatus.READING;
    result = readFileBytes(descriptor.file, options);
  } else {
    var data = descriptor.data || '';
    if (_.isObject(descriptor.file) &&
      !(descriptor.file.data instanceof ArrayBuffer)) {
      data = descriptor.file.data || '';
    }
    if (!_.isString(data) && _.isObject(data)) {
      data = JSON.stringify(data, null, 2);
    }
    result = Promise.resolve(data);
  }

  return result
    .then(function(data) {
      descriptor.progress = 1.0;
      descriptor.data = data;
      descriptor.countOfLines = 0;
      for (var i = 0; i < data.length; i++) {
        if (data[i] == '\n' || data[i] == 10) {
          descriptor.countOfLines ++;
        }
      }
      return descriptor;
    });
};

module.exports.prepareForUpload = function(descriptor, options) {
  options = _.extend({}, defaultOptions, options);
  descriptor.status = ProcessingStatus.PREPARING;
  descriptor.progress = 0.0;
  return prepareFilesForUpload([descriptor], options)
    .then(function(results) {
      _.extend(descriptor, results[descriptor.name]);
      descriptor.progress = 1.0;
      return descriptor;
    });
};

module.exports.upload = function(descriptor, options) {
  options = _.extend({}, defaultOptions, options, {
    onUploadProgress: function(value) {
      descriptor.progress = value;
    }
  });
  descriptor.status = ProcessingStatus.UPLOADING;
  descriptor.progress = 0.0;
  return uploadFile(descriptor, options)
    .then(function() {
      descriptor.progress = 1.0;
      return descriptor;
    });
};

module.exports.publish = function(descriptor, options) {
  return new Promise(function(resolve, reject) {
    options = _.extend({}, module.exports.defaultOptions, options);

    descriptor.status = ProcessingStatus.PUBLISHING;
    descriptor.progress = 0.0;

    var pollUrl = options.publishUrl +
      '?datapackage=' + encodeURIComponent(descriptor.uploadUrl);

    var poll = function() {
      fetch(pollUrl)
        .then(function(response) {
          if (response.status != 200) {
            throw 'Failed to load data from ' + response.url;
          }
          return response.json();
        })
        .then(function(response) {
          if (!_.isObject(response)) {
            throw 'Response should be an object';
          }
          switch (('' + response.status).toLowerCase()) {
            case 'success':
            case 'done':
              descriptor.progress = 1.0;
              resolve(descriptor);
              break;
            case 'fail':
              throw response.error; // Go to .catch()
              break;
            default:
              // response.progress is count of processed lines
              var progress = parseFloat(response.progress);
              if (isFinite(progress) && (descriptor.countOfLines >= progress)) {
                descriptor.progress = progress / descriptor.countOfLines;
              }
              setTimeout(poll, options.pollInterval);
          }
        })
        .catch(function(error) {
          descriptor.status = ProcessingStatus.FAILED;
          descriptor.error = error;
          reject(error);
        });
    };

    var requestOptions = {
      method: 'POST',
      mode: 'cors',
      credentials: 'omit'
    };
    fetch(pollUrl, requestOptions)
      .then(function() {
        poll();
      })
      .catch(function(error) {
        descriptor.status = ProcessingStatus.FAILED;
        descriptor.error = error;
        reject(error);
      });
  });
};
<commit_msg>Provide better status indications while publishing<commit_after>'use strict';

var _ = require('underscore');
var md5 = require('js-md5');
var base64 = require('base64-js');
var Promise = require('bluebird');
require('isomorphic-fetch');

var OS_CONDUCTOR = process.env.OS_PACKAGER_CONDUCTOR_HOST ||
  'http://next.openspending.org';
var defaultOptions = {
  conductorUrl: OS_CONDUCTOR + '/datastore/',
  publishUrl: OS_CONDUCTOR + '/hooks/load/api/',
  pollInterval: 1000
};
module.exports.defaultOptions = defaultOptions;

var ProcessingStatus = {
  DOWNLOADING: 'Downloading',
  READING: 'Reading',
  PREPARING: 'Preparing',
  UPLOADING: 'Uploading',
  PUBLISHING: 'Publishing',
  READY: 'Ready',
  FAILED: 'Failed'
};

var RemoteProcessingStatus = {
  'queued': 'Waiting in queue for an available processor',
  'initializing': 'Getting ready to load the package',
  'loading-datapackage': 'Reading the Fiscal Data Package',
  'validating-datapackage': 'Validagin Data Package correctness',
  'loading-resource': 'Loading Resource data',
  'deleting-table': 'Clearing previous rows for this dataset from the database',
  'creating-table': 'Preparing space for rows in the database',
  'loading-data-ready': 'Starting to load rows to database',
  'loading-data': 'Loading data into the database',
  'creating-babbage-model': 'Converting the Data Package into an API model',
  'saving-metadata': 'Saving package metadata',
  'done': 'Done',
  'fail': 'Failed'
};

module.exports.ProcessingStatus = ProcessingStatus;

function requestViaFetch(url, options) {
  return new Promise(function(resolve, reject) {
    options.mode = 'cors';
    options.credentials = 'omit';

    if (_.isFunction(options.onUploadProgress)) {
      options.onUploadProgress(0.0); // normalized to range 0.0 .. 1.0
    }

    fetch(url, options)
      .then(resolve)
      .catch(reject);
  })
  .then(function(response) {
    if (response.status != 200) {
      throw 'Failed to load data from ' + response.url;
    }
    if (_.isFunction(options.onUploadProgress)) {
      options.onUploadProgress(1.0); // normalized to range 0.0 .. 1.0
    }
    if (_.isFunction(options.onDownloadProgress)) {
      options.onDownloadProgress(0.0); // normalized to range 0.0 .. 1.0
    }
    return response.text();
  })
  .then(function(data) {
    if (_.isFunction(options.onDownloadProgress)) {
      options.onDownloadProgress(1.0); // normalized to range 0.0 .. 1.0
    }
    return data;
  });
}

function requestViaXhr(url, options) {
  return new Promise(function(resolve, reject) {
    var xhr = new XMLHttpRequest();

    // Upload events
    if (xhr.upload) {
      xhr.upload.onprogress = function(event) {
        if (event.lengthComputable) {
          if (_.isFunction(options.onUploadProgress)) {
            // normalized to range 0.0 .. 1.0
            options.onUploadProgress(event.loaded / event.total);
          }
        }
      };
      xhr.upload.onload = function(event) {
        if (_.isFunction(options.onUploadProgress)) {
          // normalized to range 0.0 .. 1.0
          options.onUploadProgress(1.0);
        }
      };
      xhr.upload.onerror = function(event) {
        reject('An error occurred while transferring the file.');
      };
      xhr.upload.onabort = function(event) {
        reject('The transfer has been canceled by the user.');
      };
    }

    // Download events
    xhr.onprogress = function(event) {
      var total = 0;
      var loaded = event.loaded;
      if (event.lengthComputable) {
        total = event.total;
      } else
      if (xhr.explicitTotal) {
        total = xhr.explicitTotal;
      } else {
        total = parseFloat(xhr.getResponseHeader('Content-Length'));
        if (isFinite(total)) {
          var encoding = xhr.getResponseHeader('Content-Encoding') || 'deflate';
          if (('' + encoding).toLowerCase() != 'deflate') {
            total = total * 17; // Magic number
          }
          xhr.explicitTotal = total;
        } else {
          total = 0;
        }
      }
      if ((total >= loaded) && _.isFunction(options.onDownloadProgress)) {
        // normalized to range 0.0 .. 1.0
        options.onDownloadProgress(loaded / total);
      }
    };
    xhr.onload = function(event) {
      if (_.isFunction(options.onDownloadProgress)) {
        // normalized to range 0.0 .. 1.0
        options.onDownloadProgress(1.0);
      }
      resolve(xhr.responseText);
    };
    xhr.onerror = function(event) {
      reject('An error occurred while transferring the file.');
    };
    xhr.onabort = function(event) {
      reject('The transfer has been canceled by the user.');
    };

    xhr.open(options.method || 'GET', url);

    // Set headers
    _.each(options.headers, function(value, key) {
      if (('' + key).toLowerCase() == 'content-length') {
        return;
      }
      xhr.setRequestHeader(key, value);
    });

    xhr.send(options.body);
  });
}

function requestAutoDetect(url, options) {
  if (!module.exports.disableXhr) {
    if ((typeof XMLHttpRequest != 'undefined') &&
      _.isFunction(XMLHttpRequest)) {
      return requestViaXhr(url, options);
    }
  }
  if ((typeof fetch != 'undefined') && _.isFunction(fetch)) {
    return requestViaFetch(url, options);
  }
  return Promise.reject('Both XMLHttpRequest and fetch API are not supported.');
}

function readFileBytes(fileOrBlob, options) {
  options = _.isObject(options) ? options : {};
  return new Promise(function(resolve, reject) {
    var reader = new FileReader();

    reader.addEventListener('progress', function(event) {
      if (event.lengthComputable) {
        if (_.isFunction(options.onDownloadProgress)) {
          // normalized to range 0.0 .. 1.0
          options.onDownloadProgress(event.loaded / event.total);
        }
      }
    });
    reader.addEventListener('load', function(event) {
      if (_.isFunction(options.onDownloadProgress)) {
        // normalized to range 0.0 .. 1.0
        options.onDownloadProgress(1.0);
      }
      resolve(new Uint8Array(reader.result));
    });
    reader.addEventListener('error', function(event) {
      reject('An error occurred while reading the file.');
    });
    reader.addEventListener('abort', function(event) {
      reject('Reading has been canceled by the user.');
    });

    reader.readAsArrayBuffer(fileOrBlob);
  });
}

function calculateMD5(data) {
  var hash = md5.update(data);
  return base64.fromByteArray(hash.array());
}

function uploadFile(descriptor, options) {
  var requestOptions = _.extend({}, options, {
    method: 'PUT',
    headers: _.extend({}, options.headers, {
      'Content-Length': descriptor.data.length,
      'Content-MD5': calculateMD5(descriptor.data),
      'Content-Type': 'application/octet-stream'
    }),
    body: descriptor.data,
    mode: 'cors',
    redirect: 'follow',
    credentials: 'omit'
  });

  var query = _.chain(descriptor.uploadParams)
    .map(function(value, key) {
      return encodeURIComponent(key) + '=' + encodeURIComponent(value);
    })
    .join('&')
    .value();

  return requestAutoDetect(descriptor.uploadUrl + '?' + query, requestOptions);
}

function prepareFilesForUpload(files, options) {
  options = _.extend({}, module.exports.defaultOptions, options);

  var payload = {
    metadata: {
      owner: options.owner,
      name: options.name,
      author: options.name
    },
    filedata: _.chain(files)
      .map(function(item) {
        return [
          item.name,
          {
            md5: calculateMD5(item.data),
            name: item.name,
            length: item.data.length,
            type: 'application/octet-stream'
          }
        ];
      })
      .object()
      .value()
  };

  var requestOptions = {
    method: 'POST',
    headers: {
      // jscs:disable
      'Auth-Token': options.permission_token
      // jscs:enable
    },
    body: JSON.stringify(payload),
    mode: 'cors',
    credentials: 'omit'
  };

  return fetch(options.conductorUrl, requestOptions)
    .then(function(response) {
      if (response.status != 200) {
        throw 'Failed to load data from ' + response.url;
      }
      return response.json();
    })
    .then(function(response) {
      if (_.isObject(response.filedata)) {
        return _.chain(response.filedata)
          .map(function(item, key) {
            // jscs:disable
            var uploadUrl = item.upload_url;
            var uploadParams = item.upload_query;
            // jscs:enable
            return [
              key,
              {
                uploadUrl: uploadUrl,
                uploadParams: _.chain(uploadParams)
                  .map(function(values, key) {
                    return [key, _.first(values)];
                  })
                  .object()
                  .value()
              }
            ];
          })
          .object()
          .value();
      }
      return {};
    });
}

module.exports.readContents = function(descriptor, options) {
  options = _.extend({}, defaultOptions, options, {
    onDownloadProgress: function(value) {
      descriptor.progress = value;
    }
  });
  descriptor.progress = 0.0;

  var result = null;

  if (_.isString(descriptor.url)) {
    descriptor.status = ProcessingStatus.DOWNLOADING;
    options.headers = options.header || {};
    result = requestAutoDetect(descriptor.url, options);
  } else
  if (_.isObject(descriptor.file) && (descriptor.file instanceof Blob)) {
    descriptor.status = ProcessingStatus.READING;
    result = readFileBytes(descriptor.file, options);
  } else {
    var data = descriptor.data || '';
    if (_.isObject(descriptor.file) &&
      !(descriptor.file.data instanceof ArrayBuffer)) {
      data = descriptor.file.data || '';
    }
    if (!_.isString(data) && _.isObject(data)) {
      data = JSON.stringify(data, null, 2);
    }
    result = Promise.resolve(data);
  }

  return result
    .then(function(data) {
      descriptor.progress = 1.0;
      descriptor.data = data;
      descriptor.countOfLines = 0;
      for (var i = 0; i < data.length; i++) {
        if (data[i] == '\n' || data[i] == 10) {
          descriptor.countOfLines ++;
        }
      }
      return descriptor;
    });
};

module.exports.prepareForUpload = function(descriptor, options) {
  options = _.extend({}, defaultOptions, options);
  descriptor.status = ProcessingStatus.PREPARING;
  descriptor.progress = 0.0;
  return prepareFilesForUpload([descriptor], options)
    .then(function(results) {
      _.extend(descriptor, results[descriptor.name]);
      descriptor.progress = 1.0;
      return descriptor;
    });
};

module.exports.upload = function(descriptor, options) {
  options = _.extend({}, defaultOptions, options, {
    onUploadProgress: function(value) {
      descriptor.progress = value;
    }
  });
  descriptor.status = ProcessingStatus.UPLOADING;
  descriptor.progress = 0.0;
  return uploadFile(descriptor, options)
    .then(function() {
      descriptor.progress = 1.0;
      return descriptor;
    });
};

module.exports.publish = function(descriptor, options) {
  return new Promise(function(resolve, reject) {
    options = _.extend({}, module.exports.defaultOptions, options);

    descriptor.status = ProcessingStatus.PUBLISHING;
    descriptor.progress = 0.0;

    var pollUrl = options.publishUrl +
      '?datapackage=' + encodeURIComponent(descriptor.uploadUrl);

    var poll = function() {
      fetch(pollUrl)
        .then(function(response) {
          if (response.status != 200) {
            throw 'Failed to load data from ' + response.url;
          }
          return response.json();
        })
        .then(function(response) {
          if (!_.isObject(response)) {
            throw 'Response should be an object';
          }
          var responseStatus = ('' + response.status).toLowerCase();
          switch (responseStatus) {
            case 'done':
              descriptor.progress = 1.0;
              resolve(descriptor);
              break;
            case 'fail':
              throw response.error; // Go to .catch()
              break;
            default:
              // response.progress is count of processed lines
              descriptor.status = RemoteProcessingStatus[responseStatus] || responseStatus;
              var progress = parseFloat(response.progress);
              if (isFinite(progress) && (descriptor.countOfLines >= progress)) {
                descriptor.progress = progress / descriptor.countOfLines;
              }
              setTimeout(poll, options.pollInterval);
          }
        })
        .catch(function(error) {
          descriptor.status = ProcessingStatus.FAILED;
          descriptor.error = error;
          reject(error);
        });
    };

    var requestOptions = {
      method: 'POST',
      mode: 'cors',
      credentials: 'omit'
    };
    fetch(pollUrl, requestOptions)
      .then(function() {
        poll();
      })
      .catch(function(error) {
        descriptor.status = ProcessingStatus.FAILED;
        descriptor.error = error;
        reject(error);
      });
  });
};
<|endoftext|>


<commit_before>import Ember from 'ember';

// How to use
// thinkyBrain: Ember.inject.service('thinky-brain')
const { computed, get } = Ember;

export default Ember.Service.extend({
  patterns: ["say", "don't say", "think", "don't think", "know", "don't know"],
  subjects: ["you", "I", "we", "they", "he", "she"],

  thoughts: computed(function(){
    let patterns = get(this, 'patterns');
    let subjects = get(this, 'subjects');
    let rp = this.shuffle(patterns); // random patterns
    let rs = this.shuffle(subjects); // random subjects
    let s = rs[0];
    let phrase = `${s} ${rp[0]} ${s} ${rp[1]} ${s} ${rp[2]} ${s} ${rp[3]}`;
    return phrase;
  }).volatile(),

  shuffle: function(array) {
    var m = array.length, t, i;

    // While there remain elements to shuffle…
    while (m) {

      // Pick a remaining element…
      i = Math.floor(Math.random() * m--);

      // And swap it with the current element.
      t = array[m];
      array[m] = array[i];
      array[i] = t;
    }

    return array;
  }

});
<commit_msg>better parts of speech<commit_after>import Ember from 'ember';

// How to use
// thinkyBrain: Ember.inject.service('thinky-brain')
const { computed, get } = Ember;

export default Ember.Service.extend({
  verbs: ["see", "don't see", "say", "don't say", "think", "don't think", "know", "don't know", "help", "don't help"],
  nouns: ["cats", "dogs", "people", "lovers", "friends"],
  subjects: ["you", "I", "we", "they", "he", "she"],

  thoughts: computed(function(){
    let verbs = get(this, 'verbs');
    let subjects = get(this, 'subjects');
    let nouns = get(this, 'nouns');
    let rp = this.shuffle(verbs); // random verbs
    let rn = this.shuffle(nouns); // random nouns
    let rs = this.shuffle(subjects); // random subjects
    let s = rs[0];
    let n = rn[0];
    let phrase = `${s} ${rp[0]} ${s} ${rp[1]} when ${s} ${rp[2]} ${n} ${s} ${rp[3]}`;
    return phrase;
  }).volatile(),

  shuffle: function(array) {
    var m = array.length, t, i;

    // While there remain elements to shuffle…
    while (m) {

      // Pick a remaining element…
      i = Math.floor(Math.random() * m--);

      // And swap it with the current element.
      t = array[m];
      array[m] = array[i];
      array[i] = t;
    }

    return array;
  }

});
<|endoftext|>


<commit_before>// creates the tests out of the examples in the documentation

hfile = process.argv[2]; // the path to the files (e.g. ./qminer/nodedoc/)
outfile = process.argv[3]; // the the folder where the tests will be saved (e.g. ./qminer/test/nodejs/)

fs = require('fs');

// get the .js files from the file array
if (hfile != 0) {
    var fileNames = fs.readdirSync(hfile);
}
var JSFiles = [];
for (var i = 0; i < fileNames.length; i++) {
    if (fileNames[i].indexOf(".js") != -1 && fileNames[i].indexOf(".html") == -1) {
        JSFiles.push(fileNames[i]);
    }
}

// constructs the it('should something', function () { ... }) test
var constructIt = function (describe, str, i) {
    var test = 'describe("'+ describe + ', number ' + i +'", function () {\nit("should make test number ' + i + '", function () {\n this.timeout(10000); \n';
    test += str + "\n});\n});\n";
    return test;
}

// for each .js file extract the examples
for (var i = 0; i < JSFiles.length; i++) {
    // prepared outfile for writing
    if (outfile != '') {
        fout = fs.createWriteStream(outfile + 'example' + JSFiles[i]);
    }

    // write the describe of the file (to know in which file the test throws the error)
    fout.write("describe('example tests for the " + JSFiles[i] + " file', function () {\n");

    var hstr = fs.readFileSync(hfile + JSFiles[i], 'ascii');
    // get the rows between * @example and @example or */ - getting the example code
    var regex = /(\/\*\*([\s\S]*?)\*\/)/g;
    var count = 0;
    while ((match = regex.exec(hstr)) != null) {
        str = match[0];

        if ((str.indexOf("IntVector") != -1 || str.indexOf("StrVector") != -1 || str.indexOf("BoolVector") != -1) &&
            (str.indexOf("cosine") != -1 || str.indexOf("sortPerm") != -1 || str.indexOf("outer") != -1)) {
            continue;
        }

        // for quicker search of the test
        title = str.slice(3);
        title = title.slice(title.indexOf('*') + 1);
        // get the description of the function
        describe = title.slice(1, title.indexOf('*') - 1);
        lastTab = describe.lastIndexOf("\t");
        if (lastTab != -1) {
            describe = describe.substring(0, lastTab);
        }
        lastNewline = describe.lastIndexOf("\n");
        if (lastNewline != -1) {
            describe = describe.substring(0, lastNewline - 1);
        }
        if (lastNewline == -1 && lastTab == -1) {
            describe = describe.substring(0, describe.length - 1);
        }
        // if it has the example
        var exampleIdx = str.indexOf('@example');
        if (exampleIdx != -1) {
            // create the it block/test
			str = str.slice(exampleIdx);
			examples = str.split('@example');
			for (var ExpN = 0; ExpN < examples.length; ExpN++) {
				var example = examples[ExpN];
				//console.log(example);
				if (example == '') { continue; }
				if (example.indexOf('
') != -1) {
					example = example.slice(example.indexOf('
') + 10);
				}
				count += 1;
				example = example.replace(/(\*)/g, '');
				if (example.indexOf('*/') != -1) { example = example.slice(0, example.length - 2);}
				else { example = example.slice(0, example.length - 1); }
				fout.write(constructIt(describe, example, count));
			}
            // str = str.slice(exampleIdx);
            // str = str.replace(/(\*)/g, '');
            // str = str.slice(8, str.length - 2);
            // fout.write(constructIt(str, count));
        }
    }
    fout.write("\n});\n");
}<commit_msg>Removed timeout from the example tests.<commit_after>// creates the tests out of the examples in the documentation

hfile = process.argv[2]; // the path to the files (e.g. ./qminer/nodedoc/)
outfile = process.argv[3]; // the the folder where the tests will be saved (e.g. ./qminer/test/nodejs/)

fs = require('fs');

// get the .js files from the file array
if (hfile != 0) {
    var fileNames = fs.readdirSync(hfile);
}
var JSFiles = [];
for (var i = 0; i < fileNames.length; i++) {
    if (fileNames[i].indexOf(".js") != -1 && fileNames[i].indexOf(".html") == -1) {
        JSFiles.push(fileNames[i]);
    }
}

// constructs the it('should something', function () { ... }) test
var constructIt = function (describe, str, i) {
    var test = 'describe("'+ describe + ', number ' + i +'", function () {\nit("should make test number ' + i + '", function () {\n';
    test += str + "\n});\n});\n";
    return test;
}

// for each .js file extract the examples
for (var i = 0; i < JSFiles.length; i++) {
    // prepared outfile for writing
    if (outfile != '') {
        fout = fs.createWriteStream(outfile + 'example' + JSFiles[i]);
    }

    // write the describe of the file (to know in which file the test throws the error)
    fout.write("describe('example tests for the " + JSFiles[i] + " file', function () {\n");

    var hstr = fs.readFileSync(hfile + JSFiles[i], 'ascii');
    // get the rows between * @example and @example or */ - getting the example code
    var regex = /(\/\*\*([\s\S]*?)\*\/)/g;
    var count = 0;
    while ((match = regex.exec(hstr)) != null) {
        str = match[0];

        if ((str.indexOf("IntVector") != -1 || str.indexOf("StrVector") != -1 || str.indexOf("BoolVector") != -1) &&
            (str.indexOf("cosine") != -1 || str.indexOf("sortPerm") != -1 || str.indexOf("outer") != -1)) {
            continue;
        }

        // for quicker search of the test
        title = str.slice(3);
        title = title.slice(title.indexOf('*') + 1);
        // get the description of the function
        describe = title.slice(1, title.indexOf('*') - 1);
        lastTab = describe.lastIndexOf("\t");
        if (lastTab != -1) {
            describe = describe.substring(0, lastTab);
        }
        lastNewline = describe.lastIndexOf("\n");
        if (lastNewline != -1) {
            describe = describe.substring(0, lastNewline - 1);
        }
        if (lastNewline == -1 && lastTab == -1) {
            describe = describe.substring(0, describe.length - 1);
        }
        // if it has the example
        var exampleIdx = str.indexOf('@example');
        if (exampleIdx != -1) {
            // create the it block/test
			str = str.slice(exampleIdx);
			examples = str.split('@example');
			for (var ExpN = 0; ExpN < examples.length; ExpN++) {
				var example = examples[ExpN];
				//console.log(example);
				if (example == '') { continue; }
				if (example.indexOf('
') != -1) {
					example = example.slice(example.indexOf('
') + 10);
				}
				count += 1;
				example = example.replace(/(\*)/g, '');
				if (example.indexOf('*/') != -1) { example = example.slice(0, example.length - 2);}
				else { example = example.slice(0, example.length - 1); }
				fout.write(constructIt(describe, example, count));
			}
            // str = str.slice(exampleIdx);
            // str = str.replace(/(\*)/g, '');
            // str = str.slice(8, str.length - 2);
            // fout.write(constructIt(str, count));
        }
    }
    fout.write("\n});\n");
}<|endoftext|>


<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 */
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(["require", "../deep"], function (require, deep) {

    function Unit(unit){
        if(unit)
            deep.utils.up(unit, this);
        //console.log("Unit created : ", this);
        this.tests  = this.tests || {};
    }

    Unit.prototype = {
        _deep_unit_:true,
        title:"Generic tests",
        stopOnError:false,
        options:null,
        setup : function(options){
        },
        clean : function(options){
            delete this.context;
        },
        run : function(tests, options)
        {
            options = options || {};
            tests = tests || [];
            if(!tests.forEach)
                tests = [tests];
            //console.log("unit context : ", context);
            var functions = deep.query(this.tests, "./["+tests.join(",")+"]", { resultType:"full" });
            var numberOfTests = functions.length;
            var stopOnError = this.stopOnError;
            if(typeof options.stopOnError !== 'undefined')
                stopOnError = options.stopOnError;
            if(options.verbose !== false)
            {
                if(console.group)
                    console.group("unit : "+this.title);

                console.log("\n\n**********************************************************");
                console.log("*****  lib/unit : will run : ", this.title, " *****");
                console.log("\tStop on error ? ", stopOnError );
                console.log("\tNumber of tests : ",functions.length,"\n" );
            }
            //console.log("\tContext : ",context,"\n\n" );
            var errors = [];
            var self = this, totalTime = 0;

            if(functions.length === 0)
            {
                if(options.verbose !== false)
                {
                    console.log("**********************************************************");
                    console.log("************* Nothing to do : aborting unit **************");
                    console.log("**********************************************************");
                    if(console.groupEnd)
                        console.groupEnd();
                }
                return {
                    title:self.title,
                    numberOfTests:0,
                    success:0,
                    failure:0,
                    ommited:0,
                    errors:errors,
                    valid:true,
                    time:0
                };
            }
            var results = [];
            var d = deep.when(this.setup(options));
            var closure = {};
            var applyTest = function(fn)
            {
                if(options.verbose !== false)
                    console.log("\n- unit test runned : ", fn.key);
                closure.fn = fn;
                var time = new Date().getTime();
                return deep.when(fn.value.call(self.context))
                .always(function(s,e){
                    time = new Date().getTime() - time;
                    totalTime += time;
                    if(options.verbose !== false)
                        if(e)
                            console.error("****** test failed ! ******* : ",fn.key, " error : ", e, e.report);
                        else
                            console.log("\tok !         ("+time+" ms)");
                });
            };
            var done = function(r)
            {
                results.push(r);
                if(functions.length > 0)
                    d.when(applyTest(functions.shift())).done(done).fail(fail);
            };
            var fail = function(error)
            {
                results.push(error);
                 errors.push({
                            unit:self.title,
                            test:closure.fn.key,
                            error:error
                        });
                //deep.utils.dumpError(error);
                if(!stopOnError && functions.length > 0)
                    d.when(applyTest(functions.shift())).done(done).fail(fail);
                return true;
            };
            d.always(function(){
                if(options.verbose !== false)
                {
                    console.log("\tsetup done.");
                }
            })
            .done(function(context)
            {
                self.context = context || {};

                this.when(applyTest(functions.shift()))
                .done(done)
                .fail(fail);
            })
            .always(function(s,e)
            {
                //console.log("_______________________________________________ unit test result : ",s,e);
                if(options.verbose !== false)
                {
                    console.log("\n*************", self.title, " : time ****************");

                    if(e || results.length < numberOfTests || errors.length > 0)
                        console.warn("*************",self.title," : FAILED **************");
                    else
                        console.log("*************",self.title," : PASSED **************");

                    if(errors.length > 0)
                    {
                        console.log("\n\tErrors : ");
                        console.log("\t", e || errors);
                    }

                    console.log("\n\tNumber of tests : ", numberOfTests);
                    console.log("\tsuccess : ", results.length-errors.length,"/",numberOfTests);
                    console.log("\tfailure : ", errors.length,"/",numberOfTests);
                    console.log("\tommited : ", numberOfTests-results.length,"/",numberOfTests);
                    console.log("\ttime : ", totalTime);
                }
                return self.clean();
            })
            .always(function(s,e)
            {
                if(options.verbose !== false)
                {
                    if(e)
                        console.log("error while cleanin test : ",self.title, " : ", e);
                    console.log("\n**************", self.title, " cleaned **************");
                    console.log("***********************************************************");
                    if(console.groupEnd)
                        console.groupEnd();
                }
                return {
                    title:self.title,
                    numberOfTests:numberOfTests,
                    success:results.length-errors.length,
                    failure:errors.length,
                    ommited:numberOfTests-results.length,
                    //results:results,
                    errors:errors,
                    valid:((errors.length === 0) && (results.length == numberOfTests)),
                    time:totalTime
                };
            });
            return d;
        }
    };

    Unit.run = deep.test = function(units, options){
        if(!options && units === false)
            options = units;
        if(options === false)
            options = { verbose:false };
        else
            options = options || {};
        //if(options.verbose !== false)
        //{
            console.log("\n*******************************************************************");
            console.log("*************************** Units Bunch ****************************");
        //}
        units = units || deep.coreUnits;
        var alls = [];
        if(!units.forEach)
            units = [units];
        units.forEach(function(unit){
            if(typeof unit === 'string')
                alls.push(deep.get(unit));
            else
                alls.push(unit);
        });
        var report = {
            reports:[],
            errors:[],
            numberOfUnits:units.length,
            numberOfTests:0,
            success:0,
            failure:0,
            ommited:0,
            time:0
        };
        deep.counter = { delayCount:0 };
        if(alls.length === 0)
            return deep.when(report);
        return deep.all(alls)
        .done(function(units){
            deep.context = this._context = {};
            //console.log("units loaded : ", units);
            if(options.profile)
                console.profile("bunch");
            var results = [];
            var errors = [];
            var doTest = function(unit){
                unit = new deep.Unit(unit);
                if(options.verbose !== false)
                    console.log("\n\n\n*************** Executing unit : ", unit.title);
                return deep.when(unit.run("*",options));
            };
            var startTime = new Date().getTime();

            //if(options.verbose !== false)
            if(console.time)
                console.time("bunch");
            var d = deep.when(doTest(units.shift()));
            var always = function(s,e){
                if(e)
                    report.errors.push(e);
                report.reports.push(s);
                report.success += s.success;
                report.failure += s.failure;
                report.ommited += s.ommited;
                report.numberOfTests += s.numberOfTests;
                report.errors = report.errors.concat(s.errors);
                report.time += s.time;
                results.push(s);
                if(units.length > 0)
                    d.when(doTest(units.shift())).always(always);
                return true;
            };
            return d.always(always)
            .always(function(s,e){
                if(options.profile)
                    console.profileEnd("bunch");
                report.totalTime = new Date().getTime() - startTime;
                //if(options.verbose !== false)
                //{
                    console.log("\n\n\n___________________________________________________________________");
                    console.log("\n*******************************************************************");
                    console.log("************************** Bunch time : ***************************");
                    if(console.time)
                        console.timeEnd("bunch");
                    if(e)
                        console.log("error while executings tests bunch : ", e);
                    console.log("*******************************************************************");
                    console.log("********** tests bunch arrived to end : final report : ************");
                    //console.log("\n",report,"\n");
                    console.log("\n\tErrors: ");
                    report.errors.forEach(function (e) {
                        console.log(e.unit+":"+e.test, e.error.toString());
                        if(e.error && e.error.report)
                            console.log("report : ", report.toString());

                    });
                    console.log("\tNumber of units : ", report.numberOfUnits);
                    console.log("\tNumber of tests : ", report.numberOfTests);
                    console.log("\tsuccess : ", report.success,"/",report.numberOfTests);
                    console.log("\tfailure : ", report.failure,"/",report.numberOfTests);
                    console.log("\tommited : ", report.ommited,"/",report.numberOfTests);
                    console.log("\ttime : ", report.time);
                    console.log("\ttotalTime : ", report.totalTime);
                    console.log("\tcounters : ", JSON.stringify(deep.counter, null, ' '));
                    //console.log(JSON.stringify(report, null, ' '));
                    console.log("\n*******************************************************************");
                    console.log("*******************************************************************");
                    console.log("___________________________________________________________________\n\n");
                //}
                report.counters = deep.counter;
                return report;
            });
        })
        .fail(function(error){
            console.error("deep : Unit bunch failed to load : ", error);
        });
    };

    deep.Unit = Unit;

    return Unit;
});

<commit_msg>add ocm management in units<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 */
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}

define(["require", "../deep"], function (require, deep) {

    function Unit(unit){
        if(unit)
            deep.utils.up(unit, this);
        //console.log("Unit created : ", this);
        this.tests  = this.tests || {};
    }

    Unit.prototype = {
        _deep_unit_:true,
        title:"Generic tests",
        stopOnError:false,
        options:null,
        setup : function(options){
        },
        clean : function(options){
            delete this.context;
        },
        run : function(tests, options)
        {
            options = options || {};
            tests = tests || [];
            if(!tests.forEach)
                tests = [tests];

            var toTest = this.tests;
            if(toTest._deep_ocm_)
                toTest = toTest();
            //console.log("unit context : ", context);
            var functions = deep.query(toTest, "./["+tests.join(",")+"]", { resultType:"full" });
            var numberOfTests = functions.length;
            var stopOnError = this.stopOnError;
            if(typeof options.stopOnError !== 'undefined')
                stopOnError = options.stopOnError;
            if(options.verbose !== false)
            {
                if(console.group)
                    console.group("unit : "+this.title);

                console.log("\n\n**********************************************************");
                console.log("*****  lib/unit : will run : ", this.title, " *****");
                console.log("\tStop on error ? ", stopOnError );
                console.log("\tNumber of tests : ",functions.length,"\n" );
            }
            //console.log("\tContext : ",context,"\n\n" );
            var errors = [];
            var self = this, totalTime = 0;

            if(functions.length === 0)
            {
                if(options.verbose !== false)
                {
                    console.log("**********************************************************");
                    console.log("************* Nothing to do : aborting unit **************");
                    console.log("**********************************************************");
                    if(console.groupEnd)
                        console.groupEnd();
                }
                return {
                    title:self.title,
                    numberOfTests:0,
                    success:0,
                    failure:0,
                    ommited:0,
                    errors:errors,
                    valid:true,
                    time:0
                };
            }
            var results = [];
            var d = deep.when(this.setup(options));
            var closure = {};
            var applyTest = function(fn)
            {
                if(fn._deep_ocm_)
                    fn = fn();
                if(options.verbose !== false)
                    console.log("\n- unit test runned : ", fn.key);
                closure.fn = fn;
                var time = new Date().getTime();
                return deep.when(fn.value.call(self.context))
                .always(function(s,e){
                    time = new Date().getTime() - time;
                    totalTime += time;
                    if(options.verbose !== false)
                        if(e)
                            console.error("****** test failed ! ******* : ",fn.key, " error : ", e, e.report);
                        else
                            console.log("\tok !         ("+time+" ms)");
                });
            };
            var done = function(r)
            {
                results.push(r);
                if(functions.length > 0)
                    d.when(applyTest(functions.shift())).done(done).fail(fail);
            };
            var fail = function(error)
            {
                results.push(error);
                 errors.push({
                            unit:self.title,
                            test:closure.fn.key,
                            error:error
                        });
                //deep.utils.dumpError(error);
                if(!stopOnError && functions.length > 0)
                    d.when(applyTest(functions.shift())).done(done).fail(fail);
                return true;
            };
            d.always(function(){
                if(options.verbose !== false)
                {
                    console.log("\tsetup done.");
                }
            })
            .done(function(context)
            {
                self.context = context || {};

                this.when(applyTest(functions.shift()))
                .done(done)
                .fail(fail);
            })
            .always(function(s,e)
            {
                //console.log("_______________________________________________ unit test result : ",s,e);
                if(options.verbose !== false)
                {
                    console.log("\n*************", self.title, " : time ****************");

                    if(e || results.length < numberOfTests || errors.length > 0)
                        console.warn("*************",self.title," : FAILED **************");
                    else
                        console.log("*************",self.title," : PASSED **************");

                    if(errors.length > 0)
                    {
                        console.log("\n\tErrors : ");
                        console.log("\t", e || errors);
                    }

                    console.log("\n\tNumber of tests : ", numberOfTests);
                    console.log("\tsuccess : ", results.length-errors.length,"/",numberOfTests);
                    console.log("\tfailure : ", errors.length,"/",numberOfTests);
                    console.log("\tommited : ", numberOfTests-results.length,"/",numberOfTests);
                    console.log("\ttime : ", totalTime);
                }
                return self.clean();
            })
            .always(function(s,e)
            {
                if(options.verbose !== false)
                {
                    if(e)
                        console.log("error while cleanin test : ",self.title, " : ", e);
                    console.log("\n**************", self.title, " cleaned **************");
                    console.log("***********************************************************");
                    if(console.groupEnd)
                        console.groupEnd();
                }
                return {
                    title:self.title,
                    numberOfTests:numberOfTests,
                    success:results.length-errors.length,
                    failure:errors.length,
                    ommited:numberOfTests-results.length,
                    //results:results,
                    errors:errors,
                    valid:((errors.length === 0) && (results.length == numberOfTests)),
                    time:totalTime
                };
            });
            return d;
        }
    };

    Unit.run = deep.test = function(units, options){
        if(!options && units === false)
            options = units;
        if(options === false)
            options = { verbose:false };
        else
            options = options || {};
        //if(options.verbose !== false)
        //{
            console.log("\n*******************************************************************");
            console.log("*************************** Units Bunch ****************************");
        //}
        units = units || deep.coreUnits;
        var alls = [];
        if(!units.forEach)
            units = [units];
        units.forEach(function(unit){
            if(typeof unit === 'string')
                alls.push(deep.get(unit));
            else
                alls.push(unit);
        });
        var report = {
            reports:[],
            errors:[],
            numberOfUnits:units.length,
            numberOfTests:0,
            success:0,
            failure:0,
            ommited:0,
            time:0
        };
        deep.counter = { delayCount:0 };
        if(alls.length === 0)
            return deep.when(report);
        return deep.all(alls)
        .done(function(units){
            deep.context = this._context = {};
            //console.log("units loaded : ", units);
            if(options.profile)
                console.profile("bunch");
            var results = [];
            var errors = [];
            var doTest = function(unit){
                unit = new deep.Unit(unit);
                if(options.verbose !== false)
                    console.log("\n\n\n*************** Executing unit : ", unit.title);
                return deep.when(unit.run("*",options));
            };
            var startTime = new Date().getTime();

            //if(options.verbose !== false)
            if(console.time)
                console.time("bunch");
            var d = deep.when(doTest(units.shift()));
            var always = function(s,e){
                if(e)
                    report.errors.push(e);
                report.reports.push(s);
                report.success += s.success;
                report.failure += s.failure;
                report.ommited += s.ommited;
                report.numberOfTests += s.numberOfTests;
                report.errors = report.errors.concat(s.errors);
                report.time += s.time;
                results.push(s);
                if(units.length > 0)
                    d.when(doTest(units.shift())).always(always);
                return true;
            };
            return d.always(always)
            .always(function(s,e){
                if(options.profile)
                    console.profileEnd("bunch");
                report.totalTime = new Date().getTime() - startTime;
                //if(options.verbose !== false)
                //{
                    console.log("\n\n\n___________________________________________________________________");
                    console.log("\n*******************************************************************");
                    console.log("************************** Bunch time : ***************************");
                    if(console.time)
                        console.timeEnd("bunch");
                    if(e)
                        console.log("error while executings tests bunch : ", e);
                    console.log("*******************************************************************");
                    console.log("********** tests bunch arrived to end : final report : ************");
                    //console.log("\n",report,"\n");
                    console.log("\n\tErrors: ");
                    report.errors.forEach(function (e) {
                        console.log(e.unit+":"+e.test, e.error.toString());
                        if(e.error && e.error.report)
                            console.log("report : ", report.toString());

                    });
                    console.log("\tNumber of units : ", report.numberOfUnits);
                    console.log("\tNumber of tests : ", report.numberOfTests);
                    console.log("\tsuccess : ", report.success,"/",report.numberOfTests);
                    console.log("\tfailure : ", report.failure,"/",report.numberOfTests);
                    console.log("\tommited : ", report.ommited,"/",report.numberOfTests);
                    console.log("\ttime : ", report.time);
                    console.log("\ttotalTime : ", report.totalTime);
                    console.log("\tcounters : ", JSON.stringify(deep.counter, null, ' '));
                    //console.log(JSON.stringify(report, null, ' '));
                    console.log("\n*******************************************************************");
                    console.log("*******************************************************************");
                    console.log("___________________________________________________________________\n\n");
                //}
                report.counters = deep.counter;
                return report;
            });
        })
        .fail(function(error){
            console.error("deep : Unit bunch failed to load : ", error);
        });
    };

    deep.Unit = Unit;

    return Unit;
});

<|endoftext|>


<commit_before>describe("Readium.Models.ReflowablePageNumberLogic", function () {

    describe("going to pages", function () {

        beforeEach(function () {
            this.pageNumSelector = new Readium.Models.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to go to and the expected result.
            this.testGetPageNumber = function (params) {

                var selectedPageNums = this.pageNumSelector.getGotoPageNumsToDisplay(
                    params.goToPage,
                    params.twoUp, // two pages displayed?
                    params.firstPageOffset // first page offset
                    );

                return selectedPageNums;
            };
        });

        describe("1 page displayed", function () {

            it ("gets selected page number when LTR", function () {
                var pageNums = this.testGetPageNumber({ twoUp : false, firstPageOffset : false, goToPage : 1});
                expect(pageNums).toEqual([1]);
            });

            it ("gets selected page number when RTL", function () {
                var pageNums = this.testGetPageNumber({ twoUp : false, firstPageOffset : false, goToPage : 1});
                expect(pageNums).toEqual([1]);
            });
        });

        describe("2 pages displayed", function () {

            describe("LTR", function () {

                it("gets 2 page numbers; go to p, p is odd", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 1});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is odd, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 3});
                    expect(pageNums).toEqual([2, 3]);
                });

                it("gets 2 page numbers; go to p, p is even", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 2});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is even, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 2});
                    expect(pageNums).toEqual([2, 3]);
                });
            });

            describe("RTL", function () {

                it("gets 2 page numbers; go to p, p is odd", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 1});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is odd, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 3});
                    expect(pageNums).toEqual([2, 3]);
                });

                it("gets 2 page numbers; go to p, p is even", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 2});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is even, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 2});
                    expect(pageNums).toEqual([2, 3]);
                });
            });
        });
    });

    describe("getting previous page", function () {

        beforeEach(function () {
            this.pageNumSelector = new Readium.Models.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to navigate to, and the expected result.
            this.testPrevPage = function (params) {

                var selectedPageNums = this.pageNumSelector.getPrevPageNumsToDisplay(
                    params.prevPageNum,
                    params.firstPageOffset // first page offset
                    );

                return selectedPageNums;
            };
        });

        describe("LTR", function () {

            it("go to p in [p-1, p]", function () {

                var pageNums = this.testPrevPage({firstPageOffset : false, prevPageNum : 2});
                expect(pageNums).toEqual([1, 2]);
            });

            it("go to p in [p-1, p]; offset", function () {

                var pageNums = this.testPrevPage({firstPageOffset : true, prevPageNum : 3});
                expect(pageNums).toEqual([2, 3]);
            });
        });

        describe("RTL", function () {

            it("go to p in [p, p-1]", function () {

                var pageNums = this.testPrevPage({firstPageOffset : false, prevPageNum : 2});
                expect(pageNums).toEqual([1, 2]);
            });

            it("go to p in [p, p-1]; offset", function () {

                var pageNums = this.testPrevPage({firstPageOffset : true, prevPageNum : 3});
                expect(pageNums).toEqual([2, 3]);
            });
        });
    });

    describe("getting next page", function () {

        beforeEach(function () {
            this.pageNumSelector = new Readium.Models.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to navigate to, and the expected result.
            this.testNextPage = function (params) {

                var selectedPageNums = this.pageNumSelector.getNextPageNumsToDisplay(
                    params.prevPageNum,
                    params.firstPageOffset // first page offset
                    );

                return selectedPageNums;
            };
        });

        describe("LTR", function () {

            it("go to p in [p, p+1]", function () {

                var pageNums = this.testNextPage({firstPageOffset : false, prevPageNum : 3});
                expect(pageNums).toEqual([3, 4]);
            });

            it("go to p in [p, p+1]; offset", function () {

                var pageNums = this.testNextPage({firstPageOffset : true, prevPageNum : 2});
                expect(pageNums).toEqual([2, 3]);
            });
        });

        describe("RTL", function () {

            it("go to p in [p+1, p]", function () {

                var pageNums = this.testNextPage({firstPageOffset : false, prevPageNum : 3});
                expect(pageNums).toEqual([3, 4]);
            });

            it("go to p in [p+1, p]; offset", function () {

                var pageNums = this.testNextPage({firstPageOffset : true, prevPageNum : 2});
                expect(pageNums).toEqual([2, 3]);
            });
        });
    });

    describe("toggling two-up pages", function () {

        beforeEach(function () {
            this.pageNumSelector = new Readium.Models.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to navigate to, and the expected result.
            this.testGotoPageNums = function (params) {

                var selectedPageNums = this.pageNumSelector.getPageNumbersForTwoUp(
                    params.twoUp,
                    params.current_pages, // the pages currently displayed
                    params.firstPageOffset // first page is offset
                    );

                return selectedPageNums;
            };
        });

        describe("2 pages up", function () {

            describe("LTR", function () {

                it("gets 1 page number", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [1, 2]});
                    expect(pageNums).toEqual([1]);
                });

                it("gets 1 page number at page num boundary", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [0, 1]});
                    expect(pageNums).toEqual([1]);
                });
            });

            describe("RTL", function () {

                it("gets 1 page number", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [1, 2]});
                    expect(pageNums).toEqual([1]);
                });

                it("gets 1 page number at page num boundary", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [0, 1]});
                    expect(pageNums).toEqual([1]);
                });
            });
        });

        describe("1 page up", function () {

            it("gets 2 page numbers; odd page", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : false, current_pages : [1]});
                expect(pageNums).toEqual([1, 2]);
            });

            it("gets 2 page numbers; odd page, offset", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : true, current_pages : [3]});
                expect(pageNums).toEqual([2, 3]);
            });

            it("gets 2 page numbers; even page", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : false, current_pages : [2]});
                expect(pageNums).toEqual([1, 2]);
            });

            it("gets 2 page numbers; even page, offset", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : true, current_pages : [2]});
                expect(pageNums).toEqual([2, 3]);
            });
        });
    });
});<commit_msg>Updated the reflowable page number logic spec<commit_after>describe("EpubReflowable.ReflowablePageNumberLogic", function () {

    describe("getGotoPageNumsToDisplay()", function () {

        beforeEach(function () {
            this.pageNumSelector = new EpubReflowable.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to go to and the expected result.
            this.testGetPageNumber = function (params) {

                var selectedPageNums = this.pageNumSelector.getGotoPageNumsToDisplay(
                    params.goToPage,
                    params.twoUp, // two pages displayed?
                    params.firstPageOffset // first page offset
                    );

                return selectedPageNums;
            };
        });

        describe("1 page displayed", function () {

            it ("gets selected page number when LTR", function () {
                var pageNums = this.testGetPageNumber({ twoUp : false, firstPageOffset : false, goToPage : 1});
                expect(pageNums).toEqual([1]);
            });

            it ("gets selected page number when RTL", function () {
                var pageNums = this.testGetPageNumber({ twoUp : false, firstPageOffset : false, goToPage : 1});
                expect(pageNums).toEqual([1]);
            });
        });

        describe("2 pages displayed", function () {

            describe("LTR", function () {

                it("gets 2 page numbers; go to p, p is odd", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 1});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is odd, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 3});
                    expect(pageNums).toEqual([2, 3]);
                });

                it("gets 2 page numbers; go to p, p is even", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 2});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is even, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 2});
                    expect(pageNums).toEqual([2, 3]);
                });
            });

            describe("RTL", function () {

                it("gets 2 page numbers; go to p, p is odd", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 1});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is odd, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 3});
                    expect(pageNums).toEqual([2, 3]);
                });

                it("gets 2 page numbers; go to p, p is even", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : false, goToPage : 2});
                    expect(pageNums).toEqual([1, 2]);
                });

                it("gets 2 page numbers; go to p, p is even, offset", function () {
                    var pageNums = this.testGetPageNumber({ twoUp : true, firstPageOffset : true, goToPage : 2});
                    expect(pageNums).toEqual([2, 3]);
                });
            });
        });
    });

    describe("getPrevPageNumsToDisplay()", function () {

        beforeEach(function () {
            this.pageNumSelector = new EpubReflowable.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to navigate to, and the expected result.
            this.testPrevPage = function (params) {

                var selectedPageNums = this.pageNumSelector.getPrevPageNumsToDisplay(
                    params.prevPageNum,
                    params.firstPageOffset // first page offset
                    );

                return selectedPageNums;
            };
        });

        describe("LTR", function () {

            it("go to p in [p-1, p]", function () {

                var pageNums = this.testPrevPage({firstPageOffset : false, prevPageNum : 2});
                expect(pageNums).toEqual([1, 2]);
            });

            it("go to p in [p-1, p]; offset", function () {

                var pageNums = this.testPrevPage({firstPageOffset : true, prevPageNum : 3});
                expect(pageNums).toEqual([2, 3]);
            });
        });

        describe("RTL", function () {

            it("go to p in [p, p-1]", function () {

                var pageNums = this.testPrevPage({firstPageOffset : false, prevPageNum : 2});
                expect(pageNums).toEqual([1, 2]);
            });

            it("go to p in [p, p-1]; offset", function () {

                var pageNums = this.testPrevPage({firstPageOffset : true, prevPageNum : 3});
                expect(pageNums).toEqual([2, 3]);
            });
        });
    });

    describe("getNextPageNumsToDisplay()", function () {

        beforeEach(function () {
            this.pageNumSelector = new EpubReflowable.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to navigate to, and the expected result.
            this.testNextPage = function (params) {

                var selectedPageNums = this.pageNumSelector.getNextPageNumsToDisplay(
                    params.prevPageNum,
                    params.firstPageOffset // first page offset
                    );

                return selectedPageNums;
            };
        });

        describe("LTR", function () {

            it("go to p in [p, p+1]", function () {

                var pageNums = this.testNextPage({firstPageOffset : false, prevPageNum : 3});
                expect(pageNums).toEqual([3, 4]);
            });

            it("go to p in [p, p+1]; offset", function () {

                var pageNums = this.testNextPage({firstPageOffset : true, prevPageNum : 2});
                expect(pageNums).toEqual([2, 3]);
            });
        });

        describe("RTL", function () {

            it("go to p in [p+1, p]", function () {

                var pageNums = this.testNextPage({firstPageOffset : false, prevPageNum : 3});
                expect(pageNums).toEqual([3, 4]);
            });

            it("go to p in [p+1, p]; offset", function () {

                var pageNums = this.testNextPage({firstPageOffset : true, prevPageNum : 2});
                expect(pageNums).toEqual([2, 3]);
            });
        });
    });

    describe("getPageNumsForTwoUp()", function () {

        beforeEach(function () {
            this.pageNumSelector = new EpubReflowable.ReflowablePageNumberLogic();

            // Rationale: This function will make these sets of repetitive tests clearer - as in, the conditions of the
            //   EPUB, the page to navigate to, and the expected result.
            this.testGotoPageNums = function (params) {

                var selectedPageNums = this.pageNumSelector.getPageNumbersForTwoUp(
                    params.twoUp,
                    params.current_pages, // the pages currently displayed
                    params.firstPageOffset // first page is offset
                    );

                return selectedPageNums;
            };
        });

        describe("2 pages up", function () {

            describe("LTR", function () {

                it("gets 1 page number", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [1, 2]});
                    expect(pageNums).toEqual([1]);
                });

                it("gets 1 page number at page num boundary", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [0, 1]});
                    expect(pageNums).toEqual([1]);
                });
            });

            describe("RTL", function () {

                it("gets 1 page number", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [1, 2]});
                    expect(pageNums).toEqual([1]);
                });

                it("gets 1 page number at page num boundary", function () {

                    var pageNums = this.testGotoPageNums({twoUp : true, firstPageOffset : false, current_pages : [0, 1]});
                    expect(pageNums).toEqual([1]);
                });
            });
        });

        describe("1 page up", function () {

            it("gets 2 page numbers; odd page", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : false, current_pages : [1]});
                expect(pageNums).toEqual([1, 2]);
            });

            it("gets 2 page numbers; odd page, offset", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : true, current_pages : [3]});
                expect(pageNums).toEqual([2, 3]);
            });

            it("gets 2 page numbers; even page", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : false, current_pages : [2]});
                expect(pageNums).toEqual([1, 2]);
            });

            it("gets 2 page numbers; even page, offset", function () {

                var pageNums = this.testGotoPageNums({twoUp : false, firstPageOffset : true, current_pages : [2]});
                expect(pageNums).toEqual([2, 3]);
            });
        });
    });
});<|endoftext|>


<commit_before>'use strict';

var readabilityCallback = function(dataRdb, target) {
  if (dataRdb.readability === undefined) {
    return;
  }

  var htmlRdb =
    '
' +
    '
Readability
' +
    '

' +
    '
' +
    kconnect.config.difficultyKeyword[dataRdb.readability.difficulty] +
    '

';

  if (target.find('.readability').length === 0) {
    target.append(htmlRdb);
  }
};

var trustabilityCallback = function(data, target, link) {
  if (data.trustability === undefined) {
    return;
  }
  var trustClass;
  var trustabilityLevel =
    Math.round((data.trustability.principles.length / 9) * 100);

  target.siblings('.certificateLink').hasClass('valid') ?
    trustClass = 'honTrust' : trustClass =  'circle';

  var html =
    '
' +
    '
Trustability
' +
    '
' +
    '' +
    '' +
    '
' +
    '
';

  if (target.find('.trustability').length === 0) {
    var progress = new CircularProgress({
      radius: 25,
      strokeStyle: 'limegreen',
      lineCap: 'round',
      lineWidth: 3,
    });
    target.append(html);
    kconnect.contentHONcodeStatus(target.find('.honTrust'), link);

    target.find('.circle').html(progress.el);
    progress.update(trustabilityLevel);
  }
};

var updateLinks = function() {
  var deferred = new $.Deferred();

  // Get links
  var links = [];
  var hrefSelector = '';
  var targetSelector = '';
  var trustabilityRequested = 0;
  // Match Google
  if (window.location.host.indexOf('google') > -1) {
    hrefSelector = 'h3.r a';
    targetSelector = '.s';
  }
  // Match Yahoo
  else if (window.location.host.indexOf('yahoo') > -1) {
    hrefSelector = 'div.compTitle h3.title a';
    targetSelector = 'div:first';
  }
  // Match Bing
  else if (window.location.host.indexOf('bing') > -1) {
    hrefSelector = 'li.b_algo h2 a';
    targetSelector = 'div.b_caption';
  }
  var nodeList = document.querySelectorAll(hrefSelector);
  for (var i = 0; i < nodeList.length; ++i) {
    links[i] = nodeList[i].href;
  }
  links.forEach(function(link, index) {
    var $layerId;
    var $logoId;

    var honLogo = $(nodeList.item(index)).parent();
    var domain = kconnect.getDomainFromUrl(link);

    var trustabilityRequest = kconnect.getIsTrustable(domain);
    var readabilityRequest = kconnect.getReadability(link);

    var layerId = 'honLayer_' + index;
    var logoId = 'honLogo_' + index;

    var honCodeLogo = '

';
    var popUp = '
' +
      '
' + domain + '
' +
      '
';

    if (honLogo.children('.certificateLink').length === 0) {
      // Normalize Search Engine parents' behaviors
      honLogo.parent().css('overflow','visible');
      honLogo.parent().css('position','relative');
      honLogo.prepend(honCodeLogo + popUp);
      kconnect.contentHONcodeStatus(honLogo.children('.certificateLink'), link);
    }

    $layerId =  $('#' + layerId);
    $logoId =  $('#' + logoId);

    $.when(trustabilityRequest, readabilityRequest)
      .then(function(trustabilityResponse, readabilityResponse) {
        readabilityCallback(readabilityResponse[0], $layerId);
        trustabilityCallback(trustabilityResponse[0], $layerId, link);

        var timeoutId;
        var hideTimeoutId;

        // Add honLogo eventListener
        $logoId.hover(function() {
          if (!timeoutId) {
            timeoutId = window.setTimeout(function() {
              timeoutId = null;
              $layerId.show();
            }, 200);
          }
        }, function() {
          if (timeoutId) {
            window.clearTimeout(timeoutId);
            timeoutId = null;
          }
        });

        $layerId.hover(function() {
          if (hideTimeoutId) {
            window.clearTimeout(hideTimeoutId);
            hideTimeoutId = null;
          }
        }, function() {
          if (!hideTimeoutId) {
            hideTimeoutId = window.setTimeout(function() {
              hideTimeoutId = null;
              $layerId.hide();
            }, 200);
          }
        });
      })
      .always(function() {
        trustabilityRequested++;
        if (trustabilityRequested === links.length) {
          deferred.resolve();
        }
      });
  });

  return deferred.promise();
};

updateLinks().done(function() {});
<commit_msg>clean<commit_after>'use strict';

var readabilityCallback = function(dataRdb, target) {
  if (dataRdb.readability === undefined) {
    return;
  }

  var htmlRdb =
    '
' +
    '
Readability
' +
    '

' +
    '
' +
    kconnect.config.difficultyKeyword[dataRdb.readability.difficulty] +
    '

';

  if (target.find('.readability').length === 0) {
    target.append(htmlRdb);
  }
};

var trustabilityCallback = function(data, target, link) {
  if (data.trustability === undefined) {
    return;
  }
  var trustClass;
  var trustabilityLevel =
    Math.round((data.trustability.principles.length / 9) * 100);

  target.siblings('.certificateLink').hasClass('valid') ?
    trustClass = 'honTrust' : trustClass =  'circle';

  var html =
    '
' +
    '
Trustability
' +
    '
' +
    '' +
    '

';

  if (target.find('.trustability').length === 0) {
    var progress = new CircularProgress({
      radius: 25,
      strokeStyle: 'limegreen',
      lineCap: 'round',
      lineWidth: 3,
    });
    target.append(html);
    kconnect.contentHONcodeStatus(target.find('.honTrust'), link);

    target.find('.circle').html(progress.el);
    progress.update(trustabilityLevel);
  }
};

var updateLinks = function() {
  var deferred = new $.Deferred();

  // Get links
  var links = [];
  var hrefSelector = '';
  var trustabilityRequested = 0;
  // Match Google
  if (window.location.host.indexOf('google') > -1) {
    hrefSelector = 'h3.r a';
  }
  // Match Yahoo
  else if (window.location.host.indexOf('yahoo') > -1) {
    hrefSelector = 'div.compTitle h3.title a';
  }
  // Match Bing
  else if (window.location.host.indexOf('bing') > -1) {
    hrefSelector = 'li.b_algo h2 a';
  }
  var nodeList = document.querySelectorAll(hrefSelector);
  for (var i = 0; i < nodeList.length; ++i) {
    links[i] = nodeList[i].href;
  }
  links.forEach(function(link, index) {
    var $layerId;
    var $logoId;

    var honLogo = $(nodeList.item(index)).parent();
    var domain = kconnect.getDomainFromUrl(link);

    var trustabilityRequest = kconnect.getIsTrustable(domain);
    var readabilityRequest = kconnect.getReadability(link);

    var layerId = 'honLayer_' + index;
    var logoId = 'honLogo_' + index;

    var honCodeLogo = '

';
    var popUp = '
' +
      '
' + domain + '
' +
      '
';

    if (honLogo.children('.certificateLink').length === 0) {
      // Normalize Search Engine parents' behaviors
      honLogo.parent().css('overflow','visible');
      honLogo.parent().css('position','relative');
      honLogo.prepend(honCodeLogo + popUp);
      kconnect.contentHONcodeStatus(honLogo.children('.certificateLink'), link);
    }

    $layerId =  $('#' + layerId);
    $logoId =  $('#' + logoId);

    $.when(trustabilityRequest, readabilityRequest)
      .then(function(trustabilityResponse, readabilityResponse) {
        readabilityCallback(readabilityResponse[0], $layerId);
        trustabilityCallback(trustabilityResponse[0], $layerId, link);

        var timeoutId;
        var hideTimeoutId;

        // Add honLogo eventListener
        $logoId.hover(function() {
          if (!timeoutId) {
            timeoutId = window.setTimeout(function() {
              timeoutId = null;
              $layerId.show();
            }, 200);
          }
        }, function() {
          if (timeoutId) {
            window.clearTimeout(timeoutId);
            timeoutId = null;
          }
        });

        $layerId.hover(function() {
          if (hideTimeoutId) {
            window.clearTimeout(hideTimeoutId);
            hideTimeoutId = null;
          }
        }, function() {
          if (!hideTimeoutId) {
            hideTimeoutId = window.setTimeout(function() {
              hideTimeoutId = null;
              $layerId.hide();
            }, 200);
          }
        });
      })
      .always(function() {
        trustabilityRequested++;
        if (trustabilityRequested === links.length) {
          deferred.resolve();
        }
      });
  });

  return deferred.promise();
};

updateLinks().done(function() {});
<|endoftext|>