Class: HeatingSystemCalculator::BaseElementFinder
- Inherits:
-
BaseItemFinder
- Object
- BaseItemFinder
- HeatingSystemCalculator::BaseElementFinder
- Defined in:
- app/services/heating_system_calculator/base_element_finder.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#coverage_percentage ⇒ Object
readonly
Returns the value of attribute coverage_percentage.
-
#elements ⇒ Object
readonly
Returns the value of attribute elements.
-
#error ⇒ Object
readonly
Returns the value of attribute error.
-
#target_area ⇒ Object
readonly
Returns the value of attribute target_area.
Instance Method Summary collapse
- #consolidate_elements(solution) ⇒ Object
- #find_best_solution(solutionset, targetarea, return_index_only = false) ⇒ Object
-
#initialize(options) ⇒ BaseElementFinder
constructor
A new instance of BaseElementFinder.
Methods inherited from BaseItemFinder
#get_number_of_poles_from_consolidated_elements, #get_total_from_solution
Constructor Details
#initialize(options) ⇒ BaseElementFinder
Returns a new instance of BaseElementFinder.
5 6 7 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 5 def initialize() @element_set = [:element_set] end |
Instance Attribute Details
#coverage_percentage ⇒ Object (readonly)
Returns the value of attribute coverage_percentage.
3 4 5 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 3 def coverage_percentage @coverage_percentage end |
#elements ⇒ Object (readonly)
Returns the value of attribute elements.
3 4 5 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 3 def elements @elements end |
#error ⇒ Object (readonly)
Returns the value of attribute error.
3 4 5 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 3 def error @error end |
#target_area ⇒ Object (readonly)
Returns the value of attribute target_area.
3 4 5 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 3 def target_area @target_area end |
Instance Method Details
#consolidate_elements(solution) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 9 def consolidate_elements(solution) # set up consolidated elements list elements = [] # loop over solution elements solution.each do |soln| # assume no duplicate products in the product set foundmatch = false # loop over our result set of unique elements elements.each do |elem| # test for duplicate product entries in the solution set next unless soln['sku'] == elem['sku'] # match found , increment quantity in our result set, set flag and break foundmatch = true elem['qty'] = elem['qty'] + (soln['qty'] || 1) break end next if foundmatch # no match found, so this is a unique entry in our result set elemnt = soln.merge({}) elemnt['qty'] ||= 1 elements << elemnt end elements end |
#find_best_solution(solutionset, targetarea, return_index_only = false) ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'app/services/heating_system_calculator/base_element_finder.rb', line 36 def find_best_solution(solutionset, targetarea, return_index_only = false) # Priority: Prefer solutions that MEET OR EXCEED target over undersized ones # Among adequate solutions, prefer closest to target with lowest price threshold = 0.05 # Separate solutions into adequate (>= target) and undersized (< target) adequate_solutions = [] undersized_solutions = [] solutionset.each_with_index do |solution, i| area = get_total_from_solution(solution, 'area') if area >= targetarea adequate_solutions << [i, solution, area] else undersized_solutions << [i, solution, area] end end # Use adequate solutions if available, otherwise fall back to undersized candidates = adequate_solutions.any? ? adequate_solutions : undersized_solutions bestdiffarea = 99_999_999.0 bestprice = 99_999_999.0 bestsolnsetind = -1 best_length = 99_999 candidates.each do |i, solution, area| diffarea = (targetarea - area).abs price = get_total_from_solution(solution, 'price') # Select best solution: closest to target, then cheapest, then fewest pieces is_better = (diffarea < bestdiffarea && bestdiffarea > threshold * targetarea) || (diffarea < threshold * targetarea && price < bestprice) || (diffarea < threshold * targetarea && (price - bestprice).abs < threshold * bestprice && solution.length < best_length) next unless is_better bestsolnsetind = i bestdiffarea = diffarea bestprice = price best_length = solution.length end res = solutionset[bestsolnsetind] res = bestsolnsetind if return_index_only res end |