diff --git a/.gitignore b/.gitignore new file mode 100644 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +log +config/environment.rb +config/database.yml diff --git a/Rakefile b/Rakefile --- a/Rakefile +++ b/Rakefile @@ -8,3 +8,12 @@ require 'rake/rdoctask' require 'tasks/rails' + +require 'spec/rake/spectask' + +desc "Run all examples with RCov" +Spec::Rake::SpecTask.new('examples_with_rcov') do |t| + t.spec_files = FileList['spec/*/*.rb'] + t.rcov = true + #t.rcov_opts = ['--exclude', 'examples'] +end diff --git a/app/controllers/application.rb b/app/controllers/application.rb deleted file mode 100644 --- a/app/controllers/application.rb +++ /dev/null @@ -1,76 +0,0 @@ -# Filters added to this controller apply to all controllers in the application. -# Likewise, all the methods added will be available for all controllers. - -class ApplicationController < ActionController::Base - # Pick a unique cookie name to distinguish our session data from others' - session :session_key => '_grader_session_id' - - SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode' - - def admin_authorization - return false unless authenticate - user = User.find(session[:user_id], :include => ['roles']) - redirect_to :controller => 'main', :action => 'login' unless user.admin? - end - - def authorization_by_roles(allowed_roles) - return false unless authenticate - user = User.find(session[:user_id]) - unless user.roles.detect { |role| allowed_roles.member?(role.name) } - flash[:notice] = 'You are not authorized to view the page you requested' - redirect_to :controller => 'main', :action => 'login' - return false - end - end - - protected - - def authenticate - unless session[:user_id] - redirect_to :controller => 'main', :action => 'login' - return false - end - - #Configuration.reload - # check if run in single user mode - if (Configuration[SINGLE_USER_MODE_CONF_KEY]) - user = User.find(session[:user_id]) - if user==nil or user.login != 'root' - redirect_to :controller => 'main', :action => 'login' - return false - end - end - - return true - end - - def authorization - return false unless authenticate - user = User.find(session[:user_id]) - unless user.roles.detect { |role| - role.rights.detect{ |right| - right.controller == self.class.controller_name and - (right.action == 'all' or right.action == action_name) - } - } - flash[:notice] = 'You are not authorized to view the page you requested' - #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login') - redirect_to :controller => 'main', :action => 'login' - return false - end - end - - def verify_time_limit - return true if session[:user_id]==nil - user = User.find(session[:user_id], :include => :site) - return true if user==nil or user.site == nil - if user.site.finished? - flash[:notice] = 'Error: the contest on your site is over.' - redirect_to :back - return false - end - return true - end - -end - diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,76 @@ +# Filters added to this controller apply to all controllers in the application. +# Likewise, all the methods added will be available for all controllers. + +class ApplicationController < ActionController::Base + # Pick a unique cookie name to distinguish our session data from others' + session :session_key => '_grader_session_id' + + SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode' + + def admin_authorization + return false unless authenticate + user = User.find(session[:user_id], :include => ['roles']) + redirect_to :controller => 'main', :action => 'login' unless user.admin? + end + + def authorization_by_roles(allowed_roles) + return false unless authenticate + user = User.find(session[:user_id]) + unless user.roles.detect { |role| allowed_roles.member?(role.name) } + flash[:notice] = 'You are not authorized to view the page you requested' + redirect_to :controller => 'main', :action => 'login' + return false + end + end + + protected + + def authenticate + unless session[:user_id] + redirect_to :controller => 'main', :action => 'login' + return false + end + + #Configuration.reload + # check if run in single user mode + if (Configuration[SINGLE_USER_MODE_CONF_KEY]) + user = User.find(session[:user_id]) + if user==nil or user.login != 'root' + redirect_to :controller => 'main', :action => 'login' + return false + end + end + + return true + end + + def authorization + return false unless authenticate + user = User.find(session[:user_id]) + unless user.roles.detect { |role| + role.rights.detect{ |right| + right.controller == self.class.controller_name and + (right.action == 'all' or right.action == action_name) + } + } + flash[:notice] = 'You are not authorized to view the page you requested' + #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login') + redirect_to :controller => 'main', :action => 'login' + return false + end + end + + def verify_time_limit + return true if session[:user_id]==nil + user = User.find(session[:user_id], :include => :site) + return true if user==nil or user.site == nil + if user.site.finished? + flash[:notice] = 'Error: the contest on your site is over.' + redirect_to :back + return false + end + return true + end + +end + diff --git a/app/controllers/login_controller.rb b/app/controllers/login_controller.rb --- a/app/controllers/login_controller.rb +++ b/app/controllers/login_controller.rb @@ -31,12 +31,12 @@ flash[:notice] = 'Wrong site' redirect_to :controller => 'main', :action => 'login' and return end - if site.password == params[:login][:password] + if (site.password) and (site.password == params[:login][:password]) session[:site_id] = site.id redirect_to :controller => 'site', :action => 'index' else flash[:notice] = 'Wrong site password' - redirect_to :controller => 'main', :action => 'login' + redirect_to :controller => 'site', :action => 'login' end end 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 @@ -35,22 +35,6 @@ # @hidelogin = true # end - # Site administrator login - @countries = Country.find(:all, :include => :sites) - @country_select = @countries.collect { |c| [c.name, c.id] } - - @country_select_with_all = [['Any',0]] - @countries.each do |country| - @country_select_with_all << [country.name, country.id] - end - - @site_select = [] - @countries.each do |country| - country.sites.each do |site| - @site_select << ["#{site.name}, #{country.name}", site.id] - end - end - @announcements = Announcement.find_for_frontpage render :action => 'login', :layout => 'empty' end @@ -197,7 +181,11 @@ @prob_submissions << { :count => 0, :submission => nil } end end - @announcements = Announcement.find_published + if Configuration.show_tasks_to?(@user) + @announcements = Announcement.find_published(true) + else + @announcements = Announcement.find_published + end end def check_viewability diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb --- a/app/controllers/site_controller.rb +++ b/app/controllers/site_controller.rb @@ -1,6 +1,28 @@ class SiteController < ApplicationController - before_filter :site_admin_authorization + before_filter :site_admin_authorization, :except => 'login' + + def login + # Site administrator login + @countries = Country.find(:all, :include => :sites) + @country_select = @countries.collect { |c| [c.name, c.id] } + + @country_select_with_all = [['Any',0]] + @countries.each do |country| + @country_select_with_all << [country.name, country.id] + end + + @site_select = [] + @countries.each do |country| + country.sites.each do |site| + @site_select << ["#{site.name}, #{country.name}", site.id] + end + end + + @default_site = Site.first if !Configuration['contest.multisites'] + + render :action => 'login', :layout => 'empty' + end def index if @site.started @@ -25,7 +47,7 @@ protected def site_admin_authorization if session[:site_id]==nil - redirect_to :controller => 'main', :action => 'login' and return + redirect_to :controller => 'site', :action => 'login' and return end begin @site = Site.find(session[:site_id], :include => :country) @@ -33,7 +55,7 @@ @site = nil end if @site==nil - redirect_to :controller => 'main', :action => 'login' and return + redirect_to :controller => 'site', :action => 'login' and return end end diff --git a/app/controllers/test_controller.rb b/app/controllers/test_controller.rb --- a/app/controllers/test_controller.rb +++ b/app/controllers/test_controller.rb @@ -99,7 +99,12 @@ @problems << problem end end - @test_requests = @user.test_requests + @test_requests = [] + @user.test_requests.each do |ts| + if ts.problem.available + @test_requests << ts + end + end end def check_viewability diff --git a/app/controllers/user_admin_controller.rb b/app/controllers/user_admin_controller.rb --- a/app/controllers/user_admin_controller.rb +++ b/app/controllers/user_admin_controller.rb @@ -13,6 +13,7 @@ def list @users = User.find(:all) + @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at'] end def show @@ -77,8 +78,7 @@ @scorearray = Array.new @users.each do |u| ustat = Array.new - ustat[0] = u.login - ustat[1] = u.full_name + ustat[0] = u @problems.each do |p| sub = Submission.find_last_by_user_and_problem(u.id,p.id) if (sub!=nil) and (sub.points!=nil) @@ -152,7 +152,12 @@ u.password = user[:password] u.country = countries[user[:country_id]] u.site = sites[user[:site_id]] - u.save + u.activated = true + u.email = "empty-#{u.login}@none.com" + if not u.save + @import_log << "Errors\n" + u.errors.each { |attr,msg| @import_log << "#{attr} - #{msg}\n" } + end end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -5,11 +5,13 @@ before_filter :authenticate, :except => [:new, :register, :confirm] + before_filter :verify_online_registration, :only => [:new, :register] + verify :method => :post, :only => [:chg_passwd], :redirect_to => { :action => :index } - in_place_edit_for :user, :alias_for_editing - in_place_edit_for :user, :email_for_editing + #in_place_edit_for :user, :alias_for_editing + #in_place_edit_for :user, :email_for_editing def index if !Configuration['system.user_setting_enabled'] @@ -37,6 +39,10 @@ end def register + if(params[:cancel]) + redirect_to :controller => 'main', :action => 'login' + return + end @user = User.new(params[:user]) @user.password_confirmation = @user.password = User.random_password @user.activated = false @@ -44,6 +50,7 @@ if send_confirmation_email(@user) render :action => 'new_splash', :layout => 'empty' else + @admin_email = Configuration['system.admin_email'] render :action => 'email_error', :layout => 'empty' end else @@ -72,8 +79,15 @@ protected + def verify_online_registration + if !Configuration['system.online_registration'] + redirect_to :controller => 'main', :action => 'login' + end + end + def send_confirmation_email(user) contest_name = Configuration['contest.name'] + admin_email = Configuration['system.admin_email'] activation_url = url_for(:action => 'confirm', :login => user.login, :activation => user.activation_key) @@ -82,22 +96,16 @@ mail.to = user.email mail.from = Configuration['system.online_registration.from'] mail.subject = "[#{contest_name}] Confirmation" - mail.body = <<-EOF -Hello #{user.full_name}, - -You have registered for #{contest_name} (#{home_url}). - -Your login is: #{user.login} -Your password is: #{user.password} + mail.body = t('registration.email_body', { + :full_name => user.full_name, + :contest_name => contest_name, + :login => user.login, + :password => user.password, + :activation_url => activation_url, + :admin_email => admin_email + }) -Please follow the link: -#{activation_url} -to activate your user account. - -If you did not register, please ignore this e-mail. - -Thanks! -EOF + logger.info mail.body smtp_server = Configuration['system.online_registration.smtp'] diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -14,27 +14,28 @@ append_to menu_items, '[Msg console]', 'messages', 'console' append_to menu_items, '[Problem admin]', 'problems', 'index' append_to menu_items, '[User admin]', 'user_admin', 'index' - append_to menu_items, '[User stat]', 'user_admin', 'user_stat' + append_to menu_items, '[Results]', 'user_admin', 'user_stat' append_to menu_items, '[Graders]', 'graders', 'list' - append_to menu_items, '[Site config]', 'configurations', 'index' + append_to menu_items, '[Sites]', 'sites', 'index' + append_to menu_items, '[System config]', 'configurations', 'index' menu_items << "
" end # main page - append_to menu_items, '[Main]', 'main', 'list' - append_to menu_items, '[Messages]', 'messages', 'list' + append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list' + append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list' if (user!=nil) and (Configuration.show_tasks_to?(user)) - append_to menu_items, '[Tasks]', 'tasks', 'list' - append_to menu_items, '[Submissions]', 'main', 'submission' - append_to menu_items, '[Test]', 'test', 'index' + append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list' + append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission' + append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index' end - append_to menu_items, '[Help]', 'main', 'help' + append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help' if Configuration['system.user_setting_enabled'] - append_to menu_items, '[Settings]', 'users', 'index' + append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index' end - append_to menu_items, '[Log out]', 'main', 'login' + append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login' menu_items end @@ -78,8 +79,13 @@ CONTEST_OVER end - if user.site!=nil - time_left = ". Time left: #{Time.at(user.site.time_left).gmtime.strftime("%X")}" + if !user.site.started + time_left = "  " + (t 'title_bar.contest_not_started') + else + if user.site!=nil + time_left = "  " + (t 'title_bar.remaining_time') + + " #{Time.at(user.site.time_left).gmtime.strftime("%X")}" + end end end @@ -104,7 +110,7 @@ #{user.full_name}
-Current time is #{format_short_time(Time.new.gmtime)} UTC +#{t 'title_bar.current_time'} #{format_short_time(Time.new)} #{time_left}
diff --git a/app/models/announcement.rb b/app/models/announcement.rb --- a/app/models/announcement.rb +++ b/app/models/announcement.rb @@ -1,9 +1,15 @@ class Announcement < ActiveRecord::Base - def self.find_published - Announcement.find(:all, - :conditions => "(published = 1) AND (frontpage = 0)", - :order => "created_at DESC") + def self.find_published(contest_started=false) + if contest_started + Announcement.find(:all, + :conditions => "(published = 1) AND (frontpage = 0)", + :order => "created_at DESC") + else + Announcement.find(:all, + :conditions => "(published = 1) AND (frontpage = 0) AND (contest_only = 0)", + :order => "created_at DESC") + end end def self.find_for_frontpage diff --git a/app/models/configuration.rb b/app/models/configuration.rb --- a/app/models/configuration.rb +++ b/app/models/configuration.rb @@ -6,6 +6,7 @@ class Configuration < ActiveRecord::Base SYSTEM_MODE_CONF_KEY = 'system.mode' + TEST_REQUEST_EARLY_TIMEOUT_KEY = 'contest.test_request.early_timeout' # set @@cache = true to only reload once. @@cache = false @@ -36,6 +37,10 @@ @@configurations = nil end + def self.cache? + @@cache + end + def self.enable_caching @@cache = true end @@ -67,8 +72,11 @@ def self.allow_test_request(user) mode = get(SYSTEM_MODE_CONF_KEY) + early_timeout = get(TEST_REQUEST_EARLY_TIMEOUT_KEY) if (mode=='contest') - return false if (user.site!=nil) and ((user.site.started!=true) or (user.site.time_left < 30.minutes)) + return false if ((user.site!=nil) and + ((user.site.started!=true) or + (early_timeout and (user.site.time_left < 30.minutes)))) end return false if mode=='analysis' return true diff --git a/app/models/site.rb b/app/models/site.rb --- a/app/models/site.rb +++ b/app/models/site.rb @@ -14,12 +14,16 @@ if tmatch = /(\d+):(\d+)/.match(contest_time) h = tmatch[1].to_i m = tmatch[2].to_i + + contest_time = h.hour + m.minute + + return contest_time if !self.started current_time = Time.now.gmtime if self.start_time!=nil - finish_time = self.start_time + h.hour + m.minute + finish_time = self.start_time + contest_time else - finish_time = current_time + h.hour + m.minute + finish_time = current_time + contest_time end if current_time > finish_time diff --git a/app/models/user.rb b/app/models/user.rb --- a/app/models/user.rb +++ b/app/models/user.rb @@ -23,8 +23,8 @@ validates_presence_of :login validates_uniqueness_of :login - validates_format_of :login, :with => /^[\_a-z0-9]+$/ - validates_length_of :login, :within => 3..10 + validates_format_of :login, :with => /^[\_A-Za-z0-9]+$/ + validates_length_of :login, :within => 3..30 validates_presence_of :full_name validates_length_of :full_name, :minimum => 1 @@ -33,14 +33,22 @@ validates_length_of :password, :within => 4..20, :if => :password_required? validates_confirmation_of :password, :if => :password_required? - validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :allow_blank => true + validates_format_of :email, + :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, + :if => :email_validation? + validate :uniqueness_of_email_from_activated_users, + :if => :email_validation? + validate :enough_time_interval_between_same_email_registrations, + :if => :email_validation? - validate :uniqueness_of_email_from_activated_users - validate :enough_time_interval_between_same_email_registrations + # these are for ytopc + # disable for now + #validates_presence_of :province attr_accessor :password before_save :encrypt_new_password + before_save :assign_default_site def self.authenticate(login, password) user = find_by_login(login) @@ -112,6 +120,16 @@ self.hashed_password = User.encrypt(self.password,self.salt) end + def assign_default_site + # have to catch error when migrating (because self.site is not available). + begin + if self.site==nil + self.site = Site.find_by_name('default') + end + rescue + end + end + def password_required? self.hashed_password.blank? || !self.password.blank? end @@ -129,6 +147,7 @@ def enough_time_interval_between_same_email_registrations return if !self.new_record? + return if self.activated open_user = User.find_by_email(self.email, :order => 'created_at DESC') if open_user and open_user.created_at and @@ -136,4 +155,12 @@ self.errors.add_to_base("There are already unactivated registrations with this e-mail address (please wait for 5 minutes)") end end + + def email_validation? + begin + return VALIDATE_USER_EMAILS + rescue + return false + end + end end diff --git a/app/views/announcements/edit.html.erb b/app/views/announcements/edit.html.erb --- a/app/views/announcements/edit.html.erb +++ b/app/views/announcements/edit.html.erb @@ -24,6 +24,11 @@

