// <Class definitions>
var Setup = new Class({
	initialize: function(theDatasizeInBytes) {
		this.datasize=theDatasizeInBytes;
		this.startTime=0;
		this.endTime=0;
		this.throughput=0;
	},
  
	startBandwidthTest: function() {
		this.startTime = new Date().getTime();
	},
	
	endBandwidthTest: function() {
		this.endTime = new Date().getTime();
	},
	
	getThroughput: function() {
		if (this.throughput == 0) {
			if (this.startTime > 0 && this.endTime > 0) {
				var diffTimeMilliseconds = this.endTime - this.startTime;
				var diffTimeSeconds = diffTimeMilliseconds/1000;
				var bits = (this.datasize*8);   // convert Bytes to bits,
				var kbits = bits/1024;     // convert bits to kbits
				this.throughput = kbits/(diffTimeSeconds);
				this.throughput = Math.round(this.throughput * .93);  // account for IP packet header overhead - averages about 7%
			}
		}
		return this.throughput;
    }
});
// </Class definitions>


// <Functions>
function browser_ie()
{
	return (navigator.userAgent.indexOf("MSIE") != -1)
}

function browser_windows_nt4() {
	return (navigator.userAgent.indexOf("Windows NT 4.") != -1);
}

function browser_axcomp()
{
	return ((navigator.userAgent.indexOf("Opera")==-1)&&(navigator.userAgent.indexOf("FireFox")==-1)&&(navigator.userAgent.indexOf("Netscape")!=-1));
}

function browser_ns4()
{
	return ((navigator.appName == "Netscape")
		&& (parseFloat(navigator.appVersion) >= 4)
		&& (navigator.userAgent.indexOf("Netscape6") == -1)) ? true : false;
}

function browser_ns6()
{
	return (document.getElementById && !document.all) ? true : false;
}

function browser_ns71()
{
	return (document.queryCommandSupported ? true : false);
}

function browser_ns() { return browser_ns4() || browser_ns6(); }

function browser_old()
{
	return (!document.layers
		&& !document.getElementById && !document.all) ? true : false;
}

function browser_mac() { return (navigator.appVersion.indexOf("Macintosh") != -1); }

function browser_webtv() { return (navigator.userAgent.indexOf("WebTV") != -1); }

function browser_aol() { return (navigator.userAgent.indexOf("AOL") != -1); }

function browser_getVersion(inUserAgent)
{
	if (!inUserAgent) inUserAgent = navigator.userAgent;

	if (inUserAgent.indexOf("MSIE ") != -1)
		return parseFloat(inUserAgent.substring(inUserAgent.indexOf("MSIE ") + 5));
	if (inUserAgent.indexOf("Netscape6/") != -1)
		return parseFloat(inUserAgent.substring(inUserAgent.indexOf("Netscape6/") + 10));
	if (inUserAgent.indexOf("Mozilla/") != -1)
		return parseFloat(inUserAgent.substring(inUserAgent.indexOf("Mozilla/") + 8));

	return 0;
}


/*
This library handles video player detection for Plugins and ActiveX controls.

For activeX detection the axdetect.vbs script should also be included in the page.
*/
function detection_all()
{
	var player = {
		real: detection_realPlayerVersion(),
		windowsmedia: detection_windowsMediaVersion(),
		quicktime: detection_quickTimeVersion(),
		shockwave: detection_shockwaveVersion(),
		flash: detection_flashVersion()
	};
	return player;
}

function detection_realPlayerVersion()
{
	return parseFloat(RealPlayer_detection());
}

function detection_windowsMediaVersion()
{
	return parseFloat(((browser_ie() && !browser_mac())||browser_axcomp()) ? WMPlayer_detection() : detection_windowsMediaNsVersion());
}

function detection_quickTimeVersion()
{
	return parseFloat((browser_ie() && !browser_mac()) ? detection_quickTimeAxVersion() : detection_quickTimeNsVersion());
}

function detection_shockwaveVersion()
{
	return parseFloat((browser_ie() && !browser_mac()) ? detection_shockwaveAxVersion() : detection_shockwaveNsVersion());
}

function detection_flashVersion()
{
	return parseFloat((browser_ie() && !browser_mac()) ? detection_flashAxVersion() : detection_flashNsVersion());
}

//***************************
// Netscape detection,
// returns the version of wm plugin found or 0.0

function detection_windowsMediaNsVersion() {
	// this function returns a floating point value which should be the version of the Windows
	// Media plugin or 0.0
	// this function only returns useful information if called from Netscape or IE Mac 5.0+

	// Set these local variables to avoid the Netscape 4 crashing bug.
	var thearray = navigator.plugins
	var arraylen = thearray.length

	// Step through each plugin in the array.
	for (var i=0; i < arraylen; i++) {
		// Set these local variables to avoid the Netscape 4 crashing bug.
		var theplugin = thearray[i]
		var thename	 = theplugin.name
		var thedesc	 = theplugin.description
		//txt = txt + theplugin.name +' : '+ theplugin.description + ' <br>';
		
		if (thename.indexOf("Windows Media") != -1 &&
			(thename.indexOf("Player") != -1 || thename.indexOf("Plugin") != -1)) {
			return 1.0;
		}
	}
	return 0.0;
}

//***************************
// Netscape detection,
// returns the version of qt plugin found or 0.0

function detection_quickTimeNsVersion() {
	// this function returns a floating point value which should be the version of the Shockwave plugin or 0.0
	// this function only returns useful information if called from Netscape or IE Mac 5.0+

	// Set these local variables to avoid the Netscape 4 crashing bug.
	var thearray = navigator.plugins
	var arraylen = thearray.length

	// Step through each plugin in the array.
	for (var i=0; i < arraylen; i++) {
		// Set these local variables to avoid the Netscape 4 crashing bug.
		var theplugin = thearray[i]
		var thename	 = theplugin.name
		var thedesc	 = theplugin.description
		// QuickTime Plug-in 4.1.2

		// If the plugin is Shockwave...
		if (thename.indexOf("QuickTime") != -1) {
			var versionString = thename.substring(thename.indexOf("Plug-in ") + 8);
			if (versionString.indexOf(".") > 0) {
				var versionMajor = versionString.substring(0,versionString.indexOf("."));
				var versionMinor = versionString.substring(versionString.indexOf(".") + 1);
				if (versionMinor.indexOf(".") > 0) versionMinor = versionMinor.substring(0,versionString.indexOf(".")) + versionMinor.substring(versionMinor.indexOf(".") + 1)
				return parseFloat(versionMajor + "." + versionMinor);
			}
			//else return parseFloat(versionString);
		}
	}
	return 0.0;
}

//*********************************
function detection_shockwaveNsVersion()
{
  // this function returns a floating point value which should 
  // be the version of the Shockwave plugin or 0.0 this function 
  // only returns useful information if called from Netscape or 
  // IE Mac 5.0+

  // Set these local variables to avoid the Netscape 4 crashing bug.
  var thearray = navigator.plugins
  var arraylen = thearray.length

  // Step through each plugin in the array.
  for (var i=0; i < arraylen; i++)
  {
    // Set these local variables to avoid the Netscape 4 crashing bug.
    var theplugin = thearray[i]
    var thename   = theplugin.name
    var thedesc   = theplugin.description
    
    // If the plugin is Shockwave...
    if (thename.indexOf("Shockwave") != -1 && thename.indexOf("Director") != -1)
    {
      var versionString = thedesc.substring(thedesc.indexOf("version ") + 8);
      
      if (versionString.indexOf(".") > 0)
      {
        var versionMajor = versionString.substring(0,versionString.indexOf("."));
        var versionMinor = versionString.substring(versionString.indexOf(".") + 1);
        
        if (versionMinor.indexOf(".") > 0)
        {
        	versionMinor = versionMinor.substring(0,versionString.indexOf(".")) 
        		+ versionMinor.substring(versionMinor.indexOf(".") + 1)
        }
        
        return parseFloat(versionMajor + "." + versionMinor);
      }
      
      else return parseFloat(versionString);
    }
  }
  
  return 0.0;
}

//***************************
// Netscape detection,
// returns the version of flash plugin found or 0.0

