openstax_kitchen 5.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/changelog.yml +27 -0
  3. data/.github/workflows/rubocop.yml +28 -0
  4. data/CHANGELOG.md +33 -0
  5. data/Gemfile.lock +8 -6
  6. data/docker/rubocop +22 -0
  7. data/lib/kitchen/directions/bake_appendix.rb +3 -1
  8. data/lib/kitchen/directions/bake_chapter_introductions.rb +22 -15
  9. data/lib/kitchen/directions/bake_chapter_introductions/chapter_introduction.xhtml.erb +0 -0
  10. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +2 -2
  11. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +2 -1
  12. data/lib/kitchen/directions/bake_chapter_solutions/main.rb +11 -0
  13. data/lib/kitchen/directions/bake_chapter_solutions/v1.rb +37 -0
  14. data/lib/kitchen/directions/bake_chapter_summary.rb +13 -6
  15. data/lib/kitchen/directions/bake_example.rb +4 -1
  16. data/lib/kitchen/directions/bake_figure.rb +13 -0
  17. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  18. data/lib/kitchen/directions/bake_footnotes/v1.rb +11 -8
  19. data/lib/kitchen/directions/bake_further_research.rb +2 -0
  20. data/lib/kitchen/directions/bake_index/v1.rb +2 -2
  21. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/main.rb +43 -0
  22. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v1.rb +37 -0
  23. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v2.rb +25 -0
  24. data/lib/kitchen/directions/bake_notes/bake_numbered_notes/v3.rb +32 -0
  25. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +3 -2
  26. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +10 -1
  27. data/lib/kitchen/directions/bake_numbered_table/bake_table_body.rb +29 -0
  28. data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -0
  29. data/lib/kitchen/directions/bake_numbered_table/v1.rb +1 -17
  30. data/lib/kitchen/directions/bake_numbered_table/v2.rb +31 -0
  31. data/lib/kitchen/directions/bake_preface/main.rb +2 -2
  32. data/lib/kitchen/directions/bake_preface/v1.rb +3 -2
  33. data/lib/kitchen/directions/book_answer_key_container/eob_answer_key_outer_container.xhtml.erb +9 -0
  34. data/lib/kitchen/directions/book_answer_key_container/main.rb +2 -2
  35. data/lib/kitchen/directions/book_answer_key_container/v1.rb +4 -3
  36. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +3 -3
  37. data/lib/kitchen/directions/chapter_review_container/main.rb +2 -2
  38. data/lib/kitchen/directions/chapter_review_container/v1.rb +4 -2
  39. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +13 -0
  40. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +10 -0
  41. data/lib/kitchen/directions/move_exercises_to_eoc/v3.rb +49 -0
  42. data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +6 -2
  43. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/default.rb +27 -0
  44. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/precalculus.rb +84 -0
  45. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +11 -7
  46. data/lib/kitchen/element_base.rb +15 -0
  47. data/lib/kitchen/page_element.rb +2 -3
  48. data/lib/kitchen/patches/integer.rb +24 -0
  49. data/lib/kitchen/patches/nokogiri.rb +7 -0
  50. data/lib/kitchen/version.rb +1 -1
  51. data/lib/locales/en.yml +2 -1
  52. data/lib/locales/es.yml +2 -1
  53. data/lib/locales/pl.yml +3 -2
  54. metadata +19 -6
  55. data/.github/config.yml +0 -14
  56. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +0 -51
  57. data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +0 -9
  58. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c8e1365bab888949c899b5cb36518be9456bd23d0369ddab9a42ac81f82cc024
4
- data.tar.gz: cd86a88028f0946885add3866ffad6133f84ce48a779800cb5105cc8153736d4
3
+ metadata.gz: 544eb8b780fd248111e4dc9738c32b7edfefc101fbf6abd82f25c01bada69708
4
+ data.tar.gz: c3f1e2658259f5d9a04dde8aa188793c3c82e8ef6a4f6c1354e2b50d5ed7982d
5
5
  SHA512:
