<commit_before>const subManager = new SubsManager();

BlazeComponent.extendComponent({
  events() {
    return [
      {
        'click .js-due-cards-view-change': Popup.open('globalSearchViewChange'),
      },
    ];
  },
}).register('globalSearchHeaderBar');

Template.globalSearch.helpers({
  userId() {
    return Meteor.userId();
  },
});

BlazeComponent.extendComponent({
  events() {
    return [
      {
        'click .js-due-cards-view-me'() {
          Utils.setDueCardsView('me');
          Popup.close();
        },

        'click .js-due-cards-view-all'() {
          Utils.setDueCardsView('all');
          Popup.close();
        },
      },
    ];
  },
}).register('globalSearchViewChangePopup');

BlazeComponent.extendComponent({
  onCreated() {
    this.searching = new ReactiveVar(false);
    this.hasResults = new ReactiveVar(false);
    this.hasQueryErrors = new ReactiveVar(false);
    this.query = new ReactiveVar('');
    this.resultsHeading = new ReactiveVar('');
    this.searchLink = new ReactiveVar(null);
    this.myLists = new ReactiveVar([]);
    this.myLabelNames = new ReactiveVar([]);
    this.myBoardNames = new ReactiveVar([]);
    this.results = new ReactiveVar([]);
    this.queryParams = null;
    this.parsingErrors = [];
    this.resultsCount = 0;
    this.totalHits = 0;
    this.queryErrors = null;
    this.colorMap = null;
    // this.colorMap = {};
    // for (const color of Boards.simpleSchema()._schema['labels.$.color']
    //   .allowedValues) {
    //   this.colorMap[TAPi18n.__(`color-${color}`)] = color;
    // }
    // // eslint-disable-next-line no-console
    // console.log('colorMap:', this.colorMap);

    Meteor.call('myLists', (err, data) => {
      if (!err) {
        this.myLists.set(data);
      }
    });

    Meteor.call('myLabelNames', (err, data) => {
      if (!err) {
        this.myLabelNames.set(data);
      }
    });

    Meteor.call('myBoardNames', (err, data) => {
      if (!err) {
        this.myBoardNames.set(data);
      }
    });
  },

  onRendered() {
    Meteor.subscribe('setting');
    if (Session.get('globalQuery')) {
      this.searchAllBoards(Session.get('globalQuery'));
    }
  },

  resetSearch() {
    this.searching.set(false);
    this.results.set([]);
    this.hasResults.set(false);
    this.hasQueryErrors.set(false);
    this.resultsHeading.set('');
    this.parsingErrors = [];
    this.resultsCount = 0;
    this.totalHits = 0;
    this.queryErrors = null;
  },

  getResults() {
    // eslint-disable-next-line no-console
    // console.log('getting results');
    if (this.queryParams) {
      const sessionData = SessionData.findOne({
        userId: Meteor.userId(),
        sessionId: SessionData.getSessionId(),
      });
      // eslint-disable-next-line no-console
      console.log('session data:', sessionData);

      const cards = Cards.find({ _id: { $in: sessionData.cards } });
      this.queryErrors = sessionData.errorMessages;
      // eslint-disable-next-line no-console
      // console.log('errors:', this.queryErrors);
      if (this.parsingErrors.length) {
        this.queryErrors = this.errorMessages();
        this.hasQueryErrors.set(true);
        return null;
      }
      if (this.queryErrors.length) {
        this.hasQueryErrors.set(true);
        return null;
      }

      if (cards) {
        this.totalHits = sessionData.totalHits;
        this.resultsCount = cards.count();
        this.resultsHeading.set(this.getResultsHeading());
        this.results.set(cards);
      }
    }
    this.resultsCount = 0;
    return null;
  },

  errorMessages() {
    const messages = [];

    if (this.parsingErrors.length) {
      this.parsingErrors.forEach(err => {
        messages.push(TAPi18n.__(err.tag, err.value));
      });
    }

    return messages;
  },

  searchAllBoards(query) {
    query = query.trim();
    // eslint-disable-next-line no-console
    console.log('query:', query);

    this.query.set(query);

    this.resetSearch();

    if (!query) {
      return;
    }

    this.searching.set(true);

    if (!this.colorMap) {
      this.colorMap = {};
      for (const color of Boards.simpleSchema()._schema['labels.$.color']
        .allowedValues) {
        this.colorMap[TAPi18n.__(`color-${color}`)] = color;
      }
    }

    const reOperator1 = /^((?<operator>\w+):|(?<abbrev>[#@]))(?<value>\w+)(\s+|$)/;
    const reOperator2 = /^((?<operator>\w+):|(?<abbrev>[#@]))(?<quote>["']*)(?<value>.*?)\k<quote>(\s+|$)/;
    const reText = /^(?<text>\S+)(\s+|$)/;
    const reQuotedText = /^(?<quote>["'])(?<text>\w+)\k<quote>(\s+|$)/;

    const operators = {
      'operator-board': 'boards',
      'operator-board-abbrev': 'boards',
      'operator-swimlane': 'swimlanes',
      'operator-swimlane-abbrev': 'swimlanes',
      'operator-list': 'lists',
      'operator-list-abbrev': 'lists',
      'operator-label': 'labels',
      'operator-label-abbrev': 'labels',
      'operator-user': 'users',
      'operator-user-abbrev': 'users',
      'operator-member': 'members',
      'operator-member-abbrev': 'members',
      'operator-assignee': 'assignees',
      'operator-assignee-abbrev': 'assignees',
      'operator-is': 'is',
      'operator-due': 'dueAt',
      'operator-created': 'createdAt',
      'operator-modified': 'modifiedAt',
      'operator-comment': 'comments',
    };

    const operatorMap = {};
    Object.entries(operators).forEach(([key, value]) => {
      operatorMap[TAPi18n.__(key).toLowerCase()] = value;
    });

    // eslint-disable-next-line no-console
    // console.log('operatorMap:', operatorMap);
    const params = {
      boards: [],
      swimlanes: [],
      lists: [],
      users: [],
      members: [],
      assignees: [],
      labels: [],
      is: [],
      dueAt: null,
      createdAt: null,
      modifiedAt: null,
      comments: [],
    };

    let text = '';
    while (query) {
      m = query.match(reOperator1);
      if (!m) {
        m = query.match(reOperator2);
        if (m) {
          query = query.replace(reOperator2, '');
        }
      } else {
        query = query.replace(reOperator1, '');
      }
      if (m) {
        let op;
        if (m.groups.operator) {
          op = m.groups.operator.toLowerCase();
        } else {
          op = m.groups.abbrev;
        }
        if (operatorMap.hasOwnProperty(op)) {
          let value = m.groups.value;
          if (operatorMap[op] === 'labels') {
            if (value in this.colorMap) {
              value = this.colorMap[value];
            }
          } else if (
            ['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op])
          ) {
            let days = parseInt(value, 10);
            let duration = null;
            if (isNaN(days)) {
              if (['day', 'week', 'month', 'quarter', 'year'].includes(value)) {
                duration = value;
                value = moment();
              } else if (value === 'overdue') {
                value = moment();
                duration = 'days';
                days = 0;
              } else {
                this.parsingErrors.push({
                  tag: 'operator-number-expected',
                  value: { operator: op, value },
                });
                value = null;
              }
            } else {
              value = moment();
            }
            if (value) {
              if (operatorMap[op] === 'dueAt') {
                value = value.add(days, duration ? duration : 'days').format();
              } else {
                value = value
                  .subtract(days, duration ? duration : 'days')
                  .format();
              }
            }
          } else if (operatorMap[op] === 'sort') {
            if (!['due', 'modified', 'created', 'system'].includes(value)) {
              this.parsingErrors.push({
                tag: 'operator-sort-invalid',
                value,
              });
            }
          }
          if (Array.isArray(params[operatorMap[op]])) {
            params[operatorMap[op]].push(value);
          } else {
            params[operatorMap[op]] = value;
          }
        } else {
          this.parsingErrors.push({
            tag: 'operator-unknown-error',
            value: op,
          });
        }
        continue;
      }

      m = query.match(reQuotedText);
      if (!m) {
        m = query.match(reText);
        if (m) {
          query = query.replace(reText, '');
        }
      } else {
        query = query.replace(reQuotedText, '');
      }
      if (m) {
        text += (text ? ' ' : '') + m.groups.text;
      }
    }

    // eslint-disable-next-line no-console
    // console.log('text:', text);
    params.text = text;

    // eslint-disable-next-line no-console
    console.log('params:', params);

    this.queryParams = params;

    if (this.parsingErrors.length) {
      this.searching.set(false);
      this.queryErrors = this.errorMessages();
      this.hasQueryErrors.set(true);
      return;
    }

    this.autorun(() => {
      const handle = subManager.subscribe(
        'globalSearch',
        SessionData.getSessionId(),
        params,
      );
      Tracker.nonreactive(() => {
        Tracker.autorun(() => {
          if (handle.ready()) {
            this.getResults();
            this.searching.set(false);
            this.hasResults.set(true);
          }
        });
      });
    });
  },

  getResultsHeading() {
    if (this.resultsCount === 0) {
      return TAPi18n.__('no-cards-found');
    } else if (this.resultsCount === 1) {
      return TAPi18n.__('one-card-found');
    } else if (this.resultsCount === this.totalHits) {
      return TAPi18n.__('n-cards-found', this.resultsCount);
    }

    return TAPi18n.__('n-n-of-n-cards-found', {
      start: 1,
      end: this.resultsCount,
      total: this.totalHits,
    });
  },

  getSearchHref() {
    const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
    return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
  },

  searchInstructions() {
    tags = {
      operator_board: TAPi18n.__('operator-board'),
      operator_list: TAPi18n.__('operator-list'),
      operator_swimlane: TAPi18n.__('operator-swimlane'),
      operator_label: TAPi18n.__('operator-label'),
      operator_label_abbrev: TAPi18n.__('operator-label-abbrev'),
      operator_user: TAPi18n.__('operator-user'),
      operator_user_abbrev: TAPi18n.__('operator-user-abbrev'),
      operator_member: TAPi18n.__('operator-member'),
      operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
      operator_assignee: TAPi18n.__('operator-assignee'),
      operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
    };

    text = `# ${TAPi18n.__('globalSearch-instructions-heading')}`;
    text += `\n${TAPi18n.__('globalSearch-instructions-description', tags)}`;
    text += `\n${TAPi18n.__('globalSearch-instructions-operators', tags)}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-board',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-list',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-swimlane',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-label',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-hash',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-user',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-operator-at', tags)}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-member',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-assignee',
      tags,
    )}`;

    text += `\n## ${TAPi18n.__('heading-notes')}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-1', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-2', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-3', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-4', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-5', tags)}`;

    return text;
  },

  labelColors() {
    return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map(
      color => {
        return { color, name: TAPi18n.__(`color-${color}`) };
      },
    );
  },

  events() {
    return [
      {
        'submit .js-search-query-form'(evt) {
          evt.preventDefault();
          this.searchAllBoards(evt.target.searchQuery.value);
        },
        'click .js-label-color'(evt) {
          evt.preventDefault();
          this.query.set(
            `${this.query.get()} ${TAPi18n.__('operator-label')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
        'click .js-board-title'(evt) {
          evt.preventDefault();
          this.query.set(
            `${this.query.get()} ${TAPi18n.__('operator-board')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
        'click .js-list-title'(evt) {
          evt.preventDefault();
          this.query.set(
            `${this.query.get()} ${TAPi18n.__('operator-list')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
        'click .js-label-name'(evt) {
          evt.preventDefault();
          this.query.set(
            `${this.query.get()} ${TAPi18n.__('operator-label')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
      },
    ];
  },
}).register('globalSearch');
<commit_msg>get input value from input, not reactive var<commit_after>const subManager = new SubsManager();

BlazeComponent.extendComponent({
  events() {
    return [
      {
        'click .js-due-cards-view-change': Popup.open('globalSearchViewChange'),
      },
    ];
  },
}).register('globalSearchHeaderBar');

Template.globalSearch.helpers({
  userId() {
    return Meteor.userId();
  },
});

BlazeComponent.extendComponent({
  events() {
    return [
      {
        'click .js-due-cards-view-me'() {
          Utils.setDueCardsView('me');
          Popup.close();
        },

        'click .js-due-cards-view-all'() {
          Utils.setDueCardsView('all');
          Popup.close();
        },
      },
    ];
  },
}).register('globalSearchViewChangePopup');

BlazeComponent.extendComponent({
  onCreated() {
    this.searching = new ReactiveVar(false);
    this.hasResults = new ReactiveVar(false);
    this.hasQueryErrors = new ReactiveVar(false);
    this.query = new ReactiveVar('');
    this.resultsHeading = new ReactiveVar('');
    this.searchLink = new ReactiveVar(null);
    this.myLists = new ReactiveVar([]);
    this.myLabelNames = new ReactiveVar([]);
    this.myBoardNames = new ReactiveVar([]);
    this.results = new ReactiveVar([]);
    this.queryParams = null;
    this.parsingErrors = [];
    this.resultsCount = 0;
    this.totalHits = 0;
    this.queryErrors = null;
    this.colorMap = null;
    // this.colorMap = {};
    // for (const color of Boards.simpleSchema()._schema['labels.$.color']
    //   .allowedValues) {
    //   this.colorMap[TAPi18n.__(`color-${color}`)] = color;
    // }
    // // eslint-disable-next-line no-console
    // console.log('colorMap:', this.colorMap);

    Meteor.call('myLists', (err, data) => {
      if (!err) {
        this.myLists.set(data);
      }
    });

    Meteor.call('myLabelNames', (err, data) => {
      if (!err) {
        this.myLabelNames.set(data);
      }
    });

    Meteor.call('myBoardNames', (err, data) => {
      if (!err) {
        this.myBoardNames.set(data);
      }
    });
  },

  onRendered() {
    Meteor.subscribe('setting');
    if (Session.get('globalQuery')) {
      this.searchAllBoards(Session.get('globalQuery'));
    }
  },

  resetSearch() {
    this.searching.set(false);
    this.results.set([]);
    this.hasResults.set(false);
    this.hasQueryErrors.set(false);
    this.resultsHeading.set('');
    this.parsingErrors = [];
    this.resultsCount = 0;
    this.totalHits = 0;
    this.queryErrors = null;
  },

  getResults() {
    // eslint-disable-next-line no-console
    // console.log('getting results');
    if (this.queryParams) {
      const sessionData = SessionData.findOne({
        userId: Meteor.userId(),
        sessionId: SessionData.getSessionId(),
      });
      // eslint-disable-next-line no-console
      console.log('session data:', sessionData);

      const cards = Cards.find({ _id: { $in: sessionData.cards } });
      this.queryErrors = sessionData.errorMessages;
      // eslint-disable-next-line no-console
      // console.log('errors:', this.queryErrors);
      if (this.parsingErrors.length) {
        this.queryErrors = this.errorMessages();
        this.hasQueryErrors.set(true);
        return null;
      }
      if (this.queryErrors.length) {
        this.hasQueryErrors.set(true);
        return null;
      }

      if (cards) {
        this.totalHits = sessionData.totalHits;
        this.resultsCount = cards.count();
        this.resultsHeading.set(this.getResultsHeading());
        this.results.set(cards);
      }
    }
    this.resultsCount = 0;
    return null;
  },

  errorMessages() {
    const messages = [];

    if (this.parsingErrors.length) {
      this.parsingErrors.forEach(err => {
        messages.push(TAPi18n.__(err.tag, err.value));
      });
    }

    return messages;
  },

  searchAllBoards(query) {
    query = query.trim();
    // eslint-disable-next-line no-console
    console.log('query:', query);

    this.query.set(query);

    this.resetSearch();

    if (!query) {
      return;
    }

    this.searching.set(true);

    if (!this.colorMap) {
      this.colorMap = {};
      for (const color of Boards.simpleSchema()._schema['labels.$.color']
        .allowedValues) {
        this.colorMap[TAPi18n.__(`color-${color}`)] = color;
      }
    }

    const reOperator1 = /^((?<operator>\w+):|(?<abbrev>[#@]))(?<value>\w+)(\s+|$)/;
    const reOperator2 = /^((?<operator>\w+):|(?<abbrev>[#@]))(?<quote>["']*)(?<value>.*?)\k<quote>(\s+|$)/;
    const reText = /^(?<text>\S+)(\s+|$)/;
    const reQuotedText = /^(?<quote>["'])(?<text>\w+)\k<quote>(\s+|$)/;

    const operators = {
      'operator-board': 'boards',
      'operator-board-abbrev': 'boards',
      'operator-swimlane': 'swimlanes',
      'operator-swimlane-abbrev': 'swimlanes',
      'operator-list': 'lists',
      'operator-list-abbrev': 'lists',
      'operator-label': 'labels',
      'operator-label-abbrev': 'labels',
      'operator-user': 'users',
      'operator-user-abbrev': 'users',
      'operator-member': 'members',
      'operator-member-abbrev': 'members',
      'operator-assignee': 'assignees',
      'operator-assignee-abbrev': 'assignees',
      'operator-is': 'is',
      'operator-due': 'dueAt',
      'operator-created': 'createdAt',
      'operator-modified': 'modifiedAt',
      'operator-comment': 'comments',
    };

    const operatorMap = {};
    Object.entries(operators).forEach(([key, value]) => {
      operatorMap[TAPi18n.__(key).toLowerCase()] = value;
    });

    // eslint-disable-next-line no-console
    // console.log('operatorMap:', operatorMap);
    const params = {
      boards: [],
      swimlanes: [],
      lists: [],
      users: [],
      members: [],
      assignees: [],
      labels: [],
      is: [],
      dueAt: null,
      createdAt: null,
      modifiedAt: null,
      comments: [],
    };

    let text = '';
    while (query) {
      m = query.match(reOperator1);
      if (!m) {
        m = query.match(reOperator2);
        if (m) {
          query = query.replace(reOperator2, '');
        }
      } else {
        query = query.replace(reOperator1, '');
      }
      if (m) {
        let op;
        if (m.groups.operator) {
          op = m.groups.operator.toLowerCase();
        } else {
          op = m.groups.abbrev;
        }
        if (operatorMap.hasOwnProperty(op)) {
          let value = m.groups.value;
          if (operatorMap[op] === 'labels') {
            if (value in this.colorMap) {
              value = this.colorMap[value];
            }
          } else if (
            ['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op])
          ) {
            let days = parseInt(value, 10);
            let duration = null;
            if (isNaN(days)) {
              if (['day', 'week', 'month', 'quarter', 'year'].includes(value)) {
                duration = value;
                value = moment();
              } else if (value === 'overdue') {
                value = moment();
                duration = 'days';
                days = 0;
              } else {
                this.parsingErrors.push({
                  tag: 'operator-number-expected',
                  value: { operator: op, value },
                });
                value = null;
              }
            } else {
              value = moment();
            }
            if (value) {
              if (operatorMap[op] === 'dueAt') {
                value = value.add(days, duration ? duration : 'days').format();
              } else {
                value = value
                  .subtract(days, duration ? duration : 'days')
                  .format();
              }
            }
          } else if (operatorMap[op] === 'sort') {
            if (!['due', 'modified', 'created', 'system'].includes(value)) {
              this.parsingErrors.push({
                tag: 'operator-sort-invalid',
                value,
              });
            }
          }
          if (Array.isArray(params[operatorMap[op]])) {
            params[operatorMap[op]].push(value);
          } else {
            params[operatorMap[op]] = value;
          }
        } else {
          this.parsingErrors.push({
            tag: 'operator-unknown-error',
            value: op,
          });
        }
        continue;
      }

      m = query.match(reQuotedText);
      if (!m) {
        m = query.match(reText);
        if (m) {
          query = query.replace(reText, '');
        }
      } else {
        query = query.replace(reQuotedText, '');
      }
      if (m) {
        text += (text ? ' ' : '') + m.groups.text;
      }
    }

    // eslint-disable-next-line no-console
    // console.log('text:', text);
    params.text = text;

    // eslint-disable-next-line no-console
    console.log('params:', params);

    this.queryParams = params;

    if (this.parsingErrors.length) {
      this.searching.set(false);
      this.queryErrors = this.errorMessages();
      this.hasQueryErrors.set(true);
      return;
    }

    this.autorun(() => {
      const handle = subManager.subscribe(
        'globalSearch',
        SessionData.getSessionId(),
        params,
      );
      Tracker.nonreactive(() => {
        Tracker.autorun(() => {
          if (handle.ready()) {
            this.getResults();
            this.searching.set(false);
            this.hasResults.set(true);
          }
        });
      });
    });
  },

  getResultsHeading() {
    if (this.resultsCount === 0) {
      return TAPi18n.__('no-cards-found');
    } else if (this.resultsCount === 1) {
      return TAPi18n.__('one-card-found');
    } else if (this.resultsCount === this.totalHits) {
      return TAPi18n.__('n-cards-found', this.resultsCount);
    }

    return TAPi18n.__('n-n-of-n-cards-found', {
      start: 1,
      end: this.resultsCount,
      total: this.totalHits,
    });
  },

  getSearchHref() {
    const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
    return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
  },

  searchInstructions() {
    tags = {
      operator_board: TAPi18n.__('operator-board'),
      operator_list: TAPi18n.__('operator-list'),
      operator_swimlane: TAPi18n.__('operator-swimlane'),
      operator_label: TAPi18n.__('operator-label'),
      operator_label_abbrev: TAPi18n.__('operator-label-abbrev'),
      operator_user: TAPi18n.__('operator-user'),
      operator_user_abbrev: TAPi18n.__('operator-user-abbrev'),
      operator_member: TAPi18n.__('operator-member'),
      operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
      operator_assignee: TAPi18n.__('operator-assignee'),
      operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
    };

    text = `# ${TAPi18n.__('globalSearch-instructions-heading')}`;
    text += `\n${TAPi18n.__('globalSearch-instructions-description', tags)}`;
    text += `\n${TAPi18n.__('globalSearch-instructions-operators', tags)}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-board',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-list',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-swimlane',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-label',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-hash',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-user',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-operator-at', tags)}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-member',
      tags,
    )}`;
    text += `\n* ${TAPi18n.__(
      'globalSearch-instructions-operator-assignee',
      tags,
    )}`;

    text += `\n## ${TAPi18n.__('heading-notes')}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-1', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-2', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-3', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-4', tags)}`;
    text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-5', tags)}`;

    return text;
  },

  labelColors() {
    return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map(
      color => {
        return { color, name: TAPi18n.__(`color-${color}`) };
      },
    );
  },

  events() {
    return [
      {
        'submit .js-search-query-form'(evt) {
          evt.preventDefault();
          this.searchAllBoards(evt.target.searchQuery.value);
        },
        'click .js-label-color'(evt) {
          evt.preventDefault();
          const input = document.getElementById('global-search-input');
          this.query.set(
            `${input.value} ${TAPi18n.__('operator-label')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
        'click .js-board-title'(evt) {
          evt.preventDefault();
          const input = document.getElementById('global-search-input');
          this.query.set(
            `${input.value} ${TAPi18n.__('operator-board')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
        'click .js-list-title'(evt) {
          evt.preventDefault();
          const input = document.getElementById('global-search-input');
          this.query.set(
            `${input.value} ${TAPi18n.__('operator-list')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
        'click .js-label-name'(evt) {
          evt.preventDefault();
          const input = document.getElementById('global-search-input');
          this.query.set(
            `${input.value} ${TAPi18n.__('operator-label')}:"${
              evt.currentTarget.textContent
            }"`,
          );
          document.getElementById('global-search-input').focus();
        },
      },
    ];
  },
}).register('globalSearch');
<|endoftext|>


<commit_before>var convert = require('convert');
var hogan = require('hogan.js');
var session = require('session');
var toSentenceCase = require('to-sentence-case');
var view = require('view');

var rowTemplate = require('./row.html');
var template = require('./template.html');

var row = hogan.compile(rowTemplate);

var View = module.exports = view(template);

/**
 * To/from
 */

View.prototype.from = function() {
  return session.plan().from().split(',')[0];
};
View.prototype.to = function() {
  return session.plan().to().split(',')[0];
};

/**
 * Details, details
 */

View.prototype.directions = function() {
  var access = this.model.access()[0];
  var egress = this.model.egress();
  var segments = this.model.transit();
  var length = segments.length;
  var details = '';

  // Add a detail
  function addDetail(d) {
    details += row.render(d);
  }

  details += narrativeDirections(access.streetEdges);

  // Add transit segments
  var transferType = true;
  var lastColor = null;
  for (var i = 0; i < length; i++) {
    var segment = segments[i];
    var fromName = segment.fromName;
    var patterns = segment.segmentPatterns;
    var color = patterns[0].color;

    // Check for a walking distance to see if you are boarding or transferring
    if (segment.walkTime !== 0 || i === 0) {
      if (i > 0) {
        addDetail({
          description: 'Walk ' + (Math.ceil(segment.walkTime / 60) + 1) + ' min',
          icon: 'walk'
        });
      }

      addDetail({
        color: color,
        description: strong(fromName),
        transfer: 'transfer board'
      });
    } else {
      addDetail({
        color: 'linear-gradient(to bottom, ' + lastColor + ' 0%, ' +
          lastColor + ' 50%,' + color + ' 50%, ' + color + ' 100%)',
        description: strong(fromName),
        transfer: 'transfer'
      });
    }

    addDetail({
      color: color,
      description: 'Take ' + getUniquePatternNames(patterns).map(strong).join(' / '),
      segment: true
    });

    // Check if you are debaording
    if (i + 1 >= length || segments[i + 1].walkTime > 0) {
      addDetail({
        color: color,
        description: strong(segment.toName),
        transfer: 'transfer alight'
      });
    }

    lastColor = color;
  }

  if (egress && egress.length > 0) {
    details += narrativeDirections(egress[0].streetEdges);
  }

  return details;
};

function getUniquePatternNames(patterns) {
  return patterns.map(function(p) {
      return p.shortName;
    })
    .reduce(function(names, name) {
      if (names.indexOf(name) === -1) names.push(name);
      return names;
    }, []);
}

function strong(s) {
  return '' + s + '';
}

/**
 * Add narrative directions
 */

function narrativeDirections(edges) {
  if (!edges) return '';

  return edges.map(function(se) {
    if (!se.streetName && !se.bikeRentalOffStation) return '';

    var step = {};
    if (se.mode) {
      if (se.bikeRentalOnStation) {
        step.description = 'Rent bike from ' + se.bikeRentalOnStation.name + ' and ride ' + se.absoluteDirection.toLowerCase() +
          ' on ' + se.streetName;
        step.icon = 'cabi';
      } else {
        step.description = MODE_TO_ACTION[se.mode] + ' ' + se.absoluteDirection.toLowerCase() + ' on ' + se.streetName;
        step.icon = MODE_TO_ICON[se.mode];
      }
    } else {
      if (se.bikeRentalOffStation) {
        step.description = 'Park bike at ' + se.bikeRentalOffStation.name;
        step.icon = 'cabi';
      } else {
        step.description = toSentenceCase(se.relativeDirection) + ' on ' + se.streetName;
        step.direction = DIRECTION_TO_CARDINALITY[se.relativeDirection];
      }
    }

    return row.render(step);
  }).join('');
}

var MODE_TO_ACTION = {
  BICYCLE: 'Bike',
  BICYCLE_RENT: 'Bike',
  CAR: 'Drive',
  WALK: 'Walk'
};

var MODE_TO_ICON = {
  BICYCLE: 'bike',
  BICYCLE_RENT: 'cabi',
  CAR: 'car',
  WALK: 'walk'
};

var DIRECTION_TO_CARDINALITY = {
  HARD_LEFT: 'west',
  HARD_RIGHT: 'east',
  RIGHT: 'east',
  LEFT: 'west',
  CONTINUE: 'north',
  SLIGHTLY_RIGHT: 'northeast',
  SLIGHTLY_LEFT: 'northwest'
};
<commit_msg>Use longName if shortName does not exist<commit_after>var convert = require('convert');
var hogan = require('hogan.js');
var session = require('session');
var toSentenceCase = require('to-sentence-case');
var view = require('view');

var rowTemplate = require('./row.html');
var template = require('./template.html');

var row = hogan.compile(rowTemplate);

var View = module.exports = view(template);

/**
 * To/from
 */

View.prototype.from = function() {
  return session.plan().from().split(',')[0];
};
View.prototype.to = function() {
  return session.plan().to().split(',')[0];
};

/**
 * Details, details
 */

View.prototype.directions = function() {
  var access = this.model.access()[0];
  var egress = this.model.egress();
  var segments = this.model.transit();
  var length = segments.length;
  var details = '';

  // Add a detail
  function addDetail(d) {
    details += row.render(d);
  }

  details += narrativeDirections(access.streetEdges);

  // Add transit segments
  var transferType = true;
  var lastColor = null;
  for (var i = 0; i < length; i++) {
    var segment = segments[i];
    var fromName = segment.fromName;
    var patterns = segment.segmentPatterns;
    var color = patterns[0].color;

    // Check for a walking distance to see if you are boarding or transferring
    if (segment.walkTime !== 0 || i === 0) {
      if (i > 0) {
        addDetail({
          description: 'Walk ' + (Math.ceil(segment.walkTime / 60) + 1) + ' min',
          icon: 'walk'
        });
      }

      addDetail({
        color: color,
        description: strong(fromName),
        transfer: 'transfer board'
      });
    } else {
      addDetail({
        color: 'linear-gradient(to bottom, ' + lastColor + ' 0%, ' +
          lastColor + ' 50%,' + color + ' 50%, ' + color + ' 100%)',
        description: strong(fromName),
        transfer: 'transfer'
      });
    }

    addDetail({
      color: color,
      description: 'Take ' + getUniquePatternNames(patterns).map(strong).join(' / '),
      segment: true
    });

    // Check if you are debaording
    if (i + 1 >= length || segments[i + 1].walkTime > 0) {
      addDetail({
        color: color,
        description: strong(segment.toName),
        transfer: 'transfer alight'
      });
    }

    lastColor = color;
  }

  if (egress && egress.length > 0) {
    details += narrativeDirections(egress[0].streetEdges);
  }

  return details;
};

function getUniquePatternNames(patterns) {
  return patterns.map(function(p) {
      return p.shortName || p.longName;
    })
    .reduce(function(names, name) {
      if (names.indexOf(name) === -1) names.push(name);
      return names;
    }, []);
}

function strong(s) {
  return '' + s + '';
}

/**
 * Add narrative directions
 */

function narrativeDirections(edges) {
  if (!edges) return '';

  return edges.map(function(se) {
    if (!se.streetName && !se.bikeRentalOffStation) return '';

    var step = {};
    if (se.mode) {
      if (se.bikeRentalOnStation) {
        step.description = 'Rent bike from ' + se.bikeRentalOnStation.name + ' and ride ' + se.absoluteDirection.toLowerCase() +
          ' on ' + se.streetName;
        step.icon = 'cabi';
      } else {
        step.description = MODE_TO_ACTION[se.mode] + ' ' + se.absoluteDirection.toLowerCase() + ' on ' + se.streetName;
        step.icon = MODE_TO_ICON[se.mode];
      }
    } else {
      if (se.bikeRentalOffStation) {
        step.description = 'Park bike at ' + se.bikeRentalOffStation.name;
        step.icon = 'cabi';
      } else {
        step.description = toSentenceCase(se.relativeDirection) + ' on ' + se.streetName;
        step.direction = DIRECTION_TO_CARDINALITY[se.relativeDirection];
      }
    }

    return row.render(step);
  }).join('');
}

var MODE_TO_ACTION = {
  BICYCLE: 'Bike',
  BICYCLE_RENT: 'Bike',
  CAR: 'Drive',
  WALK: 'Walk'
};

var MODE_TO_ICON = {
  BICYCLE: 'bike',
  BICYCLE_RENT: 'cabi',
  CAR: 'car',
  WALK: 'walk'
};

var DIRECTION_TO_CARDINALITY = {
  HARD_LEFT: 'west',
  HARD_RIGHT: 'east',
  RIGHT: 'east',
  LEFT: 'west',
  CONTINUE: 'north',
  SLIGHTLY_RIGHT: 'northeast',
  SLIGHTLY_LEFT: 'northwest'
};
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import {Button, Grid, Row, Col} from 'react-bootstrap'
import utils from 'utils'

import LinkTo from 'components/LinkTo'
import {Report, Person, Organization} from 'models'

import moment from 'moment'

export default class ReportSummary extends Component {
	static propTypes = {
		report: PropTypes.object.isRequired,
	}

	render() {
		let report = new Report(this.props.report)

		return <Grid fluid className="report-summary">
			<Row>
				<Col md={6}>
					{report.advisorOrg &&
						<LinkTo organization={new Organization(report.advisorOrg)} />
					}
					{report.principalOrg && "-> "}
					{report.principalOrg &&
						<LinkTo organization={new Organization(report.principalOrg)} />
					}
				</Col>
				<Col md={6}>
					{report.engagementDate && moment(report.engagementDate).format("D MMM YYYY")}
					{report.location &&
						 @
							<LinkTo location={report.location} />

					}
				</Col>
			</Row>
			<Row>
				<Col md={6}>{report.primaryAdvisor && this.renderPerson(report.primaryAdvisor)}</Col>
				<Col md={6}>{report.primaryPrincipal && this.renderPerson(report.primaryPrincipal)}</Col>
			</Row>
			{report.cancelledReason &&
				<Row>
					<Col md={12}>
						Cancelled for: {utils.sentenceCase(report.cancelledReason)}
					</Col>
				</Row>
			}
			<Row>
				<Col md={8}>

{report.intent}

					{report.keyOutcomes &&
Key outcomes: {report.keyOutcomes}
}
					{report.nextSteps &&
Next steps: {report.nextSteps}
}
				</Col>
			</Row>
			<LinkTo report={report} className="pull-right" ><Button>Read Full Report</Button></LinkTo>
		</Grid>
	}

	renderPerson(person) {
		person = new Person(person);
		return

			<LinkTo person={person} />
			{person.position && person.position.organization &&
				 -
				<LinkTo organization={new Organization(person.position.organization)} />

			}

	}
}
<commit_msg>Fix class name on Read Full Report button<commit_after>import React, {Component, PropTypes} from 'react'
import {Button, Grid, Row, Col} from 'react-bootstrap'
import utils from 'utils'

import LinkTo from 'components/LinkTo'
import {Report, Person, Organization} from 'models'

import moment from 'moment'

export default class ReportSummary extends Component {
	static propTypes = {
		report: PropTypes.object.isRequired,
	}

	render() {
		let report = new Report(this.props.report)

		return <Grid fluid className="report-summary">
			<Row>
				<Col md={6}>
					{report.advisorOrg &&
						<LinkTo organization={new Organization(report.advisorOrg)} />
					}
					{report.principalOrg && "-> "}
					{report.principalOrg &&
						<LinkTo organization={new Organization(report.principalOrg)} />
					}
				</Col>
				<Col md={6}>
					{report.engagementDate && moment(report.engagementDate).format("D MMM YYYY")}
					{report.location &&
						 @
							<LinkTo location={report.location} />

					}
				</Col>
			</Row>
			<Row>
				<Col md={6}>{report.primaryAdvisor && this.renderPerson(report.primaryAdvisor)}</Col>
				<Col md={6}>{report.primaryPrincipal && this.renderPerson(report.primaryPrincipal)}</Col>
			</Row>
			{report.cancelledReason &&
				<Row>
					<Col md={12}>
						Cancelled for: {utils.sentenceCase(report.cancelledReason)}
					</Col>
				</Row>
			}
			<Row>
				<Col md={8}>

{report.intent}

					{report.keyOutcomes &&
Key outcomes: {report.keyOutcomes}
}
					{report.nextSteps &&
Next steps: {report.nextSteps}
}
				</Col>
			</Row>
			<LinkTo report={report} className="read-full"><Button>Read Full Report</Button></LinkTo>
		</Grid>
	}

	renderPerson(person) {
		person = new Person(person);
		return

			<LinkTo person={person} />
			{person.position && person.position.organization &&
				 -
				<LinkTo organization={new Organization(person.position.organization)} />

			}

	}
}
<|endoftext|>


<commit_before>/*global ODSA */
"use strict";
// Sequential Tree serialization visualization slideshow
$(document).ready(function () {
  var av_name = "SequentialTreeCON";
  var av = new JSAV(av_name);
  var temp1;
  var msg = av.label(" A B / D / / C E G / / / F H / / I / /",{bottom: 50});
  var bt = av.ds.binarytree({visible: true, nodegap: 35});
  bt.root('A');
  var cur = av.g.rect(0, 338,13, 28);
  var a = bt.root();
  //BEGIN TEST
  a.left('B'); //<--- HERE IS THE LINE IN QUESTION
  var b = a.left();
  var d = a.left().right('D');
  var c = a.right('C');
  var e = a.right().left('E');
  var g = a.right().left().left('G');
  var f = a.right().right('F');
  var h = a.right().right().left('H');
  var i = a.right().right().right('I');
  b.hide();
  d.hide();
  c.hide();
  e.hide();
  g.hide();
  f.hide();
  h.hide();
  i.hide();
  //END TEST
  bt.layout();

  var ptr = av.pointer("rt", a, {anchor: "middle top", top: -10});

  //Slide 1
  av.umsg("We begin with the first node in the string 'A' which will be the root node");
  av.displayInit();

  //Slide 2
  av.umsg("The next character in the serialized string represents A's left child");
  cur.hide();
  var cur = av.g.rect(14, 338,13, 28);
  av.step();

  //Slide 3
  av.umsg("We insert B as the left child of A");
  b.show();
  bt.layout();
  ptr.target(b);
  av.step();

  //Slide 4
  av.umsg("The next character in the serialized string says B has no left child ('/') ");
  cur.hide();
  var cur = av.g.rect(24, 338,13, 28);
  av.step();

  //Slide 5
  av.umsg("The next token 'D' is the right child of 'B' ");
  d.show();
  ptr.target(d);
  cur.hide();
  var cur = av.g.rect(36, 338,13, 28);
  //point to D
  av.step();

  //Slide 6
  cur.hide();
  var cur = av.g.rect(49, 338,18, 28);
  av.umsg("The two slashes imply D has no children and is a leaf node");
  av.step();

  //Slide 7
  av.umsg("We pop back up to the parent of D");
  //point to B
  ptr.target(b);
  av.step();

  //Slide 8
  av.umsg("Since we have already processed both of B's children, we continue popping up to the root.");
  //point to A
  ptr.target(a);
  av.step();

  //Slide 9
  av.umsg("The next character in the string represents A's right child 'C' ");
  c.show();
  ptr.target(c);
  cur.hide();
  var cur = av.g.rect(68, 338,13, 28);
  //point to C
  av.step();

  //Slide 10
  av.umsg("'E' must be C's left child");
  e.show();
  ptr.target(e);
  cur.hide();
  var cur = av.g.rect(82, 338,13, 28);
  //point to E
  av.step();

  //Slide 11
  av.umsg("The next character 'G' represents E's left child");
  g.show();
  ptr.target(g);
  cur.hide();
  var cur = av.g.rect(97, 338,13, 28);
  //point to G
  av.step();

  //Slide 12
  av.umsg("Double slashes implies G has no children");
  cur.hide();
  var cur = av.g.rect(112, 338,17, 28);
  av.step();

  //Slide 13
  av.umsg("Pop back up to G's parent ('E') ");
  ptr.target(e);
  //point to E
  av.step();

  //Slide 14
  av.umsg("The next character in the serialized string ('/') represents E's right child");
  cur.hide();
  var cur = av.g.rect(126, 338,13, 28);
  av.step();

  //Slide 15
  av.umsg("It is a slash, so no right child for E");
  av.step();

  //Slide 16
  av.umsg("We pop back up to E's parent ('C') ");
  ptr.target(c);
  //point to C
  av.step();

  //Slide 17
  av.umsg("F represents C's right child");
  f.show();
  ptr.target(f);
  cur.hide();
  var cur = av.g.rect(138, 338,13, 28);
  //point to F
  av.step();

  //Slide 18
  av.umsg("H represents F's left child");
  h.show();
  ptr.target(h);
  cur.hide();
  var cur = av.g.rect(152, 338,13, 28);
  //point to H
  av.step();

  //Slide 19
  av.umsg("Double slash implies H is a leaf node with no children. Pop back up to F");
  ptr.target(f);
  cur.hide();
  var cur = av.g.rect(165, 338,17, 28);
  av.step();

  //Slide 20
  av.umsg("I must be the right child of F");
  i.show();
  ptr.target(i);
  //point to I
  cur.hide();
  var cur = av.g.rect(181, 338,11, 28);
  av.step();

  //Slide 21
  av.umsg("Double slashes implies I is a leaf node with no children");
  cur.hide();
  var cur = av.g.rect(191, 338,17, 28);
  av.step();
  av.recorded();

});
<commit_msg>Setting up SequentialTreeCON test<commit_after>/*global ODSA */
"use strict";
// Sequential Tree serialization visualization slideshow
$(document).ready(function () {
  var av_name = "SequentialTreeCON";
  var av = new JSAV(av_name);
  var temp1;
  var msg = av.label(" A B / D / / C E G / / / F H / / I / /",{bottom: 50});
  var bt = av.ds.binarytree({visible: true, nodegap: 35});
  bt.root('A');
  var cur = av.g.rect(0, 338, 13, 28);
  var a = bt.root();
  //BEGIN TEST
  a.left('B'); //<--- HERE IS THE LINE IN QUESTION
  var b = a.left();
  var d = a.left().right('D');
  var c = a.right('C');
  var e = a.right().left('E');
  var g = a.right().left().left('G');
  var f = a.right().right('F');
  var h = a.right().right().left('H');
  var i = a.right().right().right('I');
  bt.layout();

  av.umsg("Test");
  av.displayInit();

  b.hide();
  d.hide();
  c.hide();
  e.hide();
  g.hide();
  f.hide();
  h.hide();
  i.hide();
  //END TEST
  av.umsg("Test 2");
  av.step();

  var ptr = av.pointer("rt", a, {anchor: "middle top", top: -10});

  //Slide 1
  av.umsg("We begin with the first node in the string 'A' which will be the root node");
  av.step();

  //Slide 2
  av.umsg("The next character in the serialized string represents A's left child");
  cur.hide();
  var cur = av.g.rect(14, 338, 13, 28);
  av.step();

  //Slide 3
  av.umsg("We insert B as the left child of A");
  b.show();
  ptr.target(b);
  av.step();

  //Slide 4
  av.umsg("The next character in the serialized string says B has no left child ('/') ");
  cur.hide();
  var cur = av.g.rect(24, 338,13, 28);
  av.step();

  //Slide 5
  av.umsg("The next token 'D' is the right child of 'B' ");
  d.show();
  ptr.target(d);
  cur.hide();
  var cur = av.g.rect(36, 338,13, 28);
  //point to D
  av.step();

  //Slide 6
  cur.hide();
  var cur = av.g.rect(49, 338,18, 28);
  av.umsg("The two slashes imply D has no children and is a leaf node");
  av.step();

  //Slide 7
  av.umsg("We pop back up to the parent of D");
  //point to B
  ptr.target(b);
  av.step();

  //Slide 8
  av.umsg("Since we have already processed both of B's children, we continue popping up to the root.");
  //point to A
  ptr.target(a);
  av.step();

  //Slide 9
  av.umsg("The next character in the string represents A's right child 'C' ");
  c.show();
  ptr.target(c);
  cur.hide();
  var cur = av.g.rect(68, 338,13, 28);
  //point to C
  av.step();

  //Slide 10
  av.umsg("'E' must be C's left child");
  e.show();
  ptr.target(e);
  cur.hide();
  var cur = av.g.rect(82, 338,13, 28);
  //point to E
  av.step();

  //Slide 11
  av.umsg("The next character 'G' represents E's left child");
  g.show();
  ptr.target(g);
  cur.hide();
  var cur = av.g.rect(97, 338,13, 28);
  //point to G
  av.step();

  //Slide 12
  av.umsg("Double slashes implies G has no children");
  cur.hide();
  var cur = av.g.rect(112, 338,17, 28);
  av.step();

  //Slide 13
  av.umsg("Pop back up to G's parent ('E') ");
  ptr.target(e);
  //point to E
  av.step();

  //Slide 14
  av.umsg("The next character in the serialized string ('/') represents E's right child");
  cur.hide();
  var cur = av.g.rect(126, 338,13, 28);
  av.step();

  //Slide 15
  av.umsg("It is a slash, so no right child for E");
  av.step();

  //Slide 16
  av.umsg("We pop back up to E's parent ('C') ");
  ptr.target(c);
  //point to C
  av.step();

  //Slide 17
  av.umsg("F represents C's right child");
  f.show();
  ptr.target(f);
  cur.hide();
  var cur = av.g.rect(138, 338,13, 28);
  //point to F
  av.step();

  //Slide 18
  av.umsg("H represents F's left child");
  h.show();
  ptr.target(h);
  cur.hide();
  var cur = av.g.rect(152, 338,13, 28);
  //point to H
  av.step();

  //Slide 19
  av.umsg("Double slash implies H is a leaf node with no children. Pop back up to F");
  ptr.target(f);
  cur.hide();
  var cur = av.g.rect(165, 338,17, 28);
  av.step();

  //Slide 20
  av.umsg("I must be the right child of F");
  i.show();
  ptr.target(i);
  //point to I
  cur.hide();
  var cur = av.g.rect(181, 338,11, 28);
  av.step();

  //Slide 21
  av.umsg("Double slashes implies I is a leaf node with no children");
  cur.hide();
  var cur = av.g.rect(191, 338,17, 28);
  av.step();
  av.recorded();

});
<|endoftext|>


<commit_before>var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepairer = require('role.repairer');

module.exports.loop = function () {

    // Always place this memory cleaning code at the very top of your main loop!

    for (var dead in Memory.creeps) {
        if (!Game.creeps[dead]) {
            delete Memory.creeps[dead];
        }
    }

    var harvesters = _.filter(Game.creeps, (creep) = > creep.memory.role == 'harvester'
    )
    if (harvesters.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'harvester'});
    }

    var builders = _.filter(Game.creeps, (creep) = > creep.memory.role == 'builder'
    )
    if (builders.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'builder'});
    }

    var upgraders = _.filter(Game.creeps, (creep) = > creep.memory.role == 'upgrader'
    )
    if (upgraders.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'upgrader'});
    }

    var repairers = _.filter(Game.creeps, (creep) = > creep.memory.role == 'repairer'
    )
    if (repairers.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'repairer', isRepairing:false});
    }

    for (var c in Game.creeps) {
        var creep = Game.creeps[c];
        if (creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if (creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        if (creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
        if(creep.memory.role == 'repairer')
        {
            roleRepairer.run(creep);
        }
    }
};;;;;
<commit_msg>Cleans up code properly this time.<commit_after>var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleRepairer = require('role.repairer');

module.exports.loop = function () {

    // Always place this memory cleaning code at the very top of your main loop!

    for (var dead in Memory.creeps) {
        if (!Game.creeps[dead]) {
            delete Memory.creeps[dead];
        }
    }

    var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
    if (harvesters.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'harvester'});
    }

    var builders = _.filter(Game.creeps, (creep) => creep.memory.role == 'builder');
    if (builders.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'builder'});
    }

    var upgraders = _.filter(Game.creeps, (creep) => creep.memory.role == 'upgrader');
    if (upgraders.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'upgrader'});
    }

    var repairers = _.filter(Game.creeps, (creep) => creep.memory.role == 'repairer');
    if (repairers.length < 4) {
        Game.spawns.Spawn1.createCreep([WORK, CARRY, MOVE], undefined, {role: 'repairer', isRepairing:false});
    }

    for (var c in Game.creeps) {
        var creep = Game.creeps[c];
        if (creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if (creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        if (creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
        if(creep.memory.role == 'repairer')
        {
            roleRepairer.run(creep);
        }
    }
};
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var questionSchema = new mongoose.Schema({
    author: {
        type:mongoose.Schema.Types.ObjectId,
        ref:'User'
    },
    makeWith: String,
    language: String,
    question: [{
        type: {type: String},
        questionText: {type: String},
        image: {type: String},
        answers: [{
            text: String,
            url: String,
            attributesForTForMultiple: {
                isItRight: Boolean
            },
            attributesForSorting: {
                position: Number
            },
            attributesForLinking: {
                text1: String,
                text2: String,
                url1: String,
                url2: String
            },
            attributesForClickableArea: {
                x: Number,
                y: Number
            },
            attributesForEmptySpaces: {
                wordNumber: Number
            }
        }],
    }],
    keywords: [String],
    level: {type:Number, default: 500},
    totalAnswers: {type:Number, default: 0},
    correctAnswers: {type:Number, default: 0},
});

questionSchema.statics.createQuestion=function(author,question, callback){
    question.author = author
    var new_question = new this(question);
    return new_question.save(callback);
};

questionSchema.statics.getQuestion=function(questionId,callback) {
    return this.findOne({'_id': questionId},'makeWith language question -question._id', callback);
}

questionSchema.statics.getQuestions=function(author, callback){
    return this.find({'author': author},'_id makeWith language question.type question.questionText', callback);
};

questionSchema.statics.editQuestion=function(question,callback){
    return this.findOneAndUpdate({'_id' : question._id}, question, callback)
};

questionSchema.statics.updateLevel=function(questionId,userLevel,isCorrected,callback){
    this.findOne({_id:questionId}, function(err,question){
        console.log(userLevel)
        if(err){
            return next(err);
        }
        var oldDifficult = question.level;
        var differentLevel = oldDifficult - userLevel;
        // caso in cui la domanda sia piÃ¹ difficile dell'abilitÃ  dell'utente:
        if(differentLevel <= 100 && differentLevel > 0){
            var scarto = oldDifficult - userLevel;
            if(isCorrected == true){
                if(scarto > 90){
                    question.level = oldDifficult + 11;
                }else if(scarto > 80){
                    question.level = oldDifficult + 10;
                }else if(scarto > 70){
                    question.level = oldDifficult + 9;
                }else if(scarto > 60){
                    question.level = oldDifficult + 8;
                }else if(scarto > 50){
                    question.level = oldDifficult + 7;
                }else if(scarto > 40){
                    question.level = oldDifficult + 6;
                }else if(scarto > 30){
                    question.level = oldDifficult + 5;
                }else if(scarto > 20){
                    question.level = oldDifficult + 4;
                }else if(scarto > 10){
                    question.level = oldDifficult + 3;
                }else if(scarto > 0){
                    question.level = oldDifficult + 2;
                }
            } else{
                if(scarto > 90){
                    question.level = oldDifficult - 2;
                }else if(scarto > 80){
                    question.level = oldDifficult - 3;
                }else if(scarto > 70){
                    question.level = oldDifficult - 4;
                }else if(scarto > 60){
                    question.level = oldDifficult - 5;
                }else if(scarto > 50){
                    question.level = oldDifficult - 6;
                }else if(scarto > 40){
                    question.level = oldDifficult - 7;
                }else if(scarto > 30){
                    question.level = oldDifficult - 8;
                }else if(scarto > 20){
                    question.level = oldDifficult - 9;
                }else if(scarto > 10){
                    question.level = oldDifficult - 10;
                }else if(scarto > 0){
                    question.level = oldDifficult - 11;
                }
            }
        }
        else{
            // caso in cui la domanda sia più facile dell'abilità  dell'utente
            var scarto = userLevel - oldDifficult;
            console.log(scarto)
            if(isCorrected == true){
                if(scarto > 90){
                    question.level = oldDifficult - 2;
                }else if(scarto > 80){
                    question.level = oldDifficult - 3;
                }else if(scarto > 70){
                    question.level = oldDifficult - 4;
                }else if(scarto > 60){
                    question.level = oldDifficult - 5;
                }else if(scarto > 50){
                    question.level = oldDifficult - 6;
                }else if(scarto > 40){
                    question.level = oldDifficult - 7;
                }else if(scarto > 30){
                    question.level = oldDifficult - 8;
                }else if(scarto > 20){
                    question.level = oldDifficult - 9;
                }else if(scarto > 10){
                    question.level = oldDifficult - 10;
                }else if(scarto > 0){
                    question.level = oldDifficult - 11;
                }else if(scarto == 0){
                    question.level = oldDifficult - 1;
                }
            } else{
                if(scarto > 90){
                    question.level = oldDifficult + 11;
                }else if(scarto > 80){
                    question.level = oldDifficult + 10;
                }else if(scarto > 70){
                    question.level = oldDifficult + 9;
                }else if(scarto > 60){
                    question.level = oldDifficult + 8;
                }else if(scarto > 50){
                    question.level = oldDifficult + 7;
                }else if(scarto > 40){
                    question.level = oldDifficult + 6;
                }else if(scarto > 30){
                    question.level = oldDifficult + 5;
                }else if(scarto > 20){
                    question.level = oldDifficult + 4;
                }else if(scarto > 10){
                    question.level = oldDifficult + 3;
                }else if(scarto > 0){
                    question.level = oldDifficult + 2;
                }else if(scarto == 0){
                    question.level = oldDifficult + 1;
                }
            }
        }
        // controllo che il livello non sia oltre i limiti
        if(question.level > 1000){
            question.level = 1000;
        }
        else if(question.level < 0){
            question.level = 0;
        }
        return question.save(callback)
    })

}

questionSchema.statics.addKeyword=function(questionId,keyword,callback){

}

questionSchema.statics.addCorrect=function(questionId,callback){
    this.findOneAndUpdate({_id: questionId},{ $inc: { correctAnswers: 1 }},callback)

}

questionSchema.statics.addTotal=function(questionId,callback){
    this.findOneAndUpdate({_id: questionId},{ $inc: { totalAnswers: 1 }},callback)
}

module.exports = mongoose.model('Question', questionSchema);<commit_msg>Question model updated<commit_after>var mongoose = require('mongoose');
var questionSchema = new mongoose.Schema({
    author: {
        type:mongoose.Schema.Types.ObjectId,
        ref:'User'
    },
    makeWith: String,
    language: String,
    question: [{
        type: {type: String},
        questionText: {type: String},
        image: {type: String},
        answers: [{
            text: String,
            url: String,
            attributesForTForMultiple: {
                isItRight: Boolean
            },
            attributesForSorting: {
                position: Number
            },
            attributesForLinking: {
                text1: String,
                text2: String,
                url1: String,
                url2: String
            },
            attributesForClickableArea: {
                x: Number,
                y: Number
            },
            attributesForEmptySpaces: {
                wordNumber: Number
            }
        }],
    }],
    keywords: [String],
    level: {type:Number, default: 500},
    totalAnswers: {type:Number, default: 0},
    correctAnswers: {type:Number, default: 0},
});

questionSchema.statics.createQuestion=function(author,question, callback){
    question.author = author
    var new_question = new this(question);
    return new_question.save(callback);
};

questionSchema.statics.getQuestion=function(questionId,callback) {
    return this.findOne({'_id': questionId},'makeWith language question', callback);
}

questionSchema.statics.getQuestions=function(author, callback){
    return this.find({'author': author},'_id makeWith language question.type question.questionText', callback);
};

questionSchema.statics.editQuestion=function(question,callback){
    return this.findOneAndUpdate({'_id' : question._id}, question, callback)
};

questionSchema.statics.updateLevel=function(questionId,userLevel,isCorrected,callback){
    this.findOne({_id:questionId}, function(err,question){
        console.log(userLevel)
        if(err){
            return next(err);
        }
        var oldDifficult = question.level;
        var differentLevel = oldDifficult - userLevel;
        // caso in cui la domanda sia piÃ¹ difficile dell'abilitÃ  dell'utente:
        if(differentLevel <= 100 && differentLevel > 0){
            var scarto = oldDifficult - userLevel;
            if(isCorrected == true){
                if(scarto > 90){
                    question.level = oldDifficult + 11;
                }else if(scarto > 80){
                    question.level = oldDifficult + 10;
                }else if(scarto > 70){
                    question.level = oldDifficult + 9;
                }else if(scarto > 60){
                    question.level = oldDifficult + 8;
                }else if(scarto > 50){
                    question.level = oldDifficult + 7;
                }else if(scarto > 40){
                    question.level = oldDifficult + 6;
                }else if(scarto > 30){
                    question.level = oldDifficult + 5;
                }else if(scarto > 20){
                    question.level = oldDifficult + 4;
                }else if(scarto > 10){
                    question.level = oldDifficult + 3;
                }else if(scarto > 0){
                    question.level = oldDifficult + 2;
                }
            } else{
                if(scarto > 90){
                    question.level = oldDifficult - 2;
                }else if(scarto > 80){
                    question.level = oldDifficult - 3;
                }else if(scarto > 70){
                    question.level = oldDifficult - 4;
                }else if(scarto > 60){
                    question.level = oldDifficult - 5;
                }else if(scarto > 50){
                    question.level = oldDifficult - 6;
                }else if(scarto > 40){
                    question.level = oldDifficult - 7;
                }else if(scarto > 30){
                    question.level = oldDifficult - 8;
                }else if(scarto > 20){
                    question.level = oldDifficult - 9;
                }else if(scarto > 10){
                    question.level = oldDifficult - 10;
                }else if(scarto > 0){
                    question.level = oldDifficult - 11;
                }
            }
        }
        else{
            // caso in cui la domanda sia più facile dell'abilità  dell'utente
            var scarto = userLevel - oldDifficult;
            console.log(scarto)
            if(isCorrected == true){
                if(scarto > 90){
                    question.level = oldDifficult - 2;
                }else if(scarto > 80){
                    question.level = oldDifficult - 3;
                }else if(scarto > 70){
                    question.level = oldDifficult - 4;
                }else if(scarto > 60){
                    question.level = oldDifficult - 5;
                }else if(scarto > 50){
                    question.level = oldDifficult - 6;
                }else if(scarto > 40){
                    question.level = oldDifficult - 7;
                }else if(scarto > 30){
                    question.level = oldDifficult - 8;
                }else if(scarto > 20){
                    question.level = oldDifficult - 9;
                }else if(scarto > 10){
                    question.level = oldDifficult - 10;
                }else if(scarto > 0){
                    question.level = oldDifficult - 11;
                }else if(scarto == 0){
                    question.level = oldDifficult - 1;
                }
            } else{
                if(scarto > 90){
                    question.level = oldDifficult + 11;
                }else if(scarto > 80){
                    question.level = oldDifficult + 10;
                }else if(scarto > 70){
                    question.level = oldDifficult + 9;
                }else if(scarto > 60){
                    question.level = oldDifficult + 8;
                }else if(scarto > 50){
                    question.level = oldDifficult + 7;
                }else if(scarto > 40){
                    question.level = oldDifficult + 6;
                }else if(scarto > 30){
                    question.level = oldDifficult + 5;
                }else if(scarto > 20){
                    question.level = oldDifficult + 4;
                }else if(scarto > 10){
                    question.level = oldDifficult + 3;
                }else if(scarto > 0){
                    question.level = oldDifficult + 2;
                }else if(scarto == 0){
                    question.level = oldDifficult + 1;
                }
            }
        }
        // controllo che il livello non sia oltre i limiti
        if(question.level > 1000){
            question.level = 1000;
        }
        else if(question.level < 0){
            question.level = 0;
        }
        return question.save(callback)
    })

}

questionSchema.statics.addKeyword=function(questionId,keyword,callback){

}

questionSchema.statics.addCorrect=function(questionId,callback){
    this.findOneAndUpdate({_id: questionId},{ $inc: { correctAnswers: 1 }},callback)

}

questionSchema.statics.addTotal=function(questionId,callback){
    this.findOneAndUpdate({_id: questionId},{ $inc: { totalAnswers: 1 }},callback)
}

module.exports = mongoose.model('Question', questionSchema);<|endoftext|>


<commit_before>//@fix Write documentation.
function B_PlaySound(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"play sound"));
	var dS=new DropSlot(this);
	for(var i=0;i<Sounds.getSoundCount();i++){
		dS.addOption(Sounds.getSoundName(i),new SelectionData(Sounds.getSoundId(i)));
	}
	this.addPart(dS);
}
B_PlaySound.prototype = Object.create(CommandBlock.prototype);
B_PlaySound.prototype.constructor = B_PlaySound;
B_PlaySound.prototype.startAction=function(){
	var soundData=this.slots[0].getData();
	if(soundData==null){
		return false;
	}
	var soundId=soundData.getValue();
	if(Sounds.checkIdIsValid(soundId)){
		var mem=this.runMem;
		mem.request = "sound/play/"+soundId;
		mem.requestStatus=function(){};
		HtmlServer.sendRequest(mem.request,mem.requestStatus);
		return true; //Still running
	}
	return false;
};
/* Wait for the request to finish. */
B_PlaySound.prototype.updateAction=function(){
	var mem=this.runMem;
	var status=mem.requestStatus;
	if(status.finished==true){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};

function B_PlaySoundUntilDone(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"play sound until done"));
	var dS=new DropSlot(this);
	for(var i=0;i<Sounds.getSoundCount();i++){
		dS.addOption(Sounds.getSoundName(i),new SelectionData(Sounds.getSoundId(i)));
	}
	this.addPart(dS);
}
B_PlaySoundUntilDone.prototype = Object.create(CommandBlock.prototype);
B_PlaySoundUntilDone.prototype.constructor = B_PlaySoundUntilDone;
B_PlaySoundUntilDone.prototype.startAction=function(){
	var soundData=this.slots[0].getData();
	if(soundData==null){
		return false;
	}
	var soundId=soundData.getValue();
	var soundIndex=Sounds.indexFromId(soundId);
	if(soundIndex>=0){
		var mem=this.runMem;
		mem.soundDuration=Sounds.getSoundDuration(soundIndex);
		mem.timerStarted=false;
		mem.request = "sound/play/"+soundId;
		mem.cancel=false;
		mem.requestStatus=function(){};
		HtmlServer.sendRequest(mem.request,mem.requestStatus);
		return true; //Still running
	}
	return false;
};
/* Wait for the request to finish. */
B_PlaySoundUntilDone.prototype.updateAction=function(){
	var mem=this.runMem;
	if(mem.cancel){
		return false;
	}
	if(!mem.timerStarted){
		var status=mem.requestStatus;
		if(status.finished==true){
			mem.startTime=new Date().getTime();
			mem.timerStarted=true;
		}
		else{
			return true; //Still running
		}
	}
	if(new Date().getTime()>=mem.startTime+mem.soundDuration){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};
B_PlaySoundUntilDone.prototype.stopAllSounds=function(){
	if(this.runMem!=null) {
		this.runMem.cancel = true;
	}
};

function B_StopAllSounds(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"stop all sounds"));
}
B_StopAllSounds.prototype = Object.create(CommandBlock.prototype);
B_StopAllSounds.prototype.constructor = B_StopAllSounds;
B_StopAllSounds.prototype.startAction=function(){
	var mem=this.runMem;
	mem.request = "sound/stop";
	mem.requestStatus=function(){};
	HtmlServer.sendRequest(mem.request,mem.requestStatus);
	return true; //Still running
};
B_StopAllSounds.prototype.updateAction=function(){
	return !this.runMem.requestStatus.finished;
};

function B_RestForBeats(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"rest for"));
	this.addPart(new NumSlot(this,0.2,true)); //Positive
	this.addPart(new LabelText(this,"beats"));
}
B_RestForBeats.prototype = Object.create(CommandBlock.prototype);
B_RestForBeats.prototype.constructor = B_RestForBeats;
B_RestForBeats.prototype.startAction=function(){
	var mem=this.runMem;
	mem.startTime=new Date().getTime();
	var beats=this.slots[0].getData().getValueWithC(true); //Positive
	mem.delayTime=CodeManager.beatsToMs(beats);
	return true; //Still running
};
B_RestForBeats.prototype.updateAction=function(){
	var mem=this.runMem;
	if(new Date().getTime()>=mem.startTime+mem.delayTime){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};

function B_PlayNoteForBeats(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"play note"));
	this.addPart(new NumSlot(this,60,true,true)); //Positive integer
	this.addPart(new LabelText(this,"for"));
	this.addPart(new NumSlot(this,1,true)); //Positive
	this.addPart(new LabelText(this,"beats"));
}
B_PlayNoteForBeats.prototype = Object.create(CommandBlock.prototype);
B_PlayNoteForBeats.prototype.constructor = B_PlayNoteForBeats;
B_PlayNoteForBeats.prototype.startAction=function(){
	var mem=this.runMem;
	var note=this.slots[0].getData().getValueWithC(true,true);
	var beats=this.slots[1].getData().getValueWithC(true); //Positive
	mem.soundDuration=CodeManager.beatsToMs(beats);
	mem.request = "sound/note/"+note+"/"+mem.soundDuration;
	mem.timerStarted=false;
	mem.requestStatus=function(){};
	HtmlServer.sendRequest(mem.request,mem.requestStatus);
	return true; //Still running
};
B_PlayNoteForBeats.prototype.updateAction=function(){
	var mem=this.runMem;
	if(!mem.timerStarted){
		var status=mem.requestStatus;
		if(status.finished==true){
			mem.startTime=new Date().getTime();
			mem.timerStarted=true;
		}
		else{
			return true; //Still running
		}
	}
	if(new Date().getTime()>=mem.startTime+mem.soundDuration){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};

function B_ChangeTempoBy(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"change tempo by"));
	this.addPart(new NumSlot(this,20));
}
B_ChangeTempoBy.prototype = Object.create(CommandBlock.prototype);
B_ChangeTempoBy.prototype.constructor = B_ChangeTempoBy;
B_ChangeTempoBy.prototype.startAction=function(){
	var slotData=this.slots[0].getData();
	if(slotData.isValid) {
		var newTempo = CodeManager.sound.tempo +slotData.getValue();
		CodeManager.setSoundTempo(newTempo);
	}
	return false;
};

function B_SetTempoTo(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"set tempo to"));
	this.addPart(new NumSlot(this,60,true)); //Positive
	this.addPart(new LabelText(this,"bpm"));
}
B_SetTempoTo.prototype = Object.create(CommandBlock.prototype);
B_SetTempoTo.prototype.constructor = B_SetTempoTo;
B_SetTempoTo.prototype.startAction=function(){
	var slotData=this.slots[0].getData();
	if(slotData.isValid) {
		var newTempo = slotData.getValue();
		CodeManager.setSoundTempo(newTempo);
	}
	return false;
};

function B_Tempo(x,y){
	ReporterBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"tempo"));
}
B_Tempo.prototype = Object.create(ReporterBlock.prototype);
B_Tempo.prototype.constructor = B_Tempo;
B_Tempo.prototype.startAction=function(){
	this.resultData=new NumData(CodeManager.sound.tempo);
	return false;
};
<commit_msg>Update BlockDefs_sound.js<commit_after>//@fix Write documentation.
function B_PlaySound(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"play sound"));
	var dS=new DropSlot(this);
	for(var i=0;i<Sounds.getSoundCount();i++){
		dS.addOption(Sounds.getSoundName(i),new SelectionData(Sounds.getSoundName(i)));
	}
	this.addPart(dS);
}
B_PlaySound.prototype = Object.create(CommandBlock.prototype);
B_PlaySound.prototype.constructor = B_PlaySound;
B_PlaySound.prototype.startAction=function(){
	var soundData=this.slots[0].getData();
	if(soundData==null){
		return false;
	}
	var soundName=soundData.getValue();
	if(Sounds.checkNameIsValid(soundName)){
		var mem=this.runMem;
		mem.request = "sound/play/"+soundName;
		mem.requestStatus=function(){};
		HtmlServer.sendRequest(mem.request,mem.requestStatus);
		return true; //Still running
	}
	return false;
};
/* Wait for the request to finish. */
B_PlaySound.prototype.updateAction=function(){
	var mem=this.runMem;
	var status=mem.requestStatus;
	if(status.finished==true){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};

function B_PlaySoundUntilDone(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"play sound until done"));
	var dS=new DropSlot(this);
	for(var i=0;i<Sounds.getSoundCount();i++){
		dS.addOption(Sounds.getSoundName(i),new SelectionData(Sounds.getSoundName(i)));
	}
	this.addPart(dS);
}
B_PlaySoundUntilDone.prototype = Object.create(CommandBlock.prototype);
B_PlaySoundUntilDone.prototype.constructor = B_PlaySoundUntilDone;
B_PlaySoundUntilDone.prototype.startAction=function(){
	var soundData=this.slots[0].getData();
	if(soundData==null){
		return false;
	}
	var soundName=soundData.getValue();
	var soundIndex=Sounds.indexFromName(soundName);
	if(soundIndex>=0){
		var mem=this.runMem;
		mem.soundDuration=Sounds.getSoundDuration(soundIndex);
		mem.timerStarted=false;
		mem.request = "sound/play/"+soundName;
		mem.cancel=false;
		mem.requestStatus=function(){};
		HtmlServer.sendRequest(mem.request,mem.requestStatus);
		return true; //Still running
	}
	return false;
};
/* Wait for the request to finish. */
B_PlaySoundUntilDone.prototype.updateAction=function(){
	var mem=this.runMem;
	if(mem.cancel){
		return false;
	}
	if(!mem.timerStarted){
		var status=mem.requestStatus;
		if(status.finished==true){
			mem.startTime=new Date().getTime();
			mem.timerStarted=true;
		}
		else{
			return true; //Still running
		}
	}
	if(new Date().getTime()>=mem.startTime+mem.soundDuration){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};
B_PlaySoundUntilDone.prototype.stopAllSounds=function(){
	if(this.runMem!=null) {
		this.runMem.cancel = true;
	}
};

function B_StopAllSounds(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"stop all sounds"));
}
B_StopAllSounds.prototype = Object.create(CommandBlock.prototype);
B_StopAllSounds.prototype.constructor = B_StopAllSounds;
B_StopAllSounds.prototype.startAction=function(){
	var mem=this.runMem;
	mem.request = "sound/stop";
	mem.requestStatus=function(){};
	HtmlServer.sendRequest(mem.request,mem.requestStatus);
	return true; //Still running
};
B_StopAllSounds.prototype.updateAction=function(){
	return !this.runMem.requestStatus.finished;
};

function B_RestForBeats(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"rest for"));
	this.addPart(new NumSlot(this,0.2,true)); //Positive
	this.addPart(new LabelText(this,"beats"));
}
B_RestForBeats.prototype = Object.create(CommandBlock.prototype);
B_RestForBeats.prototype.constructor = B_RestForBeats;
B_RestForBeats.prototype.startAction=function(){
	var mem=this.runMem;
	mem.startTime=new Date().getTime();
	var beats=this.slots[0].getData().getValueWithC(true); //Positive
	mem.delayTime=CodeManager.beatsToMs(beats);
	return true; //Still running
};
B_RestForBeats.prototype.updateAction=function(){
	var mem=this.runMem;
	if(new Date().getTime()>=mem.startTime+mem.delayTime){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};

function B_PlayNoteForBeats(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"play note"));
	this.addPart(new NumSlot(this,60,true,true)); //Positive integer
	this.addPart(new LabelText(this,"for"));
	this.addPart(new NumSlot(this,1,true)); //Positive
	this.addPart(new LabelText(this,"beats"));
}
B_PlayNoteForBeats.prototype = Object.create(CommandBlock.prototype);
B_PlayNoteForBeats.prototype.constructor = B_PlayNoteForBeats;
B_PlayNoteForBeats.prototype.startAction=function(){
	var mem=this.runMem;
	var note=this.slots[0].getData().getValueWithC(true,true);
	var beats=this.slots[1].getData().getValueWithC(true); //Positive
	mem.soundDuration=CodeManager.beatsToMs(beats);
	mem.request = "sound/note/"+note+"/"+mem.soundDuration;
	mem.timerStarted=false;
	mem.requestStatus=function(){};
	HtmlServer.sendRequest(mem.request,mem.requestStatus);
	return true; //Still running
};
B_PlayNoteForBeats.prototype.updateAction=function(){
	var mem=this.runMem;
	if(!mem.timerStarted){
		var status=mem.requestStatus;
		if(status.finished==true){
			mem.startTime=new Date().getTime();
			mem.timerStarted=true;
		}
		else{
			return true; //Still running
		}
	}
	if(new Date().getTime()>=mem.startTime+mem.soundDuration){
		return false; //Done running
	}
	else{
		return true; //Still running
	}
};

function B_ChangeTempoBy(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"change tempo by"));
	this.addPart(new NumSlot(this,20));
}
B_ChangeTempoBy.prototype = Object.create(CommandBlock.prototype);
B_ChangeTempoBy.prototype.constructor = B_ChangeTempoBy;
B_ChangeTempoBy.prototype.startAction=function(){
	var slotData=this.slots[0].getData();
	if(slotData.isValid) {
		var newTempo = CodeManager.sound.tempo +slotData.getValue();
		CodeManager.setSoundTempo(newTempo);
	}
	return false;
};

function B_SetTempoTo(x,y){
	CommandBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"set tempo to"));
	this.addPart(new NumSlot(this,60,true)); //Positive
	this.addPart(new LabelText(this,"bpm"));
}
B_SetTempoTo.prototype = Object.create(CommandBlock.prototype);
B_SetTempoTo.prototype.constructor = B_SetTempoTo;
B_SetTempoTo.prototype.startAction=function(){
	var slotData=this.slots[0].getData();
	if(slotData.isValid) {
		var newTempo = slotData.getValue();
		CodeManager.setSoundTempo(newTempo);
	}
	return false;
};

function B_Tempo(x,y){
	ReporterBlock.call(this,x,y,"sound");
	this.addPart(new LabelText(this,"tempo"));
}
B_Tempo.prototype = Object.create(ReporterBlock.prototype);
B_Tempo.prototype.constructor = B_Tempo;
B_Tempo.prototype.startAction=function(){
	this.resultData=new NumData(CodeManager.sound.tempo);
	return false;
};
<|endoftext|>