Class: ArticleJSON::Utils::AdditionalElementPlacer

Inherits:
Object
  • Object
show all
Defined in:
lib/article_json/utils/additional_element_placer.rb

Overview

This class allows the user to place additional elements within an article. It distributes elements over the whole article and ensures that an additional element is only ever placed between two paragraph elements or after a paragraph and before the next headline. If there are not enough spaces, the remaining additional elements will be appended to the existing article elements.

Instance Method Summary collapse

Constructor Details

#initialize(elements, additional_elements) ⇒ AdditionalElementPlacer

Returns a new instance of AdditionalElementPlacer.

Parameters:

  • elements (Array[ArticleJSON::Article::Elements::Base])
  • additional_elements (Array[Object])


12
13
14
15
# File 'lib/article_json/utils/additional_element_placer.rb', line 12

def initialize(elements, additional_elements)
  @elements = elements&.dup
  @additional_elements = additional_elements
end

Instance Method Details

#merge_elementsArray[ArticleJSON::Elements::Base|Object]

Distribute additional elements evenly throughout the article elements

Outline of the algorithm:

  1. It calculates every how many characters (only considering paragraphs) an additional element should be inserted, given the number of additional elements provided

  2. It then iterates over the existing elements within the article, inserting them into the resulting, merged article

  3. As soon as it has passed the right amount characters, it checks if the current position is eligible for inserting an additional element (the previous element needs to be a paragraph and the following needs to be either a paragraph or a headline)

    a) If so, it inserts the additional element and recalculates in how
       many characters the next element should be inserted, based on the
       remaining number of characters and remaining additional elements
    b) If not, it keeps iterating over the article until it finds an
       eligible position and only then inserts the additional element
       and recalculates the number of characters until the next
       insertion
    
  4. If there are still additional elements remaining which couldn’t be inserted (due to not finding enough eligible positions), they are appended to the end of the article

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/article_json/utils/additional_element_placer.rb', line 41

def merge_elements
  return @additional_elements if @elements.nil? || @elements.empty?
  remaining_elements = @additional_elements.dup
  next_in = insert_next_element_in(0, remaining_elements)
  characters_passed = 0
  @elements
    .each_cons(2)
    .each_with_object([]) do |(element, next_element), result|
      result << element
      next if remaining_elements.empty?
      if element.respond_to?(:length)
        characters_passed += element.length
        next_in -= element.length
      end
      if insert_here?(next_in, element, next_element)
        result << remaining_elements.shift
        next_in = insert_next_element_in(characters_passed,
                                         remaining_elements)
      end
    end
    .push(@elements.last,      # add last element
          *remaining_elements) # followed by remaining ads
end