6
- metadata.gz: 16b9afc1d63a6098aad2396e114975ea35d39890c9a4c27c88dfef7710d129ddf16e3f18d775042ae919d0dff5284d41b53f668621d5cd74f2e723a670fd33d9
7
- data.tar.gz: 9b93c51846a460a3e71c6a6080f53be61f1fa93ab268f954ddf3b7d447a1f9602dd789d876bc41e2997f8f44e682453c413f2f28ea7754c4d7f1015d3ecde1a6
6
+ metadata.gz: 1829a8193fd8d53e2eaa4d91bd00417eb439b1dce3e690b865ff7741d3aad8637282a680f7840842180bfd811cbd79d7275b1c75502fdbcb72d39ed81572b905
7
+ data.tar.gz: 6cf08743860774a7f7b6fa73d26d4adbc56d7e2849e2178fc020456f113774942d23f7f14f2a5f02393c43cbfa0312b787bbb8a1adbdca4943fd76cb697ff9c0
@@ -0,0 +1,27 @@
1
+ name: CHANGELOG.md
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ exists:
11
+ timeout-minutes: 10
12
+ runs-on: ubuntu-18.04
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ with:
17
+ fetch-depth: 0
18
+ - name: Check for CHANGELOG.md in this PR
19
+ # https://dev.to/scienta/get-changed-files-in-github-actions-1p36
20
+ run: |
21
+ if [[ $(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | grep CHANGELOG.md) ]]; then
22
+ echo "CHANGELOG.md is included in the pull request! Way to go!"
23
+ exit 0
24
+ else
25
+ echo "CHANGELOG.md was not modified in this pull request. Boo!"
26
+ exit 1
27
+ fi
@@ -0,0 +1,28 @@
1
+ name: Rubocop
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches:
7
+ - main
8
+
9
+ jobs:
10
+ lint:
11
+ timeout-minutes: 10
12
+ runs-on: ubuntu-18.04
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ with:
17
+ fetch-depth: 0
18
+ - uses: actions/cache@v2
19
+ with:
20
+ path: vendor/bundle
21
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
22
+ restore-keys: |
23
+ ${{ runner.os }}-gems-
24
+ - name: Build docker image and run rubocop within it
25
+ # See https://docs.codecov.io/docs/testing-with-docker
26
+ run: |
27
+ ./docker/build --ci
28
+ ./docker/rubocop ${{ github.event.pull_request.base.sha }} ${{ github.sha }}
data/CHANGELOG.md CHANGED
@@ -6,6 +6,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+
10
+ ## [6.0.0] - 2021-06-15
11
+
12
+ * Allow `BakeChapterSummary` to skip pages where there is no summary (minor)
13
+ * Change `PageElement#summary` to return nil instead of raise an error if no matches (major?)
14
+ * Fix bug in `BakeNumberedNotes:::V3` when there are multiple os-numbers (minor)
15
+ * Add Rubocop and a working CHANGELOG check to GitHub actions (patch)
16
+ * Allow `BakeFootnotes` to number footnotes with Roman numerals (minor)
17
+ * Create V2 for `BakeNumberedTables` (minor)
18
+ * Remove extraneous title in `BakeChapterSectionExercises` (minor)
19
+ * Create V2 for `BookAnswerKeyContainer` and `MoveSolutionsToEOC` with singular option for wrapper class (minor)
20
+ * Delete `abstract` and `description` elements from preface in `BakePreface` (minor)
21
+ * Stop deleting the first `<strong>` tag in `BakeNumberedNotes` (major)
22
+ * Allow `BakeFigure` to bake unnumbered splash figures (minor)
23
+ * Extend `ChapterReviewContainer` to accept other classes (major?)
24
+ * Add a `Strategy` for Precalculus (minor)
25
+ * Create a `BakeNumberedNotes` V2 (minor)
26
+ * Added a version of `BakeChapterIntroductions` without a chapter outline (minor)
27
+ * Add `BakeChapterSolutions` which bakes the free response solutions at the eoc (minor)
28
+ * Changed locale `eoc_answer_key_title` to `answer_key_title` as it was only used in eob (major)
29
+ * Added spec for translations (minor)
30
+ * Remove summary attribute from numbered tables, add option to pass title element to `BakePreface` (minor)
31
+ * Renamed `American Government` strategy to `Default` inside `move_solutions_to_answer_key` for other books to use it with a sent in classname (major)
32
+ * Adds `#previous` method to note_elements to find the immediately previous element (minor)
33
+ * Adds `BakeNumberedNotes` V3 (minor)
34
+ * Added line that puts the classname `has-footnote` in the footnote ref's parent element (major)
35
+ * Added a condition into `BakeChapterSummary` so it doesn't bake the title if it already includes the respective number in it
36
+ * Create v3 of MoveExercisesToEOC which differs from v1 by the presence of a section title
37
+ and from v2 the lack of additional "os-section-area" and os-#{@klass} wrapper (minor)
38
+ * Add a condition in BakeNumberedExercise to make it possible to suppress even solutions in the Answer Key (minor)
39
+ * Fix BakeFurtherResearch baking with main bake script error by breaking the loop if further research sections are not present (minor)
40
+ * Fix for `BakeIndex` for words that start with a number to be grouped as symbols and for first letters with accent marks to be grouped with regular letters in alphabetic order (major)
41
+
9
42
  ## [5.0.0] - 2021-06-02