+ Show only in contest?
+ <%= f.check_box :contest_only %> +

+ +

<%= f.submit "Update" %>

<% end %> diff --git a/app/views/announcements/index.html.erb b/app/views/announcements/index.html.erb --- a/app/views/announcements/index.html.erb +++ b/app/views/announcements/index.html.erb @@ -1,5 +1,4 @@ <% content_for :head do %> - <%= stylesheet_link_tag 'scaffold' %> <%= javascript_include_tag :defaults %> <% end %> diff --git a/app/views/announcements/new.html.erb b/app/views/announcements/new.html.erb --- a/app/views/announcements/new.html.erb +++ b/app/views/announcements/new.html.erb @@ -24,6 +24,11 @@

+ Show only in contest?
+ <%= f.check_box :contest_only %> +

+ +

<%= f.submit "Create" %>

<% end %> diff --git a/app/views/announcements/show.html.erb b/app/views/announcements/show.html.erb --- a/app/views/announcements/show.html.erb +++ b/app/views/announcements/show.html.erb @@ -18,6 +18,10 @@ <%=h @announcement.frontpage %>

+

+ Show only in contest: + <%=h @announcement.contest_only %> +

<%= link_to 'Edit', edit_announcement_path(@announcement) %> | <%= link_to 'Back', announcements_path %> diff --git a/app/views/configurations/index.html.haml b/app/views/configurations/index.html.haml --- a/app/views/configurations/index.html.haml +++ b/app/views/configurations/index.html.haml @@ -1,7 +1,7 @@ - content_for :head do = javascript_include_tag :defaults -%h1 Grader configuration +%h1 System configuration %table.info %tr.info-head @@ -19,12 +19,13 @@ %td = in_place_editor_field :configuration, :value, {}, :rows=>1 -%br/ -Your config is saved, but it does not automatically take effect. -%br/ -If you have one mongrel process running, you can -= link_to '[click]', :action => 'reload' -here to reload. -%br/ -If you have more than one process running, you should restart -them manually. +- if Configuration.cache? + %br/ + Your config is saved, but it does not automatically take effect. + %br/ + If you have one mongrel process running, you can + = link_to '[click]', :action => 'reload' + here to reload. + %br/ + If you have more than one process running, you should restart + them manually. diff --git a/app/views/graders/list.html.haml b/app/views/graders/list.html.haml --- a/app/views/graders/list.html.haml +++ b/app/views/graders/list.html.haml @@ -2,18 +2,20 @@ = stylesheet_link_tag 'graders' -%h2 (Under Experiments) +%h1 Grader information - form_for :clear, nil, :url => {:action => 'clear_all'} do |f| = submit_tag 'Clear all data' -Last task: -= link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task' +- if @last_task + Last task: + = link_to "#{@last_task.id}", :action => 'view', :id => @last_task.id, :type => 'Task' -%br/ + %br/ -Last test_request: -= link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest' +- if @last_test_request + Last test_request: + = link_to "#{@last_test_request.id}", :action => 'view', :id => @last_test_request.id, :type => 'TestRequest' %h3 Current graders diff --git a/app/views/layouts/sites.html.erb b/app/views/layouts/sites.html.erb deleted file mode 100644 --- a/app/views/layouts/sites.html.erb +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - Sites: <%= controller.action_name %> - <%= stylesheet_link_tag 'scaffold' %> - - - -

