source: trunk/lib/Stats.cc @ 80

Last change on this file since 80 was 80, checked in by Jari Häkkinen, 16 years ago

Removed nasty bug: svnstat crashed when the last checkin contained zero statistics
count items only, eg. empty directories or binary files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 3.9 KB
Line 
1//$Id: Stats.cc 80 2006-03-10 16:52:04Z jari $
2
3#include "Stats.h"
4#include "GnuplotFE.h"
5#include "utility.h"
6
7#include <algorithm>
8#include <cassert>
9#include <cstdlib>
10#include <fstream>
11#include <iostream>
12#include <map>
13#include <numeric>
14#include <sstream>
15#include <string>
16#include <unistd.h>
17#include <utility>
18#include <vector>
19
20
21namespace theplu{
22namespace svnstat{
23
24
25  Stats::Stats(const std::string& path)
26  {
27    // Make sure latest revision is set properly
28    std::map<std::string,std::string> svn_info = info(path);
29    std::stringstream ss;
30    ss << (svn_info.count("Revision") ? svn_info["Revision"] : "0");
31    ss >> latest_revision_;
32  }
33
34
35  std::vector<u_int> Stats::accumulated(void) const
36  {
37    // sum of all users
38    std::vector<u_int> sum(latest_revision_+1, 0);
39    sum=std::accumulate(map_.begin(), map_.end(), sum,
40                        PairValuePlus<std::string,u_int>());
41
42    // calculate accumulated sum
43    std::vector<u_int> accum(sum.size());
44    std::partial_sum(sum.begin(),sum.end(),accum.begin());
45    assert(sum.size()==accum.size());
46    return accum;
47  }
48
49  std::vector<u_int> Stats::accumulated(const std::string& user) const
50  {
51    if (!map_.count(user))
52      return std::vector<u_int>();
53    std::vector<u_int> vec=(map_.find(user))->second;
54 
55    if (vec.size() < latest_revision_+1)
56      vec.insert(vec.end(), latest_revision_+1-vec.size(), 0);
57
58    std::vector<u_int> accum(vec.size());
59    std::partial_sum(vec.begin(),vec.end(),accum.begin());
60    return accum;
61  }
62
63  void Stats::add(const std::string& user, const u_int& rev)
64  {
65    std::vector<u_int>* vec = &(map_[user]);
66    if (vec->size() < rev+1){
67      vec->reserve(latest_revision_ + 1);
68      vec->insert(vec->end(), rev - vec->size(),0);
69      vec->push_back(1);
70    }
71    else
72      (*vec)[rev]++;
73  }
74
75
76  bool Stats::parse(const std::string& path)
77  {
78    // Calling svn blame
79    if (blame(path))
80      return true;
81
82    // Check if file is binary
83    std::ifstream is("svnstat.tmp");
84    std::string line;
85    getline(is,line,' ');
86    if (line==std::string("Skipping")){
87      getline(is,line,' ');
88      if (line==std::string("binary")){
89        is.close();
90        return true;
91      }
92    }
93    is.close();
94
95    is.open("svnstat.tmp");
96    while (getline(is,line, '\n')){
97      if (!line.size()) // skip empty line
98        continue;
99      std::stringstream ss(line);
100      u_int revision;
101      std::string user;
102      ss >> revision;
103      ss >> user;
104      add(user, revision);
105    }
106    is.close();
107    return false;
108  }
109
110
111  std::string Stats::plot(const std::string& name) const
112  {
113    GnuplotFE* gp=GnuplotFE::instance();
114    gp->command(std::string("set term png; set output '")+name+"'");
115    gp->command(std::string("set title '")+name+"'");
116    gp->command("set key default");
117    gp->command("set key left Left reverse");
118    gp->command("set multiplot");
119    std::vector<u_int> total=accumulated();   
120    double yrange_max=1.03*total.back()+1;
121    gp->yrange(yrange_max);
122    size_t plotno=1;
123    std::stringstream ss;
124    for (MapConstIter_ i= map_.begin(); i != map_.end(); i++) {
125      ss.str("");
126      ss << "set key height " << 2*plotno;
127      gp->command(ss.str());
128      std::vector<u_int> x=accumulated(i->first);
129      ss.str("");
130      ss << x.back() << " " << i->first;
131      gp->yrange(yrange_max);
132      gp->linetitle(ss.str());
133      ss.str("");
134      ss << "steps " << ++plotno;
135      gp->linestyle(ss.str());
136      gp->plot(x);
137    }
138    ss.str("");
139    ss << total.back() << " total";
140    gp->command("set key height 0");
141    gp->linetitle(ss.str());
142    gp->linestyle("steps 1");
143    gp->plot(total);
144
145    gp->command("unset multiplot");
146    gp->yrange();
147
148    return name;
149  }
150
151  Stats& Stats::operator+=(const Stats& other)
152  {
153    for (MapConstIter_ o_i= other.map_.begin(); o_i != other.map_.end(); ++o_i)
154    {
155      std::pair<MapIter_,bool> result = map_.insert(*o_i);
156      if (!result.second)
157        map_[(*(result.first)).first] = 
158          VectorPlus<u_int>()( (*(result.first)).second, (*o_i).second );
159 
160    }
161    return *this;
162  }
163
164}} // end of namespace svnstat and namespace theplu
Note: See TracBrowser for help on using the repository browser.