diff --git a/.pryrc b/.pryrc new file mode 100644 index 00000000..c150ac88 --- /dev/null +++ b/.pryrc @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +if defined?(PryByebug) + Pry.config.pager = false + Pry.commands.alias_command 'c', 'continue' + Pry.commands.alias_command 's', 'step' + Pry.commands.alias_command 'n', 'next' + Pry.commands.alias_command 'f', 'finish' +end diff --git a/Gemfile b/Gemfile index cd4f04d8..abd0b4b8 100644 --- a/Gemfile +++ b/Gemfile @@ -20,6 +20,7 @@ group :development, :test do gem 'dotenv-rails' gem 'factory_bot_rails' gem 'faker' + gem 'pry-byebug' gem 'rspec' gem 'rspec_junit_formatter' gem 'rspec-rails' diff --git a/Gemfile.lock b/Gemfile.lock index e3116564..246366e3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -64,6 +64,8 @@ GEM bootsnap (1.9.3) msgpack (~> 1.0) builder (3.2.4) + byebug (11.1.3) + coderay (1.1.3) concurrent-ruby (1.1.9) crass (1.0.6) diff-lcs (1.4.4) @@ -112,6 +114,12 @@ GEM parser (3.0.3.2) ast (~> 2.4.1) pg (1.2.3) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) + pry-byebug (3.9.0) + byebug (~> 11.0) + pry (~> 0.13.0) puma (5.5.2) nio4r (~> 2.0) racc (1.6.0) @@ -233,6 +241,7 @@ DEPENDENCIES importmap-rails jbuilder pg (~> 1.1) + pry-byebug puma (~> 5.0) rack-cors rails (~> 7.0.0) diff --git a/app/models/component.rb b/app/models/component.rb index 5f605f05..f8b53364 100644 --- a/app/models/component.rb +++ b/app/models/component.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true class Component < ApplicationRecord + belongs_to :project end diff --git a/app/models/project.rb b/app/models/project.rb index 4dce289f..23217a0e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -5,7 +5,7 @@ class Project < ApplicationRecord before_validation :check_unique_not_null, on: :create validates :identifier, presence: true, uniqueness: true - has_many :components, dependent: :destroy + has_many :components, -> { order(:index) }, dependent: :destroy, inverse_of: :project private diff --git a/db/migrate/20220211102958_add_index_field_to_project_components.rb b/db/migrate/20220211102958_add_index_field_to_project_components.rb new file mode 100644 index 00000000..77ae188a --- /dev/null +++ b/db/migrate/20220211102958_add_index_field_to_project_components.rb @@ -0,0 +1,5 @@ +class AddIndexFieldToProjectComponents < ActiveRecord::Migration[7.0] + def change + add_column :components, :index, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 9975cbb4..ec9163cf 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_02_11_085731) do +ActiveRecord::Schema.define(version: 2022_02_11_102958) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -23,6 +23,7 @@ t.text "content", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false + t.integer "index" t.index ["project_id"], name: "index_components_on_project_id" end diff --git a/lib/tasks/project_components/hello_world_example/emoji.py b/lib/tasks/project_components/hello_world_example/emoji.py new file mode 100644 index 00000000..13dae5d0 --- /dev/null +++ b/lib/tasks/project_components/hello_world_example/emoji.py @@ -0,0 +1,27 @@ +# Emoji variables to use in your project + +world = '🌍🌎🌏' +python = '🐍⌨️' +sums = '✖️➗➖➕' +calendar = '📅' +clock = '🕒' +projects = '🎨🎮🔬' +fun = '🎉🕶️' +dice = '🎲' +unicorn = '🦄' +space = '🚀' +happy = '😃' +silly = '😜' +heart = '❤️' +games = '🎮' +books = '📚' +sports = '⚽🎾👟' +green = '♻️' +nature = '🌳' +fire = '🔥' +sparkles = '✨' +plead = '🥺' +hundred = '💯' +star = '⭐' +yellow_heart = '💛' +rainbow = '🌈' \ No newline at end of file diff --git a/lib/tasks/project_components/hello_world_example/main.py b/lib/tasks/project_components/hello_world_example/main.py new file mode 100644 index 00000000..f89e0563 --- /dev/null +++ b/lib/tasks/project_components/hello_world_example/main.py @@ -0,0 +1,45 @@ +#!/bin/python3 + +from emoji import * +from datetime import * +from random import randint + +# Put function definitions under here + +def roll_dice(): + print(python, 'can make a', dice) + max = input('How many sides?') # get input from the user + print('That is a D', max) # use the number the user entered + roll = randint(1, int(max)) # generate a random number + print('You rolled a', roll) # print the value of the roll variable + print(fire * roll) # repeat the fire text roll times + +def hobbies(): + hobby = input('What do you like?') + print('That sounds', fun) + print('You could make a', python, 'project about', hobby) + +# Put code to run under here +# Useful characters :',()*_/.# + +print('Hello', world) +print('Welcome to', python) + +input() # wait for the user to tap Enter + +print(python, 'is very good at', sums) +print(230 * 5782 ** 2 / 23781) + +input() + +now = datetime.now() # get the current date and time +print('The', calendar, clock, 'is', now) # print with emoji + +input() + +roll_dice() # Call the roll_dice function + +input() + +hobbies() # Call the hobbies function + diff --git a/lib/tasks/project_components/hello_world_example/noemoji.py b/lib/tasks/project_components/hello_world_example/noemoji.py new file mode 100644 index 00000000..67b400e0 --- /dev/null +++ b/lib/tasks/project_components/hello_world_example/noemoji.py @@ -0,0 +1,19 @@ +# Add ASCII art alternatives +# Before emoji we used emoticons made from characters + +world = 'o' +python = '~~~-<' +happy = ':-)' +heart = '♡' # or '<3' +star = '☆' +sparkles = '✺' +silly = ';)' +sums = '+-*/' +hundred = '100!' +plead = '◔◔' +fire = '/\\' +books = '≣' +rainbow = '⌒' +dice = '⊡' +clock = '◷' +calendar = '▦' diff --git a/lib/tasks/project_components/hello_world_example/project_config.yml b/lib/tasks/project_components/hello_world_example/project_config.yml new file mode 100644 index 00000000..0d29c426 --- /dev/null +++ b/lib/tasks/project_components/hello_world_example/project_config.yml @@ -0,0 +1,15 @@ +NAME: "Hello 🌍🌎🌏 Example" +IDENTIFIER: "python-emoji-example" +COMPONENTS: + - name: "main" + extension: "py" + location: "main.py" + index: 0 + - name: "emoji" + extension: "py" + location: "emoji.py" + index: 1 + - name: "noemoji" + extension: "py" + location: "noemoji.py" + index: 2 \ No newline at end of file diff --git a/lib/tasks/project_components/hello_world_starter/emoji.py b/lib/tasks/project_components/hello_world_starter/emoji.py new file mode 100644 index 00000000..13dae5d0 --- /dev/null +++ b/lib/tasks/project_components/hello_world_starter/emoji.py @@ -0,0 +1,27 @@ +# Emoji variables to use in your project + +world = '🌍🌎🌏' +python = '🐍⌨️' +sums = '✖️➗➖➕' +calendar = '📅' +clock = '🕒' +projects = '🎨🎮🔬' +fun = '🎉🕶️' +dice = '🎲' +unicorn = '🦄' +space = '🚀' +happy = '😃' +silly = '😜' +heart = '❤️' +games = '🎮' +books = '📚' +sports = '⚽🎾👟' +green = '♻️' +nature = '🌳' +fire = '🔥' +sparkles = '✨' +plead = '🥺' +hundred = '💯' +star = '⭐' +yellow_heart = '💛' +rainbow = '🌈' \ No newline at end of file diff --git a/lib/tasks/project_components/hello_world_starter/main.py b/lib/tasks/project_components/hello_world_starter/main.py new file mode 100644 index 00000000..6d157065 --- /dev/null +++ b/lib/tasks/project_components/hello_world_starter/main.py @@ -0,0 +1,12 @@ +#!/bin/python3 + +from emoji import * +from datetime import * +from random import randint + +# Put function definitions under here + +# Useful characters :',()*_/.# + +# Put code to run under here + diff --git a/lib/tasks/project_components/hello_world_starter/noemoji.py b/lib/tasks/project_components/hello_world_starter/noemoji.py new file mode 100644 index 00000000..67b400e0 --- /dev/null +++ b/lib/tasks/project_components/hello_world_starter/noemoji.py @@ -0,0 +1,19 @@ +# Add ASCII art alternatives +# Before emoji we used emoticons made from characters + +world = 'o' +python = '~~~-<' +happy = ':-)' +heart = '♡' # or '<3' +star = '☆' +sparkles = '✺' +silly = ';)' +sums = '+-*/' +hundred = '100!' +plead = '◔◔' +fire = '/\\' +books = '≣' +rainbow = '⌒' +dice = '⊡' +clock = '◷' +calendar = '▦' diff --git a/lib/tasks/project_components/hello_world_starter/project_config.yml b/lib/tasks/project_components/hello_world_starter/project_config.yml new file mode 100644 index 00000000..8e1bc82c --- /dev/null +++ b/lib/tasks/project_components/hello_world_starter/project_config.yml @@ -0,0 +1,15 @@ +NAME: "Hello 🌍🌎🌏" +IDENTIFIER: "python-hello-starter" +COMPONENTS: + - name: "main" + extension: "py" + location: "main.py" + index: 0 + - name: "emoji" + extension: "py" + location: "emoji.py" + index: 1 + - name: "noemoji" + extension: "py" + location: "noemoji.py" + index: 2 \ No newline at end of file diff --git a/lib/tasks/project_components/target_practice_example/main.py b/lib/tasks/project_components/target_practice_example/main.py new file mode 100644 index 00000000..8d0da567 --- /dev/null +++ b/lib/tasks/project_components/target_practice_example/main.py @@ -0,0 +1,61 @@ +#!/bin/python3 + +# Import library code +from p5 import * +from math import * +from random import randint + +# The mouse_pressed function goes here +def mouse_pressed(): + if hit_color == outer: + print('You hit the outer circle, 50 points!') #Like functions, 'if' statements are indented + elif hit_color == inner: + print('You hit the inner circle, 200 points!') + elif hit_color == bullseye: + print('You hit the bullseye, 500 points!') + else: + print('You missed! No points!') + +# The shoot_arrow function goes here +def shoot_arrow(): + global hit_color + arrow_x = randint(100, 300) + arrow_y = randint(100, 300) + hit_color = get(arrow_x, arrow_y) + ellipse(arrow_x, arrow_y, 15, 15) + +def setup(): +# Setup your game here + size(400, 400) # width and height + frame_rate(2) + + +def draw(): +# Things to do in every frame + global outer, inner, bullseye + sky = color(92, 204, 206) # Red = 92, Green = 204, Blue = 206 + grass = color(149, 212, 122) + wood = color(145, 96, 51) + outer = color(0, 120, 180) + inner = color(210, 60, 60) + bullseye = color(220, 200, 0) + + no_stroke() + fill(sky) + rect(0, 0, 400, 250) + fill(grass) + rect(0, 250, 400, 150) + + fill(wood) + triangle(150, 350, 200, 150, 250, 350) + fill(outer) + ellipse(200, 200, 170, 170) + fill(inner) + ellipse(200, 200, 110, 110) #Inner circle + fill(bullseye) + ellipse(200, 200, 30, 30) #Bullseye + + fill(wood) + shoot_arrow() +# Keep this to run your code +run() diff --git a/lib/tasks/project_components/target_practice_example/project_config.yml b/lib/tasks/project_components/target_practice_example/project_config.yml new file mode 100644 index 00000000..b221ea73 --- /dev/null +++ b/lib/tasks/project_components/target_practice_example/project_config.yml @@ -0,0 +1,7 @@ +NAME: "Target Practice Example" +IDENTIFIER: "python-archery-example" +COMPONENTS: + - name: "main" + extension: "py" + location: "main.py" + index: 0 \ No newline at end of file diff --git a/lib/tasks/project_components/target_practice_starter/main.py b/lib/tasks/project_components/target_practice_starter/main.py new file mode 100644 index 00000000..a90ab85c --- /dev/null +++ b/lib/tasks/project_components/target_practice_starter/main.py @@ -0,0 +1,27 @@ +#!/bin/python3 + +# Import library code +from p5 import * +from math import * +from random import randint + +# The mouse_pressed function goes here + +# The shoot_arrow function goes here + +def setup(): +# Setup your game here + size(400, 400) # width and height + frame_rate(2) + + +def draw(): +# Things to do in every frame + sky = color(92, 204, 206) # Red = 92, Green = 204, Blue = 206 + grass = color(149, 212, 122) + wood = color(145, 96, 51) + outer = color(0, 120, 180) + + +# Keep this to run your code +run() diff --git a/lib/tasks/project_components/target_practice_starter/project_config.yml b/lib/tasks/project_components/target_practice_starter/project_config.yml new file mode 100644 index 00000000..12de0e7f --- /dev/null +++ b/lib/tasks/project_components/target_practice_starter/project_config.yml @@ -0,0 +1,7 @@ +NAME: "Target Practice" +IDENTIFIER: "python-archery-starter" +COMPONENTS: + - name: "main" + extension: "py" + location: "main.py" + index: 0 \ No newline at end of file diff --git a/lib/tasks/projects.rake b/lib/tasks/projects.rake index 6c636dad..0e17816f 100644 --- a/lib/tasks/projects.rake +++ b/lib/tasks/projects.rake @@ -1,144 +1,24 @@ # frozen_string_literal: true +require 'yaml' + namespace :projects do desc 'Import starter projects' task create_starter: :environment do - Project.find_by(identifier: 'python-hello-starter')&.destroy - project = Project.new(identifier: 'python-hello-starter', name: 'Hello World!') - project.components << Component.new(name: 'main', extension: 'py', content: main_content) - project.components << Component.new(name: 'emoji', extension: 'py', content: emoji_content) - project.components << Component.new(name: 'noemoji', extension: 'py', content: no_emoji_content) - project.save - - Project.find_by(identifier: 'python-emoji-example')&.destroy - project = Project.new(identifier: 'python-emoji-example', name: 'Emoji Example Project') - project.components << Component.new(name: 'main', extension: 'py', content: main_runner_content) - project.components << Component.new(name: 'emoji', extension: 'py', content: emoji_content) - project.components << Component.new(name: 'noemoji', extension: 'py', content: no_emoji_content) - project.save + Dir.each_child("#{File.dirname(__FILE__)}/project_components") do |dir| + proj_config = YAML.safe_load(File.read("#{File.dirname(__FILE__)}/project_components/#{dir}/project_config.yml")) + Project.find_by(identifier: proj_config['IDENTIFIER'])&.destroy + new_project = Project.new(identifier: proj_config['IDENTIFIER'], name: proj_config['NAME']) + components = proj_config['COMPONENTS'] + components.each do |component| + name = component['name'] + extension = component['extension'] + code = File.read(File.dirname(__FILE__) + "/project_components/#{dir}/#{component['location']}") + index = component['index'] + project_component = Component.new(name: name, extension: extension, content: code, index: index) + new_project.components << project_component + end + new_project.save + end end end - -def main_content - main_content = <<~END - #!/bin/python3 - - from emoji import *#{' '} - from datetime import * - from random import randint - - # Put function definitions under here - - # Useful characters :',()*_/.# - - # Put code to run under here - - print('Hello ', world) - END -end - -def emoji_content - emoji_content = <<~END - # Emoji variables to use in your project - - world = '🌍🌎🌏' - python = '🐍⌨️' - sums = '✖️➗➖➕' - calendar = '📅' - clock = '🕒' - projects = '🎨🎮🔬' - fun = '🎉🕶️' - dice = '🎲' - unicorn = '🦄' - space = '🚀' - happy = '😃' - silly = '😜' - heart = '❤️' - games = '🎮' - books = '📚' - sports = '⚽🎾👟' - green = '♻️' - nature = '🌳' - fire = '🔥' - sparkles = '✨' - plead = '🥺' - hundred = '💯' - star = '⭐' - yellow_heart = '💛' - rainbow = '🌈' - END -end - -def no_emoji_content - no_emoji_content = <<~END - # Add ASCII art alternatives - # Before emoji we used emoticons made from characters - - world = 'o' - python = '~~~-<' - happy = ':-)' - heart = '♡' # or '<3' - star = '☆' - sparkles = '✺' - silly = ';)' - sums = '+-*/' - hundred = '100!' - plead = '◔◔' - fire = '/\\' - books = '≣' - rainbow = '⌒' - dice = '⊡' - clock = '◷' - calendar = '▦' - - END -end - -def main_runner_content - main_runner_content = <<~END - #!/bin/python3 - - from emoji import *#{' '} - from datetime import * - from random import randint - - # Put function definitions under here - - def roll_dice(): - print(python, 'can make a', dice) - max = input('How many sides?') # get input from the user - print('That is a D', max) # use the number the user entered - roll = randint(1, int(max)) # generate a random number#{' '} - print('You rolled a', roll) # print the value of the roll variable - print(fire * roll) # repeat the fire text roll times - - def hobbies(): - hobby = input('What do you like?') - print('That sounds', fun) - print('You could make a', python, 'project about', hobby) - - # Put code to run under here - # Useful characters :',()*_/.# - - print('Hello', world) - print('Welcome to', python) - - input() # wait for the user to tap Enter - - print(python, 'is very good at', sums) - print(230 * 5782 ** 2 / 23781) - - input() - - now = datetime.now() # get the current date and time - print('The', calendar, clock, 'is', now) # print with emoji#{' '} - - input() - - roll_dice() # Call the roll_dice function - - input() - - hobbies() # Call the hobbies function - END -end