Skip to content

Commit 42f081b

Browse files
committed
Implement model solution tokens
1 parent 456a34d commit 42f081b

10 files changed

+147
-17
lines changed

app/controllers/api/v8/organizations/courses/exercises_controller.rb

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,20 @@ def show
8181
course = organization.courses.find_by!(name: params[:course_name]) unless course
8282
ex = course.exercises.find_by!(name: params[:name])
8383
authorize! :read, ex
84-
present({
84+
85+
model_solution_token_used_on_this_exercise = tokens_used = ModelSolutionTokenUsed.where(user: current_user, course: course, exercise_name: ex.name).count > 0
86+
87+
total_model_solution_tokens = 0
88+
grant_model_solution_token_every_nth_completed_exercise = course.grant_model_solution_token_every_nth_completed_exercise
89+
if grant_model_solution_token_every_nth_completed_exercise && grant_model_solution_token_every_nth_completed_exercise > 0
90+
completed_exercises_count = course.submissions.where(all_tests_passed: true, user: current_user).distinct.select(:exercise_name).count
91+
total_model_solution_tokens = completed_exercises_count / grant_model_solution_token_every_nth_completed_exercise
92+
93+
tokens_used = ModelSolutionTokenUsed.where(user: current_user, course: course).count
94+
available_model_solution_tokens = total_model_solution_tokens - tokens_used
95+
end
96+
97+
present(
8598
id: ex.id,
8699
available_points: ex.available_points,
87100
name: ex.name,
@@ -90,8 +103,14 @@ def show
90103
soft_deadline: ex.soft_deadline_for(current_user),
91104
expired: ex.expired_for?(current_user),
92105
disabled: ex.disabled?,
93-
completed: ex.completed_by?(current_user)
94-
})
106+
completed: ex.completed_by?(current_user),
107+
model_solution_token_used_on_this_exercise: model_solution_token_used_on_this_exercise,
108+
course: {
109+
grant_model_solution_token_every_nth_completed_exercise: grant_model_solution_token_every_nth_completed_exercise,
110+
total_model_solution_tokens: total_model_solution_tokens,
111+
available_model_solution_tokens: available_model_solution_tokens,
112+
}
113+
)
95114
end
96115

97116
def download

app/controllers/application_controller.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@ def unauthorize_guest!(message = 'Authentication required')
128128
unauthorized!(message) if current_user.guest?
129129
end
130130

131+
def only_admins!
132+
unauthorized! unless current_user.administrator?
133+
end
134+
131135
def authorization_skip!
132136
authorize! :read, nil
133137
end
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# frozen_string_literal: true
2+
3+
class ModelSolutionTokenUsedsController < ApplicationController
4+
before_action :set_model_solution_token_used, only: [:show, :edit, :update, :destroy]
5+
before_action :only_admins
6+
7+
# GET /model_solution_token_useds
8+
def index
9+
@model_solution_token_useds = ModelSolutionTokenUsed.all
10+
end
11+
12+
# GET /model_solution_token_useds/1
13+
def show
14+
end
15+
16+
private
17+
# Use callbacks to share common setup or constraints between actions.
18+
def set_model_solution_token_used
19+
@model_solution_token_used = ModelSolutionTokenUsed.find(params[:id])
20+
end
21+
22+
# Only allow a trusted parameter "white list" through.
23+
def model_solution_token_used_params
24+
params.require(:model_solution_token_used).permit(:user_id, :course_id, :exercise_name)
25+
end
26+
end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# frozen_string_literal: true
2+
3+
class ModelSolutionTokenUsed < ActiveRecord::Base
4+
belongs_to :user
5+
belongs_to :course
6+
7+
validates :exercise_name, presence: true
8+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<p id="notice"><%= notice %></p>
2+
3+
<h1>Listing Model Solution Token Useds</h1>
4+
5+
<table>
6+
<thead>
7+
<tr>
8+
<th>User</th>
9+
<th>Course</th>
10+
<th>Exercise name</th>
11+
<th colspan="3"></th>
12+
</tr>
13+
</thead>
14+
15+
<tbody>
16+
<% @model_solution_token_useds.each do |model_solution_token_used| %>
17+
<tr>
18+
<td><%= model_solution_token_used.user %></td>
19+
<td><%= model_solution_token_used.course %></td>
20+
<td><%= model_solution_token_used.exercise_name %></td>
21+
<td><%= link_to 'Show', model_solution_token_used %></td>
22+
<td><%= link_to 'Edit', edit_model_solution_token_used_path(model_solution_token_used) %></td>
23+
<td><%= link_to 'Destroy', model_solution_token_used, method: :delete, data: { confirm: 'Are you sure?' } %></td>
24+
</tr>
25+
<% end %>
26+
</tbody>
27+
</table>
28+
29+
<br>
30+
31+
<%= link_to 'New Model solution token used', new_model_solution_token_used_path %>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<p id="notice"><%= notice %></p>
2+
3+
<p>
4+
<strong>User:</strong>
5+
<%= @model_solution_token_used.user %>
6+
</p>
7+
8+
<p>
9+
<strong>Course:</strong>
10+
<%= @model_solution_token_used.course %>
11+
</p>
12+
13+
<p>
14+
<strong>Exercise name:</strong>
15+
<%= @model_solution_token_used.exercise_name %>
16+
</p>
17+
18+
<%= link_to 'Edit', edit_model_solution_token_used_path(@model_solution_token_used) %> |
19+
<%= link_to 'Back', model_solution_token_useds_path %>

