[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] master 1aa42aa 1/3: Move page_count() to tabular-rep
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] master 1aa42aa 1/3: Move page_count() to tabular-reports TU |
Date: |
Mon, 3 Sep 2018 17:39:19 -0400 (EDT) |
branch: master
commit 1aa42aa2f13c87d5158f5b4773be1c3652844d23
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>
Move page_count() to tabular-reports TU
---
ledger_pdf_generator_wx.cpp | 3 +-
miscellany.cpp | 75 -----------------------------
miscellany.hpp | 6 ---
miscellany_test.cpp | 96 ------------------------------------
report_table.cpp | 75 +++++++++++++++++++++++++++++
report_table.hpp | 8 +++
report_table_test.cpp | 115 ++++++++++++++++++++++++++++++++++++++++----
7 files changed, 191 insertions(+), 187 deletions(-)
diff --git a/ledger_pdf_generator_wx.cpp b/ledger_pdf_generator_wx.cpp
index b616837..659054a 100644
--- a/ledger_pdf_generator_wx.cpp
+++ b/ledger_pdf_generator_wx.cpp
@@ -36,9 +36,10 @@
#include "ledger_evaluator.hpp"
#include "ledger_invariant.hpp"
#include "ledger_variant.hpp"
-#include "miscellany.hpp" // lmi_tolower(), page_count()
+#include "miscellany.hpp" // lmi_tolower()
#include "oecumenic_enumerations.hpp"
#include "pdf_writer_wx.hpp"
+#include "report_table.hpp" // page_count()
#include "ssize_lmi.hpp"
#include "wx_table_generator.hpp"
diff --git a/miscellany.cpp b/miscellany.cpp
index 83e9450..4be7039 100644
--- a/miscellany.cpp
+++ b/miscellany.cpp
@@ -25,7 +25,6 @@
#include "alert.hpp"
#include "assert_lmi.hpp"
-#include "math_functions.hpp" // outward_quotient()
#include "ssize_lmi.hpp"
#include <algorithm> // equal(), max()
@@ -291,77 +290,3 @@ std::string iso_8601_datestamp_terse()
LMI_ASSERT(0 != rc);
return s;
}
-
-/// Number of pages needed to display the given number of data
-/// rows in groups of the given size separated by blank lines.
-///
-/// Nomenclature:
-/// - a 'line' is a printable zone of unit height;
-/// - a 'row' is a series of data to be shown side by side.
-/// With quinquennial spacing, the Morse alphabet is printed thus:
-///
-/// A .- line 0 row 0
-/// B -... line 1 row 1
-/// C -.-. line 2 row 2
-/// D -.. line 3 row 3
-/// E . line 4 row 4
-/// [blank] line 5
-/// F ..-. line 6 row 5
-/// G --. line 7 row 6
-/// ...
-/// Z --.. line 30 row 25
-///
-/// with a page length of 50 lines. With a page length of 25 lines,
-/// the first page would end with
-/// T - line 22 row 19
-/// and the second page would be printed thus:
-///
-/// U ..- line 0 row 20
-/// V ...- line 1 row 21
-/// W .-- line 2 row 22
-/// X -..- line 3 row 23
-/// Y -.-- line 4 row 24
-/// [blank] line 5
-/// Z --.. line 6 row 25
-///
-/// Preconditions: 0 <= total_rows && 0 < rows_per_group <= lines_per_page
-
-int page_count
- (int total_rows
- ,int rows_per_group
- ,int lines_per_page
- )
-{
- LMI_ASSERT(0 <= total_rows);
- LMI_ASSERT(0 < rows_per_group );
- LMI_ASSERT( rows_per_group <= lines_per_page);
-
- // If there are zero rows of data, then one empty page is wanted.
- if(0 == total_rows)
- return 1;
-
- // "+ 1": blank-line separator after each group.
- int const lines_per_group = rows_per_group + 1;
-
- // "+ 1": no blank-line separator after the last group.
- int const groups_per_page = (lines_per_page + 1) / lines_per_group;
-
- int const rows_per_page = rows_per_group * groups_per_page;
-
- int number_of_pages = outward_quotient(total_rows, rows_per_page);
-
- // Avoid widowing a partial group on the last page, by moving it
- // to the preceding page if there's room.
- if(1 < number_of_pages)
- {
- auto const rows_on_last_page = total_rows - (number_of_pages - 1) *
rows_per_page;
- auto const free_lines = lines_per_page - lines_per_group *
groups_per_page;
- LMI_ASSERT(free_lines < rows_per_group);
- if(rows_on_last_page <= free_lines)
- {
- --number_of_pages;
- }
- }
-
- return number_of_pages;
-}
diff --git a/miscellany.hpp b/miscellany.hpp
index 69dc12b..95d23b0 100644
--- a/miscellany.hpp
+++ b/miscellany.hpp
@@ -199,12 +199,6 @@ inline unsigned char lmi_toupper(unsigned char c)
return static_cast<unsigned char>(std::toupper(c));
}
-int LMI_SO page_count
- (int total_rows
- ,int rows_per_group
- ,int lines_per_page
- );
-
/// DWISOTT
///
/// Perhaps this function template's only legitimate use is within a
diff --git a/miscellany_test.cpp b/miscellany_test.cpp
index eaafa73..e4c1a16 100644
--- a/miscellany_test.cpp
+++ b/miscellany_test.cpp
@@ -152,101 +152,6 @@ void test_minmax()
BOOST_TEST(!(zero < m || m < one));
}
-void test_page_count()
-{
- // Original tests: vary only the number of data rows.
-
- // Edge cases.
- BOOST_TEST_EQUAL(1, page_count( 0, 5, 28));
- BOOST_TEST_EQUAL(1, page_count( 1, 5, 28));
- // Just a trivial sanity test.
- BOOST_TEST_EQUAL(1, page_count(17, 5, 28));
- // 4 full groups + incomplete last group.
- BOOST_TEST_EQUAL(1, page_count(24, 5, 28));
- // 5 full groups don't fit on one page.
- BOOST_TEST_EQUAL(2, page_count(25, 5, 28));
- // 4 + 4 groups + incomplete last one.
- BOOST_TEST_EQUAL(2, page_count(44, 5, 28));
- // 9 full groups don't fit on two pages.
- BOOST_TEST_EQUAL(3, page_count(45, 5, 28));
-
- // Test preconditions.
-
- // Negative number of data rows.
- BOOST_TEST_THROW
- (page_count(-1, 1, 1)
- ,std::runtime_error
- ,lmi_test::what_regex("^Assertion.*failed")
- );
-
- // Zero rows per group.
- BOOST_TEST_THROW
- (page_count(1, 0, 1)
- ,std::runtime_error
- ,lmi_test::what_regex("^Assertion.*failed")
- );
-
- // Insufficient room to print even one group.
- BOOST_TEST_THROW
- (page_count(1, 7, 3)
- ,std::runtime_error
- ,lmi_test::what_regex("^Assertion.*failed")
- );
-
- // A single row of data.
- BOOST_TEST_EQUAL(1, page_count(1, 1, 1));
- BOOST_TEST_EQUAL(1, page_count(1, 1, 3));
- BOOST_TEST_EQUAL(1, page_count(1, 3, 3));
- BOOST_TEST_EQUAL(1, page_count(1, 3, 7));
-
- // One-row groups:
-
- // Page length an odd number.
- BOOST_TEST_EQUAL(1, page_count(1, 1, 5));
- BOOST_TEST_EQUAL(1, page_count(3, 1, 5));
- BOOST_TEST_EQUAL(2, page_count(4, 1, 5));
- BOOST_TEST_EQUAL(2, page_count(6, 1, 5));
- BOOST_TEST_EQUAL(3, page_count(7, 1, 5));
-
- // Same, but next even length: same outcome.
- BOOST_TEST_EQUAL(1, page_count(1, 1, 6));
- BOOST_TEST_EQUAL(1, page_count(3, 1, 6));
- BOOST_TEST_EQUAL(2, page_count(4, 1, 6));
- BOOST_TEST_EQUAL(2, page_count(6, 1, 6));
- BOOST_TEST_EQUAL(3, page_count(7, 1, 6));
-
- // Two-row groups.
-
- // Page length four.
- BOOST_TEST_EQUAL(1, page_count(1, 2, 4));
- BOOST_TEST_EQUAL(1, page_count(3, 2, 4));
- BOOST_TEST_EQUAL(2, page_count(4, 2, 4));
- BOOST_TEST_EQUAL(2, page_count(5, 2, 4));
- BOOST_TEST_EQUAL(3, page_count(6, 2, 4));
-
- // Page length five: no room for widow and orphan control.
- BOOST_TEST_EQUAL(1, page_count(1, 2, 5));
- BOOST_TEST_EQUAL(1, page_count(4, 2, 5));
- BOOST_TEST_EQUAL(2, page_count(5, 2, 5));
- BOOST_TEST_EQUAL(2, page_count(8, 2, 5));
- BOOST_TEST_EQUAL(3, page_count(9, 2, 5));
-
- // Same, but next even length: same outcome.
- BOOST_TEST_EQUAL(1, page_count(1, 2, 6));
- BOOST_TEST_EQUAL(1, page_count(4, 2, 6));
- BOOST_TEST_EQUAL(2, page_count(5, 2, 6));
- BOOST_TEST_EQUAL(2, page_count(8, 2, 6));
- BOOST_TEST_EQUAL(3, page_count(9, 2, 6));
-
- // Page length seven: one extra data row possible on last page.
- BOOST_TEST_EQUAL(1, page_count(1, 2, 7));
- BOOST_TEST_EQUAL(1, page_count(4, 2, 7));
- BOOST_TEST_EQUAL(1, page_count(5, 2, 7));
- BOOST_TEST_EQUAL(2, page_count(6, 2, 7));
- BOOST_TEST_EQUAL(2, page_count(8, 2, 7));
- BOOST_TEST_EQUAL(2, page_count(9, 2, 7));
-}
-
void test_prefix_and_suffix()
{
std::string s = "";
@@ -496,7 +401,6 @@ int test_main(int, char*[])
test_each_equal();
test_files_are_identical();
test_minmax();
- test_page_count();
test_prefix_and_suffix();
test_scale_power();
test_trimming();
diff --git a/report_table.cpp b/report_table.cpp
index 308cc19..8869ba7 100644
--- a/report_table.cpp
+++ b/report_table.cpp
@@ -25,6 +25,7 @@
#include "alert.hpp"
#include "assert_lmi.hpp"
+#include "math_functions.hpp" // outward_quotient()
#include "ssize_lmi.hpp"
#include <algorithm> // min()
@@ -173,3 +174,77 @@ std::vector<int> set_column_widths
return w;
}
+
+/// Number of pages needed to display the given number of data
+/// rows in groups of the given size separated by blank lines.
+///
+/// Nomenclature:
+/// - a 'line' is a printable zone of unit height;
+/// - a 'row' is a series of data to be shown side by side.
+/// With quinquennial spacing, the Morse alphabet is printed thus:
+///
+/// A .- line 0 row 0
+/// B -... line 1 row 1
+/// C -.-. line 2 row 2
+/// D -.. line 3 row 3
+/// E . line 4 row 4
+/// [blank] line 5
+/// F ..-. line 6 row 5
+/// G --. line 7 row 6
+/// ...
+/// Z --.. line 30 row 25
+///
+/// with a page length of 50 lines. With a page length of 25 lines,
+/// the first page would end with
+/// T - line 22 row 19
+/// and the second page would be printed thus:
+///
+/// U ..- line 0 row 20
+/// V ...- line 1 row 21
+/// W .-- line 2 row 22
+/// X -..- line 3 row 23
+/// Y -.-- line 4 row 24
+/// [blank] line 5
+/// Z --.. line 6 row 25
+///
+/// Preconditions: 0 <= total_rows && 0 < rows_per_group <= lines_per_page
+
+int page_count
+ (int total_rows
+ ,int rows_per_group
+ ,int lines_per_page
+ )
+{
+ LMI_ASSERT(0 <= total_rows);
+ LMI_ASSERT(0 < rows_per_group );
+ LMI_ASSERT( rows_per_group <= lines_per_page);
+
+ // If there are zero rows of data, then one empty page is wanted.
+ if(0 == total_rows)
+ return 1;
+
+ // "+ 1": blank-line separator after each group.
+ int const lines_per_group = rows_per_group + 1;
+
+ // "+ 1": no blank-line separator after the last group.
+ int const groups_per_page = (lines_per_page + 1) / lines_per_group;
+
+ int const rows_per_page = rows_per_group * groups_per_page;
+
+ int number_of_pages = outward_quotient(total_rows, rows_per_page);
+
+ // Avoid widowing a partial group on the last page, by moving it
+ // to the preceding page if there's room.
+ if(1 < number_of_pages)
+ {
+ auto const rows_on_last_page = total_rows - (number_of_pages - 1) *
rows_per_page;
+ auto const free_lines = lines_per_page - lines_per_group *
groups_per_page;
+ LMI_ASSERT(free_lines < rows_per_group);
+ if(rows_on_last_page <= free_lines)
+ {
+ --number_of_pages;
+ }
+ }
+
+ return number_of_pages;
+}
diff --git a/report_table.hpp b/report_table.hpp
index 0147223..1ff00c8 100644
--- a/report_table.hpp
+++ b/report_table.hpp
@@ -103,4 +103,12 @@ std::vector<int> LMI_SO set_column_widths
,int minimum_margin
);
+class paginator; // Coming soon.
+
+int LMI_SO page_count
+ (int total_rows
+ ,int rows_per_group
+ ,int lines_per_page
+ );
+
#endif // report_table_hpp
diff --git a/report_table_test.cpp b/report_table_test.cpp
index 4a5f1e9..149d7e3 100644
--- a/report_table_test.cpp
+++ b/report_table_test.cpp
@@ -80,17 +80,19 @@ class report_table_test
{
test_apportion();
test_bloat();
- test_generally();
- test_group_quote();
- test_illustration();
+ test_column_widths_generally();
+ test_column_widths_for_group_quotes();
+ test_column_widths_for_illustrations();
+ test_paginator();
}
private:
static void test_apportion();
static void test_bloat();
- static void test_generally();
- static void test_group_quote();
- static void test_illustration();
+ static void test_column_widths_generally();
+ static void test_column_widths_for_group_quotes();
+ static void test_column_widths_for_illustrations();
+ static void test_paginator();
};
void report_table_test::test_apportion()
@@ -171,7 +173,7 @@ void report_table_test::test_bloat()
BOOST_TEST(v == bloat({3, 1, 0, 0, 2}, {0, 1, 0, 1, 0}));
}
-void report_table_test::test_generally()
+void report_table_test::test_column_widths_generally()
{
std::vector<table_column_info> v;
std::vector<int> expected;
@@ -278,7 +280,7 @@ void report_table_test::test_generally()
/// group quote. Therefore, they aren't written in a compact way
/// or expanded by bloat().
-void report_table_test::test_group_quote()
+void report_table_test::test_column_widths_for_group_quotes()
{
static int const total_width = 756;
static int const default_margin = 14;
@@ -309,7 +311,7 @@ void report_table_test::test_group_quote()
/// illustrations. Therefore, they aren't written in a compact way
/// or expanded by bloat().
-void report_table_test::test_illustration()
+void report_table_test::test_column_widths_for_illustrations()
{
static int const total_width = 576;
static int const default_margin = 14;
@@ -402,3 +404,98 @@ int test_main(int, char*[])
report_table_test::test();
return EXIT_SUCCESS;
}
+
+void report_table_test::test_paginator()
+{
+ // Original tests: vary only the number of data rows.
+
+ // Edge cases.
+ BOOST_TEST_EQUAL(1, page_count( 0, 5, 28));
+ BOOST_TEST_EQUAL(1, page_count( 1, 5, 28));
+ // Just a trivial sanity test.
+ BOOST_TEST_EQUAL(1, page_count(17, 5, 28));
+ // 4 full groups + incomplete last group.
+ BOOST_TEST_EQUAL(1, page_count(24, 5, 28));
+ // 5 full groups don't fit on one page.
+ BOOST_TEST_EQUAL(2, page_count(25, 5, 28));
+ // 4 + 4 groups + incomplete last one.
+ BOOST_TEST_EQUAL(2, page_count(44, 5, 28));
+ // 9 full groups don't fit on two pages.
+ BOOST_TEST_EQUAL(3, page_count(45, 5, 28));
+
+ // Test preconditions.
+
+ // Negative number of data rows.
+ BOOST_TEST_THROW
+ (page_count(-1, 1, 1)
+ ,std::runtime_error
+ ,lmi_test::what_regex("^Assertion.*failed")
+ );
+
+ // Zero rows per group.
+ BOOST_TEST_THROW
+ (page_count(1, 0, 1)
+ ,std::runtime_error
+ ,lmi_test::what_regex("^Assertion.*failed")
+ );
+
+ // Insufficient room to print even one group.
+ BOOST_TEST_THROW
+ (page_count(1, 7, 3)
+ ,std::runtime_error
+ ,lmi_test::what_regex("^Assertion.*failed")
+ );
+
+ // A single row of data.
+ BOOST_TEST_EQUAL(1, page_count(1, 1, 1));
+ BOOST_TEST_EQUAL(1, page_count(1, 1, 3));
+ BOOST_TEST_EQUAL(1, page_count(1, 3, 3));
+ BOOST_TEST_EQUAL(1, page_count(1, 3, 7));
+
+ // One-row groups:
+
+ // Page length an odd number.
+ BOOST_TEST_EQUAL(1, page_count(1, 1, 5));
+ BOOST_TEST_EQUAL(1, page_count(3, 1, 5));
+ BOOST_TEST_EQUAL(2, page_count(4, 1, 5));
+ BOOST_TEST_EQUAL(2, page_count(6, 1, 5));
+ BOOST_TEST_EQUAL(3, page_count(7, 1, 5));
+
+ // Same, but next even length: same outcome.
+ BOOST_TEST_EQUAL(1, page_count(1, 1, 6));
+ BOOST_TEST_EQUAL(1, page_count(3, 1, 6));
+ BOOST_TEST_EQUAL(2, page_count(4, 1, 6));
+ BOOST_TEST_EQUAL(2, page_count(6, 1, 6));
+ BOOST_TEST_EQUAL(3, page_count(7, 1, 6));
+
+ // Two-row groups.
+
+ // Page length four.
+ BOOST_TEST_EQUAL(1, page_count(1, 2, 4));
+ BOOST_TEST_EQUAL(1, page_count(3, 2, 4));
+ BOOST_TEST_EQUAL(2, page_count(4, 2, 4));
+ BOOST_TEST_EQUAL(2, page_count(5, 2, 4));
+ BOOST_TEST_EQUAL(3, page_count(6, 2, 4));
+
+ // Page length five: no room for widow and orphan control.
+ BOOST_TEST_EQUAL(1, page_count(1, 2, 5));
+ BOOST_TEST_EQUAL(1, page_count(4, 2, 5));
+ BOOST_TEST_EQUAL(2, page_count(5, 2, 5));
+ BOOST_TEST_EQUAL(2, page_count(8, 2, 5));
+ BOOST_TEST_EQUAL(3, page_count(9, 2, 5));
+
+ // Same, but next even length: same outcome.
+ BOOST_TEST_EQUAL(1, page_count(1, 2, 6));
+ BOOST_TEST_EQUAL(1, page_count(4, 2, 6));
+ BOOST_TEST_EQUAL(2, page_count(5, 2, 6));
+ BOOST_TEST_EQUAL(2, page_count(8, 2, 6));
+ BOOST_TEST_EQUAL(3, page_count(9, 2, 6));
+
+ // Page length seven: one extra data row possible on last page.
+ BOOST_TEST_EQUAL(1, page_count(1, 2, 7));
+ BOOST_TEST_EQUAL(1, page_count(4, 2, 7));
+ BOOST_TEST_EQUAL(1, page_count(5, 2, 7));
+ BOOST_TEST_EQUAL(2, page_count(6, 2, 7));
+ BOOST_TEST_EQUAL(2, page_count(8, 2, 7));
+ BOOST_TEST_EQUAL(2, page_count(9, 2, 7));
+}