<commit_before>var async = require('async');
var api2HTML = require('./to_html');
var api2JSON = require('../origin/tools/json');
var utils = require('./utils');
var config = require('../config');
var db = config.mysql;

module.exports = function (app) {

  // 网站首页
  app.get('/', function (req, res, next) {
    req.url = '/public/index.html';
    app(req, res);
  });

  // 浏览指定API页面
  app.get('/api/:name.:type', function (req, res, next) {
    var name = req.params.name;
    var type = req.params.type;

    utils.readAPIFile(name, function (err, content, filename) {
      if (err) return next(err);
      if (type === 'html') {
        api2HTML(content, filename, utils.TEMPLATE_FILE, function (err, html) {
          if (err) return next(err);
          res.writeHead(200, {'content-type': 'text/html'});
          res.end(html);
        });
      } else {
        api2JSON(content, filename, function (err, data) {
          if (err) return next(err);
          res.json(data);
        })
      }
    });
  });

  // API首页
  app.get('/api', function (req, res, next) {
    req.url = '/api/index.html';
    app(req, res);
  });

  // 翻译进度
  app.get('/progress', function (req, res, next) {
    // 查询出所有的文件名
    db.select('origin_api', 'file', '`version`=' + db.escape(config.api.version), 'GROUP BY `file`', function (err, files) {
      if (err) return next(err);
      files = files.map(function (f) {
        return f.file;
      });

      // 分别获取每个文件的翻译进度
      var results = [];
      var userIds = {};
      async.eachSeries(files, function (f, next) {

        var sql = 'SELECT `A`.`hash`,`B`.`user_id`' +
                  ' FROM `origin_api` AS `A`' +
                  ' LEFT JOIN `translate_api` AS `B`' +
                  ' ON `A`.`hash`=`B`.`origin_hash`' +
                  ' WHERE `file`=' + db.escape(f) +
                  ' GROUP BY `A`.`hash`';
        db.query(sql, function (err, list) {
          if (err) return next(err);

          var lines = {};
          var users = {};
          list.forEach(function (line) {
            var uid = line.user_id;
            var hash = line.hash;
            if (uid > 0) {
              userIds[uid] = true;
              // 记录用户翻译的数量
              if (uid in users) {
                users[uid]++
              } else {
                users[uid] = 1;
              }
              // 记录已经完成的数量
              if (hash in lines) {
                lines[hash]++;
              } else {
                lines[hash] = 1;
              }
            } else {
              lines[hash] = 0;
            }
          });

          var count = 0;
          var finish = 0;
          for (var i in lines) {
            count++;
            if (lines[i] > 0) finish++;
          }

          // 用户按照翻译数量排序
          var userList = [];
          for (var i in users) {
            userList.push({
              user_id: i,
              count:   users[i]
            });
          }
          userList.sort(function (a, b) {
            return b.count - a.count;
          });

          results.push({
            name:    f,
            count:   count,
            finish:  finish,
            percent: finish / count,
            users:   userList
          });

          next();
        });

      }, function (err) {
        if (err) return next(err);

        // 获取相关用户信息
        var users = {};
        async.eachSeries(Object.keys(userIds), function (uid, next) {

          db.selectOne('user_list', '`id`,`nickname`', '`id`=' + db.escape(uid), function (err, user) {
            if (err) return next(err);
            if (!user) user = {id: 0, nickname: '该用户不存在'};
            users[uid] = user;
            next();
          });

        }, function (err) {
          if (err) return next(err);

          // 按照完成量排序
          results.sort(function (a, b) {
            return b.percent - a.percent;
          });

          res.locals.files = results;
          res.locals.users = users;
          res.render('progress');
        });
      });
    });
  });

};
<commit_msg>修正完成进度页面<commit_after>var async = require('async');
var api2HTML = require('./to_html');
var api2JSON = require('../origin/tools/json');
var utils = require('./utils');
var config = require('../config');
var db = config.mysql;

module.exports = function (app) {

  // 网站首页
  app.get('/', function (req, res, next) {
    req.url = '/public/index.html';
    app(req, res);
  });

  // 浏览指定API页面
  app.get('/api/:name.:type', function (req, res, next) {
    var name = req.params.name;
    var type = req.params.type;

    utils.readAPIFile(name, function (err, content, filename) {
      if (err) return next(err);
      if (type === 'html') {
        api2HTML(content, filename, utils.TEMPLATE_FILE, function (err, html) {
          if (err) return next(err);
          res.writeHead(200, {'content-type': 'text/html'});
          res.end(html);
        });
      } else {
        api2JSON(content, filename, function (err, data) {
          if (err) return next(err);
          res.json(data);
        })
      }
    });
  });

  // API首页
  app.get('/api', function (req, res, next) {
    req.url = '/api/index.html';
    app(req, res);
  });

  // 翻译进度
  app.get('/progress', function (req, res, next) {
    // 查询出所有的文件名
    db.select('origin_api', 'file', '`version`=' + db.escape(config.api.version), 'GROUP BY `file`', function (err, files) {
      if (err) return next(err);
      files = files.map(function (f) {
        return f.file;
      });

      // 分别获取每个文件的翻译进度
      var results = [];
      var userIds = {};
      async.eachSeries(files, function (f, next) {

        var sql = 'SELECT `A`.`hash`,`B`.`user_id`' +
                  ' FROM `origin_api` AS `A`' +
                  ' LEFT JOIN `translate_api` AS `B`' +
                  ' ON `A`.`hash`=`B`.`origin_hash`' +
                  ' WHERE `file`=' + db.escape(f) +
                  ' AND `type`!="meta"' +
                  ' AND `version`=' + db.escape(config.api.version) +
                  ' GROUP BY `A`.`hash`';
        db.query(sql, function (err, list) {
          if (err) return next(err);

          var lines = {};
          var users = {};
          list.forEach(function (line) {
            var uid = line.user_id;
            var hash = line.hash;
            if (uid > 0) {
              userIds[uid] = true;
              // 记录用户翻译的数量
              if (uid in users) {
                users[uid]++
              } else {
                users[uid] = 1;
              }
              // 记录已经完成的数量
              if (hash in lines) {
                lines[hash]++;
              } else {
                lines[hash] = 1;
              }
            } else {
              lines[hash] = 0;
            }
          });

          var count = 0;
          var finish = 0;
          for (var i in lines) {
            count++;
            if (lines[i] > 0) finish++;
          }

          // 用户按照翻译数量排序
          var userList = [];
          for (var i in users) {
            userList.push({
              user_id: i,
              count:   users[i]
            });
          }
          userList.sort(function (a, b) {
            return b.count - a.count;
          });

          results.push({
            name:    f,
            count:   count,
            finish:  finish,
            percent: finish / count,
            users:   userList
          });

          next();
        });

      }, function (err) {
        if (err) return next(err);

        // 获取相关用户信息
        var users = {};
        async.eachSeries(Object.keys(userIds), function (uid, next) {

          db.selectOne('user_list', '`id`,`nickname`', '`id`=' + db.escape(uid), function (err, user) {
            if (err) return next(err);
            if (!user) user = {id: 0, nickname: '该用户不存在'};
            users[uid] = user;
            next();
          });

        }, function (err) {
          if (err) return next(err);

          // 按照完成量排序
          results.sort(function (a, b) {
            return b.percent - a.percent;
          });

          res.locals.files = results;
          res.locals.users = users;
          res.render('progress');
        });
      });
    });
  });

};
<|endoftext|>


<commit_before>import { Point } from "./point.js";
import { Range } from "./range.js";
import { Focus } from "./focus.js";

/**
 * A `Table` object represents a table.
 */
export class Table {
  /**
   * Creates a new `Table` object.
   *
   * @param {Array<TableRow>} rows - An array of rows that the table contains.
   */
  constructor(rows) {
    /** @private */
    this._rows = rows.slice();
  }

  /**
   * Gets the number of rows in the table.
   *
   * @returns {number} The number of rows.
   */
  getHeight() {
    return this._rows.length;
  }

  /**
   * Gets the maximum width of the rows in the table.
   *
   * @returns {number} The maximum width of the rows.
   */
  getWidth() {
    return this._rows.map(row => row.getWidth())
      .reduce((x, y) => Math.max(x, y), 0);
  }

  /**
   * Gets the width of the header row.
   *
   * @returns {number|undefined} The width of the header row;
   * `undefined` if there is no header row.
   */
  getHeaderWidth() {
    if (this._rows.length === 0) {
      return undefined;
    }
    return this._rows[0].getWidth();
  }

  /**
   * Get the rows that the table contains.
   *
   * @returns {Array<TableRow>} An array of the rows.
   */
  getRows() {
    return this._rows.slice();
  }

  /**
   * Gets a row at the specified index.
   *
   * @param {number} index - Row index.
   * @returns {TableRow|undefined} The row at the specified index;
   * `undefined` if not found.
   */
  getRowAt(index) {
    return this._rows[index];
  }

  /**
   * Gets the delimiter row of the table.
   *
   * @returns {TableRow|undefined} The delimiter row;
   * `undefined` if there is not delimiter row.
   */
  getDelimiterRow() {
    const row = this._rows[1];
    if (row === undefined) {
      return undefined;
    }
    if (row.isDelimiter()) {
      return row;
    }
    else {
      return undefined;
    }
  }

  /**
   * Get the cell at the specified index.
   *
   * @param {number} rowIndex - Row index of the cell.
   * @param {number} columnIndex - Column index of the cell.
   * @returns {TableCell|undefined} The cell at the specified index;
   * `undefined` if not found.
   */
  getCellAt(rowIndex, columnIndex) {
    const row = this._rows[rowIndex];
    if (row === undefined) {
      return undefined;
    }
    return row.getCellAt(columnIndex);
  }

  /**
   * Get the cell at the focus.
   *
   * @param {Focus} focus - Focus object.
   * @returns {TableCell|undefined} The cell at the focus;
   * `undefined` if not found.
   */
  getFocusedCell(focus) {
    return this.getCellAt(focus.row, focus.column);
  }

  /**
   * Converts the table to a text representation.
   *
   * @returns {string} A text representation of the table.
   */
  toText() {
    return this._rows.map(row => row.toText()).join("\n");
  }

  /**
   * Computes a focus from a point in the text editor.
   *
   * @param {Point} pos - A point in the text editor.
   * @param {number} rowOffset - The row index where the table starts in the text editor.
   * @returns {Focus|undefined} A focus object that corresponds to the specified point;
   * `undefined` if the row index is out of bounds.
   */
  computeFocus(pos, rowOffset) {
    const rowIndex = pos.row - rowOffset;
    const row = this._rows[rowIndex];
    if (row === undefined) {
      return undefined;
    }
    if (pos.column < row.marginLeft.length + 1) {
      return new Focus(rowIndex, -1, pos.column);
    }
    else {
      const cellWidths = row.getCells().map(cell => cell.rawContent.length);
      let columnPos = row.marginLeft.length + 1; // left margin + a pipe
      let columnIndex = 0;
      for (; columnIndex < cellWidths.length; columnIndex++) {
        if (columnPos + cellWidths[columnIndex] + 1 > pos.column) {
          break;
        }
        columnPos += cellWidths[columnIndex] + 1;
      }
      const offset = pos.column - columnPos;
      return new Focus(rowIndex, columnIndex, offset);
    }
  }