10
43
 
11
44
  * Reditributed duplicated id logic across `#record_id_copied`, `#record_id_cut`, `#record_id_pasted`, added a couple more tests for `#copy`, `#cut`, and `#paste`, created a new class `IdTracker` and moved `#record_id_copied`, `#record_id_cut`, `#record_id_pasted`, and `modified_id_to_paste` into the new class (major)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openstax_kitchen (5.0.0)
4
+ openstax_kitchen (6.0.0)
5
5
  activesupport
6
6
  i18n
7
7
  nokogiri
@@ -21,12 +21,12 @@ GEM
21
21
  byebug (11.1.2)
22
22
  camertron-eprun (1.1.1)
23
23
  cldr-plurals-runtime-rb (1.1.0)
24
- codecov (0.2.13)
25
- simplecov (~> 0.18.0)
24
+ codecov (0.5.2)
25
+ simplecov (>= 0.15, < 0.22)
26
26
  coderay (1.1.3)
27
- concurrent-ruby (1.1.8)
27
+ concurrent-ruby (1.1.9)
28
28
  diff-lcs (1.3)
29
- docile (1.3.3)
29
+ docile (1.4.0)
30
30
  i18n (1.8.10)
31
31
  concurrent-ruby (~> 1.0)
32
32
  inch (0.8.0)
@@ -86,10 +86,12 @@ GEM
86
86
  rubocop (~> 1.0)
87
87
  rubocop-ast (>= 1.1.0)
88
88
  ruby-progressbar (1.10.1)
89
- simplecov (0.18.5)
89
+ simplecov (0.21.2)
90
90
  docile (~> 1.1)
91
91
  simplecov-html (~> 0.11)
92
+ simplecov_json_formatter (~> 0.1)
92
93
  simplecov-html (0.12.3)
94
+ simplecov_json_formatter (0.1.3)
93
95
  sparkr (0.4.1)
94
96
  sync (0.5.0)
95
97
  tdiff (0.3.4)
data/docker/rubocop ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # set -x
4
+
5
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
6
+
7
+ from="${1:-main}"
8
+ to="${2:-HEAD}"
9
+
10
+ echo "Checking from $from to $to"
11
+
12
+ # https://dev.to/scienta/get-changed-files-in-github-actions-1p36
13
+ changed_ruby_files=$(git diff --name-only --diff-filter=ACMRT $from $to | grep -E "(lib\/|spec\/)*.rb$" | xargs)
14
+
15
+ if [[ -z "${changed_ruby_files// }" ]]; then
16
+ echo "No files to lint with Rubocop"
17
+ else
18
+ docker run -v $DIR/..:/code \
19
+ -w /code \
20
+ openstax/kitchen.ci:latest \
21
+ /bin/bash -c "bundle config path vendor/bundle; bundle install; bundle exec rubocop $changed_ruby_files --disable-pending-cops"
22
+ fi
@@ -17,7 +17,9 @@ module Kitchen
17
17
 
18
18
  # Make a section with data-depth of X have a header level of X+1
19
19
  page.search('section').each do |section|
20
- title = section.first!("[data-type='title']")
20
+ title = section.titles.first
21
+ next unless title.present?
22
+
21
23
  title.name = "h#{section['data-depth'].to_i + 1}"
22
24
  end
23
25
  end
@@ -3,21 +3,31 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeChapterIntroductions
6
- def self.v1(book:)
6
+ def self.v1(book:, bake_chapter_objectives: true)
7
7
  book.chapters.each do |chapter|
8
- outline_items_html = chapter.pages.map do |page|
9
- next if page.is_introduction?
8
+ chapter_outline_html = ''
10
9
 