function detection_flashNsVersion()
{
  // this function returns a floating point value which should be the version of the Shockwave plugin or 0.0
  // this function only returns useful information if called from Netscape or IE Mac 5.0+

  // Set these local variables to avoid the Netscape 4 crashing bug.
  var thearray = navigator.plugins
  var arraylen = thearray.length

  // Step through each plugin in the array.
  for (var i=0; i < arraylen; i++) {
    // Set these local variables to avoid the Netscape 4 crashing bug.
    theplugin = thearray[i]
    thename   = theplugin.name
    thedesc   = theplugin.description

    // If the plugin is Flash...
    if (thename.indexOf("Shockwave") != -1 && thename.indexOf("Flash") != -1)
    {
		var versionString = thedesc.substring(thedesc.indexOf("Flash ") + 6);
		
		// Look for an " r".  Whatever's after the "r" is the minor version. For
		// example, "Flash 4.0 r12" is minor release 12 of Flash 4.
		var versionLoc = versionString.indexOf(" r");
		
		if (versionLoc != -1)
		{
			// If there is an "r", then everything before the " r" is the major version...
			var versionMajor = versionString.substring(0,versionLoc);
			
			// ...and everything after is the minor version.
			var versionMinor = parseInt(versionString.substring(versionLoc + 2));
			
			// pad with zeroes
			if (versionMinor < 10) versionMajor += "0";
			
			// Format the final version string as x.xyy where x.x is the major version
			// and yy is the minor release version.
			
			return parseFloat(versionMajor + versionMinor);
		}
		else return parseFloat(versionString);
    }
  }
  
  return 0.0;
}

//***************************
// For detecting the ActiveX of players for ie win.
// Requires a vbscript function be included on the page
// to do the actual checking returns version found or 0.0

function detection_quickTimeAxVersion() {
	// this function returns a floating point value which should be the version of the Shockwave control or 0.0
	// this function should only be called from Internet Explorer for Windows
	// loop backwards through the versions until we get a bite
	for (var i=3;i>0;i--) {
		var versionNum = VBGetQuicktimeVersion(i);
		if (versionNum != 0) {
			return 1.0;
		}
	}
	return 0.0;
}

function detection_shockwaveAxVersion()
{
	// This function returns a floating point value which should be the version 
	// of the Shockwave control or 0.0 this function should only be called from
	// Internet Explorer for Windows loop backwards through the versions until
	// we get a bite
	for (var i=8;i>0;i--) {
		var versionString = VBGetShockwaveVersion(i);
		// if we get 1.0 we assume it is actually 6.0 or less
		if (versionString != "0.0") return (versionString == "1.0" ? 6.0 : parseFloat(versionString));
	}
	return 0.0;
}

function detection_flashAxVersion()
{
	// This function returns a floating point value which should 
	// be the version of the Shockwave control or 0.0.
	// This function should only be called from Internet Explorer
	// for Windows.

    // loop backwards through the versions until we get a bite
	for (var i=8;i>0;i--)
	{
		var versionNum = VBGetFlashVersion(i);
		if (versionNum != 0)
		{
			var versionMajor = Math.floor(versionNum / 65536);
			var versionMinor = versionNum % 65536;
			var versionMiddle = ".";
			for (var i=100;i>5;i/=10) if (versionMinor < i) versionMiddle += "0";
			return parseFloat(versionMajor + versionMiddle + versionMinor);
		}
	}
	return 0.0;
}


/* Real Player detection on a Web page.
* Version 1.0
* March 09, 2004
* Paul Davis <pdavis@real.com>, Real Networks Inc.
* This example illustrates how to detect an installed copy of Real Player to ensure proper playback of Real Media files embedded in a web page.
* If the user has IE5+, the code will attempt to instantiate the Real Player active X control and query it. If the user doesn't have IE5+, the code will 1st attempt to look for Real Player in the plug-ins array and then the mime-Type array.
* The code won't detect the presence Real Player if Netscape Browser 6+ is installed after installing Real Player. This is a known issue in Netscape browser.
* The code will return a "true" value if Real Player version G2 or above is installed, but it may not be able to detect the correct Real Player version number in all cases.
* The recommended next step, when the detection fails to find Real Player, is to redirect the user to a landing page, and allow the user to choose to either download Real Player or to play the embedded contents anyway. In the example, http://guide.real.com is used as the landing page.
* The URL to download the latest release of RealPlayer is http://www.real.com/player.
* Finally, the Real Player detection logic should be intended to enhance web user experience, and not to be used as a mean to restrict access to contents.
*/

