diff --git a/.gitignore b/.gitignore
index ca8c327d..1be6c9d9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,11 @@
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
+# Docker related files
+Dockerfile
+docker-compose.yml
+entrypoint.sh
+
### RubyMine Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
@@ -64,4 +69,4 @@
# .idea/misc.xml
# *.ipr
-# End of https://www.gitignore.io/api/ruby,rails,rubymine
\ No newline at end of file
+# End of https://www.gitignore.io/api/ruby,rails,rubymine
diff --git a/Gemfile b/Gemfile
index bfc41880..576a878b 100644
--- a/Gemfile
+++ b/Gemfile
@@ -27,7 +27,6 @@ gem 'jbuilder', '~> 2.5'
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
-gem 'webdrivers', '~> 4.0'
# Uses HAML templates
gem 'haml'
@@ -56,6 +55,8 @@ gem 'nokogiri'
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
+ gem 'rubycritic'
+ gem 'rdoc'
end
# Uses railroady gem
group :development, :test do
diff --git a/Gemfile.lock b/Gemfile.lock
index c2dba9cb..9b3bacbb 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -20,48 +20,43 @@ GIT
GEM
remote: https://rubygems.org/
specs:
-
- abstract_type (0.0.7)
- actioncable (5.2.4)
- actionpack (= 5.2.4)
+ actioncable (5.2.5)
+ actionpack (= 5.2.5)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailer (5.2.4)
- actionpack (= 5.2.4)
- actionview (= 5.2.4)
- activejob (= 5.2.4)
+ actionmailer (5.2.5)
+ actionpack (= 5.2.5)
+ actionview (= 5.2.5)
+ activejob (= 5.2.5)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.2.4)
- actionview (= 5.2.4)
- activesupport (= 5.2.4)
- rack (~> 2.0)
+ actionpack (5.2.5)
+ actionview (= 5.2.5)
+ activesupport (= 5.2.5)
+ rack (~> 2.0, >= 2.0.8)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.2.4)
- activesupport (= 5.2.4)
-
+ actionview (5.2.5)
+ activesupport (= 5.2.5)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
-
- activejob (5.2.4)
- activesupport (= 5.2.4)
+ activejob (5.2.5)
+ activesupport (= 5.2.5)
globalid (>= 0.3.6)
- activemodel (5.2.4)
- activesupport (= 5.2.4)
- activerecord (5.2.4)
- activemodel (= 5.2.4)
- activesupport (= 5.2.4)
+ activemodel (5.2.5)
+ activesupport (= 5.2.5)
+ activerecord (5.2.5)
+ activemodel (= 5.2.5)
+ activesupport (= 5.2.5)
arel (>= 9.0)
- activestorage (5.2.4)
- actionpack (= 5.2.4)
- activerecord (= 5.2.4)
- marcel (~> 0.3.1)
- activesupport (5.2.4)
-
+ activestorage (5.2.5)
+ actionpack (= 5.2.5)
+ activerecord (= 5.2.5)
+ marcel (~> 1.0.0)
+ activesupport (5.2.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -70,11 +65,13 @@ GEM
public_suffix (>= 2.0.2, < 5.0)
arel (9.0.0)
arrayfields (4.9.2)
-
ast (2.4.2)
autoprefixer-rails (10.2.4.0)
-
execjs
+ axiom-types (0.1.1)
+ descendants_tracker (~> 0.0.4)
+ ice_nine (~> 0.11.0)
+ thread_safe (~> 0.3, >= 0.3.1)
bcrypt (3.1.16)
bindex (0.8.1)
bootsnap (1.7.3)
@@ -107,6 +104,8 @@ GEM
sexp_processor
code_metrics (0.1.3)
coderay (1.1.3)
+ coercible (1.0.0)
+ descendants_tracker (~> 0.0.1)
coffee-rails (4.2.2)
coffee-script (>= 2.2.0)
railties (>= 4.0.0)
@@ -114,7 +113,6 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
-
concurrent-ruby (1.1.8)
crass (1.0.6)
cucumber (5.3.0)
@@ -147,7 +145,6 @@ GEM
capybara (>= 2.18, < 4)
cucumber (>= 3.0.2, < 6)
mime-types (~> 3.2)
-
nokogiri (~> 1.8)
rails (>= 5.0, < 7)
cucumber-rails-training-wheels (1.0.0)
@@ -163,8 +160,11 @@ GEM
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
+ descendants_tracker (0.0.4)
+ thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.4.4)
docile (1.3.5)
+ equalizer (0.0.11)
erubi (1.10.0)
erubis (2.7.0)
execjs (2.7.0)
@@ -174,9 +174,7 @@ GEM
factory_bot (~> 6.1.0)
railties (>= 5.0.0)
fattr (2.4.0)
-
ffi (1.15.0)
-
flay (2.12.1)
erubis (~> 2.7.0)
path_expander (~> 1.0)
@@ -189,9 +187,7 @@ GEM
formatador (0.2.5)
globalid (0.4.2)
activesupport (>= 4.2.0)
-
guard (2.16.2)
-
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0)
@@ -215,22 +211,17 @@ GEM
html2haml (>= 1.0.1)
railties (>= 5.1)
hirb (0.7.3)
-
html2haml (2.2.0)
erubis (~> 2.7.0)
haml (>= 4.0, < 6)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
- http-accept (1.7.0)
- http-cookie (1.0.3)
- domain_name (~> 0.5)
- i18n (1.7.0)
+ i18n (1.8.9)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
- jbuilder (2.9.1)
- activesupport (>= 4.2.0)
- jquery-rails (4.3.5)
-
+ jbuilder (2.11.2)
+ activesupport (>= 5.0.0)
+ jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
@@ -242,9 +233,7 @@ GEM
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
-
loofah (2.9.0)
-
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
lumberjack (1.2.8)
@@ -256,36 +245,30 @@ GEM
fattr (~> 2.2, >= 2.2.0)
map (~> 6.1, >= 6.1.0)
map (6.6.0)
- marcel (0.3.3)
- mimemagic (~> 0.3.2)
+ marcel (1.0.0)
method_source (1.0.0)
metric_fu-Saikuro (1.1.3)
middleware (0.1.0)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2021.0225)
- mimemagic (0.3.6)
- mini_mime (1.0.2)
-
-
- mini_portile2 (2.4.0)
- minitest (5.13.0)
- msgpack (1.3.1)
- multi_json (1.14.1)
-
+ mini_mime (1.0.3)
+ mini_portile2 (2.5.0)
+ minitest (5.14.4)
+ msgpack (1.4.2)
+ multi_json (1.15.0)
multi_test (0.1.2)
nenv (0.3.0)
- netrc (0.11.0)
- nio4r (2.5.2)
- nokogiri (1.10.7)
- mini_portile2 (~> 2.4.0)
+ nio4r (2.5.7)
+ nokogiri (1.11.2)
+ mini_portile2 (~> 2.5.0)
+ racc (~> 1.4)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
- parallel (1.19.1)
- parser (2.5.3.0)
- ast (~> 2.4.0)
-
+ parallel (1.20.1)
+ parser (3.0.0.0)
+ ast (~> 2.4.1)
path_expander (1.1.0)
pg (1.2.3)
popper_js (1.16.0)
@@ -305,20 +288,18 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
railroady (1.5.3)
-
- rails (5.2.4.5)
- actioncable (= 5.2.4.5)
- actionmailer (= 5.2.4.5)
- actionpack (= 5.2.4.5)
- actionview (= 5.2.4.5)
- activejob (= 5.2.4.5)
- activemodel (= 5.2.4.5)
- activerecord (= 5.2.4.5)
- activestorage (= 5.2.4.5)
- activesupport (= 5.2.4.5)
+ rails (5.2.5)
+ actioncable (= 5.2.5)
+ actionmailer (= 5.2.5)
+ actionpack (= 5.2.5)
+ actionview (= 5.2.5)
+ activejob (= 5.2.5)
+ activemodel (= 5.2.5)
+ activerecord (= 5.2.5)
+ activestorage (= 5.2.5)
+ activesupport (= 5.2.5)
bundler (>= 1.3.0)
- railties (= 5.2.4.5)
-
+ railties (= 5.2.5)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@@ -337,10 +318,9 @@ GEM
json
require_all (~> 3.0)
ruby-progressbar
-
- railties (5.2.4.5)
- actionpack (= 5.2.4.5)
- activesupport (= 5.2.4.5)
+ railties (5.2.5)
+ actionpack (= 5.2.5)
+ activesupport (= 5.2.5)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
@@ -348,8 +328,8 @@ GEM
rake (13.0.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
-
ffi (~> 1.0)
+ rdoc (6.3.1)
redcard (1.1.0)
reek (6.0.3)
kwalify (~> 0.7.0)
@@ -383,10 +363,19 @@ GEM
rspec-support (3.10.2)
ruby-progressbar (1.11.0)
ruby_dep (1.5.0)
-
ruby_parser (3.15.1)
-
sexp_processor (~> 4.9)
+ rubycritic (4.6.1)
+ flay (~> 2.8)
+ flog (~> 4.4)
+ launchy (>= 2.0.0)
+ parser (>= 2.6.0)
+ rainbow (~> 3.0)
+ reek (~> 6.0, < 7.0)
+ ruby_parser (~> 3.8)
+ simplecov (>= 0.17.0)
+ tty-which (~> 0.4.0)
+ virtus (~> 1.0)
rubyzip (2.3.0)
sass (3.7.4)
sass-listen (~> 4.0.0)
@@ -435,6 +424,7 @@ GEM
thor (1.1.0)
thread_safe (0.3.6)
tilt (2.0.10)
+ tty-which (0.4.2)
turbolinks (5.2.1)
turbolinks-source (~> 5.2)
turbolinks-source (5.2.0)
@@ -442,27 +432,28 @@ GEM
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
+ virtus (1.0.5)
+ axiom-types (~> 0.1)
+ coercible (~> 1.0)
+ descendants_tracker (~> 0.0, >= 0.0.3)
+ equalizer (~> 0.0, >= 0.0.9)
web-console (3.7.0)
actionview (>= 5.0)
activemodel (>= 5.0)
bindex (>= 0.4.0)
railties (>= 5.0)
-
-
- webdrivers (4.1.3)
+ webdrivers (4.6.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
- websocket-driver (0.7.1)
-
-
+ websocket-driver (0.7.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
PLATFORMS
- x86_64-linux
+ ruby
DEPENDENCIES
bcrypt (~> 3.1.7)
@@ -489,7 +480,9 @@ DEPENDENCIES
railroady
rails (~> 5.2.0)
rails-controller-testing
+ rdoc
rspec-rails
+ rubycritic
sass-rails (~> 5.0)
selenium-webdriver
simplecov
@@ -499,12 +492,10 @@ DEPENDENCIES
tzinfo-data
uglifier (>= 1.3.0)
web-console (>= 3.3.0)
-
- webdrivers (~> 4.0)
-
+ webdrivers
RUBY VERSION
ruby 2.7.2p137
BUNDLED WITH
- 2.2.9
+ 2.1.4
diff --git a/Grupo_01_Sprint_01.md b/Grupo_01_Sprint_01.md
new file mode 100644
index 00000000..1e426990
--- /dev/null
+++ b/Grupo_01_Sprint_01.md
@@ -0,0 +1,24 @@
+# Engenharia de Software 2020/2 - Grupo 01
+# Sprint #1
+
+## Integrantes
+* **Scrum master:** João Moraes (@joaoadm94)
+* **Product Owner:** Marco Antônio (@masathayde)
+* **Equipe de desenvolvimento:** Daniel Carvalho (@danielc-957), Rafael Barbosa de Sousa (@rafaelbarbosas)
+
+## Funcionalidade principal
+* Realizar scraping dos dados presentes no HTML gerado pelo SIGAA (turmas, professores responsáveis).
+
+## User stories
+1. Exibir uma lista de disciplinas importada do site SIGAA
+1. Filtrar lista de disciplinas importadas do site de matrícula
+1. Adicionar disciplinas importadas do site de matrícula ao banco de dados
+1. Adicionar todas as disciplinas importadas do site de matrícula ao banco de dados
+1. Inverter marcação das caixas na página de importação de disciplinas
+1. Importar uma lista de professores importada do site SIGAA
+
+## Política de branching
+Feature branching.
+
+## Mudanças
+Foram criadas 6 user stories iniciais.
\ No newline at end of file
diff --git a/app/controllers/concerns/turmas_parser.rb b/app/controllers/concerns/turmas_parser.rb
new file mode 100644
index 00000000..4a0e044d
--- /dev/null
+++ b/app/controllers/concerns/turmas_parser.rb
@@ -0,0 +1,103 @@
+# controllers/concerns/turmas_parser.rb
+
+##
+# Implementa funções dedicadas à extração de dados de turmas de um arquivo importado.
+# Este módulo serve apenas para uma formatação específica. Se o formato do arquivo for alterado, o módulo também deve ser.
+module TurmasParser
+ extend ActiveSupport::Concern
+
+ ##
+ # Usa funções da gema Nokogiri para separar o arquivo html em +file+ em blocos
+ # menores, em cada qual deve estar contida informação sobre uma única turma.
+ # Retorna uma lista de tais blocos.
+ def parsear_arquivo_de_turmas (file)
+ doc_to_parse = Nokogiri::HTML(file.read, nil, 'UTF-8') do |config|
+ config.recover
+ end
+ blocos_de_turma_html = doc_to_parse.xpath(
+ '//table[tr[@class="componentescur"]]') # Separa o html em blocos da table pai do tr de classe 'componentescur'
+ return blocos_de_turma_html
+ end
+
+ ##
+ # Retorna o primeiro casamento de texto encontrado no +bloco+, utilizando o parâmetro +regex+ passado.
+ def extrair_texto_de_bloco (bloco, regex)
+ return bloco.to_s.match(/#{regex}/)[1]
+ end
+
+ ##
+ # Recebe um bloco html em +info_turma+, subdivide-o e extrai informações referentes a uma disciplina,
+ # utilizando casamento de regex específicos. Para isso, utiliza-se a função +extrair_texto_de_bloco+.
+ # Retorna uma hash com as informações.
+ def extrair_info_de_disciplina (info_turma)
+ info = Hash.new()
+ info_disciplina = info_turma.at_css('tr.componentescur').css('td')
+ info[:disciplina] = extrair_texto_de_bloco(info_disciplina[0], '^\s+\S+ - (.+)+ -')
+ info[:cod_disciplina] = extrair_texto_de_bloco(info_disciplina[0], '^\s+CIC(\S+) -').to_i
+ info[:codigo_turma] = extrair_texto_de_bloco(info_disciplina[1], '^\s+(\S+)\s')
+ info[:situacao] = extrair_texto_de_bloco(info_disciplina[2], '
\s+(.+?)\s+<\/td>')
+ return info
+ end
+
+ ##
+ # Recebe um bloco html em +info_professor+, utiliza o padrão +regex+ passado para realizar casamento.
+ # Caso haja casamento, retorna a primeira instância. Caso não, retorna um objeto nil.
+ def buscar_nome_do_professor (info_professor, regex)
+ professor = info_professor[0].css('i').to_s.match(/#{regex}/)
+ if (professor != nil)
+ professor = professor[1] # Caso haja match, usamos a senteça que causou o primeiro match, a qual fica no índice 1 do objeto MatchData.
+ end
+ return professor
+ end
+
+ ##
+ # Recebe um bloco html em +info_turma+, utiliza a função +buscar_nome_do_professor+ para extrair informações.
+ # Retorna uma hash com as informações.
+ def extrair_info_de_professor (info_turma)
+ info = Hash.new()
+ info_professor = info_turma.at_css('tr.componentescur').next_element.css('td') # Pulamos as quatro primeiras rows na tabela
+ info[:prof_principal] = buscar_nome_do_professor(info_professor, '(.+?) \(.+\)')
+ info[:prof_auxiliar] = buscar_nome_do_professor(info_professor, ' (.+?) \(.+\)')
+ info[:reserva] = info_professor[1].css('i').to_s.match(/?(.+?)\/?<\/i>/)[1]
+ #turma[:prof_auxiliar] = infoProfessor[0].css('i').to_s.match(/ (.+?) \(.+\)/) # Espera-se que seja = nil se houver só um professor
+ return info
+ end
+
+ ##
+ # Recebe uma lista de blocos, +blocos_de_turma+, contendo informações de turmas individuais. Com ajuda de subfunções de extração,
+ # retira informações de cada turma, coloca-as em hashes, os quais iram compor uma lista de hashes para cada turma.
+ # Retorna essa lista.
+ def extrair_info_de_todas_turmas (blocos_de_turma)
+ lista_de_turmas = Array.new()
+ blocos_de_turma.each do |bloco|
+ turma = Hash.new()
+ turma.merge!(extrair_info_de_disciplina(bloco))
+ turma.merge!(extrair_info_de_professor(bloco))
+ lista_de_turmas.append(turma)
+ end
+ return lista_de_turmas
+ end
+
+ ##
+ # Recebe um arquivo html como entrada. Executa parsing e extrai informações de todas as turmas, cada em um hash.
+ # Retorna uma lista de tais hashes.
+ def gerar_lista_de_turmas_a_partir_de_arquivo (uploaded_file)
+ blocos_de_turma_html = parsear_arquivo_de_turmas(uploaded_file)
+ lista_de_turmas = extrair_info_de_todas_turmas(blocos_de_turma_html)
+ return lista_de_turmas
+ end
+
+ ##
+ # Adiciona ao banco de dados registros de professores, disciplinas, e turmas, a partir de dados de turmas individuais
+ # contidos na lista de hashes de entrada. Para isso, chama funções especiais dos modelos Professor, Disciplina, e Turma,
+ # as quais usam valores derivados para campos ausentes.
+ def criar_registros_a_partir_de_info_importada(lista_de_turmas)
+ lista_de_turmas.each do |hash|
+ Professor.criar_professor_com_valores_padroes(hash[:prof_principal])
+ Professor.criar_professor_com_valores_padroes(hash[:prof_auxiliar])
+ Disciplina.criar_disciplina_com_valores_padroes(hash)
+ Turma.criar_turma_a_partir_de_parametros(hash)
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 9f93d455..865d188d 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -1,6 +1,6 @@
class DashboardController < ApplicationController
+ include TurmasParser
before_action :user_logged
-
def index; end
def edit_user
@@ -92,13 +92,21 @@ def importar_disciplinas
end
##
- # Método para raspar as disciplinas do site do MatrículaWeb
- # e carregá-las no modelo.
-
+ # Utiliza funções no módulo TurmaParser para interpretar um arquivo de html enviado, o qual deve
+ # conter informações sobre turmas, em formato adequado. A partir dessas informações, cria novos
+ # registros no banco de dados. Após as operações, redireciona o usuário para a página de importação
+ # de disciplinas.
def raspar_disciplinas
- disciplinas = raspar_matriculaweb_disciplinas
- carregar_disciplinas(disciplinas)
-
+ arquivo = params[:arquivo_turmas]
+ if (arquivo == nil)
+ raise "Por favor, selecionar um arquivo"
+ end
+ array_de_turmas = gerar_lista_de_turmas_a_partir_de_arquivo(arquivo)
+ criar_registros_a_partir_de_info_importada(array_de_turmas)
+ flash[:notice] = "Disciplinas importadas com sucesso!"
+ rescue StandardError => error
+ flash[:danger] = error.message
+ ensure
redirect_to dashboard_importar_disciplinas_path
end
diff --git a/app/controllers/disciplinas_controller.rb b/app/controllers/disciplinas_controller.rb
index 1631d12c..e836ffa3 100644
--- a/app/controllers/disciplinas_controller.rb
+++ b/app/controllers/disciplinas_controller.rb
@@ -20,6 +20,11 @@ def create
def edit; end
+ def show
+ @turmas = Turma.where(fk_cod_disciplina: params[:id])
+ @disciplina = params[:nome]
+ end
+
def update
if @disciplina.update disciplina_params
redirect_to dashboard_disciplinas_path, notice: "Disciplina atualizada!"
diff --git a/app/models/disciplina.rb b/app/models/disciplina.rb
index 627e62b4..5290d7bd 100644
--- a/app/models/disciplina.rb
+++ b/app/models/disciplina.rb
@@ -13,12 +13,20 @@ def self.all_disciplinas
validates_presence_of :c_teor
validates_presence_of :c_est
validates_presence_of :c_ext
+ validates_uniqueness_of :nome
+ validates_uniqueness_of :cod_disciplina
- validates :nome, format: { without: /[\d]+|['"!¹@²#³$£%¢¨¬&\*\(\)\-_\+=§`´\[\]{}\^~ªº°\?\/:;>.<,\|\\]+/, message: 'apenas letras e espaços'}
+ validates :nome, format: { without: /['"!¹@²#³$£%¢¨¬&\*\(\)\-_\+=§`´\[\]{}\^~ªº°\?\/:;>.<,\|\\]+/, message: 'apenas letras, números e espaços'}
validates :c_prat, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
validates :c_teor, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
validates :c_est, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
validates :c_ext, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
+ def self.criar_disciplina_com_valores_padroes (params)
+ Disciplina.create([{nome: params[:disciplina],
+ fk_tipo_disciplina_id: 1, c_prat: 0, c_teor: 0,
+ cod_disciplina: params[:cod_disciplina]}])
+ end
+
end
diff --git a/app/models/professor.rb b/app/models/professor.rb
index 3005ec85..b049fe4f 100644
--- a/app/models/professor.rb
+++ b/app/models/professor.rb
@@ -1,3 +1,5 @@
+# A classe Professor é responsável pelas regras de negócios relacionadas à entidade Professor.
+# Para isso realiza operações na tabela Professor no banco de dados.
class Professor < ActiveRecord::Base
has_secure_password
@@ -29,4 +31,16 @@ def self.all_roles
# Verificação da senha e confirmação de senha
validates :password, length: { in: 6..12, message: "must be between 6 and 12 characters" }, on: :create
validates :password_confirmation, length: { in: 6..12, message: "must be between 6 and 12 characters" }, on: :create
+
+ def self.criar_professor_com_valores_padroes (nome_professor)
+ if (!nome_professor.nil?)
+ nome_formatado = nome_professor.split.map(&:capitalize).join(' ') # Transforme a primeira letra de cada nome em maiúscula
+ usuario_padrao = nome_formatado.split.join('')[0...14]
+ senha_padrao = '123456abc'
+ role = 1
+ Professor.create(name: nome_formatado, email: usuario_padrao + '@unb.br', username: usuario_padrao,
+ password: senha_padrao, password_confirmation: senha_padrao, role: role)
+ end
+ end
+
end
\ No newline at end of file
diff --git a/app/models/turma.rb b/app/models/turma.rb
index eba73ce3..ea8c0fc9 100644
--- a/app/models/turma.rb
+++ b/app/models/turma.rb
@@ -1,40 +1,35 @@
+# A classe Turma é responsável pelas regras de negócios relacionadas à entidade Turma.
+# Para isso realiza operações na tabela Turma no banco de dados.
class Turma < ActiveRecord::Base
def self.qnt_bolsas
- @qnt_bolsas = []
+ qnt_bolsas = []
- for i in 1..10
- @vaga = []
- @vaga = [i.to_s, i]
- @qnt_bolsas.insert(-1, @vaga)
+ for index in 1..10
+ vaga = [index.to_s, index]
+ qnt_bolsas.insert(-1, vaga)
end
- return @qnt_bolsas
+ return qnt_bolsas
end
def self.sel_disciplinas
- @disciplinas = Disciplina.select('cod_disciplina', 'nome')
-
- @select = []
- @disciplinas.each do |disciplina|
- @atual = []
- @atual = [disciplina.nome, disciplina.cod_disciplina]
- @select.insert(-1, @atual)
+ disciplinas = Disciplina.select('cod_disciplina', 'nome')
+ select = []
+ disciplinas.each do |disciplina|
+ select.insert(-1, [disciplina.nome, disciplina.cod_disciplina])
end
-
- return @select
+ return select
end
def self.show_disciplinas
- @disciplinas = Disciplina.select('nome')
- @show = []
+ disciplinas = Disciplina.select('nome')
+ show = []
- @disciplinas.each do |disciplina|
- @atual = String.new
- @atual = disciplina.nome
- @show.insert(-1, @atual)
+ disciplinas.each do |disciplina|
+ show.insert(-1, disciplina.nome)
end
- return @show
+ return show
end
def self.sel_turmas
@@ -55,12 +50,26 @@ def self.all_turmas
validate :turma_unica
def turma_unica
- @turmas = Turma.where(fk_cod_disciplina: fk_cod_disciplina)
+ turmas = Turma.where(fk_cod_disciplina: fk_cod_disciplina)
- @turmas.each do |t|
- if t.turma == turma
+ turmas.each do |elem|
+ if elem.turma == turma
errors.add(:turma, "#{turma} não é a única para a disciplina #{Disciplina.find(fk_cod_disciplina).nome}")
end
end
end
+
+ def self.criar_turma_a_partir_de_parametros (params)
+ if (Disciplina.exists?(nome: params[:disciplina]))
+ disciplina_id = Disciplina.find_by(nome: params[:disciplina]).id
+ Turma.create([{
+ fk_cod_disciplina: disciplina_id,
+ turma: params[:codigo_turma],
+ professor: params[:prof_principal],
+ professor_aux: params[:prof_auxiliar],
+ fk_vagas_id: 1
+ }])
+ end
+ end
+
end
\ No newline at end of file
diff --git a/app/views/dashboard/disciplinas.html.haml b/app/views/dashboard/disciplinas.html.haml
index 0cb05b2b..ffaaa154 100644
--- a/app/views/dashboard/disciplinas.html.haml
+++ b/app/views/dashboard/disciplinas.html.haml
@@ -120,9 +120,12 @@
%td=d.c_ext
- if current_user.kind_of?(Admin)
.row
- .col-6
+ .col-4
%a.btn.btn-outline-warning.btn-block{href: edit_disciplina_path(d.cod_disciplina)}
Editar Disciplina
- .col-6
+ .col-4
=link_to "Apagar Disciplina", disciplina_path(d.cod_disciplina), method: :delete,
- class: 'btn btn-outline-danger btn-block'
\ No newline at end of file
+ class: 'btn btn-outline-danger btn-block'
+ .col-4
+ %a.btn.btn-outline-primary.btn-block{href: disciplina_path(d.id)}
+ Ver Turmas
diff --git a/app/views/dashboard/importar_disciplinas.html.haml b/app/views/dashboard/importar_disciplinas.html.haml
index aaf92e0f..81763827 100644
--- a/app/views/dashboard/importar_disciplinas.html.haml
+++ b/app/views/dashboard/importar_disciplinas.html.haml
@@ -108,9 +108,14 @@
.col-4
- Clique no botão abaixo para importar a lista de disciplinas a partir do
- %a{href: 'https://matriculaweb.unb.br/graduacao/'}site do MatriculaWeb
- %hr
- = link_to "Importar disciplinas", dashboard_raspar_disciplinas_path,
- :class => "btn btn-outline-primary btn-block"
+ Envie um arquivo .HTML do site SIGAA com a lista de turmas e aperte o botão para
+ fazer importação automática
+ = form_with url: dashboard_raspar_disciplinas_path, local: true, multipart: :true do |form|
+ = form.file_field :arquivo_turmas
+ = form.submit "Importar disciplinas"
+ -# Clique no botão abaixo para importar a lista de disciplinas a partir do
+ -# %a{href: 'https://matriculaweb.unb.br/graduacao/'}site do MatriculaWeb
+ -# %hr
+ -# = link_to "Importar disciplinas", dashboard_raspar_disciplinas_path,
+ -# :class => "btn btn-outline-primary btn-block"
.col-1
\ No newline at end of file
diff --git a/app/views/disciplinas/show.html.haml b/app/views/disciplinas/show.html.haml
new file mode 100644
index 00000000..98206abf
--- /dev/null
+++ b/app/views/disciplinas/show.html.haml
@@ -0,0 +1,92 @@
+%br
+%br
+.container-fluid
+ .row
+ %nav.col-md-2.d-none.d-md-block.bg-light.sidebar{style: 'margin-top: 40px'}
+ .sidebar-sticky
+ %ul.nav.flex-column
+ %li.nav-item
+ %a.nav-link{href: dashboard_path}
+ %span{'data-feather': "home"}
+ Dashboard
+ %span.sr-only (current)
+ -if current_user.kind_of?(Admin)
+ %li.nav-item
+ %a.nav-link.active{href: dashboard_disciplinas_path}
+ %span{'data-feather': "file"}
+ Disciplinas
+ - if current_user.kind_of?(User) || current_user.kind_of?(Professor)
+ %li.nav-item
+ %a.nav-link{href: dashboard_monitorias_path}
+ %span{'data-feather': "github"}
+ Monitoria
+
+ -if current_user.kind_of?(Professor)
+ %ul.nav.flex-column.mb-2
+ %li.nav-item
+ %a.nav-link{href: dashboard_turmas_path}
+ %span{'data-feather': "edit"}
+ Turmas
+
+ -if current_user.kind_of?(Admin)
+ %ul.nav.flex-column.mb-2
+ %li.nav-item
+ %a.nav-link{href: dashboard_apagar_alunos_path}
+ %span{'data-feather': "trash"}
+ Apagar alunos
+
+ -if current_user.kind_of?(Admin)
+ %ul.nav.flex-column.mb-2
+ %li.nav-item
+ %a.nav-link{href: dashboard_importar_professores_path}
+ %span{'data-feather': "users"}
+ Importar lista de professores
+
+ -unless current_user.kind_of?(Admin)
+ %h6.sidebar-heading.d-flex.justify-content-between.align-items-center.px-3.mt-4.mb-1.text-muted
+ Menu
+ %span do usuário
+ %a.d-flex.align-items-center.text-muted{href: "#"}
+ %span{'data-feather': "plus-circle"}
+
+ -if current_user.kind_of?(User) || current_user.kind_of?(Professor)
+ %ul.nav.flex-column.mb-2
+ %li.nav-item
+ %a.nav-link{href: dashboard_edit_user_path}
+ %span{'data-feather': "settings"}
+ Editar Perfil
+
+ -if current_user.kind_of?(User)
+ %ul.nav.flex-column.mb-2
+ %li.nav-item
+ %a.nav-link{href: dashboard_dados_bancarios_path}
+ %span{'data-feather': "dollar-sign"}
+ Dados Bancários
+
+ %main.col-md-9.ml-sm-auto.col-lg-10.px-4{role: "main"}
+ .row
+ .col-3
+ .col.text-center
+ %h1 Lista de Turmas
+ %hr
+ %p.text-center
+ %h5.card-title=@disciplina
+
+ .col-4
+
+ - if (@turmas.blank?)
+ %h5 Não há turmas cadastradas para esta disciplina
+
+ .row
+ - @turmas.each do |d|
+ .col-6
+ .card{style: 'width: 100%;'}
+ .card-body
+ %h5
+ Turma:
+ =d.turma
+ %br
+ Professor:
+ =d.professor
+ %br
+
\ No newline at end of file
diff --git a/config/database.yml b/config/database.yml
index c26fbd59..58910553 100644
--- a/config/database.yml
+++ b/config/database.yml
@@ -7,6 +7,9 @@
default: &default
adapter: postgresql
encoding: utf8
+ host: db
+ username: postgres
+ password: password
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
timeout: 5000
diff --git a/config/environments/development.rb b/config/environments/development.rb
index fbe02f55..4f986909 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -64,7 +64,7 @@
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
- config.file_watcher = ActiveSupport::EventedFileUpdateChecker
+ # config.file_watcher = ActiveSupport::EventedFileUpdateChecker
#mailcatcher setup
config.action_mailer.delivery_method = :smtp
diff --git a/config/routes.rb b/config/routes.rb
index 5c0e1204..26d7739a 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -21,6 +21,8 @@
end
resources :reset_senhas, only: [:new, :create, :edit, :update]
+ match "/turmas/show/:id", to: "turmas#show", via: 'get'
+
match "/dashboard", to: "dashboard#index", via: 'get'
match "/dashboard/edit_user", to: "dashboard#edit_user", via: 'get'
match "/dashboard/dados_bancarios", to: "dashboard#dados_bancarios", via: 'get'
@@ -32,7 +34,7 @@
match "/dashboard/apagar_alunos", to: "dashboard#apagar_alunos", via: 'get'
match "/dashboard/deletar_aluno", to: "dashboard#deletar_aluno", via: 'post'
match "/dashboard/importar_disciplinas", to: "dashboard#importar_disciplinas", via: 'get'
- match "/dashboard/raspar_disciplinas", to: "dashboard#raspar_disciplinas", via: 'get'
+ match "/dashboard/raspar_disciplinas", to: "dashboard#raspar_disciplinas", via: [:get, :post]
match "/dashboard/importar_professores", to: "dashboard#importar_professores", via: 'get'
match "/dashboard/scrape_professores", to: "dashboard#scrape_professores", via: 'get'
diff --git a/coverage/.last_run.json b/coverage/.last_run.json
index 04ed82cb..a08c57b1 100644
--- a/coverage/.last_run.json
+++ b/coverage/.last_run.json
@@ -1,7 +1,5 @@
{
"result": {
-
- "covered_percent": 12.93
-
+ "line": 27.78
}
}
diff --git a/coverage/.resultset.json b/coverage/.resultset.json
index e69de29b..f25d582f 100644
--- a/coverage/.resultset.json
+++ b/coverage/.resultset.json
@@ -0,0 +1,1843 @@
+{
+ "RSpec": {
+ "coverage": {
+ "/myapp/app/helpers/application_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/atendimentos_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/atividades_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/disciplinas_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/historico_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/home_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/motivos_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/reset_senhas_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/helpers/sessions_helper.rb": {
+ "lines": [
+ 1,
+ 1,
+ 0,
+ null,
+ null,
+ 1,
+ 2,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 4,
+ null,
+ null,
+ 1,
+ 2,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/helpers/tarefas_helper.rb": {
+ "lines": [
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/controllers/dashboard_controller.rb": {
+ "lines": [
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ 1,
+ 3,
+ 1,
+ 2,
+ 1,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 1,
+ null,
+ 1,
+ 2,
+ 2,
+ 2,
+ 2,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 2,
+ null,
+ null,
+ 1,
+ 2,
+ 2,
+ 2,
+ 3,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 8,
+ 8,
+ 1,
+ null,
+ 8,
+ null,
+ 8,
+ 6,
+ 6,
+ 6,
+ null,
+ null,
+ 6,
+ 6,
+ 6,
+ null,
+ null,
+ 6,
+ 6,
+ null,
+ 2,
+ 1,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ 8,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 4,
+ 4,
+ 1,
+ null,
+ 3,
+ 3,
+ 2,
+ null,
+ 2,
+ null,
+ 4,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 1,
+ 2,
+ 2,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 87,
+ null,
+ null,
+ 87,
+ 50,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 87,
+ null,
+ null,
+ null,
+ 1,
+ 50,
+ 50,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 50,
+ 50,
+ null,
+ null,
+ null,
+ 1,
+ 50,
+ null,
+ 0,
+ null,
+ 2,
+ null,
+ 34,
+ null,
+ 9,
+ null,
+ 4,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/controllers/application_controller.rb": {
+ "lines": [
+ 1,
+ 1,
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/controllers/concerns/turmas_parser.rb": {
+ "lines": [
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ 1,
+ 2,
+ 2,
+ null,
+ 2,
+ null,
+ 2,
+ null,
+ null,
+ 1,
+ 3656,
+ null,
+ null,
+ 1,
+ 914,
+ 914,
+ 914,
+ 914,
+ 914,
+ 914,
+ 914,
+ null,
+ null,
+ 1,
+ null,
+ 1828,
+ 1828,
+ 924,
+ null,
+ 1828,
+ null,
+ null,
+ 1,
+ 914,
+ 914,
+ 914,
+ 914,
+ 914,
+ null,
+ 914,
+ null,
+ null,
+ 1,
+ 2,
+ 2,
+ 914,
+ 914,
+ 914,
+ 914,
+ null,
+ 2,
+ null,
+ null,
+ 1,
+ 2,
+ 2,
+ 2,
+ null,
+ null,
+ 1,
+ 2,
+ 457,
+ 457,
+ 457,
+ 457,
+ null,
+ null,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/models/user.rb": {
+ "lines": [
+ 1,
+ 1,
+ 1,
+ null,
+ 1,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ null,
+ 1,
+ 1,
+ null,
+ 1,
+ 1,
+ null,
+ 1,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/models/professor.rb": {
+ "lines": [
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ 1,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ null,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 1,
+ null,
+ 1,
+ 914,
+ 462,
+ 462,
+ 462,
+ 462,
+ 462,
+ null,
+ null,
+ null,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/models/admin.rb": {
+ "lines": [
+ 1,
+ 1,
+ null,
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/models/disciplina.rb": {
+ "lines": [
+ 1,
+ 1,
+ 0,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ 1,
+ 457,
+ null,
+ null,
+ null,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/models/application_record.rb": {
+ "lines": [
+ 1,
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/models/monitoria.rb": {
+ "lines": [
+ 1,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/models/dados_bancarios.rb": {
+ "lines": [
+ 1,
+ 1,
+ null,
+ 1,
+ 1,
+ 1,
+ null,
+ 1,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 1,
+ null
+ ]
+ },
+ "/myapp/app/models/turma.rb": {
+ "lines": [
+ null,
+ null,
+ 1,
+ 1,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ 1,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ null,
+ null,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ null,
+ 1,
+ 457,
+ null,
+ 457,
+ 6078,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 457,
+ 457,
+ 457,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null
+ ]
+ },
+ "/myapp/app/channels/application_cable/channel.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/channels/application_cable/connection.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/admins_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/atendimentos_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/atividades_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/dados_bancarios_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/disciplinas_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/faq_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/historico_controller.rb": {
+ "lines": [
+ 0,
+ null,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/home_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/monitorias_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/motivos_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/professors_controller.rb": {
+ "lines": [
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/reset_senhas_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/sessions_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/sobre_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/tarefas_controller.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/turmas_controller.rb": {
+ "lines": [
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/controllers/users_controller.rb": {
+ "lines": [
+ 0,
+ null,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/jobs/application_job.rb": {
+ "lines": [
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/mailers/application_mailer.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/mailers/professor_mailer.rb": {
+ "lines": [
+ 0,
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/mailers/user_mailer.rb": {
+ "lines": [
+ 0,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/models/atendimento.rb": {
+ "lines": [
+ 0,
+ null,
+ null,
+ 0,
+ null,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ null,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/models/atividade.rb": {
+ "lines": [
+ 0,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/models/motivo.rb": {
+ "lines": [
+ 0,
+ null,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ },
+ "/myapp/app/models/tarefa.rb": {
+ "lines": [
+ 0,
+ 0,
+ 0
+ ],
+ "branches": {
+ }
+ }
+ },
+ "timestamp": 1621452870
+ }
+}
diff --git a/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc.png b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc.png
new file mode 100644
index 00000000..e1ba61a8
Binary files /dev/null and b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc.png differ
diff --git a/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc_disabled.png b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc_disabled.png
new file mode 100644
index 00000000..fb11dfe2
Binary files /dev/null and b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc_disabled.png differ
diff --git a/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_both.png b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_both.png
new file mode 100644
index 00000000..af5bc7c5
Binary files /dev/null and b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_both.png differ
diff --git a/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc.png b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc.png
new file mode 100644
index 00000000..0e156deb
Binary files /dev/null and b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc.png differ
diff --git a/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc_disabled.png b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc_disabled.png
new file mode 100644
index 00000000..c9fdd8a1
Binary files /dev/null and b/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc_disabled.png differ
diff --git a/coverage/assets/0.12.3/application.css b/coverage/assets/0.12.3/application.css
new file mode 100644
index 00000000..916699ed
--- /dev/null
+++ b/coverage/assets/0.12.3/application.css
@@ -0,0 +1 @@
+html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,code,del,dfn,em,img,q,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,dialog,figure,footer,header,hgroup,nav,section{margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline}article,aside,dialog,figure,footer,header,hgroup,nav,section{display:block}body{line-height:1.5}table{border-collapse:separate;border-spacing:0}caption,th,td{text-align:left;font-weight:normal}table,td,th{vertical-align:middle}blockquote:before,blockquote:after,q:before,q:after{content:""}blockquote,q{quotes:"" ""}a img{border:0}html{font-size:100.01%}body{font-size:82%;color:#222;background:#fff;font-family:"Helvetica Neue",Arial,Helvetica,sans-serif}h1,h2,h3,h4,h5,h6{font-weight:normal;color:#111}h1{font-size:3em;line-height:1;margin-bottom:.5em}h2{font-size:2em;margin-bottom:.75em}h3{font-size:1.5em;line-height:1;margin-bottom:1em}h4{font-size:1.2em;line-height:1.25;margin-bottom:1.25em}h5{font-size:1em;font-weight:bold;margin-bottom:1.5em}h6{font-size:1em;font-weight:bold}h1 img,h2 img,h3 img,h4 img,h5 img,h6 img{margin:0}p{margin:0 0 1.5em}p img.left{float:left;margin:1.5em 1.5em 1.5em 0;padding:0}p img.right{float:right;margin:1.5em 0 1.5em 1.5em}a:focus,a:hover{color:#000}a{color:#009;text-decoration:underline}blockquote{margin:1.5em;color:#666;font-style:italic}strong{font-weight:bold}em,dfn{font-style:italic}dfn{font-weight:bold}sup,sub{line-height:0}abbr,acronym{border-bottom:1px dotted #666}address{margin:0 0 1.5em;font-style:italic}del{color:#666}pre{margin:1.5em 0;white-space:pre}pre,code,tt{font:1em 'andale mono','lucida console',monospace;line-height:1.5}li ul,li ol{margin:0}ul,ol{margin:0 1.5em 1.5em 0;padding-left:3.333em}ul{list-style-type:disc}ol{list-style-type:decimal}dl{margin:0 0 1.5em 0}dl dt{font-weight:bold}dd{margin-left:1.5em}table{margin-bottom:1.4em;width:100%}th{font-weight:bold}thead th{background:#c3d9ff}th,td,caption{padding:4px 10px 4px 5px}tr.even td{background:#efefef}tfoot{font-style:italic}caption{background:#eee}.small{font-size:.8em;margin-bottom:1.875em;line-height:1.875em}.large{font-size:1.2em;line-height:2.5em;margin-bottom:1.25em}.hide{display:none}.quiet{color:#666}.loud{color:#000}.highlight{background:#ff0}.added{background:#060;color:#fff}.removed{background:#900;color:#fff}.first{margin-left:0;padding-left:0}.last{margin-right:0;padding-right:0}.top{margin-top:0;padding-top:0}.bottom{margin-bottom:0;padding-bottom:0}label{font-weight:bold}fieldset{padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc}legend{font-weight:bold;font-size:1.2em}input[type=text],input[type=password],input.text,input.title,textarea,select{background-color:#fff;border:1px solid #bbb}input[type=text]:focus,input[type=password]:focus,input.text:focus,input.title:focus,textarea:focus,select:focus{border-color:#666}input[type=text],input[type=password],input.text,input.title,textarea,select{margin:.5em 0}input.text,input.title{width:300px;padding:5px}input.title{font-size:1.5em}textarea{width:390px;height:250px;padding:5px}input[type=checkbox],input[type=radio],input.checkbox,input.radio{position:relative;top:.25em}form.inline{line-height:3}form.inline p{margin-bottom:0}.error,.notice,.success{padding:.8em;margin-bottom:1em;border:2px solid #ddd}.error{background:#fbe3e4;color:#8a1f11;border-color:#fbc2c4}.notice{background:#fff6bf;color:#514721;border-color:#ffd324}.success{background:#e6efc2;color:#264409;border-color:#c6d880}.error a{color:#8a1f11}.notice a{color:#514721}.success a{color:#264409}.box{padding:1.5em;margin-bottom:1.5em;background:#e5ecf9}hr{background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:0}hr.space{background:#fff;color:#fff;visibility:hidden}.clearfix:after,.container:after{content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden}.clearfix,.container{display:block}.clear{clear:both}table.dataTable{width:100%;margin:0 auto;clear:both;border-collapse:separate;border-spacing:0}table.dataTable thead th,table.dataTable tfoot th{font-weight:bold}table.dataTable thead th,table.dataTable thead td{padding:10px 18px;border-bottom:1px solid #111}table.dataTable thead th:active,table.dataTable thead td:active{outline:0}table.dataTable tfoot th,table.dataTable tfoot td{padding:10px 18px 6px 18px;border-top:1px solid #111}table.dataTable thead .sorting,table.dataTable thead .sorting_asc,table.dataTable thead .sorting_desc,table.dataTable thead .sorting_asc_disabled,table.dataTable thead .sorting_desc_disabled{cursor:pointer;*cursor:hand;background-repeat:no-repeat;background-position:center right}table.dataTable thead .sorting{background-image:url("DataTables-1.10.20/images/sort_both.png")}table.dataTable thead .sorting_asc{background-image:url("DataTables-1.10.20/images/sort_asc.png")}table.dataTable thead .sorting_desc{background-image:url("DataTables-1.10.20/images/sort_desc.png")}table.dataTable thead .sorting_asc_disabled{background-image:url("DataTables-1.10.20/images/sort_asc_disabled.png")}table.dataTable thead .sorting_desc_disabled{background-image:url("DataTables-1.10.20/images/sort_desc_disabled.png")}table.dataTable tbody tr{background-color:#fff}table.dataTable tbody tr.selected{background-color:#b0bed9}table.dataTable tbody th,table.dataTable tbody td{padding:8px 10px}table.dataTable.row-border tbody th,table.dataTable.row-border tbody td,table.dataTable.display tbody th,table.dataTable.display tbody td{border-top:1px solid #ddd}table.dataTable.row-border tbody tr:first-child th,table.dataTable.row-border tbody tr:first-child td,table.dataTable.display tbody tr:first-child th,table.dataTable.display tbody tr:first-child td{border-top:0}table.dataTable.cell-border tbody th,table.dataTable.cell-border tbody td{border-top:1px solid #ddd;border-right:1px solid #ddd}table.dataTable.cell-border tbody tr th:first-child,table.dataTable.cell-border tbody tr td:first-child{border-left:1px solid #ddd}table.dataTable.cell-border tbody tr:first-child th,table.dataTable.cell-border tbody tr:first-child td{border-top:0}table.dataTable.stripe tbody tr.odd,table.dataTable.display tbody tr.odd{background-color:#f9f9f9}table.dataTable.stripe tbody tr.odd.selected,table.dataTable.display tbody tr.odd.selected{background-color:#acbad4}table.dataTable.hover tbody tr:hover,table.dataTable.display tbody tr:hover{background-color:#f6f6f6}table.dataTable.hover tbody tr:hover.selected,table.dataTable.display tbody tr:hover.selected{background-color:#aab7d1}table.dataTable.order-column tbody tr>.sorting_1,table.dataTable.order-column tbody tr>.sorting_2,table.dataTable.order-column tbody tr>.sorting_3,table.dataTable.display tbody tr>.sorting_1,table.dataTable.display tbody tr>.sorting_2,table.dataTable.display tbody tr>.sorting_3{background-color:#fafafa}table.dataTable.order-column tbody tr.selected>.sorting_1,table.dataTable.order-column tbody tr.selected>.sorting_2,table.dataTable.order-column tbody tr.selected>.sorting_3,table.dataTable.display tbody tr.selected>.sorting_1,table.dataTable.display tbody tr.selected>.sorting_2,table.dataTable.display tbody tr.selected>.sorting_3{background-color:#acbad5}table.dataTable.display tbody tr.odd>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd>.sorting_1{background-color:#f1f1f1}table.dataTable.display tbody tr.odd>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd>.sorting_2{background-color:#f3f3f3}table.dataTable.display tbody tr.odd>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd>.sorting_3{background-color:whitesmoke}table.dataTable.display tbody tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.dataTable.display tbody tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.dataTable.display tbody tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.dataTable.display tbody tr.even>.sorting_1,table.dataTable.order-column.stripe tbody tr.even>.sorting_1{background-color:#fafafa}table.dataTable.display tbody tr.even>.sorting_2,table.dataTable.order-column.stripe tbody tr.even>.sorting_2{background-color:#fcfcfc}table.dataTable.display tbody tr.even>.sorting_3,table.dataTable.order-column.stripe tbody tr.even>.sorting_3{background-color:#fefefe}table.dataTable.display tbody tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_1{background-color:#acbad5}table.dataTable.display tbody tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_2{background-color:#aebcd6}table.dataTable.display tbody tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody tr:hover>.sorting_1,table.dataTable.order-column.hover tbody tr:hover>.sorting_1{background-color:#eaeaea}table.dataTable.display tbody tr:hover>.sorting_2,table.dataTable.order-column.hover tbody tr:hover>.sorting_2{background-color:#ececec}table.dataTable.display tbody tr:hover>.sorting_3,table.dataTable.order-column.hover tbody tr:hover>.sorting_3{background-color:#efefef}table.dataTable.display tbody tr:hover.selected>.sorting_1,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_1{background-color:#a2aec7}table.dataTable.display tbody tr:hover.selected>.sorting_2,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_2{background-color:#a3b0c9}table.dataTable.display tbody tr:hover.selected>.sorting_3,table.dataTable.order-column.hover tbody tr:hover.selected>.sorting_3{background-color:#a5b2cb}table.dataTable.no-footer{border-bottom:1px solid #111}table.dataTable.nowrap th,table.dataTable.nowrap td{white-space:nowrap}table.dataTable.compact thead th,table.dataTable.compact thead td{padding:4px 17px 4px 4px}table.dataTable.compact tfoot th,table.dataTable.compact tfoot td{padding:4px}table.dataTable.compact tbody th,table.dataTable.compact tbody td{padding:4px}table.dataTable th.dt-left,table.dataTable td.dt-left{text-align:left}table.dataTable th.dt-center,table.dataTable td.dt-center,table.dataTable td.dataTables_empty{text-align:center}table.dataTable th.dt-right,table.dataTable td.dt-right{text-align:right}table.dataTable th.dt-justify,table.dataTable td.dt-justify{text-align:justify}table.dataTable th.dt-nowrap,table.dataTable td.dt-nowrap{white-space:nowrap}table.dataTable thead th.dt-head-left,table.dataTable thead td.dt-head-left,table.dataTable tfoot th.dt-head-left,table.dataTable tfoot td.dt-head-left{text-align:left}table.dataTable thead th.dt-head-center,table.dataTable thead td.dt-head-center,table.dataTable tfoot th.dt-head-center,table.dataTable tfoot td.dt-head-center{text-align:center}table.dataTable thead th.dt-head-right,table.dataTable thead td.dt-head-right,table.dataTable tfoot th.dt-head-right,table.dataTable tfoot td.dt-head-right{text-align:right}table.dataTable thead th.dt-head-justify,table.dataTable thead td.dt-head-justify,table.dataTable tfoot th.dt-head-justify,table.dataTable tfoot td.dt-head-justify{text-align:justify}table.dataTable thead th.dt-head-nowrap,table.dataTable thead td.dt-head-nowrap,table.dataTable tfoot th.dt-head-nowrap,table.dataTable tfoot td.dt-head-nowrap{white-space:nowrap}table.dataTable tbody th.dt-body-left,table.dataTable tbody td.dt-body-left{text-align:left}table.dataTable tbody th.dt-body-center,table.dataTable tbody td.dt-body-center{text-align:center}table.dataTable tbody th.dt-body-right,table.dataTable tbody td.dt-body-right{text-align:right}table.dataTable tbody th.dt-body-justify,table.dataTable tbody td.dt-body-justify{text-align:justify}table.dataTable tbody th.dt-body-nowrap,table.dataTable tbody td.dt-body-nowrap{white-space:nowrap}table.dataTable,table.dataTable th,table.dataTable td{box-sizing:content-box}.dataTables_wrapper{position:relative;clear:both;*zoom:1;zoom:1}.dataTables_wrapper .dataTables_length{float:left}.dataTables_wrapper .dataTables_filter{float:right;text-align:right}.dataTables_wrapper .dataTables_filter input{margin-left:.5em}.dataTables_wrapper .dataTables_info{clear:both;float:left;padding-top:.755em}.dataTables_wrapper .dataTables_paginate{float:right;text-align:right;padding-top:.25em}.dataTables_wrapper .dataTables_paginate .paginate_button{box-sizing:border-box;display:inline-block;min-width:1.5em;padding:.5em 1em;margin-left:2px;text-align:center;text-decoration:none !important;cursor:pointer;*cursor:hand;color:#333 !important;border:1px solid transparent;border-radius:2px}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{color:#333 !important;border:1px solid #979797;background-color:white;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,white),color-stop(100%,#dcdcdc));background:-webkit-linear-gradient(top,white 0,#dcdcdc 100%);background:-moz-linear-gradient(top,white 0,#dcdcdc 100%);background:-ms-linear-gradient(top,white 0,#dcdcdc 100%);background:-o-linear-gradient(top,white 0,#dcdcdc 100%);background:linear-gradient(to bottom,white 0,#dcdcdc 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button.disabled,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover,.dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active{cursor:default;color:#666 !important;border:1px solid transparent;background:transparent;box-shadow:none}.dataTables_wrapper .dataTables_paginate .paginate_button:hover{color:white !important;border:1px solid #111;background-color:#585858;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#585858),color-stop(100%,#111));background:-webkit-linear-gradient(top,#585858 0,#111 100%);background:-moz-linear-gradient(top,#585858 0,#111 100%);background:-ms-linear-gradient(top,#585858 0,#111 100%);background:-o-linear-gradient(top,#585858 0,#111 100%);background:linear-gradient(to bottom,#585858 0,#111 100%)}.dataTables_wrapper .dataTables_paginate .paginate_button:active{outline:0;background-color:#2b2b2b;background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#2b2b2b),color-stop(100%,#0c0c0c));background:-webkit-linear-gradient(top,#2b2b2b 0,#0c0c0c 100%);background:-moz-linear-gradient(top,#2b2b2b 0,#0c0c0c 100%);background:-ms-linear-gradient(top,#2b2b2b 0,#0c0c0c 100%);background:-o-linear-gradient(top,#2b2b2b 0,#0c0c0c 100%);background:linear-gradient(to bottom,#2b2b2b 0,#0c0c0c 100%);box-shadow:inset 0 0 3px #111}.dataTables_wrapper .dataTables_paginate .ellipsis{padding:0 1em}.dataTables_wrapper .dataTables_processing{position:absolute;top:50%;left:50%;width:100%;height:40px;margin-left:-50%;margin-top:-25px;padding-top:20px;text-align:center;font-size:1.2em;background-color:white;background:-webkit-gradient(linear,left top,right top,color-stop(0,rgba(255,255,255,0)),color-stop(25%,rgba(255,255,255,0.9)),color-stop(75%,rgba(255,255,255,0.9)),color-stop(100%,rgba(255,255,255,0)));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,0.9) 25%,rgba(255,255,255,0.9) 75%,rgba(255,255,255,0) 100%);background:-moz-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,0.9) 25%,rgba(255,255,255,0.9) 75%,rgba(255,255,255,0) 100%);background:-ms-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,0.9) 25%,rgba(255,255,255,0.9) 75%,rgba(255,255,255,0) 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,rgba(255,255,255,0.9) 25%,rgba(255,255,255,0.9) 75%,rgba(255,255,255,0) 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,rgba(255,255,255,0.9) 25%,rgba(255,255,255,0.9) 75%,rgba(255,255,255,0) 100%)}.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter,.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_processing,.dataTables_wrapper .dataTables_paginate{color:#333}.dataTables_wrapper .dataTables_scroll{clear:both}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody{*margin-top:-1px;-webkit-overflow-scrolling:touch}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td{vertical-align:middle}.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>thead>tr>td>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>th>div.dataTables_sizing,.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody>table>tbody>tr>td>div.dataTables_sizing{height:0;overflow:hidden;margin:0 !important;padding:0 !important}.dataTables_wrapper.no-footer .dataTables_scrollBody{border-bottom:1px solid #111}.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,.dataTables_wrapper.no-footer div.dataTables_scrollBody>table{border-bottom:0}.dataTables_wrapper:after{visibility:hidden;display:block;content:"";clear:both;height:0}@media screen and (max-width:767px){.dataTables_wrapper .dataTables_info,.dataTables_wrapper .dataTables_paginate{float:none;text-align:center}.dataTables_wrapper .dataTables_paginate{margin-top:.5em}}@media screen and (max-width:640px){.dataTables_wrapper .dataTables_length,.dataTables_wrapper .dataTables_filter{float:none;text-align:center}.dataTables_wrapper .dataTables_filter{margin-top:.5em}}pre .comment,pre .template_comment,pre .diff .header,pre .javadoc{color:#998;font-style:italic}pre .keyword,pre .css .rule .keyword,pre .winutils,pre .javascript .title,pre .lisp .title{color:#000;font-weight:bold}pre .number,pre .hexcolor{color:#458}pre .string,pre .tag .value,pre .phpdoc,pre .tex .formula{color:#d14}pre .subst{color:#712}pre .constant,pre .title,pre .id{color:#900;font-weight:bold}pre .javascript .title,pre .lisp .title,pre .subst{font-weight:normal}pre .class .title,pre .haskell .label,pre .tex .command{color:#458;font-weight:bold}pre .tag,pre .tag .title,pre .rules .property,pre .django .tag .keyword{color:navy;font-weight:normal}pre .attribute,pre .variable,pre .instancevar,pre .lisp .body{color:teal}pre .regexp{color:#009926}pre .class{color:#458;font-weight:bold}pre .symbol,pre .ruby .symbol .string,pre .ruby .symbol .keyword,pre .ruby .symbol .keymethods,pre .lisp .keyword,pre .tex .special,pre .input_number{color:#990073}pre .builtin,pre .built_in,pre .lisp .title{color:#0086b3}pre .preprocessor,pre .pi,pre .doctype,pre .shebang,pre .cdata{color:#999;font-weight:bold}pre .deletion{background:#fdd}pre .addition{background:#dfd}pre .diff .change{background:#0086b3}pre .chunk{color:#aaa}pre .tex .formula{opacity:.5}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute;left:-99999999px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.ui-helper-clearfix{display:inline-block}/*\*/* html .ui-helper-clearfix{height:1%}.ui-helper-clearfix{display:block}/**/.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default !important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-widget :active{outline:0}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-off{background-position:-96px -144px}.ui-icon-radio-on{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-corner-top{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-bottom{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-corner-right{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-corner-left{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.30;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.30;filter:Alpha(Opacity=30);-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}#colorbox,#cboxOverlay,#cboxWrapper{position:absolute;top:0;left:0;z-index:9999;overflow:hidden}#cboxOverlay{position:fixed;width:100%;height:100%}#cboxMiddleLeft,#cboxBottomLeft{clear:left}#cboxContent{position:relative}#cboxLoadedContent{overflow:auto}#cboxTitle{margin:0}#cboxLoadingOverlay,#cboxLoadingGraphic{position:absolute;top:0;left:0;width:100%;height:100%}#cboxPrevious,#cboxNext,#cboxClose,#cboxSlideshow{cursor:pointer}.cboxPhoto{float:left;margin:auto;border:0;display:block;max-width:none}.cboxIframe{width:100%;height:100%;display:block;border:0}#colorbox,#cboxContent,#cboxLoadedContent{box-sizing:content-box}#cboxOverlay{background:#000}#cboxTopLeft{width:14px;height:14px;background:url(colorbox/controls.png) no-repeat 0 0}#cboxTopCenter{height:14px;background:url(colorbox/border.png) repeat-x top left}#cboxTopRight{width:14px;height:14px;background:url(colorbox/controls.png) no-repeat -36px 0}#cboxBottomLeft{width:14px;height:43px;background:url(colorbox/controls.png) no-repeat 0 -32px}#cboxBottomCenter{height:43px;background:url(colorbox/border.png) repeat-x bottom left}#cboxBottomRight{width:14px;height:43px;background:url(colorbox/controls.png) no-repeat -36px -32px}#cboxMiddleLeft{width:14px;background:url(colorbox/controls.png) repeat-y -175px 0}#cboxMiddleRight{width:14px;background:url(colorbox/controls.png) repeat-y -211px 0}#cboxContent{background:#fff;overflow:visible}.cboxIframe{background:#fff}#cboxError{padding:50px;border:1px solid #ccc}#cboxLoadedContent{margin-bottom:5px}#cboxLoadingOverlay{background:url(colorbox/loading_background.png) no-repeat center center}#cboxLoadingGraphic{background:url(colorbox/loading.gif) no-repeat center center}#cboxTitle{position:absolute;bottom:-25px;left:0;text-align:center;width:100%;font-weight:bold;color:#7c7c7c}#cboxCurrent{position:absolute;bottom:-25px;left:58px;font-weight:bold;color:#7c7c7c}#cboxPrevious,#cboxNext,#cboxClose,#cboxSlideshow{position:absolute;bottom:-29px;background:url(colorbox/controls.png) no-repeat 0 0;width:23px;height:23px;text-indent:-9999px}#cboxPrevious{left:0;background-position:-51px -25px}#cboxPrevious:hover{background-position:-51px 0}#cboxNext{left:27px;background-position:-75px -25px}#cboxNext:hover{background-position:-75px 0}#cboxClose{right:0;background-position:-100px -25px}#cboxClose:hover{background-position:-100px 0}.cboxSlideshow_on #cboxSlideshow{background-position:-125px 0;right:27px}.cboxSlideshow_on #cboxSlideshow:hover{background-position:-150px 0}.cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px;right:27px}.cboxSlideshow_off #cboxSlideshow:hover{background-position:-125px 0}#loading{position:fixed;left:40%;top:50%}a{color:#333;text-decoration:none}a:hover{color:#000;text-decoration:underline}body{font-family:"Lucida Grande",Helvetica,"Helvetica Neue",Arial,sans-serif;padding:12px;background-color:#333}h1,h2,h3,h4{color:#1c2324;margin:0;padding:0;margin-bottom:12px}table{width:100%}#content{clear:left;background-color:white;border:2px solid #ddd;border-top:8px solid #ddd;padding:18px;-webkit-border-bottom-left-radius:5px;-webkit-border-bottom-right-radius:5px;-webkit-border-top-right-radius:5px;-moz-border-radius-bottomleft:5px;-moz-border-radius-bottomright:5px;-moz-border-radius-topright:5px;border-bottom-left-radius:5px;border-bottom-right-radius:5px;border-top-right-radius:5px}.dataTables_filter,.dataTables_info{padding:2px 6px}abbr.timeago{text-decoration:none;border:0;font-weight:bold}.timestamp{float:right;color:#ddd}.group_tabs{list-style:none;float:left;margin:0;padding:0}.group_tabs li{display:inline;float:left}.group_tabs li a{font-family:Helvetica,Arial,sans-serif;display:block;float:left;text-decoration:none;padding:4px 8px;background-color:#aaa;background:-webkit-gradient(linear,0 0,0 bottom,from(#ddd),to(#aaa));background:-moz-linear-gradient(#ddd,#aaa);background:linear-gradient(#ddd,#aaa);text-shadow:#e5e5e5 1px 1px 0;border-bottom:0;color:#333;font-weight:bold;margin-right:8px;border-top:1px solid #efefef;-webkit-border-top-left-radius:2px;-webkit-border-top-right-radius:2px;-moz-border-radius-topleft:2px;-moz-border-radius-topright:2px;border-top-left-radius:2px;border-top-right-radius:2px}.group_tabs li a:hover{background-color:#ccc;background:-webkit-gradient(linear,0 0,0 bottom,from(#eee),to(#aaa));background:-moz-linear-gradient(#eee,#aaa);background:linear-gradient(#eee,#aaa)}.group_tabs li a:active{padding-top:5px;padding-bottom:3px}.group_tabs li.active a{color:black;text-shadow:#fff 1px 1px 0;background-color:#ddd;background:-webkit-gradient(linear,0 0,0 bottom,from(white),to(#ddd));background:-moz-linear-gradient(white,#ddd);background:linear-gradient(white,#ddd)}.file_list{margin-bottom:18px}.file_list--responsive{overflow-x:auto;overflow-y:hidden}a.src_link{background:url("./magnify.png") no-repeat left 50%;padding-left:18px}tr,td{margin:0;padding:0}th{white-space:nowrap}th.ui-state-default{cursor:pointer}th span.ui-icon{float:left}td{padding:4px 8px}td.strong{font-weight:bold}.cell--number{text-align:right}.source_table h3,.source_table h4{padding:0;margin:0;margin-bottom:4px}.source_table .header{padding:10px}.source_table pre{margin:0;padding:0;white-space:normal;color:#000;font-family:"Monaco","Inconsolata","Consolas",monospace}.source_table code{color:#000;font-family:"Monaco","Inconsolata","Consolas",monospace}.source_table pre{background-color:#333}.source_table pre ol{margin:0;padding:0;margin-left:45px;font-size:12px;color:white}.source_table pre li{margin:0;padding:2px 6px;border-left:5px solid white}.source_table pre li code{white-space:pre;white-space:pre-wrap}.source_table pre .hits{float:right;margin-left:10px;padding:2px 4px;background-color:#444;background:-webkit-gradient(linear,0 0,0 bottom,from(#222),to(#666));background:-moz-linear-gradient(#222,#666);background:linear-gradient(#222,#666);color:white;font-family:Helvetica,"Helvetica Neue",Arial,sans-serif;font-size:10px;font-weight:bold;text-align:center;border-radius:6px}#footer{color:#ddd;font-size:12px;font-weight:bold;margin-top:12px;text-align:right}#footer a{color:#eee;text-decoration:underline}#footer a:hover{color:#fff;text-decoration:none}.green{color:#090}.red{color:#900}.yellow{color:#da0}.blue{color:blue}thead th{background:white}.source_table .covered{border-color:#090}.source_table .missed{border-color:#900}.source_table .never{border-color:black}.source_table .skipped{border-color:#fc0}.source_table .missed-branch{border-color:#bf0000}.source_table .covered:nth-child(odd){background-color:#cdf2cd}.source_table .covered:nth-child(even){background-color:#dbf2db}.source_table .missed:nth-child(odd){background-color:#f7c0c0}.source_table .missed:nth-child(even){background-color:#f7cfcf}.source_table .never:nth-child(odd){background-color:#efefef}.source_table .never:nth-child(even){background-color:#f4f4f4}.source_table .skipped:nth-child(odd){background-color:#fbf0c0}.source_table .skipped:nth-child(even){background-color:#fbffcf}.source_table .missed-branch:nth-child(odd){background-color:#cc8e8e}.source_table .missed-branch:nth-child(even){background-color:#cc6e6e}
\ No newline at end of file
diff --git a/coverage/assets/0.12.3/application.js b/coverage/assets/0.12.3/application.js
new file mode 100644
index 00000000..e1c2ab23
--- /dev/null
+++ b/coverage/assets/0.12.3/application.js
@@ -0,0 +1,7 @@
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(T,e){"use strict";function g(e,t,n){var r,a,i=(n=n||le).createElement("script");if(i.text=e,t)for(r in Se)(a=t[r]||t.getAttribute&&t.getAttribute(r))&&i.setAttribute(r,a);n.head.appendChild(i).parentNode.removeChild(i)}function m(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?pe[ge.call(e)]||"object":typeof e}function s(e){var t=!!e&&"length"in e&&e.length,n=m(e);return!we(e)&&!xe(e)&&("array"===n||0===t||"number"==typeof t&&0D.cacheLength&&delete n[r.shift()],n[e+" "]=t}var r=[];return n}function l(e){return e[q]=!0,e}function a(e){var t=E.createElement("fieldset");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function t(e,t){for(var n=e.split("|"),r=n.length;r--;)D.attrHandle[n[r]]=t}function u(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function r(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function i(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function o(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&_e(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function s(o){return l(function(i){return i=+i,l(function(e,t){for(var n,r=o([],e.length,i),a=r.length;a--;)e[n=r[a]]&&(e[n]=!(t[n]=e[n]))})})}function p(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function c(){}function g(e){for(var t=0,n=e.length,r="";t+~]|"+re+")"+re+"*"),fe=new RegExp(re+"|>"),de=new RegExp(oe),he=new RegExp("^"+ae+"$"),pe={ID:new RegExp("^#("+ae+")"),CLASS:new RegExp("^\\.("+ae+")"),TAG:new RegExp("^("+ae+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+re+"*(even|odd|(([+-]|)(\\d*)n|)"+re+"*(?:([+-]|)"+re+"*(\\d+)|))"+re+"*\\)|)","i"),bool:new RegExp("^(?:"+ne+")$","i"),needsContext:new RegExp("^"+re+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+re+"*((?:-\\d)?\\d*)"+re+"*\\)|)(?=[^-]|$)","i")},ge=/HTML$/i,me=/^(?:input|select|textarea|button)$/i,ve=/^h\d$/i,ye=/^[^{]+\{\s*\[native \w/,be=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,we=/[+~]/,xe=new RegExp("\\\\([\\da-f]{1,6}"+re+"?|("+re+")|.)","ig"),Se=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},De=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,Te=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},Ce=function(){L()},_e=f(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{Q.apply(Y=ee.call(W.childNodes),W.childNodes),Y[W.childNodes.length].nodeType}catch(Ae){Q={apply:Y.length?function(e,t){K.apply(e,ee.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}for(v in S=w.support={},C=w.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!ge.test(t||n&&n.nodeName||"HTML")},L=w.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:W;return r!==E&&9===r.nodeType&&r.documentElement&&(R=(E=r).documentElement,F=!C(E),W!==E&&(n=E.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Ce,!1):n.attachEvent&&n.attachEvent("onunload",Ce)),S.attributes=a(function(e){return e.className="i",!e.getAttribute("className")}),S.getElementsByTagName=a(function(e){return e.appendChild(E.createComment("")),!e.getElementsByTagName("*").length}),S.getElementsByClassName=ye.test(E.getElementsByClassName),S.getById=a(function(e){return R.appendChild(e).id=q,!E.getElementsByName||!E.getElementsByName(q).length}),S.getById?(D.filter.ID=function(e){var t=e.replace(xe,Se);return function(e){return e.getAttribute("id")===t}},D.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&F){var n=t.getElementById(e);return n?[n]:[]}}):(D.filter.ID=function(e){var n=e.replace(xe,Se);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},D.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&F){var n,r,a,i=t.getElementById(e);if(i){if((n=i.getAttributeNode("id"))&&n.value===e)return[i];for(a=t.getElementsByName(e),r=0;i=a[r++];)if((n=i.getAttributeNode("id"))&&n.value===e)return[i]}return[]}}),D.find.TAG=S.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):S.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],a=0,i=t.getElementsByTagName(e);if("*"!==e)return i;for(;n=i[a++];)1===n.nodeType&&r.push(n);return r},D.find.CLASS=S.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&F)return t.getElementsByClassName(e)},H=[],P=[],(S.qsa=ye.test(E.querySelectorAll))&&(a(function(e){R.appendChild(e).innerHTML=" ",e.querySelectorAll("[msallowcapture^='']").length&&P.push("[*^$]="+re+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||P.push("\\["+re+"*(?:value|"+ne+")"),e.querySelectorAll("[id~="+q+"-]").length||P.push("~="),e.querySelectorAll(":checked").length||P.push(":checked"),e.querySelectorAll("a#"+q+"+*").length||P.push(".#.+[+~]")}),a(function(e){e.innerHTML=" ";var t=E.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&P.push("name"+re+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&P.push(":enabled",":disabled"),R.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&P.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),P.push(",.*:")})),(S.matchesSelector=ye.test(M=R.matches||R.webkitMatchesSelector||R.mozMatchesSelector||R.oMatchesSelector||R.msMatchesSelector))&&a(function(e){S.disconnectedMatch=M.call(e,"*"),M.call(e,"[s!='']:x"),H.push("!=",oe)}),P=P.length&&new RegExp(P.join("|")),H=H.length&&new RegExp(H.join("|")),t=ye.test(R.compareDocumentPosition),O=t||ye.test(R.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},G=t?function(e,t){if(e===t)return j=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!S.sortDetached&&t.compareDocumentPosition(e)===n?e===E||e.ownerDocument===W&&O(W,e)?-1:t===E||t.ownerDocument===W&&O(W,t)?1:I?te(I,e)-te(I,t):0:4&n?-1:1)}:function(e,t){if(e===t)return j=!0,0;var n,r=0,a=e.parentNode,i=t.parentNode,o=[e],s=[t];if(!a||!i)return e===E?-1:t===E?1:a?-1:i?1:I?te(I,e)-te(I,t):0;if(a===i)return u(e,t);for(n=e;n=n.parentNode;)o.unshift(n);for(n=t;n=n.parentNode;)s.unshift(n);for(;o[r]===s[r];)r++;return r?u(o[r],s[r]):o[r]===W?-1:s[r]===W?1:0}),E},w.matches=function(e,t){return w(e,null,null,t)},w.matchesSelector=function(e,t){if((e.ownerDocument||e)!==E&&L(e),S.matchesSelector&&F&&!V[t+" "]&&(!H||!H.test(t))&&(!P||!P.test(t)))try{var n=M.call(e,t);if(n||S.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(Ae){V(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(xe,Se),e[3]=(e[3]||e[4]||e[5]||"").replace(xe,Se),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||w.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&w.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&de.test(n)&&(t=_(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(xe,Se).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=U[e+" "];return t||(t=new RegExp("(^|"+re+")"+e+"("+re+"|$)"))&&U(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,a){return function(e){var t=w.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===a:"!="===r?t!==a:"^="===r?a&&0===t.indexOf(a):"*="===r?a&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;Te.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?Te.find.matchesSelector(r,e)?[r]:[]:Te.find.matches(e,Te.grep(t,function(e){return 1===e.nodeType}))},Te.fn.extend({find:function(e){var t,n,r=this.length,a=this;if("string"!=typeof e)return this.pushStack(Te(e).filter(function(){for(t=0;t)[^>]*|#([\w-]+))$/;(Te.fn.init=function(e,t,n){var r,a;if(!e)return this;if(n=n||je,"string"!=typeof e)return e.nodeType?(this[0]=e,this.length=1,this):we(e)?n.ready!==undefined?n.ready(e):e(Te):Te.makeArray(e,this);if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:Le.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof Te?t[0]:t,Te.merge(this,Te.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:le,!0)),Ie.test(r[1])&&Te.isPlainObject(t))for(r in t)we(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(a=le.getElementById(r[2]))&&(this[0]=a,this.length=1),this}).prototype=Te.fn,je=Te(le);var Ee=/^(?:parents|prev(?:Until|All))/,Re={children:!0,contents:!0,next:!0,prev:!0};Te.fn.extend({has:function(e){var t=Te(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,rt=/^$|^module$|\/(?:java|ecma)script/i,at={option:[1,""," "],thead:[1,""],col:[2,""],tr:[2,""],td:[3,""],_default:[0,"",""]};at.optgroup=at.option,at.tbody=at.tfoot=at.colgroup=at.caption=at.thead,at.th=at.td;var it,ot,st=/<|?\w+;/;it=le.createDocumentFragment().appendChild(le.createElement("div")),(ot=le.createElement("input")).setAttribute("type","radio"),ot.setAttribute("checked","checked"),ot.setAttribute("name","t"),it.appendChild(ot),be.checkClone=it.cloneNode(!0).cloneNode(!0).lastChild.checked,it.innerHTML="",be.noCloneChecked=!!it.cloneNode(!0).lastChild.defaultValue;var lt=/^key/,ut=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ct=/^([^.]*)(?:\.(.+)|)/;Te.event={global:{},add:function(t,e,n,r,a){var i,o,s,l,u,c,f,d,h,p,g,m=Be.get(t);if(m)for(n.handler&&(n=(i=n).handler,a=i.selector),a&&Te.find.matchesSelector(Je,a),n.guid||(n.guid=Te.guid++),(l=m.events)||(l=m.events={}),(o=m.handle)||(o=m.handle=function(e){return void 0!==Te&&Te.event.triggered!==e.type?Te.event.dispatch.apply(t,arguments):undefined}),u=(e=(e||"").match(Fe)||[""]).length;u--;)h=g=(s=ct.exec(e[u])||[])[1],p=(s[2]||"").split(".").sort(),h&&(f=Te.event.special[h]||{},h=(a?f.delegateType:f.bindType)||h,f=Te.event.special[h]||{},c=Te.extend({type:h,origType:g,data:r,handler:n,guid:n.guid,selector:a,needsContext:a&&Te.expr.match.needsContext.test(a),namespace:p.join(".")},i),(d=l[h])||((d=l[h]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,p,o)||t.addEventListener&&t.addEventListener(h,o)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),a?d.splice(d.delegateCount++,0,c):d.push(c),Te.event.global[h]=!0)},remove:function(e,t,n,r,a){var i,o,s,l,u,c,f,d,h,p,g,m=Be.hasData(e)&&Be.get(e);if(m&&(l=m.events)){for(u=(t=(t||"").match(Fe)||[""]).length;u--;)if(h=g=(s=ct.exec(t[u])||[])[1],p=(s[2]||"").split(".").sort(),h){for(f=Te.event.special[h]||{},d=l[h=(r?f.delegateType:f.bindType)||h]||[],s=s[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),o=i=d.length;i--;)c=d[i],!a&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(d.splice(i,1),c.selector&&d.delegateCount--,f.remove&&f.remove.call(e,c));o&&!d.length&&(f.teardown&&!1!==f.teardown.call(e,p,m.handle)||Te.removeEvent(e,h,m.handle),delete l[h])}else for(h in l)Te.event.remove(e,h+t[u],n,r,!0);Te.isEmptyObject(l)&&Be.remove(e,"handle events")}},dispatch:function(e){var t,n,r,a,i,o,s=Te.event.fix(e),l=new Array(arguments.length),u=(Be.get(this,"events")||{})[s.type]||[],c=Te.event.special[s.type]||{};for(l[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,dt=/
+
+
+
+
+
+
+
+
+
+
+
Generated
2021-05-19T19:34:31+00:00
+
+
+
+
+
+ All Files
+ (
+
+ 27.79%
+
+
+
+ covered at
+
+
+ 41.0
+
+ hits/line
+ )
+
+
+
+
+
+ 48 files in total.
+
+
+
+ 986 relevant lines,
+ 274 lines covered and
+ 712 lines missed.
+ (
+ 27.79%
+
+)
+
+
+
+
+
+
+
+
+
+
+
+ Controllers
+ (
+
+ 19.44%
+
+
+
+ covered at
+
+
+ 37.39
+
+ hits/line
+ )
+
+
+
+
+
+ 20 files in total.
+
+
+
+ 756 relevant lines,
+ 147 lines covered and
+ 609 lines missed.
+ (
+ 19.44%
+
+)
+
+
+
+
+
+
+
+
+
+
+ Channels
+ (
+
+ 0.0%
+
+
+
+ covered at
+
+
+ 0.0
+
+ hits/line
+ )
+
+
+
+
+
+ 2 files in total.
+
+
+
+ 8 relevant lines,
+ 0 lines covered and
+ 8 lines missed.
+ (
+ 0.0%
+
+)
+
+
+
+
+
+
+
+
+
+
+ Models
+ (
+
+ 60.11%
+
+
+
+ covered at
+
+
+ 66.34
+
+ hits/line
+ )
+
+
+
+
+
+ 12 files in total.
+
+
+
+ 183 relevant lines,
+ 110 lines covered and
+ 73 lines missed.
+ (
+ 60.11%
+
+)
+
+
+
+
+
+
+
+
+
+
+ Mailers
+ (
+
+ 0.0%
+
+
+
+ covered at
+
+
+ 0.0
+
+ hits/line
+ )
+
+
+
+
+
+ 3 files in total.
+
+
+
+ 18 relevant lines,
+ 0 lines covered and
+ 18 lines missed.
+ (
+ 0.0%
+
+)
+
+
+
+
+
+
+
+
+
+
+ Helpers
+ (
+
+ 89.47%
+
+
+
+ covered at
+
+
+ 1.16
+
+ hits/line
+ )
+
+
+
+
+
+ 10 files in total.
+
+
+
+ 19 relevant lines,
+ 17 lines covered and
+ 2 lines missed.
+ (
+ 89.47%
+
+)
+
+
+
+
+
+
+
+
+
+
+ Jobs
+ (
+
+ 0.0%
+
+
+
+ covered at
+
+
+ 0.0
+
+ hits/line
+ )
+
+
+
+
+
+ 1 files in total.
+
+
+
+ 2 relevant lines,
+ 0 lines covered and
+ 2 lines missed.
+ (
+ 0.0%
+
+)
+
+
+
+
+
+
+
+
+ File
+ % covered
+ Lines
+ Relevant Lines
+ Lines covered
+ Lines missed
+ Avg. Hits / Line
+
+
+
+
+
+
+ app/jobs/application_job.rb
+ 0.00 %
+ 2
+ 2
+ 0
+ 2
+ 0.00
+
+
+
+
+
+
+
+
+
+
+
+ Libraries
+ (
+
+ 100.0%
+
+
+
+ covered at
+
+
+ 0.0
+
+ hits/line
+ )
+
+
+
+
+
+ 0 files in total.
+
+
+
+ 0 relevant lines,
+ 0 lines covered and
+ 0 lines missed.
+ (
+ 100.0%
+
+)
+
+
+
+
+
+
+
+
+ File
+ % covered
+ Lines
+ Relevant Lines
+ Lines covered
+ Lines missed
+ Avg. Hits / Line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ module ApplicationCable
+
+
+
+
+
+
+
+
+
+
+ class Channel < ActionCable::Channel::Base
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ module ApplicationCable
+
+
+
+
+
+
+
+
+
+
+ class Connection < ActionCable::Connection::Base
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class AdminsController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ def index ; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def new ; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @admin = Admin.create(admin_params)
+
+
+
+
+
+
+
+
+
+
+ redirect_to root_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def admin_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:admin).permit(:id, :name, :email, :password, :password_confirmation)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class ApplicationController < ActionController::Base
+
+
+
+
+
+ 1
+
+
+
+
+ protect_from_forgery
+
+
+
+
+
+ 1
+
+
+
+
+ include SessionsHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class AtendimentosController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :set_atendimento, only: [:edit, :update, :destroy]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /atendimentos/new
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # busca o usuário logado para associá-lo ao novo atendimento.
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @atendimento = Atendimento.new
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /atendimentos/1/edit
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # POST /atendimentos
+
+
+
+
+
+
+
+
+
+
+ # POST /atendimentos.json
+
+
+
+
+
+
+
+
+
+
+ # Método para criar um atendimento, associando o atendimento ao usuário logado,
+
+
+
+
+
+
+
+
+
+
+ # que será passado pelo atendimento_params
+
+
+
+
+
+
+
+
+
+
+ # Retorna para a pagina dashboard/atendimentos
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ @atendimento = Atendimento.create(atendimento_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@atendimento.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "Registro de atendimento realizado com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @atendimento.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atendimentos_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /atendimentos/1
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /atendimentos/1.json
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ @atendimento = Atendimento.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @atendimento.update_attributes(atendimento_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@atendimento.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Atendimento atualizado com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ elsif
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @atendimento.errors.first[1]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atendimentos_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # DELETE /atendimentos/1
+
+
+
+
+
+
+
+
+
+
+ # DELETE /atendimentos/1.json
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @atendimento = Atendimento.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @atendimento.delete
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Atendimento apagado com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atendimentos_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ # Use callbacks to share common setup or constraints between actions.
+
+
+
+
+
+
+
+
+
+
+ def set_atendimento
+
+
+
+
+
+
+
+
+
+
+ @atendimento = Atendimento.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+
+
+
+
+
+
+
+
+
+
+ def atendimento_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:atendimento).permit(:motivo_id, :dia, :descricao, :aluno_atendido, :monitor_id)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class AtividadesController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :user_logged
+
+
+
+
+
+
+
+
+
+
+ before_action :set_atividade, only: [:show, :edit, :update, :destroy]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /atividades
+
+
+
+
+
+
+
+
+
+
+ # GET /atividades.json
+
+
+
+
+
+
+
+
+
+
+ def index
+
+
+
+
+
+
+
+
+
+
+ @atividades = Atividade.all
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /atividades/1
+
+
+
+
+
+
+
+
+
+
+ # GET /atividades/1.json
+
+
+
+
+
+
+
+
+
+
+ def show
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /atividades/new
+
+
+
+
+
+
+
+
+
+
+ #Associa o registro de atividade ao usuario logado
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @atividade = Atividade.new
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /atividades/1/edit
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # POST /atividades
+
+
+
+
+
+
+
+
+
+
+ # POST /atividades.json
+
+
+
+
+
+
+
+
+
+
+ # Método para criar o registro de uma atividade, associando a atividade ao usuário logado,
+
+
+
+
+
+
+
+
+
+
+ # que será passado pelo atividade_params
+
+
+
+
+
+
+
+
+
+
+ # Criando ou não, retorna para o dashboard
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @atividade = Atividade.create(atividade_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@atividade.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "Registro de atividade realizado com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atividades_path
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @atividade.errors.first[1]
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atividades_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /atividades/1
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /atividades/1.json
+
+
+
+
+
+
+
+
+
+
+ # Método para editar o registro de uma atividade, passando pelo atividade_params a atividade atualizada associada
+
+
+
+
+
+
+
+
+
+
+ # ao usuario que foi capturada por params[:id]
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @atividade = Atividade.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @atividade.update_attributes(atividade_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@atividade.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Atividade atualizada com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ elsif
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @atividade.errors.first[1]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atividades_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # DELETE /atividades/1
+
+
+
+
+
+
+
+
+
+
+ # DELETE /atividades/1.json
+
+
+
+
+
+
+
+
+
+
+ # Metodo utilizado para apagar uma atividade, utilizando seu id como paramentro
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @atividade = Atividade.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @atividade.delete
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Atividade apagada com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_atividades_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ # verifica se o usuario está logado para poder acessar a pagina de registro
+
+
+
+
+
+
+
+
+
+
+ def user_logged
+
+
+
+
+
+
+
+
+
+
+ if !logged_in?
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_session_path, notice: "Você precisa estar logado para acessar essa página"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ # Use callbacks to share common setup or constraints between actions.
+
+
+
+
+
+
+
+
+
+
+ def set_atividade
+
+
+
+
+
+
+
+
+
+
+ @atividade = Atividade.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+
+
+
+
+
+
+
+
+
+
+ def atividade_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:atividade).permit(:titulo, :mensagem, :matricula_monitor, :data)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # controllers/concerns/turmas_parser.rb
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Implementa funções dedicadas à extração de dados de turmas de um arquivo importado.
+
+
+
+
+
+
+
+
+
+
+ # Este módulo serve apenas para uma formatação específica. Se o formato do arquivo for alterado, o módulo também deve ser.
+
+
+
+
+
+ 1
+
+
+
+
+ module TurmasParser
+
+
+
+
+
+ 1
+
+
+
+
+ extend ActiveSupport::Concern
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def parsear_arquivo_de_turmas (file)
+
+
+
+
+
+ 2
+
+
+
+
+ doc_to_parse = Nokogiri::HTML(file.read, nil, 'UTF-8') do |config|
+
+
+
+
+
+ 2
+
+
+
+
+ config.recover
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+ 2
+
+
+
+
+ blocos_de_turma_html = doc_to_parse.xpath(
+
+
+
+
+
+
+
+
+
+
+ '//table[tr[@class="componentescur"]]') # Separa o html em blocos da table pai do tr de classe 'componentescur'
+
+
+
+
+
+ 2
+
+
+
+
+ return blocos_de_turma_html
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def extrair_texto_de_bloco (bloco, regex)
+
+
+
+
+
+ 3656
+
+
+
+
+ return bloco.to_s.match(/#{regex}/)[1]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def extrair_info_de_disciplina (info_turma)
+
+
+
+
+
+ 914
+
+
+
+
+ info = Hash.new()
+
+
+
+
+
+ 914
+
+
+
+
+ info_disciplina = info_turma.at_css('tr.componentescur').css('td')
+
+
+
+
+
+ 914
+
+
+
+
+ info[:disciplina] = extrair_texto_de_bloco(info_disciplina[0], '^\s+\S+ - (.+)+ -')
+
+
+
+
+
+ 914
+
+
+
+
+ info[:cod_disciplina] = extrair_texto_de_bloco(info_disciplina[0], '^\s+CIC(\S+) -').to_i
+
+
+
+
+
+ 914
+
+
+
+
+ info[:codigo_turma] = extrair_texto_de_bloco(info_disciplina[1], '^\s+(\S+)\s')
+
+
+
+
+
+ 914
+
+
+
+
+ info[:situacao] = extrair_texto_de_bloco(info_disciplina[2], '<td>\s+(.+?)\s+<\/td>')
+
+
+
+
+
+ 914
+
+
+
+
+ return info
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def buscar_nome_do_professor (info_professor, regex)
+
+
+
+
+
+
+
+
+
+
+ # professor = info_professor[0].css('i').to_s.match(/<i>(.+?) \(.+\)/)
+
+
+
+
+
+ 1828
+
+
+
+
+ professor = info_professor[0].css('i').to_s.match(/#{regex}/)
+
+
+
+
+
+ 1828
+
+
+
+
+ if (professor != nil)
+
+
+
+
+
+ 924
+
+
+
+
+ professor = professor[1] # Caso haja match, usamos a senteça que causou o primeiro match, a qual fica no índice 1 do objeto MatchData.
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+ 1828
+
+
+
+
+ return professor
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def extrair_info_de_professor (info_turma)
+
+
+
+
+
+ 914
+
+
+
+
+ info = Hash.new()
+
+
+
+
+
+ 914
+
+
+
+
+ info_professor = info_turma.at_css('tr.componentescur').next_element.css('td') # Pulamos as quatro primeiras rows na tabela
+
+
+
+
+
+ 914
+
+
+
+
+ info[:prof_principal] = buscar_nome_do_professor(info_professor, '<i>(.+?) \(.+\)')
+
+
+
+
+
+ 914
+
+
+
+
+ info[:prof_auxiliar] = buscar_nome_do_professor(info_professor, '<br>(.+?) \(.+\)')
+
+
+
+
+
+ 914
+
+
+
+
+ info[:reserva] = info_professor[1].css('i').to_s.match(/<i><?i?>?(.+?)\/?<\/i><?/)[1]
+
+
+
+
+
+
+
+
+
+
+ #turma[:prof_auxiliar] = infoProfessor[0].css('i').to_s.match(/<br>(.+?) \(.+\)/) # Espera-se que seja = nil se houver só um professor
+
+
+
+
+
+ 914
+
+
+
+
+ return info
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def extrair_info_de_todas_turmas (blocos_de_turma)
+
+
+
+
+
+ 2
+
+
+
+
+ lista_de_turmas = Array.new()
+
+
+
+
+
+ 2
+
+
+
+
+ blocos_de_turma.each do |bloco|
+
+
+
+
+
+ 914
+
+
+
+
+ turma = Hash.new()
+
+
+
+
+
+ 914
+
+
+
+
+ turma.merge!(extrair_info_de_disciplina(bloco))
+
+
+
+
+
+ 914
+
+
+
+
+ turma.merge!(extrair_info_de_professor(bloco))
+
+
+
+
+
+ 914
+
+
+
+
+ lista_de_turmas.append(turma)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+ 2
+
+
+
+
+ return lista_de_turmas
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def gerar_lista_de_turmas_a_partir_de_arquivo (uploaded_file)
+
+
+
+
+
+ 2
+
+
+
+
+ blocos_de_turma_html = parsear_arquivo_de_turmas(uploaded_file)
+
+
+
+
+
+ 2
+
+
+
+
+ lista_de_turmas = extrair_info_de_todas_turmas(blocos_de_turma_html)
+
+
+
+
+
+ 2
+
+
+
+
+ return lista_de_turmas
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def criar_registros_a_partir_de_info_importada(lista_de_turmas)
+
+
+
+
+
+ 2
+
+
+
+
+ lista_de_turmas.each do |hash|
+
+
+
+
+
+ 457
+
+
+
+
+ Professor.criar_professor_com_valores_padroes(hash[:prof_principal])
+
+
+
+
+
+ 457
+
+
+
+
+ Professor.criar_professor_com_valores_padroes(hash[:prof_auxiliar])
+
+
+
+
+
+ 457
+
+
+
+
+ Disciplina.criar_disciplina_com_valores_padroes(hash)
+
+
+
+
+
+ 457
+
+
+
+
+ Turma.criar_turma_a_partir_de_parametros(hash)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class DadosBancariosController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :user_logged
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def new; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @dados_bancarios = DadosBancarios.create(dados_bancarios_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@dados_bancarios.errors.any?
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ @fk_banco = DadosBancarios.find_by(
+
+
+
+
+
+
+
+
+
+
+ codigo: @dados_bancarios.codigo,
+
+
+
+
+
+
+
+
+
+
+ agencia: @dados_bancarios.agencia,
+
+
+
+
+
+
+
+
+
+
+ conta_corrente: @dados_bancarios.conta_corrente
+
+
+
+
+
+
+
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+ @user.update(fk_banco: @fk_banco.id)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Dados bancários cadastrados com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @dados_bancarios.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_dados_bancarios_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ @dados_bancarios = DadosBancarios.find(@user.fk_banco)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ @dados_bancarios = DadosBancarios.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @dados_bancarios.update_attributes(dados_bancarios_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@dados_bancarios.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Dados atualizados com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ elsif
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @dados_bancarios.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_dados_bancarios_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ @dados_bancarios = DadosBancarios.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @dados_bancarios.delete
+
+
+
+
+
+
+
+
+
+
+ @user.update(fk_banco: nil)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Dados bancários apagados com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_dados_bancarios_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ def user_logged
+
+
+
+
+
+
+
+
+
+
+ if !logged_in?
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_session_path, notice: "Você precisa estar logado para acessar essa página"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def dados_bancarios_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:dados_bancarios).permit(:codigo, :agencia, :conta_corrente)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class DashboardController < ApplicationController
+
+
+
+
+
+ 1
+
+
+
+
+ include TurmasParser
+
+
+
+
+
+ 1
+
+
+
+
+ before_action :user_logged
+
+
+
+
+
+ 1
+
+
+
+
+ def index; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def edit_user
+
+
+
+
+
+ 3
+
+
+
+
+ if current_user.kind_of?(User)
+
+
+
+
+
+ 1
+
+
+
+
+ @user = current_user
+
+
+
+
+
+ 2
+
+
+
+
+ elsif current_user.kind_of?(Professor)
+
+
+
+
+
+ 1
+
+
+
+
+ @professor = current_user
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+ 1
+
+
+
+
+ flash[:danger] = "Apenas alunos e professores podem editar o perfil!"
+
+
+
+
+
+ 1
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def dados_bancarios; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def turmas; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método chama a view dashboard/atendimentos para renderizar todos os atendimentos
+
+
+
+
+
+ 1
+
+
+
+
+ def atendimentos; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def atividades; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def monitorias
+
+
+
+
+
+ 2
+
+
+
+
+ @user = current_user
+
+
+
+
+
+ 2
+
+
+
+
+ @monitorias = Array.new
+
+
+
+
+
+ 2
+
+
+
+
+ Monitoria.find_each do |m|
+
+
+
+
+
+ 2
+
+
+
+
+ if @user.kind_of?(User)
+
+
+
+
+
+
+
+
+
+
+ if m.fk_matricula == @user.matricula
+
+
+
+
+
+
+
+
+
+
+ if m.fk_status_monitoria_id != 4
+
+
+
+
+
+
+
+
+
+
+ @monitorias << m
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def disciplinas
+
+
+
+
+
+ 1
+
+
+
+
+ @disciplinas = Disciplina.find_each
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def apagar_alunos
+
+
+
+
+
+ 2
+
+
+
+
+ @users = User.order(:matricula)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def historico
+
+
+
+
+
+ 2
+
+
+
+
+ @user = current_user
+
+
+
+
+
+ 2
+
+
+
+
+ @mostrar = Array.new
+
+
+
+
+
+ 2
+
+
+
+
+ Monitoria.find_each do |m|
+
+
+
+
+
+ 3
+
+
+
+
+ if (@user.kind_of?(User) && m.fk_matricula == @user.matricula && m.fk_status_monitoria_id == 4)
+
+
+
+
+
+
+
+
+
+
+ @mostrar << m
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def deletar_aluno
+
+
+
+
+
+ 8
+
+
+
+
+ @matricula = params[:user][:matricula]
+
+
+
+
+
+ 8
+
+
+
+
+ if @matricula.length == 0
+
+
+
+
+
+ 1
+
+
+
+
+ @matricula = nil
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+ 8
+
+
+
+
+ @user = User.find_by_matricula(@matricula)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+ if !@user.nil?
+
+
+
+
+
+ 6
+
+
+
+
+ @dados_bancarios = DadosBancarios.where(id: @user.fk_banco)
+
+
+
+
+
+ 6
+
+
+
+
+ if !@dados_bancarios.nil?
+
+
+
+
+
+ 6
+
+
+
+
+ DadosBancarios.delete(@dados_bancarios)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 6
+
+
+
+
+ @monitoria = Monitoria.where(fk_matricula: @user.matricula)
+
+
+
+
+
+ 6
+
+
+
+
+ if !@monitoria.nil?
+
+
+
+
+
+ 6
+
+
+
+
+ Monitoria.delete(@monitoria)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 6
+
+
+
+
+ @user = User.delete(@user.id)
+
+
+
+
+
+ 6
+
+
+
+
+ flash[:notice] = 'Aluno apagado com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+ 2
+
+
+
+
+ if !@matricula.nil?
+
+
+
+
+
+ 1
+
+
+
+
+ flash[:danger] = "Aluno de matrícula #{@matricula} não existe."
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+ 1
+
+
+
+
+ flash[:danger] = "Digite uma matrícula para deletar algum aluno."
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8
+
+
+
+
+ redirect_to dashboard_apagar_alunos_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def importar_disciplinas
+
+
+
+
+
+ 1
+
+
+
+
+ @disciplinas = Disciplina.all
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def raspar_disciplinas
+
+
+
+
+
+ 4
+
+
+
+
+ arquivo = params[:arquivo_turmas]
+
+
+
+
+
+ 4
+
+
+
+
+ if (arquivo == nil)
+
+
+
+
+
+ 1
+
+
+
+
+ raise "Por favor, selecionar um arquivo"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+ 3
+
+
+
+
+ array_de_turmas = gerar_lista_de_turmas_a_partir_de_arquivo(arquivo)
+
+
+
+
+
+ 3
+
+
+
+
+ criar_registros_a_partir_de_info_importada(array_de_turmas)
+
+
+
+
+
+ 2
+
+
+
+
+ flash[:notice] = "Disciplinas importadas com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ rescue StandardError => error
+
+
+
+
+
+ 2
+
+
+
+
+ flash[:danger] = error.message
+
+
+
+
+
+
+
+
+
+
+ ensure
+
+
+
+
+
+ 4
+
+
+
+
+ redirect_to dashboard_importar_disciplinas_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def importar_professores
+
+
+
+
+
+ 1
+
+
+
+
+ @teachers = Professor.all
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def scrape_professores
+
+
+
+
+
+ 1
+
+
+
+
+ web_scraper
+
+
+
+
+
+ 1
+
+
+
+
+ redirect_to dashboard_importar_professores_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ private
+
+
+
+
+
+ 1
+
+
+
+
+ def user_logged
+
+
+
+
+
+ 2
+
+
+
+
+ if !logged_in?
+
+
+
+
+
+ 2
+
+
+
+
+ redirect_to new_session_path, notice: "Você precisa estar logado para acessar essa página"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método que faz a requisição da página das disciplinas.
+
+
+
+
+
+
+
+
+
+
+ #
+
+
+
+
+
+
+
+
+
+
+ # Retorna uma lista de hashes com os dados das disciplinas.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def raspar_matriculaweb_disciplinas(url = "https://matriculaweb.unb.br/graduacao/oferta_dis.aspx?cod=116")
+
+
+
+
+
+
+
+
+
+
+ require 'open-uri'
+
+
+
+
+
+
+
+
+
+
+ require 'openssl'
+
+
+
+
+
+
+
+
+
+
+ require 'nokogiri'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pagina = Nokogiri::HTML(open(url))
+
+
+
+
+
+
+
+
+
+
+ tbls_disciplinas = pagina.css('#datatable').css('tr').drop(1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disciplinas = []
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ tbls_disciplinas.each do |d|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disciplinas << extrai_campos_disciplina(d)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disciplinas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método que realiza as extrações dos dados da disciplina.
+
+
+
+
+
+
+
+
+
+
+ # Retorna um hash com as informações da disciplina.
+
+
+
+
+
+ 1
+
+
+
+
+ def extrai_campos_disciplina(node)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ link_disciplina = node.css('td')[1].css('a')[0][:href]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ info_disciplina = raspar_pagina_disciplina(caminho = link_disciplina)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+
+
+
+
+
+
+
+
+ :cod_disciplina => node.css('td')[0].text,
+
+
+
+
+
+
+
+
+
+
+ :nome_disciplina => node.css('td')[1].text.titleize,
+
+
+
+
+
+
+
+
+
+
+ :creditos => info_disciplina[:creditos],
+
+
+
+
+
+
+
+
+
+
+ :turmas => info_disciplina[:turmas]
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método para fazer a requisição da página da oferta de uma disciplina específica.
+
+
+
+
+
+
+
+
+
+
+ # Retorna um hash com as informações de créditos e turmas das disciplinas.
+
+
+
+
+
+ 1
+
+
+
+
+ def raspar_pagina_disciplina(caminho, url_base = "https://matriculaweb.unb.br/graduacao/")
+
+
+
+
+
+
+
+
+
+
+ require 'open-uri'
+
+
+
+
+
+
+
+
+
+
+ require 'openssl'
+
+
+
+
+
+
+
+
+
+
+ require 'nokogiri'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pagina = Nokogiri::HTML(open(url_base + caminho))
+
+
+
+
+
+
+
+
+
+
+ tabelas = pagina.css('#datatable')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ c_teor, c_prat, c_ext, c_est = tabelas[0]
+
+
+
+
+
+
+
+
+
+
+ .css('tr:nth-child(4) > td')
+
+
+
+
+
+
+
+
+
+
+ .text.split('-').map {|str| str.to_i}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+
+
+
+
+
+
+
+
+ :creditos => {
+
+
+
+
+
+
+
+
+
+
+ :c_prat => c_prat,
+
+
+
+
+
+
+
+
+
+
+ :c_teor => c_teor,
+
+
+
+
+
+
+
+
+
+
+ :c_est => c_est,
+
+
+
+
+
+
+
+
+
+
+ :c_ext => c_ext
+
+
+
+
+
+
+
+
+
+
+ },
+
+
+
+
+
+
+
+
+
+
+ :turmas => extrai_turmas(tabelas)
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método para raspagem das turmas da disciplina.
+
+
+
+
+
+
+
+
+
+
+ # Retorna uma lista de hashes das turmas.
+
+
+
+
+
+ 1
+
+
+
+
+ def extrai_turmas(node)
+
+
+
+
+
+
+
+
+
+
+ turmas = []
+
+
+
+
+
+
+
+
+
+
+ node.drop(1).each do |t|
+
+
+
+
+
+
+
+
+
+
+ turmas << extrai_campos_turma(t)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ turmas
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método para extração das informações da turma da página da oferta da
+
+
+
+
+
+
+
+
+
+
+ # disciplina no MatrículoWeb.
+
+
+
+
+
+
+
+
+
+
+ # Retorna um hash com nome da turma e nome do professor.
+
+
+
+
+
+ 1
+
+
+
+
+ def extrai_campos_turma(node)
+
+
+
+
+
+
+
+
+
+
+ {
+
+
+
+
+
+
+
+
+
+
+ :nome_turma => node.css('td.turma').text,
+
+
+
+
+
+
+
+
+
+
+ :nome_professor => node.css('tbody > tr > td:nth-child(5) td').text
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método para carregar as disciplinas no modelo.
+
+
+
+
+
+ 1
+
+
+
+
+ def carregar_disciplinas(disciplinas)
+
+
+
+
+
+
+
+
+
+
+ disciplinas.each do |d|
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !Disciplina.find_by_cod_disciplina(d[:cod_disciplina])
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ criar_disciplina(
+
+
+
+
+
+
+
+
+
+
+ d[:cod_disciplina],
+
+
+
+
+
+
+
+
+
+
+ d[:nome_disciplina],
+
+
+
+
+
+
+
+
+
+
+ d[:creditos]
+
+
+
+
+
+
+
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Método para criar uma disciplina no modelo.
+
+
+
+
+
+ 1
+
+
+
+
+ def criar_disciplina(cod_disciplina, nome, creditos)
+
+
+
+
+
+
+
+
+
+
+ Disciplina.create(
+
+
+
+
+
+
+
+
+
+
+ :cod_disciplina => cod_disciplina,
+
+
+
+
+
+
+
+
+
+
+ :nome => nome,
+
+
+
+
+
+
+
+
+
+
+ :c_prat => creditos[:c_prat],
+
+
+
+
+
+
+
+
+
+
+ :c_teor => creditos[:c_teor],
+
+
+
+
+
+
+
+
+
+
+ :c_est => creditos[:c_est],
+
+
+
+
+
+
+
+
+
+
+ :c_ext => creditos[:c_ext]
+
+
+
+
+
+
+
+
+
+
+ )
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Faz um web scrape da página do CIC para adquirir os dados dos professores e cadastrá-los no BD
+
+
+
+
+
+ 1
+
+
+
+
+ def web_scraper
+
+
+
+
+
+
+
+
+
+
+ # Habilitam a abertura de webpages no código
+
+
+
+
+
+ 1
+
+
+
+
+ require 'open-uri'
+
+
+
+
+
+ 1
+
+
+
+
+ require 'openssl'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Cria um node a partir da página do CIC, filtrando pela 'div' em questão os elementos 'li'. Esse node contém todas
+
+
+
+
+
+
+
+
+
+
+ # as informações disponíveis de todos os professores
+
+
+
+
+
+ 1
+
+
+
+
+ teachers_list = Nokogiri::HTML(open('https://cic.unb.br/professores/',
+
+
+
+
+
+
+
+
+
+
+ :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE)).
+
+
+
+
+
+
+
+
+
+
+ css('div#main-content').
+
+
+
+
+
+
+
+
+
+
+ css('li')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ teachers_list.each do |t|
+
+
+
+
+
+ 87
+
+
+
+
+ email = t.css('span.p-email').text.reverse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Verifica se o e-mail pertence ao domínio da UnB e se o e-mail já está cadastrado no banco de dados
+
+
+
+
+
+ 87
+
+
+
+
+ if valid_email?(email) && !Professor.find_by_email(email)
+
+
+
+
+
+ 50
+
+
+
+
+ create_teacher(t, email)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Verifica se o e-mail pertence ao domínio da UnB (retorna 'true' se sim e 'false', caso contrário)
+
+
+
+
+
+ 1
+
+
+
+
+ def valid_email?(email)
+
+
+
+
+
+ 87
+
+
+
+
+ email =~ /\A[\w+\-.]+@unb\.br\z/i
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Cadastra um professor no banco de dados
+
+
+
+
+
+ 1
+
+
+
+
+ def create_teacher(teacher, email)
+
+
+
+
+
+ 50
+
+
+
+
+ pwd = generate_password
+
+
+
+
+
+ 50
+
+
+
+
+ Professor.create(:name => teacher.css('h4.people-details-h4').text.match(/(\S+\.?\s?)+/),
+
+
+
+
+
+
+
+
+
+
+ :email => email,
+
+
+
+
+
+
+
+
+
+
+ :username => email.match(/[^@]+/),
+
+
+
+
+
+
+
+
+
+
+ :role => match_role(teacher.css('span.people-details.p-people').text),
+
+
+
+
+
+
+
+
+
+
+ :password => pwd,
+
+
+
+
+
+
+
+
+
+
+ :password_confirmation => pwd)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Gera uma string de caracteres aleatórios de tamanho adequado para salvar como senha do professor no BD.
+
+
+
+
+
+
+
+
+
+
+ # Essa senha é apenas um placeholder, durante o cadastro, o professor deverá modifica-la.
+
+
+
+
+
+ 1
+
+
+
+
+ def generate_password
+
+
+
+
+
+ 50
+
+
+
+
+ require 'securerandom'
+
+
+
+
+
+ 50
+
+
+
+
+ SecureRandom.base64(9)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Faz o match da titularidade do professor com o número esperado no BD
+
+
+
+
+
+ 1
+
+
+
+
+ def match_role(role)
+
+
+
+
+
+ 50
+
+
+
+
+ case role
+
+
+
+
+
+
+
+
+
+
+ when /substituto/i
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+
+ when /colaborador/i
+
+
+
+
+
+ 2
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+ when /adjunto/i
+
+
+
+
+
+ 34
+
+
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+ when /associado/i
+
+
+
+
+
+ 9
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+
+ when /titular/i
+
+
+
+
+
+ 4
+
+
+
+
+ 6
+
+
+
+
+
+
+
+
+
+
+ # Cláusula específica para um erro comum do parser: retornar uma string contendo apenas caracteres de espaço
+
+
+
+
+
+
+
+
+
+
+ when /\A\s/
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+ # Cláusula padrão retorna um valor para cadastrar o professor com o papel de 'professor' no BD
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+ 1
+
+
+
+
+ 2
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class DisciplinasController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :find_disciplina, only: [:show, :edit, :update, :destroy]
+
+
+
+
+
+
+
+
+
+
+ before_action :is_admin, only: [:edit, :new, :create, :update, :destroy]
+
+
+
+
+
+
+
+
+
+
+ before_action :logged_in
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @disciplina = Disciplina.new
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @disciplina = Disciplina.new disciplina_params
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if @disciplina.save
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_disciplinas_path, notice: "Disciplina cadastrada com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Ocorreu um erro ao cadastrar a disciplina. Nenhuma disciplina cadastrada."
+
+
+
+
+
+
+
+
+
+
+ render 'new'
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def edit; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def show
+
+
+
+
+
+
+
+
+
+
+ @turmas = Turma.where(fk_cod_disciplina: params[:id])
+
+
+
+
+
+
+
+
+
+
+ @disciplina = params[:nome]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ if @disciplina.update disciplina_params
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_disciplinas_path, notice: "Disciplina atualizada!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ render 'edit'
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ Turma.find_each do |t|
+
+
+
+
+
+
+
+
+
+
+ if t.fk_cod_disciplina == @disciplina.cod_disciplina
+
+
+
+
+
+
+
+
+
+
+ t.destroy
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ Monitoria.find_each do |m|
+
+
+
+
+
+
+
+
+
+
+ if m.fk_cod_disciplina == @disciplina.cod_disciplina
+
+
+
+
+
+
+
+
+
+
+ m.destroy
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ @disciplina.destroy
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_disciplinas_path, notice: "Disciplina removida!"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ def disciplina_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:disciplina).permit(:nome, :fk_tipo_disciplina_id, :c_prat, :c_teor, :c_est, :c_ext)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def find_disciplina
+
+
+
+
+
+
+
+
+
+
+ @disciplina = Disciplina.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def logged_in
+
+
+
+
+
+
+
+
+
+
+ if !logged_in?
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_session_path, notice: "Você precisa estar logado para acessar as Disciplinas"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def is_admin
+
+
+
+
+
+
+
+
+
+
+ if !current_user.kind_of?(Admin)
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Acesso negado."
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_disciplinas_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class FaqController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ def index ; end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class HistoricoController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class HomeController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ def index ; end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class MonitoriasController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :find_monitor, only: [:show]
+
+
+
+
+
+
+
+
+
+
+ before_action :find_monitoria, only: [:destroy, :edit, :update]
+
+
+
+
+
+
+
+
+
+
+ before_action :logged_in
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @cod_disciplina = params[:turma]
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @monitoria = Monitoria.new(monitoria_params)
+
+
+
+
+
+
+
+
+
+
+ valid = true
+
+
+
+
+
+
+
+
+
+
+ Monitoria.find_each do |m|
+
+
+
+
+
+
+
+
+
+
+ if m.fk_matricula==@monitoria.fk_matricula and m.fk_turmas_id==@monitoria.fk_turmas_id and m.fk_cod_disciplina==@monitoria.fk_cod_disciplina
+
+
+
+
+
+
+
+
+
+
+ valid = false
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if valid and @monitoria.save
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path, notice: "Aplicaçao para monitoria enviada com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Ocorreu um erro ao cadastrar a monitoria. Nenhuma monitoria cadastrada."
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def show
+
+
+
+
+
+
+
+
+
+
+ @alunos = User.find_each
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ if @monitoria.update monitoria_params
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path, notice: "Situaçao atualizada!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ render 'edit'
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @monitoria.destroy
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path, notice: "Monitoria removida!"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ def monitoria_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:monitoria).permit(:remuneracao, :fk_matricula, :fk_cod_disciplina, :fk_turmas_id, :descricao_status, :prioridade, :fk_status_monitoria_id)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def find_monitor
+
+
+
+
+
+
+
+
+
+
+ @monitoria = Monitoria.where(fk_turmas_id: params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def find_monitoria
+
+
+
+
+
+
+
+
+
+
+ @monitoria = Monitoria.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def logged_in
+
+
+
+
+
+
+
+
+
+
+ if !logged_in?
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_session_path, notice: "Você precisa estar logado para acessar a pagina Monitoria"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class MotivosController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :set_motivo, only: [:show, :edit, :update, :destroy]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /motivos
+
+
+
+
+
+
+
+
+
+
+ # GET /motivos.json
+
+
+
+
+
+
+
+
+
+
+ def index
+
+
+
+
+
+
+
+
+
+
+ @motivos = Motivo.all
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /motivos/1
+
+
+
+
+
+
+
+
+
+
+ # GET /motivos/1.json
+
+
+
+
+
+
+
+
+
+
+ def show
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /motivos/new
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @motivo = Motivo.new
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /motivos/1/edit
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # POST /motivos
+
+
+
+
+
+
+
+
+
+
+ # POST /motivos.json
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @motivo = Motivo.new(motivo_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ respond_to do |format|
+
+
+
+
+
+
+
+
+
+
+ if @motivo.save
+
+
+
+
+
+
+
+
+
+
+ format.html { redirect_to @motivo, notice: 'Motivo was successfully created.' }
+
+
+
+
+
+
+
+
+
+
+ format.json { render :show, status: :created, location: @motivo }
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ format.html { render :new }
+
+
+
+
+
+
+
+
+
+
+ format.json { render json: @motivo.errors, status: :unprocessable_entity }
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /motivos/1
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /motivos/1.json
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ respond_to do |format|
+
+
+
+
+
+
+
+
+
+
+ if @motivo.update(motivo_params)
+
+
+
+
+
+
+
+
+
+
+ format.html { redirect_to @motivo, notice: 'Motivo was successfully updated.' }
+
+
+
+
+
+
+
+
+
+
+ format.json { render :show, status: :ok, location: @motivo }
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ format.html { render :edit }
+
+
+
+
+
+
+
+
+
+
+ format.json { render json: @motivo.errors, status: :unprocessable_entity }
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # DELETE /motivos/1
+
+
+
+
+
+
+
+
+
+
+ # DELETE /motivos/1.json
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @motivo.destroy
+
+
+
+
+
+
+
+
+
+
+ respond_to do |format|
+
+
+
+
+
+
+
+
+
+
+ format.html { redirect_to motivos_url, notice: 'Motivo was successfully destroyed.' }
+
+
+
+
+
+
+
+
+
+
+ format.json { head :no_content }
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ # Use callbacks to share common setup or constraints between actions.
+
+
+
+
+
+
+
+
+
+
+ def set_motivo
+
+
+
+
+
+
+
+
+
+
+ @motivo = Motivo.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+
+
+
+
+
+
+
+
+
+
+ def motivo_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:motivo).permit(:nome)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class ProfessorsController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # usando como pagina de selecao de professores (issue: select de professores)
+
+
+
+
+
+
+
+
+
+
+ def index
+
+
+
+
+
+
+
+
+
+
+ # conteudo do select de professores
+
+
+
+
+
+
+
+
+
+
+ @professor = Professor.all
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def new ; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @professor = Professor.create(professor_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@professor.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "Registro realizado com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ log_in(@professor)
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @professor.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_professor_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ # usando como pagina de confirmacao dos professores
+
+
+
+
+
+
+
+
+
+
+ def identityconfirmation
+
+
+
+
+
+
+
+
+
+
+ # procura o professor selecionado na lista
+
+
+
+
+
+
+
+
+
+
+ @professor = Professor.where(:name => params[:professor][:name])[0]
+
+
+
+
+
+
+
+
+
+
+ # faz o envio do e-mail de confirmação para o respectivo professor
+
+
+
+
+
+
+
+
+
+
+ ProfessorMailer.with(professor: @professor).key_email.deliver_now
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ @professor = Professor.find_by_email(session[:user_id])
+
+
+
+
+
+
+
+
+
+
+ @professor.update_attributes(professor_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@professor.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "Cadastro atualizado com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ elsif
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @professor.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ protected
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def professor_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:professor).permit(:id, :name, :username, :email, :role, :password, :password_confirmation)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class ResetSenhasController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :get_user, only: [:edit, :update]
+
+
+
+
+
+
+
+
+
+
+ before_action :valid_user, only: [:edit, :update]
+
+
+
+
+
+
+
+
+
+
+ before_action :check_expiration, only: [:edit, :update]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @user = User.find_by(email: params[:reset_senha][:email].downcase)
+
+
+
+
+
+
+
+
+
+
+ if @user
+
+
+
+
+
+
+
+
+
+
+ @user.create_reset_digest
+
+
+
+
+
+
+
+
+
+
+ @user.send_password_reset_email
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "As instruções para resetar sua senha foram enviadas para seu e-mail."
+
+
+
+
+
+
+
+
+
+
+ redirect_to root_url
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash.now[:danger] = "Seu e-mail não foi encontrado."
+
+
+
+
+
+
+
+
+
+
+ render 'new'
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ if params[:user][:password].empty?
+
+
+
+
+
+
+
+
+
+
+ @user.errors.add(:password, "O campo senha deve ser preenchido.")
+
+
+
+
+
+
+
+
+
+
+ render 'edit'
+
+
+
+
+
+
+
+
+
+
+ elsif @user.update_attributes(user_params)
+
+
+
+
+
+
+
+
+
+
+ log_in @user
+
+
+
+
+
+
+
+
+
+
+ flash[:success] = "Sua nova senha foi salva."
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ render 'edit'
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Instancia o usuário em questão procurando por seu e-mail
+
+
+
+
+
+
+
+
+
+
+ def get_user
+
+
+
+
+
+
+
+
+
+
+ @user = User.find_by(email: params[:email])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Confirma se o usuário instanciado acima é válido verificando o token que foi passado
+
+
+
+
+
+
+
+
+
+
+ def valid_user
+
+
+
+
+
+
+
+
+
+
+ unless @user && @user.authenticated?(:reset, params[:id])
+
+
+
+
+
+
+
+
+
+
+ redirect_to root_url
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Verifica se o token em questão expirou
+
+
+
+
+
+
+
+
+
+
+ def check_expiration
+
+
+
+
+
+
+
+
+
+
+ if @user.password_reset_expired?
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Password reset has expired."
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_reset_senha_url
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Filtra os parâmetros que serão passados para o BD
+
+
+
+
+
+
+
+
+
+
+ def user_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:user).permit(:password, :password_confirmation)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class SessionsController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ def new ; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ ## Busca aluno e professor. Retorna apenas um que for encontrado.
+
+
+
+
+
+
+
+
+
+
+ @login ||= User.find_by_email(login_params[:email]) ||
+
+
+
+
+
+
+
+
+
+
+ Professor.find_by_email(login_params[:email]) ||
+
+
+
+
+
+
+
+
+
+
+ Admin.find_by_email(login_params[:email])
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if @login&.authenticate(login_params[:password])
+
+
+
+
+
+
+
+
+
+
+ log_in(@login)
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Email ou senha inválidos"
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_session_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ session[:user_id] = nil
+
+
+
+
+
+
+
+
+
+
+ redirect_to root_url
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ## Define os parâmetros que serão lidos no formulário de login
+
+
+
+
+
+
+
+
+
+
+ def login_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:user).permit(:email, :password)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class SobreController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ def index ; end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class TarefasController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ before_action :set_tarefa, only: [:show, :edit, :update, :destroy]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /tarefas
+
+
+
+
+
+
+
+
+
+
+ # GET /tarefas.json
+
+
+
+
+
+
+
+
+
+
+ def index
+
+
+
+
+
+
+
+
+
+
+ @tarefas = []
+
+
+
+
+
+
+
+
+
+
+ @monitoria_id = params[:monitoria_id].to_i
+
+
+
+
+
+
+
+
+
+
+ @all_tarefas = Tarefa.all
+
+
+
+
+
+
+
+
+
+
+ @all_tarefas.each do |tarefa|
+
+
+
+
+
+
+
+
+
+
+ if tarefa.monitoria_id == @monitoria_id
+
+
+
+
+
+
+
+
+
+
+ @tarefas.push(tarefa)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /tarefas/1
+
+
+
+
+
+
+
+
+
+
+ # GET /tarefas/1.json
+
+
+
+
+
+
+
+
+
+
+ def show
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /tarefas/new
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @monitoria_id = params[:monitoria_id]
+
+
+
+
+
+
+
+
+
+
+ @tarefa = Tarefa.new(:monitoria_id => @monitoria_id)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # GET /tarefas/1/edit
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # POST /tarefas
+
+
+
+
+
+
+
+
+
+
+ # POST /tarefas.json
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @tarefa = Tarefa.new(tarefa_params)
+
+
+
+
+
+
+
+
+
+
+ if @tarefa.save
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path, notice: "Tarefa atribuida com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Ocorreu um erro ao atribuir a tarefa."
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /tarefas/1
+
+
+
+
+
+
+
+
+
+
+ # PATCH/PUT /tarefas/1.json
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ if @tarefa.update(tarefa_params)
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path, notice: "Tarefa atualizada!"
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = "Ocorreu um erro ao atualizar a tarefa."
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # DELETE /tarefas/1
+
+
+
+
+
+
+
+
+
+
+ # DELETE /tarefas/1.json
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @tarefa.destroy
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_monitorias_path, notice: "Tarefa removida!"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ # Use callbacks to share common setup or constraints between actions.
+
+
+
+
+
+
+
+
+
+
+ def set_tarefa
+
+
+
+
+
+
+
+
+
+
+ @tarefa = Tarefa.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+
+
+
+
+
+
+
+
+
+
+ def tarefa_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:tarefa).permit(:titulo, :descricao, :nota, :feito, :inicio, :fim, :monitoria_id)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class TurmasController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ # GET #new
+
+
+
+
+
+
+
+
+
+
+ def new
+
+
+
+
+
+
+
+
+
+
+ @user = current_user
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def edit
+
+
+
+
+
+
+
+
+
+
+ @turma = Turma.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @turma = Turma.create(turma_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@turma.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Turma cadastrada com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @turma.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_turmas_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ @turma = Turma.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ @turma.update_attributes(turma_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@turma.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Turma atualizada com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @turma.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_turmas_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def destroy
+
+
+
+
+
+
+
+
+
+
+ @turma = Turma.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ Monitoria.find_each do |m|
+
+
+
+
+
+
+
+
+
+
+ if m.fk_turmas_id == @turma.id
+
+
+
+
+
+
+
+
+
+
+ m.destroy
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ @turma.destroy
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = 'Turma apagada com sucesso!'
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_turmas_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ def turma_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:turma).permit(:id, :turma, :professor, :fk_cod_disciplina, :qnt_bolsas, :fk_vagas_id)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def find_turma
+
+
+
+
+
+
+
+
+
+
+ @turma = Turma.find(params[:id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def self.get_turmas(professor)
+
+
+
+
+
+
+
+
+
+
+ @turmas = Array.new
+
+
+
+
+
+
+
+
+
+
+ @turmas_buscadas = Turma.find_each do |turma|
+
+
+
+
+
+
+
+
+
+
+ if turma.professor == professor.name
+
+
+
+
+
+
+
+
+
+
+ @turmas << turma
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ @turmas
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class UsersController < ApplicationController
+
+
+
+
+
+
+
+
+
+
+ ## GET /users/new
+
+
+
+
+
+
+
+
+
+
+ def new ; end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ## POST /users/sign_up
+
+
+
+
+
+
+
+
+
+
+ def create
+
+
+
+
+
+
+
+
+
+
+ @user = User.create(user_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@user.errors.any?
+
+
+
+
+
+
+
+
+
+
+ log_in(@user)
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "Registro realizado com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ else
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @user.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ redirect_to new_user_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ def update
+
+
+
+
+
+
+
+
+
+
+ @user = User.find_by_email(session[:user_id])
+
+
+
+
+
+
+
+
+
+
+ @user.update_attributes(user_params)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if !@user.errors.any?
+
+
+
+
+
+
+
+
+
+
+ flash[:notice] = "Cadastro atualizado com sucesso!"
+
+
+
+
+
+
+
+
+
+
+ elsif
+
+
+
+
+
+
+
+
+
+
+ flash[:danger] = @user.errors.full_messages
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ redirect_to dashboard_path
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private
+
+
+
+
+
+
+
+
+
+
+ def user_params
+
+
+
+
+
+
+
+
+
+
+ params.require(:user).permit(:id, :name, :matricula, :email, :cpf, :rg, :password, :password_confirmation)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module ApplicationHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module AtendimentosHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module AtividadesHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module DisciplinasHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module HistoricoHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module HomeHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module MotivosHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module ResetSenhasHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module SessionsHelper
+
+
+
+
+
+ 1
+
+
+
+
+ def log_in(user)
+
+
+
+
+
+
+
+
+
+
+ session[:user_id] = user.email
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def logged_user
+
+
+
+
+
+ 2
+
+
+
+
+ if !current_user.nil?
+
+
+
+
+
+
+
+
+
+
+ current_user
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def current_user
+
+
+
+
+
+
+
+
+
+
+ ## Determina se o usuário logado é um aluno ou professor
+
+
+
+
+
+ 4
+
+
+
+
+ @current_user ||= User.find_by(email: session[:user_id]) || Professor.find_by(email: session[:user_id]) || Admin.find_by(email: session[:user_id])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def logged_in?
+
+
+
+
+
+ 2
+
+
+
+
+ !logged_user.nil?
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ module TarefasHelper
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class ApplicationJob < ActiveJob::Base
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class ApplicationMailer < ActionMailer::Base
+
+
+
+
+
+
+
+
+
+
+ default from: 'noreply@example.com' # TODO: mudar esse campo após definir o domínio utilizado pela plataforma
+
+
+
+
+
+
+
+
+
+
+ layout 'mailer'
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class ProfessorMailer < ApplicationMailer
+
+
+
+
+
+
+
+
+
+
+ default from: 'notifications@example.com'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # as configuracoes de envio de email de confirmacao para professores eh feita aqui
+
+
+
+
+
+
+
+
+
+
+ def key_email
+
+
+
+
+
+
+
+
+
+
+ @professor = params[:professor]
+
+
+
+
+
+
+
+
+
+
+ @url = 'http://localhost:3000/sessions/new'
+
+
+
+
+
+
+
+
+
+
+ mail(to: @professor.email, subject: 'Saudações querido(a) professor(a)!')
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class UserMailer < ApplicationMailer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Subject can be set in your I18n file at config/locales/en.yml
+
+
+
+
+
+
+
+
+
+
+ # with the following lookup:
+
+
+
+
+
+
+
+
+
+
+ #
+
+
+
+
+
+
+
+
+
+
+ # en.user_mailer.reset_senha.subject
+
+
+
+
+
+
+
+
+
+
+ #
+
+
+
+
+
+
+
+
+
+
+ def reset_senha(user)
+
+
+
+
+
+
+
+
+
+
+ @user = user
+
+
+
+
+
+
+
+
+
+
+ mail to: user.email, subject: "Recuperação de senha"
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class Admin < ActiveRecord::Base
+
+
+
+
+
+ 1
+
+
+
+
+ has_secure_password
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ self.primary_key = :id
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class ApplicationRecord < ActiveRecord::Base
+
+
+
+
+
+ 1
+
+
+
+
+ self.abstract_class = true
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class Atendimento < ApplicationRecord
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # Cada atendimento está associado à um monitor
+
+
+
+
+
+
+
+
+
+
+ belongs_to :motivo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ##
+
+
+
+
+
+
+
+
+
+
+ # atendimento possui os campos obrigatórios monitor_id, motivo_id e dia
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :monitor_id
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :motivo_id
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :dia
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class Atividade < ApplicationRecord
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ## Verifica se o formulário foi preenchido de acordo com a especificação
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :titulo, message: "Campo obrigatório 'Título' não preenchido! Registro não realizado."
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :mensagem, message: "Campo obrigatório 'Descrição' não preenchido! Registro não realizado."
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :data, message: "Campo obrigatório 'Data' não preenchido! Registro não realizado."
+
+
+
+
+
+
+
+
+
+
+ validates_presence_of :matricula_monitor, message: "Campo obrigatório 'Matrícula' não preenchido! Registro não realizado."
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class DadosBancarios < ActiveRecord::Base
+
+
+
+
+
+ 1
+
+
+
+
+ self.primary_key = :id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :codigo
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :agencia
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :conta_corrente
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates :codigo, length: { in: 6..25 }, format: {
+
+
+
+
+
+
+
+
+
+
+ without: /[\d]+|['"!¹@²#³$£%¢¨¬&\*\(\)\-_\+=§`´\[\]{}\^~ªº°\?\/:;>.<,\|\\]+/,
+
+
+
+
+
+
+
+
+
+
+ message: 'only letters and spaces'
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates :agencia, format: { with: /\A[\d]+\z/, message: "only numbers" }
+
+
+
+
+
+ 1
+
+
+
+
+ validates :conta_corrente, format: { with: /\A[\d]+\z/, message: "only numbers" }
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class Disciplina < ApplicationRecord
+
+
+
+
+
+ 1
+
+
+
+
+ def self.all_tipos
+
+
+
+
+
+
+
+
+
+
+ return [['Obrigatória', 1], ['Optativa', 2]]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.all_disciplinas
+
+
+
+
+
+
+
+
+
+
+ order(:nome).all
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :nome
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :fk_tipo_disciplina_id
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :c_prat
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :c_teor
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :c_est
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :c_ext
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :nome
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :cod_disciplina
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates :nome, format: { without: /['"!¹@²#³$£%¢¨¬&\*\(\)\-_\+=§`´\[\]{}\^~ªº°\?\/:;>.<,\|\\]+/, message: 'apenas letras, números e espaços'}
+
+
+
+
+
+ 1
+
+
+
+
+ validates :c_prat, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
+
+
+
+
+
+ 1
+
+
+
+
+ validates :c_teor, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
+
+
+
+
+
+ 1
+
+
+
+
+ validates :c_est, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
+
+
+
+
+
+ 1
+
+
+
+
+ validates :c_ext, format: { with: /\A[\d]+\z/, message: "apenas numeros" }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.criar_disciplina_com_valores_padroes (params)
+
+
+
+
+
+ 457
+
+
+
+
+ Disciplina.create([{nome: params[:disciplina],
+
+
+
+
+
+
+
+
+
+
+ fk_tipo_disciplina_id: 1, c_prat: 0, c_teor: 0,
+
+
+
+
+
+
+
+
+
+
+ cod_disciplina: params[:cod_disciplina]}])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class Monitoria < ApplicationRecord
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.all_disciplinas
+
+
+
+
+
+
+
+
+
+
+ @disciplinas = Array.new
+
+
+
+
+
+
+
+
+
+
+ Disciplina.find_each do |d|
+
+
+
+
+
+
+
+
+
+
+ @disciplinas << [d.nome, d.cod_disciplina]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ @disciplinas
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # def self.all_turmas
+
+
+
+
+
+
+
+
+
+
+ # @turmas = Array.new
+
+
+
+
+
+
+
+
+
+
+ # Turma.find_each do |t|
+
+
+
+
+
+
+
+
+
+
+ # @turmas << [t.turma, t.id]
+
+
+
+
+
+
+
+
+
+
+ # end
+
+
+
+
+
+
+
+
+
+
+ # @turmas
+
+
+
+
+
+
+
+
+
+
+ # end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.all_status
+
+
+
+
+
+
+
+
+
+
+ return [['Pendente', 1], ['Recusado', 2], ['Aceito', 3], ['Encerrado', 4]]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :remuneracao
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :fk_matricula
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :fk_cod_disciplina
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :fk_turmas_id
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :fk_status_monitoria_id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class Motivo < ApplicationRecord
+
+
+
+
+
+
+
+
+
+
+ #belongs_to:organization,:class_name=>'User',:foreign_key=>'user_id'
+
+
+
+
+
+
+
+
+
+
+ CLASS_LIST=["Duvida","Pergunta","Falar com o coordenador"]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # A classe Professor é responsável pelas regras de negócios relacionadas à entidade Professor.
+
+
+
+
+
+
+
+
+
+
+ # Para isso realiza operações na tabela Professor no banco de dados.
+
+
+
+
+
+ 1
+
+
+
+
+ class Professor < ActiveRecord::Base
+
+
+
+
+
+ 1
+
+
+
+
+ has_secure_password
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ self.primary_key = :id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.all_roles
+
+
+
+
+
+
+
+
+
+
+ return [['Professor(a) substituto(a)', 1], ['Professor(a)', 2], ['Professor(a) Colaborador(a)', 3],
+
+
+
+
+
+
+
+
+
+
+ ['Professor(a) Adjunto(a)', 4], ['Professor(a) Associado(a)', 5], ['Professor(a) Titular', 6]]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :name
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :username
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :email
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :username
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :email
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Verificação do nome
+
+
+
+
+
+ 1
+
+
+
+
+ validates :name, length: { in: 3..50 }, format: { without: /[\d]+|[!@#$%*\(\)\|\\;\:\/?\]\[=\+\-_",\.]+/,
+
+
+
+
+
+
+
+
+
+
+ message: "only letters and spaces" }
+
+
+
+
+
+
+
+
+
+
+ # Verificação do username
+
+
+
+
+
+ 1
+
+
+
+
+ validates :username, length: { in: 3..15 }, format: {
+
+
+
+
+
+
+
+
+
+
+ with: /\A[\w+]+\z/, message: "only word characters (letter, numbers, underscore...)" }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Verificação do email
+
+
+
+
+
+ 1
+
+
+
+
+ VALID_EMAIL_REGEX = /\A[\w+\-.]+@unb\.br\z/i
+
+
+
+
+
+ 1
+
+
+
+
+ validates :email, format: { with: VALID_EMAIL_REGEX, message: "not a UnB email" }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Verificação da senha e confirmação de senha
+
+
+
+
+
+ 1
+
+
+
+
+ validates :password, length: { in: 6..12, message: "must be between 6 and 12 characters" }, on: :create
+
+
+
+
+
+ 1
+
+
+
+
+ validates :password_confirmation, length: { in: 6..12, message: "must be between 6 and 12 characters" }, on: :create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.criar_professor_com_valores_padroes (nome_professor)
+
+
+
+
+
+ 914
+
+
+
+
+ if (!nome_professor.nil?)
+
+
+
+
+
+ 462
+
+
+
+
+ nome_formatado = nome_professor.split.map(&:capitalize).join(' ') # Transforme a primeira letra de cada nome em maiúscula
+
+
+
+
+
+ 462
+
+
+
+
+ usuario_padrao = nome_formatado.split.join('')[0...14]
+
+
+
+
+
+ 462
+
+
+
+
+ senha_padrao = '123456abc'
+
+
+
+
+
+ 462
+
+
+
+
+ role = 1
+
+
+
+
+
+ 462
+
+
+
+
+ Professor.create(name: nome_formatado, email: usuario_padrao + '@unb.br', username: usuario_padrao,
+
+
+
+
+
+
+
+
+
+
+ password: senha_padrao, password_confirmation: senha_padrao, role: role)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ class Tarefa < ApplicationRecord
+
+
+
+
+
+
+
+
+
+
+ belongs_to :monitoria
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # A classe Turma é responsável pelas regras de negócios relacionadas à entidade Turma.
+
+
+
+
+
+
+
+
+
+
+ # Para isso realiza operações na tabela Turma no banco de dados.
+
+
+
+
+
+ 1
+
+
+
+
+ class Turma < ActiveRecord::Base
+
+
+
+
+
+ 1
+
+
+
+
+ def self.qnt_bolsas
+
+
+
+
+
+
+
+
+
+
+ qnt_bolsas = []
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for index in 1..10
+
+
+
+
+
+
+
+
+
+
+ vaga = [index.to_s, index]
+
+
+
+
+
+
+
+
+
+
+ qnt_bolsas.insert(-1, vaga)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ return qnt_bolsas
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.sel_disciplinas
+
+
+
+
+
+
+
+
+
+
+ disciplinas = Disciplina.select('cod_disciplina', 'nome')
+
+
+
+
+
+
+
+
+
+
+ select = []
+
+
+
+
+
+
+
+
+
+
+ disciplinas.each do |disciplina|
+
+
+
+
+
+
+
+
+
+
+ select.insert(-1, [disciplina.nome, disciplina.cod_disciplina])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ return select
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.show_disciplinas
+
+
+
+
+
+
+
+
+
+
+ disciplinas = Disciplina.select('nome')
+
+
+
+
+
+
+
+
+
+
+ show = []
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ disciplinas.each do |disciplina|
+
+
+
+
+
+
+
+
+
+
+ show.insert(-1, disciplina.nome)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ return show
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.sel_turmas
+
+
+
+
+
+
+
+
+
+
+ [
+
+
+
+
+
+
+
+
+
+
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+
+
+
+
+
+
+
+
+
+
+ 'AA', 'BB', 'CC', 'DD', 'EE', 'FF', 'GG', 'HH'
+
+
+
+
+
+
+
+
+
+
+ ]
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.all_turmas
+
+
+
+
+
+
+
+
+
+
+ find_each()
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :turma
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :professor
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :fk_cod_disciplina
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :qnt_bolsas
+
+
+
+
+
+ 1
+
+
+
+
+ validate :turma_unica
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def turma_unica
+
+
+
+
+
+ 457
+
+
+
+
+ turmas = Turma.where(fk_cod_disciplina: fk_cod_disciplina)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 457
+
+
+
+
+ turmas.each do |elem|
+
+
+
+
+
+ 6078
+
+
+
+
+ if elem.turma == turma
+
+
+
+
+
+
+
+
+
+
+ errors.add(:turma, "#{turma} não é a única para a disciplina #{Disciplina.find(fk_cod_disciplina).nome}")
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def self.criar_turma_a_partir_de_parametros (params)
+
+
+
+
+
+ 457
+
+
+
+
+ if (Disciplina.exists?(nome: params[:disciplina]))
+
+
+
+
+
+ 457
+
+
+
+
+ disciplina_id = Disciplina.find_by(nome: params[:disciplina]).id
+
+
+
+
+
+ 457
+
+
+
+
+ Turma.create([{
+
+
+
+
+
+
+
+
+
+
+ fk_cod_disciplina: disciplina_id,
+
+
+
+
+
+
+
+
+
+
+ turma: params[:codigo_turma],
+
+
+
+
+
+
+
+
+
+
+ professor: params[:prof_principal],
+
+
+
+
+
+
+
+
+
+
+ professor_aux: params[:prof_auxiliar],
+
+
+
+
+
+
+
+
+
+
+ fk_vagas_id: 1
+
+
+
+
+
+
+
+
+
+
+ }])
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ class User < ActiveRecord::Base
+
+
+
+
+
+ 1
+
+
+
+
+ attr_accessor :remember_token, :reset_token
+
+
+
+
+
+ 1
+
+
+
+
+ has_secure_password
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ self.primary_key = :id
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ## Verifica se o formulário foi preenchido de acordo com a especificação
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :name
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :email
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :cpf
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :rg
+
+
+
+
+
+ 1
+
+
+
+
+ validates_presence_of :matricula
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ## Verifica se as informações não se repetem no Banco de Dados
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :email
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :cpf
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :rg
+
+
+
+
+
+ 1
+
+
+
+
+ validates_uniqueness_of :matricula
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ## Verifica se os campos tem o tamanho correto
+
+
+
+
+
+
+
+
+
+
+ # Verificação do nome
+
+
+
+
+
+ 1
+
+
+
+
+ validates :name, length: { in: 3..50 }, format: {
+
+
+
+
+
+
+
+
+
+
+ without: /[\d]+|['"!¹@²#³$£%¢¨¬&\*\(\)\-_\+=§`´\[\]{}\^~ªº°\?\/:;>.<,\|\\]+/,
+
+
+
+
+
+
+
+
+
+
+ message: 'only letters and spaces'
+
+
+
+
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+ # Verificação da matrícula
+
+
+
+
+
+ 1
+
+
+
+
+ validates :matricula, length: { is: 9 }, format: { with: /\A[\d]+\z/, message: "only numbers" }
+
+
+
+
+
+
+
+
+
+
+ # Verificação do email
+
+
+
+
+
+ 1
+
+
+
+
+ VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(?:\.[a-z\d\-]+)*\.[a-z]+\z/i
+
+
+
+
+
+ 1
+
+
+
+
+ validates :email, format: { with: VALID_EMAIL_REGEX, message: "invalid email format" }
+
+
+
+
+
+
+
+
+
+
+ # Verificação do CPF
+
+
+
+
+
+ 1
+
+
+
+
+ validates :cpf, length: { is: 11 }, format: { with: /\A[\d]+\z/, message: "only numbers" }
+
+
+
+
+
+ 1
+
+
+
+
+ validate :valid_cpf
+
+
+
+
+
+
+
+
+
+
+ # Verificação do RG
+
+
+
+
+
+ 1
+
+
+
+
+ validates :rg, length: { minimum: 7 }, format: { with: /\A[\d]+\z/, message: "only numbers" }
+
+
+
+
+
+
+
+
+
+
+ # Verificação da senha e confirmação de senha
+
+
+
+
+
+ 1
+
+
+
+
+ validates :password, length: { in: 6...12, message: "must be between 6 and 12 characters" }, on: :create
+
+
+
+
+
+ 1
+
+
+
+
+ validates :password_confirmation, length: { in: 6...12, message: "must be between 6 and 12 characters" }, on: :create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Cálculo de validação dp CPF
+
+
+
+
+
+ 1
+
+
+
+
+ def nth_validation_digit(cpf_array, digit)
+
+
+
+
+
+
+
+
+
+
+ @somatorio = 0
+
+
+
+
+
+
+
+
+
+
+ @aux = 0
+
+
+
+
+
+
+
+
+
+
+ @peso = 12-digit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ cpf_array.each do |value|
+
+
+
+
+
+
+
+
+
+
+ @somatorio += value*(@peso-(@aux))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @aux += 1
+
+
+
+
+
+
+
+
+
+
+ break if @aux == (11-digit)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ @validation_digit = 11-(@somatorio%11)
+
+
+
+
+
+
+
+
+
+
+ if @validation_digit > 9
+
+
+
+
+
+
+
+
+
+
+ @validation_digit = 0
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ return @validation_digit
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ def valid_cpf
+
+
+
+
+
+
+
+
+
+
+ @cpf_array = Array.new
+
+
+
+
+
+
+
+
+
+
+ for x in 0...(cpf.length)
+
+
+
+
+
+
+
+
+
+
+ @cpf_array[x] = cpf[x].to_i
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @first = nth_validation_digit(@cpf_array, 2) # Calcula o @first com base nos 9 digitos
+
+
+
+
+
+
+
+
+
+
+ @second = nth_validation_digit(@cpf_array, 1) # Calcula o @second com base nos 9 digitos + 1o validação
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if (cpf[9].to_i) != @first || (cpf[10].to_i) != @second
+
+
+
+
+
+
+
+
+
+
+ errors.add(:cpf, "is invalid")
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Retorna o digest de um hash de uma string passada para o método
+
+
+
+
+
+ 1
+
+
+
+
+ def User.digest(string)
+
+
+
+
+
+
+
+
+
+
+ cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
+
+
+
+
+
+
+
+
+
+
+ BCrypt::Engine.cost
+
+
+
+
+
+
+
+
+
+
+ BCrypt::Password.create(string, cost: cost)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Retorna um token aleatório
+
+
+
+
+
+ 1
+
+
+
+
+ def User.new_token
+
+
+
+
+
+
+
+
+
+
+ SecureRandom.urlsafe_base64
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Define os atributos para resetar a senha
+
+
+
+
+
+ 1
+
+
+
+
+ def create_reset_digest
+
+
+
+
+
+
+
+
+
+
+ self.reset_token = User.new_token
+
+
+
+
+
+
+
+
+
+
+ update_attribute(:reset_digest, User.digest(reset_token))
+
+
+
+
+
+
+
+
+
+
+ update_attribute(:reset_sent_at, Time.zone.now)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Envia o e-mail para resetar a senha
+
+
+
+
+
+ 1
+
+
+
+
+ def send_password_reset_email
+
+
+
+
+
+
+
+
+
+
+ UserMailer.reset_senha(self).deliver_now
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Retorna true se o parâmetro password reset expirou
+
+
+
+
+
+ 1
+
+
+
+
+ def password_reset_expired?
+
+
+
+
+
+
+
+
+
+
+ reset_sent_at < 2.hours.ago
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # Retorna true se o token passado é o mesmo que o digest armazenado no banco
+
+
+
+
+
+ 1
+
+
+
+
+ def authenticated?(attribute, token)
+
+
+
+
+
+
+
+
+
+
+ digest = send("#{attribute}_digest")
+
+
+
+
+
+
+
+
+
+
+ return false if digest.nil?
+
+
+
+
+
+
+
+
+
+
+ BCrypt::Password.new(digest).is_password?(token)
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+ end
+
+
+
+
+
+
+
+
+
+
+
+