Skip to content

Commit

Permalink
Improves calculating algorithm AS F***
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjaniec committed Jan 29, 2020
1 parent 5824bf7 commit d782442
Show file tree
Hide file tree
Showing 16 changed files with 203 additions and 53 deletions.
3 changes: 3 additions & 0 deletions kompas_maturalny_backend/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '2.7.0'

gem 'rails', '~> 6.0.0'
gem 'amoeba'
gem 'devise'
gem 'devise-token_authenticatable'
gem "interactor-rails", "~> 2.0"
gem 'pg', '>= 0.18', '< 2.0'
gem 'puma', '~> 3.11'
gem 'dotenv-rails'
Expand All @@ -32,6 +34,7 @@ end

group :development do
gem 'annotate'
gem 'hirb'
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
Expand Down
10 changes: 10 additions & 0 deletions kompas_maturalny_backend/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2)
amoeba (3.1.0)
activerecord (>= 3.2.6)
annotate (3.0.3)
activerecord (>= 3.2, < 7.0)
rake (>= 10.4, < 14.0)
Expand Down Expand Up @@ -95,8 +97,13 @@ GEM
railties
sprockets-rails
graphql (1.9.18)
hirb (0.7.3)
i18n (1.8.2)
concurrent-ruby (~> 1.0)
interactor (3.1.2)
interactor-rails (2.2.1)
interactor (~> 3.0)
rails (>= 4.2)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
Expand Down Expand Up @@ -205,6 +212,7 @@ PLATFORMS
ruby

DEPENDENCIES
amoeba
annotate
bcrypt (~> 3.1.7)
bootsnap (>= 1.4.2)
Expand All @@ -217,6 +225,8 @@ DEPENDENCIES
faker
graphiql-rails
graphql
hirb
interactor-rails (~> 2.0)
listen (>= 3.0.5, < 3.2)
pg (>= 0.18, < 2.0)
puma (~> 3.11)
Expand Down
10 changes: 2 additions & 8 deletions kompas_maturalny_backend/app/models/academy_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
#

class AcademyField < ApplicationRecord
after_create :extract_recruitment_factors

belongs_to :academy
belongs_to :field_of_study

Expand All @@ -31,11 +29,7 @@ class AcademyField < ApplicationRecord
presence: true,
format: { with: /\[\(.*\)\]/, on: :create, message: "Błędny format formuły." }

attr_accessor :recruitment_factors

private

def extract_recruitment_factors
@recruitment_factors = RecruitmentFormulaCalculator::Formula.new(self.recruitment_formula).extract_factors
def calculate_recruitment_points_for(user)
RecruitmentFormulaCalculator::Formula.new(self.recruitment_formula).calculate(user)
end
end
2 changes: 1 addition & 1 deletion kompas_maturalny_backend/app/models/matura_result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ class MaturaResult < ApplicationRecord
validates :result,
presence: true,
numericality: { only_integer: true },
inclusion: { in: 0...100 }
inclusion: { in: 0..100 }
end
6 changes: 5 additions & 1 deletion kompas_maturalny_backend/app/models/matura_subject.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Table name: matura_subjects
#
# id :bigint not null, primary key
# level :integer
# name :string
# subject_type :integer
# created_at :datetime not null
Expand All @@ -12,11 +13,14 @@
class MaturaSubject < ApplicationRecord
has_many :matura_results

enum level: %i[basic advanced]
enum subject_type: %i[humanities sciences others]

validates :name,
presence: true,
uniqueness: { case_sensitive: false }
uniqueness: { case_sensitive: false, scope: :level }
validates :level,
presence: true
validates :subject_type,
presence: true
end
5 changes: 5 additions & 0 deletions kompas_maturalny_backend/app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class User < ApplicationRecord
has_many :matura_results
has_many :matura_subjects, through: :matura_results

# ENABLE DEEP COPY CREATION
amoeba do
enable
end

enum role: %i[schoolboy student partner admin]
enum gender: %i[female male]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class CreateMaturaSubjects < ActiveRecord::Migration[6.0]
def change
create_table :matura_subjects do |t|
t.string :name
t.integer :level
t.integer :subject_type
t.timestamps
end
Expand Down
1 change: 1 addition & 0 deletions kompas_maturalny_backend/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

