<commit_before>import WorkerPool from '../extra/worker-pool';

function wavefrontWorker(responder, options) {

    var timerName = 'Parsing OBJ file';

    var startTimer = console.time.bind(console);
    var stopTimer = console.timeEnd.bind(console);

    startTimer(timerName);

    var INITIAL_BUFFER_SIZE = 1 << 16;
    var UintXArray = Uint16Array;
    var global = self || window;

    // Contains points
    var vertices = new Array(INITIAL_BUFFER_SIZE),
        normals = new Array(INITIAL_BUFFER_SIZE),
        texcoords = new Array(INITIAL_BUFFER_SIZE);

    // Contains arrays of length 3. Three arrays make a triangle
    var triangles = new Array(INITIAL_BUFFER_SIZE);

    var startIndex = 0, stopIndex = 0;
    var currentMaterial = 'default';

    var processModel = (function () {

        var triangleIndices = new Array(INITIAL_BUFFER_SIZE),
            vertexIndices = new Array(INITIAL_BUFFER_SIZE),
            texcoordIndices = new Array(INITIAL_BUFFER_SIZE),
            normalIndices = new Array(INITIAL_BUFFER_SIZE);

        return function processModel() {

            // Maps tuples of vertex, texcoord and normal indices to new indices
            var uniqueIndices = {};

            var uniqueIndexCount = 0 | 0,
                triangleIndexCount = 0 | 0,
                vertexIndexCount = 0 | 0,
                texcoordIndexCount = 0 | 0,
                normalIndexCount = 0 | 0;

            var i = 0 | 0,
                oldOffset = 0 | 0,
                newOffset = 0 | 0;

            for (i = startIndex; i < stopIndex; i += 3) {

                // Extract id:s
                var v_id = triangles[i],
                    vt_id = triangles[i + 1],
                    vn_id = triangles[i + 2];

                // Create the key
                var key = v_id;
                key += ':';
                key += vt_id;
                key += ':';
                key += vn_id;

                // Try to fetch the new index
                var newIndex = uniqueIndices[key];

                // The new index did not exist, create it
                if (newIndex === undefined) {
                    // Allocate the new index and store it
                    newIndex = uniqueIndices[key] = uniqueIndexCount++;

                    vertexIndices[vertexIndexCount++] = v_id;

                    // -1 signals non-existing index
                    if (vt_id !== -1) texcoordIndices[texcoordIndexCount++] = vt_id;
                    if (vn_id !== -1) normalIndices[normalIndexCount++] = vn_id;
                }

                // Store the new index
                triangleIndices[triangleIndexCount++] = newIndex;
            }

            // The typed arrays to return
            var newIndices = new UintXArray(triangleIndexCount),
                newVertices = new Float32Array(3 * vertexIndexCount),
                newNormals = new Float32Array(3 * normalIndexCount),
                newTexcoords = new Float32Array(2 * texcoordIndexCount);

            // Copy face indices over
            for (i = 0; i < triangleIndexCount; ++i) {
                newIndices[i] = triangleIndices[i];
            }

            // Copy the vertices to the new locations
            for (i = 0, newOffset = 0; i < vertexIndexCount; ++i, newOffset += 3) {
                oldOffset = 3 * vertexIndices[i];

                newVertices[newOffset] = vertices[oldOffset];
                newVertices[newOffset + 1] = vertices[oldOffset + 1];
                newVertices[newOffset + 2] = vertices[oldOffset + 2];
            }

            // Copy the normals to the new locations
            for (i = 0, newOffset = 0; i < normalIndexCount; ++i, newOffset += 3) {
                oldOffset = 3 * normalIndices[i];

                newNormals[newOffset] = normals[oldOffset];
                newNormals[newOffset + 1] = normals[oldOffset + 1];
                newNormals[newOffset + 2] = normals[oldOffset + 2];
            }

            // Copy the texcoords to the new locations
            for (i = 0, newOffset = 0; i < texcoordIndexCount; ++i, newOffset += 2) {
                oldOffset = 2 * texcoordIndices[i];

                newTexcoords[newOffset] = texcoords[oldOffset];
                newTexcoords[newOffset + 1] = texcoords[oldOffset + 1];
            }

            responder.progress(['geometry', {
                indices: newIndices,
                vertices: newVertices,
                normals: newNormals,
                texcoords: newTexcoords,
                materialName: currentMaterial
            }], [
                newIndices.buffer,
                newVertices.buffer,
                newNormals.buffer,
                newTexcoords.buffer
            ]);

            startIndex = stopIndex;
        };
    })();

    var processLine = (function () {

        var firstMaterial = true;

        var v_i = 0|0, // 3 * vertex count
            vn_i = 0|0, // 3 * normal count
            vt_i = 0|0; // 2 * texcoord count

        var polygon = [];

        return function processLine(line) {
            var i = 0|0,
                lineLength = line.length;

            switch (line[0]) {
            case 'mtllib':
                var mtllib = line[1];
                for (i = 2; i < lineLength; ++i) mtllib += line[i];
                responder.progress(['mtllib', mtllib]);
                break;

            case 'usemtl':
                if (!firstMaterial) {
                    processModel();
                }

                currentMaterial = line[1];

                for (i = 2; i < lineLength; ++i) {
                    currentMaterial += ' ' + line[i];
                }

                firstMaterial = false;
                break;

            case 'v':
                vertices[v_i++] = +line[1];
                vertices[v_i++] = +line[2];
                vertices[v_i++] = +line[3];
                break;

            case 'vt':
                texcoords[vt_i++] = +line[1];
                texcoords[vt_i++] = +line[2];
                break;

            case 'vn':
                normals[vn_i++] = +line[1];
                normals[vn_i++] = +line[2];
                normals[vn_i++] = +line[3];
                break;

            case 'f':
                var points;

                for (i = 1; i < lineLength; ++i) {
                    points = line[i].split('/');
                    var value = 0 | 0;

                    // Correct for absolute or relative indexing
                    // Empty strings result in index === -1
                    value = ~~points[0];
                    points[0] = value >= 0 ? value - 1 : value + v_i / 3;
                    value = ~~points[1];
                    points[1] = value >= 0 ? value - 1 : value + vt_i / 2;
                    value = ~~points[2];
                    points[2] = value >= 0 ? value - 1 : value + vn_i / 3;

                    polygon[i - 1] = points;
                }

                // If points are fewer than 3, repeat to form a triangle
                if (lineLength < 4) {
                    for (i = lineLength - 1; i <= 3; ++i) {
                        polygon[i] = polygon[lineLength - 2];
                    }
                }

                // Triangulate and store each triangle as 9 values
                for (i = 1; i < lineLength - 2; ++i) {
                    // First point: (v, vt, vn)
                    points = polygon[0];
                    triangles[stopIndex++] = points[0];
                    triangles[stopIndex++] = points[1];
                    triangles[stopIndex++] = points[2];

                    // Second point: (v, vt, vn)
                    points = polygon[i];
                    triangles[stopIndex++] = points[0];
                    triangles[stopIndex++] = points[1];
                    triangles[stopIndex++] = points[2];

                    // Third point: (v, vt, vn)
                    points = polygon[i + 1];
                    triangles[stopIndex++] = points[0];
                    triangles[stopIndex++] = points[1];
                    triangles[stopIndex++] = points[2];
                }
            }
        };
    })();

    var supportsFetch = 'fetch' in global;
    var supportsStreamingResponse = 'Response' in global && 'body' in Response.prototype;
    var supportsTextDecoder = 'TextDecoder' in global;
    var isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;

    if (options.type === 'stream') {
        var filename = options.filename;

        // Stream natively using a ReadableStream with the fetch API. Available in Chrome 42+
        if (supportsFetch && supportsStreamingResponse && supportsTextDecoder) {

            // Consume the stream by piping it into a function
            function pipeTo(stream, fn) {
                var reader = stream.getReader();
                return (function search() {
                    return reader.read().then(function (result) {
                        fn(result);
                        if (!result.done) return search();
                    });
                })();
            }

            fetch(filename)
                .then(function (response) {
                    var decoder = new TextDecoder();
                    var lastLine = '';
                    var emptyArray = new Uint8Array();

                    return pipeTo(response.body, function (result) {
                        var str = decoder.decode(result.value || emptyArray, { stream: !result.done });
                        var lines = str.split(/[\r\n]+/);
                        var lastIndex = lines.length - 1;

                        processLine((lastLine + lines[0]).split(/\s+/));

                        for (var i = 1; i < lastIndex; ++i) {
                            processLine(lines[i].split(/\s+/));
                        }

                        lastLine = lines[lastIndex];

                        if (result.done) {
                            processLine(lastLine);
                        }
                    });
                })
                .then(function () {
                    processModel();
                    stopTimer(timerName);

                    responder.done();
                });

        } else {
            // Streaming hack using progress events

            var xhr = new XMLHttpRequest();
            xhr.open('GET', filename, true);
            xhr.responseType = isFirefox ? 'moz-chunked-text' : 'text';

            var prevLine = '';

            function processTextChunk(str, done) {
                var lines = str.split(/[\r\n]+/);
                var lastIndex = lines.length - 1;

                processLine((prevLine + lines[0]).split(/\s+/));

                for (var i = 1; i < lastIndex; ++i) {
                    processLine(lines[i].split(/\s+/));
                }

                prevLine = lines[lastIndex];

                if (done) processLine(prevLine);
            }

            var prevLength = 0;

            function processDataNormally(done) {
                processTextChunk(xhr.response.slice(prevLength), done);
                prevLength = xhr.response.length;
            }

            function processDataFirefox(done) {
                processTextChunk(xhr.response, done);
            }

            var processData = isFirefox ? processDataFirefox : processDataNormally;

            xhr.onerror = function (error) {
                responder.error('Something went wrong!!!');
            };

            xhr.onreadystatechange = function () {
                if (xhr.status === 200 && xhr.response) {
                    switch (xhr.readyState) {
                    case xhr.LOADING:
                        processData(false);
                        break;

                    case xhr.DONE:
                        processData(true);
                        processModel();

                        stopTimer(timerName);
                        responder.done();
                    }
                } else {
                    responder.error("Couldn't do it! " + xhr.status);
                }
            };

            xhr.send();
        }
    } else {
        var buffer = options.buffer;

        var str;
        if (supportsTextDecoder) {
            var decoder = new TextDecoder();
            str = decoder.decode(buffer);
        } else {
            var CHUNK_SIZE = 1 << 15;
            var array = new Uint8Array(buffer);

            for (var i = 0, len = array.length; i < len; i += CHUNK_SIZE) {
                str += String.fromCharCode.apply(undefined, array.subarray(i, Math.min(i + CHUNK_SIZE, len)));
            }
        }

        var lines = str.split(/[\r\n]+/);

        for (var i = 0, len = lines.length; i < len; ++i) {
            processLine(lines[i].trim().split(/\s+/));
        }

        processModel();

        stopTimer(timerName);
        responder.done();
    }
}

export const workerpool = WorkerPool.fromFunction(wavefrontWorker);
<commit_msg>Fix binary text parsing for browsers without TextDecoder<commit_after>import WorkerPool from '../extra/worker-pool';

function wavefrontWorker(responder, options) {

    var timerName = 'Parsing OBJ file';

    var startTimer = console.time.bind(console);
    var stopTimer = console.timeEnd.bind(console);

    startTimer(timerName);

    var INITIAL_BUFFER_SIZE = 1 << 16;
    var UintXArray = Uint16Array;
    var global = self || window;

    // Contains points
    var vertices = new Array(INITIAL_BUFFER_SIZE),
        normals = new Array(INITIAL_BUFFER_SIZE),
        texcoords = new Array(INITIAL_BUFFER_SIZE);

    // Contains arrays of length 3. Three arrays make a triangle
    var triangles = new Array(INITIAL_BUFFER_SIZE);

    var startIndex = 0, stopIndex = 0;
    var currentMaterial = 'default';

    var processModel = (function () {

        var triangleIndices = new Array(INITIAL_BUFFER_SIZE),
            vertexIndices = new Array(INITIAL_BUFFER_SIZE),
            texcoordIndices = new Array(INITIAL_BUFFER_SIZE),
            normalIndices = new Array(INITIAL_BUFFER_SIZE);

        return function processModel() {

            // Maps tuples of vertex, texcoord and normal indices to new indices
            var uniqueIndices = {};

            var uniqueIndexCount = 0 | 0,
                triangleIndexCount = 0 | 0,
                vertexIndexCount = 0 | 0,
                texcoordIndexCount = 0 | 0,
                normalIndexCount = 0 | 0;

            var i = 0 | 0,
                oldOffset = 0 | 0,
                newOffset = 0 | 0;

            for (i = startIndex; i < stopIndex; i += 3) {

                // Extract id:s
                var v_id = triangles[i],
                    vt_id = triangles[i + 1],
                    vn_id = triangles[i + 2];

                // Create the key
                var key = v_id;
                key += ':';
                key += vt_id;
                key += ':';
                key += vn_id;

                // Try to fetch the new index
                var newIndex = uniqueIndices[key];

                // The new index did not exist, create it
                if (newIndex === undefined) {
                    // Allocate the new index and store it
                    newIndex = uniqueIndices[key] = uniqueIndexCount++;

                    vertexIndices[vertexIndexCount++] = v_id;

                    // -1 signals non-existing index
                    if (vt_id !== -1) texcoordIndices[texcoordIndexCount++] = vt_id;
                    if (vn_id !== -1) normalIndices[normalIndexCount++] = vn_id;
                }

                // Store the new index
                triangleIndices[triangleIndexCount++] = newIndex;
            }

            // The typed arrays to return
            var newIndices = new UintXArray(triangleIndexCount),
                newVertices = new Float32Array(3 * vertexIndexCount),
                newNormals = new Float32Array(3 * normalIndexCount),
                newTexcoords = new Float32Array(2 * texcoordIndexCount);

            // Copy face indices over
            for (i = 0; i < triangleIndexCount; ++i) {
                newIndices[i] = triangleIndices[i];
            }

            // Copy the vertices to the new locations
            for (i = 0, newOffset = 0; i < vertexIndexCount; ++i, newOffset += 3) {
                oldOffset = 3 * vertexIndices[i];

                newVertices[newOffset] = vertices[oldOffset];
                newVertices[newOffset + 1] = vertices[oldOffset + 1];
                newVertices[newOffset + 2] = vertices[oldOffset + 2];
            }

            // Copy the normals to the new locations
            for (i = 0, newOffset = 0; i < normalIndexCount; ++i, newOffset += 3) {
                oldOffset = 3 * normalIndices[i];

                newNormals[newOffset] = normals[oldOffset];
                newNormals[newOffset + 1] = normals[oldOffset + 1];
                newNormals[newOffset + 2] = normals[oldOffset + 2];
            }

            // Copy the texcoords to the new locations
            for (i = 0, newOffset = 0; i < texcoordIndexCount; ++i, newOffset += 2) {
                oldOffset = 2 * texcoordIndices[i];

                newTexcoords[newOffset] = texcoords[oldOffset];
                newTexcoords[newOffset + 1] = texcoords[oldOffset + 1];
            }

            responder.progress(['geometry', {
                indices: newIndices,
                vertices: newVertices,
                normals: newNormals,
                texcoords: newTexcoords,
                materialName: currentMaterial
            }], [
                newIndices.buffer,
                newVertices.buffer,
                newNormals.buffer,
                newTexcoords.buffer
            ]);

            startIndex = stopIndex;
        };
    })();

    var processLine = (function () {

        var firstMaterial = true;

        var v_i = 0|0, // 3 * vertex count
            vn_i = 0|0, // 3 * normal count
            vt_i = 0|0; // 2 * texcoord count

        var polygon = [];

        return function processLine(line) {
            var i = 0|0,
                lineLength = line.length;

            switch (line[0]) {
            case 'mtllib':
                var mtllib = line[1];
                for (i = 2; i < lineLength; ++i) mtllib += line[i];
                responder.progress(['mtllib', mtllib]);
                break;

            case 'usemtl':
                if (!firstMaterial) {
                    processModel();
                }

                currentMaterial = line[1];

                for (i = 2; i < lineLength; ++i) {
                    currentMaterial += ' ' + line[i];
                }

                firstMaterial = false;
                break;

            case 'v':
                vertices[v_i++] = +line[1];
                vertices[v_i++] = +line[2];
                vertices[v_i++] = +line[3];
                break;

            case 'vt':
                texcoords[vt_i++] = +line[1];
                texcoords[vt_i++] = +line[2];
                break;

            case 'vn':
                normals[vn_i++] = +line[1];
                normals[vn_i++] = +line[2];
                normals[vn_i++] = +line[3];
                break;

            case 'f':
                var points;

                for (i = 1; i < lineLength; ++i) {
                    points = line[i].split('/');
                    var value = 0 | 0;

                    // Correct for absolute or relative indexing
                    // Empty strings result in index === -1
                    value = ~~points[0];
                    points[0] = value >= 0 ? value - 1 : value + v_i / 3;
                    value = ~~points[1];
                    points[1] = value >= 0 ? value - 1 : value + vt_i / 2;
                    value = ~~points[2];
                    points[2] = value >= 0 ? value - 1 : value + vn_i / 3;

                    polygon[i - 1] = points;
                }

                // If points are fewer than 3, repeat to form a triangle
                if (lineLength < 4) {
                    for (i = lineLength - 1; i <= 3; ++i) {
                        polygon[i] = polygon[lineLength - 2];
                    }
                }

                // Triangulate and store each triangle as 9 values
                for (i = 1; i < lineLength - 2; ++i) {
                    // First point: (v, vt, vn)
                    points = polygon[0];
                    triangles[stopIndex++] = points[0];
                    triangles[stopIndex++] = points[1];
                    triangles[stopIndex++] = points[2];

                    // Second point: (v, vt, vn)
                    points = polygon[i];
                    triangles[stopIndex++] = points[0];
                    triangles[stopIndex++] = points[1];
                    triangles[stopIndex++] = points[2];

                    // Third point: (v, vt, vn)
                    points = polygon[i + 1];
                    triangles[stopIndex++] = points[0];
                    triangles[stopIndex++] = points[1];
                    triangles[stopIndex++] = points[2];
                }
            }
        };
    })();

    var supportsFetch = 'fetch' in global;
    var supportsStreamingResponse = 'Response' in global && 'body' in Response.prototype;
    var supportsTextDecoder = 'TextDecoder' in global;
    var isFirefox = navigator.userAgent.indexOf('Firefox') !== -1;

    if (options.type === 'stream') {
        var filename = options.filename;

        // Stream natively using a ReadableStream with the fetch API. Available in Chrome 42+
        if (supportsFetch && supportsStreamingResponse && supportsTextDecoder) {

            // Consume the stream by piping it into a function
            function pipeTo(stream, fn) {
                var reader = stream.getReader();
                return (function search() {
                    return reader.read().then(function (result) {
                        fn(result);
                        if (!result.done) return search();
                    });
                })();
            }

            fetch(filename)
                .then(function (response) {
                    var decoder = new TextDecoder();
                    var lastLine = '';
                    var emptyArray = new Uint8Array();

                    return pipeTo(response.body, function (result) {
                        var str = decoder.decode(result.value || emptyArray, { stream: !result.done });
                        var lines = str.split(/[\r\n]+/);
                        var lastIndex = lines.length - 1;

                        processLine((lastLine + lines[0]).split(/\s+/));

                        for (var i = 1; i < lastIndex; ++i) {
                            processLine(lines[i].split(/\s+/));
                        }

                        lastLine = lines[lastIndex];

                        if (result.done) {
                            processLine(lastLine);
                        }
                    });
                })
                .then(function () {
                    processModel();
                    stopTimer(timerName);

                    responder.done();
                });

        } else {
            // Streaming hack using progress events

            var xhr = new XMLHttpRequest();
            xhr.open('GET', filename, true);
            xhr.responseType = isFirefox ? 'moz-chunked-text' : 'text';

            var prevLine = '';

            function processTextChunk(str, done) {
                var lines = str.split(/[\r\n]+/);
                var lastIndex = lines.length - 1;

                processLine((prevLine + lines[0]).split(/\s+/));

                for (var i = 1; i < lastIndex; ++i) {
                    processLine(lines[i].split(/\s+/));
                }

                prevLine = lines[lastIndex];

                if (done) processLine(prevLine);
            }

            var prevLength = 0;

            function processDataNormally(done) {
                processTextChunk(xhr.response.slice(prevLength), done);
                prevLength = xhr.response.length;
            }

            function processDataFirefox(done) {
                processTextChunk(xhr.response, done);
            }

            var processData = isFirefox ? processDataFirefox : processDataNormally;

            xhr.onerror = function (error) {
                responder.error('Something went wrong!!!');
            };

            xhr.onreadystatechange = function () {
                if (xhr.status === 200 && xhr.response) {
                    switch (xhr.readyState) {
                    case xhr.LOADING:
                        processData(false);
                        break;

                    case xhr.DONE:
                        processData(true);
                        processModel();

                        stopTimer(timerName);
                        responder.done();
                    }
                } else {
                    responder.error("Couldn't do it! " + xhr.status);
                }
            };

            xhr.send();
        }
    } else {
        var buffer = options.buffer;

        var str;
        if (supportsTextDecoder) {
            var decoder = new TextDecoder();
            str = decoder.decode(buffer);
        } else {
            var CHUNK_SIZE = 1 << 15;
            var array = new Uint8Array(buffer);

            str = '';
            for (var i = 0, len = array.length; i < len; i += CHUNK_SIZE) {
                str += String.fromCharCode.apply(undefined, array.subarray(i, Math.min(i + CHUNK_SIZE, len)));
            }
        }

        var lines = str.split(/[\r\n]+/);

        for (var i = 0, len = lines.length; i < len; ++i) {
            processLine(lines[i].trim().split(/\s+/));
        }

        processModel();

        stopTimer(timerName);
        responder.done();
    }
}