<%= flash[:notice] %>

- -<%= yield %> - - - diff --git a/app/views/main/_announcement.html.haml b/app/views/main/_announcement.html.haml --- a/app/views/main/_announcement.html.haml +++ b/app/views/main/_announcement.html.haml @@ -1,4 +1,4 @@ .announcement = markdown(announcement.body) - .pub-info - %p= "#{announcement.author}, #{announcement.created_at}" + -#.pub-info + -# %p= "#{announcement.author}, #{announcement.created_at}" diff --git a/app/views/main/_problem.html.erb b/app/views/main/_problem.html.erb --- a/app/views/main/_problem.html.erb +++ b/app/views/main/_problem.html.erb @@ -4,7 +4,7 @@ <%= "#{problem.full_name} (#{problem.name})" %> - <%= link_to '[desc]', problem.url, :popup => true if (problem.url!=nil) and (problem.url!='') %> + <%= link_to "[#{t 'main.problem_desc'}]", problem.url, :popup => true if (problem.url!=nil) and (problem.url!='') %> <%= @prob_submissions[problem_counter][:count] %> diff --git a/app/views/main/_submission_box.html.erb b/app/views/main/_submission_box.html.erb --- a/app/views/main/_submission_box.html.erb +++ b/app/views/main/_submission_box.html.erb @@ -1,6 +1,6 @@ <% form_tag({:action => 'submit'}, :multipart => true) do %> Problem: <%= select 'submission', 'problem_id', - [['Specified in header','-1']] + + [[(t 'main.specified_in_header'),'-1']] + @problems.collect {|p| [p.full_name, p.id]}, :selected => '-1' %> File: <%= file_field_tag 'file' %> diff --git a/app/views/main/_submission_short.html.haml b/app/views/main/_submission_short.html.haml --- a/app/views/main/_submission_short.html.haml +++ b/app/views/main/_submission_short.html.haml @@ -3,11 +3,14 @@ = "-" - else - if submission.graded_at==nil - Submitted at - = format_short_time(submission.submitted_at) + =t 'main.submitted_at' + = format_short_time(submission.submitted_at.localtime) - else - = "Graded at #{format_short_time(submission.graded_at)}, " - = "score: #{(submission.points*100/submission.problem.full_score).to_i} " if Configuration['ui.show_score'] + = t 'main.graded_at' + = "#{format_short_time(submission.graded_at.localtime)}, " + - if Configuration['ui.show_score'] + = t 'main.score' + = "#{(submission.points*100/submission.problem.full_score).to_i} " = " [" %tt = submission.grader_comment @@ -16,8 +19,8 @@ = " | " = link_to '[detailed result]', :action => 'result', :id => submission.id = " | " - = link_to('[msg]', {:action => 'compiler_msg', :id => submission.id}, {:popup => true}) + = link_to("[#{t 'main.cmp_msg'}]", {:action => 'compiler_msg', :id => submission.id}, {:popup => true}) = " | " - = link_to('[src]',{:action => 'source', :id => submission.id}) + = link_to("[#{t 'main.src_link'}]",{:action => 'source', :id => submission.id}) = " | " - = link_to '[submissions]', :action => 'submission', :id => problem_name + = link_to "[#{t 'main.submissions_link'}]", :action => 'submission', :id => problem_name diff --git a/app/views/main/help.html.haml b/app/views/main/help.html.haml --- a/app/views/main/help.html.haml +++ b/app/views/main/help.html.haml @@ -2,55 +2,46 @@ .announcementbox %span{:class => 'title'} - How to submit + =t 'help.how_to_submit' .announcement %p - You must specify the language you are using - in your program header. You can optionally - specify the task you are submitting to. + =t 'help.must_specify_language' %p - The possible language options are - C, C++, and Pascal. - The follow are examples. + =t 'help.list_available_language' %table{:border => '1'} %tr - %th{:width => '100px'} C - %th{:width => '100px'} C++ - %th{:width => '100px'} Pascal + %th{:width => '150px'} C + %th{:width => '150px'} C++ + %th{:width => '150px'} Pascal %tr %td= "/*
LANG: C
*/
" %td= "/*
LANG: C++
*/
" %td= "{
LANG: Pascal
}
" %p - The server will not accept your submission, - if you do not specify the language. + =t 'help.accept_only_language_specified' %p - Optionally, you can also specify - the task with TASK: taskname. - On the first page, the taskname for each task is - shown in parentheses. + =t 'help.specifying_task' %p - For example, suppose you are using C++ - to write task mobiles, you put + =t 'help.example_cpp' %table{:border => '1'} %tr - %td{:width => '100px'} + %td{:width => '300px'} %tt /*
LANG: C++
TASK: mobiles
*/
%p - on top of your source code. - If you are using Pascal to write the same task, - you'll use + =t 'help.example_pas' %table{:border => '1'} %tr - %td{:width => '100px'} + %td{:width => '300px'} %tt {
LANG: Pascal
TASK: mobiles
}
+ %p + = (t('help.ask_questions_at_messages',:message_link_name => (t 'menu.messages'),:url => url_for(:controller => 'messages', :action => 'list'))) diff --git a/app/views/main/list.html.haml b/app/views/main/list.html.haml --- a/app/views/main/list.html.haml +++ b/app/views/main/list.html.haml @@ -15,7 +15,7 @@ %hr/ - if (@user.site!=nil) and (@user.site.started!=true) - %p The contest at your site will start soon. Please wait. + %p=t 'main.start_soon' - if Configuration.show_tasks_to?(@user) %table.info diff --git a/app/views/main/login.html.haml b/app/views/main/login.html.haml --- a/app/views/main/login.html.haml +++ b/app/views/main/login.html.haml @@ -10,7 +10,7 @@ %br/ - if !@hidelogin - Please login to see the problem list. + =t 'login.message' %br/ %br/ @@ -23,48 +23,20 @@ - form_tag :controller => 'login', :action => 'login' do %table %tr - %td{:align => "right"} Login: + %td{:align => "right"} + ="#{t 'login_label'}:" %td= text_field_tag 'login' %tr - %td{:align => "right"} Password: + %td{:align => "right"} + ="#{t 'password_label'}:" %td= password_field_tag - = submit_tag 'Login' + = submit_tag t('login.login_submit') %br/ - if Configuration['system.online_registration'] - Want to participate? + =t 'login.participation' %b - Please - = link_to 'register.', :controller => :users, :action => :new + = "#{t 'login.please'} " + = link_to "#{t 'login.register'}", :controller => :users, :action => :new %br/ -- if (Configuration['system.mode']=='contest') and (Configuration['contest.multisites']) - %script{:type => 'text/javascript'} - var siteList = new Array(); - - @countries.each do |country| - = "siteList[#{country.id}] = new Array();" - - country.sites.each do |site| - = "siteList[#{country.id}][#{site.id}] = \"#{site.name}\";" - - var allSiteList = new Array(); - - @site_select.each do |sel| - = "allSiteList[#{sel[1]}]=\"#{sel[0]}\";" - - %script{:type => 'text/javascript', :src => '/javascripts/site_update.js'} - - %div{ :style => "border: solid 1px gray; padding: 2px; background: #f0f0f0;"} - %b For Site Administrator. - %br/ - Please select your country and site and login. - - form_for :login, nil, :url => {:controller => 'login', :action => 'site_login'} do |f| - Country: - = select :site_country, :id, @country_select_with_all, {}, {:onchange => "updateSiteList();", :onclick => "updateSiteList();" } - Site: - = select :login, :site_id, @site_select - %br/ - Password: - = f.password_field :password - = submit_tag "Site Administrator Login" - - %script{:type => 'text/javascript'} - updateSiteList(); diff --git a/app/views/problems/list.rhtml b/app/views/problems/list.rhtml --- a/app/views/problems/list.rhtml +++ b/app/views/problems/list.rhtml @@ -1,5 +1,4 @@ <% content_for :head do %> - <%= stylesheet_link_tag 'scaffold' %> <%= stylesheet_link_tag 'problems' %> <%= javascript_include_tag :defaults %> <% end %> diff --git a/app/views/problems/stat.rhtml b/app/views/problems/stat.rhtml --- a/app/views/problems/stat.rhtml +++ b/app/views/problems/stat.rhtml @@ -13,7 +13,7 @@ <% count = 0 %> <% @submissions.each do |sub| %> "> - <%= sub.user.full_name %> + <%= sub.user.full_name if sub.user %> <%= sub.submitted_at.to_s %> <%= sub.points %>
<%= sub.grader_comment %>
diff --git a/app/views/site/login.html.haml b/app/views/site/login.html.haml new file mode 100644 --- /dev/null +++ b/app/views/site/login.html.haml @@ -0,0 +1,39 @@ +%script{:type => 'text/javascript'} + var siteList = new Array(); + - @countries.each do |country| + = "siteList[#{country.id}] = new Array();" + - country.sites.each do |site| + = "siteList[#{country.id}][#{site.id}] = \"#{site.name}\";" + + var allSiteList = new Array(); + - @site_select.each do |sel| + = "allSiteList[#{sel[1]}]=\"#{sel[0]}\";" + +%script{:type => 'text/javascript', :src => '/javascripts/site_update.js'} + +%div{ :style => "border: solid 1px gray; padding: 2px; background: #f0f0f0;"} + %h2 For Site Administrator. + + - if @default_site + - form_for :login, nil, :url => {:controller => 'login', :action => 'site_login'} do |f| + %b Log in for default site. + = f.hidden_field :site_id, :value => @default_site.id + %br/ + Password: + = f.password_field :password + = submit_tag "Site Administrator Login" + + - else + Please select your country and site and login. + - form_for :login, nil, :url => {:controller => 'login', :action => 'site_login'} do |f| + Country: + = select :site_country, :id, @country_select_with_all, {}, {:onchange => "updateSiteList();", :onclick => "updateSiteList();" } + Site: + = select :login, :site_id, @site_select + %br/ + Password: + = f.password_field :password + = submit_tag "Site Administrator Login" + +%script{:type => 'text/javascript'} + updateSiteList(); diff --git a/app/views/site/prompt.html.haml b/app/views/site/prompt.html.haml --- a/app/views/site/prompt.html.haml +++ b/app/views/site/prompt.html.haml @@ -1,6 +1,6 @@ %h2 Contest Administration for site: - = "#{@site.name}, #{@site.country.name}" + = "#{@site.name}, #{@site.country.name if @site.country}" Current time at the server is diff --git a/app/views/site/started.html.haml b/app/views/site/started.html.haml --- a/app/views/site/started.html.haml +++ b/app/views/site/started.html.haml @@ -1,6 +1,6 @@ %h2 Contest Administration for site: - = "#{@site.name}, #{@site.country.name}" + = "#{@site.name}, #{@site.country.name if @site.country}" - curr_time = Time.new.gmtime diff --git a/app/views/sites/edit.html.erb b/app/views/sites/edit.html.erb --- a/app/views/sites/edit.html.erb +++ b/app/views/sites/edit.html.erb @@ -9,6 +9,11 @@

