<commit_before>require 'date'
require 'time'

class Moment
  def self.to_a
    ["Year", "Month", "ISO Year", "ISO Week"]
  end

  attr_reader :ts
  def initialize(s)
    @ts = DateTime.strptime(s, "%Y-%m-%d %H:%M:%S")
  end

  def cohort
    "%d:%02d" % [ts.cwyear, ts.cweek]
  end

  def to_a
    [ts.year, ts.month, ts.cwyear, ts.cweek]
  end

  def to_s
    ts.strftime("%Y-%m-%d")
  end
end

class Metric
  def self.report(sql, headers, fn)
    require 'active_record'
    require 'db/connection'
    DB::Connection.establish

    rows = ActiveRecord::Base.connection.execute(sql)
    puts headers.join(",")
    rows.each do |row|
      puts fn.call(row)
    end
  end
end

def days(first, last)
  return 0 if last.nil?
  (DateTime.parse(last)-DateTime.parse(first)).to_i + 1
end

def ttf(signup, submit)
  return "(4) never" if submit.nil?

  diff = Time.parse(submit)-Time.parse(signup)

  return '(1) day' if diff < 24*60*60
  return '(2) week' if diff < 24*60*60*7
  '(3) more'
end

namespace :metrics do
  namespace :events do
    desc "extract signup events"
    task :signups do
      sql = <<-SQL
        SELECT id, created_at FROM users ORDER BY created_at ASC
      SQL
      fn = lambda { |row|
        at = Moment.new(row['created_at'])
        ([ row['id'], at.to_s] + at.to_a).join(",")
      }
      Metric.report(sql, ["User ID", "Signed Up On"]+Moment.to_a, fn)
    end

    desc "extract comment events"
    task :comments do
      sql = <<-SQL
        SELECT id, user_id, created_at FROM comments ORDER BY created_at ASC
      SQL
      fn = lambda { |row|
        at = Moment.new(row['created_at'])
        ([ row['id'], row['user_id'], at.to_s] + at.to_a).join(",")
      }
      Metric.report(sql, ["Comment ID", "User ID", "Submitted On"]+Moment.to_a, fn)
    end

    desc "extract iteration events"
    task :iterations do
      sql = "SELECT id, user_id, created_at FROM submissions ORDER BY created_at ASC"
      fn = lambda { |row|
        at = Moment.new(row['created_at'])
        ([ row['id'], row['user_id'], at.to_s] + at.to_a).join(",")
      }
      Metric.report(sql, ["Iteration ID", "User ID", "Submitted On"]+Moment.to_a, fn)
    end
  end

  desc "feedback"
  task :feedback do
    sql = <<-SQL
      SELECT
        user_exercise_id AS id,<commit_msg>Add a couple more metrics tasks<commit_after>require 'date'
require 'time'

class Moment
  def self.to_a
    ["Year", "Month", "ISO Year", "ISO Week"]
  end

  attr_reader :ts
  def initialize(s)
    @ts = DateTime.strptime(s, "%Y-%m-%d %H:%M:%S")
  end

  def cohort
    "%d:%02d" % [ts.cwyear, ts.cweek]
  end

  def to_a
    [ts.year, ts.month, ts.cwyear, ts.cweek]
  end

  def to_s
    ts.strftime("%Y-%m-%d")
  end
end

class Metric
  def self.report(sql, headers, fn)
    require 'active_record'
    require 'db/connection'
    DB::Connection.establish

    rows = ActiveRecord::Base.connection.execute(sql)
    puts headers.join(",")
    rows.each do |row|
      puts fn.call(row)
    end
  end
end

def days(first, last)
  return 0 if last.nil?
  (DateTime.parse(last)-DateTime.parse(first)).to_i + 1
end

def ttf(signup, submit)
  return "(4) never" if submit.nil?

  diff = Time.parse(submit)-Time.parse(signup)

  return '(1) day' if diff < 24*60*60
  return '(2) week' if diff < 24*60*60*7
  '(3) more'
end

namespace :metrics do
  namespace :events do
    desc "extract signup events"
    task :signups do
      sql = <<-SQL
        SELECT id, created_at FROM users ORDER BY created_at ASC
      SQL
      fn = lambda { |row|
        at = Moment.new(row['created_at'])
        ([ row['id'], at.to_s] + at.to_a).join(",")
      }
      Metric.report(sql, ["User ID", "Signed Up On"]+Moment.to_a, fn)
    end

    desc "extract comment events"
    task :comments do
      sql = <<-SQL
        SELECT id, user_id, created_at FROM comments ORDER BY created_at ASC
      SQL
      fn = lambda { |row|
        at = Moment.new(row['created_at'])
        ([ row['id'], row['user_id'], at.to_s] + at.to_a).join(",")
      }
      Metric.report(sql, ["Comment ID", "User ID", "Submitted On"]+Moment.to_a, fn)
    end

    desc "extract iteration events"
    task :iterations do
      sql = "SELECT id, user_id, created_at FROM submissions ORDER BY created_at ASC"
      fn = lambda { |row|
        at = Moment.new(row['created_at'])
        ([ row['id'], row['user_id'], at.to_s] + at.to_a).join(",")
      }
      Metric.report(sql, ["Iteration ID", "User ID", "Submitted On"]+Moment.to_a, fn)
    end
  end

  namespace :unique do
    desc "extract unique commenter count per week"
    task :commenters do
      sql = <<-SQL
      SELECT
        extract(isoyear from created_at) AS isoyear,
        extract(week from created_at) AS isoweek,
        count(DISTINCT user_id) AS tally
      FROM comments
      GROUP BY
        extract(isoyear from created_at),
        extract(week from created_at)
      SQL

      fn = lambda { |row|
        [row['isoyear'], row['isoweek'], row['tally']].join(",")
      }
      Metric.report(sql, ["ISO Year", "ISO Week", "Unique Commenters"], fn)
    end

    desc "extract unique submitter count per week"
    task :submitters do
      sql = <<-SQL
      SELECT
        extract(isoyear from created_at) AS isoyear,
        extract(week from created_at) AS isoweek,
        count(DISTINCT user_id) AS tally
      FROM submissions
      GROUP BY
        extract(isoyear from created_at),
        extract(week from created_at)
      SQL

      fn = lambda { |row|
        [row['isoyear'], row['isoweek'], row['tally']].join(",")
      }
      Metric.report(sql, ["ISO Year", "ISO Week", "Unique Submitters"], fn)
    end
  end

  desc "feedback"
  task :feedback do
    sql = <<-SQL
      SELECT
        user_exercise_id AS id,
{'fraction_non_alphanumeric': 0.14040263797292607, 'fraction_numerical': 0.007289135716765012, 'mean_word_length': 2.5928927680798006, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4295720', 'n_tokens_mistral': 2111, 'n_tokens_neox': 2007, 'n_words': 568}