Planets.nu - PLSCheck Plugin

PLSCheck Plugin

目前為 2014-10-08 提交的版本,檢視 最新版本

// ==UserScript==
// @name          Planets.nu - PLSCheck Plugin
// @description   PLSCheck Plugin
// @version       0.9
// @date          2014-10-8
// @author        robodoc
// @include       http://planets.nu/#/*
// @include       http://planets.nu/*
// @include       http://play.planets.nu/*
// @include       http://test.planets.nu/*
// @history       0.9    Beta version

// @namespace https://greasyfork.org/users/5275
// ==/UserScript==


function wrapper () { // wrapper for injection
    
	if (vgap.version < 3.0) {
		console.log("PLSCheck Plugin requires at least NU version 3.0. Plugin disabled." );
		return;	
	}
	// Global variables
	var plugin_version = "0.9 BETA";
	console.log("PLSCheck plugin version: v" + plugin_version );
	var plsType = 70; // Default plsType is PLS-70
	var ruleType = "short"; // Default rule set is "Short"
	
	var plsCheckPlugin = {
			
		processload: function() {
			//console.log("ProcessLoad: plsCheckPlugin plugin called.");

			//console.log("END PROCESS LOAD");
		},	
		
		loaddashboard: function() {
			//console.log("LoadDashboard: plsCheckPlugin plugin called.");
			
			// Add PLSCheck Button
			var menu = document.getElementById("DashboardMenu").childNodes[2]; //insert in middle
			$("<li style=\"color:#FFF000\">PLSCheck »</li>").tclick(function () { vgap.plugins["plsCheckPlugin"].displayPLS(); }).appendTo(menu);
			
		},

		/*
		 * showdashboard: executed when switching from starmap to dashboard
		 */
		showdashboard: function() {
		},
		
		/*
		 * showsummary: executed when returning to the main screen of the dashboard
		 */
		showsummary: function() {
			//console.log("ShowSummary: plsCheckPlugin plugin called.");
			
			//insert Icon for PLSCheck on Home Screen
			var summary_list = document.getElementById("TurnSummary").childNodes[0];
			var planets_entry = summary_list.children[2];
			
			var node = document.createElement("li");
			node.setAttribute("style", "color:#FFF000");
			// alternate icon http://play.planets.nu/img/races/9.png
			node.innerHTML = "<div class=\"iconholder\"><img src=\"http://play.planets.nu/img/icons/blacksquares/ships.png\"/></div>" + 
							"PLSCheck";
			node.onclick = function() {vgap.plugins["plsCheckPlugin"].displayPLS();};
			summary_list.insertBefore(node, planets_entry);
			//summary_list.appendChild(node);
			
		},
		
		/*
		 * loadmap: executed after the first turn has been loaded to create the map
		 * as far as I can tell not executed again when using time machine
		 */
		loadmap: function() {
			//console.log("LoadMap: plsCheckPlugin plugin called.");
		},
		
		/*
		 * showmap: executed when switching from dashboard to starmap
		 */
		showmap: function() {
			//console.log("ShowMap: plsCheckPlugin plugin called.");
		},
		
		/*
		 * draw: executed on any click or drag on the starmap
		 */			
		draw: function() {
			//console.log("Draw: plsCheckPlugin plugin called.");
		},		
		
		/*
		 * loadplanet: executed a planet is selected on dashboard or starmap
		 */
		loadplanet: function() {
			//console.log("LoadPlanet: plsCheckPlugin plugin called.");
			
		},
		
		/*
		 * loadstarbase: executed a starbase is selected on dashboard or starmap
		 */
		loadstarbase: function() {
			//console.log("LoadStarbase: plsCheckPlugin plugin called.");
		},
		
		/*
		 * loadship: executed a ship is selected on dashboard or starmap
		 */
		loadship: function() {
			//console.log("LoadShip: plsCheckPlugin plugin called.");
		},
		
		
		/*
		 * Variables
		 */
	
		
		/* Main Display Function
		 */
		displayPLS: function(view) {

			vgap.playSound("button");
			vgap.closeSecond();
			var plg = vgap.plugins["plsCheckPlugin"];
			vgap.dash.content.empty();

			var html = "";

			if (!view)
				view = 0;
			//console.log("Entered displayPLS, buildmethods is " + plg.buildmethods);
			console.log("Entered displayPLS");
			var filterMenu = $("<ul class='FilterMenu'></ul>").appendTo(vgap.dash.content);
				$("<li " + (view == 0 ? "class='SelectedFilter'" : "") + ">PLSCheck Summary</li>").tclick(function() { vgap.plugins["plsCheckPlugin"].displayPLS(0); }).appendTo(filterMenu);
				//$("<li " + (view == 3 ? "class='SelectedFilter'" : "") + ">Planet need and surplus view</li>").tclick(function() { vgap.plugins["plsCheckPlugin"].displayPLS(3); }).appendTo(filterMenu);
				$("<li " + (view == 2 ? "class='SelectedFilter'" : "") + ">PLSCheck Help</li>").tclick(function() { vgap.plugins["plsCheckPlugin"].displayPLS(2); }).appendTo(filterMenu);
			
			//loop through all planets and show the ones owned by this player
			html = "<div class='DashPane' style='height:" + ($("#DashboardContent").height() - 70) + "px;'>";
							
			if (view == 0) {
				var PMBreak = $("<br /><br />").appendTo(vgap.dash.content);
				
				// Display Summary
				//html += "<br><h1>PLSCheck v" + plugin_version + "</h1>"; 
				html += "<p>The <span style='color:yellow'><b>PLSCheck v" + plugin_version + "</b></span> plug-in checks a player's turn for conformance to PLS rules.</p>";


				// Display Options
				html += "<table><td valign='top' style='width:20%'>";
				html += "<p><span style='font-size:20px;'>PLS Options:</span>"; 
				html += "</td><td valign='top'>";

				// radio buttons
				html += "<p>PLS type: ";
				if (plsType == 70) {
					html += "<input type='radio' name='plsradio' value='pls70' checked>PLS-70;";
				} else {
					html += "<input type='radio' name='plsradio' value='pls70' >PLS-70;";
				}
				if (plsType == 50) {
					html += "<input type='radio' name='plsradio' value='pls50' checked>PLS-50;";
				} else {
					html += "<input type='radio' name='plsradio' value='pls50' >PLS-50;";
				}
				if (plsType == 20) {
					html += "<input type='radio' name='plsradio' value='pls20' checked>PLS+20;";
				} else {
					html += "<input type='radio' name='plsradio' value='pls20'>PLS+20;";
				}
				if (plsType == 0) {
					html += "<input type='radio' name='plsradio' value='nobuild' checked>NoBuild;";
				} else {
					html += "<input type='radio' name='plsradio' value='nobuild'>NoBuild;";
				}

				html += "</p>"

				html += "<p>Rule Set: "
				if (ruleType == "short") {
					html += "<input type='radio' name='ruleradio' value='short' checked>Short (no-allies);"
				} else {
					html += "<input type='radio' name='ruleradio' value='short'>Short (no-allies);"
				}
				if (ruleType == "long") {
					html += "<input type='radio' name='ruleradio' value='long' checked>Long (allies permitted);"
				} else {
					html += "<input type='radio' name='ruleradio' value='long' >Long (allies permitted);"
				}
				html += "</p>"

				html += "</td><td valign='top'>";
				// Display Update Button
				html += "<p><div id='UpdateButton' class='BasicFlatButton' title='Update'>Update and re-check</div></p><p></p><br/><br/>";
				html += "</td></table>";


				// Display PLS Scenario and rule set
				html += "<span style='text-decoration: underline; font-size:20px;'>Showing results for ";
				if (plsType == 70) html += "<span style='color:yellow'><b>PLS-70</b></span>, ";
				if (plsType == 50) html += "<span style='color:yellow'><b>PLS-50</b></span>, ";
				if (plsType == 20) html += "<span style='color:yellow'><b>PLS+20</b></span>, ";
				if (plsType == 0) html += "<span style='color:yellow'><b>NoBuild</b></span>, ";
				if (ruleType == "short") html += "Rule set = <span style='color:yellow'><b>Short</b></span>";
				if (ruleType == "long") html += "Rule set = <span style='color:yellow'><b>Long</b></span>";
				html += ":</span><br><br>"; 
/////
				// Construct Summary Table Header
				var headhtml = "";
				//var headhtml = "<div class='DashPane' style='height:" + ($("#DashboardContent").height() - 70) + "px;'>";

				headhtml += "<table id='PlanetTable' align='left' class='CleanTable' border='0' width='100%' style='cursor:pointer;'><thead>";
				headhtml += "<thead><th align='left'>Player</th><th align='left'>Planets</th>";
				headhtml += "<th title='Warships' align='left'>Warships</th><th title='Freighters' align='left'>Freighters</th><th title='Total Ships' align='left'>Total Ships</th><th title='Ship slots' align='left'>Ship limit</th><th title='Available slots' align='left'>Available slots</th></tr>";

				var rowhtml = "";
				var totalPlanets = 0;
				var totalShips = 0;
				for (var i = 0; i < vgap.scores.length; i++) {
				    	var score = vgap.scores[i];
				    	totalPlanets += score.planets;
				   	totalShips += score.capitalships + score.freighters;
					var playerShips = score.capitalships + score.freighters;
					//console.log(i,vgap.raceName(score.ownerid),score.planets,score.capitalships,score.freighters);
					if (playerShips < plg.findLimit(i)) rowhtml += "<tr>"
					if (playerShips > plg.findLimit(i)) rowhtml += "<tr style='background-color:#680000 ;'>" // dark red
					if (playerShips == plg.findLimit(i)) rowhtml += "<tr style='background-color:#666600 ;'>" // dark yellow
					rowhtml += "<td>" + vgap.raceName(score.ownerid) + "</td>";
				    	rowhtml += "<td>" + score.planets + plg.plsScoreChange(score.planetchange) + "</td>";
				    	rowhtml += "<td>" + score.capitalships + plg.plsScoreChange(score.shipchange) + "</td>";
				    	rowhtml += "<td>" + score.freighters + plg.plsScoreChange(score.freighterchange) + "</td>";
				    	rowhtml += "<td>" + playerShips + plg.plsScoreChange(score.shipchange + score.freighterchange) + "</td>";
				    	rowhtml += "<td>" + plg.findLimit(i)  + "</td>";
				    	rowhtml += "<td>" + (plg.findLimit(i)-playerShips)  + "</td>";
				    	rowhtml += "</tr>";
				}

				// Put the Summary table together
				//html += "<br /><table id='PLSTable' align='left' border='0' width='100%'>";
				html += headhtml;
				html += rowhtml;
				html += "</table>";

				html += "<br //><p><b>Total planets: " + totalPlanets + ".  Total ships: " + totalShips + "</b></p>";

				html += "<hr>";

				// End summary. Now start checking for conformity to the rules.
				// Check the following:
				// 1. Ship building (and cloning)
				// 2. Starbase force surrender
				// 3. Check starbase fix
				// 4. Tow capture
				// 5. gsX

				if (plg.limitStatus() > 0) html += "<p><b>You are under your ship limit, with " + plg.limitStatus() + " ship slots available.</b></p>";
				if (plg.limitStatus() == 0) html += "<p><b>You are at your ship limit.</b></p>";
				if (plg.limitStatus() < 0) html += "<p><b>You are " + -1*plg.limitStatus() + " ships over your ship limit.</b></p>";

				var conformsToRules = true;

				// 1. Check ships builds for conformity
				var buildsAllowed = Math.max(plg.limitStatus(),0);
				if (plg.findBuilds() > buildsAllowed) {
					conformsToRules = false;
					if (plg.limitStatus() > 0) html += "<p>You are building " + plg.findBuilds() + " ships, and you are allowed to build " + plg.limitStatus() + " ships.</p>";
					if (plg.limitStatus() <= 0) html += "<p>You are building " + plg.findBuilds() + " ships, and you are allowed to build 0 ships.</p>";
					html += "<br /><table id='ShipBuildsTable' align='left' border='0' width='100%'>";
					for (var i = 0; i < vgap.mystarbases.length; i++) {
						var sb = vgap.mystarbases[i];
						var planet = vgap.getPlanet(sb.planetid)
						if (sb.isbuilding == true) {
							html += "<tr><td>Building " + vgap.getHull(sb.buildhullid).name + " at planet " + plg.addStarbaseLink(planet.id) + ".</td>";
							//html += "<td>Remove from queue.<button onclick='removeBaseBuild(" + planet.id + ");'>Button 1</button></td></tr>";
							html += "<td class=BLDqueue data-plid='" + planet.id + "' id='BLDqueue_" + planet.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color:#680000; '><b> Remove from queue </b></td><td></td>";
						} else {
							// Looks for possible clones
							// skip if privateer or crystal
							if (vgap.player.raceid == 5 || vgap.player.raceid == 7) continue;
							var plships = vgap.shipsAt(planet.x, planet.y);
							for (var j = 0; j < plships.length; j++) {
								var ship = plships[j];
								if (ship.ownerid != planet.ownerid) continue; // Skip ships that aren't owned
								if (ship.friendlycode.toLowerCase() != "cln") continue; // Skip
 fcode
								//console.log("Can clone?? ",plg.possibleClone(sb,ship));
								if (plg.possibleClone(sb,ship)) {
									html += "<tr><td>Cloning ship " + plg.addShipLink(ship.id) + " at planet " + plg.addStarbaseLink(planet.id) + ".</td>";
									html += "<td class=CLNcode data-plid='" + ship.id + "' id='CLNcode_" + ship.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color:#680000; '><b> Change ship friendly code </b></td><td></td></tr>";
								}
							}
						}
					}
					/*// Looks for possible clones
					//var planet = vgap.getPlanet(sb.planetid)
					//var plships = vgap.shipsAt(planet.x, planet.y);
					for (var j = 0; j < vgap.myships.length; j++) {
						var ship = vgap.myships[j];
						//if (ship.ownerid != planet.ownerid) continue; // Skip ships that aren't owned
						if (ship.friendlycode.toLowerCase() != "cln") continue; // Skip ships without cln fcode
						if (plg.possibleClone(sb,ship)) {
							html += "<tr><td>Friendly code " + ship.friendlycode + " is used on alien hull " +  ship.id + vgap.getHull(ship.hullid).name + ".</td>";
							html += "<td>Remove from queue.</td></tr>";
						}
					}*/

					html += "</table>";
				} 

				// 2. Check force surrender
				if (plg.limitStatus() <= 0 && ruleType == "long" && plg.findForceSurrender()) {
					conformsToRules = false;
					html += "<hr><p>You cannot use the starbase mission 'force a surrender' if you are at or above your ship limit.</p>";
					html += "<br /><table id='ForceSurrenderTable' align='left' border='0' width='100%'>";
					for (var i = 0; i < vgap.mystarbases.length; i++) {
						var sb = vgap.mystarbases[i];
						var planet = vgap.getPlanet(sb.planetid)
						if (sb.mission == 6) {
							html += "<tr><td>The starbase at " + plg.addStarbaseLink(planet.id) + " has mission set to 'force a surrender.'</td>";
							html += "<td class=FCmiss data-plid='" + planet.id + "' id='FCmiss_" + planet.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color:#680000; '><b> Change mission to 'none' </b></td><td></td>";
						}
					}
					html += "</table>";
				}

				// 3. Check starbase fix
				if (plg.limitStatus() < 0 && ruleType == "long" && plg.findSBFix()) {
					conformsToRules = false;
					html += "<hr><p>You cannot use the starbase ship mission 'fix' if you are above your ship limit.</p>";
					html += "<br /><table id='SBFixTable' align='left' border='0' width='100%'>";
					for (var i = 0; i < vgap.mystarbases.length; i++) {
						var sb = vgap.mystarbases[i];
						var planet = vgap.getPlanet(sb.planetid)
						if (sb.shipmission == 1) {
							html += "<tr><td>The starbase at " + plg.addStarbaseLink(planet.id) + " has a ship mission set to 'fix.'</td>";
							html += "<td class=Fixmiss data-plid='" + planet.id + "' id='Fixmiss_" + planet.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color:#680000; '><b> Remove starbase fix orders </b></td><td></td>";
						}
					}
					html += "</table>";
				}

				// 4. Check tow capture
				if (plg.limitStatus() <= 0 && ruleType == "long" && plg.findTowCapture()) {
					conformsToRules = false;
					html += "<hr><p>You cannot tow an alien ship without using the 'NBR' friendly code if you are at or above your ship limit.</p>";
					html += "<br /><table id='TowCaptureTable' align='left' border='0' width='100%'>";
					for (var i = 0; i < vgap.myships.length; i++) {
						var ship = vgap.myships[i];
						if (ship.mission != 6) continue; // skip ships that are not towing
						// skip if you are towing your own ship:
						if (vgap.getShip(ship.mission1target).ownerid == vgap.player.id) continue;
						if (ship.friendlycode.toLowerCase() != "nbr") {
							html += "<tr><td>Ship " + plg.addShipLink(ship.id) + " is towing the alien ship " + ship.mission1target + " without NBR.</td>";
							html += "<td class=Towcode data-plid='" + ship.id + "' id='Towcode_" + ship.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color:#680000; '><b> Change friendly code to NBR </b></td><td></td>";
						}
					}
					html += "</table>";
				}

				// 5. Check gsX

				// NOTE: need to reconcile fcode value with player.id

				if (plg.findIllegalGsx()) {
					conformsToRules = false;
					html += "<hr><p>You cannot use gsX to give a ship to a race that is at or above its ship limit.</p>";
					html += "<br /><table id='GsxTable' align='left' border='0' width='100%'>";
					for (var i = 0; i < vgap.myships.length; i++) {
						var ship = vgap.myships[i];
						var fcode = ship.friendlycode.toLowerCase()
						if (fcode.substring(0,2) != "gs") continue; // skip ships not using gsx
						//var fieldOwnerId = vgap.getPlayerIdVal(ship.friendlycode.toLowerCase().replace("gs", ""));
						var recipientId = plg.getPlayerId(fcode.substring(2,3));
						//console.log(ship.id,fcode,recipientId);
						if (recipientId == 0 || recipientId > vgap.game.slots) continue;
						for (var j = 0; j < vgap.scores.length; j++) {
						    	var score = vgap.scores[j];
							var raceShips = score.capitalships + score.freighters;
							if (score.ownerid == recipientId && raceShips >= plg.findLimit(j)) {
							html += "<tr><td>Ship " + plg.addShipLink(ship.id) + " has friendlycode " + ship.friendlycode + ".</td>";
							html += "<td class=GsXcode data-plid='" + ship.id + "' id='GsXcode_" + ship.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color:#680000; '><b> Change ship friendly code </b></td><td></td>";
							}
						}
					}
					html += "</table>";
				}

				// Notice of rule conformance goes here:
				html += "<p></p><br><table><td class=RuleConform id='RuleConform' align='left' style='background-color:#680000; font-size:20px; '><b> Saving changes... </b></td></table>";
				//html += "<hr><p><span style='font-size:20px; background-color:#680000;'>Saving changes...</span>";

				// Display Update Button again
				html += "<p><div id='UpdateButton2' class='BasicFlatButton' title='Update'>Update and re-check</div></p><p></p><br/><br/>";

				html += "</div>";
				this.pane = $(html).appendTo(vgap.dash.content);

				// Save changes before revealing Notice of rule conformance
				vgap.save(); // Save all our changes at the end

				// Check save and reveal Notice of rule conformance when complete
				var checkInterval = setInterval(function(){
					if (vgap.saveInProgress == 2) {
						// We are still saving, check again in a little bit
						return;
					} else {
						clearInterval(checkInterval);
						if (conformsToRules) {
							$("#RuleConform").replaceWith("<td class=RuleConform id='RuleConform'  align='left' style='background-color: #006400; font-size:20px;'><b>No rule violations detected.</b></td>");
							//html += "<hr><p><span style='background-color:#006400; font-size:20px;'>No rule violations detected.</span></p>";
						} else {
							$("#RuleConform").replaceWith("<td class=RuleConform id='RuleConform'  align='left' style='background-color: #680000; font-size:20px;'><b>Rule violations detected. Please correct your orders.</b></td>");
							//html += "<hr><p><span style='font-size:20px; background-color:#680000;'>Rule violations detected. Please correct your orders.</span>";
						}
					}
				}, 250);

        			$("#UpdateButton").tclick(function () { plg.updateButton(); });
        			$("#UpdateButton2").tclick(function () { plg.updateButton(); });

				// "Remove ship from queue" button function
				$('body').delegate('.BLDqueue','click',function() {
					console.log("BLDqueue CLICKED!!!");
					this.curplanet = ($(this).attr('data-plid'));
					var planet = vgap.getPlanet(this.curplanet);
					var sb = vgap.getStarbase(this.curplanet);
					//console.log("Starbase at ",vgap.getPlanet(sb.planetid).id);
					sb.isbuilding = false;
					planet.changed = 1;
					//vgap.planetScreen.load(planet);
					//vgap.planetScreen.randomFC();
					var identifier = "#BLDqueue_" + planet.id;
					console.log("SELECTOR: " + identifier);
					$(identifier).replaceWith("<td class=BLDqueue data-plid='" + planet.id + "' id='BLDqueue_" + planet.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color: #006400;'><b> Removed </b></td>");
				});

				// "Change friendly code (from CLN) button function
				$('body').delegate('.CLNcode','click',function() {
					console.log("CLNcode CLICKED!!!");
					this.curship = ($(this).attr('data-plid'));
					var ship = vgap.getShip(this.curship);
					//var sb = vgap.getStarbase(this.curplanet);
					//console.log("Ship ",vgap.getShi(sb.planetid).id);
					plg.randomShipFcode(ship); // change ship friendly code
					ship.friendlycode = plg.permuteFcode(ship.friendlycode); 
					ship.changed = 1;
					//vgap.planetScreen.load(planet);
					//vgap.planetScreen.randomFC();
					var identifier = "#CLNcode_" + ship.id;
					console.log("SELECTOR: " + identifier);
					$(identifier).replaceWith("<td class=CLNcode data-plid='" + ship.id + "' id='CLNcode_" + ship.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color: #006400;'><b> Ship friendly code changed to " + ship.friendlycode + "</b></td>");
				});

				// "Remove starbase fix" button function
				$('body').delegate('.Fixmiss','click',function() {
					console.log("Fixmiss CLICKED!!!");
					this.curplanet = ($(this).attr('data-plid'));
					var planet = vgap.getPlanet(this.curplanet);
					var sb = vgap.getStarbase(this.curplanet);
					//console.log("Starbase at ",vgap.getPlanet(sb.planetid).id);
					sb.shipmission = 0; // change starbase ship mission to "none"
					planet.changed = 1;
					//vgap.planetScreen.load(planet);
					//vgap.planetScreen.randomFC();
					var identifier = "#Fixmiss_" + planet.id;
					console.log("SELECTOR: " + identifier);
					$(identifier).replaceWith("<td class=Fixmiss data-plid='" + planet.id + "' id='Fixmiss_" + planet.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color: #006400;'><b> Starbase fix removed </b></td>");
				});

				// "Change mission to none" button function
				$('body').delegate('.FCmiss','click',function() {
					console.log("FCmiss CLICKED!!!");
					this.curplanet = ($(this).attr('data-plid'));
					var planet = vgap.getPlanet(this.curplanet);
					var sb = vgap.getStarbase(this.curplanet);
					//console.log("Starbase at ",vgap.getPlanet(sb.planetid).id);
					sb.mission = 0; // change starbase mission to "none"
					planet.changed = 1;
					//vgap.planetScreen.load(planet);
					//vgap.planetScreen.randomFC();
					var identifier = "#FCmiss_" + planet.id;
					console.log("SELECTOR: " + identifier);
					$(identifier).replaceWith("<td class=FCmiss data-plid='" + planet.id + "' id='FCmiss_" + planet.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color: #006400;'><b> Starbase mission changed to 'none' </b></td>");
				});

				// "Change friendly code to NBR" button function
				$('body').delegate('.Towcode','click',function() {
					console.log("Towcode CLICKED!!!");
					this.curship = ($(this).attr('data-plid'));
					var ship = vgap.getShip(this.curship);
					//var sb = vgap.getStarbase(this.curplanet);
					//console.log("Ship ",vgap.getShi(sb.planetid).id);
					ship.friendlycode = plg.permuteFcode("NBR"); // change ship friendly code to "NBR"
					ship.changed = 1;
					//vgap.planetScreen.load(planet);
					//vgap.planetScreen.randomFC();
					var identifier = "#Towcode_" + ship.id;
					console.log("SELECTOR: " + identifier);
					$(identifier).replaceWith("<td class=Towcode data-plid='" + ship.id + "' id='Towcode_" + ship.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color: #006400;'><b> Ship friendly code changed to " + ship.friendlycode + "</b></td>");
				});

				// "Change friendly code (from GsX) button function
				$('body').delegate('.GsXcode','click',function() {
					console.log("GsXcode CLICKED!!!");
					this.curship = ($(this).attr('data-plid'));
					var ship = vgap.getShip(this.curship);
					//var sb = vgap.getStarbase(this.curplanet);
					//console.log("Ship ",vgap.getShi(sb.planetid).id);
					plg.randomShipFcode(ship); // change ship friendly code
					ship.friendlycode = plg.permuteFcode(ship.friendlycode); 
					ship.changed = 1;
					//vgap.planetScreen.load(planet);
					//vgap.planetScreen.randomFC();
					var identifier = "#GsXcode_" + ship.id;
					console.log("SELECTOR: " + identifier);
					$(identifier).replaceWith("<td class=GsXcode data-plid='" + ship.id + "' id='GsXcode_" + ship.id + "' align='center' style='border: solid white 1px; color: #FFEBCD; background-color: #006400;'><b> Ship friendly code changed to " + ship.friendlycode + "</b></td>");
				});
						
			}
			
			if (view == 2) {
				// Help Screen
				 
				html += "<br /><table border='0' width='100%'>";
				 
				html += "<tr><td>";
				 
				html += "<h1>PLSCheck v" + plugin_version + "</h1><br />";
				html += "<h4><i><b>by Robodoc</b></i></h4><br/>";		 
				html += "<h2 style='color:yellow'>Introduction</h2><p>PLSCheck checks for conformance to a set of voluntary PLS (Planets Limit Ships) rules. The PLS scenario (e.g., PLS+20, PLS-70) determines how the player's planet total affects the player's number of ship slots, and the rule set (e.g., 'Long' or 'Short') specifies the voluntary restrictions if a player is at or above his ship limit.</p><br/>";
				html += "<h2 style='color:yellow'>PLS Scenarios</h2><p>PLS-70:</p><ul><li>If your planet total is less than or equal to 70, then you have 70 ship slots.</li><li>If your planet total is greater than 70, then your number of ship slots equals your planet total.</li></ul></p>";
				html += "<p>PLS-50:</p><ul><li>This is the same as PLS-70, except that the threshold is 50 instead of 70.</li></ul></p>";
				html += "<p>PLS+20:</p><ul><li>Your number of ship slots is equal to your number of planets, plus 20.</li></ul></p>";
				html += "<p>NoBuild:</p><ul><li>Sets the number of ship slots of each player equal to 0 (Used for testing).</li></ul></p>";

				html += "<h2 style='color:yellow'>Rule Sets</h2><p>Short. This rule set is based on rules written by MJS68508 and is designed for maximum simplicity in games where max-allies = 0.</p><ol><li>If your ship total equals or exceeds your number of ship slots, then you cannot build or clone any new ships.</li><li>The total number of ships you build or clone in a turn cannot exceed your available ship slots.</li><li>If another player is at or above his ship limit, you cannot have a matching gsX friendly code on any of your ships.</li></ol></p>";

				html += "<p>Long. This is a slightly more elaborate rule set designed for games where allies are permitted (such as Diplomatic Planets), and for games using the Stellar Cartography addon. This includes all of the 'Short' rule set, plus the following:</p><ol start=4><li>If your ship total equals or exceeds your number of ship slots, then you cannot use the 'force a surrender' mission at any of your starbases.</li><li>If your race is Privateer or Crystal and your ship total equals or exceeds your number of ship slots, then you cannot tow an alien ship without using the 'NBR' friendly code.</li><li>If your ship total <u>exceeds</u> your number of ship slots, then you cannot use starbase 'fix' on any of your ships.</li></ol></p>";

				html += "<h2 style='color:yellow'>Instructions</h2><p>Installation instructions are beyond the scope of this manual. General instructions for running PLSCheck are:</p><ol><li>Click on 'PLSCheck' in the main menu. This will run a conformance check based on the PLS scenario and rule set currently selected. <span style='color:yellow'><i>IMPORTANT: If the PLS scenario and rule set do not match your game, then you need to select the correct options and re-run PLSCheck.</i></span></li><li>If needed, select the PLS scenario and rule set options that match your game, and click the 'Update and Re-check' button.</li><li>Scan the list of rule violations listed below, and make corrections. Click the 'Update and Re-check' button when you are finished making corrections.</li><li>Before you submit your turn, make sure you get the message 'No rule violations detected,' indicating that your turn conforms to the rules.</li><li>If you make additional changes to your turn, be sure to run PLSCheck again before you submit.</li></ol><p><span style='color:yellow'>You should not submit your turn unless PLSCheck has verified that your turn conforms to the rules.</span></p>";

				html += "<h2 style='color:yellow'>Correcting Violations</h2><p>For your convenience, buttons are provided to help correct rule violations for you:</p><p><span style='color:yellow'>Remove from queue.</span> This will remove the build orders for the ship. <span style='color:yellow'><i>This will only remove the build orders, and will not sell any ship components that you have bought.</i></span></li><p><span style='color:yellow'>Change mission to 'none'.</span> This will change the starbase mission to 'none'.<p><span style='color:yellow'>Remove starbase fix orders.</span> This will remove the orders to fix a ship at the starbase.<p><span style='color:yellow'>Change friendly code to NBR.</span> This will change the ship's friendly code to a random permutation of 'NBR'.<p><span style='color:yellow'>Change friendly code.</span> This will change the ship's friendly code to a random code beginning with an 'x'.";


				html += "</td></tr>"	
						
				html += "</table><br /></div>";
						
				this.pane = $(html).appendTo(vgap.dash.content);							
				
			}
			
		
		//this.content.fadeIn();
		//$("#PlanetTable").tablesorter();
		this.pane.jScrollPane();

		// vgap.action added for the assistant (Alex):
		vgap.CurrentView = "showPlanets";
		vgap.showPlanetsViewed = 1;

		
				
		},
		

// ***********************************************************************************************

	randomShipFcode: function (ship) {
		// Reset ship friendly code
		var abc = "abcdefghijklmnopqrstuvwxyz";
		var r1 = Math.floor(Math.random()*26);	
		var r2 = Math.floor(Math.random()*26);
		ship.friendlycode = "x" + abc[r1] + abc[r2];
	},

	getPlayerId: function (val) {
		if (val.charCodeAt(0) >= 97 && val.charCodeAt(0) <= 122) {
			return val.charCodeAt(0) - 96 + 9;
		} else if (val.charCodeAt(0) >= 49 && val.charCodeAt(0) <= 57){
			return val.charCodeAt(0) - 48;
		} else {
			return 0;
		}
	},

	findIllegalGsx: function () {
		var plg = vgap.plugins["plsCheckPlugin"];
		// Finds out if any ships illegally use the Gsx friendly code 
		console.log("Entered function findIllegalGsx");

		for (var i = 0; i < vgap.myships.length; i++) {
			var ship = vgap.myships[i];
			var fcode = ship.friendlycode.toLowerCase()
			//console.log(ship.id,fcode.substring(0,2));
			if (fcode.substring(0,2) != "gs") continue; // skip ships that do not have gsx fcode
			//var fieldOwnerId = vgap.getPlayerIdVal(ship.friendlycode.toLowerCase().replace("gs", ""));
			//var fieldOwnerId = vgap.getPlayerIdVal(fcode.substring(2,3));
			//var pcode = fcode.substring(2,3);
			var recipientId = plg.getPlayerId(fcode.substring(2,3));
			if (recipientId == 0 || recipientId > vgap.game.slots || recipientId == vgap.player.id) continue;
			//console.log(fcode.substring(2,3));
			for (var j = 0; j < vgap.scores.length; j++) {
			    	var score = vgap.scores[j];
				var raceShips = score.capitalships + score.freighters;
				//console.log(score.ownerid,recipientId,raceShips,plg.findLimit(j));
				if (score.ownerid == recipientId && raceShips >= plg.findLimit(j)) {
					console.log("Found Illegal Gsx");
					return true;
				}
			}
		}
		return false;
	},

	permuteFcode: function (fcode) {
		// Create a random permuation of a friendly code
		fcode = fcode.toLowerCase();
		var r1 = Math.random(); var r2 = Math.random(); var r3 = Math.random(); 
		var a1 = fcode.charAt(0).toLowerCase();
		var a2 = fcode.charAt(1).toLowerCase();
		var a3 = fcode.charAt(2).toLowerCase();
		if (r1 < 0.5) a1 = fcode.charAt(0).toUpperCase();
		if (r2 < 0.5) a2 = fcode.charAt(1).toUpperCase();
		if (r3 < 0.5) a3 = fcode.charAt(2).toUpperCase();
		fcode = a1 + a2 + a3;
		return fcode;
	},

	findTowCapture: function () {
		// Finds out if any ship might tow capture 
		console.log("Entered function findTowCapture");
		// Only applies to Privateers and Crystals
		if (vgap.player.raceid != 5 && vgap.player.raceid != 7) return false;

		for (var i = 0; i < vgap.myships.length; i++) {
			var ship = vgap.myships[i];
			if (ship.mission != 6) continue; // skip ships that are not towing

			if (ship.mission1target == null || ship.mission1target == 0) continue; // skip if no tow target
			// skip if you are towing your own ship:
			if (vgap.getShip(ship.mission1target).ownerid == vgap.player.id) continue;
			// return true if you are towing an alien ship without "nbr" fcode
			if (ship.friendlycode.toLowerCase() != "nbr") return true;
		}
		return false;
	},

	findSBFix: function () {
		// Finds out if any starbases have the "fix" mission
		console.log("Entered function findSBFix");
		for (var i = 0; i < vgap.mystarbases.length; i++) {
			var sb = vgap.mystarbases[i];
			if (sb.shipmission == 1) return true;
		}
		return false;
	},

	findForceSurrender: function () {
		// Finds out if any starbases have the "force surrender" mission
		console.log("Entered function findForceSurrender");
		for (var i = 0; i < vgap.mystarbases.length; i++) {
			var sb = vgap.mystarbases[i];
			if (sb.mission == 6) return true;
		}
		return false;
	},

	removeBaseBuild: function (id) {

            var planet = vgap.getPlanet(id);

	},    

	addShipLink: function (id) {
		// Adds link to ship
		var ship = vgap.getShip(id);
		if (ship != null) {
		jumpfunc = ( vgap.player.id == ship.ownerid ? "vgap.map.selectShip(" + id + ");" : "vgap.map.shipSurvey(" + id + ");" );
		mouseover = "";
		return "<a style='color:cyan;' onclick='vgap.showMap();vgap.map.centerMap(" + ship.x + ", " + ship.y + ");" + jumpfunc + "return false;'" + mouseover + " ><span style='cursor:pointer'>" + ship.id + " " + ship.name + "</span></a>"; 
		}
	},    

	addStarbaseLink: function (id) {
		// Adds link to starbase
		var planet = vgap.getPlanet(id);
		if (planet != null) {
		jumpfunc = ( vgap.player.id == planet.ownerid ? "vgap.map.selectStarbase(" + id + ");" : "vgap.map.planetSurvey(" + id + ");" );
		mouseover = "";
		return "<a style='color:cyan;' onclick='vgap.showMap();vgap.map.centerMap(" + planet.x + ", " + planet.y + ");" + jumpfunc + "return false;'" + mouseover + " ><span style='cursor:pointer'>" + planet.id + " " + planet.name + "</span></a>"; 
		}
	},    

	findBuilds: function (){
		// Finds out how many ship builds are scheduled (regular build and clone)
		console.log("Entered function findBuilds");

		var plg = vgap.plugins["plsCheckPlugin"];
		var shipBuilds = 0;
		// Find regular builds and clones
		for (var i = 0; i < vgap.mystarbases.length; i++) {
			var sb = vgap.mystarbases[i];
			if (sb.isbuilding == true) {
				shipBuilds += 1;
			} else {
				// Looks for possible clones
				// skip if privateer or crystal
				if (vgap.player.raceid == 5 || vgap.player.raceid == 7) continue;
				var planet = vgap.getPlanet(sb.planetid)
				var plships = vgap.shipsAt(planet.x, planet.y);
				for (var j = 0; j < plships.length; j++) {
					var ship = plships[j];
					if (ship.ownerid != planet.ownerid) continue; // Skip ships that aren't owned
					if (ship.friendlycode.toLowerCase() != "cln") continue; // Skip ships without cln fcode
					if (plg.possibleClone(sb,ship)) shipBuilds += 1;
				}
			}
		}
		/*// Looks for possible clones
		var planet = vgap.getPlanet(sb.planetid)
		//var plships = vgap.shipsAt(planet.x, planet.y);
		for (var j = 0; j < vgap.myships.length; j++) {
			var ship = vgap.myships[j];
			//if (ship.ownerid != planet.ownerid) continue; // Skip ships that aren't owned
			if (ship.friendlycode.toLowerCase() != "cln") continue; // Skip ships without cln fcode
			if (plg.possibleClone(sb,ship)) shipBuilds += 1;
		}*/
		return shipBuilds;
	},

	possibleClone: function(sb,ship) {
		// checks to see if it is possible to clone a ship.
		console.log("Entered function possibleClone");
		var plg = vgap.plugins["plsCheckPlugin"];
		var planet = vgap.getPlanet(sb.planetid)

		var hull = vgap.getHull(ship.hullid);

		// This hull must be of a different race for cloning to be possible
		for (var i = 0; i < vgap.racehulls.length; i++) {
			//console.log("race hull ",vgap.getHull(vgap.racehulls[i]).id);
			if (hull.id == vgap.getHull(vgap.racehulls[i]).id) {
				//console.log("Cannot clone ship",ship.id);
				return false; // cannot clone
			} 
		}
		console.log("Can clone hull of ship",ship.id);
		//return true;

		// Check to see if build is possible		
		var engine = vgap.getEngine(ship.engineid);
		var n_engines = hull.engines;
		var n_tubes = ship.torps;
		var n_beams = ship.beams;
		if (n_beams > 0) var beam = vgap.getBeam(ship.beamid);
		if (n_tubes > 0) var tube = vgap.getTorpedo(ship.torpedoid);

		// Calculate total cost to clone ship
		buildcost = hull.cost + n_engines * engine.cost;
		buildduranium = hull.duranium + n_engines * engine.duranium;
		buildtritanium = hull.tritanium + n_engines * engine.tritanium;
		buildmolybdenum = hull.molybdenum + n_engines * engine.molybdenum;
		if (hull.techlevel > sb.hulltechlevel) return false;
		if (engine.techlevel > sb.enginetechlevel) return false;
		if (n_beams > 0) {
			if (beam.techlevel > sb.beamtechlevel) return false;
			buildcost = buildcost  + n_beams * beam.cost; 
			buildduranium = buildduranium + n_beams * beam.duranium;
			buildtritanium = buildtritanium + n_beams * beam.tritanium;
			buildmolybdenum = buildmolybdenum + n_beams * beam.molybdenum;
		}
		if (n_tubes > 0) {
			if (tube.techlevel > sb.torptechlevel) return false;
			buildcost = buildcost + n_tubes * tube.launchercost; 
			buildduranium = buildduranium + n_tubes * tube.duranium;
			buildtritanium = buildtritanium + n_tubes * tube.tritanium;
			buildmolybdenum = buildmolybdenum + n_tubes * tube.molybdenum;
		}
		buildcost = buildcost * 2;
		//console.log("Can clone?",planet.megacredits >= buildcost,planet.duranium >= buildduranium,planet.tritanium >= buildtritanium,planet.molybdenum >= buildmolybdenum);
		// Check to see if we can build this ship
		var canbuild = (planet.megacredits >= buildcost && planet.duranium >= buildduranium && planet.tritanium >= buildtritanium && planet.molybdenum >= buildmolybdenum);
		if (!canbuild) return false; // cannot clone

		return true;
	},

	limitStatus: function (){
		// Finds out the player's status regarding the individual ship limit
		// returns negative value is you are over your limit, and positive if you are under
		console.log("Entered function limitStatus");

		var plg = vgap.plugins["plsCheckPlugin"];
		var playerLimit;
		// Find the individual ship limit
		if (plsType == 70) {
			playerLimit = 70;
			if (vgap.myplanets.length > 70) playerLimit = vgap.myplanets.length;
		} 
		if (plsType == 50) {
			playerLimit = 50;
			if (vgap.myplanets.length > 50) playerLimit = vgap.myplanets.length;
		} 
		if (plsType == 20) playerLimit = vgap.myplanets.length + 20;
		if (plsType == 0) playerLimit = 0;

		return playerLimit - vgap.myships.length;
	},

	findLimit: function(id) { 
		// find ship limit for a player
            	var score = vgap.scores[id];
		var shipLimit;
		if (plsType == 70) {
			shipLimit = 70;
			if (score.planets > 70) shipLimit = score.planets;
		} 
		if (plsType == 50) {
			shipLimit = 50;
			if (score.planets > 50) shipLimit = score.planets;
		} 
		if (plsType == 20) shipLimit = score.planets + 20;
		if (plsType == 0) shipLimit = 0;
		return shipLimit;
	}, 

	updateButton: function (){
		// Runs when the update button is clicked
		console.log("Entered function updateButton");
		var plg = vgap.plugins["plsCheckPlugin"];
		var plsVal = plg.valButton( document.getElementsByName('plsradio'))
		if (plsVal == "pls70") plsType = 70;
		if (plsVal == "pls50") plsType = 50;
		if (plsVal == "pls20") plsType = 20;
		if (plsVal == "nobuild") plsType = 0;
		var ruleVal = plg.valButton( document.getElementsByName('ruleradio'))
		if (ruleVal == "short") ruleType = "short";
		if (ruleVal == "long") ruleType = "long";
		//console.log("plsType is ",plsType,"ruleType is ",ruleType);
		plg.plsSaveChanges(false); // Save changes
		plg.displayPLS(0); // Re-run PLSCheck
	   	//return null;
	},

	valButton: function(btn) { 
		// Returns value of radio button
		for (var i=btn.length-1; i > -1; i--) { 
		  if (btn[i].checked) return btn[i].value; 
		} 
		return null; 
	}, 

	plsScoreChange: function (change) {
		if (!change || change == 0)
		    return "";

		var txt = " <span class='";
		if (change > 0)
		    txt += "GreatText'>(+";
		else
		    txt += "WarnText'>(";

		return txt + change + ")</span>";
	},


	plsSaveChanges: function(savestarted) {
		var plg = vgap.plugins["plsCheckPlugin"];
		
		/*if (vgap.saveInProgress == 2) {
			// We are still saving, check again in a little bit
			timeoutID = window.setTimeout(plg.plsSaveChanges(true), 500);
			return;*/
		if (savestarted == true) {
			return;
		} else if (savestarted == false) {
			// We can start the save 
			vgap.save();
			timeoutID = window.setTimeout(plg.plsSaveChanges(true), 1000);
		} else {
			// save is completed
			return;
		}
	},

		/*addCss: function(cssString) {
			var head = document.getElementsByTagName('head')[0];
			if (head == null)
				return
				
			//return unless head; var newCss = document.createElement('style');
			var newCss = document.createElement('style');
			newCss.type = "text/css";
			newCss.innerHTML = cssString;
			head.appendChild(newCss);
		}, */
			
			
	};
		
	// register your plugin with NU
	vgap.registerPlugin(plsCheckPlugin, "plsCheckPlugin");

	
} //wrapper for injection

var script = document.createElement("script");
script.type = "application/javascript";
script.textContent = "(" + wrapper + ")();";

document.body.appendChild(script);