<commit_before>package com.planet_ink.coffee_mud.Libraries;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.CostType;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.ExpertiseDefinition;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.SkillCost;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.CMSecurity.SecFlag;
import com.planet_ink.coffee_mud.core.collections.*;
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.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;
import java.util.Map.Entry;

/*
   Copyright 2006-2019 <NAME>

   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 ColumbiaUniv extends StdLibrary implements ExpertiseLibrary
{
	@Override
	public String ID()
	{
		return "ColumbiaUniv";
	}

	protected SHashtable<String,ExpertiseLibrary.ExpertiseDefinition> completeEduMap=new SHashtable<String,ExpertiseLibrary.ExpertiseDefinition>();
	protected SHashtable<String,List<String>> baseEduSetLists=new SHashtable<String,List<String>>();
	@SuppressWarnings("unchecked")
	protected Map<String,String>[] completeUsageMap=new Hashtable[ExpertiseLibrary.Flag.values().length];
	@SuppressWarnings("unchecked")
	protected Map<String,String[]>[] completeUsageMaps=new Hashtable[ExpertiseLibrary.Flag.values().length];
	protected Properties helpMap=new Properties();
	protected DVector rawDefinitions=new DVector(7);

	@Override
	public ExpertiseLibrary.ExpertiseDefinition addDefinition(final String ID, final String name, final String baseName, final String listMask, final String finalMask, final String[] costs, final String[] data)
	{
		ExpertiseLibrary.ExpertiseDefinition def=getDefinition(ID);
		if(def!=null)
			return  def;
		if(CMSecurity.isExpertiseDisabled(ID.toUpperCase()))
			return null;
		if(CMSecurity.isExpertiseDisabled("*"))
			return null;
		for(int i=1;i<ID.length();i++)
		{
			if(CMSecurity.isExpertiseDisabled(ID.substring(0,i).toUpperCase()+"*"))
				return null;
		}
		def=createNewExpertiseDefinition(ID.toUpperCase(), name, baseName);
		def.addListMask(listMask);
		def.addFinalMask(finalMask);
		def.setData((data==null)?new String[0]:data);
		final int practices=CMath.s_int(costs[0]);
		final int trains=CMath.s_int(costs[1]);
		final int qpCost=CMath.s_int(costs[2]);
		final int expCost=CMath.s_int(costs[3]);
		//int timeCost=CMath.s_int(costs[0]);
		if(practices>0)
			def.addCost(CostType.PRACTICE, Double.valueOf(practices));
		if(trains>0)
			def.addCost(CostType.TRAIN, Double.valueOf(trains));
		if(qpCost>0)
			def.addCost(CostType.QP, Double.valueOf(qpCost));
		if(expCost>0)
			def.addCost(CostType.XP, Double.valueOf(expCost));
		//if(timeCost>0) def.addCost(CostType.PRACTICE, Double.valueOf(practices));
		completeEduMap.put(def.ID(),def);
		baseEduSetLists.clear();
		return def;
	}

	@Override
	public String getExpertiseHelp(String ID, final boolean exact)
	{
		if(ID==null)
			return null;
		ID=ID.toUpperCase();
		if(exact)
			return helpMap.getProperty(ID);
		for(final Enumeration<Object> e = helpMap.keys();e.hasMoreElements();)
		{
			final String key = e.nextElement().toString();
			if(key.startsWith(ID))
				return helpMap.getProperty(key);
		}
		for(final Enumeration<Object> e = helpMap.keys();e.hasMoreElements();)
		{
			final String key = e.nextElement().toString();
			if(CMLib.english().containsString(key, ID))
				return helpMap.getProperty(key);
		}
		return null;
	}

	@Override
	public void delDefinition(final String ID)
	{
		completeEduMap.remove(ID);
		baseEduSetLists.clear();
	}

	@Override
	public Enumeration<ExpertiseDefinition> definitions()
	{
		return completeEduMap.elements();
	}

	@Override
	public ExpertiseDefinition getDefinition(final String ID)
	{
		if(ID!=null)
			return completeEduMap.get(ID.trim().toUpperCase());
		return null;
	}

	@Override
	public ExpertiseDefinition findDefinition(final String ID, final boolean exactOnly)
	{
		ExpertiseDefinition D=getDefinition(ID);
		if(D!=null)
			return D;
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(D.name().equalsIgnoreCase(ID))
				return D;
		}
		if(exactOnly)
			return null;
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(D.ID().startsWith(ID))
				return D;
		}
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(CMLib.english().containsString(D.name(),ID))
				return D;
		}
		return null;
	}

	@Override
	public List<ExpertiseDefinition> myQualifiedExpertises(final MOB mob)
	{
		ExpertiseDefinition D=null;
		final List<ExpertiseDefinition> V=new Vector<ExpertiseDefinition>();
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(((D.compiledFinalMask()==null)||(CMLib.masking().maskCheck(D.compiledFinalMask(),mob,true)))
			&&((D.compiledListMask()==null)||(CMLib.masking().maskCheck(D.compiledListMask(),mob,true))))
				V.add(D);
		}
		final PlayerStats pStats = mob.playerStats();
		if(pStats != null)
		{
			for(final ExpertiseDefinition def : pStats.getExtraQualifiedExpertises().values())
			{
				if(((def.compiledFinalMask()==null)||(CMLib.masking().maskCheck(def.compiledFinalMask(),mob,true)))
				&&((def.compiledListMask()==null)||(CMLib.masking().maskCheck(def.compiledListMask(),mob,true))))
				{
					D = completeEduMap.get(def.ID());
					if(D!=null)
						V.remove(D);
					V.add(def);
				}
			}
		}
		return V;
	}

	@Override
	public List<ExpertiseDefinition> myListableExpertises(final MOB mob)
	{
		ExpertiseDefinition D=null;
		final List<ExpertiseDefinition> V=new Vector<ExpertiseDefinition>();
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if((D.compiledListMask()==null)||(CMLib.masking().maskCheck(D.compiledListMask(),mob,true)))
			{
				V.add(D);
			}
		}
		final PlayerStats pStats = mob.playerStats();
		if(pStats != null)
		{
			for(final ExpertiseDefinition def : pStats.getExtraQualifiedExpertises().values())
			{
				if((def.compiledListMask()==null)||(CMLib.masking().maskCheck(def.compiledListMask(),mob,true)))
				{
					D = completeEduMap.get(def.ID());
					if(D!=null)
						V.remove(D);
					V.add(def);
				}
			}
		}
		return V;
	}

	@Override
	public int getExpertiseLevel(final MOB mob, final String abilityID, final ExpertiseLibrary.Flag code)
	{
		if((mob==null)||(code==null)||(abilityID==null)||(abilityID.length()==0))
			return 0;
		int expertiseLvl=0;
		final int[][] usageCache=mob.getAbilityUsageCache(abilityID);
		if(usageCache[Ability.CACHEINDEX_EXPERTISE]!=null)
			expertiseLvl=usageCache[Ability.CACHEINDEX_EXPERTISE][code.ordinal()];
		else
		{
			final int[] xFlagCache=new int[ExpertiseLibrary.Flag.values().length];
			final CharClass charClass = mob.baseCharStats().getCurrentClass();
			if(charClass == null)
				return 0;
			for(final ExpertiseLibrary.Flag flag : ExpertiseLibrary.Flag.values())
			{
				xFlagCache[flag.ordinal()]=getApplicableExpertiseLevel(abilityID,flag,mob)
											+charClass.addedExpertise(mob, flag, abilityID);
			}
			usageCache[Ability.CACHEINDEX_EXPERTISE]=xFlagCache;
			expertiseLvl = xFlagCache[code.ordinal()];
		}
		return expertiseLvl;
	}

	private int getStageNumber(final ExpertiseDefinition D)
	{
		if(D.ID().startsWith(D.getBaseName()))
		{
			final String remID=D.ID().substring(D.getBaseName().length());
			if(CMath.isInteger(remID))
				return CMath.s_int(remID);
			if(CMath.isRomanNumeral(remID))
				return CMath.convertFromRoman(remID);
		}
		return 0;
	}

	@Override
	public int getHighestListableStageBySkill(final MOB mob, final String ableID, final ExpertiseLibrary.Flag flag)
	{
		final String expertiseID = completeUsageMap[flag.ordinal()].get(ableID);
		if(expertiseID == null)
			return 0;
		ExpertiseDefinition D=null;
		int max=0;
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(expertiseID.equals(D.getBaseName()))
			{
				if((D.compiledListMask()==null)||(CMLib.masking().maskCheck(D.compiledListMask(),mob,true)))
				{
					final int stage=getStageNumber(D);
					if(stage > max)
						max=stage;
				}
			}
		}
		final PlayerStats pStats = mob.playerStats();
		if(pStats != null)
		{
			for(final ExpertiseDefinition def : pStats.getExtraQualifiedExpertises().values())
			{
				if(expertiseID.equals(def.getBaseName()))
				{
					if((def.compiledListMask()==null)||(CMLib.masking().maskCheck(def.compiledListMask(),mob,true)))
					{
						final int stage=getStageNumber(def);
						if(stage > max)
							max=stage;
					}
				}
			}
		}
		return max;
	}

	@Override
	public int numExpertises()
	{
		return completeEduMap.size();
	}

	private String expertMath(String s,final int l)
	{
		int x=s.indexOf('{');
		while(x>=0)
		{
			final int y=s.indexOf('}',x);
			if(y<0)
				break;
			s=s.substring(0,x)+CMath.parseIntExpression(s.substring(x+1,y))+s.substring(y+1);
			x=s.indexOf('{');
		}
		return s;
	}

	@Override
	public List<String> getStageCodes(String baseExpertiseCode)
	{
		String key=null;
		if(baseExpertiseCode==null)
			return new ReadOnlyVector<String>(1);
		baseExpertiseCode=baseExpertiseCode.toUpperCase();
		if(!baseEduSetLists.containsKey(baseExpertiseCode))
		{
			synchronized(("ListedEduBuild:"+baseExpertiseCode).intern())
			{
				if(!baseEduSetLists.containsKey(baseExpertiseCode))
				{
					final List<String> codes=new LinkedList<String>();
					for(final Enumeration<String> e=completeEduMap.keys();e.hasMoreElements();)
					{
						key=e.nextElement();
						if(key.startsWith(baseExpertiseCode)
						&&(CMath.isInteger(key.substring(baseExpertiseCode.length()))||CMath.isRomanNumeral(key.substring(baseExpertiseCode.length()))))
							codes.add(key);
					}
					baseEduSetLists.put(baseExpertiseCode, new ReadOnlyVector<String>(codes));
				}
			}
		}
		return baseEduSetLists.get(baseExpertiseCode);
	}

	@Override
	public int getStages(final String baseExpertiseCode)
	{
		return getStageCodes(baseExpertiseCode).size();
	}

	@Override
	public String getGuessedBaseExpertiseName(final String expertiseCode)
	{
		int lastBadChar=expertiseCode.length()-1;
		while( (lastBadChar>=0)
		&&(CMath.isInteger(expertiseCode.substring(lastBadChar))||CMath.isRomanNumeral(expertiseCode.substring(lastBadChar))))
			lastBadChar--;
		if(lastBadChar<expertiseCode.length()-1)
			return expertiseCode.substring(0,lastBadChar+1);
		return expertiseCode;
	}

	@Override
	public List<String> getPeerStageCodes(final String expertiseCode)
	{
		return getStageCodes(getGuessedBaseExpertiseName(expertiseCode));
	}

	@Override
	public String getApplicableExpertise(final String ID, final Flag code)
	{
		return completeUsageMap[code.ordinal()].get(ID);
	}

	@Override
	public String[] getApplicableExpertises(final String ID, final Flag code)
	{
		if(code == null)
		{
			final Set<String> all=new TreeSet<String>();
			for(final Flag f : Flag.values())
			{
				final String[] set=completeUsageMaps[f.ordinal()].get(ID);
				if(set != null)
					all.addAll(Arrays.asList(set));
			}
			return all.toArray(new String[0]);
		}
		return completeUsageMaps[code.ordinal()].get(ID);
	}

	protected int getConfirmedExpertiseLevel(final MOB mob, final String baseID, final Pair<String,Integer> e)
	{
		final ExpertiseDefinition def=getDefinition(baseID+e.getValue().toString());
		if((!mob.isMonster())
		&&(!CMSecurity.isAllowedEverywhere(mob, SecFlag.ALLSKILLS)))
		{
			if((def == null)
			||(!CMLib.masking().maskCheck(def.compiledListMask(), mob, true))
			||(!CMLib.masking().maskCheck(def.compiledFinalMask(), mob, true)))
			{
				final List<String> defList = getStageCodes(baseID);
				for(int i = defList.size()-e.getValue().intValue();i<defList.size();i++)
				{
					final ExpertiseDefinition def2=getDefinition(defList.get(i));
					if((def2 != null)
					&&(CMLib.masking().maskCheck(def2.compiledListMask(), mob, true))
					&&(CMLib.masking().maskCheck(def2.compiledFinalMask(), mob, true)))
						return this.getStageNumber(def2);
				}
				return 0;
			}
		}
		return e.getValue().intValue();<commit_msg>tiny optim.<commit_after>package com.planet_ink.coffee_mud.Libraries;
import com.planet_ink.coffee_mud.Libraries.interfaces.*;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.CostType;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.ExpertiseDefinition;
import com.planet_ink.coffee_mud.Libraries.interfaces.ExpertiseLibrary.SkillCost;
import com.planet_ink.coffee_mud.core.interfaces.*;
import com.planet_ink.coffee_mud.core.*;
import com.planet_ink.coffee_mud.core.CMSecurity.SecFlag;
import com.planet_ink.coffee_mud.core.collections.*;
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.interfaces.*;
import com.planet_ink.coffee_mud.Locales.interfaces.*;
import com.planet_ink.coffee_mud.MOBS.interfaces.*;
import com.planet_ink.coffee_mud.Races.interfaces.*;

import java.util.*;
import java.util.Map.Entry;

/*
   Copyright 2006-2019 <NAME>

   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 ColumbiaUniv extends StdLibrary implements ExpertiseLibrary
{
	@Override
	public String ID()
	{
		return "ColumbiaUniv";
	}

	protected SHashtable<String,ExpertiseLibrary.ExpertiseDefinition> completeEduMap=new SHashtable<String,ExpertiseLibrary.ExpertiseDefinition>();
	protected SHashtable<String,List<String>> baseEduSetLists=new SHashtable<String,List<String>>();
	@SuppressWarnings("unchecked")
	protected Map<String,String>[] completeUsageMap=new Hashtable[ExpertiseLibrary.Flag.values().length];
	@SuppressWarnings("unchecked")
	protected Map<String,String[]>[] completeUsageMaps=new Hashtable[ExpertiseLibrary.Flag.values().length];
	protected Properties helpMap=new Properties();
	protected DVector rawDefinitions=new DVector(7);

	@Override
	public ExpertiseLibrary.ExpertiseDefinition addDefinition(final String ID, final String name, final String baseName, final String listMask, final String finalMask, final String[] costs, final String[] data)
	{
		ExpertiseLibrary.ExpertiseDefinition def=getDefinition(ID);
		if(def!=null)
			return  def;
		if(CMSecurity.isExpertiseDisabled(ID.toUpperCase()))
			return null;
		if(CMSecurity.isExpertiseDisabled("*"))
			return null;
		for(int i=1;i<ID.length();i++)
		{
			if(CMSecurity.isExpertiseDisabled(ID.substring(0,i).toUpperCase()+"*"))
				return null;
		}
		def=createNewExpertiseDefinition(ID.toUpperCase(), name, baseName);
		def.addListMask(listMask);
		def.addFinalMask(finalMask);
		def.setData((data==null)?new String[0]:data);
		final int practices=CMath.s_int(costs[0]);
		final int trains=CMath.s_int(costs[1]);
		final int qpCost=CMath.s_int(costs[2]);
		final int expCost=CMath.s_int(costs[3]);
		//int timeCost=CMath.s_int(costs[0]);
		if(practices>0)
			def.addCost(CostType.PRACTICE, Double.valueOf(practices));
		if(trains>0)
			def.addCost(CostType.TRAIN, Double.valueOf(trains));
		if(qpCost>0)
			def.addCost(CostType.QP, Double.valueOf(qpCost));
		if(expCost>0)
			def.addCost(CostType.XP, Double.valueOf(expCost));
		//if(timeCost>0) def.addCost(CostType.PRACTICE, Double.valueOf(practices));
		completeEduMap.put(def.ID(),def);
		baseEduSetLists.clear();
		return def;
	}

	@Override
	public String getExpertiseHelp(String ID, final boolean exact)
	{
		if(ID==null)
			return null;
		ID=ID.toUpperCase();
		if(exact)
			return helpMap.getProperty(ID);
		for(final Enumeration<Object> e = helpMap.keys();e.hasMoreElements();)
		{
			final String key = e.nextElement().toString();
			if(key.startsWith(ID))
				return helpMap.getProperty(key);
		}
		for(final Enumeration<Object> e = helpMap.keys();e.hasMoreElements();)
		{
			final String key = e.nextElement().toString();
			if(CMLib.english().containsString(key, ID))
				return helpMap.getProperty(key);
		}
		return null;
	}

	@Override
	public void delDefinition(final String ID)
	{
		completeEduMap.remove(ID);
		baseEduSetLists.clear();
	}

	@Override
	public Enumeration<ExpertiseDefinition> definitions()
	{
		return completeEduMap.elements();
	}

	@Override
	public ExpertiseDefinition getDefinition(final String ID)
	{
		if(ID!=null)
			return completeEduMap.get(ID.trim().toUpperCase());
		return null;
	}

	@Override
	public ExpertiseDefinition findDefinition(final String ID, final boolean exactOnly)
	{
		ExpertiseDefinition D=getDefinition(ID);
		if(D!=null)
			return D;
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(D.name().equalsIgnoreCase(ID))
				return D;
		}
		if(exactOnly)
			return null;
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(D.ID().startsWith(ID))
				return D;
		}
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(CMLib.english().containsString(D.name(),ID))
				return D;
		}
		return null;
	}

	@Override
	public List<ExpertiseDefinition> myQualifiedExpertises(final MOB mob)
	{
		ExpertiseDefinition D=null;
		final List<ExpertiseDefinition> V=new Vector<ExpertiseDefinition>();
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(((D.compiledFinalMask()==null)||(CMLib.masking().maskCheck(D.compiledFinalMask(),mob,true)))
			&&((D.compiledListMask()==null)||(CMLib.masking().maskCheck(D.compiledListMask(),mob,true))))
				V.add(D);
		}
		final PlayerStats pStats = mob.playerStats();
		if(pStats != null)
		{
			for(final ExpertiseDefinition def : pStats.getExtraQualifiedExpertises().values())
			{
				if(((def.compiledFinalMask()==null)||(CMLib.masking().maskCheck(def.compiledFinalMask(),mob,true)))
				&&((def.compiledListMask()==null)||(CMLib.masking().maskCheck(def.compiledListMask(),mob,true))))
				{
					D = completeEduMap.get(def.ID());
					if(D!=null)
						V.remove(D);
					V.add(def);
				}
			}
		}
		return V;
	}

	@Override
	public List<ExpertiseDefinition> myListableExpertises(final MOB mob)
	{
		ExpertiseDefinition D=null;
		final List<ExpertiseDefinition> V=new Vector<ExpertiseDefinition>();
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if((D.compiledListMask()==null)||(CMLib.masking().maskCheck(D.compiledListMask(),mob,true)))
			{
				V.add(D);
			}
		}
		final PlayerStats pStats = mob.playerStats();
		if(pStats != null)
		{
			for(final ExpertiseDefinition def : pStats.getExtraQualifiedExpertises().values())
			{
				if((def.compiledListMask()==null)||(CMLib.masking().maskCheck(def.compiledListMask(),mob,true)))
				{
					D = completeEduMap.get(def.ID());
					if(D!=null)
						V.remove(D);
					V.add(def);
				}
			}
		}
		return V;
	}

	@Override
	public int getExpertiseLevel(final MOB mob, final String abilityID, final ExpertiseLibrary.Flag code)
	{
		if((mob==null)||(code==null)||(abilityID==null)||(abilityID.length()==0))
			return 0;
		int expertiseLvl=0;
		final int[][] usageCache=mob.getAbilityUsageCache(abilityID);
		if(usageCache[Ability.CACHEINDEX_EXPERTISE]!=null)
			expertiseLvl=usageCache[Ability.CACHEINDEX_EXPERTISE][code.ordinal()];
		else
		{
			final int[] xFlagCache=new int[ExpertiseLibrary.Flag.values().length];
			final CharClass charClass = mob.baseCharStats().getCurrentClass();
			if(charClass == null)
				return 0;
			for(final ExpertiseLibrary.Flag flag : ExpertiseLibrary.Flag.values())
			{
				xFlagCache[flag.ordinal()]=getApplicableExpertiseLevel(abilityID,flag,mob)
											+charClass.addedExpertise(mob, flag, abilityID);
			}
			usageCache[Ability.CACHEINDEX_EXPERTISE]=xFlagCache;
			expertiseLvl = xFlagCache[code.ordinal()];
		}
		return expertiseLvl;
	}

	private int getStageNumber(final ExpertiseDefinition D)
	{
		if(D.ID().startsWith(D.getBaseName()))
		{
			final String remID=D.ID().substring(D.getBaseName().length());
			if(CMath.isInteger(remID))
				return CMath.s_int(remID);
			if(CMath.isRomanNumeral(remID))
				return CMath.convertFromRoman(remID);
		}
		return 0;
	}

	@Override
	public int getHighestListableStageBySkill(final MOB mob, final String ableID, final ExpertiseLibrary.Flag flag)
	{
		final String expertiseID = completeUsageMap[flag.ordinal()].get(ableID);
		if(expertiseID == null)
			return 0;
		ExpertiseDefinition D=null;
		int max=0;
		for(final Enumeration<ExpertiseDefinition> e=definitions();e.hasMoreElements();)
		{
			D=e.nextElement();
			if(expertiseID.equals(D.getBaseName()))
			{
				if((D.compiledListMask()==null)||(CMLib.masking().maskCheck(D.compiledListMask(),mob,true)))
				{
					final int stage=getStageNumber(D);
					if(stage > max)
						max=stage;
				}
			}
		}
		final PlayerStats pStats = mob.playerStats();
		if(pStats != null)
		{
			for(final ExpertiseDefinition def : pStats.getExtraQualifiedExpertises().values())
			{
				if(expertiseID.equals(def.getBaseName()))
				{
					if((def.compiledListMask()==null)||(CMLib.masking().maskCheck(def.compiledListMask(),mob,true)))
					{
						final int stage=getStageNumber(def);
						if(stage > max)
							max=stage;
					}
				}
			}
		}
		return max;
	}

	@Override
	public int numExpertises()
	{
		return completeEduMap.size();
	}

	private String expertMath(String s,final int l)
	{
		int x=s.indexOf('{');
		while(x>=0)
		{
			final int y=s.indexOf('}',x);
			if(y<0)
				break;
			s=s.substring(0,x)+CMath.parseIntExpression(s.substring(x+1,y))+s.substring(y+1);
			x=s.indexOf('{');
		}
		return s;
	}

	@Override
	public List<String> getStageCodes(String baseExpertiseCode)
	{
		String key=null;
		if(baseExpertiseCode==null)
			return new ReadOnlyVector<String>(1);
		baseExpertiseCode=baseExpertiseCode.toUpperCase();
		if(!baseEduSetLists.containsKey(baseExpertiseCode))
		{
			synchronized(("ListedEduBuild:"+baseExpertiseCode).intern())
			{
				if(!baseEduSetLists.containsKey(baseExpertiseCode))
				{
					final List<String> codes=new LinkedList<String>();
					for(final Enumeration<String> e=completeEduMap.keys();e.hasMoreElements();)
					{
						key=e.nextElement();
						if(key.startsWith(baseExpertiseCode)
						&&(CMath.isInteger(key.substring(baseExpertiseCode.length()))||CMath.isRomanNumeral(key.substring(baseExpertiseCode.length()))))
							codes.add(key);
					}
					baseEduSetLists.put(baseExpertiseCode, new ReadOnlyVector<String>(codes));
				}
			}
		}
		return baseEduSetLists.get(baseExpertiseCode);
	}

	@Override
	public int getStages(final String baseExpertiseCode)
	{
		return getStageCodes(baseExpertiseCode).size();
	}

	@Override
	public String getGuessedBaseExpertiseName(final String expertiseCode)
	{
		int lastBadChar=expertiseCode.length()-1;
		while( (lastBadChar>=0)
		&&(CMath.isInteger(expertiseCode.substring(lastBadChar))||CMath.isRomanNumeral(expertiseCode.substring(lastBadChar))))
			lastBadChar--;
		if(lastBadChar<expertiseCode.length()-1)
			return expertiseCode.substring(0,lastBadChar+1);
		return expertiseCode;
	}

	@Override
	public List<String> getPeerStageCodes(final String expertiseCode)
	{
		return getStageCodes(getGuessedBaseExpertiseName(expertiseCode));
	}

	@Override
	public String getApplicableExpertise(final String ID, final Flag code)
	{
		return completeUsageMap[code.ordinal()].get(ID);
	}

	@Override
	public String[] getApplicableExpertises(final String ID, final Flag code)
	{
		if(code == null)
		{
			final Set<String> all=new TreeSet<String>();
			for(final Flag f : Flag.values())
			{
				final String[] set=completeUsageMaps[f.ordinal()].get(ID);
				if(set != null)
					all.addAll(Arrays.asList(set));
			}
			return all.toArray(new String[0]);
		}
		return completeUsageMaps[code.ordinal()].get(ID);
	}

	protected int getConfirmedExpertiseLevel(final MOB mob, final String baseID, final Pair<String,Integer> e)
	{
		if((!mob.isMonster())
		&&(!CMSecurity.isAllowedEverywhere(mob, SecFlag.ALLSKILLS)))
		{
			final ExpertiseDefinition def=getDefinition(baseID+e.getValue().toString());
			if((def == null)
			||(!CMLib.masking().maskCheck(def.compiledListMask(), mob, true))
			||(!CMLib.masking().maskCheck(def.compiledFinalMask(), mob, true)))
			{
				final List<String> defList = getStageCodes(baseID);
				for(int i = defList.size()-e.getValue().intValue();i<defList.size();i++)
				{
					final ExpertiseDefinition def2=getDefinition(defList.get(i));
					if((def2 != null)
					&&(CMLib.masking().maskCheck(def2.compiledListMask(), mob, true))
					&&(CMLib.masking().maskCheck(def2.compiledFinalMask(), mob, true)))
						return this.getStageNumber(def2);
				}
				return 0;
			}
		}
		return e.getValue().intValue();
{'fraction_non_alphanumeric': 0.1418532501027922, 'fraction_numerical': 0.003812656524501925, 'mean_word_length': 5.091530054644808, 'pattern_counts': {'":': 0, '<': 81, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4328190', 'n_tokens_mistral': 10613, 'n_tokens_neox': 9277, 'n_words': 1444}