root/OpenSceneGraph/trunk/applications/osgversion/Contributors.cpp @ 10477

Revision 10477, 21.6 kB (checked in by robert, 5 years ago)

Updated Contributors mapping

Line 
1// The majority of the application is dedicated to building the
2// current contribitors list by parsing the ChangeLog, it just takes
3// one line in the main itself to report the version number.
4
5#include <set>
6#include <vector>
7#include <iostream>
8
9#include <OpenThreads/Version>
10
11#include <osg/Notify>
12#include <osg/Version>
13#include <osg/ArgumentParser>
14#include <osg/ApplicationUsage>
15
16#include <osg/Matrix>
17#include <osg/Plane>
18#include <osg/BoundingBox>
19#include <osg/BoundingSphere>
20
21#include <osgDB/fstream>
22
23using namespace std;
24
25
26#if defined(_MSC_VER)
27    #pragma setlocale("C")
28#endif
29
30typedef pair<string, string>        NamePair;
31typedef map<NamePair, unsigned int> NameMap;
32typedef vector<string>              Words;
33
34NamePair EmptyNamePair;
35NamePair NameRobertOsfield("Robert", "Osfield");
36NamePair NameDonBurns     ("Don",    "Burns");
37
38
39const char* validNames[] =
40{
41    "de",
42    "den",
43    "van"
44};
45
46const char* invalidNames[] =
47{
48    "Added",
49    "AnimationPath",
50    "AnimationPathCallback",
51    "AnimationPathManipulator",
52    "ArgumentParser",
53    "AttrData",
54    "AutoTransform",
55    "AutoTransform.",
56    "Azimuth",
57    "BlenColour(Vec4",
58    "Camera",
59    "CameraBarrierCallback",
60    "CameraNode",
61    "Canvas",
62    "CluserCullingCallback",
63    "ClusterCullingCallback",
64    "CoordinateSystem",
65    "CoordinateSystemNode",
66    "CoordinateSystemNode&",
67    "CopyOp",
68    "Copyright",
69    "Core",
70    "Creator",
71    "CullCallbacks",
72    "CullingSettngs",
73    "CullVisitor",
74    "CullVistor",
75    "Cygwin",
76    "DatabasePager",
77    "DataSet",
78    "DataVariance",
79    "DeleteHandler",
80    "DisplaySettings",
81    "Drawable",
82    "DrawElementsUByte",
83    "Endian",
84    "Escape",
85    "EventQueue",
86    "Face",
87    "Files",
88    "Fixed",
89    "Fixes",
90    "FluidProgram",
91    "FontImplementation",
92    "FrameStats",
93    "Framstamp",
94    "FreeBSD",
95    "Geode",
96    "GeoemtryTechnique",
97    "GeometryTechnique",
98    "GeoSet",
99    "GraphicsContext",
100    "GraphicsContextImplementation",
101    "GraphicsThread",
102    "GraphicsWindowX11",
103    "Group",
104    "Image",
105    "ImageOptions",
106    "Images",
107    "Images/SolarSystem",
108    "ImageStream",
109    "Improved",
110    "IndexBlock",
111    "IndexFaceSets",
112    "IntersectVisitor",
113    "Inventor",
114    "KdTree",
115    "KeyboardMouse",
116    "KeyboardMouseCallback",
117    "LightModel",
118    "LightPointNode",
119    "LineSegment",
120    "LineStipple",
121    "Logos",
122    "LongIDRecord",
123    "Make",
124    "Makefile",
125    "Material",
126    "Matrix",
127    "Matrix*",
128    "MatrixManipulator",
129    "MatrixTransform",
130    "MemoryManager",
131    "MergeGeometryVisitor",
132    "MeshRecord",
133    "Mode",
134    "Mr",
135    "Multigen",
136    "New",
137    "NewCullVisitor",
138    "NodeVisitor",
139    "Object",
140    "OpenDX",
141    "OpenSceneGraph",
142    "OpenSceneGraph-2",
143    "OpenSceneGraph-osgWidget-dev",
144    "OpenThreads",
145    "OperationThread",
146    "Optimizer",
147    "OrientationConverter",
148    "Osfields",
149    "Ouput",
150    "Output",
151    "OveralyNode",
152    "PagedLOD",
153    "PageLOD",
154    "Paging",
155    "ParentList",
156    "Performer",
157    "PickHandler",
158    "PixelDataBufferObject",
159    "PolygonStipple",
160    "PolytopeVisitor",
161    "PrimitiveIndexFunctor",
162    "Prodcuer",
163    "Producer",
164    "ProducerEventCallback",
165    "Program",
166    "Proxy",
167    "ProxyNode",
168    "Quake3",
169    "Quicktime",
170    "ReaderWriters",
171    "ReentrantMutex",
172    "Referenced",
173    "ReferenceFrame",
174    "Removed",
175    "RemoveLoadedProxyNodes",
176    "RenderStage",
177    "RenderTargetFallback",
178    "RenderToTextureStage",
179    "SceneGraphBuilder",
180    "SceneView",
181    "Sequence",
182    "Shape",
183    "SimpleViewer",
184    "SimpleViewer",
185    "SmokeTrailEffect",
186    "Source",
187    "SpotExponent",
188    "State",
189    "StateAttribute",
190    "Stats",
191    "StatsVisitor",
192    "Studio",
193    "Support",
194    "Switch",
195    "TechniqueEventHandler",
196    "TerraPage",
197    "TessellationHints",
198    "TestManipulator",
199    "TestSupportCallback",
200    "TexEnv",
201    "TexMat(Matrix",
202    "Texture",
203    "Texture2DArray",
204    "Texture3D",
205    "TextureCubeMap",
206    "TextureObjectManager",
207    "TextureRectangle",
208    "TextureRectangle(Image*",
209    "TextureType",
210    "Texuture",
211    "TriStripVisitor",
212    "TrPageViewer",
213    "Uniform",
214    "UseFarLineSegments",
215    "UserData",
216    "Valve",
217    "Vec*",
218    "Vec2d",
219    "Vec3d",
220    "Vec4ub",
221    "Version",
222    "VertexData",
223    "View",
224    "Viewer",
225    "ViewPoint",
226    "Viewport",
227    "Viewport",
228    "Visual",
229    "VisualStudio",
230    "WindowData",
231    "Windows",
232    "X",
233    "Xcode",
234    "GraphicsWindowWin32",
235    "ImageLayer",
236    "Xml",
237    "Y"
238};
239
240
241struct TypoCorrection
242{
243    const char* original;
244    const char* corrected;
245};
246
247TypoCorrection typoCorrections[] =
248{
249    {"Aderian",        "Adrian"},
250    {"Adndre",         "Andre"},
251    {"Adrain",         "Adrian"},
252    {"Amueller",       "Aumueller"},
253    {"Andew",          "Andrew"},
254    {"André",         "André"},
255    {"Antione",        "Antoine"},
256    {"Antonoine",      "Antoine"},
257    {"Atr",            "Art"},
258    {"Baverage",       "Beverage"},
259    {"Bistroviae",     "Bistrovic"},
260    {"Callue",         "Callu"},
261    {"Christaiansen""Christiansen"},
262    {"Cobin",          "Corbin"},
263    {"Comporesi",      "Camporesi"},
264    {"Connel",         "Connell"},
265    {"Cullu",          "Callu"},
266    {"Daneil",         "Daniel"},
267    {"Daust",          "Daoust"},
268    {"Daved",          "David"},
269    {"Drederic",       "Frederic"},
270    {"Eileman",        "Eilemann"},
271    {"Elgi",           "Egli"},
272    {"Fabian",         "Fabien"},
273    {"Fautre",         "Fautré"},
274    {"Frashid",        "Farshid"},
275    {"Fred",           "Frederic"},
276    {"Fredrick",       "Frederic"},
277    {"Fredric",        "Frederic"},
278    {"Froechlich",     "Fröhlich"},
279    {"Froehilch",      "Fröhlich"},
280    {"Froehlich",      "Fröhlich"},
281    {"Froelich",       "Fröhlich"},
282    {"Froenlich",      "Fröhlich"},
283    {"Fröhlich",      "Fröhlich"},
284    {"Fruciel",        "Frauciel"},
285    {"García",        "Garcea"},
286    {"Garrat",         "Garrett"},
287    {"Garret",         "Garrett"},
288    {"Geof",           "Geoff"},
289    {"Giatan",         "Gaitan"},
290    {"Gronenger",      "Gronager"},
291    {"Gronger",        "Gronager"},
292    {"Haritchablaet""Haritchabalet"},
293    {"Hebelin",        "Herbelin"},
294    {"Heirtlein",      "Hertlein"},
295    {"Heirtlein",      "Hertlein"},
296    {"Hertleinm",      "Hertlein"},
297    {"Happalahti",     "Haapalahti"},
298    {"Hertlien",       "Hertlein"},
299    {"Hi",             "He"},
300    {"Hooper",         "Hopper"},
301    {"Inverson",       "Iverson"},
302    {"Iversion",       "Iverson"},
303    {"Jean-Sebastein", "Jean-Sebastien"},
304    {"Jean-Sebastian", "Jean-Sebastien"},
305    {"Jean-Sebastirn", "Jean-Sebastien"},
306    {"Jea-Sebastien""Jean-Sebastien"},
307    {"Johhansen",      "Johansen"},
308    {"Johnansen",      "Johansen"},
309    {"Johnasen",       "Johansen"},
310    {"Jolly",          "Jolley"},
311    {"Jose",           "José"},
312    {"José",          "José"},
313    {"Joson",          "Jason"},
314    {"J",              "José"},
315    {"Keuhne",         "Kuehne"},
316    {"Kheune",         "Kuehne"},
317    {"Lagrade",        "Lagarde"},
318    {"Largade",        "Lagarde"},
319    {"Larshkari",      "Lashkari"},
320    {"Lashakari",      "Lashkari"},
321    {"Lashari",        "Lashkari"},
322    {"Lasharki",       "Lashkari"},
323    {"Laskari",        "Lashkari"},
324    {"Leandowski",     "Lewandowski"},
325    {"Lawandowski",    "Lewandowski"},
326    {"Luacas",         "Luaces"},
327    {"Luacas",         "Luaces"},
328    {"Liech",          "Leich"},
329    {"Lugi",           "Luigi"},
330    {"Lweandowski",    "Lewandowski"},
331    {"Maceij",         "Maciej"},
332    {"Machler",        "Mächler"},
333    {"Macro",          "Marco"},
334    {"Maechler",       "Mächler"},
335    {"Mahai",          "Mihai"},
336    {"Mammond",        "Marmond"},
337    {"March",          "Marco"},
338    {"Martsz",         "Martz"},
339    {"Marz",           "Martz"},
340    {"Matz",           "Martz"},
341    {"Melchoir",       "Melchior"},
342    {"Mellis",         "Melis"},
343    {"Messerschimdt""Messerschmidt"},
344    {"Micheal",        "Michael"},
345    {"Mihair",         "Mihai"},
346    {"Molishtan",      "Moloshtan"},
347    {"Molishtan",      "Moloshtan"},
348    {"Moloshton",      "Moloshtan"},
349    {"Morné",         "Morné"},
350    {"Morne",          "Morné"},
351    {"Moule",          "Moiule"},
352    {"Narache",        "Marache"},
353    {"Nicklov",        "Nikolov"},
354    {"Nickolov",       "Nikolov"},
355    {"Olad",           "Olaf"},
356    {"Olar",           "Olaf"},
357    {"Oritz",          "Ortiz"},
358    {"Osfeld",         "Osfield"},
359    {"Osfied",         "Osfield"},
360    {"Pail",           "Paul"},
361    {"Rajce",          "Trajce"},
362    {"Randal",         "Randall"},
363    {"Robet",          "Robert"},
364    {"Rodger",         "Roger"},
365    {"Rolad",          "Roland"},
366    {"Riddel",         "Riddell"},
367    {"Rucard",         "Richard"},
368    {"Sekender",       "Sukender"},
369    {"Sewel",          "Sewell"},
370    {"Simmonson",      "Simonsson"},
371    {"Simmonsson",     "Simonsson"},
372    {"Sjolie",         "Sjölie"},
373    {"Sjölie",        "Sjölie"},
374    {"Skinnder",       "Skinner"},
375    {"Sokolosky",      "Sokolowsky"},
376    {"Sokolowky",      "Sokolowsky"},
377    {"Sokolowki",      "Sokolowsky"},
378    {"Sokolowski",     "Sokolowsky"},
379    {"Sokolsky",       "Sokolowsky"},
380    {"Sokolwsky",      "Sokolowsky"},
381    {"Sonda",          "Sondra"},
382    {"Stansilav",      "Stanislav"},
383    {"Stefan",         "Stephan"},
384    {"Stell",          "Steel"},
385    {"Sylvan",         "Sylvain"},
386    {"Takeahei",       "Takahei"},
387    {"Takehei",        "Takahei"},
388    {"Tery",           "Terry"},
389    {"Tarantilils",    "Tarantilis"},
390    {"Trastenjak",     "Trstenjak"},
391    {"Urlich",         "Ulrich"},
392    {"Vines",          "Vine"},
393    {"Waldrom",        "Waldron"},
394    {"Wedner",         "Weidner"},
395    {"Weidemann",      "Wiedemann"},
396    {"Wieblen",        "Weiblen"},
397    {"Woesnner",       "Woessner"},
398    {"Wojchiech",      "Wojciech"},
399    {"Wojiech",        "Wojciech"},
400    {"Xennon",         "Hanson"},
401    {"Yefrei",         "Yefei"},
402    {"Yfei",           "Yefei"}
403};
404
405
406struct NameCorrection
407{
408    const char* originalFirst;
409    const char* originalSecond;
410    const char* correctedFirst;
411    const char* correctedSecond;
412};
413
414NameCorrection nameCorrections[] =
415{
416    {"Marc",           "Sciabica",
417     "Mark",           "Sciabica"},
418    {"Jean",           "Sebastien",
419     "Jean-Sebastien", "Guay"},
420    {"Michale",        "Platings",
421     "Michael",        "Platings"},
422    {"Mick",           "",
423     "Maik",           "Keller"},
424    {"Gary",           "Quin",
425     "Gary",           "Quinn"},
426    {"BjornHein",      "",
427     "Björn",          "Hein"},
428    {"Bjorn",          "Hein",
429     "Björn",          "Hein"},
430    {"Erik",           "van",
431     "Erik",           "den Dekker"},
432    {"Erik",           "den",
433     "Erik",           "den Dekker"},
434    {"Jeoen",          "den",
435     "Jeroen",         "den Dekker"},
436    {"John",           "Vidar",
437     "John",           "Vidar Larring"},
438    {"John",           "Vida",
439     "John",           "Vidar Larring"},
440    {"Sebastien",      "Messerschmidt",
441     "Sebastian",      "Messerschmidt"},
442    {"Mattias",        "Fröhlich",
443     "Mathias",        "Fröhlich"},
444    {"Mathias",        "Helsing",
445     "Mattias",        "Helsing"},
446    {"Jose",           "Delport",
447     "J.P.",           "Delport"},
448    {"José",           "Delport",
449     "J.P.",           "Delport"},
450    {"Franz",          "Melchior",
451     "Melchior",       "Franz"},
452    {"Glen",           "Waldon",
453     "Glenn",          "Waldron"},
454    {"Ralf",           "Karn",
455     "Ralf",           "Kern"},
456    {"Donny",          "Cipperly",
457     "Donald",         "Cipperly"},
458    {"Gino",           "van",
459     "Gino",           "van den Bergen"},
460    {"Radu",           "Mihai",
461     "Mihai",          "Radu"},
462    {"Art",            "Trevs",
463     "Art",            "Tevs"},
464    {"Tim",            "More",
465     "Tim",            "Moore"},
466    {"Andre",          "Garneau",
467     "André",          "Garneau"},
468    {"Eric",           "Hammil",
469     "Chris",          "Hanson"},
470    {"Paul",           "de",
471     "Paul",           "de Repentigny"},
472    {"Raymond",        "de",
473     "Raymond",        "de Vries"},
474    {"Nick",           "",
475     "Trajce",         "Nikolov"},
476    {"Daniel",         "",
477     "Daniel",         "Sjölie"},
478    {"Julia",          "Ortiz",
479     "Julian",         "Ortiz"},
480    {"Rune",           "Schmidt",
481     "Rune",           "Schmidt Jensen"},
482    {"Romano",         "José",
483     "Romano",         "José Magacho da Silva"},
484    {"Rommano",        "Silva",
485     "Romano",         "José Magacho da Silva"},
486    {"Leandro",        "Motta",
487     "Leandro",        "Motta Barros"},
488    {"A",              "Botorabi",
489     "Ali",            "Botorabi"},
490    {"Waltice",        "",
491     "Walter",         "J. Altice"},
492    {"Drew",           "",
493     "Drew",           "Whitehouse"},
494    {"Douglas",        "A",
495     "Douglas",        "A. Pouk"},
496    {"Colin",          "MacDonald",
497     "Colin",          "McDonald"},
498    {"Nikolov",        "Trajce",
499     "Trajce",         "Nikolov"},
500    {"Frauciel",       "Luc",
501     "Luc",            "Frauciel"},
502    {"Alberto",        "Lucas",
503     "Alberto",        "Luaces"},
504};
505
506
507bool validName(const string& first)
508{
509    // Check for valid names
510    for (unsigned int i = 0; i < sizeof(validNames) / sizeof(char*); ++i)
511    {
512        if (first == validNames[i])
513        {
514            return true;
515        }
516    }
517
518    if (first.empty()) return false;
519
520    if (first[0] < 'A' || first[0] > 'Z') return false;
521
522    if (first.size() >= 2 && (first[1] < 'a' || first[1] > 'z') && (first[1] != '.') && (first[1] != ',')) return false;
523
524    // Check for invalid names
525    for (unsigned int i = 0; i < sizeof(invalidNames) / sizeof(char*); ++i)
526    {
527        if (first == invalidNames[i])
528        {
529            return false;
530        }
531    }
532
533    // Default to a valid name
534    return true;
535}
536
537
538string typoCorrection(const string& name)
539{
540    // Loop over all known typo corrections
541    for (unsigned int i = 0; i < sizeof(typoCorrections) / sizeof(TypoCorrection); ++i)
542    {
543        // If a typo is found
544        if (name == typoCorrections[i].original)
545        {
546            // Return the correction
547            return typoCorrections[i].corrected;
548        }
549    }
550
551    return name;
552}
553
554
555void nameCorrection(NamePair& name)
556{
557    // Loop over all known name corrections
558    for (unsigned int i = 0; i < sizeof(nameCorrections) / sizeof(NameCorrection); ++i)
559    {
560        // If a matching name is found
561        if (name.first  == nameCorrections[i].originalFirst &&
562            name.second == nameCorrections[i].originalSecond)
563        {
564            // Return the correction
565            name.first  = nameCorrections[i].correctedFirst;
566            name.second = nameCorrections[i].correctedSecond;
567
568            // Early out, since we don't want corrections of corrections
569            return;
570        }
571    }
572}
573
574
575void lastValidCharacter(const string& name, unsigned int& pos, char c)
576{
577    for (unsigned int i = 0; i < pos; ++i)
578    {
579        if (name[i] == c)
580        {
581            pos = i;
582            return;
583        }
584    }
585}
586
587
588void lastValidCharacter(const string& name, unsigned int& last)
589{
590    lastValidCharacter(name, last, '.');
591    lastValidCharacter(name, last, ',');
592    lastValidCharacter(name, last, '\'');
593    lastValidCharacter(name, last, '/');
594    lastValidCharacter(name, last, '\\');
595    lastValidCharacter(name, last, ':');
596    lastValidCharacter(name, last, ';');
597    lastValidCharacter(name, last, ')');
598}
599
600
601NamePair createName(const string& first, const string& second)
602{
603    if (first.empty()) return EmptyNamePair;
604
605//  cout << "first = " << first << " second = " << second << endl;
606
607    unsigned int last = first.size();
608    lastValidCharacter(first, last);
609
610    if (last == 0) return EmptyNamePair;
611
612    string name;
613
614    name.append(first.begin(), first.begin() + last);
615
616    if (!validName(name)) return EmptyNamePair;
617
618    name = typoCorrection(name);
619
620    if (second.empty() ||
621        !validName(second))
622    {
623        // filter any single or two letter words as unlike to be names.
624        if (name.size() <= 2) return EmptyNamePair;
625
626        return NamePair(name, "");
627    }
628
629    last = second.size();
630
631    lastValidCharacter(second, last);
632
633    if (last > 0)
634    {
635        string surname(second.begin(), second.begin() + last);
636
637        if (validName(surname))
638        {
639            surname = typoCorrection(surname);
640            return NamePair(name, surname);
641        }
642    }
643
644    // filter any single or two letter words as unlike to be names.
645    if (name.size() <= 2) return EmptyNamePair;
646
647    return NamePair(name, "");
648}
649
650
651bool submissionsSequence(const Words& words, unsigned int& i)
652{
653    if (i + 1 >= words.size()) return false;
654
655    if (words[i] == "From"   ||
656        words[i] == "from"   ||
657        words[i] == "From:"  ||
658        words[i] == "from:"  ||
659        words[i] == "Merged" ||
660        words[i] == "Integrated") return true;
661
662    if (i + 2 >= words.size()) return false;
663
664    if (words[i] == "submitted" && words[i + 1] == "by")
665    {
666        i += 1;
667        return true;
668    }
669
670    if (words[i] == "Folded" && words[i + 1] == "in")
671    {
672        i += 1;
673        return true;
674    }
675
676    if (words[i] == "Rolled" && words[i + 1] == "in")
677    {
678        i += 1;
679        return true;
680    }
681
682    if (words[i] == "Checked" && words[i + 1] == "in")
683    {
684        i += 1;
685        return true;
686    }
687
688    if (i + 3 >= words.size()) return false;
689
690    if (words[i] == "sent" && words[i + 1] == "in" && words[i + 2] == "by")
691    {
692        i += 2;
693        return true;
694    }
695
696    return false;
697}
698
699
700void readContributors(NameMap& names, const string& file)
701{
702    osgDB::ifstream fin(file.c_str());
703
704    Words words;
705    while(fin)
706    {
707        string keyword;
708        fin >> keyword;
709        words.push_back(keyword);
710    }
711
712    string blank_string;
713
714    for(unsigned int i = 0; i < words.size(); ++i)
715    {
716        if (submissionsSequence(words, i))
717        {
718            if (i + 2 < words.size() && validName(words[i + 1]))
719            {
720                NamePair name = createName(words[i + 1], words[i + 2]);
721                nameCorrection(name);
722                if (!name.first.empty()) ++names[name];
723                i += 2;
724            }
725            else if (i + 1 < words.size() && validName(words[i + 1]))
726            {
727                NamePair name = createName(words[i + 1], blank_string);
728                nameCorrection(name);
729                if (!name.first.empty()) ++names[name];
730                i += 1;
731            }
732        }
733        else
734        {
735            if (words[i] == "robert")
736            {
737                ++names[NameRobertOsfield];
738            }
739            else if (words[i] == "don")
740            {
741                ++names[NameDonBurns];
742            }
743        }
744    }
745
746    // reassign fisrt name entries to their full names entries
747    if (names.size() > 1)
748    {
749        for (NameMap::iterator itr = names.begin(); itr != names.end(); )
750        {
751            if (itr->first.second.empty())
752            {
753                NameMap::iterator next_itr = itr;
754                ++next_itr;
755
756                if (next_itr != names.end() && itr->first.first == next_itr->first.first)
757                {
758                    next_itr->second += itr->second;
759                    names.erase(itr);
760                    itr = next_itr;
761                }
762                else
763                {
764                    ++itr;
765                }
766            }
767            else
768            {
769                ++itr;
770            }
771        }
772    }
773
774    // remove the double entries from Robert's contributions
775    if (names.size() > 1)
776    {
777        for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr)
778        {
779            if (itr->first != NameRobertOsfield && itr->first != NameDonBurns)
780            {
781                names[NameRobertOsfield] -= itr->second;
782            }
783        }
784    }
785}
786
787
788void buildContributors(NameMap& names)
789{
790    // top five contributors
791    ++names[NamePair("Robert",     "Osfield")];
792    ++names[NamePair("Don",        "Burns")];
793    ++names[NamePair("Marco",      "Jez")];
794    ++names[NamePair("Mike",       "Weiblen")];
795    ++names[NamePair("Geoff",      "Michel")];
796    ++names[NamePair("Ben",        "van Basten")];
797
798    // contributors that don't appear in the ChangeLog due to their contributions
799    // being before CVS started for the OSG, or before the name logging began.
800    ++names[NamePair("Karsten",    "Weiss")];
801    ++names[NamePair("Graeme",     "Harkness")];
802    ++names[NamePair("Axel",       "Volley")];
803    ++names[NamePair("Nikolaus",   "Hanekamp")];
804    ++names[NamePair("Kristopher", "Bixler")];
805    ++names[NamePair("Tanguy",     "Fautré")];
806    ++names[NamePair("J.E.",       "Hoffmann")];
807}
808
809
810void printContributors(const std::string& changeLog, bool printNumEntries)
811{
812    NameMap names;
813    buildContributors(names);
814    if (!changeLog.empty())
815    {
816        readContributors(names, changeLog);
817    }
818
819    typedef multimap<unsigned int, NamePair> SortedNameMap;
820
821    SortedNameMap sortedNames;
822    for (NameMap::iterator itr = names.begin(); itr != names.end(); ++itr)
823    {
824        sortedNames.insert(SortedNameMap::value_type(itr->second, itr->first));
825    }
826
827    cout << names.size() << " Contributors:" << endl << endl;
828
829    if (printNumEntries)
830    {
831        cout << "Entries Firstname Surname" << endl;
832        cout << "-------------------------" << endl;
833        for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr)
834        {
835            cout << sitr->first << "\t" << sitr->second.first << " " << sitr->second.second << endl;
836        }
837    }
838    else
839    {
840        cout << "Firstname Surname" << endl;
841        cout << "-----------------" << endl;
842        for (SortedNameMap::reverse_iterator sitr = sortedNames.rbegin(); sitr != sortedNames.rend(); ++sitr)
843        {
844            cout << sitr->second.first << " " << sitr->second.second << endl;
845        }
846    }
847}
Note: See TracBrowser for help on using the browser.