📄 metrics.pm
字号:
my $metric = { name => 'Time In ' . $statename, description => 'Time in days the topic spent in the ' . $statename . ' state.', value => $time_days, # User can not change the metric, not configured. enabled => 0, in_database => 0, filter =>"count", builtin => 1, }; push @topic_metrics, $metric; } return @topic_metrics;}# Returns the user topic metrics as a collection of references to# hashs. The hash that is returned has the same keys as the# metrics_schema hash, plus a value key. This private function# returns "built in" metrics derived from the topic history# table and the topic view history table.sub _get_built_in_user_metrics { my ($self,$username) = @_; my @user_metrics; my $dbh = Codestriker::DB::DBI->get_connection(); # Setup the prepared statements. my $select_topic = $dbh->prepare_cached('SELECT creation_ts ' . 'FROM topicviewhistory ' . 'WHERE topicid = ? AND ' . 'LOWER(email) = LOWER(?) ' . 'ORDER BY creation_ts'); $select_topic->execute($self->{topicid}, $username); my $total_time = $self->calculate_topic_view_time($select_topic); Codestriker::DB::DBI->release_connection($dbh, 1); if ($total_time == 0) { $total_time = ""; } else { $total_time = sprintf("%1.0f",$total_time / (60)); } # This is the topic metric. my $metric = { name => 'Codestriker Time', description => 'Time in minutes spent in Codestriker looking at this topic.', value => $total_time, enabled => 0, in_database => 0, filter =>"minutes", builtin => 1, scope =>'participant', }; push @user_metrics, $metric; return @user_metrics;}# Given a DBI statement that returns a sorted collection of timestamps from# the topicviewhistory table, return the total time.sub calculate_topic_view_time { my ($self,$select_topic) = @_; # The amount of time you give to people after a click assuming no other # clicks are after it. my $time_increment = 4*60; my $total_time = 0; my $last_time = 0; while ( my @row_array = $select_topic->fetchrow_array) { my ($creation_ts) = @row_array; my $time = Codestriker->convert_date_timestamp_time($creation_ts); if ($last_time) { if ($time - $last_time > $time_increment) { $total_time += $time_increment } else { $total_time += $time - $last_time; } } $last_time = $time; } if ($last_time) { $total_time += $time_increment; } return $total_time;}# Returns the topichistory rows as an array of hashes. Each element in the# array is a row, each field in the table is a key. It will only fetch if# from the db once.sub _get_topic_history_rows { my ($self) = @_; if (defined( $self->{topichistoryrows})) { return @{$self->{topichistoryrows}}; } else { my $dbh = Codestriker::DB::DBI->get_connection(); my @history_list; # Setup the prepared statements. my $select_topic = $dbh->prepare_cached('SELECT topichistory.author, ' . 'topichistory.title, ' . 'topichistory.description, ' . 'topichistory.state, ' . 'topichistory.modified_ts, ' . 'topichistory.version, ' . 'topichistory.repository, ' . 'project.name, ' . 'topichistory.reviewers, ' . 'topichistory.cc, ' . 'topichistory.modified_by_user ' . 'FROM topichistory, project ' . 'WHERE topichistory.topicid = ? AND ' . 'topichistory.projectid = project.id ' . 'ORDER BY topichistory.version'); $select_topic->execute($self->{topicid}); while ( my @row_array = $select_topic->fetchrow_array) { my ($author,$title,$description,$state,$modified_ts, $version, $repository,$project,$reviewers,$cc, $modified_by) = @row_array; my %entry = ( author=>$author, title=>decode_utf8($title), description=>decode_utf8($description), state=>$state, modified_ts=>$modified_ts, version=>$version, repository=>$repository, project=>decode_utf8($project), reviewers=>lc($reviewers), cc=>lc($cc), modified_by=>lc($modified_by) ); push @history_list, \%entry; } Codestriker::DB::DBI->release_connection($dbh, 1); $self->{topichistoryrows} = \@history_list; return @history_list; }}# Returns an error message if a number is not a valid value for a given metric.sub _verify_metric { my ($self, $metric, $value) = @_; my $msg = ''; if ($metric->{enabled}) { my $input_ok = 0; if ($metric->{filter} eq "hours") { $input_ok = ($value =~ /(^[\d]+([\.:][\d]*)?$)|(^$)/); $msg = $metric->{name} . " must be a valid time in hours. " . HTML::Entities::encode($value) . " was " . "not saved.<BR>" unless $input_ok; } elsif ($metric->{filter} eq "minutes") { $input_ok = ($value =~ /(^[\d]+)|(^$)/); $msg = $metric->{name} . " must be a valid time in minutes. " . HTML::Entities::encode($value) . " was " . "not saved.<BR>" unless $input_ok; } elsif ($metric->{filter} eq "count") { $input_ok = ($value =~ /(^[\d]+$)|(^$)/); $msg = $metric->{name} . " must be a valid count. " . HTML::Entities::encode($value) . " was not " . "saved.<BR>" unless $input_ok; } elsif ($metric->{filter} eq "percent") { $input_ok = ($value =~ /(^[\d]+(\.[\d]*)?$)|(^$)/); if ($input_ok && $value ne '') { $input_ok = 0 unless ($value >= 0.0 && $value <= 100.0); } $msg = $metric->{name} . " must be a valid percent, between 0 and 100. " . HTML::Entities::encode($value) . " was not saved.<BR>" unless $input_ok; } else { # invalid config. $input_ok = 0; $msg = HTML::Entities::encode($metric->{name}) . " invalid filter type in configuration. Must " . "be hours, count, or percent.<BR>"; } } return $msg;}# Stores all of the metrics to the database.sub store { my ($self) = @_; $self->_store_topic_metrics(); $self->_store_user_metrics();}# Stores the topic metrics to the database.sub _store_user_metrics { my ($self) = @_; foreach my $user (keys %{$self->{usermetrics}}) { $self->get_user_metrics($user); } # Obtain a database connection. my $dbh = Codestriker::DB::DBI->get_connection(); # Flush out the user metrics from the topic. my $delete_alluser_metric = $dbh->prepare_cached('DELETE FROM topicusermetric ' . 'WHERE topicid = ?'); $delete_alluser_metric->execute($self->{topicid}); my $insert_user_metric = $dbh->prepare_cached('INSERT INTO topicusermetric (topicid, email, metric_name, value) ' . 'VALUES (?, LOWER(?), ?, ? )'); foreach my $user (keys %{$self->{usermetrics}}) { my @metrics = $self->get_user_metrics($user); foreach my $metric (@metrics) { next if ($metric->{builtin}); if ($metric->{value} ne '') { $insert_user_metric->execute($self->{topicid}, $user, $metric->{name}, $metric->{value}); } } } # Close the connection, and check for any database errors. Codestriker::DB::DBI->release_connection($dbh, 1);}# Stores the topic metrics to the database.sub _store_topic_metrics { my ($self) = @_; # Obtain a database connection. my $dbh = Codestriker::DB::DBI->get_connection(); # Store the topic metrics first. my @topic_metrics = $self->get_topic_metrics(); my $insert_topic_metric = $dbh->prepare_cached('INSERT INTO topicmetric (topicid, metric_name, value) ' . 'VALUES (?, ?, ? )'); my $update_topic_metric = $dbh->prepare_cached('UPDATE topicmetric SET value = ? ' . 'WHERE topicid = ? and metric_name = ?'); my $delete_topic_metric = $dbh->prepare_cached('DELETE FROM topicmetric ' . 'WHERE topicid = ? and metric_name = ?'); foreach my $metric (@topic_metrics) { # don't save built in metrics next if ($metric->{builtin}); if ($metric->{in_database}) { if ($metric->{value} ne '') { $update_topic_metric->execute($metric->{value}, $self->{topicid}, $metric->{name}); } else { # Delete the row. $delete_topic_metric->execute($self->{topicid}, $metric->{name}); $metric->{in_database} = 0; } } else { # New metric that is not in the datbase. if ($metric->{value} ne '') { $insert_topic_metric->execute($self->{topicid}, $metric->{name}, $metric->{value}); $metric->{in_database} = 1; } } $metric->{in_database} = 1; } # Close the connection, and check for any database errors. Codestriker::DB::DBI->release_connection($dbh, 1);}1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -