<commit_before>module.exports = function(io) {
  var _self = this;
  var rooms = {};

  console.log(rooms);

  function Room(_name) {
    this.name = _name;
  }

  io.on('connection', function(socket) {
    console.log('connection');

    socket.on('/room/join', function(data) {
      console.log('join', rooms, data.name, rooms[data.name]);
      if (rooms[data.name] == undefined) {
        rooms[data.name] = new Room(data.name);
        console.log('room created', rooms);
      }
      socket.join(data.name);
      io.sockets.adapter.sids[socket.id].ROOM = data.name;
      socket.emit('/room/join/success');
    });

    socket.on('/room/message', function(data) {
      var room = rooms[io.sockets.adapter.sids[socket.id].ROOM];
      console.log('message', room);
    });
  });
}
<commit_msg>broadcast<commit_after>module.exports = function(io) {
  var _self = this;
  var rooms = {};

  console.log(rooms);

  function Room(_name) {
    this.name = _name;
  }

  io.on('connection', function(socket) {
    console.log('connection');

    socket.on('/room/join', function(data) {
      console.log('join', rooms, data.name, rooms[data.name]);
      if (rooms[data.name] == undefined) {
        rooms[data.name] = new Room(data.name);
        console.log('room created', rooms);
      }
      socket.join(data.name);
      io.sockets.adapter.sids[socket.id].ROOM = data.name;
      socket.emit('/room/join/success');
    });

    socket.on('/room/message', function(data) {
      var room = rooms[io.sockets.adapter.sids[socket.id].ROOM];
      console.log('message', room);
      io.sockets.emit('/room/message', data);
    });
  });
}
<|endoftext|>


<commit_before>'use strict';

function numberInWords(num) {
  var number = num,
      numPackage = [],
      numWordPackage = [],
      output = '',
      firstDigits = [
      '',
      'ein',
      'zwei',
      'drei',
      'vier',
      'fünf',
      'sechs',
      'sieben',
      'acht',
      'neun',
      'zehn',
      'elf',
      'zwölf',
      'dreizehn',
      'vierzehn',
      'fünfzehn',
      'sechszehn',
      'achtzehn',
      'neunzehn'
    ],
    secondDigits = [
      '',
      'zehn',
      'zwanzig',
      'dreißig',
      'vierzig',
      'fünfzig',
      'sechzig',
      'siebzig',
      'achtzig',
      'neunzig'
    ],
    furtherDigits = [
      'hundert',
      'tausend',
      'million',
      'milliarde',
      'billion',
      'billiarde',
      'trillion',
      'trilliade',
      'quadrillion',
      'quadrilliarde',
      'quintillion',
      'quintilliarde'
    ],
    furtherDigitsPlural = [
      'hundert',
      'tausend',
      'millionen',
      'milliarden',
      'billionen',
      'billiarden',
      'trillionen',
      'trilliaden',
      'quadrillionen',
      'quadrilliarden',
      'quintillionen',
      'quintilliarden'
    ];
  this.parse = function parse() {
    if(isNaN(parseInt(number))) {
      console.log(output);
      return output;
    }
    var packageCount = splitNumber();
    numPackage = new Array(packageCount);
    numWordPackage = new Array(packageCount);
    pushNumbersIntoPackage();
    createOutputThreeDigitsOutput();
    createCompleteOutput();
    console.log(output);
    return output;
  };
  function splitNumber() {
    number = number.split('').reverse();
    var packages = number.length/3;
    if(packages%1) {
      packages++;
    }
    return parseInt(packages);
  }
  function pushNumbersIntoPackage() {
    var i = 0;
    $.each(number,function(k,v) {
      if(numPackage[i] === undefined) {
        numPackage[i] = [];
      }
      if(numPackage[i].length >= 3) {
        i++;
        numPackage[i] = [];
      }
      numPackage[i].push(v);
    });
  }
  function createOutputThreeDigitsOutput() {
    $.each(numPackage, function(k,v) {
      numPackage[k].reverse();
      if(numPackage[k].length === 1) {
        numWordPackage[k] = firstDigits[numPackage[k][0]];
      }
      if(numPackage[k].length === 2) {
        numWordPackage[k] = createTwoDigitsWord(numPackage[k]);
      }
      if(numPackage[k].length === 3) {
        numWordPackage[k] = createThreeDigitsWord(numPackage[k]);
      }
    });
  }
  function createTwoDigitsWord(n) {
    var integer = parseInt(n[0]+''+n[1]);
    if(integer < 20) {
      return firstDigits[integer];
    }
    if(n[1] > 0) {
      return firstDigits[n[1]]+'und'+secondDigits[n[0]];
    }
    return secondDigits[n[0]];
  }
  function createThreeDigitsWord(n) {
    var lastTwoDigits = [n[1],n[2]];
    if(n[0] === 0) {
      return createTwoDigitsWord(lastTwoDigits);
    }
    return firstDigits[n[0]]+furtherDigits[0]+createTwoDigitsWord(lastTwoDigits);
  }
  function createCompleteOutput() {
    $.each(numWordPackage, function(k,v) {
      if(k === 0) {
        output = numWordPackage[k] + output;
      } else {
        if(k+1 === numWordPackage.length) {
          output = numWordPackage[k] + checkPronounciation(k) + output;
        }
        if(k+1 !== numWordPackage.length && numWordPackage[k] !== furtherDigits[0]) {
          output = numWordPackage[k] + checkPronounciation(k) + output;
        }
      }
    });
  }
  function checkPronounciation(k) {
    var n = parseInt(numPackage[k].join(''));
    if(n === 1 && k > 2) {
      return 'e'+furtherDigits[k];
    }
    return furtherDigitsPlural[k];
  }
}
<commit_msg>removed console.log<commit_after>'use strict';

function numberInWords(num) {
  var number = num,
      numPackage = [],
      numWordPackage = [],
      output = '',
      firstDigits = [
      '',
      'ein',
      'zwei',
      'drei',
      'vier',
      'fünf',
      'sechs',
      'sieben',
      'acht',
      'neun',
      'zehn',
      'elf',
      'zwölf',
      'dreizehn',
      'vierzehn',
      'fünfzehn',
      'sechszehn',
      'achtzehn',
      'neunzehn'
    ],
    secondDigits = [
      '',
      'zehn',
      'zwanzig',
      'dreißig',
      'vierzig',
      'fünfzig',
      'sechzig',
      'siebzig',
      'achtzig',
      'neunzig'
    ],
    furtherDigits = [
      'hundert',
      'tausend',
      'million',
      'milliarde',
      'billion',
      'billiarde',
      'trillion',
      'trilliade',
      'quadrillion',
      'quadrilliarde',
      'quintillion',
      'quintilliarde'
    ],
    furtherDigitsPlural = [
      'hundert',
      'tausend',
      'millionen',
      'milliarden',
      'billionen',
      'billiarden',
      'trillionen',
      'trilliaden',
      'quadrillionen',
      'quadrilliarden',
      'quintillionen',
      'quintilliarden'
    ];
  this.parse = function parse() {
    if(isNaN(parseInt(number))) {
      return output;
    }
    var packageCount = splitNumber();
    numPackage = new Array(packageCount);
    numWordPackage = new Array(packageCount);
    pushNumbersIntoPackage();
    createOutputThreeDigitsOutput();
    createCompleteOutput();
    return output;
  };
  function splitNumber() {
    number = number.split('').reverse();
    var packages = number.length/3;
    if(packages%1) {
      packages++;
    }
    return parseInt(packages);
  }
  function pushNumbersIntoPackage() {
    var i = 0;
    $.each(number,function(k,v) {
      if(numPackage[i] === undefined) {
        numPackage[i] = [];
      }
      if(numPackage[i].length >= 3) {
        i++;
        numPackage[i] = [];
      }
      numPackage[i].push(v);
    });
  }
  function createOutputThreeDigitsOutput() {
    $.each(numPackage, function(k,v) {
      numPackage[k].reverse();
      if(numPackage[k].length === 1) {
        numWordPackage[k] = firstDigits[numPackage[k][0]];
      }
      if(numPackage[k].length === 2) {
        numWordPackage[k] = createTwoDigitsWord(numPackage[k]);
      }
      if(numPackage[k].length === 3) {
        numWordPackage[k] = createThreeDigitsWord(numPackage[k]);
      }
    });
  }
  function createTwoDigitsWord(n) {
    var integer = parseInt(n[0]+''+n[1]);
    if(integer < 20) {
      return firstDigits[integer];
    }
    if(n[1] > 0) {
      return firstDigits[n[1]]+'und'+secondDigits[n[0]];
    }
    return secondDigits[n[0]];
  }
  function createThreeDigitsWord(n) {
    var lastTwoDigits = [n[1],n[2]];
    if(n[0] === 0) {
      return createTwoDigitsWord(lastTwoDigits);
    }
    return firstDigits[n[0]]+furtherDigits[0]+createTwoDigitsWord(lastTwoDigits);
  }
  function createCompleteOutput() {
    $.each(numWordPackage, function(k,v) {
      if(k === 0) {
        output = numWordPackage[k] + output;
      } else {
        if(k+1 === numWordPackage.length) {
          output = numWordPackage[k] + checkPronounciation(k) + output;
        }
        if(k+1 !== numWordPackage.length && numWordPackage[k] !== furtherDigits[0]) {
          output = numWordPackage[k] + checkPronounciation(k) + output;
        }
      }
    });
  }
  function checkPronounciation(k) {
    var n = parseInt(numPackage[k].join(''));
    if(n === 1 && k > 2) {
      return 'e'+furtherDigits[k];
    }
    return furtherDigitsPlural[k];
  }
}
<|endoftext|>


<commit_before>// ==UserScript==
// @version        1.7.1
// @name           Steam Database Integration
// @description    Adds Steam Database link across Steam Community and Store
// @homepage       http://steamdb.info
// @namespace      http://steamdb.info/userscript/
// @icon           http://steamdb.info/static/logo_144px.png
// @match          http://store.steampowered.com/app/*
// @match          http://store.steampowered.com/sub/*
// @match          http://store.steampowered.com/video/*
// @match          http://steamcommunity.com/app/*
// @match          http://steamcommunity.com/games/*
// @match          http://steamcommunity.com/id/*
// @match          http://steamcommunity.com/profiles/*
// @match          http://steamcommunity.com/market/*
// @match          http://steamcommunity.com/sharedfiles/filedetails*
// @match          http://steamcommunity.com/workshop/browse*
// @match          http://steamcommunity.com/workshop/discussions*
// @updateURL      https://github.com/SteamDatabase/SteamDatabase/raw/master/SteamDatabase.user.js
// ==/UserScript==