11
- <<~HTML
12
- <div class="os-chapter-objective">
13
- <a class="os-chapter-objective" href="##{page.title[:id]}">
14
- <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter) - 1}</span>
15
- <span class="os-divider"> </span>
16
- <span data-type="" itemprop="" class="os-text">#{page.title.children[0].text}</span>
17
- </a>
10
+ if bake_chapter_objectives
11
+ outline_items_html = chapter.non_introduction_pages.map do |page|
12
+
13
+ <<~HTML
14
+ <div class="os-chapter-objective">
15
+ <a class="os-chapter-objective" href="##{page.title[:id]}">
16
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
17
+ <span class="os-divider"> </span>
18
+ <span data-type="" itemprop="" class="os-text">#{page.title.children[0].text}</span>
19
+ </a>
20
+ </div>
21
+ HTML
22
+ end.join('')
23
+
24
+ chapter_outline_html = <<~HTML
25
+ <div class="os-chapter-outline">
26
+ <h3 class="os-title">#{I18n.t(:chapter_outline)}</h3>
27
+ #{outline_items_html}
18
28
  </div>
19
29
  HTML
20
- end.join('')
30
+ end
21
31
 
22
32
  introduction_page = chapter.introduction_page
23
33
 
@@ -33,10 +43,7 @@ module Kitchen
33
43
  introduction_page.append(child:
34
44
  <<~HTML
35
45
  <div class="intro-body">
36
- <div class="os-chapter-outline">
37
- <h3 class="os-title">#{I18n.t(:chapter_outline)}</h3>
38
- #{outline_items_html}
39
- </div>
46
+ #{chapter_outline_html}
40
47
  <div class="intro-text">
41
48
  #{title.paste}
42
49
  #{intro_content.paste}
@@ -3,8 +3,8 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeChapterSectionExercises
6
- def self.v1(chapter:)
7
- V1.new.bake(chapter: chapter)
6
+ def self.v1(chapter:, trash_title: false)
7
+ V1.new.bake(chapter: chapter, trash_title: trash_title)
8
8
  end
9
9
  end
10
10
  end
@@ -2,9 +2,10 @@
2
2
 
3
3
  module Kitchen::Directions::BakeChapterSectionExercises
4
4
  class V1
5
- def bake(chapter:)
5
+ def bake(chapter:, trash_title:)
6
6
  chapter.pages.each do |page|
7
7
  page.search('section.section-exercises').each do |section|
8
+ section.first('h3[data-type="title"]')&.trash if trash_title
8
9
  section.wrap(
9
10
  %(<div class="os-eos os-section-exercises-container"
10
11
  data-uuid-key=".section-exercises">)
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeChapterSolutions
6
+ def self.v1(chapter:, metadata_source:, uuid_prefix: '')
7
+ V1.new.bake(chapter: chapter, metadata_source: metadata_source, uuid_prefix: uuid_prefix)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeChapterSolutions
4
+ class V1
5
+ renderable
6
+
7
+ def bake(chapter:, metadata_source:, uuid_prefix: '')
8
+ @metadata = metadata_source.children_to_keep.copy
9
+ @klass = 'solutions'
10
+ @title = I18n.t(:eoc_solutions_title)
11
+ @uuid_prefix = uuid_prefix
12
+
13
+ solutions_clipboard = Kitchen::Clipboard.new
14
+
15
+ chapter.search('section.free-response').each do |free_response_question|
16
+ exercises = free_response_question.exercises
17
+ # must run AFTER .free-response notes are baked
18
+
19
+ next if exercises.none?
20
+
21
+ exercises.each do |exercise|
22
+ solution = exercise.solution
23
+ next unless solution.present?
24
+
25
+ solution.cut(to: solutions_clipboard)
26
+ end
27
+ end
28
+
29
+ @content = solutions_clipboard.paste
30
+
31
+ @in_composite_chapter = false
32
+
33
+ chapter.append(child: render(file:
34
+ '../../templates/eoc_section_title_template.xhtml.erb'))
35
+ end
36
+ end
37
+ end
@@ -27,15 +27,22 @@ module Kitchen
27
27
  # TODO: include specific page types somehow without writing it out
28
28
  chapter.non_introduction_pages.each do |page|
29
29
  summary = page.summary
30
+
31
+ next if summary.nil?
32
+
30
33
  summary.first("[data-type='title']")&.trash # get rid of old title if exists
31
34
  summary_title = page.title.copy
32
35
  summary_title.name = 'h3'
33
- summary_title.replace_children(with: <<~HTML
34
- <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
35
- <span class="os-divider"> </span>
36
- <span class="os-text" data-type="" itemprop="">#{summary_title.children}</span>
37
- HTML
38
- )
36
+
37
+ unless summary_title.children.search('span.os-number').present?
38
+ summary_title.replace_children(with:
39
+ <<~HTML
40
+ <span class="os-number">#{chapter.count_in(:book)}.#{page.count_in(:chapter)}</span>
41
+ <span class="os-divider"> </span>
42
+ <span class="os-text" data-type="" itemprop="">#{summary_title.children}</span>
43
+ HTML
44
+ )
45
+ end
39
46
 
40
47
  summary.prepend(child:
41
48
  <<~HTML
@@ -21,7 +21,10 @@ module Kitchen
21
21
  .store("#{I18n.t(:example_label)} #{number}", label: example.id)
22
22
 
23
23
  example.titles.each do |title|
24
- next if title.parent.has_class?('os-caption-container')
24
+ if title.parent.has_class?('os-caption-container') || \
25
+ title.parent.has_class?('os-caption')
26
+ next
27
+ end
25
28
 
26
29
  title.name = 'h4'
27
30
  end
@@ -4,7 +4,20 @@ module Kitchen
4
4
  module Directions
5
5
  module BakeFigure
6
6
  def self.v1(figure:, number:)
7
+ return if figure.has_class?('unnumbered') && !figure.has_class?('splash')
8
+
7
9
  figure.wrap(%(<div class="os-figure#{' has-splash' if figure.has_class?('splash')}">))
10
+ if figure.has_class?('unnumbered') && figure.has_class?('splash')
11
+ caption = figure.caption&.cut
12
+ figure.append(sibling:
13
+ <<~HTML
14
+ <div class="os-caption-container">
15
+ #{"<span class=\"os-caption\">#{caption.children}</span>" if caption}
16
+ </div>
17
+ HTML
18
+ )
19
+ return
20
+ end
8
21
 
9
22
  figure.pantry(name: :link_text).store "#{I18n.t(:figure)} #{number}", label: figure.id
10
23
  title = figure.title&.cut
@@ -3,8 +3,8 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeFootnotes
6
- def self.v1(book:)
7
- V1.new.bake(book: book)
6
+ def self.v1(book:, number_format: :arabic)
7
+ V1.new.bake(book: book, number_format: number_format)
8
8
  end
9
9
  end
10
10
  end
@@ -3,37 +3,40 @@
3
3
  module Kitchen::Directions::BakeFootnotes
4
4
  class V1
5
5
 
6
- def bake(book:)
6
+ def bake(book:, number_format: :arabic)
7
7
  # Footnotes are numbered either within their top-level pages (preface,
8
8
  # appendices, etc) or within chapters. Tackle each case separately
9
9
 
10
10
  book.body.element_children.only(Kitchen::PageElement,
11
11
  Kitchen::CompositePageElement,
12
12
  Kitchen::CompositeChapterElement).each do |page|
13
- bake_footnotes_within(page)
13
+ bake_footnotes_within(page, number_format: number_format)
14
14
  end
15
15
 
16
16
  book.chapters.each do |chapter|
17
- bake_footnotes_within(chapter)
17
+ bake_footnotes_within(chapter, number_format: number_format)
18
18
  end
19
19
  end
20
20
 
21
- def bake_footnotes_within(container)
22
- footnote_number = 0
21
+ def bake_footnotes_within(container, number_format:)
22
+ footnote_count = 0
23
23
  aside_id_to_footnote_number = {}
24
24
 
25
25
  container.search("a[role='doc-noteref']").each do |anchor|
26
- footnote_number += 1
27
- anchor.replace_children(with: footnote_number.to_s)
26
+ footnote_count += 1
27
+ footnote_number = footnote_count.to_format(number_format)
28
+ anchor.replace_children(with: footnote_number)
28
29
  aside_id = anchor[:href][1..-1]
29
30
  aside_id_to_footnote_number[aside_id] = footnote_number
31
+ anchor.parent.add_class('has-noteref') if anchor.parent.name == 'p'
30
32
  end
31
33
 
32
34
  container.search('aside').each do |aside|
33
35
  footnote_number = aside_id_to_footnote_number[aside.id]
34
36
  aside.prepend(child: "<div data-type='footnote-number'>#{footnote_number}</div>")
35
37
  end
36
- end
37
38
 
39
+ footnote_count
40
+ end
38
41
  end
39
42
  end