source: trunk/lib/Stats.cc @ 527

Last change on this file since 527 was 527, checked in by Peter Johansson, 14 years ago

removing valid variable - starting to refactor Stats class.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.1 KB
Line 
1// $Id: Stats.cc 527 2007-12-25 05:11:09Z peter $
2
3/*
4  Copyright (C) 2005 Peter Johansson
5  Copyright (C) 2006, 2007 Jari Häkkinen, Peter Johansson
6
7  This file is part of svndigest, http://trac.thep.lu.se/svndigest
8
9  svndigest 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  svndigest 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
25#include "Stats.h"
26
27#include "Functor.h"
28#include "GnuplotFE.h"
29#include "SVNblame.h"
30#include "SVNinfo.h"
31#include "utility.h"
32
33#include <algorithm>
34#include <cassert>
35#include <cstdlib>
36#include <fstream>
37#include <iostream>
38#include <iterator>
39#include <map>
40#include <numeric>
41#include <string>
42#include <sstream>
43#include <unistd.h>
44#include <utility>
45#include <vector>
46
47
48namespace theplu{
49namespace svndigest{
50
51
52  Stats::Stats(const std::string& path)
53  {
54    // Make sure latest revision is set properly
55    SVNinfo svn_info(path);
56    revision_=svn_info.rev();
57    last_changed_rev_=svn_info.last_changed_rev();
58  }
59
60
61  Stats::~Stats(void)
62  {
63  }
64
65
66  void Stats::base_add(v_map::const_iterator first1, 
67                       v_map::const_iterator last1, v_map& map)
68  {
69    v_map::iterator first2(map.begin());
70    v_map::key_compare compare;
71    while ( first1 != last1) { 
72      // key of first1 less than key of first2
73      if (first2==map.end() || compare(first1->first,first2->first)) {
74        first2 = map.insert(first2, *first1);
75        ++first1;
76      }
77      // key of first2 less than key of first1
78      else if ( compare(first2->first, first1->first)) {
79        ++first2;
80      }
81      // keys are equivalent
82      else {
83        VectorPlus<v_map::mapped_type::value_type> vp;
84        first2->second = vp(first1->second, first2->second);
85        ++first1;
86        ++first2;
87      }
88    }
89  }
90
91
92  void Stats::add_author(std::string name)
93  {
94    authors_.insert(name);
95  }
96
97
98  void Stats::add_authors(std::set<std::string>::const_iterator first, 
99                          std::set<std::string>::const_iterator last)
100  {
101    authors_.insert(first, last);
102  }
103
104
105  const std::set<std::string>& Stats::authors(void) const
106  {
107    return authors_;
108  }
109
110
111  void Stats::base_add(const Stats& rhs)
112  {
113    revision_ = std::max(revision_, rhs.revision_);
114    last_changed_rev_ = std::max(last_changed_rev_, rhs.last_changed_rev_);
115    add_authors(rhs.authors().begin(), rhs.authors().end());
116    base_add(rhs.code_.begin(), rhs.code_.end(), code_);
117    base_add(rhs.comments_.begin(), rhs.comments_.end(), comments_);
118    base_add(rhs.other_.begin(), rhs.other_.end(), other_);
119    base_add(rhs.total_.begin(), rhs.total_.end(), total_);
120  }
121
122
123  u_int Stats::code(const std::string& user) const
124  {
125    return get_vector(code_, "all").back();
126  }
127
128
129  u_int Stats::comments(const std::string& user) const
130  {
131    return get_vector(comments_, "all").back();
132  }
133
134
135  u_int Stats::empty(const std::string& user) const
136  {
137    return get_vector(other_, "all").back();
138  }
139
140
141  const std::vector<u_int>& Stats::get_vector(const v_map& m, 
142                                              std::string user) const
143  {
144    v_map::const_iterator iter(m.find(std::string(user)));
145    if (iter==m.end()) 
146      throw std::runtime_error(user+std::string(" not found i Stats"));
147    return iter->second;
148  }
149
150  bool Stats::load_cache(std::istream& is)
151  {
152
153    svn_revnum_t rev;
154    is >> rev;
155    if (rev<last_changed_rev_){
156      return false; // cache is not up to date
157    }
158    size_t a_size=0;
159    authors_.clear();
160    is >> a_size;
161    std::string str;
162    getline(is, str);
163    while (authors_.size()<a_size){
164      getline(is, str);
165      assert(str.size());
166      authors_.insert(str);
167    }
168    return do_load_cache(is);
169  }
170
171
172  svn_revnum_t Stats::last_changed_rev(void) const
173  {
174    return last_changed_rev_;
175  }
176
177
178  u_int Stats::lines(const std::string& user) const
179  {
180    return get_vector(total_, "all").back();
181  }
182
183
184  void Stats::parse(const std::string& path)
185  {
186    // First we let inherited class do parsing
187    do_parse(path);
188    // then we fill up with statistics
189
190    update_stats();
191  }
192
193  std::string Stats::plot(const std::string& filename,
194                          const std::string& linetype) const
195  {
196    return do_plot(filename, linetype);
197  }
198
199
200  void Stats::plot_init(const std::string& filename) const
201  {
202    GnuplotFE* gp=GnuplotFE::instance();
203    gp->command("set term png");
204    gp->command("set output '"+filename+"'");
205    gp->command("set xtics nomirror");
206    gp->command("set ytics nomirror");
207    gp->command("set key default");
208    gp->command("set key left Left reverse");
209    gp->command("set multiplot");
210  }
211
212
213  void Stats::plot_summary(const std::string& filename) const
214  {
215    plot_init(filename);
216    GnuplotFE* gp=GnuplotFE::instance();
217    std::vector<u_int> total = get_vector(total_, "all");
218    double yrange_max=1.03*total.back()+1;
219    gp->yrange(yrange_max);
220    std::stringstream ss;
221   
222    ss.str("");
223    std::vector<u_int> x(get_vector(code_, "all"));
224    ss << x.back() << " code";
225    gp->command("set key height 2");
226    gp->linetitle(ss.str());
227    gp->linestyle("steps 2");
228    gp->plot(x);
229
230    ss.str("");
231    x = get_vector(comments_, "all");
232    ss << x.back() << " comment";
233    gp->command("set key height 4");
234    gp->linetitle(ss.str());
235    gp->linestyle("steps 3");
236    gp->plot(x);
237
238    ss.str("");
239    x = get_vector(other_, "all");
240    ss << x.back() << " other";
241    gp->command("set key height 6");
242    gp->linetitle(ss.str());
243    gp->linestyle("steps 4");
244    gp->plot(x);
245
246    ss.str("");
247    ss << total.back() << " total";
248    gp->command("set key height 0");
249    gp->linetitle(ss.str());
250    gp->linestyle("steps 1");
251    gp->plot(total);
252
253    gp->command("unset multiplot");
254    gp->yrange();
255  }
256
257
258  void Stats::print(std::ostream& os) const
259  {
260    os << last_changed_rev_ << " ";
261    os << authors_.size() << "\n";
262
263    std::copy(authors_.begin(), authors_.end(), 
264              std::ostream_iterator<std::string>(os, "\n"));
265    do_print(os);
266  }
267
268
269  void Stats::reset(void)
270  {
271    do_reset();
272  }
273
274
275  void Stats::update_stats(void)
276  {
277    for (std::set<std::string>::const_iterator iter(authors_.begin());
278         iter!=authors_.end(); ++iter) {
279      std::vector<u_int> code(vector("code", *iter));
280      code_[*iter] = code;
281      std::vector<u_int> comments(vector("comments", *iter));
282      comments_[*iter] = comments;
283      std::vector<u_int> other(vector("other", *iter));
284      other_[*iter] = other;
285      VectorPlus<u_int> vp;
286      total_[*iter] = vp(vp(code, comments),other);
287    }
288    std::vector<u_int> init(revision()+1);
289    code_["all"]=std::accumulate(code_.begin(), code_.end(), init,
290                                 PairValuePlus<std::string,u_int>());
291    comments_["all"]=std::accumulate(comments_.begin(), comments_.end(), init,
292                                     PairValuePlus<std::string,u_int>());
293    other_["all"]=std::accumulate(other_.begin(), other_.end(), init,
294                                  PairValuePlus<std::string,u_int>());
295    VectorPlus<u_int> vp;
296    total_["all"] = vp(vp(code_["all"], comments_["all"]), other_["all"]);
297  }
298
299
300}} // end of namespace svndigest and namespace theplu
Note: See TracBrowser for help on using the repository browser.