BACKGROUND OF THE INVENTION
I. FIELD OF THE INVENTION
[0001] This invention pertains to apparatus and method for sorting postal envelopes prior
to mailing, and particularly to such apparatus and method for presorting envelopes
in order to obtain postage discounts offered by the United States Postal Service.
II. PRIOR ART AND OTHER CONSIDERATIONS
[0002] The United States Postal Service is handling an ever increasing volume of domestic
mail. A large component of the domestic mail volume is attributed to postal patrons
who introduce large or bulk shipments of mail into the Postal Service. Examples of
such postal patrons include financial institutions (such as banks and credit card
companies that mail out periodic statements to their customers); utilities (which
mail out monthly or quarterly bills); charitable and non-profit institutions; and,
advertising agencies.
[0003] The United States Postal Service affords more favorable postage rates for postal
patrons who cooperate with the United States Postal Service by preparing bulk shipments
of mail in a manner more easily handled by the United States Postal Service. The United
States Postal Service defines its postage class structure, and the requirements for
obtaining the more favorable postage rates for bulk mail patrons, in a publication
called the
Domestic Mail Manual (also known as the "DMM").
[0004] By way of example for the foregoing, the DMM sets forth a schedule of rates and fees
for third class mail, with the postage rate for third class mail depending upon a
presort level of the mail. In this respect, for third class mail the DMM prescribes
the following presort levels for bulk rate mail: basic; basic ZIP + 4; 5 digit; 5
digit ZIP + 4; ZIP + 4 barcoded; and, carrier route. Of these presort levels, the
basic level is the most expensive, the basic ZIP +4 the second most expensive, and
so on with the carrier route presort level being the least expensive. Indeed, a patron
preparing a bulk shipment of mail can achieve a considerable postage savings depending
upon the extent to which the mailpieces included in the shipment qualify for the less
expensive presort levels.
[0005] Qualifying for a particular presort level involves more than the degree (five or
nine digit) and manner (barcoded or not) by which ZIP code information is provided
on the mailpieces. For a mailpiece to qualify for most of the presort levels, the
DMM further requires that the mailpiece be included as a part of a package (a specified
number, such as 10 or more) of mailpieces packaged (i.e., associated by a rubberband)
in accordance with specified criteria (such as the same carrier route, same 5 digit
ZIP code destination, same 3 digit ZIP code prefix destination, for examples). In
addition, to qualify for most of the presort levels, in accordance with specified
criteria the postal patron must place the packages in a sack along with other mailpieces,
and the sack must contain at least a specified minimum number of pieces (or have at
least a specified minimum weight). Examples of such specified criteria for inclusion
of mailpieces in the same sack are that the mailpieces either be destined to the same
carrier route, the same 5 digit ZIP code destination, or the same 3 digit ZIP code
prefix destination.
[0006] In addition to complying with the foregoing package and sack requirements, the postal
patron must apply a label or tag, having a prescribed format, to each sack. As required
by the DMM, the sack tag or label must include select information regarding the contents
of the sack.
[0007] Thus, in order to obtain the maximum possible postage savings for each mailpiece,
a postal patron must presort the mailpieces in accordance with ZIP code; must attempt
to associate mailpieces in accordance with DMM specifications into packages; must
attempt to associate packages in accordance with DMM specifications into sacks; and,
must generate a label for each sack in accordance with the format prescribed by the
DMM. It should become apparent that factors such as insufficient quantity and thin
geographical distribution may disqualify many of the mailpieces included in a bulk
shipment from receiving the most favored presort level. A greater postage rate associated
with a less favored presort level must be paid for a mailpieces disqualified from
the most favored presort level.
[0008] Large bulk shipments of mail can be presorted in ZIP code groupings using automated
sorting machines, such as those provided by the Bell & Howell Phillipsburg Company.
Examples of such automated sorting machines include the Bell & Howell Phillipsburg
Company model 1000, 800, and 600 Mail Processing Systems. These automated sorting
machines read optical characters and/or bar code and sort mail into bins.
[0009] While the prior art automated sorting machines cited above perform admirably for
their initially intended purposes, the machines still required much human thought
in the preparation of packages and associating of packages into sacks for obtaining
the more favorable presort levels. In this respect, a human operator must mentally
determine how to associate into packages and sacks mailpieces from numerous and often
non-adjacent bins of the sorting machine. Such tedious determinations are subject
to human error. Erroneous packaging and sacking of mailpieces causes considerable
consternation with the United States Postal Service, and may jeopardize or render
suspect the entire bulk mail shipment.
[0010] In order to qualify as many mailpieces as possible for the most favored presort levels,
many companies and organizations send their bulk shipments to a third party company
such as a presort agency for combining with the bulk shipments of other companies
and organizations. By combining the bulk mail shipments of several postal patrons,
and by presorting the combined mail for the several patrons on the automated sorting
machines described above, the presort agencies are often able to leverage the quantity
and geographical distribution factors in order to qualify the maximum number of mailpieces
for the most favored presort levels. Unfortunately, since some mailpieces do not achieve
the most favored presort levels, it is very difficult for the presort agencies to
allocate the postage costs (e.g., qualified discount vs. non-qualified postage rate)
incurred among the contributing patrons.
[0011] Moreover, some postal patrons meter the mailpieces included in a bulk shipment with
postage prior to conducting their own in-house sorting or prior to sending the shipment
to a presort agency. In such cases, it may turn out that a mailpiece pre-metered at
a rate for a favored presort level may not qualify for that presort level, with the
result that additional postage must be applied to that mailpiece. When the mailpieces
of more than one patron are combined or commingled, as at a presort agency, it is
very difficult from an accounting standpoint to allocate the resultant postage increase
triggered by the non-qualifying pre-metered mailpiece to the postal patron from whom
the mailpiece came.
[0012] As mentioned above, some postal patrons meter the mailpieces included in a bulk shipment
prior to the sorting operation (either in-house or at a presort agency). Other postal
patrons use the "permit" mail provisions of the United States Postal Service. Traditionally
the United States Postal Service has refused to accept bulk shipments that include
both pre-metered and permit mail, in view inter alia of the difficulty in verifying
the accuracy of the computed postage amounts.
[0013] In view of the foregoing, it is an object of the present invention to provide a sorting
method and apparatus for associating mailpieces in a manner conducive for collection
and associating into packages and sacks for obtaining desired postage presort levels.
[0014] An advantage of the present invention is the provision of method and apparatus for
sorting mailpieces and for providing reports indicative of the postage presort levels
into which mailpieces are classified.
[0015] Another advantage of the present invention is the provision of method and apparatus
for sorting mailpieces wherein sack labels are automatically generated for sacks of
mail.
SUMMARY
[0016] A mail sorting machine includes an input hopper; a mailpiece reading and processing
section; and, a sorting bin section comprising a plurality of bins. The reading and
processing section includes a CPU which executes a program ANALYZE_MAIL for sorting
third class mailpieces. The program ANALYZE_MAIL sorts the mailpieces included in
a batch into packages, and then associates the packages into sacks or bags. The program
ANALYZE_MAIL constructs the packages and sacks to obtain maximum postage discounts.
[0017] Upon an initial physical pass of all mailpieces of a batch through the sorting machine,
the program ANALYZE_MAIL generates output advising how the bins are to be associated
for subsequent passes. As a result of the first physical pass, the program ANALYZE_MAIL
classifies the mailpieces of the batch into a plurality of "groups". A "group" is
a set of mailpieces which is to be separately sorted, independently from the remainder
of the batch, during one or more "passes" of the sorting machine. For example, after
the first or initial physical pass, for a first subsequent pass only a first group
of mailpieces is loaded into the input hopper; for a second subsequent pass only a
second group of mailpieces is loaded into the input hopper; and so forth. In general,
during the first physical pass, mailpieces belonging to a first group are assigned
to a first set of bins; mailpieces belonging to a second group are assigned to a second
set of the bins; and so forth.
[0018] In addition to assigning mailpieces to specified groups (i.e., bins) during the first
physical pass, the program ANALYZE_MAIL also generates a report which informs the
operator from which bins to collect each group. Advantageously, each group is collected
from physically adjacent bins. Moreover, the program ANALYZE_MAIL also generates a
report for each group, which report indicates from which bins mailpieces are to be
collected into sacks. Advantageously, the sack is composed of mailpieces from physically
adjacent bins. Further, the program ANALYZE_MAIL generates "bag tags" (also known
as "sack tags") for each sack, with the bag tag bearing information to apprise the
operator from which bins to gather the contents of the sack, as well as the sack and
group number.
[0019] The program ANALYZE_MAIL also includes an accounting capability for billing postage
to a possible plurality of clients having mailstreams included in the batch, and for
allocating postage costs in accordance with whether the client's mailpieces qualify
for postage discounts.
BRIEF DESCRIPTION OF THE DRAWINGS
[0020] The foregoing and other objects, features, and advantages of the invention will be
apparent from the following more particular description of preferred embodiments as
illustrated in the accompanying drawings in which reference characters refer to the
same parts throughout the various views. The drawings are not necessarily to scale,
emphasis instead being placed upon illustrating the principles of the invention.
[0021] Fig. 1 is a top schematic view of a sorter apparatus according to an embodiment of
the invention.
[0022] Fig. 2 is a schematic view of electronic circuitry included in the sorter apparatus
of the embodiment of Fig. 1.
[0023] Fig. 3 is an isometric view of an edge post and hook assembly provided thereon according
to the embodiment of Fig. 1.
[0024] Fig. 4 is a schematic view showing the interrelationships between Figs. 4A - 4N.
[0025] Figs. 4A - 4N are schematic views showing a series of functions and their constituent
steps executed in accordance with a program ANALYZE_MAIL by the sorter apparatus of
the embodiment of Fig. 1.
DETAILED DESCRIPTION OF THE DRAWINGS
[0026] Fig. 1 shows a sorter apparatus 20 according to an embodiment of the invention. The
sorter 20 includes a reading and processing section 22 and a sorting bin section 24.
The sorting bin section 24 includes a plurality of bins 26 into which mailpieces are
ultimately sorted. In one embodiment, 128 such bins 26, numbered as bins 26₁-26₁₂₈,
are provided (although not all of the 128 such bins 26 are illustrated in Fig. 1).
It should be understood that in other embodiments a different number of bins are provided.
[0027] The processing section 22 includes an input hopper 30; a feeder 31; and a mailpiece
transport assembly 32 which directs mailpieces along a processing path 33. Along the
processing path 33 are various processing stations also included in the processing
section 22, including an optical character recognition (OCR) station 34; an ink jet
printer station 36; a bar code reader station 38.
[0028] As shown in Fig. 1, a plurality of hopper floor belts 40 and hopper augers 42 transport
incoming mailpieces on edge in the direction of arrow 44 toward the feeder 31. The
feeder 31, being of a rotating belt variety, feeds the leading mailpiece in the hopper
31 in the direction of the processing path 33 (i.e., in the direction of arrow 46).
The mailpieces travel on edge down the processing path 33 along the OCR station 34,
the ink jet printer station 36, the bar code reader section 38, and into the sorting
bin section 24.
[0029] The processing section 22 also includes an operator console 50 and a data processing
system 52. The data processing system 52 includes a central processing unit (CPU)
54 and an I/O interface 56 (see Fig. 2). The CPU 54 communicates through the I/O interface
56 to various peripheral devices, including a keyboard 58; a monitor 60; a report
printer 62; a bag tag or sack tag printer 64; and, a disk drive 66 (see Fig. 2). In
addition, the CPU 54 communicates through the I/O interface 56 to electronics for
the aforementioned OCR station 34; ink jet printer station 36; bar code reader station
38; and, operator console 50.
[0030] The operator console 50 includes a start switch 70 and stop switch 72, as well a
feed select switch 74 and a series of status indicator lights 76. The feed select
switch 74 is used to control the rate at which the feeder 31 feeds mailpieces from
the input hopper 30 toward the mail processing path 33.
[0031] The sorting bin section 24 includes a central transport assembly 80 which directs
mailpieces along a sorting path that is collinear with the processing path 33 of the
processing section 22. That is, the central transport assembly 80 of the sorting bin
section 24 continues to transport a mailpiece in the direction of arrow 46 through
the sorting bin section 24 until the mailpiece is deflected into an appropriate one
of the bins 26. The central transport assembly 80 includes a plurality of unillustrated
transport belts.
[0032] As shown in Fig. 1, bins are provided on both sides of the sorting path in paired
relationship. That is, at the same distance from the processing section 22, bin 26₁
is paired with bin 26₁₂₈; a little further downstream bin 26₂ is paired with bin 26₁₂₇;
and so forth until the downstream-most pair of bins 26₆₄ and 26₆₅.
[0033] The sorting path is defined by a plurality of diverter gates 82 and sorting path
walls 84. Each bin 26 has a diverter gate 82 and a sorting path wall 82 associated
therewith. When activated, a diverter gate 84 pivots about a pivot point (such as
pivot point 86 shown with respect to diverter gate 82₁ of bin 26₁) for diverting a
mailpiece from the sorting path into its respective bin. Each sorting path wall 84
has a rear ramp surface 88 inclined with respect to the sorting path. The rear ramp
surface 88 and the diverter gate 82 form a planar surface inclined with respect to
the sorting path when the diverter gate 82 is pivoted to deflect mailpieces out of
the sorting path and into the bin 26. The angle of inclination of this planar surface
including the rear ramp surface 88 facilitates direction of the on edge mailpiece
into the queue of mailpieces developing in the bin.
[0034] In addition to the rear ramp surface 88, a bin 26 is defined by a horizontal bin
floor 90 and a leading edge abutment rail 92. The leading edge abutment rail is suspended
above the horizontal bin floor 90 between the sorting path wall 84 and a vertical
edge post 94. As shown in Figs. 1 and 3, the leading edge abutment rail extends through
an aperture provided in a travelling vertical plate 96. The bin floor 90 has an auger
98 provide therein which transports mailpieces diverted into the bin 26 in a direction
perpendicular and away from the sorting path. For example, with reference to bin 26₁,
the auger 98₁ directs deflected mailpieces away from the sorting path in the direction
of arrow 100. The leading or first such mailpiece deflected into a bin 26 contacts
the travelling plate 96. As successive mailpieces are diverted into a bin 26 and interposed
between the ramp surface 88 and the previous mailpiece, the travelling plate 96 is
slidingly pushed along the abutment rail 92 away from the sorting path toward the
edge post 94. Near the edge post 94 a pressure sensor switch 102 is provided to detect
when a bin 26 is becoming full. In this respect, when a sufficient number of mailpieces
are diverted into a single bin 26 such that the travelling plate 96 closes the pressure
sensor switch 102 for that bin, the sorting operation is temporarily halted an a diagnostic
message is provided to the operator so that mailpieces diverted to the bin can be
manually removed for accommodating additional mailpieces in that bin.
[0035] As is shown in Fig. 3, each edge post 94 has hook assembly 104 provided thereon for
engaging mail sacks, for example. The hook assembly 104 comprises two perpendicular
bracket members 106a and 106b. The hook assembly 104 is mounted on the edge post 94
by fasteners 108 which extend through the bracket member 106a. The bracket member
106b has two U-shaped hooks 110 provided thereon. The hooks 110 engage one of the
metal rings 112 provided around the mouth of a mail sack 114.
[0036] Referring again to the diverter gates 82 provided along the sorting path, each diverter
gate 82 is activated by a solenoid 120. The solenoids 120 of each pair of bins are
controlled by bin pair controller 122, there being 64 such bin pair controllers 122
shown in the embodiment of Fig. 1. Bin pair controller 122₁ controls the solenoids
120₁ and 120₁₂₈ for bins 26₁ and 26₁₂₈, respectively; bin pair controller 122₂ controls
the solenoids 120₂ and 120₁₂₇ for bins 26₂ and 26₁₂₇, respectively; and so forth.
[0037] The bin pair controllers 122 are connected in series to the I/O interface 56 of the
data processing system 52 in shift register fashion along line 124. The signal carried
on line 124 is a digital signal indicative of the bin number to which a mailpiece
should be directed in accordance with the sorting operation. The signal from the I/O
interface 56 is first applied to the bin pair controller 122₁ as a mailpiece approaches
diverter gates 82₁ and 82₁₂₈. If the signal indicates that the mailpiece is destined
for either bin 26₁ or bin 26₁₂₈, the bin pair controller, upon evaluating the signal,
causes activation of the appropriate solenoid 120. If the signal indicates that the
mailpiece is destined for another downstream bin 26, the signal for that mailpiece
is shifted downstream to the bin pair controller 122₂ as the mailpiece approaches
diverter gates 82₂ and 82₁₂₇ associated with bins 26₂ and 26₁₂₇. The bin pair controller
122₂ then either activates an appropriate solenoid 120 or shifts the signal yet further
downstream along with the travelling mailpiece.
[0038] The data processing system 52, and particularly the CPU 54 executes a set of instructions
that control the operation of the sorter 20. That set of instructions in collectively
referred to as program ANALYZE_MAIL. The program ANALYZE_MAIL consists of numerous
subsets of instructions coded in the "C" programming language, which subsets are referred
to herein as "functions". Execution of the program ANALYZE_MAIL and its constituent
functions causes the sorting machine 20 to operate in the manner described below.
In connection with the ensuing description of the operation of the sorting machine
20, it should be understood that the word "bundle" is often used interchangeably with
"package", and that the word "bag" is often used interchangeably with "sack".
OPERATION
[0039] In the operation of the sorting machine 20 of Fig. 1, a batch of third class mail
is placed in the input hopper 30. The batch may comprise a plurality of mailstreams
from a plurality of patrons. In the example discussed hereinafter particularly with
reference to the TABLES, the batch includes mailstreams from an insurance company
patron, a utility company patron, and a publishing company patron. The insurance company
actually contributes three separate mailstreams to the batch, in particular an automotive
insurance mailstream, a life insurance mailstream, and a health insurance mailstream.
[0040] After the mailstreams are all loaded into the input hopper 30, and when the CPU 54
is running the program ANALYZE_MAIL and the start switch 70 is turned on, the operator
activates the feed select switch 74. Activation of the feed select switch 74 initiates
a first physical pass of the mailpieces through the sorter 20, which includes transport
of the mailpieces through the input hopper 30 in the direction of arrow 44; through
the processing section 32 (in the direction of arrow 46); and, into the sorting bin
section 24. As each mailpiece is transported through the processing section 22, the
OCR 34 reads the character address; the ink jet printer 36 prints a barcode corresponding
to the character-read ZIP code; and, the bar code reader 38 verifies the printed bar
code.
[0041] As discussed hereinbefore, the program ANALYZE_MAIL executed by sorting machine 20
collectively sorts the entire batch, comprising the mailstreams of all the patrons,
in order to achieve the optimum third class postage discounts in accordance with the
DMM. In order to do so, the program ANALYZE_MAIL associates the mailpieces of the
batch into "packages" (also known as "bundles"), and the packages are associated into
sacks or bags.
[0042] In the above regard, the program ANALYZE_MAIL creates four different package types,
notably: five digit (or "5") packages; three digit ("3") packages; state ("S") packages;
and, mixed state (or "M") packages. Generally, packages must consist of ten (10) or
more mailpieces satisfying the same package ZIP code rule. For example, all the mailpieces
in a FIVE_DIGIT package must be destined for the same five digit zip code. All the
mailpieces included in a THREE_DIGIT package must have the same three initial three
ZIP code digits (e.g., 22151, 22153, 22155, 22165). All the mailpieces included in
a single STATE package must have initial ZIP code digits which destine the mailpieces
to the same state (e.g., to Illinois).
[0043] As is more fully explained by the DMM, to qualify for certain third class postage
discounts, the packages must in turn be placed into sacks consisting of a minimum
number of mailpieces (or a minimum weight). Typically the minimum number of mailpieces
per sack is 125, or alternatively the minimum weight is 15 pounds. Accordingly, the
program ANALYZE_MAIL creates four different sack types: FIVE_DIGIT sacks; THREE_DIGIT
sacks; STATE sacks; and MIXED_STATE sacks.
[0044] As a result of the first physical pass, the program ANALYZE_MAIL classifies the mailpieces
of the batch into a plurality of "groups". A "group" is a set of mailpieces which
is to be separately sorted, independently from the remainder of the batch, during
one or more "passes" of the sorting machine 20. For example, after the first or initial
physical pass, for a first subsequent pass only a first group of mailpieces is loaded
into the input hopper 30; for a second subsequent pass only a second group of mailpieces
is loaded into the input hopper 30; and so forth. In general, during the first physical
pass, mailpieces belonging to a first group are assigned to a first set of bins 26;
mailpieces belonging to a second group are assigned to a second set of the bins 26;
and so forth.
[0045] In addition to assigning mailpieces to specified groups (i.e., bins) during the first
physical pass, the program ANALYZE_MAIL also generates a report in the form of TABLE
1 which informs the operator from which bins 26 to collect each group. Advantageously,
each group is collected from physically adjacent bins 26. Moreover, the program ANALYZE_MAIL
also generates a report in the form of TABLE 2A for each group, which report indicates
from which bins mailpieces are to be collected into sacks. Advantageously, the sack
is composed of mailpieces from physically adjacent bins 26. Further, the program ANALYZE_MAIL
generates "bag tags" (also known as "sack tags") for each sack, with the bag tag bearing
information to apprise the operator from which bins 26 to gather the contents of the
sack, as well as the sack and group number. A format for a plurality of bag tags is
illustrated in TABLE 3.
[0046] In addition, during the first physical pass, the program ANALYZE_MAIL generates a
number of accounting reports as exemplified by TABLES 4, 5, 6, and 6A discussed infra.
Function FIRST_SORT_PASS
[0047] As a result of the execution of a function FIRST_SORT_PASS, three files are created
during the first physical pass, including file COUNT.DAT, file AGGR.DAT, and CLIENT1.DAT.
The creation of these three files is indicated by steps 200, 202, and 204 in Fig.
4A.
[0048] The size of the file COUNT.DAT (i.e., the number of records in the file) depends
on the number of unique zip codes and mailstreams encountered during the first physical
pass.
[0049] The format of each record in file COUNT.DAT is as follows:

