<commit_before># == Schema Information
#
# Table name: project_anchors
#
#  id         :integer          not null, primary key
#  program_id :integer          not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class ProjectAnchor < ApplicationRecord
  belongs_to :program
  has_many :projects, inverse_of: :project_anchor, dependent: :destroy

  has_many :dhis2_snapshots, inverse_of: :project_anchor, dependent: :destroy

  def invalid_project?
    project.nil? || project.invalid?
  end

  def project
    projects.first
  end

  def latest_draft
    projects.where(status: "draft").fully_loaded.last
  end

  def nearest_pyramid_for(date)
    kinds = %i(organisation_units organisation_unit_groups organisation_unit_group_sets)
    pyramid_snapshots = dhis2_snapshots.select("id, year, month, kind").where(kind: kinds)

    candidates = pyramid_snapshots.sort_by { |snap| [snap.kind, [snap.year, snap.month].join("-")] }

    final_candidates = kinds.map do |kind|
      kind_method = "kind_#{kind}?".to_sym
      [kind, nearest(candidates.select(&kind_method), date)]
    end.to_h

    final_snapshots = final_candidates.map { |kind, candidate| [kind, candidate ? dhis2_snapshots.find(candidate.id) : nil] }
                                      .to_h
    return nil if final_snapshots.values.compact.size != kinds.size
    new_pyramid(final_snapshots)
  end

  def nearest_data_compound_for(date)
    kinds = %i(data_elements data_element_groups indicators)
    pyramid_snapshots = dhis2_snapshots.select("id, year, month, kind").where(kind: kinds)

    candidates = pyramid_snapshots.sort_by { |snap| [snap.kind, [snap.year, snap.month].join("-")] }

    data_elements = nearest(candidates.select(&:kind_data_elements?), date)
    data_element_groups = nearest(candidates.select(&:kind_data_element_groups?), date)
    indicators = nearest(candidates.select(&:kind_indicators?), date)

    return nil unless data_elements || data_element_groups || indicators
    puts "for #{date} using snapshots #{data_elements.year} #{data_elements.month} and #{data_element_groups.year} #{data_element_groups.month} and #{indicators.year} #{indicators.month}"
    data_elements = dhis2_snapshots.find(data_elements.id) if data_elements
    data_element_groups = dhis2_snapshots.find(data_element_groups.id) if data_element_groups
    indicators = dhis2_snapshots.find(indicators.id) if indicators
    new_data_compound(data_elements, data_element_groups, indicators)
  end

  def nearest(snapshots, date)
    # there should be a better way
    time = date.to_time
    past_candidates = snapshots.select { |snapshot| snapshot.snapshoted_at <= date }
                               .sort_by { |snapshot| time - snapshot.snapshoted_at }

    past_candidate = past_candidates.first
    return past_candidate if past_candidate
    futur_candidates = snapshots.select { |snapshot| snapshot.snapshoted_at > date }
                                .sort_by { |snapshot|
                                  snapshot.snapshoted_at.to_time - time }

    futur_candidates.first
  end

  def pyramid_for(date)
    kinds = %i(organisation_units organisation_unit_groups organisation_unit_group_sets)
    pyramid_snapshots = dhis2_snapshots
                        .where(kind: kinds)
                        .where(month: date.month)
                        .where(year: date.year)

    organisation_units = pyramid_snapshots.find(&:kind_organisation_units?)
    organisation_unit_groups = pyramid_snapshots.find(&:kind_organisation_unit_groups?)
    organisation_unit_group_sets = pyramid_snapshots.find(&:kind_organisation_unit_group_sets?)
    new_pyramid(<commit_msg>fix simulation page<commit_after># == Schema Information
#
# Table name: project_anchors
#
#  id         :integer          not null, primary key
#  program_id :integer          not null
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class ProjectAnchor < ApplicationRecord
  belongs_to :program
  has_many :projects, inverse_of: :project_anchor, dependent: :destroy

  has_many :dhis2_snapshots, inverse_of: :project_anchor, dependent: :destroy

  def invalid_project?
    project.nil? || project.invalid?
  end

  def project
    projects.first
  end

  def latest_draft
    projects.where(status: "draft").fully_loaded.last
  end

  def nearest_pyramid_for(date)
    kinds = %i(organisation_units organisation_unit_groups organisation_unit_group_sets)
    pyramid_snapshots = dhis2_snapshots.select("id, year, month, kind").where(kind: kinds)

    candidates = pyramid_snapshots.sort_by { |snap| [snap.kind, [snap.year, snap.month].join("-")] }

    final_candidates = kinds.map do |kind|
      kind_method = "kind_#{kind}?".to_sym
      [kind, nearest(candidates.select(&kind_method), date)]
    end.to_h

    final_snapshots = final_candidates.map { |kind, candidate| [kind, candidate ? dhis2_snapshots.find(candidate.id) : nil] }
                                      .to_h
    return nil if final_snapshots.values.compact.size != kinds.size
    new_pyramid(final_snapshots)
  end

  def nearest_data_compound_for(date)
    kinds = %i(data_elements data_element_groups indicators)
    pyramid_snapshots = dhis2_snapshots.select("id, year, month, kind").where(kind: kinds)

    candidates = pyramid_snapshots.sort_by { |snap| [snap.kind, [snap.year, snap.month].join("-")] }

    data_elements = nearest(candidates.select(&:kind_data_elements?), date)
    data_element_groups = nearest(candidates.select(&:kind_data_element_groups?), date)
    indicators = nearest(candidates.select(&:kind_indicators?), date)

    return nil unless data_elements || data_element_groups || indicators
    puts "for #{date} using snapshots #{data_elements.year} #{data_elements.month} and #{data_element_groups.year} #{data_element_groups.month} and #{indicators.year} #{indicators.month}"
    data_elements = dhis2_snapshots.find(data_elements.id) if data_elements
    data_element_groups = dhis2_snapshots.find(data_element_groups.id) if data_element_groups
    indicators = dhis2_snapshots.find(indicators.id) if indicators
    new_data_compound(data_elements, data_element_groups, indicators)
  end

  def nearest(snapshots, date)
    # there should be a better way
    time = date.to_time
    past_candidates = snapshots.select { |snapshot| snapshot.snapshoted_at <= date }
                               .sort_by { |snapshot| time - snapshot.snapshoted_at.to_time }

    past_candidate = past_candidates.first
    return past_candidate if past_candidate
    futur_candidates = snapshots.select { |snapshot| snapshot.snapshoted_at > date }
                                .sort_by { |snapshot|
                                  snapshot.snapshoted_at.to_time - time }

    futur_candidates.first
  end

  def pyramid_for(date)
    kinds = %i(organisation_units organisation_unit_groups organisation_unit_group_sets)
    pyramid_snapshots = dhis2_snapshots
                        .where(kind: kinds)
                        .where(month: date.month)
                        .where(year: date.year)

    organisation_units = pyramid_snapshots.find(&:kind_organisation_units?)
    organisation_unit_groups = pyramid_snapshots.find(&:kind_organisation_unit_groups?)
    organisation_unit_group_sets = pyramid_snapshots.find(&:kind_organisation_unit_group_sets?)
    new_pyramid(
{'fraction_non_alphanumeric': 0.09372464160129836, 'fraction_numerical': 0.0021639166892074655, 'mean_word_length': 3.5704573547589615, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2733339', 'n_tokens_mistral': 2325, 'n_tokens_neox': 2267, 'n_words': 439}