/*
* The version variable will be set when we are able
* to detect the version. Note, we do not do comprehensive
* version detection, because of the time overhead in
* instantiating a plugin. This invloves creating an instance of
* the plugin (on non Windows IE5+ platforms), setting up a
* background thread to check when it is ready and querying
* the plugin for its version.
*/

var version = 0;

function isObject(type){
return ( "undefined" != typeof(type) );
}


function winIE5upPlyrDetect(){
var player;
var iectl;

// attempt to instantiate the IE control to see if activeX is enabled.
iectl = new ActiveXObject("Shell.Explorer");


player = new ActiveXObject("rmocx.RealPlayer G2 Control.1");
version = (player.GetVersionInfo());

if(!isObject(iectl)){
return "unknown"; //ActiveX disabled
}
return new String(isObject(player));

}

function checkPlugin(name){
plugin = navigator.plugins[name];
if(isObject(plugin)){
version = plugin.description;
return true;
}
return false;
}

function pluginDetect(){
return (
(checkPlugin("RealPlayer Version Plugin"))
||
(checkPlugin("RealOne Player Version Plugin"))
);
}

function mimeTypeDetect(){
return (
isObject(navigator.mimeTypes)
&&
isObject(navigator.mimeTypes["audio/x-pn-realaudio-plugin"])
);
}

function isWinIE5plus(){
var result = false;
var uaLower = navigator.userAgent.toLowerCase();
if(uaLower.indexOf("windows") >=0 && uaLower.indexOf("msie")>=0){
var versRX = /msie\s+[5-9]/;
result = versRX.test(uaLower);
}
return result;
}

/*
* Returns a string, "true", "false", "unknown" based on the results
* of player detection.
* "false" will only be returned if the user has IE5+, activeX is
* enabled, and we can not instantiate the player control.
* That is the only case where we are sure the user does not have
* the player installed. All other cases where the player can not
* be detected will return "unknown".
*/
function hasRealPlayer(){
if( isWinIE5plus() ){
return winIE5upPlyrDetect();
}else{
return ((pluginDetect() || mimeTypeDetect()
)?"true":"unknown");
}
}

function RealPlayer_detection(){
switch( hasRealPlayer()+"" ){
case "true":
/* Successful player detection
*/
/*document.write("Real Player successfully detected.");*/
if( version != 0 ){ return version;
}
else{ return 1; }
break;
case "unknown":
/* Unable to determine if the user has a player
* If using for media ensure resulting page offers link to the media. */
/*document.location.href = "http://guide.real.com";*/
return 0;
break;
case "false":
/* Player is definitely not installed
*/
/*document.location.href = "http://guide.real.com";*/
return -1;
break;
}
}


//Detect ActiveX Architecture on Both IE and on Gecko
//Defer to plugin architecture for other browsers

function detectWMP()
{
	var wmpInfo = {
		installed: false,
		scriptable: false,
		type: null,
		versionInfo: null
	};
	var wmp64 = "MediaPlayer.MediaPlayer.1";
	var wmp7 = "WMPlayer.OCX.7";

	if((window.ActiveXObject && navigator.userAgent.indexOf('Windows') != -1) || window.GeckoActiveXObject)
	{
		wmpInfo.type = "ActiveX";
		var player = createActiveXObject(wmp7);
		if(player)
		{
			wmpInfo.installed = true;
			wmpInfo.scriptable = true;
			wmpInfo.versionInfo = player.versionInfo;
			return wmpInfo;
		}
		else
		{
			player = createActiveXObject(wmp64);
			if(player)
			{
				wmpInfo.installed = true;
				wmpInfo.scriptable = true;
				wmpInfo.versionInfo = "6.4";
				return wmpInfo;
			}
			else
			{
				wmpInfo.versionInfo = "none";
				return wmpInfo;
			}
		}
	}
	else if(navigator.mimeTypes)
	{
		wmpInfo.type = "NetscapePlugin";
		var player = navigator.mimeTypes["application/x-mplayer2"].enabledPlugin;
		if(player)
		{	
			
			wmpInfo.installed = true;
			//wmpInfo.scriptable = false;
			wmpInfo.versionInfo = "PluginVersion";
			return wmpInfo;
		}
		return wmpInfo;
	}
	
	
}


