<commit_before>#include <osg/Version>
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>

#include <set>
#include <vector>
#include <iostream>
#include <fstream>

typedef std::pair<std::string, std::string> NamePair;
typedef std::set<NamePair> NameSet;
typedef std::vector< std::string > Words;

NamePair EmptyNamePair;


bool validName(const std::string& first)
{
    if (first.empty()) return false;
    if (first[0]<'A' || first[0]>'Z') return false;
    
    if (first.size()>=2 && (first[1]<'a' || first[1]>'z')) return false; 

    if (first=="Added") return false;
    if (first=="CameraNode") return false;
    if (first=="CopyOp") return false;
    if (first=="Fixed") return false;
    if (first=="Creator") return false;
    if (first=="CullVisitor") return false;
    if (first=="Drawable") return false;
    if (first=="Geode") return false;
    if (first=="GeoSet") return false;
    if (first=="Image") return false;
    if (first=="Images/SolarSystem") return false;
    if (first=="IntersectVisitor") return false;
    if (first=="LongIDRecord") return false;
    if (first=="Makefile") return false;
    if (first=="Matrix") return false;
    if (first=="MemoryManager") return false;
    if (first=="MeshRecord") return false;
    if (first=="Multigen") return false;
    if (first=="NewCullVisitor") return false;
    if (first=="Output") return false;
    if (first=="PageLOD") return false;
    if (first=="Improved") return false;
    if (first=="PagedLOD") return false;
    if (first=="Referenced") return false;
    if (first=="StateAttribute") return false;
    if (first=="Switch") return false;
    if (first=="TechniqueEventHandler") return false;
    if (first=="Uniform") return false;
    if (first=="Vec*") return false;
    if (first=="Viewer") return false;
    if (first=="VisualStudio") return false;
    if (first=="X") return false;
    if (first=="Y") return false;
    if (first=="Producer") return false;
    if (first=="New") return false;
    if (first=="Removed") return false;
    if (first=="Ouput") return false;
    if (first=="ReaderWriters") return false;
    if (first=="NodeVisitor") return false;
    if (first=="Fixes") return false;
    if (first=="FontImplementation") return false;
    if (first=="DisplaySettings") return false;
    if (first=="AnimationPath") return false;
    if (first=="AnimationPathCallback") return false;
    if (first=="AnimationPathManipulator") return false;
    if (first=="ArgumentParser") return false;
    if (first=="AttrData") return false;
    if (first=="Azimuth") return false;
    if (first=="CluserCullingCallback") return false;
    if (first=="ClusterCullingCallback") return false;
    if (first=="CoordinateSystem") return false;
    if (first=="CoordinateSystemNode") return false;
    if (first=="CoordinateSystemNode&") return false;
    if (first=="Copyright") return false;
    if (first=="Cygwin") return false;
    if (first=="CullCallbacks") return false;
    if (first=="CullingSettngs") return false;
    if (first=="DataVariance") return false;
    if (first=="DatabasePager") return false;
    if (first=="DrawElementsUByte") return false;
    if (first=="Escape") return false;
    if (first=="FluidProgram") return false;
    if (first=="FrameStats") return false;
    if (first=="FreeBSD") return false;
    if (first=="GraphicsContextImplementation") return false;
    if (first=="GraphicsThread") return false;
    if (first=="Images") return false;
    if (first=="IndexBlock") return false;
    if (first=="Inventor") return false;
    if (first=="Make") return false;
    if (first=="Material") return false;
    if (first=="MergeGeometryVisitor") return false;
    if (first=="Mode") return false;
    if (first=="Prodcuer") return false;
    if (first=="ProxyNode") return false;
    if (first=="ReentrantMutex") return false;
    if (first=="ReferenceFrame") return false;
    if (first=="RemoveLoadedProxyNodes") return false;
    if (first=="RenderTargetFallback") return false;
    if (first=="RenderToTextureStage") return false;
    if (first=="Sequence") return false;
    if (first=="Shape") return false;
    if (first=="TessellationHints") return false;
    if (first=="Support") return false;
    if (first=="State") return false;
    if (first=="SmokeTrailEffect") return false;
    if (first=="TexEnv") return false;
    if (first=="Texture3D") return false;
    if (first=="TextureCubeMap") return false;
    if (first=="TextureObjectManager") return false;
    if (first=="TextureRectangle(Image*") return false;
    if (first=="TextureType") return false;
    if (first=="Texuture") return false;
    if (first=="TriStripVisitor") return false;
    if (first=="UserData") return false;
    if (first=="Viewport") return false;
    if (first=="Visual") return false;
    if (first=="Studio") return false;
    if (first=="Vec2d") return false;
    if (first=="Vec3d") return false;
    if (first=="Windows") return false;
    if (first=="Version") return false;
    if (first=="Viewport") return false;
    if (first=="Core") return false;
    if (first=="DataSet") return false;
    if (first=="Endian") return false;
    if (first=="ImageOptions") return false;
    if (first=="ImageStream") return false;
    if (first=="KeyboardMouse") return false;
    if (first=="KeyboardMouseCallback") return false;
    if (first=="AutoTransform") return false;
    if (first=="LightModel") return false;
    if (first=="MatrixManipulator") return false;
    if (first=="MatrixTransform") return false;
    if (first=="OpenDX") return false;
    if (first=="ParentList") return false;
    if (first=="TerraPage") return false;
    if (first=="OveralyNode") return false;
    if (first=="OpenThreads") return false;
    if (first=="PolygonStipple") return false;
    if (first=="SceneView") return false;
    if (first=="PrimitiveIndexFunctor") return false;
    if (first=="PolytopeVisitor") return false;
    if (first=="Performer") return false;
    if (first=="Paging") return false;
    return true;
}

