<commit_before>'use strict';

const bodyParser = require('body-parser');
const express = require('express');
const request = require('request');
var path = require('path');
var nus = require( path.resolve( __dirname, "./nusmod.js" ) );

// Webserver parameter
const PORT = process.env.PORT || 8445;

// Messenger API parameters
const FB_PAGE_ID = process.env.FB_PAGE_ID;
if (!FB_PAGE_ID) {
  throw new Error('missing FB_PAGE_ID');
}
const FB_PAGE_TOKEN = process.env.FB_PAGE_TOKEN;
if (!FB_PAGE_TOKEN) {
  throw new Error('missing FB_PAGE_TOKEN');
}
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;

const sessions = {};
const findOrCreateSession = (fbid) => {
  let sessionId;
  // Let's see if we already have a session for the user fbid
  Object.keys(sessions).forEach(k => {
    if (sessions[k].fbid === fbid) {
      // Yep, got it!
      sessionId = k;
    }
  });
  if (!sessionId) {
    // No session found for user fbid, let's create a new one
    sessionId = new Date().toISOString();
    sessions[sessionId] = {fbid: fbid, context: {}};
  }
  return sessionId;
};

// Messenger API specific code

// See the Send API reference
// https://developers.facebook.com/docs/messenger-platform/send-api-reference
const fbReq = request.defaults({
  uri: 'https://graph.facebook.com/me/messages',
  method: 'POST',
  json: true,
  qs: { access_token: FB_PAGE_TOKEN },
  headers: {'Content-Type': 'application/json'},
});

const fbMessage = (recipientId, msg, cb) => {
  const opts = {
    form: {
      recipient: {
        id: recipientId,
      },
      message: {
        text: msg,
      },
    },
  };
  fbReq(opts, (err, resp, data) => {
    if (cb) {
      cb(err || data.error && data.error.message, data);
    }
  });
};

const fbMessageWithButtons = (recipientId, msg, cb) => {
  const opts = {
    form: {
      recipient: {
        id: recipientId,
      },
      message: {
        'attachment': {
        	'type': 'template',
        	'payload': {
        		'template_type': 'button',
        		'text': msg,
        		'buttons': [
        		{
        			'type': 'postback',
        			'title': 'Thank you',
        			'payload': 'yay'
        		},
        		{
        			'type': 'postback',
        			'title': 'Err no',
        			'payload': 'nay'
        		}
        		]
        	}
      },
    },
  },
};
  fbReq(opts, (err, resp, data) => {
    if (cb) {
      cb(err || data.error && data.error.message, data);
    }
  });
};

// See the Webhook reference
// https://developers.facebook.com/docs/messenger-platform/webhook-reference
// const getFirstMessagingEntry = (body) => {
//   const val = body.object == 'page' &&
//     body.entry &&
//     Array.isArray(body.entry) &&
//     body.entry.length > 0 &&
//     body.entry[0] &&
//     body.entry[0].id === FB_PAGE_ID &&
//     body.entry[0].messaging &&
//     Array.isArray(body.entry[0].messaging) &&
//     body.entry[0].messaging.length > 0 &&
//     body.entry[0].messaging[0]
//   ;
//   return val || null;
// };

// Starting our webserver and putting it all together
const app = express();
app.set('port', PORT);
app.listen(app.get('port'));
app.use(bodyParser.json());

// Webhook setup
app.get('/fb', (req, res) => {
  if (!FB_VERIFY_TOKEN) {
    throw new Error('missing FB_VERIFY_TOKEN');
  }
  if (req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === FB_VERIFY_TOKEN) {
    res.send(req.query['hub.challenge']);
  } else {
    res.sendStatus(400);
  }
});

// Message handler
app.post('/fb', (req, res) => {
  // Parsing the Messenger API response

  // const messaging = getFirstMessagingEntry(req.body);
  // if (messaging && messaging.message && messaging.recipient.id === FB_PAGE_ID) {
  //   // Yay! We got a new message!

  //   // We retrieve the Facebook user ID of the sender

  //   const sender = messaging.sender.id;

  //   // We retrieve the message content
  //   const msg = messaging.message.text.toUpperCase();
  //   const atts = messaging.message.attachments;
  //   // const payload = messaging.postback;

  //   if (atts) {
  //     // We received an attachment

  //     // Let's reply with an automatic message

  //     fbMessage(
  //       sender,
  //       'What a nice photo!'
  //     );
  //   } else if (msg) {

  //     execute(sender, msg);

  //   } else if (payload){
  //   	console.log('fine');
  //   }
  //   // } else if (payload) {

  //   //   // Handle a payload from this sender
  //   //   console.log(payload);
  //   // }
  // }

  let messaging_events = req.body.entry[0].messaging
	for (let i = 0; i < messaging_events.length; i++) {

		let event = req.body.entry[0].messaging[i]
		let sender = event.sender.id
		const sessionId = findOrCreateSession(sender);

		if (event.message && event.message.text) {
			let text = event.message.text.toUpperCase()
			// sessions[sessionId].context.parameter = execute(sender,text);
			// fbMessage(sender,sessions[sessionId].context.parameter);
			execute(sender,text);
		}
		if (event.postback) {
			if (event.postback.payload == 'yay' ) {
				fbMessage(sender,'It is my pleasure!');
				delete sessions[sessionId];
				console.log('session terminated');
			} else {
				fbMessage(sender,'Too bad!');
				delete sessions[sessionId];
				console.log('session terminated');
			}
		}
	}

  res.sendStatus(200);
});

//function to check text

var execute = (sender, msg ) => {

	var intent = nus.findKey(msg);
	var module = nus.findModule(msg);

	// var module = nusmod.findModule(msg);

	switch(intent){
		case "unsure":

		fbMessage(sender,"Do you wish to find class location or examination detail?");
		break;

		case "no intent":

		fbMessage(sender,"We are not ready for this sh*t");
		break;

		case "class":

		if (module !== -1) {
		var result = {};
		nus.getModule("2015-2016",module).then(function(res){
				result = Object.assign(result,res);
		}).catch(function(err){
			console.log(err);
		})
		// blah blah
		var messageToSend = "This is the message to send";
		fbMessage(sender,messageToSend);
		} else
			fbMessage(sender,'There is either no module indicated or we cannot find that module. Please indicate again');
		break;

		case "exam":

		if (module !== -1) {
			var result = {};

			nus.getModule(nus.findModule(msg)).then(function(res){
				// console.log(nus.findModule(msg));
				// console.log(res);
				result = Object.assign(result,res);
        // console.log(result);

        var messageToSend = "The time of examination of module " + nus.findModule(msg) + " is at " + nus.convertTime(result.ExamDate) + ", it will last for " + nus.convertPeriod(result.ExamDuration) +
        " and it will be held in " + result.ExamVenue + ".";
        console.log(nus.convertTime(result.ExamDate));
        fbMessageWithButtons(sender,messageToSend);
		// delete sessions[sessionId];
		console.log("Waiting for other messages");

		}).catch(function(err){
			console.log(err);

			var messageToSend = "Sorry we cannot find your module. Is it " + err + "?";
			fbMessage(sender,messageToSend);
			console.log("Waiting for other messages");

		});
		} else
			fbMessage(sender,'There is either no module indicated or we cannot find that module. Please indicate again');

	}
	// return intent || module;

}

<commit_msg>fixing bugsss<commit_after>'use strict';

const bodyParser = require('body-parser');
const express = require('express');
const request = require('request');
var path = require('path');
var nus = require( path.resolve( __dirname, "./nusmod.js" ) );

// Webserver parameter
const PORT = process.env.PORT || 8445;

// Messenger API parameters
const FB_PAGE_ID = process.env.FB_PAGE_ID;
if (!FB_PAGE_ID) {
  throw new Error('missing FB_PAGE_ID');
}
const FB_PAGE_TOKEN = process.env.FB_PAGE_TOKEN;
if (!FB_PAGE_TOKEN) {
  throw new Error('missing FB_PAGE_TOKEN');
}
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;

const sessions = {};
const findOrCreateSession = (fbid) => {
  let sessionId;
  // Let's see if we already have a session for the user fbid
  Object.keys(sessions).forEach(k => {
    if (sessions[k].fbid === fbid) {
      // Yep, got it!
      sessionId = k;
    }
  });
  if (!sessionId) {
    // No session found for user fbid, let's create a new one
    sessionId = new Date().toISOString();
    sessions[sessionId] = {fbid: fbid, context: {}};
  }
  return sessionId;
};

// Messenger API specific code

// See the Send API reference
// https://developers.facebook.com/docs/messenger-platform/send-api-reference
const fbReq = request.defaults({
  uri: 'https://graph.facebook.com/me/messages',
  method: 'POST',
  json: true,
  qs: { access_token: FB_PAGE_TOKEN },
  headers: {'Content-Type': 'application/json'},
});

const fbMessage = (recipientId, msg, cb) => {
  const opts = {
    form: {
      recipient: {
        id: recipientId,
      },
      message: {
        text: msg,
      },
    },
  };
  fbReq(opts, (err, resp, data) => {
    if (cb) {
      cb(err || data.error && data.error.message, data);
    }
  });
};

const fbMessageWithButtons = (recipientId, msg, cb) => {
  const opts = {
    form: {
      recipient: {
        id: recipientId,
      },
      message: {
        'attachment': {
        	'type': 'template',
        	'payload': {
        		'template_type': 'button',
        		'text': msg,
        		'buttons': [
        		{
        			'type': 'postback',
        			'title': 'Thank you',
        			'payload': 'yay'
        		},
        		{
        			'type': 'postback',
        			'title': 'Err no',
        			'payload': 'nay'
        		}
        		]
        	}
      },
    },
  },
};
  fbReq(opts, (err, resp, data) => {
    if (cb) {
      cb(err || data.error && data.error.message, data);
    }
  });
};

