<commit_before>var SRC = 'src';
var ES5 = 'es5';
var CLIENT = __dirname + '/public';

var UI_SCRIPTS = [
    'common/ModelInterface',
    'common/UIControllerInterface',
    'logger/DefaultLogger',
    'logger/LoggerInterface',
    'ticTacToe/TicTacToeUIController',
    'ticTacToe/TicTacToeUIControllerInterface',
    'index'
];

var browserify = require('browserify');
var buffer = require('vinyl-buffer');
var bunyan = require('bunyan');
var concatCss = require('gulp-concat-css');
var del = require('del');
var gulp = require('gulp');
var gulpUtil = require('gulp-util');
var nodemon = require('gulp-nodemon');
var runSeq = require('run-sequence');
var source = require('vinyl-source-stream');
var sourceMaps = require('gulp-sourcemaps');
var spawn = require('child_process').spawn;
var typeScript = require('gulp-typescript');
var typeScriptify = require('tsify');
var typeScriptLint = require('gulp-tslint');
var uglify = require('gulp-uglify');

var environments = require('gulp-environments');
var development = environments.development;
var staging = environments.make('staging');
var production = environments.production;

var node;

function build(callback) {
    console.log('Building...');
    return runSeq(
            'clean-fast',
            ['transpile-ts', 'transcribe-html', 'transcribe-images', 'transcribe-css'],
            'transcribe-ui-js',
            callback
            );
}

function stop() {
    console.log('Stopping...');
    if (node){
        node.kill();
    }
}

function transpile() {
    console.log('Transpiling...');
    var tsProject = typeScript.createProject('src/tsconfig.json');
    return tsProject
            .src()
            .pipe(typeScript(tsProject))
            .js.pipe(gulp.dest(ES5));
}

function transcribeCss() {
    console.log('Transcribing CSS...');
    return gulp.src([SRC + '/**/*.css'])
            .pipe(concatCss('index.css'))
            .pipe(gulp.dest(CLIENT));
}

function transcribeHtml() {
    console.log('Transcribing HTML...');
    return gulp.src([SRC + '/**/*.html'])
            .pipe(gulp.dest(CLIENT));
}

function transcribeImages () {
    console.log('Transcribing Images...');
    return gulp.src([SRC + '/**/*.png'])
            .pipe(gulp.dest(CLIENT));
}

function transcribeUiJs() {
    console.log('Transcribing UI JavaScript...');
    function pointTo(scripts) {
        return scripts.map(function (script) {
            return ES5 + '/' + script + '.js';
        });
    }

    return browserify({
        basedir: '.',
        debug: true,
        entries: pointTo(UI_SCRIPTS),
        cache: {},
        packageCache: {}
    })
            //.transform(production('babelify'))
            .bundle()
            .pipe(source('index.js'))
            .pipe(buffer())
            .pipe(sourceMaps.init({loadMaps: true}))
            //.pipe(production(uglify()))
            .pipe(sourceMaps.write('./'))
            .pipe(gulp.dest(CLIENT));
}

function tslint() {
    console.log('Linting...');
    return gulp.src('./src/**/*.ts')
            .pipe(typeScriptLint({
                configuration: 'tslint.json',
                formatter: 'verbose'
            }))
            .pipe(typeScriptLint.report({
                emitError: false,
                summarizeFailureOutput: true
            }));
}

// Cleaning tasks --------------------------------------

gulp.task('clean-all', function (callback) {
    return del([ES5, CLIENT], callback);
});

gulp.task('clean-fast', ['clean-api', 'clean-ui-fast']);

gulp.task('clean-api', function (callback) {
    return del([ES5], callback);
});

gulp.task('clean-ui-all', function (callback) {
    return del([CLIENT], callback);
});

gulp.task('clean-ui-fast', function (callback) {
    return del([
        CLIENT + '/**/*', CLIENT + '/**/*.*',
        '!' + CLIENT,
        '!' + CLIENT + '/bower_components',
        '!' + CLIENT + '/bower_components/**'
    ], callback);
});

// Transformation tasks --------------------------------------

gulp.task('default', ['start']);

gulp.task('build', build);
gulp.task('build-api', ['transpile']);
gulp.task('build-ui', ['build']);

gulp.task('transpile', ['transpile-ts']);
gulp.task('transpile-ts', transpile);
gulp.task('transcribe-css', transcribeCss);
gulp.task('transcribe-html', transcribeHtml);
gulp.task('transcribe-images', transcribeImages);
gulp.task('transcribe-ui-js', transcribeUiJs);

// Misc tasks --------------------------------------

gulp.task('stop', stop);

gulp.task('start', function () {
    runSeq('stop', 'tslint', 'build', function () {
        node = nodemon({
            ext: 'css html js json sh ts',
            ignore: [ES5, CLIENT],
            legacyWatch: true,
            readable: true,
            script: ES5 + '/app.js',
            stdout: true
        });
        node.on('restart', function () {
                    gulpUtil.log('---------- Restarted! ----------');
                    tslint();
                    transpile();
                    transcribeCss();
                    transcribeHtml();
                    transcribeImages();
                    transcribeUiJs();
                });
    });
});

gulp.task('tslint', tslint);

process.on('exit', stop);
<commit_msg>fixed bug in gulpfile so restart works more reliably<commit_after>var SRC = 'src';
var ES5 = 'es5';
var CLIENT = __dirname + '/public';

var UI_SCRIPTS = [
    'common/ModelInterface',
    'common/UIControllerInterface',
    'logger/DefaultLogger',
    'logger/LoggerInterface',
    'ticTacToe/TicTacToeUIController',
    'ticTacToe/TicTacToeUIControllerInterface',
    'index'
];

var browserify = require('browserify');
var buffer = require('vinyl-buffer');
var bunyan = require('bunyan');
var concatCss = require('gulp-concat-css');
var del = require('del');
var gulp = require('gulp');
var gulpUtil = require('gulp-util');
var nodemon = require('gulp-nodemon');
var runSeq = require('run-sequence');
var source = require('vinyl-source-stream');
var sourceMaps = require('gulp-sourcemaps');
var spawn = require('child_process').spawn;
var typeScript = require('gulp-typescript');
var typeScriptify = require('tsify');
var typeScriptLint = require('gulp-tslint');
var uglify = require('gulp-uglify');

var environments = require('gulp-environments');
var development = environments.development;
var staging = environments.make('staging');
var production = environments.production;

var node;

function build(callback) {
    console.log('Building...');
    return runSeq(
            'clean-fast',
            ['transpile-ts', 'transcribe-html', 'transcribe-images', 'transcribe-css'],
            'transcribe-ui-js',
            callback
            );
}

function stop() {
    console.log('Stopping...');
    if (node){
        try {
            node && node.kill();
        } catch (error) {
            console.error('Failed to stop node: ' + error);
        }

    }
}

function transpile() {
    console.log('Transpiling...');
    var tsProject = typeScript.createProject('src/tsconfig.json');
    return tsProject
            .src()
            .pipe(typeScript(tsProject))
            .js.pipe(gulp.dest(ES5));
}

function transcribeCss() {
    console.log('Transcribing CSS...');
    return gulp.src([SRC + '/**/*.css'])
            .pipe(concatCss('index.css'))
            .pipe(gulp.dest(CLIENT));
}

function transcribeHtml() {
    console.log('Transcribing HTML...');
    return gulp.src([SRC + '/**/*.html'])
            .pipe(gulp.dest(CLIENT));
}

function transcribeImages () {
    console.log('Transcribing Images...');
    return gulp.src([SRC + '/**/*.png'])
            .pipe(gulp.dest(CLIENT));
}

function transcribeUiJs() {
    console.log('Transcribing UI JavaScript...');
    function pointTo(scripts) {
        return scripts.map(function (script) {
            return ES5 + '/' + script + '.js';
        });
    }

    return browserify({
        basedir: '.',
        debug: true,
        entries: pointTo(UI_SCRIPTS),
        cache: {},
        packageCache: {}
    })
            //.transform(production('babelify'))
            .bundle()
            .pipe(source('index.js'))
            .pipe(buffer())
            .pipe(sourceMaps.init({loadMaps: true}))
            //.pipe(production(uglify()))
            .pipe(sourceMaps.write('./'))
            .pipe(gulp.dest(CLIENT));
}