std::string typoCorrection(const std::string& name)
{
#if 0
    if (name=="") return "";
    if (name=="") return "";
    if (name=="") return "";
#endif
    if (name=="Micheal") return "Michael";
    if (name=="Heirtlein") return "Hertlein";
    if (name=="Yefrei") return "Yefei";
    if (name=="Randal") return "Randall";
    if (name=="Hooper") return "Hopper";
    if (name=="Molishtan") return "Moloshtan";
    if (name=="Vines") return "Vine";
    if (name=="Connel") return "Connell";
    if (name=="Bistroviae") return "Bistrovic";
    if (name=="Christaiansen") return "Christiansen";
    if (name=="Daust") return "Daoust";
    if (name=="Daved") return "David";
    if (name=="Fred") return "Frederic";
    if (name=="Fredrick") return "Frederic";
    if (name=="Fredric") return "Frederic";
    if (name=="Garrat") return "Garret";
    if (name=="Geof") return "Geoff";
    if (name=="Gronenger") return "Gronager";
    if (name=="Gronger") return "Gronager";
    if (name=="Heirtlein") return "Heirtlein";
    if (name=="Heirtlein") return "Hertlein";
    if (name=="Hertlien") return "Hertlein";
    if (name=="Hi") return "He";
    if (name=="Inverson") return "Iverson";
    if (name=="Iversion") return "Iverson";
    if (name=="Jeoen") return "Joran";
    if (name=="Johhansen") return "Johansen";
    if (name=="Johnansen") return "Johansen";
    if (name=="Johnasen") return "Johansen";
    if (name=="Jolley") return "Jolly";
    if (name=="Jose") return "Jos";
    if (name=="J") return "Jos";
    if (name=="Keuhne") return "Kuehne";
    if (name=="Kheune") return "Kuehne";
    if (name=="Lashari") return "Lashkari";
    if (name=="Laskari") return "Lashkari";
    if (name=="Macro") return "Marco";
    if (name=="Mammond") return "Marmond";
    if (name=="March") return "Marco";
    if (name=="Marz") return "Martz";
    if (name=="Molishtan") return "Molishtan";
    if (name=="Molishtan") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moule") return "Moiule";
    if (name=="Nicklov") return "Nikolov";
    if (name=="Olad") return "Olaf";
    if (name=="Osfied") return "Osfield";
    if (name=="Pail") return "Paul";
    if (name=="Sewel") return "Sewell";
    if (name=="Sjolie") return "Sjlie";
    if (name=="Sokolosky") return "Sokolowsky";
    if (name=="Sokolsky") return "Sokolowsky";
    if (name=="Sonda") return "Sondra";
    if (name=="Stansilav") return "Stanislav";
    if (name=="Stefan") return "Stephan";
    if (name=="Stell") return "Steel";
    if (name=="Tarantilils") return "Tarantilis";
    if (name=="Wieblen") return "Weiblen";
    if (name=="Xennon") return "Hanson";
    if (name=="Yfei") return "Yefei";
    if (name=="Oritz") return "Ortiz";
    if (name=="Cobin") return "Corbin";
    return name;
}

