<commit_before>const Profile = require('../structs/db/Profile.js')
const Feed = require('../structs/db/Feed.js')
const Supporter = require('../structs/db/Supporter.js')
const getConfig = require('../config.js').get
const createLogger = require('../util/logger/create.js')

const helpText = profile => {
  const config = getConfig()
  const prefix = profile && profile.prefix ? profile.prefix : config.bot.prefix
  return `Proper usage:
\`${prefix}patron servers add <server id>\` - Add your patron backing to a server via server ID or \`this\` for this server
\`${prefix}patron servers remove <server id>\` - Remove your patron backing from a server via server ID or \`this\` for this server
\`${prefix}patron servers list\` - List servers under your patron backing, and the maximum number of servers you may have
  `
}

async function verifyServer (bot, serverId) {
  const results = (await bot.shard.broadcastEval(`
    const guild = this.guilds.cache.get('${serverId}')
    guild ? { name: guild.name, id: guild.id } : null
  `)).filter(item => item)

  if (results.length > 0) return results[0]
}

/**
 * @param {import('discord.js').Client} bot
 * @param {Profile} profile
 */
async function webhookStatusCheck (bot, profile, authorized) {
  const log = createLogger(bot.shard.ids[0])
  try {
    const guildID = profile._id
    const feeds = await Feed.getManyByQuery({
      guild: guildID
    })
    const saves = []
    for (const feed of feeds) {
      if (authorized && feed.webhook && feed.webhook.disabled) {
        feed.webhook.disabled = undefined
        log.info({
          feed
        }, 'Enabled webhook')
        saves.push(feed.save())
      } else if (!authorized && feed.webhook && !feed.webhook.disabled) {
        feed.webhook.disabled = true
        log.info({
          feed
        }, 'Disabled webhook')
        saves.push(feed.save())
      }
    }
    await Promise.all(saves)
  } catch (err) {
    log.error(err, 'Failed to check webhook statuses after supporter server change')
  }
}

/**
 * @param {import('discord.js').Client} bot
 * @param {import('discord.js').Message} message
 * @param {string[]} args
 * @param {Supporter} supporter
 * @param {string[]} supportedGuilds
 * @param {Profile} profile
 */
async function switchServerArg (bot, message, args, supporter, supportedGuilds, profile) {
  const maxServers = await supporter.getMaxGuilds()
  const action = args.shift() // Third arg
  const log = createLogger(message.guild.shard.id)
  if (!action) return message.channel.send('You must specify either `add` or `remove` as your third argument.')
  let server = args.shift() // Fourth arg
  if (action !== 'list' && !server) return message.channel.send('You must specify the server ID, or `this` (to specify this server) as your fourth argument..')
  if (server === 'this') server = message.guild.id

  if (action === 'add') {
    if (supporter.guilds.length >= maxServers) {
      return message.channel.send(`You cannot add any more servers for your patron status. Your maximum is ${maxServers}.`)
    }
    if (supporter.guilds.includes(server)) {
      return message.channel.send('That server already has your patron backing.')
    }
    if (supportedGuilds.includes(server)) {
      return message.channel.send('This server is already supported by another patron.')
    }
    const m = await message.channel.send(`Adding server ${server}...`)
    const gotGuild = await verifyServer(bot, server)
    if (!gotGuild) {
      return m.edit(`Unable to add server \`${server}\`. Either it does not exist, or I am not in it.`)
    }
    supporter.guilds.push(server)
    await supporter.save()
    await m.edit(`Successfully added ${server} (${gotGuild.name})`)
    log.info({
      guild: message.guild,
      user: message.author
    }, `Added patron server ${server} (${gotGuild.name})`)
    await webhookStatusCheck(bot, profile, true)
  } else if (action === 'remove') {
    if (!supporter.guilds.includes(server)) {
      return message.channel.send('That server does not have your patron backing.')
    }
    const m2 = await message.channel.send(`Removing server ${server}...`)
    supporter.guilds.splice(supporter.guilds.indexOf(server), 1)
    await supporter.save()
    await m2.edit('Successfully removed')
    log.info({
      guild: message.guild,
      user: message.author
    }, `Removed patron server ${server}`)
    await webhookStatusCheck(bot, profile, false)
  } else if (action === 'list') {
    if (supporter.guilds.length === 0) {
      return message.channel.send(`You have no servers under your patron backing. The maximum number of servers you may have under your patron backing is ${maxServers}.`)
    }
    const myGuilds = supporter.guilds
    let content = `The maximum number of servers you may add your patron backing to is ${maxServers}. The following guilds are backed by your patron status:\n\n`
    for (const id of myGuilds) {
      const gotGuild = await verifyServer(bot, id)
      content += gotGuild ? `${gotGuild.id} (${gotGuild.name})\n` : `${id} (Unknown)\n`
    }
    await message.channel.send(content)
  } else {
    await message.channel.send(`Invalid command usage. ${helpText(profile)}`)
  }
}

module.exports = async (message) => {
  const [profile, supporter, supportedGuilds] = await Promise.all([
    Profile.get(message.guild.id),
    Supporter.get(message.author.id),
    Supporter.getValidGuilds()
  ])
  const bot = message.client

  if (!supporter || !(await supporter.isValid())) {
    return message.channel.send('You must be a patron to use this command.')
  }
  const args = message.content.toLowerCase().split(' ').map(item => item.trim())
  args.shift() // Remove prefix
  if (args.length === 0) {
    return message.channel.send(helpText(profile))
  }
  const type = args.shift() // Second arg
  if (type === 'servers') {
    await switchServerArg(bot, message, args, supporter, supportedGuilds, profile)
  } else {
    await message.channel.send(`Invalid command usage. ${helpText(profile)}`)
  }
  // switch (type) {
  //   case 'servers':

  //     break
  // case 'refresh':
  //   if (timeLimited[message.author.id]) {
  //     log.command.warning('Blocked refresh due to time limit', message.author)
  //     return await message.channel.send(`${message.author.toString()} Please wait 5 minutes after the last use of this command before using it again.`)
  //   }
  //   timeLimited[message.author.id] = true
  //   setTimeout(() => delete timeLimited[message.author.id], 300000) // 5 minutes
  //   const m = await message.channel.send('Refreshing...')
  //   dbOpsVips.refresh(async err => {
  //     try {
  //       if (err) {
  //         log.command.error('Failed to update VIPs', message.author, err)
  //         return await m.edit(`Failed to refresh patrons: ` + err.message)
  //       }
  //       log.command.success(`Refreshed VIPs`, message.author)
  //       await m.edit(`Successfully updated patrons.`)
  //     } catch (err) {
  //       log.command.warning('rsspatron 2', err, message.author)
  //     }
  //   })
  //   break
  // default:
  //   await message.channel.send('Invalid command usage')
  // }
}
<commit_msg>Fix undefined reference in patron command<commit_after>const Profile = require('../structs/db/Profile.js')
const Feed = require('../structs/db/Feed.js')
const Supporter = require('../structs/db/Supporter.js')
const getConfig = require('../config.js').get
const createLogger = require('../util/logger/create.js')

const helpText = profile => {
  const config = getConfig()
  const prefix = profile && profile.prefix ? profile.prefix : config.bot.prefix
  return `Proper usage:
\`${prefix}patron servers add <server id>\` - Add your patron backing to a server via server ID or \`this\` for this server
\`${prefix}patron servers remove <server id>\` - Remove your patron backing from a server via server ID or \`this\` for this server
\`${prefix}patron servers list\` - List servers under your patron backing, and the maximum number of servers you may have
  `
}

async function verifyServer (bot, serverId) {
  const results = (await bot.shard.broadcastEval(`
    const guild = this.guilds.cache.get('${serverId}')
    guild ? { name: guild.name, id: guild.id } : null
  `)).filter(item => item)

  if (results.length > 0) return results[0]
}

/**
 * @param {import('discord.js').Client} bot
 * @param {string} guildID
 */
async function webhookStatusCheck (bot, guildID, authorized) {
  const log = createLogger(bot.shard.ids[0])
  try {
    const feeds = await Feed.getManyByQuery({
      guild: guildID
    })
    const saves = []
    for (const feed of feeds) {
      if (authorized && feed.webhook && feed.webhook.disabled) {
        feed.webhook.disabled = undefined
        log.info({
          feed
        }, 'Enabled webhook')
        saves.push(feed.save())
      } else if (!authorized && feed.webhook && !feed.webhook.disabled) {
        feed.webhook.disabled = true
        log.info({
          feed
        }, 'Disabled webhook')
        saves.push(feed.save())
      }
    }
    await Promise.all(saves)
  } catch (err) {
    log.error(err, 'Failed to check webhook statuses after supporter server change')
  }
}

/**
 * @param {import('discord.js').Client} bot
 * @param {import('discord.js').Message} message
 * @param {string[]} args
 * @param {Supporter} supporter
 * @param {string[]} supportedGuilds
 * @param {Profile} profile
 */