function tslint() {
    console.log('Linting...');
    return gulp.src('./src/**/*.ts')
            .pipe(typeScriptLint({
                configuration: 'tslint.json',
                formatter: 'verbose'
            }))
            .pipe(typeScriptLint.report({
                emitError: false,
                summarizeFailureOutput: true
            }));
}

// Cleaning tasks --------------------------------------

gulp.task('clean-all', function (callback) {
    return del([ES5, CLIENT], callback);
});

gulp.task('clean-fast', ['clean-api', 'clean-ui-fast']);

gulp.task('clean-api', function (callback) {
    return del([ES5], callback);
});

gulp.task('clean-ui-all', function (callback) {
    return del([CLIENT], callback);
});

gulp.task('clean-ui-fast', function (callback) {
    return del([
        CLIENT + '/**/*', CLIENT + '/**/*.*',
        '!' + CLIENT,
        '!' + CLIENT + '/bower_components',
        '!' + CLIENT + '/bower_components/**'
    ], callback);
});

// Transformation tasks --------------------------------------

gulp.task('default', ['start']);

gulp.task('build', build);
gulp.task('build-api', ['transpile']);
gulp.task('build-ui', ['build']);

gulp.task('transpile', ['transpile-ts']);
gulp.task('transpile-ts', transpile);
gulp.task('transcribe-css', transcribeCss);
gulp.task('transcribe-html', transcribeHtml);
gulp.task('transcribe-images', transcribeImages);
gulp.task('transcribe-ui-js', transcribeUiJs);

// Misc tasks --------------------------------------

gulp.task('stop', stop);

gulp.task('start', function () {
    runSeq('stop', 'tslint', 'build', function () {
        node = nodemon({
            ext: 'css html js json sh ts',
            ignore: [ES5, CLIENT],
            legacyWatch: true,
            readable: true,
            script: ES5 + '/app.js',
            stdout: true
        });
        node.on('restart', function () {
                    gulpUtil.log('---------- Restarted! ----------');
                    tslint();
                    transpile();
                    transcribeCss();
                    transcribeHtml();
                    transcribeImages();
                    transcribeUiJs();
                });
    });
});

gulp.task('tslint', tslint);

process.on('exit', stop);
<|endoftext|>


<commit_before>#!/usr/bin/env node

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

/**
 * @fileoverview Uploads Artifact Bundles for SNAPSHOT builds to Sonatype.
 *
 * Based on
 * https://support.sonatype.com/hc/en-us/articles/213465818-How-can-I-programmatically-upload-an-artifact-into-Nexus-2-
 *
 * It seems the only tool capable of uploading SNAPSHOTs in the way Sonatype
 * accepts is Maven. Flogger appears to have encountered the same limitation.
 * At least, Maven doesn't need to conduct the build of the SNAPSHOT files and
 * SNAPSHOTs don't require PGP signatures.
 *
 * Additionally, the section of that article on "Uploading Multiple Artifacts
 * at Once" is outdated; the steps do not work.
 *
 * While researching this, we discovered
 * https://github.com/graknlabs/bazel-distribution which may be a general
 * solution the problem of deploying from Bazel.
 *
 * See Also:
 *   https://maven.apache.org/plugins/maven-deploy-plugin/deploy-file-mojo.html
 */

const {execSync} = require('child_process');
const fs = require('fs');

const /** !Array<string> */ ARITFACT_TO_UPLOAD = [
  `closure-compiler`,
  `closure-compiler-unshaded`,
  `closure-compiler-externs`,
  `closure-compiler-main`,
  `closure-compiler-parent`,
];

const /** string */ SNAPSHOT_REPO_ID = 'snapshot-repo-id';

/** Main */
function main() {
  withTempDir((tmpPath) => {
    const settingsPath = `${tmpPath}/settings.xml`;
    fs.writeFileSync(
        settingsPath,
        lines(
            `<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'`,
            `          xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'`,
            `          xsi:schemaLocation='http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd'>`,
            `  <servers>`,
            `    <server>`,
            `      <id>${SNAPSHOT_REPO_ID}</id>`,
            `      <username>${getEnvOrThrow('SONATYPE_USERNAME')}</username>`,
            `      <password>${getEnvOrThrow('SONATYPE_PASSWORD')}</password>`,
            `    </server>`,
            `  </servers>`,
            `</settings>`,
            ),
        {flag: 'wx+'});

    for (const id of ARITFACT_TO_UPLOAD) {
      mavenDeploySnapshotFromBazel(settingsPath, id);
    }
  });
}

/**
 * @param {string} settingsPath
 * @param {string} artifactId
 */
function mavenDeploySnapshotFromBazel(settingsPath, artifactId) {
  withTempDir((tmpPath) => {
    execSync(
        `unzip bazel-bin/${artifactId}_bundle.jar -d ${tmpPath}`,
        {stdio: 'inherit'});
    execSync(
        spaces(
            'mvn',
            `  deploy:deploy-file`,
            `  --settings=${settingsPath}`,
            `  -DgeneratePom=false`,
            `  -DrepositoryId=${SNAPSHOT_REPO_ID}`,
            `  -Durl=https://oss.sonatype.org/content/repositories/snapshots/`,
            `  -DpomFile=${tmpPath}/pom.xml`,
            ...assembleJarArgs(artifactId, tmpPath),
            ),
        {stdio: 'inherit'});
  });
}

/**
 * Create a list of JAR arguments for `mvn deploy:deploy-file`.
 *
 * Example: -Dfile=/some/tmp/path/some-artifact-1.0-SNAPSHOT.jar
 *
 * @param {string} artifactId
 * @param {string} unpackPath
 * @return {!Array<string>}
 */
function assembleJarArgs(artifactId, unpackPath) {
  const baseJarPath = `${unpackPath}/${artifactId}-1.0-SNAPSHOT`;

  const mvnArgToJarName = new Map();
  for (const [arg, suffix] of MVN_ARG_TO_JAR_SUFFIX) {
    const fullJarPath = `${baseJarPath}${suffix}.jar`;
    if (fs.existsSync(fullJarPath)) {
      mvnArgToJarName.set(arg, fullJarPath);
    }
  }

  if (!mvnArgToJarName.get(D_FILE)) {
    // -Dfile is required but not all bundles have a JAR, so default to the POM.
    mvnArgToJarName.set(D_FILE, `${unpackPath}/pom.xml`);
  }

  return [...mvnArgToJarName].map(([arg, path]) => `${arg}=${path}`);
}

const /** string */ D_FILE = `-Dfile`;

const /** !Map<string, string> */ MVN_ARG_TO_JAR_SUFFIX = new Map([
  [D_FILE, ``],
  [`-Dsources`, `-sources`],
  [`-Djavadoc`, `-javadoc`],
]);

/**
 * @param {function(string)} callback
 */
function withTempDir(callback) {
  const tmpPath = String(execSync(`mktemp -d`)).trim();
  callback(tmpPath);
  execSync(`rm -R ${tmpPath}`);
}

/**
 * @param {...string} args
 * @return {string}
 */
function lines(...args) {
  return args.join('\n');
}

/**
 * @param {...string} args
 * @return {string}
 */
function spaces(...args) {
  return args.join(' ');
}

/**
 * @param {string} name
 * @return {string}
 */
function getEnvOrThrow(name) {
  const val = process.env[name];
  if (val === undefined) {
    throw new Error(`Environment variable not set: ${name}`);
  }
  return val;
}

main();
<commit_msg>Update license header.<commit_after>#!/usr/bin/env node

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

/**
 * @fileoverview Uploads Artifact Bundles for SNAPSHOT builds to Sonatype.
 *
 * Based on
 * https://support.sonatype.com/hc/en-us/articles/213465818-How-can-I-programmatically-upload-an-artifact-into-Nexus-2-
 *
 * It seems the only tool capable of uploading SNAPSHOTs in the way Sonatype
 * accepts is Maven. Flogger appears to have encountered the same limitation.
 * At least, Maven doesn't need to conduct the build of the SNAPSHOT files and
 * SNAPSHOTs don't require PGP signatures.
 *
 * Additionally, the section of that article on "Uploading Multiple Artifacts
 * at Once" is outdated; the steps do not work.
 *
 * While researching this, we discovered
 * https://github.com/graknlabs/bazel-distribution which may be a general
 * solution the problem of deploying from Bazel.
 *
 * See Also:
 *   https://maven.apache.org/plugins/maven-deploy-plugin/deploy-file-mojo.html
 */