var mainURL  = 'http://steamdb.info',
    pathName = location.pathname,
    element,
    container,

    IMAGE_PROFILE = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAACTElEQVR42p2UO2hTURjHr/XRQCtSWnyAOBWEVumQRXBSqTiUOqiL6CBZBCedpEtAhEJXoUPERbDo0slSUDSWFBQMQiSQ182TvG8Sktw8m3t7/J2QDKGxtl748f/O97rnfPdwFeUfjxDiDFyuVquTyv88FI92Op2bpmm+gi/YDsMwbuMfP3ATiq7BN9AoNkH0tITvZ6vVkg2PDS0ul8sTzWbzRrvd/gw7IPaD3O+NRuMuDafgiJLNZsfq9foizg1o8jZxCNo0/Eq9Tc5iBMOq6/omKg6JUavVXGzg6sDxaDYL65VKRUMNvpQYgkmsyCi20Ov7fq1CoTBP4goNg2CCkOBLoqulUmkhGo1aBgrtdvuI1+s9QfB+sVh8nc/nbTSzuN3u4xRN03QJ/za6jM7I2LD87rA1TXtBYhmEhOBv9An+c3KG/Reqqno6l8vdIf6DuAG7oLN+290V3U+xuEeSA9LYspnBS37Bc+xb6FNw9WICu0LuGjyIx+MTA8eU5yYwl06n34CeyWQEuoMWoNlbt+A9WP1+/8k9Q5Zdw+HwhWQyOSkvWCgUOo/tgEQqldIhg/0hkUhcGpaveDyeMZyLsAEqiZ/Qx5FI5CIJR9E51g/Z7RX5AdCz5DzC97GfH4vFbN0h4rBSsIkKCYE6qPhe9rfPXMbZwTMaqcR08nbBYO1CBy8kx5klsE6Bhho0EthZ/O/4YmG5BhOKsIXv7xeSotFgMDhP0goEwQQhIZaEVeILTqfTcqBfiZwHxdM+n28pEAhswzJNZvbc6N7zB4IDJhjugBeWAAAAAElFTkSuQmCC',
    IMAGE_GROUP   = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAeFBMVEUAAAD7+vvBwMHa2dj6+vvAv8GenZ/Z2djBv7/AwcDY2Nq/v8D6+vqdnp7Y2difnp7Awb/5+vnAv8C/v8Gdn5+enp7Z2NnBwMC/wL+fnZ6fn56en5/6+frZ2dnZ2NjY2dn5+/r7+fnY2Nj7+vr6+/qenp/AwMCen55YC6VhAAAAAXRSTlMAQObYZgAAAExJREFUeNq1zrcBgDAMAEEyJoPJwdmW9t+QBVTC11d89E9emynOWu28cQ8ptj5VQopalspaUhzz2FTAkpzvAKQIeK5D0eGC1x2+GX8BaDwE0HkrefEAAAAASUVORK5CYII=',
    IMAGE_STORE   = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARYAAAAlCAMAAACwCjbKAAABGlBMVEUAAAD7+vv6+vvBv7/a2djAwcD6+vrY2NrBwMHZ2djAv8HY2dj5+vm/v8CenZ+dnp7Av8Cfnp7Awb/Z2Nmdn5/BwMC/v8Genp6/wL+fnZ6fn576+fqen5+Bf3vZ2dnZ2NjY2dn5+/r7+vr7+fnY2Nj6+/qenp+WlJFsammtq6ipp6Slo6Cgnpycmph9e3iGhIFxbmx1cnBoZmN5d3SPjYptamiYlpOUko+CgH07OTnAwMCen55oZWNraGZlYmBiX11/fHmxr6yLiYZ9e3dpZ2RsamdmZGFua2l7eXZjYF5vbWpxb2xgXVt6eHRycG11c3B3dXF0cm54dnNPTEtfXFpdWlhaV1VbWVdXVFJYVlRVUlFUUU9ST05RTk1/9Yr5AAAAAXRSTlMAQObYZgAAAQhJREFUeNrt0NVWAgEUBdAxUTFAMTDo7o4ZyjFAUcHC/v/f0OV58N5nH+fsT9jGj9QpSSnjVzpp059kGi2ZAQknGbRkz0jKoiU3IimHlvwtSXm0NB5IaqClOSWpiZbahKQaWux7kmy0FO9IKqKlNSaphZbCNUkFtFSHJFXRUr4gqYyWUleKh6Prc/PL4Ug8GjnqOlEJLfVzkupoqXSkHfdiKBAMuIKroVis40QVtFyShpaecrC3vbFkLqyseXZNs+dIaLkiDS19JWH5972bW5bPOjxO9B0JLTekoeWJNLQ8k4aWF9LQMiMNLW+koeWVNLS8k4aWD9LQ8kkaWr5IQ0v7kaS2QUT/9Q1Dy8tw8txFbQAAAABJRU5ErkJggg==';

var SteamDB =
{
	CurrentAppID: 0,

	RegexAppID: /\/([0-9]{1,6})\/?/,

	FindAppID: function( )
	{
		element = pathName.match( SteamDB.RegexAppID );

		if( element )
		{
			SteamDB.CurrentAppID = element[ 1 ];
		}
	},

	/**
	 * Game hubs
	 */
	InjectGameHub: function( bSharedFile, bHackyGameURL )
	{
		container = document.querySelector( '.apphub_OtherSiteInfo' );

		if( !container )
		{
			return;
		}

		if( bSharedFile || bHackyGameURL )
		{
			element = document.querySelector( '.apphub_sectionTab' );

			if( !element )
			{
				return;
			}

			SteamDB.CurrentAppID = element.href.match( SteamDB.RegexAppID )[ 1 ];
		}

		element = document.createElement( 'a' );
		element.className = 'btn_darkblue_white_innerfade btn_medium';
		element.href = mainURL + '/app/' + SteamDB.CurrentAppID + '/';
		element.target = '_blank';
		element.innerHTML = 'Steam Database';

		if( bSharedFile )
		{
			// Steam piston blocks button, and can't be clicked
			element.style.position = 'relative';
			element.style.zIndex = 1;
		}

		container.insertBefore( element, container.firstChild );

		// fix AppName madness
		element = document.querySelector( '.apphub_AppName' );

		if( element )
		{
			element.style.paddingRight = '30px';
			element.style.maxWidth = 'none';
			element.style.float = 'none';
		}
	},

	/**
	 * Official game groups
	 */
	InjectGameGroup: function( )
	{
		// Some game groups fancy custom urls
		if( !SteamDB.CurrentAppID )
		{
			// Let's try to find game hub link, what possibly could go wrong?
			container = document.querySelector( 'a[href*="http://steamcommunity.com/app/"]' );

			if( !container )
			{
				return;
			}

			SteamDB.CurrentAppID = container.href.match( SteamDB.RegexAppID )[ 1 ];
		}

		// Uh oh, if we are in game hub with a fancy /games/ url, we should use game hub code instead
		if( document.querySelector( '.apphub_OtherSiteInfo' ) !== null )
		{
			SteamDB.InjectGameHub( false, true );

			return;
		}

		container = document.querySelector( '#rightActionBlock' );

		if( !container )
		{
			return;
		}

		element = document.createElement( 'div' );
		element.className = 'actionItem';
		element.innerHTML = '

View on Steam Database';

		container.insertBefore( element, null );

		// While we're here, let's fix this annoyance
		element = document.querySelector( '#oggLogo img' );

		if( element )
		{
			element.style.height = '208px';
		}
	},

	/**
	 * App store page
	 */
	InjectStoreApp: function( )
	{
		container = document.querySelector( '#demo_block .block_content_inner' );

		if( !container )
		{
			return;
		}

		element = document.createElement( 'div' );
		element.className = 'demo_area_button';
		element.innerHTML = 'View on Steam Database';

		container.insertBefore( element, container.firstChild );

		// Find each "add to cart" button
		container = document.querySelectorAll( 'input[name="subid"]' );

		var i = 0, appid = 0;

		for( i = 0; i < container.length; i++ )
		{
			element = container[ i ];

			appid = element.value; // It's subid, but let's reuse things

			element = element.parentElement.parentElement;

			element.insertAdjacentHTML( 'beforeEnd', 'View on Steam Database (' + appid + ')' );
		}

		// While we're here, let's fix this broken url
		element = document.querySelector( '.apphub_OtherSiteInfo a' );

		if( element && element.href.charAt( 26 ) === '/' )
		{
			element.href = element.href.replace( /\/\/app\//, '/app/' ) + '/';
		}

		if( !document.querySelector( '.game_area_purchase_game_dropdown_selection' ) )
		{
			// There are no dropdowns, so don't bother hooking
			return;
		}

		element = document.createElement( 'script' );
		element.id = 'steamdb_dropdown_hook';
		element.type = 'text/javascript';
		element.appendChild( document.createTextNode( '(' + SteamDB.InjectAppSubscriptions + ')();' ) );

		document.head.appendChild( element );
	},

	/**
	 * Package store page
	 */
	InjectStorePackage: function( )
	{
		container = document.querySelector( '.share' );

		if( !container )
		{
			return;
		}

		element = document.createElement( 'div' );
		element.className = 'demo_area_button';
		element.innerHTML = 'View on Steam Database';

		container.insertBefore( element, container.firstChild );
	},

	/**
	 * Trailer/movie store page
	 */
	InjectStoreVideo: function( )
	{
		container = document.querySelector( '.game_details .block_content_inner' );

		if( !container )
		{
			return;
		}

		element = document.createElement( 'div' );
		element.innerHTML = 'View on Steam Database';

		container.insertBefore( element, null );
	},

	/**
	 * Profile page
	 */
	InjectProfile: function( )
	{
		container = document.querySelector( '#profile_action_dropdown .popup_body' );

		if( !container )
		{
			return;
		}

		// Can't access g_rgProfileData inside sandbox
		var steamID = pathName.match( /^\/(id|profiles)\/([^\s/]+)\/?$/ );

		if( !steamID )
		{
			// wtf?
			return;
		}

		element = document.createElement( 'a' );
		element.href = mainURL + '/calculator/?player=' + steamID[ 2 ];
		element.target = '_blank';
		element.className = 'popup_menu_item';
		element.innerHTML = '  SteamDB Calculator';

		container.insertBefore( element, null );
	},

	/**
	 * Inventory page
	 */
	InjectProfileInventory: function( )
	{
		if( !document.getElementById( 'inventory_link_753' ) )
		{
			// There is no Steam inventory, so don't bother hooking
			return;
		}

		element = document.createElement( 'script' );
		element.id = 'steamdb_inventory_hook';
		element.type = 'text/javascript';
		element.appendChild( document.createTextNode( '(' + SteamDB.InsaneInventoryHackery + ')();' ) );

		document.head.appendChild( element );
	},

	/**
	 * Market page
	 */
	InjectMarketInventory: function( )
	{
		element = document.createElement( 'script' );
		element.id = 'steamdb_market_hook';
		element.type = 'text/javascript';
		element.appendChild( document.createTextNode( '(' + SteamDB.InsaneMarketHackery + ')();' ) );

		document.head.appendChild( element );
	},

	/**
	 * This function is injected into DOM
	 */
	InsaneInventoryHackery: function( )
	{
		var i, link, SteamDB_Hackery_PopulateActions = window.PopulateActions;

		window.PopulateActions = function( elActions, rgActions, item )
		{
			var foundState = 0;

			try
			{
				if( item.appid == 753 )
				{
					if( rgActions )
					{
						for( i = 0; i < rgActions.length; i++ )
						{
							link = rgActions[ i ];

							if( link.steamdb )
							{
								foundState = 2;
								break;
							}
							else if( link.link && link.link.match( /\.com\/(app|sub)\// ) )
							{
								foundState = 1;
							}
						}

						if( foundState === 1 )
						{
							for( i = 0; i < rgActions.length; i++ )
							{
								link = rgActions[ i ].link;

								if( !link )
								{
									continue;
								}

								link = link.match( /\.com\/(app|sub)\/([0-9]{1,6})/ );

								if( link )
								{
									rgActions.push( {
										steamdb: true,
										link: 'http://steamdb.info/' + link[ 1 ] + '/' + link[ 2 ] + '/', // mainURL is not accessible from here
										name: 'View on Steam Database'
									} );

									foundState = 2;

									break;
								}
							}
						}
					}
					else if( !item.actions && item.type === 'Gift' ) // This function gets called with owner_actions too
					{
						item.actions = rgActions = [ {
							steamdb: true,
							link: 'http://steamdb.info/search/?a=sub&q=' + encodeURIComponent( item.name ), // mainURL is not accessible from here
							name: 'Search on Steam Database'
						} ];

						foundState = 2;
					}

					if( item.tags )
					{
						for( i = 0; i < item.tags.length; i++ )
						{
							link = item.tags[ i ];

							if( ( link.internal_name === 'cardborder_1' || link.internal_name === 'droprate_1' || link.internal_name === 'droprate_2' ) && link.name.substring( 0, 5 ) !== '<span' )
							{
								item.tags[ i ].name = '' + link.name + '';
							}
						}
					}
				}
			}
			catch( e )
			{
				// Don't break website functionality if something fails above
				console.log( e );
			}

			SteamDB_Hackery_PopulateActions( elActions, rgActions, item );

			// We want our links to be open in new tab
			if( foundState === 2 )
			{
				link = elActions.querySelector( '.item_action[href^="http://steamdb.info"]' );

				if( link )
				{
					link.target = '_blank';
				}
			}
		};
	},

	InsaneMarketHackery: function( )
	{
		var SteamDB_Hackery_BuildHover = window.BuildHover;

		window.BuildHover = function( prefix, item, owner )
		{
			try
			{
				if( item.classid )
				{
					var found = false;

					if( !Array.isArray( item.fraudwarnings ) )
					{
						item.fraudwarnings = [ ];
					}
					else
					{
						// We have to search if we inserted already because Steam's economy code re-uses things weirdly
						for( var i = 0; i < item.fraudwarnings.length; i++ )
						{
							if( item.fraudwarnings[ i ].substring( 0, 7 ) === 'ClassID' )
							{
								found = true;

								break;
							}
						}
					}

					if( !found )
					{
						item.fraudwarnings.push( 'ClassID: ' + item.classid );

						if( item.instanceid > 0 )
						{
							item.fraudwarnings.push( 'InstanceID: ' + item.instanceid );
						}

						if( item.app_data && item.app_data.def_index )
						{
							item.fraudwarnings.push( 'DefIndex: ' + item.app_data.def_index );
						}
					}
				}
			}
			catch( e )
			{
				// Don't break website functionality if something fails above
				console.log( e );
			}

			SteamDB_Hackery_BuildHover( prefix, item, owner );
		};
	},

	/**
	 * This function is injected into store's app page
	 */
	InjectAppSubscriptions: function( )
	{
		var link, SteamDB_Hackery_dropdownSelectOption = window.dropdownSelectOption;

		window.dropdownSelectOption = function( dropdownName, subId, inCart )
		{
			try
			{
				link = document.getElementById('add_to_cart_' + dropdownName + '_description_text');
				link = link.parentNode.querySelector( '.steamdb_sub_link' );

				link.href = 'http://steamdb.info/sub/' + subId + '/';
				link.innerHTML = 'View on Steam Database (' + subId + ')';
			}
			catch( e )
			{
				// Don't break website functionality if something fails above
			}

			SteamDB_Hackery_dropdownSelectOption( dropdownName, subId, inCart );
		};
	}
};

if( location.hostname === 'steamcommunity.com' )
{
	if( pathName.match( /^\/app\// ) )
	{
		SteamDB.FindAppID( );

		SteamDB.InjectGameHub( false );
	}
	else if( pathName.match( /^\/sharedfiles\/filedetails\/?$/ ) || pathName.match( /^\/workshop\/(browse|discussions)\/?/ ) )
	{
		SteamDB.InjectGameHub( true );
	}
	else if( pathName.match( /^\/games\// ) )
	{
		SteamDB.FindAppID( );

		SteamDB.InjectGameGroup( );
	}
	else if( pathName.match( /^\/(id|profiles)\/[^\s/]+\/?$/ ) )
	{
		SteamDB.InjectProfile( );
	}
	else if( pathName.match( /^\/(id|profiles)\/[^\s/]+\/inventory/ ) )
	{
		SteamDB.InjectProfileInventory( );
		SteamDB.InjectMarketInventory( );
	}
	else if( pathName.match( /^\/market\// ) )
	{
		SteamDB.InjectMarketInventory( );
	}
}
else
{
	SteamDB.FindAppID( );

	// Did we hit an error page?
	container = document.getElementById( 'error_box' );

	if( container )
	{
		container.insertAdjacentHTML( 'beforeEnd', '

View on Steam Database' );
	}
	else if( pathName.match( /^\/app\// ) )
	{
		SteamDB.InjectStoreApp( );
	}
	else if( pathName.match( /^\/sub\// ) )
	{
		SteamDB.InjectStorePackage( );
	}
	else if( pathName.match( /^\/video\// ) )
	{
		SteamDB.InjectStoreVideo( );
	}
}
<commit_msg>Remove old and unmaintained userscript<commit_after><|endoftext|>


<commit_before>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.subtitle.TranscribeRightPanel');

mirosubs.subtitle.TranscribeRightPanel = function(serverModel,
                                                  helpContents,
                                                  extraHelp,
                                                  legendKeySpecs,
                                                  showRestart,
                                                  doneStrongText,
                                                  doneText) {
    mirosubs.RightPanel.call(this, serverModel, helpContents, extraHelp,
                             legendKeySpecs,
                             showRestart, doneStrongText, doneText);
};
goog.inherits(mirosubs.subtitle.TranscribeRightPanel, mirosubs.RightPanel);

mirosubs.subtitle.TranscribeRightPanel.PLAYMODE_CHANGED = 'modechanged';

mirosubs.subtitle.TranscribeRightPanel.prototype.playModeText_ = function(playMode) {
    var pm = mirosubs.subtitle.TranscribePanel.PlayMode;
    if (playMode == pm.NO_AUTOPAUSE)
        return "Expert: no automatic pausing (use TAB key)";
    else if (playMode == pm.AUTOPAUSE)
        return "Recommended: magical autopause (just keep typing!)";
    else if (playMode == pm.PLAY_STOP)
        return "Beginner: play 8 seconds, then pause";
};

mirosubs.subtitle.TranscribeRightPanel.prototype.appendLegendContentsInternal =
    function($d, legendDiv)
{
    mirosubs.subtitle.TranscribeRightPanel.superClass_
        .appendLegendContentsInternal.call(this, $d, legendDiv);
    this.playModeSelect_ = $d('select');

    var speed = mirosubs.UserSettings.getStringValue(
        mirosubs.UserSettings.Settings.VIDEO_SPEED_MODE) || pm.PLAY_STOP;
    var select = this.playModeSelect_;
    var pm = mirosubs.subtitle.TranscribePanel.PlayMode;
    var text = goog.bind(this.playModeText_, this);
    goog.array.forEach(
        [pm.PLAY_STOP, pm.AUTOPAUSE, pm.NO_AUTOPAUSE],
        function(opt) {
            var attrs = { 'value': opt };
            if (opt == speed)
                attrs['selected'] = 'selected';
            select.appendChild(
                $d('option', attrs, text(opt)));
        });
    legendDiv.appendChild($d('div', 'mirosubs-speedmode',
                             $d('h4', null, 'Speed Mode'),
                             select));
    this.setButtonText_();
};

mirosubs.subtitle.TranscribeRightPanel.prototype.enterDocument = function() {
    mirosubs.subtitle.TranscribeRightPanel.superClass_.enterDocument.call(this);
    this.getHandler().listen(this.playModeSelect_,
                             goog.events.EventType.CHANGE,
                             this.playModeChanged_);
};

mirosubs.subtitle.TranscribeRightPanel.prototype.setButtonText_ = function() {
    var kc = goog.events.KeyCodes;
    if (this.playModeSelect_.value ==
        mirosubs.subtitle.TranscribePanel.PlayMode.PLAY_STOP) {
        this.setButtonTextInternal(kc.CTRL, "Re-play last 8 seconds");
        this.setButtonTextInternal(kc.TAB, "Play next 8 seconds");
        this.enableButtonClassInternal(kc.TAB, '-beginner', true);
    }
    else {
        this.setButtonTextInternal(kc.CTRL);
        this.setButtonTextInternal(kc.TAB);
        this.enableButtonClassInternal(kc.TAB, '-beginner', false);
    }
};

mirosubs.subtitle.TranscribeRightPanel.prototype.playModeChanged_ = function(event) {
    this.setButtonText_();
    mirosubs.UserSettings.setStringValue(
        mirosubs.UserSettings.Settings.VIDEO_SPEED_MODE,
        this.playModeSelect_.value);
    this.dispatchEvent(
        new mirosubs.subtitle.TranscribeRightPanel.PlayModeChangeEvent(
            this.playModeSelect_.value));
};

mirosubs.subtitle.TranscribeRightPanel.PlayModeChangeEvent = function(mode) {
    this.type = mirosubs.subtitle.TranscribeRightPanel.PLAYMODE_CHANGED;
    this.mode = mode;
};<commit_msg>Minor fix<commit_after>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.subtitle.TranscribeRightPanel');

mirosubs.subtitle.TranscribeRightPanel = function(serverModel,
                                                  helpContents,
                                                  extraHelp,
                                                  legendKeySpecs,
                                                  showRestart,
                                                  doneStrongText,
                                                  doneText) {
    mirosubs.RightPanel.call(this, serverModel, helpContents, extraHelp,
                             legendKeySpecs,
                             showRestart, doneStrongText, doneText);
};
goog.inherits(mirosubs.subtitle.TranscribeRightPanel, mirosubs.RightPanel);

mirosubs.subtitle.TranscribeRightPanel.PLAYMODE_CHANGED = 'modechanged';

mirosubs.subtitle.TranscribeRightPanel.prototype.playModeText_ = function(playMode) {
    var pm = mirosubs.subtitle.TranscribePanel.PlayMode;
    if (playMode == pm.NO_AUTOPAUSE)
        return "Expert: no automatic pausing (use TAB key)";
    else if (playMode == pm.AUTOPAUSE)
        return "Recommended: magical autopause (just keep typing!)";
    else if (playMode == pm.PLAY_STOP)
        return "Beginner: play 8 seconds, then pause";
};

mirosubs.subtitle.TranscribeRightPanel.prototype.appendLegendContentsInternal =
    function($d, legendDiv)
{
    mirosubs.subtitle.TranscribeRightPanel.superClass_
        .appendLegendContentsInternal.call(this, $d, legendDiv);
    this.playModeSelect_ = $d('select');

    var pm = mirosubs.subtitle.TranscribePanel.PlayMode;
    var speed = mirosubs.UserSettings.getStringValue(
        mirosubs.UserSettings.Settings.VIDEO_SPEED_MODE) || pm.PLAY_STOP;
    var select = this.playModeSelect_;
    var pm = mirosubs.subtitle.TranscribePanel.PlayMode;
    var text = goog.bind(this.playModeText_, this);
    goog.array.forEach(
        [pm.PLAY_STOP, pm.AUTOPAUSE, pm.NO_AUTOPAUSE],
        function(opt) {
            var attrs = { 'value': opt };
            if (opt == speed)
                attrs['selected'] = 'selected';
            select.appendChild(
                $d('option', attrs, text(opt)));
        });
    legendDiv.appendChild($d('div', 'mirosubs-speedmode',
                             $d('h4', null, 'Speed Mode'),
                             select));
    this.setButtonText_();
};

mirosubs.subtitle.TranscribeRightPanel.prototype.enterDocument = function() {
    mirosubs.subtitle.TranscribeRightPanel.superClass_.enterDocument.call(this);
    this.getHandler().listen(this.playModeSelect_,
                             goog.events.EventType.CHANGE,
                             this.playModeChanged_);
};

mirosubs.subtitle.TranscribeRightPanel.prototype.setButtonText_ = function() {
    var kc = goog.events.KeyCodes;
    if (this.playModeSelect_.value ==
        mirosubs.subtitle.TranscribePanel.PlayMode.PLAY_STOP) {
        this.setButtonTextInternal(kc.CTRL, "Re-play last 8 seconds");
        this.setButtonTextInternal(kc.TAB, "Play next 8 seconds");
        this.enableButtonClassInternal(kc.TAB, '-beginner', true);
    }
    else {
        this.setButtonTextInternal(kc.CTRL);
        this.setButtonTextInternal(kc.TAB);
        this.enableButtonClassInternal(kc.TAB, '-beginner', false);
    }
};

mirosubs.subtitle.TranscribeRightPanel.prototype.playModeChanged_ = function(event) {
    this.setButtonText_();
    mirosubs.UserSettings.setStringValue(
        mirosubs.UserSettings.Settings.VIDEO_SPEED_MODE,
        this.playModeSelect_.value);
    this.dispatchEvent(
        new mirosubs.subtitle.TranscribeRightPanel.PlayModeChangeEvent(
            this.playModeSelect_.value));
};

mirosubs.subtitle.TranscribeRightPanel.PlayModeChangeEvent = function(mode) {
    this.type = mirosubs.subtitle.TranscribeRightPanel.PLAYMODE_CHANGED;
    this.mode = mode;
};<|endoftext|>


<commit_before>import AggregationWidget from "components/AggregationWidgets"
import AddAssessmentModal from "components/assessments/AddAssessmentModal"
import { ReadonlyCustomFields } from "components/CustomFields"
import Fieldset from "components/Fieldset"
import PropTypes from "prop-types"
import React, { useState } from "react"
import { Button } from "react-bootstrap"

/* The AssessmentResults component displays the results of two types of
 * assessments made on a given entity and subentities:
 * - aggregation of the assessments made on the entity/subentities when
 *   working on them in relation to another type of entity (example:
 *   assessments made on tasks, while filling  report related to the tasks);
 *   the definition of these assessments is to be found in
 *   entity.customFields.assessmentDefinition
 * - display of the last assessment made on the entity/subentities
 *   as a conclusion about a given period of time;
 *   the definition of these assessments is to be found in
 *   assessmentCustomFields
 */
const AssessmentResults = ({
  assessmentPeriod,
  entity,
  label,
  subEntities,
  style,
  assessmentCustomFields,
  refetch,
  canEdit
}) => {
  const [showAssessmentModal, setShowAssessmentModal] = useState(false)

  if (!entity) {
    return null
  }

  const assessmentDefinition = JSON.parse(
    JSON.parse(entity.customFields || "{}").assessmentDefinition || "{}"
  )

  const assessmentResultsWidgets = []
  // display one aggregation widget per assessment question
  Object.keys(assessmentDefinition || {}).forEach(key => {
    const aggWidgetProps = {
      widget:
        assessmentDefinition[key].aggregation?.widget ||
        assessmentDefinition[key].widget,
      aggregationType: assessmentDefinition[key].aggregation?.aggregationType,
      vertical: true
    }
    const widgetLayoutConfig = Object.without(
      assessmentDefinition[key],
      "aggregation",
      "type",
      "typeError",
      "placeholder",
      "helpText",
      "validations",
      "visibleWhen",
      "objectFields"
    )
    assessmentResultsWidgets.push(
      <AggregationWidget
        key={`assessment-${key}`}
        values={entity.getAssessmentResults(assessmentPeriod)[key]}
        {...aggWidgetProps}
        {...widgetLayoutConfig}
      />
    )
  })

  const lastAssessment = entity.getLastAssessment(assessmentPeriod)
  const assessmentLabelPrefix = lastAssessment ? "Add a" : "Make a new"
  const addAssessmentLabel = `${assessmentLabelPrefix} ${entity?.toString()} assessment for the month of ${assessmentPeriod.start.format(
    "MMM-YYYY"
  )}`

  return (

      {assessmentResultsWidgets && (
        <Fieldset
          title={`${label} results for ${assessmentPeriod.start.format(
            "MMM-YYYY"
          )}`}
          id="assessments-results"
        >
          {assessmentResultsWidgets}

          {subEntities?.map(subEntity => (
            <AssessmentResults
              key={`subassessment-${subEntity.uuid}`}
              label={`${subEntity.toString()} ${label}`}
              entity={subEntity}
              assessmentPeriod={assessmentPeriod}
              canEdit={false}
            />
          ))}

          {lastAssessment && assessmentCustomFields && (
            <ReadonlyCustomFields
              fieldNamePrefix=""
              fieldsConfig={assessmentCustomFields}
              values={lastAssessment}
              vertical
            />
          )}

          {canEdit && assessmentCustomFields && (
            <>
              <Button
                bsStyle="primary"
                onClick={() => setShowAssessmentModal(true)}
              >
                {addAssessmentLabel}
              </Button>
              <AddAssessmentModal
                task={entity}
                assessmentPeriod={assessmentPeriod}
                showModal={showAssessmentModal}
                onCancel={() => setShowAssessmentModal(false)}
                onSuccess={() => {
                  setShowAssessmentModal(false)
                  refetch()
                }}
              />
            </>
          )}
        </Fieldset>
      )}

  )
}

AssessmentResults.propTypes = {
  assessmentCustomFields: PropTypes.object,
  assessmentPeriod: PropTypes.shape({
    start: PropTypes.object,
    end: PropTypes.object
  }),
  canEdit: PropTypes.bool,
  entity: PropTypes.object,
  label: PropTypes.string,
  refetch: PropTypes.func,
  style: PropTypes.object,
  subEntities: PropTypes.array
}

export default AssessmentResults
<commit_msg>NCI-Agency/anet#2926: Fix display of last assessments<commit_after>import AggregationWidget from "components/AggregationWidgets"
import AddAssessmentModal from "components/assessments/AddAssessmentModal"
import { ReadonlyCustomFields } from "components/CustomFields"
import Fieldset from "components/Fieldset"
import { Formik } from "formik"
import PropTypes from "prop-types"
import React, { useState } from "react"
import { Button } from "react-bootstrap"

/* The AssessmentResults component displays the results of two types of
 * assessments made on a given entity and subentities:
 * - aggregation of the assessments made on the entity/subentities when
 *   working on them in relation to another type of entity (example:
 *   assessments made on tasks, while filling  report related to the tasks);
 *   the definition of these assessments is to be found in
 *   entity.customFields.assessmentDefinition
 * - display of the last period related assessment made on the entity/subentities
 *   as a conclusion about the given period of time;
 *   the definition of these assessments is to be found in
 *   assessmentCustomFields
 */
const AssessmentResults = ({
  assessmentPeriod,
  entity,
  label,
  subEntities,
  style,
  assessmentCustomFields,
  refetch,
  canEdit
}) => {
  const [showAssessmentModal, setShowAssessmentModal] = useState(false)

  if (!entity) {
    return null
  }

  const assessmentDefinition = JSON.parse(
    JSON.parse(entity.customFields || "{}").assessmentDefinition || "{}"
  )

  const assessmentResultsWidgets = []
  // display one aggregation widget per assessment question
  Object.keys(assessmentDefinition || {}).forEach(key => {
    const aggWidgetProps = {
      widget:
        assessmentDefinition[key].aggregation?.widget ||
        assessmentDefinition[key].widget,
      aggregationType: assessmentDefinition[key].aggregation?.aggregationType,
      vertical: true
    }
    const widgetLayoutConfig = Object.without(
      assessmentDefinition[key],
      "aggregation",
      "type",
      "typeError",
      "placeholder",
      "helpText",
      "validations",
      "visibleWhen",
      "objectFields"
    )
    assessmentResultsWidgets.push(
      <AggregationWidget
        key={`assessment-${key}`}
        values={entity.getAssessmentResults(assessmentPeriod)[key]}
        {...aggWidgetProps}
        {...widgetLayoutConfig}
      />
    )
  })

  const lastAssessment = entity.getLastAssessment(assessmentPeriod)
  const assessmentLabelPrefix = lastAssessment ? "Add a" : "Make a new"
  const addAssessmentLabel = `${assessmentLabelPrefix} ${entity?.toString()} assessment for the month of ${assessmentPeriod.start.format(
    "MMM-YYYY"
  )}`

  return (

      {assessmentResultsWidgets && (
        <Fieldset
          title={`${label} results for ${assessmentPeriod.start.format(
            "MMM-YYYY"
          )}`}
          id="assessments-results"
        >
          {assessmentResultsWidgets}

          {subEntities?.map(subEntity => (
            <AssessmentResults
              key={`subassessment-${subEntity.uuid}`}
              label={`${subEntity.toString()} ${label}`}
              entity={subEntity}
              assessmentPeriod={assessmentPeriod}
              canEdit={false}
            />
          ))}

          {lastAssessment && assessmentCustomFields && (
            <Formik
              initialValues={{
                [`lastAssessment-${entity.uuid}`]: lastAssessment
              }}
            >
              {({ values }) => (
                <ReadonlyCustomFields
                  fieldNamePrefix={`lastAssessment-${entity.uuid}`}
                  fieldsConfig={assessmentCustomFields}
                  values={values}
                  vertical
                />
              )}
            </Formik>
          )}

          {canEdit && assessmentCustomFields && (
            <>
              <Button
                bsStyle="primary"
                onClick={() => setShowAssessmentModal(true)}
              >
                {addAssessmentLabel}
              </Button>
              <AddAssessmentModal
                task={entity}
                assessmentPeriod={assessmentPeriod}
                showModal={showAssessmentModal}
                onCancel={() => setShowAssessmentModal(false)}
                onSuccess={() => {
                  setShowAssessmentModal(false)
                  refetch()
                }}
              />
            </>
          )}
        </Fieldset>
      )}

  )
}

AssessmentResults.propTypes = {
  assessmentCustomFields: PropTypes.object,
  assessmentPeriod: PropTypes.shape({
    start: PropTypes.object,
    end: PropTypes.object
  }),
  canEdit: PropTypes.bool,
  entity: PropTypes.object,
  label: PropTypes.string,
  refetch: PropTypes.func,
  style: PropTypes.object,
  subEntities: PropTypes.array
}

export default AssessmentResults
<|endoftext|>


<commit_before>import React from "react";
import { toNumber } from "lodash-es";
import { connect } from "react-redux";
import { Row, Col, Panel } from "react-bootstrap";

import { updateSetting } from "../../actions";
import { Checkbox, Icon, InputError } from "../../../base";

const HTTPCheckboxLabel = () => (

        Enable API

);

const HTTPFooter = () => (

        <Icon name="warning" /> Changes to these settings will only take effect when the server is reloaded.

);

const HTTPOptions = (props) => (
    <Row>
        <Col xs={12}>

HTTP Server

        </Col>
        <Col xs={12} md={6} mdPush={6}>
            <Panel>
                <Panel.Body>
                    Change the address and port the the web server listens on.
                </Panel.Body>
                <Panel.Footer>
                    <HTTPFooter />
                </Panel.Footer>
            </Panel>
        </Col>
        <Col xs={12} md={6} mdPull={6}>
            <Panel>
                <Panel.Body>
                    <InputError
                        label="Host"
                        autoComplete={false}
                        onSave={props.onUpdateHost}
                        initialValue={props.host}
                        noMargin
                        withButton
                    />
                    <InputError
                        label="Port"
                        type="number"
                        autoComplete={false}
                        onSave={props.onUpdatePort}
                        initialValue={props.port}
                        noMargin
                        withButton
                    />
                    <Checkbox
                        label={<HTTPCheckboxLabel />}
                        checked={props.enableApi}
                        onClick={() => props.onUpdateAPI(!props.enableApi)}
                    />
                </Panel.Body>
            </Panel>
        </Col>
    </Row>
);

const mapStateToProps = (state) => ({
    host: state.settings.data.server_host,
    port: state.settings.data.server_port,
    enableApi: state.settings.data.enable_api
});

const mapDispatchToProps = (dispatch) => ({

    onUpdateHost: (e) => {
        dispatch(updateSetting("server_host", e.value));
    },

    onUpdatePort: (e) => {
        dispatch(updateSetting("server_port", toNumber(e.value)));
    },

    onUpdateAPI: (value) => {
        dispatch(updateSetting("enable_api", value));
    }

});

export default connect(mapStateToProps, mapDispatchToProps)(HTTPOptions);
<commit_msg>Fix broken link<commit_after>import React from "react";
import { toNumber } from "lodash-es";
import { connect } from "react-redux";
import { Row, Col, Panel } from "react-bootstrap";

import { updateSetting } from "../../actions";
import { Checkbox, Icon, InputError } from "../../../base";

const HTTPCheckboxLabel = () => (

        Enable API

);

const HTTPFooter = () => (

        <Icon name="warning" /> Changes to these settings will only take effect when the server is reloaded.

);

const HTTPOptions = (props) => (
    <Row>
        <Col xs={12}>

HTTP Server

        </Col>
        <Col xs={12} md={6} mdPush={6}>
            <Panel>
                <Panel.Body>
                    Change the address and port the the web server listens on.
                </Panel.Body>
                <Panel.Footer>
                    <HTTPFooter />
                </Panel.Footer>
            </Panel>
        </Col>
        <Col xs={12} md={6} mdPull={6}>
            <Panel>
                <Panel.Body>
                    <InputError
                        label="Host"
                        autoComplete={false}
                        onSave={props.onUpdateHost}
                        initialValue={props.host}
                        noMargin
                        withButton
                    />
                    <InputError
                        label="Port"
                        type="number"
                        autoComplete={false}
                        onSave={props.onUpdatePort}
                        initialValue={props.port}
                        noMargin
                        withButton
                    />
                    <Checkbox
                        label={<HTTPCheckboxLabel />}
                        checked={props.enableApi}
                        onClick={() => props.onUpdateAPI(!props.enableApi)}
                    />
                </Panel.Body>
            </Panel>
        </Col>
    </Row>
);

const mapStateToProps = (state) => ({
    host: state.settings.data.server_host,
    port: state.settings.data.server_port,
    enableApi: state.settings.data.enable_api
});

const mapDispatchToProps = (dispatch) => ({

    onUpdateHost: (e) => {
        dispatch(updateSetting("server_host", e.value));
    },

    onUpdatePort: (e) => {
        dispatch(updateSetting("server_port", toNumber(e.value)));
    },

    onUpdateAPI: (value) => {
        dispatch(updateSetting("enable_api", value));
    }

});

export default connect(mapStateToProps, mapDispatchToProps)(HTTPOptions);
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { FlowRouter } from 'meteor/kadira:flow-router';

import { MeetingSeries } from '/imports/meetingseries'
import { Minutes } from '/imports/minutes'
import { UserRoles } from '/imports/userroles'
import { User, userSettings } from '/imports/users'

import { TopicListConfig } from '../topic/topicsList'
import { ItemListConfig } from './itemsList'

let _meetingSeriesID;   // the parent meeting object of this minutes

Template.meetingSeriesDetails.onCreated(function () {
    this.autorun(() => {
        _meetingSeriesID = FlowRouter.getParam('_id');
        this.subscribe('meetingseries', _meetingSeriesID);

        this.showSettingsDialog = FlowRouter.getQueryParam('edit') === 'true';

        let usrRoles = new UserRoles();
        if (!usrRoles.hasViewRoleFor(_meetingSeriesID)) {
            FlowRouter.go('/');
        }
    });

    Session.setDefault("currentTab", "minutesList");
});

Template.meetingSeriesDetails.onRendered(function () {
    Session.set("currentTab", "minutesList");

    if (this.showSettingsDialog) {
        Session.set("meetingSeriesEdit.showUsersPanel", true);
        $('#dlgEditMeetingSeries').modal('show');
    }
});

Template.meetingSeriesDetails.helpers({
    meetingSeries: function() {
        return new MeetingSeries(_meetingSeriesID);
    },

    showQuickHelp: function() {
        const user = new User();
        return user.getSetting(userSettings.showQuickHelp.meetingSeries, true);
    },

    minutes: function() {
        let ms = new MeetingSeries(_meetingSeriesID);
        return ms.getAllMinutes();
    },

    tab: function() {
        return Session.get("currentTab");
    },

    tabData: function() {
        let tab = Session.get("currentTab");
        let ms = new MeetingSeries(_meetingSeriesID);

        switch (tab) {
            case "minutesList":
                return {
                    minutes: ms.getAllMinutes(),
                    meetingSeriesId: _meetingSeriesID
                };

            case "topicsList":
                let status = Session.get("actionItemStatus");
                let  topics;
                switch (status) {
                    case "open":
                        topics = ms.openTopics;
                        break;
                    case "topics":
                        topics = ms.topics;
                        break;
                    default:
                        throw new Meteor.Error("illegal-state", "Unknown topic list status: " + status);
                }

                return new TopicListConfig(topics, null, true, _meetingSeriesID);

            case "itemsList":
                return new ItemListConfig(ms.topics, _meetingSeriesID);
        }
    },

    isModerator: function () {
        let usrRole = new UserRoles();
        return usrRole.isModeratorOf(_meetingSeriesID);
    }
});

Template.meetingSeriesDetails.events({
    "click #btnHideHelp": function () {
        const user = new User();
        user.storeSetting(userSettings.showQuickHelp.meetingSeries, false);
    },
    "click .nav-tabs li": function(event) {
        var currentTab = $(event.target).closest("li");

        currentTab.addClass("active");
        $(".nav-tabs li").not(currentTab).removeClass("active");

        Session.set("currentTab", currentTab.data("template"));

        if (currentTab.data("action")) {
            Session.set("actionItemStatus", currentTab.data("action"));
        }
    }
});
<commit_msg>Remove subscription from meeting series details<commit_after>import { Meteor } from 'meteor/meteor';
import { FlowRouter } from 'meteor/kadira:flow-router';

import { MeetingSeries } from '/imports/meetingseries'
import { Minutes } from '/imports/minutes'
import { UserRoles } from '/imports/userroles'
import { User, userSettings } from '/imports/users'

import { TopicListConfig } from '../topic/topicsList'
import { ItemListConfig } from './itemsList'

let _meetingSeriesID;   // the parent meeting object of this minutes

Template.meetingSeriesDetails.onCreated(function () {
    this.autorun(() => {
        _meetingSeriesID = FlowRouter.getParam('_id');
        this.showSettingsDialog = FlowRouter.getQueryParam('edit') === 'true';

        let usrRoles = new UserRoles();
        if (!usrRoles.hasViewRoleFor(_meetingSeriesID)) {
            FlowRouter.go('/');
        }
    });

    Session.setDefault("currentTab", "minutesList");
});

Template.meetingSeriesDetails.onRendered(function () {
    Session.set("currentTab", "minutesList");

    if (this.showSettingsDialog) {
        Session.set("meetingSeriesEdit.showUsersPanel", true);
        $('#dlgEditMeetingSeries').modal('show');
    }
});

Template.meetingSeriesDetails.helpers({
    meetingSeries: function() {
        return new MeetingSeries(_meetingSeriesID);
    },

    showQuickHelp: function() {
        const user = new User();
        return user.getSetting(userSettings.showQuickHelp.meetingSeries, true);
    },

    minutes: function() {
        let ms = new MeetingSeries(_meetingSeriesID);
        return ms.getAllMinutes();
    },

    tab: function() {
        return Session.get("currentTab");
    },

    tabData: function() {
        let tab = Session.get("currentTab");
        let ms = new MeetingSeries(_meetingSeriesID);

        switch (tab) {
            case "minutesList":
                return {
                    minutes: ms.getAllMinutes(),
                    meetingSeriesId: _meetingSeriesID
                };

            case "topicsList":
                let status = Session.get("actionItemStatus");
                let  topics;
                switch (status) {
                    case "open":
                        topics = ms.openTopics;
                        break;
                    case "topics":
                        topics = ms.topics;
                        break;
                    default:
                        throw new Meteor.Error("illegal-state", "Unknown topic list status: " + status);
                }

                return new TopicListConfig(topics, null, true, _meetingSeriesID);

            case "itemsList":
                return new ItemListConfig(ms.topics, _meetingSeriesID);
        }
    },

    isModerator: function () {
        let usrRole = new UserRoles();
        return usrRole.isModeratorOf(_meetingSeriesID);
    }
});

Template.meetingSeriesDetails.events({
    "click #btnHideHelp": function () {
        const user = new User();
        user.storeSetting(userSettings.showQuickHelp.meetingSeries, false);
    },
    "click .nav-tabs li": function(event) {
        var currentTab = $(event.target).closest("li");

        currentTab.addClass("active");
        $(".nav-tabs li").not(currentTab).removeClass("active");

        Session.set("currentTab", currentTab.data("template"));

        if (currentTab.data("action")) {
            Session.set("actionItemStatus", currentTab.data("action"));
        }
    }
});
<|endoftext|>


<commit_before>/* eslint unicorn/filename-case: "off", func-names: "off", camelcase: "off", no-unused-vars: "off", no-negated-condition: "off" */

module.exports = function (iface) {
    const {mqttPub, mqttSub, mqttStatus, log, newAccessory, Service, Characteristic} = iface;

    return function createAccessory_ContactSensor(settings) {
        const sensor = newAccessory(settings);

        sensor.addService(Service.ContactSensor, settings.name)
            .getCharacteristic(Characteristic.ContactSensorState)
            .on('get', callback => {
                log.debug('< hap get', settings.name, 'ContactSensorState');
                const contact = mqttStatus[settings.topic.statusContactSensorState] === settings.payload.onContactDetected ?
                    Characteristic.ContactSensorState.CONTACT_DETECTED :
                    Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;

                log.debug('> hap re_get', settings.name, 'ContactSensorState', contact);
                callback(null, contact);
            });

        mqttSub(settings.topic.statusContactSensorState, val => {
            const contact = val === settings.payload.onContactDetected ?
                Characteristic.ContactSensorState.CONTACT_DETECTED :
                Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
            log.debug('> hap update', settings.name, 'ContactSensorState', contact);
            sensor.getService(Service.ContactSensor)
                .updateCharacteristic(Characteristic.ContactSensorState, contact);
        });

        /* istanbul ignore else */
		/* Optional: Low Battery Status */
        if (settings.topic.statusLowBattery) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusLowBattery)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusLowBattery');
                    const bat = mqttStatus[settings.topic.statusLowBattery] !== settings.payload.onLowBattery ?
                        Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL :
                        Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
                    log.debug('> hap re_get', settings.name, 'StatusLowBattery', bat);
                    callback(null, bat);
                });

            mqttSub(settings.topic.statusLowBattery, val => {
                const bat = val !== settings.payload.onLowBattery ?
                    Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL :
                    Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
                log.debug('> hap update', settings.name, 'StatusLowBattery', bat);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusLowBattery, bat);
            });
        }

        /* istanbul ignore else */
        /* Optional: Status Active */
        if (settings.topic.statusActive) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusActive)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusActive');
                    const act = mqttStatus[settings.topic.statusActive] !== settings.payload.onStatusActive ? 0 : 1;
                    log.debug('> hap re_get', settings.name, 'StatusActive', act);
                    callback(null, act);
                });

            mqttSub(settings.topic.statusActive, val => {
                const act = val !== settings.payload.onStatusActive ? 0 : 1;
                log.debug('> hap update', settings.name, 'StatusActive', act);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusActive, act);
            });
        }

        /* istanbul ignore else */
        /* Optional: Status Fault */
        if (settings.topic.statusFault) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusFault)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusFault');
                    const fault = mqttStatus[settings.topic.statusFault] !== settings.payload.onStatusFault ?
                        Characteristic.StatusFault.NO_FAULT :
                        Characteristic.StatusFault.GENERAL_FAULT
                    log.debug('> hap re_get', settings.name, 'StatusFault', fault);
                    callback(null, fault);
                });

            mqttSub(settings.topic.statusFault, val => {
                const fault = val !== settings.payload.onStatusFault ?
                    Characteristic.StatusFault.NO_FAULT :
                    Characteristic.StatusFault.GENERAL_FAULT;
                log.debug('> hap update', settings.name, 'StatusFault', fault);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusFault, fault);
            });
        }

        /* istanbul ignore else */
        /* Optional: Status Tampered */
        if (settings.topic.statusTampered) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusTampered)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusTampered');
                    const tampered = mqttStatus[settings.topic.statusTampered] !== settings.payload.onTampered ?
                        Characteristic.StatusTampered.NOT_TAMPERED :
                        Characteristic.StatusTampered.TAMPERED;
                    log.debug('> hap re_get', settings.name, 'StatusTampered', tampered);
                    callback(null, tampered);
                });

            mqttSub(settings.topic.statusTampered, val => {
                const tampered = val !== settings.payload.onStatusTampered ?
                    Characteristic.StatusTampered.NOT_TAMPERED :
                    Characteristic.StatusTampered.TAMPERED;
                log.debug('> hap update', settings.name, 'StatusTampered', tampered);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusTampered, tampered);
            });
        }

        return sensor;
    };
};
<commit_msg>Removed whitespace and added missing semicolon.<commit_after>/* eslint unicorn/filename-case: "off", func-names: "off", camelcase: "off", no-unused-vars: "off", no-negated-condition: "off" */