+ Password
+ <%= f.text_field :password %> +

+ +

Started
<%= f.check_box :started %>

diff --git a/app/views/sites/index.html.erb b/app/views/sites/index.html.erb --- a/app/views/sites/index.html.erb +++ b/app/views/sites/index.html.erb @@ -3,6 +3,7 @@ + @@ -13,6 +14,7 @@ <% background = "lightgreen" if (site.started==true) and (site.finished? != true) %> + diff --git a/app/views/sites/new.html.erb b/app/views/sites/new.html.erb --- a/app/views/sites/new.html.erb +++ b/app/views/sites/new.html.erb @@ -9,6 +9,11 @@

+ Password
+ <%= f.text_field :password %> +

+ +

Started
<%= f.check_box :started %>

diff --git a/app/views/sites/show.html.erb b/app/views/sites/show.html.erb --- a/app/views/sites/show.html.erb +++ b/app/views/sites/show.html.erb @@ -4,6 +4,11 @@

+ Password: + <%=h @site.password %> +

+ +

Started: <%=h @site.started %>

diff --git a/app/views/test/index.html.erb b/app/views/test/index.html.erb --- a/app/views/test/index.html.erb +++ b/app/views/test/index.html.erb @@ -1,11 +1,13 @@ <%= user_title_bar(@user) %> -

Test Interface

+

<%=t 'test.title' %>

-

- Note: Test interface will be disabled in the last 30 minutes - of the contest time on your site. -