// See the Webhook reference
// https://developers.facebook.com/docs/messenger-platform/webhook-reference
// const getFirstMessagingEntry = (body) => {
//   const val = body.object == 'page' &&
//     body.entry &&
//     Array.isArray(body.entry) &&
//     body.entry.length > 0 &&
//     body.entry[0] &&
//     body.entry[0].id === FB_PAGE_ID &&
//     body.entry[0].messaging &&
//     Array.isArray(body.entry[0].messaging) &&
//     body.entry[0].messaging.length > 0 &&
//     body.entry[0].messaging[0]
//   ;
//   return val || null;
// };

// Starting our webserver and putting it all together
const app = express();
app.set('port', PORT);
app.listen(app.get('port'));
app.use(bodyParser.json());

// Webhook setup
app.get('/fb', (req, res) => {
  if (!FB_VERIFY_TOKEN) {
    throw new Error('missing FB_VERIFY_TOKEN');
  }
  if (req.query['hub.mode'] === 'subscribe' &&
    req.query['hub.verify_token'] === FB_VERIFY_TOKEN) {
    res.send(req.query['hub.challenge']);
  } else {
    res.sendStatus(400);
  }
});

// Message handler
app.post('/fb', (req, res) => {
  // Parsing the Messenger API response

  // const messaging = getFirstMessagingEntry(req.body);
  // if (messaging && messaging.message && messaging.recipient.id === FB_PAGE_ID) {
  //   // Yay! We got a new message!

  //   // We retrieve the Facebook user ID of the sender

  //   const sender = messaging.sender.id;

  //   // We retrieve the message content
  //   const msg = messaging.message.text.toUpperCase();
  //   const atts = messaging.message.attachments;
  //   // const payload = messaging.postback;

  //   if (atts) {
  //     // We received an attachment

  //     // Let's reply with an automatic message

  //     fbMessage(
  //       sender,
  //       'What a nice photo!'
  //     );
  //   } else if (msg) {

  //     execute(sender, msg);

  //   } else if (payload){
  //   	console.log('fine');
  //   }
  //   // } else if (payload) {

  //   //   // Handle a payload from this sender
  //   //   console.log(payload);
  //   // }
  // }

  let messaging_events = req.body.entry[0].messaging
	for (let i = 0; i < messaging_events.length; i++) {

		let event = req.body.entry[0].messaging[i]
		let sender = event.sender.id
		const sessionId = findOrCreateSession(sender);

		if (event.message && event.message.text) {
			let text = event.message.text.toUpperCase()
			// sessions[sessionId].context.parameter = execute(sender,text);
			// fbMessage(sender,sessions[sessionId].context.parameter);
			execute(sender,text);
		}
		if (event.postback) {
			if (event.postback.payload == 'yay' ) {
				fbMessage(sender,'It is my pleasure!');
				delete sessions[sessionId];
				console.log('session terminated');
			} else {
				fbMessage(sender,'Too bad!');
				delete sessions[sessionId];
				console.log('session terminated');
			}
		}
	}

  res.sendStatus(200);
});

//function to check text

var execute = (sender, msg ) => {

	var intent = nus.findKey(msg);
	var module = nus.findModule(msg);

	// var module = nusmod.findModule(msg);
  if (nus.findModule(msg) !== -1) {

	switch(intent){
		case "unsure":

		fbMessage(sender,"Do you wish to find class location or examination detail?");
		break;

		case "no intent":

		fbMessage(sender,"We are not ready for this sh*t");
		break;

		case "class":

		var result = {};
		nus.getModule("2015-2016",module).then(function(res){
				result = Object.assign(result,res);
		}).catch(function(err){
			console.log(err);
		})
		// blah blah
		var messageToSend = "This is the message to send";
		fbMessage(sender,messageToSend);

		break;

		case "exam":

			var result = {};

			nus.getModule(nus.findModule(msg)).then(function(res){
				// console.log(nus.findModule(msg));
				// console.log(res);
				result = Object.assign(result,res);
        // console.log(result);

        var messageToSend = "The time of examination of module " + nus.findModule(msg) + " is at " + nus.convertTime(result.ExamDate) + ", it will last for " + nus.convertPeriod(result.ExamDuration) +
        " and it will be held in " + result.ExamVenue + ".";
        console.log(nus.convertTime(result.ExamDate));
        fbMessageWithButtons(sender,messageToSend);
		// delete sessions[sessionId];
		console.log("Waiting for other messages");

		}).catch(function(err){
			console.log(err);

			var messageToSend = "Sorry we cannot find your module?";
			fbMessage(sender,messageToSend);
			console.log("Waiting for other messages");

		});

	}
} else
  fbMessage(sender,'There is either no module indicated or we cannot find your module. Please make sure you type in your module code correctly');
	// return intent || module;

}

<|endoftext|>


<commit_before>var BasicResizeHelpers = {

  listenForResize: function(listen) {
    if ( listen || listen == null ) {

      // Listen
      this._resizeHandler = this._onResize.bind(this);
      window.addEventListener('resize', this._resizeHandler);

      // Trigger resized handler so that element can do initial setup.
      this._onResize();

    } else {

      // Stop listening
      window.removeEventListener('resize', this._resizeHandler);
      this._resizeHandler = null;

    }
  },

  _onResize: function() {
    var previousSize = this._previousSize;
    var width = this.offsetWidth;
    var height = this.offsetHeight;
    var sizeChanged = ( previousSize == null ||
        width !== previousSize.width ||
        height !== previousSize.height );
    if (sizeChanged) {
      this._previousSize = {
        height: height,
        width: width
      };
      if (this.resized) {
        this.resized();
      }
    }
  }

};
<commit_msg>Add comments.<commit_after>/**
 * Basic helpers to let components track changes in their size in response to
 * window resize events.
 *
 * The standard DOM resize event is only available on the top-level window.
 * Elements that want to know if their own size changed in response to a window
 * resize often track the window resize event, but a naive event listener will
 * perform work even if the element's size was unaffected by the resize. These
 * helpers make it easier to only do work when a window resize actually changed
 * the element's size.
 */

var BasicResizeHelpers = {

  /**
   * Ask to start (or stop) listening to changes in the element's size that
   * occur in response to a window resize. If the element's size has changed,
   * an method called resized() will be invoked on the element.
   *
   * The resized() method will not be invoked if a window resize didn't actually
   * affect the size of the element in question.
   *
   * @method listenForResize
   * @param list True (the default) to start listening, false to stop
   */
  listenForResize: function(listen) {
    if ( listen || listen == null ) {

      // Listen
      this._resizeHandler = this._onResize.bind(this);
      window.addEventListener('resize', this._resizeHandler);

      // Trigger resized handler so that element can do initial setup.
      this._onResize();

    } else {

      // Stop listening
      window.removeEventListener('resize', this._resizeHandler);
      this._resizeHandler = null;

    }
  },

  _onResize: function() {
    var previousSize = this._previousSize;
    var width = this.offsetWidth;
    var height = this.offsetHeight;
    var sizeChanged = ( previousSize == null ||
        width !== previousSize.width ||
        height !== previousSize.height );
    if (sizeChanged) {
      this._previousSize = {
        height: height,
        width: width
      };
      if (this.resized) {
        this.resized();
      }
    }
  }

};
<|endoftext|>


<commit_before>var AddToDOM = require('../../../dom/AddToDOM');
var CanvasPool = require('../../../display/canvas/CanvasPool');
var Class = require('../../../utils/Class');
var Components = require('../../components');
var GameObject = require('../../GameObject');
var GetTextSize = require('../GetTextSize');
var GetValue = require('../../../utils/object/GetValue');
var RemoveFromDOM = require('../../../dom/RemoveFromDOM');
var TextRender = require('./TextRender');
var TextStyle = require('../TextStyle');

var Text = new Class({

    Extends: GameObject,

    Mixins: [
        Components.Alpha,
        Components.BlendMode,
        Components.Flip,
        Components.GetBounds,
        Components.Origin,
        Components.RenderTarget,
        Components.ScaleMode,
        Components.ScrollFactor,
        Components.Tint,
        Components.Transform,
        Components.Visible,
        TextRender
    ],

    initialize:

    function Text (scene, x, y, text, style)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = 0; }

        GameObject.call(this, scene, 'Text');

        this.setPosition(x, y);
        this.setOrigin(0, 0);

        /**
         * @property {HTMLCanvasElement} canvas - The canvas element that the text is rendered.
         */
        this.canvas = CanvasPool.create(this);

        /**
         * @property {HTMLCanvasElement} context - The context of the canvas element that the text is rendered to.
         */
        this.context = this.canvas.getContext('2d');

        this.style = new TextStyle(this, style);

        this.autoRound = true;

        /**
         * The Regular Expression that is used to split the text up into lines, in
         * multi-line text. By default this is `/(?:\r\n|\r|\n)/`.
         * You can change this RegExp to be anything else that you may need.
         * @property {Object} splitRegExp
         */
        this.splitRegExp = /(?:\r\n|\r|\n)/;

        //  This is populated in this.setText
        this.text = '';

        this.resolution = 1;

        /**
        * Specify a padding value which is added to the line width and height when calculating the Text size.
        * Allows you to add extra spacing if the browser is unable to accurately determine the true font dimensions.
        * @property {Phaser.Point} padding
        */
        this.padding = { left: 0, right: 0, top: 0, bottom: 0 };

        this.width = 1;
        this.height = 1;

        this.canvasTexture = null;
        this.dirty = false;

        this.initRTL();

        if (style && style.padding)
        {
            this.setPadding(style.padding);
        }

        this.setText(text);

        var _this = this;

        scene.sys.game.renderer.addContextRestoredCallback(function ()
        {
            _this.canvasTexture = null;
            _this.dirty = true;
        });
    },

    initRTL: function ()
    {
        if (!this.style.rtl)
        {
            return;
        }

        //  Here is where the crazy starts.
        //
        //  Due to browser implementation issues, you cannot fillText BiDi text to a canvas
        //  that is not part of the DOM. It just completely ignores the direction property.

        this.canvas.dir = 'rtl';

        //  Experimental atm, but one day ...
        this.context.direction = 'rtl';

        //  Add it to the DOM, but hidden within the parent canvas.
        this.canvas.style.display = 'none';

        AddToDOM(this.canvas, this.scene.sys.canvas);

        //  And finally we set the x origin
        this.originX = 1;
    },

    setText: function (value)
    {
        if (Array.isArray(value))
        {
            value = value.join('\n');
        }

        if (value !== this.text)
        {
            this.text = value.toString();

            this.updateText();
        }

        return this;
    },

    setStyle: function (style)
    {
        return this.style.setStyle(style);
    },

    setFont: function (font)
    {
        return this.style.setFont(font);
    },

    setFontFamily: function (family)
    {
        return this.style.setFontFamily(family);
    },

    setFontSize: function (size)
    {
        return this.style.setFontSize(size);
    },

    setFontStyle: function (style)
    {
        return this.style.setFontStyle(style);
    },

    setFixedSize: function (width, height)
    {
        return this.style.setFixedSize(width, height);
    },

    setBackgroundColor: function (color)
    {
        return this.style.setBackgroundColor(color);
    },

    setFill: function (color)
    {
        return this.style.setFill(color);
    },

    setColor: function (color)
    {
        return this.style.setColor(color);
    },

    setStroke: function (color, thickness)
    {
        return this.style.setStroke(color, thickness);
    },

    setShadow: function (x, y, color, blur, shadowStroke, shadowFill)
    {
        return this.style.setShadow(x, y, color, blur, shadowStroke, shadowFill);
    },

    setShadowOffset: function (x, y)
    {
        return this.style.setShadowOffset(x, y);
    },

    setShadowColor: function (color)
    {
        return this.style.setShadowColor(color);
    },

    setShadowBlur: function (blur)
    {
        return this.style.setShadowBlur(blur);
    },

    setShadowStroke: function (enabled)
    {
        return this.style.setShadowStroke(enabled);
    },

    setShadowFill: function (enabled)
    {
        return this.style.setShadowFill(enabled);
    },

    setAlign: function (align)
    {
        return this.style.setAlign(align);
    },

    //  'left' can be an object
    //  if only 'left' and 'top' are given they are treated as 'x' and 'y'
    setPadding: function (left, top, right, bottom)
    {
        if (typeof left === 'object')
        {
            var config = left;

            //  If they specify x and/or y this applies to all
            var x = GetValue(config, 'x', null);

            if (x !== null)
            {
                left = x;
                right = x;
            }
            else
            {
                left = GetValue(config, 'left', 0);
                right = GetValue(config, 'right', left);
            }

            var y = GetValue(config, 'y', null);

            if (y !== null)
            {
                top = y;
                bottom = y;
            }
            else
            {
                top = GetValue(config, 'top', 0);
                bottom = GetValue(config, 'bottom', top);
            }
        }
        else
        {
            if (left === undefined) { left = 0; }
            if (top === undefined) { top = left; }
            if (right === undefined) { right = left; }
            if (bottom === undefined) { bottom = top; }
        }

        this.padding.left = left;
        this.padding.top = top;
        this.padding.right = right;
        this.padding.bottom = bottom;

        return this.updateText();
    },

    setMaxLines: function (max)
    {
        return this.style.setMaxLines(max);
    },

    updateText: function ()
    {
        var canvas = this.canvas;
        var context = this.context;
        var style = this.style;
        var size = style.metrics;

        var outputText = this.text;

        // if (style.wordWrap)
        // {
        //     outputText = this.runWordWrap(this.text);
        // }

        //  Split text into lines
        var lines = outputText.split(this.splitRegExp);

        var textSize = GetTextSize(this, size, lines);

        var padding = this.padding;

        var w = textSize.width + padding.left + padding.right;
        var h = textSize.height + padding.top + padding.bottom;

        if (!style.fixedWidth)
        {
            this.width = w;
        }

        if (!style.fixedHeight)
        {
            this.height = h;
        }

        this.updateDisplayOrigin();

        w *= this.resolution;
        h *= this.resolution;

        if (canvas.width !== w || canvas.height !== h)
        {
            canvas.width = w;
            canvas.height = h;
        }
        else
        {
            context.clearRect(0, 0, w, h);
        }

        context.save();

        if (style.backgroundColor)
        {
            context.fillStyle = style.backgroundColor;
            context.fillRect(0, 0, w, h);
        }

        style.syncFont(canvas, context);

        context.textBaseline = 'alphabetic';

        //  Apply padding
        context.translate(padding.left, padding.top);

        var linePositionX;
        var linePositionY;

        //  Draw text line by line
        for (var i = 0; i < textSize.lines; i++)
        {
            linePositionX = style.strokeThickness / 2;
            linePositionY = (style.strokeThickness / 2 + i * textSize.lineHeight) + size.ascent;

            if (i > 0)
            {
                linePositionY += (textSize.lineSpacing * i);
            }

            if (style.rtl)
            {
                linePositionX = w - linePositionX;
            }
            else if (style.align === 'right')
            {
                linePositionX += textSize.width - textSize.lineWidths[i];
            }
            else if (style.align === 'center')
            {
                linePositionX += (textSize.width - textSize.lineWidths[i]) / 2;
            }

            if (this.autoRound)
            {
                linePositionX = Math.round(linePositionX);
                linePositionY = Math.round(linePositionY);
            }

            if (style.strokeThickness)
            {
                this.style.syncShadow(context, style.shadowStroke);

                context.strokeText(lines[i], linePositionX, linePositionY);
            }

            if (style.color)
            {
                this.style.syncShadow(context, style.shadowFill);

                context.fillText(lines[i], linePositionX, linePositionY);
            }
        }

        context.restore();

        this.dirty = true;

        return this;
    },

    getTextMetrics: function ()
    {
        return this.style.getTextMetrics();
    },

    toJSON: function ()
    {
        var out = Components.ToJSON(this);

        //  Extra Text data is added here

        var data = {
            autoRound: this.autoRound,
            text: this.text,
            style: this.style.toJSON(),
            resolution: this.resolution,
            padding: {
                left: this.padding.left,
                right: this.padding.right,
                top: this.padding.top,
                bottom: this.padding.bottom
            }
        };

        out.data = data;

        return out;
    },

    preDestroy: function ()
    {
        if (this.style.rtl)
        {
            RemoveFromDOM(this.canvas);
        }

        CanvasPool.remove(this.canvas);
    }

});

module.exports = Text;
<commit_msg>Port v2 text wrapping functions to Text<commit_after>var AddToDOM = require('../../../dom/AddToDOM');
var CanvasPool = require('../../../display/canvas/CanvasPool');
var Class = require('../../../utils/Class');
var Components = require('../../components');
var GameObject = require('../../GameObject');
var GetTextSize = require('../GetTextSize');
var GetValue = require('../../../utils/object/GetValue');
var RemoveFromDOM = require('../../../dom/RemoveFromDOM');
var TextRender = require('./TextRender');
var TextStyle = require('../TextStyle');

var Text = new Class({

    Extends: GameObject,

    Mixins: [
        Components.Alpha,
        Components.BlendMode,
        Components.Flip,
        Components.GetBounds,
        Components.Origin,
        Components.RenderTarget,
        Components.ScaleMode,
        Components.ScrollFactor,
        Components.Tint,
        Components.Transform,
        Components.Visible,
        TextRender
    ],

    initialize:

    function Text (scene, x, y, text, style)
    {
        if (x === undefined) { x = 0; }
        if (y === undefined) { y = 0; }

        GameObject.call(this, scene, 'Text');

        this.setPosition(x, y);
        this.setOrigin(0, 0);

        /**
         * @property {HTMLCanvasElement} canvas - The canvas element that the text is rendered.
         */
        this.canvas = CanvasPool.create(this);

        /**
         * @property {HTMLCanvasElement} context - The context of the canvas element that the text is rendered to.
         */
        this.context = this.canvas.getContext('2d');

        this.style = new TextStyle(this, style);

        this.autoRound = true;

        /**
         * The Regular Expression that is used to split the text up into lines, in
         * multi-line text. By default this is `/(?:\r\n|\r|\n)/`.
         * You can change this RegExp to be anything else that you may need.
         * @property {Object} splitRegExp
         */
        this.splitRegExp = /(?:\r\n|\r|\n)/;

        //  This is populated in this.setText
        this.text = '';

        this.resolution = 1;

        /**
        * Specify a padding value which is added to the line width and height when calculating the Text size.
        * Allows you to add extra spacing if the browser is unable to accurately determine the true font dimensions.
        * @property {Phaser.Point} padding
        */
        this.padding = { left: 0, right: 0, top: 0, bottom: 0 };

        this.width = 1;
        this.height = 1;

        this.canvasTexture = null;
        this.dirty = false;

        this.initRTL();

        if (style && style.padding)
        {
            this.setPadding(style.padding);
        }

        this.setText(text);

        var _this = this;

        scene.sys.game.renderer.addContextRestoredCallback(function ()
        {
            _this.canvasTexture = null;
            _this.dirty = true;
        });
    },

    initRTL: function ()
    {
        if (!this.style.rtl)
        {
            return;
        }

        //  Here is where the crazy starts.
        //
        //  Due to browser implementation issues, you cannot fillText BiDi text to a canvas
        //  that is not part of the DOM. It just completely ignores the direction property.

        this.canvas.dir = 'rtl';

        //  Experimental atm, but one day ...
        this.context.direction = 'rtl';

        //  Add it to the DOM, but hidden within the parent canvas.
        this.canvas.style.display = 'none';

        AddToDOM(this.canvas, this.scene.sys.canvas);

        //  And finally we set the x origin
        this.originX = 1;
    },

    /**
     * Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal
     * bounds.
     *
     * @param {string} text - The text to perform word wrap detection against.
     */
    runWordWrap: function (text)
    {
        var style = this.style;
        if (style.wordWrapCallback)
        {
            var wrappedLines = style.wordWrapCallback.call(style.wordWrapCallbackScope, text, this);
            if (Array.isArray(wrappedLines))
            {
                wrappedLines = wrappedLines.join('\n');
            }
            return wrappedLines;
        }
        else if (style.wordWrapWidth)
        {
            if (style.wordWrapUseAdvanced)
            {
                return this.advancedWordWrap(text);
            }
            else
            {
                return this.basicWordWrap(text);
            }
        }
        else
        {
            return text;
        }
    },

    /**
     * Advanced wrapping algorithm that will wrap words as the line grows longer than its horizontal
     * bounds. White space is condensed (e.g., consecutive spaces are replaced with one). Lines are
     * trimmed of white space before processing. Throws an error if the user was smart enough to
     * specify a wordWrapWidth less than a single character.
     *
     * @param {string} text - The text to perform word wrap detection against.
     */
    advancedWordWrap: function (text)
    {
        var context = this.context;
        var wordWrapWidth = this.style.wordWrapWidth;
        var output = '';

        // condense consecutive spaces and split into lines
        var lines = text
            .replace(/ +/gi, ' ')
            .split(/\r?\n/gi);

        var linesCount = lines.length;

        for (var i = 0; i < linesCount; i++)
        {
            var line = lines[i];
            var out = '';

            // trim whitespace
            line = line.replace(/^ *|\s*$/gi, '');

            // if entire line is less than wordWrapWidth append the entire line and exit early
            var lineWidth = context.measureText(line).width;

            if (lineWidth < wordWrapWidth)
            {
                output += line + '\n';
                continue;
            }

            // otherwise, calculate new lines
            var currentLineWidth = wordWrapWidth;

            // split into words
            var words = line.split(' ');

            for (var j = 0; j < words.length; j++)
            {
                var word = words[j];
                var wordWithSpace = word + ' ';
                var wordWidth = context.measureText(wordWithSpace).width;

                if (wordWidth > currentLineWidth)
                {
                    // break word
                    if (j === 0)
                    {
                        // shave off letters from word until it's small enough
                        var newWord = wordWithSpace;

                        while (newWord.length)
                        {
                            newWord = newWord.slice(0, -1);
                            wordWidth = context.measureText(newWord).width;

                            if (wordWidth <= currentLineWidth)
                            {
                                break;
                            }
                        }

                        // if wordWrapWidth is too small for even a single letter, shame user
                        // failure with a fatal error
                        if (!newWord.length)
                        {
                            throw new Error('This text\'s wordWrapWidth setting is less than a single character!');
                        }

                        // replace current word in array with remainder
                        var secondPart = word.substr(newWord.length);

                        words[j] = secondPart;

                        // append first piece to output
                        out += newWord;
                    }

                    // if existing word length is 0, don't include it
                    var offset = (words[j].length) ? j : j + 1;

                    // collapse rest of sentence and remove any trailing white space
                    var remainder = words.slice(offset).join(' ')
                        .replace(/[ \n]*$/gi, '');

                    // prepend remainder to next line
                    lines[i + 1] = remainder + ' ' + (lines[i + 1] || '');
                    linesCount = lines.length;

                    break; // processing on this line

                    // append word with space to output
                }
                else
                {
                    out += wordWithSpace;
                    currentLineWidth -= wordWidth;
                }
            }

            // append processed line to output
            output += out.replace(/[ \n]*$/gi, '') + '\n';
        }

        // trim the end of the string
        output = output.replace(/[\s|\n]*$/gi, '');

        return output;
    },

    /**
     * Greedy wrapping algorithm that will wrap words as the line grows longer than its horizontal
     * bounds.
     *
     * @param {string} text - The text to perform word wrap detection against.
     */
    basicWordWrap: function (text)
    {
        var result = '';
        var lines = text.split('\n');

        for (var i = 0; i < lines.length; i++)
        {
            var spaceLeft = this.style.wordWrapWidth;
            var words = lines[i].split(' ');

            for (var j = 0; j < words.length; j++)
            {
                var wordWidth = this.context.measureText(words[j]).width;
                var wordWidthWithSpace = wordWidth + this.context.measureText(' ').width;

                if (wordWidthWithSpace > spaceLeft)
                {
                    // Skip printing the newline if it's the first word of the line that is greater
                    // than the word wrap width.
                    if (j > 0)
                    {
                        result += '\n';
                    }
                    result += words[j] + ' ';
                    spaceLeft = this.style.wordWrapWidth - wordWidth;
                }
                else
                {
                    spaceLeft -= wordWidthWithSpace;
                    result += words[j] + ' ';
                }
            }

            if (i < lines.length - 1)
            {
                result += '\n';
            }
        }

        return result;
    },
    setText: function (value)
    {
        if (Array.isArray(value))
        {
            value = value.join('\n');
        }

        if (value !== this.text)
        {
            this.text = value.toString();

            this.updateText();
        }

        return this;
    },

    setStyle: function (style)
    {
        return this.style.setStyle(style);
    },

    setFont: function (font)
    {
        return this.style.setFont(font);
    },

    setFontFamily: function (family)
    {
        return this.style.setFontFamily(family);
    },

    setFontSize: function (size)
    {
        return this.style.setFontSize(size);
    },

    setFontStyle: function (style)
    {
        return this.style.setFontStyle(style);
    },

    setFixedSize: function (width, height)
    {
        return this.style.setFixedSize(width, height);
    },

    setBackgroundColor: function (color)
    {
        return this.style.setBackgroundColor(color);
    },

    setFill: function (color)
    {
        return this.style.setFill(color);
    },

    setColor: function (color)
    {
        return this.style.setColor(color);
    },

    setStroke: function (color, thickness)
    {
        return this.style.setStroke(color, thickness);
    },

    setShadow: function (x, y, color, blur, shadowStroke, shadowFill)
    {
        return this.style.setShadow(x, y, color, blur, shadowStroke, shadowFill);
    },

    setShadowOffset: function (x, y)
    {
        return this.style.setShadowOffset(x, y);
    },

    setShadowColor: function (color)
    {
        return this.style.setShadowColor(color);
    },

    setShadowBlur: function (blur)
    {
        return this.style.setShadowBlur(blur);
    },

    setShadowStroke: function (enabled)
    {
        return this.style.setShadowStroke(enabled);
    },

    setShadowFill: function (enabled)
    {
        return this.style.setShadowFill(enabled);
    },

    setAlign: function (align)
    {
        return this.style.setAlign(align);
    },

    //  'left' can be an object
    //  if only 'left' and 'top' are given they are treated as 'x' and 'y'
    setPadding: function (left, top, right, bottom)
    {
        if (typeof left === 'object')
        {
            var config = left;

            //  If they specify x and/or y this applies to all
            var x = GetValue(config, 'x', null);

            if (x !== null)
            {
                left = x;
                right = x;
            }
            else
            {
                left = GetValue(config, 'left', 0);
                right = GetValue(config, 'right', left);
            }

            var y = GetValue(config, 'y', null);

            if (y !== null)
            {
                top = y;
                bottom = y;
            }
            else
            {
                top = GetValue(config, 'top', 0);
                bottom = GetValue(config, 'bottom', top);
            }
        }
        else
        {
            if (left === undefined) { left = 0; }
            if (top === undefined) { top = left; }
            if (right === undefined) { right = left; }
            if (bottom === undefined) { bottom = top; }
        }

        this.padding.left = left;
        this.padding.top = top;
        this.padding.right = right;
        this.padding.bottom = bottom;

        return this.updateText();
    },

    setMaxLines: function (max)
    {
        return this.style.setMaxLines(max);
    },

    updateText: function ()
    {
        var canvas = this.canvas;
        var context = this.context;
        var style = this.style;
        var size = style.metrics;

        var outputText = this.text;

        // if (style.wordWrap)
        // {
        //     outputText = this.runWordWrap(this.text);
        // }

        //  Split text into lines
        var lines = outputText.split(this.splitRegExp);

        var textSize = GetTextSize(this, size, lines);

        var padding = this.padding;

        var w = textSize.width + padding.left + padding.right;
        var h = textSize.height + padding.top + padding.bottom;

        if (!style.fixedWidth)
        {
            this.width = w;
        }

        if (!style.fixedHeight)
        {
            this.height = h;
        }

        this.updateDisplayOrigin();

        w *= this.resolution;
        h *= this.resolution;

        if (canvas.width !== w || canvas.height !== h)
        {
            canvas.width = w;
            canvas.height = h;
        }
        else
        {
            context.clearRect(0, 0, w, h);
        }

        context.save();

        if (style.backgroundColor)
        {
            context.fillStyle = style.backgroundColor;
            context.fillRect(0, 0, w, h);
        }

        style.syncFont(canvas, context);

        context.textBaseline = 'alphabetic';

        //  Apply padding
        context.translate(padding.left, padding.top);

        var linePositionX;
        var linePositionY;

        //  Draw text line by line
        for (var i = 0; i < textSize.lines; i++)
        {
            linePositionX = style.strokeThickness / 2;
            linePositionY = (style.strokeThickness / 2 + i * textSize.lineHeight) + size.ascent;

            if (i > 0)
            {
                linePositionY += (textSize.lineSpacing * i);
            }

            if (style.rtl)
            {
                linePositionX = w - linePositionX;
            }
            else if (style.align === 'right')
            {
                linePositionX += textSize.width - textSize.lineWidths[i];
            }
            else if (style.align === 'center')
            {
                linePositionX += (textSize.width - textSize.lineWidths[i]) / 2;
            }

            if (this.autoRound)
            {
                linePositionX = Math.round(linePositionX);
                linePositionY = Math.round(linePositionY);
            }

            if (style.strokeThickness)
            {
                this.style.syncShadow(context, style.shadowStroke);

                context.strokeText(lines[i], linePositionX, linePositionY);
            }

            if (style.color)
            {
                this.style.syncShadow(context, style.shadowFill);

                context.fillText(lines[i], linePositionX, linePositionY);
            }
        }

        context.restore();

        this.dirty = true;

        return this;
    },

    getTextMetrics: function ()
    {
        return this.style.getTextMetrics();
    },

    toJSON: function ()
    {
        var out = Components.ToJSON(this);

        //  Extra Text data is added here

        var data = {
            autoRound: this.autoRound,
            text: this.text,
            style: this.style.toJSON(),
            resolution: this.resolution,
            padding: {
                left: this.padding.left,
                right: this.padding.right,
                top: this.padding.top,
                bottom: this.padding.bottom
            }
        };

        out.data = data;

        return out;
    },

    preDestroy: function ()
    {
        if (this.style.rtl)
        {
            RemoveFromDOM(this.canvas);
        }

        CanvasPool.remove(this.canvas);
    }

});

module.exports = Text;
<|endoftext|>


<commit_before>/**
* @author       Richard Davey (@photonstorm)
* @author       Felipe Alfonso (@bitnenfer)
* @copyright    2017 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

var CONST = require('../../const');
var BlitterBatch = require('./renderers/blitterbatch/BlitterBatch');
var QuadBatch = require('./renderers/quadbatch/QuadBatch');
var SpriteBatch = require('./renderers/spritebatch/SpriteBatch');
var ShapeBatch = require('./renderers/shapebatch/ShapeBatch');
var EffectRenderer = require('./renderers/effectrenderer/EffectRenderer');
var BlendModes = require('../BlendModes');
var ScaleModes = require('../ScaleModes');
var ResourceManager = require('./ResourceManager');
var Resources = require('./resources');

var WebGLRenderer = function (game)
{
    this.game = game;
    this.type = CONST.WEBGL;
    this.width = game.config.width * game.config.resolution;
    this.height = game.config.height * game.config.resolution;
    this.resolution = game.config.resolution;
    this.view = game.canvas;

    //   All of these settings will be able to be controlled via the Game Config
    this.config = {
        clearBeforeRender: true,
        transparent: false,
        autoResize: false,
        preserveDrawingBuffer: false,

        WebGLContextOptions: {
            alpha: true,
            antialias: true,
            premultipliedAlpha: true,
            stencil: true,
            preserveDrawingBuffer: false
        }
    };

    this.contextLost = false;
    this.maxTextures = 1;
    this.multiTexture = false;
    this.blendModes = [];
    this.gl = null;
    this.extensions = null;
    this.currentRendereres = [];
    this.blitterBatch = null;
    this.aaQuadBatch = null;
    this.spriteBatch = null;
    this.shapeBatch = null;
    this.effectRenderer = null;
    this.currentRenderer = null;
    this.currentTexture = null;
    this.shaderCache = {};
    this.currentShader = null;
    this.resourceManager = null;
    this.currentRenderTarget = null;

    this.init();
};

WebGLRenderer.prototype.constructor = WebGLRenderer;

WebGLRenderer.prototype = {

    init: function ()
    {
        console.log('WebGLRenderer.init');

        this.gl = this.view.getContext('webgl', this.config.WebGLContextOptions) || this.view.getContext('experimental-webgl', this.config.WebGLContextOptions);

        if (!this.gl)
        {
            this.contextLost = true;
            throw new Error('This browser does not support WebGL. Try using the Canvas renderer.');
        }

        var gl = this.gl;
        var color = this.game.config.backgroundColor;

        this.resourceManager = new ResourceManager(gl);

        gl.disable(gl.DEPTH_TEST);
        gl.disable(gl.CULL_FACE);
        gl.enable(gl.BLEND);
        gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);

        this.resize(this.width, this.height);

        //  Map Blend Modes

        var add = [ gl.SRC_ALPHA, gl.DST_ALPHA ];
        var normal = [ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ];
        var multiply = [ gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA ];
        var screen = [ gl.SRC_ALPHA, gl.ONE ];

        this.blendModes = [
            normal, add, multiply, screen, normal,
            normal, normal, normal, normal,
            normal, normal, normal, normal,
            normal, normal, normal, normal
        ];

        this.blendMode = -1;
        this.extensions = gl.getSupportedExtensions();
        this.blitterBatch = this.addRenderer(new BlitterBatch(this.game, gl, this));
        this.quadBatch = this.addRenderer(new QuadBatch(this.game, gl, this));
        this.spriteBatch = this.addRenderer(new SpriteBatch(this.game, gl, this));
        this.shapeBatch = this.addRenderer(new ShapeBatch(this.game, gl, this));
        this.effectRenderer = this.addRenderer(new EffectRenderer(this.game, gl, this));
    },

    createTexture: function (source)
    {
        var gl = this.gl;
        var filter = gl.NEAREST;

        if (!source.glTexture)
        {

            if (source.scaleMode === ScaleModes.LINEAR)
            {
                filter = gl.LINEAR;
            }
            else if (source.scaleMode === ScaleModes.NEAREST)
            {
                filter = gl.NEAREST;
            }

            source.glTexture = this.resourceManager.createTexture(
                    0,
                    filter,
                    filter,
                    gl.CLAMP_TO_EDGE,
                    gl.CLAMP_TO_EDGE,
                    gl.RGBA,
                    source.image
                );
        }

        this.currentTexture = null;
    },

    setTexture: function (texture)
    {
        if (this.currentTexture !== texture)
        {
            if (this.currentRenderer)
            {
                this.currentRenderer.flush();
            }

            var gl = this.gl;

            gl.activeTexture(gl.TEXTURE0);
            if (texture !== null)
            {
                gl.bindTexture(gl.TEXTURE_2D, texture.texture);
            }
            else
            {
                gl.bindTexture(gl.TEXTURE_2D, null);
            }

            this.currentTexture = texture;
        }
    },

    setRenderer: function (renderer, texture, camera, renderTarget)
    {
        this.setTexture(texture);
        this.setRenderTarget(renderTarget);

        if (this.currentRenderer !== renderer)
        {
            if (this.currentRenderer)
            {
                this.currentRenderer.flush();
            }

            this.currentRenderer = renderer;
        }
    },

    setRenderTarget: function (renderTarget)
    {
        var gl = this.gl;

        if (this.currentRenderTarget !== renderTarget)
        {
            if (this.currentRenderer)
            {
                this.currentRenderer.flush();
            }

            if (renderTarget !== null)
            {
                gl.bindFramebuffer(gl.FRAMEBUFFER, renderTarget.framebufferObject);
                if (renderTarget.shouldClear)
                {
                    gl.clearColor(0, 0, 0, 0);
                    gl.clear(gl.COLOR_BUFFER_BIT);
                    renderTarget.shouldClear = false;
                }
            }
            else
            {
                gl.bindFramebuffer(gl.FRAMEBUFFER, null);
                gl.viewport(0, 0, this.width, this.height);
            }
            this.currentRenderTarget = renderTarget;
        }
    },

    resize: function (width, height)
    {
        var res = this.game.config.resolution;

        this.width = width * res;
        this.height = height * res;

        this.view.width = this.width;
        this.view.height = this.height;

        if (this.autoResize)
        {
            this.view.style.width = (this.width / res) + 'px';
            this.view.style.height = (this.height / res) + 'px';
        }

        this.gl.viewport(0, 0, this.width, this.height);
        for (var i = 0, l = this.currentRendereres.length; i < l; ++i)
        {
            this.currentRendereres[i].bind();
            this.currentRendereres[i].resize(width, height, resolution);
        }
        if (this.currentRenderer)
        {
            this.currentRenderer.bind();
        }
    },

    //  Call at the start of the render loop
    preRender: function ()
    {
        this.setRenderTarget(null);
        //  No point rendering if our context has been blown up!
        if (this.contextLost)
        {
            return;
        }

        //  Add Pre-render hook

        var gl = this.gl;
        var color = this.game.config.backgroundColor;

        gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);
        // Some drivers require to call glClear
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

        this.setBlendMode(BlendModes.NORMAL);
    },

    /**
     * Renders a single State.
     *
     * @method render
     * @param {Phaser.State} state - The State to be rendered.
     * @param {number} interpolationPercentage - The cumulative amount of time that hasn't been simulated yet, divided
     *   by the amount of time that will be simulated the next time update()
     *   runs. Useful for interpolating frames.
     */
    render: function (state, children, interpolationPercentage, camera)
    {
        //  Could move to the State Systems or MainLoop
        var gl = this.gl;
        var scissor = (camera.x !== 0 || camera.y !== 0 || camera.width !== gl.canvas.width || camera.height !== gl.canvas.height);

        this.setRenderTarget(null);
        if (scissor)
        {
            gl.enable(gl.SCISSOR_TEST);
            gl.scissor(camera.x, (gl.drawingBufferHeight - camera.y - camera.height), camera.width, camera.height);
        }
        // We could either clear color or render a quad
        var color = this.game.config.backgroundColor;
        gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);
        gl.clear(gl.COLOR_BUFFER_BIT);

        var list = children.list;
        var length = list.length;
        for (var index = 0; index < length; ++index)
        {
            var child = list[index];
            // Setting blend mode if needed
            var renderer = this.currentRenderer;
            var newBlendMode = child.blendMode;
            if (this.blendMode !== newBlendMode)
            {
                if (renderer)
                {
                    renderer.flush();
                }
                var blend = this.blendModes[newBlendMode];
                gl.enable(gl.BLEND);
                if (blend.length > 2)
                {
                    gl.blendFuncSeparate(blend[0], blend[1], blend[2], blend[3]);
                }
                else
                {
                    gl.blendFunc(blend[0], blend[1]);
                }
                this.blendMode = newBlendMode;
            }
            // drawing child
            child.renderWebGL(this, child, interpolationPercentage, camera);
            renderer = this.currentRenderer;
            if (renderer && renderer.isFull())
            {
                renderer.flush();
            }
        }
        if (this.currentRenderer)
        {
            this.currentRenderer.flush();
        }
        if (camera._fadeAlpha > 0 || camera._flashAlpha > 0)
        {
            var quadBatch = this.quadBatch;
            quadBatch.bind();
            // fade rendering
            quadBatch.add(
                camera.x, camera.y, camera.width, camera.height,
                camera._fadeRed,
                camera._fadeGreen,
                camera._fadeBlue,
                camera._fadeAlpha
            );
            // flash rendering
            quadBatch.add(
                camera.x, camera.y, camera.width, camera.height,
                camera._flashRed,
                camera._flashGreen,
                camera._flashBlue,
                camera._flashAlpha
            );
            quadBatch.flush();
            this.currentRenderer.bind();
        }
        if (scissor)
        {
            gl.disable(gl.SCISSOR_TEST);
        }
    },

    //  Called at the end of the render loop (tidy things up, etc)
    postRender: function ()
    {
        if (this.currentRenderer)
        {
            this.currentRenderer.flush();
        }
        //  Add Post-render hook

        // console.log('%c render end ', 'color: #ffffff; background: #ff0000;');
    },

    destroy: function ()
    {
        this.gl = null;
    },

    createFBO: function () {},

    setBlendMode: function (newBlendMode)
    {
        var gl = this.gl;
        var renderer = this.currentRenderer;
        var blend = null;

        if (this.blendMode !== newBlendMode)
        {
            if (renderer)
                renderer.flush();
            blend = this.blendModes[newBlendMode];
            gl.enable(gl.BLEND);
            if (blend.length > 2)
            {
                gl.blendFuncSeparate(blend[0], blend[1], blend[2], blend[3]);
            }
            else
            {
                gl.blendFunc(blend[0], blend[1]);
            }
            this.blendMode = newBlendMode;
        }
    },

    addRenderer: function (rendererInstance)
    {
        var index = this.currentRendereres.indexOf(rendererInstance);
        if (index < 0)
        {
            this.currentRendereres.push(rendererInstance);
            return rendererInstance;
        }
        return null;
    },

    uploadCanvasToGPU: function (srcCanvas, dstTexture, shouldUpdateResource)
    {
        var gl = this.gl;

        if (!dstTexture)
        {
            dstTexture = new Resources.Texture(null, 0, 0);
            /* only call this once */
            dstTexture.texture = gl.createTexture();
        }

        if (shouldUpdateResource)
        {
            /* Update resource */
            gl.bindTexture(gl.TEXTURE_2D, dstTexture.texture);
            gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
        }
        else
        {
            /* Allocate or Reallocate resource */
            gl.bindTexture(gl.TEXTURE_2D, dstTexture.texture);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        }

        dstTexture.width = srcCanvas.width;
        dstTexture.height = srcCanvas.height;

        /* we must rebind old texture */
        gl.bindTexture(gl.TEXTURE_2D, this.currentTexture.texture);

        return dstTexture;
    }
};