module.exports = function (iface) {
    const {mqttPub, mqttSub, mqttStatus, log, newAccessory, Service, Characteristic} = iface;

    return function createAccessory_ContactSensor(settings) {
        const sensor = newAccessory(settings);

        sensor.addService(Service.ContactSensor, settings.name)
            .getCharacteristic(Characteristic.ContactSensorState)
            .on('get', callback => {
                log.debug('< hap get', settings.name, 'ContactSensorState');
                const contact = mqttStatus[settings.topic.statusContactSensorState] === settings.payload.onContactDetected ?
                    Characteristic.ContactSensorState.CONTACT_DETECTED :
                    Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;

                log.debug('> hap re_get', settings.name, 'ContactSensorState', contact);
                callback(null, contact);
            });

        mqttSub(settings.topic.statusContactSensorState, val => {
            const contact = val === settings.payload.onContactDetected ?
                Characteristic.ContactSensorState.CONTACT_DETECTED :
                Characteristic.ContactSensorState.CONTACT_NOT_DETECTED;
            log.debug('> hap update', settings.name, 'ContactSensorState', contact);
            sensor.getService(Service.ContactSensor)
                .updateCharacteristic(Characteristic.ContactSensorState, contact);
        });

        /* istanbul ignore else */
		/* Optional: Low Battery Status */
        if (settings.topic.statusLowBattery) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusLowBattery)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusLowBattery');
                    const bat = mqttStatus[settings.topic.statusLowBattery] !== settings.payload.onLowBattery ?
                        Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL :
                        Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
                    log.debug('> hap re_get', settings.name, 'StatusLowBattery', bat);
                    callback(null, bat);
                });

            mqttSub(settings.topic.statusLowBattery, val => {
                const bat = val !== settings.payload.onLowBattery ?
                    Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL :
                    Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
                log.debug('> hap update', settings.name, 'StatusLowBattery', bat);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusLowBattery, bat);
            });
        }

        /* istanbul ignore else */
        /* Optional: Status Active */
        if (settings.topic.statusActive) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusActive)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusActive');
                    const act = mqttStatus[settings.topic.statusActive] !== settings.payload.onStatusActive ? 0 : 1;
                    log.debug('> hap re_get', settings.name, 'StatusActive', act);
                    callback(null, act);
                });

            mqttSub(settings.topic.statusActive, val => {
                const act = val !== settings.payload.onStatusActive ? 0 : 1;
                log.debug('> hap update', settings.name, 'StatusActive', act);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusActive, act);
            });
        }

        /* istanbul ignore else */
        /* Optional: Status Fault */
        if (settings.topic.statusFault) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusFault)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusFault');
                    const fault = mqttStatus[settings.topic.statusFault] !== settings.payload.onStatusFault ?
                        Characteristic.StatusFault.NO_FAULT :
                        Characteristic.StatusFault.GENERAL_FAULT;
                    log.debug('> hap re_get', settings.name, 'StatusFault', fault);
                    callback(null, fault);
                });

            mqttSub(settings.topic.statusFault, val => {
                const fault = val !== settings.payload.onStatusFault ?
                    Characteristic.StatusFault.NO_FAULT :
                    Characteristic.StatusFault.GENERAL_FAULT;
                log.debug('> hap update', settings.name, 'StatusFault', fault);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusFault, fault);
            });
        }

        /* istanbul ignore else */
        /* Optional: Status Tampered */
        if (settings.topic.statusTampered) {
            sensor.getService(Service.ContactSensor, settings.name)
                .getCharacteristic(Characteristic.StatusTampered)
                .on('get', callback => {
                    log.debug('< hap get', settings.name, 'StatusTampered');
                    const tampered = mqttStatus[settings.topic.statusTampered] !== settings.payload.onTampered ?
                        Characteristic.StatusTampered.NOT_TAMPERED :
                        Characteristic.StatusTampered.TAMPERED;
                    log.debug('> hap re_get', settings.name, 'StatusTampered', tampered);
                    callback(null, tampered);
                });

            mqttSub(settings.topic.statusTampered, val => {
                const tampered = val !== settings.payload.onStatusTampered ?
                    Characteristic.StatusTampered.NOT_TAMPERED :
                    Characteristic.StatusTampered.TAMPERED;
                log.debug('> hap update', settings.name, 'StatusTampered', tampered);
                sensor.getService(Service.ContactSensor)
                    .updateCharacteristic(Characteristic.StatusTampered, tampered);
            });
        }

        return sensor;
    };
};
<|endoftext|>