+
+ <%=t 'test.intro' %>
+ <% if Configuration['contest.test_request.early_timeout'] %> + <%=t 'test.disabled_at_end_announcement' %> + <% end %> +
<% if @problems.length==0 %> There is no submission @@ -69,21 +71,6 @@ - - - - - diff --git a/app/views/test/result.html.haml b/app/views/test/result.html.haml --- a/app/views/test/result.html.haml +++ b/app/views/test/result.html.haml @@ -27,12 +27,14 @@ %div{:style => "border: 1px solid black; background: lightgrey"} - if @test_request.input_file_name!=nil %pre + = "" = h(read_textfile(@test_request.input_file_name,2048)) %b Output (first 2kb) %div{:style => "border: 1px solid black; background: lightgrey"} - if @test_request.output_file_name!=nil %pre + = "" = h(read_textfile(@test_request.output_file_name,2048)) - else (no output) diff --git a/app/views/user_admin/_form.rhtml b/app/views/user_admin/_form.rhtml --- a/app/views/user_admin/_form.rhtml +++ b/app/views/user_admin/_form.rhtml @@ -13,6 +13,9 @@


<%= password_field 'user', 'password_confirmation' %>

+


+<%= text_field 'user', 'email' %>

+


<%= text_field 'user', 'alias' %>

diff --git a/app/views/user_admin/list.rhtml b/app/views/user_admin/list.rhtml --- a/app/views/user_admin/list.rhtml +++ b/app/views/user_admin/list.rhtml @@ -1,7 +1,3 @@ -<% content_for :head do %> - <%= stylesheet_link_tag 'scaffold' %> -<% end %> -

Listing users

@@ -11,16 +7,16 @@
- - + + - +
NamePassword Started Start time
<%=h site.name %><%=h site.password %> <%=h site.started %> <%=h site.start_time %> <%= link_to 'Show', site %>
- Additional file*: - - <%= f.file_field :additional_file %> - - - * This option works only for task beads. - You can use this to submit questions.txt.
- The file shall be copied to the execution directory before your program runs. -
-
<%= submit_tag 'submit' %>
<%= text_field 'user', 'login', :size => 10 %> <%= text_field 'user', 'full_name', :size => 30 %><%= text_field 'user', 'alias', :size => 10 %> <%= password_field 'user', 'password', :size => 10 %> <%= password_field 'user', 'password_confirmation', :size => 10 %><%= text_field 'user', 'email', :size => 15 %> <%= submit_tag "Create" %>
<% end %> @@ -34,14 +30,18 @@ <% for column in User.content_columns %> - + <% if !@hidden_columns.index(column.name) %> + + <% end %> <% end %> <% for user in @users %> <% for column in User.content_columns %> - + <% if !@hidden_columns.index(column.name) %> + + <% end %> <% end %> diff --git a/app/views/user_admin/user_stat.rhtml b/app/views/user_admin/user_stat.rhtml --- a/app/views/user_admin/user_stat.rhtml +++ b/app/views/user_admin/user_stat.rhtml @@ -1,7 +1,10 @@

User grading results

<%= column.human_name %><%= column.human_name %>
<%=h user.send(column.name) %><%=h user.send(column.name) %><%= link_to 'Show', :action => 'show', :id => user %> <%= link_to 'Edit', :action => 'edit', :id => user %>
- + + + + <% @problems.each do |p| %> <% end %> @@ -14,8 +17,10 @@ <% total = 0 %> <% num_passed = 0 %> <% sc.each_index do |i| %> - <% if i<=1 %> - + <% if i==0 %> + + + <% else %> <% total += sc[i][0] %> diff --git a/app/views/users/confirm.html.haml b/app/views/users/confirm.html.haml --- a/app/views/users/confirm.html.haml +++ b/app/views/users/confirm.html.haml @@ -1,15 +1,17 @@ - if @result == :successful - %h1 User activated - Your account has been activated. + %h1 + =t 'registration.activation_sucessful_title' + =t 'registration.account_activated' %br/ - Please go ahead to - = link_to 'login.', :controller => 'main', :action => 'login' + =t 'go_ahead_to' + = link_to((t 'login_page'), {:controller => 'main', :action => 'login'}) - else - %h1 Activation failed + %h1 + =t 'registration.activation_failed_title' - if @result == :email_used - A user with this E-mail exists. + =t 'registration.errors.activation.email_exists' - else - Your activation code is invalid. Please check again. + =t 'registration.errors.activation.invalid' %br/ - Get back to - = link_to 'home.', :controller => 'main', :action => 'login' + =t 'go_back_to' + = link_to((t 'home_page'), {:controller => 'main', :action => 'login'}) diff --git a/app/views/users/email_error.html.haml b/app/views/users/email_error.html.haml --- a/app/views/users/email_error.html.haml +++ b/app/views/users/email_error.html.haml @@ -1,9 +1,8 @@ -%h1 Errors in sending registration confirmation +%h1 + =t 'registration.errors.email.title' .errorExplanation - %h2 - Your user account has been created, but the system cannot send you the - confirmation e-mail. + =t 'registration.errors.email.expl', :email => @admin_email - Maybe there's a problem in the configuration. Please report the - admin. Thank you! +=t 'go_back_to' +=link_to((t 'login_page'), {:controller => 'main', :action => 'login'}) diff --git a/app/views/users/index.html.haml b/app/views/users/index.html.haml --- a/app/views/users/index.html.haml +++ b/app/views/users/index.html.haml @@ -5,9 +5,8 @@ %h1 Your account settings -%p - You can edit your alias and e-mails. Just click on the text and edit it. - +-#%p + -#You can edit your alias and e-mails. Just click on the text and edit it. %table.uinfo %tr @@ -16,12 +15,12 @@ %tr %th.uinfo Full name %td.uinfo= @user.full_name - %tr - %th.uinfo Alias - %td.uinfo= in_place_editor_field :user, 'alias_for_editing', {}, :rows => 1 - %tr - %th.uinfo E-mail - %td.uinfo= in_place_editor_field :user, 'email_for_editing', {}, :rows => 1 + -#%tr + -#%th.uinfo Alias + -#%td.uinfo= in_place_editor_field :user, 'alias_for_editing', {}, :rows => 1 + -#%tr + -#%th.uinfo E-mail + -#%td.uinfo= in_place_editor_field :user, 'email_for_editing', {}, :rows => 1 %tr %th.uinfo Password %td.uinfo diff --git a/app/views/users/new.html.haml b/app/views/users/new.html.haml --- a/app/views/users/new.html.haml +++ b/app/views/users/new.html.haml @@ -1,29 +1,39 @@ -%h1 New user registration +.contest-title + %h1 + = "#{Configuration['contest.name']}: #{t 'registration.title'}" -= error_messages_for :user, :header_message => 'Errors occured during registration' +.registration-desc + =t 'registration.description' + += error_messages_for :user, :header_message => (t 'registration.errors.header') %table - form_for :user, @user, :url => { :action => 'register' } do |f| %tr - %td Login: + %td{:align => "right"} + = "#{t 'login_label'}:" %td= f.text_field :login %tr %td %td - %small Only a-z, A-Z, 0-9 and _ + %small + =t 'registration.login_guide' %tr - %td Full name: + %td{:align => "right"} + = "#{t 'full_name_label'}:" %td= f.text_field :full_name %tr - %td E-mail: + %td{:align => "right"} + = "#{t 'email_label'}:" %td= f.text_field :email %tr %td %td %small - Please make sure that your e-mail is correct. - %br/ - You'll need to verify your account by email. + =t 'registration.email_guide' %tr - %td{:colspan => 2}= submit_tag "Register" + %td/ + %td + = submit_tag((t 'registration.register'), :name => 'commit') + = submit_tag((t 'cancel'), :name => 'cancel') diff --git a/app/views/users/new_splash.html.haml b/app/views/users/new_splash.html.haml --- a/app/views/users/new_splash.html.haml +++ b/app/views/users/new_splash.html.haml @@ -1,11 +1,11 @@ -%h1 Registration successful +%h1 + =t 'registration.successful_title' -We have sent a confimation message to your e-mail. +=t 'registration.email_sent' %br/ -Please check at -= "#{@user.email}." +=t 'registration.email_verify_at', :email => @user.email %br/ %br/ -Go back to -= link_to 'login page.', :controller => 'main', :action => 'login' +=t 'go_back_to' +=link_to((t 'login_page'), {:controller => 'main', :action => 'login'}) diff --git a/config/environment.rb.SAMPLE b/config/environment.rb.SAMPLE --- a/config/environment.rb.SAMPLE +++ b/config/environment.rb.SAMPLE @@ -5,7 +5,7 @@ # ENV['RAILS_ENV'] ||= 'production' # Specifies gem version of Rails to use when vendor/rails is not present -RAILS_GEM_VERSION = '2.1.1' unless defined? RAILS_GEM_VERSION +RAILS_GEM_VERSION = '2.3.2' unless defined? RAILS_GEM_VERSION # Bootstrap the Rails environment, frameworks, and default configuration require File.join(File.dirname(__FILE__), 'boot') @@ -39,19 +39,23 @@ # config.active_record.observers = :cacher, :garbage_collector # Make Active Record use UTC-base instead of local time - config.active_record.default_timezone = :utc + config.time_zone = 'UTC' + # Setting locales + config.i18n.default_locale = 'th' + # See Rails::Configuration for more options # ------------- # Required gems # ------------- - - # This is for rspec - config.gem "rspec-rails", :lib => "spec" config.gem "haml" config.gem "tmail" - #config.gem "BlueCloth", :lig => "bluecloth" + config.gem "BlueCloth", :lib => "bluecloth" + + # NOTES on rspec: if you wan to test with rspec, you have to install + # rspec yourself, just call: [sudo] gem install rspec-rails + end # Add new inflection rules using the following format @@ -73,5 +77,13 @@ TEST_REQUEST_INPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/input' TEST_REQUEST_OUTPUT_FILE_DIR = RAILS_ROOT + '/data/test_request/output' +# To use ANALYSIS MODE, provide the testcases/testruns breakdown, +# and the directory of the grading result (usually in judge's dir). +TASK_GRADING_INFO_FILENAME = RAILS_ROOT + '/config/tasks.yml' +GRADING_RESULT_DIR = '/home/thailandoi/ytopc/judge/result' + # Uncomment so that configuration is read only once when the server is loaded # Configuration.enable_caching + +# Uncomment so that the system validates user e-mails +# VALIDATE_USER_EMAILS = true diff --git a/config/environments/development.rb b/config/environments/development.rb --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -14,7 +14,6 @@ # Show full error reports and disable caching config.action_controller.consider_all_requests_local = true config.action_controller.perform_caching = false -config.action_view.cache_template_extensions = false config.action_view.debug_rjs = true # Don't care if the mailer can't send diff --git a/config/environments/test.rb b/config/environments/test.rb --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -16,4 +16,4 @@ # Tell ActionMailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. -config.action_mailer.delivery_method = :test \ No newline at end of file +config.action_mailer.delivery_method = :test diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,118 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +en: + cancel: 'Cancel' + + login_label: 'Login' + full_name_label: 'Full name' + email_label: 'E-mail' + password_label: 'Password' + + go_ahead_to: "Go ahead to" + go_back_to: "Go back to" + login_page: "login page" + home_page: "home page" + + menu: + main: 'Main' + messages: 'Messages' + tasks: 'Tasks' + submissions: 'Submissions' + test: 'Test Interface' + help: 'Help' + settings: 'Settings' + log_out: 'Log out' + + title_bar: + current_time: "Current time is" + remaining_time: "Time left: " + contest_not_started: "The contest has not started." + + login: + message: 'Please login to see the problem list' + login_submit: 'Login' + participation: 'Want to participate?' + please: 'Please' + register: 'register' + + main: + start_soon: "The contest at your site will start soon. Please wait." + specified_in_header: "Specified in header" + + problem_desc: "desc" + submitted_at: "Submitted at" + graded_at: "Graded at" + score: "score: " + cmp_msg: "compiler msg" + src_link: "src" + submissions_link: "submissions" + + test: + title: "Test Interface" + intro: "You can test your submission with your own test data on the grading environment using this test interface." + disabled_at_end_announcement: "Note: Test interface will be disabled in the last 30 minutes of the contest time on your site." + + registration: + title: "New user registration" + successful_title: "Registration successful" + + login_guide: "Only a-z, A-Z, 0-9 and _. Can be at most 20 characters long" + email_guide: "Please make sure that your e-mail is correct.
You'll need to verify your account by email." + register: "Register" + + email_body: "Hello {{full_name}}, + +You have registered for {{contest_name}} + +Your login is: {{login}} + +Your password is: {{password}} + +Please follow the link: + +{{activation_url}} + +to activate your user account. + +If you did not register, please ignore this e-mail +and report this event to {{admin_email}}. + +Thanks!" + + email_sent: "We have sent a confimation message to your e-mail. (Please also check the Junk mail box." + email_verify_at: "Please check at {{email}} and confirm." + + activation_sucessful_title: "User activated" + account_activated: "Your account has been activated." + + activation_failed_title: "Activation failed" + + errors: + header: "Errors occured during registration" + email: + title: "Errors in sending registration confirmation" + expl: "