  /**
   * Computes a position in the text editor from a focus.
   *
   * @param {Focus} focus - A focus object.
   * @param {number} rowOffset - The row index where the table starts in the text editor.
   * @returns {Point|undefined} A position in the text editor that corresponds to the focus;
   * `undefined` if the focus is out of the table.
   */
  computePosition(focus, rowOffset) {
    const row = this._rows[focus.row];
    if (row === undefined) {
      return undefined;
    }
    const rowPos = focus.row + rowOffset;
    if (focus.column < 0) {
      return new Point(rowPos, focus.offset);
    }
    const cellWidths = row.getCells().map(cell => cell.rawContent.length);
    const maxIndex = Math.min(focus.column, cellWidths.length);
    let columnPos = row.marginLeft.length + 1;
    for (let columnIndex = 0; columnIndex < maxIndex; columnIndex++) {
      columnPos += cellWidths[columnIndex] + 1;
    }
    return new Point(rowPos, columnPos + focus.offset);
  }

  /**
   * Computes a selection range from a focus.
   *
   * @param {Focus} focus - A focus object.
   * @param {number} rowOffset - The row index where the table starts in the text editor.
   * @returns {Range|undefined} A range to be selected that corresponds to the focus;
   * `undefined` if the focus does not specify any cell or the specified cell is empty.
   */
  computeSelectionRange(focus, rowOffset) {
    const row = this._rows[focus.row];
    if (row === undefined) {
      return undefined;
    }
    const cell = row.getCellAt(focus.column);
    if (cell === undefined) {
      return undefined;
    }
    if (cell.content === "") {
      return undefined;
    }
    const rowPos = focus.row + rowOffset;
    const cellWidths = row.getCells().map(cell => cell.rawContent.length);
    let columnPos = row.marginLeft.length + 1;
    for (let columnIndex = 0; columnIndex < focus.column; columnIndex++) {
      columnPos += cellWidths[columnIndex] + 1;
    }
    columnPos += cell.paddingLeft;
    return new Range(
      new Point(rowPos, columnPos),
      new Point(rowPos, columnPos + cell.content.length)
    );
  }
}
<commit_msg>Fix typos<commit_after>import { Point } from "./point.js";
import { Range } from "./range.js";
import { Focus } from "./focus.js";

/**
 * A `Table` object represents a table.
 */
export class Table {
  /**
   * Creates a new `Table` object.
   *
   * @param {Array<TableRow>} rows - An array of rows that the table contains.
   */
  constructor(rows) {
    /** @private */
    this._rows = rows.slice();
  }

  /**
   * Gets the number of rows in the table.
   *
   * @returns {number} The number of rows.
   */
  getHeight() {
    return this._rows.length;
  }

  /**
   * Gets the maximum width of the rows in the table.
   *
   * @returns {number} The maximum width of the rows.
   */
  getWidth() {
    return this._rows.map(row => row.getWidth())
      .reduce((x, y) => Math.max(x, y), 0);
  }

  /**
   * Gets the width of the header row.
   *
   * @returns {number|undefined} The width of the header row;
   * `undefined` if there is no header row.
   */
  getHeaderWidth() {
    if (this._rows.length === 0) {
      return undefined;
    }
    return this._rows[0].getWidth();
  }

  /**
   * Gets the rows that the table contains.
   *
   * @returns {Array<TableRow>} An array of the rows.
   */
  getRows() {
    return this._rows.slice();
  }

  /**
   * Gets a row at the specified index.
   *
   * @param {number} index - Row index.
   * @returns {TableRow|undefined} The row at the specified index;
   * `undefined` if not found.
   */
  getRowAt(index) {
    return this._rows[index];
  }

  /**
   * Gets the delimiter row of the table.
   *
   * @returns {TableRow|undefined} The delimiter row;
   * `undefined` if there is not delimiter row.
   */
  getDelimiterRow() {
    const row = this._rows[1];
    if (row === undefined) {
      return undefined;
    }
    if (row.isDelimiter()) {
      return row;
    }
    else {
      return undefined;
    }
  }

  /**
   * Gets a cell at the specified index.
   *
   * @param {number} rowIndex - Row index of the cell.
   * @param {number} columnIndex - Column index of the cell.
   * @returns {TableCell|undefined} The cell at the specified index;
   * `undefined` if not found.
   */
  getCellAt(rowIndex, columnIndex) {
    const row = this._rows[rowIndex];
    if (row === undefined) {
      return undefined;
    }
    return row.getCellAt(columnIndex);
  }

  /**
   * Gets the cell at the focus.
   *
   * @param {Focus} focus - Focus object.
   * @returns {TableCell|undefined} The cell at the focus;
   * `undefined` if not found.
   */
  getFocusedCell(focus) {
    return this.getCellAt(focus.row, focus.column);
  }

  /**
   * Converts the table to a text representation.
   *
   * @returns {string} A text representation of the table.
   */
  toText() {
    return this._rows.map(row => row.toText()).join("\n");
  }

  /**
   * Computes a focus from a point in the text editor.
   *
   * @param {Point} pos - A point in the text editor.
   * @param {number} rowOffset - The row index where the table starts in the text editor.
   * @returns {Focus|undefined} A focus object that corresponds to the specified point;
   * `undefined` if the row index is out of bounds.
   */
  computeFocus(pos, rowOffset) {
    const rowIndex = pos.row - rowOffset;
    const row = this._rows[rowIndex];
    if (row === undefined) {
      return undefined;
    }
    if (pos.column < row.marginLeft.length + 1) {
      return new Focus(rowIndex, -1, pos.column);
    }
    else {
      const cellWidths = row.getCells().map(cell => cell.rawContent.length);
      let columnPos = row.marginLeft.length + 1; // left margin + a pipe
      let columnIndex = 0;
      for (; columnIndex < cellWidths.length; columnIndex++) {
        if (columnPos + cellWidths[columnIndex] + 1 > pos.column) {
          break;
        }
        columnPos += cellWidths[columnIndex] + 1;
      }
      const offset = pos.column - columnPos;
      return new Focus(rowIndex, columnIndex, offset);
    }
  }

  /**
   * Computes a position in the text editor from a focus.
   *
   * @param {Focus} focus - A focus object.
   * @param {number} rowOffset - The row index where the table starts in the text editor.
   * @returns {Point|undefined} A position in the text editor that corresponds to the focus;
   * `undefined` if the focus is out of the table.
   */
  computePosition(focus, rowOffset) {
    const row = this._rows[focus.row];
    if (row === undefined) {
      return undefined;
    }
    const rowPos = focus.row + rowOffset;
    if (focus.column < 0) {
      return new Point(rowPos, focus.offset);
    }
    const cellWidths = row.getCells().map(cell => cell.rawContent.length);
    const maxIndex = Math.min(focus.column, cellWidths.length);
    let columnPos = row.marginLeft.length + 1;
    for (let columnIndex = 0; columnIndex < maxIndex; columnIndex++) {
      columnPos += cellWidths[columnIndex] + 1;
    }
    return new Point(rowPos, columnPos + focus.offset);
  }

  /**
   * Computes a selection range from a focus.
   *
   * @param {Focus} focus - A focus object.
   * @param {number} rowOffset - The row index where the table starts in the text editor.
   * @returns {Range|undefined} A range to be selected that corresponds to the focus;
   * `undefined` if the focus does not specify any cell or the specified cell is empty.
   */
  computeSelectionRange(focus, rowOffset) {
    const row = this._rows[focus.row];
    if (row === undefined) {
      return undefined;
    }
    const cell = row.getCellAt(focus.column);
    if (cell === undefined) {
      return undefined;
    }
    if (cell.content === "") {
      return undefined;
    }
    const rowPos = focus.row + rowOffset;
    const cellWidths = row.getCells().map(cell => cell.rawContent.length);
    let columnPos = row.marginLeft.length + 1;
    for (let columnIndex = 0; columnIndex < focus.column; columnIndex++) {
      columnPos += cellWidths[columnIndex] + 1;
    }
    columnPos += cell.paddingLeft;
    return new Range(
      new Point(rowPos, columnPos),
      new Point(rowPos, columnPos + cell.content.length)
    );
  }
}
<|endoftext|>


<commit_before>
/**
 * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
 * This file is licensed under the Affero General Public License version 3 or later.
 * See the COPYING-README file.
 */

OCA = OCA || {};