<commit_before>// --------------------------------------------------------------------------------------------------------------------
// tyn.io - (c) 2015 Tynio.
// --------------------------------------------------------------------------------------------------------------------

// core
var util = require('util')
var dgram = require('dgram')
var events = require('events')
var os = require('os')

// --------------------------------------------------------------------------------------------------------------------

var TYPES = {
  c : true,
  g : true,
  t : true,
  s : true,
}

function getPeriod(interval) {
  var period = Math.floor(Date.now() / interval) * interval
  return new Date(period)
}

function createStatsServer(opts, callback) {
  // check which options we have been given
  if ( !opts ) {
    opts = {}
  }
  if ( typeof opts === 'function') {
    callback = opts
    opts = {}
  }
  callback = callback || function() {}

  var port     = opts.port     || 9526
  var interval = opts.interval || 15 * 1000 // default: 15s
  var info = {
    pid : process.pid,
    host : os.hostname(),
  }

  // to emit 'stats' messages
  var ee = new events.EventEmitter()

  // remember which period we're currently in
  var currentPeriod

  // this is the data we'll use for this server
  var counters = {
    'statto.packets.total' : 0,
    'statto.msgs.total'    : 0,
    'statto.msgs.good'     : 0,
    'statto.msgs.bad'      : 0,
  }
  var timers   = {}
  var gauges   = {}
  var sets     = {}

  var server = dgram.createSocket('udp4')

  server.on("error", function (err) {
    // console.log("server error:\n" + err.stack)
    server.close()
    callback(err)
  })

  server.on('message', function (msg, rinfo) {
    ee.emit('debug', util.format('Received %d bytes from %s:%d', msg.length, rinfo.address, rinfo.port))

    // some meta stats
    counters['statto.packets.total']++

    // ToDo: convert op into multiple ops if string contains "\n"
    var op = msg.toString()
    op = op.replace(/\n$/, '')
    ee.emit('debug', 'Op = ' + op)

    // see what type of message this is:
    var parts = op.split(/:/)

    var type = parts[0]
    var key  = parts[1]
    var val  = type === 's' ? parts[2] : parts[2]|0

    counters['statto.msgs.total']++
    if ( type in TYPES ) {
      counters['statto.msgs.good']++
    }
    else {
      counters['statto.msgs.bad']++
      return
    }

    if ( type === 'c' ) {
      // this is a counter
      if ( !counters[key] ) {
        counters[key] = 0
      }
      counters[key] += val
    }
    else if ( type === 'g' ) {
      // gauge
      gauges[key] = val
    }
    else if ( type === 't' ) {
      // timer
      if ( !timers[key] ) {
        timers[key] = []
      }
      timers[key].push(val)
    }
    else if ( type === 's' ) {
      // set
      if ( !sets[key] ) {
        sets[key] = {}
      }
      if ( !sets[key][val] ) {
        sets[key][val] = 0
      }
      sets[key][val] += 1
    }
    else {
      throw new Error('Program error, unknown type ' + type)
    }
  })

  server.bind(port, function() {
    callback(null, port)
  })

  function flush() {
    // remember the last period and the stats
    var ts = currentPeriod.toISOString()
    var lastStats = {
      counters : counters,
      gauges   : gauges,
      timers   : timers,
      sets     : sets,
      info     : info,
      ts       : ts,
    }

    // emit these on the nextTick
    process.nextTick(function() {
      ee.emit('stats', lastStats)
    })

    // reset the current stats
    counters = {
      'statto.packets.total' : 0,
      'statto.msgs.total'    : 0,
      'statto.msgs.good'     : 0,
      'statto.msgs.bad'      : 0,
    }
    timers   = {}
    gauges   = {}
    sets     = {}

    // set the new currentPeriod
    currentPeriod = getPeriod(interval)

    // figure out the next interval
    var nextPeriod = currentPeriod.getTime() + interval
    setTimeout(flush, nextPeriod - Date.now())
  }

  // set the new currentPeriod
  currentPeriod = getPeriod(interval)

  // figure out the next interval
  var nextPeriod = currentPeriod.getTime() + interval
  setTimeout(flush, nextPeriod - Date.now())

  return ee
}