create_table "matura_subjects", force: :cascade do |t|
t.string "name"
t.integer "level"
t.integer "subject_type"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
Expand Down
33 changes: 19 additions & 14 deletions kompas_maturalny_backend/db/seeds.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
NUMBER_OF_FIELDS = 50
NUMBER_OF_FIELDS = 70
NUMBER_OF_ACADEMIES = 40
NUMBER_OF_FIELDS_ON_ACADEMY = 35
NUMBER_OF_MATURA_RESULTS = 5
MIN_NUMBER_OF_FIELDS_ON_ACADEMY = 20
MAX_NUMBER_OF_FIELDS_ON_ACADEMY = 65
NUMBER_OF_MATURA_RESULTS = 7

puts "Seeding database"
puts "Seeding test users"
Expand All @@ -11,14 +12,18 @@
User.create(username: 'admin', email: "admin@example.com", role: "admin", password: "test1234")

puts "Seeding matura subjects"
MaturaSubject.create(name: 'Chemia', subject_type: 'sciences')
MaturaSubject.create(name: 'Biologia', subject_type: 'sciences')
MaturaSubject.create(name: 'Fizyka', subject_type: 'sciences')
MaturaSubject.create(name: 'Geografia', subject_type: 'sciences')
MaturaSubject.create(name: 'Matematyka', subject_type: 'sciences')
MaturaSubject.create(name: 'Angielski', subject_type: 'humanities')
MaturaSubject.create(name: 'Niemiecki', subject_type: 'humanities')
MaturaSubject.create(name: 'Francuski', subject_type: 'humanities')
MaturaSubject.create(name: 'Chemia', level: 'advanced', subject_type: 'sciences')
MaturaSubject.create(name: 'Biologia', level: 'advanced', subject_type: 'sciences')
MaturaSubject.create(name: 'Fizyka', level: 'advanced', subject_type: 'sciences')
MaturaSubject.create(name: 'Geografia', level: 'advanced', subject_type: 'sciences')
MaturaSubject.create(name: 'Matematyka', level: 'advanced', subject_type: 'sciences')
MaturaSubject.create(name: 'Matematyka', level: 'basic', subject_type: 'sciences')
MaturaSubject.create(name: 'Angielski', level: 'advanced', subject_type: 'humanities')
MaturaSubject.create(name: 'Angielski', level: 'basic', subject_type: 'humanities')
MaturaSubject.create(name: 'Niemiecki', level: 'advanced', subject_type: 'humanities')
MaturaSubject.create(name: 'Niemiecki', level: 'basic', subject_type: 'humanities')
MaturaSubject.create(name: 'Francuski', level: 'advanced', subject_type: 'humanities')
MaturaSubject.create(name: 'Francuski', level: 'basic', subject_type: 'humanities')

User.all.each do |user|
NUMBER_OF_MATURA_RESULTS.times do |i|
Expand All @@ -43,12 +48,12 @@
city: Faker::Address.city
)

NUMBER_OF_FIELDS_ON_ACADEMY.times do |i|
puts "Seeding academy fields #{i}/#{NUMBER_OF_FIELDS_ON_ACADEMY}"
rand(MIN_NUMBER_OF_FIELDS_ON_ACADEMY...MAX_NUMBER_OF_FIELDS_ON_ACADEMY).times do |i|
puts "Seeding academy fields #{i}"
AcademyField.create!(
field_of_study: FieldOfStudy.all[i],
academy: academy,
recruitment_formula: "[(Chemia_Pr*2)|(Biologia_Pr*2)]+[(Fizyka_Pr*2)|(Matematyka_Pr*2]"
recruitment_formula: "[(chemia_pr*2)|(biologia_pr*2)]+[(fizyka_pr*2)|(matematyka_pr*2]"
)
end
end
77 changes: 65 additions & 12 deletions kompas_maturalny_backend/lib/recruitment_formula_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@

module RecruitmentFormulaCalculator
class Formula
def initialize(formula)
@formula = formula
def initialize(formula, remove_duplicates=true)
# $stderr.puts "FORMULA STRING"
# $stderr.puts "----------------------------------"
# $stderr.puts formula.gsub!(/\n/, '').gsub!(/ /, '')
# $stderr.puts "\n\n"
@user = nil
@formula = formula.gsub!(/\n/, '').gsub!(/ /, '')
@exponents = build_exponents
@remove_duplicates = remove_duplicates
end

attr_accessor :formula, :exponents
attr_accessor :formula, :exponents, :user