[0050] After the first physical pass, the records in file COUNT.DAT are sorted in ascending
order. In this respect, a primary sortation is done by ZIP code. For ZIP codes repeated
due to their usage in different client/mailstreams, a secondary sortation is performed
by first sorting the client index number, followed by the stream index number.
[0051] The following is an example of how multiple records in the file COUNT.DAT are stored
(note that the binary values are converted to ascii for display purposes):
ZIP CODE |
stream |
client |
bin |
5 Digit |
ZIP+4 |
ZIP+4 Barcoded |
203460000 |
2 |
1 |
3 |
12 |
3 |
7 |
203500000 |
1 |
1 |
3 |
1 |
0 |
3 |
203500000 |
3 |
1 |
3 |
0 |
0 |
1 |
203500000 |
2 |
3 |
3 |
1 |
0 |
0 |
203500000 |
0 |
7 |
3 |
0 |
2 |
0 |
302530000 |
2 |
1 |
4 |
0 |
0 |
5 |
406770000 |
1 |
1 |
5 |
0 |
1 |
3 |
[0052] File AGGR.DAT is a binary file of fixed length. Each entry is four bytes long representing
a long integer. The first 256 entries is an array of bin counts where each individual
bin count is indexed by bin. The 257th entry represents the total number of mailpieces
fed, the 258th entry represents the total number of mailpieces read, and the last
entry represents the total 5 Digit ZIP count (OCR and Barcoded mailpieces). The following
summarizes the file format for file AGGR.DAT:
- counts by bin
- - 256 entries, each entry 4 bytes
- total fed
- - 1 entry 4 bytes long
- total read
- - 1 entry 4 bytes long
- total 5 Digit count
- - 1 entry 4 bytes long
[0053] The file CLIENT1.DAT is a binary file containing ten bytes per record. Each record
contains the following data and is presented in order:

File CLIENT1.DAT contains a variable number of records, depending on the number of
unique clients and mailstreams used. The records in this file are sorted in ascending
order. A sortation is performed by first sorting the client index number followed
by the stream index number.
[0054] The following discussion describes other steps executed by the CPU 54 in connection
with a plurality of functions included in the program ANALYZE_MAIL.
Function ASSIGN_PACKAGES
[0055] The function ASSIGN_PACKAGES (see Fig. 4A) takes records from file COUNT.DAT and
assigns package types to each zip code. The package types are reflected by the numbers
"5" and "3" and the letters "S" and "M". A package type of "5" refers to a five digit
package; a package type of "3" refers to a three digit package; a package type of
"M" refers to mixed states package; a package type of "S" refers to a state package.
[0056] During the first pass through the records in the file COUNT.DAT, the function ASSIGN_PACKAGES
initially examines each record in the file COUNT.DAT in the record order noted above
in order to determine potential three digit packages (i.e., packages wherein all the
mailpieces have identical first three ZIP code digits, but which do not qualify as
five digit packages) [reflected by step 250] and potential state packages [reflected
by step 252]. In this regard, the function ASSIGN_PACKAGES examines the field ZIP
CODE for the current record to determine whether the record has the same ZIP code
as did the next previous record. (Consecutive records might have the same ZIP codes
when the same ZIP codes are present in different mailstreams). If the ZIP code for
the currently examined record is the same as the previous record, the function ASSIGN_PACKAGES
determines the total number of mailpieces represented by the record by adding the
values in the "5 Digit", "ZIP+4", and "ZIP+4 Barcoded" fields of the record and adds
that sum to a running total mailpiece counter (in location CNT) for this ZIP code.
[0057] If the ZIP code for the currently examined record differs from the previous record,
the function ASSIGN_PACKAGES momentarily lays aside the current record to process
the mailpiece count for the previous ZIP code (i.e, the ZIP code for the previous
record). In this respect, the function ASSIGN_PACKAGES determines whether the number
of mailpieces for the previous ZIP code was less than the predetermined minimum bundle
size. If it was, the function ASSIGN_PACKAGES realizes that the previous ZIP code
might qualify for a three digit package. To do this, the function ASSIGN_PACKAGES
determines to what 3 Digit ZIP code the previous ZIP code belongs (i.e, determines
the first three digits of the previous ZIP code).
[0058] The function ASSIGN_PACKAGES then assigns the total count of the number of mailpieces
for the previous ZIP code (stored at location CNT) to a three digit package counter
for the 3 Digit ZIP code to which the previous ZIP code belongs (i.e, to counter THREE_DIGIT_PACK_CNT[3_DIGIT_ZIP]).
[0059] After processing the mailpiece count for a previous ZIP code in the manner described
above, the function ASSIGN_PACKAGES returns to processing the ZIP code for the current
record. At this juncture, the function ASSIGN_PACKAGES assigns to the mailpiece counter
CNT the sum of the values in the "5 Digit", "ZIP+4", and "ZIP+4 Barcoded" fields of
the current record. The function ASSIGN_PACKAGES then examines the next record in
the file COUNT.DAT, and continues the process described above for each such record
until an end of file is encountered.
[0060] After determining the potential three digit packages at step 250, the function ASSIGN_PACKAGES
attempts to locate potential state packages (step 252). In this regard, the function
ASSIGN_PACKAGES compares the number of mailpieces assigned to each 3 Digit ZIP code
with the predetermined minimum number of mailpieces necessary to make up a package
(e.g., 10). If the actual number of counted mailpieces for an 3 Digit ZIP code is
less than the predetermined minimum, the function ASSIGN_PACKAGES determines with
which state the 3 Digit ZIP code is associated, and increments a state package counter
for that state (i.e., STATE_PACK_CNT(i); where i = a number corresponding to the associated
state). Also, if the number of counted mailpieces for an 3 Digit ZIP code is less
than the predetermined minimum, the corresponding three digit package counter (THREE_DIGIT_PACK_CNT)
is set to zero.
[0061] Having determined potential three digit packages and potential state packages in
the manner described above (steps 250 and 252), the function ASSIGN_PACKAGES then
conducts a second pass through the file COUNT.DAT in order to create a temporary file
SACK1.TMP (step 254). As will be seen later, the file SACK1.TMP is used by function
ASSIGN_SACKS to generate a file SACK2.TMP. The file SACK1.TMP contains multiple records
of the following structure:

Thus, the file SACK1.TMP is much reduced in size from the file COUNT.DAT since the
multiple zip_id entries due to client/mailstream selections are combined. Also, the
three different count categories ("ZIP+4"; "5 Digit"; and "ZIP+4 Barcoded") are combined
into one count value (CNT) since the sortation of mail only depends on the combined
count. The file SACK1.TMP is created in ZIP code order.
[0062] As mentioned above, the function ASSIGN_PACKAGES creates the file SACK1.TMP during
the second pass through the file COUNT.DAT (step 254). During the second pass through
file COUNT.DAT the function ASSIGN_PACKAGES examines each record of file COUNT.DAT
in a manner similar to the first pass. The function ASSIGN_PACKAGES determines whether
the ZIP code for each currently examined record in file COUNT.DAT is the same as for
the previous record. If the ZIP code is the same, the function ASSIGN_PACKAGES determines
the total number of mailpieces represented by the record and adds that number to a
cumulative counter (CNT) for the total number of mailpieces for that ZIP code.
[0063] When, during the second pass through file COUNT.DAT, the function ASSIGN_PACKAGES
encounters a record having a ZIP code which differs from the previous ZIP code (i.e.,
the ZIP code of the previous record), the function ASSIGN_PACKAGES prepares a record
for file SACK1.TMP for the previous ZIP code. In this respect, in creating the record,
the previous ZIP code is stored in the ZIP_ID field of the structure PACKAGE and the
current value of the counter CNT is stored in the CNT field of the structure PACKAGE.
A value for the bin assignment (BIN) for the mailpieces for this package is obtained
from the corresponding "bin" field from the record in the COUNT.DAT file. The value
for the package type (PTYPE) is determined as follows.
[0064] In determining the package type (PTYPE) for a package of mailpieces, the function
ASSIGN_PACKAGES determines whether the total number of mailpieces for the ZIP code
(stored in location CNT) exceeds the predetermined minimum package size (e.g., 10).
If the predetermined minimum is equalled or exceeded, the function ASSIGN_PACKAGES
assigns a "5" value to the PTYPE field for the record in the structure PACKAGE associated
with this ZIP code. The "5" value in the PTYPE field is indicative of the fact that
the package is a "5 Digit Package", meaning that all the mailpieces in this package
have the identical first five digit ZIP codes.
[0065] If the total number of mailpieces for the ZIP code is less than the predetermined
minimum package size, the function ASSIGN_PACKAGES determines to what 3 Digit ZIP
code this ZIP code belongs. Then the function ASSIGN_PACKAGES determines whether the
three digit package counter (THREE_DIGIT_PACK_CNT[3_DIGIT_ZIP]) for the 3 Digit ZIP
code equals or exceeds the predetermined minimum package size. If (THREE_DIGIT_PACK_CNT[3_DIGIT_ZIP])
for the 3 Digit ZIP code equals or exceeds the predetermined minimum package size,
then the function ASSIGN_PACKAGES assigns a "3" value to the PTYPE field for the record
in the structure PACKAGE.
[0066] If the total number of mailpieces for the 3 Digit ZIP code is less than the predetermined
minimum package size, the function ASSIGN_PACKAGES determines to what state this 3
Digit ZIP code belongs. Then the function ASSIGN_PACKAGES determines whether the state
package counter (STATE_PACK_CNT) for this state equals or exceeds the predetermined
minimum package size. If the state package counter for this state equals or exceeds
the predetermined minimum package size, then the function ASSIGN_PACKAGES assigns
a "S" value to the PTYPE field for the record in the structure PACKAGE.
[0067] If the function ASSIGN_PACKAGES cannot assign a "5", "3", or "S" value to the PTYPE
field for this record in the SACK1.TMP file, a "M" value (indicative of "Mixed State
Packages) is assigned to the PTYPE field.
Function ASSIGN_SACKS
[0068] Function ASSIGN_SACKS (see Fig. 4A) uses the file SACK1.TMP created by function ASSIGN_PACKAGES
to generate another file (file SACK2.TMP). In so doing, function ASSIGN_SACKS makes
tentative sack assignments.
[0069] The file SACK2.TMP is a temporary work file for making sack assignments to ZIP codes.
Once created by function ASSIGN_SACKS, the file SACK2.TMP contains multiple records
of the following structure:

where the structure PACKAGE is as formerly defined.
[0070] There are five possible sack assignments: FIVE_DIGIT; MIXED_FIVE; THREE_DIGIT; STATE;
and MIXED_STATES.
[0071] The function ASSIGN_SACKS reads through the file SACK1.TMP in two passes. During
the first pass, the function ASSIGN_SACKS obtains certain sack counts. During the
second pass, the function ASSIGN_SACKS generates the file SACK2.TMP.
[0072] During the first pass through the file SACK1.TMP, function ASSIGN_SACKS determines
the 3 Digit ZIP code and the package type (PTYPE) assigned to each record in the file
SACK1.TMP. If the package type (PTYPE) of a record is "5", the package count (CNT)
for that package is checked to determine whether the package contains enough mailpieces
to be its own sack (step 260). This is done by comparing the package count (CNT) value
of the package to a predetermined minimum mailpiece number necessary to make up a
sack ("MIN_MAIL"). If the package count (CNT) does not qualify the package to be its
own sack, then the function ASSIGN_SACKS realizes that this "5" type package may be
part of a MIXED_FIVE; THREE_DIGIT; STATE; or MIXED_STATES sack. Accordingly, for the
3 Digit ZIP code corresponding to the ZIP code for the current package, the function
ASSIGN_SACKS adds the package count (CNT) to a "mixed five sack counter" (MIXED_FIVE_SACK_CNT[3_DIGIT_ZIP])
[step 262].
[0073] For packages belonging to the other types (PTYPE = 3, S, or M), the function ASSIGN_SACKS
adds the package count (CNT) to the appropriate counter (step 262). For example, for
a record in SACK1.TMP having a PTYPE = 3, the function ASSIGN_SACKS adds the package
count (CNT) of that record to a "three digit sack counter" (THREE_DIGIT_SACK_CNT[3_DIGIT_ZIP])
for the 3 Digit ZIP code for the ZIP code of the record. Similarly, a unique counter
exists for each state (STATE_SACK_CNT) and each mixed state (MS_SACK_CNT).
[0074] The function ASSIGN_SACKS then checks the potential mixed five, three digit, and
state sack counts (step 264). First, for each 3 Digit ZIP code, the function ASSIGN_SACKS
checks the value of the counter MIXED_FIVE_SACK_CNT to determine whether each potential
mixed five sack has the predetermined minimum number of mailpieces to be a sack. If
the counter MIXED_FIVE_SACK_CNT falls short of the predetermined minimum number, then
it is assumed for the moment that these mailpieces, previously thought to comprise
a mixed five sack, should now comprise a three digit sack. To this end, the value
of the counter MIXED_FIVE_SACK_CNT[3_DIGIT_ZIP] for this 3 Digit ZIP code is added
to the counter THREE_DIGIT_SACK_CNT[3_DIGIT_ZIP] for the 3 Digit ZIP code. The value
of the counter MIXED_FIVE_SACK_CNT for this 3 Digit ZIP code is then re-initialized
at zero.
[0075] In the same manner the function ASSIGN_SACKS checks the number of mailpieces in each
potential three digit sack to insure that the potential sack has the predetermined
minimum number of mailpieces to qualify as a sack. If the value of THREE_DIGIT_SACK_CNT[3_DIGIT_ZIP]
does not have the predetermined minimum number of mailpieces, it is assumed that these
mailpieces should now be part of a state sack. Accordingly, a state sack counter (STATE_SACK_CNT)
for the state having the concerned 3 Digit ZIP code is incremented by the value of
the THREE_DIGIT_SACK_CNT[3_DIGIT_ZIP], and the value of the counter THREE_DIGIT_SACK_CNT[3_DIGIT_ZIP]
is reinitialized at zero.
[0076] In the same manner the function ASSIGN_SACKS checks the number of mailpieces in each
potential state sack to insure that the potential state sack has the predetermined
minimum number of mailpieces to qualify as a sack. If the value of STATE_SACK_CNT
for the state does not have the predetermined minimum number of mailpieces, it is
assumed that these mailpieces should now be part of a mixed state sack. Accordingly,
a mixed state sack counter (MS_SACK_CNT) is incremented by the value of the STATE_SACK_CNT
for the affected state, and the value of the counter STATE_SACK_CNT for the affected
state is reinitialized at zero.
[0077] During the second pass through the file SACK1.TMP the function ASSIGN_SACKS uses
the data in the file SACK1.TMP and the various sack counters described above (MIXED_FIVE_SACK_CNT;
THREE_DIGIT_SACK_CNT; STATE_SACK_CNT; and, MS_SACK_CNT) to create the new file SACK2.TMP
(step 266). As the function ASSIGN_SACKS reads through each record in file SACK1.TMP,
the function ASSIGN_SACKS again examines the package type (PTYPE) and obtains the
3 Digit ZIP Code corresponding to the ZIP code stored in the record. For records in
SACK1.TMP having a record type "5" (i.e., PTYPE = 5) and a package count (CNT) exceeding
the predetermined minimum number required to form sack, a record is created in file
SACK2.TMP having a five digit sack type value (STYPE = FIVE_DIGIT).
[0078] If a record has a record type "5" but does not represent the predetermined minimum
number of mailpieces for a FIVE_DIGIT sack, the associated count is compared to see
if it exceeds the minimum sack count for the next lowest priority sack type (i.e.,
sack type MIXED_FIVE) to which it belongs. If it does, a record is created in file
SACK2.TMP having a mixed five sack type value (STYPE = MIXED_FIVE). If the record
does not represent the minimum sck count, the same type process is repeated for the
remaining lower priority sacks in the order THREE_DIGIT, followed by STATE. If the
record does not meet the minimum number for any of the above sack types, it is assigned
a MIXED_STATES sack type.
[0079] For records in SACK1.TMP having a package record type of "3", a similar count comparison
is performed as above. However, the check begins with the THREE_DIGIT sack count level
so only THREE_DIGIT, STATE, and MIXED_STATES assignments can be made.
[0080] For records in SACK1.TMP having a package record type of "S" a similar count comparison
is performed as above. However, the check begins with the STATE sack count level so
that only STATE and MIXED_STATES assignments can be made.
[0081] Finally, all records having package type "M" are assigned a MIXED_STATES sack type.
Function FIRST_PASS_PACKS
[0082] The function FIRST_PASS_PACKS (see Fig. 4B) determines which bins, as a result of
the first sort pass, consist of completely sorted packages. In this regard, function
FIRST_PASS_PACKS prepares an array FULLSORT_BIN having elements corresponding to each
of the 128 bins 26 included in the sorter. As a result of the execution of function
FIRST_PASS_PACKS, bins which do not contain a fully sorted package as a result of
the first sort pass have a zero value stored in their corresponding element in array
FULLSORT_BIN. For example, if bin 26₃ does not include a fully sorted package, a "zero"
value is stored in FULLSORT_BIN[3]. For any bin consisting of fully sorted packages,
a unique non-zero number is stored in the element in array FULLSORT_BIN corresponding
to that bin number.
[0083] In the simple case (reflected by step 270), the determination of function FIRST_PASS_PACKS
is made by comparing the number of mailpieces in a bin with the sum of the number
of mailpieces included in all the packages in the bin. If the number of mailpieces
in a bin equals the sum of the number of mailpieces included in all the packages in
the bin, then the bin consists of fully sorted packages. For any bin consisting of
fully sorted packages, a unique non-zero number is stored in the element in array
FULLSORT_BIN corresponding to that bin number.
[0084] For three digit and state packages the comparison is complicated by the fact that
completely sorted package contents could end up in several first pass bins. Therefore,
for three digit and state packages, the partial package counts from several bins making
up one complete package are compared against the same several bins total piece count.
[0085] In order to process the three digit and state packages, the function FIRST_PASS_PACKS
reads through every record in the file SACK2.TMP (which was created by function ASSIGN_SACKS)
and creates two additional work files, i.e., STATE_PACK_FILE and THREE_PACK_FILE (step
272). For every record encountered in file SACK2.TMP that concerns a state package
(PTYPE = S), the function FIRST_PASS_PACKS duplicates that record in the file STATE_PACK_FILE.
Likewise, for every record encountered in file SACK2.TMP that concerns a three digit
package (PTYPE = 3), the function FIRST_PASS_PACKS duplicates that record in the file
THREE_PACK_FILE.
[0086] To determine whether a potentially completely sorted state package is spread through
a plurality of bins (step 274), for each state the function FIRST_PASS_PACKS determines
what records in the file STATE_PACKS_FILE have ZIP codes belonging to that state.
When a record in file STATE_PACKS_FILE pertains to the state, the function FIRST_PASS_PACKS
sets a flag in an element of an array BIN_USAGE corresponding to the bin number indicated
in the record. For example, if bins 26₇, 26₅₅, and 26₉₂ all have mailpieces belonging
to a completely sorted state package, flags are set at BIN_USAGE[7], BIN_USAGE[55],
and BIN_USAGE[92].
[0087] Having noted the bins in which completely sorted state packages may reside, the function
FIRST_PASS_PACKS then compares the total number of mailpieces in the state package
with the total number of mailpieces in all the bins for which a flag was set in array
BIN_USAGE for the state of interest. Recall that the number of mailpieces for each
bin 26 is obtainable from the file AGGR.DAT which was created during the first sort
pass (i.e., at step 202).
[0088] If the total number of mailpieces in the state package is equal to the total number
of mailpieces in all the bins for which a flag was set in array BIN_USAGE, then those
bins are known to include mailpieces for the fully sorted state package. For the bins
including mailpieces for the fully sorted state package, the same non-zero number
is placed in the elements of array FULLSORT_BIN corresponding to those bins. The non-zero
number placed in each of the elements of array FULLSORT_BIN for the state is unique
number which does not appear in array FULLSORT_BIN for any other state or any other
purpose.
[0089] It should be understood that the foregoing processing related to state packages is
conducted separately for each state. This requires that certain parameters, including
the array BIN_USAGE, be reinitialized for each state. Likewise, whatever number entered
into one or more elements of the array FULLSORT_BIN for a particular state will be
a number unique to that state.
[0090] The function FIRST_PASS_PACKS also determines whether fully sorted three digit packages
are spread through more than one bin (step 276). This determination is made in a similar
manner as was the determination for state packages. That is, for each 3 Digit ZIP
Code value the function FIRST_PASS_PACKS reads through the file THREE_PACK_FILE which
it created, and determines whether mailpieces belonging to that 3 Digit ZIP Code are
in a plurality of bins. If so, the function FIRST_PASS_PACKS sets flags in array BIN_USAGE
in the same manner as with the state packages. Then, in like manner as with the state
packages, the function FIRST_PASS_PACKS determines whether the total mailpiece count
of the particular three digit package equals the sum of the bin counts for each of
the bins in which the three digit package is spread. If an equality is determined,
then function FIRST_PASS_PACKS realizes that the bins for which flags were set in
array BIN_USAGE contain the completely sorted three digit package. As with the completely
sorted state packages, a unique number associate with this three digit package is
assigned to each element in array FULLSORT_BIN corresponding to the bins wherein mailpieces
belonging to this completely sorted three digit package reside.
[0091] Thus, upon completion of the execution of function FIRST_PASS_PACKS, an example of
the contents of a portion of array FULLSORT_BIN might be as follows:

Where a FULLSORT_BIN value of "0" indicates that the bin does not contain a completely
sorted package; a value of "1" indicates that a first fully sorted package is contained
in bin 26₁; a value of "2" indicates that a second fully sorted package (perhaps a
state package) is contained in bins 26₄ and 26₅; and, a value of "3" indicates that
a third fully sorted package (perhaps a three digit package) is contained in bins
26₆ and 26₇.
Function MAKE_SORT_RECORDS
[0092] The function MAKE_SORT_RECORDS (see Fig. 4B) makes a file (file SORTREC1.TMP) which
lists packages for second pass sorting and makes another file (file FULLSORT1.TMP)
which lists packages that will not be sorted in a subsequent pass. The function MAKE_SORT_RECORDS
creates the files SORTREC1.TMP and FULLSORT1.TMP after reading through the file SACK2.TMP
(which was created by function ASSIGN_SACKS).
[0093] In reading each record from the file SACK2.TMP, the function MAKE_SORT_RECORDS determines
to which type of package the record relates. In particular, the function MAKE_SORT_RECORDS
checks to see if the PTYPE for the record is either "5", "3", or "S".
[0094] For a record in file SACK2.TMP having a PTYPE of "5", corresponding to a five digit
package, the function MAKE_SORT_RECORDS duplicates the record either in file SORTREC1.TMP
or file FULLSRT1.TMP (step 280). To determine to which file to duplicate the record,
the function MAKE_SORT_RECORDS further checks to determine whether this five digit
package is in a fully sorted bin. This further check is conducted by noting the bin
number included in the record, and then indexing into the array FULLSORT_BIN for that
bin number. If the array FULLSORT_BIN contains a non-zero value for that bin, the
routine ASSIGN_PACKAGES concludes that the record is fully sorted and duplicates the
record from SACK2.TMP in the file FULLSORT1.TMP. Otherwise the function MAKE_SORT_RECORDS
duplicates the record from SACK2.TMP in the file SORTREC1.TMP.
[0095] If the function MAKE_SORT_RECORDS determines that the PTYPE for a record in file
SACK2.TMP is "3", corresponding to a three digit package, the function MAKE_SORT_RECORDS
determines the 3 Digit ZIP Code to which the record pertains. Then the function MAKE_SORT_RECORDS
notes the bin number stored in the record, and stores that bin number in an element
of an array THREE_DIG_BIN corresponding to the pertinent 3 Digit ZIP Code (step 282).
Likewise, the function MAKE_SORT_RECORDS notes from the record the sack type assignment
(from STYPE), and stores that sack type in an element of an array THREE_DIGIT_SACK_TYPE
corresponding to the pertinent 3 Digit ZIP Code (step 284).
[0096] If the function MAKE_SORT_RECORDS determines that the PTYPE for a record in file
SACK2.TMP is "S", corresponding to a state package, the function MAKE_SORT_RECORDS
determines the state to which the record pertains. Then the function MAKE_SORT_RECORDS
notes the bin number stored in the record, and stores that bin number in an element
of an array STATE_BIN corresponding to the pertinent state (step 286). Likewise, the
function MAKE_SORT_RECORDS notes from the record the sack type assignment (from STYPE),
and stores that sack type in an element of an array STATE_SACK_TYPE corresponding
to the pertinent state (288).
[0097] After reading all the records in file SACK2.TMP, after storing information in the
arrays THREE_DIG_BIN and THREE_DIGIT_SACK_TYPE for three digit package records, and
after storing information in arrays STATE_BIN and STATE_SACK_TYPE for state package
records, the function MAKE_SORT_RECORDS is prepared to complete the writing of the
two output files SORTREC1.TMP and FULLSORT1.TMP. The function MAKE_SORT_RECORDS first
writes three digit packages to the appropriate one of the two output files (step 290),
and then the state packages to the appropriate one of the two output files (292),
with the result that the two output files are sorted first by package type, and then
within each package type by package ZIP.
[0098] In writing the three digit packages to the appropriate file (file FULLSORT1.TMP or
file SORTREC1.TMP) at step 290, the routine MAKE_SORT_RECORDS checks to determine
which elements of array THREE_DIGIT_PACK_CNT (generated by the function ASSIGN_PACKAGES),
i.e. which 3 Digit ZIP Codes, have non-zero values, and write a record to the appropriate
file only for those 3 Digit ZIP Codes. Similarly, the routine MAKE_SORT_RECORDS writes
the state packages to the appropriate file (file FULLSORT1.TMP or file SORTREC1.TMP)
at step 292 only for those states having a number of mailpieces exceeding the predetermined
minimum bundles size.
[0099] The formats for file FULLSORT1.TMP and SORTREC1.TMP are identical. In particular,
the formats are both files are prescribed by the structure SACK, which was defined
above in connection with the discussion of function ASSIGN_SACKS as including the
structure PACKAGE (which, in turn, was defined above in connection with the discussion
of the function ASSIGN_PACKAGES). But in creating these two files, the routine ASSIGN_PACKAGES
must store the proper information in the structure PACKAGE portion of the structure
SACK, particularly the fields for ZIP_ID, CNT and BIN. It should be noted that only
one record is written to a 3 Digit ZIP code, e.g., 60202 is written to ZIP_ID 602.
Furthermore, only one record per state is written to FULLSOR1.TMP and SORTREC1.TMP.
[0100] For each three digit package, the function MAKE_SORT_RECORDS obtains the information
for fields CNT and BIN from the corresponding elements in the respective arrays THREE_DIGIT_PACK_CNT
and THREE_DIGIT_BIN. Recall that array THREE_DIGIT_BIN was generated by the function
MAKE_SORT_RECORDS and that the array THREE_DIGIT_PACK_CNT was generated by the function
ASSIGN_PACKAGES. To determine whether a record should be written to file FULLSORT1.TMP
or to file SORTREC1.TMP, the function MAKE_SORT_RECORDS checks the status of array
FULLSORT_BIN for the bin whose number is stored in the array THREE_DIGIT_BIN for the
pertinent 3 Digit ZIP Code. If the value stored in array FULLSORT_BIN is non-zero,
then a record is written to file FULLSORT1.TMP. Otherwise a record is written to file
SORTREC1.TMP.
[0101] For each state package, the function MAKE_SORT_RECORDS obtains the information for
fields CNT and BIN from the corresponding elements in the respective arrays STATE_PACK_CNT
and STATE_BIN. Recall that array STATE_BIN was generated by the function MAKE_SORT_RECORDS
and that the array STATE_PACK_CNT was generated by the function ASSIGN_PACKAGES. To
determine whether a record should be written to file FULLSORT1.TMP or to file SORTREC1.TMP,
the function MAKE_SORT_RECORDS checks the status of array FULLSORT_BIN for the state.
If the value stored in array FULLSORT_BIN for the pertinent state is non-zero, then
a record is written to file FULLSORT1.TMP. Otherwise a record is written to file SORTREC1.TMP.
Function SACK_SORT
[0102] The function SACK_SORT (see Fig. 4C) creates a file SORTREC2.TMP using file SORTREC1.TMP
(step 300). Each record in file SORTREC2.TMP has the format of the structure SACK
described above.
[0103] The function SACK_SORT sorts the records in file SORTREC1.TMP by sack type (step
302), then within sack type by package type (step 304), and within package type by
package ZIP id (step 306). The resultant sort creates the file SORTREC2.TMP. At the
end of execution of the function SACK_SORT, mail is not yet in the final "sack and
bag" order, since further sorting is required by major tree as described below.
[0104] Function SACK_SORT begins by scanning the file SORTREC1.TMP and writing all FIVE_DIBIT
sack package entries to the output file SORTREC2.TMP. While scanning the input file,
the count for each package type entry is recorded. Since the file SORTREC1.TMP has
been sorted by package type, the package type counts are used to determine the starting
position of each different package type's entries.
[0105] Next, the file SORTREC1.TMP is scanned from the beginning and all MIXED_FIVE SACK
package entries are appended to the output file.
[0106] Since only one package type could go into FIVE_DIGIT and MIXED_FIVE sacks, it was
a simple matter of copying sequential records marked with the appropriate sack type
to the output file. For the remaining sack types (THREE_DIGIT, STATE, and MIXED_STATES)
multiple package types are allowed. Therefore, much searching is required to find
the apprpriate next entry for the output file.
[0107] The THREE_DIGIT sack can be composed of both FIVE_DIGIT and THREE_DIGIT packages.
The first step is to determine if any entries exist for all possible package types.
Then the function SACK_SORT repeatedly determines which of the existing package entries
of sack type THREE_DIGIT (which are located in the input file by the starting position
previously saved and count values of records already processed) corresponds to the
first THREE_DIGIT sack entry and the appropriate record is appended to the output
file with the ZIP_ID corresponding to the three digit ZIP of the sack. In addition,
the processed record count for the selected package type is incremented. This is done
until all package entries have been processed.
[0108] The MIXED_STATES sack can be composed of both FIVE_DIGIT, THREE_DIGIT, STATE, and
MIXED_STATE packages. The first step is to determine if any entries exist for all
possible package types. Since there is only one MIXED_STATES sack, packages are written
in package priority order until all entries are exhausted.
[0109] Upon completion of the execution of function SACK_SORT, the ZIP_ID field in a record
in file SORTREC2.TMP is the package ZIP id, which is no longer necessarily the long
integer value of the full 5 digit zip code with four zeros trailing in the "+4" position.
The ZIP_ID for non-5 digit package mail may be the 3 digit zip (range 0 - 999) for
3 digit packages and a state index number (range 0 - 99) for state packages. The BAG
field of the records in file SORTREC2.TMP are undefined at this point, since further
processing is necessary to determine the appropriate values for this field.
Function MAKE_COMBOS
[0110] The function MAKE_COMBOS (Fig. 4D) determines mandatory combinations of first pass
bins for making up state packages and three digit packages. Function MAKE_COMBOS sets
up the required data in an array BIN_COMBOS to force mailpieces scattered across numerous
bins by ineffective first pass sort schemes back into a single second pass group.
Bins fully sorted on the first sort pass are pulled out since they are not part of
second pass records.
[0111] The function MAKE_COMBOS first handles state packages. For each state at step 310
the function MAKE_COMBOS reads each record in the STATE_PACK_FILE (which was created
by function FIRST_PASS_PACKS) and determines (by reference to array FULLSORT_BIN)
whether the particular bin number contained in the record is a fully sorted bin (step
312). If the bin number for that record is fully sorted and the record belongs to
the current state, the function MAKE_COMBOS goes on to the read the next record in
the array STATE_PACK_FILE (i.e., to step 310). If the bin is not fully sorted, the
function MAKE_COMBOS sets a flag in an element of array BIN_USAGE corresponding to
that bin, thereby indicating that the bin has mailpieces for the current state (step
314).
[0112] After the entire file STATE_PACK_FILE has been read for a particular state (determined
at step 316), at step 318 the function MAKE_COMBOS calls another function, function
CHECK_COMBOS, which actually sets up the data in array BIN_COMBOS giving consideration
to possible conflicting bin assignments. A detailed discussion of the function CHECK_COMBOS
is provided below.
[0113] After the function CHECK_COMBOS has been called for a particular state, as indicated
by the affirmative result at step 320 the function MAKE_COMBOS moves on the next state
and repeats the afore-described state package handling for that next state, including
a call to function CHECK_COMBOS after reading through the entire STATE_PACK_FILE for
that next state. The function MAKE_COMBOS conducts the afore-described state package
handling procedure for each state.
[0114] The function MAKE_COMBOS executes much the same procedure for the three digit packages
as it did for the state packages. In handling the three digit packages, at step 330
the function MAKE_COMBOS reads the first record in the file THREE_DIGIT_PACK_FILE
(which was created by function FIRST_PASS_PACKS). As reflected by step 332 for example,
in handling the state packages, the function MAKE_COMBOS ignores any records in the
file THREE_DIGIT_PACK_FILE which pertain to fully sorted bins (determined by reference
to array FULLSORT_BINS).
[0115] At step 334 the function MAKE_COMBOS obtains the first three digit ZIP code from
the first record in the file THREE_DIGIT_PACK_FILE and stores that first ZIP code
in a location THREE_DIG_ZIP. At step 336 the function MAKE_COMBOS determines the bin
number contained in that record; and, sets a flag in the element of array BIN_USAGE
corresponding to that bin number.
[0116] Having processed the first record in file THREE_DIGIT_PACK_FILE, the function MAKE_COMBOS
then reads through further records in the file THREE_DIGIT_PACK_FILE (as reflected
by step 340), noting the ZIP code stored in the record and storing the first three
digits of the ZIP code in a location SCF (step 342). At step 344 the function MAKE_COMBOS
checks to determine if the value in location SCF (the ZIP code for the most recently
read record) is the same as the value in THREE_DIGIT_ZIP (see the preceding paragraph).
If so, the function MAKE_COMBOS (1) at step 346 sets a flag in an element of the array
BIN_USAGE corresponding to the bin number included in the most recently read record
from file THREE_DIGIT_PACK_FILE (thereby indicating that the three digit ZIP code
has mailpieces in that bin as well), and (2) goes on to read the next record in file
THREE_DIGIT_PACK_FILE (i.e., returns to step 340). If the next record in file THREE_DIGIT_PACK_FILE
is read at this point, the function MAKE_COMBOS repeats the steps described in this
paragraph with respect to that next record.
[0117] If the function MAKE_COMBOS determines at step 344 that the value in location SCF
(the ZIP code for the most recently read record) is not the same as the value in THREE_DIGIT_ZIP,
the function MAKE_COMBOS concludes its processing of the ZIP code whose value is stored
in location THREE_DIGIT_ZIP by: (1) calling function CHECK_COMBOS (described below)
at step 348 to set appropriate values in the array BIN_COMBO; (2) setting the value
in location THREE_DIGIT_ZIP equal to the value in location SCF (at step 350); (3)
at step 352 setting a flag in an element of the array BIN_USAGE corresponding to the
bin number included in the most recently read record from file THREE_DIGIT_PACK_FILE;
and, (4) repeating the steps of the preceding paragraph for the next record in file
THREE_DIGIT_PACK_FILE (e.g., by returning to step 340). The processing of three digit
packages continues in this manner until all three digit packages have been processed
(step 354), after which the function MAKE_SACK_COMBOS is called (step 356).
Function CHECK_COMBOS
[0118] The function CHECK_COMBOS is called by the function MAKE_COMBOS (described above)
in order to resolve any conflicting bin assignments and to store data in the array
BIN_COMBOS. The routine MAKE_COMBOS calls the function CHECK_COMBOS as the routine
MAKE_COMBOS finishes with each state, and as the routine MAKE_COMBOS finishes with
each three digit ZIP value.
[0119] As indicated above, the function CHECK_COMBOS stores values in the array BIN_COMBO
to indicate which first pass bins are to be mandatorily combined together. As an example
of how the array BIN_COMBOS might appear upon completion of the execution of function
CHECK_COMBOS, consider the following:

where a zero ("0") assignment indicates that there is no forced combination for a
bin; where bins assigned a "1" are to be forced into combination (i.e., bins 3 and
6); and, where bins assigned a "2" are to be forced into combination (i.e., bins 5
and 7). Thus, each forced combination has a unique combination number associated therewith,
and the bins forced into combination together have the same combination number assigned
to their corresponding elements in the array BIN_COMBOS.
[0120] When function CHECK_COMBOS is called, function CHECK_COMBOS initially executes two
steps: (1) initializes a counter COLLISION_CNT; and, (2) counts the number of bins
for which a flag has been set in array BIN_USAGE for the current package. If the number
of flags set is only one, then function CHECK_COMBOS knows that no combination of
bins is required and returns control to the calling function MAKE_COMBOS.
[0121] Assuming that the function CHECK_COMBOS does not immediately return control to the
calling function MAKE_COMBOS, the function CHECK_COMBOS checks to determine whether
any of the bins for which a flag was set in array BIN_USAGE has already been forced
into a combination. This check is implemented by checking the element in array BIN_COMBO
corresponding to that bin to determine if a non-zero combination number has already
been assigned to the bin. If a non-zero combination number has already been assigned,
the function CHECK_COMBOS notes a "collision".
[0122] The function CHECK_COMBOS counts the number of collisions detected using a counter
COLLISION_CNT. In addition, the function CHECK_COMBOS stores the numbers of the bins
subject to collision in an array COLLISION_COMBO. For example, if a first collision
occurred in bin 67 and a second collision occurred in bin 48, COLLISION_COMBO[1] =
34 and COLLISION_COMBO[2] = 48.
[0123] Having searched for collisions, the function CHECK_COMBOS executes different steps
in determining the combination number to be stored in BIN_COMBOS, depending upon whether
no collisions, one collision, or multiple collisions were detected.
[0124] If no collisions were encountered during the execution of function CHECK_COMBOS,
the function CHECK_COMBOS would then select the next available number for use as a
combination number. For example, in the example, if the highest number thus far stored
in the array BIN_COMBOS was "2", the function CHECK_COMBOS would then store a "3"
in every element in array BIN_COMBOS for which a flag was set in a corresponding element
of array BIN_USAGE. The function CHECK_COMBOS would then return control to the calling
function MAKE_COMBOS.
[0125] If only one collision were encountered during the execution of function CHECK_COMBOS,
the function CHECK_COMBOS would assign the combination number stored in the first
element of COLLISION_COMBO to the elements in array BIN_COMBOS corresponding to the
elements in array BIN_USAGE having flags set. For example, if bins 67 and 102 were
utilized for the current package as indicated by flags being set in the 67th and 102nd
elements of array BIN_USAGE, if the only collision detected by function CHECK_COMBOS
for the current package occurred with respect to bin 67, and if the combination number
assigned to bin 67 were "5", then the function CHECK_COMBOS would assign the combination
number "5" to bins 67 and 102 (i.e., to BIN_COMBO[67] and BIN_COMBO[102]). The function
CHECK_COMBOS would then return control to the calling function MAKE_COMBOS.
[0126] In the more complex case where multiple collisions are encountered, the function
CHECK_COMBOS replaces all the elements of array BIN_COMBO affected by the collision
with the combination number of the first detected collision, i.e., all collision bins
are assigned the value COLLISION_COMBO[0] and are properly placed in the BIN_COMBO
array. Then the combination number in COLLISION_COMBO[0] is assigned to any new bins
that might not have collided. This is done by setting the array elements in BIN_COMBO
to COLLISION_COMBO[0] using the corresponding elements marked in array BIN_USAGE.
Since the value in COLLISION_COMBO[0] may not have been the lowest forced combination
indicator out of multiple such indicators, a numbering gap could possibly occur.
[0127] A numbering gap, if it occurs, is fixed by placing all non-zero elements from the
BIN_COMBO array into another array UNIQUE_COLLISIONS along with counting the number
of elements in array UNIQUE_COLLISIONS. All elements in the array UNIQUE_COLLISIONS
are sorted in numerical order, then each element repeating the value of the previous
element is removed from the array, thereby shrinking the array in size. The array
UNIQUE_COLLISIONS makes it possible to easily reassign forced bin combination numbers
without gaps to the BIN_COMBO array. This is accomplished by searching both the BIN_COMBO
array and the UNIQUE_COLLISIONS array for matching contents. When the contents match,
a new sequential number is assigned into yet another array COMBO_TRANSLATION corresponding
to the position of the UNIQUE_COLLISIONS array. Finally, the BIN_COMBO array is updated
by assigning the value in the COMBO_TRANSLATION array which is indexed by the contents
of the BIN_COMBO array.
Function MAKE_SACK_COMBOS
[0128] The function MAKE_SACK_COMBOS (see Fig. 4E) determines mandatory combinations of
first pass bins for forming sacks. That is, the function MAKE_SACK_COMBOS sets up
the required data to force a sack's packages scattered across bins by the first pass
sort scheme back into a single second pass group.
[0129] The function MAKE_SACK_COMBOS (which forces a sack's packages together) is somewhat
simpler than the function MAKE_COMBOS (which determined combinations of first pass
bins for making up state packages and three digit packages). The simplicity results
from two factors. First, the function MAKE_COMBOS has already forced zip codes scattered
across bins to form packages. Second, an input file (i.e., SORTREC2.TMP) of subsequent
pass packages sorted by sack zip ID already exists. The file SORTREC2.TMP was created
by the function SACK_SORT. The file SORTREC2.TMP is sorted by sack type, within sack
type by package type, and within package type by package zip. Therefore, the file
SORTREC2.TMP is effectively sorted by sack zip ID.
[0130] At step 370 the function MAKE_SACK_COMBOS reads the initial record in the file SORTREC2.TMP.
At step 372 the sack ID value obtained from the first record is stored in location
LAST_SACK_ZIP_ID. At step 374 the sack type value obtained from the first record is
stored in location LAST_SACK_TYPE. At step 376 a flag is set in the element of array
BIN_USAGE corresponding to the bin value obtained from the first record of file SORTREC2.TMP.
[0131] At step 378 the function MAKE_SACK_COMBOS begins a loop of reading and processing
records in the file SORTREC2.TMP. The next record is read at step 378. If the record
was not the last record (as determined at step 380), at step 382 the function MAKE_SACK_COMBOS
checks whether the sack type value of the record indicates a "MIXED STATES" sack.
There is no forced combination with respect to any MIXED STATES sacks, so that an
affirmative result at step 382 results in the continuation of the loop with the reading
of the next record at step 378. If the record does not indicate a MIXED STATES sack,
the ZIP ID value from the record is stored at location SACK_ZIP_ID (step 384).
[0132] At step 386 the function MAKE_SACK_COMBOS determines whether the next record indicates
a change of sack types from the previous record. A change of sack types occurs when
the current records has two critical parameters that differ from the previous records.
That is, when SACK_ZIP_ID is not equal to LAST_SACK_ZIP_ID, and when the sack type
read from the current record is not equal to LAST_SACK_TYPE, a change of sack type
has occurred.
[0133] When, at step 386, a change in sack type is determined not to have occurred, the
function MAKE_SACK_COMBOS sets a flag in an element of the array BIN_USAGE corresponding
to the bin value obtained from the current record in the SORTREC2.TMP file (step 388).
The value in location SACK_ZIP_ID is then stored in location LAST_SACK_ZIP_ID (step
390), and a value indicative of the sack type obtained from the current record is
stored in the location LAST_SACK_TYPE (step 392). The function MAKE_SACK_COMBOS then
loops back to step 378 for the reading of another record from file SORTREC2.TMP.
[0134] When, at step 386, a change in sack type is determined to have occurred, at step
394 the function MAKE_SACK_COMBOS calls the function CHECK_COMBOS (described above)
to update the array BIN_COMBOS. The function CHECK_COMBOS resolves conflicting bin
assignments for sacks in essentially the same manner as described above in connection
with the resolution of conflicting bin assignments for packages. After the call to
function CHECK_COMBOS, at step 396 the function MAKE_SACK_COMBOS clears the array
BIN_USAGE in anticipating of processing the next sack type. The function MAKE_SACK_COMBOS
then sets a flag in an element of the array BIN_USAGE corresponding to the bin value
obtained from the current record in the SORTREC2.TMP file (step 388). The value in
location SACK_ZIP_ID is then stored in location LAST_SACK_ZIP_ID (step 390), and a
value indicative of the sack type obtained from the current record is stored in the
location LAST_SACK_TYPE (step 392). The function MAKE_SACK_COMBOS then loops back
to step 378 for the reading of another record from file SORTREC2.TMP.
[0135] After the last record is read from file SORTREC2.TMP (as determined at step 380),
the function MAKE_SACK_COMBOS calls the function CHECK_COMBOS at step to update the
array BIN_COMBOS with respect to the last record. Thereafter, as indicated by step
398, processing continues with the function BUILD_TREES, which is described immediately
below.
Function BUILD_TREES
[0136] The function BUILD_TREES (see Figs. 4F and 4G) builds a major tree array, i.e. array
MAJ_TREE, which associates particular bins with a sort tree. In addition, the function
BUILD_TREES develops pointer information in a file SRTREE.DAT. The file SRTREE.DAT
contains key pointer and offset information used to process individual subsequent
pass groups within a properly ordered input file containing package information for
multiple groups.
[0137] As an example of how the major trees built by function BUILD_TREES appear, after
the execution of function BUILD_TREES, the array MAJ_TREE might have values such as
the following:

[0138] The function BUILD_TREES takes the number of different packages coming from a first
pass bin or a required combination of bins and forms information for "groups" (including
"groups" requiring even more passes). This is done by comparing the package count
with the number of available bins. Several first pass bins may be combined together
if the total package count is less than the number of bins available.
[0139] At the beginning of the execution of function BUILD_TREES, as reflected by step 400,
the function BUILD_TREES determines the number of packages in each state/3-digit forced
bin combination and stores that value in an array QUAL_PER_COMBO. This is done by
determining which bins have the same value stored in the array BIN_COMBO (e.g., which
bins are forced into combination), and summing the number of packages for all bins
combined together. The number of packages in each bin is available from the array
PACKS_PER_BIN, which was developed in the previous function MAKE_SORT_RECORDS.
[0140] At steps 402 - 408 the function BUILD_TREES initializes various parameters. At step
402 the counter CUTOFF_CNT is initialized at a value equaling the number of available
bins. This initialization value may not be 128, since some bins may be designated
as reject bins, or may not be used, or may be used for other purposes. At step 404
the counter TREE_CNT, which counts the number of sort trees, is initialized at 1.
At steps 406 and 408, respectively, the counters QUAL_CNT and TEMP_CNT are initialized
at zero.
[0141] Commencing at step 410 the function BUILD_TREES attempts to find the first bin belonging
to a tree. In so doing, the function BUILD_TREES considers only bins having packages
stored therein which are not fully sorted during the first pass, or bins which have
been forced into combination (e.g., bins having a non-zero value in their corresponding
element in array BIN_COMBO).
[0142] At step 412 the function BUILD_TREES determines whether the considered bin was forced
into combination by checking for a non-zero value at the corresponding element in
array BIN_COMBO. If the considered bin was involved in a forced combination, at step
414 the qualifying package counter QUAL_CNT has the value of the number of packages
included in the combined bins added thereto. Where "i" stands for the bin under consideration,
the number of packages included in the combined bins is obtained from array QUAL_PER_COMBO[BIN_COMBO[i]].
Values were stored in array QUAL_PER_COMBO at step 400 of function BUILD_TREES. Also
for the considered bin involved in the forced combination, for each bin included in
the forced combination, at step 416 the function BUILD_TREES sets elements corresponding
to each such bin in array MAJ_TREE equal to the value in counter TREE_CNT, which is
presently "1". The function BUILD_TREES then sets BIN_COMBO-USAGE[BIN_COMBO[i]] =
1 at step 417, indicating that all bins in this combination have been accounted for.
Processing then continues at step 420 as indicated by path 422.
[0143] The function BUILD_TREES locates a bin not involved in a combination (e.q., a bin
for which the corresponding element in array BIN_COMBO is zero) at step 412. Upon
locating a non-combined bin, the function BUILD_TREES stores the current value of
counter TREE_CNT (i.e., "1"), in the element of array MAJ_TREE corresponding to the
located non-combined bin (step 418). From thence processing continues with step 420
as indicated by path 422.
[0144] At step 420 the function BUILD_TREES computes the number of the next-highest numbered
bin by incrementing the number of the bin located at step 412. Then, using the incremented
bin number (symbolically expressed by "i"), at step 422 the function BUILD_TREES checks
to see if the bin was involved in a forced combination by checking the value of BIN_COMBO[i].
If the bin was involved in a forced combination, the number of packages involved in
the combination (i.e., QUAL_PER_COMBO[BIN_COMBO]) is stored at the temporary counter
TEMP_CNT (step 424). If the bin was not involved in a forced combination, the number
of packages in the bin (i.e., PACKS_PER_BIN[i]) is stored at the temporary counter
TEMP_CNT (step 424). After execution of step 424 or step 426, the function BUILD_TREES
adds the value of TEMP_CNT to the counter QUAL_CNT (step 428).
[0145] At step 430 the function BUILD_TREES determines whether the value in counter QUAL_CNT
(updated at step 428) exceeds the number of available bins (i.e., exceeds the value
of the counter CUTOFF_CNT initialized at step 402). If an excess is determined at
step 430, at steps 432 and 434, respectively, the function BUILD_TREES increments
the value in counter TREE_CNT and stores the value in TEMP_CNT in counter QUAL_CNT
before proceeding to step 436. In so doing, the function BUILD_TREES begins another
sort tree beginning with the current bin and initializes the value in counter QUAL_CNT
for the new tree on the basis of the count determined at the appropriate one of steps
424 or 426.
[0146] At step 436 the function BUILD_TREES again discerns whether the current bin was involved
in a forced combination. If the current bin was involved in a forced combination,
at step 438 the function BUILD_TREES sets the corresponding elements in array MAJ_TREE
equal to the current value of counter TREE_CNT for each bin included in forced combination
with the current bin. Then, at step 440, a flag is set in array BIN_COMBO_USAGE at
element BIN_COMBO[i] thereof.
[0147] If at step 436 the function BUILD_TREES discerns that the current bin was not involved
in a forced combination, at step 442 the function BUILD_TREES assigns the value of
the counter TREE_CNT to the element i in array MAJ_TREE for this bin (i.e., MAJ_TREE[i]
= TREE_CNT).
[0148] After processing either step 442 or step 440, the function BUILD_TREES checks at
step 444 if all bins have been processed. If not, execution loops back to step 420
for processing the next bin.
[0149] After all bins have been processed by function BUILD_TREES as determined at step
444, at step 446 the function BUILD_TREES prepares the file SRTREE.DAT (described
below). The file SRTREE.DAT contains key pointer and offset information eventually
used to process individual "groups" within a properly ordered input file, containing
package information for multiple groups.
[0150] The file SRTREE.DAT contains records of the following structure:

[0151] In preparing the file SRTREE.DAT, the function BUILD_TREES finds the bins belonging
to each sort tree. Then, for each sort tree, the number of qualifying packages for
all the bins included in the tree is summed to obtain a total package count for the
tree (stored in location QUAL_CNT [which is re-initialized at zero before checking
each tree]). This value is stored in field QUAL_TRE for the appropriate record in
file SRTREE.DAT for the tree of interest.
[0152] To determine the value for field GRPS_TRE for a record in filed SRTREE.DAT, the function
BUILD_TREES evaluates the expression:
1 + (QUAL_CNT - 2)/(TOT_BINS - 1)
assuming QUAL_CNT is greater than zero, and wherein TOT_BINS is as described with
respect to step 402 supra. If the value of counter QUAL_CNT is zero, the value for
field GRPS_TRE becomes "1".
[0153] The values of fields QUAL_PTR and GROF_TRE, respectively, for each record in file
SRTREE.DAT, are obtained by maintaining running summations of the values QUAL_TRE
and GRPS_TRE for previous trees.
Function TREESORT
[0154] The function TREESORT (see Fig. 4H) takes the input file SORTREC2.TMP and produces
an output file SORTREC3.TMP. Whereas the records in input file SORTREC2.TMP are sorted
by sack type, then within sack type by package type, and within package type by ZIP
ID, the records in output file SORTREC3.TMP are sorted by major tree, then within
major tree by sack type, then within sack type by package type, then within package
type by ZIP ID.
[0155] At step 450, the function TREESORT determines the number of entries (i.e., the number
of records) belonging to each tree. This is done by making a first pass through the
input file SORTREC2.TMP. As each record in file SORTREC2.TMP is read, the bin number
for that record is obtained from the record. Using the bin number extracted from the
record as an index, the function TREESORT determines the major tree to which the record
belongs by checking the array MAJ_TREE. The entries for each tree are counted as the
input file SORTREC2.TMP is read.
[0156] All the records from input file SORTREC2.TMP for as many trees as possible are stored
in dynamic memory by the function TREESORT. All the records for all the trees may
not fit into dynamic memory simultaneously, so for each execution of a loop (consisting
of steps 452, 454, 456, and 458), the records for as many trees as possible are stored
in dynamic memory. The lowest numbered trees are handled during the first execution
of the loop, with successive loop executions involving progressively higher numbered
trees.
[0157] Before conducting another pass of the records included in the input file SORTREC2.TMP,
at step 452 the function TREESORT sets a memory pointer for each tree which will fit
into dynamic memory for the current execution of the loop. The memory pointer is easily
determined since the number of entries for each tree is known from step 450, and the
size of each record is standardized in accordance with the format discussed supra.
[0158] At step 454 each record in the input file SORTREC2.TMP is again read. As a record
is read, it is copied into dynamic memory at the location specified by the memory
pointer for the tree to which the record belongs. After each record is written to
dynamic memory, the memory pointer for its tree is advanced to the next record location
for that tree in dynamic memory.
[0159] When all the trees being handled by this execution of the loop have been written
into dynamic memory, at step 456 the contents of the dynamic memory is written to
the output file SORTREC3.TMP. Thus, the output file SORTREC3.TMP is sorted first by
tree, then by sack, then by package, and then by ZIP ID.
[0160] At step 458 the function TREESORT checks to determine if all trees have been processed.
If further trees remain, the function TREESORT goes back to the beginning of the loop
(i.e., back to step 452) to handle further trees and to continue writing to the output
file SORTREC3.TMP in the manner just described. If all trees have been written, processing
continues with function FIRST_PASS_SACKS (as indicated by step 460).
Function FIRST_PASS_SACKS
[0161] Function FIRST_PASS_SACKS (see Fig. 4I) determines first pass bins containing completed
sorted sacks. In this regard, the function FIRST_PASS_SACKS uses the file FULLSOR2.TMP
to prepare an array FULL_SACK_BIN, which is an array of completely sorted first pass
sacks indexed by first pass bin. An example of the appearance of a portion of array
FULL_SACK_BIN upon completion of execution of function FIRST_PASS_SACKS is as follows::

[0162] In the simple case, function FIRST_PASS_SACKS determines completely sorted sacks
by comparing the sack count with the bin count of the bin where the sack contents
was assigned. If the two counts are equal, the bin is completely sorted.
[0163] For Mixed five digit, three digit, and state sacks the comparison is complicated
because the sack contents could end up in several first pass bins. Therefore the partial
sack counts from several bins making up one complete sack are compared against the
same several bins total piece count. In addition, only the file containing the first
pass package records is scanned, so records that end up in the subsequent pass package
record file are not included. To account for this, the sack count arrays containing
both first pass and subsequent pass data are compared against the first pass sack
count.
[0164] Describing now in detail the steps executed by function FIRST_PASS_SACKS, various
arrays and parameters are initialized at step 470. For example, the output array FULL_SACK_BIN
has all its elements set equal to zero, and the array BIN_USAGE is set to a logical
FALSE value at step 470. In addition, the counters SACK_BIN_CNT and FIRST_PASS_SACKS,
and the location SACK_CNT are initialized at zero.
[0165] At step 472 the function FIRST_PASS_SACKS reads the first record from file FULLSOR2.TMP.
The file FULLSOR2.TMP was created by the function SACK_SORT, and is a file containing
one record per completely sorted first pass package. In reading the first record from
file FULLSOR2.TMP at step 472, the function FIRST_PASS_SACKS obtains the ZIP ID and
the sack type from the initial record, and stores those values at the respective locations
LAST_SACK_ZIP_ID and LAST_SACK_TYPE.
[0166] At step 474 the function FIRST_PASS_SACKS begins a loop of reading and processing
further records in the file FULLSOR2.TMP. In so doing, the function FIRST_PASS_SACKS
obtains the ZIP ID and the sack type from the new record, and stores those values
at the respective locations SACK_ZIP_ID and SACK_TYPE.
[0167] At step 476 the function FIRST_PASS_SACKS determines whether the most-recently read
record is in the same sack as the previous record. This is affirmatively determined
when SACK_ZIP_ID = LAST_SACK_ZIP_ID and SACK_ZIP_ID = LAST_SACK_ZIP_ID. If it is determined
at step 476 that the most-recently read record is not in the same sack as the Previous
record, processing continues at step 478. Otherwise processing branches to step 480.
[0168] At step 480 the function FIRST_PASS_SACKS determines whether the most recently read
record involves a new bin. A new bin is involved if the element corresponding to the
new bin in array BIN_USAGE is still FALSE. If a new bin is not involved, processing
continues with step 482. Otherwise, processing branches to step 484.
[0169] When a new bin is involved, at step 484 the function FIRST_PASS_SACKS sets the element
in array BIN_USAGE corresponding to the new bin to a TRUE value. Then, at step 486,
the function FIRST_PASS_SACKS adds the count of the number of mailpieces in that new
bin to the counter SACK_BIN_CNT. It will be remembered that the count of the number
of mailpieces in the new bin is obtained from the file AGGR.DAT, which was created
at step 202.
[0170] At step 482, reached either from step 480 or step 486, the function FIRST_PASS_SACKS
sums the partial package counts by adding the adding the package count from the most
recent record to the counter SACK_CNT. At step 478, reached either from step 476 or
step 482, the function FIRST_PASS_SACKS initializes the logical flag ALL_FROM_PASS1
to a logical zero.
[0171] At step 488 the function FIRST_PASS_SACKS examines the value of the location LAST_SACK_TYPE
to determine what type of sack is being processed, with a view to determining whether
the flag ALL_FROM_PASS1 should be changed from FALSE to TRUE for this sack, thereby
indicating that the sack is not split into first and second pass records. FIVE_DIGIT
sacks cannot be split into first and second pass records, so if the value of LAST_SACK_TYPE
is FIVE_DIGIT, the flag ALL-FROM_PASS1 is set TRUE.
[0172] For the other sack types, function FIRST_PASS_SACKS at step 488 determines whether
the value of an appropriate counter equals the current value of the counter SACK_CNT
(calculated at step 482). In this respect, the equality determination at step 488
is made with respect to the appropriate one of the counters MIXED_FIVE_SACK_CNT, THREE_DIGIT_SACK_CNT,
or STATE_SACK_CNT for the last sack ZIP_ID.
[0173] At step 490 the function FIRST_PASS_SACKS determines whether the flag ALL_FROM_PASS1
is TRUE and whether the value in counter SACK_CNT equals the value in the counter
SACK_BIN_CNT (see step 486). When both determinations are affirmative, the function
FIRST_PASS_SACKS realizes that it has encountered a completely sorted first pass sack.
If either determination is negative, the function FIRST_PASS_SACKS continues processing
at step 492; otherwise the function FIRST_PASS_SACKS branches to steps 493 followed
by step 494.
[0174] Both determinations at step 490 being affirmative reflect the location of a completely
sorted sack, and cause a branch in processing to step 493. At step 493 the counter
FIRST_PASS_SACKS is incremented to a value which will be used as a unique identifying
value for the just-located completely sorted sack. At step 494 the value of FIRST_PASS_SACKS
is stored in every element of array FULL_SACK_BIN which corresponds to a bin which
has mailpieces included in the completely sorted sack. The bins which have mailpieces
included in this most-recently located completely sorted sack are reflected by the
elements in array BIN_USAGE which have been set to a logical TRUE value.
[0175] At step 492, reached either from step 490 or step 494, the function FIRST_PASS_SACKS
reinitializes the counters SACK_CNT and SACK_BIN_CNT at zero; sets every element in
array BIN_USAGE to a FALSE value; and, stores the value from location SACK_ZIP_ID
in location LAST_SACK_ZIP_ID and the value from location SACK_TYPE in the location
LAST_SACK_TYPE.
[0176] At step 495 the function FIRST_PASS_SACKS determines whether any more records remain
for reading in file FULLSOR2.TMP. If records remain, processing loops back to step
474, at which the repetition of the above-described steps occurs for the next record.
If no further records remain in file FULLSOR2.TMP, the function FIRST_PASS_SACKS processes
the last-read record at step 496. In this regard, the processing of step 496 is essentially
the same as steps 488 through 494 inclusive, except there is no step corresponding
to reinitialization step 492. At step 497 processing is transfered to function MAKE_BAGS.
Function MAKE_BAGS
[0177] Function MAKE-BAGS (see Figs. 4J and 4K) assigns unique identification numbers to
each bag destination and determines the number of pieces assigned to a destination.
In addition, the bag identification numbers get corresponding assignments to subsequent
pass groups and bins.
[0178] At step 500 the function MAKE_BAGS initializes the value of location LAST_BAG_ASSIGNED
at zero. At step 502 the function MAKE_BAGS handles mixed states bags, assigning all
mixed states records to the bag number "one". As part of step 502, the function MAKE_BAGS
increments the value at location LAST_BAG_ASSIGNED (so that the value is "1"), and
then sets BAG_NO = 1. Further, at step 502 the function MAKE_BAGS creates a record
in a file BAGTAG_HANDLE, with the record having the following format and values:

[0179] Having handled the mixed states bags at step 502, the function MAKE_BAGS determines
the number of first pass bags containing either some or all completely sorted first
pass packages. These sacks must have their bag ID assignment before subsequent pass
groups are handled. The completely sorted first pass bags are processed by steps 504
through 550 of the function MAKE_BAGS. Thereafter, at steps 554 through 572, the subsequent
bags are processed.
[0180] In the above regard, at step 504 the function MAKE_BAGS initializes various values
for handling the first pass bags. The function MAKE_BAGS sets LAST_ID = -1; LAST_TYPE
= -1; and, FRST_PASS_BAGS.CNT = 0.
[0181] At step 506 the function MAKE_BAGS reads, as a first step in a loop, a record from
file FULLSOR2.TMP. The file FULLSOR2.TMP was created by the function SACK_SORT. Assuming
at step 508 that the record read is not from the same sack as the last record in the
file FULLSOR2.TMP, at step 510 the function MAKE_BAGS checks whether the record just
read from the file FULLSOR2.TMP pertained to a mixed states sack. If so, the function
MAKE_BAGS realizes that it has already handled (at step 502) the mixed states bag,
and at step 512 sets SACK_NO = 1. Also, at step 514, the function MAKE_BAGS writes
a corresponding record (i.e., the record read from file FULLSOR2.TMP with the bag
number updated) to file FULLSORT. After execution of step 514, processing loops back
to step 506 for the reading of another record from file FULLSOR2.TMP.
[0182] Assuming that the function MAKE_BAGS determined at step 510 that the record just-read
pertained to a sack type other than a mixed states sack, at step 516 the function
MAKE_BAGS obtains the ZIP ID from the record and stores that ZIP ID in location SACK_ZIP_ID.
At step 518 the function MAKE_BAGS checks whether the record just-read from file FULLSOR2.TMP
signals a change of sack. A change of sack is signalled when SACK_ZIP_ID does not
equal the value stored in location LAST_ID.
[0183] If a change of sack is not encountered at step 518, the function MAKE_BAGS adds the
value in the field SACK.PACKAGE.CNT from the record just-read to the counter FRST_PASS_BAG.CNT
(step 520). Location SACK.NO is then set to the value at location BAG.NO (step 522).
At step 524, a corresponding record is written to file FULLSORT. After the corresponding
record is written at step 524, execution loops back to step 506 for the reading of
yet another record from the file FULLSOR2.TMP.
[0184] If a change of sack is encountered at step 518, the function MAKE_BAGS determines
whether the record just-read from file FULLSOR2.TMP was the very first record in file
FULLSOR2.TMP (step 526). For all but the very first record in file FULLSOR2.TMP, the
function MAKE_BAGS writes a corresponding record in the file BAGTAG_HANDLE (step 528).
[0185] At step 530 the function MAKE_BAGS computes a value for pointer PREV_ASSIGN_PTR.
In this regard, at step 530 the function MAKE_BAGS uses the value of SACK_ZIP_ID obtained
from the record just-read as an index for an appropriate one of arrays MIXED_FIVE_BAG_NO;
STATE_BAG_NO; THREE_DIGIT_BAG_NO; depending on the value of SACK.STYPE obtained for
the record just-read. (These arrays were also initialized at step 500). The value
obtained by indexing into the appropriate array is stored in the pointer PREV_ASSIGN_PTR.
If the value of SACK.STYPE obtained from the record just-read is other than MIXED_FIVE;
THREE_DIGIT; or STATE; the pointer PREV_ASSIGN_PTR is assigned the value NULL at step
530.
[0186] At step 532 the function MAKE_BAGS checks to determine if PREV_ASSIGN_PTR is NULL
or the contents thereof is zero. If either value is stored in pointer PREV_ASSIGN_PTR,
at step 534 LAST_BAG_ASSIGNED is incremented and at step 536 that incremented value
is stored in location BAG_NO. Otherwise, at step 538, BAG_NO has the value from *PREV_ASSIGN_PTR
stored therein.
[0187] Step 540 is reached either from step 536 or step 538. At step 540, the function MAKE_BAGS
checks whether the pointer PREV_ASSIGN_PTR has the value NULL stored therein. If so,
at step 542 the value of BAG_NO is stored in location *PREV_ASSIGN_PTR.
[0188] At step 544, which follows either step 540 or step 542, the function MAKE_BAGS creates
a record for the array FRST_PASS_BAGS. The record created at step 544 has the following
format and values:

[0189] After creating a record for file FRST_PASS_BAGS at step 544, the function MAKE_BAGS
stores the value in location SACK_ZIP_ID in location LAST_ID (step 546) and stores
the value in location SACK.STYPE in location LAST_TYPE (step 548). Then function MAKE_BAGS
jumps back to execute steps 522 and 524 before reading another record from file FULLSOR2.TMP
at step 506. In this respect, as explained before, at step 522 the location SACK.NO
is then set to the value at location BAG.NO and, at step 524, a corresponding record
is written to file FULLSORT.
[0190] After all records from file FULLSOR2.TMP have been read as determined by step 508,
the final FIRST_PASS_BAGS record is written to file BAGTAG_HANDLE at step 549. Then,
as indicated by symbol 550 processing continues at step 554 (see Fig. 4K) for handling
package records for subsequent pass sorting (i.e., package records from file SORTREC3.TMP).
[0191] At step 554, which is somewhat akin to step 504, various parameters are initialized,
i.e., CUS_GROUP = 0; LAST_ID = -1; LAST_TYPE = -1; and, BAG_DATA.CNT = 0. The file
SRTREE.DAT is read to determine if any more tree structures remain. In the case of
remaining tree structures, CUS_GROUP is incremented by one (step 560). Then a check
at step 562 is made to determine if there are any more groups defined by the present
tree record. If there are not more groups, the function continues at step 556 where
the file SRTREE.DAT is read for another tree structure. In the case where a group
remains in the present tree (deterimed at step 562), at step 564 an array BIN_CNT
is set declaring the number of packages to be placed in the present group's bins.
In addition, at step 565 a file seek position is set in file SORTREC3.TMP, for the
first record in the present group being processed, by using tree record information
and the present group within the tree. At step 567 the array BIN_CNT contents are
checked for a value of one. This indicates that no more groups are required to sort
the next record found in SORTREC3.TMP. For all bins such that BIN_CNT[i] = 1 a record
is read from the file SORTREC3.TMP (step 568). In the case where no more bins remain,
processing proceeds to step 560 where a new group is used. Where a record is read
from SORTREC3.TMP the record is processed at step 570 in the same way as for a first
pass sort record. Step 570 is the same as steps 506 through 549 except in step 506
where a record is read from file FULLSOR2.TMP it is now read from file SORTREC3.TMP.
After processing the package record from file SORTREC3.TMP the process continues by
going to step 566 where a check is made to determine if any more bins have been assigned
to the present group.
[0192] In the case where no more trees are left at step 558, the program is ready to go
to the function MAKE_CLIENT_CNTS (as indicated by step 572).
Function MAKE_CLIENT_COUNTS
[0193] The function MAKE_CLIENT_COUNTS (see Fig. 4L) sets up several count categories for
each client. These counts are subsequently used in postage reporting and client billing.
[0194] The function MAKE_CLIENT_COUNTS uses the input file COUNT.DAT created by function
FIRST_SORT_PASS and the input file SORTREC2.TMP created by the function SACK_SORT.
It will be recalled that the format of file COUNT.DAT is as follows:

The records in file COUNT.DAT are sorted in ascending order. In this respect, a primary
sortation is done by ZIP code. For ZIP codes repeated due to their usage in different
client/mailstreams, a secondary sortation is performed by first sorting the client
index number, followed by the stream index number.
[0195] At step 600 the function MAKE_CLIENT_COUNTS initializes several counter arrays. In
this respect, at step 600 the following are initialized at zero:

where i represents the client index (the number associated with a particular client).
CLIENT[i].QUAL_TOT.COUNT5 will ultimately contain the total number of mailpieces from
client "i" which qualify for the 5 Digit OCR/barcode postage discount; CLIENT[i].QUAL_TOT.ZIP4
will ultimately contain the total number of mailpieces from client "i" which qualify
for the ZIP+4 OCR postage discount; CLIENT[i].QUAL_TOT.BARCDE will ultimately contain
the total number of mailpieces from client "i" which qualify for the ZIP+4 barcoded
postage discount; CLIENT[i].NQUAL_TOT.COUNT5 will ultimately contain the total number
of 5 Digit OCR/barcoded mailpieces from client "i" which do not qualify for the 5
Digit OCR/barcoded postage discount; CLIENT[i].NQUAL_TOT.ZIP4 will ultimately contain
the total number of ZIP+4 OCR mailpieces from client "i" which do not qualify for
the ZIP+4 OCR postage discount; and, CLIENT[i].NQUAL_TOT.BARCDE will ultimately contain
the total number of ZIP+4 Barcoded mailpieces from client "i" which do not qualify
for the ZIP+4 Barcoded postage discount
At step 600 the following are also initialized at zero:

[0196] At step 602 the function MAKE_CLIENT_COUNTS reads a record in the file COUNT.DAT.
As noted above, each record in file COUNT.DAT has a ZIP ID field. At step 604 the
function MAKE_CLIENT_COUNTS searches the file SACK2.TMP to find the record in file
SACK2.TMP having the same ZIP ID as the current record in file COUNT.DAT. At step
606 the function MAKE_CLIENT_COUNTS consults the record found in file SACK2.TMP to
determine the sack type (STYPE) assigned to the sack containing mailpieces for the
current ZIP ID.
[0197] At step 608 a determination is made whether the record in file SACK2.TMP for the
current ZIP ID indicates that mailpieces having the current ZIP ID are contained in
FIVE_DIGIT or MIXED_FIVE sacks (thereby qualifying for the applicable postage discounts).
If the determination at step 608 is affirmative, the function MAKE_CLIENT_COUNTS adds
values from the appropriate fields of the current COUNT.DAT record to "qualifying"
counters for the client having the client index borne by the current COUNT.DAT record.
In this respect, for client "i" at step 610 the counter CLIENT[i].QUAL_TOT.COUNT5
is incremented by the value contained at byte offset 7 in the COUNT.DAT record; the
counter CLIENT[i].QUAL_TOT.ZIP4 is incremented by the value contained at byte offset
9 in the COUNT.DAT record; and, the counter CLIENT[i].QUAL_TOT.BARCDE is incremented
by the value contained at byte offset 11 in the COUNT.DAT record.
[0198] On the otherhand, if the determination at step 608 is negative, at step 612 other
"non-qualifying" counters for client "i" are incremented by the values contained at
byte offsets 7, 9, and 11, namely counters CLIENT[i].NQUAL_TOT.COUNT5 , CLIENT[i].NQUAL_TOT.ZIP4,
and CLIENT[i].NQUAL_TOT.BARCDE, respectively.
[0199] If other records remain in file COUNT.DAT (as determined at step 614), the function
MAKE_CLIENT_COUNTS loops back to step 602 to obtain the next record and to execute
the steps of Fig. 4L for that next record. After all records in file COUNT.DAT have
been processed by function MAKE_CLIENT_COUNTS, several "totals" are computed at step
616.
[0200] At step 616 the function MAKE_CLIENT_COUNTS determines the following totals:

Then, at step 616, for j = 0, 1, and 2, the function MAKE_CLIENT_COUNTS determines
TOTALS[j].TOTAL, which is evaluated for each j by the expression TOTALS[j].TOTAL =
TOTALS[j].COUNT5 + TOTALS[j].COUNT9 + TOTALS[j].BAR_CNT.
Function CORRELATE_BAGS
[0201] The function CORRELATE_BAGS (see Fig. 4M) determines the bag number (i.e., the sack
number) for each Zip Code and creates a file SACK3.TMP. The file SACK3.TMP is similar
to the file SACK2.TMP which is used to create file SACK3.TMP, but unlike file SACK2.TMP
the file SACK3.TMP has a bag number assigned to the "no" field in each record.
[0202] The input files utilized by function CORRELATE_BAGS are file SACK2.TMP, file SORTREC.DAT,
and file FULLSORT.DAT. These input files are created by the functions ASSIGN_SACKS,
MAKE_BAGS, and MAKE_BAGS, respectively.
[0203] Function CORRELATE_BAGS reads successive records from the file SACK2.TMP and attempts
to first match the current record with a record from the file SORTREC.DAT. If a match
is found, the function CORRELATE_BAGS can assign a bag number for the Zip Code for
the current record from the file SACK2.TMP, and writes a record including that bag
number to the new file SACK3.TMP. If a match is not found in the file SORTREC.DAT,
the function CORRELATE_BAGS then attempts to match the current record from the file
SACK2.TMP with a record from the file FULLSORT.DAT. If a match is found, the function
CORRELATE_BAGS assigns a bag number for the Zip Code for the current record from the
file SACK2.TMP, and writes a record including that bag number to the new file SACK3.TMP.
[0204] At step 640 the function CORRELATE_BAGS reads a record from the file SACK2.TMP. At
step 642 the function CORRELATE_BAGS obtains the value in the PTYPE field for the
record just read from the file SACK2.TMP. At step 644 a check is made to determine
if the PTYPE value is "M", indicating a mixed states package. If the PTYPE is "M",
the function CORRELATE_BAGS knows that all MIXED STATES packages are to go into the
first bin, and accordingly at step 646 assigns SACK.NO the value "1". Then, at step
648, a record is written to the new file SACK3.TMP, with the "no" field of the record
having stored therein the value of SACK.NO (i.e., "1").
[0205] If the PTYPE value for the current record from file SACK2.TMP is not an "M", at step
650 the function CORRELATE_BAGS obtains the PACKAGE_ZIP_ID value from the zip identifier
field of the struct PACKAGE included in the struct SACK comprising the record for
the file SACK2.TMP. Then, preparatory to a loop of reading records from file SORTREC.DAT,
at step 652 the function CORRELATE_BAGS initializes the flag MATCH_FLAG to have a
TRUE value and the index CURRENT_INDEX to have the value "0".
[0206] As indicated above, the function CORRELATE_BAGS first attempts to match the current
record in the file SACK2.TMP with a record in file SORTREC.DAT. In this regard, at
step 654 the function CORRELATE_BAGS requires the reading of a record from the file
SORTREC.DAT. Then, at step 656, a value for pointer CURRENT_PTR is determined, which
value reflects the physical position of the current record in the file SORTREC.DAT
relative to the beginning of the file SORTREC.DAT. As will be seen below, the value
of pointer CURRENT_PTR is ultimately used to determine the bag number for the package
referred to by the current record in file SACK2.TMP.
[0207] At step 658 the function CORRELATE_BAGS determines whether information from the current
record in file SACK2.TMP matches the corresponding information for the current record
in file SORTREC.DAT. Specifically, the PTYPE and zip identifier fields for the two
current records are compared. In this regard, the zip identifier information for the
current record in file SACK2.TMP is stored in the location PACKAGE_ZIP_ID previously
determined at step 650.
[0208] If a "match" is located at step 658, the function CORRELATE_BAGS performs three operations
depicted by steps 660, 662, and 664. At step 660 the value of CURRENT_PTR is used
to find the bag number and set the SACK.NO. At step 662 a record is written to the
new file SACK3.TMP, with the value of SACK.NO as determined at step 660 being stored
in the "no" field of the record. At step 664, the flag MATCH_FLAG is set to a TRUE
value.
[0209] At step 666, reached either from step 664 after a "match" or from step 658 when a
match is not found, the index CURRENT_INDEX is incremented. As explained above, the
value of CURRENT_INDEX is used at step 656 to determine the value of CURRENT_PTR,
which in turn is used at step 660 to determine the value of SACK.NO.
[0210] At step 668 the function CORRELATE_BAGS checks to see if the flag MATCH_FLAG has
a TRUE value, indicating that a match has just been found. If so, the function CORRELATE_BAGS
knows that it is finished with the current record in file SACK2.TMP, and can go on
to process the next record in file SACK2.TMP, with the hope of finding a match for
that next record as well. In this regard, an affirmative determination at step 668
results in a branching back to step 640 for reading the next record in file SACK2.TMP.
[0211] If a match were not found comparing the current record in file SACK2.TMP with the
current record in file SORTREC.DAT, at step 670 the function CORRELATE_BAGS checks
to determine whether there are yet further records in the file SORTREC.DAT for which
a comparison for prospective match can be made. If additional records remain in file
SORTREC.DAT, the function CORRELATE_BAGS branches back to step 654 for reading the
next record in file SORTREC.DAT. For that next record, the steps 658 through 668 of
Fig. 4M are executed, with that next record from file SORTREC.DAT becoming the "current"
record from file SORTREC.DAT.
[0212] If, at step 670, it is determined that the file SORTREC.DAT has been exhausted with
no match for the current record in file SACK2.TMP, as indicated above the function
CORRELATE BAGS goes on to check if a match for the current record in file SACK2.TMP
can be found with a record in the file FULLSORT.DAT. Before reading a record from
the file FULLSORT.DAT, however, at step 672 a loop parameter "i" is initialized at
"0". As seen hereinafter, this loop parameter "i" plays a role in determining the
SACK.NO should a match occur.
[0213] At step 674 the function CORRELATE_BAGS requires the reading of a record from the
file FULLSORT.DAT.At step 678 the function CORRELATE_BAGS determines whether information
from the current record in file SACK2.TMP matches the corresponding information for
the current record in file FULLSORT.DAT. Specifically, the PTYPE and zip identifier
fields for the two current records are compared. In this regard, the zip identifier
information for the current record in file SACK2.TMP is stored in the location PACKAGE_ZIP_ID
previously determined at step 650.
[0214] If a "match" is located at step 678, the function CORRELATE_BAGS performs three operations
depicted by steps 680, 682, and 684. At step 680 the value of the loop parameter "i"
(which points to the first pass record with a match) is used to find the assigned
bag number and to set SACK.NO. At step 682 a record is written to the new file SACK3.TMP,
with the value of SACK.NO as determined at step 680 being stored in the "no" field
of the record. At step 684, the flag MATCH_FLAG is set to a TRUE value.
[0215] At step 686, reached either from step 684 after a "match" or from step 678 when a
match is not found, the loop parameter "i" is incremented. As explained above, the
value of the loop parameter "i" is used to determine the value of SACK.NO.
[0216] At step 688 the function CORRELATE_BAGS checks to see if the flag MATCH_FLAG has
a TRUE value, indicating that a match has just been found. If so, the function CORRELATE_BAGS
knows that it is finished with the current record in file SACK2.TMP, and can go on
to process the next record in file SACK2.TMP, with the hope of finding a match for
that next record as well. In this regard, an affirmative determination at step 688
results in a branching back to step 640 for reading the next record in file SACK2.TMP.
[0217] If a match were not found comparing the current record in file SACK2.TMP with the
current record in file SORTREC.DAT, at step 690 the function CORRELATE_BAGS checks
to determine whether there are yet further records in the file FULLSORT.DAT for which
a comparison for prospective match can be made. If additional records remain in file
FULLSORT.DAT, the function CORRELATE_BAGS branches back to step 674 for reading the
next record in file FULLSORT.DAT. For that next record, the steps 678 through 688
of Fig. 4M are executed, with that next record from file FULLSORT.DAT becoming the
"current" record from file FULLSORT.DAT.
[0218] If, at step 690, it is determined that the file FULLSORT.DAT has been exhausted with
no match for the current record in file SACK2.TMP, an error message is created at
step 692. When, at step 640, it is determined that the file SACK2.TMP has been exhausted,
and a match found for each record therein, processing continues with the function
SAVE_ANAL_CNT described below.
[0219] After the last record is read at step 640, processing continues with the function
SAVE_ANAL_CNT.
Function SAVE_ANAL_CNT
[0220] The function SAVE_ANAL_CNT (see Fig. 4L) creates a first pass count file ANAL_CNT.DAT
which resembles the file COUNT.DAT, except that the file ANAL_CNT.DAT has the parameters
package type (PTYPE), bag type (STYPE), and bag id (SACK.NO) appended to each record.
[0221] In the above regard, the function SAVE_ANAL_CNT uses the files COUNT.DAT and SACK3.TMP
as input. The file COUNT.DAT was created by the function FIRST_SORT_PASS (see Fig.
4A); the file SACK3.TMP was created by the file CORRELATE_BAGS (see Fig. 4M).
[0222] The file ANAL_CNT.DAT has its records sorted by zip code, then within zip code by
client, and within client by mailstream. Each record includes zip code counts by 5
Digit, ZIP+4, and ZIP+4 Barcoded categories, first pass destination bin, package type
(PTYPE), bag type (STYPE), and bag ID number (SACK.NO).
[0223] Multiple records of the following structure are contained in the file ANAL_CNT.DAT:

Thus, the file ANAL_CNT.DAT is sorted by Zip code, then within Zip code by client,
then within client by mailstream.
[0224] At step 700, the function SAVE_ANAL_CNT (see Fig. 4N) reads an initial SACK3.TMP
record. Then successive COUNT.DAT records are read and a corresponding ANAL_CNT.DAT
record is written for every COUNT.DAT record read. Since there is only one record
per package in file SACK3.TMP, and since packages may be made up of multiple records,
there will be more COUNT.DAT records than SACK3.TMP records. After a COUNT.DAT record
is read, at steps 702 and 704 the ZIP code is checked to see if it belongs to the
package from the SACK3.TMP record. If the ZIP code belongs to the packages, the package
type, bag type, and bag number information from the package is appended to the information
in the COUNT.DAT record and written to ANAL_CNT.DAT at step 708. If the ZIP code did
not belong to the current SACK3.TMP record, another SACK3.TMP record is read and the
new information is written to ANAL_CNT.DAT as in step 708 discussed above. This process
repeats until all records in COUNT.DAT have been processed.
Function SET_POST_CNTS
[0225] The function SET_POST_CNTS (see Fig. 4N) sets up initial counts files for postage
reporting based on the final sorting pass. In this respect, the function SET_POST_CNTS
uses input files ANAL_CNT.DAT (generated by the function SAVE_ANAL_CNT) and AGGR.DAT
(generated by the function FIRST_SORT_PASS) to create two new files, file PASS1AGGR.DAT
and file PASS2AGGR.DAT. The file PASS1AGGR.DAT contains counts for all mailpieces
that will not be fed during subsequent pass sorting. The file PASS2AGGR.DAT contains
counts for subsequent pass sorting. Both files PASS1AGGR.DAT and PASS2AGGR.DAT include
counts for both 5 Digit level rate (qualifying) and Basic level rate (non-qualifying)
mailpieces by 5 Digit, ZIP+4, and ZIP+4 Barcoded categories, and also include rejects.
[0226] The following data structure is employed for both files PASS1AGGR.DAT and PASS2AGGR.DAT:

[0227] The function SET_POST_CNTS basically creates the new files PASS1AGGR.DAT and PASS2AGGR.DAT
after reading all the records in the file ANAL_CNT.DAT. At the beginning of a loop
commencing with step 730, the function SET_POST_CNTS reads a record from the file
ANAL_CNT.DAT. At step 732 the function SET_POST_CNTS determines whether the bin number
included in the bin field from the record just read from file ANAL_CNT.DAT is a bin
containing fully sorted packages. This is done by checking whether the element of
array FULLSORT corresponding to that bin has a non-zero value. If a zero value exists
for the element in array FULLSORT corresponding to that bin, the function SET_POST_CNTS
loops back to step 730 for the reading of another record from the file ANAL_CNT.DAT.
Otherwise, execution continues with step 734.
[0228] At step 734 the function SET_POST_CNTS examines the sack type (STYPE) field of the
current record from the file ANAL_CNT.DAT. If the value of STYPE is FIVE_DIGIT or
MIXED_FIVE, the function SET_POST_CNTS knows to go to step 736 to increase certain
"qualifying" counters. Otherwise the function SET_POST_CNTS will go to step 738 to
increase certain "non-qualifying" counters.
[0229] In the above regard, at step 736 the function SET_POST_CNTS increases the following
counters by the values stored in corresponding fields in the current record from file
ANAL_CNT.DAT: counter PASS1.QUAL.COUNT5; counter PASS1.QUAL.COUNT9; and, counter PASS1.QUAL.BAR_CNT.
Alternatively, at step 738 the function SET_POST_CNTS increases the following counters
by the values stored in corresponding fields in the current record from file ANAL_CNT.DAT:
counter PASS1.NQUAL.COUNT5; counter PASS1.NQUAL.COUNT9; and, counter PASS1.NQUAL.BAR_CNT.
[0230] At step 740 the function SET_POST_CNTS determines whether the current record read
from file ANAL_CNT.DAT was the last record. If not, processing loops back to step
730 for the reading of a new record from file ANAL_CNT.DAT, after which the steps
732 et seq. of function SET_POST_CNTS are repeated, with the next record becoming
the "current" record in accordance with the preceding discussion.
[0231] Upon the exhaustion of file ANAL_CNT.DAT as determined at step 740, the function
SET_POST_CNTS reads the file AGGR.DAT in order to include reject counts (step 742).
Then, at step 744, the function SET_POST_CNTS writes the entire file PASS1AGGR.DAT,
which has the format described above. Thereafter, at step 746, the function SET_POST_CNTS
initializes all count values to zero in the file PASS2AGGR.DAT in preparation for
subsequent use.
Function INIT_GROUP_CNTS
[0232] Function INIT_GROUP_CNTS produces a file GRPCNTS.DAT that maintains counts, by group
number, of actually fed and rejected mailpieces. The file GRPCNTS.DAT is initialized
with all zeros and is intended to be updated during subsequent pass sorting. The file
GRPCNTS.DAT is used for second pass sorting display and insures that mailpieces fed
in a wrong mode will not allow the reject count to go negative. Records in the file
GRPCNTS.DAT are of the following structure:
Function PRINT_OUT
[0233] Function PRINT_OUT serves to print information pretaining to the files created in
the manner described above. In particular, the function PRINT_OUT generates hardcopies
of the following reports: Group Listing Report (see TABLES 1, 2A - 2E); Bag Tags Report
(see TABLE 3); Job Summary Report (see TABLE 4); Postage Summary Report (see TABLES
5 - 6A); and, Bag Audit Report (see TABLE 7).
[0234] TABLE 1 is produced by printing out file ANAL_SUM.DAT; file TOTQUL.DAT; file MAJ_TREE.DAT;
file FRST_PAK.DAT; and, file FRST_SAK.DAT. TABLES 1, 2A - 2E show which bins 26 are
to be grouped together for subsequent for subsequent passes through the sorter apparatus
20. For example, bins 26₃ - 26₇ are to be grouped together as Group 1; bin 26₈ forms
Group 2; bin 26₉ forms Group 3; bins 26₁₀ - 26₁₁ are to be grouped together as Group
5; and so forth. Some groups are noticeably absent from TABLE 1, such as Group 4,
for example. It will be seen below in connection with TABLES 2C and 2D that Group
4 is ultimately generated during a second pass of the Group 3 mailpieces. Likewise,
other groups not listed in TABLE 1 are generated during successive passes (not the
first passes) of other groups.
[0235] The output of TABLE 1, and of TABLES 2A - 2E explained hereafter, are available upon
completion of the program ANALYZE_MAIL after the initial pass of mailpieces through
the sorter 20. Using the output of TABLE 1 AND TABLES 2A - 2E, an operator knows how
to group together mailpieces for subsequent passes before those passes are executed.
For example, after the initial pass is completed and the program ANALYZE_MAIL has
generated TABLE 1 and TABLES 2A - 2E, the operator would manually retrieve the Group
1 mailpieces from bins 26₃ - 26₇ and load those mailpieces into the input hopper 30
of the sorter 20.
[0236] TABLES 2A - 2E illustrate the output generated upon the printing of the Group Listing
Report, which reflects the contents of the bins 26 after passes of the various groups.
Table 2A reflects the contents of the bins 26 after the Group 1 mailpieces (gathered
from bins 26₃ - 26₇ after the initial pass). Each bin 26 has a package stored therein,
since it is indicated that these bins are fully sorted.
[0237] TABLE 2A has five headings: "BIN"; "ZIP"; "P"; "B", and "ID". The "BIN" heading refers
to the bins 26 of the sorting machine 20. For example, "bin 3" refers to bin 26₃ according
to the nomenclature previously adopted. "ZIP" refers to the Zip Code for the package
of mailpieces stored in the associated bin. The heading "P" refers to the type of
package (PTYPE) stored in the bin. The heading "B" refers to the type of sack (STYPE)
in which the package in the bin is to be inserted. The heading "ID" refers to the
bag identification number, or sack number, of the sack which includes the mailpieces
of the bin.
[0238] For example, from TABLE 2A it is seen that bin 26₃ contains a 5 Digit package for
Zip code 02806, which is to be placed in a MIXED_FIVE ("M5") sack bearing sack number
("ID") "2". As TABLE 2A is further read across the page, it is also seen that bin
26₄ contains a 5 Digit package for Zip code 02809, which is to be placed in the same
MIXED_FIVE ("M5") sack bearing sack number ("ID") "2". In this regard, if a number
is not listed under the heading "ID" for a bin, it is understood that the mailpieces
from that bin are to be placed in the same sack with the preceding bin(s). Thus, from
TABLE 2A it is apparent that the packages from bins 26₃ - 26₃₄ will all be placed
in the same sack (i.e., the sack bearing sack number "2"). Similarly, the packages
from bins 26₃₅ - 26₅₁ are to be placed in sack number 3; the three digit packages
from bins 26₅₂ - 26₅₄ are to be placed in sack number 4; and so forth. Noticeably,
bin 26₁₂₄ houses the MIXED_STATES sack, which bears sack number 1 (see the function
MAKE_BAGS, step 502, for an explanation in this regard).
[0239] After running Group 1, and loading all the mailpieces from Group 1 into sacks bearing
sack numbers 1 - 12 as indicated in TABLE 2A, the machine operator requests that a
new sort scheme be loaded into memory with instructions to direct pieces in Group
2 to the proper bins. This is done by referencing file SORTREC.DAT (the creation of
which has been described above). The operator also loads the mailpieces of Group 2
(from bin 26₈ from the initial pass) into the input hopper 30 of the sorter 20. TABLE
2B explains how the Group 2 mailpieces will be distributed across the bins 26. The
Group 2 mailpieces from bins 26₃ - 26₆ are all to be collected for insertion in a
THREE_DIGIT sack which will bear sack number 13; the Group 2 mailpieces from bins
26₇ 26₁₉ are all to be collected for insertion into a STATE sack which will bear sack
number 14.
[0240] After collecting the Group 2 mailpieces into sacks 13 and 14 in accordance with TABLE
2B, the operator loads the mailpieces for Group 3 into the input hopper 30 of the
sorter 20. The sorter 20 directs the Group 3 mailpieces to the bins 26 in accordance
with TABLE 2C. In this regard, TABLE 2C directs how the sacks numbered 15 through
21 inclusive are to be filled (i.e., from which bins packages are gathered for filling
the respective sacks). TABLE 2C also indicates that bin 26₁₂₈ is to be further sorted
as Group 4. Recall that Group 4 was not listed in TABLE 1, the reason for which is
now understood. Group 4 is derived from Group 3, inasmuch as a secondary sorting pass
arising from Group 3 necessitated the generation of Group 4.
[0241] After collecting the packages from the bins 26 after the running of Group 3 as indicated
in TABLE 2C, the operator collects Group 4 from bin 26₁₂₈ and places the Group 4 mailpieces
in the input hopper 30 of the sorter 20. TABLE 2D reflects the contents of the bins
26 after the running of the Group 4 mailpieces. From TABLE 2D it is seen that packages
from bins 26₃ - 26₁₇ are also to be included in sack number 21 generated during the
running of Group 4; that packages from bins 26₁₈ - 26₃₀ are to be collected together
for insertion into sack number 22; and so forth through sack number 27.
[0242] Subsequent groups are run in accordance with TABLE 1 and in the manner of the foregoing
discussion. TABLE 2E reflects the contents of the bins 26 upon the running of the
last group, i.e. Group 86. It is thus seen that a total of 722 sacks were filled by
the mailpieces run during the illustrative batch.
[0243] TABLE 3 shows a partial listing of bag tag data generated by the program ANALYZE_MAIL.
The data for generating TABLE 3 is obtained from the file BAGTAG.DAT in conjunction
with the table published by the USPS in the DMM. TABLE 3 reflects the contents of
bag tags printed for the sacks filled in accordance with the execution of the program
ANALYZE_MAIL.
[0244] Each bag tag has its first three lines of text generated in accordance with the format
prescribed by the
Domestic Mail Manual. In addition, a forth line of text tells the operator what group was run, and which
bins to collect together for insertion into the bag. For example, the first bag tag
generated for Group 1 reads:

indicating that Group 1 bins 26₃ - 26₃₄ are to be collected together for insertion
into a sack bearing sack number ("bag number") "2".
[0245] Thus, using the bag tags generated by the sorter 20 as a result of the execution
of program ANALYZE_MAIL, an operator can visibly determine, for each group, which
bins 26 are to have their contents loaded into a given sack, as well as the sack number
for that sack. Moreover, advantageously the bins having contents for the same sack
are consecutively arranged (i.e., arranged in successive physical relationship), so
that the operator need not jump around from bin to bin, as by walking around the large
sorting machine 20, for example.
[0246] The Job Summary Report in TABLE 4 is produced using information from the file CLIENT.DAT,
which file was produced byt he function MAKE_CLIENT_COUNTS. The Job Summary Report
demonstrates the accounting capabilities of the program ANALYZE_MAIL. The report is
a brief summary of total fed and total reject mailpiece counts maintained by individual
mailstreams.
[0247] The Postage Summary and Postage Summary by client/mailstream is display in TABLE
5 and TABLES 6 - 6A, respectively. These reports are produced from information obtained
from the file CLIENT.DAT. These reports demonstrate the requirements for maintaining
detail counts during execution of the program ANALYZE_MAIL.
[0248] The Bag Audit Report shown in TABLE 7 demonstrates a unique advantage of the program
ANALYZE_MAIL. This report is generated from information in the file ANAL_CNT.DAT.
The program ANALYZE_MAIL organizes data in such a way that counts are made available
by package, bag, client, mailstream, and ZIP class categories. This feature is needed
to verify the accuracy of the sort process and the accounting.