(function() {

	/**
	 * @classdesc This class represents the view belonging to the server tab
	 * in the LDAP wizard.
	 */
	var WizardTabElementary = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
		/**
		 * initializes the instance. Always call it after initialization.
		 *
		 * @param tabIndex
		 * @param tabID
		 */
		init: function (tabIndex, tabID) {
			tabIndex = 0;
			this._super(tabIndex, tabID);
			this.isActive = true;
			this.configChooserID = '#ldap_serverconfig_chooser';

			var items = {
				ldap_host: {
					$element: $('#ldap_host'),
					setMethod: 'setHost'
				},
				ldap_port: {
					$element: $('#ldap_port'),
					setMethod: 'setPort',
					$relatedElements: $('.ldapDetectPort')
				},
				ldap_dn: {
					$element: $('#ldap_dn'),
					setMethod: 'setAgentDN'
				},
				ldap_agent_password: {
					$element: $('#ldap_agent_password'),
					setMethod: 'setAgentPwd'
				},
				ldap_base: {
					$element: $('#ldap_base'),
					setMethod: 'setBase',
					$relatedElements: $('.ldapDetectBase, .ldapTestBase'),
					$detectButton: $('.ldapDetectBase'),
					$testButton: $('.ldapTestBase')
				},
				ldap_base_test: {
					$element: $('#ldap_base')
				},
				ldap_experienced_admin: {
					$element: $('#ldap_experienced_admin'),
					setMethod: 'setExperiencedAdmin'
				}
			};
			this.setManagedItems(items);
			_.bindAll(this, 'onPortButtonClick', 'onBaseDNButtonClick', 'onBaseDNTestButtonClick');
			this.managedItems.ldap_port.$relatedElements.click(this.onPortButtonClick);
			this.managedItems.ldap_base.$detectButton.click(this.onBaseDNButtonClick);
			this.managedItems.ldap_base.$testButton.click(this.onBaseDNTestButtonClick);
		},

		/**
		 * Sets the config model for this view and subscribes to some events.
		 * Also binds the config chooser to the model
		 *
		 * @param {OCA.LDAP.Wizard.ConfigModel} configModel
		 */
		setModel: function(configModel) {
			this._super(configModel);
			this.configModel.on('configLoaded', this.onConfigSwitch, this);
			this.configModel.on('newConfiguration', this.onNewConfiguration, this);
			this.configModel.on('deleteConfiguration', this.onDeleteConfiguration, this);
			this.configModel.on('receivedLdapFeature', this.onTestResultReceived, this);
			this._enableConfigChooser();
			this._enableConfigButtons();
		},

		/**
		 * returns the currently selected configuration ID
		 *
		 * @returns {string}
		 */
		getConfigID: function() {
			return $(this.configChooserID).val();
		},

		/**
		 * updates the host configuration text field
		 *
		 * @param {string} host
		 */
		setHost: function(host) {
			this.setElementValue(this.managedItems.ldap_host.$element, host);
			if(host) {
				this.enableElement(this.managedItems.ldap_port.$relatedElements);
			} else {
				this.disableElement(this.managedItems.ldap_port.$relatedElements);
			}
		},

		/**
		 * updates the port configuration text field
		 *
		 * @param {string} port
		 */
		setPort: function(port) {
			this.setElementValue(this.managedItems.ldap_port.$element, port);
		},

		/**
		 * updates the user (agent) DN text field
		 *
		 * @param {string} agentDN
		 */
		setAgentDN: function(agentDN) {
			this.setElementValue(this.managedItems.ldap_dn.$element, agentDN);
		},

		/**
		 * updates the user (agent) password field
		 *
		 * @param {string} agentPwd
		 */
		setAgentPwd: function(agentPwd) {
			this.setElementValue(
				this.managedItems.ldap_agent_password.$element, agentPwd
			);
		},
		/**
		 * updates the base DN text area
		 *
		 * @param {string} bases
		 */
		setBase: function(bases) {
			this.setElementValue(this.managedItems.ldap_base.$element, bases);
			if(!bases) {
				this.disableElement(this.managedItems.ldap_base.$testButton);
			} else {
				this.enableElement(this.managedItems.ldap_base.$testButton);
			}
		},

		/**
		 * updates the experienced admin check box
		 *
		 * @param {string} xpAdminMode contains an int
		 */
		setExperiencedAdmin: function(xpAdminMode) {
			this.setElementValue(
				this.managedItems.ldap_experienced_admin.$element, xpAdminMode
			);
		},

		/**
		 * @inheritdoc
		 */
		overrideErrorMessage: function(message, key) {
			switch(key) {
				case 'ldap_port':
					if (message === 'Invalid credentials') {
						return t('user_ldap', 'Please check the credentials, they seem to be wrong.');
					} else {
						return t('user_ldap', 'Please specify the port, it could not be auto-detected.');
					}
					break;
				case 'ldap_base':
					if(   message === 'Server is unwilling to perform'
						|| message === 'Could not connect to LDAP'
					) {
						return t('user_ldap', 'Base DN could not be auto-detected, please revise credentials, host and port.');
					}
					return t('user_ldap', 'Could not detect Base DN, please enter it manually.');
					break;
			}
			return message;
		},

		/**
		 * resets the view when a configuration switch happened.
		 *
		 * @param {WizardTabElementary} view
		 * @param {Object} configuration
		 */
		onConfigSwitch: function(view, configuration) {
			view.disableElement(view.managedItems.ldap_port.$relatedElements);

			view.onConfigLoaded(view, configuration);
		},

		/**
		 * updates the configuration chooser when a new configuration was added
		 * which also means it is being switched to. The configuration fields
		 * are updated on a different step.
		 *
		 * @param {WizardTabElementary} view
		 * @param {Object} result
		 */
		onNewConfiguration: function(view, result) {
			if(result.isSuccess === true) {
				$(view.configChooserID + ' option:selected').removeAttr('selected');
				var html = '<option value="'+result.configPrefix+'" selected="selected">'+t('user_ldap','{nthServer}. Server', {nthServer: $(view.configChooserID + ' option').length})+'</option>';
				$(view.configChooserID + ' option:last').before(html);
			}
		},

		/**
		 * updates the configuration chooser upon the deletion of a
		 * configuration and, if necessary, loads an existing one.
		 *
		 * @param view
		 * @param result
		 */
		onDeleteConfiguration: function(view, result) {
			if(result.isSuccess === true) {
				if(view.getConfigID() === result.configPrefix) {
					// if the deleted value is still the selected one (99% of
					// the cases), remove it from the list and load the topmost
					$(view.configChooserID + ' option:selected').remove();
					$(view.configChooserID + ' option:first').select();
					if($(view.configChooserID +  ' option').length < 2) {
						view.configModel.newConfig(false);
					} else {
						view.configModel.load(view.getConfigID());
					}
				} else {
					// otherwise just remove the entry
					$(view.configChooserID + ' option[value=' + result.configPrefix + ']').remove();
				}
			} else {
				OC.Notification.showTemporary(result.errorMessage);
			}
		},

		/**
		 * Base DN test results will arrive here
		 *
		 * @param {WizardTabElementary} view
		 * @param {FeaturePayload} payload
		 */
		onTestResultReceived: function(view, payload) {
			if(payload.feature === 'TestBaseDN') {
				var message;
				if(payload.data.status === 'success') {
					var objectsFound = parseInt(payload.data.changes.ldap_test_base, 10);
					if(objectsFound < 1) {
						message = t('user_ldap', 'No object found in the given Base DN. Please revise.');
					} else if(objectsFound > 1000) {
						message = t('user_ldap', 'More then 1.000 directory entries available.');
					} else {
						message = t('user_ldap', objectsFound + ' entries available within the provided Base DN');
					}
				} else {
					message = t('user_ldap', 'An error occurred. Please check the Base DN, as well as connection settings and credentials.');
					if(payload.data.message) {
						console.warn(payload.data.message);
					}
				}
				OC.Notification.showTemporary(message);
			}
		},

		/**
		 * request to count the users with the current filter
		 *
		 * @param {Event} event
		 */
		onPortButtonClick: function(event) {
			event.preventDefault();
			this.configModel.requestWizard('ldap_port');
		},

		/**
		 * request to count the users with the current filter
		 *
		 * @param {Event} event
		 */
		onBaseDNButtonClick: function(event) {
			event.preventDefault();
			this.configModel.requestWizard('ldap_base');
		},

		/**
		 * request to count the users with the current filter
		 *
		 * @param {Event} event
		 */
		onBaseDNTestButtonClick: function(event) {
			event.preventDefault();
			this.configModel.requestWizard('ldap_test_base');
		},

		/**
		 * registers the change event on the configuration chooser and makes
		 * the model load a newly selected configuration
		 *
		 * @private
		 */
		_enableConfigChooser: function() {
			var view = this;
			$(this.configChooserID).change(function(){
				var value = $(view.configChooserID + ' option:selected:first').attr('value');
				view.configModel.load(value);
			});
		},

		/**
		 * adds actions to the action buttons for configuration management
		 *
		 * @private
		 */
		_enableConfigButtons: function() {
			var view = this;
			$('#ldap_action_delete_configuration').click(function(event) {
				event.preventDefault();
				OC.dialogs.confirm(
					t('user_ldap', 'Do you really want to delete the current Server Configuration?'),
					t('user_ldap', 'Confirm Deletion'),
					function(doDelete) {
						if(doDelete) {
							view.configModel.deleteConfig(view.getConfigID());
						}
					},
					false
				);
			});

			$('#ldap_action_add_configuration').click(function(event) {
				event.preventDefault();
				view.configModel.newConfig(false);
			});

			$('#ldap_action_copy_configuration').click(function(event) {
				event.preventDefault();
				view.configModel.newConfig(true);
			});
		}
	});

	OCA.LDAP.Wizard.WizardTabElementary = WizardTabElementary;
})();
<commit_msg>fix number and insert position when adding/copying a config<commit_after>
/**
 * Copyright (c) 2015, Arthur Schiwon <blizzz@owncloud.com>
 * This file is licensed under the Affero General Public License version 3 or later.
 * See the COPYING-README file.
 */

OCA = OCA || {};

(function() {

	/**
	 * @classdesc This class represents the view belonging to the server tab
	 * in the LDAP wizard.
	 */
	var WizardTabElementary = OCA.LDAP.Wizard.WizardTabGeneric.subClass({
		/**
		 * initializes the instance. Always call it after initialization.
		 *
		 * @param tabIndex
		 * @param tabID
		 */
		init: function (tabIndex, tabID) {
			tabIndex = 0;
			this._super(tabIndex, tabID);
			this.isActive = true;
			this.configChooserID = '#ldap_serverconfig_chooser';

			var items = {
				ldap_host: {
					$element: $('#ldap_host'),
					setMethod: 'setHost'
				},
				ldap_port: {
					$element: $('#ldap_port'),
					setMethod: 'setPort',
					$relatedElements: $('.ldapDetectPort')
				},
				ldap_dn: {
					$element: $('#ldap_dn'),
					setMethod: 'setAgentDN'
				},
				ldap_agent_password: {
					$element: $('#ldap_agent_password'),
					setMethod: 'setAgentPwd'
				},
				ldap_base: {
					$element: $('#ldap_base'),
					setMethod: 'setBase',
					$relatedElements: $('.ldapDetectBase, .ldapTestBase'),
					$detectButton: $('.ldapDetectBase'),
					$testButton: $('.ldapTestBase')
				},
				ldap_base_test: {
					$element: $('#ldap_base')
				},
				ldap_experienced_admin: {
					$element: $('#ldap_experienced_admin'),
					setMethod: 'setExperiencedAdmin'
				}
			};
			this.setManagedItems(items);
			_.bindAll(this, 'onPortButtonClick', 'onBaseDNButtonClick', 'onBaseDNTestButtonClick');
			this.managedItems.ldap_port.$relatedElements.click(this.onPortButtonClick);
			this.managedItems.ldap_base.$detectButton.click(this.onBaseDNButtonClick);
			this.managedItems.ldap_base.$testButton.click(this.onBaseDNTestButtonClick);
		},

		/**
		 * Sets the config model for this view and subscribes to some events.
		 * Also binds the config chooser to the model
		 *
		 * @param {OCA.LDAP.Wizard.ConfigModel} configModel
		 */
		setModel: function(configModel) {
			this._super(configModel);
			this.configModel.on('configLoaded', this.onConfigSwitch, this);
			this.configModel.on('newConfiguration', this.onNewConfiguration, this);
			this.configModel.on('deleteConfiguration', this.onDeleteConfiguration, this);
			this.configModel.on('receivedLdapFeature', this.onTestResultReceived, this);
			this._enableConfigChooser();
			this._enableConfigButtons();
		},

		/**
		 * returns the currently selected configuration ID
		 *
		 * @returns {string}
		 */
		getConfigID: function() {
			return $(this.configChooserID).val();
		},

		/**
		 * updates the host configuration text field
		 *
		 * @param {string} host
		 */
		setHost: function(host) {
			this.setElementValue(this.managedItems.ldap_host.$element, host);
			if(host) {
				this.enableElement(this.managedItems.ldap_port.$relatedElements);
			} else {
				this.disableElement(this.managedItems.ldap_port.$relatedElements);
			}
		},

		/**
		 * updates the port configuration text field
		 *
		 * @param {string} port
		 */
		setPort: function(port) {
			this.setElementValue(this.managedItems.ldap_port.$element, port);
		},

		/**
		 * updates the user (agent) DN text field
		 *
		 * @param {string} agentDN
		 */
		setAgentDN: function(agentDN) {
			this.setElementValue(this.managedItems.ldap_dn.$element, agentDN);
		},

		/**
		 * updates the user (agent) password field
		 *
		 * @param {string} agentPwd
		 */
		setAgentPwd: function(agentPwd) {
			this.setElementValue(
				this.managedItems.ldap_agent_password.$element, agentPwd
			);
		},
		/**
		 * updates the base DN text area
		 *
		 * @param {string} bases
		 */
		setBase: function(bases) {
			this.setElementValue(this.managedItems.ldap_base.$element, bases);
			if(!bases) {
				this.disableElement(this.managedItems.ldap_base.$testButton);
			} else {
				this.enableElement(this.managedItems.ldap_base.$testButton);
			}
		},

		/**
		 * updates the experienced admin check box
		 *
		 * @param {string} xpAdminMode contains an int
		 */
		setExperiencedAdmin: function(xpAdminMode) {
			this.setElementValue(
				this.managedItems.ldap_experienced_admin.$element, xpAdminMode
			);
		},

		/**
		 * @inheritdoc
		 */
		overrideErrorMessage: function(message, key) {
			switch(key) {
				case 'ldap_port':
					if (message === 'Invalid credentials') {
						return t('user_ldap', 'Please check the credentials, they seem to be wrong.');
					} else {
						return t('user_ldap', 'Please specify the port, it could not be auto-detected.');
					}
					break;
				case 'ldap_base':
					if(   message === 'Server is unwilling to perform'
						|| message === 'Could not connect to LDAP'
					) {
						return t('user_ldap', 'Base DN could not be auto-detected, please revise credentials, host and port.');
					}
					return t('user_ldap', 'Could not detect Base DN, please enter it manually.');
					break;
			}
			return message;
		},

		/**
		 * resets the view when a configuration switch happened.
		 *
		 * @param {WizardTabElementary} view
		 * @param {Object} configuration
		 */
		onConfigSwitch: function(view, configuration) {
			view.disableElement(view.managedItems.ldap_port.$relatedElements);

			view.onConfigLoaded(view, configuration);
		},

		/**
		 * updates the configuration chooser when a new configuration was added
		 * which also means it is being switched to. The configuration fields
		 * are updated on a different step.
		 *
		 * @param {WizardTabElementary} view
		 * @param {Object} result
		 */
		onNewConfiguration: function(view, result) {
			if(result.isSuccess === true) {
				$(view.configChooserID + ' option:selected').removeAttr('selected');
				var html = '<option value="'+result.configPrefix+'" selected="selected">'+t('user_ldap','{nthServer}. Server', {nthServer: $(view.configChooserID + ' option').length + 1})+'</option>';
				$(view.configChooserID + ' option:last').after(html);
			}
		},

		/**
		 * updates the configuration chooser upon the deletion of a
		 * configuration and, if necessary, loads an existing one.
		 *
		 * @param view
		 * @param result
		 */
		onDeleteConfiguration: function(view, result) {
			if(result.isSuccess === true) {
				if(view.getConfigID() === result.configPrefix) {
					// if the deleted value is still the selected one (99% of
					// the cases), remove it from the list and load the topmost
					$(view.configChooserID + ' option:selected').remove();
					$(view.configChooserID + ' option:first').select();
					if($(view.configChooserID +  ' option').length < 2) {
						view.configModel.newConfig(false);
					} else {
						view.configModel.load(view.getConfigID());
					}
				} else {
					// otherwise just remove the entry
					$(view.configChooserID + ' option[value=' + result.configPrefix + ']').remove();
				}
			} else {
				OC.Notification.showTemporary(result.errorMessage);
			}
		},

		/**
		 * Base DN test results will arrive here
		 *
		 * @param {WizardTabElementary} view
		 * @param {FeaturePayload} payload
		 */
		onTestResultReceived: function(view, payload) {
			if(payload.feature === 'TestBaseDN') {
				var message;
				if(payload.data.status === 'success') {
					var objectsFound = parseInt(payload.data.changes.ldap_test_base, 10);
					if(objectsFound < 1) {
						message = t('user_ldap', 'No object found in the given Base DN. Please revise.');
					} else if(objectsFound > 1000) {
						message = t('user_ldap', 'More then 1.000 directory entries available.');
					} else {
						message = t('user_ldap', objectsFound + ' entries available within the provided Base DN');
					}
				} else {
					message = t('user_ldap', 'An error occurred. Please check the Base DN, as well as connection settings and credentials.');
					if(payload.data.message) {
						console.warn(payload.data.message);
					}
				}
				OC.Notification.showTemporary(message);
			}
		},

		/**
		 * request to count the users with the current filter
		 *
		 * @param {Event} event
		 */
		onPortButtonClick: function(event) {
			event.preventDefault();
			this.configModel.requestWizard('ldap_port');
		},

		/**
		 * request to count the users with the current filter
		 *
		 * @param {Event} event
		 */
		onBaseDNButtonClick: function(event) {
			event.preventDefault();
			this.configModel.requestWizard('ldap_base');
		},

		/**
		 * request to count the users with the current filter
		 *
		 * @param {Event} event
		 */
		onBaseDNTestButtonClick: function(event) {
			event.preventDefault();
			this.configModel.requestWizard('ldap_test_base');
		},

		/**
		 * registers the change event on the configuration chooser and makes
		 * the model load a newly selected configuration
		 *
		 * @private
		 */
		_enableConfigChooser: function() {
			var view = this;
			$(this.configChooserID).change(function(){
				var value = $(view.configChooserID + ' option:selected:first').attr('value');
				view.configModel.load(value);
			});
		},

		/**
		 * adds actions to the action buttons for configuration management
		 *
		 * @private
		 */
		_enableConfigButtons: function() {
			var view = this;
			$('#ldap_action_delete_configuration').click(function(event) {
				event.preventDefault();
				OC.dialogs.confirm(
					t('user_ldap', 'Do you really want to delete the current Server Configuration?'),
					t('user_ldap', 'Confirm Deletion'),
					function(doDelete) {
						if(doDelete) {
							view.configModel.deleteConfig(view.getConfigID());
						}
					},
					false
				);
			});

			$('#ldap_action_add_configuration').click(function(event) {
				event.preventDefault();
				view.configModel.newConfig(false);
			});

			$('#ldap_action_copy_configuration').click(function(event) {
				event.preventDefault();
				view.configModel.newConfig(true);
			});
		}
	});

	OCA.LDAP.Wizard.WizardTabElementary = WizardTabElementary;
})();
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var util = require('util');

