lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [6589] Add averages sub-header to the group quote report (


From: gchicares
Subject: [lmi-commits] [6589] Add averages sub-header to the group quote report (VZ)
Date: Fri, 13 May 2016 14:04:33 +0000 (UTC)

Revision: 6589
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=6589
Author:   chicares
Date:     2016-05-13 14:04:33 +0000 (Fri, 13 May 2016)
Log Message:
-----------
Add averages sub-header to the group quote report (VZ)

Modified Paths:
--------------
    lmi/trunk/group_quote_pdf_gen_wx.cpp

Modified: lmi/trunk/group_quote_pdf_gen_wx.cpp
===================================================================
--- lmi/trunk/group_quote_pdf_gen_wx.cpp        2016-05-13 14:02:32 UTC (rev 
6588)
+++ lmi/trunk/group_quote_pdf_gen_wx.cpp        2016-05-13 14:04:33 UTC (rev 
6589)
@@ -526,7 +526,7 @@
         ,wxHtmlWinParser& html_parser
         ,int*             pos_y
         );
-    void output_table_totals
+    void output_aggregate_values
         (wxPdfDC&            pdf_dc
         ,wx_table_generator& table_gen
         ,int*                pos_y
@@ -599,6 +599,68 @@
     };
     totals_data totals_;
 
+    class averages_data
+    {
+      public:
+        averages_data()
+            {
+            for(int col = e_first_totalled_column; col < e_col_max; ++col)
+                {
+                int const n = index_from_col(col);
+                values_counts_[n] = 0;
+                mean_values_[n] = 0.0;
+                }
+            }
+
+        // Adds 1000*premium/face_amount to the values over which the mean
+        // value is computed. The value is silently ignored if the face amount
+        // is zero, which can happen if this column is not used at all in this
+        // quote.
+        void add_data_point(int col, double premium, double face_amount)
+            {
+            if(face_amount == 0.0)
+                {
+                return;
+                }
+
+            double const d = 1000.0*premium / face_amount;
+
+            // Iteratively compute the mean of the sequence of values using the
+            // simplified (as we don't need the standard deviation here)
+            // version of the algorithm described in Knuth's "The Art of
+            // Computer Programming, Volume 2: Seminumerical Algorithms",
+            // section 4.2.2.
+            //
+            // The algorithm defines the sequence M(k)
+            //
+            //  M(1) = x(1), M(k) = M(k-1) + (x(k) - M(k-1)) / k
+            //
+            // where x(k) is the k-th value and the mean value of the sequence
+            // up to the member N is simply the last value M(N).
+            int const n = index_from_col(col);
+            if(values_counts_[n]++ == 0)
+                {
+                mean_values_[n] = d;
+                }
+            else
+                {
+                mean_values_[n] += (d - mean_values_[n]) / values_counts_[n];
+                }
+            }
+
+        double mean(int col) const
+            {
+            return mean_values_[index_from_col(col)];
+            }
+
+      private:
+        static int index_from_col(int col) { return col - 
e_first_totalled_column; }
+
+        unsigned values_counts_[e_col_max - e_first_totalled_column];
+        double   mean_values_  [e_col_max - e_first_totalled_column];
+    };
+    averages_data averages_;
+
     struct page_metrics
         {
         page_metrics()
@@ -831,6 +893,10 @@
                     {
                     totals_.total(col, z);
                     }
+                else
+                    {
+                    averages_.add_data_point(col, z, basic_face_amount);
+                    }
                 }
                 break;
             case e_col_supplemental_face_amount:
@@ -850,6 +916,10 @@
                     {
                     totals_.total(col, z);
                     }
+                else
+                    {
+                    averages_.add_data_point(col, z, suppl_face_amount);
+                    }
                 }
                 break;
             case e_col_total_face_amount:
@@ -869,6 +939,10 @@
                     {
                     totals_.total(col, z);
                     }
+                else
+                    {
+                    averages_.add_data_point(col, z, total_face_amount);
+                    }
                 }
                 break;
             case e_col_max:
@@ -1020,7 +1094,7 @@
         table_gen.add_column(header, cd.widest_text_);
         }
 
-    output_table_totals(pdf_dc, table_gen, &pos_y);
+    output_aggregate_values(pdf_dc, table_gen, &pos_y);
 
     int const y_before_header = pos_y;
     table_gen.output_header(&pos_y);
@@ -1310,7 +1384,7 @@
     *pos_y += summary_height;
 }
 
-void group_quote_pdf_generator_wx::output_table_totals
+void group_quote_pdf_generator_wx::output_aggregate_values
     (wxPdfDC& pdf_dc
     ,wx_table_generator& table_gen
     ,int* pos_y
@@ -1323,8 +1397,10 @@
     table_gen.output_vert_separator(e_col_max, y);
 
     y += table_gen.row_height();
+    int const y_next = y + table_gen.row_height();
 
     table_gen.output_vert_separator(e_col_number, y);
+    table_gen.output_vert_separator(e_col_number, y_next);
 
     // Render "Census" in bold.
     wxDCFontChanger set_bold_font(pdf_dc, pdf_dc.GetFont().Bold());
@@ -1334,7 +1410,7 @@
         ,wxALIGN_LEFT
         );
 
-    // And the totals in bold italic: notice that there is no need to create
+    // And the aggregates in bold italic: notice that there is no need to 
create
     // another wxDCFontChanger here, the original font will be restored by the
     // one just above anyhow.
     pdf_dc.SetFont(pdf_dc.GetFont().Italic());
@@ -1346,6 +1422,12 @@
         ,wxALIGN_RIGHT
         );
 
+    pdf_dc.DrawLabel
+        ("Average Cost per $1000:"
+        ,table_gen.text_rect(e_first_totalled_column - 1, y_next)
+        ,wxALIGN_RIGHT
+        );
+
     for(int col = e_first_totalled_column; col < e_col_max; ++col)
         {
         int const num_dec =
@@ -1365,12 +1447,27 @@
             ,"$"
             ,ledger_format(totals_.total(col), f)
             );
+
+        // Only premium columns have averages, but we must output something for
+        // all cells to ensure that we use homogeneous background.
+        double const average = averages_.mean(col);
+        std::string lhs, rhs;
+        if(average != 0.0)
+            {
+            lhs = "$";
+            rhs = ledger_format(average, f);
+            }
+
+        table_gen.output_highlighted_cell(col, y_next, lhs, rhs);
         }
 
     table_gen.output_vert_separator(e_col_max, y);
     table_gen.output_horz_separator(e_col_number, e_col_max, y);
 
-    y += table_gen.row_height();
+    table_gen.output_vert_separator(e_col_max, y_next);
+    table_gen.output_horz_separator(e_first_totalled_column, e_col_max, 
y_next);
+
+    y = y_next + table_gen.row_height();
 }
 
 void group_quote_pdf_generator_wx::output_footer




reply via email to

[Prev in Thread] Current Thread [Next in Thread]