source: trunk/lib/Stats.cc @ 60

Last change on this file since 60 was 60, checked in by Peter Johansson, 16 years ago

plotting vs date rather than revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 3.8 KB
Line 
1//$Id: Stats.cc 60 2006-01-16 10:03:04Z peter $
2
3#include "Stats.h"
4#include "Gnuplot.h"
5#include "utility.h"
6
7#include <algorithm>
8#include <iostream>
9#include <map>
10#include <numeric>
11#include <sstream>
12#include <string>
13#include <unistd.h>
14#include <utility>
15#include <vector>
16
17namespace theplu{
18namespace svnstat{
19
20  Gnuplot Stats::gnuplot_pipe_;
21  u_int Stats::latest_revision_=0;
22
23  std::vector<double> Stats::accumulated(void) const
24  {
25    // sum of all users
26    std::vector<u_int> sum(latest_revision_+1, 0);
27    sum=std::accumulate(map_.begin(), map_.end(), sum,
28                        PairValuePlus<std::string,u_int>());
29
30    // calculate accumulated sum
31    std::vector<double> accum(sum.size());
32    std::partial_sum(sum.begin(),sum.end(),accum.begin());
33    return accum;
34  }
35
36  std::vector<double> Stats::accumulated(const std::string& user) const
37  {
38    if (!map_.count(user))
39      return std::vector<double>();
40    std::vector<u_int> vec=(map_.find(user))->second;
41 
42    if (vec.size() < latest_revision_+1)
43      vec.insert(vec.end(), latest_revision_+1-vec.size(), 0);
44
45    std::vector<double> accum(vec.size());
46    std::partial_sum(vec.begin(),vec.end(),accum.begin());
47    return accum;
48  }
49
50  void Stats::add(const std::string& user, const u_int& rev)
51  {
52    std::vector<u_int>* vec = &(map_[user]);
53    if (vec->size() < rev+1){
54      vec->reserve(rev+1);
55      vec->insert(vec->end(), rev - vec->size(),0);
56      vec->push_back(1);
57      latest_revision_ = std::max(latest_revision_,rev);
58    }
59    else
60      (*vec)[rev]++;
61  }
62
63
64  bool Stats::parse(const std::string& path, const bool binary)
65  {
66    if (binary){
67      std::map<std::string,std::string> svn_info = info(path);
68      std::stringstream ss(svn_info["Last Changed Rev"]);
69      u_int revision;
70      ss >> revision;
71      add(svn_info["Last Changed Author"],revision);
72      return true;
73    }
74
75    // Calling svn blame
76    if (blame(path))
77      return true;
78
79    // Check if file is binary
80    std::ifstream is("svnstat.tmp");
81    std::string line;
82    getline(is,line,' ');
83    if (line==std::string("Skipping")){
84      getline(is,line,' ');
85      if (line==std::string("binary")){
86        is.close();
87        return parse(path,true);
88      }
89    }
90    is.close();
91
92    is.open("svnstat.tmp");
93    while (getline(is,line, '\n')){
94      if (!line.size()) // skip empty line
95        continue;
96      std::stringstream ss(line);
97      u_int revision;
98      std::string user;
99      ss >> revision;
100      ss >> user;
101      add(user, revision);
102    }
103    is.close();
104    return false;
105  }
106
107
108  std::string Stats::plot(void) const
109  {
110    char name[]="svnstat_XXXXXX.png";
111    if (mkstemps(name,4)==-1){
112      throw std::runtime_error(std::string("Failed to get unique filename: ") +
113                             name);
114    }
115    std::string cmd=std::string("set term png; set output '")+name+"'";
116    gnuplot_pipe_.command(cmd);
117    gnuplot_pipe_.command("set key left Left reverse");
118    std::vector<double> x=accumulated();   
119    std::stringstream sa;
120    sa << x.back() << " total";
121    gnuplot_pipe_.linetitle(sa.str());
122    gnuplot_pipe_.date_plot(x);
123    for (MapConstIter_ i= map_.begin(); i != map_.end(); i++) {
124      x=accumulated(i->first);
125      std::stringstream s;
126      s << x.back() << " " << i->first;
127      gnuplot_pipe_.linetitle(s.str());
128      gnuplot_pipe_.date_replot(x);
129    }
130
131    // Jari, must rewrite output once since the replots above are not
132    // added to the plot. Rather, the plot only contains the result
133    // from the first 'plot' call.
134    gnuplot_pipe_.command(cmd);
135    gnuplot_pipe_.command("replot");
136    return name;
137  }
138
139  Stats& Stats::operator+=(const Stats& other)
140  {
141    for (MapConstIter_ o_i= other.map_.begin(); o_i != other.map_.end(); ++o_i)
142    {
143      std::pair<MapIter_,bool> result = map_.insert(*o_i);
144      if (!result.second)
145        map_[(*(result.first)).first] = 
146          VectorPlus<u_int>()( (*(result.first)).second, (*o_i).second );
147 
148    }
149    return *this;
150  }
151
152}} // end of namespace svnstat and namespace theplu
Note: See TracBrowser for help on using the repository browser.