Description:
[web] added site and time out basic functionality git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@169 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r85:f0e9de51d9aa - - 23 files changed: 442 inserted, 9 deleted

@@ -0,0 +1,87
1 + class SitesController < ApplicationController
2 + # GET /sites
3 + # GET /sites.xml
4 + def index
5 + @sites = Site.find(:all)
6 +
7 + respond_to do |format|
8 + format.html # index.html.erb
9 + format.xml { render :xml => @sites }
10 + end
11 + end
12 +
13 + # GET /sites/1
14 + # GET /sites/1.xml
15 + def show
16 + @site = Site.find(params[:id])
17 +
18 + respond_to do |format|
19 + format.html # show.html.erb
20 + format.xml { render :xml => @site }
21 + end
22 + end
23 +
24 + # GET /sites/new
25 + # GET /sites/new.xml
26 + def new
27 + @site = Site.new
28 +
29 + respond_to do |format|
30 + format.html # new.html.erb
31 + format.xml { render :xml => @site }
32 + end
33 + end
34 +
35 + # GET /sites/1/edit
36 + def edit
37 + @site = Site.find(params[:id])
38 + end
39 +
40 + # POST /sites
41 + # POST /sites.xml
42 + def create
43 + @site = Site.new(params[:site])
44 + @site.clear_start_time_if_not_started
45 +
46 + respond_to do |format|
47 + if @site.save
48 + flash[:notice] = 'Site was successfully created.'
49 + format.html { redirect_to(@site) }
50 + format.xml { render :xml => @site, :status => :created, :location => @site }
51 + else
52 + format.html { render :action => "new" }
53 + format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
54 + end
55 + end
56 + end
57 +
58 + # PUT /sites/1
59 + # PUT /sites/1.xml
60 + def update
61 + @site = Site.find(params[:id])
62 + @site.clear_start_time_if_not_started
63 +
64 + respond_to do |format|
65 + if @site.update_attributes(params[:site])
66 + flash[:notice] = 'Site was successfully updated.'
67 + format.html { redirect_to(@site) }
68 + format.xml { head :ok }
69 + else
70 + format.html { render :action => "edit" }
71 + format.xml { render :xml => @site.errors, :status => :unprocessable_entity }
72 + end
73 + end
74 + end
75 +
76 + # DELETE /sites/1
77 + # DELETE /sites/1.xml
78 + def destroy
79 + @site = Site.find(params[:id])
80 + @site.destroy
81 +
82 + respond_to do |format|
83 + format.html { redirect_to(sites_url) }
84 + format.xml { head :ok }
85 + end
86 + end
87 + end
@@ -0,0 +1,2
1 + module SitesHelper
2 + end
@@ -0,0 +1,24
1 + class Site < ActiveRecord::Base
2 +
3 + def clear_start_time_if_not_started
4 + if !self.started
5 + self.start_time = nil
6 + end
7 + end
8 +
9 + def finished?
10 + if !self.started
11 + return false
12 + end
13 +
14 + contest_time = Configuration['contest.time_limit']
15 + if tmatch = /(\d+):(\d+)/.match(contest_time)
16 + h = tmatch[1].to_i
17 + m = tmatch[2].to_i
18 + return Time.now > (self.start_time + h.hour + m.minute)
19 + else
20 + false
21 + end
22 + end
23 +
24 + end
@@ -0,0 +1,17
1 + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 +
4 + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 + <head>
6 + <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
7 + <title>Sites: <%= controller.action_name %></title>
8 + <%= stylesheet_link_tag 'scaffold' %>
9 + </head>
10 + <body>
11 +
12 + <p style="color: green"><%= flash[:notice] %></p>
13 +
14 + <%= yield %>
15 +
16 + </body>
17 + </html>
@@ -0,0 +1,27
1 + <h1>Editing site</h1>
2 +
3 + <%= error_messages_for :site %>
4 +
5 + <% form_for(@site) do |f| %>
6 + <p>
7 + <b>Name</b><br />
8 + <%= f.text_field :name %>
9 + </p>
10 +
11 + <p>
12 + <b>Started</b><br />
13 + <%= f.check_box :started %>
14 + </p>
15 +
16 + <p>
17 + <b>Start time</b><br />
18 + <%= f.datetime_select :start_time %>
19 + </p>
20 +
21 + <p>
22 + <%= f.submit "Update" %>
23 + </p>
24 + <% end %>
25 +
26 + <%= link_to 'Show', @site %> |
27 + <%= link_to 'Back', sites_path %>
@@ -0,0 +1,24
1 + <h1>Listing sites</h1>
2 +
3 + <table>
4 + <tr>
5 + <th>Name</th>
6 + <th>Started</th>
7 + <th>Start time</th>
8 + </tr>
9 +
10 + <% for site in @sites %>
11 + <tr>
12 + <td><%=h site.name %></td>
13 + <td><%=h site.started %></td>
14 + <td><%=h site.start_time %></td>
15 + <td><%= link_to 'Show', site %></td>
16 + <td><%= link_to 'Edit', edit_site_path(site) %></td>
17 + <td><%= link_to 'Destroy', site, :confirm => 'Are you sure?', :method => :delete %></td>
18 + </tr>
19 + <% end %>
20 + </table>
21 +
22 + <br />
23 +
24 + <%= link_to 'New site', new_site_path %>
@@ -0,0 +1,26
1 + <h1>New site</h1>
2 +
3 + <%= error_messages_for :site %>
4 +
5 + <% form_for(@site) do |f| %>
6 + <p>
7 + <b>Name</b><br />
8 + <%= f.text_field :name %>
9 + </p>
10 +
11 + <p>
12 + <b>Started</b><br />
13 + <%= f.check_box :started %>
14 + </p>
15 +
16 + <p>
17 + <b>Start time</b><br />
18 + <%= f.datetime_select :start_time %>
19 + </p>
20 +
21 + <p>
22 + <%= f.submit "Create" %>
23 + </p>
24 + <% end %>
25 +
26 + <%= link_to 'Back', sites_path %>
@@ -0,0 +1,18
1 + <p>
2 + <b>Name:</b>
3 + <%=h @site.name %>
4 + </p>
5 +
6 + <p>
7 + <b>Started:</b>
8 + <%=h @site.started %>
9 + </p>
10 +
11 + <p>
12 + <b>Start time:</b>
13 + <%=h @site.start_time %>
14 + </p>
15 +
16 +
17 + <%= link_to 'Edit', edit_site_path(@site) %> |
18 + <%= link_to 'Back', sites_path %>
@@ -0,0 +1,15
1 + class CreateSites < ActiveRecord::Migration
2 + def self.up
3 + create_table :sites do |t|
4 + t.string :name
5 + t.boolean :started
6 + t.datetime :start_time
7 +
8 + t.timestamps
9 + end
10 + end
11 +
12 + def self.down
13 + drop_table :sites
14 + end
15 + end
@@ -0,0 +1,22
1 + class AddSiteToUserAndAddDefaultSite < ActiveRecord::Migration
2 + def self.up
3 + default_site = Site.new({:name => 'default',
4 + :started => false})
5 + default_site.save!
6 +
7 + add_column :users, :site_id, :integer
8 + User.reset_column_information
9 +
10 + User.find(:all).each do |user|
11 + user.site_id = default_site.id
12 + user.save
13 + end
14 + end
15 +
16 + def self.down
17 + remove_column :users, :site_id
18 +
19 + default_site = Site.find_by_name('default')
20 + default_site.destroy
21 + end
22 + end
@@ -0,0 +1,43
1 +
2 + require File.dirname(__FILE__) + '/../spec_helper'
3 +
4 + describe Site do
5 +
6 + before(:each) do
7 + start_time = Time.local(2008,5,10,9,00)
8 + @site = Site.new({:name => 'Test site',
9 + :started => true,
10 + :start_time => start_time })
11 + end
12 +
13 + it "should report that the contest is not finished when the contest time limit is not set" do
14 + Configuration.should_receive(:[]).with('contest.time_limit').
15 + and_return('unlimit')
16 + Time.should_not_receive(:now)
17 + @site.finished?.should == false
18 + end
19 +
20 + it "should report that the contest is finished when the contest is over" do
21 + Configuration.should_receive(:[]).with('contest.time_limit').
22 + and_return('5:00')
23 + Time.should_receive(:now).and_return(Time.local(2008,5,10,14,01))
24 + @site.finished?.should == true
25 + end
26 +
27 + it "should report if the contest is finished correctly, when the contest is over, and the contest time contains some minutes" do
28 + Configuration.should_receive(:[]).twice.with('contest.time_limit').
29 + and_return('5:15')
30 + Time.should_receive(:now).
31 + and_return(Time.local(2008,5,10,14,14),Time.local(2008,5,10,14,16))
32 + @site.finished?.should == false
33 + @site.finished?.should == true
34 + end
35 +
36 + it "should report that the contest is not finished, when the time is exactly at the finish time" do
37 + Configuration.should_receive(:[]).with('contest.time_limit').
38 + and_return('5:00')
39 + Time.should_receive(:now).and_return(Time.local(2008,5,10,14,00))
40 + @site.finished?.should == false
41 + end
42 +
43 + end
@@ -0,0 +1,11
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + one:
4 + name: MyString
5 + started: false
6 + start_time: 2008-04-09 14:08:28
7 +
8 + two:
9 + name: MyString
10 + started: false
11 + start_time: 2008-04-09 14:08:28
@@ -0,0 +1,45
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class SitesControllerTest < ActionController::TestCase
4 + def test_should_get_index
5 + get :index
6 + assert_response :success
7 + assert_not_nil assigns(:sites)
8 + end
9 +
10 + def test_should_get_new
11 + get :new
12 + assert_response :success
13 + end
14 +
15 + def test_should_create_site
16 + assert_difference('Site.count') do
17 + post :create, :site => { }
18 + end
19 +
20 + assert_redirected_to site_path(assigns(:site))
21 + end
22 +
23 + def test_should_show_site
24 + get :show, :id => sites(:one).id
25 + assert_response :success
26 + end
27 +
28 + def test_should_get_edit
29 + get :edit, :id => sites(:one).id
30 + assert_response :success
31 + end
32 +
33 + def test_should_update_site
34 + put :update, :id => sites(:one).id, :site => { }
35 + assert_redirected_to site_path(assigns(:site))
36 + end
37 +
38 + def test_should_destroy_site
39 + assert_difference('Site.count', -1) do
40 + delete :destroy, :id => sites(:one).id
41 + end
42 +
43 + assert_redirected_to sites_path
44 + end
45 + end
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class SiteTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + def test_truth
6 + assert true
7 + end
8 + end
@@ -44,14 +44,26
44 44 role.rights.detect{ |right|
45 45 right.controller == self.class.controller_name and
46 46 (right.action == 'all' or right.action == action_name)
47 47 }
48 48 }
49 49 flash[:notice] = 'You are not authorized to view the page you requested'
50 50 #request.env['HTTP_REFERER'] ? (redirect_to :back) : (redirect_to :controller => 'login')
51 51 redirect_to :controller => 'main', :action => 'login'
52 52 return false
53 53 end
54 54 end
55 55
56 + def verify_time_limit
57 + return true if session[:user_id]==nil
58 + user = User.find(session[:user_id], :include => :site)
59 + return true if user==nil or user.site == nil
60 + if user.site.finished?
61 + flash[:notice] = 'Error: the contest on your site is over.'
62 + redirect_to :back
63 + return false
64 + end
65 + return true
66 + end
67 +
56 68 end
57 69
@@ -1,42 +1,56
1 1 class MainController < ApplicationController
2 2
3 3 before_filter :authenticate, :except => [:index, :login]
4 4
5 + #
6 + # COMMENT OUT: filter in each action instead
7 + #
8 + # before_filter :verify_time_limit, :only => [:submit]
9 +
5 10 verify :method => :post, :only => [:submit],
6 11 :redirect_to => { :action => :index }
7 12
8 13
9 14 def index
10 15 redirect_to :action => 'login'
11 16 end
12 17
13 18 def login
14 19 saved_notice = flash[:notice]
15 20 reset_session
16 21 flash[:notice] = saved_notice
17 22
18 23 render :action => 'login', :layout => 'empty'
19 24 end
20 25
21 26 def list
22 27 prepare_list_information
23 28 end
24 29
25 30 def submit
31 + user = User.find(session[:user_id])
32 +
26 33 @submission = Submission.new(params[:submission])
27 - @submission.user_id = session[:user_id]
34 + @submission.user = user
28 35 @submission.language_id = 0
29 36 @submission.source = params['file'].read if params['file']!=''
30 37 @submission.submitted_at = Time.new
38 +
39 + if user.site!=nil and user.site.finished?
40 + @submission.errors.add_to_base "The contest is over."
41 + prepare_list_information
42 + render :action => 'list' and return
43 + end
44 +
31 45 if @submission.valid?
32 46 if @submission.save == false
33 47 flash[:notice] = 'Error saving your submission'
34 48 elsif Task.create(:submission_id => @submission.id,
35 49 :status => Task::STATUS_INQUEUE) == false
36 50 flash[:notice] = 'Error adding your submission to task queue'
37 51 end
38 52 else
39 53 prepare_list_information
40 54 render :action => 'list' and return
41 55 end
42 56 redirect_to :action => 'list'
@@ -1,27 +1,38
1 1 class TestController < ApplicationController
2 2
3 3 before_filter :authenticate
4 4
5 + #
6 + # COMMENT OUT: filter in each action instead
7 + #
8 + # before_filter :verify_time_limit, :only => [:submit]
9 +
5 10 verify :method => :post, :only => [:submit],
6 11 :redirect_to => { :action => :index }
7 12
8 13 def index
9 14 @user = User.find(session[:user_id])
10 15 prepare_index_information
11 16 @test_requests = @user.test_requests
12 17 end
13 18
14 19 def submit
15 20 @user = User.find(session[:user_id])
21 +
22 + if @user.site!=nil and @user.site.finished?
23 + flash[:notice] = 'Error saving your test submission: Contest is over.'
24 + redirect_to :action => 'index' and return
25 + end
26 +
16 27 test_request = TestRequest.new_from_form_params(@user,params[:test_request])
17 28 if test_request.save
18 29 redirect_to :action => 'index'
19 30 else
20 31 flash[:notice] = 'Error saving your test submission'
21 32 redirect_to :action => 'index'
22 33 end
23 34 end
24 35
25 36 def read
26 37 user = User.find(session[:user_id])
27 38 begin
@@ -36,27 +36,35
36 36 def format_short_time(time)
37 37 now = Time.now
38 38 st = ''
39 39 if (time.yday != now.yday) or
40 40 (time.year != now.year)
41 41 st = time.strftime("%x ")
42 42 end
43 43 st + time.strftime("%X")
44 44 end
45 45
46 46
47 47 def user_title_bar(user)
48 + if user.site!=nil and user.site.finished?
49 + contest_over_string = <<CONTEST_OVER
50 + <tr><td colspan="2" align="center">
51 + <span class="contest-over-msg">THE CONTEST IS OVER</span>
52 + </td></tr>
53 + CONTEST_OVER
54 + end
48 55 <<TITLEBAR
49 56 <div class="title">
50 57 <table>
58 + #{contest_over_string}
51 59 <tr>
52 60 <td class="left-col">
53 61 #{user.full_name}<br/>
54 62 Current time is #{format_short_time(Time.new)}<br/>
55 63 </td>
56 64 <td class="right-col">APIO'08</td>
57 65 </tr>
58 66 </table>
59 67 </div>
60 68 TITLEBAR
61 69 end
62 70
@@ -1,20 +1,22
1 1 require 'digest/sha1'
2 2
3 3 class User < ActiveRecord::Base
4 4
5 5 has_and_belongs_to_many :roles
6 6
7 7 has_many :test_requests, :order => "submitted_at DESC"
8 8
9 + belongs_to :site
10 +
9 11 validates_presence_of :login
10 12 validates_presence_of :full_name
11 13 validates_length_of :full_name, :minimum => 1
12 14
13 15 validates_presence_of :password, :if => :password_required?
14 16 validates_length_of :password, :within => 4..20, :if => :password_required?
15 17 validates_confirmation_of :password, :if => :password_required?
16 18
17 19 attr_accessor :password
18 20
19 21 before_save :encrypt_new_password
20 22
@@ -1,13 +1,15
1 1 ActionController::Routing::Routes.draw do |map|
2 + map.resources :sites
3 +
2 4 # The priority is based upon order of creation: first created -> highest priority.
3 5
4 6 # Sample of regular route:
5 7 # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
6 8 # Keep in mind you can assign values other than :controller and :action
7 9
8 10 # Sample of named route:
9 11 # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
10 12 # This route can be invoked with purchase_url(:id => product.id)
11 13
12 14 # You can have the root of your site routed by hooking up ''
13 15 # -- just remember to delete public/index.html.
@@ -1,24 +1,24
1 1 # This file is auto-generated from the current state of the database. Instead of editing this file,
2 2 # please use the migrations feature of ActiveRecord to incrementally modify your database, and
3 3 # then regenerate this schema definition.
4 4 #
5 5 # Note that this schema.rb definition is the authoritative source for your database schema. If you need
6 6 # to create the application database on another system, you should be using db:schema:load, not running
7 7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 9 #
10 10 # It's strongly recommended to check this file into your version control system.
11 11
12 - ActiveRecord::Schema.define(:version => 23) do
12 + ActiveRecord::Schema.define(:version => 25) do
13 13
14 14 create_table "configurations", :force => true do |t|
15 15 t.string "key"
16 16 t.string "value_type"
17 17 t.string "value"
18 18 t.datetime "created_at"
19 19 t.datetime "updated_at"
20 20 end
21 21
22 22 create_table "grader_processes", :force => true do |t|
23 23 t.string "host", :limit => 20
24 24 t.integer "pid"
@@ -70,24 +70,32
70 70
71 71 add_index "roles_users", ["user_id"], :name => "index_roles_users_on_user_id"
72 72
73 73 create_table "sessions", :force => true do |t|
74 74 t.string "session_id"
75 75 t.text "data"
76 76 t.datetime "updated_at"
77 77 end
78 78
79 79 add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
80 80 add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
81 81
82 + create_table "sites", :force => true do |t|
83 + t.string "name"
84 + t.boolean "started"
85 + t.datetime "start_time"
86 + t.datetime "created_at"
87 + t.datetime "updated_at"
88 + end
89 +
82 90 create_table "submissions", :force => true do |t|
83 91 t.integer "user_id"
84 92 t.integer "problem_id"
85 93 t.integer "language_id"
86 94 t.text "source"
87 95 t.binary "binary"
88 96 t.datetime "submitted_at"
89 97 t.datetime "compiled_at"
90 98 t.text "compiler_message"
91 99 t.datetime "graded_at"
92 100 t.integer "points"
93 101 t.text "grader_comment"
@@ -118,23 +126,24
118 126 t.text "compiler_message"
119 127 t.datetime "graded_at"
120 128 t.string "grader_comment"
121 129 t.datetime "created_at"
122 130 t.float "running_time"
123 131 t.string "exit_status"
124 132 t.integer "memory_usage"
125 133 end
126 134
127 135 add_index "test_requests", ["user_id", "problem_id"], :name => "index_test_requests_on_user_id_and_problem_id"
128 136
129 137 create_table "users", :force => true do |t|
130 - t.string "login", :limit => 10
131 - t.string "full_name"
132 - t.string "hashed_password"
133 - t.string "salt", :limit => 5
134 - t.string "alias"
135 - t.string "email"
138 + t.string "login", :limit => 10
139 + t.string "full_name"
140 + t.string "hashed_password"
141 + t.string "salt", :limit => 5
142 + t.string "alias"
143 + t.string "email"
144 + t.integer "site_id"
136 145 end
137 146
138 147 add_index "users", ["login"], :name => "index_users_on_login", :unique => true
139 148
140 149 end
@@ -12,24 +12,30
12 12 }
13 13
14 14 /* This is the top bar, displaying user's full name */
15 15 div.title {
16 16 font-size: 12px;
17 17 background: #ddffdd;
18 18 border: 1px solid black;
19 19 padding: 2px;
20 20 margin-top: 3px;
21 21 margin-bottom: 5px;
22 22 }
23 23
24 + div.title span.contest-over-msg {
25 + font-size: 15px;
26 + color: red;
27 + font-weight: bold;
28 + }
29 +
24 30 div.title table {
25 31 width: 100%;
26 32 }
27 33
28 34 div.title td.left-col {
29 35 text-align: left;
30 36 vertical-align: top;
31 37 }
32 38
33 39 div.title td.right-col {
34 40 text-align: right;
35 41 vertical-align: top;
@@ -53,22 +53,22
53 53 }
54 54
55 55 div.uploadStatus {
56 56 margin: 5px;
57 57 }
58 58
59 59 div.progressBar {
60 60 margin: 5px;
61 61 }
62 62
63 63 div.progressBar div.border {
64 64 background-color: #fff;
65 - border: 1px solid grey;
65 + border: 1px solid gray;
66 66 width: 100%;
67 67 }
68 68
69 69 div.progressBar div.background {
70 70 background-color: #333;
71 71 height: 18px;
72 72 width: 0%;
73 73 }
74 74
You need to be logged in to leave comments. Login now