<commit_before>// @flow
import { parseISO } from 'date-fns';
import type { Semester, AcadYear } from 'types/modules';

import holidays from 'data/holidays.json';
import corsData from 'data/cors-schedule-ay1819-sem2.json';
import appConfig from './app-config.json';

export type CorsPeriodType = 'open' | 'closed';

export type CorsPeriod = {
  type: CorsPeriodType,
  start: string,
  startDate: Date,
  end: string,
  endDate: Date,
};

export type CorsRound = {
  round: string,
  periods: CorsPeriod[],
};

export type Config = {
  brandName: string,
  academicYear: AcadYear,
  semester: Semester,
  getSemesterKey: () => string,

  apiBaseUrl: string,
  corsUrl: string,
  ivleUrl: string,

  disqusShortname: string,
  googleAnalyticsId: string,
  venueFeedbackApi: string,

  semesterNames: { [Semester]: string },
  shortSemesterNames: { [Semester]: string },
  timetableAvailable: Semester[],
  archiveYears: string[],

  defaultPreferences: {
    theme: string,
    mode: string,
    faculty: string,
    student: string,
    account: string,
  },

  contact: {
    blog: string,
    email: string,
    facebook: string,
    githubOrg: string,
    githubRepo: string,
    messenger: string,
    twitter: string,
  },

  holidays: Date[],

  corsSchedule: CorsRound[],
};

function convertCorsDate(roundData: Object): CorsRound {
  return {
    ...roundData,
    periods: roundData.periods.map((period) => ({
      ...period,
      // Convert timestamps to date objects
      startDate: new Date(period.startTs),
      endDate: new Date(period.endTs),
    })),
  };
}

const augmentedConfig: Config = {
  ...appConfig,
  corsUrl: appConfig.corsUrl
    .replace('<AcademicYear>', appConfig.academicYear)
    .replace('<Semester>', appConfig.semester),

  holidays: holidays.map(parseISO),

  corsSchedule: corsData.map(convertCorsDate),

  /**
   * Returns a unique key for every acad year + semester
   */
  getSemesterKey: (): string =>
    `${augmentedConfig.academicYear} ${augmentedConfig.semesterNames[augmentedConfig.semester]}`,
};

export default augmentedConfig;
<commit_msg>Fix holiday exclusion rules<commit_after>// @flow
import type { Semester, AcadYear } from 'types/modules';

import holidays from 'data/holidays.json';
import corsData from 'data/cors-schedule-ay1819-sem2.json';
import appConfig from './app-config.json';

export type CorsPeriodType = 'open' | 'closed';

export type CorsPeriod = {
  type: CorsPeriodType,
  start: string,
  startDate: Date,
  end: string,
  endDate: Date,
};

export type CorsRound = {
  round: string,
  periods: CorsPeriod[],
};

export type Config = {
  brandName: string,
  academicYear: AcadYear,
  semester: Semester,
  getSemesterKey: () => string,

  apiBaseUrl: string,
  corsUrl: string,
  ivleUrl: string,

  disqusShortname: string,
  googleAnalyticsId: string,
  venueFeedbackApi: string,

  semesterNames: { [Semester]: string },
  shortSemesterNames: { [Semester]: string },
  timetableAvailable: Semester[],
  archiveYears: string[],

  defaultPreferences: {
    theme: string,
    mode: string,
    faculty: string,
    student: string,
    account: string,
  },

  contact: {
    blog: string,
    email: string,
    facebook: string,
    githubOrg: string,
    githubRepo: string,
    messenger: string,
    twitter: string,
  },

  holidays: Date[],

  corsSchedule: CorsRound[],
};

function convertCorsDate(roundData: Object): CorsRound {
  return {
    ...roundData,
    periods: roundData.periods.map((period) => ({
      ...period,
      // Convert timestamps to date objects
      startDate: new Date(period.startTs),
      endDate: new Date(period.endTs),
    })),
  };
}

const augmentedConfig: Config = {
  ...appConfig,
  corsUrl: appConfig.corsUrl
    .replace('<AcademicYear>', appConfig.academicYear)
    .replace('<Semester>', appConfig.semester),

  holidays: holidays.map((date) => new Date(date)),

  corsSchedule: corsData.map(convertCorsDate),

  /**
   * Returns a unique key for every acad year + semester
   */
  getSemesterKey: (): string =>
    `${augmentedConfig.academicYear} ${augmentedConfig.semesterNames[augmentedConfig.semester]}`,
};

export default augmentedConfig;
<|endoftext|>


<commit_before>// Copyright 2016 Joseph W. May. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * An object representing the form responses sheet.
 *
 * @constructor
 */
var FormResponses = function() {
  // Get the sheet name from the configuration object.
  this.config = Configuration.getCurrent();
  this.sheetName = this.config.sheets.formResponses.name;

  // Get the sheet id.
  var spreadsheet = new BaseSpreadsheet();
  var sheetId = spreadsheet.getSheetId(this.sheetName);

  // Inherit from BaseSheet.
  BaseSheet.call(this, sheetId);
};
inherit_(FormResponses, BaseSheet);

/**
 * Returns true if the form responses sheet is properly initialized with the
 * required headers.
 *
 * @return {boolean} True if the sheet is initialized, otherwise, false.
 */
FormResponses.prototype.isInitialized = function() {
  // Ensure the required headers are set.
  var header = this.getHeader();
  var requiredHeaders = this.config.sheets.formResponses.headers;
  var lastColumn = this.sheet.getLastColumn();
  var headerSlice = header.slice(lastColumn - 2, lastColumn);
  var headersSet = arraysEqual(requiredHeaders, headerSlice);
  if (headersSet !== true) {
    this.initialize();
  }

  // Ensure a template file has been selected.
  var templateFile = new TemplateFile();
  var file = templateFile.getFile();
  if (file === null) {
    showAlert('Template File', 'Please select a template file');
    return false;
  }

  // Ensure a report filename has been specified.
  var reports = new Reports();
  var filename = reports.getFilename();
  if (filename === null) {
    showAlert('Report Name', 'Please provide a report name');
    return false;
  }

  return true;
};

/**
 * Initializes the form responses sheet by adding the required headers to the
 * header row of the sheet. The added column numbers are stored in document
 * properties for later use.
 */
FormResponses.prototype.initialize = function() {
  var requiredHeaders = this.config.sheets.formResponses.headers;

  // Get the required header column numbers.
  var lastColumn = this.sheet.getLastColumn();
  var reportStatusColumn = lastColumn + 1;
  var pdfLinkColumn = reportStatusColumn + 1;

  // Add the headers and notes and resize the columns.
  this.addHeader(reportStatusColumn, requiredHeaders[0]);
  this.addHeader(pdfLinkColumn, requiredHeaders[1]);
  this.sheet.setColumnWidth(reportStatusColumn, 100);
  this.sheet.setColumnWidth(pdfLinkColumn, 600);
};

/**
 * Returns a Google Range object containing the header cells.
 *
 * @return {Range} A Google Range object.
 */
FormResponses.prototype.getHeaderRange = function() {
  var headerRange = this.getRow(1, 1, this.sheet.getLastColumn());
  return headerRange;
};

/**
 * Returns an array containing the headers for the form responses sheet.
 *
 * @return {array} An array of the header values.
 */
FormResponses.prototype.getHeader = function() {
  var headerRange = this.getHeaderRange();
  var header = headerRange.getValues();
  return header[0];
};

/**
 * Returns an array of header keys for use in JavaScript objects. The keys are
 * constructed by replacing spaces with an underscore and removing any special
 * characters from the string.
 *
 * @return {array} An array of header keys.
 */
FormResponses.prototype.getHeaderKeys = function() {
  var headers = this.getHeader();

  var headerKeys = [];
  for (var i = 0; i < headers.length; i++) {
    var header = headers[i];
    var headerKey = header.replace(/\s+/g, '_').replace(/\W+/g, '');
    headerKeys.push(headerKey);
  }

  return headerKeys;
};

/**
 * Returns an array of header tags for use in the template file. The tags are
 * constructed by adding **...** around the header key.
 *
 * @return {array} An array of header tags.
 */
FormResponses.prototype.getHeaderTags = function() {
  var headerKeys = this.getHeaderKeys();

  var headerTags = [];
  for (var i = 0; i < headerKeys.length; i++) {
    var headerKey = headerKeys[i];
    var headerTag = '**' + headerKey + '**';
    headerTags.push(headerTag);
  }

  return headerTags;
};

/**
 * Adds the header to the given colNum.
 *
 * @param {integer} colNum The column number to add to.
 * @param {string} header The header to add.
 */
FormResponses.prototype.addHeader = function(colNum, header) {
  var headerCell = this.sheet.getRange(1, colNum);
  headerCell.setValue(header);
  headerCell.setNote('This column is required by the ' +
          'incident reporter plugin. Do not remove this column.');
};

/**
 * Returns the number of the last column with content in the header.
 *
 * @return {integer} The last column's position.
 */
FormResponses.prototype.getMaxColumn = function() {
  var header = this.getHeader();
  var headerLength = header.length;
  return headerLength;
};

/**
 * Returns the 'Report Status' column's position.
 *
 * @return {integer} The Report Status column position.
 */
FormResponses.prototype.getReportStatusColumn = function() {
  var header = this.getHeader();
  var requiredHeaders = this.config.sheets.formResponses.headers;
  var index = header.indexOf(requiredHeaders[0]);
  var column = index + 1;
  return column;
};

/**
 * Returns the 'PDF Link' column's position.
 *
 * @return {integer} The PDF Link column position.
 */
FormResponses.prototype.getPdfLinkColumn = function() {
  var header = this.getHeader();
  var requiredHeaders = this.config.sheets.formResponses.headers;
  var index = header.indexOf(requiredHeaders[1]);
  var column = index + 1;
  return column;
};<commit_msg>error handling for unspecified reports folder<commit_after>// Copyright 2016 Joseph W. May. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * An object representing the form responses sheet.
 *
 * @constructor
 */
var FormResponses = function() {
  // Get the sheet name from the configuration object.
  this.config = Configuration.getCurrent();
  this.sheetName = this.config.sheets.formResponses.name;

  // Get the sheet id.
  var spreadsheet = new BaseSpreadsheet();
  var sheetId = spreadsheet.getSheetId(this.sheetName);

  // Inherit from BaseSheet.
  BaseSheet.call(this, sheetId);
};
inherit_(FormResponses, BaseSheet);

