source: trunk/lib/Stats.cc @ 112

Last change on this file since 112 was 112, checked in by Peter Johansson, 15 years ago

fixes #27 and added some beauty

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.8 KB
RevLine 
[84]1// $Id: Stats.cc 112 2006-06-29 09:30:54Z peter $
[14]2
[84]3/*
4  Copyright (C) 2005 Peter Johansson
5  Copyright (C) 2006 Jari Häkkinen, Peter Johansson
6
7  This file is part of svnstat, http://lev.thep.lu.se/trac/svnstat
8
9  svnstat is free software; you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13
14  svnstat is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  General Public License for more details.
18
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22  02111-1307, USA.
23*/
24
[14]25#include "Stats.h"
[73]26#include "GnuplotFE.h"
[14]27#include "utility.h"
28
[41]29#include <algorithm>
[65]30#include <cassert>
[63]31#include <cstdlib>
[73]32#include <fstream>
[60]33#include <iostream>
[14]34#include <map>
35#include <numeric>
[39]36#include <sstream>
[14]37#include <string>
[44]38#include <unistd.h>
[23]39#include <utility>
[14]40#include <vector>
41
[63]42
[14]43namespace theplu{
44namespace svnstat{
45
46
[80]47  Stats::Stats(const std::string& path)
48  {
49    // Make sure latest revision is set properly
50    std::map<std::string,std::string> svn_info = info(path);
51    std::stringstream ss;
52    ss << (svn_info.count("Revision") ? svn_info["Revision"] : "0");
[112]53    ss >> revision_;
54    ss.clear();
55    ss << (svn_info.count("Last Changed Rev") ? svn_info["Last Changed Rev"] : "0");
56    ss >> last_changed_rev_;
[80]57  }
58
59
[74]60  std::vector<u_int> Stats::accumulated(void) const
[14]61  {
[36]62    // sum of all users
[112]63    std::vector<u_int> sum(revision_+1, 0);
[36]64    sum=std::accumulate(map_.begin(), map_.end(), sum,
65                        PairValuePlus<std::string,u_int>());
[14]66
67    // calculate accumulated sum
[74]68    std::vector<u_int> accum(sum.size());
[60]69    std::partial_sum(sum.begin(),sum.end(),accum.begin());
[63]70    assert(sum.size()==accum.size());
[14]71    return accum;
72  }
73
[74]74  std::vector<u_int> Stats::accumulated(const std::string& user) const
[14]75  {
[35]76    if (!map_.count(user))
[74]77      return std::vector<u_int>();
[35]78    std::vector<u_int> vec=(map_.find(user))->second;
[41]79 
[112]80    if (vec.size() < revision_+1)
81      vec.insert(vec.end(), revision_+1-vec.size(), 0);
[35]82
[74]83    std::vector<u_int> accum(vec.size());
[14]84    std::partial_sum(vec.begin(),vec.end(),accum.begin());
85    return accum;
86  }
87
88  void Stats::add(const std::string& user, const u_int& rev)
89  {
[42]90    std::vector<u_int>* vec = &(map_[user]);
91    if (vec->size() < rev+1){
[112]92      vec->reserve(revision_ + 1);
[42]93      vec->insert(vec->end(), rev - vec->size(),0);
94      vec->push_back(1);
[14]95    }
96    else
[42]97      (*vec)[rev]++;
[14]98  }
99
[60]100
[72]101  bool Stats::parse(const std::string& path)
[60]102  {
103    // Calling svn blame
104    if (blame(path))
105      return true;
106
107    // Check if file is binary
108    std::ifstream is("svnstat.tmp");
109    std::string line;
110    getline(is,line,' ');
111    if (line==std::string("Skipping")){
112      getline(is,line,' ');
113      if (line==std::string("binary")){
114        is.close();
[72]115        return true;
[60]116      }
117    }
118    is.close();
119
120    is.open("svnstat.tmp");
121    while (getline(is,line, '\n')){
122      if (!line.size()) // skip empty line
123        continue;
124      std::stringstream ss(line);
125      u_int revision;
126      std::string user;
127      ss >> revision;
128      ss >> user;
129      add(user, revision);
130    }
131    is.close();
132    return false;
133  }
134
135
[101]136  std::string Stats::plot(const std::string& filename,
137                          const std::string& title) const
[34]138  {
[73]139    GnuplotFE* gp=GnuplotFE::instance();
[101]140    gp->command(std::string("set term png; set output '")+filename+"'");
141    gp->command(std::string("set title '")+title+"'");
[73]142    gp->command("set key default");
143    gp->command("set key left Left reverse");
144    gp->command("set multiplot");
[76]145    std::vector<u_int> total=accumulated();   
146    double yrange_max=1.03*total.back()+1;
[74]147    gp->yrange(yrange_max);
148    size_t plotno=1;
[77]149    std::stringstream ss;
[39]150    for (MapConstIter_ i= map_.begin(); i != map_.end(); i++) {
[77]151      ss.str("");
152      ss << "set key height " << 2*plotno;
153      gp->command(ss.str());
[76]154      std::vector<u_int> x=accumulated(i->first);
[77]155      ss.str("");
156      ss << x.back() << " " << i->first;
[74]157      gp->yrange(yrange_max);
[77]158      gp->linetitle(ss.str());
159      ss.str("");
160      ss << "steps " << ++plotno;
161      gp->linestyle(ss.str());
[73]162      gp->plot(x);
[39]163    }
[77]164    ss.str("");
165    ss << total.back() << " total";
[76]166    gp->command("set key height 0");
[77]167    gp->linetitle(ss.str());
[76]168    gp->linestyle("steps 1");
169    gp->plot(total);
170
[73]171    gp->command("unset multiplot");
[74]172    gp->yrange();
[36]173
[101]174    return filename;
[34]175  }
176
[14]177  Stats& Stats::operator+=(const Stats& other)
178  {
[23]179    for (MapConstIter_ o_i= other.map_.begin(); o_i != other.map_.end(); ++o_i)
[14]180    {
[23]181      std::pair<MapIter_,bool> result = map_.insert(*o_i);
[14]182      if (!result.second)
[23]183        map_[(*(result.first)).first] = 
184          VectorPlus<u_int>()( (*(result.first)).second, (*o_i).second );
[14]185 
186    }
187    return *this;
188  }
189
190}} // end of namespace svnstat and namespace theplu
Note: See TracBrowser for help on using the repository browser.