Skip to content

Commit

Permalink
♻️ Refactorise la facon de calculer le temps passé dans les exports d…
Browse files Browse the repository at this point in the history
…e litteratie et numeratie
  • Loading branch information
Marion Velard authored and cprodhomme committed Jan 20, 2025
1 parent 15af084 commit fff18d6
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 51 deletions.
5 changes: 5 additions & 0 deletions app/models/evenement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ class Evenement < ApplicationRecord
acts_as_paranoid

scope :reponses, -> { where(nom: 'reponse') }
scope :groupees_par_questions, lambda {
select("donnees->>'question' AS question, date, position")
.order(:position)
.group_by(&:question)
}

def fin_situation?
nom == 'finSituation'
Expand Down
6 changes: 0 additions & 6 deletions app/models/restitution/base/temps_total.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ def calcule(evenements_situation, evenements_entrainement)

evenements.last.date - evenements.first.date
end

def self.format_temps_total(temps_total)
minutes = temps_total / 60
seconds = temps_total % 60
format('%<minutes>02d:%<seconds>02d', minutes: minutes, seconds: seconds)
end
end
end
end
31 changes: 31 additions & 0 deletions app/models/restitution/metriques/temps_passe_par_question.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

module Restitution
module Metriques
class TempsPasseParQuestion
include ApplicationHelper

def initialize(evenements)
@evenements = evenements
end

def calculer
return if @evenements.empty?

evenements_groupes = @evenements.groupees_par_questions
evenements_groupes.each_with_object({}) do |(question, evenements), result|
temps_total = calcul_temps_total(evenements)
result[question] = formate_duree(temps_total)
end
end

private

def calcul_temps_total(evenements)
return unless evenements.size >= 2

Restitution::MetriquesHelper.temps_entre_couples(evenements)&.first || 0
end
end
end
end
3 changes: 1 addition & 2 deletions app/models/restitution/positionnement/export.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ class Export < ::ImportExport::ExportXls # rubocop:disable Metrics/ClassLength
def initialize(partie:)
super()
@partie = partie
@evenements_reponses = Evenement.where(session_id: @partie.session_id).reponses
@workbook = Spreadsheet::Workbook.new
end

Expand Down Expand Up @@ -55,7 +54,7 @@ def remplie_la_feuille
end

def remplis_reponses_litteratie(ligne)
export = ExportLitteratie.new(@evenements_reponses.sort_by(&:position), @sheet)
export = ExportLitteratie.new(@partie, @sheet)
export.remplis_reponses(ligne)
end

Expand Down
18 changes: 7 additions & 11 deletions app/models/restitution/positionnement/export_litteratie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
module Restitution
module Positionnement
class ExportLitteratie
def initialize(evenements_reponses, sheet)
def initialize(partie, sheet)
super()
@evenements_reponses = evenements_reponses
@sheet = sheet
@partie = partie
@temps_par_question = Restitution::Metriques::TempsPasseParQuestion
.new(@partie.evenements).calculer
@evenements_reponses = Evenement.where(session_id: @partie.session_id).reponses
end

def remplis_reponses(ligne)
@evenements_reponses.each do |evenement|
@evenements_reponses.sort_by(&:position).each do |evenement|
ligne = remplis_ligne(ligne, evenement)
end
ligne
Expand All @@ -23,16 +26,9 @@ def remplis_ligne(ligne, evenement)
evenement.donnees['score'],
evenement.donnees['scoreMax'],
evenement.donnees['metacompetence'],
calcule_temps_passe(evenement)])
@temps_par_question[evenement.donnees['question']]])
ligne + 1
end

def calcule_temps_passe(evenement)
evenement_debut = evenement.recupere_evenement_affichage_question_qcm
temps_total = evenement_debut.nil? ? 0 : evenement.date - evenement_debut.date

Restitution::Base::TempsTotal.format_temps_total(temps_total)
end
end
end
end
14 changes: 3 additions & 11 deletions app/models/restitution/positionnement/export_numeratie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ def initialize(partie, sheet)
@partie = partie
@evenements_reponses = Evenement.where(session_id: @partie.session_id).reponses
@sheet = sheet
@temps_par_question = Restitution::Metriques::TempsPasseParQuestion
.new(@partie.evenements).calculer
end

def regroupe_par_codes_clea
Expand Down Expand Up @@ -122,21 +124,11 @@ def pris_en_compte_pour_calcul_score_clea?(liste_questions, question)
liste_questions.include?(question) ? 'Oui' : 'Non'
end

def calcule_temps_passe(question)
evenement_reponse = @evenements_reponses.find_by("donnees ->> 'question' = ?", question)
return if evenement_reponse.nil?

evenement_qcm = evenement_reponse.recupere_evenement_affichage_question_qcm
temps_total = evenement_qcm.nil? ? 0 : evenement_reponse.date - evenement_qcm.date

Restitution::Base::TempsTotal.format_temps_total(temps_total)
end

def remplis_choix(ligne, donnees, question)
@sheet[ligne, 8] = question&.interaction == 'qcm' ? question&.liste_choix : nil
@sheet[ligne, 9] = question&.bonnes_reponses if question&.qcm? || question&.saisie?
@sheet[ligne, 10] = donnees['reponseIntitule'] || donnees['reponse']
@sheet[ligne, 11] = calcule_temps_passe(donnees['question'])
@sheet[ligne, 11] = @temps_par_question[donnees['question']]
end

# Trie par code cléa et par question
Expand Down
63 changes: 63 additions & 0 deletions spec/models/evenement_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,69 @@
end
end

describe '.groupees_par_questions' do
let(:session_id) { 'session_id' }
let(:partie) { create(:partie, session_id: session_id) }

let!(:evenement) do
create(:evenement, partie: partie, session_id: session_id,
donnees: { 'question' => question_evenement },
date: 10.minutes.ago, position: 3)
end
let!(:autre_evenement) do
create(:evenement, partie: partie, session_id: session_id,
donnees: { 'question' => autre_question_evenement },
date: 10.minutes.ago, position: 2)
end

context 'quand une question a deux evenements' do
let(:question_evenement) { 'Question 1' }
let(:autre_question_evenement) { 'Question 1' }

it 'regroupe les evenements' do
result = described_class.groupees_par_questions

expect(result.keys).to contain_exactly('Question 1')
expect(result['Question 1'].size).to eq(2)
expect(result['Question 1']).to contain_exactly(
have_attributes(question: 'Question 1', date: evenement.date, position: 3),
have_attributes(question: 'Question 1', date: autre_evenement.date, position: 2)
)
end

it 'ordonne les evenements par position' do
result = described_class.groupees_par_questions

expect(result['Question 1'][0]).to have_attributes(
question: 'Question 1', date: autre_evenement.date, position: 2
)

expect(result['Question 1'][1]).to have_attributes(
question: 'Question 1', date: evenement.date, position: 3
)
end
end

context "quand une question a qu'un evenement" do
let(:question_evenement) { 'Question 1' }
let(:autre_question_evenement) { 'Question 2' }

it 'regroupe les evenements seuls' do
result = described_class.groupees_par_questions

expect(result.keys).to contain_exactly('Question 1', 'Question 2')
expect(result['Question 1'].size).to eq(1)
expect(result['Question 1']).to contain_exactly(
have_attributes(question: 'Question 1', date: evenement.date, position: 3)
)
expect(result['Question 2'].size).to eq(1)
expect(result['Question 2']).to contain_exactly(
have_attributes(question: 'Question 2', date: autre_evenement.date, position: 2)
)
end
end
end

describe '#recupere_evenement_affichage_question_qcm' do
subject { described_class.new(partie: partie, donnees: donnees) }

Expand Down
14 changes: 0 additions & 14 deletions spec/models/restitution/base/temps_total_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,4 @@
it { expect(metrique_temps_total).to eq 2.minutes }
end
end

describe '#format_temps_total' do
it 'formate correctement le temps total en mm:ss pour des minutes et secondes exactes' do
expect(described_class.format_temps_total(300)).to eq('05:00')
end

it 'formate correctement le temps total en mm:ss pour moins d’une minute' do
expect(described_class.format_temps_total(45)).to eq('00:45')
end

it 'formate correctement le temps total en mm:ss pour zéro seconde' do
expect(described_class.format_temps_total(0)).to eq('00:00')
end
end
end
24 changes: 17 additions & 7 deletions spec/models/restitution/positionnement/export_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@
end

before do
heure_debut = DateTime.new(2025, 1, 17, 10, 0, 0)
heure_fin = heure_debut + 59.seconds
create :evenement_affichage_question_qcm,
date: DateTime.current,
partie: partie,
date: heure_debut,
donnees: { question: 'LOdi1' }
create :evenement_reponse,
partie: partie,
date: DateTime.current,
date: heure_fin,
donnees: { question: 'LOdi1',
reponse: 'couverture',
score: 2,
Expand All @@ -61,7 +63,7 @@
expect(ligne[3]).to eq(2)
expect(ligne[4]).to eq(2)
expect(ligne[5]).to eq('lecture')
expect(ligne[6]).to eq('00:00')
expect(ligne[6]).to eq('00:59')
end

it 'verifie les détails de la deuxième question' do
Expand All @@ -72,7 +74,7 @@
expect(ligne[3]).to be_nil
expect(ligne[4]).to be_nil
expect(ligne[5]).to be_nil
expect(ligne[6]).to eq('00:00')
expect(ligne[6]).to be_nil
end
end
end
Expand Down Expand Up @@ -111,9 +113,13 @@

describe 'génére un fichier xls avec les evenements réponses' do
before do
heure_debut = DateTime.new(2025, 1, 17, 10, 0, 0)
heure_fin = heure_debut + 59.seconds

create :evenement_reponse,
date: DateTime.current,
date: heure_fin,
partie: partie,
position: 2,
donnees: { question: 'LOdi1',
reponse: 'drapeau',
reponseIntitule: "c'est un drapeau",
Expand All @@ -122,16 +128,19 @@
intitule: 'De quoi s’agit-il ?',
metacompetence: :renseigner_horaires }
create :evenement_affichage_question_qcm,
date: DateTime.current,
date: heure_debut,
partie: partie,
position: 1,
donnees: { question: 'LOdi1' }
create :evenement_reponse,
partie: partie,
position: 3,
donnees: { question: 'LOdi2',
score: 1,
scoreMax: 2,
metacompetence: :renseigner_horaires }
create :evenement_reponse,
position: 4,
partie: partie,
donnees: { question: 'LOdi3',
metacompetence: 'tableaux_graphiques',
Expand All @@ -142,6 +151,7 @@
metacompetence: :renseigner_horaires, score: 1)
create :evenement_reponse,
partie: partie,
position: 5,
donnees: { question: 'LOdi5',
metacompetence: 'situation_dans_lespace' }
partie.situation.questionnaire.questions << question
Expand Down Expand Up @@ -211,7 +221,7 @@
ligne = worksheet.row(2)
expect(ligne[0]).to eq('2.3.3')
expect(ligne[1]).to eq('LOdi2')
expect(ligne[11]).to eq('00:00')
expect(ligne[10]).to be_nil
ligne = worksheet.row(3)
expect(ligne[0]).to eq('2.3.3')
expect(ligne[1]).to eq('LOdi4')
Expand Down

0 comments on commit fff18d6

Please sign in to comment.