/**
 * Returns true if the form responses sheet is properly initialized with the
 * required headers.
 *
 * @return {boolean} True if the sheet is initialized, otherwise, false.
 */
FormResponses.prototype.isInitialized = function() {
  // Ensure the required headers are set.
  var header = this.getHeader();
  var requiredHeaders = this.config.sheets.formResponses.headers;
  var lastColumn = this.sheet.getLastColumn();
  var headerSlice = header.slice(lastColumn - 2, lastColumn);
  var headersSet = arraysEqual(requiredHeaders, headerSlice);
  if (headersSet !== true) {
    this.initialize();
  }

  // Ensure a template file has been selected.
  var templateFile = new TemplateFile();
  var file = templateFile.getFile();
  if (file === null) {
    showAlert('Template File', 'Please select a template file');
    return false;
  }

  // Ensure a report folder has been specified.
  var reportsFolder = new ReportsFolder();
  var folder = reportsFolder.folder;
  if (folder === null) {
    showAlert('Reports Folder', 'Please provide a folder to store reports');
    return false;
  }

  // Ensure a report filename has been specified.
  var reports = new Reports();
  var filename = reports.getFilename();
  if (filename === null) {
    showAlert('Report Name', 'Please provide a report name');
    return false;
  }

  return true;
};

/**
 * Initializes the form responses sheet by adding the required headers to the
 * header row of the sheet. The added column numbers are stored in document
 * properties for later use.
 */
FormResponses.prototype.initialize = function() {
  var requiredHeaders = this.config.sheets.formResponses.headers;

  // Get the required header column numbers.
  var lastColumn = this.sheet.getLastColumn();
  var reportStatusColumn = lastColumn + 1;
  var pdfLinkColumn = reportStatusColumn + 1;

  // Add the headers and notes and resize the columns.
  this.addHeader(reportStatusColumn, requiredHeaders[0]);
  this.addHeader(pdfLinkColumn, requiredHeaders[1]);
  this.sheet.setColumnWidth(reportStatusColumn, 100);
  this.sheet.setColumnWidth(pdfLinkColumn, 600);
};

/**
 * Returns a Google Range object containing the header cells.
 *
 * @return {Range} A Google Range object.
 */
FormResponses.prototype.getHeaderRange = function() {
  var headerRange = this.getRow(1, 1, this.sheet.getLastColumn());
  return headerRange;
};

/**
 * Returns an array containing the headers for the form responses sheet.
 *
 * @return {array} An array of the header values.
 */
FormResponses.prototype.getHeader = function() {
  var headerRange = this.getHeaderRange();
  var header = headerRange.getValues();
  return header[0];
};

/**
 * Returns an array of header keys for use in JavaScript objects. The keys are
 * constructed by replacing spaces with an underscore and removing any special
 * characters from the string.
 *
 * @return {array} An array of header keys.
 */
FormResponses.prototype.getHeaderKeys = function() {
  var headers = this.getHeader();

  var headerKeys = [];
  for (var i = 0; i < headers.length; i++) {
    var header = headers[i];
    var headerKey = header.replace(/\s+/g, '_').replace(/\W+/g, '');
    headerKeys.push(headerKey);
  }

  return headerKeys;
};

/**
 * Returns an array of header tags for use in the template file. The tags are
 * constructed by adding **...** around the header key.
 *
 * @return {array} An array of header tags.
 */
FormResponses.prototype.getHeaderTags = function() {
  var headerKeys = this.getHeaderKeys();

  var headerTags = [];
  for (var i = 0; i < headerKeys.length; i++) {
    var headerKey = headerKeys[i];
    var headerTag = '**' + headerKey + '**';
    headerTags.push(headerTag);
  }

  return headerTags;
};

/**
 * Adds the header to the given colNum.
 *
 * @param {integer} colNum The column number to add to.
 * @param {string} header The header to add.
 */
FormResponses.prototype.addHeader = function(colNum, header) {
  var headerCell = this.sheet.getRange(1, colNum);
  headerCell.setValue(header);
  headerCell.setNote('This column is required by the ' +
          'incident reporter plugin. Do not remove this column.');
};

/**
 * Returns the number of the last column with content in the header.
 *
 * @return {integer} The last column's position.
 */
FormResponses.prototype.getMaxColumn = function() {
  var header = this.getHeader();
  var headerLength = header.length;
  return headerLength;
};

/**
 * Returns the 'Report Status' column's position.
 *
 * @return {integer} The Report Status column position.
 */
FormResponses.prototype.getReportStatusColumn = function() {
  var header = this.getHeader();
  var requiredHeaders = this.config.sheets.formResponses.headers;
  var index = header.indexOf(requiredHeaders[0]);
  var column = index + 1;
  return column;
};

/**
 * Returns the 'PDF Link' column's position.
 *
 * @return {integer} The PDF Link column position.
 */
FormResponses.prototype.getPdfLinkColumn = function() {
  var header = this.getHeader();
  var requiredHeaders = this.config.sheets.formResponses.headers;
  var index = header.indexOf(requiredHeaders[1]);
  var column = index + 1;
  return column;
};<|endoftext|>


<commit_before>import fetch from 'utils/fetch';

module.exports = Backbone.View.extend({

  template: _.template(`
  <form>
    <div id="<%= pfx %>title"><%= title %>

    <input type="file" id="<%= uploadId %>" name="file" accept="image/*" <%= disabled ? 'disabled' : '' %> multiple/>

  </form>
  `),

  events:   {},

  initialize(opts = {}) {
    this.options = opts;
    const c = opts.config || {};
    this.config = c;
    this.pfx = c.stylePrefix || '';
    this.ppfx = c.pStylePrefix || '';
    this.target = this.options.globalCollection || {};
    this.uploadId = this.pfx + 'uploadFile';
    this.disabled = c.disableUpload !== undefined ? c.disableUpload : !c.upload && !c.embedAsBase64;
    this.events['change #' + this.uploadId]  = 'uploadFile';
    let uploadFile = c.uploadFile;

    if (uploadFile) {
      this.uploadFile = uploadFile.bind(this);
    } else if (c.embedAsBase64) {
      this.uploadFile = this.constructor.embedAsBase64;
    }

    this.delegateEvents();
  },

  /**
   * Triggered before the upload is started
   * @private
   */
  onUploadStart() {
    const em = this.config.em;
    em && em.trigger('asset:upload:start');
  },

  /**
   * Triggered after the upload is ended
   * @param  {Object|string} res End result
   * @private
   */
  onUploadEnd(res) {
    const em = this.config.em;
    em && em.trigger('asset:upload:end', res);
  },

  /**
   * Triggered on upload error
   * @param  {Object} err Error
   * @private
   */
  onUploadError(err) {
    const em = this.config.em;
    console.error(err);
    this.onUploadEnd(err);
    em && em.trigger('asset:upload:error', err);
  },

  /**
   * Triggered on upload response
   * @param  {string} text Response text
   * @private
   */
  onUploadResponse(text) {
    const em = this.config.em;
    const config = this.config;
    const target = this.target;
    const json = typeof text === 'text' ? JSON.parse(text) : text;
    em && em.trigger('asset:upload:response', json);

    if (config.autoAdd && target) {
      target.add(json.data, {at: 0});
    }

    this.onUploadEnd(text);
  },

  /**
   * Upload files
   * @param  {Object}  e Event
   * @return {Promise}
   * @private
   * */
  uploadFile(e) {
    const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
    const body = new FormData();
    const config = this.config;
    const params = config.params;

    for (let i = 0; i < files.length; i++) {
      body.append(`${config.uploadName}[]`, files[i]);
    }

    for (let param in params) {
      body.append(param, params[param]);
    }

    var target = this.target;
    const url = config.upload;
    const headers = config.headers;
    const reqHead = 'X-Requested-With';

    if (typeof headers[reqHead] == 'undefined') {
      headers[reqHead] = 'XMLHttpRequest';
    }

    if (url) {
      this.onUploadStart();
      return fetch(url, {
        method: 'post',
        credentials: 'include',
        headers,
        body,
      }).then(res => (res.status/200|0) == 1 ?
        res.text() : res.text().then((text) =>
          Promise.reject(text)
        ))
      .then((text) => this.onUploadResponse(text))
      .catch(err => this.onUploadError(err));
    }
  },

  /**
   * Make input file droppable
   * @private
   * */
  initDrop() {
    var that  = this;
    if(!this.uploadForm){
      this.uploadForm = this.$el.find('form').get(0);
      if( 'draggable' in this.uploadForm ){
        var uploadFile = this.uploadFile;
        this.uploadForm.ondragover = function(){
          this.className = that.pfx + 'hover';
          return false;
        };
        this.uploadForm.ondragleave = function(){
          this.className = '';
          return false;
        };
        this.uploadForm.ondrop = function(e){
          this.className = '';
          e.preventDefault();
          that.uploadFile(e);
          return;
        };
      }
    }
  },

  initDropzone(ev) {
    let addedCls = 0;
    const c = this.config;
    const em = ev.model;
    const edEl = ev.el;
    const editor = em.get('Editor');
    const container = em.get('Config').el;
    const frameEl = em.get('Canvas').getBody();
    const ppfx = this.ppfx;
    const updatedCls = `${ppfx}dropzone-active`;
    const dropzoneCls = `${ppfx}dropzone`;
    const cleanEditorElCls = () => {
      edEl.className = edEl.className.replace(updatedCls, '').trim();
      addedCls = 0;
    }
    const onDragOver = () => {
      if (!addedCls) {
        edEl.className += ` ${updatedCls}`;
        addedCls = 1;
      }
      return false;
    };
    const onDragLeave = () => {
      cleanEditorElCls();
      return false;
    };
    const onDrop = (e) => {
      cleanEditorElCls();
      e.preventDefault();
      e.stopPropagation();
      this.uploadFile(e);

      if (c.openAssetsOnDrop && editor) {
        const target = editor.getSelected();
        editor.runCommand('open-assets', {
          target,
          onSelect() {
            editor.Modal.close();
            editor.AssetManager.setTarget(null);
          }
        });
      }

      return false;
    };

    ev.$el.append(`<div class="${dropzoneCls}">${c.dropzoneContent}</div>`);
    cleanEditorElCls();

    if ('draggable' in edEl) {
      [edEl, frameEl].forEach((item) => {
        item.ondragover = onDragOver;
        item.ondragleave = onDragLeave;
        item.ondrop = onDrop;
      });
    }
  },

  render() {
    this.$el.html( this.template({
      title: this.config.uploadText,
      uploadId: this.uploadId,
      disabled: this.disabled,
      pfx: this.pfx
    }) );
    this.initDrop();
    this.$el.attr('class', this.pfx + 'file-uploader');
    return this;
  },

}, {
  embedAsBase64: function (e) {
    // List files dropped
    const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
    const response = { data: [] };

    // Unlikely, widely supported now
    if (!FileReader) {
      this.onUploadError(new Error('Unsupported platform, FileReader is not defined'));
      return;
    }

    const promises = [];
    const mimeTypeMatcher = /^(.+)\/(.+)$/;

    for (const file of files) {
      // For each file a reader (to read the base64 URL)
      // and a promise (to track and merge results and errors)
      const promise = new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.addEventListener('load', (event) => {
          let type;
          const name = file.name;

          // Try to find the MIME type of the file.
          const match = mimeTypeMatcher.exec(file.type);
          if (match) {
            type = match[1]; // The first part in the MIME, "image" in image/png
          } else {
            type = file.type;
          }

          // If it's an image, try to find its size
          if (type === 'image') {
            const data = {
              src: reader.result,
              name,
              type,
              height: 0,
              width: 0
            };

            const image = new Image();
            image.addEventListener('error', (error) => {
              reject(error);
            });
            image.addEventListener('load', () => {
              data.height = image.height;
              data.width = image.width;
              resolve(data);
            });
            image.src = data.src;

          } else if (type) {
            // Not an image, but has a type
            resolve({
              src: reader.result,
              name,
              type
            });
          } else {
            // No type found, resolve with the URL only
            resolve(reader.result);
          }
        });
        reader.addEventListener('error', (error) => {
          reject(error);
        });
        reader.addEventListener('abort', (error) => {
          reject('Aborted');
        });

        reader.readAsDataURL(file);
      });

      promises.push(promise);
    }

    Promise
      .all(promises)
      .then((data) => {
        response.data = data;
        this.onUploadResponse(response);
      }, (error) =>  {
        this.onUploadError(error);
      });
  }
});
<commit_msg>Update FileUploader.js<commit_after>import fetch from 'utils/fetch';

module.exports = Backbone.View.extend({

  template: _.template(`
  <form>
    <div id="<%= pfx %>title"><%= title %>

    <input type="file" id="<%= uploadId %>" name="file" accept="image/*" <%= disabled ? 'disabled' : '' %> multiple/>

  </form>
  `),

  events:   {},

  initialize(opts = {}) {
    this.options = opts;
    const c = opts.config || {};
    this.config = c;
    this.pfx = c.stylePrefix || '';
    this.ppfx = c.pStylePrefix || '';
    this.target = this.options.globalCollection || {};
    this.uploadId = this.pfx + 'uploadFile';
    this.disabled = c.disableUpload !== undefined ? c.disableUpload : !c.upload && !c.embedAsBase64;
    this.events['change #' + this.uploadId]  = 'uploadFile';
    let uploadFile = c.uploadFile;

    if (uploadFile) {
      this.uploadFile = uploadFile.bind(this);
    } else if (c.embedAsBase64) {
      this.uploadFile = this.constructor.embedAsBase64;
    }

    this.delegateEvents();
  },

  /**
   * Triggered before the upload is started
   * @private
   */
  onUploadStart() {
    const em = this.config.em;
    em && em.trigger('asset:upload:start');
  },

  /**
   * Triggered after the upload is ended
   * @param  {Object|string} res End result
   * @private
   */
  onUploadEnd(res) {
    const em = this.config.em;
    em && em.trigger('asset:upload:end', res);
  },

  /**
   * Triggered on upload error
   * @param  {Object} err Error
   * @private
   */
  onUploadError(err) {
    const em = this.config.em;
    console.error(err);
    this.onUploadEnd(err);
    em && em.trigger('asset:upload:error', err);
  },

  /**
   * Triggered on upload response
   * @param  {string} text Response text
   * @private
   */
  onUploadResponse(text) {
    const em = this.config.em;
    const config = this.config;
    const target = this.target;
    const json = typeof text === 'string' ? JSON.parse(text) : text;
    em && em.trigger('asset:upload:response', json);

    if (config.autoAdd && target) {
      target.add(json.data, {at: 0});
    }

    this.onUploadEnd(text);
  },

  /**
   * Upload files
   * @param  {Object}  e Event
   * @return {Promise}
   * @private
   * */
  uploadFile(e) {
    const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
    const body = new FormData();
    const config = this.config;
    const params = config.params;

    for (let i = 0; i < files.length; i++) {
      body.append(`${config.uploadName}[]`, files[i]);
    }

    for (let param in params) {
      body.append(param, params[param]);
    }

    var target = this.target;
    const url = config.upload;
    const headers = config.headers;
    const reqHead = 'X-Requested-With';

    if (typeof headers[reqHead] == 'undefined') {
      headers[reqHead] = 'XMLHttpRequest';
    }

    if (url) {
      this.onUploadStart();
      return fetch(url, {
        method: 'post',
        credentials: 'include',
        headers,
        body,
      }).then(res => (res.status/200|0) == 1 ?
        res.text() : res.text().then((text) =>
          Promise.reject(text)
        ))
      .then((text) => this.onUploadResponse(text))
      .catch(err => this.onUploadError(err));
    }
  },

  /**
   * Make input file droppable
   * @private
   * */
  initDrop() {
    var that  = this;
    if(!this.uploadForm){
      this.uploadForm = this.$el.find('form').get(0);
      if( 'draggable' in this.uploadForm ){
        var uploadFile = this.uploadFile;
        this.uploadForm.ondragover = function(){
          this.className = that.pfx + 'hover';
          return false;
        };
        this.uploadForm.ondragleave = function(){
          this.className = '';
          return false;
        };
        this.uploadForm.ondrop = function(e){
          this.className = '';
          e.preventDefault();
          that.uploadFile(e);
          return;
        };
      }
    }
  },

  initDropzone(ev) {
    let addedCls = 0;
    const c = this.config;
    const em = ev.model;
    const edEl = ev.el;
    const editor = em.get('Editor');
    const container = em.get('Config').el;
    const frameEl = em.get('Canvas').getBody();
    const ppfx = this.ppfx;
    const updatedCls = `${ppfx}dropzone-active`;
    const dropzoneCls = `${ppfx}dropzone`;
    const cleanEditorElCls = () => {
      edEl.className = edEl.className.replace(updatedCls, '').trim();
      addedCls = 0;
    }
    const onDragOver = () => {
      if (!addedCls) {
        edEl.className += ` ${updatedCls}`;
        addedCls = 1;
      }
      return false;
    };
    const onDragLeave = () => {
      cleanEditorElCls();
      return false;
    };
    const onDrop = (e) => {
      cleanEditorElCls();
      e.preventDefault();
      e.stopPropagation();
      this.uploadFile(e);

      if (c.openAssetsOnDrop && editor) {
        const target = editor.getSelected();
        editor.runCommand('open-assets', {
          target,
          onSelect() {
            editor.Modal.close();
            editor.AssetManager.setTarget(null);
          }
        });
      }

      return false;
    };

    ev.$el.append(`<div class="${dropzoneCls}">${c.dropzoneContent}</div>`);
    cleanEditorElCls();

    if ('draggable' in edEl) {
      [edEl, frameEl].forEach((item) => {
        item.ondragover = onDragOver;
        item.ondragleave = onDragLeave;
        item.ondrop = onDrop;
      });
    }
  },

  render() {
    this.$el.html( this.template({
      title: this.config.uploadText,
      uploadId: this.uploadId,
      disabled: this.disabled,
      pfx: this.pfx
    }) );
    this.initDrop();
    this.$el.attr('class', this.pfx + 'file-uploader');
    return this;
  },

}, {
  embedAsBase64: function (e) {
    // List files dropped
    const files = e.dataTransfer ? e.dataTransfer.files : e.target.files;
    const response = { data: [] };

    // Unlikely, widely supported now
    if (!FileReader) {
      this.onUploadError(new Error('Unsupported platform, FileReader is not defined'));
      return;
    }

    const promises = [];
    const mimeTypeMatcher = /^(.+)\/(.+)$/;

    for (const file of files) {
      // For each file a reader (to read the base64 URL)
      // and a promise (to track and merge results and errors)
      const promise = new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.addEventListener('load', (event) => {
          let type;
          const name = file.name;

          // Try to find the MIME type of the file.
          const match = mimeTypeMatcher.exec(file.type);
          if (match) {
            type = match[1]; // The first part in the MIME, "image" in image/png
          } else {
            type = file.type;
          }

          // If it's an image, try to find its size
          if (type === 'image') {
            const data = {
              src: reader.result,
              name,
              type,
              height: 0,
              width: 0
            };

            const image = new Image();
            image.addEventListener('error', (error) => {
              reject(error);
            });
            image.addEventListener('load', () => {
              data.height = image.height;
              data.width = image.width;
              resolve(data);
            });
            image.src = data.src;

          } else if (type) {
            // Not an image, but has a type
            resolve({
              src: reader.result,
              name,
              type
            });
          } else {
            // No type found, resolve with the URL only
            resolve(reader.result);
          }
        });
        reader.addEventListener('error', (error) => {
          reject(error);
        });
        reader.addEventListener('abort', (error) => {
          reject('Aborted');
        });

        reader.readAsDataURL(file);
      });

      promises.push(promise);
    }

    Promise
      .all(promises)
      .then((data) => {
        response.data = data;
        this.onUploadResponse(response);
      }, (error) =>  {
        this.onUploadError(error);
      });
  }
});
<|endoftext|>


<commit_before>var LocalFileImportModel = function () {
    var self = this;

    self.ImportResults = ko.observableArray();

    self.submitImportRequest = function () {
        self.ImportResults(null);

        var formData = new FormData();
        // Main magic with files here
        var files = $('input[type=file]');
        formData.append('headerFileInput', $('input[type=file]')[0].files[0]);
        formData.append('sampleFileInput', $('input[type=file]')[1].files[0]);
        formData.append('chemistryFileInput', $('input[type=file]')[2].files[0]);

        $.ajax({
            url: '../api/ESDATImportAPI/ImportLocalFiles',
            type: 'POST',
            data: formData,
            mimeType: "multipart/form-data",
            contentType: false,
            cache: false,
            processData: false,
            success: function (data) {
                self.ImportResults(data);

            },
            error: function (data) {
                alert('Import local file system fail');
            }
        });//end of ajax
    };
};<commit_msg>fix binding fail for the local file system js<commit_after>var LocalFileImportModel = function () {
    var self = this;

    self.ImportResults = ko.observableArray();

    self.submitImportRequest = function () {
        //self.ImportResults();

        var formData = new FormData();
        // Main magic with files here
        var files = $('input[type=file]');
        formData.append('headerFileInput', $('input[type=file]')[0].files[0]);
        formData.append('sampleFileInput', $('input[type=file]')[1].files[0]);
        formData.append('chemistryFileInput', $('input[type=file]')[2].files[0]);

        $.ajax({
            url: '../api/ESDATImportAPI/ImportLocalFiles',
            type: 'POST',
            data: formData,
            mimeType: "multipart/form-data",
            contentType: false,
            cache: false,
            processData: false,
            success: function (data) {
                var parsedJson = JSON.parse(data);//parsed the string to json because the data type was set to form
                self.ImportResults.removeAll();
                ko.utils.arrayPushAll(self.ImportResults, parsedJson); //push the json array to the station list

            },
            error: function (data) {
                alert('Import local file system fail');
            }
        });//end of ajax
    };
};<|endoftext|>


