diff --git a/db/languages.yml b/db/languages.yml index 12645ff2..1b4765b8 100644 --- a/db/languages.yml +++ b/db/languages.yml @@ -6,174 +6,177 @@ # interpreter_command is executed directly using 'isolate' (so the first argument must be the full path to the interpreter) c++: - :name: "C++" - :lexer: c++ - :compiled: yes - :interpreted: no - :current: c++17 - :extension: .cpp - :source_filename: program - :exe_extension: .exe - :processes: 1 - :variants: - c++03: # deprecated - :name: "C++03" - :compiler: g++ - :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++03 -O2 -o %{output} %{source} -lm" + name: "C++" + lexer: c++ + compiled: yes + interpreted: no + current: c++17 + extension: .cpp + source_filename: program + exe_extension: .exe + processes: 1 + variants: + c++03: # deprecated + name: "C++03" + compiler: g++ + compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++03 -O2 -o %{output} %{source} -lm" c++11: - :name: "C++11" - :compiler: g++ - :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++11 -O2 -o %{output} %{source} -lm" - c++14: # Changes since C++11: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1319r0.html - :name: "C++14" - :compiler: g++ - :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++14 -O2 -o %{output} %{source} -lm" - c++17: # Changes since C++14: https://isocpp.org/files/papers/p0636r0.html - :name: "C++17" - :compiler: g++ - :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++17 -O2 -o %{output} %{source} -lm" + name: "C++11" + compiler: g++ + compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++11 -O2 -o %{output} %{source} -lm" + c++14: # Changes since C++11: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1319r0.html + name: "C++14" + compiler: g++ + compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++14 -O2 -o %{output} %{source} -lm" + c++17: # Changes since C++14: https://isocpp.org/files/papers/p0636r0.html + name: "C++17" + compiler: g++ + compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu++17 -O2 -o %{output} %{source} -lm" c: - :name: "C" - :lexer: c - :compiled: yes - :interpreted: no - :current: c11 - :extension: .c - :source_filename: program - :exe_extension: .exe - :processes: 1 - :variants: - c99: # deprecated - :name: C99 - :compiler: gcc - :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu99 -O2 -o %{output} %{source} -lm" - c11: # Changes since c99: https://en.wikipedia.org/wiki/C11_(C_standard_revision) - :name: C11 - :compiler: gcc - :compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu11 -O2 -o %{output} %{source} -lm" + name: "C" + lexer: c + compiled: yes + interpreted: no + current: c11 + extension: .c + source_filename: program + exe_extension: .exe + processes: 1 + variants: + c99: # deprecated + name: C99 + compiler: gcc + compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu99 -O2 -o %{output} %{source} -lm" + c11: # Changes since c99: https://en.wikipedia.org/wiki/C11_(C_standard_revision) + name: C11 + compiler: gcc + compiler_command: "%{compiler} --version | head -n 1 1>&2 && %{compiler} -std=gnu11 -O2 -o %{output} %{source} -lm" java: - :name: Java - :lexer: java - :compiled: yes - :interpreted: yes - :current: java11 - :extension: .java - :source_filename: Main - :exe_extension: .jar - :processes: 0 - :variants: + name: Java + lexer: java + compiled: yes + interpreted: yes + current: java11 + extension: .java + source_filename: Main + exe_extension: .jar + processes: 0 + variants: java6: - :name: Java 1.6 # deprecated (note: uses '-source 1.6', which will be removed in a future JDK release) - :compiler: javac;jar - :compiler_command: '%{compiler[0]} -version | head -n 1 1>&2 && %{compiler[0]} -O -source 1.6 -J-Xms16m -J-Xmx256m %{source} && %{compiler[1]} cfe %{output} Main -C %{source_dir} .' - :interpreter: /usr/bin/java - :interpreter_command: '%{interpreter} -jar %{source}' + name: Java 1.6 # deprecated (note: uses '-source 1.6', which will be removed in a future JDK release) + compiler: javac;jar + compiler_command: "%{compiler[0]} -version | head -n 1 1>&2 && %{compiler[0]} -O -source 1.6 -J-Xms16m -J-Xmx256m %{source} && %{compiler[1]} cfe %{output} Main -C %{source_dir} ." + interpreter: /usr/bin/java + interpreter_command: "%{interpreter} -jar %{source}" java11: - :name: Java 11 - :compiler: javac;jar - :compiler_command: '%{compiler[0]} -version | head -n 1 1>&2 && %{compiler[0]} -O -source 11 -J-Xms16m -J-Xmx256m %{source} && %{compiler[1]} cfe %{output} Main -C %{source_dir} .' - :interpreter: /usr/bin/java - :interpreter_command: '%{interpreter} -jar %{source}' + name: Java 11 + compiler: javac;jar + compiler_command: "%{compiler[0]} -version | head -n 1 1>&2 && %{compiler[0]} -O -source 11 -J-Xms16m -J-Xmx256m %{source} && %{compiler[1]} cfe %{output} Main -C %{source_dir} ." + interpreter: /usr/bin/java + interpreter_command: "%{interpreter} -jar %{source}" + haskell: - :name: Haskell - :lexer: haskell - :compiled: yes - :interpreted: no - :current: haskell2010 - :extension: .hs - :source_filename: program - :exe_extension: .exe - :processes: 1 - :variants: + name: Haskell + lexer: haskell + compiled: yes + interpreted: no + current: haskell2010 + extension: .hs + source_filename: program + exe_extension: .exe + processes: 1 + variants: haskell2010: - :name: "Haskell 2010" - :compiler: ghc - :compiler_command: '%{compiler} --version 1>&2 && %{compiler} --make -O2 -o %{output} %{source} -lm' + name: "Haskell 2010" + compiler: ghc + compiler_command: "%{compiler} --version 1>&2 && %{compiler} --make -O2 -o %{output} %{source} -lm" + python: - :name: Python - :lexer: python - :compiled: no - :interpreted: yes - :current: python3.8 - :extension: .py - :source_filename: program - :processes: 1 - :interpreter_command: '%{interpreter} %{source}' - :compiler_command: '%{interpreter} -m py_compile %{source}' - :variants: - python2: # deprecated - Python 2 reached end-of-life in late 2019 - :name: "Python 2.7" - :interpreter: /usr/bin/python2 - python3.4: # deprecated - :name: "Python 3.4" - :interpreter: /usr/bin/python3.4 + name: Python + lexer: python + compiled: no + interpreted: yes + current: python3.8 + extension: .py + source_filename: program + processes: 1 + interpreter_command: "%{interpreter} %{source}" + compiler_command: "%{interpreter} -m py_compile %{source}" + variants: + python2: # deprecated - Python 2 reached end-of-life in late 2019 + name: "Python 2.7" + interpreter: /usr/bin/python2 + python3.4: # deprecated + name: "Python 3.4" + interpreter: /usr/bin/python3.4 python3.8: - :name: "Python 3.8" - :interpreter: /usr/bin/python3.8 + name: "Python 3.8" + interpreter: /usr/bin/python3.8 pypy3: - :name: "Python 3.6 (PyPy 7.3)" - :interpreter: /usr/bin/pypy3 + name: "Python 3.6 (PyPy 7.3)" + interpreter: /usr/bin/pypy3 ruby: - :name: Ruby - :lexer: ruby - :compiled: no - :interpreted: yes - :current: ruby2.2 - :extension: .rb - :source_filename: program - :processes: 2 # ruby seems to have an extra process - :interpreter_command: '%{interpreter} %{source}' - :compiler_command: '%{interpreter} -c %{source}' - :variants: + name: Ruby + lexer: ruby + compiled: no + interpreted: yes + current: ruby2.2 + extension: .rb + source_filename: program + processes: 2 # ruby seems to have an extra process + interpreter_command: "%{interpreter} %{source}" + compiler_command: "%{interpreter} -c %{source}" + variants: ruby2.2: - :name: "Ruby 2.2" - :interpreter: /usr/bin/ruby2.2 + name: "Ruby 2.2" + interpreter: /usr/bin/ruby2.2 + j: - :name: J - :lexer: text - :compiled: no - :interpreted: yes - :current: j8 - :extension: .ijs - :source_filename: program - :processes: 3 # needed for system/main/stdlib.ijs to shell out to uname - :interpreter_command: '%{interpreter} %{source}' - :variants: + name: J + lexer: text + compiled: no + interpreted: yes + current: j8 + extension: .ijs + source_filename: program + processes: 3 # needed for system/main/stdlib.ijs to shell out to uname + interpreter_command: "%{interpreter} %{source}" + variants: j8: - :name: "J 8.03" - :interpreter: /usr/bin/ijconsole-8.0.3 + name: "J 8.03" + interpreter: /usr/bin/ijconsole-8.0.3 javascript: - :name: JavaScript - :lexer: javascript - :compiled: no - :interpreted: yes - :current: v8_8 - :extension: .js - :source_filename: program - :interpreter_command: '%{interpreter} %{source}' - :variants: + name: JavaScript + lexer: javascript + compiled: no + interpreted: yes + current: v8_8 + extension: .js + source_filename: program + interpreter_command: "%{interpreter} %{source}" + variants: v8_8: - :name: "JavaScript (V8 8.1)" - :interpreter: /usr/local/bin/d8 - :processes: 9 + name: "JavaScript (V8 8.1)" + interpreter: /usr/local/bin/d8 + processes: 9 csharp: - :name: "C#" - :lexer: csharp - :compiled: yes - :interpreted: yes - :current: csharp8 - :extension: .cs - :source_filename: program - :exe_extension: .exe - :processes: 5 - :interpreter: /usr/local/bin/dotnet-exec # custom shell script - :variants: + name: "C#" + lexer: csharp + compiled: yes + interpreted: yes + current: csharp8 + extension: .cs + source_filename: program + exe_extension: .exe + processes: 5 + interpreter: /usr/local/bin/dotnet-exec # custom shell script + variants: csharp8: - :name: "C# 8.0" - :compiler: dotnet-csc # custom shell script (also prints SDK version number) - :compiler_command: '%{compiler} %{source} -optimize+ -out:%{output} -langversion:8.0 -nologo' - :interpreter_command: '%{interpreter} %{source}' + name: "C# 8.0" + compiler: dotnet-csc # custom shell script (also prints SDK version number) + compiler_command: "%{compiler} %{source} -optimize+ -out:%{output} -langversion:8.0 -nologo" + interpreter_command: "%{interpreter} %{source}" diff --git a/db/seeds.rb b/db/seeds.rb index 70863652..d19dc2f2 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -6,81 +6,12 @@ # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) # Mayor.create(:name => 'Daley', :city => cities.first) -if !User.exists?(0) # code in this block to be fixed - # rootuser = User.new() - # rootuser.id = 0 - # rootuser.name = "System" - # rootuser.username = "system" - # rootuser.email = "system@nztrain.com" - # rootuser.encrypted_password = "" - # rootuser.save - # no users in user table, create a user - # rootuser = User.new({:id => 0, :name => "Root User", :username => "root", :email => "root@nztrain.com", :encrypted_password => "Need an encrypted password here"}) -end +# We use different seed files for different environments, meaning we don't +# have to worry about development data leaking into prod (in the unlikely +# event we ever ran db:seed in prod), and vice-vesa. -["superadmin", "admin", "staff", "organiser", "author"].each do |role| - Role.find_or_create_by(name: role) -end +# db/seeds/common.rb is things we want in every environment +require_relative Rails.root.join("db/seeds/common") -# give superadmin status to set everything up -rootuser = nil - -if User.exists?(0) - rootuser = User.find(0) # if a root user exists and is zeroth (this is for security because normally users get positive integers as id) user in users table, give superadmin status -end - -if rootuser && rootuser.username == "root" - superadmin = Role.find_by_name("superadmin") - superadmin.users.push(rootuser) unless superadmin.users.include?(rootuser) -end - -["system/mailer/email", "system/mailer/password", "recaptcha/public_key", "recaptcha/private_key"].each do |setting| - Setting.find_or_create_by(key: setting) -end - -setting = Setting.find_or_create_by(key: "submissions/shuffle") -setting.update_attributes(value: Random.new.rand(2E9.to_i).to_s) if setting.value.nil? - -# create a special group called Everyone -if !Group.exists?(0) - everyone = Group.new - everyone.id = 0 - everyone.name = "Everyone" - everyone.owner_id = 0 - everyone.save -end - -if !User.exists?(0) - everyone = Group.find(0) - user = User.new - user.id = 0 - user.username = "System" - user.name = "System" - user.email = "nztrain@gmail.com" - user.password = "somepassword" # ensure validation succeeds - user.encrypted_password = "$2a$10$KpSeaHGXoXEwdrERTFVCPo428a2s2r4ZazR999X9abc22368nneen" # set password hash so no known password matches the hash - user.groups.push(everyone) - user.save -end - -languages = YAML.load(File.read(File.expand_path("db/languages.yml", Rails.root))) -langfields = %i[name compiler compiler_command interpreter interpreter_command lexer interpreted compiled extension source_filename exe_extension processes] -languages.each do |grpid, grpcfg| - groupopts = grpcfg.slice(:name) - group = LanguageGroup.where(identifier: grpid).first_or_create! - group.update_attributes(groupopts) - - grpcfg[:variants].each do |langid, langcfg| - langopts = langcfg.reverse_merge(grpcfg).slice(*langfields).merge(group_id: group.id) - language = Language.where(identifier: langid).first_or_create! - language.update_attributes(langopts) - end - - group.update_attributes(current_language_id: group.languages.find_by_identifier(grpcfg[:current]).id) -end - -ProblemSeries.where(identifier: "COCI").first_or_create!.update_attributes(name: "Croatian Open Competition in Informatics", importer_type: "Problems::COCI::Importer") - -Entity.find_or_create_by(name: "New Zealand Olympiad in Informatics", entity_type: "Organisation") do |entity| - entity.entity_id = Organisation.create.id -end +env_seed_path = Rails.root.join("db/seeds/#{Rails.env}.rb") +require_relative env_seed_path if File.exist?(env_seed_path) diff --git a/db/seeds/common.rb b/db/seeds/common.rb new file mode 100644 index 00000000..6c7fe2d5 --- /dev/null +++ b/db/seeds/common.rb @@ -0,0 +1,50 @@ +%w[superadmin admin staff organiser author].each do |name| + Role.find_or_create_by!(name: name) +end + +rootuser = User + .create_with( + username: "System", + name: "System", + email: "nztrain@gmail.com", + password: SecureRandom.base64(18), + roles: [Role.find_by!(name: "superadmin")] + ) + .find_or_create_by!(id: 0) + +["system/mailer/email", "system/mailer/password", "recaptcha/public_key", "recaptcha/private_key"].each do |setting| + Setting.find_or_create_by!(key: setting) +end + +Setting + .create_with(value: Random.new.rand(2E9.to_i).to_s) + .find_or_create_by!(key: "submissions/shuffle") + +Group + .create_with( + name: "Everyone", + owner: rootuser + ) + .find_or_create_by(id: 0) + +languages = YAML.safe_load(File.read(File.expand_path("db/languages.yml", Rails.root))).with_indifferent_access +langfields = %i[name compiler compiler_command interpreter interpreter_command lexer interpreted compiled extension source_filename exe_extension processes] +languages.each do |grpid, grpcfg| + groupopts = grpcfg.slice(:name) + group = LanguageGroup.where(identifier: grpid).first_or_create! + group.update_attributes(groupopts) + + grpcfg[:variants].each do |langid, langcfg| + langopts = langcfg.reverse_merge(grpcfg).slice(*langfields).merge(group_id: group.id) + language = Language.where(identifier: langid).first_or_create! + language.update_attributes(langopts) + end + + group.update_attributes(current_language_id: group.languages.find_by_identifier(grpcfg[:current]).id) +end + +ProblemSeries.where(identifier: "COCI").first_or_create!.update_attributes(name: "Croatian Open Competition in Informatics", importer_type: "Problems::COCI::Importer") + +Entity.find_or_create_by(name: "New Zealand Olympiad in Informatics", entity_type: "Organisation") do |entity| + entity.entity_id = Organisation.create.id +end diff --git a/db/seeds/development.rb b/db/seeds/development.rb new file mode 100644 index 00000000..2427db30 --- /dev/null +++ b/db/seeds/development.rb @@ -0,0 +1,26 @@ +# db/seeds/common.rb always runs before this, so we can assume +# roles etc defined there exist already. + +# Add a nice, memorable, boring set of users for local development +%w[user admin superadmin].each do |username| + User + .create_with( + name: username.capitalize, + email: "#{username}@example.com", + password: "password", + confirmed_at: Time.current + ).find_or_create_by!( + username: username + ) +end + +User.find_by!(username: "admin").update!(roles: [Role.find_by!(name: "admin")]) +User.find_by!(username: "superadmin").update!(roles: [Role.find_by!(name: "superadmin")]) + +# A problem & set +problem_set = ProblemSet.find_or_create_by!(name: "Example problems") +Problem + .create_with(problem_sets: [problem_set]) + .find_or_create_by!(name: "Example problem") + +problem_set.group_associations.find_or_create_by!(group: Group.find_by(name: "Everyone"))