Description:
- remove inplace editor from view
- add link to edit announcement directly
- modify submission_short display button
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r598:db36298d10ca - - 4 files changed: 55 inserted, 22 deleted
@@ -1,100 +1,104 | |||
|
1 | 1 | class ReportController < ApplicationController |
|
2 | 2 | |
|
3 | 3 | before_filter :admin_authorization, only: [:login_stat,:submission_stat, :stuck, :cheat_report, :cheat_scruntinize, :show_max_score] |
|
4 | 4 | |
|
5 | 5 | before_filter(only: [:problem_hof]) { |c| |
|
6 | 6 | return false unless authenticate |
|
7 | 7 | |
|
8 | 8 | if GraderConfiguration["right.user_view_submission"] |
|
9 | 9 | return true; |
|
10 | 10 | end |
|
11 | 11 | |
|
12 | 12 | admin_authorization |
|
13 | 13 | } |
|
14 | 14 | |
|
15 | 15 | def max_score |
|
16 | 16 | end |
|
17 | 17 | |
|
18 | + def current_score | |
|
19 | + @problems = Problem.find_available_problems | |
|
20 | + @users = User.includes(:contests).includes(:contest_stat).where(enabled: true) | |
|
21 | + @scorearray = calculate_max_score(problems, users,0,0,{max: true}) | |
|
22 | + | |
|
23 | + #rencer accordingly | |
|
24 | + if params[:commit] == 'download csv' then | |
|
25 | + csv = gen_csv_from_scorearray(@scorearray,@problems) | |
|
26 | + send_data csv, filename: 'max_score.csv' | |
|
27 | + else | |
|
28 | + #render template: 'user_admin/user_stat' | |
|
29 | + render 'current_score' | |
|
30 | + end | |
|
31 | + end | |
|
32 | + | |
|
18 | 33 | def show_max_score |
|
19 | 34 | #process parameters |
|
20 | 35 | #problems |
|
21 | 36 | @problems = [] |
|
22 | 37 | params[:problem_id].each do |id| |
|
23 | 38 | next unless id.strip != "" |
|
24 | 39 | @problems << Problem.find(id.to_i) |
|
25 | 40 | end |
|
26 | 41 | |
|
27 | 42 | #users |
|
28 | 43 | @users = if params[:user] == "all" then |
|
29 | 44 | User.find(:all, :include => [:contests, :contest_stat]) |
|
30 | 45 | else |
|
31 | 46 | User.includes(:contests).includes(:contest_stat).where(enabled: true) |
|
32 | 47 | end |
|
33 | 48 | |
|
34 | 49 | #set up range from param |
|
35 | 50 | since_id = params.fetch(:min_id, 0).to_i |
|
36 | 51 | until_id = params.fetch(:max_id, 0).to_i |
|
37 | 52 | |
|
38 | - #get data | |
|
39 | - @scorearray = Array.new | |
|
40 | - @users.each do |u| | |
|
41 | - ustat = Array.new | |
|
42 | - ustat[0] = u | |
|
43 | - @problems.each do |p| | |
|
44 | - max_points = 0 | |
|
45 | - Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub| | |
|
46 | - max_points = sub.points if sub and sub.points and (sub.points > max_points) | |
|
47 | - end | |
|
48 | - ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)] | |
|
49 | - end | |
|
50 | - @scorearray << ustat | |
|
51 | - end | |
|
53 | + #calculate the routine | |
|
54 | + @scorearray = calculate_max_score(problems, users,since_id,until_id) | |
|
52 | 55 | |
|
56 | + #rencer accordingly | |
|
53 | 57 | if params[:commit] == 'download csv' then |
|
54 | 58 | csv = gen_csv_from_scorearray(@scorearray,@problems) |
|
55 | 59 | send_data csv, filename: 'max_score.csv' |
|
56 | 60 | else |
|
57 | 61 | #render template: 'user_admin/user_stat' |
|
58 | 62 | render 'max_score' |
|
59 | 63 | end |
|
60 | 64 | |
|
61 | 65 | end |
|
62 | 66 | |
|
63 | 67 | def score |
|
64 | 68 | if params[:commit] == 'download csv' |
|
65 | 69 | @problems = Problem.all |
|
66 | 70 | else |
|
67 | 71 | @problems = Problem.find_available_problems |
|
68 | 72 | end |
|
69 | 73 | @users = User.includes(:contests, :contest_stat).where(enabled: true) #find(:all, :include => [:contests, :contest_stat]).where(enabled: true) |
|
70 | 74 | @scorearray = Array.new |
|
71 | 75 | @users.each do |u| |
|
72 | 76 | ustat = Array.new |
|
73 | 77 | ustat[0] = u |
|
74 | 78 | @problems.each do |p| |
|
75 | 79 | sub = Submission.find_last_by_user_and_problem(u.id,p.id) |
|
76 | 80 | if (sub!=nil) and (sub.points!=nil) and p and p.full_score |
|
77 | 81 | ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)] |
|
78 | 82 | else |
|
79 | 83 | ustat << [0,false] |
|
80 | 84 | end |
|
81 | 85 | end |
|
82 | 86 | @scorearray << ustat |
|
83 | 87 | end |
|
84 | 88 | if params[:commit] == 'download csv' then |
|
85 | 89 | csv = gen_csv_from_scorearray(@scorearray,@problems) |
|
86 | 90 | send_data csv, filename: 'last_score.csv' |
|
87 | 91 | else |
|
88 | 92 | render template: 'user_admin/user_stat' |
|
89 | 93 | end |
|
90 | 94 | |
|
91 | 95 | end |
|
92 | 96 | |
|
93 | 97 | def login_stat |
|
94 | 98 | @logins = Array.new |
|
95 | 99 | |
|
96 | 100 | date_and_time = '%Y-%m-%d %H:%M' |
|
97 | 101 | begin |
|
98 | 102 | md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/) |
|
99 | 103 | @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i) |
|
100 | 104 | rescue |
@@ -403,50 +407,78 | |||
|
403 | 407 | end |
|
404 | 408 | |
|
405 | 409 | def cheat_scruntinize |
|
406 | 410 | #convert date & time |
|
407 | 411 | date_and_time = '%Y-%m-%d %H:%M' |
|
408 | 412 | begin |
|
409 | 413 | md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/) |
|
410 | 414 | @since_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i) |
|
411 | 415 | rescue |
|
412 | 416 | @since_time = Time.zone.now.ago( 90.minutes) |
|
413 | 417 | end |
|
414 | 418 | begin |
|
415 | 419 | md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/) |
|
416 | 420 | @until_time = Time.zone.local(md[1].to_i,md[2].to_i,md[3].to_i,md[4].to_i,md[5].to_i) |
|
417 | 421 | rescue |
|
418 | 422 | @until_time = Time.zone.now |
|
419 | 423 | end |
|
420 | 424 | |
|
421 | 425 | #convert sid |
|
422 | 426 | @sid = params[:SID].split(/[,\s]/) if params[:SID] |
|
423 | 427 | unless @sid and @sid.size > 0 |
|
424 | 428 | return |
|
425 | 429 | redirect_to actoin: :cheat_scruntinize |
|
426 | 430 | flash[:notice] = 'Please enter at least 1 student id' |
|
427 | 431 | end |
|
428 | 432 | mark = Array.new(@sid.size,'?') |
|
429 | 433 | condition = "(u.login = " + mark.join(' OR u.login = ') + ')' |
|
430 | 434 | |
|
431 | 435 | @st = <<-SQL |
|
432 | 436 | SELECT l.created_at as submitted_at ,-1 as id,u.login,u.full_name,l.ip_address,"" as problem_id,"" as points,l.user_id |
|
433 | 437 | FROM logins l INNER JOIN users u on l.user_id = u.id |
|
434 | 438 | WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition} |
|
435 | 439 | UNION |
|
436 | 440 | SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id |
|
437 | 441 | FROM submissions s INNER JOIN users u ON s.user_id = u.id |
|
438 | 442 | WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition} |
|
439 | 443 | ORDER BY submitted_at |
|
440 | 444 | SQL |
|
441 | 445 | |
|
442 | 446 | p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid |
|
443 | 447 | @logs = Submission.joins(:problem).find_by_sql(p) |
|
444 | 448 | |
|
445 | 449 | |
|
446 | 450 | |
|
447 | 451 | |
|
448 | 452 | |
|
449 | 453 | end |
|
450 | 454 | |
|
455 | + protected | |
|
456 | + | |
|
457 | + def calculate_max_score(problems, users,since_id,until_id, get_last_score = false) | |
|
458 | + scorearray = Array.new | |
|
459 | + users.each do |u| | |
|
460 | + ustat = Array.new | |
|
461 | + ustat[0] = u | |
|
462 | + problems.each do |p| | |
|
463 | + unless get_last_score | |
|
464 | + #get max score | |
|
465 | + max_points = 0 | |
|
466 | + Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub| | |
|
467 | + max_points = sub.points if sub and sub.points and (sub.points > max_points) | |
|
468 | + end | |
|
469 | + ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)] | |
|
470 | + else | |
|
471 | + #get latest score | |
|
472 | + sub = Submission.find_last_by_user_and_problem(u.id,p.id) | |
|
473 | + if (sub!=nil) and (sub.points!=nil) and p and p.full_score | |
|
474 | + ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)] | |
|
475 | + else | |
|
476 | + ustat << [0,false] | |
|
477 | + end | |
|
478 | + end | |
|
479 | + scorearray << ustat | |
|
480 | + end | |
|
481 | + return scorearray | |
|
482 | + end | |
|
451 | 483 | |
|
452 | 484 | end |
@@ -1,13 +1,15 | |||
|
1 | 1 | %li.list-group-item |
|
2 | 2 | %strong |
|
3 | 3 | = announcement.title |
|
4 | + - if @current_user.admin? | |
|
5 | + = link_to 'Edit', edit_announcement_path(announcement), class: 'btn btn-xs btn-default' | |
|
4 | 6 | %small= "(updated #{time_ago_in_words(announcement.updated_at)} ago on #{announcement.updated_at})" |
|
5 | 7 | |
|
6 | 8 | %br |
|
7 | 9 | = markdown(announcement.body) |
|
8 | 10 | :javascript |
|
9 | 11 | Announcement.updateRecentId(#{announcement.id}); |
|
10 | 12 | - if (defined? announcement_effect) and announcement_effect |
|
11 | 13 | :javascript |
|
12 | 14 | $("announcement-#{announcement.id}").blindDown({duration: 0.2}); |
|
13 | 15 | $("announcement-#{announcement.id}").appear({duration: 0.5, queue: 'end'}); |
@@ -1,27 +1,26 | |||
|
1 | 1 | |
|
2 | 2 | - if submission.nil? |
|
3 | 3 | = "-" |
|
4 | 4 | - else |
|
5 | 5 | - if submission.graded_at.nil? |
|
6 | 6 | = t 'main.submitted_at' |
|
7 | 7 | = format_short_time(submission.submitted_at.localtime) |
|
8 | 8 | - else |
|
9 | 9 | %strong= t 'main.graded_at' |
|
10 | 10 | = "#{format_short_time(submission.graded_at.localtime)} " |
|
11 | 11 | %br |
|
12 | 12 | - if GraderConfiguration['ui.show_score'] |
|
13 | 13 | %strong= t 'main.score' |
|
14 | 14 | = "#{(submission.points*100/submission.problem.full_score).to_i} " |
|
15 | 15 | = " [" |
|
16 | 16 | %tt |
|
17 | 17 | = submission.grader_comment |
|
18 | 18 | = "]" |
|
19 | 19 | %br |
|
20 | 20 | %strong View: |
|
21 | 21 | - if GraderConfiguration.show_grading_result |
|
22 | 22 | = link_to '[detailed result]', :action => 'result', :id => submission.id |
|
23 |
- = link_to |
|
|
24 | - = " | " | |
|
25 | - = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id}) | |
|
26 | - = " | " | |
|
27 | - = link_to "[#{t 'main.submissions_link'}]", problem_submissions_path(problem_id) | |
|
23 | + = link_to "#{t 'main.cmp_msg'}", {:action => 'compiler_msg', :id => submission.id}, {popup: true,class: 'btn btn-xs btn-info'} | |
|
24 | + = link_to "#{t 'main.src_link'}",{:action => 'source', :id => submission.id}, class: 'btn btn-xs btn-info' | |
|
25 | + = link_to "#{t 'main.submissions_link'}", problem_submissions_path(problem_id), class: 'btn btn-xs btn-info' | |
|
26 | + |
@@ -1,50 +1,50 | |||
|
1 | 1 | - content_for :head do |
|
2 | 2 | = stylesheet_link_tag 'problems' |
|
3 | 3 | %h1 Listing problems |
|
4 | 4 | %p |
|
5 | 5 | = link_to 'New problem', new_problem_path, class: 'btn btn-default btn-sm' |
|
6 | 6 | = link_to 'Manage problems', { action: 'manage'}, class: 'btn btn-default btn-sm' |
|
7 | 7 | = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-default btn-sm' |
|
8 | 8 | = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm' |
|
9 | 9 | = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm' |
|
10 | 10 | .submitbox |
|
11 | 11 | = form_tag :action => 'quick_create' do |
|
12 | 12 | %b Quick New: |
|
13 | 13 | %label{:for => "problem_name"} Name |
|
14 | 14 | = text_field 'problem', 'name' |
|
15 | 15 | | |
|
16 | 16 | %label{:for => "problem_full_name"} Full name |
|
17 | 17 | = text_field 'problem', 'full_name' |
|
18 | 18 | = submit_tag "Create" |
|
19 | 19 | %table.table.table-condense.table-hover |
|
20 | 20 | %thead |
|
21 | 21 | %th Name |
|
22 | 22 | %th Full name |
|
23 | 23 | %th.text-right Full score |
|
24 | 24 | %th Date added |
|
25 | 25 | %th.text-center |
|
26 | 26 | Avail? |
|
27 | 27 | %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?] |
|
28 | 28 | %th.text-center |
|
29 | 29 | Test? |
|
30 | 30 | %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?] |
|
31 | 31 | - if GraderConfiguration.multicontests? |
|
32 | 32 | %th Contests |
|
33 | 33 | - for problem in @problems |
|
34 | 34 | %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"} |
|
35 | 35 | - @problem=problem |
|
36 |
- %td= |
|
|
37 |
- %td= |
|
|
38 |
- %td.text-right= |
|
|
36 | + %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1 | |
|
37 | + %td= problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1 | |
|
38 | + %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1 | |
|
39 | 39 | %td= problem.date_added |
|
40 | 40 | %td= toggle_button(@problem.available?, toggle_problem_url(@problem), "problem-avail-#{@problem.id}") |
|
41 | 41 | %td= toggle_button(@problem.test_allowed?, toggle_test_problem_url(@problem), "problem-test-#{@problem.id}") |
|
42 | 42 | - if GraderConfiguration.multicontests? |
|
43 | 43 | %td |
|
44 | 44 | = problem.contests.collect { |c| c.name }.join(', ') |
|
45 | 45 | %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block' |
|
46 | 46 | %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block' |
|
47 | 47 | %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block' |
|
48 | 48 | %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :post, class: 'btn btn-danger btn-xs btn-block' |
|
49 | 49 | %br/ |
|
50 | 50 | = link_to '[New problem]', :action => 'new' |
You need to be logged in to leave comments.
Login now