<commit_before>Audio51
Part of the Glue Game Engine
Copyright (C) 2013, SpilGames
all rights reserved
maintained by [Buffer-Overflow](https://github.com/Buffer-Overflow)

BSD 3-Clause License

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of Glue, nor SpilGames, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<commit_msg>updated license added author<commit_after>Audio51
Part of the Glue Game Engine
Copyright (C) 2013, SpilGames
all rights reserved
author: Martin Reurings
maintained by [Buffer-Overflow](https://github.com/Buffer-Overflow)

BSD 3-Clause License

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

3. Neither the name of Audio51, nor Glue, nor SpilGames, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<|endoftext|>


<commit_before>"use strict";
/*global alert: true, ODSA */
/*global sweep */
(function ($) {
  var comp = function(a, b) {
    return a - b;
  };

  var Bintree = function (jsav, xrange, yrange) {

    // This is the JSAV base data structure, a binary tree.
    this.tree = jsav.ds.binarytree({nodegap: 10});
    // This is the root of the tree
    this.vrt = this.tree.root('ROOT');

    this.root = this.vrt;
    console.log("I'm making a new Bintree object. root = ", this.root);
    // Set the values of the root node.
    this.vrt.leaf = true;
    this.vrt.empty = true;
    this.vrt.level = 0;

    // The bintree starts with a root node, and two empty leafnodes
    // var newL1  = this.tree.newNode('');
    // var newR1 = this.tree.newNode('');
    // newL1.leaf = true;
    // newR1.leaf = true;
    // newR1.empty = true;
    // newL1.empty = true;
    // this.vrt.left(newL1);
    // this.vrt.right(newR1);

    // Don't forget to refresh the tree layout
    this.tree.layout();

    // Getter function for the tree
    this.getTree = function () {
      console.log("getTree: ", this.tree);
      return this.tree;
    };

    // Getter function for the root
    this.getRoot = function () {
      console.log("getRoot: ", this.root);
      return this.root;
    };

    // I don't think this is working correctly
    this.isEmpty = function () {
      var returning = (this.root.leaf == true);
      console.log("Bintree isEmpty test: ", returning);
      return (returning);
    };

    this.add = function(INx, INy, INrec, Bx, By, Bwid, Bhgt, level) {
      this.root = this.insert(this.root, INx, INy, INrec, Bx, By, Bwid, Bhgt, level);
      this.tree.layout();
    }

    // returns a node!
    this.insert = function(rt, INx, INy, INrec, Bx, By, Bwid, Bhgt, level) {
      //console.assert(rt != null, "rt not defined");

      jsav.step();
      this.tree.layout();
      console.log("Bintree insert: BEGIN: ", INrec, ", Level:", level);

      console.assert(rt != null, "rt not defined");

      if (rt.leaf == true && rt.empty == true) {
        console.log("insert: encountered empty leaf node: insert data and return")
        jsav.umsg("Insert: Encountered an empty leaf node: Now insert data and return!");
        console.log("Bintree insert: (LEAF) Value = ", INrec);

        var temp = this.tree.newNode(INrec);
        // this.tree.newNode(INrec);
        // rt = temp;
        //temp.value(INrec);
        temp.x = INx;
        temp.y = INy;
        //temp.tree = true;
        temp.leaf = true;
        temp.empty = false;
        temp.level = level;
        // if (typeof rt === 'undefined')
        // {
        //   rt = temp;
        // }
        //this.tree.layout();
        //jsav.umsg("Finished inserting ", INrec);
        //jsav.step();
        return temp;
      }

      // If the entry is a leaf and not empty.
      if (rt.leaf == true && rt.empty == false) {
        console.log("insert: is a leaf and not empty: ", INrec, rt);

        var tp = this.tree.newNode('tp');
        tp.left(this.tree.newNode('tl'));
        tp.right(this.tree.newNode('tr'));

        //this.tree.layout();

        // Set the levels
        tp.level = level;
        tp.left().level = level + 1;
        tp.right().level = level + 1;

        // Set the internal/external value
        tp.leaf = false;
        tp.left().leaf = true;
        tp.right().leaf = true;

        // Set the emptyness
        tp.empty = true;
        tp.left().empty = true;
        tp.right().empty = true;

        var oldval = rt.value();
        this.insert(tp, rt.x, rt.y, oldval, Bx, By, Bwid, Bhgt, level);
        this.insert(tp, INx,    INy, INrec, Bx, By, Bwid, Bhgt, level);
        console.log("Finished moving down the previous entry");
        //jsav.umsg("Finished moving down the previous entry ", oldval, ".");
        //this.tree.layout();
        //jsav.step();
        return tp;
        // NO Return: Rolls through to next if statement
      }

      // If it isn't a leaf, then we have an internal node to insert into
      if (level % 2 == 0) // Branch on X
      {
        if (rt.x < (Bx + Bwid/2)) // Insert left
        {
          // This ensures that the data will be stored due to an empty node being placed where it is needed to recurse
          if (typeof rt.left() === 'undefined')
          {
            rt.left(this.tree.newNode(''));
            rt.left().leaf = true;
            rt.left().empty = true;
          }

          console.log("Branch on X, Insert Left");
          jsav.umsg("Branch on X, Insert Left");
          rt.left(this.insert(rt.left(), INx, INy, INrec, Bx, By, Bwid/2, Bhgt, level+1));
        }
        else
        {
          if (typeof rt.right() === 'undefined')
          {
            rt.right(this.tree.newNode(''));
            rt.right().leaf = true;
            rt.right().empty = true;
          }

          console.log("Branch on X, Insert Right: ", rt.right());
          jsav.umsg("Branch on X, Insert Right");
          rt.right(this.insert(rt.right(), INx, INy, INrec, Bx + Bwid/2, By, Bwid/2, Bhgt, level+1));
        }
      }

      else // Branch on Y
      {
        if (rt.y < (By + Bhgt/2)) // Insert left
        {
          if (typeof rt.left() === 'undefined')
          {
            rt.left(this.tree.newNode(''));
            rt.left().leaf = true;
            rt.left().empty = true;
          }

          console.log("Branch on Y, Insert Left: ", rt.left());
          jsav.umsg("Branch on Y, Insert Left");
          rt.left(this.insert(rt.left(), INx, INy, INrec, Bx, By, Bwid, Bhgt/2, level+1));
        }
        else
        {

          if (typeof rt.right() === 'undefined')
          {
            rt.right(this.tree.newNode(''));
            rt.right().leaf = true;
            rt.right().empty = true;
          }

          console.log("Branch on Y, Insert Right: ", rt.right());
          jsav.umsg("Branch on Y, Insert Right");
          rt.right(this.insert(rt.right(), INx, INy, INrec, Bx, By + Bhgt/2, Bwid, Bhgt/2, level+1));
        }
      }

      this.tree.layout();
      return rt;
    } // insert

    this.delete = function (rt, INx, INy, Bx, By, Bwid, Bhgt, level) {
      console.assert( !(rt.leaf == true && rt.empty == true), "Cannot be an empty leaf during delete");

      if (rt.leaf) {
        if (rt.x == INx && rt.y == INy)
        {
          var temp = tree.newNode('');
          temp.leaf = true;
          temp.empty = true;
          return temp;
        }
        // else ERROR: THIS IS IMPOSSIBLE;
      };

      // We have an internal node
      if (level % 2 == 0) // Branch on X
      {
        if (INx < (Bx + Bwid/2)) // delete left
        {
          console.log("Branch on X, Delete Left");
          rt.left(delete(rt.left(), INx, INy, Bx, By, Bwid/2, Bhgt, level+1));
        }
        else
        {
          console.log("Branch on X, Delete Right");
          rt.right(delete(rt.right(), INx, INy, Bx + Bwid/2, By, Bwid/2, Bhgt, level+1));
        }
      }

      else // Branch on Y
      {
        if (INy < (By + Bhgt/2)) // Insert left
        {
          rt.left(delete(rt.left(), INx, INy, Bx, By, Bwid, Bhgt/2, level+1));
        }
        else
          rt.right(delete(rt.right(), INx, INy, Bx, By + Bhgt/2, Bwid, Bhgt/2, level+1));
      }

      tree.layout();

      // Now, check to see if there should be a merge
      if ((rt.left().leaf == true && rt.left().empty == true) && (rt.right().leaf))
      {
        return rt.right();
      }
      if ((rt.left().leaf) && (rt.right().leaf && rt.left.empty))
      {
        return rt.left();
      }

      // Otherwise, return just the rt subtree without a merge
      return rt;

    } // delete

  } // bintree

  var arr;

  // check query parameters from URL
  var params = JSAV.utils.getQueryParameter();
  if ("increments" in params) { // set value of increments if it is a param
    $('#increments').val(params.increments).prop("disabled", true);
  }

  // create a new settings panel and specify the link to show it
  var settings = new JSAV.utils.Settings($(".jsavsettings"));
  // add the layout setting preference
  var arrayLayout = settings.add("layout",
    {"type": "select", "options": {"bar": "Bar", "array": "Array"},
     "label": "Array layout: ", "value": "bar"});

  // Initialize the arraysize dropdown list
  ODSA.AV.initArraySize(5, 16, 8);

  // Process help button: Give a full help page for this activity
  // We might give them another HTML page to look at.
  function help() {
    window.open("bintreeHelpAV.html", 'helpwindow');
  }

  // Process About button: Pop up a message with an Alert
  function about() {
    alert("Bintree Visualization\nWritten by Anthony Rinaldi and Cliff Shaffer\nCreated as part of the OpenDSA hypertextbook project\nFor more information, see http://algoviz.org/OpenDSA\nSource and development history available at\nhttps://github.com/cashaffer/OpenDSA\nCompiled with JSAV library version " + JSAV.version());
  }

  // Execute the "Run" button function
  function runIt() {

    ODSA.AV.reset(true);

    var jsav = new JSAV($('.avcontainer'));

    jsav.umsg("Let's get started");
    console.log("Create the Bintree object");
    var bint = new Bintree(jsav, 200, 200);
    console.log("I just made a new Bintree, and bint.root is: ", bint.getRoot());
    bint.isEmpty();
    jsav.displayInit();

    jsav.step();

    // Setup the tree
    jsav.umsg("Step 1: insert node with value \"A\" @ 10, 10");
    // rt, INx, INy, INrec, Bx, By, Bwid, Bhgt, level
    console.log("Let's call insert. bint.root is now: ", bint.getRoot());
    bint.add(10, 10, "A", 100, 100, 200, 200, 0);
    //bint.isEmpty();

    jsav.step();

    // Insert another object
    jsav.umsg("Step 2: insert node with value \"B\" @ 5, 5");
    // rt, INx, INy, INrec, Bx, By, Bwid, Bhgt, level
    console.log("Let's call insert. bint.root is now: ", bint.getRoot());
    bint.add(5, 5, "B", 100, 100, 200, 200, 0);

    jsav.step();

    jsav.umsg("Step 2: insert node with value \"C\" @ 20, 20");
    //bint.add(20, 20, "C", 100, 100, 200, 200, 0);
    //bint.isEmpty();

    jsav.step();

  // Done
    jsav.umsg("All Done!");

    jsav.recorded(); // mark the end

  }

  // Connect action callbacks to the HTML entities
  $('#help').click(help);
  $('#about').click(about);
  $('#run').click(runIt);
  $('#reset').click(ODSA.AV.reset);

}(jQuery));<commit_msg>There is still a recursive error in Bintree<commit_after>"use strict";
/*global alert: true, ODSA */
/*global sweep */
(function ($) {
  var comp = function(a, b) {
    return a - b;
  };

  var Bintree = function (jsav, xrange, yrange) {

    // This is the JSAV base data structure, a binary tree.
    this.tree = jsav.ds.binarytree({nodegap: 10});
    // This is the root of the tree
    this.vrt = this.tree.root('ROOT');

    this.root = this.vrt;
    console.log("I'm making a new Bintree object. root = ", this.root);
    // Set the values of the root node.
    this.vrt.leaf = true;
    this.vrt.empty = true;
    this.vrt.level = 0;

    // The bintree starts with a root node, and two empty leafnodes
    // var newL1  = this.tree.newNode('');
    // var newR1 = this.tree.newNode('');
    // newL1.leaf = true;
    // newR1.leaf = true;
    // newR1.empty = true;
    // newL1.empty = true;
    // this.vrt.left(newL1);
    // this.vrt.right(newR1);

    // Don't forget to refresh the tree layout
    this.tree.layout();

    // Getter function for the tree
    this.getTree = function () {
      console.log("getTree: ", this.tree);
      return this.tree;
    };

    // Getter function for the root
    this.getRoot = function () {
      console.log("getRoot: ", this.root);
      return this.root;
    };

    // I don't think this is working correctly
    this.isEmpty = function () {
      var returning = (this.root.leaf == true);
      console.log("Bintree isEmpty test: ", returning);
      return (returning);
    };

    this.add = function(INx, INy, INrec, Bx, By, Bwid, Bhgt, level) {
      this.root = this.insert(this.root, INx, INy, INrec, Bx, By, Bwid, Bhgt, level);
      this.tree.layout();
    }

    // returns a node!
    this.insert = function(rt, INx, INy, INrec, Bx, By, Bwid, Bhgt, level) {
      //console.assert(rt != null, "rt not defined");

      jsav.step();
      this.tree.layout();
      console.log("Bintree insert: BEGIN: ", INrec, ", Level:", level);

      console.assert(rt != null, "rt not defined");

      if (rt.leaf == true && rt.empty == true) {
        console.log("insert: encountered empty leaf node: insert data and return")
        jsav.umsg("Insert: Encountered an empty leaf node: Now insert data and return!");
        console.log("Bintree insert: (LEAF) Value = ", INrec);

        var temp = this.tree.newNode(INrec);
        // this.tree.newNode(INrec);
        // rt = temp;
        //temp.value(INrec);
        temp.x = INx;
        temp.y = INy;
        //temp.tree = true;
        temp.leaf = true;
        temp.empty = false;
        temp.level = level;
        // if (typeof rt === 'undefined')
        // {
        //   rt = temp;
        // }
        //this.tree.layout();
        //jsav.umsg("Finished inserting ", INrec);
        //jsav.step();
        return temp;
      }

      // If the entry is a leaf and not empty.
      if (rt.leaf == true && rt.empty == false) {
        console.log("insert: is a leaf and not empty: ", INrec, rt);

        // Create the new nodes and set them as
        var tp = this.tree.newNode('tp');
        var tpl = this.tree.newNode('tl');
        var tpr = this.tree.newNode('tr');
        tp.left(tpl);
        tp.right(tpr);

        // Set the levels
        tp.level = rt.level;
        tpl.level = rt.level + 1;
        tpr.level = rt.level + 1;

        // Set the internal/external value
        tp.leaf = false;
        tpl.leaf = true;
        tpr.leaf = true;

        // Set the emptyness
        tp.empty = true;
        tpl.empty = true;
        tpr.empty = true;

        // Insert the old data
        var oldval = rt.value();
        this.insert(tp, rt.x, rt.y, oldval, Bx, By, Bwid, Bhgt, tp.level);
        console.log("Finished moving down the previous entry");

        // NO Return: Rolls through to next if statement to continue inserting the new data.
        rt = tp;
      }

      // If it isn't a leaf, then we have an internal node to insert into
      if (level % 2 == 0) // Branch on X
      {
        if (rt.x < (Bx + Bwid/2)) // Insert left
        {
          // This ensures that the data will be stored due to an empty node being placed where it is needed to recurse
          if (typeof rt.left() === 'undefined')
          {
            rt.left(this.tree.newNode(''));
            rt.left().leaf = true;
            rt.left().empty = true;
          }

          console.log("Branch on X, Insert Left");
          jsav.umsg("Branch on X, Insert Left");
          rt.left(this.insert(rt.left(), INx, INy, INrec, Bx, By, Bwid/2, Bhgt, level+1));
        }
        else
        {
          if (typeof rt.right() === 'undefined')
          {
            rt.right(this.tree.newNode(''));
            rt.right().leaf = true;
            rt.right().empty = true;
          }

          console.log("Branch on X, Insert Right: ", rt.right());
          jsav.umsg("Branch on X, Insert Right");
          rt.right(this.insert(rt.right(), INx, INy, INrec, Bx + Bwid/2, By, Bwid/2, Bhgt, level+1));
        }
      }

      else // Branch on Y
      {
        if (rt.y < (By + Bhgt/2)) // Insert left
        {
          if (typeof rt.left() === 'undefined')
          {
            rt.left(this.tree.newNode(''));
            rt.left().leaf = true;
            rt.left().empty = true;
          }

          console.log("Branch on Y, Insert Left: ", rt.left());
          jsav.umsg("Branch on Y, Insert Left");
          rt.left(this.insert(rt.left(), INx, INy, INrec, Bx, By, Bwid, Bhgt/2, level+1));
        }
        else
        {

          if (typeof rt.right() === 'undefined')
          {
            rt.right(this.tree.newNode(''));
            rt.right().leaf = true;
            rt.right().empty = true;
          }

          console.log("Branch on Y, Insert Right: ", rt.right());
          jsav.umsg("Branch on Y, Insert Right");
          rt.right(this.insert(rt.right(), INx, INy, INrec, Bx, By + Bhgt/2, Bwid, Bhgt/2, level+1));
        }
      }

      this.tree.layout();
      return rt;
    } // insert

    this.delete = function (rt, INx, INy, Bx, By, Bwid, Bhgt, level) {
      console.assert( !(rt.leaf == true && rt.empty == true), "Cannot be an empty leaf during delete");

      if (rt.leaf) {
        if (rt.x == INx && rt.y == INy)
        {
          var temp = tree.newNode('');
          temp.leaf = true;
          temp.empty = true;
          return temp;
        }
        // else ERROR: THIS IS IMPOSSIBLE;
      };

      // We have an internal node
      if (level % 2 == 0) // Branch on X
      {
        if (INx < (Bx + Bwid/2)) // delete left
        {
          console.log("Branch on X, Delete Left");
          rt.left(delete(rt.left(), INx, INy, Bx, By, Bwid/2, Bhgt, level+1));
        }
        else
        {
          console.log("Branch on X, Delete Right");
          rt.right(delete(rt.right(), INx, INy, Bx + Bwid/2, By, Bwid/2, Bhgt, level+1));
        }
      }

      else // Branch on Y
      {
        if (INy < (By + Bhgt/2)) // Insert left
        {
          rt.left(delete(rt.left(), INx, INy, Bx, By, Bwid, Bhgt/2, level+1));
        }
        else
          rt.right(delete(rt.right(), INx, INy, Bx, By + Bhgt/2, Bwid, Bhgt/2, level+1));
      }

      tree.layout();

      // Now, check to see if there should be a merge
      if ((rt.left().leaf == true && rt.left().empty == true) && (rt.right().leaf))
      {
        return rt.right();
      }
      if ((rt.left().leaf) && (rt.right().leaf && rt.left.empty))
      {
        return rt.left();
      }

      // Otherwise, return just the rt subtree without a merge
      return rt;

    } // delete

  } // bintree

  var arr;

  // check query parameters from URL
  var params = JSAV.utils.getQueryParameter();
  if ("increments" in params) { // set value of increments if it is a param
    $('#increments').val(params.increments).prop("disabled", true);
  }

  // create a new settings panel and specify the link to show it
  var settings = new JSAV.utils.Settings($(".jsavsettings"));
  // add the layout setting preference
  var arrayLayout = settings.add("layout",
    {"type": "select", "options": {"bar": "Bar", "array": "Array"},
     "label": "Array layout: ", "value": "bar"});

  // Initialize the arraysize dropdown list
  ODSA.AV.initArraySize(5, 16, 8);

  // Process help button: Give a full help page for this activity
  // We might give them another HTML page to look at.
  function help() {
    window.open("bintreeHelpAV.html", 'helpwindow');
  }

  // Process About button: Pop up a message with an Alert
  function about() {
    alert("Bintree Visualization\nWritten by Anthony Rinaldi and Cliff Shaffer\nCreated as part of the OpenDSA hypertextbook project\nFor more information, see http://algoviz.org/OpenDSA\nSource and development history available at\nhttps://github.com/cashaffer/OpenDSA\nCompiled with JSAV library version " + JSAV.version());
  }

  // Execute the "Run" button function
  function runIt() {

    ODSA.AV.reset(true);

    var jsav = new JSAV($('.avcontainer'));

    jsav.umsg("Let's get started");
    console.log("Create the Bintree object");
    var bint = new Bintree(jsav, 200, 200);
    console.log("I just made a new Bintree, and bint.root is: ", bint.getRoot());
    bint.isEmpty();
    jsav.displayInit();

    jsav.step();

    // Setup the tree
    jsav.umsg("Step 1: insert node with value \"A\" @ 10, 10");
    // rt, INx, INy, INrec, Bx, By, Bwid, Bhgt, level
    console.log("Let's call insert. bint.root is now: ", bint.getRoot());
    bint.add(10, 10, "A", 100, 100, 200, 200, 0);
    //bint.isEmpty();

    jsav.step();

    // Insert another object
    jsav.umsg("Step 2: insert node with value \"B\" @ 5, 5");
    // rt, INx, INy, INrec, Bx, By, Bwid, Bhgt, level
    console.log("Let's call insert. bint.root is now: ", bint.getRoot());
    bint.add(5, 5, "B", 100, 100, 200, 200, 0);

    jsav.step();

    jsav.umsg("Step 2: insert node with value \"C\" @ 20, 20");
    //bint.add(20, 20, "C", 100, 100, 200, 200, 0);
    //bint.isEmpty();

    jsav.step();

  // Done
    jsav.umsg("All Done!");

    jsav.recorded(); // mark the end

  }

  // Connect action callbacks to the HTML entities
  $('#help').click(help);
  $('#about').click(about);
  $('#run').click(runIt);
  $('#reset').click(ODSA.AV.reset);

}(jQuery));<|endoftext|>


<commit_before>import React from 'react';
import {Platform, StyleSheet, ScrollView, View, TouchableHighlight} from 'react-native';
import {NavigationContext} from 'navigation-react';
import {SharedElement, NavigationBar, SearchBar, RightBar, BarButton} from 'navigation-react-native';

const Colors = ({colors, children, filter}) => {
  const suffix = filter != null ? '_search' : '';
  const matchedColors = colors.filter(color => (
    !filter || color.indexOf(filter.toLowerCase()) !== -1
  ));
  return (
    <NavigationContext.Consumer>
      {({stateNavigator}) => (
        <ScrollView
          style={styles.scene}
          contentInsetAdjustmentBehavior="automatic">
          <View style={styles.colors}>
            {matchedColors.map(color => (
              <TouchableHighlight
                key={color}
                style={styles.color}
                underlayColor={color}
                onPress={() => {
                  stateNavigator.navigate('detail', {
                    color, name: color + suffix, filter, search: filter != null
                  });
                }}>
                <SharedElement name={color + suffix} style={{flex: 1}}>
                  <View style={{backgroundColor: color, flex: 1}} />
                </SharedElement>
              </TouchableHighlight>
            ))}
            {children}
          </View>
        </ScrollView>
      )}
    </NavigationContext.Consumer>
  );
}

const Container = (props) => (
  Platform.OS === 'ios' ? <ScrollView {...props}/> : <View {...props} />
);

export default class Grid extends React.Component {
  constructor(props) {
    super(props);
    this.state = {text: ''};
  }
  render() {
    const {colors} = this.props;
    return (
      <>
        <ScrollView
          style={styles.scene}
          nestedScrollEnabled={true}
          contentInsetAdjustmentBehavior="automatic">
          <View style={styles.colors}>
            {colors.map(color => (
              <TouchableHighlight
                key={color}
                style={styles.color}
                underlayColor={color}>
                <View style={{backgroundColor: color, flex: 1}} />
              </TouchableHighlight>
            ))}
          </View>
        </ScrollView>
        <NavigationBar title="Colors" />
      </>
    );
  }
}

const styles = StyleSheet.create({
  scene: {
    backgroundColor: '#fff',
    flex: 1,
  },
  colors: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'center',
    marginTop: 10,
  },
  color: {
    width: 100,
    height: 150,
    marginLeft: 10,
    marginRight: 10,
    marginBottom: 20,
  },
});<commit_msg>Moved nav bar to top<commit_after>import React from 'react';
import {Platform, StyleSheet, ScrollView, View, TouchableHighlight} from 'react-native';
import {NavigationContext} from 'navigation-react';
import {SharedElement, NavigationBar, SearchBar, RightBar, BarButton} from 'navigation-react-native';

const Colors = ({colors, children, filter}) => {
  const suffix = filter != null ? '_search' : '';
  const matchedColors = colors.filter(color => (
    !filter || color.indexOf(filter.toLowerCase()) !== -1
  ));
  return (
    <NavigationContext.Consumer>
      {({stateNavigator}) => (
        <ScrollView
          style={styles.scene}
          contentInsetAdjustmentBehavior="automatic">
          <View style={styles.colors}>
            {matchedColors.map(color => (
              <TouchableHighlight
                key={color}
                style={styles.color}
                underlayColor={color}
                onPress={() => {
                  stateNavigator.navigate('detail', {
                    color, name: color + suffix, filter, search: filter != null
                  });
                }}>
                <SharedElement name={color + suffix} style={{flex: 1}}>
                  <View style={{backgroundColor: color, flex: 1}} />
                </SharedElement>
              </TouchableHighlight>
            ))}
            {children}
          </View>
        </ScrollView>
      )}
    </NavigationContext.Consumer>
  );
}

const Container = (props) => (
  Platform.OS === 'ios' ? <ScrollView {...props}/> : <View {...props} />
);

export default class Grid extends React.Component {
  constructor(props) {
    super(props);
    this.state = {text: ''};
  }
  render() {
    const {colors} = this.props;
    return (
      <>
        <NavigationBar title="Colors" />
        <ScrollView
          style={styles.scene}
          nestedScrollEnabled={true}
          contentInsetAdjustmentBehavior="automatic">
          <View style={styles.colors}>
            {colors.map(color => (
              <TouchableHighlight
                key={color}
                style={styles.color}
                underlayColor={color}>
                <View style={{backgroundColor: color, flex: 1}} />
              </TouchableHighlight>
            ))}
          </View>
        </ScrollView>
      </>
    );
  }
}

const styles = StyleSheet.create({
  scene: {
    backgroundColor: '#fff',
    flex: 1,
  },
  colors: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    justifyContent: 'center',
    marginTop: 10,
  },
  color: {
    width: 100,
    height: 150,
    marginLeft: 10,
    marginRight: 10,
    marginBottom: 20,
  },
});<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import electron, { shell, remote } from 'electron';
const Menu = remote.Menu
const MenuItem = remote.MenuItem
import fetch from 'node-fetch';
import config from '../../server/config';
import classnames from 'classnames';
import $ from 'jquery';
import util from "../utils/util";
import live from '../backend/live';