function createActiveXObject(id)
{
  var error;
  var control = null;
  try {
    if (window.ActiveXObject)
    {
      control = new ActiveXObject(id);
    }
    else if (window.GeckoActiveXObject)
    {
      control = new GeckoActiveXObject(id);
    }
  }
  catch (error)
  {
    ;
  }

  return control;
}
	

function WMPlayer_detection(){
	var detectionResults = detectWMP();
	if(detectionResults.installed){
		return detectionResults.versionInfo;
	}else{
		return -1;
	}
}


function getBandwidth(detectedSpeed, preferredSpeedListString) {
  if (preferredSpeedListString == "") return "";
  var speedArray = preferredSpeedListString.split(",");  
  var minSpeed = 1000;
  for (var i=0;i<speedArray.length;i++)
  {
    var speed = parseFloat(speedArray[i]);
    if ( minSpeed > speed )
      minSpeed = speed;
    var effSpeed= 1.2 * speed;
    if (detectedSpeed>effSpeed) {
     return speed;
    }
  }
  return minSpeed;
}

function getIDeviceSetup(detectedSpeed, preferredSpeedListString, language, validFormats){
	 var bw = getBandwidth(detectedSpeed,preferredSpeedListString);
	 var preferredSpeedListArray = preferredSpeedListString.split(",");
	 if ( validFormats != undefined ) {
	 	//only mp4
	 	var type = "q";
	 	for (var i=0; i<preferredSpeedListString.length;i++){
		    if (preferredSpeedListArray[i] <= bw) {
		    	var format = findValidFormat(type, preferredSpeedListArray[i], language, validFormats.split(","));
				if(format != null){
					return format;
				}
		    	
		    }
		}
		if (validFormats.indexOf(type+"_"+preferredSpeedListArray[0]+"_"+language) > -1){
			var format = findValidFormat(type, preferredSpeedListArray[0], language, validFormats.split(","));
			if(format != null){
				return format;
			}
        }
	 }
	 throw new Error("device not supported");
}

function findValidFormat(format, bandwidth, language, validFormats){
	var fmtString = format + "_" + bandwidth + "_" + language;
	for (var i = 0; i < validFormats.length; i++){
		var fmt = validFormats[i];
		if(fmt.indexOf(fmtString) == 0){
			return fmt;
		}
	}
	return null;
}

function getBestSetup(detectedSpeed, preferredPlayerListString, preferredSpeedListString, language, validFormats, isIDevice) {
  if (preferredPlayerListString == "") return "";
  if(isIDevice){
  	return getIDeviceSetup(detectedSpeed, preferredSpeedListString, language, validFormats);
  }
  if (window.navigator.platform == "iPhone" || window.navigator.platform == "iPod" || window.navigator.platform == "iPad"){
  	return getIDeviceSetup(detectedSpeed, preferredSpeedListString, language, validFormats);
  }
  //detect safari with developer user agent
  if((window.navigator.userAgent.match(/iPhone/i)) || (window.navigator.userAgent.match(/iPod/i)) || (window.navigator.userAgent.match(/iPad/i))){
  	return getIDeviceSetup(detectedSpeed, preferredSpeedListString, language, validFormats);
  }
	var os = system.os;
	
  if ( preferredPlayerListString.indexOf("s") > -1 ) {
    preferredPlayerListString = "s," + preferredPlayerListString;
  }
  if ( preferredPlayerListString.indexOf("r") > -1 ) {
    preferredPlayerListString = "r," + preferredPlayerListString;
  }
  if ( preferredPlayerListString.indexOf("q") > -1 ) {
    preferredPlayerListString = "q," + preferredPlayerListString;
  }
  if ( preferredPlayerListString.indexOf("m") > -1 ) {
    preferredPlayerListString = "m," + preferredPlayerListString;
  }
  if ( preferredPlayerListString.indexOf("f") > -1 ) {
    preferredPlayerListString = "f," + preferredPlayerListString;
  }
  var bw = getBandwidth(detectedSpeed,preferredSpeedListString);
  var playerArray = preferredPlayerListString.split(",");
  var preferredSpeedListArray = preferredSpeedListString.split(",");
  if ( validFormats != undefined ) {
	  if (playerArray.length == 1) {
	    var type = playerArray[0];
	    if (type == "s" || type == "f" || type == "r" || type == "m" || type == "q"){
			for (var i=0; i<preferredSpeedListString.length;i++){
				if (preferredSpeedListArray[i] <= bw) {
					var format = findValidFormat(type, preferredSpeedListArray[i], language, validFormats.split(","));
					if(format != null){
						return format;
					}        
			    }
			}
	    }
	  }
	  for (var i=0;i<playerArray.length;i++)
	  {
	    var type = playerArray[i];
	    if ( (type == "s" && (detection_shockwaveVersion()>0)) || 
		    	(type == "f" && (detection_flashVersion()>0)) || 
		    	(type == "r" && (detection_realPlayerVersion()>0)) || 
		    	(type == "m" && (detection_windowsMediaVersion()>0)) || 
		    	(type == "q" && (detection_quickTimeVersion()>0))){
			for (var i=0; i<preferredSpeedListString.length;i++){
			    if (preferredSpeedListArray[i] <= bw) {
			    	var format = findValidFormat(type, preferredSpeedListArray[i], language, validFormats.split(","));
			    	if(format != null){
						return format;
					}        
			    }
			}
	    }
	  }
  } else {
  	
	  if (playerArray.length == 1) {
	    var type = playerArray[0];
	    if (type == "s" || type == "f" || type == "r" || type == "m" || type == "q"){ 
	    	return (type+"_"+bw+"_"+language); 
	    }
	  }
	  for (var i=0;i<playerArray.length;i++)
	  {
	    var type = playerArray[i];
	    if ( (type == "s" && (detection_shockwaveVersion()>0)) || 
		    	(type == "f" && (detection_flashVersion()>0)) || 
		    	(type == "r" && (detection_realPlayerVersion()>0)) || 
		    	(type == "m" && (detection_windowsMediaVersion()>0)) || 
		    	(type == "q" && (detection_quickTimeVersion()>0))){
	    	return (type+"_"+bw+"_"+language); 
	    }
	  }
  }
  throw new Error("device not supported");
}


function buildSetupUrl(setup, rawUrl) {
	var pos = rawUrl.indexOf(identifierVideoInfo);
	if ( pos < 0 ) {
		var pos2 = rawUrl.indexOf(urlBasePath);
		if ( pos2 > -1 ) {
			pos = pos2 + urlBasePath.length;
			rawUrl = rawUrl.substring(0, pos) + identifierVideoInfo + "/" + rawUrl.substring(pos);
		}
		else {
			return rawUrl;
		}
	} 
	var scndPos = rawUrl.indexOf("/", pos + 1);
	if (scndPos < 0) {
		return rawUrl;
	} 
	var tmpUrl = rawUrl.substring(0,pos);
	tmpUrl += identifierVideoInfo + setup;
	tmpUrl += rawUrl.substring(scndPos);
	return tmpUrl;
}


function removeSetupInfoFromUrl(url) {
	var pos = url.indexOf(identifierVideoInfo);
	if ( pos < 0 ) {
		return url;
	}
	var posTo = url.indexOf("/", pos);
	if ( posTo < 0 ) {
		return url;
	}
	var tmpUrl = url.substring(0, pos+3);
	var rest = url.substring(posTo);
	return tmpUrl + rest;	
}


function saveSettings(form) {
	var setup_btn = form.setup;
	var setup;
	if ( setup_btn ) {
		if ( !setup_btn.length ) {
			if ( setup_btn.checked ) {
				setup = setup_btn.value;
			}
		}
		else {
			for (var i=0; i<setup_btn.length; i++) {
				if ( setup_btn[i].checked ) {
					setup = setup_btn[i].value;
					break;
				}
			}
		}
	}
	if ( setup ) {
		if ( system.currentVideolistId < 0) {
			system.currentTab=undefined;
		}
		system.reloadPlayer(buildSetupUrl(setup, form.action));
	}
}


function clearSettings(form, url) {
	form.target="_self";
	return submitSetupForm(form, "", url);
}



function submitSetupForm(form, setup, url) {
	form.action = buildSetupUrl(setup, url);
	if(url.length > 0)
	//if(confirm(form.action+" target="+form.target))
	form.submit();
	return false;
}

// default-values		
var identifierVideoInfo = '_v_';
var urlBasePath = '/player/macros';

var setup = new Setup(31468);
setup.startBandwidthTest();
// TO COMPLETE THE BANDWIDTHTEST, INCLUDE setup_detect.js DIRECTLY AFTER THIS ONE

