Commit 8656d8f7 authored by Tyler Wilson's avatar Tyler Wilson
Browse files

PROG Documentation updates for Strategy class/improved code coverage for...

PROG Documentation updates for Strategy class/improved code coverage for unitTest.  References #2408

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@6618 41f8697f-d340-4b68-9986-7bafba869bb8
parent 9c3c9ea5
Loading
Loading
Loading
Loading
+53 −22
Original line number Diff line number Diff line
@@ -55,12 +55,11 @@ namespace Isis {
  
  
  /** 
   * Constructs Strategy object from the given name, type, and shared resource
   * Constructs a Strategy object from the given name, type, and shared resource
   * globals. Debug and apply discarded are set to false.
   * 
   * @param name A string containing the strategy name.
   * @param type A string containing the strategy type.
   * @param globals A shared pointer to a global Resource of keywords.
   */ 
  Strategy::Strategy(const QString &name, const QString &type) : 
                     m_globals(),
@@ -130,26 +129,41 @@ namespace Isis {
    return (m_type);
  }

  /** Allow derived strategies to reset name (mostly for default
   *  constructors)  */

  /**
   * Allow derived strategies to reset name (mostly for default
   * constructors)
   * @param   A string containing the new name of the strategy.
   */
  void Strategy::setName(const QString &name) {
    m_name = name;
    return;
  }


  /** Allow derived strategies to reset type (mostly for default
   *  constructors)  */
   *  constructors)
   * @param A string containing the new type of the strategy.


   */
  void Strategy::setType(const QString &type) {
    m_type = type;
    return;
  }


  /**
   * Accessor method to get the global defaults
   *
   * @return ResourceList containing the global defaults.
   */
   ResourceList Strategy::getGlobalDefaults() const {
     return (m_globals);
   }