void nameCorrection(NamePair& name)
{
    if (name.first=="Eric" && name.second=="Hammil")
    {
        name.first = "Chris";
        name.second = "Hanson";
    }
    if (name.first=="Nick" && name.second=="")
    {
        name.first = "Trajce";
        name.second = "Nikolov";
    }
    if (name.first=="Julia" && name.second=="Ortiz")
    {
        name.first = "Julian";
        name.second = "Ortiz";
    }
    if (name.first=="Rune" && name.second=="Schmidt")
    {
        name.first = "Rune";
        name.second = "<NAME>";
    }
    if (name.first=="Romano" && name.second=="Jos")
    {
        name.first = "Romano";
        name.second = "<NAME>";
    }
    if (name.first=="Rommano" && name.second=="Silva")
    {
        name.first = "Romano";
        name.second = "<NAME>";
    }
}

void lastValidCharacter(const std::string& name, unsigned int& pos,char c)
{
    for(unsigned int i=0;i<pos;++i)
    {
        if (name[i]==c)
        {
            pos = i;
            return;
        }
    }
}

void lastValidCharacter(const std::string& name, unsigned int& last)
{
    lastValidCharacter(name, last, '.');
    lastValidCharacter(name, last, ',');
    lastValidCharacter(name, last, '\'');
    lastValidCharacter(name, last, '/');
    lastValidCharacter(name, last, '\\');
    lastValidCharacter(name, last, ':');
    lastValidCharacter(name, last, ';');
    lastValidCharacter(name, last, ')');
}



NamePair createName(const std::string& first, const std::string& second)
{
    if (first.empty()) return EmptyNamePair;
    
    unsigned int last = first.size();
    
    lastValidCharacter(first, last);
    
    if (last==0) return EmptyNamePair;
    
    std::string name;
    
    name.append(first.begin(), first.begin()+last);

    if (!validName(name)) return EmptyNamePair;

    name = typoCorrection(name);
    
    if (second.empty()) return NamePair(name,"");
    
    if (!validName(second)) return NamePair(name,"");

    last = second.size();
    
    lastValidCharacter(second, last);
    
    if (last>0)
    {
        std::string surname(second.begin(), second.begin()+last);
        surname = typoCorrection(surname);
    
        return NamePair(name, surname);
    }
    
    return NamePair(name,"");
}

bool submissionsSequence(const Words& words, unsigned int& i)
{
    if (i+1>=words.size()) return false;
    
    if (words[i]=="From" || 
        words[i]=="from" || 
        words[i]=="From:" || 
        words[i]=="from:" || 
        words[i]=="Added" || 
        words[i]=="Merged" || 
        words[i]=="Integrated") return true;
        
    if (i+2>=words.size()) return false;
    
    if (words[i]=="submitted" && words[i+1]=="by")
    {
        i+=1;
        return true;
    }
        
    if (words[i]=="Folded" && words[i+1]=="in")
    {
        i+=1;
        return true;
    }

    if (words[i]=="Checked" && words[i+1]=="in")
    {
        i+=1;
        return true;
    }

    if (i+3>=words.size()) return false;

    if (words[i]=="sent" && words[i+1]=="in" && words[i+2]=="by")
    {
        i+=2;
        return true;
    }
    
    return false;
}

void readContributors(NameSet& names, const std::string& file)
{
    std::ifstream fin(file.c_str());
    
    Words words;
    while(fin)
    {
        std::string keyword;
        fin >> keyword;
        words.push_back(keyword);
    }
    
    std::string blank_string;
    
    for(unsigned int i=0; i< words.size(); ++i)
    {
        if (submissionsSequence(words,i)) 
        {
            if (i+2<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], words[i+2]);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=2;
            }
            else if (i+1<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], blank_string);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=1;
            }
        }
    }

    if (names.size()>1)
    {
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            )
        {
            if (itr->second.empty()) 
            {
                NameSet::iterator next_itr = itr;
                ++next_itr;
                
                if (next_itr!=names.end() && itr->first==next_itr->first)
                {
                    names.erase(itr);
                    itr = next_itr;
                }
                else
                {
                    ++itr;
                }
            }
            else
            {
                ++itr;
            }
        }
    }
}