class RedPacketPage extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            type: "random",
            score_max: 200,
            score_min: 200,
            score_single: 100,
            score_count: 100,
            list: [],
        };
        this.match_id = 0;
    }

    componentDidMount() {
        this.timer();
    }

    timer(){
        setInterval(this.getRedpacketInfo.bind(this), 5 * 1000)
    }

    getTypeArr(){
        return {
            "random": {name: "随机积分", className:"label-important"},
            "fixed": {name: "固定积分", className:"label-success"},
        }
    }

    getType(value){
        let arr = this.getTypeArr();
        if(arr.hasOwnProperty(value)){
            return arr[value];
        }else{
            return {};
        }
    }

    getStatusArr(){
        return {
            0: {name: "未开始", className:"label-info", bsStyle:"default"},
            1: {name: "进行中", className:" label-success", bsStyle:"info"},
            9: {name: "已结束", className:" label-inverse", bsStyle:"success"},
        }
    }

    getScore(value){
        let arr = this.getScoreArr();
        if(arr.hasOwnProperty(value)){
            return arr[value];
        }else{
            return {};
        }
    }

    getScoreArr(){
        return {
            10: {name: "10", className:"", bsStyle:"default"},
            20: {name: "20", className:"", bsStyle:"info"},
            50: {name: "50", className:"", bsStyle:"success"},
        }
    }

    getStatus(value){
        let arr = this.getStatusArr();
        if(arr.hasOwnProperty(value)){
            return arr[value];
        }else{
            return {};
        }

    }

    getRedpacketInfo(match_id, callback){
        let self = this;
        if(!callback) callback = (redpacket) => self.setState({list: redpacket})
        live.sendMessage({
            r: "appredpacketapi/list",
            match_id: self.match_id,
        }, function(error, message, data){
            if(error){
                alert(message)
            }else{
                callback(data.data)
            }
        });
    }

    shouldComponentUpdate(nextProps, nextState){
        let bool = this.match_id != nextProps.matchId || this.state !== nextState
        if(this.match_id != nextProps.matchId){
            let self = this;
            this.match_id = nextProps.matchId;
            this.getRedpacketInfo(this.match_id)
        }
        return bool
    }

    sendRedpacket(data, callback){
        data.r = "appredpacketapi/add"
        data.match_id = this.match_id
        live.sendMessage(data, function(error, message, data){
            callback(error ? null : message)
        });
    }

    handlerDeleteRedpacket(redpacket_id){
        let self = this;
        if(!confirm("你确定要删除该信息吗?")){
            return false;
        }
        live.sendMessage({
            r: "appredpacketapi/delete",
            redpacket_id: redpacket_id,
        }, function(error, message, data){
            if(error)alert(message);
            else{
                self.getRedpacketInfo(self.match_id)
            }
        });
    }

    handlerSelectResult(redpacket_id, e){
        let self = this;
        live.sendMessage({
            r: "appredpacketapi/update",
            redpacket_id: redpacket_id,
            result_id: e.target.value,
            status: 9,
        }, function(error, message, data){
            if(error)alert(message);
            else{
                self.getRedpacketInfo(self.match_id)
            }
        });
    }

    handlerUpdateStatus(redpacket_id, e){
        let self = this;
        let data = {
            r: "appredpacketapi/update",
            redpacket_id: redpacket_id,
            status: e.target.value,
        }
        if(data.status == 1) data.start_time = parseInt(new Date().getTime() / 1000)
        if(data.status == 9) data.end_time = parseInt(new Date().getTime() / 1000)
        live.sendMessage(data, function(error, message, data){
            if(error)alert(message);
            else{
                self.getRedpacketInfo(self.match_id)
            }
        });
    }

    handlerSubmitRedpacket(e){
        let self = this;
        let data = {}
        data.title = this.refs.redpacket_title.getDOMNode().value
        data.type = this.refs.redpacket_type.getDOMNode().value
        data.status = this.refs.redpacket_status.getDOMNode().value
        data.score_count = this.state.score_count
        if(data.type == 'fixed'){
            data.score_single = this.state.score_single
        }else{
            data.score_max = this.state.score_max
        }

        self.sendRedpacket(data, function(err){
            if(err) alert(err)
            else{
                self.getRedpacketInfo(self.match_id)
            }
        })
    }

    handlerSelectType(e){
        let type = e.target.value;
        this.setState({type: type});
    }

    handleChange(key, e){
        let data = {}
        let value = parseInt(e.target.value)
        data[key] = value >= 0 && value < 99999 ? value : this.state.value;
        this.setState(data);
    }

    renderListType(item){
        if(item.type == "fixed"){
            return (

                        固定积分
                        {item.score_single}

                        数量
                        {item.score_count}

                        剩余数量
                        {item.score_surplus_count}

            )
        }else{
            return (

                        最大积分
                        {item.score_max}

                        数量
                        {item.score_count}

                        剩余数量
                        {item.score_surplus_count}

            )
        }
    }

    renderList(list){
        let self = this;
        return list.map((item, index) => {
            let typeItem = self.getType(item.type)
            let activeStatus = self.getStatus(item.status);
            let statusOption = Object.keys(self.getStatusArr()).map((status) => {
                let statusItem = self.getStatus(status);
                let selected = status == item.status ? "selected" : false;
                return <option selected={selected} value={status}>{statusItem.name}</option>
            })
            return (

                    <button type="button"  className="close" onClick={this.handlerDeleteRedpacket.bind(this, item.redpacket_id)}>×</button>

                       {item.title}

                    {this.renderListType(item)}
                    <span className={`label label-type ${typeItem.className}`}>{typeItem.name}
                    <select className={`label label-status ${activeStatus.className}`} onChange={this.handlerUpdateStatus.bind(this, item.redpacket_id)}>{statusOption}</select>

            )
        });
    }

    renderFormType(type){
        if(type == "fixed"){
            return (

                    积分
                    <input type="text" value={this.state.score_single} className="redpacket-option" onChange={this.handleChange.bind(this, "score_single")}/>
                    数量
                    <input type="text" value={this.state.score_count} className="redpacket-option" onChange={this.handleChange.bind(this, "score_count")}/>

            )
        }else{
            return (

                    最大
                    <input type="text" value={this.state.score_max} className="redpacket-option" onChange={this.handleChange.bind(this, "score_max")}/>
                    数量
                    <input type="text" value={this.state.score_count} className="redpacket-option" onChange={this.handleChange.bind(this, "score_count")}/>

            )
        }
    }

    renderForm(){
        let self = this;
        let submitButton = <button className="btn btn-info pull-right ">提交</button>;
        return (

                    <textarea ref="redpacket_title" rows="3" id="redpacket-title"  placeholder="竞猜红包描述" ></textarea>

                    类型
                    <select ref="redpacket_type" onChange={this.handlerSelectType.bind(this)} className="redpacket-type">
                        {
                            Object.keys(this.getTypeArr()).map((type, index) => {
                                let item = self.getType(type)
                                return <option value={type}>{item.name}</option>
                            })
                        }
                    </select>
                      状态
                    <select ref="redpacket_status" className="redpacket-status">
                        {
                            Object.keys(this.getStatusArr()).map((status, index) => {
                                let item = self.getStatus(status)
                                return <option value={status}>{item.name}</option>
                            })
                        }
                    </select>

                { this.renderFormType(this.state.type) }

 {submitButton}

        )
    }

    render() {
        const {list} = this.state;
        return (

红包列表

                        { this.renderList(this.state.list) }

                    { this.renderForm() }

        );
    }

}

