diff --git a/T2/README.md b/T2/README.md new file mode 100644 index 0000000000000000000000000000000000000000..2ec2b8ab1305c3dec3925c786f30cafbe7f120aa --- /dev/null +++ b/T2/README.md @@ -0,0 +1,67 @@ +# STEAMDB V0.0.1 +### dependencies: latest version of ruby (2.5.0), active\_record gem, sqlite3 gem + + +## Introduction +### Wellington Gabriel Vicente de Souza - GRR20163081 - CI320 + +Hi! This is a project made for the second evaluation of the Tópicos em Programação de Computadores (CI320) course at Universidade Federal do Paraná in Brazil. The objective of this project was purely to solidify our knowledge in the Ruby language. + +This project simulates a simplified working database management system similar to sqlite3. It was implemented in the Ruby language and it uses the Active Record gem to establish a connection with sqlite3. + +## How to use +### Creating the database +To create the tables defined in the schema.rb file, run: +$ ruby schema.rb + +The steamdb.sqlite3 file on this repository already contains a few example rows to simplify the testing of the different functionalities. To reset the entire database, simply delete the steamdb.sqlite3 file and run the schema.rb file again. + +The models for each object type are defined in the models.rb file. This database system implements 1 to 1, 1 to n and n to n relationships. + +### Seeding the database +This repository includes a seed file for the database. Just execute the seed_db.sh file to seed the database: +$ ./seed_db.sh + +### Running SteamDB +To run SteamDB, just enter the following command on your terminal: +$ ruby steamdb.rb + +### Instructions +This program contains five basic commands: + - insere (add a new element) + - exclui (remove one or more elements) + - altera (update one or more elements) + - lista (list all the elements of a table) + - sair (exit) + +### Command syntax +< op > < table > < { attribute=value } > + +possible < op > values are insere, exclui, altera and lista +< table > indicates the name of the table you will be using for the operation +{ ... } indicates the possibility of more than one argument +attribute=value has different meanings, acting both as a WHERE select and as an attribution + +To clarify, here are some examples: + +Creating a developer named Jose that lives in Brasil: ++ insere developers name="jose" country="brasil" + +Listing all the developers ++ lista developers + +Changing the name and country values of the row(s) with a "Jose" value on the name column ++ altera developers name="jose" name="joão" country="usa" + +Observation: in the "altera" operation, the first (and only the first) attribute=value pair is used to select one or more rows with the defined value + +Deleting a row ++ exclui developers name="joão" country="usa" + +Deleting all rows of a table ++ exclui developers + +## Relationships +1 to 1 = (Game Price), a game can only have one price list +1 to n = (Developer Game), a developer can have one or more games +n to n = (Category Game), a game can have many categories and categories have many games related to them diff --git a/T2/criaSchema.rb b/T2/criaSchema.rb deleted file mode 100644 index ac5c8e09d2456bd319756420546985341da815be..0000000000000000000000000000000000000000 --- a/T2/criaSchema.rb +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# Cria uma nova base de dados a cada vez. -# Para criar o bd execute "ruby criaSchema.rb". - -require 'rubygems' -require 'active_record' - -# As duas linhas abaixo indicam o SGBD a ser usado (sqlite3) e o nome -# do arquivo que contém o banco de dados (Aulas.sqlite3) -ActiveRecord::Base.establish_connection :adapter => "sqlite3", - :database => "Aulas.sqlite3" - -# As linhas abaixo criam a tabela "pessoas" dentro do banco -# "Aulas.sqlite3", indicando os atributos e os seus tipos. No caso, -# todos são "string", mas tem várias outras oportunidades. -ActiveRecord::Base.connection.create_table :pessoas do |t| - t.string :last_name - t.string :first_name - t.string :address - t.string :city -end - -# Sugestão de bibliografia: -# http://www.amazon.com/Pro-Active-Record-Databases-Experts/dp/1590598474 - -=begin ------>>>> ------ Dica de como implementar relações: -1x1 (Pessoa Profissão) -1xn (Pessoa Sapatos) -nxn (Pessoa Casa) ------>>>> - - -ActiveRecord::Base.connection.create_table :profissaos do |t| - t.integer :pessoa_id - ... demais atributos ... -end - -ActiveRecord::Base.connection.create_table :sapatos do |t| - t.integer :pessoa_id - ... demais atributos ... -end - -ActiveRecord::Base.connection.create_table :casas do |t| - ... demais atributos ... -end - -ActiveRecord::Base.connection.create_table :pessoas do |t| - t.integer :profissao_id - ... demais atributos ... -end - -ActiveRecord::Base.connection.create_table :casas_pessoas do |t| - t.integer :pessoa_id - t.integer :casa_id - ... demais atributos ... -end - -=end diff --git a/T2/models.rb b/T2/models.rb index 23d507eae070b024e5e1ce7f6c84d8682c88fb3b..eabc3e3b2bea12e1056301bc9693afd3c5db3195 100644 --- a/T2/models.rb +++ b/T2/models.rb @@ -4,13 +4,14 @@ ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => "steamdb.sqlite3" class Game < ActiveRecord::Base; - has_one :price + has_one :price, dependent: :destroy belongs_to :developer - has_and_belongs_to_many :categories + has_many :category_games + has_many :categories, through: :category_games, dependent: :destroy end class Developer < ActiveRecord::Base; - has_many :games + has_many :games, dependent: :destroy end class Price < ActiveRecord::Base; @@ -18,5 +19,11 @@ class Price < ActiveRecord::Base; end class Category < ActiveRecord::Base; - has_and_belongs_to_many :games + has_many :category_games + has_many :games, through: :category_games, dependent: :destroy +end + +class CategoryGame < ActiveRecord::Base; + belongs_to :category + belongs_to :game end \ No newline at end of file diff --git a/T2/pessoas.rb b/T2/pessoas.rb deleted file mode 100644 index 636e9c23738e0d915d64d722eb70c544aa2f79e6..0000000000000000000000000000000000000000 --- a/T2/pessoas.rb +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: utf-8 -*- -require 'active_record' - -# Só execute este programa depois de criar o banco de dados (ruby -# criaSchema.rb) - -# Este exemplo só tem dois "parâmetros" (adapter e database). Porém, -# existem outros: (host, username, password), que podem ser usados com -# outros bancos de dados. -ActiveRecord::Base.establish_connection :adapter => "sqlite3", - :database => "Aulas.sqlite3" - - -class Pessoa < ActiveRecord::Base; -end - -# O bacana aqui é que não foram declarados os atributos da classe -# Pessoa. Para isto, o ActiveRecord vai até o banco de dados, procura -# pelos atributos daquela tabela e automaticamente as "insere" como -# atributos da classe. - -# Para demonstrar como acessar estes atributos, vamos a alguns exemplos: - -# Formas de inserir informação no banco de dados. -# Método 1: campo a campo. - -p = Pessoa.new() -p.last_name = "Hansen" -p.first_name = "Ola" -p.address = "Timoteivn 10" -p.city = "Sandnes" -p.save() - -# Método 1: em um único comando. -p = Pessoa.new(:last_name => "Svendson", - :first_name => "Tove", - :address => "Borgvn 23", - :city => "Sandnes") -p.save() - -p = Pessoa.new(:last_name => "Pettersen", - :first_name => "Kari", - :address => "Storgt 20", - :city => "Stavanger") -p.save() - -# Formas de acessar o banco de dados; - -# (1) Traz "todo o banco" para uma única variável (Array), e usar os -# iteradores para navegar lá dentro. - -pessoas = Pessoa.all; -pessoas.each do |p| - puts "#{p.id}, #{p.last_name}, #{p.first_name}, #{p.address}, #{p.city}" -end - -# (2) Usar o método "find", dando como parâmetro o pk. Verifique a -# classe resultante. - -p = Pessoa.find(1) -puts "(Pessoa.find(1)): #{p.id}, #{p.last_name}, #{p.first_name}, #{p.address}, #{p.city}" - -# (3) Usar os métodos do tipo "dynamic finders". Estes métodos não -# estão implementados em lugar nenhum. A composição é feita da -# seguinte forma: "<Objeto>.find_by_<nome do atributo>". Muito -# esquisito, mas isto é metaprogramação. Um código será "criado" a -# partir destes parâmetros para fazer a busca no BD. Uma coisa -# importante é que tem dois tipos de finders, o "find" e o -# "find_all". O primeiro retorna um objeto da classe espeficiada. O -# segundo retorna um array de objetos da classe. - -pes = Pessoa.where(city: "Stavanger").find_each do |p| - puts p.class - puts p.inspect - puts "(Pessoa.find(...): #{p.id}, #{p.last_name}, #{p.first_name}, #{p.address}, #{p.city}" -end - - - -=begin - -1x1 (Pessoa Profissão) -1xn (Pessoa Sapatos) -nxn (Pessoa Casa) - -class Profissao < ActiveRecord::Base; - belongs_to :pessoa -end - -class Sapato < ActiveRecord::Base; - belongs_to :pessoa -end - -class Casa < ActiveRecord::Base; - has_and_belongs_to_many :pessoas -end - -class Pessoa < ActiveRecord::Base; - has_one :profissao - has_many :sapatos - has_and_belongs_to_many :casas - -end - - -=end diff --git a/T2/schema.rb b/T2/schema.rb index 50c94c6c80e6aa9e4387f55a43bac4612e5d5f9e..7383aa8cebd5a354a5923cdde921d5d1e519c5f4 100644 --- a/T2/schema.rb +++ b/T2/schema.rb @@ -28,7 +28,7 @@ ActiveRecord::Base.connection.create_table :categories do |t| t.text :description end -ActiveRecord::Base.connection.create_table :categories_games, id: false do |t| +ActiveRecord::Base.connection.create_table :category_games, id: false do |t| t.references :category t.references :game -end \ No newline at end of file +end diff --git a/T2/seed_db.sh b/T2/seed_db.sh new file mode 100755 index 0000000000000000000000000000000000000000..e8be18290fbeada99bcebd61d60e93d5411e220a --- /dev/null +++ b/T2/seed_db.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +eval "ruby steamdb.rb < seeds" diff --git a/T2/seeds b/T2/seeds new file mode 100644 index 0000000000000000000000000000000000000000..a704e7f9633733398e541525f65bc6ca02ff7b6b --- /dev/null +++ b/T2/seeds @@ -0,0 +1,53 @@ +insere developers name="Obsidian" country="Luxembourg" +insere developers name="Bethesda" country="USA" +insere developers name="Icarus" country="Argentina" +insere developers name="Capivara Games" country="Brazil" +insere developers name="Degica" country="Japan" +insere developers name="Square Enix" country="Japan" +insere developers name="Eidos Interactive" country="USA" +insere developers name="inXile" +insere developers name="Taleworlds" country="Poland" +insere developers name="EA Games" country="USA" +insere games name="Oblivion" description="second best elder scrolls game" is_released=true developer_id=2 +insere games name="Fallout 1" description="one of the best games that ever existed" is_released=true developer_id=1 +insere games name="Fallout 2" description="the best game that ever existed" is_released=true developer_id=1 +insere games name="Fallout New Vegas" description="this is fallout, not bethesda's fallout 3" is_released=true developer_id=1 +insere games name="Fallout 3: Van Buren" is_released=false developer_id=1 +insere games name="Capivara Land" description="capivaras!" is_released=true developer_id=4 +insere games name="Wasteland 1" description="old but good" is_released=true developer_id=8 +insere games name="Wasteland 2" description="a really really good game" is_released=true developer_id=8 +insere games name="Mount and Blade: Warband" description="pointy spears" is_released=true developer_id=9 +insere games name="Kingdoms of Amalur: Reckoning" description="a really cool rpg" is_released=true developer_id=10 +insere prices price_us=530 price_br=239 price_ru=200 game_id=1 +insere prices price_us=530 price_br=259 price_ru=230 game_id=2 +insere prices price_us=530 price_br=4529 price_ru=400 game_id=3 +insere prices price_us=530 price_br=329 price_ru=500 game_id=4 +insere prices price_us=530 price_br=219 price_ru=270 game_id=6 +insere prices price_us=530 price_br=219 price_ru=120 game_id=7 +insere prices price_us=530 price_br=129 price_ru=200 game_id=8 +insere prices price_us=530 price_br=29 price_ru=2400 game_id=9 +insere prices price_us=530 price_br=29 price_ru=2030 game_id=10 +insere categories name="fps" description="first person shooters" +insere categories name="tps" description="third person shooters" +insere categories name="arcade" +insere categories name="platformer" +insere categories name="rpg" description="roleplaying games" +insere categories name="open world" description="games with a huge world to explore" +insere categories name="fantasy" description="fantasy games" +insere categories name="capivaras" description="capivaras!" +insere categories name="post-apocalyptic" description="the one true genre" +insere categories name="high fantasy" description="fantasy x100" +insere category_games category_id=1 game_id=1 +insere category_games category_id=2 game_id=1 +insere category_games category_id=5 game_id=1 +insere category_games category_id=6 game_id=1 +insere category_games category_id=7 game_id=1 +insere category_games category_id=10 game_id=1 +insere category_games category_id=3 game_id=6 +insere category_games category_id=5 game_id=7 +insere category_games category_id=9 game_id=7 +insere category_games category_id=5 game_id=8 +insere category_games category_id=9 game_id=8 +insere category_games category_id=6 game_id=9 +insere category_games category_id=10 game_id=10 +sair diff --git a/T2/steamdb.rb b/T2/steamdb.rb index f0bb322b622bece58b52b6af2f9f5d59c11c93bf..19255c27a9aa07bc427ed1417a7c3a196e31bef3 100644 --- a/T2/steamdb.rb +++ b/T2/steamdb.rb @@ -1,359 +1,742 @@ require './models.rb' def is_a_string (string) - string.start_with?('"') && string.end_with?('"') ? true : false + string.start_with?('"') && string.end_with?('"') ? true : false end def is_a_integer (integer) - integer =~ /\A\d+\z/ ? true : false + integer =~ /\A\d+\z/ ? true : false end -def insere(tabela, args) - error = false - case tabela - when "developers" - dev = Developer.new () - args.each do |x| - x = x.split("=") - case x[0] - when "name" - if is_a_string(x[1]) - dev.name = x[1].tr('"',''); - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "country" - if is_a_string(x[1]) - dev.country = x[1].tr('"','') - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if (!error) - dev.save - puts "Linha inserida na tabela #{tabela}." - end - when "games" - game = Game.new () - args.each do |x| - x = x.split("=") - case x[0] - when "name" - if is_a_string(x[1]) - game.name = x[1]; - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "description" - if is_a_string(x[1]) - game.description = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "is_released" - if x[1] === "true" || x[1] === "false" - game.is_released = x[1] === "true" ? true : false - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "developer_id" - if is_a_integer(x[1]) - game.developer_id = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if (!error) - game.save - puts "Linha inserida na tabela #{tabela}." - end - when "prices" - price = Price.new () - args.each do |x| - x = x.split("=") - case x[0] - when "price_us" - if is_a_integer(x[1]) - price.price_us = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "price_br" - if is_a_integer(x[1]) - price.price_br = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "price_ru" - if is_a_integer(x[1]) - price.price_ru = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "game_id" - if is_a_integer(x[1]) - price.game_id = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if (!error) - price.save - puts "Linha inserida na tabela #{tabela}." - end - when "categories" - category = Category.new () - args.each do |x| - x = x.split("=") - case x[0] - when "name" - if is_a_string(x[1]) - category.name = x[1]; - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "description" - if is_a_string(x[1]) - category.description = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if (!error) - category.save - puts "Linha inserida na tabela #{tabela}." - end - when "categories_games" - category_game = CategoryGame.new () - args.each do |x| - x = x.split("=") - case x[0] - when "category_id" - if is_a_integer(x[1]) - category_game.category_id = x[1]; - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - when "game_id" - if is_a_integer(x[1]) - category_game.game_id = x[1] - else - puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if (!error) - category_game.save - puts "Linha inserida na tabela #{tabela}." - end - else - puts "Tabela #{tabela} não encontrada." - end -end - -def exclui(tabela, args) - to_be_deleted = nil - error = false - case tabela - when "developers" - to_be_deleted = Developer.all - puts to_be_deleted - args.each do |x| - x = x.split("=") - case x[0] - when "name" - if is_a_string(x[1]) - to_be_deleted = to_be_deleted.select {|delete| delete.name == x[1].tr('"','')} - else - puts "Erro de SÃntaxe: Valor inválido para #{{x[0]}}" - error = true - end - when "country" - if is_a_string(x[1]) - to_be_deleted = to_be_deleted.select {|delete| delete.country == x[1].tr('"','')} - else - puts "Erro de SÃntaxe: Valor inválido para #{{x[0]}}" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if to_be_deleted.length > 0 - to_be_deleted.each do |d| - d.delete - end - end - when "games" - to_be_deleted = Game.all - puts to_be_deleted - args.each do |x| - x = x.split("=") - case x[0] - when "name" - if is_a_string(x[1]) - to_be_deleted = to_be_deleted.select {|delete| delete.name == x[1].tr('"','')} - else - puts "Erro de SÃntaxe: Valor inválido para #{{x[0]}}" - error = true - end - when "description" - if is_a_string(x[1]) - to_be_deleted = to_be_deleted.select {|delete| delete.country == x[1].tr('"','')} - else - puts "Erro de SÃntaxe: Valor inválido para #{{x[0]}}" - error = true - end - when "is_released" - if x[1] === "true" || x[1] === "false" - to_be_deleted = to_be_deleted.select {|delete| (delete.is_released == (x[1] === "true" ? true : false))} - else - puts "Erro de SÃntaxe: Valor inválido para #{{x[0]}}" - error = true - end - when "description" - if is_a_integer(x[1]) - to_be_deleted = to_be_deleted.select {|delete| delete.developer_id == x[1]} - else - puts "Erro de SÃntaxe: Valor inválido para #{{x[0]}}" - error = true - end - else - puts "Atributo #{x[0]} não encontrado." - error = true - end - next - end - if to_be_deleted.length > 0 - to_be_deleted.each do |d| - d.delete - end - end - when "prices" +def parse_input (string) + i = 0 + args = [] + arg = '' + begin_quote = false + string.each_char do |c| + if c == '"' + begin_quote = !begin_quote + end - when "categories" + if c != ' ' || begin_quote == true + arg = arg + c + else + args[i] = arg + i = i + 1 + arg = '' + end + end - when "categories_games" + if !begin_quote + args[i] = arg + else + puts "Erro de SÃntaxe: Aspas não encontradas." + args = [] + end - else - puts "Tabela #{tabela} não encontrada." - end + return args end -def altera(tabela) - case tabela - when "developers" - #???????? como alterar? sintaxe do comando - when "games" - - when "prices" +def insere(tabela, args) + error = false + case tabela + when "developers" + dev = Developer.new () + args.each do |x| + x = x.split("=") + case x[0] + when "name" + if is_a_string(x[1]) + dev.name = x[1].tr('"',''); + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "country" + if is_a_string(x[1]) + dev.country = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + if !error + dev.save + puts "Linha inserida na tabela #{tabela}." + end + when "games" + game = Game.new () + args.each do |x| + x = x.split("=") + case x[0] + when "name" + if is_a_string(x[1]) + game.name = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "description" + if is_a_string(x[1]) + game.description = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "is_released" + if x[1] === "true" || x[1] === "false" + game.is_released = x[1] === "true" ? true : false + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "developer_id" + if is_a_integer(x[1]) + game.developer_id = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + if (!error) + game.save + puts "Linha inserida na tabela #{tabela}." + end + when "prices" + price = Price.new () + args.each do |x| + x = x.split("=") + case x[0] + when "price_us" + if is_a_integer(x[1]) + price.price_us = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "price_br" + if is_a_integer(x[1]) + price.price_br = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "price_ru" + if is_a_integer(x[1]) + price.price_ru = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "game_id" + if is_a_integer(x[1]) + price.game_id = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + if (!error) + price.save + puts "Linha inserida na tabela #{tabela}." + end + when "categories" + category = Category.new () + args.each do |x| + x = x.split("=") + case x[0] + when "name" + if is_a_string(x[1]) + category.name = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "description" + if is_a_string(x[1]) + category.description = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + if (!error) + category.save + puts "Linha inserida na tabela #{tabela}." + end + when "category_games" + category_game = CategoryGame.new () + args.each do |x| + x = x.split("=") + case x[0] + when "category_id" + if is_a_integer(x[1]) + category_game.category_id = x[1]; + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "game_id" + if is_a_integer(x[1]) + category_game.game_id = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + if (!error) + category_game.save + puts "Linha inserida na tabela #{tabela}." + end + else + puts "Tabela #{tabela} não encontrada." + end +end - when "categories" +def select_rows(tabela, args) + selected = [] + error = false + case tabela + when "developers" + selected = Developer.all + args.each do |x| + x = x.split("=") + case x[0] + when "id" + if (is_a_integer(x[1])) + selected = selected.select {|delete| delete.id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "name" + if is_a_string(x[1]) + selected = selected.select {|delete| delete.name == x[1].tr('"','')} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "country" + if is_a_string(x[1]) + selected = selected.select {|delete| delete.country == x[1].tr('"','')} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + when "games" + selected = Game.all + args.each do |x| + x = x.split("=") + case x[0] + when "id" + if (is_a_integer(x[1])) + selected = selected.select {|delete| delete.id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "name" + if is_a_string(x[1]) + selected = selected.select {|delete| delete.name == x[1].tr('"','')} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "description" + if is_a_string(x[1]) + selected = selected.select {|delete| delete.country == x[1].tr('"','')} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "is_released" + if x[1] === "true" || x[1] === "false" + selected = selected.select {|delete| (delete.is_released == (x[1] === "true" ? true : false))} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "developer_id" + if is_a_integer(x[1]) + selected = selected.select {|delete| delete.developer_id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + end + next + end + when "prices" + selected = Price.all + args.each do |x| + x = x.split("=") + case x[0] + when "id" + if (is_a_integer(x[1])) + selected = selected.select {|delete| delete.id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "price_us" + if is_a_integer(x[1]) + selected = selected.select {|delete| delete.price_us == x[1].to_i} + else + puts "Erro de SÃntaxe: valor inválido para #{x[0]}" + error = true + end + when "price_br" + if is_a_integer(x[1]) + selected = selected.select {|delete| delete.price_br == x[1].to_i} + else + puts "Erro de SÃntaxe: valor inválido para #{x[0]}" + error = true + end + when "price_ru" + if is_a_integer(x[1]) + selected = selected.select {|delete| delete.price_ru == x[1].to_i} + else + puts "Erro de SÃntaxe: valor inválido para #{x[0]}" + error = true + end + when "game_id" + if is_a_integer(x[1]) + selected = selected.select {|delete| delete.game_id == x[1].to_i} + else + puts "Erro de SÃntaxe: valor inválido para #{x[0]}" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true; + end + if error + break + end + next + end + when "categories" + selected = Category.all + args.each do |x| + x = x.split("=") + case x[0] + when "id" + if (is_a_integer(x[1])) + selected = selected.select {|delete| delete.id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "name" + if is_a_string(x[1]) + selected = selected.select {|delete| delete.name == x[1].tr('"','')} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "description" + if is_a_string(x[1]) + selected = selected.select {|delete| delete.name == x[1].tr('"','')} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true; + end + if error + break + end + next + end + when "category_games" + selected = CategoryGame.all + args.each do |x| + x = x.split("=") + case x[0] + when "category_id" + if (is_a_integer(x[1])) + selected = selected.select {|delete| delete.category_id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + when "game_id" + if (is_a_integer(x[1])) + selected = selected.select {|delete| delete.category_id == x[1].to_i} + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true; + end + if error + break + end + next + end + else + puts "Tabela #{tabela} não encontrada." + end + return selected +end - when "categories_games" +def exclui(tabela, args) + selected = select_rows(tabela,args) + if selected.length > 0 + selected.each do |d| + d.destroy + end + end + puts "#{selected.length} linha(s) deletada(s) da tabela #{tabela}!" +end - else - puts "Tabela #{tabela} não encontrada." - end +def altera(tabela, args) + error = false + case tabela + when "developers" + selected = select_rows(tabela, args[0..0]) + args[1..args.length-1].each do |x| + x = x.split("=") + selected.each do |dev| + case x[0] + when "name" + if is_a_string(x[1]) + dev.name = x[1].tr('"',''); + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "country" + if is_a_string(x[1]) + dev.country = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + else + dev.save + end + end + next + end + if !error + puts "#{selected.length} linha(s) atualizada(s) na tabela #{tabela}!" + end + when "games" + selected = select_rows(tabela, args[0..0]) + args[1..args.length-1].each do |x| + x = x.split("=") + selected.each do |game| + case x[0] + when "name" + if is_a_string(x[1]) + game.name = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "description" + if is_a_string(x[1]) + game.description = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "is_released" + if x[1] === "true" || x[1] === "false" + game.is_released = x[1] === "true" ? true : false + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "developer_id" + if is_a_integer(x[1]) + game.developer_id = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + else + game.save + end + end + next + end + if !error + puts "#{selected.length} linha(s) atualizada(s) na tabela #{tabela}!" + end + when "prices" + selected = select_rows(tabela, args[0..0]) + args[1..args.length-1].each do |x| + x = x.split("=") + selected.each do |price| + case x[0] + when "price_us" + if is_a_integer(x[1]) + price.price_us = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "price_br" + if is_a_integer(x[1]) + price.price_br = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "price_ru" + if is_a_integer(x[1]) + price.price_ru = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "game_id" + if is_a_integer(x[1]) + price.game_id = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + else + price.save + end + end + next + end + if !error + puts "#{selected.length} linha(s) atualizada(s) na tabela #{tabela}!" + end + when "categories" + selected = select_rows(tabela, args[0..0]) + args[1..args.length-1].each do |x| + x = x.split("=") + selected.each do |category| + case x[0] + when "name" + if is_a_string(x[1]) + category.name = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "description" + if is_a_string(x[1]) + category.description = x[1].tr('"','') + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + else + category.save + end + end + next + end + if !error + puts "#{selected.length} linha(s) atualizada(s) na tabela #{tabela}!" + end + when "category_games" + selected = select_rows(tabela, args[0..0]) + args[1..args.length-1].each do |x| + x = x.split("=") + selected.each do |game| + case x[0] + when "category_id" + if is_a_integer(x[1]) + category_game.category_id = x[1]; + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + when "game_id" + if is_a_integer(x[1]) + category_game.game_id = x[1] + else + puts "Erro de SÃntaxe: Valor inválido para #{x[0]}!" + error = true + end + else + puts "Atributo #{x[0]} não encontrado." + error = true + end + if error + break + else + category_game.save + end + end + next + end + if !error + puts "#{selected.length} linha(s) atualizada(s) na tabela #{tabela}!" + end + else + puts "Tabela #{tabela} não encontrada." + end end def lista(tabela) - case tabela - when "developers" - lista = Developer.all - lista.each do |l| - puts "#{l.id}|#{l.name}|#{l.country}" - end - when "games" - lista = Game.all - lista.each do |l| - puts "#{l.id}|#{l.name}|#{l.description}|#{l.is_released}|#{l.developer_id}|#{l.price_id}" - end - when "prices" - lista = Price.all - lista.each do |l| - puts "#{l.id}|#{l.price_us}|#{l.price_br}|#{l.price_ru}|#{l.game_id}" - end - when "categories" - lista = Category.all - lista.each do |l| - puts "#{l.id}|#{l.name}|#{l.description}" - end - when "categories_games" - lista = CategoryGame.all - lista.each do |l| - puts "#{l.id}|#{l.category_id}|#{l.game_id}" - end - else - puts "Tabela #{tabela} não encontrada." - end - if (tabela) - puts "Tabela #{tabela} listada com sucesso!" - end + error = false + case tabela + when "developers" + lista = Developer.all + puts "id|name|country" + lista.each do |l| + puts "#{l.id}|#{l.name}|#{l.country}" + end + when "games" + lista = Game.all + puts "id|name|description|is_released|developer_id" + lista.each do |l| + puts "#{l.id}|#{l.name}|#{l.description}|#{l.is_released}|#{l.developer_id}" + end + when "prices" + lista = Price.all + puts "id|price_us|price_br|price_ru|game_id" + lista.each do |l| + puts "#{l.id}|#{l.price_us}|#{l.price_br}|#{l.price_ru}|#{l.game_id}" + end + when "categories" + lista = Category.all + puts "id|name|description" + lista.each do |l| + puts "#{l.id}|#{l.name}|#{l.description}" + end + when "category_games" + lista = CategoryGame.all + puts "category_id|game_id" + lista.each do |l| + puts "#{l.category_id}|#{l.game_id}" + end + else + puts "Tabela #{tabela} não encontrada." + error = true + end + if !error + puts "Tabela #{tabela} listada com sucesso!" + end end puts "Olá! Seja bem vindo ao SteamDB!" while true do - args = gets.split(" ") - - case args[0] - when "insere" - insere(args[1],args[2..args.length-1]) - when "exclui" - exclui(args[1],args[2..args.length-1]) - when "altera" - altera(args[1],args[2..args.length-1]) - when "lista" - lista(args[1]) - when "sair" - exit() - else - puts "Comando não encontrado." - end + args = parse_input(gets.tr("\n","")) + if args.length > 0 + case args[0] + when "insere" + if args.length > 2 + insere(args[1],args[2..args.length-1]) + else + puts "Erro: não há parâmetros o suficiente para inserir um novo elemento." + end + when "exclui" + if args.length > 1 + exclui(args[1],args[2..args.length-1]) + else + puts "Erro: não há parâmetros o suficiente para excluir um elemento." + end + when "altera" + if args.length > 3 + altera(args[1],args[2..args.length-1]) + else + puts "Erro: não há parâmetros o suficiente para atualizar a tabela." + end + when "lista" + if args.length == 2 + lista(args[1]) + else + puts "Erro: número inválido de parâmetros." + end + when "sair" + puts "Tchau! :)" + exit() + else + puts "Comando não encontrado." + end + end end - - -# 1 x n = 1 usuário tendo vários jogos -# 1 x 1 = 1 jogo só tem 1 tabela de preços (preços por paÃs) -# n x n = vários jogos tem várias categorias \ No newline at end of file diff --git a/T2/steamdb.sqlite3 b/T2/steamdb.sqlite3 deleted file mode 100644 index f6000c4ac7286d8adc503aa895177246f179825f..0000000000000000000000000000000000000000 Binary files a/T2/steamdb.sqlite3 and /dev/null differ diff --git a/T3/canvas.css b/T3/canvas.css new file mode 100644 index 0000000000000000000000000000000000000000..cb27467182800223b23cf42f7f5a3482e08fbc7b --- /dev/null +++ b/T3/canvas.css @@ -0,0 +1,25 @@ +* { + margin:0; + padding:0; +} + +html, body { + width: 100%; +} + +canvas { + display:block; + height: 100%; + width: 100%; +} + +div { + position: absolute; + left: 10px; + top: 10px; + width: 300px; +} + +#number { + width: 50px; +} \ No newline at end of file diff --git a/T3/index.html b/T3/index.html new file mode 100644 index 0000000000000000000000000000000000000000..4e989f4a2187a721c78751beda894131e46393f9 --- /dev/null +++ b/T3/index.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <link rel="stylesheet" href="canvas.css"> + </head> + <body> + <canvas id="canvas"> + Your browser does not support the HTML5 canvas tag. + </canvas> + <div> + <h3> Gerador de PolÃgonos </h3> + Informe um número de 3 a 8: + <input type="number" id="number" step="1" min="3" max="8" value="3" required/> + <input type="submit" onclick="generatePolygon()" value="Gerar"/> + <span class="validity"></span> + </div> + </body> + + <script type="text/javascript" src="lines.js"></script> +</html> diff --git a/T3/lines.js b/T3/lines.js new file mode 100644 index 0000000000000000000000000000000000000000..f01aeae5dc8ecdd2b1981a733ce3a9afa7a89e93 --- /dev/null +++ b/T3/lines.js @@ -0,0 +1,245 @@ +class Line { + constructor(x0,y0,xf,yf) { + this.x0 = x0; + this.y0 = y0; + this.xf = xf; + this.yf = yf; + this.width = Math.abs(xf - x0); + this.height = Math.abs(yf - y0); + if (this.x0 < this.xf) + this.centerX = x0 + this.width/2; + else + this.centerX = xf + this.width/2; + if (this.y0 < this.yf) + this.centerY = y0 + this.height/2; + else + this.centerY = yf + this.height/2; + } +} + +var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var width = window.innerWidth; +var height = window.innerHeight; +var centerX = width / 2; +var centerY = height / 2; + +var mouseX = 0; +var mouseY = 0; +var mouseDown = 0; +var rightClick = 0; + +var lines = []; +lines[0] = new Line(centerX-200,centerY,centerX+200,centerY); +var selectedLine = null; +var movingEntireLine = false; +var draggingFirstEnd = false; +var draggingSecondEnd = false; + +canvas.width = width; +canvas.height = height; +canvas.style.background = "#333"; +document.body.style.color = "#fff"; +ctx.strokeStyle = "#fff"; + +//event listeners +window.addEventListener('resize', resizeCanvas, false); +window.addEventListener('mousedown', handleMouseDown, false); +window.addEventListener('mouseup', handleMouseUp, false); +document.addEventListener("contextmenu", function(e){ + e.preventDefault(); +}, false); +onmousemove = function(e){ + mouseX = e.clientX; + mouseY = e.clientY; +} + +//event handlers +function resizeCanvas() { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + width = window.innerWidth; + height = window.innerHeight; + centerX = width / 2; + centerY = height / 2; + drawCurrentCanvas(); +} + +function handleMouseDown(e) { + rightClick = e.button == 2?1:0; + if (!rightClick) mouseDown = 1; +} + +function handleMouseUp() { + mouseDown = 0; + rightClick = 0; + selectedLine = null; + movingEntireLine = false; + draggingFirstEnd = false; + draggingSecondEnd = false; +} + +function dragLine() { + if (selectedLine != null) { + if (movingEntireLine) { + if (lines[selectedLine].x0 <= lines[selectedLine].xf) { + lines[selectedLine].x0 = mouseX-(lines[selectedLine].width/2); + lines[selectedLine].xf = mouseX+(lines[selectedLine].width/2); + } else { + lines[selectedLine].xf = mouseX-(lines[selectedLine].width/2); + lines[selectedLine].x0 = mouseX+(lines[selectedLine].width/2); + } + if (lines[selectedLine].y0 <= lines[selectedLine].yf) { + lines[selectedLine].y0 = mouseY-(lines[selectedLine].height/2); + lines[selectedLine].yf = mouseY+(lines[selectedLine].height/2); + } else { + lines[selectedLine].yf = mouseY-(lines[selectedLine].height/2); + lines[selectedLine].y0 = mouseY+(lines[selectedLine].height/2); + } + if (lines[selectedLine].x0 <= lines[selectedLine].xf) { + lines[selectedLine].centerX = lines[selectedLine].x0 + lines[selectedLine].width/2; + } else { + lines[selectedLine].centerX = lines[selectedLine].xf + lines[selectedLine].width/2; + } + if (lines[selectedLine].y0 <= lines[selectedLine].yf) { + lines[selectedLine].centerY = lines[selectedLine].y0 + lines[selectedLine].height/2; + } else { + lines[selectedLine].centerY = lines[selectedLine].yf + lines[selectedLine].height/2; + } + } else if (draggingFirstEnd) { + lines[selectedLine].x0 = mouseX; + lines[selectedLine].y0 = mouseY; + lines[selectedLine].width = Math.abs(lines[selectedLine].xf - lines[selectedLine].x0); + lines[selectedLine].height = Math.abs(lines[selectedLine].yf - lines[selectedLine].y0); + if (lines[selectedLine].x0 <= lines[selectedLine].xf) { + lines[selectedLine].centerX = lines[selectedLine].x0 + lines[selectedLine].width/2; + } else { + lines[selectedLine].centerX = lines[selectedLine].xf + lines[selectedLine].width/2; + } + if (lines[selectedLine].y0 <= lines[selectedLine].yf) { + lines[selectedLine].centerY = lines[selectedLine].y0 + lines[selectedLine].height/2; + } else { + lines[selectedLine].centerY = lines[selectedLine].yf + lines[selectedLine].height/2; + } + } else if (draggingSecondEnd) { + lines[selectedLine].xf = mouseX; + lines[selectedLine].yf = mouseY; + lines[selectedLine].width = Math.abs(lines[selectedLine].xf - lines[selectedLine].x0); + lines[selectedLine].height = Math.abs(lines[selectedLine].yf - lines[selectedLine].y0); + if (lines[selectedLine].x0 <= lines[selectedLine].xf) { + lines[selectedLine].centerX = lines[selectedLine].x0 + lines[selectedLine].width/2; + } else { + lines[selectedLine].centerX = lines[selectedLine].xf + lines[selectedLine].width/2; + } + if (lines[selectedLine].y0 <= lines[selectedLine].yf) { + lines[selectedLine].centerY = lines[selectedLine].y0 + lines[selectedLine].height/2; + } else { + lines[selectedLine].centerY = lines[selectedLine].yf + lines[selectedLine].height/2; + } + } + } +} + +function handleMouse() { + if (mouseDown && selectedLine == null) { + for (var i = lines.length - 1; i >= 0; i--) { + if (mouseX >= lines[i].centerX - 10 && mouseX <= lines[i].centerX + 10 && mouseY >= lines[i].centerY - 10 && mouseY <= lines[i].centerY + 10) { + selectedLine = i; + movingEntireLine = true; + break; + } else if (mouseX >= lines[i].x0 - 20 && mouseX <= lines[i].x0 + 20 && + mouseY >= lines[i].y0 - 20 && mouseY <= lines[i].y0 + 20) { + selectedLine = i; + draggingFirstEnd = true; + break; + } else if (mouseX >= lines[i].xf - 20 && mouseX <= lines[i].xf + 20 + && mouseY >= lines[i].yf - 20 && mouseY <= lines[i].yf + 20) { + selectedLine = i; + draggingSecondEnd = true; + break; + } + } + } else if (rightClick) { + for (var i = lines.length - 1; i >= 0; i--) { + if ((mouseY >= lines[i].y0 && mouseY <= lines[i].yf) || (mouseY >= lines[i].yf && mouseY <= lines[i].y0)) { + if (mouseX >= lines[i].x0 && mouseX <= lines[i].xf) { + lines[lines.length] = new Line(mouseX,mouseY,lines[i].xf,lines[i].yf); + lines[i].xf = mouseX; + lines[i].yf = mouseY; + lines[i].width = Math.abs(lines[i].xf - lines[i].x0); + lines[i].height = Math.abs(lines[i].yf - lines[i].y0); + lines[i].centerX = lines[i].x0 + lines[i].width/2; + lines[i].centerY = lines[i].y0 + lines[i].height/2; + rightClick = 0; + break; + } else if (mouseX <= lines[i].x0 && mouseX >= lines[i].xf) { + lines[lines.length] = new Line(mouseX,mouseY,lines[i].x0,lines[i].y0); + lines[i].x0 = mouseX; + lines[i].y0 = mouseY; + lines[i].width = Math.abs(lines[i].xf - lines[i].x0); + lines[i].height = Math.abs(lines[i].yf - lines[i].y0); + lines[i].centerX = lines[i].xf + lines[i].width/2; + lines[i].centerY = lines[i].yf + lines[i].height/2; + rightClick = 0; + break; + } + } + } + } +} + +function generatePolygon() { + edges = parseInt(document.getElementById("number").value,10); + if (edges >= 3 && edges <= 8) { + lines = []; + var tmpx0 = centerX + 300; + var tmpy0 = centerY; + + var edge = (2 * Math.PI)/edges; + for (var i = 0; i < edges; i++) { + var angle = edge * (i+1); + var tmpxf = 300 * Math.cos(angle) + centerX; + var tmpyf = 300 * Math.sin(angle) + centerY; + lines[i] = new Line(tmpx0, tmpy0, tmpxf,tmpyf); + tmpx0 = tmpxf; + tmpy0 = tmpyf; + } + drawCurrentCanvas(); + } else { + alert("Valor inválido! O número de arestas deve estar no intervalo de [3..8].") + } +} + +//function that updates screen +function drawCurrentCanvas() { + drawLines(); + if ((mouseDown && selectedLine == null) || rightClick) handleMouse(); + dragLine(); + requestAnimationFrame(drawCurrentCanvas); +} + +//function that draws all existing lines +function drawLines() { + ctx.clearRect(0,0,canvas.width,canvas.height); + for (var i = lines.length - 1; i >= 0; i--) { + drawLine(lines[i].x0,lines[i].y0,lines[i].xf,lines[i].yf, i); + } +} + +//function that draws a line +function drawLine(x0,y0,xf,yf,i) { + ctx.beginPath(); + ctx.lineWidth = 3; + ctx.moveTo(x0,y0); + ctx.lineTo(xf,yf); + if (selectedLine == i) ctx.strokeStyle = "red"; + else ctx.strokeStyle = "#fff"; + ctx.stroke(); + lineX0 = x0; + lineY0 = y0; + lineXf = xf; + lineYf = yf; +} + +//start +drawCurrentCanvas(); \ No newline at end of file