
GetPlainMapRotation(number)
{
	return GetMapRotation(false, false, number);
}

GetRandomMapRotation()
{
	return GetMapRotation(true, false, undefined);
}

GetCurrentMapRotation(number)
{
	return GetMapRotation(false, true, number);
}

GetPlayerBasedMapRotation()
{
	return GetMapRotation(false, false, undefined);
}

GetRandomPlayerBasedMapRotation()
{
	return GetMapRotation(true, false, undefined);
}

GetMapRotation(random, current, number)
{
	maprot = "";

	if(!isdefined(number))
		number = 0;

	if(current)
		maprot = strip(getcvar("sv_maprotationcurrent"));

	if(maprot == "")
	{
		if(level.ex_pbrotate || (level.ex_mapvotemode > 1))
		{
			small_rot_size = level.ex_pbrsmall;
			med_rot_size = level.ex_pbrmedium;

			players = getentarray("player", "classname");

			if (players.size > med_rot_size) maprot = strip(getcvar("scr_large_rotation"));
			else if (players.size > small_rot_size) maprot = strip(getcvar("scr_med_rotation"));
			else maprot = strip(getcvar("scr_small_rotation"));
		}
		else maprot = strip(getcvar("sv_maprotation"));
	}

	if(maprot == "") return undefined;
	
	j=0;
	temparr2[j] = "";	
	for(i=0;i<maprot.size;i++)
	{
		if(maprot[i]==" ")
		{
			j++;
			temparr2[j] = "";
		}
		else temparr2[j] += maprot[i];
	}

	temparr = [];
	for(i=0;i<temparr2.size;i++)
	{
		element = strip(temparr2[i]);

		if(element != "") temparr[temparr.size] = element;
	}

	x = spawn("script_origin",(0,0,0));
	x.maps = [];
	lastexec = undefined;
	lastjeep = undefined;
	lasttank = undefined;
	lastgt = getcvar("g_gametype");
	for(i=0;i<temparr.size;)
	{
		switch(temparr[i])
		{
			case "allow_jeeps":
				if(isdefined(temparr[i+1]))
					lastjeep = temparr[i+1];
				i += 2;
				break;

			case "allow_tanks":
				if(isdefined(temparr[i+1]))
					lasttank = temparr[i+1];
				i += 2;
				break;
	
			case "exec":
				if(isdefined(temparr[i+1]))
					lastexec = temparr[i+1];
				i += 2;
				break;

			case "gametype":
				if(isdefined(temparr[i+1]))
					lastgt = temparr[i+1];
				i += 2;
				break;

			case "map":
				if(isdefined(temparr[i+1]))
				{
					x.maps[x.maps.size]["exec"]		= lastexec;
					x.maps[x.maps.size-1]["jeep"]	= lastjeep;
					x.maps[x.maps.size-1]["tank"]	= lasttank;
					x.maps[x.maps.size-1]["gametype"]	= lastgt;
					x.maps[x.maps.size-1]["map"]	= temparr[i+1];
				}

				if(!random)
				{
					lastexec = undefined;
					lastjeep = undefined;
					lasttank = undefined;
					lastgt = undefined;
				}

				i += 2;
				break;

			default:
				if(!level.ex_mapvote) iprintln(&"MAPROTATION_ERROR");

				if(isGametype(temparr[i])) lastgt = temparr[i];
				else if(isConfig(temparr[i])) lastexec = temparr[i];
				else
				{
					x.maps[x.maps.size]["exec"] = lastexec;
					x.maps[x.maps.size-1]["jeep"]	= lastjeep;
					x.maps[x.maps.size-1]["tank"]	= lasttank;
					x.maps[x.maps.size-1]["gametype"]	= lastgt;
					x.maps[x.maps.size-1]["map"]	= temparr[i];
	
					if(!random)
					{
						lastexec = undefined;
						lastjeep = undefined;
						lasttank = undefined;
						lastgt = undefined;
					}
				}

				i += 1;
				break;
		}

		if(number && x.maps.size >= number) break;
	}

	if(random)
	{
		for(k = 0; k < 20; k++)
		{
			for(i = 0; i < x.maps.size; i++)
			{
				j = randomInt(x.maps.size);
				element = x.maps[i];
				x.maps[i] = x.maps[j];
				x.maps[j] = element;
			}
		}
	}
	return x;
}