module.exports = WebGLRenderer;
<commit_msg>Reset renderTarget to null when rendering camera effects<commit_after>/**
* @author       Richard Davey (@photonstorm)
* @author       Felipe Alfonso (@bitnenfer)
* @copyright    2017 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

var CONST = require('../../const');
var BlitterBatch = require('./renderers/blitterbatch/BlitterBatch');
var QuadBatch = require('./renderers/quadbatch/QuadBatch');
var SpriteBatch = require('./renderers/spritebatch/SpriteBatch');
var ShapeBatch = require('./renderers/shapebatch/ShapeBatch');
var EffectRenderer = require('./renderers/effectrenderer/EffectRenderer');
var BlendModes = require('../BlendModes');
var ScaleModes = require('../ScaleModes');
var ResourceManager = require('./ResourceManager');
var Resources = require('./resources');

var WebGLRenderer = function (game)
{
    this.game = game;
    this.type = CONST.WEBGL;
    this.width = game.config.width * game.config.resolution;
    this.height = game.config.height * game.config.resolution;
    this.resolution = game.config.resolution;
    this.view = game.canvas;

    //   All of these settings will be able to be controlled via the Game Config
    this.config = {
        clearBeforeRender: true,
        transparent: false,
        autoResize: false,
        preserveDrawingBuffer: false,

        WebGLContextOptions: {
            alpha: true,
            antialias: true,
            premultipliedAlpha: true,
            stencil: true,
            preserveDrawingBuffer: false
        }
    };

    this.contextLost = false;
    this.maxTextures = 1;
    this.multiTexture = false;
    this.blendModes = [];
    this.gl = null;
    this.extensions = null;
    this.currentRendereres = [];
    this.blitterBatch = null;
    this.aaQuadBatch = null;
    this.spriteBatch = null;
    this.shapeBatch = null;
    this.effectRenderer = null;
    this.currentRenderer = null;
    this.currentTexture = null;
    this.shaderCache = {};
    this.currentShader = null;
    this.resourceManager = null;
    this.currentRenderTarget = null;

    this.init();
};

WebGLRenderer.prototype.constructor = WebGLRenderer;

WebGLRenderer.prototype = {

    init: function ()
    {
        console.log('WebGLRenderer.init');

        this.gl = this.view.getContext('webgl', this.config.WebGLContextOptions) || this.view.getContext('experimental-webgl', this.config.WebGLContextOptions);

        if (!this.gl)
        {
            this.contextLost = true;
            throw new Error('This browser does not support WebGL. Try using the Canvas renderer.');
        }

        var gl = this.gl;
        var color = this.game.config.backgroundColor;

        this.resourceManager = new ResourceManager(gl);

        gl.disable(gl.DEPTH_TEST);
        gl.disable(gl.CULL_FACE);
        gl.enable(gl.BLEND);
        gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);

        this.resize(this.width, this.height);

        //  Map Blend Modes

        var add = [ gl.SRC_ALPHA, gl.DST_ALPHA ];
        var normal = [ gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ];
        var multiply = [ gl.DST_COLOR, gl.ONE_MINUS_SRC_ALPHA ];
        var screen = [ gl.SRC_ALPHA, gl.ONE ];

        this.blendModes = [
            normal, add, multiply, screen, normal,
            normal, normal, normal, normal,
            normal, normal, normal, normal,
            normal, normal, normal, normal
        ];

        this.blendMode = -1;
        this.extensions = gl.getSupportedExtensions();
        this.blitterBatch = this.addRenderer(new BlitterBatch(this.game, gl, this));
        this.quadBatch = this.addRenderer(new QuadBatch(this.game, gl, this));
        this.spriteBatch = this.addRenderer(new SpriteBatch(this.game, gl, this));
        this.shapeBatch = this.addRenderer(new ShapeBatch(this.game, gl, this));
        this.effectRenderer = this.addRenderer(new EffectRenderer(this.game, gl, this));
    },

    createTexture: function (source)
    {
        var gl = this.gl;
        var filter = gl.NEAREST;

        if (!source.glTexture)
        {

            if (source.scaleMode === ScaleModes.LINEAR)
            {
                filter = gl.LINEAR;
            }
            else if (source.scaleMode === ScaleModes.NEAREST)
            {
                filter = gl.NEAREST;
            }

            source.glTexture = this.resourceManager.createTexture(
                    0,
                    filter,
                    filter,
                    gl.CLAMP_TO_EDGE,
                    gl.CLAMP_TO_EDGE,
                    gl.RGBA,
                    source.image
                );
        }

        this.currentTexture = null;
    },

    setTexture: function (texture)
    {
        if (this.currentTexture !== texture)
        {
            if (this.currentRenderer)
            {
                this.currentRenderer.flush();
            }

            var gl = this.gl;

            gl.activeTexture(gl.TEXTURE0);
            if (texture !== null)
            {
                gl.bindTexture(gl.TEXTURE_2D, texture.texture);
            }
            else
            {
                gl.bindTexture(gl.TEXTURE_2D, null);
            }

            this.currentTexture = texture;
        }
    },

    setRenderer: function (renderer, texture, camera, renderTarget)
    {
        this.setTexture(texture);
        this.setRenderTarget(renderTarget);

        if (this.currentRenderer !== renderer)
        {
            if (this.currentRenderer)
            {
                this.currentRenderer.flush();
            }

            this.currentRenderer = renderer;
        }
    },

    setRenderTarget: function (renderTarget)
    {
        var gl = this.gl;

        if (this.currentRenderTarget !== renderTarget)
        {
            if (this.currentRenderer)
            {
                this.currentRenderer.flush();
            }

            if (renderTarget !== null)
            {
                gl.bindFramebuffer(gl.FRAMEBUFFER, renderTarget.framebufferObject);
                if (renderTarget.shouldClear)
                {
                    gl.clearColor(0, 0, 0, 0);
                    gl.clear(gl.COLOR_BUFFER_BIT);
                    renderTarget.shouldClear = false;
                }
            }
            else
            {
                gl.bindFramebuffer(gl.FRAMEBUFFER, null);
                gl.viewport(0, 0, this.width, this.height);
            }
            this.currentRenderTarget = renderTarget;
        }
    },

    resize: function (width, height)
    {
        var res = this.game.config.resolution;

        this.width = width * res;
        this.height = height * res;

        this.view.width = this.width;
        this.view.height = this.height;

        if (this.autoResize)
        {
            this.view.style.width = (this.width / res) + 'px';
            this.view.style.height = (this.height / res) + 'px';
        }

        this.gl.viewport(0, 0, this.width, this.height);
        for (var i = 0, l = this.currentRendereres.length; i < l; ++i)
        {
            this.currentRendereres[i].bind();
            this.currentRendereres[i].resize(width, height, resolution);
        }
        if (this.currentRenderer)
        {
            this.currentRenderer.bind();
        }
    },

    //  Call at the start of the render loop
    preRender: function ()
    {
        this.setRenderTarget(null);
        //  No point rendering if our context has been blown up!
        if (this.contextLost)
        {
            return;
        }

        //  Add Pre-render hook

        var gl = this.gl;
        var color = this.game.config.backgroundColor;

        gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);
        // Some drivers require to call glClear
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

        this.setBlendMode(BlendModes.NORMAL);
    },

    /**
     * Renders a single State.
     *
     * @method render
     * @param {Phaser.State} state - The State to be rendered.
     * @param {number} interpolationPercentage - The cumulative amount of time that hasn't been simulated yet, divided
     *   by the amount of time that will be simulated the next time update()
     *   runs. Useful for interpolating frames.
     */
    render: function (state, children, interpolationPercentage, camera)
    {
        //  Could move to the State Systems or MainLoop
        var gl = this.gl;
        var scissor = (camera.x !== 0 || camera.y !== 0 || camera.width !== gl.canvas.width || camera.height !== gl.canvas.height);

        this.setRenderTarget(null);
        if (scissor)
        {
            gl.enable(gl.SCISSOR_TEST);
            gl.scissor(camera.x, (gl.drawingBufferHeight - camera.y - camera.height), camera.width, camera.height);
        }
        // We could either clear color or render a quad
        var color = this.game.config.backgroundColor;
        gl.clearColor(color.redGL, color.greenGL, color.blueGL, color.alphaGL);
        gl.clear(gl.COLOR_BUFFER_BIT);

        var list = children.list;
        var length = list.length;
        for (var index = 0; index < length; ++index)
        {
            var child = list[index];
            // Setting blend mode if needed
            var renderer = this.currentRenderer;
            var newBlendMode = child.blendMode;
            if (this.blendMode !== newBlendMode)
            {
                if (renderer)
                {
                    renderer.flush();
                }
                var blend = this.blendModes[newBlendMode];
                gl.enable(gl.BLEND);
                if (blend.length > 2)
                {
                    gl.blendFuncSeparate(blend[0], blend[1], blend[2], blend[3]);
                }
                else
                {
                    gl.blendFunc(blend[0], blend[1]);
                }
                this.blendMode = newBlendMode;
            }
            // drawing child
            child.renderWebGL(this, child, interpolationPercentage, camera);
            renderer = this.currentRenderer;
            if (renderer && renderer.isFull())
            {
                renderer.flush();
            }
        }
        if (this.currentRenderer)
        {
            this.currentRenderer.flush();
        }
        if (camera._fadeAlpha > 0 || camera._flashAlpha > 0)
        {
            this.setRenderTarget(null);
            var quadBatch = this.quadBatch;
            quadBatch.bind();
            // fade rendering
            quadBatch.add(
                camera.x, camera.y, camera.width, camera.height,
                camera._fadeRed,
                camera._fadeGreen,
                camera._fadeBlue,
                camera._fadeAlpha
            );
            // flash rendering
            quadBatch.add(
                camera.x, camera.y, camera.width, camera.height,
                camera._flashRed,
                camera._flashGreen,
                camera._flashBlue,
                camera._flashAlpha
            );
            quadBatch.flush();
            this.currentRenderer.bind();
        }
        if (scissor)
        {
            gl.disable(gl.SCISSOR_TEST);
        }
    },

    //  Called at the end of the render loop (tidy things up, etc)
    postRender: function ()
    {
        if (this.currentRenderer)
        {
            this.currentRenderer.flush();
        }
        //  Add Post-render hook

        // console.log('%c render end ', 'color: #ffffff; background: #ff0000;');
    },

    destroy: function ()
    {
        this.gl = null;
    },

    createFBO: function () {},

    setBlendMode: function (newBlendMode)
    {
        var gl = this.gl;
        var renderer = this.currentRenderer;
        var blend = null;

        if (this.blendMode !== newBlendMode)
        {
            if (renderer)
                renderer.flush();
            blend = this.blendModes[newBlendMode];
            gl.enable(gl.BLEND);
            if (blend.length > 2)
            {
                gl.blendFuncSeparate(blend[0], blend[1], blend[2], blend[3]);
            }
            else
            {
                gl.blendFunc(blend[0], blend[1]);
            }
            this.blendMode = newBlendMode;
        }
    },

    addRenderer: function (rendererInstance)
    {
        var index = this.currentRendereres.indexOf(rendererInstance);
        if (index < 0)
        {
            this.currentRendereres.push(rendererInstance);
            return rendererInstance;
        }
        return null;
    },

    uploadCanvasToGPU: function (srcCanvas, dstTexture, shouldUpdateResource)
    {
        var gl = this.gl;

        if (!dstTexture)
        {
            dstTexture = new Resources.Texture(null, 0, 0);
            /* only call this once */
            dstTexture.texture = gl.createTexture();
        }

        if (shouldUpdateResource)
        {
            /* Update resource */
            gl.bindTexture(gl.TEXTURE_2D, dstTexture.texture);
            gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
        }
        else
        {
            /* Allocate or Reallocate resource */
            gl.bindTexture(gl.TEXTURE_2D, dstTexture.texture);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, srcCanvas);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        }

        dstTexture.width = srcCanvas.width;
        dstTexture.height = srcCanvas.height;

        /* we must rebind old texture */
        gl.bindTexture(gl.TEXTURE_2D, this.currentTexture.texture);

        return dstTexture;
    }
};

module.exports = WebGLRenderer;
<|endoftext|>


<commit_before>var YN = jQuery.noConflict();

// Main page cleanup
function changeUI() {
  YN('#uhWrapper').css('padding-top','22px');
  YN('#masterNav, #theAd').remove();
  removeListAdd();
  YN('#main, #yucs, #yuhead-bucket').css('max-width','100%');
  YN('#shellcontent, .frost-container').css('right','0px');
  YN('#shellcontent').removeClass('wide-right-rail');
}

// remove list adds
function removeListAdd() {
  YN('.mb-list-ad, .search-message-container-ad').remove();
}

// Init page cleanup
changeUI();

// Listen for page to load
YN(function() {
  changeUI();
});

// Listen for page to finnish
YN(document).ready(function() {
  changeUI();
});

// Listen for complete AJAX calls
YN(document).ajaxSuccess(function() {
  changeUI();
});

// Bind to changes in the DOM
YN('body').bind('DOMSubtreeModified', function() {
    removeListAdd();
});
<commit_msg>updating script to remove additional adds in the side panel<commit_after>var YN = jQuery.noConflict();

// Main page cleanup
function changeUI() {
  YN('#uhWrapper').css('padding-top','22px');
  YN('#masterNav, #theAd').remove();
  YN('div.listnav-outter div[id^=slot]').remove();
  removeListAdd();
  YN('#main, #yucs, #yuhead-bucket').css('max-width','100%');
  YN('#shellcontent, .frost-container').css('right','0px');
  YN('#shellcontent').removeClass('wide-right-rail');
}

// remove list adds
function removeListAdd() {
  YN('.mb-list-ad, .search-message-container-ad').remove();
}

// Init page cleanup
changeUI();

// Listen for page to load
YN(function() {
  changeUI();
});

// Listen for page to finnish
YN(document).ready(function() {
  changeUI();
});

// Listen for complete AJAX calls
YN(document).ajaxSuccess(function() {
  changeUI();
});

// Bind to changes in the DOM
YN('body').bind('DOMSubtreeModified', function() {
    removeListAdd();
});
<|endoftext|>


<commit_before>
class GameState_Gameplay extends GameState {

	constructor(gsm, seed) {
		super(gsm);

		this.timeRunning = 0.0;
		this.seed = seed;
		print("seed " + this.seed);

		this.physicsEngine = new PhysicsEngine();
		this.shipManager = new ShipManager();
		this.geneticAlgorithm = new GeneticAlgorithm();
		this.ships = [];
	}

	initiate() {

		this.timeRunning = 0.0;

		// get ship prototype
		var shipPrototype = this.shipManager.defaultShip;

		// populate genetic algorithm
		this.geneticAlgorithm.populate(this.seed, shipPrototype, 10);

		// first simulation start
		this.startSimulation();
	}