// --------------------------------------------------------------------------------------------------------------------

module.exports = createStatsServer

// --------------------------------------------------------------------------------------------------------------------
<commit_msg>Add ability to process multiple ops in each message<commit_after>// --------------------------------------------------------------------------------------------------------------------
// tyn.io - (c) 2015 Tynio.
// --------------------------------------------------------------------------------------------------------------------

// core
var util = require('util')
var dgram = require('dgram')
var events = require('events')
var os = require('os')

// --------------------------------------------------------------------------------------------------------------------

var TYPES = {
  c : true,
  g : true,
  t : true,
  s : true,
}

function getPeriod(interval) {
  var period = Math.floor(Date.now() / interval) * interval
  return new Date(period)
}

function createStatsServer(opts, callback) {
  // check which options we have been given
  if ( !opts ) {
    opts = {}
  }
  if ( typeof opts === 'function') {
    callback = opts
    opts = {}
  }
  callback = callback || function() {}

  var port     = opts.port     || 9526
  var interval = opts.interval || 15 * 1000 // default: 15s
  var info = {
    pid : process.pid,
    host : os.hostname(),
  }

  // to emit 'stats' messages
  var ee = new events.EventEmitter()

  // remember which period we're currently in
  var currentPeriod

  // this is the data we'll use for this server
  var counters = {
    'statto.packets.total' : 0,
    'statto.msgs.total'    : 0,
    'statto.msgs.good'     : 0,
    'statto.msgs.bad'      : 0,
  }
  var gauges   = {}
  var timers   = {}
  var sets     = {}

  var server = dgram.createSocket('udp4')

  server.on("error", function (err) {
    // console.log("server error:\n" + err.stack)
    server.close()
    callback(err)
  })

  server.on('message', function (msg, rinfo) {
    ee.emit('debug', util.format('Received %d bytes from %s:%d', msg.length, rinfo.address, rinfo.port))

    // some meta stats
    counters['statto.packets.total']++

    // for each command in this message
    var str = msg.toString().replace(/\n+$/, '')
    var commands = str.split("\n")

    commands.forEach(function(op) {
      ee.emit('debug', 'Op = ' + op)

      // see what type of message this is:
      var parts = op.split(/:/)

      if ( parts.length !== 3 ) {
        counters['statto.msgs.total']++
        counters['statto.msgs.bad']++
        if ( !sets['statto.bad'] ) {
          sets['statto.bad'] = {}
        }
        if ( sets['statto.bad'][parts.join(':')] ) {
          // add one
          sets['statto.bad'][parts.join(':')] += 1
        }
        else {
          // initialise with one
          sets['statto.bad'][parts.join(':')] = 1
        }
        return
      }

      var type = parts[0]
      var key  = parts[1]
      var val  = type === 's' ? parts[2] : parts[2]|0

      counters['statto.msgs.total']++
      if ( type in TYPES ) {
        counters['statto.msgs.good']++
      }
      else {
        counters['statto.msgs.bad']++
        return
      }

      if ( type === 'c' ) {
        // this is a counter
        if ( !counters[key] ) {
          counters[key] = 0
        }
        counters[key] += val
      }
      else if ( type === 'g' ) {
        // gauge
        gauges[key] = val
      }
      else if ( type === 't' ) {
        // timer
        if ( !timers[key] ) {
          timers[key] = []
        }
        timers[key].push(val)
      }
      else if ( type === 's' ) {
        // set
        if ( !sets[key] ) {
          sets[key] = {}
        }
        if ( !sets[key][val] ) {
          sets[key][val] = 0
        }
        sets[key][val] += 1
      }
      else {
        throw new Error('Program error, unknown type ' + type)
      }
    })
  })

  server.bind(port, function() {
    callback(null, port)
  })

  function flush() {
    // remember the last period and the stats
    var ts = currentPeriod.toISOString()
    var lastStats = {
      counters : counters,
      gauges   : gauges,
      timers   : timers,
      sets     : sets,
      info     : info,
      ts       : ts,
    }

    // emit these on the nextTick
    process.nextTick(function() {
      ee.emit('stats', lastStats)
    })

    // reset the current stats
    counters = {
      'statto.packets.total' : 0,
      'statto.msgs.total'    : 0,
      'statto.msgs.good'     : 0,
      'statto.msgs.bad'      : 0,
    }
    gauges   = {}
    timers   = {}
    sets     = {}

    // set the new currentPeriod
    currentPeriod = getPeriod(interval)

    // figure out the next interval
    var nextPeriod = currentPeriod.getTime() + interval
    setTimeout(flush, nextPeriod - Date.now())
  }

  // set the new currentPeriod
  currentPeriod = getPeriod(interval)

  // figure out the next interval
  var nextPeriod = currentPeriod.getTime() + interval
  setTimeout(flush, nextPeriod - Date.now())

  return ee
}

