lib/how_is/analyzer.rb in how_is-10.0.0 vs lib/how_is/analyzer.rb in how_is-11.0.0
- old
+ new
@@ -10,16 +10,20 @@
end
class Analyzer
include Contracts::Core
+ ##
+ # Raised when attempting to export to an unsupported format.
class UnsupportedImportFormat < StandardError
def initialize(format)
super("Unsupported import format: #{format}")
end
end
+ ##
+ # Generates and returns an analysis.
Contract Fetcher::Results, C::KeywordArgs[analysis_class: C::Optional[Class]] => Analysis
def call(data, analysis_class: Analysis)
issues = data.issues
pulls = data.pulls
@@ -41,10 +45,12 @@
oldest_issue: issue_or_pull_to_hash(oldest_for(issues)),
oldest_pull: issue_or_pull_to_hash(oldest_for(pulls)),
)
end
+ ##
+ # Generates an analysis from a JSON report.
def from_file(file)
extension = file.split('.').last
raise UnsupportedImportFormat, extension unless extension == 'json'
hash = JSON.parse(open(file).read)
@@ -80,23 +86,29 @@
end
end
hash
end
+ # Returns the number of issues with no label.
def num_with_no_label(issues)
issues.select { |x| x['labels'].empty? }.length
end
+ # Given an Array of dates, average the timestamps and return the date that
+ # represents.
def average_date_for(issues_or_pulls)
timestamps = issues_or_pulls.map { |iop| Date.parse(iop['created_at']).strftime('%s').to_i }
average_timestamp = timestamps.reduce(:+) / issues_or_pulls.length
DateTime.strptime(average_timestamp.to_s, '%s')
end
# Given an Array of issues or pulls, return the average age of them.
+ # Returns nil if no issues or pulls are provided.
def average_age_for(issues_or_pulls)
+ return nil if issues_or_pulls.empty?
+
ages = issues_or_pulls.map {|iop| time_ago_in_seconds(iop['created_at'])}
raw_average = ages.reduce(:+) / ages.length
seconds_in_a_year = 31_556_926
seconds_in_a_month = 2_629_743
@@ -134,31 +146,40 @@
"approximately #{value}"
end
# Given an Array of issues or pulls, return the creation date of the oldest.
+ # Returns nil if no issues or pulls are provided.
def oldest_for(issues_or_pulls)
+ return nil if issues_or_pulls.empty?
+
issues_or_pulls.sort_by {|x| DateTime.parse(x['created_at']) }.first
end
+ # Given an issue or PR, returns the date it was created.
def date_for(issue_or_pull)
DateTime.parse(issue_or_pull['created_at'])
end
private
+ # Takes an Array of labels, and returns amodified list that includes links
+ # to each label.
def with_label_links(labels, repository)
labels.map do |label, num_issues|
label_link = "https://github.com/#{repository}/issues?q=" + CGI.escape("is:open is:issue label:\"#{label}\"")
[label, {'link' => label_link, 'total' => num_issues}]
end.to_h
end
+ # Returns how many seconds ago a date (as a String) was.
def time_ago_in_seconds(x)
DateTime.now.strftime("%s").to_i - DateTime.parse(x).strftime("%s").to_i
end
def issue_or_pull_to_hash(iop)
+ return nil if iop.nil?
+
ret = {}
ret['html_url'] = iop['html_url']
ret['number'] = iop['number']
ret['date'] = date_for(iop)