void buildContributors(NameSet& names)
{
    names.insert(NamePair("Robert","Osfield"));
    names.insert(NamePair("Don","Burns"));
    names.insert(NamePair("Marco","Jez"));
    names.insert(NamePair("Karsten","Weiss"));
    names.insert(NamePair("Graeme","Harkness"));
    names.insert(NamePair("Axel","Volley"));
    names.insert(NamePair("Nikolaus","Hanekamp"));
    names.insert(NamePair("Kristopher","Bixler"));
    names.insert(NamePair("Tanguy","Fautr"));
    names.insert(NamePair("J.E.","Hoffmann"));
}

int main( int argc, char **argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options]");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("-c or --contributors","Print out the contributors list.");
    arguments.getApplicationUsage()->addCommandLineOption("-r <file> or --read <file>","Read the changelog to generate an estimated contributors list.");

    std::cout<<osgGetLibraryName()<< " "<< osgGetVersion()<<std::endl<<std::endl;

    bool printContributors = false;
    while ( arguments.read("-c") || arguments.read("--contributors")) printContributors = true;

    std::string changeLog;
    while ( arguments.read("-r",changeLog) || arguments.read("--read",changeLog)) printContributors = true;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        std::cout<<arguments.getApplicationUsage()->getCommandLineUsage()<<std::endl;
        arguments.getApplicationUsage()->write(std::cout,arguments.getApplicationUsage()->getCommandLineOptions());
        return 1;
    }

    if (printContributors)
    {
        NameSet names;
        buildContributors(names);
        if (!changeLog.empty())
        {
            readContributors(names, changeLog);
        }
        
        std::cout<<names.size()<<" Contributors:"<<std::endl<<std::endl;
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            ++itr)
        {
            std::cout<<"  "<<itr->first<<" "<<itr->second<<std::endl;
        }
    }

    return 0;
}
<commit_msg>Added typo correction for "Jolley".<commit_after>#include <osg/Version>
#include <osg/ArgumentParser>
#include <osg/ApplicationUsage>

#include <set>
#include <vector>
#include <iostream>
#include <fstream>

typedef std::pair<std::string, std::string> NamePair;
typedef std::set<NamePair> NameSet;
typedef std::vector< std::string > Words;

NamePair EmptyNamePair;


bool validName(const std::string& first)
{
    if (first.empty()) return false;
    if (first[0]<'A' || first[0]>'Z') return false;
    
    if (first.size()>=2 && (first[1]<'a' || first[1]>'z')) return false; 

    if (first=="Added") return false;
    if (first=="CameraNode") return false;
    if (first=="CopyOp") return false;
    if (first=="Fixed") return false;
    if (first=="Creator") return false;
    if (first=="CullVisitor") return false;
    if (first=="Drawable") return false;
    if (first=="Geode") return false;
    if (first=="GeoSet") return false;
    if (first=="Image") return false;
    if (first=="Images/SolarSystem") return false;
    if (first=="IntersectVisitor") return false;
    if (first=="LongIDRecord") return false;
    if (first=="Makefile") return false;
    if (first=="Matrix") return false;
    if (first=="MemoryManager") return false;
    if (first=="MeshRecord") return false;
    if (first=="Multigen") return false;
    if (first=="NewCullVisitor") return false;
    if (first=="Output") return false;
    if (first=="PageLOD") return false;
    if (first=="Improved") return false;
    if (first=="PagedLOD") return false;
    if (first=="Referenced") return false;
    if (first=="StateAttribute") return false;
    if (first=="Switch") return false;
    if (first=="TechniqueEventHandler") return false;
    if (first=="Uniform") return false;
    if (first=="Vec*") return false;
    if (first=="Viewer") return false;
    if (first=="VisualStudio") return false;
    if (first=="X") return false;
    if (first=="Y") return false;
    if (first=="Producer") return false;
    if (first=="New") return false;
    if (first=="Removed") return false;
    if (first=="Ouput") return false;
    if (first=="ReaderWriters") return false;
    if (first=="NodeVisitor") return false;
    if (first=="Fixes") return false;
    if (first=="FontImplementation") return false;
    if (first=="DisplaySettings") return false;
    if (first=="AnimationPath") return false;
    if (first=="AnimationPathCallback") return false;
    if (first=="AnimationPathManipulator") return false;
    if (first=="ArgumentParser") return false;
    if (first=="AttrData") return false;
    if (first=="Azimuth") return false;
    if (first=="CluserCullingCallback") return false;
    if (first=="ClusterCullingCallback") return false;
    if (first=="CoordinateSystem") return false;
    if (first=="CoordinateSystemNode") return false;
    if (first=="CoordinateSystemNode&") return false;
    if (first=="Copyright") return false;
    if (first=="Cygwin") return false;
    if (first=="CullCallbacks") return false;
    if (first=="CullingSettngs") return false;
    if (first=="DataVariance") return false;
    if (first=="DatabasePager") return false;
    if (first=="DrawElementsUByte") return false;
    if (first=="Escape") return false;
    if (first=="FluidProgram") return false;
    if (first=="FrameStats") return false;
    if (first=="FreeBSD") return false;
    if (first=="GraphicsContextImplementation") return false;
    if (first=="GraphicsThread") return false;
    if (first=="Images") return false;
    if (first=="IndexBlock") return false;
    if (first=="Inventor") return false;
    if (first=="Make") return false;
    if (first=="Material") return false;
    if (first=="MergeGeometryVisitor") return false;
    if (first=="Mode") return false;
    if (first=="Prodcuer") return false;
    if (first=="ProxyNode") return false;
    if (first=="ReentrantMutex") return false;
    if (first=="ReferenceFrame") return false;
    if (first=="RemoveLoadedProxyNodes") return false;
    if (first=="RenderTargetFallback") return false;
    if (first=="RenderToTextureStage") return false;
    if (first=="Sequence") return false;
    if (first=="Shape") return false;
    if (first=="TessellationHints") return false;
    if (first=="Support") return false;
    if (first=="State") return false;
    if (first=="SmokeTrailEffect") return false;
    if (first=="TexEnv") return false;
    if (first=="Texture3D") return false;
    if (first=="TextureCubeMap") return false;
    if (first=="TextureObjectManager") return false;
    if (first=="TextureRectangle(Image*") return false;
    if (first=="TextureType") return false;
    if (first=="Texuture") return false;
    if (first=="TriStripVisitor") return false;
    if (first=="UserData") return false;
    if (first=="Viewport") return false;
    if (first=="Visual") return false;
    if (first=="Studio") return false;
    if (first=="Vec2d") return false;
    if (first=="Vec3d") return false;
    if (first=="Windows") return false;
    if (first=="Version") return false;
    if (first=="Viewport") return false;
    if (first=="Core") return false;
    if (first=="DataSet") return false;
    if (first=="Endian") return false;
    if (first=="ImageOptions") return false;
    if (first=="ImageStream") return false;
    if (first=="KeyboardMouse") return false;
    if (first=="KeyboardMouseCallback") return false;
    if (first=="AutoTransform") return false;
    if (first=="LightModel") return false;
    if (first=="MatrixManipulator") return false;
    if (first=="MatrixTransform") return false;
    if (first=="OpenDX") return false;
    if (first=="ParentList") return false;
    if (first=="TerraPage") return false;
    if (first=="OveralyNode") return false;
    if (first=="OpenThreads") return false;
    if (first=="PolygonStipple") return false;
    if (first=="SceneView") return false;
    if (first=="PrimitiveIndexFunctor") return false;
    if (first=="PolytopeVisitor") return false;
    if (first=="Performer") return false;
    if (first=="Paging") return false;
    return true;
}