const {execSync} = require('child_process');
const fs = require('fs');

const /** !Array<string> */ ARITFACT_TO_UPLOAD = [
  `closure-compiler`,
  `closure-compiler-unshaded`,
  `closure-compiler-externs`,
  `closure-compiler-main`,
  `closure-compiler-parent`,
];

const /** string */ SNAPSHOT_REPO_ID = 'snapshot-repo-id';

/** Main */
function main() {
  withTempDir((tmpPath) => {
    const settingsPath = `${tmpPath}/settings.xml`;
    fs.writeFileSync(
        settingsPath,
        lines(
            `<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0'`,
            `          xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'`,
            `          xsi:schemaLocation='http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd'>`,
            `  <servers>`,
            `    <server>`,
            `      <id>${SNAPSHOT_REPO_ID}</id>`,
            `      <username>${getEnvOrThrow('SONATYPE_USERNAME')}</username>`,
            `      <password>${getEnvOrThrow('SONATYPE_PASSWORD')}</password>`,
            `    </server>`,
            `  </servers>`,
            `</settings>`,
            ),
        {flag: 'wx+'});

    for (const id of ARITFACT_TO_UPLOAD) {
      mavenDeploySnapshotFromBazel(settingsPath, id);
    }
  });
}

/**
 * @param {string} settingsPath
 * @param {string} artifactId
 */
function mavenDeploySnapshotFromBazel(settingsPath, artifactId) {
  withTempDir((tmpPath) => {
    execSync(
        `unzip bazel-bin/${artifactId}_bundle.jar -d ${tmpPath}`,
        {stdio: 'inherit'});
    execSync(
        spaces(
            'mvn',
            `  deploy:deploy-file`,
            `  --settings=${settingsPath}`,
            `  -DgeneratePom=false`,
            `  -DrepositoryId=${SNAPSHOT_REPO_ID}`,
            `  -Durl=https://oss.sonatype.org/content/repositories/snapshots/`,
            `  -DpomFile=${tmpPath}/pom.xml`,
            ...assembleJarArgs(artifactId, tmpPath),
            ),
        {stdio: 'inherit'});
  });
}

/**
 * Create a list of JAR arguments for `mvn deploy:deploy-file`.
 *
 * Example: -Dfile=/some/tmp/path/some-artifact-1.0-SNAPSHOT.jar
 *
 * @param {string} artifactId
 * @param {string} unpackPath
 * @return {!Array<string>}
 */
function assembleJarArgs(artifactId, unpackPath) {
  const baseJarPath = `${unpackPath}/${artifactId}-1.0-SNAPSHOT`;

  const mvnArgToJarName = new Map();
  for (const [arg, suffix] of MVN_ARG_TO_JAR_SUFFIX) {
    const fullJarPath = `${baseJarPath}${suffix}.jar`;
    if (fs.existsSync(fullJarPath)) {
      mvnArgToJarName.set(arg, fullJarPath);
    }
  }

  if (!mvnArgToJarName.get(D_FILE)) {
    // -Dfile is required but not all bundles have a JAR, so default to the POM.
    mvnArgToJarName.set(D_FILE, `${unpackPath}/pom.xml`);
  }

  return [...mvnArgToJarName].map(([arg, path]) => `${arg}=${path}`);
}

const /** string */ D_FILE = `-Dfile`;

const /** !Map<string, string> */ MVN_ARG_TO_JAR_SUFFIX = new Map([
  [D_FILE, ``],
  [`-Dsources`, `-sources`],
  [`-Djavadoc`, `-javadoc`],
]);

/**
 * @param {function(string)} callback
 */
function withTempDir(callback) {
  const tmpPath = String(execSync(`mktemp -d`)).trim();
  callback(tmpPath);
  execSync(`rm -R ${tmpPath}`);
}

/**
 * @param {...string} args
 * @return {string}
 */
function lines(...args) {
  return args.join('\n');
}

/**
 * @param {...string} args
 * @return {string}
 */
function spaces(...args) {
  return args.join(' ');
}

/**
 * @param {string} name
 * @return {string}
 */
function getEnvOrThrow(name) {
  const val = process.env[name];
  if (val === undefined) {
    throw new Error(`Environment variable not set: ${name}`);
  }
  return val;
}

main();
<|endoftext|>


<commit_before>if (typeof (require) != 'undefined') {
	var loader = require('../../node_modules/Butterfly-js/dist/butterfly.min.js').loader;
}

/**
 * Entry point of the game, contains some part of the game engine and deals with
 * the different entities
 */
loader.executeModule('main',
'B', 'Canvas', 'Entities', 'Physics', 'Utils',
function (B, canvas, Entities, Physics, Utils) {
	var ball,
		tracks = [],
		// position of the mouse in the canvas, taking in account the scroll
		// and position of the canvas in the page
		mouseX,
		mouseY,
		fps = 30,
		urlParams = Utils.getUrlParams(window.location.search);

	const DEBUG = urlParams.debug || NO_DEBUG;
	console.log(DEBUG);

	// Init the view
	canvas.init(document.getElementById('game-canvas'));
	setInterval(updateAll, 1000 / fps);

	// Init the ball
	ball = new Entities.Ball(canvas.width() / 2, canvas.height() / 4, BALL_RADIUS, BALL_SPEED_X, BALL_SPEED_Y);
	// Position of the ball in the grid
	ball.setGridCoordinates(TRACK_SPACE_WIDTH, TRACK_SPACE_HEIGHT);

	/* Events */
	// Event to execute when the player wins
	B.Events.on('win', null, function () {
		resetTracks(tracks);
		ball.reset();
	});

	// Event to execute when the player loses
	B.Events.on('lost', null, function () {
		resetTracks(tracks);
	});

	// Event to execute when the mouse move
	B.Events.on('mouse-moved', null, function (mX, mY) {
		mouseX = mX;
		mouseY = mY;

		if (DEBUG) {
			ball.x = mouseX;
			ball.y = mouseY;
			ball.speedX = BALL_SPEED_X;
			ball.speedY = BALL_SPEED_Y * -1;
		}
	});
	/* End of Events */

	/*
	 * Create the tracks, The whole game is a grid and tracks are on the grid
	 * The tracks are organised on a rectangle of the grid started at the
	 * position (TRACK_GRID_START_COL, TRACK_GRID_START_COL) and ends at the
	 * position (TRACK_GRID_COL, TRACK_GRID_ROW)
	 * Each track is an instance of the class Entities.Track
	 */
	var col, row;
	for (row = TRACK_GRID_START_ROW; row < TRACK_GRID_ROW; row++ ) {
		for (col = TRACK_GRID_START_COL; col < TRACK_GRID_COL; col++ ) {
			tracks.push(new Entities.Track(
				// 5 is the initial left margin
				TRACK_SPACE_WIDTH * col,
				TRACK_SPACE_HEIGHT * row,
				TRACK_WIDTH,
				TRACK_HEIGHT,
				// @TODO remove destructable field
				true, Entities.Track.STATE_ACTIVE
			));
		}
	}

	// Set the number of remaining tracks to destroy
	var remainingTracks = TRACKS_NUMBER;

	// @TODO put that somewhere
	// Reset the tracks to the original state (all active)
	function resetTracks (tracks) {
		for (var b = 0; b < TRACKS_NUMBER; b++) {
			tracks[b].reset();
		}
	}

	/**
	 * Method to convert a pair of coordinates to the index of the cell in the
	 * grid the coordinates are in
	 */
	colRowToGridIndex = function (col, row) {
		return col - TRACK_GRID_START_COL +
			(TRACK_GRID_COL - TRACK_GRID_START_COL) * (row - TRACK_GRID_START_ROW);
	};

	/**
	 * Method to update the game state and the objects's position
	 */
	function moveAll () {
		// Update the ball position
		ball.updatePosition();
		ball.setGridCoordinates(TRACK_SPACE_WIDTH, TRACK_SPACE_HEIGHT);

		/* Ball and edges collision*/
		var wallBounded = Physics.sphereBounceAgainstInnerRectangle(ball, {x: 0, y: 0, w: canvas.width(), h: canvas.height()});
		if (wallBounded == 'down') {
			ball.reset();
			console.log('fire lost');
			B.Events.fire('lost');
		}
		/* End of Ball and edges collision*/

		/* Ball and active track collision */
		var track,
			trackSide,
			trackTopBot;

		track = tracks[colRowToGridIndex(
			ball.gridCellCol,
			ball.gridCellRow
		)];

		// if the ball is on an active track
		if (TRACK_GRID_START_COL <= ball.gridCellCol && ball.gridCellCol < TRACK_GRID_COL
			&& TRACK_GRID_START_COL <= ball.gridCellRow && ball.gridCellRow < TRACK_GRID_ROW
			&& track.state == Entities.Track.STATE_ACTIVE
		) {
			// track next to the current one, according to ball's old position
			trackSide = tracks[colRowToGridIndex(ball.oldGridCellCol, ball.gridCellRow)];
			trackSide = trackSide && trackSide.state == Entities.Track.STATE_ACTIVE && trackSide || undefined;

			// track under or above to the current one, according to ball's old position
			trackTopBot = tracks[colRowToGridIndex(ball.gridCellCol, ball.oldGridCellRow)];
			trackTopBot = trackTopBot && trackTopBot.state == Entities.Track.STATE_ACTIVE && trackTopBot || undefined;

			Physics.sphereBounceAgainstGridRectangle(ball, track, trackSide, trackTopBot);

			track.state = Entities.Track.STATE_INACTIVE;
			remainingTracks--;

			if (remainingTracks == 0) {
				console.log('win');
				B.Events.fire('win');
				return;
			}
		}
		/* End of Ball and active track collision */
	}

	/**
	 * Method to execute on each frame to update the game state and the
	 * objects's position and then redraw the canvas
	 */
	function updateAll () {
		moveAll();
		canvas.drawAll([ball, tracks]);

		if (DEBUG) {
			canvas.drawText('(' +
				Math.floor(mouseX / TRACK_SPACE_WIDTH) + ', ' +
				Math.floor(mouseY / TRACK_SPACE_HEIGHT) + ', ' +
				colRowToGridIndex(Math.floor(mouseX / TRACK_SPACE_WIDTH), Math.floor(mouseY / TRACK_SPACE_HEIGHT)) + ')', mouseX, mouseY, 'white');

			canvas.line([ball.x, ball.y], [ball.x + ball.speedX * 30, ball.y + ball.speedY * 30]);
		}
	}
});
<commit_msg>tracks initialized according to the map<commit_after>if (typeof (require) != 'undefined') {
	var loader = require('../../node_modules/Butterfly-js/dist/butterfly.min.js').loader;
}