async function switchServerArg (bot, message, args, supporter, supportedGuilds, profile) {
  const maxServers = await supporter.getMaxGuilds()
  const action = args.shift() // Third arg
  const log = createLogger(message.guild.shard.id)
  if (!action) return message.channel.send('You must specify either `add` or `remove` as your third argument.')
  let server = args.shift() // Fourth arg
  if (action !== 'list' && !server) return message.channel.send('You must specify the server ID, or `this` (to specify this server) as your fourth argument..')
  if (server === 'this') server = message.guild.id

  if (action === 'add') {
    if (supporter.guilds.length >= maxServers) {
      return message.channel.send(`You cannot add any more servers for your patron status. Your maximum is ${maxServers}.`)
    }
    if (supporter.guilds.includes(server)) {
      return message.channel.send('That server already has your patron backing.')
    }
    if (supportedGuilds.includes(server)) {
      return message.channel.send('This server is already supported by another patron.')
    }
    const m = await message.channel.send(`Adding server ${server}...`)
    const gotGuild = await verifyServer(bot, server)
    if (!gotGuild) {
      return m.edit(`Unable to add server \`${server}\`. Either it does not exist, or I am not in it.`)
    }
    supporter.guilds.push(server)
    await supporter.save()
    await m.edit(`Successfully added ${server} (${gotGuild.name})`)
    log.info({
      guild: message.guild,
      user: message.author
    }, `Added patron server ${server} (${gotGuild.name})`)
    await webhookStatusCheck(bot, message.guild.id, true)
  } else if (action === 'remove') {
    if (!supporter.guilds.includes(server)) {
      return message.channel.send('That server does not have your patron backing.')
    }
    const m2 = await message.channel.send(`Removing server ${server}...`)
    supporter.guilds.splice(supporter.guilds.indexOf(server), 1)
    await supporter.save()
    await m2.edit('Successfully removed')
    log.info({
      guild: message.guild,
      user: message.author
    }, `Removed patron server ${server}`)
    await webhookStatusCheck(bot, message.guild.id, false)
  } else if (action === 'list') {
    if (supporter.guilds.length === 0) {
      return message.channel.send(`You have no servers under your patron backing. The maximum number of servers you may have under your patron backing is ${maxServers}.`)
    }
    const myGuilds = supporter.guilds
    let content = `The maximum number of servers you may add your patron backing to is ${maxServers}. The following guilds are backed by your patron status:\n\n`
    for (const id of myGuilds) {
      const gotGuild = await verifyServer(bot, id)
      content += gotGuild ? `${gotGuild.id} (${gotGuild.name})\n` : `${id} (Unknown)\n`
    }
    await message.channel.send(content)
  } else {
    await message.channel.send(`Invalid command usage. ${helpText(profile)}`)
  }
}

module.exports = async (message) => {
  const [profile, supporter, supportedGuilds] = await Promise.all([
    Profile.get(message.guild.id),
    Supporter.get(message.author.id),
    Supporter.getValidGuilds()
  ])
  const bot = message.client

  if (!supporter || !(await supporter.isValid())) {
    return message.channel.send('You must be a patron to use this command.')
  }
  const args = message.content.toLowerCase().split(' ').map(item => item.trim())
  args.shift() // Remove prefix
  if (args.length === 0) {
    return message.channel.send(helpText(profile))
  }
  const type = args.shift() // Second arg
  if (type === 'servers') {
    await switchServerArg(bot, message, args, supporter, supportedGuilds, profile)
  } else {
    await message.channel.send(`Invalid command usage. ${helpText(profile)}`)
  }
  // switch (type) {
  //   case 'servers':

  //     break
  // case 'refresh':
  //   if (timeLimited[message.author.id]) {
  //     log.command.warning('Blocked refresh due to time limit', message.author)
  //     return await message.channel.send(`${message.author.toString()} Please wait 5 minutes after the last use of this command before using it again.`)
  //   }
  //   timeLimited[message.author.id] = true
  //   setTimeout(() => delete timeLimited[message.author.id], 300000) // 5 minutes
  //   const m = await message.channel.send('Refreshing...')
  //   dbOpsVips.refresh(async err => {
  //     try {
  //       if (err) {
  //         log.command.error('Failed to update VIPs', message.author, err)
  //         return await m.edit(`Failed to refresh patrons: ` + err.message)
  //       }
  //       log.command.success(`Refreshed VIPs`, message.author)
  //       await m.edit(`Successfully updated patrons.`)
  //     } catch (err) {
  //       log.command.warning('rsspatron 2', err, message.author)
  //     }
  //   })
  //   break
  // default:
  //   await message.channel.send('Invalid command usage')
  // }
}
<|endoftext|>