config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@
289289

290290
resources :status, only: [:index]
291291

292+
resources :model_solution_token_useds, only: [:index, :show]
293+
292294
if SiteSetting.value('pghero_enabled')
293295
constraints CanAccessPgHero do
294296
mount PgHero::Engine, at: 'pghero'
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# frozen_string_literal: true
2+
3+
class AddGrantModelSolutionTokenEveryNthCompletedExerciseToCourse < ActiveRecord::Migration
4+
def change
5+
add_column :courses, :grant_model_solution_token_every_nth_completed_exercise, :integer, null: true
6+
end
7+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# frozen_string_literal: true
2+
3+
class CreateModelSolutionTokenUseds < ActiveRecord::Migration
4+
def change
5+
create_table :model_solution_token_useds do |t|
6+
t.references :user, index: true, foreign_key: true
7+
t.references :course, index: true, foreign_key: true
8+
t.string :exercise_name
9+
10+
t.timestamps null: false
11+
end
12+
end
13+
end

db/schema.rb

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#
1212
# It's strongly recommended that you check this file into your version control system.
1313

14-
ActiveRecord::Schema.define(version: 20181003140911) do
14+
ActiveRecord::Schema.define(version: 20181213161532) do
1515

1616
# These are extensions that must be enabled in order to support this database
1717
enable_extension "plpgsql"
@@ -94,29 +94,30 @@
9494
t.datetime "created_at"
9595
t.datetime "updated_at"
9696
t.datetime "hide_after"
97-
t.boolean "hidden", default: false, null: false
98-
t.integer "cached_version", default: 0, null: false
97+
t.boolean "hidden", default: false, null: false
98+
t.integer "cached_version", default: 0, null: false
9999
t.string "spreadsheet_key"
100100
t.datetime "hidden_if_registered_after"
101101
t.datetime "refreshed_at"
102-
t.boolean "locked_exercise_points_visible", default: true, null: false
102+
t.boolean "locked_exercise_points_visible", default: true, null: false
103103
t.text "description"
104104
t.string "paste_visibility"
105105
t.string "formal_name"
106-
t.boolean "certificate_downloadable", default: false, null: false
106+
t.boolean "certificate_downloadable", default: false, null: false
107107
t.string "certificate_unlock_spec"
108108
t.integer "organization_id"
109-
t.integer "disabled_status", default: 1
109+
t.integer "disabled_status", default: 1
110110
t.string "title"
111111
t.string "material_url"
112-
t.integer "course_template_id", null: false
113-
t.boolean "hide_submission_results", default: false
112+
t.integer "course_template_id", null: false
113+
t.boolean "hide_submission_results", default: false
114114
t.string "external_scoreboard_url"
115-
t.boolean "initial_refresh_ready", default: false
116-
t.boolean "hide_submissions", default: false, null: false
117-
t.boolean "model_solution_visible_before_completion", default: false, null: false
118-
t.float "soft_deadline_point_multiplier", default: 0.75, null: false
119-
t.boolean "code_review_requests_enabled", default: true, null: false
115+
t.boolean "initial_refresh_ready", default: false
116+
t.boolean "hide_submissions", default: false, null: false
117+
t.boolean "model_solution_visible_before_completion", default: false, null: false
118+
t.float "soft_deadline_point_multiplier", default: 0.75, null: false
119+
t.boolean "code_review_requests_enabled", default: true, null: false
120+
t.integer "grant_model_solution_token_every_nth_completed_exercise"
120121
end
121122

122123
add_index "courses", ["organization_id"], name: "index_courses_on_organization_id", using: :btree
@@ -181,7 +182,7 @@
181182

182183
add_index "migrated_submissions", ["from_course_id", "to_course_id", "original_submission_id", "new_submission_id"], name: "unique_values", unique: true, using: :btree
183184

184-
create_table "model_solution_access_log", force: :cascade do |t|
185+
create_table "model_solution_access_logs", force: :cascade do |t|
185186
t.integer "user_id", null: false
186187
t.integer "course_id", null: false
187188
t.string "exercise_name", null: false

0 commit comments

Comments
 (0)