diff --git a/app/assets/javascripts/submissions.js.coffee b/app/assets/javascripts/submissions.js.coffee new file mode 100644 --- /dev/null +++ b/app/assets/javascripts/submissions.js.coffee @@ -0,0 +1,29 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ + + +$ -> + $("#live_submit").on "click", (event) -> + h = $("#editor_text") + e = ace.edit("editor") + h.val(e.getValue()) + + $("#language_id").on "change", (event) -> + text = $("#language_id option:selected").text() + mode = 'ace/mode/c_cpp' + switch text + when 'Pascal' then mode = 'ace/mode/pascal' + when 'C++','C' then mode = 'ace/mode/c_cpp' + when 'Ruby' then mode = 'ace/mode/ruby' + when 'Python' then mode = 'ace/mode/python' + when 'Java' then mode = 'ace/mode/java' + editor = ace.edit('editor') + editor.getSession().setMode(mode) + + e = ace.edit("editor") + + + + + return diff --git a/app/assets/stylesheets/submissions.css.scss b/app/assets/stylesheets/submissions.css.scss new file mode 100644 --- /dev/null +++ b/app/assets/stylesheets/submissions.css.scss @@ -0,0 +1,4 @@ +// Place all the styles related to the sources controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ + diff --git a/app/controllers/sources_controller.rb b/app/controllers/sources_controller.rb deleted file mode 100644 --- a/app/controllers/sources_controller.rb +++ /dev/null @@ -1,27 +0,0 @@ -class SourcesController < ApplicationController - before_filter :authenticate - - def direct_edit - @problem = Problem.find(params[:pid]) - @source = '' - end - - def direct_edit_submission - @submission = Submission.find(params[:sid]) - @source = @submission.source.to_s - @problem = @submission.problem - @lang_id = @submission.language.id - render 'direct_edit' - end - - def get_latest_submission_status - @problem = Problem.find(params[:pid]) - @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid]) - puts User.find(params[:uid]).login - puts Problem.find(params[:pid]).name - puts 'nil' unless @submission - respond_to do |format| - format.js - end - end -end 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,27 +1,10 @@ class SubmissionsController < ApplicationController before_filter :authenticate - - before_filter(only: [:show]) { - #check if authenticated - return false unless authenticate - - #admin always has privileged - if @current_user.admin? - return true - end - - sub = Submission.find(params[:id]) - if sub.problem.available? - return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user - end - - #default to NO - unauthorized_redirect - return false - } + before_filter :submission_authorization, only: [:show, :direct_edit_submission] # GET /submissions # GET /submissions.json + # Show problem selection and user's submission of that problem def index @user = @current_user @problems = @user.available_problems @@ -32,7 +15,7 @@ else @problem = Problem.find_by_id(params[:problem_id]) if (@problem == nil) or (not @problem.available) - redirect_to :action => 'list' + redirect_to main_list_path flash[:notice] = 'Error: submissions for that problem are not viewable.' return end @@ -50,63 +33,105 @@ SubmissionViewLog.create(user_id: session[:user_id],submission_id: @submission.id) unless user.admin? end - # GET /submissions/new - # GET /submissions/new.json - def new - @submission = Submission.new - - respond_to do |format| - format.html # new.html.erb - format.json { render json: @submission } - end + #on-site new submission on specific problem + def direct_edit_problem + @problem = Problem.find(params[:problem_id]) + @source = '' + render 'edit' end # GET /submissions/1/edit def edit @submission = Submission.find(params[:id]) + @source = @submission.source.to_s + @problem = @submission.problem + @lang_id = @submission.language.id end - # POST /submissions - # POST /submissions.json - def create - @submission = Submission.new(params[:submission]) + def get_latest_submission_status + @problem = Problem.find(params[:pid]) + @submission = Submission.find_last_by_user_and_problem(params[:uid],params[:pid]) + puts User.find(params[:uid]).login + puts Problem.find(params[:pid]).name + puts 'nil' unless @submission respond_to do |format| - if @submission.save - format.html { redirect_to @submission, notice: 'Submission was successfully created.' } - format.json { render json: @submission, status: :created, location: @submission } - else - format.html { render action: "new" } - format.json { render json: @submission.errors, status: :unprocessable_entity } - end + format.js end end - # PUT /submissions/1 - # PUT /submissions/1.json - def update - @submission = Submission.find(params[:id]) +# # GET /submissions/new +# # GET /submissions/new.json +# def new +# @submission = Submission.new +# +# respond_to do |format| +# format.html # new.html.erb +# format.json { render json: @submission } +# end +# end +# +# +# # POST /submissions +# # POST /submissions.json +# def create +# @submission = Submission.new(params[:submission]) +# +# respond_to do |format| +# if @submission.save +# format.html { redirect_to @submission, notice: 'Submission was successfully created.' } +# format.json { render json: @submission, status: :created, location: @submission } +# else +# format.html { render action: "new" } +# format.json { render json: @submission.errors, status: :unprocessable_entity } +# end +# end +# end +# +# # PUT /submissions/1 +# # PUT /submissions/1.json +# def update +# @submission = Submission.find(params[:id]) +# +# respond_to do |format| +# if @submission.update_attributes(params[:submission]) +# format.html { redirect_to @submission, notice: 'Submission was successfully updated.' } +# format.json { head :no_content } +# else +# format.html { render action: "edit" } +# format.json { render json: @submission.errors, status: :unprocessable_entity } +# end +# end +# end +# +# # DELETE /submissions/1 +# # DELETE /submissions/1.json +# def destroy +# @submission = Submission.find(params[:id]) +# @submission.destroy +# +# respond_to do |format| +# format.html { redirect_to submissions_url } +# format.json { head :no_content } +# end +# end - respond_to do |format| - if @submission.update_attributes(params[:submission]) - format.html { redirect_to @submission, notice: 'Submission was successfully updated.' } - format.json { head :no_content } - else - format.html { render action: "edit" } - format.json { render json: @submission.errors, status: :unprocessable_entity } - end +protected + def submission_authorization + #admin always has privileged + if @current_user.admin? + return true end - end + + sub = Submission.find(params[:id]) + if sub.problem.available? + puts "sub = #{sub.user.id}, current = #{@current_user.id}" + return true if GraderConfiguration["right.user_view_submission"] or sub.user == @current_user + end - # DELETE /submissions/1 - # DELETE /submissions/1.json - def destroy - @submission = Submission.find(params[:id]) - @submission.destroy - - respond_to do |format| - format.html { redirect_to submissions_url } - format.json { head :no_content } - end + #default to NO + unauthorized_redirect + return false end + end diff --git a/app/views/application/_submission.html.haml b/app/views/application/_submission.html.haml --- a/app/views/application/_submission.html.haml +++ b/app/views/application/_submission.html.haml @@ -23,4 +23,4 @@ %td = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message } %td - = link_to 'Edit', direct_edit_submission_path(submission.id), class: 'btn btn-success' + = link_to 'Edit', edit_submission_path(submission.id), class: 'btn btn-success' diff --git a/app/views/application/_submission_short.html.haml b/app/views/application/_submission_short.html.haml --- a/app/views/application/_submission_short.html.haml +++ b/app/views/application/_submission_short.html.haml @@ -3,7 +3,7 @@ = "-" - else - if submission.graded_at.nil? - =t 'main.submitted_at' + = t 'main.submitted_at' = format_short_time(submission.submitted_at.localtime) - else = t 'main.graded_at' diff --git a/app/views/main/_problem.html.haml b/app/views/main/_problem.html.haml --- a/app/views/main/_problem.html.haml +++ b/app/views/main/_problem.html.haml @@ -13,6 +13,6 @@ :locals => {:submission => @prob_submissions[problem.id][:submission], :problem_name => problem.name, :problem_id => problem.id } %td - if @prob_submissions[problem.id][:submission] - = link_to 'Edit', direct_edit_submission_path(@prob_submissions[problem.id][:submission]), class: 'btn btn-success' + = link_to 'Edit', edit_submission_path(@prob_submissions[problem.id][:submission]), class: 'btn btn-success' - else - = link_to 'New', direct_edit_path(problem.id), class: 'btn btn-success' + = link_to 'New', direct_edit_problem_submissions_path(problem.id), class: 'btn btn-success' diff --git a/app/views/sources/direct_edit.html.haml b/app/views/sources/direct_edit.html.haml deleted file mode 100644 --- a/app/views/sources/direct_edit.html.haml +++ /dev/null @@ -1,264 +0,0 @@ -%h2 Live submit -%br - -%textarea#text_haha{style: "display:none"}~ @source -.container - .row - .col-md-12 - .alert.alert-info - Write your code in the following box, choose language, and click submit button when finished - .row - .col-md-8 - %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'} - .col-md-4 - = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do - - = hidden_field_tag 'editor_text', @source - = hidden_field_tag 'submission[problem_id]', @problem.id - .form-group - = label_tag "Task:" - = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true - - .form-group - = label_tag 'Language' - = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px" - .form-group - = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit', - data: {confirm: "Submitting this source code for task #{@problem.long_name}?"} - .panel.panel-info - .panel-heading - Latest Submission Status - .panel-body - - if @submission - = render :partial => 'submission_short', - :locals => {:submission => @submission, :problem_name => @problem.name } - .row - .col-md-12 - %h2 Console - %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20} - -:javascript - $(document).ready(function() { - brython(); - }); - - -%script#__main__{type:'text/python3'} - :plain - import sys - import traceback - - from browser import document as doc - from browser import window, alert, console - - _credits = """ Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands - for supporting Python development. See www.python.org for more information.""" - - _copyright = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com - All Rights Reserved. - - Copyright (c) 2001-2013 Python Software Foundation. - All Rights Reserved. - - Copyright (c) 2000 BeOpen.com. - All Rights Reserved. - - Copyright (c) 1995-2001 Corporation for National Research Initiatives. - All Rights Reserved. - - Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. - All Rights Reserved.""" - - _license = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. Redistributions in binary - form must reproduce the above copyright notice, this list of conditions and - the following disclaimer in the documentation and/or other materials provided - with the distribution. - Neither the name of the nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - """ - - def credits(): - print(_credits) - credits.__repr__ = lambda:_credits - - def copyright(): - print(_copyright) - copyright.__repr__ = lambda:_copyright - - def license(): - print(_license) - license.__repr__ = lambda:_license - - def write(data): - doc['console'].value += str(data) - - - sys.stdout.write = sys.stderr.write = write - history = [] - current = 0 - _status = "main" # or "block" if typing inside a block - - # execution namespace - editor_ns = {'credits':credits, - 'copyright':copyright, - 'license':license, - '__name__':'__main__'} - - def cursorToEnd(*args): - pos = len(doc['console'].value) - doc['console'].setSelectionRange(pos, pos) - doc['console'].scrollTop = doc['console'].scrollHeight - - def get_col(area): - # returns the column num of cursor - sel = doc['console'].selectionStart - lines = doc['console'].value.split('\n') - for line in lines[:-1]: - sel -= len(line) + 1 - return sel - - - def myKeyPress(event): - global _status, current - if event.keyCode == 9: # tab key - event.preventDefault() - doc['console'].value += " " - elif event.keyCode == 13: # return - src = doc['console'].value - if _status == "main": - currentLine = src[src.rfind('>>>') + 4:] - elif _status == "3string": - currentLine = src[src.rfind('>>>') + 4:] - currentLine = currentLine.replace('\n... ', '\n') - else: - currentLine = src[src.rfind('...') + 4:] - if _status == 'main' and not currentLine.strip(): - doc['console'].value += '\n>>> ' - event.preventDefault() - return - doc['console'].value += '\n' - history.append(currentLine) - current = len(history) - if _status == "main" or _status == "3string": - try: - _ = editor_ns['_'] = eval(currentLine, editor_ns) - if _ is not None: - write(repr(_)+'\n') - doc['console'].value += '>>> ' - _status = "main" - except IndentationError: - doc['console'].value += '... ' - _status = "block" - except SyntaxError as msg: - if str(msg) == 'invalid syntax : triple string end not found' or \ - str(msg).startswith('Unbalanced bracket'): - doc['console'].value += '... ' - _status = "3string" - elif str(msg) == 'eval() argument must be an expression': - try: - exec(currentLine, editor_ns) - except: - traceback.print_exc() - doc['console'].value += '>>> ' - _status = "main" - elif str(msg) == 'decorator expects function': - doc['console'].value += '... ' - _status = "block" - else: - traceback.print_exc() - doc['console'].value += '>>> ' - _status = "main" - except: - traceback.print_exc() - doc['console'].value += '>>> ' - _status = "main" - elif currentLine == "": # end of block - block = src[src.rfind('>>>') + 4:].splitlines() - block = [block[0]] + [b[4:] for b in block[1:]] - block_src = '\n'.join(block) - # status must be set before executing code in globals() - _status = "main" - try: - _ = exec(block_src, editor_ns) - if _ is not None: - print(repr(_)) - except: - traceback.print_exc() - doc['console'].value += '>>> ' - else: - doc['console'].value += '... ' - - cursorToEnd() - event.preventDefault() - - def myKeyDown(event): - global _status, current - if event.keyCode == 37: # left arrow - sel = get_col(doc['console']) - if sel < 5: - event.preventDefault() - event.stopPropagation() - elif event.keyCode == 36: # line start - pos = doc['console'].selectionStart - col = get_col(doc['console']) - doc['console'].setSelectionRange(pos - col + 4, pos - col + 4) - event.preventDefault() - elif event.keyCode == 38: # up - if current > 0: - pos = doc['console'].selectionStart - col = get_col(doc['console']) - # remove current line - doc['console'].value = doc['console'].value[:pos - col + 4] - current -= 1 - doc['console'].value += history[current] - event.preventDefault() - elif event.keyCode == 40: # down - if current < len(history) - 1: - pos = doc['console'].selectionStart - col = get_col(doc['console']) - # remove current line - doc['console'].value = doc['console'].value[:pos - col + 4] - current += 1 - doc['console'].value += history[current] - event.preventDefault() - elif event.keyCode == 8: # backspace - src = doc['console'].value - lstart = src.rfind('\n') - if (lstart == -1 and len(src) < 5) or (len(src) - lstart < 6): - event.preventDefault() - event.stopPropagation() - - - doc['console'].bind('keypress', myKeyPress) - doc['console'].bind('keydown', myKeyDown) - doc['console'].bind('click', cursorToEnd) - v = sys.implementation.version - doc['console'].value = "Brython %s.%s.%s on %s %s\n>>> " % ( - v[0], v[1], v[2], window.navigator.appName, window.navigator.appVersion) - #doc['console'].value += 'Type "copyright", "credits" or "license" for more information.' - doc['console'].focus() - cursorToEnd() - - - - diff --git a/app/views/sources/get_latest_submission_status.js.haml b/app/views/sources/get_latest_submission_status.js.haml deleted file mode 100644 --- a/app/views/sources/get_latest_submission_status.js.haml +++ /dev/null @@ -1,2 +0,0 @@ -:javascript - $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}") diff --git a/app/views/submissions/edit.html.haml b/app/views/submissions/edit.html.haml --- a/app/views/submissions/edit.html.haml +++ b/app/views/submissions/edit.html.haml @@ -1,7 +1,268 @@ -%h1 Editing submission +%h2 Live submit +%br + +%textarea#text_haha{style: "display:none"}~ @source +.container + .row + .col-md-12 + .alert.alert-info + Write your code in the following box, choose language, and click submit button when finished + .row + .col-md-8 + %div#editor{style: 'height: 500px; border-radius: 7px; font-size: 14px;'} + .col-md-4 + = form_tag({controller: :main, :action => 'submit'}, :multipart => true, class: 'form') do + + = hidden_field_tag 'editor_text', @source + = hidden_field_tag 'submission[problem_id]', @problem.id + .form-group + = label_tag "Task:" + = text_field_tag 'asdf', "#{@problem.long_name}", class: 'form-control', disabled: true + + .form-group + = label_tag 'Language' + = select_tag 'language_id', options_from_collection_for_select(Language.all, 'id', 'pretty_name', @lang_id || Language.find_by_pretty_name("Python").id || Language.first.id), class: 'form-control select', style: "width: 100px" + .form-group + = submit_tag 'Submit', class: 'btn btn-success', id: 'live_submit', + data: {confirm: "Submitting this source code for task #{@problem.long_name}?"} + .panel.panel-info + .panel-heading + Latest Submission Status + .panel-body + - if @submission + = render :partial => 'submission_short', + :locals => {:submission => @submission, :problem_name => @problem.name } + .row + .col-md-12 + %h2 Console + %textarea#console{style: 'height: 100%; width: 100%;background-color:#000;color:#fff;font-family: consolas, monaco, "Droid Sans Mono";',rows: 20} + +:javascript + $(document).ready(function() { + e = ace.edit("editor") + e.setValue($("#text_haha").val()); + e.gotoLine(1); + $("#language_id").trigger('change'); + brython(); + }); + + +%script#__main__{type:'text/python3'} + :plain + import sys + import traceback + + from browser import document as doc + from browser import window, alert, console + + _credits = """ Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands + for supporting Python development. See www.python.org for more information.""" + + _copyright = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com + All Rights Reserved. -= render 'form' + Copyright (c) 2001-2013 Python Software Foundation. + All Rights Reserved. + + Copyright (c) 2000 BeOpen.com. + All Rights Reserved. + + Copyright (c) 1995-2001 Corporation for National Research Initiatives. + All Rights Reserved. + + Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. + All Rights Reserved.""" + + _license = """Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. Redistributions in binary + form must reproduce the above copyright notice, this list of conditions and + the following disclaimer in the documentation and/or other materials provided + with the distribution. + Neither the name of the nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + """ + + def credits(): + print(_credits) + credits.__repr__ = lambda:_credits + + def copyright(): + print(_copyright) + copyright.__repr__ = lambda:_copyright + + def license(): + print(_license) + license.__repr__ = lambda:_license + + def write(data): + doc['console'].value += str(data) + + + sys.stdout.write = sys.stderr.write = write + history = [] + current = 0 + _status = "main" # or "block" if typing inside a block + + # execution namespace + editor_ns = {'credits':credits, + 'copyright':copyright, + 'license':license, + '__name__':'__main__'} -= link_to 'Show', @submission -\| -= link_to 'Back', submissions_path + def cursorToEnd(*args): + pos = len(doc['console'].value) + doc['console'].setSelectionRange(pos, pos) + doc['console'].scrollTop = doc['console'].scrollHeight + + def get_col(area): + # returns the column num of cursor + sel = doc['console'].selectionStart + lines = doc['console'].value.split('\n') + for line in lines[:-1]: + sel -= len(line) + 1 + return sel + + + def myKeyPress(event): + global _status, current + if event.keyCode == 9: # tab key + event.preventDefault() + doc['console'].value += " " + elif event.keyCode == 13: # return + src = doc['console'].value + if _status == "main": + currentLine = src[src.rfind('>>>') + 4:] + elif _status == "3string": + currentLine = src[src.rfind('>>>') + 4:] + currentLine = currentLine.replace('\n... ', '\n') + else: + currentLine = src[src.rfind('...') + 4:] + if _status == 'main' and not currentLine.strip(): + doc['console'].value += '\n>>> ' + event.preventDefault() + return + doc['console'].value += '\n' + history.append(currentLine) + current = len(history) + if _status == "main" or _status == "3string": + try: + _ = editor_ns['_'] = eval(currentLine, editor_ns) + if _ is not None: + write(repr(_)+'\n') + doc['console'].value += '>>> ' + _status = "main" + except IndentationError: + doc['console'].value += '... ' + _status = "block" + except SyntaxError as msg: + if str(msg) == 'invalid syntax : triple string end not found' or \ + str(msg).startswith('Unbalanced bracket'): + doc['console'].value += '... ' + _status = "3string" + elif str(msg) == 'eval() argument must be an expression': + try: + exec(currentLine, editor_ns) + except: + traceback.print_exc() + doc['console'].value += '>>> ' + _status = "main" + elif str(msg) == 'decorator expects function': + doc['console'].value += '... ' + _status = "block" + else: + traceback.print_exc() + doc['console'].value += '>>> ' + _status = "main" + except: + traceback.print_exc() + doc['console'].value += '>>> ' + _status = "main" + elif currentLine == "": # end of block + block = src[src.rfind('>>>') + 4:].splitlines() + block = [block[0]] + [b[4:] for b in block[1:]] + block_src = '\n'.join(block) + # status must be set before executing code in globals() + _status = "main" + try: + _ = exec(block_src, editor_ns) + if _ is not None: + print(repr(_)) + except: + traceback.print_exc() + doc['console'].value += '>>> ' + else: + doc['console'].value += '... ' + + cursorToEnd() + event.preventDefault() + + def myKeyDown(event): + global _status, current + if event.keyCode == 37: # left arrow + sel = get_col(doc['console']) + if sel < 5: + event.preventDefault() + event.stopPropagation() + elif event.keyCode == 36: # line start + pos = doc['console'].selectionStart + col = get_col(doc['console']) + doc['console'].setSelectionRange(pos - col + 4, pos - col + 4) + event.preventDefault() + elif event.keyCode == 38: # up + if current > 0: + pos = doc['console'].selectionStart + col = get_col(doc['console']) + # remove current line + doc['console'].value = doc['console'].value[:pos - col + 4] + current -= 1 + doc['console'].value += history[current] + event.preventDefault() + elif event.keyCode == 40: # down + if current < len(history) - 1: + pos = doc['console'].selectionStart + col = get_col(doc['console']) + # remove current line + doc['console'].value = doc['console'].value[:pos - col + 4] + current += 1 + doc['console'].value += history[current] + event.preventDefault() + elif event.keyCode == 8: # backspace + src = doc['console'].value + lstart = src.rfind('\n') + if (lstart == -1 and len(src) < 5) or (len(src) - lstart < 6): + event.preventDefault() + event.stopPropagation() + + + doc['console'].bind('keypress', myKeyPress) + doc['console'].bind('keydown', myKeyDown) + doc['console'].bind('click', cursorToEnd) + v = sys.implementation.version + doc['console'].value = "Brython %s.%s.%s on %s %s\n>>> " % ( + v[0], v[1], v[2], window.navigator.appName, window.navigator.appVersion) + #doc['console'].value += 'Type "copyright", "credits" or "license" for more information.' + doc['console'].focus() + cursorToEnd() + + + + diff --git a/app/views/submissions/get_latest_submission_status.js.haml b/app/views/submissions/get_latest_submission_status.js.haml new file mode 100644 --- /dev/null +++ b/app/views/submissions/get_latest_submission_status.js.haml @@ -0,0 +1,2 @@ +:javascript + $("#latest_status").html("#{j render({partial: 'submission_short', locals: {submission: @submission, problem_name: @problem.name}})}") diff --git a/config/routes.rb b/config/routes.rb --- a/config/routes.rb +++ b/config/routes.rb @@ -37,15 +37,11 @@ resources :submissions do collection do get 'prob/:problem_id', to: 'submissions#index', as: 'problem' + get 'direct_edit_problem/:problem_id', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem' + get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status' end end - #source code edit - get 'sources/direct_edit/:pid', to: 'sources#direct_edit', as: 'direct_edit' - get 'sources/direct_edit_submission/:sid', to: 'sources#direct_edit_submission', as: 'direct_edit_submission' - get 'sources/get_latest_submission_status/:uid/:pid', to: 'sources#get_latest_submission_status', as: 'get_latest_submission_status' - - match 'tasks/view/:file.:ext' => 'tasks#view' match 'tasks/download/:id/:file.:ext' => 'tasks#download' match 'heartbeat/:id/edit' => 'heartbeat#edit'