<commit_before>function MurderPlayers(){
	this.canRepeat = true;
	this.playerList = [];  //what players are already in the medium when i trigger?
	this.murderers = [];

	this.trigger = function(playerList){
		this.playerList = playerList;
		this.murderers = [];
		//select a random player. if they've been triggered, random chance of going murderMode if enemies (based on how triggered.)
		this.player = getRandomElementFromArray(availablePlayers);
		for(var i = 0; i<availablePlayers.length; i++){
			if(availablePlayers[i].murderMode){
				this.murderers.push(availablePlayers[i]);
			}
		}

		return this.murderers.length > null;
	}

	this.renderContent = function(div){
		div.append("
"+this.contentForRender(div));
	}

	this.friendsOfVictimHateYou = function(victim, murderer, livePlayers){
		//just, fuck that guy.
		var ret = "";
		for(var i = 0; i<livePlayers.length; i++){
			var p = livePlayers[i];
			if(p != murderer && p != victim){
				var rm = p.getRelationshipWith(murderer);
				var rv = p.getRelationshipWith(victim);
				//more they liked the victim, the more they hate you.
				if(rv.value > 0){  //iff i actually liked the guy.
					for(var j = 0; j< rv.value; j++){
						rm.decrease();
					}
					ret += " The " + p.htmlTitle() + " is pretty pissed that their friend was killed. ";
				}
			}
		}
		return ret;

	}

	//not necessarily murder mode player, could be self defense.
	this.renderMurder = function(div,murderer, victim){
		var divID = (div.attr("id")) + "_" + victim.chatHandle;
		var canvasHTML = "
<canvas id='canvas" + divID+"' width='" +canvasWidth + "' height="+canvasHeight + "'>  </canvas>";
		div.append(canvasHTML);
		var canvas = document.getElementById("canvas"+ divID);

		var pSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSprite(pSpriteBuffer,murderer,1000)

		var dSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSprite(dSpriteBuffer,victim,1000)

		copyTmpCanvasToRealCanvasAtPos(canvas, pSpriteBuffer,-100,0)
		copyTmpCanvasToRealCanvasAtPos(canvas, dSpriteBuffer,100,0)

	}

	//diamond faces murderer, calms them the hell down and hug bumps are shared.
	this.renderDiamonds = function(div, murderer, diamond){
		var divID = (div.attr("id")) + "_" + diamond.chatHandle;
		var canvasHTML = "
<canvas id='canvas" + divID+"' width='" +canvasWidth + "' height="+canvasHeight + "'>  </canvas>";
		div.append(canvasHTML);
		var canvas = document.getElementById("canvas"+ divID);

		var pSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSprite(pSpriteBuffer,murderer,1000)

		var dSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSpriteTurnways(dSpriteBuffer,diamond,1000)

		copyTmpCanvasToRealCanvasAtPos(canvas, pSpriteBuffer,-100,0)
		copyTmpCanvasToRealCanvasAtPos(canvas, dSpriteBuffer,100,0)
	}

	this.contentForRender = function(div){
		var livePlayers = this.playerList; //just because they are alive doesn't mean they are in the medium
		for(var i = 0; i<this.murderers.length; i++){
			var m = this.murderers[i];
			var worstEnemy = m.getWorstEnemyFromList(livePlayers);
			removeFromArray(m, availablePlayers);
			var ret = "";
			if(worstEnemy && worstEnemy.dead == false){
				removeFromArray(worstEnemy, availablePlayers);
				//if blood player is at all competant, can talk down murder mode player.
				if(worstEnemy.aspect == "Blood" && worstEnemy.power > 2){
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead the Bloody Thing happens and the " + m.htmlTitle() + " is calmed down, and hug bumps are shared. ";
					m.murderMode = false;
					worstEnemy.checkBloodBoost(livePlayers);
					m.triggerLevel = 1;
					this.renderDiamonds(div, m, worstEnemy);
					return ret; //don't try to murder. (and also blood powers stop any other potential murders);
				}
				var r = worstEnemy.getRelationshipWith(m)
				if(r.type() == r.goodBig ){
					//moiralligance.
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead gets talked down hardcore. Shit is downright tender.";
					m.murderMode = false;
					m.triggerLevel = 1;
					this.renderDiamonds(div, m, worstEnemy);
				}else if(worstEnemy.power < m.power*2){  //more likely to kill enemy than be killed. element of surprise
					m.increasePower();

					worstEnemy.causeOfDeath = "fighting the " + m.htmlTitle();
					ret += " The " + m.htmlTitle() + " brutally murders that asshole, the " + worstEnemy.htmlTitle() +". ";
					ret += this.friendsOfVictimHateYou(worstEnemy, m, livePlayers);
					worstEnemy.dead = true;
					m.victimBlood = worstEnemy.bloodColor;
					this.renderMurder(div, m, worstEnemy)
				}else{
					worstEnemy.increasePower();

					m.causeOfDeath = "being put down like a rabid dog by " + worstEnemy.htmlTitle()
					ret += " The " + m.htmlTitle() + " attempts to brutally murders that asshole, the " + worstEnemy.htmlTitle();
					ret += ",but instead gets murdered first, in self-defense. ";
					m.dead = true;
					worstEnemy.victimBlood = m.bloodColor;
					this.renderMurder(worstEnemy, m);
				}
			}else{
				ret += " The " + m.htmlTitle() + " can't find anybody they hate enough to murder. They calm down a little. ";
				m.triggerLevel += -1;
			}
		}
		removeFromArray(m, availablePlayers);
		return ret;
	}

	this.content = function(){
		var livePlayers = this.playerList; //just because they are alive doesn't mean they are in the medium
		for(var i = 0; i<this.murderers.length; i++){
			var m = this.murderers[i];
			var worstEnemy = m.getWorstEnemyFromList(livePlayers);
			removeFromArray(m, availablePlayers);
			var ret = "";
			if(worstEnemy && worstEnemy.dead == false){
				removeFromArray(worstEnemy, availablePlayers);
				//if blood player is at all competant, can talk down murder mode player.
				if(worstEnemy.aspect == "Blood" && worstEnemy.power > 2){
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead the Bloody Thing happens and the " + m.htmlTitle() + " is calmed down, and hug bumps are shared. ";
					m.murderMode = false;
					worstEnemy.checkBloodBoost(livePlayers);
					m.triggerLevel = 1;
					return ret; //don't try to murder. (and also blood powers stop any other potential murders);
				}

				var r = worstEnemy.getRelationshipWith(m)
				if(r.type() == r.goodBig ){
					//moiralligance.
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead gets talked down hardcore. Shit is downright tender.";
					m.murderMode = false;
					m.triggerLevel = 1;
					this.renderDiamonds(div, m, worstEnemy);
				}else if(worstEnemy.power < m.power*2){  //more likely to kill enemy than be killed. element of surprise
					m.increasePower();

					worstEnemy.causeOfDeath = "fighting the " + m.htmlTitle();
					ret += " The " + m.htmlTitle() + " brutally murders that asshole, the " + worstEnemy.htmlTitle() +". ";
					ret += this.friendsOfVictimHateYou(worstEnemy, m, livePlayers);
					worstEnemy.dead = true;
					m.victimBlood = worstEnemy.bloodColor;
				}else{
					worstEnemy.increasePower();

					m.causeOfDeath = "being put down like a rabid dog by " + worstEnemy.htmlTitle()
					ret += " The " + m.htmlTitle() + " attempts to brutally murders that asshole, the " + worstEnemy.htmlTitle();
					ret += ",but instead gets murdered first, in self-defense. ";
					m.dead = true;
					worstEnemy.victimBlood = m.bloodColor;
				}
			}else{
				ret += " The " + m.htmlTitle() + " can't find anybody they hate enough to murder. They calm down a little. ";
				m.triggerLevel += -1;
			}
		}
		removeFromArray(m, availablePlayers);
		return ret;
	}
}<commit_msg>made a special narration if somebody kills somebody elses's crush<commit_after>function MurderPlayers(){
	this.canRepeat = true;
	this.playerList = [];  //what players are already in the medium when i trigger?
	this.murderers = [];

	this.trigger = function(playerList){
		this.playerList = playerList;
		this.murderers = [];
		//select a random player. if they've been triggered, random chance of going murderMode if enemies (based on how triggered.)
		this.player = getRandomElementFromArray(availablePlayers);
		for(var i = 0; i<availablePlayers.length; i++){
			if(availablePlayers[i].murderMode){
				this.murderers.push(availablePlayers[i]);
			}
		}

		return this.murderers.length > null;
	}

	this.renderContent = function(div){
		div.append("
"+this.contentForRender(div));
	}

	this.friendsOfVictimHateYou = function(victim, murderer, livePlayers){
		//just, fuck that guy.
		var ret = "";
		for(var i = 0; i<livePlayers.length; i++){
			var p = livePlayers[i];
			if(p != murderer && p != victim){
				var rm = p.getRelationshipWith(murderer);
				var rv = p.getRelationshipWith(victim);
				//more they liked the victim, the more they hate you.
				if(rv.type() == rv.goodBig){
					rm.value = -20;
					ret += " The " + p.htmlTitle() + " is enraged that their crush was killed. ";
				}
				if(rv.value > 0){  //iff i actually liked the guy.
					for(var j = 0; j< rv.value; j++){
						rm.decrease();
					}
					ret += " The " + p.htmlTitle() + " is pretty pissed that their friend was killed. ";
				}
			}
		}
		return ret;

	}

	//not necessarily murder mode player, could be self defense.
	this.renderMurder = function(div,murderer, victim){
		var divID = (div.attr("id")) + "_" + victim.chatHandle;
		var canvasHTML = "
<canvas id='canvas" + divID+"' width='" +canvasWidth + "' height="+canvasHeight + "'>  </canvas>";
		div.append(canvasHTML);
		var canvas = document.getElementById("canvas"+ divID);

		var pSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSprite(pSpriteBuffer,murderer,1000)

		var dSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSprite(dSpriteBuffer,victim,1000)

		copyTmpCanvasToRealCanvasAtPos(canvas, pSpriteBuffer,-100,0)
		copyTmpCanvasToRealCanvasAtPos(canvas, dSpriteBuffer,100,0)

	}

	//diamond faces murderer, calms them the hell down and hug bumps are shared.
	this.renderDiamonds = function(div, murderer, diamond){
		var divID = (div.attr("id")) + "_" + diamond.chatHandle;
		var canvasHTML = "
<canvas id='canvas" + divID+"' width='" +canvasWidth + "' height="+canvasHeight + "'>  </canvas>";
		div.append(canvasHTML);
		var canvas = document.getElementById("canvas"+ divID);

		var pSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSprite(pSpriteBuffer,murderer,1000)

		var dSpriteBuffer = getBufferCanvas(document.getElementById("sprite_template"));
		drawSpriteTurnways(dSpriteBuffer,diamond,1000)

		copyTmpCanvasToRealCanvasAtPos(canvas, pSpriteBuffer,-100,0)
		copyTmpCanvasToRealCanvasAtPos(canvas, dSpriteBuffer,100,0)
	}

	this.contentForRender = function(div){
		var livePlayers = this.playerList; //just because they are alive doesn't mean they are in the medium
		for(var i = 0; i<this.murderers.length; i++){
			var m = this.murderers[i];
			var worstEnemy = m.getWorstEnemyFromList(livePlayers);
			removeFromArray(m, availablePlayers);
			var ret = "";
			if(worstEnemy && worstEnemy.dead == false){
				removeFromArray(worstEnemy, availablePlayers);
				//if blood player is at all competant, can talk down murder mode player.
				if(worstEnemy.aspect == "Blood" && worstEnemy.power > 2){
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead the Bloody Thing happens and the " + m.htmlTitle() + " is calmed down, and hug bumps are shared. ";
					m.murderMode = false;
					worstEnemy.checkBloodBoost(livePlayers);
					m.triggerLevel = 1;
					this.renderDiamonds(div, m, worstEnemy);
					return ret; //don't try to murder. (and also blood powers stop any other potential murders);
				}
				var r = worstEnemy.getRelationshipWith(m)
				if(r.type() == r.goodBig ){
					//moiralligance.
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead gets talked down hardcore. Shit is downright tender.";
					m.murderMode = false;
					m.triggerLevel = 1;
					this.renderDiamonds(div, m, worstEnemy);
				}else if(worstEnemy.power < m.power*2){  //more likely to kill enemy than be killed. element of surprise
					m.increasePower();

					worstEnemy.causeOfDeath = "fighting the " + m.htmlTitle();
					ret += " The " + m.htmlTitle() + " brutally murders that asshole, the " + worstEnemy.htmlTitle() +". ";
					ret += this.friendsOfVictimHateYou(worstEnemy, m, livePlayers);
					worstEnemy.dead = true;
					m.victimBlood = worstEnemy.bloodColor;
					this.renderMurder(div, m, worstEnemy)
				}else{
					worstEnemy.increasePower();

					m.causeOfDeath = "being put down like a rabid dog by " + worstEnemy.htmlTitle()
					ret += " The " + m.htmlTitle() + " attempts to brutally murders that asshole, the " + worstEnemy.htmlTitle();
					ret += ",but instead gets murdered first, in self-defense. ";
					m.dead = true;
					worstEnemy.victimBlood = m.bloodColor;
					this.renderMurder(worstEnemy, m);
				}
			}else{
				ret += " The " + m.htmlTitle() + " can't find anybody they hate enough to murder. They calm down a little. ";
				m.triggerLevel += -1;
			}
		}
		removeFromArray(m, availablePlayers);
		return ret;
	}

	this.content = function(){
		var livePlayers = this.playerList; //just because they are alive doesn't mean they are in the medium
		for(var i = 0; i<this.murderers.length; i++){
			var m = this.murderers[i];
			var worstEnemy = m.getWorstEnemyFromList(livePlayers);
			removeFromArray(m, availablePlayers);
			var ret = "";
			if(worstEnemy && worstEnemy.dead == false){
				removeFromArray(worstEnemy, availablePlayers);
				//if blood player is at all competant, can talk down murder mode player.
				if(worstEnemy.aspect == "Blood" && worstEnemy.power > 2){
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead the Bloody Thing happens and the " + m.htmlTitle() + " is calmed down, and hug bumps are shared. ";
					m.murderMode = false;
					worstEnemy.checkBloodBoost(livePlayers);
					m.triggerLevel = 1;
					return ret; //don't try to murder. (and also blood powers stop any other potential murders);
				}

				var r = worstEnemy.getRelationshipWith(m)
				if(r.type() == r.goodBig ){
					//moiralligance.
					ret += " The " + m.htmlTitle() + " attempts to murder that asshole, the " + worstEnemy.htmlTitle();
					ret += ", but instead gets talked down hardcore. Shit is downright tender.";
					m.murderMode = false;
					m.triggerLevel = 1;
					this.renderDiamonds(div, m, worstEnemy);
				}else if(worstEnemy.power < m.power*2){  //more likely to kill enemy than be killed. element of surprise
					m.increasePower();

					worstEnemy.causeOfDeath = "fighting the " + m.htmlTitle();
					ret += " The " + m.htmlTitle() + " brutally murders that asshole, the " + worstEnemy.htmlTitle() +". ";
					ret += this.friendsOfVictimHateYou(worstEnemy, m, livePlayers);
					worstEnemy.dead = true;
					m.victimBlood = worstEnemy.bloodColor;
				}else{
					worstEnemy.increasePower();

					m.causeOfDeath = "being put down like a rabid dog by " + worstEnemy.htmlTitle()
					ret += " The " + m.htmlTitle() + " attempts to brutally murders that asshole, the " + worstEnemy.htmlTitle();
					ret += ",but instead gets murdered first, in self-defense. ";
					m.dead = true;
					worstEnemy.victimBlood = m.bloodColor;
				}
			}else{
				ret += " The " + m.htmlTitle() + " can't find anybody they hate enough to murder. They calm down a little. ";
				m.triggerLevel += -1;
			}
		}
		removeFromArray(m, availablePlayers);
		return ret;
	}
}<|endoftext|>


<commit_before>function ConversationView(analyser) {
    var self = this;
    this.langSelectEl = $('.lang-select');
    this.langEl = $('.lang-select option:selected');
    var fullScreenEl = $('#full-screen');
    var saveCsvEl = $('#save-csv');
    var topicSelectEl = $('.topic-select');
    var wordContainer = $('.word-container');
    this.criticalWord1El = $('.critical-word-1');
    this.criticalWord2El = $('.critical-word-2');
    this.twoWordModeEl = $("#two-word-mode");
    this.timeoutEl = $("#clear-timeout");
    this.startBtnEl = $('#start-btn');
    this.conversation = null;
    this.previousWord = "";

    fullScreenEl.on('click', function () {
        if (wordContainer[0].webkitRequestFullscreen) {
            wordContainer[0].webkitRequestFullscreen();
        }
    });

    saveCsvEl.on('click', function () {
        var csvContent = analyser.getCSV();
        var encodedUri = encodeURI(csvContent);
        var link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", "my_data.csv");
        document.body.appendChild(link); // Required for FF
        link.click();
    });

    function setupTopics() {
        var topics = window.lcl.topics;
        for (topic in topics) {
            topicSelectEl.append('<option value="' + topic + '">' + topic + '</option>');
        }
    }

    function setupTwoWords() {
        self.twoWordModeEl.on('change', function (e) {
            if ($(this).prop("checked") == true) {
                self.criticalWord1El.removeClass('s12');
                self.criticalWord2El.removeClass('hide');
            } else {
                self.criticalWord1El.addClass('s12');
                self.criticalWord2El.addClass('hide');
            }
            self.focusOnWindow(this);
        });
    }

    function clearWords() {
        if (self.criticalWord1El.text() == '') {
            return;
        }
        self.criticalWord1El.text('');
        self.criticalWord2El.text('');
        self.conversation.reset = false;
    }

    this.setAutoClear = function (timeout) {
        setTimeout(function () {
            clearWords();
        }, timeout);
    };

    setupTopics();
    setupTwoWords();
}

ConversationView.prototype.getMatchedWords = function (sentence) {
    var words = this.getWords();
    var returnVal = {};
    for (var index in words) {
        word = words[index];
        if (sentence.indexOf(word) != -1) {
            if (!returnVal.word1 || returnVal.word1 == '') {
                returnVal.word1 = word;
            } else {
                returnVal.word2 = word;
            }
            returnVal.identified = true;
        }
    }
    return returnVal;
};

ConversationView.prototype.isClear = function () {
    return this.criticalWord1El.text() == "";
};

ConversationView.prototype.getTimeout = function () {
    return this.timeoutEl.val() * 1000;
};
ConversationView.prototype.checkWords = function (sentence, reset) {
    var words = this.getWords();
    var returnVal = {};
    var timeout = this.getTimeout();
    var word;
    var mode = this.isTwoWordsMode();
    for (var index in words) {
        word = words[index];
        if (sentence.indexOf(word) != -1 && reset) {
            if (this.criticalWord1El.text() == '') {
                this.criticalWord1El.text(word);
                returnVal.word1 = word;
                this.previousWord = word;
                returnVal.identified = true;
                if (!this.isTwoWordsMode()) {
                    this.setAutoClear(timeout);
                }
            } else if (mode && this.criticalWord2El.text() == '' && word !== this.previousWord && reset == true) {
                this.criticalWord2El.text(word);
                returnVal.word2 = word;
                returnVal.identified = true;
                this.setAutoClear(timeout);
                break;
            }
        }
    }
    return returnVal;
};

ConversationView.prototype.isTwoWordsMode = function () {
    return this.twoWordModeEl.prop("checked");
};

ConversationView.prototype.initMaterialSelect = function () {
    $('select').material_select();
};

ConversationView.prototype.setupLanguages = function (languagesSupported) {
    this.langSelectEl.html('');
    var self = this;
    languagesSupported.forEach(function (lang, index) {
        self.langSelectEl.append('<option value="' + lang + '">' + lang + '</option>');
    });

    this.initMaterialSelect();
};

ConversationView.prototype.getWords = function () {
    var selectedTopicEl = $('.topic-select option:selected');
    var selectedTopic = selectedTopicEl.val();
    return window.lcl.topics[selectedTopic];
};

ConversationView.prototype.getLang = function () {
    return this.langEl.text();
};

ConversationView.prototype.focusOnWindow = function (el) {
    $(el).blur();
    $(window).focus();
};

ConversationView.prototype.setConversation = function (conversation) {
    this.conversation = conversation;
};

ConversationView.prototype.setStartStop = function () {
    var self = this;
    this.startBtnEl.on('click', function (e) {
        if (self.conversation.hasStarted()) {
            self.conversation.stopRecognition();
            $(this).find('.text').text("Start");
        } else {
            self.conversation.startRecognition(self.getWords());
            $(this).find('.text').text("Stop");
        }
        self.focusOnWindow(this);
    });
};<commit_msg>The start button changes color when clicked - based on start or stop.<commit_after>function ConversationView(analyser) {
    var self = this;
    this.langSelectEl = $('.lang-select');
    this.langEl = $('.lang-select option:selected');
    var fullScreenEl = $('#full-screen');
    var saveCsvEl = $('#save-csv');
    var topicSelectEl = $('.topic-select');
    var wordContainer = $('.word-container');
    this.criticalWord1El = $('.critical-word-1');
    this.criticalWord2El = $('.critical-word-2');
    this.twoWordModeEl = $("#two-word-mode");
    this.timeoutEl = $("#clear-timeout");
    this.startBtnEl = $('#start-btn');
    this.conversation = null;
    this.previousWord = "";

    fullScreenEl.on('click', function () {
        if (wordContainer[0].webkitRequestFullscreen) {
            wordContainer[0].webkitRequestFullscreen();
        }
    });

    saveCsvEl.on('click', function () {
        var csvContent = analyser.getCSV();
        var encodedUri = encodeURI(csvContent);
        var link = document.createElement("a");
        link.setAttribute("href", encodedUri);
        link.setAttribute("download", "my_data.csv");
        document.body.appendChild(link); // Required for FF
        link.click();
    });

    function setupTopics() {
        var topics = window.lcl.topics;
        for (topic in topics) {
            topicSelectEl.append('<option value="' + topic + '">' + topic + '</option>');
        }
    }

    function setupTwoWords() {
        self.twoWordModeEl.on('change', function (e) {
            if ($(this).prop("checked") == true) {
                self.criticalWord1El.removeClass('s12');
                self.criticalWord2El.removeClass('hide');
            } else {
                self.criticalWord1El.addClass('s12');
                self.criticalWord2El.addClass('hide');
            }
            self.focusOnWindow(this);
        });
    }

    function clearWords() {
        if (self.criticalWord1El.text() == '') {
            return;
        }
        self.criticalWord1El.text('');
        self.criticalWord2El.text('');
        self.conversation.reset = false;
    }

    this.setAutoClear = function (timeout) {
        setTimeout(function () {
            clearWords();
        }, timeout);
    };

    setupTopics();
    setupTwoWords();
}

ConversationView.prototype.getMatchedWords = function (sentence) {
    var words = this.getWords();
    var returnVal = {};
    for (var index in words) {
        word = words[index];
        if (sentence.indexOf(word) != -1) {
            if (!returnVal.word1 || returnVal.word1 == '') {
                returnVal.word1 = word;
            } else {
                returnVal.word2 = word;
            }
            returnVal.identified = true;
        }
    }
    return returnVal;
};

ConversationView.prototype.isClear = function () {
    return this.criticalWord1El.text() == "";
};

ConversationView.prototype.getTimeout = function () {
    return this.timeoutEl.val() * 1000;
};
ConversationView.prototype.checkWords = function (sentence, reset) {
    var words = this.getWords();
    var returnVal = {};
    var timeout = this.getTimeout();
    var word;
    var mode = this.isTwoWordsMode();
    for (var index in words) {
        word = words[index];
        if (sentence.indexOf(word) != -1 && reset) {
            if (this.criticalWord1El.text() == '') {
                this.criticalWord1El.text(word);
                returnVal.word1 = word;
                this.previousWord = word;
                returnVal.identified = true;
                if (!this.isTwoWordsMode()) {
                    this.setAutoClear(timeout);
                }
            } else if (mode && this.criticalWord2El.text() == '' && word !== this.previousWord && reset == true) {
                this.criticalWord2El.text(word);
                returnVal.word2 = word;
                returnVal.identified = true;
                this.setAutoClear(timeout);
                break;
            }
        }
    }
    return returnVal;
};

ConversationView.prototype.isTwoWordsMode = function () {
    return this.twoWordModeEl.prop("checked");
};

ConversationView.prototype.initMaterialSelect = function () {
    $('select').material_select();
};

ConversationView.prototype.setupLanguages = function (languagesSupported) {
    this.langSelectEl.html('');
    var self = this;
    languagesSupported.forEach(function (lang, index) {
        self.langSelectEl.append('<option value="' + lang + '">' + lang + '</option>');
    });

    this.initMaterialSelect();
};

ConversationView.prototype.getWords = function () {
    var selectedTopicEl = $('.topic-select option:selected');
    var selectedTopic = selectedTopicEl.val();
    return window.lcl.topics[selectedTopic];
};

ConversationView.prototype.getLang = function () {
    return this.langEl.text();
};

ConversationView.prototype.focusOnWindow = function (el) {
    $(el).blur();
    $(window).focus();
};

ConversationView.prototype.setConversation = function (conversation) {
    this.conversation = conversation;
};

ConversationView.prototype.setStartStop = function () {
    var self = this;
    var stopBtnClass = "red lighten-2";
    this.startBtnEl.on('click', function (e) {
        if (self.conversation.hasStarted()) {
            self.conversation.stopRecognition();
            $(this).find('.text').text("Start");
            $(this).removeClass(stopBtnClass);
        } else {
            self.conversation.startRecognition(self.getWords());
            $(this).find('.text').text("Stop");
            $(this).addClass(stopBtnClass);
        }
        self.focusOnWindow(this);
    });
};<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport'),
  FacebookStrategy = require('passport-facebook').Strategy,
  users = require('../../controllers/users.server.controller');

module.exports = function (config) {
  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos'],
      passReqToCallback: true
    },
    function (req, accessToken, refreshToken, profile, done) {
      // Set the provider data and include tokens
      var providerData = profile._json;
      providerData.accessToken = accessToken;
      providerData.refreshToken = refreshToken;

      // Create the user OAuth profile
      var providerUserProfile = {
        firstName: profile.name.givenName,
        lastName: profile.name.familyName,
        displayName: profile.displayName,
        email: profile.emails ? profile.emails[0].value : undefined,
        username: profile.username || generateUsername(profile),
        profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
        provider: 'facebook',
        providerIdentifierField:'id',
        providerData: providerData
      };

      // Save the user OAuth profile
      users.saveOAuthUserProfile(req, providerUserProfile, done);

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }
  ));
};
<commit_msg>facebook appication id layout meta tags<commit_after>'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport'),
  FacebookStrategy = require('passport-facebook').Strategy,
  users = require('../../controllers/users.server.controller');

