Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance Export Functionality with PLD and GDU Metrics #2250

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

RongYYYY
Copy link

@RongYYYY RongYYYY commented Dec 8, 2024

Description

This pull request enhances the export functionality of assessments by including Presumably Late Days (PLD) and Grade Distribution Usage (GDU) metrics. These metrics are now calculated for each assessment and included in the exported tarball as separate YAML files, PLD.yml and GDU.yml.

Motivation and Context

This change provides educators and administrators with more detailed insights into assessment performance and submission timeliness, aiding in better academic decision-making. This enhancement does not fix a specific issue but adds significant functionality to the existing export capabilities.

How Has This Been Tested?

The new export functionality was tested in a local development environment where:

  • Multiple assessments with varied due dates and submission times were used to generate the PLD

Attempt for issue: #1733

Copy link
Contributor

coderabbitai bot commented Dec 8, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request introduces enhancements to the AssessmentsController and the Assessment model. It adds functionality for exporting assessment data, specifically calculating and including Program Level Data (PLD) and Grade Distribution Unit (GDU) metrics in a tarball. The export method is updated to handle these new metrics and includes improved error handling. Additionally, two new methods, calculate_pld and calculate_gdu, are added to the Assessment class to compute late days for submissions and generate grade distributions, respectively.

Changes

File Change Summary
app/controllers/assessments_controller.rb - Updated export method to include PLD and GDU data in the tarball.
- Enhanced error handling with specific rescue clauses for exceptions.
app/models/assessment.rb - Added calculate_pld method to compute late days for submissions.
- Added calculate_gdu method to generate grade distributions based on scores.

Possibly related PRs

  • add validation of yaml fields before loading them during import #2181: The changes in this PR involve modifications to the Assessment class in app/models/assessment.rb, specifically adding a new method validate_yaml, which is related to the handling of YAML files. This is connected to the main PR's enhancements to the export method that generates YAML files, as both involve the management and validation of YAML data associated with assessments.

Suggested reviewers

  • KesterTan

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
app/models/assessment.rb (1)

478-478: Consider making grade boundaries configurable

The grade boundaries are currently hardcoded. Consider making them configurable through course settings or assessment configuration.

-    grade_boundaries = { 'A': 90, 'B': 80, 'C': 70, 'D': 60, 'F': 0 }
+    grade_boundaries = course.grade_boundaries || { 'A': 90, 'B': 80, 'C': 70, 'D': 60, 'F': 0 }
app/controllers/assessments_controller.rb (2)

509-515: Fix octal literals and remove trailing whitespace

  1. Use 0o prefix for octal literals instead of implicit octal
  2. Remove trailing whitespace on line 516
-        tar.add_file_simple("PLD.yml", 0644, pld_data.bytesize) do |io|
+        tar.add_file_simple("PLD.yml", 0o644, pld_data.bytesize) do |io|
           io.write pld_data
         end
 
-        tar.add_file_simple("GDU.yml", 0644, gdu_data.bytesize) do |io|
+        tar.add_file_simple("GDU.yml", 0o644, gdu_data.bytesize) do |io|
           io.write gdu_data
         end
-        
+
🧰 Tools
🪛 rubocop (1.68.0)

[convention] 509-509: Use 0o for octal literals.

(Style/NumericLiteralPrefix)


[convention] 513-513: Use 0o for octal literals.

(Style/NumericLiteralPrefix)


Line range hint 492-516: Consider adding error handling for PLD and GDU calculations

The export method should handle potential errors from PLD and GDU calculations.

+    begin
       pld_data = @assessment.calculate_pld.to_yaml
       gdu_data = @assessment.calculate_gdu.to_yaml
+    rescue StandardError => e
+      flash[:error] = "Error calculating assessment metrics: #{e.message}"
+      redirect_to action: "index"
+      return
+    end

     begin
       # Update the assessment config YAML file.
🧰 Tools
🪛 rubocop (1.68.0)

[convention] 509-509: Use 0o for octal literals.

(Style/NumericLiteralPrefix)


[convention] 513-513: Use 0o for octal literals.

(Style/NumericLiteralPrefix)


[convention] 516-516: Trailing whitespace detected.

(Layout/TrailingWhitespace)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between fe44b53 and 580adc2.

📒 Files selected for processing (2)
  • app/controllers/assessments_controller.rb (2 hunks)
  • app/models/assessment.rb (1 hunks)
🧰 Additional context used
🪛 rubocop (1.68.0)
app/models/assessment.rb

[warning] 486-486: Shadowing outer local variable - grade.

(Lint/ShadowingOuterLocalVariable)

app/controllers/assessments_controller.rb

[convention] 509-509: Use 0o for octal literals.

(Style/NumericLiteralPrefix)


[convention] 513-513: Use 0o for octal literals.

(Style/NumericLiteralPrefix)


[convention] 516-516: Trailing whitespace detected.

(Layout/TrailingWhitespace)

Comment on lines +482 to +488
total_submissions = submissions.joins(:scores).count
submissions.includes(:scores).each do |submission|
# Assuming 'score' is a method that sums up scores for a submission
score = submission.scores.sum(&:points)
grade = grade_boundaries.keys.reverse.detect { |grade| score >= grade_boundaries[grade] }
distribution[grade] += 1
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix variable shadowing and add error handling

There are several issues to address:

  1. The grade variable on line 486 shadows the outer variable
  2. Need to handle edge case of no submissions
  3. Need to handle nil scores
