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

/**
 * Creates a composite report of all of the 3rd party images, code, audio, fonts used by PhET Simulations and updates
 * the online version by automatically adding and pushing the changes to GitHub.  The output can be seen at:
 * https://github.com/phetsims/sherpa/blob/master/third-party-licenses.md
 *
 * Entries in sherpa/license.json are used for the code report, and this is augmented by information obtained
 * by running mandatory simulation-specific reports using:
 *
 * grunt-all.sh build-no-lint --createSimSpecificThirdPartyReport
 *
 * indicating which third-party code resources are used by which simulations.
 *
 * See https://github.com/phetsims/chipper/issues/162
 *
 * @author Sam Reid
 */

// modules
var child_process = require( 'child_process' );
var assert = require( 'assert' );
var fs = require( 'fs' );

// constants
var SHERPA = '../sherpa';  // The relative path to sherpa, from the chipper path
var ACTIVE_RUNNABLES_FILENAME = 'chipper/data/active-runnables';  // The relative path to the list of active runnables
var OUTPUT_FILE = 'third-party-licenses.md';  // The name of the output file
var LICENSES_DIRECTORY = '../sherpa/licenses/'; // contains third-party licenses themselves.

module.exports = function( grunt ) {
  // The following comment permits node-specific globals (such as process.cwd()) to pass jshint
  /* jslint node: true */
  'use strict';

  /* jshint -W079 */
  var _ = require( '../../../sherpa/lib/lodash-2.4.1.min' ); // allow _ to be redefined, contrary to jshintOptions.js
  /* jshint +W079 */

  var directory = process.cwd();

  // Start in the github checkout dir (above one of the sibling directories)
  var rootdir = directory + '/../';

  // Aggregate results for each of the license types
  var compositeCode = {};
  var compositeImagesAndAudio = {};

  // List of all of the repository names, so that we can detect which libraries are used by all-sims
  var repositoryNames = [];

  /**
   * Add the source (images/audio or code/fonts) entries to the destination object, keyed by name.
   * @param {string} repositoryName - the name of the repository, such as 'energy-skate-park-basics'
   * @param {object} source - the object from which to read the entry
   * @param {object} destination - the object to which to append the entry
   */
  var augment = function( repositoryName, source, destination ) {
    for ( var entry in source ) {
      if ( source.hasOwnProperty( entry ) ) {
        if ( !destination.hasOwnProperty( entry ) ) {
          destination[ entry ] = source[ entry ];//overwrites
          destination[ entry ].usedBy = [];
        }
        destination[ entry ].usedBy.push( repositoryName );
      }
    }
  };

  // Iterate over all repositories images and audio directories recursively
  grunt.file.recurse( rootdir, function( abspath, rootdir, subdir, filename ) {
    if ( filename === 'third-party-report.json' ) {
      var repositoryName = subdir.substring( 0, subdir.lastIndexOf( '/' ) );

      // Report on progress as we go
      grunt.log.writeln( 'checking ' + repositoryName + '...' );
      repositoryNames.push( repositoryName );

      var json = grunt.file.readJSON( abspath );

      augment( repositoryName, json.code, compositeCode );
      augment( repositoryName, json.imagesAndAudio, compositeImagesAndAudio );
    }
  } );

  // Make sure we received a report from every active-runnable.  Otherwise, perhaps something isn't building properly
  var activeRunnables = grunt.file.read( rootdir + '/' + ACTIVE_RUNNABLES_FILENAME ).trim();
  var activeRunnablesByLine = activeRunnables.split( /\r?\n/ );
  var missing = [];
  for ( var i = 0; i < activeRunnablesByLine.length; i++ ) {
    var element = activeRunnablesByLine[ i ];
    var completed = false;
    for ( var k = 0; k < repositoryNames.length; k++ ) {
      if ( repositoryNames[ k ] === element ) {
        completed = true;
        break;
      }
    }
    if ( !completed ) {
      missing.push( element );
    }
  }
  if ( missing.length > 0 ) {
    grunt.fail.warn( 'missing reports for ' + missing.join( ', ' ) );
  }

  // Sort to easily compare lists of repositoryNames with usedBy columns, to see which resources are used by everything.
  repositoryNames.sort();

  // If anything is used by every sim indicate that here
  for ( var entry in compositeCode ) {
    if ( compositeCode.hasOwnProperty( entry ) ) {
      compositeCode[ entry ].usedBy.sort();
      if ( _.isEqual( repositoryNames, compositeCode[ entry ].usedBy ) ) {
        compositeCode[ entry ].usedBy = 'all-sims';// Confusing that this matches a repo name, but since that repo isn't actually a sim, perhaps this will be ok
      }
    }
  }

  var json = grunt.file.readJSON( SHERPA + '/lib/license.json' );

  var entries = [];
  var codeLicensesUsed = [];
  var imageAndAudioLicensesUsed = [];

  // Get a list of the library names
  var libraries = [];
  for ( var lib in json ) {
    if ( json.hasOwnProperty( lib ) ) {
      libraries.push( lib );
    }
  }

  // Use a case insensitive sort, see http://stackoverflow.com/questions/8996963/how-to-perform-case-insensitive-sorting-in-javascript
  libraries.sort( function( a, b ) {
    return a.toLowerCase().localeCompare( b.toLowerCase() );
  } );

  // Add info for each library to the MD report
  for ( i = 0; i < libraries.length; i++ ) {
    var library = libraries[ i ];

    // check for existence of the license file
    if ( !fs.existsSync( LICENSES_DIRECTORY + library + '.txt' ) ) {
      grunt.log.error( 'license file not found for ' + library );
    }

    var lines = [
      '**' + library + '**',
      json[ library ].text.join( '
' ),
      json[ library ].projectURL,
      'License: [' + json[ library ].license + '](licenses/' + library + '.txt)',
      'Notes: ' + json[ library ].notes
    ];

    if ( json[ library ].dependencies ) {
      lines.push( 'Dependencies: **' + json[ library ].dependencies + '**' );
    }

    if ( compositeCode.hasOwnProperty( library ) && compositeCode[ library ].usedBy instanceof Array ) {
      lines.push( 'Used by: ' + compositeCode[ library ].usedBy.join( ', ' ) );
    }

    // \n worked well when viewing GitHub markdown as an issue comment, but for unknown reasons
 is necessary when
    // viewing from https://github.com/phetsims/sherpa/blob/master/third-party-licenses.md
    entries.push( lines.join( '
' ) );

    if ( codeLicensesUsed.indexOf( json[ library ].license ) < 0 ) {
      codeLicensesUsed.push( json[ library ].license );
    }
  }

  var imagesAndAudioOutput = [];
  var imageAudioKeys = [];
  for ( var imageAudioEntry in compositeImagesAndAudio ) {
    if ( compositeImagesAndAudio.hasOwnProperty( imageAudioEntry ) ) {
      imageAudioKeys.push( imageAudioEntry );
    }
  }
  // Use a case insensitive sort, see http://stackoverflow.com/questions/8996963/how-to-perform-case-insensitive-sorting-in-javascript
  imageAudioKeys.sort( function( a, b ) {
    return a.toLowerCase().localeCompare( b.toLowerCase() );
  } );

  // Create the text for the image and audio, and keep track of which licenses were used by them.
  for ( i = 0; i < imageAudioKeys.length; i++ ) {
    var imageAndAudioKey = imageAudioKeys[ i ];

    var imageAudioEntryLines = [
      '**' + imageAndAudioKey + '**',
      compositeImagesAndAudio[ imageAndAudioKey ].text.join( '
' ),
      compositeImagesAndAudio[ imageAndAudioKey ].projectURL,
      'License: ' + compositeImagesAndAudio[ imageAndAudioKey ].license,
      'Notes: ' + compositeImagesAndAudio[ imageAndAudioKey ].notes
    ];
    imagesAndAudioOutput.push( imageAudioEntryLines.join( '
' ) );

    if ( imageAndAudioLicensesUsed.indexOf( compositeImagesAndAudio[ imageAndAudioKey ].license ) < 0 ) {
      imageAndAudioLicensesUsed.push( compositeImagesAndAudio[ imageAndAudioKey ].license );
    }
  }

  // Summarize licenses used
  var output =
      'This report is for the current branch & revision of each repository at the time the report was generated ' +
      'and may not match with published versions.  To see the third party resources used in published simulations, inspect ' +
      'their HTML files for the `window.phet.chipper.thirdPartyLicenses` and `window.phet.chipper.thirdPartyImagesAndAudio` ' +
      '(only exists in recent sim publications).\n' +
      '* [Third-party Code & Fonts](#third-party-code-and-fonts)\n' +
      '* [Third-party Code & Fonts License Summary](#third-party-code-and-fonts-license-summary)\n' +
      '* [Third-party Images & Audio](#third-party-images-and-audio)\n' +
      '* [Third-party Images & Audio License Summary](#third-party-images-and-audio-license-summary)\n\n' +
      '# Third-party Code & Fonts:
\n' +
      entries.join( '\n\n' ) + '\n\n' +

      '---\n' +

      '# Third-party Code & Fonts License Summary:
\n' +
      codeLicensesUsed.join( '
' ) + '\n\n' +

      '---\n' +

      '# Third-party Images & Audio:
\n' +
      imagesAndAudioOutput.join( '\n\n' ) + '\n\n' +

      '---\n' +

      '# Third-party Images & Audio License Summary:
\n' +
      imageAndAudioLicensesUsed.join( '
' ) + '\n\n'
    ;

  // It is sometimes convenient to iterate using GitHub issue preview rather than committing every time.
  // In this case, you may want to comment out the commit below.
  grunt.log.debug( '!!!!!! BEGIN LICENSES OUTPUT' );
  grunt.log.debug( output );
  grunt.log.debug( '!!!!!! END LICENSES OUTPUT' );

  // Compare the file output to the existing file, and write & git commit only if different
  if ( grunt.file.read( SHERPA + '/' + OUTPUT_FILE ) !== output ) {
    grunt.log.writeln( 'File output changed, writing file ' + OUTPUT_FILE );
    grunt.file.write( SHERPA + '/' + OUTPUT_FILE, output );

    var done = grunt.task.current.async();

    // exec a command in the sherpa directory
    var exec = function( command, callback ) {
      child_process.exec( command, { cwd: SHERPA }, function( err, stdout, stderr ) {
        grunt.log.writeln( stdout );
        grunt.log.writeln( stderr );
        assert( !err, 'assertion error running ' + command );
        callback();
      } );
    };

    // Add and commit the changes to the output file
    exec( 'git add ' + OUTPUT_FILE, function() {
      exec( 'git commit --message "updated ' + OUTPUT_FILE + '"', function() {
        exec( 'git push', function() {
          done();
        } );
      } );
    } );
  }
  else {
    grunt.log.writeln( OUTPUT_FILE + ' contents are the same.  No need to save/commit.' );
  }
};<commit_msg>Changed "code and fonts" to "code", see #55<commit_after>// Copyright 2002-2015, University of Colorado Boulder

/**
 * Creates a composite report of all of the 3rd party images, code, audio and other media used by PhET Simulations and
 * updates the online version by automatically adding and pushing the changes to GitHub.  The output can be seen at:
 * https://github.com/phetsims/sherpa/blob/master/third-party-licenses.md
 *
 * Entries in sherpa/license.json are used for the code report, and this is augmented by information obtained
 * by running mandatory simulation-specific reports using:
 *
 * grunt-all.sh build-no-lint --createSimSpecificThirdPartyReport
 *
 * indicating which third-party code resources are used by which simulations.
 *
 * See https://github.com/phetsims/chipper/issues/162
 *
 * @author Sam Reid
 */

// modules
var child_process = require( 'child_process' );
var assert = require( 'assert' );
var fs = require( 'fs' );

// constants
var SHERPA = '../sherpa';  // The relative path to sherpa, from the chipper path
var ACTIVE_RUNNABLES_FILENAME = 'chipper/data/active-runnables';  // The relative path to the list of active runnables
var OUTPUT_FILE = 'third-party-licenses.md';  // The name of the output file
var LICENSES_DIRECTORY = '../sherpa/licenses/'; // contains third-party licenses themselves.

module.exports = function( grunt ) {
  // The following comment permits node-specific globals (such as process.cwd()) to pass jshint
  /* jslint node: true */
  'use strict';

  /* jshint -W079 */
  var _ = require( '../../../sherpa/lib/lodash-2.4.1.min' ); // allow _ to be redefined, contrary to jshintOptions.js
  /* jshint +W079 */

  var directory = process.cwd();

  // Start in the github checkout dir (above one of the sibling directories)
  var rootdir = directory + '/../';

  // Aggregate results for each of the license types
  var compositeCode = {};
  var compositeImagesAndAudio = {};

  // List of all of the repository names, so that we can detect which libraries are used by all-sims
  var repositoryNames = [];

  /**
   * Add the source (images/audio/media or code) entries to the destination object, keyed by name.
   * @param {string} repositoryName - the name of the repository, such as 'energy-skate-park-basics'
   * @param {object} source - the object from which to read the entry
   * @param {object} destination - the object to which to append the entry
   */
  var augment = function( repositoryName, source, destination ) {
    for ( var entry in source ) {
      if ( source.hasOwnProperty( entry ) ) {
        if ( !destination.hasOwnProperty( entry ) ) {
          destination[ entry ] = source[ entry ];//overwrites
          destination[ entry ].usedBy = [];
        }
        destination[ entry ].usedBy.push( repositoryName );
      }
    }
  };

  // Iterate over all repositories images and audio directories recursively
  grunt.file.recurse( rootdir, function( abspath, rootdir, subdir, filename ) {
    if ( filename === 'third-party-report.json' ) {
      var repositoryName = subdir.substring( 0, subdir.lastIndexOf( '/' ) );

      // Report on progress as we go
      grunt.log.writeln( 'checking ' + repositoryName + '...' );
      repositoryNames.push( repositoryName );

      var json = grunt.file.readJSON( abspath );

      augment( repositoryName, json.code, compositeCode );
      augment( repositoryName, json.imagesAndAudio, compositeImagesAndAudio );
    }
  } );

  // Make sure we received a report from every active-runnable.  Otherwise, perhaps something isn't building properly
  var activeRunnables = grunt.file.read( rootdir + '/' + ACTIVE_RUNNABLES_FILENAME ).trim();
  var activeRunnablesByLine = activeRunnables.split( /\r?\n/ );
  var missing = [];
  for ( var i = 0; i < activeRunnablesByLine.length; i++ ) {
    var element = activeRunnablesByLine[ i ];
    var completed = false;
    for ( var k = 0; k < repositoryNames.length; k++ ) {
      if ( repositoryNames[ k ] === element ) {
        completed = true;
        break;
      }
    }
    if ( !completed ) {
      missing.push( element );
    }
  }
  if ( missing.length > 0 ) {
    grunt.fail.warn( 'missing reports for ' + missing.join( ', ' ) );
  }

  // Sort to easily compare lists of repositoryNames with usedBy columns, to see which resources are used by everything.
  repositoryNames.sort();

  // If anything is used by every sim indicate that here
  for ( var entry in compositeCode ) {
    if ( compositeCode.hasOwnProperty( entry ) ) {
      compositeCode[ entry ].usedBy.sort();
      if ( _.isEqual( repositoryNames, compositeCode[ entry ].usedBy ) ) {
        compositeCode[ entry ].usedBy = 'all-sims';// Confusing that this matches a repo name, but since that repo isn't actually a sim, perhaps this will be ok
      }
    }
  }

  var json = grunt.file.readJSON( SHERPA + '/lib/license.json' );

  var entries = [];
  var codeLicensesUsed = [];
  var imageAndAudioLicensesUsed = [];

  // Get a list of the library names
  var libraries = [];
  for ( var lib in json ) {
    if ( json.hasOwnProperty( lib ) ) {
      libraries.push( lib );
    }
  }

  // Use a case insensitive sort, see http://stackoverflow.com/questions/8996963/how-to-perform-case-insensitive-sorting-in-javascript
  libraries.sort( function( a, b ) {
    return a.toLowerCase().localeCompare( b.toLowerCase() );
  } );

  // Add info for each library to the MD report
  for ( i = 0; i < libraries.length; i++ ) {
    var library = libraries[ i ];

    // check for existence of the license file
    if ( !fs.existsSync( LICENSES_DIRECTORY + library + '.txt' ) ) {
      grunt.log.error( 'license file not found for ' + library );
    }

    var lines = [
      '**' + library + '**',
      json[ library ].text.join( '
' ),
      json[ library ].projectURL,
      'License: [' + json[ library ].license + '](licenses/' + library + '.txt)',
      'Notes: ' + json[ library ].notes
    ];

    if ( json[ library ].dependencies ) {
      lines.push( 'Dependencies: **' + json[ library ].dependencies + '**' );
    }

    if ( compositeCode.hasOwnProperty( library ) && compositeCode[ library ].usedBy instanceof Array ) {
      lines.push( 'Used by: ' + compositeCode[ library ].usedBy.join( ', ' ) );
    }

    // \n worked well when viewing GitHub markdown as an issue comment, but for unknown reasons
 is necessary when
    // viewing from https://github.com/phetsims/sherpa/blob/master/third-party-licenses.md
    entries.push( lines.join( '
' ) );

    if ( codeLicensesUsed.indexOf( json[ library ].license ) < 0 ) {
      codeLicensesUsed.push( json[ library ].license );
    }
  }

  var imagesAndAudioOutput = [];
  var imageAudioKeys = [];
  for ( var imageAudioEntry in compositeImagesAndAudio ) {
    if ( compositeImagesAndAudio.hasOwnProperty( imageAudioEntry ) ) {
      imageAudioKeys.push( imageAudioEntry );
    }
  }
  // Use a case insensitive sort, see http://stackoverflow.com/questions/8996963/how-to-perform-case-insensitive-sorting-in-javascript
  imageAudioKeys.sort( function( a, b ) {
    return a.toLowerCase().localeCompare( b.toLowerCase() );
  } );

  // Create the text for the image and audio, and keep track of which licenses were used by them.
  for ( i = 0; i < imageAudioKeys.length; i++ ) {
    var imageAndAudioKey = imageAudioKeys[ i ];

    var imageAudioEntryLines = [
      '**' + imageAndAudioKey + '**',
      compositeImagesAndAudio[ imageAndAudioKey ].text.join( '
' ),
      compositeImagesAndAudio[ imageAndAudioKey ].projectURL,
      'License: ' + compositeImagesAndAudio[ imageAndAudioKey ].license,
      'Notes: ' + compositeImagesAndAudio[ imageAndAudioKey ].notes
    ];
    imagesAndAudioOutput.push( imageAudioEntryLines.join( '
' ) );

    if ( imageAndAudioLicensesUsed.indexOf( compositeImagesAndAudio[ imageAndAudioKey ].license ) < 0 ) {
      imageAndAudioLicensesUsed.push( compositeImagesAndAudio[ imageAndAudioKey ].license );
    }
  }

  // Summarize licenses used
  var output =
      'This report is for the current branch & revision of each repository at the time the report was generated ' +
      'and may not match with published versions.  To see the third party resources used in published simulations, inspect ' +
      'their HTML files for the `window.phet.chipper.thirdPartyLicenses` and `window.phet.chipper.thirdPartyImagesAndAudio` ' +
      '(only exists in recent sim publications).\n' +
      '* [Third-party Code](#third-party-code)\n' +
      '* [Third-party Code License Summary](#third-party-code-license-summary)\n' +
      '* [Third-party Images & Audio](#third-party-images-and-audio)\n' +
      '* [Third-party Images & Audio License Summary](#third-party-images-and-audio-license-summary)\n\n' +
      '# Third-party Code:
\n' +
      entries.join( '\n\n' ) + '\n\n' +

      '---\n' +

      '# Third-party Code License Summary:
\n' +
      codeLicensesUsed.join( '
' ) + '\n\n' +

      '---\n' +

      '# Third-party Images & Audio:
\n' +
      imagesAndAudioOutput.join( '\n\n' ) + '\n\n' +

      '---\n' +

      '# Third-party Images & Audio License Summary:
\n' +
      imageAndAudioLicensesUsed.join( '
' ) + '\n\n'
    ;

  // It is sometimes convenient to iterate using GitHub issue preview rather than committing every time.
  // In this case, you may want to comment out the commit below.
  grunt.log.debug( '!!!!!! BEGIN LICENSES OUTPUT' );
  grunt.log.debug( output );
  grunt.log.debug( '!!!!!! END LICENSES OUTPUT' );

  // Compare the file output to the existing file, and write & git commit only if different
  if ( grunt.file.read( SHERPA + '/' + OUTPUT_FILE ) !== output ) {
    grunt.log.writeln( 'File output changed, writing file ' + OUTPUT_FILE );
    grunt.file.write( SHERPA + '/' + OUTPUT_FILE, output );

    var done = grunt.task.current.async();

    // exec a command in the sherpa directory
    var exec = function( command, callback ) {
      child_process.exec( command, { cwd: SHERPA }, function( err, stdout, stderr ) {
        grunt.log.writeln( stdout );
        grunt.log.writeln( stderr );
        assert( !err, 'assertion error running ' + command );
        callback();
      } );
    };

    // Add and commit the changes to the output file
    exec( 'git add ' + OUTPUT_FILE, function() {
      exec( 'git commit --message "updated ' + OUTPUT_FILE + '"', function() {
        exec( 'git push', function() {
          done();
        } );
      } );
    } );
  }
  else {
    grunt.log.writeln( OUTPUT_FILE + ' contents are the same.  No need to save/commit.' );
  }
};<|endoftext|>


<commit_before>'use strict';

const electron = require("electron");
const BrowserWindow = electron.BrowserWindow;
const PersistentStorage = require(__app.basePath + "/js/common/PersistentStorage");

/**
 * HackBrowserWindowManager handles opening and closing of browser windows
 *
 * @constructor
 */
function HackBrowserWindowManager(mainProcessController) {
	var _this = this;

	var mainProcessEventEmitter;

	var browserWindowList = {};
	var createdWindowCount = 0;

	var loginWindow;
	var pictureDisplayWindow;
	var researchTopicWindow;
	var browserWindow;
	var browserPictureDisplayWindow;
	var helpWindow;

	/* ====================================
	 private methods
	 ====================================== */
	var init = function() {
		loginWindow = null;
		pictureDisplayWindow = null;
		researchTopicWindow = null;
		browserWindow = null;
		browserPictureDisplayWindow = null;
		helpWindow = null;

		mainProcessEventEmitter = mainProcessController.getMainProcessEventEmitter();

		mainProcessEventEmitter.on("userNameCheckPass", handleUserNameCheckPass);
		mainProcessEventEmitter.on("userPictureWindowCloseRequest", handleUserPictureWindowCloseRequest);
		mainProcessEventEmitter.on("researchTopicInputComplete", handleResearchTopicInputComplete);
	};

	var attachEventHandlersToBrowserWindow = function(browserWindow) {
		var windowId = browserWindow.id;

		browserWindow.on("move", function(e) {
			_this.repositionBrowserPictureDisplayWindow();
		});

		browserWindow.on("resize", function(e) {
			_this.repositionBrowserPictureDisplayWindow();
		});

		browserWindow.on("blur", function(e) {
			setTimeout(function() {
				setBrowserPictureDisplayWindowVisibility(false);
			}, 50);
		});

		browserWindow.on("focus", function(e) {
			setBrowserPictureDisplayWindowVisibility(true);
		});

		// save browser window's width/height when user closes it
		browserWindow.on("close", function(e) {
			var size = browserWindow.getSize();

			var sizeObject = {
				"width": size[0],
				"height": size[1]
			};

			// save to persistent storage
			PersistentStorage.setItem("browserWindowSize", sizeObject);

			// also close in-browser picture display
			_this.closeBrowserPictureDisplayWindow();

			e.returnValue = false;
		});

		// remove the window from browserWindowList and remove reference so that GC clear is from memory
		browserWindow.on("closed", function() {
			if (browserWindowList.hasOwnProperty(windowId)) {
				console.log("deleting window " + windowId);

				delete browserWindowList[windowId];
				browserWindow = null;
			}
		});
	};

	var attachEventHandlersToBrowserPictureWindow = function(pictureWindow) {
		pictureWindow.on("move", function(e) {
			repositionBrowserWindowRelativeToPictureWindow();
		});
	};

	/**
	 * event handler for username check pass result
	 *
	 * @param {string} userName
	 */
	var handleUserNameCheckPass = function(userName) {
		mainProcessController.setParticipantDataItem("userName", userName);

		// also set userName in ActivityRecorder
		mainProcessController.getActivityRecorder().setParticipantUserName(userName);

		// get picture URL
		mainProcessController.getActivityRecorder().getUserPictureInfoFromServer(
			function(err) {
				dialog.showErrorBox('Error retrieving picture URL', 'Server is not responding. ');
			},
			function(imageInfoObj) {
				console.log("HackBrowserWindowManager.handleUserNameCheckPass()");
				console.log(imageInfoObj);
				mainProcessController.setPictureInfo(imageInfoObj);

				// _this.openResearchTopicWindow();
				_this.openPictureDisplayWindow();
				_this.closeLoginWindow();
			}
		);
	};

	/**
	 * close "picture display" window and open research topic input window
	 */
	var handleUserPictureWindowCloseRequest= function() {
		_this.openResearchTopicWindow();
		_this.closePictureDisplayWindow();
	};

	/**
	 * handle user's research topic information input from window
	 * and pass it to an ActivityRecorder instance to post to TrackBrowser server
	 *
	 * @param {object} msgObject containing user's research topic data
	 */
	var handleResearchTopicInputComplete = function(msgObject) {
		var isNewSession = msgObject.isNewSession;
		var researchTopicData = msgObject.researchTopicData;

		for (var key in researchTopicData) {
			if (researchTopicData.hasOwnProperty(key)) {
				mainProcessController.setParticipantDataItem(key, researchTopicData[key]);
			}
		}

		mainProcessController.getActivityRecorder().recordUserInfo(researchTopicData);

		if (isNewSession === true) {
			_this.openNewBrowserWindow(function() {
				_this.closeResearchTopicWindow();
			});
		} else {
			_this.closeResearchTopicWindow();
		}
	};

	var setBrowserPictureDisplayWindowVisibility = function(isVisible) {
		// if either browserWindow or browserPictureDisplayWindow is not open, do nothing
		if ((browserWindow === null) || (browserPictureDisplayWindow === null)) return;

		if (isVisible === true) {
			browserPictureDisplayWindow.showInactive();
		} else {
			if (browserPictureDisplayWindow.isFocused() === false) {
				browserPictureDisplayWindow.hide();
			}
		}
	};

	var repositionBrowserWindowRelativeToPictureWindow = function() {
		// if either browserWindow or browserPictureDisplayWindow is not open, do nothing
		if ((browserWindow === null) || (browserPictureDisplayWindow === null)) return;

		var browserWindowBounds = browserWindow.getBounds();
		var pictureWindowBounds = browserPictureDisplayWindow.getBounds();

		var newXPos = pictureWindowBounds.x - browserWindowBounds.width - 10;
		var newYPos = pictureWindowBounds.y;

		browserWindow.setPosition(newXPos, newYPos);
	};

	/* ====================================
	 public methods
	 ====================================== */
	/**
	 * open login window
	 *
	 * @param callback
	 */
	_this.openLoginWindow = function(callback) {
		callback = callback || function() {};

		// if research topic input window is already open,
		// do nothing
		if (loginWindow !== null) {
			return;
		}

		// Create the login window
		loginWindow = new BrowserWindow({
			width:600,
			height: 400,
			resizable: false,
			frame: false
		});

		loginWindow.loadURL("file://" + __app.basePath + "/html-pages/login.html");

		loginWindow.on('closed', function() {
			loginWindow = null;
		});

		callback();
	};

	/**
	 * close login window
	 *
	 * @param callback
	 */
	_this.closeLoginWindow = function(callback) {
		callback = callback || function() {};

		// close login window
		loginWindow.close();

		callback();
	};

	/**
	 * open "picture display" window
	 *
	 * @param callback
	 */
	_this.openPictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		// if research topic input window is already open,
		// do nothing
		if (pictureDisplayWindow !== null) {
			return;
		}

		var pictureInfo = mainProcessController.getPictureInfo();

		var windowWidth = 600;

		// if the image's width is smaller than default window width,
		// fit the window's width to image width
		if (windowWidth > pictureInfo.width) {
			windowWidth = pictureInfo.width;
		}

		// calculate width/height ratio
		var widthHeightRatio = pictureInfo.width / pictureInfo.height;

		var windowHeight = Math.ceil(windowWidth * (1 / widthHeightRatio)) + 60;

		// create the picture display window
		pictureDisplayWindow = new BrowserWindow({
			width: windowWidth,
			height: windowHeight,
			resizable: false,
			frame: false
		});

		pictureDisplayWindow.loadURL("file://" + __app.basePath + "/html-pages/picture-display.html");

		// pictureDisplayWindow.openDevTools();

		pictureDisplayWindow.on('closed', function() {
			pictureDisplayWindow = null;
		});

		callback();
	};

	/**
	 * close "picture display" window
	 *
	 * @param callback
	 */
	_this.closePictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		// close login window
		pictureDisplayWindow.close();

		callback();
	};

	/**
	 * open "research topic" window
	 *
	 * @param callback
	 */
	_this.openResearchTopicWindow = function(callback) {
		callback = callback || function() {};

		// if research topic input window is already open,
		// do nothing
		if (researchTopicWindow !== null) {
			return;
		}

		researchTopicWindow = new BrowserWindow({
			width: 600,
			height: 600,
			resizable: false,
			frame: false
		});

		researchTopicWindow.loadURL("file://" + __app.basePath + "/html-pages/research-topic.html");

		// researchTopicWindow.openDevTools();

		researchTopicWindow.on('closed', function() {
			researchTopicWindow = null;
		});

		callback();
	};

	/**
	 * close "research topic" window
	 *
	 * @param callback
	 */
	_this.closeResearchTopicWindow = function(callback) {
		callback = callback || function() {};

		researchTopicWindow.close();

		callback();
	};

	/**
	 * open a new browser(TrackBrowser) window
	 * @param callback
	 */
	_this.openNewBrowserWindow = function(callback) {
		callback = callback || function() {};

		// get last browser size
		PersistentStorage.getItem("browserWindowSize", function(err, browserSize) {
			if (err) {
				browserSize = {
					width: 1000,
					height: 800
				};
			}

			// create the browser window
			browserWindow = new BrowserWindow({
				width: browserSize.width,
				height: browserSize.height,
				frame: true
			});

			// load the HTML file for browser window
			browserWindow.loadURL("file://" + __app.basePath + "/html-pages/browser-window.html");

			// Open the DevTools (debugging)
			// browserWindow.openDevTools();

			browserWindowList[browserWindow.id] = browserWindow;
			attachEventHandlersToBrowserWindow(browserWindow);

			_this.openBrowserPictureDisplayWindow();

			// increase window count
			createdWindowCount++;

			callback();
		});
	};

	/**
	 * open in-browser "picture display" window
	 *
	 * @param callback
	 */
	_this.openBrowserPictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		console.log("HackBrowserWindowManager.openBrowserPictureDisplayWindow()");

		// if browser picture display window is already open,
		// do nothing
		if (browserPictureDisplayWindow !== null) {
			return;
		}

		var pictureInfo = mainProcessController.getPictureInfo();

		// make max window width small
		var windowWidth = 250;

		// if the image's width is smaller than default window width,
		// fit the window's width to image width
		if (windowWidth > pictureInfo.width) {
			windowWidth = pictureInfo.width;
		}

		// calculate width/height ratio
		var widthHeightRatio = pictureInfo.width / pictureInfo.height;
		var windowHeight = Math.ceil(windowWidth * (1 / widthHeightRatio));

		// create the picture display window
		browserPictureDisplayWindow = new BrowserWindow({
			width: windowWidth,
			height: windowHeight,
			resizable: false,
			frame: false
		});

		browserPictureDisplayWindow.loadURL("file://" + __app.basePath + "/html-pages/browser-window-picture-display.html");
		browserPictureDisplayWindow.setAlwaysOnTop(true);

		browserPictureDisplayWindow.on('closed', function() {
			browserPictureDisplayWindow = null;
		});

		attachEventHandlersToBrowserPictureWindow(browserPictureDisplayWindow);

		callback();
	};

	/**
	 * close in-browser "picture display" window
	 *
	 * @param callback
	 */
	_this.closeBrowserPictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		// close login window
		browserPictureDisplayWindow.close();

		callback();
	};

	_this.repositionBrowserPictureDisplayWindow = function() {
		// if either browserWindow or browserPictureDisplayWindow is not open, do nothing
		if ((browserWindow === null) || (browserPictureDisplayWindow === null)) return;

		var browserWindowBounds = browserWindow.getBounds();

		var newXPos = browserWindowBounds.x + browserWindowBounds.width + 10;
		var newYPos = browserWindowBounds.y;

		browserPictureDisplayWindow.setPosition(newXPos, newYPos);
	};

	/**
	 * open help window
	 *
	 * @param callback
	 */
	_this.openHelpWindow = function(callback) {
		callback = callback || function() {};

		helpWindow = new BrowserWindow({
			width: 700,
			height: 600,
			resizable: false,
			frame: false
		});

		helpWindow.loadURL("file://" + __app.basePath + "/html-pages/help.html");

		// helpWindow.openDevTools();

		helpWindow.on('closed', function() {
			helpWindow = null;
		});

		callback();
	};

	/**
	 * close help window
	 *
	 * @param callback
	 */
	_this.closeHelpWindow = function(callback) {
		callback = callback || function() {};

		helpWindow.close();

		callback();
	};

	_this.getBrowserWindow = function() {
		return browserWindow;
	};

	_this.getLoginWindow = function() {
		return loginWindow;
	};

	_this.getResearchTopicWinodw = function() {
		return researchTopicWindow;
	};

	init();
}

module.exports = HackBrowserWindowManager;<commit_msg>test release v1<commit_after>'use strict';

const electron = require("electron");
const BrowserWindow = electron.BrowserWindow;
const PersistentStorage = require(__app.basePath + "/js/common/PersistentStorage");

/**
 * HackBrowserWindowManager handles opening and closing of browser windows
 *
 * @constructor
 */
function HackBrowserWindowManager(mainProcessController) {
	var _this = this;

	var mainProcessEventEmitter;

	var browserWindowList = {};
	var createdWindowCount = 0;

	var loginWindow;
	var pictureDisplayWindow;
	var researchTopicWindow;
	var browserWindow;
	var browserPictureDisplayWindow;
	var helpWindow;

	/* ====================================
	 private methods
	 ====================================== */
	var init = function() {
		loginWindow = null;
		pictureDisplayWindow = null;
		researchTopicWindow = null;
		browserWindow = null;
		browserPictureDisplayWindow = null;
		helpWindow = null;

		mainProcessEventEmitter = mainProcessController.getMainProcessEventEmitter();

		mainProcessEventEmitter.on("userNameCheckPass", handleUserNameCheckPass);
		mainProcessEventEmitter.on("userPictureWindowCloseRequest", handleUserPictureWindowCloseRequest);
		mainProcessEventEmitter.on("researchTopicInputComplete", handleResearchTopicInputComplete);
	};

	var attachEventHandlersToBrowserWindow = function(browserWindow) {
		var windowId = browserWindow.id;

		browserWindow.on("move", function(e) {
			_this.repositionBrowserPictureDisplayWindow();
		});

		browserWindow.on("resize", function(e) {
			_this.repositionBrowserPictureDisplayWindow();
		});

		browserWindow.on("blur", function(e) {
			setTimeout(function() {
				setBrowserPictureDisplayWindowVisibility(false);
			}, 50);
		});

		browserWindow.on("focus", function(e) {
			setBrowserPictureDisplayWindowVisibility(true);
		});

		// save browser window's width/height when user closes it
		browserWindow.on("close", function(e) {
			var size = browserWindow.getSize();

			var sizeObject = {
				"width": size[0],
				"height": size[1]
			};

			// save to persistent storage
			PersistentStorage.setItem("browserWindowSize", sizeObject);

			// also close in-browser picture display
			_this.closeBrowserPictureDisplayWindow();

			e.returnValue = false;
		});

		// remove the window from browserWindowList and remove reference so that GC clear is from memory
		browserWindow.on("closed", function() {
			if (browserWindowList.hasOwnProperty(windowId)) {
				console.log("deleting window " + windowId);

				delete browserWindowList[windowId];
				browserWindow = null;
			}
		});
	};

	var attachEventHandlersToBrowserPictureWindow = function(pictureWindow) {
		pictureWindow.on("move", function(e) {
			repositionBrowserWindowRelativeToPictureWindow();
		});
	};

	/**
	 * event handler for username check pass result
	 *
	 * @param {string} userName
	 */
	var handleUserNameCheckPass = function(userName) {
		mainProcessController.setParticipantDataItem("userName", userName);

		// also set userName in ActivityRecorder
		mainProcessController.getActivityRecorder().setParticipantUserName(userName);

		// get picture URL
		mainProcessController.getActivityRecorder().getUserPictureInfoFromServer(
			function(err) {
				dialog.showErrorBox('Error retrieving picture URL', 'Server is not responding. ');
			},
			function(imageInfoObj) {
				console.log("HackBrowserWindowManager.handleUserNameCheckPass()");
				console.log(imageInfoObj);
				mainProcessController.setPictureInfo(imageInfoObj);

				// _this.openResearchTopicWindow();
				_this.openPictureDisplayWindow();
				_this.closeLoginWindow();
			}
		);
	};

	/**
	 * close "picture display" window and open research topic input window
	 */
	var handleUserPictureWindowCloseRequest= function() {
		_this.openResearchTopicWindow();
		_this.closePictureDisplayWindow();
	};

	/**
	 * handle user's research topic information input from window
	 * and pass it to an ActivityRecorder instance to post to TrackBrowser server
	 *
	 * @param {object} msgObject containing user's research topic data
	 */
	var handleResearchTopicInputComplete = function(msgObject) {
		var isNewSession = msgObject.isNewSession;
		var researchTopicData = msgObject.researchTopicData;

		for (var key in researchTopicData) {
			if (researchTopicData.hasOwnProperty(key)) {
				mainProcessController.setParticipantDataItem(key, researchTopicData[key]);
			}
		}

		mainProcessController.getActivityRecorder().recordUserInfo(researchTopicData);

		if (isNewSession === true) {
			_this.openNewBrowserWindow(function() {
				_this.closeResearchTopicWindow();
			});
		} else {
			_this.closeResearchTopicWindow();
		}
	};

	var setBrowserPictureDisplayWindowVisibility = function(isVisible) {
		// if either browserWindow or browserPictureDisplayWindow is not open, do nothing
		if ((browserWindow === null) || (browserPictureDisplayWindow === null)) return;

		if (isVisible === true) {
			browserPictureDisplayWindow.showInactive();
		} else {
			if (browserPictureDisplayWindow.isFocused() === false) {
				browserPictureDisplayWindow.hide();
			}
		}
	};

	var repositionBrowserWindowRelativeToPictureWindow = function() {
		// if either browserWindow or browserPictureDisplayWindow is not open, do nothing
		if ((browserWindow === null) || (browserPictureDisplayWindow === null)) return;

		var browserWindowBounds = browserWindow.getBounds();
		var pictureWindowBounds = browserPictureDisplayWindow.getBounds();

		var newXPos = pictureWindowBounds.x - browserWindowBounds.width - 10;
		var newYPos = pictureWindowBounds.y;

		browserWindow.setPosition(newXPos, newYPos);
	};

	/* ====================================
	 public methods
	 ====================================== */
	/**
	 * open login window
	 *
	 * @param callback
	 */
	_this.openLoginWindow = function(callback) {
		callback = callback || function() {};

		// if research topic input window is already open,
		// do nothing
		if (loginWindow !== null) {
			return;
		}

		// Create the login window
		loginWindow = new BrowserWindow({
			width:600,
			height: 400,
			resizable: false,
			frame: false
		});

		loginWindow.loadURL("file://" + __app.basePath + "/html-pages/login.html");

		// loginWindow.openDevTools();

		loginWindow.on('closed', function() {
			loginWindow = null;
		});

		callback();
	};

	/**
	 * close login window
	 *
	 * @param callback
	 */
	_this.closeLoginWindow = function(callback) {
		callback = callback || function() {};

		// close login window
		loginWindow.close();

		callback();
	};

	/**
	 * open "picture display" window
	 *
	 * @param callback
	 */
	_this.openPictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		// if research topic input window is already open,
		// do nothing
		if (pictureDisplayWindow !== null) {
			return;
		}

		var pictureInfo = mainProcessController.getPictureInfo();

		var windowWidth = 600;

		// if the image's width is smaller than default window width,
		// fit the window's width to image width
		if (windowWidth > pictureInfo.width) {
			windowWidth = pictureInfo.width;
		}

		// calculate width/height ratio
		var widthHeightRatio = pictureInfo.width / pictureInfo.height;

		var windowHeight = Math.ceil(windowWidth * (1 / widthHeightRatio)) + 60;

		// create the picture display window
		pictureDisplayWindow = new BrowserWindow({
			width: windowWidth,
			height: windowHeight,
			resizable: false,
			frame: false
		});

		pictureDisplayWindow.loadURL("file://" + __app.basePath + "/html-pages/picture-display.html");

		// pictureDisplayWindow.openDevTools();

		pictureDisplayWindow.on('closed', function() {
			pictureDisplayWindow = null;
		});

		callback();
	};

	/**
	 * close "picture display" window
	 *
	 * @param callback
	 */
	_this.closePictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		// close login window
		pictureDisplayWindow.close();

		callback();
	};

	/**
	 * open "research topic" window
	 *
	 * @param callback
	 */
	_this.openResearchTopicWindow = function(callback) {
		callback = callback || function() {};

		// if research topic input window is already open,
		// do nothing
		if (researchTopicWindow !== null) {
			return;
		}

		researchTopicWindow = new BrowserWindow({
			width: 600,
			height: 600,
			resizable: false,
			frame: false
		});

		researchTopicWindow.loadURL("file://" + __app.basePath + "/html-pages/research-topic.html");

		// researchTopicWindow.openDevTools();

		researchTopicWindow.on('closed', function() {
			researchTopicWindow = null;
		});

		callback();
	};

	/**
	 * close "research topic" window
	 *
	 * @param callback
	 */
	_this.closeResearchTopicWindow = function(callback) {
		callback = callback || function() {};

		researchTopicWindow.close();

		callback();
	};

	/**
	 * open a new browser(TrackBrowser) window
	 * @param callback
	 */
	_this.openNewBrowserWindow = function(callback) {
		callback = callback || function() {};

		// get last browser size
		PersistentStorage.getItem("browserWindowSize", function(err, browserSize) {
			if (err) {
				browserSize = {
					width: 1000,
					height: 800
				};
			}

			// create the browser window
			browserWindow = new BrowserWindow({
				width: browserSize.width,
				height: browserSize.height,
				frame: true
			});

			// load the HTML file for browser window
			browserWindow.loadURL("file://" + __app.basePath + "/html-pages/browser-window.html");

			// Open the DevTools (debugging)
			// browserWindow.openDevTools();

			browserWindowList[browserWindow.id] = browserWindow;
			attachEventHandlersToBrowserWindow(browserWindow);

			_this.openBrowserPictureDisplayWindow();

			// increase window count
			createdWindowCount++;

			callback();
		});
	};

	/**
	 * open in-browser "picture display" window
	 *
	 * @param callback
	 */
	_this.openBrowserPictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		console.log("HackBrowserWindowManager.openBrowserPictureDisplayWindow()");

		// if browser picture display window is already open,
		// do nothing
		if (browserPictureDisplayWindow !== null) {
			return;
		}

		var pictureInfo = mainProcessController.getPictureInfo();

		// make max window width small
		var windowWidth = 250;

		// if the image's width is smaller than default window width,
		// fit the window's width to image width
		if (windowWidth > pictureInfo.width) {
			windowWidth = pictureInfo.width;
		}

		// calculate width/height ratio
		var widthHeightRatio = pictureInfo.width / pictureInfo.height;
		var windowHeight = Math.ceil(windowWidth * (1 / widthHeightRatio));

		// create the picture display window
		browserPictureDisplayWindow = new BrowserWindow({
			width: windowWidth,
			height: windowHeight,
			resizable: false,
			frame: false
		});

		browserPictureDisplayWindow.loadURL("file://" + __app.basePath + "/html-pages/browser-window-picture-display.html");
		browserPictureDisplayWindow.setAlwaysOnTop(true);

		browserPictureDisplayWindow.on('closed', function() {
			browserPictureDisplayWindow = null;
		});

		attachEventHandlersToBrowserPictureWindow(browserPictureDisplayWindow);

		callback();
	};

	/**
	 * close in-browser "picture display" window
	 *
	 * @param callback
	 */
	_this.closeBrowserPictureDisplayWindow = function(callback) {
		callback = callback || function() {};

		// close login window
		browserPictureDisplayWindow.close();

		callback();
	};

	_this.repositionBrowserPictureDisplayWindow = function() {
		// if either browserWindow or browserPictureDisplayWindow is not open, do nothing
		if ((browserWindow === null) || (browserPictureDisplayWindow === null)) return;

		var browserWindowBounds = browserWindow.getBounds();

		var newXPos = browserWindowBounds.x + browserWindowBounds.width + 10;
		var newYPos = browserWindowBounds.y;

		browserPictureDisplayWindow.setPosition(newXPos, newYPos);
	};

	/**
	 * open help window
	 *
	 * @param callback
	 */
	_this.openHelpWindow = function(callback) {
		callback = callback || function() {};

		helpWindow = new BrowserWindow({
			width: 700,
			height: 600,
			resizable: false,
			frame: false
		});

		helpWindow.loadURL("file://" + __app.basePath + "/html-pages/help.html");

		// helpWindow.openDevTools();

		helpWindow.on('closed', function() {
			helpWindow = null;
		});

		callback();
	};

	/**
	 * close help window
	 *
	 * @param callback
	 */
	_this.closeHelpWindow = function(callback) {
		callback = callback || function() {};

		helpWindow.close();

		callback();
	};

	_this.getBrowserWindow = function() {
		return browserWindow;
	};

	_this.getLoginWindow = function() {
		return loginWindow;
	};

	_this.getResearchTopicWinodw = function() {
		return researchTopicWindow;
	};

	init();
}

module.exports = HackBrowserWindowManager;<|endoftext|>


<commit_before>
function getCookie(c_name)
{
    var i,x,y,ARRcookies=document.cookie.split(";");
    for (i=0;i<ARRcookies.length;i++)
    {
        x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
        y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
        x=x.replace(/^\s+|\s+$/g,"");
        if (x==c_name)
        {
            return unescape(y);
        }
    }
}

function setCookie(c_name,value,exdays)
{
    var exdate=new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
    document.cookie=c_name + "=" + c_value;
}

function checkCookie()
{
    firstName 			= getCookie("firstName");
    lastName  			= getCookie("lastName");
    organizationName	= getCookie("organizationName");
    userEmail			= getCookie("userEmail");
    userRole			= getCookie("userRole");
    userGrade			= getCookie("userGrade");
    userExperience		= getCookie("userExperience");

    if (firstName !=null && firstName != "" && lastName != null && lastName != "")
    {
        document.getElementById('userWelcome').innerHTML = "Welcome, " + firstName + " " + lastName + " (Not Me?)";
    }
    else
    {
        $("#userModal").modal('show');
    }
}

function clearCookie()
{
    setCookie("firstName",'',1);
    setCookie("lastName",'',1);
    setCookie("organizationName",'',1);
    setCookie("userEmail",'',1);
    setCookie("userRole",'',1);
    setCookie("userGrade",'',1);
    setCookie("userExperience",'',1);
    document.getElementById('userWelcome').innerHTML = "You are not logged in.";
    checkCookie();
}
<commit_msg>Removing the label<commit_after>
function getCookie(c_name)
{
    var i,x,y,ARRcookies=document.cookie.split(";");
    for (i=0;i<ARRcookies.length;i++)
    {
        x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
        y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
        x=x.replace(/^\s+|\s+$/g,"");
        if (x==c_name)
        {
            return unescape(y);
        }
    }
}

function setCookie(c_name,value,exdays)
{
    var exdate=new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
    document.cookie=c_name + "=" + c_value;
}

function checkCookie()
{
    firstName 			= getCookie("firstName");
    lastName  			= getCookie("lastName");
    organizationName	= getCookie("organizationName");
    userEmail			= getCookie("userEmail");
    userRole			= getCookie("userRole");
    userGrade			= getCookie("userGrade");
    userExperience		= getCookie("userExperience");

    if (firstName !=null && firstName != "" && lastName != null && lastName != "")
    {
        document.getElementById('userWelcome').innerHTML = "Welcome, " + firstName + " " + lastName + " (Not Me?)";
    }
    else
    {
        $("#userModal").modal('show');
    }
}

function clearCookie()
{
    setCookie("firstName",'',1);
    setCookie("lastName",'',1);
    setCookie("organizationName",'',1);
    setCookie("userEmail",'',1);
    setCookie("userRole",'',1);
    setCookie("userGrade",'',1);
    setCookie("userExperience",'',1);
    document.getElementById('userWelcome').innerHTML = "You are not logged in.";
    checkCookie();
}
<|endoftext|>


<commit_before>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-84354173-1', 'auto');
  ga('send', 'pageview');
<commit_msg>136: Adds pathname to GA call to record page being viewed<commit_after>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-84354173-1', 'auto');
  ga('send', 'pageview', location.pathname);
<|endoftext|>


<commit_before>/*jshint devel: true, browser: true, white: false, forin: true, plusplus: true, maxerr: 1000, indent: 2, jquery: true */
/*global _ */
(function() {
	'use strict';
	var vm = {
			board: {
				name: 'Tessel'
				, chips: buildChips()
				, switches: buildSwitches()
				, leds: buildLEDs()
				, pinGroups: buildPinGroups()
			}
		}
		, mapping = {
			  chips:     { create: function(o) { return new Chip    (o.data, o.parent); } }
			, switches:  { create: function(o) { return new Switch  (o.data, o.parent); } }
			, leds:      { create: function(o) { return new LED     (o.data, o.parent); } }
			, pins:      { create: function(o) { return new Pin     (o.data, o.parent); } }
			, pinGroups: { create: function(o) { return new PinGroup(o.data, o.parent); } }
			, board:     { create: function(o) { return new Board   (o.data, o.parent); } }
		}
	;

	function buildChips() {
		return _.map('Microcontroller|Flash|RAM|Wi-Fi'.split('|'), function(name, i) {
			return { name: name, description: name };
		});
	}

	function buildSwitches() {
		return _.map('Reset button|SimpleLink Wi-Fi SmartConfig button'.split('|'), function(desc, i) {
			var name = 'S' + (i + 1);
			return { name: name, description: desc || name };
		});
	}

	function buildLEDs() {
		return _.map('Power LED|Wi-Fi Connection LED|Wi-Fi Error LED|Debug LED 1|Debug LED 2'.split('|'), function(desc, i) {
			var name = 'D' + (i + 1);
			return { name: name, description: desc || name };
		});
	}

	function buildPinGroups() {
		var groups = _.map('GPIO Bank|A|B|C|D'.split('|'), function(name, i) {
				var inches = i ? '0.1' : '0.2'
					, mm = i ? '2.54' : '5.08'
					, pinNumFactor = !i * 2
					, pinNumOffset = !i * -1
				;
				return {
					name: name
					, description: name.length === 1 ? 'Module ' + name : name
					, numPins: name.length === 1 ? '10 pins (1x10)' : '20 pins (2x10)'
					, pins: buildDefaultPins(inches, mm, pinNumFactor, pinNumOffset)
				};
			})
			, gpio = groups[0]
		;
		gpio.pins = buildGPIOPins().concat(gpio.pins);
		return groups;
	}

	function buildPins(names, inches, mm, pinNumFactor, pinNumOffset) {
		pinNumFactor = pinNumFactor || 1;
		pinNumOffset = pinNumOffset || 0;
		return _.map(names.split('|'), function(name, i) {
			return {
				name: name
				, description: name
					.replace(/^A(\d)$/, 'ADC$1')
					.replace(/^G(\d)$/, 'GPIO$1')
				, inchesToEdge: inches || '0.1'
				, mmToEdge: mm || '2.54'
				, pinNum: (i + 1) * pinNumFactor + pinNumOffset
			};
		});
	}

	function buildDefaultPins(inches, mm, pinNumFactor, pinNumOffset) {
		return buildPins('GND|3V3|SCL|SDA|CLK|MISO|MOSI|G1|G2|G3', inches, mm, pinNumFactor, pinNumOffset);
	}

	function buildGPIOPins(inches, mm) {
		return buildPins('G6|G5|G4|A5|A4|A3|A2|A1|A0|5V', inches, mm, 2);
	}

	function init(data, parent) {
		var self = this;
		_.extend(self, ko.mapping.fromJS(data, mapping));
		self.ctor = ko.computed(function() {
			return _.objectTypeName(self);
		});
		self.typeCode = ko.computed(function() {
			return _.slugify(self.ctor());
		});
		self.code = ko.computed(function() {
			var name = _.isFunction(self.name) ? '-' + _.slugify(self.name()) : '';
			return self.typeCode() + name;
		});
		self.tooltipTmpl = ko.computed(function() { return '#' + self.code() + '-tooltip-tmpl, #' + self.typeCode() + '-tooltip-tmpl'; });
		self.tooltipTmplClass = ko.computed(function() { return self.code() + '-tooltip ' + self.typeCode() + '-tooltip'; });
		self.hovered = ko.observable(false);
	}

	function Chip() {
		var self = this;
		init.apply(self, arguments);
	}

	function Switch() {
		var self = this;
		init.apply(self, arguments);
	}

	function LED() {
		var self = this;
		init.apply(self, arguments);
	}

	function Pin(data, pinGroup) {
		var self = this;
		init.apply(self, arguments);
		self.tooltipTmpl = ko.computed(function() {
			var code = self.code()
				, pinGroupCode = 'pin-group-' + _.slugify(pinGroup.name())
			;
			return '#' + pinGroupCode + '-' + code + '-tooltip-tmpl, #' + code + '-tooltip-tmpl, #' + self.typeCode() + '-tooltip-tmpl';
		});
		self.fullName = ko.computed(function() {
			var name = self.name()
				, desc = self.description()
			;
			return name === desc ? name : name + ' (' + desc + ')';
		});
	}

	function PinGroup() {
		var self = this;
		init.apply(self, arguments);
		self.hasHoveredChild = ko.computed(function() {
			return !!self.pins.firstByProperty('hovered', true);
		});
	}

	function Board() {
		var self = this
			, w = 1977
			, h = 2360
		;
		init.apply(self, arguments);
		self.scale = ko.observable(0.24);
		self.rotation = ko.observable(0);
		self.width  = ko.computed(function() { return self.scale() * w + 'px'; });
		self.height = ko.computed(function() { return self.scale() * h + 'px'; });
		self.rotationDeg = ko.computed(function() { return self.rotation() + 'deg'; });
		self.transform = ko.computed(function() {
			return 'rotate(' + self.rotationDeg() + ')';
		});
	}

	function ViewModel() {
		var self = this;
		init.apply(self, arguments);
		self.ready = ko.observable(false);
	}

	window.vm = vm = new ViewModel(vm);

	$(function() {
		ko.applyBindings(vm);
		vm.ready(true);
	});
}());<commit_msg>Don't wait for document.ready to apply bindings<commit_after>/*jshint devel: true, browser: true, white: false, forin: true, plusplus: true, maxerr: 1000, indent: 2, jquery: true */
/*global _ */
(function() {
	'use strict';
	var vm = {
			board: {
				name: 'Tessel'
				, chips: buildChips()
				, switches: buildSwitches()
				, leds: buildLEDs()
				, pinGroups: buildPinGroups()
			}
		}
		, mapping = {
			  chips:     { create: function(o) { return new Chip    (o.data, o.parent); } }
			, switches:  { create: function(o) { return new Switch  (o.data, o.parent); } }
			, leds:      { create: function(o) { return new LED     (o.data, o.parent); } }
			, pins:      { create: function(o) { return new Pin     (o.data, o.parent); } }
			, pinGroups: { create: function(o) { return new PinGroup(o.data, o.parent); } }
			, board:     { create: function(o) { return new Board   (o.data, o.parent); } }
		}
	;

	function buildChips() {
		return _.map('Microcontroller|Flash|RAM|Wi-Fi'.split('|'), function(name, i) {
			return { name: name, description: name };
		});
	}

	function buildSwitches() {
		return _.map('Reset button|SimpleLink Wi-Fi SmartConfig button'.split('|'), function(desc, i) {
			var name = 'S' + (i + 1);
			return { name: name, description: desc || name };
		});
	}

	function buildLEDs() {
		return _.map('Power LED|Wi-Fi Connection LED|Wi-Fi Error LED|Debug LED 1|Debug LED 2'.split('|'), function(desc, i) {
			var name = 'D' + (i + 1);
			return { name: name, description: desc || name };
		});
	}

	function buildPinGroups() {
		var groups = _.map('GPIO Bank|A|B|C|D'.split('|'), function(name, i) {
				var inches = i ? '0.1' : '0.2'
					, mm = i ? '2.54' : '5.08'
					, pinNumFactor = !i * 2
					, pinNumOffset = !i * -1
				;
				return {
					name: name
					, description: name.length === 1 ? 'Module ' + name : name
					, numPins: name.length === 1 ? '10 pins (1x10)' : '20 pins (2x10)'
					, pins: buildDefaultPins(inches, mm, pinNumFactor, pinNumOffset)
				};
			})
			, gpio = groups[0]
		;
		gpio.pins = buildGPIOPins().concat(gpio.pins);
		return groups;
	}

	function buildPins(names, inches, mm, pinNumFactor, pinNumOffset) {
		pinNumFactor = pinNumFactor || 1;
		pinNumOffset = pinNumOffset || 0;
		return _.map(names.split('|'), function(name, i) {
			return {
				name: name
				, description: name
					.replace(/^A(\d)$/, 'ADC$1')
					.replace(/^G(\d)$/, 'GPIO$1')
				, inchesToEdge: inches || '0.1'
				, mmToEdge: mm || '2.54'
				, pinNum: (i + 1) * pinNumFactor + pinNumOffset
			};
		});
	}

	function buildDefaultPins(inches, mm, pinNumFactor, pinNumOffset) {
		return buildPins('GND|3V3|SCL|SDA|CLK|MISO|MOSI|G1|G2|G3', inches, mm, pinNumFactor, pinNumOffset);
	}

	function buildGPIOPins(inches, mm) {
		return buildPins('G6|G5|G4|A5|A4|A3|A2|A1|A0|5V', inches, mm, 2);
	}

	function init(data, parent) {
		var self = this;
		_.extend(self, ko.mapping.fromJS(data, mapping));
		self.ctor = ko.computed(function() {
			return _.objectTypeName(self);
		});
		self.typeCode = ko.computed(function() {
			return _.slugify(self.ctor());
		});
		self.code = ko.computed(function() {
			var name = _.isFunction(self.name) ? '-' + _.slugify(self.name()) : '';
			return self.typeCode() + name;
		});
		self.tooltipTmpl = ko.computed(function() { return '#' + self.code() + '-tooltip-tmpl, #' + self.typeCode() + '-tooltip-tmpl'; });
		self.tooltipTmplClass = ko.computed(function() { return self.code() + '-tooltip ' + self.typeCode() + '-tooltip'; });
		self.hovered = ko.observable(false);
	}

	function Chip() {
		var self = this;
		init.apply(self, arguments);
	}

	function Switch() {
		var self = this;
		init.apply(self, arguments);
	}

	function LED() {
		var self = this;
		init.apply(self, arguments);
	}

	function Pin(data, pinGroup) {
		var self = this;
		init.apply(self, arguments);
		self.tooltipTmpl = ko.computed(function() {
			var code = self.code()
				, pinGroupCode = 'pin-group-' + _.slugify(pinGroup.name())
			;
			return '#' + pinGroupCode + '-' + code + '-tooltip-tmpl, #' + code + '-tooltip-tmpl, #' + self.typeCode() + '-tooltip-tmpl';
		});
		self.fullName = ko.computed(function() {
			var name = self.name()
				, desc = self.description()
			;
			return name === desc ? name : name + ' (' + desc + ')';
		});
	}

	function PinGroup() {
		var self = this;
		init.apply(self, arguments);
		self.hasHoveredChild = ko.computed(function() {
			return !!self.pins.firstByProperty('hovered', true);
		});
	}

	function Board() {
		var self = this
			, w = 1977
			, h = 2360
		;
		init.apply(self, arguments);
		self.scale = ko.observable(0.24);
		self.rotation = ko.observable(0);
		self.width  = ko.computed(function() { return self.scale() * w + 'px'; });
		self.height = ko.computed(function() { return self.scale() * h + 'px'; });
		self.rotationDeg = ko.computed(function() { return self.rotation() + 'deg'; });
		self.transform = ko.computed(function() {
			return 'rotate(' + self.rotationDeg() + ')';
		});
	}

	function ViewModel() {
		var self = this;
		init.apply(self, arguments);
		self.ready = ko.observable(false);
	}

	window.vm = vm = new ViewModel(vm);
	ko.applyBindings(vm);
	vm.ready(true);
	$(function() {

	});
}());<|endoftext|>


<commit_before><commit_msg>修改点点点<commit_after><|endoftext|>


<commit_before>//for now, just run this in the JS console... will be improved upon later!

var data = {
  "date": $("[id$='wtDateTitle']").text().trim(),
  "name": $(".wod_wrapper > .wod_header").text().trim(),
  "comment": $(".wod_wrapper > .wod_comment").text().trim(),
  "components":[],
  "results_measure": "none", //this will get replaced later, after we have athlete results to parse
  "results":{}
};

//Loop over the components
$(".wod_wrapper > .ListRecords > .component_show_wrapper").each(function(i, componentEl){
  var $componentItems = $(componentEl).children();
  data.components.push({
    "name":$componentItems.filter(".component_name").text().trim(),
    "description":$componentItems.filter(".component_wrapper").text().trim()
  })
});

//Loop over the groups of male & female athletes
$("[id$='WhiteboardWrapper'] > table >tbody >tr> td").each(function(i, groupEl){
  var $thisGroup = $(groupEl);
  var title = $thisGroup.children(".header2").text().trim();
  var resultsData = [];
  var $results = $thisGroup.find(".CardWrapper");

  //WIthin the male/female groups, loop over the results from each athlete
  $results.each(function(ii, resultEl){
    //Select some elements that we will use in here
    var $thisResult = $(resultEl);
    var $details = $thisResult.children(".DetailsBanner");
    var $detailItems = $details.children();
    var $soc = $thisResult.find(".AthleteCardSocialLinks a");
    var $badges = $details.find(".BadgeWrapper");

    //The athlete data we are looking for

    //Parse the ranking to a real number
    var pRank = parseInt($thisResult.children(".RankingBanner").text().trim(), 10);

    //The name is split into two lines, replace line breaks with spaces
    var pName = $detailItems.eq(0).attr("title").replace("\n", " ");

    //Save the full image URL. If it's a relative URL, prefix it with the current page URL
    var pImg = $thisResult.find("img").attr("src");
    if(pImg.indexOf("http") !== 0){
      pImg = document.location.origin + pImg;
    }

    var pClass = $detailItems.filter(".DetailsClass").text().trim();
    var pPerf = $detailItems.filter(".DetailsPerformance").text().trim();
    var pPerfParts = {};

    var parsedTime = pPerf.match(/(\d+):(\d+)/);
    var parsedWeight = pPerf.match(/(?:(\d+)\sX\s(\d+) @ )?(\d+)\s(lbs?|kgs?)/i);
    var parsedReps = pPerf.match(/(\d+)(?:\s\+\s(\d+))?\s?([a-z\s]+)?/i);

    //We only need to set the results measure type for the first athlete
    if(ii === 0 && data.results_measure === "none"){
      if(parsedTime){
        data.results_measure = "time";
      }else if(parsedWeight){
        data.results_measure = "weight";
      }else if(parsedReps){
        data.results_measure = "reps";
      }else{
        data.results_measure = "none";
      }
    }

    if(parsedTime){
      data.results_measure = "time";
      var min = parseInt(parsedTime[1], 10);
      var sec = parseInt(parsedTime[2], 10);
      pPerfParts = {
        "time_minutes": min,
        "time_seconds": sec,
        "total_seconds": sec + (min > 0 ? min*60 : 0)
      };
    }else if(parsedWeight){
      data.results_measure = "weight";
      var rounds = parseInt(parsedWeight[1], 10);
      var reps = parseInt(parsedWeight[2], 10);
      var weight = parseInt(parsedWeight[3], 10);
      var units = parsedWeight[4];
      pPerfParts = {
        "weight": weight,
        "units": units,
      };

      if(!isNaN(rounds)){
        pPerfParts["rounds"] = rounds;
      }
      if(!isNaN(reps)){
        pPerfParts["reps"] = reps;
      }

    }else if(parsedReps){
      data.results_measure = "reps";
      var rounds = parseInt(parsedReps[1], 10);
      var reps = parseInt(parsedReps[2], 10);
      var units = parsedReps[3];
      if(!isNaN(rounds) && !isNaN(reps)){
        pPerfParts["rounds"] = rounds;
        pPerfParts["reps"] = reps;
      }else if(!isNaN(rounds) && isNaN(reps)){
        pPerfParts["reps"] = rounds;
      }

      if(units){
        pPerfParts["units"] = units;
      }
    }

    //Details about the performance are stored on the title (like breakdowns for each round in an AMRAP, etc.)
    //Split info on new lines into array parts
    var pPerfDetails = $detailItems.filter(".DetailsPerformance").children("span").attr("title").trim().split("\n");

    //If there is just one item and it's blank, reset this to an empty array
    if(pPerfDetails.length===1 && pPerfDetails[0]===""){
      pPerfDetails = [];
    }

    var pPerfComment = $detailItems.filter(".DetailsComment").text().trim();

    //If there are two badges, then it was a PR since the RX on/off badge is always there
    var pIsPR = $badges.length === 2;

    //If it was a PR, details about the PR are stored on the image title
    var pPrDetails = pIsPR ? $badges.first().children("img").attr("title").trim() : "";

    //If it was a PR, then the RX badge is the 2nd one, otherwise it's the first badge
    var $rxBadge = $badges.eq(pIsPR ? 1 : 0).children().first();

    //Depending on the class applied to this badge, we can determine if it was RX or not, or RX+
    var pIsRX = $rxBadge.hasClass("RxOnNoClick");
    var pIsRxPlus = $rxBadge.hasClass("RxPlusOnNoClick");

    //Parse out the number of likes from the text and convert it to a real number
    var pLikeCount = parseInt($soc.eq(0).text().trim().replace(/(un)?like\s.\s/i,""));

    //Parse out the number of comments from the text and convert it to a real number
    var pCommentCount = parseInt($soc.eq(1).children("span").eq(1).text().trim());

    //Add a new item to the array, one for each athlete
    resultsData.push({
  		"name": pName,
      "avatar":pImg,
      "rank":pRank,
      "class": pClass,
      "performance_string": pPerf,
      "performance_parts": pPerfParts,
      "performance_details":pPerfDetails,
      "comment": pPerfComment,
      "pr": pIsPR,
      "pr_details": pPrDetails,
      "rx": pIsRX,
      "rx_plus": pIsRxPlus,
      "social_likes": pLikeCount,
      "social_comments": pCommentCount
    });
  });

  //Add all of the results for each athlete gender group
  data.results[title]=resultsData;
});

console.log(JSON.stringify(data,null, 2));<commit_msg>Componentize into functions<commit_after>/* global $ */

//for now, just run this in the JS console... will be improved upon later!

function getWodComponents(){
  var components = [];
  //Loop over the components
  $(".wod_wrapper > .ListRecords > .component_show_wrapper").each(function(i, componentEl){
    var $componentItems = $(componentEl).children();
    components.push({
      "name":$componentItems.filter(".component_name").text().trim(),
      "description":$componentItems.filter(".component_wrapper").text().trim()
    })
  });
  return components;
}

function getAthleteRank($result){
  //Parse the ranking to a real number
  return parseInt($result.children(".RankingBanner").text().trim(), 10)
}
function getAthleteName($resultDetailItems){
  //The name is split into two lines, replace line breaks with spaces
  return $resultDetailItems.eq(0).attr("title").replace("\n", " ");
}
function getAthleteAvatar($result){
  //Save the full image URL. If it's a relative URL, prefix it with the current page URL
  var imgUrl = $result.find("img").attr("src");
  if(imgUrl.indexOf("http") !== 0){
    imgUrl = document.location.origin + imgUrl;
  }
  return imgUrl;
}
function getAthleteClass($resultDetailItems){
  return $resultDetailItems.filter(".DetailsClass").text().trim();
}
function getAthletePerformanceString($resultDetailItems){
  return $resultDetailItems.filter(".DetailsPerformance").text().trim();
}
function getAthletePerformanceDetails($resultDetailItems){
  //Details about the performance are stored on the title (like breakdowns for each round in an AMRAP, etc.)
  //Split info on new lines into array parts
  var details = $resultDetailItems.filter(".DetailsPerformance").children("span").attr("title").trim().split("\n");

  //If there is just one item and it's blank, reset this to an empty array
  if(details.length===1 && details[0]===""){
    details = [];
  }
  return details;
}
function setWodMeasure(athleteNum, parsedTime, parsedWeight, parsedReps){
  //We only need to set the results measure type for the first athlete
  if(athleteNum === 0 && data.results_measure === "none"){
    if(parsedTime){
      data.results_measure = "time";
    }else if(parsedWeight){
      data.results_measure = "weight";
    }else if(parsedReps){
      data.results_measure = "reps";
    }else{
      data.results_measure = "none";
    }
  }
}
function getAthletePerformanceParts(parsedTime, parsedWeight, parsedReps){
  var parts = {};
  if(parsedTime){
      data.results_measure = "time";
      var min = parseInt(parsedTime[1], 10);
      var sec = parseInt(parsedTime[2], 10);
      parts = {
        "time_minutes": min,
        "time_seconds": sec,
        "total_seconds": sec + (min > 0 ? min * 60 : 0)
      };
    }else if(parsedWeight){
      data.results_measure = "weight";
      var wRounds = parseInt(parsedWeight[1], 10);
      var wReps = parseInt(parsedWeight[2], 10);
      var wWeight = parseInt(parsedWeight[3], 10);
      var wUnits = parsedWeight[4];
      parts = {
        "weight": wWeight,
        "units": wUnits,
      };

      if(!isNaN(wRounds)){
        parts["rounds"] = wRounds;
      }
      if(!isNaN(wReps)){
        parts["reps"] = wReps;
      }

    }else if(parsedReps){
      data.results_measure = "reps";
      var rRounds = parseInt(parsedReps[1], 10);
      var rReps = parseInt(parsedReps[2], 10);
      var rUnits = parsedReps[3];
      if(!isNaN(rRounds) && !isNaN(rReps)){
        parts["rounds"] = rRounds;
        parts["reps"] = rReps;
      }else if(!isNaN(rRounds) && isNaN(rReps)){
        parts["reps"] = rRounds;
      }

      if(rUnits){
        parts["units"] = rUnits;
      }
    }
    return parts;
}
function getAthleteBadges($resultDetails){
  var $badges = $resultDetails.find(".BadgeWrapper");
  //If there are two badges, then it was a PR since the RX on/off badge is always there
  var isPR = $badges.length === 2;

  //If it was a PR, details about the PR are stored on the image title
  var prDetails = isPR ? $badges.first().children("img").attr("title").trim() : "";

  //If it was a PR, then the RX badge is the 2nd one, otherwise it's the first badge
  var $rxBadge = $badges.eq(isPR ? 1 : 0).children().first();

  //Depending on the class applied to this badge, we can determine if it was RX or not, or RX+
  var isRX = $rxBadge.hasClass("RxOnNoClick");
  var isRxPlus = $rxBadge.hasClass("RxPlusOnNoClick");

  return {
    "isPr": isPR,
    "prDetails":prDetails,
    "isRx": isRX,
    "isRxPlus": isRxPlus
  }
}
function getAthleteSocialCounts($result){
  var $soc = $result.find(".AthleteCardSocialLinks a");
  //Parse out the number of likes from the text and convert it to a real number
  var likeCount = parseInt($soc.eq(0).text().trim().replace(/(un)?like\s.\s/i,""));

  //Parse out the number of comments from the text and convert it to a real number
  var commentCount = parseInt($soc.eq(1).children("span").eq(1).text().trim());

  return{
    "likes": likeCount,
    "comments": commentCount
  }
}

function getAthleteResult(athleteNum, elementToParse){
  //Select some elements that we will use in here
  var $thisResult = $(elementToParse);
  var $details = $thisResult.children(".DetailsBanner");
  var $detailItems = $details.children();

  var pRank = getAthleteRank($thisResult);
  var pName = getAthleteName($detailItems);
  var pImg = getAthleteAvatar($thisResult);
  var pClass = getAthleteClass($detailItems);
  var pPerf = getAthletePerformanceString($detailItems);
  var pPerfDetails = getAthletePerformanceDetails($detailItems);
  var pPerfComment = $detailItems.filter(".DetailsComment").text().trim();

  //Run some regex's against the performance string
  var parsedTime = pPerf.match(/(\d+):(\d+)/);
  var parsedWeight = pPerf.match(/(?:(\d+)\sX\s(\d+) @ )?(\d+)\s(lbs?|kgs?)/i);
  var parsedReps = pPerf.match(/(\d+)(?:\s\+\s(\d+))?\s?([a-z\s]+)?/i);

  //determine the measure type for the entire WOD
  setWodMeasure(athleteNum, parsedTime, parsedWeight, parsedReps);

  //Now back to the athlete, parse the performance parts
  var pPerfParts = getAthletePerformanceParts(parsedTime, parsedWeight, parsedReps);
  var badges = getAthleteBadges($details);
  var social = getAthleteSocialCounts($thisResult);

  return {
    "name": pName,
    "avatar":pImg,
    "rank":pRank,
    "class": pClass,
    "performance_string": pPerf,
    "performance_parts": pPerfParts,
    "performance_details":pPerfDetails,
    "comment": pPerfComment,
    "pr": badges.isPr,
    "pr_details": badges.prDetails,
    "rx": badges.isRx,
    "rx_plus": badges.isRxPlus,
    "social_likes": social.likes,
    "social_comments": social.comments
  };
}

function getAllAthleteResults(){
  var results = {};

  //Loop over the groups of male & female athletes
  $("[id$='WhiteboardWrapper'] > table >tbody >tr> td").each(function(i, groupEl){
    var $thisGroup = $(groupEl);
    var title = $thisGroup.children(".header2").text().trim();
    var resultsData = [];
    var $results = $thisGroup.find(".CardWrapper");

    //WIthin the male/female groups, loop over the results from each athlete
    $results.each(function(ii, resultEl){
      //Add a new item to the array, one for each athlete
      resultsData.push(getAthleteResult(ii, resultEl));
    });

    //Add all of the results for each athlete gender group
    results[title]=resultsData;
  });

  return results;
}

var data = {
  "date": $("[id$='wtDateTitle']").text().trim(),
  "name": $(".wod_wrapper > .wod_header").text().trim(),
  "comment": $(".wod_wrapper > .wod_comment").text().trim(),
  "components": getWodComponents(),
  "results_measure": "none", //this will get replaced later, after we have athlete results to parse
  "results": {}
};
data.results = getAllAthleteResults();

console.log(JSON.stringify(data,null, 2));<|endoftext|>