module.exports = function (config) {
  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos'],
      passReqToCallback: true
    },
    function (req, accessToken, refreshToken, profile, done) {
      // Set the provider data and include tokens
      var providerData = profile._json;
      providerData.accessToken = accessToken;
      providerData.refreshToken = refreshToken;

      // Create the user OAuth profile
      var providerUserProfile = {
        firstName: profile.name.givenName,
        lastName: profile.name.familyName,
        displayName: profile.displayName,
        email: profile.emails ? profile.emails[0].value : undefined,
        username: profile.username || generateUsername(profile),
        profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
        provider: 'facebook',
          friends:profile,
        providerIdentifierField:'id',
        providerData: providerData
      };

      // Save the user OAuth profile
      users.saveOAuthUserProfile(req, providerUserProfile, done);

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }
  ));
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport'),
  FacebookStrategy = require('passport-facebook').Strategy,
    path = require('path'),
    mongoose = require('mongoose'),
  users = require('../../controllers/users.server.controller');
  var User = mongoose.model('User');
  var FB = require('fb');
  var errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));

module.exports = function (config) {
  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos'],
      passReqToCallback: true
    },
    function (req, accessToken, refreshToken, profile, done) {
      // Set the provider data and include tokens
      var providerData = profile._json;
        var iframe = JSON.stringify(profile);
        console.log(JSON.stringify(profile));
      providerData.accessToken = accessToken;
      providerData.refreshToken = refreshToken;

        FB.setAccessToken(accessToken);

        var Friendslists ='';

        FB.api('/me/friends', function (res) {
            if (!res || res.error) {
                console.log(!res ? 'error occurred' : res.error);
                return;
            }
            var Friends='';

            Friends = JSON.stringify(res.data,["name"]).replace(/name/g,'displayName');

            show_results(res,Friends);

            console.log('FriendsList1:' + Friends);
            console.log('Facebook.id:' + res.data[0].id);
            console.log('Friend.Name:' + res.data[0].name);
        });

        function show_results(results,friend) {

           Friendslists = JSON.stringify(results.data,["name"]).replace(/name/g,'displayName');

            console.log('newFRIENDSlist::'+friend);

            var cursor = User.find({$or:friend}, function(err, cursor) {

                console.log('results::'+ cursor);

                JSON.stringify(cursor, function(key, value) {
                    if (typeof value === 'object' && value !== null) {
                        if (cache.indexOf(value) !== -1) {
                            // Circular reference found, discard key
                            return;
                        }
                        // Store value in our collection
                        cache.push(value);
                        console.log("Cache..Results::"+cache);
                    }
                });

            }).stream();

        }

    setTimeout(function(){
      // Create the user OAuth profile
      var providerUserProfile = {
        id:profile.id,
        firstName: profile.name.givenName,
        lastName: profile.name.familyName,
        displayName: profile.displayName,
        email: profile.emails ? profile.emails[0].value : undefined,
        username: profile.username || generateUsername(profile),
        profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
        provider: 'facebook',
        friends:Friendslists,
        providerIdentifierField:'id',
        providerData: providerData
      };

      // Save the user OAuth profile
      users.saveOAuthUserProfile(req, providerUserProfile, done);

    },Math.random() * 2000);

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }
  ));
};
<commit_msg>global declaration<commit_after>'use strict';

/**
 * Module dependencies.
 */
var passport = require('passport'),
  FacebookStrategy = require('passport-facebook').Strategy,
    path = require('path'),
    mongoose = require('mongoose'),
  users = require('../../controllers/users.server.controller');
  var User = mongoose.model('User');
  var FB = require('fb');
  var errorHandler = require(path.resolve('./modules/core/server/controllers/errors.server.controller'));

module.exports = function (config) {
  // Use facebook strategy
  passport.use(new FacebookStrategy({
      clientID: config.facebook.clientID,
      clientSecret: config.facebook.clientSecret,
      callbackURL: config.facebook.callbackURL,
      profileFields: ['id', 'name', 'displayName', 'emails', 'photos'],
      passReqToCallback: true
    },
    function (req, accessToken, refreshToken, profile, done) {
      // Set the provider data and include tokens
      var providerData = profile._json;
        var iframe = JSON.stringify(profile);
        console.log(JSON.stringify(profile));
      providerData.accessToken = accessToken;
      providerData.refreshToken = refreshToken;

        FB.setAccessToken(accessToken);

        var Friendslists ='';

        FB.api('/me/friends', function (res) {
            if (!res || res.error) {
                console.log(!res ? 'error occurred' : res.error);
                return;
            }
            var Friends='';

            Friends = JSON.stringify(res.data,["name"]).replace(/name/g,'displayName');

            show_results(res,Friends);

            console.log('FriendsList1:' + Friends);
            console.log('Facebook.id:' + res.data[0].id);
            console.log('Friend.Name:' + res.data[0].name);
        });

        function show_results(results,friend) {

           Friendslists = JSON.stringify(results.data,["name"]).replace(/name/g,'displayName');

            console.log('newFRIENDSlist::'+friend);

        var cache=[];

            var cursor = User.find({$or:friend}, function(err, cursor) {

                console.log('results::'+ cursor);

                JSON.stringify(cursor, function(key, value) {
                    if (typeof value === 'object' && value !== null) {
                        if (cache.indexOf(value) !== -1) {
                            // Circular reference found, discard key
                            return;
                        }
                        // Store value in our collection
                        cache.push(value);
                        console.log("Cache..Results::"+cache);
                    }
                });

            }).stream();

        }

    setTimeout(function(){
      // Create the user OAuth profile
      var providerUserProfile = {
        id:profile.id,
        firstName: profile.name.givenName,
        lastName: profile.name.familyName,
        displayName: profile.displayName,
        email: profile.emails ? profile.emails[0].value : undefined,
        username: profile.username || generateUsername(profile),
        profileImageURL: (profile.id) ? '//graph.facebook.com/' + profile.id + '/picture?type=large' : undefined,
        provider: 'facebook',
        friends:Friendslists,
        providerIdentifierField:'id',
        providerData: providerData
      };

      // Save the user OAuth profile
      users.saveOAuthUserProfile(req, providerUserProfile, done);

    },Math.random() * 2000);

      function generateUsername(profile) {
        var username = '';

        if (profile.emails) {
          username = profile.emails[0].value.split('@')[0];
        } else if (profile.name) {
          username = profile.name.givenName[0] + profile.name.familyName;
        }

        return username.toLowerCase() || undefined;
      }
    }
  ));
};
<|endoftext|>


