/
com/planet_ink/coffee_mud/Abilities/Common/
com/planet_ink/coffee_mud/Abilities/Diseases/
com/planet_ink/coffee_mud/Abilities/Druid/
com/planet_ink/coffee_mud/Abilities/Fighter/
com/planet_ink/coffee_mud/Abilities/Languages/
com/planet_ink/coffee_mud/Abilities/Misc/
com/planet_ink/coffee_mud/Abilities/Prayers/
com/planet_ink/coffee_mud/Abilities/Properties/
com/planet_ink/coffee_mud/Abilities/Skills/
com/planet_ink/coffee_mud/Abilities/Songs/
com/planet_ink/coffee_mud/Abilities/Spells/
com/planet_ink/coffee_mud/Abilities/Thief/
com/planet_ink/coffee_mud/Abilities/Traps/
com/planet_ink/coffee_mud/Behaviors/
com/planet_ink/coffee_mud/CharClasses/interfaces/
com/planet_ink/coffee_mud/Commands/
com/planet_ink/coffee_mud/Commands/interfaces/
com/planet_ink/coffee_mud/Common/
com/planet_ink/coffee_mud/Common/interfaces/
com/planet_ink/coffee_mud/Exits/interfaces/
com/planet_ink/coffee_mud/Items/Armor/
com/planet_ink/coffee_mud/Items/Basic/
com/planet_ink/coffee_mud/Items/CompTech/
com/planet_ink/coffee_mud/Items/MiscMagic/
com/planet_ink/coffee_mud/Items/Weapons/
com/planet_ink/coffee_mud/Items/interfaces/
com/planet_ink/coffee_mud/Libraries/
com/planet_ink/coffee_mud/Libraries/interfaces/
com/planet_ink/coffee_mud/Locales/
com/planet_ink/coffee_mud/MOBS/
com/planet_ink/coffee_mud/Races/
com/planet_ink/coffee_mud/Races/interfaces/
com/planet_ink/coffee_mud/WebMacros/
com/planet_ink/coffee_mud/WebMacros/interfaces/
com/planet_ink/coffee_mud/core/
com/planet_ink/coffee_mud/core/collections/
com/planet_ink/coffee_mud/core/interfaces/
com/planet_ink/coffee_mud/core/intermud/
com/planet_ink/coffee_mud/core/intermud/i3/
com/planet_ink/coffee_web/server/
com/planet_ink/siplet/applet/
lib/
resources/factions/
resources/fakedb/
resources/progs/autoplayer/
resources/quests/holidays/
web/
web/admin.templates/
web/admin/grinder/
web/admin/images/
web/clan.templates/
web/pub.templates/
web/pub/images/mxp/
web/pub/sounds/
web/pub/textedit/
package com.planet_ink.coffee_mud.Areas;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.collections.*;
import com.planet_ink.coffee_mud.core.exceptions.CMException;
import com.planet_ink.coffee_mud.Abilities.interfaces.*;
import com.planet_ink.coffee_mud.Areas.interfaces.*;
import com.planet_ink.coffee_mud.Behaviors.interfaces.*;
import com.planet_ink.coffee_mud.CharClasses.interfaces.*;
import com.planet_ink.coffee_mud.Commands.interfaces.*;
import com.planet_ink.coffee_mud.Common.interfaces.*;
import com.planet_ink.coffee_mud.Exits.interfaces.*;
import com.planet_ink.coffee_mud.Items.Basic.StdItem;
import com.planet_ink.coffee_mud.Items.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.XMLLibrary.XMLTag;
import com.planet_ink.coffee_mud.Libraries.interfaces.XMLLibrary.XMLTag;
import com.planet_ink.coffee_mud.MOBS.GenShopkeeper;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.lang.ref.WeakReference;
import java.util.*;