/*var callers = require('callers-module');*/

var _registry = { };
var wd = process.cwd();
var DEBUG = (process.env.DEBUG || '').trim().split(',')
    .map(function(filename){
      var file = filename.split('#');
      var method = file.slice(1);
      file[0] = relative(file[0], { noext : true });
      register(file[0], method);
      return file[0];
    });

function register(pathrel, method){
  _registry[pathrel] = method
    ? { method : method }
    : { };
  console.log(_registry);
}

function registry(pathrel){
  return (
       _registry[pathrel]
    || _registry['*']
    || { }
  );
}

function skip(pathrel, frame){
  var ret = DEBUG.indexOf(pathrel) > -1
    ? !_registry[pathrel]
    : DEBUG[0] !== '*';

  var methods = registry(pathrel).method;
  if( !methods[0] || !frame ){
    return ret;
  }

  var method =
    frame.getFunctionName()
    || frame.getMethodName();

  var index = -1, len = methods.length;
  while(++index < len){
    index = methods.indexOf(method) > -1
      ? len + index
      : index;
  }
  // -1 => not found => true to skip
  return index-len-1 < 0;
}

function relative(str, opt){
  opt = opt || { };
  var relre = new RegExp(escapeRegExp(wd+path.sep), 'g');
  var ret = str.replace(relre, '');
  if( opt.noext || str[0] === path.sep ){
    ret = ret.replace(path.extname(str), '') || './.';
  }
  return ret;
}

function regexpOf(arr, pattern, character){
  var index = -1;
  var len = arr.length;
  var reg = escapeRegExp(pattern, character);
  while(++index < len){
    index = arr[index].match(reg)
      ? len + index
      : index;
  }
  return index-len-1;
}

function escapeRegExp(pattern, character) {
  return (
    character
      ? pattern.substring(0, pattern.indexOf(character))
      : pattern
  ).replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}

module.exports = {
       DEBUG : DEBUG,
        skip : skip,
     inspect : util.inspect,
    regexpOf : regexpOf,
    relative : relative,
    register : register,
    registry : registry
};
<commit_msg>take that console.log out of the way<commit_after>'use strict';

var path = require('path');
var util = require('util');

/*var callers = require('callers-module');*/

var _registry = { };
var wd = process.cwd();
var DEBUG = (process.env.DEBUG || '').trim().split(',')
    .map(function(filename){
      var file = filename.split('#');
      var method = file.slice(1);
      file[0] = relative(file[0], { noext : true });
      register(file[0], method);
      return file[0];
    });

function register(pathrel, method){
  _registry[pathrel] = method
    ? { method : method }
    : { };
}

function registry(pathrel){
  return (
       _registry[pathrel]
    || _registry['*']
    || { }
  );
}

function skip(pathrel, frame){
  var ret = DEBUG.indexOf(pathrel) > -1
    ? !_registry[pathrel]
    : DEBUG[0] !== '*';

  var methods = registry(pathrel).method;
  if( !methods[0] || !frame ){
    return ret;
  }

  var method =
    frame.getFunctionName()
    || frame.getMethodName();

  var index = -1, len = methods.length;
  while(++index < len){
    index = methods.indexOf(method) > -1
      ? len + index
      : index;
  }
  // -1 => not found => true to skip
  return index-len-1 < 0;
}

function relative(str, opt){
  opt = opt || { };
  var relre = new RegExp(escapeRegExp(wd+path.sep), 'g');
  var ret = str.replace(relre, '');
  if( opt.noext || str[0] === path.sep ){
    ret = ret.replace(path.extname(str), '') || './.';
  }
  return ret;
}

function regexpOf(arr, pattern, character){
  var index = -1;
  var len = arr.length;
  var reg = escapeRegExp(pattern, character);
  while(++index < len){
    index = arr[index].match(reg)
      ? len + index
      : index;
  }
  return index-len-1;
}

function escapeRegExp(pattern, character) {
  return (
    character
      ? pattern.substring(0, pattern.indexOf(character))
      : pattern
  ).replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}

module.exports = {
       DEBUG : DEBUG,
        skip : skip,
     inspect : util.inspect,
    regexpOf : regexpOf,
    relative : relative,
    register : register,
    registry : registry
};
<|endoftext|>


<commit_before>'use strict'

const restrictedGlobals = require('eslint-restricted-globals')

module.exports = {
  rules: {
    'init-declarations': [ 'off' ],
    'no-catch-shadow': 'error',
    'no-delete-var': 'error',
    'no-label-var': 'error',
    'no-restricted-globals': [ 'error' ].concat(restrictedGlobals),
    'no-shadow': 'error',
    'no-shadow-restricted-names': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-undefined': 'error',
    'no-unused-vars': 'error',
    'no-use-before-define': 'error',
  },
}
<commit_msg>update rule settings<commit_after>'use strict'

const restrictedGlobals = require('eslint-restricted-globals')

module.exports = {
  rules: {
    'init-declarations': 'off',
    'no-catch-shadow': 'error',
    'no-delete-var': 'error',
    'no-label-var': 'error',
    'no-restricted-globals': [ 'error' ].concat(restrictedGlobals),
    'no-shadow': 'error',
    'no-shadow-restricted-names': 'error',
    'no-undef': 'error',
    'no-undef-init': 'error',
    'no-undefined': 'error',
    'no-unused-vars': 'error',
    'no-use-before-define': 'off',
  },
}
<|endoftext|>


<commit_before>Ext.namespace('Gemma');
Ext.BLANK_IMAGE_URL = '/Gemma/images/default/s.gif';

/**
 * This provides a summary of the differential analyses done for a particular dataset/expression experiment.
 * It is structured as a tree with each analysis as a node and its result sets as its children
 *
 * @param ee {ExpressionExperimentValueObject} the expression experiment for which to display the analyses
 * @class Gemma.DifferentialExpressionAnalysesSummaryTree
 * @extends Ext.tree.TreePanel
 */

