source: trunk/lib/Stats.cc @ 73

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

Divided Gnuplot class into a basic gnuplot communication class
and a front end class specialized for svnstat.
Added option to plot stats against time or revision.
Removed gnuplot usage of temporary files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 3.5 KB
Line 
1//$Id: Stats.cc 73 2006-03-04 18:10:07Z 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  u_int Stats::latest_revision_=0;
25
26  std::vector<double> Stats::accumulated(void) const
27  {
28    // sum of all users
29    std::vector<u_int> sum(latest_revision_+1, 0);
30    sum=std::accumulate(map_.begin(), map_.end(), sum,
31                        PairValuePlus<std::string,u_int>());
32
33    // calculate accumulated sum
34    std::vector<double> accum(sum.size());
35    std::partial_sum(sum.begin(),sum.end(),accum.begin());
36    assert(sum.size()==accum.size());
37    return accum;
38  }
39
40  std::vector<double> Stats::accumulated(const std::string& user) const
41  {
42    if (!map_.count(user))
43      return std::vector<double>();
44    std::vector<u_int> vec=(map_.find(user))->second;
45 
46    if (vec.size() < latest_revision_+1)
47      vec.insert(vec.end(), latest_revision_+1-vec.size(), 0);
48
49    std::vector<double> accum(vec.size());
50    std::partial_sum(vec.begin(),vec.end(),accum.begin());
51    return accum;
52  }
53
54  void Stats::add(const std::string& user, const u_int& rev)
55  {
56    std::vector<u_int>* vec = &(map_[user]);
57    if (vec->size() < rev+1){
58      vec->reserve(rev+1);
59      vec->insert(vec->end(), rev - vec->size(),0);
60      vec->push_back(1);
61      latest_revision_ = std::max(latest_revision_,rev);
62    }
63    else
64      (*vec)[rev]++;
65  }
66
67
68  bool Stats::parse(const std::string& path)
69  {
70    // Calling svn blame
71    if (blame(path))
72      return true;
73
74    // Check if file is binary
75    std::ifstream is("svnstat.tmp");
76    std::string line;
77    getline(is,line,' ');
78    if (line==std::string("Skipping")){
79      getline(is,line,' ');
80      if (line==std::string("binary")){
81        is.close();
82        return true;
83      }
84    }
85    is.close();
86
87    is.open("svnstat.tmp");
88    while (getline(is,line, '\n')){
89      if (!line.size()) // skip empty line
90        continue;
91      std::stringstream ss(line);
92      u_int revision;
93      std::string user;
94      ss >> revision;
95      ss >> user;
96      add(user, revision);
97    }
98    is.close();
99    return false;
100  }
101
102
103  std::string Stats::plot(const std::string& name) const
104  {
105    std::string cmd=std::string("set term png; set output '")+name+"'";
106    GnuplotFE* gp=GnuplotFE::instance();
107    gp->command(cmd);
108    gp->command("set key default");
109    gp->command("set key left Left reverse");
110    gp->command("set multiplot");
111    std::vector<double> x=accumulated();   
112    std::stringstream sa;
113    sa << x.back() << " total";
114    gp->linetitle(sa.str());
115    gp->linestyle("steps 1");
116    gp->plot(x);
117    size_t plotno=2;
118    for (MapConstIter_ i= map_.begin(); i != map_.end(); i++) {
119      std::stringstream s0;
120      s0 << "set key height " << plotno;
121      gp->command(s0.str());
122      x=accumulated(i->first);
123      std::stringstream s;
124      s << x.back() << " " << i->first;
125      gp->linetitle(s.str());
126      // Jari, reuse the stream above
127      std::stringstream s2;
128      s2 << "steps " << plotno++;
129      gp->linestyle(s2.str());
130      gp->plot(x);
131    }
132    gp->command("unset multiplot");
133
134    return name;
135  }
136
137  Stats& Stats::operator+=(const Stats& other)
138  {
139    for (MapConstIter_ o_i= other.map_.begin(); o_i != other.map_.end(); ++o_i)
140    {
141      std::pair<MapIter_,bool> result = map_.insert(*o_i);
142      if (!result.second)
143        map_[(*(result.first)).first] = 
144          VectorPlus<u_int>()( (*(result.first)).second, (*o_i).second );
145 
146    }
147    return *this;
148  }
149
150}} // end of namespace svnstat and namespace theplu
Note: See TracBrowser for help on using the repository browser.