pbrotation()
{
	thread extreme\_ex_logfile::Log("pbrotation");

	if(!level.ex_pbrotate) return;

	rot = Get_Next_Map();

	if(rot == "") return;

	cur_rot = getcvar("sv_maprotationcurrent");

	new_rot = rot + cur_rot;

	setcvar("sv_maprotationcurrent", new_rot);

	return;
}

Get_Next_Map()
{
	thread extreme\_ex_logfile::Log("Get_Next_Map");

	mapstring = undefined;
	execstring = undefined;
	gtstring = undefined;
	jeepstring = undefined;
	tankstring = undefined;

	players = getentarray("player", "classname");
	
	if(players.size >= 1)
	{
		setCvar("ex_playerslg", players.size);
		psize = players.size;
	}
	else psize = getCvarInt("ex_playerslg"); 

	small_rot_size = level.ex_pbrsmall;
	med_rot_size = level.ex_pbrmedium;

	if ( psize > med_rot_size)
	{
		map_rot_cur = "scr_large_rotation_current";
		map_rot = "scr_large_rotation";
	}
	else if ( psize > small_rot_size)
	{
		map_rot_cur = "scr_med_rotation_current";
		map_rot = "scr_med_rotation";
	}
	else
	{
		map_rot_cur = "scr_small_rotation_current";
		map_rot = "scr_small_rotation";
	}
	
	cur_map_rot = getcvar(map_rot_cur);
	if (cur_map_rot == "" || cur_map_rot == " ")
	{
		setcvar(map_rot_cur, getcvar(map_rot) );
		cur_map_rot = getcvar(map_rot);
	}

	//Parce Map Rotation
	maprotation = splitArray(cur_map_rot, " ", "", true);
	for (i=0; i < maprotation.size; i++ )
	{
		if (!isdefined(maprotation[i]) )
			continue;

		if (maprotation[i] == "exec")
		{
			execstring = "exec " + maprotation[i+1] + " ";
			i++;
			continue;
		}
		else if (maprotation[i] == "gametype")
		{
			gtstring = "gametype " + maprotation[i+1] + " ";
			i++;
			continue;
		}
		else if (maprotation[i] == "allow_jeeps")
		{
			jeepstring = "allow_jeeps " + maprotation[i+1] + " ";
			i++;
			continue;
		}
		else if (maprotation[i] == "allow_tanks")
		{
			tankstring = "allow_tanks " + maprotation[i+1] + " ";
			i++;
			continue;
		}
		else if (maprotation[i] == "map")
		{
			mapstring = "map " + maprotation[i+1] + " ";

			newcurrentstring = " ";
			for (a=i+2; a<maprotation.size ; a++)
			{
				newcurrentstring = newcurrentstring + maprotation[a];
				newcurrentstring = newcurrentstring + " ";
			}

			if(newcurrentstring == " " || newcurrentstring == "  ") setcvar(map_rot_cur, getcvar(map_rot) );
			else setcvar(map_rot_cur, newcurrentstring);
			break;
		}

		//Whatever it is, it isn't one of the above so ignore it
		continue;
	}

	// Rebuild Map Rotation Current Return Value
	rebuild = "";
	if(!isdefined(mapstring)) return rebuild;
	if(isdefined(execstring)) rebuild = execstring;
	if(isdefined(gtstring)) rebuild = rebuild + gtstring;
	if(isdefined(jeepstring)) rebuild = rebuild + jeepstring;
	if(isdefined(tankstring)) rebuild = rebuild + tankstring;

	rebuild = rebuild + mapstring;
	return rebuild;
}