	deinitiate() {
	}

	update(deltaTime) {
		this.timeRunning += deltaTime;
		// simulation update
		this.updateSimulation(deltaTime);
	}

	display() {

		translate(width/2, height/2 + this.timeRunning * 20.0);

		this.level.display();

		for (var i = 0; i < this.ships.length; i++) {
			this.ships[i].display();
		}
	}

	startSimulation() {

		this.timeRunning = 0.0;

		// simulation basics
		this.simulationTimer = 0.0;
		this.simulationDuration = 30.0;
		this.simulationStatus = "on";

		// build level
		this.level = new Level(this.seed);

		// get training genome batch
		var trainingGenomeBatch = this.geneticAlgorithm.getTrainingBatch();

		// spawn ships
		this.ships = [];
		for (var i = 0; i < trainingGenomeBatch.length; i++) {
			var ship = _.cloneDeep(this.geneticAlgorithm.shipPrototype);
			ship.initiate(trainingGenomeBatch[i], this.physicsEngine);
			this.ships.push(ship);
		}

		// Create static colliders for rocks
		for (var i = 0; i < this.level.rocks.length; i++) {
			var rock = this.level.rocks[i];
			this.physicsEngine.staticColliders.push(new StaticCollider(rock.points[0], rock.points[1], rock.points[2], rock.points[3]));
		}
	}

	updateSimulation(deltaTime) {

		// check if playing
		if (this.simulationStatus == "on") {

			// check ending condition
			if (this.simulationTimer > this.simulationDuration) {

				// turn it off
				this.simulationStatus = "off";

				// evaluate and apply
				var results = this.evaluateSimulation();
				this.geneticAlgorithm.applySimulationResults(results);

				// repeat simulation
				this.startSimulation();
			}
			else {
				// update the level
				this.level.update(deltaTime);

				// Update the physics.
				this.physicsEngine.update(deltaTime);

				// Update ships
				for (var i = 0; i < this.ships.length; i++) {
					this.ships[i].update(deltaTime, this.level.rocks);
				}

				// progress timer
				this.simulationTimer += deltaTime;
			}
		}
	}

	evaluateSimulation() {
		// get current ship altitude
		var altitudes = [];
		for (var i = 0; i < this.ships.length; i++) {
			var centerOfMass = this.ships[i].centerOfMass();
			var altitude = centerOfMass.y;
			altitude *= -1.0;
			altitudes.push(altitude);
		}
		// return altitudes
		return altitudes;
	}

	print() {
		return '(Base)';
	}
}
<commit_msg>Camera follows the best duderolo.<commit_after>
class GameState_Gameplay extends GameState {

	constructor(gsm, seed) {
		super(gsm);

		this.timeRunning = 0.0;
		this.seed = seed;
		print("seed " + this.seed);

		this.physicsEngine = new PhysicsEngine();
		this.shipManager = new ShipManager();
		this.geneticAlgorithm = new GeneticAlgorithm();
		this.ships = [];
	}

	initiate() {

		this.timeRunning = 0.0;

		// get ship prototype
		var shipPrototype = this.shipManager.defaultShip;

		// populate genetic algorithm
		this.geneticAlgorithm.populate(this.seed, shipPrototype, 10);

		// first simulation start
		this.startSimulation();
	}

	deinitiate() {
	}

	update(deltaTime) {
		this.timeRunning += deltaTime;
		// simulation update
		this.updateSimulation(deltaTime);
	}

	display() {

		// get center of the best ship
		var bestX = 0.0;
		var bestY = 0.0;
		for (var i = 0; i < this.ships.length; i++) {
			var currX = this.ships[i].nodes[0].x;
			var currY = this.ships[i].nodes[0].y;
			if (currY < bestY) {
				bestX = currX;
				bestY = currY;
			}
		}

		// follow the winner
		translate(width/2 - bestX, height/2 - bestY);

		// display level and ships
		this.level.display();
		for (var i = 0; i < this.ships.length; i++) {
			this.ships[i].display();
		}
	}

	startSimulation() {

		this.timeRunning = 0.0;

		// simulation basics
		this.simulationTimer = 0.0;
		this.simulationDuration = 30.0;
		this.simulationStatus = "on";

		// build level
		this.level = new Level(this.seed);

		// get training genome batch
		var trainingGenomeBatch = this.geneticAlgorithm.getTrainingBatch();

		// spawn ships
		this.ships = [];
		for (var i = 0; i < trainingGenomeBatch.length; i++) {
			var ship = _.cloneDeep(this.geneticAlgorithm.shipPrototype);
			ship.initiate(trainingGenomeBatch[i], this.physicsEngine);
			this.ships.push(ship);
		}

		// Create static colliders for rocks
		for (var i = 0; i < this.level.rocks.length; i++) {
			var rock = this.level.rocks[i];
			this.physicsEngine.staticColliders.push(new StaticCollider(rock.points[0], rock.points[1], rock.points[2], rock.points[3]));
		}
	}

	updateSimulation(deltaTime) {

		// check if playing
		if (this.simulationStatus == "on") {

			// check ending condition
			if (this.simulationTimer > this.simulationDuration) {

				// turn it off
				this.simulationStatus = "off";

				// evaluate and apply
				var results = this.evaluateSimulation();
				this.geneticAlgorithm.applySimulationResults(results);

				// repeat simulation
				this.startSimulation();
			}
			else {
				// update the level
				this.level.update(deltaTime);

				// Update the physics.
				this.physicsEngine.update(deltaTime);

				// Update ships
				for (var i = 0; i < this.ships.length; i++) {
					this.ships[i].update(deltaTime, this.level.rocks);
				}

				// progress timer
				this.simulationTimer += deltaTime;
			}
		}
	}

	evaluateSimulation() {
		// get current ship altitude
		var altitudes = [];
		for (var i = 0; i < this.ships.length; i++) {
			var centerOfMass = this.ships[i].centerOfMass();
			var altitude = centerOfMass.y;
			altitude *= -1.0;
			altitudes.push(altitude);
		}
		// return altitudes
		return altitudes;
	}

	print() {
		return '(Base)';
	}
}
<|endoftext|>


<commit_before>var m = require('mithril');
var getPlayer = require('game').game.getPlayer;

function renderPlayer(data, color) {
  var p = getPlayer(data, color);
  if (p.ai) return 'Stockfish level ' + p.ai;
  return m('a.user_link', {
    href: '/@/' + p.user.username
  }, p.user.username);
}

var advices = [
  ['inaccuracy', 'Inaccuracies', '?!'],
  ['mistake', 'Mistakes', '?'],
  ['blunder', 'Blunders', '??']
];

var cached = false;

module.exports = function(ctrl) {
  var d = ctrl.data;
  if (!d.analysis) return;

  var first = ctrl.vm.mainline[0].eval;
  if (first.cp || first.mate) {
    if (cached) return {
      subtree: 'retain'
    };
    else cached = true;
  }

  return m('div.advice_summary', {
    config: function(el, isUpdate) {
      if (!isUpdate)
        $(el).on('click', 'tr.symbol', function() {
          ctrl.jumpToGlyphSymbol($(this).data('color'), $(this).data('symbol'));
        });
    }
  }, ['white', 'black'].map(function(color) {
    return m('table', [
      m('thead', m('tr', [
        m('td', m('i.is.color-icon.' + color)),
        m('th', renderPlayer(d, color))
      ])),
      m('tbody', [
        advices.map(function(a) {
          var nb = d.analysis[color][a[0]];
          attrs = nb ? {
            class: 'symbol',
            'data-color': color,
            'data-symbol': a[2]
          } : {};
          return m('tr', attrs, [
            m('td', nb),
            m('th', a[1])
          ]);
        }),
        m('tr', [
          m('td', d.analysis[color].acpl),
          m('th', 'Average centipawn loss')
        ])
      ])
    ]);
  }));
};
<commit_msg>fix import analysis<commit_after>var m = require('mithril');
var getPlayer = require('game').game.getPlayer;

function renderPlayer(data, color) {
  var p = getPlayer(data, color);
  if (p.name) return p.name;
  if (p.ai) return 'Stockfish level ' + p.ai;
  return m('a.user_link', {
    href: '/@/' + p.user.username
  }, p.user.username);
}

var advices = [
  ['inaccuracy', 'Inaccuracies', '?!'],
  ['mistake', 'Mistakes', '?'],
  ['blunder', 'Blunders', '??']
];

var cached = false;

module.exports = function(ctrl) {
  var d = ctrl.data;
  if (!d.analysis) return;

  var first = ctrl.vm.mainline[0].eval;
  if (first.cp || first.mate) {
    if (cached) return {
      subtree: 'retain'
    };
    else cached = true;
  }

  return m('div.advice_summary', {
    config: function(el, isUpdate) {
      if (!isUpdate)
        $(el).on('click', 'tr.symbol', function() {
          ctrl.jumpToGlyphSymbol($(this).data('color'), $(this).data('symbol'));
        });
    }
  }, ['white', 'black'].map(function(color) {
    return m('table', [
      m('thead', m('tr', [
        m('td', m('i.is.color-icon.' + color)),
        m('th', renderPlayer(d, color))
      ])),
      m('tbody', [
        advices.map(function(a) {
          var nb = d.analysis[color][a[0]];
          attrs = nb ? {
            class: 'symbol',
            'data-color': color,
            'data-symbol': a[2]
          } : {};
          return m('tr', attrs, [
            m('td', nb),
            m('th', a[1])
          ]);
        }),
        m('tr', [
          m('td', d.analysis[color].acpl),
          m('th', 'Average centipawn loss')
        ])
      ])
    ]);
  }));
};
<|endoftext|>