/**
 * Entry point of the game, contains some part of the game engine and deals with
 * the different entities
 */
loader.executeModule('main',
'B', 'Canvas', 'Entities', 'Physics', 'Utils', 'Maps',
function (B, canvas, Entities, Physics, Utils, Maps) {
	var ball,
		tracks = [],
		// position of the mouse in the canvas, taking in account the scroll
		// and position of the canvas in the page
		mouseX,
		mouseY,
		fps = 30,
		urlParams = Utils.getUrlParams(window.location.search);

	const DEBUG = urlParams.debug || NO_DEBUG;
	console.log(DEBUG);

	// Init the view
	canvas.init(document.getElementById('game-canvas'));
	setInterval(updateAll, 1000 / fps);

	// Init the ball
	ball = new Entities.Ball(canvas.width() / 2, canvas.height() / 4, BALL_RADIUS, BALL_SPEED_X, BALL_SPEED_Y);
	// Position of the ball in the grid
	ball.setGridCoordinates(TRACK_SPACE_WIDTH, TRACK_SPACE_HEIGHT);

	/* Events */
	// Event to execute when the player wins
	B.Events.on('win', null, function () {
		resetTracks(tracks);
		ball.reset();
	});

	// Event to execute when the player loses
	B.Events.on('lost', null, function () {
		resetTracks(tracks);
	});

	// Event to execute when the mouse move
	B.Events.on('mouse-moved', null, function (mX, mY) {
		mouseX = mX;
		mouseY = mY;

		if (DEBUG) {
			ball.x = mouseX;
			ball.y = mouseY;
			ball.speedX = BALL_SPEED_X;
			ball.speedY = BALL_SPEED_Y * -1;
		}
	});
	/* End of Events */

	/*
	 * Create the tracks, The whole game is a grid and tracks are on the grid
	 * The tracks are organised on a rectangle of the grid started at the
	 * position (TRACK_GRID_START_COL, TRACK_GRID_START_COL) and ends at the
	 * position (TRACK_GRID_COL, TRACK_GRID_ROW)
	 * Each track is an instance of the class Entities.Track
	 */
	var col, row,
		trackWidth = canvas.width() / Maps[0].width,
		trackHeight = canvas.height() / Maps[0].height;
	for (row = 0; row < Maps[0].height; row++ ) {
		for (col = 0; col < Maps[0].width; col++ ) {
			tracks.push(new Entities.Track(
				// 5 is the initial left margin
				trackWidth * col, trackHeight * row,
				trackWidth, trackHeight,
				// @TODO remove destructable field
				true, Maps[0].map[row][col] ? Entities.Track.STATE_ACTIVE : Entities.Track.STATE_INACTIVE
			));
		}
	}

	// Set the number of remaining tracks to destroy
	var remainingTracks = TRACKS_NUMBER;

	// @TODO put that somewhere
	// Reset the tracks to the original state (all active)
	function resetTracks (tracks) {
		for (var b = 0; b < TRACKS_NUMBER; b++) {
			tracks[b].reset();
		}
	}

	/**
	 * Method to convert a pair of coordinates to the index of the cell in the
	 * grid the coordinates are in
	 */
	colRowToGridIndex = function (col, row) {
		return col - TRACK_GRID_START_COL +
			(TRACK_GRID_COL - TRACK_GRID_START_COL) * (row - TRACK_GRID_START_ROW);
	};

	/**
	 * Method to update the game state and the objects's position
	 */
	function moveAll () {
		// Update the ball position
		ball.updatePosition();
		ball.setGridCoordinates(TRACK_SPACE_WIDTH, TRACK_SPACE_HEIGHT);

		/* Ball and edges collision*/
		var wallBounded = Physics.sphereBounceAgainstInnerRectangle(ball, {x: 0, y: 0, w: canvas.width(), h: canvas.height()});
		if (wallBounded == 'down') {
			ball.reset();
			console.log('fire lost');
			B.Events.fire('lost');
		}
		/* End of Ball and edges collision*/

		/* Ball and active track collision */
		var track,
			trackSide,
			trackTopBot;

		track = tracks[colRowToGridIndex(
			ball.gridCellCol,
			ball.gridCellRow
		)];

		// if the ball is on an active track
		if (TRACK_GRID_START_COL <= ball.gridCellCol && ball.gridCellCol < TRACK_GRID_COL
			&& TRACK_GRID_START_COL <= ball.gridCellRow && ball.gridCellRow < TRACK_GRID_ROW
			&& track.state == Entities.Track.STATE_ACTIVE
		) {
			// track next to the current one, according to ball's old position
			trackSide = tracks[colRowToGridIndex(ball.oldGridCellCol, ball.gridCellRow)];
			trackSide = trackSide && trackSide.state == Entities.Track.STATE_ACTIVE && trackSide || undefined;

			// track under or above to the current one, according to ball's old position
			trackTopBot = tracks[colRowToGridIndex(ball.gridCellCol, ball.oldGridCellRow)];
			trackTopBot = trackTopBot && trackTopBot.state == Entities.Track.STATE_ACTIVE && trackTopBot || undefined;

			Physics.sphereBounceAgainstGridRectangle(ball, track, trackSide, trackTopBot);

			track.state = Entities.Track.STATE_INACTIVE;
			remainingTracks--;

			if (remainingTracks == 0) {
				console.log('win');
				B.Events.fire('win');
				return;
			}
		}
		/* End of Ball and active track collision */
	}

	/**
	 * Method to execute on each frame to update the game state and the
	 * objects's position and then redraw the canvas
	 */
	function updateAll () {
		moveAll();
		canvas.drawAll([ball, tracks]);

		if (DEBUG) {
			canvas.drawText('(' +
				Math.floor(mouseX / TRACK_SPACE_WIDTH) + ', ' +
				Math.floor(mouseY / TRACK_SPACE_HEIGHT) + ', ' +
				colRowToGridIndex(Math.floor(mouseX / TRACK_SPACE_WIDTH), Math.floor(mouseY / TRACK_SPACE_HEIGHT)) + ')', mouseX, mouseY, 'white');

			canvas.line([ball.x, ball.y], [ball.x + ball.speedX * 30, ball.y + ball.speedY * 30]);
		}
	}
});
<|endoftext|>