Gemma.DifferentialExpressionAnalysesSummaryTree = Ext.extend(Ext.tree.TreePanel, {

		animate: true,
		id:'differentialExpressionAnalysesSummaryTreeEEPage',
		rootVisible: false,
		enableDD: false,
		cls: 'x-tree-noicon',
		singleClickExpand:true,
		lines:false,
		containerScroll:false,
		//panel
		autoScroll:true,
		border:false,
		layout: 'fit',
		root:{text:'root'},
		// for drawing charts
		percentUpProbes:[],
		listeners:{
			afterrender: function(){this.drawPieCharts();},
			expandnode: function(){this.drawPieCharts();}
		},

		constructor : function(ee) {
			Ext.apply(this,{ee: ee});
			Gemma.DifferentialExpressionAnalysesSummaryTree.superclass.constructor.call(this);
		},

		initComponent : function(){
			Gemma.DifferentialExpressionAnalysesSummaryTree.superclass.initComponent.call(this);
			this.build();
		},
		build:function(){
				var analyses = this.ee.differentialExpressionAnalyses;
				//console.log("in build" + this.ee.differentialExpressionAnalyses);
				// set the root node
				var root = new Ext.tree.TreeNode({
					expanded: true,
					id: 'diffExRoot',
					text: 'root'
				});
				this.setRootNode(root);
				var subsetTracker = {}; //used to keep subset nodes adjacent
				var nodeId = 0; // used to keep track of nodes and give each a specific div in which to draw a pie chart
				for (var j = 0; j < analyses.size(); j++) {
					var analysis = analyses[j];
					//console.log(analysis.protocol);

					//console.log("ANALYSIS " + (j + 1) + " of " + analyses.size());

					var parentNode = null;
					var parentText = null;
					var interaction = 0;

					// prepare subset text if applicable
					var subsetText = '';
					var subsetIdent = '';
					var neighbourNode = null;
					if (analysis.subsetFactorValue) {
						var subsetFactor = (analysis.subsetFactorValue.factor) ? analysis.subsetFactorValue.factor : analysis.subsetFactorValue.category;
						subsetText = '' +
						"subset where " +
						subsetFactor +
						" = " +
						analysis.subsetFactorValue.value +
						' ';
						subsetIdent = subsetFactor;
						//console.log("susbetIdent: " + subsetIdent);
						//if a similar subset node has already been created, insert this node adjacent to it
						neighbourNode = root.findChild('subsetIdent', subsetIdent);
					}

					// prepare download link
					var downloadDiffDataLink = String.format("       ", this.ee.id); // FIXME

					// make node for analysis
					parentNode = new Ext.tree.TreeNode({
						id: 'node'+ (nodeId++),
						expanded: false,
						singleClickExpand: true,
						text: downloadDiffDataLink,
						subsetIdent: subsetIdent
					});

					// add node to tree
					if (neighbourNode) {
						root.insertBefore(parentNode, neighbourNode);
					}
					else {
						root.appendChild(parentNode);
					}

					// if analysis has only one result set, don't give it children and put all info in parent node
					if(analysis.resultSets.size()==1){
						var resultSet = analysis.resultSets[0];
							// get experimental factor string and build analysis parent node text
							var analysisName = this.getFactorNameText(resultSet);
							var nodeText= '';
							if (resultSet.numberOfDiffExpressedProbes == 0) {
								nodeText = "  No expressed probes.";
							}
							else {
								nodeText += subsetText;
								nodeText += this.getBaseline(resultSet);
								nodeText += this.getActionLinks(resultSet,analysisName[0],this.ee.id, nodeId);
								//nodeText += this.getExpressionNumbers(resultSet);
							}
						parentText = '' +analysisName[0]+' '+nodeText;
					}
					// if analysis has >1 result set, create result set children
					else{
						for (var i = 0; i < analysis.resultSets.size(); i++) {
							//console.log("RESULT SET " + (i + 1) + " of " + analysis.resultSets.size());
							var resultSet = analysis.resultSets[i];

							// get experimental factor string and build analysis parent node text
							var analysisName = this.getFactorNameText(resultSet);
							var factor = ''+analysisName[0]+'';
							interaction += analysisName[1];

							if (resultSet.experimentalFactors.size() == 1) {
								parentText = (!parentText) ? factor : (parentText + " & " + factor);
							}

							var nodeText= '';
							if (resultSet.numberOfDiffExpressedProbes == 0) {
								nodeText = "  No expressed probes.";
							}
							else {
								nodeText += subsetText;
								nodeText += this.getBaseline(resultSet);
								nodeText += this.getActionLinks(resultSet,factor,this.ee.id,(nodeId+1));
								//nodeText += this.getExpressionNumbers(resultSet);
							}

							//make child nodes for each analysis and add them to parent factor node
							var analysisNode = new Ext.tree.TreeNode({
								id: 'node'+ (nodeId++),
								expanded: true,
								singleClickExpand: true,
								text: factor + nodeText
							});

							parentNode.appendChild(analysisNode);

						}
					}

					var analysisDesc = '';
					if(resultSet.experimentalFactors.size()>1){
						analysisDesc = 'Two-way ANOVA' + ((interaction>0) ? ' with interactions on: ' : 'on: ');
					}else{
						analysisDesc = 'One-way ANOVA on ';
					}
					parentNode.setText(analysisDesc + parentText + " " + parentNode.text);
				}
	},
	/**
	 * get the number of probes that are differentially expressed and the number of 'up' and 'down' probes
	 * @return String text with numbers
	 */
	getExpressionNumbers:function(resultSet, nodeId){
		/* Show how many probes are differentially expressed; */

		 var numbers = resultSet.numberOfDiffExpressedProbes +  ' probes' ;

		 //if (resultSet.upregulatedCount != 0) {
			 numbers += ': ' + resultSet.upregulatedCount
			 + " Up";
		 //}

		 //if (resultSet.downregulatedCount != 0) {
			 numbers += '; ' + resultSet.downregulatedCount
			 + " Down";
		// }
		numbers += '.
Threshold value = '+resultSet.threshold;
		numbers += (resultSet.qValue)?(', qvalue = '+resultSet.qValue):'';

		// save number of up regulated probes for drawing as chart after tree has been rendered
		this.percentUpProbes[nodeId]=resultSet.upregulatedCount/resultSet.numberOfDiffExpressedProbes;
		return numbers;
	},
	getBaseline: function(resultSet){
		// get baseline info
		if (resultSet.baselineGroup) {
			return ' with baseline = ' + resultSet.baselineGroup.value;
		}
		return '';
	},
	getActionLinks:function(resultSet, factor, eeID, nodeId){
		/*link for details*/
		var numbers = this.getExpressionNumbers(resultSet, nodeId);
		var linkText = ' ' +
		'' +
		' <canvas height=20 width=20 id="chartDiv'+nodeId+'"></canvas>';
		/*+ '  ';*/

		/* provide link for visualization.*/
		linkText +=
		'  ';
		return linkText;
	},
	/**
	 * get experimental factor string and build analysis parent node text
	 * @param {Object} resultSet
	 * @return {[String,int]} an array with the first element being the factor text and the second a flag marking interaction
	 */
	getFactorNameText:function(resultSet){
		var factor ='';
		var interaction = 0;
		if (resultSet.experimentalFactors == null || resultSet.experimentalFactors.size() == 0) {
			factor = "n/a";
		}
		else {
			factor = resultSet.experimentalFactors[0].name /*+ " (" + resultSet.experimentalFactors[0].category + ")"*/;

			for (var k = 1; k < resultSet.experimentalFactors.size(); k++) {
				//console.log("expFac " + k + ": " + resultSet.experimentalFactors[k].name);
				factor = factor + " x " + resultSet.experimentalFactors[k].name /*+ " (" + resultSet.experimentalFactors[k].category + ")"*/;
				interaction = 1;
			}
		}
		return [ factor, interaction];
	},
	drawPieCharts: function(){
		var ctx, up;
		for (i = 0; i < this.percentUpProbes.size(); i++) {
			if (Ext.get('chartDiv' + i)) {
				up = this.percentUpProbes[i];
				ctx = Ext.get('chartDiv' + i).dom.getContext("2d");
				drawTwoColourMiniPie(ctx, 12, 12, 14, 'lightgrey', 'SteelBlue', up * 360, 'black');
			}
		}
	}
});

// register panel as xtype
Ext.reg('differentialExpressionAnalysesSummaryTree',Gemma.DifferentialExpressionAnalysesSummaryTree);
<commit_msg>fixed bug where wrong analysis description was being used<commit_after>Ext.namespace('Gemma');
Ext.BLANK_IMAGE_URL = '/Gemma/images/default/s.gif';

/**
 * This provides a summary of the differential analyses done for a particular dataset/expression experiment.
 * It is structured as a tree with each analysis as a node and its result sets as its children
 *
 * @param ee {ExpressionExperimentValueObject} the expression experiment for which to display the analyses
 * @class Gemma.DifferentialExpressionAnalysesSummaryTree
 * @extends Ext.tree.TreePanel
 */

Gemma.DifferentialExpressionAnalysesSummaryTree = Ext.extend(Ext.tree.TreePanel, {

		animate: true,
		id:'differentialExpressionAnalysesSummaryTreeEEPage',
		rootVisible: false,
		enableDD: false,
		cls: 'x-tree-noicon',
		singleClickExpand:true,
		lines:false,
		containerScroll:false,
		//panel
		autoScroll:true,
		border:false,
		layout: 'fit',
		root:{text:'root'},
		// for drawing charts
		percentUpProbes:[],
		listeners:{
			afterrender: function(){this.drawPieCharts();},
			expandnode: function(){this.drawPieCharts();}
		},

		constructor : function(ee) {
			Ext.apply(this,{ee: ee});
			Gemma.DifferentialExpressionAnalysesSummaryTree.superclass.constructor.call(this);
		},

		initComponent : function(){
			Gemma.DifferentialExpressionAnalysesSummaryTree.superclass.initComponent.call(this);
			this.build();
		},
		build:function(){
				var analyses = this.ee.differentialExpressionAnalyses;
				//console.log("in build" + this.ee.differentialExpressionAnalyses);
				// set the root node
				var root = new Ext.tree.TreeNode({
					expanded: true,
					id: 'diffExRoot',
					text: 'root'
				});
				this.setRootNode(root);
				var subsetTracker = {}; //used to keep subset nodes adjacent
				var nodeId = 0; // used to keep track of nodes and give each a specific div in which to draw a pie chart
				for (var j = 0; j < analyses.size(); j++) {
					var analysis = analyses[j];
					//console.log(analysis.protocol);

					//console.log("ANALYSIS " + (j + 1) + " of " + analyses.size());

					var parentNode = null;
					var parentText = null;
					var interaction = 0;

					// prepare subset text if applicable
					var subsetText = '';
					var subsetIdent = '';
					var neighbourNode = null;
					if (analysis.subsetFactorValue) {
						var subsetFactor = (analysis.subsetFactorValue.factor) ? analysis.subsetFactorValue.factor : analysis.subsetFactorValue.category;
						subsetText = '' +
						"subset where " +
						subsetFactor +
						" = " +
						analysis.subsetFactorValue.value +
						' ';
						subsetIdent = subsetFactor;
						//console.log("susbetIdent: " + subsetIdent);
						//if a similar subset node has already been created, insert this node adjacent to it
						neighbourNode = root.findChild('subsetIdent', subsetIdent);
					}

					// prepare download link
					var downloadDiffDataLink = String.format("       ", this.ee.id); // FIXME

					// make node for analysis
					parentNode = new Ext.tree.TreeNode({
						id: 'node'+ (nodeId++),
						expanded: false,
						singleClickExpand: true,
						text: downloadDiffDataLink,
						subsetIdent: subsetIdent
					});

					// add node to tree
					if (neighbourNode) {
						root.insertBefore(parentNode, neighbourNode);
					}
					else {
						root.appendChild(parentNode);
					}

					// if analysis has only one result set, don't give it children and put all info in parent node
					if(analysis.resultSets.size()==1){
						var resultSet = analysis.resultSets[0];
							// get experimental factor string and build analysis parent node text
							var analysisName = this.getFactorNameText(resultSet);
							var nodeText= '';
							if (resultSet.numberOfDiffExpressedProbes == 0) {
								nodeText = "  No expressed probes.";
							}
							else {
								nodeText += subsetText;
								nodeText += this.getBaseline(resultSet);
								nodeText += this.getActionLinks(resultSet,analysisName[0],this.ee.id, nodeId);
								//nodeText += this.getExpressionNumbers(resultSet);
							}
						parentText = '' +analysisName[0]+' '+nodeText;
					}
					// if analysis has >1 result set, create result set children
					else{
						for (var i = 0; i < analysis.resultSets.size(); i++) {
							//console.log("RESULT SET " + (i + 1) + " of " + analysis.resultSets.size());
							var resultSet = analysis.resultSets[i];

							// get experimental factor string and build analysis parent node text
							var analysisName = this.getFactorNameText(resultSet);
							var factor = ''+analysisName[0]+'';
							interaction += analysisName[1];

							if (resultSet.experimentalFactors.size() == 1) {
								parentText = (!parentText) ? factor : (parentText + " & " + factor);
							}

							var nodeText= '';
							if (resultSet.numberOfDiffExpressedProbes == 0) {
								nodeText = "  No expressed probes.";
							}
							else {
								nodeText += subsetText;
								nodeText += this.getBaseline(resultSet);
								nodeText += this.getActionLinks(resultSet,factor,this.ee.id,(nodeId+1));
								//nodeText += this.getExpressionNumbers(resultSet);
							}

							//make child nodes for each analysis and add them to parent factor node
							var analysisNode = new Ext.tree.TreeNode({
								id: 'node'+ (nodeId++),
								expanded: true,
								singleClickExpand: true,
								text: factor + nodeText
							});

							parentNode.appendChild(analysisNode);

						}
					}

					var analysisDesc = '';
					if(analysis.resultSets.size()>1){
						analysisDesc = 'Two-way ANOVA' + ((interaction>0) ? ' with interactions on: ' : 'on: ');
					}else{
						analysisDesc = 'One-way ANOVA on ';
					}
					parentNode.setText(analysisDesc + parentText + " " + parentNode.text);
				}
	},
	/**
	 * get the number of probes that are differentially expressed and the number of 'up' and 'down' probes
	 * @return String text with numbers
	 */
	getExpressionNumbers:function(resultSet, nodeId){
		/* Show how many probes are differentially expressed; */

		 var numbers = resultSet.numberOfDiffExpressedProbes +  ' probes' ;

		 //if (resultSet.upregulatedCount != 0) {
			 numbers += ': ' + resultSet.upregulatedCount
			 + " Up";
		 //}

		 //if (resultSet.downregulatedCount != 0) {
			 numbers += '; ' + resultSet.downregulatedCount
			 + " Down";
		// }
		numbers += '.
Threshold value = '+resultSet.threshold;
		numbers += (resultSet.qValue)?(', qvalue = '+resultSet.qValue):'';

		// save number of up regulated probes for drawing as chart after tree has been rendered
		this.percentUpProbes[nodeId]=resultSet.upregulatedCount/resultSet.numberOfDiffExpressedProbes;
		return numbers;
	},
	getBaseline: function(resultSet){
		// get baseline info
		if (resultSet.baselineGroup) {
			return ' with baseline = ' + resultSet.baselineGroup.value;
		}
		return '';
	},
	getActionLinks:function(resultSet, factor, eeID, nodeId){
		/*link for details*/
		var numbers = this.getExpressionNumbers(resultSet, nodeId);
		var linkText = ' ' +
		'' +
		' <canvas height=20 width=20 id="chartDiv'+nodeId+'"></canvas>';
		/*+ '  ';*/

		/* provide link for visualization.*/
		linkText +=
		'  ';
		return linkText;
	},
	/**
	 * get experimental factor string and build analysis parent node text
	 * @param {Object} resultSet
	 * @return {[String,int]} an array with the first element being the factor text and the second a flag marking interaction
	 */
	getFactorNameText:function(resultSet){
		var factor ='';
		var interaction = 0;
		if (resultSet.experimentalFactors == null || resultSet.experimentalFactors.size() == 0) {
			factor = "n/a";
		}
		else {
			factor = resultSet.experimentalFactors[0].name /*+ " (" + resultSet.experimentalFactors[0].category + ")"*/;

			for (var k = 1; k < resultSet.experimentalFactors.size(); k++) {
				//console.log("expFac " + k + ": " + resultSet.experimentalFactors[k].name);
				factor = factor + " x " + resultSet.experimentalFactors[k].name /*+ " (" + resultSet.experimentalFactors[k].category + ")"*/;
				interaction = 1;
			}
		}
		return [ factor, interaction];
	},
	drawPieCharts: function(){
		var ctx, up;
		for (i = 0; i < this.percentUpProbes.size(); i++) {
			if (Ext.get('chartDiv' + i)) {
				up = this.percentUpProbes[i];
				ctx = Ext.get('chartDiv' + i).dom.getContext("2d");
				drawTwoColourMiniPie(ctx, 12, 12, 14, 'lightgrey', 'SteelBlue', up * 360, 'black');
			}
		}
	}
});

