diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -39,6 +39,17 @@ return true end + #admin always count as every roles + def role_authorization(roles) + return false unless check_valid_login + user = User.find(session[:user_id]) + return true if user.admin? + roles.each do |r| + return true if user.has_role?(r) + end + unauthorized_redirect + end + def authorization_by_roles(allowed_roles) return false unless check_valid_login unless @current_user.roles.detect { |role| allowed_roles.member?(role.name) } diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb --- a/app/controllers/main_controller.rb +++ b/app/controllers/main_controller.rb @@ -71,7 +71,7 @@ end @submission.submitted_at = Time.new.gmtime - @submission.ip_address = request.remote_ip + @submission.ip_address = cookies.encrypted[:uuid] if @current_user.admin? == false && GraderConfiguration.time_limit_mode? && @current_user.contest_finished? @submission.errors.add(:base,"The contest is over.") diff --git a/app/controllers/report_controller.rb b/app/controllers/report_controller.rb --- a/app/controllers/report_controller.rb +++ b/app/controllers/report_controller.rb @@ -234,16 +234,21 @@ return unless @problem + #model submisssion + @model_subs = Submission.where(problem: @problem,tag: Submission.tags[:model]) + + + #calculate best submission @by_lang = {} #aggregrate by language range =65 - @histogram = { data: Array.new(range,0), summary: {} } + #@histogram = { data: Array.new(range,0), summary: {} } @summary = {count: 0, solve: 0, attempt: 0} user = Hash.new(0) Submission.where(problem_id: @problem.id).find_each do |sub| #histogram d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60 - @histogram[:data][d.to_i] += 1 if d < range + #@histogram[:data][d.to_i] += 1 if d < range next unless sub.points @summary[:count] += 1 @@ -311,9 +316,13 @@ end end - @histogram[:summary][:max] = [@histogram[:data].max,1].max + #@histogram[:summary][:max] = [@histogram[:data].max,1].max @summary[:attempt] = user.count user.each_value { |v| @summary[:solve] += 1 if v == 1 } + + + #for new graph + @chart_dataset = @problem.get_jschart_history.to_json.html_safe end def stuck #report struggling user,problem diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -1,7 +1,8 @@ class SubmissionsController < ApplicationController + before_action :set_submission, only: [:show,:download,:compiler_msg,:rejudge,:set_tag, :edit] before_action :check_valid_login before_action :submission_authorization, only: [:show, :download, :edit] - before_action :admin_authorization, only: [:rejudge] + before_action only: [:rejudge, :set_tag] do role_authorization([:ta]) end # GET /submissions # GET /submissions.json @@ -27,8 +28,6 @@ # GET /submissions/1 # GET /submissions/1.json def show - @submission = Submission.find(params[:id]) - #log the viewing user = User.find(session[:user_id]) SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin? @@ -37,12 +36,10 @@ end def download - @submission = Submission.find(params[:id]) send_data(@submission.source, {:filename => @submission.download_filename, :type => 'text/plain'}) end def compiler_msg - @submission = Submission.find(params[:id]) respond_to do |format| format.js end @@ -65,7 +62,6 @@ # GET /submissions/1/edit def edit - @submission = Submission.find(params[:id]) @source = @submission.source.to_s @problem = @submission.problem @lang_id = @submission.language.id @@ -82,7 +78,6 @@ # GET /submissions/:id/rejudge def rejudge - @submission = Submission.find(params[:id]) @task = @submission.task @task.status_inqueue! if @task respond_to do |format| @@ -90,6 +85,11 @@ end end + def set_tag + @submission.update(tag: params[:tag]) + redirect_to @submission + end + protected def submission_authorization @@ -106,6 +106,10 @@ unauthorized_redirect return false end + + def set_submission + @submission = Submission.find(params[:id]) + end end diff --git a/app/models/problem.rb b/app/models/problem.rb --- a/app/models/problem.rb +++ b/app/models/problem.rb @@ -24,6 +24,28 @@ DEFAULT_TIME_LIMIT = 1 DEFAULT_MEMORY_LIMIT = 32 + def get_jschart_history + start = 4.month.ago.beginning_of_day + start_date = start.to_date + count = Submission.where(problem: self).where('submitted_at >= ?', start).group('DATE(submitted_at)').count + i = 0 + label = [] + value = [] + while (start_date + i < Time.zone.now.to_date) + if (start_date+i).day == 1 + #label << (start_date+i).strftime("%d %b %Y") + #label << (start_date+i).strftime("%d") + else + #label << ' ' + #label << (start_date+i).strftime("%d") + end + label << (start_date+i).strftime("%d-%b") + value << (count[start_date+i] || 0) + i+=1 + end + return {labels: label,datasets: [label:'sub',data: value, backgroundColor: 'rgba(54, 162, 235, 0.2)', borderColor: 'rgb(75, 192, 192)']} + end + def self.available_problems available.order(date_added: :desc).order(:name) #Problem.available.all(:order => "date_added DESC, name ASC") diff --git a/app/models/submission.rb b/app/models/submission.rb --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -1,5 +1,7 @@ class Submission < ActiveRecord::Base + enum tag: {default: 0, model: 1}, _prefix: true + belongs_to :language belongs_to :problem belongs_to :user @@ -24,12 +26,12 @@ def self.find_all_last_by_problem(problem_id) # need to put in SQL command, maybe there's a better way Submission.includes(:user).find_by_sql("SELECT * FROM submissions " + - "WHERE id = " + - "(SELECT MAX(id) FROM submissions AS subs " + - "WHERE subs.user_id = submissions.user_id AND " + - "problem_id = " + problem_id.to_s + " " + - "GROUP BY user_id) " + - "ORDER BY user_id") + "WHERE id = " + + "(SELECT MAX(id) FROM submissions AS subs " + + "WHERE subs.user_id = submissions.user_id AND " + + "problem_id = " + problem_id.to_s + " " + + "GROUP BY user_id) " + + "ORDER BY user_id") end def self.find_in_range_by_user_and_problem(user_id, problem_id,since_id,until_id) @@ -75,12 +77,12 @@ i = 0 source.each_line do |s| if s =~ option - words = s.split - return words[1] + words = s.split + return words[1] end i = i + 1 if i==10 - return nil + return nil end end return nil diff --git a/app/views/report/_task_hof.html.haml b/app/views/report/_task_hof.html.haml --- a/app/views/report/_task_hof.html.haml +++ b/app/views/report/_task_hof.html.haml @@ -24,113 +24,131 @@ } -.container +.container-fluid + .row + .col-md-8 + .card + .card-body + %h2.card-title Submission History + %canvas#chart{height: '50px'} + + .col-md-4 + .card + .card-body + %h2.card-title General Info + .row + .col-sm-6 + Subs + .col-sm-6 + = @summary[:count] + .row + .col-sm-6 + Solved/Attempted User + .col-sm-6 + #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%) .row .col-md-4 - %h2 Overall Stat - %table.table.table-hover - %thead - %tr - %th - %th - %tbody - %tr - %td.info_param Submissions - %td= @summary[:count] - %tr - %td.info_param Solved/Attempted User - %td #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%) - - if @best - %tr - %td.info_param Best Runtime - %td - by #{link_to @best[:runtime][:user], stat_user_path(@best[:runtime][:user_id])} - %br - using #{@best[:runtime][:lang]} - %br - with #{@best[:runtime][:value] * 1000} milliseconds - %br - at submission - = link_to "#" + @best[:runtime][:sub_id].to_s, submission_path(@best[:runtime][:sub_id]) - - %tr - %td.info_param - Best Memory Usage - %sup{ id: "xmem_remark", - style: "position:relative; color: blue;", - data: {toggle: 'tooltip', placement: 'top', animation: 'false', delay: 20}, - title: "This counts only for submission with 100% score. Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)"} - [?] - %td - by #{link_to @best[:memory][:user], stat_user_path(@best[:memory][:user_id])} - %br - using #{@best[:memory][:lang]} - %br - with #{number_with_delimiter(@best[:memory][:value])} kbytes - %br - at submission - = link_to "#" + @best[:memory][:sub_id].to_s, submission_path(@best[:memory][:sub_id]) - - %tr - %td.info_param Shortest Code - %td - by #{link_to @best[:length][:user], stat_user_path(@best[:length][:user_id])} - %br - using #{@best[:length][:lang]} - %br - with #{@best[:length][:value]} bytes - %br - at submission - = link_to "#" + @best[:length][:sub_id].to_s, submission_path(@best[:length][:sub_id]) - - %tr - %td.info_param First solver - %td - - if @best[:first][:user] != '(NULL)' - #{link_to @best[:first][:user], stat_user_path(@best[:first][:user_id])} is the first solver - %br - using #{@best[:first][:lang]} - %br - on #{@best[:first][:value]} - %br - at submission - = link_to "#" + @best[:first][:sub_id].to_s, submission_path( @best[:first][:sub_id]) - - else - no first solver - .col-md-8 - - if @best - %h2 By Language + .card + .card-body + %h2.card-title Model submission %table.table.table-hover %thead %tr - %th Language - %th Best runtime (ms) - %th Best memory (kbytes) - %th Shortest Code (bytes) - %th First solver + %th #Sub + %th Author %tbody - - @by_lang.each do |lang,value| + - @model_subs.each do |sub| %tr - %td= lang + %td= link_to "##{sub.id}", submission_path(sub) + %td= sub.user.full_name + .col-md-8 + - if @best + .card + .card-body + %h2.card-title Top Submissions + %table.table.table-hover + %thead + %tr + %th Language + %th Best runtime (ms) + %th Best memory (kbytes) + %th Shortest Code (bytes) + %th First solver + %tbody + %tr.bg-warning %td - = link_to value[:runtime][:user], stat_user_path(value[:runtime][:user_id]) + Overall + %td + by #{link_to @best[:runtime][:user], stat_user_path(@best[:runtime][:user_id])} + %br + using #{@best[:runtime][:lang]} + %br + with #{@best[:runtime][:value] * 1000} milliseconds + %br= link_to "#" + @best[:runtime][:sub_id].to_s, submission_path(@best[:runtime][:sub_id]) + %td + by #{link_to @best[:memory][:user], stat_user_path(@best[:memory][:user_id])} %br - = "#{(value[:runtime][:value] * 1000).to_i} @" - = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id]) + using #{@best[:memory][:lang]} + %br + with #{number_with_delimiter(@best[:memory][:value])} kbytes + %br= link_to "#" + @best[:memory][:sub_id].to_s, submission_path(@best[:memory][:sub_id]) + %td + by #{link_to @best[:length][:user], stat_user_path(@best[:length][:user_id])} + %br + using #{@best[:length][:lang]} + %br + with #{@best[:length][:value]} bytes + %br= link_to "#" + @best[:length][:sub_id].to_s, submission_path(@best[:length][:sub_id]) %td - = link_to value[:memory][:user], stat_user_path( value[:memory][:user_id]) - %br - = "#{number_with_delimiter(value[:memory][:value])} @" - = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id]) - %td - = link_to value[:length][:user], stat_user_path(value[:length][:user_id]) - %br - = "#{value[:length][:value]} @" - = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id]) - %td - - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong... - = link_to value[:first][:user], stat_user_path(value[:first][:user_id]) + - if @best[:first][:user] != '(NULL)' + #{link_to @best[:first][:user], stat_user_path(@best[:first][:user_id])} is the first solver + %br + using #{@best[:first][:lang]} + %br + on #{@best[:first][:value]} + %br= link_to "#" + @best[:first][:sub_id].to_s, submission_path( @best[:first][:sub_id]) + - else + no first solver + - @by_lang.each do |lang,value| + %tr + %td= lang + %td + = link_to value[:runtime][:user], stat_user_path(value[:runtime][:user_id]) + %br + = "#{(value[:runtime][:value] * 1000).to_i} @" + = link_to "#" + value[:runtime][:sub_id].to_s, submission_path( value[:runtime][:sub_id]) + %td + = link_to value[:memory][:user], stat_user_path( value[:memory][:user_id]) + %br + = "#{number_with_delimiter(value[:memory][:value])} @" + = link_to "#" + value[:memory][:sub_id].to_s, submission_path(value[:memory][:sub_id]) + %td + = link_to value[:length][:user], stat_user_path(value[:length][:user_id]) %br - = "#{value[:first][:value]} @" - = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id]) + = "#{value[:length][:value]} @" + = link_to "#" + value[:length][:sub_id].to_s, submission_path(value[:length][:sub_id]) + %td + - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong... + = link_to value[:first][:user], stat_user_path(value[:first][:user_id]) + %br + = "#{value[:first][:value]} @" + = link_to "#" + value[:first][:sub_id].to_s, submission_path( value[:first][:sub_id]) +%script{src:"https://cdn.jsdelivr.net/npm/chart.js"} +:javascript + data = #{@chart_dataset} + config = { + type: 'bar', + data: data, + options: { + plugins: { + legend: { + display: false + }, + }, + } + } + Chart.defaults.font.size = 15 + //Chart.defaults.font.family = 'Sarabun Light' + chart = new Chart($('#chart'),config) + diff --git a/app/views/report/problem_hof.html.haml b/app/views/report/problem_hof.html.haml --- a/app/views/report/problem_hof.html.haml +++ b/app/views/report/problem_hof.html.haml @@ -23,7 +23,7 @@ Please select a problem. - else %h1 [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name} - %h2 Submission History - =render partial: 'application/bar_graph', locals: { histogram: @histogram } + -# %h2 Submission History + -# =render partial: 'application/bar_graph', locals: { histogram: @histogram } =render partial: 'task_hof' diff --git a/app/views/submissions/show.html.haml b/app/views/submissions/show.html.haml --- a/app/views/submissions/show.html.haml +++ b/app/views/submissions/show.html.haml @@ -89,11 +89,6 @@ %td %button.btn.btn-info.btn-xs{type: 'button', data: {toggle: 'modal', target: '#compiler'}} view - - if session[:admin] - %tr - %td.text-right - %strong IP - %td #{@submission.ip_address} %tr %td.text-right %strong Grading Task Status @@ -101,6 +96,23 @@ = @task.status_str if @task - if session[:admin] = link_to "rejudge", rejudge_submission_path, data: {remote: true}, class: 'btn btn-info btn-xs' + - if session[:admin] + %tr + %td.text-right + %strong IP + %td #{@submission.ip_address} + %tr + %td.text-right + %strong Model solution + %td + - if @submission.tag_model? + YES + - if session[:admin] + = link_to "remove model status", set_tag_submission_path(@submission, tag: :default), class: 'btn btn-warning btn-xs' + - else + No + - if session[:admin] + = link_to "set as model solution", set_tag_submission_path(@submission, tag: :model), class: 'btn btn-success btn-xs' .modal.fade#compiler{tabindex: -1,role: 'dialog'} diff --git a/config/routes.rb b/config/routes.rb --- a/config/routes.rb +++ b/config/routes.rb @@ -94,6 +94,7 @@ get 'download' get 'compiler_msg' get 'rejudge' + get 'set_tag' end collection do get 'prob/:problem_id', to: 'submissions#index', as: 'problem' diff --git a/db/migrate/20220204080936_add_type_to_submission.rb b/db/migrate/20220204080936_add_type_to_submission.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20220204080936_add_type_to_submission.rb @@ -0,0 +1,6 @@ +class AddTypeToSubmission < ActiveRecord::Migration[7.0] + def change + add_column :submissions, :tag, :integer, default: 0 + add_column :problems, :difficulty, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb --- a/db/schema.rb +++ b/db/schema.rb @@ -2,19 +2,19 @@ # of editing this file, please use the migrations feature of Active Record to # incrementally modify your database, and then regenerate this schema definition. # -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_08_09_105935) do +ActiveRecord::Schema.define(version: 2022_02_04_080936) do - create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "announcements", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "author" - t.text "body", limit: 16777215 + t.text "body" t.boolean "published" t.datetime "created_at", null: false t.datetime "updated_at", null: false @@ -25,7 +25,7 @@ t.boolean "on_nav_bar", default: false end - create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "contests", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "title" t.boolean "enabled" t.datetime "created_at", null: false @@ -33,39 +33,39 @@ t.string "name" end - create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "contests_problems", id: false, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "contest_id" t.integer "problem_id" end - create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "contests_users", id: false, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "contest_id" t.integer "user_id" end - create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "countries", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "name" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| - t.text "body", limit: 16777215 + create_table "descriptions", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + t.text "body" t.boolean "markdowned" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "grader_configurations", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "key" t.string "value_type" t.string "value" t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.text "description", limit: 16777215 + t.text "description" end - create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "grader_processes", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "host" t.integer "pid" t.string "mode" @@ -78,25 +78,25 @@ t.index ["host", "pid"], name: "index_grader_processes_on_ip_and_pid" end - create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "groups", id: :integer, charset: "latin1", force: :cascade do |t| t.string "name" t.string "description" t.boolean "enabled", default: true end - create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "groups_problems", id: false, charset: "latin1", force: :cascade do |t| t.integer "problem_id", null: false t.integer "group_id", null: false t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id" end - create_table "groups_users", options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "groups_users", charset: "latin1", force: :cascade do |t| t.integer "group_id", null: false t.integer "user_id", null: false t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id" end - create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "heart_beats", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "user_id" t.string "ip_address" t.datetime "created_at", null: false @@ -105,14 +105,14 @@ t.index ["updated_at"], name: "index_heart_beats_on_updated_at" end - create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "languages", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "name", limit: 10 t.string "pretty_name" t.string "ext", limit: 10 t.string "common_ext" end - create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "logins", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "user_id" t.string "ip_address" t.datetime "created_at", null: false @@ -120,18 +120,18 @@ t.index ["user_id"], name: "index_logins_on_user_id" end - create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "messages", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "sender_id" t.integer "receiver_id" t.integer "replying_message_id" - t.text "body", limit: 16777215 + t.text "body" t.boolean "replied" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| - t.string "name", limit: 100 + create_table "problems", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| + t.string "name", limit: 30 t.string "full_name" t.integer "full_score" t.date "date_added" @@ -142,9 +142,10 @@ t.boolean "output_only" t.string "description_filename" t.boolean "view_testcase" + t.integer "difficulty" end - create_table "problems_tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "problems_tags", id: :integer, charset: "latin1", force: :cascade do |t| t.integer "problem_id" t.integer "tag_id" t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true @@ -152,37 +153,37 @@ t.index ["tag_id"], name: "index_problems_tags_on_tag_id" end - create_table "rights", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "rights", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "name" t.string "controller" t.string "action" end - create_table "rights_roles", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "rights_roles", id: false, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "right_id" t.integer "role_id" t.index ["role_id"], name: "index_rights_roles_on_role_id" end - create_table "roles", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "roles", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "name" end - create_table "roles_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "roles_users", id: false, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "role_id" t.integer "user_id" t.index ["user_id"], name: "index_roles_users_on_user_id" end - create_table "sessions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "sessions", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "session_id" - t.text "data", limit: 16777215 + t.text "data" t.datetime "updated_at" t.index ["session_id"], name: "index_sessions_on_session_id" t.index ["updated_at"], name: "index_sessions_on_updated_at" end - create_table "sites", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "sites", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "name" t.boolean "started" t.datetime "start_time" @@ -192,37 +193,38 @@ t.string "password" end - create_table "submission_view_logs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "submission_view_logs", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "user_id" t.integer "submission_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "submissions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "submissions", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "user_id" t.integer "problem_id" t.integer "language_id" - t.text "source", limit: 16777215 + t.text "source", size: :medium t.binary "binary" t.datetime "submitted_at" t.datetime "compiled_at" - t.text "compiler_message", limit: 16777215 + t.text "compiler_message" t.datetime "graded_at" t.integer "points" - t.text "grader_comment", limit: 16777215 + t.text "grader_comment" t.integer "number" t.string "source_filename" t.float "max_runtime" t.integer "peak_memory" t.integer "effective_code_length" t.string "ip_address" + t.integer "tag", default: 0 t.index ["submitted_at"], name: "index_submissions_on_submitted_at" t.index ["user_id", "problem_id", "number"], name: "index_submissions_on_user_id_and_problem_id_and_number", unique: true t.index ["user_id", "problem_id"], name: "index_submissions_on_user_id_and_problem_id" end - create_table "tags", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "tags", id: :integer, charset: "latin1", force: :cascade do |t| t.string "name", null: false t.text "description" t.boolean "public" @@ -230,7 +232,7 @@ t.datetime "updated_at", null: false end - create_table "tasks", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "tasks", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "submission_id" t.datetime "created_at" t.integer "status" @@ -239,15 +241,15 @@ t.index ["submission_id"], name: "index_tasks_on_submission_id" end - create_table "test_pairs", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "test_pairs", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "problem_id" - t.text "input", limit: 4294967295 - t.text "solution", limit: 4294967295 + t.text "input", size: :medium + t.text "solution", size: :medium t.datetime "created_at", null: false t.datetime "updated_at", null: false end - create_table "test_requests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "test_requests", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "user_id" t.integer "problem_id" t.integer "submission_id" @@ -258,7 +260,7 @@ t.datetime "updated_at", null: false t.datetime "submitted_at" t.datetime "compiled_at" - t.text "compiler_message", limit: 16777215 + t.text "compiler_message" t.datetime "graded_at" t.string "grader_comment" t.datetime "created_at", null: false @@ -268,19 +270,19 @@ t.index ["user_id", "problem_id"], name: "index_test_requests_on_user_id_and_problem_id" end - create_table "testcases", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t| + create_table "testcases", id: :integer, charset: "latin1", force: :cascade do |t| t.integer "problem_id" t.integer "num" t.integer "group" t.integer "score" - t.text "input", limit: 4294967295 - t.text "sol", limit: 4294967295 - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.text "input", size: :long + t.text "sol", size: :long + t.datetime "created_at" + t.datetime "updated_at" t.index ["problem_id"], name: "index_testcases_on_problem_id" end - create_table "user_contest_stats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "user_contest_stats", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.integer "user_id" t.datetime "started_at" t.datetime "created_at", null: false @@ -288,7 +290,7 @@ t.boolean "forced_logout" end - create_table "users", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| + create_table "users", id: :integer, charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "login", limit: 50 t.string "full_name" t.string "hashed_password" @@ -300,10 +302,10 @@ t.boolean "activated", default: false t.datetime "created_at" t.datetime "updated_at" - t.string "section" t.boolean "enabled", default: true t.string "remark" t.string "last_ip" + t.string "section" t.integer "default_language" t.index ["login"], name: "index_users_on_login", unique: true end