// --------------------------------------------------------------------------------------------------------------------

module.exports = createStatsServer

// --------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>'use strict';

const status = {
    OK: 200,
    BadRequest: 400,
    NotFound: 404,
    NotAcceptable: 406,
    UnprocessableEntity: 422,
    InternalServerError: 500,
    GatewayTimeout: 504,
};

const error = {
    RequestError: 1,
    ResponseTimeout: 2,
    JsonError: 3,
    InvalidAction: 4,
    MissingAction: 5,
    ServerError: 6,
};

module.exports = {
    OK: {
        status: status.OK
    },
    RequestError: {
        status: status.BadRequest,
        error: error.RequestError
    },
    ResponseTimeout: {
        status: status.GatewayTimeout,
        error: error.ResponseTimeout
    },
    JsonError: {
        status: status.UnprocessableEntity,
        error: error.JsonError
    },
    InvalidAction: {
        status: status.NotAcceptable,
        error: error.InvalidAction
    },
    MissingAction: {
        status: status.NotFound,
        error: error.MissingAction
    },
    ServerError: {
        status: status.InternalServerError,
        error: error.ServerError
    },
};
<commit_msg>syntax fix<commit_after>'use strict';

const status = {
    OK: 200,
    BadRequest: 400,
    NotFound: 404,
    NotAcceptable: 406,
    UnprocessableEntity: 422,
    InternalServerError: 500,
    GatewayTimeout: 504
};