/*
   Copyright 2011-2016 Bo Zimmerman

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

	   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
public class StdAutoGenInstance extends StdArea implements AutoGenArea
{
	@Override
	public String ID()
	{
		return "StdAutoGenInstance";
	}

	private long	flags	= Area.FLAG_INSTANCE_PARENT;

	@Override
	public long flags()
	{
		return flags;
	}

	protected CList<AreaInstanceChild>	instanceChildren= new SVector<AreaInstanceChild>();
	protected volatile int				instanceCounter	= 0;
	protected long						childCheckDown	= CMProps.getMillisPerMudHour() / CMProps.getTickMillis();
	protected WeakReference<Area>		parentArea		= null;
	protected String					filePath		= "randareas/example.xml";
	protected Map<String, String>		varMap			= new Hashtable<String, String>(1);

	protected String getStrippedRoomID(String roomID)
	{
		final int x=roomID.indexOf('#');
		if(x<0)
			return null;
		return roomID.substring(x);
	}

	protected String convertToMyArea(String roomID)
	{
		final String strippedID=getStrippedRoomID(roomID);
		if(strippedID==null)
			return null;
		return Name()+strippedID;
	}

	protected Area getParentArea()
	{
		if((parentArea!=null)&&(parentArea.get()!=null))
			return parentArea.get();
		final int x=Name().indexOf('_');
		if(x<0)
			return null;
		if(!CMath.isNumber(Name().substring(0,x)))
			return null;
		final Area parentA = CMLib.map().getArea(Name().substring(x+1));
		if((parentA==null)
		||(!CMath.bset(parentA.flags(),Area.FLAG_INSTANCE_PARENT))
		||(CMath.bset(parentA.flags(),Area.FLAG_INSTANCE_CHILD)))
			return null;
		parentArea=new WeakReference<Area>(parentA);
		return parentA;
	}

	@Override 
	public int getPercentRoomsCached()
	{
		return (getParentArea()==null)?0:100;
	}

	@Override 
	public int[] getAreaIStats()
	{
		if(!CMProps.getBoolVar(CMProps.Bool.MUDSTARTED))
			return emptyStats;
		final Area parentArea=getParentArea();
		final String areaName = (parentArea==null)?Name():parentArea.Name();
		int[] statData=(int[])Resources.getResource("STATS_"+areaName.toUpperCase());
		if(statData!=null)
			return statData;
		List<Area> workList = new LinkedList<Area>();
		synchronized(("STATS_"+areaName).intern())
		{
			if(parentArea==null)
			{
				for(final Enumeration<AreaInstanceChild> childE=instanceChildren.elements();childE.hasMoreElements();)
					workList.add(childE.nextElement().A);
			}
			else
			{
				statData=buildAreaIStats();
			}
		}
		if(parentArea == null)
		{
			int ct=0;
			statData=new int[Area.Stats.values().length];
			for(Area childA : workList)
			{
				final int[] theseStats=childA.getAreaIStats();
				if(theseStats != emptyStats)
				{
					ct++;
					for(int i=0;i<theseStats.length;i++)
						statData[i]+=theseStats[i];
				}
			}
			if(ct==0)
				return emptyStats;
			for(int i=0;i<statData.length;i++)
				statData[i]=statData[i]/ct;
			Resources.removeResource("HELP_"+areaName.toUpperCase());
			Resources.submitResource("STATS_"+areaName.toUpperCase(),statData);
		}
		return statData;
	}

	@Override
	public boolean tick(Tickable ticking, int tickID)
	{
		if(!super.tick(ticking, tickID))
			return false;
		if(CMath.bset(flags(),Area.FLAG_INSTANCE_CHILD))
			return true;
		if((--childCheckDown)<=0)
		{
			childCheckDown=CMProps.getMillisPerMudHour()/CMProps.getTickMillis();
			LinkedList<AreaInstanceChild> workList = new LinkedList<AreaInstanceChild>();
			final List<AreaInstanceChild> children = this.instanceChildren;
			if(children == null)
				return true;
			synchronized(children)
			{
				for(int i=children.size()-1;i>=0;i--)
				{
					final AreaInstanceChild child = children.get(i);
					final Area childA=child.A;
					if(childA.getAreaState() != Area.State.ACTIVE)
					{
						workList.add(child);
					}
				}
			}
			for(AreaInstanceChild child : workList)
			{
				final Area childA=child.A;
				final List<WeakReference<MOB>> V=child.mobs;
				boolean anyInside=false;
				for(final WeakReference<MOB> wmob : V)
				{
					final MOB M=wmob.get();
					if((M!=null)
					&&CMLib.flags().isInTheGame(M,true)
					&&(M.location()!=null)
					&&(M.location().getArea()==childA))
					{
						anyInside=true;
						break;
					}
				}
				if(!anyInside)
				{
					synchronized(children)
					{
						children.remove(child);
					}
					for(final WeakReference<MOB> wmob : V)
					{
						final MOB M=wmob.get();
						if((M!=null)
						&&(M.location()!=null)
						&&(M.location().getArea()==this))
							M.setLocation(M.getStartRoom());
					}
					final MOB mob=CMClass.sampleMOB();
					for(final Enumeration<Room> e=childA.getProperMap();e.hasMoreElements();)
					{
						final Room R=e.nextElement();
						R.executeMsg(mob,CMClass.getMsg(mob,R,null,CMMsg.MSG_EXPIRE,null));
					}
					CMLib.map().delArea(childA);
					childA.destroy();
				}
			}
		}
		return true;
	}

	@Override
	public void executeMsg(final Environmental myHost, final CMMsg msg)
	{
		super.executeMsg(myHost, msg);
		if(CMath.bset(flags(),Area.FLAG_INSTANCE_CHILD))
		{
			if((msg.sourceMinor()==CMMsg.TYP_SPEAK)
			&&(msg.sourceMessage()!=null)
			&&((msg.sourceMajor()&CMMsg.MASK_MAGIC)==0))
			{
				final String said=CMStrings.getSayFromMessage(msg.sourceMessage());
				if("RESET INSTANCE".equalsIgnoreCase(said))
				{
					Room returnToRoom=null;
					final Room thisRoom=msg.source().location();
					if(thisRoom.getArea()==this)
					{
						for(int d=0;d<Directions.NUM_DIRECTIONS();d++)
						{
							final Room R=thisRoom.getRoomInDir(d);
							if((R!=null)&&(R.getArea()!=null)&&(R.getArea()!=this))
								returnToRoom=R;
						}
					}
					if(returnToRoom==null)
					{
						msg.addTrailerMsg(CMClass.getMsg(msg.source(),null,null,CMMsg.MSG_OK_ACTION,CMMsg.NO_EFFECT,CMMsg.NO_EFFECT, L("You must be at an entrance to reset the area.")));
						return;
					}
					final Area A=this.getParentArea();
					if(A instanceof StdAutoGenInstance)
					{
						final StdAutoGenInstance parentA=(StdAutoGenInstance)A;
						synchronized(parentA.instanceChildren)
						{
							for(int i=parentA.instanceChildren.size()-1;i>=0;i--)
							{
								final List<WeakReference<MOB>> V=parentA.instanceChildren.get(i).mobs;
								if(parentA.instanceChildren.get(i).A==this)
								{
									for(final WeakReference<MOB> wM : V)
									{
										final MOB M=wM.get();
										if((M!=null)
										&&CMLib.flags().isInTheGame(M,true)
										&&(M.location()!=null)
										&&(M.location()!=returnToRoom)
										&&(M.location().getArea()==this))
										{
											returnToRoom.bringMobHere(M, true);
											CMLib.commands().postLook(M, true);
										}
									}
									parentA.instanceChildren.remove(i);
									final MOB mob=CMClass.sampleMOB();
									for(final Enumeration<Room> e=getProperMap();e.hasMoreElements();)
									{
										final Room R=e.nextElement();
										R.executeMsg(mob,CMClass.getMsg(mob,R,null,CMMsg.MSG_EXPIRE,null));
									}
									msg.addTrailerMsg(CMClass.getMsg(msg.source(),CMMsg.MSG_OK_ACTION,L("The instance has been reset.")));
									CMLib.map().delArea(this);
									destroy();
									return;
								}
							}
						}
					}
					msg.addTrailerMsg(CMClass.getMsg(msg.source(),CMMsg.MSG_OK_ACTION,L("The instance failed to reset.")));
				}
			}
			else
			if((msg.sourceMinor()==CMMsg.TYP_QUIT)&&(CMLib.map().isHere(msg.source(), this)))
			{
				final MOB mob = msg.source();
				CMLib.tracking().forceRecall(mob);
			}
		}
	}

	@Override
	public boolean okMessage(final Environmental myHost, final CMMsg msg)
	{
		if(!super.okMessage(myHost, msg))
			return false;
		if(CMath.bset(flags(),Area.FLAG_INSTANCE_CHILD))
			return true;
		setAreaState(Area.State.PASSIVE);
		if((msg.sourceMinor()==CMMsg.TYP_ENTER)
		&&(msg.target() instanceof Room)
		&&(CMath.bset(flags(),Area.FLAG_INSTANCE_PARENT))
		&&(isRoom((Room)msg.target()))
		&&(((msg.source().getStartRoom()==null)||(msg.source().getStartRoom().getArea()!=this))))
		{
			if(msg.source().isMonster())
			{
				final Set<MOB> friends=msg.source().getGroupMembers(new HashSet<MOB>());
				boolean playerInvolved=false;
				for(final MOB M : friends)
					playerInvolved = playerInvolved || (!M.isMonster());
				if(!playerInvolved)
				{
					msg.source().tell(L("You'll need to be accompanied by an adult to enter there."));
					return false;
				}
			}
			synchronized(instanceChildren)
			{
				int myDex=-1;
				for(int i=0;i<instanceChildren.size();i++)
				{
					final List<WeakReference<MOB>> V=instanceChildren.get(i).mobs;
					for (final WeakReference<MOB> weakReference : V)
					{
						if(msg.source() == weakReference.get())
						{
							myDex = i;
							break;
						}
					}
				}
				final Set<MOB> grp = msg.source().getGroupMembers(new HashSet<MOB>());
				for(int i=0;i<instanceChildren.size();i++)
				{
					if(i!=myDex)
					{
						final List<WeakReference<MOB>> V=instanceChildren.get(i).mobs;
						for(int v=V.size()-1;v>=0;v--)
						{
							final WeakReference<MOB> wmob=V.get(v);
							if(wmob==null)
								continue;
							final MOB M=wmob.get();
							if(grp.contains(M))
							{
								if(myDex<0)
								{
									myDex=i;
									break;
								}
								else
								if((CMLib.flags().isInTheGame(M,true))
								&&(M.location().getArea()!=instanceChildren.get(i).A))
								{
									V.remove(M);
									instanceChildren.get(myDex).mobs.add(new WeakReference<MOB>(M));
								}
							}
						}
					}
				}
				Area redirectA = null;
				int direction = CMLib.map().getRoomDir(msg.source().location(), (Room)msg.target());
				if((direction<0)&&(msg.tool() instanceof Exit))
					direction = CMLib.map().getExitDir(msg.source().location(), (Exit)msg.target());
				if(direction < 0)
				{
					msg.source().tell(L("Can't figure out where you're coming from?!"));
					return false;
				}
				if(myDex<0)
				{
					final StdAutoGenInstance newA=(StdAutoGenInstance)this.copyOf();
					newA.properRooms=new STreeMap<String, Room>(new Area.RoomIDComparator());
					newA.properRoomIDSet = null;
					newA.metroRoomIDSet = null;
					newA.blurbFlags=new STreeMap<String,String>();
					newA.setName((++instanceCounter)+"_"+Name());
					newA.flags |= Area.FLAG_INSTANCE_CHILD;
					final Set<MOB> myGroup=msg.source().getGroupMembers(new HashSet<MOB>());
					final StringBuffer xml = Resources.getFileResource(getGeneratorXmlPath(), true);
					if((xml==null)||(xml.length()==0))
					{
						msg.source().tell(L("Unable to load this area.  Please try again later."));
						return false;
					}
					final List<XMLLibrary.XMLTag> xmlRoot = CMLib.xml().parseAllXML(xml);
					final Hashtable<String,Object> definedIDs = new Hashtable<String,Object>();
					CMLib.percolator().buildDefinedIDSet(xmlRoot,definedIDs);
					String idName = "";
					final List<String> idChoices = new Vector<String>();
					for(final String key : getAutoGenVariables().keySet())
						if(key.equalsIgnoreCase("AREA_ID")||key.equalsIgnoreCase("AREA_IDS")||key.equalsIgnoreCase("AREAID")||key.equalsIgnoreCase("AREAIDS"))
							idChoices.addAll(CMParms.parseCommas(getAutoGenVariables().get(key),true));
					if(idChoices.size()==0)
					{
						for(final Object key : definedIDs.keySet())
						{
							final Object val=definedIDs.get(key);
							if((key instanceof String)
							&&(val instanceof XMLTag)
							&&(((XMLTag)val).tag().equalsIgnoreCase("area")))
							{
								final XMLTag piece=(XMLTag)val; 
								final String inserter = piece.getParmValue("INSERT");
								if(inserter!=null)
								{
									final List<String> V=CMParms.parseCommas(inserter,true);
									for(int v=0;v<V.size();v++)
									{
										String s = V.get(v);
										if(s.startsWith("$"))
											s=s.substring(1).trim();
										final XMLTag insertPiece =(XMLTag)definedIDs.get(s.toUpperCase().trim());
										if(insertPiece == null)
											continue;
										if(insertPiece.tag().equalsIgnoreCase("area"))
											if(!idChoices.contains(s.toUpperCase().trim()))
												idChoices.add(s.toUpperCase().trim());
									}
								}
								else
									idChoices.add((String)key);
							}
						}
					}

					if(idChoices.size()>0)
						idName=idChoices.get(CMLib.dice().roll(1, idChoices.size(), -1)).toUpperCase().trim();

					if((!(definedIDs.get(idName) instanceof XMLTag))
					||(!((XMLTag)definedIDs.get(idName)).tag().equalsIgnoreCase("area")))
					{
						msg.source().tell(L("The area id '@x1' has not been defined in the data file.",idName));
						return false;
					}
					final ScriptingEngine scrptEng=(ScriptingEngine)CMClass.getCommon("DefaultScriptingEngine");
					final Object[] scriptObjs = new Object[ScriptingEngine.SPECIAL_NUM_OBJECTS];
					final List<Double> levels=new ArrayList<Double>();
					final Set<MOB> followers=msg.source().getGroupMembers(new HashSet<MOB>());
					if(!followers.contains(msg.source()))
						followers.add(msg.source());
					double totalLevels=0.0;
					for(final MOB M : followers)
					{
						final Double D=Double.valueOf(M.basePhyStats().level());
						levels.add(D);
						totalLevels+=D.doubleValue();
					}
					final Double[] sortedLevels=levels.toArray(new Double[0]);
					final double lowestLevel=sortedLevels[0].doubleValue();
					final double medianLevel=sortedLevels[(int)Math.round(Math.floor(sortedLevels.length/2))].doubleValue();
					final double averageLevel=Math.round(10.0*totalLevels/(sortedLevels.length))/10.0;
					final double highestLevel=sortedLevels[sortedLevels.length-1].doubleValue();
					final double groupSize=Double.valueOf(followers.size()).doubleValue();
					final double values[]={msg.source().basePhyStats().level(),lowestLevel,medianLevel,averageLevel,highestLevel,totalLevels,groupSize};
					for(final String key : getAutoGenVariables().keySet())
						if(!(key.equalsIgnoreCase("AREA_ID")||key.equalsIgnoreCase("AREA_IDS")||key.equalsIgnoreCase("AREAID")||key.equalsIgnoreCase("AREAIDS")))
						{
							final String rawValue = CMath.replaceVariables(getAutoGenVariables().get(key),values);
							final String val=scrptEng.varify(msg.source(), newA, msg.source(), msg.source(), null, null, msg.sourceMessage(), scriptObjs, rawValue);
							definedIDs.put(key.toUpperCase(),val);
						}
					definedIDs.put("AREANAME", Name());
					if(!definedIDs.containsKey("AREASIZE"))
						definedIDs.put("AREASIZE", "50");
					if(!definedIDs.containsKey("LEVEL_RANGE"))
						definedIDs.put("LEVEL_RANGE", (msg.source().basePhyStats().level()-4)+"?"+(msg.source().basePhyStats().level()));
					if(!definedIDs.containsKey("AGGROCHANCE"))
						definedIDs.put("AGGROCHANCE", ""+msg.source().basePhyStats().level());
					try
					{
						XMLTag piece=(XMLTag)definedIDs.get(idName);
						final List<XMLTag> pieces = CMLib.percolator().getAllChoices(piece.tag(), piece, definedIDs);
						if(pieces.size()>0)
							piece=pieces.get(CMLib.dice().roll(1, pieces.size(), -1));
//TODO: fix this
//FIXME: this can maybe pick town.
						if(!definedIDs.containsKey("THEME"))
						{
							final Map<String,String> unfilled = CMLib.percolator().getUnfilledRequirements(definedIDs,piece);
							final List<String> themes = CMParms.parseCommas(unfilled.get("THEME"), true);
							if(themes.size()>0)
								definedIDs.put("THEME", themes.get(CMLib.dice().roll(1, themes.size(), -1)).toUpperCase().trim());
						}
						try
						{
							CMLib.percolator().checkRequirements(piece, definedIDs);
						}
						catch(final CMException cme)
						{
							msg.source().tell(L("Required ids for @x1 were missing: @x2",idName,cme.getMessage()));
							return false;
						}
						for(final MOB M : myGroup)
							M.tell(L("^x------------------------------------------------------\n\rPreparing to enter @x1, please stand by...\n\r------------------------------------------------------^N^.",Name()));
						definedIDs.put("ROOMTAG_NODEGATEEXIT", Directions.getDirectionName(Directions.getOpDirectionCode(direction)));
						definedIDs.put("ROOMTAG_GATEEXITROOM", msg.source().location());
						if(!CMLib.percolator().fillInArea(piece, definedIDs, newA, direction))
						{
							msg.source().tell(L("Failed to enter the new area.  Try again later."));
							return false;
						}
						CMLib.percolator().postProcess(definedIDs);
					}
					catch(final CMException cme)
					{
						Log.errOut("StdAutoGenInstance",cme);
						msg.source().tell(L("Failed to finish entering the new area.  Try again later."));
						return false;
					}
					redirectA=newA;
					CMLib.map().addArea(newA);
					newA.setAreaState(Area.State.ACTIVE); // starts ticking
					final List<WeakReference<MOB>> newMobList = new SVector<WeakReference<MOB>>(5);
					newMobList.add(new WeakReference<MOB>(msg.source()));
					final AreaInstanceChild child = new AreaInstanceChild(redirectA,newMobList);
					instanceChildren.add(child);

					getAreaIStats(); // if this is the first child ever, this will force stat making

					final Room R=redirectA.getRoom(redirectA.Name()+"#0");
					if(R!=null)
					{
						Exit E=R.getExitInDir(Directions.getOpDirectionCode(direction));
						if(E==null)
							E = CMClass.getExit("Open");
						final int opDir=Directions.getOpDirectionCode(direction);
						if(R.getRoomInDir(opDir)!=null)
							msg.source().tell(L("An error has caused the following exit to be one-way."));
						else
						{
							R.setRawExit(opDir, E);
							R.rawDoors()[opDir]=msg.source().location();
						}
					}
				}
				else
					redirectA=instanceChildren.get(myDex).A;
				if(redirectA instanceof StdAutoGenInstance)
				{
					final Room R=redirectA.getRoom(redirectA.Name()+"#0");
					if(R!=null)
					{
						msg.setTarget(R);
					}
				}
			}
		}
		return true;
	}

	private final static String[] MYCODES={"GENERATIONFILEPATH","OTHERVARS"};

	@Override
	public String getStat(String code)
	{
		if(CMParms.indexOfIgnoreCase(STDAREACODES, code)>=0)
			return super.getStat(code);
		else
		switch(getCodeNum(code))
		{
			case 0:
				return this.getGeneratorXmlPath();
			case 1:
				return CMParms.toEqListString(this.getAutoGenVariables());
			default:
				break;
		}
		return "";
	}

	@Override
	public void setStat(String code, String val)
	{
		if(CMParms.indexOfIgnoreCase(STDAREACODES, code)>=0)
			super.setStat(code, val);
		else
		switch(getCodeNum(code))
		{
			case 0:
				setGeneratorXmlPath(val);
				break;
			case 1:
				setAutoGenVariables(val);
				break;
			default:
				break;
		}
	}

	@Override
	protected int getCodeNum(String code)
	{
		for(int i=0;i<MYCODES.length;i++)
		{
			if(code.equalsIgnoreCase(MYCODES[i]))
				return i;
		}
		return -1;
	}

	private static String[] codes=null;

	@Override
	public String[] getStatCodes()
	{
		if(codes!=null)
			return codes;
		final String[] MYCODES=CMProps.getStatCodesList(StdAutoGenInstance.MYCODES,this);
		final String[] superCodes=STDAREACODES;
		codes=new String[superCodes.length+MYCODES.length];
		int i=0;
		for(;i<superCodes.length;i++)
			codes[i]=superCodes[i];
		for(int x=0;x<MYCODES.length;i++,x++)
			codes[i]=MYCODES[x];
		return codes;
	}

	@Override
	public boolean sameAs(Environmental E)
	{
		if(!(E instanceof StdAutoGenInstance))
			return false;
		final String[] codes=getStatCodes();
		for(int i=0;i<codes.length;i++)
		{
			if(!E.getStat(codes[i]).equals(getStat(codes[i])))
				return false;
		}
		return true;
	}

	@Override
	public String getGeneratorXmlPath()
	{
		return filePath;
	}

	@Override
	public Map<String, String> getAutoGenVariables()
	{
		return varMap;
	}

	@Override
	public void setGeneratorXmlPath(String path)
	{
		filePath = path;
	}

	@Override
	public void setAutoGenVariables(Map<String, String> vars)
	{
		varMap = vars;
	}

	@Override
	public void setAutoGenVariables(String vars)
	{
		setAutoGenVariables(CMParms.parseEQParms(vars));
	}
}