/**
 * 
 * 
 * @history kbecker (5/11/2015)
 * 
@@ -172,10 +186,12 @@ namespace Isis {
     return ( v_globals );
   }


   const PvlObject &Strategy::getDefinition() const {
     return (*m_definition);
   }


/**
 * @brief Returns the keyword definitions found in the Strategy object 
 * 
@@ -210,6 +226,7 @@ namespace Isis {
    }
  }

  
/**
 * @brief Apply algorithm to resource list 
 *  
@@ -243,6 +260,7 @@ namespace Isis {
    return ( apply( resource, getGlobalDefaults()) );
  }

  
  /**
   * @brief Apply strategy algorithms to list of Resources 
   *  
@@ -330,7 +348,7 @@ namespace Isis {
   * Applies the strategy algorithms to the resources in the given list. 
   *  
   * @param resources A list of resources to which the strategy will be applied.
   *  
   * @param globals A list of global resources.
   * @return int The number of resources processed.
   */ 
  int Strategy::applyToResources(ResourceList &resources, const ResourceList &globals) { 
@@ -415,9 +433,10 @@ namespace Isis {
   * Searches the given resource for an asset with the given name and converts 
   * it to a ResourceList, if possible. 
   *  
   * @param resource
   * @param name
   * @return ResourceList 
   * @param resource The resource to be searched
   * @param name The name of the asset being searched for
   * @return ResourceList If the asset can be converted to a ResourceList, it
   * is returned.  Otherwise an empty ResourceList is returned.
   */ 
  ResourceList Strategy::assetResourceList(const SharedResource &resource, 
                                           const QString &name) const {
@@ -432,15 +451,16 @@ namespace Isis {
    return (alist);
  }

  
/**
 * @brief Find keyword replacement value in globals list 
 * 
 * @author 2015-05-07 Kris Becker
 * 
 * @param globals 
 * @param target 
 * @param index 
 * @param defValue 
 * @param globals ResourceList A list of resources to be searched.
 * @param target QString The keyword of the target resource.
 * @param index int The index of the last resource in the list with keyword == target.
 * @param defValue QString The value to return in the event the resource is not found.
 * 
 * @return QString 
 */
@@ -477,6 +497,7 @@ namespace Isis {
    return (parts);
  }

  
  /** 
   * Performs a case insensitive scan of the input string for a substring 
   * matching the target string and replaces the target substring with the 
@@ -505,11 +526,12 @@ namespace Isis {
   * passing it to processArgs() along with using the argument list, resource,
   * and default resource pointers. 
   *  
   * If a keyword does not exist, an empty string is returned. 
   * If a keyword does not exist, the string provided by defValue is returned.
   * The empty string is returned in the event that defValue is not given an argument.
   *  
   * @param keyBase A string containing the base of the keyword name.
   * @param resource A pointer to the resource
   * @param defaults A pointer to the resource 
   * @param globals A list of resources that will be searched.
   * @param defValue The default value to return if the keyBase does not exist
   *  
   * @return QString A modified keyword value with appropriate arguments 
   *                 inserted into the appropriate locations.
@@ -554,9 +576,9 @@ namespace Isis {
   *              resources.
   * @param argKeys A list of string arguments representing the resource values
   *                to be found in the resource's PVL flat map.
   * @param resource A pointer to the resource whose PVL flat map will be 
   *                 searched for the arguments.
   * @param defaults A pointer to the default resource whose PVL flat map will 
   * @param globals  A list of resources that will be searched.
   *
   * @param defValue A pointer to the default resource whose PVL flat map will
   *                 be searched for the arguments if they are not found in the
   *                 main resource PVL flat map.
   *  
@@ -597,6 +619,7 @@ namespace Isis {
    return;
  }

  
/**
 * @brief Create a composite Resource from a pair by merging keywords 
 *  
@@ -692,6 +715,7 @@ namespace Isis {
   *  
   * @param resource A shared pointer to the resource from which the geometry 
   *                 will be imported.
   * @param globals  The resource list to be searched.
   * @return bool Indicates whether the geometry was successfully imported.
   */ 
  bool Strategy::importGeometry(SharedResource &resource, 
@@ -823,8 +847,9 @@ namespace Isis {
    }
  }

  
/**
 * @brief Make a copy of the resource list that is idependently managed 
 * @brief Make a copy of the resource list that is independently managed
 *  
 * This method creates a copy of the resources but provides independent 
 * management of its status from its parent. All Resource data, name, keywords,
@@ -841,7 +866,7 @@ namespace Isis {
 * 
 * @param resources Input list of Resources to copy
 * 
 * @return ResourceList List of copied (data) Resources
 * @return resources of copied (data) Resources
 */
  ResourceList Strategy::copyList(const ResourceList &resources) const {
    ResourceList v_copy;
@@ -851,6 +876,7 @@ namespace Isis {
    return ( v_copy);
  }


/**
 *  @brief Create a clone of a Resource list
 *  
@@ -879,6 +905,7 @@ namespace Isis {
    return ( v_clone );
  }


  /**
   * @brief Identify and apply Strategy to Resources that intersect a geometry
   *  
@@ -1054,6 +1081,7 @@ namespace Isis {
    return ( m_debug );
  }


  /** 
   *  
   * @return bool 
@@ -1063,6 +1091,7 @@ namespace Isis {
  }



  /**
   * @brief Initializes strategy progress monitor if requested by user
   *  
@@ -1103,6 +1132,7 @@ namespace Isis {
      }
    }


    // No check if progress is requested
    if ( doShowProgress() ) {
      if ( !p_text.isEmpty() ) m_progress->SetText(p_text);
@@ -1126,4 +1156,5 @@ namespace Isis {
    return (objList);
  }


}  //namespace Isis
+7 −29
Original line number Diff line number Diff line
@@ -41,11 +41,10 @@ namespace Isis {

  class GisGeometry;
  class Progress;
//  class PvlObject;


  /**
   * @brief Strategy - Supports algorithm development Planning 
   *        Resource.
   * @brief Strategy - Supports algorithm development
   *  
   * This base class provides a framework to develop strategic 
   * planning tools used to process and/or rank ISIS resources. 
@@ -96,30 +95,10 @@ namespace Isis {
   *                          and replaced. Once the count of arguments reached
   *                          above 9, %1 was replaced for %10. Scan for
   *                          replacements in reverse order fixes this issue.
   *  
   *  
   *   @todo Test coverage - Unable to test constructors Strategy(),
   *         Strategy(name,type,globals) as a support class for isisminer.
   *  
   *   NOTE: Some of the following may be taken care of when we finish testing strategies.
   *   @todo Test coverge - Never called methods: resetProcessed(),
   *         assetResourceList(), propagateKeys(), activeList(),
   *         activateList(), deactivateList(), applyToIntersectedGeometry(),
   *         queryCallback()
   *  
   *   @todo Test coverage - empty resource list - apply(), countActive(),
   *         processArgs(), propagateKeys(), activateList(), deactivateList(),
   *         applyToIntersectedGeometry()
   *  
   *   @todo Test coverage - applyDiscarded=t - apply() 
   *  
   *   @todo Test coverage - keyBase+"Keyword" exists in PVL def - (1) keyBase
   *         exists, (2) keyBase DNE -  translateKeywordArgs()
   *  
   *   @todo Test coverage - def file has GisGeometryRef, GisGeometryKey,
   *         GisGeometryArgs, RemoveGisKeywordAfterImport - importGeometry()
   *  
   * @history 2016-03-07  Tyler Wilson - Corrected documentation, and created a
   *                          unit test to test most of this classe's methods.
   */

  class Strategy {
  
    public:
@@ -131,7 +110,7 @@ namespace Isis {
      QString type() const;
      QString description() const;
  
      // Not intended to be reimplemnented but available for direct calls
      // Not intended to be reimplemented but available for direct calls
      int apply(ResourceList &resources);
      int apply(SharedResource &resource);

@@ -187,8 +166,7 @@ namespace Isis {
  
     void propagateKeys(SharedResource &source, SharedResource &target) const;
     SharedResource composite(SharedResource &resourceA, SharedResource &resourceB,
                              const QPair<QString, QString> &keySuffix = qMakePair(QString("A"),QString("B"))) 
                              const;
        const QPair<QString, QString> &keySuffix = qMakePair(QString("A"),QString("B"))) const;
     bool importGeometry(SharedResource &resource, 
                         const ResourceList &globals) const;
  
+345 −78
Original line number Diff line number Diff line
Testing default constructor:   
************************************************ 

*                Constructors                  * 

************************************************ 



Testing default constructor Strategy()   

Creating empty strategy: 
Name:          "Strategy" 
Type:          "Counter" 
Description:   "Strategy::Strategy is running a Counter algorithm." 
Testing constructors: 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

Testing Strategy(const PvlObject &def,const ResourceList &globals) constructor: 


"**PROGRAMMER ERROR** Keyword Name does not exist!." 
"Elven Dictionary" 

"strat4" 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

Testing Strategy(const QString &name,const QString &type) constructor: 

"strat4name" 

"strat4type" 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 





************************************************ 

*              Protected Members               * 

************************************************ 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             setName, setType                 % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Name:          "Derived Strategy Name" 
Type:          "Derived Strategy Type" 
Testing getGlobalDefaults:   
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             getGlobalDefaults                % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Elven Word List 1
Elven Word List 2
************************************************ 
Elven Word List 3




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             getGlobals                       % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


Testing getGlobals:   

Elven Word List 3
Elven Word List 1
Elven Word List 2
************************************************ 
Elven Word List 3




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             assetResourceList                % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



assetResourceList
"Resource 1" 

"Resource 2" 

"Resource 3" 

"Resource 4" 

"Resource 5" 





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             getDefinition                    % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


Testing getDefinition:   

"Elven Dictionary" 

************************************************ 


Testing getDefinitionMap:   


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             getDefinitionMap                 % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



	ApplyToDiscarded = false
	Debug = true
	Name = "Elven Dictionary"
	PropagateKeyword = Middle-Earth
	PropagateKeywords = wolf
	Type = Dictionary
************************************************ 


Testing setApplyToDiscarded(), isApplytToDiscarded(), setDoNotApplyToDiscarded() 


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             isApplyToDiscarded               % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



isApplyToDiscarded =  
false 

Testing setApplyToDiscarded:   
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             setApplyToDiscarded              % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Calling setApplyToDiscarded:   
isApplyToDiscarded =  
true 
false 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%         setDoNotApplyToDiscarded             % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

Testing setDoNotApplyToDiscarded:   


Calling setDoNotApplyToDiscarded:   
isApplyToDiscarded =  
false 

************************************************ 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%               applyToResources               % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


Testing applyToResources(....) 

Calling apply(SharedResource &resource, const ResourceList &globals)
Calling apply(SharedResource &resource, const ResourceList &globals)
Number of resources processed =  2 

************************************************ 
Calling apply(SharedResource &resource, const ResourceList &globals)
Number of resources processed (after discarding resource 0) =  
1 

Call setApplyToDiscarded: 

Calling apply(SharedResource &resource, const ResourceList &globals)
Calling apply(SharedResource &resource, const ResourceList &globals)
Number of resources processed (after discarding resource 0) =  
2 

Calling apply(SharedResource &resource, const ResourceList &globals)
Calling apply(SharedResource &resource, const ResourceList &globals)
Number of resources processed (after activiating resource 0) =  
2 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%           processed/resetProcessed           % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



************************************************ 
@@ -81,88 +210,158 @@ Resetting Processed:

Processed =  1 

************************************************ 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                  countActive                 % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Testing countActive/countDiscard:   

Active Resources in lstA: 2 
Active Resources in ResourseList lst: 3 

Discarded Resources in lstA: 0 
Discarded Resources in ResourceList lst: 0 

************************************************ 
Discarding the first resource in ResourceList lst: 

Testing findReplacement:   
Discarded Resources in ResourceList lst: 1 

Active Resources in ResourceList lst: 2 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             findreplacement                  % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Searching for elvish word for demon (with default args):   
"red balrog" 

Empty apply is called...
Empty apply is called...
Elven Word List 3
Elven Word List 1
Elven Word List 2
Searching for elvish word for demon (with default args):  balrog
Searching for value not in the ResourceList:   
Could not find fluffy bunny
************************************************ 

Testing qualifiers (more elvish words):   
"Could not find fluffy bunny" 

Searching for the 100th demon (which is not in lst:   

"100th demon not in lst" 





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                qualifiers                    % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



"Aaye" 

"Aelin" 

"Adan" 

"Adanedhel" 

"Aduial" 

"Aglarond" 


Aaye
Aelin
Adan
Adanedhel
Aduial
Aglarond

Testing qualifiers with default delimiter (::):   

Aaye
Aelin
Adan
Adanedhel
Aduial
Aglarond
************************************************ 
"Aaye" 

Testing scanAndReplace:   
"Aelin" 

Original sentence:  Balrogs require much fnord love and fnord attention.
Fixed sentence:  Balrogs require much  love and  attention.
************************************************ 
"Adan" 

Testing translateKeywordArgs:   
"Adanedhel" 

blah
************************************************ 
"Aduial" 

"Aglarond" 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%               scanAndReplace                 % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Original sentence:   "Balrogs require much fnord love and fnord attention." 

Fixed sentence:   "Balrogs require much  love and  attention." 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%             translateKeywordArgs             % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



"blah" 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                 processArgs                  % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

Testing processArgs:   

balrog
************************************************ 

Testing propagateKeys:   
"balrog" 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                propagateKeys                 % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Propagating keys from Shared Resource elven2 -> elven3 

elven3 keys before propagation: 

	daisy = eirien
	Identity = "Elven Word List 3"
	pipe-weed = galena
	Sun = Anor


elven3 keys after propagation: 

	daisy = eirien
	Identity = "Elven Word List 3"
	pipe-weed = galena
	Sun = Anor
************************************************ 
	wolf = draug




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%    activeList/deactivateList/activateList    % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


Testing activeList 

Elven Word List 3
Elven Word List 1
Elven Word List 2
Number of active resources =  3 
Elven Word List 3
Number of active resources in DerivedStrategy dstrat4 =  
3 

************************************************ 

Testing deactivateList 

Number of active resources =  0 
Number of active resources in DerivedStrategy dstrat4 =  
0 

************************************************ 

@@ -172,68 +371,126 @@ Number of active resources = 3

************************************************ 

Deactivating Resource 0 in ResourceList lst: 

Number of active resources =  2 





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                  copyList                    % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Testing copyList (globals -> l5) 

Elven Word List 3
Elven Word List 1
Elven Word List 2
Elven Word List 3
Decativating l5 Resources (global resources are active) 

Number of active resources in l5 =  0 

Number of active resources in global =  3 
Number of active resources in global =  4 





%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                  cloneList                   % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 


************************************************ 

Testing cloneList (globals -> l6) 

Elven Word List 3
Elven Word List 1
Elven Word List 2
************************************************ 
Elven Word List 3
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                  isDebug                     % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

Testing applyToIntersectedGeometry 

************************************************ 

Testing isDebug(): 

isDebug() =  true 

************************************************ 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                doShowProgress                % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Testing doShowProgress(): 

doShowProgress() =  false 

************************************************ 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                initProgress                  % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Testing initProgress(): 

Calling with no args, initProgress =   false 
Calling: initProgress() =   false 

Calling: initProgress(2,"some text") =  
false 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                  composite                   % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



Calling:  initProgress(2,"some text") =  false 

************************************************ 

Testing composite(...): 

"Elven Word List 1_Elven Word List 3" 
	Identity = "Elven Word List 2_Elven Word List 3"
	wolfA = draug
	wolfB = draug




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                 importGeometry               % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



************************************************ 

Testing importGeometry(...): 

importGeometry =  
true 

************************************************ 

getObjectList:   

************************************************ 

getObjectList:   

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%                  getObjectList               % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



"O1" 

@@ -241,7 +498,17 @@ getObjectList:

"O3" 

Testing applyToIntersected Geometry  




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

%         applyToIntersectedGeometry           % 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 



"**PROGRAMMER ERROR** Dictionary:Elven DictionaryCannot apply RTree search to bad geometry." 

  Dictionary:Elven Dictionary does not have a geometry!
+374 −305

File changed.

Preview size limit exceeded, changes collapsed.