diff --git a/applications/osgversion/CMakeLists.txt b/applications/osgversion/CMakeLists.txt index 45aedad94..8f776ae98 100644 --- a/applications/osgversion/CMakeLists.txt +++ b/applications/osgversion/CMakeLists.txt @@ -1,5 +1,10 @@ SET(TARGET_SRC osgversion.cpp ) +IF (OSG_MAINTAINER) + SET(TARGET_SRC ${TARGET_SRC} Contributors.cpp ) + ADD_DEFINITIONS("-DBUILD_CONTRIBUTORS") +ENDIF() + SET(TARGET_COMMON_LIBRARIES OpenThreads osg diff --git a/applications/osgversion/Contributors.cpp b/applications/osgversion/Contributors.cpp new file mode 100644 index 000000000..e9f16ceeb --- /dev/null +++ b/applications/osgversion/Contributors.cpp @@ -0,0 +1,836 @@ +// The majority of the application is dedicated to building the +// current contribitors list by parsing the ChangeLog, it just takes +// one line in the main itself to report the version number. + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using namespace std; + + +#if defined(_MSC_VER) + #pragma setlocale("C") +#endif + +typedef pair NamePair; +typedef map NameMap; +typedef vector Words; + +NamePair EmptyNamePair; +NamePair NameRobertOsfield("Robert", "Osfield"); +NamePair NameDonBurns ("Don", "Burns"); + + +const char* validNames[] = +{ + "de", + "den", + "van" +}; + +const char* invalidNames[] = +{ + "Added", + "AnimationPath", + "AnimationPathCallback", + "AnimationPathManipulator", + "ArgumentParser", + "AttrData", + "AutoTransform", + "AutoTransform.", + "Azimuth", + "BlenColour(Vec4", + "Camera", + "CameraBarrierCallback", + "CameraNode", + "Canvas", + "CluserCullingCallback", + "ClusterCullingCallback", + "CoordinateSystem", + "CoordinateSystemNode", + "CoordinateSystemNode&", + "CopyOp", + "Copyright", + "Core", + "Creator", + "CullCallbacks", + "CullingSettngs", + "CullVisitor", + "CullVistor", + "Cygwin", + "DatabasePager", + "DataSet", + "DataVariance", + "DeleteHandler", + "DisplaySettings", + "Drawable", + "DrawElementsUByte", + "Endian", + "Escape", + "EventQueue", + "Face", + "Files", + "Fixed", + "Fixes", + "FluidProgram", + "FontImplementation", + "FrameStats", + "Framstamp", + "FreeBSD", + "Geode", + "GeoemtryTechnique", + "GeometryTechnique", + "GeoSet", + "GraphicsContext", + "GraphicsContextImplementation", + "GraphicsThread", + "GraphicsWindowX11", + "Group", + "Image", + "ImageOptions", + "Images", + "Images/SolarSystem", + "ImageStream", + "Improved", + "IndexBlock", + "IndexFaceSets", + "IntersectVisitor", + "Inventor", + "KdTree", + "KeyboardMouse", + "KeyboardMouseCallback", + "LightModel", + "LightPointNode", + "LineSegment", + "LineStipple", + "Logos", + "LongIDRecord", + "Make", + "Makefile", + "Material", + "Matrix", + "Matrix*", + "MatrixManipulator", + "MatrixTransform", + "MemoryManager", + "MergeGeometryVisitor", + "MeshRecord", + "Mode", + "Mr", + "Multigen", + "New", + "NewCullVisitor", + "NodeVisitor", + "Object", + "OpenDX", + "OpenSceneGraph", + "OpenSceneGraph-2", + "OpenSceneGraph-osgWidget-dev", + "OpenThreads", + "OperationThread", + "Optimizer", + "OrientationConverter", + "Osfields", + "Ouput", + "Output", + "OveralyNode", + "PagedLOD", + "PageLOD", + "Paging", + "ParentList", + "Performer", + "PickHandler", + "PixelDataBufferObject", + "PolygonStipple", + "PolytopeVisitor", + "PrimitiveIndexFunctor", + "Prodcuer", + "Producer", + "ProducerEventCallback", + "Program", + "Proxy", + "ProxyNode", + "Quake3", + "Quicktime", + "ReaderWriters", + "ReentrantMutex", + "Referenced", + "ReferenceFrame", + "Removed", + "RemoveLoadedProxyNodes", + "RenderStage", + "RenderTargetFallback", + "RenderToTextureStage", + "SceneGraphBuilder", + "SceneView", + "Sequence", + "Shape", + "SimpleViewer", + "SimpleViewer", + "SmokeTrailEffect", + "Source", + "SpotExponent", + "State", + "StateAttribute", + "Stats", + "StatsVisitor", + "Studio", + "Support", + "Switch", + "TechniqueEventHandler", + "TerraPage", + "TessellationHints", + "TestManipulator", + "TestSupportCallback", + "TexEnv", + "TexMat(Matrix", + "Texture", + "Texture2DArray", + "Texture3D", + "TextureCubeMap", + "TextureObjectManager", + "TextureRectangle", + "TextureRectangle(Image*", + "TextureType", + "Texuture", + "TriStripVisitor", + "TrPageViewer", + "Uniform", + "UseFarLineSegments", + "UserData", + "Valve", + "Vec*", + "Vec2d", + "Vec3d", + "Vec4ub", + "Version", + "VertexData", + "View", + "Viewer", + "ViewPoint", + "Viewport", + "Viewport", + "Visual", + "VisualStudio", + "WindowData", + "Windows", + "X", + "Xcode", + "Y" +}; + + +struct TypoCorrection +{ + const char* original; + const char* corrected; +}; + +TypoCorrection typoCorrections[] = +{ + {"Aderian", "Adrian"}, + {"Adndre", "Andre"}, + {"Adrain", "Adrian"}, + {"Amueller", "Aumueller"}, + {"Andew", "Andrew"}, + {"André", "André"}, + {"Antione", "Antoine"}, + {"Antonoine", "Antoine"}, + {"Atr", "Art"}, + {"Baverage", "Beverage"}, + {"Bistroviae", "Bistrovic"}, + {"Callue", "Callu"}, + {"Christaiansen", "Christiansen"}, + {"Cobin", "Corbin"}, + {"Comporesi", "Camporesi"}, + {"Connel", "Connell"}, + {"Cullu", "Callu"}, + {"Daneil", "Daniel"}, + {"Daust", "Daoust"}, + {"Daved", "David"}, + {"Drederic", "Frederic"}, + {"Eileman", "Eilemann"}, + {"Elgi", "Egli"}, + {"Fabian", "Fabien"}, + {"Fautre", "Fautré"}, + {"Frashid", "Farshid"}, + {"Fred", "Frederic"}, + {"Fredrick", "Frederic"}, + {"Fredric", "Frederic"}, + {"Froechlich", "Fröhlich"}, + {"Froehilch", "Fröhlich"}, + {"Froehlich", "Fröhlich"}, + {"Froelich", "Fröhlich"}, + {"Froenlich", "Fröhlich"}, + {"Fröhlich", "Fröhlich"}, + {"Fruciel", "Frauciel"}, + {"García", "Garcea"}, + {"Garrat", "Garrett"}, + {"Garret", "Garrett"}, + {"Geof", "Geoff"}, + {"Giatan", "Gaitan"}, + {"Gronenger", "Gronager"}, + {"Gronger", "Gronager"}, + {"Haritchablaet", "Haritchabalet"}, + {"Hebelin", "Herbelin"}, + {"Heirtlein", "Hertlein"}, + {"Heirtlein", "Hertlein"}, + {"Hertleinm", "Hertlein"}, + {"Hertlien", "Hertlein"}, + {"Hi", "He"}, + {"Hooper", "Hopper"}, + {"Inverson", "Iverson"}, + {"Iversion", "Iverson"}, + {"Jean-Sebastein", "Jean-Sebastien"}, + {"Jean-Sebastian", "Jean-Sebastien"}, + {"Jean-Sebastirn", "Jean-Sebastien"}, + {"Jea-Sebastien", "Jean-Sebastien"}, + {"Johhansen", "Johansen"}, + {"Johnansen", "Johansen"}, + {"Johnasen", "Johansen"}, + {"Jolly", "Jolley"}, + {"Jose", "José"}, + {"José", "José"}, + {"Joson", "Jason"}, + {"J", "José"}, + {"Keuhne", "Kuehne"}, + {"Kheune", "Kuehne"}, + {"Lagrade", "Lagarde"}, + {"Larshkari", "Lashkari"}, + {"Lashakari", "Lashkari"}, + {"Lashari", "Lashkari"}, + {"Lasharki", "Lashkari"}, + {"Laskari", "Lashkari"}, + {"Leandowski", "Lewandowski"}, + {"Lawandowski", "Lewandowski"}, + {"Lucas", "Luaces"}, + {"Lugi", "Luigi"}, + {"Lweandowski", "Lewandowski"}, + {"Maceij", "Maciej"}, + {"Machler", "Mächler"}, + {"Macro", "Marco"}, + {"Maechler", "Mächler"}, + {"Mahai", "Mihai"}, + {"Mammond", "Marmond"}, + {"March", "Marco"}, + {"Martsz", "Martz"}, + {"Marz", "Martz"}, + {"Matz", "Martz"}, + {"Melchoir", "Melchior"}, + {"Mellis", "Melis"}, + {"Messerschimdt", "Messerschmidt"}, + {"Micheal", "Michael"}, + {"Mihair", "Mihai"}, + {"Molishtan", "Moloshtan"}, + {"Molishtan", "Moloshtan"}, + {"Moloshton", "Moloshtan"}, + {"Morné", "Morné"}, + {"Morne", "Morné"}, + {"Moule", "Moiule"}, + {"Narache", "Marache"}, + {"Nicklov", "Nikolov"}, + {"Nickolov", "Nikolov"}, + {"Olad", "Olaf"}, + {"Olar", "Olaf"}, + {"Oritz", "Ortiz"}, + {"Osfeld", "Osfield"}, + {"Osfied", "Osfield"}, + {"Pail", "Paul"}, + {"Rajce", "Trajce"}, + {"Randal", "Randall"}, + {"Robet", "Robert"}, + {"Rodger", "Roger"}, + {"Rolad", "Roland"}, + {"Rucard", "Richard"}, + {"Sekender", "Sukender"}, + {"Sewel", "Sewell"}, + {"Simmonson", "Simonsson"}, + {"Simmonsson", "Simonsson"}, + {"Sjolie", "Sjölie"}, + {"Sjölie", "Sjölie"}, + {"Skinnder", "Skinner"}, + {"Sokolosky", "Sokolowsky"}, + {"Sokolowky", "Sokolowsky"}, + {"Sokolowki", "Sokolowsky"}, + {"Sokolowski", "Sokolowsky"}, + {"Sokolsky", "Sokolowsky"}, + {"Sokolwsky", "Sokolowsky"}, + {"Sonda", "Sondra"}, + {"Stansilav", "Stanislav"}, + {"Stefan", "Stephan"}, + {"Stell", "Steel"}, + {"Sylvan", "Sylvain"}, + {"Takeahei", "Takahei"}, + {"Takehei", "Takahei"}, + {"Tarantilils", "Tarantilis"}, + {"Trastenjak", "Trstenjak"}, + {"Urlich", "Ulrich"}, + {"Vines", "Vine"}, + {"Waldrom", "Waldron"}, + {"Wedner", "Weidner"}, + {"Weidemann", "Wiedemann"}, + {"Wieblen", "Weiblen"}, + {"Woesnner", "Woessner"}, + {"Wojchiech", "Wojciech"}, + {"Wojiech", "Wojciech"}, + {"Xennon", "Hanson"}, + {"Yefrei", "Yefei"}, + {"Yfei", "Yefei"} +}; + + +struct NameCorrection +{ + const char* originalFirst; + const char* originalSecond; + const char* correctedFirst; + const char* correctedSecond; +}; + +NameCorrection nameCorrections[] = +{ + {"Marc", "Sciabica", + "Mark", "Sciabica"}, + {"Jean", "Sebastien", + "Jean-Sebastien", "Guay"}, + {"Michale", "Platings", + "Michael", "Platings"}, + {"Mick", "", + "Maik", "Keller"}, + {"Gary", "Quin", + "Gary", "Quinn"}, + {"BjornHein", "", + "Björn", "Hein"}, + {"Bjorn", "Hein", + "Björn", "Hein"}, + {"Erik", "van", + "Erik", "den Dekker"}, + {"Erik", "den", + "Erik", "den Dekker"}, + {"Jeoen", "den", + "Jeroen", "den Dekker"}, + {"John", "Vidar", + "John", "Vidar Larring"}, + {"John", "Vida", + "John", "Vidar Larring"}, + {"Sebastien", "Messerschmidt", + "Sebastian", "Messerschmidt"}, + {"Mattias", "Fröhlich", + "Mathias", "Fröhlich"}, + {"Mathias", "Helsing", + "Mattias", "Helsing"}, + {"Jose", "Delport", + "J.P.", "Delport"}, + {"José", "Delport", + "J.P.", "Delport"}, + {"Franz", "Melchior", + "Melchior", "Franz"}, + {"Glen", "Waldon", + "Glenn", "Waldron"}, + {"Ralf", "Karn", + "Ralf", "Kern"}, + {"Donny", "Cipperly", + "Donald", "Cipperly"}, + {"Gino", "van", + "Gino", "van den Bergen"}, + {"Radu", "Mihai", + "Mihai", "Radu"}, + {"Art", "Trevs", + "Art", "Tevs"}, + {"Tim", "More", + "Tim", "Moore"}, + {"Andre", "Garneau", + "André", "Garneau"}, + {"Eric", "Hammil", + "Chris", "Hanson"}, + {"Paul", "de", + "Paul", "de Repentigny"}, + {"Raymond", "de", + "Raymond", "de Vries"}, + {"Nick", "", + "Trajce", "Nikolov"}, + {"Daniel", "", + "Daniel", "Sjölie"}, + {"Julia", "Ortiz", + "Julian", "Ortiz"}, + {"Rune", "Schmidt", + "Rune", "Schmidt Jensen"}, + {"Romano", "José", + "Romano", "José Magacho da Silva"}, + {"Rommano", "Silva", + "Romano", "José Magacho da Silva"}, + {"Leandro", "Motta", + "Leandro", "Motta Barros"}, + {"A", "Botorabi", + "Ali", "Botorabi"}, + {"Waltice", "", + "Walter", "J. Altice"}, + {"Drew", "", + "Drew", "Whitehouse"}, + {"Douglas", "A", + "Douglas", "A. Pouk"}, + {"Colin", "MacDonald", + "Colin", "McDonald"}, + {"Nikolov", "Trajce", + "Trajce", "Nikolov"}, + {"Frauciel", "Luc", + "Luc", "Frauciel"}, +}; + + +bool validName(const string& first) +{ + // Check for valid names + for (unsigned int i = 0; i < sizeof(validNames) / sizeof(char*); ++i) + { + if (first == validNames[i]) + { + return true; + } + } + + if (first.empty()) return false; + + if (first[0] < 'A' || first[0] > 'Z') return false; + + if (first.size() >= 2 && (first[1] < 'a' || first[1] > 'z') && (first[1] != '.') && (first[1] != ',')) return false; + + // Check for invalid names + for (unsigned int i = 0; i < sizeof(invalidNames) / sizeof(char*); ++i) + { + if (first == invalidNames[i]) + { + return false; + } + } + + // Default to a valid name + return true; +} + + +string typoCorrection(const string& name) +{ + // Loop over all known typo corrections + for (unsigned int i = 0; i < sizeof(typoCorrections) / sizeof(TypoCorrection); ++i) + { + // If a typo is found + if (name == typoCorrections[i].original) + { + // Return the correction + return typoCorrections[i].corrected; + } + } + + return name; +} + + +void nameCorrection(NamePair& name) +{ + // Loop over all known name corrections + for (unsigned int i = 0; i < sizeof(nameCorrections) / sizeof(NameCorrection); ++i) + { + // If a matching name is found + if (name.first == nameCorrections[i].originalFirst && + name.second == nameCorrections[i].originalSecond) + { + // Return the correction + name.first = nameCorrections[i].correctedFirst; + name.second = nameCorrections[i].correctedSecond; + + // Early out, since we don't want corrections of corrections + return; + } + } +} + + +void lastValidCharacter(const 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 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 string& first, const string& second) +{ + if (first.empty()) return EmptyNamePair; + +// cout << "first = " << first << " second = " << second << endl; + + unsigned int last = first.size(); + lastValidCharacter(first, last); + + if (last == 0) return EmptyNamePair; + + string name; + + name.append(first.begin(), first.begin() + last); + + if (!validName(name)) return EmptyNamePair; + + name = typoCorrection(name); + + if (second.empty() || + !validName(second)) + { + // filter any single or two letter words as unlike to be names. + if (name.size() <= 2) return EmptyNamePair; + + return NamePair(name, ""); + } + + last = second.size(); + + lastValidCharacter(second, last); + + if (last > 0) + { + string surname(second.begin(), second.begin() + last); + + if (validName(surname)) + { + surname = typoCorrection(surname); + return NamePair(name, surname); + } + } + + // filter any single or two letter words as unlike to be names. + if (name.size() <= 2) return EmptyNamePair; + + 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] == "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] == "Rolled" && 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(NameMap& names, const string& file) +{ + osgDB::ifstream fin(file.c_str()); + + Words words; + while(fin) + { + string keyword; + fin >> keyword; + words.push_back(keyword); + } + + 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[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[name]; + i += 1; + } + } + else + { + if (words[i] == "robert") + { + ++names[NameRobertOsfield]; + } + else if (words[i] == "don") + { + ++names[NameDonBurns]; + } + } + } + + // reassign fisrt name entries to their full names entries + if (names.size() > 1) + { + for (NameMap::iterator itr = names.begin(); itr != names.end(); ) + { + if (itr->first.second.empty()) + { + NameMap::iterator next_itr = itr; + ++next_itr; + + if (next_itr != names.end() && itr->first.first == next_itr->first.first) + { + next_itr->second += itr->second; + names.erase(itr); + itr = next_itr; + } + else + { + ++itr; + } + } + else + { + ++itr; + } + } + } + + // remove the double entries from Robert's contributions + if (names.size() > 1) + { + for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr) + { + if (itr->first != NameRobertOsfield && itr->first != NameDonBurns) + { + names[NameRobertOsfield] -= itr->second; + } + } + } +} + + +void buildContributors(NameMap& names) +{ + // top five contributors + ++names[NamePair("Robert", "Osfield")]; + ++names[NamePair("Don", "Burns")]; + ++names[NamePair("Marco", "Jez")]; + ++names[NamePair("Mike", "Weiblen")]; + ++names[NamePair("Geoff", "Michel")]; + ++names[NamePair("Ben", "van Basten")]; + + // contributors that don't appear in the ChangeLog due to their contributions + // being before CVS started for the OSG, or before the name logging began. + ++names[NamePair("Karsten", "Weiss")]; + ++names[NamePair("Graeme", "Harkness")]; + ++names[NamePair("Axel", "Volley")]; + ++names[NamePair("Nikolaus", "Hanekamp")]; + ++names[NamePair("Kristopher", "Bixler")]; + ++names[NamePair("Tanguy", "Fautré")]; + ++names[NamePair("J.E.", "Hoffmann")]; +} + + +void printContributors(const std::string& changeLog, bool printNumEntries) +{ + NameMap names; + buildContributors(names); + if (!changeLog.empty()) + { + readContributors(names, changeLog); + } + + typedef multimap SortedNameMap; + + SortedNameMap sortedNames; + for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr) + { + sortedNames.insert(SortedNameMap::value_type(itr->second, itr->first)); + } + + cout << names.size() << " Contributors:" << endl << endl; + + if (printNumEntries) + { + cout << "Entries Firstname Surname" << endl; + cout << "-------------------------" << endl; + for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr) + { + cout << sitr->first << "\t" << sitr->second.first << " " << sitr->second.second << endl; + } + } + else + { + cout << "Firstname Surname" << endl; + cout << "-----------------" << endl; + for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr) + { + cout << sitr->second.first << " " << sitr->second.second << endl; + } + } +} diff --git a/applications/osgversion/osgversion.cpp b/applications/osgversion/osgversion.cpp index 95e7c0779..a10c201cd 100644 --- a/applications/osgversion/osgversion.cpp +++ b/applications/osgversion/osgversion.cpp @@ -18,790 +18,17 @@ #include #include -#include - -using namespace std; - - -#if defined(_MSC_VER) - #pragma setlocale("C") +#ifdef BUILD_CONTRIBUTORS +extern void printContributors(const std::string& changeLog, bool printNumEntries); #endif -typedef pair NamePair; -typedef map NameMap; -typedef vector Words; - -NamePair EmptyNamePair; -NamePair NameRobertOsfield("Robert", "Osfield"); -NamePair NameDonBurns ("Don", "Burns"); - - -const char* validNames[] = -{ - "de", - "den", - "van" -}; - -const char* invalidNames[] = -{ - "Added", - "AnimationPath", - "AnimationPathCallback", - "AnimationPathManipulator", - "ArgumentParser", - "AttrData", - "AutoTransform", - "AutoTransform.", - "Azimuth", - "BlenColour(Vec4", - "Camera", - "CameraBarrierCallback", - "CameraNode", - "Canvas", - "CluserCullingCallback", - "ClusterCullingCallback", - "CoordinateSystem", - "CoordinateSystemNode", - "CoordinateSystemNode&", - "CopyOp", - "Copyright", - "Core", - "Creator", - "CullCallbacks", - "CullingSettngs", - "CullVisitor", - "CullVistor", - "Cygwin", - "DatabasePager", - "DataSet", - "DataVariance", - "DeleteHandler", - "DisplaySettings", - "Drawable", - "DrawElementsUByte", - "Endian", - "Escape", - "EventQueue", - "Face", - "Files", - "Fixed", - "Fixes", - "FluidProgram", - "FontImplementation", - "FrameStats", - "Framstamp", - "FreeBSD", - "Geode", - "GeoemtryTechnique", - "GeometryTechnique", - "GeoSet", - "GraphicsContext", - "GraphicsContextImplementation", - "GraphicsThread", - "GraphicsWindowX11", - "Group", - "Image", - "ImageOptions", - "Images", - "Images/SolarSystem", - "ImageStream", - "Improved", - "IndexBlock", - "IndexFaceSets", - "IntersectVisitor", - "Inventor", - "KdTree", - "KeyboardMouse", - "KeyboardMouseCallback", - "LightModel", - "LightPointNode", - "LineSegment", - "LineStipple", - "Logos", - "LongIDRecord", - "Make", - "Makefile", - "Material", - "Matrix", - "Matrix*", - "MatrixManipulator", - "MatrixTransform", - "MemoryManager", - "MergeGeometryVisitor", - "MeshRecord", - "Mode", - "Mr", - "Multigen", - "New", - "NewCullVisitor", - "NodeVisitor", - "Object", - "OpenDX", - "OpenSceneGraph", - "OpenSceneGraph-2", - "OpenSceneGraph-osgWidget-dev", - "OpenThreads", - "OperationThread", - "Optimizer", - "OrientationConverter", - "Osfields", - "Ouput", - "Output", - "OveralyNode", - "PagedLOD", - "PageLOD", - "Paging", - "ParentList", - "Performer", - "PickHandler", - "PixelDataBufferObject", - "PolygonStipple", - "PolytopeVisitor", - "PrimitiveIndexFunctor", - "Prodcuer", - "Producer", - "ProducerEventCallback", - "Program", - "Proxy", - "ProxyNode", - "Quake3", - "Quicktime", - "ReaderWriters", - "ReentrantMutex", - "Referenced", - "ReferenceFrame", - "Removed", - "RemoveLoadedProxyNodes", - "RenderStage", - "RenderTargetFallback", - "RenderToTextureStage", - "SceneGraphBuilder", - "SceneView", - "Sequence", - "Shape", - "SimpleViewer", - "SimpleViewer", - "SmokeTrailEffect", - "Source", - "SpotExponent", - "State", - "StateAttribute", - "Stats", - "StatsVisitor", - "Studio", - "Support", - "Switch", - "TechniqueEventHandler", - "TerraPage", - "TessellationHints", - "TestManipulator", - "TestSupportCallback", - "TexEnv", - "TexMat(Matrix", - "Texture", - "Texture2DArray", - "Texture3D", - "TextureCubeMap", - "TextureObjectManager", - "TextureRectangle", - "TextureRectangle(Image*", - "TextureType", - "Texuture", - "TriStripVisitor", - "TrPageViewer", - "Uniform", - "UseFarLineSegments", - "UserData", - "Valve", - "Vec*", - "Vec2d", - "Vec3d", - "Vec4ub", - "Version", - "VertexData", - "View", - "Viewer", - "ViewPoint", - "Viewport", - "Viewport", - "Visual", - "VisualStudio", - "WindowData", - "Windows", - "X", - "Xcode", - "Y" -}; - - -struct TypoCorrection -{ - const char* original; - const char* corrected; -}; - -TypoCorrection typoCorrections[] = -{ - {"Aderian", "Adrian"}, - {"Adndre", "Andre"}, - {"Adrain", "Adrian"}, - {"Amueller", "Aumueller"}, - {"Andew", "Andrew"}, - {"André", "André"}, - {"Antione", "Antoine"}, - {"Antonoine", "Antoine"}, - {"Atr", "Art"}, - {"Baverage", "Beverage"}, - {"Bistroviae", "Bistrovic"}, - {"Callue", "Callu"}, - {"Christaiansen", "Christiansen"}, - {"Cobin", "Corbin"}, - {"Comporesi", "Camporesi"}, - {"Connel", "Connell"}, - {"Cullu", "Callu"}, - {"Daneil", "Daniel"}, - {"Daust", "Daoust"}, - {"Daved", "David"}, - {"Drederic", "Frederic"}, - {"Eileman", "Eilemann"}, - {"Elgi", "Egli"}, - {"Fabian", "Fabien"}, - {"Fautre", "Fautré"}, - {"Frashid", "Farshid"}, - {"Fred", "Frederic"}, - {"Fredrick", "Frederic"}, - {"Fredric", "Frederic"}, - {"Froechlich", "Fröhlich"}, - {"Froehilch", "Fröhlich"}, - {"Froehlich", "Fröhlich"}, - {"Froelich", "Fröhlich"}, - {"Froenlich", "Fröhlich"}, - {"Fröhlich", "Fröhlich"}, - {"Fruciel", "Frauciel"}, - {"García", "Garcea"}, - {"Garrat", "Garrett"}, - {"Garret", "Garrett"}, - {"Geof", "Geoff"}, - {"Giatan", "Gaitan"}, - {"Gronenger", "Gronager"}, - {"Gronger", "Gronager"}, - {"Haritchablaet", "Haritchabalet"}, - {"Hebelin", "Herbelin"}, - {"Heirtlein", "Hertlein"}, - {"Heirtlein", "Hertlein"}, - {"Hertleinm", "Hertlein"}, - {"Hertlien", "Hertlein"}, - {"Hi", "He"}, - {"Hooper", "Hopper"}, - {"Inverson", "Iverson"}, - {"Iversion", "Iverson"}, - {"Jean-Sebastein", "Jean-Sebastien"}, - {"Jean-Sebastian", "Jean-Sebastien"}, - {"Jean-Sebastirn", "Jean-Sebastien"}, - {"Jea-Sebastien", "Jean-Sebastien"}, - {"Johhansen", "Johansen"}, - {"Johnansen", "Johansen"}, - {"Johnasen", "Johansen"}, - {"Jolly", "Jolley"}, - {"Jose", "José"}, - {"José", "José"}, - {"Joson", "Jason"}, - {"J", "José"}, - {"Keuhne", "Kuehne"}, - {"Kheune", "Kuehne"}, - {"Lagrade", "Lagarde"}, - {"Larshkari", "Lashkari"}, - {"Lashakari", "Lashkari"}, - {"Lashari", "Lashkari"}, - {"Lasharki", "Lashkari"}, - {"Laskari", "Lashkari"}, - {"Leandowski", "Lewandowski"}, - {"Lawandowski", "Lewandowski"}, - {"Lucas", "Luaces"}, - {"Lugi", "Luigi"}, - {"Lweandowski", "Lewandowski"}, - {"Maceij", "Maciej"}, - {"Machler", "Mächler"}, - {"Macro", "Marco"}, - {"Maechler", "Mächler"}, - {"Mahai", "Mihai"}, - {"Mammond", "Marmond"}, - {"March", "Marco"}, - {"Martsz", "Martz"}, - {"Marz", "Martz"}, - {"Matz", "Martz"}, - {"Melchoir", "Melchior"}, - {"Mellis", "Melis"}, - {"Messerschimdt", "Messerschmidt"}, - {"Micheal", "Michael"}, - {"Mihair", "Mihai"}, - {"Molishtan", "Moloshtan"}, - {"Molishtan", "Moloshtan"}, - {"Moloshton", "Moloshtan"}, - {"Morné", "Morné"}, - {"Morne", "Morné"}, - {"Moule", "Moiule"}, - {"Narache", "Marache"}, - {"Nicklov", "Nikolov"}, - {"Nickolov", "Nikolov"}, - {"Olad", "Olaf"}, - {"Olar", "Olaf"}, - {"Oritz", "Ortiz"}, - {"Osfeld", "Osfield"}, - {"Osfied", "Osfield"}, - {"Pail", "Paul"}, - {"Rajce", "Trajce"}, - {"Randal", "Randall"}, - {"Robet", "Robert"}, - {"Rodger", "Roger"}, - {"Rolad", "Roland"}, - {"Rucard", "Richard"}, - {"Sekender", "Sukender"}, - {"Sewel", "Sewell"}, - {"Simmonson", "Simonsson"}, - {"Simmonsson", "Simonsson"}, - {"Sjolie", "Sjölie"}, - {"Sjölie", "Sjölie"}, - {"Skinnder", "Skinner"}, - {"Sokolosky", "Sokolowsky"}, - {"Sokolowky", "Sokolowsky"}, - {"Sokolowki", "Sokolowsky"}, - {"Sokolowski", "Sokolowsky"}, - {"Sokolsky", "Sokolowsky"}, - {"Sokolwsky", "Sokolowsky"}, - {"Sonda", "Sondra"}, - {"Stansilav", "Stanislav"}, - {"Stefan", "Stephan"}, - {"Stell", "Steel"}, - {"Sylvan", "Sylvain"}, - {"Takeahei", "Takahei"}, - {"Takehei", "Takahei"}, - {"Tarantilils", "Tarantilis"}, - {"Trastenjak", "Trstenjak"}, - {"Urlich", "Ulrich"}, - {"Vines", "Vine"}, - {"Waldrom", "Waldron"}, - {"Wedner", "Weidner"}, - {"Weidemann", "Wiedemann"}, - {"Wieblen", "Weiblen"}, - {"Woesnner", "Woessner"}, - {"Wojchiech", "Wojciech"}, - {"Wojiech", "Wojciech"}, - {"Xennon", "Hanson"}, - {"Yefrei", "Yefei"}, - {"Yfei", "Yefei"} -}; - - -struct NameCorrection -{ - const char* originalFirst; - const char* originalSecond; - const char* correctedFirst; - const char* correctedSecond; -}; - -NameCorrection nameCorrections[] = -{ - {"Marc", "Sciabica", - "Mark", "Sciabica"}, - {"Jean", "Sebastien", - "Jean-Sebastien", "Guay"}, - {"Michale", "Platings", - "Michael", "Platings"}, - {"Mick", "", - "Maik", "Keller"}, - {"Gary", "Quin", - "Gary", "Quinn"}, - {"BjornHein", "", - "Björn", "Hein"}, - {"Bjorn", "Hein", - "Björn", "Hein"}, - {"Erik", "van", - "Erik", "den Dekker"}, - {"Erik", "den", - "Erik", "den Dekker"}, - {"Jeoen", "den", - "Jeroen", "den Dekker"}, - {"John", "Vidar", - "John", "Vidar Larring"}, - {"John", "Vida", - "John", "Vidar Larring"}, - {"Sebastien", "Messerschmidt", - "Sebastian", "Messerschmidt"}, - {"Mattias", "Fröhlich", - "Mathias", "Fröhlich"}, - {"Mathias", "Helsing", - "Mattias", "Helsing"}, - {"Jose", "Delport", - "J.P.", "Delport"}, - {"José", "Delport", - "J.P.", "Delport"}, - {"Franz", "Melchior", - "Melchior", "Franz"}, - {"Glen", "Waldon", - "Glenn", "Waldron"}, - {"Ralf", "Karn", - "Ralf", "Kern"}, - {"Donny", "Cipperly", - "Donald", "Cipperly"}, - {"Gino", "van", - "Gino", "van den Bergen"}, - {"Radu", "Mihai", - "Mihai", "Radu"}, - {"Art", "Trevs", - "Art", "Tevs"}, - {"Tim", "More", - "Tim", "Moore"}, - {"Andre", "Garneau", - "André", "Garneau"}, - {"Eric", "Hammil", - "Chris", "Hanson"}, - {"Paul", "de", - "Paul", "de Repentigny"}, - {"Raymond", "de", - "Raymond", "de Vries"}, - {"Nick", "", - "Trajce", "Nikolov"}, - {"Daniel", "", - "Daniel", "Sjölie"}, - {"Julia", "Ortiz", - "Julian", "Ortiz"}, - {"Rune", "Schmidt", - "Rune", "Schmidt Jensen"}, - {"Romano", "José", - "Romano", "José Magacho da Silva"}, - {"Rommano", "Silva", - "Romano", "José Magacho da Silva"}, - {"Leandro", "Motta", - "Leandro", "Motta Barros"}, - {"A", "Botorabi", - "Ali", "Botorabi"}, - {"Waltice", "", - "Walter", "J. Altice"}, - {"Drew", "", - "Drew", "Whitehouse"}, - {"Douglas", "A", - "Douglas", "A. Pouk"}, - {"Colin", "MacDonald", - "Colin", "McDonald"}, - {"Nikolov", "Trajce", - "Trajce", "Nikolov"}, - {"Frauciel", "Luc", - "Luc", "Frauciel"}, -}; - - -bool validName(const string& first) -{ - // Check for valid names - for (unsigned int i = 0; i < sizeof(validNames) / sizeof(char*); ++i) - { - if (first == validNames[i]) - { - return true; - } - } - - if (first.empty()) return false; - - if (first[0] < 'A' || first[0] > 'Z') return false; - - if (first.size() >= 2 && (first[1] < 'a' || first[1] > 'z') && (first[1] != '.') && (first[1] != ',')) return false; - - // Check for invalid names - for (unsigned int i = 0; i < sizeof(invalidNames) / sizeof(char*); ++i) - { - if (first == invalidNames[i]) - { - return false; - } - } - - // Default to a valid name - return true; -} - - -string typoCorrection(const string& name) -{ - // Loop over all known typo corrections - for (unsigned int i = 0; i < sizeof(typoCorrections) / sizeof(TypoCorrection); ++i) - { - // If a typo is found - if (name == typoCorrections[i].original) - { - // Return the correction - return typoCorrections[i].corrected; - } - } - - return name; -} - - -void nameCorrection(NamePair& name) -{ - // Loop over all known name corrections - for (unsigned int i = 0; i < sizeof(nameCorrections) / sizeof(NameCorrection); ++i) - { - // If a matching name is found - if (name.first == nameCorrections[i].originalFirst && - name.second == nameCorrections[i].originalSecond) - { - // Return the correction - name.first = nameCorrections[i].correctedFirst; - name.second = nameCorrections[i].correctedSecond; - - // Early out, since we don't want corrections of corrections - return; - } - } -} - - -void lastValidCharacter(const 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 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 string& first, const string& second) -{ - if (first.empty()) return EmptyNamePair; - -// cout << "first = " << first << " second = " << second << endl; - - unsigned int last = first.size(); - lastValidCharacter(first, last); - - if (last == 0) return EmptyNamePair; - - string name; - - name.append(first.begin(), first.begin() + last); - - if (!validName(name)) return EmptyNamePair; - - name = typoCorrection(name); - - if (second.empty() || - !validName(second)) - { - // filter any single or two letter words as unlike to be names. - if (name.size() <= 2) return EmptyNamePair; - - return NamePair(name, ""); - } - - last = second.size(); - - lastValidCharacter(second, last); - - if (last > 0) - { - string surname(second.begin(), second.begin() + last); - - if (validName(surname)) - { - surname = typoCorrection(surname); - return NamePair(name, surname); - } - } - - // filter any single or two letter words as unlike to be names. - if (name.size() <= 2) return EmptyNamePair; - - 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] == "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] == "Rolled" && 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(NameMap& names, const string& file) -{ - osgDB::ifstream fin(file.c_str()); - - Words words; - while(fin) - { - string keyword; - fin >> keyword; - words.push_back(keyword); - } - - 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[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[name]; - i += 1; - } - } - else - { - if (words[i] == "robert") - { - ++names[NameRobertOsfield]; - } - else if (words[i] == "don") - { - ++names[NameDonBurns]; - } - } - } - - // reassign fisrt name entries to their full names entries - if (names.size() > 1) - { - for (NameMap::iterator itr = names.begin(); itr != names.end(); ) - { - if (itr->first.second.empty()) - { - NameMap::iterator next_itr = itr; - ++next_itr; - - if (next_itr != names.end() && itr->first.first == next_itr->first.first) - { - next_itr->second += itr->second; - names.erase(itr); - itr = next_itr; - } - else - { - ++itr; - } - } - else - { - ++itr; - } - } - } - - // remove the double entries from Robert's contributions - if (names.size() > 1) - { - for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr) - { - if (itr->first != NameRobertOsfield && itr->first != NameDonBurns) - { - names[NameRobertOsfield] -= itr->second; - } - } - } -} - - -void buildContributors(NameMap& names) -{ - // top five contributors - ++names[NamePair("Robert", "Osfield")]; - ++names[NamePair("Don", "Burns")]; - ++names[NamePair("Marco", "Jez")]; - ++names[NamePair("Mike", "Weiblen")]; - ++names[NamePair("Geoff", "Michel")]; - ++names[NamePair("Ben", "van Basten")]; - - // contributors that don't appear in the ChangeLog due to their contributions - // being before CVS started for the OSG, or before the name logging began. - ++names[NamePair("Karsten", "Weiss")]; - ++names[NamePair("Graeme", "Harkness")]; - ++names[NamePair("Axel", "Volley")]; - ++names[NamePair("Nikolaus", "Hanekamp")]; - ++names[NamePair("Kristopher", "Bixler")]; - ++names[NamePair("Tanguy", "Fautré")]; - ++names[NamePair("J.E.", "Hoffmann")]; -} - +using namespace std; 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("--entries", "Print out number of entries into the ChangeLog file for each contributor."); arguments.getApplicationUsage()->addCommandLineOption("--version-number", "Print out version number only"); arguments.getApplicationUsage()->addCommandLineOption("--major-number", "Print out major version number only"); arguments.getApplicationUsage()->addCommandLineOption("--minor-number", "Print out minor version number only"); @@ -813,7 +40,19 @@ int main( int argc, char** argv) arguments.getApplicationUsage()->addCommandLineOption("Plane::value_type", "Print the value of Plane::value_type"); arguments.getApplicationUsage()->addCommandLineOption("BoundingSphere::value_type", "Print the value of BoundingSphere::value_type"); arguments.getApplicationUsage()->addCommandLineOption("BoundingBox::value_type", "Print the value of BoundingBox::value_type"); + +#ifdef BUILD_CONTRIBUTORS arguments.getApplicationUsage()->addCommandLineOption("-r or --read ", "Read the ChangeLog to generate an estimated contributors list."); + arguments.getApplicationUsage()->addCommandLineOption("--entries", "Print out number of entries into the ChangeLog file for each contributor."); +#endif + + // if user request help write it out to cout. + if (arguments.read("-h") || arguments.read("--help")) + { + cout << arguments.getApplicationUsage()->getCommandLineUsage() << endl; + arguments.getApplicationUsage()->write(cout, arguments.getApplicationUsage()->getCommandLineOptions()); + return 1; + } if (arguments.read("--version-number")) { @@ -902,64 +141,14 @@ int main( int argc, char** argv) cout << osgGetLibraryName() << " " << osgGetVersion() << endl << endl; - bool printContributors = false; - bool printNumEntries = false; - while (arguments.read("--entries")) - { - printContributors = true; - printNumEntries = true; - } - +#ifdef BUILD_CONTRIBUTORS 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")) + arguments.read("--read", changeLog)) { - cout << arguments.getApplicationUsage()->getCommandLineUsage() << endl; - arguments.getApplicationUsage()->write(cout, arguments.getApplicationUsage()->getCommandLineOptions()); - return 1; - } - - if (printContributors) - { - NameMap names; - buildContributors(names); - if (!changeLog.empty()) - { - readContributors(names, changeLog); - } - - typedef multimap SortedNameMap; - - SortedNameMap sortedNames; - for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr) - { - sortedNames.insert(SortedNameMap::value_type(itr->second, itr->first)); - } - - cout << names.size() << " Contributors:" << endl << endl; - - if (printNumEntries) - { - cout << "Entries Firstname Surname" << endl; - cout << "-------------------------" << endl; - for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr) - { - cout << sitr->first << "\t" << sitr->second.first << " " << sitr->second.second << endl; - } - } - else - { - cout << "Firstname Surname" << endl; - cout << "-----------------" << endl; - for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr) - { - cout << sitr->second.first << " " << sitr->second.second << endl; - } - } + printContributors(changeLog, arguments.read("--entries")); } +#endif return 0; }