def extract_factors
factors = []
@exponents&.each do |e|
factors << e
end
factors
def calculate(user)
@exponents.permutation.to_a.collect do |exponents_permutation|
@user = user.amoeba_dup
exponents_permutation.reduce(0) do |result, exponent|
recruitment_points = result + exponent.calculate(@user)[:user_result]
@user.matura_results = @user.matura_results
.reject { |result| result.matura_subject == exponent.calculate(@user)[:subject] } if @remove_duplicates
recruitment_points
end
end.max
end

private
Expand All @@ -27,13 +37,28 @@ def build_exponents
end

class Exponent
def initialize(exponent)
@exponent = exponent.gsub!(/^[\[]|[\]]$/, '')
def initialize(exponent_string)
# $stderr.puts "EXPONENT STRING"
# $stderr.puts "----------------------------------"
# $stderr.puts exponent_string
# $stderr.puts "\n\n"
@exponent = exponent_string.gsub!(/^[\[]|[\]]$/, '')
@subjects = build_subjects
end

attr_reader :subjects, :exponent

def calculate(user)
# $stderr.puts "SUBJECTS"
# $stderr.puts "----------------------------------"
# $stderr.puts @subjects.map { |s| s.name }
# $stderr.puts "\n\n"
@subjects.collect { |subject| subject.calculate(user) }
.max_by { |calculated| calculated[:user_result] }
end

private

def build_subjects
exponent.split('|').map do |subject|
Subject.new(subject)
Expand All @@ -42,11 +67,39 @@ def build_subjects
end

class Subject
attr_reader :subject, :level, :multiplier, :name

def initialize(subject_string)
# $stderr.puts "SUBJECT STRING"
# $stderr.puts "----------------------------------"
# $stderr.puts subject_string
# $stderr.puts "\n\n"
subject_string.gsub!(/^[(]|[)]$/, '')
@subject = MaturaSubject.find_by_name(/(.*)_/.match(subject_string)[1].to_s.capitalize!)
@name = /(.*)_/.match(subject_string)[1].to_s.capitalize!
@level = /.*_(..)/.match(subject_string)[1].to_s == 'pp' ? :basic : :advanced
@multiplier = /.*\*(.*)/.match(subject_string)[1].to_f
@subject = MaturaSubject.where(name: @name, level: @level).take
end

def calculate(user)
{
subject: @subject,
user_result: find_user_result(user) * @multiplier
}
end

private

def find_user_result(user)
results = user.matura_results.find_all do |matura_result|
matura_result.matura_subject == self.subject
end

if results.is_a?(Array) && !results.empty?
results.pluck(:result).max
else
0
end
end
end
end
2 changes: 2 additions & 0 deletions kompas_maturalny_backend/spec/factories/matura_subjects.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Table name: matura_subjects
#
# id :bigint not null, primary key
# level :integer
# name :string
# subject_type :integer
# created_at :datetime not null
Expand All @@ -12,6 +13,7 @@
FactoryBot.define do
factory :matura_subject do
name { Faker::Educator.subject }
level { ['basic', 'advanced'].sample }
subject_type { ['humanities', 'sciences', 'others'].sample }
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,30 @@ module Academies


result = JSON.parse(response.body).to_h.deep_symbolize_keys
expect(result.dig(:data, :academies)).to include(id: be_present,
expect(result.dig(:data, :academies, :edges).sample[:node]).to include(id: be_present,
name: be_present,
description: be_present,
city: be_present
)
expect(result.dig(:data, :academies).count).to eq(20)
)
expect(result.dig(:data, :academies, :edges).count).to eq(20)
end

def query()
<<-GRAPHQL
query academies {
academies {
id
name
description
city
totalCount
pageInfo {
hasNextPage
}
edges {
node {
id
name
city
description
}
}
}
}
GRAPHQL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,28 @@ module FieldsOfStudy
}

result = JSON.parse(response.body).to_h.deep_symbolize_keys
expect(result.dig(:data, :fields)).to include(id: be_present,
name: be_present,
description: be_present
)
expect(result.dig(:data, :fields).count).to eq(10)
expect(result.dig(:data, :fields, :edges).sample[:node]).to include(id: be_present,
name: be_present,
description: be_present
)
expect(result.dig(:data, :fields, :edges).count).to eq(10)
end

def query()
<<-GRAPHQL
query fields {
fields {
id
name
description
totalCount
pageInfo {
endCursor
}
edges {
node {
id
name
description
}
}
}
}
GRAPHQL
Expand Down
Loading

0 comments on commit d782442

Please sign in to comment.