<commit_before>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');

var MRoomMemberTileController = require("../../../../src/controllers/molecules/MRoomMemberTile");

var ComponentBroker = require('../../../../src/ComponentBroker');
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');

module.exports = React.createClass({
    displayName: 'MRoomMemberTile',
    mixins: [MRoomMemberTileController],

    getMemberEventText: function() {
        var ev = this.props.mxEvent;
        // XXX: SYJS-16
        var senderName = ev.sender ? ev.sender.name : "Someone";
        switch (ev.getContent().membership) {
            case 'invite':
                return senderName + " invited " + ev.target.name + ".";
            case 'join':
                return senderName + " joined the room.";
            case 'leave':
                return senderName + " left the room.";
        }
    },

    render: function() {
        // XXX: for now, just cheekily borrow the css from message tile...
        return (

                <MessageTimestamp ts={this.props.mxEvent.getTs()} />

                    {this.getMemberEventText()}

        );
    },
});

<commit_msg>avatars for joins & parts<commit_after>/*
Copyright 2015 OpenMarket Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

'use strict';

var React = require('react');

var MRoomMemberTileController = require("../../../../src/controllers/molecules/MRoomMemberTile");

var MatrixClientPeg = require("../../../../src/MatrixClientPeg");
var ComponentBroker = require('../../../../src/ComponentBroker');
var MessageTimestamp = ComponentBroker.get('atoms/MessageTimestamp');

module.exports = React.createClass({
    displayName: 'MRoomMemberTile',
    mixins: [MRoomMemberTileController],

    getMemberEventText: function() {
        var ev = this.props.mxEvent;
        // XXX: SYJS-16
        var senderName = ev.sender ? ev.sender.name : "Someone";
        switch (ev.getContent().membership) {
            case 'invite':
                return senderName + " invited " + ev.target.name + ".";
            case 'join':
                return senderName + " joined the room.";
            case 'leave':
                return senderName + " left the room.";
        }
    },

    render: function() {
        // XXX: for now, just cheekily borrow the css from message tile...
        return (

                <MessageTimestamp ts={this.props.mxEvent.getTs()} />

                    {this.getMemberEventText()}

        );
    },
});

<|endoftext|>


<commit_before>const React = require("react");

const ContextMenu = React.createClass({
  componentWillMount() {
    this.hideContext = () => {
      this.props.onUpdate(false);
      window.removeEventListener("click", this.hideContext);
    };
  },
  componentWillUnmount() {
    window.removeEventListener("click", this.hideContext);
  },
  componentDidUpdate(prevProps) {
    if (this.props.visible && !prevProps.visible) {
      setTimeout(() => {
        window.addEventListener("click", this.hideContext, false);
      }, 0);
    }
  },
  render() {
    return (

        {this.props.options.map((option, i) => {
          if (option.type === "separator") {
            return (
);
          }
          if (option.type === "submenu") {
            return (

 {}}>
              {option.icon && <span className={`icon icon-spacer icon-${option.icon}`} />}
              {option.label}

              <ContextMenu
                visible={this.props.visible}
                onUpdate={this.props.onUpdate}
                onUserEvent={this.userEvent}
                options={option.options} />

);
          }
          return (
 {
              this.props.onUpdate(false);
              option.onClick();
              if (option.userEvent) {
                this.props.onUserEvent(option.userEvent);
              }
            }}>
            {option.icon && <span className={`icon icon-spacer icon-${option.icon}`} />}
            {option.iconURL && <span className={"icon icon-spacer"} style={{backgroundImage: `url(${option.iconURL})`}} />}
            {option.label}

);
        })}

    );
  }
});

ContextMenu.propTypes = {
  visible: React.PropTypes.bool,
  onUpdate: React.PropTypes.func.isRequired,
  onUserEvent: React.PropTypes.func,
  options: React.PropTypes.arrayOf(React.PropTypes.shape({
    type: React.PropTypes.string,
    label: React.PropTypes.string,
    icon: React.PropTypes.string,
    iconURL: React.PropTypes.string,
    onClick: React.PropTypes.func,
    userEvent: React.PropTypes.string,
    ref: React.PropTypes.string
  })).isRequired
};

module.exports = ContextMenu;
<commit_msg>fix (content): #1298 stop propagation on "Share" click event<commit_after>const React = require("react");

const ContextMenu = React.createClass({
  componentWillMount() {
    this.hideContext = () => {
      this.props.onUpdate(false);
      window.removeEventListener("click", this.hideContext);
    };
  },
  componentWillUnmount() {
    window.removeEventListener("click", this.hideContext);
  },
  componentDidUpdate(prevProps) {
    if (this.props.visible && !prevProps.visible) {
      setTimeout(() => {
        window.addEventListener("click", this.hideContext, false);
      }, 0);
    }
  },
  render() {
    return (

        {this.props.options.map((option, i) => {
          if (option.type === "separator") {
            return (
);
          }
          if (option.type === "submenu") {
            return (

 {
                ev.stopPropagation();
              }}>
              {option.icon && <span className={`icon icon-spacer icon-${option.icon}`} />}
              {option.label}

              <ContextMenu
                visible={this.props.visible}
                onUpdate={this.props.onUpdate}
                onUserEvent={this.userEvent}
                options={option.options} />

);
          }
          return (
 {
              this.props.onUpdate(false);
              option.onClick();
              if (option.userEvent) {
                this.props.onUserEvent(option.userEvent);
              }
            }}>
            {option.icon && <span className={`icon icon-spacer icon-${option.icon}`} />}
            {option.iconURL && <span className={"icon icon-spacer"} style={{backgroundImage: `url(${option.iconURL})`}} />}
            {option.label}

);
        })}

    );
  }
});

ContextMenu.propTypes = {
  visible: React.PropTypes.bool,
  onUpdate: React.PropTypes.func.isRequired,
  onUserEvent: React.PropTypes.func,
  options: React.PropTypes.arrayOf(React.PropTypes.shape({
    type: React.PropTypes.string,
    label: React.PropTypes.string,
    icon: React.PropTypes.string,
    iconURL: React.PropTypes.string,
    onClick: React.PropTypes.func,
    userEvent: React.PropTypes.string,
    ref: React.PropTypes.string
  })).isRequired
};

module.exports = ContextMenu;
<|endoftext|>


<commit_before>var player = {
    name: "anonymous",
    id: 0
};

function join_game () {
    var nf = document.getElementById("nameform");
    var ns = nf.value;
    if (ns) {
        player.name = ns;
    } else {
        player.name = "anon" + Math.floor((Math.random()*100)+1);
    }

    send_name(player.name);

    var block = document.getElementById("join");
    block.style.display=none;

    canvas.canvas.style.display=inline;

    return false;
}

var counter = 0;
var ctr = document.getElementById("countdown");

function counter_tick(seconds) {
    counter = seconds;
    ctr.innerHTML = counter;
    var iv = window.setInterval(function () {
            counter -= 1;
                ctr.innerHTML = counter;
            if (counter <= 0) {
                clearInterval(iv);
            }
    }, 1000);
}
<commit_msg>working player name submission<commit_after>var player = {
    name: "anonymous",
    id: 0
};

function join_game () {
    var nf = document.getElementById("nameform");
    var ns = nf.value;
    if (ns) {
        player.name = ns;
    } else {
        player.name = "anon" + Math.floor((Math.random()*100)+1);
    }

    send_name(player.name);

    var block = document.getElementById("join");
    block.style.display="none";

    canvas.canvas.style.display="inline";

    return false;
}

var counter = 0;
var ctr = document.getElementById("countdown");

function counter_tick(seconds) {
    counter = seconds;
    ctr.innerHTML = counter;
    var iv = window.setInterval(function () {
            counter -= 1;
                ctr.innerHTML = counter;
            if (counter <= 0) {
                clearInterval(iv);
            }
    }, 1000);
}
<|endoftext|>


<commit_before>
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');

/**
 * Module dependencies.
 */