export const workerpool = WorkerPool.fromFunction(wavefrontWorker);
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react'
import Ink from 'react-ink'
import styles from 'part:@sanity/components/buttons/default-style'
import Spinner from 'part:@sanity/components/loading/spinner'

export default class DefaultButton extends React.Component {
  static propTypes = {
    kind: PropTypes.oneOf(['simple', 'secondary']),
    color: PropTypes.oneOf(['primary', 'success', 'danger', 'white']),
    onClick: PropTypes.func,
    children: PropTypes.node,
    inverted: PropTypes.bool,
    icon: PropTypes.func,
    loading: PropTypes.bool,
    ripple: PropTypes.bool,
    className: PropTypes.string,
    disabled: PropTypes.bool,
    tabIndex: PropTypes.number
  }

  static defaultProps = {
    ripple: true,
    icon: null,
    onClick() {},
    tabIndex: 0
  }

  constructor(...args) {
    super(...args)

    this.handleClick = this.handleClick.bind(this)

    this.state = {
      recentlyHovered: false
    }
  }

  handleClick(event) {
    this.setState({
      recentlyHovered: true
    })
    this.props.onClick(event)
    this.timeOut = setTimeout(() => {
      this.setState({
        recentlyHovered: true
      })
    }, 300)
  }

  render() {

    const {kind, ripple, disabled, inverted, color, icon, loading, className, children, ...rest} = this.props

    const Icon = icon

    const style = `
      ${(inverted ? styles.inverted : '')}
      ${kind ? styles[kind] : styles.default}
      ${color ? styles[`color__${color}`] : ''}
      ${Icon ? styles.hasIcon : ''}
      ${className || ''}
      ${disabled ? styles.disabled : ''}
      ${this.state.recentlyHovered ? styles.recentlyHovered : styles.notRecentlyHovered}`

    return (
      <button
        {...rest}
        className={style}
        type="button"
        onClick={this.handleClick}
        disabled={disabled}
      >

          {
            loading && <Spinner />
          }
          {
            Icon && <Icon className={styles.icon} />
          }
          {
            children && {children}
          }
          {
            ripple && !disabled && <Ink duration={200} opacity={0.10} radius={200} />
          }

      </button>
    )
  }
}
<commit_msg>setting prop kind to default<commit_after>import React, {PropTypes} from 'react'
import Ink from 'react-ink'
import styles from 'part:@sanity/components/buttons/default-style'
import Spinner from 'part:@sanity/components/loading/spinner'

export default class DefaultButton extends React.Component {
  static propTypes = {
    kind: PropTypes.oneOf(['default', 'simple', 'secondary']),
    color: PropTypes.oneOf(['primary', 'success', 'danger', 'white']),
    onClick: PropTypes.func,
    children: PropTypes.node,
    inverted: PropTypes.bool,
    icon: PropTypes.func,
    loading: PropTypes.bool,
    ripple: PropTypes.bool,
    className: PropTypes.string,
    disabled: PropTypes.bool,
    tabIndex: PropTypes.number
  }

  static defaultProps = {
    ripple: true,
    icon: null,
    onClick() {},
    kind: 'default'
  }

  constructor(...args) {
    super(...args)

    this.handleClick = this.handleClick.bind(this)

    this.state = {
      recentlyHovered: false
    }
  }

  handleClick(event) {
    this.setState({
      recentlyHovered: true
    })
    this.props.onClick(event)
    this.timeOut = setTimeout(() => {
      this.setState({
        recentlyHovered: true
      })
    }, 300)
  }

  render() {

    const {kind, ripple, disabled, inverted, color, icon, loading, className, children, ...rest} = this.props

    const Icon = icon

    const style = `
      ${(inverted ? styles.inverted : '')}
      ${kind ? styles[kind] : styles.default}
      ${color ? styles[`color__${color}`] : ''}
      ${Icon ? styles.hasIcon : ''}
      ${className || ''}
      ${disabled ? styles.disabled : ''}
      ${this.state.recentlyHovered ? styles.recentlyHovered : styles.notRecentlyHovered}`

    return (
      <button
        {...rest}
        className={style}
        type="button"
        onClick={this.handleClick}
        disabled={disabled}
      >

          {
            loading && <Spinner />
          }
          {
            Icon && <Icon className={styles.icon} />
          }
          {
            children && {children}
          }
          {
            ripple && !disabled && <Ink duration={200} opacity={0.10} radius={200} />
          }

      </button>
    )
  }
}
<|endoftext|>


<commit_before>/* Add modules */
var crypto = require('crypto'),
    db = require('./database'),
    config = require('./config');

var tasks = [];
var currentTask = 0;

exports.getTasks = function getTasks() {
    return tasks;
}

/* Get new task */
exports.getTask = function getTask() {
    /* Update tasks */
    db.Task.find(function(err, db_tasks) {
        if (err) return new Error(err);
        else tasks = etasks = db_tasks;
    });
    if (tasks.length == 0) return { name: "Currently no tasks available" };
    return { name: "Task " + (currentTask + 1) + ": " + tasks[currentTask].name, points: tasks[currentTask].points };
}

/* Check if task is complete */
exports.taskComplete = function taskComplete(code) {
    if (tasks.length == 0) return false;
    /* When task was completed */
    if (code.replace(/\s+/g, '').match(tasks[currentTask].verification)) {
        currentTask = (currentTask + 1) % tasks.length;
        return true;
    }
    return false;
}

/* Hashing function */
exports.calculateHash = function calculateHash(type, text) {
    var shasum = crypto.createHash(type);
    shasum.update(text);
    return shasum.digest('hex');
}

/* Random function */
exports.generateRandom = function generateRandom() {
    /* TODO: Add existing check, or add date + time */
    var current_date = (new Date()).valueOf().toString();
    var random = parseInt(Math.random()*100);
    return random;
}

/* Generate a random guest account */
exports.generateGuest = function generateGuest() {
    var random = exports.generateRandom();
    var randomEmailHash = exports.calculateHash('md5', random + "@gmail.com");
    var user = {
        name: "Guest" + random,
        email: random + "@email.com",
        guest: true,
        profile: {
            mugshot: config.gravatar.mugshot + randomEmailHash + "?d=identicon",
            website: config.gravatar.profile,
            description: "",
            points: 0
        },
        verification: { verified: true }
    };
    console.log("INFO", "generated guest user:", user);
    return user;
}
<commit_msg>config/utils.js removed task numbering<commit_after>/* Add modules */
var crypto = require('crypto'),
    db = require('./database'),
    config = require('./config');

var tasks = [];
var currentTask = 0;

exports.getTasks = function getTasks() {
    return tasks;
}

/* Get new task */
exports.getTask = function getTask() {
    /* Update tasks */
    db.Task.find(function(err, db_tasks) {
        if (err) return new Error(err);
        else tasks = etasks = db_tasks;
    });
    if (tasks.length == 0) return { name: "Currently no tasks available" };
    return { name: tasks[currentTask].name, points: tasks[currentTask].points };
}

/* Check if task is complete */
exports.taskComplete = function taskComplete(code) {
    if (tasks.length == 0) return false;
    /* When task was completed */
    if (code.replace(/\s+/g, '').match(tasks[currentTask].verification)) {
        currentTask = (currentTask + 1) % tasks.length;
        return true;
    }
    return false;
}

/* Hashing function */
exports.calculateHash = function calculateHash(type, text) {
    var shasum = crypto.createHash(type);
    shasum.update(text);
    return shasum.digest('hex');
}

/* Random function */
exports.generateRandom = function generateRandom() {
    /* TODO: Add existing check, or add date + time */
    var current_date = (new Date()).valueOf().toString();
    var random = parseInt(Math.random()*100);
    return random;
}

/* Generate a random guest account */
exports.generateGuest = function generateGuest() {
    var random = exports.generateRandom();
    var randomEmailHash = exports.calculateHash('md5', random + "@gmail.com");
    var user = {
        name: "Guest" + random,
        email: random + "@email.com",
        guest: true,
        profile: {
            mugshot: config.gravatar.mugshot + randomEmailHash + "?d=identicon",
            website: config.gravatar.profile,
            description: "",
            points: 0
        },
        verification: { verified: true }
    };
    console.log("INFO", "generated guest user:", user);
    return user;
}
<|endoftext|>


<commit_before>// Copyright 2014-2015, University of Colorado Boulder

/**
 * View for the 'Energy Systems' screen of the Energy Forms And Changes simulation.
 *
 * @author  John Blanco
 * @author  Martin Veillette (Berea College)
 * @author  Jesse Greenberg
 * @author  Andrew Adare
 */
define( function( require ) {
  'use strict';

  // Modules
  var Bounds2 = require( 'DOT/Bounds2' );
  var CheckBox = require( 'SUN/CheckBox' );
  var EFACConstants = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACConstants' );
  var EnergyChunkLegend = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergyChunkLegend' );
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );
  var EnergySystemElementSelector = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergySystemElementSelector' );
  var EnergyChunkNode = require( 'ENERGY_FORMS_AND_CHANGES/common/view/EnergyChunkNode' );
  var EnergyType = require( 'ENERGY_FORMS_AND_CHANGES/common/model/EnergyType' );
  var HSlider = require( 'SUN/HSlider' );
  var Image = require( 'SCENERY/nodes/Image' );
  var inherit = require( 'PHET_CORE/inherit' );
  var LayoutBox = require( 'SCENERY/nodes/LayoutBox' );
  var ModelViewTransform2 = require( 'PHETCOMMON/view/ModelViewTransform2' );
  var Panel = require( 'SUN/Panel' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var SunNode = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/SunNode' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Vector2 = require( 'DOT/Vector2' );

  // Images
  var mockupImage = require( 'image!ENERGY_FORMS_AND_CHANGES/mockup_energy_systems.png' );

  // Strings
  var energySymbolsString = require( 'string!ENERGY_FORMS_AND_CHANGES/energySymbols' );

  // Constants
  var EDGE_INSET = 10;

  /**
   * @param {EnergySystemsModel} model
   * @constructor
   */
  function EnergySystemsScreenView( model ) {

    ScreenView.call( this, {
      layoutBounds: new Bounds2( 0, 0, 1008, 679 )
    } );

    var thisScreenView = this;

    // Create the model-view transform.  The primary units used in the model are
    // meters, so significant zoom is used. The multipliers for the 2nd parameter
    // can be used to adjust where the point (0, 0) in the model, which is on the
    // middle of the screen above the counter as located in the view.
    // Final arg is zoom factor - smaller zooms out, larger zooms in.
    var mvtOriginX = Math.round( thisScreenView.layoutBounds.width * 0.5 );
    var mvtOriginY = Math.round( thisScreenView.layoutBounds.height * 0.475 );
    var modelViewTransform = ModelViewTransform2.createSinglePointScaleInvertedYMapping(
      Vector2.ZERO, new Vector2( mvtOriginX, mvtOriginY ), 2200 );

    //Show the mock-up and a slider to change its transparency
    function addMockupImage() {
      var opacity = new Property( 0.8 );
      var image = new Image( mockupImage, {
        pickable: false
      } );
      image.scale( thisScreenView.layoutBounds.width / image.width );
      opacity.linkAttribute( image, 'opacity' );
      thisScreenView.addChild( image );
      thisScreenView.addChild( new HSlider( opacity, {
        min: 0,
        max: 1
      }, {
        top: 10,
        left: 10
      } ) );
    }

    // Create the legend for energy chunk types
    function addEnergyChunkLegend() {
      var legend = new EnergyChunkLegend();
      var x = 0.9 * thisScreenView.layoutBounds.width;
      var y = 0.5 * thisScreenView.layoutBounds.height;
      legend.center = new Vector2( x, y );
      thisScreenView.addChild( legend );
    }

    // Check box panel to display energy chunks
    function addCheckBoxPanel() {
      var label = new Text( energySymbolsString, {
        font: new PhetFont( 20 )
      } );

      var energyChunkNode = EnergyChunkNode.createEnergyChunkNode( EnergyType.THERMAL );
      energyChunkNode.scale( 1.0 );
      energyChunkNode.pickable = false;

      var checkBox = new CheckBox( new LayoutBox( {
        children: [ label, energyChunkNode ],
        orientation: 'horizontal',
        spacing: 5
      } ), model.energyChunksVisibleProperty );

      var panel = new Panel( checkBox, {
        fill: EFACConstants.CONTROL_PANEL_BACKGROUND_COLOR,
        stroke: EFACConstants.CONTROL_PANEL_OUTLINE_STROKE,
        lineWidth: EFACConstants.CONTROL_PANEL_OUTLINE_LINE_WIDTH
      } );
      panel.rightTop = new Vector2( thisScreenView.layoutBounds.width - EDGE_INSET, EDGE_INSET );
      thisScreenView.addChild( panel );
    }

    // Create and add the Reset All Button in the bottom right, which resets the model
    function addResetButton() {
      var resetAllButton = new ResetAllButton( {
        listener: function() {
          model.reset();
        },
        right: thisScreenView.layoutBounds.maxX - 10,
        bottom: thisScreenView.layoutBounds.maxY - 10
      } );
      thisScreenView.addChild( resetAllButton );
    }

    function addSun() {
      var sun = new SunNode( model.sun, model.energyChunksVisibleProperty, modelViewTransform );
      thisScreenView.addChild( sun );
    }

    // Create the carousel control nodes.
    function addCarousels() {
      var sourcesCarousel = new EnergySystemElementSelector( model.energySourcesCarousel );
      var convertersCarousel = new EnergySystemElementSelector( model.energyConvertersCarousel );
      var usersCarousel = new EnergySystemElementSelector( model.energyUsersCarousel );

      thisScreenView.addChild( sourcesCarousel );
      thisScreenView.addChild( convertersCarousel );
      thisScreenView.addChild( usersCarousel );
    }

    addMockupImage();
    addEnergyChunkLegend();
    addCheckBoxPanel();
    addResetButton();
    addSun();
    addCarousels();
  }

  energyFormsAndChanges.register( 'EnergySystemsScreenView', EnergySystemsScreenView );

  return inherit( ScreenView, EnergySystemsScreenView );
} );
<commit_msg>Don't add selectors for converters or users yet<commit_after>// Copyright 2014-2015, University of Colorado Boulder

/**
 * View for the 'Energy Systems' screen of the Energy Forms And Changes simulation.
 *
 * @author  John Blanco
 * @author  Martin Veillette (Berea College)
 * @author  Jesse Greenberg
 * @author  Andrew Adare
 */
define( function( require ) {
  'use strict';

  // Modules
  var Bounds2 = require( 'DOT/Bounds2' );
  var CheckBox = require( 'SUN/CheckBox' );
  var EFACConstants = require( 'ENERGY_FORMS_AND_CHANGES/common/EFACConstants' );
  var EnergyChunkLegend = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergyChunkLegend' );
  var energyFormsAndChanges = require( 'ENERGY_FORMS_AND_CHANGES/energyFormsAndChanges' );
  var EnergySystemElementSelector = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/EnergySystemElementSelector' );
  var EnergyChunkNode = require( 'ENERGY_FORMS_AND_CHANGES/common/view/EnergyChunkNode' );
  var EnergyType = require( 'ENERGY_FORMS_AND_CHANGES/common/model/EnergyType' );
  var HSlider = require( 'SUN/HSlider' );
  var Image = require( 'SCENERY/nodes/Image' );
  var inherit = require( 'PHET_CORE/inherit' );
  var LayoutBox = require( 'SCENERY/nodes/LayoutBox' );
  var ModelViewTransform2 = require( 'PHETCOMMON/view/ModelViewTransform2' );
  var Panel = require( 'SUN/Panel' );
  var PhetFont = require( 'SCENERY_PHET/PhetFont' );
  var Property = require( 'AXON/Property' );
  var ResetAllButton = require( 'SCENERY_PHET/buttons/ResetAllButton' );
  var ScreenView = require( 'JOIST/ScreenView' );
  var SunNode = require( 'ENERGY_FORMS_AND_CHANGES/energy-systems/view/SunNode' );
  var Text = require( 'SCENERY/nodes/Text' );
  var Vector2 = require( 'DOT/Vector2' );

  // Images
  var mockupImage = require( 'image!ENERGY_FORMS_AND_CHANGES/mockup_energy_systems.png' );

  // Strings
  var energySymbolsString = require( 'string!ENERGY_FORMS_AND_CHANGES/energySymbols' );

  // Constants
  var EDGE_INSET = 10;

  /**
   * @param {EnergySystemsModel} model
   * @constructor
   */
  function EnergySystemsScreenView( model ) {

    ScreenView.call( this, {
      layoutBounds: new Bounds2( 0, 0, 1008, 679 )
    } );

    var thisScreenView = this;

    // Create the model-view transform.  The primary units used in the model are
    // meters, so significant zoom is used. The multipliers for the 2nd parameter
    // can be used to adjust where the point (0, 0) in the model, which is on the
    // middle of the screen above the counter as located in the view.
    // Final arg is zoom factor - smaller zooms out, larger zooms in.
    var mvtOriginX = Math.round( thisScreenView.layoutBounds.width * 0.5 );
    var mvtOriginY = Math.round( thisScreenView.layoutBounds.height * 0.475 );
    var modelViewTransform = ModelViewTransform2.createSinglePointScaleInvertedYMapping(
      Vector2.ZERO, new Vector2( mvtOriginX, mvtOriginY ), 2200 );

    //Show the mock-up and a slider to change its transparency
    function addMockupImage() {
      var opacity = new Property( 0.8 );
      var image = new Image( mockupImage, {
        pickable: false
      } );
      image.scale( thisScreenView.layoutBounds.width / image.width );
      opacity.linkAttribute( image, 'opacity' );
      thisScreenView.addChild( image );
      thisScreenView.addChild( new HSlider( opacity, {
        min: 0,
        max: 1
      }, {
        top: 10,
        left: 10
      } ) );
    }

    // Create the legend for energy chunk types
    function addEnergyChunkLegend() {
      var legend = new EnergyChunkLegend();
      var x = 0.9 * thisScreenView.layoutBounds.width;
      var y = 0.5 * thisScreenView.layoutBounds.height;
      legend.center = new Vector2( x, y );
      thisScreenView.addChild( legend );
    }

    // Check box panel to display energy chunks
    function addCheckBoxPanel() {
      var label = new Text( energySymbolsString, {
        font: new PhetFont( 20 )
      } );

      var energyChunkNode = EnergyChunkNode.createEnergyChunkNode( EnergyType.THERMAL );
      energyChunkNode.scale( 1.0 );
      energyChunkNode.pickable = false;

      var checkBox = new CheckBox( new LayoutBox( {
        children: [ label, energyChunkNode ],
        orientation: 'horizontal',
        spacing: 5
      } ), model.energyChunksVisibleProperty );

      var panel = new Panel( checkBox, {
        fill: EFACConstants.CONTROL_PANEL_BACKGROUND_COLOR,
        stroke: EFACConstants.CONTROL_PANEL_OUTLINE_STROKE,
        lineWidth: EFACConstants.CONTROL_PANEL_OUTLINE_LINE_WIDTH
      } );
      panel.rightTop = new Vector2( thisScreenView.layoutBounds.width - EDGE_INSET, EDGE_INSET );
      thisScreenView.addChild( panel );
    }

    // Create and add the Reset All Button in the bottom right, which resets the model
    function addResetButton() {
      var resetAllButton = new ResetAllButton( {
        listener: function() {
          model.reset();
        },
        right: thisScreenView.layoutBounds.maxX - 10,
        bottom: thisScreenView.layoutBounds.maxY - 10
      } );
      thisScreenView.addChild( resetAllButton );
    }

    function addSun() {
      var sun = new SunNode( model.sun, model.energyChunksVisibleProperty, modelViewTransform );
      thisScreenView.addChild( sun );
    }

    // Create the carousel control nodes.
    function addCarousels() {
      var sourcesCarousel = new EnergySystemElementSelector( model.energySourcesCarousel );
      // var convertersCarousel = new EnergySystemElementSelector( model.energyConvertersCarousel );
      // var usersCarousel = new EnergySystemElementSelector( model.energyUsersCarousel );

      thisScreenView.addChild( sourcesCarousel );
      // thisScreenView.addChild( convertersCarousel );
      // thisScreenView.addChild( usersCarousel );
    }

    addMockupImage();
    addEnergyChunkLegend();
    addCheckBoxPanel();
    addResetButton();
    addSun();
    addCarousels();
  }

  energyFormsAndChanges.register( 'EnergySystemsScreenView', EnergySystemsScreenView );

  return inherit( ScreenView, EnergySystemsScreenView );
} );
<|endoftext|>