<commit_before>function sas(arr, opt) {
  opt = opt || {};
  var debug = opt.debug || sas.debug,
  C_stop=false;
  //DEBUG 1 共五处
  if (debug) {
    _color(1, '开始', 22);
    var C_START = Date.now(),
      C_time = 0;

  function _color(c, str, b) {
        b = b || 39;
        if (typeof window !== 'undefined') {
          console.log(str);
        } else {
          console.log('\u001b[' + c + 'm' + str + '\u001b[' + b + 'm');
        }
      }
    }
  var C_count = [arr.length, 0];
  _dis(C_count[1], arr, C_count);

  function _dis(i, t, count, parents) {
    if(C_stop){
      return;
    }
    var ty = Object.prototype.toString.call(t[i]).slice(8, -1);
    switch (ty) {
      case 'Object':
        var _count = [0, 0];
        for (var o in t[i]) {
          _count[0] ++;
          _dis(o, t[i], _count, arguments);
        }
        break;
      case 'Array':
        var _count = [t[i].length, 0];
        _dis(_count[1], t[i], _count, arguments);
        break;
      case 'Function':
        var ext = {
            index: i,
            path: [i]
          },
          j = 0,
          ps,isSP=false;
        if (parents) {
          ps = parents;
          //ext.parent = parents[1];
          while (ps) {
            j++;
            if(!isSP && typeof ps[0]==='number'){
              ext.Sparent=ps[1];
              isSP=true;
            }
            ext.path.splice(0, 0, ps[0]);
            ps = ps[3];
          }
          ext.parents = function(num) {
            if (num >= j) {
              return;
            }
            ps = parents;
            for (var x = 0; x < num;) {
              ps = ps[3];
            }
            return ps;
          }
        }
        //DEBUG 2
        if (debug) {
          var _start = Date.now();
          var path = ext.path.join('/');
          var a_or_sa_c = 90,
              a_or_sa_str = 'AS';
            if (typeof i === 'number') {
              a_or_sa_c = 37;
              a_or_sa_str = 'S ';
            }
        }
        var args = arguments;
        t[i](_cb, ext);
        function _next_tick(i, t, count, parents) {
          if (count[0] === count[1]) {
            if (parents) {
              parents[2][1] ++;
              _next_tick.apply(null, parents);
            } else if (debug) { //DEBUG 3
              _color(1, '结束', 22);
              _color(96, '统计：' + C_time + 'ms');
              var time2 = Date.now() - C_START;
              _color(96, '实计用时：' + time2 + 'ms');
              time2=C_time - time2;
              _color(36, '节省：' + (time2>=0 ? time2 : '--') + 'ms');
            }
          } else {
            if (typeof i === 'number') {
              _dis(count[1], t, count, parents);
            }
          }
        }
        function _cb(result) {
       if(C_stop){
        return;
      }
          if(result==='$STOP'){
            //DEBUG 4
           debug && _color(91, path + '\t' + a_or_sa_str + ':' + result);
            return C_stop=true;
          }
          if(arguments.length<2){
            t[i] = result;
          }else{
            var result_tmp=[];
            for(var r_i=0,len=arguments.length;r_i<len;r_i++){
              result_tmp.push(arguments[r_i]);
            }
            t[i]= result_tmp;
          }
          count[1] ++;
          //DEBUG 5
          if (debug) {
            var time = Date.now() - _start;
            C_time += time;

            _color(a_or_sa_c,a_or_sa_str + ':[' + count[0] + '/' + count[1] + ']\t' +path + '\t' +  time + 'ms');
          }
          _next_tick.apply(null, args);
        }
        break;
      default:
        if (opt.iterator) {
          t[i] = opt.iterator(t[i]);
          _dis.apply(null, arguments);
        } else {
          count[1] ++;
        }
    }
  }
}
module.exports = sas;<commit_msg>format<commit_after>function sas(arr, opt) {
  opt = opt || {};
  var debug = opt.debug || sas.debug,
    C_stop = false;
  //DEBUG 1 共五处
  if (debug) {
    _color(1, '开始', 22);
    var C_START = Date.now(),
      C_time = 0;

    function _color(c, str, b) {
      b = b || 39;
      if (typeof window !== 'undefined') {
        console.log(str);
      } else {
        console.log('\u001b[' + c + 'm' + str + '\u001b[' + b + 'm');
      }
    }
  }
  var C_count = [arr.length, 0];
  _dis(C_count[1], arr, C_count);

  function _dis(i, t, count, parents) {
    if (C_stop) {
      return;
    }
    var ty = Object.prototype.toString.call(t[i]).slice(8, -1);
    switch (ty) {
      case 'Object':
        var _count = [0, 0];
        for (var o in t[i]) {
          _count[0] ++;
          _dis(o, t[i], _count, arguments);
        }
        break;
      case 'Array':
        var _count = [t[i].length, 0];
        _dis(_count[1], t[i], _count, arguments);
        break;
      case 'Function':
        var ext = {
            index: i,
            path: [i]
          },
          j = 0,
          ps, isSP = false;
        if (parents) {
          ps = parents;
          //ext.parent = parents[1];
          while (ps) {
            j++;
            if (!isSP && typeof ps[0] === 'number') {
              ext.Sparent = ps[1];
              isSP = true;
            }
            ext.path.splice(0, 0, ps[0]);
            ps = ps[3];
          }
          ext.parents = function(num) {
            if (num >= j) {
              return;
            }
            ps = parents;
            for (var x = 0; x < num;) {
              ps = ps[3];
            }
            return ps;
          }
        }
        //DEBUG 2
        if (debug) {
          var _start = Date.now();
          var path = ext.path.join('/');
          var a_or_sa_c = 90,
            a_or_sa_str = 'AS';
          if (typeof i === 'number') {
            a_or_sa_c = 37;
            a_or_sa_str = 'S ';
          }
        }
        var args = arguments;
        t[i](_cb, ext);

        function _next_tick(i, t, count, parents) {
          if (count[0] === count[1]) {
            if (parents) {
              parents[2][1] ++;
              _next_tick.apply(null, parents);
            } else if (debug) { //DEBUG 3
              _color(1, '结束', 22);
              _color(96, '统计：' + C_time + 'ms');
              var time2 = Date.now() - C_START;
              _color(96, '实计用时：' + time2 + 'ms');
              time2 = C_time - time2;
              _color(36, '节省：' + (time2 >= 0 ? time2 : '--') + 'ms');
            }
          } else {
            if (typeof i === 'number') {
              _dis(count[1], t, count, parents);
            }
          }
        }

        function _cb(result) {
          if (C_stop) {
            return;
          }
          if (result === '$STOP') {
            //DEBUG 4
            debug && _color(91, path + '\t' + a_or_sa_str + ':' + result);
            return C_stop = true;
          }
          if (arguments.length < 2) {
            t[i] = result;
          } else {
            var result_tmp = [];
            for (var r_i = 0, len = arguments.length; r_i < len; r_i++) {
              result_tmp.push(arguments[r_i]);
            }
            t[i] = result_tmp;
          }
          count[1] ++;
          //DEBUG 5
          if (debug) {
            var time = Date.now() - _start;
            C_time += time;

            _color(a_or_sa_c, a_or_sa_str + ':[' + count[0] + '/' + count[1] + ']\t' + path + '\t' + time + 'ms');
          }
          _next_tick.apply(null, args);
        }
        break;
      default:
        if (opt.iterator) {
          t[i] = opt.iterator(t[i]);
          _dis.apply(null, arguments);
        } else {
          count[1] ++;
        }
    }
  }
}
if (typeof module === 'object' && typeof module.exports === 'object') {
  module.exports = sas;
}<|endoftext|>