std::string typoCorrection(const std::string& name)
{
#if 0
    if (name=="") return "";
    if (name=="") return "";
    if (name=="") return "";
#endif
    if (name=="Micheal") return "Michael";
    if (name=="Heirtlein") return "Hertlein";
    if (name=="Yefrei") return "Yefei";
    if (name=="Randal") return "Randall";
    if (name=="Hooper") return "Hopper";
    if (name=="Molishtan") return "Moloshtan";
    if (name=="Vines") return "Vine";
    if (name=="Connel") return "Connell";
    if (name=="Bistroviae") return "Bistrovic";
    if (name=="Christaiansen") return "Christiansen";
    if (name=="Daust") return "Daoust";
    if (name=="Daved") return "David";
    if (name=="Fred") return "Frederic";
    if (name=="Fredrick") return "Frederic";
    if (name=="Fredric") return "Frederic";
    if (name=="Garrat") return "Garret";
    if (name=="Geof") return "Geoff";
    if (name=="Gronenger") return "Gronager";
    if (name=="Gronger") return "Gronager";
    if (name=="Heirtlein") return "Heirtlein";
    if (name=="Heirtlein") return "Hertlein";
    if (name=="Hertlien") return "Hertlein";
    if (name=="Hi") return "He";
    if (name=="Inverson") return "Iverson";
    if (name=="Iversion") return "Iverson";
    if (name=="Jeoen") return "Joran";
    if (name=="Johhansen") return "Johansen";
    if (name=="Johnansen") return "Johansen";
    if (name=="Johnasen") return "Johansen";
    if (name=="Jolly") return "Jolley";
    if (name=="Jose") return "Jos";
    if (name=="J") return "Jos";
    if (name=="Keuhne") return "Kuehne";
    if (name=="Kheune") return "Kuehne";
    if (name=="Lashari") return "Lashkari";
    if (name=="Laskari") return "Lashkari";
    if (name=="Macro") return "Marco";
    if (name=="Mammond") return "Marmond";
    if (name=="March") return "Marco";
    if (name=="Marz") return "Martz";
    if (name=="Molishtan") return "Molishtan";
    if (name=="Molishtan") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moloshton") return "Moloshtan";
    if (name=="Moule") return "Moiule";
    if (name=="Nicklov") return "Nikolov";
    if (name=="Olad") return "Olaf";
    if (name=="Osfied") return "Osfield";
    if (name=="Pail") return "Paul";
    if (name=="Sewel") return "Sewell";
    if (name=="Sjolie") return "Sjlie";
    if (name=="Sokolosky") return "Sokolowsky";
    if (name=="Sokolsky") return "Sokolowsky";
    if (name=="Sonda") return "Sondra";
    if (name=="Stansilav") return "Stanislav";
    if (name=="Stefan") return "Stephan";
    if (name=="Stell") return "Steel";
    if (name=="Tarantilils") return "Tarantilis";
    if (name=="Wieblen") return "Weiblen";
    if (name=="Xennon") return "Hanson";
    if (name=="Yfei") return "Yefei";
    if (name=="Oritz") return "Ortiz";
    if (name=="Cobin") return "Corbin";
    return name;
}

void nameCorrection(NamePair& name)
{
    if (name.first=="Eric" && name.second=="Hammil")
    {
        name.first = "Chris";
        name.second = "Hanson";
    }
    if (name.first=="Nick" && name.second=="")
    {
        name.first = "Trajce";
        name.second = "Nikolov";
    }
    if (name.first=="Julia" && name.second=="Ortiz")
    {
        name.first = "Julian";
        name.second = "Ortiz";
    }
    if (name.first=="Rune" && name.second=="Schmidt")
    {
        name.first = "Rune";
        name.second = "<NAME>";
    }
    if (name.first=="Romano" && name.second=="Jos")
    {
        name.first = "Romano";
        name.second = "<NAME>";
    }
    if (name.first=="Rommano" && name.second=="Silva")
    {
        name.first = "Romano";
        name.second = "<NAME>";
    }
}

void lastValidCharacter(const std::string& name, unsigned int& pos,char c)
{
    for(unsigned int i=0;i<pos;++i)
    {
        if (name[i]==c)
        {
            pos = i;
            return;
        }
    }
}

void lastValidCharacter(const std::string& name, unsigned int& last)
{
    lastValidCharacter(name, last, '.');
    lastValidCharacter(name, last, ',');
    lastValidCharacter(name, last, '\'');
    lastValidCharacter(name, last, '/');
    lastValidCharacter(name, last, '\\');
    lastValidCharacter(name, last, ':');
    lastValidCharacter(name, last, ';');
    lastValidCharacter(name, last, ')');
}



NamePair createName(const std::string& first, const std::string& second)
{
    if (first.empty()) return EmptyNamePair;
    
    unsigned int last = first.size();
    
    lastValidCharacter(first, last);
    
    if (last==0) return EmptyNamePair;
    
    std::string name;
    
    name.append(first.begin(), first.begin()+last);

    if (!validName(name)) return EmptyNamePair;

    name = typoCorrection(name);
    
    if (second.empty()) return NamePair(name,"");
    
    if (!validName(second)) return NamePair(name,"");

    last = second.size();
    
    lastValidCharacter(second, last);
    
    if (last>0)
    {
        std::string surname(second.begin(), second.begin()+last);
        surname = typoCorrection(surname);
    
        return NamePair(name, surname);
    }
    
    return NamePair(name,"");
}

