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)