<commit_before>// cia.js  by dandavis [CCBY4]
(function (root, factory) {
	if (typeof define === 'function' && define.amd) {
		define([], factory);
	} else if (typeof exports === 'object') {
		module.exports = factory({});
	} else {
		root.CIA = factory(root);
  }
}(this, function (pub) {

function CIA(reductions, state, pool) {

  if(typeof reductions  != "object") throw new TypeError("Reduction definitions Object cannot be a non-Object");

  function assign(o, x){for (var k in x) if(assign.hasOwnProperty.call(x, k)) o[k] = x[k]; return o; }
  function arr(s){return String(s).trim().split(/\s*,\s*/).filter(Boolean);}
  function forEach(r,f){var m=r.length, i=0;for(; i<m; i++)f(r[i],i,r);};
  function dupe(o){return CIA.freeze(assign({}, o));}

	state = state || {};
	pool = Array.isArray(pool) ? pool : (typeof pool==="function" ? pool() : []);

	forEach(Object.keys(reductions), function(k){
		var o=reductions[k];
		if(!Array.isArray(o)) reductions[k]=[o];
	});

  	var orig=dupe(state),
	 flags={},
	 rxInternal = /^_[A-Z]+_$/,
	 ret={
	  	returnValue: true,
		history: [],
	  	undo: function(n){
		  	state=orig;
		  	var r=this.history.slice(0, -(n||1));
		  	this.history.length=0;
		  	r.forEach(function(e){ this.dispatch(e[0],e[1]); }, this);
		},

		getState: function(){
			return dupe(state);
		},

		flag: function(strType, value){ // fires knowns and news when subscribed, good for ready()
			forEach(arr(strType), function(strType){
				flags[strType] = value;
				ret.dispatch(strType, value);
			});
		},

		unflag: function(strType){ // un-set an auto-dispatch event
			forEach(arr(strType), function(strType){
				delete flags[strType];
			});
		},

		on: function(strType, fnReducer) {
			if(typeof strType==="object"){
				forEach(Object.keys(strType), function(k){
					ret.on(k, strType[k]);
				});
				return this;
			}
		  	if(!Array.isArray(fnReducer)) fnReducer = [fnReducer];
		  	forEach( arr(strType), function(strType){
				forEach(fnReducer, function(fnReducer){
					var r=reductions[strType] || (reductions[strType]=[]);
					r.push(fnReducer);
					ret.dispatch("_ON_", [strType, fnReducer]);
					if(flags[strType]!=null) ret.dispatch(strType, flags[strType]);
				});
			});
			return this;
		},

		off: function(strType, fnReducer) {

			if(typeof strType==="object"){
				forEach(Object.keys(strType), function(k){
					ret.off(k, strType[k]);
				});
				return this;
			}

			var r=reductions[strType];
			if(!r) return false;
			ret.dispatch("_OFF_", [strType, fnReducer]);
			if(fnReducer==="*"){
				return delete reductions[strType];
			}

			var index=r.indexOf(fnReducer);
			if(index===-1) return false;
			r.splice(index, 1);
			return true;
		},

		once: function(strType, fnReducer){

			if(typeof strType==="object"){
				forEach(Object.keys(strType), function(k){
					ret.once(k, strType[k]);
				});
				return this;
			}

		  	if(!Array.isArray(fnReducer)) fnReducer = [fnReducer];

		  	forEach( arr(strType), function(strType){
				forEach(fnReducer, function(fnReducer){
					ret.on(strType, function oncer(state, e){
						fnReducer(state, e);
						ret.off(strType, oncer);
					});
				});
			});
			return this;
		},

		after: function(strType, trigger, fnReducer){
			if(typeof trigger==="function") return ret.on(strType, function wait(state, data){
				if(trigger(state, data)){
					ret.off(strType, wait);
					ret.on(strType, fnReducer);
					fnReducer.call(ret, state, data);
				}
			});
			var ok=ret.history.some(function(x){return x[0]===trigger;});
			if(ok) return ret.on(strType, fnReducer);
			return ret.once(trigger, fnReducer);
		},

		before: function(strType, trigger, fnReducer){

			if(typeof trigger==="function") return ret.on(strType, function wait(state, data){
				if(trigger(state, data)){
					ret.off(strType, wait);
				}else{
					fnReducer.call(ret, state, data);
				}
			});

			var used=ret.history.some(function(x){return x[0]===trigger;});
			if(used) return ret;
			ret.on(strType, fnReducer);
			return ret.once(trigger, function oncer(){
				ret.off(strType, fnReducer);
			});
		},

		push: function(strEvent, objCIA){
			function pusher(state, e){
				objCIA.dispatch(strEvent, e);
			}
			ret.on(strEvent, pusher);
			return ret.off.bind(ret, strEvent, pusher);
		},

		pull: function(strEvent, objCIA){
			function puller(state, e){
				ret.dispatch(strEvent, e);
			}
			objCIA.on(strEvent, puller);
			return objCIA.off.bind(objCIA, strEvent, puller);
		},

		subscribe: function(fnHandler, matcher){
			pool.push(fnHandler);
		  	fnHandler._matcher=matcher;
			ret.dispatch("_SUBSCRIBE_", [fnHandler, matcher]);
			return this.unsubscribe.bind(this, fnHandler);
		},

		unsubscribe: function(fnHandler){
			pool = pool.filter(function(fn){return fn !== fnHandler;});
			ret.dispatch("_UNSUBSCRIBE_", [fnHandler]);
			return this;
		},

		dispatch: function(strType, data){   // allows reducer return values to be fed to handlers via this:
		  	var that=this;
			if(strType.constructor===RegExp) strType = Object.keys(reductions).filter(/./.test, strType);

		  forEach( arr(strType), function(strType){

			var heap = reductions[strType] || [],
			isInternal = rxInternal.test(strType);

			if(!heap.length && !isInternal) return ret.dispatch("_MISSING_", [strType, data]);

		  	if(!isInternal) that.history.push([strType, data]);

		  	forEach(heap, function(fn){
				try{
			  		if(that.returnValue) state = fn.call(that, state, data) || state;
				}catch(err){
					ret.dispatch("_ERROR_", [err, strType, data]);
				}
			});
		  	if(!that.returnValue){
			 	that.returnValue=true;
			  	return that;
			}

			forEach(pool, function(fn){
			  if(fn._matcher){
				if(fn._matcher.call && !fn._matcher.call(that, strType)) return;
				if(strType.search(fn._matcher)===-1) return;
			  }
			  fn(state);
			});

		  });

		   return this;
		},

		reset: function(){
			ret.history.length=0;
			state = orig;
			ret.dispatch.call(ret, "_INIT_", []);
			return true;
		}
	};
	ret.dispatch.call(ret, "_INIT_", []);
	return ret;
}; // end CIA()

// config, available externally
CIA.freeze=Object.freeze; // used to freeze state, change to just "Object" (or K) to allow mutable state properties.

return CIA;

}));
<commit_msg>add publishing and missing reducer behavior cfg<commit_after>// cia.js  by dandavis [CCBY4]
(function (root, factory) {
	if (typeof define === 'function' && define.amd) {
		define([], factory);
	} else if (typeof exports === 'object') {
		module.exports = factory({});
	} else {
		root.CIA = factory(root);
  }
}(this, function (pub) {

function CIA(reductions, state, pool) {

  if(typeof reductions  != "object") throw new TypeError("Reduction definitions Object cannot be a non-Object");

  function assign(o, x){for (var k in x) if(assign.hasOwnProperty.call(x, k)) o[k] = x[k]; return o; }
  function arr(s){return String(s).trim().split(/\s*,\s*/).filter(Boolean);}
  function forEach(r,f){var m=r.length, i=0;for(; i<m; i++)f(r[i],i,r);};
  function dupe(o){return CIA._freeze(assign({}, o));}

	state = state || {};
	pool = Array.isArray(pool) ? pool : (typeof pool==="function" ? pool() : []);

	forEach(Object.keys(reductions), function(k){
		var o=reductions[k];
		if(!Array.isArray(o)) reductions[k]=[o];
	});

  	var orig=dupe(state),
	 flags={},
	 rxInternal = /^_[A-Z]+_$/,
	 ret={
	  	returnValue: true,
		history: [],
	  	undo: function(n){
		  	state=orig;
		  	var r=this.history.slice(0, -(n||1));
		  	this.history.length=0;
		  	r.forEach(function(e){ this.dispatch(e[0],e[1]); }, this);
		},

		getState: function(){
			return dupe(state);
		},

		flag: function(strType, value){ // fires knowns and news when subscribed, good for ready()
			forEach(arr(strType), function(strType){
				flags[strType] = value;
				ret.dispatch(strType, value);
			});
		},

		unflag: function(strType){ // un-set an auto-dispatch event
			forEach(arr(strType), function(strType){
				delete flags[strType];
			});
		},

		on: function(strType, fnReducer) {
			if(typeof strType==="object"){
				forEach(Object.keys(strType), function(k){
					ret.on(k, strType[k]);
				});
				return this;
			}
		  	if(!Array.isArray(fnReducer)) fnReducer = [fnReducer];
		  	forEach( arr(strType), function(strType){
				forEach(fnReducer, function(fnReducer){
					var r=reductions[strType] || (reductions[strType]=[]);
					r.push(fnReducer);
					ret.dispatch("_ON_", [strType, fnReducer]);
					if(flags[strType]!=null) ret.dispatch(strType, flags[strType]);
				});
			});
			return this;
		},

		off: function(strType, fnReducer) {

			if(typeof strType==="object"){
				forEach(Object.keys(strType), function(k){
					ret.off(k, strType[k]);
				});
				return this;
			}

			var r=reductions[strType];
			if(!r) return false;
			ret.dispatch("_OFF_", [strType, fnReducer]);
			if(fnReducer==="*"){
				return delete reductions[strType];
			}

			var index=r.indexOf(fnReducer);
			if(index===-1) return false;
			r.splice(index, 1);
			return true;
		},

		once: function(strType, fnReducer){

			if(typeof strType==="object"){
				forEach(Object.keys(strType), function(k){
					ret.once(k, strType[k]);
				});
				return this;
			}

		  	if(!Array.isArray(fnReducer)) fnReducer = [fnReducer];

		  	forEach( arr(strType), function(strType){
				forEach(fnReducer, function(fnReducer){
					ret.on(strType, function oncer(state, e){
						fnReducer(state, e);
						ret.off(strType, oncer);
					});
				});
			});
			return this;
		},

		after: function(strType, trigger, fnReducer){
			if(typeof trigger==="function") return ret.on(strType, function wait(state, data){
				if(trigger(state, data)){
					ret.off(strType, wait);
					ret.on(strType, fnReducer);
					fnReducer.call(ret, state, data);
				}
			});
			var ok=ret.history.some(function(x){return x[0]===trigger;});
			if(ok) return ret.on(strType, fnReducer);
			return ret.once(trigger, fnReducer);
		},

		before: function(strType, trigger, fnReducer){

			if(typeof trigger==="function") return ret.on(strType, function wait(state, data){
				if(trigger(state, data)){
					ret.off(strType, wait);
				}else{
					fnReducer.call(ret, state, data);
				}
			});

			var used=ret.history.some(function(x){return x[0]===trigger;});
			if(used) return ret;
			ret.on(strType, fnReducer);
			return ret.once(trigger, function oncer(){
				ret.off(strType, fnReducer);
			});
		},

		push: function(strEvent, objCIA){
			function pusher(state, e){
				objCIA.dispatch(strEvent, e);
			}
			ret.on(strEvent, pusher);
			return ret.off.bind(ret, strEvent, pusher);
		},

		pull: function(strEvent, objCIA){
			function puller(state, e){
				ret.dispatch(strEvent, e);
			}
			objCIA.on(strEvent, puller);
			return objCIA.off.bind(objCIA, strEvent, puller);
		},

		subscribe: function(fnHandler, matcher){
			pool.push(fnHandler);
		  	fnHandler._matcher=matcher;
			ret.dispatch("_SUBSCRIBE_", [fnHandler, matcher]);
			return this.unsubscribe.bind(this, fnHandler);
		},

		unsubscribe: function(fnHandler){
			pool = pool.filter(function(fn){return fn !== fnHandler;});
			ret.dispatch("_UNSUBSCRIBE_", [fnHandler]);
			return this;
		},

		dispatch: function(strType, data){   // allows reducer return values to be fed to handlers via this:
		  	var that=this;
			if(strType.constructor===RegExp) strType = Object.keys(reductions).filter(/./.test, strType);

		  forEach( arr(strType), function(strType){

			var heap = reductions[strType] || [],
			isInternal = rxInternal.test(strType);

			if(!heap.length && !isInternal){
				if(CIA._blnStrictReducers) throw "Unknown reducer type dispatched: " + strType;
				return ret.dispatch("_MISSING_", [strType, data]);
			}

		  	if(!isInternal) that.history.push([strType, data]);

		  	forEach(heap, function(fn){
				try{
			  		if(that.returnValue) state = fn.call(that, state, data) || state;
				}catch(err){
					ret.dispatch("_ERROR_", [err, strType, data]);
				}
			});
		  	if(!that.returnValue){
			 	that.returnValue=true;
			  	return that;
			}

			forEach(pool, function(fn){
			  if(fn._matcher){
				if(fn._matcher.call && !fn._matcher.call(that, strType)) return;
				if(strType.search(fn._matcher)===-1) return;
			  }
			  fn(state);
			});

		  });

		   return this;
		},

		reset: function(){
			ret.history.length=0;
			state = orig;
			ret.dispatch.call(ret, "_INIT_", []);
			return true;
		}
	};
	if(CIA._blnPublishState) ret.state= state;
	if(CIA._blnPublishReducers) ret.reducers= reducers;
	ret.dispatch.call(ret, "_INIT_", []);
	return ret;
}; // end CIA()

// config, available externally
CIA._freeze=Object.freeze; // used to freeze state, change to just "Object" (or K) to allow mutable state properties.
CIA._blnPublishState = false; // if true, add a state property to instance to allow outside mutations (not usually recommended)
CIA._blnPublishReducers = false; // if true, add a reducer property to the instance to allow customization
CIA._blnStrictReducers = false; // if true, dispatch()ing missing reducer types will throw instead of fire a _MISSING_ internal

return CIA;

}));
<|endoftext|>