bool submissionsSequence(const Words& words, unsigned int& i)
{
    if (i+1>=words.size()) return false;
    
    if (words[i]=="From" || 
        words[i]=="from" || 
        words[i]=="From:" || 
        words[i]=="from:" || 
        words[i]=="Added" || 
        words[i]=="Merged" || 
        words[i]=="Integrated") return true;
        
    if (i+2>=words.size()) return false;
    
    if (words[i]=="submitted" && words[i+1]=="by")
    {
        i+=1;
        return true;
    }
        
    if (words[i]=="Folded" && words[i+1]=="in")
    {
        i+=1;
        return true;
    }

    if (words[i]=="Checked" && words[i+1]=="in")
    {
        i+=1;
        return true;
    }

    if (i+3>=words.size()) return false;

    if (words[i]=="sent" && words[i+1]=="in" && words[i+2]=="by")
    {
        i+=2;
        return true;
    }
    
    return false;
}

void readContributors(NameSet& names, const std::string& file)
{
    std::ifstream fin(file.c_str());
    
    Words words;
    while(fin)
    {
        std::string keyword;
        fin >> keyword;
        words.push_back(keyword);
    }
    
    std::string blank_string;
    
    for(unsigned int i=0; i< words.size(); ++i)
    {
        if (submissionsSequence(words,i)) 
        {
            if (i+2<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], words[i+2]);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=2;
            }
            else if (i+1<words.size() && validName(words[i+1]))
            {
                NamePair name = createName(words[i+1], blank_string);
                nameCorrection(name);
                if (!name.first.empty()) names.insert(name);
                i+=1;
            }
        }
    }

    if (names.size()>1)
    {
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            )
        {
            if (itr->second.empty()) 
            {
                NameSet::iterator next_itr = itr;
                ++next_itr;
                
                if (next_itr!=names.end() && itr->first==next_itr->first)
                {
                    names.erase(itr);
                    itr = next_itr;
                }
                else
                {
                    ++itr;
                }
            }
            else
            {
                ++itr;
            }
        }
    }
}

void buildContributors(NameSet& names)
{
    names.insert(NamePair("Robert","Osfield"));
    names.insert(NamePair("Don","Burns"));
    names.insert(NamePair("Marco","Jez"));
    names.insert(NamePair("Karsten","Weiss"));
    names.insert(NamePair("Graeme","Harkness"));
    names.insert(NamePair("Axel","Volley"));
    names.insert(NamePair("Nikolaus","Hanekamp"));
    names.insert(NamePair("Kristopher","Bixler"));
    names.insert(NamePair("Tanguy","Fautr"));
    names.insert(NamePair("J.E.","Hoffmann"));
}

int main( int argc, char **argv)
{
    osg::ArgumentParser arguments(&argc,argv);
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options]");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
    arguments.getApplicationUsage()->addCommandLineOption("-c or --contributors","Print out the contributors list.");
    arguments.getApplicationUsage()->addCommandLineOption("-r <file> or --read <file>","Read the changelog to generate an estimated contributors list.");

    std::cout<<osgGetLibraryName()<< " "<< osgGetVersion()<<std::endl<<std::endl;

    bool printContributors = false;
    while ( arguments.read("-c") || arguments.read("--contributors")) printContributors = true;

    std::string changeLog;
    while ( arguments.read("-r",changeLog) || arguments.read("--read",changeLog)) printContributors = true;

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        std::cout<<arguments.getApplicationUsage()->getCommandLineUsage()<<std::endl;
        arguments.getApplicationUsage()->write(std::cout,arguments.getApplicationUsage()->getCommandLineOptions());
        return 1;
    }

    if (printContributors)
    {
        NameSet names;
        buildContributors(names);
        if (!changeLog.empty())
        {
            readContributors(names, changeLog);
        }
        
        std::cout<<names.size()<<" Contributors:"<<std::endl<<std::endl;
        for(NameSet::iterator itr = names.begin();
            itr != names.end();
            ++itr)
        {
            std::cout<<"  "<<itr->first<<" "<<itr->second<<std::endl;
        }
    }

    return 0;
}

{'fraction_non_alphanumeric': 0.17616173049110231, 'fraction_numerical': 0.002326605043073634, 'mean_word_length': 3.1490999217323243, 'pattern_counts': {'":': 0, '<': 109, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '807071', 'n_tokens_mistral': 10660, 'n_tokens_neox': 10427, 'n_words': 2384}