splitArray( str, sep, quote, skipEmpty )
{
	thread extreme\_ex_logfile::Log("splitArray");

	if(!isdefined(str) || str == "") return ( [] );

	if(!isdefined(sep) || sep == "") sep = ";";	// Default separator

	if(!isdefined(quote)) quote = "";

	skipEmpty = isdefined( skipEmpty );

	a = _splitRecur( 0, str, sep, quote, skipEmpty );

	return ( a );
}

_splitRecur( iter, str, sep, quote, skipEmpty )
{
	thread extreme\_ex_logfile::Log("_splitRecur");

	s = sep[ iter ];

	_a = [];
	_s = "";
	doQuote = false;
	for(i = 0; i < str.size; i++)
	{
		ch = str[i];
		if(ch == quote)
		{
			doQuote = !doQuote;

			if(iter + 1 < sep.size) _s += ch;
		}
		else
		if(ch == s && !doQuote )
		{
			if( _s != "" || !skipEmpty)
			{
				_l = _a.size;

				if(iter + 1 < sep.size)
				{
					_x = _splitRecur( iter + 1, _s,	sep, quote, skipEmpty );

					if(_x.size > 0 || !skipEmpty)
					{
						_a[ _l ][ "str" ] = _s;
						_a[ _l ][ "fields" ] = _x;
					}
				}
				else _a[ _l ] = _s;
			}

			_s = "";
		}
		else _s += ch;
	}

	if( _s != "")
	{
		_l = _a.size;

		if(iter + 1 < sep.size)
		{
			_x = _splitRecur( iter + 1, _s, sep, quote, skipEmpty);
			if(_x.size > 0 )
			{
				_a[ _l ][ "str" ] = _s;
				_a[ _l ][ "fields" ] = _x;
			}
		}
		else _a[ _l ] = _s;
	}

	return ( _a );
}

findStr( find, str, pos )
{
	thread extreme\_ex_logfile::Log("findStr");

	if ( !isdefined( find ) || ( find == "" ) || !isdefined( str ) || !isdefined( pos ) || ( find.size > str.size ) )
		return ( -1 );

	fsize = find.size;
	ssize = str.size;

	switch ( pos )
	{
		case "start": place = 0 ; break;
		case "end":	place = ssize - fsize; break;
		default:	place = 0 ; break;
	}

	for ( i = place; i < ssize; i++ )
	{
		if ( i + fsize > ssize )
			break;			// Too late to compare

		// Compare now ...
		for ( j = 0; j < fsize; j++ )
			if ( str[ i + j ] != find[ j ] )
				break;		// No match

		if ( j >= fsize )
			return ( i );		// Found it!

		if ( pos == "start" )
			break;			// Didn't find at start
	}

	return ( -1 );
}

fixMapRotation()
{
	thread extreme\_ex_logfile::Log("fixMapRotation");
	maps = undefined;

	x = GetPlainMapRotation();
	if(isdefined(x))
	{
		if(isdefined(x.maps))
			maps = x.maps;
		x delete();
	}

	if(!isdefined(maps) || !maps.size)
		return;

	newmaprotation = "";
	newmaprotationcurrent = "";
	for(i = 0; i < maps.size; i++)
	{
		if(!isdefined(maps[i]["exec"])) exec = "";
		else exec = " exec " + maps[i]["exec"];

		if(!isdefined(maps[i]["jeep"])) jeep = "";
		else jeep = " allow_jeeps " + maps[i]["jeep"];

		if(!isdefined(maps[i]["tank"])) tank = "";
		else tank = " allow_tanks " + maps[i]["tank"];

		if(!isdefined(maps[i]["gametype"])) gametype = "";
		else gametype = " gametype " + maps[i]["gametype"];

		newmaprotation += exec + jeep + tank + gametype + " map " + maps[i]["map"];

		if(i>0) newmaprotationcurrent += exec + jeep + tank + gametype + " map " + maps[i]["map"];
	}

	setCvar("sv_maprotation", strip(newmaprotation));
	setCvar("sv_maprotationcurrent", newmaprotationcurrent);
	setCvar("ex_fix_maprotation", "0");
}
	
randomMapRotation()
{
	thread extreme\_ex_logfile::Log("randomMapRotation");
	level endon("ex_gameover");
	maps = undefined;

	if(!level.ex_randommaprotation || level.ex_mapvote)
		return;

	if( strip(getcvar("sv_maprotationcurrent")) == "" || level.ex_randommaprotation == 1)
	{
		x = GetRandomMapRotation();
		if(isdefined(x))
		{
			if(isdefined(x.maps))
				maps = x.maps;
			x delete();
		}

		if(!isdefined(maps) || !maps.size)
			return;

		lastexec = "";
		lastjeep = "";
		lasttank = "";
		lastgt = "";

		newmaprotation = "";
		for(i = 0; i < maps.size; i++)
		{
			if(!isdefined(maps[i]["exec"]) || lastexec == maps[i]["exec"]) exec = "";
			else
			{
				lastexec = maps[i]["exec"];
				exec = " exec " + maps[i]["exec"];
			}

			if(!isdefined(maps[i]["jeep"]) || lastjeep == maps[i]["jeep"]) jeep = "";
			else
			{
				lastjeep = maps[i]["jeep"];
				jeep = " allow_jeeps " + maps[i]["jeep"];
			}

			if(!isdefined(maps[i]["tank"]) || lasttank == maps[i]["tank"]) tank = "";
			else
			{
				lasttank = maps[i]["tank"];
				tank = " allow_tanks " + maps[i]["tank"];	
			}

			if(!isdefined(maps[i]["gametype"]) || lastgt == maps[i]["gametype"]) gametype = "";
			else
			{
				lastgt = maps[i]["gametype"];
				gametype = " gametype " + maps[i]["gametype"];	
			}

			newmaprotation += exec + jeep + tank + gametype + " map " + maps[i]["map"];
		}

		setCvar("sv_maprotationcurrent", newmaprotation);
		setCvar("ex_random_maprotation", "2");
	}
}

strip(s)
{
	thread extreme\_ex_logfile::Log("strip");
	
	if(s=="") return "";

	s2="";
	s3="";

	i=0;
	while(i<s.size && s[i]==" ")
		i++;

	// String is just blanks?
	if(i==s.size) return "";
	
	for(;i<s.size;i++)
		s2 += s[i];

	i=s2.size-1;
	while(s2[i]==" " && i>0)
		i--;

	for(j=0;j<=i;j++)
		s3 += s2[j];
		
	return s3;
}

isGametype(gt)
{
	switch(gt)
	{
		case "chq":
		case "cnq":
		case "ctf":
		case "ctfb":
		case "dm":
		case "dom":
		case "esd":
		case "ft":
		case "hm":
		case "hq":
		case "htf":
		case "ihtf":
		case "lib":
		case "lms":
		case "lts":
		case "ons":
		case "rbcnq":
		case "rbctf":
		case "sd":
		case "tdm":
		case "tkoth":
		case "vip":
			return true;

		default:
			return false;
	}
}

isConfig(cfg)
{
	temparr = explode(cfg,".");
	if(temparr.size == 2 && temparr[1] == "cfg") return true;
	else return false;
}

explode(s,delimiter)
{
	thread extreme\_ex_logfile::Log("explode");

	j=0;
	temparr[j] = "";	

	for(i=0;i<s.size;i++)
	{
		if(s[i]==delimiter)
		{
			j++;
			temparr[j] = "";
		}
		else temparr[j] += s[i];
	}

	return temparr;
}