<commit_before>// Copyright 2018-2019, University of Colorado Boulder

/**
 * A Scenery Node that portrays a thermometer and a triangular indicator of the precise location where the temperature
 * is being sensed. The triangular indicator can be filled with a color to make it more clear what exactly is being
 * measured.
 *
 * @author Arnab Purkayastha
 * @author John Blanco
 */
define( require => {
  'use strict';

  // modules
  const Bounds2 = require( 'DOT/Bounds2' );
  const Color = require( 'SCENERY/util/Color' );
  const merge = require( 'PHET_CORE/merge' );
  const Node = require( 'SCENERY/nodes/Node' );
  const Path = require( 'SCENERY/nodes/Path' );
  const sceneryPhet = require( 'SCENERY_PHET/sceneryPhet' );
  const Shape = require( 'KITE/Shape' );
  const ThermometerNode = require( 'SCENERY_PHET/ThermometerNode' );

  class TemperatureAndColorSensorNode extends Node {

    /**
     * @param {number} minTemperature
     * @param {number} maxTemperature
     * @param {Property.<number>} temperatureProperty
     * @param {Object} [options]
     */
    constructor( minTemperature, maxTemperature, temperatureProperty, options ) {
      super();

      options = merge( {
        draggable: false,
        dragBounds: Bounds2.EVERYTHING,
        horizontalSpace: 3, // horizontal spacing between color indicator and thermometer
        bottomOffset: 5, // vertical difference between bottom of color indicator and thermometer
        thermometerNodeOptions: {
          bulbDiameter: 30,
          tubeWidth: 18,
          lineWidth: 2,
          tickSpacingTemperature: 25,
          majorTickLength: 10,
          minorTickLength: 5,
          backgroundFill: new Color( 256, 256, 256, 0.67 ),
        },
        colorIndicatorOptions: {
          fill: new Color( 0, 0, 0, 0 ),
          lineWidth: 2,
          stroke: 'black',
          lineJoin: 'round',
          sideLength: 18
        }
      }, options );

      // Add the triangle that will display the sensed color.  The leftmost point of this triangle will correspond to the
      // position of the sensor in the model.
      const triangleShape = new Shape();
      const s = options.colorIndicatorOptions.sideLength;
      triangleShape.moveTo( 0, 0 )
        .lineTo( Math.cos( Math.PI / 6 ) * s, -Math.sin( Math.PI / 6 ) * s )
        .lineTo( Math.cos( Math.PI / 6 ) * s, Math.sin( Math.PI / 6 ) * s )
        .close();

      // @private {Path}
      this.colorIndicatorNode = new Path( triangleShape, options.colorIndicatorOptions );
      this.addChild( this.colorIndicatorNode );

      // @private {ThermometerNode}
      this.thermometerNode = new ThermometerNode(
        minTemperature,
        maxTemperature,
        temperatureProperty,
        _.extend( options.thermometerNodeOptions, {
          left: this.colorIndicatorNode.right + options.horizontalSpace,
          bottom: this.colorIndicatorNode.bottom + options.bottomOffset
        } )
      );
      this.addChild( this.thermometerNode );

      this.mutate( options );
    }

    /**
     * Allows for the arrow node's fill color to be changed publicly
     * @public
     */
    changeColor( color ) {
      this.colorIndicatorNode.fill = color;
    }

    /**
     * Returns bounds for thermomemeter node
     * @public
     *
     * @returns {Vector2}
     */
    getThermometerBounds() {
      return this.thermometerNode.bounds;
    }

    get thermometerBounds() { return this.getThermometerBounds(); }

    /**
     * Returns bounds for color indicator arrow node
     * @public
     *
     * @returns {Vector2}
     */
    getColorIndicatorBounds() {
      return this.colorIndicator.bounds;
    }

    get colorIndicatorBounds() { return this.getColorIndicatorBounds(); }
  }

  return sceneryPhet.register( 'TemperatureAndColorSensorNode', TemperatureAndColorSensorNode );
} );<commit_msg>fixed getColorIndicatorBounds function, see #523<commit_after>// Copyright 2018-2019, University of Colorado Boulder

/**
 * A Scenery Node that portrays a thermometer and a triangular indicator of the precise location where the temperature
 * is being sensed. The triangular indicator can be filled with a color to make it more clear what exactly is being
 * measured.
 *
 * @author Arnab Purkayastha
 * @author John Blanco
 */
define( require => {
  'use strict';

  // modules
  const Bounds2 = require( 'DOT/Bounds2' );
  const Color = require( 'SCENERY/util/Color' );
  const merge = require( 'PHET_CORE/merge' );
  const Node = require( 'SCENERY/nodes/Node' );
  const Path = require( 'SCENERY/nodes/Path' );
  const sceneryPhet = require( 'SCENERY_PHET/sceneryPhet' );
  const Shape = require( 'KITE/Shape' );
  const ThermometerNode = require( 'SCENERY_PHET/ThermometerNode' );

  class TemperatureAndColorSensorNode extends Node {

    /**
     * @param {number} minTemperature
     * @param {number} maxTemperature
     * @param {Property.<number>} temperatureProperty
     * @param {Object} [options]
     */
    constructor( minTemperature, maxTemperature, temperatureProperty, options ) {
      super();

      options = merge( {
        draggable: false,
        dragBounds: Bounds2.EVERYTHING,
        horizontalSpace: 3, // horizontal spacing between color indicator and thermometer
        bottomOffset: 5, // vertical difference between bottom of color indicator and thermometer
        thermometerNodeOptions: {
          bulbDiameter: 30,
          tubeWidth: 18,
          lineWidth: 2,
          tickSpacingTemperature: 25,
          majorTickLength: 10,
          minorTickLength: 5,
          backgroundFill: new Color( 256, 256, 256, 0.67 ),
        },
        colorIndicatorOptions: {
          fill: new Color( 0, 0, 0, 0 ),
          lineWidth: 2,
          stroke: 'black',
          lineJoin: 'round',
          sideLength: 18
        }
      }, options );

      // Add the triangle that will display the sensed color.  The leftmost point of this triangle will correspond to the
      // position of the sensor in the model.
      const triangleShape = new Shape();
      const s = options.colorIndicatorOptions.sideLength;
      triangleShape.moveTo( 0, 0 )
        .lineTo( Math.cos( Math.PI / 6 ) * s, -Math.sin( Math.PI / 6 ) * s )
        .lineTo( Math.cos( Math.PI / 6 ) * s, Math.sin( Math.PI / 6 ) * s )
        .close();

      // @private {Path}
      this.colorIndicatorNode = new Path( triangleShape, options.colorIndicatorOptions );
      this.addChild( this.colorIndicatorNode );

      // @private {ThermometerNode}
      this.thermometerNode = new ThermometerNode(
        minTemperature,
        maxTemperature,
        temperatureProperty,
        _.extend( options.thermometerNodeOptions, {
          left: this.colorIndicatorNode.right + options.horizontalSpace,
          bottom: this.colorIndicatorNode.bottom + options.bottomOffset
        } )
      );
      this.addChild( this.thermometerNode );

      this.mutate( options );
    }

    /**
     * Allows for the arrow node's fill color to be changed publicly
     * @public
     */
    changeColor( color ) {
      this.colorIndicatorNode.fill = color;
    }

    /**
     * Returns bounds for thermomemeter node
     * @public
     *
     * @returns {Vector2}
     */
    getThermometerBounds() {
      return this.thermometerNode.bounds;
    }

    get thermometerBounds() { return this.getThermometerBounds(); }

    /**
     * Returns bounds for color indicator arrow node
     * @public
     *
     * @returns {Vector2}
     */
    getColorIndicatorBounds() {
      return this.colorIndicatorNode.bounds;
    }

    get colorIndicatorBounds() { return this.getColorIndicatorBounds(); }
  }

  return sceneryPhet.register( 'TemperatureAndColorSensorNode', TemperatureAndColorSensorNode );
} );<|endoftext|>


<commit_before>/* exported AllSets */

// Copyright 2016 Endless Mobile, Inc.

const Actions = imports.app.actions;
const Dispatcher = imports.app.dispatcher;
const Module = imports.app.interfaces.module;
const QueryObject = imports.search.queryObject;
const Xapian = imports.app.modules.selection.xapian;

const AllSets = new Module.Class({
    Name: 'Selection.AllSets',
    Extends: Xapian.Xapian,

    _init: function (props={}) {
        this.parent(props);
        this._set_needs_refresh(true);
    },

    construct_query_object: function (limit, query_index) {
        if (query_index > 0)
            return null;
        return new QueryObject.QueryObject({
            limit: limit,
            tags_match_all: ['EknSetObject'],
        });
    },

    show_more: function () {
        Dispatcher.get_default().dispatch({
            action_type: Actions.ALL_SETS_CLICKED,
        });
    },
});
<commit_msg>Sort sets by sequence number.<commit_after>/* exported AllSets */

// Copyright 2016 Endless Mobile, Inc.

const Actions = imports.app.actions;
const Dispatcher = imports.app.dispatcher;
const Module = imports.app.interfaces.module;
const QueryObject = imports.search.queryObject;
const Xapian = imports.app.modules.selection.xapian;

const AllSets = new Module.Class({
    Name: 'Selection.AllSets',
    Extends: Xapian.Xapian,

    _init: function (props={}) {
        this.parent(props);
        this._set_needs_refresh(true);
    },

    construct_query_object: function (limit, query_index) {
        if (query_index > 0)
            return null;
        return new QueryObject.QueryObject({
            limit: limit,
            tags_match_all: ['EknSetObject'],
            sort: QueryObject.QueryObjectSort.SEQUENCE_NUMBER,
        });
    },

    show_more: function () {
        Dispatcher.get_default().dispatch({
            action_type: Actions.ALL_SETS_CLICKED,
        });
    },
});
<|endoftext|>