RedPacketPage.propTypes = {
    matchId: PropTypes.string,
};

export default RedPacketPage;
<commit_msg>add redpacket +2<commit_after>import React, { Component, PropTypes } from 'react';
import electron, { shell, remote } from 'electron';
const Menu = remote.Menu
const MenuItem = remote.MenuItem
import fetch from 'node-fetch';
import config from '../../server/config';
import classnames from 'classnames';
import $ from 'jquery';
import util from "../utils/util";
import live from '../backend/live';

class RedPacketPage extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            type: "random",
            score_max: 200,
            score_min: 200,
            score_single: 100,
            score_count: 100,
            list: [],
        };
        this.match_id = 0;
    }

    componentDidMount() {
        this.timer();
    }

    timer(){
        setInterval(this.getRedpacketInfo.bind(this), 5 * 1000)
    }

    getTypeArr(){
        return {
            "random": {name: "随机积分", className:"label-important"},
            "fixed": {name: "固定积分", className:"label-success"},
        }
    }

    getType(value){
        let arr = this.getTypeArr();
        if(arr.hasOwnProperty(value)){
            return arr[value];
        }else{
            return {};
        }
    }

    getStatusArr(){
        return {
            0: {name: "未开始", className:"label-info", bsStyle:"default"},
            1: {name: "进行中", className:" label-success", bsStyle:"info"},
            9: {name: "已结束", className:" label-inverse", bsStyle:"success"},
        }
    }

    getScore(value){
        let arr = this.getScoreArr();
        if(arr.hasOwnProperty(value)){
            return arr[value];
        }else{
            return {};
        }
    }

    getScoreArr(){
        return {
            10: {name: "10", className:"", bsStyle:"default"},
            20: {name: "20", className:"", bsStyle:"info"},
            50: {name: "50", className:"", bsStyle:"success"},
        }
    }

    getStatus(value){
        let arr = this.getStatusArr();
        if(arr.hasOwnProperty(value)){
            return arr[value];
        }else{
            return {};
        }

    }

    getRedpacketInfo(match_id, callback){
        let self = this;
        if(!callback) callback = (redpacket) => self.setState({list: redpacket})
        live.sendMessage({
            r: "appredpacketapi/list",
            match_id: self.match_id,
        }, function(error, message, data){
            if(error){
                alert(message)
            }else{
                callback(data.data)
            }
        });
    }

    shouldComponentUpdate(nextProps, nextState){
        let bool = this.match_id != nextProps.matchId || this.state !== nextState
        if(this.match_id != nextProps.matchId){
            let self = this;
            this.match_id = nextProps.matchId;
            this.getRedpacketInfo(this.match_id)
        }
        return bool
    }

    sendRedpacket(data, callback){
        data.r = "appredpacketapi/add"
        data.match_id = this.match_id
        live.sendMessage(data, function(error, message, data){
            callback(error ? null : message)
        });
    }

    handlerDeleteRedpacket(redpacket_id){
        let self = this;
        if(!confirm("你确定要删除该信息吗?")){
            return false;
        }
        live.sendMessage({
            r: "appredpacketapi/delete",
            redpacket_id: redpacket_id,
        }, function(error, message, data){
            if(error)alert(message);
            else{
                self.getRedpacketInfo(self.match_id)
            }
        });
    }

    handlerSelectResult(redpacket_id, e){
        let self = this;
        live.sendMessage({
            r: "appredpacketapi/update",
            redpacket_id: redpacket_id,
            result_id: e.target.value,
            status: 9,
        }, function(error, message, data){
            if(error)alert(message);
            else{
                self.getRedpacketInfo(self.match_id)
            }
        });
    }

    handlerUpdateStatus(redpacket_id, e){
        let self = this;
        let data = {
            r: "appredpacketapi/update",
            redpacket_id: redpacket_id,
            status: e.target.value,
        }
        if(data.status == 1) data.start_time = parseInt(new Date().getTime() / 1000)
        if(data.status == 9) data.end_time = parseInt(new Date().getTime() / 1000)
        live.sendMessage(data, function(error, message, data){
            if(error)alert(message);
            else{
                self.getRedpacketInfo(self.match_id)
            }
        });
    }

    handlerSubmitRedpacket(e){
        let self = this;
        let data = {}
        data.title = this.refs.redpacket_title.getDOMNode().value
        data.type = this.refs.redpacket_type.getDOMNode().value
        data.status = this.refs.redpacket_status.getDOMNode().value
        data.score_count = this.state.score_count
        if(data.type == 'fixed'){
            data.score_single = this.state.score_single
        }else{
            data.score_min = 1
            data.score_max = this.state.score_max
        }

        self.sendRedpacket(data, function(err){
            if(err) alert(err)
            else{
                self.getRedpacketInfo(self.match_id)
            }
        })
    }

    handlerSelectType(e){
        let type = e.target.value;
        this.setState({type: type});
    }

    handleChange(key, e){
        let data = {}
        let value = parseInt(e.target.value)
        data[key] = value >= 0 && value < 99999 ? value : this.state.value;
        this.setState(data);
    }

    renderListType(item){
        if(item.type == "fixed"){
            return (

                        固定积分
                        {item.score_single}

                        数量
                        {item.score_count}

                        剩余数量
                        {item.score_surplus_count}

            )
        }else{
            return (

                        最大积分
                        {item.score_max}

                        数量
                        {item.score_count}

                        剩余数量
                        {item.score_surplus_count}

            )
        }
    }

    renderList(list){
        let self = this;
        return list.map((item, index) => {
            let typeItem = self.getType(item.type)
            let activeStatus = self.getStatus(item.status);
            let statusOption = Object.keys(self.getStatusArr()).map((status) => {
                let statusItem = self.getStatus(status);
                let selected = status == item.status ? "selected" : false;
                return <option selected={selected} value={status}>{statusItem.name}</option>
            })
            return (

                    <button type="button"  className="close" onClick={this.handlerDeleteRedpacket.bind(this, item.redpacket_id)}>×</button>

                       {item.title}

                    {this.renderListType(item)}
                    <span className={`label label-type ${typeItem.className}`}>{typeItem.name}
                    <select className={`label label-status ${activeStatus.className}`} onChange={this.handlerUpdateStatus.bind(this, item.redpacket_id)}>{statusOption}</select>

            )
        });
    }

    renderFormType(type){
        if(type == "fixed"){
            return (

                    积分
                    <input type="text" value={this.state.score_single} className="redpacket-option" onChange={this.handleChange.bind(this, "score_single")}/>
                    数量
                    <input type="text" value={this.state.score_count} className="redpacket-option" onChange={this.handleChange.bind(this, "score_count")}/>

            )
        }else{
            return (

                    最大
                    <input type="text" value={this.state.score_max} className="redpacket-option" onChange={this.handleChange.bind(this, "score_max")}/>
                    数量
                    <input type="text" value={this.state.score_count} className="redpacket-option" onChange={this.handleChange.bind(this, "score_count")}/>

            )
        }
    }

    renderForm(){
        let self = this;
        let submitButton = <button className="btn btn-info pull-right ">提交</button>;
        return (

                    <textarea ref="redpacket_title" rows="3" id="redpacket-title"  placeholder="竞猜红包描述" ></textarea>

                    类型
                    <select ref="redpacket_type" onChange={this.handlerSelectType.bind(this)} className="redpacket-type">
                        {
                            Object.keys(this.getTypeArr()).map((type, index) => {
                                let item = self.getType(type)
                                return <option value={type}>{item.name}</option>
                            })
                        }
                    </select>
                      状态
                    <select ref="redpacket_status" className="redpacket-status">
                        {
                            Object.keys(this.getStatusArr()).map((status, index) => {
                                let item = self.getStatus(status)
                                return <option value={status}>{item.name}</option>
                            })
                        }
                    </select>

                { this.renderFormType(this.state.type) }

 {submitButton}

        )
    }

    render() {
        const {list} = this.state;
        return (

红包列表

                        { this.renderList(this.state.list) }

                    { this.renderForm() }

        );
    }

}

RedPacketPage.propTypes = {
    matchId: PropTypes.string,
};

export default RedPacketPage;
<|endoftext|>


<commit_before>/**
 *
 */
const fs = require("fs");

const Raspberrypi = adaptor("raspberrypi"),
      Adaptor = lib('adaptor'),
      I2CDevice = lib("platforms/raspberrypi/i2c-device"),
      PwmPin = lib('platforms/raspberrypi/pwm-pin'),
      MockI2C = lib("platforms/raspberrypi/i2c");
      DigitalPin = lib('platforms/raspberrypi/digital-pin');

      const Arduino = require('./arduino');

      let arduino = new Arduino({
      	name: 'Arduino',
      	port: 'COM4'
      });

      arduino.connect();

      arduino.on('connect', (err) => {
      	console.log(arduino.name + ' is connected!');
      	// testAnalogRead();
      	// testSetNGetSamplingInterval();
      	// testI2CWrite();
      	// testI2CRead();
      	// testServo();
      	// testPwmWrite();
      	testSerial();
      });

      /* Test digital Write */
      function testDigitalReadAndWrite() {
      	arduino.digitalWrite(11, 1);
      }

      /* Test pwmWrite */
      function testPwmWrite() {
      	let ledPin = 9;
      	let val = 0;
      	let add = true;
      	setInterval(() => {
      		arduino.pwmWrite(ledPin, val/200);
      		if (add) {
      			val += 2;
      			if (val == 80) {
      				add = false;
      			}
      		} else {
      			val -= 2;
      			if (val == 0) {
      				add = true;
      			}
      		}
      	}, 30);
      }

      /* Test analog read */
      function testAnalogRead() {
      	let pot = 0;
      	arduino.analogRead(0, (err, val, pin) => {
      		console.log(val, pin);
      	});
      }

      /* Test set & get samplingInterval */
      function testSetNGetSamplingInterval() {
      	console.log('Default value before setting: ', arduino.getSamplingInterval());
      	arduino.setSamplingInterval(100);
      	console.log('After setting: ', arduino.getSamplingInterval());
      }

      /* Test i2c write*/
      function testI2CWrite() {
      	let x = 20;
      	let slaveAddress = 8;
      	setInterval(() => {
      		arduino.i2cWrite(slaveAddress, 'x is ');
      		arduino.i2cWrite(slaveAddress, x++);
      	}, 1000);
      }

      /* Test i2c read*/
      function testI2CRead() {
      	let slaveAddress = 8;

      	arduino.i2cReadOnce(slaveAddress, 16, (err, data) => {
      		console.log('-------- Read Once --------');
      		console.log(data);
      		console.log('------ Read Once End ------')
      	});

      	arduino.i2cRead(slaveAddress, null, 8, (err, data) => {
      		console.log(data);
      	});
      }

      /* Test Servo */
      function testServo() {
      	let pin = 9;

      	let degree = 5;
      	arduino.servoWrite(pin, 5);
      	setTimeout(() => {
      		arduino.servoWrite(pin, 15);
      	}, 5000);
      }

      /* TODO Test Serial config */
      function testSerial() {
      	// setInterval(() => {
      	// 	arduino.serialWrite(0, 'hello, world!');
      	// }, 3000);

      	arduino.serialConfig(0x08, 4800, 10, 11);
      	arduino.serialRead(0x08, 10, (err, data, port) => {
      		console.log('Read from serial port:', port, '\nDATA:', data);
      	});

      	setTimeout(() => {
      		arduino.serialStop(0x08);
      	}, 5000);
      	arduino.on('serialStop', (port) => {
      		console.log('Serial port ' + port + ' stopped');
      	});

      	setTimeout(() => {
      		arduino.serialClose(0x08);
      	}, 8000);
      	arduino.on('serialClose', (port) => {
      		console.log('Serial port ' + port + ' closed');
      	});

      }<commit_msg>adaptor test for raspi<commit_after>/**
 *
 */
const fs = require("fs");

const Raspberrypi = require('./raspberrypi');
      I2CDevice = require("./i2c-device"),
      PwmPin = require('./pwm-pin'),
      MockI2C = require("./i2c");
      DigitalPin = require('./digital-pin');

      let raspberrypi = new Raspberrypi({
      	name: 'Raspberrypi',
      	port: 'no need'
      });

      raspberrypi.connect();

      raspberrypi.on('connect', (err) => {
      	console.log(raspberrypi.name + ' is connected!');
      	testDigitalRead();
      	//testDigitalWrite();
      	// testI2CWrite();
      	// testI2CRead();
      	// testServo();
      	// testPwmWrite();
      	testSerial();
      });

      /* Test digital read */
      function testDigitalRead() {
      	let pin = 7;
      	raspberrypi.digitalRead(pin, (err, pin) => {
      		console.log(pin+" test digital read");
      	});
      }

      /* Test digital Write */
      function testDigitalWrite() {
      	raspberrypi.digitalWrite(7, 1,()=>{
      		console.log('pinNum:'+pinNum+"  value:"+value+"   test digital write");
      	});
      }

      /* Test i2c write*/
      function testI2CWrite() {
      	let buffer = '1100011';
      	let address = 8;
      	let cmd = 'w'
      	setInterval(() => {
      		raspberrypi.i2cWrite(address,cmd,buffer,(address,cmd,buffer)=>{
      			console.log("address:  "+address+"  test i2c write");
      		});
      	}, 1000);
      }

      /* Test i2c read*/
      function testI2CRead() {
      	let address = 8;
      	let cmd='r';
        let length = 8;

      	raspberrypi.i2cRead(address, cmd,length, (err, data) => {
      		console.log('-------- I2C Read  --------');
      		console.log(data);
      		console.log('------ I2C Read End ------')
      	});
      }

      /* Test pwmWrite */
      function testPwmWrite() {
      	let ledPin = 7;
      	let angle = 0;
      	let add = true;
      	setInterval(() => {
      		raspberrypi.pwmWrite(ledPin, angle/200,(err,angle)=>{
      			console.log("angle:  "+angle  +" test pwm write");
      		});
      		if (add) {
      			angle += 2;
      			if (angle == 80) {
      				add = false;
      			}
      		} else {
      			angle -= 2;
      			if (angle == 0) {
      				add = true;
      			}
      		}
      	}, 30);
      }

      /* Test Servo */
      function testServo() {
      	let pin = 7;

      	let degree = 5;
      	raspberrypi.servoWrite(pin, 5,(err,angle)=>{
      		console.log("angle:" + angle+"  test servo write");
      	});
      	setTimeout(() => {
      		raspberrypi.servoWrite(pin, 15,(err,angle)=>{
          		console.log("angle:" + angle+"  test servo write");
          	});
      	}, 5000);
      }

 <|endoftext|>