RUnit/0000755000175100001440000000000011444151274011334 5ustar hornikusersRUnit/man/0000755000175100001440000000000011444151274012107 5ustar hornikusersRUnit/man/runit.Rd0000644000175100001440000002242611303245740013541 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: runit.Rd,v 1.23 2009/11/25 15:23:12 burgerm Exp $ \encoding{latin1} \name{runTestSuite} \alias{runTestSuite} \concept{test suite} \alias{runTestFile} \concept{test runner} \alias{defineTestSuite} \alias{isValidTestSuite} \title{Definition and execution of RUnit test suites.} \usage{ defineTestSuite(name, dirs, testFileRegexp = "^runit.+\\\\.[rR]$", testFuncRegexp = "^test.+", rngKind = "Marsaglia-Multicarry", rngNormalKind = "Kinderman-Ramage") isValidTestSuite(testSuite) runTestSuite(testSuites, useOwnErrorHandler = TRUE, verbose = getOption("RUnit")$verbose) runTestFile(absFileName, useOwnErrorHandler = TRUE, testFuncRegexp = "^test.+", rngKind = "Marsaglia-Multicarry", rngNormalKind = "Kinderman-Ramage", verbose = getOption("RUnit")$verbose) } \arguments{ \item{name}{The name of the test suite.} \item{dirs}{Vector of absolute directory names where to look for test files.} \item{testFileRegexp}{Regular expression for matching test files.} \item{testFuncRegexp}{Regular expression for matching test functions.} \item{rngKind}{name of an available RNG (see \code{\link[base:Random]{RNGkind}} for possible options).} \item{rngNormalKind}{name of a valid rnorm RNG version (see \code{\link[base:Random]{RNGkind}} for possible options).} \item{testSuite}{A single object of class test suite.} \item{testSuites}{A single object of class test suite or a list of test suite objects.} \item{useOwnErrorHandler}{If \code{TRUE} the RUnit framework installs its own error handler during test case execution (but reinstalls the original handler before it returns). If \code{FALSE} the error handler is not touched by RUnit but then the test protocol does not contain any call stacks in the case of errors.} \item{verbose}{level of verbosity of output log messages, 0: omits begin/end comments for each test function. Queried from global options set for RUnit at package load.} \item{absFileName}{Absolute file name of a test function.} } \description{ \code{runTestSuite} is the central function of the RUnit package. Given one or more test suites it identifies and sources specified test code files one after another and executes all specified test functions defined therein. This is done sequentially for suites, test code files and test functions. During the execution information about the test function calls including the possible occurrence of failures or errors is recorded and returned at the end of the test run. The return object can then be used to create a test protocol of various formats. \code{runTestFile} is just a convenience function for executing the tests in a single test file. \code{defineTestSuite} is a helper function to define a test suite. See below for a precise definition of a test suite. \code{isValidTestSuite} checks if an object defines a valid test suite. } \details{ The basic idea of the RUnit test framework is to declare a certain set of functions to be test functions and report the results of their execution. The test functions must not take any parameter nor return anything such that their execution can be automatised. The specification which functions are taken as test functions is contained in an object of class \code{RUnitTestSuite} which is a list with the following elements. \describe{ \item{name}{A simple character string. The name of a test suite is mainly used to create a well structure test protocol.} \item{dirs}{A character vector containing the absolute names of all directories where to look for test files.} \item{testFileRegexp}{A regular expression specifying the test files. All files in the test directories whose names match this regular expression are taken as test files. Order of file names will be alphabetical but depending on the used locale.} \item{testFuncRegexp}{A regular expression specifying the test functions. All functions defined in the test files whose names match this regular expression are used as test functions. Order of test functions will be alphabetical.} } After the RUnit framework has sequentially executed all test suites it returns all data collected during the test run as an object of class \code{RUnitTestData}. This is a (deeply nested) list with one list element for each executed test suite. Each of these executed test suite lists contains the following elements: \describe{ \item{nTestFunc}{The number of test functions executed in the test suite.} \item{nErr}{The number of errors that occurred during the execution.} \item{nFail}{The number of failures that occurred during the execution.} \item{dirs}{The test directories of the test suite.} \item{testFileRegexp}{The regular expression for identifying the test files of the test suite.} \item{testFuncRegexp}{The regular expression for identifying the test functions of the test suite.} \item{sourceFileResults}{A list containing the results for each separate test file of the test suite.} } The \code{sourceFileResults} list just mentioned contains one element for each specified test function in the source file. This element is a list with the following entries: \describe{ \item{kind}{Character string with one of \code{success}, \code{error} or \code{failure} describing the outcome of the test function.} \item{msg}{the error message in case of an error or failure and \code{NULL} for a successfully executed test function.} \item{time}{The duration (measured in seconds) of the successful execution of a test function and \code{NULL} in the case of an error or failure.} \item{traceBack}{The full trace back as a character vector in the case of an error and \code{NULL} otherwise.} } To further control test case execution it is possible to define two parameterless function \code{.setUp} and \code{\link{.tearDown}} in each test file. \code{.setUp()} is executed directly before and \code{.tearDown()} directly after each test function execution. Quite often, it is useful to base test cases on random numbers. To make this procedure reproducible, the function \code{runTestSuite} sets the random number generator to the default setting \code{RNGkind(kind="Marsaglia-Multicarry", normal.kind="Kinderman-Ramage")} before sourcing each test file (note that this default has been chosen due to historical reasons and differs from the current R default). This default can be overwritten by configuring the random number generator at the beginning of a test file. This setting, however, is valid only inside its own source file and gets overwritten when the next test file is sourced. } \value{ \code{runTestSuite} and \code{runTestFile} both return an object of class RUnitTestData. \code{defineTestSuite} returns an object of class \code{RUnitTestSuite}. } \author{ Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ \code{\link{checkTrue}} and friends for writing test cases. \code{\link{printTextProtocol}} and \code{\link{printHTMLProtocol}} for printing the test protocol. See \link{RUnit-options} for global options controlling log out. } \examples{ ## run some test suite myTestSuite <- defineTestSuite("RUnit Example", system.file("examples", package = "RUnit"), testFileRegexp = "correctTestCase.r") testResult <- runTestSuite(myTestSuite) ## same but without the logger being involved ## source(file.path(system.file("examples", package = "RUnit"), ## "correctTestCase.r")) ## test.correctTestCase() ## prints detailed text protocol ## to standard out: printTextProtocol(testResult, showDetails = TRUE) ## use current default RNGs myTestSuite1 <- defineTestSuite("RUnit Example", system.file("examples", package = "RUnit"), testFileRegexp = "correctTestCase.r", rngKind = "Mersenne-Twister", rngNormalKind = "Inversion") testResult1 <- runTestSuite(myTestSuite) ## for single test files, e.g. outside a package context testResult2 <- runTestFile(file.path(system.file("examples", package = "RUnit"), "correctTestCase.r")) printTextProtocol(testResult2, showDetails = TRUE) } \keyword{programming} \concept{RUnit} RUnit/man/RUnit-options.Rd0000644000175100001440000000450611303245767015142 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: RUnit-options.Rd,v 1.2 2009/11/25 15:23:35 burgerm Exp $ \encoding{latin1} \name{options} \alias{RUnit options} \alias{RUnit-options} \title{RUnit options} \description{ RUnit uses three options available via the global R options list } \details{ RUnit specif options are added to R's global options list on package loading and removed again on pachage unloading. } \section{Options used in RUnit}{ \describe{ \item{\code{silent}:}{logical flag, default \code{FALSE}, sets the 'silent' argument for \code{checkException}. Allows to globally silence output from exception checks for all test suites excuted in one run.} \item{\code{verbose}:}{non-negative integer, default \code{1}, \code{0}: surpresses enclosing begin/end messages for each test case, \code{1}: output enclosing begin/end messages for each test case} \item{\code{outfile}:}{\code{NULL}, connection or character, default \code{NULL}. If non-null has to be an open connection or a file name. Will be used to redirect all output to specified file/connection using \code{sink}. Connection is close after test suite execution call (via \code{runTestSuite} or \code{runTestFile}) has completed. If the file exists it is overwriten.} } } \author{Matthias Burger} \seealso{\code{\link{options}}, \code{\link{getOption}}, \code{\link{sink}}.} \examples{ \dontrun{ ## quiet log output ro <- getOption("RUnit") ro$silent <- TRUE ro$verbose <- 0L options("RUnit"=ro) } } \keyword{programming} \keyword{environment} \concept{RUnit} RUnit/man/RUnit-intro.Rd0000644000175100001440000000427311274624140014574 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: RUnit-intro.Rd,v 1.6 2009/11/05 19:32:48 burgerm Exp $ \encoding{latin1} \name{RUnit} \alias{RUnit} \title{RUnit - Package Description} \description{ This package models the common Unit Test framework for R and provides functionality to track results of test case execution and generate a summary report. It also provides tools for code inspection and thus for test case coverage analysis. The design is inspired by the popular JUnit unit test framework. This package comes with a set of unit tests, serving as a test battery to check correct functioning against new R versions released as well as practical examples for writing test cases (see the \file{inst/unitTests} subdirectory of the source package, or \file{unitTests} contained in the binary package version). The \R wiki has a section on setting up a test suite for your package and combining it with \command{R CMD check} as well as references to alternative implementations: \url{http://wiki.r-project.org/rwiki/doku.php?id=developers:runit} } \references{RUnit - A Unit Test Framework for R. useR! 2004 Vienna} \author{ Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ See \code{\link{defineTestSuite}}, \code{\link{runTestSuite}} for unit testing or \code{\link{inspect}} and \code{\link{tracker}} for code inspection. } \keyword{programming} \concept{RUnit} RUnit/man/testCaseSetUp.Rd0000644000175100001440000000304511274630624015136 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: testCaseSetUp.Rd,v 1.2 2009/11/05 20:12:04 burgerm Exp $ \encoding{latin1} \name{.setUp} \alias{.setUp} \alias{.tearDown} \title{Definition of RUnit Test Case code files.} \usage{ .setUp() .tearDown() } \description{ Either one or both functions have to be provided by the test case author, take precedence over the dummy definitions provided by the RUnit package and are called once for every test case identified. } \details{ To be written ... } \value{ Functions do not return a value; called for their side effects. } \author{ Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ \code{\link{runTestFile}}. } \keyword{programming} \concept{RUnit} RUnit/man/RUnit-internal.Rd0000644000175100001440000000306711171573273015263 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: RUnit-internal.Rd,v 1.5 2009/04/16 09:13:31 burgerm Exp $ \name{RUnit-internal} \alias{includeTracker} \alias{plotConnection.trackInfo} \alias{writeBeginBody} \alias{writeBeginHead} \alias{writeBeginHtml} \alias{writeBeginTag} \alias{writeBeginTable} \alias{writeCR} \alias{writeEndBody} \alias{writeEndHead} \alias{writeEndHtml} \alias{writeEndTable} \alias{writeEndTag} \alias{writeHtmlEnd} \alias{writeHtmlHeader} \alias{writeHtmlSection} \alias{writeHtmlSep} \alias{writeImage} \alias{writeLi} \alias{writeLinkRef} \alias{writeLink} \alias{writeP} \alias{writeRaw} \alias{writeRawCR} \alias{writeTableRow} \alias{writeTitle} \title{Internal functions} \description{ Helper functions and private methods not intended for direct use. } \keyword{internal} RUnit/man/checkFuncs.Rd0000644000175100001440000001615011303246164014452 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: checkFuncs.Rd,v 1.17 2009/11/25 15:25:40 burgerm Exp $ \encoding{latin1} \name{checkFuncs} \alias{checkEquals} \alias{checkEqualsNumeric} \alias{checkIdentical} \alias{checkTrue} \alias{checkException} \alias{DEACTIVATED} \title{RUnit check functions} \usage{ checkEquals(target, current, msg, tolerance = .Machine$double.eps^0.5, checkNames = TRUE, ...) checkEqualsNumeric(target, current, msg, tolerance = .Machine$double.eps^0.5, ...) checkIdentical(target, current, msg) checkTrue(expr, msg) checkException(expr, msg, silent = getOption("RUnit")$silent) DEACTIVATED(msg) } \arguments{ \item{current, target}{objects to be compared (\code{checkEqualsNumeric} cannot handle S4 class objects).} \item{msg}{an optional message to document a check and to facilitate the identification of a possible failure. The message only appears as text in the test protocol, it is not further used in any of the check functions.} \item{tolerance}{numeric >= 0. A numeric check does not fail if differences are smaller than `tolerance'.} \item{checkNames}{flag, if \code{FALSE} the names attributes are set to \code{NULL} for both current and target before performing the check.} \item{expr}{syntactically valid R expression which can be evaluated and must return a logical scalar (\code{TRUE}|\code{FALSE}). A named expression is also allowed but the name is disregarded.} \item{silent}{flag passed on to \code{try}, which determines if the error message generated by the checked function is displayed. Queried from global options set for RUnit at package load.} \item{...}{optional arguments passed to \code{all.equal} or \code{all.equal.numeric}} } \description{A set of functions used to check the results of some test calculation. If these functions are called within the RUnit framework, the results of the checks are stored and reported in the test protocol. \code{checkEquals} compares two R objects by invoking \code{all.equal} on the two objects. If the objects are not equal an error is generated and the failure is reported to the test logger such that it appears in the test protocol. \code{checkEqualsNumeric} works just like \code{checkEquals} except that it invokes \code{all.equal.numeric} instead of \code{all.equal} \code{checkIdentical} is a convenience wrapper around identical using the error logging mechanism of RUnit. \code{checkTrue} uses the function \code{identical} to check if the expression provided as first argument evaluates to \code{TRUE}. If not, an error is generated and the failure is reported to the test logger such that it appears in the test protocol. \code{checkException} evaluates the passed expression and uses the \code{try} mechanism to check if the evaluation generates an error. If it does the test is OK. Otherwise an error is generated and the failure is reported to the test logger such that it appears in the test protocol. \code{DEACTIVATED} interrupts the test function and reports the test case as deactivated. In the test protocol deactivated test functions are listed separately. Test case deactivation can be useful in the case of major refactoring. Alternatively, test cases can be commented out completely but then it is easy to forget the test case altogether. } \details{ The check functions are direct equivalents of the various methods of the class junit.framework.Assert of Javas JUnit framework which served as basis for the RUnit package. For functions defined inside a package equipped with a namespace only exported functions can be accessed inside test cases directly. For functions not exported the only way to test them is to use the '\code{\link[base:ns-dblcolon]{:::}}' operator combined with the package name as a prefix. Special care is required if test cases are written for S4 classes and methods. If a new class is defined inside a test case via a \code{\link[methods]{setClass}} call the class is added to the global class cache and thus available outside the test case. It will persist until explicitly removed via a \code{\link[methods:findClass]{removeClass}} call. Same applies for new method and generic definitions. Be sure to remove methods and classes in each test case they are defined after the checks have been performed. This is an advise gained from the cumbersome experience: not doing so leads to difficult to pin down error causes incurred from previously executed test cases. For a simple example see the provided test cases in \Sexpr{file.path(system.file("examples", package="RUnit"), "runitVirtualClassTest.r")}. } \author{ Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ \code{\link{all.equal}}, \code{\link{all.equal.numeric}} and \code{\link{identical}} are the underlying comparison functions. \code{\link{try}} is used for error catching. \code{\link{.setUp}} for details on test case setup. See \link{RUnit-options} for global options controlling log out. } \examples{ checkTrue(1 < 2, "check1") ## passes fine ## checkTrue(1 > 2, "check2") ## appears as failure in the test protocol v <- 1:3 w <- 1:3 checkEquals(v, w) ## passes fine names(v) <- c("A", "B", "C") ## checkEquals(v, w) ## fails because v and w have different names checkEqualsNumeric(v, w) ## passes fine because names are ignored x <- rep(1:12, 2) y <- rep(0:1, 12) res <- list(a=1:3, b=letters, LM=lm(y ~ x)) res2 <- list(a=seq(1,3,by=1), b=letters, LM=lm(y ~ x)) checkEquals( res, res2) ## passes fine checkIdentical( res, res) checkIdentical( res2, res2) ## checkIdentical( res, res2) ## fails because element 'a' differs in type fun <- function(x) { if(x) { stop("stop conditions signaled") } return() } checkException(fun(TRUE)) ## passes fine ## checkException(fun(FALSE)) ## failure, because fun raises no error checkException(fun(TRUE), silent=TRUE) ## special constants ## same behaviour as for underlying base functions checkEquals(NA, NA) checkEquals(NaN, NaN) checkEquals(Inf, Inf) checkIdentical(NA, NA) checkIdentical(NaN, NaN) checkIdentical(-Inf, -Inf) ## DEACTIVATED("here one can document on the reason for deactivation") } \keyword{programming} \concept{RUnit} RUnit/man/inspect.Rd0000644000175100001440000000521211274625624014051 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: inspect.Rd,v 1.11 2009/11/05 19:46:28 burgerm Exp $ \encoding{latin1} \name{inspect} \alias{inspect} \title{Track the executed code lines of a function or method.} \usage{ inspect(expr, track = track) } \arguments{ \item{expr}{Any R function or method call.} \item{track}{list object, as returned by a call to \code{tracker}.} } \description{ \code{inspect} examines and modifies the source code of a function or method. After the modification of the source code, the modified function will be executed and the result of the tracking process will be stored. To store the information a \code{tracker} environment with the name track must exist. Note, that not all R code constructs can be handled at the current state. In some cases it is not possible to track a specific code line. Therefore, clearly structured code with consequent use of opening and closing braces to indicate conditional expressions can prevent these parser problems. } \details{The return value of \code{inspect} is the result returned by the function executed. If the function has no return value nothing is returned either.} \author{Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ \code{\link{tracker}} for the call tracking object, and \code{\link{printHTML.trackInfo}} for displaying results. } \examples{ ## example function foo <- function(x){ y <- 0 for(i in 1:100) { y <- y + i } return(y) } ## the name track is necessary track <- tracker() ## initialize the tracker track$init() ## inspect the function ## res will collect the result of calling foo res <- inspect(foo(10), track = track) ## get the tracked function call info resTrack <- track$getTrackInfo() ## create HTML sites printHTML.trackInfo(resTrack) } \keyword{programming} \concept{RUnit} RUnit/man/textProtocol.Rd0000644000175100001440000001420111274625624015110 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: textProtocol.Rd,v 1.16 2009/11/05 19:46:28 burgerm Exp $ \encoding{latin1} \name{textProtocol} \alias{printTextProtocol} \alias{printHTMLProtocol} \alias{print.RUnitTestData} \alias{summary.RUnitTestData} \alias{getErrors} \title{Printing a plain text or HTML version of an RUnit test run protocol.} \usage{ printTextProtocol(testData, fileName = "", separateFailureList = TRUE, showDetails = TRUE, traceBackCutOff = 9) printHTMLProtocol(testData, fileName = "", separateFailureList = TRUE, traceBackCutOff = 9, testFileToLinkMap = function(x) x ) print.RUnitTestData(x, ...) summary.RUnitTestData(object, ...) getErrors(testData) } \arguments{ \item{testData, x, object}{objects of class \code{RUnitTestData}, typically obtained as return value of a test run.} \item{fileName}{Connection where to print the text protocol (printing is done by the \code{cat} command).} \item{separateFailureList}{If \code{TRUE} a separate list of failures and errors is produced at the top of the protocol. Otherwise, the failures and errors are only listed in the details section.} \item{showDetails}{If \code{TRUE} the protocol contains a detailed listing of all executed test functions.} \item{traceBackCutOff}{The details section of the test protocol contains the call stack for all errors. The first few entries of the complete stack typically contain the internal RUnit function calls that execute the test cases and are irrelevant for debugging. This argument specifies how many calls are removed from the stack before it is written to the protocol. The default value is chosen such that all uninteresting RUnit calls are removed from the stack if \code{runTestSuite} has been called from the console. This argument takes effect only if \code{showDetails=TRUE}.} \item{testFileToLinkMap}{This function can be used to map the full name of the test file to a corresponding html link to be used in the html protocol. By default, this is the identity map. See example below.} \item{...}{additional arguments to summary are passed on to the printTextProtocol() call.} } \description{ \code{printTextProtocol} prints a plain text protocol of a test run. The resulting test protocol can be configured through the function arguments. \code{printHTMLProtocol} prints an HTML protocol of a test run. For long outputs this version of the test protocol is slightly more readable than the plain text version due to links in the document. The resulting test protocol can be configured through the function arguments. \code{print} prints the number of executed test functions and the number of failures and errors. \code{summary} directly delegates the work to \code{printTextProtocol}. \code{getErrors} returns a list containing the number of test functions, the number of deactivated functions (if there are any), the number of errors and the number of failures. } \details{ The text protocol can roughly be divided into three sections with an increasing amount of information. The first section as an overview just reports the number of executed test functions and the number of failures and errors. The second section describes all test suites. Optionally, all errors and failures that occurred in some test suite are listed. In the optional third section details are given about all executed test functions in the order they were processed. For each test file all test functions executed are listed in the order they were executed. After the test function name the number of \code{check<*>} function calls inside the test case and the execution time in seconds are stated. In the case of an error or failure as much debug information as possible is provided. } \author{Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ \code{\link{runTestSuite}} } \examples{ ## run some test suite myTestSuite <- defineTestSuite("RUnit Example", system.file("examples", package = "RUnit"), testFileRegexp = "correctTestCase.r") testResult <- runTestSuite(myTestSuite) ## prints detailed text protocol ## to standard out: printTextProtocol(testResult, showDetails = TRUE) ## prints detailed html protocol ## to standard out printHTMLProtocol(testResult) \dontrun{ ## example function to add links to URL of the code files in a code ## repository, here the SourceForge repository testFileToSFLinkMap <- function(testFileName, testDir = "tests") { ## get unit test file name bname <- basename(testFileName) ## figure out package name regExp <- paste("^.*/([\\.a-zA-Z0-9]*)/", testDir,"/.*$", sep = "") pack <- sub(regExp, "\\1", testFileName) return(paste("http://runit.cvs.sourceforge.net/runit/", pack, testDir, bname, sep = "/")) } ## example call for a test suite run on the RUnit package testSuite <- defineTestSuite("RUnit", "/RUnit/tests", testFileRegexp = "^test.+") testResult <- runTestSuite(testSuite) printHTMLProtocol(testResult, fileName = "RUnit-unit-test-log.html", testFileToLinkMap = testFileToSFLinkMap ) } } \keyword{programming} \concept{RUnit} RUnit/man/printHTML.trackinfo.Rd0000644000175100001440000000537611274625624016217 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: printHTML.trackinfo.Rd,v 1.13 2009/11/05 19:46:28 burgerm Exp $ \encoding{latin1} \name{printHTML.trackInfo} \alias{printHTML.trackInfo} \alias{printHTML} \title{Write HTML pages of the tracking result.} \usage{ printHTML.trackInfo(object, baseDir = ".") } \arguments{ \item{object}{'trackInfo' S3 class object (list), containing the result of the function \code{tracker}.} \item{baseDir}{A character string, specifying the base directory for the HTML pages to be written to. Defaults to the current working directory.} } \description{ \code{printHTML.trackInfo} creates a subdirectory named "result" in the base directory specified via \code{baseDir}. All HTML pages and images will be put in that directory. } \details{An "index.html" page will be created in the directory "results" which is the root entry page of the HTML pages. The displayed result for every tracked function consists of two HTML pages. The first page is an overview on how often every line of code was executed. Code lines not executed are highlighted red, executed lines are shown in green. The second page is a graph representation of the execution flow of the function. Each code line has a edge pointing to the next code line that is executed subsequently. Thus loops and jumps become clearly visible. } \author{Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{&} Matthias Burger} \seealso{ \code{\link{tracker}} for the call tracking object definition. } \examples{ ## example function foo <- function(x){ y <- 0 for(i in 1:100) { y <- y + i } return(y) } ## the name track is necessary track <- tracker() ## initialize the tracker track$init() ## inspect the function ## res is the result of foo res <- inspect(foo(10), track = track) ## get the tracking info resTrack <- track$getTrackInfo() ## create HTML pages printHTML.trackInfo(resTrack) } \keyword{programming} \concept{RUnit} RUnit/man/tracker.Rd0000644000175100001440000000743211274332260014034 0ustar hornikusers%% RUnit : A unit test framework for the R programming language %% Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann %% %% This program is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by %% the Free Software Foundation; version 2 of the License. %% %% This program is distributed in the hope that it will be useful, %% but WITHOUT ANY WARRANTY; without even the implied warranty of %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the %% GNU General Public License for more details. %% %% You should have received a copy of the GNU General Public License %% along with this program; if not, write to the Free Software %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA %% $Id: tracker.Rd,v 1.15 2009/11/04 17:06:56 burgerm Exp $ \encoding{latin1} \name{tracker} \alias{tracker} \title{Tracking the results of the inspect process.} \usage{tracker() } \description{ The current implementation uses the 'closure trick' to hide all details from the user and only allows to retrieve the results of the code inspection. \code{tracker} is used to create a new environment to manage and store the results of the tracking process. The \code{inspect} function requires such an environment with the name "track" (currently mandatory). The tracker records how often each and every function was called by \code{inspect} and summarizes the results of all calls. \code{tracker$init} initializes the tracker environment. \code{tracker$getTrackInfo} returns a list with the tracked results of the inspection process. } \section{Methods}{ \tabular{rll}{ \tab \code{init} \tab initializes the tracker environment\cr \tab \code{addFunc} \tab add function to the inspect tracking list (internal use)\cr \tab \code{getSource} \tab return the modified source code used for during inspection the specified index (internal use)\cr \tab \code{bp} \tab update tracking info for specified function index (internal use)\cr \tab \code{getTrackInfo} \tab return 'trackInfo' object\cr \tab \code{isValid} \tab check 'trackInfo' object for conformance to class contract \cr } } \details{The 'trackInfo' S3 class object (list) has one entry for each function on the inspect list with the following elements: \describe{ \item{src}{The source code of the function.} \item{run}{The number of executions for each line of code.} \item{graph}{A matrix. Each element in the matrix counts how often a code line was called from the previous code line in the execution flow.} \item{nrRuns}{Counts how often the function was called.} \item{funcCall}{The declaration of the function.} } } \author{Thomas \enc{König}{Koenig}, Klaus \enc{Jünemann}{Juenemann} \ifelse{html}{\out{&}}{\&} Matthias Burger} \seealso{ \code{\link{inspect}} for the registration of functions \& methods to be on the tracking list, and \code{\link{printHTML.trackInfo}} for displaying results } \examples{ ## example functions foo <- function(x){ y <- 0 for(i in 1:100) { y <- y + i } return(y) } bar <- function(x){ y <- 0 for(i in 1:100) { y <- y - i } return(y) } ## the object name track is 'fixed' (current implementation) track <- tracker() ## initialize the tracker track$init() ## inspect the function ## resFoo1 will contain the result of calling foo(50) resFoo1 <- inspect(foo(50), track = track) resFoo2 <- inspect(foo(20), track = track) resBar1 <- inspect(bar(30), track = track) ## get the tracked function call info for all inspect calls resTrack <- track$getTrackInfo() ## create HTML sites in folder ./results for all inspect calls printHTML.trackInfo(resTrack) } \keyword{programming} \concept{RUnit} RUnit/tests/0000755000175100001440000000000011444151274012476 5ustar hornikusersRUnit/tests/README0000644000175100001440000000012111274632342013351 0ustar hornikusers unit tests have been moved to inst/unitTests in the source package structure RUnit/R/0000755000175100001440000000000011444151274011535 5ustar hornikusersRUnit/R/00Init.r0000644000175100001440000000315311274617446012776 0ustar hornikusers###################################################################### ## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: 00Init.r,v 1.9 2009/11/05 18:53:26 burgerm Exp $ .onLoad <- function(libname, pkgname) { ##@bdescr ## Internal Function. ## Not to be called by users. ##@edescr ## load required packages errMsg <- paste("\nLoading required package 'methods' failed. RUnit could not be loaded.", "\nCheck your library installation path.\n") require(methods) || stop(errMsg) runitVersion <- packageDescription("RUnit", lib.loc=libname, fields="Version") ## avoid cmd check NOTEs assign(".testLogger", NULL, envir=.GlobalEnv) ## add options to R's global options list .buildRUnitOptions() } .onUnload <- function(libpath) { ## drop RUnit specific options from global options list options("RUnit"=NULL) } RUnit/R/htmlProtocol.r0000644000175100001440000004150311274331543014411 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: htmlProtocol.r,v 1.28 2009/11/04 17:01:23 burgerm Exp $ printHTMLProtocol <- function(testData, fileName = "", separateFailureList = TRUE, traceBackCutOff=9, testFileToLinkMap=function(x) x) { ##@bdescr ## Report generator ## Extracts the log information stored in the 'RUnitTestData' test run object ## and generates a well formated HTML output. ##@edescr ## ##@in testData : [RUnitTestData] S3 class object ##@in fileName : [character] ##@in separateFailureList : [logical] if TRUE (default) add a list of all failures ##@in traceBackCutOff : [integer] number of steps back in the trace back stack to be displayed ##@in testFileToLinkMap : [function] a function transforming the full name of the test file to a link location ##@ret : [logical] TRUE if execution completed w/o error ## ##@codestatus : testing ## -------------------------------- ## CHECK OF INPUT DATA ## -------------------------------- if (!is(testData, "RUnitTestData")) { stop("Argument 'testData' must be of class 'RUnitTestData'.") } if (!is.character(fileName)) { stop("Argument 'fileName' has to be of type character.") } if (length(fileName) != 1) { stop("Argument 'fileName' must contain exactly one element.") } if (!is.logical(separateFailureList)) { stop("Argument 'separateFailureList' has to be of type logical.") } if (length(separateFailureList) != 1) { stop("Argument 'separateFailureList' must contain exactly one element.") } if (!is.numeric(traceBackCutOff)) { stop("Argument 'traceBackCutOff' has to be of type logical.") } if (length(traceBackCutOff) != 1) { stop("Argument 'traceBackCutOff' must contain exactly one element.") } if (traceBackCutOff < 0 || traceBackCutOff > 100) { stop("Argument 'traceBackCutOff' out of valid range [0, 100].") } ## -------------------------------- ## HELPER FUNCTIONS ## -------------------------------- ## get singular or plural right sop <- function(number, word, plext="s") { ifelse(number == 1, paste(number, word), paste(number, paste(word, plext, sep=""))) } pr <- function(...) { writeRaw(paste(...), htmlFile=fileName) writeRaw("
", htmlFile=fileName) } writeP <- function(string, para="") { writeBeginTag("p", para=para, htmlFile=fileName) writeRaw(string, htmlFile=fileName) writeEndTag("p", htmlFile=fileName) writeCR(htmlFile=fileName) } writeLi <- function(..., para="") { writeBeginTag("li", para=para, htmlFile=fileName) writeRaw(paste(...), htmlFile=fileName) writeEndTag("li", htmlFile=fileName) } createTestFuncRef <- function(testSuite, srcFileName, testFuncName, asAnchor=FALSE) { tmp <- paste(testSuite, srcFileName, testFuncName, sep="_") if(asAnchor) { return(paste("#", gsub("/", "_", tmp), sep="")) } else { return(gsub("/", "_", tmp)) } } printTraceBack <- function(traceBack) { if(length(traceBack) > 0) { writeRaw("Call Stack:
", htmlFile=fileName) if(traceBackCutOff > length(testFuncInfo$traceBack)) { writeRaw("(traceBackCutOff argument larger than length of trace back: full trace back printed)
", htmlFile=fileName) writeBeginTag("ol", htmlFile=fileName) for(i in seq_along(traceBack)) { writeBeginTag("li", htmlFile=fileName) writeRaw(traceBack[i], htmlFile=fileName) writeEndTag("li", htmlFile=fileName) } } else { writeBeginTag("ol", htmlFile=fileName) for(i in traceBackCutOff:length(traceBack)) { writeBeginTag("li", htmlFile=fileName) writeRaw(traceBack[i], htmlFile=fileName) writeEndTag("li", htmlFile=fileName) } } writeEndTag("ol", htmlFile=fileName) } } errorStyle <- "color:red" deactivatedStyle <- "color:black" ## -------------------------------------------- ## PART 1: TITLE AND BASIC ERROR INFORMATION ## -------------------------------------------- ## title title <- paste("RUNIT TEST PROTOCOL", date(), sep="--") writeHtmlHeader(title, htmlFile=fileName) writeHtmlSection(title, 1, htmlFile=fileName) if(length(testData) == 0) { writeP(" no test cases :-(") return(invisible(TRUE)) } ## basic Info errInfo <- getErrors(testData) writeP(paste("Number of test functions:", errInfo$nTestFunc)) if(errInfo$nDeactivated > 0) { writeP(paste("Number of deactivated test functions:", errInfo$nDeactivated), para=ifelse(errInfo$nDeactivated == 0, "", paste("style", deactivatedStyle, sep="="))) } writeP(paste("Number of errors:", errInfo$nErr), para=ifelse(errInfo$nErr == 0, "", paste("style", errorStyle, sep="="))) writeP(paste("Number of failures:", errInfo$nFail), para=ifelse(errInfo$nFail == 0, "", paste("style", errorStyle, sep="="))) writeHtmlSep(htmlFile=fileName) ## -------------------------------- ## PART 2: TABLE OF TEST SUITES ## -------------------------------- ## summary of test suites writeHtmlSection(sop(length(testData), "Test suite"), 3, htmlFile=fileName) ## table of test suites if(errInfo$nDeactivated > 0) { writeBeginTable(c("Name", "Test functions", "Deactivated", "Errors", "Failures"), width="80%", htmlFile=fileName, columnWidth=c("20%", "20%", "20%", "20%", "20%")) for(tsName in names(testData)) { rowString <- c(paste("", tsName, "", sep=""), testData[[tsName]]$nTestFunc, testData[[tsName]]$nDeactivated, testData[[tsName]]$nErr, testData[[tsName]]$nFail) rowCols <- c("", "", ifelse(testData[[tsName]]$nDeactivated==0, "", "yellow"), ifelse(testData[[tsName]]$nErr==0, "", "red"), ifelse(testData[[tsName]]$nFail==0, "", "red")) writeTableRow(row=rowString, bgcolor=rowCols, htmlFile=fileName) } writeEndTable(htmlFile=fileName) } else { ## skip 'deactivated' column if no function has been deactivated writeBeginTable(c("Name", "Test functions", "Errors", "Failures"), width="60%", htmlFile=fileName, columnWidth=c("30%", "30%", "20%", "20%")) for(tsName in names(testData)) { rowString <- c(paste("", tsName, "", sep=""), testData[[tsName]]$nTestFunc, testData[[tsName]]$nErr, testData[[tsName]]$nFail) rowCols <- c("", "", ifelse(testData[[tsName]]$nErr==0, "", "red"), ifelse(testData[[tsName]]$nFail==0, "", "red")) writeTableRow(row=rowString, bgcolor=rowCols, htmlFile=fileName) } writeEndTable(htmlFile=fileName) } writeHtmlSep(htmlFile=fileName) ## ------------------------------------------------ ## PART 3: ERROR, FAILURE AND DEACTIVATED TABLES ## ------------------------------------------------- ## error table if(separateFailureList && (errInfo$nErr > 0)) { writeHtmlSection("Errors", 3, htmlFile=fileName) writeBeginTable(c("Test suite : test function", "message"), htmlFile=fileName, columnWidth=c("30%", "70%")) for(tsName in names(testData)) { if(testData[[tsName]]$nErr > 0) { srcFileRes <- testData[[tsName]]$sourceFileResults srcFileNames <- names(srcFileRes) for(i in seq_along(srcFileRes)) { testFuncNames <- names(srcFileRes[[i]]) for(j in seq_along(testFuncNames)) { funcList <- srcFileRes[[i]][[testFuncNames[j]]] if(funcList$kind == "error") { lnk <- paste("", paste(tsName, testFuncNames[j], sep=" : "), "", sep="") writeTableRow(row=c(lnk, funcList$msg), htmlFile=fileName) } } } } } writeEndTable(htmlFile=fileName) writeHtmlSep(htmlFile=fileName) } ## failure table if(separateFailureList && (errInfo$nFail > 0)) { writeHtmlSection("Failures", 3, htmlFile=fileName) writeBeginTable(c("Test suite : test function", "message"), htmlFile=fileName, columnWidth=c("30%", "70%")) for(tsName in names(testData)) { if(testData[[tsName]]$nFail > 0) { srcFileRes <- testData[[tsName]]$sourceFileResults srcFileNames <- names(srcFileRes) for(i in seq_along(srcFileRes)) { testFuncNames <- names(srcFileRes[[i]]) for(j in seq_along(testFuncNames)) { funcList <- srcFileRes[[i]][[testFuncNames[j]]] if(funcList$kind == "failure") { lnk <- paste("", paste(tsName, testFuncNames[j], sep=" : "), "", sep="") writeTableRow(row=c(lnk, funcList$msg), htmlFile=fileName) } } } } } writeEndTable(htmlFile=fileName) writeHtmlSep(htmlFile=fileName) } ## deactivated table if(separateFailureList && (errInfo$nDeactivated > 0)) { writeHtmlSection("Deactivated", 3, htmlFile=fileName) writeBeginTable(c("Test suite : test function", "message"), htmlFile=fileName, columnWidth=c("30%", "70%")) for(tsName in names(testData)) { if(testData[[tsName]]$nDeactivated > 0) { srcFileRes <- testData[[tsName]]$sourceFileResults srcFileNames <- names(srcFileRes) for(i in seq_along(srcFileNames)) { testFuncNames <- names(srcFileRes[[i]]) for(j in seq_along(testFuncNames)) { funcList <- srcFileRes[[i]][[testFuncNames[j]]] if(funcList$kind == "deactivated") { lnk <- paste("", paste(tsName, testFuncNames[j], sep=" : "), "", sep="") writeTableRow(row=c(lnk, funcList$msg), htmlFile=fileName) } } } } } writeEndTable(htmlFile=fileName) writeHtmlSep(htmlFile=fileName) } ## -------------------------------- ## PART 4: DETAILS ## -------------------------------- writeHtmlSection("Details", 3, htmlFile=fileName) ## loop over all test suites for(tsName in names(testData)) { tsList <- testData[[tsName]] writeBeginTag("p", htmlFile=fileName) writeBeginTag("a", para=paste("name=\"", tsName, "\"", sep=""), htmlFile=fileName) writeHtmlSection(paste("Test Suite:", tsName), 5, htmlFile=fileName) writeEndTag("a", htmlFile=fileName) pr("Test function regexp:", tsList$testFuncRegexp) pr("Test file regexp:", tsList$testFileRegexp) if(length(tsList$dirs) == 0) { pr("No directories !") } else { if(length(tsList$dirs) == 1) { pr("Involved directory:") } else { pr("Involved directories:") } for(dir in tsList$dirs) { pr(dir) } res <- tsList$sourceFileResults testFileNames <- names(res) if(length(res) == 0) { pr(" no test files") } else { ## loop over all source files writeBeginTag("ul", htmlFile=fileName) for(testFileName in testFileNames) { testFuncNames <- names(res[[testFileName]]) if(length(testFuncNames) > 0) { writeBeginTag("li", htmlFile=fileName) writeLink(target=testFileToLinkMap(testFileName), name=paste("Test file:", basename(testFileName)), htmlFile=fileName) ## loop over all test functions in the test file writeBeginTag("ul", htmlFile=fileName) for(testFuncName in testFuncNames) { writeBeginTag("li", htmlFile=fileName) testFuncInfo <- res[[testFileName]][[testFuncName]] anchorName <- createTestFuncRef(tsName, testFileName, testFuncName) writeBeginTag("a", para=paste("name=\"", anchorName, "\"", sep=""), htmlFile=fileName) if(testFuncInfo$kind == "success") { pr(paste(testFuncName, ": (",testFuncInfo$checkNum, " checks) ... OK (", testFuncInfo$time, " seconds)", sep="")) writeEndTag("a", htmlFile=fileName) } else { if(testFuncInfo$kind == "error") { writeBeginTag("u", para=paste("style", errorStyle, sep="="), htmlFile=fileName) writeRaw(paste(testFuncName, ": ERROR !! ", sep=""), htmlFile=fileName) writeEndTag("u", htmlFile=fileName) writeEndTag("a", htmlFile=fileName) } else if (testFuncInfo$kind == "failure") { writeBeginTag("u", para=paste("style", errorStyle, sep="="), htmlFile=fileName) writeRaw(paste(testFuncName, ": FAILURE !! (check number ", testFuncInfo$checkNum, ") ", sep=""), htmlFile=fileName) writeEndTag("u", htmlFile=fileName) writeEndTag("a", htmlFile=fileName) } else if (testFuncInfo$kind == "deactivated") { writeBeginTag("u", para=paste("style", deactivatedStyle, sep="="), htmlFile=fileName) writeRaw(paste(testFuncName, ": DEACTIVATED, ", sep=""), htmlFile=fileName) writeEndTag("a", htmlFile=fileName) } else { writeLi(paste(testFuncName, ": unknown error kind", sep="")) writeEndTag("a", htmlFile=fileName) } pr(testFuncInfo$msg) printTraceBack(testFuncInfo$traceBack) } writeEndTag("li", htmlFile=fileName) } writeEndTag("ul", htmlFile=fileName) } writeEndTag("li", htmlFile=fileName) } writeEndTag("ul", htmlFile=fileName) } } writeHtmlSep(htmlFile=fileName) } ver <- cbind(unlist(version)) ## add host name ver <- rbind(ver, Sys.info()["nodename"]) rownames(ver)[dim(ver)[1]] <- "host" colnames(ver) <- "Value" ## compiler used (under *nix) rhome <- Sys.getenv("R_HOME") ## on Windows Makeconf does not exist ## other than that we have no indication which compiler ## would be used for R CMD INSTALL so we report NA gccVersion <- as.character(NA) makeconfFile <- file.path(rhome, "etc", "Makeconf") if (file.exists(makeconfFile) && identical(.Platform$OS.type, "unix")) { gccVersion <- system(paste("cat ", makeconfFile," | grep \"^CXX =\" "), intern=TRUE) gccVersion <- sub("^CXX[ ]* =[ ]*", "", gccVersion) } ver <- rbind(ver, gccVersion) rownames(ver)[dim(ver)[1]] <- "compiler" writeHtmlTable(ver, htmlFile=fileName, border=0, width="80%", append=TRUE) ## finish html document writeHtmlEnd(htmlFile=fileName) return(invisible(TRUE)) } RUnit/R/runit.r0000644000175100001440000003500011444146175013063 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: runit.r,v 1.34 2010/09/15 13:39:09 burgerm Exp $ defineTestSuite <- function(name, dirs, testFileRegexp="^runit.+\\.[rR]$", testFuncRegexp="^test.+", rngKind="Marsaglia-Multicarry", rngNormalKind="Kinderman-Ramage") { ##@bdescr ## Convenience functions to handle test suites ##@edescr ## ##@in name : [character] test suite title used in protocol ##@in dirs : [character] vector of paths to search for test case files ##@in testFileRegexp : [character] regular expression string to match file names ##@in testFuncRegexp : [character] (vector) regular expression string(s) to match test case functions within all test case files ##@in rngKind : [character] name of the RNG version, see RNGversion() ##@in rngNormalKind : [character] name of the RNG version for the rnorm, see RNGversion() ##@ret : [RUnitTestSuite] S3 class (list) object, ready for test runner ## ##@codestatus : testing if (missing(dirs)) { stop("argument 'dirs' is missing without a default.") } if (missing(name)) { warning("argument 'name' is missing. using basename(dirs)[1] instead.") name <- basename(dirs)[1] } ret <- list(name=name, dirs=dirs, testFileRegexp=testFileRegexp, testFuncRegexp=testFuncRegexp, rngKind=rngKind, rngNormalKind=rngNormalKind) class(ret) <- "RUnitTestSuite" return(invisible(ret)) } isValidTestSuite <- function(testSuite) { ##@bdescr ## Helper function ## checks 'RUnitTestSuite' class object features ##@edescr ## ##@in testSuite : [RUnitTestSuite] S3 class (list) object, input object for test runner ##@ret : [logical] TRUE if testSuite is valid ## ##@codestatus : testing if(!is(testSuite, "RUnitTestSuite")) { warning(paste("'testSuite' object is not of class 'RUnitTestSuite'.")) return(FALSE) } ## check required elements, irrespective of order, allow for additional elements requiredNames <- c("name", "dirs", "testFileRegexp", "testFuncRegexp", "rngKind", "rngNormalKind") if(!all(requiredNames %in% names(testSuite))) { warning("'testSuite' object does not conform to S3 class definition. Not all list elements present.") return(FALSE) } for(i in seq_along(testSuite)) { if(!is.character(testSuite[[i]])) { warning(paste("'testSuite' object does not conform to S3 class definition.\n", "'", names(testSuite)[i],"' element has to be of type 'character'.", sep="")) return(FALSE) } if(any(testSuite[[i]] == "")) { warning(paste("'testSuite' object does not conform to S3 class definition.\n", "'",names(testSuite)[i],"' element may not contain empty string.", sep="")) return(FALSE) } } notFound <- !file.exists(testSuite[["dirs"]]) if (any(notFound)) { warning(paste("specified directory", paste(testSuite[["dirs"]][notFound], collapse=", "), "not found.")) return(FALSE) } if (length(testSuite[["name"]]) != 1) { warning(paste("'name' element may only contain exactly one name.")) return(FALSE) } if (length(testSuite[["testFileRegexp"]]) != 1) { warning(paste("'testFileRegexp' element may only contain exactly one string.")) return(FALSE) } if (length(testSuite[["testFuncRegexp"]]) != 1) { warning(paste("'testFuncRegexp' element may only contain exactly one string.")) return(FALSE) } ## RNGkind has an internal list of valid names which cannot be accessed ## programmatically. Furthermore, users can define their own RNG and select that one ## so we have to leave it to RNGkind() to check if the arguments are valid. if (length(testSuite[["rngKind"]]) != 1) { warning(paste("'rngKind' element may only contain exactly one name.")) return(FALSE) } if (length(testSuite[["rngNormalKind"]]) != 1) { warning(paste("'rngNormalKind' element may only contain exactly one name.")) return(FALSE) } return(TRUE) } .setUp <- function() { ##@bdescr ## Internal Function. ## Default function to be executed once for each test case before the test case gets executed. ## This function can be adopted to specific package requirements for a given project. ## Need to replace this default with a new function definition. ## Function cannot take arguments and does not have a return value. ##@edescr ## ##@codestatus : internal return(invisible()) } .tearDown <- function() { ##@bdescr ## Internal Function. ## Default function to be executed once for each test case after the test case got executed. ## This function can be adopted to specific package requirements for a given project. ## Need to replace this default with a new function definition. ## Function cannot take arguments and does not have a return value. ##@edescr ## ##@codestatus : internal return(invisible()) } .executeTestCase <- function(funcName, envir, setUpFunc, tearDownFunc) { ##@bdescr ## Internal Function. ## Execute individual test case, record logs and change state of global TestLogger object. ##@edescr ## ##@in funcName : [character] name of test case function ##@in envir : [environment] ##@in setUpFunc : [function] ##@in tearDownFunc : [function] ##@ret : [NULL] ## ##@codestatus : internal ## write to stdout for logging func <- get(funcName, envir=envir) ## anything else than a function is ignored. if(mode(func) != "function") { return(invisible()) } if (.testLogger$getVerbosity() > 0) { cat("\n\nExecuting test function", funcName, " ... ") } ## safe execution of setup function res <- try(setUpFunc()) if (inherits(res, "try-error")) { message <- paste("Error executing .setUp before",funcName, ":", geterrmessage()) .testLogger$addError(testFuncName=paste(".setUp (before ", funcName, ")", sep=""), errorMsg=message) return(invisible()) } ## reset book keeping variables in .testLogger .testLogger$cleanup() ## ordinary test function execution: timing <- try(system.time(func())) if (inherits(timing, "try-error")) { if(.testLogger$isFailure()) { .testLogger$addFailure(testFuncName=funcName, failureMsg=geterrmessage()) } else if(.testLogger$isDeactivated()) { .testLogger$addDeactivated(testFuncName=funcName) } else { .testLogger$addError(testFuncName=funcName, errorMsg=geterrmessage()) } } else { .testLogger$addSuccess(testFuncName=funcName, secs=round(timing[3], 2)) } ## add number of check function calls within test case .testLogger$addCheckNum(testFuncName=funcName) ## safe execution of tearDown function res <- try(tearDownFunc()) if (inherits(res, "try-error")) { message <- paste("Error executing .tearDown after",funcName, ":", geterrmessage()) .testLogger$addError(testFuncName=paste(".tearDown (after ", funcName, ")", sep=""), errorMsg=message) return(invisible()) } if (.testLogger$getVerbosity() > 0) { cat(" done successfully.\n\n") } return(invisible()) } .sourceTestFile <- function(absTestFileName, testFuncRegexp) { ##@bdescr ## This function sources a file, finds all the test functions in it, executes them ## and reports the results to the TestLogger. ## No return value, called for its side effects on TestLogger object ##@edescr ## ##@in absTestFileName : [character] absolute path name of the file to test ##@in testFuncRegexp : [character] a regular expression identifying the names of test functions ##@ret : [NULL] ## ##@codestatus : internal .testLogger$setCurrentSourceFile(absTestFileName) if (!file.exists(absTestFileName)) { msgText <- paste("Test case file ", absTestFileName," not found.") .testLogger$addError(testFuncName=absTestFileName, errorMsg=msgText) return(invisible()) } sandbox <- new.env(parent=.GlobalEnv) ## will be destroyed after function closure is left ## catch syntax errors in test case file res <- try(sys.source(absTestFileName, envir=sandbox)) if (inherits(res, "try-error")) { message <- paste("Error while sourcing ",absTestFileName,":",geterrmessage()) .testLogger$addError(testFuncName=absTestFileName, errorMsg=message) return(invisible()) } ## test file provides definition of .setUp/.tearDown if (exists(".setUp", envir=sandbox, inherits=FALSE)) { .setUp <- get(".setUp", envir=sandbox) } if (exists(".tearDown", envir=sandbox, inherits=FALSE)) { .tearDown <- get(".tearDown", envir=sandbox) } testFunctions <- ls(pattern=testFuncRegexp, envir=sandbox) for (funcName in testFunctions) { .executeTestCase(funcName, envir=sandbox, setUpFunc=.setUp, tearDownFunc=.tearDown) } } runTestSuite <- function(testSuites, useOwnErrorHandler=TRUE, verbose=getOption("RUnit")$verbose) { ##@bdescr ## This is the main function of the RUnit framework. It identifies all specified ## test files and triggers all required actions. At the end it creates a test ## protocol data object. ## IMPORTANT to note, the random number generator is (re-)set to the default ## methods specified in defineTestSuite() before each new test case *file* is sourced. ## This guarantees that each new test case set defined together in on file can rely ## on the default, even if the random number generator version is being reconfigured in some ## previous test case file(s). ##@edescr ## ##@in testSuites : [list] list of test suite lists ##@in useOwnErrorHandler : [logical] TRUE (default) : use the RUnit error handler ##@in verbose : [integer] >= 1: (default) write begin/end comments for each test case, 0: omit begin/end comment ##@ret : [list] 'RUnitTestData' S3 class object ## ##@codestatus : testing ## preconditions if (!is.logical(useOwnErrorHandler)) { stop("argument 'useOwnErrorHandler' has to be of type logical.") } if (length(useOwnErrorHandler) != 1) { stop("argument 'useOwnErrorHandler' has to be of length 1.") } if (is.na(useOwnErrorHandler)) { stop("argument 'useOwnErrorHandler' may not contain NA.") } oFile <- getOption("RUnit")$outfile if (!is.null(oFile)) { if(is.character(oFile)) { ## connection has to be open when handed on to sink oFile <- file(oFile, "w") } else if(!inherits(oFile, "connection")) { stop("'outfile' must be a connection or a character string.") } sink(file=oFile) sink(file=oFile, type="message") resetStream <- function() { sink(type="message") sink() flush(oFile) close(oFile) ##close(oFile) } on.exit(resetStream()) } ## record RNGkind and reinstantiate on exit rngDefault <- RNGkind() on.exit(RNGkind(kind=rngDefault[1], normal.kind=rngDefault[2]), add=TRUE) oldErrorHandler <- getOption("error") ## reinstall error handler on.exit(options(error=oldErrorHandler), add=TRUE) ## initialize TestLogger assign(".testLogger", .newTestLogger(useOwnErrorHandler), envir=.GlobalEnv) .testLogger$setVerbosity(verbose) ## main loop if (isValidTestSuite(testSuites)) { testSuites <- list(testSuites) } else if (isValidTestSuite(testSuites[[1]])) { ## do nothing } else { stop("invalid test suite supplied.") } for (i in seq_along(testSuites)) { testSuite <- testSuites[[i]] if(!isValidTestSuite(testSuite)) { errMsg <- paste("Invalid test suite",testSuite$name,". Test run aborted.") stop(errMsg) } .testLogger$setCurrentTestSuite(testSuite) testFiles <- list.files(testSuite$dirs, pattern = testSuite$testFileRegexp, full.names=TRUE) for(testFile in testFiles) { ## set a standard random number generator. RNGkind(kind=testSuite$rngKind, normal.kind=testSuite$rngNormalKind) .sourceTestFile(testFile, testSuite$testFuncRegexp) } } ret <- .testLogger$getTestData() return(ret) } runTestFile <- function(absFileName, useOwnErrorHandler=TRUE, testFuncRegexp="^test.+", rngKind="Marsaglia-Multicarry", rngNormalKind="Kinderman-Ramage", verbose=getOption("RUnit")$verbose) { ##@bdescr ## Convenience function. ##@edescr ## ##@in absFileName : [character] complete file name of test cases code file ##@in useOwnErrorHandler : [logical] if TRUE RUnits error handler will be used ##@in testFuncRegexp : [character] ##@in rngKind : [character] name of the RNG, see RNGkind for avialbale options ##@in rngNormalKind : [character] name of the RNG for rnorm, see RNGkind for avialbale options ##@in verbose : [integer] >= 1: (default) write begin/end comments for each test case, 0: ommit begin/end comment (passed on to function runTestSuite) ##@ret : [list] 'RUnitTestData' S3 class object ## ##@codestatus : testing ## preconditions ## all error checking and handling is delegated to function runTestSuite fn <- basename(absFileName) nn <- strsplit(fn, "\\.")[[1]][1] dn <- dirname(absFileName) ts <- defineTestSuite(name=nn, dirs=dn, testFileRegexp=paste("^", fn, "$", sep=""), testFuncRegexp=testFuncRegexp, rngKind=rngKind, rngNormalKind=rngNormalKind) return(runTestSuite(ts, useOwnErrorHandler=useOwnErrorHandler, verbose=verbose)) } RUnit/R/inspector.r0000644000175100001440000003537711173620300013733 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: inspector.r,v 1.12 2009/04/22 13:50:56 burgerm Exp $ includeTracker <- function(fbody, track=track) { ##@bdescr ## Internal function ## ##@edescr ## ##@in fbody : [character] vector of code lines of function to track ##@in track : [trackInfo] list ##@ret : [list] with elements list(modFunc=c(sig,newBody),newSource = newCode) ## ##@codestatus : internal ## get the signature sig <- fbody[1] ## get the block structure (important for if, for, while, else with one line) block <- sapply(fbody[-1],function(x) regexpr("[^ ]",x)[1], USE.NAMES=FALSE) ## vector of keywords kwOpen <- c("for","while","repeat","if","else") ## keyword at begin kwGrep <- paste("(",paste(kwOpen,sep="",collapse="|"),")",sep="") oneLiner <- function(code) { ##@bdescr ## utility ## search a character vector ie. the vector of lines of a function body ## for block structures e.g. for|while|repeat|if|else { } code block ##@edescr ## ##@in code : [character] vector of function body code lines ##@ret : [logical] vector of length of code, indication which are one line control blocks ## ##@codestatus : internal return(sapply(code, function(line) { opBr <- grep(paste("^[ ]*",kwGrep,".*[ ]+$",sep=""), line) ## special case if combined with assignment or math operators opBr2 <- grep(paste("(<-|=|\\+|\\-|\\*|\\/)[ ]*if[ ]*\\(",sep=""), line) if(length(opBr) > 0 || length(opBr2) > 0) { return(TRUE) } return(FALSE) }, USE.NAMES=FALSE)) } ## set Brackets setBrackets <- function(potLine,block,env) { ##@bdescr ## ##@edescr ## ##@in potLine : [logical] mask vector which line contains a one-line control construct ##@in block : [integer] vector ##@in env : [logical] mask vector: which line already contains a opening brace ##@ret : [list] with matching element vectors: openBr & clodeBr ## ##@codestatus : internal oBr <- character(length(potLine)) clBr <- character(length(potLine)) lineIdx <- 1L while(lineIdx < length(potLine)) { if(potLine[lineIdx] && !(potLine[lineIdx+1])) { oBr[lineIdx] <- "{" if (!env[lineIdx+1]) { clBr[lineIdx+2] <- paste(clBr[lineIdx+2],"}") } else { bbl <- block[lineIdx] endBlockIdx <- min(which((bbl >= block) & (seq_along(block) > lineIdx))) clBr[endBlockIdx] <- paste(clBr[endBlockIdx],"}") } } else if(potLine[lineIdx] && (potLine[lineIdx+1]) ) { oBr[lineIdx] <- "{" bbl <- block[lineIdx] endBlockIdx <- min(which((bbl >= block) & (seq_along(block) > lineIdx))) clBr[endBlockIdx] <- paste(clBr[endBlockIdx],"}") } lineIdx <- lineIdx + 1L } return(list(openBr=oBr, closeBr=clBr)) } ## check for new environments env <- sapply(fbody[-1], function(code) { envIdx <- grep("\\{$",code) if(length(envIdx) > 0) { return(TRUE) } return(FALSE) },USE.NAMES=FALSE) ## check the block structure block <- sapply(fbody[-1], function(x) regexpr("[^ ]",x)[1], USE.NAMES=FALSE) ## is 4 a convention or a rule? block <- (block %/% 4) + 1 ## check for if's, while's, etc. ol <- oneLiner(fbody[-1]) ## create brackets for control structures without new environments br <- setBrackets(ol,block,env) ## create new Code newCode <- paste(as.vector(rbind(br$closeBr,fbody[-1],br$openBr))) newCode <- newCode[newCode != ""] ## include the breakpoint function bpVec <- sapply(newCode, function(line) { nobp <- grep("^[ ]*(else |\\{|\\})",line) if(length(nobp) == 0) { return("track$bp();") } return("") },USE.NAMES=FALSE) for(i in seq_along(bpVec)) { bpVec[i] <- gsub("\\(\\)",paste("(",i,")",sep=""),bpVec[i]) } ## create the mainpulated body of the function newBody <- paste(bpVec,newCode) ## return signature and body return(list(modFunc=c(sig,newBody), newSource=newCode)) } tracker <- function() { ##@bdescr ## initialization of the central tracking object ## which stores all information related to inspection results and code execution structure ## defines accessor functions ## - addFunc (fId,src,callExpr): add specified function to the track list ## - getSource(nr): get the source code (character) for function nr on track list ## - init ## - bp ## - getTrackInfo ## - isValidTrackInfo ##@edescr ## ##@ret : [list] OO object with functions addFunc, getSourcee, init, bp, getTrackInfo ## ##@codestatus : testing ## object for information trackInfo <- list() class(trackInfo) <- "trackInfo" ## current function index fIdx <- 0 ## old time oldTime <- NULL ## old src line oldSrcLine <- 0 addFunc <- function(fId,src,callExpr) { ##@bdescr ## ## accessor function ##@edescr ## ##@in fId : [character] function name ##@in src : [character] source code character vector ##@in callExpr : [character] function call ##@ret : [NULL] returns invisible, used for its side effects ## ## codestatus : internal ## preconditions if( length(fId) != 1) { stop("fId must be one character string: function name") } isThere <- which(fId == names(trackInfo)) if(length(isThere) == 1) { ## already in tracking list fIdx <<- isThere } else { fIdx <<- fIdx + 1 newFuncInfo <- list(src=src, run=integer(length(src)), time=numeric(length(src)), graph=matrix(0,nrow=length(src),ncol=length(src)), nrRuns=as.integer(0), funcCall=callExpr) ## append strips class attribute trackInfo <- append(trackInfo,list(newFuncInfo)) names(trackInfo)[fIdx] <- fId class(trackInfo) <- "trackInfo" ## update global state trackInfo <<- trackInfo } ## increment run number trackInfo[[fIdx]]$nrRuns <<- trackInfo[[fIdx]]$nrRuns + 1 ## initialize local variables oldSrcLine <<- 0 oldTime <<- NULL return(invisible()) } getTrackInfo <- function() { ##@bdescr ## ## accessor function ## returns the main inspection result list with ## elements ## - src ## - run ## - time ## - graph ## - nrRuns ## - funCall ##@edescr ## ##@ret : [trackInfo] S3 class list (see description above) ## ## codestatus : internal return(trackInfo) } init <- function() { ##@bdescr ## ## initalisation function ## sets/resets variables run and fIdx ##@edescr ## ##@ret : [NULL] returns invisible, used for its side effects ## ## codestatus : internal trackInfoInit <- list() class(trackInfoInit) <- "trackInfo" trackInfo <<- trackInfoInit fIdx <<- 0L return(invisible()) } bp <- function(nr) { ##@bdescr ## ## accessor function ##@edescr ## ##@in : [integer] index, function run number ##@ret : [NULL] returns invisible, used for its side effects ## ## codestatus : internal ## preconditions if (length(nr) != 1) { stop("argument 'nr' has to be of length 1.") } if (is.na(nr)) { stop("argument 'nr' may not contain missing value (NA).") } trackInfo[[fIdx]]$run[nr] <<- trackInfo[[fIdx]]$run[nr] + 1 ## cumulative processing time if(!is.null(oldTime)) { dtime <- proc.time()[1] - oldTime trackInfo[[fIdx]]$time[nr] <<- trackInfo[[fIdx]]$time[nr] + dtime } oldTime <<- proc.time()[1] ## graph if(oldSrcLine != 0) { trackInfo[[fIdx]]$graph[oldSrcLine,nr] <<- trackInfo[[fIdx]]$graph[oldSrcLine,nr] + 1 } ## store the old line oldSrcLine <<- nr return(invisible()) } getSource <- function(nr) { ##@bdescr ## ## accessor function ## returns the source code as character string ##@edescr ## ##@in : [integer] index, function run number ##@ret : [character] string, source code ## ##@codestatus : untested ## preconditions if (length(nr) != 1) { stop("argument 'nr' has to be of length 1.") } if (is.na(nr)) { stop("argument 'nr' may not contain missing value (NA).") } return(trackInfo[[nr]]$src) } isValidTrackInfo <- function(trackInfo) { ##@bdescr ## test function ## returns TRUE iff trackInfo object fullfils S3 class definition constraints ## - S3 class 'trackInfo' ## - with elements ## - src [character] vector of function source code lines ## - run [integer] vector of no. of times this function was called ## - time [numeric] vector of function execution times in seconds per call ## - graph [matrix] connection matrix (# code linbes x # of execution calls) ## - nrRuns [integer] ## - funcCall [character] function call ##@edescr ## ##@in : [trackInfo] S3 class object ##@ret : [logical] TRUE, iff object fullfils class definition constraints ## ##@codestatus : untested if (!is(trackInfo,"trackInfo")) { return(FALSE) } checkElements <- function(x) { if (!all(c("src", "run", "time", "graph", "nrRuns", "funcCall") %in% names(x))) { return(FALSE) } if (length(x[["run"]]) < 1 || any(is.na(x[["run"]])) || any(x[["run"]] < 0)) { return(FALSE) } if (length(x[["time"]]) < 1 || any(is.na(x[["time"]])) || any(x[["time"]] < 0)) { return(FALSE) } ## TODO: graph if (length(x[["nrRuns"]]) != 1 || is.na(x[["nrRuns"]]) || x[["nrRuns"]] < 0) { return(FALSE) } if (length(x[["funcCall"]]) != 1 || is.na(x[["funcCall"]])) { return(FALSE) } } ok <- sapply(trackInfo, checkElements) if (!all(ok)) { return(FALSE) } return(TRUE) } return(list(addFunc=addFunc, getSource=getSource, init=init, bp=bp, getTrackInfo=getTrackInfo, isValid=isValidTrackInfo)) } inspect <- function(expr, track=track) { ##@bdescr ## inspector function ## an attempt is made to parse the expression or function ## insert track info statements to be used for subsequent ## code execution structure displays ## ## can handle functions aswell as generics ##@edescr ## ##@in expr : [call] ##@in track : [list] tracker object ##@ret : [expression|ANY] either the unevaluated expression of the function or the result of the function call ## ##@codestatus : testing ## get the call and its parameters fCall <- as.character(substitute(expr)) ## get the original call callExpr <- deparse(substitute(expr)) ## get the name of the function fname <- fCall[1] ## check for generic function if(isGeneric(fname)) { ## get type of arguments selType <- sapply(fCall[-1], function(x) { if(exists(x, envir=sys.parent(sys.parent()))) { varSig <- is(get(x,envir=sys.parent(sys.parent())))[1] } else { varSig <- is(eval(parse(text=x)))[1] } return(varSig) },USE.NAMES=FALSE) ## we have to check for missing arguments formalArg <- names(formals(getGeneric(fCall[1]))) ## number of missing arguments nrMissing <- length(formalArg) - length(selType) if(nrMissing > 0) { ## check for ... ellipseIdx <- which(formalArg == "...") if(length(ellipseIdx) != 0) { selType <- c(selType,rep("missing",nrMissing -1 )) } else { selType <- c(selType,rep("missing",nrMissing)) } } ## select function selFunc <- selectMethod(fname, selType) ## deparse the function fbody <- deparse(selFunc@.Data, width.cutoff=500) ## create an identifier for the generic function fNameId <- paste("S4",fname,paste(selFunc@defined@.Data, collapse="/"), sep="/") } else { ## deparse the function fbody <- try(deparse(get(fname), width.cutoff=500), silent=TRUE) if (inherits(fbody, "try-error")) { ## in case the function is defined ## in the test case file fbody <- try(deparse(get(fname, envir=sys.parent()), width.cutoff=500)) if (inherits(fbody, "try-error")) { stop("function not found.") } } ## create an identifier for the generic function fNameId <- paste("R/",fname,sep="") } ## generate the new body of the function newFunc <- includeTracker(fbody, track=track) track$addFunc(fNameId, newFunc$newSource, callExpr) ## build the test function eval(parse(text=c("testFunc <- ",newFunc$modFunc)),envir=sys.frame()) ## create function call newFunCall <- paste("testFunc(",paste(fCall[-1], collapse=","), ")",sep="") parsedFunc <- try(parse(text=newFunCall)) ## check for an error if(!inherits(parsedFunc,"try-error")) { ## call the new function res <- eval(parsedFunc, envir=parent.frame()) } else { ## no parsing possible ## simple call without tracking res <- expr } ## do here some error checking return(res) } RUnit/R/checkFuncs.r0000644000175100001440000001704411274620064014001 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: checkFuncs.r,v 1.24 2009/11/05 18:57:56 burgerm Exp $ checkEquals <- function(target, current, msg="", tolerance = .Machine$double.eps^0.5, checkNames=TRUE, ...) { ##@bdescr ## checks if two objects are equal, thin wrapper around 'all.equal' ## with tolerance one can adjust to and allow for numerical imprecision ##@edescr ##@in target : [ANY] one thing to be compared ##@in current : [ANY] second object to be compared ##@in msg : [character] an optional message to further identify and document the call ##@in tolerance : [numeric] directly passed to 'all.equal', see there for further documentation ##@in checkNames: [logical] iff TRUE do not strip names attributes from current and target prior to the comparison ##@ret : [logical] TRUE iff check was correct ## ##@codestatus : testing if (missing(current)) { stop("argument 'current' is missing") } if(!is.numeric(tolerance)) { stop("'tolerance' has to be a numeric value") } if (length(tolerance) != 1) { stop("'tolerance' has to be a scalar") } if(!is.logical(checkNames)) { stop("'checkNames' has to be a logical value") } if (length(checkNames) != 1) { stop("'checkNames' has to be a scalar") } if(.existsTestLogger()) { .testLogger$incrementCheckNum() } if (!identical(TRUE, checkNames)) { names(target) <- NULL names(current) <- NULL } result <- all.equal(target, current, tolerance=tolerance, ...) if (!identical(result, TRUE)) { if(.existsTestLogger()) { .testLogger$setFailure() } stop(paste(result, collapse="\n"), msg) } else { return(TRUE) } } checkEqualsNumeric <- function(target, current, msg="", tolerance = .Machine$double.eps^0.5, ...) { ##@bdescr ## checks if two objects are equal, thin wrapper around 'all.equal.numeric' ## with tolerance one can adjust to and allow for numerical imprecision. ## current and target are converted via as.vector() thereby stripping all attributes. ##@edescr ##@in target : [ANY] one thing to be compared ##@in current : [ANY] second object to be compared ##@in tolerance : [numeric] directly passed to 'all.equal.numeric', see there for further documentation ##@in msg : [character] an optional message to further identify and document the call ## ##@ret : [logical] TRUE, if objects 'target' and 'current' are equal w.r.t. specified numerical tolerance, else a stop signal is issued ## ##@codestatus : testing if (missing(current)) { stop("argument 'current' is missing") } if(!is.numeric(tolerance)) { stop("'tolerance' has to be a numeric value") } if (length(tolerance) != 1) { stop("'tolerance' has to be a scalar") } if(.existsTestLogger()) { .testLogger$incrementCheckNum() } ## R 2.3.0: changed behaviour of all.equal ## strip attributes before comparing current and target result <- all.equal.numeric(as.vector(target), as.vector(current), tolerance=tolerance, ...) if (!identical(result, TRUE)) { if(.existsTestLogger()) { .testLogger$setFailure() } stop(paste(result, collapse="\n"), msg) } else { return(TRUE) } } checkIdentical <- function(target, current, msg="") { ##@bdescr ## checks if two objects are exactly identical, thin convenience wrapper around 'identical' ## ##@edescr ##@in target : [ANY] one object to be compared ##@in current : [ANY] second object to be compared ##@in msg : [character] an optional message to further identify and document the call ## ##@ret : [logical] TRUE, if objects 'target' and 'current' are identical ## ##@codestatus : testing if (missing(current)) { stop("argument 'current' is missing") } if(.existsTestLogger()) { .testLogger$incrementCheckNum() } result <- identical(target, current) if (!identical(TRUE, result)) { if(.existsTestLogger()) { .testLogger$setFailure() } stop(paste(paste(result, collapse="\n"), msg)) } else { return(TRUE) } } checkTrue <- function(expr, msg="") { ##@bdescr ## checks whether or not something is true ##@edescr ##@in expr : [expression] the logical expression to be checked to be TRUE ##@in msg : [character] optional message to further identify and document the call ## ##@ret : [logical] TRUE, if the expression in a evaluates to TRUE, else a stop signal is issued ## ##@codestatus : testing if (missing(expr)) { stop("'expr' is missing") } if(.existsTestLogger()) { .testLogger$incrementCheckNum() } ## allow named logical argument 'expr' result <- eval(expr) names(result) <- NULL if (!identical(result, TRUE)) { if(.existsTestLogger()) { .testLogger$setFailure() } stop("Test not TRUE\n", msg) } else { return(TRUE) } } checkException <- function(expr, msg="", silent=getOption("RUnit")$silent) { ##@bdescr ## checks if a function call creates an error. The passed function must be parameterless. ## If you want to check a function with arguments, call it like this: ## 'checkException(function() func(args...))' ## ## adding argument silent was suggested by Seth Falcon ## who provided a patch. ##@edescr ##@in expr : [parameterless function] the function to be checked ##@in msg : [character] an optional message to further identify and document the call ##@in silent : [logical] passed on to try, iff TRUE error messages will be suppressed ## ##@ret : [logical] TRUE, if evaluation of the expression results in a 'try-error', else a stop signal is issued ## ##@codestatus : testing if (missing(expr)) { stop("'expr' is missing") } if(is.null(silent)) { silent <- FALSE warning("'silent' has to be of type 'logical'. Was NULL. Set to FALSE.") } if(.existsTestLogger()) { .testLogger$incrementCheckNum() } if (!inherits(try(eval(expr, envir=parent.frame()), silent=silent), "try-error")) { if(.existsTestLogger()) { .testLogger$setFailure() } stop("Error not generated as expected\n", msg) } else { return(TRUE) } } DEACTIVATED <- function(msg="") { ##@bdescr ## Convenience function, for maintaining test suites. ## If placed in an existing test case call ## the test will be executed normally until occurrence of the call ## after which execution will leave the test case (so all code will ## be checked and errors or failures reported as usual). ## An entry for a separate table in the log will be added ## for this test case. ## ##@edescr ##@in msg : [character] optional message to further identify and document the call ## ##@codestatus : testing if(.existsTestLogger()) { .testLogger$setDeactivated(paste(msg, "\n", sep="")) } stop(msg) } RUnit/R/exportHTML.r0000644000175100001440000002316011444146020013721 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2010 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: exportHTML.r,v 1.12 2010/09/15 13:37:20 burgerm Exp $ plotConnection.trackInfo <- function(con, pngfile, ...) { ##@bdescr ## create a plot displaying the execution flow as a graph ##@edescr ## ##@in con : [matrix] counts of execution calls for previous functions ##@in pngfile : [character] string specifying the full path & file name of the ## plot file (PNG) to be generate ##@ret : [NULL] used for its side effect ## ##@codestatus : testing stopifnot(require(graphics)) ## experimental 2nd order connections ## color for arrows color <- c("black","lightgreen","green","lightblue","blue","orangered","red") ## create nothing if if(all(con==0)) { ## open png device grDevices::png(filename=pngfile,width=1024,height=960) plot(1:10,axes=FALSE,xlab="",ylab="",main="",type="n") text(5,5,labels="No connection graph available") grDevices::dev.off() return(invisible()) } ## overall connections allCon <- sum(con) ## connections with percent con <- ceiling(con/sum(con)*100) ## normalize for colors con <- (con + 14) %/% 15 ## open png device grDevices::png(filename=pngfile,width=1024,height=960) ## basic plot plot(x=1:nrow(con), y=1:nrow(con), type="n",axes=FALSE,ylab="# line",xlab="", ylim=c(nrow(con),1)) ## draw text lines text(x=1, y=1:nrow(con), labels=1:nrow(con)) ## offset, to avoid complete overlay offset <- rep(3,length.out=nrow(con)) ## minimal x xmin <- 2 ## check all connections for(i in 1:nrow(con)) { for(j in 1:ncol(con)) { ## check for an existing connection if(con[i,j] != 0) { colDraw <- color[con[i,j]] from <- j to <- i ## circular if(from == to) { top <- from + 0.5 bot <- from - 0.5 middle <- (xmin+offset[from])/2 ## top spline splTop <- stats::spline(c(xmin,middle,offset[from]), c(from + 0.2,top,from)) ## bottom spline splBot <- stats::spline(c(xmin,middle,offset[from]), c(from - 0.2,bot,from)) lines(splTop$x, splTop$y, col=colDraw) lines(splBot$x, splBot$y, col=colDraw) l <- length(splTop$y) ## draw arrow tips arrows(splTop$x[l-1], splTop$y[l-1], splTop$x[l], splTop$y[l], length=0.04, col=colDraw) offset[from] <- offset[from] + 1 } else { ## "regular" case middle <- (i+j)/2; splxy <- stats::spline(c(from - 0.2, middle, to + 0.2), c(xmin - 0.2, offset[from], xmin + 0.2)) lines(splxy$y, splxy$x, col=colDraw) if(i < j) { l <- length(splxy$y) ## draw an arrow tip arrows(splxy$y[l-1], splxy$x[l-1], splxy$y[l], splxy$x[l], length=0.06, col=colDraw) } else { ## draw "inverse" arrow tip arrows(splxy$y[2], splxy$x[2], splxy$y[1], splxy$x[1], length=0.06, col=colDraw) } ## set offset higher offset[from] <- offset[from] + 1 } } } } legposx <- nrow(con) leg.txt <- c("0-15%","15-30%","30-45%","45-60%","60-75%","75-90%","90-100%") legend(x=legposx,y=1,legend=leg.txt,lty=1,xjust=1,col=color) grDevices::dev.off() return(invisible()) } printHTML <- function(object, ...) UseMethod("printHTML") printHTML.default <- function(object, ...) NextMethod("printHTML") printHTML.trackInfo <- function(object, baseDir=".") { ##@bdescr ## create a HTML representation of the TrackInfo object data ##@edescr ## ##@in object : [list] trackInfo object ##@in baseDir : [character] string specifying the full path to the root directory to hold the HTML pages ## ## ##@codestatus : untested ## preconditions if (!is(object, "trackInfo")) { stop("argument 'object' has to be a list of class 'trackInfo'.") } if (!is.character(baseDir)) { stop("argument 'baseDir' has to be of type 'character'.") } if (length(baseDir) != 1) { stop("argument 'baseDir' has to contain exactly one element.") } if (is.na(baseDir)) { stop("argument 'baseDir' may not be missing value.") } path <- file.path(baseDir,"results") if (!file.exists(path)) { ok <- dir.create(path) if(!ok) { stop(paste("could not create", path) ) } } htmlFile <- file.path(path,"index.html") footerString <- paste("RUnit ", packageDescription("RUnit", fields="Version"), as.character(Sys.time())) ## create index.html writeHtmlHeader("RUnit Code Inspection - Overview",htmlFile) writeHtmlSection("Overview",2,htmlFile) writeBeginTable(c("Categ.","Name","Signature"),htmlFile) for(i in seq_along(object)) { funcID <- strsplit(names(object)[i],"/")[[1]] funcCat <- funcID[1] funcName <- funcID[2] if(length(funcID) > 2) { sig <- funcID[3:length(funcID)] funcSig <- paste(funcName,"(",paste(sig,collapse=", "),")",sep="") } else { funcSig <- "" } writeBeginTag("tr",htmlFile) writeCR(htmlFile) ## write function category writeBeginTag("td",htmlFile) writeRaw(funcCat,htmlFile) writeEndTag("td",htmlFile) writeCR(htmlFile) ## write function name writeBeginTag("td",htmlFile) writeLink(file.path(".", paste("result",i,".html",sep="")), funcName, htmlFile) writeEndTag("td",htmlFile) writeCR(htmlFile) ## write function signature writeBeginTag("td",htmlFile) writeRaw(funcSig,htmlFile) writeEndTag("td",htmlFile) writeCR(htmlFile) writeEndTag("tr",htmlFile) } writeEndTable(htmlFile) writeRaw(footerString, htmlFile) writeHtmlEnd(htmlFile) writeLinkRef <- function(htmlFile,leftLink,leftName,rightLink,rightName) { writeBeginTable(c("",""),htmlFile,border=0,width="100%") writeBeginTag("tr",htmlFile) writeCR(htmlFile) writeBeginTag("td",htmlFile) writeLink(leftLink,leftName,htmlFile) writeEndTag("td",htmlFile) writeCR(htmlFile) writeBeginTag("td",htmlFile,"align=\"right\""); writeLink(rightLink,rightName,htmlFile) writeEndTag("td",htmlFile) writeEndTag("tr",htmlFile) writeCR(htmlFile) writeEndTable(htmlFile) } ## create result pages for(i in seq_along(object)) { absGraphImg <- file.path(path, paste("con",i,".png",sep="")) absGraphFile <- file.path(path, paste("con",i,".html",sep="")) relGraphImg <- file.path(".", paste("con",i,".png",sep="")) relGraphFile <- file.path(".", paste("con",i,".html",sep="")) relHTMLFile <- file.path(".", paste("result",i,".html",sep="")) htmlFile <- file.path(path, paste("result",i,".html",sep="")) ## begin result page writeHtmlHeader("RUnit Code Inspection - Result",htmlFile) writeLinkRef(htmlFile,"index.html","index",relGraphFile,"graph") writeHtmlSep(htmlFile) writeHtmlSection("Result",2,htmlFile) funcName <- strsplit(names(object)[i],"/")[[1]][2] writeRaw("Function: ",htmlFile) writeBeginTag("b",htmlFile) writeRaw(funcName,htmlFile) writeEndTag("b",htmlFile) writeCR(htmlFile) writeRaw("Runs: ",htmlFile) writeBeginTag("b",htmlFile) writeRaw(object[[i]]$nrRuns,htmlFile) writeEndTag("b",htmlFile) writeCR(htmlFile) writeCR(htmlFile) writeBeginTable(c("line","code","calls","time"),htmlFile) for(j in seq_along(object[[i]]$src)) { srcLine <- object[[i]]$src[j] leadingSpaceNr <- attr(regexpr("^( )*",srcLine),"match.length") if(leadingSpaceNr > 0) { srcLine <- gsub("^( )*","",srcLine) srcLine <- paste(paste(rep(" ",leadingSpaceNr),collapse=""), srcLine,collapse="",sep="") } if(object[[i]]$run[j] > 0) { bgcolor <- "#00D000" } else { bgcolor <- "#D00000" } writeTableRow(c(j,srcLine,object[[i]]$run[j],round(object[[i]]$time[j],2)), htmlFile,bgcolor=bgcolor) } writeEndTable(htmlFile) writeHtmlSep(htmlFile) writeLinkRef(htmlFile,"index.html","index",relGraphFile,"graph") writeHtmlSep(htmlFile) writeRaw(footerString, htmlFile) writeHtmlEnd(htmlFile) ## Conncetion plot plotConnection.trackInfo(object[[i]]$graph, absGraphImg) writeHtmlHeader("RUnit Code Inspection - Connection Graph",absGraphFile) writeLinkRef(absGraphFile,"index.html","index",relHTMLFile,"Function") writeHtmlSep(absGraphFile) writeHtmlSection("Connection Graph",2,absGraphFile) writeImage(relGraphImg,absGraphFile) writeCR(absGraphFile) writeHtmlSep(absGraphFile) writeLinkRef(absGraphFile,"index.html","index",relHTMLFile,"Function") writeRaw(footerString, absGraphFile) writeHtmlEnd(absGraphFile) } return(invisible()) } RUnit/R/testLogger.r0000644000175100001440000002572011274617566014061 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: testLogger.r,v 1.19 2009/11/05 18:54:46 burgerm Exp $ .newTestLogger <- function(useOwnErrorHandler) { ##@bdescr ## creates a new, empty TestLogger 'object'. ## TestLogger is an object based on the 'closure trick'. It has the task ## to store, administrate and print the test protocol. ##@edescr ##@in useOwnErrorHandler : [logical] ##@ret : [list] ## ##@codestatus : internal ## private data: ## ----------------------- .testData <- list() class(.testData) <- "RUnitTestData" .currentTestSuiteName <- NULL .currentSourceFileName <- NULL ## book keeping variables for individual test functions ## can be reset by function cleanup .currentTraceBack <- NULL .failure <- FALSE .deactivationMsg <- NULL ## if non-NULL test function is deactivated .checkNum <- 0 ## verbosity level: 0: silent .verbosity <- 1L ## define own error handler ## ----------------------- errorHandler <- function() { ##@bdescr ## used as default error handler during test case execution iff ## the user specified 'useOwnErrorHandler' as TRUE (default). ## called in case an error condition, typically stop() has been signalled. ## tries to create a traceback object, currently only used by addError(). ## ## not provided via testLogger but used by R's error handler. ##@edescr ## ##@ret : [NULL] used for it's side effect ## ##@codestatus : internal res <- try(dump.frames()) if (inherits(res, "try-error")) { .currentTraceBack <<- "traceback not available (dump.frames failed)." } else { .currentTraceBack <<- names(last.dump)[-length(last.dump)] } } if(useOwnErrorHandler) { options(error=errorHandler) } ## public methods: ## ----------------------- .getTestData <- function() { ##@bdescr ## return the protocol data collected during the test runs ##@edescr return(.testData) } .setCurrentTestSuite <- function(testSuite) { ##@bdescr ## record the test suite that is currently executed. ##@edescr ##@in testSuite : [testSuite - list] the current testSuite if(is.null(testSuite)) { .currentTestSuiteName <<- NULL } else { if(is.element(testSuite$name, names(.testData))) { stop(paste("Duplicate test suite:", testSuite$name)) } .currentTestSuiteName <<- testSuite$name .testData[[testSuite$name]] <<- list(nTestFunc = 0L, nDeactivated = 0L, nErr = 0, nFail = 0, dirs = testSuite[["dirs"]], testFileRegexp = testSuite[["testFileRegexp"]], testFuncRegexp = testSuite[["testFuncRegexp"]], sourceFileResults = list()) } } .setCurrentSourceFile <- function(sourceFileName) { ##@bdescr ## record the source file whose test functions are currently executed ##@edescr ##@in sourceFileName : [character] name of current source file if(is.null(sourceFileName)) { .currentSourceFileName <<- NULL } else { .currentSourceFileName <<- sourceFileName .testData[[.currentTestSuiteName]]$sourceFileResults[[sourceFileName]] <<- list() } } .addSuccess <- function(testFuncName, secs) { ##@bdescr ## add a successful test function run. ##@edescr ##@in testFuncName : [character] name of test function ##@in secs : [numeric] time in seconds needed by the test function to complete .testData[[.currentTestSuiteName]]$nTestFunc <<- 1 + .testData[[.currentTestSuiteName]]$nTestFunc .testData[[.currentTestSuiteName]]$sourceFileResults[[.currentSourceFileName]][[testFuncName]] <<- list(kind="success", checkNum=.checkNum, time=secs) } .addError <- function(testFuncName, errorMsg) { ##@bdescr ## add a test function that generated an error. ##@edescr ##@in testFuncName : [character] name of test function ##@in errorMsg : [character] the error message .testData[[.currentTestSuiteName]]$nTestFunc <<- 1 + .testData[[.currentTestSuiteName]]$nTestFunc .testData[[.currentTestSuiteName]]$nErr <<- 1 + .testData[[.currentTestSuiteName]]$nErr .testData[[.currentTestSuiteName]]$sourceFileResults[[.currentSourceFileName]][[testFuncName]] <<- list(kind="error", msg=errorMsg, checkNum=.checkNum, traceBack=.currentTraceBack) } .addFailure <- function(testFuncName, failureMsg) { ##@bdescr ## add a test function that generated an error. ##@edescr ##@in testFuncName : [character] name of test function ##@in failureMsg : [character] the failure message .testData[[.currentTestSuiteName]]$nTestFunc <<- 1 + .testData[[.currentTestSuiteName]]$nTestFunc .testData[[.currentTestSuiteName]]$nFail <<- 1 + .testData[[.currentTestSuiteName]]$nFail .testData[[.currentTestSuiteName]]$sourceFileResults[[.currentSourceFileName]][[testFuncName]] <<- list(kind="failure", msg=failureMsg, checkNum=.checkNum, traceBack=NULL) ## traceBack is useless in this case } .addDeactivated <- function(testFuncName) { ##@bdescr ## add a deactivated test function that generated an error. ##@edescr ##@in testFuncName : [character] name of test function .testData[[.currentTestSuiteName]]$nDeactivated <<- 1 + .testData[[.currentTestSuiteName]]$nDeactivated .testData[[.currentTestSuiteName]]$sourceFileResults[[.currentSourceFileName]][[testFuncName]] <<- list(kind="deactivated", msg=.deactivationMsg, checkNum=.checkNum) } .addCheckNum <- function(testFuncName) { ##@bdescr ## add total number of checks performed ##@edescr ##@in testFuncName : [character] name of test function .testData[[.currentTestSuiteName]]$sourceFileResults[[.currentSourceFileName]][[testFuncName]]$checkNum <<- .checkNum } .cleanup <- function() { ##@bdescr ## reset book keeping variables like .failure, ... ## should be called before each test function execution ##@edescr .currentTraceBack <<- NULL .failure <<- FALSE .deactivationMsg <<- NULL .checkNum <<- 0 } .isFailure <- function() { ##@bdescr ## return current failure status ##@edescr return(.failure) } .setFailure <- function() { ##@bdescr ## set failure status to TRUE ##@edescr .failure <<- TRUE } .isDeactivated <- function() { ##@bdescr ## return current deactivation message ##@edescr ##@ret : [logical] TRUE if deactivation msg is not NULL return(!is.null(.deactivationMsg)) } .setDeactivated <- function(msg) { ##@bdescr ## set deactivation message variable, indicating a deactivated test case ##@edescr ##@in msg : [character] message string if (length(msg) > 1) { msg <- paste(msg, collapse=" ") } .deactivationMsg <<- msg } .incrementCheckNum <- function() { ##@bdescr ## increment internal counter of total num of test cases ##@edescr .checkNum <<- 1 + .checkNum } .getCheckNum <- function() { ##@bdescr ## return counter value for total num of test cases ##@edescr return(.checkNum) } .getVerbosity <- function() { ##@bdescr ## return verbosity level for output log messages ##@edescr return(.verbosity) } .setVerbosity <- function(level) { ##@bdescr ## set verbosity level for output log messages ##@edescr ##@in level : [integer] 0: omit output log messages, 1 >= : write begin/end comments for each test case if (length(level) > 1) { level <- level[1] } .verbosity <<- level } tl <- list(getTestData = .getTestData, setCurrentTestSuite = .setCurrentTestSuite, setCurrentSourceFile = .setCurrentSourceFile, addSuccess = function(testFuncName, secs) .addSuccess(testFuncName, secs), addError = function(testFuncName, errorMsg) .addError(testFuncName, errorMsg), addFailure = function(testFuncName, failureMsg) .addFailure(testFuncName, failureMsg), addDeactivated = function(testFuncName) .addDeactivated(testFuncName), addCheckNum = function(testFuncName) .addCheckNum(testFuncName), isFailure = .isFailure, setFailure = .setFailure, isDeactivated = .isDeactivated, setDeactivated = function(msg) .setDeactivated(msg), incrementCheckNum = .incrementCheckNum, getCheckNum = .getCheckNum, getVerbosity = .getVerbosity, setVerbosity = .setVerbosity, cleanup = .cleanup) class(tl) <- "TestLogger" return(invisible(tl)) } getErrors <- function(testData) { ##@bdescr ## return a brief summary of the test case execution result, ## computed from the testData listOfListsOfLists ## ##@edescr ## ##@in testData : [list] S3 RUnitTestData class object ##@ret : [list] containing no of errors, deactivated, failed, and total test functions ## ##@codestatus : testing if(class(testData) != "RUnitTestData") { stop("getErrors needs an object of class 'RUnitTestData' as argument.") } ret <- list(nErr=0, nDeactivated=0, nFail=0, nTestFunc=0) for(i in seq_along(testData)) { ret$nErr <- ret$nErr + testData[[i]]$nErr ret$nDeactivated <- ret$nDeactivated + testData[[i]]$nDeactivated ret$nFail <- ret$nFail + testData[[i]]$nFail ret$nTestFunc <- ret$nTestFunc + testData[[i]]$nTestFunc } return(ret) } .existsTestLogger <- function(envir=.GlobalEnv) { ##@bdescr ## Internal Function ## checks if .testLogger object is available in specified environment ## and if present if this object is of class 'TestLogger' ## ##@edescr ## ##@in envir : [environment] to search within ##@ret : [logical] TRUE iff .testLogger list object is found in specified environment ## ##@codestatus : internal exists(".testLogger", envir=envir) && inherits(.testLogger, "TestLogger") } RUnit/R/textProtocol.r0000644000175100001440000002117111274331664014434 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: textProtocol.r,v 1.18 2009/11/04 17:02:44 burgerm Exp $ printTextProtocol <- function(testData, fileName = "", separateFailureList = TRUE, showDetails = TRUE, traceBackCutOff=9) { ##@bdescr ## Report generator ## Extracts the log information stored in the 'RUnitTestData' test run object ## and generates a well formated protocol output. ##@edescr ## ##@in testData : [RUnitTestData] S3 class object ##@in fileName : [character] string, full path + file name to be written to ##@in separateFailureList : [logical] if TRUE (default) add a failure list ##@in showDetails : [logical] if TRUE (default) add detailed traceback for each error incurred ##@in traceBackCutOff : [integer] number of steps back in the trace back stack to display ##@ret : [logical] TRUE if execution completed without error ## ##@codestatus : testing ## preconditions if (!is(testData, "RUnitTestData")) { stop("Argument 'testData' must be of class 'RUnitTestData'.") } if (!is.character(fileName)) { stop("Argument 'fileName' has to be of type character.") } if (length(fileName) != 1) { stop("Argument 'fileName' must contain exactly one element.") } if (!is.logical(separateFailureList)) { stop("Argument 'separateFailureList' has to be of type logical.") } if (length(separateFailureList) != 1) { stop("Argument 'separateFailureList' must contain exactly one element.") } if (!is.logical(showDetails)) { stop("Argument 'showDetails' has to be of type logical.") } if (length(showDetails) != 1) { stop("Argument 'showDetails' must contain exactly one element.") } if (!is.numeric(traceBackCutOff)) { stop("Argument 'traceBackCutOff' has to be of type logical.") } if (length(traceBackCutOff) != 1) { stop("Argument 'traceBackCutOff' must contain exactly one element.") } if (traceBackCutOff < 0 || traceBackCutOff > 100) { stop("Argument 'traceBackCutOff' out of valid range [0, 100].") } ## just a convenience function pr <- function(..., sep=" ", nl=TRUE) { if(nl) { cat(... , "\n", file = fileName, append=TRUE, sep=sep) } else { cat(... , file = fileName, append=TRUE, sep=sep) } } ## get singular or plural right sop <- function(number, word, plext="s") { ifelse(number == 1, paste(number, word), paste(number, paste(word, plext, sep=""))) } ## header part cat("RUNIT TEST PROTOCOL --", date(), "\n", file = fileName) pr("***********************************************") if(length(testData) == 0) { pr("no test cases :-(") return(invisible(TRUE)) } errInfo <- getErrors(testData) pr("Number of test functions:", errInfo$nTestFunc) if(errInfo$nDeactivated > 0) { pr("Number of deactivated test functions:", errInfo$nDeactivated) } pr("Number of errors:", errInfo$nErr) pr("Number of failures:", errInfo$nFail, "\n\n") ## summary of test suites pr(sop(length(testData), "Test Suite"), ":") for(tsName in names(testData)) { pr(tsName, " - ", sop(testData[[tsName]]$nTestFunc, "test function"), ", ", sop(testData[[tsName]]$nErr, "error"), ", ", sop(testData[[tsName]]$nFail, "failure"), sep="") if(separateFailureList && (testData[[tsName]]$nErr + testData[[tsName]]$nFail > 0)) { srcFileRes <- testData[[tsName]][["sourceFileResults"]] for(i in seq_along(srcFileRes)) { testFuncNames <- names(srcFileRes[[i]]) for(j in seq_along(testFuncNames)) { funcList <- srcFileRes[[i]][[testFuncNames[j]]] if(funcList$kind == "error") { pr("ERROR in ", testFuncNames[j], ": ", funcList$msg, nl=FALSE, sep="") } else if(funcList$kind == "failure") { pr("FAILURE in ", testFuncNames[j], ": ", funcList$msg, sep="", nl=FALSE) } else if(funcList$kind == "deactivated") { pr("DEACTIVATED ", testFuncNames[j], ": ", funcList$msg, sep="", nl=FALSE) } } } } } ## if no details are required, we are done. if(!showDetails) { return(invisible(TRUE)) } pr("\n\n\nDetails") ## loop over all test suites for(tsName in names(testData)) { tsList <- testData[[tsName]] pr("***************************") pr("Test Suite:", tsName) pr("Test function regexp:", tsList$testFuncRegexp) pr("Test file regexp:", tsList$testFileRegexp) if(length(tsList$dirs) == 0) { pr("No directories !") } else { if(length(tsList$dirs) == 1) { pr("Involved directory:") } else { pr("Involved directories:") } for(dir in tsList$dirs) { pr(dir) } res <- tsList$sourceFileResults testFileNames <- names(res) if(length(res) == 0) { pr("no test files") } else { ## loop over all source files for(testFileName in testFileNames) { testFuncNames <- names(res[[testFileName]]) if(length(testFuncNames) > 0) { pr("---------------------------") pr("Test file:", testFileName) ## loop over all test functions in the test file for(testFuncName in testFuncNames) { testFuncInfo <- res[[testFileName]][[testFuncName]] if(testFuncInfo$kind == "success") { pr(testFuncName, ": (",testFuncInfo$checkNum, " checks) ... OK (", testFuncInfo$time, " seconds)", sep="") } else { if(testFuncInfo$kind == "error") { pr(testFuncName, ": ERROR !! ", sep="") } else if (testFuncInfo$kind == "failure") { pr(testFuncName, ": FAILURE !! (check number ", testFuncInfo$checkNum, ")", sep="") } else if (testFuncInfo$kind == "deactivated") { pr(testFuncName, ": DEACTIVATED, ", nl=FALSE) } else { pr(testFuncName, ": unknown error kind", sep="") } pr(testFuncInfo$msg, nl=FALSE) if(length(testFuncInfo$traceBack) > 0) { pr(" Call Stack:") if(traceBackCutOff > length(testFuncInfo$traceBack)) { pr(" (traceBackCutOff argument larger than length of ", "trace back: full trace back printed)") for(i in 1:length(testFuncInfo$traceBack)) { pr(" ", i, ": ", testFuncInfo$traceBack[i], sep="") } } else { for(i in traceBackCutOff:length(testFuncInfo$traceBack)) { pr(" ", 1+i-traceBackCutOff, ": ", testFuncInfo$traceBack[i], sep="") } } } } } } } } } } ## return type return(invisible(TRUE)) } print.RUnitTestData <- function(x, ...) { ##@bdescr ## Generic print method ##@edescr ## ##@in x : [RUnitTestData] S3 class object ##@in ... : [ANY] currently ignored ##@ret : [NULL] ## ##@codestatus : untested errInfo <- getErrors(x) cat("Number of test functions:", errInfo$nTestFunc, "\n") if(errInfo$nDeactivated > 0) { cat("Number of deactivated test functions:", errInfo$nDeactivated, "\n") } cat("Number of errors:", errInfo$nErr, "\n") cat("Number of failures:", errInfo$nFail, "\n") } summary.RUnitTestData <- function(object, ...) { ##@bdescr ## Generic summary method ##@edescr ## ##@in object : [RUnitTestData] S3 class object ##@in ... : [ANY] ##@ret : [logical] return valof from printTextProtocol ## ##@codestatus : untested printTextProtocol(object, ...) } RUnit/R/html.r0000644000175100001440000003112611274331467012674 0ustar hornikusers## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: html.r,v 1.10 2009/11/04 17:00:39 burgerm Exp $ writeRaw <- function(htmlStr,htmlFile,append=TRUE) { ##@bdescr ## private function ## write raw text in a html file ##@bdescr ##@in htmlStr : [character] text ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal cat(htmlStr,file=htmlFile,append=append) invisible(TRUE) } writeRawCR <- function(htmlStr,htmlFile,append=TRUE) { ##@bdescr ## private function ## write raw text in a html file with a cr at end ##@bdescr ##@in htmlStr : [character] text ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw(htmlStr,htmlFile,append) cat("\n",file=htmlFile,append=TRUE) invisible(TRUE) } writeTitle <- function(htmlStr,htmlFile,append=TRUE) { ##@bdescr ## private function ## write title tags and title text ##@bdescr ##@in htmlStr : [character] title ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("",htmlFile,append) writeRaw(htmlStr,htmlFile) writeRaw("\n",htmlFile) } writeBeginHead <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("",htmlFile,append) } writeEndHead <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("\n",htmlFile,append) } writeBeginHtml <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("",htmlFile,append) } writeEndHtml <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("\n",htmlFile,append) } writeBeginBody <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("",htmlFile,append) } writeEndBody <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw("\n",htmlFile,append) } writeBeginTag <- function(htmlTag,htmlFile,para="",append=TRUE) { ##@bdescr ## private function ## write begin of a tag, with parameters ##@bdescr ##@in htmlTag : [character] name of the tag ##@in htmlFile : [character] name of the html file ##@in para : [character] parameters as string ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal if(all(para =="")) { writeRaw(paste("<",htmlTag,">",sep=""),htmlFile,append) } else { writeRaw(paste("<",htmlTag," ",para,">",sep=""),htmlFile,append) } } writeEndTag <- function(htmlTag,htmlFile,append=TRUE) { ##@bdescr ## private function ## write end of tag ##@bdescr ##@in htmlTag : [character] name of the tag ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRaw(paste("",sep=""),htmlFile,append) } writeCR <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## write CR in html file for better formatting of the html source ##@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal cat("\n",file=htmlFile,append=append) invisible(TRUE) } writeBeginTable <- function(header,htmlFile,border=1, width="100%",append=TRUE, columnWidth=NULL) { ##@bdescr ## private function ## write begin of a table ##@bdescr ##@in header : [character] title for columns ##@in htmlFile : [character] name of the html file ##@in border : [integer] border of table ##@in width : [character] width of table ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal tablePara <- paste("border=\"",border,"\" width=\"",width,"\"",sep="") writeRawCR(paste("",sep=""),htmlFile,append) ## if header is provided if (length(header) > 0) { writeBeginTag("tr",htmlFile) for(i in seq_along(header)) { para <- "" if(!is.null(columnWidth)) { if (length(columnWidth) == length(header)) { para = paste("width=\"", columnWidth[i], "\"", sep="") } else { ## recycle first para = paste("width=\"", columnWidth[1], "\"", sep="") } } writeBeginTag("th",htmlFile, para=para) writeRaw(header[i],htmlFile) writeEndTag("th",htmlFile) writeCR(htmlFile) } writeEndTag("tr",htmlFile,append) } writeCR(htmlFile) } writeTableRow <- function(row,htmlFile,append=TRUE,bgcolor="") { ##@bdescr ## private function ## write a table row ##@bdescr ##@in row : [character] data for table cells in row ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@in bgcolor : [character] color for table cells ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeBeginTag("tr",htmlFile) if(length(bgcolor) == 1) { bgcolor <- rep(bgcolor,length(row)) } for(i in seq_along(row)) { if(bgcolor[i] == "") { writeBeginTag("td",htmlFile) } else { writeBeginTag("td",htmlFile,para=paste("bgcolor=\"",bgcolor[i],"\"",sep="")) } writeRaw(row[i],htmlFile) writeEndTag("td",htmlFile) writeCR(htmlFile) } writeEndTag("tr",htmlFile,append) writeCR(htmlFile) } writeLink <- function(target,name,htmlFile,append=TRUE) { ##@bdescr ## private function ## write a link ##@bdescr ##@in target : [character] target of the link ##@in name : [character] name of the target ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeBeginTag("a",htmlFile,paste("href=\"",target,"\"",sep=""),append=append) writeRaw(name,htmlFile,append=TRUE) writeEndTag("a",htmlFile,append=TRUE) } writeEndTable <- function(htmlFile,append=TRUE) { ##@bdescr ## private function ## close an
enviroment by adding
#@bdescr ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeEndTag("table",htmlFile,append) writeCR(htmlFile) } writeHtmlHeader <- function(header,htmlFile) { ##@bdescr ## private function ## write a HTML file header ## - DOCTYPE ## - ## - </head> ## - <body> ## ## should be finished by writeHtmlEnd ##@bdescr ##@in header : [character] title of the document ##@in htmlFile : [character] name of the link ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRawCR("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"", htmlFile,FALSE) writeRawCR("\"http://www.w3.org/TR/html4/transitional.dtd\">",htmlFile) writeBeginHtml(htmlFile) writeBeginHead(htmlFile) writeTitle(header,htmlFile) writeEndHead(htmlFile) writeBeginBody(htmlFile) } writeHtmlEnd <- function(htmlFile) { ##@bdescr ## private function ## write end of html code ##@bdescr ##@in htmlFile : [character] name of the html file ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeEndBody(htmlFile) writeEndHtml(htmlFile) } writeHtmlSep <- function(htmlFile) { ##@bdescr ## private function ## write horizontal seperator ##@bdescr ##@in htmlFile : [character] name of the html file ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeRawCR("<hr>",htmlFile) } writeImage <- function(img,htmlFile,append=TRUE) { ##@bdescr ## private function ## write image tags ##@bdescr ##@in img : [character] name of the image file ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal writeBeginTag("img",htmlFile,para=paste("src=\"",img,"\"",sep=""),append) writeEndTag("img",htmlFile) } writeHtmlSection <- function(title,sec,htmlFile,append=TRUE) { ##@bdescr ## private function ## write titles for section ##@bdescr ##@in title : [character] title of the section ##@in sec : [integer] size of title (between 1-6) ##@in htmlFile : [character] name of the html file ##@in append : [logical] append the html code ##@ret : [logical] TRUE if execution completes ## ##@codestatus : internal secTag <- paste("h",sec,sep="") writeBeginTag(secTag,htmlFile,append) writeRaw(title,htmlFile,append) writeEndTag(secTag,htmlFile,append) writeCR(htmlFile,append) } writeHtmlTable <- function(dataFrame, htmlFile, border=1, width="100%", append=TRUE) { ##@bdescr ## private function ## write a data frame to a HTML table ##@bdescr ## ##@in dataFrame : [data frame] size of title (between 1-6) ##@in htmlFile : [character] name of the html file ##@in border : [integer] 1 (default) table borders will be shown ##@in width : [character] width of table ##@in append : [logical] if TRUE append the tabel to an existing HTML file ##@ret : [logical] TRUE if execution completed ## ##@codestatus : internal header <- NULL colNames <- colnames(dataFrame) if (!is.null(colNames)) { if (length(colNames) == dim(dataFrame)[2]) { header <- colNames } else { ## don't write column names header <- NULL } } rowNames <- rownames(dataFrame) if (!is.null(rowNames)) { header <- c("Name", header) dataFrame <- cbind(rowNames, dataFrame) } writeBeginTable(header, htmlFile, border=border, width=width, append=append, columnWidth=NULL) for (ti in 1:dim(dataFrame)[1]) { writeTableRow(dataFrame[ti, ], htmlFile, append=TRUE, bgcolor="") } writeEndTable(htmlFile,append=TRUE) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/R/options.r�����������������������������������������������������������������������������������0000644�0001751�0000144�00000003023�11303243532�013402� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: options.r,v 1.2 2009/11/25 15:03:54 burgerm Exp $ .buildRUnitOptions <- function() { ##@bdescr ## Internal function ## adds an entry to R's default global option list ## modelled after version in package Biobase (BioC) ##@edescr ## ##@ret : [list] extended options() list ## ##@codestatus : internal RUnit <- getOption("RUnit") if (is.null(RUnit)) { RUnit <- list() class(RUnit) <- "RUnitOptions" } if (is.null( RUnit$verbose)) { ## integer: == 0: silent, >= 1: add comments to test case log RUnit$verbose <- 1L } if (is.null(RUnit$silent)) { RUnit$silent <- FALSE } if (is.null(RUnit$outfile)) { RUnit$outfile <- NULL } options("RUnit"=RUnit) } �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/ChangeLog�������������������������������������������������������������������������������������0000644�0001751�0000144�00000120705�11173623463�013116� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������2009-04-22 15:52 burgerm * tests/runitInspect.r: added test cases for more complex functions to track 2009-04-22 15:50 burgerm * R/inspector.r: includeTracker: fix `<- if` call handling which caused the inspect mechanism to fail 2009-04-22 15:48 burgerm * R/runit.r: isValidTestSuite: check for empty name string as this will cause subsequent failure which is harder to understand 2009-04-22 15:46 burgerm * NAMESPACE: declare S3 print and summary methods for RUnitTestData 2009-04-22 11:37 burgerm * inst/doc/RUnit.pdf: removed: use R CMD build to generate, no need to store in repository 2009-04-16 11:54 burgerm * DESCRIPTION: patch level 0.4.22: clarified GPL version 2009-04-16 11:49 burgerm * R/textProtocol.r: specified license to be version 2 of the GPL 2009-04-16 11:48 burgerm * R/testLogger.r: specified license to be version 2 of the GPL; extended function descriptions 2009-04-16 11:44 burgerm * R/: checkFuncs.r, exportHTML.r, html.r, htmlProtocol.r, inspector.r, runit.r: specified license to be version 2 of the GPL 2009-04-16 11:39 burgerm * R/00Init.r: specified license to be version 2 of the GPL 2009-04-16 11:23 burgerm * inst/: examples/correctTestCase.r, examples/runitVirtualClassTest.r, share/R/checkCode.r, share/R/compareRUnitTestData.r: specified license to be version 2 of the GPL 2009-04-16 11:18 burgerm * tests/: runitHTMLProtocol.r, runitInspect.r, runitPlotConnection.r, runitRUnit.r, runitS4.r, runitSetUp.r, runitTearDown.r, runitTextProtocol.r: specified license to be version 2 of the GPL 2009-04-16 11:13 burgerm * man/: RUnit-internal.Rd, RUnit-intro.Rd, checkFuncs.Rd, inspect.Rd, printHTML.trackinfo.Rd, runit.Rd, textProtocol.Rd, tracker.Rd: specified license to be version 2 of the GPL 2009-03-16 17:38 burgerm * R/inspector.r: always coninue if-else on the same line removed semicolon at line ends 2009-03-16 17:36 burgerm * R/runit.r: defineTestSuite: gained some argument checks isValidTestSuite: warning messages modified to handle multiple names some typos in inline documentation fixed 2009-03-16 17:29 burgerm * R/checkFuncs.r: always coninue if else on the same line checkIdentical: added precondition check 2009-03-16 17:26 burgerm * R/exportHTML.r: always coninue if-else on the same line removed semicolon at line ends 2009-03-16 17:24 burgerm * R/html.r: always coninue if else on the same line html.r removed semicolon at line ends 2009-03-16 17:21 burgerm * inst/doc/RUnit.Rnw: minute corrections 2009-03-05 16:58 burgerm * DESCRIPTION: License field updated according to R-ext for R 2.8.1 2009-01-23 19:13 burgerm * man/: checkFuncs.Rd, inspect.Rd, printHTML.trackinfo.Rd, runit.Rd, textProtocol.Rd, tracker.Rd: corrected typos, changed formating of code chunks to allow for proper display in pdf reference manual (suggested by Terry Therneau) 2009-01-23 17:23 burgerm * NEWS: typos corrected 2009-01-15 14:47 burgerm * DESCRIPTION: patch level 0.4.21 2009-01-15 14:46 burgerm * ChangeLog: update for 0.4.21 submission 2009-01-15 14:46 burgerm * NEWS: updated for 0.4.21 submission 2009-01-15 14:26 burgerm * man/tracker.Rd: enclosed \item statements within \describe environment: identified by new R 2.9.0 Rd parser 2009-01-15 14:23 burgerm * man/runit.Rd: defineTestSuite default argument value: use \ escape to display \\ in resulting help page after parsing 2008-11-07 14:49 burgerm * R/htmlProtocol.r: compiler detection failed on MacOS, fixed, thanks to report by Steffen Neumann 2008-11-07 12:20 burgerm * R/inspector.r: use seq_along 2008-11-07 12:19 burgerm * R/checkFuncs.r: check for missing arguments 2008-11-07 12:15 burgerm * DESCRIPTION: patch level 0.4.20 2008-06-20 17:51 burgerm * R/textProtocol.r: printTextProtocol rewritten by Klaus using toText; getErrors moved here, TODO replace with S4 method 2008-06-20 17:49 burgerm * NAMESPACE: adopt S4 classes and methods; removed some outdated functions 2008-06-20 17:36 burgerm * R/runit.r: rewritten by Klaus, using S4 design and condition mechanism 2008-06-20 17:29 burgerm * R/00Init.r: added generics definition used for S4 methods 2008-06-20 17:27 burgerm * R/testLogger.r: removed; will eventually be replaced 2008-06-20 17:26 burgerm * R/: TestFileResult.r, TestFunctionResult.r, TestResult.r, TestSuite.r, TestSuiteResult.r: S4 class based design of RUnit 2008-06-20 17:26 burgerm * R/checkFuncs.r: rewritten by Klaus using conditions 2008-06-20 17:24 burgerm * R/utility.r: utility functions not attributed to one class; miscellaneous 2008-06-19 15:57 burgerm * ChangeLog: updated 2008-06-19 13:49 burgerm * tests/runitInspect.r: added 2nd example function 2008-06-19 13:46 burgerm * man/textProtocol.Rd: details section updated; example on RUnit test suite execution added in a dontrun clause: works only on source package as tests/ folder is not copied to installed package 2008-06-19 13:42 burgerm * man/runit.Rd: runTestFile example call added 2008-06-19 10:07 burgerm * DESCRIPTION: patch version 0.4.19 2008-06-18 19:18 burgerm * R/textProtocol.r: details section: output check number per test case 2008-06-18 19:17 burgerm * R/htmlProtocol.r: details section: output check number per test case; improved compiler detection 2008-06-18 19:16 burgerm * R/runit.r: isValidTestSuite: changed check for object class to is() to allow derived class objects to pass (suggested by Philippe Grosjean); use addCheckNum to set number of checks performed within test function 2008-06-18 19:13 burgerm * R/testLogger.r: added addCheckNum, getCheckNum functions to allow check number output in summary 2008-06-18 19:12 burgerm * R/checkFuncs.r: checkEquals: argument checkNames checked for correct type; not required paste calls around error message removed (suggested by Philippe Grosjean) 2008-06-18 19:09 burgerm * R/00Init.r: removed start up message 2008-04-29 10:06 burgerm * inst/share/R/compareRUnitTestData.r: check for empty test case results and exclude them from comparison; replaced seq with seq_along 2007-11-30 15:13 burgerm * tests/runitRUnit.r: error introduced in last commit corrected; some more check conditions added 2007-11-30 14:57 burgerm * R/htmlProtocol.r: fixed errors introduced in last commit: replaced seq_len with seq_along 2007-11-27 20:07 burgerm * ChangeLog: updated 2007-11-27 20:05 burgerm * DESCRIPTION: patch level 0.4.18; R dependency set to 2.4.0 were seq_along was introduced 2007-11-27 19:56 burgerm * tests/runitRUnit.r: seq_along introduced; partial argument names expanded 2007-11-27 19:55 burgerm * R/runit.r: seq_along introduced 2007-11-27 19:53 burgerm * R/exportHTML.r: seq_along introduced; partial argument names expanded 2007-11-27 19:52 burgerm * R/: html.r, htmlProtocol.r, testLogger.r, textProtocol.r: seq_along introduced 2007-05-21 13:42 burgerm * NEWS: updated for 0.4.17 CRAN submission 2007-05-21 13:37 burgerm * DESCRIPTION: patch level 0.4.17 2007-05-21 13:33 burgerm * man/: textProtocol.Rd, runit.Rd: changed example code to work with installed package test case example path 2007-05-18 14:58 burgerm * R/runit.r: try harder to ensure previous error handler is reinstantiated after test runner execution 2007-05-18 14:56 burgerm * DESCRIPTION: patch level 0.4.16 2007-05-18 14:55 burgerm * NEWS: updated for 0.4.16 2007-05-16 15:17 burgerm * DESCRIPTION: SaveImage replaced by LazyLoad 2007-05-16 14:27 burgerm * inst/share/R/compareRUnitTestData.r: initial prototype: comare two RUnitTestData objects: intended for test run time performance evaluation 2007-05-16 14:24 burgerm * R/runit.r: .sourceTestFile: updated to observe - after sandbox introduction - test case file defined .setUp and .tearDown functions 2007-05-16 14:21 burgerm * tests/runitS4.r: check S4 setClass + removeClass chain with new sandbox implementation 2007-05-16 14:19 burgerm * tests/: runitSetUp.r, runitTearDown.r: added for focused check of .setUp and .tearDown functioning 2007-05-16 14:16 burgerm * tests/runitRUnit.r: class names changed; clean up operation revised: try harder to reset to previous global state 2007-05-16 14:15 burgerm * tests/runitInspect.r: .tearDown added: cleanup 2007-05-16 10:49 burgerm * DESCRIPTION: dev patch level 0.4.15-2 2007-05-16 00:46 burgerm * man/runit.Rd: added encoding latin1 to display umlaut correctly if available; make use of describe command to format details section 2007-05-16 00:42 burgerm * man/checkFuncs.Rd: added encoding latin1 to display umlaut correctly if available; added paragraph on S4 classes and methods to details section 2007-05-15 23:46 burgerm * man/inspect.Rd: added encoding latin1 to display umlaut correctly if available 2007-05-15 23:45 burgerm * man/textProtocol.Rd: added encoding latin1 to display umlaut correctly if available; added header; added \pkg command around RUnit phrase 2007-05-15 23:43 burgerm * man/: RUnit-intro.Rd, tracker.Rd, printHTML.trackinfo.Rd: added encoding latin1 to display umlaut correctly if available 2007-05-15 17:33 burgerm * R/runit.r: make use of a new environment defined as child of .GlobalEnv to allow setClass calls wo where argument 2007-04-25 08:46 burgerm * R/TestCaseMethods.r: construct method added; verify method checks partially switched off 2007-04-25 08:39 burgerm * R/TestCaseTestResultData.r: slots checkNum, traceBack and warnMessageStack added 2007-04-23 00:14 burgerm * R/testLogger.r: replaced by condition signals 2007-04-23 00:10 burgerm * R/TestCaseTestResultDataMethods.r: .printTextProtocol added: used in recursive call chain 2007-04-23 00:08 burgerm * R/: SourceFileTestResultDataMethods.r, TestSuiteTestResultDataMethods.r: .printTextProtocol, getError and getTestCaseNum added: used in recursive call chain 2007-04-23 00:05 burgerm * R/runit.r: removed .testLogger; added warning handler; switched to condition signals; use testCaseCheckCount for check call counting 2007-04-23 00:03 burgerm * R/checkFuncs.r: removed .testLogger 2007-04-23 00:00 burgerm * DESCRIPTION: removed .testLogger; added experimental condition signaling 2007-04-15 12:50 burgerm * DESCRIPTION: patch level 0.6.0-2 exploration stage; NOT FIT FOR PUBLIC USE 2007-04-15 12:48 burgerm * NAMESPACE: new S4 classes and methods added 2007-04-15 12:47 burgerm * R/runit.r: experimental: enabled new S4 class based result collection IN PARALLEL to exiting logger mechanism for exploration; NOT FIT FOR PUBLIC USE 2007-04-15 12:45 burgerm * R/Logger.r: getSealed added to exported accessors 2007-04-15 12:40 burgerm * R/checkFuncs.r: RUnit specific signals/conditions implemented and enabled in check* functions 2007-04-15 12:38 burgerm * R/zzz.r: log statement added; TestResultData method def enabled 2007-04-15 12:37 burgerm * R/TestSuiteTestResultDataMethods.r: method implementation added, accessor methods added 2007-04-15 12:36 burgerm * R/TestSuiteTestResultData.r: slots error & errorMsg added to cover suite level errors 2007-04-15 12:35 burgerm * R/TestResultData.r: slot name changed 2007-04-15 12:34 burgerm * R/TestCaseTestResultDataMethods.r: method implementation added, accessor methods added 2007-04-15 12:33 burgerm * R/TestCaseTestResultData.r: class definition reworked, slots renamed and added: NOT FINAL DESIGN 2007-04-15 12:31 burgerm * R/SourceFileTestResultDataMethods.r: method implementation added, getTestResultData added 2007-04-15 12:29 burgerm * R/SourceFileTestResultData.r: slot name renamed to sourceFileName, slots error & errorMsg added to cover source file level errors 2007-04-15 12:28 burgerm * R/htmlProtocol.r: regexpr fixed for R 2.5.0 2007-04-12 10:29 burgerm * R/inspector.r: unused variables removed 2007-04-09 19:42 burgerm * tests/runitRUnit.r: all check* test cases reviewed and extended to cover more failure conditions; checkEquals extended to be checked for all basic R types and S4 objects 2007-04-09 19:38 burgerm * R/testLogger.r: errorHandler: rewritten to be more failure robust; docu added 2007-04-09 19:25 burgerm * R/checkFuncs.r: checkEqualsNumeric: one more argument check added (now identical to checkEquals; docu description made more clear 2007-04-08 14:14 burgerm * R/runit.r: runTestSuite docu make more clear 2007-04-08 14:11 burgerm * R/00Init.r: pass lib argument on to packageDescription to load correct DESCRITPION file 2007-04-05 16:28 burgerm * R/htmlProtocol.r: included deactivatedStyle tag to HTML output: non-visible change 2007-04-02 00:08 burgerm * R/zzz.r: class and method init calls added/updated 2007-04-02 00:04 burgerm * R/00Init.r: packageDescription now observes the library path for the currently loaded package version 2007-04-02 00:02 burgerm * R/TestCaseTestResultData.r: sealed argument controlled by .GLOBAL state; slot failed renamed to failure 2007-04-01 23:59 burgerm * R/: TestResultData.r, SourceFileTestResultData.r, TestSuiteTestResultData.r: sealed argument controlled by .GLOBAL state 2007-04-01 23:53 burgerm * R/: TestCase.r, TestCaseMethods.r, TestLogger.r, TestLoggerMethods.r: playground extended 2007-04-01 23:51 burgerm * R/ArrayMethods.r: - code formating changes ArrayMethods.r - setNames: unnecessary precondition check removed - concat: precondition check added method definition also added to Array base class - printObject rewritten to use show - show method added - array class constructor: sealed argument controlled by .GLOBAL state - applyFun method definition added to array class generator 2007-04-01 23:43 burgerm * R/Array.r: allow sealed argument to be controlled by .GLOBAL state 2007-04-01 23:42 burgerm * R/classUtilities.r: in setGeneric avoid assigning to temp variable value as no postprocessing is intended here and this assignment has a small memory penalty as shown by memprof 2007-04-01 23:38 burgerm * DESCRIPTION: patch level 0.6.0-1: more exploratory code chunks added 2007-03-31 23:15 burgerm * inst/examples/runitVirtualClassTest.r: S4 class example 2007-03-29 09:26 burgerm * inst/share/R/checkCode.r: utility wrappers around checkUsage (package codetools) to check no default location code files; experimental 2007-03-23 15:18 burgerm * tests/runitPlotConnection.r: deactivate test case if R is run in non-interactive mode i.e. most likely no X server is present but require by the png device 2007-03-19 21:08 burgerm * tests/runitPlotConnection.r: simple run test 2007-03-19 01:54 burgerm * R/htmlProtocol.r: fixed gcc query under Windows: report NA 2007-03-19 01:52 burgerm * NEWS: printHTMLProtocol fixed (Windows) 2007-03-19 00:55 burgerm * man/runit.Rd: added header 2007-03-19 00:54 burgerm * tests/runitRUnit.r: added exception check for call object: R 2.5.0 devel issue with new try implementation 2007-03-19 00:51 burgerm * tests/: runitTextProtocol.r, runitHTMLProtocol.r: added check for successful execution, taking care of nested test suite calls 2007-03-19 00:49 burgerm * inst/examples/correctTestCase.r: R 1.9.0 compatibility: replace isTRUE by identical 2007-03-19 00:45 burgerm * R/inspector.r: docu updated/extended; tracker closure functions revised: internal object now is always of S3 class trackInfo, renamed to trackInfo for clarity, addFunc simplified, reinit of oldTime was not written to closure variable; several precondition checks added 2007-03-19 00:40 burgerm * R/exportHTML.r: functions now return invisible; HTML head info updated; result page file names changed; HTML footer added 2007-03-19 00:36 burgerm * man/printHTML.trackinfo.Rd: header added; details text description corrected 2007-03-19 00:34 burgerm * man/tracker.Rd: header added; moved closure functions to new section to avoid R CMD check warning; added isValid 2007-03-16 12:25 burgerm * NEWS: updated for 0.4.15 2007-03-16 12:22 burgerm * DESCRIPTION: patch level 0.4.15 2007-03-16 12:08 burgerm * R/checkFuncs.r: compatibility to R 1.9.0 as declared in DESCRIPTION: removed calls to isTRUE as this was introduced only in R 2.1.0, replaced where needed by identical(TRUE, x) 2007-03-16 12:07 burgerm * R/htmlProtocol.r: createTestFuncRef: removed unnecessary escape characters in gsub call 2007-03-16 12:05 burgerm * tests/runitRUnit.r: compatibility to R 1.9.0 as declared in DESCRIPTION: removed calls to isTRUE as this was introduced only in R 2.1.0, replaced where needed by identical(TRUE, x) 2006-08-30 01:13 burgerm * DESCRIPTION: patch level 0.6.0-0: start new minor level 0.6.0.x for development, first public release will be 0.6.0; 0.5.x is reserved for potential S3 implementation updates; class layout as described in dia 2006-08-30 01:11 burgerm * NAMESPACE: initial commit: class layout as described in dia 2006-08-30 00:58 burgerm * R/TestSuiteTestResultDataMethods.r: initial commit: class layout as described in dia 2006-08-30 00:54 burgerm * R/: ArrayMethods.r, Logger.r, SignalHandler.r, SourceFileTestResultDataMethods.r, TestCaseTestResultDataMethods.r, TestSuiteMethods.r, classUtilities.r, zzz.r: initial commit: class layout as described in dia 2006-08-30 00:51 burgerm * R/: Array.r, SourceFileTestResultData.r, TestCaseTestResultData.r, TestResultData.r, TestSuite.r, TestSuiteTestResultData.r: initial commit: class layout as described in dia 2006-08-22 11:21 burgerm * NEWS: 0.4.14 update log added 2006-08-17 09:12 burgerm * DESCRIPTION: patch level 0.4.14: package utils dependency made explicit in DESCRIPTION and NAMESPACE 2006-08-17 01:14 burgerm * NAMESPACE: import of package utils added (required for R 2.4.0) 2006-08-16 17:39 burgerm * inst/doc/RUnit.Rnw: added a note on the new arguments rngKind, and rngNormalKind; replaced path construction via paste by the more protable file.path (Gregor Gorjanc) 2006-08-16 17:36 burgerm * inst/doc/RUnit.pdf: updated 2006-08-15 18:52 burgerm * ChangeLog: updated 2006-08-15 18:51 burgerm * R/textProtocol.r: return type enforced (a bit more) to be logical 2006-08-15 18:50 burgerm * R/runit.r: defineTestSuite, runTestFile: added arguments rngKind, rngNormalKind to allow configuartion of default RNG configuration, docu tag updated 2006-08-15 18:48 burgerm * R/testLogger.r: documentaion tags added 2006-08-15 18:47 burgerm * R/htmlProtocol.r: return type enforced (a bit more) to be logical, documentation updated 2006-08-15 18:41 burgerm * R/textProtocol.r: documentation updated; printTextProtocol return type changed to logical 2006-08-15 18:34 burgerm * R/html.r: documentation tags updated 2006-08-15 18:33 burgerm * R/exportHTML.r: file I/O: replaced paste call by more protable file.path 2006-08-15 18:31 burgerm * tests/runitRUnit.r: defineTestSuite test case added 2006-08-15 18:29 burgerm * man/runit.Rd: runTestFile, defineTestSuite: documented new arguments rngKind, rngNormalKind 2006-08-15 18:27 burgerm * NEWS: updated: added recent releases 2006-08-15 18:26 burgerm * DESCRIPTION: patch level: 0.4.12 2006-08-08 00:58 burger * R/runit.r: defineTestSuite - allow file extension .R 2006-08-08 00:57 burger * DESCRIPTION: patch level 0.4.12 - allow file extension .R (runit.r) 2006-07-17 19:27 burger * R/00Init.r: package version added to startup message 2006-05-22 10:33 burger * R/checkFuncs.r: DEACTIVATED - fixed typo in var name 2006-04-05 13:47 burger * R/checkFuncs.r: checkException: added comment on contributing author 2006-04-04 19:25 burger * R/TestResultClass.r: License header text added 2006-04-04 19:25 burger * R/TestLogger.r: initial commit 2006-04-04 19:24 burger * R/: TestResultMethods.r, TestSuiteResult.r, TestSuiteResultMethods.r: Lincence header text added 2006-04-04 17:38 burger * NEWS, inst/doc/RUnit.pdf: updated 2006-04-04 17:08 burger * man/inspect.Rd: updated inspect call and argument documentation 2006-04-04 17:08 burger * man/printHTML.trackinfo.Rd: updated inspect call 2006-04-04 17:07 burger * man/tracker.Rd: updated inspect calls 2006-04-04 17:07 burger * inst/doc/RUnit.Rnw: updated inspect calls, added some line to recomendations 2006-04-03 18:35 burger * tests/runitRUnit.r: checkException: silent added to checks 2006-04-03 18:34 burger * R/checkFuncs.r: checkException: argument silent added 2006-04-03 18:32 burger * man/checkFuncs.Rd: checkException, checkEquals documentation updated 2006-04-03 18:31 burger * DESCRIPTION: patch level 0.4.11: checkException arg added 2006-04-03 14:40 burger * inst/examples/runitfoo.r: example function 2006-03-21 15:47 burger * tests/runitRUnit.r: unsuccessful attempt to extend runTestSuite test case 2006-03-21 15:37 burger * R/runit.r: isValidTestSuite: error message texts added 2006-03-21 15:34 burger * R/inspector.r: inspect, and includeTracker have new argument track, which defaults to track for consitency; API docu enhanced and extended 2006-03-21 15:32 burger * tests/runitInspect.r: reactivated both test cases after changes to inspect, and includeTracker 2006-03-21 15:31 burger * DESCRIPTION: patch level 0.4.10 2006-03-07 20:41 burger * R/checkFuncs.r: checkEquals: new compatibility argument to allow to workaround stricter all.equal checks; tolerance precondtion added 2006-03-07 20:39 burger * DESCRIPTION: patch level 0.4.9: checkEquals has new compatibility argument 2006-01-20 18:25 burger * tests/runitRUnit.r: checkIdentical added; checkEquals test case extended 2006-01-20 18:24 burger * man/checkFuncs.Rd: checkIdentical added; arguments a,b, renamed consitent with all.equal 2006-01-20 18:23 burger * R/checkFuncs.r: checkIdentical added; msg argument default added; msg added to stop calls; arguments a,b, renamed consitent with all.equal 2006-01-20 18:21 burger * NAMESPACE: checkIdentical added 2006-01-20 18:18 burger * DESCRIPTION: patch version 0.4.8: checkIdentical added 2006-01-05 15:09 burger * R/checkFuncs.r: checkEqualsNumeric: update to be compatible with R 2.3.0 2006-01-05 15:08 burger * DESCRIPTION: patch level 0.4.7: update for checkEqualsNumeric to be compattible with R 2.3.0 2005-12-12 10:35 burger * DESCRIPTION: patch level 0.4.6 2005-12-12 10:32 burger * R/htmlProtocol.r: replaced HOST query by supposedly platform independent Sys.info variant 2005-12-05 14:44 burger * R/htmlProtocol.r: system info table format changed 2005-12-05 14:44 burger * R/html.r: writeHtmlTable added; API tags updated 2005-11-21 15:29 burger * DESCRIPTION: patch level 0.5.0 added - temporary - dependency on EpiR.base (arrayTemplate class) 2005-11-21 15:28 burger * R/zzz.r: class & method init currently required arrayTemplate and thus relies on EpiR.base FIXME: remove dependency on EpiR.base once design has matured 2005-11-21 15:28 burgerm * R/zzz.r: file zzz.r was added on branch S4-devel-branch-2006-08 on 2006-08-29 22:54:46 +0000 2005-11-21 15:26 burger * R/Logger.r: first exploration 2005-11-21 15:26 burgerm * R/Logger.r: file Logger.r was added on branch S4-devel-branch-2006-08 on 2006-08-29 22:54:46 +0000 2005-11-21 15:15 burger * R/textProtocol.r: added execTime S3 method 2005-11-21 15:15 burger * R/: TestFileResult.r, TestFunctionResult.r, TestResultMethods.r, TestSuiteResult.r, TestFileResultMethods.r, TestSuiteResultMethods.r: first prototype 2005-11-21 15:13 burger * R/TestResultClass.r: first prototype: virtual base class: the mother of all test results 2005-11-14 13:40 burger * DESCRIPTION: patch level 0.4.5 improvements to error detection in runTestSuite & new test cases 2005-11-14 13:39 burger * tests/runitRUnit.r: added isValidTestSuite, runTestFile, and runTestSuite test cases added test case description 2005-11-14 13:37 burger * R/runit.r: runTestSuite: added preconditions runTestFile: pass on error handler flag 2005-11-14 13:36 burger * inst/examples/correctTestCase.r: used for unit test cases 2005-11-14 11:37 burger * R/runit.r: added codestatus API tag runTestSuite: modified error msg 2005-11-14 11:36 burger * R/checkFuncs.r: added codestatus API tag, set to testing 2005-10-27 10:44 burger * .cvsignore: initial commit ignaore eclipse project file 2005-09-29 14:19 burger * DESCRIPTION: changed Klaus email address 2005-09-29 14:16 burger * inst/doc/Makefile: initial commit: utility 2005-08-30 16:28 burger * DESCRIPTION: patch level 0.4.4: changed maintainer 2005-04-07 16:17 burger * tests/runitInspect.r: added & deactivated 2 test cases: environment issues to be addressed by Thomas 2005-04-07 16:04 burger * tests/runitRUnit.r: DEACTIVATED test added 2005-04-07 16:03 burger * R/inspector.r: includeTracker: modifed regexp in grep to comply to R 2.1.0; removed semi-colons; added docu tags 2005-04-07 16:02 burger * R/checkFuncs.r: checkTrue: argument renmaed to match docu: R 2.1.0 CMD check issue 2005-04-07 16:00 burger * R/runit.r: isValidTestSuite: added check on folder existance; docu tags added 2005-04-07 15:59 burger * R/testLogger.r: setDeactivated: added handling of msg with string length > 1; docu extended 2005-04-07 15:41 burger * DESCRIPTION: patch level 0.4.2: fixed R 2.1.0 inspect regexp problem 2005-02-02 13:38 kjuen * R/: htmlProtocol.r, textProtocol.r: the protocol now doesn't mention test files that do not contain any test functions 2005-01-17 19:03 kjuen * R/htmlProtocol.r: minor formatting modifications 2004-12-13 15:34 burger * R/checkFuncs.r: checkTrue: had to add explicit eval to ensure the argument gets evaluated before attempting to set the names attribute to NULL 2004-12-13 14:58 burger * man/checkFuncs.Rd: updated help text for checkTrue 2004-12-13 14:49 burger * R/checkFuncs.r, tests/runitRUnit.r: checkTrue: extended: correct handling of named logical arguments 2004-12-13 14:48 burger * DESCRIPTION: patch level 0.4.2: corrected deficient checkTrue 2004-11-29 19:53 burger * DESCRIPTION: patch level: 0.4.1: http URL mapped 2004-11-29 18:12 kjuen * R/htmlProtocol.r, man/textProtocol.Rd: 'testFileToLinkMap' parameter added to the printHTMLProtocol function added 2004-09-30 15:19 kjuen * inst/doc/: RUnit.Rnw, RUnit.pdf: typos fixed 2004-09-29 18:53 burger * DESCRIPTION: added methods dependency, again 2004-09-29 14:18 kjuen * DESCRIPTION: changes for new release 2004-09-29 14:17 kjuen * inst/doc/RUnit.pdf: hopefully readable for everybody 2004-09-28 11:11 kjuen * R/htmlProtocol.r: deactivated table cells are now printed yellow 2004-09-22 15:27 burger * DESCRIPTION: patch level 0.3.8: RC 0.4.0; removed package splines dependency; added SaveImage directive 2004-09-22 15:24 burger * NAMESPACE: removed splines import 2004-09-22 15:23 burger * R/00Init.r: added .onLoad hook for loading methods prior to RUnit attachment: recommended for R 2.0.0 2004-09-22 15:23 burger * R/inspector.r: removed library calls for methods & splines; added 00Init.r file for this 2004-09-22 15:22 burger * NEWS: replaced tabs; corrected typo, added splines dependency removal 2004-09-22 14:40 kjuen * NEWS: news for release 0.4.0 2004-09-15 15:07 kjuen * NAMESPACE: DEACTIVATED added 2004-09-15 15:07 kjuen * man/: RUnit-internal.Rd, RUnit-intro.Rd, checkFuncs.Rd, inspect.Rd, printHTML.trackinfo.Rd, runit.Rd, textProtocol.Rd, tracker.Rd: some very small cleanups to avoid warnings with R-2 2004-09-09 12:21 kjuen * R/: htmlProtocol.r, testLogger.r, textProtocol.r: .getErrors completely removed 2004-09-08 18:05 burger * DESCRIPTION: updated patch level to 0.3.7 2004-09-08 18:03 burger * NAMESPACE: added getErrors to namespace exports 2004-09-08 18:02 burger * R/testLogger.r: copied .getErrors to getErrors, added to namespace exports, .getErrors set deprecated 2004-09-08 14:20 kjuen * R/htmlProtocol.r: deactivated column in testsuite table is included only when there are any deactivated test functions 2004-09-07 17:28 kjuen * R/: checkFuncs.r, htmlProtocol.r, runit.r, testLogger.r, textProtocol.r: several small cleanups, DEACTIVATED function added 2004-09-06 15:32 burger * inst/NAMESPACE: removed, moved to from inst/ folder 2004-09-06 15:32 burger * NAMESPACE: moved here from inst/ folder as promoted by R 2.0.0 docu 2004-09-06 15:21 burger * R/runit.r: .executeTestCase: added log output: test function call 2004-09-06 15:13 burger * R/textProtocol.r: added braces 2004-08-05 13:34 burger * R/htmlProtocol.r: added braces; added col.names=FALSE to write.table for printing out R version info 2004-07-13 18:16 burger * inst/doc/RUnit.pdf: created via R 1.9.1 buildVignettes("RUnit", "~/src/R/Runit", quiet=FALSE) call, package tools 2004-07-13 16:07 burger * inst/doc/: RUnit.Rnw, RUnit.pdf: set VignetteDepends; commented out LaTeX dependencies; added bibliography with URL for SF RUnit site 2004-07-13 16:04 burger * DESCRIPTION: added SF URL; fixed vignette PDF problem; updated patch level to 0.3.6 2004-06-29 17:17 burger * R/htmlProtocol.r: added colnames(ver) <- "" to avoid warning in R >= 1.9.0 2004-06-10 11:01 burger * R/htmlProtocol.r: added writeCR to writeP function: creates better structured HTML code, relevant also for the internal built script 2004-06-09 20:40 burger * R/html.r: corrected writeEndHead & writeEndHtml: both wrote start instead of end tags 2004-06-08 11:01 burger * DESCRIPTION: updated patch level to 0.3.4, corrected R CMD check warning on man page files 2004-06-08 09:27 burger * man/: RUnit-intro.Rd, RUnit.Rd: renamed RUnit.Rd to RUnit-intro.Rd 2004-06-08 09:24 burger * man/: RUnit.Rd, checkFuncs.Rd, inspect.Rd, printHTML.trackinfo.Rd, runit.Rd, textProtocol.Rd, tracker.Rd: replaced keyword{RUnit} by concept{RUnit}, suggested by Kurt Hornik 2004-06-07 11:41 koenig * inst/doc/RUnit.Rnw: some formatting changes and better descriptions 2004-06-04 22:44 burger * man/checkFuncs.Rd: renamed f to fun 2004-06-04 22:44 burger * DESCRIPTION: updated patch level to 0.3.3, fixed last failing R CMD check tests: ready for CRAN submission 2004-06-04 22:33 burger * man/tracker.Rd: only example text format changed 2004-06-04 22:32 burger * man/printHTML.trackinfo.Rd: updated to new argument name 2004-06-04 22:31 burger * R/exportHTML.r: fixed error introduced with the check on the successful directory creation: renamed res input argument to trackInfo 2004-06-04 20:16 burger * R/htmlProtocol.r: added R version output at end of HTML page 2004-06-03 17:41 burger * R/exportHTML.r: added preconditions and handling of the case the directory results exists already 2004-06-03 17:40 burger * man/tracker.Rd: modified useage to be consistent with required default name for tracker object 2004-06-03 17:32 burger * man/inspect.Rd: added seealso section 2004-06-03 17:32 burger * man/tracker.Rd: added sealso section, clarified comments, added one sentence to description 2004-06-03 16:54 burger * R/inspector.r: added methods dependency 2004-06-03 16:50 burger * man/RUnit-internal.Rd: added writeBeginHtml & writeEndHtml 2004-06-03 16:37 burger * INDEX: initial commit 2004-06-03 16:35 burger * inst/doc/00Index.dcf: updated 2004-06-03 16:05 kjuen * inst/examples/runitc2f.r: example extended 2004-06-03 16:05 kjuen * man/runit.Rd: small improvements 2004-06-03 15:30 kjuen * man/runit.Rd: random number generator behaviour documented 2004-06-03 15:15 kjuen * inst/doc/RUnit.Rnw: junk character that made texi2dvi fail removed 2004-06-03 15:13 kjuen * man/: runit.Rd, textProtocol.Rd: print and summary documentation improved 2004-06-03 13:59 burger * tests/runitRUnit.r: added test cases 2004-06-03 13:47 burger * tests/: runitHTMLProtocol.r, runitTextProtocol.r: initial commit, simple test cases, currently only checked if all input arguments are checked correctly 2004-06-02 18:53 burger * R/: htmlProtocol.r, textProtocol.r: added precondition checks 2004-06-02 18:51 burger * DESCRIPTION: updated patch level to 0.3.2: updated Seawve file, added preconditon checks 2004-06-02 18:40 burger * inst/doc/RUnit.Rnw: corrected errors in R code which incurred R CMD check error 2004-06-01 18:11 burger * inst/examples/runitc2f.r: initial commit, simple example test case, required for correct automatic Sweave translation 2004-05-27 11:37 koenig * R/runit.r: random generator set to kind=Marsaglia-Multicarry, normal.kind=Kinderman-Ramage (default before R-1.8.1 2004-05-25 11:07 kjuen * inst/NAMESPACE: exports of generic print and summary functions corrected 2004-05-25 11:07 kjuen * R/textProtocol.r: type fixed in summary function 2004-05-25 11:06 kjuen * R/runit.r: code that attempts to clean up the global environment after the test runs removed, because it did not work with R-1.9 (because of some namespace stuff that I do not understand) 2004-05-25 11:04 kjuen * R/htmlProtocol.r: junk code removed 2004-05-19 21:08 burger * DESCRIPTION: updated patch level to 0.3.1, version presented at useR 2004-05-19 14:42 koenig * inst/doc/RUnit.Rnw: E-Mail adresses changed 2004-05-19 14:39 koenig * inst/doc/RUnit.Rnw: company name and E-Mail added 2004-05-19 14:12 kjuen * inst/doc/RUnit.Rnw: some details improved and section that explains test case execution added 2004-05-19 12:48 kjuen * R/testLogger.r: debug print statement removed 2004-05-19 11:26 burger * inst/doc/RUnit.Rnw: added library(RUnit) before example code 2004-05-19 11:24 burger * man/RUnit-internal.Rd: added newline 2004-05-19 11:24 burger * R/exportHTML.r: added API doc tags, code polish for better readability 2004-05-19 11:12 burger * man/RUnit.Rd: updated, added links, removed unused tags 2004-05-19 11:09 burger * man/: tracker.Rd, printHTML.trackinfo.Rd: added CVS header 2004-05-19 11:08 burger * man/: tracker.Rd, inspect.Rd: minor text changes 2004-05-19 11:07 burger * man/printHTML.trackinfo.Rd: fixed spelling of function name 2004-05-19 11:04 burger * man/RUnit-internal.Rd: initial commit, list all private functions not covered in the docs 2004-05-19 09:46 koenig * man/: inspect.Rd, printHTML.trackinfo.Rd, tracker.Rd: initial release for the documentation of the inspector 2004-05-18 23:17 burger * inst/doc/RUnit.pdf: updated 2004-05-18 23:17 burger * inst/doc/RUnit.Rnw: corrected missing end closure 2004-05-18 21:46 burger * man/: runit.Rd, textProtocol.Rd: typo corrections 2004-05-18 21:45 burger * inst/doc/RUnit.Rnw: removed duplicate abstract, typo corrections 2004-05-18 19:58 burger * inst/NAMESPACE: removed Copyright notice, removed class &method export directive 2004-05-18 19:49 burger * man/: RUnit.Rd, checkFuncs.Rd, runit.Rd: added newline in lats line: suggested by R CMD check 2004-05-18 19:47 burger * DESCRIPTION: removed 2nd maintainer entry: not allowed by R CMD check 2004-05-18 19:02 burger * DESCRIPTION: added splines dependency, added poster, added more Rd files 2004-05-18 16:58 burger * inst/doc/RUnit.Rnw: added some lines to Motivation, added Future Ideas 2004-05-18 16:34 koenig * inst/doc/RUnit.Rnw: enhanced for the code inspector 2004-05-18 13:24 kjuen * R/runit.r: sanity check of looking for a 'runit' call in a test function removed because it is not necessary anymore 2004-05-18 13:22 kjuen * R/testLogger.r: a dot prepended to getError and newTestLogger to mark them as internal functions 2004-05-18 13:21 kjuen * R/runit.r: bugfix in .executeTestCase: setUp and tearDown are now checked for errors. typo fixed in the code that copes with errors occuring while sourcing a test file 2004-05-18 13:18 kjuen * R/: htmlProtocol.r, textProtocol.r: trace back writing improved 2004-05-18 13:16 kjuen * man/textProtocol.Rd: documentation of printHTMLProtocol added 2004-05-18 13:15 kjuen * inst/doc/RUnit.Rnw: my version of the introduction added 2004-05-17 19:54 burger * inst/doc/RUnit.Rnw: added abstract 2004-05-17 19:53 burger * inst/doc/RUnit.pdf: initial commit 2004-05-17 15:40 kjuen * R/htmlProtocol.r: some minor modifications 2004-05-17 15:40 kjuen * R/runit.r: default test file regexp in defineTestSuite improved 2004-05-17 15:16 burger * R/: exportHTML.r, html.r, inspector.r: added GPL preamble 2004-05-14 18:38 kjuen * R/textProtocol.r: useless code deleted 2004-05-14 18:38 kjuen * R/runit.r: small bugfix in isValidTestSuite 2004-05-14 18:37 kjuen * R/htmlProtocol.r: first usable version 2004-05-14 18:29 kjuen * R/html.r: small improvement of writeBeginTable 2004-05-11 15:34 koenig * R/exportHTML.r: moved html helper function to html.r 2004-05-11 15:33 koenig * R/html.r: initial release. helper function for generating html pages 2004-05-10 23:09 burger * R/: checkFuncs.r, runit.r, testLogger.r, textProtocol.r: added CVS tag 2004-05-10 22:58 burger * R/runit.r: renamed argument to isValid to testSuite; ts is a time series object 2004-05-10 22:57 burger * R/textProtocol.r: added API documentation tags; renamed arguments to required defaults for print & summary methods 2004-05-10 22:56 burger * man/runit.Rd: added authors and keyword paragraphs; changed ts to testSuite argument name and documented it 2004-05-10 22:54 burger * man/textProtocol.Rd: added authors and keyword paragraphs; added ... argument description 2004-05-10 22:52 burger * man/checkFuncs.Rd: added authors and keyword paragraphs 2004-05-10 22:22 burger * inst/doc/RUnit.Rnw: fixed broken LaTeX code: missing begin environment 2004-05-10 22:21 burger * inst/doc/00Index.dcf: initial commit, required by R CMD check; needs to be updated with this directories contents 2004-05-10 22:07 burger * DESCRIPTION: updated to minor level 0.2.0: CodeInspector code added, documentation pages added; package passes R CMD check 2004-05-10 22:05 burger * man/: checkFuncs.Rd, runit.Rd, textProtocol.Rd: changed examples such that no Errors are thrown, and packages passes R CMD check 2004-05-10 18:51 kjuen * R/: 00Init.r, initGeneratedRUnit.r, utilities.r: removed 2004-05-10 18:49 koenig * R/inspector.r: initial release for tracking tool 2004-05-10 18:48 koenig * R/exportHTML.r: initial release for exporting results to HTML pages 2004-05-10 16:52 kjuen * man/: checkFuncs.Rd, runit.Rd, textProtocol.Rd: first attempt to cope with Rs documentation tool 2004-05-10 16:51 kjuen * R/runit.r: test suite objects now have a class attribute 2004-05-10 16:50 kjuen * R/testProtocol.r: renamed to textProtocol 2004-05-10 16:50 kjuen * R/textProtocol.r: renamed from testProtocol 2004-05-07 17:51 kjuen * R/checkFuncs.r: ... added to checkEquals so that further args can be passed to all.equal 2004-05-07 15:45 kjuen * R/testProtocol.r: S3 generic methods 'print' and 'summary' added 2004-05-07 15:44 kjuen * R/testLogger.r: getErrors improved 2004-05-06 20:46 burger * DESCRIPTION: added GPL 2 licence text, some code improvements 2004-05-06 20:43 burger * COPYING: GPL 2, downloaded from http://www.gnu.org/copyleft/gpl.html 2004-05-06 19:39 kjuen * R/testProtocol.r: license header added, optional args added to configure printTextProtocol 2004-05-06 19:38 kjuen * R/testLogger.r: license header added, traceback removed for Failures 2004-05-06 19:37 kjuen * R/runit.r: license header added, file regexp in runTestFile improved 2004-05-06 19:37 kjuen * R/checkFuncs.r: license header added 2004-05-05 21:35 burger * R/runit.r: changed to default set in R >= 1.8.0 2004-05-05 20:08 burger * DESCRIPTION: updated version to 0.1.0, runit test framework from EpiR.tools revised and commited here 2004-05-05 19:30 kjuen * R/: checkFuncs.r, runit.r, testLogger.r, testProtocol.r: initial check in of rewritten version 2004-04-06 11:27 burger * DESCRIPTION, R/00Init.r, R/initGeneratedRUnit.r, R/utilities.r, inst/NAMESPACE, inst/doc/RUnit.Rnw, man/RUnit.Rd, tests/runitRUnit.r: Initial revision 2004-04-06 11:27 burger * DESCRIPTION, R/00Init.r, R/initGeneratedRUnit.r, R/utilities.r, inst/NAMESPACE, inst/doc/RUnit.Rnw, man/RUnit.Rd, tests/runitRUnit.r: initial import: preparation for public CRAN package, will take on most of EpiR.tools functionality �����������������������������������������������������������RUnit/NEWS������������������������������������������������������������������������������������������0000644�0001751�0000144�00000013420�11444146730�012034� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ Dear Emacs, please make this -*-Text-*- mode! ************************************************** * * * RUnit * * * ************************************************** Changes in RUnit 0.4.26 o isValidTestSuite: fixed insufficient if expression handling, reported by Rich Calaway; extended validity checks Changes in RUnit 0.4.25 o enable redirection of error and log messages to file, controlled via new global option 'outfile', (following a suggestion by Seth Falcon) Changes in RUnit 0.4.24 o added RUnit specific options 'verbose' and 'silent' to global options list to allow control of test log output o moved unit tests from tests/ to inst/unitTests o added Makefile for executing unit tests (using R wiki example) Changes in RUnit 0.4.23 o vignette: fixed function name in example code, reported by Blair Christian o init .testLogger to avoid R CMD check NOTE messages o allow verbosity of console output log to be controlled: added 'verbose' argument to runTestFile and runTestSuite (following a suggestion by Seth Falcon) o test logger object declared as S3 class 'TestLogger' Changes in RUnit 0.4.22 o clarified applicable license: GPL 2 o defineTestSuite: gained some argument checks o isValidTestSuite: check for empty name o includeTracker: fix `<- if` handling Changes in RUnit 0.4.21 o documentation issues corrected, identified by new R 2.9.0 devel Rd parser Changes in RUnit 0.4.20 o test protocol generation on Mac OS X failed due to incorrect code to identify 'gcc' version o Rd documentation updated Changes in RUnit 0.4.19 o test protocol now states check number per test case o changed check for object class to is() to allow derived class objects to pass (suggested by Philippe Grosjean) o removed start up message Changes in RUnit 0.4.18 o seq_along introduced instead of seq( ) for efficiency and R version dependency set to 2.4.0 when seq_along was introduced o some small changes to avoid warnings with options(warnPartialMatchArgs=TRUE) Changes in RUnit 0.4.17 o corrected documentation example code Changes in RUnit 0.4.16 o changed the environment test code files are evaluated, now a new environment outside the RUnit namespace is utilized, allowing e.g. setClass calls without specifying where=.GlobalEnv o updated documentation to use encoding latin1 o use LazyLoad: yes instead of SaveImage:yes (to be deprecated for R 2.6.0) o internal error handler rewritten to be more failure robust o added new test cases for .setUp and .tearDown, extended tests to cover S4 class and method behaviour in check* functions o example on S4 virtual class testing added o utility function to compare to RUnitTestResult objects added: concept idea for comparing and optimizing test suite performance (share/R/checkCode.r) Changes in RUnit 0.4.15 o compatibility to R 1.9.0 as declared in DESCRIPTION: removed calls to isTRUE as this was introduced only in R 2.1.0, replaced where needed by identical(TRUE, x) o fixed printHTMLProtocol: on Windows Makeconf does not exist so CC compiler used by R cannot be queried this way (reported by Tobias Verbeke) Changes in RUnit 0.4.14 o stated all package dependencies in DESCRIPTION, required for R 2.4.0 compatibility Changes in RUnit 0.4.13 o allow the RNG to be set by the user via new arguments 'rngKind' and 'rngNormalKind' to functions defineTestSuite and runTestFile (patch by Seth Falcon) o fixed exit status: RNG kind was left changed after runTestSuite execution in user workspace o email contact address modified Changes in RUnit 0.4.12 o allow *.R test case file extension (suggested by Gregor Gorjanc) o fixed code typo in example vignette (spotted by Gregor Gorjanc) Changes in RUnit 0.4.11 o checkException: argument silent added to allow to suppress error messages emitted by the failing function o inspect: added argument track, which _has_ to be provided at each invocation to avoid recursive default argument reference call errors (experimental: subject to change if this leads to new incompatibilities) Changes in RUnit 0.4.9 o checkEquals has new compatibility argument checkNames Changes in RUnit 0.4.8 o checkIdentical added, to allow to check for exact identity Changes in RUnit 0.4.7 o update for checkEqualsNumeric to be compatible with R 2.3.0 Changes in RUnit 0.4.5 o improvements to error detection in runTestSuite Changes in RUnit 0.4.4 o changed maintainer Changes in RUnit 0.4.2 o checkTrue: corrected handling of named logical arguments Changes in RUnit 0.4.1 o printHTMLProtocol has new parameter 'testFileToLinkMap' to allow to provide a function to add dynamically generated URLs for each test case file, e.g. for use with CVSweb Changes in RUnit 0.4.0 o New 'error' category DEACTIVATED introduced: If the function DEACTIVATED is inserted into a test function the function stops at that point and is reported as deactivated in the test protocol. o New function 'getErrors' which takes a list of type 'RUnitTestData' and returns some very basic error information of a test run. o The name of the currently executed test function is written to standard out. o 'printHTMLProtocol' fixed such that it does not produce a warning anymore. o Dependency on package 'splines' removed. o Various small fixes of the documentation. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/INDEX�����������������������������������������������������������������������������������������0000644�0001751�0000144�00000001055�10057633671�012134� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit-internal Internal functions RUnit RUnit - Package Description checkFuncs RUnit check functions inspect Track the executed code lines of a function or method. printHTML.trackInfo Write HTML pages of the tracking result. runTestSuite Definition and execution of RUnit test suites. textProtocol Printing a plain text or HTML version of an RUnit test run. tracker Tracking the results of the inspect process. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/�����������������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�11444151274�012311� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/share/�����������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�11444151274�013413� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/share/R/���������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�11444151274�013614� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/share/R/checkCode.r����������������������������������������������������������������������0000644�0001751�0000144�00000011742�11274330127�015651� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������###################################################################### ## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: checkCode.r,v 1.3 2009/11/04 16:48:23 burgerm Exp $ checkCodeFiles <- function(fileName) { ##@bdescr ## utility function for code checks of files outside usual R/ folder structure ## requires package codetools ##@edescr ## ##@in fileName : [character] vector of file names (including path, relative to pwd or absolute) ##@ret : [list] with elements per function, that incurred any warning ## ##@depends : codetools ## ##@codestatus : untested ## return list retList <- list() ## initialized before ls() call to avoid listing ok <- x <- c() tmpRetEnv <- new.env() tmpRet <- NULL ## generate listing of existing objects before first source'ing lsTmp <- lsInit <- ls() sapply(fileName, function(x) { cat("\n file ",x) ok <- try(utils::capture.output(source(x, local=TRUE, echo=FALSE))) if (inherits(ok, "try-error")) { cat("\n file",x,"could not be sourced:", geterrmessage(), "\n") return() } newElements <- setdiff(ls(), lsTmp) cat("\n functions",paste(newElements, collapse=", ")) lsTmp <- ls() sapply(newElements, function(x) { ok <- try(get(x)) if (!inherits(ok, "try-error") && identical(mode(ok), "function")) { cat("\n ",x," (",is(ok)[1],"): ",sep="") ## this function will be used in signalUsageIssue w$warn reportFunc <- function(x) { cat(x) assign("tmpRet", c(tmpRet, x), pos=parent.env(tmpRetEnv)) } codetools::checkUsage(ok, report=reportFunc, all=TRUE) if (!is.null(tmpRet)) { retList[[length(retList) + 1]] <<- tmpRet names(retList)[length(retList)] <<- x } tmpRet <<- NULL } }) }) return(invisible(retList)) } checkCodeFolders <- function(path=".") { ##@bdescr ## utility function ## code checks of all .[RrSs] files found in one or more folders ## requires package codetools ##@edescr ## ##@in path : [character] ##@ret : [list] ## ##@depends : codetools ## ##@codestatus : untested stopifnot(require(codetools)) if (!is(path, "character")) { stop("argument 'path' has to be of type 'character'.") } if (!all(file.exists(path))) { stop("argument 'path' has to contain existing folder(s).") } fNames <- list.files(path=path, pattern="\\.[rRsS]$", full.names=TRUE) checkCodeFiles(fNames) } checkCodeSweave <- function(path=".") { ##@bdescr ## utility function ## code checks of all .[RS]nw files found in one or more folders ## experimental: does not convert extracted code chunks to closures ## thus only functions defined inside a chunk but nut all of the chunk code is checked ## ## requires package codetools ##@edescr ## ##@in path : [character] ##@ret : [list] ##@depends : codetools ## ##@codestatus : untested ## Issue: ## local path e.g. 'RUnit/inst/doc' ## is no expanded to full path ## which I would wnat to use as absolute path ## in the Stangle call stopifnot(require(utils)) stopifnot(require(codetools)) if (!is(path, "character")) { stop("argument 'path' has to be of type 'character'.") } if (!all(file.exists(path))) { stop("argument 'path' has to contain existing folder(s).") } browser() path <- path.expand(path) pwd <- getwd() if (length(path)) { if (path == ".") { path <- pwd } ## do we have a local path rather then an absolute ## how to infer correct absolute path? } fName <- list.files(path=path, pattern="\\.[RS]nw$", full.names=TRUE) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") tmpDir <- file.path(tempdir(), timeStamp) print(tmpDir) if(!file.exists(tmpDir)) { stopifnot(dir.create(tmpDir, recursive=TRUE)) } #on.exit(unlink(tmpDir, recursive=TRUE)) ## change to temp folder to dump Stangle output therein setwd(tmpDir) on.exit(setwd(pwd), add=TRUE) codeFiles <- unlist(sapply(fName, function(x) { Stangle(x) x <- basename(x) gsub("[RS]nw$", "R", x) })) ## codeFiles <- file.path(tmpDir, codeFiles) checkCodeFiles(codeFiles) } ������������������������������RUnit/inst/share/R/compareRUnitTestData.r�����������������������������������������������������������0000644�0001751�0000144�00000010770�11274330537�020050� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������###################################################################### ## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: compareRUnitTestData.r,v 1.4 2009/11/04 16:52:47 burgerm Exp $ compare <- function(td1, td2, tolerance=100) { ##@bdescr ## compare two test suite result data objects obtained ## on the same test suite ## identify timing differences exceeding 'tolerance' [seconds] ##@edescr ## ## ##@in td1 : [list] of S3 class 'RUnitTestData' ##@in td2 : [list] of S3 class 'RUnitTestData' ##@in tolerance : [numeric] positive scalar ##@ret : [data.frame] ## ##@codestatus : untested ## preconditions if (!is(td1, "RUnitTestData")) { stop("argument 'td1' has to be of class 'RUnitTestData'.") } if (!is(td2, "RUnitTestData")) { stop("argument 'td2' has to be of class 'RUnitTestData'.") } if (length(tolerance) != 1 || is.na(tolerance) || tolerance < 0) { stop("argument 'tolerance' has to be positive scalar.") } ## helper functions commonNames <- function(x1, x2) { return(intersect(names(x1), names(x2))) } compareTiming <- function(x1, x2, tol=0) { d <- x1 - x2 if (abs(d) > tol) { return(d) } else { return(as.numeric(0)) } } comparePerSourceFile <- function(sf1,sf2, tol=0) { ## FIXME ## check if test case file was considered in this suite ## i.e. test case file name can be in list albeit it ## was not executed in the scenario ## thus list is empty if (length(sf1) == 0 | length(sf2) == 0) { cat("\n skipped empty result set:", sf1) return(NULL) } commonTests <- commonNames(sf1, sf2) t(sapply(commonTests, function(x, obj1, obj2) { ##cat("\n test:", x, "\n") if(obj1[[x]][["kind"]] == obj2[[x]][["kind"]]) { if (obj1[[x]][["kind"]] == "success") { return(c(x, obj1[[x]][["kind"]], obj1[[x]][["time"]], obj2[[x]][["kind"]], obj2[[x]][["time"]], compareTiming(obj1[[x]][["time"]], obj2[[x]][["time"]], tol=tol))) } else { return(c(x, obj1[[x]][["kind"]], as.numeric(NA), obj2[[x]][["kind"]], as.numeric(NA), as.numeric(NA))) } } else { ## no timing delta ## should check for timing in second case ## obj2[[x]][["time"]]) return(c(x, obj1[[x]][["kind"]], as.numeric(NA), obj2[[x]][["kind"]], as.numeric(NA), as.numeric(NA))) } }, obj1=sf1, obj2=sf2)) } comparePerSuite <- function(s1,s2, tol=0) { ## absolute file names recorded, strip path commonFiles <- intersect(basename(names(s1[["sourceFileResults"]])), basename(names(s2[["sourceFileResults"]]))) do.call("rbind", sapply(commonFiles, function(x, obj1, obj2) { ## match exact file name in abs. name idx1 <- match(x, basename(names(obj1))) idx2 <- match(x, basename(names(obj2))) if (length(idx1) != 1 || is.na(idx1) || length(idx2) != 1 || is.na(idx2)) { stop("ambiguous file name.") next; } comparePerSourceFile(obj1[[idx1]], obj2[[idx2]], tol=tol) }, obj1=s1[["sourceFileResults"]], obj2=s2[["sourceFileResults"]]) ) } ## main ## test suites to compare commonTestSuites <- commonNames(td1, td2) res <- matrix(ncol=6, nrow=0) colnames(res) <- c("TestCase", "Suite1 State", "Suite1 Timing", "Suite2 State", "Suite2 Timing", "Delta") for (ti in seq_along(commonTestSuites)) { res <- rbind(res, comparePerSuite(td1[[commonTestSuites[ti]]], td2[[commonTestSuites[ti]]], tol=tolerance)) } ## postcondition return(res) } ��������RUnit/inst/examples/��������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�11444151274�014127� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/examples/runitc2f.r����������������������������������������������������������������������0000644�0001751�0000144�00000003135�11274330634�016050� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## This is a very trivial demo of ## the RUnit test case execution system: ## --------------------------------- ## functions to be tested (usually defined in a different ## file from where the test cases are located): ## centigrade to Fahrenheit c2f <- function(c) return(9/5 * c + 32) ## Fahrenheit to centigrade f2c <- function(f) return(5/9 * f - 32) ## ups, a bug (brackets missing) ## test functions: ## --------------------- .setUp <- function() { ## called before each test case, see also .tearDown() print(".setUp") } test.c2f <- function() { checkEquals(c2f(0), 32) checkEquals(c2f(10), 50) ## check that an error is created for a bogus argument checkException(c2f("xx")) } test.f2c <- function() { checkEquals(f2c(32), 0) checkEquals(f2c(50), 10) ## check that an error is created for a bogus argument checkException(f2c("xx")) } test.errordemo <- function() { stop("this is just to show what an error looks like as opposed to a failure") } ## How to run the tests (do not uncomment in this file, ## but execute the commands at the R prompt): ## All you have to do is to adapt the directory locations. ## ------------------------------------------------ ## define the test suite: #testsuite.cf <- defineTestSuite("cfConversion", dirs="directoryOfThisFile") ## run test suite: #testResult <- runTestSuite(testsuite.cf) ## print text protocol to console: #printTextProtocol(testResult) ## print HTML version to a file: #printHTMLProtocol(testResult, fileName="someFileName.html") ## In this case we also have a shortcut #runTestFile("directoryOfThisFile/runitcfConversion.r") �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/examples/correctTestCase.r���������������������������������������������������������������0000644�0001751�0000144�00000001731�11171574402�017410� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: correctTestCase.r,v 1.3 2009/04/16 09:23:14 burgerm Exp $ test.correctTestCase <- function() { checkTrue( TRUE) checkTrue( !identical(TRUE, FALSE)) } ���������������������������������������RUnit/inst/examples/runitVirtualClassTest.r���������������������������������������������������������0000644�0001751�0000144�00000010113�11274330665�020650� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## $Id: runitVirtualClassTest.r,v 1.3 2009/11/04 16:54:13 burgerm Exp $ ## example code for test cases for S4 virtual class methods ## the following class definition code would be part of a package or script ## ## execute these test cases via e.g. ## testSuite <- defineTestSuite("VirtualClassTest", ## file.path(yourSrcPath, "RUnit/inst/examples"), ## "runitVirtual") ## testData <- runTestSuite(testSuite) ## printTextProtocol(testData) ## package 'methods' is usually loaded, but make sure it is checkTrue(require(methods)) ## define class className <- "MyVirtualBaseClass" setClass(className, representation("VIRTUAL", x = "numeric", y = "numeric", description = "character"), validity = NULL, sealed = FALSE, where = .GlobalEnv) if (!isGeneric("getX")) { setGeneric("getX", function(object, ...) standardGeneric("getX"), useAsDefault=TRUE, where=.GlobalEnv, valueClass="numeric") } setMethod("getX", signature=className, function(object) return(object@x), where=.GlobalEnv) if (!isGeneric("setX<-")) { setGeneric("setX<-", function(object, value) standardGeneric("setX<-"), useAsDefault=TRUE, where=.GlobalEnv) } setMethod("setX<-", signature=signature(object=className, value="numeric"), function(object, value) { if (length(value) < 1) { stop("value has to contain at least one element.") } if (any(is.na(value))) { stop("value may not contain NA(s).") } object@x <- value return(object) }, where=.GlobalEnv) testMyVirtualBaseClass.getX <- function() { ##@bdescr ## create a derived class with no own method definitions ## which inherits parent class methods that can then be checked ## ## getter test case ##@edescr testClassName <- "MyDerivedTestClass" setClass(testClassName, representation("MyVirtualBaseClass"), validity = NULL, sealed = FALSE, where = .GlobalEnv) on.exit(removeClass(testClassName, where=.GlobalEnv)) ## system constructor this <- new(testClassName) ## constructor call succeeded? checkTrue( is(this, testClassName)) ret <- getX(this) checkTrue( is(ret, "numeric")) ## class default checkEquals( ret, numeric(0)) } testMyVirtualBaseClass.setX <- function() { ##@bdescr ## setter test case ## also check correct handling of invalid arguments ##@edescr testClassName <- "MyDerivedTestClass" setClass(testClassName, representation("MyVirtualBaseClass"), validity = NULL, sealed = FALSE, where = .GlobalEnv) on.exit(removeClass(testClassName, where=.GlobalEnv)) ## system constructor this <- new(testClassName) ## constructor call succeeded? checkTrue( is(this, testClassName)) testSeq <- 1:23 setX(this) <- testSeq ret <- getX(this) checkTrue( is(ret, "numeric")) checkEquals( ret, testSeq) ## error handling checkException( setX(this) <- numeric(0)) checkException( setX(this) <- as.numeric(NA)) checkException( setX(this) <- c(1:4, NA)) } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/doc/�������������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�11444151274�013056� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/doc/RUnit.tex����������������������������������������������������������������������������0000644�0001751�0000144�00000050710�11444151273�014643� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% -*- mode: noweb; noweb-default-code-mode: R-mode; -*- % % $Id: RUnit.Rnw,v 1.22 2009/11/25 15:12:11 burgerm Exp $ % % %\VignetteIndexEntry{RUnit primer} %\VignetteKeywords{Unit Testing, Code Inspection, Programming} %\VignetteDepends{methods, splines} %\VignettePackage{RUnit} \documentclass[12pt, a4paper]{article} %\usepackage{amsmath,pstricks} \usepackage{hyperref} %\usepackage[authoryear,round]{natbib} %\parskip=.3cm \oddsidemargin=.1in \evensidemargin=.1in \headheight=-.3in \newcommand{\scscst}{\scriptscriptstyle} \newcommand{\scst}{\scriptstyle} \newcommand{\Rfunction}[1]{{\texttt{#1}}} \newcommand{\Robject}[1]{{\texttt{#1}}} \newcommand{\Rpackage}[1]{{\textit{#1}}} %\makeindex % \usepackage{/mnt/local/R/lucid/amd64/R-2.12.0-devel_100914/lib64/R/share/texmf/tex/latex/Sweave} \begin{document} \title{RUnit - A Unit Test Framework for R} \author{Thomas K\"onig, Klaus J\"unemann, and Matthias Burger\\Epigenomics AG} \maketitle \tableofcontents \section*{Abstract} \label{section:abstract} Software development for production systems presents a challenge to the development team as the quality of the coded package(s) has to be constantly monitored and verified. We present a generic approach to software testing for the R language modelled after successful examples such as JUnit, CppUnit, and PerlUnit. The aim of our approach is to facilitate development of reliable software packages and provide a set of tools to analyse and report the software quality status. The presented framework is completely implemented within R and does not rely on external tools or other language systems. The basic principle is that every function or method is accompanied with a test case that queries many calling situations including incorrect invocations. A test case can be executed instantly without reinstalling the whole package - a feature that is necessary for parallel development of functionality and test cases. On a second level one or more packages can be tested in a single test run, the result of which is reported in an well structured test protocol. To verify the coverage of the test framework a code inspector is provided that monitors the code coverage of executed test cases. The result of individual test invocations as well as package wide evaluations can be compiled into a summary report exported to HTML. This report details the executed tests, their failure or success, as well as the code coverage. Taking it one step further and combining the build system with a development and release procedure with defined code status description this approach opens the way for a principled software quality monitoring and risk assessment of the developed application. For our code development we have utilised the described system with great benefit w.r.t.\ code reliability and maintenance efforts in a medium sized development team. \section{Introduction} The importance of software testing can hardly be overrated. This is all the more true for interpreted languages where not even a compiler checks the basic consistency of a program. Nonetheless, testing is often perceived more as a burden than a help by the programmer. Therefore it is necessary to provide tools that make the task of testing as simple and systematic as possible. The key goal of such a testing framework should be to promote the creation and execution of test cases to become an integral part of the software development process. Experience shows that such a permanently repeated code - test - simplify cycle leads to faster and more successful software development than the usually futile attempt to add test cases once the software is largely finished. This line of thought has been pushed furthest by the Extreme Programming \cite{xp} and Test-First paradigms where test cases are viewed as the essential guidelines for the development process. These considerations lead to various requirements that a useful testing framework should satisfy: \begin {itemize} \item {Tests should be easy to execute.} \item {The results should be accessible through a well structured test protocol.} \item{It should be possible to execute only small portions of the test cases during the development process.} \item{It should be possible to estimate the amount of code that is covered by some test case.} \end {itemize} %\paragraph{Background} %\label{paragraph:Background} Testing frameworks that address these aspects have been written in a variety of languages such as Smalltalk, Java, C++ and Python. In particular, the approach described in \cite{beck} has turned out to be very successful, leading -- among others -- to the popular JUnit library for Java \cite{junit}, which has been ported to many other languages (see \cite{xp} for an extensive list of testing frameworks for all kinds of languages). Accordingly, the RUnit package (available at sourceforge \cite{runit-sf}) is our version of porting JUnit to R, supplemented by additional functionality to inspect the test coverage of some function under question. %\paragraph{Motivation} %\label{paragraph:Motivation} One may wonder why R would need yet another testing framework even though the standard method, namely executing {\it R CMD check} on ones complete package at the shell prompt, is widely accepted and applied. We think, however, that the RUnit approach is more in line with the above listed requirements and can be seen as a complement to the existing process in that: \begin{itemize} \item{test cases are called and executed from the R prompt} \item{the programmer decides which result or functionality to put under testing, e.g.\ formating issues of textual output do not need to matter} \item{test and reference data files need not be maintained separately but are combined into one file} \item{test cases need not be limited to testing/using functionality from one package checked at a time} \end{itemize} Moreover, testing frameworks based on JUnit ports seem to have become a quasi standard in many programming languages. Therefore, programmers new to R but familiar with other languages might appreciate a familiar testing environment. And finally, offering more than one alternative in the important field of code testing is certainly not a bad idea and could turn out useful. Before explaining the components of the RUnit package in detail, we would like to list some of the lessons learned in the attempt of writing useful test suites for our software (a more complete collection of tips relating to a Test-First development approach can be found in \cite{tfg}): \begin{itemize} \item {Develop test cases parallel to implementing your functionality. Keep testing all the time (code - test - simplify cycle). Do not wait until the software is complete and attempt to add test cases at the very end. This typically leads to poor quality and incomplete test cases.} \item{Distinguish between unit and integration tests: Unit tests should be as small as possible and check one unit of functionality that cannot be further decomposed. Integration tests, on the other hand, run through a whole analysis workflow and check the interplay of various software components.} \item{Good test coverage enables refactoring, by which a reorganisation of the implementation is meant. Without regular testing the attitude {\it `I better do not touch this code anymore`} once some piece of software appears to be working is frequently encountered. It is very pleasing and time-saving just to run a test suite after some improvement or simplification of the implementation to see that all test cases are still passing (or possibly reveal some newly introduced bug). This refactoring ability is a key benefit of unit testing leading not only to better software quality but also to better design.} \item{Do not test internal functions but just the public interface of a library. Since R does not provide very much language support for this distinction, the first step here is to clarify which functions are meant to be called by a user of a package and which are not (namespaces in R provide a useful directive for making this distinction, if the export list is selected carefully and maintained). If internal functions are directly tested, the ability of refactoring gets lost because this typically involves reorganisation of the internal part of a library.} \item {Once a bug has been found, add a corresponding test case.} \item{We greatly benefitted from an automated test system: A shell script, running nightly, checks out and installs all relevant packages. After that all test suites are run and the resulting test protocol is stored in a central location. This provides an excellent overview over the current status of the system and the collection of nightly test protocols documents the development progress.} \end{itemize} \section{The RUnit package} \label{section:RUnitPackage} This section contains a detailed explanation of the RUnit package and examples how to use it. As has already been mentioned the package contains two independent components: a framework for test case execution and a tool that allows to inspect the flow of execution inside a function in order to analyse which portions of code are covered by some test case. Both components are now discussed in turn. \subsection{Test case execution} \label{subsection:Testcaseexecution} The basic idea of this component is to execute a set of test functions defined through naming conventions, store whether or not the test succeeded in a central logger object and finally write a test protocol that allows to precisely identify the problems. {\bf Note, that RUnit - by default - sets the version for normal, and all other RNGs to 'Kinderman-Ramage', and 'Marsaglia-Multicarry', respectively. If you like to change these defaults please see {\tt ?defineTestSuite} for argument 'rngNormalKind' and 'rngKind'.} As an example consider a function that converts centigrade to Fahrenheit: \begin{Sinput} c2f <- function(c) return(9/5 * c + 32) \end{Sinput} A corresponding test function could look like this: \begin{Sinput} test.c2f <- function() { checkEquals(c2f(0), 32) checkEquals(c2f(10), 50) checkException(c2f("xx")) } \end{Sinput} The default naming convention for test functions in the RUnit package is {\tt test...} as is standard in JUnit. To perform the actual checks that the function to be tested works correctly a set of functions called {\tt check ...} is provided. The purpose of these {\tt check} functions is two-fold: they make sure that a possible failure is reported to the central test logger so that it will appear properly in the final test protocol and they are supposed to make explicit the actual checks in a test case as opposed to other code used to set up the test scenario. Note that {\tt checkException} fails if the passed expression does not generate an error. This kind of test is useful to make sure that a function correctly recognises error situations instead of silently creating inappropriate results. These check functions are direct equivalents to the various {\tt assert} functions of the JUnit framework. More information can be found in the online help. Before running the test function it is necessary to create a test suite which is a collection of test functions and files relating to one topic. One could, for instance, create one test suite for one R package. A test suite is just a list containing a name, an array of absolute directories containing the locations of the test files, a regular expression identifying the test files and a regular expression identifying the test functions. In our example assume that the test function is located in a file {\tt runitc2f.r} located in a directory {\tt /foo/bar/}. To create the corresponding test suite we can use a helper function: \begin{Sinput} testsuite.c2f <- defineTestSuite("c2f", dirs = file.path(.path.package(package="RUnit"), "examples"), testFileRegexp = "^runit.+\\.r", testFuncRegexp = "^test.+", rngKind = "Marsaglia-Multicarry", rngNormalKind = "Kinderman-Ramage") \end{Sinput} All that remains is to run the test suite and print the test protocol: \begin{Sinput} testResult <- runTestSuite(testsuite.c2f) printTextProtocol(testResult) \end{Sinput} The resulting test protocol should be self explanatory and can also be printed as HTML version. See the online help for further information. Note that for executing just one test file there is also a shortcut in order to make test case execution as easy as possible: \begin{Sinput} runTestFile(file.path(.path.package(package="RUnit"), "examples/runitc2f.r")) \end{Sinput} The creation and execution of test suites can be summarised by the following recipe: \begin{enumerate} \item{create as many test functions in as many test files as necessary } \item{create one or more test suites using the helper function {\tt defineTestSuite}} \item{run the test suites with {\tt runTestSuite}} \item{print the test protocol either with {\tt printTextProtocol} or with {\tt printHTMLProtocol} (or with a generic method like {\tt print} or {\tt summary})} \end{enumerate} We conclude this section with some further comments on various aspects of the test execution framework: \begin{itemize} \item{A test file can contain an arbitrary number of test functions. A test directory can contain an arbitrary number of test files, a test suite can contain an arbitrary number of test directories and the test runner can run an arbitrary number of test suites -- all resulting in one test protocol. The test function and file names of a test suite must, however, obey a naming convention expressible through regular expressions. As default test functions start with {\tt test} and files with {\tt runit}.} \item{RUnit makes a distinction between failure and error. A failure occurs if one of the check functions fail (e.g.~{\tt checkTrue(FALSE)} creates a failure). An error is reported if an ordinary R error (usually created by {\tt stop}) occurs.} \item{Since version 0.4.0 there is a function {\tt DEACTIVATED} which can be used to deactivate test cases temporarily. This might be useful in the case of a major refactoring. In particular, the deactivated test cases are reported in the test protocol so that they cannot fall into oblivion.} \item{The test runner tries hard to leave a clean R session behind. Therefore all objects created during test case execution will be deleted after a test file has been processed.} \item{In order to prevent mysterious errors the random number generator is reset to a standard setting before sourcing a test file. If a particular setting is needed to generate reproducible results it is fine to configure the random number generator at the beginning of a test file. This setting applies during the execution of all test functions of that test file but is reset before the next test file is sourced.} \item{In each source file one can define the parameterless functions {\tt .setUp()} and {\tt .tearDown()}. which are then executed directly before and after each test function. This can, for instance, be used to control global settings or create addition log information.} \end{itemize} \subsection{R Code Inspection} \label{subsection:RCodeInspection} The Code Inspector is an additional tool for checking detailed test case coverage and getting profiling information. It records how often a code line will be executed. We utilise this information for improving our test cases, because we can identify code lines not executed by the current test case code. The Code Inspector is able to handle S4 methods. During the development of the Code Inspector, we noticed, that the syntax of R is very flexible. Because our coding philosophy has an emphasis of maintenance and a clear style, we developed style guides for our R coding. Therefore, one goal for the Code Inspector was to handle our coding styles in a correct manner. This leads to the consequence that not all R expression can be handled correctly. In our implementation the Code Inspector has two main functional parts. The first part is responsible for parsing and modifying the code of the test function. The second part, called the Tracker, holds the result of the code tracking. The result of the tracking process allows further analysis of the executed code. \subsubsection{Usage} The usage of the Code Inspector and the Tracker object is very simple. The following code snippet is an example: \begin{Schunk} \begin{Sinput} > library(RUnit) > foo <- function(x) { + x <- x * x + x <- 2 * x + return(x) + } > test.foo <- function() { + checkTrue(is.numeric(foo(1:10))) + checkEquals(length(foo(1:10)), 10) + checkEqualsNumeric(foo(1), 2) + } > bar <- function(x, y = NULL) { + if (is.null(y)) { + y <- x + } + if (all(y > 100)) { + y <- y - 100 + } + res <- x^y + return(res) + } > track <- tracker() > track$init() > a <- 1:10 > d <- seq(0, 1, 0.1) > resFoo <- inspect(foo(a), track = track) > resBar <- inspect(bar(d), track = track) > resTrack <- track$getTrackInfo() > printHTML.trackInfo(resTrack) \end{Sinput} \end{Schunk} Note, that the tracking object is an global object and must have the name {\tt track}. The {\tt inspect} function awaits a function call as argument and executes and tracks the function. The results will be stored in the tracking object. The result of the function (not of the Tracker) will be returned as usual. The tracking results will received by tr\$getResult(). With {\tt printHTML} the result of the tracking process will be presented as HTML pages. \subsubsection{Technical Details} The general idea for the code tracking is to modify the source code of the function. Therefore, we use the {\tt parse} and {\tt deparse} functions and the capability of R to generate functions on runtime. To track the function we try to include a hook in every code line. That hook calls a function of the tracked object. The information of the tracking will be stored in the closure of the tracking object (actually a function). Because the R parser allows very nested expressions, we didn't try to modify every R expression. This is a task for the future. A simple example for the modifying process is as follow:\\ original: \begin{Schunk} \begin{Sinput} > foo <- function(x) { + y <- 0 + for (i in 1:x) { + y <- y + x + } + return(y) + } \end{Sinput} \end{Schunk} modified: \begin{Schunk} \begin{Sinput} > foo.mod <- function(x) { + track$bp(1) + y <- 0 + track$bp(2) + for (i in 1:x) { + track$bp(4) + y <- y + x + } + track$bp(6) + return(y) + } \end{Sinput} \end{Schunk} Problematic code lines are: \begin{Schunk} \begin{Sinput} > if (any(a == 1)) { + print("do TRUE") + } else print("do FALSE") \end{Sinput} \end{Schunk} This must be modified to \begin{Schunk} \begin{Sinput} > if (any(a == 1)) { + track$bp(2) + print("do TRUE") + } else { + track$bp(3) + print("do FALSE") + } \end{Sinput} \end{Schunk} The problem is the \textit{else} branch, that cannot be modified in the current version. \section{Future Development Ideas} Here we briefly list -- in an unordered manner -- some of the avenues for future development we or someone interested in this package could take: \begin{itemize} \item{extend the {\tt checkEquals} function to handle complex S4 class objects correctly in comparisons. To this end R core has modified check.equal to handle S4 objects.} \item{reimplement the internal structures storing the test suite as well as the test result data as S4 classes.} \item{record all warnings generated during the execution of a test function.} \item{add tools to create test cases automatically. This is a research project but -- given the importance of testing -- worth the effort. See \cite{junit} for various approaches in other languages.} \item{improve the export of test suite execution data e.g.~by adding XML data export support.} \item{add some evaluation methods to the code inspector e.g.~use software metrics to estimate standard measures of code quality, complexity, and performance.} \item{overcome the problem of nested calls to registered functions for code inspection.} \item{allow automatic registration of functions \& methods.} \end{itemize} \begin{thebibliography}{99} % \bibliographystyle{plainnat} \bibitem{xp} http://www.xprogramming.com \bibitem{beck} http://www.xprogramming.com/testfram.htm \bibitem{junit} http://www.junit.org/ \bibitem{tfg} http://www.xprogramming.com/xpmag/testFirstGuidelines.htm \bibitem{runit-sf} https://sourceforge.net/projects/runit/ \end{thebibliography} \end{document} ��������������������������������������������������������RUnit/inst/doc/Makefile�����������������������������������������������������������������������������0000644�0001751�0000144�00000000706�10316755410�014520� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## ## RUnit ## ## utility ## create PDF document from dvi (usefull if R CMD INSTALL fails to build the pdf) ## $Id: Makefile,v 1.1 2005/09/29 12:16:08 burger Exp $ ## all: RUnit.pdf clean RUnit.pdf: RUnit.ps ps2pdf -dEncodeColorImages=false -dColorImageFilter=/FlateEncode -dAutoRotatePages=/None RUnit.ps RUnit.ps: RUnit.dvi dvips RUnit RUnit.dvi: RUnit.tex latex RUnit latex RUnit clean: rm -f RUnit.aux RUnit.log RUnit.toc ����������������������������������������������������������RUnit/inst/doc/RUnit.out����������������������������������������������������������������������������0000644�0001751�0000144�00000000633�11444151274�014652� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������\BOOKMARK [1][-]{section.1}{Introduction}{} \BOOKMARK [1][-]{section.2}{The RUnit package}{} \BOOKMARK [2][-]{subsection.2.1}{Test case execution}{section.2} \BOOKMARK [2][-]{subsection.2.2}{R Code Inspection}{section.2} \BOOKMARK [3][-]{subsubsection.2.2.1}{Usage}{subsection.2.2} \BOOKMARK [3][-]{subsubsection.2.2.2}{Technical Details}{subsection.2.2} \BOOKMARK [1][-]{section.3}{Future Development Ideas}{} �����������������������������������������������������������������������������������������������������RUnit/inst/doc/RUnit.ps�����������������������������������������������������������������������������0000644�0001751�0000144�00000673403�11444151274�014500� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%!PS-Adobe-2.0 %%Creator: dvips(k) 5.98 Copyright 2009 Radical Eye Software %%Title: RUnit.dvi %%CreationDate: Wed Sep 15 16:05:48 2010 %%Pages: 11 %%PageOrder: Ascend %%BoundingBox: 0 0 596 842 %%DocumentFonts: CMR17 CMR12 CMBX12 CMTI12 CMTT12 CMSLTT10 %%DocumentPaperSizes: a4 %%EndComments %DVIPSWebPage: (www.radicaleye.com) %DVIPSCommandLine: dvips RUnit %DVIPSParameters: dpi=600 %DVIPSSource: TeX output 2010.09.15:1605 %%BeginProcSet: tex.pro 0 0 %! /TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin /FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array /BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get }B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr 1 add N}if}B/CharBuilder{save 3 1 roll S A/base get 2 index get S /BitMaps get S get/Cd X pop/ctr 0 N Cdx 0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx sub Cy .1 sub]{Ci}imagemask restore}B/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn /BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put }if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X 1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N /p{show}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 N/Ry 0 N/V{}B/RV/v{ /Ry X/Rx X V}B statusdict begin/product where{pop false[(Display)(NeXT) (LaserWriter 16/600)]{A length product length le{A length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse}forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat{BDot} imagemask grestore}}ifelse B/QV{gsave newpath transform round exch round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M}B/g{0 M} B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p -3 w}B/n{ p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end %%EndProcSet %%BeginProcSet: texps.pro 0 0 %! TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]FontType 0 ne{/Metrics exch def dict begin Encoding{exch dup type/integertype ne{ pop pop 1 sub dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def}ifelse}forall Metrics/Metrics currentdict end def}{{1 index type /nametype eq{exit}if exch pop}loop}ifelse[2 index currentdict end definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def end %%EndProcSet %%BeginProcSet: special.pro 0 0 %! TeXDict begin/SDict 200 dict N SDict begin/@SpecialDefaults{/hs 612 N /vs 792 N/ho 0 N/vo 0 N/hsc 1 N/vsc 1 N/ang 0 N/CLIP 0 N/rwiSeen false N /rhiSeen false N/letter{}N/note{}N/a4{}N/legal{}N}B/@scaleunit 100 N /@hscale{@scaleunit div/hsc X}B/@vscale{@scaleunit div/vsc X}B/@hsize{ /hs X/CLIP 1 N}B/@vsize{/vs X/CLIP 1 N}B/@clip{/CLIP 2 N}B/@hoffset{/ho X}B/@voffset{/vo X}B/@angle{/ang X}B/@rwi{10 div/rwi X/rwiSeen true N}B /@rhi{10 div/rhi X/rhiSeen true N}B/@llx{/llx X}B/@lly{/lly X}B/@urx{ /urx X}B/@ury{/ury X}B/magscale true def end/@MacSetUp{userdict/md known {userdict/md get type/dicttype eq{userdict begin md length 10 add md maxlength ge{/md md dup length 20 add dict copy def}if end md begin /letter{}N/note{}N/legal{}N/od{txpose 1 0 mtx defaultmatrix dtransform S atan/pa X newpath clippath mark{transform{itransform moveto}}{transform{ itransform lineto}}{6 -2 roll transform 6 -2 roll transform 6 -2 roll transform{itransform 6 2 roll itransform 6 2 roll itransform 6 2 roll curveto}}{{closepath}}pathforall newpath counttomark array astore/gc xdf pop ct 39 0 put 10 fz 0 fs 2 F/|______Courier fnt invertflag{PaintBlack} if}N/txpose{pxs pys scale ppr aload pop por{noflips{pop S neg S TR pop 1 -1 scale}if xflip yflip and{pop S neg S TR 180 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{pop S neg S TR pop 180 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{ppr 1 get neg ppr 0 get neg TR}if}{ noflips{TR pop pop 270 rotate 1 -1 scale}if xflip yflip and{TR pop pop 90 rotate 1 -1 scale ppr 3 get ppr 1 get neg sub neg ppr 2 get ppr 0 get neg sub neg TR}if xflip yflip not and{TR pop pop 90 rotate ppr 3 get ppr 1 get neg sub neg 0 TR}if yflip xflip not and{TR pop pop 270 rotate ppr 2 get ppr 0 get neg sub neg 0 S TR}if}ifelse scaleby96{ppr aload pop 4 -1 roll add 2 div 3 1 roll add 2 div 2 copy TR .96 dup scale neg S neg S TR}if}N/cp{pop pop showpage pm restore}N end}if}if}N/normalscale{ Resolution 72 div VResolution 72 div neg scale magscale{DVImag dup scale }if 0 setgray}N/psfts{S 65781.76 div N}N/startTexFig{/psf$SavedState save N userdict maxlength dict begin/magscale true def normalscale currentpoint TR/psf$ury psfts/psf$urx psfts/psf$lly psfts/psf$llx psfts /psf$y psfts/psf$x psfts currentpoint/psf$cy X/psf$cx X/psf$sx psf$x psf$urx psf$llx sub div N/psf$sy psf$y psf$ury psf$lly sub div N psf$sx psf$sy scale psf$cx psf$sx div psf$llx sub psf$cy psf$sy div psf$ury sub TR/showpage{}N/erasepage{}N/setpagedevice{pop}N/copypage{}N/p 3 def @MacSetUp}N/doclip{psf$llx psf$lly psf$urx psf$ury currentpoint 6 2 roll newpath 4 copy 4 2 roll moveto 6 -1 roll S lineto S lineto S lineto closepath clip newpath moveto}N/endTexFig{end psf$SavedState restore}N /@beginspecial{SDict begin/SpecialSave save N gsave normalscale currentpoint TR @SpecialDefaults count/ocount X/dcount countdictstack N} N/@setspecial{CLIP 1 eq{newpath 0 0 moveto hs 0 rlineto 0 vs rlineto hs neg 0 rlineto closepath clip}if ho vo TR hsc vsc scale ang rotate rwiSeen{rwi urx llx sub div rhiSeen{rhi ury lly sub div}{dup}ifelse scale llx neg lly neg TR}{rhiSeen{rhi ury lly sub div dup scale llx neg lly neg TR}if}ifelse CLIP 2 eq{newpath llx lly moveto urx lly lineto urx ury lineto llx ury lineto closepath clip}if/showpage{}N/erasepage{}N /setpagedevice{pop}N/copypage{}N newpath}N/@endspecial{count ocount sub{ pop}repeat countdictstack dcount sub{end}repeat grestore SpecialSave restore end}N/@defspecial{SDict begin}N/@fedspecial{end}B/li{lineto}B /rl{rlineto}B/rc{rcurveto}B/np{/SaveX currentpoint/SaveY X N 1 setlinecap newpath}N/st{stroke SaveX SaveY moveto}N/fil{fill SaveX SaveY moveto}N/ellipse{/endangle X/startangle X/yrad X/xrad X/savematrix matrix currentmatrix N TR xrad yrad scale 0 0 1 startangle endangle arc savematrix setmatrix}N end %%EndProcSet TeXDict begin @defspecial systemdict /pdfmark known{userdict /?pdfmark systemdict /exec get put}{userdict /?pdfmark systemdict /pop get put userdict /pdfmark systemdict /cleartomark get put}ifelse /DvipsToPDF{72.27 mul Resolution div} def/PDFToDvips{72.27 div Resolution mul} def/BPToDvips{72 div Resolution mul}def/BorderArrayPatch{[exch{dup dup type/integertype eq exch type/realtype eq or{BPToDvips}if}forall]}def/HyperBorder {1 PDFToDvips} def/H.V {pdf@hoff pdf@voff null} def/H.B {/Rect[pdf@llx pdf@lly pdf@urx pdf@ury]} def/H.S {currentpoint HyperBorder add /pdf@lly exch def dup DvipsToPDF 72 add /pdf@hoff exch def HyperBorder sub /pdf@llx exch def} def/H.L {2 sub dup/HyperBasePt exch def PDFToDvips /HyperBaseDvips exch def currentpoint HyperBaseDvips sub /pdf@ury exch def/pdf@urx exch def} def/H.A {H.L currentpoint exch pop vsize 72 sub exch DvipsToPDF HyperBasePt sub sub /pdf@voff exch def} def/H.R {currentpoint HyperBorder sub /pdf@ury exch def HyperBorder add /pdf@urx exch def currentpoint exch pop vsize 72 sub exch DvipsToPDF sub /pdf@voff exch def} def @fedspecial end %%BeginFont: CMSLTT10 %!PS-AdobeFont-1.0: CMSLTT10 003.002 %%Title: CMSLTT10 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (<http://www.ams.org>), with Reserved Font Name CMSLTT10. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMSLTT10 known{/CMSLTT10 findfont dup/UniqueID known{dup /UniqueID get 5000800 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMSLTT10 def /FontBBox {-20 -233 617 696 }readonly def /UniqueID 5000800 def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMSLTT10.) readonly def /FullName (CMSLTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -9.46 def /isFixedPitch true def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 34 /quotedbl put dup 36 /dollar put dup 40 /parenleft put dup 41 /parenright put dup 42 /asterisk put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 57 /nine put dup 58 /colon put dup 60 /less put dup 61 /equal put dup 62 /greater put dup 65 /A put dup 66 /B put dup 69 /E put dup 70 /F put dup 72 /H put dup 73 /I put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 92 /backslash put dup 94 /asciicircum put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 120 /x put dup 121 /y put dup 123 /braceleft put dup 125 /braceright put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE33C33655F6FF751F340A8D6C01E3 2E02C24E186BA91B34A1F538959D4450CB683EAE5B034D030186901B458D3777 6B3942BD2E07121385120248891AEC2EB33C4E3A0CF00828D0F130C31A918C18 979FE94379C648EF21ABF659253E43CD1253866F157F1DF85AE7E8714F061B1E ABA3AD094FE8D6293916FA82EE4F486C7E513A06D4C9BE44306A8287970B4ABF B6D1F9274A5A0BB6ECF713ADBD1260D5D6C4420D357FD486470A74B2F0621B59 A9373ABECDBF32FA68AABB66FAB0C970A3354A335FEDDA1C288245E6C890B8DA 3D0EB953283ABFE372221EEB1586B0167F634E3F29CADCAB484B81A243CE1E3F D5106AD6BDB1AEC91123377F816711CB9D5140120FEA84B8205B79D1569509FC 6B671211985CEF51691C45A168740BD826464B2CB0ABC575E7D453161328F80F 3AF1C99EC219010EC6C95E0A8D1909719CF18BE424967E90DF67537220E60C3C 4345B154D08F9EA684710E659DFFB0BA1B7FDDCD519305900A5E1CDA219A6C90 DF8BD712A3686DAB90344E8784C7A9AF3318550285039B701B9FA1D3A3C3B6C2 753F1E794A3463A173C99A9EC0E2AB5737134CEC2C97CD6A37E38692ADB4B131 54697B7BBBB23680C72CE96066D8007B90AF0FC5958232AB4F21826691E9874D 107F47DAC1026298D787989BD77CB43A09FC95F6997DB00D8483AE9C2716CBD3 7CDF02DA34FDA2F0754ED0968270E118DDD8BAAAA65C41D699E2BCC2556AA231 328187D2F50FD518CF458B0BA1F7DBAF4B231CFD61D5DC56335B53C3013BCCC9 85690E19E992ACE55EEF2BA7A75DEE6DC33933C226FC1494269B7CA4CBAE987C 2C787386400172AE3F44AE47115F4117EED866713BDDCA4A7AF658C49F913CB7 308635000043F63BA210410A66E192289592882C477B2EEA0B2A339F0E7CF450 CA0EF79D3A6C28598825CA03FD688DA60C95EF707C6E67CB7E57DE7A80545195 739ACBDF27069F34C9E0216C3D17CFE7A652B910FCC9B9AECC2E646809C22D93 FAFAD465DE794755AFF5BEC17160C9563B5C51D07022E2D3A256FB5CACE131D6 F4B30F591A0419D957D8F0DCAA0A8D65A8D83422AD7C2613FF13A302E152B312 3F1ABB45E42084EAC894FE335C07324849C9736D00C872C4551997DB889AF17A A52C5AA77DEB548B0103B77F65717F70B90C1BBAEA7BCB4959F32851A9882A3F 55673F24103D6BF7FB3AD3EC3CC50FD8FBB4A6B13C3D278174320713A7B327CC A71F01E50840B33D0FC3F5F6A6F2B0F2D0E38494B1C73096A430510F927235FB 69E931DA8CE5415EE88D0248565E3347353621A48F7948AC9EAB5F5057541B50 82BA955D90BBC82E582FD71904445A59186022FB928015235B60830DA59813D0 8DA3FC306C43FF8BB2CB6772B1F7BA3C1AA4B2343E7DA7E065EA53A4E5E28DC8 0790F2D5CFB203CB135A08DCC9702B59A63290444F202756E55B9FB053F773D6 0F69C63E74DE593E49186FF4304E8FA76C3E3006358DE549E946DB69431981E8 1261C9C9A884E4EC708F69E6AF5D22C5BAC49F2AE85903E3D48D03B7B97054F1 D2937A0C685D912D6D20A75A77712164DCBF8FE4D5460DACE139C5A934EEA09F B94DBF168A4BC03A9D689936D833018FF43837DF9519AD10F357F00BC068E737 170FC9FC6715165F733A0B6FADB9ABB48B845167DBE6D771C916577FC2132863 767DC6E3D460E779254194AA690983184D934F5E858C1176B3862B69B42EBE7D EC9AC4E020085D474093F7694C8A8C2025D4B0163E29320C384D62A9F3FBCB1F AB5A374EF3DBA48AC2147A207AEFE8B78BECEBC55C97B538F3A0FF4589D171E3 826342C8A5186224FEE54E4C6AD5EB02BCB4088B132FA1A48362824BEF161235 8E661DCFDFD8429C65CCEF63902D0E07C2FEC1DC2756D942F13FECCB7E8A8048 345338F24B7808E46A04A915C111F939E2669A12FAC0BA4F74B832EAC83EABEE 67E2817C058E69C2010F2572FDD15194CD8DF0FE9F827D349C0444A18D1A86FD 802BC120A5114FA3523C221242C7E767B0AAF6AD15DA1561CE8EB18A2401D71E 20481FA5F1E247CB5288F47795A6A3A3BB186E89EAAC4A54AC91405427136127 5B151203426830F7CADABDB3FF63B40CA29CF8E667E71615869978E99E6F3F07 0170EACDE3DC62DC05681D7680E2E96C30002AE34A4E5EAEDF88577601A82C36 22D625A03B0451D7BBAAAE0C396711500E94A482EA787495073F16A76D1657DC 4EA7C7B83BC30CE7F145B65B6E2ADC207D192CE3B5FEF7031F4BD64F57E1BEFF CCFFE06F1E4ECA48B442DF413766A70DA626359183A9B24C70419487423C816B 4BCB067E661E47E172563090D6328BD738D2B0FE41A0C1D7A47576A79BAFC880 0473229D134F998909898301CEF50A82B627A9A06DF59D0B9C530EC5D877F1E5 220D3A1ABD2ACBFDF1933F92B3137B22B9F95A961D93B729307749A50D8A6403 7AD0F9C40743E39B8D198CFCF7C033D99440D46D821D97545B930EF92E7AE005 27F2FC766FDD4790FD1913C7A13328E73E587618ABD9008022C5C6C23935CEFE B5ECA2CEBA1D25DD846B48423F7186E03B1F61C8F1D5AC95CE03C83B2F221300 7A761D6CB5F7F9251D3F9A7F4B25B99EE7A1347ED3059A811A82A35A033E9B07 A4FB2A95009576F48665605C478E5F6C1B135016FEB4AE6A6BE4B4359836E04D 45AA11366992162973FB6266547C2E570B8F56F6D992D2C0F63950A16839FE10 F56E59D93A37573E3268C5892C9F3358753D1FAD6379E82BE740FA17236E96F7 C53A2FF785FAB86AD17EB1DE8A6AA9C69B91C9D9B43B5188E51F6939FEC21B65 AF17DCE95DD3BA4F1DD51F0BD5E5869A1ECA7398B6E664EB0D189181E9C23012 DC1E54C146842A90909DBEC03B79B58909205F2CB2A7F83C66B437D7F7DB9781 FF0C67F004E979C95B706D8D85255CCD827CF6196D847DB380B56980109E96CA 997157BE78A4F758CE59D78158A854EF2C20099438F74777D3B0298D45BA86D4 3C0AC30C984718FD62ABA0567AF0A70C1DD41953E3E7212D5C562085177E650A 2ACD49940551E3F7619B4CC31DBF67AC15D938619B95DBF66E6D1300B1BB8605 31C4011379FB5388CA49E4A9BD6C921560CB8D513F8716A0733D2A7D77E62D22 A69B54E9048CA168D210816E613CF6357706EF6B118A1263B858B7E19AA98891 43BD675B06C893579957BAB97199ACB82C080593ECB8B66A7334779CC16E4D0D 4AF365CA6AF9727AE29417B61A5FD52452873B1D666044F8E7C1F6C6AA3397B5 94A5780F4005FB5E41698FADD1594B505A58253D68D2AE3320E22165D198050E 425820CC0A43FF1D61F168D87CDD30C14D387610B6CDB63BAA39B3EC9B3CA616 FF1CC679227749DED3DDEA26B4D97C633090DCB8D8A6E5E07E3579E4A99BF1D5 51E43D1D7F139C9CB1D76D8F693A3F23A74EFBE79F01E0B850BC6B6C7F62C2E9 859469A144853434895D73DA6BD2B348A48BA80E79327ABD96539F2EA2209852 E1BF6B0B819D7C68A9A1D0F6F39416E3EC4AC21DCD3C51D3B5B8D417EFAE165F 2A7E0B76E558AC9F685A76FEC7E3C73CD607D9025DE6113BE5D0401887A53910 82A813B026A502B51D484797D9D7E79A25B6624940AEDB4A15F2C73CA1AF60FA 22D15BFBF268EB044FAE17822511AC6580D1D74DBA3C3335217780B29FEE792D 200B00B8CD888A8BFF15D938FC758BB5CD9B3E08E1AC6CD1669E663BE86711A5 892684DFCAF70C11E803164994BDAD89128AAD6461D4558AC2ECA3E05EB56D32 0290AB16A6DF7133DDCBDEAE89C6CD83552792E23CBF567D57E46548EEB0A140 437492B53C14419B6FE7E64AC23923A9E85F56A9DF209DC4E6BCAF1E045F9CA3 BB904BFA150F4083C18B0CB5580450CDB657EA768E71222C71DA911A722AB9D9 E18B6847F417125C40EA8A0CA1F551A4548712D098209C78DF9C3F78605E5402 DA2DBE2218E49B819296D5AC88D17DDBA982E171733D1E9E295B3157C9B90BF1 CE68CB185947D1E3D7544155B741296D14B064BEFD3E6AF25C74006CF6800551 80FCAAEE6FC9105E1674EDFE68C45617D8D3E2264CD395EE94EDD017EB85884F FDF530EDF4F3F14750CA066F149E688FAF8EF4B5FE6AB515CD298E8D170346CA 9B32BAD1D86DC147BD12EBEDF6CE1E749C5B48314F512470A568C172C35CFA41 031E34586A89404CB5372D7B2C7A6D96F420D4D7C2D4C08184F4AF86B4536A90 9367598424112A7B05D7107B23695CBCD569002290599E0FF4EC5C852C31F5F3 9BD56BB840DC17DEEA579E7A7A9F764788D4E3774BD523D21267869224D68891 4523070E80A123B58F7B579866332FC38A41A5915EC06F2D14FBE4A6CAF59AEB 57E98D661637EBB885AA5D74AD429CCFF64E5149815E7350118E6385F4C74E0B 2EB474A6DED021D429F01C9B0634A09250C40E22B3BFE1B7246D18116D585F39 0E06E9B5F27A6CB77C8E9462189CB900CFEF08F798CAE15FBD94587F33816EE9 03FB2DA6826EB69D8C284AB9F7B00630D0420EB6E35E0E288BA25F5C2345C067 22412633898AF99C2FB232D1469025BF262B567F29A05F4816FE8EEF5F02BD79 06202F6A1E3E5D4B3C91BA8D5FF53D5136BF70E5FAEF441A7310CA83721711FC 39EE48BFB2FF287234B1A6102AF146B10A632A53AF97E11FFAC3A2A86BBAE3BD E0459ECF0305366078066F2CC628A3918E775E4236651B3D817AF1684B07A163 A0142D16F55D2FB5F2255A8813B8E54EF3E801E95A4A226AB8C0476AC5EDCAD6 9258ACB6F7C0CBDD298A0B816560622A1871FBE2FAEBFE697A8216A0D8FE30C6 B1BA6C3E975F78182743842E7F851064037394142AC91B2530FB1D511EB20F3F 79EDD8B7E1579D35F6E7B2883C47A46B6C1A458BECD6BE58AAFD834A7D82A553 2FE4E66878E4699856DEDE964F454638F768AEDB595A883E380408F558015FB5 8720954ECE2704AFAD4D62E8BB2657C4FA920D72248B3F762B2F12D125B796AA 1C4BD6B42D766EC1C9B2C7AA4B6A3474BF753742DE8AB76D0AB0DD9A20EE2DCA 0F34CB25995ED3183759CA83ABC32B8BDF0B06EF169252587971F7D37463BFA2 BE36B2E45559DD73DE7CBE29DE92B9BE6B9F8093F934BA311D81E18A8DA92FC3 312E3FAB43C53E803975981F0076EBB8F257C123908450661B6FA79E7ECE98F3 B0A94E0DE3A4DCC8E0FEC106CDEDAA297A75BF1E40F3C2419BF72A644F452E2F 9A8793810319885EB3AB23B1E80E8B62A889311355C73722C18E62711A7E6A16 A5B923408444B13F6522FECA9A60B067EE332B83E1A69CD835C9D69B5D8859D6 91F9276863D2E2E8193641E4239F4ED15E2C482C735BF5434BAA454EC2830C1F 7CF766DAC9E924F17F03093132627673BA3D99DC2DBFC89E5BA032C16D3C1C8D 78B3C464081044DB53C7A29E925F4157EEEE928C8E28EDA5F0A4BB6E0042D8AC 7595C350645118172D04FBF06B2C9A9F3603A54B57999E2960C993724CCD6A09 766BDF73F66E07FCA9BD09079CE8010E6CFECBE2E5DE1EA4E280AB78D5184C11 016385007CB5AC0BC95955A1E88EA1A1D8EFEA886007708BA063F556D9284D4D C764E75CECA51BEE3D35DFCEBF6175953D30FDAC00F23B1721A1DD577945B5E3 8176A21A649D907B5F63C71718ECF32ECCF1B26BF15AF694F1045CF98FC75278 E9782ACD3D83CBDBEE690D29B3176E745AAE436382D258CB22F3DEDD02E441FC 6A9931AC2F61156DE258DAAD5EDAD41E6C0DFC902173168BB4F51DFA7EA615C8 B0F92FDB118378CBAC3D56B6B9BB0883C0C14EAA67396AAA7987222A132B7959 44FC1E9D6DB6D549DFBEF8D2DD8C53DD3B66935FC239E74E2C440CCA13C068EB C4A3B69F499F573D076E2C92E24F2C69B806591B0807CD903E078683854963EE 5125C3640860CEF37BE186DB781475554BFE6C528A9633AD5772BD53244E24AB 42CA2D1123AF45FA257940CE611D83014DF04E60220E9AF27CB2A2247BBB004A F5722A5EF058FDC7DC2B6ED1406649DBAA58DF2ED3A91483D60F11C4A39BAF57 CB1E320A987B790672CDD3E3BEF4A67032244DED2FF4588B2072CDABFEB36009 9F4BCBEE16F811A44CEC77F8AE873C90C0F4C975E51014ECBD45A56A63F034C2 82212977023A132E5C88AAA826D841FDE9CBCE7A01E4B6F0EBDDB9A69EFEBD72 0B41EDA807CEDB791084047624BC11CE10B7A0A311272EFC9E013FA374D97EA5 F7998FD908748CA72D8CABFD0F01220C2114D3B462B22FB71A23B284B1CBC7D9 EA20BE71F8ACCED21F096009A14A7C7B51450BA51514707EB46B9FAAB31CFBEA E1DDA6F5D9AF0B6E7D05A1EEEEECD606427B0F2363D1B882B50140466B9D3CBD D00DB06DDD1BD4681E367DAA4B7C405C6281B67FFF794041738FC6A01D261CDD F6E0A330985F2CA782CBCC02B6F4EE5993434F656B91A51CC03B1D73FFA6629F 14F6075EBFD83B702D8844A96CFB5C14051595BC7DB2218156A6DEDA5C98CAD8 BEB5284D9D9F86406A8C1AE85857185991C360E5F44DEF352A1F301207BE94C2 9A3A11BA468FACB3FA2D683419C44EFDD7C8F1079659F3ABD89D7F168B1591E5 6105F9B3FA481BA953CD34CCFE73E427D3AFC46E5C58C2981198BA284DB8B37A 6647BEAA561799877DD6858FCA71CA6003F2961FAA529906673EA94D82D78116 4DAC81011FD175DA707C1E15D4B6FF19F8720A4E05E6E103E2DE880FA9C192BE C5ABE7C311C2ECCBCE8F9713DBA74AEC37A61C8F21F271B35F0F7C88B182525B A4183377597ACDA9A6E2F181725D427795B975BC4168A408D292CAA484BD1B8C 9DC62E737ABC805C8FCB7E96454DA032B601345570EAE0379BDA84BB6D15D780 42FA1E068A7D62F152B43B788513E13724666FAB4E2B4F04B0448194E46582CE 7389BAF0D1DD4435BAA6B82AC305C04686B89FD51197C721D941BD2893596024 1598E6C2BD84527EDA6FAB782033E4BB4F964FBACD96CAEC3F3CF89CBABF6B4D 4D3AD14A03D4BE931632BB03BC2B92842FAD51A19A756892D5B978DB695D0540 CC9D030C612E2B201D60D09F56332DD0BA1351EE62816C21A35C33DC11B37BE4 D2F164ACD836A5CA1553CBC733E3B159860454B17064B4E22D3764FF6293BC81 CFA3B2325C8E072857F6FF4ADAA8818247D431A28D3C5FDFBFB24A6CAA327AC1 0B3630C84ED9F0D33B8255A3CAA9C5A0C79F7BF6BA3B9801C3BD0B30AEF7CCA9 92F25E332EA97A7CC653C93D1497992D6B76363885B92ADE34C2A33E30A3B1A0 57E9C16D8CEC189565808D3FAC92973C71CDE74DE9D8781CCAF88747758014C4 5B62667D4D2CC5EBEBE77C5AD00C6A69D1819F5A786964501E077EB3BBEA52A4 57729AEDF35253F7E1D31F2DD1587BC15CCFC1B0CA930DA83E2031B099A38158 8D1849E7145AC74777A3C7136DEABB0C787E5A218309A65EC7D128147EDE3AE0 C0AC039B56F767A22555CFCC12DCBC7F5A5A3B4E86EF5A69EEA93DF0BAF2A3F3 7504F5C6A7A67388D2F9045BD755BEB7DFBC2EED679497EBEC808BE20FDCB5C7 B586463BBB898DECCCF7249E9047DA943FAF0718A2050FCFDF8A4C2029FBA674 EA64003AC03A847185936FC375CC67B3006EA681F61F640C3640A78D0C7FF521 D477981E23E5956BAF42252463FDBEC49BB560A9428D248B0C5250CFA2A49CD9 DBCEF73123C13BA382D3CF6A7B8A8CA3191D379A659F0E2C6E9CAFE9DA2AC074 F622E397A2F7C73347364AE249B11AE2C34AA7F0D27B5F35D548D5AD1228597D D16A478C901D3A34D870BA39F770885B7DE62298F0114752435050E99EA4E5E0 56B965EA185E8DF96B9FE97EE23DD45AADBFE02B427222B9FC99DA94FB2648B8 46BD30F881BAD3820DCA4D8093BA0FE70E03482CC063B751439125623FA7AE40 52DB2A380D89D5E37BF264CC73DA9A1540031587F481A0F146C6ED6F3F2957FA 19477F075ACF64D424279612DA5AE02B2A140048386D01B1F30EADF2050B71A7 993773D5B68C6FE65EAC53411AC6E7E26E49BE5FE1079A8BC565D2CEB7E3B896 593D720DBF66CDB26DA5D8E533A346845E31374A7C85FB6B06C3D54FE3408013 864CB0954A2FFC00ED17CC167AF714716376B789A71059DF2032E0E907761E81 F0C887810337F52662AF43FA1A7528923B0A30A217FA184ACB73207EB3018D5C 09EA88CA0873AE690E94D43B360D9C1070D7CBAE9BBA72E82EF9914D3AED6D1A 5539585EA969F0A1407C8FEDAB69BA3EEE3097D5B123C5770D5B8D1530A3598F 35E26FA96A6EF43C5B4804EDCCCF380241412F3A13D41E30449EBEBCE40A206D 6CA4491AE94BE9C09FC704EA364369A76A042525620D280574C5EF103E8B871C EE9C81B55BEB298A750057FD0CDE0F687965ABDC141927BCFE94118A75969B80 351DC361ACD6BEA662E8F935DAC80DC771EB0FDD967766935952B020D3324B89 5346FB2B9D0EF69B4EC965F20FD1D5F68CFF48B79840BCB88B55B45DB0DCE67E 25DF066F40F7AC2BBCDADF148C53CBE7702FCEC88A2DCD8FF2A860FE99B73DBF BF0561DA5CD1229D99F82D505C2B15C3588BBD6EFBE7830EBD88DE45BD9BEEE2 D3B9AB4CEB281D678C5A56B974F6F195A32F030659129157EDA0BF3D6F0DA7FA 611BE824BB3FEEEF46726004537E6F70507519E3439A5B8713A2B52B9B40C818 91A763097FDC120969CAAF54CDDF17FD81B8E43D7ECA22B535A8C84060F01FD9 357EEE127E914C372C6ED1CF7B13F1D231F9EDC030EFC2BE8F32B1A7A62AA6BA 356E3A7D3ACD281FB52785B35506D74E83260C03C07D5714155DCB1E51156925 7C195560586B619B4A614CB73CED24864AE4590271AB3095C877CEE8CE81FACC 865E1271FEE1F54BE3A6D93BB5B53162469DEB63CF1EA72B19DF2EB3E838EEA9 77AA9F6871864B5F56C1E6B2653F4644E4852F5A13CFCA3D375541172E6B345A DE41ED91449EB9C90AC4BADFD78B663EC995B51FA37E3C23A2D0FDFDA81107D8 DB44094DC63C1A6CCDCFAF66DBE95E76245C78BC947F0D8FFC6C922359F67F3F B94920FC253530570B08AAD44049139E01F94EC58AA5066187F5318147DCDB55 8FAC34C9F64FCBD15F00F21A57AD788DC864211D48757B32C62E3F1875488DA6 3395016849063F6F135E8B1B3E0CC7E8C07078565D87370A5C6BDC67F5E7FC9A 260BFCE7C040D1F9DC0691174D40FD2EAFAEDBA8BB0DD6C6C382E2FF0F3BB236 802A92FBC4C12B712F8C8A823E19265E1831E4CAE0BD8D660C99438365C4DF4D C10549BA8473076461EAA9DD0A041067BAA6F66095587BE783EF5A209F1A980E 7687925CCCE0E4726339B78D1EE8D1FADFC9657622FECCACD214533E2022E47C A95768FF9E29D55CF6D6568D8B83238FB13151F919A77AFD2FAD4415C694E537 83503437686E4311F7B3BE264218080E63C6F206BCDAA7B0423D27E26A846377 EA6E71DD470F348655070C589AB10043A681CFA6E4125A85C80B6D77AA2597EA 9D1AD450058D949BB952931D198652D2A822EE2310273893FB904E00E18948E8 8BF3711DA31FDB1F8D3EA10A257F42E2B3C8ADC00CB63D8CFDD88EA3F32B1A07 B9EA64D5008D3A342FF7C5648E88BBFA70BE851E49130B31E23EB800A340F1D5 9C335C3AB19C6D65A5BAEBBE43067AE6E56A0C4D3878DE536AFCFBCFBA2505E9 E7A2002DCC4F3D61E041D5E925EE0C8AD260BFDEC5A4C449242E708B16D40678 71B1F37BF41CF8EF32300F6A4163AA5C59D6AD9634C05F5D679F39177AEA3626 D6DAA39BED629D7019F6BF954D1E7C035F8BE8C1EDE30DE6ED25DD9AE2CBB62A 5C5887A5038DE4CEC750143AF8CE3F98C5EDEF5E3F0AF2CF33CB9588677E487B D8D34B94F706A1A2F3E3B2D5358711781D5BB1BABD6671C99FBAA0421BF891B9 A1455DA7810C6D8E7060892556085EFC9FCD787C456F8049AC7A5B4E97E15B09 0EFA2FE35FA59F7B3B795F6783F803312A4EC8D0BB8EB62D702300AA6E98FD9A 1D61695E9E74F2721433463364ABBC4B865DA946E674F48CE02837C85EBDB9E9 635B55E7C2C8B02359CE19898EF114D8ED9135DAA40A137E27FB5FE31D7B47DD 4D68BDB9A5A1BC869BCFDBDCFA7172EEF6733CBB3299D79AFA03ECDC15C5F1E0 4D6E5ED506AB2DA751A7F1637C32839E81B2E9E3D43B31461B056A29A091214D BED11C401F6E8B44CA26033DA33DB0354862B68E41E046AEF8048550B79DF3DE 5D67DBD377E5BC0564AE1740C2325204CF13162F02AA5BE720C31969B46DB703 59080406E700BD4054E12AF2D5B40AE6457A82B85BDDAEB2F494B11C2601DF64 3B0AFAA57817638505F5699AE916617DCB9BC822B7DBDAE48BFC998D04764E50 9E3647453A8D02FADE8834BF4327CA547C8E418383630142CEB81EC5C914E710 D1D2CB82F69B21803F828128ADC33CB5C2A6AF71958387AEA01BE6164658CE12 E0A7BBC587289C3D95EF9E3F74AFFC5139649C93442FF82AFD3D6C9E852E4FE0 ADD6652226A165142AA89E279748B8E96A259329A7A2035961DF2B612AE9C459 F4F7BCB4DC8AC4F61AF52A22EE7D770628EE2918BC66E175E3F928B2CA5E4237 84B945E54861BA8842B1411FC67E0CEDC09D267021939406E6F8BE7F5D893309 FBF81CA7AC851163828ABB6056F010B5A8068E167B6EDE3E4A975DB68F44DCAA C5EACC56947D15D29437747488725EDCC526A0C0E7E68C1EA2D0310379919E0B 4C7F1F040EC244BEE39BE0A4EBF3B3CDC1C09343303AD61CCE65FBAF6A5FCCA4 E542930746422059E701A7A91ECA1614E362EC8939B835924A44A07338315384 6A7B1A839B4998EF5516151797658DB0DA4D4BE2D7692EF458BA530EC9E4815C 191EDA0F023B1DF089357E3671F2D1F1B92F147B034F47595165F8F3AAFA7FDC DC8D56FCAD436F947836CA0AD6AB2B9CC77D9C97C5BD3B0C3B5DF605D68A6D8B 89C7E354FFB410DBE9ADC274E6D3D02B4D033819F5C9B5AD10A6F742B5769917 37708EAB5F2D8D5A93D68663DC551BB05AAD1E404E08A4832D2564D0504D5966 9D55364CB2ABAA6DF570072315CFC481AB63F98173E955FC29503CD160C8C507 7F9750A6FFA70D7962849C042BFDD2490A50BF0E82C51176A9CE8E4B6C4211CB 3E6EF018588E50881F1A0D2BB444671917ADAB0DE1DBAAE15B9EFC9353B9E76D F946947AB98CDB0AAEC89B8CCC7D46EB67874D7E0D1590CAD7D73AFFE9C9FCF6 3578A81946B3A81FB23443C6D3C8C45531CAD8A94CA092ACA433DD7DC3A80F53 A8333287E36F6F3F626431EEF7AC7081F38F03068908461114EB7267BCE1852F 67A5A7718EC409BC09A2FD62C42F53046961D1B111264E8B91EC143FEE64B669 3CF181490037E35CE2A812A714C1D4B4FA25C5E406D7929D992C549654F6BE1C 5A1CFA51945386389119E564FA8636DCF9935D12B4C60AA9F61C205CDDB117F0 FDBE306E4842A39B4CDD1634EF6B0C2E1F0C0DCFE701E9E1E34AD7D3F77EB377 8A9AA513D9E1C078AEE3AAC407D7E7C4EB588EEF5C8DD8CED7F5190C75F5F42C D752DBC6E1BB464E0B88E5C5DEF5D04274E81B6724A6DA34AE78EEEE69FA8A21 BB7D9F44F2D3F2E343DE17FF7A6FFE639D6E14D50FEA7EA14490AB52368547D8 AD22197C00B99CF3C2E0FBAF68288A583618A75C3B03B169B0AA423866EFA464 68A2796A7FC6BA61EEB88BF28A35CA676C1467652D31AED81F275A1168C3A9D5 2A750FBD35250C318368F07F65EDA381F0CE063062D7D9CA0385BCAD74DD0D22 36020965577DEE694CAFD835A38187B92AC07FCDE8F9B85C14FF18CA052C6C84 6B6CCD26AA4512637034E6889FA93E40F725A6BC2DC4A514F0E7B5206E31F668 FE6DA1046DBC90934A8DDC4957D336429BCC474D1BB07169BF0B69E668063AD3 88E38B67948734E5B65EFD27E1771A294E5FFE8FDC602EC465AC92F582E10B2E 07DBB581B99463EF60E00F289AAE4C80A5C70C4A943BC64B1D79089B0FF50834 8C43A73BE5D7A73E558017CC442C49CC49703D9F727F97DF136AB08A3DFE9895 19DB3C4A3B47D14C4F4D271505217F286B95A04628C2FFC81E3CB2087A4C2E34 A98BEECEF94F5E03B2EB0ED5F63317937BED68A2E27D6AA851C79C2A8A1A5C00 17963D44693C394948F0C58B2D8305B6369B0D518F7E183F0FA393A972C1C211 B6FFC0D376E425F982F2F6FD02830F020C51F7DF35287EFD3B5CCA37BBE88CAA 00990B9213698A5A08C64825CA984A2EFB05C283D67D926816D58D9254F42992 13B52BC09D4D65469DB6599D8115D165392CB5610FF2313B68850C643E5F144B C17B838132A21E1206507B50BA5A1045333C32FC23ECB3B0944AE059BF23EFA5 13D38501CAD7CB6E1BB31E45216DC35BC8A7FA708C124006B220B251F53BC449 F2E8DDFB16284E7FBB4E5B74919E287C7232814C8126D07FB9D55E63FC0F7B39 9E7293E3EBE9132B6C1C89CD1E83C276F2D8A4C93174B330DEE1D9DF83BBF6FD BCEA28A80AAEBB8E8ED605C1820BBE118F09F1C6A3D41C9388C9BEC1FEE939D2 4196218BCC6EB291B41DEB2A89590C237023936865CC8FFE46B58A41501B9275 72EAB90579CB9E7D2AD239BDCE9E864253DCA052C9457D44BAE11F6B5FB5200D 3ECF63ED84667AC109510EA773F526F0947E54E88E1C8B4FEBFC336D770ADE2D 7D11DFE71E146FB41BEB28A3D6F1F9B21319F01DA3E6F211EE39E77B14A6EF4F A8B60A49D151D52C1713477F0C890CFBAAB18E275EB0CF680A567DCCDB0A9C4B A8DE30A6976480CF8CD7794CBDA3D8DF62F1F0F3101F97A5C950997B4941AF7F DE6CCA825978BD8852E023B3A0AD65090363CC678148316B9653CAB5B3E311C2 E2091AFB051D1407674EC487C8EF04DFE7273FFAFC5F405FDE2BA932801ECBBF DDD13D4160085D94704AE098F8CDFD7DFD95977E892E2E0F31BC9A632B890369 8138FFBB16C5A1B228B12A51ABF6063E7827DCA420677FD1B89C0BB3AB80C93C 23BC4E8AF8EF4EFF7B99873790B4EEC645C4B2C0439F10F396269E79093FDBFA 7B93780F4B979A8EAFA60DDF74716D18D3F259266E718B6F6A5D9BAF55A43F8F 789280B688D4A436CD06A5A17D1562840221D0BB1D596B6CF623BBB64272CBAD E3A11FC5ED5E6C14887EBB84A4127B21898C1EBA3BCB65D5C5CF9FEC54441F49 F17B0D03BC5B710A0B4166DDF1F7AEA025E1390F7F2D0B77085EC593250AE580 300E4961E43F3E7435E2D61CBC40BBAADFEFA905BFEEF7D5CB46B135E6973324 54D052B091F034BB87FDD885E4155DF9E8FE3088E0FAA26580D17EA1A09A8FA6 301BE014333F0EB187B8D50D553C1EA97518E4B63A6D277F51627C6ED82CCD1E 0FB52C98C3C6C66AD4E7310322A1049E0BD4BCBED8AF5FB3991087AB6BC89085 84400D9D474B298F96708DD35DA8169D84A359E31287FE0DB913C83D927DB250 F7AA8DA39D7D10F00CA1297AF6A6FFE140672C644575C0B38B4A72B898B15AA6 7CDDEE85596FB03A5849FCD29E1773420DC308FF2BA17454E2D695E45371CEED 20710529028D7ECEDFD3685F85EA0F1EF2AD67DCB8AECC0A61BE95E455932671 54CFDE21702552C10F8160327B8E0DD627EDD41353A6607A98F1F235C268841E 254B411E64976052D5A045F9A7DF79C0411238BACC3470C48C5AF7DA1B7AD925 1391A8E1CBF01EB4E5AB29243571C467B28FCCDAD004E3120FC62603FD8A2DEF B63714F6CFC9BD3D00788CFBB2CD3624E2A5ECDC4B8C4FD5BA26F412B746627F 515B224DA89ACC3C87C15D8F8DDB7A987B7F23EBBCCE800F7F23BCE987146445 E0EAEAD5521F52F75990D288440005B53ABE88563BD6610B005B5B76B3DC275C 95EE5F0E247819F834744DEA59D66D80191C029D64A1B78DB1DFED5478147A44 7ED9912F571AC27EF3EB318C44B47727418C897B2DB085E8CFF5DB8D6A03DDBA 733A0FDF6B7CE51410C81A55B6346F6EFD30302FE7F4839FBCCA9996CCE6C8BA 0D71D22801B8B9938DDBA46C0FB0A86E5B55DC3EA196B722B8A797B0E485C7DA C56092CEBB7A69C7541A8C3A4B30B08DF08CB26EB2BEEE603964EC22866531B9 38FCFE2DE44EF169D679651C6D090591E5494F65662C1E4E876BB14B355CDF0A BAF9CC717F1890C6F4235E9C837638BBF2C743418817B5AD137BCB388A74036C 7B98989794AC426D5DAE83ED05E67564671CAA4EECACC849A91A88A1490BCE0B 82401968DFD1D489D7848BE9C66907F722717628710490D4EAAF1FE2B2DDB44A 7CD7E2B3B778431D0C87E913242B22A0DEE6C1EFC57E948B715DECA191AA9B9C 933DB53D7BC7AB4A5C91FD70EB6FC93D0618D4C9C449122C2D018D24EE8B1744 C03EFE024812500672B47B4CF0F3D5211BE460EDFA32A578579096487A2CA559 998D6F4C4C4D76BDEC6B336D5747E028318E700EDB587309929C1D43802D0C9B 5B783D023D96CA2A70AAA7F7C05605D16E512B056DD65AA177CF8F95FE4311B5 DD5C2ECD7942B3C8AE60E8C324C7CC525B8A5791FC3E5DD06CAE6D0CF0B2BD75 AFA21B8E892E266D9A67248C4ED7358A2280AF4D22EEEC7829FAFF9C63B3FB17 D4A427F35F45401EFCC6EE6E2B912053D4AC3090BF64BD4ED0E5470AC0FCE95C EC51359DEDF765DEA07A6E182D74A2D633492C19785489B081A2183A56EE4B9D 915912E566E16FA8DB954918194D421E3D400E62FB9183811EB78EEC189A31D5 4B4775DE49536680364E293531FF1DFB751B46C7972BDA426213171DAB40BACD 2499B29B425E9CF9F5E972669C67BA060E7992DFF85FA3682D088FA710EF9681 666076A1FDF489DE53011D76A267A4469BD630C740E4331AD5BEFFDC6B5AE79F 0D8755D1CF78AA0B6C0C2E27A8956B0CFE0A49EACD91E56C22779A03B5772576 A7A6FFA96E47127F8E6E1118C2C8C582E13D3963E53E57639C6A80B9DE6D42AF 9C7700FCCFF0284B59769EF7B4A6C498F281FE891A52507BF6D4C7A26A4CF996 D72BD796AE75C7ACD389EE8C729DF0AB145F0DD08AEEA7113426297C03CC2E9F 7D4C6869CC5D32A20E11A135C0B0D81F8B09BEDC3703AEFC07B9494C9B1F052E A87E8F96007A2CC2DA42AFDD1D7260E49D665B8E10740F1FCCDC7259ECE2018C D12CC6AE369BAF17D8274AB3A7E029CA4225CB67BFF14B135474FF15883EA7DE 6BC40C945103C36855466D4872CEE3A77579396474010EE3696D1129D635EB8A 2C38355E10E495D96416A800F3AC32799B42AEBD7D9406C62FE82DEB37B7BDE6 AB93B803659EE625DE127145D1621F39534C9A2D71DE99B534100E00015D5FB0 FA192D6D4E248368592DC8FB64146F0A7D67ECB5C54AEFB77E8E200FFFDBE3FF 814868A4D162F71E68A2FDA7B8E30BD29497D7C69F6F84F362722F57726B18EA 74DEC2022EAC39FC7C39074D048C7E6EB69E522F15030381C9E81F991E457AC3 3ABF64D92C9FA7F32B4D74D37F912D6ECE053DC36BCD85D04C0B4B3DED1706C3 6E2AB8D2EE2785CA560A0A34823F10DC887304AFDDF88F35E109AA95277B1040 4A41ED388254075DADF224F86F66A92514D8182D7B3523E7891AEA1A7B0D64DD A1CDAA3431445A537AFAA5B143C7809891FEA0F31382B07064268737D92FBD89 283030B3733F65475860F272E747B2C179063F5A1883A30DDD5FEB24D84875D5 F163AEEA467EA8BE0E9BD41485CBC3FCC961FF02AE6E21F97918271F80CC3F1D F5DE7B1AE9B4D41487AD6AF1BFC7539522256F10D85BC9E837CD8671CAE4EE2C 8F0205704E2F0A826571B12053241AC62499F3F25D3D941F465BFD595F3FA886 EFB95EC4659908CA81BF42A04BE587632EA4978028A80BED403BC1EB85731C58 020EB390D8E3FE8946E722B2F69301F6988F80556711310F0BEB5377A24F0C09 0E4604030D8B87D3EFDE49A57041E20F7164DDDCBA3FA50613B81894C7CA76DC F7AAE6100830366F66ED83662653361DF69C39BA5DBF373BD07F29AE42C9F0AE 62D0E116E1836150CE6ED15035824511D0045459F70900AE41994C6CAE409C02 136669C6847000B8ECC643E835E1EA664FA21866F7585522494329E7F9345B2B 86A5878A3C6D7D9A74C9B273FC91F2A8D0437CF44CF73E0ED5E3A81E19295213 B31CECD82FE0E4A08BCAFB27CD0FE243315B89A6482BE8E36B4A52226302A383 4BCEEB46D8B57D1DC01CF7C9B255662E485B5A0807D27BBBEC357DBDB1354773 5EFBCA9132C26716B7E8A5695DABE632B6921A3D73268CF85AFF3E3E96C61A1C 3B86623D3FFFE05808FF0EC3A89ACCACC595B0AAC6A77A972FE07961D80D19FC 41B8301147EEE2A7618FCA3B333F1F74A06C20EEB06E9785DA6DB6785BF7341C 2356CB0BE763D5105B7A5319EF79D3BF440C1F45BFB04AABA8A41A1082664014 05578AC436C50AA6E1D8765B67F658100FF1D902F3A9F4D954022714B5F4D7FE 7FABD9FF7AF6E0E6E181AB7F3F12372F01F79F72282BBEF1B3D1756DCB4D4819 5DE6E5302CA38CB28BCE1FFF2A813150C96D0BB8E1DEB837EB5FAA284483EAD5 332DE04E43E4FD974AE492F3028C92FD5A590B4B1931884E19BEEAF5B2D6066D 62276ED453329BE3509912376CBFBBCFA6863A0B9AD901544833A33B8DF290F6 750EAB08FC51751104BB9614F25CEBEB60B9D938B88527108C5ED5B1CF4EFBD0 24245EF47EF7974878056F5238CFA79418C4DCC7DFE4822C8B30DBE7E0E570CC 15FEA3D617AA965FB2B47ABF96EF86AAE0C1DA02AD25E68347C332A06130FDCD 4866173840A8A16650BDBDD7CFC177C0DE50A24A56639257FBCE7B0DCB625804 8D5FE9D3C294FEF9CE45FE7F797BAD6C45FF5A9345650B67CB20F2F91108FEA1 F80D3D9264DD7DE550CD56DB0FAFEE2F3E8BF4ECA2E3643E8BFF8FD52B909122 9876B90B4AB81185C88EF74C93BBF40280B3E12781A8D34C0E328D614B6BB743 7066FBFA1A3D27D75EA0E78274B7865C008F60E8A0F3A2405317EEA5D1EC9BE9 B45731288CDA59C708E4B733312D63365B2FE49D9ADAF9FFA812045710875ECB 4CF8552EC4AD337788BF81738D5C89632FF97D4DA83F8B1544838594C44245FA 71C5B79608D7AF074D0367A58A7CE6A83786C7989EF2908FE51BFAD5A2888B45 3C0CDE8F790B5037D82019FF679B0C77B79AC3B3EC9B0194F448CC54FC16B8D1 266005443A777941D5CE840145E0040A8AC6A1A1FC917778CCEA48557AE93F0E 995D1CF1303443BFE0D844C5924B0512C0FCC84E5E29BAD5F7E81B8EF6311819 EE2010F0BB2BB30858002BA45249D8A031DC53BD06630652BBC61920B34A861F 7F387223584D30845D80ED93FAC2E00255B2FD3C9DE1CDF13990C7A7D34D5239 F7FF0E2B22D10C676DF40108ECBE257B307CB93DF443CBAB426D5592E8113D79 D1E6BF55468D540BE4736673B9C8F720912DC90880BCB4BD95C27D9357BE05BC 1AC77930D727FC36A8596550126DF29511C8BDF8893401992096DC21A86B0463 9991A22097E3C90B51392EF39E30908409EBFB601534C26F48690D024BC0BF39 184429FD4FE93109A4F3A4827F0E0FF8BEF17AB3810B4A110F9BD658D07AC08F CCB0C4708B244927524AD4F980C68C04D789F7F8626C723817BFF423E6D6247E 5221F0635BC9024152D9D0203EFC8EC0A42EA936893F2C62AABF283BBEEBC200 622DD69270D404C4BBCC0B18C5F775BEDA837E31A23018461BE114401FEAE077 DFE425B12D7702BD50C68EEC7148FAAB7D3EF743E8BC4DD148ADF1DBDB9A83BB A63BD0F0342EE72FEA35836B521EBEFA35DE6A8EA478EDAA8EC7746DD21CFC01 FF9F82A2E1715106279E9CE544BC8545DE8439D35AF124BA93F6B776C8CD4832 C32F769A4979D845B6B195119AE1584826AFE740615E16BB470D844DAAF81F78 96713D953F2AA931DBEDC251519053C976AB969217544694CAF83A5FD59B06FD 320552E9B03FCCABCD72CD96413E39749AF5E3C05ECAEAC625B7DBEA4466D4C0 E2678275CCF9C6EB62B9D6F381846BE27CF0339BF5187DF8A244816CB6ECBE72 66421C1CB4967EF2887FFC3EE449235162D7E36602D7AB3E087E19C6AE9ACA0F 2F61E95A8335C56908C75B2EB201D95A751B37EC7F0AE011044D22A4FF8103DD EC16F8C3621AE40AF2AB92600169C097841213E744EEF6BCA58435EC4EF8B3F1 62D387B45A295FF7281C0B4E19ECE69A17424D73454460AFB4D7FDDF7DE41A54 DA42DBC8D371B0A1EACCDC7BC47F21B2B238097EB606BC7C4E9461C5579441FF 1558C93F6C354D83ED43A08DCC8E088FF74C6B722FB236013AEB05F5F3493F3A 9169D48EDF544B41BC2AD0D4C70DC16801C63183DEBCEFA2A2667945990598E3 B10FCB2791BB6A37DCD6C8DECC18DCCD973DDB78155842699F9693B8BB8EA441 A3446F0591614A2247F150F337627409D3899561197A1B1B5046CEE8D2E123EE 90AEB355318FE92B331EF3D0747BB4457C37B485A395DFF164C24E793696E0A6 A94FA37F2CADFB61E2F86D4ECBF11632E59982EB5184C1649DC1ABDD16ABBB3D C7EBE5F0D7C77BC47B32AC8652FF9D189921A9D0B832DD09B60B94235B051056 A43F90D0E6A4FBAD2A1444412BD8A400E6A8C4A1CA2E91C7CA0271B7519E1BC8 111DC069C310A9DA0050601C1606AC646B3EBB0D058D76C3FE53C618E372C05C F8C18494D975C7AE68DA3D626A46AF746C4D1DC1F208A971CC262EA115321178 CF92E122DA6A4F0A6B1EFC1E27CD2934ECC28558B477D0E7EC8FD8345B28F947 906AE744B3D1251752E5307BE020354B5275FA23F05BE14A6544865A9F288EC1 95A86D05FBD31EAE9BAAA9C3A12FBB746BD6F0D641ED74C0AB1709CF1D842143 673EC064449B3B26E0944C33E32EAA31C0247EECA41EBDA9DCFBD8E50AE7B637 D2D29638C09DB8EABA369D8BF2DBEF34621BFAC718B43A7C1B0FF1CAFD4FEDB2 E39722C3953D4711E4091DFF08C2E3C216B3C4972AB417DE832980E589CF20F8 8B466A4252608760A38DAE1A29659053B90F21E863D8D9DBF68DD93C213FE23A 465E73E93867D679E70D3B34216A8005EDD4C5579DB383A50CF85708A65F4BCE 0C0AD3B81EDDBCB5E4EF5A7A598ED8AC88D5C7DABB6A7B826FFDEF25420A1FD1 B8EB48B62B2EB93D6C1ACBBEBCA79CBBA5A0F7542C8186810745E8BDF9C2E4F0 A1469B29BE382BB352285408EFD78AC13CDF636F4B92E1072473BD1FA8BA16A1 AD11E9E29B2790D089F3A9CB725821D86737DC34D8AE4DC69676243074BCBDAA 4974E4D6C5B09F5241D15E6194F3784B24E8C329CD0EE5FD19C4188CB4042AF5 C55E539D86BF4D000D7B60867E0CAF073052A5A4DB5D2ED85710392C2B5B3CB1 129CAC374CB93707816DCAE37E0A8E9F7D14711672C6F6477E18194FEC16C51D EB3E840302BB2FF72C543CECF77BAB2B1184598138AD81FFA750D5EE71F5EBFE A410D026B111C96C3D2CB6BC92A8F3DB310F2D9F909889BB5F3259C70CCFA5EF 8F7917B967F2F82756C11D0659301966555D0B9351ED44583BF111562C4E42D5 31CE919D2BF2ABDD64030E58EBD4D590E1937E294B3DEEBD8B4143C15CE89A76 C39B928026B7B8104729E45389AE606BC16D428E84BCEBAD61F1C9803A9D0EE3 11E87E82A90702EFE91D0D4092F42CF97B16B71C6EB0EB16FB733F0337E7D65D ECBE14DD98D6DAB725C5C97B4E9750ED62F1BB2FFFE2767F664FE74525F9E240 5688A506AE7B5F6E2AD90E2559AEC9EA08AA4D1F2D6BB51D94FD6DE573111E8F 73DE3F47C9B68216BC459AC89B9B4AE5280007A5796C8D74D6DAD1345658D12A 9AAC7BE921BA67845BDB95F50B1610AB586CCF8B668A0A29AC0AB97FCA74CFE2 781641A0DA593E8CEA065B6BE7AE53C6B82258000B6D542C994283ADCC45070B 0B8C59BA1E84F51414A40A84F396F215955F8DE4BCBE407BF556D7BAE0C53732 B0CEC3AF7880B2829ACEB3BE8B52CB01AC7CD5BC939D7FB358FFF5959D5CD955 2279F924E1B7BEFEF50156AB727B0BD76E89AC10E613C7AA44749EDD900A55C2 6489BA7C2F0B96A3AEE0AB4794A43DD4CE028FA51FF73D29D43A331C888441CD FAA68CB48913BA71AEF4EECEABCB3E40FB126E70242958268571B4E764C42AB1 3025CFF1ADE239BE9FBB219C8698A4302A1C1E92D27AEE0923C69067FE968DF5 8EAD65D126CB3EDAABEDA727013ECE87480CDAA8EB33AFA9106A566124432D93 E108814911A27D9115805A6DEF3983194B4B6F88E2EA8B10C441549A7D015F4E 9E1FE9A83607047EF7B85355A7F4697C50216CC7EBF79BCC8316D89480C90C2C 659C5B76DCCE3606B1C55498138470AE7413B927C255D5416CEFF3E21FBD8C3F 700472991B54E74C696C183D62872AA2404D32B642CA777C54DFCA23B83CE0FD E7009EE98CC40D58B8D199A318346D1574B1C66408FFD957BCEFC489B280E689 3A17BD29A0D67FF62D037326E780B1DF01092457115041017FDCB4EDEDE3D29A 6D55CE53BABBC001797B2FAA6B46C401DC9217E343A0DBB2067618944BB34C46 CE29B8B4D7DDC8710C16BEF31FB3D77D9575CDF26E863C760EBEA1AEE705B8C3 6A4A6DED85C0ABE1AE735946D08193810420FE0E91FED98B2CF78378A8319381 EB588155C026C07618A8E356C8E956839941EAED855BAFFB35D3689115B6A419 64A6F99E0B0B53C9F5395DD39314C666107E4EEBED22182628BD19B076A985D5 3C6D4F70C5C99F9FAE6F1E78F0DF62D6193997B48F01250BBC1CFB41BA66ABC9 7A7C6C9C1C2228AB3AF954854CCCB6B10376C932BACD3FBCFC586CDD61102541 6E7ACB663375419E0E5365AE3EE8FA35DBF8BF09E8C55526761F4D258EAAC3D8 E9F4FC03615B91C99FA8B829E452541850AD4AE86F926A205955E28EDAB12CC6 C30613365393ECC723E180D5FA2C8500502584ECA98D62D6FD308078FA50481B CC696D9787DE45F18A9C32720E3F17D0722C0F75CEF77B397702C8BD660D7498 E6F23F0336DAD240F1ACA897DE23498F950AD8A352F39555A2BAC41A5FAECE43 9DFFC8D439711480F489EF44237896B38D5FD534A8ED08030F6B22EE50D8EBA3 A8C1D003D24456DB7995DDF16B0AD616DED40C994903AFE96A8B16533ABE5562 5F1550C8190D579F7ED994919BA1910C271D0AD96A134199588DA13149D5985F FDFE49334F4DFBBB05D1E78BD7AD26DC191AB862D32E125251831085DA1DF864 0F2BA2A7A14B0FC2296191DB71BB45D4AFA56D0842037D1FD9143BAD07E3CC11 0D45734AA95B4051CD1343B624EB61942979F7D1D924E8E934E019FEE29B50CB DC9FA695E9A334DCE0A802E02A74CEB00DB586AD809AFC85E0632EBC53CE38D4 6B5CA22B53FE9E9F8678539CEF8C6D479106EE9BE257B9F4A1824459CFC20B6F 111778D61A60A38F154584402C9F8B34BD39F04F9A1FE451A8E798713510DE7E 3F64D0E92C1084C733DB00F16F710DBF274D1CF1E7B4F4F57D53EAACB991E120 714986ADE364ED192D37FAFCAE3BB7ACD2E612E0110D36C8C211FCBC2E0AEF87 F5DBC7A3A5957C38C38C197434E7ACB70AFB8D56AF1334C3CD729A62DC8B4E59 61DA48B0FF1852E261511E1618EC694C91C74A2F16DAA781A75E5FE9664AEB24 C6B6CCD84FDC3ED63480CF4D2F72AC4F7FC250F9D911FD3D7DF74CDA10083EF8 6C70EBCD7754C5240B8BB57E6198C57A7207EEFA156F9E0ED543FD310D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMTT12 %!PS-AdobeFont-1.0: CMTT12 003.002 %%Title: CMTT12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (<http://www.ams.org>), with Reserved Font Name CMTT12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMTT12 known{/CMTT12 findfont dup/UniqueID known{dup /UniqueID get 5000833 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMTT12 def /FontBBox {-1 -234 524 695 }readonly def /UniqueID 5000833 def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTT12.) readonly def /FullName (CMTT12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 40 /parenleft put dup 41 /parenright put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 50 /two put dup 63 /question put dup 65 /A put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 72 /H put dup 73 /I put dup 76 /L put dup 77 /M put dup 80 /P put dup 83 /S put dup 84 /T put dup 85 /U put dup 86 /V put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 119 /w put dup 120 /x put dup 121 /y put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7 5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99 8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716 EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C 02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D 46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A 4B60D020D325E4C2450F3BCF59223103D20DB6943DE1B57D05DA0555DF933BB0 7B42D264831116C06C79335D519461E7B0E870A6715E3D74A08D1BCF86E3BCC3 A43FC6BAD1C68BD9D4AFCC06D845FD1F1E70D7A47F0BBCAECE8396E04591E5E3 4797F646AFEEB7DB548183F0B74C9BB6BA2AA04E7F5950EC8AE97C741D4B2C5C A8E7A8DF5A36A30B5A7592D95E1DBC63EF33C92FE459792CED29E2B8B6919251 75EF62089BD7D44A6E1F9B62EC802FBE62B821DA1C3B2DDED45D27964AD29ED0 9FB7868F3A8FEADA87A8E42D52C1EB7229D7C79B60BDA263F2BDB025AE14A507 098FA274206BACFB4A0A7257D5998EE8F0FDCA79CB61DD1FC59DADD11E16BF02 ECDFD706CDA1E72054D4EB55AF7BA9F19955886BC0BD6E0E3FE3769C94AF3581 DFB2BCD67FE2892AF07E858A01280194D8DD7332B3D0A585C87FAB056C2EAA9B 5AD48D1C9F00CEF8EF0D1408DBE1C03D04B231D7B8D5D998FE0CD7EE19828EF2 F988EBF6DDBFEE00F04A4A1F4E1A55DED7EF3AACEAB5005F1962C724A017C914 2936E2E0DF26A55ACD7DD836C6035CBF07981C1BCE3615064F0540A1034C69B4 E3908E76EF8925D486DF0B4A8E1F02D8AA99585A7C31847AB9382F83880C1C21 C496AB2DF8E7BD4643B28B704B5F6B53429D3EE940A79135F5BF0396E5B46F23 42AF406C26D12BEA7A41F332AEB75DF43C15334CF4651A99F602036946B1B91D 4BB0D2E51C20216D892C8173241AC8FD15A37C3CDD8AB4FB67D8565AFA61C068 95E3D6E46D7C09BBD09428207D506AD43C693F3C3D787F6A5C39084AE45E81C9 830900DB50DAD10A17E118FB5E9680B5194716A788FF7514A1167DD1A305FBE3 FC1F39A39F5613D50934419B95A4A2FE1B6C18912CECB86726926F6B77B5C3AF F38F85F974A2D2145BE010EBB4A390B842BC222AD4A0B7FDD882668C04C51F19 13FF91E7CFA0A0F4E99A1944B272E0291BBF3F9ADFCF3F625B87377AFEBD9F11 6385726E908BAB7D1357504048C0F5B26251A1FA52F08BAE1D64B9FC32A684AE 896F3DD0AAE9624050D4DFDA25E581FB2630E8840AC5322D38B92F3E77B55CE2 91ACB8321BE53A2C7D274D63CF0C68AC833BAF4B22B26EFC197D4A893A5AE492 660D995DA9294C16BED1113CBCC18AFCB5968175EE2FB374B1AA261F22CD75F6 6E7295A254FEFC41A66EA6833A6A4EE0E75EF6B6FAF292DC5D2AFB61D5203DB5 4BAEAABAF39E9F98B45F22F2E37F337A7BA412807A31B4A5A4E1627BAA964B77 6AA397D368985045244ACE969799A9489CCA8FEFCF2EAF262ECE08BBD9573C79 2785F1004C34F4D728E9E820B4133FD5F823B067F6686C82BCD35123E4831E38 CDD5ADB098BC3F1B4162F45B11ED39CFB65DB1A10646D0B9FB5BBE475031B2AC 9E0769CB063B82D1232E24CAA86D9D5DBB9737B1E69608106D34CFEE3FFB4213 5DBFB88BF9012F430D50DB76D3DEDBEEE3242AA47932F0A7939D001A1C9253F6 2AF85FA9C9F28A5787ECF6F5E7EAA11C9E8555FB50ED21D88B1D35650A0750B8 321CF76CFA54D4184BA4754943D4D66CED49E3EAF0634C0AC1B3A1B5B0EDC386 0FBE666F87C916781EFDE9CA529C4DE01C76850F4CDB3A16F7DAB44AE7201B57 E7A77F58609ABB17D909F872E7A6DDD5F8A08A9A5AA2E87164BB1581F8BE10A3 31DABA584156D7D2ABC2143DBB1C99C11BC1DF5C66653723EA933C0625142C33 5DC086895D776A1F4D09E28C5637180ADB4D36FE403900515D2CF26D764849CE A3C24A06CAC1FE0DACCB81B0B81E1CB9DFF8B5AA4EACE3D54380A80E203BC51F DC199DDA2BE5451DF1163FC99303E7AA60C6BC36FFDA12A81F40D7600EEEF4D0 5E4E1906F6427B0AC03B33530E121A74EF9C325E915D84035FC344E285F89F23 2B8CCEC623AEF0BEF9EC9B672D81ECAEEB233990C75D5AB2A72BC3F9A63F34EA 45E8060D5756D7187B8BAAAA51F2DA20A5B019DE27B9B4EF1FC4726E2F759657 0932E1456B8739C38EF82F715565278EB8FAF7D5C095F40907C44FC7F5BF4766 755D02699C6E818406EE3030D2AF78A9C1071DEA3A03A5B30D63290B0693EC83 992EB624375BFB7E6F6012888C3A4DE43DB5FAA956DAD044021E04D4AC71F4A9 21160A1DC54ACABAFDF5CF6AEABE8FD4CA0B18CDC8D20DEB6DB35388A6BE1032 83D4402EDA86AB6EE0D63DF0A81304249E887FAA95902FE57ACBEC4A1CB352A6 1CA374B6C870E83BA23C7EE8C9697316DC6F4FDFF006442DB4C21EB1B965F678 7C8D1F91A167E42478418D176A0E061776E13E8EB070AAE1A0952421D3868A25 EEB88AF2FD4A62EB8E743D7EE30E15C165DACA8FCB2C1FA219E2719EFAA76DBC CCE50209695627353B388366CF6501CD7C4E86AA4A7FB0F508A081A3664C60D1 143B7F37F73BBAF4A918D254F96B66DBF9CAFA6676AAD17A36E327CC29D15D9C B5673DE08BA4C9A706C198DF2A411A668565E00B77ADA0A2452561383693BC6E F5206E0FEB08A0DE9E420221DAA4FF4A40BD23B7CAB5F7FC17665E17495478FB 1BFAE0796A76156FB936642044A29E17E76C59075493CED6F607B27E9A563ECA 5821A4BE7A44CF203CA20D1D01CF4D3F915F08B1E87C709C0A251D10390A837A A5177A1626BD949020C805FCF335A8D9228ACB9B414822B0A102F847F568D0AB 32C5CCA6148FD7D32965250669F158C6940D09A3232089E5CC295D9FFA34846E EDA0EBE56334B137F76A3E18612C0937A2D93562D0B2279449FDC2557DBA3BDB 3554AD5D267B70C464A2CDC62312793C50756CA5F54DAC3D2CDEA959291D1FF8 D9044E6693856021A2FF45D3817A7F071797634410C4601D663184C53C9BC2C3 82DF75AACC200FD44FDE00C253EEBBFC85EF97AB3EFD296DFD292447CE46932C F3A0F1B3EAF83013114084763206E51A057CCD129EF056EA05AD5FEE2AEB2F1B 1716B558BFED0848368B152F603244BBA6E60A4A6BFEC9962B98057D4F707B5D ADD68B1D020111BB8E1520B1A546ED66080923B5146F8D732E10E9C95598E8D4 52E24014FD186CFC1A73F0974EE6D82A24FBE9BA42D6CF821B8D5BBD09431822 28D1D00BCE1058269D67C83EA6B9F5990AC6FE6B6CED5DFCDAC78C0889FEED31 F2AD47A0E0DCF252BC6643B677C24359137C063D4B341F738EDDF9344F612E6D 32D0E0B10F6FD61F728BF2FE4E45EC2DD4D1FCA1AA12FD1766029123DFEC8790 96CF2151188D0C5319B43CECB69753BFAA07BC7488E462F4F6C2FEFB9CF0634F 7E6280E9A836912FC76FA8A7D6CA0D2A5D7042EA1C93C146CE68700A18F1702E 70062ED4AFC5D29F88AEE951C2458CF04B55ECA2DD9786C5C71AC8113DFFA4A5 4A79ECBDCA184E8D3DDFF36AD0F1524AD2FDC144B8CD9B03EF182E19CCEFE4FE AEF05E1F015AC46BBFE1734B0C837223F1558D1C2C7B326BFC677D4641157E98 7E0969434E483B8BE8E9AA19AC8ABD2443DDB9632364FA9D5CF21E8B760AD524 018B690A81261F12C4AB39B88E87E88F2E2CBC8DCD4A0E6DD9CF2CC91FD47E1B A93B0C23984DFBFD9AD85C6FBBB409EDE5D5E8041AB3BF4267C9D2F6D445CFE3 DA956681E8616B6A83257FEF9D0BDBC6A8F40673204520A09966936971208F1A 8E52FAFCDB06539A7497B915CC3791D33D41B3E0D818BBB49BEFF9F405AB21D4 68B9FDEF07E0920272B90C554DB3EA49091878F62AF63D7453168CF260F778A2 61098CF822D7385137D61D8AA29CD856C28BA078B7A9F5AE0E3C284BC7550A2E B9A7FA172019FD896407792669DE7F11CE8C79618019F881E3CBD8057B6A3CF7 8C04A110A4BC1E9EB38BEC3AB630BF1D83BA6E5A4142D4690A854552650DA729 329FC201B3227247A32D9B883FE4C04F589835205D6B927C234902AD4D2B90BD 28C184813EAD8FE9DDEF587466B0E55B569033B8D5766EE6E61E70C77B0389E8 F9B8C89FEDF2B68E0EAEBF8E3521E58B1B96C92A342C0F5E401BB54EBC780EF2 D52167C2A32813BF9E88CA180EC4AE7EA174BD933AF024D0AC39E4DB7127ADAC 89CF02290948DB93E8D6EFD410DE1E5A8F0A6DDED74EB2FEDFE41F813357F200 B8C6197F16D281332CE370A5FCD019086B4C7E9E42F5E93ED92E01D6786EAB40 C427C801ABC17A67F923646A31CD81693A79B45E6AAD927F72584BB34AE75C87 050643F8E1746607A966749083C8EE29E5D607EC6B5A03C414E0977DA08020E6 A4FD7EB6BE9FC93C76D6428A3575FBED9052A33237EF89D2AABA8400AE55CA1B 2A6C498E31B1E294AB9AC075FD9358858397E2AB2880B51D04F395974FE788A9 060CEA08EC492105A19657EDDCD7102E301EB0713A7D4B7DC3718367C587023E 9558CAB4ACEE18E2CA9E9D8236A2960DC97655F960F3FA3D5B2650A41FAE78B5 A89E3B051DB673ADE326CFA4EC430543796A543B02B0BAA3C0A5D7E91F5AC313 351E5A3B656CE85907B23EC7F00C6E3188F34C01CE68D3C93EEC4FD668A79C77 B764275E5A478F4394E3678ABA1523FB576B96B585D142F943ECE9F218FB21EB 5608584EBB6F5DECB9AA06C404FEDA8967934EF89D7ECA7C11D520E890722670 49DB196238C87A09F1F652EFDD7E96A9E25D3C09C272B0E47455774E999E86D7 B0D70F8A79BE460CA2B0FC47E15F54077B40941B6ABEE55361CEFABDE790B6F7 13A29EB37764B1972FE1E4966E2216B6BB95C94213C479F5A11A233BF3BECCB2 AECF33A61A4539E3A507914B67DA0D94D0D75C055D017F8039903D18F756C8E7 F76FB4E1658F2AA19C08FFB214B5EB2A5DC9D1316DD972DD66F2F8A60EA6030C 522E8E59AF647BF567A83F61AA0201BC41DF5C9F9C7840A35BF4610C1F250FD7 B2B778549D098C58FB79212E0E37FEC3B371E02113CBB17C577034D29EF26B96 2E1A12FC7380A30D0E3087C79C9204D7C18055153BD4FC9F8B3D3DCCC7BDF1A9 4A3E022D6BEF8D99DF4DB6F97B1393DD6372556D6CD60A7386846C94007E7DCD 8B89B1BDFB199609F110C4A333688DCE1540EB8A85F99F2D44D0C8A0FAACD9B7 ED8A44ABD7719941742B76E9EF0B75F840289891FDE2C90563FD70F24DD6872C E40E5C054CD0D12CBF89ADC29637FE2A31787555F3C592DB05BCD28503BB5CEF 44FFAC151912193E0464C1A421708D58B13E886ED43850F693A42136142D7737 0352429720EEFACC81B339D40F82C54E970EB00D7D87FF45A664360194850E9F 8E578B8F0CD0487FB73CC604CBAAB619E2C05BEFEB50B9AC3C4E5854B815C48A 238380A1E1CAA04CF34C4C6C9B5DB10EC7DA1B703AD063CF20C2706CA89EC8A7 C25F319B81309D80463D88311A3DB2DFB73B6D360F7F54C4F050BA73D021C39E 6AFEC8B45915F61E6D5886005CFC0EE5787A347251155C375FCB22A5FE1F0EAD C8FE6228768D4D7C82269573214A549A8A4C5FB2D878F0F87C3A47F924933F27 FA6ACA91CB15A7789FDE857437A10655F22D5EDDDC113A0833FF344847E608E7 EF4CB3B0F475FC11AF1E2A4E7B5F9BF2A375D156654CCAD3FE79930AB9EE18DB 2CD9E4209A321B6C29DCD5CF5B751C52A5EE2B71A3B6B45BF7D6CD5A1A8E0A6D F5B385B50BC8732148F41C853E1023787DC79FA8D80AA1B0283EE857F0FA2156 07D55DB03D0F96FDBC432F3DDDC3809E2AF5200FFB1D443F0D801868ED2B9D59 CAAA0DB1133E062D50031552C2A914B8C61CE13C7F05977B5D7B02BE69A279ED 2F8985B75B5A6924C12A176352B199518B0BDA40FA8B7743574546C2A9B7B150 32E03512FAAF5B08E339D918CE99E91465C80C438FD222DD3D04684990507998 44012C55EA85D6EC1119E6298F908822CCAAEDD8D823517AA29B0B64C9FAC769 341D00D5C30B05F712404487DBD6B39AB9370308B11B85F6D773CC2E980D9B59 E6087FDC4CB8E8B077FE69279C848EAB6E46C2AC7674DCF9F304AF83888EBD6E 4491849A5795874D8E6195B58D6E4CB583427B9E6D8D0CA5CD75520453EAB3B1 8CC75F61A8EE70B86B150A8880ABE7A239D337F82954D4EB5F360E3BF51D8E4A FF89CCBBD4EA2B01DCF79AFB15EF5057844C18083CC33A4FADC7FCF95E3E65C2 A8E535D05DBD49A78C615BC488F21A45C3D75D26BBD4573242C71C5666700C51 9F68E411E47AEC2D368ABCF66587352D3376B354417C183C7131E70D6E872DA2 D7A318E93A528DE053DE3D00C9220DC9DB7DBCCA28790D16CD71D93166B25617 5F87FB1EAB884574645A2D7F117E9C92F4930117F01FB72C4F91561F67127576 480131296965E0C66E8A0585B498E2E1B92547D24D7569C7C7A6B403C1964C0F EB3DA911D60CA7902787E3C2043ECABABF30987AD39E34BAADDFC44CD1FE26BD CDC6A451F920D5CBB6777A8FC41C7D17A0C8082E1788A1BBEAAC5E1DECEAE577 8DDAB68ECD96F5FCCFBA8908C0BC6154B38C276E2407FB4A7ABC2928100CA45E 36B0CE7AC2A97591F4D19650337DCCA4C0AED1E862D6AB994546CDEC42E5C3E9 61412D89735D609CB0F651B60E168F461BA54784888E836E1BAB44D976395D07 59C0AFA6D691EFD7A90E7F348A694BB239E89B5D617E9C1DA2D9010CE85F1BB6 F4C40C7B1E06905AC27777EE6B6A05CE3DDF84EE3CC7F707DFED189EA2C64F0D 102105AEEA76BC257B53C3F070693E56F7B96A9D88EF2CE330A6BA40BE380F14 4CB2CD61BC3FA1455387E77CECE42A3128F81AFB1C0BCCFF85A3B28035C973E5 CAD59E9D4340D30BB368E63C3E035AE77F2CAF3F421187E51F79CC9F4B993F2C 15EB24ED0471867C7FC4DD4F3F3B6BE87F11D93F6DF8A4A68637AABCCFB6766E 8B145818727178FA3E5F9FF42C2DAD7DB1C2317369F40A1AF5D90CC6B2D8861B E3B39CCF40BAD8C7EC9A3B6FAEB1AE0893DAAA83060163CF3E2C66179ED0F4C2 59D61313BAC1CDB40CBD55E74D3D174070A1E2A06E8FF99B5824608CBACB02D2 520C9C174658F6A1BFEA6BC9CFB5EC41EF8F3C24CB09B3C6C461323F22AFC5AA 52A6FA94A1DFEC10B2BACD31CBB108BAD7598D4535F9BDD097C238762C871228 A60D7ADF8A9036F101CED52C97CAE2B443B0991AFF3A1B4F6ACD34B978FD8DE9 6B4E6FDE9CA82494A5D3A331145DE63AEEAA8921488E3617B4C28BACC60D01E7 8DB765B97021B7EEFF9353D69889EAFD1C2F2B1457C35C2F0AD5B7D718BD0056 B7EAAD46F9437411443937971B221B9D086FE284734B7B9FD031EFD704EB9944 311ECA39196A0C170C5016A0A7B7D29BD5B806D0E80B52934A8C7C068852E092 E016DEF614122412172F59003B8B95E511647A8817F751869A7D3D748D2D1AF3 C17EC83A86113B7B6923F9F5E25D9689A26BADF35C7ED4A53D0D25DFCCD711C2 3299FD9865515E4BAF7FF03B2E0B364EAB23FB35AFADF406BAEE2A648E755D12 3873C64353E7E71FD98A041BA2ADD45D3CDC2B9D7C53B17897304DDECE4EC1A2 D54CE09946CD5EFE55FEF4D4BBD7BABA04DA6739965C13E9DC428C77C99F14F8 FE2FF9A58D491F2E775A0495ECDDCB36600D3B8E16267B67BE21F129E45AD42F 05CB3477CFD4FC9212A752D84EC39AE87D083F413DDB741514F1E01CAD057EAB 7CDDEDF3D4BB88EB9616EDC4DB3D1F48B856DF317C16E9D28FAEB218F61F62DB AD30763290E93CC081B9D5D9B115A5A482EE103F3B53DC99532316E47E6E7C6A BC24052001FA3E6E65C1D8063E775D65CD912FD5E543255DEEF49B959AE6CBA9 9F215A864C31ED092F470AABDE5BB8DD3934A4E8B4878A6801CA5AB6EF959958 FE993D9C06158EC8215534691A9EA63DB64CD3D9CE829830653C744CB0B0D3E0 1A4732AFEABDD331AAA045E9690045F1577D2B071D99D11587B9747BC0EBD8F2 6FAD07CD0CB52C4B14F2B3E0E661CD04A2A78584BA0102C88BBD59DA8059A045 058DA18270DD8D017D3C3444216351745DCE03E3B61281CA2C1E4F09EEB08D3D 65D90908EB3252C16E47A5564319E7A2B00E33EADFFC576E561105800D103D84 6BD6A32EFC5923D8FEEAF756E32A3F610B42FFA00F13DDF0880B1CD099FCD65D 972BF81D24DFE078D9981E9628AF7D3BBD3128BD40908625508CC68E98B974F6 1954DFEEA6E77CB556CB3D53E42FDCD8ECA87071D331FA6C857889AD8676F0BA 5F470E7D38F364C28C06689D34AE9A64B31D895757E2A4E48B0D7D3D939C5FCE 81240A2954286C26705824487134EBE796CD0E3C798228A796D55D5B1048ACEC C7DEA8FBC98BC185514EE689C2B5AA52B0A624C81C0AA77D2281A9A25B9313BA B41258F70484A6B76B4D170F87354634C79E1E4948552F6E54B8EC44F0CE5E3B 74CD08CAEC2AEF9D11C82FFA6FE4036F68F33699931D061F08C79D0E965A3B74 9B9607F3002F9594BA9211033519057D3500E7E7317A9CAAD8CDEB844D3EFEEF BE90805CF99055ECBA8A10A7639C03B67CD35BDAB7EB74201B4F652494E682EE 1C0A3DCBD70B9BEB7023D16CF2D2462A177CB55BA94D35180FCF1C2ABE93C09B 998F008584219AD52E61EC4311E4AB9FEBAF84D501583338AA1E892BF72EC707 15A34BEF1E925E2701893F8EFA8F3F7F6D214D2AC15C51D9318FAC2C6231FDF6 8ACCC8B4E99CFE0547892BE76599F71D8CF7D4865F485DFE3F1D141415C7CEA2 265A6A5A663662B5C73442A1B7C79A70D0956F01205CB375E2374EDF4F436187 2DFA83634A2BCB2C567246E6A99E6A9997580127415EEEA775288532C555F119 F0A83D54E8E2C8F07FEC66B167FDF079D60A004261F4C58E7D576E3845DE99E6 E20CDECBF8848313E1B73F31312EEAAECFC98B473F768AA515DCA0CF68EE5469 F826E0D4883C3905F323AE21B8D87D1CA9D91154FB6977C0F64E70FF842306AC CFF4AC5710F67F54B0E9221391204C4AEA79A2213DE37C71DA6E7FB4D26DBC8A AD259F56621005581FEB5B8A255513EF93A3886D1ECD0D220C1DBFFDA668D5A8 CA91AB7ABD8B6BFD35E2895010230298D8DB8FFF445C71631EFF51B13D02489F 85DD6FC5CD4C4CDA6027A83BDA87FB86FDF83367F842B72682D17048B03BB40D E7F8FBFB42DC50B17DF2142F32176CBD05307E033FE97C7FC50EED70B8E54F0C CAA1220C6B07F04981531690C98FD08F568F0C0FA27F37EBAE6BE8C33D4C9992 4BEED5C206C9B001B6ED1BB8076498B28B3A518B2887114C75005CC69495CC9A 12BC0144B00FA89E47EB55C677FF8D0E8A0FFA0A2E8E013DDE0CCD85D29423DF 82C5FEADA367E07B704AC7BBDFBE0C0155AC06D4752B03FE6E69754A7E62A75D 898FD0AE8AB2C62629F97F4C2A4193F396B2A26C9B9411307F207DD192653473 EBDFFA0FA5A174F357C953BB95BDB5C535728296B4E98132ECD5D5591BA83661 45C9F858A4E89AA0CE9E3E194E9CC64AF0A9B38A3546D037AC5A6A088BD41A49 A4AB8D6EF963A57495271C26AEA620759D694ECBAC418E09F976BF46F4ABAB41 2778479DB20DE753D734B685C13B2ED5CD691449266475884FCAD95FD27548EA 502082FC4B23FE3B4409C782E9A6B900A6A8E83A1FE54984DB13604C31A200C3 F033E4B80CE194FD1D7D17B1A2AE49A1050F18D434620CB1E192F9984113D2C2 AD2BA90E009F1801C4D4E0E08605A3ACAEDB6507B3705A167B53D6265BAE1574 4EF509C228CA725454B663D7ECF0B2D87FA9A963DA3E2F00F22FE13BD8C41258 6F11421747A72A7FEB38ECDB5C5C8A76551CC14CD4178E15B4CD0B783F1F51D4 5402D629C94396FB90539745BB8B1C29700F3D7322587DAF429D9EC152BD7E55 34590B5937736DA9F8030C0F067116AEF51AAFA482BB02788ECE2753093B83C2 13F9432CCCE3E5CE94506456EA5C05EA544831F89D4FDAC64DA96345946CC4E7 F83DB1DA9EF330C3791FA22D4CA4C07EDC7C 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMBX12 %!PS-AdobeFont-1.0: CMBX12 003.002 %%Title: CMBX12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (<http://www.ams.org>), with Reserved Font Name CMBX12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMBX12 known{/CMBX12 findfont dup/UniqueID known{dup /UniqueID get 5000769 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMBX12 def /FontBBox {-53 -251 1139 750 }readonly def /UniqueID 5000769 def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMBX12.) readonly def /FullName (CMBX12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Bold) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 39 /quoteright put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 65 /A put dup 67 /C put dup 68 /D put dup 70 /F put dup 71 /G put dup 73 /I put dup 75 /K put dup 77 /M put dup 78 /N put dup 82 /R put dup 84 /T put dup 85 /U put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 120 /x put dup 121 /y put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2D43A151FEE81296FBE 0CF37DF6A338C826464BA5198991445EC4BE80971DB687336AE8F74B516E333D 2D8AB74D362C559AAE6ACFAE49AEEF4F52E28C869222C1301D041E7A0BC1B608 1BF728EF9E98F3A12EB2714E7F16B14E055FE1FA0EEFB058860ACADEDA9D0E4C 42E3C6F1E4869471BFAA3760175F3FBD842755A9D7847EBF605F18293B42F557 FBE2715002669091BB033E1AAD657532F34F7C66E4F04D63ABB07E6CB9D9AEAE 78EDE8B79DD9BC87A1FF445EAA05B5572BB880E69F4DE1F82D7F0E9980AB0C18 22C448B0B1722D3CC33C56FF287CECB80658B3AF5E7675BE82CEFF3DAD5942EE A03C955FF979E41E54BCFB5316A9AB8945C403A73180D0961416EC9C92F49811 4B91BC4C788392994587517718521E416D469F69952149FF7F9224377EBA1065 4A727BF806A112A7B45B0A1BA1D5A23683960575368D9EAC8C04753BF7465AF7 95F25C258C63E4FDFFD0B412FD381946AA38C0B961652BCEC30322C47BF4755D 9F91880688AF066E32FFB22E1A52DE741307AD3ED830D6BAA1D1F562919666DC 5E8FD9862AC8600B0AE0BC7FC779252AAC57248744ACC8A8AAFA836BCF09B0DF 9253DFBB1CB77EA8A59D42D1B18FF25E9AED72FA62FEC3F126F030F5D7DED9C3 CF60FE890BA4A48E39E687BFFAEAB96AE542A6387F6624486037C8924002A511 BEE5FBFD780AC1D4BEC3FBC47A930BAD0280D444259528B6C565DE11DE36BB65 9BADC55C1EDA1A80458E98896D782DFB5C137897419602809F9BF8CA39F00C68 EFB9E076FB324C2963F23CBFED28B9EF70EAA4E4B903225D1F199A7162AB239A D92D71C18B1B682D04C6A48926275BCB16D413B2A0E953E1257E0B12D8B717CE 2EC84CFBC046A4338A69F454A469B12118E562B4F56C5FFB3CA5D357513E6FFE 947A564B229C7FD873057D5C7CDF03E958294A1003B37D8DF565A70A00A3734B 0138AE5277D383D10C2BD853EF806D3CCDC47739F0E374A3DF3B63638B949ED6 4EC25869DC1C0B1F4DBDFFCC97382841D8F10F3635C792139A1EC462FDBA379C BE0990CA2E70FE73137AFBBF30CA54954D7E7377CC50BDD780DDD4C7FDC77AD2 F3EB1169F14A0041F18160F43C24FAF556DB5D621709FBC544CE55424F7446D4 6AC07A51C8CD5161AB0AD5084A96FB35D77F1CA155147DEF8D7A590EA6939514 D4A226588295CE0007BA8A550895511C8D80BBE5CDFB8A50D249C3BDCA974415 F5557914A9B805782F399E4078DDB6264F1A49A9A5BA45E284A5196E9828EBA8 481D357B8D9E6ECA631A6204439FDFACE7D7E6A2392726107CB7D2517CD19A24 FBE592C119626DB221BBB635B6EB84845C16A9585282E34958B961F4A543AF9D 419B6A9105BF185FC767712D923437BE08A9C0EB92AB6792DBDC671029B6FCA6 7F717FCE379C0F3B51C6CF042A762ED04898FBB4B0105C3C4ADDDC18C51BAA3B 70A93666669547081D9246732CFF74C83EE90DA17F5B4F8BAF47FE4D81590988 2858C9B96071341FA0A0D23BDD4947FC9BC2297913CFBD4FD6CA4303AB3179AE 0203F1BD502065F90CE9BEA3B52DAFE4A29446082EA0E6B1D7AF1F31D0AD02CC 9A7FACE2CA86E5FE0F6A425B28A5940ECA306891CECDB3CFC7A5BBC76B5D9E8A C754379ADE80B4D72CE493010317BF21A0CF4A0A55C1246218839DCA3F4D626D 1F4161D38F54AD5142C1CEE95C61D8BB10FAD4B772F4955777AFDE8AE5A837C2 A2BBB11D0BF5DA2E63D0B75ED421DBA9C789B281B01846B65DC572BA69591969 21265DB722AE86BD8CAA3D887C975A617ACEDDFB7AAB341F47532AC0F354A530 7662C089DA3939588774FFA16FC4A52555DED6D6F51DE718BF5F345C23C90198 17B77CB8B5D53A5CE7A79F3E286B6A59F3F6178AC8BF15C0A15C1A8A95D03B60 30EBE53DE328CE085CD9A1D49C69AA299C5B58B24334A546F6E274C1B534DC8F 3289553F560C2F81E413ADB92FA0E7DD1C2F39D5FD268EBA97AB7335ECF28257 96B4EADB7D0778706CB41C7E9C882760E7670936774A1088FFB2011115FDADB3 B69EBD5108760762521C25C968C3E282DC3400001AC8FB1EA27FF643E3025950 1D617BB8BB321281708E496277E11DD3AE0023DA9F25AD06B39C7CF527FED27B 57397E88D3DF70EE4FCCEFC8A0927D6B05517E571B3E70ECC99F3CBA32CCD4DE B8BF22626B6C94FE65598A88AB90D238461EBD9A098DADEA4091AF1CDD7560EC 8E1B9BC2321686E1759E6B8A270C8CB4A254F7368039602EAEAB86ED21CDED91 8F2DB9889F46981C494C7EAF5E819B91C129F0740B8002B510014985E5791F59 B16879CC6521D8E9F1C4C1890AC85A78022BE614BEFF318AB2616F0C3F02405E BB425D1555472A2642BA7686E431DC3FB8A1688B76660D9957C3FDE8D58109AC 21B1234C9DDF3F0FAF93BCF7B2F88A001F23162E1A13E5E9118D51B485B70A91 D0CBC39CF44413FD8686D9030782DAB58064F5B987E0402AF5B264B17BD31BD4 FDF63951BECD73ACA6138854EF35B062D01F33073850D9C09A818828C581241F A625AB3638081DD0F00F946BE5450D38489CECEA4E66B4D85CC8AE0157E2AEE4 A22A9313829F24D573101D84CC1784D1CED7DFAD5DD966601370C6CCBB723082 A86BBAF0A5D867D0D2E3CA16E14E5109A29EF02649C47E12E88B3B397D65CACA DEB9940B92100744D686066F8250FF30E5F13D81428EE238A2E4E07ACE0F5C38 7D79D4A336D0D26AF9C2B84088ED8ECDF94A1E3FADB45AFDAB46CAD6FF950B0F 07AA2CDF82374DA76C56D29C80138841EB13F0D02ADD32F88B23E282ECC845F9 BB9AAECE9CDC644AC2D49577A92307A83A99434F6493156DF25DBF0FCF2EC21E 8C50A312C3D19E0609C0038554CF4FEF3ACEB7A833FD54B06EF0D617C2971C89 E4C06075B09B84A4F78A82152B9A9C540B1D881313C2C74F20ED064A9606EC2C B56D7BB4797F1EEF4A9B13579CCF311FA4A4DFA62D80FDB7F535CC6526D1AAE5 45C008EAF024B48C377522F74D939A475970533E645B1BFA81997549AFF26F67 2AAE6C2EFA357DB3B525276EF330905688777057F4E4CBF584520A534A8587E5 5A8360891E75A15205E8ADAC4A4E5A6E27D0C4A7D492216E4BC023AB027F37AF A8DC7579BA50204D5F45A51460C5BD8A5A7F87668CA6451137F2F59E117BBE28 5C40820882A5546FA76F0CF49F8A6EC445F0647CC3227C400F56E7E9B84A6975 E85E243CC1666DBAFF4E07EEAF3AF71BDACB30DAEA792F2B8504CAB071544F01 5D66243D529C479D276FE22F7E275D9E7FA9C6EECA18716B2F213916E32C1D94 6E32397B41AC6779543218E506569E3544803BBF9B404A983EBA62A494187B30 8D3DFA4E1237A2E5E08224A60492C09ADAD8775B7CDB830520829BA164209ACB BCDEB2D574CEBFB7AE4BE72DF4EB1945FEF2458761AD8DCC0D378AEB7DA002C6 9C14A665DAAA532B0ABA98D7BFB5A6151FF6703385AF7AE8FD315A492FCCDBCB B825707F9566B3B4943A3C61C3DEFDC31A843A2D67AB06891F3E110DD8C73D3B B5E4151B51D9F13905D7D94DB9ABBFCAF35F43B6EEE256B1A80ED6D1739D8D5E 8C767F6F0E8704C5345D028A2A6DAFD9BB7AA048B8B895FE9423A7ACE858BADD 595CB074A128DAFE08FDFFD6BDAC0114159A702FDCBF8013804B0CAEAD7AF38E FAF086A3248AD4FCA1401A85AE2F72E3E6956DC0996FE8ADB18F89B14A208A15 13F81AF73D0DB72F78C4DA634ADE3C73756CAE6AF2E149C26316DFD93370BE1A FB4A79F77A67C07CB0A53C78367F21661D4AFE9E27328E077B522B50FD9AE2E3 DA087BE481515B5DD7BF894A96A84A6C78874100505B7DDE1D22EFCE8D58B3AB 313AB5495F72E2CA4E6AE22C0CB854302B9990372F1661D9F0A517F90686F248 C5643008B3D29F7296E5C8FD4049886662EFDD4106E17C879F5D41CE84F87E89 F6A3117C968B95A35940CC29C43E1E0DEF51C1E46B676301F40D59615C3F73DD DE37B72FF7105DB84227DA5241583272AB1C3CD97AE11C1EE98FFDB5E5F44844 8FC41BEA5C54B26341AFF6830D9D0A5A2901B0653D8BD0746838194D240FF753 E99750D3383373F453723D86BE97B571B8B84D8696089B5CFDD53E6C562A2197 A8C4FB0CC690C27761A816B441029D3D306245052E0C41B53025D8CB7267CFE3 C17FDFE348E765326F91AEB700CC49162DF748171214252CBC821493DD01AA20 417D66DF47EBEFFF3E9BB2B0A2BE7D9B8C68BD570FC2EB0FA54CECC318F04C43 19598BDE93F2F13DC7847354C99059AB20593EE51E94F9D4E9241869D605AAF4 9D9B5FD88C3798A039A67993C5EC68B6326B132E647F67EACCA7F7AE7F718D85 12666E90D7C73EF210E344964A38228B236679A2B18F5E081234CAA2458F8D83 3F0CA308D19663CB12EB904076EF88E556407C33C9380A6A3D68A9EFE65387C1 A1BCD2D26DFD2AC0881EC30E81C0A4E76C244A2BD822EE88C4A60B480D107E68 90E419A1F512E865BA922A7830909BC2611A80931CB2E9344529586726614D94 3AC5200FB9FF68AD9686506C5EFA8788C0AD0251AFE7F95E84683380CDB421C5 B1A783B6D5F3A6BD1BC1C14B363DB01C87C0796DCDD5BECF41A1A9F43183CF6B 82C2AE49F0BFDC5DEF7729F2E638EE6EA9E4D059EB9BB1B992AD8C82D501A550 1BF73CBBFE740179B54E193E84A55DCD61B343C1852780FFB44248FC9426AC94 AA2B3FE20FBA30F6C4D1E0FF3EDCDD8C0F57CCB50CDB0EFE2E04A8927E239C1D 9B026C7929BB48461D4D695FFC766C8A0E545B1BCC2AA068D1865333108E7985 2D93F9B00EA0A90939D0D3840D59B6CC0CE2C147B2E1A9A4F14270FE3ACF51D5 99F7349106165AD627CBBB0ABA01ECC6D3A14C1DC1ED23A9DB9865BB4396C51A 31ECD001EAC94B33C34E29C5611148EF3E55DD61813470B8F3CE32564C749414 3C93C77EA5A3538A0B5AE3FC4DA32813B06772E0E48E25BB39F3F6FDCC077E86 F86FA50E18FD19EB2F37311CE87F18F3BC85CE7FD71CA92D5C3264E34E04A2E5 70C79D99F54D6C6D9D527AE45EBB48411221134587D2253E7C8ED7658EDCA34E 5E768DD14E0200470F73C44D006CE8CB35DE1CA3EC10ADC668B0662A7774C891 84EC95A31DD872F0728D9F65CA80940080E04630BE4DEC77A2C49E3913C39978 BF145F8832AF2C4385EBCDB15F9D32C22CBA0CF950877717D6F1591D7C0B8047 8C9BFCB16AF7124ED83137695F3D69228DB633053208C29E0ABA1B06A7FB3EE7 5625CB44927E2DA6E038A6E62DEBDA2D96A03177982D8FA33BAAF4426E05F4B7 9C1748B3FF7691F9888E7FF864A10B9DF761A41E6B5CFAD2BDD7E1C4924AC97B F4B352705316DD1A58637CC12D71C18A5CA691AB2AA8F171590EC24582B1123E 94D4DC587D8F99E18A711776BF4013C96446BFECFEE4C809EA94B169088024DE 0CBD20199A915AA406F0BD5F3D63D1467C49B4691AEBBB35ED6624F2D7BB74BC E80FD92B9FD04DD9C2BE9B6FD29EC7EC07FAB447511C61DD299C783BC09AE2A4 7B3CBCA6A20C6631D06D0B2E2482A50612BB7C29B7E7D0A205EB0E8436702581 596BC996ABD58CD8D5BAAE4B1478195CAFF98FE0141287296C4EFB8D2E7A8442 F0A3AA9F9264329982532295A176BA1867EF732BBAC49AF485D9D0F7130F617E 7F7DEEF935874D55A22240F8EDE4F247D5F73481373A392D40A8076BD91079E1 1CE5998BA13D48D56B49A92B4A18430E316405D2E2E391B496A1934671FF1785 AF42BA3B2D14B8E04014437FD194455C50289DFBA61B5C377BCBDADA48E82DEE 4E70EF5E9DC03064907BCB8BE4D59DE069FB0C0CB140DA54708E630767313F9F 744594AD8A499CFEF733E640A11FD74E46A749F9C7D18D49251BF85C6EB4668D 67598C31A8F90922FEAEAD4B83B6E7184567DC798E4BA1C4C9B3461A478D63CA 054F13B502DACB674EB49D6BB935E5EC82BF99FDA7D47C581AD7F940DF4FC6FA 6C6D25D647033AC69505F0CAC58DE99087F365531A6283CB89CB644688963C3B 8B2203A94294E58739EF23C7803630A1F9121D62BE1977DE2F41687C8CAF87FE CBD7AD3B98E0D95C8C6E1A7CCB0E09465AA874DC90A0F5DB2C5E7C130297FD39 EFE63B0350B5139D09E6864D22C3F1150B29196E40EEF9723E71158B7ECFB8E4 C426FEDCD439420B7F1C251FADA347C9A2C49738B5A17922E1EA93CA7B125B76 57449EAA9C1D591CAD327D0E98EF2D44D614EE9ED49DD31ACAC0B956620B6BA5 5BF6D08CA7541059D5ED2EF00AE2EE95488F5645BF6837D9241C0D3959B7580F C9ECB2BCF3E65C07D52EC9CFB21C11CD4C883E44C173214C900C44D2E1E43DD1 CE8DFE3DA93C38B548BC4EC46FF91F30CFB97525E1FD4E77686433B20BABF8D2 848C1CDF1BCF185CFD7A81D2D4BB826E837E2AF35CFC4F419F698DB0C43E9F9C B0FB628AC9A3CBE9B1FF4A067016E70333E78B32AB2D89C483834B31F5808FDB 77492E099F1504DABCA5722C7860CDCEDB2DDEB512FFCC7D287F4945FD711F28 87BC3D36173566B81FC2C1290C717A09697DAC6072408E20926D39270121CE58 3EF97CE12EDD7F87F2C8CFE36C3C0400869C0D813B71C425343EE0CDF717BDD8 409D5297D0F8F7FDEB0257C0A391F5635E0DB1116058942FF3E7C94D5F2873A7 A3B0ADAFC3835AF2BE474E6741319BC6695FB37F59AEE388F81F6E66F910000B 72E6BA7531B4378CEFEEDC79CCF4947BA1703823B5AB4F4AD73D9615C66C489D 99D68E49C9BF765B7FC547BAB9640D51D5A7A2396507AB5A4DFF3D14F52422CD 8FCFEAA06A56C6C7FFCD29C9A7A59DDD2A909A9363FE5F1E9629616D25ED38CB E754C059E4379318CC491C3B1A90128693AC53F80F8210FAEA7EE638902A7D3C 82B95B3F5AE340EC1B648DBB9FB679D6E80B7F426D8671FE7136D97F51E2D2F3 C9CE9183E4061CA40091A2A70DBB9ECBB19CE3F65ADD0FB346B54BAB182E2CD0 EAF4C0F402C25573FB344EA771B297BEB615FCD0595172E84ED2A62FF8962634 23C19076C2A9ECEED5135994EB397303A9619C76DC55E032DA83FBA441BD484A 59F70A5110A8927F6239A14D4E223E189A5462E4A92EAEFFA4B961A2A32B320F C2B4E8C1821FA67A655B5042C15E4DE1FB3652B55078DB123573C4E986B19DB0 1C5131F3DFAB271C30A5476B4A19D8FC922E31879C34BAED94C07A4841B8209C 403369FB8E842610D1EB4662B6171A4465FD0E819964F62EC5B0ADC92F08CF90 1DE0B410FFBAD16F6D355E8AD72CCF67961EDB6CDA82398021007C2D0462E893 75EB0710AE4A6CDD15077C9DEFC5774EF4A657734D703CE42174259B58E5277E 0DF26BF59AF8D1A3E7DC12E3C12AA4B67CF35B19962F6950C2020B698D971B35 82FF84E72F72FBB0C54A112BADBAE6C4CAA358BDE6A705AB59332C3850CA3D25 C7564499BC1319121CE0D93218210C68080AFF33420E3CB3A48BF9EB66BC07C8 A79D8CD8E78C200FF7CFA3DAED0B9E87E6141C88B436D8FCBA50AC195FCBB9BC 9512B95FE3A37FFAAB39850FCEBD4D50A243EA416E73F53B4B00F3B6EAE0CA06 0693AFFEF215D00BFCAD02E45496D7C8F5E99EB9096FC4300D038C1AFD31EC4C 5ACA6B72C1BE7204E37A4CBBCB1EC26AB87F2FF82DE20601025169A5FBD2D060 62B5B2DBC288C79C33B596832AA18D730AD572C6EDFABCBD36DEA87C0F323C3D 6E537AD3B43C6F3A905597570A8C6B0B4A5E08C08EAFF9731E745F2BA8ED0C0E 1ADF7821CFCD4E38F3F4C243CAD31D9F8FC68B9043740852B4CCBDD37BF728E5 648215961FA82A0C847ADCC5187331D0863A4573BE520C02CAE14AED4F06B3F1 FB4A318AB54CD86DEC824707B29F858FD726A167F2333855C0575EAF4EBEA0B6 754B1775F967140641FC06F82B191244186FF347A351FBD8FA62E8C978B21F6A E124929876488AFA97FAD1A68A0C3496BCA768F4AF8016D7A65BBA3AAFD7F5FE E75FE714FFF3D54D09C9747ACA01CEFD260985C6E87477C9C7843343C7E9E3F4 0537D461EF019E046DB8A6F08DC7B007337B688E610C55A35496196C01E6F8C3 C7ACEA49F6AFA7FD9CC809E9916813F64BB5704664DD21422F8F32477EB874E4 D86593B4D4050C116B8861EFDC6BE1ABCBF942F0BBBF4E4241C418DD1263F252 B16F904E5B650CFC5763390916625B28ECE4C39C55CA937E28093E66A9837BBD 98666F090E8E06F1934736F800CDD0E78706E3F1CE6D2EE55CC48D1302770DDB A139EEEFCF8353D4473D89EAD552B810E0F1737A6636D15265E0FA2699BA0669 7D84AC5B1216617D02E4244BDDF1FC58BD441006AE56FC518796B786A3D5D0C5 AC21EE755C8D8137459DB46953811B0F3A594C57F12E46E8C0892ABAA08F3A3A B73E3CE1466FDCFD6477AC1F79A54C1AB7C8E208E6A61FBB6E2ED11941FA5045 84522DAAFAAB6BDA47189AB457D9565DEA706394B9CA6028C208680183D0EF60 ED71A39A296A6D5883A23339F2B9258522578AB5AA4FE8189C57333B49761E64 ADC063F1489F0E785A6C10258A3FFEF577752AA9ED3850277A3723675CA36659 67E38FE4D056969AB8C0D86A4049AA951E896C454D234BA929950DFB33C1B359 EDD9BBFDC44B0FA55382EA59F5F02CC49ED6DC49CCA49E851106B8A242746A4A 8CB65391C06A7FE3D63D48C76D2457083A4F5C31FE4AB2C6596ABA6FF853C2D1 5C85613FF23BEA9B7F6DBE01D523C587741410547F26F8073B4F9DFF036D4D36 34A3B2D91509C527C2E2C8C183F3F74193B0E56AC188DA680C7A2C99C468B06F D226EF0CB2DB5BAF83A899FB48498676B05D652F11FA4B823A72AFF70D7CFD36 17887333BC2F92D5CBAE7D7C76E903111A78E99BDDE5DBC7F6946A593294B771 4002FAD60CB843933A493C4109513F301475A682A5B95ED2BC96ADDF61A725F8 5E69D9004EBD595A8CAE5F34222D48942DE4D496AADFE6C839D8931F902649C6 5BFA480D9567BEE320624C2BD510C7EE8DD5BE099B666E6DF576A07A4F8B4BC7 C18C99A9D1435F6BB9B4C464CEA594123BFE306CDA2D650884F320F4C12704EB CA8EA99B057CAEF9BC5038A9ACF73458F122B9BD828C49CCD7C8822184ED5EF2 660563CCD40893C69B3CDEFBE44ECEA824DB2D8EC1A7D8B1EC2A094E57A0FEB5 0CC4C98EE3D131B6C573274C1DCAB70C3DC0DA251C7A9DF055FC4312F4287C77 0D298F636D144E3BFDC231DD6B3945C8A3203BF9F821DA9D9CE205438BDB1353 D9E9EF4BB5B342B726BFDDF58EBD11E329D0A415A6C052052C96EC1778CED52E 42690F98080EF2CB4546EE6C62F847B8A26220843C921D496D0CB462975EBD2C 719D2FCC88E5976FA2B2EE63852E9D9FAD22849A4727015E31CAB094D867CB74 45DCCAC7A9A68E8C9FD03C39E2BE34DC7D5BAC44EA2E659BDE7C71D360B24AAF EEEF3C70E84F88F6802E5430D82A6BE948443BB03C52F1E650F00335AC61D274 2D7696971B6F72183D89DF46CBFF04A5B1B6A71857B3C4EE858B6F1E1C7D0EE6 22AAD2F919F0199E279B212F8684276369E883BF01B8ACBB12C902DEEF9F5989 B8B54CA348C48D19182D79858B1ED3FE4629435540D16146CFF80A68A2D11519 9D64567E81748D03DD9703B6B6B44873ED70BDEA42FCCE7A4681BC2218A144FF F8D30D3314DAFAB36D7B27FC9A76D71C38A6E84DD0941B00A9AAEB20EC749867 B5F8C875D7E42236635FCE276247B5CAF43A3E333E15E9101723C354E79E2FA7 FE3512DD925FA0CA8FBE0C4168C8815561960F2E1CC2C5D6ADB354B06B096BA6 5A9E931178F6DD19695610A66EABD4C794A7F03F90E4D164C585124224E89D2E 5221EB11A2308F0E94E0686F124712C14B249E2659E0CF44EAB18B5CD9116200 08624167651094667CDF937F2D5BEEDD8D52463E7FE12BC96E56FA35CAA9F2EE D1EFB3CD3EF11F1D16D0C876700D4DD9F3B76310DC6DFEB4C32A03D977A3C5C9 A6868B1BCBDD785B54491E51CF877AF2E0C844A24363179F25CF2F265F4F03ED 078012922624525A08DB40EF91A3752768BAB0379DE92BF92CF0C9E7A5967337 6F9E3A293C253538647FA3E545DC35A60B9C93139F86C6DEED3803421F2E4278 91E59C1D598167897D2AC4A7BCE177757AB257FDBD5BB4CE6F7479B02B3CDC3B C29B30E8625361B9424BC3C05A7687B0F1F3AE55AFD12F9D8DDB18A060A22C80 D8DD858DB38B4B6BEC83ADF5743D81417950059A669A103FE851BC6D8C3939D0 FA3DC18E78A4A01581CF7307D9641332C84F6556456A9732D7578E63220F4A8C 941876B26A243E4E9A7C6CC8A3446B4E9E44C5390BA39A0D5F19C83D85521BD8 B71EB02A88972949F627D7AAE7D11307B4082426066F8F85314F146671EC7A80 D9E2064DC059C3A39C7465B54BE20596D5070E174BE39B83ECE5333F686242A1 E523B6FEC0C2C627044101B49E5F95F48872765331208C04C41A2DE4F566CB0F 276E8CD2080F1B79AA194C275EB8CA0C1AC48226A626B611881CEFB3D981D8CE 6EDC499B6C2C0C629763CFF543C47AA0E1893AD56690813E21BA17A814B322DD B4EDBFC899FCED33B0071BA71A9516B53909855D7669E1651242DBED3AFEF847 EDDFA782980A55C0F88151AC12CF0772A77A31E425B59217BB4D379247A0CCC5 B4943982D39AF98D7D7FAEC0C0941C4DBB29E40AF20C9175A4E22E10F18A1866 D456E4C5DD727A6689B515A1E37E884F2722C27A2E2D17DB645CCAC6AF69C51D 1122D0E907019830F914882742927594A27586CFAA597ECCAA63EA04B191B6ED 51F12E189576381D23FED58AEC77624C606394AF270571207948D2560AFE7E81 1508F658D28F390F3486047EA93792EC9BD332EBBAE511F3081F38A71AEF3666 D2C013287039A39DA8BC704167744DCAC8C8CC95D93B13B78CE6423307E7D084 8F78DAC6D5CB90EF1983D68F80EF2935F61D0CA5BE47B7E02EE0A6B49870A4D4 1D6207CD38C8B67B6123A16D568464544598E0893323CF8ED7702F4DADAC9F6D E2E4A8353EC4D8A72763FBC1B7ECFBA5D3B567656A50047C1FE699678D2DF9D6 EB9C0E35DE525CD3C7CDA374D3BF84C84DFC9D9E494813EBE92339D3C80FEEFA 0FE15B03191B7773093C25FE8DD5E0FFE68D97436E9C9547C130D25D7D9FC960 86433C5AEE6F9FE9DCABC5E7E939C6943AAE815C69402948B7D2B8A5B9B54BA0 6DDBD8C077324CA46D748415EEFD689965FADE219647BF43FA85717397F562A2 DC52276BC78C4741392EDA24B3B482A61CB4E2C000C22E83F7AA54257AB8C901 E3893B5FC867DDBB40A7529D86E80E61E34A1FCDE7E9660DD152AF4DE79504E4 EA86F40EAEFCD027DB72461C31D7B27D445B745533B519B87F6FEBE40CE4C2CA A6E9196481E11CB67D5E48E2BDF6A0BBF0CA49FB5E875EDADEFACDDC13F83ECE BB2ABD763566851B59F7B565A1DBA55AEBAC5C303241A8E2BBA512B78FF7A9AF E565AC23CA6B325A6BAE24149E28DA5BAA64D15D00A246FE138DA2B4EE6BF762 CACAC84FCF62F4BDDC47B537D66EC2D599CA966AFF08D4DB2D4FF9E1B1724831 98042A180705D2D8F134627EB22B2E8D039A9C3A2F5526CCB01CE34F34838D11 59D3A5018A1FD5482B41450769E735529140F5674B4165BFCED19378D87B01C4 A1FD2EC26B51C5EF8A91D243D4A97EEE66BC28B9DE12E442F9CC845F7A1C084B 539D9A048C182C64A46DE0849636E0CC99237D20D07ADAC3A9AC86AE9DECAC8C 2328200C360010AD29F2082FCF30E0E064C27404BFB26FF0CEF6EE34C0F4378D 41FDB4DF9CDB9FF5001416F09BD6D4C591C209919D4AFCDBE87523D0D3C6598A EDEEFE383D6592A7D47CB6BE2C445C066F137C3FDCB3662D07A2B96FE9EB00E3 55DF244D90F303847E4488EFF8076E81C9B9ED03FD1A519BE1FDA2F8F7165029 5A99F8A98BB29E365EDFA74C6E04046BA2BC503EB7C273D8D849FADE571EF158 09D1B40D14E5FC5D0FF53ACC988304031700F9C41124CEA510C4FADB3211078A E51A36C281A9435921CA39D69ECB4DB92C2FE64DCE84F07A86DC9A96D7872EA9 7E3EFCB7FB9DDC37B4D39F7404A43A98C2244D46E1E08D86B2D5493B8F10C2BB A375DCFC688DCCDFE633D82EC629BFA68DFB8062CA307A146C425D9559BBE85C F11D4D18B6A0F53981EDD8ADF5C984FCA68341848BE895B25A287AB4E2CBCD49 98AB06188FD55CDCCAB5BFEF8B13E2C40CDA50C2A755083730049DEF6F3B4F44 21DA7D7026ED822B21F3EDC2FFEC276C981F7693B2F4361D658EA9360DF616F8 63A4CC7CC817018A0DB3C6BCE780ACCB07E4E5806EF1F734E1DEAF02AD6D9324 582B242803BBECD1B3B1E066F62955544CC8EBEEF8C6D175F9663D3C4B912DBE 0D1BC7AC4FCFA632665A3F3728ABE2ADDF27CCDCB3417C1A795CCF4D29FF4BC3 BAEB519FC5BF65474C8E76A704BA99594E038F47BEEA87DBF6AF6823C10970EF FD53EDD64F0E25A3739B669F0FDA565606DF916B65D864B94E464C5C6E66D5B2 FD9B5A0823097D3025F2FDFDCFFC0E640189DB251A7B6C3581BBFBFD86B57B3C CDB39069A0A90371D90C0DB5A679174D8349532C513E7B5258EAA26D027A1807 7E6A76920D0C50BD5123E0E96E73765C9E6C3B7CA14883CDC577594D2C7CA270 9731EEF73FCD3476DEF6F5B60B6CFC3797316E394072572E95531C635ECC78B1 9BD1459D1DEDB4BB6B9D6454F8EB010D1788664482454746B820D8A96A778717 ED2237E8B26F6FA276CA9B49502759E200D54AA7B9778D1E7FDE49EA10927DE5 CFFEF8D43A1B7AC84235E42BD52D36DAC9CE1A77F0A44F25D3DD21131760ED2C 528820A78E5839E46D96B106713FE0FF07F34A49AB18F94B458BD3CB44A6DD2B 195117B33DA7B3FD59DE57AAC2511B9F6E9356C9ACF6A8B3AF337636C8624939 C7C8396409F5584A3D8C9304121B08A6140CF5A786157572545190395C4576F6 0593CA2BF35A153372B175DC16F62840F0D3586FE2F95E01C5BD8029AE3DE5D0 F4BDF873A35E34B583F922082B239C8EE5ABE439F37D19938FC872D836F5E318 BF3BDBAC3E74FFC8FEFD516E74A8923A15470E47F6B5E42DBB70F16B3AC13850 3AD1CF72280335EBECCC34B9EAF104D669BBEBA3508183C88DCB6542C7A77798 61DA6D6536B81B46825CA255D211E2569ECB28F037522D515DAAC75326FD97CC EB89C97AA04535A0072F08E1694F10AC32ECE4050CCC782449DE883DF80E314F 1AF07C96C9FADADC1454FA1D33650E50B3186348254B0FF1E35259755DA4B9D2 912F98A22751367DAC508399671076BC6386C9B2739C7D507C952C755CF01D39 5DDE4F66ED5D46E07A035EA3F7FC0DA4E717BA0550827B0FEBD4B2D3C9F1C49F 30CE63AAE859F8155AD95B776B72BAFB1C36C0674831567DD71900E8210633A7 86A6132A8B164F8FA6A9C6F67078EE7D21586C120A383CAAC5B7E75F21C414AF BC57BCD606B17004B2B4BF1A30F8E695FBA19EA7863B996EFEF6F86AE47551EC 2CD48EB097B096981A49A86FA410A28AB3A33279AE15DBC31C27E43B49E52B1F C29BE52B4F49BDE5BE33C69903030371086C566F0C4168C881778CE367A8C23A DF1096031DF2FA786BAE3815B5A12B5AF566ECAD661A77418D0980DCFF53441F 03A3231EB93A9C81913C0CBD27F9A8635D049F83B9DBABC3A8D13BE6BD35D7B3 6D0DBFE57A0B9079E7A54ACF11E93C3D8128E700F93A9A5FF63001512031B3F2 8F63ECB6585078B2D02EFE9DB9301C61284322FCB1E759966E4CC3EC353C2B59 11B1E6BAB38BD03129DFE6B472DDF405FD5DCC3A9DA445D0555508493518D8CF 897DBD5362421EBCF759CC9489AB1BF8E33E50438369E8A76D4444C79E0398BB FE2DC2CE0280AA2C677D8705D8DD840F7F34F57F4FBA9D9EDF0F45C924900D00 818D54ADBB1F1BEDE348A101FCB7142362D60B41C9068038BDA7F741A8DB4B0C E63DD41A610F63F2E78D8769FF2F99973B483FCD645232E12A5937209B2B77A3 2121647304F683EF84FB5A1EA36FC96BFA9E6D9E36D9B10B9473027EEE5291A8 B06A545D32EB9FFF075947E006BEB7DB050FB696ADDC440D08B4D72133C0A772 0E10582D171D38AD0A7379B9AE81F9A80CEB8AB3F487675EFF22FF6E4434E7F2 BF4126A05FF245429600729225F3154B500333B03323A5621160C2445F52AA51 31FB8726B4230BF69B6BF02974FC9332F9DBAB650844CE234BFABA6C7C199C1B DBD7185E841AE7B1477FA535F0B83DF5EFB31BF1C7D4E63E6E8B6B20D271C93F 2FEB0214713C602850A93B8584068CFA40C33CCE02A4435C70459305429CB82D 10EB3F75243FE358EC8E89FF66BB32C5A8D161E02D920470C1F1FFD65F3E7160 0EA5BA6CE8BADEF989E9E0E8A3D43E72F4154CDB8DBF3B9355E32F6B918BCD1C 30043D9F434FAE3938F8D2EEBAF62DE510DA6B84E8DB2EC9C454F6E98DBAA5C5 F5F3FF8FEA8AEEC8A8EF7F9B2CC110951B77B16BB8FF949F8B165BE5DC7AACD0 C856B790F1E376DC6071102CA7D4AFEBB63A181B09C4C39859FEA3E1824C5784 1B747F6D7482B65F9C18C012C2435A10800875E080FA3ADDDA4C5F3F5342382C 1D3F7D7D0BD6B260B3970BC3B67947CD7BDBF5F58536F7C4F1E8E953CF03DBA1 39C450FB7A00253FCEAE8121D0327DA000C36A77F329BF37A94B123E11DAA04D 77AFBFF9D3FDA52A9044B0657C10BDA86E552381781AC5C61EB16B1D06C6E254 4042C7C6A6D0B9AA52EEDE7E5DC213A72E5B55DF6CC6218A98F00C0E2FEF569F 0772BE6A66C181741A63292EF88504757DF7D2AFF47D0D4A3D4BF2D3F050CF9A 372908F72668E8C09443736C7CF60EDE6AE4956DE78CA0481A97E5B69AC6BF34 47B684B77CE4C4D977DF3C570C01E933EAFA1B8D1DA5EDEA89F07DBCE613C846 14AE43F2453C70220C06E7CDA466560F626E4810F29D51E775449620D2D60293 AFD4B8BD0107469FC1C335EEA22074A4881C9E975D1F93C158864892208E6373 9110C53EFBF8166648EF33565627340C7B80E9FC19C39A57D4A297334687D4E2 13E006ED8F3F993452076B780A1EA37DA9A80DF0C60F20D987600A6AE29B259E 48A2E28837124708EC1BB7A7903229C2C2FAE8F490BD273490D4D663258B540B C83F17F7E7966E81D90A628E4BC4811381554DA41E2E58DE9E28508B5165A3CB 246E1866623918570DC1F43BE86143F96417507EAA02FC3372147F7AEAB40B38 69EF88168A4011C6B4B15BA63AC28F0AB4D8CB2968A4001DC6595DF01362B69A 5A06E775742F7618EC3878E573391AB5E58C9829FEE6FF533CF0940645798596 8BA4947E2AB5AC3506F40EACCE97ECAA18D3042237C6F4C25FD1E0C120B3537D 41449B179911E1F8DFDF210A6FAB085C1076234E8F17D3CF4AE2BBFF085B310D 99C10C8AD7A70B991ABB2C5A30AB833D20F5F12B6F51701535921E2ECB2DFAE9 E59BA98C3C36374272901C9A0048608D196CBA90C14834172AE6A5750AC09D6A ADA7FC6F045F77E7FF2D23013144691C19B727C47694428BDA99173B85F2DFD7 5E07E6A1DD8BD3EDB4453939C435C3FAF2CEE6DACF52E9DF383299922772E43D 0664DC2E9587AEE01B49F8D418BF258924CE8AE748BF96A0788108BE4F0052A9 9B2E82A7FFAD8A82784C75FA431EDBF36E67E0F69AE4B02FB1FEE867A38A83B8 D9CE1761ADE270C86C291180A554EAA3928FEB662663DD20095C13C1644FAD24 43918F864ED0CF6A53D29756322754272A4469B67AED6F80A0EEF4CFFC405BA5 39519F9DA7BF34EBED3573521ABBA11B6FDC8F4A3A6727D2184686758391E13F DA9ACE21D0D057D888057091E9B3F2596A30EBC262845220458FDFE11F1AC55D 0D56564C2B9771A2F1599DA1F8F177463F1899FF92E05A78BCB4E5E860262628 2BDE4F7BFCF76FC0F894A448162A6F9F8FDA33E3364CD7817B9DDF5006DE2A63 EEE8801A0551B6A9B7D3B9F88086C5530F2CACE0B2B06323329C1784597B8A3E 94DC7CBBFA637D148BA32F1AAA3D9CFD6D880EE563BE5CA20C781ADE0E864C40 E2EF96788DFC2881F041AFD99DD4D0D165D3AAFED7EE354E87A191707E82BB31 3BE4364FBE508A84F3430B86732B686807119E17963002EF666FB8D060774964 DA2E626398F036CEC817444CD53B7F4B860DF0D16C86383149C1DFF4D1B4DBF2 DF604F64F8EB876880C4118254A12F44CC7531A0D24166EB23ADEDC3DC48B7C8 86894D0F06A927E886741A8B48116BE09162C8B190A1F5BF907CF1A01D09FC56 DE45E76D7CC4C048B85D0A5450F6EE3F4E2F5721579617EE33DC2D24E3B85137 BF483C0E12D8BE891BA3F86A32BA97969C50B9226A7C4D06779453B1E33E565A 2AECB628A2445635D51604F0EAF567204361D695CFA3162CD407703FBC5AFED0 89CD9C90A269A8D3AFBEC1300128F069F2B69B92682B0BCCE8CF814AD967282D 201711CC80F4737E7561FBB14136FDF936F96FFC20848768C93A3D7B95FEB39A 50F117452346F6B0C882B000CA0B32CDDB954C2A0522AB32F03C85A3BD8B75F9 B21F626957BCEEB66936CF5F456E0E284ADBC4A28887E4C7562C7FDDBC5D8EB4 49A655C89007C5FECCEBDB33225B2D29C737D327E7D9E85E57D915D3D09573A3 CBA6198F5EF90C7382C8BFA25BDF82E7F58879D8330E565EC0A78E27481A534E 15F45061AF6335533EC8EEB44B24DE25E2EBC10F4EF601F03C2242F03923880E 67893DCEB23A420C154A5CFA01A0C33549BDAB8CA56905F2328C5CC8C96BA88A 90B91FF2A39E90D052A4B4BB0DF4F2A6724B92320F3C886A6B8ECAC1A6AFD9C9 44810130B08CBC4BC85BE53C75CB605A4A597A4BFA7126DB0BA48C109FB82571 AACCEEB32CAC08538B186B5E0EC897778E7011C5CACC4138F09076A091CA6914 C55202A0D407BF656C8C2254691072AF53EE0EC4986453940815A49EA08E222F 744BE850FC5C52C2434412514C0C5C473549D9E31E24208137CC18500CF7CA78 66DB8A71C496BC2FDD7930C92C1D7DD7946967B9BF24FD180D8BE360A1C4B217 64E6CBEADD67B56BA55B67C5F0F2CB512D7A87860B08324047824352C114A163 FAD5039C4FBF4CEE66EDD7EF6BA0A81493F176B819E1811D39AD6D9F2B637196 62EBE698FA8779D2AC1424748A8ACDA6E28C00C33EF347799F1608FF664E3E6D BB0F5876CCF81FFC96DDFFDA2A831C9CEC84EFEB353C8671253AC064FC8C0F04 01BAF823219F5896D10F6AB1A7AB8045295E4AEB1A9BDBCDD2CA7DBABABBC4C1 6CCEA0D181BC91B65EDA080F783347BD584D91E850E552CC0094FCE6AD951D9D 3509BB186BA9614956D80C7691A8F06C5052F2EA2755ABDA7EA4C486E86D5A4A AE5E31EA213908FB5A057616B9ACEF4375AB1AD37C843AA41FD2A7DC02EF28B6 496366372201D07272DE9553C5950F7ADB4052EDD33AA4CB77F96C2C0B2AB5D5 E0BD6723356C366BAB5FBD3C5D3A5686343315392CA63B32C6A986195CD58FB1 5B468B062B912D590EF3DB7B67A970A3EF6CE7814AA27337B9506841CABE1717 475C02072E01A3BDA2AF9DCFE757397621997E25C1E47DB5B72AB5EE80D5D183 FB001BEE9C122936055517D29104208C1BF43CCDF9D84895B40A6E56FF3D130A 85A4EC7424E6EAF268E6359FCF894DB1C270E97789473C99A17B62935CCFC669 3F57DF0DC15200E121A262AE0E744AE5D6A493D1C2A84B213068F0CDAC94D795 AD0DFBA9D6AF48B8F2B824B2AEBA4BF3EC885C46D388F640996C26BC3AA8E3F8 8741DB48B29D6A44622E8904BF20FCB5AAC82559178B93992033A2EE460F5FFA 1CF8FC2CC2CEF48FACB7B6494383253A659240D500673F17FAC354CB4DAF12E9 F32C7FA906199C700F533E0FE99796C1DA1F1372DE2E68281619CEFF5856F9D2 1CA6CC298B9B2F2CC6E11F49C4963D78E949A8EE55EFC05B5D1C79E100A5DD91 C2ECC4FF008A8123FA46946428F1C9F71EF80C701870EF415DE4148A170EC3F6 EBE4FB53A5DA44C38E73D64971CF170014EA981E03192EFCD266B6F4D009E869 86562A6A432467C8EDE0028714BD7EE2D906D9E57C040E5C10FED573A32F130F 5B7455112613F5E1CFE900CB6C7DB34C20AF49B26043A5DFA2B8C493D6B2CAC7 FE0AF2CC4BFFD812840A8212D2E85089463B6ED04D179D0578740F4A95141850 C4B75F2C7F78AA7AFC7F3CF3405D4DC279DC5F5DD39B450C6E1BEEA7701B53C3 A36C9E6C3310CCD84A827142279C4D0D44FC73D519308CE51F4F369C4692997B 81DBDEED618EFAFFF9D9054B867058D82378B05F42B5589F6173D5A2A2877E6B 0D89FCDD9D9CE5793A67FC0B686003E4C7907E399ED07215AA36D92C024BA8D8 4922E3C1EF8676994840CA2F145E7E3E46376AD7861619AF1B350B1BEBCBC972 94F0C4D453B62F021FE0C4B906A7E7837E8F0D4F9C41FB80169D4C07A05D0CD4 7BFAD57AC71E8052FAE53F2DD24E34733CFBE4F057304C9CA349B0AF36422D44 382E15A4DDDE67CBAAC7209B21B6CB80A406CFA3C1CA20969BE41C715A80F34B AC99D381CCA0B9AB3C5A09FE25E50B76B3BD039C6589021471EC29C526AEBF8C D9C1805B61F1AEF42F23E36AAA1B6AD933CBD16FABD3A1EE7C6C2CF43A4B500A 1E570D396D206E38A3CF34B2D0B75B72C52CA89DAA0A218E4B5B837368B31E79 165A3133C5B4ADCD13A4586714A34AE04583382EB1A615235C501D84DAD2EBBB 8999CDD91A4881A34039ADC1893EF397A91D55894BBBA0593BA7DAEBB2FA6720 3BFFD9C57DB9F06DE98CA4E576197243A418037FA03803B5AEC720FE941D5DFA DF0C877D79 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMTI12 %!PS-AdobeFont-1.0: CMTI12 003.002 %%Title: CMTI12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (<http://www.ams.org>), with Reserved Font Name CMTI12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMTI12 known{/CMTI12 findfont dup/UniqueID known{dup /UniqueID get 5000829 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMTI12 def /FontBBox {-36 -251 1103 750 }readonly def /UniqueID 5000829 def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMTI12.) readonly def /FullName (CMTI12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.04 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 67 /C put dup 68 /D put dup 73 /I put dup 77 /M put dup 82 /R put dup 96 /quoteleft put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 104 /h put dup 105 /i put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 121 /y put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE32340DC6F28AF40857E4451976E7 5182433CF9F333A38BD841C0D4E68BF9E012EB32A8FFB76B5816306B5EDF7C99 8B3A16D9B4BC056662E32C7CD0123DFAEB734C7532E64BBFBF5A60336E646716 EFB852C877F440D329172C71F1E5D59CE9473C26B8AEF7AD68EF0727B6EC2E0C 02CE8D8B07183838330C0284BD419CBDAE42B141D3D4BE492473F240CEED931D 46E9F999C5CB3235E2C6DAAA2C0169E1991BEAEA0D704BF49CEA3E98E8C2361A 4B60D020D325E4C2450F3BCF59223103D20DB6943DE1B57C5E0311AE44B83C3E 4FBCDB0B74ABB18FDD877252FD3501E05E597A77D142BED9940318B98D508672 4ECF79C43A857674E4DCF2556325CA8CC1C432E54543F706987376A084BF512F 0E4C517917FB1D607C83E479DD094240C3F309A57561CDF8496722F1D3EBF6FA 45CD3D7D810E2C07D39BFE08C0A25FD568DD37C2D182E5D30A7B2855BAD24559 D455B29B1F723BE1C4F827D72B1156DC2C1EEA76C9B27733FBB23ED36F61919B 4A6E8253C8C05F3D4BDC64B99B8494F7C37E9C19DB6A9CA8E9B0F9E7E3346EE0 EF416016CEE932E53A26599DD8CD09D77DF591A9D532AAD3E321CDCB28636809 E61D9EC969F2E27190A475407B90211902429778103D18665A681B0DD51F6E92 58D1288E2AB3FAEF05854938FEFFD3B4F376AAD303ECD28B23649E5D4C3CB85A 5C9CDCD1853BBF3282BCB5CF57720C6CF7AE468048D7AE5BCD2F15DEC1B33B5F 9917BF69BB64261CF101BB47A09E47D6508250374D00ACEC3E3FE8C5330AD9DB 9D9F60CC170F2FD6DEA12DA24CEA846E25ED6683A213E4FFD0BA239894C920B0 EFF562ED994A7A46F8EE2AF98F88317E513A06AB82A629979AAD3ACE316E7074 01EAD920A9E1D54E8FBD623773429C58A2964B498990E8420E5F7A45B3D4342C 1AC109FA67D4BF33C9D1E0E2973BB8B2495DDF5A7F8E306A0C712BD7A7FC98C7 44B26D102D3CD44A320FE89CBA6B3AB39627DA4679A5BB7C27276B34ED66260F DEB659189A797BC41D05323454CA4600A6D840CA3C1DC31BB7FEE8DE367B8177 3F1546C9EA98FA9F7CD61F177CEC2950526D54A6E7A0038F2B20609E7BE31EFB 51FDB6829852937071FEAAA3A0E51E625D7FBF2F7C224467C7DB77F7AFE006A5 418CF691841AB7A9923506845BFE066769A01A51EA48840E898FC6FF0ED9C2A6 1DB61E8840029ED92A129D38CAFAD4084B17679A84A262D2F9376363D4B5E46B 1C94302E5CD24CBE93A27319A8F79138414B2E94CE6F78C6F06B544D5862C2C6 297EFE524BBEF0CC2C32F63CDCE433E19B52BF0C2C7064E3ACD429E2466BB85A ED82C6EDC8AF5D75855B43A61504128F75C2DAF7F5C4405BE36C136CB809DF31 A40E0DEE80C10F6E6442CDCEDEF8DD0C01FB2C035A1D136693D366552862A421 81A290080EB8A3C5160FC2CD760A69F8254E8B0EC8E7280EC33802EC2668C149 73CADCFBD4E56A1E7A9CDA3F6A50E00AA536B02B4BBF4CE60B7A791098C3E434 B5A7F17D6E461FEE23C6C8C148C54D14345DECB7A619E56268131F65F86C51B0 E45860D46A1A798134AB3283BC8B73D9B39EC5D0C1241A85AA46B02E51DE6433 60BEAC76351AB35D8DBFD60C6F12F8B32E08C671E0269174E1E142E687B1C558 5668FDA480255261DC29288FF5ED56B50DD8512BD4948F31F14C71CB4F8FEFEC DD8E4F4EBE9C28312640334BE454634EF26B5FD02A93210D487AA4F3AF284479 303995AD31F4A6DD2C2DCDED3380D50EA1D8743A3C6561CBF4DE91634374DE87 FED0CF17C73B49060648AC6AF2921D19FFE1B7C7E76AA84600078A0160160D5B BFAA2007AE70640698BBBFEBFA5C11F351610023F563840413AF6934156D93B6 551069D681492EE73D480D648503801A921E37868B4ABBB013B628772DAC3683 3E44C318352E7700094ED0FF624AE560D2A783343B266FB925AE0D990B65F8E4 7A9725F23F0A08EFA08F81616A5D51E5EC31CD1BA229A89AB63ED782A6D716C7 1F00BA66A3158CDEAE3399653D7A29193760AD92F65C066A4DF35F91BDE771B1 74E17E4879428B5692343AA963A349064693B52F14B09C5F4B329C4AF4078998 D3F6C1046538F989C8AE84AE032A112C3E657907EE7A844B14C6A0FA8C9A1CD9 797E195186C478057525CBCCAA0FFB09F67F97E69BC402F6199B6900D9F285E6 47D359B1728728770C95B1A85E22D2132FDE7075F8FA1123F62504E53AB106D7 99B33689D55D0BC0C552745C5129CEF9F874850240FA6BF5F4779E35BF15A8F9 F425ED40480C60FE3ED85173E620320A462092834C0BCF6EFF9F1D5912CEB941 9C18D8EED5CA36CF2C7D3965BB0929EDBF7FC997A9CFE79A9FA9C54A11E1F421 7F3FA4ABB80A3C60E9165DBFB0EA765BD21846FD1260F1AA4644CBE05CEC736E 638311023F9F51F4C0166733A32BC1F615C8D9256E44BE8C2FFEC45B7B612FCB 21C52DB57E87EC8E166498AA8A4528B7C612E3BB8117D6BAF5CA8F9D038C1430 B7EA8699F31ACDC03774AEDDF6B73233944A1A89ECBAED2EFBD30DDF42821846 AF828EC54BEA6E7312B3255A7F55783C5D4AF1D9780A9670C9C7E02A50535A13 6D957F895D53E4E18A4B4263695DF2BD9626E717D5C3B80E908E59EF5D093798 7215550A5613AB86D67C1F89C95FBB0E6ACCAAB397479D483AEE4607E111EF34 2FD92DC7F991B6AE84BC7CB982D819A17022ECFEFFB981A6F678655A6278825F 0EFB5733C5F46529EF1FBB01C6BA7413BA9211251C0A70A470F735A96F6E0D45 DB1342D6B97ABC234790D346C74927F5C910F71918D615CA907984F0229E3F54 4F5F75AFF784C7A470DDCFFC308ADF6EF43979DD3B54C6A8DF3B53DB783B81E3 9C57413C3A317419C190F207720743084DC20288C1AD08B8B0FD4ED805FBA8B5 BB874DCE4AE93AE3B8A117612787DA6C8C7512191BC36F6D8AA38F39099474AE CD570CB5570BBA932C9C7A63DD386CABF1956FF87C266BF145ED5D27547234BD 943841047FE9A41C24B82FD3D3EA49A56C56840B1B359FB2A3F28E10AB09AECA 2FE2520DEE9B5542591E72ACE610DA4BF31C6E204574DC78033008F019519B2F E45C99F1B938D212602E824CA1CA020211420C77FF545DF586702451B0923EDA CA15BFF98CF2F0A56404591E57F7C89CAC6D22E0FEF9094770CF003801E5CC08 110B272A50805F89C0BB5C2966B9385C26F4A5008AAD97A29408A5116BE613CD 5ED9F85D2BCDE96FCF3121D5EE1D455A4CB03BF2AC33493FEEBEB955EF737F7A EABF96C137DD84B3EA39C61CE95B5967405CEF17D9CF1BDD1199346F95E77CB8 5FA2D38D858DAEF10D0DD660211C8C4C69EF58B60DEDE48DF76300EAB8F0A547 6DBC87BEE8DD4EDFE3020BA56F362503AFA62D8C13BB270C3884560E227AFABB 5D810B2B092531A679485FCFFB88BA8313646B644A35C413053DECCD4B371450 18F54701F610E52E727AE8D25A8093B60093FAF775B6414F66F43F517488B4A4 00AA4F672A34A73531218601904A7F50A045E80CD804D028EAFF506EDA1ED998 ECF16435C6CA8E203F2A813506F4B8CDAC0A3D69F4B704AB80F170EC87B7C732 AEFCBA3BF4050A9CFADB87F7AD4B53BECE197C10A2E84571A640328B90E9A294 73F6CDDE4F4AF9F1F3A257BD130454CF95D390ECA95FC4221D5041E71D65FC21 8323BA5A3335E2E905E33D5BA56BBBC9CC30D25764A066D013B116E693C56762 4F683F112A572C2C04ED041CF7BB4FAB0D899B3F2679B431E8993A650184CB4B 1B391B39929AF803F868245A69C964B560A274B07DFCB88A6508082DD6092E38 80D9187A146B60B225CA22F593AA6B4B7EE1EE41A0D375C4FA69EC6C8E02B54F B855D385C973A7223DE22465D039D213315C35F0D079E8CD030F62993495B2EB A0F9BA98565F89D2E09BB60D90B0CFFFF1F0845810ED27CC8F1088F74D48A30D 7FA0728498E78A381B0169B7678520EB5769522BB5838212D32C8C1ED5635753 EAA3C14E6640BC34D43EC162711996E0CABBBDE0932FCB6B2838C22C0E42DCE7 1BC85E372F24C1145655D59CCD50EA6E1A673CB0342BB744A43EA1B9104CF736 324E367D82ED67E01B0608294A91386045C1564E4E417E1A62EFBC148C0B4A56 73A98AE2F2433164740B839F851F9C38124B3C01CD976128DF6A06FEFE14B960 4573E748370D70F9FBFDBF875584852E70264766FA5CE893F74D0D5884889178 078CB149821A743D797E9577A7D27E7ED607349CB2CC6968A7CE402DF9A55069 4A985B517B714C603F993944CC64083DE3D5F969F9C5913C297E8493D310CA42 795C94740A5E5D3415CE7B4A5AA11A940D93992329D8B00213244405BBE73958 37CD65B6AEBCCB2263B937F671FFF3C6314D400983E5AEB6A34709D854FDD0AA 3D27A62BB23E253E6E2CA994294009B857B5F1FFB66E772A0BF9D83F4F72B89F 51B125AC9E495343C9D84A4BB4759DA4D2ADA38A195C7905CE288FD8634ED996 9068F0DC8DD08F3D3A1288A271E7F7EC4AF76EF6A78C47BAD95FA14A3AB690E1 19A13639774593D77FC1610D7F1E25A31AF94C5354B35500B8E57B0F65AC82C2 2A519581B587F5E3C941734A4269842D38F74E89C2AADB8ADB3D16542B0485BF BD4F1EDB4064E96A330D735F73789614C8D606DC553A0A2409CF4C595AE51505 CF203817971BD7F9B3346C036A18FECA44CE1C2042BA4E7FFA3FFEB6371A06F9 30082F47FE87B207E13A68BCA122968AD74CF6A12EF6767988F0EB0CB64981C9 30D9717F6C7D07F4B37CFDD68EE4480C0CA305AFA4BD21DFE131D6715E839973 E1271BF576F70C2F8C6827B3EF02CCA123EA46A02B2722E06078C3D9B3743CDE 45B43B561743264277D0D1FCACDDA80E5C6185E90F82D1DA4DC076B6BE49D2BE F03EF513F1861CF66D2B7F8D52C7A5C21DF1276B72CC1CDAAB5A16D20722A95F 8B1EB6E6B605D3878831204A0EFC95CB3C5B588D4F0A540D466D13B8468ECDC1 DB08D36E7FA19709A67A0FA08421053EEC9068ED464D29BB1BEDD0BA88882707 9F41334C3BD3F995321711B6ABDE3C12A8907F930F7AF490D774A05398ED03D6 789D91B4DACEA3D8EE11C2CD850A6EF4128B60EDE9BD37710F43836EF6D53FD2 D8123F81EC6F01A93A8B36FAE49692E7276F7CDCCB09F332ECE359E3E7DB2364 A60B192438FD158B18CB3EB40FD28F74A740367F02D5CB6B53959A0D11BDF388 9AAEE02F0E96AE2F802FF08BF778F26DBBAC8F5AA04CF3AEB180235BFDE493DA 4D0B13E0B61696A8ACE4FF7A09956A1896B2875E5B2BDBA09DA08B9589957E85 51084D76A00FB728E286CCFD2F53088158005599835B18F6F5AAAA6051270AF2 59F7BF641B0AF4E79F4491725189B89E57CD10B442B8EF89345D04EE3E18EC98 217D81FFB1B473B9562605F7B0AC3FA8CFB798A988E5FF20F068A6B2399C71B8 2E3C19E58601B0AD3872170B0AE8FA33F3A50EC5E67EC22C00D3DDDCD7B592E1 0D1CF31DAA48D10F7C6A56CA052A5AE914EE08CEE011FFF20D00B46A7738C434 D70F1040C611168D2C1851DBA89DA526428E6D5DDA244AA267AE3559B0C7DC8F AAE1687F823CE628AAD59999E74DFFACCF7D3412B466F6C3A315D8AA3350FB18 9EBE417717C42F3201D19E1870A2A3424E96F1A9734F32E85DF220E08C4DDF8A AE6F3491A3C805578924F36C146CBAF1D38C8C18D18E5A9B38236BD3E6B9E5BA 595F66A2A8DE9F52C9DFE00ABA5B99806A87D2EA39EF2C3A8D94FBFCB0CB5345 9AC36328B89AA13E4BBFAD70314009B0A2588847B7092C9EB938DD069CFA3679 73D9CF01F9756B931B34E70F4A5F1C41FC577515A5CDC49FE2C9A13D62E7E612 2AA5969248241BEAEEA5CAD34154EF5F9153D85ACD6FBD6B7F2834BC65C77E27 5ED803220949B14126BFAAC7728CAE16EF205F408232C5D7B83AFDB9C2191997 38005204EF424640DE1163B577274FB455EC0383BC6CC17F35112AB638743DEF 9954A5B2DF6A50DAA8662967E8E2208A9D1E3506309A9EC4C001CF91896E79A1 F3F6FE998DDF7C7971707CF7DF7415F6D42EE28620C0A225A1B9E389F397F972 552E566F748613EA1FD417CAA7B90A2BEC1AB07F44BB8AB6ED829F2D7F4DD597 989617E6BEF5E701498823382DEFC2D5FD078DF888DDCA99E62890AC0E5BE8BE 0CB662B561A49D2221847151D203457C797A904BCB5A1D68A51EEA20A167047C 36FF0FDD999E46C857864D1CE7568CE9518230418124EE5E51FD96C0FD8EB7BC 2A49F49AD72BB71F849B112147271000A77F41CF476AD687E6BC3DFDDE0CDE1D ABE816BF31348D25FE0A11FE7F5559BEDFC24A14F91BB73BE7F5FA95DA24D705 3DA96E8D05B84A1E5BFB0F15D7D4638CE4C63B74404128CF56A016180EAA054B 85FEE6937681557D0B5BC3C560947D456F48D7F4CB7A5EED52B103281B152E3F ADCE8B98497B74B05096AABA261D2A2EF56572904ACE2866C6A081C926BAC3E0 DE02EBB63FA29197B3812809F08A9E3D5ECFFF751E60F7082749F57352040E06 CAF9290336395684E85FA2446FBF1D0223F74B0D3464B06975010B83D0975181 3DB6C0E2967CFBDAFBD555018305184953487AFAE112D36E696DB8A18F3E3A74 C8B123F16D077DBBC85A226A26D406F622858EB7F1646BC0093A7C9711A1DCD2 6302B0611AC20A3870195D8BBA4E8E4F2CC73030B2354308CF8C06D68DD7FA14 87CE9D6FC7A8A356AA2DC356231B4993655A0FF55AF67090E2947C2B7FB9E96C EAAF52A01ABA6D69B738D6E3D4B2CF1E037D991EB5943BB0E6AB3868138CBF20 A112805F4CC00C65A4BE86D7492C23E34CC0BEEFAA0403E2AC21FD33D7A7FD09 9DCAC0BE550881647B322FE5806735FD993F5ED7C62173AB29095F67A626B9F3 20829E4788786C978B4BC9BAB9B3A750F130F9D4AFDA6EA3A7DF09D7615951D1 0C783A653F0BBFC23902019BA276A6D7944F1A34C1EC7E2710091C0B94CC3938 01C50C5E4A9C19F47D69074023F574D7A7302565EF9920A8E2A5076E6E3DDD2F 409CF1AB8BCE348FE63A136E03A520DDACA32571675AEB94D761B7B625AF1626 8BA9ED761E12A52C511890DAF1F790857C3C9FD3FD033A8330CD8E19266FE888 76AB1F3B3C8BA1FFCF3A6CA570290FC1640B6C4231D8346BD346E647D138B2B7 F7861E2C7C7C4431E3E91E318BA1DF8338AD4EB4AC104EBE7AAD8F5A09E6AB3A 48B9EB51A85277B221E3A22AAF38219B681918DBBB2F77FA8AA27F310159C763 A6E66D93879B592289B919B425FD7A367B7820FF430100E1EAE0877F84326FCF 5F1DD99964BC6BEB63528D2B218CCE41024EA2CE703959071A65EDE99127EFB8 0CC01566E5E52DB32D01512383A7711C7770AE17A71E5D95629642AA79CD5F01 D37FC89696F25C2EE4DD70DBDECEFA4FA2CD5D2F8ACE75937D2B1FEC7A31A893 16D314D800AFD3EA28068983A2ED3A7C75A5570F30A2824A47D6A789AC554C3C A78C2DE9771B86F73C66EF8E1D0FD046DD4F19A31EEAEE04D5F38B73C623F326 F146C7164C9B18B5EED2113363092ADE0ABF0D7BD4C10BE9766F81C34878B236 1A0FD6D8AB4BC7E3C01F1C880C3A9186E4006210D22EB64CD7690FDA750EAE7E C87A9D29128D49082578ECC0BC977D91E9CBB1ECC0D3527DC0ACAB39402015F1 B067FC5E7705586D97E81F8911FC2BC8E7C077384AAD4DDDEDBEF65CA4B75F6E 39E41528CF53CADA928537D557B518BB740593A6E4D0100ACBF126FF20888342 A0D3D7C201C4CDE8CBF59A1BA4F924E4EBC3E02883D5FDF2C8249AD8117332E1 BB52D2F621115C0F98037D4962EFAC0FA86B14F3C046A1F7085E40E99C0F2841 8B2C299411F9DC8FA0C8C7E5D7822A10D31D881F6C47B6C47CFA943FF9A9F5E8 D5F1C3E6CCFA324059B942FBA2C6D0E9A3D080DA0CD80D8DF76B0FB6BB706F45 C84054E62F75294ED126A95DBB4FA2D09EF80D1F2C507DF980D3DD2BFA3DBF49 6A99DCC954BE39E51507B12ECDD92C397E82B1E979FBFCE731CDDAE1D9147448 8C312DF818A0E08266A2B60C9C0902AE64276F7A1C6D7BB2EDCCB2E3B7659B13 AEA47A527FB302716624B48AB754218E2E3D99115C606CBC90B5EF73B9F99439 6184472986249C8D8E52A404FE76E17FF814D5BDCA95AC580B44DAE8C593939C 9E7C0ED996B9D2B8118F71BC2F0EBBEA6D7E18FC7CCDC78BF05A034BE39DF9EE C6BDAE8886C7058B15DABA55E85757137873AE811F25AC7EE3A0CCB8649F6095 7249EDD95E20DF06719DE1E109E5BEFC2A4098E77020110C37A90B5BDBF09654 0F72A7AA528BB009E0FC966D03BF5EC2AB2F109FB09BABE1DE6A9F210B590563 EA94F930201F1676F3D23805CB9620828E3A3B42E9FC4459744013528BFB0E0C F46A06EA698545C376603E34B998965C47F537E7730C26A70C09FB286814A9B3 218B124002B56B027D7BE4F871E2D5B98B200DFB07A85FE0D2A7DDE63C0B9009 C04D9A7AE3F3FE6C7F07BF0E72960B1D7993E09BED045DEE9D644261A1D375A9 52EC8D6569D908C485C4744C0DA6F49F05E3E7E394A6E83E0D2F376CD791A134 043863AFCBF676B76DAD14424859A6A5125302B261F69BB308231C797F64B7D6 6945F4DFC64F256782E167234F0BD6D0D1FE2A5851EF55B0424B7450A51E2791 32481BEAB54023EDD93BB6F0977BF3D172AF78CBE55AAD9F59607E74887779ED AEFAC06B25549E1AE80EFA714E2B8B2C420306AF3EFCAC537E92683DD6CAED46 D9DBB8A7450F6D0272A6C202CA18B0268AA5D9780E5B4E2FCC0C6819051E973C 9F72FF4AB63570EC2640E61C100B3FEFC93DD69DDD9996B9324D09DCFE937447 2E6A4409B6658765E96EB8A7CE278E97DBDB6BEBAB1E7C3E440960E01B1D3327 D8F80A370E87F72F159A8CC031EE3BE05E9B7D62E56960BAC8C947FBFC8E1A18 5192F95AD654286D5C2C2D8EAF51CDCB61AF5DDB36FF06A85E730FC54F033806 206BD7AFC6D723D784A13C827DCC5B61CDF66F212A644D3F152506C4B096069E 2F168C8319BFA566B894A8775216409DC1A0929FD62A052B61E6070F830C8583 46726380616855513F4B59D8025E7764B44A7CD2847C51AF4F3AB4DD9911E225 131731BF8ADCFD4F0F9085D856E99AC2F282386CF9BC80A16016AE34B7150B5C 009A6DEF004295DB39BFF023C41B003E3E19E5D97E1938E43F45A37EB0491E8C A815950E8E50BE5CDCEE1DD23C226CD071D29D8024A8B38A251DD9E1C4816BB1 B2213F7504AE4D1865FE5CCF304753F65EE55B9BADD0231C8704F72EEE473383 BB7C075C43169517E0294E34098435F1161907C34C8DF8243CDD84783B409B7A 7AE18B0355A756AECBB9BAABC0AFE199A65EE4463EF299CAAA272C809C1EA599 57972026819A641C0D1FA5C21444FDAE49D1625A136DCBE504758D6FF4958A2A 24A960214878F67F55EED8859685CDD6A229F6F44316033F3102A4E48E012F89 2F461E483D1DE7C4A0868B85FBEA7EB1403036219DFAD4B81F6DE6A551A470A5 D060D21CF37009D2973AD7417EFFE08DD4E1783D18F6C32A1EBE21CFB913F22A 27E576E364BA54A13D061D73DFF07496C8BF3E82E4D3D0F29AF241D32DFD9240 92D23F3DE0F2910968D5DC586EA46503DAAE5B3163EEC6618759A72786CB77AE 418A29D0CD7D110F2EE1F11FCA11321151972C40E479BBF9B4E0770F6BA046E9 A304E14E195EDF428041AAB181EFCD943F2FB63F5DB05AA0D990B8778B95517D 601FE768B6494170EFB47E6EAF2BC1566A0A9E0033C1499414AD36C2D35FFC27 B77161732CD538CBE28D0DE2CE14D4AD9A8CFBB9BA7C216DD3C6A108157ADF79 8B7A49985DD1A7B3D29148BA38CD630E3A41B03B70ED3B4459D744EEC9931CF3 DDB7859DDD1DE2A236876F2FB93A5BDD0817EE9239975D265F457DAB2FAA9E9C 1C3746BEC1664CB0D2FBE5E7155DF1D19032C37995512C6A3D3917A16A76408C 65BE3D4CCAE274901A5078DE796478B81EB6DD30902FF3B46645315387263710 DDF3ACAD8E2AC86E91B411488A7527D978E02E4420848EDB676537EC92C9D40B E15C6895EB27F33B323DFD12F7CB373F6E97363A07DF80D00C36429AF0D66B51 4DDE75126462789DDA9E92FD8B2FDCE72E15AFAE2E4641247DBF527D19C5340B C1321871E0DCDBC03458E018909180F87AEF089EB604A5C0772912D90E97D1E8 FFA2FFDEDD99AEA47F0CECF8CEC4947A568D71D0BEABC652B18F41FC2FDBD45A 40CA0A0AD5C9225F66DE208D83CF4F74AA9CAE2AA243A688D1ACB3A2A377F671 E8D4625EAD0809EA37BB12E48FDDF9F98BD2EC32B466D21C9B7C167DA1BD09EA 0AD03E5B84AFC4B009044AAB6405E6541DC444915608E7DDE955C4DE58DBD2DF DCFCFF5D332CBF3ECB9E28DF4CFE58079B01811B521C273C44CD4890492577A8 B6F0C1DADA56E1D19D91E040546E6DFC376C40B6C288BABD9C94594221A472D3 E1CB5C2F0219FC0AD681A6C76EA624DB1C534874470AEA253ADC8772FC5494BA 82D60618542B6487DFEB3F7A0F6BCB76ACB725F33E546501FFAFFF17E60ACE31 500A446F7D6C361F8740FA97DE305C19D7D7ED68FBD420DC64AABFBD979B5991 4F6202D6E68839659094C0E392C376A8669C7F9164990AFAA8908AA2E5FC568C 4C25872F04A973A7A27A3CBE406AB0BAD6825C1F0CE13078472E77B476C3BB6C 220EAAB5C9F601F0F2C93F4B9ADA1EB1672C33A7C9771B02578C8BC600FF4A7C 06F0E7C3EA255E9C0956139968A4FA7F35C2A1479315D409C040B51E8A152CCA D410F89310121721D287D5C53C7A866DAE452CB6796BCA3E541FCFD3C9BDB2EF C7EAE0332F97DC382FC688E841B8E928D951D7F53E8C4E0B967FECB41A7A9C40 22033FC6C757576EA0E434DCD5D9776FE9D7D719A42CAA9E64B820FEF1D94998 678778AE8EB462D447E748BFEB7C3B1A518121690B7493519746256CBD49D69A 11948C5D45F0CBDC9B12529703FEEF4CA87754EF513C9B2B2EBD460628D4BFA3 4B90B68A3849259E8CF126FE1EA67436420C7989AC76F42752B6B24A3AAE4859 59C9D4165C98EB162AF5A4CFADC0E9D88F8353DBCD2574D650CE312475478925 66969242956B32EC55854F4C496401C22D6969DB385094B7C43E91CC04B4C229 19AE92048592B95F908E4AFD7496FF7B00E7F42AF9408E06E7F87A7FD4F87219 9EB389CB74FECD5E04E9F52CA08917CF9300CCA93B6D7F028EAA7071DF0A4F74 EBAFC07E33DEC9B06FBFDECBC0729EFEE55EE2D315191D9C36A78DA3269A168C 456FE044125F7F7A98523381F052609BEAC11C1CA714F9A7DA625269DD309D8F 35DD9BB5DFFAB0F9FC0D331967CA81AE4D2A2B0309D827EB3D037622919445AD B8A23E57B78B1CB96B31D97E83E34D1F13BFD260F4E79D8001C23CB095143552 3D1411BECE4F99198A3CD9B4DB27054877884E2DDA074538EFCE518A25CF72F8 FA7FCA83220C27B50353FD97DA28EB3D9AF6323CAC694FC43213726689BE6CE5 58BCEAB2FB4C4B29E91512EF6509A2B884F600FA37BEA17F13DB59100002A920 1F2EC543EF642D04617861DB6C7349FAC8157D4D32B1EBB65BEDA6F056E92B3F 39A3BB23B10BEE06F60605F555A9C60B4B5F4137BCCCB8C0C272018982F51659 F17A3548D92B79F64C126168739CB0FE0D5964C58C02E8DF608D131E160A08F6 BFE4174A9B85E67E354DC31914593E4FB0E1A04B636B07DBD2F44F5567448D49 0BB7B862E213D0CBDF9330D1BFC154C3E87AF170560F48661F9E28F24D9369E8 EDF2BB0F06B26DFD4283E30F224E6CD4E17A22CECC7C9EC1E986AA5F3A19F50D E1B580B57DC7838FFCC9BB6163773815714D5A3D03EAFF24A7351AD6773F5EE9 167D46E68403F4D9A99E4844CE241C1B050FE9E7588DF0FF94DD8FCDF59D34C0 FB0FD90DA6A0E1099FEAFECE762CDD82682685EDF4F406C73CFDF42B139844AB AA796FC8E90D7A2E6B14CFC2A1894E7F0AB0F958281C61E13BF65F805A2155C4 9F286111D0B4A31F2C113DA7F35EDF9AACED40D419E83F37C07E178FA6AB4F51 36E81A51644C70F07D7BCDC81AE8978C0CCF24A33EC2D0B8BADFC727BBCF9006 74924980074C0FD69635789B7FD39A717B5A074BDC7A85564D8D9AAEA9FE4C8C E2106EA3B0885199C4FEE631D6E2D3284DC42023913D69E611AC1922F883B490 6CBCA36B7594C0C7E95806817F27B7B4852CCC2684648A87FE14B1FCB3332B5B 7D5296D15EE29C9D70070257A44DD665870ED87EA2E6129EA3C8A6C144DBAC1F C39D5A615A0DA974390D232D44845359C21C846B5EF610F2B1C7CCD78CC67B1D 3D13E7E2968813EE63C444F67B2C4E64459EFC0C7D8563D62788BDBD9DBF8428 AAC134053D7FE306B38653C842BEF0C5815CE00F81F93453BBF550D6CFC9CAC6 8A2623646EC54B104E3D423F06F66F461265DEA10D0F60C847A585568FF34508 69C7F21D08231605D53F7F87CE2F036F96E819D05B97F3D341461BD98C4DE92B 871E3E78FD1742820EBCD1E1E3A22400FB4C28CC69267E8DDC9B4E0B4FB8F22D 3463DC9885754C4F6F8FB393068383E6A4DE51985D11C0B4BA7C0135FF589A33 E5C3832DF150D8146C3816BF00E14370BFA69664F45FAA50504083810445FFB9 917166C3D88F35130202F5133C5FC5F7AF51F1F299A3201A1AD343C803EF1BF2 81733A1E7D040D6C1DC5426F5BAAB00699444B6E0161A8E1246DD7083F849D80 A98479B6C1882CA272C36416660F1365E15C8A8BE53B059FD0484247AA5BC45C 08DEF1F80994CA251DD6441A32B909E7BCF16EEF576337E38D5A1174927E4752 D2801CEE43054D376062BDEBC99FC15368B4B331E998D0EC8AC828B5B6C0B31B 0E1E54571F69B9427F252D90ABB66DA475E742B6A1017B73DEE388E3A42392CB EFFDDBAFF00D7D7549BAE4149E11458FDC9BA90829F0907F3F1DA2143BC973B2 19A863E5084D628E8457B4E7A8486399C7DBC8D5F3BFCCA19D7EEAD430C62DF0 1EABCD2DE44840C5CAC66D9EC458B609C078AF6977009EAEC2391119CB196205 8483507B99B92FDEAB2897B965ED295763BCA9A4C7BF2D1D225CAE4F0F3B2FE2 CA6250995A570CFF83BA5BAA336F4DAF34B21BBEDC7335716DA8B3AB641D3D7A 38593FFA6E23A5352D4796F93BB1A4C97D653F9513E8C0088224A0D28855D3D3 E6805CE02392E987A953655E4786DCF271EF967B78D2B7711BCCD368856417CB 7E11A7E0964B5912621465002E688D3B9C360F49C59FFCE0C62B3B25D00297E8 E3A10FCDFFDB673E0414A8E9755DE4442BBCEF215085C97DBB920FBEA7E56780 32AEAA12E9259DEBB8C13DD9D33B46456C07D394BB14D30A4321236A42BFECD1 BBF882203B8DA5F1A3D4FC30A9366019004EC0F3235A177ABA3A9407B9D93535 1013D313AF44D800BFA70ECC3A65B05F1BE293EE6CAF66162145FEA89078BB56 F099C42B934BFC87F3315BA5C0E9D78BD795FCFCB4C60EA766C99985501B19C4 B1798B8CDE585DD51142FBCF7D7653981A7E5215FEE4F3B4C66CA3CC14CC0167 8881297CDDFEBFB2E217770F36F745668C5C89479548766B859DD7C87524EAE0 3B9A1206B6AE098060BFF07449FA9F23E20435E2BC2AF962F1A4772EE3C84EEB DA36F24C69774402DA4FA11F8F90856632CADC7F765A4D70FF7C327FE853BEC9 D6B14B69D329ABA609F1443FE8C2A8E79D587223E78DD5942A8C63909190D8D7 C277221324F210971B773A433B2FA29C995E78162CDD781DE0E1D4FE3C6A37B5 5E0295EDC093B61E17BB11906CB8A6689663B33B87895E3876E9B25318716BD5 760AB1E3848234A9D0DBA17769976B2E8A09948799575889AA7AE0569CF979CA 81A7810B6BB5100C274A96542FCA219D9325FD5AF2E829D2C2713C6B3F06B2E7 1251AD6469A7FC6B543B04A8AFE18DAC30711939850CC16C08B44D138FC49136 A2A11F0CC90D855AC3D045C8C02B9B77CEC18471E11830537A322D806EE4700D FF92503EB70F8F58B7AD3CBF1CC2CC1C290EF9B8E5AEA26D07A120CE591583CA B80BC45F2F8D353C55773FBF44557A32279B133A209DE662D98487EEEB4E8D5E 2379854160B752D80176D6AC3BE80CAA8583223F3C8747EC0E69347962AFE7B6 39A2687375FDB0670C2CBDF2E8BFA351A7C10EEE59B9AEFD771D558583BA2FA6 1A444152D8450A147A403C73EC22139E4C54D91025CF21036BE2F0AB1CF302B5 A0A458EE86B65D06A76DC24101F5F821E4A011F770AC609E346DFF8D24D18D7F DDB78DB24DD55FD800B6846A0F48458C53DE7F8BBB6BA6F63AC446F4D96D4BAC A58C7D38132B7E187B4F8789A45133E0F1B2DF0DD796DED6C2E1B63F50958AB3 3F5AC6FA263ABEA39C38EDC31C7F40732F63D5C33B3CC346CD8A5ED69FCCBEDB 38E97516CC5B7DD797A29B0FE3305292FC54AF0A9AC09145EC9117CD1C819C23 6AEB1DF4324809040D57C178C931A86E030CA802CA5F3097110AE84BE3C0D495 8A1B358447A826CFF2AD68547FC75A0ABBF93A20BA9071CF50715AF0D481BCE1 36D5BAA30DA8D921787FAA18D97B6AE11E360C533CD271DE811016459BF2E930 E83B88099DE03C888BA348B4BE122DEFE2E8FAC19977F58CBCCB0A684AB28651 21FEFF2E0024C224B611D92945C8A00C79899831B96E54A024396E90D3E8C5D6 B07F3AEDD59B9DD5C14B547F67119EEF6730E7ECE38C1FCE5C65AC717C64ACE0 9F4216128B2C69B21D 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMR12 %!PS-AdobeFont-1.0: CMR12 003.002 %%Title: CMR12 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (<http://www.ams.org>), with Reserved Font Name CMR12. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR12 known{/CMR12 findfont dup/UniqueID known{dup /UniqueID get 5000794 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR12 def /FontBBox {-34 -251 988 750 }readonly def /UniqueID 5000794 def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR12.) readonly def /FullName (CMR12) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 11 /ff put dup 12 /fi put dup 13 /fl put dup 36 /dollar put dup 38 /ampersand put dup 39 /quoteright put dup 40 /parenleft put dup 41 /parenright put dup 43 /plus put dup 44 /comma put dup 45 /hyphen put dup 46 /period put dup 47 /slash put dup 48 /zero put dup 49 /one put dup 50 /two put dup 51 /three put dup 52 /four put dup 53 /five put dup 54 /six put dup 55 /seven put dup 56 /eight put dup 57 /nine put dup 58 /colon put dup 65 /A put dup 66 /B put dup 67 /C put dup 68 /D put dup 69 /E put dup 70 /F put dup 71 /G put dup 72 /H put dup 73 /I put dup 74 /J put dup 75 /K put dup 76 /L put dup 77 /M put dup 78 /N put dup 79 /O put dup 80 /P put dup 82 /R put dup 83 /S put dup 84 /T put dup 85 /U put dup 87 /W put dup 88 /X put dup 91 /bracketleft put dup 93 /bracketright put dup 97 /a put dup 98 /b put dup 99 /c put dup 100 /d put dup 101 /e put dup 102 /f put dup 103 /g put dup 104 /h put dup 105 /i put dup 106 /j put dup 107 /k put dup 108 /l put dup 109 /m put dup 110 /n put dup 111 /o put dup 112 /p put dup 113 /q put dup 114 /r put dup 115 /s put dup 116 /t put dup 117 /u put dup 118 /v put dup 119 /w put dup 120 /x put dup 121 /y put dup 122 /z put dup 123 /endash put dup 127 /dieresis put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9C535A5E57376651 F6823308463DC4E0339C78699AC82C769542FD3B410E236AF8AF68CF124D9224 FD6EE92A38075CAAF82447C7AF41EF96F3ADF62F76FB425BEDE4C4124E7B1E0B 8BF254D91912D3A99557F5427907A56514C5A3EB961B94112077FE9417B70DA0 B2E1C1FA3E1D6F01D11F640CF848E45BE3E205258E64FE36AFBD4DF4E93F6B1A 966C8E7FBE2CC8FF43C1F67BF6C361678B5E90F4BA524FE8A4CAD6AB28183E6E CA6C9636E884845105595A2E40CDBE8D4807A81AF4DB77B31873FEB221BCADD4 2C4669459704CB58A7BC230FC59F867EEADE660E49AEEDEEB042BA9A7DD8193E 56C3A36A1F639F7EA512EE4BC6992F52C2FC82A890EFDA730105B0AF7B819295 EE00B48F64C2B5BCB275B1DD62F289CDAD4AD9B7EF057684642FA6FA6322C277 E779CAC36D78F7779CB6DE12638B3C65B70C6B5F8A8C6421A379719B8DD44973 5F52856A4A29B2ED37F2B1FBE6EF4B79B7C0CD6395C756A00FACD763C235914F 847D1D99831023CE1FD89EFEC83AA7E313131C0C197248605EF5BA773D0A4000 72F607551A8EA6F0FF19441ACA179177D1FF7B423FEBDF58B0C19CAE3C10EEF6 3538D8FC4762B77C5AA023A8186C40D0365A4487DC3564265B3DF908572DEAA2 57E29EC669DD72974F806EFF5ECAFA9ADF1F9D2A63087FB7BBD100F0F81C6FFB B1EA1C9DD46548AEDD147EE64B1B4894972DAE1DC3E8569D6A3CEF9F9E46DEB7 547E10BB2959D374A33E47C58F1B20419920AB485F166062FCCC08EB5CC9AC88 F388F0C0155027B727729488E44CCABB7064A1432E179189C4627453C5231535 47D1F2B8BA43069696830CBB6E5F9A135CF22D3D1FE490A3A63C088EA32FF444 24A2427BBA63033DFE2E06DF8CE67949B6AB02F26335A376B57376814D2A7DE7 64A4347577EBE9A6E33DD2FC214A09C6D889C8FFBF1D567032548851B8F97204 49E215CC7D222F593E1EF1439ED60AD922D41E0E9EFB5CA48F2FEFF75AC5FEE7 FB6676D8B8D4DB6885FBE8B61B586313E4DAFB09D94CEDC0507E93000104F3DD F83865A2C6F6A7DA8562BF86F5DB233CC9B53391273A1462E40876A8AC2B098A DBADD5A160DEAC061F86A5FCCAB495EF8A9D121AF07928EAFD56F618E4EAEA97 CF89A3AFD406FC9DE1E9769C1E1EB83BB883786BC075EB5DA2692CD59C4DD7C1 7FD2FF9B18AC740A390C1DB38670DEB18C67721A1DCD502FE7368F47DB4281D5 459B3F020595FA3B10544AAE9EF786A0645FB7C9BB29D091E1432CD878A05918 1665643005BFD9A4B0FFD347ADC84CE22D6F9AD4EDC05E8C7179DCB360AB57D1 6ABCD200A4B4AD56825DC345984D9A3DE11CDA5E9EC1E5006EE4181E4EFE0846 67D8C27BEE8F84A1E01947E945BBE988702DEB2240C4BED952E433E5305484E5 71965D3DE95C4115FF78CE9EC18E323C599727C8B93CDFBCD1CCA780DB8C81ED C4B5E596E1603624308972FFAE9A57B0EDB51FDDB6E23EDE2946F61BEB241345 2A192D8CAD53E823D687F9C64A70A4B4B703291FA6317C051DC6A44BCCE0288E 3839D726A8F2E39BFF429865E95C726E808E02CD06F36C1CC9AC77999F8E28BF CE9D74B699CA982479E9D0DD98EAB24D29C981EF0349721D6819549A39413801 F80182D567EE316E2F0AB208068E15693E4C399A381BF9BBA625E597E6E109B8 16F3A84C8EC92F2ADE288821092A421A8D3B907048FE947230810F0777EE2542 29A3485223FEA079B359034F70464DAD2F0E420271A4E0CCF57A0ABBC20AB327 0CA71B292126D395E0D083B19BEC6B48A9DE2BF470C3D01A8C3F52075BD4BE02 A0C518355814478202FD4762EC542F8E7B9B1F7824F0554660CEB83E35635E1E DF0D03C94C903ECB36B4948ED98B6324E0094EB1DF70863142D4ED3A932D7346 39D69F8F044B6084482D7748C27328AFD24A3A70B99D1F7D32CB984488672254 28B6A9E9DCA2C9FF6A1B311D72413404B3CE5428BDB7FF3C36357D7975184F56 FA6B32AD54C37D0AF7576663AB1397B80D4E998F0B4C4F6D90B483029EF2EDA9 D4C4204C1546EFF3100629453EAE01918D09FE104E626ABA38646F17B6A94CE8 116BC7A8D9C319434CA5B830859B4164DFADF1D7C3ECA5C78D8DEA930EA4AC3F 59DBBF3148C91A2E807FB934E3439D4F67C6DBBA9972854E6E3688E1E0A34B74 482217CFE031CD7B5DFEF727C3EF8DAEEEDA08F4C90289E62FB2AF2357EB2E45 4BC547980FD479101FFEEE477AAC6268DD659E8DD9E244676FD3C6909713B71A 323B211E571BE711D103FA23B5B9AF077D84E2D20FEE805E81D20C03501F0F17 C3B081946CD0FD577F00E50B76CC37CFA97A61B89C25DD43911B28857284BEBB 5BEC61FFE3A14C64BC5425A7A82326617F6F1FA4FEAE56071C9F559F91568179 46369B394A5CE96FB7420FF8AB7C61CB83492FA5AE4A4B0799578594C9EA67E1 E54498AA5CD6ABA34AD3417F04F5D8D664A7EB39D41E2D17643CAEBBCCD9C38C C5C9541641A09335EFBCE0D276A54253EFD68141807A66F1DFEB4BEA5889FFA3 4D20BD52012206A9F8D3E0F6AFC03FDBBDF3E51506EC6336E249CEFB571AB84C BDF8E471E3795C04E38A5306BA6D450D72E50910D1AC385BB06CCD4B8E433A32 5A4B7FACC976BB31FCAA1E62DB2C4FE06DDDE7367930E336B49F47DAD91C8735 9A35D80CA2E117E86B52E41E9278046ED923454989E48610ACB3B1663F197117 52659A9D7BFA561C7ACE0771794FC778675F83C5EDCB132AF124C7E6540A140B E0A268836C73A3C746DC964E482E63C56C0D396515283970FBFF182F9F684FE2 655FD8F5D057D22246DDC3FD11B77552DB4D90ADBAB77BBB1FB1592129DE0AEC F822D7D36E52BCDABBD560B403A5C56C5E1BE789C3AC049318C7FAC5E5861E42 FD66C3C0F46361078D7E036281682BCE9BBF77983C93ECBBEBA9B359769CA442 87FCA1B98F4EEC4935CC93B08AAADDF355C99816453587310F08C50B9BA3D107 5388A1F3AED2AE32BEFADF0285DA90436D1D7EA85D7B9B6DF2AC4B778CFADFF6 6EEE54D1A1C5DEE3CCA7EFF57A7C2931933CEED90CA26DAAB45E4388EC4DC366 B9E88518D6CF094861D2A59282044CC06E63EFB390A6DF4BA5EAC7CE39E1EE03 3D84099F5BE96612789AF3EDED07266EF10A0FC23EA1EA97040B6BAA63138B1A A9CB8F5DED781260962D7618EDB200C3ED976033E8967A8CC676E9C11F74BE34 343A7ECE7EE97E8F76F7E95517A6D6163527406EF5A669535CB2BF4031F29046 BB2D0FFFB47A576F5EAB1D00A582965C56F28C00B3BB7BE2CC8D8391F789070D 775EB775437F0CD53DA840BB3575104B63E4B0BF14E3F14B320EDEF65FD4CAF5 8596DA491BBCF3153DED3B718F833D106432DF8DB8B8E6B34D5308C9010A5DD0 7E0E53260BB84BAB3EA748E8D72F75901604F80F4416920D69B4B983DCDB72C5 E9928F01A4A85954FD74578AE336C782CDF81D1EB7EBCEBFBAE7ED8AB4862584 397928F502D65139CCD582CF0723C5262EE54B9D2B8C39614652A8A90E1C3B65 7D26B99DA298FE4B9A7E98848F619C9BB4FF9FD215B72F99506F06355B332689 37D80AFD9F9ACD8172CDC51FCD3A759ACA0F7D4EBB07840840EE42C2D5B8B257 2C6DB3A7657B75F2F0B9730A20112745703E2D0FE709436CA6A5F36F59E64D9E 37C0A23D6D289E1AC1DA273872F5FC5C3DA2B127F078A4D7AB3FD7E124455817 DDC796D54EF26A1FBFD539D3A21B86DD4477DA49213259ABB3FF241424F2BE5F 89151E02FF87E0BEE26E85C0E518D8BE7CC9214B8E9A9EA1DBB49C6C212CCF08 90C0F23E9858947EE344062EBD9C574979087439975EAD4E85CD7BFAD3C91CF1 EFF577843AF1427D06CB2F3BB519ED1591974218C43F0D2038665F9E2E3960B7 FE68CD3CB2DB6B36C7997C6B21EC11CF1DE049541001FFF26D14C255E3AE862C 5A5701292FD2FB3D04523D6E2F3547923BB117718DFB6E6520F0D0B5450C695B 8C9242CC8671B7284CB2E1E9EB097A3DB1B4D5E8EEB93B4DC7E38C0A10474665 54DDCBAF079B92EA494F6FA75A84C5AAFE280284D0823D7C22249A21044BB0E6 4062074ECD17B62E03EDF4945A294BFEFB51F5FD870D9D7230FC91B83C1D85A8 86CDDF326FC90E04362145D6E8630C50594484FB829DA18F5C078F2EE67D2F2B 08DFF39AE2E8C9741FA989AE494C7166F122D2C5F71B97C973B7CE8500E9F87E D59C30F2E99CC4D34713DAB680598F41955FBDC26A14CF1E73D6BD6B9AAC8D3B B998F2D0D647356CD236DEAD6561389ED3A6746221B0CF15D6648412B35A6B54 6A0EF5BBB34AA376D9BAF025BFC650C1B74333CE85413D0EBB2F4D082A26A5BC 3C0A25D2B12CB159F140E00E262F1CFECCB2C802FF94CD34DA0CE9B4B3830FB1 DA85B9B670D5169928990A2E9CC869891CA2FFAD9774E6B92549644DAA5FE00C A5BE4F5FF91A0B6D2FD8F96121D766391EC4ED3E73DADD476B7DAE1A50AFCD98 DB7E27E44D30416088D9BC07D4661D9ECEC0806830ABF14CE55AA3CA2DF66E8E 748B8ED46466F1EEB072AC0674FE6FED231E0DDA59ED7C42BC05EF00E176050A C4834D893DE42474EA20DB1E25059E84BD137EF65A02CC295B0FFDE4CDE95879 0FE88BDF2519ABAE7F8CC3E6386ED35E04A14F1E3861922645E3A3F43B48A5AA 1999A5EFE192515FCC625C829FF5A7B337AA422F5E920545F9BB269C869A821D 6C4C26DD2AE746EF0F0B4C1E7E9871ADB5270E1CA9BE28225F7A0370D4C52422 E25263EE101C4EC1C7811B05AD42F364844A56BB91EE72FC8ED53CC6954D2BD6 F945D739BE4C61E36143CE890FC0CBF2F610018D678ECF7CEAB18FF5A0E48F76 FDE2463D40A99380D679B3B76D39C664F4992D23E5988B0D1AF33DFB04894016 E852EFD1EFFE586153C0F31ADBDBDE3F73FB49C5EE64D0D02E1504248FAFAC3D 903FD44679BB09C30288139B41B1E90A10139CA3172677250B16535A1F3E5E4B 6F4264DE58896E66051FC677030A121C5A285C47B6129CB5A3998830CE070D21 2F093FC1B44089F603A21F45F60960F134A47226874C737EF6C085634B0A4A66 139420501351F737A73F39D960EC38420BE46E5B09D298E7C16B8E32F01507D4 0141FC52DA1DE718D634AD9C8B00E46EEEF84356759324D2B9A3473C5DA38DE9 E30182B87F91B6A7F7BACF29A93B44C879CCDEDB063F9D2E51E0F1FC9F018FE1 2433D85AF24B55DE3A61C4D0A2DA4FDE933F5F6FDF17E9FA9932BFC46E2D71F6 585EEF5B2E4E89E797A24B799D7F064DD1A817A53677FC9EB8CC3E7F93FE50E8 D50E3191052943FD6C98B573BDD1F6D70349E1F8011599E3F8FDF1D6E80A710E 51E434E85801617C6FD8ACCF1B77B4BFCCDD35CB4C0367F4EB4D8D9DE8284D5E B4F43E2F8320C2C5A9AE90ECBA7E65D377E91DB69FEF27069235366AD3E126C3 A73CE97F4C90BA00D206FA012C327FD69EE59AF4470A315B1799CDC0539BF90E 512C8FC3BEFE4D1B01D969EA9E3FEF976CD6E0FA4C9ECEC955B265CFD58AB8E5 F7371E479279EE14B689269205C5B506940606CF3E24A1E7EFF3CA96ED30AD6D E243DE57690C3D69A401AB3315FA49E4BF4ACD4DD1CA39272533E82EFDD508E5 1C2CD286CCC5DE1202C7C7F654521750632EB637F918667E2233A43DF75239EB F28F3129EB5DEE2FC5BFC331FF709B0FE9B327CBBCE98BCA2C861C6547E50407 1218CEBE6EB5F9BABA4F2E11BCC6FB553A544A567B459E06375102C69F8018DF BA6A227CFB13E2D74E6A521E01B74F2963E9A0A1C9FD87A88EE6356E3BFABF55 BABC751D2BF85E6712E8EF57914920775906662E4BA68FFA21AD422D34E15578 43CA0568B431101A1194F8AB1EF25E886BFCDFC10F4A5EBD9530816548BC298E AE4A0B6B52B8B59C644C409B4191B6F4203F52314F2675F02AEB65A72C66E92A 2AC703E15D8D381522C0AC30C165B822A9B8D18CAECC094EDE020756018DCF51 D0701B507519C4270B70D8CE94B436F640C15872F9B5B77892AA3D110E4D6A65 8F0815C61A5127BA25815378683F46E69E54A391A8675977E7DF9C2D4E6FA991 9F029E50CC2F266B31EE9F9F24452D5838905F330CB7E416B8AF836C5AC26AB8 BE2ECC6EA4BDAA08C30995709E225C21D35DB6369167602CBFA8DB2697635925 969002CD1BEE745DA2E56C17EF3F0C05E3847147F86963C37A221C8827195A8A 3D38993E4939AC915BFD9A212F5FF3F826F742B952018986F9FBDDB69C3AC65A 845F7F33C55D4BE60A1817EBBCA7E1538E8087E1BD5C083A320D52953BE65F31 E8339C612A510B59CE48D2EF7061560C4AD258E7DC59694493E3AC878246F37D 6DE89253EBC8830C6B209E818213C4AC4CF1F391AD91D57BE76FB0E2924A1407 E4A949C905E44F54EAED6419F13D59942C8079336A172D4758BEB5D3E786FB93 3CBE4FD2EB53E4E1DAC34E821EB30FD44BC6CB4298242C38F848FC23AEDC9733 52BE6F32E31E25F18301370F8936810B0566B664B042C7AE0D78ACF0A87E5BF6 F9B66E358168B2CEA30DCD940074F3ADB793CDB136161FE2522905E87B8E463F 95D4DAB7E14A3DF7BCCE8141C5A08FCFA2BCE9F2D1B05A7642E75877EB840149 AAB007CD239AE47AD115929427717F219B0A8907F0EC79ADE1B901DAEE87A2F8 39361DAB43DFFF69650F601B24061A9353CFD619FF9626F63275FD09A5B13BB4 8B3379EC4D147C41197E8387FC04DA7BE409524CEF74EA91DC066808A7FD0EF3 957A44E2503EDA67B1C61827479486134E922E560A673BF314D601C66003CD07 55569085AFC8428389A140EB976CCFB8F29E27587E46C413ABE2EFB51AF5913F 53EEB74063162E0BA1E24CEDCA320377D3E11BD374F0B44E132A5C35835B6E2C D32948EF9DC7931D104C1385709DA882DED6458319F21C2329938396BC074106 CB9CFB9E0A915F8DBC8435F386917AC87A2BA45D857EC30ECA66FB4044F5439E CDD556B82A0E43418D179AD883C85AC276E1190CEC242E3E1D86E725ADC39E46 BB6C47FE9E17E29F8EA81E870302A00D91434F3B7A05F243176E6EF1082541A1 B9052191EE5C2B8E94A2E02DB65FC769653CA8D1C07A13CB853544AEC7FC35C5 218DE3128AA31952DCE19C55C23FD69BCEA2C661F57B11B8F9E86BFA718D1521 3346E78C701A5E51923D6D937E62FDE3669B214D240538F069A100A542720A86 31DE88116DE775F7ACC2A49EA6C02A24408271A846990669F2AF60AFAB4C16F9 7F4E88E917F0FFDCE68F22998AC0AF2A60A73258C3A4BBC42A2F918123128195 196D0E150D79AC3CF4628503D1F3FC528265ED8324E56849A47B3B07C29940B9 1BC270071E221D355EA51E9942D3BD7F99816304FFFC8F5B036C953B38759341 ED5D7B9C8E6B70C409DD8362FD291201CC385E4A98D73E8518A4C0E544152563 82032FBD2FCB6E403D34B85ED4053A8CB619BDD4DE001F4C3007B1F317579651 E6D6662189CC2D95AB85D7473F65C5D7B4AC63B0FE928F3400035D5A9D443D0D F3532B99F3AC26CB25EA3CD64C341159061E02EFBC7C033C05CD919BBD827A6A BAD2E141C0A7B647030FFD1FEAB8CE703C40802E0D32EF0DF87BBD5131CD110D BF5A11D66FC2087779FCA72E245C6BFA23F60759FECFDF932C3026D4CC21D843 9789FD52FD7A85BEDF58DAB6334F4880C2C99F49C0F64025C76E0550BC4B8AC8 5C7E817DBABA0E78F36954E9922286067E92E69D23E9FD278CD5F26788A7E5D8 476DE8E21397716DBA03B23D85CC8B701EAA654C5EE74F40D6C3AA3F46E30A2E E663C2CC64E2DA3631AB809AE1B70D89F53B1D72088642CD07D1DC4C7263A7EC 9785A2EBF8CA24D40E2C60CAF478FAFBEA8A27A55CE0320FE47E2512D88D1244 95CBCA87983B8795DBE8C15ECA68CDDBDEB167512E91930A7FB226994EE4487A D1E69C7E7908AAA5D45BE3B0D1072BF1F36C6368AF31FC583EC20E6634FA5777 5ACA6512C5114593C89A9FA5772BD7C4C2FA987C6CF164C2564BD1502C3042FC 860D2A57D5DD11848588A0264C6A7AF607D175EBC791022DED8909929C00B48C 2CF4EC05B43963F1DD6EAAA0506953CF028F59D81B51256DFEE6967960E4D051 03EA65DA9A2CD6C3FCDF0035EEA5E1DDEAB533317418A8E967F635ADA03D2EFF 80D463A1F617E7831D0309FC06C6CE580564F6B90D2D374F89AB7920DE34A7C0 5AFECC87242B5B8EFE4144223E55B84C97E724D41AAA52D3226F44558F333499 D9913DE4917260FBC356C0A4DA2A1460705FAC1ED593565146E1C03546AF5114 7686E11EB4C532EB40F5D2E24B136D306D7A0514F3096D12ECF28940F177ECFA 65BF83F29413779A6A5839431C54831890239B563411742AEBCECFD0568FCD64 4A8E85E3204581EA1442F6186B5FB1E4FE9E040E8265DBD78FCE441332774259 3EA89D248C9EB5938CE7EAB1181C70E10A723DC5DACCAB37BC3FE3ECD81ECFAF 7F95430F89B89B49D782289D6C1B1070E7B6F1BD4F0E7418206534D362835959 AE8298CDCAFF9B438D9333A4CB3E7090196F7D4D1879C5285237ADE2230DA2DD F5E9A7B1E43C11EC9507DEED0586F4B46CDBD368BED32F7FE08ED88B8499A5E5 82B76247AA3BD10851F796A6F510191B953E871B6BF2C59C58493B9F57E14184 BDBC98E01E6B33F3B3288D9046C08BE7D45022F66291211A60F87D60D2C5C407 8FF098041BA0CDA52CB028F1DF660C5C87ADF4D2435F59F5CD43CD5E004CF8BB FE78A4A7DDB3F875F34C2852E72B71479E1C6735B1A52DBDEB1BE5D3E4EE1D9B E260F6E015E86461EAA02FFBEF4B076AF674A62AD0EE4ECEB81321FDAEDE9806 88804F632587409C5D6E431BFB6648CB79E30944CB8276C1327E316A8960BDD3 5163D0D9172F627B6E299BAD3401BF7585BF5441DEDA66B1B02A1ACF08BEA5DD 9E1EF340414D51640CC609C34D5BB4A9835CBA523CA77411355D8B76CFE0A5A5 401AEEF58BE3D0525435F8A22188B9DFCE3172D4D2C50FACD96FFBC41835478D 2503DFB077A649C9B3EC63E573A598AE229B51960BB0B22B85ABD61C1E0870F4 C86BDD2745518C376AE0A1AA8F3726CC1DF2185B9CD75B5DAD3B6C1D88E6A11C 1A334B86912972130B743F356D8C21C4A861F11BD52CC5CA99FF089FB75B3DAE 9AAE187D9E2EA3E081EA184E3F129A74A26C28F429968BFE1FE793E0811F9820 E99CCFE7DFB64C7601783E89F4E3DE7B10E00FF86A572B6ACD7DDDA4203E9BFF 4CD29FCE07BEF7F91749192A40BD9E46DC25C5F8A46518EE4D7AF23690A469A4 8F1E16F27BA2CE2F2FA35FE0F664CF32088E14DC1E06EC7A376AB5E8D1BB1A1E 4596BAA6094D5048E450A2DE15B948F7C3F5668476FD9A4BB8E35F1AE8A1F5DB 48C8FFA0D744F15B8AEE4D22A9FCAB952E4FF8F41078CE57227D210A696410F6 11BD5DC5EC60DB22715460AA9FC73AEABC57FBFBD07ACA7E8F60B83838B962F2 E548C4FE5A73282AF86CBDC8A168A51573BBC24B94CB8E1CF0A452E886EF9DB2 C94F25F3511DB8DB130B7F00F95F38F522B16F7F2CEF44B814E9A0C58E03FBF0 0ACA7ABED6FD6A0EBFB87F3DA07213F85C39F562EAC50BD08844C594AA4A4330 C738199EBAD745025B0DE56F40D5B11F52AB6BC5300B57D080F6817955F42E9D 2515248F53B94CD3783BA7D81FA57FEFE628767319A0961FA32205F8A5131FBA FEDE6BB6ACC09DC69617D320DD008DC7F6D5A1B89AEE278FE538B56EAE5B257D DE9FD2EC5FA009AEA51A19167B2C11B9C732D7469EEA2625B32A35DB5DF2BF34 B818052F53D0D98A00D2DF87688D25F4DD280F50AD277390088F479B67A90443 9ABA0FE166E6969C1A2E0A82263EB03AD2DFF4AF415F7945B3277A272412C7C4 E766AE78C3E8B8C751F004297DCCD7D8F2C8ADDA46BEA21C93C54252DF56394B 77E1867FAE86C6199D1A26A79EF2BABDABD464437FE35C44BA01E5DB7D28EEEF DC3D9495957A693ACE1B12EEA6E3D9BB6A08D0B3392BB13F32201B13D06197EB EA5DCA618B5305A30F3925283631C64BC18D19C8C24C8B7CC1EFCA02CEC0CC89 64F83E264469225624C6F5038AF88B343414395CEED526A0209BDBFA97CFF53C 98BE740788F3FEC1CEEA7B1F4490D5C84336E2BF91A57C070F702612AF60A55A 63C7A9C5D0F012F853258F3F9329A62620BBD63F89DD09544C2E3A21298EC991 3238B80B0562BC13BA5C1BC7712D7CB4A8DDD92F217B5A80ECFFB31C4FA0B3C0 59477FB77AF126761AFD0EB3406B1F05C4D66666E6206751BD1828352392402C 43865262C0ED63360ADD803D852E4A1AFA8E1A95A4EF6E1D9B8F5479E608F760 9C283C074393F582CE4729D13F0A5D4BA4A68C8F9481A70AC93E3B89EFA4AFBF CC2812B94429B7B24B9163D868615688A71C01F93ABC503F920D9CA11E2E1A91 691B50859134FF03E9243FBFB5CC92F38827B1F5D790C8AD0438E6863DAA2E1A 796ECDCC63091A20A6CDC310C1BD856DDEF3C0EE0A529B7D1169016452199E34 DE33AFDDDEC552E61D746CFEAF186B919865ACFE707E4A8BCABACF1CD5545896 B823FD6AB8C9BE7D5CE025C92FF6831D8AD5EEE557E24380C1399C0E0D0B9CF7 65560EA3A9409181A088C17666AF114EFADA8E1B477F5E8C82B65718DBEE5B64 97ACBA29BF1183F8EB2CCE11D8DD34E0F615DD73263FE37BEB99596C18CBBA1B 75762EE20D81B7386AF321C6FE9F6A7D541A5527B641061D27F6FD91CD99B345 0B09B7F31C65111C226EA2A610F61EE3C0EBA82163A5C204C29055A193DF1843 0655A87E7A9F7AD2985DD9C3F14C682D2D9DC4E69C8FBD984FFEE07F27471D5A 112EBB63684EF9CF01138E2139CF2CC73F89825EC99F8EE14D09D5F0F5D9AC5E 359571DC32088355D5B05337F5E738D7778A4CD2122E1ABC3A7B3E9DBE960A72 57A282FC9D7A854C9BE6CEAE4DEBB37F0EF97D159F7ADD6C2627FB6B079CC5B7 97D18AF49334C1EAB634A38C50391D8A2BDB926EC8CC9BFFE3E058BE19895265 8B6D53DAF6BFAB54EC4BE1C7A3766BD6382EC64CF6B5170A141CF742B92F7119 3D204CF8ECE3601584B6FF55FE9A68436CB95C1B6E3075FCCBD420B400EF869E 3C4F7F46C54E38611E243F20CA5D0198E658E949CE097C4C5E444BF0F67C34AF 3A06837C5B90CCA5A258DE349F6D7A31AEF69BA41FC59B1149269680F0F3E1D6 E67694754F1185E2B6DB7E068272EA622D6F049518A220D98DA373A781FA2EBF 5A2B00390033F61F38271DD9C70C04D9A7F5A89C86E55A6CC2DC0076E3976422 BD5FFE06E269793D508DBE19B381B7EBE84CB0D7A4FB918D2BC65955F00810EA 849A6EE01B750CED99B0A84745950024A3194A4EDA01163D62DBDB8AE520BDC0 79CA2E0D4856594656B17DB6FDF6D104967D71514D45B14FB857E4E4BAD6D14E E2C46BC3F630FDA694C691FA96C188A4432E6986731F599052B67127C0EC1724 DBCF6E42D08660C37CEACAF513B012D52B71933C5F8092C429D1B1C508F2F048 1CAFA643EC4554D4253E5485A112DA5B3D78080E0AECF7A568BE8E12ADDFC356 01DEC844684A49017D92EE8BEA71806954B46C65A08EBA8F10A08725B3BE1FF9 E77A5C27A598AA4C2EE085752B9F215128B31B141B4EF1B102C6ACA3D93B509E 35810C68ABDAE536D9EA643D389E5E1892E9718F47308E4272EE4C14C65E3AEE 1EB62A6E2BC0277146AC0F2104DFA44E2F4D842DF31581760BDC55A4D97B7AA9 D8C564824D22F5054177AD0A057ECDE112FEA0FBBF6045B45BD34161594C4785 D72F5AA45E5135195A59CB54143291C95AEC09001F0F3B230F93389E758CE300 9E2399CF5BEF323FF7D7E236359CA6BB663932DD879BF573E18A9DD16830E23F 0BA0D8B1E3920152EF685652E14106986005A7D89871D08194ECA165A8C2DC7F 984DF1E03725DB1B91F0B54D10ADF1DB0C77BD58385651EE5BE722ECCF69045D 2D659901307F493E17873DC98585563F5FB0BBE87114B4C5E297F766DA5080F1 3988E4DF3D6EC3F5845F5F2BED2AC7D899C51504D6B88E263F734F013D096A03 C25D288327843315DA1B929CFB68E536EA4144CAC6F26DC65D3A7B529EAD1FBB 97C0AFF082662B1D33B849FD60969AAFF7C221A0DFF3A5DF928ACE185C4853B6 1A7703C167827B50A60EE1D69C1AA2CB7C07BC720B73C1D32BF096ACE197BA33 3F299E74891C1B3C7DF5EE06E491F14635A9C547A1FF41AA14656885C6F9FA62 A1D2694F6F7D3718A863ED968A0792F40E709119539021F2B6CF5EF139367CE3 451A08E723B0DB70ECF33785FBD2C5454493540DAC7CE9F41C6DB020C4FEF653 1084CA85E58FAA16BD23CC0579A35548174F41D789B4317C2C2D82EDA25EDCA2 20E61DBA8ADC0E5C1E7DFD1B0B2D556ED6288FB273BA38DE1A7D000D4AAAE215 107AF2397E02794D7A45A51C4920F834B476F5C439E78B73E7F2907F0D344614 8CE0EBF4CED36F226B0B46AA16DE62138C453F9DE84EBDDC0989E63FF8F78C40 0FD0699E3352B45B0CF615311688309CADCCD218C626C4717CC736011BBFB0A7 D4C5B1229AF24177AF2DEBA6764CDF170438FD93431C6EC6DC556F9F29EB0722 52E3F7A8B089AF6F5558520CE7DE85A52E0652D4EF74827B93C62ACEDDCB9704 E8C7AC466E898A32F80E01A5304C784BFA57149611B99A5D33A5A9587C7132F5 97E3C5AE12CCCEE17C22D56B6233100BF38840D2E0ED186611527930C0E83084 1A626BA248E0A7B1B7E6497E742C6D20C68273E8F64B539A37A6110E5BC5A486 D5E48C5FFCD264F63513B618DDDA615DCE1C92DA2F47319308DC790EAB6F3BFA 886ADD77D6EA903284542DE755B4BD2A056F823CEBD3830C1CCF028FA6D59765 A3BF96F1A1733785EC57943538864749A23B781162B11E7949C5B41B09C6DF74 AA5F1C71590FEDC552BE3246A946365907649DDC172E8CE7DCDE2AE1727AED6F D21E05FC3C6DEFB72F7260DFE4A8DCB24FB4010B7E1C8180BF85651E6EB999ED B7EEBA966D080C0DF16CD1EE653B1FAE2803B80401392B370D87D21E0529F2CE 8AD2D8A2A01F2301BFDE9C0DDFF09EAFAA8DD818BEF0911935AD631752A6FD5D DD7A2DAD1BE71EC55F4FCDB2E3342554BFD725E7C666849647143F4CF1F56B59 B576D7BF41A65F44D15B9EA7382DEE0C841FDD4DA590D036B6DA8D42698507A8 B6C109C1B5A52D187CEDF494E61A53D87A3FDF05ED68B66A1E19074DCF869FE1 BA20F37657F3240022516E3C6DC8337E0A1817F3B01B6D4B14BE274D149BC16F AEAB2131B59FF56039884FC7E6D97206CEC98C42B1B7B37A4162010C33D09C5E 89A45827DF1F4F5184E390F9C5EE10A0C07ABE0E6D8D426E7759285D83FB6304 DD8AA233E2B146B384B69D90E9E4A19A7D865E7AD4894B7433DD07FBD4689467 AFBD4C55F7CDDC9F686034C4D235A1D61A9F7DDE24FBC9267831F14CD0B05B3F C59955F0749EC47D375D38E37EE3A1B86615F1F01681AD3803CD44062B63E6B5 E98BFBBB3A77C22DACA71398090A6114E69655F6050BF6B5BCFFA76EC76DFB0F 9AF5A1E173349FC1C9083F495A2817FCBC79E441F4333E2E99BF3FA9969056A7 A4C361E7E3350C6FFF98D7934C09C1251375ABF6195B3EF41DBEF0B80561F46B 3C71359EEF2BCDC106CA7C8A7773B3170B48B502FF9007DB33197260BC20A123 397A77D5B4C9392F2B1BE1929E428897D4C2B1CD0A09B1CA9B2015FCBEFA12D1 347A044363E2010B9B1AD26440A022E38763C5B2E392A17AC0213E4DA3F2B2B4 1784863C2E7CF7188D5C61804B5B81FDA5E406995A180137302D2960A429F363 3D8460E1CF05FB800EF1EFB94FE0AFB995E17886AC45F38B7248BE27504BB60B 19FF74259A032251C7A58E5F664072A51B3CF8BE6E4086555E6BDC1EA46A92B8 6603B9BCD426B84138B959B5DD3947085E4E77230046F554EE87D97815ED2FDB 8D8AE61F5CAA5E27E42056ABD74C254EDD0CEC368F19E4603CF36724E53F1DBB 660CA1483099E85053489A176F66DF64D6204AC2F39AFC46A03276EECE89D87E 1E1D7498EEF8A2F07D3DEFF274338567C379676B65898C9E1F8E1C5BE0E51887 21FE74BA801CB5FA83E783E0CE7E4504F67D922D7AA7BB6B14F43FB9568943DE 1A68599EE5982FCF71E0069DBE14925F2EBCEF352C678D6D4A89341F4AFEE233 6B5D7504D6AF30C9A020ACEFED14F04309731013505EE0CCF0045380DFA0E4FC 6857AC0A0475A3F200AF5CB76E67CBA12205C0BD15EF6DBDA7893AC168DB765C 8D40460BCAF656ECD0D73A5F37B4EB124DA8E00C0AF47A61B4EC75D647B7759A D85CE296219B23A2B9285E2195304933BD4F1721598E3B7ADAFB67D779869AD4 3BE98BBB63A85175E2A85AB08A58BEBA402C8A8319239D37DD48AFF241D4E409 CA63B876FA01366E7F9D3E28BB5B2C574A7052AF725E0474FE01C83C5A2C04AF 17318290C9642B273C7D6358950269E2CE1883716496836F852C0F8A5DADA3E0 ED4782C6378EEF595C33171E8A355CEEB5531B227A3879419BE150C679B950CC F52057F07B90A1749FCB5B98715010F86789F19668BCF65DC42D8BA77285A4AD 51C64910110DD49648CDC7788E54F9DF00204C319425A9B8444EE664FB69AF75 0A5F71736CD441EDB67CA259BB6689D27AA84E4528EB97FA5435519285078BED 2D86F944B44EDE65676DD54213C8BC03B8227B1ED8BB6898F837BAE2A289A107 1152823274A655CB6A5F689D467F3FA74CAB2D75AA261B264AA6FA2EA835B6A2 241BB25F41BA1B62E35E3BF4C0F854705C35B604D29F9996C30CE0A22F1F9D55 5E33093140A91BE6D710DE6A728D78E593AB045C921D405C0FB8DF9D3C41E94E 05D712254333CD23E0C5EA4BAC1843AC83B1CFCB53860B81C8F6ED94D778304C 0719DB64001BB2315A07E64F30FF5331616363118EA3816AE55CE6C684AF1BA1 C380FB22964875633B0C1A3144CAA1C4F19CF479024CFEDBDC3030136FD4C597 EAF615C2765D0610EE62065AE8FD1533B4C223C92F2A49674449223C259CA6E8 7E834A7938A86AFFBB29943695B836A86714DD3BC0C5331C615E6B65F280C270 32F66B66FF46F31EB928B62F0EC612A2E1013F207A2056A3A3E586C924CF074C 2585E81545D12A7381245422BD64086E9EB9645E462FB2DA048262039C7C46F4 0109FC4133C0853391F7940497212C29EAAF6FDD0D2956BAC9E1FF7606672DD3 9CD662E6493D67AE8F0DF00C7C934E8BF5416A807C8BD90662D0350257D8B680 3EAF74920BAFB827638F2F2F28BA024E37DA866CD109820F98B946F53B2D0512 70900C16C0999FAAF4CCE5361D027790045AA51FB6EC28C2818C63BD3AC465AF 948E14E0B3B2BD359940070535E971403C03A58D6C2658DDB3D3E3C95BA49C85 D2EFF15BBDACEDD42F3380C45A696A33153B1D7F1DD966AE77AD0D012482D056 DFE1FE5D3BCB21A30B34AD8F0417C07342B9F4A84CE97225CE162445713E8452 12F13D9060619B1EA7471DD62DC3A2731775A9E5C1ABD7559A9C9F0BA63CCB55 92B8B93099FF4019D6E68A1104BDD07DAC56E47B04798CFCBF0EF99493BF8C74 0D2DEB231754725E8A59B239EBDB82B6DE33D6DE7ACA96A48E2BD29837AE9D1C CCFD847E4B6EAF36350F5FB057C6DC21A6F0A6400608239450FB55948D2C8C35 CCB042FCAFFD7FD8CD5BB7EE59554D1DCC1E6B73A9D7C99971423EE6BBA1600F F5110B5E853494264109891A4440350FBC0732835FF2D4DDB71691AF7939A067 3F1A954A8F6CEA5EACE52ABFAC42C7D5B15D2CA0243F2FD296FF618AD66F0976 F4D93B472DBDA4AB4D6793D59C7AAB383BBD6CFE422BBD95D8578A88DD501508 3B23E63E97FC3576E80D2E90DA2637FEE799665F86E1663EFBF515208EFA406B 71305543F3CAB383AFB3E5C2B0F2D0BF902398170E4155C660F475E35FD12B68 EC6AA27B2BD86AB9D63471EBF57396890CD947492A2890B4534408D09DFCA66A CEA33BDB68198BEF18418C221EB6E277CD1A216844349BA4A12FF86DCB883B00 397D0370F83A48F238F049B19579E265CF76F2FECA09AD0154CB95DAEF3B99AD CBF3C37711E497B64C6EEF9842A915725C67B53ED78C321FC16AD7EDB96EB8AF C6C899CF31352C8AE8D01F7CDBE776B9D0CF70D1301076FBD4F188DCBF5AF4D9 28F66027A666C11271FACCB35298838DB65A5B11F2F32008684B2DE4D93C6534 341B80254F6B4C54C77610EA379FC51E30EB9BFB587B58A67F66B3A6683AEDDA 14BA4CCFCD7D736D365A85BD632F0AE18347AB6D7DBCA8E2BE9F02149B338DE5 3C9CCB1B67BA6010C2690EA863E027CF4E4251A9D2D720AF91529B38CACE86AE 7086393F10A6929F421C07C1217DFAB9804214B2826C226A934C30CD947E33C1 A300C5459511ECDB315E78F2738D9F1BD3960CDF75B536DFF2476194DE9D3E3E AD8C919D5A4E8718CE4E92F30101970419A94E53106836758FF537DD4EC9CDD5 227894C18B0B3EFFFDD1B5C5C634A4D89E0F63B86FB8CDE9634AEA65755DD660 1114A8E50B347FF09EAD64CDEEAECEBCCC41FB366885CBD3F650B01931842108 5E412D2EF6AF4A7B31C4E580D8F72273AD78EB57DFDB02A5CF95B701C1B0D163 22E8D5CBEF165FA9BBE73AE35B72E214974B2B98723D5443397E92DCF3852FC0 AAA751F8C83BE165E9DB298251BF370A109A03BD472286E2C98D2AAFABBFF00E DF6F762C7B1AEEF34F6C7E4E081C61DD5BB8EE596388C6B001023B28A3D59709 98F6858696623ACB862DDD3222DCC6741693DF6F5595E0F88BCAC3EB65C87180 E6131F5D70FB97ABC3523DD508BCFA0E723C639AC3DF4956D533E0A067B1C597 35F6272F27B4CC3F7D1D20A87707BD24F3FF16EF9ADD708FE2C146254F95133E 1C1C1E34F1E4A154079B8735FD89ED33AE4C1DFD4CAE421839AA7A105071296C D4A4980BD3DD38EDF8BFCA1364844F080209F0F989ADC051E7F1BC77ECE2E591 3D84D59F0F741E98B13E9BC30C6836E301FFDB5F97D0E7199F292E666FB5F00B 084F474B2080C0D3BC5C43ABC132BB34B32D41F724D60564DF0D76DBC28759A4 C998311887BDDB9839F38997DD80A1F0784F2A9EB10A2E8D16F068114FBFC06C 06572F5E233648555B533408BD9EEA2C35BA1CEDA8EAE55F2AC19BBF6509845B C5C793388626F5AC5A94656F29E7208C0082C5BEE5866AB63816D9DED94CFD1B 959880FC9D14AE9F9891BAB4C234F6603E050FB4CC8F64C5295BA09303FB6856 5AD60670B35E149EC82E7160E22CE7FAFEE9CB9A7B2ACB138C9D0C0B72AF7332 84B4F27A94B3F6554B57A57520CCF9665BB5B6C522044E42BA2A97FCB703A86F 06A4F8119A1D0DC514C3C419C20F5883CBC06176E292F31D13CC9B9D84A2801B D34E6092376499E8E59D0CBED6BF28837E9E5122FC8D29E23A25E3814B1F04AC 585164D22E2F58DC2AC1B66F2E35E41581DA65C46384A120A3480745BF21E832 33E8B794E5C27EC5AA4EA22D9A5386CFF9C60D10061D3D2BF8C4E1AB5032C516 BFE905B4DA3E8A818E13161399BCD3F410AEAB68AFCBE164F5CAE00439C17D7C 1FADADE9990CBBA17E89EB7B4E931C551D5625E2B3422C0BB8C916F0CD5C0BB9 4E708FB39A38D3D4BB3EB0C918955BC9C166A5DEE4A7F87A6D88A82CFCE201A0 89A1608E51F4BCF93A0F1F4A090E1CD892111C99E9ED23C19BA5DB59D11F8B59 313AF6C86BF5B0EE5DD061FED12A2F2A59F5365B2A48220B797A29F8AB6EE675 AFEE12D1462D39946E105859995E42D4BD22AA35DEB12A8F895D998A336CC5F4 5BD1D4DF34BDD5264F9FFC1AC23121AC38318BE00C138293C85487C0571E7540 8385AED8F5AA64C6CEA49712EFCD893D748C9A55E12133BF92DE7F2F9DC654D1 0C3F160CC804CC5FBFE06CE3C3573C8FF8FA4293159CE76DD5820F5A739E8357 93743E3BBA66FCC096143BB3BB276EDD43552E2F9BC3FBEEB0D2B0E3D1074AB3 E7FEF9373BC7C459EB9413B1177515C12EE7B36222109C556206DEAB8775AB59 26095C2A00B43663BD4A83DEB0FE93CD0159190A81EA6406117468D3F2AC1BE4 3E6C6E9A4D1EB3EAEEA73B55A8F7CB8F6A128DDBE3A2936F0151D497D6A952DE 2883A71B119330A1200CAF83DC1F33838C6E7DE498E807108CA8C789A023F6FE E86A320A8ECC8D1AC9C2032EC55EB1AE1B70E427A774EBD42088AF51FF8BD093 922B2C735CB2167E415C21463CE8CA67AF5D196D1BE14F5296E9082C8FB4EDA1 B428C60BBFC6C576961DF465FCAC9123A2FCE485BC002229EE099A5AEBBB781F ECB99ED5A67BC8C434BFB244A41C75BF215715F517DD801097163FC212AFB1DB 1335B446504E49091E3F7EF70F8374937CC1B41020D1C5B968DF11B62F0AAE7A EEA87C6CD49A9DA25F597620B179344DA2245DA5667D098E771BB94E92999C1E B4AB7F4E48945A66D839F8744992AE8A13D28A73039B8A7ACBE25C6A16847F0C 5596CB11B83A23F35A4686318C50A3B3857C15E117B5E4E1F555F69A082932CC 6014BC4009FF6B40F5F76989307EE748528A90D878C73DF3405AED4BE6ABAAFD 5EEAC65B89CAF66BAA7E6D5BF51425A1C480E6A506343E41AB0AE9EABF05CEFD C36D4620DE7D26B133BB5BFEBE9A68D2B38981D3B7B6E2ECFD3E58D9363D4CA5 136FCA0FC9FDA355C4EEDC05957D93390899CFCF935591B971B13416DF600582 B766931A059DB146E5D8A7047E5C2C30582E57C53FD30C94C584BCBC21F155E8 B5777AE209CA3023378B9E09831296B33E83CEF7CE24E537BD84FCA761CC58CA 987D7A1FA0CBA4B35474174A9D44DB761796C47EEB47D9C28EDB090A4F539632 E76E009D54DD653E1095606C5924CE0C9D1501F158C44929DF87BE692C25DCDB BB03E210D8D7FE9112CD5C2034B1BD98D753C1E35DF873D3334E6C3528E12384 0DBE99FB787A8623C49DF81F752541A6065F3F946A701E9FC8EA20D2011A3D74 9172C3AA228867165337AAC126B3DDFC88AF5B1406665B21C51CDEE7E7DFD260 0D9D9E3C66A298BD3CBFEDAB9CC424E277788953D0588A3132735466E5B2AC5E AA8267C93941A6507E2DCE929841F20D172B21C368A87376D668072260979F91 332DB4F7CB9D5CC38581FFB53503B45323F57BC51E6EF5CF6165E7DE9F4227EC 9AB163D45312704CBA05721DF84C24B76DC4AEA3DC08BB764CAF7F0E9B8FF43A 163AD3BAAC52A04BEABCF474D9B5915F7F62442CB9BB17146E949942EAA37DF7 E5511F241335E87FDB00DD0331BD53F4AD3FD890BEEE6ACB504A81A618F9E19C 2139B6874A85CBB0C7F82552369CBFEA834A20900BB98F4A394207BB0E9ECC9D B36ED4BB80FA1295E407738EA37616F0FCC86B3AB4677110090DF533320D5079 7B488471F4A95018F514F2DBC9D02949950F92A6504340D0FA8DB1CA7A4A0ED7 A92AF3BCB6C2593CA1C3EEBABA0C50717A2582863B56534E7AF6920199DF1C91 C0C5D4B8B51B9F3B463DEE44CBA8A6443FF8318628651EE1D53F26E5416AD732 318050881E7A3813CE27AA1EBDDCECC580608826FFD43D152102B3367E05B469 8FF1F5623703C68DE6CC36EADC49369D23BC70E53CE2952FF4C286C6D520C285 17B54D6798DB0A5ABE2FF9A8E951C7B0DDF627E1AC4F2455D8CB6B3235BF633B 1FE12862F69968D837199AC3BB971A4D9F31E833582048D3C94883A55C68B90D F2A65D173F9DA34122BD481A6FB97279144681E502E5098F8431A493DD23EC8A 1131EE785E167F05D2C93FD5FCCF34B58B6E59995C0286F3B77BDAF12882CE1F E41D44B81A76D2BDCB2D1D83BC7BA8CF5C8E31E7D3B01EAC3A8029BFE32442E6 D1C8D04D3E620977AF70AA3B1ADC96F506AA0203C2990F7F8495B15BD77BC57E 109EB6703E03019F5E5AB042246204CE0C665191DD8719FD3D2D37E7A3C6412C 39186A4B3B8B0483E78D6524F41F9D377274033A05FD4509B2CE324B58940D25 BAB0FE846B96E7ACE1F17C8173F4086B4FB7C98D154369E34688391B0DE70EFA 764AB5ED558E323F29E885AED917045CBDF9A688CBF26AD655D5DB3884EC5A80 0805DC638B239ED25208290F56366CC095FD46180C519916698BA918989AB47E F4F422FA1FD9AF99FEAC2A6065FF61681CD3A78E872DF509E0F5AB62A17A01CF 7F5D5646A13072758E5196251D74EE1703DDB0D131B6AD695C3970F9790E4A3A CDFE3AECF4B96AD750CBAA582065E47ACA902FBB74F73629EE01D38D4871D7A5 1D59F93E4480789D157C2E79876DEED20C1A55FC2F0E44DB48E7A3D4CF287D7E 616B9D6867CEAFAF4E5AF0A20BDF685AE5C4CBCE3978C995A1BC24CF91B54BDE CF6A9669AFEC0FB57D78CB75BEB680AE81110D581B2CEF914965866DB85DAC38 43B6B896E62AC321C5F2CF639184E38C85A89C8B9C055DA1DB1FAD71C69F5CF0 C5652CBAB0B27758B676A722FE1EE8CA5868B24502E22E56B6B9BCD15F2115FC B92BC0A04B3CA670A00A9DD0D3C8A8B1EF9943B8D8DE92BB00C8A6B9119DF5C3 775DF3142A825D467BD8A3A1CA23685D41E40534828595A0ABA1C865F9928D92 A23EECF91FE0C62A4F07062A6CD9B1157A61DD42AED295908BF0C43F198321F3 4022FD5F083AEA27D020C67B0610E7CF77EF9E89E76AB24D3C9A5DC4D5B602D5 794578EF367BBE1920052E7042A5D4ABFDEB289C0F14BE19955B374186130E65 D290B8FE82ACE6290B12C73ABF3C66AEA878D7F9DADE572D5C379D0A66FD1BF0 3065FF1BD3061CC48EDA770A029711FFC60FD6D7F22A9D1FFD03293863250AF6 85129F4D43E3AF4742E5ABE4FBE09BCA323D5E12FDAD0B509DF3C701A8537609 E1D7282F7DC137F3DB69ED07CC18868B8D443456EABD687FD3B3EBCCB98E4C20 CC028B19091815EBD078D54FDEC18242FC5C6D26B75FF0975B5E01DD4560D11D 5DDACCA4A74F18268B1F6DD3092C00244FB19015E3FA8BE404538443B1418BDE 88EC829F5FDE7338D33FC6F849F3898BD348A9ACCADF112A8E1D923051A097CC 871AA1D06D0786C730D91093F42E120A96663144E72C4C3D9BBD96953FF6C2D4 D614BB4F5349E2603E5433789D77F0A1B4C3FE5F40E910C0C7CAEE64C38EC09E D755024896E8F4C35F66F79A10B8CEFE6D196D3A61EFA813F6715D7987099044 AE1F6568668788C2EDA5F086DA433D6AE10A7DBD9839308FFC393618146DC2F7 E16D4A2BD0FBFCF937DD3BE404A3A0F93A9B58B7D92A3DE0245B6401DE55BC03 60E0AA4CEAADC70A9425733E36435034C6600ADD363C5C0EA83C33F086E4BDE9 44DAB2FCC578B81CBA5DB667193A27F01847D7B8CA484251098BEE660C88CF74 5C103046DAC0DAB40BE8E5B540FCA235408864F67086C2E8D1BBA0CF983B444E 0AA5FF8870B825B6D50646696A9B367566FA3BE5BEE501B94882E5671E228651 C5B3871D1B6414DCEC5542732BB7F0E9CD9B977E0F7AFC4C68960AFF2766E975 DF0F75B1ACE0A110BBD5F01460BA873179E8F5E1517AD06B1D6AF15613EB1B3A 9AA30FA65D4D4D07CC24C92FE09E968627D8030C176598FB08162F85A1B943CA 1737404AF40538D0B80C2757296E5ECE686E72D5322C92BB9F1BC3044B98A197 83B4F6F2EB08FDC8E09782DFD4420289CD3F45C913E3D3CFD62E422674386AD7 0EA7E9751848DE4C033212E035BB5EDED222CE9FF7576C08BA6DF932F933F9E7 872BE308AE9116ACDD58AC17867940A79A3EEC0D8673B4BE4FBE011D9DD4A6E5 DAA2A59A9E275CA0EE483DEE4D1CAFAD6C17972B58CD4647E2EA8F8B02A7A617 0411268F3EDD8A6F0FEDAE13F2D7A5D446C1416DD92FF579217475B348DA3012 BBC3732642D03EF76649A6AC923D1E9C65B5FE57F9A0887AD0DDA72DF90B86F5 6C0425CBC5804BC3283F78E15FC0CCB044C48DDBBE27CB33F917B04A4108F23E E5B268949EB8187512BE7F4C6A373976430C1CE8D15529AAAF3E22E53FF99C85 D3D174F976ABB9A64CFD16253B0B0CC481A38054CD08D1647E98F787D9686023 987CFDF697698129D7017F82E6161F1DFD664959683D4B799385FC7B14AC0C6C F5E64B3A40985EA232C4954978B3418048D65952A22A9E6CCF8CA743EB6E6390 7403A5B7CA8FD009CB3E5F01F6D519A5EF8E21B23A586F9DF93DD64219024DA1 C786DBA09EF291CC2E8D2BC0B3492D6886E2FB271F2700999C12039FA2143F85 D669100A8FB0BB0967CB76E6CFDD15C3E28FD1BA860FF64638256AB471515B65 4E3AC148FAC2AB9869E9A11BA7BAE28045F8C218D208D41CAE66FFC9A592B8A7 97B8385AA16A43BE83F31DCFB20A04DB31EC24A3907C3F564FD5F15AEB324F55 A14F011A271D580E0B990141055A7ACDAF5C195B2F5DD2DE805C468E1DD4F0D1 8CCCCE9091C67F57431A6D7D8D64D30AA3C7DFD48E3F4D0C93CED29C95BFBDBE 20E6E901DA947AFA96858DEE344D676715708EEA37021695471D2A1E2831C4C8 B292A44DE5AE328C2C197B35F347CB035530F779027F8E6892498DB077B8A351 836209BE1BD354918EDE89FEE8878F8ABC32120DEF3F5D5E4307D7A533080A20 4CEF74BA9B33FF787A085150F121E918D2EB3A985F7CB203044F0745D3DAB45C BA9D1E808160FBB92149707D8144C5689737AD110CC871BCBB3E19B4512F447F 70AA3BC0FF37B0204D96CD14954A4588A6521ACC1B43D83CBFDE51F7F801E592 787811E31D83D07D132A357739D21A279920A2876A460FE9B76682B5EE498B76 E323BF7F9E9F15811B56151137F867F1AA601FFBE9507293ACC5D1146025D9C5 952FECF6F0BB7EBC221AAB460EF85D9CF91F24738C7FEB0C75E49584F1CD8F30 2F91C5EBCA8A589FA556EE12FC7B6949E3E04F2D18B224EDCE6E8381C552B32B 25FA74B366F26A1145A53CAAE06812EDB1A483ED40E46D10BA4C14589C7821D4 5236BE4678F62AAB2813AB6042E39B7E89B4D3BB5E91D2C136671DC85FEAEB83 8CEFA482CECF5260FDDCC6FC5656F0896E6A9BD036E9BEC44F3BE833D646BD49 18158F45179A3C5C0B54F877D9D8FAB7BF346FEC2BD063152501AB053A9EB6E8 03A0A99CABA8DD77530492663A6B96E78E1D5C60AF40FBFFF185522660D8F788 A0C84B3740F895C16ADC59FF697CCCA812A97AA40D8CFC45059A88720007AE91 C1AB6239B033CA2A5B9E03D6B219C18A57D71C83A12E63453E215BF13C9EAA46 E3CA0AB4FAD99F2FB9B304F418C760BC022131ACDB582AA68B73A793696FA208 E81FB671C8F10A7078962AE2C43F5DFA90CB8FE3982E2D9974784B971EF491D3 5B0231F67AC8C05D704704048F5569A0ADF75209CB90403BF7922C9861F4BBA4 3CC12AF34C72AA7A9E5093143DDF54FC2692D2857ECF45EE3F67A70DA98510AF 8974122DA1335564FD06855ED1995AEA709DC8742CB8CBA5650EC406482C9478 76AA7FE7C2E37ED5D425E08F51E84DE452FBAAF2A2A5AADBA8661D18D5A6DBAE 1CD96C9B40998A207CE7EC5B03648B06A42BEE7006163F27C1F3BE0784C9BA3C 878F7113230FE1A1AC37B1E3E4BC533F5F82BF3DD6530828E93CE96BBAD0177D 91AAFA7938909E8E243CA53237CC6A3AA1CA17138C32AD72ED49E61A87789596 DE8E84DB70FAFD6513A81F067B5BDF96126CFC3DAEC4FD6BA31CB6BB9B117DBA 6AC83A27328C28E18A31D7D78473686A05809E46A67E60F3011FDD3A35AFF293 2132B1483BC3008FE39B15DA834860619B8B80D6B0452518BE8EE5911C0F31A1 929A1F6E1902ED9E3A168311A135B0A948F16175F0BD51C6CD7D43867E225C0B 328873F225A7F7BB7DBA0BA4C3FC5B8B100E0C0C4822762D2803327A68A31F39 03A3010E5C3C8E23D7D3267708E6877EA7ECB9F3E8FB0744CFF7F8E9DEAAD953 19F8F707E0268AF72EE196E7479410FF15D2B7A2D7086315CB7CB5421C84EDD3 784AEEE8622E767BFAD692E8B7F3DEAEB66C85BA3933DDCE9D6469CB2B1762F4 5DDEE0E9F631299E23949562C96DE55A893A5F9B7B37A5B16901872F695FC463 AB640ACDBCE123FE04829676EE422292A32839315FF16BF216568A53008DE3DB 1343716B84E3E832DAA4CFDA0589889BD2AF54A6A68A97EEAD47C51CD99E6942 8766C00129BCE246B2AF38EE7C3B1F88F41C843762E99E891215D7AF75D3E866 1784218F5E6F2E7787FC98EABF144FEDDB4EB290E6F421CB40B9323B14BAEBAC 2B1C1A4036E7F0D1791D750157EDBF46FB097D166A56EEA4EF427B15AE43906D 5B2EAC5DC996CAEFFDC926E1835C619DDE46B5B0A3725EC51012F7D5967FAF19 C1AB85A35A0465563E9D6A4BB7EA5AE3DC922A1E4A558062838AE3B289CF564A 8E7A314C1207CEDA8A66D8D8BC24503CBA28E962293E3C345B5D0E045E64542B 347E747A71579FCA448A3CAA6FFB54D48436504E857DC92A391977B8071EBBF9 A188CC96E84EEC8E830EFED4B09A6E82F4FF0CA2AB596975832980FE222C96CD 8AAA730CE6A2FD77AB8ECD3BC14797D1C1BEEC9905B9F886979FA97A30DDA0DA 8C608BC47ED9B639F772149425B3648C3A463FCC43119FA4FACD1EB75074CC43 F1611D97D580B94D5213C3C3F9F2FAEFBAC6C0F788575958AB4FC3646C41F8FD C8FA3DEEB38C44EB674EA1D7D013CE575CC683A5F133D7C884A1B9C55104AE05 30C4C00058E8624505299C509A94E74D4E2E097C5E01F5C0FB4D996B5ADC6B98 0CB278B5D00E3C646144985DDAE3A24B43F2C0D6A660648C087EBF3A105F31EE 06F6F285A138D9E91A4647903661FD6936EFECCC0940580D4E63DDB65ED2F68B 3BABDD63B6E2CC435E7B1F4ECB83CC47F6110A22FB7328A7FE015A06054B3846 F63C670C08C8F12ECE7685642939D9381573CA866E49E83616F55EEFC1812C9A E4C1310C1154891BA87C00CE6ECF8C1761CD7B262FD8E1885F68CCE3A71FB17B 7B3B7E33DC700858A950CE396FE45935DE6FB00B1767646004FABA8A4F5E46B0 827F44851D4A1D072365184E0BB281DDD532B21059797B113D55DDB862D2E425 A7BF5F8662AE6FCCD76F515FDEE05AE207D0DC5CBC1EB035C42C067B095170FA 5D9507040BC70F8E35345E5DD6684DD8F240DE8B62B6E42CC93C7C8E624D8EFC 679FA6F4F3B10ACBC3205AD855D1B86356894913AE2D8CDF365AA9BB0188E26A 82BD264D1A24982D7EBA2C015EAB2ED0E5E33ABB8B59AD7E60AB18AFACC74586 D3DDF4B036EDCDEEFE224E2CA6472339A39B8D502CA336C3DF71C156810470C4 33ACD79F0301C7CBB20CDC15DFC1FD7C88A4E2AF23702754200C72CAE8DD99A1 2262AD51912A3C9C3806AE11011A47D531C4F3CB14E64BB6E87FE768A7E8013A 04C5ED42244A1781D94D45D7A8F81483797564D8204F9826D9CCD763F5BA25A2 2602191918E2703AB6CF349E2809B422C2FB78A5F0936C4DBE205E76B0B2AED0 B9A5F2523D479FE926719DADA88758CF1E3C099A36C2041B7CF99E1985762B73 7B16F5303D16BC3864BA1E7FEC734F76E782990E8F99F6B9E68134EB0A4ACE9B 3AE7ADEF2F1B005946BBF765E854B132BE184C1CA7157A53C8665476C1EC56B2 9C32CCA6C317F210F48E8611BB73C5973F79585D155A9A99989AC2A8FDAB7314 A57307E3D7C4ADB264783B54A6C41244637E95F22820BF6D49DA30C00C3D1BEA 4296130968AFB5284A31E91123CE569A5FA766FC6297CDB48AA2D838F78524E1 0971B49E1F5C26FF0A3822902CEF647A3A7078F78BCDE7AF4CBAD00ED300BD17 02E568E01B76B6AF4D85ED1FAB284197ECBB98C19B883F50D3A985D092943A33 7D0F0BEC6DF548DA1149E83D75B3B1AB971A3374CD78B65D934894F39776371B 9A068EDC11A0F314B1AD21AE3E51AC40965520F527085D472042661E52DE8968 F08DC225E3EC421EE0D4652FBAAA38F5E5585EF06659171BE04F3212506DE5E7 7AA5A2178C5BEB2278730B05E4083CC9B57D7C2692F7BC3CACAB26BFD0DC53B2 0998508BFCBDD8F74E0FA1D410EFCA063A4D62CC80BF5CDB09A9E49FA8DCCB54 B974D97BD6169D4F5F441B9C6F977D60FD65565978C79FD5D0AD003AD21DC0EE C8156E46A04D7F8C7D3483AA5CEE636E924F3C80A3C18EC4503D3FCBFEDC4015 09E91357246393E4629FE18F200AA7756222D2B8DBEE5D7AA87975CCC4988B1B 1A2E564A714F020297F3520779CCFF0F94883F6CDC035B14426F5DB41110DF32 E7367B50186A9CA53467746AE88F7959E98683DCA612C29D4F97A1B6D7A4F2BA C92A5347B007BB5778DC2A72E23333062D61E643CE7A9E0164A2D3C4E069A17A 68029382CD79309899FBACB916A1F3AD313296BA113300EE3AC68AD7EE8F9654 A6236A695077E1C195DCC24BB79E3C8ED55000882655C6498130842995987430 267AD06E87F7806D32377483F91F80D6C493EF4427FCF9DC95E5F03069028746 EAC267D225770B61170D39B997919A144F304D65F7318B391F3570E94CC2B5CC 238A8D1A329A6AF4EF43CF2FC479052A94E97D7B62FB0877B5542C8D7819B749 14AC65CFCF6A2EE9E9A2AC05113946B31968F504C6FFE1AB7E72F58AA9E3448A 25578ECBD0FD291EAED7F1B45586E83DCFA3ED9BA924101CC96B6EC14A218D4A FD08D44B708EC13A7272EE117C793DA0D33F2D02D7553EFD4CD86CB198D08940 37E9AC04A978D4A407362D4218A736C0962CE6DEE2C8E231F2B8ADB077D98796 E7A7351D00A5C6F0F2D3C20B15006B0D07446F74EEDBBEA60A1849E408A441A5 4A1D2A1F73EB71722822DC27E7C3F8F0CC63FCFF6BC1FE5E42BD79238008D62B 3627EA08986CC7DFA933BD532C97B45CE64E729BF1AAA73B2E53F304B14C4295 5E23F3106CB4CC3AC487C6EBEBFD83662D3201BACFF71D9E0AD50B4756B68AC9 C91165D79ED5647E40319E8B391B3E398E23FCFDEAE2D201D0AE129709E214E7 142B9EB5BFC58740A672F654D731119489CED8336B847416F8595F712AF1BCCE FAF2B1E3D2C13F7617091DCAC1B17D22227FC8FBBAF503EA14E33AE53A7CD634 F00127ED9161F291F21094A49365AA97CECE92287797ADD2AB25AB42612C7F2A 5306CB894BE378EDC6A5F92C691E114765FC7D16FF244F412F56920FD38E7E96 B06F4A8D0B05E9A1B526AF4F014E65AF02DFC1EC3A22F4D6867484EE329801FE 9264756B4B5F2119B2F51B8EBF4B15884C44F9A9C061ADBB9D5BE96F00E8E7D7 4D51C7E0E13A8E9A8D9AD13F34D3A00B3A9281500A9A85AB0125B1030465660B B8C2C1EE77A0F4D0FB061459C224642D20A141A6D7E1B2F8D46140D23F1F9998 28AFA9559E432E3939C5090F8C0D4005A822BA875D83D903BBBF46EE7322041F 3B1B884FC0237F8C55F747EF1A580DEC5870D945210536F55EDDB6D8DF6F97FD 32833D8A4C232A 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont %%BeginFont: CMR17 %!PS-AdobeFont-1.0: CMR17 003.002 %%Title: CMR17 %Version: 003.002 %%CreationDate: Mon Jul 13 16:17:00 2009 %%Creator: David M. Jones %Copyright: Copyright (c) 1997, 2009 American Mathematical Society %Copyright: (<http://www.ams.org>), with Reserved Font Name CMR17. % This Font Software is licensed under the SIL Open Font License, Version 1.1. % This license is in the accompanying file OFL.txt, and is also % available with a FAQ at: http://scripts.sil.org/OFL. %%EndComments FontDirectory/CMR17 known{/CMR17 findfont dup/UniqueID known{dup /UniqueID get 5000795 eq exch/FontType get 1 eq and}{pop false}ifelse {save true}{false}ifelse}{false}ifelse 11 dict begin /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0 ]readonly def /FontName /CMR17 def /FontBBox {-33 -250 945 749 }readonly def /UniqueID 5000795 def /PaintType 0 def /FontInfo 9 dict dup begin /version (003.002) readonly def /Notice (Copyright \050c\051 1997, 2009 American Mathematical Society \050<http://www.ams.org>\051, with Reserved Font Name CMR17.) readonly def /FullName (CMR17) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 45 /hyphen put dup 65 /A put dup 70 /F put dup 82 /R put dup 84 /T put dup 85 /U put dup 97 /a put dup 101 /e put dup 102 /f put dup 105 /i put dup 107 /k put dup 109 /m put dup 110 /n put dup 111 /o put dup 114 /r put dup 115 /s put dup 116 /t put dup 119 /w put readonly def currentdict end currentfile eexec D9D66F633B846AB284BCF8B0411B772DE5CE3DD325E55798292D7BD972BD75FA 0E079529AF9C82DF72F64195C9C210DCE34528F540DA1FFD7BEBB9B40787BA93 51BBFB7CFC5F9152D1E5BB0AD8D016C6CFA4EB41B3C51D091C2D5440E67CFD71 7C56816B03B901BF4A25A07175380E50A213F877C44778B3C5AADBCC86D6E551 E6AF364B0BFCAAD22D8D558C5C81A7D425A1629DD5182206742D1D082A12F078 0FD4F5F6D3129FCFFF1F4A912B0A7DEC8D33A57B5AE0328EF9D57ADDAC543273 C01924195A181D03F5054A93B71E5065F8D92FE23794D2DB9D6295729076BD8E CBC0F4C1BE246922D2482233846A96D867B66D9CF25A1DB661141D36B8506E61 A022F9EF8BC1F2F674EDF1533E67A78CA29A612AA9268E113C5EB84DA56CEDFC D7A111403E6E2A8682DB04368889747E003A124395ECF0C7FC81218552EE7C6F 60BCFB4120893528670D0E8A4117EA5676915E3591AE5652D003EEF67818A41A 8882E102AEEEBECBD15DCF632ED246A6A58B6A7780DB6F1F9AE3FDAC8344585D E104F2BA2DF06D68945889A2A3B6C262FB53FC670BC5EB7C56887FBFB7AA7026 84115872CFB0652C6BB330447AFF8F0F665EFD6A41D6DB6877B08052F402448F CB21C26BDC900636C99CA347B79AA73AFCDE9762A992CA3DDF7279E5C50F453F 52098529850AFB1F501A442D6A02E0A2896F81C8AC735AF1E7EE47208B4CC944 649DF6802EEE813F1456205C6126D7D0B1821AB62DD65468F3A30575E491623E 0054E2E680E4402E1C8C538DA389B81603BE88D6DC287A076F92B224CD58A0AC 44B8D490197341808DEF243660971F444A560C747BC6F52707ED42A99736ECCF EBCB694A561C3A70A319D204CD40D402FBF937A00BBCBE85DD26C9E3F91B7D10 D85B9D314BC3AAD5A58B107F5F341BE2C53490924142566417D6BE03BB4977FA 6635EA58DEB9508E40B9FFAC75FF44C683680CF242FE210519C9BF92483B0A54 83F48341318BE16D2F8C988FE3DB2E7914581F579D5E323148A31E4ED03BC24B C990372DF5F3B0C5FA32EB2CA4FA0EA33316569133C87697BAA2292E685C26CC F8CD40A2366E60B47D47CC9D0FA29D2836011376A07F78BA7664DE96E775CF45 9BC91559A063073A4C2FAAD0893C517C5C46A1425D07EDCC2B57162E3A45103E FF26A2D2F98B194256A4B052AAFCC08965A50EECD7B9E8F35AFDF7B6568B3983 8030655E7C2BEC961A2F20539D617626E8454E3FE9EBD3EFCEF7F63498441DAE 16CB509BF239FBBE25EFEF07A3E16C9C71EB8D9DCB8403916FB40FD7F4E1A52F 72F2DFF94FD14D7D49FE775390C17C37C1BA0CAF35CF75D682B7833A83224158 D54CE962CFBAFB1B2CA50B60CBEB1F8F58DDB2F5470C355ED9632342D9382AE4 5D33BCA3A0A25EE9E5B39BE5370E7F20684C664EDB48E7973FEDAD9676F9EE8F 701CD4D8CC9B9EBC06E8C86EB88AD56E15CEBB8E1930E8F711CB6E01D5D14967 D7E6C1BDDDE2C4D00384EF4CB02877DECC27AD53FC981338977BA0CC0257CF7D B42E9BC91AF45D9722461EC3CD9DEAA8011FB855FE14B74BE0A102008EACA2B6 0E287BB4F466FBFDD6E65A5262B9322F95E20DAB875A10A84572D982E6FC7ACA 23C0C37E5EB47B8E69C07507B53CDD98CD1B6445E1699CF35B3DA3E0DC56BB76 F997C40E2ECE47DBDDB707EB527055960113F2DABC87FD9EC7D0AB36B400CE33 0D54D4F197B2830B43DF0AA802DFB2BF747A4C44B31FB708B2C8BBE1955A6A28 379C91AA4CC065A50098AEC0B837E180B76801865A43C74859DF18FE1DA1483B C17843BF1C7E1B11A8C6D8BB8CDB1D552FE6A1FD0A696A8F7405F2320F8621EA 17C1A32056C45A9ED35D2BD12D02D8B26489CAAEBF4EF33B66FF4BD9B46E4823 6395831A8F3366EEA0D0EA88D612DEBF63DA7FAA24DA979ACC1A52544BCAA007 6C39946BEA6076ACF45722B2B8E4D0823EA2D12B14A98367BB0433A21FBD9F94 18DF298C56F67ABC9DB1868D431A854DBEDF8E1F49E359A545C75A7AA1FA4D5A 50F1EE6B45FC68ABF65FFF257964E4E50D8B0C1FAF498DFC554073697C2F219D 4A68DA9E873B270B9C56F0DDBC9927ADAF9203FD684DE615F68C24ACFFB44690 89C0D5322049FA69E7FD00EFC9C9B2BD177B5B339907F81C31496662847BEC1E 56B5DCDF4FE618970F4268F475B2EF7E0F28CC986DDF098E59DDAD818649CC35 4080C0867A884B8177A6880F06F1E5CC130AB4243EF8DD8032FCF390765BAB1C 1F0C9728EEE261A09F8C1D7ABC7A6B1550551BE2A7D19D45B656650DB00B3A5E B3E1186043E173BB4DD5EFFB379654F88146382AE3F7196F099BDCD6D245FB6B AA2FA9B6CFBC9F0CD52798DDF2F13874BDE5B124DFFE0DD93E24C9DAEAE4C3BB 71A9A13AE2860F620B4EC789F95221015D9C510CB4AC775EF69DB9E32E59C896 1AF82C9F0DCDB4812A37761859A3D3BA0CA57F244489C78065346FFA78F5F7C8 0B2E8CBA9EE62FF5C27369D0BCD52857D40F1FB8F8A1441B83565A4150AB1945 0B54D6E49F66389E43096269EF5CDD39526A288C0CB81E324E75D326EC9A182F 2CD966368CE300B41873B08E17C3E6BB51804460D2562AF5A12339966F44CD09 114C6809AF246B5BA6937631842CB9417781A58944B6BA4FCF961465C208957C 81A662D560D0F81BD3CB53C06B6D979F04F6121CCFD5D52702CBF6C70C01EDBF 2040AAB9CB144321E68C4010E0E98CCA2603EB55DD62E881DB621C37EA4108D1 528ECC7A0121B57C6BB1E26F8AE7161ABA7E88256D2D6A8B7CDE2E730D137493 3FF628EF6030DD2330D747FABBA03B44CF600418C245C388F33EC5559E7313BC 4B530C4FC12530D38B27D6408548F25FC084DD0523B27D29D6518D3115AE7755 37162CFD4CF528214466FE525B13782F9C3CD78F3D6C7423E63A134C0A371F15 10F4ECE1D482C647B563D3D15586F80BD9DF7381BD53927825D5AEAF762E1CDC 3BD184F345029A95B3AD4D1B66E79AB4F0809418C0CFD4D503457A190D02F134 3F57FC04FF655AEEB783D6791E4EC300755861837D3D50649F6B7F60766211B3 8148F8E575E28D6C2DE75B15E722ABFC6DAADAE53D89FD295352781DCC2CFF6D 982F6DB778D6FCBF1B7BDCB53F3A23AE6EB499BBFA96E8BE04C3C8E5B660EF24 01EB842DAEBE979F2C2DB72AAB4D21627063B1D3C6CD40944E4CB81655698FBA A343766CB22E392E5DAE01DB33A00918D6DAA07F2F38B336A3C5DF3708865E75 0DE04D3AFBCA27A249E97377D5785B4E28EE0E93F7D353619C200DB967372ED2 153BF8BE945474266EB2FD30F80042A11B7E3586DE4AB1FBD4A741D36DE583E9 1CA25DA345520AA60634EC819E7EB493CDB128BBADEC3890F055455F060A1100 D5A41D7B180027E08AD6EE7E393DB9F83799544404FE397F557773BE6A130541 157C0EB37E036C94825B5090EF85F8B4E3DB72895D86687758C20EDEBD6D1079 196E9949DC6ED0113571C70B150B37E446E319EC54D44CC0CF6A14760953DF4A D0E1F33A54D240E236AB63B35BA8E071D77776BE5B9312245F2C6E4FDB4312A0 0D9CF723E7D9A3D8546C4739C00C301A89ABA60A02757AB1A0AC40B24CE6CF12 5850485B11E16646D7150795EABAEB08364A53161111F46A7BC3423A0D3BEB69 BF15726C1F8363914945DEEB29CB8766328318AF3B344FD6D77BBB92BD7FD161 93356493D4D8252AD125708D47C124E44232FB2BF7DD75F87889496DCDB75D03 F58A57D4122CFC194B75A9E9C4789C9A33C0435FB4ADA16AD4A6191928D1663D 05FB8152C0AA176FBA4755205F8A66713404787070757D3721ED6E6D55A59DF0 C92BA8F05EC7BE05D0A2E66DE85E75373483EA3BBEE0F0DFC7E2FA5FBAFAB118 058D095AA71FDFC8AF37E5A98406B64E58BF476C6926725D7EF3C2346CE3F662 1E5A4A18D966479A37070859014719456EA2C7F23E68E1AB2F25ED3A0C00A18C DD403506923BC983F89CCA125780DC76A411472E38173BC0DD4CDA7B43E13419 B5AB0B9A35E77C58BBA12AA4F5C7EBF8A29996B059E4FAE6809565570442AEE5 D56CBF4407E1CD9A4398B1F3ADFF023F64B230E3D29F526B62D964F5C8DF801F E94295AD85BD9E1C18E6327977260A871E921C0745CA06A263E335E344686E7D D6FE3ADB4EE0A7E462F3C00873C3E95D183CCEC71C0E5DC1D2FB310B28FC3611 67C23DE336C374F72368F4973052B48E39969305791C986E6EE35D0350571860 3A8ED849712CF21AEF444BA390644E8646CCA16559BA4642A5800827A0DDC453 7CA0818BC47DF6348A5209A2F0A10CA39840CE6346E89CA0E842BE8692DEF25C 4623A5A0E0B98708B9492E9F564324BB3872D6B953CA59E9F393C477E2AB85EC C557D333E88C111CF995FB79D9432DC94C2BDB3BFEE13C0D7D1BB920DAFA6158 8548447AFC65CD5515D5021E0ED7D213B0C08C35BB424AA91885CA023D7AF767 B83E619B15DFEF5588D2F0564296E14B5A6ACE03751E1016105C51BE76EA5ADB 4167BAED2A8899031FD7BA05C410ADA25ADD94A787EED1A7AE133B0568B1DBA5 44B41BE013782CFCA3D81E8E8210DD506ADFCE7DC7E792EFEF438221164A7D1B 5E7089F476240C5F94988F081943F24DBF7CC3D1E58CB89E1C0C1624682CC3D8 C95815ECC9183A4B3E353C7F920B7E64086E01672DAA7C8A81319BAA03C1FBB7 8E5E84CC5BAE0E107754794C755B7AF00953504094E1A9DF357D51B578259613 8D26F0BA26AAC459BBEEB90BCC98B865EDD26AA4DF533D6624EDAC762C446B6F CF9F86DD2D8989D4655775E662B93BF51805EE3CBA0AE2293D95F166E80973CC 82C53042D0249C598B0821E9E7F218BA6114EEC86C158F277934F2651490B723 7F0D0288560DA5BEBAFDDF243048E590871AD18B3B220EC56549004DF122AA03 BAAD6971D790BC644369FDBEE74A324083CFA9496C2A333774F06E35299242BC F4B26578907CC5AD1893613F2B8622CFBB7B55810162EEBFAAEAB2A6D69CB72B D7859C73843E665125FF450631F32E64F13A6207F368103C7A7318DBAF2560D0 F1CDD83C3E48CB30C62AF1E0896E1962C655D9ED98E1BB38477C1C60ECDB6B95 067D3A638AD43EE886338F7AD2D2A574CE6FD2E21F6FCB4220EFEC85ABF8272A 82081CE70E4390A74EC717F1DDD168F4A4A080A79EE2ECE0F98A96871DA4B52F 78441601AF47763C2219F5A167604C32F478D498835EF3A6167936994F7C7139 3019FF43C97E7978D3CDA641C1E391FEA572D308E759F28DDE2B40B5BC207A4B C5EB6A93EEE26782016F8B6534420BE4D790A2E1A65B6CDBE9468152230384FD 14E9AE84418A44F94E6825DD7D77D0BB5486DE26A692B3DA96C81FA4440C5D44 8E7F3CAA9B8DF38F87E09C4D78841F629F78F4E7CC8580CC44E59E5D9AE8B2DE C0682F793AE7AEC12A8AE688636197E8A08FEB70EFDB6203681A60223B9B0D39 2DA656E5E99B82130D4BE38D7AFE18568DD30B0CC3C73C1E2914ACE11A65334D A9F18135E7B86157122CD221C33C62012FFB16D2D2F3473A53BE3E7B9FD4303F 66ADF0B07155C7B9B002EA68C6AC7247EB3CE7D2670A60138049DAA964F86A05 22983EDA7242E6BEEB90DF61C937399B2CE1061DF1E551CEED4A80D86C2D4649 C9FF9A1F93E96773CD392478D5B70D5336A03A274E0A6EF44BE8CB2274324142 706BC2E340DC944339D647961FD7BF29944503B4AFCDC69A706AA6B0F6AB2CB5 D220A96ACC1EE5E7826F6F75F044224E5260D581AE761AD0C752A06AA03FD935 FAD65C9EDD4E5505396E331D45DE88F0D1A4303D766ABE0702C17E2A7F53C0EA 96A4DEC5A6B6186F5DBAAB05DD78E38AFE630465BEF0EC66ABA9C1C9232214A9 795D105C33CF069F6BE20B179F4CC9F484AB63ED25C1212C457DF62CA0D56E20 608572216F2D4C09010B03A8AA6D287C8F514BEEDC1C912552CC2489858BF4D3 084882CE4F4B6FB9EE27C0168671E6DA154018ABEAD013C88E1D3EC918371251 63D95BA0FE20212C20AD3F4DB614EE36B488A3F55D94C1EDFCA8E68E54A1EED4 7DD168DCCF07C3DDB5E2B499DB5635C5C5056A7438120DB4839427D07F96AB8E F842E285243E40259F6DF029E27779CCF3D3BD7206B2C341045A5A4AABACC2A5 91C6830FE05ACDCFDE99046F16F2AC183426ACA4A89FE5F09B7EB2F811BB5FB5 AF073BDA2886070B2327D582DCBA66B47E8948C3BE05E837BE4B81402A583403 74FF9E938F0E9DC3B1CB81B93DFD4070F9EBAED40BA570DE8F9A5C2C0A097311 22A6065139A6580E332473E9410D9F4C734794F79E41D0D437CEC7381919DF6F A24B170E2BC97A6396A4E3AC3D844AD6E2B8FCE1C6AE97DFC5319F49130C3D6F AF2541EB2384D5D4CCBEB976846EF8C2165DBF706112BDDDEC9A57D157F5996D 95229FD5C71B885D16B177BAB06B9DF5740A45C2A005778EE879193290419C0A A4A339029E37E685B8A05B111DDF94AC19B1D85C8E6026E57E3D3B373C08557A F96E6FE3916695ADFC1F0BF5D558565F42A71C61ACFEFC9026424397F0646642 7EDAA05794BCCD164A645860B57EAD53CB6899B18C6E9496EA4DAB0A0C272639 DEBC4FCBA94B3BF123F7771F602E7667C8F56E12429669F2219C7D8E294BE07B 71E88EA62F5616CAAB7C0198E6FF12A348E36B306FE2684A401399431B6A84CF B46EE4BAA0F4099E65E9AF3B70274EDD6B6524F4FA38C23F9CD5273EEDC8C6C3 E7312B6E0497C05AD3F3C246638F01387CC11DBCBD287ACF54D8E24759F51415 35ED64132EF4158F54AB9F4D567482B3057880490F805822F71E7E2C52F7BC38 8B1F803AC3731064B90E5E97AA3351D17E73DC2FE526CD6C91158636E395867D C1150FD3BD12493FFFB813AF0D08C8ED0B7418A2CF90BD5B783364358605D075 5DEA95A9299C0654EFB28E2FE8A41358A0DD124D0314A27558E42ED5F2D74BB7 056DE04D2CF13B9B804A3CBBA29BC155A3F18B8B48283194C33CE8291677E1EF 0721138F8E0409D49BB99F217607586D2DF00C29A25536E21924B4CF6702CF85 C02DFBFD2AA4DE3DBED1D2C02E21052A8D10F96629D0D18154923638FE0C48BD E2DEAF11663E20717EA77A5453686AAA39D6FF7919AF09B1AD956FDBF734F49E 262F3076F62E77BD45122B55A5913902D9F91C4246FC235BA9C0FA4A96994291 830638949BED423387DA2D455A3C9122484EFF27F5367D1D3DD27D207D973815 965E1CFF36F43C653ED406F65348671D9FFAF55BA3FC266D438AF473181B7801 164EA3F04FEC870743195B3F467DE36B3719BAD9BF15A18637A314C887D46673 445BA3C212749B0A33136FEE9FE2C9A13D62E7ACC96378D257FBE0EB06AD4D4E D41976AB92AC720DFD33B0677062C32E6F5C992A0324FD26E984B5341A58C190 D20EC3F1144697D514D9157340A6C9F82E62AD8CFDEE59F6FF86C6250CE33D6B BB82DDB4F65BEFC6F6D0E4044F7BF307CC346E2FFD191846E3CA288C6F91CB71 5FDE855FEC5E38816CC635C470BF15263A10A409F0BC4877F7E6D4C223E3564E E7BB5B320AAA5AAF4F32528F7413BFB97C70FF5E6843E1FE501472129BC9758D 7531BE576C75840CBC4CD3E6D9E5FF52559B68DE6E7827128BB2ED1BAD43F36E A0CB68C1A147A7093EB02062AC5492DB7EEE08B1BDB187E15339A66269E459BC 67495937B4317AF66A498923322B087ECF47B601C26E253D223A784DB2D204FD 0668BD403A73723848018B7C86B627B9AE0BD9038F567CD5F670CAFC5C4D86FC ECA211B713ACF8C1370191161CBB6C2592E8B9DBF3471133F2D9A60F15D72F9C 5E5539D59A6A7E124D9A38A6FF6EB7C71990716F88E1888295584F17D49144B2 B57183FE1C6ED5D71A48D20EA8C18DB6CA7D3C3A6403B9A767D805747C0D25BF 7F2F88CEE69141F72141640FD36EDB5886A78D3A1E0FA4DD0E213082C3E6822B F981212D179C25CD0570748C3BBE642CCF1F43F5226B9C2EEA6B966628B185F7 11441471ED972022B4D84CF007C1D9B1D12804610E4F730DAF2F2D5AB767C320 C62543E261EDE128761D164A9843955BBFEC7213307B78378CD1914FD7D79D14 947572CB28073B7AA530ADC51270B03CEB7FD7ADB4D72671135435609A235501 EA55EDE2B2B915DCA5D50A7E3512B325253FEEE5FB8F99189924DE9EDDB672E5 653E83A354F6E55F47CB4B2F056C6232AA66CF460A06E592FB4DAB538C280A86 6C7FC5A1A8A411A597335E6BCB62888AC8539B30E8AC2A39A813FC4891B49E77 75375100F55E9F16BABDD3F76B2F587530D12214A376FCA98170E67BE8E450CF CD9116344965344652128A18AA5FBC61A89117BB7D016B4F18A1B81B17D28D28 4E88AD093DD415E8CAFFF90EC043388F37FAA134C8796F2281E0400F7760B408 FEDFB89C3BCEDA58887EFE51865FCE4C95D8AA12E1FDF5D6FFE39F4A70E14F7D B441B2D22DC99098358DE77FC418A1390B67980518533AB4F7CDE57AA7490CA1 5AF1A21A10D919935BE812D455BB28ADF57794D07CB33FE8EBFFC29DF833D394 F2D6060EBC4D96C2A7C539C64DA7A739262A83B49FA9EFAE117C1119102F1EB9 BAB173960FC04E4AB960509804B91544D7A3A811236A74DFE3320FB44C8E8827 BCAF2AA2B9B3BA4CF07F61BF2301929396386E4616417E0E3B7216C72E4F2DE4 CD646CCCCE2B38E3808D56E223AD1F32EECD0401488BDD56A4F42833F3E68E76 29216C016B647986E68D972F689938B5E26789AC239491CAAB03CA431B58623D F02865FF18611BF5C863E6C40709087530D3BF5D79A01DEFD54B27ECE80E1568 B2DED8B01D82B5A2F1874BE4F73C6C16A088EB166ED11508CA4A0975B287BB15 112DCFCE93AC76F970F3BEF78E13478C4ABF0829E4F96AF9B76235200355AB04 1F8145974E6B83E72463A37150FA5225C7E73F4BA8CFA449E78EA296DED1D09F 4E74BCB41424AC5E4FD5ED4DAE0A2290DD4D2BBBE43DAEC727F4574742406BDC 86C9BDF40E3EF07B2FEA3A685E66F78138255FDE8101AD633BDC63E43DF565AB F1C1BF6BA95FB1430918CC00D818988E88E4C70291822649FB093B230060E7C3 008EBB0B0CF1D242142EDFD7F2613287917DC626F14140D2B8AF19FA98445F43 A51092AB42BE578D1B2002747A4CFE98A4E927303AAB411DF1DA710F69729FC0 605F060115ACF07AD8710086899E039BE208F1D3E6362D5DC0D46B5643F957B7 6332D417C5CE41D985AA98679114ADF6901908D7C0122F59C2A622D02F6B5BFD BA3578972F084F76A4755753DFF92CAEEC6BF2373054F17153134B93B5A22999 97824A8AAD155AC0BBBBCCCA16479F34AFF09721D80CFC9C0B2EDFC0FC1F8DAC 357E3EC03FB25170540035DCA9B630138C9B03ED2FE920D73A1A0F4C1C73ACA5 4D9F63935F355CC0C8BEF6614AA858103021E6359575930AA58B02806E1F2971 61601FE8EF8CE9A6C702945CAD9950B079D59653D18732BFF2266C867D3ADF36 D4E623A8C5DDA26E118D5A12DCB64538A8635C653A5F55138EEE60A122664604 C938B4628ADD1C4D901D5F2BFECDA5385D96DDC2E69AFFB69F718D1D9176A2EC 7F15E5AE838A9054177E215EDFD717E8A2167DD250065F3ECA5CF098FA07BA24 9433111AF5349D65E6462B62474DB667405873E27893C71755EF9256D319CC48 DBF9529D4ACFA6A652F9C084364B50C497EE22BC9CCA30959589FC5D55472F81 CF1C32ECC8B36980319252D5CCF4C9BBD5C6F871899DC3E907EC670E0D90F8D9 C3E2840C583AF7944D80CBF9411E115AFFE23DAB0EBDC950582807A9B43986E0 83C74EDBC1FB81A139AEB9C2175F6F440BC6C68BCC20EE7126FCE3F2414FA98D AAD4394445D9EF96526B9E64DCBA8E1803A75F7ADE5D754F0423B0E7AA1FFE65 DCCA47FBB3ABB385EB1B18BE01FD161B2B9433DE942E44B05ACC5829D4A28FA0 E85DD49DCFB8D6C7732888442BD8C910A8FDB65C5CDB8D579B4F2834F52C7044 2FBE7FF9E156BFC01ED80D82034D312BD5FD66812333C8E49D16FAB86DEA17CB 573E164CA895B303A9959327A85E215CCEFBB6824EFC1459A9C7D560605ACE67 3549AF9197FC52171284747CC733AAEB1C3DEECF292CF03FB39F42D8EF1A773B DBB6864A58B673A836AD5C592585D885D00A7823365B49BFA6911EE8DBBB1E19 C3D7C3A7E114CAB2F3461C1F114381CD099A39D05DA142B50E1B4052C06F44AB 021CA43AA16442B1D5291D1F8BD85B77ECD8511761BB3350C358C4E906E3DB61 28C67A4CB01AA228A2276B2D7AD070BD0DA61C85096AE2CE20CC6EE818EBB7D4 00D2E3B9E5025B156B6957836F5E9F1967DDB5F01A51A1115C59AC20F5DE0B87 DC5DEAF638C0B2402D2133AE9350B365AB274D0F5342DD838CEE7D08EE6FB757 8A1C20BB0ADB96B8E2930AEE816352431F420D60D93E2CFFFF058F4E1B87E4A3 9DDEE0C50D44A27834859458A02E69CB7BBE94E565EBE72F44DD580E558C71D8 1173C5AB8AC1170DDDAAAF360FA651E683BA731B5B86F9C42E4609849738EDC0 CF259868DFB3DE2140D4816B50CF7E4E7313FBD1AA138CD6DB1708D0941778A1 F52572EE7363F9DF8DA6323B8C050C2A38EE061A219AEC38F40FBB34ADBE0D8D 3D878F99ED78AECF24855E0D859FE5CFE859A94E445A273BCECD995F98ACB6EB EF882E094AAF532BE0EDA73673ECBAE439FE7C432324100E6592B5BAF72D00B6 2985F15E9286B856D30AE4C2CA1C870586EAD5D88401DA0F99CBF639FCCBDA1D 16979A5E6E932885990EDF9197FB953E61862134EAEBF9A0D9259055DE8C3448 0DF3AD33BDDB4C7510796FDE56C9BFE8BFADEE690ACC47E3599A59F5903077D1 F27FD32F0C232E235F799895246E1C44D6A354D948AE860D8C0BD5355CC1C496 90120E835DB8B0976FA130D5556D14474CA9CBBD225DEEE59125206782DB95AF CC69D52E44FB45D624AC1E285F0FD66EB6E76EC6F7365B2477D77109DA9D9159 DC88028FE840EAA63A45A12506DE11E1EC63A4076D44EA550974E93B3CE4A9E5 C39DC286D7EC81AD7174BFFF18505D37ED190A136E2D8FFE966A15FFED1812E2 D6FB1E546167316D3FDCB0B4B7F39B328F643AD087E7288C2F1FC044731B6DB8 0077EE6E90AB6D92311AD9B1D5ADB744D95E138D2DE8C6266935B1D4095A2B13 0D3743675259C9F03B6C2F1973A8E0C1F05F22467DD961F7CA7618CDA8ED5309 7A09C33BE07B6295310EC4FDF50F76AF6E8A33D1E22B2943F6D4291F739C3EB0 3DC861D77E42853278E51BF741376CBC72C180A8240756291201CA87D2659C80 2CA9B7DE8359FC6E823850AD910B5D9279CF4D2BF5CD2B6E2D287B25CE9462EE D4E273788109E40D6C04E6B038C0EEAFC83BB473561676FB0AAAF46B1DE6A758 623E83D1448A4194B5ABC771AA62607B728829ED402F27961372C6F0FDA2C62C 6F3786974D170E1AB4C965FC9698C3E2C8CAC5CBDCCD4C81E4F27AFE55719233 B3097A8590C1EC247D7C299339E69F227897378D8B1A6FA6FA10601E3A8748A2 70AA4F8B1F757AF2BCBF3C50EDD8B3B2335CC3D77D135802F9B8216293E2ED71 B75698715878DD7734EBE9428ADF7A431C99709B1638C15F45876525B31619CE 3F4E35F7A6A1904F03B1DF2AF14637E50C6042872F4AC8946D612D0CEBECAD4A 45D85A32E454CB0AFB256C3AA3E5A6231E664598EC37B1E7FB8D9EB62CC7656B 4BA381CB99D9D6288E94E0331665CAC9C4A547D72F6906B8E98C6A251B806BAA E967C076C6C0612B346EFFF2B83DC52377EF06050567436F5EA58FC33A126AC9 CB6F0212E0BB53FEBB2D09336F562F41B21629926169593070937F272337D400 CA5EB8860B71B6205EBBD78CE8DE86EC93D5E6629884F81E47CE9A162B6F3A6D 7224B5E942C39F65DC5259FD1ABA3190E1D7127A2AD774B3B3D46E22756C3BDF D40E3E6DA9B2F77DF3A13CE2812F9767CAD34F3FB9B0FBDC33AAB64FA87A29C6 F0096F427B76FFFD3E8548BC89B6FEF1AABBCA9D8098FFDE65452217B7E9D039 96C5FB8950CC15C69B33B0627BF88A2A62F216DD497DD901C1B26A5E65ED81CA F77917462FCB349631CF840FCB6E5EB4DA70C0F06FBD26337636FB6C7D740827 96BA1C03A495170ECE694D56CC17A1C8617A08118F4BE9CF3636EB1CA1DC3208 88C45DDD3BAF4E32BE4912EDFE1DDBC4AD0774DE9A7C5083B7AE74B35814E858 ABD661C0CC5FDCF483C5BB8D92E678258B8116D143E653C64FD6971AAB4AB0AF 88D70A8D4DE7EDC6B93AD73ECBCEF42B55881235061EBB1926A7F7B30A554A9B 72339A33E119CAB92C3B27E673EE84FB43D9C147BE39CCC06E082B2C180F1438 9DB3732FE2006EA35ED2D7E0534516B0B9608AE9EED2705BC15F4C859B5F554B 3B88CEDCECFF99BA4432C49CF155F9F4662849BA83D718A2B4C6CBBAD15F738A 6C09410F21EF6F473FC85385444221D1A1C9E0783B674D14BC1EC8E9605EB48A 78B79D521F40C6FC6DBF66CD9771A59FC5A5D239B2E48250AA8B62B3ECEFB6F2 92ACC33424957E4EE789984B3D864D1D2BF2F2F856B36A33AF8EE53F629BA05C F9C79A049188A27939F404E7F647242863D839D7B5E6B4B67CFB9B43E959ECCA BDF2679AAFF0C8E2E16004699C64CD8FCACF4B4807CABD9765CCBD5AB30E165D 9572F9FCE083831349954074F29E1D304740F36E4DC228AD955CE0B31E10D01F 0CA1AB6ABCC30182DB4035D606316EF69C600B6FF6F75913B804F7667501F4D3 6B757435575AAD2328A905CFDD298700F47AA80262DABC59D70B52A0A830F66F D37616133BE5E82ADB14624B81148DC8A73A4CFDA9A95EAE3A85CBD9A3D332BE 4EB4605738500BEB3589C81FD099A26D3399800F4547615C3AE8C55D65E6D4E3 1D36172FEB1D5681D30175788DFCC5C72964E1A49F4A992FD890F103185D16D6 81B554FF0FE44032F5AE65A1CFEA5D750FEBF1018B93E680B9B1C1DE27299EC6 6675F3744FD875ED2CFDA01C4CA452FC67C29211EC1F31B5AA85B44E2587283C F9F0888AA9C00D521A82E3F647D0EF90101F21B354C4DE739676213479678FA1 EE809D35AD929F9853BC55BBA522B1057A3EA689A2A6308FC637345CDBA40DFE 80D4EF6445E1910B444666AAC270B11FC8C24842BB2EA93FB1AA3A1C9FFF96C8 2808CA772F2DF843E4CC30949F6093B9FC4DEB8D22AAD12C9B6D25 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark {restore}if %%EndFont TeXDict begin 39158280 55380996 1000 600 600 (RUnit.dvi) @start /Fa 130[52 1[52 1[52 52 2[52 52 52 52 52 52 52 52 52 52 52 1[52 52 52 52 52 52 52 52 52 2[52 1[52 6[52 52 52 52 1[52 1[52 52 52 52 1[52 52 1[52 52 2[52 52 2[52 52 52 1[52 52 2[52 52 52 52 52 52 52 52 52 52 52 52 52 52 52 3[52 1[52 34[{}63 99.6264 /CMSLTT10 rf /Fb 134[51 51 51 1[51 51 51 51 51 51 51 51 51 51 51 1[51 51 1[51 51 51 51 51 51 10[51 51 51 51 2[51 2[51 51 2[51 51 1[51 51 51 51 1[51 1[51 12[51 2[51 51 51 3[51 51 40[{}43 99.6264 /CMTT12 rf /Fc 135[71 2[75 52 53 2[75 67 75 4[37 3[61 75 60 1[65 12[94 1[100 8[50 5[97 16[67 67 2[37 46[{}19 119.552 /CMBX12 rf /Fd 134[47 3[52 32 40 41 2[50 55 80 25 45 1[30 50 2[45 50 45 45 50 30 13[71 4[87 3[38 4[74 70 67[{}23 99.6264 /CMTI12 rf %DVIPSBitmapFont: Fe tcrm1200 12 1 /Fe 1 137 df<0003FF0000001FFFE000007FFFF80000FFFFFC0003FFFFFF0007FFFFFF 800FFFFFFFC01FFFFFFFE01FFFFFFFE03FFFFFFFF03FFFFFFFF07FFFFFFFF87FFFFFFFF8 7FFFFFFFF8FFFFFFFFFCFFFFFFFFFCFFFFFFFFFCFFFFFFFFFCFFFFFFFFFCFFFFFFFFFCFF FFFFFFFCFFFFFFFFFCFFFFFFFFFCFFFFFFFFFC7FFFFFFFF87FFFFFFFF87FFFFFFFF83FFF FFFFF03FFFFFFFF01FFFFFFFE01FFFFFFFE00FFFFFFFC007FFFFFF8003FFFFFF0000FFFF FC00007FFFF800001FFFE0000003FF000026267BAB31>136 D E %EndDVIPSBitmapFont /Ff 132[49 43 51 51 70 51 54 38 38 38 51 54 49 54 81 27 51 30 27 54 49 30 43 54 43 54 49 3[27 1[27 2[73 100 1[73 70 54 72 1[66 76 73 89 61 76 50 35 73 77 64 66 75 70 69 73 6[27 49 49 49 49 49 49 49 49 49 49 49 27 33 27 76 1[38 38 27 76 1[49 22[54 54 57 11[{}75 99.6264 /CMR12 rf /Fg 134[59 2[59 62 44 44 46 1[62 56 62 93 31 59 1[31 62 56 34 51 62 50 62 54 11[86 78 1[84 3[88 106 1[88 1[42 1[88 70 1[86 15[56 56 56 56 56 1[31 37 31 4[31 39[{}40 99.6264 /CMBX12 rf /Fh 137[85 90 63 64 66 1[90 81 90 134 45 85 1[45 90 81 49 74 90 72 90 78 11[124 112 1[120 8[60 2[101 1[124 117 1[122 13[81 81 81 49[{}31 143.462 /CMBX12 rf /Fi 128[59 9[65 46 46 46 1[65 59 65 98 33 2[33 65 59 1[52 65 52 65 59 12[85 65 5[107 1[91 60 2[92 1[80 2[83 88 11[59 2[59 59 59 3[33 44[{}32 119.552 /CMR12 rf /Fj 136[115 2[61 62 61 2[79 88 133 1[83 1[43 2[47 70 3[79 11[119 115 1[117 11[104 4[119 19[52 45[{}18 172.188 /CMR17 rf end %%EndProlog %%BeginSetup %%Feature: *Resolution 600dpi TeXDict begin %%BeginPaperSize: a4 /setpagedevice where { pop << /PageSize [595 842] >> setpagedevice } { /a4 where { pop a4 } if } ifelse %%EndPaperSize end %%EndSetup %%Page: 1 1 TeXDict begin 1 0 bop 0 0 a SDict begin [/Producer (dvips + Distiller)/Title ()/Subject ()/Creator (LaTeX with hyperref package)/Author ()/Keywords () /DOCINFO pdfmark end 0 0 a 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.1) cvn /DEST pdfmark end 52 158 a 60 194 a SDict begin [/Count -0/Dest (section.1) cvn/Title (Introduction) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/Count -2/Dest (section.2) cvn/Title (The RUnit package) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/Count -0/Dest (subsection.2.1) cvn/Title (Test case execution) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/Count -2/Dest (subsection.2.2) cvn/Title (R Code Inspection) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/Count -0/Dest (subsubsection.2.2.1) cvn/Title (Usage) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/Count -0/Dest (subsubsection.2.2.2) cvn/Title (Technical Details) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/Count -0/Dest (section.3) cvn/Title (Future Development Ideas) /OUT pdfmark end 60 194 a 60 194 a SDict begin [/PageMode /UseOutlines/Page 1/View [/Fit] /DOCVIEW pdfmark end 60 194 a 60 194 a SDict begin [ {Catalog}<<>> /PUT pdfmark end 60 194 a 60 194 a SDict begin H.S end 60 194 a 60 194 a SDict begin 14.5 H.A end 60 194 a 60 194 a SDict begin [/View [/XYZ H.V]/Dest (Doc-Start) cvn /DEST pdfmark end 60 194 a 362 696 a Fj(R)l(Unit)52 b(-)f(A)i(Unit)e(T)-13 b(est)51 b(F)-13 b(ramew)l(ork)50 b(for)i(R)264 992 y Fi(Thomas)37 b(K)804 997 y(\177)804 992 y(onig,)f(Klaus)i(J)1484 997 y(\177)1481 992 y(unemann,)f(and)i(Matthias)d(Burger)1252 1141 y(Epigenomics)g(A)m (G)1179 1374 y(Septem)m(b)s(er)h(15,)g(2010)60 1815 y Fh(Con)l(ten)l(ts)60 1913 y SDict begin H.S end 60 1913 a 60 1913 a SDict begin 14.5 H.A end 60 1913 a 60 1913 a SDict begin [/View [/XYZ H.V]/Dest (section*.1) cvn /DEST pdfmark end 60 1913 a 60 2033 a SDict begin H.S end 60 2033 a Fg(1)90 b(In)m(tro)s(duction) 823 2033 y SDict begin 14.5 H.L end 823 2033 a 823 2033 a SDict begin [/Subtype /Link/Dest (section.1) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 823 2033 a 2419 w Fg(2)60 2251 y SDict begin H.S end 60 2251 a Fg(2)g(The)38 b(R)m(Unit)f(pac)m(k)-6 b(age)1153 2251 y SDict begin 14.5 H.L end 1153 2251 a 1153 2251 a SDict begin [/Subtype /Link/Dest (section.2) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 1153 2251 a 2089 w Fg(4)206 2372 y SDict begin H.S end 206 2372 a Ff(2.1)100 b(T)-8 b(est)33 b(case)g(execution)1253 2372 y SDict begin 14.5 H.L end 1253 2372 a 1253 2372 a SDict begin [/Subtype /Link/Dest (subsection.2.1) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 1253 2372 a 61 w Ff(.)50 b(.)g(.)f(.)h(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.) g(.)f(.)h(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)g(.)141 b(4)206 2492 y SDict begin H.S end 206 2492 a Ff(2.2)100 b(R)32 b(Co)s(de)h(Insp)s(ection)1225 2492 y SDict begin 14.5 H.L end 1225 2492 a 1225 2492 a SDict begin [/Subtype /Link/Dest (subsection.2.2) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 1225 2492 a 89 w Ff(.)50 b(.)g(.)f(.)h(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)f (.)h(.)g(.)g(.)g(.)g(.)141 b(7)431 2612 y SDict begin H.S end 431 2612 a Ff(2.2.1)111 b(Usage)995 2612 y SDict begin 14.5 H.L end 995 2612 a 995 2612 a SDict begin [/Subtype /Link/Dest (subsubsection.2.2.1) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 995 2612 a 88 w Ff(.)50 b(.)g(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)f(.)h (.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)g(.)141 b(7)431 2733 y SDict begin H.S end 431 2733 a Ff(2.2.2)111 b(T)-8 b(ec)m(hnical)34 b(Details)1473 2733 y SDict begin 14.5 H.L end 1473 2733 a 1473 2733 a SDict begin [/Subtype /Link/Dest (subsubsection.2.2.2) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 1473 2733 a 71 w Ff(.)50 b(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.)f(.)h(.)g(.)g(.)g(.) f(.)h(.)g(.)g(.)g(.)g(.)141 b(8)60 2951 y SDict begin H.S end 60 2951 a Fg(3)90 b(F)-9 b(uture)38 b(Dev)m(elopmen)m(t)g(Ideas)1501 2951 y SDict begin 14.5 H.L end 1501 2951 a 1501 2951 a SDict begin [/Subtype /Link/Dest (section.3) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark end 1501 2951 a 1685 w Fg(10)60 3283 y Fh(Abstract)60 3382 y SDict begin H.S end 60 3382 a 60 3382 a SDict begin 14.5 H.A end 60 3382 a 60 3382 a SDict begin [/View [/XYZ H.V]/Dest (section*.2) cvn /DEST pdfmark end 60 3382 a 120 x Ff(Soft)m(w)m(are)30 b(dev)m(elopmen)m(t)i (for)e(pro)s(duction)f(systems)j(presen)m(ts)g(a)d(c)m(hallenge)i(to)f (the)g(de-)60 3623 y(v)m(elopmen)m(t)35 b(team)f(as)g(the)f(qualit)m(y) i(of)e(the)h(co)s(ded)f(pac)m(k)-5 b(age\(s\))34 b(has)g(to)f(b)s(e)h (constan)m(tly)60 3743 y(monitored)26 b(and)f(v)m(eri\014ed.)42 b(W)-8 b(e)27 b(presen)m(t)g(a)e(generic)h(approac)m(h)g(to)f(soft)m(w) m(are)i(testing)f(for)60 3863 y(the)34 b(R)g(language)f(mo)s(delled)h (after)g(successful)i(examples)g(suc)m(h)f(as)f(JUnit,)g(CppUnit,)60 3984 y(and)i(P)m(erlUnit.)57 b(The)37 b(aim)g(of)f(our)g(approac)m(h)g (is)h(to)f(facilitate)h(dev)m(elopmen)m(t)h(of)e(reli-)60 4104 y(able)g(soft)m(w)m(are)i(pac)m(k)-5 b(ages)37 b(and)f(pro)m(vide) h(a)f(set)h(of)f(to)s(ols)g(to)g(analyse)h(and)f(rep)s(ort)g(the)60 4225 y(soft)m(w)m(are)27 b(qualit)m(y)g(status.)42 b(The)27 b(presen)m(ted)h(framew)m(ork)f(is)g(completely)h(implemen)m(ted)60 4345 y(within)i(R)f(and)g(do)s(es)h(not)f(rely)h(on)g(external)g(to)s (ols)e(or)h(other)h(language)f(systems.)44 b(The)60 4465 y(basic)36 b(principle)g(is)g(that)f(ev)m(ery)i(function)e(or)g(metho)s (d)h(is)f(accompanied)h(with)g(a)f(test)60 4586 y(case)h(that)e (queries)j(man)m(y)e(calling)g(situations)g(including)g(incorrect)h(in) m(v)m(o)s(cations.)51 b(A)60 4706 y(test)34 b(case)h(can)f(b)s(e)g (executed)i(instan)m(tly)f(without)f(reinstalling)g(the)g(whole)g(pac)m (k)-5 b(age)34 b(-)60 4826 y(a)e(feature)h(that)f(is)g(necessary)j(for) d(parallel)g(dev)m(elopmen)m(t)i(of)e(functionalit)m(y)h(and)f(test)60 4947 y(cases.)46 b(On)33 b(a)g(second)h(lev)m(el)h(one)e(or)g(more)g (pac)m(k)-5 b(ages)34 b(can)f(b)s(e)h(tested)g(in)f(a)g(single)g(test) 60 5067 y(run,)39 b(the)e(result)h(of)f(whic)m(h)i(is)f(rep)s(orted)f (in)h(an)f(w)m(ell)i(structured)f(test)g(proto)s(col.)57 b(T)-8 b(o)1655 5358 y(1)p eop end %%Page: 2 2 TeXDict begin 2 1 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.2) cvn /DEST pdfmark end 52 158 a 60 293 a Ff(v)m(erify)38 b(the)g(co)m(v)m(erage)g(of)f(the)g(test)h(framew)m(ork)g(a)f(co)s(de)g (insp)s(ector)h(is)f(pro)m(vided)h(that)60 414 y(monitors)e(the)h(co)s (de)g(co)m(v)m(erage)h(of)e(executed)i(test)f(cases.)57 b(The)37 b(result)g(of)f(individual)60 534 y(test)g(in)m(v)m(o)s (cations)g(as)g(w)m(ell)h(as)e(pac)m(k)-5 b(age)36 b(wide)g(ev)-5 b(aluations)36 b(can)g(b)s(e)f(compiled)i(in)m(to)e(a)60 654 y(summary)g(rep)s(ort)f(exp)s(orted)h(to)f(HTML.)h(This)g(rep)s (ort)f(details)h(the)g(executed)h(tests,)60 775 y(their)45 b(failure)g(or)g(success,)51 b(as)45 b(w)m(ell)h(as)f(the)h(co)s(de)f (co)m(v)m(erage.)82 b(T)-8 b(aking)46 b(it)f(one)g(step)60 895 y(further)29 b(and)h(com)m(bining)g(the)g(build)g(system)h(with)f (a)f(dev)m(elopmen)m(t)j(and)d(release)i(pro-)60 1016 y(cedure)26 b(with)g(de\014ned)h(co)s(de)e(status)h(description)g(this) g(approac)m(h)f(op)s(ens)h(the)g(w)m(a)m(y)g(for)f(a)60 1136 y(principled)34 b(soft)m(w)m(are)h(qualit)m(y)f(monitoring)f(and)g (risk)h(assessmen)m(t)j(of)c(the)g(dev)m(elop)s(ed)60 1256 y(application.)41 b(F)-8 b(or)28 b(our)g(co)s(de)g(dev)m(elopmen)m (t)i(w)m(e)g(ha)m(v)m(e)f(utilised)g(the)g(describ)s(ed)g(system)60 1377 y(with)e(great)f(b)s(ene\014t)h(w.r.t.)g(co)s(de)g(reliabilit)m(y) h(and)e(main)m(tenance)i(e\013orts)f(in)g(a)f(medium)60 1497 y(sized)34 b(dev)m(elopmen)m(t)g(team.)60 1666 y SDict begin H.S end 60 1666 a 60 1666 a SDict begin 14.5 H.A end 60 1666 a 60 1666 a SDict begin [/View [/XYZ H.V]/Dest (section.1) cvn /DEST pdfmark end 60 1666 a 163 x Fh(1)161 b(In)l(tro)t(duction)60 2048 y Ff(The)36 b(imp)s(ortance)f (of)g(soft)m(w)m(are)h(testing)f(can)g(hardly)h(b)s(e)f(o)m(v)m (errated.)52 b(This)36 b(is)g(all)f(the)60 2169 y(more)42 b(true)g(for)g(in)m(terpreted)h(languages)f(where)h(not)f(ev)m(en)h(a)f (compiler)h(c)m(hec)m(ks)i(the)60 2289 y(basic)33 b(consistency)h(of)d (a)h(program.)42 b(Nonetheless,)34 b(testing)e(is)g(often)g(p)s(erceiv) m(ed)i(more)60 2409 y(as)28 b(a)f(burden)h(than)f(a)h(help)g(b)m(y)g (the)g(programmer.)41 b(Therefore)29 b(it)e(is)h(necessary)i(to)d(pro-) 60 2530 y(vide)i(to)s(ols)f(that)g(mak)m(e)i(the)e(task)h(of)f(testing) h(as)f(simple)i(and)e(systematic)i(as)f(p)s(ossible.)60 2650 y(The)k(k)m(ey)g(goal)e(of)g(suc)m(h)i(a)f(testing)g(framew)m(ork) h(should)f(b)s(e)g(to)f(promote)h(the)g(creation)60 2771 y(and)f(execution)i(of)e(test)h(cases)h(to)e(b)s(ecome)i(an)e(in)m (tegral)h(part)f(of)g(the)h(soft)m(w)m(are)g(dev)m(el-)60 2891 y(opmen)m(t)h(pro)s(cess.)44 b(Exp)s(erience)35 b(sho)m(ws)f(that)e(suc)m(h)h(a)f(p)s(ermanen)m(tly)i(rep)s(eated)f(co) s(de)f(-)60 3011 y(test)d(-)e(simplify)i(cycle)g(leads)g(to)f(faster)g (and)f(more)i(successful)h(soft)m(w)m(are)f(dev)m(elopmen)m(t)60 3132 y(than)i(the)h(usually)g(futile)g(attempt)f(to)g(add)h(test)g (cases)h(once)f(the)g(soft)m(w)m(are)g(is)g(largely)60 3252 y(\014nished.)44 b(This)31 b(line)g(of)f(though)m(t)g(has)h(b)s (een)g(pushed)h(furthest)f(b)m(y)g(the)g(Extreme)g(Pro-)60 3373 y(gramming)39 b([)554 3373 y SDict begin H.S end 554 3373 a Ff(1)603 3307 y SDict begin H.R end 603 3307 a 603 3373 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.xp) cvn H.B /ANN pdfmark end 603 3373 a Ff(])g(and)h(T)-8 b(est-First)39 b(paradigms)h(where)g(test)g(cases)h(are)e(view)m(ed)j (as)e(the)60 3493 y(essen)m(tial)f(guidelines)g(for)e(the)h(dev)m (elopmen)m(t)i(pro)s(cess.)59 b(These)39 b(considerations)g(lead)60 3613 y(to)32 b(v)-5 b(arious)32 b(requiremen)m(ts)j(that)d(a)g(useful)h (testing)g(framew)m(ork)g(should)g(satisfy:)206 3816 y Fe(\210)49 b Ff(T)-8 b(ests)34 b(should)f(b)s(e)f(easy)i(to)e (execute.)206 4019 y Fe(\210)49 b Ff(The)25 b(results)h(should)e(b)s(e) h(accessible)h(through)e(a)g(w)m(ell)i(structured)f(test)g(proto)s (col.)206 4222 y Fe(\210)49 b Ff(It)39 b(should)h(b)s(e)f(p)s(ossible)h (to)f(execute)i(only)e(small)h(p)s(ortions)f(of)f(the)i(test)g(cases) 304 4342 y(during)32 b(the)h(dev)m(elopmen)m(t)i(pro)s(cess.)206 4545 y Fe(\210)49 b Ff(It)29 b(should)g(b)s(e)g(p)s(ossible)h(to)e (estimate)i(the)f(amoun)m(t)g(of)f(co)s(de)h(that)f(is)i(co)m(v)m(ered) g(b)m(y)304 4665 y(some)j(test)g(case.)206 4868 y(T)-8 b(esting)30 b(framew)m(orks)h(that)e(address)h(these)g(asp)s(ects)g(ha) m(v)m(e)h(b)s(een)f(written)f(in)h(a)f(v)-5 b(a-)60 4988 y(riet)m(y)34 b(of)f(languages)g(suc)m(h)i(as)e(Smalltalk,)h(Ja)m(v)-5 b(a,)33 b(C++)g(and)h(Python.)46 b(In)33 b(particular,)60 5108 y(the)39 b(approac)m(h)f(describ)s(ed)i(in)e([)1242 5108 y SDict begin H.S end 1242 5108 a Ff(2)1291 5043 y SDict begin H.R end 1291 5043 a 1291 5108 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.beck) cvn H.B /ANN pdfmark end 1291 5108 a Ff(])g(has)h(turned)g(out)f(to)g(b)s(e)g(v)m(ery)i (successful,)i(leading)1655 5358 y(2)p eop end %%Page: 3 3 TeXDict begin 3 2 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.3) cvn /DEST pdfmark end 52 158 a 60 293 a Ff({)35 b(among)h(others)g({) f(to)h(the)g(p)s(opular)f(JUnit)h(library)f(for)g(Ja)m(v)-5 b(a)36 b([)2502 293 y SDict begin H.S end 2502 293 a Ff(3)2551 228 y SDict begin H.R end 2551 228 a 2551 293 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.junit) cvn H.B /ANN pdfmark end 2551 293 a Ff(],)g(whic)m(h)h(has)f(b)s(een)60 414 y(p)s(orted)28 b(to)f(man)m(y)i(other)f(languages)g(\(see)h([)1650 414 y SDict begin H.S end 1650 414 a Ff(1)1698 349 y SDict begin H.R end 1698 349 a 1698 414 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.xp) cvn H.B /ANN pdfmark end 1698 414 a Ff(])g(for)e(an)h(extensiv)m(e)i(list)f(of)e(testing)h (frame-)60 534 y(w)m(orks)34 b(for)d(all)h(kinds)i(of)e(languages\).)42 b(Accordingly)-8 b(,)33 b(the)g(R)m(Unit)f(pac)m(k)-5 b(age)33 b(\(a)m(v)-5 b(ailable)60 654 y(at)44 b(sourceforge)g([)736 654 y SDict begin H.S end 736 654 a Ff(5)785 589 y SDict begin H.R end 785 589 a 785 654 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.runit-sf) cvn H.B /ANN pdfmark end 785 654 a Ff(]\))g(is)g(our)g(v)m(ersion)i(of)d(p)s(orting)h(JUnit)g(to)g (R,)g(supplemen)m(ted)i(b)m(y)60 775 y(additional)34 b(functionalit)m(y)h(to)g(insp)s(ect)h(the)f(test)g(co)m(v)m(erage)h (of)f(some)g(function)g(under)60 895 y(question.)206 1016 y(One)f(ma)m(y)f(w)m(onder)h(wh)m(y)h(R)e(w)m(ould)g(need)h(y)m (et)g(another)f(testing)h(framew)m(ork)f(ev)m(en)60 1136 y(though)e(the)h(standard)g(metho)s(d,)g(namely)g(executing)h Fd(R)i(CMD)e(che)-5 b(ck)31 b Ff(on)h(ones)g(com-)60 1256 y(plete)e(pac)m(k)-5 b(age)29 b(at)g(the)g(shell)h(prompt,)g(is)g (widely)g(accepted)g(and)f(applied.)43 b(W)-8 b(e)29 b(think,)60 1377 y(ho)m(w)m(ev)m(er,)41 b(that)c(the)h(R)m(Unit)f (approac)m(h)h(is)g(more)g(in)f(line)h(with)g(the)g(ab)s(o)m(v)m(e)g (listed)g(re-)60 1497 y(quiremen)m(ts)33 b(and)d(can)h(b)s(e)g(seen)h (as)f(a)f(complemen)m(t)i(to)e(the)h(existing)h(pro)s(cess)g(in)e (that:)206 1700 y Fe(\210)49 b Ff(test)33 b(cases)h(are)e(called)h(and) f(executed)j(from)d(the)g(R)h(prompt)206 1904 y Fe(\210)49 b Ff(the)26 b(programmer)g(decides)h(whic)m(h)h(result)e(or)g (functionalit)m(y)g(to)f(put)h(under)h(test-)304 2024 y(ing,)32 b(e.g.)h(formating)e(issues)j(of)e(textual)h(output)f(do)h (not)f(need)h(to)f(matter)206 2228 y Fe(\210)49 b Ff(test)31 b(and)f(reference)i(data)e(\014les)h(need)h(not)e(b)s(e)g(main)m (tained)h(separately)g(but)g(are)304 2348 y(com)m(bined)j(in)m(to)e (one)h(\014le)206 2551 y Fe(\210)49 b Ff(test)37 b(cases)h(need)f(not)f (b)s(e)g(limited)h(to)f(testing/using)h(functionalit)m(y)g(from)f(one) 304 2672 y(pac)m(k)-5 b(age)33 b(c)m(hec)m(k)m(ed)i(at)d(a)g(time)60 2875 y(Moreo)m(v)m(er,)48 b(testing)43 b(framew)m(orks)i(based)f(on)g (JUnit)f(p)s(orts)g(seem)i(to)e(ha)m(v)m(e)i(b)s(ecome)60 2996 y(a)33 b(quasi)h(standard)g(in)f(man)m(y)i(programming)d (languages.)46 b(Therefore,)35 b(programmers)60 3116 y(new)23 b(to)f(R)g(but)g(familiar)g(with)h(other)f(languages)g(migh)m (t)g(appreciate)h(a)f(familiar)g(testing)60 3236 y(en)m(vironmen)m(t.) 42 b(And)24 b(\014nally)-8 b(,)25 b(o\013ering)e(more)h(than)f(one)h (alternativ)m(e)g(in)g(the)f(imp)s(ortan)m(t)60 3357 y(\014eld)33 b(of)f(co)s(de)h(testing)f(is)h(certainly)g(not)g(a)f(bad) g(idea)h(and)f(could)h(turn)f(out)g(useful.)206 3477 y(Before)48 b(explaining)h(the)f(comp)s(onen)m(ts)h(of)e(the)h(R)m (Unit)g(pac)m(k)-5 b(age)48 b(in)g(detail,)k(w)m(e)60 3597 y(w)m(ould)30 b(lik)m(e)h(to)e(list)h(some)h(of)e(the)h(lessons)h (learned)f(in)g(the)g(attempt)f(of)g(writing)h(useful)60 3718 y(test)36 b(suites)h(for)e(our)g(soft)m(w)m(are)h(\(a)f(more)h (complete)g(collection)g(of)f(tips)h(relating)f(to)g(a)60 3838 y(T)-8 b(est-First)33 b(dev)m(elopmen)m(t)h(approac)m(h)f(can)f(b) s(e)h(found)f(in)h([)2222 3838 y SDict begin H.S end 2222 3838 a Ff(4)2270 3773 y SDict begin H.R end 2270 3773 a 2270 3838 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.tfg) cvn H.B /ANN pdfmark end 2270 3838 a Ff(]\):)206 4042 y Fe(\210)49 b Ff(Dev)m(elop)40 b(test)h(cases)g(parallel)f(to)f (implemen)m(ting)i(y)m(our)g(functionalit)m(y)-8 b(.)65 b(Keep)304 4162 y(testing)42 b(all)g(the)g(time)g(\(co)s(de)g(-)g(test) g(-)g(simplify)h(cycle\).)73 b(Do)41 b(not)g(w)m(ait)i(un)m(til)304 4282 y(the)29 b(soft)m(w)m(are)g(is)g(complete)h(and)e(attempt)h(to)f (add)g(test)h(cases)h(at)f(the)f(v)m(ery)i(end.)304 4403 y(This)j(t)m(ypically)h(leads)f(to)f(p)s(o)s(or)f(qualit)m(y)j(and)e (incomplete)h(test)g(cases.)206 4606 y Fe(\210)49 b Ff(Distinguish)41 b(b)s(et)m(w)m(een)i(unit)e(and)g(in)m(tegration)g(tests:)61 b(Unit)41 b(tests)h(should)g(b)s(e)304 4727 y(as)31 b(small)h(as)f(p)s (ossible)h(and)g(c)m(hec)m(k)h(one)e(unit)h(of)e(functionalit)m(y)i (that)f(cannot)g(b)s(e)304 4847 y(further)f(decomp)s(osed.)44 b(In)m(tegration)30 b(tests,)i(on)e(the)h(other)f(hand,)h(run)f (through)304 4967 y(a)36 b(whole)h(analysis)g(w)m(ork\015o)m(w)h(and)e (c)m(hec)m(k)j(the)d(in)m(terpla)m(y)i(of)e(v)-5 b(arious)36 b(soft)m(w)m(are)304 5088 y(comp)s(onen)m(ts.)1655 5358 y(3)p eop end %%Page: 4 4 TeXDict begin 4 3 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.4) cvn /DEST pdfmark end 52 158 a 206 293 a Fe(\210)49 b Ff(Go)s(o)s(d)22 b(test)i(co)m(v)m(erage)g(enables)h(refactoring,)g (b)m(y)f(whic)m(h)h(a)e(reorganisation)g(of)g(the)304 414 y(implemen)m(tation)k(is)f(mean)m(t.)42 b(Without)26 b(regular)g(testing)g(the)g(attitude)g Fd(`I)j(b)-5 b(etter)304 534 y(do)40 b(not)h(touch)g(this)f(c)-5 b(o)g(de)40 b(anymor)-5 b(e`)38 b Ff(once)i(some)f(piece)h(of)e(soft)m(w)m(are)i(app)s(ears)304 654 y(to)34 b(b)s(e)i(w)m(orking)f(is)g(frequen)m(tly)i(encoun)m (tered.)52 b(It)35 b(is)g(v)m(ery)i(pleasing)e(and)g(time-)304 775 y(sa)m(ving)29 b(just)g(to)e(run)i(a)f(test)h(suite)g(after)f(some) h(impro)m(v)m(emen)m(t)h(or)e(simpli\014cation)304 895 y(of)44 b(the)h(implemen)m(tation)g(to)f(see)h(that)f(all)h(test)g (cases)g(are)g(still)f(passing)h(\(or)304 1016 y(p)s(ossibly)31 b(rev)m(eal)h(some)f(newly)g(in)m(tro)s(duced)g(bug\).)43 b(This)31 b(refactoring)f(abilit)m(y)g(is)304 1136 y(a)g(k)m(ey)h(b)s (ene\014t)g(of)e(unit)h(testing)h(leading)f(not)f(only)i(to)e(b)s (etter)h(soft)m(w)m(are)h(qualit)m(y)304 1256 y(but)h(also)h(to)f(b)s (etter)g(design.)206 1460 y Fe(\210)49 b Ff(Do)29 b(not)h(test)h(in)m (ternal)g(functions)g(but)f(just)h(the)f(public)h(in)m(terface)g(of)f (a)g(library)-8 b(.)304 1580 y(Since)34 b(R)e(do)s(es)h(not)g(pro)m (vide)g(v)m(ery)h(m)m(uc)m(h)g(language)f(supp)s(ort)f(for)g(this)i (distinc-)304 1700 y(tion,)41 b(the)e(\014rst)h(step)g(here)g(is)g(to)f (clarify)g(whic)m(h)i(functions)f(are)f(mean)m(t)h(to)f(b)s(e)304 1821 y(called)32 b(b)m(y)g(a)e(user)i(of)f(a)g(pac)m(k)-5 b(age)31 b(and)g(whic)m(h)i(are)e(not)g(\(namespaces)i(in)e(R)g(pro-) 304 1941 y(vide)46 b(a)f(useful)h(directiv)m(e)h(for)d(making)h(this)h (distinction,)j(if)c(the)g(exp)s(ort)h(list)304 2062 y(is)33 b(selected)i(carefully)f(and)e(main)m(tained\).)45 b(If)33 b(in)m(ternal)h(functions)f(are)g(directly)304 2182 y(tested,)c(the)d(abilit)m(y)h(of)f(refactoring)g(gets)h(lost)f(b) s(ecause)i(this)f(t)m(ypically)h(in)m(v)m(olv)m(es)304 2302 y(reorganisation)j(of)h(the)h(in)m(ternal)g(part)f(of)g(a)g (library)-8 b(.)206 2506 y Fe(\210)49 b Ff(Once)33 b(a)f(bug)h(has)f(b) s(een)h(found,)g(add)f(a)g(corresp)s(onding)h(test)g(case.)206 2709 y Fe(\210)49 b Ff(W)-8 b(e)37 b(greatly)f(b)s(ene\014tted)i(from)e (an)g(automated)g(test)h(system:)53 b(A)37 b(shell)g(script,)304 2830 y(running)43 b(nigh)m(tly)-8 b(,)47 b(c)m(hec)m(ks)f(out)d(and)h (installs)g(all)f(relev)-5 b(an)m(t)44 b(pac)m(k)-5 b(ages.)77 b(After)304 2950 y(that)45 b(all)g(test)h(suites)h(are)f(run)f(and)h (the)g(resulting)g(test)g(proto)s(col)e(is)j(stored)304 3070 y(in)h(a)f(cen)m(tral)h(lo)s(cation.)88 b(This)48 b(pro)m(vides)h(an)f(excellen)m(t)h(o)m(v)m(erview)h(o)m(v)m(er)f(the) 304 3191 y(curren)m(t)29 b(status)g(of)f(the)h(system)i(and)d(the)h (collection)g(of)f(nigh)m(tly)h(test)g(proto)s(cols)304 3311 y(do)s(cumen)m(ts)34 b(the)e(dev)m(elopmen)m(t)j(progress.)60 3480 y SDict begin H.S end 60 3480 a 60 3480 a SDict begin 14.5 H.A end 60 3480 a 60 3480 a SDict begin [/View [/XYZ H.V]/Dest (section.2) cvn /DEST pdfmark end 60 3480 a 164 x Fh(2)161 b(The)53 b(R)l(Unit)g(pac)l(k)-9 b(age)60 3863 y Ff(This)29 b(section)g(con)m(tains)f(a)g(detailed)g(explanation) g(of)f(the)i(R)m(Unit)f(pac)m(k)-5 b(age)28 b(and)g(exam-)60 3983 y(ples)k(ho)m(w)g(to)f(use)i(it.)43 b(As)32 b(has)f(already)h(b)s (een)g(men)m(tioned)h(the)e(pac)m(k)-5 b(age)32 b(con)m(tains)g(t)m(w)m (o)60 4103 y(indep)s(enden)m(t)27 b(comp)s(onen)m(ts:)40 b(a)25 b(framew)m(ork)h(for)f(test)g(case)i(execution)f(and)f(a)g(to)s (ol)f(that)60 4224 y(allo)m(ws)36 b(to)f(insp)s(ect)i(the)f(\015o)m(w)g (of)f(execution)i(inside)f(a)f(function)h(in)g(order)f(to)g(analyse)60 4344 y(whic)m(h)f(p)s(ortions)f(of)f(co)s(de)i(are)f(co)m(v)m(ered)h(b) m(y)g(some)g(test)f(case.)46 b(Both)33 b(comp)s(onen)m(ts)h(are)60 4464 y(no)m(w)f(discussed)i(in)d(turn.)60 4604 y SDict begin H.S end 60 4604 a 60 4604 a SDict begin 14.5 H.A end 60 4604 a 60 4604 a SDict begin [/View [/XYZ H.V]/Dest (subsection.2.1) cvn /DEST pdfmark end 60 4604 a 149 x Fc(2.1)135 b(T)-11 b(est)45 b(case)g(execution)60 4938 y Ff(The)31 b(basic)g(idea)f(of)f(this)i(comp)s(onen)m(t)f(is)h(to)e(execute)j(a)e (set)g(of)g(test)g(functions)h(de\014ned)60 5058 y(through)41 b(naming)f(con)m(v)m(en)m(tions,)46 b(store)41 b(whether)h(or)f(not)g (the)g(test)g(succeeded)j(in)d(a)1655 5358 y(4)p eop end %%Page: 5 5 TeXDict begin 5 4 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.5) cvn /DEST pdfmark end 52 158 a 60 293 a Ff(cen)m(tral)30 b(logger)f(ob)5 b(ject)29 b(and)h(\014nally)f(write)h(a)f(test)h(proto) s(col)e(that)h(allo)m(ws)h(to)f(precisely)60 414 y(iden)m(tify)k(the)g (problems.)206 534 y Fg(Note,)h(that)g(R)m(Unit)f(-)i(b)m(y)f(default)g (-)h(sets)f(the)f(v)m(ersion)i(for)e(normal,)j(and)60 654 y(all)25 b(other)g(RNGs)f(to)h('Kinderman-Ramage',)30 b(and)25 b('Marsaglia-Multicarry',)60 775 y(resp)s(ectiv)m(ely)-9 b(.)79 b(If)48 b(y)m(ou)f(lik)m(e)h(to)e(c)m(hange)i(these)g(defaults)g (please)g(see)g Fb(?de-)60 895 y(fineTestSuite)40 b Fg(for)d(argumen)m (t)h('rngNormalKind')g(and)g('rngKind'.)206 1016 y Ff(As)26 b(an)f(example)h(consider)g(a)e(function)h(that)g(con)m(v)m(erts)i(cen) m(tigrade)e(to)g(F)-8 b(ahrenheit:)60 1208 y Fa(c2f)53 b(<-)f(function\(c\))j(return\(9/5)f(*)f(c)f(+)g(32\))60 1401 y Ff(A)33 b(corresp)s(onding)f(test)h(function)g(could)f(lo)s(ok)g (lik)m(e)i(this:)60 1593 y Fa(test.c2f)54 b(<-)e(function\(\))j({)164 1714 y(checkEquals\(c2f\(0\),)h(32\))164 1834 y (checkEquals\(c2f\(10\),)h(50\))164 1954 y (checkException\(c2f\("xx"\)\))60 2075 y(})60 2267 y Ff(The)44 b(default)f(naming)f(con)m(v)m(en)m(tion)j(for)d(test)i (functions)f(in)g(the)g(R)m(Unit)g(pac)m(k)-5 b(age)43 b(is)60 2388 y Fb(test...)76 b Ff(as)43 b(is)h(standard)e(in)h(JUnit.) 75 b(T)-8 b(o)43 b(p)s(erform)g(the)g(actual)g(c)m(hec)m(ks)i(that)e (the)60 2508 y(function)i(to)f(b)s(e)h(tested)h(w)m(orks)g(correctly)g (a)e(set)i(of)e(functions)i(called)f Fb(check)52 b(...)60 2629 y Ff(is)41 b(pro)m(vided.)69 b(The)41 b(purp)s(ose)g(of)f(these)i Fb(check)f Ff(functions)g(is)g(t)m(w)m(o-fold:)60 b(they)41 b(mak)m(e)60 2749 y(sure)49 b(that)e(a)g(p)s(ossible)i(failure)e(is)i (rep)s(orted)e(to)h(the)g(cen)m(tral)g(test)g(logger)f(so)h(that)60 2869 y(it)40 b(will)g(app)s(ear)g(prop)s(erly)g(in)g(the)g(\014nal)g (test)h(proto)s(col)e(and)h(they)g(are)g(supp)s(osed)h(to)60 2990 y(mak)m(e)34 b(explicit)f(the)g(actual)g(c)m(hec)m(ks)i(in)e(a)f (test)i(case)f(as)g(opp)s(osed)g(to)f(other)h(co)s(de)g(used)60 3110 y(to)41 b(set)h(up)f(the)h(test)g(scenario.)70 b(Note)41 b(that)g Fb(checkException)j Ff(fails)d(if)g(the)h(passed)60 3231 y(expression)g(do)s(es)e(not)g(generate)g(an)g(error.)66 b(This)41 b(kind)g(of)e(test)i(is)f(useful)h(to)f(mak)m(e)60 3351 y(sure)g(that)e(a)h(function)g(correctly)h(recognises)g(error)f (situations)g(instead)h(of)e(silen)m(tly)60 3471 y(creating)e (inappropriate)g(results.)56 b(These)39 b(c)m(hec)m(k)f(functions)f (are)f(direct)h(equiv)-5 b(alen)m(ts)60 3592 y(to)35 b(the)i(v)-5 b(arious)35 b Fb(assert)j Ff(functions)e(of)f(the)h(JUnit) h(framew)m(ork.)54 b(More)36 b(information)60 3712 y(can)d(b)s(e)f (found)h(in)f(the)h(online)g(help.)206 3832 y(Before)25 b(running)g(the)g(test)h(function)f(it)g(is)g(necessary)i(to)d(create)i (a)e(test)i(suite)g(whic)m(h)60 3953 y(is)31 b(a)f(collection)h(of)f (test)i(functions)f(and)f(\014les)i(relating)e(to)g(one)h(topic.)42 b(One)31 b(could,)h(for)60 4073 y(instance,)39 b(create)f(one)f(test)h (suite)f(for)g(one)g(R)g(pac)m(k)-5 b(age.)57 b(A)37 b(test)h(suite)g(is)f(just)h(a)f(list)60 4194 y(con)m(taining)e(a)f (name,)h(an)g(arra)m(y)f(of)g(absolute)h(directories)h(con)m(taining)e (the)h(lo)s(cations)60 4314 y(of)i(the)g(test)h(\014les,)h(a)d(regular) h(expression)i(iden)m(tifying)f(the)f(test)h(\014les)g(and)e(a)h (regular)60 4434 y(expression)26 b(iden)m(tifying)g(the)f(test)g (functions.)41 b(In)25 b(our)f(example)i(assume)g(that)e(the)h(test)60 4555 y(function)41 b(is)g(lo)s(cated)f(in)h(a)f(\014le)h Fb(runitc2f.r)i Ff(lo)s(cated)d(in)h(a)f(directory)h Fb(/foo/bar/)p Ff(.)60 4675 y(T)-8 b(o)33 b(create)f(the)h(corresp)s (onding)g(test)g(suite)g(w)m(e)h(can)e(use)i(a)e(help)s(er)h(function:) 60 4868 y Fa(testsuite.c2f)55 b(<-)d(defineTestSuite\("c2f",)947 4988 y(dirs)h(=)g(file.path\(.path.package\(package=)q("RUni)q(t"\),) 1522 5108 y("examples"\),)1655 5358 y Ff(5)p eop end %%Page: 6 6 TeXDict begin 6 5 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.6) cvn /DEST pdfmark end 52 158 a 947 293 a Fa(testFileRegexp)56 b(=)c("^runit.+\\\\.r",)947 414 y(testFuncRegexp)k(=)c("^test.+",)947 534 y(rngKind)i(=)f("Marsaglia-Multicarry",)947 654 y(rngNormalKind)i (=)e("Kinderman-Ramage"\))60 841 y Ff(All)33 b(that)f(remains)h(is)g (to)f(run)g(the)h(test)g(suite)g(and)g(prin)m(t)f(the)h(test)g(proto)s (col:)60 1028 y Fa(testResult)54 b(<-)f(runTestSuite\(testsuite.c2f\)) 60 1149 y(printTextProtocol\(testResult\))60 1336 y Ff(The)26 b(resulting)g(test)g(proto)s(col)e(should)i(b)s(e)g(self)g(explanatory) f(and)h(can)f(also)h(b)s(e)f(prin)m(ted)60 1456 y(as)31 b(HTML)g(v)m(ersion.)44 b(See)31 b(the)g(online)g(help)g(for)f(further) h(information.)42 b(Note)30 b(that)h(for)60 1576 y(executing)h(just)e (one)h(test)g(\014le)g(there)g(is)g(also)f(a)h(shortcut)f(in)h(order)f (to)h(mak)m(e)g(test)g(case)60 1697 y(execution)j(as)e(easy)i(as)e(p)s (ossible:)60 1884 y Fa(runTestFile\(file.path\(.path.pack)q(age\(p)q (ackag)q(e="RU)q(nit")q(\),)686 2004 y("examples/runitc2f.r"\)\))206 2191 y Ff(The)k(creation)f(and)g(execution)h(of)f(test)h(suites)g(can)f (b)s(e)g(summarised)i(b)m(y)f(the)f(fol-)60 2311 y(lo)m(wing)e(recip)s (e:)60 2359 y SDict begin H.S end 60 2359 a 60 2359 a SDict begin 14.5 H.A end 60 2359 a 60 2359 a SDict begin [/View [/XYZ H.V]/Dest (Item.1) cvn /DEST pdfmark end 60 2359 a 179 2498 a Ff(1.)49 b(create)33 b(as)f(man)m(y)i(test)f (functions)g(in)f(as)h(man)m(y)g(test)g(\014les)g(as)g(necessary)60 2556 y SDict begin H.S end 60 2556 a 60 2556 a SDict begin 14.5 H.A end 60 2556 a 60 2556 a SDict begin [/View [/XYZ H.V]/Dest (Item.2) cvn /DEST pdfmark end 60 2556 a 179 2696 a Ff(2.)49 b(create)37 b(one)g(or)f(more)h(test)g(suites)h (using)f(the)g(help)s(er)g(function)g Fb(defineTest-)304 2817 y(Suite)60 2855 y SDict begin H.S end 60 2855 a 60 2855 a SDict begin 14.5 H.A end 60 2855 a 60 2855 a SDict begin [/View [/XYZ H.V]/Dest (Item.3) cvn /DEST pdfmark end 60 2855 a 179 3015 a Ff(3.)49 b(run)32 b(the)h(test)g(suites) h(with)f Fb(runTestSuite)60 3053 y SDict begin H.S end 60 3053 a 60 3053 a SDict begin 14.5 H.A end 60 3053 a 60 3053 a SDict begin [/View [/XYZ H.V]/Dest (Item.4) cvn /DEST pdfmark end 60 3053 a 179 3212 a Ff(4.)49 b(prin)m(t)29 b(the)g(test)g(proto)s(col)e(either)i(with)g Fb(printTextProtocol)j Ff(or)d(with)g Fb(print-)304 3333 y(HTMLProtocol)35 b Ff(\(or)d(with)h(a)f(generic)h(metho)s(d)f(lik)m(e)i Fb(print)f Ff(or)g Fb(summary)p Ff(\))206 3520 y(W)-8 b(e)31 b(conclude)h(this)f(section)g(with)g(some)h(further)e(commen)m (ts)i(on)e(v)-5 b(arious)31 b(asp)s(ects)60 3640 y(of)h(the)h(test)g (execution)g(framew)m(ork:)206 3827 y Fe(\210)49 b Ff(A)39 b(test)h(\014le)f(can)h(con)m(tain)f(an)g(arbitrary)g(n)m(um)m(b)s(er)h (of)f(test)g(functions.)64 b(A)39 b(test)304 3948 y(directory)47 b(can)g(con)m(tain)f(an)h(arbitrary)f(n)m(um)m(b)s(er)h(of)g(test)g (\014les,)k(a)46 b(test)h(suite)304 4068 y(can)30 b(con)m(tain)f(an)h (arbitrary)e(n)m(um)m(b)s(er)j(of)e(test)h(directories)g(and)g(the)f (test)i(runner)304 4188 y(can)40 b(run)f(an)h(arbitrary)f(n)m(um)m(b)s (er)i(of)e(test)h(suites)h({)e(all)h(resulting)g(in)g(one)f(test)304 4309 y(proto)s(col.)g(The)25 b(test)g(function)f(and)g(\014le)g(names)h (of)f(a)g(test)g(suite)h(m)m(ust,)i(ho)m(w)m(ev)m(er,)304 4429 y(ob)s(ey)33 b(a)f(naming)g(con)m(v)m(en)m(tion)i(expressible)h (through)d(regular)h(expressions.)45 b(As)304 4549 y(default)32 b(test)h(functions)g(start)f(with)h Fb(test)h Ff(and)e(\014les)h(with)g Fb(runit)p Ff(.)206 4747 y Fe(\210)49 b Ff(R)m(Unit)35 b(mak)m(es)h(a)f(distinction)g(b)s(et)m(w)m(een)i(failure)d(and)h (error.)50 b(A)35 b(failure)f(o)s(ccurs)304 4868 y(if)48 b(one)g(of)g(the)h(c)m(hec)m(k)h(functions)f(fail)e(\(e.g.)h Fb(checkTrue\(FALSE\))k Ff(creates)d(a)304 4988 y(failure\).)41 b(An)29 b(error)g(is)g(rep)s(orted)f(if)g(an)h(ordinary)f(R)g(error)h (\(usually)g(created)g(b)m(y)304 5108 y Fb(stop)p Ff(\))k(o)s(ccurs.) 1655 5358 y(6)p eop end %%Page: 7 7 TeXDict begin 7 6 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.7) cvn /DEST pdfmark end 52 158 a 206 293 a Fe(\210)49 b Ff(Since)32 b(v)m(ersion)h(0.4.0)e(there)h(is)g(a)g(function)f Fb(DEACTIVATED)j Ff(whic)m(h)f(can)f(b)s(e)g(used)304 414 y(to)k(deactiv)-5 b(ate)36 b(test)h(cases)h(temp)s(orarily)-8 b(.)54 b(This)37 b(migh)m(t)g(b)s(e)f(useful)h(in)f(the)h(case)304 534 y(of)44 b(a)f(ma)5 b(jor)44 b(refactoring.)78 b(In)44 b(particular,)j(the)d(deactiv)-5 b(ated)45 b(test)f(cases)i(are)304 654 y(rep)s(orted)32 b(in)h(the)g(test)g(proto)s(col)e(so)i(that)f (they)h(cannot)f(fall)g(in)m(to)h(oblivion.)206 858 y Fe(\210)49 b Ff(The)30 b(test)f(runner)h(tries)g(hard)e(to)h(lea)m(v)m (e)i(a)d(clean)i(R)f(session)i(b)s(ehind.)42 b(Therefore)304 978 y(all)26 b(ob)5 b(jects)27 b(created)f(during)g(test)h(case)g (execution)g(will)g(b)s(e)f(deleted)h(after)f(a)f(test)304 1099 y(\014le)33 b(has)g(b)s(een)g(pro)s(cessed.)206 1302 y Fe(\210)49 b Ff(In)33 b(order)g(to)g(prev)m(en)m(t)i(m)m (ysterious)g(errors)e(the)h(random)f(n)m(um)m(b)s(er)h(generator)e(is) 304 1422 y(reset)40 b(to)f(a)g(standard)g(setting)h(b)s(efore)f (sourcing)h(a)f(test)h(\014le.)64 b(If)39 b(a)g(particular)304 1543 y(setting)32 b(is)g(needed)h(to)e(generate)h(repro)s(ducible)g (results)h(it)e(is)h(\014ne)g(to)g(con\014gure)304 1663 y(the)47 b(random)f(n)m(um)m(b)s(er)h(generator)f(at)g(the)h(b)s (eginning)f(of)g(a)g(test)h(\014le.)86 b(This)304 1783 y(setting)28 b(applies)h(during)e(the)i(execution)g(of)e(all)h(test)g (functions)g(of)g(that)f(test)h(\014le)304 1904 y(but)k(is)h(reset)h(b) s(efore)e(the)h(next)g(test)g(\014le)g(is)g(sourced.)206 2107 y Fe(\210)49 b Ff(In)28 b(eac)m(h)g(source)g(\014le)g(one)f(can)h (de\014ne)g(the)g(parameterless)g(functions)g Fb(.setUp\(\))304 2228 y Ff(and)39 b Fb(.tearDown\(\))p Ff(.)65 b(whic)m(h)40 b(are)f(then)g(executed)i(directly)f(b)s(efore)e(and)h(after)304 2348 y(eac)m(h)k(test)f(function.)71 b(This)43 b(can,)h(for)e (instance,)j(b)s(e)d(used)g(to)g(con)m(trol)g(global)304 2468 y(settings)33 b(or)f(create)h(addition)f(log)g(information.)60 2627 y SDict begin H.S end 60 2627 a 60 2627 a SDict begin 14.5 H.A end 60 2627 a 60 2627 a SDict begin [/View [/XYZ H.V]/Dest (subsection.2.2) cvn /DEST pdfmark end 60 2627 a 130 x Fc(2.2)135 b(R)45 b(Co)t(de)g(Insp)t(ection)60 2942 y Ff(The)26 b(Co)s(de)f(Insp)s(ector)h(is)f(an)g(additional)f(to)s (ol)g(for)g(c)m(hec)m(king)j(detailed)f(test)f(case)h(co)m(v)m(er-)60 3062 y(age)h(and)f(getting)h(pro\014ling)f(information.)41 b(It)27 b(records)g(ho)m(w)h(often)e(a)h(co)s(de)g(line)g(will)h(b)s(e) 60 3182 y(executed.)58 b(W)-8 b(e)37 b(utilise)h(this)f(information)f (for)g(impro)m(ving)h(our)f(test)i(cases,)h(b)s(ecause)60 3303 y(w)m(e)f(can)g(iden)m(tify)g(co)s(de)f(lines)h(not)f(executed)i (b)m(y)f(the)f(curren)m(t)h(test)g(case)g(co)s(de.)57 b(The)60 3423 y(Co)s(de)28 b(Insp)s(ector)h(is)f(able)g(to)f(handle)h (S4)g(metho)s(ds.)42 b(During)27 b(the)h(dev)m(elopmen)m(t)i(of)e(the) 60 3544 y(Co)s(de)39 b(Insp)s(ector,)i(w)m(e)f(noticed,)h(that)d(the)h (syn)m(tax)h(of)e(R)h(is)g(v)m(ery)h(\015exible.)64 b(Because)60 3664 y(our)32 b(co)s(ding)f(philosoph)m(y)i(has)f(an)g(emphasis)h(of)f (main)m(tenance)h(and)f(a)f(clear)h(st)m(yle,)i(w)m(e)60 3784 y(dev)m(elop)s(ed)41 b(st)m(yle)f(guides)g(for)f(our)g(R)g(co)s (ding.)63 b(Therefore,)42 b(one)d(goal)f(for)h(the)h(Co)s(de)60 3905 y(Insp)s(ector)31 b(w)m(as)h(to)e(handle)h(our)f(co)s(ding)g(st)m (yles)j(in)d(a)h(correct)g(manner.)43 b(This)31 b(leads)g(to)60 4025 y(the)37 b(consequence)h(that)e(not)g(all)g(R)g(expression)i(can)e (b)s(e)h(handled)f(correctly)-8 b(.)56 b(In)36 b(our)60 4146 y(implemen)m(tation)31 b(the)g(Co)s(de)g(Insp)s(ector)g(has)f(t)m (w)m(o)h(main)g(functional)f(parts.)42 b(The)32 b(\014rst)60 4266 y(part)k(is)i(resp)s(onsible)g(for)e(parsing)h(and)g(mo)s(difying) f(the)i(co)s(de)f(of)f(the)h(test)h(function.)60 4386 y(The)j(second)g(part,)g(called)f(the)g(T)-8 b(rac)m(k)m(er,)43 b(holds)e(the)f(result)g(of)f(the)i(co)s(de)f(trac)m(king.)60 4507 y(The)46 b(result)f(of)g(the)g(trac)m(king)g(pro)s(cess)h(allo)m (ws)f(further)g(analysis)h(of)e(the)h(executed)60 4627 y(co)s(de.)1655 5358 y(7)p eop end %%Page: 8 8 TeXDict begin 8 7 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.8) cvn /DEST pdfmark end 52 158 a 60 194 a SDict begin H.S end 60 194 a 60 194 a SDict begin 14.5 H.A end 60 194 a 60 194 a SDict begin [/View [/XYZ H.V]/Dest (subsubsection.2.2.1) cvn /DEST pdfmark end 60 194 a 99 x Fg(2.2.1)112 b(Usage)60 478 y Ff(The)32 b(usage)g(of)f(the)h(Co)s(de)g(Insp)s(ector)g(and)f (the)h(T)-8 b(rac)m(k)m(er)33 b(ob)5 b(ject)32 b(is)g(v)m(ery)h (simple.)44 b(The)60 598 y(follo)m(wing)32 b(co)s(de)h(snipp)s(et)g(is) g(an)f(example:)60 802 y Fa(>)52 b(library\(RUnit\))60 922 y(>)g(foo)h(<-)g(function\(x\))h({)60 1042 y(+)261 b(x)53 b(<-)f(x)h(*)f(x)60 1163 y(+)261 b(x)53 b(<-)f(2)h(*)f(x)60 1283 y(+)261 b(return\(x\))60 1404 y(+)52 b(})60 1524 y(>)g(test.foo)i(<-)f(function\(\))h({)60 1644 y(+)261 b(checkTrue\(is.numeric\(foo\(1:10\)\))q(\))60 1765 y(+)g (checkEquals\(length\(foo\(1:10\)\),)59 b(10\))60 1885 y(+)261 b(checkEqualsNumeric\(foo\(1\),)58 b(2\))60 2005 y(+)52 b(})60 2126 y(>)g(bar)h(<-)g(function\(x,)h(y)f(=)f(NULL\))h({) 60 2246 y(+)261 b(if)53 b(\(is.null\(y\)\))h({)60 2367 y(+)470 b(y)52 b(<-)h(x)60 2487 y(+)261 b(})60 2607 y(+)g(if)53 b(\(all\(y)g(>)g(100\)\))g({)60 2728 y(+)470 b(y)52 b(<-)h(y)f(-)h(100) 60 2848 y(+)261 b(})60 2969 y(+)g(res)53 b(<-)g(x^y)60 3089 y(+)261 b(return\(res\))60 3209 y(+)52 b(})60 3330 y(>)g(track)i(<-)e(tracker\(\))60 3450 y(>)g(track$init\(\))60 3570 y(>)g(a)h(<-)f(1:10)60 3691 y(>)g(d)h(<-)f(seq\(0,)i(1,)e(0.1\))60 3811 y(>)g(resFoo)i(<-)e(inspect\(foo\(a\),)k(track)d(=)f(track\))60 3932 y(>)g(resBar)i(<-)e(inspect\(bar\(d\),)k(track)d(=)f(track\))60 4052 y(>)g(resTrack)i(<-)f(track$getTrackInfo\(\))60 4172 y(>)f(printHTML.trackInfo\(resTrack\))206 4376 y Ff(Note,)e(that)c(the)h(trac)m(king)g(ob)5 b(ject)47 b(is)f(an)h(global)e(ob)5 b(ject)47 b(and)g(m)m(ust)g(ha)m(v)m(e)h(the) 60 4496 y(name)35 b Fb(track)p Ff(.)51 b(The)35 b Fb(inspect)h Ff(function)f(a)m(w)m(aits)g(a)f(function)h(call)f(as)h(argumen)m(t)g (and)60 4617 y(executes)i(and)f(trac)m(ks)g(the)g(function.)51 b(The)36 b(results)h(will)f(b)s(e)f(stored)h(in)f(the)h(trac)m(king)60 4737 y(ob)5 b(ject.)63 b(The)39 b(result)h(of)e(the)h(function)g(\(not) g(of)f(the)h(T)-8 b(rac)m(k)m(er\))40 b(will)f(b)s(e)g(returned)h(as)60 4857 y(usual.)j(The)30 b(trac)m(king)g(results)h(will)f(receiv)m(ed)i (b)m(y)e(tr$getResult\(\).)42 b(With)30 b Fb(printHTML)60 4978 y Ff(the)j(result)g(of)f(the)h(trac)m(king)f(pro)s(cess)i(will)f (b)s(e)f(presen)m(ted)j(as)d(HTML)i(pages.)1655 5358 y(8)p eop end %%Page: 9 9 TeXDict begin 9 8 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.9) cvn /DEST pdfmark end 52 158 a 60 194 a SDict begin H.S end 60 194 a 60 194 a SDict begin 14.5 H.A end 60 194 a 60 194 a SDict begin [/View [/XYZ H.V]/Dest (subsubsection.2.2.2) cvn /DEST pdfmark end 60 194 a 99 x Fg(2.2.2)112 b(T)-9 b(ec)m(hnical)38 b(Details)60 478 y Ff(The)i(general)f(idea)h(for)e (the)i(co)s(de)f(trac)m(king)h(is)g(to)f(mo)s(dify)g(the)g(source)h(co) s(de)g(of)f(the)60 598 y(function.)66 b(Therefore,)43 b(w)m(e)e(use)g(the)f Fb(parse)h Ff(and)f Fb(deparse)i Ff(functions)e(and)g(the)g(ca-)60 719 y(pabilit)m(y)j(of)g(R)f(to)h (generate)g(functions)g(on)g(run)m(time.)75 b(T)-8 b(o)43 b(trac)m(k)h(the)f(function)g(w)m(e)60 839 y(try)37 b(to)g(include)h(a) f(ho)s(ok)g(in)g(ev)m(ery)i(co)s(de)e(line.)58 b(That)37 b(ho)s(ok)g(calls)h(a)f(function)g(of)g(the)60 959 y(trac)m(k)m(ed)c (ob)5 b(ject.)44 b(The)32 b(information)f(of)g(the)i(trac)m(king)f (will)g(b)s(e)g(stored)g(in)g(the)g(closure)60 1080 y(of)26 b(the)g(trac)m(king)h(ob)5 b(ject)27 b(\(actually)f(a)g(function\).)41 b(Because)28 b(the)e(R)g(parser)h(allo)m(ws)g(v)m(ery)60 1200 y(nested)g(expressions,)i(w)m(e)e(didn't)f(try)f(to)g(mo)s(dify)h (ev)m(ery)h(R)f(expression.)42 b(This)27 b(is)f(a)f(task)60 1321 y(for)32 b(the)h(future.)43 b(A)32 b(simple)i(example)g(for)d(the) i(mo)s(difying)f(pro)s(cess)i(is)f(as)f(follo)m(w:)60 1441 y(original:)60 1644 y Fa(>)52 b(foo)h(<-)g(function\(x\))h({)60 1765 y(+)261 b(y)53 b(<-)f(0)60 1885 y(+)261 b(for)53 b(\(i)g(in)f(1:x\))h({)60 2005 y(+)470 b(y)52 b(<-)h(y)f(+)h(x)60 2126 y(+)261 b(})60 2246 y(+)g(return\(y\))60 2367 y(+)52 b(})60 2570 y Ff(mo)s(di\014ed:)60 2773 y Fa(>)g(foo.mod)i(<-)f (function\(x\))h({)60 2894 y(+)261 b(track$bp\(1\))60 3014 y(+)g(y)53 b(<-)f(0)60 3135 y(+)261 b(track$bp\(2\))60 3255 y(+)g(for)53 b(\(i)g(in)f(1:x\))h({)60 3375 y(+)470 b(track$bp\(4\))60 3496 y(+)g(y)52 b(<-)h(y)f(+)h(x)60 3616 y(+)261 b(})60 3736 y(+)g(track$bp\(6\))60 3857 y(+)g(return\(y\))60 3977 y(+)52 b(})206 4181 y Ff(Problematic)33 b(co)s(de)g(lines)g(are:)60 4409 y Fa(>)52 b(if)h(\(any\(a)g(==)g (1\)\))g({)60 4529 y(+)261 b(print\("do)54 b(TRUE"\))60 4650 y(+)e(})h(else)g(print\("do)h(FALSE"\))60 4878 y Ff(This)33 b(m)m(ust)h(b)s(e)e(mo)s(di\014ed)h(to)1655 5358 y(9)p eop end %%Page: 10 10 TeXDict begin 10 9 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.10) cvn /DEST pdfmark end 52 158 a 60 293 a Fa(>)52 b(if)h(\(any\(a)g(==)g(1\)\))g({)60 414 y(+)261 b(track$bp\(2\))60 534 y(+)g(print\("do)54 b(TRUE"\))60 654 y(+)e(})h(else)g({)60 775 y(+)261 b(track$bp\(3\))60 895 y(+)g(print\("do)54 b(FALSE"\))60 1016 y(+)e(})60 1219 y Ff(The)34 b(problem)f(is)h(the)f Fd(else)40 b Ff(branc)m(h,)33 b(that)g(cannot)g(b)s(e)g(mo)s(di\014ed)g (in)g(the)h(curren)m(t)f(v)m(er-)60 1339 y(sion.)60 1489 y SDict begin H.S end 60 1489 a 60 1489 a SDict begin 14.5 H.A end 60 1489 a 60 1489 a SDict begin [/View [/XYZ H.V]/Dest (section.3) cvn /DEST pdfmark end 60 1489 a 183 x Fh(3)161 b(F)-13 b(uture)52 b(Dev)l(elopmen)l(t)f(Ideas)60 1891 y Ff(Here)26 b(w)m(e)g(brie\015y)g(list)g({)f(in)g(an)g(unordered) h(manner)f({)g(some)h(of)f(the)h(a)m(v)m(en)m(ues)h(for)e(future)60 2011 y(dev)m(elopmen)m(t)35 b(w)m(e)e(or)f(someone)i(in)m(terested)g (in)e(this)h(pac)m(k)-5 b(age)33 b(could)f(tak)m(e:)206 2215 y Fe(\210)49 b Ff(extend)39 b(the)g Fb(checkEquals)i Ff(function)d(to)g(handle)h(complex)g(S4)g(class)g(ob)5 b(jects)304 2335 y(correctly)34 b(in)f(comparisons.)45 b(T)-8 b(o)33 b(this)g(end)h(R)f(core)g(has)g(mo)s(di\014ed)g(c)m(hec)m (k.equal)304 2455 y(to)f(handle)h(S4)f(ob)5 b(jects.)206 2659 y Fe(\210)49 b Ff(reimplemen)m(t)31 b(the)e(in)m(ternal)g (structures)h(storing)f(the)h(test)f(suite)h(as)f(w)m(ell)h(as)g(the) 304 2779 y(test)j(result)g(data)f(as)g(S4)h(classes.)206 2983 y Fe(\210)49 b Ff(record)33 b(all)f(w)m(arnings)h(generated)g (during)f(the)h(execution)h(of)e(a)g(test)h(function.)206 3186 y Fe(\210)49 b Ff(add)33 b(to)s(ols)f(to)g(create)i(test)f(cases)h (automatically)-8 b(.)44 b(This)34 b(is)g(a)e(researc)m(h)i(pro)5 b(ject)304 3306 y(but)41 b({)f(giv)m(en)h(the)g(imp)s(ortance)g(of)f (testing)h({)f(w)m(orth)h(the)g(e\013ort.)68 b(See)41 b([)3065 3306 y SDict begin H.S end 3065 3306 a Ff(3)3114 3241 y SDict begin H.R end 3114 3241 a 3114 3306 a SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.junit) cvn H.B /ANN pdfmark end 3114 3306 a Ff(])g(for)304 3427 y(v)-5 b(arious)32 b(approac)m(hes)h(in)g(other)f(languages.)206 3630 y Fe(\210)49 b Ff(impro)m(v)m(e)43 b(the)e(exp)s(ort)h(of)f(test)h (suite)g(execution)h(data)d(e.g.)i(b)m(y)g(adding)g(XML)304 3750 y(data)32 b(exp)s(ort)g(supp)s(ort.)206 3954 y Fe(\210)49 b Ff(add)39 b(some)i(ev)-5 b(aluation)39 b(metho)s(ds)h(to)f(the)h(co)s (de)g(insp)s(ector)g(e.g.)g(use)g(soft)m(w)m(are)304 4074 y(metrics)29 b(to)g(estimate)g(standard)f(measures)i(of)e(co)s(de) h(qualit)m(y)-8 b(,)30 b(complexit)m(y)-8 b(,)31 b(and)304 4195 y(p)s(erformance.)206 4398 y Fe(\210)49 b Ff(o)m(v)m(ercome)41 b(the)e(problem)g(of)g(nested)h(calls)g(to)f(registered)h(functions)f (for)g(co)s(de)304 4518 y(insp)s(ection.)206 4722 y Fe(\210)49 b Ff(allo)m(w)33 b(automatic)f(registration)f(of)h(functions)h(&)g (metho)s(ds.)1630 5358 y(10)p eop end %%Page: 11 11 TeXDict begin 11 10 bop 0 0 a SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if end 0 0 a 52 158 a SDict begin H.S end 52 158 a 52 158 a SDict begin H.R end 52 158 a 52 158 a SDict begin [/View [/XYZ H.V]/Dest (page.11) cvn /DEST pdfmark end 52 158 a 60 293 a Fh(References)60 392 y SDict begin H.S end 60 392 a 60 392 a SDict begin 14.5 H.A end 60 392 a 60 392 a SDict begin [/View [/XYZ H.V]/Dest (section*.3) cvn /DEST pdfmark end 60 392 a 60 350 a SDict begin H.S end 60 350 a 60 350 a SDict begin 14.5 H.A end 60 350 a 60 350 a SDict begin [/View [/XYZ H.V]/Dest (cite.xp) cvn /DEST pdfmark end 60 350 a 109 512 a Ff([1])48 b(h)m(ttp://www.xprogramming.com)60 579 y SDict begin H.S end 60 579 a 60 579 a SDict begin 14.5 H.A end 60 579 a 60 579 a SDict begin [/View [/XYZ H.V]/Dest (cite.beck) cvn /DEST pdfmark end 60 579 a 109 716 a Ff([2])g(h)m(ttp://www.xprogramming.com/testfram.h)m(tm)60 782 y SDict begin H.S end 60 782 a 60 782 a SDict begin 14.5 H.A end 60 782 a 60 782 a SDict begin [/View [/XYZ H.V]/Dest (cite.junit) cvn /DEST pdfmark end 60 782 a 109 919 a Ff([3])g(h)m(ttp://www.junit.org/)60 985 y SDict begin H.S end 60 985 a 60 985 a SDict begin 14.5 H.A end 60 985 a 60 985 a SDict begin [/View [/XYZ H.V]/Dest (cite.tfg) cvn /DEST pdfmark end 60 985 a 109 1122 a Ff([4])g(h)m (ttp://www.xprogramming.com/xpmag/testFirstGuidelines.h)m(tm)60 1189 y SDict begin H.S end 60 1189 a 60 1189 a SDict begin 14.5 H.A end 60 1189 a 60 1189 a SDict begin [/View [/XYZ H.V]/Dest (cite.runit-sf) cvn /DEST pdfmark end 60 1189 a 109 1326 a Ff([5])g(h)m(ttps://sourceforge.net/pro)5 b(jects/runit/)1630 5358 y(11)p eop end %%Trailer userdict /end-hook known{end-hook}if %%EOF �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/doc/RUnit.Rnw����������������������������������������������������������������������������0000644�0001751�0000144�00000050411�11303244513�014601� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������% -*- mode: noweb; noweb-default-code-mode: R-mode; -*- % % $Id: RUnit.Rnw,v 1.22 2009/11/25 15:12:11 burgerm Exp $ % % %\VignetteIndexEntry{RUnit primer} %\VignetteKeywords{Unit Testing, Code Inspection, Programming} %\VignetteDepends{methods, splines} %\VignettePackage{RUnit} \documentclass[12pt, a4paper]{article} %\usepackage{amsmath,pstricks} \usepackage{hyperref} %\usepackage[authoryear,round]{natbib} %\parskip=.3cm \oddsidemargin=.1in \evensidemargin=.1in \headheight=-.3in \newcommand{\scscst}{\scriptscriptstyle} \newcommand{\scst}{\scriptstyle} \newcommand{\Rfunction}[1]{{\texttt{#1}}} \newcommand{\Robject}[1]{{\texttt{#1}}} \newcommand{\Rpackage}[1]{{\textit{#1}}} %\makeindex % \begin{document} \title{RUnit - A Unit Test Framework for R} \author{Thomas K\"onig, Klaus J\"unemann, and Matthias Burger\\Epigenomics AG} \maketitle \tableofcontents \section*{Abstract} \label{section:abstract} Software development for production systems presents a challenge to the development team as the quality of the coded package(s) has to be constantly monitored and verified. We present a generic approach to software testing for the R language modelled after successful examples such as JUnit, CppUnit, and PerlUnit. The aim of our approach is to facilitate development of reliable software packages and provide a set of tools to analyse and report the software quality status. The presented framework is completely implemented within R and does not rely on external tools or other language systems. The basic principle is that every function or method is accompanied with a test case that queries many calling situations including incorrect invocations. A test case can be executed instantly without reinstalling the whole package - a feature that is necessary for parallel development of functionality and test cases. On a second level one or more packages can be tested in a single test run, the result of which is reported in an well structured test protocol. To verify the coverage of the test framework a code inspector is provided that monitors the code coverage of executed test cases. The result of individual test invocations as well as package wide evaluations can be compiled into a summary report exported to HTML. This report details the executed tests, their failure or success, as well as the code coverage. Taking it one step further and combining the build system with a development and release procedure with defined code status description this approach opens the way for a principled software quality monitoring and risk assessment of the developed application. For our code development we have utilised the described system with great benefit w.r.t.\ code reliability and maintenance efforts in a medium sized development team. \section{Introduction} The importance of software testing can hardly be overrated. This is all the more true for interpreted languages where not even a compiler checks the basic consistency of a program. Nonetheless, testing is often perceived more as a burden than a help by the programmer. Therefore it is necessary to provide tools that make the task of testing as simple and systematic as possible. The key goal of such a testing framework should be to promote the creation and execution of test cases to become an integral part of the software development process. Experience shows that such a permanently repeated code - test - simplify cycle leads to faster and more successful software development than the usually futile attempt to add test cases once the software is largely finished. This line of thought has been pushed furthest by the Extreme Programming \cite{xp} and Test-First paradigms where test cases are viewed as the essential guidelines for the development process. These considerations lead to various requirements that a useful testing framework should satisfy: \begin {itemize} \item {Tests should be easy to execute.} \item {The results should be accessible through a well structured test protocol.} \item{It should be possible to execute only small portions of the test cases during the development process.} \item{It should be possible to estimate the amount of code that is covered by some test case.} \end {itemize} %\paragraph{Background} %\label{paragraph:Background} Testing frameworks that address these aspects have been written in a variety of languages such as Smalltalk, Java, C++ and Python. In particular, the approach described in \cite{beck} has turned out to be very successful, leading -- among others -- to the popular JUnit library for Java \cite{junit}, which has been ported to many other languages (see \cite{xp} for an extensive list of testing frameworks for all kinds of languages). Accordingly, the RUnit package (available at sourceforge \cite{runit-sf}) is our version of porting JUnit to R, supplemented by additional functionality to inspect the test coverage of some function under question. %\paragraph{Motivation} %\label{paragraph:Motivation} One may wonder why R would need yet another testing framework even though the standard method, namely executing {\it R CMD check} on ones complete package at the shell prompt, is widely accepted and applied. We think, however, that the RUnit approach is more in line with the above listed requirements and can be seen as a complement to the existing process in that: \begin{itemize} \item{test cases are called and executed from the R prompt} \item{the programmer decides which result or functionality to put under testing, e.g.\ formating issues of textual output do not need to matter} \item{test and reference data files need not be maintained separately but are combined into one file} \item{test cases need not be limited to testing/using functionality from one package checked at a time} \end{itemize} Moreover, testing frameworks based on JUnit ports seem to have become a quasi standard in many programming languages. Therefore, programmers new to R but familiar with other languages might appreciate a familiar testing environment. And finally, offering more than one alternative in the important field of code testing is certainly not a bad idea and could turn out useful. Before explaining the components of the RUnit package in detail, we would like to list some of the lessons learned in the attempt of writing useful test suites for our software (a more complete collection of tips relating to a Test-First development approach can be found in \cite{tfg}): \begin{itemize} \item {Develop test cases parallel to implementing your functionality. Keep testing all the time (code - test - simplify cycle). Do not wait until the software is complete and attempt to add test cases at the very end. This typically leads to poor quality and incomplete test cases.} \item{Distinguish between unit and integration tests: Unit tests should be as small as possible and check one unit of functionality that cannot be further decomposed. Integration tests, on the other hand, run through a whole analysis workflow and check the interplay of various software components.} \item{Good test coverage enables refactoring, by which a reorganisation of the implementation is meant. Without regular testing the attitude {\it `I better do not touch this code anymore`} once some piece of software appears to be working is frequently encountered. It is very pleasing and time-saving just to run a test suite after some improvement or simplification of the implementation to see that all test cases are still passing (or possibly reveal some newly introduced bug). This refactoring ability is a key benefit of unit testing leading not only to better software quality but also to better design.} \item{Do not test internal functions but just the public interface of a library. Since R does not provide very much language support for this distinction, the first step here is to clarify which functions are meant to be called by a user of a package and which are not (namespaces in R provide a useful directive for making this distinction, if the export list is selected carefully and maintained). If internal functions are directly tested, the ability of refactoring gets lost because this typically involves reorganisation of the internal part of a library.} \item {Once a bug has been found, add a corresponding test case.} \item{We greatly benefitted from an automated test system: A shell script, running nightly, checks out and installs all relevant packages. After that all test suites are run and the resulting test protocol is stored in a central location. This provides an excellent overview over the current status of the system and the collection of nightly test protocols documents the development progress.} \end{itemize} \section{The RUnit package} \label{section:RUnitPackage} This section contains a detailed explanation of the RUnit package and examples how to use it. As has already been mentioned the package contains two independent components: a framework for test case execution and a tool that allows to inspect the flow of execution inside a function in order to analyse which portions of code are covered by some test case. Both components are now discussed in turn. \subsection{Test case execution} \label{subsection:Testcaseexecution} The basic idea of this component is to execute a set of test functions defined through naming conventions, store whether or not the test succeeded in a central logger object and finally write a test protocol that allows to precisely identify the problems. {\bf Note, that RUnit - by default - sets the version for normal, and all other RNGs to 'Kinderman-Ramage', and 'Marsaglia-Multicarry', respectively. If you like to change these defaults please see {\tt ?defineTestSuite} for argument 'rngNormalKind' and 'rngKind'.} As an example consider a function that converts centigrade to Fahrenheit: \begin{Sinput} c2f <- function(c) return(9/5 * c + 32) \end{Sinput} A corresponding test function could look like this: \begin{Sinput} test.c2f <- function() { checkEquals(c2f(0), 32) checkEquals(c2f(10), 50) checkException(c2f("xx")) } \end{Sinput} The default naming convention for test functions in the RUnit package is {\tt test...} as is standard in JUnit. To perform the actual checks that the function to be tested works correctly a set of functions called {\tt check ...} is provided. The purpose of these {\tt check} functions is two-fold: they make sure that a possible failure is reported to the central test logger so that it will appear properly in the final test protocol and they are supposed to make explicit the actual checks in a test case as opposed to other code used to set up the test scenario. Note that {\tt checkException} fails if the passed expression does not generate an error. This kind of test is useful to make sure that a function correctly recognises error situations instead of silently creating inappropriate results. These check functions are direct equivalents to the various {\tt assert} functions of the JUnit framework. More information can be found in the online help. Before running the test function it is necessary to create a test suite which is a collection of test functions and files relating to one topic. One could, for instance, create one test suite for one R package. A test suite is just a list containing a name, an array of absolute directories containing the locations of the test files, a regular expression identifying the test files and a regular expression identifying the test functions. In our example assume that the test function is located in a file {\tt runitc2f.r} located in a directory {\tt /foo/bar/}. To create the corresponding test suite we can use a helper function: \begin{Sinput} testsuite.c2f <- defineTestSuite("c2f", dirs = file.path(.path.package(package="RUnit"), "examples"), testFileRegexp = "^runit.+\\.r", testFuncRegexp = "^test.+", rngKind = "Marsaglia-Multicarry", rngNormalKind = "Kinderman-Ramage") \end{Sinput} All that remains is to run the test suite and print the test protocol: \begin{Sinput} testResult <- runTestSuite(testsuite.c2f) printTextProtocol(testResult) \end{Sinput} The resulting test protocol should be self explanatory and can also be printed as HTML version. See the online help for further information. Note that for executing just one test file there is also a shortcut in order to make test case execution as easy as possible: \begin{Sinput} runTestFile(file.path(.path.package(package="RUnit"), "examples/runitc2f.r")) \end{Sinput} The creation and execution of test suites can be summarised by the following recipe: \begin{enumerate} \item{create as many test functions in as many test files as necessary } \item{create one or more test suites using the helper function {\tt defineTestSuite}} \item{run the test suites with {\tt runTestSuite}} \item{print the test protocol either with {\tt printTextProtocol} or with {\tt printHTMLProtocol} (or with a generic method like {\tt print} or {\tt summary})} \end{enumerate} We conclude this section with some further comments on various aspects of the test execution framework: \begin{itemize} \item{A test file can contain an arbitrary number of test functions. A test directory can contain an arbitrary number of test files, a test suite can contain an arbitrary number of test directories and the test runner can run an arbitrary number of test suites -- all resulting in one test protocol. The test function and file names of a test suite must, however, obey a naming convention expressible through regular expressions. As default test functions start with {\tt test} and files with {\tt runit}.} \item{RUnit makes a distinction between failure and error. A failure occurs if one of the check functions fail (e.g.~{\tt checkTrue(FALSE)} creates a failure). An error is reported if an ordinary R error (usually created by {\tt stop}) occurs.} \item{Since version 0.4.0 there is a function {\tt DEACTIVATED} which can be used to deactivate test cases temporarily. This might be useful in the case of a major refactoring. In particular, the deactivated test cases are reported in the test protocol so that they cannot fall into oblivion.} \item{The test runner tries hard to leave a clean R session behind. Therefore all objects created during test case execution will be deleted after a test file has been processed.} \item{In order to prevent mysterious errors the random number generator is reset to a standard setting before sourcing a test file. If a particular setting is needed to generate reproducible results it is fine to configure the random number generator at the beginning of a test file. This setting applies during the execution of all test functions of that test file but is reset before the next test file is sourced.} \item{In each source file one can define the parameterless functions {\tt .setUp()} and {\tt .tearDown()}. which are then executed directly before and after each test function. This can, for instance, be used to control global settings or create addition log information.} \end{itemize} \subsection{R Code Inspection} \label{subsection:RCodeInspection} The Code Inspector is an additional tool for checking detailed test case coverage and getting profiling information. It records how often a code line will be executed. We utilise this information for improving our test cases, because we can identify code lines not executed by the current test case code. The Code Inspector is able to handle S4 methods. During the development of the Code Inspector, we noticed, that the syntax of R is very flexible. Because our coding philosophy has an emphasis of maintenance and a clear style, we developed style guides for our R coding. Therefore, one goal for the Code Inspector was to handle our coding styles in a correct manner. This leads to the consequence that not all R expression can be handled correctly. In our implementation the Code Inspector has two main functional parts. The first part is responsible for parsing and modifying the code of the test function. The second part, called the Tracker, holds the result of the code tracking. The result of the tracking process allows further analysis of the executed code. \subsubsection{Usage} The usage of the Code Inspector and the Tracker object is very simple. The following code snippet is an example: <<eval=FALSE>>= library(RUnit) ## define sample functions to be tested foo <- function(x) { x <- x*x x <- 2*x return(x) } test.foo <- function() { checkTrue(is.numeric(foo(1:10))) checkEquals(length(foo(1:10)), 10) checkEqualsNumeric(foo(1), 2) } bar <- function(x, y=NULL) { if (is.null(y)) { y <- x } if (all(y > 100)) { ## subtract 100 y <- y - 100 } res <- x^y return(res) } track <- tracker(); ## initialize a tracking "object" track$init(); ## initialize the tracker a <- 1:10 d <- seq(0,1,0.1) resFoo <- inspect(foo(a), track=track); ## execute the test function and track resBar <- inspect(bar(d), track=track); ## execute the test function and track resTrack <- track$getTrackInfo(); ## get the result of Code Inspector (a list) printHTML.trackInfo(resTrack) ; ## create HTML sites @ Note, that the tracking object is an global object and must have the name {\tt track}. The {\tt inspect} function awaits a function call as argument and executes and tracks the function. The results will be stored in the tracking object. The result of the function (not of the Tracker) will be returned as usual. The tracking results will received by tr\$getResult(). With {\tt printHTML} the result of the tracking process will be presented as HTML pages. \subsubsection{Technical Details} The general idea for the code tracking is to modify the source code of the function. Therefore, we use the {\tt parse} and {\tt deparse} functions and the capability of R to generate functions on runtime. To track the function we try to include a hook in every code line. That hook calls a function of the tracked object. The information of the tracking will be stored in the closure of the tracking object (actually a function). Because the R parser allows very nested expressions, we didn't try to modify every R expression. This is a task for the future. A simple example for the modifying process is as follow:\\ original: <<eval=FALSE>>= foo <- function(x) { y <- 0 for(i in 1:x) { y <- y + x } return(y) } @ modified: <<eval=FALSE>>= foo.mod <- function(x) { track$bp(1) ; y <- 0 track$bp(2); for(i in 1:x) { track$bp(4) ; y <- y +x } track$bp(6); return(y) } @ Problematic code lines are: <<eval=FALSE>>= if(any(a==1)) { print("do TRUE") } else print ("do FALSE"); @ This must be modified to <<eval=FALSE>>= if(any(a==1)) { track$bp(2); print("do TRUE") }else{ track$bp(3); print("do FALSE"); } @ The problem is the \textit{else} branch, that cannot be modified in the current version. \section{Future Development Ideas} Here we briefly list -- in an unordered manner -- some of the avenues for future development we or someone interested in this package could take: \begin{itemize} \item{extend the {\tt checkEquals} function to handle complex S4 class objects correctly in comparisons. To this end R core has modified check.equal to handle S4 objects.} \item{reimplement the internal structures storing the test suite as well as the test result data as S4 classes.} \item{record all warnings generated during the execution of a test function.} \item{add tools to create test cases automatically. This is a research project but -- given the importance of testing -- worth the effort. See \cite{junit} for various approaches in other languages.} \item{improve the export of test suite execution data e.g.~by adding XML data export support.} \item{add some evaluation methods to the code inspector e.g.~use software metrics to estimate standard measures of code quality, complexity, and performance.} \item{overcome the problem of nested calls to registered functions for code inspection.} \item{allow automatic registration of functions \& methods.} \end{itemize} \begin{thebibliography}{99} % \bibliographystyle{plainnat} \bibitem{xp} http://www.xprogramming.com \bibitem{beck} http://www.xprogramming.com/testfram.htm \bibitem{junit} http://www.junit.org/ \bibitem{tfg} http://www.xprogramming.com/xpmag/testFirstGuidelines.htm \bibitem{runit-sf} https://sourceforge.net/projects/runit/ \end{thebibliography} \end{document} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/doc/RUnit.pdf����������������������������������������������������������������������������0000644�0001751�0000144�00000242204�11444151274�014616� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������%PDF-1.4 %Çì¢ 14 0 obj <</Length 15 0 R/Filter /FlateDecode>> stream xœí[Ɏǽü}¬64¥Ü—£vX¶a›ÃÉŠâÒPIDÑ<ù×ý"×ȪlrÑ€„ÀRuV./^¼ˆ*þp«<úSþ~t{õáéO¼‡/ðßÓ«®dq(=º=||C£üA‰Õ9å7O®òãò ¥]9¸àV7·W_/ŽJ¯^«°üý(×ÓËóãµ\…‹Z.§ãµX½rÎ-?¯µP«r~¹>^«èWåòݵk²L`•ª©ë>I3¨è°³Ü½YVryL,6ÌòczÎKÚXë–Ï^¯Vªåކ*§MËCºBŠ–[º6Rig‡é^•ZµÅÙ^°Ñ|–ï±Jôìòä¨VaTTÛÁùЖÂÄRmþyó%™8¤YµqŠL|-åêm ‡km1,ÆÃÍw0ï ž_cR.ÏhZ]ðž–0«!XÚ¼INg¢»Ñ“!´XÖ.¤Ç¤7F+Z×™k`¢<ÿ¿ë#ô!¥ÜѦz^–Ê‘3ì*4Üò´oàZË­Ò¶µ`1½œóXalÝWX^±¹h‹Ò­“} ÇKì5m"HìáÂq[;!­ëåSò­>†µ…1Ê8YMä­f&*ƒa3<HÇ_¬²ûÁiÀw ÜñÜŸ±ñN6ô§´˜b¸|¶·"³Lö˜Šq °ÜÇ„be)|Êé¼W J˜Íí«õñ?fl¥üj€Âõô˜É^Ÿ ¤ƒ)^‚7»¹•¥xã¨àãve<b•SEaè !q¨/è|V‡×`ïýöKóçm~uÁ•|Ó̼|«·GE0A<|‹Õ-"Q¸­ÈØA¶³ÚvÕüÕnŠv%ëáæ‡ØÑ¯JZ“£YcšUklÁü ÙÞç#ÙP­NDaZlÒj9k•&WAºdyúYEË~þ19QJ£úâ@¢µ‰J#˜äæOW7¿ÿšv…^ ò‡´o<ÅŠV«º˜Ñ™ Y7•­¾ ¨Æy°îw`6‡ é ‘ áìL´õñŒt�ïf”àÀ@K•Çh³ñ ²I²ˆÊÔ³å×k:BÂ긡ñQÁþRe[0–p9âé IÙiÃc[eyŒcÛ£\ä‚0�Qåç‡G0­w‚¬ÀÊhð;ð’°BQlÐv(JH5Èn*3ž*S}÷ϵ k…À4ŒéUr¹ö Ñ.Ã*nµ'0/ÑÂclC`çÇ#žóÖ¤SÀ‹0>¶\~|اiãÈ@ˆ®`Ø$ÿÂØ¾¶åÙ¬Mò –‰¥Œ´†\)²Ë_ä¹MÚáH€ÏŠÈ»¹4—Z]ð~Œ]JQ¤Éçdc¹ž55þ¸cUwìr €…pþ¾Àï*åu8QIi†|`HD4ÿED0Òcð<Ð~oŽ~It ŠàŽnN-ž4 œêÉ`Sj 2Çÿߕŕ~p¥ò)PÍ>J·+!gÀ7$c!…ë~aAù´ÇÜ ¿¬Ì¿bÏ¿ ÿ—\ÓøshCÐßLØñÜ\DBiõ¼àiK­ä:ˆ[màf槤| Ï£*sÚàj¬ihµ‡=ÔNg$n].ÿ·íþÞÜwmuʵ)þÓ½îéþóc„“Qé˹Êê÷˜l©Z�w?M2w]ÉÕΨåç#TM^—{¨‹àLÒ¤c«lI ¾ ƒÛc*gódùäMÚ²'ªUY商ΚIK¦ŠŽÐ‘28R§•!&íà-ªŸªd×$1¡ZcJÙ©Ê,^k¦Úï#:7­Bòª{,z•1‘w©XF¹MÅ@¡€Ö"ì,S›3 ‡)}¼¯z¸¼è÷$Í L ¥Eå<DÄë£&Ù,'Å»žšçÖ�Œ8fÀƒ?Óã*+úrëÌdÉËþÈ-ÕfN™ØGÂiÔÐÉ µ½SÃ.ÙD¥n·I ¶9ïzX—Lmßæ«~¹M»\@•´«¢ ²·¤ ƒ¥Þ4Q–﹌¯ú|ç—~¸ZFkya£ý¡¾ÎÆ"1—­u™6e&¯ÔêÊ“¨v9O2r;ŸûJÏ Ø ²ÆU`‰O øØ §KÖ2ÃfòbNšŽŒXLžoÖ5¯‰‡•RåJ"/>jì„I\¿CÁðe‡ñ;уÂÎ[®©Oø- ô¸RÃdÐå¸ û‚ÖØóÏözÏé准ˆWs«ŸJhA‰¿¡¤Dì´'´¶f/Z(YŠ¢GÍ–Ü&†iR„ŠCÏ!Ç6ÕSê÷GKu°â¿>í—mÆo¿ ýoŽt":5Pf+5SÆ-’àh}›qvd>)îò“&¤êçT¤æä¯„­!FH>äQ L Ì~?ç06ªÔ´yr&";¸ø¸ä`°xq%»+”C’ù”ÍE D&°TÐïMœMyúÝÔÓm"ÒJ®6ÄåÇ�jt©vÄò<ê~5û(¯VS(ÇjäV7EÊóí.in¶ äžÇ–Äà(¶»— ûwdêP&ó E'Ùy²¼OÃŽÆ2HÉ+Y "D½*g?è�â»Â–ãP1X +Í<LybÈ%Û9½¥ëNtPudìð…/Óò ¥„•š ]˜TÀð5ÂüÌlÆÄ(Ï^t÷i‡lå<¸pâ!Jn3ª)§P’%…Ap>˜`ò.ó jæÃW &úÕ¦ CtÂbë±S±àHðqÈöþ ³G>95†;HÏlE¤‡´©/í–t*®žÑÀÜ›qem¸Ó›–\¬*aŠßh¢ƒÔ¥Ð‰Ë'…)ãÚˆ²oòeÞ»g,¬H¥ô¬„Îó]d0 ŠÓ¨µþJG2”Áνòf ädJEŠ'UK/jÏe“x]XI^²½œ(»vRÛÄŠ3¹l¨w_ 4¨²—{ßL”Ì~<‘K[Ã6ù9$]Æ17gÃΧyN"%ÛCÚËbâÊ1\Ÿ_lJçËÀ6V/\$r=…ŒBýIFP̾…!=qìÙÖ<mÅ_ÉØŒùóÛŽ­3ÐúDb­[ó–Æc…û”0ÚÃjv"˜/'òh× b‘O~nmv#—Ê+2˜…Ó*ñœ¸ŒÆó0CHò•ð#C˜¥ìÔ8Wi'óPØ ±¨H6ö\il?8Áv~@Þ{™UI ©ï´ÐO¨Uþ1RË=ÔhæÙ2™ …u¼¤¨ .›úÛ¶úï‡4q/¤e• ÞZ($«ÕBÁ¤BANQ‡á]B•­Åî²iÛCMʧ°Å†OÓþ´zoÅé |”/ ˘înGic^mg%æµæØd;û¾Ø"š¥k:ÜP#Ý/mÏ6&x—xé%¹Y™}jeeõöE·Hÿ¹…xc^ƒÑâëì6J&S½I‰ª\¬ÒJ|Ô ðA¾¥Ö ž†z7•”¾Î°Fóe&MŸo¨úÕÆ®ìIö‹~fð_ݬÓS¥uIÖ›{¾I„E“ÂÆzWcÎÉüjœÚà*F RmçÙ6»VušzP® ì ©±©ëÀK¥6Âů^š·ô›Œ#Œ2;Úµuqz"ïO @#:gw,0ãCš!eãÙ»KªçR†.÷’ W†À®nØØ–ä«dJ":\h¾<@˜ú<Æl4„î…òóMN¤Zø Å�óÞ=Z„UÆXJ›RfפÚÔ9Ïv1èŒl‰°ùÉëmû†¿:ddG¿öEçê†Kï¡<£E˜¯DNCúl»"Y$Súɺÿçö²oVù—“îå7ä&dÍVtà½`A])y¡=7í®Ì´\7åÀ§)ëaJÖÏëžà)ý|¹ ™Íð`æ&ž2ÄEè±dŸ1¼vàMê›Ñþloôl:ÇØy¯;º›dÎGéI‡…Ôø¨µDorÕwéÖîÍG’n<zšE‘7vÝÀ—T?Ò[øî£ZæfÄ¥'§Í“²s½ùnƒÚѼû» �€tÚlÜóÜóÐÓ&'£¬_ø©GO´4ÓÅî“–/6¯:§ÚíÌ}‰¶b`Ìm5ô„Ÿ‚ã4sÚ¾ÊnÆvÛ´Kþz&t¹`}æ—,ä2À4}&# u ‘ãsLÞiJøc[éæÇB—Þ}Ä«)fo'vâ>¡`°k{q/R¤7jpí©}Ú©öíZþEÊþ‹¦ÙlC ?Cwc“iãÛ°¡×:C+k$’ÚCICïœßGËc¨9ÆŽGi<nÊh…±2¾ñÀŽŸûËŽeÑR¦*óMv³´Ãõ’Ó¯bUyã÷kF—¦²ûå‰x‹ ’—NÒ7æË_ÒÛie&¿ô* zÝã§Î-Øv¯ZZ[ qèyãâA VÂ1j™›¸FŠõ[4Ò÷yNí_ù00òP³ïïZé÷’L™Ê‡fÁ /Éfuë”öyµ™­)M.óôÍ?’+“òŽ˜Ìº}GÜh4}ôö Þ€J”õÍo¡Ä»–ŒÏï9S“;b„½@s­;æ§Åè¶Ÿ;‹û¦fióhúר_Ï:ЧÜÅ \’Ĩ¦­™QQVg¦y¯ô¬¬ÜV ÕEz˜”þáC)ó®m³x¡Ù›+F|çj8?GÛë;>è)~w¾ºUÚÞ [Xf«ÏªÅM{½T†¾'ª¬e½ö{uJ¬xn¯ÚÇdžw­%%eÈAX¬ü-ÛÂ4æ³›«¿áÏ�N¡ë“endstream endobj 15 0 obj 3550 endobj 33 0 obj <</Length 34 0 R/Filter /FlateDecode>> stream xœÍ\Û’Çq}_ù#öqÆæ¶ºîU~”C×¶¼o=€ lc°  Êðø³•Y׬®¬™YHŒp0\Ît×%ëäÉkÍ·ë"nWü'ÿ÷áýÍ/ÿ,ìíÛO7ëíoáß·7?ÞˆøÄmþÏÃûÛ_ÝãSáVˆ%#oï¿¿I¯‹[yë”^œ¾½óêðÓþGxßÕ¢¼ ‡Ç;±hi´8lßïä"¤öúðåx§œ[”Ô‡çô„VáðÃq]‚Ókð0�<à—ÕÊPOGéi½-ó8=̃£¼Æi¼rÆÞ¦?­‘u@åa úÀ÷ø©Z Ì3¬Ã ß²n >”ïq'uÖOG½§aLøVyU‡CÞ¦…’Ý¿nKyYÚU›6Ð_qGÚ)Uç+o+åï²¼TH9½H²hp"xKÉ%hÜ›^ˆö¼ºÃöØ>n«þ�“…E(Qö„cU“?µÕÌ;…nŸp»à@ut²ê§ã_îÿp£”YV ˆ¹1¢—Õk o¿!b.“¿ÁÑ×EÃÛdúv ¯›xò÷B)œå.Os'`s"„4[µÔz… Áœ:y‚  ·hìâƒ&d„ˆ£P={ö«Aû~ÛþAŸ"¨­8"Øÿ‰r÷Š€®Áçs[äs;¾K§2Q람N ßžd^^Žw^°Ý{øP.Í éçgWA¶sª+’Ž€x[áHd•UD®Æ47°ŸÛ£ywZÃdÇ„Ä4"Q§Y r*1ª²\ PY¹8ïq J,«ƒm58d0¢5ØŽ#¨Üˆšvúž ì}¯~êû˜u%§r:¡ÜÄ¢B§sø’†—€·‰Ê“`… M4ïŽXÊË3Ð5u¦/‡½í´°”~ŠƒÚà訧ÏìR’/Æ­x2ë�9|›˜2!È�¦v<Òû‡†¢SÚC�q¢29P&!!‰¨®ìiWÁ†hmƒYÂXz…`¬âés£·Fí¯×,Í}I›’BÒO+²¡0°fž&Ä@ ÜV_j”SìŒóׇ9QNf¥>B‰‘ÀD¿ƒ=I+WMèâßámk• ‡?â;Ò[È‚#–as,±lÖZ³Ì2î~gžëî]Ï÷£!%øÜNeZ%ycW&Ýˈß}NÈÒ|’‚¬žÐÙÎŽ„Žß'0yÝñ}#Øo2Ñ¥Ñ{“Û¸î‡ÄF{ˆMµ¡Ä!$Z·Q}îÀxè‡ST;ápk{ ˆï?ô2rao/àqº¯;ƒŽ.LÑ“ž†cÀ)’Ÿê᢬*µ‹ëÍ4ykv¸ÚÀvÀç»ÂÃËêb¤Ggžñ<œ3þÍb�åðh=(‡×‹…c¢ï¼«x£>ä[Ü3ˆ qüÜNô©CbM¿Ë,çëBcç4ôD–üP_Ï|—^&„GÐC(ïc…ß u‚Dë#´d€\O9‘8‡¨$+DKÊwž]yòýŽ lµãШäqø;ŽõÇR@ÁjhÈà"†ÈhÈÛ©,G"»/õtÒgVK^£ßãÛ°QkÛI( n^‚Šö#³„¶,UB‹Íè1qNöo ŒAÊ”r±ÒP°é½Áe¬‘èNŽs~·7ÙˆºO j XA6Úƒ½l­$‹ûØ™”2ÿÀ"sL‘Æé nÏ$UNñ G(¦eßIpf ¸`IþFº.ø�ùK»²ÿ§6â#ó5Ê Ü óåøC#3êÞŽ'0šEù„{°Ñ#ä–ÙÆ|àXh#þ"~{¢‡„µŸeÌ-¯@‹Î©$_:^be²£ª“èuˆªÙÁ˜ 9adK+Á!ór½bÇ“WÄx¼ŽÜíeô»p†8ó×”F‘¥ŒŒ>èÞL3FüÀÑ e¡ z§ÎãÒଢÇ>YR÷ù“»UH;ðŽeõaÌáÇÊU£ÃŽGrÚâ°Ö)ýQåЪ1üŽ(¶çá¬sž¢‚¬7\Já:Ôœw”Zѱì†hð~——væ¾Ðï>ÆmþTÿmÛמƒ<takÙl•™û‹�,ðy4·’Á°ø–ƒ‰î8 GÌì+Šý:bvýp<‚=rú†äÏÓöuÑ+ø'|2¾ùoŽÎ.=•ÞM‚¾ÃjOÃñàÞ+Ò9Œ~nË·‚ßaUçN&ûo LO8péÛEz?IÛl§­Á­sù£=BGu«ÿ*rÏá1@¶›1ÙbEò-sÏ…õ“ç‚Â3›dU’+Í$gŸ�½Ñð#FùÛ 5õxDà=£°ˆ]È_Oñ¬}Æ·Ak5`µ™ù…L¹¼/ø0`âºD®DXI6>=m„ˆ¾%I‡L¨˜ŽCCƒÚcà BÂv>$ b¸Ú!xXÃã@ém|\LÛbÑ2Cù8¤À3œ‡Ø-…•Ú˜Üó!›äX”):ýK¡è›„oZh²}•6é.òýïLVÓÉg�¢úÊ•fGN„îˆ5ž[…LZbˆÆfL¯¶a–(_þö"0Ác4Öpз^åíýoîÿùÕAÀh€ôÅ›Ãïw`ý€*`¾Ç£4À¼1fÓ¯KæÄ-ãA¡ÔÁ$'tQ¬RýóŸõ™æóû~f]6kvÅ0ã1½¢eZi_m’0¸²Òûªê]P—r…˜Åm;/f¬9Tó¬S—õ³5ç'wÒ‘½Ì_ÊN ‡ó²ðá>Õ^éwçßÄ”¡›ç41«;ùUY²‚äÓ—´.iÃ$šò~ —òcQl—­e|ŽXp°ðõ>…—Cƒäå€q¨nÎFò»4KÊé@9u£òüÙÓ‰cFƒ#Wu¦®Ô|nLØ /(Æò>wÜŽÏ¢§K�Ó;²4«£õNÿ‰d™P€>ÉA tXƒ>cD~âMI5Ú<—^J®/ìÏŪ×_lUg\=ÊFö!ïS‡–(AýL²Ž:ÞyS)¾),HB/ÎÛgkp¾WUª!È5ÉÛ=TÆçàt΢a)ç…˜T8wèKã+ôm;Ù®šSlÓCŒc³V$lïÐZÔIJ÷ñc ÏœÙó¡P1O‰Uj6‘±6Lª­(ø·,ù\QcgÁ�gªÙ>nhG¨eÀÝ.“ÄÅiß Ç‰È|_ÍÈ( 2JØÅ µ ëJÇ�KƒÈÙrêðaï”&d– zÄ+MSa2¥=¸eé¶Ÿ]Q>18å5òQà§äpbe?uà™†ä枢8ï ýN^«Vìjð½}‹aÎ+z˜ Ç7§eXXÒj€X„¸ÉÓ8 Wç¦=^Â50±—<æIaœ£Ðü×èY—Üd(·À`v¸ çÃêЪÐþz{@©C‘É¿¤¸wŠ|0F¿8c›&êÃÃTÂÇîšdjkÈÛ9Ó$�#Ìv*°ò2ŸsÂÁJ¾ìú®‹åcÔ?ï-Ihë<¶Ÿâ]ÜÍžU�þÂ2+y+Ö„ïó\Y­iݬsºib±5æ1gÔÀ¯,iì„›…_sve~š;;ðv1+ªp²Ù’¤nŸè“#ž·o[ðH Ç’+¢i(ˆÓx%Úè Ķ—èÁ“¼1rJèÊ3«&vxRE¯D™XõÁ\§¡öšó,_bä~®þ7”‰¦¨k¬L^¢½?o²ÝTCÌ©jG9 N Ó‰ÍHwÍ3LH VIŒ yµ¾Êg6ÖVoÍa‹ódó:§Xc´Âôn´‚iõþˆåfò·iôœDŸáò"ÈbqP ¶å‰í"ƒ7À±r“3’y]§#{¶EIÕ.£…%àL.dÄFó¿ÓT^pfEP“fª]‡‰‹ñC§_¨Ÿz+ˆ+mÞ Lò}v]ë=ŠyŠ•ÉS ®`šëãdK ÉVkˆÚ²ÿè(S èuŸC vQ°smŒ§ašsc¯k�AO |}kõá×ð˜‘ð}Ö$§ì}c‡kÒܸlèC’bÂa±Ÿc5$LFT+Kó}çºa£Êj¬Z”Þ"Q†óå,¬¨ðc3œWØU°Ê‚O¤šw¡¿*S# Òò8€¬@*vc"ÝùŸ ´RöXL3¾ g3öެB‡HÒœw‡v ðè|®«£Auá܇ õSñÎoZ¡–‰—Šc#_£ ßÅ™lå’c±Z=“g|¸Ø y»8Fn†ÐŽ–ÏF¸Z²jô1)-bñ„òH¬=%»!)›xR/¶¯!\Az]]µºŽµ¨Õ…ù£9ÉD‰_Ñf×Ù÷d§ü,`ɺàB—äºH©¿U^cû­CF6<UaéÏU;çַد˜¿>"öœÛ››Éä-ô‡ãš¾õâqðm ïG)L~—ŒôõˆMä Ú®í~ÊÃÓôÓiDº� ǦpO•™2W¦ Y=JévEE—¬ ¡x1»&‡KX6Ý÷ç®6z?'ÚÏB:»vnæ ^‘™¥‹ˆp tÉÖˆšˆQ)Öóå’²47ñ1i«($1 ƒê!³ñÒÊPVâãk¥ÜP=ìQ­‚îS`(ÔÕÎ[¢Ð]v‘´“$\ ¯d8jI2âLYŸ øu@É!ÙÓŒvº/Í0µ~¦2*4ujöšAÇ å•h¯ý?†ÑŒGQz]1®.}´^íeÞgØsêÊË÷}×ñN�1˜ýIÃáýåP§ÂÀ»mÑl¬k¾¤8£‚�2½ã{tiÐ ^Dª´)˜©!¾SÞÇî­ŸZ_rUÎ#tfµ´¡€Ñ’ŒKYDЧæõ˜8 BN…`)¨ÛÞ=9ï½gÜ—î¶]8ˆ³Šb˜Øá>yY=ÄóÃqWà zx`ZUL fa$É¢åñ¦ü™{¡"DÔü aŠßüµ^!ŠAQ¤4rå} TVñ…AöêäÆI¥à®Û„_øÔM;77ipn½+Ùm*Í3|jI¹tqÊ CÙ‹†®Cï\½!þZÐ52¦0åžl¬»C_»Žøz%fb|øˆ—D²¬Am’œ °©ù èUÙOl*uæÿYöÃbWšâÁ9ñ‚jÒæJÚ‘¿Ôâõ¿æf"åð9¹ ~'nD†'˜o„þïxÿßÓëãbõh½Û㯮5œ%-HßÍE÷®Êcì`‰¹ZÙædS$‡± A²Š5ý]wm—+D3òj·Ç_ñv»Àéî>ZOí¼½ÒÆfxZo¸ê<¤ ±3¼?´”.ßð0ÊñlÕq#uæiÁg9…/,¶ÌDä5'NÖ*vìÎn…a?eðþ ³r÷ÕØ+ìE”c¼¿À¹Ã]¾r—€–U9€+º+õ—ìkFM1ý3±¯ê*äZÌìõÈ­¿:üþˆ):—Ñ®5Èkñ–ôAÿ£ñï’ O{0dª­µØžŠ3¼ú=+` ÔßË °d¯|ñI†˜ŽíV]•ÍÖÆkŠ+vyf§ónÛŸ¹8*®³?z{ˆáf?ßPÄ%C;`5j úÚli¼‚ÿ~è3Ï^{ú’xIÄ}ãQ¸êæ¹ß€ˆ/Î\øÇtÿ‚ú:óó•¯PXØ·¹^_ËÓ;uÅd¹¦Wt¯3x_a_¼ËÍ*î¥êš¬VmIØKŽœë£ÚÀêV_ûÌ›KëE ¶ˆµ@]U¥È’oõ¸æ*A®'\á`—>–Ø À¤ýdl É-¿]ÜÍÖ±s0®1à®)Jš{ÊžfÎï¤Ç¸üî"î¾dk®)0cݰ Œóúhôžû;�ùήÿÎ2Jîñ¸ÊmÝ3J¼h|ÎÿŠC 9bÐû«ðåívi»æ'™_Zb΋ZÒNÓéSGdÇ0,—Z\û <)¦è³«EK鵃ç-•É•í3¶ìMª˜wŠºœº—£É’ÑËdú|Tì2žˆýÇÌh«Œ÷VÊeîzßÚå(Ý…®_}¨T8"ªä®'iðŽ7)S‡]‰[v9r¼I/Hp:6{ïh™<K’TCQÄ’ÈlÚy„×´Ù'Óãëòð_œQìÜ™±#.~Þ _wá|ÿ�C@P.e¹z¯)Œ?PóMKü[=éÁ‰¼Y…Ã?Ql«?ÓÑVši[2»vùÌüüâ#þ¬„4Ù–Z_ûjhú˜)%8Œ×ê…ˆÖL~ÀèD°F(¿ñ‘F`óK»Ž¶˜˜íÚÓ†› gºÀÉkíG„&ù‡§æ×nD@¸r)ѓОdé£âàà0½’Mˆ˜é÷8ˆ=SòÉ9ºKQÚä¾À,1Ÿ¹Aãam(vz»váKü0yéÚ ò�¬ c@ÿâòû.?ô9õ•4mœ¾i­ú—2™Å2öÁv2¸ÙJpÜUVv_ÿúþæ?៿ÙÃVZendstream endobj 34 0 obj 4824 endobj 42 0 obj <</Length 43 0 R/Filter /FlateDecode>> stream xœ½\ÉrǽÃú{œVí‹n–·ð¢p˜‡”$@RmA)#üþlgÖÒ•µôÌÀ¢ …FƒZ³^e¾\j>\²™_2ü'ý÷úíÅ×O¹¹|ýñ‚]þþ}}ñႇ—é?×o/¿½ÂVþ’óÙk-.¯^]ÄîüÒúY\Z©f«.¯Þ^<›þµÛK­f®íô|·³“Vëéíº¡üô.~i´˜nwlöV1ï¦×Ð˨Yä?cŸûÝžÏJ(é§CK͹Ÿ^îä,õÓ]ü³V|úˆsšÙW¦7´ÿ»<|7f˜ý%v²°73½‡ùýÌÉJìä}iû)|4\M‡çe+w8‚˜­Óa«\h!¦¿Á'aSi§Øi¹Ç¥@Kg§Ãò¢Œ›¶#å*7œ˜|û�•Lñ ÀÎÐEæ5EÖð|' c~ú¼¹‡_apç¦g²tÿá ~Ïg©§Ÿvj–dK…´\卵5³¾ÝKËfÅLj€;#«^σO/Š<_î~¸úã…´ðï<W7�—xœ¸“UFØjŸ›í¹š5‡¡õz:Š% ¦¸/˜Xqr ›™m!¬œyÁ&ìíNò™yÆö·&ˆyVVW©ÑžEõi$?ò÷"Ÿ¸bêéû‰bd¤é˰äÙx5=ã; Gm0 6åŽ�HXX¸’t1·I~Æ“þ ³2çä* Dh{–a¯e}Ëçè Á¥ ôvÁÁ%(-îñkçM—õ*—|x¾#¬$lÈdT‘vK\‹`pÒ(W‡ît–€t‚*’´m¥\BSšlk¿Ûk¸€†ÉˆÑ8'BTÅyÂjÆäžo‚Ô¬”á†H@x^‡rŠjF¼Ê\̆qŠÉþ SÒ@(þ…ˆú¦€1Ï«•¼Âþ°î¾02ó~¿+²œw{‹Õ á_­Šð:ŸÚõÚ»Þvî}CÏx}‡‡S8ŸPsÁu…Ó¤'_TêwPƒÎèé)êCÅ´ÚÖÎX#:Ÿ (Aå fѧCñÄ9á#\×�Q8a<c4jfËlÒÌ í(þ–ùŸÇUîƒiPB‚ØÜæpwã!éJq~*€¹+:-q®Ü±M”æ>¯Ë °q%ìÇLÏtùúÄFXŒƒKùÙðys=¡1ŒÔwVÈ»7SNË»Jk)†©U‰‚ó³`ÙÆ†žŒÛëŒ@…2÷ú K…_¡ò]ê;Šóï-X)>#ÉvÊ$P$ :eå½JÌÁ‰WZ3 ¹PÆáM’\ßÄè¡‚QÂF…öµ)&(#z‡|\¨�É!ß–&T·!» B¤`ûTvKº­J„â3f€ 7[ÆÄÊ¥x{4;Âá/ÃI˜‘œ(ÒÕfgõ¶‚I½°v,Os_ˆU“¨.Œ;y¶ÕR\kšû 5è3àSezrÃ)®ââAb„<tç>^'‹¬`¯Eæ`ûòQ¡b»Å°Y*MàN,ö ‘^³W^²Âa¢�?¬f–(”FÎåZAÏ6Âm„}ÿ¿`o§<×të(&Ðkx8”Vîìà#:'™)¸i<õ ³K©@c� ]”~¤D5ƒú).CÎN3L¤¼wôÜɹn°-›E³4g;¶SpTpÞ§Å+Õð:$Uw=ú}µ2…±o_”ŒúFE£Yäàž¬ö4¯ExÞJ™Õ+wB¤’îoÒ1*C:}Ž × ôYÞ±ž‚ö~e‰Ä§èl#%A¸|ôÄ88ó~à•¬€�#¹ÿù)ðÕ>nag À ´-0Ù¨åæxQ» hZ“»'‰Ò®×¾%\ƒñqSÌ]’—=É$ÒëAƒê¥¨J< ¯Ÿ*K£BÁyåC}u–Rõë`Á…‚¾Û¡ûžÅo"õfÁPÁT ²žG­`ðD”ÛoÉŸßäOqò:ÔbõÌyñ˜k’ŽATH%ê³ò%‡MpÛSïÚ݉NpJ¡ §c+õú¾�åО¹*¾t 8Ú¦ÐCîäÆÚ†Ñ‘|èÄLüHÉgŠñàV’uCúnÂ÷æOÒXH{ÐO÷fÖÀ<Keéô9ÊŒ²bB5>F‹ßuÙãùi°C2ÐrK c4ij IƒŽ`†øÖB•þÝ:°8F˜éï;'a‹ÊÏͲµø5¢ÞxqbŸì"ÔbÿÚÎVÚ0xLÊ?{Ýy .0SÛ‘ $Øp¥´R°y^Y'iá˜9¢S­›YïMJVÅ>–<”8)컊†æ¦ý­ öa/›*0¼Ö`KœQ}ˆ•ø3#qÕ*œB à BÞö;ƒ6»ÕI®sorÜ šjÇ/ o~Gâ‘Dh¹v’b)9Àwf!¸� «Äp¢úÚÛÛ6T›"‰ËÝàN ,Pô­l‰H!Bð,¨X³mVÓåtåŠW-£-ÿ¡ŠšB'ÐgŽ}6`g«)Ðm –Á’BÌ—!hÿš‘ë¿)€8_ >à „L„n})œP è@ nË-x‚Þ\K­•ÙVÞÈ6´ë”h‰X9esôì¹^5W¸xPjÓ#&~Í7»h½¥Åô É’ìù¥ÇX¨4môì1Q2ý{wõͬ gîziýŒâlÃcDÆlÄY=pÖø#iuG§XYãh¼Ã¡28Á{0Û'�SòáIŸÍÕj|Æ1½¯€ ñ0ûÂFãÔgú¹|à (lz>ÖæÏŽÐðïµ±™œðHBy=<óÎ)âjȾ1K`Ä,½:©åÇœé‘1!Ép4ͤCš)fÄ4ÒËm¤,º³÷qy˜›jRø-ç„/z?¦-ŽXC^‚ ¢�µJZ‚ÊS}>1(Hv]ÙyÁ³ 9F™A/ËZtYSKöSgb'bÀp²ßÆ7 wŸSH˜ÄÑà1.b˜€£Ñ™Æ·çpK}ÄHŒ‚¦µïÊÎ8ÛÆ¾B2dœ6ì2\ø×Oã£O{­cÍc5¶yò9í@. Ú0àH½ïã(ÉøÄnöŒØMŒñ4&:ØPEì?I:¦€PþwçØ;‚:_Ï­Íϱx˜!;MµîãHŽê ÏëƒÎÙd ¢$„¤Hlà@@ο†íWzvúôR´eAr¢aŽ9ÉÚÝ0ìµt,¶‰-£eÝ$– >M9‘{:®bè%UóûÛbȬHY/¼ËŸRDYÏŠ¸—�m%Ålwˆkž,ô%zm=Oc{»ÅìšpëÒ•‰W«Uå Ë5ð’üà§ï–2`LÜÙw«4?çn¡×ÊÇ~ʘM¢ªé¡$µT7²)#[(ä.ÀÈ$/#­g¼Õt´üçÑáä¼¾¯‡ê”84–ʪà‘ý(‡4¬ÙViCëÛcœZz]‡ £'¤o-{Hñ™ð·¶$ççÆøò5Hĉa¼.þ•ƒ=~ÓdÒ±£KP¼ßD!²U}ž®£¬0° <Û°S@0O~¹‡>Ò0·ú´KWÅ@¥ºãeÑ(9NÕ¦êú ”ãàe©Órƒ )ÌThjÏzF_×߭ç,‡”ƒx^žCáa²^Ù™3Mõbfèk0­ ]Ò&-Ÿ¾=#{'Îg:?Uké3ÉGæ‰fÌa!>T4Éù(Ñ*4ØgYõaƒJcÕÙáÍ`ûʦÒ ãu‰öÈÅ8fEn)…Hét÷ÅÓ>)b$H)?£€.ç%O:Ö¯‡ç;L!¶Z7]ôÃ8 ñ3Kœ0þmx�ÎÕÈ=Ê'7ëè_i¢¡E¨FJä_‰Ð°¨-~RZ’MVµ I‰<¹ŒËÄž*"³*”½àÙ;×!!dˆŠ>µT(£ [€ù'm˜XKº 5IŒ/dI€»é¬nhsFXw€Ù·£š/Œ¥½à& KØL•Ô%¼<íëùƒQ(f‹vÃðvV)bǤ-iwñ0Eô hi‰ƒ2#9»•°ãmuf4…ÞtMøÝ19kÄ¥u5ê­€§HRÄæÂE“ ›¬¦Ð¤Ÿ=lù«–ÍuEG¹J1ä¦eåºýçåÒ*Û_ÄAŠ‹×˜8'×#$–­H*ìa�û6^ Ïø4&œd,Òí0¢ÒdcÆJO>%ìt™!•(Z3^w¬ÏÔ-¦,¢-¶M†¼Qƒ½Yo_%—l±m ñWw ñïq¡-õ31#¡¼«ã¦‘ÿ*ÿ_sÀìg.9Zîºf<õÙÜ-+õ+•Œ8rG¹õ˜’À8&¼Rœ#Yë<Â05ªg2UðõÓHSæ¤Y]o^š’øZù²¥•¸”WI߉Ÿ ïDæÝZªëUhßBš–÷a»Ôëk-xôœ$¿K°’Ö‡n„rZ«ٸ#OcÂlBŸÎÆ$¯›Š¤Òº)wH‰»³¡�´)ØÅgŽo*„¸<{Fe·rÜqõ*»ã„›£2øƒFçÇ:g9€-Ð`b¼´¤>¯vAiÕá±×„>rÔõóò†¾¶È)䆘y*:sÖ=jÁJWŒS?2jD£øpPqL‡â _ÇAë@>òì1†Öˆé¡ÒŸ¡^ޤ¢€€`žLò’¥ŽÃ»Ãøe›Lj$>k‘ ´³¨J"Œ(§¥§I9ó2ù¦ÒIQÿ€é4}懄ˆVJJ)ö©--æ wVÖnd|ÀæÊwDÿ.c3}Ìì¸8òà%”<ë l¯ìø—dÔƒ©Jí"ë³?W½¨Bk”ÊÀÏ©©ÁÔÆƒ–ãu÷ý@õ÷Ó±B58é¦}D•+½i¿÷õÕÂG{nà†Èüó”_”¡tõäK« Úí¯ö4Ï”l£l b¯8g]dž-7L…>è ü†Ÿ¥÷¼ö*äÎ"‡™ëDHiFó@΀ˆêTEP®ÒþÂE_1ƒwÝ*¾ø„+$ßιT‘‡.«º)c­Q;=Så!!}æuNÕ‹€“tæìLEiþ «i5ê ¯ºƒ¢¥~õAí(v-Ï ÔÀ¾PÜŸçP`}¼z\¢‹”Ëpð-™iï°00µ_Ó«Œ“¥XÍe\IG'TÊý1 î’HÔYÏ<›´¨’è[áÐ熣 4óO8šÓŒgØ{J©¢·ÕÄŸ/®~yF2k+vN‹jÝõäûÛ#åÅŠ»™ÛúýHÅ‹B65*­Ø”Áç^°Õ=.!ÚÊ“é*€ÚŒ ‹ô!1àa•Òa!û£åZR»ó°:ë¢ �›žV†ª÷|M¹Ä- ÍŽ’|‰BeŒòKéqý QÕÁ ž³-‘Å4(8Q þhÚÐÇå1C±·3áÅò8¡Ü³Á-ûŸsõÛuÛá»þ‚l´)N O£mí¹p–¹Bhªi™\2¯ÚÒʦԿ'èÖm¨3%ˆè œ*s™­zûÁÓœ´Ý@`²Ï»×ôøŠ<¾*¼7G_t„’Á=Œüò¥56‘áaÈE‚L�Bþ~SµæÙ(æ©Óe¨l¤í~("ÔÎ|X—×6]m¬ ª—Çk€Œc4Kg%~/F3*?^{uµÛ9ŸCb8îþ|³6¯HÌ2JÇmÔØÑÂtò–´' ÏKº„c]80E_ö…¶�Zg4ß°íKVÒÇBraVo­“õ9½¦ÎhÛ‘‰;=ã½lÖ‚åËo€QÀ$ãÛñ Dþ1:ôþçhÅaQHÃ"eÜ üÜýʪV"“©Èg t¬_Ò•Ú(u˜£Þ}ê¼b¶ë‡ôK4ùQW¬pgÔtGÅû£E°õüfR›ÍèàOÚ†d~hÐ8¶L΢N\ý/Ëlðb‹³^„5ß+¤æ•Þm‹ T}£ê¨ÌIÞóø=a1_"‰ ü퇻Ü.ó¶¾×êˆÐ°#u;ëÈsú =ýa—^E–‚/¬VbtëçdŽª•µîÙNƒ1ÍF¾­¼vy\ú9œ€4SÿP­Àµ—ðw\ X%^I%ÕO‚er+:ÿ׎}åkS/ü6Â1NTÿ&IüÍ©úézë„ë†Â2ùÞÈ­>ŸÓÉzŒD‡/߇Nßß‘~fa%Á^½dFÑ‚hsîQZ\yì'"RDò„Q%§S§|ò󺇸|©T«- ¿Mõyå ‰ç¡5[Ù‹^j.JsèåÝe¥¶©ÑÖ}Ê¿ŠÙ'W¥#Fe*]¸¤Š¦Ÿ|0"èS)2€Ë¥áß{uñWøç?;Ðþñendstream endobj 43 0 obj 4746 endobj 53 0 obj <</Length 54 0 R/Filter /FlateDecode>> stream xœ½\ÛŽÇ }_ø#öq&дë~ñ[ŒF‚�A” ü °´+¯Æie],ëòÙ!ëÊêfíNd90 »«ëJ’‡¬ýùR,òRà?å¿×//¾|,ÝåíÛ qù ü{{ñó…L-.Ë®_^~}­´Ç¯ÔåÕùÛƒ¼Œnñ2ÆK¯ÍâÍåÕË‹ÝöW?bŸñRÊ%ZK>ÐeXL ÍŸì¾ÙÌ‚vw·?h߸úK;·»Ù”ŒK0f÷n‹QFÇÝó½^tðq÷voëøVµhv×õíÝ^ùE¹àv¿ìaL¼éŸ¾éÝ=…o— ½µ»ÛüÓY-JûÅ W>²ÐÑ«½X¢wÒÔ‚õ»gé¡1ìN½é[œ‘[´“u,kdÿü^*lIºjs×?¹ë¯KGZûÝñU•Ìúü´ð¶äÙ^ËEDmwq)n Rí>ÀŽiï^ôï0¬†•Z OaÖq‰N§iÁc»€í´ð5™ Y™ë±ŸYi`L Ë=Þíÿ}õ× ­äâ@l®n@L^AKQPê°øn! Š·ôûíˆÚY`‡ÜáAÂè(´©ßãË=ˆ©ƒï^oÞß·u¿ÊÛ=•H"Bäéñ®ï.Á‹EÀÎQ4,ˆFÔ›Vò RÓ. 4°ëÔîÛ½Zà¼Þ7[ÖBfð¾?Emq -ѰG{Û'@>:=N;0 ï˜½œI¬ÓKPÓ£ƒå šîéŒ ùý¾õp“~)aÝ(_>6ž‚“x³ª’ö=ö%•–~÷ ÎDT%@?„ljlÀ `þBK~õ·o`xã¤U* _ÅÏä‘n°-@’K‡dÌÅdNe¬ Þa¿x+Ó`>Féû÷ðPX-�Hš UÙH½˜$<õ£ý£c^*L±ÊФ€T—z‡¿´TNõyž*`)L}Jfý†R:탦“|³`r:wR¶éû6‡|6+ÃáåâU=š;ObB§:èŒH‘þ¬h"Ìo°ÛDé]ÿ6]‚8‘ÁÀï.A Ù‘²¿Û«°x!wÁ™Ôt¯ E¼îBü¥q‘Ú«-R¬új³J¢W6‘HA(4µL#èñ³<@†¢ƒí‹.æyƒ8´"ÄÛùŒ%à´mUo+em¡[°"vì ×¾îŒ †vÑPãçÖAj{zC•ÿ¶M;rªY3}ݞݭA _ç>}T,ŒqØxÓ§8lJ«¬h¨�+W ©dáaãà|ˆ-¯k�¥Ûš!rÎ(]]äVxš6Üh*¯ºøÜ`±h5ìÞ‘jE²ºÖB›ªqXࢌÄòËÑ„æùXÛîm­d¢A~ÔK„üØå€œtë ­ST0FX‰ªò�´ÖQá!ß#EpReÞPÑ0z·‡–<ìâq$MR� š¤AÙI[rÊ*€¡tá XJýÓCyÝfBD1»µADV¬¦‹×2I'à¼uzå¾¥9B?Dº¸YœŽ_t‘ºæ`è]#øØ¼·ã'’Y¤rCNf`o ¼÷aƒ بßÓ+.)1=ŠäG— -8ਠ}ûPuž"ðÞÎèâàšA}èÓÓ GXœÕ¸ªíéŒàA>†=X�¿ý;"÷yòjâÖ¥ÉÀ?Ò^skêŸå_Á4g[Þâ¤á¹Þ}·ÛD=Ù´¡¬4ÔùÛÅÕžT{ˆGJD¦aHûq|ÖÍR2àG¡éç PÖ'Œ˜Ú#"§}Š!d$½“¡©ˆ¥Q¼SÔQi]ö¬ÍÇ%4'ZZwœC‰Š<%6è=ë Õ£GÔ—"Mùû ×¾ÛÌÆ_±#Ú6áÀ?çcÃÏÜéÐàpÂÿP˜yÖaèx:&7Ëùˆ–4[1 qwƒŸÑ*/ ä<-C8tg6D‘™ÁEj0²=á/ºÈ!âJµ8!WȆ¶P);°öÙ‘ õ§XV(à·~îöM7r«ÏÊn“§w>eÛ,'þx—i¹>g´þ2lwqe<'žXÚû™]nTS_O£¨gø´2E$©IšEI+ß;¦VBµÑ·& Ä¡³ Y(žh˜µpqí¥+xj +‚¤ålïpL9�#JÇ[öD—}ŽÍî£�m4‹?›l­Ÿìþ„.f*š&":0²‡§\uÂhºd^'’Ò5P5’ý‚Ñ=b/òaÒ "¶QÙ~§Žñtzº (·uªê)¯FÍ+uFÕ•Ú yÏÊ2®LjtõŒøv×U!ÜÄq·…zܸî}<ïŽÔ⌲¾£/`Ç‘àú›¢€bç¢j ¯É÷Á ›¦‹¬êWDÿI¬×Œ>Ð~ `Ñ£ÂÀŒ„§ Sì/¢už´‚ƒtñ‘…¯°ÙÿÁª§¨ â5ÝÐóÓÐ 8{N ó— /÷ÙiWÞ4L /nÆ#ç)Ú ý·òçÈû:?Øø‰¬¹økVډͯÐ(]ÛfìœÈzrJ4œF´ÔºuŸ“*& ¯Iä+ÇÐW;¡Iè+',ÊÈó¶%?BN‚c; Ï¿$& Îì‹t`['‚Naòˆhè¼Æ†Æ ã@£Qø2—w <*·²Ù@™èó‰ŽäÌP!’Õ°¬3Ò Tts>7ÀâzÀäMƒš¼ózˆÀq€Í”¯gÀm’m3Š Æ)×\$q"tµ�OÐù-=nõM9ªdcä•]ù™ZÌf¶V9zæ�!9ÀŠ© îÑ÷ÚðØQ"޳MZCC{Ï eïlêˆ&Ëçǰ‘MÐqI–nC§[Ò,X‹ ÷Ù@æÐ ~?λ¼›6­×C eMc7°ß˜ A·NœÃcy¿r•8œ›; Nš¢¶ìÈmkýJjM­ôS‚UNñ9QŽÒ-dG7Tq56iyjêÆúä‚Ñ<�ýh8e2bcÈ 1w¨*Òeé×¶²ÊÒëÑzBqz‘®Í" Cu›ÜYæÜOÓ\ñÖ™�6–…$Ž™HÔ‰¸s@PÓ’—Þ»$îã‘‹ªÉñW®}ÉÔ¿ÆÂ#îidõ|OöÕj`$@bøì*yŽêžè´x~Ä™) @À*a®X§ê¶tÔs$c¬š?á}™9Å0¼½é%Q&Êrêæäd®¤Gx¹FáR±‚sÉÌŽI7Lÿj)03-ãh÷¶}½Í5ÐÁ‰ô;&0IØËrk=\åÛ»… ôôßÏA2M%EÆi#qÕQi°À[Ö>é´ò°ë–*Ì/YÄFé!ÁµÓš0통±måc"lÔðÉÅÛþ”hä½Å$®ê™cÅb« ‡Áž–Œô®"°Ï%ÐR37Œ‹†ÖZ'›d&qBZµ°y[ò=¯ƒåû‰ã@lÃÙÌNoþd÷÷”úËj§ùzÜØB¤µÈ mv[h1?x“CbÎÖ%^cÈ[›½Î©³ö^KR}…t†zp€oXÛGŽh“†ÆIáP­Ëvõ*¦¤ë†Ì­ÌyÚ´3²F™¤PggÎc– ÎÖüÉîÛ}HÜw.Öp"[åoµ`x°,åÓ¨{âµ±U‹éç­ÛŸ³¼0‘ZgG Ö.ÙmD Éþl£¾4jLÿà�Žw G ðЕ¤4N·ß8v3¦œ¿Ú NY0Vú#v)R Û»djóRnS{ ÿ§IË.ˆ•ÄcKéô8‹ÌèQ%ÿRÓ±LaV2ÐN›Z•±’Å  szhAäñE Û‰ý8e”õ&¹GKp\Ü•èW(–›Éo±è'²ó9ú±ŒÂp¾FÏ]qþžs#íɆOCÂGÖ˜ÆQãó’–ŬŒü’‰„uŒ@Jxr°xOü=¡$ÐóظfÝó@¦bò#È! µSÂT-EuÄ8³†Tšõ•òÏÌ+¨x{Tñ$yŸ’Æ|>bL䣻ëTøÈ±ù¯á_Kó&™üD*hzv´*—6Œ¥�+a<ñcRr Ž·0Ë£U¥[V¶ñÚŸƒ]u«fû%+o‡t¾ö[ãœ|ÛRÔàr%WÚYo·ŠÃÖ*hã ZQ@.[U€ÊW *r…¬’£²{a< ÖØWÿPñ _ÒŽ àˆ¥ ¥TØs ÀÃ|6h€Ò¢Az§Uâ%çGñ@¶£«2LšŽF®îޤQT'_˜´λÁ컩WfµTdæd¾ü€áV”¥ZGV¥Ý”UÒ½By`ßoöquÒ¼H`ŽÞÄÈ& ø3σ çºf! ž1ÙŒšj,õqŸäC´ˆË=´2œR �¦yÎ28ëjŸHÄÃ,M®#Tkþ!d”aü�l±ñª Šìû™Uˆ~F 瑀ʻÎ=e«<÷3”¢sYNNÏ­£+©8?±”Ïs‚ÃÇÈ–$Z!Ò›7”bé›´NÞlªs-ávb07¤‘ã)aô¬Á¨à UyyÐxF¨¼Å z…èÂ]ÀNpvE–_Uƒ™£a¯R¨òx*@Øýk�ï]Gg²T–¶©pßùœ]×ÒzŸBDxmPB´CAWnR"õîïy™VìDL‚‹—ήúP>úJFä‡�ú!ð*d(Ž¡¾Oá 1“N™^35ÄF¿6ÑX¦x‹©ذ2¶%ž3}¢Æ:cNà­ -4Ý€Ö¶ªs†4e„ÔxáþƒX÷­ŽYQ©nnŸ�z‰µ°÷·çýé"õ‡úòìFüzÛ¶MZüäm¡yî†@Ôk’€Ê/볺ò„¦ØÛ€ößã½·U5U)ãj…ðÓƒ›ÝJ"U )´p”vÚÆ™ Îu’~ˆÏNœwÌÓI$Ìrȳ…¼“äï”±—'&¹‰â(lÙLKŽö3¤•a•A9Þ‚MòEYäRº 2ÙNÇV¼Wöþ‹ÐåŽFw¼IIx´ý©¼\PôV¬ÜøI9—o9�âw«=¢­ho£ ¨8ë|cŠ«éú À\È| Ÿú‘}³ÁÄõ…2PÞD¯×תáüiŸ.8†hæ¹beUºû°kT>ÈMiN9wVÖh•Ä£IäÕ¥Mx…´UÚðŸé×R5Ý›•}oW·:V>¬¢L€=ب³n‡¯ß(,,—z(Ë\C½þ\«p¬Êxãƒ\#"Þê©°$W,ÍZõDö» Œ·‡×É@%¿{3Ãi˜¹¬’°Æ˜Ïz ÈJÂ6Nè°UFšwNPà~>5 œIÙZD’Ú™"m<—¢¦É¯ÝVk¥C´]$ØEZÑÜRÖ¿Ý›ÎXüÀº€…ÜtC…!Kƒ„¯³5SnÝ*­i;ŠžIÅô¶SL…÷•µ=³?°âF²VÑÞXÉ¥3'wÆ­ÔRú;dkJPØ} c@|ÇTÑ–Ýæ³‘4½Ön¤ÞÕbùÇÛ×Ù<I!¸mžåÆAjÒh"– U•>d‰Áz,¾dhÙ°³†Û?R;s¬~ÖXÁÓ4dv4Xí1._>7Xó kl¥öÌЛeŸîX@2ŽHBè…n¿N·ÐAýÌÚ·:¥Ë¼¨å¢“ç…¹W'VB>“ ­mŠ75ôIg¿bƒŒH—ŒëÓÒ—ŒXOœ¢L™Üµ4Gަ¹&÷¤Î?G«:F>¤T)º¿7¤¬¾e4'¼‘s¼áUëÖA#ŽœÏUk(ýAêÞl[™þyþ™#Οü³z½§ß¥Zû õÂÌo²~Õµ²ï'ãuFÖ¯mp©Ó•ðsí~›…Ì6«Þ! PêYµãøbr-õózÍ»§ž™|N¤¸Måâ¹U Uk³Õ~tqY'9Ây€ù`þ€M‰$„ž;L)Ñ£b ´Þ±9@þ¯º¤¿ú’ƒÈÖõr¬Ê¤üܨüw&V…£2ÿ—i­oj`&^rž9ãºw‰»®ÐuéºU>õÛðë 3�Ü_i9×ó9E.ºuË–Á¨$„àZ¥ÞM[.¾þóÕÅ?àŸÿ¹6ÐPendstream endobj 54 0 obj 4635 endobj 58 0 obj <</Length 59 0 R/Filter /FlateDecode>> stream xœÍ\YoÇ~'ò#¿xÖñŽú>ŒA8†ÄAdú)Î%‘Ôš«Ã<| ÈOUŸÕ==Ë¥Í ¨ÕÓwW}uö~wÊf~ÊðOú÷囓gϹ9½º=a§ŸÁß«“ïNxhqšþyùæôOgØÊŸr>{­ÅéÙåIìÎO­ŸÅ©•j¶êôìÍÉ?§—9Kgýt ÒOo7’Ïœ1;Ým¶|VBùé&•àóùf+f'­ÖÓ~³• Úr1íßÅj£ÅtU[\ÕÚ‹<Œ%¼˜5÷Ó»ÚòÅf«`qBÛé[¬åB9U;•uÞ¥ÞÂЕ¼Ý°Ù[ÍaÌW¸(80i§ß„ZżK Bñ¼®i¿ÿ þãÌ콜~بYZ%tÞ­V|ÚÝÕòNmg+yÃËÙK?5 Ò"oa(m•tøU2X®4Óûº„4„5¦#pÚÒ‘ VŠÙ+hw®™ÈïqÙ|f²éõ:Ì`¸Ê{L£v†µ{¸0aga`ܺñ[lkfm$tû×Ù'RêY8 ³W@,ïÒ®yÞ NuÓï—Z½«gQ?ñ«™9'5N²M³l¹Bªðq²Ý«z§å`m2gU¡M¸Ýe%˜Ÿðàì̵¡-^×£¿ˆ lqy!Ø–œò‹Ú`_–ðfle)âδšæpVÏž Þðœ»Ám©¸§/Ègá½ 7Ì˘ѸR5å=|ÜŸš>†…*6+¥è÷×1k„€Ë”x<LSˆÑMÏ7 ƹékX»µÐÎ »ÀvvP·7ºÀ¡;ǧ-ö¶3öy±¢³ŽÉpŒ0¹fø)uK3JL—P²B›´ “ÜçVû0‰Ú.ëâÍ$·ÐY*ïtÐ)C7x‹+ó¡ÓbÛaðNOßoà_Ï€–ë8-°2%8™&nÛ «›C‹Kr³+û‘Ú4 np*ØŸ!G˜¾ èH&{ç �m:Ç\:ˆ0-^¥ÓäŽ|ÌÈYËg¹ÂqJ;õ¾ÉȈV´FN¯ÛËCºÂek9#€Z !W@Í‘27³>CÊaLA/ĸŒˆePäàã¦+Iý6‰#0OO¼œ\Üšäz|]ý ¦R_ì²…:Ãcè’+ñÅÎJsRwE¤Îøa{) '„S¤YîððQÑ>ƒ†L(ÚcHrãe{#'TÛÖ]ÆyޝBÍÚh&¾D,ƒ«6”ÚÈ2S. خڹn——b¤Ã8Q‹ÎiàóLZ^“xŸí¬$'„GÖEˆ‰€Räh.éD¶ýÓÆƒ®!âíÖzD|=}ŽTâÅàâ­r úqh°Á؆/î¡ñH +WqÝœ‹0ƒcYî;ÂWöÀQ@šùÊb=!á¶TLJ8‰”"dZ†øe0Œ“µ$ ‡Œò~а® òàr-,-Ð s$E3)–F¡hX#áøã¹í6ØÇÄý1@}œ(×ms]¤Cƒ`L!ñ2¶° ¥«¹î¢Ô•kÝm)Ý•¯_•ºûRÚ•¯w¥®Œ2ûpÔ0‘w/Ii·-V ®¸Nxôª!ÛtU#ëM½ "Û‹(ÒA“e†S^&cŽ©2©$ÎøÃ­EWÂ?Gãþ‡¸@‚ί�®´ìý¨å‡ÙaùL˜ót&ŠKí>(¾õ¦ÒÖhØÞáÈ…‘úAüT[ †GͰj«?f-—6¬úãûF½„AAaôªš:ï6#û¦hIANZ-1®Œ€r´s”œ¡×”dT½ï‡65¯ŠéCL“²;y”½x�Ü:6]¢ Fà=°�*óÕ2 –™®E):fg€Vݬþª.‰ JÚlN_w6*J DOÞXƒò¤J9Ø}´àdMæö…1„ÏY0@êzbuËÔÄü$YF4$  ºó)(c uyç“`šXRhÃÂEkL*W*Aù°ž]øž+ïco´•ë^–Ò])íJ»w¥®öøfj;‡†ßl`Âà4Èß.BÉy­ênÊ×·uŒ©TúRù¬”4Ì aŸNN¥-S9l.júm-ÊÒK”1a‰©rpÌ!üì¯'g!ëƒÉèƒ!0âMb;’bç �~Eȃ#ø g‚ÜÞ¼ÂéHTcô®ø€Q³'ñÏfx´³„31tÈ- )hûä·ˆÒ.u •` 3”»kdzÁÃ` °Ä­cJò ¦3f‹Â ñšî ?\»-u•¢çɶ„” å¯ÈA”of›ÿ7¥O.ÀFdÑÔ‚Éžÿ_wŒÖ®äº”>-S}×î"”ÎKi_ÚÝ®rz(‰ÒðrÔÕÊÂohwi ›Aü0gF]/Þïÿÿ~y»ó|©yk¸s´?€´tùÎVvþKwüã ]íû¾´ëè4”::¥€<8Ä6äþ [ ÖýXê>Q{Û†ò‹.öŸ|.+àMQá,:7m–½ÉŸ¸ÀœÑv)Q=Ïǘ‡6•ÄEðÏrÕò:(ôž3+Z^P ûH5J¾O.`¶Òh`ªð½kô …Çà b,I@ךQáyÕ±4EûSØàµÞábAÀµ‚þxEhb£Ë] $è×A,«TAJ䫞8¥‰šëCïëÑc=ÚÑ÷W¡Š-JÆ<¹Ä=2g·yŒ–@ïFèm©«†ä\ŒË¹«+ÆeKÜ©ª—Ĭ g‹e¬è )ÚÇÝ0‚3Ö>…öÎÀ‚‰Boï ¸ !V¯'ëÞè¶ËÀq\ f²qVŸ Ð:R]Ri†Á*Qçop…>¸t ©–>ô{?<‹=.•ÏF˜DTÞ‹6´PƒUh2ÃŒ×Á„‹ ÷&çGElE ±¶t8"3I4~‘Nû Lîºßsˆ¢4@”„6À›R0PÕ zSPëfYai];]|E’2,˜¨? âiÆÜÊÝÆ“42ƒ Le.ÍX7%$»0ÇJ$ûÒÄ8 jP-ÛÄÐGºŠ¦ŒÄøYæe„Këü“Ã%nôùºè&zYÙäU¦ŽJaC¨ / è¼øÜ^–ºkTzýìtSák©úPÒŒ­Âp‰!­sü0ã 5¹CLR`t'»N†nT1ßt.Éz ÜÖüsá‰Ãå~1¿ $е®×¡5Û!y,µ¸~&vâ×A }¤¾¾r_ÄYîË¡ûðúÐHÅkâÉÈo}é冃”sñ>²6€eÃÚhR€5L®àúžÜû'pÇL}íF>fyÈZ¦4uÚ\GÅJËEšwŽ‚h‘œKRIÉ�ʹYUGUh&ŒŠ a4\HP:xѱiEü|/êöyZ½¢¤îö÷ãÈ<À ´5ñް™Âã’: ^hŽ~`[�ä^Ñï(1Pίe)àª,lFÐ,‡Ãn½±+%³ã3X G(¶À]T€=ÙÞÕ¢ˆ´Ò(!á-ÞOŒxhPûH^DÜçŠ.ÛÊvüÎ¥L±µ0!» Ï­{�ÁŠí²ÛãtõŠêoF³{É4iy“‡Uç= ŽåÜ…¥ôÀdÜGMV¸Š}ЊgãÄ-ê£Ì° qž8©Fzhl5½1²ÖWi¯üA Ï'Äš¤²Br.u_•ußW—qº â‘öl&¼Qn .’³³§ÎìHÖ‰îlg²Tƒ•MBKCœu$'«†7h$cWDÇ.;$íÉ8dÖ‘vJ@¸K@ ?>N#ÇEc¦‰23F™wÙÝP%x[[a¾âmU°9/ÇÚ½›¸KÕ N/LðÖr%'™Ú6 ¨2B®<9k{jnã%; .Î)!]ô!c*P(¶^¤ ,d]Õ8ËþŠÄ4T½¢¤nÓÈûj¾!"*ÔË/”ä`£ƒ 1Go=®H÷~ØHynð£g7I™¼Ï“ô #Á€^]BÓÐ-Ó/‹•L §Í2 :¦>ÊPLßGj$ ¹¹Gk‘Ó§¥ôc×®íû¾ô­‘ô5WJoé§ž5Ž ¢’ýîöY¿éŒYŠƒÚmhá¾ÍØ1T/<–\¬·´ŠõCo²~X1³CB+åÀ®QC«Ú]gv£‡Å9êÉ<',ÄœodiKPAÜsGÓq;â%¹•«eHdEhµâ1ÊDéÆ#Ý,dP' Ñ~3èæ•ÙW 8FضØFðÞUSxšwF™ô@G©„I™ØåcY4‚ÜD ¨mUÌÛ'Ä4¬e ¦eu˜Á…xœm’|”mî© „ƒ¶ lé#ˆ>¯‚+çPüðX’ô1ô¸˜éq>š¨vŠ:-sÑ;En˜”\xŠ?’’¥‡ÿ4Ö= éßFîV5¦ó¸6¼p§E]²ª�A­°¦æ”&5D 솖wÄ¡”¬¯Ö¤IyÛ�E‘0ãD„0Ë].ˆˆIJ5„ª0ÔmT°³hõšÁsÀŒéÚ’»ñ2g´ (³ůJz Õ• 3†ù€{˜Ú`Lœ¬zsfŽÔc·ÒÚ.ó©9 ¸;`¸à9éFFíââœ*#Hš`þú]Aõûjöì¾'ÑšB¶{šUÂaºñ84Ášmš°Í%SÂ\Ò—.ub`«ÎNq1N T½ù‚C}²VÏÚ{S#9]œ((Ÿ‹„C˜t‘Ž8R§è˜$Íò ÒA ÑÀ÷ÎöâVËüZaìHdópÀLž@„° }-¢¬(F ÑEg#ªbÅOÁ€CKó­áZSÑÑ Ô�*ãR Q¢h%ýâú”–`?v+GßÜtþÈ—Íf+Ø<mHóm0ÎF.~œ½Óz7ò`Á9=nݘʖû8™iO4´ÜXº!¨í ’ǧ4ƒ§3‚6 ù5'�3Þ]ß9¯TŽª´)&®©R‹ÔÁu£3U½”'ÉÆÜ‘tKT_èŠX~;½µ7H°4ŽþâC9 ¾õ‹à¢0ò%9ýf¬š¬»!íÕyš®ú ÂžO29c1ѯ é}%‹‰è;?’k+³²V&bð}N÷4 1Lú’ÉÕäÀý¾;~|u@gC†W8ÁÚË8h_´­8¤úøãÕ÷ðöjÖ}¢ƒç–ûV­0Ãe”„ý˜0úÈpÄ}p!ÔÖðI·2DfAA]PlqsW–/2£ ÎQ•›þ޽˜0vj± Gubip ŒßgíìJ|`_}eøê†ç^?(=²£¢‚Q.xÕ_É-¢”sÿ89»õBgoÈk]Y¶ ¯ ½‚þAu‚ÇdóS-Uì>}¤¨c~=$kë‘Võ<>ÀÀì3BÒ†ªî׌.åh˜S[1cØ2j€p"?bûxæZDüA-}ú6yyD8òÁæy¢£w.€ª÷»…=Yè.¹Ì8]ÉYS|Lƒ»u¹tï´ ßÂ<”KwQ ÉWóYŠ^Ò Ÿ& ôô΄?©Žù«‘³íz…Ä‘jíö³ÁGƒÖn;Ç( >¼ã:Þhų¨ƒ¹Ù ”ó±¤>º¸£GPÃÆËk*Ћw³®Ôã¶„Åhj~ FìŽE`î ÈiÈ6!`’@`'­¤1ÃUîh Zʱ¦eFNvüÎÁ“x^‰£n>€,ê[ÆÕ†JU¥AâÄé²ø=èÍ~”FCrJm#Yw^ËC}êqEªphœ ‹„ÔGÃߺò`Mh°P?’ï_VÇçN…�W_ãàWTVÏíù Œ#êûxý…mÞ«ƒ¿y`üæAwG™u…}Úˆ‡-=­èÛÁÂx’wdüD•‹óà‹ü Þ�ÀS‡t¿oøA€Œ’B 9gè$¨a úÞ®‰õø‰ÌIQéž}[l.&Èê»8\°\ÍaJ×1<W^Ç U/ªÃÔ­…ò$ )‹€¦í•>fèXËñ I2&‹„PMȃÂXˆRcÎæÅmKŸÚeOØý2ĘmP²/E)]vØXºÉ}Gž5cšç½äÅÓ0 `ÄZåD9^D?¥’ÐüÒÊò5¶%Šã³öTBšç»6êj»¥î¼;=,=£Ï·™ìZeMÿì[üÅ ¬¤X›óÄcTÂVJ2ì£ t‰±#2Q~…7~†«^žâÞì »ní…ß1æBØ&ù—äÉÝZ‹ÛϯÅ?cohžÌŠO/žDM‹ëÿùïJ"ØZò{õ×^ÏÆæøz–ëüzöØ×‚õEX}ïW_JÕvu”¹´?”ŠoüØÊûÂWíˆÝc³ú–0¾ Ä'SµÝÙ î¶”îÊׯJ]¿§ö‰n}¶K^)~Ðm?wïâj»ôî¾èc¦Ëx|5Ø]}:|›Ÿ÷òé÷õ¥ïå`ÝûvÝ¡4—¯õÅÛù`§¯K‰<_«yDç#zÔç¦×ƒ¯Wƒå“Å<jÀP *“ܽ±Ž¹CI½Çç¥ôuéRþíbDéêÛ=ìÓܳi¼÷´›ë^Ö5¿ìwª+™5oLÉJ¿…§Óƒ™�DÁ‰Í?=;ùüù/Æyñ•endstream endobj 59 0 obj 4988 endobj 67 0 obj <</Length 68 0 R/Filter /FlateDecode>> stream xœ½\YoÇ~'ü#zÚM¼ã¾»'ˆÀŽË"Ñȃ�)‘k-/)[Bþ@~vªúîžšå’"ÁP«§Ïªêª¯Žõ¯ 6ðÃ?ñïÓË£¯^q³8¿=b‹¿ÂçG¿q?bÿ:½\üåF±à|µ‹ãwGa:_p§£VªÁªÅñåÑOË»•˜G¹|‹-ÍF½¼Í}w¹ï[ßçF¾Üä¾mî+s_åÖÛüõ¼íó­ùëÍj­õÝvù54¹Ff–ÏòÈç‘»Ü÷!·®ˆsÝå¾!÷ý1·~þ9Mß[Fîòçr†/Sß¿ŽÿvÄÕ ù8.Ž_ÿá1¤Nú¡à±Î-ñuÈ}…nóÔP‰»|í«<ø<÷}Ÿû6yù2î N.áänô—Д¶Úô‡<ç¤eUw‰“ngìÛ¶;ûÖIþºn÷(ÖÍ-bUV9%ÖÛçû4'TØB2ÞO¾¿ç¾kb«K‚�åèßGoI¯@~˜£Ißì©(oè²%P'õ…ô¯B^}ÔKxVôª¦)(˱VƒkÎÌ Ôb-Ä äèÇg Ÿ¯ø ŒÐ@¯íj-%üK:`öšJÀ°åÅŠ £Ultp޵œ4Zà� ëîà¶y,J:;ÂÙa_Õ­çl®ÊR·8ß Æ‚PVíjßkìUp3Uïð¡,q…צiZñx\ØßíàŒ®¿ç#Þ®@‘Y.+%ÜňªóC^ggKبZ3^ÌÚ©îu†k1¤(è¥Ü»++�€ÆÌY•i(ôÓ]€ÞôºœµZÉSx 8õ‹jgÒP¥Ürû§U£Öœ¢ø(& ‘Moóc½Í}Å<¼Úk(>äÖ¶2Q'ŠåŸsç:>Q¡*…Ñ›ì;n÷«ÏÕh³×„Y-š2?/ç>û¾n“NAw›t‡)›‹|š¿ŠÜ÷næÍwÆù&ó¡Ðj“û®*J7T«.„}‰q/;e‡}×ĸëîí¸Âë@ÓŠã:ŠSH¡Ð~Ö„®ÒgJSf¨x MZeM|›šsTuk¡í`Hõ׫?c[)·¨ }ÿ9¬däà y·w­;GãÔ3*³ÒÏ"­Ÿ¹mF‚Ö Vã²Úª(¡JuTºw{†×ámºåhŽ*E{‰Okå›lß…›rfc'*œ09'u}©íD»âYNæÔXê­TÞ'¼–œjVS Ã÷.Ú¯²VW¸�ÜÐÈzm¹×µ×ŽRâ&èbxsÚC1tb^aWÎ,VSõŽg9K“p›uÚg'îeµö欻Y~—ÍyZ-¬Çu`àô/` ‚æo+pƒ8š¡ÌŸJ’Ê-7×e—Jh‡ÕZ)>€iz]HšWBËÅì` $’eÃïeªx³­¡Blj,R¤ê/N⨖(`@üÊŽE©L ZšzÀÒRN q»Ù.P;Þ ™Ù}Ó²1¥; •e¦RYpà„üëËTm¡¹Á*iT‘^0µJBy1ó‚ÂUt:¾C[-^D5 ¬W _&Ix¿VÊÒÕL†k^b¦ÚÏ_ñ¼À¼_Â1”S5s‚(†GâÙ¨²úêd2K¸_‘âÕÍò‹Jä*1›Acéa-7ñ j âœÂ€—ÃÖ¼GáVU´h«ŠJwEÆ7WñAØ9i<ë%;Þ*­ÐaD`:jÉ Ã¢U¨ïƒÑÈ}/uJ “à‘z-\Ú©,‚†‰© F ìm|¢6Yg´óÙÙ¬~T½‚å `eÀ›ÏQH?!·¨XgfßqM̯ï›F8yhLžýgì ˜¾Ê}‡Àaìû¶Š¦u 0‚`l¾ë±eŽµÛ ¹uÓ¹¶-f¼(ච‚‡oòç“îüØwqàŒºx¿Z›a™dô¤ÇýqEœã3ý’~Îûö~qÅ<¥,ùužRâ ×þX¦”€å›< o;€éíÇ  µ�(‘ƒµ.Ö2«Š¯a_aÑ%Á@ŠÑE®¾Ê‡}xô²pˆò{ºˆål$ä¾ bø.$RÓE‹B`,莂¢)è_½zBÁD`)5Àc¯Wvì,ºWjˆ’;¥6µ9ÒÐí `·ø¨»ßá>œy€Nì%8”Úý’¢æau“ø,¾NdhA³Ð<Ê©…[5±F¸f® ãá)kxPöDð=JíU6pVh>gø#œ”K‹FL[ N (-ƒjŸÙöz%¬ ýž=ÊΔҳ™”¬,v›hC4¯¤!ØØL8Æ;æEÌQŽà1bœ"RrκM¸D»&u´Ž÷#´Ñ¢!{… ó=îÇÓ)ÒhD@I>|Øà™j‰wÚ»�-¸6¼žx—/H“^íIŸäŠðDÊ›"¶,­M~òÂ"À˜ÈO)%Þð¨ö�uã<¨¬슖)¤o¿7;„î§½…¸{ æ²èmË©b”˜¸/œUnœu^ñ)K^#ä]<µPO)ý7²Úü¡Ãb3\?[ DΡ¤Ö»ÜÚ`käYÙŒó}ÇÄÜÛüõ.÷­S_À" e¶Gò¯ý`ÇSÍæ¾ï.·òFt¶CƒLŽËJR¾ïÉ-Ì¥Brl^®É2ȯ6Úг}¸ÇÀKˆ– Àf"_sLåÒ¦‰<Ýebþ®ipÀ:®ùVáÚkb•Mž{7å=Í0äŠÉ¶I‘\¡ã›mîDŒ`ãÆqžAÂgÎÌý •4ÓŸU­‚?)¬já°ÌT{ÊÃId!ÝêQŒwc…Qn2WvÏŠ ´Ü£ÞðGB^æ¹eåkb\é;íúpîvŸ¬p+_¥ c$ví#Q ›öÇž!>¢IäUUG¢½êKú\XP_‚ɰèwYAzþû^äÖËŽ?ØwÝ©¹B1ì;íÆá×m꣨hmxiÉ%\N¤:^ŸËå³$ IM½ôÑ:�íç…'ùUM€J.ó.ÉiT›5~/#+k\½äøÒ ä,ªe̦l|èIpY­@> í«ÇG¿ Š®°±F»BŠg¼yô⤢f‹J½l[^öNý´ïp ÏR1}ÕÅqåCÇÎEøçÊÁ£2Þ¿ !Íì·Ù¹xkþ¼­ ÚY ó¸í[g79m‘MãÔÛ!pMr9ˆ{„£ ®†~ÕÅ•LçO“À ª¦å¾V›m‘dö­ºT lwôñÛJ£Ï'¤_JþÎø¸sªní7Ñå…U\V–åžö/–Ë*y¤Ì`EM“®ª„#€$/ðê³ÑÕl¨Ä¸ %ÿõ2I&$*<P9=G­¤0úLÇÞßûÓ¡¯œ"¹Òb‰cU©¸æ‹`9âa”`c°VqùßÕñ/S3™J™CË_†caÏZŽì0_[Ì‚b™äCœóшSÂß»ÂY QûŒšðÂÜf¹ÚZ <e»Jª·"ß›)tÆî¹IãñÂmì�^cåÂWOür%½åm0ª²aF¶ �fYódgÄ@‹sOåÏ™&yÀüÒAe˜r½O¾¤`–Çiš&eúü×Ö+«’F›qÛþàtny¡À'6{$˲`Ú>É*9±êM&ÉR†Í·dáªÖQ1‘Ï”,…AdÍ-YV@æN²°gÝ+Yaºœ .¥°Å—X ªƒ{¥¯ bbùIŠ.¬¯ç(Iž›ZŠ,N)˜a»·iJ=˜íøÙ.Pò§V-U](éM1e»°µÿcÙî³ïVvl P„8$¦“µ‡½Ë^ÓIæM`„t[ýÒ:"a÷T_ÿÛ b) ¼‹%5¬Ê!a » ¦M¥©´|Ĺ,%‰÷K]2có‘ ´HEoÔÓ¤;\¬°{ #žÞNq K¸ÇÚ©.U _¸ün`¼­4ÁÂbÅ8¹¹êlµ\Paµýk®ŠÁšM\h’0•”$c‰Ú^Sõ¤wãSõä“Ù¡dl¤ 6r6½ŠÅˆViòñ$‰‘µ@gPî+‘Ã�Ó;d($œU4ƒ«%XŒúD8÷Dß)9°xLLëdT�Ø‘…ôs^x7†ëiH_ÉFE}w¢©ÉÁÄU JƒI™:F¾¨D„¥£fò³i×èMŸ€Ë§TSH»…� 'h_\L¤=Ue%÷b*˜Þ—â bÔµM¶t‚äKfܽu;Z$ˆ2[ý’Âb&ÉR‘˜tw«PÕEÉúQªè¼Ÿ>©FÝES›ïZÖÇ„•£ÛÐÚ+BuxiÙb„œrDÎÏs=`çxûñ•lMŠ½àš•c[‰N§}CLðZº6SÛÕïQ#ÂõžÏÔN^©”–Àð±JΟZ>2q^ SÅ+šÉhUQnÍY@îšøà<‚ò¢ØûÝD^ø1·±"ÄJÉ2ðÉRf dÑÇ#öE/Ã8ÊÁÑ‹2ü§å+Ô¸ŠiµüÑ ºd¦¦RA‚´‚¨Aö~ZÞœ RBš½ÌÝ×ð™”´ÍÃ,ª¯iQš†g@[‡¿s²1L46ò*ÊTj_ÉÐfûR}oCq…ë#*Àùº"5w>»õ£ÇáÏÃZ¬DÉ|È™d,틚ºéA'"8Û ‹ì$=_e ,»Ð£ŸÆG²Eb�ö¥ýaä Y†“ øÊ¥¯ TX{íìSW«(‡…Iz–ÆxEîE:åvs6œí>¬(%!àéɬ¨Jšî‚P~§YG¼'R†”~)sáxiò·¹óyn½ 2Íߔɫý©BU±S xûKÿ„¤¶Ï‘æÙÄ€U†8ájËJ[ÑÍvš9hlgJÈ`'t¸ŠV*ô çb$£Ê¬U MŸiô!}^”‡JtáÌ iw«ª£Ÿù̯Q`Mæ})|zÞ·}„Íûþ¢ó ù“"¸b±Öï…~ÁÔV oF!|Ί‹Ûí§@D¬Üy¤L¥Ÿ¦ØDΊ¦þÁ£dÆp¨ÄîvoŽøf_>X` c‰Ó¡$&0›´±1EEuY“^¢sÒ.¨pO𯰖qu“É‚_¿9>úüù%› =endstream endobj 68 0 obj 3829 endobj 72 0 obj <</Length 73 0 R/Filter /FlateDecode>> stream xœ½\É’·½3ôsìv°ËØ—£E)røbyl$HIµÔäHCR´þÀŸíL¬ TV÷pH9 •ª«P@âáåËL`~¹‹¼øOùïó×þø­tW¯Þ>W†_=úå‘LO\•ÿ<}õå5<¥=¾¥®®_>ÊïäUt‹—1^ymo®®_?Úýwý#¶¯¤\¢µä M†Åòøw»¿ïŽ1ìŽoúõó½^tðq÷bÐÒ/A¹Ý¯{xOoàfùõn‹QFÇÝÛ½Y¬7Ú¹ÝÔ´·v÷^×bQv'úÍÅkÐK n÷.·fÜýºâdý–…ŸïúϤWÇ·xí'õî)\*³­v/ñRá{ïû°¸’¯ÖžëÉ£ÿ¾þ XÔ‰Á¢F«À¨×7`įöjÁ ·ûº]ý©]=IWV¨Ýu»÷M»ú'óÆõÔ¾Û¾‘»3N°‡ÔÎ|€‰ÐTŒ˜ç†«+¬†»uJž7Ó>Íã6&¤Sð3Lé3¸Áˆ¦Ã�Œü¾MMŸò>I7õWìæA9»DP…¨©ƒï:hÀÞÚ™E•×RW¸J§œUüdýº·ðª‡>?íx"cŸ­¹ñniª÷~Õamüú<Îô2¼âx’v©ýüzsãÐp?g0<W²Ö¾~‡ÜMƒ;ý¶0Qëݲ?X“/#�ƒ›[쌃Î�^ú‡¯ú�~Øk¹¯eªšg-åéZÉ£vF‘ÙåWÕ …ž ‰}‹vzk9Ãïð©[#Z´‰‹i0fÀ• UžBH™ü$¡èŸ1zñ!aÂ�_0q7 Ü´z`¿óHL0õ}4Ô]~_¸ÚÚ´¾ì/ÈÍà,À®?“¹¦ K¦&صDë7ÐU\Z†Æ¸Fµ—Ö`Áfé¢èFíëôÄ¿ö>Óæí&ó‚¬0ynyb£ý£ïÈ`Ëú´Ã£äJcÅ⻘†…š¦ÇóÔE!“�”ç:žà~‘zxånþ^ƒYz— ŒÃCYÜVZfÂñIŽwn*Áª¼Z‹ÝðèÔÚð0ðn_Ng8L«Å9EñBfûv58h$`@®’nR² piƒŸ‘޲ ¾KKxËgœn­ [2\òî¿å‘J@#KÂoX/~»þ°¡)Ò—FÁ`bDËJ¤Ö(»íy–>§ô젆߃Q¾‰…ì43Þ`¦„̈ƒU”Ø9Ýæ€µãýu[ü»â ,ôcD‹ŠÖ‘¹ŒêŠÖ•P²|ÎfíÃKZÀûf€%iêH=¥‚ñZ;ô”g$X*°oœfEEPˆ€¡Ó  @ <] Ý‚ñ•>ô<•9ÃëYð–@½û6ÊÉ;ýz«ûÆãíØ„Õ,&çZ¿ÙaOASLè àl2ûù3B¸»æìCAå5λ½Ñå7Ó׆KF;`QÂp0:ðÂJAO‰mvâ"Â�àkŒé?s”º%å:yb„Ô'½g¯m‡ÎÖi\œ—=Œ}^沄&ýâ é“ðŸÄAÛÙ“b¢nrò0:㈊?¦I�G-àS£hƒ Xl´¬{>½˜fañMý’¡Þ°ð¦“#NÈR°.œ¬ÐºÃსD6¨*Ϲow¶Y0Ôñdè•&Çðà ",«ûÓyäù€ øsq½ä<¹¨ŽÖ;Æ=ÖHD¥XáùêenÝÏOjoÙçàì,çC°ëÜý9¿=þ]‡Èn=¬æuÇM§ï³“BГP­.7L{Ÿ ÿ³ "µ¨­- b>"H¢ßÚbÖ×ZþѸ‡8thMý´Z¿…MÝÎbíX*L6  }wú‹V|¼Æ�%†PŒaØdÁg«ð+¬gÀ¹Ï2yÕ—cÿýM— ùfŒ^ÊëÆÕ¢¦µÒ–zŽ<³Jò7–i)«15tAò2nU9ˆ8ªVýsZ.µÔåu;<I(ŸÈŽv½“éAhÖW“y~·r 5�3zÝf焈È[¶ˆš�ëzÔÆõѵW·½Œî)wÅu[™Ëž*Y]ʉ1kÿAM�Q-¦Ç”/±m<FûL &Ý~·2â¢Ë¬sÑXrï‰<f#«O¥wFªoh83mIMŽÓ–r|à¹zêO±*•x»‰] ?ëØ a }€ÕWÝ„ñ¦ÏLL´^4])ãZ‡ùÈ/ Íâ–ÔéHzÖCý Ÿêø¡ùÒÕæPÃ.AåkÑ,+Û`Ž–’ãKœ-µŽ/sàÔÀóYUÊŠÀ l5. Ã&eá Â`›AµqaÑNQŠ»HCdi¿ÆdBwçJ÷Æëˆ~>Mi,»R‡éÙtשM/˜Í²Aˆ$cE¸‹tvb4‡P/sBâŸôû˜&Ü ¹d*K�rêNX.@“J²1Ó±iOHÆÅ_]ÿáÁÔ“bÊà)X~î`! ù4FÀ"`áÖ 9½v·ú\Y`äáŒhQ‚]AQòð© =§iÞH-çtŠ €}s9T<HÇÏX–Ivõ.5;u6œAù¸ R°§¦)û8¹„1]"˜<DZ¸:|5y:%tná;ñ-eU’øH¼Þ~„îBшe".ö!Éj>Hh®b›rîѲÞ5CÍ•¢BŠ,øb›¤d£<j÷ Qõà°Ì‚%Äýòþø–¥ü•S}ôc¡�Ô—ÔÈPíÁFDd’xnxÞ¤ .}ïV&;¦ÛvÇ/˜š²Ðu®Úý ÙŒÂ¦ßÏõÛ4•úê/2ÈÝ^³éSz.xÄ›'r•$Üg+ •O®6Œ9À.\–VË}‹W ×‘›ë½wíÞ?Ú½ŸÛ½ïwíæ÷ûsõßCùæ(¯/)®óJç†ÞrOSW^´{OÛÕ]ûõ«vï¶]}h¿¾i÷ÊØÒåÙ±bõУ`—Ä}*ÝF@„¨ÕÞj6‹•=�oÁæ'9۱擆 ˆ,¶#'ÚÙòÚ &ѧ ÜÃãWÒn‰¡þß„v‰°M÷I®³9ÉBAÇA•_äFq™S|x”†�W!õu|ƒKIûTÚ£X…¨Xt³ÚnÀ[ nÅ”+ «‘‰p׳Q°X‡p” “/{Êr:ãùð«V‚.˜küF†E†p©ÈÈT€Ì8¤ nñ.L¡Œ|¥-¨­sˆ S©s�‚H¶ëtÛ¾Fž=°¥Âsߢ½V•ôD€z©VT·hùk2�²Þ{ñç¸-És¹X£…Z5 ¢Fäl¬6ýª0–Bö²Ö®J‚Eî4¹”òò &$\¤‰P{,b™TÑR°¨%XBÁ'$˜‚Ëo‘w0°‘»'ðÿ#MN¼,!š\„oÔ)ð¬K[#`øœN»#êoñ¶VÒi ÅÚ.i1(¬,¤õC ^§(Ja°dLÝ‹ZØULmR:Ã9!€€ª¡c¡_ z%¯”ª1¸Û«fKG;7Ê©ƒ2~œPÝ8-H�qÝ8ÑÕÙÂÚˆU¬ÉÀ‰¥”q)Ç1È�¸�úðȉ8Œ 0}gÔÖíêÙ¸ Vaλ±ôbbTcö¦[]ôõ§æˆùø™S³¤›dÇÓÀƒÊ‚±âåTlŽq·QÓ)w¨´ê¥S¬i{ák±ÅjÖ±îûƒJpB—ˆ3š/âŽ#À–8ÌõÕb¿öÚwkBM T«o•“’hè2s2f‰”ý?Q8F`c{¦¼fÆÚ#ÈxeuC×s®{Ì2ÑÀur|‚û¼¦$F++ߤiJãDc·¢zé“7n3Ÿl-~¶t 4æÚ3&yrÕ¥2‹'Î-q/kd¯×,Ö6œÔTÈèSsŠžª2Ð °$Ôî_{¸°.Éîƒv‘Ú •§#QYꎚ’ÛC)Ãï º¶7r³] ìÅ#÷†{fS}û O~0ƒ‹Rccî$}ÉÝcC(}€X¼¼!b,øã½ÇA@ëËó tÖAÀ;èê;,]žÝjœ¡WÚ³m=­ºÇ8D¾þPˆpù¹šy)p»¡^y$ÑaTº­esV“Ô?QÂ\m)Ö;MÜpï®¢é§Æ 5ª}ÖÊdH÷ßÁûžÃ(G¥\}GÖ=ÒÇ÷†`‹h)v¶«¸»!£!õR æÅ:çÙíW„òìtŒ.·ú¤ Ã*ýÚÖÙ¦1ëÿwÑ~¸£4í±æ¼ÂàåŸõŽôL¡››K¾ÛmlÕëüB€ÝƒÁ’Ó$f_Š%òR.oð‹Énnö¡5H­;ä€ô¿B `4\N˜Ûl]Fv)IÉiŬÆ`žÉ�h0Ö:Õ º­¸[Éuß?õ®ì tšFÆ—Š3ùå&Gò» ó¶…ø» °Þ}\e•itœh èøŽ#ž3ÑìfR-Q›ó ›{Cêá6¡•,`§’¾y©ø�o˜»üŸ’‡SnRpiBÿ|Šw£I;›“Ì@ò ûçýTS2»¤÷€]vßß-¿Ÿ ‹‘TFqÿØ{÷e÷½æ£\oJξ·Õ¹r{üIŒ±„Q«\|ä¼ÏCEhûxºù¬ ¢l?üB¶˜óüV79ÌÙ¶œQ–žð™z8ÁŒëÛÐ&¤(9îñ J IÙÌ·Y€eê>»¤ÌÆçÛÉ„„o=¼¼Þ:]6ùäíýjð×*` 1œqÉY9ÒªC#"4QDúk}—Þ%ãdÚÌϸý•�¤™VãØ”~ouÆ´'-uÜ8²úO•²„£1÷Z8bè‚SÝ•e ±UëƒÃáŒBO¿;J —Â<&·‰í"ÀÓÚm!£›DW; O>®îYíøX»R­·´wäY«xZ"O#Óƒ ¾d!U30A#¸‘àq áòI}uŽÖrj°ˆ¼ÔÞXT+>ÖñŸè3Ó.+O%Ñm”äÔ€çcgôjËjS~éˆÄ8EîÒÑõ±`KýñD@Ö‰w2É Œñð–‹e24©ã uu’hótÊMà^Çœ¼,»‹ê¹Å^ïå‰ò†ºS¬ qOÇu;åÈoe‹SÖ9Çb~p­Lbo*Ž EýÒ&å=Ç`\õ¬XvÀ"Àw%ÅàÏh½œƒ’Ñé”–ak3ñ9è¤ã#^þ Ûœ‡À¸a}8½:vŒþáK’¯™˺ð‘¸S“—“ˆÛÏéœs‹êÐ+g†}>3 ¶EÊ£GJÓ·ýÀ¢ìÆÊ’UNôWòRš*¬SÍêÍ?³Ù’©È’ÃT2¨ ¨5& ÷©¹äsaÃ[&¾$§µg}ìWgÒú”eþ¶Ûª2€3ª0"¶ÕOÞq¼©ý²üÖÙë‡m›Ü¬)$û˜ƒÆ}E-…J*ù JÙ!¬ÈÞ¹;®ÉùœPi›°!AßÓÁ•ŽläSb.L¬hÏשׂ:QÊK$:…\%ë©W’ҺᲉ SMÞÓ¹rË‘!¯x‘ªóH|6åH€Ôýò”;Æ?Ê Îì LNà²BhIÏy0pêb¶Î“ ãý2ƒVÒ])ïKÔÑ·jù²­eµ&mXmJÏ'2K’Û"�Ü*BÓéÙßR¸ÂVÁpËx†©ôVÓ Ê²ùíÓixÒf¨¸mô"’¯Ñ ÆÝ8 E ¯gs‹~vJò5g?VÊ è¢x¥ƒu²!’Ñó†f<ãÄFò¨Î£±çN;%z ‚;èÉ)ÉÉ~ˆ¯^Öþ©Ÿ& ×-n+˜=ñ&-<|i1Q|ÉF�p9ž&|™ï¶ý¯Á~ÑŸùãeGžP›…zc1ƒ¹ý— ÒÑÌ0ä2VCªàÁ©QNæJø|R×ÄgOCæÝ*ïô6"æd=©7¨™úÚùHd:A^;nçbþS&Ûë5™_¨Ag곸#æ\¦¯×kØ=|ã_ñ©íú›yV63“,±xuÀÓ ¾¾ ŸøúúÑßàŸÿ óendstream endobj 73 0 obj 4531 endobj 77 0 obj <</Length 78 0 R/Filter /FlateDecode>> stream xœÍZYo$·~ׯ˜?ô8; ïÈýàÀ‰7ðb~pb@«kÇ+²»üßSÅn²Øl¶.Ë‚ˆjU_},V³úý‚3±àøþžïýõµ°‹Ó›=¾ø'üî½ß±Çbøwx¾øz ½¤XÁ‚1r±>Ù뇋… L.œÒÌéÅú|ïÇN.W09çÜšŽ-9óÊ9o[béL'–+!¤f2to@꜡»Y ¦tð¦;X*œåº;íÇ sÃsîÖÿYÿ Õ¥bR‚Bëý½õç?vë¥fÊig»w0ypFˆ�£WJ8æ¡y¥škjfœÑ°äJ‚vÖH\›Î$»K’ž T1é]·C˜–Z…a­8ë0ÌQºép%YPÖvG“®^øî%Øg½ó²»¨´ZvW @`BƒSÞ�&‡±åBRÄh‘4ES®qMÉ,¨7è+§?Âå9“åøÞ+tVŽ ÀÔkÔNᜩg(¢�­»³%ÐB€Ÿ 5Q0ÞZŸ´C=Þ.Wx$¡ù3J…4ÑÍ-ã¢�Òæu²ÐVÝÛ+¡vJ¹îŽrL�)ƒp ô]a7ç�w�Ž@6¼¥‰(§Á!Z'>I3‚fèˆ3¯†©WB3ÝOÒ¤½.™³Ý^.A%i½è>dfl.ˆ¦§¨´f\j2`ŽŽþ1æò:‹ Ïn®hÒ: ¨u\b]zL%`ê̘& åèŸß°÷^™Òùw@ +}±ì7¬•£ P¹àÒžýj¹2³Àm·…Üp�~ƒ- ¨’Z×¹u0– ø<ÉþÝåæëÜz“;^d-²£ÁËÔUï½:Ñó$ëy™‚«Œ„Ç�Åß²p5Á§'YxÛPå°¡Ê&÷£U.ZV~ÌAû•Q° øö¥!hÀ_Àm6øúã 앱²` 3æçŸ“ÙS×#¹Jè<brù ÉU¶19‘à8[½C[‘å‚Щ +>oUÒï—äó;x±Ë¼8Îóß4<Ërë¤áãËÁ‡pŠýFLòAL`óÇ«;ùC‹¼Ëc*œåÖ:÷»nx‹ÆÊlr¤ÿm¶é|¬L±>%kJàãÊ\…^" ¿Ëb‹ÓåWÇ8Äv?0F„Ð`úã1þ&÷{ßÀ˜‚æ6÷#`‹½±ml±‹lÕéxÛÅÖ»L5µñ1!û<£Œ— Ž›ñù `¬‡#ÎÝãƒzÛþaH¿jŒ¨ˆU§£­"î3�]@‰øAN/ ‘ |‹Í? KþÁðm†åqý'8$_Ðù‰Ž¢/IóW¹ë›ŒØ~–í—(õÃ!EËžQ@;!“ É–Ù€WaC[uÛ²ùSíÐáÀb|˜h]…"íPf#L6M·ÕgwËø_Ê>æàág~EM‘ŸS0™ Ós}"4ÅóÕ¬Fã@÷Pç3°V’tsÏÖ£Œè§<æÓüúL Y5 û}Ÿ(9k½H”Q~ز¾îÆ:GýÚóL¡• Ó'èÝ©å}Ú§Ögãó£Š!Õ»OíŽ)à….÷$øÄîú@'Æn»ëèžEnð¾oÁ›×£Àï u^Дԓ5ô~ЛáuvSë à¹5ÍöA©¦•óªã᪱m(»ÝµðxpºpÐ ‘— ßø‰8”cS¤&-Î(¨~9!ôFOµ¸›9wûàëÆö¹þ½}ð¶òuËGv<~¬1¿Zt‡ç^ƒ‡)"žfƒªC+¶Ö ŸÔâÓ³,{™eDÖ>¿jHV^5¢}+ŠßVÚ£ì»ÜÚoD¶ ¿Ö‰R8e/Üc%ñªÌDî:Ê*/&u)@¸>&¬ðŠÑsÑ_ȾZ &­X‹ûØâú>_Wâ¾â‚ygfn÷‹‹Oè ­Â+æÙB€¶ž)+Ë×Ô< ]útÎ%šîX‡›a¼O=ÅlS3+ÌS¯ÐµM½ˆ×½Ú8&´®®{µãÌyŸ* (ÝŽka°ÅÙ°rñä»ý¤Øl‰"ê4¾ KÆ‚I G+Ÿ§råEýA¼pwÚ¥rA¬Ÿ@GÏ4ÇN, @ Í•ÙK~g!ä”—üŽ}áÈþ6\êÄ)@f¸�ç%Mp@ŸVÝ-%:{ ¶\L±’ì0·ÎÒÓõg6MÈ0À#i†–FÜì=ÐÔMÑ<›¼ôEVì&Ë®rë8?=Ì­Ý]Êj  å2­sB4)¼[¡UëÚ\Žë†3¥ÍàtÏC÷1Ê—ìÚ3`íCÃ;ŒŒ›Ai ˆ´ÏªÌa&}¹k¶¸„¤qÍe¬M’E­bkÞfžRý¥wjX RX.5:VzŒd´ÖÉÉMªFÂ<‘åBC—Hò>±B×䨨WœR$€P©¬wÃ$®bt@Û¬ÅÔb·{‹‘–£þO‹–¸€ðf#7–Ì ðó,Î]ÓN› G‹º\œÄ©2~¾ =¶A6˜õCžùcCN¼íË{}ÄþÀb*Œãb¢Ïå„T#e’°(˜¬f‹Ã1rÂjTT-:NËÄH»è6ØŽÉmšÊŸÃ!7¨×GÜ~ò"âg÷ô„ÁbkÍË•ÀQN4o&$®”÷pÂø’u³®Š¤EWiŽ…}_#à¡ÊÞÁE\Ë‹ç 6ÃvˆYWîB¸}1P—‹RšÕusδU¿þK€ÄE¼gë‘“fèdUÍìè5e.N<ä¿óÑuKAîº Æ$ƒ‚›­ÙáãÜ äüàAËGáj‹Ÿ@@¶³Ä“ÁŰÿkòÄ8~AÀž²#qo¸…>jâH‹±w+rÐ!—E›˜pI‘W€Ž(¯¿pB…7ŒÑ|ÂiAª|FL-ÀãÆ¶xm®X“¾¡i„ØÈÄbÓ +“&3¾ÿ�™Œ„w15JÈ…í,J¡!±ñ*§E1à B˜!¹BÙE–å¤ ^ç’leßåÖ~zÚJ®ViññIžØêO£ðKÚZcLü~ÄØ:ìI'üaoXëY˜ŽßʤÏN¢ðztØáw3Æ·ØIV!á•ÒL •ð–T…¡ø½–šY´¦®í“2dç®±‡ŽÒ‰ëë”?x‚Íñm|‡•¼ü$ _ï­…à„(ÉÌŽƒÉÎÁÀV*Y‡M`ýúgÈ1e„h§ ¼ DîøÑáüÍzï{øý7ç…«endstream endobj 78 0 obj 2403 endobj 82 0 obj <</Length 83 0 R/Filter /FlateDecode>> stream xœÍZÛnÇ}'ò !@fbo»ï!`#J€À‰²y²ó@‘¢<ÖR’y±Eþ÷œš™î®Ùí¡ÈD AP³·»º.§NU-õãF µ‘ôgþ÷ìòä‹çÊo^]ŸÈÍ_ð÷ÕÉ'j<±™ÿ9»Ü|½Ã)­6J‰äœÞì.N¦ëj’Л`¬v³»<ù¶ÓýÂ¥”Þu¢—"š¢omëàh[)m…NÝ®IXéB÷²WBÆ`mwÖë(´¶¦û¾×§»7ãÂkÝ UÌÄÜð±;íHÁKÛíû­‰Rx©º?Ñç£ý,Ü[ÝÝô[+¼IÏ—LJ\è¾.¯qÉØÝ¿v%‡%î ­á‚Ý7'»ß #¬0Á…%D:¥žÜš…„øWýV“Pç°k„‰!Á"vrÞ»"…­vVA·ñЇídQ¾ë†óÆ%œ´ï;Õ]Ð%86Úîm½EÁŽl'ùÖ¤YQ+SÌŠ""ð( uˆî-¬ïΗG#lò)Ë"]gµ YíˆxB–6ÁϯᣓÕ^Yòɨ¶AH¯I/ÅÄ’ ‰@bºKD"ymSÖËãs¦×0[Nšß‘ŽA ‚ û¾<œmˆ¶Âk"w×mËâq–Ý]¼eÞ Ù[ÓC„ã€e$Íîi2?cm¤X™dFœ®¨9 '!ÛIÊVYa'I,Ô· TEaôám";*ú­÷ZX¯g$;–�Yâ“D•½UÌe“ÊÉÏq£„G”îÁNÊQVÂÎsÇO¡tÍŸ[÷�7}ñÜË]ÍÎÁH”æÕUY]+'éÉy¯•öÆ §RÊ2ÞßTõ ZJiÊ΋åÝ#MI«CM7ZšÚ b”*¿Ã2„9š)}òsÌ}9_Uá)Bôt@K„òœ¢&á)½žƒGIÄDmû­ÚJ¥Gôë„#üGçÏá,�>­°~Qw‡ýpC•Ä£B+X„3ªcIpA4"hÛ=§`›¨yƼ¥–¸÷¿ãðžxˆê›ûØ1!%Hxq�ú# ŒâŠÝ–@¼é‘‘2˜ •nKzI€DTD%4SÜcâãên!~£‡lvÊ×B炳 žY2†4¯G¢eôg?Àé#÷@xH±ãyF±‹˜Ruñ¨.2Àõ_høqhqðþöJ‹PŠ 50“9óæº¢GíëI ³ñîI1õ8Ù?‘‰Zf" «)øÂÜýð¦Q� ‡æBAÖÜÁÅÌ€R? ® —¸e&ÄØ퉃‚'Tߥ‡fÔ1b‹M•þ°Zƒ’å—!²–„TÍ~WŒÂÆDAq¤DA:Üêo0«µ7/�ïD”ºj=.—Z½�g-ª±[«ù[£PA€GŽèãjOÏ3lMÔ!A˜mö[²ÞÀ|<=¹Z„þžþ D½û=¨çK¨øsï°§†[crÀ 8V'28Uð¾ñ¦>ËLhu?8Àáú˜´´6©&  Ô²_•ŠAwÏYu¹­¼xU±}�ÇYú²”.+"°%CéÀ˜pQq(±¶pƾeQAEJÅÿÉd‚†²û®[{ÿ¨vÖ"Â@²ßß‘YžFÉqöS”?fuþ®¯@¡ÌCŸæ°ü',žPêÐDÆw$ª*^ãMÁ ÆÈ­Ns° 57d•in›¹™¥`$2$•Bz5û];Þ¯íH䤨5“®éU/ˆÚš˜Ì™ãŠ4UÕ!H§e¶­YϘTy¶A!5ëÖÞ2´Fšêiålcrbs >ÿœxTrËÙF£ˆQÓÁgÕó&˜~Gˆ¦)l…Õ£µ ¸‘Z ,ûÈ™�Ÿ¤zT×@ÑLØœêÑûÜK÷ëÉ:ÝUO¯ä å ¨-Æ¢½qi�­2F l:Mk˜gҔϣƒUˆA·ª0Ñz­ „“ø%Q®–?£5šl½ÊšSÅ2Çcûx€q)æ éã䢻¯¨0$„#0”V °ìé}ôÛ1Ùf¸X¡®Õû]¡‘r=,–e¹3 ö°^?¢÷lëW@6Ëu¼Ñkæõ_ŸÌôå“öôí"'DÚU~œØòvò¦q‰såîžö»h¨˜ö—÷MðÇÀÆKÞo±z¶ÚÏ_'èÅ× È /ËW‘D?®"2ÛCoƒÖFZÂ*VhƒÆJë0Z%Døes;oŽWÞ¼n'⻼wVV7e5”sõ•zµ9/ß—ƒT Áƒ>u¿ä]²­äÚdËg”Ò€w7«ˆ/õ†­K™7g1¶!ã‚y!«rUýÁTªCfTyM•ͧEÒûjsŸ•UKóf}l ;GΡjÆ‚}þY5ÿý¥+ûõ¹*¯¾,fÜ,0®®–bX½uÇ-¿W¹lί™Í/Ö—€>æ £ø =ü¦1•2Nig̓R%¯DY]6 t>ƒÅð“§TLjö<ÃܸYR*§”–¦ý›e|G§ ½^—Õo˹eï]+ÕOõãð±É½ùOh~œAÿoLó =c=4¶Ãôqi¯åöçýïÀá×Á±‚ÔOO¼ö±¬«Â¤,† ´½RM½ÊßpÅaˆt|Xc¿æy±è2sZ){å; ³ÜÚ:C¯ÿH'!k?´§À©{s+ÓlmxÛ…`[ sÝ!ÃYmJm¸È ]Dá´Áêw-œœV4Y6¿¬ÀWᬽÒ̿܃ïwý1¾‡%|ª «#OÊæ9c®¹ Ðä•7Ÿ—+ÿ,{ÏÊê /G5h­(.yYÄìË#×,O Ñ}JKÿ\6¿*¶|S.ÿ£¬ž•OŸ¬ðßQWt¹ïýeÚÑih!½rÇ¿uãWÆjA¿l}C©ï뚦I«Ý5•ï–—¿Û˜sxŒ%ýO„ÍÖá§LI%íèãg»“¿ãÏ¿SÏQ—endstream endobj 83 0 obj 2249 endobj 87 0 obj <</Length 88 0 R/Filter /FlateDecode>> stream xœÍZËŽ·ÝOò #ª“t…ï"8@‚Èy@YÄ™�Æ^Œfôh»5I#9‚‘}>;ç’,ò²Š=Ó²µ0A%É"/Ï9÷Á~½£Üú“ÿ½zyöÛ/¥Û<{&6Æßçg¯Ïdì±Éÿ\½Üüñ½œÚH9kÕæüÙY.7SÕfÒfœÌæüåÙÅðûíÎJ?á†ýV c†ghThTvøj V‚.Óû`‡›Òö¡<5Óp= Ÿ—ÆÏç9Í ë m™©ƒ±Ã÷s‡¯Ïÿv&Íhe›óÇg翺~½Ý)'Ý8Ùá®Ìó¦LsYÚ®ÊÓ·åé¥ß“ÒvÛÛ‚âëjc:+¹í¬d_Úª¹îߊ?+×å錡a §†óÒøeò¯Òö¨<¥i|̪´ä¼Ôù”ÿ[çi{(3¿-mOçŽò'pú§s_”Æ?”!KÛ?'CçñÙrñhì[²R¦"uãç²2£vBÍÃηøÿd&7¼ØŠ1LVÊ@‡§õ4z/a j5"xc'G£Œ´!5zí¬‚éK‡ABû) /1‚Xx5ìßÒd°+vWgxQ‡Í£ÒjÍÔ(£3ŸókÈÍSïü„iÛ jÐѬ!ÀBµCwëz,S=Yí ;&í¡}y;á˜K`OÓ_õoh[rT¼¼-kdîà¤áSÝQW…}„c´y7¿'²O±ÇWë ™{ÃJeÒ))œVðr+ ]&ž z‡µ\×¹ö?_š›–pMÓŠQaÚýM~žú»™Û»òúMÃë—À9â,ëV¬ÞoáI¤·šud£w�ô¨€ÕHÕTØßìgéߺv²fØgSMÖfFÛ%7r•´†@ ðüŒ𣷠fУ%ø¾£ù´Ñ°ç=J#&ÞW)¬Ä&È0ÎF¤ÿ)vЇXt8š÷[È`<EÖxˆ8T:d'q›æ7 §‰´†¸ÙbûVk h'€iø+Q@)+dËÆ\b-4–N¥”¦O ‡å 9[ä/À aíLL õ#è}^Èá;:?+„Ÿm0^Û÷E¾zSè s,9öå4Éâ+‡~Oô8A“  ø~ÔÐK~ܹUg4aÑŒaëz­>kà¢ìêÄ(¤eë‹Ä ã C³²ØŠc[q·F7‹KÓ c‹1q¬Lž¥ñÂ飣<PPœh˜6™%…—ÁÒ뢘*çhúøI(öS޶ˆ$ݬ ls¬gÕ¶ÌÔ¨„-—š±>ò;OÎø}ÍR>´£\m:0+2oUÏ«ôL[Ÿ’D)òõ ˆ“œêéÉjE1¨ ”½î|åUÌ¥î›u¬0×Ãa…Loé¸#1=긂,èÐÇItÇ`<ùf-†éäí¼ ˆ´¬‰ÊÆÞ>¯³ÁÒ˜ /v _‡ëyY |™üvq°4×ï²€ë‰R–‰ìä& ¢ èa²$#Ãÿ¶ç߬´mÎ\¤ðØSí}Q­÷ØVx¯m׶̟Ђ)V:%q‚/Ć­eò\A›ñQÀîE|¢èèii«o¿-o•¶×¥í]yº,O‡ød…hr[Oô'Eñóz2ƒ«W_êèÕlf¤}õö0ŽnŠF¼‰Æ‹.تj2I>²¼EŽ «Šåm`ŠÑ„I!ž.“:=‚3Ÿó—bŒg#Šx‡`ÇÎ¥÷ˆ¼ài”¢¾©zWÑZg½«W&M1 x?5wµP,93¸ØcÙÞò$èåáC’ /¡œ Ýé«d­ù¿p“û®«b¨¨ïGXÇRLc‘RàÈ„GÕ õQ§Åň{¨Š‰,lÙ+¦Òˆø}j–¸¸ºòUÿãçenÐ�ñ-ÄÀȤ2ñõX_¿.ÒÃ<äeöµ6Lô§!m»ÜÄÐ×ٺ›^œs¬&â ²Ðl`3CÎÌ�[`¼9L:‹‡Àt<AÌ b�¯NVóÚý¢Ë”}ê<K} D*Æ´ÇÔ~1‰yíìÑ̓ý¦{6Jê ­ý<%¥o–ÔQAî&dnÛÁÔV»þ‡˜œs`k&ï$)Hu< °I}ôÃ`]aYc]þž­ŠÍÙrXA£-bž‚œ¡‡CbreQrþFì³)ü±4±iš¦Ï¼þîæ|½‡ËåŽYf|ÝE ûæeæ§2<"]“.ƪ .GÇ—L9s´.¬³Ö“Ld5§¸tïøï8Ëðä¸pô0rXÛ_vdzØn òlòÙSØ6îmbÃ…oèW“Ž…í©äÂΛ1œÍ´¯>ñy>z{œ‚QÐe‹ª1î¶‹€Ñnßxüè‡U ˆrJª&‘ZÝÃ{¥Me†é'7Õ^%CXµšÌ"«= ͪuN)‡ÖŸ ÒÚý‚ãˆ9Ñè•G¼k"¢s&© GÜ÷ÕÂm4Œ` h$(FTHyPvgaêV"»Ë·’㹎n¹„Ãëj±%z@‹ØQ#I¦xÒPí×Ì%je¹÷-ee©Y‰yâH¼?‘^š”y=‚WŽëˆY)¸n{î5—FÐÅ•lêäü y—4–y—'K=ˆ0Ã0##¢¨šdÊü³0"ö¹:Âi~Cƒéûñ0Æ�èÒè6^Šef=—(ûè6Éë¦su·ó¬\ˆ‡¾ê>ÅXÄ' ‘6’ â«1, \õ‹l˜{ jÉ.\GF=%Ý—<ü Øy„8vöÆmjÀæ¿ÐUʾ¦eÉ8ª©¿•o¶ËŸ÷‹JÍÂÑñ9cn‘¢fÜmE܃—?lX-u*"Å‘æJnö{¯ºÒ°ŸÝê\‡;ô °Ï—ê´¸…YyðL~Bq”>Ýq̽/Žd"McÍV¶5ÛQ~TÒ?LÝN5k¦°’GÂ'Ò˜4øiIL b¶¼èç5 áN áÄB'÷Ic¹ö²|6î2+Dñ¤ô‰‘‚¼ BFë]%#•# ý@«†ïç“^/êUq§,h!Y‚ûÁ¸áßéE˜áïÛhO†Ç´&„[]?LÈÿ;òG²:63rCú8••¶3ÕJã& ¢Fô>™5µû}áÕa½*É'~h³'¥t~jR†w÷YŸ—:çh8~_¯*Ì»/”¬_^"Y„‚l·W¹TŽ»&°¯ÆÍ²p³¹ÝJ]ßYé:ÃFÊU ÒVÚJ›ø’¼L‚nä “x•կʋäà˜Û»£»ÓIÅ{.™0Öì.jUîȱUêÇ‚«NÕ‡m”{Í+潨؀ï/böT Y¥Ë¶¹ýÊâ/Ít„Ú¹’ä‚éÇ=}wÝsrÍ'fÈûU¦Ý@?û\WìÒe(¯GÙdGñ8ouYü\ê÷aßMÚ )-˜°úÙÀ%¥þè«êt¨ ›g§Cû3MŠ_fDÑw R²Öj¢•¾˜?á, Þ•¸ŒæÈìj Æðõ¬ÖPûš½Ê¡?pHpžáï$A6ô‹†Ó¹t¿8¦¬·vÿ½Ã¬Ëm¾Ü6ñþç‡ýþˆÎ™~€äøªW€¯ôÓ…Uåæ”;V#.(×Ïœ‡YËÛŒ†iy/e²¹ïr¿ûÓ˜õª>Å^•êtýåÕÑ{R±C.Ò S/UÖ™ø—¨¥*S¦É{†ê{¼Ó‘Û¯~ÿs/ƒ*w:J÷&891¬ÿ]Êtüdy6_À¸eG¿ÄgAšF/û5åÄàs¤"³¸ÍErL׉ý‚ß'‚[ ‚ò%à/Ó-ýØñLJVmf'-Iñf79Ú@VhY$Ê#õ~t~öüù?¹è£endstream endobj 88 0 obj 2909 endobj 93 0 obj <</Length 94 0 R/Filter /FlateDecode>> stream xœíU=oÛ0Ýõ+8R|æ‘wüèX  Pti -ÈP8ë ¶;Aûó{4%“I”©C—@t ïó½Gê^@eò3~WÛny‰^­Qò®»ûOjü¬¶êà ^°È¤†Û®„£ ¬ Ž Èò¶»Ò—½&ôQï"z"}Û#yÆvñÐ/ #ûvu—MGŽ’^e‡˜§}¤ýÂ"’½>çæ“B„Äls[ 1ÕÂz°!5ÜHOWxŠw9Õu¿ ˆé½“’cý+‘%—ZóWo 2)ê÷Ë’Á³ÕËšìwO † ³üÓÄàܘŠS»Ø×Lëj6ßÊjä ·aòV`©ÖfW;\WWXõÄŠ~ªð$AÆÍP4¨†/ÝðN�²o�5a˺8Në\NAGi›ƒ';m‹àEã„6ïjÐlƒP€ éI‚ç9oì™ ÷º+CQ$ýXsí*Y›¦ì_p”!h€¯ÀæOƒÑ›òæ•W:ŒAéÐ#ކx*Ÿ‡žÅ·VnH£nÉÅVÖŸò…JÆ ëÍ¡Íú^CrÃÆF9ä¦67uÔs©Ÿ-�3 LGÀáË#@ìæî(þW¥”êL¯Iæ¼ßÿ8«ŽÕ4P™ÌÇ8ÿ|Rö5{ÓÈèŒìÎ(ÖÛ¥Á»á³™£9[RŠ'WÑ]½j®s£ϙͷW“¾a¾2ÛP¸™í*Ó„Q~øV !"•.ÖÄøÄùãÐ}•ç/SxÎ=endstream endobj 94 0 obj 566 endobj 4 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 30 0 R /Font 31 0 R >> /Annots[23 0 R 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R]/Contents 14 0 R >> endobj 32 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 39 0 R /Font 40 0 R >> /Annots[35 0 R 38 0 R]/Contents 33 0 R >> endobj 41 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 50 0 R /Font 51 0 R >> /Annots[44 0 R 45 0 R 46 0 R 49 0 R]/Contents 42 0 R >> endobj 52 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 55 0 R /Font 56 0 R >> /Contents 53 0 R >> endobj 57 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 64 0 R /Font 65 0 R >> /Contents 58 0 R >> endobj 66 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 69 0 R /Font 70 0 R >> /Contents 67 0 R >> endobj 71 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 74 0 R /Font 75 0 R >> /Contents 72 0 R >> endobj 76 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 79 0 R /Font 80 0 R >> /Contents 77 0 R >> endobj 81 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 84 0 R /Font 85 0 R >> /Contents 82 0 R >> endobj 86 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 90 0 R /Font 91 0 R >> /Annots[89 0 R]/Contents 87 0 R >> endobj 92 0 obj <</Type/Page/MediaBox [0 0 595 842] /Parent 3 0 R /Resources<</ProcSet[/PDF /Text] /ExtGState 95 0 R /Font 96 0 R >> /Contents 93 0 R >> endobj 3 0 obj << /Type /Pages /Kids [ 4 0 R 32 0 R 41 0 R 52 0 R 57 0 R 66 0 R 71 0 R 76 0 R 81 0 R 86 0 R 92 0 R ] /Count 11 >> endobj 6 0 obj << /Count 3 /First 7 0 R /Last 13 0 R >> endobj 1 0 obj <</Type /Catalog /Pages 3 0 R /Outlines 6 0 R /Dests 5 0 R /OpenAction [4 0 R /Fit] /PageMode/UseOutlines /Metadata 107 0 R >> endobj 7 0 obj << /Title(Introduction) /Dest/section.1 /Parent 6 0 R /Next 8 0 R >> endobj 9 0 obj << /Title(Test case execution) /Dest/subsection.2.1 /Parent 8 0 R /Next 10 0 R >> endobj 11 0 obj << /Title(Usage) /Dest/subsubsection.2.2.1 /Parent 10 0 R /Next 12 0 R >> endobj 12 0 obj << /Title(Technical Details) /Dest/subsubsection.2.2.2 /Parent 10 0 R /Prev 11 0 R >> endobj 10 0 obj << /Title(R Code Inspection) /Dest/subsection.2.2 /Count -2 /Parent 8 0 R /Prev 9 0 R /First 11 0 R /Last 12 0 R >> endobj 8 0 obj << /Title(The RUnit package) /Dest/section.2 /Count -2 /Parent 6 0 R /Prev 7 0 R /Next 13 0 R /First 9 0 R /Last 10 0 R >> endobj 16 0 obj <</Type/ExtGState /OPM 1>>endobj 23 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [78.2037 524.944 170.76 538.393] /Dest/section.1 /Subtype/Link>>endobj 24 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [78.2037 498.784 210.36 512.233] /Dest/section.2 /Subtype/Link>>endobj 25 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [95.7237 484.264 222.36 497.713] /Dest/subsection.2.1 /Subtype/Link>>endobj 26 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [95.7237 469.864 219 483.313] /Dest/subsection.2.2 /Subtype/Link>>endobj 27 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [122.724 455.464 191.4 468.913] /Dest/subsubsection.2.2.1 /Subtype/Link>>endobj 28 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [122.724 440.944 248.76 454.393] /Dest/subsubsection.2.2.2 /Subtype/Link>>endobj 29 0 obj <</Type/Annot /H/I /Border [0 0 1] /C [1 0 0] /Rect [78.2037 414.784 252.12 428.233] /Dest/section.3 /Subtype/Link>>endobj 30 0 obj <</R16 16 0 R>> endobj 31 0 obj <</R21 21 0 R/R19 19 0 R/R17 17 0 R>> endobj 35 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [137.484 364.144 145.356 374.056] /Dest/cite.xp /Subtype/Link>>endobj 38 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [220.044 155.944 227.916 165.736] /Dest/cite.beck /Subtype/Link>>endobj 39 0 obj <</R16 16 0 R>> endobj 40 0 obj <</R37 37 0 R/R21 21 0 R/R19 19 0 R>> endobj 44 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [371.244 733.744 379.116 743.536] /Dest/cite.junit /Subtype/Link>>endobj 45 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [269.004 719.224 276.756 729.016] /Dest/cite.xp /Subtype/Link>>endobj 46 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [159.324 690.424 167.196 700.216] /Dest/cite.runit-sf /Subtype/Link>>endobj 49 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [337.644 308.344 345.396 318.136] /Dest/cite.tfg /Subtype/Link>>endobj 50 0 obj <</R16 16 0 R>> endobj 51 0 obj <</R47 47 0 R/R37 37 0 R/R19 19 0 R>> endobj 55 0 obj <</R16 16 0 R>> endobj 56 0 obj <</R47 47 0 R/R37 37 0 R/R21 21 0 R/R19 19 0 R>> endobj 64 0 obj <</R16 16 0 R>> endobj 65 0 obj <</R62 62 0 R/R60 60 0 R/R21 21 0 R/R19 19 0 R>> endobj 69 0 obj <</R16 16 0 R>> endobj 70 0 obj <</R62 62 0 R/R60 60 0 R/R37 37 0 R/R19 19 0 R>> endobj 74 0 obj <</R16 16 0 R>> endobj 75 0 obj <</R60 60 0 R/R37 37 0 R/R21 21 0 R/R19 19 0 R>> endobj 79 0 obj <</R16 16 0 R>> endobj 80 0 obj <</R62 62 0 R/R60 60 0 R/R21 21 0 R/R19 19 0 R>> endobj 84 0 obj <</R16 16 0 R>> endobj 85 0 obj <</R62 62 0 R/R60 60 0 R/R21 21 0 R/R19 19 0 R>> endobj 89 0 obj <</Type/Annot /C [0 1 0] /H/I /Border [0 0 1] /Rect [438.804 372.184 446.676 381.976] /Dest/cite.junit /Subtype/Link>>endobj 90 0 obj <</R16 16 0 R>> endobj 91 0 obj <</R62 62 0 R/R60 60 0 R/R47 47 0 R/R37 37 0 R/R21 21 0 R/R19 19 0 R>> endobj 95 0 obj <</R16 16 0 R>> endobj 96 0 obj <</R21 21 0 R/R19 19 0 R>> endobj 36 0 obj <</Filter/FlateDecode/Length 157>>stream xœ3±T0P0U0S01V01QH1ä*T0¶�Š€(S=C ¶THÎåròäÒ÷ôU()*MåÒJré{€I§�gC.}—hC.ƒX.}7}gg7 7ÀÆFß[A(㜟Sš›W TlgÇå颠¶àɃš/â÷÷÷ÿòßÿŸþ?ß ÿ·þ®¿uëÖaîl †.WO…@.�ÿ“.à endstream endobj 62 0 obj <</BaseFont/PMALJH+CMSLTT10/FontDescriptor 63 0 R/Type/Font /FirstChar 34/LastChar 125/Widths[ 525 0 525 0 0 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 0 525 525 0 525 525 525 0 0 525 525 0 0 525 525 0 525 525 0 525 525 525 525 0 525 0 525 525 525 525 0 0 0 0 0 0 525 0 525 0 0 525 525 525 525 525 525 525 525 525 0 525 525 525 525 525 525 525 525 525 525 525 0 0 525 525 0 525 0 525] /Encoding/WinAnsiEncoding/Subtype/Type1>> endobj 60 0 obj <</BaseFont/VBYXOH+CMTT12/FontDescriptor 61 0 R/Type/Font /FirstChar 40/LastChar 121/Widths[ 514 514 0 0 0 514 514 514 0 0 514 0 0 0 0 0 0 0 0 0 0 0 0 514 0 514 0 514 514 514 514 0 514 514 0 0 514 514 0 0 514 0 0 514 514 514 514 0 0 0 0 0 0 0 0 0 0 514 514 514 514 514 514 0 514 514 0 514 514 514 514 514 514 514 514 514 514 514 0 514 514 514] /Encoding/WinAnsiEncoding/Subtype/Type1>> endobj 47 0 obj <</BaseFont/CTGDUP+CMTI12/FontDescriptor 48 0 R/Type/Font /FirstChar 67/LastChar 121/Widths[ 700 738 0 0 0 0 376 0 0 0 876 0 0 0 0 713 0 0 0 0 0 0 0 0 0 0 0 0 0 300 500 450 450 500 450 0 0 500 300 0 450 250 800 550 500 0 0 412 400 325 525 0 0 0 475] /Encoding 103 0 R/Subtype/Type1>> endobj 103 0 obj <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[ 96/quoteleft]>> endobj 37 0 obj <</Type/Font /Encoding 104 0 R/CharProcs <</DS 36 0 R >>/FontMatrix[1 0 0 -1 0 0]/FontBBox[0 0 1000 1000]/FirstChar 136/LastChar 136/Widths[ 49] /Subtype/Type3>> endobj 104 0 obj <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[ 136/DS]>> endobj 21 0 obj <</BaseFont/VABMVS+CMBX12/FontDescriptor 22 0 R/Type/Font /FirstChar 39/LastChar 121/Widths[ 312 0 0 0 0 312 375 312 0 562 562 562 562 562 0 0 0 0 0 0 0 0 0 0 0 0 849 0 812 862 0 707 884 0 418 0 880 0 1067 879 0 0 0 839 0 782 864 0 0 0 0 0 0 0 0 0 0 0 546 625 500 625 513 343 562 625 312 0 593 312 937 625 562 625 0 459 443 437 625 593 0 593 593] /Encoding 105 0 R/Subtype/Type1>> endobj 105 0 obj <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[ 39/quoteright]>> endobj 19 0 obj <</BaseFont/OBAVOW+CMR12/FontDescriptor 20 0 R/Type/Font /FirstChar 11/LastChar 127/Widths[ 571 543 543 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 489 0 761 271 380 380 0 761 271 326 271 489 489 489 489 489 489 489 489 489 489 489 271 0 0 0 0 0 0 734 693 707 747 666 639 768 734 353 503 761 611 897 734 761 666 0 720 543 707 734 0 1006 734 0 0 271 0 271 0 0 0 489 543 435 543 435 299 489 543 271 299 516 271 815 543 489 543 516 380 386 380 543 516 707 516 516 435 489 0 0 0 489] /Encoding 106 0 R/Subtype/Type1>> endobj 106 0 obj <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[ 11/ff/fi/fl 39/quoteright 123/endash 127/dieresis]>> endobj 17 0 obj <</BaseFont/VEAUKV+CMR17/FontDescriptor 18 0 R/Type/Font /FirstChar 45/LastChar 119/Widths[ 301 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 693 0 0 0 0 602 0 0 0 0 0 0 0 0 0 0 0 680 0 667 693 0 0 0 0 0 0 0 0 0 0 0 458 0 0 0 406 275 0 0 249 0 484 0 772 510 458 0 0 354 359 354 0 0 667] /Encoding/WinAnsiEncoding/Subtype/Type1>> endobj 63 0 obj <</Type/FontDescriptor/FontName/PMALJH+CMSLTT10/FontBBox[-20 -229 617 694]/Flags 99 /Ascent 694 /CapHeight 623 /Descent -229 /ItalicAngle -10 /StemV 126 /AvgWidth 525 /MaxWidth 525 /MissingWidth 525 /XHeight 442 /CharSet(/A/B/E/F/H/I/K/L/M/N/P/R/S/T/U/a/asciicircum/asterisk/b/backslash/braceleft/braceright/c/colon/comma/d/dollar/e/equal/f/five/four/g/greater/h/hyphen/i/k/l/less/m/n/nine/o/one/p/parenleft/parenright/period/plus/q/quotedbl/r/s/six/slash/t/three/two/u/x/y/zero)/FontFile3 97 0 R>> endobj 97 0 obj <</Filter/FlateDecode /Subtype/Type1C/Length 5603>>stream xœ•Y XSWÚ¾1æzë~•¨½—êT놻VëVQëŽkë.($vHH„,'+B–„Ü—©Ý”hµŠÚj§ÖnZµû2ιýó<ÿI@gÚéÌ#>йœó}ï÷½ï÷~WѽÁãñ‚ÂW®[±~ý¤‰ÞoFrCyܰnÜóüL”Íýó·eЋzu¯ö<ןcûAW¸£/ÁçñR²5áâälIB\|ZèKÑ£C'Íœ9c\èä‰g†¾š+IˆŽ…®ŒJ‹MŠJÃß$†®G'Ħe‡¾4;>--yÖ„ ™™™aQI©abIÜÜÑãB3ÒâCׯ¦ÆJ2bcB‹Ei¡«¢’bCŸÄöä/áâ¤äô´XIèJqL¬DDļWE ÄÉ)‹$‹SÓ–¤/ZžµsEvôʘU±»VÇůMX·~φĤÜI“eS¦N›>|欿̞3÷¥ÑcÆn7~{Ø„‰1œˆ F«‰5ÄZb$±ŽE¬'6£‰×‰1Äb±‰'Æ›‰…D±ˆ˜@,&^#&Kˆ¥Äb1•˜F¬ ¦+‰UÄV¢?1€ØN $hb1˜àCˆ¡„€xž`–"zÁD/bñÑ›˜Gô!úýˆù¸Dw"›'à¥ñNv›×í#ÿd÷EÝ¿lÜ%SÈã=¦ô8NͤÎõ²ýÔÓlþ¾×Ž^gŸSôØÛÓg\Ÿ;}×ö½Ûïõ~Uý7÷ÿhÀØ®“§_¤«½0H> ž4…,Q‡\Æ áÙ9Ä9äæÇCZ=ô!çî͹çW÷\5›Ä}Jkë5¶X@)É òv£]ëCRIi Ø-nåì#ÒÞ�ö6¥1{äWœFdÒd°GÔ�ìøcG=Ø×˜ Y4„ëAÛ8–4Pú=$ÈÙzy9R„ !é»^ñ𸰫|®»‡Þá½a¨Ç“Î:|E ±1ä>¸½ø°Þª„·¶î}íâ] 0Š™ò>Á,ðÞÝZ¹]l8iràIupŠå ­¡öôÛÇ=€:V’%*ÔåéTlg,¸‡q•§q~z¨›œõX&Øp¨Š„}ÿöÏ=Ñg—9Øöï»Þ¤>Ø|ù%±«hؼcÈÜ´5|$û"¹¦ |ž|`~Yºbý²‰ÞëTxËû×[®ð9#´Ò°ûÜëãQ?Ô õE,¢>Yò5ì{Ã`8‚Ar´^²ÃsãŸÝ¹ýÁÉõ ÇÏ1É{’xà„N ·ã œ¦Ý’Ñy@Áç`/_€Ýçߘ¸v[JV [ì1Ï"5åq#F*Wò»HÁ0‘ŽYUŠ ©»°4�ƒý§b{ý[ïµ½ ¨ GÞGĤÉÓ¢øÐû YÊ ¦N &ª6Ë,Ý£•í(dä΄£á€BQo„Óãßš÷ýõ3G•l<мîïøJgo%ã "I4±ró™[ÜýúfÕüEÊ%*›¼|õú%€ê,ZºîððànØFÃA¤®H“ Š(‰K]Þh.¯22?Jq0¡USµ'Q+‹,dÐ ²î@ ©I/Œj*µªÈÑl(¯11¶«8t#~Ú×WƒüèÔùz ÞßK�z³õŒ¡ÜÖ,”Må%i¥’"F±H€ªºÚûm†‡ž¡ÝKN˜_ Í-Îï6÷½O>{ôÑMêR@ÕW¹êÏÍò±KVÈd¬ÁnªyÒ稛ÿú›]ìö~ñ`l¤áPR ´@E‰Aq³ÁéÄéÿd(ó¥ï o6'ºˆACÉýp·�þ4ý~þniô¥@ ,ƒ<vù´¡a?Ìóð¹%Üt:Öý:â¢Ïˆš³qæ½ÜïrÙc…—òA$¥¯ ‘Û6•]S0j—Ö‘’€¶@ùº6O¾R96ye¥Ñ²¯š9s¸p3Ï;øÝ©C™ IÕì·Ø<Ç¶ÉºÖ öR5Ç!ù™>QªgtEʘc l–¦º’SÀH•V¦¥©¤…¦3¸+ž_ªyp>¦ÉAޤálÐÒþi@—$is¥&w‚`¢?ÿOɤÐä`tåÂYŹöáU/¤ù*‰š‘Í_¨ÎÔ °ÏacųzRÏ¢›HGCZ(˜”%w¡XMîFÛ(Î+q‚?|Æ ½ˆÌ}"¿0Ø}éÓ–8rÊøãgž Àƒ$f¨œë÷„¡ÿ.Ÿˆ–ŽSåJã¶Æ,Ô2­«¢¸ä¤©ž57šͶë!Þ¿û“;‘ÞB8ú'ÐØzÌÒt”1ŠÜÀ ¨ÊâÆ“a`„(ðòóí_ÖHÐqmþ’ý¥+¥ž=¼pN"xŽ®—Bz9 ñÁœd—ÌUÒf:øͭ P7­–ªµ™:5»Hƒ¬ù�¡–¿½îá›í¶úÃLeò¾¢·ÕPëÃK¦Èætví'´*A“—™’·³ PoÄÕ¸{ï‡ýŒìÓ àWðÿh¸®¸üYLé ¹XYT‚ªŽÃ*Aƒ?ò‘~È*|)&û3üÉSé†BØ}Œ‚LÉSÒûÎIiìSyá¢q;'Oª¨N­©UìÄ‘«4×<éó ÿUÈè%4Ml÷ÏuHuv`2ÈdÁ>WQA|Æôƒ¼Áy?ËcãÈ‘pš ³z  kü”sç¼}eÀäû÷îxù±Z“‹»C-ôÊÃN˜?Vo¢{ÿåðé*D n¥voô]4½“?^ÁmñÁ¼“”‰»þ ~V¹E@•¤•¥t*w¡·µPìÏ%zx•wùœãÛ@Í ÿÑn£‚¤•šZ`P5 7@𠉞¬'?EШÀ�è„@9C)Û¹b—6Gg.6Û•r(«E9 Šm;›ÄGn_øâFæ©¢>º Í_ñ¹,È£íJ»$]­ÊU2i±‘éÛ5kKûÕŽó°dlÍ@SÊêuz­P9 þˆ³¥ìð•0°-ŠÆ éÚ$Œ±ðí‡.ÆO¿XNN[+-åærJOÎy,äøéwûI'd°·9™ ÂßÀ}¦P&žf‡¤m­‘ÅS:RóN$,Q+«r@. "žt ›õBÿûÇ~̉zÒ˜Xº¢d‹mž%Á”bÙmÌhÄã§8Z¨À ^ÙÙ\¿/ZÉhZnÕ®¦ Äö©êF î-¸ú¸«å «+Òi€’òÞÏ<#Dh“Š^³ýôMÈûú«ÏnT½–¡.J*ØÂÊf.z퉻ðáTý¬~¿(ͳ1l:r§.Ü'5&aøÐíG’ü7N„Óÿñq‘Yb–ÂbÒ À¼·+ñaíp ‡w÷*lÁ¹GÂut³ü ׺… žØE… Á—³¡�ºx·Þך¢œ|6eç–¬(@­œ{ð¶¼®íè8wP߃—Så@«+|ªxLóàïì0ƒH“K_jª¶ìol» Œ‘­À(G³íÀ»¯‚œÙ;¢å [(Eîj„ýo|Ž;�Xç?rl—KYáŒdVFC- û’pð}ØýÇ›o|Œº±(ë?ø,lêžÖLBâf¤ÿN>lX½"bîHv¸¬ÙíðÕ÷Þi‡ÛÚyös‡¯Bõy>LòÐxÝ(0PŠtpÀU^e0²NE³ô( ~¸ûåÃZ•[YÉ6:ÜÆr½Yâ*°Êåªh¨·®M‹*JÚʦ¸¬{�õâÔÉ✉5›•&ÛŠ ¤:Ò¦m“/�éÔ¢ÛËáÌ>Úó3ìƒÆ˜¶1"؃ޚ´ÿø…síž{wo[¹&b+BßÓc"ÚT:ÚŽÖ±N¸¨û÷Á¢/F‡±OÖ ŸŒ†ùeô÷;Ý Îÿ¼ÝD#•àZ®pL Ϧ.sÙþãJEÇàRîøýñÑÖ+àêÚºHÀ ¥ÿµMñZÎgî7K·f«Š$ºV±(A5ïdú¡kMŸÕbQ(”J¨ˆÑé”Û3ðöYhj°™›Lu¬©ÖÜ�Ê©RàVصB‚Vz¡ïÄëäç­£6¬]2úikßvÇ>ïíŸùÜ(î"]›å'¦‰%)®Œú¦ºº&l Qÿ�4ÎøÛuù¼Ñ‰}§FÃö#‚ôá•`î ¸ Õ—ù\w‹Ö›ôÅÀ@9òí™Y*y‘†: •‰w¶­·Æ`÷ÛcÜÔ1oÔŠ«3ØÆäzÕÇYï熜’»ã@,µ*"|J&ê¾sÌ ˜ñnKJ)0j¥MŸ®6YU1Gã.+ÞÄ“’þ_¿¿?¯œMnÈ2¨Ë2'« ‰¶Ô:p:éÜ-(ÐO傌ֺâR·‰ù³5øO=ÿPoü@§x-Äçæ4x—ÂîzŸÁAÁ_©×ì4¯úí϶§› Æ@Ý%4í=GüÝ€Âüƒq/‰"ÐØ÷à7°/ó—ç¸ï®À 1,pC4ØŒî’S÷? yˆ&¾ƒ€=ýUMÆ;LùÜ! ÄþÎ3|ª7(P|Ö¢ïd3‡/ÂM;}XŠ 6ö<|$øO?àÝ8TˆºÝXüä߃ÄwÎ�܇þ Ñd?Ÿ±ú\î€v¼` úú·HnÛ»|¨ôÐ’Ôg½`³æÌü’úšKG[÷ªÔ®‹Sê4Xí£Mð{Ï—Ý(¿n»Q|X€“ÂseþºÑ %#?¼§L$ !?9MÝîÝݺÞyÔ€FÖ«ò~ºßýóëqì/{à_½_<(ÃÈåÚiSMñ Ȩ²z} Æ#wÌHI˜”MF³4ÊMh¸F¨”èŵ:‡ýWíV•l–&UÅ+×{É/:16 b½ŠIÒ‡éÁ1Plë0ØKÏ•¥`_NCrÅÅ–’“{×ôîíù¹šÇó’Ô¢7c’Ú•ŽŒœB…JÍH%Û^ WIuZD),9õÛ*ÝÍÌâÇÓã dôëé]›‹ÆKÿ{ÐÖÁç‚áRŸ½s|N}3ï:ËÃg£î«$Õ9îWM]©Ê¦635Gκ¨>Ø3 šžƒëZ‰^—*Š €Lès%ð>Y*¥ÖPj9J|ïMdé`«–Arò?ö¡ˆªÛl+u•/ÉÅ%7ê,L³î¡D ÐjrSФNþªÀ†ìQ~¤:]«”MÓæhdZ©FZ¸Sµ ÖRŠ\EŽÂYuÝà>;ßbÙo}Ë ™sSÉ ø’‘2Õ›SõÒ¼†SC 0°>6AC»w¹½|¶á™už¥ì[»mñ«sGåL1œ•°&£Ýj¨úLGú°1ì£]ßÀÐ_ýø¦øíˆ½Ìƒ³Ÿƒzêü†+(ݰpc|KaYMmU“­¨è™­z Ú$Lj2"cEì®ä$m‚vµZ¦ÃÕòaÖI ÂÃá sè�Þ, /pmm6ÈB1™ ,xL„äçÉ@nçÙˆ, ø×üG¬#¹rZO®A? ¤S@`‹NÃëæ×°§lðê©&À=¹H ëTñ‘¨¼z5%µÊjœF£ÕÊœ:}ÁÜ ¨Ž– ëÇŽ_01j“ó¸Œ--.ubVÊjD[ÀùSîl|�Á~?Á—Ý‘¼C¾¥sÃàLïá‡Ðo^¿¡À¿ÿ °—Î!W) A•æÈnp×—Ÿhß´w!z-Å¿ëÐè[K¾…=`ßoáðÖ=DTĆԤXæ t‚‘5£IêV´zlô &þ³åøa³ùXÛ@}Q³p׈I᳽冷]Ђ§êv(x øðç¡õFƒ˜©Š¼Ú¤Hu”BÇd¢ÍZ™@ ’[êŒN§‰i0òÏŸêÌoæx·w¯«°Ój5tÓ1hØè—§âÒíYv«ÕlÃÀ%«§§(¶.¼’qŽ‚³à$è€#]?=œûîHýõ­Šƒg4²„žš~}?ìöíÿ�PZ+Çë¿Ndº¢¼å‹6Îë´øØ¾-…ýxÜ`®'ݜ֟›äN>ÐÚÚ|ˆÙˆÎÿû?z éò´sÊv†$äÌ»Äçqg鳪ætK¬LY ¤TvyZÓiÛ•[Ï,eÌMÆJ¼{=B²&'EÍhš,ÿÒåiQÌðWÀlqx)$²b,dj)hÇ7é Fƒ½Üd¥T}º3c3X#üþæ;J¦HŒ‡ŽšÊ¶)*ëMÕV=cª6”«a·²_‚ïÁ'«ÎϰSvz5¶ «ä{—N\(£œ¨‰Þ«:ŸV‚Õk7,”yó×ÅíÀjäréR‹½TRîìòU¶0AQT–¢Pe d—+Íjxņ8ò½/©Ê {ue~q¡™E6¸Üû2�¾Ññiï&'âsø#]Ö öïõN±ÈÜxßâÕÓOÐ8Ú¹’èý‘ŠüÉ!ü‰?–|XCW•—;¨Ì+-2¢306DZªÀ¶ŠÊÍ’§eÛ Š‹XXŠüZ‘¯’åƒlaze^E‰Õh.ñ–g¦ë·T\Ëùh`/°È­/Þʂݰñ¾Ý7Á$8Èb²;e+p¦G£r4Ž2O9?…iŒ>Ѩ:Ku ë?ê>j<׋ÇT_®ù*¹-Â#”D•Y +QÙ”ìÏs«P7°¼"F› V©1!eT9³þ nÑ9ð¨7¬{.nH5ïWn¦÷AÛ,•V¬Õ²™R£U)¼¬ööJ,0 ËóíÙù’¢ø"&õ÷~žµ› azNf¶ÌRX^Èþ°¯‘«r C¨4gÕ”ãna`Ÿ+éˆÒȰú sÊóe5ÅfFo.>£·Z/‡|»×˜Ð]Q]éTZ”fvT»·x˜às:àÜjÞ]n=~ ki8Š´y ä,FÖÂáz3^  YeFR‘(_ËHÐXEʽÕÝl,F¦¢áxßV­0Çžíj67•: ó[†q6<Ƈ¿¡5Ö‚  ²rs³ð¸2KY¸ûŸáæKvV;**K´­Å÷ ¬ öÄü„»àp>ܧ§Å«¶ÈrT*]– dRò²L×IØýãŸOˆÛ¶G¦Ä퉫Ïh)1�½Ñ{)¬íàýƒ›Èçq:þ\®ùÆq{\g:xp%¼Åçúq?Ð2«wfª½ï1UhÈÒ¹JQ²)1¶Ùb2˜­ ¾ø ®4ë0Š.GƒÍ©4+ŠÙN)ñ†ÙŸï^ùÕð‚ðW®†Ï½ÿ[Ú\l*ÆÄ®ÊufeÊó ™Çëÿ¹¬P®Qa¶#§ºªÄVjaž®¯Á³Wø\7†ôrÈ{ ÿ֢(rù…áóp(\w0Ⱦ¤—Æ|ö \ñ ýòúÁi“И0´r$Û[QÆ…[á¼2…“DÙÅ=<=¯3=»g‹{ÄÿUë¯ñ endstream endobj 61 0 obj <</Type/FontDescriptor/FontName/VBYXOH+CMTT12/FontBBox[-1 -228 524 694]/Flags 35 /Ascent 694 /CapHeight 625 /Descent -228 /ItalicAngle 0 /StemV 113 /AvgWidth 514 /MaxWidth 514 /MissingWidth 514 /XHeight 440 /CharSet(/A/C/D/E/F/H/I/L/M/P/S/T/U/V/a/b/c/d/e/f/h/hyphen/i/k/l/m/n/o/p/parenleft/parenright/period/q/question/r/s/slash/t/two/u/w/x/y)/FontFile3 98 0 R>> endobj 98 0 obj <</Filter/FlateDecode /Subtype/Type1C/Length 3445>>stream xœ¥WyTSgÚ¿!äæªˆK{Ï€õ»7ÓZÔ¢¸Tq­K±ZA\m]+ Ö@HHØÕ°¼ì Èš„�* ¨E[ÁZé©5J]ZÇQ«Nµu§¶£Ïõ¼™ïûn´Ú?¾óÃ9áž÷½Ïóü~ïïyÞßîn„H$’‡†N™jÿׇMÄvãÿKœµ¼éy yˆ‘‡ûѯx„#À0 Ö 'Ä"‘B HHQFm—«dã"ÆË¦Ìš5c‚lêäɳd ã"•Qañ²à0•<2.L%<ÄÊV+"¢"U)²qså*UÂìI“4_X\’ŸB¹}Þø 2M”J. ‰LŠT&Gn•-VÄ«dËÃâ"eŽêü?Џµ*R) VlTÆá»0^°(ñ=åâ$Õû꥚0mø²”ˆà­‘ÛVÊ£V‡Æ¬‰]7uÜüñý&ÄëÄ b%1†XE¼I„>Äjb,J¬!Æk‰·ˆ‰w‰uD�1‘XO,"üˆ÷ˆÅÄb ±”$¦Ó‰e„?LÌ –¯ƒ1˜ð$†É „;‘Lü +Úã&q[çÆ‰ç‰Íî#ÜMîÿ‘è$?’È.é"é—ÔXJ;ÈmÐæAχþÓÙŒ!¿xz<ºxèYωž ÏKÆ}7|ÒpËð§#F˜3"‰ßãÉïA¸süP£¨™ß"†/ùÛ´®CƒT(eådÇàá¶}^Ñ*ߌªØ‡dU3Ú¿? ŲMà.² »Kb“~½¬BÑ,6À<ºìÀiØQò'ª€,RU-Gù'qŠ—#ã7œè¡B­bÞŽÓÿÜt|Ö’"µ©Ì!TÁ,%3…ˆMBÄNÜî|‚±dU“ e°á°”|Ôsìs®2:„ÁiáÒ—ï"…|z¾ãDœLB¾KÈÉ1‰Éãð<òGßgÏ~|#¼Ϥ‚¯<¸wöÜ… g—úù/`…�Y_É>¶Âç=b>ž¿A× ³"Ű#;‡ÉÕéRr³Ã;6U‡! Ó2Ìà%8Üðk0]¿÷}K2ÊÊH3¤æ±:<Â';Q~þ _ð½ ÄŸÿeˤ*¶H]¡7"ª Õíé°’ƒ©ý[Ű+iàѤ%áP|7¢žÞ{�¯À°ÿ|ãÝMíÜŶ¡ê_³g;èÂÞS>þ¢»Ûz‰{wŠï’%‹l»ÕÅô¯ãD7¬PkŸáxÁhÓi\Èß@}^‡©0m&øboKl]4¯{ ꔀ›ÄCWbO,rpuZÁ(ÐÈËè:ÔÔZF+Õ·}¼X L4~"~{~?D—;™M,NÚ,ÍHèÓLr*A€½™  W¯Ÿ9g~ðå»÷/\¸zåØì`GýÊAD/[^Ö _Ó¡“/RŽ´m­¨¡Ž¹)u¤ÖÊì·žLAªÖ6d®gÎI[ô»£üßä@Úf›.ÁùÄ¿J¶•U´²×¥õa£Ô‘¸‡ŽÒ Ë®Š!VÑ0äæÅ[%¥(¿„)Ú¾/· Q 5µæca5ëÞ‰[½‰=âHæãdõ î™ïÂq¾Sº¯“Ž â9Ñ+Œ¶ž°Í4Œ~9¶Ñ/b³¹;ѰéâœOð†3ßg«\ä šó3yŸ^¥'éUùL„eÒ'6C=3*Ü¢8¨e[Söndɾ–‰B©mQr¿ °ÆKÉŒ¡*wQBEvŒ4 ©÷UV Îjæxäg¹-ˆ‚`»ÁÃMÊØ·«WìFG©æ–ÖûŠ7'2…šºÜJg'èí]ð³±—ã·ð±ü Z:5cÿ¤¾*…™åïPŽÈÛ¸„ô;uéóÇÍOŒÈƒÔÉLþŠ*D½ƒº,¬ƒÛ4Â9Ñm+ȉ.à»h³#¶¥³XääɌñÂÍN9 «éʾdf›Ní8ÃFT͂ȹK i ÇijÆEduc_õj²âÀ0äGѽGö«GÎZ¢Þ<u´0`‘¾¸^INú«âo_n¬52Û-¨–9÷›èèpP @>q!Ðì ôĦ{ÓEŠfç®7íA &xΉªy­˜_+ƒ¥±Ÿ u ×aN’Oæ4¥uïlM±æVF£”“•¤Y’Ÿ›Bå“�'9áÂcßÛÈÂþß+•×ä6 ï#¨°ÜøuE{Íé¢fáö(È,Q˜æß/ÜuÕ"#*;D9˜›Í=åDÝVÐ ÜM…Cô•køµ°·Ðâ„útsi[áÑ•˜ + ö¢JÔ€¢6e‡)PüʼU9Ášu©AÛÑjÑW+)éøŒ1FwåF”Å„¨),Í`ÏÑÂ…˜®•§nD¹ˆZ¹¥µó/ÏÂPÖ9ÚAIƒ|%í.ìŠ|Zp ÆÌûYÒ`ùÍŠév†`_á&š)‰rŠ›#Ž %°·aä]<R¢Lê?±3‡¼OD×8 .Œéüùud«°Oaj˜ö3¿sàAî¿C�a½|¡ ¡Ï\@¾å,ºÍ¦‹v™œ„crÞÖ:&g ˆõöɉµ0˜×p¢£ós15¹ÂÍ ‘TÌ Ás2BÝÌ9{v6ûA¾WÃË77“ öâ(å{£¼Äié ýNåÆ %EE¥hÕV£R¦§ª"[#ºº¼ˆxߺj÷"ºI‰tª]†Q‡®×'!Ê?à⽓û…£ýC³)/¿‚-Ë+ÈG†¢ð–üRD™ë«›¿öAáù¡X6{Þ 0ªýq ;@[O7Ôw‹áSž¡3ÃÓ6è£0º®iPW¼£AƒC°¶¿šX›Nš¨ìtÅS‰Y^S --ÚQ¹ý"Nò*ÔU(ö r®-/¯+©þÚPeS¿üE´©¿Q×’[‘>K—H¹ æP¯`„ÁóÁàÙdZMøÁåˆúã$_<»=þgë±#æz6 e~üë)^ôêM³¬º|÷aOÏE뉕ôñ+; ¯ ]ÚõçÄü4¥Mõè Zz_<å7V° #À>q§©4Ï«Õg§ëYåª@ƒÍDK¿Úñ7ªà4½÷–µë+ô/dò/^Gõ·¼*È2Ðúäšýjê"Ë¡]äÕ ¨•É+ßÖVÓP¹ï‹ù(}þœ-S™5ãœ÷Ä¿pÏ—™Wî|BßõÂêí«¼^cQ@Ãp¨ ?Þ¹p“,Žý=ß�Cœ:M yûSòá±÷Ö†l~"ûG²ß÷5í‹NB^œô6Ýÿß ÷òöÃ]ìðœæÏÒ£R©Ñ(•FMc£ÑØÈàx´Ó>Ã=˜tAÕâŒ7n‘½5Xä“g óŒ˜_Úg‘“ótaYÌúc!erACó翽²}k©ž=V›óoå·©µ9Š:õn%RPk¶¬˜;=àÐ÷&¿:¿6®Ï>`¦×?˜ ËV2§·|Ý)øÉÅܹ°å“Üb6¢S[ìcQ•n­Ð†WG·£O©S]þúÛ“þ{™"maæ>§“pôb“FYÁ»ïï—x¥d´NÍ.•¬üFÙt\(þÓä¢''z&ôy;” Á’.ZôqØNbì'_ù–;W>µé6»íãâ}o’W¿.‰©’˜þO-pw†O P̉¾µB¦ ¥ ]³Ë˜â"RüˆÄ¢À5¬ : š¥¿³ïgÁÐ7ññãïîÃPæ·.¢o\à±.‚ô´é°§Ëó<í5î2ñ‡9Q¯óË… [úV':ÒZÐv6¾’ùaê{úpï|RdÇÑ“á¼Xú*œèß ì, ÁÛÖP±Ý„ÌÈÛ,¸‚ŠƒÔÀÇå©n ìb~tÓfîoË£Ò¶%0újõá h3Š×íÊoMF)ˆŠëÙÂâiŒº¯ü›ý÷o, ˤ7;N}²¯\¾‘Á:ij?G—ÿO[ ‡tò:Ô $þ tUåO·ˆ) '^³ÃyÓf„µç–Ö™«šë³K ÅLÕ©ãí¢n}»~Ú;+W¬ÙÈâ¼zÇ®Ü\”åmOÀÀÒ\* ¯¦L}_ÉI ÖÛéžiz®¼ó<»· ¡ÑÞìâŒÝ˜yo GèA+ŒÙ£ªÝeÅh/µÛP“¤\¸*p³ú…š€°øc¿£+]^.4‘¥¤¶¢·ü»7M<Á‰¾¼~ö¸ Z F=í]W?ý¤©®uPª»8ÿ!4h…|¿®²º±r¡$§„©2¶™Ï#êßòh…2}—ÅoúçÎDRÛQFGª53xî‹£È ¢UÈö8]Õþð(êøÂóÂPéSwe•ê²íM?ŽG!,ASâñXüƸÌ]:ʤv•¦64~ÃY3ܦûèŽ]!ÐdæÇÙc½·µ¶ÅÚzžÌŒA1Ñ-¡١‚D›@"†óÝt[‚%>F©Œ‰kJ<ÐfiÞï¬ë ~Œ˜ÿàù«tQYQ*£L©•éɺÔ_ÿϲÜìÜl”í\›Um*¯ÙSÂxfUò0¿’Ä)eRn°u3Ø=Eá1ˆóð°z %ˆÿbº]å endstream endobj 48 0 obj <</Type/FontDescriptor/FontName/CTGDUP+CMTI12/FontBBox[0 -204 977 704]/Flags 4 /Ascent 704 /CapHeight 704 /Descent -204 /ItalicAngle 0 /StemV 146 /MissingWidth 500 /XHeight 441 /CharSet(/C/D/I/M/R/a/b/c/d/e/h/i/k/l/m/n/o/quoteleft/r/s/t/u/y)/FontFile3 99 0 R>> endobj 99 0 obj <</Filter/FlateDecode /Subtype/Type1C/Length 2697>>stream xœ­—yp÷ÇW–-p•Ä©Ô]¥98RBC& —¹ì8b°ñ%alÙ²,K¾ukõ$[·/Y²dŒe߯€  †4¤MH€\M:m’̴ô¿UÖÓve“”d2L§ô/»ó~ß÷ù~ß[…q8œiñ Ië—,¼G?Ê¡gGÑqIû6+œ±\ˆî˜Í>B²ÐŽ1.‡#-ÖÅK T2IŽX.šŸ±@´dÅŠçŸ-]¼x…hu^–L’‘ž/JH—‹³òÒåì‡ý¢Di†$K®Íÿ­X./xaÑ¢’’’…éyE ¥²œU ž•HäbÑö¬¢,™"+Sôª4_.Úœž—%šªnáÔK¼4¯ Xž%%H3³dù†=’/_++’¯Oß«ÊHÈÌo—äîÏKð-ØVì l.–ˆ%a¯cÉØSØ,Û‰­Åb¯`¯bë±eØl–€mÆVc³X-°h¬ƒUâü+ª,*ÌÍžm‹y<¦“·…78ÂãöéËf̘a›™1ójìñØÐ&>=¬öÓ‹ü:v4pŽ‹,¨U`œA?ÿ ðã°£4a[º“ÔÈŒPà»:óßìB j]0V™MåFB#)X’x¹Ölõt:ýdÛûÝ7á<~Z~rU›9»÷¦¡ý½© ‡Bµ"M™]¹(\k£\‹%h'Ç|cÝ€·A~•ÒXl¬ ×0CÆ 0ƒQXå¬jº›½µŸ6M‰¢.£ºË\Zº·7ž™á3qÌãÌ|{çõ÷Å¡9hÁ�¤Kz¯oEQ‡Î‘}—G:ú�i{s{Z“›Dî]›"ÎoU„‹B4ÿ7Ü^%°ÔXœ`Å]: (#htĆ•¹c)@ÈìfÄŒœQ3«PÔ³èaĹqÝá$¿ø¼éO‘ÿkA¯5š5&b7ó,3ýÅ…€/^qÍn÷ —¾F¿$GÞýËÛ_Žu ¹§œ’›ÊIÍ4ln«¥‰=_X¡pLˆ~ù.r‡_¨4 T;Àw Êô`¢ô$óØÄ X¯Ý ÂÉÐD¢aJ@Û)Ñü·>ɼ²Nàê·+é7<Ä9µò©mRæ¹MO“)«V&²U=ÁË7[<N«Óê ùôbu úðý¶ù >ä"ÔÔ ¡>´C ¢Ü¨,®hÒ66¬ïyÍ!MÍ*~#›ÐŒ¥5üÏõENL?¡ö_¼Š~}yÔϹzm<É¥ãèhAŽ‘Ê#^í¨ð½ÍÝÇ3ú72±â¹iÙ>…KMxË|†£ê†‘*HÂ Š–1Q9;†«‰V8Ìv¡Eå¬Ôf“6Ÿ¿‹DÇ÷Ìçk›vyˆ{ކð¶À•‡¹‚®³<Í¡5,R3Îr‘‹ž'ø”çuC³G¥äoyƒh‰ÅjqUèÒ5*ešb–ôLfIÌrÞ÷âÌ‹gJ Š=XêÁô³ßœBóm_T›©jQµ?sÁÖŽCµÁÚFVîÀˆŸ=çåÒýˆ ¶¬P‹7V¹*¥ZY…‰ˆgްJ©)ƒ°$=[œ ønÍС =·‚—IgÐV~|°¨çb ó¤^ã[¥¦¡–pv´Ý:xÇP$S*¶‘¹K+S _2VtòH°‹ðdv*z`�ü¡ú·§îÔàS6ËõDÉo”b)àņßw•ÆNá8N¯äÒ|:,pv»�oq‚Ï­#™ ™T6dA¦5NÅÎÑVƒªÚÞ1ÐUS 7–‘Ì£}š½î5V¨YÁÜPKö€µúaê‹\äô°7ÓRš^;X­.ò?6ÇÆ¹´”ŽÔx †m¬G[¯ÊÕea6+‡%u¬9Ì4Öió–oºrøpÛP?éÙ<¤þ×GLlè ·,ßx2u½îTšÑ4H¶ü‚c©ÎlªŠ-(y² $éà Þ(*¸ÄE#áe«ÃRÃæÒYÊÌOjfU˜5fPá, §@£6P:³˜7±@“…P-|æDÒ8ŠF1h1šóEêÛ¯îØ›QVFP3»+Îð þLÖ¸­î·{àâµÓ€÷ú²“%ÌC%餸•½ÒýlPÑR&Í?òþ©{¤“U‰5Ì íþŒÄDÞ/9G;MM„zOUŠ8%wwŽB  ­×õ°Z"fk¬n(ÑePÛRöÜþâï·Z‰IµÐ‘†§r:ë:—^COÈÌÅJ(ÂeƒËÝgNïÛü]lϽ¸å#ôà'mphz“Ù¬ÑÉñ/KS�O)»“ÞÝNv;œ††]8ÿ[ìNRþ“¦®n»sp¯ëŽo™é<˜@]ÆÜœøý¬×éKTÀl)biùï'õþÒu»¨<JhP›U§¹–l‡Nk: “ Eµ³ˆº´=™g‘:ØLu±r[Уtÿ, ïüÄ·V¥ÕTÂ:¨±9ëéiáhökæWïÜÓn¨!»¡×Ú½ÐGõDîꈀ¯…òDpºœ›Åú=ø“œEØ?ÆBf±[kï™Öl$¶2šŠ.Y(í~ Qok¯©'“|]Á–ç~Òí M¤©"fªÁ2?z‘í0ï2tsQ)*ô ­€â†²û·ÎaȹÌÚy£ñüa[É;m]¯¹ÑuÌÑî í~Á Zö»ðÁ T"b^€Üêpcr™´›Ýr%Œ”šU‚™7ñ±©ÒLIXéªò¶ÛÛVbYìÁ3èá¯@xß»ÌÆôl‰”Ô©Š¡·üèlˆC;ÿ0ø —Ö¡›ô`è³Oá3ü£Õï0|‚©ý)à~4Á#™Ø ý“hôO¡á¼ ÒÚxµÆ ŒwÛœ]¦•èd¤NªÉ†üÅK²3uÜvE²˜6¬íËÞŠ÷žK…Ú;§k;I°Úú .ïíÙÝŒ¯¨Ìåýy]Ž—Eè°v€ðñ¿ÁÓ*³•ÙCòÑé)ቫôðÈ©Q.z/Ìø*<¥ªÂ2i1»ø[›ÛfÓ„C -†JÐàÛ‡¾ü±~…K¶^]ekmkèm>IŽ¡å®V'4 GöÌ\´™o¸+|ºÚn²á�eu¡¾T§šŠ[tíjý�G.\¹vŸ�Œ¢ŒVÓµ2X'(5;® P¯=VÔ××ÚÖå%|Ýõoí.cTlWnN\Uåé €ÕÕCÚ|P ø`yKª3Ôä÷<rüશPƒVå“+R0èëjSvìÙº'95“H\W¢Uiq>ªQûó:87ÏNåÞ®¾s”¸ ¥a'P¹0¹[|¼Ûlo š5¼ÍZ˜¥Ã`Ôž"Ì&c¹IS¹³t‹än#óǧ†h˜1mˆ,ôS&ø?,ô;r’rý•7ƒ»`ìÜŸ³ã~–ûº&‡ßAXÝýè)û[ÀÞb ¸û΢é7#•¦”•°—¨ÈõŒ—U”°ÚYùÝó�:M?ù5ZÍÆPæm6ƒè÷ÖÅñŽ  +R­Ñn(eb™é OnÏè:ØÞÙ®p+ 5jŽà+Zèx7*²z[xLš{ZhÆ¥™ÄŒèçý±Óý®ØX û7´ ` endstream endobj 22 0 obj <</Type/FontDescriptor/FontName/VABMVS+CMBX12/FontBBox[0 -201 1025 700]/Flags 6 /Ascent 700 /CapHeight 700 /Descent -201 /ItalicAngle 0 /StemV 144 /MissingWidth 500 /XHeight 456 /CharSet(/A/C/D/F/G/I/K/M/N/R/T/U/a/b/c/comma/d/e/f/four/g/h/hyphen/i/k/l/m/n/o/one/p/period/quoteright/r/s/t/three/two/u/v/x/y/zero)/FontFile3 100 0 R>> endobj 100 0 obj <</Filter/FlateDecode /Subtype/Type1C/Length 4050>>stream xœX TSç¶>1$爈Š=*¨¢V­‚z^i«(NEQT´(&Bd’)€Ì†d' ³Ì£ÈD¢b‹T[ÛªµZ«·ƒÖ>‡ÒW­¶ZÝîZï`ë»·}ë®»þ° dŸsöÞÿ·¿ïû#b,†1"‘ˆuq[²Ùi¶ùÏÉÂK"áåaÂ+b Ûžö¹KÀJ V‡_û• ^ƒ£pËhF,…Fi\Bwdž«ü"í¦îxÍÎiáÂù3ìf;:.´[ì®Ú¡ ±sSFø+#é› ;Ð*¿ÈX»©oDFî^4kVttôLepÄÌÐpÿ7_›a­Š °[ïá®öóµs ‰´[£ ö³Ìnæà/—ÐàÝQ‘~ávn¡¾~á! ÃL_ê²{i¸kÄòȨ•jåêŸØn¾küvú¬WmÜì4{ÎÜ)3^ŸéÈ0¯2kwf³Žq`<˜)Ìf*³‘ÙÄLc<™%Ì f ã¼Ë,ef2˘YŒ+³œYÁ¬dæ0«˜¿1ï0ó7f cÃŒe^`x†cF2ÖÌ(f 3ƒö‘±`’™»¢e¢†-fÖ+~[üß =’q’Í’.éߤÙ]ìen3÷þpáZz[ž1iÄ]«-Vd¤ëÈ|k'ëƒÖ7G¥Œúxô¢ÑÇØÙ:¦xŒqÌy›9B–uß0¡£IXU%¼ûòš íÞm†&–èûŸLÐÄ64+<+¢€‹UH÷>†Fh€/¡Vû¾ÕD~Z”]�CNŽ›€ÕÒ³ÄQòºBÚb¸íпBý@è –ÜâxäH‡„$H­û$`,"£½Q$àþ'Ÿ÷È0·€·U2“ç4‰‚ý4|åä’«‚­5\†t={¾+ªXd¾í9w¨:â-iø³ÖZ8“Þ&¼h5££•XhÀP_šuŸ8‘ùs'’qd|ïëè„óoÞG1u<8üz¼_Ù&¯9r¬ÂBÛîòÐ*ð/nŽð2뾞$zVáªjô1‰>E{Aß)îKé›Ë×Bv”ìm+êƒ-I#3‰ÙI|ð5òjÑY´FËòt}|J $ëä©dá=`Ì©ð8Ðx P?—~ÙuúÜÕ…'à*àHeYjH-€bàjÁP'§M$›Lè`Æ·‰Ñ>æÒêð ™Î»âi}ÔÑðÃWž|‡“Q6ó6yÉ}stàùI–,þ½¯ýùÿÚ4W¡ƒ?t¢§ì0pçϸ“ ÄÁeój…¢¦+ˆ>ò!Ý·{&N±ÂËø²¸½o ¯xÜÏ^!,dqNÅQ¸ ÕdŽ"îrâþñ¼p§±7á’êg£Oå»@x Ãã=¶l[±Ë 8kaû =zˆœ}1Š7æá.KHÖìXÎǸ§¾ÞXÞÑíyÀë •«2ÂC,% þWip êö~.kÝçI!ÞH_'ÌOÀ9t,ûœùþÛ4ç^{…´Ñ€R8=pÞ¸ˆØbã)önþö%òNlRJ—¤mŸ.Û€8QŠs ~I ÉuJ­…µéFÁ®IÔþ9Æ}.F oñ•Ÿ®…ÔxYfV²&#+´lg®?pÁdq¯âè¨æ yC†1=ޤ %÷¦#¨7¿Sv/T–^¥ÓïN Y‘r²1 )Í3@Y•lå±€ lOá˜b´=fŒ®û´ªr7®.Z['¸ó·¡ŹË 2}b¾Õ]+·~ÊQlz™›A`ÎÆ ™¸‡ÿÚ$ÐÚA ¬•°Æ@KV ½ jÝ”¢„õ0µÄíKßcŸ�ZÁÃòKÇzþ„Âþÿ`¿ðMiO‡¼5ðÈlàŠ¡°Ln-¬¤Éšð­*ѯ¶#;Åè/8ð8ÉD&¡‡Rª›ê5uj·ëifí¯G^¾rôôYÒ“]´.ÔÒÑ“ÐþsÝð>ÖðÏа™}Ë{óÛ™õ§dx—%®à$…r!äIݸf’éIqq®Äĺià°\° T1oÝi»ð@ßx-LRíPÒ5üûeÑX(Ø6Ãè¤ë´ BÇ|‡;Õo i‚5ŸWš“8ë¯Õ‚ì-¬¸ÛP“¡Ñ.#EN†“BÂc«ä”I©]FƒB`„ „eqi¿MAŒ!£lË ßPPE‡Å”nDŸœkµÒê}ÌÜ©À“|ï’O‰½±Ì˜¯l‰mhj¬n¯ÔTì)’ ê ¸Ï;üÊw°d6™³ˆ‘‹¾øÕ{G«ä;Añ‹¬[Z5Õ© GePËÑiþõù±ïúÿ€LóÏ{eÖO-~þ bA%,â1½÷äß[»–Vé Áà áƒUÖ@n §cû-Ée ÞxlbC(öü鲃˜æ` O ®'Ð8ÐI{ÜÅ>¼…~¤Å•“™¶ÉïB”LÁ¶~¤ªÒÿ3Äî»Ù¹7¥„vŬeOijw¨Ê mѾ‚üïÌYyЬT´© ̪²:CC%N«•Ï}m*Ž”tš¿œ6>6Å|Á¢#YO•aJR‚F³�lìÇ4Sr鄃ڣޛ§}^¾üJPL^’(Ò:ÃJAM”O£–±ƒH}ш»)¿a‘™¢}ûVñÏsð/lyeyeYU÷¦SÉG(gËß@|åõ;ä÷­1>ò½^üÁ'+:ég£Œ]é ë#vʃ¼¶¦ÂrØy"¡ÆÜ²Õ(œ7‰jÌHFñ¹%9ùçÌøSi3ÿ/þô]˜••®Ë2ão/y›Ìø‹ m¥­rÂß9Ýú2’B2’lÕÞ®Ë ’ 9× o*†vÎQ¡Vm=ªüøúWŽVɬ…,:ÚTŽÚ©Ø.GK±€ÃùâdH‰Óé’2dš˜Ý+fGìg;£Çñ8>ïŒ6C§Óiuò¬¬Äxç”­{ê«Û÷u]'lîF⺌j-K^þiNA§fäò(OápJ—ðÈü&Ëp0•"XM)HEquA Q:]Xf¬6Z \¤BZkøz@æ¾BO$kîHDvHŽN5œpJÏb}ÿ“½É¹)å`[¹…{‹°©oؽ¤ÒÃ#h¥ë4 ‚T¸÷ØDT¬R!UÍ=¿ÑæêsͤôÀ¬ŽCÔãÍFUnot¥Õ¿:y±#ïÏCÛS]•ÆÃrO]ÿ "%¢þ;¼rÍæDªd4àØÏ¨©i—7Ÿ>“[ p4Ö¸³~*~6Ž]Bz—M}óø”">š^öuÀÈ iý?%éuûÀ¶rkåÂ5jôúý9†*}å|ó°8S”„Â9€’Z¶ P—Õ˜©×A×?²`azz4⛃®+µW,lÆ0¾6ê›4W·uÉ•ûÖÑ4ç9b÷ЧãôcËKã!=N—•˜.[µRíE#tøÒiy£…¡C¸º­²å`‰ÒD±Òoá¬ñîÀÔc5’’G·Íæ!Ø,$RñPúè³2c‘A§Í•ŧ¤î5·£%vM[éÑÿÎ¥ŽDìG8™ÃbÅòôÏ̓p†lkÁÙ½W[0±UÔ|#ç^ã8\ÅŸ; ¥æA=õեBycY]N¹!+ƒšåDN]³Ieu]l‹RᣎUË|ê| 6ÓrdÞ\TèÓ©’  D¨¨ÝY‘î ë9÷ó+ð\tル·Ö5†˼êVÃjÈ·C†^‘—ÔNy<__Z´Ã¹ü\¸xü8\¼y\·m×¹òÓÄ‹ÿòR¢g@À:êÙ&øŸn?wJåϬ¶—â¶'¿»4Øl§~–>ÏHýÇn»ïÛ$£Ú„‡ŒØf²1»DlGûñcã…ýø#uÝmÆËð÷àÕÄMÖ/¤j Ðÿo¿Óÿ!vì{8BzZ’jšTôü±‚.ŸnÕÉ€ëºà~-¾SRž–£Ó$êä[‚Ô¡°4Òz¹±ñé=š+„1R–©âÉpl£7ÂùÙ Ý7èæ’ÿ’[ãy ¡ûœd#úÄ|Ç®f_Ÿ •Ÿ_³ªã°±¹CF–’•trÏ<g./Ò“Ï87„7a:-¶–¶öÖI~m¶W¾ô õ)Òh’"é” (ÿ{œܵþ[dºBú­á!åŽOàïðí Y˜.Üú–¥ùó ȰK9(aèe 1~Fm~-.,*¸hÖ±0m4ì„0ð;¶¸.+-3=“êYE&Kû¯;hι.þ¾ƒ/²eÅ¥ûj*p$qœ—F‡_Ç¥DCÕÖ:Ãg4´J sPàâ ’õ Ù™ÙÉT`û~K2  ö ¯§Õ }ü_Qƒó_PÖLœ¼ŽX—L|ñ#™°àOK&<&ÃpºÝ %ÙÀ– ÷º÷+øŸÔs°Ò/*ýâ >u~}ðGÜ÷=Å}¯ïIb1yëòÀ8YÜ÷ËKWÃtðtS{qÿö‘StíäÙC5QÎ1ÿFˆ™\hzÙ¦£U"L@‰ï÷±|£e‹W±ù¼£¨”„žÜ#û¸þ"W°†ß ‹®ÇCD^¸ Zâ9´í6‰N£-ºã bÁ€¼Rš¥Ö¸Ç§¤iœ!žòÎ,i{Ë/-BñwŸwÃ]-í¾ ,!™¶zÆ&S|ms[õñΠê Ù‘ã=9ÕÀõ}ÛÅy“‹BN‚ItJ*EJ¬íaù‘IG£ mÞÀ:ÛD_ã0tC{1–à j—a¢—7ØF½2»ÕKn*(m†&®#¤ÑG¢œõ`#=.üæ‡ï…ÿDf5Èn5|ò)|Ã]u9KäÄb¡û¢-‡ãö7¬<^›Òº5OÖÙñ9äw\ƒƒ3·Q¦ Óúi“tѺLmzh “Û“ fßAÛIißü]~e&¸eèÄß3MKëu9á±ZˆO’‘{ýk% <D¤Dd6÷)ç´Âý!=ŸFeWåÉXŠ8ªq1åˆ8×|<¹Äkw¹yx§¦étô©©Å)¹%¿Þ@ÛÏvòؾ{—¯½WcEi~¾­dÓ³kŸ£’×…f,X¸L“N­hÆÀ¥ûîßÀÏŸÞðÜ¥99´Œ¸´WTŒ=bšÀR¾—ôÌ2ç÷š$ƘËTå»+ÈÇÇtx€ªÌ;bîEG©Ô&˜¿à(ÁËü]Àt’LR€h¦M’„ɘ¬Çøû2úÏn>"öEW‡×Ç•&Á%8—²äþå¼hOãKæS©ZDˆ$9>!88:zwJ=¥' ª°XJ¶å±&KYZ̯²ÞZ`e…¢Z«‘z+k†ù_Jâí endstream endobj 20 0 obj <</Type/FontDescriptor/FontName/OBAVOW+CMR12/FontBBox[-34 -251 988 750]/Flags 4 /Ascent 750 /CapHeight 750 /Descent -251 /ItalicAngle 0 /StemV 148 /MissingWidth 500 /CharSet(/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/R/S/T/U/W/X/a/ampersand/b/bracketleft/bracketright/c/colon/comma/d/dieresis/dollar/e/eight/endash/f/ff/fi/five/fl/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/period/plus/q/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero)/FontFile3 101 0 R>> endobj 101 0 obj <</Filter/FlateDecode /Subtype/Type1C/Length 7431>>stream xœµyTT×·þGæ^K¢×€š{1VìbÅX"Xb+Ti¢0ôÞë”ÍÀÐ;30”•"(6T4vcM41jkŒ1õ\<$ïfF“_òòÖ½·F]Œëœ{ÏÞûÛßþ¾ƒˆêÞ‰D{‡Õ“m ?‹„!Ý„·Å>8óE@g’˜‹Á¼ûž!#V¿)ÌyUõEëúQb‘Hœdïäã½=Äj´»µÕd[Ûã¬l&M²µšïçäãî&µrp ÙîéçB¾øZ­ñw÷ñ ‰´={{HHÀ¬‰ÃÃÃ'¸ùOðòžk=Î*Ü'd»ÕjÏ`Ï 0O«EþÒ+G7?O+ãá&ÿµ÷÷  ñ ²rð÷ð ’Rµ|¾tƒ¿}À‚À…A‹‚‡¼º$li¸Û²ˆmË#Ý¢<=Wx­ôÞ¾ÚgÍŽµ;|ýÖO¶™2uÚô3mg 9j´õ¦±ñæãzo=aâ¤^õµ‚²¥†Q+©áÔ*jµšI­¡FQk©Ñ”eM­£ÆP멱ÔÊŽGm¤ì©ñ”3µ€š@m¢R©EÔ$j15™zŸZBM¡–RS©eÔ4j95r ©™Ô›Tj�ÅR©·( Ê’D ¦Ì(šb¨TOj6eN%S~ToJJÍ¥úPþT_ªõ†¨'å@êDu§¢Þ¢›Ýº5‰yqM÷ÞÝ“ºÿ`¶Áì´ÄÑ èÇÌ2¦¼ÛÃ¿çØž½|Íç˜7õ÷.èý¼ô¹Ýw]ßÏúÍìý~xÃõM»7Ï÷Oïÿ倬ß±›Š† l~+ÀÂÆ"Öâ©eŒåµAaƒ„Á+Ÿâ8$å활%·‘kä~$È×Z-´‚¡c‡.ê24xhÖÐóï¼?¬— ïÓz´U/,Ј„·:—³²EV,Ä‚Bž=»žXÄnó\¦d¤ôY• vC-†jE»ù0=í–¤%ß³@¥.<ˆ,-ZrOVǃä–~ ˆ“Ò•ª[dI-\‡JÓ¦¥ ±­ .*XÄà/ÍpŒ¤ÐzaˆF„¨‹Èý¢XX…d,<‚Ú]Ò½›³|` xÎLg”?Hð3)}9'Å™Ç:Ú%–’—T«:È+ôÐñêdËâá�韮œ<w®hƒ#‡ãÿqíFecLD§™^TѹP, °ˆC[Juú¶'é–zz«"6@�,ƒÙ&¥[å…Á ²ÔÔ$lŽXàÁh³<S– jË"mI#§§ƒ³A þ°‚M{n@^šv'Zë,ðl¬ˆ Úé>Yi)¥÷«òá(ÔÀÅWIrSÅUA)䫳³rÑ(´ÓMÇiYIéJYB|d”‡¡:Õ§$ŽZ¸:Ó®• ! $’%¤¤W4hŸ^„¸›èËâýóX©†¾ž‘èÅwÕÒ^òD{.\*˜K{ÿÞ7·í>ý ù'eW.À æË©wñ[^„¯±HEïVe·qèMÉwÓœ–¬Ÿ‰Åühü5ëªÈÞÍ#=ZAÓ>cî,ÇùÖ|!6±B°Ñˆên¢º›bÁí`kýf°ù¸¡øM<à»±H‚z>ý½ÉáØ…õ—é‘€ÊÓ°šálýÚým% °öEÖxÔoåàÛÁ!p³ÿ¦-ž@[¦ïœ¨u<‚«ÅVsØ2P'¦*‰©œól—“‹ìÁ/Ã6ä³»£©xZ‚f>BÃP·|ÈJHT¦¥ðIx fŽf!^³@ûÐʶë?=´Ác4¼*äÀA††DÔ‚×éÑD0¾BôãETrSŒØ–5ËŽ. jõ¸� ¢Ÿ?E,ê?þ[,š²y¹LÎ_¢1o@éÕ¬W¾kÇ? ožÇB9¤ç—Ô8RÞ Ì3“pwÜkñÔ¹¾ÒÂòp>¤2Fµ$êx0ÑÛ·„Äûþ¶–è z Bcr"Pœˆgñxà¯ï˜J%ì3ò'É]øÐ½uÉ0Üarüêù;ÜVl›A’+þmÃMTBÚp™àÀ†K¼&D6{œ˜GÛmØxlûcDmUí<vøï[p9Êfag¤4$ÄÛËS̼•‘™_ýüã[û¦­çûtN P=¯GMõ"4ä6r®w¾‰rÙPI0ž¼�Ï‘˜ÐVù€þ&ßw_JB%Ó|Çr“\b§¥‚úÅx8S! DÁf]­RÄ”¢êßáÞAˆ¦Ÿ‰h~<ÿË-1IX,û´åÁ'9*PfrɲèT`¤• %MaM]@íÖéÒ‰©œ‰%xÐßðN­êÔ‘¾½ö²oÃi;E~#‰ª?‰ªü1Eµ¶B,\&XíªùÏCItª¯É3à+ПáGOU4òHõý8oÇ S¸3wŒç¦ ¼—á¾!AÃA¿®%áö&j„ée¢ÝPä1º-¼kìŠäˆÐ¤ηÊ7k'Éboï%k`{óv~—ÿž”ƒI' åUáe1…¡àÏl Ú4eɦæïB9Y¤+Ó™2“�i‘<BGBZž:=][Ê©³AU\Ò¼¹ƒóÓ±S·:vìJÊå½ë²–øeÙÁ¦^{ð>eMðUqéÉÙL>¨ËHRrÃô(N/Œ6öï»·Å<rf÷fª/ª T,?Ø S!ÀH•õôWñÞü2Kð[ɳñŠÃh/éÔUmWïý¸/¬æT t*J¤_çi£ã‰q®KH£OÆn„¦Xzívå…&¾lçî9Àä@V éð~„³éÑL臋hH…ÍF²h¨EËC%ÊñÞc'É™ð/p=Ň?¿ûÜuîƒÐµ´½ÔÍc1<*åLóó"A°ÞXëc·ÅÂcáG¶)#ï:§ÑK‚¶døíËð²qq">FNý/«þho“;¤»êàÎK²§íåyM<*CÇpÙ¿­"LF 2¸åÕ|Evì+4/¦§»,xÏ6íÐq}N㡜߹ ÇÐà�Þu;t­ñGIÅwÁ½¾²¤€™L#>ÏLO/NÎ>Â#îƒ~~IRCn‹‘Ÿ)7¸ ChÓH`~¤²¦Ð*è„öj8ô—äÈupïå¡Cé÷L‡.LÔ ƒõ¢2!D,ŒC_³¹¥û/¤3zZªˆ_ƒØb¬ûj?H€$EZZüœo»£†´"%Y\Ý e`AŠõdzï ÒÄÑ´å$äÉ |Ñ0üÂB«J+€lÈRe—„0ÍÙ„x½èè34ö–Xè'üb€é%ãSìIv¼Ó¯ 0ír¥m6¯t [™sÊ«K«+ƒFF]åëµà¢Ã½ÏAÝTÖ¿ ¨ÓF,|Oª8ߦ*5¤ˆ$IÉéœL§; (€PBŠ,q".¶…ÉUaYÛZrÅ6²~'ٱƴ£ ùqêÔ‚ÙáÓ±Üb,ªJ+$;2-köB¹ñìIüÉŽå¦GIòw¢7I22Rò!Ôê’ïP³Åw¸Y­–ç‚e>ddgæ3†é®AQåUwÎhDm×ж‹7 © D–0~‹ëÞí»\Š\±]î´TZ[©+-ÕµzC _¹ïpY 0O{NæÝi¼E>oÌef? :ûá–Ãå\ææzïýÀhO}ÆŸ ]C¯NŽõ„ãÅÜÒ#¬µÝŽ­ÎÛ# 4· QEò§úcD¡Í`‹Kö6•övmí-•ñà°ò•JÓ*Ë’ bR’BÃð)|ØݤäÃçFuö瞣?Ïg¾KG;'À Î ¯þÜKôŒ8b˜û¨¢‘®ËLÍLQ¥YªdéiÊø{C´q×GdW5´Cƒi—D©w6ŒW2yzèEyBŠíF ¬¾y_G¹¶õà¡ì]À¦<À“”g£é8…Š’T¨¤„Ôäe³,æü ÏLÍ…lKÈR—Õ™@³áÏ> å m�êÇ[¨™©„Âås¬ã\\¶c3ðû‰ÒRA»élÁ²b(‚’으ÂbíîV]ý+‹ÒPòÄTHNŽ0lªV!ƒ}7ÙtÆ´iDª‚w1&N™¨A>-dš¢2"ŽÞí\Êš”‘YºžTЙ9µí™Ù•^û=ÿ¬”Äk7¹ùð*'Ê@•_¢klÓ¦î§x¼öýD·`o>Ü×Ýw#8Áö†¨š8-d‚¡5Ñk�¸dÔ ‰£âplÌT“LöЪ‚{\^"UL!òÑlþ‰TTÏVMÙM!A/*¿!¬Ñ=¶æÒ¡ôrxI3;I ~ï±&En±/„fd‰#°Ú‹QUj1@é–Õ  1Î1gÒb†*®6m99i…¾Èº«›…ëPPÈ’£ü<]€ñ(2t…‘Qa‰RÏ&¯ã'[œ¯&Ä·8±éïtu˜Ë]1úM°ñ^°-¸4JWY^¤¿´ðð,ÜcÂ0ƒª&bÌ YÔ!óÜÜ')åñr>t“Ÿ0޳ޣqhÖ­íÍ'b<*ù>/Ø—ùãuBéÇbÕ9ŽM)W’<ñwm’NÀæqFMwÜèÝŽ¿ÒtãàP /ìO§Qê¯= g$çe.qYÅHÖÙÇ"½ë†äÕ$ªT}Fú@Ÿý.Œ“H¨}5óðDI((•ÉXÚõ¡‰*K¨Fè&ÞF±¹ùòbòS ŠÃ—$ xŠY…$ëûò&$"Hb$xo×Ûf‘*¨àÐ-I Zn*IÂ’¨M¸—AíH^‡'ÉbÙy1:nÎ/‡^ ¦ßÚàH–2£¬ñ�Üÿ‰5êv³­½¼ˆ_D£¡¿6ágzi×Ç,)º<64xû6éF`1•‡Ö]/h©ØÍkê[êÛá4¸äED‘²Gþa$Ñ0Y'Fa“Ù¤Bez(yÛx©d?TAM Óµ—–þsšõ¼PIç$ƒ"7^ÔõÀ"/6]™MZ•™®b„+´=1Âm›?¬ƒ@ÜžÀf)ßµ„6a( Ù Yò9±ÐŰ*(îô÷Æ’)Ãq?lñý"Ç{@”6+-35™ÌO8ãý7`ÜFÖ¢ù|9^Îæ É_•ÕÂ/…‡¦ûUa•³+ :Îû‘¸s=zÈ"w<Ù`;â­ñT"º\ÑX<Ù£Åh4š‚¶pø¾ÏŽÀß \¤@üÝÇÏÐài8 â!Çð}Ð1#=¢,‰Î? âü=ƒ3ÓcõÜ?x°5§X‘ZÀÉ”AI eBJ¢+u%%º&oý¦…³Fp¸Çé§øö¿*sƒßا#‚Í`§Ð‰Gb$EÄèΑ ¿ÜzþtÌWx0ïÿÞ ÿ*À¨œEU&wõX‚¦6ÛêDµÎ08bì¦EN'¾Ô"•Vtö ²¿²÷I7ZÂòm|`î_ºüIMróÎ]üÞ–C &,Gþ*ei‰ÀĿŗ䔩+Êbk·¯÷ØËùUn/$>xòû‹ç®nðÊKâãc"¥dj¬jÊIÛ·ÅÖ3‹¯F}Q¯gÇoT¥œ^QÏm¨ÞÓÀR ²<1/©´PšUšWÄ<Kd§ÀóÊ2h-­áËõuyZ`¾‚‘!‘°-*€ú%†Sƒ;ÖîÈ9ª½ÍÕ|EQ.\æ.2ƒ©+çmžÈ¿º¸1tÙ?ÝÝL÷¥±¾Œ}/y}8hÿw/o<´¤²'5è„©²û}« ³Ð#öYå'çáæ)6»‹‡søØßÔ¶ÒX[=Üý3Y¤2ô^hJ¨ñßãIäæ"˜ m[‹cö…œæÓÂ{Ú,ÈMH„ÔD%Ÿ¶B°¶@â¡äãÊìÔýòª”vÙ.¿ú„üÀšµÅÌø–hÒb TB637½4ÀÜF�ºyH@G2É´ þO FvB[Véà§‹ÐÕ—UWp˜ÃŽ„Ã.䦫úì‡ÉáóáìyyÇ&Sïå…î„ZÂô“kD§ÐõSbä!Lc7º´ÃæêÉóŸ¢™xúÖ,N²¼—6 ¹­”\q)ÜÇMç–¸+%že3bS©k“;ßàÑt-²!ùDlQê¡z'Xü·nÁL‡üýÎܪc²ëÊÝJq½².Fû˜•®*Èæ2s´M9Åîç}¾$ÞýöÔílȀݼ×—|<†°�™Æ%Ÿ ±Æ<øÜ}@áJQ\ìXZ]W®Óqx”17r PN¯M˜¿Já E!\µ:§œH…ʨ²à ¨ÈàMÇ®Ÿ>÷€h¢¿ 1S{DèCb>‡vÎb»žJ"q0™+EÈ&·Ù-R 9 <=B˜.=í±Öœ·T²Kõì%Ÿa—1ÃÞ´5íá= UªÜ’Ì•Ê< ×»ÛM¹AîIv¡`ƒ:2¾2ÒSr 2Îwää\9Ó–®5ˆ¸pE ‘(°á•b-U$A4©ä0™ðfBý·}c¨ºÁ6†Ú×úægúÂÉo0W–�±–‘±iadiÑp5DúùgZ@܆«aT| 29ןk š*ŠÅVãlǯÖ‚ì9aÀ¿:Ô>4˜wPÄßBC¾ã„>ôÙOŒŽ+PáD&“”H¸?fS€ çf-&¿÷ÅøZpGŒÁµÿ)¸>'_¿'6ÐM§Û_èf&¸­ˆöˆýÄ©bùÿéµñÿK½H Óv¾£•¾p¿xC¸Ã–ÖkÚÓ_ªW§Wf䬲l'„Cš<Y‘‚ÇuI-ðt”Šb뎃Îh`æ“ôJ ·¿Lðq(’çGfÇeûzãa]«-ðT!-­ÈhëŽB5Ù¢˜g,Êï{:n <‘s×oê˜LY.äL`1š%”X w»JÔ1jyŽAåefª‹ 6 EßFJàEŒZ;Y¶Òùà€^ÃØ…JR²ÕLWí-ŸÂùJ%5ª§Ä>ì†o Æ˜ _zм Ñ0ázñ˜ŒxÑ‘ÇhÇ]±°Í&Š^•¼61:%i5Aƒ$5•g/T눵:y ž1éLdÛâÑÓ6´A†¶ºxWmD¹’”r®ürÇÁ‹À|qlÁÄéÎóW/#ôƒÃÌ‚¡Âذš¯¿E#t¨÷ƒK:ÑåhþËf£”2%$1‰jÛƒ’/šŽÅo-Þî¼É¶òC)¿+Mopóú0p`¬§Í×vÁôÕƒçç_[ÊÝ«:ù|Êܲ=5fÔ|G;÷úäb­®¸nWpQhªñDÍ—“™Îì¾c!_#ÝÊû¹úȉ±2fqzÁ•¤òð‡bôk'Ï–ƒ:6YñÉîèò6“¢’I´—"ÑÎ4£L¿Hù‹ ~ð\?’^"ôf»zc™)JD…Vk#_#z^ƒ¢o‹Ñ�á*»?¶AI$2»~·(S¡N%ˆ“%ñk‚7Éa lÖDä¤d#“ ©Ñ<n'¼Z NO/Èãj[éÚ úÔ9'ªÔ#Ý™OXíïêíäJ6/=ù‘Z‘¥$–Öäí©( Š Lò˜~Ù .Íž=!ìÐëÝgï¬v òäg†kÞiÕ‰Zï Ù1,ÏY”…ú¶t46&ø•sñž°-´8¢ºª´XÌóèTbt,0‹p-2wø‰=A‘儯GÙì˜ëŸÈ£¾ø2»üN&i“ªÀUæVã³û'ô^>Å\‰l„­„_]"<ƒ6yG¹®ºcôÂÕk$õ îü;El%N¥qoPÊÊ™P‰/ÞL¦BFYî¹Âüœ¬Ä#3h»d(à1ϼÒ2Ü[÷ÁÞB®d­CÌ¡KÆçÖtö%QD[Åè(ú•m¯ùè |ÎÜ›qfâè9v“|ò|j}¸ü¸tåUç1.ß;fèó%ß#ñ£;?}o`Îa¹ÏÆåºWÃæâåÖK×/¬·wtu^µ“[´ŽE½gWGôGËys׿;ÝîÜÝO?8±Ž3¾¸ùÎ#0òUJ…n¨Å ï8¯^—ÑÄeI²YÐÄTÄ”FG:´»ÝCo ÞÈù¡ ÜýÒÜmÌD’f‹G“¿û¸¹ã¨†Ã¦“¬M*n&cæ�œ„ÃÕ­e55úø�ôóB4Î0b˜žc§pfŠŸŠî=%}%ôgkB´AÒ𠿪ˆÊš m-‡ïuÿÿ#G_£­ªC½ï¢Â»¿èk4¢ŽCˆÕ#ötÎ`?’õ.^˜¤R.¤#Bâ¤AeÑ•šŠ¼Æ{«oã^YüAéfúäÓ`<¬­Ü¼Ç§q{}ò±8@{dL* ÿ9C™­È"°ÔÔé¢JƒÃC½'uØ >Éüý!ú—¼+á9ì?¶õ°W«k¾{#Ía1[ O Î¼p7—ÑcÌ¢~Aêᄎl|v’ÑÿèNJ5¢Ö›m§‘e:S%þ°Qá;À™z×áñ¥3úÃG¹ªÐsk¿€pîÕXŠy^Îà .­nGÚsúØW gµM÷ #`‡’|^ÿ ã¾Úh¤Ê’ùp¯�— mÞ«|=eiQÚhàd^]ûðÜ`ò”ˆ±u\èôÎæÜÅU‹8UJ†A{ɉS0\`ÃN%]†6ævsCã‰Ì©áKm'‡sÛæ±-“>´¾°Àa•cŠ[ÿûg«3÷Õ4ñéÇ>ÈÉ%:L'ŒÖ¢÷ˆ]¤£¯lzJzÄA,ÌZ´()Éð &M¦Î½õ1’œ iq—F„”‡ÖÕ–§“¢öÙÚk5¢o;ÄèSL&t¨¢JG=_ƒlm´îz1¨g^®a:1Yi*Yœ­½µ3·adˆà¾`S„{³:Íï,%¤•©Veñ<EÇ6  7Q¿5ˆY‰Ìm/&�#KS¤ÊAQÅ7ò$¶¼ðºÍø]20z&šNªVdÞ¹þíîè÷•ˆdng4½°i!¦IŒ2pÛ4æ…ÍÓ&<è·"Usµ¨¥ µ’ÿÖ$†¡hé%EePV1<Ö¾AYdDÅpXõtl$DF”B1È7I,D–QZl�»põ¡èLJOŠÑá¿Øª0mPph¤¿E¤®J«­âЪµ¡Dº†…iête†1˜¬-¨ïç †ß\!O¢œ® ‹ØTHT* R÷@f’ïï5ŸÎ;¬ô©ãÜä¾ R]\i™® þèæs'áž1Åcú/6ùïdº&Ó³â¶ñ¸æ¿_ið$yN&¬Ø¬¬—±çÂöz¼‚Cq~¶:‹ËÈH'—QAlÚ²À®[x™œZfBÐÍý*F=Ê-}¡°ŒhÃeXZ*)›Ò2| }!˜aVk‡ÿÃðü·5¸u²ÈŒ~róÀG *HÑq�é2¥2!)9‘¼-9#ª4‰ÁïѯA¤'ÈÄÎ$òzú›Í/4HÒÝB«:Dù¨PŒthÛ ³åjD ÄŠ ?±š®ØpÚH’&†<òŸi¸1ÈоXCHPxC,Øuº°jþŠ)LÌJŽ“'Å¥qøþoviq†œX&ä$çfäåg€¦sŽPÎM±°}ÄÂÝ´ÛÞ7·Ýµ¯p†U°@ê5Óy¢` ÆdÛ5.Ø;ïJð1¸íÇô§o¨¾…S ÞŠ?fwÂÒ²$J87‰×¿—œ.½t´Þpo|*¤|Zájb‚Ãû0/Á1w[±Ý0O/ÿ~yCŠçqþá-±°Ôp}#Ñcõ|ÙÖÞV\”&ÏúëõMãöºîž‘ÁA\`Óu�0cq÷õCÿÇåõø× \¡¾ßÑ|&» Âô\@ZrÄ@Tnlqª,†PZiºöÅÈ?/G+Ánù´¾çÅ^\Ïî34æ=4¹ææKÌ{SÔÿF$d† endstream endobj 18 0 obj <</Type/FontDescriptor/FontName/VEAUKV+CMR17/FontBBox[0 -16 744 707]/Flags 131104 /Ascent 707 /CapHeight 707 /Descent -16 /ItalicAngle 0 /StemV 111 /MissingWidth 500 /XHeight 442 /CharSet(/A/F/R/T/U/a/e/f/hyphen/i/k/m/n/o/r/s/t/w)/FontFile3 102 0 R>> endobj 102 0 obj <</Filter/FlateDecode /Subtype/Type1C/Length 2055>>stream xœµUmPT×¾—…½W!hLn ¹»¶&~Cl¬¨%Zc‚5ŠQ“TTVYýbV _ ìÞûî²°Ëײ,â B X"¨1Z«m5mµ±¦6FÕv’sw3íAbÚt:íôGçÌììμçÙó¼ïû<MP4MË×ÄÆ-Žšøö¼ô,-Í ž“Ažÿ€ÿÍ ‘AH`×Ì)m3Pù“H= %L§d4­É*^£Õ™ ê=iFåÜ”yÊÅË—G-T~ïÅ—+Wgª ê”d26Ù˜¦ÊL6’Ê-ÚµÊhRÎN3u+"#srr"’3³"´†=+ç-Tæ¨iÊ8U–ʰO•ªŒÑjŒÊÉ™*壷E<ú\£ÍÔeUe¬6UeÐP5cµFkˆÉ2æ$«vÇ©ãÓ2QÔw¨7¨MÔjO%PoQ¯P1ÔZê%êuêûÔj)µ‘ ¥ž"Ä©@J h}>`IÀUY˜ìgÉ£Aó‚®Ë#äõÌ*¦ŸÕ°fÉê_>”î“–5Ñèoþµ\YP^E XËòqÚø½°Ü„”Â4`õŒ×Þpú U ù®I´—tB-TÙ+ì•#h^ª—€WV€�–p]äòz¦Ý~ :ÀC/mä÷°¸^àP(¾„­òPÉ >I題 Ô™ô:à ÝÄS£wmL9À‹äxjaž9WUºM;•¥l=Ánµ÷d <Æ^oqô*P<ó騕Ÿ_s­ÛÆcó® •v˜½Ò}ø"j¿(“Ö ½z:âϘÆtÄü4žq{¢}û.šÁã8‰K„”6c¯aÀ:ýpÂ~Ê7Ðônoç0Á=fhMëH„u©ÂºmÚíI¹*`CÑ—“Üî#æ² ÍG…ÜÝã·>r:E«“‡ì}VcQ}m‹³­3½I½jïê´"…ˆh9fÿ-ã“„C; ÃáIk `€°¸Of8êC§Ûhô­K(Þ+“Žû_æÆ‹ôò+5°C1ÞÍì(„˜Gã#ã8ƒpü@6³J¨îV ª[Ìíª½Q /ª3É£Š÷Fð‹É4»ì}<âäh4ĺq8땇"löHËÜô¡nTØ-CJ+8¯h+µˆâÞj).²ZÒ»vØö‹e)›7/~¸¯½Tq!¿ÅÒlª+hɆ=lrVBä’ŒKŸ˜x«lf`Í¢˜£À³“M¬¬°Ù\|eU}keu“î¨~ Øû#§3¬;œ_«ÈìHs&»âk_sÃyÖç}ðeåœt;o+«Ë­‚òi7™(ïCË›èÏGï•¡Ò\)}X‰bMravÚ⥛÷ÜÅäDì¹®³×ø3¦-LŒn{²&¥éO|¨?ÒÜ,=ë£ÑØY™tÝášÎõÙëm¬ÉÉ\H‚ývÒ?=Ó!4˜À�%B±P² { N« á¾.ðð>Æ($C©ÐƒqòÆ(€Ð¼!7‡ÍE'ÊêÀåk³H­²A û&kû¡ÆZ³MÃãaŽür뇽¢þ/h4ì¯x´â€CpB¸ ÊËuìÄ.{Pž§é—×=tßy´kä·„ü8ªåàMîÝýnRµØè¸Øu»•u]m‡rkö[ÊDѪh¾pÚ{Ø¡ÑQŠÌ&áUó–Ì i¦·AÅ®¼•=2:Üq¦…·ïlKé¶yÄ}]1fŠc6êÌù»àT?¿µ•[»3þíÔž“GêFÎvòƒ‡Gvò¤ùf/Ê®G¯>RX ‘ö“¨€s8éjöa±|VÔ x~æÎ‚/P`ÿÍÎRJD¡ÀÂg¯W¿IúœÔªëφsðÖVÏ9Ñì_wöÁe8¹Þ†‰¸Úˆ¸B}èµË5úáð§D`‹&Æ-÷a=!¿yâÔ{uõ–’jÞ,ì+«o2»ÝM.ß±=Sâ^NœÅãàèoàOþ‹ÀüÑy"±óôÙŠ°‹hðW÷ˆÈf¢Ï¸;7. ö³Y¿ÇJ·<Vܱ(nÂ�;à´O"ÆDäAS˜3Ðitç÷¥‚ÖÂ@}D}l×°¥Øk57*ÁYlK-в×5Ù¥JÏ[›…z¡¥tÈ|w³Ë«8,GÍ“2½*¿yOƒ§cn–á‡DvÒ—àôÜǤ+2)s-¦Fcv®É˜íÍ=ØÒè=Èã)x3§gÆ\ÿb1ïo%qpò½›„Ên…$gˆ*ÀçgÛitú’ÌàæÆ¯É÷c}W^‡V¸ÛQxIç\b£ ÀÈŽ÷2{¬…Ëx­^>h²½ïÃ8(N`j™eÖÚË@ Ôz.[;¹‹A½¦¯˜p)—üWp1Mr£N´—UB9ØñÓ*×™Áî ߄ɮ€(þX Ó’=ÑÙID¹Åj3¼ÃæääŠ<^€ù )ŸÁÁ_éø7¢ã9ýߌŽ�æÊ…x~­©úÈ7™¬_wÄ =bƒ8™{PX•ÙÏ’èÌóù'l‚xîÝf™ÔƒLþö’¥ ßÚ~ø„–O´|GY)Œ¨+DÞa+ ‡ Ø šIyO®ÊS žè‹žù…ÎKÓ™±áÊö¯¼Ã@NÒc︉²uÿ”–é_Fs¨øw8xmâö/Ê >ÞäÝѰkãöÿ—ŸÿSÖ¢Ó(¡Ÿv ‡ ¹P×;™Ð<ôJ-ÒºÜ9Nªb|SG‚ù©&mÈOuHÈH]Èõw0<¤m endstream endobj 13 0 obj << /Title(Future Development Ideas) /Dest/section.3 /Parent 6 0 R /Prev 8 0 R >> endobj 5 0 obj <</page.1 [4 0 R /XYZ 78.2634048 750.858765 null] /Doc-Start [4 0 R /XYZ 79.227 759.022583 null] /section*.1 [4 0 R /XYZ 79.227 551.969116 null] /section*.2 [4 0 R /XYZ 79.227 375.028 null] /page.2 [32 0 R /XYZ 78.2634048 750.858765 null] /section.1 [32 0 R /XYZ 79.227 581.720215 null] /page.3 [41 0 R /XYZ 78.2634048 750.858765 null] /page.4 [52 0 R /XYZ 78.2634048 750.858765 null] /section.2 [52 0 R /XYZ 79.227 363.223938 null] /subsection.2.1 [52 0 R /XYZ 79.227 227.838135 null] /page.5 [57 0 R /XYZ 78.2634048 750.858765 null] /page.6 [66 0 R /XYZ 78.2634048 750.858765 null] /Item.1 [66 0 R /XYZ 79.227 498.248352 null] /Item.2 [66 0 R /XYZ 79.227 474.519714 null] /Item.3 [66 0 R /XYZ 79.227 438.505127 null] /Item.4 [66 0 R /XYZ 79.227 414.656067 null] /page.7 [71 0 R /XYZ 78.2634048 750.858765 null] /subsection.2.2 [71 0 R /XYZ 79.227 465.967743 null] /page.8 [76 0 R /XYZ 78.2634048 750.858765 null] /subsubsection.2.2.1 [76 0 R /XYZ 79.227 759.022583 null] /page.9 [81 0 R /XYZ 78.2634048 750.858765 null] /subsubsection.2.2.2 [81 0 R /XYZ 79.227 759.022583 null] /page.10 [86 0 R /XYZ 78.2634048 750.858765 null] /section.3 [86 0 R /XYZ 79.227 603.039856 null] /page.11 [92 0 R /XYZ 78.2634048 750.858765 null] /section*.3 [92 0 R /XYZ 79.227 735.173523 null] /cite.xp [92 0 R /XYZ 79.227 740.232361 null] /cite.beck [92 0 R /XYZ 79.227 712.649353 null] /cite.junit [92 0 R /XYZ 79.227 688.198 null] /cite.tfg [92 0 R /XYZ 79.227 663.746643 null] /cite.runit-sf [92 0 R /XYZ 79.227 639.174866 null]>>endobj 107 0 obj <</Type/Metadata /Subtype/XML/Length 1527>>stream <?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?> <?adobe-xap-filters esc="CRLF"?> <x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 2.9.1-13, framework 1.6'> <rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'> <rdf:Description rdf:about='e39d081b-f8ee-11ea-0000-3d00cd43ad6c' xmlns:pdf='http://ns.adobe.com/pdf/1.3/'><pdf:Producer>dvips + GPL Ghostscript 8.71</pdf:Producer> <pdf:Keywords>()</pdf:Keywords> </rdf:Description> <rdf:Description rdf:about='e39d081b-f8ee-11ea-0000-3d00cd43ad6c' xmlns:xmp='http://ns.adobe.com/xap/1.0/'><xmp:ModifyDate>2010-09-15T16:05:48+02:00</xmp:ModifyDate> <xmp:CreateDate>2010-09-15T16:05:48+02:00</xmp:CreateDate> <xmp:CreatorTool>LaTeX with hyperref package</xmp:CreatorTool></rdf:Description> <rdf:Description rdf:about='e39d081b-f8ee-11ea-0000-3d00cd43ad6c' xmlns:xapMM='http://ns.adobe.com/xap/1.0/mm/' xapMM:DocumentID='e39d081b-f8ee-11ea-0000-3d00cd43ad6c'/> <rdf:Description rdf:about='e39d081b-f8ee-11ea-0000-3d00cd43ad6c' xmlns:dc='http://purl.org/dc/elements/1.1/' dc:format='application/pdf'><dc:title><rdf:Alt><rdf:li xml:lang='x-default'>()</rdf:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>()</rdf:li></rdf:Seq></dc:creator><dc:description><rdf:Seq><rdf:li>()</rdf:li></rdf:Seq></dc:description></rdf:Description> </rdf:RDF> </x:xmpmeta> <?xpacket end='w'?> endstream endobj 2 0 obj <</Producer(dvips + GPL Ghostscript 8.71) /CreationDate(D:20100915160548+02'00') /ModDate(D:20100915160548+02'00') /Creator(LaTeX with hyperref package) /Title() /Subject() /Author() /Keywords()>>endobj xref 0 108 0000000000 65535 f 0000042265 00000 n 0000080549 00000 n 0000042079 00000 n 0000040267 00000 n 0000077412 00000 n 0000042209 00000 n 0000042407 00000 n 0000042912 00000 n 0000042491 00000 n 0000042780 00000 n 0000042588 00000 n 0000042678 00000 n 0000077315 00000 n 0000000015 00000 n 0000003637 00000 n 0000043050 00000 n 0000048904 00000 n 0000074907 00000 n 0000048245 00000 n 0000066896 00000 n 0000047755 00000 n 0000062412 00000 n 0000043092 00000 n 0000043224 00000 n 0000043356 00000 n 0000043493 00000 n 0000043627 00000 n 0000043768 00000 n 0000043910 00000 n 0000044042 00000 n 0000044074 00000 n 0000040476 00000 n 0000003658 00000 n 0000008554 00000 n 0000044128 00000 n 0000046008 00000 n 0000047491 00000 n 0000044259 00000 n 0000044392 00000 n 0000044424 00000 n 0000040651 00000 n 0000008575 00000 n 0000013393 00000 n 0000044478 00000 n 0000044612 00000 n 0000044743 00000 n 0000047099 00000 n 0000059353 00000 n 0000044880 00000 n 0000045012 00000 n 0000045044 00000 n 0000040840 00000 n 0000013414 00000 n 0000018121 00000 n 0000045098 00000 n 0000045130 00000 n 0000040993 00000 n 0000018142 00000 n 0000023202 00000 n 0000046697 00000 n 0000055444 00000 n 0000046233 00000 n 0000049241 00000 n 0000045195 00000 n 0000045227 00000 n 0000041146 00000 n 0000023223 00000 n 0000027124 00000 n 0000045292 00000 n 0000045324 00000 n 0000041299 00000 n 0000027145 00000 n 0000031748 00000 n 0000045389 00000 n 0000045421 00000 n 0000041452 00000 n 0000031769 00000 n 0000034244 00000 n 0000045486 00000 n 0000045518 00000 n 0000041605 00000 n 0000034265 00000 n 0000036586 00000 n 0000045583 00000 n 0000045615 00000 n 0000041758 00000 n 0000036607 00000 n 0000039588 00000 n 0000045680 00000 n 0000045814 00000 n 0000045846 00000 n 0000041926 00000 n 0000039609 00000 n 0000040247 00000 n 0000045933 00000 n 0000045965 00000 n 0000049756 00000 n 0000055823 00000 n 0000059630 00000 n 0000062760 00000 n 0000067390 00000 n 0000075174 00000 n 0000047399 00000 n 0000047669 00000 n 0000048152 00000 n 0000048775 00000 n 0000078944 00000 n trailer << /Size 108 /Root 1 0 R /Info 2 0 R /ID [<AE7834D5D494C08F6C7C778A85EE988D><AE7834D5D494C08F6C7C778A85EE988D>] >> startxref 80760 %%EOF ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/doc/RUnit.dvi����������������������������������������������������������������������������0000644�0001751�0000144�00000114334�11444151274�014631� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������÷ƒ’À;����è TeX output 2010.09.15:1605‹���������������������������������������ÿÿÿÿï¬! systemdict /pdfmark known{userdict /?pdfmark systemdict /exec get put}{userdict /?pdfmark systemdict /pop get put userdict /pdfmark systemdict /cleartomark get put}ifelseï’ps:SDict begin [/Producer (dvips + Distiller)/Title ()/Subject ()/Creator (LaTeX with hyperref package)/Author ()/Keywords () /DOCINFO pdfmark endò��o! /DvipsToPDF{72.27 mul Resolution div} def/PDFToDvips{72.27 div Resolution mul} def/BPToDvips{72 div Resolution mul}def/BorderArrayPatch{[exch{dup dup type/integertype eq exch type/realtype eq or{BPToDvips}if}forall]}def/HyperBorder {1 PDFToDvips} def/H.V {pdf@hoff pdf@voff null} def/H.B {/Rect[pdf@llx pdf@lly pdf@urx pdf@ury]} def/H.S {currentpoint HyperBorder add /pdf@lly exch def dup DvipsToPDF 72 add /pdf@hoff exch def HyperBorder sub /pdf@llx exch def} def/H.L {2 sub dup/HyperBasePt exch def PDFToDvips /HyperBaseDvips exch def currentpoint HyperBaseDvips sub /pdf@ury exch def/pdf@urx exch def} def/H.A {H.L currentpoint exch pop vsize 72 sub exch DvipsToPDF HyperBasePt sub sub /pdf@voff exch def} def/H.R {currentpoint HyperBorder sub /pdf@ury exch def HyperBorder add /pdf@urx exch def currentpoint exch pop vsize 72 sub exch DvipsToPDF sub /pdf@voff exch def} defŽ¥…Qœ ýz®dïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.1) cvn /DEST pdfmark endŽŽ¡ ýy�� i��‘:9 ý°��ïTps:SDict begin [/Count -0/Dest (section.1) cvn/Title (Introduction) /OUT pdfmark endïYps:SDict begin [/Count -2/Dest (section.2) cvn/Title (The RUnit package) /OUT pdfmark endï`ps:SDict begin [/Count -0/Dest (subsection.2.1) cvn/Title (Test case execution) /OUT pdfmark endï^ps:SDict begin [/Count -2/Dest (subsection.2.2) cvn/Title (R Code Inspection) /OUT pdfmark endïWps:SDict begin [/Count -0/Dest (subsubsection.2.2.1) cvn/Title (Usage) /OUT pdfmark endïcps:SDict begin [/Count -0/Dest (subsubsection.2.2.2) cvn/Title (Technical Details) /OUT pdfmark endï`ps:SDict begin [/Count -0/Dest (section.3) cvn/Title (Future Development Ideas) /OUT pdfmark endïNps:SDict begin [/PageMode /UseOutlines/Page 1/View [/Fit] /DOCVIEW pdfmark endï/ps:SDict begin [ {Catalog}<<>> /PUT pdfmark endïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïGps:SDict begin [/View [/XYZ H.V]/Dest (Doc-Start) cvn /DEST pdfmark endïpapersize=210mm,297mmŸ<~î‘$iËó‡úBq�½q�G®�aer17¼R‘ÿuùUnit–>-“A“Unit“T›þaâest“F˜ramew‘ÿuùork“for“RŽŸ#Ÿ2‘Œxóa J¤�ff� ���aer12½Thomas–±ÃK€önig,“Klaus“J€ünemann,“and“Matthias“BurgerŽŽŸ��’�JEpigenomics‘±ÃAœyGŽŽŽŽŽŸ.ï’�†ÃðSeptemœybc†er–±Ã15,“2010ŽŸ5Hóкß�G®� ���aebx12ÂCon–ÿváten“tsŽŸ Þ)ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïHps:SDict begin [/View [/XYZ H.V]/Dest (section*.1) cvn /DEST pdfmark end¤€�ïps:SDict begin H.S endóкß� ��� ���aebx12Ã1Ž‘Ÿ2In Çtro_8ductionïps:SDict begin 14.5 H.L endïzps:SDict begin [/Subtype /Link/Dest (section.1) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ’A2ŽŽ©?wïps:SDict begin H.S end2Ž‘Ÿ2The–€�Rš ÇUnit“pac˜k‘ÿAageïps:SDict begin 14.5 H.L endïzps:SDict begin [/Subtype /Link/Dest (section.2) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ’A4ŽŽ¡‘Ÿ2ïps:SDict begin H.S endóa J¤� ��� ���aer12»2.1Ž‘-T‘ÿ0est–éxcase“executionïps:SDict begin 14.5 H.L endïps:SDict begin [/Subtype /Link/Dest (subsection.2.1) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ’�” ‘ÿý.ŽŽ– @z‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ‘O:4ŽŽ¡‘Ÿ2ïps:SDict begin H.S end2.2Ž‘-R–éxCošRïde“Insp˜ectionïps:SDict begin 14.5 H.L endïps:SDict begin [/Subtype /Link/Dest (subsection.2.2) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ’�” ‘ÿý.ŽŽ– @z‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ‘O:7ŽŽ¡‘,¤`ïps:SDict begin H.S end2.2.1Ž‘%—àUsageïps:SDict begin 14.5 H.L endï„ps:SDict begin [/Subtype /Link/Dest (subsubsection.2.2.1) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ‘xF2‘ÿý.ŽŽ– @z‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ‘O:7ŽŽ¡‘,¤`ïps:SDict begin H.S end2.2.2Ž‘%—àT‘ÿ0ec­hnical‘éxDetailsïps:SDict begin 14.5 H.L endï„ps:SDict begin [/Subtype /Link/Dest (subsubsection.2.2.2) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ’�¯É‘ÿý.ŽŽ– @z‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ“‘ÿý.ŽŽ‘O:8ŽŽ¦ïps:SDict begin H.S endÃ3Ž‘Ÿ2F‘þâOuture›€�Dev• Çelopmen“t˜Ideasïps:SDict begin 14.5 H.L endïzps:SDict begin [/Subtype /Link/Dest (section.3) cvn/H /I/Border [0 0 1]BorderArrayPatch/Color [1 0 0] H.B /ANN pdfmark endŽ’xƒ 10ŽŽŸ(HÂAbstractŽŸ Þ)ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïHps:SDict begin [/View [/XYZ H.V]/Dest (section*.2) cvn /DEST pdfmark end¡»Soft•­w“are›™üdev“elopmen“t‘™ýfor˜proRïduction˜systems˜presen“ts‘™ýa˜c“hallenge˜to‘™ýthe˜de-Ž¡v•­elopmen“t– Oteam“as“the“qualitš­y“of‘ Pthe“coRïded“pac˜k‘ÿZage(s)“has“to“bRïe“constan˜tlyŽ¡monitored–Æand“vš­eried.‘îýW‘ÿ0e“presen˜t“a“generic“approac˜h“to“soft˜w˜are“testing“forŽ¡the–¶R‘ªlanguage“moRïdelled“after›µsuccessful“examples“suc­h˜as“JUnit,‘…CppUnit,Ž¡and–fcPš­erlUnit.‘«úThe“aim“of“our“approac˜h“is“to‘fdfacilitate“dev˜elopmen˜t“of“reli-Ž¡able›`*soft•­w“are˜pac“k‘ÿZages˜and˜pro“vide˜a˜set‘`+of˜to•Rïols˜to˜analyse˜and˜rep“ort˜theŽ¡soft•­w“are›-îqualit“y‘-ístatus.‘öµThe˜presen“ted‘-íframew“ork˜is‘-ícompletely˜implemen“tedŽ¡within–‹¦R‘‹Žand“došRïes“not“rely“on“external‘‹§to˜ols“or“other“language“systems.‘òTheŽ¡basic–Bâprinciple›Báis“that˜ev­ery“function“or˜methoRïd“is˜accompanied“with˜a“testŽ¡case–3Žthat“queries“manš­y“calling“situations‘3including“incorrect“in˜v˜oRïcations.‘zAŽ¡test–case“can›bRïe“executed“instan­tly“without“reinstalling“the˜whole“pac­k‘ÿZage“-Ž¡a–è(feature“that“is“necessary“for‘è)parallel“dev•­elopmen“t–è(of“functionalit­y“and“testŽ¡cases.‘psOn–ý6a“second›ý7lev­el“one“or˜more“pac­k‘ÿZages“can˜bRïe“tested“in“a˜single“testŽ¡run,‘¨'the›‚result–‚of“whic­h˜is“repRïorted“in˜an“w­ell“structured˜test“protoRïcol.‘þÛT‘ÿ0oŽŽŸ��’�ÇK!1ŽŽŽŽŒ‹������������������������������������������*ïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.2) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘:9»vš­erify–z³the“co˜v˜erage“of“the“test“framew˜ork‘z²a“cošRïde“insp˜ector“is“pro­vided“thatޤ€�‘:9monitors–fÈthe›fÇcoRïde“co•­v“erage˜of–fÈexecuted˜test“cases.‘­&The“result˜of“individualŽ¡‘:9test›G~in•­v“oRïcations˜as‘G}w“ell˜as˜pac“k–ÿZage˜wide‘G}ev“aluations˜can˜bRïe˜compiled‘G}in­to˜aŽ¡‘:9summary–$<repšRïort“exp˜orted‘$;to“HTML.“This“rep˜ort“details‘$;the“executed“tests,Ž¡‘:9their–o„failure“or“success,‘Ñas“wš­ell“as“the“coRïde“co˜v˜erage.‘ Ç]T‘ÿ0aking“it“one“stepŽ¡‘:9further–ŽÆand“comš­bining“the“build“system‘ŽÇwith“a“dev˜elopmen˜t“and“release“pro-Ž¡‘:9cedure–§with“dened‘¦cošRïde“status“description“this“approac­h“op˜ens‘¦the“w•­a“y–§for“aŽ¡‘:9principled› Osoft•­w“are‘ Pqualit“y˜monitoring– Pand˜risk“assessmen­t˜of“the˜dev­elopRïedŽ¡‘:9application.‘ yF‘ÿ0or–f:our“coRïde‘f;dev•­elopmen“t›f:w“e˜ha“v“e˜utilised‘f;the˜describRïed˜systemŽ¡‘:9with–7_great“bšRïenet“w.r.t.“co˜de“reliabilitš­y“and“main˜tenance“eorts“in“a“mediumŽ¡‘:9sized›éxdev•­elopmen“t˜team.Ž‘:9Ÿ]Hïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïGps:SDict begin [/View [/XYZ H.V]/Dest (section.1) cvn /DEST pdfmark endŸ¬Â1Ž‘&µIn‘ÿvátro‘�‰ductionŽŸ^)»The–;šimpšRïortance“of“soft•­w“are–;štesting“can“hardly“b˜e‘;™o•­v“errated.‘+žThis–;šis“all“theŽ¡more–Ùtrue“for“inš­terpreted“languages“where‘Ønot“ev˜en“a“compiler“c˜hec˜ks“theŽ¡basic–Øjconsistency“of“a“program.‘/‰Nonetheless,‘ÛÓtesting“is“often“pRïerceiv­ed“moreŽ¡as–Qîa“burden“than“a“help“b­y“the“programmer.‘´Therefore“it“is“necessary“to“pro-Ž¡vide–mtoRïols“that›mmak­e“the“task“of˜testing“as“simple“and˜systematic“as“pRïossible.Ž¡The–Õtkš­ey“goal“of“suc˜h“a“testing‘Õsframew˜ork“should“bRïe“to“promote“the“creationŽ¡and–Íkexecution›Íjof“test˜cases“to“bRïecome˜an“in­tegral“part˜of“the˜soft•­w“are‘Íkdev“el-Ž¡opmen­t›é9pro•Rïcess.‘5$Exp“erience˜sho•­ws˜that‘é:suc“h˜a‘é:pRïermanen“tly˜rep•Rïeated‘é:co“de˜-Ž¡test–_˜-›_—simplify“cycle˜leads“to˜faster“and˜more“successful˜soft•­w“are‘_˜dev“elopmen“tŽ¡than–ËÃthe“usually“futile›ËÄattempt“to“add“test“cases“once˜the“soft•­w“are–ËÃis“largelyŽ¡nished.‘ ¤This–«¼line›«»of“though­t“has˜bRïeen“pushed˜furthest“b­y“the˜Extreme“Pro-Ž¡gramming–Áü[ïps:SDict begin H.S end1Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ïxps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.xp) cvn H.B /ANN pdfmark endŽ‘Þ0]“and“T‘ÿ0est-First“paradigms“where“test“cases“are“view­ed“as“theŽ¡essenš­tial–‡Âguidelines“for‘‡Áthe“dev˜elopmen˜t“proRïcess.‘These“considerations“leadŽ¡to–éxv‘ÿZarious“requiremenš­ts“that“a“useful“testing“framew˜ork“should“satisfy:ŽŸ]‘ Nó!ªã|C� ��� ���tcrm1200Ì€ˆŽŽŽ‘_ì»T‘ÿ0ests–éxshould“bRïe“easy“to“execute.ޤt€‘ NÌ€ˆŽŽŽ‘_ì»The–ïÓresults“should“bšRïe“accessible“through“a“w­ell“structured“test“proto˜col.Ž¡‘ NÌ€ˆŽŽŽ‘_ì»It–¹-should‘¹.bšRïe“p˜ossible“to›¹.execute“only“small˜pRïortions“of“the˜test“casesŽ©€�‘_ìduring–éxthe“dev•­elopmen“t‘éxproRïcess.Ž¡‘ NÌ€ˆŽŽŽ‘_ì»It–xÖshould‘xÕbšRïe“p˜ossible›xÕto“estimate“the˜amoun­t“of“coRïde˜that“is˜co•­v“ered‘xÖb“yަ‘_ìsome–éxtest“case.ŽŸ]‘ŸôT‘ÿ0esting–†2framewš­orks“that‘†3address“these“aspRïects“ha˜v˜e“bRïeen“written‘†3in“a“v‘ÿZa-ަrietš­y–Ìof“languages‘Ësuc˜h“as“Smalltalk,‘ !Ja˜v‘ÿZa,‘ C++“and“Python.‘3In“particular,ަthe–Ÿapproac­h“describšRïed“in‘Ÿ[ïps:SDict begin H.S end2Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ïzps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.beck) cvn H.B /ANN pdfmark endŽ‘Þ0]“has“turned“out“to“b˜e“v­ery‘Ÿsuccessful,‘ÌleadingŽŽŸ��’�ÇK!2ŽŽŽŒ‹�����������������������������������������Hïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.3) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘:9»–Nlamong“others““to“the“pRïopular“JUnit“library“for“Jaš­v‘ÿZa“[ïps:SDict begin H.S end3Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ï{ps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.junit) cvn H.B /ANN pdfmark endŽ‘Þ0],‘g©whic˜h“has“bRïeenޤ€�‘:9pRïorted–`to›`man­y“other“languages˜(see“[ïps:SDict begin H.S end1Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ïxps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.xp) cvn H.B /ANN pdfmark endŽ‘Þ0]“for“an˜extensiv­e“list“of˜testing“frame-Ž¡‘:9wš­orks–å3for‘å4all“kinds“of“languages).‘3ÌAccordingly‘ÿ0,‘æthe“R˜Unit‘å4pac˜k‘ÿZage“(a˜v‘ÿZailableŽ¡‘:9at–Qýsourceforge“[ïps:SDict begin H.S end5Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ï~ps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.runit-sf) cvn H.B /ANN pdfmark endŽ‘Þ0])“is“our“vš­ersion“of‘QüpRïorting“JUnit“to“R,“supplemen˜ted“b˜yŽ¡‘:9additional–5 functionalitš­y“to‘5!inspRïect“the“test“co˜v˜erage“of‘5!some“function“underŽ¡‘:9question.Ž¡‘Ú-One›ý*ma•­y‘ý+w“onder˜wh“y›ý+R‘ý%w“ould˜need‘ý*y“et˜another‘ý*testing˜framew“ork‘ý*ev“enŽ¡‘:9though–Óthe›Óstandard“methoRïd,‘׊namely“executing“ó"”Ší@� ��� ���aeti12ÍR–iCMD“che‘ÿfgck–Ó»on˜ones“com-Ž¡‘:9plete–‚žpac­k‘ÿZage“at“the‘‚shell“prompt,‘—0is“widely“accepted“and“applied.‘ïW‘ÿ0e“think,Ž¡‘:9ho•­w“ev“er,‘¬that–…the“Rš­Unit“approac˜h›…is“more“in“line“with“the˜abRïo•­v“e–…listed“re-Ž¡‘:9quiremenš­ts–±ÿand“can“bRïe‘²�seen“as“a“complemen˜t“to“the‘²�existing“proRïcess“in“that:ޤ€�‘ڇ̀ˆŽŽŽ‘$š%»test–éxcases“are“called“and“executed“from“the“R“promptŽ¡‘ڇ̀ˆŽŽŽ‘$š%»the– «programmer“decides“whicš­h“result“or“functionalit˜y“to“put“under“test-Ž©€�‘$š%ing,–éxe.g.“formating“issues“of“textual“output“do“not“need“to“matterŽ¡‘ڇ̀ˆŽŽŽ‘$š%»test–«‘and›«reference“data˜les“need˜not“bRïe˜main­tained“separately˜but“areަ‘$š%com•­bined›éxin“to˜one˜leŽ¡‘ڇ̀ˆŽŽŽ‘$š%»test–bžcases›bŸneed“not“bRïe˜limited“to“testing/using“functionalit­y˜from“oneަ‘$š%pac•­k‘ÿZage›éxc“hec“k“ed˜at˜a˜timeŽ¡‘:9Moreo•­v“er,‘“‰testing›>Rframew“orks–>Sbased˜on˜JUnit“pRïorts˜seem˜to“ha•­v“e˜bRïecomeަ‘:9a–¼quasi›»standard“in˜man­y“programming“languages.‘“Therefore,‘programmersަ‘:9new–¯6to›¯5R‘®åbut“familiar“with˜other“languages˜migh­t“appreciate“a˜familiar“testingަ‘:9en•­vironmen“t.‘Ù4And–Õknally‘ÿ0,‘ ¡oering“more“than“one“alternativš­e“in“the“impRïortan˜tަ‘:9eld–éxof“coRïde“testing“is“certainly“not“a“bad“idea“and“could“turn“out“useful.ަ‘Ú-Before–ÃÂexplaining“the“compRïonenš­ts‘ÃÃof“the“R˜Unit“pac˜k‘ÿZage“in“detail,‘:Uw˜eަ‘:9w•­ould›’¤lik“e–’£to˜list“some˜of“the˜lessons˜learned“in˜the“attempt˜of“writing˜usefulަ‘:9test–Fãsuites›Fâfor“our˜soft•­w“are–Fã(a“more˜complete“collection“of˜tips“relating˜to“aަ‘:9T‘ÿ0est-First›éxdev•­elopmen“t˜approac“h˜can˜bRïe˜found˜in˜[ïps:SDict begin H.S end4Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ïyps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.tfg) cvn H.B /ANN pdfmark endŽ‘Þ0]):Ž¡‘ڇ̀ˆŽŽŽ‘$š%»Dev­elop–Îrtest›Îqcases“parallel˜to“implemen•­ting˜y“our‘Îrfunctionalit“y‘ÿ0.‘ä$Keepަ‘$š%testing– —all“the“time“(coRïde“-“test“-‘ –simplify“cycle).‘¡•Do“not“wš­ait“un˜tilަ‘$š%the›q¿soft•­w“are˜is–qÀcomplete˜and˜attempt˜to“add˜test˜cases˜at“the˜v­ery˜end.ަ‘$š%This–éxtš­ypically“leads“to“p•Rïo“or–éxqualit˜y“and“incomplete“test“cases.Ž¡‘ڇ̀ˆŽŽŽ‘$š%»Distinguish›òbRïet•­w“een–òunit˜and“in­tegration˜tests:‘FkUnit˜tests“should˜bRïeަ‘$š%as–Ãksmall›Ãjas“pRïossible˜and“c•­hec“k˜one–Ãkunit“of˜functionalit­y“that˜cannot“bRïeަ‘$š%further–ª|decompRïosed.‘ :In­tegration“tests,‘·on‘ª}the“other“hand,‘·run“throughަ‘$š%a–b whole›bŸanalysis“w•­orko“w–b and“c•­hec“k˜the›b in“terpla“y˜of‘bŸv‘ÿZarious˜soft“w“areަ‘$š%compRïonen­ts.ŽŽŸ��’�ÇK!3ŽŽŽŒ‹�����������������������������������������,Çïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.4) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘ڇ̀ˆŽŽŽ‘$š%»Go•Rïo“d–Õtest“co•­v“erage–Õenables“refactoring,‘ bbš­y“whic˜h“a“reorganisation“of“theޤ€�‘$š%implemenš­tation–$‚is“mean˜t.‘ó‘Without‘$ƒregular“testing“the“attitude“Í`I‘|¡b‘ÿfgetterŽ¡‘$š%do–æ{not“touch‘æzthis“c–ÿfgo“de‘æ{anymor“e`–¬N»once“some“piece“of“soft•­w“are‘¬NappRïearsŽ¡‘$š%to–6bRïe›6w­orking“is˜frequenš­tly“encoun˜tered.‘,It“is‘6v˜ery“pleasing‘6and“time-Ž¡‘$š%sa­ving–jÉjust›jÊto“run˜a“test˜suite“after˜some“impro•­v“emen“t˜or‘jÉsimplicationŽ¡‘$š%of–Z·the“implemen­tation›Z¸to“see“that“all“test“cases˜are“still“passing“(orŽ¡‘$š%pRïossibly–©yrev­eal›©xsome“newly˜in­troRïduced“bug).‘âThis“refactoring˜abilit­y“isŽ¡‘$š%a–ž k­ey›ž bRïenet“of˜unit“testing˜leading“not˜only“to˜bRïetter“soft•­w“are˜qualit“yŽ¡‘$š%but–éxalso“to“bRïetter“design.Ž©€�‘ڇ̀ˆŽŽŽ‘$š%»Do–§ƒnot“test“inš­ternal“functions“but“just‘§„the“public“in˜terface“of“a“library‘ÿ0.Ž¡‘$š%Since–òÈR‘òÆdoRïes“not“proš­vide“v˜ery“m˜uc˜h“language‘òÉsuppRïort“for“this“distinc-Ž¡‘$š%tion,‘òÀthe–½±rst“step“here“is›½²to“clarify“whic­h“functions“are˜mean­t“to“bRïeŽ¡‘$š%called–Á,bš­y“a“user“of“a“pac˜k‘ÿZage“and“whic˜h“are“not“(namespaces“in“R‘Á"pro-Ž¡‘$š%vide–q²a“useful“directiv­e‘q³for“making“this“distinction,‘ÓÁif“the“expRïort“listŽ¡‘$š%is–øïselected“carefully“and“mainš­tained).‘cIf“in˜ternal“functions“are“directlyŽ¡‘$š%tested,‘Vthe–1Fabilit­y›1Gof“refactoring“gets“lost“bRïecause˜this“tš­ypically“in˜v˜olv˜esŽ¡‘$š%reorganisation–éxof“the“in­ternal“part“of“a“library‘ÿ0.ަ‘ڇ̀ˆŽŽŽ‘$š%»Once–éxa“bug“has“bšRïeen“found,“add“a“corresp˜onding“test“case.ަ‘ڇ̀ˆŽŽŽ‘$š%»W‘ÿ0e–f$greatly›f#bRïenetted“from“an“automated˜test“system:‘.A‘fshell“script,Ž¡‘$š%running›<ünigh•­tly‘ÿ0,‘‘Ýc“hec“ks‘<ýout˜and˜installs˜all˜relev‘ÿZan“t˜pac“k‘ÿZages.‘ /ÅAfterŽ¡‘$š%that–~ all“test›~ suites“are“run“and˜the“resulting“test“protoRïcol˜is“storedŽ¡‘$š%in–»þa‘»ÿcenš­tral“loRïcation.‘ ¬ÌThis“pro˜vides“an‘»ÿexcellen˜t“o˜v˜erview‘»ÿo˜v˜er“theŽ¡‘$š%curren­t–rSstatus›rTof“the˜system“and˜the“collection˜of“nigh­tly˜test“protoRïcolsŽ¡‘$š%doRïcumenš­ts–éxthe“dev˜elopmen˜t“progress.Ž‘:9Ÿc7ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïGps:SDict begin [/View [/XYZ H.V]/Dest (section.2) cvn /DEST pdfmark endŸ¬Â2Ž‘&µThe–záR›ÿváUnit“pac˜k‘þíÄageŽŸ^)»This–\Êsection›\Ëcon­tains“a˜detailed“explanation˜of“the˜Rš­Unit“pac˜k‘ÿZage‘\Ëand“exam-Ž¡ples–Êåhoš­w“to“use“it.‘+As“has‘Êæalready“bRïeen“men˜tioned“the“pac˜k‘ÿZage“con˜tains“t˜w˜oŽ¡indep•Rïendenš­t‘ žcomp“onen˜ts:‘ÅËa– žframew˜ork› for“test“case“execution“and˜a“toRïol“thatŽ¡allo­ws–H‡to›HˆinspRïect“the˜o­w“of˜execution“inside˜a“function˜in“order˜to“analyseŽ¡whic­h–úÞpšRïortions‘úÝof“co˜de›úÝare“co•­v“ered˜b“y–úÞsome˜test“case.‘ihBoth“compRïonen­ts˜areŽ¡no­w–éxdiscussed“in“turn.ŽŸÅ ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïLps:SDict begin [/View [/XYZ H.V]/Dest (subsection.2.1) cvn /DEST pdfmark endŸ��ó#кß�ff� ���aebx12Î2.1Ž‘$àÄT‘þ©,est–ffcase“executionŽŸ=h»The–šbasic››idea“of˜this“compRïonen­t˜is“to“execute˜a“set˜of“test˜functions“denedŽ¡through–ò®naming“con•­v“en“tions,‘4üstore–ò®whether“or“not“the‘ò¯test“succeeded“in“aŽŽŸ��’�ÇK!4ŽŽŽŒ‹�����������������������������������������>yïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.5) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘:9»cen­tral–ˆ‡logger›ˆ†ob‘�¥àject“and“nally“write˜a“test“protoRïcol“that“allo­ws˜to“preciselyޤ€�‘:9iden­tify–éxthe“problems.Ž¡‘Ú-ÃNote,‘+*that–ôRš ÇUnit‘õ-“b˜y“default“-‘õsets“the“v˜ersion‘õfor“normal,‘+*andŽ¡‘:9all–��other“RNGs“to“'Kinderman-Ramage',‘LÍand“'Marsaglia-Multicarry',Ž¡‘:9resp_8ectiv• Çely‘þâO.‘ ”~If›±y“ou˜lik“e˜to˜c“hange˜these‘±€defaults˜please˜see˜ó$ëXc� ��� ���aett12Ï?de-Ž¡‘:9fineTestSuite–€�Ãfor“argumen Çt“'rngNormalKind'“and“'rngKind'.Ž¡‘Ú-»As–:an›;example“consider“a“function˜that“con•­v“erts‘:cen“tigrade˜to‘:F‘ÿ0ahrenheit:ޤ33‘:9ó%…JÇö� ��� ���aesltt10Ðc2f–I¹<-“function(c)“return(9/5“*“c“+“32)ŽŽŽ¡‘:9»A–éxcorrespšRïonding“test“function“could“lo˜ok“lik­e“this:ŽŸ34‘:9Ðtest.c2f–I¹<-“function()“{ŽŽŽ¤€�‘Í«checkEquals(c2f(0),‘I¹32)ŽŽ¡‘Í«checkEquals(c2f(10),‘I¹50)ŽŽ¡‘Í«checkException(c2f("xx"))ŽŽ¡‘:9}ŽŽ©33‘:9»The–+Šdefault›+‹naming“con•­v“en“tion˜for–+Štest˜functions“in˜the“R•­Unit˜pac“k‘ÿZage‘+ŠisŽ¡‘:9Ïtest...›üy»as‘+äis–+ãstandard“in“JUnit.˜T‘ÿ0o“pRïerform“the‘+äactual“c•­hec“ks–+ãthat“theŽ¡‘:9function–gßto›gÞbRïe“tested“w­orks“correctly˜a“set“of“functions˜called“Ïcheck‘*ÿ...Ž¡‘:9»is–ã®pro­vided.‘#ÙThe›ã­purpRïose“of“these˜Ïcheck“»functions˜is“t•­w“o-fold:‘)£they‘ã®mak“eŽ¡‘:9sure–Àøthat›À÷a“pRïossible˜failure“is˜repRïorted“to˜the“cen­tral˜test“logger˜so“thatŽ¡‘:9it–Ñ–will“appšRïear“prop˜erly‘Ñ•in“the“nal“test“proto˜col“and‘Ñ•they“are“supp˜osed“toŽ¡‘:9makš­e–ðüexplicit“the‘ðýactual“c˜hec˜ks“in“a›ðýtest“case“as“oppRïosed“to˜other“coRïde“usedŽ¡‘:9to–øMset“up“the“test“scenario.‘a¸Note“that“ÏcheckException“»fails“if“the“passedŽ¡‘:9expression–ÔdoRïes“not“generate“an“error.‘ôâThis“kind“of“test“is“useful“to“mak­eŽ¡‘:9sure–´that“a›´�function“correctly“recognises“error“situations˜instead“of“silen­tlyŽ¡‘:9creating›cƒinappropriate–c‚results.‘£XThese“c•­hec“k˜functions–c‚are˜direct“equiv‘ÿZalen­tsŽ¡‘:9to–RÄthe“v‘ÿZarious‘RÅÏassert“»functions“of“the“JUnit“framew­ork.‘qMore“informationŽ¡‘:9can–éxbRïe“found“in“the“online“help.Ž¡‘Ú-Before–�Õrunning›�Ôthe“test˜function“it“is˜necessary“to“create˜a“test˜suite“whic­hŽ¡‘:9is–¯Ãa›¯Âcollection“of˜test“functions“and˜les“relating˜to“one˜topic.‘!üOne“could,‘»MforŽ¡‘:9instance,‘›jcreate–wÔone“test›wÓsuite“for˜one“R–w¯pac­k‘ÿZage.‘àJA“test–wÔsuite˜is“just˜a“listŽ¡‘:9conš­taining–+~a‘+}name,‘;ÿan“arra˜y“of‘+}absolute“directories“con˜taining‘+}the“loRïcationsŽ¡‘:9of–vöthe›võtest“les,‘šUa˜regular“expression˜iden­tifying“the“test˜les“and˜a“regularŽ¡‘:9expression–ùXiden­tifying›ùWthe“test“functions.‘å-In“our˜example“assume“that˜the“testŽ¡‘:9function–ã~is›ã}loRïcated“in˜a“le˜Ïrunitc2f.r“»loRïcated˜in“a˜directory“Ï/foo/bar/».Ž¡‘:9T‘ÿ0o–éxcreate“the“correspšRïonding“test“suite“w­e“can“use“a“help˜er“function:ަ‘:9Ðtestsuite.c2f–I¹<-“defineTestSuite("c2f",ŽŽŽ¡‘r‚dirs–I¹=“file.path(.path.package(package="RUnit"),ŽŽ¡’�·Ju"examples"),ŽŽŽŸ��’�ÇK!»5ŽŽŽŒ‹�����������������������������������������MNïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.6) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘r‚ÐtestFileRegexp–I¹=“"^runit.+\\.r",ŽŽ¤€�‘r‚testFuncRegexp–I¹=“"^test.+",ŽŽ¡‘r‚rngKind–I¹=“"Marsaglia-Multicarry",ŽŽ¡‘r‚rngNormalKind–I¹=“"Kinderman-Ramage")ŽŽ©„’‘:9»All–éxthat“remains“is“to“run“the“test“suite“and“prin­t“the“test“protoRïcol:ŽŸ„“‘:9ÐtestResult–I¹<-“runTestSuite(testsuite.c2f)ŽŽŽ¡‘:9printTextProtocol(testResult)ŽŽ¦‘:9»The–¯resulting“test“protošRïcol“should“b˜e‘®self“explanatory“and“can“also“b˜e“prin­tedŽ¡‘:9as–°ÔHTML‘°Åv­ersion.‘"VSee“the“online›°Óhelp“for“further˜information.‘"WNote˜that“forŽ¡‘:9executing–¬èjust›¬çone“test˜le“there˜is“also˜a“shortcut˜in“order˜to“mak­e˜test“caseŽ¡‘:9execution–éxas“easy“as“pRïossible:ަ‘:9ÐrunTestFile(file.path(.path.package(package="RUnit"),ŽŽŽ¡‘R®å"examples/runitc2f.r"))ŽŽ¦‘Ú-»The–8öcreation“and“execution“of“test“suites‘8õcan“bRïe“summarised“b­y“the“fol-Ž¡‘:9lo­wing‘éxrecipRïe:Ž‘:9Ÿ­ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïDps:SDict begin [/View [/XYZ H.V]/Dest (Item.1) cvn /DEST pdfmark end¤×‘a@1.ŽŽŽ‘_ìcreate–éxas“manš­y“test“functions“in“as“man˜y“test“les“as“necessaryŽŸÿ\ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïDps:SDict begin [/View [/XYZ H.V]/Dest (Item.2) cvn /DEST pdfmark end¡‘a@2.ŽŽŽ‘_ìcreate–j™one“or“more“test“suites‘j˜using“the“helpRïer“function“ÏdefineTest-Ž©€�‘_ìSuiteŽŸ«nïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïDps:SDict begin [/View [/XYZ H.V]/Dest (Item.3) cvn /DEST pdfmark end¤+n‘a@»3.ŽŽŽ‘_ìrun–éxthe“test“suites“with“ÏrunTestSuiteŽŸ«mïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïDps:SDict begin [/View [/XYZ H.V]/Dest (Item.4) cvn /DEST pdfmark end¡‘a@»4.ŽŽŽ‘_ìprin­t–qÈthe›qÉtest“protoRïcol˜either“with˜ÏprintTextProtocol“»or˜with“Ïprint-ަ‘_ìHTMLProtocol–éx»(or“with“a“generic“methoRïd“lik­e“Ïprint“»or“Ïsummary»)ŽŸ„’‘ŸôW‘ÿ0e–®¥conclude“this“section“with‘®¤some“further“commen­ts“on“v‘ÿZarious“aspRïectsަof–éxthe“test“execution“framew­ork:ŽŸ„“‘ NÌ€ˆŽŽŽ‘_ì»A‘¸test–¸Gle“can“conš­tain“an“arbitrary“n˜um˜bRïer“of“test“functions.‘¡¥A‘¸testަ‘_ìdirectory–can›con­tain“an˜arbitrary“n•­um“bRïer–of˜test“les,‘ a˜test“suiteަ‘_ìcan–÷conš­tain“an“arbitrary“n˜um˜bRïer“of‘øtest“directories“and“the“test“runnerަ‘_ìcan–Çrrun›Çqan“arbitrary“n•­um“bRïer˜of–Çrtest“suites“˜all“resulting“in˜one“testަ‘_ìprotoRïcol.‘ÞäThe–æztest“function“and“le“names“of“a“test“suite“m•­ust,‘Gho“w“ev“er,ަ‘_ìobRïey–ì a›ì naming“con•­v“en“tion˜expressible–ì through˜regular“expressions.‘<ìAsަ‘_ìdefault–éxtest“functions“start“with“Ïtest“»and“les“with“Ïrunit».ŽŸÖÛ‘ NÌ€ˆŽŽŽ‘_ì»R•­Unit›1Ãmak“es˜a˜distinction˜bRïet“w“een˜failure˜and˜error.‘A‘1°failure˜oRïccursަ‘_ìif–ÏOone›ÏPof“the“c•­hec“k˜functions–ÏOfail“(e.g.˜ÏcheckTrue(FALSE)‘ÎÒ»creates“aަ‘_ìfailure).‘ SAn–qÇerror›qÈis“repRïorted“if˜an“ordinary˜R‘q©error“(usually˜created“b­yަ‘_ìÏstop»)‘éxoRïccurs.ŽŽŸ��’�ÇK!6ŽŽŽŒ‹�����������������������������������������[)ïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.7) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘ڇ̀ˆŽŽŽ‘$š%»Since–Ðnv­ersion›Ðm0.4.0“there“is˜a“function“ÏDEACTIVATED‘Ðg»whic­h“can˜bRïe“usedޤ€�‘$š%to–^‡deactiv‘ÿZate›^ˆtest“cases˜tempRïorarily‘ÿ0.‘”fThis˜migh­t“bRïe˜useful“in˜the“caseŽ¡‘$š%of–Q¯a›Q®ma‘�¥àjor“refactoring.‘ mÜIn“particular,‘«¼the“deactiv‘ÿZated“test˜cases“areŽ¡‘$š%repšRïorted–éxin“the“test“proto˜col“so“that“they“cannot“fall“in­to“oblivion.Ž©€�‘ڇ̀ˆŽŽŽ‘$š%»The–Âtest›Ãrunner“tries“hard˜to“lea•­v“e–Âa“clean˜R‘§session˜bRïehind.‘¦ThereforeŽ¡‘$š%all–$0ob‘�¥àjects›$1created“during˜test“case“execution˜will“bRïe˜deleted“after˜a“testŽ¡‘$š%le–éxhas“bšRïeen“pro˜cessed.ަ‘ڇ̀ˆŽŽŽ‘$š%»In–ÿ²order›ÿ³to“prev•­en“t˜m“ysterious–ÿ²errors“the˜random“n•­um“bRïer˜generator‘ÿ²isŽ¡‘$š%reset–½Mto“a“standard“setting“bRïefore“sourcing“a‘½Ltest“le.‘°·If“a“particularŽ¡‘$š%setting–Ïis›Ïneeded“to“generate“reproRïducible˜results“it“is“ne˜to“congureŽ¡‘$š%the–˜Wrandom“n•­um“bšRïer‘˜Vgenerator–˜Wat“the“b˜eginning‘˜Vof“a“test“le.‘ AÔThisŽ¡‘$š%setting–[|applies›[{during“the“execution˜of“all“test˜functions“of“that˜test“leŽ¡‘$š%but–éxis“reset“bRïefore“the“next“test“le“is“sourced.ަ‘ڇ̀ˆŽŽŽ‘$š%»In–LHeac­h›LGsource“le“one˜can“dene“the“parameterless˜functions“Ï.setUp()Ž¡‘$š%»and–°÷Ï.tearDown()».‘‹¶whic­h“are›°øthen“executed“directly“bRïefore˜and“afterŽ¡‘$š%eac­h› Qtest– Rfunction.‘—ÃThis“can,‘R‡for˜instance,‘RˆbRïe˜used˜to“con­trol˜globalŽ¡‘$š%settings–éxor“create“addition“log“information.Ž‘:9Ÿûïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïLps:SDict begin [/View [/XYZ H.V]/Dest (subsection.2.2) cvn /DEST pdfmark endŸ¬Î2.2Ž‘$àÄR–ffCošrCde“Insp˜ectionŽŸ=h»The–CošRïde“Insp˜ector‘is“an“additional“to˜ol›for“c•­hec“king–detailed“test˜case“co•­v“er-Ž¡age–=.and“getting“proling“information.‘ûÊIt‘=/records“ho­w“often“a“cošRïde“line“will“b˜eŽ¡executed.‘ÁéW‘ÿ0e–m³utilise“this“information“for“impro­ving“our“test“cases,‘ŽÂbRïecauseŽ¡w•­e›yJcan‘yIiden“tify˜coRïde˜lines˜not‘yIexecuted˜b“y˜the˜curren“t‘yItest˜case˜coRïde.‘ä­TheŽ¡Co•Rïde›Z&Insp“ector˜is˜able‘Z'to˜handle˜S4˜metho“ds.‘rDuring‘Z'the˜dev•­elopmen“t˜of˜theŽ¡Co•Rïde›«œInsp“ector,–Ü$w­e˜noticed,“that˜the–«›syn­tax˜of“R‘«jis˜v­ery“exible.‘{£BecauseŽ¡our–Ø[coRïding›ØZphilosoph­y“has˜an“emphasis˜of“main­tenance˜and“a“clear˜st•­yle,‘ÛÇw“eŽ¡dev•­elopRïed›º:st“yle–º;guides˜for˜our“R‘ºcoRïding.‘§Therefore,‘îkone˜goal˜for“the˜CoRïdeŽ¡InspšRïector–¯Aw­as“to“handle“our‘¯@co˜ding“st­yles“in“a“correct“manner.‘!ÐThis“leads“toŽ¡the–]Ôconsequence“that“not“all“R‘]¶expression“can‘]ÓbRïe“handled“correctly‘ÿ0.‘’LIn“ourŽ¡implemen­tation–©athe“CošRïde“Insp˜ector“has‘©bt•­w“o–©amain“functional“parts.‘ÛThe“rstŽ¡part–r€is›rrespRïonsible“for“parsing˜and“moRïdifying“the˜coRïde“of“the˜test“function.Ž¡The–Ìsecond“part,›Écalled“the“T‘ÿ0rac•­k“er,˜holds–Ìthe‘Ì result“of“the“coRïde“trac­king.Ž¡The–g result“of‘gthe“tracš­king“proRïcess“allo˜ws“further“analysis‘gof“the“executedŽ¡coRïde.ŽŽŸ��’�ÇK!7ŽŽŽŒ‹�����������������������������������������hÉïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.8) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i��‘:9 ý°��ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïQps:SDict begin [/View [/XYZ H.V]/Dest (subsubsection.2.2.1) cvn /DEST pdfmark endŸ ��Ã2.2.1Ž‘)80UsageŽŸ=h»The–˦usage‘˧of“the“CošRïde“Insp˜ector›˧and“the“T‘ÿ0rac•­k“er˜ob‘�¥àject–˦is“v­ery˜simple.‘+GTheޤ€�follo­wing–éxcošRïde“snipp˜et“is“an“example:Ž©€�Ð>‘I¹library(RUnit)ŽŽŽ¡>–I¹foo“<-“function(x)“{ŽŽ¡+‘px–I¹<-“x“*“xŽŽ¡+‘px–I¹<-“2“*“xŽŽ¡+‘preturn(x)ŽŽ¡+‘I¹}ŽŽ¡>–I¹test.foo“<-“function()“{ŽŽ¡+‘pcheckTrue(is.numeric(foo(1:10)))ŽŽ¡+‘pcheckEquals(length(foo(1:10)),‘I¹10)ŽŽ¡+‘pcheckEqualsNumeric(foo(1),‘I¹2)ŽŽ¡+‘I¹}ŽŽ¡>–I¹bar“<-“function(x,“y“=“NULL)“{ŽŽ¡+‘pif–I¹(is.null(y))“{ŽŽ¡+‘8—y–I¹<-“xŽŽ¡+‘p}ŽŽ¡+‘pif–I¹(all(y“>“100))“{ŽŽ¡+‘8—y–I¹<-“y“-“100ŽŽ¡+‘p}ŽŽ¡+‘pres–I¹<-“x^yŽŽ¡+‘preturn(res)ŽŽ¡+‘I¹}ŽŽ¡>–I¹track“<-“tracker()ŽŽ¡>‘I¹track$init()ŽŽ¡>–I¹a“<-“1:10ŽŽ¡>–I¹d“<-“seq(0,“1,“0.1)ŽŽ¡>–I¹resFoo“<-“inspect(foo(a),“track“=“track)ŽŽ¡>–I¹resBar“<-“inspect(bar(d),“track“=“track)ŽŽ¡>–I¹resTrack“<-“track$getTrackInfo()ŽŽ¡>‘I¹printHTML.trackInfo(resTrack)ŽŽ¦‘Ÿô»Note,‘ëthat–—mthe›—ntrac­king“ob‘�¥àject“is˜an“global“ob‘�¥àject˜and“m•­ust˜ha“v“e‘—mtheŽ¡name–*HÏtrack».‘÷§The“Ïinspect“»function“a•­w“aits–*Ha“function‘*Gcall“as“argumen­t“andŽ¡executes–@¤and“tracš­ks“the“function.‘:½The“results“will“bRïe“stored“in“the“trac˜kingŽ¡ob‘�¥àject.‘€%The–­result›­of“the“function˜(not“of“the˜T‘ÿ0rac•­k“er)–­will“bRïe˜returned“asŽ¡usual.‘‹The–“ptrac­king›“qresults“will˜receivš­ed“b˜y‘“qtr$getResult().‘‹With“ÏprintHTMLŽ¡»the–éxresult“of“the“trac­king“prošRïcess“will“b˜e“presen­ted“as“HTML“pages.ŽŽŸ��’�ÇK!8ŽŽŽŒ‹��� ��������������������������������������vÉïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïDps:SDict begin [/View [/XYZ H.V]/Dest (page.9) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i��‘:9 ý°��ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïQps:SDict begin [/View [/XYZ H.V]/Dest (subsubsection.2.2.2) cvn /DEST pdfmark endŸ ��Ã2.2.2Ž‘)80T‘þâOec Çhnical‘€�DetailsŽŸ=h»The–º¥general›º¦idea“for˜the“coRïde˜trac­king“is“to˜moRïdify“the˜source“coRïde˜of“theޤ€�function.‘ñTherefore,‘ w­e–ÒÄuse“the›ÒÃÏparse“»and“Ïdeparse“»functions˜and“the“ca-Ž¡pabilit­y–*Ìof›*ËR‘*yto“generate“functions˜on“runš­time.‘ù3T‘ÿ0o“trac˜k“the‘*Ëfunction“w˜eŽ¡try–zDto›zEinclude“a˜hoRïok“in“ev­ery˜cošRïde“line.‘çžThat“ho˜ok“calls›zEa“function˜of“theŽ¡trac•­k“ed–Õ9ob‘�¥àject.‘.xThe“information“of“the“trac­king“will‘Õ8bRïe“stored“in“the“closureŽ¡of–)ïthe›)ðtrac­king“ob‘�¥àject“(actually˜a“function).‘õ`Because˜the“R‘)¾parser˜alloš­ws“v˜eryŽ¡nested–hexpressions,‘@Ÿw­e›ididn't“try“to˜moRïdify“ev­ery“R‘2expression.‘îÞThis“is˜a“taskŽ¡for–éxthe“future.‘58A“simple“example“for“the“mošRïdifying“pro˜cess“is“as“follo­w:Ž¡original:Ž©€�Ð>–I¹foo“<-“function(x)“{ŽŽŽ¡+‘py–I¹<-“0ŽŽ¡+‘pfor–I¹(i“in“1:x)“{ŽŽ¡+‘8—y–I¹<-“y“+“xŽŽ¡+‘p}ŽŽ¡+‘preturn(y)ŽŽ¡+‘I¹}ŽŽ¦»moRïdied:ަÐ>–I¹foo.mod“<-“function(x)“{ŽŽŽ¡+‘ptrack$bp(1)ŽŽ¡+‘py–I¹<-“0ŽŽ¡+‘ptrack$bp(2)ŽŽ¡+‘pfor–I¹(i“in“1:x)“{ŽŽ¡+‘8—track$bp(4)ŽŽ¡+‘8—y–I¹<-“y“+“xŽŽ¡+‘p}ŽŽ¡+‘ptrack$bp(6)ŽŽ¡+‘preturn(y)ŽŽ¡+‘I¹}ŽŽ¦‘Ÿô»Problematic–éxcoRïde“lines“are:Ž©€�Ð>–I¹if“(any(a“==“1))“{ŽŽŽ¡+‘pprint("do‘I¹TRUE")ŽŽ¡+–I¹}“else“print("do“FALSE")ŽŽ¦»This–éxm­ust“bšRïe“mo˜died“toŽŽŸ��’�ÇK!9ŽŽŽŒ‹��� ��������������������������������������_ïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïEps:SDict begin [/View [/XYZ H.V]/Dest (page.10) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘:9Ð>–I¹if“(any(a“==“1))“{ŽŽŽ¤€�‘:9+‘ptrack$bp(2)ŽŽ¡‘:9+‘pprint("do‘I¹TRUE")ŽŽ¡‘:9+–I¹}“else“{ŽŽ¡‘:9+‘ptrack$bp(3)ŽŽ¡‘:9+‘pprint("do‘I¹FALSE")ŽŽ¡‘:9+‘I¹}ŽŽ©€�‘:9»The–ú8problem“is›ú7the“Íelse‘݇»branc­h,‘þhthat˜cannot“bšRïe“mo˜died“in‘ú7the“currenš­t“v˜er-Ž¡‘:9sion.Ž‘:9ŸHïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïGps:SDict begin [/View [/XYZ H.V]/Dest (section.3) cvn /DEST pdfmark endŸ��Â3Ž‘&µF‘þd›uture›záDev–ÿváelopmen“t˜IdeasŽŸ^)»Here– Jw­e› Kbriey“list“˜in“an“unordered˜manner““some˜of“the“a•­v“en“ues˜for‘ JfutureŽ¡dev•­elopmen“t›éxw“e˜or˜someone˜in“terested˜in˜this˜pac“k‘ÿZage˜could˜tak“e:ަ‘ NÌ€ˆŽŽŽ‘_ì»extend–ŸÜthe›ŸÛÏcheckEquals“»function˜to“handle˜complex“S4˜class“ob‘�¥àjectsŽ¡‘_ìcorrectly–øiin“comparisons.‘b T‘ÿ0o‘øhthis“end“R‘øecore“has“moRïdied“c•­hec“k.equalŽ¡‘_ìto–éxhandle“S4“ob‘�¥àjects.ަ‘ NÌ€ˆŽŽŽ‘_ì»reimplemen•­t›€the‘€�in“ternal˜structures–€�storing˜the“test˜suite“as˜w­ell“as˜theŽ¡‘_ìtest–éxresult“data“as“S4“classes.ަ‘ NÌ€ˆŽŽŽ‘_ì»record–éxall“w­arnings“generated“during“the“execution“of“a“test“function.ަ‘ NÌ€ˆŽŽŽ‘_ì»add–öStoRïols“to“create“test“cases“automatically‘ÿ0.‘[ÈThis“is“a“researc­h“pro‘�¥àjectŽ¡‘_ìbut–ås“givš­en“the“impRïortance“of“testing“‘åtw˜orth“the“eort.‘))See“[ïps:SDict begin H.S end3Ž‘Þ0Ÿø(yïps:SDict begin H.R endŽ‘Þ0ï{ps:SDict begin [/Color [0 1 0]/H /I/Border [0 0 1]BorderArrayPatch/Subtype /Link/Dest (cite.junit) cvn H.B /ANN pdfmark endŽ‘Þ0]“forŽ¡‘_ìv‘ÿZarious–éxapproac­hes“in“other“languages.ަ‘ NÌ€ˆŽŽŽ‘_ì»impro•­v“e–þãthe“expRïort›þâof“test“suite“execution“data“e.g.˜b­y“adding“XMLŽ¡‘_ìdata–éxexpšRïort“supp˜ort.ަ‘ NÌ€ˆŽŽŽ‘_ì»add–ʼnsome“ev‘ÿZaluation“methošRïds“to“the“co˜de“insp˜ector“e.g.“use“soft•­w“areŽ¡‘_ìmetrics–oÌto“estimate‘oÍstandard“measures“of“coRïde“qualit•­y›ÿ0,‘ˆ"complexit“y˜,‘ˆ"andŽ¡‘_ìpRïerformance.ަ‘ NÌ€ˆŽŽŽ‘_ì»o•­v“ercome–¶|the“problem“of“nested“calls‘¶{to“registered“functions“for“coRïdeŽ¡‘_ìinspRïection.ަ‘ NÌ€ˆŽŽŽ‘_ì»allo­w–éxautomatic“registration“of“functions“&“methoRïds.ŽŽŸ��’�Ä\ 10ŽŽŽŒ‹��� ��������������������������������������‡Rïþps:SDict begin /product where{pop product(Distiller)search{pop pop pop version(.)search{exch pop exch pop(3011)eq{gsave newpath 0 0 moveto closepath clip/Courier findfont 10 scalefont setfont 72 72 moveto(.)show grestore}if}{pop}ifelse}{pop}ifelse}if endŸÿ ‘9Dïps:SDict begin H.S endïps:SDict begin H.R endïEps:SDict begin [/View [/XYZ H.V]/Dest (page.11) cvn /DEST pdfmark endŽŽ …Qœ ýy�� i�� ý¼��‘:9ÂReferencesŽ‘:9Ÿ Þ)ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïHps:SDict begin [/View [/XYZ H.V]/Dest (section*.3) cvn /DEST pdfmark endŸû��ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïEps:SDict begin [/View [/XYZ H.V]/Dest (cite.xp) cvn /DEST pdfmark endŸ€�‘Þ0»[1]ŽŽ‘\h­ttp://www.xprogramming.comޤ��ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïGps:SDict begin [/View [/XYZ H.V]/Dest (cite.beck) cvn /DEST pdfmark end©€�‘Þ0[2]ŽŽ‘\h•­ttp://www.xprogramming.com/testfram.h“tmŽ¡ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïHps:SDict begin [/View [/XYZ H.V]/Dest (cite.junit) cvn /DEST pdfmark end¦‘Þ0[3]ŽŽ‘\h­ttp://www.junit.org/Ž¡ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïFps:SDict begin [/View [/XYZ H.V]/Dest (cite.tfg) cvn /DEST pdfmark end¦‘Þ0[4]ŽŽ‘\h•­ttp://www.xprogramming.com/xpmag/testFirstGuidelines.h“tmŽ¡ïps:SDict begin H.S endïps:SDict begin 14.5 H.A endïKps:SDict begin [/View [/XYZ H.V]/Dest (cite.runit-sf) cvn /DEST pdfmark end¦‘Þ0[5]ŽŽ‘\h­ttps://sourceforge.net/pro‘�¥àjects/runit/ŽŽŸ��’�Ä\ 11ŽŽŽŒø��‘µƒ’À;����è…Qœ:9� � ó%…JÇö� ��� ���aesltt10ó$ëXc� ��� ���aett12ó#кß�ff� ���aebx12ó"”Ší@� ��� ���aeti12ó!ªã|C� ��� ���tcrm1200óкß� ��� ���aebx12óкß�G®� ���aebx12óa J¤�ff� ���aer12ó‡úBq�½q�G®�aer17óa J¤� ��� ���aer12ù��—Ößßßßßß����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/�������������������������������������������������������������������������������0000755�0001751�0000144�00000000000�11444151274�014313� 5����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitHTMLProtocol.r������������������������������������������������������������0000644�0001751�0000144�00000004737�11171573774�020073� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitHTMLProtocol.r,v 1.3 2009/04/16 09:18:52 burgerm Exp $ cat("\n\nRUnit test cases for 'HTMLProtocol' function\n\n") testRUnit.printHTMLProtocol <- function() { ## FIXME ## this is not safe, think about assigning .logger to new environment ## copy baseenv() .logger tmp <- get(".testLogger", envir = .GlobalEnv) testCaseDir <- file.path(system.file(package="RUnit"), "examples") testSuiteInternal <- defineTestSuite("RUnit Self Test", testCaseDir, "correctTestCase.r") testData2 <- runTestSuite(testSuiteInternal, useOwnErrorHandler=FALSE) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") testProtocolFile <- file.path(tempdir(), paste(timeStamp, "test_printHTMLProtocol.html", sep="_")) ret <- printHTMLProtocol(testData2, fileName=testProtocolFile) assign(".testLogger", tmp, envir = .GlobalEnv) checkTrue( file.exists(testProtocolFile)) ## input argument error handling ## missing 'testData' object checkException(printHTMLProtocol()) ## wrong class checkException(printHTMLProtocol("dummy")) ## fileName arg errors testData <- list() class(testData) <- "RUnitTestData" ## wrong type checkException(printHTMLProtocol(testData, fileName=numeric(1))) ## wrong length checkException(printHTMLProtocol(testData, fileName=character(0))) checkException(printHTMLProtocol(testData, fileName=character(2))) ## separateFailureList arg errors ## wrong type checkException(printHTMLProtocol(testData, separateFailureList=numeric(0))) ## wrong length checkException(printHTMLProtocol(testData, separateFailureList=logical(0))) checkException(printHTMLProtocol(testData, separateFailureList=logical(2))) } ���������������������������������RUnit/inst/unitTests/Makefile�����������������������������������������������������������������������0000644�0001751�0000144�00000000366�11274617056�015766� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������TOP=../../.. TEST_DIR=$(shell pwd) INST_PATH=$(shell dirname ${TEST_DIR}) PKG_PATH=$(shell dirname ${INST_PATH}) all: install test install: cd ${TOP}; \ R CMD INSTALL --clean ${PKG_PATH} && \ cd ${TEST_DIR} test: R --slave < runalltests.R ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitRUnit.r�������������������������������������������������������������������0000644�0001751�0000144�00000052672�11444146311�016631� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitRUnit.r,v 1.18 2010/09/15 13:40:25 burgerm Exp $ cat("\n\nRUnit test cases for 'RUnit:check' functions\n\n") testRUnit.checkEquals <- function() { ##@bdescr ## test case for function checkEquals of class: none ##@edescr ## integer x <- 1:10 checkEquals(x, x) ## return value checkTrue( checkEquals(x, x)) namedInt <- 1:10 names(namedInt) <- letters[namedInt] checkEquals(namedInt, namedInt) checkEquals(namedInt, x, checkNames=FALSE) ## numeric checkEquals(pi, pi) y <- 1/0 checkEquals(Inf, y) checkEquals(y, Inf) y <- log(-1) checkEquals(NaN, y) checkEquals(rep(NaN, 23), rep(y, 23)) checkEquals(9, 9.0) checkEquals(NA, NA) checkEquals(rep(NA, 14), rep(NA, 14)) checkEquals( numeric(1), numeric(1)) checkEquals( 0.01, 0.02, tolerance=0.01) tmp <- c(0.01, NA, 0.02, Inf, -Inf, NaN, 1.0) checkEquals( tmp, tmp, tolerance=0.01) ## complex checkEquals(complex(0), complex(0)) checkEquals(complex(2), complex(2)) checkEquals(complex(2, imaginary=1), complex(2, imaginary=1)) ## character checkEquals( character(1), character(1)) checkEquals( letters, letters) ## matrix checkEquals( matrix(1, 3,5), matrix(1, 3,5)) checkEquals( matrix(1, 50000,5), matrix(1, 50000,5), "large matrix not identified as equal") ## language checkEquals( expression(2), expression(2)) checkEquals( call("mean", "median"), call("mean", "median")) ## formula simpleForm <- x ~ 1 checkEquals( simpleForm, simpleForm, "simple formula not identified as equal") compForm <- y ~ x + y + x*y + offset(x) checkEquals( compForm, compForm, "formula not identified as equal") ## factor alphaFac <- factor(letters) checkEquals( alphaFac, alphaFac, "factor not identified as equal") ## list checkEquals( list(100), list(100)) checkEquals( list(100), list(100), tolerance=1) alphaList <- seq_along(letters) names(alphaList) <- letters checkEquals( alphaList, alphaList) checkEquals( alphaList, alphaList, checkNames=FALSE) ## nested list with NA, NaN, Inf nl <- list(a=list(1), b=list(1:4), c=list(ab=1, bc=list(list(2), list(NA), list(NaN)) ), d=list(m1=matrix(NA, 2,3), m2=matrix(1+1i, 4,5)), e=list(e1=NaN, e2=list(Inf), e3=list(a=Inf, b=-Inf, c=NaN, d=-0/0))) checkEquals(nl, nl) ## example from ?glm counts <- c(18,17,15,20,10,20,25,13,12) outcome <- gl(3,1,9) treatment <- gl(3,3) lmFit <- glm(counts ~ outcome + treatment, family=poisson()) checkEquals( lmFit, lmFit, checkNames=FALSE) checkEquals( lmFit, lmFit) lmFitUnnamed <- lmFit names(lmFitUnnamed) <- NULL checkEquals( lmFit, lmFitUnnamed, checkNames=FALSE) ## POSIXct sysTime <- as.POSIXct(Sys.time()) checkEquals( sysTime, sysTime) ## raw checkEquals( raw(14), raw(14)) namedRaw <- as.raw(1:14) names(namedRaw) <- letters[1:14] checkEquals( namedRaw, namedRaw) ## formula a <- 1:10 f <- gl(2,5) checkEquals( a~f, a~f) ## S4 objects if (identical(TRUE, require(methods))) { setClass("track1", representation(x="numeric", y="numeric"), where=.GlobalEnv) on.exit(removeClass("track1", where=.GlobalEnv)) s4Obj <- try(new("track1")) s4Obj@x <- 1:10 s4Obj@y <- 10:1 checkEquals( s4Obj, s4Obj) ## S4 class containing S4 class slot setClass("trackPair", representation(trackx = "track1", tracky = "track1"), where=.GlobalEnv) on.exit(removeClass("trackPair", where=.GlobalEnv), add=TRUE) tPair <- new("trackPair") tPair@trackx <- s4Obj tPair@tracky <- s4Obj checkEquals( tPair, tPair) } if (require(Biobase)) { ## class still available? #if (isClass(Class="ExpressionSet", formal=TRUE)) { # ES <- new("ExpressionSet", exprs=matrix(runif(1000), nrow=100, ncol=10)) # checkEquals(ES, ES) #} ## cleanup workspace ## catch error if this ns is required by some other package ## and therefore cannot be unloaded try(unloadNamespace("Biobase")) } ## detect differences checkException( checkEquals(1 , 1, tolerance=FALSE)) checkException( checkEquals(1 , 1, tolerance=numeric(0))) checkException( checkEquals(1 , 1, tolerance=numeric(2))) ## integer namedInt <- 1:9 names(namedInt) <- letters[namedInt] checkException( checkEquals( namedInt, 1:9)) ## numeric checkException( checkEquals( 8, 9)) checkException( checkEquals( 0.01, 0.02, tolerance=0.009)) checkException(checkEquals(NaN, NA)) checkException(checkEquals(NaN, Inf)) checkException(checkEquals(NaN, -Inf)) checkException(checkEquals(NA, Inf)) checkException(checkEquals(NA, -Inf)) checkException(checkEquals(numeric(2), numeric(3))) checkException(checkEquals(numeric(3), numeric(2))) ## complex checkException( checkEquals(complex(0), complex(1))) checkException( checkEquals(complex(2), complex(1))) checkException( checkEquals(complex(2, imaginary=1), complex(2, imaginary=0))) checkException( checkEquals(complex(2, real=1, imaginary=1), complex(2, real=1, imaginary=0))) checkException( checkEquals(complex(2, real=1, imaginary=1), complex(2, real=0, imaginary=1))) checkException( checkEquals(complex(2, real=1, imaginary=1), complex(2, real=0, imaginary=0))) ## character named <- character(1) names(named) <- "name" checkException( checkEquals( character(1), named)) checkException( checkEquals( letters, letters[-1])) ## formula checkException( checkEquals( lmFit, lmFitUnnamed)) lmFitInter <- glm(counts ~ outcome * treatment, family=poisson()) checkException( checkEquals( lmFitInter, lmFit)) ## factor alphaFacRecoded <- factor(alphaFac, labels=as.character(seq_along(levels(alphaFac)))) checkException( checkEquals(alphaFacRecoded, alphaFac)) ## list checkException( checkEquals( list(1), list("1"=1))) checkException( checkEquals( list(), list("1"=1))) checkException( checkEquals( list(list(), list(list()), list(list(list()))), list(list(), list(list()), list(list(list(), list()))))) ## POSIXct checkException( checkEquals(as.POSIXct(Sys.time()), as.POSIXct("2007-04-04 16:00:00"))) checkException( checkEquals(as.POSIXlt(Sys.time()), as.POSIXlt("2007-04-04 16:00:00"))) ## nested type sysTime <- as.POSIXct(Sys.time()) checkException( checkEquals( list(a=2, list(time=sysTime)), list(a=2, time=list(sysTime)))) ## raw checkException( checkEquals(raw(1), raw(2))) checkException( checkEquals(raw(1E5), raw(100001))) raw3 <- raw(3) raw3mod <- raw3 raw3mod[1] <- as.raw(3) checkException( checkEquals(raw3, raw3mod)) checkException( checkEquals(as.raw(1:1000), as.raw(c(1:99,-1,101:1000)) ) ) ## S4 objects if (identical(TRUE, require(methods))) { ## class defined above s4Obj <- new("track1") s4Obj@x <- 1:10 checkException( checkEquals( s4Obj, new("track1"))) tPair <- new("trackPair") tPair@trackx <- s4Obj checkException( checkEquals( tPair, new("trackPair"))) } } testRUnit.checkEqualsNumeric <- function() { ##@bdescr ## test case for function checkEqualsNumeric of class: none ##@edescr checkTrue( checkEqualsNumeric( 9,9)) checkTrue( checkEqualsNumeric( 9.1,9.2, tolerance=0.1)) x <- 1:10 attributes(x) <- list(dummy="nonsense") checkTrue( checkEqualsNumeric( x, x)) checkTrue( checkEqualsNumeric( 1:10, x, check.attributes=FALSE)) rvec <- rnorm(132) checkTrue( checkEqualsNumeric( matrix(rvec, 12, 11), matrix(rvec, 12, 11))) checkTrue( checkEqualsNumeric( rvec, rvec)) ## special constants checkEqualsNumeric( pi, pi) checkEqualsNumeric( NA, NA) checkEqualsNumeric( c(1, NA, 3), c(1, NA, 3)) checkEqualsNumeric( NaN, NaN) checkEqualsNumeric( c(1, NaN, 3), c(1, NaN, 3)) checkEqualsNumeric( Inf, Inf) checkEqualsNumeric( c(1, Inf, 3), c(1, Inf, 3)) checkEqualsNumeric( -Inf, -Inf) checkEqualsNumeric( c(1, -Inf, 3), c(1, -Inf, 3)) ## numeric difference checkException( checkEqualsNumeric( 9, 10)) checkException( checkEqualsNumeric( list(9), list(10))) checkException( checkEqualsNumeric( matrix(9), matrix(10))) rvec2 <- rnorm(132) checkException( checkEqualsNumeric( matrix(rvec, 12, 11), matrix(rvec2, 12, 11))) ## exception handling ## type not supported checkException( checkEqualsNumeric( list(rvec), list(rvec))) if (require(Biobase)) { ## class still available? if (isClass(Class="ExpressionSet", formal=TRUE)) { ES <- new("ExpressionSet", exprs=matrix(runif(1000), nrow=100, ncol=10)) checkException(checkEqualsNumeric(ES, ES)) } ## cleanup workspace try(unloadNamespace("Biobase")) } } testRUnit.checkIdentical <- function() { ##@bdescr ## test case for function checkIdentical of class: none ##@edescr checkIdentical( TRUE, TRUE) ## return value checkTrue( checkIdentical( TRUE, TRUE)) checkIdentical( FALSE, FALSE) ## bit representation identical checkIdentical( NA, NA) checkIdentical( c(1, NA, 3), c(1, NA, 3)) checkIdentical( NaN, NaN) checkIdentical( c(1, NaN, 3), c(1, NaN, 3)) checkIdentical( Inf, Inf) checkIdentical( c(1, Inf, 3), c(1, Inf, 3)) checkIdentical( -Inf, -Inf) checkIdentical( c(1, -Inf, 3), c(1, -Inf, 3)) checkIdentical( as.integer(2), as.integer(2)) checkIdentical( as.character(2), as.character(2)) checkIdentical( as.complex(2), as.complex(2)) checkIdentical( as.numeric(2), as.numeric(2)) checkIdentical( as.expression("2+4"), as.expression("2+4")) checkIdentical( as.expression(2+4), as.expression(2+4)) checkIdentical( as.factor(letters), factor(letters)) ## nested list with NA, NaN, Inf nl <- list(a=list(1), b=list(1:4), c=list(ab=1, bc=list(list(2), list(NA), list(NaN)) ), d=list(m1=matrix(NA, 2,3), m2=matrix(1+1i, 4,5)), e=list(e1=NaN, e2=list(Inf), e3=list(a=Inf, b=-Inf, c=NaN, d=-0/0))) checkIdentical(nl, nl) ## POSIX sysTime <- as.POSIXlt(Sys.time()) checkIdentical( sysTime, sysTime) ## raw checkIdentical( raw(14), raw(14)) namedRaw <- as.raw(1:14) names(namedRaw) <- letters[1:14] checkIdentical( namedRaw, namedRaw) ## formula a <- 1:10 f <- gl(2,5) checkIdentical( a~f, a~f) ## call cl <- call("round", 10.5) checkIdentical( cl, cl) ## S3 objects (ie. lists with attributes) ## from ?lm Example ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14) trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69) group <- gl(2,10,20, labels=c("Ctl","Trt")) weight <- c(ctl, trt) lm.D9 <- lm(weight ~ group) checkIdentical( lm.D9, lm(weight ~ group)) ## S4 objects if (identical(TRUE, require(methods))) { setClass("track1", representation(x="numeric", y="numeric"), where=.GlobalEnv) on.exit(removeClass("track1", where=.GlobalEnv)) s4Obj <- try(new("track1")) checkIdentical( s4Obj, new("track1")) rm(s4Obj) } ## exception handling ## type mismatches checkException( checkIdentical( as.integer(2), as.numeric(2))) checkException( checkIdentical( as.integer(2), as.character(2))) checkException( checkIdentical( as.integer(2), as.list(2))) checkException( checkIdentical( as.integer(2), as.complex(2))) checkException( checkIdentical( as.integer(2), as.expression(2))) ## value mismatches checkException( checkIdentical( as.integer(2), as.integer(3))) checkException( checkIdentical( as.character(2), as.character(3))) checkException( checkIdentical( as.complex(2), as.complex(3))) checkException( checkIdentical( as.numeric(2), as.numeric(3))) checkException( checkIdentical( as.expression("2+4"), as.expression("2+3"))) checkException( checkIdentical( as.factor(letters), factor(letters[-1]))) fac <- factor(letters) levels(fac) <- c("1", letters[-1]) checkException( checkIdentical( fac, as.factor(letters))) ## nested list with NA, NaN, Inf checkException( checkIdentical( )) ## POSIX sysTime <- as.POSIXlt(Sys.time()) checkException( checkIdentical( sysTime, as.POSIXlt(Sys.time(), tz="GMT"))) ## raw checkException(checkIdentical( raw(14), raw(13))) namedRaw <- as.raw(1:14) names(namedRaw) <- letters[1:14] checkException(checkIdentical( namedRaw, as.raw(1:14))) ## S3 objects (ie. lists with attributes) ## from ?lm Example lm.D9base <- lm(weight ~ group - 1) checkException( checkIdentical( lm.D9base, lm.D9)) ## S4 objects if (identical(TRUE, require(methods))) { setClass("track2", representation(x="numeric", y="numeric"), prototype(x=as.numeric(1:23), y=as.numeric(23:1)), where=.GlobalEnv) on.exit(removeClass("track2", where=.GlobalEnv), add=TRUE) s4Obj <- try(new("track2")) s4ObjDiff <- s4Obj s4ObjDiff@y <- s4ObjDiff@x checkException( checkIdentical( s4Obj, s4ObjDiff)) } } testRUnit.checkTrue <- function() { ##@bdescr ## test case for function checkTrue of class: none ##@edescr checkEquals( checkTrue( TRUE), TRUE) ## named arguments namedArg <- TRUE names(namedArg) <- "Yes" checkEquals( checkTrue( namedArg), TRUE) ## errorr handling namedArg <- FALSE names(namedArg) <- "No" checkException( checkTrue( namedArg)) checkException( checkTrue( FALSE)) ## incorrect length checkException( checkTrue( c(TRUE, TRUE))) checkException( checkTrue( c(FALSE, TRUE))) checkException( checkTrue( logical(0))) checkException( checkTrue( logical(2))) } testRUnit.checkException <- function() { ##@bdescr ## test case for function checkException of class: none ##@edescr checkException( checkTrue( FALSE)) checkException( checkTrue( )) checkException( checkEquals( )) checkException( checkEquals( 24)) checkException( checkEquals( 24, 24, tolerance="dummy")) checkException( checkEqualsNumeric( )) checkException( checkEqualsNumeric( 24)) checkException( checkEqualsNumeric( 24, 24, tolerance="dummy")) checkException( stop("with message"), silent=FALSE) checkException( stop("wo message"), silent=TRUE) ## R 2.5.0 devel example that failed ## minimal example provided by Seth Falcon ll = list() ll[[1]] = function(x) stop("died") checkException( do.call(ll[[1]], list(1))) ## S4 objects if (identical(TRUE, require(methods))) { setClass("track2", representation(x="numeric", y="numeric"), prototype(x=as.numeric(1:23), y=as.numeric(23:1)), where=.GlobalEnv) on.exit(removeClass("track2", where=.GlobalEnv)) s4Obj <- try(new("track2")) checkException( slot(s4Obj, "z")) checkException( slot(s4Obj, "z") <- 1:10) ## missing method argument ## coerce(from, to) checkException( coerce(s4Obj)) } } testRUnit.DEACTIVATED <- function() { ##@bdescr ## test case for function DEACTIVATED of class: none ##@edescr checkException( DEACTIVATED()) checkException( DEACTIVATED("some message")) ## compound text checkException( DEACTIVATED(c("some message", "some more", "and more"))) } testRUnit.defineTestSuite <- function() { ##@bdescr ## test case for function defineTestSuite of class: none ##@edescr ## correct working testSuite <- defineTestSuite("RUnit Example", system.file("examples", package="RUnit"), testFileRegexp="correctTestCase.r") ## this also works for S3 objects checkTrue( inherits(testSuite, "RUnitTestSuite")) checkTrue( is.list(testSuite)) checkTrue( all(c("name", "dirs", "testFileRegexp", "testFuncRegexp", "rngKind", "rngNormalKind") %in% names(testSuite))) checkTrue( isValidTestSuite(testSuite)) ## error handling ## missing 'dirs' argument checkException(defineTestSuite("RUnit Example", testFileRegexp="correctTestCase.r")) } testRUnit.isValidTestSuite <- function() { ##@bdescr ## test case for function isValidTestSuite of class: none ##@edescr ## correct working testSuite <- defineTestSuite("RUnit Example", system.file("examples", package="RUnit"), testFileRegexp="correctTestCase.r") checkTrue( isValidTestSuite(testSuite)) ## error handling ## has to be S3 class 'RUnitTestSuite' testSuiteFail <- testSuite class(testSuiteFail) <- "NotUnitTestSuite" checkTrue( !isValidTestSuite(testSuiteFail)) ## expecting list elements testSuiteFail <- testSuite testSuiteFail[["dirs"]] <- NULL checkTrue( !isValidTestSuite(testSuiteFail)) ## has to be character testSuiteFail <- testSuite testSuiteFail[["name"]] <- list() checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["dirs"]] <- list() checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["testFileRegexp"]] <- list() checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["testFuncRegexp"]] <- list() checkTrue( !isValidTestSuite(testSuiteFail)) ## length 1 required testSuiteFail <- testSuite testSuiteFail[["name"]] <- character(0) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["name"]] <- character(2) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["testFileRegexp"]] <- character(0) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["testFileRegexp"]] <- character(2) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["testFuncRegexp"]] <- character(0) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["testFuncRegexp"]] <- character(2) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["rngKind"]] <- character(0) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["rngKind"]] <- character(2) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["rngNormalKind"]] <- character(0) checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["rngNormalKind"]] <- character(2) checkTrue( !isValidTestSuite(testSuiteFail)) ## director has to exist testSuiteFail <- testSuite testSuiteFail[["dirs"]] <- "doesNotExist" checkTrue( !isValidTestSuite(testSuiteFail)) testSuiteFail <- testSuite testSuiteFail[["dirs"]] <- c(tempdir(), "doesNotExist", tempdir()) checkTrue( !isValidTestSuite(testSuiteFail)) ## same, '' has to return FALSE testSuiteFail <- testSuite testSuiteFail[["dirs"]] <- c(tempdir(), "", tempdir()) checkTrue( !isValidTestSuite(testSuiteFail)) } testRUnit.runTestFile <- function() { ##@bdescr ## test case for function runTestFile of class: none ##@edescr testFile <- file.path(system.file("examples", package="RUnit"), "correctTestCase.r") checkTrue( file.exists(testFile)) ## The issue: .testLogger is the hard coded logger object ## regenerated by each new run call in the global environment ## thereby overwriting the existing logger. ## With the current implementation there seems to be no way to ## test the test suite execution *within* a test suite run # tmpFile <- tempfile() # writeLines(text=" testFile <- file.path(system.file(\"examples\", package=\"RUnit\"), \"correctTestCase.r\");\n res <- runTestFile(testFile, useOwnErrorHandler=FALSE);\n", con=tmpFile) # # execEnv <- new.env(parent=.GlobalEnv) # sys.source(tmpFile, execEnv) # unlink(tmpFile) # checkTrue(exists("res", envir=execEnv)) # checkTrue(inherits(get("res", envir=execEnv), "RUnitTestData")) # rm(execEnv) ## error handling ## all argument checks delegated to runTestSuite so no need for comprehensive check here ## check if any argument check is reached/performed ## useOwnErrorHandler ## type logical checkException( runTestFile(testFile, useOwnErrorHandler=integer(1))) } testRUnit.runTestSuite <- function() { ##@bdescr ## test case for function runTestSuite of class: none ##@edescr testSuiteTest <- defineTestSuite("RUnit Example", system.file("examples", package="RUnit"), testFileRegexp="correctTestCase.r") checkTrue( isValidTestSuite(testSuiteTest)) ## The issue: same as above ##res <- runTestSuite(testSuiteTest) ## ## error handling ## ## useOwnErrorHandler ## type logical tS <- testSuiteTest checkException( runTestSuite(tS, useOwnErrorHandler=integer(1))) ## length 1 checkException( runTestSuite(tS, useOwnErrorHandler=logical(0))) checkException( runTestSuite(tS, useOwnErrorHandler=logical(2))) checkException( runTestSuite(tS, useOwnErrorHandler=as.logical(NA))) ## testSuite } ����������������������������������������������������������������������RUnit/inst/unitTests/runalltests.R������������������������������������������������������������������0000644�0001751�0000144�00000000564�11274617056�017031� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������library("RUnit") options(warn=1) testSuite <- defineTestSuite(name="RUnit", dirs=".", testFileRegexp="runit.*\\.r$", rngKind="default", rngNormalKind="default") testData <- runTestSuite(testSuite, verbose=0L) printTextProtocol(testData, showDetails=FALSE) ��������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitPlotConnection.r����������������������������������������������������������0000644�0001751�0000144�00000005500�11171573774�020530� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitPlotConnection.r,v 1.3 2009/04/16 09:18:52 burgerm Exp $ cat("\n\nRUnit test cases for 'RUnit:plotConnection' function\n\n") testRUnit.plotConnection <- function() { ##@bdescr ## test case for function plotConnection of class: none ##@edescr ## requires X server to be available for png device if (!interactive()) { DEACTIVATED("plotConnection uses png device which requires X sverer to be available.") } ## 1) no counts conMat <- matrix(0, nrow=5, ncol=5) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") tmpPlotFile <- file.path(tempdir(), paste(timeStamp, "connectionPlot.png", sep="_")) ret <- RUnit:::plotConnection.trackInfo(conMat, tmpPlotFile) checkTrue( is(ret, "NULL")) checkTrue( file.exists(tmpPlotFile)) ## clean up try(unlink(tmpPlotFile)) ## 2) num <- 5 conMat <- matrix(sample(1:3, num^2, replace=TRUE), nrow=num, ncol=num) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") tmpPlotFile <- file.path(tempdir(), paste(timeStamp, "connectionPlot2.png", sep="_")) ret <- RUnit:::plotConnection.trackInfo(conMat, tmpPlotFile) checkTrue( is(ret, "NULL")) checkTrue( file.exists(tmpPlotFile)) ## clean up try(unlink(tmpPlotFile)) num <- 25 colNum <- 3 conMat <- matrix(sample(1:3, num*colNum, replace=TRUE), nrow=num, ncol=colNum) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") tmpPlotFile <- file.path(tempdir(), paste(timeStamp, "connectionPlot3.png", sep="_")) ret <- RUnit:::plotConnection.trackInfo(conMat, tmpPlotFile) checkTrue( is(ret, "NULL")) checkTrue( file.exists(tmpPlotFile)) ## clean up try(unlink(tmpPlotFile)) num <- 25 colNum <- 3 conMat <- matrix(sample(0:3, num*colNum, replace=TRUE), nrow=num, ncol=colNum) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") tmpPlotFile <- file.path(tempdir(), paste(timeStamp, "connectionPlot4.png", sep="_")) ret <- RUnit:::plotConnection.trackInfo(conMat, tmpPlotFile) checkTrue( is(ret, "NULL")) checkTrue( file.exists(tmpPlotFile)) ## clean up try(unlink(tmpPlotFile)) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitInspect.r�����������������������������������������������������������������0000644�0001751�0000144�00000011143�11173620417�017164� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitInspect.r,v 1.6 2009/04/22 13:52:15 burgerm Exp $ cat("\n\nRUnit test cases for 'RUnit:inspect' functions\n\n") .tearDown <- function() { if (exists("track", envir=.GlobalEnv)) { rm(track, envir=.GlobalEnv) } } bar <- function(x) { y <- 0 for(i in 1:100) { y <- y + i } return(y) } foo <- function(x) { if (length(x)) n <- length(x) len <- if(n==0) "zero" else if (n==1) "one" else if (n==2) "two" else if (n==3) "three" else "many" cat("object contains",len, "elements") return(n) } foo2 <- function(x) { if (length(x)) n <- length(x) ## should not confuse tracker len <- ifelse(n==0, "zero", "more") cat("object contains",len, "elements") } testRUnit.inspect <- function() { foo <- function(x) { y <- 0 for(i in 1:100) { y <- y + i } return(y) } ## the name track is necessary track <<- tracker() ## initialize the tracker track$init() ## inspect the function ## res will collect the result of calling foo res <- inspect(foo(10), track=track) checkEquals( res, 5050) } testRUnit.inspect.extended <- function() { ## the name track is necessary track <<- tracker() ## initialize the tracker track$init() # from ? svd hilbert <- function(n) { i <- 1:n; 1 / outer(i - 1, i, "+") } X <- hilbert(9)[,1:6] s <- svd(X) res <- inspect(svd(X), track=track) checkEquals( res, s) } testRUnit.getTrackInfo <- function() { ## the name track is necessary track <<- tracker() ## initialize the tracker track$init() ## inspect the function checkTrue( exists("bar")) ## res will collect the result of calling foo res <- inspect(bar(10), track=track) checkEquals( res, 5050) res <- inspect(foo(10), track=track) checkEquals( res, 1) res <- inspect(foo2(10), track=track) ## get the tracked function call info resTrack <- track$getTrackInfo() checkTrue( is.list(resTrack)) checkTrue( c("R/foo2") %in% names(resTrack)) checkEquals( names(resTrack$"R/foo2"), c("src", "run", "time", "graph", "nrRuns", "funcCall")) } testRUnit.printHTML <- function() { ## the name track is necessary track <<- tracker() ## initialize the tracker track$init() ## inspect the function checkTrue( exists("bar")) ## res will collect the result of calling foo res <- inspect(bar(10), track=track) checkEquals( res, 5050) ## get the tracked function call info resTrack <- track$getTrackInfo() outDir <- tempdir() ##checkTrue( is.null(printHTML(resTrack, baseDir=outDir))) checkTrue( is.null(printHTML.trackInfo(resTrack, baseDir=outDir))) checkTrue( "index.html" %in% dir(file.path(outDir, "results"))) inspect(foo(1:3), track=track) resTrack <- track$getTrackInfo() checkTrue( is.null(printHTML.trackInfo(resTrack, baseDir=outDir))) ## error handling checkException(printHTML("notCorrectClass")) ## baseDir checkException(printHTML(resTrack, baseDir=logical(1))) checkException(printHTML(resTrack, baseDir=character(0))) checkException(printHTML(resTrack, baseDir=character(2))) checkException(printHTML(resTrack, baseDir=as.character(NA))) } testRUnit.printHTML.extended <- function() { ## the name track is necessary track <<- tracker() ## initialize the tracker track$init() # from ? svd hilbert <- function(n) { i <- 1:n; 1 / outer(i - 1, i, "+") } X <- hilbert(9)[ ,1:6] s <- svd(X) res <- inspect(svd(X, LINPACK=TRUE), track=track) res <- inspect(svd(X), track=track) res <- inspect(svd(X, nu=nrow(X)), track=track) res <- inspect(svd(X, nv=ncol(X)), track=track) res <- inspect(svd(X, nv=0L), track=track) resTrack <- track$getTrackInfo() outDir <- tempdir() checkTrue( is.null(printHTML.trackInfo(resTrack, baseDir=outDir))) } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitS4.r����������������������������������������������������������������������0000644�0001751�0000144�00000005743�11171573774�016071� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitS4.r,v 1.2 2009/04/16 09:18:52 burgerm Exp $ cat("\n\nRUnit test cases for S4 class inheritance\n\n") testRUnit.S4classInheritance <- function() { ##@bdescr ## test case for noneof class: none ## test if S4 classes can be instantiated inside test code ## given that no where argument is specified ##@edescr className <- setClass("testVirtualClass", representation("VIRTUAL", x = "numeric", y = "numeric", xlab = "character", ylab = "character") ) checkEquals(className, "testVirtualClass") checkException( new(className)) derivedClassName <- setClass("testDerivedClass", representation(className, scale = "numeric", title = "character") ) ## Attention: ## invert inheritance order! on.exit(removeClass(derivedClassName)) on.exit(removeClass(className), add=TRUE) checkEquals(derivedClassName, "testDerivedClass") objD <- new(derivedClassName) checkTrue( is(objD, derivedClassName)) checkTrue( isS4(objD)) checkTrue(require(stats4)) ## instantiate S4 class from stats ## be sure to use a unique unused variable name here ## i.e. NOT className as this has been used before ## and the on.exit call will look up the name just *before* ## the test function exists classNameMLE <- "mle" obj <- new(classNameMLE) checkTrue( is(obj, classNameMLE)) checkTrue( isS4(obj)) derivedStats4ClassName <- setClass("mleChild", representation(classNameMLE, scale = "numeric", title = "character") ) on.exit(removeClass(derivedStats4ClassName), add=TRUE) checkEquals(derivedStats4ClassName, "mleChild") obj <- new("mleChild") checkTrue( is(obj, "mleChild")) checkTrue( isS4(obj)) } �����������������������������RUnit/inst/unitTests/runitTextProtocol.r������������������������������������������������������������0000644�0001751�0000144�00000005230�11171573774�020240� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitTextProtocol.r,v 1.3 2009/04/16 09:18:52 burgerm Exp $ cat("\n\nRUnit test cases for 'textProtocol' function\n\n") testRUnit.printTextProtocol <- function() { ## copy baseenv() logger tmp <- get(".testLogger", envir = .GlobalEnv) testCaseDir <- file.path(system.file(package="RUnit"), "examples") testSuiteInternal <- defineTestSuite("RUnit Self Test", testCaseDir, "correctTestCase.r") testData2 <- runTestSuite(testSuiteInternal, useOwnErrorHandler=FALSE) timeStamp <- format(Sys.time(), "%y%m%d-%H%M") testProtocolFile <- file.path(tempdir(), paste(timeStamp, "test_printHTMLProtocol.txt", sep="_")) ret <- printTextProtocol(testData2, fileName=testProtocolFile) assign(".testLogger", tmp, envir = .GlobalEnv) checkTrue( file.exists(testProtocolFile)) ## input argument error handling ## missing 'testData' object checkException(printTextProtocol()) ## wrong class checkException(printTextProtocol("dummy")) ## fileName arg errors testData <- list() class(testData) <- "RUnitTestData" ## wrong type checkException(printTextProtocol(testData, fileName=numeric(1))) ## wrong length checkException(printTextProtocol(testData, fileName=character(0))) checkException(printTextProtocol(testData, fileName=character(2))) ## separateFailureList arg errors ## wrong type checkException(printTextProtocol(testData, separateFailureList=numeric(0))) ## wrong length checkException(printTextProtocol(testData, separateFailureList=logical(0))) checkException(printTextProtocol(testData, separateFailureList=logical(2))) ## showDetails arg errors ## wrong type checkException(printTextProtocol(testData, showDetails=numeric(0))) ## wrong length checkException(printTextProtocol(testData, showDetails=logical(0))) checkException(printTextProtocol(testData, showDetails=logical(2))) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitSetUp.r�������������������������������������������������������������������0000644�0001751�0000144�00000007404�11171573774�016637� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitSetUp.r,v 1.2 2009/04/16 09:18:52 burgerm Exp $ cat("\n\nRUnit test cases for '.setUp' function\n\n") ## defined for the life time of this environment warningsLengthDefault <- getOption("warnings.length") .setUp <- function() { ## define global variable if (exists("runitDummy", where=.GlobalEnv)) { stop(".setUp found 'runitDummy'.") } assign("runitDummy", "this is a test dummy variable", envir=.GlobalEnv) if( !exists("runitDummy", where=.GlobalEnv)) { stop(".setUp failed to assign 'runitDummy'.") } ## create temp file tempFile <- file.path(tempdir(), "runitDummyFile.txt") checkTrue( !file.exists(tempFile)) write.table(matrix(1:42, 6, 7), file=tempFile) if ( !file.exists(tempFile)) { stop(paste(".setUp failed to create file", tempFile)) } ## modify options ## current default: 1000 options(warnings.length=123) if ( !identical(TRUE, all.equal.numeric(getOption("warnings.length"), 123))) { stop(paste(".setUp failed to set options.")) } ## define S4 class checkTrue( !isClass("runitDummyS4Class", where=.GlobalEnv)) setClass("runitDummyS4Class", representation(x = "numeric", y = "numeric"), prototype(x = 1:10, y = 10:1), where=.GlobalEnv) if ( !isClass("runitDummyS4Class", where=.GlobalEnv)) { stop(paste(".setUp failed to define S4 class 'runitDummyS4Class'.")) } } testRUnit..setUp.Test1 <- function() { ##@bdescr ## testcase for function .setUp of class: none ## check existance of variables, modified options, class definitions ## defined in .setUp ## remove for subsequent check ##@edescr checkTrue( exists("runitDummy", where=.GlobalEnv)) ## remove global variable rm("runitDummy", envir=.GlobalEnv) tempFile <- file.path(tempdir(), "runitDummyFile.txt") checkTrue( file.exists(tempFile)) ## remove temp file unlink(tempFile) checkEqualsNumeric( getOption("warnings.length"), 123) ## reset options options(warnings.length=warningsLengthDefault) checkTrue( isClass("runitDummyS4Class", where=.GlobalEnv)) ## remove class checkTrue( removeClass("runitDummyS4Class", where=.GlobalEnv)) } testRUnit..setUp.Test2 <- function() { ##@bdescr ## testcase for function .setUp of class: none ## same as above, only reason is to check correct invocation of .setUp ## before *each* test case function ##@edescr checkTrue( exists("runitDummy", where=.GlobalEnv)) ## remove global variable rm("runitDummy", envir=.GlobalEnv) tempFile <- file.path(tempdir(), "runitDummyFile.txt") checkTrue( file.exists(tempFile)) ## remove temp file unlink(tempFile) checkEqualsNumeric( getOption("warnings.length"), 123) ## reset options options(warnings.length=warningsLengthDefault) checkTrue( isClass("runitDummyS4Class", where=.GlobalEnv)) ## remove class checkTrue( removeClass("runitDummyS4Class", where=.GlobalEnv)) } ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitTearDown.r����������������������������������������������������������������0000644�0001751�0000144�00000006341�11171573774�017321� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitTearDown.r,v 1.2 2009/04/16 09:18:52 burgerm Exp $ cat("\n\nRUnit test cases for '.tearDown' function\n\n") ## defined for the life time of this environment warningsLengthDefault <- getOption("warnings.length") .tearDown <- function() { ## remove global variable if (exists("runitDummy", envir=.GlobalEnv)) { try(rm("runitDummy", envir=.GlobalEnv)) } ## remove temp file tempFile <- file.path(tempdir(), "runitDummyFile.txt") if (file.exists(tempFile)) { try(unlink(tempFile)) } ## reset options options(warnings.length=warningsLengthDefault) ## remove class if (length(findClass("runitDummyS4Class")) > 0) { try(removeClass("runitDummyS4Class", where=.GlobalEnv)) } } testRUnit..tearDown.Init <- function() { ##@bdescr ## testcase for function .tearDown of class: none ## setup vriables to be removed by .tearDown after test case execution ## check in subsequent test case that this operation chain succeeded ##@edescr ## define global variable checkTrue( !exists("runitDummy", where=.GlobalEnv)) assign("runitDummy", "this is a test dummy variable", envir=.GlobalEnv) checkTrue( exists("runitDummy", where=.GlobalEnv)) ## create temp file tempFile <- file.path(tempdir(), "runitDummyFile.txt") checkTrue( !file.exists(tempFile)) write.table(matrix(1:42, 6, 7), file=tempFile) checkTrue( file.exists(tempFile)) ## modify options ## current default: 1000 options(warnings.length=123) checkEqualsNumeric( getOption("warnings.length"), 123) ## define S4 class checkTrue( !isClass("runitDummyS4Class", where=.GlobalEnv)) setClass("runitDummyS4Class", representation(x = "numeric", y = "numeric"), prototype(x = 1:10, y = 10:1), where=.GlobalEnv) checkTrue( isClass("runitDummyS4Class", where=.GlobalEnv)) } testRUnit..tearDown.Test <- function() { ##@bdescr ## testcase for function .tearDown of class: none ## test that all modifications resulting from the previous test case ## have been removed as defined in .tearDown ##@edescr checkTrue( !exists("runitDummy", where=.GlobalEnv)) tempFile <- file.path(tempdir(), "runitDummyFile.txt") checkTrue( !file.exists(tempFile)) checkEqualsNumeric( getOption("warnings.length"), warningsLengthDefault) checkTrue( !isClass("runitDummyS4Class", where=.GlobalEnv)) } �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/inst/unitTests/runitTestLogger.r��������������������������������������������������������������0000644�0001751�0000144�00000005627�11274614146�017654� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������## RUnit : A unit test framework for the R programming language ## Copyright (C) 2003-2009 Thomas Koenig, Matthias Burger, Klaus Juenemann ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; version 2 of the License. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## ## $Id: runitTestLogger.r,v 1.1 2009/11/05 18:24:38 burgerm Exp $ cat("\n\nRUnit test cases for '.testLogger' object\n\n") testRUnit..testLogger <- function() { ##@bdescr ## test case for .testLogger object of class: 'TestLogger' ##@edescr ## create new temp test logger object tlTmp <- RUnit:::.newTestLogger(TRUE) checkTrue( is(tlTmp, "TestLogger")) checkTrue( all( c("getTestData", "setCurrentTestSuite" , "setCurrentSourceFile", "addSuccess", "addError", "addFailure", "addDeactivated", "addCheckNum", "isFailure", "setFailure", "isDeactivated", "setDeactivated", "incrementCheckNum", "getCheckNum", "cleanup") %in% names(tlTmp))) testSuite <- defineTestSuite(name="Test Test", dirs=tempdir()) ## need to init 1) test suite name and 2) test case file name tlTmp$setCurrentTestSuite(testSuite) tlTmp$setCurrentSourceFile("Test File") tlTmp$addSuccess("first test case", system.time(1)) checkEquals(tlTmp$getTestData()[[1]]$nTestFunc, 1) tlTmp$incrementCheckNum() checkEquals(tlTmp$getCheckNum(), 1) checkTrue( !tlTmp$isFailure()) tlTmp$setFailure() checkTrue( tlTmp$isFailure()) checkTrue( !tlTmp$isDeactivated()) tlTmp$setDeactivated("This is a deactivated test case") checkTrue( tlTmp$isDeactivated()) tlTmp$cleanup() checkEquals(tlTmp$getCheckNum(), 0) checkTrue( !tlTmp$isFailure()) } testRUnit.getErrors <- function() { ##@bdescr ## test case for getErrors function ##@edescr ## create dummy test suite result object testData <- vector(mode="list", 3) for (i in seq_along(testData)) { testData[[i]]$nErr <- i testData[[i]]$nDeactivated <- i - 1 testData[[i]]$nTestFunc <- i*13 testData[[i]]$nFail <- i + 3 } class(testData) <- "RUnitTestData" res <- getErrors(testData) checkTrue (is.list(res)) checkEquals(length(res), 4) checkEquals(res$nErr, 6) checkEquals(res$nDeactivated, 3) checkEquals(res$nTestFunc, 78) checkEquals(res$nFail, 15) ## check exception handling checkException( getErrors( list())) } ���������������������������������������������������������������������������������������������������������RUnit/COPYING���������������������������������������������������������������������������������������0000644�0001751�0000144�00000043131�10046503544�012367� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. <signature of Ty Coon>, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/NAMESPACE�������������������������������������������������������������������������������������0000644�0001751�0000144�00000001763�11173617676�012576� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������###################################################################### ## ## RUnit ## ===================================== ## ## inst/NAMESPACE ## ===================================== ## initialization of classes, namespace, ... ## ## ## ## ## Version ## ===================================== ## $Id: NAMESPACE,v 1.7 2009/04/22 13:46:38 burgerm Exp $ ## ## ###################################################################### import(utils) import(methods) export(".setUp", ".tearDown", "checkTrue", "checkEquals", "checkEqualsNumeric", "checkException", "checkIdentical", "DEACTIVATED", "defineTestSuite", "getErrors", "inspect", "isValidTestSuite", "print.RUnitTestData", "printTextProtocol", "printHTMLProtocol", "printHTML.trackInfo", "runTestSuite", "runTestFile", "summary.RUnitTestData", "tracker") S3method(print, RUnitTestData) S3method(summary, RUnitTestData) �������������RUnit/DESCRIPTION�����������������������������������������������������������������������������������0000644�0001751�0000144�00000001242�11444353441�013041� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Package: RUnit Version: 0.4.26 Date: 2010/09/14 Title: R Unit test framework Author: Matthias Burger <burgerm@users.sourceforge.net>, Klaus Juenemann <k.junemann@gmx.net>, Thomas Koenig <thomas.koenig@epigenomics.com> Maintainer: Matthias Burger <burgerm@users.sourceforge.net> LazyLoad: yes Depends: R (>= 2.5.0), utils (>= 2.5.0), methods (>= 2.5.0) Description: R functions implementing a standard Unit Testing framework, with additional code inspection and report generation tools License: GPL-2 URL: https://sourceforge.net/projects/runit/ Packaged: 2010-09-15 14:05:48 UTC; burger Repository: CRAN Date/Publication: 2010-09-16 08:36:49 ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������RUnit/.cvsignore������������������������������������������������������������������������������������0000644�0001751�0000144�00000000011�10330111550�013306� 0����������������������������������������������������������������������������������������������������ustar �hornik��������������������������users������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������.project �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������