const error = {
    RequestError: 1,
    ResponseTimeout: 2,
    JsonError: 3,
    InvalidAction: 4,
    MissingAction: 5,
    ServerError: 6
};

module.exports = {
    OK: {
        status: status.OK
    },
    RequestError: {
        status: status.BadRequest,
        error: error.RequestError
    },
    ResponseTimeout: {
        status: status.GatewayTimeout,
        error: error.ResponseTimeout
    },
    JsonError: {
        status: status.UnprocessableEntity,
        error: error.JsonError
    },
    InvalidAction: {
        status: status.NotAcceptable,
        error: error.InvalidAction
    },
    MissingAction: {
        status: status.NotFound,
        error: error.MissingAction
    },
    ServerError: {
        status: status.InternalServerError,
        error: error.ServerError
    }
};
<|endoftext|>


<commit_before>import { AppLoading, Asset, Constants, Font } from 'expo';
import React from 'react';
import { ActivityIndicator, Linking, Platform, StatusBar, StyleSheet, View } from 'react-native';
import { NavigationProvider, StackNavigation } from '@expo/ex-navigation';
import { ActionSheetProvider } from '@expo/react-native-action-sheet';
import { Ionicons, MaterialIcons } from '@expo/vector-icons';

import getViewerUsernameAsync from './utils/getViewerUsernameAsync';
import addListenerWithNativeCallback from './utils/addListenerWithNativeCallback';
import HistoryActions from './redux/HistoryActions';
import jwtDecode from 'jwt-decode';
import SessionActions from './redux/SessionActions';
import SettingsActions from './redux/SettingsActions';
import LocalStorage from './storage/LocalStorage';
import MenuView from './menu/MenuView';
import Store from './redux/Store';

import customNavigationContext from './navigation/customNavigationContext';

function cacheImages(images) {
  return images.map(image => Asset.fromModule(image).downloadAsync());
}

export default class App extends React.Component {
  state = {
    isReady: false,
  };

  componentDidMount() {
    this._initializeStateAsync();
    addListenerWithNativeCallback(
      'ExponentKernel.getIsValidHomeManifestToOpen',
      this._getIsValidHomeManifestToOpen
    );
  }

  _getIsValidHomeManifestToOpen = async event => {
    const { manifest } = event;
    let isValid = false;
    if (!Constants.isDevice) {
      // simulator has no restriction
      isValid = true;
    } else if (manifest) {
      if (manifest.developer && manifest.developer.tool) {
        isValid = true;
      } else if (manifest.slug === 'snack') {
        isValid = true;
      } else if (manifest.id) {
        try {
          let manifestAuthorComponents = manifest.id.split('/');
          let manifestAuthor = manifestAuthorComponents[0].substring(1);

          let username = await getViewerUsernameAsync();

          if (username && manifestAuthor && manifestAuthor === username) {
            isValid = true;
          }
        } catch (_) {}
      }
    }
    return { isValid };
  };

  _initializeStateAsync = async () => {
    try {
      Store.dispatch(SettingsActions.loadSettings());
      Store.dispatch(HistoryActions.loadHistory());
      await LocalStorage.migrateNuxStateToNativeAsync();
      const storedSession = await LocalStorage.getSessionAsync();

      if (storedSession) {
        Store.dispatch(SessionActions.setSession(storedSession));
      }

      if (Platform.OS === 'ios') {
        await Promise.all([Font.loadAsync(Ionicons.font)]);
      } else {
        await Promise.all([Font.loadAsync(Ionicons.font), Font.loadAsync(MaterialIcons.font)]);
      }
    } catch (e) {
      // ..
    } finally {
      this.setState({ isReady: true }, async () => {
        if (Platform.OS == 'ios') {
          // if expo client is opened via deep linking, we'll get the url here
          const initialUrl = await Linking.getInitialURL();
          if (initialUrl) {
            Linking.openURL(initialUrl);
          }
        }
      });
    }
  };

  render() {
    if (!this.state.isReady) {
      return <AppLoading />;
    }

    return (
      <View style={styles.container}>
        <ActionSheetProvider>
          <NavigationProvider context={customNavigationContext}>
            {this.state.isReady && <StackNavigation id="root" initialRoute="rootNavigation" />}
          </NavigationProvider>
        </ActionSheetProvider>

        {Platform.OS === 'ios' && <StatusBar barStyle="default" />}
        {Platform.OS === 'android' && <View style={styles.statusBarUnderlay} />}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  statusBarUnderlay: {
    height: 24,
    backgroundColor: 'rgba(0,0,0,0.2)',
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
  },
});
<commit_msg>Use statusBarHeight constant for underlay<commit_after>import { AppLoading, Asset, Constants, Font } from 'expo';
import React from 'react';
import { ActivityIndicator, Linking, Platform, StatusBar, StyleSheet, View } from 'react-native';
import { NavigationProvider, StackNavigation } from '@expo/ex-navigation';
import { ActionSheetProvider } from '@expo/react-native-action-sheet';
import { Ionicons, MaterialIcons } from '@expo/vector-icons';

import getViewerUsernameAsync from './utils/getViewerUsernameAsync';
import addListenerWithNativeCallback from './utils/addListenerWithNativeCallback';
import HistoryActions from './redux/HistoryActions';
import jwtDecode from 'jwt-decode';
import SessionActions from './redux/SessionActions';
import SettingsActions from './redux/SettingsActions';
import LocalStorage from './storage/LocalStorage';
import MenuView from './menu/MenuView';
import Store from './redux/Store';

import customNavigationContext from './navigation/customNavigationContext';

function cacheImages(images) {
  return images.map(image => Asset.fromModule(image).downloadAsync());
}

export default class App extends React.Component {
  state = {
    isReady: false,
  };

  componentDidMount() {
    this._initializeStateAsync();
    addListenerWithNativeCallback(
      'ExponentKernel.getIsValidHomeManifestToOpen',
      this._getIsValidHomeManifestToOpen
    );
  }

  _getIsValidHomeManifestToOpen = async event => {
    const { manifest } = event;
    let isValid = false;
    if (!Constants.isDevice) {
      // simulator has no restriction
      isValid = true;
    } else if (manifest) {
      if (manifest.developer && manifest.developer.tool) {
        isValid = true;
      } else if (manifest.slug === 'snack') {
        isValid = true;
      } else if (manifest.id) {
        try {
          let manifestAuthorComponents = manifest.id.split('/');
          let manifestAuthor = manifestAuthorComponents[0].substring(1);

          let username = await getViewerUsernameAsync();

          if (username && manifestAuthor && manifestAuthor === username) {
            isValid = true;
          }
        } catch (_) {}
      }
    }
    return { isValid };
  };

  _initializeStateAsync = async () => {
    try {
      Store.dispatch(SettingsActions.loadSettings());
      Store.dispatch(HistoryActions.loadHistory());
      await LocalStorage.migrateNuxStateToNativeAsync();
      const storedSession = await LocalStorage.getSessionAsync();

      if (storedSession) {
        Store.dispatch(SessionActions.setSession(storedSession));
      }

      if (Platform.OS === 'ios') {
        await Promise.all([Font.loadAsync(Ionicons.font)]);
      } else {
        await Promise.all([Font.loadAsync(Ionicons.font), Font.loadAsync(MaterialIcons.font)]);
      }
    } catch (e) {
      // ..
    } finally {
      this.setState({ isReady: true }, async () => {
        if (Platform.OS == 'ios') {
          // if expo client is opened via deep linking, we'll get the url here
          const initialUrl = await Linking.getInitialURL();
          if (initialUrl) {
            Linking.openURL(initialUrl);
          }
        }
      });
    }
  };

  render() {
    if (!this.state.isReady) {
      return <AppLoading />;
    }

    return (
      <View style={styles.container}>
        <ActionSheetProvider>
          <NavigationProvider context={customNavigationContext}>
            {this.state.isReady && <StackNavigation id="root" initialRoute="rootNavigation" />}
          </NavigationProvider>
        </ActionSheetProvider>

        {Platform.OS === 'ios' && <StatusBar barStyle="default" />}
        {Platform.OS === 'android' && <View style={styles.statusBarUnderlay} />}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  statusBarUnderlay: {
    height: Constants.statusBarHeight,
    backgroundColor: 'rgba(0,0,0,0.2)',
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
  },
});
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
const { string } = React.PropTypes

const Landing = React.createClass({
  // this is comming from redux via connect
  propType: {
    searchTerm: string
  },
  render () {
    return (

svideo

        <input value={this.props.searchTerm} type='text' placeholder='search' />
        <Link to='/search'>or Browse All</Link>

    )
  }
})

// pull from redux and pass as a prop
const mapStateToProps = (state) => {
  return {
    searchTerm: state.searchTerm
  }
}

export default connect(mapStateToProps)(Landing)
<commit_msg>dispatching action to the root reducer<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { setSearchTerm } from './actionCreators'
const { string, func } = React.PropTypes

const Landing = React.createClass({
  // this is comming from redux via connect
  propType: {
    searchTerm: string,
    dispatch: func
  },
  handleSearchTermChange (event) {
    // dispatch comes from connect
    this.props.dispatch(setSearchTerm(event.target.value))
  },
  render () {
    return (

svideo

        <input onChange={this.handleSearchTermChange} value={this.props.searchTerm} type='text' placeholder='search' />
        <Link to='/search'>or Browse All</Link>

    )
  }
})

// pull from redux and pass as a prop
const mapStateToProps = (state) => {
  return {
    searchTerm: state.searchTerm
  }
}

export default connect(mapStateToProps)(Landing)
<|endoftext|>