<commit_before>/**
* Generated by PluginGenerator from webgme on Tue Jun 10 2014 17:42:32 GMT-0500 (Central Daylight Time).
*/

define(['plugin/PluginConfig',
        'plugin/PluginBase',
        'plugin/C2MF/C2MF/meta'], function (PluginConfig, PluginBase, MetaTypes) {
    'use strict';

    /**
    * Initializes a new instance of C2MF.
    * @class
    * @augments {PluginBase}
    * @classdesc This class represents the plugin C2MF.
    * @constructor
    */
    var C2MF = function () {
        // Call base class' constructor.
        PluginBase.call(this);
        this.metaTypes = MetaTypes;
    };

    // Prototypal inheritance from PluginBase.
    C2MF.prototype = Object.create(PluginBase.prototype);
    C2MF.prototype.constructor = C2MF;

    /**
    * Gets the name of the C2MF.
    * @returns {string} The name of the plugin.
    * @public
    */
    C2MF.prototype.getName = function () {
        return "Component2MatlabFile";
    };

    /**
    * Gets the semantic version (semver.org) of the C2MF.
    * @returns {string} The version of the plugin.
    * @public
    */
    C2MF.prototype.getVersion = function () {
        return "0.1.0";
    };

    /**
    * Gets the description of the C2MF.
    * @returns {string} The description of the plugin.
    * @public
    */
    C2MF.prototype.getDescription = function () {
        return "Generate a Matlab m-file from a Component";
    };

    /**
    * Main function for the plugin to execute. This will perform the execution.
    * Notes:
    * - Always log with the provided logger.[error,warning,info,debug].
    * - Do NOT put any user interaction logic UI, etc. inside this method.
    * - callback always has to be called even if error happened.
    *
    * @param {function(string, plugin.PluginResult)} callback - the result callback
    */
    C2MF.prototype.main = function (callback) {
        // Use self to access core, project, result, logger etc from PluginBase.
        // These are all instantiated at this point.
        var self = this,
            mFileString,
            mFileName,
            getComponentInfoCallback,
            artifact,
            filesToAdd = {},
            addFilesCallback;

        self.updateMETA(self.metaTypes);

        if (self.isMetaTypeOf(self.activeNode, MetaTypes.Component) === false) {
            self.result.createMessage(self.activeNode, 'SelectedNode is not a Component!')
            return callback(null, self.result);
        }

        getComponentInfoCallback = function (err, componentInfo) {
            if (err) {
                self.result.setSuccess(false);
                return callback(err, self.result);
            }

            mFileString = self.buildMatlabScript(componentInfo);
            mFileName = componentInfo.name + '.m';

            filesToAdd[mFileName] = mFileString;

            artifact = self.blobClient.createArtifact(componentInfo.name);

            addFilesCallback = function (err, fileHashes) {
                if (err) {
                    self.result.setSuccess(false);
                    return callback(err, self.result);
                }

                var artifactSaveCallback = function (err, artifactHash) {
                    if (err) {
                        self.result.setSuccess(false);
                        return callback(err, self.result);
                    }

                    self.result.setSuccess(true);
                    self.result.createMessage(self.activeNode, 'Generated .m-file for ' + componentInfo.name);
                    self.result.addArtifact(artifactHash);
                    callback(null, self.result);
                };

                artifact.save(artifactSaveCallback);
            }

            artifact.addFiles(filesToAdd, addFilesCallback);
        };

        self.getComponentInfo(self.activeNode, getComponentInfoCallback);
    };

    C2MF.prototype.buildMatlabScript = function (componentInfo) {
        var self = this,
            mFileString = '',
            itemPath,
            itemNumber = 1,
            element,
            key,
            value,
            bond;

        for (itemPath in componentInfo.elements) {
            element = componentInfo.elements[itemPath];

            mFileString += '%% WebGmePath = ' + itemPath;
            mFileString += '\n';

            for (key in element) {
                value = element[key];

                if (key === 'Bond') {
                    mFileString += 'element(' + itemNumber + ').' + key + ' = [\'';
                    mFileString += value.join('\',\'');
                    mFileString += '\']';
                } else if (typeof value === 'number') {
                    mFileString += 'element(' + itemNumber + ').' + key + ' = ' + value + ';';
                } else {
                    mFileString += 'element(' + itemNumber + ').' + key + ' = \'' + value + '\';';
                }

                mFileString += '\n';
            }

            itemNumber += 1;
            mFileString += '\n';
        }

        itemNumber = 1;

        for (itemPath in componentInfo.bonds) {
            bond = componentInfo.bonds[itemPath];

            mFileString += '%% WebGmePath = ' + itemPath;
            mFileString += '\n';
            mFileString += 'bond(' + itemNumber + ').ID = \'' + bond.ID + '\';';
            mFileString += '\n';
            mFileString += 'bond(' + itemNumber + ').src = \'' + bond.src + '\';';
            mFileString += '\n';
            mFileString += 'bond(' + itemNumber + ').dst = \'' + bond.dst + '\';';

            itemNumber += 1;
            mFileString += '\n\n';
        }

        return mFileString;
    };

    C2MF.prototype.createElementObject = function () {
        return {
            ID: '',
            Name: '',
            Type: '',
            Equation: 'N/A',
            Ratio: 0,
            //Bond: ''
            Bond: []
        };
    };

    C2MF.prototype.getComponentInfo = function (componentNode, callback) {
        var self = this,
            childNode,
            path,
            guid,
            metaNode,
            metaName,
            loadChildrenCallbackFunction,
            bondNodes = [],
            element,
            bond,
            bondSrcPath,
            bondDstPath,
            elements = {},
            bonds = {},
            i;

        loadChildrenCallbackFunction = function (err, children) {
            if (err) {
                callback(err, null);
            }

            for (i = 0; i < children.length; i += 1) {
                childNode = children[i];
                metaNode = self.getMetaType(childNode);
                metaName = self.core.getAttribute(metaNode, 'name');

                if (self.isMetaTypeOf(childNode, self.metaTypes.ComponentConnection)) {
                    bondNodes.push(childNode);
                } else {
                    path = self.core.getPath(childNode);
                    guid = self.core.getGuid(childNode);

                    element = self.createElementObject();
                    element.ID = self.core.getGuid(childNode);
                    element.Name = self.core.getAttribute(childNode, 'name');
                    element.Type = metaName;

                    if (metaNode === self.metaTypes.ControlPort ||
                        metaNode === self.metaTypes.ResistivePort ||
                        metaNode === self.metaTypes.StoragePort) {
                        element.Equation = self.core.getAttribute(childNode, 'Equation');
                    }
                    if (metaNode === self.metaTypes.Gyrator ||
                        metaNode === self.metaTypes.Transformer) {
                        element.Ratio = parseFloat(self.core.getAttribute(childNode, 'Ratio'));
                    }

                    elements[path] = element;
                }
            }

            for (i = 0; i < bondNodes.length; i += 1) {
                childNode = bondNodes[i];

                path = self.core.getPath(childNode);
                guid = self.core.getGuid(childNode);
                bondSrcPath = self.core.getPointerPath(childNode, 'src');
                bondDstPath = self.core.getPointerPath(childNode, 'dst');

                bond = {};

                bond.ID = guid;

                if (elements.hasOwnProperty(bondSrcPath)) {
                    elements[bondSrcPath].Bond.push(guid);
                    bond.src = elements[bondSrcPath].ID;
                } else {
                    bond.src = 'error: ' + bondSrcPath;
                }

                if (elements.hasOwnProperty(bondDstPath)) {
                    elements[bondDstPath].Bond.push(guid);
                    bond.dst = elements[bondDstPath].ID;
                } else {
                    bond.dst = 'error: ' + bondDstPath;
                }

                bonds[path] = bond;
            }

            callback(null, {
                name: self.core.getAttribute(componentNode, 'name'),
                elements: elements,
                bonds: bonds
            });
        };

        self.core.loadChildren(componentNode, loadChildrenCallbackFunction);
    };

    return C2MF;
});<commit_msg>Cleanup; Improve readability<commit_after>/**
* Generated by PluginGenerator from webgme on Tue Jun 10 2014 17:42:32 GMT-0500 (Central Daylight Time).
*/