Your user account has been created, but the system cannot send you the confirmation e-mail.

+Maybe there's a problem in the configuration. Please report the admin at {{email}}.
Thank you!" + activation: + email_exists: "A user with this E-mail exists." + invalid: "Your activation code is invalid. Please check again." + + help: + how_to_submit: "How to submit" + must_specify_language: "You must specify the language you are using in your program header. You can optionally specify the task you are submitting to." + list_available_language: "The possible language options are C, C++, and Pascal. The follow are examples." + accept_only_language_specified: "The server will not accept your submission, if you do not specify the language." + specifying_task: "Optionally, you can also specify the task with TASK:taskname. On the first page, the taskname for each task is shown in parentheses." + example_cpp: "For example, suppose you are using C++ to write task mobiles, you put the following on top of your source code." + example_pas: "If you are using Pascal to write the same task, you'll use" + ask_questions_at_messages: "If you have any problems, you can ask at [{{message_link_name}}]." + + activerecord: + attributes: + user: + login: "login" + full_name: "full name" + email: "e-mail" + province: "province" + diff --git a/config/locales/th.rb b/config/locales/th.rb new file mode 100644 --- /dev/null +++ b/config/locales/th.rb @@ -0,0 +1,106 @@ +{ + :'th' => { + :date => { + :formats => { + :default => lambda { |date| "%d-%m-#{date.year+543}" }, + :short => "%e %b", + :long => lambda { |date| "%e %B #{date.year+543}" }, + :long_ordinal => lambda { |date| "%e %B #{date.year+543}" }, + :only_day => "%e" + }, + :day_names => %w(อาทิตย์ จันทร์ อังคาร พุธ พฤหัสบดี ศุกร์ เสาร์), + :abbr_day_names => %w(อา จ อ พ พฤ ศ ส), + :month_names => [nil] + %w(มกราคม กุมภาพันธ์ มีนาคม เมษายน พฤษภาคม มิถุนายน กรกฎาคม สิงหาคม กันยายน ตุลาคม พฤศจิกายน ธันวาคม), + :abbr_month_names => [nil] + %w(ม.ค. ก.พ. มี.ค. เม.ย. พ.ค. มิ.ย. ก.ค. ส.ค. ก.ย. ต.ค. พ.ย. ธ.ค.), + :order => [:day, :month, :year] + }, + :time => { + :formats => { + :default => lambda { |time| "%a %d %b #{time.year+543} %H:%M:%S %Z" }, + :time => "%H:%M น.", + :short => "%d %b %H:%M น.", + :long => lambda { |time| "%d %B #{time.year+543} %H:%M น." }, + :long_ordinal => lambda { |time| "%d %B #{time.year+543} %H:%M น." }, + :only_second => "%S" + }, + :time_with_zone => { + :formats => { + :default => lambda { |time| "%Y-%m-%d %H:%M:%S #{time.formatted_offset(false, 'UTC')}" } + } + }, + :am => '', + :pm => '' + }, + :datetime => { + :formats => { + :default => "%Y-%m-%dT%H:%M:%S%Z" + }, + :distance_in_words => { + :half_a_minute => 'ครึ่งนาทีที่ผ่านมา', + :less_than_x_seconds => 'น้อยกว่า {{count}} วินาที', + :x_seconds => '{{count}} วินาที', + :less_than_x_minutes => 'น้อยกว่า {{count}} วินาที', + :x_minutes => '{{count}} นาที', + :about_x_hours => 'ประมาณ {{count}} ชั่วโมง', + :x_hours => '{{count}} ชั่วโมง', + :about_x_days => 'ประมาณ {{count}} วัน', + :x_days => '{{count}} วัน', + :about_x_months => 'ประมาณ {{count}} เดือน', + :x_months => '{{count}} เดือน', + :about_x_years => 'ประมาณ {{count}} ปี', + :over_x_years => 'เกิน {{count}} ปี' + } + }, + + # numbers + :number => { + :format => { + :precision => 3, + :separator => '.', + :delimiter => ',' + }, + :currency => { + :format => { + :unit => 'Baht', + :precision => 2, + :format => '%n %u' + } + }, + }, + + # Active Record + :activerecord => { + :errors => { + :template => { + :header => { + :one => "ไม่สามารถบันทึก {{model}} ได้เนื่องจากเกิดข้อผิดพลาด", + :other => "ไม่สามารถบันทึก {{model}} ได้เนื่องจากเกิด {{count}} ข้อผิดพลาด" + }, + :body => "โปรดตรวจสอบข้อมูลที่คุณกรอกในช่องต่อไปนี้:" + }, + :messages => { + :inclusion => "ไม่ได้อยู่ในลิสต์", + :exclusion => "ถูกจองเอาไว้แล้ว", + :invalid => "ไม่ถูกต้อง", + :confirmation => "ไม่ตรงกับการยืนยัน", + :accepted => "ต้องอยู่ในรูปแบบที่ยอมรับ", + :empty => "ต้องไม้เว้นว่างเอาไว้", + :blank => "ต้องไม่เว้นว่างเอาไว้", + :too_long => "ยาวเกินไป (ต้องไม่เกิน {{count}} ตัวอักษร)", + :too_short => "สั้นเกินไป (ต้องยาวกว่า {{count}} ตัวอักษร)", + :wrong_length => "มีความยาวไม่ถูกต้อง (ต้องมีความยาว {{count}} ตัวอักษร)", + :taken => "ถูกใช้ไปแล้ว", + :not_a_number => "ไม่ใช่ตัวเลข", + :greater_than => "ต้องมากกว่า {{count}}", + :greater_than_or_equal_to => "ต้องมากกว่าหรือเท่ากับ {{count}}", + :equal_to => "ต้องเท่ากับ {{count}}", + :less_than => "ต้องน้อยกว่า {{count}}", + :less_than_or_equal_to => "ต้องน้อยกว่าหรือเท่ากับ {{count}}", + :odd => "ต้องเป็นเลขคี่", + :even => "ต้องเป็นเลขคู่" + } + } + } + } +} + diff --git a/config/locales/th.yml b/config/locales/th.yml new file mode 100644 --- /dev/null +++ b/config/locales/th.yml @@ -0,0 +1,121 @@ +# Sample localization file for English. Add more files in this directory for other locales. +# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. + +th: + cancel: 'ยกเลิก' + + login_label: 'ชื่อเข้าใช้ระบบ (login)' + full_name_label: 'ชื่อเต็ม' + email_label: 'E-mail' + password_label: 'รหัสผ่าน' + + go_ahead_to: "ไปยัง" + go_back_to: "กลับไปยัง" + login_page: "หน้าเข้าใช้ระบบ" + home_page: "หน้าแรก" + + menu: + main: 'หน้าหลัก' + messages: 'ข้อความ' + tasks: 'โจทย์' + submissions: 'โปรแกรมที่ส่ง' + test: 'ทดสอบโปรแกรม' + help: 'ความช่วยเหลือ' + settings: 'เปลี่ยนรหัสผ่าน' + log_out: 'ออกจากระบบ' + + title_bar: + current_time: "เวลาปัจจุบันคือ" + remaining_time: "เหลือเวลาอีก" + contest_not_started: "ยังไม่เริ่มแข่งขัน" + + login: + message: 'กรุณา login เพื่อเข้าสู่ระบบ' + login_submit: 'เข้าใช้ระบบ' + participation: 'ต้องการเข้าร่วม?' + please: 'กรุณา' + register: 'ลงทะเบียน' + + main: + start_soon: "การแข่งขันกำลังจะเริ่ม กรุณารอก่อน" + specified_in_header: "ระบุที่หัวโปรแกรมแล้ว" + + problem_desc: "อ่าน" + submitted_at: "ส่งเมื่อเวลา" + graded_at: "ตรวจเมื่อเวลา" + score: "คะแนน: " + cmp_msg: "ผลคอมไพล์" + src_link: "ต้นฉบับ" + submissions_link: "การส่งครั้งอื่น ๆ" + + test: + title: "ทดสอบโปรแกรมบนสภาพแวดล้อมของเครื่องตรวจ" + intro: "คุณสามารถทดลองการทำงานของโปรแกรมที่เขียนกับข้อมูลชุดทดสอบของคุณเองในสภาพแวดล้อมจริงของการตรวจโปรแกรมได้ โดยเลือกโปรแกรมส่งแล้วที่ด้านล่างพร้อมทั้งส่งแฟ้มข้อมูลชุดทดสอบที่ต้องการให้ทำงานด้วย" + disabled_at_end_announcement: "หมายเหตุ: ระบบทดสอบโปรแกรมจะหยุดทำงานในช่วงเวลา 30 นาทีสุดท้ายของการแข่งขัน" + + + registration: + title: "ลงทะเบียนผู้ใช้ใหม่" + description: "ในการลงทะเบียน ให้ผู้สนใจเข้าร่วมการแข่งขันกรอกข้อมูลด้านล่าง จากนั้นระบบจะส่ง e-mail ไปยัง e-mail ที่ระบุเพื่อให้ยืนยันตัวตนและเปิดใช้บัญชีผู้ใช้
ในกรณีที่ผู้เข้าแข่งขันเป็นนักเรียน รบกวนช่วยให้ข้อมูลเกี่ยวกับโรงเรียนและจังหวัดด้วย" + + successful_title: "การลงทะเบียนเสร็จเรียบร้อย" + + login_guide: "ใช้ได้เฉพาะ a-z, A-Z, 0-9 และ _ ความยาวไม่เกิน 20 ตัวอักษร" + email_guide: "กรุณาตรวจสอบ e-mail ที่ใส่ให้ถูกต้อง
คุณจะต้องยืนยันการลงทะเบียนผ่านทางข้อมูลที่จะส่งให้ทาง e-mail" + register: "ลงทะเบียน" + + email_body: "สวัสดีครับ {{full_name}}, + +คุณได้ลงทะเบียนเข้าร่วมการแข่งขัน {{contest_name}} + +บัญชีเข้าใช้ของคุณคือ: {{login}} + +รหัสผ่านคือ: {{password}} + +กรุณาเข้าลิงก์ต่อไปนี้: + +{{activation_url}} + +เพื่อเปิดใช้งานบัญชีของคุณ + +ถ้าคุณไม่ใช้คนที่ลงทะเบียน กรุณาละทิ้ง e-mail ฉบับนี้ +และแจ้งความผิดพลาดนี้กับ {{admin_email}} + +ขอบคุณมาก!" + + email_sent: "เราได้ส่งข้อมูลสำหรับยืนยันไปให้คุณแล้ว (โปรดอย่าลืมตรวจดูในส่วน Junk mail ด้วย)" + email_verify_at: "กรุณาตรวจสอบที่ {{email}} พร้อมทั้งยืนยัน" + + activation_sucessful_title: "บัณชีผู้ใช้ได้รับการยืนยันแล้ว" + account_activated: "บัญชีผู้ใช้ของคุณพร้อมใช้งานแล้ว" + + activation_failed_title: "การยืนยันล้มเหลว" + + errors: + header: 'การลงทะเบียนมีข้อผิดพลาด' + email: + title: "เกิดปัญหาระหว่างการส่ง e-mail เพื่อยืนยันการสมัคร" + expl: "

