Description:
fix display bugs in corrent score
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r782:97cd56a5f1d8 - - 3 files changed: 5 inserted, 4 deleted

@@ -276,251 +276,252
276 276 @summary[:attempt] = user.count
277 277 user.each_value { |v| @summary[:solve] += 1 if v == 1 }
278 278 end
279 279
280 280 def stuck #report struggling user,problem
281 281 # init
282 282 user,problem = nil
283 283 solve = true
284 284 tries = 0
285 285 @struggle = Array.new
286 286 record = {}
287 287 Submission.includes(:problem,:user).order(:problem_id,:user_id).find_each do |sub|
288 288 next unless sub.problem and sub.user
289 289 if user != sub.user_id or problem != sub.problem_id
290 290 @struggle << { user: record[:user], problem: record[:problem], tries: tries } unless solve
291 291 record = {user: sub.user, problem: sub.problem}
292 292 user,problem = sub.user_id, sub.problem_id
293 293 solve = false
294 294 tries = 0
295 295 end
296 296 if sub.points >= sub.problem.full_score
297 297 solve = true
298 298 else
299 299 tries += 1
300 300 end
301 301 end
302 302 @struggle.sort!{|a,b| b[:tries] <=> a[:tries] }
303 303 @struggle = @struggle[0..50]
304 304 end
305 305
306 306
307 307 def multiple_login
308 308 #user with multiple IP
309 309 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:login)
310 310 last,count = 0,0
311 311 first = 0
312 312 @users = []
313 313 raw.each do |r|
314 314 if last != r.user.login
315 315 count = 1
316 316 last = r.user.login
317 317 first = r
318 318 else
319 319 @users << first if count == 1
320 320 @users << r
321 321 count += 1
322 322 end
323 323 end
324 324
325 325 #IP with multiple user
326 326 raw = Submission.joins(:user).joins(:problem).where("problems.available != 0").group("login,ip_address").order(:ip_address)
327 327 last,count = 0,0
328 328 first = 0
329 329 @ip = []
330 330 raw.each do |r|
331 331 if last != r.ip_address
332 332 count = 1
333 333 last = r.ip_address
334 334 first = r
335 335 else
336 336 @ip << first if count == 1
337 337 @ip << r
338 338 count += 1
339 339 end
340 340 end
341 341 end
342 342
343 343 def cheat_report
344 344 date_and_time = '%Y-%m-%d %H:%M'
345 345 begin
346 346 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
347 347 @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)
348 348 rescue
349 349 @since_time = Time.zone.now.ago( 90.minutes)
350 350 end
351 351 begin
352 352 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
353 353 @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)
354 354 rescue
355 355 @until_time = Time.zone.now
356 356 end
357 357
358 358 #multi login
359 359 @ml = Login.joins(:user).where("logins.created_at >= ? and logins.created_at <= ?",@since_time,@until_time).select('users.login,count(distinct ip_address) as count,users.full_name').group("users.id").having("count > 1")
360 360
361 361 st = <<-SQL
362 362 SELECT l2.*
363 363 FROM logins l2 INNER JOIN
364 364 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
365 365 FROM logins l
366 366 INNER JOIN users u ON l.user_id = u.id
367 367 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
368 368 GROUP BY u.id
369 369 HAVING count > 1
370 370 ) ml ON l2.user_id = ml.id
371 371 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
372 372 UNION
373 373 SELECT l2.*
374 374 FROM logins l2 INNER JOIN
375 375 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
376 376 FROM logins l
377 377 INNER JOIN users u ON l.user_id = u.id
378 378 WHERE l.created_at >= '#{@since_time.in_time_zone("UTC")}' and l.created_at <= '#{@until_time.in_time_zone("UTC")}'
379 379 GROUP BY l.ip_address
380 380 HAVING count > 1
381 381 ) ml on ml.ip_address = l2.ip_address
382 382 INNER JOIN users u ON l2.user_id = u.id
383 383 WHERE l2.created_at >= '#{@since_time.in_time_zone("UTC")}' and l2.created_at <= '#{@until_time.in_time_zone("UTC")}'
384 384 ORDER BY ip_address,created_at
385 385 SQL
386 386 @mld = Login.find_by_sql(st)
387 387
388 388 st = <<-SQL
389 389 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
390 390 FROM submissions s INNER JOIN
391 391 (SELECT u.id,COUNT(DISTINCT ip_address) as count,u.login,u.full_name
392 392 FROM logins l
393 393 INNER JOIN users u ON l.user_id = u.id
394 394 WHERE l.created_at >= ? and l.created_at <= ?
395 395 GROUP BY u.id
396 396 HAVING count > 1
397 397 ) ml ON s.user_id = ml.id
398 398 WHERE s.submitted_at >= ? and s.submitted_at <= ?
399 399 UNION
400 400 SELECT s.id,s.user_id,s.ip_address,s.submitted_at,s.problem_id
401 401 FROM submissions s INNER JOIN
402 402 (SELECT l.ip_address,COUNT(DISTINCT u.id) as count
403 403 FROM logins l
404 404 INNER JOIN users u ON l.user_id = u.id
405 405 WHERE l.created_at >= ? and l.created_at <= ?
406 406 GROUP BY l.ip_address
407 407 HAVING count > 1
408 408 ) ml on ml.ip_address = s.ip_address
409 409 WHERE s.submitted_at >= ? and s.submitted_at <= ?
410 410 ORDER BY ip_address,submitted_at
411 411 SQL
412 412 @subs = Submission.joins(:problem).find_by_sql([st,@since_time,@until_time,
413 413 @since_time,@until_time,
414 414 @since_time,@until_time,
415 415 @since_time,@until_time])
416 416
417 417 end
418 418
419 419 def cheat_scruntinize
420 420 #convert date & time
421 421 date_and_time = '%Y-%m-%d %H:%M'
422 422 begin
423 423 md = params[:since_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
424 424 @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)
425 425 rescue
426 426 @since_time = Time.zone.now.ago( 90.minutes)
427 427 end
428 428 begin
429 429 md = params[:until_datetime].match(/(\d+)-(\d+)-(\d+) (\d+):(\d+)/)
430 430 @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)
431 431 rescue
432 432 @until_time = Time.zone.now
433 433 end
434 434
435 435 #convert sid
436 436 @sid = params[:SID].split(/[,\s]/) if params[:SID]
437 437 unless @sid and @sid.size > 0
438 438 return
439 439 redirect_to actoin: :cheat_scruntinize
440 440 flash[:notice] = 'Please enter at least 1 student id'
441 441 end
442 442 mark = Array.new(@sid.size,'?')
443 443 condition = "(u.login = " + mark.join(' OR u.login = ') + ')'
444 444
445 445 @st = <<-SQL
446 446 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
447 447 FROM logins l INNER JOIN users u on l.user_id = u.id
448 448 WHERE l.created_at >= ? AND l.created_at <= ? AND #{condition}
449 449 UNION
450 450 SELECT s.submitted_at,s.id,u.login,u.full_name,s.ip_address,s.problem_id,s.points,s.user_id
451 451 FROM submissions s INNER JOIN users u ON s.user_id = u.id
452 452 WHERE s.submitted_at >= ? AND s.submitted_at <= ? AND #{condition}
453 453 ORDER BY submitted_at
454 454 SQL
455 455
456 456 p = [@st,@since_time,@until_time] + @sid + [@since_time,@until_time] + @sid
457 457 @logs = Submission.joins(:problem).find_by_sql(p)
458 458
459 459
460 460
461 461
462 462
463 463 end
464 464
465 465 protected
466 466
467 467 def calculate_max_score(problems, users,since_id,until_id, get_last_score = false)
468 + #score[i] = user #i's user stat where i is the index (not id)
468 469 scorearray = Array.new
469 470 users.each do |u|
470 471 ustat = Array.new
471 472 ustat[0] = u
472 473 problems.each do |p|
473 474 unless get_last_score
474 475 #get max score
475 476 max_points = 0
476 477 Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub|
477 478 max_points = sub.points if sub and sub.points and (sub.points > max_points)
478 479 end
479 480 ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)]
480 481 else
481 482 #get latest score
482 483 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
483 484 if (sub!=nil) and (sub.points!=nil) and p and p.full_score
484 485 ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)]
485 486 else
486 487 ustat << [0,false]
487 488 end
488 489 end
489 490 end
490 491 scorearray << ustat
491 492 end
492 493 return scorearray
493 494 end
494 495
495 496 def gen_csv_from_scorearray(scorearray,problem)
496 497 CSV.generate do |csv|
497 498 #add header
498 499 header = ['User','Name', 'Activated?', 'Logged in', 'Contest']
499 500 problem.each { |p| header << p.name }
500 501 header += ['Total','Passed']
501 502 csv << header
502 503 #add data
503 504 scorearray.each do |sc|
504 505 total = num_passed = 0
505 506 row = Array.new
506 507 sc.each_index do |i|
507 508 if i == 0
508 509 row << sc[i].login
509 510 row << sc[i].full_name
510 511 row << sc[i].activated
511 512 row << (sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no')
512 513 row << sc[i].contests.collect {|c| c.name}.join(', ')
513 514 else
514 515 row << sc[i][0]
515 516 total += sc[i][0]
516 517 num_passed += 1 if sc[i][1]
517 518 end
518 519 end
519 520 row << total
520 521 row << num_passed
521 522 csv << row
522 523 end
523 524 end
524 525 end
525 526
526 527 end
@@ -1,69 +1,69
1 1 %table.table.sortable.table-striped.table-bordered.table-condensed
2 2 %thead
3 3 %tr
4 4 %th Login
5 5 %th Name
6 6 / %th Activated?
7 7 / %th Logged_in
8 8 / %th Contest(s)
9 9 %th Remark
10 10 - @problems.each do |p|
11 11 %th.text-right= p.name.gsub('_',' ')
12 12 %th.text-right Total
13 13 %th.text-right Passed
14 14 %tbody
15 - - sum = Array.new(@scorearray[0].count,0)
16 - - nonzero = Array.new(@scorearray[0].count,0)
17 - - full = Array.new(@scorearray[0].count,0)
15 + - sum = Array.new(@problems.count,0)
16 + - nonzero = Array.new(@problems.count,0)
17 + - full = Array.new(@problems.count,0)
18 18 - @scorearray.each do |sc|
19 19 %tr
20 20 - total,num_passed = 0,0
21 21 - sc.each_index do |i|
22 22 - if i == 0
23 23 %td= link_to sc[i].login, stat_user_path(sc[i])
24 24 %td= sc[i].full_name
25 25 / %td= sc[i].activated
26 26 / %td= sc[i].try(:contest_stat).try(:started_at) ? 'yes' : 'no'
27 27 / %td= sc[i].contests.collect {|c| c.name}.join(', ')
28 28 %td= sc[i].remark
29 29 - else
30 30 %td.text-right= sc[i][0]
31 31 - total += sc[i][0]
32 32 - num_passed += 1 if sc[i][1]
33 33 - sum[i] += sc[i][0]
34 34 - nonzero[i] += 1 if sc[i][0] > 0
35 35 - full[i] += 1 if sc[i][1]
36 36 %td.text-right= total
37 37 %td.text-right= num_passed
38 38 %tfoot
39 39 %tr
40 40 %td Summation
41 41 %td
42 42 %td
43 43 - sum.each.with_index do |s,i|
44 44 - next if i == 0
45 45 %td.text-right= number_with_delimiter(s)
46 46 %td
47 47 %td
48 48 %tr
49 49 %td partial solver
50 50 %td
51 51 %td
52 52 - nonzero.each.with_index do |s,i|
53 53 - next if i == 0
54 54 %td.text-right= number_with_delimiter(s)
55 55 %td
56 56 %td
57 57 %tr
58 58 %td Full solver
59 59 %td
60 60 %td
61 61 - full.each.with_index do |s,i|
62 62 - next if i == 0
63 63 %td.text-right= number_with_delimiter(s)
64 64 %td
65 65 %td
66 66
67 67
68 68 :javascript
69 69 $.bootstrapSortable(true,'reversed')
@@ -1,11 +1,11
1 1 .container-fluid
2 2 %h1 Current Score
3 3 = form_tag current_score_report_path, method: 'get' do
4 4 Show only users from this group
5 - = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2'
5 + = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_id]), id: 'group_name',class: 'select2', style: 'width: 20em';
6 6 = submit_tag 'Apply',class: 'btn btn-default'
7 7
8 8 %br
9 9
10 10
11 11 = render "score_table"
You need to be logged in to leave comments. Login now