define(['plugin/PluginConfig',
        'plugin/PluginBase',
        'plugin/C2MF/C2MF/meta'], function (PluginConfig, PluginBase, MetaTypes) {
    'use strict';

    /**
    * Initializes a new instance of C2MF.
    * @class
    * @augments {PluginBase}
    * @classdesc This class represents the plugin C2MF.
    * @constructor
    */
    var C2MF = function () {
        // Call base class' constructor.
        PluginBase.call(this);
        this.metaTypes = MetaTypes;
    };

    // Prototypal inheritance from PluginBase.
    C2MF.prototype = Object.create(PluginBase.prototype);
    C2MF.prototype.constructor = C2MF;

    /**
    * Gets the name of the C2MF.
    * @returns {string} The name of the plugin.
    * @public
    */
    C2MF.prototype.getName = function () {
        return "Component2MatlabFile";
    };

    /**
    * Gets the semantic version (semver.org) of the C2MF.
    * @returns {string} The version of the plugin.
    * @public
    */
    C2MF.prototype.getVersion = function () {
        return "0.1.0";
    };

    /**
    * Gets the description of the C2MF.
    * @returns {string} The description of the plugin.
    * @public
    */
    C2MF.prototype.getDescription = function () {
        return "Generate a Matlab m-file from a Component";
    };

    /**
    * Main function for the plugin to execute. This will perform the execution.
    * Notes:
    * - Always log with the provided logger.[error,warning,info,debug].
    * - Do NOT put any user interaction logic UI, etc. inside this method.
    * - callback always has to be called even if error happened.
    *
    * @param {function(string, plugin.PluginResult)} callback - the result callback
    */
    C2MF.prototype.main = function (callback) {
        // Use self to access core, project, result, logger etc from PluginBase.
        // These are all instantiated at this point.
        var self = this,
            mFileString,
            mFileName,
            getComponentInfoCallback,
            resultArtifact,
            generatedFilesToAdd = {},
            addFilesCallback;

        self.updateMETA(self.metaTypes);

        if (self.isMetaTypeOf(self.activeNode, MetaTypes.Component) === false) {
            self.result.createMessage(self.activeNode, 'SelectedNode is not a Component!')
            return callback(null, self.result);
        }

        getComponentInfoCallback = function (err, componentInfo) {
            if (err) {
                self.result.setSuccess(false);
                var msg = 'Failed to get component info from ' + self.core.getName(self.activeNode)
                self.result.createMessage(self.activeNode, msg);
                return callback(err, self.result);
            }

            mFileString = self.buildMatlabScript(componentInfo);
            mFileName = componentInfo.name + '.m';

            generatedFilesToAdd[mFileName] = mFileString;

            resultArtifact = self.blobClient.createArtifact(componentInfo.name);

            addFilesCallback = function (err, fileHashes) {
                if (err) {
                    self.result.setSuccess(false);
                    self.result.createMessage(self.activeNode, 'Failed to add files to result artifact.');
                    return callback(err, self.result);
                }

                var artifactSaveCallback = function (err, artifactHash) {
                    if (err) {
                        self.result.setSuccess(false);
                        self.result.createMessage(self.activeNode, 'Failed to save result artifact.');
                        return callback(err, self.result);
                    }

                    self.result.setSuccess(true);
                    self.result.createMessage(self.activeNode, 'Generated .m-file for ' + componentInfo.name);
                    self.result.addArtifact(artifactHash);
                    callback(null, self.result);
                };

                resultArtifact.save(artifactSaveCallback);
            }

            resultArtifact.addFiles(generatedFilesToAdd, addFilesCallback);
        };

        self.getComponentInfo(self.activeNode, getComponentInfoCallback);
    };

    C2MF.prototype.buildMatlabScript = function (componentInfo) {
        var self = this,
            mFileString = '',
            nodePath,
            itemNumber = 1,
            element,
            propertyName,
            propertyValue,
            bond;

        for (nodePath in componentInfo.elements) {
            element = componentInfo.elements[nodePath];

            mFileString += '%% WebGmePath = ' + nodePath;
            mFileString += '\n';

            for (propertyName in element) {
                propertyValue = element[propertyName];

                if (propertyName === 'Bond') {
                    mFileString += 'element(' + itemNumber + ').' + propertyName + ' = [\'';
                    mFileString += propertyValue.join('\',\'');
                    mFileString += '\']';
                } else if (typeof propertyValue === 'number') {
                    mFileString += 'element(' + itemNumber + ').' + propertyName + ' = ' + propertyValue + ';';
                } else {
                    mFileString += 'element(' + itemNumber + ').' + propertyName + ' = \'' + propertyValue + '\';';
                }

                mFileString += '\n';
            }

            itemNumber += 1;
            mFileString += '\n';
        }

        itemNumber = 1;

        for (nodePath in componentInfo.bonds) {
            bond = componentInfo.bonds[nodePath];

            mFileString += '%% WebGmePath = ' + nodePath;
            mFileString += '\n';
            mFileString += 'bond(' + itemNumber + ').ID = \'' + bond.ID + '\';';
            mFileString += '\n';
            mFileString += 'bond(' + itemNumber + ').src = \'' + bond.src + '\';';
            mFileString += '\n';
            mFileString += 'bond(' + itemNumber + ').dst = \'' + bond.dst + '\';';

            itemNumber += 1;
            mFileString += '\n\n';
        }

        return mFileString;
    };

    C2MF.prototype.createNewElementObject = function () {
        return {
            ID: '',
            Name: '',
            Type: '',
            Equation: 'N/A',
            Ratio: 0,
            Bond: []
        };
    };

    C2MF.prototype.getComponentInfo = function (componentNode, callback) {
        var self = this,
            childNode,
            nodePath,
            nodeGuid,
            metaTypeNode,
            metaTypeName,
            loadChildrenCallbackFunction,
            bondNodes = [],
            elementObject,
            bondObject,
            bondSrcNodePath,
            bondDstNodePath,
            path2elementMap = {},
            path2bondMap = {},
            i;

        loadChildrenCallbackFunction = function (err, children) {
            if (err) {
                callback(err, null);
            }

            for (i = 0; i < children.length; i += 1) {
                childNode = children[i];
                metaTypeNode = self.getMetaType(childNode);
                metaTypeName = self.core.getAttribute(metaTypeNode, 'name');

                if (self.isMetaTypeOf(childNode, self.metaTypes.ComponentConnection)) {
                    // defer bond nodes; handle them after element node info is complete
                    bondNodes.push(childNode);
                } else {
                    nodePath = self.core.getPath(childNode);
                    nodeGuid = self.core.getGuid(childNode);

                    elementObject = self.createNewElementObject();
                    elementObject.ID = self.core.getGuid(childNode);
                    elementObject.Name = self.core.getAttribute(childNode, 'name');
                    elementObject.Type = metaTypeName;

                    if (metaTypeNode === self.metaTypes.ControlPort ||
                        metaTypeNode === self.metaTypes.ResistivePort ||
                        metaTypeNode === self.metaTypes.StoragePort) {
                        elementObject.Equation = self.core.getAttribute(childNode, 'Equation');
                    }
                    if (metaTypeNode === self.metaTypes.Gyrator ||
                        metaTypeNode === self.metaTypes.Transformer) {
                        elementObject.Ratio = parseFloat(self.core.getAttribute(childNode, 'Ratio'));
                    }

                    path2elementMap[nodePath] = elementObject;
                }
            }

            for (i = 0; i < bondNodes.length; i += 1) {
                childNode = bondNodes[i];

                nodePath = self.core.getPath(childNode);
                nodeGuid = self.core.getGuid(childNode);
                bondSrcNodePath = self.core.getPointerPath(childNode, 'src');
                bondDstNodePath = self.core.getPointerPath(childNode, 'dst');

                bondObject = {};

                bondObject.ID = nodeGuid;

                if (path2elementMap.hasOwnProperty(bondSrcNodePath)) {
                    path2elementMap[bondSrcNodePath].Bond.push(nodeGuid);
                    bondObject.src = path2elementMap[bondSrcNodePath].ID;
                } else {
                    bondObject.src = 'error: ' + bondSrcNodePath;
                }

                if (path2elementMap.hasOwnProperty(bondDstNodePath)) {
                    path2elementMap[bondDstNodePath].Bond.push(nodeGuid);
                    bondObject.dst = path2elementMap[bondDstNodePath].ID;
                } else {
                    bondObject.dst = 'error: ' + bondDstNodePath;
                }

                path2bondMap[nodePath] = bondObject;
            }

            callback(null, {
                name: self.core.getAttribute(componentNode, 'name'),
                elements: path2elementMap,
                bonds: path2bondMap
            });
        };

        self.core.loadChildren(componentNode, loadChildrenCallbackFunction);
    };

    return C2MF;
});<|endoftext|>


<commit_before>module.exports = {
	views: [{
		"name": "Match Strategy Profile",
		"views": [
            {
                "name": "stratAverages",
                "disableInfo": true,
                "disablePaging": true,
                "colorcode": true
            },
            {
                "name": "matches",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            },
            {
                "name": "comments",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            }
        ]
	},{
		"name": "Alliance Selection Profile",
		"views": [
            {
                "name": "selecAverages",
                "disableInfo": true,
                "disablePaging": true,
                "colorcode": true
            },
            {
                "name": "matches",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            },
            {
                "name": "comments",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            }
        ]
	},{
		"name": "Raw Match Data",
		"views": [
            {
                "name": "matches",
                "disableInfo": true,
                "disablePaging": true
            }
        ]
	}],

    query: [
      {
          $match: {"competition": 2017}
      },
      {
          $group: {
              _id: {
                  "team": '$team',
                  "event": '$event'
              },

              "baseline": { $avg: '$baseline' },

              "auto-low-kPa": { $avg: '$auto-low-kPa' },
              "teleop-low-kPa": { $avg: '$teleop-low-kPa' },

              "auto-high-kPa": { $avg: '$auto-high-kPa' },
              "teleop-high-kPa": { $avg: '$teleop-high-kPa' },

              "auto-gears": { $avg: '$auto-gears' },
              "auto-place-gears": { $avg: '$auto-place-gears' },

              "teleop-gears": { $avg: '$teleop-gears' },

              "auto-max-gears": { $max: '$auto-gears' },
              "teleop-max-gears": { $max: '$teleop-gears' },

              "teleop-drop-gears": { $avg: '$teleop-drop-gears' },

              "touchpad": { $avg: '$touchpad' },
              "touchpad-attempted": { $avg: '$touchpad-attempted' }
          }
      },
      {
         $addFields: {
            "auto-gears":{
                $cond: [
                   { "$gt": ["$auto-gears", 0] },
                   "$auto-gears",
                   "$auto-place-gears"
               ]
            },
           "touchpad-success": {
               $cond: [
                   { "$eq": ["$touchpad", 0] },
                   0,
                   { "$divide": ['$touchpad', '$touchpad-attempted']}
               ]
           },
           "auto-success-gears": {
               $cond: [
                   { "$eq": ["$auto-gears", 0] },
                   0,
                   { "$divide": ['$auto-gears', { "$sum": ["$auto-gears", "$auto-drop-gears"]}]}
               ]
           },
           "teleop-success-gears": {
               $cond: [
                   { "$eq": [{ "$sum": ["$teleop-gears", "$teleop-gears-dropped"]}, 0] },
                   0,
                   { "$divide": ['$teleop-gears', { "$sum": ["$teleop-gears", "$teleop-drop-gears"]}]}
               ]
           }
         }
      },
      {
         $addFields: {
            "auto-gears":{
                $cond: [
                   { "$gt": ["$auto-gears", 0] },
                   "$auto-gears",
                   0
               ]
            },
           "total-gears-score": {
                "$multiply": [
                    { "$sum": ["$auto-gears", "$teleop-gears"] },
                    12.3
                ]
           },

           "total-kPa": { "$sum": [
                "$auto-low-kPa", "$teleop-low-kPa","$auto-high-kPa","teleop-high-kPa"
           ]},

           "total-gears": { "$sum": [
                "$auto-gears", "$teleop-gears"
           ]},
           "total-max-gears": { "$sum": [
                "$auto-max-gears", "$teleop-max-gears"
           ]},
         }
      },
      {
         $addFields: {
            "total-score": { "$sum": [
                    {"$multiply": [5, "$baseline"]},
                    "$total-gears-score",
                    "$total-kPa",
                    {"$multiply": [50, "$touchpad"]},
            ]}
         }
      },
      {
         $addFields: {
           "team": {"$substr":["$_id.team", 0, -1 ]},
           "event": "$_id.event",
           "baseline": { "$divide": [ { "$trunc": { "$multiply": ["$baseline", 20] } }, 20] },
           "auto-low-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$auto-low-kPa", 20] } }, 20] },
           "teleop-low-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-low-kPa", 20] } }, 20] },
           "auto-high-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$auto-high-kPa", 20] } }, 20] },
           "teleop-high-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-high-kPa", 20] } }, 20] },
           "total-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$total-kPa", 20] } }, 20] },
           "auto-gears": { "$divide": [ { "$trunc": { "$multiply": ["$auto-gears", 20] } }, 20] },
           "teleop-gears": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-gears", 20] } }, 20] },
           "teleop-drop-gears": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-drop-gears", 20] } }, 20] },
           "auto-success-gears": { "$divide": [ { "$trunc": { "$multiply": ["$auto-drop-gears", 20] } }, 20] },
           "teleop-success-gears": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-drop-gears", 20] } }, 20] },
           "total-gears-score": { "$divide": [ { "$trunc": { "$multiply": ["$total-gears-score", 20] } }, 20] },
           "total-gears": { "$divide": [ { "$trunc": { "$multiply": ["$total-gears", 20] } }, 20] },
           "total-max-gears": { "$divide": [ { "$trunc": { "$multiply": ["$total-max-gears", 20] } }, 20] },
           "total-score": { "$divide": [ { "$trunc": { "$multiply": ["$total-score", 20] } }, 20] },
           "touchpad": { "$divide": [ { "$trunc": { "$multiply": ["$touchpad", 20] } }, 20] },
           "touchpad-attempted": { "$divide": [ { "$trunc": { "$multiply": ["$touchpad-attempted", 20] } }, 20] },
           "touchpad-success": { "$divide": [ { "$trunc": { "$multiply": ["$touchpad-success", 20] } }, 20] }
         }
      },
      {
          $project: {
              "_id": 0,
              "team": 1,
              "event": 1,
              "auto-gears": 1, // Avg. Auto Gears / Match
              "total-gears": 1, // Avg. Gears / Match
              "total-max-gears": 1, // Max. Gears / Match
              "teleop-drop-gears": 1, // Dropped Gears / Match
              "total-kPa": 1, // Avg. kPa / Match
              "touchpad": 1, // Avg. Climb / Match
              "touchpad-success": 1, // Avg. Climb / Attempt
              "total-score": 1 // Calculated Score
          }
      }
    ],

	matches: function (mongoCollection, callback) {
		mongoCollection
			.find({"competition": 2017})
			.sort({"_id": -1})
			.toArray(function (err, matches) {
				callback([
					{
                        name: "Team Matches",
                        cols: [2,3,4,5,6,7,8,9,10,11],
                        headers: [
                            {
                                text: "Team",
                                value: "team"
                            },
                            {
                                text: "Event",
                                value: "event"
                            },
                            {
                                text: "Baseline",
                                value: "baseline"
                            },
                            {
                                text: "Auto. Low Goal kPa",
                                value: "auto-low-kPa"
                            },
                            {
                                text: "Auto. High Goal kPa",
                                value: "auto-high-kPa"
                            },
                            {
                                text: "Auto. Gears Placed",
                                value: "auto-gears"
                            },
                            {
                                text: "Auto. Gears Dropped",
                                value: "auto-drop-gears"
                            },
                            {
                                text: "Teleop. Low Goal kPa",
                                value: "teleop-low-kPa"
                            },
                            {
                                text: "Teleop. High Goal kPa",
                                value: "teleop-high-kPa"
                            },
                            {
                                text: "Teleop. Gears Placed",
                                value: "teleop-gears"
                            },
                            {
                                text: "Teleop. Gears Dropped",
                                value: "teleop-drop-gears"
                            },
                            {
                                text: "Attempted Touchpad",
                                value: "touchpad-attempted"
                            },
                            {
                                text: "Pressed Touchpad",
                                value: "touchpad"
                            },
                            {
                                text: "Comments",
                                value: "comments"
                            }
                        ],
                        data: matches
					}
				]);

				db.close();
			});
	},

    comments: function (mongoCollection, callback) {
		mongoCollection
			.find({"competition": 2017, "comments": { $ne: "" }})
			.sort({"_id": -1})
			.toArray(function (err, matches) {
				callback([
					{
                        name: "Team Comments",
                        cols: [],
                        headers: [
                            {
                                text: "Team",
                                value: "team"
                            },
                            {
                                text: "Event",
                                value: "event"
                            },
                            {
                                text: "Comments",
                                value: "comments"
                            }
                        ],
                        data: matches
					}
				]);

				db.close();
			});
	},

    stratAverages: function (mongoCollection, callback) {
        mongoCollection.aggregate(this.query).toArray(function(err, matches) {
            callback([
                {
                    name: "Match Strategy Averages",
                    cols: [2,3,4,5,6,7,8],
                    headers: [
                        {
                            text: "Team",
                            value: "team"
                        },
                        {
                            text: "Event",
                            value: "event"
                        },
                        {
                            text: "Avg. Score",
                            value: "total-score"
                        },
                        {
                            text: "Avg. Gears Placed",
                            value: "total-gears"
                        },
                        {
                            text: "Avg. Auto Gears Placed",
                            value: "auto-gears"
                        },
                        {
                            text: "Max. Gears Placed",
                            value: "total-max-gears"
                        },
                        {
                            text: "Climb Avg. / Match",
                            value: "touchpad"
                        },
                        {
                            text: "Climb Avg. / Attempt",
                            value: "touchpad-success"
                        },
                        {
                            text: "Avg. kPa",
                            value: "total-kPa"
                        }
                    ],
                    data: matches
                }
            ]);

            db.close();
        });
	},

    selecAverages: function (mongoCollection, callback) {
        mongoCollection.aggregate(this.query).toArray(function(err, matches) {
            callback([
                {
                    name: "Alliance Selection Averages",
                    cols: [2,3,4,5,6,7,8,9],
                    headers: [
                        {
                            text: "Team",
                            value: "team"
                        },
                        {
                            text: "Event",
                            value: "event"
                        },
                        {
                            text: "Avg. Score",
                            value: "total-score"
                        },
                        {
                            text: "Avg. Gears Placed",
                            value: "total-gears"
                        },
                        {
                            text: "Avg. Auto Gears Placed",
                            value: "auto-gears"
                        },
                        {
                            text: "Max. Gears Placed",
                            value: "total-max-gears"
                        },
                        {
                            text: "Climb Avg. / Match",
                            value: "touchpad"
                        },
                        {
                            text: "Climb Avg. / Attempt",
                            value: "touchpad-success"
                        },
                        {
                            text: "Avg. kPa",
                            value: "total-kPa"
                        },
                        {
                            text: "Avg. Gears Dropped",
                            value: "teleop-drop-gears"
                        }
                    ],
                    data: matches
                }
            ]);

            db.close();
        });
	}
};<commit_msg>Fix Query<commit_after>module.exports = {
	views: [{
		"name": "Match Strategy Profile",
		"views": [
            {
                "name": "stratAverages",
                "disableInfo": true,
                "disablePaging": true,
                "colorcode": true
            },
            {
                "name": "matches",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            },
            {
                "name": "comments",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            }
        ]
	},{
		"name": "Alliance Selection Profile",
		"views": [
            {
                "name": "selecAverages",
                "disableInfo": true,
                "disablePaging": true,
                "colorcode": true
            },
            {
                "name": "matches",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            },
            {
                "name": "comments",
                "lengthMenu": [ [10, 25, 50, 100, -1], [10, 25, 50, 100, "All"] ]
            }
        ]
	},{
		"name": "Raw Match Data",
		"views": [
            {
                "name": "matches",
                "disableInfo": true,
                "disablePaging": true
            }
        ]
	}],

    query: [
      {
          $match: {"competition": 2017}
      },
      {
          $group: {
              _id: {
                  "team": '$team',
                  "event": '$event'
              },

              "baseline": { $avg: '$baseline' },

              "auto-low-kPa": { $avg: '$auto-low-kPa' },
              "teleop-low-kPa": { $avg: '$teleop-low-kPa' },

              "auto-high-kPa": { $avg: '$auto-high-kPa' },
              "teleop-high-kPa": { $avg: '$teleop-high-kPa' },

              "auto-gears": { $avg: '$auto-gears' },
              "auto-place-gears": { $avg: '$auto-place-gear' },

              "teleop-gears": { $avg: '$teleop-gears' },

              "auto-max-gears": { $max: '$auto-gears' },
              "teleop-max-gears": { $max: '$teleop-gears' },

              "teleop-drop-gears": { $avg: '$teleop-drop-gears' },

              "touchpad": { $avg: '$touchpad' },
              "touchpad-attempted": { $avg: '$touchpad-attempted' }
          }
      },
      {
         $addFields: {
            "auto-gears":{
                $cond: [
                   { "$gt": ["$auto-gears", 0] },
                   "$auto-gears",
                   "$auto-place-gears"
               ]
            },
           "touchpad-success": {
               $cond: [
                   { "$eq": ["$touchpad", 0] },
                   0,
                   { "$divide": ['$touchpad', '$touchpad-attempted']}
               ]
           },
           "auto-success-gears": {
               $cond: [
                   { "$eq": ["$auto-gears", 0] },
                   0,
                   { "$divide": ['$auto-gears', { "$sum": ["$auto-gears", "$auto-drop-gears"]}]}
               ]
           },
           "teleop-success-gears": {
               $cond: [
                   { "$eq": [{ "$sum": ["$teleop-gears", "$teleop-gears-dropped"]}, 0] },
                   0,
                   { "$divide": ['$teleop-gears', { "$sum": ["$teleop-gears", "$teleop-drop-gears"]}]}
               ]
           }
         }
      },
      {
         $addFields: {
            "auto-gears":{
                $cond: [
                   { "$gt": ["$auto-gears", 0] },
                   "$auto-gears",
                   0
               ]
            },
           "total-gears-score": {
                "$multiply": [
                    { "$sum": ["$auto-gears", "$teleop-gears"] },
                    12.3
                ]
           },

           "total-kPa": { "$sum": [
                "$auto-low-kPa", "$teleop-low-kPa","$auto-high-kPa","teleop-high-kPa"
           ]},

           "total-gears": { "$sum": [
                "$auto-gears", "$teleop-gears"
           ]},
           "total-max-gears": { "$sum": [
                "$auto-max-gears", "$teleop-max-gears"
           ]},
         }
      },
      {
         $addFields: {
            "total-score": { "$sum": [
                    {"$multiply": [5, "$baseline"]},
                    "$total-gears-score",
                    "$total-kPa",
                    {"$multiply": [50, "$touchpad"]},
            ]}
         }
      },
      {
         $addFields: {
           "team": {"$substr":["$_id.team", 0, -1 ]},
           "event": "$_id.event",
           "baseline": { "$divide": [ { "$trunc": { "$multiply": ["$baseline", 20] } }, 20] },
           "auto-low-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$auto-low-kPa", 20] } }, 20] },
           "teleop-low-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-low-kPa", 20] } }, 20] },
           "auto-high-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$auto-high-kPa", 20] } }, 20] },
           "teleop-high-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-high-kPa", 20] } }, 20] },
           "total-kPa": { "$divide": [ { "$trunc": { "$multiply": ["$total-kPa", 20] } }, 20] },
           "auto-gears": { "$divide": [ { "$trunc": { "$multiply": ["$auto-gears", 20] } }, 20] },
           "teleop-gears": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-gears", 20] } }, 20] },
           "teleop-drop-gears": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-drop-gears", 20] } }, 20] },
           "auto-success-gears": { "$divide": [ { "$trunc": { "$multiply": ["$auto-drop-gears", 20] } }, 20] },
           "teleop-success-gears": { "$divide": [ { "$trunc": { "$multiply": ["$teleop-drop-gears", 20] } }, 20] },
           "total-gears-score": { "$divide": [ { "$trunc": { "$multiply": ["$total-gears-score", 20] } }, 20] },
           "total-gears": { "$divide": [ { "$trunc": { "$multiply": ["$total-gears", 20] } }, 20] },
           "total-max-gears": { "$divide": [ { "$trunc": { "$multiply": ["$total-max-gears", 20] } }, 20] },
           "total-score": { "$divide": [ { "$trunc": { "$multiply": ["$total-score", 20] } }, 20] },
           "touchpad": { "$divide": [ { "$trunc": { "$multiply": ["$touchpad", 20] } }, 20] },
           "touchpad-attempted": { "$divide": [ { "$trunc": { "$multiply": ["$touchpad-attempted", 20] } }, 20] },
           "touchpad-success": { "$divide": [ { "$trunc": { "$multiply": ["$touchpad-success", 20] } }, 20] }
         }
      },
      {
          $project: {
              "_id": 0,
              "team": 1,
              "event": 1,
              "auto-gears": 1, // Avg. Auto Gears / Match
              "total-gears": 1, // Avg. Gears / Match
              "total-max-gears": 1, // Max. Gears / Match
              "teleop-drop-gears": 1, // Dropped Gears / Match
              "total-kPa": 1, // Avg. kPa / Match
              "touchpad": 1, // Avg. Climb / Match
              "touchpad-success": 1, // Avg. Climb / Attempt
              "total-score": 1 // Calculated Score
          }
      }
    ],

	matches: function (mongoCollection, callback) {
		mongoCollection
			.find({"competition": 2017})
			.sort({"_id": -1})
			.toArray(function (err, matches) {
				callback([
					{
                        name: "Team Matches",
                        cols: [2,3,4,5,6,7,8,9,10,11],
                        headers: [
                            {
                                text: "Team",
                                value: "team"
                            },
                            {
                                text: "Event",
                                value: "event"
                            },
                            {
                                text: "Baseline",
                                value: "baseline"
                            },
                            {
                                text: "Auto. Low Goal kPa",
                                value: "auto-low-kPa"
                            },
                            {
                                text: "Auto. High Goal kPa",
                                value: "auto-high-kPa"
                            },
                            {
                                text: "Auto. Gears Placed",
                                value: "auto-gears"
                            },
                            {
                                text: "Auto. Gears Dropped",
                                value: "auto-drop-gears"
                            },
                            {
                                text: "Teleop. Low Goal kPa",
                                value: "teleop-low-kPa"
                            },
                            {
                                text: "Teleop. High Goal kPa",
                                value: "teleop-high-kPa"
                            },
                            {
                                text: "Teleop. Gears Placed",
                                value: "teleop-gears"
                            },
                            {
                                text: "Teleop. Gears Dropped",
                                value: "teleop-drop-gears"
                            },
                            {
                                text: "Attempted Touchpad",
                                value: "touchpad-attempted"
                            },
                            {
                                text: "Pressed Touchpad",
                                value: "touchpad"
                            },
                            {
                                text: "Comments",
                                value: "comments"
                            }
                        ],
                        data: matches
					}
				]);

				db.close();
			});
	},

    comments: function (mongoCollection, callback) {
		mongoCollection
			.find({"competition": 2017, "comments": { $ne: "" }})
			.sort({"_id": -1})
			.toArray(function (err, matches) {
				callback([
					{
                        name: "Team Comments",
                        cols: [],
                        headers: [
                            {
                                text: "Team",
                                value: "team"
                            },
                            {
                                text: "Event",
                                value: "event"
                            },
                            {
                                text: "Comments",
                                value: "comments"
                            }
                        ],
                        data: matches
					}
				]);

				db.close();
			});
	},

    stratAverages: function (mongoCollection, callback) {
        mongoCollection.aggregate(this.query).toArray(function(err, matches) {
            callback([
                {
                    name: "Match Strategy Averages",
                    cols: [2,3,4,5,6,7,8],
                    headers: [
                        {
                            text: "Team",
                            value: "team"
                        },
                        {
                            text: "Event",
                            value: "event"
                        },
                        {
                            text: "Avg. Score",
                            value: "total-score"
                        },
                        {
                            text: "Avg. Gears Placed",
                            value: "total-gears"
                        },
                        {
                            text: "Avg. Auto Gears Placed",
                            value: "auto-gears"
                        },
                        {
                            text: "Max. Gears Placed",
                            value: "total-max-gears"
                        },
                        {
                            text: "Climb Avg. / Match",
                            value: "touchpad"
                        },
                        {
                            text: "Climb Avg. / Attempt",
                            value: "touchpad-success"
                        },
                        {
                            text: "Avg. kPa",
                            value: "total-kPa"
                        }
                    ],
                    data: matches
                }
            ]);

            db.close();
        });
	},

    selecAverages: function (mongoCollection, callback) {
        mongoCollection.aggregate(this.query).toArray(function(err, matches) {
            callback([
                {
                    name: "Alliance Selection Averages",
                    cols: [2,3,4,5,6,7,8,9],
                    headers: [
                        {
                            text: "Team",
                            value: "team"
                        },
                        {
                            text: "Event",
                            value: "event"
                        },
                        {
                            text: "Avg. Score",
                            value: "total-score"
                        },
                        {
                            text: "Avg. Gears Placed",
                            value: "total-gears"
                        },
                        {
                            text: "Avg. Auto Gears Placed",
                            value: "auto-gears"
                        },
                        {
                            text: "Max. Gears Placed",
                            value: "total-max-gears"
                        },
                        {
                            text: "Climb Avg. / Match",
                            value: "touchpad"
                        },
                        {
                            text: "Climb Avg. / Attempt",
                            value: "touchpad-success"
                        },
                        {
                            text: "Avg. kPa",
                            value: "total-kPa"
                        },
                        {
                            text: "Avg. Gears Dropped",
                            value: "teleop-drop-gears"
                        }
                    ],
                    data: matches
                }
            ]);

            db.close();
        });
	}
};<|endoftext|>