-    total_submissions = submissions.joins(:scores).count
-    submissions.includes(:scores).each do |submission|
-      # Assuming 'score' is a method that sums up scores for a submission
-      score = submission.scores.sum(&:points)
-      grade = grade_boundaries.keys.reverse.detect { |grade| score >= grade_boundaries[grade] }
-      distribution[grade] += 1
+    submissions_with_scores = submissions.includes(:scores).select { |s| s.scores.any? }
+    total_submissions = submissions_with_scores.length
+    
+    return {} if total_submissions.zero?
+    
+    submissions_with_scores.each do |submission|
+      score = submission.scores.sum(&:points)
+      letter_grade = grade_boundaries.keys.reverse.detect { |g| score >= grade_boundaries[g] }
+      distribution[letter_grade] += 1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
total_submissions = submissions.joins(:scores).count
submissions.includes(:scores).each do |submission|
# Assuming 'score' is a method that sums up scores for a submission
score = submission.scores.sum(&:points)
grade = grade_boundaries.keys.reverse.detect { |grade| score >= grade_boundaries[grade] }
distribution[grade] += 1
end
submissions_with_scores = submissions.includes(:scores).select { |s| s.scores.any? }
total_submissions = submissions_with_scores.length
return {} if total_submissions.zero?
submissions_with_scores.each do |submission|
score = submission.scores.sum(&:points)
letter_grade = grade_boundaries.keys.reverse.detect { |g| score >= grade_boundaries[g] }
distribution[letter_grade] += 1
🧰 Tools
🪛 rubocop (1.68.0)

[warning] 486-486: Shadowing outer local variable - grade.

(Lint/ShadowingOuterLocalVariable)

Comment on lines +467 to +473
# Public method to access the PLD data
def calculate_pld
submissions.includes(:scores).map do |submission|
late_days = [(submission.created_at.to_date - due_at.to_date).to_i, 0].max
{ submission_id: submission.id, late_days: late_days }
end
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider handling edge cases and enriching the PLD data

The implementation could be enhanced in the following ways:

  1. Handle edge cases like nil due dates
  2. Consider assessment extensions in late day calculations
  3. Include grace days information
  4. Add submission metadata like student info and timestamps
 def calculate_pld
-  submissions.includes(:scores).map do |submission|
-    late_days = [(submission.created_at.to_date - due_at.to_date).to_i, 0].max
-    { submission_id: submission.id, late_days: late_days }
+  raise "Assessment due date not set" if due_at.nil?
+  
+  submissions.includes(:scores, :course_user_datum).map do |submission|
+    extension = extensions.find_by(course_user_datum_id: submission.course_user_datum_id)
+    effective_due_at = extension ? extension.due_at : due_at
+    late_days = [(submission.created_at.to_date - effective_due_at.to_date).to_i, 0].max
+    {
+      submission_id: submission.id,
+      student_email: submission.course_user_datum.user.email,
+      submitted_at: submission.created_at,
+      late_days: late_days,
+      grace_days_used: submission.grace_days_used || 0,
+      extension_days: extension ? (extension.due_at.to_date - due_at.to_date).to_i : 0
+    }
   end
 end

Committable suggestion skipped: line range outside the PR's diff.

@davidhmnng
Copy link

For error handling, could consider adding validation to ensure the late_days calculation doesn't break if a submission or due_at date is nil.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
app/controllers/assessments_controller.rb (2)

507-516: Reduce code duplication in file writing logic.

The file writing logic for PLD.yml and GDU.yml is duplicated. Consider extracting it into a helper method.

+    def add_yaml_to_tar(tar, filename, data)
+      tar.add_file_simple(filename, 0644, data.bytesize) do |io|
+        io.write data
+      end
+    end
+
-        tar.add_file_simple("PLD.yml", 0o644, pld_data.bytesize) do |io|
-          io.write pld_data
-        end
-
-        tar.add_file_simple("GDU.yml", 0o644, gdu_data.bytesize) do |io|
-          io.write gdu_data
-        end
+        add_yaml_to_tar(tar, "PLD.yml", pld_data)
+        add_yaml_to_tar(tar, "GDU.yml", gdu_data)

517-517: Remove trailing whitespace.

There is trailing whitespace on this line that should be removed.

-        
+
🧰 Tools
🪛 rubocop (1.68.0)

[convention] 517-517: Trailing whitespace detected.

(Layout/TrailingWhitespace)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 580adc2 and bd58ac2.

📒 Files selected for processing (1)
  • app/controllers/assessments_controller.rb (2 hunks)
🧰 Additional context used
🪛 rubocop (1.68.0)
app/controllers/assessments_controller.rb

[convention] 517-517: Trailing whitespace detected.

(Layout/TrailingWhitespace)

Comment on lines +492 to +494

pld_data = @assessment.calculate_pld.to_yaml
gdu_data = @assessment.calculate_gdu.to_yaml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for PLD and GDU calculations.

The calls to calculate_pld and calculate_gdu should be wrapped in error handling to gracefully handle potential calculation failures.

-    pld_data = @assessment.calculate_pld.to_yaml
-    gdu_data = @assessment.calculate_gdu.to_yaml
+    begin
+      pld_data = @assessment.calculate_pld.to_yaml
+      gdu_data = @assessment.calculate_gdu.to_yaml
+    rescue StandardError => e
+      flash[:error] = "Unable to calculate PLD/GDU metrics -- #{e.message}"
+      redirect_to action: "index"
+      return
+    end
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
pld_data = @assessment.calculate_pld.to_yaml
gdu_data = @assessment.calculate_gdu.to_yaml
begin
pld_data = @assessment.calculate_pld.to_yaml
gdu_data = @assessment.calculate_gdu.to_yaml
rescue StandardError => e
flash[:error] = "Unable to calculate PLD/GDU metrics -- #{e.message}"
redirect_to action: "index"
return
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants