CarouselController = function( dataProvider, holder, left, right )
{
	
	this.dataProvider = dataProvider;
	this.holder = holder;
	this.index = 0;
	this.left = left;
	this.right = right;
	this.timeout = -1;
	var ctrl = this;

	this.init = function()
	{
		var htmlStr = "";
		var n = this.dataProvider.length;
		this.holder.css( { 'width' : 400 * n + 'px' } );
		for( var i = 0; i < n; i++ )
		{
			var item = this.dataProvider[ i ];
			htmlStr += "<div class='carousel-item'>";
			htmlStr += "<div class='carousel-image'>";
			if( item.imageURL )
			{
				htmlStr += "<img src='" + item.imageURL + "'/>";
			}
			htmlStr += "</div>";
			htmlStr += "<div class='carousel-description'>";
			htmlStr += "<span class='blue'><strong>";
			htmlStr += item.title;
			htmlStr += "</strong></span>: ";
			htmlStr += item.description + "&nbsp;";
			//htmlStr += "<br>";
			var o = item.technologies.length;
			for( var j = 0; j < o; j++ )
			{
				var tech = item.technologies[ j ];
				htmlStr += " <span class='tech-tag'>" + tech + "</span>";
			}
			htmlStr += "<br><a href='" + item.url + "'>&rarr;View</a>";
			htmlStr += "</div>"; //closes carousel-description
			htmlStr += "</div>"; //closes carousel-item

		}
		this.holder.html( htmlStr );
		this.timeout = setTimeout( this.next, 8000 + Math.random() * 2000 );

		left.click( function( e )
				{
					e.preventDefault();
					ctrl.prev( 4000 );
				} );

		right.click( function( e )
				{
					e.preventDefault();
					ctrl.next( 4000 );
				} );


	};
	this.goto = function( index )
	{
		//
		ctrl.holder.stop( true, true );
		if( index != this.index )
		{
			this.index = index;
			this.holder.animate( { left:-index * 400 }, 600 );
		}
	};

	this.next = function( extra )
	{
		clearTimeout( ctrl.timeout );
		if( typeof( extra ) == 'undefined' )
		{
			extra = 0;
		}
		ctrl.timeout = setTimeout( ctrl.next, 8000 + Math.round( Math.random() * 400 ) + extra );
		if( ctrl.index >= ctrl.dataProvider.length - 1 )
		{
			ctrl.goto( 0 );
		}
		else
		{
			ctrl.goto( ctrl.index + 1 );
		}
	};

	this.prev = function( extra )
	{
		clearTimeout( ctrl.timeout );
		if( typeof( extra ) == 'undefined' )
		{
			extra = 0;
		}
		ctrl.timeout = setTimeout( ctrl.next, 8000 + Math.round( Math.random() * 400 ) + extra );
		if( ctrl.index <= 0 )
		{
			ctrl.goto( ctrl.dataProvider.length - 1 );
		}
		else
		{
			ctrl.goto( ctrl.index - 1 );
		}
	};

}


bitniblet = 
{
	title : "bitniblet",
	description : "A turn-based social gaming platform with Facebook integration, a real-time notification server, gamer rankings and streamlined invitation flow. Launched with Chess and Werd Nerd.",
	imageURL : "images/projects/bitniblet.jpg",
	url : "http://bitniblet.com",
	technologies : [ "Python", "Haskell", "AS3", "Javascript" ]
};

bundle =
{
	title : "Bundle",
	description : "Data visualization and tools for financial management site bundle.com",
	imageURL : "images/projects/bundle.jpg",
	url : "http://bundle.com",
	technologies : [ "Python", "Javascript", "AS3" ]
};

boomFriends =
{
	title : "BoomFriends",
	description : "iOS color-matching puzzle game with adorable little characters.",
	imageURL : "images/projects/boomfriends.jpg",
	url : "http://games.generalrelativity.org/boomfriends/",
	technologies : [ "C++", "Objective-C" ]
};

balloono =
{
	title : "Balloono",
	description : "Real-time multiplayer bomberman clone with 3D characters, powerups and tie-ins to a virtual store.",
	imageURL : "images/projects/balloono.jpg",
	url : "http://balloono.com",
	technologies : [ "AS3" ]
};


blockles =
{
	title : "Blockles",
	description : "Real-time multiplayer block puzzle game with weapons, defensive items and personalizable game items.",
	imageURL : "images/projects/blockles.jpg",
	url : "http://blockles.com",
	technologies : [ "AS3", "C++" ]
};

ballracer =
{
	title : "BallRacer",
	description : "Real-time multiplayer physics-based racing game.",
	imageURL : "images/projects/ballracer.jpg",
	url : "http://ballracer.com",
	technologies : [ "AS3" ]
};


neuralNetwork =
{
	title : "Neural Networks",
	description : "Some experimentation with various neural networks. Includes an n-layer back propagation network, and Zhang, Amari-Hopfield and Van der Pol oscillators.",
	imageURL : "images/open-source/neural-network.jpg",
	url : "https://github.com/drewcummins/Neural-Network",
	technologies : [ "Python" ]
};

bananaLambda =
{
	title : "Banana Lambda",
	description : "An interpreter for a small grammar of statements and expressions written in Haskell. Just in early prototyping stages.",
	imageURL : "images/open-source/banana-lambda.jpg",
	url : "https://github.com/drewcummins/Banana-Lambda",
	technologies : [ "Haskell" ]
};


noughtsAndCrosses =
{
	title : "Noughts and Crosses",
	description : "A compact, fun little tic-tac-toe finite state machine that manages game and user state.",
	imageURL : "images/open-source/tic-tac-toe.jpg",
	url : "https://github.com/drewcummins/Noughts-And-Crosses",
	technologies : [ "C++" ]
};


dynamics =
{
	title : "Dynamics Harness",
	description : "A generic dynamics harness with modular ordinary differential equation solvers, global state vectors, constraint solvers and exmaple implementations. Includes minimal 2D geometry library.",
	imageURL : "images/open-source/dynamics.jpg",
	url : "https://github.com/drewcummins/Dynamics-Harness",
	technologies : [ "AS3" ]
};