var express = require('../../lib/express');

// Path to our public directory

var pub = __dirname + '/public';

// Auto-compile sass to css with "compiler"
// and then serve with connect's staticProvider

var app = express.createServer(
    express.compiler({ src: pub, enable: ['sass'] })
  , express.static(pub)
);

// Optional since express defaults to CWD/views

app.set('views', __dirname + '/views');

// Set our default template engine to "jade"
// which prevents the need for extensions
// (although you can still mix and match)
app.set('view engine', 'jade');

// Dummy users
var users = [
    { name: 'tj', email: 'tj@vision-media.ca' }
  , { name: 'ciaran', email: 'ciaranj@gmail.com' }
  , { name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
];

app.get('/', function(req, res){
  res.render('users', { users: users });
});

app.listen(3000);
console.log('Express app started on port 3000');
<commit_msg>more res.partial() examples<commit_after>
// Expose modules in ./support for demo purposes
require.paths.unshift(__dirname + '/../../support');

/**
 * Module dependencies.
 */

var express = require('../../lib/express');

// Path to our public directory

var pub = __dirname + '/public';

// Auto-compile sass to css with "compiler"
// and then serve with connect's staticProvider

var app = express.createServer(
    express.compiler({ src: pub, enable: ['sass'] })
  , express.static(pub)
);

// Optional since express defaults to CWD/views

app.set('views', __dirname + '/views');

// Set our default template engine to "jade"
// which prevents the need for extensions
// (although you can still mix and match)
app.set('view engine', 'jade');

// Dummy users
var users = [
    { name: 'tj', email: 'tj@vision-media.ca' }
  , { name: 'ciaran', email: 'ciaranj@gmail.com' }
  , { name: 'aaron', email: 'aaron.heckmann+github@gmail.com' }
];

app.get('/', function(req, res){
  res.render('users', { users: users });
});

app.get('/users', function(req, res){
  // we can use res.partial() as if
  // we were in a view, utilizing the same api
  // to render a fragment
  res.partial('users/user', users);
});

app.get('/user/:id', function(req, res){
  res.partial('users/user', users[req.params.id]);
});

app.listen(3000);
console.log('Express app started on port 3000');
<|endoftext|>


<commit_before>;(function() {

  var config = [

    // Stream Pins
    {
      placement: 'pinterest-stream-pins',
      selector: '.Pin.Module:not(.buffer-inserted, .hideHoverUI)',
      $button: $([
        '
',
          '',
            '',
          '',
        '
'
      ].join('')),
      insert: function(el) {
        var $actions = $(el);
        var $newActionItem = this.$button.clone();

        $actions
          .addClass('buffer-inserted');

        $actions
          .find('.pinImageActionButtonWrapper')
          .prepend($newActionItem);

        return $newActionItem;
      },
      getData: function(el) {
        var $img = $(el).find('.pinImg');
        var image = $img.attr('src');
        var pinLink;
        var pinIdParts;
        var pinId;
        var text;
        var $source;
        var source;
        var pageSource;
        var pinSourceRegex;
        var pinSourceMatches;

        // Grab text from image alt attribute
        text = $img.attr('alt');

        $source = $(el).find('.pinNavLink');

        // If we haven't found a link, try to get it from the page's source using
        // some regex magic
        if ($source.length === 0) {
          pinLink = $img.closest('a').attr('href');
          pinIdParts = pinLink.split('/');
          pinId = pinIdParts[pinIdParts.length - 2];

          pageSource = document.body.innerHTML;

          // That regex looks into inline JSON to find the "link" field in the pin object
          // that follows that pin's id field. If we ever need something more robust to make
          // sure we get the right "link" field, I've come up with this more involved regex:
          // /"id":\s*"22447698119542969"(?:,\s*"[^"]+":\s*(?:\d+(?:\.\d+)?|\w+|"[^"]+"|{(?:(?:{[^}]*})?|[^}])*}|\[[^]]*]))*,\s*"link":\s*("[^"]+")/i
          pinSourceRegex = RegExp('"id":\\s*"' + pinId + '".*?"link":\\s*("[^"]+")');

          pinSourceMatches = pageSource.match(pinSourceRegex);

          if (pinSourceMatches) source = JSON.parse(pinSourceMatches[1]);
        }

        // If we still haven't found a link, default to the domain name
        if ($source.length === 0 && !source) {
          $source = $(el).find('.pinDomain');
        }

        source = source || $source.attr('href') || $source.text();

        return {
          text: text,
          url: source,
          picture: getFullSizeImageUrl(image),
          placement: this.placement
        };
      }
    },
    // Single Pins
    {
      placement: 'pinterest-single-pin',
      selector: '.PinActionBar:not(.buffer-inserted)',
      $button: $([
        '
',
          '',
            '',
          '',
        '
'
      ].join('')),
      insert: function(el) {
        var $actions = $(el);
        var $newActionItem = this.$button.clone();

        $actions
          .addClass('buffer-inserted')
          .prepend($newActionItem);

        return $newActionItem;
      },
      getData: function(el) {
        var $img = $(el).parents('.closeupActionBarContainer')
                        .siblings('.closeupContainer')
                        .find('.pinImage');

        var image = $img.attr('src');
        // Grab text from image alt attribute
        var text = $img.attr('alt');

        var $source = $(el).children('.repinLike').find('.NavigateButton.website');
        var source = $source.attr('href');

        return {
          text: text,
          url: source,
          picture: getFullSizeImageUrl(image),
          placement: this.placement
        };
      }
    },
    // Pin Action Popup Pin
    {
      placement: 'pinterest-pin-popup',
      selector: '.SelectList li.item .BoardLabel:not(.buffer-inserted)',
      $button: $([
        '
',
          '',
            '',
          '',
        '
'
      ].join('')),
      insert: function(el) {
        var $actions = $(el);
        var $newActionItem = this.$button.clone();

        $actions
          .addClass('buffer-inserted')
          .prepend($newActionItem);

        return $newActionItem;
      },
      getData: function(el) {
        var $img = $(el).parents('.boardsWrapper').siblings('.pinContainer').find('.pinImg');

        var image = $img.attr('src');
        // Grab text from image alt attribute
        var text = $img.attr('alt');

        // Grab full url from page behind modal
        var $source = $(document).find('img[src="'+image+'"]').parents('.pinHolder').siblings('.pinNavLink');
        var source = $source.attr('href');

        if(!source){
          if(window.location.search){
            var params = window.location.search.split('&');

            var urlIndex = -1;
            for(var i = 0; i < params.length; i++){
              if(params[i].indexOf('url=') > -1){
                urlIndex = i;
                break;
              }
            }

            if(urlIndex > -1){
              source = decodeURIComponent(params[urlIndex].split("=")[1]);
            }
          }

        }

        return {
          text: text,
          url: source,
          picture: getFullSizeImageUrl(image),
          placement: this.placement
        };
      }
    }
  ];

  var insertButton = function(target) {
    $(target.selector).each(function(i, el) {
      var $button = target.insert(el);
      $button.on('click', function(e) {
        e.preventDefault();
        e.stopImmediatePropagation();
        xt.port.emit('buffer_click', target.getData(el));
      })
    });
  };

  var insertButtons = function() {
    config.forEach(insertButton);
  };

  var pinterestLoop = function() {
    insertButtons();
    setTimeout(pinterestLoop, 500);
  };

  var start = function() {

    // Add class for css scoping
    document.body.classList.add('buffer-pinterest');

    // Start the loop that will watch for new DOM elements
    pinterestLoop();
  };

  // Make sure we get the fullsize image
  // Example src: 'https://s-media-cache-ak0.pinimg.com/236x/55/1f/ac/551fac47c0dacff21f04012cb5c020cf.jpg'
  var getFullSizeImageUrl = function(url) {
    var urlParts = url.split('/');
    var isPinterestImage = urlParts[2].indexOf('pinimg.com') != -1;

    // Non-Pinterest images should already be full-size
    if (!isPinterestImage) return url;

    urlParts[3] = '736x'; // 736 is the Pinterest standard for fullsize images
    return urlParts.join('/');
  };

  // Wait for xt.options to be set
  ;(function check() {
    // If Pinterest is switched on, start the main loop
    if (!xt.options) {
      setTimeout(check, 0);
    } else if (xt.options['buffer.op.pinterest'] === 'pinterest' || typeof xt.options['buffer.op.pinterest'] == 'undefined') {
      start();
    } else {
      setTimeout(check, 2000);
    }
  }());

}());
<commit_msg>Update retrieval of Pinterest single pin source<commit_after>;(function() {

  var config = [

    // Stream Pins
    {
      placement: 'pinterest-stream-pins',
      selector: '.Pin.Module:not(.buffer-inserted, .hideHoverUI)',
      $button: $([
        '
',
          '',
            '',
          '',
        '
'
      ].join('')),
      insert: function(el) {
        var $actions = $(el);
        var $newActionItem = this.$button.clone();

        $actions
          .addClass('buffer-inserted');

        $actions
          .find('.pinImageActionButtonWrapper')
          .prepend($newActionItem);

        return $newActionItem;
      },
      getData: function(el) {
        var $img = $(el).find('.pinImg');
        var image = $img.attr('src');
        var pinLink;
        var pinIdParts;
        var pinId;
        var text;
        var $source;
        var source;
        var pageSource;
        var pinSourceRegex;
        var pinSourceMatches;

        // Grab text from image alt attribute
        text = $img.attr('alt');

        $source = $(el).find('.pinNavLink');

        // If we haven't found a link, try to get it from the page's source using
        // some regex magic
        if ($source.length === 0) {
          pinLink = $img.closest('a').attr('href');
          pinIdParts = pinLink.split('/');
          pinId = pinIdParts[pinIdParts.length - 2];

          pageSource = document.body.innerHTML;

          // That regex looks into inline JSON to find the "link" field in the pin object
          // that follows that pin's id field. If we ever need something more robust to make
          // sure we get the right "link" field, I've come up with this more involved regex:
          // /"id":\s*"22447698119542969"(?:,\s*"[^"]+":\s*(?:\d+(?:\.\d+)?|\w+|"[^"]+"|{(?:(?:{[^}]*})?|[^}])*}|\[[^]]*]))*,\s*"link":\s*("[^"]+")/i
          pinSourceRegex = RegExp('"id":\\s*"' + pinId + '".*?"link":\\s*("[^"]+")');

          pinSourceMatches = pageSource.match(pinSourceRegex);

          if (pinSourceMatches) source = JSON.parse(pinSourceMatches[1]);
        }

        // If we still haven't found a link, default to the domain name
        if ($source.length === 0 && !source) {
          $source = $(el).find('.pinDomain');
        }

        source = source || $source.attr('href') || $source.text();

        return {
          text: text,
          url: source,
          picture: getFullSizeImageUrl(image),
          placement: this.placement
        };
      }
    },
    // Single Pins
    {
      placement: 'pinterest-single-pin',
      selector: '.PinActionBar:not(.buffer-inserted)',
      $button: $([
        '
',
          '',
            '',
          '',
        '
'
      ].join('')),
      insert: function(el) {
        var $actions = $(el);
        var $newActionItem = this.$button.clone();

        $actions
          .addClass('buffer-inserted')
          .prepend($newActionItem);

        return $newActionItem;
      },
      getData: function(el) {
        var $img = $(el).parents('.closeupActionBarContainer')
                        .siblings('.closeupContainer')
                        .find('.pinImage');

        var image = $img.attr('src');
        // Grab text from image alt attribute
        var text = $img.attr('alt');

        var source = $(el).closest('.Closeup').find('.paddedPinLink').attr('href');

        return {
          text: text,
          url: source,
          picture: getFullSizeImageUrl(image),
          placement: this.placement
        };
      }
    },
    // Pin Action Popup Pin
    {
      placement: 'pinterest-pin-popup',
      selector: '.SelectList li.item .BoardLabel:not(.buffer-inserted)',
      $button: $([
        '
',
          '',
            '',
          '',
        '
'
      ].join('')),
      insert: function(el) {
        var $actions = $(el);
        var $newActionItem = this.$button.clone();

        $actions
          .addClass('buffer-inserted')
          .prepend($newActionItem);

        return $newActionItem;
      },
      getData: function(el) {
        var $img = $(el).parents('.boardsWrapper').siblings('.pinContainer').find('.pinImg');

        var image = $img.attr('src');
        // Grab text from image alt attribute
        var text = $img.attr('alt');

        // Grab full url from page behind modal
        var $source = $(document).find('img[src="'+image+'"]').parents('.pinHolder').siblings('.pinNavLink');
        var source = $source.attr('href');

        if(!source){
          if(window.location.search){
            var params = window.location.search.split('&');

            var urlIndex = -1;
            for(var i = 0; i < params.length; i++){
              if(params[i].indexOf('url=') > -1){
                urlIndex = i;
                break;
              }
            }

            if(urlIndex > -1){
              source = decodeURIComponent(params[urlIndex].split("=")[1]);
            }
          }

        }

        return {
          text: text,
          url: source,
          picture: getFullSizeImageUrl(image),
          placement: this.placement
        };
      }
    }
  ];

  var insertButton = function(target) {
    $(target.selector).each(function(i, el) {
      var $button = target.insert(el);
      $button.on('click', function(e) {
        e.preventDefault();
        e.stopImmediatePropagation();
        xt.port.emit('buffer_click', target.getData(el));
      })
    });
  };

  var insertButtons = function() {
    config.forEach(insertButton);
  };

  var pinterestLoop = function() {
    insertButtons();
    setTimeout(pinterestLoop, 500);
  };

  var start = function() {

    // Add class for css scoping
    document.body.classList.add('buffer-pinterest');

    // Start the loop that will watch for new DOM elements
    pinterestLoop();
  };

  // Make sure we get the fullsize image
  // Example src: 'https://s-media-cache-ak0.pinimg.com/236x/55/1f/ac/551fac47c0dacff21f04012cb5c020cf.jpg'
  var getFullSizeImageUrl = function(url) {
    var urlParts = url.split('/');
    var isPinterestImage = urlParts[2].indexOf('pinimg.com') != -1;

    // Non-Pinterest images should already be full-size
    if (!isPinterestImage) return url;

    urlParts[3] = '736x'; // 736 is the Pinterest standard for fullsize images
    return urlParts.join('/');
  };

  // Wait for xt.options to be set
  ;(function check() {
    // If Pinterest is switched on, start the main loop
    if (!xt.options) {
      setTimeout(check, 0);
    } else if (xt.options['buffer.op.pinterest'] === 'pinterest' || typeof xt.options['buffer.op.pinterest'] == 'undefined') {
      start();
    } else {
      setTimeout(check, 2000);
    }
  }());

}());
<|endoftext|>


<commit_before>/* eslint-disable init-declarations */
/* Copyright 2019 Tecnativa - Ernesto Tejeda
 * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
 */
odoo.define(
    "sale_layout_category_hide_detail.sale_layout_category_hide_detail",
    function (require) {
        "use strict";

        var sectionAndNoteListRenderer = require("account.section_and_note_backend");

        var SectionAndNoteListRenderer = {
            _renderBodyCell: function (record, node, index, options) {
                var $cell = this._super.apply(this, arguments);

                var options;
                var show_in_line_section;

                var isSection = record.data.display_type === "line_section";
                var isNote = record.data.display_type === "line_note";
                if (isSection || isNote) {
                    if (node.attrs.name in this.state.fieldsInfo.list) {
                        options = this.state.fieldsInfo.list[node.attrs.name].options;
                        show_in_line_section = options.show_in_line_section;
                    } else {
                        show_in_line_section = false;
                    }

                    if (show_in_line_section) {
                        return $cell.removeClass("o_hidden");
                    } else if (node.attrs.name === "name") {
                        var nbrColumns = this._getNumberOfCols();
                        if (this.handleField) {
                            nbrColumns--;
                        }
                        if (this.addTrashIcon) {
                            nbrColumns--;
                        }
                        nbrColumns -= this._getNumberOfLineSectionFields();
                        $cell.attr("colspan", nbrColumns);
                    }
                }
                return $cell;
            },
            _getNumberOfLineSectionFields: function () {
                var section_fields_count = 0;
                var self = this;
                this.columns.forEach(function (elem) {
                    var options;

                    if (elem.attrs.name in self.state.fieldsInfo.list) {
                        options = self.state.fieldsInfo.list[elem.attrs.name].options;
                        if (options.show_in_line_section) section_fields_count++;
                    }
                });
                return section_fields_count;
            },
            _getColumnWidth: function (column) {
                var res = this._super.apply(this, arguments);
                if (column.attrs.widget === "boolean_fa_icon") res = "15px";
                return res;
            },
            _renderHeaderCell: function (node) {
                var $th = this._super.apply(this, arguments);
                var options;
                var show_in_line_section;

                if (!(node.attrs.name in this.state.fieldsInfo.list)) {
                    return $th;
                }
                options = this.state.fieldsInfo.list[node.attrs.name].options;
                show_in_line_section = options.show_in_line_section;
                if (show_in_line_section) $th.text("").removeClass("o_column_sortable");
                return $th;
            },
        };

        sectionAndNoteListRenderer.include(SectionAndNoteListRenderer);
    }
);
<commit_msg>[IMP] sale_layout_category_hide_detail: Simplify code in functions to allow inheritability. TT38579<commit_after>/* eslint-disable init-declarations */
/* Copyright 2019 Tecnativa - Ernesto Tejeda
/* Copyright 2022 Tecnativa - Víctor Martínez
 * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
 */
odoo.define(
    "sale_layout_category_hide_detail.sale_layout_category_hide_detail",
    function (require) {
        "use strict";

        var sectionAndNoteListRenderer = require("account.section_and_note_backend");

        var SectionAndNoteListRenderer = {
            _getOptionValueFromField: function (name, option) {
                if (name in this.state.fieldsInfo.list) {
                    return this.state.fieldsInfo.list[name].options[option];
                }
                return false;
            },
            _allowRemoveClassHidden: function (name) {
                return this._getOptionValueFromField(name, "show_in_line_section");
            },
            _getColspanSectionName: function () {
                var nbrColumns = this._getNumberOfCols();
                if (this.handleField) {
                    nbrColumns--;
                }
                if (this.addTrashIcon) {
                    nbrColumns--;
                }
                nbrColumns -= this._getNumberOfLineSectionFields();
                return nbrColumns;
            },
            _renderBodyCell: function (record, node) {
                var $cell = this._super.apply(this, arguments);
                var isSection = record.data.display_type === "line_section";
                var isNote = record.data.display_type === "line_note";
                if (isSection || isNote) {
                    if (this._allowRemoveClassHidden(node.attrs.name)) {
                        return $cell.removeClass("o_hidden");
                    } else if (node.attrs.name === "name") {
                        $cell.attr("colspan", this._getColspanSectionName());
                    }
                }
                return $cell;
            },
            _getNumberOfLineSectionFields: function () {
                var section_fields_count = 0;
                var self = this;
                this.columns.forEach(function (elem) {
                    if (
                        self._getOptionValueFromField(
                            elem.attrs.name,
                            "show_in_line_section"
                        )
                    ) {
                        section_fields_count++;
                    }
                });
                return section_fields_count;
            },
            _getColumnWidth: function (column) {
                var res = this._super.apply(this, arguments);
                if (column.attrs.widget === "boolean_fa_icon") res = "15px";
                return res;
            },
            _renderHeaderCell: function (node) {
                var $th = this._super.apply(this, arguments);
                if (!(node.attrs.name in this.state.fieldsInfo.list)) {
                    return $th;
                }
                if (
                    this._getOptionValueFromField(
                        node.attrs.name,
                        "show_in_line_section"
                    )
                ) {
                    $th.text("").removeClass("o_column_sortable");
                }
                return $th;
            },
        };

        sectionAndNoteListRenderer.include(SectionAndNoteListRenderer);
    }
);
<|endoftext|>


<commit_before>/*jslint node:true */

/*
 * examples/node-discovery.js
 * https://github.com/101100/xbee-rx
 *
 * Example that performs node discovery.
 *
 * Copyright (c) 2015-2016 Jason Heard
 * Licensed under the MIT license.
 */

"use strict";

var R = require('ramda');
var rx = require('rx');
var xbee_api = require('xbee-api');
var xbeeRx = require('../lib/xbee-rx.js');

var xbee = xbeeRx({
    serialport: '/dev/ttyUSB0',
    serialportOptions: {
        baudrate: 57600
    },
    module: "ZigBee",
    // turn on debugging to see what the library is doing
    debug: false
});

xbee
    .localCommand({
        command: 'NT',
    })
    .flatMap(function (ntResult) {
        // Fulfill promise when NT expires
        // NT is 1/10 seconds
        var timeoutMs = ntResult.readInt16BE(0) * 100;
        console.log("Got node discovery timeout:", timeoutMs, "ms");
        xbee.localCommand({ command: 'ND' }).subscribe();
        return xbee
            .allPackets
            .takeUntil(rx.Observable.timer(timeoutMs + 1000))
            .where(R.propEq("type", xbee_api.constants.FRAME_TYPE.AT_COMMAND_RESPONSE))
            .where(R.propEq("command", "ND"))
            .pluck("nodeIdentification");
    })
    .subscribe(function (nodeIdentification) {
        console.log("Found node:\n", nodeIdentification);
    }, function (e) {
        console.log("Command failed:\n", e);
        xbee.close();
    }, function () {
        console.log("Timeout reached; done finding nodes");
        xbee.close();
    });

<commit_msg>Update node-discovery example<commit_after>/*jslint node:true */

/*
 * examples/node-discovery.js
 * https://github.com/101100/xbee-rx
 *
 * Example that performs node discovery.
 *
 * Copyright (c) 2015-2016 Jason Heard
 * Licensed under the MIT license.
 */

"use strict";

var R = require('ramda');
var rx = require('rx');
var xbee_api = require('xbee-api');
var xbeeRx = require('../lib/xbee-rx.js');

var xbee = xbeeRx({
    serialport: '/dev/ttyUSB0',
    serialportOptions: {
        baudrate: 57600
    },
    module: "ZigBee",
    // turn on debugging to see what the library is doing
    debug: false
});

// we want to ignore the command stream result as well as any error (for no
// reply resulting from no found nodes)
var nodeDiscoveryCommandStream = xbee
    .localCommand({ command: 'ND' })
    .catch(rx.Observable.empty())
    .ignoreElements();

var nodeDiscoveryRepliesStream = xbee
    .allPackets
    .where(R.propEq("type", xbee_api.constants.FRAME_TYPE.AT_COMMAND_RESPONSE))
    .where(R.propEq("command", "ND"))
    .pluck("nodeIdentification");

xbee
    .localCommand({
        command: 'NT',
    })
    .flatMap(function (ntResult) {
        // Fulfill promise when NT expires
        // NT is 1/10 seconds
        var timeoutMs = ntResult.readInt16BE(0) * 100;
        console.log("Got node discovery timeout:", timeoutMs, "ms");
        return nodeDiscoveryRepliesStream
            .takeUntil(rx.Observable.timer(timeoutMs + 1000))
            .merge( nodeDiscoveryCommandStream);
    })
    .subscribe(function (nodeIdentification) {
        console.log("Found node:\n", nodeIdentification);
    }, function (e) {
        console.log("Command failed:\n", e);
        xbee.close();
    }, function () {
        console.log("Timeout reached; done finding nodes");
        xbee.close();
    });

<|endoftext|>