// register panel as xtype
Ext.reg('differentialExpressionAnalysesSummaryTree',Gemma.DifferentialExpressionAnalysesSummaryTree);
<|endoftext|>


<commit_before>'use strict'

function extend (Y) {
    class twicConnector extends Y.AbstractConnector {
        constructor (y, options) {
            if (options === undefined) {
                throw new Error('Options must not be undefined!');
            }
            else if ( !options.room ) {
                throw new Error('You must define a room name!');
            }
            else if( !options.socket ){
                throw new Error('You have to set a websocket object');
            }

            options.role = 'slave';
            super(y, options);

            var socket = options.socket,
                self = this;

            self._messageid = 1;
            self._eventid = 1;

            self._socket = options.socket;
            self._room = options.room;

            self.timeout_ids = {};

            // DEFINE EVENTS HANDLERS
            // ON ROOM JOINED
            this._onJoin = function( data ){
                console.log('joinRoom', data, self._eventid++ );
                self.setUserId(data.peer_id);
                // SET ROOM PEERS
                data.peers.forEach(function(peer_id){
                    if( peer_id != data.peer_id ){
                        self.userJoined( peer_id, 'master');
                    }
                });
                // LISTEN TO ROOM MESSAGES
                socket.on('yjs_'+options.room+'_message', self._onMessage);
            };
            // ON MESSAGE
            this._onMessage = function( data ){
                if( data.type === 'yjs_confirm' ){
                    if( self.timeout_ids[data.payload] ){
                        clearTimeout( self.timeout_ids[data.payload] );
                        delete( self.timeout_ids[data.payload] );
                    }
                }else if( data.type === 'yjs_data' ){
                    self.receiveMessage( data.peer_id, data.payload );

                    if( data.need_confirm && data.id ){
                        socket.emit('yjs_message', {room: options.room, type:'yjs_confirm', payload: data.id, to: data.peer_id });
                    }
                }
            };
            // WHEN A PEER JOIN THE ROOM.
            this._onNewPeer = function( data ){
                console.log('newPeer', data.peer_id, self._eventid++ );
                self.userJoined( data.peer_id, 'master');
            };
            // WHEN A PEER LEAVE THE ROOM.
            this._onOldPeer = function( data ){
                console.log('oldPeer', data.peer_id, self._eventid++ );
                self.userLeft(data.peer_id);
            };

            // WHEN SOCKET RECONNECT & IS AUTHENTICATED
            this._onAuth = function(){
                self.reconnect();
            };
            // WHEN SOCKET IS DISCONNECTED -> DISCONNECT
            this._onDisconnect = function(){
                self.disconnect();
            };

            // BIND EVENTS
            socket.on('yjs_'+options.room+'_newpeer', this._onNewPeer);
            socket.on('yjs_'+options.room+'_oldpeer', this._onOldPeer);
            socket.on('yjs_'+options.room+'_joined', this._onJoin);
            socket.on('authenticated', this._onAuth);
            socket.on('disconnect', this._onDisconnect);

            // JOIN YJS ROOM
            socket.emit( 'yjs_joinroom', {room:options.room} );
        }
        destroy(){
            console.log('connector destroyed');
            // UNBIND EVENTS
            this._socket.off('yjs_'+this._room+'_newpeer', this._onNewPeer);
            this._socket.off('yjs_'+this._room+'_oldpeer', this._onOldPeer);
            this._socket.off('yjs_'+this._room+'_joined', this._onJoin);
            this._socket.off('authenticated', this._onAuth );
            this._socket.off('disconnect', this._onDisconnect );
            // THEN DISCONNECT
            this.disconnect();
        }
        disconnect () {
            console.log('disconnect', this._eventid++ );
            this._socket.off('yjs_'+this._room+'_message', this._onMessage);
            this._socket.emit('yjs_leaveroom',{room:this._room});
            super.disconnect()
        }
        reconnect () {
            console.log('reconnect', this._eventid++);
            this._socket.emit( 'yjs_joinroom', {room:this._room} );
            super.reconnect()
        }
        send (uid, message) {
            this._messageid++;

            var self= this,
                send = function(){
                    console.log('messageSentTo', uid, message, self._messageid, self._eventid++ );

                    self._socket.emit('yjs_message',{
                        room:self._room,
                        type:'yjs_data',
                        to: uid,
                        payload: message,
                        id: self._messageid,
                        need_confirm: true
                    });

                    self.timeout_ids[self._messageid] = setTimeout( send, 500);
                };

            send();
        }
        broadcast (message) {
            console.log('messageBroadcast', message, this._messageid++, this._eventid++ );

            this._socket.emit('yjs_message',{
                room:this._room,
                type:'yjs_data',
                payload: message,
                id: this._messageid
            });
        }
        isDisconnected () {
            return this._socket.disconnected;
        }
    }
    Y.extend('twic', twicConnector);
}

module.exports = extend;
if (typeof Y !== 'undefined') {
    extend(Y);
}
<commit_msg>letting log for debug purposes<commit_after>'use strict';

function extend (Y) {
    class twicConnector extends Y.AbstractConnector {
        constructor (y, options) {
            if (options === undefined) {
                throw new Error('Options must not be undefined!');
            }
            else if ( !options.room ) {
                throw new Error('You must define a room name!');
            }
            else if( !options.socket ){
                throw new Error('You have to set a websocket object');
            }

            options.role = 'slave';
            super(y, options);

            var socket = options.socket,
                self = this;

            self._messageid = 1;
            self._eventid = 1;

            self._socket = options.socket;
            self._room = options.room;

            self.timeout_ids = {};

            // DEFINE EVENTS HANDLERS
            // ON ROOM JOINED
            this._onJoin = function( data ){
                console.log('joinRoom', data, self._eventid++ );
                self.setUserId(data.peer_id);
                // SET ROOM PEERS
                data.peers.forEach(function(peer_id){
                    if( peer_id != data.peer_id ){
                        self.userJoined( peer_id, 'master');
                    }
                });
                // LISTEN TO ROOM MESSAGES
                socket.on('yjs_'+options.room+'_message', self._onMessage);
            };
            // ON MESSAGE
            this._onMessage = function( data ){
                console.log('yjs msg', data);
                if( data.type === 'yjs_confirm' ){
                    if( self.timeout_ids[data.payload] ){
                        clearTimeout( self.timeout_ids[data.payload] );
                        delete( self.timeout_ids[data.payload] );
                    }
                }else if( data.type === 'yjs_data' ){
                    self.receiveMessage( data.peer_id, data.payload );

                    if( data.need_confirm && data.id ){
                        socket.emit('yjs_message', {room: options.room, type:'yjs_confirm', payload: data.id, to: data.peer_id });
                    }
                }
            };
            // WHEN A PEER JOIN THE ROOM.
            this._onNewPeer = function( data ){
                console.log('newPeer', data.peer_id, self._eventid++ );
                self.userJoined( data.peer_id, 'master');
            };
            // WHEN A PEER LEAVE THE ROOM.
            this._onOldPeer = function( data ){
                console.log('oldPeer', data.peer_id, self._eventid++ );
                self.userLeft(data.peer_id);
            };

            // WHEN SOCKET RECONNECT & IS AUTHENTICATED
            this._onAuth = function(){
                self.reconnect();
            };
            // WHEN SOCKET IS DISCONNECTED -> DISCONNECT
            this._onDisconnect = function(){
                self.disconnect();
            };

            // BIND EVENTS
            socket.on('yjs_'+options.room+'_newpeer', this._onNewPeer);
            socket.on('yjs_'+options.room+'_oldpeer', this._onOldPeer);
            socket.on('yjs_'+options.room+'_joined', this._onJoin);
            socket.on('authenticated', this._onAuth);
            socket.on('disconnect', this._onDisconnect);

            // JOIN YJS ROOM
            socket.emit( 'yjs_joinroom', {room:options.room} );
        }
        destroy(){
            console.log('connector destroyed');
            // UNBIND EVENTS
            this._socket.off('yjs_'+this._room+'_newpeer', this._onNewPeer);
            this._socket.off('yjs_'+this._room+'_oldpeer', this._onOldPeer);
            this._socket.off('yjs_'+this._room+'_joined', this._onJoin);
            this._socket.off('authenticated', this._onAuth );
            this._socket.off('disconnect', this._onDisconnect );
            // THEN DISCONNECT
            this.disconnect();
        }
        disconnect () {
            console.log('disconnect', this._eventid++ );
            this._socket.off('yjs_'+this._room+'_message', this._onMessage);
            this._socket.emit('yjs_leaveroom',{room:this._room});
            super.disconnect()
        }
        reconnect () {
            console.log('reconnect', this._eventid++);
            this._socket.emit( 'yjs_joinroom', {room:this._room} );
            super.reconnect()
        }
        send (uid, message) {
            this._messageid++;

            var self= this,
                send = function(){
                    console.log('messageSentTo', uid, message, self._messageid, self._eventid++ );

                    self._socket.emit('yjs_message',{
                        room:self._room,
                        type:'yjs_data',
                        to: uid,
                        payload: message,
                        id: self._messageid,
                        need_confirm: true
                    });

                    self.timeout_ids[self._messageid] = setTimeout( send, 500);
                };

            send();
        }
        broadcast (message) {
            console.log('messageBroadcast', message, this._messageid++, this._eventid++ );

            this._socket.emit('yjs_message',{
                room:this._room,
                type:'yjs_data',
                payload: message,
                id: this._messageid
            });
        }
        isDisconnected () {
            return this._socket.disconnected;
        }
    }
    Y.extend('twic', twicConnector);
}