บัญชีผู้ใช้ของคุณถูกสร้างขึ้นแล้ว แต่ระบบไม่สามารถส่ง e-mail เพื่อยืนยันการสมัครได้

+อาจเกิดปัญหาในการตั้งค่าเริ่มต้นของระบบ กรุณาช่วยติดต่อผู้ดูแลระบบด้วยที่ {{email}}
ขอขอบคุณจากทีมงาน" + activation: + email_exists: "มีผู้ใช้ที่ใช้ e-mail นี้แล้ว" + invalid: "รหัสสำหรับยืนยันผิดพลาด กรุณาตรวจสอบอีกครั้ง" + + help: + how_to_submit: "วิธีการส่งโปรแกรม" + must_specify_language: "คุณต้องระบุภาษาโปรแกรมที่ใช้ที่ตอนต้นของรหัสโปรแกรม (source code) นอกจากนี้คุณอาจจะระบุโจทย์ที่ต้องการส่งได้ด้วย" + list_available_language: "ภาษาโปรแกรมที่สามารถระบุได้คือ C, C++, และ Pascal ด้านล่างแสดงตัวอย่างของการระบุสำหรับภาษาต่าง ๆ" + accept_only_language_specified: "ระบบจะไม่รับโปรแกรมที่ส่งถ้าคุณไม่ได้ระบุภาษาที่ใช้" + specifying_task: "นอกจากนี้ คุณยังสามารถระบุชื่อของโจทย์ที่ต้องการส่งเพิ่มเติมได้ ในการระบุให้ใส่ TASK:taskname คุณสามารถตรวจสอบชื่อของโจทย์ได้ โดยจะแสดงในวงเล็บหลังชื่อภาษาไทยของโจทย์" + example_cpp: "ยกตัวอย่างเช่น ถ้าคุณใช้ภาษา C++ สำหรับเขียนโจทย์ mobiles ตอนต้นโปรแกรมคุณจะใส่ดังนี้" + example_pas: "ถ้าคุณใช้ภาษา Pascal เพื่อเขียนโจทย์ข้อเดียวกัน คุณจะระบุ" + ask_questions_at_messages: "ถ้ามีปัญหาในการใช้งานสามารถสอบถามได้ที่หน้า{{message_link_name}}" + + activerecord: + attributes: + user: + login: "ชื่อเข้าใช้ระบบ" + full_name: "ชื่อเต็ม" + email: "e-mail" + province: "จังหวัด" + diff --git a/config/tasks.yml.SAMPLE b/config/tasks.yml.SAMPLE new file mode 100644 --- /dev/null +++ b/config/tasks.yml.SAMPLE @@ -0,0 +1,31 @@ +--- +beads: + testcases: 20 + testruns: 20 +dna: + testcases: 15 + testruns: 15 +roads: + testcases: 11 + testruns: + 1: + - 1 + - 11 + 2: + - 2 + 3: + - 3 + 4: + - 4 + 5: + - 5 + 6: + - 6 + 7: + - 7 + 8: + - 8 + 9: + - 9 + 10: + - 10 diff --git a/db/migrate/20081214185157_add_admin_email_to_config.rb b/db/migrate/20081214185157_add_admin_email_to_config.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20081214185157_add_admin_email_to_config.rb @@ -0,0 +1,11 @@ +class AddAdminEmailToConfig < ActiveRecord::Migration + def self.up + Configuration.create(:key => 'system.admin_email', + :value_type => 'string', + :value => 'admin@admin.email') + end + + def self.down + Configuration.find_by_key('system.admin_email').destroy + end +end diff --git a/db/migrate/20081215012843_change_user_login_string_limit.rb b/db/migrate/20081215012843_change_user_login_string_limit.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20081215012843_change_user_login_string_limit.rb @@ -0,0 +1,9 @@ +class ChangeUserLoginStringLimit < ActiveRecord::Migration + def self.up + execute "ALTER TABLE `users` CHANGE `login` `login` VARCHAR( 50 )" + end + + def self.down + execute "ALTER TABLE `users` CHANGE `login` `login` VARCHAR( 10 )" + end +end diff --git a/db/migrate/20090202101806_add_test_request_early_timeout_to_config.rb b/db/migrate/20090202101806_add_test_request_early_timeout_to_config.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20090202101806_add_test_request_early_timeout_to_config.rb @@ -0,0 +1,15 @@ +class AddTestRequestEarlyTimeoutToConfig < ActiveRecord::Migration + def self.up + # If Configuration['contest.test_request.early_timeout'] is true + # the user will not be able to use test request at 30 minutes + # before the contest ends. + + Configuration.create(:key => 'contest.test_request.early_timeout', + :value_type => 'boolean', + :value => 'false') + end + + def self.down + Configuration.find_by_key('contest.test_request.early_timeout').destroy + end +end diff --git a/db/migrate/20090206145016_add_contest_flag_to_announcements.rb b/db/migrate/20090206145016_add_contest_flag_to_announcements.rb new file mode 100644 --- /dev/null +++ b/db/migrate/20090206145016_add_contest_flag_to_announcements.rb @@ -0,0 +1,9 @@ +class AddContestFlagToAnnouncements < ActiveRecord::Migration + def self.up + add_column :announcements, :contest_only, :boolean, :default => false + end + + def self.down + remove_column :announcements, :contest_only + end +end diff --git a/db/schema.rb b/db/schema.rb --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20081210021333) do +ActiveRecord::Schema.define(:version => 20090206145016) do create_table "announcements", :force => true do |t| t.string "author" @@ -17,7 +17,8 @@ t.boolean "published" t.datetime "created_at" t.datetime "updated_at" - t.boolean "frontpage", :default => false + t.boolean "frontpage", :default => false + t.boolean "contest_only", :default => false end create_table "configurations", :force => true do |t| @@ -174,7 +175,7 @@ add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id" create_table "users", :force => true do |t| - t.string "login", :limit => 10 + t.string "login", :limit => 50 t.string "full_name" t.string "hashed_password" t.string "salt", :limit => 5 diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -1,6 +1,7 @@ /* Normal text */ -p { - font-size: 12px; +body { + font-size: 13px; + font-family: "Sans Serif"; } /* This is the main menu bad*/ @@ -227,3 +228,33 @@ background: green; font-weight: bold; } + +/******************** + Registration +********************/ +div.contest-title { + color: white; + background: #007700; + text-align: center; + padding: 5px; +} + +div.registration-desc { + margin-top: 5px; + margin-bottom: 5px; + border: solid 1px gray; + padding: 10px; + background: #f0f0f0; +} + +/******************** + [Test Interface] +********************/ + +div.test-desc { + border: solid 1px gray; + background: #f0f0f0; + padding: 5px; + font-size: 12px; + margin-bottom: 5px; +} diff --git a/public/stylesheets/scaffold.css b/public/stylesheets/scaffold.css deleted file mode 100644 --- a/public/stylesheets/scaffold.css +++ /dev/null @@ -1,74 +0,0 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - -pre { - background-color: #eee; - padding: 10px; - font-size: 11px; -} - -a { color: #000; } -a:visited { color: #666; } -a:hover { color: #fff; background-color:#000; } - -.fieldWithErrors { - padding: 2px; - background-color: red; - display: table; -} - -#errorExplanation { - width: 400px; - border: 2px solid red; - padding: 7px; - padding-bottom: 12px; - margin-bottom: 20px; - background-color: #f0f0f0; -} - -#errorExplanation h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; - font-size: 12px; - margin: -7px; - background-color: #c00; - color: #fff; -} - -#errorExplanation p { - color: #333; - margin-bottom: 0; - padding: 5px; -} - -#errorExplanation ul li { - font-size: 12px; - list-style: square; -} - -div.uploadStatus { - margin: 5px; -} - -div.progressBar { - margin: 5px; -} - -div.progressBar div.border { - background-color: #fff; - border: 1px solid gray; - width: 100%; -} - -div.progressBar div.background { - background-color: #333; - height: 18px; - width: 0%; -} - diff --git a/script/about b/script/about old mode 100644 new mode 100755 diff --git a/script/breakpointer b/script/breakpointer old mode 100644 new mode 100755 diff --git a/script/console b/script/console old mode 100644 new mode 100755 diff --git a/script/destroy b/script/destroy old mode 100644 new mode 100755 diff --git a/script/generate b/script/generate old mode 100644 new mode 100755 diff --git a/script/plugin b/script/plugin old mode 100644 new mode 100755 diff --git a/script/runner b/script/runner old mode 100644 new mode 100755 diff --git a/script/server b/script/server old mode 100644 new mode 100755
UserName
UserNameActivated?<%= p.name %><%= sc[i] %><%= sc[i].login %><%= sc[i].full_name %><%= sc[i].activated %><%= sc[i][0] %>