module.exports = extend;
if (typeof Y !== 'undefined') {
    extend(Y);
}
<|endoftext|>


<commit_before>"use strict";

var LWdb = require('./LWdb');

function BoxOfQuestions(db) {

        // assign database

        // initialize values
        var _question = null; // no current question
        var _wordsToRepeat = null; // words which are eligible to be repeated.
                                   // initialisation to null forces calculation
                                   // on first call of wordsToRepeat()

        var _questionHasBeenProcessed = function(){

               _question = null;

               // This will trigger a new question, when LW.question()
               // is called the next time.

        };

        var _getRandomInt = function(min, max){
             // Returns a random integer between min (inclusive) and max (inclusive)
             // Using Math.round() will give you a non-uniform distribution!

    		return Math.floor(Math.random() * (max - min + 1)) + min;
	};

        // ===============================================================================
        // literal object
        // ===============================================================================

        return {

	db : db,

	name : db.dbName,

	chooseRandomObject : function(anArray){
                return anArray[_getRandomInt(0,anArray.length-1)];
	},

        question : function(){
            // gives back a question to ask
            if (!_question) {
                 // _question is null, go for a new one.
                 var wds = this.wordsToRepeat();
                 if (wds != null) {_question = this.chooseRandomObject(wds)}
            };
            return _question
        },

        answer :function(){
            return (this.question()).translate;
        },

       moveQuestionBackwards : function(){
            if (_question) { // we have a question

                // set new date for asking the question again;
                // this has to be a a delay period later.

                _question.date = new Date().valueOf() + (this.db.getSettings()).delay;

                // put the question back at the correct step

                var s = this.db.getSettings();

                if (s.offerLearnMode) { _question.step = 1;
                                       // step 0 is the learnmode, thus do not put
                                       // it at step 0
                                       // step 1 is the lowest step of the learn mode.
                                      }
                else { // treat all the steps the same way, as repeat mode
                       // thus the lowest step value is 0
                       _question.step = 0;

                 }

                // An alternative which is not implemented:
                //
                // Set new step value to step - 1
                // With the result being not less than 1 or 0 depending on offerLearnMode.

                this.db.putWord(_question);

                // As the question has a new later date it is no more
                // a current question

                _questionHasBeenProcessed();
            }
        },

       moveQuestionForward : function(){

            if (_question) { // we have a question
                 var s = this.db.getSettings();

                // calculate new date. This depends on which step the question is.
                // And the delay calculation factor for that particular step.
                _question.date = new Date().valueOf() +
                                 s.delay * s.factorForDelayValue[_question.step];

                // With repeated calls to this method
                // the following will move the question up
                // just one step beyond the last step.
                // A step value beyond the last step value will prevent the
                // question appearing in the wordsToRepeat collection
                // the next time wordsToRepeat is calculated.

                _question.step = _question.step + 1;

                this.db.putWord(_question);

                // As the question has a new later date it is no more
                // a current question

                _questionHasBeenProcessed();

            }
       },

      importFrom : function(anArrayOfObjects){
       this.db.importFrom(anArrayOfObjects);
       },

       getAnswerOptions : function(numberOfOptions){
          throw new Error("not yet implemented");
       },

       config : function(config){
          throw new Error("not yet implemented");
       },

       status : function(){
         // give the number of words in the whole box
         // and the number of words in wordsToRepeat

         var status = {};
         status.numberOfWords = this.db.numberOfWords();

          // FIXME add more content to status

         return status
       },

       wordsToRepeat : function(){

          var lowestStep;
          var todayNow = new Date().valueOf();

          var s = this.db.getSettings();

          if (s.offerLearnMode) {
                                  lowestStep = 1
                                  // 1 is lowest step for repeat mode
               }
          else { // treat all the steps the same way.
                 // we only have a repeat mode
                 // thus the lowest step value is 0

                 lowestStep = 0;
          }

          function isToBeRepeated(aWord) {
               return (aWord.step >= lowestStep) && (todayNow >= aWord.date);
          }

          if (_question == null || _wordsToRepeat == null) {
                // _question == null means that either a question has never
                // been asked before or that a question has been asked and
                // processed but no new question yet has been picked.
                // In both cases a new _wordsToRepeat collection is necessary.

                _wordsToRepeat = (this.db.allWords()).filter(isToBeRepeated)
          };

          return _wordsToRepeat;
       }

        }

}

module.exports = BoxOfQuestions;
<commit_msg>fixes #98<commit_after>"use strict";

var LWdb = require('./LWdb');

function BoxOfQuestions(db) {

        // private variables

        var _question = null; // no current question
        var _wordsToRepeat = null; // words which are eligible to be repeated.
                                   // initialisation to null forces calculation
                                   // on first call of wordsToRepeat()

        // private methods

        var _questionHasBeenProcessed = function(){

               _question = null;

               // This will trigger a new question, when LW.question()
               // is called the next time.

        };

        var _getRandomInt = function(min, max){
             // Returns a random integer between min (inclusive) and max (inclusive)
             // Using Math.round() will give you a non-uniform distribution!

    		return Math.floor(Math.random() * (max - min + 1)) + min;
	};

        // ===============================================================================
        // literal object
        // ===============================================================================

        return {

	db : db,

	name : db.dbName,

	chooseRandomObject : function(anArray){
                return anArray[_getRandomInt(0,anArray.length-1)];
	},

        question : function(){
            // gives back a question to ask
            if (!_question) {
                 // _question is null, go for a new one.
                 var wds = this.wordsToRepeat();
                 if (wds != null) {_question = this.chooseRandomObject(wds)}
            };
            return _question
        },

        answer :function(){
            return (this.question()).translate;
        },

       moveQuestionBackwards : function(){
            if (_question) { // we have a question

                // set new date for asking the question again;
                // this has to be a a delay period later.

                _question.date = new Date().valueOf() + (this.db.getSettings()).delay;

                // put the question back at the correct step

                var s = this.db.getSettings();

                if (s.offerLearnMode) { _question.step = 1;
                                       // step 0 is the learnmode, thus do not put
                                       // it at step 0
                                       // step 1 is the lowest step of the repeat mode.
                                      }
                else { // treat all the steps the same way, as repeat mode
                       // thus the lowest step value is 0
                       _question.step = 0;

                 }

                // An alternative which is not implemented:
                //
                // Set new step value to step - 1
                // With the result being not less than 1 or 0 depending on offerLearnMode.

                this.db.putWord(_question);

                // As the question has a new later date it is no more
                // a current question

                _questionHasBeenProcessed();
            }
        },

       moveQuestionForward : function(){

            if (_question) { // we have a question
                 var s = this.db.getSettings();

                // calculate new date. This depends on which step the question is.
                // And the delay calculation factor for that particular step.
                _question.date = new Date().valueOf() +
                                 s.delay * s.factorForDelayValue[_question.step];

                // With repeated calls to this method
                // the following will move the question up
                // just one step beyond the last step.
                // A step value beyond the last step value will prevent the
                // question appearing in the wordsToRepeat collection
                // the next time wordsToRepeat is calculated.

                _question.step = _question.step + 1;

                this.db.putWord(_question);

                // As the question has a new later date it is no more
                // a current question

                _questionHasBeenProcessed();

            }
       },

      importFrom : function(anArrayOfObjects){
       this.db.importFrom(anArrayOfObjects);
       },

       getAnswerOptions : function(numberOfOptions){
          throw new Error("not yet implemented");
       },

       config : function(config){
          throw new Error("not yet implemented");
       },

       status : function(){
         // give the number of words in the whole box
         // and the number of words in wordsToRepeat

         var status = {};
         status.numberOfWords = this.db.numberOfWords();

          // FIXME add more content to status

         return status
       },

       wordsToRepeat : function(){

          var lowestStep;
          var todayNow = new Date().valueOf();

          var s = this.db.getSettings();

          if (s.offerLearnMode) {
                                  lowestStep = 1
                                  // 1 is lowest step for repeat mode
               }
          else { // treat all the steps the same way.
                 // we only have a repeat mode
                 // thus the lowest step value is 0

                 lowestStep = 0;
          }

          function isToBeRepeated(aWord) {
               return (aWord.step >= lowestStep) && (todayNow >= aWord.date);
          }

          if (_question == null || _wordsToRepeat == null) {
                // _question == null means that either a question has never
                // been asked before or that a question has been asked and
                // processed but no new question yet has been picked.
                // In both cases a new _wordsToRepeat collection is necessary.

                _wordsToRepeat = (this.db.allWords()).filter(isToBeRepeated)
          };

          return _wordsToRepeat;
       }

      }

}

module.exports = BoxOfQuestions;
<|endoftext|>


<commit_before>// @flow weak

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import dataUpdate from '../core/dataUpdate';
import Node from '../Node';
import { getRemoveUDID } from '../core/helpers';

const keyAccessor = (d) => `tick-${d.val}`;

export const propTypes = {
  scale: PropTypes.func.isRequired,

  start: PropTypes.func.isRequired,

  enter: PropTypes.func,
  update: PropTypes.func,
  leave: PropTypes.func,

  render: PropTypes.func.isRequired,

  component: PropTypes.any,
  className: PropTypes.string,
  keyAccessor: PropTypes.func.isRequired,
};

export default class TickGroup extends PureComponent {
  static propTypes = propTypes;

  static defaultProps = {
    component: 'g',
    className: 'tick-group',
  };

  constructor(props) {
    super(props);

    (this:any).lazyRemoveUDID = this.lazyRemoveUDID.bind(this);
  }

  state = {
    nodes: [],
    udids: {},
    removed: {},
    prevScale: () => {},
    currScale: () => {},
  }

  componentDidMount() {
    this.updateTicks(this.props, this.props);
  }

  componentWillReceiveProps(next) {
    if (this.props.scale !== next.scale) {
      this.updateTicks(this.props, next);
    }
  }

  updateTicks(prev, next) {
    const { tickCount, scale } = next;
    const ticks = scale.ticks ? scale.ticks(tickCount) : [];

    this.setState((prevState) => {
      const mapped = ticks.map((tick) => ({ val: tick }));
      const update = dataUpdate(mapped, prevState, keyAccessor);
      return { ...update, prevScale: prev.scale, currScale: scale };
    });
  }

  removeUDID = getRemoveUDID.call(this, keyAccessor);

  lazyRemoveUDID(udid) {
    this.setState((prevState) => ({
      removed: Object.assign({}, prevState.removed, { [udid]: true }),
    }));
  }

  render() {
    const { props: {
      scale,
      start,
      enter,
      update,
      leave,
      render,
      component,
      className,
    }, state } = this;

    return React.createElement(
      component,
      { className },
      state.nodes.map((node, index) => {
        const udid = keyAccessor(node);
        const type = state.udids[udid];

        return (
          <Node
            key={udid}

            data={scale}

            udid={udid}
            type={type}
            node={node}
            index={index}

            start={start}

            enter={enter}
            update={update}
            leave={leave}

            render={render}

            removeUDID={this.removeUDID}
            lazyRemoveUDID={this.lazyRemoveUDID}
          />
        );
      }),
    );
  }
}
<commit_msg>pass scales<commit_after>// @flow weak

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import dataUpdate from '../core/dataUpdate';
import Node from '../Node';
import { getRemoveUDID } from '../core/helpers';

const keyAccessor = (d) => `tick-${d.val}`;

export const propTypes = {
  scale: PropTypes.func.isRequired,

  start: PropTypes.func.isRequired,

  enter: PropTypes.func,
  update: PropTypes.func,
  leave: PropTypes.func,

  render: PropTypes.func.isRequired,

  component: PropTypes.any,
  className: PropTypes.string,
  keyAccessor: PropTypes.func.isRequired,
};

export default class TickGroup extends PureComponent {
  static propTypes = propTypes;

  static defaultProps = {
    component: 'g',
    className: 'tick-group',
  };

  constructor(props) {
    super(props);

    (this:any).lazyRemoveUDID = this.lazyRemoveUDID.bind(this);
  }

  state = {
    nodes: [],
    udids: {},
    removed: {},
    prevScale: () => {},
    currScale: () => {},
  }

  componentDidMount() {
    this.updateTicks(this.props, this.props);
  }

  componentWillReceiveProps(next) {
    if (this.props.scale !== next.scale) {
      this.updateTicks(this.props, next);
    }
  }

  updateTicks(prev, next) {
    const { tickCount, scale } = next;
    const ticks = scale.ticks ? scale.ticks(tickCount) : [];

    this.setState((prevState) => {
      const mapped = ticks.map((tick) => ({ val: tick }));
      const update = dataUpdate(mapped, prevState, keyAccessor);
      return { ...update, prevScale: prev.scale, currScale: scale };
    });
  }

  removeUDID = getRemoveUDID.call(this, keyAccessor);

  lazyRemoveUDID(udid) {
    this.setState((prevState) => ({
      removed: Object.assign({}, prevState.removed, { [udid]: true }),
    }));
  }

  render() {
    const { props: {
      scale,
      start,
      enter,
      update,
      leave,
      render,
      component,
      className,
    }, state } = this;

    return React.createElement(
      component,
      { className },
      state.nodes.map((node, index) => {
        const udid = keyAccessor(node);
        const type = state.udids[udid];

        return (
          <Node
            key={udid}

            data={scale}

            udid={udid}
            type={type}
            node={node}
            index={index}

            start={start}

            enter={enter}
            update={update}
            leave={leave}

            render={render}

            prevScale={state.prevScale}
            currScale={state.currScale}
            removeUDID={this.removeUDID}
            lazyRemoveUDID={this.lazyRemoveUDID}
          />
        );
      }),
    );
  }
}
<|endoftext|>


<commit_before>
"use strict";

var EventEmitter = require('events').EventEmitter;
var extend = Object.assign;

class Lfo extends EventEmitter {

  constructor(previous = null, options = {}) {

    this.idx = 0;

    if(previous && !('process' in previous)){ // no type in the duck, it's an options type of duck
      extend(options, previous);
      previous = null;
    }

    if(previous) {
      // add ourselves to the previous operator if its passed
      previous.add(this);
      // this.__previous = previous;
    }

  }

  // bind child node
  add(lfo = null){
    this.on('frame', (t, d) => lfo.process(t, d));
  }

  // removes all children from listening
  remove(){
    this.removeAllListeners('frame');
  }

  process(time, data) { console.error('process not implemented'); }

  // will delete itself from the parent node
  destroy(){
    if(this.previous)
      this.previous.removeListener('frame', this);
  }

}

module.exports = Lfo;<commit_msg>safe self-constuctor<commit_after>
"use strict";

var EventEmitter = require('events').EventEmitter;
var extend = Object.assign;

class Lfo extends EventEmitter {

  constructor(previous = null, options = {}) {
    if (!(this instanceof Lfo)) return new Lfo(previous, options);

    this.idx = 0;

    if(previous && !('process' in previous)){ // no type in the duck, it's an options type of duck
      extend(options, previous);
      previous = null;
    }

    if(previous) {
      // add ourselves to the previous operator if its passed
      previous.add(this);
      // this.__previous = previous;
    }

  }

  // bind child node
  add(lfo = null){
    this.on('frame', (t, d) => lfo.process(t, d));
  }

  // removes all children from listening
  remove(){
    this.removeAllListeners('frame');
  }

  process(time, data) { console.error('process not implemented'); }

  // will delete itself from the parent node
  destroy(){
    if(this.previous)
      this.previous.removeListener('frame', this);
  }

}

module.exports = Lfo;<|endoftext|>


<commit_before>// each one of these will target its own iframe
//
(function(){

	var iframeWindow = {}, iframeElement = {}

	var getId = function() {
		var t = (new Date()).getTime()
		while ((new Date()).getTime() === t) {}
		return t
	}
	var _id = '_v_' + getId()

	var getMyRef = function() {	// where in the document are we
		var spanId = _id + 's'
		document.write('')
		var span = document.getElementById(spanId)
		var script = span.previousElementSibling
		if (script)
			script.parentNode.removeChild(span)
		return script
	}

	var script = getMyRef()
	if (!script) {
		console.error('could not find myself')
		return
	}

	var url = ''
	var u = script.attributes.getNamedItem('data-vizorurl')
	if (u) {
		url = u.value
		if (!url)
			return console.error('could not find URL from data-vizorurl')
	}
	else
		return console.error('could not find data-vizorurl')

	// by here we have our script node and its data-url in url

	var n = script.parentNode, r = n.getBoundingClientRect()
	var aspect = 16 / 9
	var desiredAspect = script.attributes.getNamedItem('data-aspect')
	if (desiredAspect) {
		desiredAspect = parseFloat(desiredAspect.value)
		if (!isNaN(desiredAspect))
			aspect = desiredAspect
	}

	var iframeWidth = r.width * 0.995
	var iframeHeight = iframeWidth / aspect
	var iframeId = _id + 'i'

	window.addEventListener('orientationchange', function() {
		iframeWindow.postMessage({ orientation: window.orientation }, '*')
		return true
    }, false)

	var resizeIframe = function() {
		var currentWidth = iframeElement.parentNode.getBoundingClientRect().width * 0.995
		if (currentWidth !== iframeWidth) {
			iframeWidth = currentWidth
			iframeHeight = iframeWidth / aspect
			iframeElement.width = iframeWidth
			iframeElement.height = iframeHeight
		}
		return true
	}

	document.write('')

	iframeElement = document.getElementById(iframeId)
	iframeWindow = document.getElementById(iframeId).contentWindow

	resizeIframe()

	window.addEventListener('orientationchange', resizeIframe)
	window.addEventListener('resize', resizeIframe)
	window.addEventListener('devicemotion', function(deviceMotion) {
		iframeWindow.postMessage({
			devicemotion: {
				accelerationIncludingGravity: {
					x: deviceMotion.accelerationIncludingGravity.x,
					y: deviceMotion.accelerationIncludingGravity.y,
					z: deviceMotion.accelerationIncludingGravity.z
				},
				rotationRate: {
					alpha: deviceMotion.rotationRate.alpha,
					beta: deviceMotion.rotationRate.beta,
					gamma: deviceMotion.rotationRate.gamma
				},
				timeStamp: deviceMotion.timeStamp
			}
		}, '*')
	}, false)

	// log us
	window._v_urls = window._v_urls || []
	window._v_urls.push(url)

	window.addEventListener('load', resizeIframe)
})()<commit_msg>fix embed sizing when orientationchange-d<commit_after>// each one of these will target its own iframe
//
(function(){

	var iframeWindow = {}, iframeElement = {}

	var getId = function() {
		var t = (new Date()).getTime()
		while ((new Date()).getTime() === t) {}
		return t
	}
	var _id = '_v_' + getId()

	var getMyRef = function() {	// where in the document are we
		var spanId = _id + 's'
		document.write('')
		var span = document.getElementById(spanId)
		var script = span.previousElementSibling
		if (script)
			script.parentNode.removeChild(span)
		return script
	}

	var script = getMyRef()
	if (!script) {
		console.error('could not find myself')
		return
	}

	var url = ''
	var u = script.attributes.getNamedItem('data-vizorurl')
	if (u) {
		url = u.value
		if (!url)
			return console.error('could not find URL from data-vizorurl')
	}
	else
		return console.error('could not find data-vizorurl')

	// by here we have our script node and its data-url in url

	var n = script.parentNode, r = n.getBoundingClientRect()
	var aspect = 16 / 9
	var desiredAspect = script.attributes.getNamedItem('data-aspect')
	if (desiredAspect) {
		desiredAspect = parseFloat(desiredAspect.value)
		if (!isNaN(desiredAspect))
			aspect = desiredAspect
	}

	var iframeWidth = r.width * 0.995
	var iframeHeight = iframeWidth / aspect
	var iframeId = _id + 'i'

	window.addEventListener('orientationchange', function() {
		iframeWindow.postMessage({ orientation: window.orientation }, '*')
		return true
    }, false)

	var resizeIframe = function() {
		var d = iframeElement.style.display
		iframeElement.style.display = 'none'
		var currentWidth = iframeElement.parentNode.getBoundingClientRect().width * 0.995
		if (currentWidth !== iframeWidth) {
			iframeWidth = currentWidth
			iframeHeight = iframeWidth / aspect
			iframeElement.width = iframeWidth
			iframeElement.height = iframeHeight
		}
		iframeElement.style.display = d
		return true
	}

	document.write('')

	iframeElement = document.getElementById(iframeId)
	iframeWindow = document.getElementById(iframeId).contentWindow

	resizeIframe()

	// fix resizing issues with android
	// android issues orientationchange->resize, ios issues resize->orientationchange
	window.addEventListener('orientationchange', function(){
		setTimeout(resizeIframe, 500)
	}, true)
	window.addEventListener('resize', resizeIframe)
	window.addEventListener('devicemotion', function(deviceMotion) {
		iframeWindow.postMessage({
			devicemotion: {
				accelerationIncludingGravity: {
					x: deviceMotion.accelerationIncludingGravity.x,
					y: deviceMotion.accelerationIncludingGravity.y,
					z: deviceMotion.accelerationIncludingGravity.z
				},
				rotationRate: {
					alpha: deviceMotion.rotationRate.alpha,
					beta: deviceMotion.rotationRate.beta,
					gamma: deviceMotion.rotationRate.gamma
				},
				timeStamp: deviceMotion.timeStamp
			}
		}, '*')
	}, false)

	// log us
	window._v_urls = window._v_urls || []
	window._v_urls.push(url)

	window.addEventListener('load', resizeIframe)
})()<|endoftext|>