gdata/0000755000176000001440000000000012164457167011377 5ustar ripleyusersgdata/MD50000644000176000001440000002524112164457167011713 0ustar ripleyusersd06e90db42ff353bcd72b174500bef41 *ChangeLog 06148ef05a2d1fb9e7dc63726d2dca66 *DESCRIPTION 905fe9c5be6e143737163bc6317e6640 *INSTALL 4c9c62a120fea1d885151bb9e1f5e175 *NAMESPACE e8bc3126916e8abb0a56c6afffb64d79 *NEWS 92e3ca5e31d594044b8325a441142c37 *R/Args.R 94976a0bed5195b50511e200d1711280 *R/ConvertMedUnits.R eea4eaca4f623886f3b7381cc075778e *R/aggregate.table.R 38de1344cd5bc79f32a0b42e48b43965 *R/ans.R 78e0c21cf9e4693553a4174d9d3b3c80 *R/bindData.R df4bed53c71599dde15cbf23b4ca645a *R/case.R ea9399bf2240d9c3a536da45bcf34cd2 *R/cbindX.R d4034554742c82cdf9c7da28c5e5614c *R/centerText.R d1aa5d0677fb46d53b4e4628b18159c2 *R/combine.R 23a1a2a8bf811331e02ccd5668567cf4 *R/drop.levels.R 1e65b516ecac8ecc4d9caa8d66c6e494 *R/duplicated2.R 3896b0c9e1e81f87adb9c876f3ecfbda *R/elem.R 0388011f483caa3314a0688a376f7cc5 *R/env.R 7f43c48b182d910961f643876fefbdf9 *R/findPerl.R 4f9c6613afb87d8360ea897bbc485fe7 *R/frameApply.R d6474a86ab986d0cbcc8712797bbb57b *R/getDateTimeParts.R a4f086ff4289d532ac61ca2ecc5a8862 *R/installXLSXsupport.R 037266e58fb3a611b3a56bb09c898abd *R/interleave.R e9594e1749df0f487eaab95db4253e59 *R/is.what.R 4fc53a992903de783b5cd9a515f1242b *R/keep.R b17363a9b301491f375f1b898276c588 *R/ll.R b75ac1b645046c8028d8014de255bd25 *R/ls.funs.R 17850c5a2e9185aff447f7e19a125cb6 *R/mapLevels.R e7d2246f66781fe99981b2dd083dd6cb *R/matchcols.R afe62c0075aaa73974eabad0c53cf68c *R/nPairs.R 2141528b10d1732e0683ba27fc97f581 *R/nobs.R eca2d4b7165eb8ae97e0944284120cc9 *R/object.size.R c3c6e74c9238d0b99b74c09cf76b154d *R/onAttach.R 53d3ccd68f0b4b5d3e2c27d7bfaedc17 *R/read.xls.R aaace07c7a900ddec695220ad10e0d14 *R/rename.vars.R 8dbe70d52ae3d60a07aa928fc3c62413 *R/reorder.R cef4f8eb74136397feee111cf921676f *R/resample.R df4f4b68dcfee49ff4f57fd008ce6dcc *R/runRUnitTests.R f126721102aa7f6d258e74bf6215b831 *R/sheetCount.R dffd0684af87ed05ae550eab75f0787c *R/startsWith.R f511d0ee44c0d69a2d8e6ad195421243 *R/trim.R 05f7763f8efeef44932e4c47cfc091ff *R/trimSum.R 66f10bb3071d09b413973f03bd91d7a3 *R/unknown.R 0c763fce55062857b133aebac8695d8c *R/unmatrix.R d124821046808c5e8492a6db12ac0be4 *R/upperTriangle.R 5a0dcdddde5d9c1ec0d215d12f323500 *R/wideByFactor.R a568b5b2ffcd3552c2ccf06d17e88d01 *R/write.fwf.R 41c99f4c80f3c613c8173f93ec9c3bc0 *R/xls2sep.R 84c93b4e26e20d6ff792637f41c71df3 *R/xlsFormats.R 494447a9a3b7a389e79a556a1c356caa *data/MedUnits.rda d06e90db42ff353bcd72b174500bef41 *inst/ChangeLog e8bc3126916e8abb0a56c6afffb64d79 *inst/NEWS ac512b1ebd4d71ac96b2a4d5288d53cb *inst/bin/xls2csv ce0b4437c51faccb3595d986e8acae80 *inst/bin/xls2csv.bat 99af68b9933865da35d30b3f0d4606be *inst/doc/Rnews.dtx a7982b90f82857e34a253df2be42d7c1 *inst/doc/Rnews.sty e444b0ed03b42abe356a8ad70f055189 *inst/doc/gregmisc.pdf f1dc90111b7898b5944c1f67abec00a2 *inst/doc/gregmisc.tex b19ba078add1b84a300ae1adb5167567 *inst/doc/mapLevels.R afcc7e1ba12e2aab12a4349fc8470d08 *inst/doc/mapLevels.Rnw 4c6ef5f6392d7b16379427aebd117941 *inst/doc/mapLevels.pdf 788f58d8791841c0dd0a9bddfa28b8fe *inst/doc/unknown.R a968a07310286934daaea108e3f915f4 *inst/doc/unknown.Rnw 61a58e50ee3d6de9aa65406508f1ccaa *inst/doc/unknown.pdf 3622c5d29d09f1a179211f22acf6cdef *inst/perl/Archive/README-Archive-Zip 013677fabc8a49480cca5c10d67dd850 *inst/perl/Archive/Zip.pm da56a4326657fda95d0de93c65ed4006 *inst/perl/Archive/Zip/Archive.pm 51456309908c0b43ec573b698764f704 *inst/perl/Archive/Zip/BufferedFileHandle.pm d3839740a8b261feac1e977eba4721b1 *inst/perl/Archive/Zip/DirectoryMember.pm 88d6a6c71e83354937b6d16526e60da9 *inst/perl/Archive/Zip/FAQ.pod 613c672c74ec59faa88e958d16f8f2ad *inst/perl/Archive/Zip/FileMember.pm d179050e910601cc9052bc4e38ebd1b5 *inst/perl/Archive/Zip/Member.pm 6c7ce09c710d370be907cf1e70134209 *inst/perl/Archive/Zip/MemberRead.pm c6ecb7b9d336fa23a94929552eba6373 *inst/perl/Archive/Zip/MockFileHandle.pm bdffc1ab114897b87d109e06ffa94068 *inst/perl/Archive/Zip/NewFileMember.pm 5b969994e19eef9b0fda0c756dd529ef *inst/perl/Archive/Zip/StringMember.pm a0680f49434e681325498f3d0ce1147f *inst/perl/Archive/Zip/Tree.pm 5ad94e7c07432859fc85cec9b215b1a1 *inst/perl/Archive/Zip/ZipFileMember.pm dee03477030387a2eb3295ce879e5281 *inst/perl/IO/AtomicFile.pm d9c440abc4bd9ccbadb41b0f280bf2ab *inst/perl/IO/InnerFile.pm a36c1240a3b33a00e5155e7e3173d7c5 *inst/perl/IO/Lines.pm 6ed5fba59ad281b67e8018126aba53f7 *inst/perl/IO/Scalar.pm aaa5b626b1467f10703f741377f48f45 *inst/perl/IO/Scalar.pm.html 1c325acd29bf1ea0b161c6a857b4bba0 *inst/perl/IO/ScalarArray.pm ec57cd2a5a4c2b51c8052ea402790e90 *inst/perl/IO/Stringy.pm d4465a5c52bee28950caba33017cf126 *inst/perl/IO/Wrap.pm b535c978123c7e62748eb4492213a20a *inst/perl/IO/WrapTie.pm 75749fd752f9b91652bcc147694f00a1 *inst/perl/OLE/README-OLE-Storage_Lite bc2eb29f789cb0c16619b5d88e6f6410 *inst/perl/OLE/Storage_Lite.pm 2120c2a09e745f340014e2847812bcb9 *inst/perl/Spreadsheet/ParseExcel.pm 66cc990f8cf7dcc9ffc145f8e79e226d *inst/perl/Spreadsheet/ParseExcel/Cell.pm ca067073e60f54322c42f1f697ca74e0 *inst/perl/Spreadsheet/ParseExcel/Dump.pm e91db20e75505374857f2eb64474a9b3 *inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm ac8dad0ae1b3fbc2dc45dd0c32d94a8c *inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm 57d3b77da3e011dd2c4b528ecbb32423 *inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm 04ef4ce775c5af18b3bf820ebd10c41b *inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm dc6d43df24f7bdf84ea100f4fbd48717 *inst/perl/Spreadsheet/ParseExcel/Font.pm a66b33ae7c43dd18f9ac8f16005fedb7 *inst/perl/Spreadsheet/ParseExcel/Format.pm 65807f8d9ef5542a36210b10ee3f1e3c *inst/perl/Spreadsheet/ParseExcel/SaveParser.pm 7c66383e6456e4bf274ecd32345429b9 *inst/perl/Spreadsheet/ParseExcel/SaveParser/Workbook.pm 8e4ee9fc71392d04c1a1a4553b6f580e *inst/perl/Spreadsheet/ParseExcel/SaveParser/Worksheet.pm ff06c50a267369ebdcb35bb500f1b965 *inst/perl/Spreadsheet/ParseExcel/Utility.pm 4245f158cab85cac7d510d71c29cf3df *inst/perl/Spreadsheet/ParseExcel/Workbook.pm ec1611346621e6f90510acb619f5252a *inst/perl/Spreadsheet/ParseExcel/Worksheet.pm c9b8eab5a257c27463c22af1316e7241 *inst/perl/Spreadsheet/README-ParseExcel 359fb41631453c30b1c8341786d00195 *inst/perl/Spreadsheet/README-XLS 2534020557d8bfced5c2471cc74cd364 *inst/perl/Spreadsheet/XLSX.pm d1079689d1f8f016913714bc9b3534d1 *inst/perl/Spreadsheet/XLSX/Fmt2007.pm 5e9b67c572312470f95ef4470a030adb *inst/perl/Spreadsheet/XLSX/Utility2007.pm 441b297006e72c914e99851da06d4826 *inst/perl/VERSIONS 694c5ec63d43bc79613707bd7813dc7f *inst/perl/install_modules.pl 38970d085129a053e44c2fe5f704e80e *inst/perl/module_tools.pl 95fb12c6a78ec327de63e9a04f34775f *inst/perl/sheetCount.pl 95fb12c6a78ec327de63e9a04f34775f *inst/perl/sheetNames.pl f55aa6f304604c5f1eb96351f0dd9b82 *inst/perl/supportedFormats.pl 84e6c5093222000137198cc67f8f1da8 *inst/perl/xls2csv.pl 84e6c5093222000137198cc67f8f1da8 *inst/perl/xls2tab.pl 84e6c5093222000137198cc67f8f1da8 *inst/perl/xls2tsv.pl a616e808bd826e929f56223020649675 *inst/unitTests/Makefile 7b65e0f6b0ea277d2390df9b3f439fa0 *inst/unitTests/report.html f5603c25cdff9c9cbc647efee4f2b2fd *inst/unitTests/report.txt 515b18df7e17596dc38b9dbea407b26f *inst/unitTests/runRUnitTests.R 31c57f48835f4994ee0de16334d79d5b *inst/unitTests/runit.bindData.R 319f0ed3da5baab320fb7c26e24094b9 *inst/unitTests/runit.cbindX.R a4e4280826434377c475498474a7c9aa *inst/unitTests/runit.drop.levels.R 96281d9a32875f5c84672082985d4176 *inst/unitTests/runit.getDateTimeParts.R 10bc08472be4e03b9f025f0d7af1c0ff *inst/unitTests/runit.mapLevels.R 1f14c2e453df84fb51b90e2c97ea8b32 *inst/unitTests/runit.nPairs.R f76cb34a4512cab2c134ad432a01b965 *inst/unitTests/runit.reorder.factor.R b232e2a1977dc0d9d944a094a34a7656 *inst/unitTests/runit.trim.R 42330b4f7f6bd1cd335f59088d6bf282 *inst/unitTests/runit.trimSum.R 222994e34ee8182cee4f844131fc4753 *inst/unitTests/runit.unknown.R 07c0f9fc38612b196f2d7449c133fde2 *inst/unitTests/runit.wideByFactor.R 6ef53cf4cb6265365863cc9a58c4c1e9 *inst/unitTests/runit.write.fwf.R 59166d9d1e10ea9d544aad1d1a4ed978 *inst/xls/ExampleExcelFile.xls 59f44d54c2c09ee757af7b6724dc9d63 *inst/xls/ExampleExcelFile.xlsx 7c16d3cfd37123f3c321c12a92b9269a *inst/xls/iris.xls 8a0467a49bfb791295925cb6a372b1ff *inst/xls/latin-1.xls 36e751188a4e3d37ce3be57d2152922a *inst/xls/latin-1.xlsx 24a1020fb457c398c620457ad114e245 *man/Args.Rd b0dec88638d111fb8b0c75ebfd99cdfd *man/ConvertMedUnits.Rd 673f2150582676c574a306697b29ffa5 *man/MedUnits.Rd 8d8f92632f70e98c2063fd8ce368e5e7 *man/aggregate.table.Rd 6fcbcc90f241aa78bc0cd4ba479ac9bd *man/ans.Rd 140de526fc0a3c819dcd687e7bb3ed77 *man/bindData.Rd a4c69a81cca648bfdc2f6913229b4e0e *man/case.Rd 640626fce10a1b97ad82fd594f18b058 *man/cbindX.Rd ea80105996fa8d335490899cc37a5c35 *man/centerText.Rd 0c1246172eb620aed35dbfbc3e411b74 *man/combine.Rd fca345001344f5bfcbaac5f79e6f0762 *man/drop.levels.Rd a471e3c2a2b1ca5550a1822d5620e848 *man/duplicated2.Rd 28b102aeb6f3c62fe6b3b40fefa4c005 *man/elem.Rd e45e3959608492f8e12298d221e605e3 *man/env.Rd 73aeb6a00e393012dfc4fb1e0b8fc15a *man/frameApply.Rd a559b337732181f2cbc93d852de8ea17 *man/gdata-package.Rd 38580f70b4b3af84ebfa4b952dd7021b *man/getDateTimePart.Rd eb90a75f6e6d0171486d3a96626cf04b *man/humanReadable.Rd 6beab4e8b711110199599f8427d1d042 *man/installXLSXsupport.Rd 26bb8febce31195f8efcf071270913bc *man/interleave.Rd 0d70b8cd533a830a68103355b1054ec5 *man/is.what.Rd 8c50e81caf14aebb11d908fbcc9fe2de *man/keep.Rd 4bfbaf0835fff3cbc3ba8f17f9823bfb *man/ll.Rd dfe069423abb32eaed74b2daad0a56d8 *man/ls.funs.Rd 3723cf974f55156ced750e3235445f1b *man/mapLevels.Rd 3ca3aeaf85340d25fc36c6a5275fce2c *man/matchcols.Rd 4789e9c9a034bc5665d93c80579729ef *man/nPairs.Rd 4e3ba1601ecb171596b609516d2e8911 *man/nobs.Rd 67467a836f6e35a897d6bee4d0a7808d *man/object.size.Rd 2ad3d3570252d4954bdf4d81ea3404fa *man/read.xls.Rd b73a198509b4fdcb4a24a85909309532 *man/rename.vars.Rd dce038a56263e98621c3715f0aefecd3 *man/reorder.Rd fc28b1b680997fd8ff2ab73478db4872 *man/resample.Rd f6615191c438d8526183c169fcb38224 *man/runRUnitTests.Rd 55d4019112a5759791610fd48c20d4b3 *man/sheetCount.Rd 1a3958cb8dfc8a3d50d73e51bd280a08 *man/startsWith.Rd 7408562319ded22f6ea6dab9d21b25b3 *man/trim.Rd 347e8e1afc135b4ce6f5f3a7face76d5 *man/trimSum.Rd 4f5e0665c2c046b93f45963387b7d44f *man/unknown.Rd 5b789bc21ee7f46f8a9b138f1ed36829 *man/unmatrix.Rd 9778a0a2d069cddda0f2e821143d691e *man/upperTriangle.Rd ad219282ec6913083b82073691923f9b *man/wideByFactor.Rd 56d52a59a9c4f5132d5ae69673823ae8 *man/write.fwf.Rd 8a9c1fe9d0316d0b98e6d353c2b7a6cf *man/xlsFormats.Rd 10fe383026608ee1cf2c8f1b70a02c5b *tests/test.read.xls.R b829acdc86095be7759e0d001b8e9599 *tests/test.read.xls.Rout.save dee3232474b92bcdf1ad75ca31080792 *tests/test.write.fwf.eol.R b32b0eb85790d71ea6025ae5eca71fb1 *tests/tests.write.fwf.R dba6d4c18936f97e03225af5be4743ed *tests/tests.write.fwf.Rout.save 99af68b9933865da35d30b3f0d4606be *vignettes/Rnews.dtx a7982b90f82857e34a253df2be42d7c1 *vignettes/Rnews.sty afcc7e1ba12e2aab12a4349fc8470d08 *vignettes/mapLevels.Rnw a968a07310286934daaea108e3f915f4 *vignettes/unknown.Rnw gdata/vignettes/0000755000176000001440000000000012164370064013375 5ustar ripleyusersgdata/vignettes/unknown.Rnw0000644000176000001440000002336510747660474015611 0ustar ripleyusers %\VignetteIndexEntry{Working with Unknown Values} %\VignettePackage{gdata} %\VignetteKeywords{unknown, missing, manip} \documentclass[a4paper]{report} \usepackage{Rnews} \usepackage[round]{natbib} \bibliographystyle{abbrvnat} \usepackage{Sweave} \SweaveOpts{strip.white=all, keep.source=TRUE} \begin{document} \begin{article} \title{Working with Unknown Values} \subtitle{The \pkg{gdata} package} \author{by Gregor Gorjanc} \maketitle This vignette has been published as \cite{Gorjanc}. \section{Introduction} Unknown or missing values can be represented in various ways. For example SAS uses \code{.}~(dot), while \R{} uses \code{NA}, which we can read as Not Available. When we import data into \R{}, say via \code{read.table} or its derivatives, conversion of blank fields to \code{NA} (according to \code{read.table} help) is done for \code{logical}, \code{integer}, \code{numeric} and \code{complex} classes. Additionally, the \code{na.strings} argument can be used to specify values that should also be converted to \code{NA}. Inversely, there is an argument \code{na} in \code{write.table} and its derivatives to define value that will replace \code{NA} in exported data. There are also other ways to import/export data into \R{} as described in the {\emph R Data Import/Export} manual \citep{RImportExportManual}. However, all approaches lack the possibility to define unknown value(s) for some particular column. It is possible that an unknown value in one column is a valid value in another column. For example, I have seen many datasets where values such as 0, -9, 999 and specific dates are used as column specific unknown values. This note describes a set of functions in package \pkg{gdata}\footnote{ package version 2.3.1} \citep{WarnesGdata}: \code{isUnknown}, \code{unknownToNA} and \code{NAToUnknown}, which can help with testing for unknown values and conversions between unknown values and \code{NA}. All three functions are generic (S3) and were tested (at the time of writing) to work with: \code{integer}, \code{numeric}, \code{character}, \code{factor}, \code{Date}, \code{POSIXct}, \code{POSIXlt}, \code{list}, \code{data.frame} and \code{matrix} classes. \section{Description with examples} The following examples show simple usage of these functions on \code{numeric} and \code{factor} classes, where value \code{0} (beside \code{NA}) should be treated as an unknown value: <>= library("gdata") xNum <- c(0, 6, 0, 7, 8, 9, NA) isUnknown(x=xNum) @ The default unknown value in \code{isUnknown} is \code{NA}, which means that output is the same as \code{is.na} --- at least for atomic classes. However, we can pass the argument \code{unknown} to define which values should be treated as unknown: <>= isUnknown(x=xNum, unknown=0) @ This skipped \code{NA}, but we can get the expected answer after appropriately adding \code{NA} into the argument \code{unknown}: <>= isUnknown(x=xNum, unknown=c(0, NA)) @ Now, we can change all unknown values to \code{NA} with \code{unknownToNA}. There is clearly no need to add \code{NA} here. This step is very handy after importing data from an external source, where many different unknown values might be used. Argument \code{warning=TRUE} can be used, if there is a need to be warned about ``original'' \code{NA}s: <>= (xNum2 <- unknownToNA(x=xNum, unknown=0)) @ Prior to export from \R{}, we might want to change unknown values (\code{NA} in \R{}) to some other value. Function \code{NAToUnknown} can be used for this: <>= NAToUnknown(x=xNum2, unknown=999) @ Converting \code{NA} to a value that already exists in \code{x} issues an error, but \code{force=TRUE} can be used to overcome this if needed. But be warned that there is no way back from this step: <>= NAToUnknown(x=xNum2, unknown=7, force=TRUE) @ Examples below show all peculiarities with class \code{factor}. \code{unknownToNA} removes \code{unknown} value from levels and inversely \code{NAToUnknown} adds it with a warning. Additionally, \code{"NA"} is properly distinguished from \code{NA}. It can also be seen that the argument \code{unknown} in functions \code{isUnknown} and \code{unknownToNA} need not match the class of \code{x} (otherwise factor should be used) as the test is internally done with \code{\%in\%}, which nicely resolves coercing issues. <>= (xFac <- factor(c(0, "BA", "RA", "BA", NA, "NA"))) isUnknown(x=xFac) isUnknown(x=xFac, unknown=0) isUnknown(x=xFac, unknown=c(0, NA)) isUnknown(x=xFac, unknown=c(0, "NA")) isUnknown(x=xFac, unknown=c(0, "NA", NA)) (xFac <- unknownToNA(x=xFac, unknown=0)) (xFac <- NAToUnknown(x=xFac, unknown=0)) @ These two examples with classes \code{numeric} and \code{factor} are fairly simple and we could get the same results with one or two lines of \R{} code. The real benefit of the set of functions presented here is in \code{list} and \code{data.frame} methods, where \code{data.frame} methods are merely wrappers for \code{list} methods. We need additional flexibility for \code{list}/\code{data.frame} methods, due to possibly having multiple unknown values that can be different among \code{list} components or \code{data.frame} columns. For these two methods, the argument \code{unknown} can be either a \code{vector} or \code{list}, both possibly named. Of course, greater flexibility (defining multiple unknown values per component/column) can be achieved with a \code{list}. When a \code{vector}/\code{list} object passed to the argument \code{unknown} is not named, the first value/component of a \code{vector}/\code{list} matches the first component/column of a \code{list}/\code{data.frame}. This can be quite error prone, especially with \code{vectors}. Therefore, I encourage the use of a \code{list}. In case \code{vector}/\code{list} passed to argument \code{unknown} is named, names are matched to names of \code{list} or \code{data.frame}. If lengths of \code{unknown} and \code{list} or \code{data.frame} do not match, recycling occurs. The example below illustrates the application of the described functions to a list which is composed of previously defined and modified numeric (\code{xNum}) and factor (\code{xFac}) classes. First, function \code{isUnknown} is used with \code{0} as an unknown value. Note that we get \code{FALSE} for \code{NA}s as has been the case in the first example. <>= (xList <- list(a=xNum, b=xFac)) isUnknown(x=xList, unknown=0) @ We need to add \code{NA} as an unknown value. However, we do not get the expected result this way! <>= isUnknown(x=xList, unknown=c(0, NA)) @ This is due to matching of values in the argument \code{unknown} and components in a \code{list}; i.e., \code{0} is used for component \code{a} and \code{NA} for component \code{b}. Therefore, it is less error prone and more flexible to pass a \code{list} (preferably a named list) to the argument \code{unknown}, as shown below. <>= (xList1 <- unknownToNA(x=xList, unknown=list(b=c(0, "NA"), a=0))) @ Changing \code{NA}s to some other value (only one per component/column) can be accomplished as follows: <>= NAToUnknown(x=xList1, unknown=list(b="no", a=0)) @ A named component \code{.default} of a \code{list} passed to argument \code{unknown} has a special meaning as it will match a component/column with that name and any other not defined in \code{unknown}. As such it is very useful if the number of components/columns with the same unknown value(s) is large. Consider a wide \code{data.frame} named \code{df}. Now \code{.default} can be used to define unknown value for several columns: <>= df <- data.frame(col1=c(0, 1, 999, 2), col2=c("a", "b", "c", "unknown"), col3=c(0, 1, 2, 3), col4=c(0, 1, 2, 2)) @ <>= tmp <- list(.default=0, col1=999, col2="unknown") (df2 <- unknownToNA(x=df, unknown=tmp)) @ If there is a need to work only on some components/columns you can of course ``skip'' columns with standard \R{} mechanisms, i.e., by subsetting \code{list} or \code{data.frame} objects: <>= df2 <- df cols <- c("col1", "col2") tmp <- list(col1=999, col2="unknown") df2[, cols] <- unknownToNA(x=df[, cols], unknown=tmp) df2 @ \section{Summary} Functions \code{isUnknown}, \code{unknownToNA} and \code{NAToUnknown} provide a useful interface to work with various representations of unknown/missing values. Their use is meant primarily for shaping the data after importing to or before exporting from \R{}. I welcome any comments or suggestions. % \bibliography{refs} \begin{thebibliography}{1} \providecommand{\natexlab}[1]{#1} \providecommand{\url}[1]{\texttt{#1}} \expandafter\ifx\csname urlstyle\endcsname\relax \providecommand{\doi}[1]{doi: #1}\else \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi \bibitem[Gorjanc(2007)]{Gorjanc} G.~Gorjanc. \newblock Working with unknown values: the gdata package. \newblock \emph{R News}, 7\penalty0 (1):\penalty0 24--26, 2007. \newblock URL \url{http://CRAN.R-project.org/doc/Rnews/Rnews_2007-1.pdf}. \bibitem[{R Development Core Team}(2006)]{RImportExportManual} {R Development Core Team}. \newblock \emph{R Data Import/Export}, 2006. \newblock URL \url{http://cran.r-project.org/manuals.html}. \newblock ISBN 3-900051-10-0. \bibitem[Warnes (2006)]{WarnesGdata} G.~R. Warnes. \newblock \emph{gdata: Various R programming tools for data manipulation}, 2006. \newblock URL \url{http://cran.r-project.org/src/contrib/Descriptions/gdata.html}. \newblock R package version 2.3.1. Includes R source code and/or documentation contributed by Ben Bolker, Gregor Gorjanc and Thomas Lumley. \end{thebibliography} \address{Gregor Gorjanc\\ University of Ljubljana, Slovenia\\ \email{gregor.gorjanc@bfro.uni-lj.si}} \end{article} \end{document} gdata/vignettes/mapLevels.Rnw0000644000176000001440000002014711015551251016012 0ustar ripleyusers %\VignetteIndexEntry{Mapping levels of a factor} %\VignettePackage{gdata} %\VignetteKeywords{levels, factor, manip} \documentclass[a4paper]{report} \usepackage{Rnews} \usepackage[round]{natbib} \bibliographystyle{abbrvnat} \usepackage{Sweave} \SweaveOpts{strip.white=all, keep.source=TRUE} \begin{document} \begin{article} \title{Mapping levels of a factor} \subtitle{The \pkg{gdata} package} \author{by Gregor Gorjanc} \maketitle \section{Introduction} Factors use levels attribute to store information on mapping between internal integer codes and character values i.e. levels. First level is mapped to internal integer code 1 and so on. Although some users do not like factors, their use is more efficient in terms of storage than for character vectors. Additionally, there are many functions in base \R{} that provide additional value for factors. Sometimes users need to work with internal integer codes and mapping them back to factor, especially when interfacing external programs. Mapping information is also of interest if there are many factors that should have the same set of levels. This note describes \code{mapLevels} function, which is an utility function for mapping the levels of a factor in \pkg{gdata} \footnote{from version 2.3.1} package \citep{WarnesGdata}. \section{Description with examples} Function \code{mapLevels()} is an (S3) generic function and works on \code{factor} and \code{character} atomic classes. It also works on \code{list} and \code{data.frame} objects with previously mentioned atomic classes. Function \code{mapLevels} produces a so called ``map'' with names and values. Names are levels, while values can be internal integer codes or (possibly other) levels. This will be clarified later on. Class of this ``map'' is \code{levelsMap}, if \code{x} in \code{mapLevels()} was atomic or \code{listLevelsMap} otherwise - for \code{list} and \code{data.frame} classes. The following example shows the creation and printout of such a ``map''. <>= library(gdata) (fac <- factor(c("B", "A", "Z", "D"))) (map <- mapLevels(x=fac)) @ If we have to work with internal integer codes, we can transform factor to integer and still get ``back the original factor'' with ``map'' used as argument in \code{mapLevels<-} function as shown bellow. \code{mapLevels<-} is also an (S3) generic function and works on same classes as \code{mapLevels} plus \code{integer} atomic class. <>= (int <- as.integer(fac)) mapLevels(x=int) <- map int identical(fac, int) @ Internally ``map'' (\code{levelsMap} class) is a \code{list} (see bellow), but its print method unlists it for ease of inspection. ``Map'' from example has all components of length 1. This is not mandatory as \code{mapLevels<-} function is only a wrapper around workhorse function \code{levels<-} and the later can accept \code{list} with components of various lengths. <>= str(map) @ Although not of primary importance, this ``map'' can also be used to remap factor levels as shown bellow. Components ``later'' in the map take over the ``previous'' ones. Since this is not optimal I would rather recommend other approaches for ``remapping'' the levels of a \code{factor}, say \code{recode} in \pkg{car} package \citep{FoxCar}. <>= map[[2]] <- as.integer(c(1, 2)) map int <- as.integer(fac) mapLevels(x=int) <- map int @ Up to now examples showed ``map'' with internal integer codes for values and levels for names. I call this integer ``map''. On the other hand character ``map'' uses levels for values and (possibly other) levels for names. This feature is a bit odd at first sight, but can be used to easily unify levels and internal integer codes across several factors. Imagine you have a factor that is for some reason split into two factors \code{f1} and \code{f2} and that each factor does not have all levels. This is not uncommon situation. <>= (f1 <- factor(c("A", "D", "C"))) (f2 <- factor(c("B", "D", "C"))) @ If we work with this factors, we need to be careful as they do not have the same set of levels. This can be solved with appropriately specifying \code{levels} argument in creation of factors i.e. \code{levels=c("A", "B", "C", "D")} or with proper use of \code{levels<-} function. I say proper as it is very tempting to use: <>= fTest <- f1 levels(fTest) <- c("A", "B", "C", "D") fTest @ Above example extends set of levels, but also changes level of 2nd and 3rd element in \code{fTest}! Proper use of \code{levels<-} (as shown in \code{levels} help page) would be: <>= fTest <- f1 levels(fTest) <- list(A="A", B="B", C="C", D="D") fTest @ Function \code{mapLevels} with character ``map'' can help us in such scenarios to unify levels and internal integer codes across several factors. Again the workhorse under this process is \code{levels<-} function from base \R{}! Function \code{mapLevels<-} just controls the assignment of (integer or character) ``map'' to \code{x}. Levels in \code{x} that match ``map'' values (internal integer codes or levels) are changed to ``map'' names (possibly other levels) as shown in \code{levels} help page. Levels that do not match are converted to \code{NA}. Integer ``map'' can be applied to \code{integer} or \code{factor}, while character ``map'' can be applied to \code{character} or \code{factor}. Result of \code{mapLevels<-} is always a \code{factor} with possibly ``remapped'' levels. To get one joint character ``map'' for several factors, we need to put factors in a \code{list} or \code{data.frame} and use arguments \code{codes=FALSE} and \code{combine=TRUE}. Such map can then be used to unify levels and internal integer codes. <>= (bigMap <- mapLevels(x=list(f1, f2), codes=FALSE, combine=TRUE)) mapLevels(f1) <- bigMap mapLevels(f2) <- bigMap f1 f2 cbind(as.character(f1), as.integer(f1), as.character(f2), as.integer(f2)) @ If we do not specify \code{combine=TRUE} (which is the default behaviour) and \code{x} is a \code{list} or \code{data.frame}, \code{mapLevels} returns ``map'' of class \code{listLevelsMap}. This is internally a \code{list} of ``maps'' (\code{levelsMap} objects). Both \code{listLevelsMap} and \code{levelsMap} objects can be passed to \code{mapLevels<-} for \code{list}/\code{data.frame}. Recycling occurs when length of \code{listLevelsMap} is not the same as number of components/columns of a \code{list}/\code{data.frame}. Additional convenience methods are also implemented to ease the work with ``maps'': \begin{itemize} \item \code{is.levelsMap}, \code{is.listLevelsMap}, \code{as.levelsMap} and \code{as.listLevelsMap} for testing and coercion of user defined ``maps'', \item \code{"["} for subsetting, \item \code{c} for combining \code{levelsMap} or \code{listLevelsMap} objects; argument \code{recursive=TRUE} can be used to coerce \code{listLevelsMap} to \code{levelsMap}, for example \code{c(llm1, llm2, recursive=TRUE)} and \item \code{unique} and \code{sort} for \code{levelsMap}. \end{itemize} \section{Summary} Functions \code{mapLevels} and \code{mapLevels<-} can help users to map internal integer codes to factor levels and unify levels as well as internal integer codes among several factors. I welcome any comments or suggestions. % \bibliography{refs} \begin{thebibliography}{1} \providecommand{\natexlab}[1]{#1} \providecommand{\url}[1]{\texttt{#1}} \expandafter\ifx\csname urlstyle\endcsname\relax \providecommand{\doi}[1]{doi: #1}\else \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi \bibitem[Fox(2006)]{FoxCar} J.~Fox. \newblock \emph{car: Companion to Applied Regression}, 2006. \newblock URL \url{http://socserv.socsci.mcmaster.ca/jfox/}. \newblock R package version 1.1-1. \bibitem[Warnes(2006)]{WarnesGdata} G.~R. Warnes. \newblock \emph{gdata: Various R programming tools for data manipulation}, 2006. \newblock URL \url{http://cran.r-project.org/src/contrib/Descriptions/gdata.html}. \newblock R package version 2.3.1. Includes R source code and/or documentation contributed by Ben Bolker, Gregor Gorjanc and Thomas Lumley. \end{thebibliography} \address{Gregor Gorjanc\\ University of Ljubljana, Slovenia\\ \email{gregor.gorjanc@bfro.uni-lj.si}} \end{article} \end{document} gdata/vignettes/Rnews.sty0000644000176000001440000001556412164366352015254 0ustar ripleyusers%% %% This is file `Rnews.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% Rnews.dtx (with options: `package') %% %% IMPORTANT NOTICE: %% %% For the copyright see the source file. %% %% Any modified versions of this file must be renamed %% with new filenames distinct from Rnews.sty. %% %% For distribution of the original source see the terms %% for copying and modification in the file Rnews.dtx. %% %% This generated file may be distributed as long as the %% original source files, as listed above, are part of the %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) \def\fileversion{v0.3.6} \def\filename{Rnews} \def\filedate{2002/06/02} \def\docdate {2001/10/31} %% %% Package `Rnews' to use with LaTeX2e %% Copyright (C) 2001--2002 by the R Core Development Team %% Please report errors to KH or FL %% %% -*- LaTeX -*- \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{\filename}[\filedate\space\fileversion\space Rnews package] \typeout{Package: `\filename\space\fileversion \@spaces <\filedate>'} \typeout{English documentation as of <\docdate>} \RequirePackage{ifthen} \newboolean{Rnews@driver} \DeclareOption{driver}{\setboolean{Rnews@driver}{true}} \DeclareOption*{\PackageWarning{\filename}{Unknown option `\CurrentOption'}} \ProcessOptions\relax \ifthenelse{\boolean{Rnews@driver}}{}{ \RequirePackage{multicol,graphicx,color,fancyhdr,hyperref} \newcommand{\volume}[1]{\def\Rnews@volume{#1}} \newcommand{\volnumber}[1]{\def\Rnews@number{#1}} \renewcommand{\date}[1]{\def\Rnews@date{#1}} \setcounter{secnumdepth}{-1} \renewcommand{\author}[1]{\def\Rnews@author{#1}} \renewcommand{\title}[1]{\def\Rnews@title{#1}} \newcommand{\subtitle}[1]{\def\Rnews@subtitle{#1}} \newenvironment{article}{% \author{}\title{}\subtitle{}}{\end{multicols}} \renewcommand{\maketitle}{ \begin{multicols}{2}[\chapter{\Rnews@title}\refstepcounter{chapter}][3cm] \ifx\empty\Rnews@subtitle\else\noindent\textbf{\Rnews@subtitle} \par\nobreak\addvspace{\baselineskip}\fi \ifx\empty\Rnews@author\else\noindent\textit{\Rnews@author} \par\nobreak\addvspace{\baselineskip}\fi \@afterindentfalse\@nobreaktrue\@afterheading} \renewcommand\chapter{\secdef\Rnews@chapter\@schapter} \providecommand{\nohyphens}{% \hyphenpenalty=10000\exhyphenpenalty=10000\relax} \newcommand{\Rnews@chapter}{% \renewcommand{\@seccntformat}[1]{}% \@startsection{chapter}{0}{0mm}{% -2\baselineskip \@plus -\baselineskip \@minus -.2ex}{\p@}{% \normalfont\Huge\bfseries\raggedright}} \renewcommand*\l@chapter{\@dottedtocline{0}{0pt}{1em}} \def\@schapter#1{\section*#1} \renewenvironment{figure}[1][]{% \def\@captype{figure} \noindent \begin{minipage}{\columnwidth}}{% \end{minipage}\par\addvspace{\baselineskip}} \renewcommand{\theequation}{\@arabic\c@equation} \def\equation{% \let\refstepcounter\H@refstepcounter \H@equation \def\newname{\arabic{chapter}.\theequation}% \let\theHequation\newname% \hyper@makecurrent{equation}% \Hy@raisedlink{\hyper@anchorstart{\@currentHref}}% \let\refstepcounter\new@refstepcounter}% \def\endequation{\Hy@raisedlink{\hyper@anchorend}\H@endequation} \renewcommand{\thefigure}{\@arabic\c@figure} \renewcommand{\thetable}{\@arabic\c@table} \renewcommand{\contentsname}{Contents of this issue:} \renewcommand\tableofcontents{% \section*{\contentsname \@mkboth{% \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% \@starttoc{toc}} \renewcommand{\titlepage}{% \noindent \rule{\textwidth}{1pt}\\[-.8\baselineskip] \rule{\textwidth}{.5pt} \begin{center} \includegraphics[height=2cm]{Rlogo}\hspace{7mm} \fontsize{2cm}{2cm}\selectfont News \end{center} The Newsletter of the R Project\hfill Volume \Rnews@volume/\Rnews@number, \Rnews@date\\[-.5\baselineskip] \rule{\textwidth}{.5pt}\\[-.8\baselineskip] \rule{\textwidth}{1pt} \vspace{1cm} \fancyhf{} \fancyhead[L]{Vol.~\Rnews@volume/\Rnews@number, \Rnews@date} \fancyhead[R]{\thepage} \fancyfoot[L]{R News} \fancyfoot[R]{ISSN 1609-3631} \thispagestyle{empty} \begin{bottombox} \begin{multicols}{2} \setcounter{tocdepth}{0} \tableofcontents \setcounter{tocdepth}{2} \end{multicols} \end{bottombox}} \setlength{\textheight}{250mm} \setlength{\topmargin}{-10mm} \setlength{\textwidth}{17cm} \setlength{\oddsidemargin}{-6mm} \setlength{\columnseprule}{.1pt} \setlength{\columnsep}{20pt} \RequirePackage{ae,mathpple} \RequirePackage[T1]{fontenc} \renewcommand{\rmdefault}{ppl} \renewcommand{\sfdefault}{aess} \renewcommand{\ttdefault}{aett} \definecolor{Red}{rgb}{0.7,0,0} \definecolor{Blue}{rgb}{0,0,0.8} \definecolor{hellgrau}{rgb}{0.55,0.55,0.55} \newcommand{\R}{R} \newcommand{\address}[1]{\addvspace{\baselineskip}\noindent\emph{#1}} \newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} \newsavebox{\Rnews@box} \newlength{\Rnews@len} \newenvironment{bottombox}{% \begin{figure*}[b] \begin{center} \noindent \begin{lrbox}{\Rnews@box} \begin{minipage}{0.99\textwidth}}{% \end{minipage} \end{lrbox} \addtolength{\Rnews@len}{\fboxsep} \addtolength{\Rnews@len}{\fboxrule} \hspace*{-\Rnews@len}\fbox{\usebox{\Rnews@box}} \end{center} \end{figure*}} \RequirePackage{verbatim} \def\boxedverbatim{% \def\verbatim@processline{% {\setbox0=\hbox{\the\verbatim@line}% \hsize=\wd0 \the\verbatim@line\par}}% \@minipagetrue \@tempswatrue \setbox0=\vbox \bgroup\small\verbatim } \def\endboxedverbatim{% \endverbatim \unskip\setbox0=\lastbox \egroup \fbox{\box0} } \pagestyle{fancy} } % \ifthenelse{\boolean{Rnews@driver}} \newcommand\code{\bgroup\@codex} \def\@codex#1{{\normalfont\ttfamily\hyphenchar\font=-1 #1}\egroup} \newcommand{\kbd}[1]{{\normalfont\texttt{#1}}} \newcommand{\key}[1]{{\normalfont\texttt{\uppercase{#1}}}} \newcommand\samp{`\bgroup\@noligs\@sampx} \def\@sampx#1{{\normalfont\texttt{#1}}\egroup'} \newcommand{\var}[1]{{\normalfont\textsl{#1}}} \let\env=\code \newcommand{\file}[1]{{`\normalfont\textsf{#1}'}} \let\command=\code \let\option=\samp \newcommand{\dfn}[1]{{\normalfont\textsl{#1}}} \newcommand{\acronym}[1]{{\normalfont\textsc{\lowercase{#1}}}} \newcommand{\strong}[1]{{\normalfont\fontseries{b}\selectfont #1}} \let\pkg=\strong \RequirePackage{alltt} \newenvironment{example}{\begin{alltt}}{\end{alltt}} \newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} \newenvironment{display}{\list{}{}\item\relax}{\endlist} \newenvironment{smallverbatim}{\small\verbatim}{\endverbatim} \providecommand{\operatorname}[1]{% \mathop{\operator@font#1}\nolimits} \renewcommand{\P}{% \mathop{\operator@font I\hspace{-1.5pt}P\hspace{.13pt}}} \newcommand{\E}{% \mathop{\operator@font I\hspace{-1.5pt}E\hspace{.13pt}}} \newcommand{\VAR}{\operatorname{var}} \newcommand{\COV}{\operatorname{cov}} \newcommand{\COR}{\operatorname{cor}} \RequirePackage{amsfonts} \endinput %% %% End of file `Rnews.sty'. gdata/vignettes/Rnews.dtx0000644000176000001440000004601512164366352015227 0ustar ripleyusers\def\fileversion{v0.3.1} \def\filename{Rnews} \def\filedate{2001/09/04} \def\docdate {2001/09/04} % % \iffalse % %% %% Package `Rnews' to use with LaTeX2e %% Copyright (C) 2001 by the R Core Development Team %% Please report errors to KH or FL %% %% -*- LaTeX -*- % % \fi % % \iffalse % \changes{v0.1}{2001/01/05}{First draft.} % \changes{v0.2}{2001/07/01} % {Added macros \cmd\P, \cmd\E, \cmd\VAR, \cmd\COV, \cmd\COR, and % \cmd\operatorname. Require \pkg{amsfonts} to produce symbols for % sets of positive integers etc.} % \changes{v0.3}{2001/08/02} % {Add package option `driver' for typesetting the driver. % Change article environment to use chapters. % Ensure unique figure labels.} % \changes{v0.3.1}{2001/09/04} % {Remove redefinition of |\caption|, which had figures hard-wired. % Instead, have our |figure| environment set |\@captype|.} % \fi % % \MakeShortVerb{\|} % % \newcommand{\AmS}{$${\protect\the\textfont2 A}\kern-.1667em\lower % .5ex\hbox{\protect\the\textfont2 M}\kern % -.125em{\protect\the\textfont2 S}} % \newcommand{\AmSLaTeX}{\mbox{\AmS-\LaTeX}} % % \title{The package \pkg{\filename}} % \author{Kurt Hornik \and Friedrich Leisch} % % \maketitle % % \section{Introduction} % % The \LaTeXe{} package \pkg{\filename} provides commands for formatting % the R Newsletter. % % \section{Documentation} % % \subsection{Marking Words and Phrases} % % The \pkg{Rnews} package provides roughly the same commands for marking % words and phrases as does Texinfo (but note that the \LaTeX special % characters still need special treatment). These commands are % \begin{description} % \item[\code{\cmd{\code}\{\var{sample-code}\}}] % Indicate text that is a literal example of a piece of a program. % \item[\code{\cmd{\kbd}\{\var{keyboard-characters}\}}] % Indicate keyboard input. % \item[\code{\cmd{\key}\{\var{key-name}\}}] % Indicate the conventional name for a key on a keyboard. % \item[\code{\cmd{\samp}\{\var{text}\}}] % Indicate text that is a literal example of a sequence of % characters. % \item[\code{\cmd{\var}\{\var{metasyntactic-variable}\}}] % Indicate a metasyntactic variable. % \item[\code{\cmd{\env}\{\var{environment-variable}\}}] % Indicate an environment variable. % \item[\code{\cmd{\file}\{\var{file-name}\}}] % Indicate the name of a file. % \item[\code{\cmd{\command}\{\var{command-name}\}}] % Indicate a command name (such as \samp{ls}). % \item[\code{\cmd{\option}\{\var{option-name}\}}] % Indicate a command line option. % \item[\code{\cmd{\dfn}\{\var{term}\}}] % Indicate the introductory or defining use of a term. % \item[\code{\cmd{\acronym}\{\var{acronym}\}}] % Use for abbreviattions written in all capital letters, such as % \samp{NASA}. % \end{description} % If this sounds rather confusing, please see the Texinfo documentation % for more details. % % \DescribeMacro{\strong} % There is also a |\strong| command for emphasizing text more strongly % than with |\emph|. For example, |\strong{Note:}| gives \strong{Note:}. % % \DescribeMacro{\pkg} % Finally, use |\pkg| for indicating R packages. % % \subsection{Quotations and Examples} % % In addition to the standard \LaTeX{} for quotations and examples (such % as |quote|, |quotation|, |flushleft|, |center| and |flushright|), the % \pkg{\filename} package provides the following environments. % \begin{description} % \item[\code{example}] % Illustrate code, commands, and the like. The text is printed in a % fixed-width font, and indented but not filled. % \item[\code{smallexample}] % Similar to \code{example}, except that text is typeset in a smaller % font. % \end{description} % % \subsection{Mathematics} % % \DescribeMacro{\P} % \DescribeMacro{\E} % \DescribeMacro{\VAR} % \DescribeMacro{\COV} % \DescribeMacro{\COR} % The commands |\P|, |\E|, |\VAR|, |\COV|, and |\COR| produce symbols % for probability, expectation, variance, covariance and correlation. % For example, Chebyshev's inequality % \DeleteShortVerb{\|} % \begin{displaymath} % \P(|\xi-\E\xi|>\lambda) \le \frac{\VAR(\xi)}{\lambda^2}. % \end{displaymath} % can be coded as % \MakeShortVerb{\|} % \begin{quote} % \verb+\P(|\xi-\E\xi|>\lambda) \le \frac{\VAR(\xi)}{\lambda^2}+. % \end{quote} % % \DescribeMacro{\mathbb} % The symbols % \begin{displaymath} % \mathbb{N}\quad\mathbb{Z}\quad\mathbb{Q}\quad\mathbb{R}\quad\mathbb{C} % \end{displaymath} % for the positive integers, the integers, and the rational, real and % complex numbers, respectively, can be obtained using |\mathbb| from % package \pkg{amsfonts} as % \begin{quote} % |\mathbb{N}| |\mathbb{Z}| |\mathbb{Q}| |\mathbb{R}| |\mathbb{C}| % \end{quote} % % \section{The Code} % % \subsection{The Batch File} % % First comes the code for creating the batch file \file{\filename.ins} % which in turn can be used for producing the package and driver files. % % \begin{macrocode} %<*install> \begin{filecontents}{\filename.ins} % Simply TeX or LaTeX this file to extract various files from the source % file `Rnews.dtx'. \def\filedate{2001/01/05} \def\batchfile{Rnews.ins} \input docstrip.tex \preamble \endpreamble \generateFile{Rnews.drv}{t}{\from{Rnews.dtx}{driver}} \generateFile{Rnews.sty}{t}{\from{Rnews.dtx}{package}} \Msg{***********************************************************} \Msg{* For documentation, run LaTeX on Rnews.dtx or Rnews.drv. *} \Msg{***********************************************************} \end{filecontents} % % \end{macrocode} % % \subsection{The Driver} % % Next comes the documentation driver file for \TeX{}, i.e., the file % that will produce the documentation you are currently reading. It % will be extracted from this file by the \texttt{docstrip} program. % Since it is the first code in the file one can alternatively process % this file directly with \LaTeXe{} to obtain the documentation. % % \begin{macrocode} %<*driver> \documentclass[fleqn]{ltxdoc} \usepackage[driver]{\filename} \renewcommand{\pkg}[1]{\textsf{#1}} \begin{document} \DocInput{\filename.dtx} \end{document} % % \end{macrocode} % % \subsection{The Code} % % Now comes the code for the package. % % It the current format is not \LaTeXe{}, we abort immediately. % Otherwise, we provide ourselves and show the current version of the % package on the screen and in the transscript file. % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{\filename}[\filedate\space\fileversion\space Rnews package] \typeout{Package: `\filename\space\fileversion \@spaces <\filedate>'} \typeout{English documentation as of <\docdate>} % \end{macrocode} % % Next, we set up a more or less trivial option handler. We use option % `driver' for conditionalizing package code we do not want executed % when typesetting the driver file. % \begin{macrocode} \RequirePackage{ifthen} \newboolean{Rnews@driver} \DeclareOption{driver}{\setboolean{Rnews@driver}{true}} \DeclareOption*{\PackageWarning{\filename}{Unknown option `\CurrentOption'}} \ProcessOptions\relax % \end{macrocode} % % Now comes the real code. % % \begin{macrocode} \ifthenelse{\boolean{Rnews@driver}}{}{ % \end{macrocode} % % First we load some utility packages. % \begin{macrocode} \RequirePackage{multicol,graphicx,color,fancyhdr,hyperref} % \end{macrocode} % % \subsubsection{Basic Structure} % % Issues of of \emph{R News} are created from the standard \LaTeX{} % document class \pkg{report}. Individual articles correspond to % chapters, and are contained in |article| environments. This makes it % easy to have figures counted within articles and hence hyperlinked % correctly. % % Basic front matter information about the issue: volume, number, and % date. % \begin{macrocode} \newcommand{\volume}[1]{\def\Rnews@volume{#1}} \newcommand{\volnumber}[1]{\def\Rnews@number{#1}} \renewcommand{\date}[1]{\def\Rnews@date{#1}} % \end{macrocode} % % We do not want numbered sections. % \begin{macrocode} \setcounter{secnumdepth}{-1} % \end{macrocode} % % \begin{macro}{\author} % \begin{macro}{\title} % \begin{macro}{\subtitle} % An article has an author, a title, and optionally a subtitle. We use % the obvious commands for specifying these. % \begin{macrocode} \renewcommand{\author}[1]{\def\Rnews@author{#1}} \renewcommand{\title}[1]{\def\Rnews@title{#1}} \newcommand{\subtitle}[1]{\def\Rnews@subtitle{#1}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{environment}{article} % Environment |article| clears the article header information its begin % and restores single column mode at its end. % \begin{macrocode} \newenvironment{article}{% \author{}\title{}\subtitle{}}{\end{multicols}} % \end{macrocode} % \end{environment} % % \begin{macro}{\maketitle} % The real work is done by a redefined version of |\maketitle|, which % also switches to double column mode. Note that even though we do not % want chapters (articles) numbered, we need to increment the chapter % counter, so that figures get correct labelling. % \begin{macrocode} \renewcommand{\maketitle}{ \chapter{\Rnews@title} \refstepcounter{chapter} \begin{multicols}{2} \ifx\empty\Rnews@subtitle\else\par\addvspace{\baselineskip} \noindent\textbf{\Rnews@subtitle}\fi \ifx\empty\Rnews@author\else\par\addvspace{\baselineskip} \noindent\textit{\Rnews@author}\fi} % \end{macrocode} % \end{macro} % % Now for some ugly redefinitions. We do not want articles to start a % new page. % \begin{macrocode} \renewcommand\chapter{\secdef\@chapter\@schapter} % \end{macrocode} % TOC entries for articles (chapters) should really look like sections. % \begin{macrocode} \renewcommand*\l@chapter{\@dottedtocline{0}{0pt}{1em}} % \end{macrocode} % We need to adjust vertical spacing in |\@makechapterhead|: extra space % before the title only if not at the beginning, no extra space after % it. % \begin{macrocode} \def\@makechapterhead#1{% \addvspace{2\baselineskip}% {\parindent \z@ \raggedright \normalfont \ifnum \c@secnumdepth >\m@ne \huge\bfseries \@chapapp\space \thechapter \par\nobreak \vskip 20\p@ \fi \interlinepenalty\@M \Huge \bfseries #1\par\nobreak}} % \end{macrocode} % We want bibliographies as starred sections within articles. As the % standard |thebibliography| environment uses |chapter*|, we simply % redefine the latter according to our needs. % \begin{macrocode} \def\@schapter#1{\section*#1} % \end{macrocode} % % Package \pkg{multicol}, which is used for producing two-column output, % only allows for starred (single-column) floats (figures and tables). % Therefore, we provide a simple non-floating |figure| environment % ourselves. % \begin{macrocode} \renewenvironment{figure}[1][]{% \def\@captype{figure} \begin{minipage}{0.9\columnwidth}}{ \end{minipage}\par\addvspace{\baselineskip}} % \end{macrocode} % Equations, figures and tables are counted within articles, but we do % not show the article number. % \begin{macrocode} \renewcommand{\theequation}{\@arabic\c@equation} \renewcommand{\thefigure}{\@arabic\c@figure} \renewcommand{\thetable}{\@arabic\c@table} % \end{macrocode} % % \begin{macro}{\tableofcontents} % Need to provide our own version of |\tableofcontents| (no fiddling % with the number of columns). Note that |\section*| is really the same % as |\chapter*|). % \begin{macrocode} \renewcommand{\contentsname}{Contents of this issue:} \renewcommand\tableofcontents{% \section*{\contentsname \@mkboth{% \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% \@starttoc{toc}} % \end{macrocode} % \end{macro} % \begin{macro}{\titlepage} % The title page of each issue features logo et al at the top and the % TOC. We start with the top. % \begin{macrocode} \renewcommand{\titlepage}{% \noindent \rule{\textwidth}{1pt}\\[-.8\baselineskip] \rule{\textwidth}{.5pt} \begin{center} \includegraphics[height=2cm]{Rlogo}\hspace{7mm} \fontsize{2cm}{2cm}\selectfont News \end{center} The Newsletter of the R Project\hfill Volume \Rnews@volume/\Rnews@number, \Rnews@date\\[-.5\baselineskip] \rule{\textwidth}{.5pt}\\[-.8\baselineskip] \rule{\textwidth}{1pt} \vspace{1cm} % \end{macrocode} % Now set up the header and footer information for the rest of the % document. % \begin{macrocode} \fancyhf{} \fancyhead[L]{Vol.~\Rnews@volume/\Rnews@number, \Rnews@date} \fancyhead[R]{\thepage} \fancyfoot[L]{R News} \fancyfoot[R]{ISSN 1609-3631} \thispagestyle{empty} % \end{macrocode} % And finally, put the TOC at the bottom in a framed box. Note the way % |tocdepth| is adjusted before and after producing the TOC: thus, we % can ensure that only articles show up in the printed TOC, but that in % the PDF version, bookmarks are created for sections and subsections as % well (provided that the non-starred forms are used). % \begin{macrocode} \begin{bottombox} \begin{multicols}{2} \setcounter{tocdepth}{0} \tableofcontents \setcounter{tocdepth}{2} \end{multicols} \end{bottombox}} % \end{macrocode} % \end{macro} % % \subsubsection{Layout, Fonts and Color} % % \paragraph{Layout.} % We set the basic layout parameters in a way that printouts should be % fine for both A4 and Letter paper. % \begin{macrocode} \setlength{\textheight}{250mm} \setlength{\topmargin}{-10mm} \setlength{\textwidth}{17cm} \setlength{\oddsidemargin}{-6mm} \setlength{\columnseprule}{.1pt} \setlength{\columnsep}{20pt} % \end{macrocode} % % \paragraph{Fonts.} % We use the following fonts (all with T1 encoding): % \begin{center} % \begin{tabular}{lp{0.8\textwidth}} % rm & palatino \\ % tt & almost european (computer modern working with T1) \\ % & Reason for aett: uses less horizontal space than courier, % which is better for example code \\ % sf & almost european \\ % math & palatino % \end{tabular} % \end{center} % % \begin{macrocode} \RequirePackage{ae,mathpple} \RequirePackage[T1]{fontenc} \renewcommand{\rmdefault}{ppl} \renewcommand{\sfdefault}{aess} \renewcommand{\ttdefault}{aett} % \end{macrocode} % % \paragraph{Colors.} These are actually used for |\hypersetup| but we % do not call this here, although we should. % \marginpar{FIXME} % \begin{macrocode} \definecolor{Red}{rgb}{0.7,0,0} \definecolor{Blue}{rgb}{0,0,0.8} \definecolor{hellgrau}{rgb}{0.55,0.55,0.55} % \end{macrocode} % % \subsubsection{Miscellania} % % \begin{macrocode} \newcommand{\R}{R} \newcommand{\address}[1]{\addvspace{\baselineskip}\noindent\emph{#1}} \newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} % \end{macrocode} % % \begin{environment}{bottombox} % Used for creating the TOC and the back matter editorial information. % \begin{macrocode} \newsavebox{\Rnews@box} \newlength{\Rnews@len} \newenvironment{bottombox}{% \begin{figure*}[b] \begin{center} \noindent \begin{lrbox}{\Rnews@box} \begin{minipage}{0.99\textwidth}}{% \end{minipage} \end{lrbox} \addtolength{\Rnews@len}{\fboxsep} \addtolength{\Rnews@len}{\fboxrule} \hspace*{-\Rnews@len}\fbox{\usebox{\Rnews@box}} \end{center} \end{figure*}} % \end{macrocode} % \end{environment} % % \begin{environment}{boxedverbatim} % This does not seem to be used any more. % \marginpar{FIXME} % \begin{macrocode} \newenvironment{boxedverbatim}{% \begin{lrbox}{\Rnews@box} \begin{smallverbatim}}{% \end{smallverbatim} \end{lrbox} \hspace*{-\fboxsep}\fbox{\usebox{\Rnews@box}}} % \end{macrocode} % \end{environment} % % Finally, we turn on fancy page style. % \begin{macrocode} \pagestyle{fancy} } % \ifthenelse{\boolean{Rnews@driver}} % \end{macrocode} % % \subsubsection{Marking Words and Phrases} % % Simple font selection is not good enough. For example, |\texttt{--}| % gives `\texttt{--}', i.e., an endash in typewriter font. Hence, we % need to turn off ligatures, which currently only happens for commands % |\code| and |\samp| and the ones derived from them. Hyphenation is % another issue; it should really be turned off inside |\samp|. And % most importantly, \LaTeX{} special characters are a nightmare. E.g., % one needs |\~{}| to produce a tilde in a file name marked by |\file|. % Perhaps a few years ago, most users would have agreed that this may be % unfortunate but should not be changed to ensure consistency. But with % the advent of the WWW and the need for getting `|~|' and `|#|' into % URLs, commands which only treat the escape and grouping characters % specially have gained acceptance (in fact, this is also what % \pkg{alltt} does, and hence environments based on it such as our % |smallexample|). Hence, in the long run we should implement the same % for |\code|, |\kbd|, |\samp|, |\var|, and |\file|. (The other % Texinfo-style commands do not need this.) % % \begin{macrocode} %\newcommand\code{\bgroup\@noligs\@codex} \newcommand\code{\bgroup\@codex} \def\@codex#1{{\normalfont\ttfamily\hyphenchar\font=-1 #1}\egroup} \newcommand{\kbd}[1]{{\normalfont\texttt{#1}}} \newcommand{\key}[1]{{\normalfont\texttt{\uppercase{#1}}}} \newcommand\samp{`\bgroup\@noligs\@sampx} \def\@sampx#1{{\normalfont\texttt{#1}}\egroup'} \newcommand{\var}[1]{{\normalfont\textsl{#1}}} \let\env=\code \newcommand{\file}[1]{{`\normalfont\textsf{#1}'}} \let\command=\code \let\option=\samp \newcommand{\dfn}[1]{{\normalfont\textsl{#1}}} \newcommand{\acronym}[1]{{\normalfont\textsc{\lowercase{#1}}}} \newcommand{\strong}[1]{{\normalfont\fontseries{b}\selectfont #1}} \let\pkg=\strong % \end{macrocode} % % \subsubsection{Quotations and Examples} % % \begin{macrocode} \RequirePackage{alltt} \newenvironment{example}{\begin{alltt}}{\end{alltt}} \newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} \newenvironment{display}{\list{}{}\item\relax}{\endlist} % \end{macrocode} % % \subsubsection{Mathematics} % % \begin{macro}{\operatorname} % The implementation of |\operatorname| is similar to the mechanism % \LaTeXe{} uses for functions like sin and cos, and simpler than the % one of \AmSLaTeX{}. We use |\providecommand| for the definition in % order to keep the one of the \pkg{amstex} if this package has % already been loaded. % \begin{macrocode} \providecommand{\operatorname}[1]{% \mathop{\operator@font#1}\nolimits} % \end{macrocode} % \end{macro} % % \begin{macro}{\P} % \begin{macro}{\E} % \begin{macro}{\VAR} % \begin{macro}{\COV} % \begin{macro}{\COR} % Next, we provide commands for probability, expectation, variance, % covariance and correlation which are obviously useful in probability % theory and statistics. % (Of course, originally |\P| gives \mathhexbox27B.) % \begin{macrocode} \renewcommand{\P}{% \mathop{\operator@font I\hspace{-1.5pt}P\hspace{.13pt}}} \newcommand{\E}{% \mathop{\operator@font I\hspace{-1.5pt}E\hspace{.13pt}}} \newcommand{\VAR}{\operatorname{var}} \newcommand{\COV}{\operatorname{cov}} \newcommand{\COR}{\operatorname{cor}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % Finally, we load package \pkg{amsfonts} so that |\mathbb| is available % for producing the symbols for positive integers etc. % \begin{macrocode} \RequirePackage{amsfonts} % \end{macrocode} % % This ends the implementation of the \pkg{\filename} package. % \begin{macrocode} % % \end{macrocode} gdata/tests/0000755000176000001440000000000012163377345012537 5ustar ripleyusersgdata/tests/tests.write.fwf.Rout.save0000644000176000001440000002706412163375370017430 0ustar ripleyusers R version 3.0.1 (2013-05-16) -- "Good Sport" Copyright (C) 2013 The R Foundation for Statistical Computing Platform: i686-pc-linux-gnu (32-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > ### tests.write.fwf.R > ###------------------------------------------------------------------------ > ### What: Tests for write.fwf > ### $Id: tests.write.fwf.R 1300 2008-08-05 11:47:18Z ggorjan $ > ### Time-stamp: <2008-08-05 12:25:05 ggorjan> > ###------------------------------------------------------------------------ > > library(gdata) gdata: read.xls support for 'XLS' (Excel 97-2004) files ENABLED. gdata: read.xls support for 'XLSX' (Excel 2007+) files ENABLED. Attaching package: 'gdata' The following object is masked from 'package:stats': nobs The following object is masked from 'package:utils': object.size > > ## --- Test data --- > > num <- round(c(733070.345678, 1214213.78765456, 553823.798765678, + 1085022.8876545678, 571063.88765456, 606718.3876545678, + 1053686.6, 971024.187656, 631193.398765456, 879431.1), + digits=3) > > testData <- data.frame(num1=c(1:10, NA), + num2=c(NA, seq(from=1, to=5.5, by=0.5)), + num3=c(NA, num), + int1=c(as.integer(1:4), NA, as.integer(4:9)), + fac1=factor(c(NA, letters[1:9], "hjh")), + fac2=factor(c(letters[6:15], NA)), + cha1=c(letters[17:26], NA), + cha2=c(NA, "longer", letters[25:17]), + stringsAsFactors=FALSE) > levels(testData$fac1) <- c(levels(testData$fac1), "unusedLevel") > testData$Date <- as.Date("1900-1-1") > testData$Date[2] <- NA > testData$POSIXt <- as.POSIXct(strptime("1900-1-1 01:01:01", format="%Y-%m-%d %H:%M:%S")) > testData$POSIXt[5] <- NA > > ## --- Tests --- > > ## Default > write.fwf(testData) num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 1 f q 1900-01-01 1900-01-01 01:01:01 2 1.0 733070.3 2 a g r longer 1900-01-01 01:01:01 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 2.5 1085022.9 d j u w 1900-01-01 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 5.5 879431.1 9 hjh q 1900-01-01 1900-01-01 01:01:01 > > ## NA should be - > write.fwf(x=testData, na="-") num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 - - 1 - f q - 1900-01-01 1900-01-01 01:01:01 2 1.0 733070.3 2 a g r longer - 1900-01-01 01:01:01 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 2.5 1085022.9 - d j u w 1900-01-01 - 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 - 5.5 879431.1 9 hjh - - q 1900-01-01 1900-01-01 01:01:01 > ## NA should be -NA- > write.fwf(x=testData, na="-NA-") num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 -NA- -NA- 1 -NA- f q -NA- 1900-01-01 1900-01-01 01:01:01 2 1.0 733070.3 2 a g r longer -NA- 1900-01-01 01:01:01 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 2.5 1085022.9 -NA- d j u w 1900-01-01 -NA- 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 -NA- 5.5 879431.1 9 hjh -NA- -NA- q 1900-01-01 1900-01-01 01:01:01 > > ## Some other separator than space > write.fwf(testData[, 1:4], sep="-mySep-") num1-mySep-num2-mySep-num3-mySep-int1 1-mySep- -mySep- -mySep-1 2-mySep-1.0-mySep- 733070.3-mySep-2 3-mySep-1.5-mySep-1214213.8-mySep-3 4-mySep-2.0-mySep- 553823.8-mySep-4 5-mySep-2.5-mySep-1085022.9-mySep- 6-mySep-3.0-mySep- 571063.9-mySep-4 7-mySep-3.5-mySep- 606718.4-mySep-5 8-mySep-4.0-mySep-1053686.6-mySep-6 9-mySep-4.5-mySep- 971024.2-mySep-7 10-mySep-5.0-mySep- 631193.4-mySep-8 -mySep-5.5-mySep- 879431.1-mySep-9 > > ## Justify right for character columns > write.fwf(testData, justify="right") num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 1 f q 1900-01-01 1900-01-01 01:01:01 2 1.0 733070.3 2 a g r longer 1900-01-01 01:01:01 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 2.5 1085022.9 d j u w 1900-01-01 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 5.5 879431.1 9 hjh q 1900-01-01 1900-01-01 01:01:01 > > ## Justify right for character columns, track na values > write.fwf(testData, justify="right", na="!") num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 ! ! 1 ! f q ! 1900-01-01 1900-01-01 01:01:01 2 1.0 733070.3 2 a g r longer ! 1900-01-01 01:01:01 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 2.5 1085022.9 ! d j u w 1900-01-01 ! 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 ! 5.5 879431.1 9 hjh ! ! q 1900-01-01 1900-01-01 01:01:01 > > ## With quotes > write.fwf(testData, quote=TRUE) "num1" "num2" "num3" "int1" "fac1" "fac2" "cha1" "cha2" "Date" "POSIXt" " 1" " " " " "1" " " "f" "q" " " "1900-01-01" "1900-01-01 01:01:01" " 2" "1.0" " 733070.3" "2" "a " "g" "r" "longer" " " "1900-01-01 01:01:01" " 3" "1.5" "1214213.8" "3" "b " "h" "s" "y " "1900-01-01" "1900-01-01 01:01:01" " 4" "2.0" " 553823.8" "4" "c " "i" "t" "x " "1900-01-01" "1900-01-01 01:01:01" " 5" "2.5" "1085022.9" " " "d " "j" "u" "w " "1900-01-01" " " " 6" "3.0" " 571063.9" "4" "e " "k" "v" "v " "1900-01-01" "1900-01-01 01:01:01" " 7" "3.5" " 606718.4" "5" "f " "l" "w" "u " "1900-01-01" "1900-01-01 01:01:01" " 8" "4.0" "1053686.6" "6" "g " "m" "x" "t " "1900-01-01" "1900-01-01 01:01:01" " 9" "4.5" " 971024.2" "7" "h " "n" "y" "s " "1900-01-01" "1900-01-01 01:01:01" "10" "5.0" " 631193.4" "8" "i " "o" "z" "r " "1900-01-01" "1900-01-01 01:01:01" " " "5.5" " 879431.1" "9" "hjh" " " " " "q " "1900-01-01" "1900-01-01 01:01:01" > > ## With rownames > write.fwf(testData, rownames=TRUE) num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 1 1 f q 1900-01-01 1900-01-01 01:01:01 2 2 1.0 733070.3 2 a g r longer 1900-01-01 01:01:01 3 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 5 2.5 1085022.9 d j u w 1900-01-01 6 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 11 5.5 879431.1 9 hjh q 1900-01-01 1900-01-01 01:01:01 > > ## Without colnames > write.fwf(testData, colnames=FALSE) 1 1 f q 1900-01-01 1900-01-01 01:01:01 2 1.0 733070.3 2 a g r longer 1900-01-01 01:01:01 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 2.5 1085022.9 d j u w 1900-01-01 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 5.5 879431.1 9 hjh q 1900-01-01 1900-01-01 01:01:01 > > ## Without colnames, with rownames > write.fwf(testData, colnames=FALSE, rownames=TRUE) 1 1 1 f q 1900-01-01 1900-01-01 01:01:01 2 2 1.0 733070.3 2 a g r longer 1900-01-01 01:01:01 3 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 5 2.5 1085022.9 d j u w 1900-01-01 6 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 11 5.5 879431.1 9 hjh q 1900-01-01 1900-01-01 01:01:01 > > ## With rownames and colnames and rowCol > write.fwf(testData, rownames=TRUE, rowCol="HI!") HI! num1 num2 num3 int1 fac1 fac2 cha1 cha2 Date POSIXt 1 1 1 f q 1900-01-01 1900-01-01 01:01:01 2 2 1.0 733070.3 2 a g r longer 1900-01-01 01:01:01 3 3 1.5 1214213.8 3 b h s y 1900-01-01 1900-01-01 01:01:01 4 4 2.0 553823.8 4 c i t x 1900-01-01 1900-01-01 01:01:01 5 5 2.5 1085022.9 d j u w 1900-01-01 6 6 3.0 571063.9 4 e k v v 1900-01-01 1900-01-01 01:01:01 7 7 3.5 606718.4 5 f l w u 1900-01-01 1900-01-01 01:01:01 8 8 4.0 1053686.6 6 g m x t 1900-01-01 1900-01-01 01:01:01 9 9 4.5 971024.2 7 h n y s 1900-01-01 1900-01-01 01:01:01 10 10 5.0 631193.4 8 i o z r 1900-01-01 1900-01-01 01:01:01 11 5.5 879431.1 9 hjh q 1900-01-01 1900-01-01 01:01:01 > > ## formatInfo is tested with unit tests > > ###------------------------------------------------------------------------ > ### tests.write.fwf.R ends > > proc.time() user system elapsed 1.464 0.152 1.631 gdata/tests/tests.write.fwf.R0000644000176000001440000000424111227511757015734 0ustar ripleyusers### tests.write.fwf.R ###------------------------------------------------------------------------ ### What: Tests for write.fwf ### $Id: tests.write.fwf.R 1300 2008-08-05 11:47:18Z ggorjan $ ### Time-stamp: <2008-08-05 12:25:05 ggorjan> ###------------------------------------------------------------------------ library(gdata) ## --- Test data --- num <- round(c(733070.345678, 1214213.78765456, 553823.798765678, 1085022.8876545678, 571063.88765456, 606718.3876545678, 1053686.6, 971024.187656, 631193.398765456, 879431.1), digits=3) testData <- data.frame(num1=c(1:10, NA), num2=c(NA, seq(from=1, to=5.5, by=0.5)), num3=c(NA, num), int1=c(as.integer(1:4), NA, as.integer(4:9)), fac1=factor(c(NA, letters[1:9], "hjh")), fac2=factor(c(letters[6:15], NA)), cha1=c(letters[17:26], NA), cha2=c(NA, "longer", letters[25:17]), stringsAsFactors=FALSE) levels(testData$fac1) <- c(levels(testData$fac1), "unusedLevel") testData$Date <- as.Date("1900-1-1") testData$Date[2] <- NA testData$POSIXt <- as.POSIXct(strptime("1900-1-1 01:01:01", format="%Y-%m-%d %H:%M:%S")) testData$POSIXt[5] <- NA ## --- Tests --- ## Default write.fwf(testData) ## NA should be - write.fwf(x=testData, na="-") ## NA should be -NA- write.fwf(x=testData, na="-NA-") ## Some other separator than space write.fwf(testData[, 1:4], sep="-mySep-") ## Justify right for character columns write.fwf(testData, justify="right") ## Justify right for character columns, track na values write.fwf(testData, justify="right", na="!") ## With quotes write.fwf(testData, quote=TRUE) ## With rownames write.fwf(testData, rownames=TRUE) ## Without colnames write.fwf(testData, colnames=FALSE) ## Without colnames, with rownames write.fwf(testData, colnames=FALSE, rownames=TRUE) ## With rownames and colnames and rowCol write.fwf(testData, rownames=TRUE, rowCol="HI!") ## formatInfo is tested with unit tests ###------------------------------------------------------------------------ ### tests.write.fwf.R ends gdata/tests/test.write.fwf.eol.R0000644000176000001440000000025211467305345016325 0ustar ripleyuserslibrary(gdata) saveto <- tempfile(pattern = "test.txt", tmpdir = tempdir()) write.fwf(x = data.frame(a=1:length(LETTERS), b=LETTERS), file=saveto, eol="\r\n") gdata/tests/test.read.xls.Rout.save0000644000176000001440000010773512163375365017062 0ustar ripleyusers R version 3.0.1 (2013-05-16) -- "Good Sport" Copyright (C) 2013 The R Foundation for Statistical Computing Platform: i686-pc-linux-gnu (32-bit) R is free software and comes with ABSOLUTELY NO WARRANTY. You are welcome to redistribute it under certain conditions. Type 'license()' or 'licence()' for distribution details. R is a collaborative project with many contributors. Type 'contributors()' for more information and 'citation()' on how to cite R or R packages in publications. Type 'demo()' for some demos, 'help()' for on-line help, or 'help.start()' for an HTML browser interface to help. Type 'q()' to quit R. > library(gdata) gdata: read.xls support for 'XLS' (Excel 97-2004) files ENABLED. gdata: read.xls support for 'XLSX' (Excel 2007+) files ENABLED. Attaching package: 'gdata' The following object is masked from 'package:stats': nobs The following object is masked from 'package:utils': object.size > > if ( ! 'XLSX' %in% xlsFormats() ) + { + try( installXLSXsupport() ) + } > > # iris.xls is included in the gregmisc package for use as an example > xlsfile <- file.path(path.package('gdata'),'xls','iris.xls') > > iris.1 <- read.xls(xlsfile) # defaults to csv format > iris.1 Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa 7 4.6 3.4 1.4 0.3 setosa 8 5.0 3.4 1.5 0.2 setosa 9 4.4 2.9 1.4 0.2 setosa 10 4.9 3.1 1.5 0.1 setosa 11 5.4 3.7 1.5 0.2 setosa 12 4.8 3.4 1.6 0.2 setosa 13 4.8 3.0 1.4 0.1 setosa 14 4.3 3.0 1.1 0.1 setosa 15 5.8 4.0 1.2 0.2 setosa 16 5.7 4.4 1.5 0.4 setosa 17 5.4 3.9 1.3 0.4 setosa 18 5.1 3.5 1.4 0.3 setosa 19 5.7 3.8 1.7 0.3 setosa 20 5.1 3.8 1.5 0.3 setosa 21 5.4 3.4 1.7 0.2 setosa 22 5.1 3.7 1.5 0.4 setosa 23 4.6 3.6 1.0 0.2 setosa 24 5.1 3.3 1.7 0.5 setosa 25 4.8 3.4 1.9 0.2 setosa 26 5.0 3.0 1.6 0.2 setosa 27 5.0 3.4 1.6 0.4 setosa 28 5.2 3.5 1.5 0.2 setosa 29 5.2 3.4 1.4 0.2 setosa 30 4.7 3.2 1.6 0.2 setosa 31 4.8 3.1 1.6 0.2 setosa 32 5.4 3.4 1.5 0.4 setosa 33 5.2 4.1 1.5 0.1 setosa 34 5.5 4.2 1.4 0.2 setosa 35 4.9 3.1 1.5 0.2 setosa 36 5.0 3.2 1.2 0.2 setosa 37 5.5 3.5 1.3 0.2 setosa 38 4.9 3.6 1.4 0.1 setosa 39 4.4 3.0 1.3 0.2 setosa 40 5.1 3.4 1.5 0.2 setosa 41 5.0 3.5 1.3 0.3 setosa 42 4.5 2.3 1.3 0.3 setosa 43 4.4 3.2 1.3 0.2 setosa 44 5.0 3.5 1.6 0.6 setosa 45 5.1 3.8 1.9 0.4 setosa 46 4.8 3.0 1.4 0.3 setosa 47 5.1 3.8 1.6 0.2 setosa 48 4.6 3.2 1.4 0.2 setosa 49 5.3 3.7 1.5 0.2 setosa 50 5.0 3.3 1.4 0.2 setosa 51 7.0 3.2 4.7 1.4 versicolor 52 6.4 3.2 4.5 1.5 versicolor 53 6.9 3.1 4.9 1.5 versicolor 54 5.5 2.3 4.0 1.3 versicolor 55 6.5 2.8 4.6 1.5 versicolor 56 5.7 2.8 4.5 1.3 versicolor 57 6.3 3.3 4.7 1.6 versicolor 58 4.9 2.4 3.3 1.0 versicolor 59 6.6 2.9 4.6 1.3 versicolor 60 5.2 2.7 3.9 1.4 versicolor 61 5.0 2.0 3.5 1.0 versicolor 62 5.9 3.0 4.2 1.5 versicolor 63 6.0 2.2 4.0 1.0 versicolor 64 6.1 2.9 4.7 1.4 versicolor 65 5.6 2.9 3.6 1.3 versicolor 66 6.7 3.1 4.4 1.4 versicolor 67 5.6 3.0 4.5 1.5 versicolor 68 5.8 2.7 4.1 1.0 versicolor 69 6.2 2.2 4.5 1.5 versicolor 70 5.6 2.5 3.9 1.1 versicolor 71 5.9 3.2 4.8 1.8 versicolor 72 6.1 2.8 4.0 1.3 versicolor 73 6.3 2.5 4.9 1.5 versicolor 74 6.1 2.8 4.7 1.2 versicolor 75 6.4 2.9 4.3 1.3 versicolor 76 6.6 3.0 4.4 1.4 versicolor 77 6.8 2.8 4.8 1.4 versicolor 78 6.7 3.0 5.0 1.7 versicolor 79 6.0 2.9 4.5 1.5 versicolor 80 5.7 2.6 3.5 1.0 versicolor 81 5.5 2.4 3.8 1.1 versicolor 82 5.5 2.4 3.7 1.0 versicolor 83 5.8 2.7 3.9 1.2 versicolor 84 6.0 2.7 5.1 1.6 versicolor 85 5.4 3.0 4.5 1.5 versicolor 86 6.0 3.4 4.5 1.6 versicolor 87 6.7 3.1 4.7 1.5 versicolor 88 6.3 2.3 4.4 1.3 versicolor 89 5.6 3.0 4.1 1.3 versicolor 90 5.5 2.5 4.0 1.3 versicolor 91 5.5 2.6 4.4 1.2 versicolor 92 6.1 3.0 4.6 1.4 versicolor 93 5.8 2.6 4.0 1.2 versicolor 94 5.0 2.3 3.3 1.0 versicolor 95 5.6 2.7 4.2 1.3 versicolor 96 5.7 3.0 4.2 1.2 versicolor 97 5.7 2.9 4.2 1.3 versicolor 98 6.2 2.9 4.3 1.3 versicolor 99 5.1 2.5 3.0 1.1 versicolor 100 5.7 2.8 4.1 1.3 versicolor 101 6.3 3.3 6.0 2.5 virginica 102 5.8 2.7 5.1 1.9 virginica 103 7.1 3.0 5.9 2.1 virginica 104 6.3 2.9 5.6 1.8 virginica 105 6.5 3.0 5.8 2.2 virginica 106 7.6 3.0 6.6 2.1 virginica 107 4.9 2.5 4.5 1.7 virginica 108 7.3 2.9 6.3 1.8 virginica 109 6.7 2.5 5.8 1.8 virginica 110 7.2 3.6 6.1 2.5 virginica 111 6.5 3.2 5.1 2.0 virginica 112 6.4 2.7 5.3 1.9 virginica 113 6.8 3.0 5.5 2.1 virginica 114 5.7 2.5 5.0 2.0 virginica 115 5.8 2.8 5.1 2.4 virginica 116 6.4 3.2 5.3 2.3 virginica 117 6.5 3.0 5.5 1.8 virginica 118 7.7 3.8 6.7 2.2 virginica 119 7.7 2.6 6.9 2.3 virginica 120 6.0 2.2 5.0 1.5 virginica 121 6.9 3.2 5.7 2.3 virginica 122 5.6 2.8 4.9 2.0 virginica 123 7.7 2.8 6.7 2.0 virginica 124 6.3 2.7 4.9 1.8 virginica 125 6.7 3.3 5.7 2.1 virginica 126 7.2 3.2 6.0 1.8 virginica 127 6.2 2.8 4.8 1.8 virginica 128 6.1 3.0 4.9 1.8 virginica 129 6.4 2.8 5.6 2.1 virginica 130 7.2 3.0 5.8 1.6 virginica 131 7.4 2.8 6.1 1.9 virginica 132 7.9 3.8 6.4 2.0 virginica 133 6.4 2.8 5.6 2.2 virginica 134 6.3 2.8 5.1 1.5 virginica 135 6.1 2.6 5.6 1.4 virginica 136 7.7 3.0 6.1 2.3 virginica 137 6.3 3.4 5.6 2.4 virginica 138 6.4 3.1 5.5 1.8 virginica 139 6.0 3.0 4.8 1.8 virginica 140 6.9 3.1 5.4 2.1 virginica 141 6.7 3.1 5.6 2.4 virginica 142 6.9 3.1 5.1 2.3 virginica 143 5.8 2.7 5.1 1.9 virginica 144 6.8 3.2 5.9 2.3 virginica 145 6.7 3.3 5.7 2.5 virginica 146 6.7 3.0 5.2 2.3 virginica 147 6.3 2.5 5.0 1.9 virginica 148 6.5 3.0 5.2 2.0 virginica 149 6.2 3.4 5.4 2.3 virginica 150 5.9 3.0 5.1 1.8 virginica > > iris.2 <- read.xls(xlsfile,method="csv") # specify csv format > iris.2 Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa 7 4.6 3.4 1.4 0.3 setosa 8 5.0 3.4 1.5 0.2 setosa 9 4.4 2.9 1.4 0.2 setosa 10 4.9 3.1 1.5 0.1 setosa 11 5.4 3.7 1.5 0.2 setosa 12 4.8 3.4 1.6 0.2 setosa 13 4.8 3.0 1.4 0.1 setosa 14 4.3 3.0 1.1 0.1 setosa 15 5.8 4.0 1.2 0.2 setosa 16 5.7 4.4 1.5 0.4 setosa 17 5.4 3.9 1.3 0.4 setosa 18 5.1 3.5 1.4 0.3 setosa 19 5.7 3.8 1.7 0.3 setosa 20 5.1 3.8 1.5 0.3 setosa 21 5.4 3.4 1.7 0.2 setosa 22 5.1 3.7 1.5 0.4 setosa 23 4.6 3.6 1.0 0.2 setosa 24 5.1 3.3 1.7 0.5 setosa 25 4.8 3.4 1.9 0.2 setosa 26 5.0 3.0 1.6 0.2 setosa 27 5.0 3.4 1.6 0.4 setosa 28 5.2 3.5 1.5 0.2 setosa 29 5.2 3.4 1.4 0.2 setosa 30 4.7 3.2 1.6 0.2 setosa 31 4.8 3.1 1.6 0.2 setosa 32 5.4 3.4 1.5 0.4 setosa 33 5.2 4.1 1.5 0.1 setosa 34 5.5 4.2 1.4 0.2 setosa 35 4.9 3.1 1.5 0.2 setosa 36 5.0 3.2 1.2 0.2 setosa 37 5.5 3.5 1.3 0.2 setosa 38 4.9 3.6 1.4 0.1 setosa 39 4.4 3.0 1.3 0.2 setosa 40 5.1 3.4 1.5 0.2 setosa 41 5.0 3.5 1.3 0.3 setosa 42 4.5 2.3 1.3 0.3 setosa 43 4.4 3.2 1.3 0.2 setosa 44 5.0 3.5 1.6 0.6 setosa 45 5.1 3.8 1.9 0.4 setosa 46 4.8 3.0 1.4 0.3 setosa 47 5.1 3.8 1.6 0.2 setosa 48 4.6 3.2 1.4 0.2 setosa 49 5.3 3.7 1.5 0.2 setosa 50 5.0 3.3 1.4 0.2 setosa 51 7.0 3.2 4.7 1.4 versicolor 52 6.4 3.2 4.5 1.5 versicolor 53 6.9 3.1 4.9 1.5 versicolor 54 5.5 2.3 4.0 1.3 versicolor 55 6.5 2.8 4.6 1.5 versicolor 56 5.7 2.8 4.5 1.3 versicolor 57 6.3 3.3 4.7 1.6 versicolor 58 4.9 2.4 3.3 1.0 versicolor 59 6.6 2.9 4.6 1.3 versicolor 60 5.2 2.7 3.9 1.4 versicolor 61 5.0 2.0 3.5 1.0 versicolor 62 5.9 3.0 4.2 1.5 versicolor 63 6.0 2.2 4.0 1.0 versicolor 64 6.1 2.9 4.7 1.4 versicolor 65 5.6 2.9 3.6 1.3 versicolor 66 6.7 3.1 4.4 1.4 versicolor 67 5.6 3.0 4.5 1.5 versicolor 68 5.8 2.7 4.1 1.0 versicolor 69 6.2 2.2 4.5 1.5 versicolor 70 5.6 2.5 3.9 1.1 versicolor 71 5.9 3.2 4.8 1.8 versicolor 72 6.1 2.8 4.0 1.3 versicolor 73 6.3 2.5 4.9 1.5 versicolor 74 6.1 2.8 4.7 1.2 versicolor 75 6.4 2.9 4.3 1.3 versicolor 76 6.6 3.0 4.4 1.4 versicolor 77 6.8 2.8 4.8 1.4 versicolor 78 6.7 3.0 5.0 1.7 versicolor 79 6.0 2.9 4.5 1.5 versicolor 80 5.7 2.6 3.5 1.0 versicolor 81 5.5 2.4 3.8 1.1 versicolor 82 5.5 2.4 3.7 1.0 versicolor 83 5.8 2.7 3.9 1.2 versicolor 84 6.0 2.7 5.1 1.6 versicolor 85 5.4 3.0 4.5 1.5 versicolor 86 6.0 3.4 4.5 1.6 versicolor 87 6.7 3.1 4.7 1.5 versicolor 88 6.3 2.3 4.4 1.3 versicolor 89 5.6 3.0 4.1 1.3 versicolor 90 5.5 2.5 4.0 1.3 versicolor 91 5.5 2.6 4.4 1.2 versicolor 92 6.1 3.0 4.6 1.4 versicolor 93 5.8 2.6 4.0 1.2 versicolor 94 5.0 2.3 3.3 1.0 versicolor 95 5.6 2.7 4.2 1.3 versicolor 96 5.7 3.0 4.2 1.2 versicolor 97 5.7 2.9 4.2 1.3 versicolor 98 6.2 2.9 4.3 1.3 versicolor 99 5.1 2.5 3.0 1.1 versicolor 100 5.7 2.8 4.1 1.3 versicolor 101 6.3 3.3 6.0 2.5 virginica 102 5.8 2.7 5.1 1.9 virginica 103 7.1 3.0 5.9 2.1 virginica 104 6.3 2.9 5.6 1.8 virginica 105 6.5 3.0 5.8 2.2 virginica 106 7.6 3.0 6.6 2.1 virginica 107 4.9 2.5 4.5 1.7 virginica 108 7.3 2.9 6.3 1.8 virginica 109 6.7 2.5 5.8 1.8 virginica 110 7.2 3.6 6.1 2.5 virginica 111 6.5 3.2 5.1 2.0 virginica 112 6.4 2.7 5.3 1.9 virginica 113 6.8 3.0 5.5 2.1 virginica 114 5.7 2.5 5.0 2.0 virginica 115 5.8 2.8 5.1 2.4 virginica 116 6.4 3.2 5.3 2.3 virginica 117 6.5 3.0 5.5 1.8 virginica 118 7.7 3.8 6.7 2.2 virginica 119 7.7 2.6 6.9 2.3 virginica 120 6.0 2.2 5.0 1.5 virginica 121 6.9 3.2 5.7 2.3 virginica 122 5.6 2.8 4.9 2.0 virginica 123 7.7 2.8 6.7 2.0 virginica 124 6.3 2.7 4.9 1.8 virginica 125 6.7 3.3 5.7 2.1 virginica 126 7.2 3.2 6.0 1.8 virginica 127 6.2 2.8 4.8 1.8 virginica 128 6.1 3.0 4.9 1.8 virginica 129 6.4 2.8 5.6 2.1 virginica 130 7.2 3.0 5.8 1.6 virginica 131 7.4 2.8 6.1 1.9 virginica 132 7.9 3.8 6.4 2.0 virginica 133 6.4 2.8 5.6 2.2 virginica 134 6.3 2.8 5.1 1.5 virginica 135 6.1 2.6 5.6 1.4 virginica 136 7.7 3.0 6.1 2.3 virginica 137 6.3 3.4 5.6 2.4 virginica 138 6.4 3.1 5.5 1.8 virginica 139 6.0 3.0 4.8 1.8 virginica 140 6.9 3.1 5.4 2.1 virginica 141 6.7 3.1 5.6 2.4 virginica 142 6.9 3.1 5.1 2.3 virginica 143 5.8 2.7 5.1 1.9 virginica 144 6.8 3.2 5.9 2.3 virginica 145 6.7 3.3 5.7 2.5 virginica 146 6.7 3.0 5.2 2.3 virginica 147 6.3 2.5 5.0 1.9 virginica 148 6.5 3.0 5.2 2.0 virginica 149 6.2 3.4 5.4 2.3 virginica 150 5.9 3.0 5.1 1.8 virginica > > iris.3 <- read.xls(xlsfile,method="tab") # specify tab format > iris.3 Sepal.Length Sepal.Width Petal.Length Petal.Width Species 1 5.1 3.5 1.4 0.2 setosa 2 4.9 3.0 1.4 0.2 setosa 3 4.7 3.2 1.3 0.2 setosa 4 4.6 3.1 1.5 0.2 setosa 5 5.0 3.6 1.4 0.2 setosa 6 5.4 3.9 1.7 0.4 setosa 7 4.6 3.4 1.4 0.3 setosa 8 5.0 3.4 1.5 0.2 setosa 9 4.4 2.9 1.4 0.2 setosa 10 4.9 3.1 1.5 0.1 setosa 11 5.4 3.7 1.5 0.2 setosa 12 4.8 3.4 1.6 0.2 setosa 13 4.8 3.0 1.4 0.1 setosa 14 4.3 3.0 1.1 0.1 setosa 15 5.8 4.0 1.2 0.2 setosa 16 5.7 4.4 1.5 0.4 setosa 17 5.4 3.9 1.3 0.4 setosa 18 5.1 3.5 1.4 0.3 setosa 19 5.7 3.8 1.7 0.3 setosa 20 5.1 3.8 1.5 0.3 setosa 21 5.4 3.4 1.7 0.2 setosa 22 5.1 3.7 1.5 0.4 setosa 23 4.6 3.6 1.0 0.2 setosa 24 5.1 3.3 1.7 0.5 setosa 25 4.8 3.4 1.9 0.2 setosa 26 5.0 3.0 1.6 0.2 setosa 27 5.0 3.4 1.6 0.4 setosa 28 5.2 3.5 1.5 0.2 setosa 29 5.2 3.4 1.4 0.2 setosa 30 4.7 3.2 1.6 0.2 setosa 31 4.8 3.1 1.6 0.2 setosa 32 5.4 3.4 1.5 0.4 setosa 33 5.2 4.1 1.5 0.1 setosa 34 5.5 4.2 1.4 0.2 setosa 35 4.9 3.1 1.5 0.2 setosa 36 5.0 3.2 1.2 0.2 setosa 37 5.5 3.5 1.3 0.2 setosa 38 4.9 3.6 1.4 0.1 setosa 39 4.4 3.0 1.3 0.2 setosa 40 5.1 3.4 1.5 0.2 setosa 41 5.0 3.5 1.3 0.3 setosa 42 4.5 2.3 1.3 0.3 setosa 43 4.4 3.2 1.3 0.2 setosa 44 5.0 3.5 1.6 0.6 setosa 45 5.1 3.8 1.9 0.4 setosa 46 4.8 3.0 1.4 0.3 setosa 47 5.1 3.8 1.6 0.2 setosa 48 4.6 3.2 1.4 0.2 setosa 49 5.3 3.7 1.5 0.2 setosa 50 5.0 3.3 1.4 0.2 setosa 51 7.0 3.2 4.7 1.4 versicolor 52 6.4 3.2 4.5 1.5 versicolor 53 6.9 3.1 4.9 1.5 versicolor 54 5.5 2.3 4.0 1.3 versicolor 55 6.5 2.8 4.6 1.5 versicolor 56 5.7 2.8 4.5 1.3 versicolor 57 6.3 3.3 4.7 1.6 versicolor 58 4.9 2.4 3.3 1.0 versicolor 59 6.6 2.9 4.6 1.3 versicolor 60 5.2 2.7 3.9 1.4 versicolor 61 5.0 2.0 3.5 1.0 versicolor 62 5.9 3.0 4.2 1.5 versicolor 63 6.0 2.2 4.0 1.0 versicolor 64 6.1 2.9 4.7 1.4 versicolor 65 5.6 2.9 3.6 1.3 versicolor 66 6.7 3.1 4.4 1.4 versicolor 67 5.6 3.0 4.5 1.5 versicolor 68 5.8 2.7 4.1 1.0 versicolor 69 6.2 2.2 4.5 1.5 versicolor 70 5.6 2.5 3.9 1.1 versicolor 71 5.9 3.2 4.8 1.8 versicolor 72 6.1 2.8 4.0 1.3 versicolor 73 6.3 2.5 4.9 1.5 versicolor 74 6.1 2.8 4.7 1.2 versicolor 75 6.4 2.9 4.3 1.3 versicolor 76 6.6 3.0 4.4 1.4 versicolor 77 6.8 2.8 4.8 1.4 versicolor 78 6.7 3.0 5.0 1.7 versicolor 79 6.0 2.9 4.5 1.5 versicolor 80 5.7 2.6 3.5 1.0 versicolor 81 5.5 2.4 3.8 1.1 versicolor 82 5.5 2.4 3.7 1.0 versicolor 83 5.8 2.7 3.9 1.2 versicolor 84 6.0 2.7 5.1 1.6 versicolor 85 5.4 3.0 4.5 1.5 versicolor 86 6.0 3.4 4.5 1.6 versicolor 87 6.7 3.1 4.7 1.5 versicolor 88 6.3 2.3 4.4 1.3 versicolor 89 5.6 3.0 4.1 1.3 versicolor 90 5.5 2.5 4.0 1.3 versicolor 91 5.5 2.6 4.4 1.2 versicolor 92 6.1 3.0 4.6 1.4 versicolor 93 5.8 2.6 4.0 1.2 versicolor 94 5.0 2.3 3.3 1.0 versicolor 95 5.6 2.7 4.2 1.3 versicolor 96 5.7 3.0 4.2 1.2 versicolor 97 5.7 2.9 4.2 1.3 versicolor 98 6.2 2.9 4.3 1.3 versicolor 99 5.1 2.5 3.0 1.1 versicolor 100 5.7 2.8 4.1 1.3 versicolor 101 6.3 3.3 6.0 2.5 virginica 102 5.8 2.7 5.1 1.9 virginica 103 7.1 3.0 5.9 2.1 virginica 104 6.3 2.9 5.6 1.8 virginica 105 6.5 3.0 5.8 2.2 virginica 106 7.6 3.0 6.6 2.1 virginica 107 4.9 2.5 4.5 1.7 virginica 108 7.3 2.9 6.3 1.8 virginica 109 6.7 2.5 5.8 1.8 virginica 110 7.2 3.6 6.1 2.5 virginica 111 6.5 3.2 5.1 2.0 virginica 112 6.4 2.7 5.3 1.9 virginica 113 6.8 3.0 5.5 2.1 virginica 114 5.7 2.5 5.0 2.0 virginica 115 5.8 2.8 5.1 2.4 virginica 116 6.4 3.2 5.3 2.3 virginica 117 6.5 3.0 5.5 1.8 virginica 118 7.7 3.8 6.7 2.2 virginica 119 7.7 2.6 6.9 2.3 virginica 120 6.0 2.2 5.0 1.5 virginica 121 6.9 3.2 5.7 2.3 virginica 122 5.6 2.8 4.9 2.0 virginica 123 7.7 2.8 6.7 2.0 virginica 124 6.3 2.7 4.9 1.8 virginica 125 6.7 3.3 5.7 2.1 virginica 126 7.2 3.2 6.0 1.8 virginica 127 6.2 2.8 4.8 1.8 virginica 128 6.1 3.0 4.9 1.8 virginica 129 6.4 2.8 5.6 2.1 virginica 130 7.2 3.0 5.8 1.6 virginica 131 7.4 2.8 6.1 1.9 virginica 132 7.9 3.8 6.4 2.0 virginica 133 6.4 2.8 5.6 2.2 virginica 134 6.3 2.8 5.1 1.5 virginica 135 6.1 2.6 5.6 1.4 virginica 136 7.7 3.0 6.1 2.3 virginica 137 6.3 3.4 5.6 2.4 virginica 138 6.4 3.1 5.5 1.8 virginica 139 6.0 3.0 4.8 1.8 virginica 140 6.9 3.1 5.4 2.1 virginica 141 6.7 3.1 5.6 2.4 virginica 142 6.9 3.1 5.1 2.3 virginica 143 5.8 2.7 5.1 1.9 virginica 144 6.8 3.2 5.9 2.3 virginica 145 6.7 3.3 5.7 2.5 virginica 146 6.7 3.0 5.2 2.3 virginica 147 6.3 2.5 5.0 1.9 virginica 148 6.5 3.0 5.2 2.0 virginica 149 6.2 3.4 5.4 2.3 virginica 150 5.9 3.0 5.1 1.8 virginica > > stopifnot(all.equal(iris.1, iris.2)) > stopifnot(all.equal(iris.1, iris.3)) > > exampleFile <- file.path(path.package('gdata'),'xls', + 'ExampleExcelFile.xls') > > exampleFile2007 <- file.path(path.package('gdata'),'xls', + 'ExampleExcelFile.xlsx') > > # see the number and names of sheets: > sheetCount(exampleFile) [1] 4 > > if( 'XLSX' %in% xlsFormats() ) + sheetCount(exampleFile2007) [1] 4 > > sheetNames(exampleFile) [1] "Sheet First" "Sheet Second" [3] "Sheet with a very long name!" "Sheet with initial text" > > if( 'XLSX' %in% xlsFormats() ) + sheetNames(exampleFile2007) [1] "Sheet First" "Sheet Second" [3] "Sheet with a very long name!" "Sheet with initial text" > > example.1 <- read.xls(exampleFile, sheet=1) # default is first worksheet > example.1 A B C 1 1 1 1 2 2 4 8 3 3 9 27 4 4 16 64 5 5 25 125 6 6 36 216 7 7 49 343 > > example.2 <- read.xls(exampleFile, sheet=2) # second worksheet by number > example.2 X D E. F G Factor 1 FirstRow 1 NA NA NA Red 2 SecondRow 2 1 NA NA Green 3 ThirdRow 3 2 1 NA Red 4 FourthRow 4 3 2 1 Black > > example.3 <- read.xls(exampleFile, sheet=3, header=FALSE) # third worksheet by number > example.3 V1 V2 V3 V4 V5 V6 1 1 2001-01-01 1:01 0.2058182 NA A 2 2 2002-02-02 2:02 0.2910708 NA B 3 3 2003-03-03 3:03 0.3564875 -0.84147098 C 4 4 2004-04-04 4:04 0.4116363 0.70807342 5 5 2005-05-05 5:05 0.4602234 0.50136797 A 6 6 2006-06-06 6:06 NA 0.25136984 B 7 7 2007-07-07 7:07 0.5445436 0.06318679 B 8 8 2008-08-08 8:08 0.5821416 NA C 9 9 2009-09-09 9:09 0.6174545 0.00000000 A 10 10 2010-10-10 10:10 0.6508541 0.00000000 A > > example.4 <- read.xls(exampleFile, sheet=3, header=FALSE) # third worksheet by number > example.4 V1 V2 V3 V4 V5 V6 1 1 2001-01-01 1:01 0.2058182 NA A 2 2 2002-02-02 2:02 0.2910708 NA B 3 3 2003-03-03 3:03 0.3564875 -0.84147098 C 4 4 2004-04-04 4:04 0.4116363 0.70807342 5 5 2005-05-05 5:05 0.4602234 0.50136797 A 6 6 2006-06-06 6:06 NA 0.25136984 B 7 7 2007-07-07 7:07 0.5445436 0.06318679 B 8 8 2008-08-08 8:08 0.5821416 NA C 9 9 2009-09-09 9:09 0.6174545 0.00000000 A 10 10 2010-10-10 10:10 0.6508541 0.00000000 A > > if( 'XLSX' %in% xlsFormats() ) + { + example.x.1 <- read.xls(exampleFile2007, sheet=1) # default is first worksheet + print(example.x.1) + + example.x.2 <- read.xls(exampleFile2007, sheet=2) # second worksheet by number + print(example.x.2) + + example.x.3 <- read.xls(exampleFile2007, sheet=3, header=FALSE) # third worksheet by number + print(example.x.3) + + example.x.4 <- read.xls(exampleFile2007, sheet=3, header=FALSE) # third worksheet by number + print(example.x.4) + + data <- read.xls(exampleFile2007, sheet="Sheet Second") # and by name + print(data) + + # load the third worksheet, skipping the first two non-data lines... + data <- read.xls(exampleFile2007, sheet="Sheet with initial text", skip=2) + print(data) + } A B C 1 1 1 1 2 2 4 8 3 3 9 27 4 4 16 64 5 5 25 125 6 6 36 216 7 7 49 343 X D E. F G Factor 1 FirstRow 1 NA NA NA Red 2 SecondRow 2 1 NA NA Green 3 ThirdRow 3 2 1 NA Red 4 FourthRow 4 3 2 1 Black V1 V2 V3 V4 V5 V6 1 1 2001-01-01 1:01 0.2058182 NA A 2 2 2002-02-02 2:02 0.2910708 NA B 3 3 2003-03-03 3:03 0.3564875 -0.84147098 C 4 4 2004-04-04 4:04 0.4116363 0.70807342 5 5 2005-05-05 5:05 0.4602234 0.50136797 A 6 6 2006-06-06 6:06 NA 0.25136984 B 7 7 2007-07-07 7:07 0.5445436 0.06318679 B 8 8 2008-08-08 8:08 0.5821416 NA C 9 9 2009-09-09 9:09 0.6174545 0.00000000 A 10 10 2010-10-10 10:10 0.6508541 0.00000000 A V1 V2 V3 V4 V5 V6 1 1 2001-01-01 1:01 0.2058182 NA A 2 2 2002-02-02 2:02 0.2910708 NA B 3 3 2003-03-03 3:03 0.3564875 -0.84147098 C 4 4 2004-04-04 4:04 0.4116363 0.70807342 5 5 2005-05-05 5:05 0.4602234 0.50136797 A 6 6 2006-06-06 6:06 NA 0.25136984 B 7 7 2007-07-07 7:07 0.5445436 0.06318679 B 8 8 2008-08-08 8:08 0.5821416 NA C 9 9 2009-09-09 9:09 0.6174545 0.00000000 A 10 10 2010-10-10 10:10 0.6508541 0.00000000 A X D E. F G Factor 1 FirstRow 1 NA NA NA Red 2 SecondRow 2 1 NA NA Green 3 ThirdRow 3 2 1 NA Red 4 FourthRow 4 3 2 1 Black X X.1 D E. F G Factor 1 NA FirstRow 1 NA NA NA Red 2 NA SecondRow 2 1 NA NA Green 3 NA ThirdRow 3 2 1 NA Red 4 NA FourthRow 4 3 2 1 Black > > > ## Check handling of skip.blank.lines=FALSE > > example.skip <- read.xls(exampleFile, sheet=2, blank.lines.skip=FALSE) > example.skip X D E. F G Factor 1 FirstRow 1 NA NA NA Red 2 SecondRow 2 1 NA NA Green 3 NA NA NA NA 4 ThirdRow 3 2 1 NA Red 5 FourthRow 4 3 2 1 Black > > if( 'XLSX' %in% xlsFormats() ) + { + example.x.skip <- read.xls(exampleFile2007, sheet=2, blank.lines.skip=FALSE) + example.x.skip + } X D E. F G Factor 1 FirstRow 1 NA NA NA Red 2 SecondRow 2 1 NA NA Green 3 NA NA NA NA 4 ThirdRow 3 2 1 NA Red 5 FourthRow 4 3 2 1 Black > > > ## Check handing of fileEncoding for latin-1 characters > > latin1File <- file.path(path.package('gdata'),'xls', 'latin-1.xls') > latin1FileX <- file.path(path.package('gdata'),'xls', 'latin-1.xlsx') > > example.latin1 <- read.xls(latin1File, fileEncoding='latin1') > > if( 'XLSX' %in% xlsFormats() ) + { + example.latin1.x <- read.xls(latin1FileX, fileEncoding='latin1') + } > > > > proc.time() user system elapsed 10.072 1.468 12.094 gdata/tests/test.read.xls.R0000644000176000001440000000513512163377345015364 0ustar ripleyuserslibrary(gdata) if ( ! 'XLSX' %in% xlsFormats() ) { try( installXLSXsupport() ) } # iris.xls is included in the gregmisc package for use as an example xlsfile <- file.path(path.package('gdata'),'xls','iris.xls') iris.1 <- read.xls(xlsfile) # defaults to csv format iris.1 iris.2 <- read.xls(xlsfile,method="csv") # specify csv format iris.2 iris.3 <- read.xls(xlsfile,method="tab") # specify tab format iris.3 stopifnot(all.equal(iris.1, iris.2)) stopifnot(all.equal(iris.1, iris.3)) exampleFile <- file.path(path.package('gdata'),'xls', 'ExampleExcelFile.xls') exampleFile2007 <- file.path(path.package('gdata'),'xls', 'ExampleExcelFile.xlsx') # see the number and names of sheets: sheetCount(exampleFile) if( 'XLSX' %in% xlsFormats() ) sheetCount(exampleFile2007) sheetNames(exampleFile) if( 'XLSX' %in% xlsFormats() ) sheetNames(exampleFile2007) example.1 <- read.xls(exampleFile, sheet=1) # default is first worksheet example.1 example.2 <- read.xls(exampleFile, sheet=2) # second worksheet by number example.2 example.3 <- read.xls(exampleFile, sheet=3, header=FALSE) # third worksheet by number example.3 example.4 <- read.xls(exampleFile, sheet=3, header=FALSE) # third worksheet by number example.4 if( 'XLSX' %in% xlsFormats() ) { example.x.1 <- read.xls(exampleFile2007, sheet=1) # default is first worksheet print(example.x.1) example.x.2 <- read.xls(exampleFile2007, sheet=2) # second worksheet by number print(example.x.2) example.x.3 <- read.xls(exampleFile2007, sheet=3, header=FALSE) # third worksheet by number print(example.x.3) example.x.4 <- read.xls(exampleFile2007, sheet=3, header=FALSE) # third worksheet by number print(example.x.4) data <- read.xls(exampleFile2007, sheet="Sheet Second") # and by name print(data) # load the third worksheet, skipping the first two non-data lines... data <- read.xls(exampleFile2007, sheet="Sheet with initial text", skip=2) print(data) } ## Check handling of skip.blank.lines=FALSE example.skip <- read.xls(exampleFile, sheet=2, blank.lines.skip=FALSE) example.skip if( 'XLSX' %in% xlsFormats() ) { example.x.skip <- read.xls(exampleFile2007, sheet=2, blank.lines.skip=FALSE) example.x.skip } ## Check handing of fileEncoding for latin-1 characters latin1File <- file.path(path.package('gdata'),'xls', 'latin-1.xls') latin1FileX <- file.path(path.package('gdata'),'xls', 'latin-1.xlsx') example.latin1 <- read.xls(latin1File, fileEncoding='latin1') if( 'XLSX' %in% xlsFormats() ) { example.latin1.x <- read.xls(latin1FileX, fileEncoding='latin1') } gdata/man/0000755000176000001440000000000012163373113012135 5ustar ripleyusersgdata/man/xlsFormats.Rd0000644000176000001440000000112611367574371014604 0ustar ripleyusers\name{xlsFormats} \Rdversion{1.1} \alias{xlsFormats} \title{ Check which file formats are supported by read.xls } \description{ Check which file formats are supported by read.xls } \usage{ xlsFormats(perl = "perl", verbose = FALSE) } \arguments{ \item{perl}{Path to perl interpreter (optional).} \item{verbose}{If \code{TRUE}, show additional messages during processing.} } \value{ Vector of supported formats, possible elements are 'XLS' and 'XLSX'. } \seealso{ \code{\link{read.xls}}, \code{\link{xls2csv}}. } \examples{ xlsFormats() } \keyword{ misc } gdata/man/write.fwf.Rd0000644000176000001440000002255511467310235014352 0ustar ripleyusers% write.fwf.Rd %-------------------------------------------------------------------------- % What: Write fixed width format man page % $Id: write.fwf.Rd 1459 2010-11-12 19:08:12Z warnes $ % Time-stamp: <2008-08-05 12:40:32 ggorjan> %-------------------------------------------------------------------------- \name{write.fwf} \alias{write.fwf} \concept{data output} \concept{data export} \title{Write object in fixed width format} \description{ \code{write.fwf} writes object in *f*ixed *w*idth *f*ormat. } \usage{ write.fwf(x, file="", append=FALSE, quote=FALSE, sep=" ", na="", rownames=FALSE, colnames=TRUE, rowCol=NULL, justify="left", formatInfo=FALSE, quoteInfo=TRUE, width=NULL, eol="\n", qmethod=c("escape", "double"), \dots) } \arguments{ \item{x}{data.frame or matrix, the object to be written} \item{file}{character, name of file or connection, look in \code{\link{write.table}} for more} \item{append}{logical, append to existing data in \code{file}} \item{quote}{logical, quote data in output} \item{na}{character, the string to use for missing values i.e. \code{NA} in the output} \item{sep}{character, separator between columns in output} \item{rownames}{logical, print row names} \item{colnames}{logical, print column names} \item{rowCol}{character, rownames column name} \item{justify}{character, alignment of character columns; see \code{\link{format}}} \item{formatInfo}{logical, return information on number of levels, widths and format} \item{quoteInfo}{logical, should \code{formatInfo} account for quotes} \item{width}{numeric, width of the columns in the output} \item{eol}{the character(s) to print at the end of each line (row). For example, 'eol="\\r\\n"' will produce Windows' line endings on a Unix-alike OS, and 'eol="\\r"' will produce files as expected by Mac OS Excel 2004.} \item{qmethod}{a character string specifying how to deal with embedded double quote characters when quoting strings. Must be one of '"escape"' (default), in which case the quote character is escaped in C style by a backslash, or '"double"', in which case it is doubled. You can specify just the initial letter.} \item{\dots}{further arguments to \code{\link{format.info}} and \code{\link{format}} } } \details{ *F*ixed *w*idth *f*ormat is not used widely anymore. Use some other format (say *c*omma *s*eparated *v*alues; see \code{\link{read.csv}}) if you can. However, if you need fixed width format then \code{write.fwf} can help you. Output is similar to \code{print(x)} or \code{format(x)}. Formatting is done completely by \code{\link{format}} on a column basis. Columns in the output are by default separated with a space i.e. empty column with a width of one character, but that can be changed with \code{sep} argument as passed to \code{\link{write.table}} via \dots. As mentioned formatting is done completely by \code{\link{format}}. Arguments can be passed to \code{format} via \code{\dots} to further modify the output. However, note that the returned \code{formatInfo} might not properly account for this, since \code{\link{format.info}} (which is used to collect information about formatting) lacks the arguments of \code{\link{format}}. \code{quote} can be used to quote fields in the output. Since all columns of \code{x} are converted to character (via \code{\link{format}}) during the output, all columns will be quoted! If quotes are used, \code{\link{read.table}} can be easily used to read the data back into \R. Check examples. Do read the details about \code{quoteInfo} argument. Use only *true* character, i.e., avoid use of tabs, i.e., "\\t", or similar separators via argument \code{sep}. Width of the separator is taken as the number of characters evaluated via \code{\link{nchar}(sep)}. Use argument \code{na} to convert missing/unknown values. Only single value can be specified. Use \code{\link{NAToUnknown}} prior to export if you need greater flexibility. If \code{rowCol} is not \code{NULL} and \code{rownames=TRUE}, rownames will also have column name with \code{rowCol} value. This is mainly for flexibility with tools outside \R. Note that (at least in \R 2.4.0) it is not "easy" to import data back to \R with \code{\link{read.fwf}} if you also export rownames. This is the reason, that default is \code{rownames=FALSE}. Information about format of output will be returned if \code{formatInfo=TRUE}. Returned value is described in value section. This information is gathered by \code{\link{format.info}} and care was taken to handle numeric properly. If output contains rownames, values account for this. Additionally, if \code{rowCol} is not \code{NULL} returned values contain also information about format of rownames. If \code{quote=TRUE}, the output is of course wider due to quotes. Return value (with \code{formatInfo=TRUE}) can account for this in two ways; controlled with argument \code{quoteInfo}. However, note that there is no way to properly read the data back to \R if \code{quote=TRUE & quoteInfo=FALSE} arguments were used for export. \code{quoteInfo} applies only when \code{quote=TRUE}. Assume that there is a file with quoted data as shown bellow (column numbers in first three lines are only for demonstration of the values in the output). \preformatted{ 123456789 12345678 # for position 123 1234567 123456 # for width with quoteInfo=TRUE 1 12345 1234 # for width with quoteInfo=FALSE "a" "hsgdh" " 9" " " " bb" " 123" } With \code{quoteInfo=TRUE} \code{write.fwf} will return \preformatted{ colname position width V1 1 3 V2 5 7 V3 13 6 } or (with \code{quoteInfo=FALSE}) \preformatted{ colname position width V1 2 1 V2 6 5 V3 14 4 } Argument \code{width} can be used to increase the width of the columns in the output. This argument is passed to the width argument of \code{\link{format}} function. Values in \code{width} are recycled if there is less values than the number of columns. If the specified width is to short in comparison to the "width" of the data in particular column, error is issued. } \value{ Besides its effect to write/export data \code{write.fwf} can provide information on format and width. A data.frame is returned with the following columns: \item{colname}{name of the column} \item{nlevels}{number of unique values (unused levels of factors are dropped), 0 for numeric column} \item{position}{starting column number in the output} \item{width}{width of the column} \item{digits}{number of digits after the decimal point} \item{exp}{width of exponent in exponential representation; 0 means there is no exponential representation, while 1 represents exponent of length one i.e. \code{1e+6} and 2 \code{1e+06} or \code{1e+16}} } \author{Gregor Gorjanc} \seealso{ \code{\link{format.info}}, \code{\link{format}}, \code{\link{NAToUnknown}}, \code{\link{write.table}}, \code{\link{read.fwf}}, \code{\link{read.table}} and \code{\link{trim}} } \examples{ ## Some data num <- round(c(733070.345678, 1214213.78765456, 553823.798765678, 1085022.8876545678, 571063.88765456, 606718.3876545678, 1053686.6, 971024.187656, 631193.398765456, 879431.1), digits=3) testData <- data.frame(num1=c(1:10, NA), num2=c(NA, seq(from=1, to=5.5, by=0.5)), num3=c(NA, num), int1=c(as.integer(1:4), NA, as.integer(4:9)), fac1=factor(c(NA, letters[1:9], "hjh")), fac2=factor(c(letters[6:15], NA)), cha1=c(letters[17:26], NA), cha2=c(NA, "longer", letters[25:17]), stringsAsFactors=FALSE) levels(testData$fac1) <- c(levels(testData$fac1), "unusedLevel") testData$Date <- as.Date("1900-1-1") testData$Date[2] <- NA testData$POSIXt <- as.POSIXct(strptime("1900-1-1 01:01:01", format="\%Y-\%m-\%d \%H:\%M:\%S")) testData$POSIXt[5] <- NA ## Default write.fwf(x=testData) ## NA should be - write.fwf(x=testData, na="-") ## NA should be -NA- write.fwf(x=testData, na="-NA-") ## Some other separator than space write.fwf(x=testData[, 1:4], sep="-mySep-") ## Force wider columns write.fwf(x=testData[, 1:5], width=20) ## Write to file and report format and fixed width information file <- tempfile() formatInfo <- write.fwf(x=testData, file=file, formatInfo=TRUE) ## Read exported data back to R (note +1 due to separator) ## ... without header read.fwf(file=file, widths=formatInfo$width + 1, header=FALSE, skip=1, strip.white=TRUE) ## ... with header - via postimport modfication tmp <- read.fwf(file=file, widths=formatInfo$width + 1, skip=1, strip.white=TRUE) colnames(tmp) <- read.table(file=file, nrow=1, as.is=TRUE) tmp ## ... with header - persuading read.fwf to accept header properly ## (thanks to Marc Schwartz) read.fwf(file=file, widths=formatInfo$width + 1, strip.white=TRUE, skip=1, col.names=read.table(file=file, nrow=1, as.is=TRUE)) ## ... with header - with the use of quotes write.fwf(x=testData, file=file, quote=TRUE) read.table(file=file, header=TRUE, strip.white=TRUE) ## Tidy up unlink(file) } \keyword{print} \keyword{file} %-------------------------------------------------------------------------- % write.fwf.Rd ends here gdata/man/wideByFactor.Rd0000644000176000001440000000413711367120201015004 0ustar ripleyusers% wideByFactor.Rd %-------------------------------------------------------------------------- % What: Reshape by factor levels - help % $Id$ % Time-stamp: <2008-12-30 13:49:50 ggorjan> %-------------------------------------------------------------------------- \name{wideByFactor} \alias{wideByFactor} \title{Create multivariate data by a given factor} \description{ \code{wideByFactor} modifies data.frame in such a way that variables are \dQuote{separated} into several columns by factor levels. } \usage{ wideByFactor(x, factor, common, sort=TRUE, keepFactor=TRUE) } \arguments{ \item{x}{data frame} \item{factor}{character, column name of a factor by which variables will be divided} \item{common}{character, column names of (common) columns that should not be divided} \item{sort}{logical, sort resulting data frame by factor levels} \item{keepFactor}{logical, keep the \sQuote{factor} column} } \details{ Given data frame is modified in such a way, that output represents a data frame with \eqn{c + f + n * v} columns, where \eqn{c} is a number of common columns for all levels of a factor, \eqn{f} is a factor column, \eqn{n} is a number of levels in factor \eqn{f} and \eqn{v} is a number of variables that should be divided for each level of a factor. Number of rows stays the same! } \value{ A data frame where divided variables have sort of \dQuote{diagonalized} structure } \author{Gregor Gorjanc} \seealso{ \code{\link[stats]{reshape}} in the \pkg{stats} package, \code{\link[reshape]{melt}} and \code{\link[reshape]{cast}} in the \pkg{reshape} package } \examples{ n <- 10 f <- 2 tmp <- data.frame(y1=rnorm(n=n), y2=rnorm(n=n), f1=factor(rep(letters[1:f], n/2)), f2=factor(c(rep(c("M"), n/2), rep(c("F"), n/2))), c1=1:n, c2=2*(1:n)) wideByFactor(x=tmp, factor="f1", common=c("c1", "c2", "f2")) wideByFactor(x=tmp, factor="f1", common=c("c1", "c2")) } \keyword{manip} \keyword{misc} %-------------------------------------------------------------------------- % wideByFactor.Rd ends heregdata/man/upperTriangle.Rd0000644000176000001440000000257511367120201015247 0ustar ripleyusers\name{upperTriangle} \alias{upperTriangle} \alias{upperTriangle<-} \alias{lowerTriangle} \alias{lowerTriangle<-} \title{Extract or replace the upper/lower triangular portion of a matrix} \description{ Extract or replace the upper/lower triangular portion of a matrix } \usage{ upperTriangle(x, diag=FALSE) upperTriangle(x, diag=FALSE) <- value lowerTriangle(x, diag=FALSE) lowerTriangle(x, diag=FALSE) <- value } %- maybe also 'usage' for other objects documented here. \arguments{ \item{x}{Matrix} \item{diag}{Logical. If \code{TRUE}, include the matrix diagonal.} \item{value}{Either a single value or a vector of length equal to that of the current upper/lower triangular. Should be of a mode which can be coerced to that of \code{x}.} } \value{ \code{upperTriangle(x)} and \code{lowerTriangle(x)} return the upper or lower triangle of matrix x, respectively. The assignment forms replace the upper or lower traingular area of the matrix with the provided value(s). } \author{Gregory R. Warnes \email{greg@warnes.net}} \seealso{ \code{\link[base]{diag}} } \examples{ x <- matrix( 1:25, nrow=5, ncol=5) x upperTriangle(x) upperTriangle(x, diag=TRUE) lowerTriangle(x) lowerTriangle(x, diag=TRUE) upperTriangle(x) <- NA x upperTriangle(x, diag=TRUE) <- 1:15 x lowerTriangle(x) <- NA x lowerTriangle(x, diag=TRUE) <- 1:15 x } \keyword{array} gdata/man/unmatrix.Rd0000644000176000001440000000173511367120201014272 0ustar ripleyusers\name{unmatrix} \alias{unmatrix} \title{Convert a matrix into a vector, with appropriate names} \description{ Convert a matrix into a vector, with element names constructed from the row and column names of the matrix. } \usage{ unmatrix(x, byrow=FALSE) } \arguments{ \item{x}{matrix} \item{byrow}{Logical. If \code{FALSE}, the elements within columns will be adjacent in the resulting vector, otherwise elements within rows will be adjacent.} } \value{ A vector with names constructed from the row and column names from the matrix. If the the row or column names are missing, ('r1', 'r2', ..,) or ('c1', 'c2', ..) will be used as appropriate. } \author{Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link[base]{as.vector}} } \examples{ # simple, useless example m <- matrix( letters[1:10], ncol=5) m unmatrix(m) # unroll model output x <- rnorm(100) y <- rnorm(100, mean=3+5*x, sd=0.25) m <- coef( summary(lm( y ~ x )) ) unmatrix(m) } \keyword{manip} gdata/man/unknown.Rd0000644000176000001440000001325711367120201014124 0ustar ripleyusers% unknown.Rd %-------------------------------------------------------------------------- % What: Change given unknown value to NA and vice versa man page % $Id: unknown.Rd 1357 2009-08-20 14:54:44Z warnes $ % Time-stamp: <2007-08-17 20:18:54 ggorjan> %-------------------------------------------------------------------------- \name{unknownToNA} \alias{isUnknown} \alias{isUnknown.default} \alias{isUnknown.POSIXlt} \alias{isUnknown.list} \alias{isUnknown.data.frame} \alias{isUnknown.matrix} \alias{unknownToNA} \alias{unknownToNA.default} \alias{unknownToNA.factor} \alias{unknownToNA.list} \alias{unknownToNA.data.frame} \alias{NAToUnknown} \alias{NAToUnknown.default} \alias{NAToUnknown.factor} \alias{NAToUnknown.list} \alias{NAToUnknown.data.frame} \concept{missing} \title{Change unknown values to NA and vice versa} \description{ Unknown or missing values (\code{NA} in \R) can be represented in various ways (as 0, 999, etc.) in different programs. \code{isUnknown}, \code{unknownToNA}, and \code{NAToUnknown} can help to change unknown values to \code{NA} and vice versa. } \usage{ isUnknown(x, unknown=NA, \dots) unknownToNA(x, unknown, warning=FALSE, \dots) NAToUnknown(x, unknown, force=FALSE, call.=FALSE, \dots) } \arguments{ \item{x}{generic, object with unknown value(s)} \item{unknown}{generic, value used instead of \code{NA}} \item{warning}{logical, issue warning if \code{x} already has \code{NA}} \item{force}{logical, force to apply already existing value in \code{x}} \item{\dots}{arguments pased to other methods (as.character for POSIXlt in case of isUnknown)} \item{call.}{logical, look in \code{\link{warning}}} } \details{ This functions were written to handle different variants of \dQuote{other \code{NA}} like representations that are usually used in various external data sources. \code{unknownToNA} can help to change unknown values to \code{NA} for work in \R, while \code{NAToUnknown} is meant for the opposite and would usually be used prior to export of data from \R. \code{isUnknown} is utility function for testing for unknown values. All functions are generic and the following classes were tested to work with latest version: \dQuote{integer}, \dQuote{numeric}, \dQuote{character}, \dQuote{factor}, \dQuote{Date}, \dQuote{POSIXct}, \dQuote{POSIXlt}, \dQuote{list}, \dQuote{data.frame} and \dQuote{matrix}. For others default method might work just fine. \code{unknownToNA} and \code{isUnknown} can cope with multiple values in \code{unknown}, but those should be given as a \dQuote{vector}. If not, coercing to vector is applied. Argument \code{unknown} can be feed also with \dQuote{list} in \dQuote{list} and \dQuote{data.frame} methods. If named \dQuote{list} or \dQuote{vector} is passed to argument \code{unknown} and \code{x} is also named, matching of names will occur. Recycling occurs in all \dQuote{list} and \dQuote{data.frame} methods, when \code{unknown} argument is not of the same length as \code{x} and \code{unknown} is not named. Argument \code{unknown} in \code{NAToUnknown} should hold value that is not already present in \code{x}. If it does, error is produced and one can bypass that with \code{force=TRUE}, but be warned that there is no way to distinguish values after this action. Use at your own risk! Anyway, warning is issued about new value in \code{x}. Additionally, caution should be taken when using \code{NAToUnknown} on factors as additional level (value of \code{unknown}) is introduced. Then, as expected, \code{unknownToNA} removes defined level in \code{unknown}. If \code{unknown="NA"}, then \code{"NA"} is removed from factor levels in \code{unknownToNA} due to consistency with conversions back and forth. Unknown representation in \code{unknown} should have the same class as \code{x} in \code{NAToUnknown}, except in factors, where \code{unknown} value is coerced to character anyway. Silent coercing is also applied, when \dQuote{integer} and \dQuote{numeric} are in question. Otherwise warning is issued and coercing is tried. If that fails, \R introduces \code{NA} and the goal of \code{NAToUnknown} is not reached. \code{NAToUnknown} accepts only single value in \code{unknown} if \code{x} is atomic, while \dQuote{list} and \dQuote{data.frame} methods accept also \dQuote{vector} and \dQuote{list}. \dQuote{list/data.frame} methods can work on many components/columns. To reduce the number of needed specifications in \code{unknown} argument, default unknown value can be specified with component ".default". This matches component/column ".default" as well as all other undefined components/columns! Look in examples. } \value{ \code{unknownToNA} and \code{NAToUnknown} return modified \code{x}. \code{isUnknown} returns logical values for object \code{x}. } \author{Gregor Gorjanc} \seealso{\code{\link{is.na}}} \examples{ xInt <- c(0, 1, 0, 5, 6, 7, 8, 9, NA) isUnknown(x=xInt, unknown=0) isUnknown(x=xInt, unknown=c(0, NA)) (xInt <- unknownToNA(x=xInt, unknown=0)) (xInt <- NAToUnknown(x=xInt, unknown=0)) xFac <- factor(c("0", 1, 2, 3, NA, "NA")) isUnknown(x=xFac, unknown=0) isUnknown(x=xFac, unknown=c(0, NA)) isUnknown(x=xFac, unknown=c(0, "NA")) isUnknown(x=xFac, unknown=c(0, "NA", NA)) (xFac <- unknownToNA(x=xFac, unknown="NA")) (xFac <- NAToUnknown(x=xFac, unknown="NA")) xList <- list(xFac=xFac, xInt=xInt) isUnknown(xList, unknown=c("NA", 0)) isUnknown(xList, unknown=list("NA", 0)) tmp <- c(0, "NA") names(tmp) <- c(".default", "xFac") isUnknown(xList, unknown=tmp) tmp <- list(.default=0, xFac="NA") isUnknown(xList, unknown=tmp) (xList <- unknownToNA(xList, unknown=tmp)) (xList <- NAToUnknown(xList, unknown=999)) } \keyword{manip} \keyword{NA} %-------------------------------------------------------------------------- % unknown.Rd ends here gdata/man/trimSum.Rd0000644000176000001440000000261011367120200014053 0ustar ripleyusers% trimSum.Rd %-------------------------------------------------------------------------- % What: Sum trimmed values - help % $Id$ % Time-stamp: <2008-12-20 00:15:57 ggorjan> %-------------------------------------------------------------------------- \name{trimSum} \alias{trimSum} \title{Trim a vector such that the last/first value represents the sum of trimmed values} \description{\code{trimSum} trims (shortens) a vector in such a way that the last or first value represents the sum of trimmed values. User needs to specify the desired length of a trimmed vector. } \usage{trimSum(x, n, right=TRUE, na.rm=FALSE, \dots)} \arguments{ \item{x}{numeric, a vector of numeric values} \item{n}{numeric, desired length of the output} \item{right}{logical, trim on the right/bottom or the left/top side} \item{na.rm}{logical, remove \code{NA} values when applying a function} \item{\dots}{arguments passed to other methods - currently not used} } \value{Trimmed vector with a last/first value representing the sum of trimmed values} \author{Gregor Gorjanc} \seealso{\code{\link[gdata]{trim}}} \examples{ x <- 1:10 trimSum(x, n=5) trimSum(x, n=5, right=FALSE) x[9] <- NA trimSum(x, n=5) trimSum(x, n=5, na.rm=TRUE) } \keyword{manip} %-------------------------------------------------------------------------- % trimSum.Rd ends here gdata/man/trim.Rd0000644000176000001440000000326411367120200013374 0ustar ripleyusers\name{trim} \alias{trim} \title{Remove leading and trailing spaces from character strings} \description{ Remove leading and trailing spaces from character strings and other related objects. } \usage{ trim(s, recode.factor=TRUE, \dots) } \arguments{ \item{s}{object to be processed} \item{recode.factor}{should levels of a factor be recoded, see below} \item{\dots}{arguments passed to other methods, currently only to \code{\link{reorder.factor}} for factors} } \details{ \code{trim} is a generic function, where default method does nothing, while method for character \code{s} trims its elements and method for factor \code{s} trims \code{\link{levels}}. There are also methods for \code{list} and \code{data.frame}. Trimming character strings can change the sort order in some locales. For factors, this can affect the coding of levels. By default, factor levels are recoded to match the trimmed sort order, but this can be disabled by setting \code{recode.factor=FALSE}. Recoding is done with \code{\link{reorder.factor}}. } \value{ \code{s} with all leading and trailing spaces removed in its elements. } \author{Gregory R. Warnes \email{greg@warnes.net} with contributions by Gregor Gorjanc} \seealso{ \code{\link[base]{sub}}, \code{\link[base]{gsub}} as well as argument \code{strip.white} in \code{\link{read.table}} and \code{\link{reorder.factor}} } \examples{ s <- " this is an example string " trim(s) f <- factor(c(s, s, " A", " B ", " C ", "D ")) levels(f) trim(f) levels(trim(f)) trim(f, recode.factor=FALSE) levels(trim(f, recode.factor=FALSE)) l <- list(s=rep(s, times=6), f=f, i=1:6) trim(l) df <- as.data.frame(l) trim(df) } \keyword{manip} \keyword{character} gdata/man/startsWith.Rd0000644000176000001440000000275711763533673014631 0ustar ripleyusers\name{startsWith} \alias{startsWith} \title{ Determine if a character string "starts with" with the specified characters. } \description{ Determine if a character string "starts with" with the specified characters. } \usage{ startsWith(str, pattern, trim=FALSE, ignore.case=FALSE) } \arguments{ \item{str}{character vector to test} \item{pattern}{characters to check for} \item{trim}{Logical flag indicating whether leading whitespace should be removed from \code{str} before testing for a match.} \item{ignore.case}{Logical flag indicating whether case should be ignored when testing for a match.} } \details{ This function returns TRUE for each element of the vector \code{str} where \code{pattern} occurs at the beginning of the string. If \code{trim} is TRUE, leading whitespace is removed from the elements of \code{str} before the test is performed. If \code{ignore.case} is TRUE, character case is ignored. } \value{ Boolean vector of the same length as \code{str}. } \author{ Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link[base]{substr}}, \code{\link{trim}} } \examples{ ## simplest example: startsWith( 'Testing', 'Test') ## vector examples s <- c('Testing', ' Testing', 'testing', 'Texting') names(s) <- s startsWith(s, 'Test') # ' Testing', 'testing', and 'Texting' do not match startsWith(s, 'Test', trim=TRUE) # Now ' Testing' matches startsWith(s, 'Test', ignore.case=TRUE) # Now 'testing' matches } \keyword{character} gdata/man/sheetCount.Rd0000644000176000001440000000240312127540513014544 0ustar ripleyusers\name{sheetCount} \Rdversion{1.1} \alias{sheetCount} \alias{sheetNames} \title{ Count or list sheet names in Excel spreadsheet files. } \description{ Count or list sheet names in Excel spreadsheet files. } \usage{ sheetCount(xls, verbose = FALSE, perl = "perl") sheetNames(xls, verbose = FALSE, perl = "perl") } \arguments{ \item{xls}{File path to spreadsheet. Supports "http://", "https://", and "ftp://" URLS.} \item{verbose}{If \code{TRUE}, show additional messages during processing.} \item{perl}{Path to perl interpreter.} } \value{ \code{sheetCount} returns the number of sheets in the spreadsheet. \code{sheetNames} returns the names of sheets in the spreadsheet. } \seealso{ \code{\link{read.xls}}, \code{\link{xls2csv}}. } \examples{ xlsfile <- system.file("xls", "iris.xls", package = "gdata") xlsfile sheetCount(xlsfile) exampleFile <- file.path(path.package('gdata'),'xls', 'ExampleExcelFile.xls') exampleFile2007 <- file.path(path.package('gdata'),'xls', 'ExampleExcelFile.xlsx') sheetCount(exampleFile) if( 'XLSX' \%in\% xlsFormats() ) # if XLSX is supported.. sheetNames(exampleFile2007) } \keyword{ misc } gdata/man/runRUnitTests.Rd0000644000176000001440000000221011367120200015220 0ustar ripleyusers% runRUnitTests.Rd %-------------------------------------------------------------------------- % What: Run RUnit tests - help % $Id$ % Time-stamp: <2008-12-30 20:58:26 ggorjan> %-------------------------------------------------------------------------- \name{.runRUnitTestsGdata} \alias{.runRUnitTestsGdata} \title{Run RUnit tests for the gdata package} \description{ Run \pkg{RUnit} tests to perform the validity/unit testing of installed \pkg{gdata} package on your own computer. } \usage{.runRUnitTestsGdata(testFileRegexp="^runit.+\\\\.[rR]$")} \arguments{ \item{testFileRegexp}{regular expression; see details} } \details{ Argument \code{testFileRegexp} can be used to specify different sets of tests provided by the package. The following values are sensible: \itemize{ \item \code{"^runit.+\\\\.[rR]$"} for basic tests } } \value{ None, just the print out of \pkg{RUnit} testing. } \seealso{ \code{\link[RUnit]{defineTestSuite}} in \pkg{RUnit} package } \examples{ ## Basic testing .runRUnitTestsGdata() } \keyword{misc} %-------------------------------------------------------------------------- % runRUnitTests.Rd ends here gdata/man/resample.Rd0000644000176000001440000000246711367120200014235 0ustar ripleyusers\name{resample} \alias{resample} \title{Consistent Random Samples and Permutations} \description{ \code{resample} takes a sample of the specified size from the elements of \code{x} using either with or without replacement. } \usage{ resample(x, size, replace = FALSE, prob = NULL) } \arguments{ \item{x}{ A numeric, complex, character or logical vector from which to choose.} \item{size}{Non-negative integer giving the number of items to choose.} \item{replace}{Should sampling be with replacement?} \item{prob}{A vector of probability weights for obtaining the elements of the vector being sampled.} } \details{ \code{resample} differs from the S/R \code{sample} function in \code{resample} always considers \code{x} to be a vector of elements to select from, while \code{sample} treats a vector of length one as a special case and samples from \code{1:x}. Otherwise, the functions have identical behavior. } \value{ Vector of the same length as the input, with the elements permuted. } \author{Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link{sample}} } \examples{ ## sample behavior differs if first argument is scalar vs vector sample( c(10) ) sample( c(10,10) ) ## resample has the consistent behavior for both cases resample( c(10) ) resample( c(10,10) ) } \keyword{misc} gdata/man/reorder.Rd0000644000176000001440000000624511367213617014104 0ustar ripleyusers% $Id: reorder.Rd 1435 2010-05-02 06:11:26Z warnes $ \name{reorder.factor} \alias{reorder.factor} \title{Reorder the Levels of a Factor} \description{ Reorder the levels of a factor } \usage{ \method{reorder}{factor}(x, X, FUN, ..., order=is.ordered(x), new.order, sort=mixedsort) } \arguments{ \item{x}{factor} \item{X}{auxillary data vector} \item{FUN}{function to be applied to subsets of \code{X} determined by \code{x}, to determine factor order} \item{...}{optional parameters to \code{FUN}} \item{order}{logical value indicating whether the returned object should be an \code{\link{ordered}} factor} \item{new.order}{a vector of indexes or a vector of label names giving the order of the new factor levels} \item{sort}{function to use to sort the factor level names, used only when \code{new.order} is missing} } \details{ This function changes the order of the levels of a factor. It can do so via three different mechanisms, depending on whether, \code{X} \emph{and} \code{FUN}, \code{new.order} or \code{sort} are provided. If \code{X} \emph{and} \code{Fun} are provided: The data in \code{X} is grouped by the levels of \code{x} and \code{FUN} is applied. The groups are then sorted by this value, and the resulting order is used for the new factor level names. If \code{new.order} is provided: For a numeric vector, the new factor level names are constructed by reordering the factor levels according to the numeric values. For vectors, \code{new.order} gives the list of new factor level names. In either case levels omitted from \code{new.order} will become missing (\code{NA}) values. If \code{sort} is provided (as it is by default): The new factor level names are generated by applying the supplied function to the existing factor level names. With \code{sort=mixedsort} the factor levels are sorted so that combined numeric and character strings are sorted in according to character rules on the character sections (including ignoring case), and the numeric rules for the numeric sections. See \code{\link[gtools]{mixedsort}} for details. } \value{ A new factor with reordered levels } \author{Gregory R. Warnes \email{greg@warnes.net}} \seealso{\code{\link{factor}} and \code{\link[stats]{reorder}}} \examples{ # Create a 4 level example factor trt <- factor( sample( c("PLACEBO", "300 MG", "600 MG", "1200 MG"), 100, replace=TRUE ) ) summary(trt) # Note that the levels are not in a meaningful order. # Change the order to something useful # default "mixedsort" ordering trt2 <- reorder(trt) summary(trt2) # using indexes: trt3 <- reorder(trt, new.order=c(4, 2, 3, 1)) summary(trt3) # using label names: trt4 <- reorder(trt, new.order=c("PLACEBO", "300 MG", "600 MG", "1200 MG")) summary(trt4) # using frequency trt5 <- reorder(trt, X=as.numeric(trt), FUN=length) summary(trt5) # drop out the '300 MG' level trt6 <- reorder(trt, new.order=c("PLACEBO", "600 MG", "1200 MG")) summary(trt6) } \keyword{ manip } gdata/man/rename.vars.Rd0000644000176000001440000000360211367213617014655 0ustar ripleyusers% $Id: rename.vars.Rd 1435 2010-05-02 06:11:26Z warnes $ % % $Log$ % Revision 1.9 2005/09/12 15:42:45 nj7w % Updated Greg's email % % Revision 1.8 2005/06/09 14:20:25 nj7w % Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. % % Revision 1.1.1.1 2005/05/25 22:07:33 nj7w % Initial entry for individual package gdata % % Revision 1.7 2004/04/01 20:23:15 warnes % Add function remove.vars(). % % Revision 1.6 2002/09/23 13:59:30 warnes % - Modified all files to include CVS Id and Log tags. % % \name{rename.vars} \alias{rename.vars} \alias{remove.vars} \title{Remove or rename variables in a dataframe } \description{ Remove or rename a variables in a data frame. } \usage{ rename.vars(data, from="", to="", info=TRUE) remove.vars(data, names="", info=TRUE) } \arguments{ \item{data}{ dataframe to be modified. } \item{from}{ character vector containing the current name of each variable to be renamed.} \item{to}{ character vector containing the new name of each variable to be renamed.} \item{names}{ character vector containing the names of variables to be removed.} \item{info}{ boolean value indicating whether to print details of the removal/renaming. Defaults to TRUE.} } %\details{ % ~~ If necessary, more details than the __description__ above ~~ %} \value{ The updated data frame with variables listed in \code{from} renamed to the corresponding element of \code{to}. } \author{Code by Don MacQueen \email{macq\@llnl.gov}. Documentation by Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link{names}}, \code{\link{colnames}}, \code{\link{data.frame}} } \examples{ data <- data.frame(x=1:10,y=1:10,z=1:10) names(data) data <- rename.vars(data, c("x","y","z"), c("first","second","third")) names(data) data <- remove.vars(data, "second") names(data) } \keyword{ manip } gdata/man/read.xls.Rd0000644000176000001440000001407212127540441014150 0ustar ripleyusers\name{read.xls} \alias{read.xls} \alias{xls2csv} \alias{xls2tab} \alias{xls2tsv} \alias{xls2sep} \title{Read Excel files} \description{Read a Microsoft Excel file into a data frame} \usage{ read.xls(xls, sheet=1, verbose=FALSE, pattern, na.strings=c("NA","#DIV/0!"), ..., method=c("csv","tsv","tab"), perl="perl") xls2csv(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., perl="perl") xls2tab(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., perl="perl") xls2tsv(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., perl="perl") xls2sep(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., method=c("csv","tsv","tab"), perl="perl") } \arguments{ \item{xls}{path to the Microsoft Excel file. Supports "http://", "https://", and "ftp://" URLS.} \item{sheet}{name or number of the worksheet to read} \item{verbose}{logical flag indicating whether details should be printed as the file is processed.} \item{pattern}{if specified, them skip all lines before the first containing this string} \item{perl}{name of the perl executable to be called.} \item{method}{intermediate file format, "csv" for comma-separated and "tab" for tab-separated} \item{na.strings}{a character vector of strings which are to be interpreted as 'NA' values. See \code{\link[utils]{read.table}} for details.} \item{blank.lines.skip}{logical flag indicating whether blank lines in the orginal file should be ignored.} \item{...}{additional arguments to read.table. The defaults for read.csv() are used.} } \value{ \code{"read.xls"} returns a data frame. \code{"xls2sep"} returns a temporary file in the specified format. \code{"xls2csv"} and \code{"xls2tab"} are simply wrappers for \code{"xls2sep"} specifying method as "csv" or "tab", respectively. } \details{ This function works translating the named Microsoft Excel file into a temporary .csv or .tab file, using the xls2csv or xls2tab Perl script installed as part of this (gdata) package. Caution: In the conversion to csv, strings will be quoted. This can be problem if you are trying to use the \code{comment.char} option of \code{read.table} since the first character of all lines (including comment lines) will be "\"" after conversion. If you have quotes in your data which confuse the process you may wish to use \code{read.xls(..., quote = '')}. This will cause the quotes to be regarded as data and you will have to then handle the quotes yourself after reading the file in. Caution: If you call \code{"xls2csv"} directly, is your responsibility to close and delete the file after using it. } \references{http://www.analytics.washington.edu/statcomp/downloads/xls2csv} \note{ Either a working version of Perl must be present in the executable search path, or the exact path of the perl executable must be provided via the \code{perl} argument. See the examples below for an illustration.} \seealso{ \code{\link[utils]{read.csv}} } \examples{ # iris.xls is included in the gregmisc package for use as an example xlsfile <- file.path(path.package('gdata'),'xls','iris.xls') xlsfile iris <- read.xls(xlsfile) # defaults to csv format iris <- read.xls(xlsfile,method="csv") # specify csv format iris <- read.xls(xlsfile,method="tab") # specify tab format head(iris) # look at the top few rows \dontshow{ iris.1 <- read.xls(xlsfile) # defaults to csv format iris.2 <- read.xls(xlsfile,method="csv") # specify csv format iris.3 <- read.xls(xlsfile,method="tab") # specify tab format stopifnot(all.equal(iris.1, iris.2)) stopifnot(all.equal(iris.1, iris.3)) } \dontrun{ ## Example specifying exact Perl path for default MS-Windows install of ## ActiveState perl iris <- read.xls(xlsfile, perl="C:/perl/bin/perl.exe") } \dontrun{ ## Example specifying exact Perl path for Unix systems iris <- read.xls(xlsfile, perl="/usr/bin/perl") ## finding perl ## (read.xls automatically calls findPerl so this is rarely needed) perl <- gdata:::findPerl("perl") iris <- read.xls(xlsfile, perl=perl) } \dontrun{ ## read xls file from net nba.url <- "http://mgtclass.mgt.unm.edu/Bose/Excel/Tutorial.05/Cases/NBA.xls" nba <- read.xls(nba.url) } \dontrun{ ## read xls file ignoring all lines prior to first containing State crime.url <- "http://www.jrsainfo.org/jabg/state_data2/Tribal_Data00.xls" crime <- read.xls(crime.url, pattern = "State") ## use of xls2csv - open con, print two lines, close con con <- xls2csv(crime.url) print(readLines(con, 2)) file.remove(summary(con)$description) } ## Examples demonstrating selection of specific 'sheets' ## from the example XLS file 'ExampleExcelFile.xls' exampleFile <- file.path(path.package('gdata'),'xls', 'ExampleExcelFile.xls') exampleFile2007 <- file.path(path.package('gdata'),'xls', 'ExampleExcelFile.xlsx') ## see the number and names of sheets: sheetCount(exampleFile) if( 'XLSX' \%in\% xlsFormats() ) ## if XLSX is supported.. sheetCount(exampleFile2007) ## show names of shets in the file sheetNames(exampleFile) if( 'XLSX' \%in\% xlsFormats() ) ## if XLSX is supported.. sheetNames(exampleFile2007) data <- read.xls(exampleFile) ## default is first worksheet data <- read.xls(exampleFile, sheet=2) ## second worksheet by number data <- read.xls(exampleFile, sheet="Sheet Second",v=TRUE) ## and by name ## load the third worksheet, skipping the first two non-data lines... if( 'XLSX' \%in\% xlsFormats() ) ## if XLSX is supported.. data <- read.xls(exampleFile2007, sheet="Sheet with initial text", skip=2) ## load a file containing data and column names using latin-1 ## characters latinFile <- file.path(path.package('gdata'),'xls','latin-1.xls') latin1 <- read.xls(latinFile, fileEncoding="latin1") colnames(latin1) } \author{ Gregory R. Warnes \email{greg@warnes.net}, Jim Rogers \email{james.a.rogers@pfizer.com}, and Gabor Grothendiek \email{ggrothendieck@gmail.com}. } \keyword{file} gdata/man/object.size.Rd0000644000176000001440000000561111367120177014653 0ustar ripleyusers% File src/library/utils/man/object.size.Rd % Part of the R package, http://www.R-project.org % Copyright 1995-2007 R Core Development Team % Distributed under GPL 2 or later \name{object.size} \alias{object.size} \alias{print.object_size} \alias{c.object_size} \alias{as.object_size} \alias{is.object_size} \title{Report the Space Allocated for an Object} \description{ Provides an estimate of the memory that is being used to store an \R object. } \usage{ object.size(\dots) \method{print}{object_size}(x, quote=FALSE, humanReadable, \dots) } \arguments{ \item{\dots}{\code{object.size}: \R objects; \code{print}; arguments to be passed to or from other methods.} \item{x}{output from \code{object.size}} \item{quote}{logical, indicating whether or not the result should be printed with surrounding quotes.} \item{humanReadable}{logical, use the \dQuote{human readable} format.} } \details{ This is a modified copy from the utils package in R as fo 2008-12-15. Exactly which parts of the memory allocation should be attributed to which object is not clear-cut. This function merely provides a rough indication: it should be reasonably accurate for atomic vectors, but does not detect if elements of a list are shared, for example. (Sharing amongst elements of a character vector is taken into account, but not that between character vectors in a single object.) The calculation is of the size of the object, and excludes the space needed to store its name in the symbol table. Associated space (e.g. the environment of a function and what the pointer in a \code{EXTPTRSXP} points to) is not included in the calculation. Object sizes are larger on 64-bit platforms than 32-bit ones, but will very likely be the same on different platforms with the same word length and pointer size. % Modificitaion start Class of returned object is \code{c("byte", "numeric")} with appropriate \code{print} and \code{c} methods. By default \code{object.size} outputs size in bytes, but human readable format similar to \code{ls}, \code{df} or \code{du} shell commands can be invoked with \code{options(humanReadable=TRUE)}. % Modificitaion end } \value{ An object of class \code{"object.size"} with a length-one double value, an estimate of the memory allocation attributable to the object in bytes. } \seealso{ \code{\link{Memory-limits}} for the design limitations on object size. \code{\link{humanReadable}} for human readable format. } \examples{ object.size(letters) object.size(ls) ## find the 10 largest objects in the base package z <- sapply(ls("package:base"), function(x) object.size(get(x, envir = baseenv()))) (tmp <- as.matrix(rev(sort(z))[1:10])) as.object_size(14567567) options(humanReadable=TRUE) (z <- object.size(letters, c(letters, letters), rep(letters, 100), rep(letters, 10000))) is.object_size(z) as.object_size(14567567) } \keyword{utilities} gdata/man/nobs.Rd0000644000176000001440000000576511763743555013422 0ustar ripleyusers% $Id: nobs.Rd 1549 2012-06-06 21:11:07Z warnes $ % % $Log$ % Revision 1.7 2005/09/12 15:42:45 nj7w % Updated Greg's email % % Revision 1.6 2005/06/09 14:20:25 nj7w % Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. % % Revision 1.1.1.1 2005/05/25 22:07:33 nj7w % Initial entry for individual package gdata % % Revision 1.5 2002/09/23 13:59:30 warnes % - Modified all files to include CVS Id and Log tags. % % Revision 1.4 2002/03/26 19:29:15 warneg % % Updated to add ... parameter to function calls. % % Revision 1.3 2002/02/20 21:31:08 warneg % % Noted that specialized methods exist. % % Revision 1.2 2002/02/20 21:29:34 warneg % % Incorrectly had contents of nobs.R here instead of help text. Corrected. % % \name{nobs} \alias{nobs} % Now provided by stats \alias{nobs.data.frame} \alias{nobs.default} \alias{nobs.lm} % Now provided by stats %- Also NEED an `\alias' for EACH other topic documented here. \title{ Compute the Number of Non-missing Observations } \description{ Compute the number of non-missing observations. Provides a 'default' method to handle vectors, and a method for data frames. } \usage{ nobs(object, ...) \method{nobs}{default}(object, ...) \method{nobs}{data.frame}(object, ...) \method{nobs}{lm}(object, ...) } \arguments{ \item{object}{ Target Object } \item{\dots}{ Optional parameters (currently ignored)} } \details{ Calculate the number of observations in \code{object}. \itemize{ \item{For numeric vectors, this is simply the number of non-NA elements, as computed by \code{sum(!is.na(object))}. } \item{For dataframe objects, the result is a vector containing the number of non-NA elementes of each column. } } The \code{nobs} and \code{nobs.lm} functions defined in gtools are simply aliases for the functions in the base R \code{stats} package, provided for backwards compatibility. } \value{ Either single numeric value (for vectors) or a vector of numeric values (for data.frames) giving the number of non-missing values. } \note{ The base R package \code{stats} now provides a S3 dispatch function for \code{nobs}, and methods for for objects of classes "lm", "glm", "nls" and "logLik", as well as a default method. Since they provided a subset of the the functionality, the base method dispatch (\code{nobs}) function and method for "lm" objects (\code{nobs.lm}) are, as of \code{gdata} version 2.10.1, simply aliases for the equivalent functions in the base R \code{stats} package. Since \code{gdata}'s default method (\code{nobs.default}) processes vectors and hands any other data/object types to \code{stats:::nobs.default}. } \author{ Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link{is.na}}, \code{\link{length}} } \examples{ x <- c(1,2,3,5,NA,6,7,1,NA ) length(x) nobs(x) df <- data.frame(x=rnorm(100), y=rnorm(100)) df[1,1] <- NA df[1,2] <- NA df[2,1] <- NA nobs(df) fit <- lm(y ~ x, data=df) nobs(fit) } \keyword{attribute} gdata/man/nPairs.Rd0000644000176000001440000000366411552125074013673 0ustar ripleyusers% nPairs.Rd %-------------------------------------------------------------------------- % What: Number of variable pairs - help % $Id$ % Time-stamp: <2008-12-30 18:30:11 ggorjan> %-------------------------------------------------------------------------- \name{nPairs} \alias{nPairs} \concept{pairs} \title{Number of variable pairs} \description{ \code{nPairs} counts the number of pairs between variables. } \usage{ nPairs(x, margin=FALSE, names=TRUE, abbrev=TRUE, ...) } \arguments{ \item{x}{data.frame or a matrix} \item{margin}{logical, calculate the cumulative number of \dQuote{pairs}} \item{names}{logical, add row/col-names to the output} \item{abbrev}{logical, abbreviate names} \item{\dots}{other arguments passed to \code{\link{abbreviate}}} } \details{ The class of returned matrix is nPairs and matrix. There is a summary method, which shows the opposite information - counts how many times each variable is known, while the other variable of a pair is not. See examples. } \value{ Matrix of order \eqn{k}, where \eqn{k} is the number of columns in \code{x}. Values in a matrix represent the number of pairs between columns/variables in \code{x}. If \code{margin=TRUE}, the number of columns is \eqn{k+1} and the last column represents the cumulative number of pairing all variables. } \author{Gregor Gorjanc} \seealso{\code{\link{abbreviate}}} \examples{ ## Test data test <- data.frame(V1=c(1, 2, 3, 4, 5), V2=c(NA, 2, 3, 4, 5), V3=c(1, NA, NA, NA, NA), V4=c(1, 2, 3, NA, NA)) ## Number of variable pairs nPairs(x=test) ## Without names nPairs(x=test, names=FALSE) ## Longer names colnames(test) <- c("Variable1", "Variable2", "Variable3", "Variable4") nPairs(x=test) ## Margin nPairs(x=test, margin=TRUE) ## Summary summary(object=nPairs(x=test)) } \keyword{misc} %-------------------------------------------------------------------------- % nPairs.Rd ends here gdata/man/matchcols.Rd0000644000176000001440000000542711367120177014416 0ustar ripleyusers\name{matchcols} \alias{matchcols} \title{Select columns names matching certain critera} \description{ This function allows easy selection of the column names of an object using a set of inclusion and exclusion critera. } \usage{ matchcols(object, with, without, method=c("and","or"), ...) } \arguments{ \item{object}{Matrix or dataframe} \item{with, without}{Vector of regular expression patterns} \item{method}{One of "and" or "or"} \item{\dots}{Optional arguments to \code{grep}} } \value{ Vector of column names which match all (\code{method="and"}) or any (\code{method="or"}) of the patterns specified in \code{with}, but none of the patterns specified in \code{without}. } \author{Gregory R. Warnes \email{greg@warnes.net}} \seealso{ \code{\link[base]{grep}} } \examples{ # create a matrix with a lot of named columns x <- matrix( ncol=30, nrow=5 ) colnames(x) <- c("AffyID","Overall Group Means: Control", "Overall Group Means: Moderate", "Overall Group Means: Marked", "Overall Group Means: Severe", "Overall Group StdDev: Control", "Overall Group StdDev: Moderate", "Overall Group StdDev: Marked", "Overall Group StdDev: Severe", "Overall Group CV: Control", "Overall Group CV: Moderate", "Overall Group CV: Marked", "Overall Group CV: Severe", "Overall Model P-value", "Overall Model: (Intercept): Estimate", "Overall Model: Moderate: Estimate", "Overall Model: Marked: Estimate", "Overall Model: Severe: Estimate", "Overall Model: (Intercept): Std. Error", "Overall Model: Moderate: Std. Error", "Overall Model: Marked: Std. Error", "Overall Model: Severe: Std. Error", "Overall Model: (Intercept): t value", "Overall Model: Moderate: t value", "Overall Model: Marked: t value", "Overall Model: Severe: t value", "Overall Model: (Intercept): Pr(>|t|)", "Overall Model: Moderate: Pr(>|t|)", "Overall Model: Marked: Pr(>|t|)", "Overall Model: Severe: Pr(>|t|)") # Get the columns which give estimates or p-values # only for marked and severe groups matchcols(x, with=c("Pr", "Std. Error"), without=c("Intercept","Moderate"), method="or" ) # Get just the column which give the p-value for the intercept matchcols(x, with=c("Intercept", "Pr") ) } \keyword{manip} gdata/man/mapLevels.Rd0000644000176000001440000001614011367120177014363 0ustar ripleyusers% mapLevels.Rd %-------------------------------------------------------------------------- % What: Mapping levels % $Id: mapLevels.Rd,v 1.1 2006/03/29 13:47:10 ggorjan Exp ggorjan $ % Time-stamp: <2006-11-01 00:15:57 ggorjan> %-------------------------------------------------------------------------- \name{mapLevels} \alias{mapLevels} \alias{mapLevels.default} \alias{mapLevels.factor} \alias{mapLevels.character} \alias{mapLevels.list} \alias{mapLevels.data.frame} \alias{print.levelsMap} \alias{print.listLevelsMap} \alias{is.levelsMap} \alias{is.listLevelsMap} \alias{as.levelsMap} \alias{as.listLevelsMap} \alias{.checkLevelsMap} \alias{.checkListLevelsMap} \alias{"[.levelsMap"} \alias{"[.listLevelsMap"} \alias{c.levelsMap} \alias{c.listLevelsMap} \alias{unique.levelsMap} \alias{sort.levelsMap} \alias{mapLevels<-} \alias{mapLevels<-.default} \alias{mapLevels<-.factor} \alias{mapLevels<-.character} \alias{mapLevels<-.list} \alias{mapLevels<-.data.frame} \title{Mapping levels} \description{ \code{mapLevels} produces a map with information on levels and/or internal integer codes. As such can be conveniently used to store level mapping when one needs to work with internal codes of a factor and later transfrorm back to factor or when working with several factors that should have the same levels and therefore the same internal coding. } \usage{ mapLevels(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, \dots) mapLevels(x) <- value } \arguments{ \item{x}{object whose levels will be mapped, look into details} \item{codes}{boolean, create integer levelsMap (with internal codes) or character levelsMap (with level names)} \item{sort}{boolean, sort levels of character \code{x}, look into details} \item{drop}{boolean, drop unused levels} \item{combine}{boolean, combine levels, look into details} \item{\dots}{additional arguments for \code{sort}} \item{value}{levelsMap or listLevelsMap, output of \code{mapLevels} methods or constructed by user, look into details} } \section{mapLevels}{ \code{mapLevels} function was written primarly for work with \dQuote{factors}, but is generic and can also be used with \dQuote{character}, \dQuote{list} and \dQuote{data.frame}, while \dQuote{default} method produces error. Here the term levels is also used for unique character values. When \code{codes=TRUE} \bold{integer \dQuote{levelsMap}} with information on mapping internal codes with levels is produced. Output can be used to transform integer to factor or remap factor levels as described bellow. With \code{codes=FALSE} \bold{character \dQuote{levelsMap}} is produced. The later is usefull, when one would like to remap factors or combine factors with some overlap in levels as described in \code{mapLevels<-} section and shown in examples. \code{sort} argument provides possibility to sort levels of \dQuote{character} \code{x} and has no effect when \code{x} is a \dQuote{factor}. Argument \code{combine} has effect only in \dQuote{list} and \dQuote{data.frame} methods and when \code{codes=FALSE} i.e. with \bold{character \dQuote{levelsMaps}}. The later condition is necesarry as it is not possible to combine maps with different mapping of level names and integer codes. It is assumed that passed \dQuote{list} and \dQuote{data.frame} have all components for which methods exist. Otherwise error is produced. } \section{levelsMap and listLevelsMap}{ Function \code{mapLevels} returns a map of levels. This map is of class \dQuote{levelsMap}, which is actually a list of length equal to number of levels and with each component of length 1. Components need not be of length 1. There can be either integer or character \dQuote{levelsMap}. \bold{Integer \dQuote{levelsMap}} (when \code{codes=TRUE}) has names equal to levels and components equal to internal codes. \bold{Character \dQuote{levelsMap}} (when \code{codes=FALSE}) has names and components equal to levels. When \code{mapLevels} is applied to \dQuote{list} or \dQuote{data.frame}, result is of class \dQuote{listLevelsMap}, which is a list of \dQuote{levelsMap} components described previously. If \code{combine=TRUE}, result is a \dQuote{levelsMap} with all levels in \code{x} components. For ease of inspection, print methods unlists \dQuote{levelsMap} with proper names. \code{mapLevels<-} methods are fairly general and therefore additional convenience methods are implemented to ease the work with maps: \code{is.levelsMap} and \code{is.listLevelsMap}; \code{as.levelsMap} and \code{as.listLevelsMap} for coercion of user defined maps; generic \code{"["} and \code{c} for both classes (argument \code{recursive} can be used in \code{c} to coerce \dQuote{listLevelsMap} to \dQuote{levelsMap}) and generic \code{unique} and \code{sort} (generic from \R 2.4) for \dQuote{levelsMap}. } \section{mapLevels<-}{ Workhorse under \code{mapLevels<-} methods is \code{\link{levels<-}}. \code{mapLevels<-} just control the assignment of \dQuote{levelsMap} (integer or character) or \dQuote{listLevelsMap} to \code{x}. The idea is that map values are changed to map names as indicated in \code{\link{levels}} examples. \bold{Integer \dQuote{levelsMap}} can be applied to \dQuote{integer} or \dQuote{factor}, while \bold{character \dQuote{levelsMap}} can be applied to \dQuote{character} or \dQuote{factor}. Methods for \dQuote{list} and \dQuote{data.frame} can work only on mentioned atomic components/columns and can accept either \dQuote{levelsMap} or \dQuote{listLevelsMap}. Recycling occurs, if length of \code{value} is not the same as number of components/columns of a \dQuote{list/data.frame}. } \value{ \code{mapLevels()} returns \dQuote{levelsMap} or \dQuote{listLevelsMap} objects as described in levelsMap and listLevelsMap section. Result of \code{mapLevels<-} is always a factor with remapped levels or a \dQuote{list/data.frame} with remapped factors. } \author{Gregor Gorjanc} \seealso{ \code{\link{factor}}, \code{\link{levels}} and \code{\link{unclass}} } \examples{ ## --- Integer levelsMap --- (f <- factor(sample(letters, size=20, replace=TRUE))) (mapInt <- mapLevels(f)) ## Integer to factor (int <- as.integer(f)) (mapLevels(int) <- mapInt) all.equal(int, f) ## Remap levels of a factor (fac <- factor(as.integer(f))) (mapLevels(fac) <- mapInt) # the same as levels(fac) <- mapInt all.equal(fac, f) ## --- Character levelesMap --- f1 <- factor(letters[1:10]) f2 <- factor(letters[5:14]) ## Internal codes are the same, but levels are not as.integer(f1) as.integer(f2) ## Get character levelsMaps and combine them mapCha1 <- mapLevels(f1, codes=FALSE) mapCha2 <- mapLevels(f2, codes=FALSE) (mapCha <- c(mapCha1, mapCha2)) ## Remap factors mapLevels(f1) <- mapCha # the same as levels(f1) <- mapCha mapLevels(f2) <- mapCha # the same as levels(f2) <- mapCha ## Internal codes are now "consistent" among factors as.integer(f1) as.integer(f2) ## Remap characters to get factors f1 <- as.character(f1); f2 <- as.character(f2) mapLevels(f1) <- mapCha mapLevels(f2) <- mapCha ## Internal codes are now "consistent" among factors as.integer(f1) as.integer(f2) } \keyword{misc} \keyword{manip} %-------------------------------------------------------------------------- % mapLevels.Rd ends here gdata/man/ls.funs.Rd0000644000176000001440000000156311751060431014017 0ustar ripleyusers\name{ls.funs} \alias{ls.funs} \title{List function objects} \description{ Return a character vector giving the names of function objects in the specified environment. } \usage{ ls.funs(...) } \arguments{ \item{\dots}{Arguments passed to \code{ls}. See the help for \code{\link[base]{ls}} for details.} } \details{ This function calls \code{ls} and then returns a character vector containing only the names of only function objects. } \value{ character vector } \author{ Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link[base]{ls}}, \code{\link[base]{is.function}} } \examples{ ## List functions defined in the global environment: ls.funs() ## List functions available in the base package: ls.funs("package:base") } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{misc} \keyword{environment} gdata/man/ll.Rd0000644000176000001440000000401611367120176013040 0ustar ripleyusers\name{ll} \alias{ll} \title{Describe Objects or Elements} \description{ Display name, class, size, and dimensions of each object in a given environment. Alternatively, if the main argument is a list-like object, its elements are listed and described. } \usage{ ll(pos=1, unit="KB", digits=0, dim=FALSE, sort=FALSE, class=NULL, invert=FALSE, ...) } \arguments{ \item{pos}{environment position number, environment name, data frame, list, model, or any object that \code{is.list}.} \item{unit}{unit for displaying object size: "bytes", "KB", "MB", or first letter.} \item{digits}{number of decimals to display when rounding object size.} \item{dim}{whether object dimensions should be returned.} \item{sort}{whether elements should be sorted by name.} \item{class}{character vector for limiting the output to specified classes.} \item{invert}{whether to invert the \code{class} filter, so specified classes are excluded.} \item{...}{passed to \code{ls}.} } \value{ A data frame with named rows and the following columns: \item{Class}{object class.} \item{KB}{object size \emph{(see note)}.} \item{Dim}{object dimensions \emph{(optional)}.} } \note{The name of the object size column is the same as the unit used.} \author{Arni Magnusson, with a contribution by Jim Rogers} \seealso{ \code{ll} is a verbose alternative to \code{\link{ls}} (objects in an environment) and \code{\link{names}} (elements in a list-like object). \code{\link{str}} and \code{\link{summary}} also describe elements in a list-like objects. \code{\link{env}} is a related function that describes all loaded environments. } \examples{ ll() ll(all=TRUE) ll("package:base") ll("package:base", class="function", invert=TRUE) data(infert) ll(infert) model <- glm(case~spontaneous+induced, family=binomial, data=infert) ll(model, dim=TRUE) ll(model, sort=TRUE) ll(model$family) } % Basics \keyword{data} \keyword{attribute} \keyword{classes} \keyword{list} % Programming \keyword{environment} \keyword{print} \keyword{utilities} gdata/man/keep.Rd0000644000176000001440000000232511367120176013356 0ustar ripleyusers\name{keep} \alias{keep} \title{Remove All Objects, Except Those Specified} \description{ Remove all objects from the user workspace, except those specified. } \usage{ keep(..., list=character(0), all=FALSE, sure=FALSE) } \arguments{ \item{...}{objects to be kept, specified one by one, quoted or unquoted.} \item{list}{character vector of object names to be kept.} \item{all}{whether hidden objects (beginning with a \code{.}) should be removed, unless explicitly kept.} \item{sure}{whether to perform the removal, otherwise return names of objects that would have been removed.} } \details{ Implemented with safety caps: objects whose name starts with a \code{.} are not removed unless \code{all=TRUE}, and an explicit \code{sure=TRUE} is required to remove anything. } \value{ A character vector containing object names, or \code{NULL} when \code{sure} is \code{TRUE}. } \author{Arni Magnusson} \seealso{ \code{keep} is a convenient interface to \code{\link{rm}} when removing most objects from the user workspace. } \examples{ data(women, cars) keep(cars) ## To remove all objects except cars, run: ## keep(cars, sure=TRUE) } % Programming \keyword{data} \keyword{environment} \keyword{utilities} gdata/man/is.what.Rd0000644000176000001440000000223511751060431014001 0ustar ripleyusers\name{is.what} \alias{is.what} \title{Run Multiple is.* Tests on a Given Object} \description{ Run multiple \code{is.*} tests on a given object: \code{is.na}, \code{is.numeric}, and many others. } \usage{ is.what(object, verbose=FALSE) } \arguments{ \item{object}{any \R object.} \item{verbose}{whether negative tests should be included in output.} } \value{ A character vector containing positive tests, or when \code{verbose} is \code{TRUE}, a data frame showing all test results. } \author{Arni Magnusson, inspired by \code{demo(is.things)}.} \note{ The following procedure is used to look for valid tests: \enumerate{ \item{}{Find all objects named \code{is.*} in all loaded environments.} \item{}{Discard objects that are not functions.} \item{}{Include test result only if it is of class \code{"logical"}, not an \code{NA}, and of length 1.} } } \seealso{ \code{\link{is.na}} and \code{\link{is.numeric}} are commonly used tests. } \examples{ is.what(pi) is.what(NA, verbose=TRUE) is.what(lm(1~1)) is.what(is.what) } % Basics \keyword{classes} \keyword{NA} % Programming \keyword{programming} \keyword{error} \keyword{utilities} gdata/man/interleave.Rd0000644000176000001440000000653112023721011014554 0ustar ripleyusers% $Id: interleave.Rd 1603 2012-09-11 20:41:43Z warnes $ % % $Log$ % Revision 1.8 2005/12/12 22:02:48 nj7w % Updated version number for CRAN release % % Revision 1.7 2005/12/04 03:02:06 warnes % Andrew Burgess reported that interleave() converts 1-column matrixes % to vectors and provided a patch. A slight modification of his patch % has been applied. There is now a 'drop' argument, which controls % whether 'unnecessary' dimensions are dropped. The default is FALSE. % % Revision 1.6 2005/09/12 15:42:45 nj7w % Updated Greg's email % % Revision 1.5 2005/06/09 14:20:25 nj7w % Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. % % Revision 1.1.1.1 2005/05/25 22:07:33 nj7w % Initial entry for individual package gdata % % Revision 1.4 2003/06/07 17:58:37 warnes % % - Fixed error in examples. Had sqrt(var(x)/(n-1)) for the standard % error of the mean instead of sqrt(var(x)/n). % % Revision 1.3 2002/09/23 13:59:30 warnes % - Modified all files to include CVS Id and Log tags. % % Revision 1.2 2002/04/09 00:51:32 warneg % % Checkin for version 0.5.3 % % Revision 1.1 2002/02/20 21:41:54 warneg % Initial checkin. % % \name{interleave} \alias{interleave} \title{ Interleave Rows of Data Frames or Matrices } \description{ Interleave rows of data frames or Matrices. } \usage{ interleave(..., append.source=TRUE, sep=": ", drop=FALSE) } \arguments{ \item{\dots}{ objects to be interleaved } \item{append.source}{Boolean Flag. When \code{TRUE} (the default) the argument name will be appended to the row names to show the source of each row. } \item{sep}{Separator between the original row name and the object name.} \item{drop}{boolean flag - When TRUE, matrices containing one column will be converted to vectors.} } \details{ This function creates a new matrix or data frame from its arguments. The new object will have all of the rows from the source objects interleaved. IE, it will contain row 1 of object 1, followed by row 1 of object 2, .. row 1 of object 'n', row 2 of object 1, row 2 of object 2, ... row 2 of object 'n' ... } \value{ Matrix containing the interleaved rows of the function arguments. } \author{ Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link{cbind}}, \code{\link{rbind}}, \code{\link{combine}} } \examples{ # Simple example a <- matrix(1:10,ncol=2,byrow=TRUE) b <- matrix(letters[1:10],ncol=2,byrow=TRUE) c <- matrix(LETTERS[1:10],ncol=2,byrow=TRUE) interleave(a,b,c) # Useful example: # # Create a 2-way table of means, standard errors, and # obs g1 <- sample(letters[1:5], 1000, replace=TRUE) g2 <- sample(LETTERS[1:3], 1000, replace=TRUE ) dat <- rnorm(1000) stderr <- function(x) sqrt( var(x,na.rm=TRUE) / nobs(x) ) means <- tapply(dat, list(g1, g2), mean ) stderrs <- tapply(dat, list(g1, g2), stderr ) ns <- tapply(dat, list(g1, g2), nobs ) blanks <- matrix( " ", nrow=5, ncol=3) tab <- interleave( "Mean"=round(means,2), "Std Err"=round(stderrs,2), "N"=ns, " " = blanks, sep=" " ) print(tab, quote=FALSE) # Using drop to control coercion to a lower dimensions: m1 <- matrix(1:4) m2 <- matrix(5:8) interleave(m1, m2, drop=TRUE) # This will be coerced to a vector interleave(m1, m2, drop=FALSE) # This will remain a matrix } \keyword{category} \keyword{array} gdata/man/installXLSXsupport.Rd0000644000176000001440000000540111764454211016253 0ustar ripleyusers\name{installXLSXsupport} \Rdversion{1.1} \alias{installXLSXsupport} \title{ Install perl modules needed for read.xls to support Excel 2007+ XLSX format } \description{ Install perl modules needed for read.xls to support Excel 2007+ XLSX format } \usage{ installXLSXsupport(perl = "perl", verbose = FALSE) } \arguments{ \item{perl}{Path to perl interpreter (optional).} \item{verbose}{If \code{TRUE}, show additional messages during processing.} } \value{ Either \code{TRUE} indicating that the necessary perl modules have been successfully installed, or \code{FALSE} indicating that an error has occured. } \details{ This function calls the perl script 'install_modules.pl' located in the perl subdirectory of the gdata package directory (or inst/perl in the source package). This perl script attempts to use the perl 'CPAN' package, which should be included as part of most perl installations, to automatically download, compile, and install the Compress::Raw::Zlib and Spreadsheet::XLSX perl modules needed for read.xls to support support Excel 2007+ XLSX files into the gdata perl subdirectory. Since the perl modules are installed into the gdata installation directory, the perl modules will be available until the gdata package is replaced or removed. Since this occurs each time a new version of gdata is installed, \code{installXLSXsupport} will need to be run each time a new version of the gdata package is installed. Further, the binary Compress::Raw::Zlib package installed by \code{installXLSXsupport} is tied to the particular version of perl used to compile it, therefore, you will need to re-run \code{installXLSXsupport} if you install a different perl distribution. This installation process will fail if 1) perl is not available on the search path and the \code{perl} argument is not used to specify the path of the perl executable, 2) the perl installation is not properly configured for installing binary packages*, 3) if the CPAN module is not present, or 4) if the C compiler specified by the perl installation is not present. \emph{In particular, \code{installXLSXsupport} will fail for the version of perl included with the current RTools.zip package, which is not correctly configured to allow installation of additional perl packages. (The RTools version of perl is installed in a different directory than the perl configuration files expect.)} The function \code{xlsFormats} can be used to see whether XLS and XLSX formats are supported by the currently available perl modules. } \seealso{ \code{\link{read.xls}}, \code{\link{xls2csv}}, \code{\link{xlsFormats}} } \examples{ \dontrun{ installXLSXsupport() } } \keyword{ misc } gdata/man/humanReadable.Rd0000644000176000001440000001135711367120176015167 0ustar ripleyusers% humanReadable.Rd %-------------------------------------------------------------------------- % What: Print byte size in human readable format man page % $Id$ % Time-stamp: <2008-12-30 13:26:35 ggorjan> %-------------------------------------------------------------------------- \name{humanReadable} \alias{humanReadable} \title{Print byte size in human readable format} \description{ \code{humanReadable} converts byte size in human readable format such as kB, MB, GB, etc. } \usage{ humanReadable(x, standard="SI", digits=1, width=3, sep=" ") } \arguments{ \item{x}{integer, byte size} \item{standard}{character, "SI" for powers of 1000 or anything else for powers of 1024, see details} \item{digits}{integer, number of digits after decimal point} \item{width}{integer, width of number string} \item{sep}{character, separator between number and unit} } \details{ Basic unit used to store information in computers is a bit. Bits are represented as zeroes and ones - binary number system. Although, the binary number system is not the same as the decimal number system, decimal prefixes for binary multiples such as kilo and mega are often used. In the decimal system kilo represent 1000, which is close to \eqn{1024 = 2^{10}} in the binary system. This sometimes causes problems as it is not clear which powers (2 or 10) are used in a notation like 1 kB. To overcome this problem International Electrotechnical Commission (IEC) has provided the following solution to this problem: \tabular{lrcll}{ Name \tab System \tab Symbol \tab Size \tab Conversion \cr byte \tab binary \tab B \tab \eqn{2^3} \tab 8 bits \cr kilobyte \tab decimal \tab kB \tab \eqn{10^3} \tab 1000 bytes \cr kibibyte \tab binary \tab KiB \tab \eqn{2^{10}} \tab 1024 bytes \cr megabyte \tab decimal \tab MB \tab \eqn{(10^3)^2} \tab 1000 kilobytes\cr mebibyte \tab binary \tab MiB \tab \eqn{(2^{10})^2} \tab 1024 kibibytes\cr gigabyte \tab decimal \tab GB \tab \eqn{(10^3)^3} \tab 1000 megabytes\cr gibibyte \tab binary \tab GiB \tab \eqn{(2^{10})^3} \tab 1024 mebibytes\cr terabyte \tab decimal \tab TB \tab \eqn{(10^3)^4} \tab 1000 gigabytes\cr tebibyte \tab binary \tab TiB \tab \eqn{(2^{10})^4} \tab 1024 gibibytes\cr petabyte \tab decimal \tab PB \tab \eqn{(10^3)^5} \tab 1000 terabytes\cr pebibyte \tab binary \tab PiB \tab \eqn{(2^{10})^5} \tab 1024 tebibytes\cr exabyte \tab decimal \tab EB \tab \eqn{(10^3)^6} \tab 1000 petabytes\cr exbibyte \tab binary \tab EiB \tab \eqn{(2^{10})^6} \tab 1024 pebibytes\cr zettabyte \tab decimal \tab ZB \tab \eqn{(10^3)^7} \tab 1000 exabytes\cr zebibyte \tab binary \tab ZiB \tab \eqn{(2^{10})^7} \tab 1024 exbibytes\cr yottabyte \tab decimal \tab YB \tab \eqn{(10^3)^8} \tab 1000 zettabytes\cr yebibyte \tab binary \tab YiB \tab \eqn{(2^{10})^8} \tab 1024 zebibytes\cr } where Zi and Yi are GNU extensions to IEC. To get the output in the decimal system (powers of 1000) use \code{standard="SI"}. Otherwise IEC standard (powers of 1024) is used. For printout both \code{digits} and \code{width} can be specified. If \code{width} is \code{NULL}, all values have given number of digits. If \code{width} is not \code{NULL}, output is rounded to a given width and formated similar to human readable format of \code{ls}, \code{df} or \code{du} shell commands. } \references{ Wikipedia: \url{http://en.wikipedia.org/wiki/Byte} \url{http://en.wikipedia.org/wiki/SI_prefix} \url{http://en.wikipedia.org/wiki/Binary_prefix} GNU manual for coreutils: \url{http://www.gnu.org/software/coreutils/manual/html_node/Block-size.html#Block-size} } \value{ Byte size in human readable format as character with proper unit symbols added at the end of the string. } \author{Ales Korosec and Gregor Gorjanc} \seealso{ \code{\link{object.size}}, \code{\link[gdata]{ll}} } \examples{ baseSI <- 10 powerSI <- seq(from=3, to=27, by=3) SI0 <- (baseSI)^powerSI k <- length(SI0) - 1 SI1 <- SI0 - SI0 / c(2, runif(n=k, min=1.01, max=5.99)) SI2 <- SI0 + SI0 / c(2, runif(n=k, min=1.01, max=5.99)) baseIEC <- 2 powerIEC <- seq(from=10, to=90, by=10) IEC0 <- (baseIEC)^powerIEC IEC1 <- IEC0 - IEC0 / c(2, runif(n=k, min=1.01, max=5.99)) IEC2 <- IEC0 + IEC0 / c(2, runif(n=k, min=1.01, max=5.99)) cbind(humanReadable(x=SI1, width=NULL, digits=3), humanReadable(x=SI0, width=NULL, digits=2), humanReadable(x=SI2, width=NULL, digits=1), humanReadable(x=IEC1, standard="IEC", width=7, digits=3), humanReadable(x=IEC0, standard="IEC", width=7, digits=2), humanReadable(x=IEC2, standard="IEC", width=7, digits=1)) } \keyword{misc} %-------------------------------------------------------------------------- % humanReadable.Rd ends here gdata/man/getDateTimePart.Rd0000644000176000001440000000363011367120176015455 0ustar ripleyusers% getDateTimeParts.Rd %-------------------------------------------------------------------------- % What: Extract date and time parts from ... - help % $Id$ % Time-stamp: <2008-12-30 22:44:20 ggorjan> %-------------------------------------------------------------------------- \name{getYear} \alias{getDateTimeParts} \alias{getYear} \alias{getYear.default} \alias{getYear.Date} \alias{getYear.POSIXct} \alias{getYear.POSIXlt} \alias{getMonth} \alias{getMonth.default} \alias{getMonth.Date} \alias{getMonth.POSIXct} \alias{getMonth.POSIXlt} \alias{getDay} \alias{getDay.default} \alias{getDay.Date} \alias{getDay.POSIXct} \alias{getDay.POSIXlt} \alias{getHour} \alias{getHour.default} \alias{getMin} \alias{getMin.default} \alias{getSec} \alias{getSec.default} \title{Get date/time parts from date and time objects} \description{get* functions provide an *experimental* approach for extracting the date/time parts from objects of a date/time class. They are designed to be intiutive and thus lowering the learning curve for work with date and time classes in \R{}.} \usage{ getYear(x, format, \dots) getMonth(x, format, \dots) getDay(x, format, \dots) getHour(x, format, \dots) getMin(x, format, \dots) getSec(x, format, \dots) } \arguments{ \item{x}{generic, date/time object} \item{format}{character, format} \item{\dots}{arguments pased to other methods} } \value{Character} \author{Gregor Gorjanc} \seealso{ \code{\link{Date}}, \code{\link{DateTimeClasses}}, \code{\link{strptime}} } \examples{ ## --- Date class --- tmp <- Sys.Date() tmp getYear(tmp) getMonth(tmp) getDay(tmp) ## --- POSIXct class --- tmp <- as.POSIXct(tmp) getYear(tmp) getMonth(tmp) getDay(tmp) ## --- POSIXlt class --- tmp <- as.POSIXlt(tmp) getYear(tmp) getMonth(tmp) getDay(tmp) } \keyword{manip} \keyword{misc} %-------------------------------------------------------------------------- % getDateTimeParts.Rd ends heregdata/man/gdata-package.Rd0000644000176000001440000000207711367120176015107 0ustar ripleyusers \name{gdata-package} \alias{gdata-package} \alias{gdata} \docType{package} \title{Various R programming tools for data manipulation} \description{ \pkg{gdata} package provides various \R programming tools for data manipulation. } \details{ The following are sources of information on \pkg{gdata} package: \tabular{ll}{ DESCRIPTION file\tab \code{library(help="gdata")}\cr \tab \cr This file\tab \code{package?gdata}\cr \tab \cr Vignette\tab \code{vignette("unknown")}\cr \tab \code{vignette("mapLevels")}\cr \tab \cr Some help files\tab \code{\link{read.xls}}\cr \tab \code{\link{write.fwf}}\cr \tab \cr News\tab \code{file.show(system.file("NEWS", package="gdata"))}\cr } } \section{Testing}{ If you want to perform the validity/unit testing of the installed \pkg{ggmisc} package on your own computer, take a look at \code{\link{.runRUnitTestsGdata}} function - please note that you need the \pkg{RUnit} package for this to work. } \keyword{package}gdata/man/frameApply.Rd0000644000176000001440000000753211367120176014537 0ustar ripleyusers% $Id% % \name{frameApply} \alias{frameApply} \title{Subset analysis on data frames} \description{Apply a function to row subsets of a data frame. } \usage{ frameApply(x, by=NULL, on=by[1], fun=function(xi) c(Count=nrow(xi)), subset=TRUE, simplify=TRUE, byvar.sep="\\\\$\\\\@\\\\$", ...) } \arguments{ \item{x}{a data frame} \item{by}{names of columns in \code{x} specifying the variables to use to form the subgroups. None of the \code{by} variables should have the name "sep" (you will get an error if one of them does; a bit of laziness in the code). Unused levels of the \code{by} variables will be dropped. Use \code{by = NULL} (the default) to indicate that all of the data is to be treated as a single (trivial) subgroup.} \item{on}{names of columns in \code{x} specifying columns over which \code{fun} is to be applied. These can include columns specified in \code{by}, (as with the default) although that is not usually the case.} \item{fun}{a function that can operate on data frames that are row subsets of \code{x[on]}. If \code{simplify = TRUE}, the return value of the function should always be either a try-error (see \code{\link{try}}), or a vector of fixed length (i.e. same length for every subset), preferably with named elements.} \item{subset}{logical vector (can be specified in terms of variables in data). This row subset of \code{x} is taken before doing anything else.} \item{simplify}{logical. If TRUE (the default), return value will be a data frame including the \code{by} columns and a column for each element of the return vector of \code{fun}. If FALSE, the return value will be a list, sometimes necessary for less structured output (see description of return value below).} \item{byvar.sep}{character. This can be any character string not found anywhere in the values of the \code{by} variables. The \code{by} variables will be pasted together using this as the separator, and the result will be used as the index to form the subgroups. } \item{...}{additional arguments to \code{fun}.} } \value{a data frame if \code{simplify = TRUE} (the default), assuming there is sufficiently structured output from \code{fun}. If \code{simplify = FALSE} and \code{by} is not NULL, the return value will be a list with two elements. The first element, named "by", will be a data frame with the unique rows of \code{x[by]}, and the second element, named "result" will be a list where the ith component gives the result for the ith row of the "by" element. } \details{This function accomplishes something similar to \code{\link{by}}. The main difference is that \code{frameApply} is designed to return data frames and lists instead of objects of class 'by'. Also, \code{frameApply} works only on the unique combinations of the \code{by} that are actually present in the data, not on the entire cartesian product of the \code{by} variables. In some cases this results in great gains in efficiency, although \code{frameApply} is hardly an efficient function.} \examples{ data(ELISA, package="gtools") # Default is slightly unintuitive, but commonly useful: frameApply(ELISA, by = c("PlateDay", "Read")) # Wouldn't actually recommend this model! Just a demo: frameApply(ELISA, on = c("Signal", "Concentration"), by = c("PlateDay", "Read"), fun = function(dat) coef(lm(Signal ~ Concentration, data = dat))) frameApply(ELISA, on = "Signal", by = "Concentration", fun = function(dat, ...) { x <- dat[[1]] out <- c(Mean = mean(x, ...), SD = sd(x, ...), N = sum(!is.na(x))) }, na.rm = TRUE, subset = !is.na(Concentration)) } \author{Jim Rogers \email{james.a.rogers@pfizer.com}} \keyword{manip} gdata/man/env.Rd0000644000176000001440000000166711367120175013231 0ustar ripleyusers\name{env} \alias{env} \title{Describe All Loaded Environments} \description{ Display name, number of objects, and size of all loaded environments. } \usage{ env(unit="KB", digits=0) } \arguments{ \item{unit}{unit for displaying environment size: "bytes", "KB", "MB", or first letter.} \item{digits}{number of decimals to display when rounding environment size.} } \value{ A data frame with the following columns: \item{Environment}{environment name.} \item{Objects}{number of objects in environment.} \item{KB}{environment size \emph{(see notes)}.} } \note{ The name of the environment size column is the same as the unit used. } \author{Arni Magnusson} \seealso{ \code{env} is a verbose alternative to \code{\link{search}}. \code{\link{ll}} is a related function that describes objects in an environment. } \examples{ \dontrun{ env() } } % Basics \keyword{data} % Programming \keyword{environment} \keyword{utilities} gdata/man/elem.Rd0000644000176000001440000000334411367120175013355 0ustar ripleyusers\name{elem} \alias{elem} \title{ Display Information about Elements in a Given Object } \description{ \emph{This function is depreciated. Please use \code{\link{ll}} instead.} Display name, class, size, and dimensions of each element in a given object. } \usage{ elem(object=1, unit=c("KB","MB","bytes"), digits=0, dimensions=FALSE) } \arguments{ \item{object}{object containing named elements, perhaps a model or data frame.} \item{unit}{required unit for displaying element size: "KB", "MB", "bytes", or first letter.} \item{digits}{number of decimals to display when rounding element size.} \item{dimensions}{whether element dimensions should be returned.} } \details{ A verbose alternative to \code{names()}. } \value{ A data frame with named rows and the following columns: \item{Class}{element class.} \item{KB}{element size \emph{(see notes)}.} \item{Dim}{element dimensions \emph{(optional)}.} } \note{ The name of the element size column is the same as the unit used. Elements of class \code{classRepresentation}, \code{ClassUnionRepresentation}, and \code{grob} do not have a defined size, so 0 bytes are assumed for those. } \author{Arni Magnusson \email{arnima@u.washington.edu}} \seealso{ \code{\link[base]{names}}, \code{\link[utils]{str}}, and \code{\link[base]{summary}} display different information about object elements. \code{\link{ll}} and \code{\link{env}} are related to \code{elem}. } \examples{ \dontrun{ data(infert) elem(infert) model <- glm(case~spontaneous+induced, family=binomial, data=infert) elem(model, dim=TRUE) elem(model$family) } } % Basics \keyword{attribute} \keyword{classes} \keyword{list} % Programming \keyword{print} \keyword{utilities} gdata/man/duplicated2.Rd0000644000176000001440000000362412143472607014637 0ustar ripleyusers\name{duplicated2} \alias{duplicated2} \title{Determine Duplicate Elements} \description{ \code{duplicated2()} determines which elements of a vector or data frame are duplicates, and returns a logical vector indicating which elements (rows) are duplicates. } \usage{ duplicated2(x, bothWays=TRUE, ...) } \arguments{ \item{x}{a vector or a data frame or an array or \code{NULL}.} \item{bothWays}{if \code{TRUE} (the default), duplication should be considered from both sides. For more information see the argument \code{fromLast} to the function \code{\link{duplicated}}.} \item{\dots}{further arguments passed down to \code{duplicated()} and its methods.} } \details{ The standard \code{\link{duplicated}} function (in \code{package:base}) only returns \code{TRUE} for the second and following copies of each duplicated value (second-to-last and earlier when \code{fromLast=TRUE}). This function returns all duplicated elementes, including the first (last) value. When \code{bothWays} is \code{FALSE}, \code{duplicated2()} defaults to a \code{\link{duplicated}} call. When \code{bothWays} is \code{TRUE}, the following call is being executed: \code{duplicated(x, ...) | duplicated(x, fromLast=TRUE, ...)} } \value{ For a vector input, a logical vector of the same length as \code{x}. For a data frame, a logical vector with one element for each row. For a matrix or array, and when \code{MARGIN = 0}, a logical array with the same dimensions and dimnames. For more details see \code{\link{duplicated}}. } \seealso{ \code{\link[base]{duplicated}}, \code{\link[base]{unique}} } \author{Liviu Andronic} \examples{ data(iris) iris[duplicated(iris), ] # 2nd duplicated value iris[duplicated(iris, fromLast=TRUE), ] # 1st duplicated value iris[duplicated2(iris), ] # both duplicated values } \keyword{logic} \keyword{manip} gdata/man/drop.levels.Rd0000644000176000001440000000213511367120175014665 0ustar ripleyusers% $Id: drop.levels.Rd 1096 2007-06-06 10:19:15Z ggorjan $ \name{drop.levels} \alias{drop.levels} \title{Drop unused factor levels} \description{Drop unused levels in a factor} \usage{ drop.levels(x, reorder=TRUE, ...) } \arguments{ \item{x}{object to be processed} \item{reorder}{should factor levels be reordered using \code{\link{reorder.factor}}?} \item{...}{additional arguments to \code{\link{reorder.factor}}} } \details{ \code{drop.levels} is a generic function, where default method does nothing, while method for factor \code{s} drops all unused levels. Drop is done with \code{x[, drop=TRUE]}. There are also convenient methods for \code{list} and \code{data.frame}, where all unused levels are dropped in all factors (one by one) in a \code{list} or a \code{data.frame}. } \value{Input object without unused levels.} \author{Jim Rogers \email{james.a.rogers@pfizer.com} and Gregor Gorjanc} \examples{ f <- factor(c("A", "B", "C", "D"))[1:3] drop.levels(f) l <- list(f=f, i=1:3, c=c("A", "B", "D")) drop.levels(l) df <- as.data.frame(l) str(df) str(drop.levels(df)) } \keyword{manip} gdata/man/combine.Rd0000644000176000001440000000507011367213617014051 0ustar ripleyusers% $Id: combine.Rd 1435 2010-05-02 06:11:26Z warnes $ % % $Log$ % Revision 1.4 2005/12/01 16:41:14 nj7w % Updated Greg's email address % % Revision 1.3 2005/06/09 14:20:25 nj7w % Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. % % Revision 1.1.1.1 2005/05/25 22:07:33 nj7w % Initial entry for individual package gdata % % Revision 1.2 2002/09/23 13:59:30 warnes % - Modified all files to include CVS Id and Log tags. % % \name{combine} \alias{combine} \title{ Combine R Objects With a Column Labeling the Source} \description{ Take a sequence of vector, matrix or data frames and combine into rows of a common data frame with an additional column \code{source} indicating the source object. } \usage{ combine(..., names=NULL) } \arguments{ \item{\dots}{vectors or matrices to combine.} \item{names}{character vector of names to use when creating source column.} } \details{ If there are several matrix arguments, they must all have the same number of columns. The number of columns in the result will be one larger than the number of columns in the component matrixes. If all of the arguments are vectors, these are treated as single column matrixes. In this case, the column containing the combineinated vector data is labeled \code{data}. When the arguments consist of a mix of matrices and vectors the number of columns of the result is determined by the number of columns of the matrix arguments. Vectors are considered row vectors and have their values recycled or subsetted (if necessary) to achieve this length. The \code{source} column is created as a factor with levels corresponding to the name of the object from which the each row was obtained. When the \code{names} argument is ommitted, the name of each object is obtained from the specified argument name in the call (if present) or from the name of the object. See below for examples. } % \value{ % ~Describe the value returned % If it is a LIST, use % \item{comp1 }{Description of `comp1'} % \item{comp2 }{Description of `comp2'} % ... % } %\references{ ~put references to the literature/web site here ~ } \author{Gregory R. Warnes \email{greg@warnes.net}} %\note{ ~~further notes~~ } \seealso{ \code{\link{rbind}}, \code{\link{merge}}} \examples{ a <- matrix(rnorm(12),ncol=4,nrow=3) b <- 1:4 combine(a,b) combine(x=a,b) combine(x=a,y=b) combine(a,b,names=c("one","two")) c <- 1:6 combine(b,c) } \keyword{array} \keyword{manip} gdata/man/centerText.Rd0000644000176000001440000000225011743412031014544 0ustar ripleyusers\name{centerText} \alias{centerText} \title{ Center Text Strings } \description{ Function to center text strings for display on the text console by prepending the necessary number of spaces to each element. } \usage{ centerText(x, width = getOption("width")) } \arguments{ \item{x}{Character vector containing text strings to be centered.} \item{width}{Desired display width. Defaults to the R display width given by \code{getOption("width")}. } } \details{ Each element will be centered individually by prepending the necessary number of spaces to center the text in the specified display width assuming a fixed width font. } \value{ Vector of character strings. } \author{ Gregory R. Warnes \email{greg@warnes.net} } \seealso{ \code{\link[base]{strwrap}} } \examples{ cat(centerText("One Line Test"), "\n\n") mText <-c("This", "is an example", " of a multiline text ", "with ", " leading", " and trailing ", "spaces.") cat("\n", centerText(mText), "\n", sep="\n") } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{manip} \keyword{character} gdata/man/cbindX.Rd0000644000176000001440000000247611367120174013646 0ustar ripleyusers% cbindX.Rd %-------------------------------------------------------------------------- % What: Column-bind objects with different number of rows - help % $Id: cbindX.Rd 1357 2009-08-20 14:54:44Z warnes $ % Time-stamp: <2008-08-05 13:38:45 ggorjan> %-------------------------------------------------------------------------- \name{cbindX} \alias{cbindX} \title{Column-bind objects with different number of rows} \description{ \code{cbindX} column-binds objects with different number of rows. } \usage{cbindX(...)} \arguments{ \item{\dots}{matrix and data.frame objects} } \details{ First the object with maximal number of rows is found. Other objects that have less rows get (via \code{\link{rbind}}) additional rows with \code{NA} values. Finally, all objects are column-binded (via \code{\link{cbind}}). } \value{See details} \author{Gregor Gorjanc} \seealso{Regular \code{\link{cbind}} and \code{\link{rbind}}} \examples{ df1 <- data.frame(a=1:3, b=c("A", "B", "C")) df2 <- data.frame(c=as.character(1:5), a=5:1) ma1 <- matrix(as.character(1:4), nrow=2, ncol=2) ma2 <- matrix(1:6, nrow=3, ncol=2) cbindX(df1, df2) cbindX(ma1, ma2) cbindX(df1, ma1) cbindX(df1, df2, ma1, ma2) cbindX(ma1, ma2, df1, df2) } \keyword{misc} %-------------------------------------------------------------------------- % cbindX.Rd ends here gdata/man/case.Rd0000644000176000001440000000213011743412031013327 0ustar ripleyusers\name{case} \alias{case} \title{Map elements of a vector according to the provided 'cases'} \description{ Map elements of a vector according to the provided 'cases'. This function is useful for mapping discrete values to factor labels and is the vector equivalent to the \code{switch} function. } \usage{ case(x, ..., default = NA) } \arguments{ \item{x}{Vector to be converted} \item{\dots}{Map of alternatives, specified as "name"=value} \item{default}{Value to be assigned to elements of \code{x} not matching any of the alternatives. Defaults to \code{NA}.} } \details{ This function is to \code{switch} what \code{ifelse} is to \code{if}, and is a convenience wrapper for \code{factor}. } \value{ A factor variables with each element of \code{x} mapped into the corresponding level of specified in the mapping. } \author{Gregory R. Warnes \email{greg@warnes.net}} \seealso{\code{factor}, \code{switch}, \code{ifelse}} \examples{ ## default = NA case( c(1,1,4,3), "a"=1, "b"=2, "c"=3) ## default = "foo" case( c(1,1,4,3), "a"=1, "b"=2, "c"=3, default="foo" ) } \keyword{ manip } gdata/man/bindData.Rd0000644000176000001440000000531311367120174014136 0ustar ripleyusers% bindData.Rd %-------------------------------------------------------------------------- % What: Bind two data frames - help % $Id$ % Time-stamp: <2008-12-30 13:49:50 ggorjan> %-------------------------------------------------------------------------- \name{bindData} \alias{bindData} \title{Bind two data frames into a multivariate data frame} \description{ Usually data frames represent one set of variables and one needs to bind/join them for multivariate analysis. When \code{\link{merge}} is not the approriate solution, \code{bindData} might perform an appropriate binding for two data frames. This is especially usefull when some variables are measured once, while others are repeated. } \usage{ bindData(x, y, common) } \arguments{ \item{x}{data.frame} \item{y}{data.frame} \item{common}{character, list of column names that are common to both input data frames} } \details{ Data frames are joined in a such a way, that the new data frame has \eqn{c + (n_1 - c) + (n_2 - c)} columns, where \eqn{c} is the number of common columns, and \eqn{n_1} and \eqn{n_2} are the number of columns in the first and in the second data frame, respectively. } \value{ A data frame. } \author{Gregor Grojanc} \seealso{ \code{\link[base]{merge}}, \code{\link{wideByFactor}} } \examples{ n1 <- 6 n2 <- 12 n3 <- 4 ## Single trait 1 num <- c(5:n1, 10:13) (tmp1 <- data.frame(y1=rnorm(n=n1), f1=factor(rep(c("A", "B"), n1/2)), ch=letters[num], fa=factor(letters[num]), nu=(num) + 0.5, id=factor(num), stringsAsFactors=FALSE)) ## Single trait 2 with repeated records, some subjects also in tmp1 num <- 4:9 (tmp2 <- data.frame(y2=rnorm(n=n2), f2=factor(rep(c("C", "D"), n2/2)), ch=letters[rep(num, times=2)], fa=factor(letters[rep(c(num), times=2)]), nu=c((num) + 0.5, (num) + 0.25), id=factor(rep(num, times=2)), stringsAsFactors=FALSE)) ## Single trait 3 with completely distinct set of subjects num <- 1:4 (tmp3 <- data.frame(y3=rnorm(n=n3), f3=factor(rep(c("E", "F"), n3/2)), ch=letters[num], fa=factor(letters[num]), nu=(num) + 0.5, id=factor(num), stringsAsFactors=FALSE)) ## Combine all datasets (tmp12 <- bindData(x=tmp1, y=tmp2, common=c("id", "nu", "ch", "fa"))) (tmp123 <- bindData(x=tmp12, y=tmp3, common=c("id", "nu", "ch", "fa"))) ## Sort by subject tmp123[order(tmp123$ch), ] } \keyword{manip} \keyword{misc} %-------------------------------------------------------------------------- % bindData.Rd ends heregdata/man/ans.Rd0000644000176000001440000000163512143472607013220 0ustar ripleyusers\name{ans} \alias{ans} \title{Value of Last Evaluated Expression} \usage{ ans() } \description{ The functon returns the value of the last evaluated \emph{top-level} expression, which is always assigned to \code{.Last.value} (in \code{package:base}). } \details{ This function retrieves \code{.Last.value}. For more details see \code{\link[base]{.Last.value}}. } \value{ \code{.Last.value} } \seealso{ \code{\link[base]{.Last.value}}, \code{\link[base]{eval}} } \author{Liviu Andronic} \examples{ 2+2 # Trivial calculation... ans() # See the answer again gamma(1:15) # Some intensive calculation... fac14 <- ans() # store the results into a variable rnorm(20) # Generate some standard normal values ans()^2 # Convert to Chi-square(1) values... stem(ans()) # Now show a stem-and-leaf table } \keyword{programming} gdata/man/aggregate.table.Rd0000644000176000001440000000532512024144337015445 0ustar ripleyusers% $Id: aggregate.table.Rd 1605 2012-09-12 17:39:42Z warnes $ % % $Log$ % Revision 1.7 2005/09/12 15:42:45 nj7w % Updated Greg's email % % Revision 1.6 2005/06/09 14:20:25 nj7w % Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. % % Revision 1.1.1.1 2005/05/25 22:07:33 nj7w % Initial entry for individual package gdata % % Revision 1.5 2003/11/17 22:09:00 warnes % Fix syntax error. % % Revision 1.4 2003/06/07 17:58:37 warnes % % - Fixed error in examples. Had sqrt(var(x)/(n-1)) for the standard % error of the mean instead of sqrt(var(x)/n). % % Revision 1.3 2002/09/23 13:59:30 warnes % - Modified all files to include CVS Id and Log tags. % % \name{aggregate.table} \alias{aggregate.table} \title{Create 2-Way Table of Summary Statistics} \description{ Splits the data into subsets based on two factors, computes a summary statistic on each subset, and arranges the results in a 2-way table. } \usage{ aggregate.table(x, by1, by2, FUN=mean, ...) } %- maybe also `usage' for other objects documented here. \arguments{ \item{x}{ data to be summarized } \item{by1}{ first grouping factor. } \item{by2}{ second grouping factor. } \item{FUN}{ a scalar function to compute the summary statistics which can be applied to all data subsets. Defaults to \code{mean}.} \item{\dots}{ Optional arguments for \code{FUN}. } } %\details{ % ~~ If necessary, more details than the __description__ above ~~ %} \value{ Returns a matrix with one element for each combination of \code{by1} and \code{by2}. } \author{ Gregory R. Warnes \email{greg@warnes.net}} \seealso{ \code{\link{aggregate}}, \code{\link{tapply}}, \code{\link{interleave}} } \note{This function is DEPRECIATED. Please use \code{tapply} instead. See example for illustration.} \examples{ # Useful example: # # Create a 2-way table of means, standard errors, and # obs set.seed(314159) g1 <- sample(letters[1:5], 1000, replace=TRUE) g2 <- sample(LETTERS[1:3], 1000, replace=TRUE ) dat <- rnorm(1000) stderr <- function(x) sqrt( var(x,na.rm=TRUE) / nobs(x) ) ## Depreciated: means <- aggregate.table( dat, g1, g2, mean ) ## Instead use: means <- tapply( dat, list(g1, g2), mean ) ## Depreciated stderrs <- aggregate.table( dat, g1, g2, stderr ) ## Instead use: stderrs <- tapply( dat, list(g1, g2), stderr ) ## Depreciated ns <- aggregate.table( dat, g1, g2, nobs ) ## Instead use: ns <- tapply( dat, list(g1, g2), nobs ) blanks <- matrix( " ", nrow=5, ncol=3) tab <- interleave( "Mean"=round(means,2), "Std Err"=round(stderrs,2), "N"=ns, " " = blanks, sep=" " ) print(tab, quote=FALSE) } \keyword{iteration} \keyword{category} gdata/man/MedUnits.Rd0000644000176000001440000000406012163373073014161 0ustar ripleyusers\name{MedUnits} \alias{MedUnits} \docType{data} \title{ Table of conversions between Intertional Standard (SI) and US 'Conventional' Units for common medical measurements. } \description{ Table of conversions between Intertional Standard (SI) and US 'Conventional' Units for common medical measurements. } \usage{data(MedUnits)} \format{ A data frame with the following 5 variables. \describe{ \item{Abbreviation}{Common Abbreviation (mostly missing)} \item{Measurement}{Measurement Name} \item{ConventionalUnit}{Conventional Unit} \item{Conversion}{Conversion factor} \item{SIUnit}{SI Unit} } } \details{ Medical laboratories and practitioners in the United States use one set of units (the so-called 'Conventional' units) for reporting the results of clinical laboratory measurements, while the rest of the world uses the International Standard (SI) units. It often becomes necessary to translate between these units when participating in international collaborations. This data set provides constants for converting between SI and US 'Conventional' units. To perform the conversion from SI units to US 'Conventional' units do: Measurement in \code{ConventionalUnit} = (Measurement in \code{SIUnit}) / \code{Conversion} To perform conversion from 'Conventional' to SI units do: Measurement in \code{SIUnit} = (Measurement in \code{ConventionalUnit}) * \code{Conversion} } \source{ \url{http://www.globalrph.com/conv_si.htm} } \seealso{ The function \code{\link{ConvertMedUnits}} automates the conversion task. } \examples{ data(MedUnits) # show available conversions MedUnits$Measurement # utility function matchUnits <- function(X) MedUnits[ grep(X, MedUnits$Measurement),] # Convert SI Glucose measurement to 'Conventional' units GlucoseSI = c(5, 5.4, 5, 5.1, 5.6, 5.1, 4.9, 5.2, 5.5) # in SI Units GlucoseUS = GlucoseSI / matchUnits("Glucose")$Conversion cbind(GlucoseSI,GlucoseUS) # also consider using ConvertMedUnits() ConvertMedUnits( GlucoseSI, "Glucose", to="US" ) } \keyword{datasets} gdata/man/ConvertMedUnits.Rd0000644000176000001440000000420712163373113015520 0ustar ripleyusers\name{ConvertMedUnits} \alias{ConvertMedUnits} \title{Convert medical measurements between International Standard (SI) and US 'Conventional' Units.} \description{ Convert Medical measurements between International Standard (SI) and US 'Conventional' Units. } \usage{ ConvertMedUnits(x, measurement, abbreviation, to = c("Conventional", "SI", "US"), exact = !missing(abbreviation)) } \arguments{ \item{x}{Vector of measurement values} \item{measurement}{Name of the measurement} \item{abbreviation}{Measurement abbreviation} \item{to}{Target units} \item{exact}{Logicial indicating whether matching should be exact} } \details{ Medical laboratories and practitioners in the United States use one set of units (the so-called 'Conventional' units) for reporting the results of clinical laboratory measurements, while the rest of the world uses the International Standard (SI) units. It often becomes necessary to translate between these units when participating in international collaborations. This function converts between SI and US 'Conventional' units. If \code{exact=FALSE}, \code{grep} will be used to do a case-insensitive sub-string search for matching measurement names. If more than one match is found, an error will be generated, along with a list of the matching entries. } \value{ Returns a vector of converted values. The attribute 'units' will contain the target units converted. } \seealso{ The data set \code{\link{MedUnits}} provides the conversion factors. } \references{ \url{http://www.globalrph.com/conv_si.htm} } \author{ Gregory R. Warnes \email{greg@warnes.net} } \examples{ data(MedUnits) # show available conversions MedUnits$Measurement # Convert SI Glucose measurement to 'Conventional' units GlucoseSI = c(5, 5.4, 5, 5.1, 5.6, 5.1, 4.9, 5.2, 5.5) # in SI Units GlucoseUS = ConvertMedUnits( GlucoseSI, "Glucose", to="US" ) cbind(GlucoseSI,GlucoseUS) \dontrun{ # See what happens when there is more than one match ConvertMedUnits( 27.5, "Creatin", to="US") } # To solve the problem do: ConvertMedUnits( 27.5, "Creatinine", to="US", exact=TRUE) } \keyword{manip} gdata/man/Args.Rd0000644000176000001440000000163111552125074013323 0ustar ripleyusers\name{Args} \alias{Args} \title{Describe Function Arguments} \description{ Display function argument names and corresponding default values, formatted in two columns for easy reading. } \usage{ Args(name, sort=FALSE) } \arguments{ \item{name}{a function or function name.} \item{sort}{whether arguments should be sorted.} } \value{ A data frame with named rows and a single column called \code{value}, containing the default value of each argument. } \note{ Primitive functions like \code{sum} and \code{all} have no formal arguments. See the \code{\link{formals}} help page. } \author{Arni Magnusson} \seealso{ \code{Args} is a verbose alternative to \code{\link{args}}, based on \code{\link{formals}}. \code{\link{help}} also describes function arguments. } \examples{ Args(glm) Args(scan) Args(legend, sort=TRUE) } % Programming \keyword{programming} \keyword{utilities} \keyword{documentation} gdata/inst/0000755000176000001440000000000012164370064012342 5ustar ripleyusersgdata/inst/xls/0000755000176000001440000000000012163372262013151 5ustar ripleyusersgdata/inst/xls/latin-1.xlsx0000644000176000001440000012574112015205107015335 0ustar ripleyusersPK!܆ ~~Ì[Content_Types].xml ¢( Ä”ÏN1Æï&¾Ã¦W³[à`Œaá€zTñj;»[é¿´áí-B Á%ÄM¼l³mçû~3éÌxºÑ*[ƒÒš’ ‹ÉÀp+¤©Kò¶xÊïH"3‚)k $[d:¹¾/¶B†Ñ&”¤‰ÑÝSxš…Â:0xRY¯YÄ__SÇø’Õ@GƒÁ-åÖD01­™Œ b+³Ç nïH0œd³Ý½Öª$Ì9%9‹JÛSz2΃ k#Žèòo²#“xh¤ 7¿;|8¨¤nSKHõ‚åôR@6g>>3ìt£è§õËwk—Ewj'mUIÂò•ƪÁy`"4Q«"­…fÒì™;üÓå@Ó2ì¤Í/ _È1ú'Žˆohúþ½IæLâ!n„ž³Ý‰žsn˜ñ=vuï?µÏpp¦ø¬Á§Úsº]þØ?so]Àéãár€ý˜h£s‡Bࣄà8ÕtG]—u=´³Q€8áMÓ,ž|ÿÿPK!}ÌTž Ý _rels/.rels ¢( ¬’MNÃ0…÷HÜÁš}ã´ „PnRw…LíibÿÈv!½=†EC¤U‚¥=ãçïÍ›õf0={§µ³–E Œ¬tJÛFÀký´¸Z…½³$àH6ÕõÕú…zLùQlµ,«Ø( MÉ?peKcá<Ù\Ù»`0åch¸GÙaC|U–w<üÔ€j¢É¶J@ت`õÑçŸÿ¢Í %T˜KháC& Ig/¬ÆÐP œ|Î×ñ»£ÈÔÀÏÝ^äö{-éÑɃ!›Îxæ4$²ŠÔ<z?G´üO¢)ó8Ÿ¡ç.t;çº9–Õå,¿¯ÂWjfgQ÷#È)¨S­xóÔ|ÅÅ'KY}ÿÿPK!A˜ø Ìxl/_rels/workbook.xml.rels ¢( ¼“ÍjÃ0„ï…¾ƒØ{-ÛmC)‘sh)äÚ¦ äµebKF»ýñÛW$Ôq ¸Óã΢™‘´Þ|w­øÄ@w ²$Îø²qµ‚÷ÝËÍbíJÝz‡ $Ø×WëWl5ÇCd›žDtq¤À2÷R’±ØiJ|.n*:Íq µìµÙëež¦+¦PœyŠm© lË[»¡É{ûªj >{óѡ㠒#FCjd‡ñ(fIy™ánIâ¡%ŽÇy.þ~Ñx«–oâ O)¦òÌjI£[óduãNuŒÒD¶$Ä—{²ˆ|‚%’‡ÍìëÈÿ&ÿmFžýÁâÿÿPK! Ä ×xl/workbook.xmlŒRMoÛ0 ½Øtwl+±[¶‹,X€a(¶®=«² ч!ɳ‹aÿ}´¼¤zÙ‰¤H=ò=²¸•D?¹uÂè§‹#®™©…>•øÇÃ!ºÅÈyªk*æ%~áßU?ƒ±çgcδ+që}·ŽcÇZ®¨[˜ŽkÈ4Æ*ê!´§Øu–ÓÚµœ{%c’$y¬¨ÐxFXÛÿÁ0M#ßÖ+®ý b¹¤Æw­è®ŠFHþ83B´ë¾Rs#Iß×ÂóºÄ„fàÿ<ؾûÔ Y’ÞÇÕ•å½E®5ÃQŸ7Zú•Ä¢½7[£€šs÷‚ùœ)'uÜ+Ì¢ñIèÚ  v/—ü!$žDí[˜!Ë“ëÛg.N­_¦Ož>›fP½â7Í‚ÂÐ4X¤ýï“ê)¬r²G`¾] pì±LßU“7Õà_«IèÊ¡ £’8“ °«$I›ÍzkaG[Èü„þ‹óUõV”ø×MF–ûl·ŒHvXF›lŸDi¾$Q¾:lµ%d•‘ß—Qã» Q‚YãLą̃x>8*ó‘ñpc·óU…×ËÚã$=ÁŽf0 ¨w™,¾\uõÿÿPK!vŠ:ÀŸ xl/styles.xml´VMoÛ0 ½Øto•dmѶ‹m€±Vhì*Û²#D†,·ñ~ý(ÉvÜvYƒ¥Ë!‘(òñQ~¤Ýì¤@Ì4\«ÏÏg1•ë‚«*Æ?ÖéÙ5F¥ª B+ãŽ5ø&ùø!jl'ØÃ†1‹B51ÞX[¯iò “´9×5SpRj#©…­©HSF‹ÆIA³Ù‘”+V2?DR³më³\ËšZžqÁmç±0’ùê¶RÚÐLÕÝü‚æ¶ß¼‚—<7ºÑ¥=8¢Ë’çì5Ë%Y@J¢R+Û \·ÊÆø  ]†ÕVé'•º#¸ÀÞ+‰š_è‘ °,0I¢\ m…›bsgQT²àñ• žîŒ%•\tÁìãüeö~’Ci΋8Mµ`ø[®Ù{&Ë¦ÉæÎµŒ€ð$àEb·ïqjÝ›ÕwÿÈ 0 VÒVØõxãýú;+x+—£×=ÔÖCÄx¿^~Ð’ý?‹ä7ÿÿPK!¹Œq xl/worksheets/sheet2.xmlŒ“ÛŽ›0†ï+õ,÷¦•𨤻aƒ€(‡®v¥Mõ°{혬`Œl礪ïÞJU)7{xÌøãŸù‡x~Ö9‚uÊÔ Æœ¨¥ÉT]$ôçûÑ%΋:•©!¡ptž¾}ŸŒÝ»À$Ô.¡¥÷MĘ“%háÆ¦ßäÆjá1´s‘u‡tÅ&œO™ª¦=!²¯a˜ð¦éÄìŒ÷FwË' P crnŒìœý“óÝ“¬Jè¯é ç“ðS0ZL—|tÛÞ&ÓÂp,ßM9ÿ=¸¬Ï¯³X Éà,¡é»~¤ÓXŸ£íÓ3Ù˜ §øZÃkìÖ/ߥh‡ª÷eb/±ìß•þÿÿPK!0ˆkÞxl/theme/theme1.xmlìYOoE¿#ñF{oc'vGuªØ±[hÓF±[Ôãx=öN3»³š'ñ µG$$DA\¸q@@¥VâR>M ŠÔ¯À›™ÝõN‘›¸DJ¥›++2„a,/ó”$ðnÄEŒ<ŠñÊPà#г•ÕJe}%Æ4 P‚cP{g4¢!A}­2ØÊ•w<&JꉞVM ƒT5BNe› tˆY3€y†ü¨OŽU€– ^4ƒŠù V¶®®àÍLˆ©²%¹®ùËä2áÁª™SŒŤÕn­qe§ÐoLÍã:N»S-ôCðÔÚRÖYënT[¹ÎÈþœ×Ý®Ô+5_Ò¿6gs£ÕjÕ™-V©ÙŸµ9üFe½¶½êà ÈâësøZk»Ý^wðdñësøî•ÆzÍÅPÄhr0‡Öív3ídÄÙ /|à• >CA6Ù¥§ñD-ʵ?ࢠdXÑ©iJF8„,nãx (ÖàM‚KoìP(ç†ô\H†‚¦ª¼Ÿb¨ˆ™¾WÏ¿}õü)zõüÉÉÃg'8yôèäá÷V—#x'ã²à˯?ùýËÑoO¿zùø3?^–ñ?÷ÑO?~êBÍ,zñù“_ž=yñÅÇ¿~óØßxP†÷iL$ºMŽÐ>Á7CŒk9ˆóIô#L nꎊàí)f>\‹¸äÝÐ<|À듎­½HLõÌ|3Šà.ç¬Å…—€›z®ÃýI2öO.&eÜ>Ƈ¾¹Û8qBÛ™¤Ð5ó¤t¸oGÄ1sáDá1IˆBú? ÄãÝ}J^wi(¸ä#…îSÔÂÔKIŸœDš Ý 1ÄeêóBíp³{µ8óy½C]$fãû„94^Ç…cŸÊ>ŽY™ð[XE>#{S–q© ÒcÂ8ê ‰”>™;ü-ý&†~å û.›Æ.R(zàÓy s^Fîðƒv„ãÔ‡íÑ$*cß“¢íqåƒïr·Bô3Ä' Ã}'Üg7‚»tì˜4Kýf"<±¼N¸“¿½)abº ´t§SÇ4y]Ûfú¶ámÛnÛ°ˆùŠçÆ©f½÷/lÑ;x’쨊ù%êm‡~Û¡ƒÿ|‡^TËß—g­º´Þؽ¶ÙyÇ 7Þ#ÊXOM¹%ÍÞ[Â4ì –3‡NRÄÒ~êJ† ÜX`#ƒWPõ"œÂ¾½h%c™©K”r çE3ìÕ­ñ°÷Wö´Y×çÛ9$V»|h‡×ôp~Ü(Ô«ÆæL›O´¦,;ÙÚ•L)øö&“UµQKÏV5¦™¦èÌV¸¬)6çr ¼p  6agƒ`?,¯Ã±_O çÌÈPónc”‡ÅDᯠQæµu$ÂCbCä —Ø¬šØå)4çŸvÏæÈùØ,XÒÎ6¤ÅâüY’ä\ÁŒd<]M,)×KÐQ3hÔWë qÚ FpÒ…Ÿq A“z/ˆÙ®‹B%lÖžY‹¦Hg7üYU…Ë‹ã”q*¤ÚÁ2²14¯²P±DÏdí_­×t²]Œžf²œk"ÿ˜j7´d4"¡*»4¢¹³Y'äED/¡›ˆ} áNµ?C*á´~€Û5ͶyåöÖ¬Ó”ï´ ÎŽc–F8ë–úv&¯8 7ý¤°Á<•Ìß¼¶çÎø‹r¥œÆÿ3Wôr7kC.wFºRš*âÐ…Òˆ†]ë¾é-pC ¯|¸b6ÿ r¨ÿ·5gu˜²†ƒ Ú§c$(,'*„ìA[2Ùw†²j¶ôX•,Sd2ªd®L­ÙrHX_÷Àu݃Aª›n’µƒ;îsVAƒ±Þ£”ëÍédÅÒikàïÞ¸Øb§Ní%tþæü&«ûlõ³òF<_#ËŽè³]R-¯ gñk4²©ÞЄeàÒZk;֜ǫõÜ8ˆâ¼Ç0XìgR¸BúXÿ¨™ý^¡Ô>߇ފàóƒåAV_Ò] 2H7Hûkû;h“I«²Ôf;ÍZ¾X_ðFµ˜÷ÙÚ²eâ}N²‹M”;S‹Ivưõ[H5Döt‰ÂÐ(?‡˜À˜]åoQ|ð½·þf¿NÉžL¤{Âd×€§ÙO&í‚k³NŸa4’%ûd„èð8?Lز_Hò-²Ak1h…àšïÐà fx-jWËBxõláBÂÌ -»6j>ð},kÜúhxÛd­×º¸r¦Xòg([Âx?eޓϲ”Ùƒâkõ”©ã×S–1äÍ'|áŽ^=Óaѱ™nRvëÿÿPK!>y‡âÙ`xl/worksheets/sheet1.xml¤YsÛH–…ß'bþƒ‚ﶸSrXîa_ÛÝU=óFË´Í(IÔtÙUóß'“@n礢M׋E}8̼ºy‘Ié·ûþøpñûfØîžnF“×ãÑÅæé~÷qûôùfôÏį®F‡ãúéãúa÷´¹ý±9Œþöî?ÿãí·Ýþ·Ã—Íæx!Zx:ÜŒ¾Ïo./÷_6ëÃëÝóæIù´Û?®â×ýçËÃó~³þxzÓãÃåt<^^>®·O£¾…7ûic÷éÓö~íî¿>nžŽ}#ûÍÃú(â?|Ù>Tk÷?ÒÜãzÿÛ×çW÷»ÇgÑćíÃöøÇ©ÑÑÅãý›ìóÓn¿þð þîï“ùú^µ}ú…šÜÞïw‡Ý§ãkÑÜe(ÿÍ×—×—¢¥wo?nÅ_ Ó~±ß|ºÝNÞùr6º|÷ö”¡_¶›oëõÅqýáýæasÜ|F.Ž»çróénnFîvïï×2ÚÉBø¨¯¥BäÒvýyS®ÿØ}=Ê®†£ÒÕ»Ýoe¢Ÿ±ôpêUº¾?nßô=†¢ÇÃÿœB/EÔ—:lûµúâÓyÐî/>¬›p÷ðëöãñ‹èTÄùqóiýõáø÷Ý·t³ýüå(C™– óñhs¸NËPD'÷»Ñ¢ø÷âq+ÏWaÓúûéç·¾Áë×W³éx6™Š&>lÇx+Û]Ü=wª×¡©¾‘éЈø942=YÎÇË3Ú˜ mˆŸC³Åëa>¼]üüéDo§\ˆŸ*„³ÿŒåÐÆJ·q~*DÁ8Å!~ê8fçzr=4"ÏŸÎÈDŸâ…Žå\k'êü˜sÏÏÊDY,_èX–gžfr`œ’;ý+'ëT­ò…ŽåܼLÕ_$‡ÉO{4U§œ|ñ󱈶ϋ9ëÎ÷hªÎ:ùbˆeúú\fâ”=Å23gÝù±ÌÔY'_ü|,Êé™9ë~"uÖ͌ӳ³kËL9=û+Õe¦Ê‹|¡Ï×û™òxþWÜ™+w䋟ˆb®|‘/ôûÏs5å ÝÊçb®|•/ôûÏŽBù:·GðQ¨±;7çÅùg×\ò…þ[ΈB ÛÑss±P¾Ê:г¯~ e¬|¡›9;eï¶÷ü`”¿ Ûß³ƒQ./l—ÏFÙ¼°m>;m¶)ô³×g³T•^¾P6ýp%ZªÙ‰|¡Þ}vU]ªJ$_¨Vþ] —ý4ú4aÖÇõ»·ûÝ· ±þ‘ž×r57y#3mIo%¾‰sQÌ¥‚þþnòöòw1Í¿rù!ßd)æ®â´\¸‰a¡ÛX¹ŠÈÓËØ•Üq7“™+‰{‰ÝÏdéJOG×®$厦SW’qGÓ…+ɹ£é•+)¸£ä¶äŽfÜŠ;šAvkîhÙm¸£9d·åŽæÝÎÓ d÷ï,Y@vß{$Ýx$ݲd ÙýÅ#ìþÚKÄ¿úÔ]BvÿÅ­¬ »ÿÕKìA´‚ìþ7w´‚ìÞcÑ>¿WÞÛa4Ú]]A~o‡ñhÿQWàÛaDÚ}]A†o‡!i÷u )¾ƤÝ×5äøv”v_×äÛaTÚ}MÆæÛa\ÚMÆèÛadŠë¢¶t2ÆTcÓís=ŒN§» &{Ÿö7™`¶‡êt7ÁtcTÔzøó-G©uS-G¨u³,G§9<ÃüÊ‘iÆÌÊQiÆœÊiÆlÊÑhÏ1r$Z‡1ƒrZ‡1wršÃ Ìš}ÖaÈZ žu²È1g/!knÖaÈZ Gšu²ÈAf†¬r|™Ã+ÈZ ‡–u²ÈQe†¬r<™ÃWµ@Ž$ë°ÉÚ¥˜Rèy…8_}ó ‰oFbZ©[À¼õ gL¸Ðð÷GJ!?>”Ó™;1‚AŠ C#(”*5‚A‹ ³€“qQk|—ØÍ8žŠ½ÂvÕxzJ_È 8¥"¥ÐG#H¤29‚A‰ BP#h´: 8'©/ã»ÇÑÝ+D³z@q Y£4R q1‚AŠ C#(”*5‚A‹ ³€“qqùöe\b7ãX0{…hVg|…'ôH ôEJ¢sŽ F Hdr‚A… FÐ htpr.е/ç»9ÇIPÐKì‚k·Ð#â)‰N:‚A‚ E!ÈJ‚Aƒ EÐYÀIºøÈÄ—t‰!éP‰ƒ^b×\ ‡ ÔŸHItÒÄ)‚ AŽ @P"¨Ô-‚ÎNÒÅL¾¤K I‡bô§¼@ Y2… )‰N:‚A‚ E!ÈJ‚Aƒ EÐYÀIºø<Ηt‰Ý¤ã¢'è%vyÁOlBf?‘’è¤#ˆ$R‚A DP!¨4Zœ¤Ë/Y}Y?qH;Ôã`ÐØ? }˜EZ£3O$&’I‰dDr"‘’HE¤&Òi‰t6qm'¯×ÉÁ¨ÐÁ¤×Ø5?j }¨K‘ÖTˊĤIˆ¤D2"9‘‚HI¤"Riˆ´D:›¸6È%•ïCð~©%®ÑzÖˆŽò^a•H™ÑÀ´1ôipɪ5*éwDb" ‘”HF$'R)‰TDj" ‘–Hg×¹ÎòÙ ¹;fPÅy§†ÐØE ?2}˜=EZclP-+“&!’ɈäD "%‘ŠHM¤!ÒélâÚ _>$ ¦òV¡±‹~-ú40ŸŠ´F%ýŽHL$!’ɈäD "%‘ŠHM¤!ÒélâÚ ×c>úušS” ¦ò¦!aƒ]”ð«ŸÐ§Âi±Aµ¬HLš„HJ$#’)ˆ”D*"5‘†HK¤Èêt[£ý9æD®Ð|6ô+7Ûüð:8½×-JøõZèÓÀŒ+Ò•ô;"1‘„HJ$#’)ˆ”D*"5‘†HK¤ˆÇ¹fS6LVæ{ê~-çØ5=r,JøfèÓÀŒ+ÒcƒjY‘˜4 ‘”HF$'R)‰TDj" ‘–H7 r糡_Ý96@M&½Æ¾DÏ¡p…ÍWÉZ£’~G$&’I‰dDr"‘’HE¤&Òi‰t6q¯ r]糡_ïÙ6à—^Á¤×Ø6àWñ¡O3®HkŒ ªeEbÒ$DR"‘œHA¤$R©‰4DZ"M¦ö*ZŒuó̉»3¥Ôô`Ð86@á }˜qEZ£’~G$&’I‰dDr"‘’HE¤&Òi‰t6qmëUÏh˜öëXg4@Mc®Ð§Âi±¡ïýôxÇé[´˜4 ‘”HF$'R)‰TDj" ‘–Hg×{m^EÓ—åòævX¾ám;¡Oƒ«h­16¨–‰I“I‰dDr"‘’HE¤&Òi‰t6qmç²w4Hî¥%Ôô@>€6@á }(\‘Ö¨¤ß‰‰$DR"‘œHA¤$R©‰4DZ"M\ìU´=x½„šÈç,`ù†·Ÿ…> ®HkŒ ªeEbÒ$DR"‘œHA¤$R©‰4DZ"M\ìU´m¯¢—PÓù” Œ¼Å/ôip­5*éwDb" ‘”HF$'R)‰TDj" ‘–Hg×qö%ÉÝ¢D73ÉÇ„„Fœ¹úV¼2ôi pEZclP-+“&!’ɈäD "%‘ŠHM¤!ÒélâÚðÂ*zÊ«èÔô`ÐØŸ)á­ª¡O3®HkTÒïˆÄD")‘ŒHN¤ R©ˆÔD"-‘Î&® /¬¢§¼Š^AM=aÅ»Cæ WÑZclPësEbÒ$DR"‘œHA¤$R©‰4DZ"M\^XEËg¡(ÑMƒÆ.JxÃuèÓÀŒ+Ò•ô;"1‘„HJ$#’)ˆ”D*"5‘†HK¤³‰cƒ|zÒwm8q÷Úp5=4vQÂ{ÚCŸf\‘ÖhˆÄD")‘ŒHN¤ R©ˆÔD"-‘Î&® r½êYEÏúu¬¸TêËïÔô`ÐØE }˜qEZclè{·VѤIˆ¤D2"9‘‚HI¤"Riˆ´D:›¸6¼°Š–CQº†š »(á“¡Oƒ«h­16ô½ÏO»(È;ªcÒ$DR"‘œHA¤$R©‰4DZ"M\äJØ7ú²=®¡¦³^c%|ø%ôi`Æi±Aµ¬HLš„HJ$#’)ˆ”D*"5‘†HK¤³‰kƒ\¯úlܽ6\CMäðB#R¦ >_ú40㊴F%ýŽHL$!’ɈäD "%‘ŠHM¤!ÒélâÚðÂ*Zî€6@M]”è®Ð+Âu´#úþí²„$¡w¥D2"9‘‚HI¤"Riˆ´D:›¸FÈ«o<ô+Y»,MÆPÖ¹ƒpË®Kôœ\èÁ´+Ò"ã„j[‘˜4 ‘”HF$'R)‰TDj" ‘–Hg׉–Òr« “1Tö`‰sU—&z1ôŠ`æi‘Êû‘˜HB$%’ɉDʘùZE¤&Òi‰t6qxa5-· !' ¸ƒÈ­NPÂBŸ‰´È8Ñ`W'$ ½+%’ɉDJ"‘šHC¤%ÒÙÄuⅵܘ@u‘Sð‰’Ð+‚ùW¤EƉ>€Ó¦eýwq¤Iˆ¤D2"9‘‚HI¤"Riˆ´D:›8NÌ_XSŸ¸;ošL ºƒÈž8ѳˡWS°H‹´Db" ‘”HF$'R)‰TDj" ‘–Hg× ¹€õ\±ç’£P݃AäT'|@<ôŠ „EZdœè°ªi")‘ŒHN¤ R©ˆÔD"-‘Î&®/¬¬å†Nè>š "!5Wl| %ôŠ`i‘q¢`jפIˆ¤D2"9‘‚HI¤"Riˆ´D:›¸NÈe¬oLôË[g;…êÈý³, x…pØÌ¼ÜäÚÐä0*§PÕ¹÷– Ú›‡\¨ø"è0n`4r÷.>“Âas¥u#Sv_ýTÞ‰`gq wþ²"“B8lLr#xa-·CfÆÉÓ<"+0)„ÃÆ$7‚æŽrK1ŠÀ89D DV`R(Û0‡­û¯Ýì9ÓLßB6÷L™æÆÈ!!²zBÙ†uØxä ÷Õ§ à„a$Ì}Rdõ…pØXä`_!­<ȹ±q@ˆ¬À¡pá6¹Ø+ÏuoF äÞq&¼Ù2„ÃÆ!7»ZxÊá¸8dÀ)‡x›a(w¥³â3¹ØåÐ ÀS ÆÅ!§.À¡Pîgg`r°«¡€§.Œ‹CN1Ä[ËB¹ž Àº«Ì À.†VžZ¸4.8µoª å&zVf ¹صРÀS —ÆÅ!§âíD¡ÜÏ À8ä`—B+O%\‡œR‡7Ò„rç>€u€¿.<•p…•PЬÀ¡›1ä ÷ôóT†J¸2.ö"+p(„Ãf ¹ø+áÒS WÆÅ!§Ôám¡lÊό!7%” âÕo(¤Èô€_˜‡pØ8ä௄b“tÀ¸8dÀ)uøUq(Û°â3õô{™÷[#>nöŸO{ž.îw_åNäqaÖ´ß½]<2ôF>(!¦ñ—úØ©üYl²^­÷Ÿ·O‡‹±[»ØÆüõJÔ }¿Ñyÿ‹ØÉýôAì‡ÝQìQ~zùEl”¿߬å&âŸv»£úEt Û|¿9~}¾x^?oöï·ŠßÅ)¿ÛoÅFé§ðoFÏ»ýq¿ÞG_ÿs'¹B¼&8%#îÐAˆ+Rãí®o@—¨†Ì#¾å» Òªdf$ó‰0 ñ©²ÿ˜ŠÝ³³fß@Bï5û­ež‚'N_ƒ +ÚlköK­µƒýC«à1ÓÁ…óWq¶9+*©Kÿ9Hª•Wþ€òÜ=óDƒQÉ\ø/@ vÝÓw É‹¦*©KÿÈr©è+@y®ƒ/-*‰!þô¸>5Fø€p}º¼N5dÛÔÿ÷Ê5íÿÞéüÿÿPK !ƒ v,ttdocProps/thumbnail.jpegÿØÿàJFIFHHÿâ@ICC_PROFILE0appl mntrRGB XYZ Ù  acspAPPLapplöÖÓ-appl dscmòdescüogXYZlwtpt€rXYZ”bXYZ¨rTRC¼cprtÌ8chad,gTRC¼bTRC¼mluc enUS&~esES&‚daDK.êdeDE,¨fiFI(ÜfrFU(*itIT(VnlNL(nbNO&ptBR&‚svSE&jaJPRkoKR@zhTWlzhCNÔruRU"¤plPL,ÆYleinen RGB-profiiliGenerisk RGB-profilProfil Générique RVBN‚, RGB 0×0í0Õ0¡0¤0ëu( RGB ‚r_icÏðPerfil RGB GenéricoAllgemeines RGB-Profilfn RGB cÏðe‡NöGenerel RGB-beskrivelseAlgemeen RGB-profielÇ|¼ RGB Õ¸\Ó Ç|Profilo RGB GenericoGeneric RGB Profile1I89 ?@>D8;L RGBUniwersalny profil RGBdescGeneric RGB ProfileGeneric RGB ProfileXYZ Zu¬s4XYZ óRÏXYZ tM=îÐXYZ (Ÿ¸6curvÍtextCopyright 2007 Apple Inc., all rights reserved.sf32 BÞÿÿó&’ý‘ÿÿû¢ÿÿý£ÜÀlÿátExifMM*>F(‡iNHH  oÿÛCÿÛCÿÀoÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?þ¦<;…AÑÍÖ¢Ü\:ÐÜO=Œ4²˜”¼’;|ÎîÇ%›’sœÖ‰FÊé¿ü ü¿¯1]wüàÿW6ůƒ‚¯†t&f!T.›nÌÌÇ*€If$Q’O“NÑìþ|ߘçí'᩾|‹Æiá-O¿ñO‰,<m–ÿcÕt[-oD×îÆ½ÛÆÌš¬ZmœvVR¼Z\Ouq"Ëo¤ÐíÓï»ïç×þ¨_Õÿ«Ÿ£ƒà×Â|ø·^è?æ§ÿñŠþ×Âú'^ÿÁŸÿÆ(ó·þ ã >x[Âìõð§ÂúßÅýoþoˆW]§Á­Sâ›ðÛá^›±âMëC𮇬ßhRüFñÿ…>èÞ/Ôm­´ëÄ÷šÌ—öòé!Ôí¿†žøñgáß¾'ø7ÀÞ Ô<)ñ ÂzŒ¼=xº˜Æm#Äz]¶«e愉–;ˆàºH®¡'|),2$loÿ ká?ý¯à‡Oÿãå_~ü9ÓüaðBÎÇÀþ´µÖþ$kv¯oeZ•„? >&êÑYÞ¢ÄâÚ=OMÓõŠ@Ê·vV³¾ ç¯Ûåtï‚?<7â…¾ðv‹â}ãÁO‡³_ÇáO†—wË¡xóǺW‡uèt¦øœlü§ê×uÜÑiÚ¯‹o,ô=6å’ïQ»·¶ŽITµýŠm|ñÓö]øAñOÆžøaâoxŸAÔŠuŸ øÛÃú4þ Ñ/×>*ë?³æ›ûBè~ø³¥x*ˆ×0øá¿Äj6^:¶›¥¦µ¡xÖ]utY¤þÓÔììg]S¹ÔlÞI¢˜ZÉ»G+ôKÑjõûÛüÙ¯ãïØ—ã†·áˉ~ þÒú¿ü?áï7ćDÖ#ñä w¦ØÞ"\ÁμöÿnŠÚæém%¸I¡ŽiD’Ã*©C#?L~ÍãìÈkÂXÇý š¿Oü)¨#DÕüCâ[IuxËáþ¹a¡©i3^é:Uö¡i§£ÞϦêÚ{ÜZøªX…晨Û\Ø_Ûïóm/-ç¶Rh¤E·ý‡âßííµxû[ì_Ù¿ÚŸð‰jÚ?ÙÞÚ¿³þÛÿ Ú~ÅöŸô²ù¾GŸûï/Ìù¨=#ÃÞ(Ð4ÛMA—À:&‘§ÅäXiZGƒï´Ý6ÊÌþM¥Ÿˆaµ¶‹{3ypĉ¹™±’IÑû7ÿè5á/ü'5þi¨€ñ‡‡üc¨ø“áeåֹᵟCñ¶§©é SXžî_‡^:Ò$[ÅÈÒ[ý‹T»eX^ ÚÛHehRX¥óüCѼSñÇDý“|RŸ k+mbãI¶¿Ónn ¨™Ì2Et$³¸1^ˆ/>Ïö9À>hÿ‚o| ¾ýŠf›oŸ¿h 3ã6·gñ â‹´ÿµæºbÒô믭éžµ#ÕµK¡máÓ=ŤrÚ 6Æñ™ïÓI³º»»}íÿ Á_ô3i?øøÐÿ Á_ô3i?øøÐÿ Á_ô3i?øøÐã?ˆþ´›Ã:¥®¥²úF«¬êGLÒç´“Q¾ò<â¿*ÊÉn®-- åõÃÃeh.®í­Úêâ%šâËÊJÅbðØj˜œ> ŒEÆbÝHáp­R4å‰ÄÊ:Õ£‡ ¤êÖt¨Õ¨©ÆNêJÑaøñyw⛿Ú~Ú¹~þ×ÐøÞ×âíŠ-|"|û=¿á åøKwð¾EoŒ'ÆRºÓ¯õo.¶ž,O G㛨5Cà§kU¿¼èqQ𖧃¯Ž¼©Và¼FQ[:ÿY«G‡Áäo,šY¬ø~•L"Ï’ªé¥«³nI_›—Ýë¬ô½“|Í_â[µ£ý™ðoÆ? x¯Ã7ˆµoü{ªÚý¦ãÂ~0—GƒÄÚù²GöMbV×4¨îŠ ›m–­{•,y—~ô_á¬ó-¡“æØì³ œe\AC[ÙSÎrIâêeY„y#/m‚ž?€ÆJ•äázø:焽Î[JO³î“·Uu{?5×Ì­à_xFÛÂZTx‹K‚áô–á2Œ×÷l…“r’0ÊØÜ7à æ¼<ögðŒÿ'ø–þ3ø³áOÃã­{Iñ%¤P’Ê-;ZK ‹?_ˆx¼Gt¶Z¬6ðÊúY2é÷ž´ð.«tõGü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@ü,/Ðͤÿà\ã@}ñcǾøgãË;Oi—W>Öá‚îQ¤–Y,fTK;îMt?-mŸáOö{kvcàí–hc,Oöt’W$ž¤žIäòhá­â…Šࡳü;ðÆ]bÛGð.‘â»/Œ_ üeªé³hÞ/ñ>£á S🆾øJ]"ßQµO[E?‹|eã;k¶±yõøF~Ó«Ý˨G ~€xþÒÕ|âö[kuaá½h†Æ#O¸Á.AG ò(ñ[ö¡ÿ‚£øËàoíñoáÖ›®ø$x3ÀÖ?ü;{qªø Ä׺·|]à¯þ+x"ïQÓ¬õë]_ŶÞ$Ô|ãxæÔà²ð÷ƒ¯4]2ìÏïð/µ;p Ÿ¿à¤¿>+üJðÿÂxÃáoÂßüFÒ|-â_x[Yñ‹ûAÍðçöÊñßÁ_á÷ƒ&Ð|B–~<¶ø áÿ|C–=ÿÄRÔ>,ø[ÆšVœÿôÛä¿ùš?ø)ÏíOãèþx~Oxá½í‡ˆ?fY~5kº_Ãû‰fðEö£ÿ,ñìÃñoÃ(‹]ñͧ†ô÷øKeá{Äw­m«hƒW—Q‡R³Óõí6êÄô¯öý®þ/þÔž/ø…{ã{¯„zG‡t›~Âûá‚|V¿~|FðÄÿx3VðoÅ{kí=t;{]Gúv‰¨i\ÜiZ¾©ª[kº®‰a«øNòÆûOýB CÄòðýŒ÷ÿú…ø¯ühà_ø*oíóoÿùý›.~(iÞÿ„»âŠ5;ß ü>ðÛ­úÛÝêV>ÕüM¬ê3\Zi÷ÖæMAѯ¯¬tËÙ¬½¨­¦irnîãÀ>ðøaâõø…ð×áç’Ö{ñǼ%âõ²¹–Ö{›5ñ.§ëBÖâk–ÆiíÅï•,¶rIk$ˆÏnï F ü<ÿ‘;Fÿv÷ÿNW”üúøÇþ þÚn±ñ>ËÀ¿²ü~4Ó|%ñ…~øP—ã&™¤ˆz$zÅkû¿Áq„5m L…SáÖˆ£C‡\Õu-5þ"øVÞKqk£| ÿ‚ê|9øßñb×áf³à;‚ú¿³6µñ“ÅÿüSâȵ|.ñ¾áïjº—ƒu}RÒ<+ÿ •œþ?ÒbÑõ}7[·Ïoqi…‹Á©I¦zOÁø(o‰6|¹ø‡ûXøoÄ>-ø÷ám'DH¤½Ñ$øSãG@Âûüoq?‚5ëŒzF‹ðê}ö¾µ«ÇâÝ2Þk;¿N$ú+þ qÿðçü‹à¶‡ñ2ûÀW¿üUâsSÓ<1ðþËS½Ð%Ölü9 _x“Å‘ëÑxÄ6·zvŸmo†›y ëW×ÐZXÈÒ,»>Øø}ñsÁå¹Ò´ sL¸ñVáoø¯Å¾¶Ôlõ WÂ6ŸôiõÏ A­›®-àŸS°´º¹´ 3-Õ¤I{{K‹y¥üïý£à©þøûpü ýŒ¢øg®xêûÇzLúŸŽü[¢ßÝÛ^ü>køûÇz½†§Ð^?I¬é^¸bÑ5ļMSWÒ4k{KÍfþÓN¸ùWXÿ‚ä·‡¾¯Åcàg€õï øó^ðF§¢þÒ^ñš†µá‚š‡ÅíágŠáÑ|5y„~0ëwƒÃÞ¼ð,“êSÙø“Äq*÷^³Ó5iìÀ:ŠÿðXßü׿l3ñà—„uíà?ÅO|/øqá?üK—Pø£«]ø»EøMŸüNðÛøfUðg´×<{­mø—ÝÙK&‘oáÍFñ«sÍÐé7ÁßÚçGñ÷ìOáïÛG₵ÿ„~ºø9­|cñoƒõr|C¬ø_Bðîªêº›Bþ·»Ÿ]µºÓ´™5m[ ?ûCTÒ¯4ù[J¶¾žM>Ë_†¿ð\ù¾+|,мUáßÙÛBÐ<¯üEøÑàÍ/¿þ=x_á÷ƒuÛ_ƒZ_ÁëÉlü/ñÄ^¶´×>"xæÿãF…¦x'ÀQèÐ>¢4ëZÕž¦CªÝ€Yø«ÿ͋ᾃã¿XþÎÅÞѼvß ¼9‘ñsÃòøïAñ¤^7ñ‡…<ŸÚ áõ¦‰}âš>§§ü>ñoˆ´ëøüI}¨Eÿî‹q¥Xxƒ_N¶î¾Ác5¯‰^4Óü?cû3ÜiN©ð¿Ä>'‚MGâ–‘qãˆÞý|9ûWø«ÀZ·ƒtŸê3[éOèŸ 5?ZjWì|[ªØÇa¡_µ˜4€½?àŸ¿´¯‹ÿk/Ùá÷Æoi¿ 4kÚv–ž$Ó>øûþ'„ìu™|5 jú•“êÇN°m'Z²½Õç´Õ|-$º¬þž²¹ÕïnDÞXÚ”P@P›|bÿ’UñþÅ {õÓçÍxïÃ/|P¾øwà«Í3ã5Ö§\øgGšËJOxzõtëg²…¡³—¬÷B"?>`$—Ün&€<¢çâOtïÚ3Býu?‰~-²ñ/Šô/ëþñ*|>øy}¢êV~Òô}SY{Ë}?[¹×´pšÌVv7úî™§ØjwðOies4Æ$Û¼]à_Š–žñÕ÷Æ»­NÊßDÔæ»ÓŸÀ~¶[ëhìæií ÌS´¶ââ0Ñyñƒ$[¼Ä”PŒ~Ñ?µ&“û<|^ýœ>x¯TÕu?hˆžÖ¼_k£h?Øÿ ŸÅº–ƒðÇTñ’É™ÒÇâWÄÖÒ~xmÀ>µ¬Ìd‘aµœã^ý¤> øcƾ%ðˆ~=hÚGŠüi­jzµŽ¡¢iÖæ t|»i§ÝK ìé±üXøuky§iòMxÛ@µh·êpÆàÏí‰û=Ø›ÛmKãý†—5µ¾•©jöŸ„ã°»ÓÓ[øØÿ³½´ºÅ•Õ”sYÌŸá¾q¤–ZËÀ—;X€9ÿ þÝ?³Æ·¤[ëóüs A¬üWñÇÂXSÅž÷×>)ðÅËŸ€zŽ¡wõ¬3[迬 ð~â áŸ{ªOi¥Åqö `@·¿°¼OÿC­Ïþ tÏð [_Ñ|FºÇ‚Uüaq#Éâ;ՉΦ%Ç„|Ní |å£W‡k|¸”¿ÞE  Õ¾6)ý«¼1û,¯‹àŸ]»øQ®|WÕ/µBé öšÍ†•áÿh÷+g&Þ#¸°:ÿ‰o´ë»è5X|=§Å¨ÙYÜZIuqmú¶ÂÜΧƒ™§‹µ}·övŒòîÁaè¼3rUp8œ^c›ã)N²ÆÇ-£ˆy~U†ÅÐÃÔÂË3ÅO ^½*Ñ¥J©å­í}½Û&–¯½Þ‹}¾ž‰€xÒäÀDÓ0 â¿)ȉô¯†¿ ôÿxóâΙà ÃplŸT×í´{ïoõk«k;5¹¹+æÝ^Ü–ð&édv*ŠB’=Îá¬ÿ‹3(dü5”có¼Ò¥*Õá˰õ1X‡C S]šn4¨ÓNujJЂÖM]vÕìcÝüjø=£ÜxžÒûöˆð™sá;-#_ñ\7'Ã’hö>(Ôtm#FÕu%vCZΩ®è:u­Ëçí7º¦™l¥º·Wú,?…ž#béeu°¼ÄxšYÞ+ÊgC,ÄÕŽaŒÊðØÜnc†Ã8AûJØ<[˜bq^õ:,UY.J3’<žÏÏüÎÿö¦ø!¦ø‡ÁúE߯íÛ|PÔ¼ øÄvZW‡õÆZç—âl~Òm.¬ Ĩñÿ£ñM¤·Œvöiwoív$‚?¡Ãøâv+.ϱÔxc0U¸W ÄY‡eµðõp¸ü—/á¥Âo0Åâib#N5"ãÆy=Zt°ó«]áêO*q¡É9+¯u¹/}Ú:üNͤ»¶“jÛÙögEeñ÷áæµãŸ‡žðoÅ[/jž;ñ‹¼ ï…tß êV~ñƒ<«|FÔlÀò>ƒ«éöÆ)¯R6äÏü0âžà> ñ2¡‡qÕ|ã”J–"\fyF!P¾g…‹upÌÔqŒ¢Uã˜á°xªø~zte ê÷ÒÝ_>¿-ºî¯·{↟üqªxNûâ炼ãÿZÞxÿ[Ò¦Óü1£ëÞ#·Ð¼9ä^x§T äÏ©6—á/$Ô.žY-t ÷¥Ž–^6[ÀüaœdÕ8‹*á¼ã1É(ælª®gƒÀ×Äa!˜ãq8l*´ã$«â1xÜ”³¯ŠÃÒWX&vó½¼íkþh‹Gø¹ð¿ÄV1ø—Fý |©Ø½ž‰Ëq’Ëñü!Ÿáq±«¡,5\»ªªÙfK#ÌiÙAûø†qÍñQ½èà%õš–§ïþðN#áßí'ðâvƒðßYðgíàË»Š÷7rü:±¹°Ðt½KÄzŒz¤Ú5ØÓ´‹ä·½û{êÒK§œÀ“Ü^NÐ!’YJŸw‰|ñS„±üO—g|žP­Á±§>%­G <^)§[±ð«‰Æaý¦Rx7õ™MMÆS©7&Âé¤Óº–Ͼ­ißTÎûÄ?~x{Ä~)ðŠ>:x7Hñ6…ákø»CÖaðͦ¡eá-.ÚÒâï\ÕíiZ}®¥c,ó;+hoí‹mîùÜ¿Ãî8Ͳ¼·:ÊøW<Ì2¬ã6£‘e˜ü_ˆÄa±ÙÆ&¥zX|»Rœ$§‹¯W ‰§J—ÅRt+F7tçc­ºÚöëkµK§¯{˜ëñ÷àó"¯ü4·V6ðŒþ8*÷DÁ¶Ïu úôêòƒKG²¼‹Í›b±¶Q[ËjôŸ„Þ%«ÿÆÄ®ÙÍ>÷r¼L¹³º±£:ym>X?iŠ”1%ìáÌÒ­MÉ®dü×7ª}}5*Åñ×à„·>Ò¡ý¤>½×‹-¡Õ¼§¤¾iµku½×t+{ÝÝ\–Û©xsÄ:4/ «‹í'QÓ£ýý¼°‡? |M§G7ÄÏxž8|‚»Ãg5å”â•,¶¼p¸ t©bª8rÓ’Áf¹n1Ýé…Ça± û*±›/{{o;««?5­Î«àÿŒü%û@|4ðïÅ…Ÿ¬ü]ðÿâ”:Ö—¬[øcKHuDʦûÛk¨#™omd`š+È…Å´Öâ7 Ññã CåŽñ¡iAòØÜwmÎ[qÏ8Î| Ä‡Ã~ ¶‰ ·ñ|–ðÇàé1D€±b4UUË1c€2Ä“É4/ö‰ÿèu¹ÿÁ.™þaxŸþ‡[ŸüéŸá@ö‰ÿèu¹ÿÁ.™þaxŸþ‡[ŸüéŸá@ö‰ÿèu¹ÿÁ.™þaxŸþ‡[ŸüéŸá@}ñcFñ ? üy-Ç‹n.àšÛËlÚF„Å¢2 ß|¥Óç\î_˜ à>üvðV…ð÷Áz5îŸã¹.ôÏ höW/cðûÅ÷öo5½”QÈÖ·ÖšLÖ·pÇqo,‘J¸tvR xõícö™ð¿í!«øƒâA½ðE‡‰ì<7áÍàWˆô ««_ønÓךw¼_k§K«xÛAÓV õmDÔ-­­t­jk{øÚIlaÜô/‹~>xVð·ˆ´Ë];ÇÉs¨hº•” uðïÆ6–Ë5ͤ°Æ×WDp[BÁ–yäH¢MÒHêªM|¯ûHþÄ¿ ¿j=ö޶ø“¯xÒoüiÒ|¢ü>ñÅ—uØ+[+»¹µX 7wo -3å-ây.eÄ0Èã 5\^ž3ð˜J˜ŠÅb£Juå†ÃN¬c_ïR³£IÊ¢¥ Σ$}é ?&®¾|z»øêŸ´ƒþÍ>=âÌ_,~+Á«'ÇbæÙü5ÿ…BßG…¾×ý‚þ¹ð ·útº›Yÿm®¥¨Ï«­ÇœýÃKÅ hø}/ £âf\>ÄpuL¼+â¯ÔÅ×â¯õÕqCÍþ¥ý¢³J\G>*U_ê †§‚•.Fæ—ºìß=ôv÷¬Ÿ+‹Òö¶­Û¬¬ï¡úë࿉:¦­ámQñ·ƒ5ßøªîÓÌÖü3mg{â4{¿:Uû,zÖ›jö:‚˜–)|ûfhó!LîF¯âÜû ”`ó|~!Íjgy=ܘ Ö®–ÔÇQä‹öÒÀâ”qgÎçgU){¼ÛI j“òWé¯UògÁ´t?~!øoá^‡ð£áF³¬MðßÅÚ?ÅŸ |FMcÖ1èÞ?Ò¤ñ¯‡®4­GÁ¾+k5ñ”þñ.£J—–‚+íNÞúÎé/´p­û¼AáÏ ÓâÚjk}fçQ–/íZþ áo|Èòl“†q~Ñ¿~!éåøãßx·Iñd>*mCÄß|"Òê×6¿üGðríyî5-Râ{éôÍ«êw¶²YÙ\kp§húF›"XÛ¯|fð“8gÂpãœdØÌžy:Ãe^ñJ† •n4Êøâ§Ô©ÓËp”éáéæ9]<…hW¯OQýkÅ)b*;ÆÖ÷µi¶âú+/Â×¶—»I^Âi¿¿j¿‡Þ-o‹~x»@øÛ©j?ßÅ>3ñ?ÆÄ:‰ôߎ4?øæ;ŸÍxúF—q¢O¡éÍàÔÑ£±Š9t}6ËS•í&º _‹~ q.L¸3xê–eÀ8\7Ç(ȲŸ 8ƒ,Ì2œWpÎcÃÜ?:YÜ01Æâéã鿥žK÷~¹ð«ö¿ñW‰¼ âÿü'ñ5þ¹ ÇðªÓÇ ¦ø‡áv‰§üEÒþ |tÓ~>|7ÓZ «„ð¢i¾(±ŸMÖ.,%Ô¥Ö´»çØ4é`†§â€ùFUÄ.UÅK€ÌeƲŠáŽ<ÇâxgǾb¼9âœRÄÕÁS–q,^Sˆ§ŠÁSÄà /¼T*MƒqjךÖ2Ò=bÓ꺴ï»×Fºr¾ýš>;øSÆ <\fý_ÄMð£Oм9¦é^!ñׄ¦±¾ðŸ¾+ø‹âÿÃ;#â 6ÒÛÄ~ ñŠ5(¿á)»°ÖVH´Ûá¢iwú|R7±œøëá†q’qŽKÿ&¾X¸Ç˜æ¸¼f[Á\QO‡Î¸ƒƒ²Î â¼G>+&ÅW­•çÙ^S…›Ê(âpO)â°ï‹Ãâg^7¿½𶬛qV}bí®îÝ/esã_ìóûF|vø¯ãŠ>/ø#ñÄ:¯¥è‡â—‚îôß]ê¾ð.4„½½—K¹Òlµ_‡:/ŠF‡.…šž«¨ø‚ÛYÕïôëû[}?Ÿ€ükð“ÃÞÉ8K%ãl¾K,Ì0XÌÇ4©áçQÅçÔpy—ã],l°øbéc+àø£”<Â…U…ÁárÚ¸‡­W'Û¼õVø^‰µ¾ËWªwÖÚ)6Ñnm¯Ú÷@Ò´èôM-OÁpÝ]C¬fO+kÖSk:«Î²O¼áºÜˆÉ¸¾4+p/?£Â²ÄðŸcc„áž)Ž%gÙ>l¡˜ã1RÇæ3Âçµ)Rž ëp‚˫Ã2ë¯7Ê/}5ß­¶×{]ØÝðçÀïÚØÞÙJëûZÚóà^©=Ö•ãÏéÖ·:·ÁÚOÆß´ä‚C©jž Õ!›Æ¾3ñÖ§a⇟\½škhÿ´DòÞÜJ‹çfž/øk™,MâÖ=à«Pñ NŽ3‚x¯Zžü,È|'«†•L.[–á' ‡#áü&'(Œ2úáV_VtáBœ$Æàÿ›^Ví]Ź&ûûÍ·®·ï©úûEã?…¼1ð¯âG‚üIá©~oð¯ƒâxímB÷ÂËu§}»L´—û âgh.u'Òί-¥ ¿[xÿš¼vâ.ã3n0á|ÛûV>$ÿÂkZÿä:?á8ÒçÇÄŸøMk_ü‡@}ñcÅúmçÃ?ZÅg¯¤—ÖâG¸ðþ­o ³ØL–y­R(½$Œª£$œPQðkþI?ïû´ý7A@ ]øgö¼“þ ðóÆÚö›uqð l~0ørËþß_ÿÂ%¡xA<3á)þÎþ!Ò|Mð»QRºmÖ¬.ã„ä¼”êÿøoRXínt%p ÏÚV÷öʰҧñìë¥~Óšî³{û(þÕ·Þñ‹~[·Åo |@Ö?h¿Ùo[øUðöòGÓÛV±žOÃñbÎÇEÔe‚Mw@ðŦ¯«Úý³MÓ¤@¯>OûBÙ~Òž,øsñ3Pý¤.<5ð×ÇeþxËTðí½÷‹µ¯ž–ÞçÆþ3h¡†/‰Z7Æ=WÆî‡Y¶_è6&ÔéÜÓª(ñü‡<ÿc=ÿþ¡ž+ ý®¼SñwÃ?ô¹þ xoÆ>"ñJkrkWx>Â[ë‹;ÃZ]ö°t ¿& ‰bO_Ãc¤Ä ¸ß5±ž#($ê˜%ó¡†m’GæÅ¾\¨ÑÊžb†Ù$nÇ"çk£ÊÀ« ƒ@‡ÃÏù´o÷o¿ôåy@Íñ«ö½C™ðœØÍqãX­a¸Ô¼⟳ÃáA­ãK§‹dsEu¤%Áº»kñËöYíÒiœü€Ÿñã÷‹&ñü%øà½ëàž¯®x^Ñü7«{Lø§éž·mMqm(¹¼Õ5_ëwZ!g¹Þ¸i8¸@=[ÃÞ*ñÅ׎¾I¥üG‹MñÁÿÛÞx_T¶ðþ™ã%¸ð<º4¾#i-=_g·ñŒQÇu4e­$E1âkw` ´—ÄŸŠß<;¢ßü%øs­|FÖe½¾½Ôôí+I»Õû+GµIäÓY¤“[ê:ä×ÛérˆM½Ù2«¤i ¤xâ—†¾"ëtOG«<Ÿ |oÃßßÞéÒÙé—^&>ð¿Œomt;¹ÝV"Çźn›ªÜB¢;=z OIrntû€ ^­ã/‰ðü^OZxzX<i™—R>×5U×-îü?ªßÞ^Úø‚ÅN—¥]éZÕ½†–º]ñó®Ñ¥uG{Û"€Q£|DøòÞ ø3meámu|Eâ_ˆ4ðÇÄMKÅÞña}BÓßÄ×úŠžÖ;xçÓtÝRk_i¶jj¶Ii¬È|ÂÚ\†€4ÓâǨï5[û¿]*ÛÅi³h¶Þ ñ=Æ­¦hx‹]Ð?´ôûøÑ­ø”½§ŠtÙ,ƒø{MÑ|{†£ÑÞåÒ(VK©"–kV’EãÛãÏ퀞ñ¶ÿ.ÅÖþ"Ñ!Ð|$š^µuö­;RÒük.¿g>¥ Ú¬“GÐ5 mh<¶þ!žõø¿iñZúëYøMáßˆš–³ªê ñf¡ðçI×>èš6¿ã Äž-ð¶…ª[Ø_xKñ™wªÙE/Ûµõ¥˜¸Ôt­RÎÌFoÛàzxçÆ¿ ­~+øóSñ¯€¼a­ü<ÖôM3áw‹îÞãÇÞð¥¯uïh7ƒÃëaâ/i~¼‡ÆWV:5Õáÿ„q¿´¢y"hÀ}Iáqqã xwÅÚŽµË ÅZ“âMâïC“I»ŸI×,-õ=:k­+Vµ²ÕtÛ‰lî¡y´ýNÊÓP³‘šÞöÖÞæ9"@ ßøFµïú5Oü³ [_ðö¶šÇ‚¼_©»Ëâ;ÔÍžaaáÈÒ.:³"48O®i~°ÑíüE}¯êZTZÓßXèÖžº¶×®uK¨"²ƒFž-RIÖÆEœ€q–´÷Àk뿚lß´¯‡ô}gö•Ñn¼Eð;D×®ôUø‹£Ú4}³Ãö·’Gö”½}gJ‹IRêúÜ÷öði {;4j?Ä/ÚKàÏÃoxãâf«ñúÓÄ>øiâ] Â.>&ŸñQðˆüG¯XøoMÒ¼C£ø9õOJ¼m_Q¶·¹‚òÚ)­A–I£U†R ã‹|ðÄŠ,ñÅÏ…|áÄ<­Ùxmnš ;EÓPñˆ¯¬tK+½OS¹·Òôã-ÌZ]ßKohŠ© ‰7á/Œ¼;ñÏá§‚>0|*ø¯uâÿ‡?¼;§x¯Á¾%³ÒͤƇªB&³»z•µ–¥e!RR{-BÎÖúÎá%¶»·†â)#P ž?ñG…~è‰â_Š?ü=ðãÃ’Þæǯøó\ð¿„ti5”–X,ST×ï´û'»–+{‰’Ýg340O0O.Y@8µøÑð¯ûCâEœÿ´7†¬­~iž Õ~#øƒQ×<-aá_ÛüC[ù|%·âk­B-N»Õ °PÚÞ]Á7Ùu-à)‹W°iÀ"?þƒáðko„ÃþÍ?UÕü,Oć x“JÐî5;MgSÐXë»u{ *ëEÖmõËqog6‘ªÇq$o§^@)jÿ´Gìõáó׿l_ƒ+Nþ\+«|Tøc§4Ò3JÖ‚F·~!„»]ÐõPª ;ZÒo@û6¥g,À;âÏÛÇögð‹>=ø*_º¿ˆüAû0ø÷âGÇ[øGRñ¥¿Ã¿é°é·šŒzÍ÷‡¬/í?¶¬4ýZ×R¾Ñ-¦¸Ôm,Òõ®!Žm7P†ØèËωŸ4ÍKûZý¡ü%áÿ§„.<uá¯x“ÂZ‰tïYé¬ê)Õ4 WPµÕ´Í MÒ’]CSÕ/­ ²Óí ¸¸»ž( ™Ð£ðf½áïˆö7ÚŸÃßš4Ý2üiZ–¡àÍgÃ>(±ÓõCceª 6úïD½¾‚Öü麖¨ 9äŽãì7öW~_‘uŽÇÞ|`øC§éÞ1Õïÿj‡ZWÃÍ^ßÃþ>Ôîüuà;{k×sOoi¢x®î]a ðþ¯uskumm¦ê²Z^Ouksm/=¼Ñ 'Æ/ƒÒêÖÚµ/ÃI5»ß Ùé ãß>¥wàc£ÂF Š7ÒŽ‹ÿ_µýƒý"€ ²ø×ð_R¼ðfŸ§þÕ ïµˆÎbø}aiñáõÅ÷Ž%]NãDhü#i´÷#‘u»K­ÓHŽí—W·›L`/£x¯„¾|~ÓüGªüý¡<=ñ6ÃÂ>(×¼âyü©hš×ö‰<7®êÞÕtíJ+I¤šÔ®¯¡j°Ø]KÙëö¨éÚtÝÈëßðkßô:jŸøg@ü#Z÷ýš§þÙПüWÐu›†~<žoj7qEáMmä¶’ÒÕRtn‰Ù~eW¼€xæ€8†Ÿ­4_‡¾ Ò_á×ÅmE´ï höm¥øNÞëM¼h,¡ŒÜXÜb&žÖR¥ •¢ŒÉW(¹Åyf¯iá~О øûâ þкž¹ðîÏÅ àxnÃCðýÇŒ<5gá/ê,ÖvÚþº.´¸$XmõÝGQÓôë»Ùî,¡‚U·1{_‹~7Yêžñœ>üZ²kýS´[»ÿÛÛÙ[5ÅœÑ,÷“ÿl¿“m`ó˱Ìq}¬FÒó¿Çߨ³àçí) ~Ѻ?Å=#âVµ¨þÐzN¡Úø°è>ÿ„§àæ™á]&Î×Ã0ü'Õ¤æÐåÐ’iÍ-ˆ³¨é $¾Ó¼E¬êÚÖ‹¢i÷×T×ñì;àý_\×Cý¸dO‡·Ï„ü)ðïâÞ¡ñ·Hø}ák¿ê×þ ðchºn“âkÞ Õ<-áox£Ï7w—w¦Ö®¼Sá+/>5µÿ³]ê¶zŒ6ðD¦¬ÚiI^-¦”’m7ô’M4Ú½šiëp>¥øOeoð£áwÃ…Ö–ŸüOiðãÀ¾ð%§ˆüIe§\x‡]µð–…c ÛjÚåŭ͵´ú¶¡‚]jAoRÝË,‰ ^ñ`ƒÂšL_ðŽx¦m‹yûÈtëv·jmò±¿RqœÌÖ€? ¼ÿzø/ñáf¹ðƒYøûN[øSWÕäž9tý/᥾ºž—Tøâðf·®ÿÂ:ÚŸtÁâÍâÈ5_\ëž"µñ?‡¼;­ÛêÑߨyÎû=Á,'ø}ñ;Å?¾#|M´ñÿŒ5Äø3«|?Óü;¯€ümðÁß³/„uýBËÄvw–zÏÄeø á[ßx/à½ðŒO¬êÞ Ñ´M?W¸kØÚR—Â¥'Ú)ÉêÒ[_vÒ]ÛKv‡fÿ¯;~§ÕýƒüáH?dìŸü]KöCøM«üð~·.ƒðæ]SÅ u-wáþ³g£ë— ¡‘¤_èÑ|2ð–“aâ/.ƒ¯I¦YÜGw¨\I}w$¨Gο?àŸ þø âw€üñ×öµ²ãÅO„?>$x‚ïOø]©ë¾*ñ/ÁMNËÄ>MV{ÿ O Í­ÏŠ´ÛøÉ \øWK©µY®SRÔàô_ö¢ø3áïÚ»àëü ñÍׯÀÚÖ¿áÿ[øJ+L½ø‰á ê–ú®©ð÷Äw$ÒÅá?IiŸŠ¡ÒM…õæ›çXEw µÕÄryçì¥û7Ëû$øgáŸÂ¯xÛã¿ðSáO„~#hþðW‰´ }GSñĉwž>—Xñ·e%£_Xx"Ææ_ xJ··µOÓõ=ZmFMFs§=ˆ—í[û4xSö­¿økªëúůßü5ƒâ›f4x/\ÒµÝ⎇¦ø{ÅúN¹ xÒËÄZ$ÒÜéz\6Úv·oa½¢ÅuªE¥j6‘ê·ë8;8ÿ‚nx?Ǿýª¼+¬|[ý¤"ðÿío}ðØøÿJ´ðÏÂx¬ô|*ŽÒÃÂ~ ðü'ÂÌ‹áÈ*ê±ñ_ø·ªxÏÄÚwÃ?ßÜø§Âø¹ðûÏÕtoמñºæ‘ñ›Åz–«¨x‡KÔµ?øIÖÇĶ—vúÌow _â¿ø$ÏÀx_âÇ€µsãÍ¿€þ(èæÊXhÞ´ŸÀš¼¾øwá‹cÂ&‹G)¶²ŸEøm¥i?ð†Þê÷~ ‹CÔuà&‹xl”·Âoø$ìûðVøkªø{\øõt~x‹áŸ‰ô«kíáúÅ{©|9øÿ­~ÒS‰-4k{‹¼kñQÒeñzé2ØCMð®gmå2€}±û$þϾý¼'âx>ûâÇ‹<5®xŸWñ•câÁðIá•Öµÿx–ûM´¼ðõžw¬,Ú¯‰5 ¦Õ|G6«­\O"Ä}eÿ ÿ¡_Å¿ø,¶ÿå…ð™úü[ÿ‚ËoþXPŸ|WñP»øgãËoøG¼MmçøS[ϹÓíã·‹u„ÃÌ™ÖùÙ#^®Á’žSðk?ð©þgþ„í¯ýƒ Çé@šÿ¼ûExwöøñŸŠ<~Û þ1~О"ðu—ƇŸü7àÿÚÃ:/Ž5Û/ ø‹áªëÚ‡ìÓðƒVý|MàëIüC¡ÙÄ5Ž–~<ðn›§ÜÚ\x¡üq¬M§ë:ä–>!ðžƒb™ð‹Äßµoň_äѾ!þÖ·>_~×~-ø§àëÝ'Qð†­ðîûC°ø-ãÿÙ³àW‰|Uã­>ÎçÄzUõ©ñ^gâ™íãÓ«ø íygûføŸÂ|IñÄü:øey«è^¹¸ðï‡õo‚¿> ]ü,ð%·‚|Lðφþ*C¯iZÂø"]wÀÚ‹|cá/íOý¯DÓ¥ñ…ëÃá|C{eŸkã»­^Òt»ÈM¾¥g™>¥ªiПGOpœoų—ð¦mšð}L·4ÁK?†_Äœ›$Îmƒö8üT2J1©TËpø‰âkpõË.ÆbèOÚákÏO „Åš®—vÑ=/w§Ë»è®ú"ø‹ö ý£G‰5ïh´÷Ãa¤sã&½¡|ã߀z÷Ž|K¬j ¨Ç©ÝÉáý>öÖûLºµK+ïèl³Â_ ÞW—dù‡„ÜRñ«ÀÙvcÄË$ñNž1âsÿ 8‡6ã,îO©<q\;â6]ÃùN °ÒÂÑŽe‰¡[‹£ZUðâNêïMoµ·\ºêõZ>×¾Œð¯‰´?Æ_ŽZgÅÄ^:𵞃¤ø‹â%ÿÃ]?SøÁðNÓ[²¸ñ?ì©ûyü8Ôt[mkÃú׆­5½?j#Ю„¶pêþ1±šÃZÔ£ŽûPµý …<3àñ|Ëx8¯˜ãrÎÃñN' Á<{[ˆ§”øÁôwâŒ.>®2Àæµ°ùäøoe˜Qu(Wž#ÄC€ÂNx|5dïwÕnŸ¬gif¬ù_{Ê÷ÓÝû3ã_í‘®ø?âwì³áß…>Màað¿þ>¼Ÿþ ê>OÝxÇDð÷Å}nïæÖôÝSÂ>mGÅVÚ¼^ °µºq :޹m©Goøgø—g|'âîiÅü!ÄÐâJ¯‹Ô\¹ðwá³Éft²<~gÂXŒ»Øáéà1X<ëˆV'«‚ž[‰­EsÏ0Ä`0Õp²©R»»[ó]¾œ·Wwo³¿Ko®Çœ~Û_ðRíϳ†¿û?|ðoü=ñOÂ^6ø™ãqüEð¾ûÅ¿üáý3áö§a«x“ÂZ½î¿s{qaeâëé/¾hÉ‹üA¨GŸ§\Á.›}?€ŸE\ƾuâŽ]âO†ùïf|!d<+eñË8·’ñ&{™bø— ‰ÁåyÖ†]J…e¥×÷]Ö·ºwÕ¤sÞ6ý³?jÄðÆßƒš*øc✿®|O¤ø¯à߈|Aâ¿ x?ßµ}'öŠÑü1c®j/'†þ)x“ZøCáý[Ã0[ǨhGÂÞ#Qg¦éZ¶¡ªAéd>x=,Ï SÀ\s–oÂãZYN3'㜷-ɳ|ï4á<7Ã,vmˆÀacׄr¼æX<Ú¥Yaó팱ýcŒÁá°• [µ¹uݵf”[º×g;EÞÏâ·Fþ‰ý¡?lïh~:ý˜t„ßþëp^Þ|<¸øÉâ 'â_ÁÅðäWßü |KÓ5­/QÕ5=@g5/x·L¿‡Ä¶pÛGb¶º_ü$:ݺÅæ^ø‘f=âÎ;Œ¸;‹²ú”(q5>Ëq¼+lj(OÃñ­Ý׋ïüQž­ðGÂþ%Ðþx¿_´ð†›y¯jòèž!ðV»ñÎÓÂz…­höJº]ÅÞœ|Eye|nôï¥Î|ðo*âŒWöw…<[›ä4id¸|¦uð~"TÃfùVaâ6K–×αT2ì3 ·>˼>¯œæŽ‰¤åŒ§G²ºŒ?±Å4›Q»JN×ë¼lýW3ºÙ»k{¶~~Ãßµ¿üDý¥­ xëP–ëÂß ¾7k:§Âo„:þ•á­_\ûˆ4›ŸÙ¯ã溲½¶Ð|¤kz¬ñD ¨@:þײwì×âï| ðßË–šoÂHþ&Ãâ;o…Vö¶~ðî©ð«à‡iŸéߨ²xë×öÑÜ|,ñF‹u ëŸØé øƒÄouáË]PßYÈÌÐxwöãø=¯k¿ü9{ðÛöð†­ñàhëðºÏÅúÖ“asâ‰ü]àŸŠ¿<¶±iŸ5Ÿ&×ÅÞøCâ+¨õ §‚Ó@Ô5 i$}.ûT¾Ióÿ‚‡~ÍÚ¯ÃüFд~!‹âO‡´}SÁ¾Ðîõ KÇ:·‰çð‡|wã/†  ÛøÑÅ—Ä…þø{©·ô»¸­t½cXðÖ‰g©êÚ¸X?@¼eáŸx;Â~7Òÿá`éºgŒ|5¡x«NÓüKªø×Þ#°±ñ—k«ÚYxƒÃÚ­ý¾©¡kv¶÷‘ÁªèÚ•¼ú]úOcy wHŠOÅ>Ю5X]I®]ÙjZæ§c}kwâ]~ê‹I|â“4/úŒ‹²tS ÀæÛÉ4º)¤FÒ•Z´*Ó¯B­J5èÔ…Z5©NTêÒ«NJtêÓ©¥ šS„âÔ£$¤šjà|áñ¯áì»ðOFðŽ»­|ð½þ›â_ˆ>ðEÜöú| ‰g¯5Ûê$½ûòÿfxoK±¾×uf†Þq•§_\Üg½·úÿøˆþ!ïþ¾qÿì¥Íÿù¬<¾_.ÇÖö<9§YÚéú{kÖ66ÐYØÙYø£ÄVÖ–v–±,Ö¶¶ñjiöð¢E1*Çh¨Š@¯‘¯^¾*½lN&µ\F'V¥|F"½IU­^½iº•kV«7)Ô«V¤¥:•&ܧ99I¶Û õgi³ÿÂèZ&µãOi~*Õ’ÎâÆ=G_óõK¸¬ Õ5†Î¯%•ᵎI§•mã+–y¥ ¾Y½¼«‹x«"ÃK’q6“á'ZX‰ár¼ß€ÃÏ8¯*8jô©Ê´áJœ%QÅÎQ§ÛQV#ŸÂŸ°M¾—®ksè_ãÑü7w¦ZkZ™Ðµ/°ÙeõDÒµµ 8Ãs¡_XkoZ<ú ‘é·³ KÊ·‘×Óÿˆâýœcÿ‰&oÿÍ`2矰œsxêÊÓ¾Õ5‡v>'¼ñ6‘c£\5Üx>gñŸk,öÐÙ_êZTwV2_YÙÝÍ-•¶£§ß]ˆ,/mîd?â#ø‡ÿEçÿâI›ÿóX]÷þ¶6¬>~ÆÚ‡t/‡Ið×ÃIãø'Løƒ¦é_ð‹ÞÝZIá½Yõí®$׬mn¼<’ùš]ê4-ªâ4hLÉqÿˆâýœcÿ‰.oÿÍ`fÿ¿ý/tÍ3YðçÂß ø·J»ø‘¡ü.ÔîtmÒ9<1â_]YYXoXkSi:…½§Úõ]d6–·wf×W±Ô­í.4æ{¤ñµ‚êïNðæg¨ë׿æú×O·´Ò4ë‹ËÔu ›»¸!´°Žä]^ÎémgÅܰÁ"ÿˆâýœcÿ‰&oÿÍb¿õøþgQ þÌÿ²ÿ‰´=Äš'ÂÿßèÞ Ò´ýkI¾‡MʼÓ5[H¯¬n£ÈeŬñJ¹ÁÚã#9£þ"?ˆô]ñþ$™¿ÿ5ÆüBøQû|)†Æãâ„>xb-HLö{¤Ï6èmç³µžîe²¶ºkK¯5-6ÅïîÖ !¨jZu‡ŸöËûH&?â#ø‡ÿEçÿâI›ÿóX“x+ö‚?LÞð‘ü8¾:_Ž^Ûú­àðÖ¦º‚i¦ê_dÓf+¨Gu-¹–Ê1-ÌVwv:”‘.{iw1ÿÄ?ú.øÇÿLßÿšÂï¸é|ûC<–óhÿ ã0›‘-Ä–N¶ Ÿ­þ&\\¶¦`p±Àwv¾'þÐûWØ_M¸‰ã¸idX‰ÿÄ?ú/8ÇÿLßÿšÀõ„¿ ¿g;û|gðkIÑl ºkÍ ÷XðŒÚŸ‡õ{Kˆ^ûEÕRÓµKIa¸ŠÖâ}3Q†A—& åæÜWÅ9õ x\ó‰3ìç J²ÄRÃæ¹¶;Bu ÓUéÒÅW«UTêT‚©¤¡Rq½¤Ó/Óçùÿ›&›âÀÈ-|Cu/Ä-\ ø…|+®Ú'ˆ¼y.«g¯¼W·1éñè±Jú½ûIk¦ê—‘ϧY]ÚÉe¥j·©;Zé—ó[øC/Ä¿€Ís ¿'ŒZxwþ©îŸÆ>/]8hƒLÓu“pš©¼þÍšèiZÖ~t¨näÕ…¶«¦Èlq}kæ€7Nø›ðWÕ<3¢é¿/nõ_À÷”~*ñ·›t‰­^xmãº/p©¤ÝX]xtÙjïayý¾‰£yÚSÛÚÊÑü2Ö¾|_ð¼>1ð½ã SAžæâÑ.o5oè²ý¢ÕöOÙu™ìn]Qˆtq¼ r«+2º¨¡Â¤Ïð®ñ7ÿ-hÿ„#HÿŸßá]âoþZÐÿF‘ÿ?¾&ÿ»Äßüµ þ#þ|Mÿ…w‰¿ùk@ü!Güþø›ÿ ïòÖ€<÷âÏ„4ËO†^<ºŠïÄ-%¿…u©Qgñ?ˆ.afK˜,¶óêRCx[Óí<5£ÛÙkxÓÀ–pjvñYB‘ßCi}¬AymÊ68n¢ŽxÕ‚Ê¡Á OEñ¦ñ³Ç:Þ™ð>uøßñÃ>‡ÅZEÇÆÏ†·¾+¸ð‡SW‹Ã_aðߌ¦¹Ñ´)|A«ÝM.“¥ÙÙ_ßê3ß_=ÅÓ, Ñ<[ñâ…ç…üEkðĺ]•΋©Áw©KãoÜŧÛËg2M{-½®³-ÌñÚ£4òCoÏ*!H”»-q?ÿf†¿<'ûCx'â/Â?x§Ãµ…®•ñzËPø)“RÒ¬ü7cáK]3ÃwÐëq_x"ÆÛGÓà°øBãEº“Ýk¶¦nöïP˜á}ö0ñŠÿi¯Ú ø¿Æ^0Ö¼#â_é¾ñÇ…t_ˆ?´­gÄ¿üoð~„^øwãƒâ/ßü4×55Ñ<1¨_j¼|Þ;¸Õm¡Öu›? kú°Õ5ªlÿaO6?ðÄë_ƒþ>‹Æ? ÓàÁðò|rñrXÛÝüð§ŒüðËSÔt8üfšµ©éø…ã jÚ¶Ÿy>¿¡ë·–šÛ_–Yψbï‚î‡g¢Ø|ñ'fÒþ;øËö–ѼKðËâ¾·ðçÆzƈ˯Û|Añ~âÿx§Iñÿ ®™âŸhž#Ñ-¯ãÐ5W¸ÓŸLGj-À>®ÐåÖ<9£iZðúþÛJÑtû=/N·éWREec[[¤—WwÓÝÝJ"|Û›©æ¹¸“t×K+»°V¿®x‘µ³ø*ò7Äw­ sDc;Ÿø Và„"7y·¹ ˆŒyß"Pñ_án…ñ²ßI²ø‘ð³Rñ¢Ûøž+.oi±ik?Šü?wá‹ýJm>+å´¸Õì´›ûèt=VXšûC–öò}2{infgôÍ&÷Äz>•¦iþ Ö®`Ò´û=6 GÅZV£¨O ´vÑͨ^^Ëw{*DêòêYn.§i'žG•Ùˆu¿'„ô¨âð]ÝÌAo”kZ*,€êe¾I. T†àžAáÞ$ý˜üâïx‡À?Ôü'´Zfqñfñ­tM´WÃ+áÝ p¶—£Ã¡ëZ……°´hõ XÞÙíïâ’ÂÁí€+x_öoƒF»ø‘}­èž1ׯ<{®ø¶þÆêßÇwº4¾Ñüc§hÚV«a¤Ãÿ †£a½y§è¶öz¯‹ô»-RÕmÚU–¥ºÔ&¾ô;/…vÖøV{ øùeð§…â”üPÍ®xZ&¸{-'ÄÓÿkùúäZl—w/c5܆ê<ŠÓº´Ãh?³7ƒü/áɼ/áßüGÑ4»¯økâÚéîlf¹ñG„4Ý Iðýä’[k…·±³ðLJƒéñ,v7·T×Ö÷7²\ÜNìŸ|.¿4K/ øÓá¾§ªè6ž"ðÒá)Òíì5Kï ê¶úÖ“m­ÚÁzëBjv–—w:> “é÷’Û@×ò“h ðãáü-ñ%¶¹á} â/öN•ðëNøiá¯êmµxcF´ñw‰|ay¨iÅûD5­N}{NКþñ®›Ið¯„|5áϦ•¥Û]ÛÞTøéð~÷ã•¶ƒo¨øs[ðìÚeä0jzŽ•â8¢Ô5 6­¤ëš·„›û;ÅEƒZjú§‡ôK‰_]°ñ„ÄíÒ$yš@µðÃ~!Ò|W¢kñÅþâÿ7Ä]JÞçâi™-¼M*ÞEs6”²ê®šm͵ýųé¶ê¶Q*Ú\ZÃo}acun,_³ÿÃåÓF‘sðgQÔ´óðŠ×àlöÚ¯ŽF¡ßëKH´øôë±s­?Ú5WÓíí¬'ñ4™ñöV¶Ö’ê"€wÿ |%ÿ ŸÃ_ðŠøGáî­˜Úæ«1¼ñ>‰wsq|cÏ$†á~î"DŠ8ãT‰~RåÝ€<ƒAý˜¼ác«Mῇþ=ÐõWSÐõq¬ißn Õ4ËïØx¯GÓ&Ò®¶mdþÃñ·‰t]Bc³ëZ‰“Wšúú {È€:]Wàg…õËoéšÇßê~ñˆ¶ñ†/¾&\\øzöûÈÒmÛÄ-§K®2ÿÂI д‹—ÖYÚëûJÐêè˪Ý^ÞÜWÐþx[Ã뤮ðóÅÑ þÆ·Uø‰0K?…¾"¿Å=.æâÎ×R·²y¿á/ssy¶Ú8ïtð4‹„}4}˜€z?€ü7yðæÆÿKðïƒ|Rt«ÍBâúÛLÕ|sg«Øè©q<÷-§hP_j.™¦¤×3»³‚O ki5ÓëZ4«o°˜4Í3´²1HÔ»ãjòhªø4øOðë ø£´ϡӠ þ äzƒšüåÒfްÿÁD/>?\xnü'ÄÍ{]–òmsÃw~o]þΚ7Ã-#ÅZ™öÁñ+LøêÚþ/†5û[›Y>]øâKÛXáñ ¼S~›xüào ?ðkgdàiןÀO É4ø?ûk|ÿ‚ŠüEø¹ûEj¼ñEð׉|ûAxÁ ðOí¥øpø|cû8ü³ø-â{eÕü{ ë^ o|pðGŠâ¾ðÞ“cáÝÃWZŒþ-Ó"ñdþ>ñ¦£eñ_ö@ý¥¦øá.…ð¿@øÑkû3KñköÖ—I—öÕ„ƒáÿƒïÿiCö°ÒçmWâÜþ({]V×âGÃÝ?[ѾÙ,1›Ntõ½·ðíÊ|“ðÞçã§…þ5þÈ??h/ürºñÇÁï†ß²_¼;áŒ~Õ ñg_Èþ´ùßÿgÐÿm¿~Ëz‡Ã_Ø_Á#Åþ!j—Z'‰õ•ñW€<=qáo [h¾§Ëoˆ—~•©ZxŸÄvº/†uk?TƒYд½BëU²°ÕÄRÙ0è'Âåñz|3øtŸaŠßÇ«à_¯à,£‚¯‡ôñâXaM6âïNH£Ö~Ú‘¦Ÿwud¨ ZÜMŽF›áïü‰Ú7û·¿úr¼ ç¿ÅrÿÁÀþ#Õ¾&^ø`_xKñÆg½øw§D¿±ûxá5¶ŸñI—ÃÿcÖtÿ˯Ç%þ§ð‚|O«øžox‚/ xº[Ÿ ø µH[Qïþø›þ kÅhæý¤þ ÜøãàF—û3ë~ñG€<9ãÙ‡LÖ¾)|jÿ„sÀÖúgˆôßè:σµ¯ÞøƒUÔ|zž ·Š]+ÂÚzM´š WcR°:p¡üøKûXxyà’~ñgìóñvÖßöqðLjoÿhïˆ:§Çïk §x·Ä üiðÂ÷A׬m~+^j|:þ-Ôì~(¤òéÞ%¸Ó4»Yé­ý¹ˆ4û0¦à§šÇüBÏඤÁ7ü)g©ü_ÖuýJ]kÅ÷Z¿Â¨G„t­'ÃÚ…Þ‹g'‡þ.ƾÖtïx‘ôý7VÔl®Ž±áë+W¸µÒõD½™m€>ÃøUã¿xŸPñ/†¼að÷Äž—ÀšGÃÝ>ûÆúÒév:G¼k®øF×Ä>5ƒÁúUÝìÒhž¸¿Ó4«Ï,Ï¢ê> ºÖ4m{ÕðÕõÜ€&ü_ÛƒXý¶<iðíþ%xKö?ð§Â{Ý{Æ×¾‡ö`Õ-~)ü[ÒõøøÕuñþ9<}¦øYžë³ü9‡Dµñ‹bÖZ¼ÚŒÒÅuo8ê'‹gÚ?…üE«iŸ ô =GLÑu+û ¸…ï›myii,öóǺñ—|R¢º†VRFHÈ  ~Ý¿´ä³ÆÏÙÞÃAÑ<ÂÝÇ¿Ûö¤Òu?ÜÞø‡YøqûN|BÕ¿g…wžÔmínÖÎ÷Àß&â‹íPG«xkÃi¢Ø<’j²C(¾%~ÕÛ|Y×|ì÷â/ xá—íÅû=~ÉúçÅ? øÿ᜷¾+ñ§ÅÈ~x§EÓ¯< â?x’õ>ê¾øß¦^麦…ãKy4kÍ;ÃúŽ›uu§ü=ÿ‚—|*ñš¾£âÙ6Oj:žà6øe4Þ2ð÷ˆ$ñÿÿn+¿Ø*M3Äú‡ãºðNŸ§|]mÄw·6ø°ßøT¸ÔÓNî”t °ÐïÙWÆÞý¥¾ h¿/>Ù|7¹ÔüQñ'Âw^¼ÕôïOa©|/øâ¿†ä«­i¶¶V—–wzÿƒõ[2U¶‚YtÉ,縂ÚâYm`ú+þßÿèWÒ?ðÆ€9mÀ^ ‹XðDqøoJD¹ñìS¨¶KøGÄóª?<¨š¥Ç÷ãSÚ€>¾ñÆŸü§FøRºeàøO/Ÿ†—Rj.€ß´=Þ•}ñÒÆy|,ÖYb_‚Z¦ÍâõÔÄQjOiáÔ´%Ì’Oáü:Ê'ôXÇqƒÂeë”8Ú—ÓÆK'™/ èâðþâ! áby!)qîa„K$xW9ác[4•gÒŒ^¶ég×í9_krídÛn^VÔýÿ…wàúôü_ñ¯æ3x×Åÿ>|8øw©Þ|0Ô~ ø§â7,~xÁþֺlj|a­kÖgUñ~½á¿ évº†µÍRïPÖu»( 8ÚÚ‹½JêÆÊçïyše\c•árϳ®¥‚Ë£Ãø,߇åše>0eØŠØœáÔ­O*xNW–ËÆ×JWå´dîß6«Ý·5Û»×–Pq’3»R2¹é6´…¯þÑþCðCþVçâ'‰<'ñ#IñÔ>ÕµdÐdøâÏ‹¿üGá-_À~2ñ'‡Ö=r_›]RÓRžmFÁm¯m%°ƒÏ±ÔfùlG‚8 »Ã>&ñ |Q‚â<ÊóžÆpüs\YŒ|BÉx/‰2ÌçÄYW™JY|sEW _ NlK«B´191ZumjÞõºkk¦ôoGçgÝlÍOƒŸt‰¿µ_Ç7ÿ |)¦x/ÁÖ:”¿ <[hn¥×<]{ð¿Xð÷ƒ¾<Ãâ6cö}xçÆþÓ<öã> ÓWÔœì†äã0<)àÿx‡‡Î1x¼÷<ÄaaÆ95z4a€Éhqn 3Ï<;©”b©þ÷<Ó‡ò çžF¯ü‹qk…åR µò³WNí·ßKim5æwmè­w¡ñOã¯ÃßüOñ'Â]áýÆ£àCö`_øöïHðÅÿ‚t¨¿i¯šÂèú`ñÿ‡üi¯j¢ßÅ/ªYè—:…–Â×SÔ›Yy!ðþ¡Í ÖϸK+ã%xK“[ü&‡Xñ‡Ãgá÷Æß‰cÆö7©ñBéZxoövø¯çxÄZ¾•â™/ô½Ö‡ˆ!–×ô}8ªŸG#«Ç¼¨aó¼Ã…s¬æ Œ§É8³ļ ÄP— S̱µ+f¾'pw&e•à±™Dpø¼Â´ñËû:q¬œ¬›Q”š³Q\·—2mZòK[?‰ÅÝ;ÛFÿJ<5áox—Þñ~ ±Óã×ôM+[K Ø-^òÅ5[/–Îíìî.mæÙgÎÖ·7í*9‚yb+#,æ¸ eY¦e–J½,L²Ü~3,MUQÄKˆ©‡uèªôéVTªºn¥5Z•:ªJ¥8NñVômy›ÏðÿÁrmßá½-ö(Dßíˆ:"åŽÕ”`¸3þßÿèWÒ?ðÆ€øW~ÿ¡_HÿÀeÿ?á]øþ…}#ÿ—ühÿ…wàúôü_ñ þßÿèWÒ?ðÆ€øW~ÿ¡_HÿÀeÿ?á]øþ…}#ÿ—ühÿ…wàúôü_ñ þßÿèWÒ?ðÆ€øW~ÿ¡_HÿÀeÿ?á]øþ…}#ÿ—ühϾ,xÂ? üyyiáÝ.ÞêÛºÔöóÇnHfŽÆfŽD`rSê;ÐÿÙPK!‰k¿ºgydocProps/core.xml ¢( |’_Oà ÅßMü„g;J«Ë$]—L3_¶ÄèÌŒoî:b àþ|3ßýbÒv›[4>Â9÷Ç97d£mU¢5X§ŒbÚ‹1-ŒTºâ—ù$`ä<×’—FÃïÀáQ~y‘‰š cáÑš¬WàP iÇD=Ä+ïkFˆ+¨¸ë‡âÒØŠûp´©¹xç$Žû¤Ï%÷œ4À¨>ñ)ÅYزHA „ ´w„ö(ùñz°•ûs UNœ•ò»:tÚÇ=eKщG÷Ö©£q³Ùô6i#ä§äu6}n«FJ7»€óL &,polþdÊ%šq»V¿>M•–…‘W³Ñ’;? Ë_*ã]¾àVƒ»B cwùm ï´µºÇ@¢”uµÊ"½»ŸOpžÄ”F1hNì:e)}kœÍ7Á»‹jŸãbŃ(Iæ´ÏÒFoOˆ@Þæ>ÿ,ù7ÿÿPK!q}…xªUdocProps/app.xml ¢( œ“ÁnÛ0 †ïö†îœ¬†@V1¤ÛzX±I»³&Ó±YDÖˆ÷ô“l¤qºÃ€ÝHþ?¨O¤$îN-zˆh¼«ØrQ²œöµq‡Š=í¿Þ|b’rµ²ÞAÅ@v'ß¿ÛèD2€Ejá°b-QXsŽº…Ná"É.)¢”Æ÷Mc4Ü{ýÒ#¾*ËN®†ú&¼6dSÇuOÿÛ´ö:óáó~ XŠÏ!X£¥[ÊG££GßPñ¨´qä±-¾œ4XÁç6‘8w _¢¡A–‚ÏS±ÓÊÂ&!e¿Ä¨<¾­2¥èi݃& 4¿ÓW¬ø¥2XÅzr”³mJÆØ¤(úxÄ€Pðd˜Šc8÷Îcs+W£!ׯÜ`IÂ5âÞüÑlU¤ Ë|Ë9ß+é(M8sôq âͱßåù-æ÷` èM ó°"‡£·þ`?ÅwãŽøöþ^œq]»VE¨ÓîÎú¥ Ò¢ÍM6­r¨Ïž¿…ü€ž§_"—·‹òC™^Ĭ&øå?È?ÿÿPK!c±cf•©xl/calcChain.xml<ŽA Â0E÷‚w³·Óv!"IŠž@ÒÑ’IÉÑÛ›•ËLJ÷Ÿ^>9©7U‰… LÊؗ5òËÀã~;œ@Is¼ºT˜ |I`±ûö.ùkp‘U7°­mgDñ²“¡lÄ}y–š]ëX_([%·J j9á<ŽGÌ]V{U \&PÑÀ *õ@«ñbÿÿPK-!܆ ~~Ì[Content_Types].xmlPK-!}ÌTž Ý ·_rels/.relsPK-!A˜ø Ìõxl/_rels/workbook.xml.relsPK-! Ä ×> xl/workbook.xmlPK-!vŠ:ÀŸ B xl/styles.xmlPK-!¹Œq -xl/worksheets/sheet2.xmlPK-!0ˆkÞnxl/theme/theme1.xmlPK-!>y‡âÙ`°xl/worksheets/sheet1.xmlPK-!i÷…Úöü#È)xl/sharedStrings.xmlPK- !ƒ v,ttð-docProps/thumbnail.jpegPK-!‰k¿ºgyA¢docProps/core.xmlPK-!q}…xªUߤdocProps/app.xmlPK-!c±cf•©¿§xl/calcChain.xmlPK I‚¨gdata/inst/xls/latin-1.xls0000644000176000001440000012400012015201166015131 0ustar ripleyusersÐÏࡱá>þÿ EþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿR  !"#$%&'()*+,-./0123456789:;<=>?@ABCDþÿÿÿþÿÿÿþÿÿÿHIJKLMNOPQþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRÿÿÿÿÿÿÿÿ ÀFn¡o„€ÍFÀWorkbookÿÿÿÿÿÿÿÿ†SummaryInformation(ÿÿÿÿG€DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿ ÙTÌá°Áâ\pWarnes, Gregory B°a=œ¯¼= d 08ô@"·Ú1ðCalibri1ðCalibri1ðCalibri1ðCalibri1ðCalibri1ð Calibri1ðCalibri1ð4¼Calibri1ð ¼Calibri1ðCalibri1ðCalibri1,8¼Calibri18¼Calibri1Ü8¼Calibri1ð>Calibri1ð4Calibri1ð<Calibri1ð?¼Calibri1h8¼Cambria1ð¼Calibri1ð Calibri1ð Calibri1ðCalibri1&ȼ Courier New1&È Courier New1&ȼ Courier New1Times"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)¤"kr"\ #,##0;\-"kr"\ #,##0#¥"kr"\ #,##0;[Red]\-"kr"\ #,##0$¦"kr"\ #,##0.00;\-"kr"\ #,##0.00)§$"kr"\ #,##0.00;[Red]\-"kr"\ #,##0.00>¨9_-"kr"\ * #,##0_-;\-"kr"\ * #,##0_-;_-"kr"\ * "-"_-;_-@_-,©'_-* #,##0_-;\-* #,##0_-;_-* "-"_-;_-@_-FªA_-"kr"\ * #,##0.00_-;\-"kr"\ * #,##0.00_-;_-"kr"\ * "-"??_-;_-@_-4«/_-* #,##0.00_-;\-* #,##0.00_-;_-* "-"??_-;_-@_-àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À àõÿ ´‰ àõÿ ´¯ àõÿ ´Ÿ àõÿ ´‰ àõÿ ´© àõÿ ´¯ àõÿ ´¬ àõÿ ´¯ àõÿ ´Ÿ àõÿ ´® àõÿ ´¬ àõÿ ´³ àõÿ ´ž àõÿ ´ àõÿ ´Ÿ àõÿ ´– àõÿ ´± àõÿ ´¯ àõÿ ´¾ àõÿ ´“ àõÿ ´Ÿ àõÿ ´¤ àõÿ ´± àõÿ ´ àõÿ ´­ àõÿ ”— — – à õÿ ”ff¿¿· à«õÿ øÀ à©õÿ øÀ àªõÿ øÀ à¨õÿ øÀ à õÿ ôÀ à õÿ ´ª à õÿ ÔPÀ à õÿ ÔP À àõÿ Ô À àõÿ ôÀ àõÿ ôÀ àõÿ ”— — ¯ àõÿ Ô`À àõÿ ´š àõÿ œ  « àõÿ ”¿¿– à õÿ øÀ àõÿ ôÀ àõÿ Ôa>À àõÿ ôÀ àQ À à À à À à À à  À à À à À ||FÓèÿ}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-} _-;_-* "}-}  _-;_-* "}-}  _-;_-* "}-}  _-;_-* "}-}  _-;_-* "}-}  _-;_-* "}-} _-;_-* "}-} _-;_-* "}A} _-;_-* "ef"-"??_-;}A} _-;_-* "ef"-"??_-;}A} _-;_-* "ef"-"??_-;}A} _-;_-* "ef"-"??_-;}A} _-;_-* "ef"-"??_-;}A} _-;_-* "ef "-"??_-;}A} _-;_-* "ÌL"-"??_-;}A} _-;_-* "ÌL"-"??_-;}A} _-;_-* "ÌL"-"??_-;}A} _-;_-* "ÌL"-"??_-;}A} _-;_-* "ÌL"-"??_-;}A} _-;_-* "ÌL "-"??_-;}A} _-;_-* "23"-"??_-;}A} _-;_-* "23"-"??_-;}A} _-;_-* "23"-"??_-;}A} _-;_-* "23"-"??_-;}A}  _-;_-* "23"-"??_-;}A}! _-;_-* "23 "-"??_-;}A}" _-;_-* ""-"??_-;}A}# _-;_-* ""-"??_-;}A}$ _-;_-* ""-"??_-;}A}% _-;_-* ""-"??_-;}A}& _-;_-* ""-"??_-;}A}' _-;_-* " "-"??_-;}A}( œÿ_-;_-* "ÿÇÎÿ"-"??_-;}‘}) ú}ÿ_-;_-* "òòòÿ"-"??_-;ÿ ÿ ÿ ÿ}‘}* _-;_-* "¥¥¥ÿ"-"??_-;???ÿ ???ÿ ???ÿ ???ÿ}-}+ _-;_-* "}-}, _-;_-* "}-}- _-;_-* "}-}. _-;_-* "}-}/ ÿ_-;_-* "}A}0 aÿ_-;_-* "ÆïÎÿ"-"??_-;}A}1 _-;_-* ""-"??_-;}A}2 _-;_-* "ÿ?"-"??_-;}A}3 _-;_-* "23"-"??_-;}-}4 _-;_-* "}‘}6 ??vÿ_-;_-* "ÿÌ™ÿ"-"??_-;ÿ ÿ ÿ ÿ}A}7 ú}ÿ_-;_-* "ÿ€ÿ"-"??_-;}A}8 œeÿ_-;_-* "ÿëœÿ"-"??_-;}‘}9 _-;_-* "ÿÿÌÿ"-"??_-;²²²ÿ ²²²ÿ ²²²ÿ ²²²ÿ}‘}: ???ÿ_-;_-* "òòòÿ"-"??_-;???ÿ ???ÿ ???ÿ ???ÿ}-}; _-;_-* "}-}< _-;_-* "}U}= _-;_-* ""-"??_-; }-}> ÿÿ_-;_-* "}-}5  _-;_-* "}-}?  _-;_-* "}(}@ ÿ_-;_-* "}(}A ÿ_-;_-* "}(}B ÿ_-;_-* "}(}C ÿ_-;_-* "}(}D ÿ_-;_-* "}(}E ÿ_-;_-* "“ 20% - Accent1’M’ÿ 20% - Accent1 efÜæñÿ ÿ%“ 20% - Accent2’M’"ÿ 20% - Accent2 efòÜÛÿ ÿ%“ 20% - Accent3’M’&ÿ 20% - Accent3 efëñÞÿ ÿ%“ 20% - Accent4’M’*ÿ 20% - Accent4 efäßìÿ ÿ%“ 20% - Accent5’M’.ÿ 20% - Accent5 efÚîóÿ ÿ%“ 20% - Accent6’M’2ÿ 20% - Accent6  efýéÙÿ ÿ%“ 40% - Accent1’M’ÿ 40% - Accent1 ÌL¸Ìäÿ ÿ%“ 40% - Accent2’M’#ÿ 40% - Accent2 ÌL渷ÿ ÿ%“ 40% - Accent3’M’'ÿ 40% - Accent3 ÌLØä¼ÿ ÿ%“ 40% - Accent4’M’+ÿ 40% - Accent4 ÌLÌÀÚÿ ÿ%“ 40% - Accent5’M’/ÿ 40% - Accent5 ÌL·Þèÿ ÿ%“ 40% - Accent6’M’3ÿ 40% - Accent6  ÌLüÕ´ÿ ÿ%“ 60% - Accent1’M’ ÿ 60% - Accent1 23•³×ÿ ÿÿÿÿ%“ 60% - Accent2’M’$ÿ 60% - Accent2 23Ú–”ÿ ÿÿÿÿ%“ 60% - Accent3’M’(ÿ 60% - Accent3 23Ä×›ÿ ÿÿÿÿ%“ 60% - Accent4’M’,ÿ 60% - Accent4 23± Çÿ ÿÿÿÿ%“ 60% - Accent5’M’0ÿ 60% - Accent5 23’ÍÜÿ ÿÿÿÿ%“! 60% - Accent6’M’4ÿ 60% - Accent6  23ú¿ÿ ÿÿÿÿ%“ "Accent1’A’ÿAccent1 O½ÿ ÿÿÿÿ%“ #Accent2’A’!ÿAccent2 ÀPMÿ ÿÿÿÿ%“ $Accent3’A’%ÿAccent3 ›»Yÿ ÿÿÿÿ%“ %Accent4’A’)ÿAccent4 €d¢ÿ ÿÿÿÿ%“ &Accent5’A’-ÿAccent5 K¬Æÿ ÿÿÿÿ%“ 'Accent6’A’1ÿAccent6  ÷–Fÿ ÿÿÿÿ%“(Bad’9’ÿBad ÿÿÇÎÿ ÿœÿ%“) Calculation’’ÿ Calculation ÿòòòÿ ÿú}ÿ%ÿÿÿÿÿÿ ÿÿ“* Check Cell’’ÿ Check Cell ÿ¥¥¥ÿ ÿÿÿÿ%ÿ???ÿÿ???ÿÿ???ÿ ÿ???ÿ“+€ÿ’ ’ÿComma“,€ÿ’(’ÿ Comma [0]“-€ÿ’&’ÿCurrency“.€ÿ’.’ÿ Currency [0]“/Explanatory Text’G’5ÿExplanatory Text ÿÿ%“ 0Good’;’ÿGood ÿÆïÎÿ ÿaÿ%“1 Heading 1’G’ÿ Heading 1 I}ÿ%O½ÿ“2 Heading 2’G’ÿ Heading 2 I}ÿ%ÿ?§¿Þÿ“3 Heading 3’G’ÿ Heading 3 I}ÿ%23•³×ÿ“4 Heading 4’9’ÿ Heading 4 I}ÿ%“5€ÿ’9’ÿ Hyperlink  ÿÿ%“ 6Input’u’ÿInput ÿÿÌ™ÿ ÿ??vÿ%ÿÿÿÿÿÿ ÿÿ“7 Linked Cell’K’ÿ Linked Cell ÿú}ÿ%ÿÿ€ÿ“ 8Neutral’A’ÿNeutral ÿÿëœÿ ÿœeÿ%“€ÿ’3’ÿNormal ÿ%“ 9Note’b’ ÿNote ÿÿÿÌÿÿ²²²ÿÿ²²²ÿÿ²²²ÿ ÿ²²²ÿ“ :Output’w’ÿOutput ÿòòòÿ ÿ???ÿ%ÿ???ÿÿ???ÿÿ???ÿ ÿ???ÿ“;€ÿ’$’ÿPercent“ <Title’1’ÿTitle I}ÿ%“ =Total’M’ÿTotal ÿ%O½ÿO½ÿ“> Warning Text’?’ ÿ Warning Text ÿÿÿ%ŽXŽTableStyleMedium9PivotStyleMedium4’â8ÿÿÿÝ·Ôüóò„«êdq:F¥€€ÀÀÀ€€€cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½ÌÿÌÿÿÌÿÌÿÿ™™Ìÿÿ™ÌÌ™ÿÿÌ™3fÿ3ÌÌ™ÌÿÌÿ™ÿfff™–––3f3™f333™3™3f33™333\ÿÿÿ`…ˆKSheet1…„„Sheet2šš££Œ correlationÁÁá"ÖÖün øºaacute  á  small a, acute accentAacute  Á  capital A, acute accentacirc  â  small a, circumflex accentAcirc    capital A, circumflex accentagrave  à  small a, grave accentAgrave  À  capital A, grave accentaring  å  small a, ringAring  Å  capital A, ringatilde  ã  small a, tildeAtilde  à  capital A, tildeauml  ä small a, dieresis or umlautmarkAuml  Ä " capital A, dieresis or umlautmarkaelig  æ  small ae diphthong (ligature)AElig  Æ  capital AE diphthong(ligature)ccedil  ç  small c, cedillaCcedil  Ç  capital C, cedillaeth  ð  small eth, IcelandicETH  Ð  capital Eth, Icelandiceacute  é  small e, acute accentEacute  É  capital E, acute accentecirc  ê  small e, circumflex accentEcirc  Ê  capital E, circumflex accentegrave  è  small e, grave accentEgrave  È  capital E, grave accenteuml  ë small e, dieresis or umlautmarkEuml  Ë " capital E, dieresis or umlautmarkiacute  í  small i, acute accentIacute  Í  capital I, acute accenticirc  î  small i, circumflex accentIcirc  Î  capital I, circumflex accentigrave  ì  small i, grave accentIgrave  Ì  capital I, grave accentiuml  ï small i, dieresis or umlautmarkIuml  Ï " capital I, dieresis or umlautmarkntilde  ñ  small n, tildeNtilde  Ñ  capital N, tildeoacute  ó  small o, acute accentOacute  Ó  capital O, acute accentocirc  ô  small o, circumflex accentOcirc  Ô  capital O, circumflex accentograve  ò  small o, grave accentOgrave  Ò  capital O, grave accentoslash  ø  small o, slashOslash  Ø  capital O, slashotilde  õ  small o, tildeOtilde  Õ  capital O, tildeouml  ö small o, dieresis or umlautmarkOuml  Ö " capital O, dieresis or umlautmarkszlig  ß " small sharp s, German (szligaturethorn  þ  small thorn, IcelandicTHORN  Þ  capital THORN, Icelandicuacute  ú  small u, acute accentUacute  Ú  capital U, acute accentucirc  û  small u, circumflex accentUcirc  Û  capital U, circumflex accentugrave  ù  small u, grave accentUgrave  Ù  capital U, grave accentuuml  ü small u, dieresis or umlautmarkUuml  Ü " capital U, dieresis or umlautmarkyacute  ý  small y, acute accentYacute  Ý  capital Y, acute accentyuml  ÿ small y, dieresis or umlautmarkÿ¾3 !4o¡4ï5RX5¦ç55Y6§µ6/7}©7÷8k—8å9_…9Óî9<k:¹Ï:1;¯;ý<i”<â=^ z=È û=I –– –PK!›èpOü[Content_Types].xml¬‘ËjÃ0E÷…þƒÐ¶Ørº(¥ØÎ¢]‹ôyl‹Ø#!MBò÷;.”…nÒ̽÷̨\ÆAí1&ç©Ò«¼Ð ÉúÆQWéÏÍKv¯Ub OXé#&½®¯¯ÊÍ1`R¢¦Též9<“l#¤Ü$©´>ŽÀr `·Ð¡¹-Š;c=1gM ŠÔ¯À›™ÝõN‘›¸DJ¥›++2„a,/ó”$ðnÄEŒ<ŠñÊPà#г•ÕJe}%Æ4 P‚cP{g4¢!A}­2ØÊ•w<&JꉞVM ƒT5BNe› tˆY3€y†ü¨OŽU€– ^4ƒŠù V¶®®àÍLˆ©²%¹®ùËä2áÁª™SŒŤÕn­qe§ÐoLÍã:N»S-ôCðÔÚRÖYënT[¹ÎÈþœ×Ý®Ô+5_Ò¿6gs£ÕjÕ™-V©ÙŸµ9üFe½¶½êà ÈâësøZk»Ý^wðdñësøî•ÆzÍÅPÄhr0‡Öív3ídÄÙ /|à• >CA6Ù¥§ñD-ʵ?ࢠdXÑ©iJF8„,nãx (ÖàM‚KoìP(ç†ô\H†‚¦ª¼Ÿb¨ˆ™¾WÏ¿}õü)zõüÉÉÃg'8yôèäá÷V—#x'ã²à˯?ùýËÑoO¿zùø3?^–ñ?÷ÑO?~êBÍ,zñù“_ž=yñÅÇ¿~óØßxP†÷iL$ºMŽÐ>Á7CŒk9ˆóIô#L nꎊàí)f>\‹¸äÝÐ<|À듎­½HLõÌ|3Šà.ç¬Å…—€›z®ÃýI2öO.&eÜ>Ƈ¾¹Û8qBÛ™¤Ð5ó¤t¸oGÄ1sáDá1IˆBú? ÄãÝ}J^wi(¸ä#…îSÔÂÔKIŸœDš Ý 1ÄeêóBíp³{µ8óy½C]$fãû„94^Ç…cŸÊ>ŽY™ð[XE>#{S–q© ÒcÂ8ê ‰”>™;ü-ý&†~å û.›Æ.R(zàÓy s^Fîðƒv„ãÔ‡íÑ$*cß“¢íqåƒïr·Bô3Ä' Ã}'Üg7‚»tì˜4Kýf"<±¼N¸“¿½)abº ´t§SÇ4y]Ûfú¶ámÛnÛ°ˆùŠçÆ©f½÷/lÑ;x’쨊ù%êm‡~Û¡ƒÿ|‡^TËß—g­º´Þؽ¶ÙyÇ 7Þ#ÊXOM¹%ÍÞ[Â4ì –3‡NRÄÒ~êJ† ÜX`#ƒWPõ"œÂ¾½h%c™©K”r çE3ìÕ­ñ°÷Wö´Y×çÛ9$V»|h‡×ôp~Ü(Ô«ÆæL›O´¦,;ÙÚ•L)øö&“UµQKÏV5¦™¦èÌV¸¬)6çr ¼p  6agƒ`?,¯Ã±_O çÌÈPónc”‡ÅDᯠQæµu$ÂCbCä —Ø¬šØå)4çŸvÏæÈùØ,XÒÎ6¤ÅâüY’ä\ÁŒd<]M,)×KÐQ3hÔWë qÚ FpÒ…Ÿq A“z/ˆÙ®‹B%lÖžY‹¦Hg7üYU…Ë‹ã”q*¤ÚÁ2²14¯²P±DÏdí_­×t²]Œžf²œk"ÿ˜j7´d4"¡*»4¢¹³Y'äED/¡›ˆ} áNµ?C*á´~€Û5ͶyåöÖ¬Ó”ï´ ÎŽc–F8ë–úv&¯8 7ý¤°Á<•Ìß¼¶çÎø‹r¥œÆÿ3Wôr7kC.wFºRš*âÐ…Òˆ†]ë¾é-pC ¯|¸b6ÿ r¨ÿ·5gu˜²†ƒ Ú§c$(,'*„ìA[2Ùw†²j¶ôX•,Sd2ªd®L­ÙrHX_÷Àu݃Aª›n’µƒ;îsVAƒ±Þ£”ëÍédÅÒikàïÞ¸Øb§Ní%tþæü&«ûlõ³òF<_#ËŽè³]R-¯ gñk4²©ÞЄeàÒZk;֜ǫõÜ8ˆâ¼Ç0XìgR¸BúXÿ¨™ý^¡Ô>߇ފàóƒåAV_Ò] 2H7Hûkû;h“I«²Ôf;ÍZ¾X_ðFµ˜÷ÙÚ²eâ}N²‹M”;S‹Ivưõ[H5Döt‰ÂÐ(?‡˜À˜]åoQ|ð½·þf¿NÉžL¤{Âd×€§ÙO&í‚k³NŸa4’%ûd„èð8?Lز_Hò-²Ak1h…àšïÐà fx-jWËBxõláBÂÌ -»6j>ð},kÜúhxÛd­×º¸r¦Xòg([Âx?eޓϲ”Ùƒâkõ”©ã×S–1äÍ'|áŽ^=Óaѱ™nRvëÿÿPK! ÑŸ¶'theme/theme/_rels/themeManager.xml.rels„M Â0„÷‚wooÓº‘&݈ЭÔ„ä5 6?$Qìí ®,.‡a¾™i»—Éc2Þ1hª:é•qšÁm¸ìŽ@RN‰Ù;d°`‚Žo7íg‘K(M&$R(.1˜r'J“œÐŠTù€®8£Vä"£¦AÈ»ÐH÷u} ñ›|Å$½b{Õ–Pšÿ³ý8‰g/]þQAsÙ…(¢ÆÌà#›ªLÊ[ººÄßÿÿPK-!›èpOü[Content_Types].xmlPK-!¥Ö§çÀ6 -_rels/.relsPK-!ky–ƒŠtheme/theme/themeManager.xmlPK-!0ˆkÞÓtheme/theme/theme1.xmlPK-! ÑŸ¶' theme/theme/_rels/themeManager.xml.relsPK] ÙTÌ ?9h…z˃  dü©ñÒMbP?_*+‚€%,Áƒ„Mo com.apple.print.PageFormat.FormattingPrinter com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.FormattingPrinter com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 1200 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalRes 1200 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket PMPPDPaperCodeName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDPaperCodeName A4 com.apple.print.ticket.stateFlag 0 PMTiogaPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMTiogaPaperName iso-a4 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0 0 13050.000000000002 9316.6666666666679 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -300 -300 13733.333333333334 9616.6666666666679 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName iso-a4 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0 0 783 559 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -18 -18 824 577 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName A4 com.apple.print.ticket.stateFlag 0 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz°°2û$eþÔþÔ5¦%‘g{àHHØ(dÿh ¡" düÿüÿà?à?U } Õ } *} €#} *} *} *} U}  *} *} *} ª} *} *} *} *} *} ª} *} ª} !*} ""*} #$*} %%€} &(*} ))€} ***} ++€} ,,*} --€} ..*} //€} 03*} 44U} 55*} 66U} 77*} 88U} 99*} ::U} ;;} <<*} ==?>>,>,>,>,>,>,>,>,>, >, >, >, >, >,>,>,,,,,,,,,,,,,,,,,ý Bý ?ý Aý B ý ? ý Aý Bý ?ý Aý Bý ?ý A"ý B%ý ?(ý A+ý B.ý A1ý A4ý A7ý A:ý A=ý A@ý ?Cý AFý BIý ?Lý AOý BRý ?Uý AXý B[ý ?^ý Aaý !Bdý "?gý #Cjý $Bmý %?pý &Asý 'Bvý (@yý )|ý *ý +‚ý ,…ý -ˆý .‹ý /Žý 0‘ý 1”ý 2—ý 3šý 4ý 5 ý 6£ý 7¦ý 8©ý 9¬ý :¯ý ;²ý <µý =¸ý Eý Bý B¾"BBBBBBBBBBBBBBý Eý ?ý ?¾"??????????????ý Eý Aý A¾"AAAAAAAAAAAAAAý E ý B ý B ¾"BBBBBBBBBBBBBBý E ý ? ý ?¾"??????????????ý Eý Aý A¾"AAAAAAAAAAAAAAý Eý Bý B¾"BBBBBBBBBBBBBBý Eý ?ý ?¾"??????????????ý Eý Aý A¾" AAAAAAAAAAAAAAý Eý Bý B¾" BBBBBBBBBBBBBBý Eý ?ý ? ¾" ??????????????ý E!ý A"ý A#¾" AAAAAAAAAAAAAAý E$ý B%ý B&¾" BBBBBBBBBBBBBBý E'ý ?(ý ?)¾"?????????????Dý E*ý A+ý A,¾"AAAAAAAAAAAAADý E-ý B.ý B/¾"BBBBBBBBBBBBBDý E0ý A1ý A2¾"AAAAAAAAAAAAAAý E3ý A4ý A5¾"AAAAAAAAAAAAAAý E6ý A7ý A8¾"AAAAAAAAAAAAAAý E9ý A:ý A;¾"AAAAAAAAAAAAAAý E<ý A=ý A>¾"AAAAAAAAAAAAAAý E?ý A@ý AA¾"AAAAAAAAAAAAAAý EBý ?Cý ?D¾"??????????????ý EEý AFý AG¾"AAAAAAAAAAAAAAý EHý BIý BJ¾"BBBBBBBBBBBBBBý EKý ?Lý ?M¾"??????????????ý ENý AOý AP¾"AAAAAAAAAAAAAAý EQý BRý BS¾"BBBBBBBBBBBBBBý ETý ?Uý ?V¾"??????????????ý EWý AXý AY¾"AAAAAAAAAAAAAAý EZý B[ý B\¾"BBBBBBBBBBBBBB×D”ldPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP ,!,",#,$,%,&,',(,),*,+,,,-,.,/,0,1,2,3,4,5,6,7,8,9,:,;,<,=,>,ý E]ý ?^ý ?_¾" ??????????????ý !E`ý !Aaý !Ab¾"!AAAAAAAAAAAAAAý "Ecý "Bdý "Be¾""BBBBBBBBBBBBBBý #Efý #?gý #?h¾"#??????????????ý $Eiý $Cjý $Ck¾"$CCCCCCCCAAAAAAý %Elý %Bmý %Bn¾"%BBBBBBBBBBBBBBý &Eoý &?pý &?q¾"&??????????????ý 'Erý 'Asý 'At¾"'AAAAAAAAAAAAAAý (Euý (Bvý (Bw¾"(BBBBBBBBBBBBBBý )Exý )@yý )@z¾")@@@@@@@@@@@@@@ý *E{ý *|ý *}ý +E~ý +ý +€ý ,Eý ,‚ý ,ƒý -E„ý -…ý -†ý .E‡ý .ˆý .‰ý /EŠý /‹ý /Œý 0Eý 0Žý 0ý 1Eý 1‘ý 1’ý 2E“ý 2”ý 2•ý 3E–ý 3—ý 3˜ý 4E™ý 4šý 4›ý 5Eœý 5ý 5žý 6EŸý 6 ý 6¡ý 7E¢ý 7£ý 7¤ý 8E¥ý 8¦ý 8§ý 9E¨ý 9©ý 9ªý :E«ý :¬ý :­ý ;E®ý ;¯ý ;°ý <E±ý <²ý <³ý =E´ý =µý =¶ý >E·ý >¸ý >¹×BþXPPPPPPPPPP********************>¶@––ÈÈ@ å ggÿÿÿÿD ÙTÌ @…™…  dü©ñÒMbP?_*+‚€%,Áƒ„¡",ÿà?à?@U ,)ÿÿÿ!ø‘áü#$À$ÀBÿ×A>¶@ÈÈ@ggÿÿÿÿD þÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ ÕÍÕœ.“—+,ù®0ì PX€ ˆ˜  ¨ Æ' Grendel evidensbasert psykologi Sheet1Sheet2  Worksheetsþÿÿÿÿÿ ÀF$Microsoft Excel 97 - 2004 Worksheetþÿÿÿ8FIBExcel.Sheet.8þÿ à…ŸòùOh«‘+'³Ù0PHPtŒ ° ¼ÈÐ'Rolf Marvin B¿e LindgrenWarnes, GregoryMicrosoft Macintosh Excel@€K}E­µË@,z{€ÍGvþÿÿÿPICTn7€ÿ ÿþHH7€ €€ÿÿšÿ7€HH 7€7€7kZ÷o{kZ÷w½sœsœ÷w½kZþw½sœkZþw½sœo{Ùw½g9o{Úw½kZÿ?o{ùsœw½g9kZ÷ÿVµVµ÷ÿkZþÿVµVµg9ÿÿ{ÞsœÚÿNso{sœÚÿkZÿAkZúo{w½ÿckZøÿsœR”F1{ÞøÿkZþÿVµ^÷cÿÿ{ÞsœÚÿF1ØÿkZÿGkZûo{{Þÿÿcg9øÿkZÿsœkZøÿkZþÿcVµo{ÿÿ{ÞsœÚÿo{R”cÚÿkZÿ&ûkZg9VµZÖZÖVµg9ëÿkZùÿ{Þsœ°ÿkZÿ"öckZëw½o{þw½sýw½sœo{°w½o{ÿ+w½ýÿw½üÿw½ëÿw½ÿÿo?w¿üÿ{Þ°ÿw½ÿ9w½ýÿNsw½ýÿw½ýÿkZðÿw½ÿÿE¿süÿ{ÞþÿkZ´ÿw½ÿ?w½ýÿZÖw½ýÿw½þÿJR%)ðÿw½ÿk?V_R?üÿ{Þÿÿ{ÞZÖsœµÿw½ÿ?w½ýÿco{ýÿw½þÿR”Nsðÿw½ÿk?ÿk?üÿ{Þÿÿw½o{sœµÿw½ÿ'sœ÷{Þw½ëÿw½bßýR?k?ÿÿ{Þw½°ÿw½ÿökZo{ëw½sœøw½sœ°w½sœÿ/w½þÿw½ZÖo{ýÿw½÷ÿsœ{Þ÷ÿw½øÿ{Þ°ÿw½ÿ_w½ýÿ{ÞR”ýÿw½o{ZÖ^÷VµVµkZVµg9R”NsBkZ^÷Nsùÿw½ýÿg9ýÿ{Þ÷ÿNso{o{Nsðÿcïÿcãÿw½ÿ«w½ýÿZÖ{Þýÿw½o{g9F1^÷BF1ÿ{ÞF1JRJRsœBg9ùÿw½þÿB-kýÿ{Þþÿ1ŒF11Œ!R”!kZR”ÿ{ÞVµÿÿ{Þ1Œ=ïýÿ{Þ1Œ=ïR”NsJRZÖJR9ÎZÖ=ï%)o{ÿÿ=ï-kVµR”R”NsNs)J-kF1BkZ5­cäÿw½ÿ³w½þÿsœ^÷kZýÿw½o{^÷ZÖVµZÖkZVµ{ÞVµZÖkZkZR”cùÿw½þÿNsNsýÿ4{ÞÿÿsœR”^÷VµR”VµNsg9Nso{R”ZÖÿÿsœR”ZÖg9kZÿÿsœR”ZÖ^÷VµkZNsg9ZÖ^÷ZÖVµÿÿ{ÞNsNscVµkZR”g9R”^÷R”^÷w½Vµg9äÿw½ÿkZöo{ëw½sœøw½sœ°w½sœÿ+sœ÷{Þw½ÿÿo{îÿw½ÿÿo_wŸüÿ{Þ°ÿw½ÿkw½þÿw½ZÖ^÷ýÿw½ÿw½)Jÿÿo{ÿýw½{ÞNsÿsœúÿw½ÿÿR?ßüÿ{Þùÿk?o_ÿÿßbßÿo?fÿøÿsòÿo_Ûÿw½ÿ£w½ýÿVµg9ýÿw½ÿ^÷Vµg9ccR”^÷VµJRkZVµ=ïVµF1ZÖûÿw½ÿÿR?bßüÿ{Þÿ^¿^¿kR?fÿV_k^ŸAŸk?V_s_b¿ÿZZþÿZŸfÿV_kb¿b¿V_fÿZZÿo_R?o_V_gV_gZk?MÿZIßo_Üÿw½ÿ£w½ýÿ{ÞNsýÿw½ÿR”^÷=ïc^÷9Î^÷{ÞJRo{VµF1JRÿ{Þûÿw½ÿfÿR?Rüÿ+{ÞÿV_ÿbßIß^¿{ßV_ZZk?V_bßb¿ÿE¿E¿ÿÿ{ßZVV_ÿZZb¿ßE¿ZŸÿfÿRR?{ßZŸ{ßV_b¿k?^ŸZZÛÿw½ÿ¥w½þÿw½co{ýÿw½sœo{ÿR”cc^÷NskZg9^÷g9ZÖg9Vµw½ûÿw½ÿk?ÿk?üÿ{Þÿkfÿkþ^¿$wŸo?fÿk?bßss_{¿swŸ^¿s{ßbßk?bÿo_fÿ^ŸwŸk?fÿkÿk?bßsb¿s_b¿s_bßwŸo_o?o_sÜÿw½ÿ*kZöo{ëw½sœbýýV}k=þw½sœZ×V}ZÜw½sœÿ-sœýÿ{Þw½ýÿw½üÿo{w½òÿw½øÿ{Þ°ÿw½ÿgw½ýÿZÖ^÷ýÿ w½sœcg9g9ZÖkZkZR”cg9^÷öÿw½þÿsœw½ýÿ{Þ÷ÿo{ÿkZôÿ{Þ{Þ÷ÿsœsœw½sœîÿw½îÿw½ÿ¹w½þÿg9VµR”ýÿ w½o{g9BNs{Þcg9F1Vµo{{Þöÿw½þÿ^÷g9ýÿ{Þþÿ ZÖo{NsckZVµÿo{ÿkZþÿ{ÞZÖo{ýÿsœþo{#w½{ÞZÖsœkZo{kZg9c^÷o{^÷w½ÿkZkZZÖsœZÖkZÿÿ{ÞZÖsœg9o{kZkZg9ZÖo{ZÖkZco{ïÿw½ÿ¿w½üÿo{ýÿ w½o{^÷ZÖVµg9kZkZZÖ{ÞNssœöÿw½þÿkZkZýÿ?{Þÿÿw½o{sœg9o{o{g9{Þg9{ÞkZw½ÿÿw½o{o{Vµ{Þÿÿ{Þo{w½sœo{{Þg9ÿkZsœo{g9o{sœsœg9w½w½g9w½o{w½o{kZÿÿw½o{sœo{sœsœo{w½o{w½o{o{w½o{ïÿw½ÿsœ÷{Þw½ëÿw½ùÿ{Þw½°ÿw½ÿ ökZo{úw½o{ów½sœøw½sœ°w½sœÿ;w½þÿ{ÞVµg9ýÿw½ÿÿ5­ýÿg9óÿw½þÿw½^÷ýÿ{Þ°ÿw½ÿw½þÿ{Þ^÷üÿ w½ÿcBsœo{cZÖNsR”JRcNs{Þøÿw½þÿZÖNsýÿ{Þ÷ÿo{w½sœsœþÿR”cÿÿ{Þ5­{Þúÿ{ÞkZ÷ÿ^÷JRg9R”îÿsœo{ôÿw½ÿÇw½ýÿo{R”ýÿ w½ÿR”cF1F1ÿÿF1R”w½Böÿw½þÿ=ï5­ýÿ{Þÿÿw½JRNsF1-k=ïR”Ns=ïÿBVµg9%)cVµw½ÿÿkZ%)cýÿ'g9R”VµJRkZZÖF1R”R”VµB=ïB1ŒNs5­g9o{cB%)c)JJRÿÿ^÷!ZÖNsNsJRJRNs)JNs5­BF1Vµôÿw½ÿÑw½þÿ{Þco{ýÿ w½sœo{ÿR”o{R”sœZÖcsœZÖ^÷÷ÿw½ÿÿsœ^÷R”{Þþÿ{Þÿÿ{ÞR”g9NsNs9ÎR”o{Nso{cVµ^÷NscNsg9ÿÿR”kZcR”þÿ'o{R”g9NscVµ^÷o{R”o{R”NsZÖVµZÖNssœNs^÷ZÖVµg9VµZÖÿÿZÖNsg9R”g9VµZÖg9VµccZÖg9Vµôÿw½ÿ kZöo{ëw½sœøw½sœúw½^÷¸w½sœÿsœ÷{Þw½ëÿw½øÿ{Þ°ÿw½ÿWw½þÿw½R”g9ýÿw½ÿo{ÿ{Þw½ÿw½{Þo{{Þsœw½{Þsœùÿw½ÿÿfÿûÿ{ÞøÿZŸ^¿åÿo_Øÿw½ÿŸw½þÿ^÷VµkZýÿw½kZg9NsR”9Îc9ÎVµc^÷=ïc^÷NsNsúÿw½ÿsV_wŸüÿ){ÞÿZŸo?V_MÿR?o_ZŸfÿZ^ŸÿgVÿÿs_V?bßIßfÿR?b¿wŸ^¿V_bßÿgR?kZfÿZfÿV_fÿV_bßE¿sÙÿw½ÿw½þÿ^÷o{Nsýÿw½kZcF1R”^÷w½R”c^÷VµJR^÷JR{Þ{Þúÿw½ÿkV_küÿ({Þÿfÿb¿^ŸZwŸZŸZŸVZ^Ÿÿ^¿MÿÿÿfÿV_sZkRk?E¿fÿNbÿÿ^¿IßZŸÿV_ÿN^¿^¿sZZØÿw½ÿŸw½þÿ{ÞckZýÿw½o{^÷ZÖJRR”g9cg9ccw½sœw½R”sœúÿw½ÿo_bßwŸüÿ){Þÿkk?o_o?{ßk?bßk?o?o_ÿfÿbß^¿ÿ^¿^Ÿbßo?o_bß{¿bßÿbßo_ÿfÿ^¿sbßo_bßo_fÿs{¿o?k?wŸÙÿw½ÿ/kZöo{þw½R”^÷ðw½sœbýýV}ýw½sœZÚV}^½Ùw½sœÿ-sœþÿ{Þsœsœýÿw½ÿÿ^÷îÿw½øÿ{Þ°ÿw½ÿiw½ýÿkZR”ýÿw½ÿkZ9Îw½w½cZÖVµ^÷c^÷co{kZkZVµûÿw½þÿ^÷üÿ{Þ÷ÿw½ÿw½ýÿkZþÿw½kZâÿw½çÿw½ÿ·w½ýÿZÖ{Þýÿw½ÿR”cF1kZZÖcF1ÿ^÷B{Þ=ïsœ=ïkZ{Þüÿw½þÿcg9ýÿ{Þÿÿsœo{sœ^÷g9ZÖkZsœg9ÿ^÷w½o{R”ÿkZþÿkZZÖüÿkZg9o{ZÖsœg9^÷g9g9o{Vµcÿÿw½Vµ{Þg9o{g9g9o{ZÖo{ZÖkZcsœèÿw½ÿ¹w½ýÿg9üÿw½sœo{ÿR”^÷R”ZÖZÖ{ÞVµZÖÿg9ÿZÖ^÷ûÿw½ÿÿ{Þo{kZýÿ {Þÿÿ{Þo{w½kZkZckZ{Þg9{Þþsœ g9{Þg9{ÞÿÿkZ{ÞsœR”þÿw½csœg9{Þo{g9ÿkZÿkZsœÿÿsœkZw½kZsœo{o{{Þo{w½o{o{w½o{èÿw½ÿ9sœ÷{Þw½ýÿ^÷R”kZòÿw½ùÿ{Þw½úÿkZ{Þîÿ{Þo{Îÿw½ÿ ökZo{üw½o{ñw½sœøw½sœ°w½sœÿ+w½ýÿZÖkZýÿw½üÿg9ñÿw½øÿ{Þ°ÿw½ÿWw½þÿw½VµZÖýÿw½o{ZÖZÖF1ZÖþNsg9ZÖF1w½÷ÿw½þÿ{ÞZÖýÿ{Þ÷ÿNso{o{NsôÿcÌÿw½ÿw½þÿo{ZÖR”ýÿ w½o{g9F1JRÿF1JRsœR”NsZÖöÿw½þÿB-kýÿ{Þþÿ1ŒF11Œ!R”!kZR”ÿ{ÞVµÿÿ{Þ1Œ=ïüÿ 1ŒVµo{F1g9BF1JR-k{ÞÒÿw½ÿ‰w½þÿ{ÞckZýÿ w½o{^÷ZÖZÖÿZÖ^÷sœcJRR”sœ÷ÿw½þÿNsNsýÿ!{ÞÿÿsœR”^÷VµR”VµNsg9Nso{R”ZÖÿÿsœR”ZÖg9kZÿÿw½Nssœ^÷R”^÷g9^÷=ïBÑÿw½ÿ(kZöo{øw½R”^÷öw½sœøw½sœâw½^÷Ðw½sœÿ1sœ÷{Þw½ÿÿo{þÿcòÿw½ÿÿV_w¿üÿ{Þ°ÿw½ÿew½þÿsœVµZÖýÿ w½ÿsœ-kÿ{ÞkZsœÿsœo{ÿkZsœøÿw½ÿÿMÿ{ßüÿ{Þùÿo?o?ÿÿßbßÿk?fÿýÿo?Æÿw½ÿw½þÿg9cF1ýÿ w½ÿ^÷Vµ^÷VµR”B{Þ5­F1cg9=ïøÿw½ÿßV_bßüÿ{ÞÿZ^¿kNb¿V_bßZAŸk?R?o_b¿ÿZZÿÿßE¿Zb¿V_gRR?Ëÿw½ÿÿÿCompObjÿÿÿÿÿÿÿÿÿÿÿÿbÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgdata/inst/xls/iris.xls0000644000176000001440000014200010772046704014647 0ustar ripleyusersÐÏࡱá>þÿ Wþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ_  !"#$%&'()*+,þÿÿÿ./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVþÿÿÿþÿÿÿYZ[\]^`þÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRÿÿÿÿÿÿÿÿÀF€?\öïÈX@WorkbookÿÿÿÿSTBook ÿÿÿÿÿÿÿÿ-%SSummaryInformation(ÿÿÿÿÿÿÿÿ˜ Å=Ì€á°Áâ\pGregory Warmes B°a=œ¯¼=ìÿìÿ¬]Ð>8ô@"·Ú1ÈÿVerdana1Èÿ¼Verdana1ÈÿVerdana1Èÿ¼Verdana1ÈÿVerdana1È Verdana1È=Verdana"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à+õÿ øÀ à)õÿ øÀ à,õÿ øÀ à*õÿ øÀ àôÿôÀ àôÿôÀ à õÿ øÀ “€ÿ“ÿ“ÿ“ÿ“ ÿ“ÿ“ÿ“€ÿ’â8ÿÿÿÝ·Ôüóò„«êdq:F¥€€ÀÀÀ€€€cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½ÌÿÌÿÿÌÿÌÿÿ™™Ìÿÿ™ÌÌ™ÿÿÌ™3fÿ3ÌÌ™ÌÿÌÿ™ÿfff™–––3f3™f333™3™3f33™333\ÿÿÿ`…O iris.xlsŒÁÁß®ün› Sepal.Length Sepal.Width Petal.Length Petal.WidthSpeciessetosa versicolor virginicaÿß N#˜O JPP¿ÿ€Ðas#¿ÿ†#¿ÿ†¿ÿ§œ œ œ ¿ÿ€°$ Be˜ ed€ÐwyÃ[Ì#¿ÿ#¿ÿ†JPP¿ÿ†as *< € *< *<*<¿ÿ@as¿ÿ„p œ 3O0bÀ¿ÿ€Ur4c”N#˜O ¿ÿ„p ¿ÿ†¿ÿ†ÿÿÿÿ f¿ÿ€Oðe—œ3 ¿ÿÀO~ô„ÈH¿ÿ„p ¿ÿ†¿ÿ†œ ¿ÿÀ„¬êT1úÔ^ cØc ðU‰Oœ ‘€JÈ¿ÿ‚‘€JØ¿ÿ†¿ÿ‚¿ÿ†„¬é¼U†¸¿ÿ‚0HàcØc ðU‰Oœ ‘€JÈ¿ÿ‚@ÐOœ ‘€Jd¿ÿ‚P¿ÿ§Sáì¿ÿ„p¿ÿ‚P„¬ë|¿ÿ†¿ÿ‚Ú\¿ÿ‚пÿ‚>ǰ„ÂË`‘€Jd¿ÿ‚HàOœ Oœ¨¿ÿ‚ Hà„¬ë4ÿÿÿ€ÿÿÿ€Hà¿ÿ…¿ÿ‚ÀO‘¬Sáì$6¶JPP¿ÿ‚ÐcØ’„ȵ”N"ð¿ÿƒ0Hà„¸­Ì¿ÿ†  YÔ¿ÿƒ0,RZ c[ÿÿÿ _€’â¿ÿ†&¿ÿ†N#˜¿ÿ†JPP¿ÿ†as¿ÿ† œ ¿ÿ†¿ÿ†œ ¿ÿƒp$ Be˜ J‰À¿ÿƒ $ D¿ÿƒ¿ÿ† œ ¿ÿ†¿ÿ†œ ¿ÿƒÐ„¬ûp'^ U†¸œ ¿ÿƒÐ¿ÿ„Àÿÿÿ¿ÿƒà„ÂÇè¿ÿ„¿ÿ† œ ¿ÿ†Á¿ÿ†¿ÿ„€„ÈÛ¸¿ÿ„@„È—ˆ¿ÿ„€Hà¿ÿ„€¿ÿ† œ …¿ÿ†¿ÿ„€¿ÿ†¿ÿ Å=Ì€ $—q*3ç;¯DwMÛS  dü©ñÒMbP?_*+‚€%Áƒ„MÔ com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 300 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalRes 300 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0.0 0.0 3058.3333333333335 2400 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -75 -75 3225.0000000000005 2475 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName na-letter com.apple.print.ticket.client com.apple.print.pm.PostScript com.apple.print.ticket.modDate 2003-07-01T17:49:36Z com.apple.print.ticket.stateFlag 1 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0.0 0.0 734 576 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -18 -18 774 594 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName US Letter com.apple.print.ticket.client com.apple.print.pm.PostScript com.apple.print.ticket.modDate 2003-07-01T17:49:36Z com.apple.print.ticket.stateFlag 1 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.privateLock com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.privateLock com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz,, ó `ÿµÿµ š «g(üHHØ(dÿh ¡"düÿüÿà?à?U —°y|A rp.DiTtEpxpaØ+ Àx0   z´„ Œ@|A yyo..raePyPyðz|A @{oL°yc|AtzD @{ý ý ý ý ý ½à@ @€a@4@ý ½ ~@@€a@4@ý ½`}@t@@`@4@ý ½À|@`s@ø?4@ý ½@€v@€a@4@ý ½à€@`x@@e@D@ý ½À|@@u@€a@>@ý ½@@u@ø?4@ý ½ €{@ r@€a@4@ý ½  ~@`s@ø?$@ý ½ à€@ w@ø?4@ý ½ ~@@u@d@4@ý ½ ~@@€a@$@ý ½àz@@€[@$@ý ½ ‚@@^@4@ý ½Ð@€{@ø?D@ý ½à€@`x@@`@D@ý ½à@ @€a@>@ý ½Ð@Àw@@e@>@ý ½à@Àw@ø?>@ý ½à€@@u@@e@4@ý ½à@ w@ø?D@ý ½À|@€v@ð?4@ý ½à@ t@@e@à?ý ½~@@u@Àg@4@ý ½@@d@4@ý ½@@u@d@D@ý ½@€@ @ø?4@ý ½@€@@u@€a@4@ý ½`}@t@d@4@ý ½~@`s@d@4@ý ×D–lF000000000000000000000000000000 °y!|A"# $rp.D%iTtE&pxp'a(Ø+)Àx0 *+z´„,Œ@|A-y.y/o.0.r1ae2Py3Py4ðz5|A67 89@{oL:°yc;|A<t=zD> ?@{½ à€@@u@ø?D@ý ½!@€@ y@ø?$@ý !½"@@z@€a@4@ý "½# ~@`s@ø?4@ý #½$@t@^@4@ý $½%@ @@`@4@ý %½& ~@€v@€a@$@ý &½'€{@@@`@4@ý '½(à@@u@ø?4@ý (½)@ @@`@>@ý )½*@Àl@@`@>@ý *½+€{@t@@`@4@ý +½,@ @d@N@ý ,½-à@Àw@Àg@D@ý -½.~@@€a@>@ý .½/à@Àw@d@4@ý /½0À|@t@€a@4@ý 0½1€@ w@ø?4@ý 1½2@ t@€a@4@ý 2½3@t@`}@€a@ý 3½4„@t@@ø?ý 4½5…@`s@ ~@ø?ý 5½6@Àl@@@`@ý 6½7@€q@À|@ø?ý 7½8Ð@€q@@@`@ý 8½9°ƒ@ t@`}@d@ý 9½: ~@n@ t@ð?ý :½; „@ r@À|@@`@ý ;½<@€@àp@`x@€a@ý <½=@@ @ð?ý =½>p‚@@@z@ø?ý >½?@€k@@ð?ý ?×D€l0000000000000000000000000000000@°yA|ABC Drp.DEiTtEFpxpGaHØ+IÀx0 JKz´„LŒ@|AMyNyOo.P.rQaeRPySPyTðzU|AVW XY@{oLZ°yc[|A\t]zD^ _@{½@ƒ@ r@`}@€a@ý @½A€@ r@€v@@`@ý A½Bð„@`s@€{@€a@ý B½C€@@@ø?ý C½D ‚@àp@ y@ð?ý D½E`ƒ@€k@@ø?ý E½F€@@`x@€[@ý F½Gp‚@t@~@€f@ý G½Hƒ@€q@@@`@ý H½I°ƒ@@ ~@ø?ý I½Jƒ@€q@`}@^@ý J½K„@ r@àz@@`@ý K½L „@@€{@€a@ý L½M@…@€q@~@€a@ý M½Nð„@@@@e@ý N½O@ r@@ø?ý O½PÐ@@p@ @ð?ý P½Q@n@Àw@€[@ý Q½R@n@ w@ð?ý R½S ‚@àp@`x@^@ý S½T@àp@à@d@ý T½Uà€@@@ø?ý U½V@@u@@d@ý V½Wð„@`s@`}@ø?ý W½X°ƒ@Àl@€{@@`@ý X½Y€@@ y@@`@ý Y½Z@@@@`@ý Z½[@@p@€{@^@ý [½\ƒ@@À|@€a@ý \½] ‚@@p@@^@ý ]½^@Àl@ t@ð?ý ^½_€@àp@@z@@`@ý _×D€l0000000000000000000000000000000`°ya|Abc drp.DeiTtEfpxpgahØ+iÀx0 jkz´„lŒ@|Amynyoo.p.rqaerPysPytðzu|Avw xy@{oLz°yc{|A|t}zD~ @{½`Ð@@@z@^@ý `½aÐ@ r@@z@@`@ý a½b`ƒ@ r@àz@@`@ý b½cà@@@€[@ý c½dÐ@€q@ y@@`@ý d½e°ƒ@ t@@@ý e½f ‚@àp@à@Àg@ý f½g0†@@p‚@@j@ý g½h°ƒ@ r@€@€f@ý h½i@@ ‚@€k@ý i½jÀ‡@@ „@@j@ý j½k ~@@@@e@ý k½lІ@ r@°ƒ@€f@ý l½mð„@@ ‚@€f@ý m½n€†@€v@ƒ@@ý n½o@t@à@@ý o½p„@àp@€@Àg@ý p½q@…@@@@j@ý q½rÐ@@@@ý r½s ‚@€q@à@n@ý s½t„@t@€@Àl@ý t½u@@@€f@ý u½vˆ@Àw@ð„@€k@ý v½wˆ@@p@…@Àl@ý w½x@€k@@ø?ý x½y…@t@Ð@Àl@ý y½z€@€q@ ~@@ý z½{ˆ@€q@ð„@@ý {½|°ƒ@àp@ ~@€f@ý |½}ð„@ t@Ð@@j@ý }½~€†@t@@€f@ý ~½`ƒ@€q@~@€f@ý ×D€l0000000000000000000000000000000€°y|A‚ƒ „rp.D…iTtE†pxp‡aˆØ+‰Àx0 Š‹z´„ŒŒ@|AyŽyo..r‘ae’Py“Py”ðz•|A–½€ƒ@@ ~@€f@ý €½„@€q@€@@j@ý ½‚€†@@ ‚@d@ý ‚½ƒ ‡@€q@ƒ@Àg@ý ƒ½„°ˆ@Àw@„@@ý „½…„@€q@€@€k@ý …½†°ƒ@€q@à@ø?ý †½‡ƒ@@p@€@€a@ý ‡½ˆˆ@@ƒ@Àl@ý ˆ½‰°ƒ@@u@€@n@ý ‰½Š„@`s@@€f@ý н‹@@~@€f@ý ‹½Œ…@`s@à€@@j@ý Œ½ð„@`s@€@n@ý ½Ž…@`s@à@Àl@ý ޽ ‚@àp@à@Àg@ý ½@…@t@p‚@Àl@ý ½‘ð„@ t@Ð@@ý ‘½’ð„@@@€@Àl@ý ’½“°ƒ@@@Àg@ý “½”@@@€@@ý ”½•`ƒ@@u@à€@Àl@ý •½–p‚@@à@€f@ý –×2¸0000000000000000000000>¶@ÈÈ@ÿ? uBÌáÁ¿Àâ\pGregory Warmes [B'bœ=ìÿìÿ¬]Ð>8ô@"·Ú1ÈÿVerdana1Èÿ¼Verdana1ÈÿVerdana1Èÿ¼Verdana1ÈÿVerdana1È Verdana1È=Verdana"$"#,##0_);\("$"#,##0\)"$"#,##0_);[Red]\("$"#,##0\) "$"#,##0.00_);\("$"#,##0.00\)%""$"#,##0.00_);[Red]\("$"#,##0.00\)5*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_),))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)=,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)4+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à+õÿ øÀ à)õÿ øÀ à,õÿ øÀ à*õÿ øÀ àôÿôÀ àôÿôÀ à õÿ øÀ “€ÿ“ÿ“ÿ“ÿ“Followed Hyperlink“  Hyperlink“ÿ“€ÿ’â8ÿÿÿÝ·Ôüóò„«êdq:F¥€€ÀÀÀ€€€cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½ÌÿÌÿÿÌÿÌÿÿ™™Ìÿÿ™ÌÌ™ÿããã3fÿ3ÌÌ™ÌÿÌÿ™ÿfff™–––3f3™f333™3™3f33™333…Ciris.xls uBÌ  —m%¾.:8B¯K´R  dü©ñÒMbP?_*+‚€%ŒÁƒ„M  com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 300 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.i< temArray com.apple.print.PageFormat.PMVerticalRes 300 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0.0 0.0 3058.3333333333335 2400 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.printingmanager com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -75 <  -75 3225.0000000000005 2475 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:44:05Z com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName na-letter com.apple.print.ticket.client com.apple.print.pm.PostScript com.apple.print.ticket.modDate 2003-07-01T17:49:36Z com.apple.print.ticket.stateFlag 1 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0.0 0.0 734 576 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -18 -18 774 594 com.apple.print.ticket.client com.apple.printingmanager com.apple.print.ticket.modDate 2008-03-25T00:43:56Z com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.print.pm.PostScript com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName US Letter com.apple.print.ticket.client com.apple.print.pm.PostScript com.apple.print.ticket.modDate 2003-07-01T17:49:36Z com.apple.print.ticket.stateFlag 1 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.privateLock com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.privateLock com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz,, ó `ÿµÿµ š «g(üHHØ(dÿh ¡"düÿüÿà?à?U  —€|A rp.DiTtEPpaØ+   D  à€´„ Œ@|A àào..rae0€0€Ð|A  ‚oL€c|A à€(   ‚ Sepal.Length Sepal.Width Petal.Length Petal.WidthSpecies½à@ @€a@4@setosa½ ~@@€a@4@setosa½`}@t@@`@4@setosa½À|@`s@ø?4@setosa½@€v@€a@4@setosa½à€@`x@@e@D@setosa½À|@@u@€a@>@setosa½@@u@ø?4@setosa½ €{@ r@€a@4@ setosa½  ~@`s@ø?$@ setosa½ à€@ w@ø?4@ setosa½ ~@@u@d@4@ setosa½ ~@@€a@$@ setosa½àz@@€[@$@setosa½ ‚@@^@4@setosa½Ð@€{@ø?D@setosa½à€@`x@@`@D@setosa½à@ @€a@>@setosa½Ð@Àw@@e@>@setosa½à@Àw@ø?>@setosa½à€@@u@@e@4@setosa½à@ w@ø?D@setosa½À|@€v@ð?4@setosa½à@ t@@e@à?setosa½~@@u@Àg@4@setosa½@@d@4@setosa½@@u@d@D@setosa½@€@ @ø?4@setosa½@€@@u@€a@4@setosa½`}@t@d@4@setosa½~@`s@d@4@setosa×D= lq444444444444444444444444444444 €!|A"# $rp.D%iTtE&Pp'a(Ø+)  D*+à€´„,Œ@|A-à.à/o.0.r1ae20€30€4Ð5|A67 89 ‚oL:€c;|A< =à€( > ? ‚½ à€@@u@ø?D@ setosa½!@€@ y@ø?$@!setosa½"@@z@€a@4@"setosa½# ~@`s@ø?4@#setosa½$@t@^@4@$setosa½%@ @@`@4@%setosa½& ~@€v@€a@$@&setosa½'€{@@@`@4@'setosa½(à@@u@ø?4@(setosa½)@ @@`@>@)setosa½*@Àl@@`@>@*setosa½+€{@t@@`@4@+setosa½,@ @d@N@,setosa½-à@Àw@Àg@D@-setosa½.~@@€a@>@.setosa½/à@Àw@d@4@/setosa½0À|@t@€a@4@0setosa½1€@ w@ø?4@1setosa½2@ t@€a@4@2setosa½3@t@`}@€a@3 versicolor½4„@t@@ø?4 versicolor½5…@`s@ ~@ø?5 versicolor½6@Àl@@@`@6 versicolor½7@€q@À|@ø?7 versicolor½8Ð@€q@@@`@8 versicolor½9°ƒ@ t@`}@d@9 versicolor½: ~@n@ t@ð?: versicolor½; „@ r@À|@@`@; versicolor½<@€@àp@`x@€a@< versicolor½=@@ @ð?= versicolor½>p‚@@@z@ø?> versicolor½?@€k@@ð?? versicolor×D4 l4444444444444444444888888888888@€A|ABC Drp.DEiTtEFPpGaHØ+I  DJKà€´„LŒ@|AMàNàOo.P.rQaeR0€S0€TÐU|AVW XY ‚oLZ€c[|A\ ]à€( ^ _ ‚½@ƒ@ r@`}@€a@@ versicolor½A€@ r@€v@@`@A versicolor½Bð„@`s@€{@€a@B versicolor½C€@@@ø?C versicolor½D ‚@àp@ y@ð?D versicolor½E`ƒ@€k@@ø?E versicolor½F€@@`x@€[@F versicolor½Gp‚@t@~@€f@G versicolor½Hƒ@€q@@@`@H versicolor½I°ƒ@@ ~@ø?I versicolor½Jƒ@€q@`}@^@J versicolor½K„@ r@àz@@`@K versicolor½L „@@€{@€a@L versicolor½M@…@€q@~@€a@M versicolor½Nð„@@@@e@N versicolor½O@ r@@ø?O versicolor½PÐ@@p@ @ð?P versicolor½Q@n@Àw@€[@Q versicolor½R@n@ w@ð?R versicolor½S ‚@àp@`x@^@S versicolor½T@àp@à@d@T versicolor½Uà€@@@ø?U versicolor½V@@u@@d@V versicolor½Wð„@`s@`}@ø?W versicolor½X°ƒ@Àl@€{@@`@X versicolor½Y€@@ y@@`@Y versicolor½Z@@@@`@Z versicolor½[@@p@€{@^@[ versicolor½\ƒ@@À|@€a@\ versicolor½] ‚@@p@@^@] versicolor½^@Àl@ t@ð?^ versicolor½_€@àp@@z@@`@_ versicolor×D€ l8888888888888888888888888888888`€a|Abc drp.DeiTtEfPpgahØ+i  Djkà€´„lŒ@|Amànàoo.p.rqaer0€s0€tÐu|Avw xy ‚oLz€c{|A| }à€( ~  ‚½`Ð@@@z@^@` versicolor½aÐ@ r@@z@@`@a versicolor½b`ƒ@ r@àz@@`@b versicolor½cà@@@€[@c versicolor½dÐ@€q@ y@@`@d versicolor½e°ƒ@ t@@@e virginica½f ‚@àp@à@Àg@f virginica½g0†@@p‚@@j@g virginica½h°ƒ@ r@€@€f@h virginica½i@@ ‚@€k@i virginica½jÀ‡@@ „@@j@j virginica½k ~@@@@e@k virginica½lІ@ r@°ƒ@€f@l virginica½mð„@@ ‚@€f@m virginica½n€†@€v@ƒ@@n virginica½o@t@à@@o virginica½p„@àp@€@Àg@p virginica½q@…@@@@j@q virginica½rÐ@@@@r virginica½s ‚@€q@à@n@s virginica½t„@t@€@Àl@t virginica½u@@@€f@u virginica½vˆ@Àw@ð„@€k@v virginica½wˆ@@p@…@Àl@w virginica½x@€k@@ø?x virginica½y…@t@Ð@Àl@y virginica½z€@€q@ ~@@z virginica½{ˆ@€q@ð„@@{ virginica½|°ƒ@àp@ ~@€f@| virginica½}ð„@ t@Ð@@j@} virginica½~€†@t@@€f@~ virginica½`ƒ@€q@~@€f@ virginica×De l8888877777777777777777777777777€€|A‚ƒ „rp.D…iTtE†Pp‡aˆØ+‰  DŠ‹à€´„ŒŒ@|AàŽào..r‘ae’0€“0€”Е|A–½€ƒ@@ ~@€f@€ virginica½„@€q@€@@j@ virginica½‚€†@@ ‚@d@‚ virginica½ƒ ‡@€q@ƒ@Àg@ƒ virginica½„°ˆ@Àw@„@@„ virginica½…„@€q@€@€k@… virginica½†°ƒ@€q@à@ø?† virginica½‡ƒ@@p@€@€a@‡ virginica½ˆˆ@@ƒ@Àl@ˆ virginica½‰°ƒ@@u@€@n@‰ virginica½Š„@`s@@€f@Š virginica½‹@@~@€f@‹ virginica½Œ…@`s@à€@@j@Œ virginica½ð„@`s@€@n@ virginica½Ž…@`s@à@Àl@Ž virginica½ ‚@àp@à@Àg@ virginica½@…@t@p‚@Àl@ virginica½‘ð„@ t@Ð@@‘ virginica½’ð„@@@€@Àl@’ virginica½“°ƒ@@@Àg@“ virginica½”@@@€@@” virginica½•`ƒ@@u@à€@Àl@• virginica½–p‚@@à@€f@– virginica×2½¸7777777777777777777777=ìÿìÿ¬]Ð>8ô> ¶ÿ?   !"#$%&'()*+,-./012þÿÿÿ456þÿÿÿ8þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ à…ŸòùOh«‘+'³Ù0h @H`x œ¤'Gregory WarmesGregory WarmesMicrosoft Excel@¦ójŽÈG¼ þÿÿÿPICT ´ÒGÿ ÿþHHÒGµµÕÕÿÿöööööööööööö ÒG Ñññññññññññññ Ñääääääääääää Ж–§§´´––§§´´ Ñ""("5"B"O"\"i"v"ƒ"""ª"·"Ä"Ñääääääääääää""'"4"A"N"["h"u"‚""œ"©"¶"Ã"Ðöööööööööööö""")"6"C"P"]"j"w"„"‘"ž"«"¸"Åññññññññññññ"""*"7"D"Q"^"k"x"…"’"Ÿ"¬"¹"Æöööööööööööö Eññññññññññññ Eääääääääääää  E––§§´´––§§´´ F"e "° "û "F ääääääääääää"d "¯ "ú "E öööööööööööö" "f "± "ü ññññññññññññ" "g "² "ý ëëëëëëëëëëëë1öööööööööööö"" ññññññññññññ"" ääääääääääää" " ––§§´´––§§´´"" DDQQ^^ëëëëëë , Lucida Grande .+ 1 (* 2 *5* 3 7B* 4 DO* 5 Q\* 6 ^i* 7 kv* 8 xƒ* 9 …(Ž10 ’* 11 Ÿª* 12 ¬·* 13 ¹Ä* 14 ÆÑ* 15 ÒG( <A)LB)JC)KDÿÿÿÿÿÿ e, #Verdana# ( Sepal.Length ÒG)K Sepal.Width)K Petal.Length)K Petal.Width(&Q5.1)K3.5)K1.4)K0.2(3Q4.9)V3)@1.4)K0.2(@Q4.7)K3.2)K1.3)K0.2(MQ4.6)K3.1)K1.5)K0.2(Z\5)@3.6)K1.4)K0.2(gQ5.4)K3.9)K1.7)K0.4(tQ4.6)K3.4)K1.4)K0.3(\5)@3.4)K1.5)K0.2(ŽQ4.4)K2.9)K1.4)K0.2(›Q4.9)K3.1)K1.5)K0.1(¨Q5.4)K3.7)K1.5)K0.2(µQ4.8)K3.4)K1.6)K0.2(ÂQ4.8)V3)@1.4)K0.1(ÏQ4.3)V3)@1.1)K0.1¡¶ÿÎÎÎÎÎÎÎÎÎÎÎÎ ÒG!E¡¶ÿ¡¶¡¶ÿ E¡¶ÿ¡¶¡¶ÿ ((E¡¶ÿ¡¶¡¶ÿ 55E¡¶ÿ¡¶¡¶ÿ BBE¡¶ÿ¡¶¡¶ÿ OOE¡¶ÿ¡¶¡¶ÿ \\E¡¶ÿ¡¶¡¶ÿ iiE¡¶ÿ¡¶¡¶ÿ vvE¡¶ÿ¡¶¡¶ÿ ƒƒE¡¶ÿ¡¶¡¶ÿ E¡¶ÿ¡¶¡¶ÿ E¡¶ÿ¡¶¡¶ÿ ªªE¡¶ÿ¡¶¡¶ÿ ··E¡¶ÿ¡¶¡¶ÿ ÄÄE¡¶ÿ¡¶¡¶ÿ ÑÑE¡¶ÿ¡¶¡¶ÿ Ñ¡¶ÿ¡¶¡¶ÿ eÑe¡¶ÿ¡¶¡¶ÿ °Ñ°¡¶ÿ¡¶¡¶ÿ ûÑû¡¶ÿ¡¶¡¶ÿ FÑF¡¶ÿ¡¶ÿÿÿÿÿÿ F Ñÿþÿ ÕÍÕœ.“—+,ù®0¨8@ `h p …'University of Rochester  iris.xls  WorksheetsþÿÿÿÿÿÀFMicrosoft Excel Worksheetþÿÿÿ8FDocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿ3ØCompObjÿÿÿÿÿÿÿÿÿÿÿÿ7XÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿIBExcel.Sheet.5gdata/inst/xls/ExampleExcelFile.xlsx0000644000176000001440000011237111326752711017253 0ustar ripleyusersPK!îÙð8–ÜÔ[Content_Types].xml ¢Ð( ¬UÝNÂ0¾7ñ–Þš­€ÆÃàõRIĨíÙVéÚ¦-oïÙ€%’ÄífÉÖœïç|çtãé¦TÑœ—F§d˜ Hš!už’ÅKü@"˜L )Ù‚'ÓÉõÕx±µà#¬Ö>%Eö‘RÏ (™OŒ'™q% øêrj_²èh0¸§Üè:ġ “ñ pR@4g.¼²y¨0|îŒõ”Y› ‰f»ªŠ8%øUIÎʦk-Ž(c“e’b¬J$J`ƒ|Dl\ào*LÚνQÔÌxá;ó{ë€ _„R%¿°:ž c+¢çJê./ ù‘mYVM¬P{KÍéNöümÜòÓ˜eïvÑvR2©Oxu ü‘×3ï'*ÁÊz |!í¹T+‡u FU·=[mðNÛ&»š®°UÐûXÕ g˜n(Ðú9ìl¾†9CØ´dßò—©Á¿PÇ]g÷ÿÓÁ™â³—¡gþ÷Â>ŒzÖñ§<šË— 8¬~UÝr¥Óúß4ùÿÿPK!}ÌTž Ý ¶_rels/.rels ¢²( ¬’MNÃ0…÷HÜÁš}ã´ „PnRw…LíibÿÈv!½=†EC¤U‚¥=ãçïÍ›õf0={§µ³–E Œ¬tJÛFÀký´¸Z…½³$àH6ÕõÕú…zLùQlµ,«Ø( MÉ?peKcá<Ù\Ù»`0åch¸GÙaC|U–w<üÔ€j¢É¶J@ت`õÑçŸÿ¢Í %T˜KháC& Ig/¬ÆÐP œ|Î×ñ»£ÈÔÀÏÝ^äö{-éÑɃ!›Îxæ4$²ŠÔ<z?G´üO¢)ó8Ÿ¡ç.t;çº9–Õå,¿¯ÂWjfgQ÷#È)¨S­xóÔ|ÅÅ'KY}ÿÿPK!8ÙÒ$æxl/_rels/workbook.xml.rels ¢( ¼”ÏjÃ0 Æïƒ½ƒÑ}q’vÝuzØôºu`%Mì`{òö3Ù–¤P¼‹éÅ ú!òv÷Õµäm´b%)TB—ª¼žoîXÇUÉ[­Á€vÅõÕö[îü%+›Þ¯¢,é\ÿ@©;nÝ£ò•J›Ž;ššö\y4OÓ 5K (N4ɾd`öå Èaè}çÿµuU5Ÿ´xïP¹3-è§6G+å¦FÇ`JY:VV‰'zf}a˜uæ6&Œó/†óTÆŽgbØÄd°nh½½¦§ù‰Cí—Ü`ùêŒ÷þ’b™ÁøM‰çTÁ[ñ(y£æqL©DbÚbJý®KÐù…aò¿ÉГߩøÿÿPK!þ=ýÔxl/workbook.xmlœSÛnÛ0 }°ÐôÞØÍeMƒØE×.X€a(Ö®}Vd&¢‹!ѵû÷¥”¬s`öb™¢yxy¼¼êfÏàƒr¶à磜3°ÒUÊî þëau6ç, °•ÐÎBÁ_ ð«òã‡eçü~ãÜž€ ¯›E–Yƒaä°”Ù:oRèwYh<ˆ*Ôht6ÎóÏ™ÊòÂÂÿ †Ûn•„['[ ´@¢jÕ^.·JÃãAMóCâÝkδøµRUÁ§ºÞ]ø¶ùÒ*³³|ƳòMäg•@8¿Ì§4$šHíºµÝ_[ë0õ.8 N´ènœ!™!Ü)‰-½ÄÅI=*èÂ̲þIÙÊu?ÀË»¨K©'Ua]ðñärN_î¾ÚÕHL.&SºD±ùY|–GÕ3<ˆM¤J½³Aó4}"‘NfÓhîãFØJù€Qk©ô E/~]%˜Ó’{ÎVƒšñ f[ŸÖt k&¢ã^hv—8|`L“¿`(«P Íú!mÚëíiRŸ8d)´¤=Æ#é›äÓü‚3’ [ïÉM7”9®‹0¿,—tÝiú{%½ n‹#éLvp&9ZfÐKHŸ ÞzõÿÕåÒô‹k/ëõ-[i±#K¥ÙRbŸ‰jöû‡,_ÿÿPK!XE W\²xl/worksheets/sheet4.xmlŒVMoÛ8½/°ÿà±@,ËMãD°\$²-¢ÁvÛži‰²ˆ¢–¤§¿¾C2Ö§Ñæ`›š™7|oHÍxõñ(8j¨ÒL–1gsŒh™ÊŒ•‡ûowq‘6¤Ì—%ñ Õøãúï¿VÏR=é‚Rƒ C©c\SEA Ó‚ ¢g²¢%xr©1ð¨®%™ ,æó«@VbŸ!RoÉ!óœ¥t#ÓZÐÒø$Šrb€¿.X¥OÙDú–t‚¨§ººH¥¨ Åžqf^\Ò6MãZ•Ñ«¬ ÁR%µÌÅD‚¤Q#8F">J©ÈžC‘Dã,ŠjªzkŒbûÚP¨’h¢wx½Êз5GŠæ1¾ £ûk¬W®8ß}Ö½5jÀãŠèy‘µÁÈV/å“ ý”Åx95å4µu@~šPÎc|÷ð· ,a‹ Ý£¿>í·sçõ¨ÐžhšHþƒe¦€‹÷"£9©¹ùW>ÿCÙ¡0`u ]¾ 1d½RòÁ1†°eE쥣%0K­ñ¬€ÑðܬïWAû§ðP‹\œCÞµC^žG^žC&Öêø´ø«îXm¦ËaÄvÑ‘w9vÓˆŽ¤‹¸ŸF„]È Îé¸k« œ &bEÚ†C߯û`û~3ŒØþ1b7¸渟F„Ú¼«³òÀÚò G 9É[´Yýéõ}#ÜÖû~#}7èXûsóðÝÑë®Ç@Øò¬0°vÈùÄBNÂFWjÓ÷pÛ¾o$zç}}ÑcI>N¬#Ö… $ÙÖ?yïÀÚ!G´ 9Iê.¸?«¾o„Ûö}#¹»¾o$šfL÷j{¾ÓùÎäšTBx ­-¯9·Ë/åƒ$™¥ m±*`¾æü²4¶©Ú¶óRA?/e"Ë×!éb¡&êÀJ8Í¡óÙ*ª|[ôFV65ÚKc¤pËÆ…V8ŸAp.¥9=Øý!çWjê IÅ`´¹‰M_*£3`ÿ ÌßT,Æ—‹›Ë›«åâX5`>u@Zz4Ú¸ß×1+Ž“Áص µÀXÍi@)u“úúuR× ¶Mú7£×+qŒ¾£Ï2ƒªBm¾”ôtÛù…~|ni‡ðöߎ}ÐþÛXÿÿÿPK!q1¢hÂxl/worksheets/sheet2.xmlŒVÛnã6}/Ð øX –íxD°½°-] ‹ š½<ÓeáE%)ÅÙ¯ï´e]¶m^iæÌÌ9Cj&‹'ÁQMµaJ.ñd4ƈÊTeL—øÛ×ýÍ=FÆ™®$]â7jðÇÕï¿-^•~1¥Ai–¸°¶Œ£È¤ÄŒTI%xr¥±ðª‘)5%™<šŽÇóH&qÈë÷äPyÎRš¨´TÚDSN,ð7+Í%›Hß“NýR•7©%¤80Îì›OÚ¤©—¸Ò2>˺,Õʨܺ˜X4®ÇH¤ñ§£Tš84IÔÞò¤©¡º¦kk5;T–B—DÿW‹Œ}×s¤i¾ÄëI¼ŸãhµðÍùÎè«i=#KÏ”ÓÔÒ Î£K\’#}$oª²¹Ó8(õâB?h 5Œq5HjYM·”sWêNôïsÙ[W4jª¶Ÿ/ öþŸ4:C·Šÿ`™-€Ü”Œæ¤âö/õú'eÇ‚Õ'ôùbÉj¡Õ+‚ƒÒ¦$îšLâ9pKqã¬Þ‘¬õj¾ˆj ‘žÛ!⮋H†ˆÛ.b7D̺ˆý1¹B"Ðè˜þJǬ‚ɸ›|ãBœH'oÒõmƒoÖ è"’ÿE솈ûnŽý1ùÐ@:òÜÕÓ¬Wy= r‘7m²úóݶ}½¸$øþCúnˆ¸²öù÷1oÓ»^Ž0¨3¶qVǾ@¸oH‚aÖ v}Ã>üÇÛ©øáW×`½¶²×® ¹´²w‰·m_/.iûzmÞlÊö›ðÛ þív@£‡M\wÚߣ½q!I×O*4»íëÅ%m_Oî®íëÉ…!Ú’q&ádœ sɨ-á) ¶¼âÜ=~‘Šdç Q°ï,ó~%­ªðÙ·æ»T[%ÏKÓ] 7‰?}dÒ NshäxtÕa(†«J—”µJøÇÖ!…A88WÊ^^Î9Ÿ©­J¤4ƒUç7 }¥­&ÌbT€ý'0#<)ÙϦ³‡ùÝôX5`>t@Zz²Æú¿çµ+NƒEÙ,¹,¹(¬\XÕiDO)õ›ûþ¼¹+ ¥{›ÿÝÑ«…8ÅOßÑg•AW¡7_$}‚^ºý…~<ƒÿ´¡2v¿ž}Ôü÷±úÿÿPK!/±y‹xl/worksheets/sheet3.xmlŒW[oÛ6~°ÿ ©/Ý€X¼HeØ.êÛ i³¦—·ŠLÇB%Ñ“h'Ù¯ß!iËí%[Ö¹<çðpôî¹,¼½¨›\Vcï‰*“«¼zû_>/¯¸ï5*­Vi!+1ö_Dã¿›üúËèIÖß›Ê U3ö7Jm‡AÐdQ¦Í@nE”µ¬ËTÁÏú1h¶µHWF¨,‚ Ê4¯|«aXÿŒ¹^癘ËlWŠJY%µ(Rþ7›|Ûµ•ÙϨ+Óúûn{•Ér *ò"W/Fi«f?öwu5<„uUæY-¹VZfX¦Ùp_¾WfÃëÇJÖéC •{󿮍÷â½Ruþ°SP*÷Ã?üÉh•ƒûs¯ë±ÿ—ùÁddÐùš‹§¦óìíáŨߦâ&}‘;å{þ)¿kÖëÕØG ´…È4^ _{1E1ö ìà¿Æ <‚‰ µÑ}>Ú[š »«½‡´3Y|ËWj™‰±ëtW¨Oòé/‘?n¼¥­ÏóT¥“Q-Ÿ<ØG &·©Î cÒY˜ž¡­¬‹›´+ߦڜ çz3›Ü$ʼntpJ0ŠÇIÎIâx±/Z„n>þùöªÅøÍ‡/·.F–û€QÒÔÈ^ĈŒh+b0˜jÞ#Fˆ“L3K·¡& í¬¾¶¹¶ÑCÈ‚5¢3†F,äq˜Ð„²8AÌñea¤'÷×:\¡q£„‡Å-‡{®mœÅfl[†pp±Ç:4Ž\d.JaŠ9$D˜D˜@‰Ðð¬“/Á×ö×°ÑsÚù‘kãs¢™jÞN“43K?bC)ï-7)4ß°áŽ[FΣ˜E‰#½[ml¯õC=ÁœÇ–˜„wòhªyO±1ät¸™¥·±qL"tZ÷\Ûx=6}Pï=Ž Þ ãÖécE8ùo'{Rv޵^þ›žr¼Ö5†O§‰=, û ‹Ä­¹Ùá„Юœ³UO Âi‹€EˆCû PI.1w Ô ñ‚ø+hhÏÚ´8ëƒv‚µ§fgi‘ÁȺÞ…~üXÝÈt¥ÇPh>Û \\Tnè²RzXÖSÉËõJÎdu¸ý^˜°oÓú1¯¯kð bhɵwí%·fÂ}JÉÒŸÝxÚÛÊn+½;Á+ Äs&ÌŒ®`»L;W¸Ÿ–žŒÊçáÝÍWïV®UŒ?VââÖ#¦÷í"0à6X§õ§ñ>Ð÷³…“ÿÿÿPK!no`2xl/sharedStrings.xmlÄ•ËNå0 †÷#Í;x²‡Pg(bƒF\ Ó˜ÓˆÖ.±Ëåí :#±Ç –¹|þØŽÓœ¾N#r¡‘ g×ÐÌC=^sÿ·À“^¥Ö­èÛ\=o˜þßÁùÐøpŸ[àî,ð¥¾6Eìáè‚8‘9ö5)5ã‚å]¸ƒd°ÝÆFw¹ˆÞð‹Åÿ-öLÉ(r7äbÕèx):t±W.–xÜ`²àçcì-—‘,¦×õ}ýÈdÛöŒjõ Œ™°¶{ÒÚ÷_tˆ /¼Œ 12üCÇ<Ï»Ñë&®ûRÔhÉÚ§eþõ5%_ÿ¼ðÿÿPK!4Ž2§~ xl/styles.xmlÜWA¯Ú0 ¾OÚ¨zßš¶PèT:ñ ‘vØ.ïmÚ5ЕÒµa‚ýúÙ)^ŸÙƒiÒ¤•C“8ŸýÙ±’|Ü—Êù!릨ôÄõß3בzYå…^OܯOüÝØu#t.T¥åÄ=ÈÆý˜¾}“4æ äãFJ〠ÝLÜ1Ûž×,7²Íûj+5HVU] Ózí5ÛZмAP©¼€±È+E¡Ý4YUÚ4βÚi3q‡Ç…4i~:?„^ÌõÒD‹R¶óo²Î…¸è!´U& X¸Óíÿ©‰e¥ªÚ)t.÷2¿kñ‚kOÑpô#ë{ÎJ¢bô`!M¶ÂYkç8~:lá5e;»ï•ÝëZü`x; ©T‘#‹uö<4A€Jýåh`u_ÐÅcµÔì <\TuIÚeHÚÛ¥4Qre@k]¬7ø6ÕmTÆT% òB¬+- ½ѽ É yjxµFz©ðeW.dÍíÝG%DpSáÝ©Ôý¦¶Ø¡¼/zȳrêÞÈ÷ º©.ªa±+”)ô©¸ÏÝtæûs?²×º ø’ÀNu²ÑÉåJì”y: 'îyüYæÅ®Œ±ÎlǵÇû×Þ80­×‹öò´¹ãƒ€¾„Û‡– Œ’0Æù5 Ê( š¡1¸Ncpýšä7DИٌYDqóùÃòœˆZ™‘žñÙ¯‚ ØxLb›>̧” ]‰u4ðmKíÛADLbb6òCÒÎ $kÁ“Ú2†?Š5"hLN§|Naf³`Ú¡¾?plÃqFaóyÐ~ö1ÑÈ÷éÓæóéh@žö8†´¶ið0£#ú¿ùÃX–ÑqÃõë’Œ<DĶõÏ'ޝÙA­-Ëâ˜fÀ9ʨ Ã(¢1a˜ÁCaÐ>]shçš$†R¥´qAmQ’šuáÂ0†Q’0ŒcZ‚šA-‰ãßIh;¨ö%aˆ¬½Þ}äu÷”wþãœþÿÿPK!È{Ö©üŠxl/theme/theme1.xmlìYMoE¾#ñF{oc'NGuªØ±hÓF±[Ôãx=öN3»³š'ñ µG$$DA\¸q@@¥VâR~M ŠÔ¿À;3»ëxÜ8!€€æÐzgŸ÷ûkföú㘡C"$åI#¨^­ˆ$!ÐdÔîõ:WÖ$N˜ñ„4‚ ‘ÁÍwß¹Ž7TDb‚€>‘¸DJ¥KK2„e,¯ò”$ðnÈEŒ<ŠÑÒ@à#à³¥åJem)Æ4 P‚c`{w8¤!A=Í2ØÌ™·<&Jê…‰®fM ƒT5BNd‹ tˆY#9~Ô#Ç*@ K/AÅüK›×—ðFFÄÔÚ]ÇüetÁà`ÙÈ£~!´Ú©Õ¯mü €©Y\»Ýnµ«?Àa–Z]Êþõ›'ø–Àý2¼Gc"Ñr„öy ¶Ǹš“¾8E/ÂÔ¡Àðö°n«ÈÞ™`æÃ5‰ë¼ûš‡xsüÐѵ‰±¢É·¢ØîrΚ\xpKË*y¸7NF~áb\Æíc|è“݉Úö8…®™'¥ãûVD5÷N‘„(¤ßñB<Ö= Ôñë. —|¨ÐŠš˜z]Ò£}'‘¦D;4†¸L|6C¨ßìÞGMÎ|Vo“C ™GùaŽoâ±Â±eǬìðÛXE>%»–qm© Ò#Â8jˆ”>š»ì-ý†~å û.›Ä.R(zàãys^FnóƒV„ãÔ‡íÒ$*cß“¢íqåƒïr·Bô3Ä'sÃ}Ÿ'Üg7‚{tä¨4Mýf,t,¡Q;ý7¦É›š1£Ðm¼mÆ` F“¯$vNµày¸aãÝÆãd@®Ïž·}÷mß þó}w^-/Úm§ z¯Þ<Ø}±Ù%Çs7ÉCÊXWM¹-Í>Y°t`QÓ™")Mi?³æîàF$¸ú€ª¨áöØÕ@3ÉŒõH¢”K8Û™e/o‡}º²'ÃU}f°ý@bµËvyE/çGƒ‚9#sþÌ­h‹ [¹–1³/"¬ª•ZXZÕ¨fZ#­0b8k,Þ„]‚½ xy ŽèZ4œM0#íw;€ó°˜(ü5!ʬ¶†Dx@lˆœå’7«&vy ™;H)OèÎçÍÂkà´³•0i1?trÎ`êd]v§ª‰%åÚb :jõÕåÕ…8mC8•ÂÏ8… I½oÃlW;¡6kϬES¤S‹ëþ¬ªÂEÜ‚qÊ8RmcÙšWY¨X¢%Yý—Wk:Ù.Ç›¨ÐbeRäÓB톖 ‡$Tå`—V´ïìcÖ ùXÑG¨ÏÆbCøÁ§Úž•p¹` Z?ÀM˜ö¶yåöÖ¬Ó”ïŸ Î®c–F8ë–ú&%¯8 7õVè`žJêm^Ýqç7EWüe™RNãÿ™)zÀie #ÂE¬ÀH×k#àBEºPѰ#`î›ÞÙ·©ðœ×ÁæAõÿ¶æ,SÖphSût„…q¢"AÈ´%“}g0«f£Ç²d#“Q%uejÕî“CÂzº®é RÝt“¬ ÜéüsŸ³ êô¥\oN)F§­¿{ãb‹Œ:µ—Ðù›û¿PÑ3ý,½!ÏgdÙýbºKªåUá ¿z=uAÀ¥Yk;ÖŒÅË«¹rÅY‹a±ØÏ¤pgƒô?0ÿ¨™ý¶ jïCoEð©ÀúAV_Ñ] 2H7Hû«û»h“I³²®Ív>Úkù°¾äj!÷”³µf‹ÄûœÎ.6Q®8§/ÓÙ™‡_Ûµ¹®†Èž.QXæçóQªü݈÷B ·á†~Ìì—$™Â“©ƒtO˜ìêóÁ$ûɤ¸6ëôF#Y²O†ˆŽóóGá [BökF¾E6hM¦­ \ñ\ ¯Ií´,ˆ—Ï&.(ŒdhÙ±¹&ó1€oYYãÖG;ÀÛ&k­ÖÅ•{Š%Æe (ïw™÷䳨ËìAñº€ËÔñ›]–y œ7›xð5R`8štMÿ…¡c3ݤìæÿÿPK!צ–±{š xl/worksheets/sheet1.xmlŒ–ßo›0Çß'í°ü¸©!!YÚ¢À”ÐM«ÔiÕ~´o“8‚UŒ™íÐtýΆ’’d¨/ þÞ}|>û¼ø¸©Ai.ËNFcJ LdÊËMHýü|vA‰6¬LY!Kéhú1zûfñ(ՃΠA¥inLxžNrLd%~ɤÌà«ÚxºRÀR'…çÇsO0^ÒÆC ^ãCfOàJ&[¥iœ((˜A~óJ?{ÉkÜ ¦¶ÕY"E….Ö¼àæÉ9íÜÔ!ݪ2h§u&x¢¤–™±š@°$¨EA‰H‚ëM)[˜$Q;Ë­ ª†¥1Н·0K¢ÞÑh‘rÄ·9' ².'A|A½há’sÇáQ¿x&5BZ± ܰ'¹5”Øì¯¥|°C¯ÓŽÑ§†›Â𯆊"¤Ÿ&¸€\|Ä^ãåós¼Ïn½nY3 ±,îyjr, ¬‹2¶-Ìwùøø&7hvÌW̰h¡ä#Áe´!+f‹bL‘,±Æ¥µ†tJ *5Zëh¼ðj„HÚ«ã“þˆøx„ßð0z‡àŸD°Öú.øëÕþ[æs¦ ¥Íú¬ü`e7w™^ú¿1jfgpà$rûv‘“ ÐÉôÈIo ˜©Y´Öf ǘËi°l#à—þ{Äs˜û$¹¥XýÇI3?¬‘:šuiuŠx@᪪Ž.:Eo³“³°Ö³°¾­©:Âäôjc@1n—}E< h‘ýóNÒcþp’ÙZ‡™’¶P´Ì“yGÐäy@ÒBÏ÷QzÐó“ÐÖ: ý¡O°P´Ðþ$´Ð“šõùIjk¦>ÈÛj@ÑRO$ñ€ä¹>^,OÚn²ãÎZ‡©÷õÖìÃEK=;¬êIK=í÷NCÝùÍ]åØÇ OðˆÏdilóÀC˸ѼZ-Ä.¸½¹#_eŠYÅžõ­„[Ì¥íäþÎÀ="6FFhûëè½îVýÿÿPK!׫ˆAðBxl/calcChain.xmlL‘]NÃ0„ß‘¸ƒµï­ÓJAqªú‡À,Ç4‘;²-·Ç‘éÛçÝõÌxÝž¿æ‰}ú”Çí¶ 1\ìÇpôþöº9ËņÞN1xAß>Ó¹»¿kœìXUYÐPÊòÂyvƒŸmÞÆÅ‡Úùˆi¶¥Ó•ç%yÛçÁû2O|ß4G>WêZÇ’ ËØX3ÿ/<Gàð´¢J Â¬*ˆI ‚›*Ä‘@uX%PíQš¿bÌ@ÇÀÈ ‰ATó¼Jš]¾‘ÇêôÍ„ÆE}h(kXkÒˆ©á¡=øúûÝÿÿPK !véÉJôaôadocProps/thumbnail.jpegÿØÿàJFIFHHÿâ@ICC_PROFILE0appl mntrRGB XYZ Ù  acspAPPLapplöÖÓ-appl dscmòdescüogXYZlwtpt€rXYZ”bXYZ¨rTRC¼cprtÌ8chad,gTRC¼bTRC¼mluc enUS&~esES&‚daDK.êdeDE,¨fiFI(ÜfrFU(*itIT(VnlNL(nbNO&ptBR&‚svSE&jaJPRkoKR@zhTWlzhCNÔruRU"¤plPL,ÆYleinen RGB-profiiliGenerisk RGB-profilProfil Générique RVBN‚, RGB 0×0í0Õ0¡0¤0ëu( RGB ‚r_icÏðPerfil RGB GenéricoAllgemeines RGB-Profilfn RGB cÏðe‡NöGenerel RGB-beskrivelseAlgemeen RGB-profielÇ|¼ RGB Õ¸\Ó Ç|Profilo RGB GenericoGeneric RGB Profile1I89 ?@>D8;L RGBUniwersalny profil RGBdescGeneric RGB ProfileGeneric RGB ProfileXYZ Zu¬s4XYZ óRÏXYZ tM=îÐXYZ (Ÿ¸6curvÍtextCopyright 2007 Apple Inc., all rights reserved.sf32 BÞÿÿó&’ý‘ÿÿû¢ÿÿý£ÜÀlÿátExifMM*>F(‡iNHH  •ÿÛCÿÛCÿÀ•ÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ ÿĵw!1AQaq"2B‘¡±Á #3RðbrÑ $4á%ñ&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚâãäåæçèéêòóôõö÷øùúÿÚ ?þµ®›áÿ‚>ÚøçÄ> ±ÔtýÀ~&×Hð<þ.ñ%ìVºR]Þ¶Ÿ¢hºn£®ëº”ÛY£³°´¹»žBHM¡Ýj1s”asI¨®i(«¾ò“I.í¿ÄR’Œe'{E6윞šè’m³ór/ø(…-ü!¢~Ð:ÏìÝðúÙgÅž#ƒÁ¾Õ´_|:ñíºäבÙÇ{ª|ÓWœO<éÏÿøŸ[ø· EºŽ±á!›;~ÿ¨^R¢ª¿¬F.M:S ZöUŸ’oÚJ*›ÙJç×tW¨MÚ-TŒ«^ûºwûà¤æ­vµ±úG¨é~Ö¥øE§xSI²Ó|Mã Ë$ø_ûþçIÕ4 jùl5*þÊÏR³fg{Ý'Tµ‚æÖêŠîÚ+ˆ–œWûO2MÂ…Km$¤¥Íªm]ÚI½÷:*ÉßÊÚSÄROtÜd¤ÚkGg¥ÓW¹ö?ü(¿…?ô%hø*Ó¿ù°7øQ èJÐ?ðU§ò%yßÅÏ üø?ð¿ÇÿuÏiºo€ü'­øžm6ÏHÓÞÿX—J±šâÏCÓb[6yõMrùmô.ݤ¹Ô/m YäPnœZ§ç%½•Þ­ù%«}“"¤Õ8No^X¹[«²½—›ÛÕŸÿÁ=u _âÖƒñ_áÏí9ðâÇIøñð—źMþ¤šŸÂë‡ë þ'è«â¯j–¾k1Úè:¤^4øf5‹¾°ß†¹xíy«JÍÓŒ£J›§: :U"Ò´ùí8>Y¦üýÙÿÛÍ-†­I©Æ²j¤nñä¼f®¼Ÿ4oÖ×z³ôSþ_Ÿú´üißü‰\gP‹øSÿBVÿ‚­;ÿ‘(ÆüAð¯áýŸÆÿ‡ž·ð®Šš>­à?ˆ·öÙÖ_g¸¼°×< •Ô‹q\ZÅ{yº3Ä—W Œ¯”WÕëJÞò­†IõJJ¿2O{JÊêöv]Œ%'õŠ1»åt«¶¯£q• 6ºµÍ+z¾ç²‹øSÿBVÿ‚­;ÿ‘+pÿ…ð§þ„­ÿZwÿ"PÇ߷扣| ýþ8|Wøaáß hž<ðw‡t«ïj÷ð¾¥qyâ¿éWwOi¯éWÚyzuýájöwZ}¡"òêŠÓ„§ ¸šTê+ÂRjJï_u¾=×F›ØÃ9S¡Rpv’JÎ×ÞI=ÖÍï§Vf~ÀV~øñû:Xø×â›áø¶Çâ/ÅÏê:õ—…¼!ee}ià߈þ#Ðt²kÓm< ㄇÃÖšLxÿÀv:ƒ¼]wέ¢ØYÃ+@†.”iVq‚å‹…9¤ÛmsÂ2zJó¼ß»&囤ªR朹¥Ï8¶­ÒM-b”e¥½è¤žçÚŸð¢þÿЕ à«NÿäJæ:þ_Ÿú´üißü‰@3á…î¾5|UðíÇ…tY´+Ãÿ.ôë94ë'ŠÎ}B×į}%¼mnc…®Ú ÁÌ`„ÈXƤm4• ËšSÄ^]Z±²o­¹¯µÙ„xŠé¶Ò…•Ý“n­Ú[&ì¯ÞÊ糋øSÿBVÿ‚­;ÿ‘+pÿ…ð§þ„­ÿZwÿ"Pçï퓆~|Tý—~®½áÙïáÅ­[â´~Ùkÿ<;âx>ëâ%íî¿x5Ÿè—·WÑx6]BkmGUók¯ J5)â'ìÝj”Õ7 IÊÍJMNmBQœ¹ZEï.g±Í^¤¡:1çöP›Ÿ=KGGxÆóRŠæÖí®š4Ï´þüø=ªxÂZü#¿,ï|=¤Ü[|@‹Jð—ãHe³‰£ñ:Ÿ i:‡Ö”‹üè66zAóó§ÚÁjb‰y§¤ä¹=Ÿ¼ýÍ}Ý~y¹i·¼ÛîÛ7ƒ¼bù¹î¾==ï=,µßM;ü(¿…?ô%hø*Ó¿ù¤ ÿ…ð§þ„­ÿZwÿ"PŒüøYðÿ_âBêÞÑo?²>,xïHÓÚm:ÊG·Ólµya´²¤·r¶ö± H!M±Ä¹ Þ¼TeK•%|5;u“R¼Ÿvú½ßSŸ)KÛs6툫w{E5d¼—CÙ¿áEü)ÿ¡+@ÿÁVÿÈ•Ðð¢þÿЕ à«NÿäJügýºü?Áÿü/ை^ øfþý޼%ñ›àßÃ=CáÃOŸµO‰_¼;ÃO°ëºñî¾|D©T©ÍR>ÊŸ³„¹ïȹ\¥+Í;íéÈ­8TœcS“–Œg¸Æ^Ö£”×&«™¹Z1´]Öçëç†> |?Õ<5áíO^økáý\Ôt=&ÿZÑF§L4}ZòÂÞãQÒÄÆÔ™FŸy$Öža$¿“¸“šóä’“IÝ&Òov¯£~»©¶“jͤÚìú¯¼Üÿ…ð§þ„­ÿZwÿ"RRÿàw¸¬oeOè*ñÚ\ÈŒ4½8É ²E¨9A÷¤Ý“~Måÿþ|=ñ/Áÿ‡šÞµáMÿT¿ðž…q}{>›c-ÅÝĺe¬³\\K-¼’M<Ò;<²»–v$“šèÅ%ExÅ(Æ5f’JÉ%&’HÇ Û¡Eɹ7N ¶îÛqM¶ú¶õo«=oþ_Ÿú´üißü‰X?ü=ø?âßx'ÂzÕÅM[I·Ÿ@Ò<=|=áé’À%”mฒÍç–(QÓ¹ù2sÉÝU¤¢“ÃÂNÚÉΦ¾m^Êúè´0•*²“YœSm¨¨Si+íw«²¶¯WÔù;á‡ìíàÏ~Ùÿ´5œ~ð׃þ3ü#ð·ÂMzOpø'á­ï‰ kúV¿ðú}_âf¯¬#øÚÔÙÆºhmoãÑ5Ùa½/ Š´†%¨…‰Ú@ÎÐ+•×,ã ¦ç%9Éò¶›V“¶¶Zî¾gB¡.hJuçQBjj.K™&“º×K·mŸSèoøCAý¶þ?ÞþÆßto‰ÚÜ¿~.Oâÿ‹ßþx_À¶øi§êúÿþ7x÷Gøwàûf¿ñœš'†ìtó¯kvBþóTÔ­­í­ËM#„F`ysö9ý l?l†Þ-ñ‡„²ÿ„3Å_ôS¼Iÿ‚¿ò¶€øCê–ÿ&Ðî£Ôþx_Â:n›¤xïÂ~’×R—ân­áøµmbM_ÅZu厤Á¨_\[ÛO,´¥ÚÕ6ŸtìþýÁë¾¾§êrx'Äñ¢ÇÄ¿Ç*¢G“á´DEUL ¨ªUP@;þÏÑNñ'þ ü9ÿÊÚ?á ñWýïà¯ÃŸü­ ÀŸuM5|Z4¿x‚ÀÞxçÄ·×å,49Mæ£wv·wnf±“ašYY¼¸‚F™Â®*ç9MÅËìÂ4Ö–÷a{_»×VD!srý¹Ê£»¿½;_妋׹ÞÂâ¯ú)Þ$ÿÁ_‡?ù[PXÂâ¯ú)Þ$ÿÁ_‡?ù[@–ÿ¶ÿüñ_í û7|ñ5¯ÄøóöŠÑ|_®xGZµÖþøDÐl|!âøWPµ»×~'ë>K­^þûÇútºf‹¢Ëw¨_ÁmäÛ»!~¡ç×¹ú‘ÿgŠ¿è§x“ÿ~ÿåmð†x«þŠw‰?ðWáÏþVÐ$ðG‰åâ“âgˆÞ9Q£‘—áÜ:8*êq¦ƒ†RAÁž´nðÛáæ¯¥øÂ7Äéºm·‡´˜m,£°Ð¦X!ŠÆÑ<Û‹ %…EÝÉcÉëWRr©9Ô—Å99;mw«ü{ܘAS„aòÁ(«»»-®ÞçoÿgŠ¿è§x“ÿ~ÿåmAG„|,›ã¢|?ð¨ðŗÉtOì]4ؾ§¯­ÿ•ö(ý­aÒÚœ¨S"ÂòF¬J¤’¼ï«Ysûw.¼±¦ÕúÙº±o^èÂ_Yæ|ª—-ß-å$íæ½œµï©óOûÝwNý²~,Ùi>²ðÿí ã‡#ñ<Þ$×¾!Máoü4ðgŠdðÆ«è¶ku¡YXèž ×¯­ü?±i÷óÁ­ëWšl7Vo,=u=“ÃÒnUeF3qŠŒ(óFrÚ¿´Ní+ÉߢæÖ׿ƒ­õЉFšªãÍ+Î¥¥+&¿wmv¿vÒ>´Õ¦øÕ'ˆ<…muñáL²øÆð”,5/jI/‹|i¥êZφ´id±ðìñÛ]j:~“}..1hñ,¦ÚybÀ0|û{üø‰¡ø—ÄšGÄ/éz/…4ïë:ÿŠí|aáxæÑü{­x»ÃÞÕ4¥Õü7o.¯kâ cÀ~.²°zOpÍ¡^Í$ÛªÌàÙkñëÂw×v–_>^^êC¥¯Œd¸¸½{sÂ~·û,QX»Ü-Æ¿ãÏiP!ÿ‚ˆè?5oÙSÇ~"ý¶"Ó­?gï…š‡…¾0ø“[ðî»ñ#N×¼-­|6ñ ‰|'â½óáþþ+·Ô¼?â KJÒ}1w[Í ÜLÑÃÊ€©û*|(ø}ðƒà„4ŸÙ¯Â~ðÿ¿@ÿ4Ë—Öücªë^/Ô>&$^.Ô|uâ½wÅ—Þ(ñмY&¥©¬jÞ"¼¸Õf–D‚VŠ+h-¡ú+wŽÿçß¿ø0ÕùU@ïÿÏ¿…ðaªÿòª€9]=¼kÿ ‰öÁá“?ö7…|Ð×ÚŸ”Ïñ'“å°Ó 'Íó(lÚ[,ªÝã¿ù÷ð¯þ 5_þUP»Çóïá_üj¿üª É?‹³~ÿ´×íSáÿx¢tý§þøéÿfM|EøÏðÛ^±Õ¼]s{ñïÁz𥞑mâ?jÚ¹îõ+»Ç¼ðñ¿Ðí´û»„žæÒ)¾jŸðý\Æ®U |^aG2†SS ìꩬmJ8ŒD ¯ Jž¿ï“tã(rJJRНâ¼ñG¸>6ÄpÕHpÆ;„1u†Í–3,<øw ʰ±åÄ9ÓÅF¾w–Ê9}HÇR…wˆ§Ft©Uœ>ùøûIøWöÓüeª|ñGƒ¼]eà/êñ4±?‰l ž½§CËy1ê: ¬—º]íµÌW:V³h³iš¤ä±¹™c¯nOŸeYô1u2¼TqPÁbê`± Bpä¯MFNʤbçNq’•:±½:‘»„™ó¼{áŸxg‰Épœi“TÉëñK†Ïò¸Îµ B­—âjU¤¹å‡©V4qt*Ò,^ ³†+ S–5éAÎ7÷=Þ;ÿŸ ÿàÃUÿåU{ÁïÿÏ¿…ðaªÿòª€9? ·qâ?& Ÿø«5¿7̾ÔÇï¼È|À›tÆÌ}63mcÎTPY»Çóïá_üj¿üª /ã  6þÀ“ý¡ªôŸù…Qæ»w?2ü3ûH~Å¿~+øGöªÑ|Mà|MøGðöƒEñ…Ìž>ÓÛÁÿ´¿|4Õ>3Ç«h—ž‚Ö ŸTÒþjv?o´þÕ¼°hî41=­ÅÁ?)ã~ÌiJ¾2…JpÁæ9…FéÕƒ¥…ÊçBÚ•#()CÙöÃUÓol®­/m ¸ŠXrm*ÍíåY¦:ÀP̲êÞß ‰öžÎ§,éÊôªÎXÎEÂtêÓœ' ÅIJ.èüç83ˆ¼>â\Ë„¸¯ýžåO õ¼4kÐÅSäÆa(c°µ¨b°µ*á±41LM ô«P«RœáQZWM/NÝã¿ù÷ð¯þ 5_þUW |°nñßüûøWÿ¯ÿ*¨–ð;x×þï ýž ´Øšw”f¾ÔÖRŸei‘WLu¼Øg8$PS»Çóïá_üj¿üª ›~xßâ~•ðÿ¶Z?ÂxuÍ6Mš§ü&PÙ›¸¾ÅnVµ:Á·gqˆÍ!L…g, ­Õ:-'*ü²jî>ÎNϵÓiú˜J¥dÚewi{X«®öi5Ÿ{Ÿ%üÕõ¿þÕ¥Óî|K㿊~9]_Åþ#ø{ã]Lé—Ú†müMe¤ißð‡x‹Qð-„ºç€|w³Âšu¾…y}¢ÙÝêOqu$š…êÜKÙV凣z‘Œ#hóÆœŸ4¹[¼¢¥+Njó÷’•–öG-)Uj–§)NW“Œª+¥}ÔœUãîèÚ»óLûOVñŸÄ__ðZçÂè´ ñ„w÷ð—Ã|n®Æ‡®F–b1¢[ˆÃ¤’Jf26Á ]Œ_Ž”Uá[ßáä”[îîûzk}Ñ× Õ”­:<ŠÍó{HËð]ßêÏί~ÉŸ²'Åo†þø7ð¿Ä×4ÿ€ºV±¢ø«Pð¿ˆôW›Ä’ø¿_ðóˬøºòm=3Ä÷Pø&“©a>¡¦Ý·ö•¨¹‘ÆÃ‘±éÚÇüëíñÆ´ÝjçÂ:î£ñ3À¿4ÍI>µð¯†,ø[ÿ‚o¾'X2ë“|ð¶­û?Gá2²éÛ]§‰~+ü$Ò|[­Û<ësâ_‹Ÿt¹4”½—I"€?mcñ'ˆæßåx^Î_.I¡“Ëñ=«ì–Ý‚ÜDûlÙ!bdl4l@p   †¹â¶É_BÀ "€üÊH`q§uVÔAæ€9‹Ý_ÄçÆ>vðœk2øÅk#^„‰ï¼$eÉö³Ê+ µŒžnr¡@:í¯Пþ0ÿòº€í¯Пþ0ÿòº€>2ÿ‚„Zø[Ç?±ÏÇo‡_¾!Ú~Î ~'ø.÷៎þ*ËâM%_JðÇž? ëz5¯ö–“4 wâÍ/S»ðÄ\2Þ#jÆk471Æ@£þÉl¾ýš>ø{À*±øíà]áφô?ü\³ñV‡yo㟠é)§è:´wZŒº\Û4Ë{kkVûöŒ'HîѨÐßÛ^,ÿ¡>/ü(aÿåuÛ^,ÿ¡>/ü(aÿåurÚ~¯âqã:øR6™ô aþÞ„•'ñ'”âOìòÍÜù]£g—Émüu?Û^,ÿ¡>/ü(aÿåuÛ^,ÿ¡>/ü(aÿåu~G|gý¿güEÐþ7ü@ñý¿Á¯‰0ý¤iž*:_Œ¼à/ øŸ@×üeoªYjZ瀵àÓüf’¾˜²Újwzv¯.›sg6¢a`ÌÊ1ßÃ|—pµ\DòÊØ¯gŠÁàpØŠê{HN®UlÊ•iSiJ¤Wè¿ìkðÃÁÿ>kq|½¸ñ÷ÂOˆÞ9×>&øJîoYø‡MÒßÄúu޽c ë1é¡îôë¯i–±:Ω-¾±©j‘:+îøW*Ë2¬¾²É±“Æå˜üm|Ë 7Yb)Óx•^4+/ŠœëÓ©YßUV­Dõ?›»þfÄЋq•X¦›M;èÖýŸ< màoþן¿j gâç…¡ÒüYðò÷á­·„¼1à‰‰u¬Úèþ ðþ½âÝWÄ·ºå…¦¯á­?L»Òb°ðN—áÝ+W›\Ôum^ æƒK‚Ǫtë<<(*5/óóIÃM’¬ÚnIûÍÚÉ-ÙÏ´UyÖuáiG“•)÷M7vÒjÏd“»lú‡]øÑðÓÅ:÷ÃûM ÄË{qgãïîPéZå°ŠÖ= \…å/y¦AbYâPŠæF/•RÉ:©®iÓ”cÕ»nöë}N˜b(Ô—,*)Iݤ¯{-ÞÖÓÔü¢Öàœ^*Õü3¨xVÏöˆð'„| eâ k^øàÿ|k´ø)¨C¢ÙüW°ÕßWӵߊ>!ñ„ÿµ#ø—§_éžøyâMÁz±àMQ}Uš`Ö›¼ÿ°f©om¨ZÃñWà·ŒD~<Ð9Ótÿ ¿…ÿáQ|^Öâ:ßø³á_„ž[|>µŠh5ûkÂÞ¸×õ=bãFÕ®üB—ªÿÁ6­î4ŸÚY.¾!Ia¥hZÏ|Ká^j>ðn‡û;|øAÿ?ÄvWº‡¼Eâÿ‚ºŒÃÁ¾!ý¦áÑtõ×>h¾*Ÿá¯…¼a᛿ˆ_ ¼-ð÷Ç>ø‡}âk«ßêsÁñŸãÅLjü-â‰<Ó$ŠÅ/¼ ®•£¬†âê@Ô?Ù³D°ø#ðGÀ |]ñBO‰ž5Ñlu-KÇ¿nô›ý._üAñf»ªxÃÇž+]$›á£Úë¾.×µFÇGŽòâ"ÊâßM‚V†Ö:ô«ßxY¼cáÛ«ÅåE x®'o³Þñ$÷Þh—fÉ,°JÜC’22ÔÂ{á/ú Åÿ€×ßü@ü'¾ÿ Ì_ø }ÿÈÔòÿí¢øûãwì÷㯆?³ßÆßüø§â˜ll´?Š^3øeqñJÇÁößm‰µmOIðÕæ‘hþ&p¸‡ÃÚ½ÕÄñèz”±j©g=Ŭ;@)þÃß ü/û#~Ê?ÿfÉuÿÜÿ ð£øN¯‡ÞñŸ‡¼-ym¯©ÞÛ_[iž0ñ'޼Hº•ü‰yâ+ÍSÅ:œº§ˆ§ÕuH¾Çmy …¨ÕŸðžøKþƒ1à5÷ÿ#Pÿ ï„¿è3þ_ò5rº¼,ž0ñ4í«Ä"›Fð²Fßg½ùžüHdû6FÑ*‘ƒ»‚H8ê¿á=ð—ýbÿÀkïþF þß Ðf/ü¾ÿäjüéÿ‚’~Î:¿í­ðÓá‚þ|RøSðë_ø[ûBüøýmâ‰_ üUñ“Qø/ãâ…¤h0è^+ðUΊºþ± Zhþ'½û]Ô×^¼Ô¬,…•ÜñÞÄúgã¿­ªêí”×ëm½–ÒÇR‚Ò[±‹™- š;‰a·y·´1Kq<‘ÆUiX` ?ðžøKþƒ1à5÷ÿ#Pÿ ï„¿è3þ_ò5ržñ·…à#óux—Îñ^·<¸¼;¢’Hv7ǰN¨æ€:¿øO|%ÿA˜¿ðûÿ‘¨ÇžeeþÙˆngì×ÝÆ3ÿÔ=S]Æš~w?¼ÿ£Ó~è:¦…à_Ú…|9¿g=gà?Ä#‚5«ˆ&ÔÎë\–ßÃÚŽ¾ø"×ÁZŽžéuoý®ãÄÒK4’Ohߎa¼)©¡RŽ =–bò Ù&:ØYIN¦3«˜ãð±–!¬=ln-HZqUšÄë.hËûï:úl`¸—1ÂãøƒÃxæsÈüKÁøÃ¾Ó8£N¥<6EüC„á^ΫRË!S3ÃdOŸÖÏpØ…*5>§•ÆŠ…xþ”~Æÿô_Ù3Έ>ÂÚoø->"ø§ÅŸ>ßá¤Ðµ?økÅ­i¬jº‹E³µÐîa¶ñtþ$Ö,$Ò4ÊÞ×Z[´ø£µŽ¾÷…x~§ à+å‹,ncñX¬´£ 50¸|\£ZxY*\´e⥈«MÒ¥F…eISJ ¿æ/|PÂø½Äùo«´ø{;— å9Gû ~'†Î3LVÁa³ŠSÇJ¶>J¹5<¯ˆŽ3ޝV¶âg‰œëÉ/­¿á=ð—ýbÿÀkïþF¯¦? øO|%ÿA˜¿ðûÿ‘¨–ðG¼-màÿ Á6¯Ë‰¦¤‹ö{ÓµÖÖ0ÊH¶ •9ŒƒÉ §þß Ðf/ü¾ÿäjó‚×þáƒQ½ÑRét ,2^ÜØ­Â¯Ø-¶YÜH«ºŽ ;>Ïî×u÷ÿÁ>!ø7àÚGGý¿~%|NøÁ}à=WáŠþ x@ðÆ©áˆú–¡àÿÁ¦|V³ºøoá+?jÚ&“c£xÅ<öý_Æ:­¼º£jú®£©Ý¦¼öÙZ“ÛRT¦¤ªF¤\” ¹¥û·Ï.tÝãÌÒŠÒÊɯ´øéªË9ÎIÂP’MM¸¥Î¹‹Jҵܷݻ»£ï^è3k_L»Ò%—þ˜ «aqfòy_ðøƒ&E·rÞ^ý™,6îÛžH®&šÝ?™Ùtú§ó=k|_ÞþúZC ñz?ûéhß÷£ÿ¾–€ ñz?ûéhß÷£ÿ¾–€ ñz?ûéh“¿xÿá6ðÏΘ>ñ†~eÁÿOðqýq@fø¿½ýô´o‹ûÑÿßK@ø¿½ýô´o‹ûÑÿßK@ø¿½ýô´o‹ûÑÿßK@ŽšñÿÂk⯙1ý‰á|ËŒùþ'ÏôÍuÛâþô÷Òо/ïGÿ}-âþô÷Òо/ïGÿ}-âþô÷Òо/ïGÿ}-qþxöøŸ,Ÿò8k¸Ë/O2ǵvâþô÷Òо/ïGÿ}-âþô÷Òо/ïGÿ}-âþô÷Òо/ïGÿ}-r^xÿá ð®]3ýƒ¦ueÏüzG޾ÔÖï‹ûÑÿßK@+|$ø)ð“ļ'¬k|©j—º6-åý߆tYî®ç{+w’{™å±ygžWfyf•ÚI–f&·Ž'£ExÅ+$ªÔI.‰%$’] e†ÃÎNR¡IÉ»¶éŶÞí»]¶õmŸü ð….ÿmï?üei üJÑm´/xçÁÖ¾Ó~êß ¾xvßÅþðþ™ðëÇÚUÁÏxçÁ¿b[›«í"[âWŽtŸxxx“RŽÓKŸJ¶AÝV½u…£R5«BMÆr©YU¨ù[çŒWRz^ЃŒ¹UåvrS£Aâ*Ó•*3Vr\´é8As[–_ºRŒúë9&¯d¬}×âƒ? |=ªø_ øÂ: ö£â³¥¾£§ø_@Kˆá¸ðö¿ >œÑL#¸† ³Ü$¶³<—0Íä>|ëשZ•ªÔÓåIÎ7[;JM]tgd(Q§.jt©ÂZ®hÂ*V{«¥}zë©øÕ¬üWý±þê^(׬¼Aá¿–¾ øíû_xBïÁ_~ ü4ð&‹­|1ý›þëôK›=áÂ+/Œ|_©ÛÇ¥i×Ù_Ýê gåÙ¢»ÓuLO[ÕÿmŸŠŸ5'ökøk«x7á”^5ñ^±âˆ’_ø~ïGðõßÇ-kà烖_ |'¸°ox"Þ/ˆÿüE¨ß]ë:OÃÍ'ÄŸðß{ø@>ðíeûNëß>kZŒÖþ /ô7â/Œ|ðáåÿÀ?øC¼cûq~Ù¿¡Õ¯ÇUµ±¶ÔôëëSk¦x‚ÂîÛÄzF™¤iZµž•f÷‡ü Þ ÿ¡CÃø!Òÿù€øA¼ÿB‡†?ðC¥ÿò-ršƒ<Þ1ñ<-á_41hÞx¢mM1ÆòÍâA+¢m¨Òãó@/å¦âvŒuðƒx+þ… à‡KÿäZ?áðWý ÿÁ—ÿÈ´ø¹ÿ³ý¢u_Øóà€üWðWâׄ~ üfñw‹ï|5ð¿Âwÿ³ç~(øoâï‹dƒN[+âG‰üYi_>øSím¯üKñäo®Ã¡ºÛxnæMxéúN¬úõàmÁ~)ðOƒ¼LtjÇÄ~ðþºu_h6¿Ø™Õô›M@êÛí÷ö=ïÚ>Ó¦}´ ¿±IÚ@›}u?ðƒx+þ… à‡KÿäZ?áðWý ÿÁ—ÿÈ´ÉxOÁž˜x“Îð¯‡%ò¼[­Ã™¢i¯åÅì‰7[‘¦NÄ\*äà Ð[ÿ7‚¿èPðÇþt¿þE þoСáüéü‹@’µ¿í+uð#þ Uÿßýž­ü²ñÃÿ ë㿉úcÞhºle¥xë]±ÓácenJZYÛ]E´ HáÆŠª ë[ªí$½•d•Ý(¹?97{·Õ˜J‚”œ½­uvÝ£VI+öWÑy~Ì¿ïþ9|wñÏÃx³â¯´CâoÚCøS£Í«|EŸŒ4ïÙ¿â–‘ð§Æ~$ºñäÞ/}]F=OP´¿¾ð°ð~–Ö:v¿¢ ;Äܺ~´°vÖ^ÎŒjFžO–Œª¿gÊëAÎ1äjöþ÷3»Né&Ž:?¼«8Ê­x®jŠšöµ/%N\²—73[ê×*i5ï7¡÷æ­ðŽËÃ> ðÒx×âF¬×~/ŽÄG¬øÛ[Ôa·hzÜ­so ÕÌÑÇt>ZNÌHä+ ç<¬çWNŒuNð¦¡-<×GÕks¶T%Íí+Ië¤êÊQ×¼^ö}>gæÏÂOø)³©ü&Óþ-üeø]ñ/H°ñW†þ |JðÖƒðú󯶷š_ÁÿƒúlZßňz¾·ñzßáï‡üg¤øgKÖü#ýœŸ ¯|U¨x’ÿV¹³ÐôÍB[| }Ô¿oŸƒ·‡l|1¢~о:ñ‹õ´ðï†<3áÍKA‡TÕõih~Îvöþwˆ<_¢ézrMã/ë:¹¸Õµ x ðgmµ¨uÍ^Ã⃼O©xú/ÚËCý”¼5®kYxºyáM[Å~!ÓŽ¥m¢Úê~,ÒîaÕn×Cºðå¶³¨bþÍðRýCãƒîõ¿ü3ñ¦¥â]OSøO¢øÂ_ $ø‘ð³â¿Æk øÕeð³O´ºøð×áF¡âk¯Øê÷ÿüm·§é^ Öõ=~ÓPÒ¢öŸ ÁJfOüAð7ÃM÷ãÔþ'øwðÞÓÂÑL’[[^Kñv„ú÷äžiõt6W'øyñJçâ…Ôq_§€þüNÔæ¶ŽçÃ"ÊðôÛþ¸?èbñ‡þ—ßã@Åï„a_xzíï.â¹ â Ã2o¼&Ç!ù‘$ó‰•ÄŒ‘Ï–(§ÿ„.ú¼aÿ…%÷øÐÿ\ô1xÃÿ Kïñ ŽnïÚ[À?°¯ìïâŽ~2Õ<[­^_GðGÃÿ Ïãi´ |IñcÜ[øWCÖ|S~­¥x?Ã~eµÞ«â¯êäiþðΗ«ê¯Ýŵ½ÐÿÁ?>=éß·'ìaû:þÖ÷z·‡gøÝðßHñ†¯áŸx÷Rñ“áH÷$ðͶ³=µ”÷ÍáýrÊÿI¸’âÎÚu¹´–9 ŽDebÿÂý ^0ÿÂ’ûühÿ„.ú¼aÿ…%÷øÐ-§øFñ‰¡þÞñXhþq"ø‚ðLþtþ#ÊÉ ùËR’B¾h©ÿ„.ú¼aÿ…%÷øÐÿ\ô1xÃÿ Kïñ Ìßø*gíIñsöýžîÿh…ž Ó>.i> ´ñˆ~"øwÆ?~%èzä^Эl®Ï†!ð?¥fmõ:ÛQ„Új6ÄÛ_ÛîTÁ{nLQlž"c‘h ÿ„.ú¼aÿ…%÷øÐÿ\ô1xÃÿ Kïñ Sž‚aâ,ëÞ+Êñ^µî¼Ax›ÄrEûÉ1÷¥låÜüÌy4ÕÿÂý ^0ÿÂ’ûühÿ„.ú¼aÿ…%÷øÐægí…ûTüOýš¿iÏÙ࿃¼9á/‰Þý¦~&xCáÎ¡á¦øÙâý/öˆÓ4ý_T×GÄ/‹øiá KÃ? ¾ xWOÓ\ ¯øgSø_¤\è~”#Dé¢iϨ}šÊÖæx/´ôCa©[±·Ô-n¡ýÝdlTÑ¿dÿ„žñ^µã­ á÷Â]'Æ^#ñ¯‹õÏÙ|-ÑáÖõ?XëWþ%³×®/Æ f•·‰5]WÄ1\BÑ×µMOYÁÔµÛ™À-i¿²ïà "çY¼Òüð¶ÆëÄ:Ìþ!ÖçƒáŽ’¯©kw>0Òþ!O©OE”\ËãÍHñ£ùKmâ­>Û^)ý¦†å€2õÿÙ àÇŠt«-Ä_ ~júF™á½Áúmß­ÊÓü)á[»ûï øvÅ¢Ô"šÓHðõÖ­«É£YA,péÉ­kvö«¶µªÃxÓÛ~ξ²×l|Qeá…–~$Ó5o kÚv»ið§ÃöÚ­†µàÏëü!ªÙ^At“Zßø[À> ×|áë˜$Ñü/¬jZ&ž`ÓîæÀ=Sû'Å¿ô6Yÿá8?ùq@½î—â‘ã/£x¢ÐÊÞñcG/ü#ê"ßxHH†?íc¸È^6JyDmq!*Ôdø·þ†Ë?ü'ÿ.(þÉñoý –øNþ\P[ß øƒRµšËQñ•}gsÅqkwáXnmæŠDhäŽXfÕž7GFdee «x&€9ßü-¶øaàÿ|=øqÿŸ| àý&×Bð§ƒü)à{=ÞÑlcYiZ6“cªEiaak ¼¤h: ’HYý“âßú,ÿðœü¸ û'Å¿ô6Yÿá8?ùq@®Ÿ¥ø øÇÄê¾(´YWFð©’SáðDŠÓø“ËQö°Øc+!-½¼Ï0 «³,Õdø·þ†Ë?ü'ÿ.(þÉñoý –øNþ\P…|mý’~~Ò‰áh¿h?‡?¾5Eà‹ëÝGÂ|KøU¢øº/Þja£é‘j÷÷è4½0j–Œ¯g© >Ä_[Ü X{}¾ƒâ[Kx---ÿ¡²Ïÿ ÁÿËŠå¼¥ø¥üᗇűDÚšc‰¼>²´iöXö¡“ûU7•oØ¥±’4Ôÿdø·þ†Ë?ü'ÿ.(ç…^3ø¦ü>ð­ž‹ð¨ëzlZ.š-u1â­.×íqýŠÜ,¦ÞD2@\ÞS’ɬKkx‹IÊ¿+kUìæìû]oêbêUM¥AÉ&í/i;7¼ñ¯„ß| ÿ »ãWƒþ|/Šãã/ŠüC¨ø¯âÔmã]sP“X×~é¾ øy¬Çc¬x….t‡À¶—žе? xFòÛKÐ/õu¹“I‡RÖ5K»®š”?uJU1»ŠQ§û§¢Ÿ4ÕÒ×ß÷š”µiodŒ![÷•# ÔmʼZ¸Ú-§--u5£kK¶} «ø¿â>©â‡ñk¿ [B·‡ÆÏoqÿ >™xnn—C×-Fƒa‘$’S+ª" ä°’p¥Þ¹åuîòJ:=ÝÞš}ìè„êÊV•.Egï9ÆZôVÞ§¸ÿlø›þ„ù?ðy¦ÿ…djÛ>&ÿ¡>Oüi¿á@öω¿èO“ÿšoøPý³âoúäÿÁæ›þlø›þ„ù?ðy¦ÿ…Û>&ÿ¡>Oüi¿á@µö­â3ã/¹ð£¬«áÿ*Cýµ§“"=÷„Œ¼.ÕòŠÆ ·/æå~ãPSý³âoúäÿÁæ›þlø›þ„ù?ðy¦ÿ…Û>&ÿ¡>Oüi¿á@öω¿èO“ÿšoøPý³âoúäÿÁæ›þlø›þ„ù?ðy¦ÿ…rš~­â!ã¸ð¤+hÞEý³§-Vyn\®×óK?ʼ§—–ûâ€:¿íŸП'þ4ßð ûgÄßô'ÉÿƒÍ7ü(þÙñ7ý òàóMÿ ?¶|MÿB|Ÿø<Ó€íŸП'þ4ßð ûgÄßô'ÉÿƒÍ7ü(“ðž­â%#òü)$»¼Y­»ÿÄçOO.F’ñ|ÃçÙÇο+gŽôÖlø›þ„ù?ðy¦ÿ…Û>&ÿ¡>Oüi¿á@öω¿èO“ÿšoøPý³âoúäÿÁæ›þlø›þ„ù?ðy¦ÿ…Û>&ÿ¡>Oüi¿á@¯õo§ƒ¼0‘xQæt=8$ÃZÓÐH¢Ö<>Ç]˸sµ¹4Õlø›þ„ù?ðy¦ÿ…|Ùð«ã%§‡>ø[H—Àõ'´Ñ´äûv•áxntëœXÛ6ÒâMVš ˜åò”H¸`0keA´¥ípêé;J­¤¯Ñ®WgÝ\ÂXˆÆN.wfÕãNñ~i¹+¯3áÏ€>ðÃOÛãÇ=;Ä^9ñ_‹.ðÏŠ¼#gñ.Ú?ˆú­­ª|3Ó<:<1à›í?Â~¾Ö4[¸Î¹q¨ËenO}niá©Ò½ÅrrÊU}ÏÝÆQ“¦ù.Üܯ5)I'ªÕéÇJQ…yÕå¬ÛçrJŸ½i´ãιíî¥h´££Öçè¯ñnÓÄúÿ€-bð7Ä}(Ùø¾;çŸZðÔVJ©¡ëpù|é8G™Ô£-R´*sK^¶qZ.®çl+)Ë•S¬·w;GæÔž¯¥÷=¿þ(è_ñ_þ dÿãÕ‘°Âeý þ+ÿÁ,Ÿüz€øL¡ÿ¡Åø%“ÿPÿ ”?ô/ø¯ÿ²ñê?á2‡þ…ÿÿà–Oþ=@ü&Pÿпâ¿üÉÿǨ˜½ñl-ãMý…â€"Ð"IJ4+I5tÕ9´ÓÕ4Òi§¾æ2ÄP‹q•ji§fœÒi­ÓMÞéî~üø{á?‡ÿ¶¿ˆ~5ÇñkÃø?¢ÃûHÝiú^«ã¿xÄ><ñOíñÁ^:Ôç’ãÞѼC‚ü;{áMGSÑôÿˆ¾$ñ³ ÝkVðü6úF•q{èVU¥†/«Ö•I{Ú£U(ª0’Z;®v¥fᬛRv8©ÊŒq©íé¨~õ«Õ¦ÜY)=½ë+iÌÛÙ++ßôw^øÉð§Äú÷ÃÛ_ü@ð¦©siã(ï®aµÕíYá³A×b’å÷:I4HížEÏ\×:©Çš¥*°Òæœ%w¶²IjwB½’å…XNNîÑ’oM[²}¬öøN¼ÿCg‡ðqaÿÇë#Pÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇèÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇèÿ„ëÁô6xwÿü~€9kïxA¼eáÉ×ņ?ø²9%µ‰$šûÂM ;ùûUäXf(¤å„rÎÖÀSÿ ׂÿèlðïþ,?øýðx/þ†ÏÿàâÃÿÐÿ ׂÿèlðïþ,?øýðx/þ†ÏÿàâÃÿÐÿ ׂÿèlðïþ,?øýðx/þ†ÏÿàâÃÿÐ)§øÓ ãÎÞ'ÐVt ¤RZÄG#Ã7‰ ªŽgÚí–2àWÌ]ØÜ(«ÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇèÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇèÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇè“ðŸŒü#ñ'â}/7źÜÑùšµ’yÉ$%%MÓѾ WV‚h¬ÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇèÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇèÿ„ëÁô6xwÿü~€øN¼ÿCg‡ðqaÿÇè•ð?¢Æ? ?‚å‹ÅÑêÍrÑ 6ÐdP·@ê2Õtÿ‰‡âWçååß^novÞºÔååï~Wðߟgªå´¯é«? üEáÛ#\øgû(É£è_´5¿ôÙ à?†üÒÂq¡¿†?l¯|_ð¯Æ­ö‚·¸¹²ŽçD¿øcg©øHþ(E©x+Ä^ƒÇÑh—ºÆ¿dšŸ­†SÄ'ìT"¬§nG|4©MÓ+uSµãM©Æ\·Ñ;yòöî_ïy½„l¦­]T‡<ªyrõâ×2Wo_ÝÿÛék ŠZÆïã«u“ì웚1áÿ>+T:«r0)ëŠñM[¥¾Gªü¿ìþ” >_öJ>_öJ>_öJ>_öJ>_öJäïöÿÂmមÿ„sÆéÿ?þëúÐYòÿ³úPòÿ³úPòÿ³úPòÿ³úPòÿ³úPòÿ³úP!¦íÿ„×Åwþ@žôÿžþ'Íuÿ/û?¥/û?¥/û?¥/û?¥/û?¥/û?¥qþÛ·ÄùÇüŽö3Žžd?¥v/û?¥/û?¥/û?¥/û?¥/û?¥/û?¥r^ÛÿW…sŒÿ`éqžmc4Öü¿ìþ”ùë«ü1øG§~Ëú÷ÄÍz_øSÒ>^ë·?üK–úG‡ïmtE¹\Õ‡ˆ.í´i#K¢›×R¸ŠÉÝÑ$–ÝtqŽjtÔ¥(ÝEA%w¬š6Ýwës–µ .5*8Â2´¤ç.{»´¾óó÷Iø¹ðŠoƒÿðJ‰Z·ÄŸ‚vŸ´¿ˆüáŽúUľ‚ßÅ7wŸH/¼&±1ý÷TYåýó@Gü+ÿÿÐËóŸÿPÿ ÿÁ¿ô²üçÿãÔ¿ðoý,¿9ÿøõð¯üÿ@ /Îþ=@ü+ÿÿÐËóŸÿPÿ ÿÁ¿ô²üçÿãÔÊéþð“øÃÄÖí¡Ù˜aÑü-$I™°<þ$óX~÷9qyÿpPUÿ ÿÁ¿ô²üçÿãÔ¿ðoý,¿9ÿøõð¯üÿ@ /Îþ=@ü+ÿÿÐËóŸÿPÿ ÿÁ¿ô²üçÿãÔ¿ðoý,¿9ÿøõržð7„§#ót+7ò|W­A|ï–(ä‡b­è¹8ïë@_ü+ÿÿÐËóŸÿPÿ ÿÁ¿ô²üçÿãÔ¿ðoý,¿9ÿøõð¯üÿ@ /Îþ=@ü+ÿÿÐËóŸÿPÿ ÿÁ¿ô²üçÿãÔËø#ÀÞºð†n'ЬäšmN’Y Ÿ.ímf?½êÇ$ûšê?á_ø7þ€_œÿüz€>/»ð?޵ŸÙ¯T˜ëšw|)/é®n¾ëž ðV¥£xŽÆßFŽæojâŸ3K»´¹Š!¯«æ —’<•ÕF¥%*ºqÒöЬÓOnee£…÷{œÕiÕq›öŠQ´Ÿ#§šß•ÞV•¶»ß­†µ|<ßaωv?¾ëŸþ,¿Â-_á·ƒ øGðeüSð¯Äu ëwðãÁŸØ,·W^mF?xóTÐLXtßÞë-Ìö@/td½®&›uTéûE9{z¼µhûòIòÝ{ÝÝÛ©Èã/g‡Ÿ¸ã>Gì ÜeRÏÜ6¶~ô¶Ñ7{Ÿ©zÇ„þ$iºÿÃùuÿŠkðKãáµ¶o hÖKovÚ¸ËvÏjÑÉ&È–XÄE¶1—qåy³)FУÉ+¯{ÚJ]uVzjwÂc+ʯN[uøu¿oÄô!í¹¿yì¹lïÈäå{iñ+Zûõ=×wŽ?矅ÿï½R²5 Þ8ÿž~ÿ¾õJ7xãþyø_þûÕ(ÝãùçáûïT wŽ?矅ÿï½R€ Þ8ÿž~ÿ¾õJ寛Æð™xst~óÿáñg•‡Ô¼¯/íÞó‹änß»Éòöñƒ&îvÐS»ÇóÏÂÿ÷Þ©@ïÏ? ÿßz¥¼qÿ<ü/ÿ}ê”nñÇüóð¿ý÷ªP»ÇóÏÂÿ÷Þ©@ïÏ? ÿßz¥rš{xËþíÃ~wö7…|ÝÏ©y[<ÿy^^>mÙó<ÍÜ}ͽZ€:½Þ8ÿž~ÿ¾õJ7xãþyø_þûÕ(ÝãùçáûïT wŽ?矅ÿï½R€ Þ8ÿž~ÿ¾õJ7xãþyø_þûÕ(“ð›xË#òcðÙÿг[ó|ÇÔ¿×yù›6ÿË>›w|Ýs@fïÏ? ÿßz¥¼qÿ<ü/ÿ}ê”nñÇüóð¿ý÷ªP»ÇóÏÂÿ÷Þ©@ïÏ? ÿßz¥¼qÿ<ü/ÿ}ê”Êø¼gÿw†<ˆü6aþÄÓ¼£+ê^nϳG·ÌÙòïÇÞÛÆzq@VïÏ? ÿßz¥|_/TçÏ ºÊÎý;¦|c¨ø?ÁðÎÿ±Wƒuÿkòüðæ­ðBø ¬Þø·á•Ž·ñ[SÓuÏ øà~—áïAà[iú†¯eáíIšo ¶‹u®xunF¿1[‹Ë“ÚŸï±SRJ«iVýÝYFš´•W(ºŽ2W“iJéJÊ=ǯ³Ã§r^š¦Üé'7¤ ¢í̯d®­xß™õ?KõŸøÿW×ü±ð²ïÃðAãî!¸—Å:]ïÚ®WCÖãK4Š;XJ³¤’Kæ³íU…°¯:p§·þÒW^ﲜ:êï)5çþlïŒê9ZTœ¾÷1ðì‡ÂwTðÿŠÕ"þ×ÓÉ‘^ûÂFGßÑ|¢‘§æo7#„jê?·fçz¯–Iá–€:¯íÏÐqÿƒ;ü(þÜñ'ý ×ø9ӿ€íÏÐqÿƒ;ü(þÜñ'ý ×ø9ӿ€íÏÐqÿƒ;ü(þÜñ'ý ×ø9ӿ€9O k Eñ—á9åßâ½mäÿ‰¾ž¾\$[¢9”Àù‡ œŠêÿ·lMxʤ'ãR>ä\¥£W·3øŽ&©ÊT§]Jš§ËB¯+Pš•×56îÒZ¦ºªº¿Æ/ ø«Ä´°Ðþ ÚIeãïå“Wøyâí2‰4=nS\iAe¹g<»t̲(‘•HF¯2te¹9QjéZéT–¿Ý„å&»»Yug¡ ð©.Tª^ÍÞTªEiÞRŠKÉ^íísÜá4ÒÿçÃÅ?øFø«ÿ•‰°Âi¥ÿχŠðñWÿ*(ÿ„ÓKÿŸÿáâ¯þTPÿ ¦—ÿ>)ÿÂ7Å_ü¨ þM/þ|)ÿÂ7Å_ü¨ þM/þ|)ÿÂ7Å_ü¨ OÂ~.Ób#ÝeâFó|Y­Ì¾W„üM6Õy!ÂÉåéOåÊ1óÄûeCêšë?á4ÒÿçÃÅ?øFø«ÿ•Âi¥ÿχŠðñWÿ*(ÿ„ÓKÿŸÿáâ¯þTPÿ ¦—ÿ>)ÿÂ7Å_ü¨ þM/þ|ñ4ñ¶Ñ‚Rh´§ŠEÏGÙª±ÐSÿ ¦—ÿ>)ÿÂ7Å_ü¨ Ò4ÄŸ²¦¥£xƒIÓµ­'QøUªÛß麥œ¶W¶ÿð‹»˜.­®H§ˆ²©1Ȭ¤‘WMµ84ÚjQÕo¹pši4ã+¦®žtÏÊoÀÚ6ƒÿôÿ‚p~Ö0Úhú×¾ ü)ýм¤xÆ~ðgü­øãg?g ø¶[ý?ÄþÔµÅ:|?fÕ<-ã/ëÞñ¨Û’îûOºº±“ÓRoŒÃݨU©‰“”e(Í:p­(Ù©$ÖéÆJK]Žöl5{ÞtáE%$¥¥*iÝ5u-­$Ô—}OÛ/Çjÿ J¢)>=ƒ%UA?ñOx„ò@Éæ¼“Ñ=*€ ( € ä¯ÿäwðÏý‹ž0ÿÒÿP[@P@roüŽÞ+ÿ°'„ôŠ(¯ € ( €8ï}ßÿØã¯èÈ(± € ( €9ÿÈ“á_ûéŸúKuÔÿÙPK!¨9ŸImdocProps/core.xml ¢( Œ’QKÃ0…ßÿCÉ{›´u2BÛÊ|q X™ø’»®Ø$%‰ný÷¦íV+óÁÇäœûåœK²ÕQ6Á[k•£8"(ŵ¨U•£×r.Q`S‚5ZAŽ:°hU\_e¼¥\x6ºãj°')Ky›£½s-ÅØò=Hf#ïP^Üi#™óGSá–ñVN¹ÅÌ1ÜÃv"¢Rð Ù~šfŽ¡ ÊYG1þñ:0Òþ90(3§¬]×úN§¸s¶à£8¹¶žŒ‡Ã!:¤C Ÿ?Æo›§—¡jX«~WP‘ N¹æ´) TÚtÁ–6Ã3©_cÃ¬ÛøïjwÝ…ûÒáÙC•ñGÇ*ge›Þ?”kT$$&!‰Ã$-IL)M’÷>À¯ù>ìx!O1þC¼)É‚’%M3âPdøâƒßÿÿPK!fhǵdocProps/app.xml ¢( œ“QoÓ0Çß‘ø&﫳ªB¨r<¡ŽiLT´χsi¬%vdßBçç’(k:Häé|÷ÏùwößêæTW¢Å­wYr½HÎøÜºc–öwW \•w˜%ÆäF¿}£¶Á7ÈbÜÂÅ,)‰šµ”Ñ”XC\pÙq¥ð¡âe8J_Öà­7Ï5:’Ë4}/ñDèr̯š—†ÉØqÝÒÿ6ͽéùâã¾kX«MSYÄSêk‚¾ ñÆ:ò±ŸN+%ç2Åœ;4ÏÁR§S%çKµ3PᆷÐT•<'Ô=B|[°!jÕÒºEC>ˆhò.ñ"ö`YÒB°àˆ{Ù¸⪉ô7žb‰HQIŒÉ!œkç±]éÕ ààRØ7A¸p‰¸·TaüRl!ЈWsâaäqv=Ÿ¸ãYiù‚;Öù ½Ëÿ"øa©Ð;±ì´£pPã»ý`% • vÑ\{1ì«ñ6¾nÀuúàìà{ê„/ÄW϶„AÉI >[÷ÍÞßátÑ—Iµ+!`ÎÞ˜ê焺ç;UßdS‚;b>i~/ô}_¡¾^.Rþ7N9%ÏïMÿÿÿPK-!îÙð8–Ü[Content_Types].xmlPK-!}ÌTž Ý ›_rels/.relsPK-!8ÙÒ$æ‡xl/_rels/workbook.xml.relsPK-!þ=ýÔëxl/workbook.xmlPK-!XE W\² xl/worksheets/sheet4.xmlPK-!q1¢h§xl/worksheets/sheet2.xmlPK-!/±y‹Exl/worksheets/sheet3.xmlPK-!no`2xl/sharedStrings.xmlPK-!4Ž2§~ šxl/styles.xmlPK-!È{Ö©üŠlxl/theme/theme1.xmlPK-!צ–±{š ™$xl/worksheets/sheet1.xmlPK-!׫ˆAðBJ(xl/calcChain.xmlPK- !véÉJôaôah)docProps/thumbnail.jpegPK-!¨9ŸIm‘‹docProps/core.xmlPK-!fhǵŽdocProps/app.xmlPKÕ‘gdata/inst/xls/ExampleExcelFile.xls0000644000176000001440000013500012163372013017046 0ustar ripleyusersÐÏࡱá>þÿ Nþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÿÿÿ[  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMþÿÿÿþÿÿÿþÿÿÿQRSTUVWXYZþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿRÿÿÿÿÿÿÿÿ ÀFÍ<¸}ÄœÊOWorkbookÿÿÿÿÿÿÿÿ/—SummaryInformation(ÿÿÿÿP DocumentSummaryInformation8ÿÿÿÿÿÿÿÿÿÿÿÿ\ KÌá°Áâ\pGregory Warnes B°a=œ¯¼=ìÿìÿ¬]¼C8ô@"·Ú1ÈÿVerdana1Èÿ¼Verdana1ÈÿVerdana1Èÿ¼Verdana1ÈÿVerdana1Èÿ¼Verdana1 ÿVerdana1È ¼Verdana1È9Verdana"$"#,##0_);\("$"#,##0\)!"$"#,##0_);[Red]\("$"#,##0\)""$"#,##0.00_);\("$"#,##0.00\)'""$"#,##0.00_);[Red]\("$"#,##0.00\)7*2_("$"* #,##0_);_("$"* \(#,##0\);_("$"* "-"_);_(@_).))_(* #,##0_);_(* \(#,##0\);_(* "-"_);_(@_)?,:_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)6+1_(* #,##0.00_);_(* \(#,##0.00\);_(* "-"??_);_(@_)àõÿ À àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ àõÿ ôÀ à À à+õÿ øÀ à)õÿ øÀ à,õÿ øÀ à*õÿ øÀ à õÿ øÀ à"À à @ @ À à"x@ @  à"À à À à  À à À à À à À “€ÿ“€ÿ“€ÿ“€ÿ“€ÿ“€ÿ’â8ÿÿÿÝ·Ôüóò„«êdq:F¥€€ÀÀÀ€€€cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½cªþÝ-2ÿõŒNâWgÿþ§F†SW¢½ÌÿÌÿÿÌÿÌÿÿ™™Ìÿÿ™ÌÌ™ÿÿÌ™3fÿ3ÌÌ™ÌÿÌÿ™ÿfff™–––3f3™f333™3™3f33™333\ÿÿÿ`…- Sheet First…|1 Sheet Second…$6RSheet with a very long name!…WvSheet with initial textŒÁÁgýÖÖüæ5A 7B 7C 7F 7G 7NA 7D 7E  7NA 7NA 7FirstRow 7 SecondRow 7ThirdRow 7 FourthRow 7Factor 7Red 7Black 7Green 7A 7B 7C 7A 7NA 7HThis line contains text that would need to be skipped to get to the data 7This line too! 7ÿ- ‹˜ïÎÖ µîæ Å®C¯ C¯ h`® UKž˜”Fž˜x`® $G¯ ä‹˜€`ÿ¿–R¡`€dˆm®x`ÿ¿3T¡ˆm® d€d‚aÿ¿`€d¸À“0ŒŒ:&.‹˜ 9¯ -HÀ8Udxaÿ¿¡z”:&‚aÿ¿‚aÿ¿ca›—z”º%"È`ÿ¿’§nHØ`ÿ¿×^Laÿ¿=eÔ#€%ø`ÿ¿TÔ#ÑHáx¡TÔ#aÿ¿/ …Tdÿ¿…z (aÿ¿×^L…z Tdÿ¿Ð…eÑH…z Haÿ¿/ ……z Tdÿ¿ßHxaÿ¿ý’…Tdÿ¿…z cדTdÿ¿¨aÿ¿ÀÔ]Tdÿ¿&à÷&¸aÿ¿“üª; Ðøcÿ¿sg‚¸bÿ¿#rz”5&Ôèª; €%(bÿ¿ˆ“z”:&Ô#=}”(bÿ¿¡z”5&€%ê³Ö#ˆbÿ¿Â9AXbÿ¿÷9A†2' bÿ¿Vdÿ¿ÿ4ê³€%xbÿ¿€x€VVdÿ¿¨ˆØà‰,˜bÿ¿×^Lÿ¿s{ ¨bÿ¿×^Ls{ Dcÿ¿/ …Tdÿ¿s{ Èbÿ¿Kiz”øbÿ¿ˆiz”€%øbÿ¿ý’…Dcÿ¿s{ !÷ä–€§i"cÿ¿2Jz”>cÿ¿XJz”€%€³ê³8cÿ¿ !T€§i"ºì‰Tdÿ¿| Xcÿ¿D™Ê¸cÿ¿Tdÿ¿¢’z”Tdÿ¿¸cÿ¿xcÿ¿f™Ê¸cÿ¿Tdÿ¿=}”„ˆ›d˜cÿ¿7T}> &>øcÿ¿¥T}>Tdÿ¿Øcÿ¿ÀÔ]Tdÿ¿ˆÂ`…ÖTdÿ¿èÿ¿ÿÿÿÿÿÿÿÿÖ4«; KÌ w-1  dü©ñÒMbP?_*+‚€%Áƒ„M  com.apple.print.PageFormat.FormattingPrinter com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.FormattingPrinter Random_Color_Laser___Random_Technologies_iMac com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket PMPPDPaperCodeName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDPaperCodeName Letter com.apple.print.ticket.stateFlag 0 PMPPDTranslationStringPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDTranslationStringPaperName Letter com.apple.print.ticket.stateFlag 0 PMTiogaPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMTiogaPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0 0 25600 19600 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -400 -400 26000.000000000004 20000 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0 0 768 588 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -12 -12 780 600 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName Letter com.apple.print.ticket.stateFlag 0 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz ` `dLþpþpe‘N g(üHHØ(dÿh ¡"düÿüÿà?à?U %e i o %ý ý ý ~ ð?ð?(ˆ¸aý¼ LÿÀð?(ÿ¼ LþÀ@(þ¼ LÿÿÀ@(ÿ @(ÿ@(ÿ"@(ÿ;@(ÿ@(ÿ0@(ÿP@(ÿ@(ÿ9@(ÿ@_@(ÿ@(ÿB@(ÿk@(ÿ@(ÿ€H@(ÿpu@(ÿ׉Œ*zt]]]]>¶@ÈÈ@ ï7 KÌ ÆOÖQ  dü©ñÒMbP?_*+‚€%Áƒ„M  com.apple.print.PageFormat.FormattingPrinter com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.FormattingPrinter Random_Color_Laser___Random_Technologies_iMac com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket PMPPDPaperCodeName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDPaperCodeName Letter com.apple.print.ticket.stateFlag 0 PMPPDTranslationStringPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDTranslationStringPaperName Letter com.apple.print.ticket.stateFlag 0 PMTiogaPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMTiogaPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0 0 25600 19600 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -400 -400 26000.000000000004 20000 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0 0 768 588 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -12 -12 780 600 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName Letter com.apple.print.ticket.stateFlag 0 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz ` `dLþpþpe‘N g(üHHØ(dÿh ¡"düÿüÿà?à?U %e i ý ý ý ý ý ý  ~ ð?ý  ý  ý ý ý  ½@ð?ý  ý ý ¾ý  ½@@ð?ý ý ý  ½@@@ð?ý ×ødFTNF>¶@ÈÈ@   ï7 KÌ  €pïu  dü©ñÒMbP?_*+‚€%Áƒ„M  com.apple.print.PageFormat.FormattingPrinter com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.FormattingPrinter Random_Color_Laser___Random_Technologies_iMac com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket PMPPDPaperCodeName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDPaperCodeName Letter com.apple.print.ticket.stateFlag 0 PMPPDTranslationStringPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDTranslationStringPaperName Letter com.apple.print.ticket.stateFlag 0 PMTiogaPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMTiogaPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0 0 25600 19600 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -400 -400 26000.000000000004 20000 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0 0 768 588 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -12 -12 780 600 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName Letter com.apple.print.ticket.stateFlag 0 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz ` `dLþpþpe‘N g(üHHØ(dÿh ¡"düÿüÿà?à?U  %i ;?% ½ð?ÀLá@[°[°¥?ìôØÈ?XÊ? 1ð„ýDÀAÿÿ ÿý ½@`~á@[°[°µ?¢_ç Ò?(ÿ¼ LÿÀA#$nerÿÿ ÿ ð¿Bmý ½@ ¯á@DDDDDDÀ?‘ùë°ÐÖ?(ÿ"î Tíê¿ þ ð¿Aý ½@`áá@[°[°Å?ìôØÈ?XÚ?(ÿÜÔ•‰¨æ? ÿ DÀ½@àâ@ÇqÇqË?µã¾LtÝ?(ÿéwùÔ4 à?(ÿ¼  LÿÿÀý ½@€Dâ@DDDDDDÐ?ý ?:FƒqÐ?(ÿý ½@vâ@¥Oú¤OúÒ?…ã’Éælá?(ÿÈÚ-°?(ÿý ½ @À§â@[°[°Õ?¢_ç â?(ÿý ½"@`Ùâ@gfffffØ?±·¢Ö/Âã?(ÿ( ÿý ½ $@à ã@ ÇqÇqÛ? ð¢‰ÌÓä?(ÿ (ÿý ×W´y’{j‹ctUt>¶@ÈÈ@ ï7 KÌ ¡”Í–  dü©ñÒMbP?_*+‚€%Áƒ„M  com.apple.print.PageFormat.FormattingPrinter com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.FormattingPrinter Random_Color_Laser___Random_Technologies_iMac com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMHorizontalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMHorizontalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMOrientation com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMOrientation 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalRes com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalRes 2400 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMVerticalScaling com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMVerticalScaling 1 com.apple.print.ticket.stateFlag 0 com.apple.print.subTicket.paper_info_ticket PMPPDPaperCodeName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDPaperCodeName Letter com.apple.print.ticket.stateFlag 0 PMPPDTranslationStringPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMPPDTranslationStringPaperName Letter com.apple.print.ticket.stateFlag 0 PMTiogaPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray PMTiogaPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPageRect 0 0 25600 19600 com.apple.print.ticket.stateFlag 0 com.apple.print.PageFormat.PMAdjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PageFormat.PMAdjustedPaperRect -400 -400 26000.000000000004 20000 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMCustomPaper com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMPaperName na-letter com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPageRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPageRect 0 0 768 588 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.PMUnadjustedPaperRect com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.PMUnadjustedPaperRect -12 -12 780 600 com.apple.print.ticket.stateFlag 0 com.apple.print.PaperInfo.ppd.PMPaperName com.apple.print.ticket.creator com.apple.jobticket com.apple.print.ticket.itemArray com.apple.print.PaperInfo.ppd.PMPaperName Letter com.apple.print.ticket.stateFlag 0 com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PaperInfoTicket com.apple.print.ticket.APIVersion 00.20 com.apple.print.ticket.type com.apple.print.PageFormatTicket Mz ` `dLþpþpe‘N g(üHHØ(dÿh ¡"düÿüÿà?à?U ý ý ý ý ý ý ý ý  ~ ð?ý  ý  ý ý ý  ½@ð?ý  ý ý ý  ½@@ð?ý ý ý  ½@@@ð?ý ×xFTNF>¶@ÈÈ@ ï· þÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ ÕÍÕœ.“—+,ù®0, PXx €ˆ˜   'University of Rochester  Sheet First Sheet SecondSheet with a very long name!Sheet with initial text  Worksheetsþÿÿÿÿÿ ÀFMicrosoft Excel Sheetþÿÿÿ8FIBExcel.Sheet.8þÿ à…ŸòùOh«‘+'³Ù0ðHPh€ ¤ °¼Ä'Gregory WarnesGregory WarnesMicrosoft Macintosh Excel@UÓ×ΛÊ@¯ë}ÄœÊG"þÿÿÿPICTJ€ÿ ÿþHHJ€ €€ÿÿšÿJ€HHÚ8J€J€Qo{øsœgZõw½sœgZõw½k[sœöw½sœco{öw½o|k{õw½c_öw½sœgZöw½sœcg:õw½gZúw½ÿ\sœþw½kZJt_þw½gZ{Þöÿc>2õÿo|w¾öÿo|FSR•öÿw½o|öÿZ÷c9w½õÿg[öÿw¾N•V×cöÿg[ùÿ` sœw½w½Jt>2oœN•>oœw½gZ{ÞöÿJtB3c9öÿo|w¾öÿo|N•Jtöÿw½o|öÿR¶o|ôÿg[öÿw¾R¶gZZøöÿg[ùÿb sœw½w½Z÷5ÐgZB2Jtw½w½gZ{Þöÿ_ÿN•öÿo|w¾öÿsœ>N•öÿw½o|öÿw½>Jtõÿg[öÿ{Þ>B3{Þöÿg[ùÿ4sœþw½k[>_þw½gZ{Þèÿo|w¾èÿw½o|çÿg[çÿg[ùÿ+k[øk{gZçw½o{sœèw½sœo|çw½o{çw½o{úw½ÿJsœþÿsJtýÿsœçÿ{ÞõÿJRBNsõÿ{Þöÿ=ïJRw½õÿw½õÿ=ïJR{Þöÿw½ùÿFsœýÿJtýÿsœçÿ{Þõÿ5­sœ!õÿ{Þöÿ%)JR{Þõÿw½õÿ%)JRõÿw½ùÿHsœþÿs½V×wÞþÿsœçÿ{ÞõÿZÖF1cõÿ{ÞöÿNsJRw½õÿw½õÿVµôÿw½ùÿ+g:øc:g:çw½sœsœèw½sœsœçw½o{çw½o{úw½ÿBsœþ{Þg:Z÷ý{Þsœÿ{Þúÿ{Þñÿ{Þæÿ{Þ÷ÿÞòÿw½óÿÞöÿw½ùÿtsœþÿw½R¶o|þÿsœÿ5­cg9o{sœg9Nso{5­Nsw½kZw½w½{Þ÷ÿ{Þõÿc!ôÿ{Þ÷ÿx¥~Öy­x„öÿw½÷ÿy­}ïy­½x!½÷ÿw½ùÿrsœþÿsV×ýÿsœÿ=ïo{VµF1VµNsR”{Þ=ïR”R”VµNsNsB÷ÿ{Þôÿ)Jôÿ{Þ÷ÿyJyJy­yŒy~÷÷ÿw½÷ÿy­yŒy)~Ry~1÷ÿw½ùÿxsœþÿ^øZøwÞþÿsœÿg9ÿkZkZo{ZÖkZo{g9cg9ZÖw½g9^÷÷ÿ{ÞõÿkZBo{õÿ{Þ÷ÿ~µ{~µ~s{~µ÷ÿw½÷ÿ~ÖÞ~s~”½~s÷ÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿysœþÿo|Jtw½þÿsœ{ÞR”c{Þo{ÿo{{Þo{{Þo{ÿo{ZÖR”R”ÿo{ÿþ{Þýÿ{Þõÿc9ÎkZõÿ{Þöÿsœ1Œôÿw½÷ÿ~R~”~RÞyJÞ÷ÿw½ùÿxsœþÿsB2{ÞþÿsœÿBR”F19ÎNskZNsZÖVµZÖNsR”NsBB^÷g9VµJRF1Vµýÿ{Þôÿ=ïg9õÿ{Þõÿ)Jôÿw½÷ÿy­y)yk~”yk~”÷ÿw½ùÿ~sœþÿ{ÞV×k[þÿsœ{ÞsœNsNssœNs{ÞNscR”sœF1^÷NsR”NsVµsœVµ5­R”cýÿ{ÞõÿZÖ!kZõÿ{Þöÿw½ço{õÿw½÷ÿy­~÷xçyŒykyk÷ÿw½ùÿzsœþÿk{_ýÿsœÿVµkZsœVµ{ÞVµsœZÖw½{ÞsœZÖkZsœ{Þo{Vµ{Þo{sœüÿ{Þõÿg9VµkZõÿ{Þöÿw½VµkZõÿw½÷ÿ9ÿÿ÷ÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ.sœþÿ{Þ>{Þþÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ.sœþÿN•B2oœþÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ*sœýÿk[ýÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{ÞÿksœþÿZ÷Zøw½þÿsœsœJRcVµsœkZ{Þw½sœVµVµR”ÿo{ÿþ{Þùÿ{Þõÿ^÷9Îg9õÿ{ÞöÿkZBZÖõÿw½õÿ9Îsœõÿw½ùÿjsœþÿo{FSw½þÿsœÿR”ÿF1NsVµNsg9NsNsF1B^÷g9VµJRF1Vµùÿ{Þôÿ!g9õÿ{ÞõÿVµNsõÿw½õÿF1kZõÿw½ùÿjsœþÿ{ÞVÖk{þÿsœÿR”ÿýVµ {ÞR”NsVµNsVµsœVµ5­R”cùÿ{ÞõÿZÖ=ïNsõÿ{ÞöÿkZÆcõÿw½õÿ1ŒZÖõÿw½ùÿdsœþÿo|cýÿsœÿsœÿýsœ ÿ^÷kZsœ{Þo{Vµ{Þo{sœøÿ{Þõÿg9R”ôÿ{Þöÿo{Vµcõÿw½õÿVµcõÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{ÞÿisœþÿVÖ_w½þÿsœÿJRkZsœý{ÞsœVµ^÷o{o{Vµc{Þsœþ{Þûÿ{Þôÿ5­o{õÿ{Þöÿg9BVµõÿw½õÿF1JRõÿw½ùÿpsœþÿB2V×g:þÿsœÿ=ïkZR”R”VµVµR”o{NsR”^÷R”F1ZÖR”NsVµNsBûÿ{Þõÿ9Î!Vµõÿ{ÞõÿF1F1õÿw½õÿZÖJRõÿw½ùÿrsœþÿk[Zøw¾þÿsœÿg9ÿZÖg9^÷VµkZÿ^÷g9w½g9w½cc^÷w½g9^÷ûÿ{Þôÿ^÷sœõÿ{ÞöÿcBg9õÿw½öÿ{Þ=ïNsõÿw½ùÿ+g:øc:g:çw½sœsœèw½sœsœçw½o{çw½o{úw½ÿ.sœþ{Þk[Z÷k{þ{Þsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ.sœþÿs½Z×c:þÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ*sœýÿR¶ýÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ,sœþÿoœsœýÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ.sœþÿZ×N•o|þÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ.sœþÿZø5ðs½þÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ.sœþÿJtk[^øþÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ,sœþÿs½_ýÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ.sœþÿR¶V¶k[þÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ.sœþÿcV¶Z÷þÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ.sœþÿo|^ø{Þþÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+g:øc:g:çw½sœsœèw½sœsœçw½o{çw½o{úw½ÿ2 sœ{Þ{ÞkZsœw½V×w½{Þ{Þsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿR¶gZV¶g:R¶ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc9gZJt{ßFtÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿcc9sZ÷sÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ0sœÿÿV¶gZw¾B3þÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ0sœÿÿc9gZÿJtþÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿ_cÿFS{ßÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc:g:wÞcsœÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ2 sœÿÿV¶gZsœR¶c9ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc9gZ{ÞR¶{Þÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿcc9g:Z÷sœÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ2 sœÿÿV¶gZsR¶gZÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc9gZ{ÞB3oœÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿ_c{ÞkZV×ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc:g:sœZø{ßÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+k[øk{k[ç{Þsœw½è{Þw½sœç{Þsœç{Þsœú{Þÿ2 sœÿÿV¶gZÿJtk[ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc9gZZ×Ft_ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿcc9ÿsœs½ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ+g:øc:g:çw½sœsœèw½sœsœçw½o{çw½o{úw½ÿ2 sœ{Þ{ÞkZsœsœZ÷o{{Þ{Þsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿR¶gZgZ_w¾ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿ2 sœÿÿc9gZ{ÞV×c9ÿÿsœçÿ{Þæÿ{Þçÿw½çÿw½ùÿÿÿ62CompObjÿÿÿÿÿÿÿÿÿÿÿÿTÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿgdata/inst/unitTests/0000755000176000001440000000000012024144455014342 5ustar ripleyusersgdata/inst/unitTests/runit.write.fwf.R0000644000176000001440000001171511227511757017554 0ustar ripleyusers### runit.write.fwf.R ###------------------------------------------------------------------------ ### What: Unit tests for write.fwf ### $Id: runit.write.fwf.R 1300 2008-08-05 11:47:18Z ggorjan $ ### Time-stamp: <2008-08-05 11:58:50 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- write.fwf --- test.write.fwf <- function() { ## 'x' must be a data.frame or matrix checkException(write.fwf(1:10)) checkException(write.fwf(list(1:10))) ## only single value is allowed in 'na' checkException(write.fwf(data.frame(1:10, letters[1:10]), na=c("", " "))) ## Example dataset num <- round(c(733070.345678, 1214213.78765456, 553823.798765678, 1085022.8876545678, 571063.88765456, 606718.3876545678, 1053686.6, 971024.187656, 631193.398765456, 879431.1), digits=3) testData <- data.frame(num1=c(1:10, NA), num2=c(NA, seq(from=1, to=5.5, by=0.5)), num3=c(NA, num), int1=c(as.integer(1:4), NA, as.integer(4:9)), fac1=factor(c(NA, letters[1:9], "hjh")), fac2=factor(c(letters[6:15], NA)), cha1=c(letters[17:26], NA), cha2=c(NA, "longer", letters[25:17]), stringsAsFactors=FALSE) levels(testData$fac1) <- c(levels(testData$fac1), "unusedLevel") testData$Date <- as.Date("1900-1-1") testData$Date[2] <- NA testData$POSIXt <- as.POSIXct(strptime("1900-1-1 01:01:01", format="%Y-%m-%d %H:%M:%S")) testData$POSIXt[5] <- NA ## --- output --- ## is tested with regular tests ## --- formatInfo --- ## default output formatInfoT <- data.frame(colname=c("num1", "num2"), nlevels=c(0, 0), position=c(1, 4), width=c(2, 3), digits=c(0, 1), exp=c(0, 0), stringsAsFactors=FALSE) formatInfo <- write.fwf(testData[, c("num1", "num2")], formatInfo=TRUE) checkEquals(formatInfo, formatInfoT) ## scientific notation dd <- options("digits"); options(digits = 7) testData2 <- data.frame(a=123, b=pi, c=1e8, d=1e222) formatInfo <- write.fwf(x=testData2, formatInfo=TRUE) checkEquals(formatInfo$width, c(3, 8, 5, 6)) checkEquals(formatInfo$digits, c(0, 6, 0, 0)) checkEquals(formatInfo$exp, c(0, 0, 2, 3)) options(dd) ## reset old options ## 'na' can either decrease or increase the width ## --> values of int1 have width 1 and using na="" should not increase ## the width formatInfo <- write.fwf(testData[, "int1", drop=FALSE], formatInfo=TRUE, na="") checkEquals(formatInfo$width, 1) ## --> values of int1 have width 1 and using na="1234" should increase ## the width to 4 formatInfo <- write.fwf(testData[, "int1", drop=FALSE], formatInfo=TRUE, na="1234") checkEquals(formatInfo$width, 4) ## rowCol formatInfoTR <- data.frame(colname=c("row", "num1", "num2"), nlevels=c(11, 0, 0), position=c(1, 4, 7), width=c(2, 2, 3), digits=c(0, 0, 1), exp=c(0, 0, 0), stringsAsFactors=FALSE) formatInfoR <- write.fwf(testData[, c("num1", "num2")], formatInfo=TRUE, rownames=TRUE, rowCol="row") checkEquals(formatInfoR, formatInfoTR) ## quoteInfo alone does not have any effect formatInfoI <- write.fwf(testData[, c("num1", "num2")], formatInfo=TRUE, quoteInfo=TRUE) checkEquals(formatInfoI, formatInfoT) ## quote formatInfoQ <- write.fwf(testData[, c("num1", "num2")], formatInfo=TRUE, quote=TRUE) formatInfoTQ <- formatInfoT formatInfoTQ$position <- c(1, 6) formatInfoTQ$width <- c(4, 5) checkEquals(formatInfoQ, formatInfoTQ) ## quote without quoteInfo formatInfoQI <- write.fwf(testData[, c("num1", "num2")], formatInfo=TRUE, quote=TRUE, quoteInfo=FALSE) formatInfoTQI <- formatInfoT formatInfoTQI$position <- c(2, 6) checkEquals(formatInfoQI, formatInfoTQI) ## width ## --> default width for num1 is 2 formatInfo <- write.fwf(testData[, "num1", drop=FALSE], width=10, formatInfo=TRUE) checkEquals(formatInfo$width, 10) ## too small value in width (this also tests recycling) ## --> proper width for num1 is 2, while for num2 it is 3 checkException(write.fwf(testData[, c("num1", "num2")], width=2)) checkException(write.fwf(testData[, c("num1", "num2")], width=c(2, 1))) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.write.fwf.R ends here gdata/inst/unitTests/runit.wideByFactor.R0000644000176000001440000000351111227511757020216 0ustar ripleyusers### runit.wideByFactor.R ###------------------------------------------------------------------------ ### What: Reshape by factor levels - unit tests ### $Id$ ### Time-stamp: <2008-12-30 11:58:50 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- wideByFactor --- test.wideByFactor <- function() { n <- 10 f <- 2 tmp <- data.frame(y1=(1:n)/2, y2=(n:1)*2, f1=factor(rep(letters[1:f], n/2)), f2=factor(c(rep(c("M"), n/2), rep(c("F"), n/2))), c1=1:n, c2=2*(1:n)) ## 'x' must be a data.frame checkException(wideByFactor(x=1:10)) checkException(wideByFactor(x=matrix(1:10))) ## 'factor' can be only of length one checkException(wideByFactor(x=tmp, factor=c("f1", "f2"))) ## column defined in 'factor' must be a factor checkException(wideByFactor(x=tmp, factor="c1")) tmp2 <- wideByFactor(x=tmp, factor="f1", common=c("c1", "c2"), sort=FALSE) checkEquals(tmp2[c("c1", "c2")], tmp[c("c1", "c2")]) checkEquals(names(tmp2), c("c1", "c2", "f1", "y1.a", "y2.a", "f2.a", "y1.b", "y2.b", "f2.b")) checkEquals(tmp2$y1.a, c(0.5, NA, 1.5, NA, 2.5, NA, 3.5, NA, 4.5, NA)) checkEquals(tmp2$f2.a, factor(c("M", NA, "M", NA, "M", NA, "F", NA, "F", NA))) tmp2 <- wideByFactor(x=tmp, factor="f1", common=c("c1", "c2"), sort=TRUE, keepFactor=FALSE) checkEquals(tmp2$f2.a, factor(c("M", "M", "M", "F", "F", NA, NA, NA, NA, NA))) checkEquals(names(tmp2), c("c1", "c2", "y1.a", "y2.a", "f2.a", "y1.b", "y2.b", "f2.b")) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.wideByFactor.R ends here gdata/inst/unitTests/runit.unknown.R0000644000176000001440000005121610521462302017323 0ustar ripleyusers### runit.unknown.R ###------------------------------------------------------------------------ ### What: Tests for Change given unknown value to NA and vice versa methods ### $Id: runit.unknown.R 993 2006-10-30 17:10:08Z ggorjan $ ### Time-stamp: <2006-10-30 17:46:21 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### {{{ --- Vectors --- intUnk <- 9999 xInt <- as.integer(c(NA, 1:2, NA, 5, 6, 7, 8, 9)) xIntUnk <- as.integer(c(intUnk, 1:2, intUnk, 5, 6, 7, 8, 9)) xIntUnkTest <- xIntUnk %in% intUnk numUnk <- 0 xNum <- c(9999, NA, 1.5, NA, 5, 6, 7, 8, 9) xNumUnk <- c(9999, 0, 1.5, 0, 5, 6, 7, 8, 9) xNumUnkTest <- xNumUnk %in% numUnk chaUnk <- "notAvail" chaUnk1 <- "-" xCha <- c("A", "B", NA, "C", NA, "-", "7", "8", "9") xChaUnk <- c("A", "B", chaUnk, "C", chaUnk, "-", "7", "8", "9") xChaUnk1 <- c("A", "B", chaUnk1, "C", chaUnk1, "-", "7", "8", "9") xChaUnkTest <- xChaUnk %in% chaUnk xChaUnk1Test <- xChaUnk %in% chaUnk1 facUnk <- "notAvail" facUnk1 <- "NA" xFac <- factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", NA)) xFacUnk <- factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", facUnk)) xFacUnk1 <- factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", facUnk1)) xFacUnkTest <- c(0, 0, 0, 0, 0, 0, 0, 0, 1) xFacUnkTest <- as.logical(xFacUnkTest) xFacUnk1Test <- c(0, 0, 0, 1, 1, 0, 0, 0, 1) xFacUnk1Test <- as.logical(xFacUnk1Test) xFac1 <- factor(c("A", "0", 0, NA, NA, intUnk, numUnk, "-", NA)) facLev <- "A" xFacUnkLev <- factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", "A")) xFacUnkLevTest <- c(1, 0, 0, 0, 0, 0, 0, 0, 1) xFacUnkLevTest <- as.logical(xFacUnkLevTest) dateUnk <- as.Date("2006-08-14") tmp <- as.Date("2006-08-15") xDate <- c(tmp, NA) xDateUnk <- c(tmp, dateUnk) xDateTest <- c(FALSE, TRUE) xDate1Unk <- c(tmp, dateUnk, NA) xDate1Test <- c(FALSE, TRUE, FALSE) POSIXltUnk <- strptime("2006-08-14", format="%Y-%m-%d") tmp <- strptime("2006-08-15", format="%Y-%m-%d") xPOSIXlt <- c(tmp, NA) xPOSIXltUnk <- c(tmp, POSIXltUnk) xPOSIXltTest <- c(FALSE, TRUE) xPOSIXlt1Unk <- c(tmp, POSIXltUnk, NA) xPOSIXlt1Test <- c(FALSE, TRUE, FALSE) POSIXctUnk <- as.POSIXct(strptime("2006-08-14 01:01:01", format="%Y-%m-%d %H:%M:%S")) tmp <- as.POSIXct(strptime("2006-08-15 01:01:01", format="%Y-%m-%d %H:%M:%S")) xPOSIXct <- c(tmp, NA) xPOSIXctUnk <- c(tmp, POSIXctUnk) xPOSIXctTest <- xPOSIXltTest xPOSIXct1Unk <- c(tmp, POSIXctUnk, NA) xPOSIXct1Test <- xPOSIXlt1Test ### }}} ### {{{ --- Lists and data.frames --- xList <- list(xInt, xCha, xNum, xFac) xListN <- list(int=xInt, cha=xCha, num=xNum, fac=xFac) xListUnk <- list(xIntUnk, xChaUnk, xNumUnk, xFacUnk) xListUnkTest <- list(xIntUnkTest, xChaUnkTest, xNumUnkTest, xFacUnkTest) xListNUnk <- list(int=xIntUnk, cha=xChaUnk, num=xNumUnk, fac=xFacUnk) xListNUnkTest <- list(int=xIntUnkTest, cha=xChaUnkTest, num=xNumUnkTest, fac=xFacUnkTest) xDF <- as.data.frame(xListN) xDF$cha <- as.character(xDF$cha) xDFUnk <- as.data.frame(xListNUnk) xDFUnk$cha <- as.character(xDFUnk$cha) xDFUnkTest <- as.data.frame(xListNUnkTest) unkC <- c(intUnk, chaUnk, numUnk, facUnk) unkL <- list(intUnk, chaUnk, numUnk, facUnk) unkLN <- list(num=numUnk, cha=chaUnk, fac=facUnk, int=intUnk) ## mixed as it is named unkLMN <- list(cha=chaUnk, int=intUnk, num=c(intUnk, numUnk), fac=c(chaUnk1, facUnk)) xListMNUnkF <- list(int=as.integer(c(9999, 1, 2, 9999, 5, 6, 7, 8, 9)), cha=c("A", "B", "notAvail", "C", "notAvail", "-", "7", "8", "9"), num=c(9999, 0, 1.5, 0, 5, 6, 7, 8, 9), fac=factor(c("A", "0", "0", "NA", "NA", 9999, "0", "-", "notAvail"))) xListMNUnkFTest <- list(int=c(1, 0, 0, 1, 0, 0, 0, 0, 0), cha=c(0, 0, 1, 0, 1, 0, 0, 0, 0), num=c(1, 1, 0, 1, 0, 0, 0, 0, 0), fac=c(0, 0, 0, 0, 0, 0, 0, 1, 1)) xListMNUnkFTest <- lapply(xListMNUnkFTest, as.logical) xListMNF <- list(int=as.integer(c(NA, 1, 2, NA, 5, 6, 7, 8, 9)), cha=c("A", "B", NA, "C", NA, "-", "7", "8", "9"), num=c(NA, NA, 1.5, NA, 5, 6, 7, 8, 9), fac=factor(c("A", "0", "0", "NA", "NA", "9999", "0", NA, NA))) xDFMUnkF <- as.data.frame(xListMNUnkF) xDFMUnkF$cha <- as.character(xDFMUnkF$cha) xDFMUnkFTest <- as.data.frame(xListMNUnkFTest) xDFMF <- as.data.frame(xListMNF) xDFMF$cha <- as.character(xDFMF$cha) unk1 <- 555555 xListUnk1 <- list(as.integer(c(unk1, 1, 2, unk1, 5, 6, 7, 8, 9)), c("A", "B", unk1, "C", unk1, "-", "7", "8", "9"), c(9999, unk1, 1.5, unk1, 5, 6, 7, 8, 9), factor(c("A", "0", "0", "NA", "NA", "9999", "0", "-", unk1))) xListUnk1Test <- lapply(xListUnk1, function(x) x %in% unk1) xListNUnk1 <- xListUnk1 names(xListNUnk1) <- c("int", "cha", "num", "fac") xDFUnk1 <- as.data.frame(xListNUnk1) xDFUnk1$cha <- as.character(xDFUnk1$cha) xDFUnk1Test <- as.data.frame(xListUnk1Test) names(xDFUnk1Test) <- names(xListNUnk1) unkC2 <- c(0, "notAvail") xListUnk2 <- list(as.integer(c(unkC2[1], 1, 2, unkC2[1], 5, 6, 7, 8, 9)), c("A", "B", unkC2[2], "C", unkC2[2], "-", "7", "8", "9"), c(9999, as.numeric(unkC2[1]), 1.5, as.numeric(unkC2[1]), 5, 6, 7, 8, 9), factor(c("A", "0", "0", "NA", "NA", "9999", "0", "-", unkC2[2]))) xListNUnk2 <- xListUnk2 names(xListNUnk2) <- c("int", "cha", "num", "fac") xDFUnk2 <- as.data.frame(xListNUnk2) xDFUnk2$cha <- as.character(xDFUnk2$cha) xListUnk2Test <- xListUnk2 xListUnk2Test[[1]] <- xListUnk2Test[[1]] %in% unkC2[1] xListUnk2Test[[2]] <- xListUnk2Test[[2]] %in% unkC2[2] xListUnk2Test[[3]] <- xListUnk2Test[[3]] %in% unkC2[1] xListUnk2Test[[4]] <- xListUnk2Test[[4]] %in% unkC2[2] xListNUnk2Test <- xListUnk2Test names(xListNUnk2Test) <- names(xListNUnk2) xDFUnk2Test <- as.data.frame(xListNUnk2Test) unkL2 <- as.list(unkC2) unkLN2 <- unkL2[c(2, 1)] names(unkLN2) <- c("cha", "int") xListUnk2a <- list(as.integer(c(NA, 1, 2, NA, 5, 6, 7, 8, 9)), c("A", "B", unkLN2[[2]], "C", unkLN2[[2]], "-", "7", "8", "9"), c(9999, NA, 1.5, NA, 5, 6, 7, 8, 9), factor(c("A", "0", "0", "NA", "NA", "9999", "0", "-", unkLN2[[2]]))) xListUnk2aTest <- xListUnk2a xListUnk2aTest[[1]] <- xListUnk2aTest[[1]] %in% unkLN2[1] xListUnk2aTest[[2]] <- xListUnk2aTest[[2]] %in% unkLN2[2] xListUnk2aTest[[3]] <- xListUnk2aTest[[3]] %in% unkLN2[1] xListUnk2aTest[[4]] <- xListUnk2aTest[[4]] %in% unkLN2[2] xList2a <- list(xListUnk2a[[1]], c("A", "B", NA, "C", NA, "-", "7", "8", "9"), xListUnk2a[[3]], factor(c("A", NA, NA, "NA", "NA", 9999, NA, "-", NA))) ### }}} ### {{{ --- Matrix --- matUnk <- 9999 mat <- matrix(1:25, nrow=5, ncol=5) mat[1, 2] <- NA; mat[1, 4] <- NA; mat[2, 2] <- NA; mat[3, 2] <- NA; mat[3, 5] <- NA; mat[5, 4] <- NA; matUnk1 <- mat matUnk1[1, 2] <- matUnk; matUnk1[1, 4] <- matUnk; matUnk1[2, 2] <- matUnk; matUnk1[3, 2] <- matUnk; matUnk1[3, 5] <- matUnk; matUnk1[5, 4] <- matUnk; matUnkTest <- matUnk1Test <- is.na(mat) matUnk2Test <- matUnkTest | mat == 1 ### }}} ### {{{ --- Use of unknown=list(.default=, ...) or similarly named vector --- D1 <- "notAvail" unkLND1 <- list(.default=D1) xListUnkD1 <- list(as.integer(c(NA, 1:2, NA, 5, 6, 7, 8, 9)), c("A", "B", D1, "C", D1, "-", "7", "8", "9"), c(9999, NA, 1.5, NA, 5, 6, 7, 8, 9), factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", D1))) xListUnkD1Test <- lapply(xListUnkD1, function(x) x %in% D1) xListD1 <- xList xListNUnkD1 <- xListUnkD1 xListNUnkD1Test <- xListUnkD1Test names(xListNUnkD1) <- names(xListNUnkD1Test) <- names(xListNUnk1) xListND1 <- xListN DSO2 <- c("notAvail", 5678) unkLNDSO2 <- as.list(DSO2) names(unkLNDSO2) <- c(".default", "someOther") xListUnkDSO2 <- list(as.integer(c(NA, 1:2, NA, 5, 6, 7, 8, 9)), c("A", "B", DSO2[1], "C", DSO2[1], "-", "7", "8", "9"), c(9999, NA, 1.5, NA, 5, 6, 7, 8, 9), factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", DSO2[2]))) xListUnkDSO2Test <- lapply(xListUnkDSO2, function(x) x %in% DSO2) unkLND3 <- list(.default="notAvail", num=0, int=9999) xListNUnkD3 <- list(int=as.integer(c(unkLND3[[3]], 1:2, unkLND3[[3]], 5, 6, 7, 8, 9)), cha=c("A", "B", unkLND3[[1]], "C", unkLND3[[1]], "-", "7", "8", "9"), num=c(9999, unkLND3[[2]], 1.5, unkLND3[[2]], 5, 6, 7, 8, 9), fac=factor(c("A", "0", 0, "NA", "NA", intUnk, numUnk, "-", unkLND3[[1]]))) xListNUnkD3Test <- xListNUnkD3 xListNUnkD3Test$int <- xListNUnkD3Test$int %in% unkLND3[[3]] xListNUnkD3Test$cha <- xListNUnkD3Test$cha %in% unkLND3[[1]] xListNUnkD3Test$num <- xListNUnkD3Test$num %in% unkLND3[[2]] xListNUnkD3Test$fac <- xListNUnkD3Test$fac %in% unkLND3[[1]] unkLND2E <- list(.default="notAvail", 9999) ### }}} ### }}} ### {{{ --- isUnknown --- test.isUnknown <- function() { ## --- base methods for vectors --- ## base ... checkIdentical(isUnknown(xIntUnk, unknown=as.integer(intUnk)), xIntUnkTest) checkIdentical(isUnknown(xIntUnk, unknown=intUnk), xIntUnkTest) checkIdentical(isUnknown(xNumUnk, unknown=numUnk), xNumUnkTest) checkIdentical(isUnknown(xNumUnk, unknown=as.integer(numUnk)), xNumUnkTest) checkIdentical(isUnknown(xChaUnk, unknown=chaUnk), xChaUnkTest) checkIdentical(isUnknown(xFacUnk, unknown=facUnk), xFacUnkTest) ## multiple values are allowed for vector methods in vector or list form checkIdentical(isUnknown(xIntUnk, unknown=unkC), xIntUnkTest) checkIdentical(isUnknown(xIntUnk, unknown=unkL), xIntUnkTest) ## NA's in factors checkIdentical(isUnknown(xFacUnk1, unknown=facUnk1), xFacUnk1Test) facNA <- factor(c("0", 1, 2, 3, NA, "NA")) facNATest <- c(FALSE, FALSE, FALSE, FALSE, TRUE, FALSE) checkIdentical(isUnknown(facNA), facNATest) ## Date-time classes checkIdentical(isUnknown(xDateUnk, unknown=dateUnk), xDateTest) checkIdentical(isUnknown(xDate1Unk, unknown=dateUnk), xDate1Test) checkIdentical(isUnknown(xPOSIXltUnk, unknown=POSIXltUnk), xPOSIXltTest) checkIdentical(isUnknown(xPOSIXlt1Unk, unknown=POSIXltUnk), xPOSIXlt1Test) checkIdentical(isUnknown(xPOSIXctUnk, unknown=POSIXctUnk), xPOSIXctTest) checkIdentical(isUnknown(xPOSIXct1Unk, unknown=POSIXctUnk), xPOSIXct1Test) ## --- lists and data.frames --- ## with vector of single unknown values checkIdentical(isUnknown(xListUnk, unknown=unkC), xListUnkTest) checkIdentical(isUnknown(xDFUnk, unknown=unkC), xDFUnkTest) ## with list of single unknown values checkIdentical(isUnknown(xListUnk, unknown=unkL), xListUnkTest) checkIdentical(isUnknown(xDFUnk, unknown=unkL), xDFUnkTest) ## with named list of single unknown values checkIdentical(isUnknown(xListNUnk, unknown=unkLN), xListNUnkTest) checkIdentical(isUnknown(xDFUnk, unknown=unkLN), xDFUnkTest) ## with named list of multiple unknown values - valid here checkIdentical(isUnknown(xListMNUnkF, unknown=unkLMN), xListMNUnkFTest) checkIdentical(isUnknown(xDFMUnkF, unknown=unkLMN), xDFMUnkFTest) ## with single unknown value - recycling checkIdentical(isUnknown(xListUnk1, unknown=unk1), xListUnk1Test) checkIdentical(isUnknown(xDFUnk1, unknown=unk1), xDFUnk1Test) ## with vector of two unknown values - recycling checkIdentical(isUnknown(xListUnk2, unknown=unkC2), xListUnk2Test) checkIdentical(isUnknown(xDFUnk2, unknown=unkC2), xDFUnk2Test) ## with list of two unknown values - recycling checkIdentical(isUnknown(xListUnk2, unknown=unkL2), xListUnk2Test) checkIdentical(isUnknown(xDFUnk2, unknown=unkL2), xDFUnk2Test) ## list(.default=) checkIdentical(isUnknown(x=xListUnkD1, unknown=unkLND1), xListUnkD1Test) ## list(.default=, someOther=) we do not know someOther, but should work ## as x is not named checkIdentical(isUnknown(x=xListUnkDSO2, unknown=unkLNDSO2), xListUnkDSO2Test) ## list(.default=) in named list checkIdentical(isUnknown(x=xListNUnkD1, unknown=unkLND1), xListNUnkD1Test) ## list(.default=, someOther=) OK if someOther is in the named list checkIdentical(isUnknown(x=xListNUnkD3, unknown=unkLND3), xListNUnkD3Test) ## list(.default=, 99) ERROR as we do not know where to apply 99 checkException(isUnknown(x=xListNUnk, unknown=unkLND2E)) ## --- matrix --- checkIdentical(isUnknown(x=mat, unknown=NA), matUnkTest) checkIdentical(isUnknown(x=matUnk1, unknown=matUnk), matUnkTest) checkIdentical(isUnknown(x=matUnk1, unknown=c(1, matUnk)), matUnk2Test) } ### }}} ### {{{ --- unknownToNA --- test.unknownToNA <- function() { ## --- base methods for vectors --- ## base ... checkIdentical(unknownToNA(xIntUnk, as.integer(intUnk)), xInt) checkIdentical(unknownToNA(xIntUnk, intUnk), xInt) ## with numeric checkIdentical(unknownToNA(xNumUnk, numUnk), xNum) checkIdentical(unknownToNA(xNumUnk, as.integer(numUnk)), xNum) checkIdentical(unknownToNA(xChaUnk, chaUnk), xCha) checkIdentical(unknownToNA(xChaUnk, chaUnk), xCha) checkIdentical(unknownToNA(xFacUnk, facUnk), xFac) ## multiple values are allowed for vector methods in vector or list form checkIdentical(unknownToNA(xIntUnk, unknown=unkC), xInt) checkIdentical(unknownToNA(xIntUnk, unknown=unkL), xInt) ## NA's in factors checkIdentical(unknownToNA(xFacUnk1, unknown=facUnk1), xFac1) facNA <- factor(c("0", 1, 2, 3, NA, "NA")) facNATest <- factor(c("0", 1, 2, 3, NA, NA)) checkIdentical(unknownToNA(x=facNA, unknown="NA"), facNATest) ## Date-time classes checkIdentical(unknownToNA(xDateUnk, unknown=dateUnk), xDate) checkIdentical(unknownToNA(xPOSIXltUnk, unknown=POSIXltUnk), xPOSIXlt) checkIdentical(unknownToNA(xPOSIXctUnk, unknown=POSIXctUnk), xPOSIXct) ## --- lists and data.frames --- ## with vector of single unknown values checkIdentical(unknownToNA(xListUnk, unknown=unkC), xList) checkIdentical(unknownToNA(xDFUnk, unknown=unkC), xDF) ## with list of single unknown values checkIdentical(unknownToNA(xListUnk, unknown=unkL), xList) checkIdentical(unknownToNA(xDFUnk, unknown=unkL), xDF) ## with named list of single unknown values checkIdentical(unknownToNA(xListNUnk, unknown=unkLN), xListN) checkIdentical(unknownToNA(xDFUnk, unknown=unkLN), xDF) ## with names list of multiple unknown values - must be an error checkIdentical(unknownToNA(xListMNUnkF, unknown=unkLMN), xListMNF) checkIdentical(unknownToNA(xDFMUnkF, unknown=unkLMN), xDFMF) ## with single unknown value - recycling checkIdentical(unknownToNA(xListUnk1, unknown=unk1), xList) checkIdentical(unknownToNA(xDFUnk1, unknown=unk1), xDF) ## with vector of two unknown values - recycling checkIdentical(unknownToNA(xListUnk2, unknown=unkC2), xList) checkIdentical(unknownToNA(xDFUnk2, unknown=unkC2), xDF) ## with list of two unknown values - recycling checkIdentical(unknownToNA(xListUnk2, unknown=unkL2), xList) checkIdentical(unknownToNA(xDFUnk2, unknown=unkL2), xDF) ## with named list of two unknown values but x is not named so named list ## does not have any effect --> error as we do not know how to recycle checkException(unknownToNA(xListUnk2a, unknown=unkLN2)) ## but we should get some results with named x checkIdentical(unknownToNA(xListNUnk2, unknown=unkL2), xListN) ## not also necesarilly with recycling of names lists, as it is ## not clear how to properly recycle named lists (only names that match ## can be really properly recycled) checkException(unknownToNA(xListNUnk2, unknown=unkLN2)) checkIdentical(unknownToNA(xDFUnk2, unknown=unkL2), xDF) checkException(unknownToNA(xDFUnk2, unknown=unkLN2)) ## list(.default=) checkIdentical(unknownToNA(x=xListUnkD1, unknown=unkLND1), xListD1) ## list(.default=, someOther=) we do not know someOther, but should work ## as x is not named checkIdentical(unknownToNA(x=xListUnkDSO2, unknown=unkLNDSO2), xList) ## list(.default=) in named list checkIdentical(unknownToNA(x=xListNUnkD1, unknown=unkLND1), xListND1) ## list(.default=, someOther=) OK if someOther is in the named list checkIdentical(unknownToNA(x=xListNUnkD3, unknown=unkLND3), xListN) ## list(.default=, 99) ERROR as we do not know where to apply 99 checkException(unknownToNA(x=xListNUnk, unknown=unkLND2E)) ## --- matrix --- checkEquals(unknownToNA(x=matUnk1, unknown=matUnk), mat) } ### }}} ### {{{ --- NAToUnknown --- test.NAToUnknown <- function() { ## --- base methods for vectors --- ## base ... checkIdentical(NAToUnknown(xInt, as.integer(intUnk)), xIntUnk) checkIdentical(NAToUnknown(xInt, intUnk), xIntUnk) ## with numeric checkIdentical(NAToUnknown(xNum, numUnk), xNumUnk) checkIdentical(NAToUnknown(xNum, as.integer(numUnk)), xNumUnk) checkIdentical(NAToUnknown(xCha, chaUnk), xChaUnk) checkIdentical(NAToUnknown(xCha, chaUnk), xChaUnk) checkIdentical(NAToUnknown(xFac, facUnk), xFacUnk) ## only single values are allowed for vector methods checkException(NAToUnknown(xInt, unknown=unkC)) checkException(NAToUnknown(xInt, unknown=unkL)) ## and they should not already be in x unless force=TRUE checkException(NAToUnknown(xCha, unknown=chaUnk1)) checkIdentical(NAToUnknown(xCha, unknown=chaUnk1, force=TRUE), xChaUnk1) checkException(NAToUnknown(xFac, unknown=facLev)) checkIdentical(NAToUnknown(xFac, unknown=facLev, force=TRUE), xFacUnkLev) ## NA's in factors checkIdentical(NAToUnknown(xFac, unknown=facUnk1, force=TRUE), xFacUnk1) facNA <- factor(c("0", 1, 2, 3, NA, NA)) facNATest <- factor(c("0", 1, 2, 3, "NA", "NA")) checkIdentical(NAToUnknown(x=facNA, unknown="NA"), facNATest) ## Date-time classes checkIdentical(NAToUnknown(xDate, unknown=dateUnk), xDateUnk) checkIdentical(NAToUnknown(xPOSIXlt, unknown=POSIXltUnk), xPOSIXltUnk) checkIdentical(NAToUnknown(xPOSIXct, unknown=POSIXctUnk), xPOSIXctUnk) ## --- lists and data.frames --- ## with vector of single unknown values checkIdentical(NAToUnknown(xList, unknown=unkC), xListUnk) checkIdentical(NAToUnknown(xDF, unknown=unkC), xDFUnk) ## with list of single unknown values checkIdentical(NAToUnknown(xList, unknown=unkL), xListUnk) checkIdentical(NAToUnknown(xDF, unknown=unkL), xDFUnk) ## with named list of single unknown values checkIdentical(NAToUnknown(xListN, unknown=unkLN), xListNUnk) checkIdentical(NAToUnknown(xDF, unknown=unkLN), xDFUnk) ## with names list of multiple unknown values - must be an error checkException(NAToUnknown(xListN, unknown=unkLMN)) checkException(NAToUnknown(xDF, unknown=unkLMN)) ## with single unknown value - recycling checkIdentical(NAToUnknown(xList, unknown=unk1), xListUnk1) checkIdentical(NAToUnknown(xDF, unknown=unk1), xDFUnk1) ## with vector of two unknown values - recycling checkIdentical(NAToUnknown(xList, unknown=unkC2), xListUnk2) checkIdentical(NAToUnknown(xDF, unknown=unkC2), xDFUnk2) ## with list of two unknown values - recycling checkIdentical(NAToUnknown(xList, unknown=unkL2), xListUnk2) checkIdentical(NAToUnknown(xDF, unknown=unkL2), xDFUnk2) ## with named list of two unknown values but x is not named so named list ## does not have any effect --> error as we do not know how to recycle checkException(NAToUnknown(xList, unknown=unkLN2)) ## but we should get some results with named x checkIdentical(NAToUnknown(xListN, unknown=unkL2), xListNUnk2) ## not also necesarilly with recycling of names lists, as it is ## not clear how to properly recycle named lists (only names that match ## can be really properly recycled) checkException(NAToUnknown(xListN, unknown=unkLN2)) checkIdentical(NAToUnknown(xDF, unknown=unkL2), xDFUnk2) checkException(NAToUnknown(xDF, unknown=unkLN2)) ## list(.default=) checkIdentical(NAToUnknown(x=xList, unknown=unkLND1), xListUnkD1) ## list(.default=, someOther=) we do not know someOther, but should work ## as x is not named checkIdentical(NAToUnknown(x=xList, unknown=unkLNDSO2), xListUnkDSO2) ## list(.default=) in named list checkIdentical(NAToUnknown(x=xListN, unknown=unkLND1), xListNUnkD1) ## list(.default=, someOther=) OK if someOther is in the named list checkIdentical(NAToUnknown(x=xListN, unknown=unkLND3), xListNUnkD3) ## list(.default=, 99) ERROR as we do not know where to apply 99 checkException(NAToUnknown(x=xListN, unknown=unkLND2E)) ## --- matrix --- checkEquals(NAToUnknown(x=mat, unknown=matUnk), matUnk1) } ### }}} ### {{{ Dear Emacs ### Local variables: ### folded-file: t ### End: ### }}} ###------------------------------------------------------------------------ ### runit.unknown.R ends here gdata/inst/unitTests/runit.trimSum.R0000644000176000001440000000240711227511757017277 0ustar ripleyusers### runit.trimSum.R ###------------------------------------------------------------------------ ### What: Unit tests for trimSum ### $Id$ ### Time-stamp: <2008-12-20 11:58:50 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- trimSum --- test.trimSum <- function() { ## 'x' must be a vector - for now checkException(trimSum(matrix(1:10))) checkException(trimSum(data.frame(1:10))) checkException(trimSum(list(1:10))) ## 'x' must be numeric checkException(trimSum(letters)) ## 'n' must be smaller than the length of x checkException(trimSum(x=1:10, n=11)) checkException(trimSum(x=1, n=1)) ## Default x <- trimSum(x=1:10, n=5) x2 <- c(1:4, 45) checkEquals(x, x2) ## Left x <- trimSum(x=1:10, n=5, right=FALSE) x2 <- c(21, 7:10) checkEquals(x, x2) ## NA x <- trimSum(x=c(1:9, NA), n=5) x2 <- c(1:4, NA) checkEquals(x, x2) x <- trimSum(x=c(1:9, NA), n=5, na.rm=TRUE) x2 <- c(1:4, 35) checkEquals(x, x2) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.trimSum.R ends here gdata/inst/unitTests/runit.trim.R0000644000176000001440000000271510521462303016600 0ustar ripleyusers### runit.trim.R ###------------------------------------------------------------------------ ### What: Tests for trim ### $Id: runit.trim.R 993 2006-10-30 17:10:08Z ggorjan $ ### Time-stamp: <2006-08-29 14:21:02 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- trim --- test.trim <- function() { tmp <- Sys.getlocale(category="LC_COLLATE") Sys.setlocale(category="LC_COLLATE", locale="C") sTrim <- " this is an example string " sTrimR <- "this is an example string" fTrim <- factor(c(sTrim, sTrim, " A", " B ", " C ", "D ")) fTrimR <- factor(c(sTrimR, sTrimR, "A", "B", "C", "D")) lTrim <- list(s=rep(sTrim, times=6), f=fTrim, i=1:6) lTrimR <- list(s=rep(sTrimR, times=6), f=fTrimR, i=1:6) dfTrim <- as.data.frame(lTrim) dfTrimR <- as.data.frame(lTrimR) checkIdentical(trim(sTrim), sTrimR) checkIdentical(trim(fTrim), fTrimR) checkIdentical( levels(trim(fTrim, recode.factor=FALSE)), c("this is an example string", "C", "A", "B", "D") ) checkIdentical(trim(lTrim), lTrimR) checkIdentical(trim(dfTrim), dfTrimR) Sys.setlocale(category="LC_COLLATE", locale=tmp) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.trim.R ends here gdata/inst/unitTests/runit.reorder.factor.R0000644000176000001440000000357110521462302020544 0ustar ripleyusers### runit.reorder.factor.R ###------------------------------------------------------------------------ ### What: Tests for reorder.factor ### $Id: runit.reorder.factor.R 995 2006-10-30 17:27:38Z ggorjan $ ### Time-stamp: <2006-10-30 18:25:05 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- reorder.factor --- test.reorder.factor <- function() { tmp <- Sys.getlocale(category="LC_COLLATE") Sys.setlocale(category="LC_COLLATE", locale="C") ## Create a 4 level example factor levs <- c("PLACEBO", "300 MG", "600 MG", "1200 MG") trt <- factor(rep(x=levs, times=c(22, 24, 28, 26))) ## Change the order to something useful ## default "mixedsort" ordering trt2 <- reorder(trt) levsTest <- c("300 MG", "600 MG", "1200 MG", "PLACEBO") checkIdentical(levels(trt2), levsTest) ## using indexes: trt3 <- reorder(trt, new.order=c(4, 2, 3, 1)) levsTest <- c("PLACEBO", "300 MG", "600 MG", "1200 MG") checkIdentical(levels(trt3), levsTest) ## using label names: trt4 <- reorder(trt, new.order=c("PLACEBO", "300 MG", "600 MG", "1200 MG")) levsTest <- c("PLACEBO", "300 MG", "600 MG", "1200 MG") checkIdentical(levels(trt4), levsTest) ## using frequency trt5 <- reorder(trt, X=as.numeric(trt), FUN=length) levsTest <- c("PLACEBO", "300 MG", "1200 MG", "600 MG") checkIdentical(levels(trt5), levsTest) ## drop out the '300 MG' level trt6 <- reorder(trt, new.order=c("PLACEBO", "600 MG", "1200 MG")) levsTest <- c("PLACEBO", "600 MG", "1200 MG") checkIdentical(levels(trt6), levsTest) Sys.setlocale(category="LC_COLLATE", locale=tmp) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.reorder.factor.R ends here gdata/inst/unitTests/runit.nPairs.R0000644000176000001440000000422111552125257017064 0ustar ripleyusers### runit.nPairs.R ###------------------------------------------------------------------------ ### What: Number of variable pairs - unit tests ### $Id$ ### Time-stamp: <2008-12-30 18:24:59 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- nPairs --- test.nPairs <- function() { ## 'x' must be a data.frame or a matrix x <- rpois(100, lambda=10) checkException(nPairs(x=x)) checkException(nPairs(x=table(x))) test <- data.frame(V1=c(1, 2, 3, 4, 5), V2=c(NA, 2, 3, 4, 5), V3=c(1, NA, NA, NA, NA), V4=c(1, 2, 3, NA, NA)) testCheck <- matrix(data=as.integer(c(5, 4, 1, 3, 4, 4, 0, 2, 1, 0, 1, 1, 3, 2, 1, 3)), nrow=4, ncol=4, byrow=TRUE) class(testCheck) <- c("nPairs", class(testCheck)) testCheckNames <- testCheck colnames(testCheckNames) <- rownames(testCheckNames) <- colnames(test) checkIdentical(nPairs(x=test), testCheckNames) checkIdentical(nPairs(x=test, names=FALSE), testCheck) checkIdentical(nPairs(x=as.matrix(test)), testCheckNames) checkIdentical(nPairs(x=as.matrix(test), names=FALSE), testCheck) testCheck <- cbind(testCheckNames, as.integer(c(5, 4, 0, 0))) class(testCheck) <- class(testCheckNames) colnames(testCheck) <- c(colnames(test), "all") checkIdentical(nPairs(x=test, margin=TRUE), testCheck) testCheckSumm <- matrix(data=as.integer(c(0, 1, 4, 2, 0, 0, 4, 2, 0, 1, 0, 0, 0, 1, 2, 0)), nrow=4, ncol=4, byrow=TRUE) dimnames(testCheckSumm) <- dimnames(testCheckNames) tmp <- summary(nPairs(x=test)) checkEquals(tmp, testCheckSumm) } ### }}} ### {{{ Dear Emacs ### Local variables: ### folded-file: t ### end: ### }}} ###------------------------------------------------------------------------ ### runit.nPairs.R ends here gdata/inst/unitTests/runit.mapLevels.R0000644000176000001440000002405410521462303017555 0ustar ripleyusers### runit.mapLevels.R ###------------------------------------------------------------------------ ### What: Unit tests for mapLevels et al. ### $Id: runit.mapLevels.R 993 2006-10-30 17:10:08Z ggorjan $ ### Time-stamp: <2006-10-29 16:41:41 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ mapLevels, is.*, as.*, [.* test.mapLevels <- function() { ## Integer and numeric checkException(mapLevels(1:3)) # wrong class(x) checkException(mapLevels(1.5)) # wrong class(x) ## Factor f <- factor(c("B", "C", "A")) fMapInt <- list(A=as.integer(1), B=as.integer(2), C=as.integer(3)) fMapInt1 <- list(B=as.integer(1), C=as.integer(2)) fMapCha <- list(A="A", B="B", C="C") fMapInt <- as.levelsMap(fMapInt) fMapInt1 <- as.levelsMap(fMapInt1) fMapCha <- as.levelsMap(fMapCha) fMapCha1 <- fMapCha[c(1, 3)] # this will test also [.levelsMap checkIdentical(mapLevels(f), fMapInt) checkTrue(is.levelsMap(mapLevels(f))) # test for is.levelsMap checkTrue(is.levelsMap(fMapInt)) # test for as.levelsMap checkTrue(!gdata:::.isCharacterMap(fMapInt)) checkIdentical(mapLevels(f, sort=FALSE), fMapInt) # sort is not used for factors checkIdentical(mapLevels(f[1:2], drop=TRUE), fMapInt1) checkIdentical(mapLevels(f, codes=FALSE), fMapCha) checkIdentical(mapLevels(f[c(2, 3)], drop=TRUE, codes=FALSE), fMapCha1) ## Character cha <- c("Z", "M", "A") chaMapInt <- list(A=as.integer(1), M=as.integer(2), Z=as.integer(3)) chaMapIntO <- list(Z=as.integer(1), M=as.integer(2), A=as.integer(3)) chaMapInt1 <- list(M=as.integer(1), Z=as.integer(2)) chaMapCha <- list(A="A", M="M", Z="Z") chaMapInt <- as.levelsMap(chaMapInt) chaMapIntO <- as.levelsMap(chaMapIntO) chaMapInt1 <- as.levelsMap(chaMapInt1) chaMapCha <- as.levelsMap(chaMapCha) checkIdentical(mapLevels(cha), chaMapInt) checkIdentical(mapLevels(cha, sort=FALSE), chaMapIntO) # sort works for characters checkIdentical(mapLevels(cha[1:2], drop=TRUE), chaMapInt1) checkIdentical(mapLevels(cha, codes=FALSE), chaMapCha) ## List l <- list(f=f, cha=cha) l1 <- list(cha=cha, f=f) l2 <- list(cha=cha, f=f, i=1:10) lMapInt <- list(f=fMapInt, cha=chaMapInt) lMapCha <- list(f=fMapCha, cha=chaMapCha) lMapInt <- as.listLevelsMap(lMapInt) lMapCha <- as.listLevelsMap(lMapCha) lMapChaC <- as.list(sort(unique(c(cha, as.character(f))))) lMapChaCO <- as.list(unique(c(cha, as.character(f)))) names(lMapChaC) <- unlist(lMapChaC) names(lMapChaCO) <- unlist(lMapChaCO) lMapChaC <- as.levelsMap(lMapChaC) lMapChaCO <- as.levelsMap(lMapChaCO) checkIdentical(mapLevels(l), lMapInt) checkTrue(is.listLevelsMap(mapLevels(l))) # test for is.listLevelsMap checkTrue(is.listLevelsMap(lMapInt)) # test for as.listLevelsMap checkIdentical(mapLevels(l, codes=FALSE), lMapCha) checkException(mapLevels(l, combine=TRUE)) # can not combine integer maps checkIdentical(mapLevels(l, codes=FALSE, combine=TRUE), lMapChaC) checkIdentical(mapLevels(l1, codes=FALSE, combine=TRUE), lMapChaC) checkIdentical(mapLevels(l1, codes=FALSE, combine=TRUE, sort=FALSE), lMapChaCO) checkException(mapLevels(l2)) # only char and factor ## Data.frame df <- data.frame(f1=factor(c("G", "Abc", "Abc", "D", "F")), f2=factor(c("Abc", "Abc", "B", "D", "K")), cha=c("jkl", "A", "D", "K", "L"), int=1:5) dfMapInt <- list(f1=mapLevels(df$f1), f2=mapLevels(df$f2), cha=mapLevels(df$cha)) dfMapInt <- as.listLevelsMap(dfMapInt) dfMapInt1 <- dfMapInt[c(1, 3)] # this will test also [.listLevelsMap checkException(mapLevels(df)) # wrong class of int checkIdentical(mapLevels(df[, 1:3]), dfMapInt) checkIdentical(mapLevels(df[, c(1, 3)]), dfMapInt1) } ### }}} ### {{{ .check* test.checkLevelsMap <- function(x) { ## --- levelsMap --- ## not a list checkException(gdata:::.checkLevelsMap(x="A", method="raw")) ## list without names checkException(gdata:::.checkLevelsMap(x=list("A"), method="raw")) fMapInt <- list(A=as.integer(1), B=as.integer(2), C=as.integer(3)) ## x should be levelsMap checkException(gdata:::.checkLevelsMap(x=fMapInt, method="class")) ## --- listLevelsMap --- map <- list(as.levelsMap(fMapInt), as.levelsMap(fMapInt)) map1 <- list(fMapInt, fMapInt) class(map1) <- "listLevelsMap" ## x should be a listLevelsMap checkException(gdata:::.checkListLevelsMap(x=map, method="class")) ## x should be also a list of levelsMaps checkException(gdata:::.checkListLevelsMap(x=map1, method="class")) ## the rest is done with levelsMap tests } ### }}} ### {{{ c.* test.cLevelsMap <- function() { f1 <- factor(letters[c(2, 1)]) f2 <- factor(letters[c(3, 1, 2)]) mapCha1 <- mapLevels(f1, codes=FALSE) # get maps mapCha2 <- mapLevels(f2, codes=FALSE) mapCha1S <- mapLevels(as.character(f1), codes=FALSE, sort=FALSE) mapCha2S <- mapLevels(as.character(f2), codes=FALSE, sort=FALSE) mapChaTest <- list(a="a", b="b") mapChaTest1 <- list(a="a", b="b", c="c") mapChaTest2 <- list(c="c", a="a", b="b") class(mapChaTest) <- class(mapChaTest1) <- class(mapChaTest2) <- "levelsMap" mapChaTest3 <- list(mapChaTest, mapChaTest1, mapChaTest, mapChaTest1) class(mapChaTest3) <- "listLevelsMap" checkIdentical(c(mapCha1), mapChaTest) checkIdentical(c(mapCha2, mapCha1), mapChaTest1) checkIdentical(c(mapCha2S, mapCha1S, sort=FALSE), mapChaTest2) l <- list(f1, f2) mapCha <- mapLevels(l, codes=FALSE) checkIdentical(c(mapCha, mapCha), mapChaTest3) checkIdentical(c(mapCha, recursive=TRUE), mapChaTest1) checkException(c(mapLevels(f1))) # can not combine integer “levelsMaps†## Example with maps of different length of components map1 <- list(A=c("a", "e", "i", "o", "u"), B="b", C="c", C="m", D=c("d", "e"), F="f") map2 <- list(A=c("a", "z", "w", "y", "x"), F="f", G=c("g", "h", "j"), i="i", k=c("k", "l"), B="B") map0Test <- list(A=c("a", "e", "i", "o", "u"), B="b", C="c", C="m", D=c("d", "e"), F="f", A=c("z", "w", "y", "x"), G=c("g", "h", "j"), i="i", k=c("k", "l"), B="B") map0Test <- as.levelsMap(map0Test) mapTest <- sort(map0Test) map1 <- as.levelsMap(map1) map2 <- as.levelsMap(map2) map <- c(map1, map2) map0 <- c(map1, map2, sort=FALSE) checkIdentical(map, mapTest) checkIdentical(map0, map0Test) } ### }}} ### {{{ unique test.uniqueLevelsMap <- function() { map <- list(A=c(1, 2, 1, 3), B=4, C=1, C=5, D=c(6, 8), E=7, B=4, D=c(6, 8)) map1 <- map map1[[1]] <- map[[1]][c(1, 2, 4)] map1[[7]] <- NULL # remove B=4 map1[[7]] <- NULL # remove D=c(6, 8) ## unique (used in as.levelsMap), will remove duplicates (A=1) checkIdentical(as.levelsMap(map1), as.levelsMap(map)) } ### }}} ### {{{ mapLevels<- "test.mapLevels<-" <- function() { ## Some errors checkException("mapLevels<-"(1.1, value=2)) # wrong class(x) checkException("mapLevels<-"(complex(1.1), value=2)) # wrong class(x) f <- factor(c("A", "B", "C")) fMapInt <- mapLevels(f) ## can not apply integer "levelsMap" to "character" checkException("mapLevels<-"(as.character(f), value=fMapInt)) fMapCha <- mapLevels(f, codes=FALSE) ## can not apply character levelsMap to "integer" checkException("mapLevels<-"(as.integer(f), value=chaMapCha)) fMapFuzz <- fMapInt fMapFuzz[[1]] <- "A" ## all components of 'value' must be of the same class checkException("mapLevels<-"(as.character(f), value=fMapFuzz)) checkException("mapLevels<-"(as.integer(f), value=fMapFuzz)) ## x integer, value integer levelsMap f <- factor(letters[c(10, 15, 1, 2)]) fMapInt <- mapLevels(f) fInt <- as.integer(f) mapLevels(fInt) <- fMapInt checkIdentical(fInt, f) ## x factor, value integer levelsMap fInt <- factor(as.integer(f)) mapLevels(fInt) <- fMapInt checkIdentical(fInt, f) ## above is essentially the same as levels<-.factor fInt1 <- factor(as.integer(f)) levels(fInt1) <- fMapInt checkIdentical(fInt1, f) ## x character, value character levelsMap cha <- c("B", "A", "C") chaMapCha <- as.levelsMap(list(A1="A", B2="B", C3="C")) mapLevels(cha) <- chaMapCha chaTest <- factor(c("B2", "A1", "C3")) checkIdentical(cha, chaTest) ## and a bit more for components of length > 1 cha <- c("G", "I", "B", "A", "C", "D", "Z") chaMapCha <- as.levelsMap(list(A1=c("A", "G", "I"), B2="B", C3=c("C", "D"))) mapLevels(cha) <- chaMapCha chaTest <- factor(c("A1", "A1", "B2", "A1", "C3", "C3", NA)) checkIdentical(cha, chaTest) ## x factor, value character levelsMap f <- factor(c("G", "I", "B", "A", "C", "D", "Z")) fMapCha <- as.levelsMap(list(A1=c("A", "G", "I"), B2="B", C3=c("C", "D"))) mapLevels(f) <- fMapCha fTest <- factor(c("A1", "A1", "B2", "A1", "C3", "C3", NA)) checkIdentical(f, fTest) ## Two factors and character map f1 <- factor(letters[1:10]) f2 <- factor(letters[5:14]) checkIdentical(as.integer(f1), as.integer(f2)) # the same integer codes mapCha1 <- mapLevels(f1, codes=FALSE) # get maps mapCha2 <- mapLevels(f2, codes=FALSE) mapCha <- c(mapCha1, mapCha2) # combine maps ## apply map mapLevels(f1) <- mapCha # the same as levels(f1) <- mapCha mapLevels(f2) <- mapCha # the same as levels(f2) <- mapCha checkIdentical(as.integer(f1), 1:10) # \ internal codes are now checkIdentical(as.integer(f2), 5:14) # / "consistent" among factors ## The same with list l <- list(f1=f1, f2=f2) mapCha <- mapLevels(l, codes=FALSE, combine=TRUE) mapLevels(l) <- mapCha checkIdentical(as.integer(l$f1), 1:10) # \ internal codes are now checkIdentical(as.integer(l$f2), 5:14) # / "consistent" among factors ## and data.frame df <- data.frame(f1=f1, f2=f2) mapCha <- mapLevels(df, codes=FALSE, combine=TRUE) mapLevels(df) <- mapCha checkIdentical(as.integer(df$f1), 1:10) # \ internal codes are now checkIdentical(as.integer(df$f2), 5:14) # / "consistent" among factors } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.mapLevels.R ends here gdata/inst/unitTests/runit.getDateTimeParts.R0000644000176000001440000000501211243033552021026 0ustar ripleyusers### runit.getDateTimeParts.R ###------------------------------------------------------------------------ ### What: Extract date and time parts from ... - unit tests ### $Id$ ### Time-stamp: <2008-12-30 22:41:18 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } num <- 1 cha <- "a" fac <- factor(c("A")) tYear <- as.character(c(2006, 1995, 1005, 3067)) tMonth <- c("01", "04", "06", "12") tDay <- c("01", "12", "22", "04") tDate <- paste( paste(tYear, tMonth, tDay, sep="-"), "GMT" ) tHour <- c("05", "16", "20", "03") tMin <- c("16", "40", "06", "52") tSec <- c("56", "34", "05", "15") tTime <- paste(tHour, tMin, tSec, sep=":") cDate <- as.Date(tDate) cDatePOSIXct <- as.POSIXct(tDate) cDatePOSIXlt <- as.POSIXlt(tDate) ### }}} ### {{{ --- getYear --- test.getYear <- function() { checkException(getYear(x=num)) checkException(getYear(x=cha)) checkException(getYear(x=fac)) checkIdentical(getYear(x=cDate), tYear) checkIdentical(getYear(x=cDatePOSIXct), tYear) checkIdentical(getYear(x=cDatePOSIXlt), tYear) } ### }}} ### {{{ --- getMonth --- test.getMonth <- function() { checkException(getMonth(x=num)) checkException(getMonth(x=cha)) checkException(getMonth(x=fac)) checkIdentical(getMonth(x=cDate), tMonth) checkIdentical(getMonth(x=cDatePOSIXct), tMonth) checkIdentical(getMonth(x=cDatePOSIXlt), tMonth) } ### }}} ### {{{ --- getDay --- test.getDay <- function() { checkException(getDay(x=num)) checkException(getDay(x=cha)) checkException(getDay(x=fac)) checkIdentical(getDay(x=cDate), tDay) checkIdentical(getDay(x=cDatePOSIXct), tDay) checkIdentical(getDay(x=cDatePOSIXlt), tDay) } ### }}} ### {{{ --- getHour --- test.getHour <- function() { checkException(getHour(x=num)) checkException(getHour(x=cha)) checkException(getHour(x=fac)) ## checkIdentical(getHour(x=cDate), tHour) } ### }}} ### {{{ --- getMin --- test.getMin <- function() { checkException(getMin(x=num)) checkException(getMin(x=cha)) checkException(getMin(x=fac)) ## checkIdentical(getMin(x=cDate), tMin) } ### }}} ### {{{ --- getSec --- test.getSec <- function() { checkException(getSec(x=num)) checkException(getSec(x=cha)) checkException(getSec(x=fac)) ## checkIdentical(getSec(x=cDate), tSec) } ### }}} ### {{{ Dear Emacs ### Local variables: ### folded-file: t ### end: ### }}} ###------------------------------------------------------------------------ ### runit.getDateTimeParts.R ends here gdata/inst/unitTests/runit.drop.levels.R0000644000176000001440000000177610521462303020070 0ustar ripleyusers### runit.drop.levels.R ###------------------------------------------------------------------------ ### What: Tests for drop.levels ### $Id: runit.drop.levels.R 993 2006-10-30 17:10:08Z ggorjan $ ### Time-stamp: <2006-08-29 14:21:12 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- drop.levels --- test.drop.levels <- function() { f <- factor(c("A", "B", "C", "D"))[1:3] fDrop <- factor(c("A", "B", "C")) l <- list(f=f, i=1:3, c=c("A", "B", "D")) lDrop <- list(f=fDrop, i=1:3, c=c("A", "B", "D")) df <- as.data.frame(l) dfDrop <- as.data.frame(lDrop) checkIdentical(drop.levels(f), fDrop) checkIdentical(drop.levels(l), lDrop) checkIdentical(drop.levels(df), dfDrop) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.drop.levels.R ends here gdata/inst/unitTests/runit.cbindX.R0000644000176000001440000000516511227511757017052 0ustar ripleyusers### runit.cbindX.R ###------------------------------------------------------------------------ ### What: Unit tests for cbindX ### $Id: runit.cbindX.R 1300 2008-08-05 11:47:18Z ggorjan $ ### Time-stamp: <2008-08-05 13:40:49 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- cbindX --- test.cbindX <- function() { df1 <- data.frame(a=1:3, b=c("A", "B", "C")) df2 <- data.frame(c=as.character(1:5), a=5:1) ma1 <- matrix(as.character(1:4), nrow=2, ncol=2) ma2 <- matrix(1:6, nrow=3, ncol=2) df12test <- cbindX(df1, df2) df12stand <- data.frame(a=c(1:3, NA, NA), b=c("A", "B", "C", NA, NA), c=as.character(1:5), a=5:1) names(df12stand)[4] <- "a" checkEquals(df12test, df12stand) ma12test <- cbindX(ma1, ma2) ma12stand <- matrix(as.character(c(1, 3, 1, 4, 2, 4, 2, 5, NA, NA, 3, 6)), nrow=3, ncol=4, byrow=TRUE) checkEquals(ma12test, ma12stand) da11test <- cbindX(df1, ma1) da11stand <- data.frame(a=1:3, b=c("A", "B", "C"), as.character(c(1:2, NA)), as.character(c(3:4, NA))) names(da11stand)[3:4] <- c("1", "2") checkEquals(da11test, da11stand) tmpTest <- cbindX(df1, df2, ma1, ma2) tmpStand <- data.frame(a=c(1:3, NA, NA), b=c("A", "B", "C", NA, NA), c=as.character(1:5), a=5:1, as.character(c(1:2, NA, NA, NA)), as.character(c(3:4, NA, NA, NA)), c(1:3, NA, NA), c(4:6, NA, NA)) names(tmpStand)[4:8] <- c("a", "1", "2", "1", "2") checkEquals(tmpTest, tmpStand) tmpTest <- cbindX(ma1, ma2, df1, df2) tmpStand <- data.frame(as.character(c(1:2, NA, NA, NA)), as.character(c(3:4, NA, NA, NA)), as.character(c(1:3, NA, NA)), as.character(c(4:6, NA, NA)), a=c(1:3, NA, NA), b=c("A", "B", "C", NA, NA), c=as.character(1:5), a=5:1) names(tmpStand)[c(1:4, 8)] <- c("1", "2", "3", "4", "a") checkEquals(tmpTest, tmpStand) } ### }}} ### {{{ Dear Emacs ### Local variables: ### folded-file: t ### end: ### }}} ###------------------------------------------------------------------------ ### runit.cbindX.R ends here gdata/inst/unitTests/runit.bindData.R0000644000176000001440000000535311227511757017350 0ustar ripleyusers### runit.bindData.R ###------------------------------------------------------------------------ ### What: Bind two data frames - unit tests ### $Id$ ### Time-stamp: <2008-12-30 11:58:50 ggorjan> ###------------------------------------------------------------------------ ### {{{ --- Test setup --- if(FALSE) { library("RUnit") library("gdata") } ### }}} ### {{{ --- bindData --- test.bindData <- function() { ## 'x'/'y' must be a data.frame checkException(bindData(x=1:10, y=1:10)) checkException(bindData(x=matrix(1:10), y=matrix(1:10))) n1 <- 6; n2 <- 12; n3 <- 4 ## Single trait 1 num <- c(5:n1, 10:13) tmp1 <- data.frame(y1=rnorm(n=n1), f1=factor(rep(c("A", "B"), n1/2)), ch=letters[num], fa=factor(letters[num]), nu=(num) + 0.5, id=factor(num), stringsAsFactors=FALSE) ## Single trait 2 with repeated records, some subjects also in tmp1 num <- 4:9 tmp2 <- data.frame(y2=rnorm(n=n2), f2=factor(rep(c("C", "D"), n2/2)), ch=letters[rep(num, times=2)], fa=factor(letters[rep(c(num), times=2)]), nu=c((num) + 0.5, (num) + 0.25), id=factor(rep(num, times=2)), stringsAsFactors=FALSE) ## Single trait 3 with completely distinct set of subjects num <- 1:4 tmp3 <- data.frame(y3=rnorm(n=n3), f3=factor(rep(c("E", "F"), n3/2)), ch=letters[num], fa=factor(letters[num]), nu=(num) + 0.5, id=factor(num), stringsAsFactors=FALSE) ## Combine all datasets tmp12 <- bindData(x=tmp1, y=tmp2, common=c("id", "nu", "ch", "fa")) tmp123 <- bindData(x=tmp12, y=tmp3, common=c("id", "nu", "ch", "fa")) checkEquals(names(tmp123), c("id", "nu", "ch", "fa", "y1", "f1", "y2", "f2", "y3", "f3")) checkEquals(rbind(tmp1["id"], tmp2["id"], tmp3["id"]), tmp123["id"]) checkEquals(rbind(tmp1["fa"], tmp2["fa"], tmp3["fa"]), tmp123["fa"]) checkEquals(is.na(tmp123$y1), c(rep(FALSE, times=n1), rep(TRUE, times=n2+n3))) checkEquals(is.na(tmp123$f1), c(rep(FALSE, times=n1), rep(TRUE, times=n2+n3))) checkEquals(is.na(tmp123$y2), c(rep(TRUE, times=n1), rep(FALSE, times=n2), rep(TRUE, times=n3))) checkEquals(is.na(tmp123$f2), c(rep(TRUE, times=n1), rep(FALSE, times=n2), rep(TRUE, times=n3))) checkEquals(is.na(tmp123$y3), c(rep(TRUE, times=n1+n2), rep(FALSE, times=n3))) checkEquals(is.na(tmp123$f3), c(rep(TRUE, times=n1+n2), rep(FALSE, times=n3))) } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### runit.bindData.R ends here gdata/inst/unitTests/runRUnitTests.R0000644000176000001440000000664111227511757017314 0ustar ripleyusers### runRUnitTests.R ###------------------------------------------------------------------------ ### What: Run RUnit tests (the core)- R code ### $Id$ ### Time-stamp: <2008-12-30 12:52:51 ggorjan> ###------------------------------------------------------------------------ ## The setup seems to be quite messy, but it is so to enable use of this in ## several ways as shown bellow. ## "R CMD check" way should be the most authoritative way to run the RUnit ## tests for a developer. RUnit tests are issued during R CMD check of the ## package due to example section of .runRUnitTests() function. If any test ## fails (failure) or if there are any R errors during RUnit testing, R CMD ## check fails. These are variable values specific for this way: ## - .path DEVEL/PATH/PKG.Rcheck/PKG/unitTests ## - .way function ## ".runRUnitTests()" way from within R after library(PKG) is handy for ## package useRs, since it enables useRs to be sure that all tests pass for ## their installation. This is just a convenient wrapper function to run ## the RUnit testing suite. These are variable values specific for this ## way: ## - .path INSTALL/PATH/PKG/unitTests ## - .way function ## "Shell" way is another possibility mainly for a developer in order to ## skip possibly lengthy R CMD check and perform just RUnit testing with an ## installed version of a pcakage. These are variable values specific for ## this way: ## - .path DEVEL/PATH/PKG/inst/unitTests ## - .way shell ## ## Rscript runRUnitTests.R ## R CMD BATCH runRUnitTests.R ## make ## make all ## Sourced via shell (Makefile, Rscript, R CMD BATCH) if(!exists(".pkg")) { .path <- getwd() .way <- "shell" .pkg <- c(read.dcf(file="../../DESCRIPTION", fields="Package")) print(.pkg) testFileRegexp <- "^base.+\\.[rR]$" } if(require("RUnit", quietly=TRUE)) { ## Debugging echo cat("\nRunning RUnit tests\n") print(list(pkg=.pkg, getwd=getwd(), pathToRUnitTests=.path)) ## Load the package - not needed for .runRUnitTests() if(.way %in% c("shell")) library(package=.pkg, character.only=TRUE) ## Define tests testSuite <- defineTestSuite(name=paste(.pkg, "RUnit testing"), dirs=.path, testFileRegexp=testFileRegexp) ## Run tests <- runTestSuite(testSuite) if(file.access(.path, 02) != 0) { ## cannot write to .path -> use writable one tdir <- tempfile(paste(.pkg, "RUnitTests", sep="_")) dir.create(tdir) pathReport <- file.path(tdir, "report") } else { pathReport <- file.path(.path, "report") } ## Print results: printTextProtocol(tests) printTextProtocol(tests, fileName=paste(pathReport, ".txt", sep="")) ## Print HTML Version of results: printHTMLProtocol(tests, fileName=paste(pathReport, ".html", sep="")) cat("\nRUnit reports also written to\n", pathReport, ".(txt|html)\n\n", sep="") ## Return stop() to cause R CMD check stop in case of ## - failures i.e. FALSE to RUnit tests or ## - errors i.e. R errors tmp <- getErrors(tests) if(tmp$nFail > 0 || tmp$nErr > 0) { stop(paste("\n\nRUnit testing failed:\n", " - #test failures: ", tmp$nFail, "\n", " - #R errors: ", tmp$nErr, "\n\n", sep="")) } } else { cat("R package 'RUnit' cannot be loaded - no unit tests run\n", "for package", .pkg,"\n") } ###------------------------------------------------------------------------ ### runRUnitTests.R ends here gdata/inst/unitTests/report.txt0000644000176000001440000000073511243022743016420 0ustar ripleyusersRUNIT TEST PROTOCOL -- Wed Aug 19 12:18:43 2009 *********************************************** Number of test functions: 0 Number of errors: 0 Number of failures: 0 1 Test Suite : gdata RUnit testing - 0 test functions, 0 errors, 0 failures Details *************************** Test Suite: gdata RUnit testing Test function regexp: ^test.+ Test file regexp: ^base.+\.[rR]$ Involved directory: /Users/warnes/src/r-gregmisc/gdata/inst/unitTests no test files gdata/inst/unitTests/report.html0000644000176000001440000000323411243022744016543 0ustar ripleyusers RUNIT TEST PROTOCOL--Wed Aug 19 12:18:43 2009

RUNIT TEST PROTOCOL--Wed Aug 19 12:18:43 2009

Number of test functions: 0

Number of errors: 0

Number of failures: 0


1 Test suite

Name Test functions Errors Failures
gdata RUnit testing 0 0 0

Details

Test Suite: gdata RUnit testing
Test function regexp: ^test.+
Test file regexp: ^base.+\.[rR]$
Involved directory:
/Users/warnes/src/r-gregmisc/gdata/inst/unitTests
no test files

Name Value
platform i386-apple-darwin8.11.1
arch i386
os darwin8.11.1
system i386, darwin8.11.1
status
major 2
minor 9.1
year 2009
month 06
day 26
svn rev 48839
language R
version.string R version 2.9.1 (2009-06-26)
host akane.local
compiler NA
gdata/inst/unitTests/Makefile0000644000176000001440000000071011227511757016007 0ustar ripleyusersTOP=../.. PKG=${shell cd ${TOP};pwd} SUITE=runRUnitTests.R R=R test: # Run unit tests ${R} --vanilla --slave < ${SUITE} inst: # Install package cd ${TOP}/..;\ ${R} CMD INSTALL ${PKG} all: inst test echo: # Echo env. variables @echo "Package folder: ${PKG}" @echo "R binary: ${R}" help: # Help @echo -e '\nTarget: Dependency # Description'; \ echo '=================================================='; \ egrep '^[[:alnum:].+_()%]*:' ./Makefile gdata/inst/perl/0000755000176000001440000000000012163371440013302 5ustar ripleyusersgdata/inst/perl/xls2tsv.pl0000755000176000001440000001322712163371440015274 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } use strict; #use Spreadsheet::ParseExcel; #use Spreadsheet::XLSX; use POSIX; use File::Spec::Functions; use Getopt::Std; ## # Try to load the modules we need ## require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX ) = check_modules_and_notify(); # declare some varibles local my($row, $col, $sheet, $cell, $usage, $targetfile,$basename, $sheetnumber, $filename, $volume, $directories, $whoami, $sep, $sepName, $sepLabel, $sepExt, $skipBlankLines, %switches); ## ## Figure out whether I'm called as xls2csv.pl or xls2tab.pl ## ($volume,$directories,$whoami) = File::Spec->splitpath( $0 ); if($whoami eq "xls2csv.pl") { $sep=","; $sepName="comma"; $sepLabel="CSV"; $sepExt="csv"; } elsif ($whoami eq "xls2tsv.pl") { $sep="\t"; $sepName="tab"; $sepLabel="TSV"; $sepExt="tsv"; } elsif ($whoami eq "xls2tab.pl") { $sep="\t"; $sepName="tab"; $sepLabel="TAB"; $sepExt="tab"; } else { die("This script is named '$whoami', but must be named either 'xls2csv.pl' or 'xls2tab.pl' to function properly.\n"); } ## ## Usage information ## $usage = < [] [] Translate the Microsoft Excel spreadsheet file contained in into $sepName separated value format ($sepLabel) and store in , skipping blank lines unless "-s" is present. If is not specified, the output file will have the same name as the input file with '.xls', or 'xlsx' removed and '.$sepExt' appended. If no worksheet number is given, each worksheet will be written to a separate file with the name '_.$sepExt'. EOF ## ## parse arguments ## # Handle switches (currently, just -s) getopts('s', \%switches); $skipBlankLines=!$switches{s}; # Now the rest of the arguments if( !defined($ARGV[0]) ) { print $usage; exit 1; } if( defined($ARGV[1]) ) { $basename = $targetfile = $ARGV[1]; $basename =~ s/\.$sepExt$//i; } else { ($volume,$directories,$basename) = File::Spec->splitpath( $ARGV[0] ); $basename =~ s/\.xlsx*//i; } my $targetsheetname; my $sheetnumber; if(defined($ARGV[2]) ) { if ( isdigit($ARGV[2]) ) { $sheetnumber = $ARGV[2]; die "Sheetnumber must be an integer larger than 0.\n" if $sheetnumber < 1; } else { $targetsheetname = $ARGV[2]; } } ## ## open spreadsheet ## my $oExcel; my $oBook; $oExcel = new Spreadsheet::ParseExcel; open(FH, "<$ARGV[0]") or die "Unable to open file '$ARGV[0]'.\n"; close(FH); print "Loading '$ARGV[0]'...\n"; ## First try as a Excel 2007+ 'xml' file eval { local $SIG{__WARN__} = sub {}; $oBook = Spreadsheet::XLSX -> new ($ARGV[0]); }; ## Then Excel 97-2004 Format if($@) { $oBook = new Spreadsheet::ParseExcel->Parse($ARGV[0]) or \ die "Error parsing file '$ARGV[0]'.\n"; } print "Done.\n"; print "\n"; print "Orignal Filename: ", $ARGV[0], "\n"; print "Number of Sheets: ", $oBook->{SheetCount} , "\n"; print "\n"; ## Get list all worksheets in the file my @sheetlist = (@{$oBook->{Worksheet}}); my $sheet; ## If we want a specific sheet drop everything else if ( defined($sheetnumber) ) { $sheet = $oBook->Worksheet($sheetnumber-1) or die "No sheet number $sheetnumber.\n"; @sheetlist = ( $sheet ); } elsif ( defined($targetsheetname) ) { $sheet = $oBook->Worksheet($targetsheetname) or die "No sheet named '$targetsheetname'.\n"; @sheetlist = ( $sheet ); } ## ## iterate across each worksheet, writing out a separat csv file ## my $i=0; my $sheetname; my $found=0; foreach my $sheet (@sheetlist) { $i++; $sheetname = $sheet->{Name}; if( defined($sheetnumber) || defined($targetsheetname) || $oBook->{SheetCount}==1 ) { if( defined($targetfile) ) { $filename = $targetfile; } else { $filename = "${basename}.$sepExt"; } } else { $filename = "${basename}_${sheetname}.$sepExt"; } if( defined($sheetnumber) ) { print "Writing sheet number $sheetnumber ('$sheetname') to file '$filename'\n"; } elsif ( defined($targetsheetname) ) { print "Writing sheet '$sheetname' to file '$filename'\n"; } else { print "Writing sheet number $i ('$sheetname') to file '$filename'\n"; } open(OutFile,">$filename"); my $cumulativeBlankLines=0; my $minrow = $sheet->{MinRow}; my $maxrow = $sheet->{MaxRow}; my $mincol = $sheet->{MinCol}; my $maxcol = $sheet->{MaxCol}; print "Minrow=$minrow Maxrow=$maxrow Mincol=$mincol Maxcol=$maxcol\n"; for(my $row = $minrow; $row <= $maxrow; $row++) { my $outputLine = ""; for(my $col = $mincol; $col <= $maxcol; $col++) { my $cell = $sheet->{Cells}[$row][$col]; if( defined($cell) ) { $_=$cell->Value; #{Val}; # convert '#NUM!' strings to missing (empty) values s/#NUM!//; # escape double-quote characters in the data since # they are used as field delimiters s/\"/\\\"/g; } else { $_ = ''; } $outputLine .= "\"" . $_ . "\"" if(length($_)>0); # separate cells with specified separator $outputLine .= $sep if( $col != $maxcol) ; } # skip blank/empty lines if( $skipBlankLines && ($outputLine =~ /^[$sep ]*$/) ) { $cumulativeBlankLines++ } else { print OutFile "$outputLine\n" } } close OutFile; print " (Ignored $cumulativeBlankLines blank lines.)\n" if $skipBlankLines; print "\n"; } gdata/inst/perl/xls2tab.pl0000755000176000001440000001322712163371440015226 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } use strict; #use Spreadsheet::ParseExcel; #use Spreadsheet::XLSX; use POSIX; use File::Spec::Functions; use Getopt::Std; ## # Try to load the modules we need ## require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX ) = check_modules_and_notify(); # declare some varibles local my($row, $col, $sheet, $cell, $usage, $targetfile,$basename, $sheetnumber, $filename, $volume, $directories, $whoami, $sep, $sepName, $sepLabel, $sepExt, $skipBlankLines, %switches); ## ## Figure out whether I'm called as xls2csv.pl or xls2tab.pl ## ($volume,$directories,$whoami) = File::Spec->splitpath( $0 ); if($whoami eq "xls2csv.pl") { $sep=","; $sepName="comma"; $sepLabel="CSV"; $sepExt="csv"; } elsif ($whoami eq "xls2tsv.pl") { $sep="\t"; $sepName="tab"; $sepLabel="TSV"; $sepExt="tsv"; } elsif ($whoami eq "xls2tab.pl") { $sep="\t"; $sepName="tab"; $sepLabel="TAB"; $sepExt="tab"; } else { die("This script is named '$whoami', but must be named either 'xls2csv.pl' or 'xls2tab.pl' to function properly.\n"); } ## ## Usage information ## $usage = < [] [] Translate the Microsoft Excel spreadsheet file contained in into $sepName separated value format ($sepLabel) and store in , skipping blank lines unless "-s" is present. If is not specified, the output file will have the same name as the input file with '.xls', or 'xlsx' removed and '.$sepExt' appended. If no worksheet number is given, each worksheet will be written to a separate file with the name '_.$sepExt'. EOF ## ## parse arguments ## # Handle switches (currently, just -s) getopts('s', \%switches); $skipBlankLines=!$switches{s}; # Now the rest of the arguments if( !defined($ARGV[0]) ) { print $usage; exit 1; } if( defined($ARGV[1]) ) { $basename = $targetfile = $ARGV[1]; $basename =~ s/\.$sepExt$//i; } else { ($volume,$directories,$basename) = File::Spec->splitpath( $ARGV[0] ); $basename =~ s/\.xlsx*//i; } my $targetsheetname; my $sheetnumber; if(defined($ARGV[2]) ) { if ( isdigit($ARGV[2]) ) { $sheetnumber = $ARGV[2]; die "Sheetnumber must be an integer larger than 0.\n" if $sheetnumber < 1; } else { $targetsheetname = $ARGV[2]; } } ## ## open spreadsheet ## my $oExcel; my $oBook; $oExcel = new Spreadsheet::ParseExcel; open(FH, "<$ARGV[0]") or die "Unable to open file '$ARGV[0]'.\n"; close(FH); print "Loading '$ARGV[0]'...\n"; ## First try as a Excel 2007+ 'xml' file eval { local $SIG{__WARN__} = sub {}; $oBook = Spreadsheet::XLSX -> new ($ARGV[0]); }; ## Then Excel 97-2004 Format if($@) { $oBook = new Spreadsheet::ParseExcel->Parse($ARGV[0]) or \ die "Error parsing file '$ARGV[0]'.\n"; } print "Done.\n"; print "\n"; print "Orignal Filename: ", $ARGV[0], "\n"; print "Number of Sheets: ", $oBook->{SheetCount} , "\n"; print "\n"; ## Get list all worksheets in the file my @sheetlist = (@{$oBook->{Worksheet}}); my $sheet; ## If we want a specific sheet drop everything else if ( defined($sheetnumber) ) { $sheet = $oBook->Worksheet($sheetnumber-1) or die "No sheet number $sheetnumber.\n"; @sheetlist = ( $sheet ); } elsif ( defined($targetsheetname) ) { $sheet = $oBook->Worksheet($targetsheetname) or die "No sheet named '$targetsheetname'.\n"; @sheetlist = ( $sheet ); } ## ## iterate across each worksheet, writing out a separat csv file ## my $i=0; my $sheetname; my $found=0; foreach my $sheet (@sheetlist) { $i++; $sheetname = $sheet->{Name}; if( defined($sheetnumber) || defined($targetsheetname) || $oBook->{SheetCount}==1 ) { if( defined($targetfile) ) { $filename = $targetfile; } else { $filename = "${basename}.$sepExt"; } } else { $filename = "${basename}_${sheetname}.$sepExt"; } if( defined($sheetnumber) ) { print "Writing sheet number $sheetnumber ('$sheetname') to file '$filename'\n"; } elsif ( defined($targetsheetname) ) { print "Writing sheet '$sheetname' to file '$filename'\n"; } else { print "Writing sheet number $i ('$sheetname') to file '$filename'\n"; } open(OutFile,">$filename"); my $cumulativeBlankLines=0; my $minrow = $sheet->{MinRow}; my $maxrow = $sheet->{MaxRow}; my $mincol = $sheet->{MinCol}; my $maxcol = $sheet->{MaxCol}; print "Minrow=$minrow Maxrow=$maxrow Mincol=$mincol Maxcol=$maxcol\n"; for(my $row = $minrow; $row <= $maxrow; $row++) { my $outputLine = ""; for(my $col = $mincol; $col <= $maxcol; $col++) { my $cell = $sheet->{Cells}[$row][$col]; if( defined($cell) ) { $_=$cell->Value; #{Val}; # convert '#NUM!' strings to missing (empty) values s/#NUM!//; # escape double-quote characters in the data since # they are used as field delimiters s/\"/\\\"/g; } else { $_ = ''; } $outputLine .= "\"" . $_ . "\"" if(length($_)>0); # separate cells with specified separator $outputLine .= $sep if( $col != $maxcol) ; } # skip blank/empty lines if( $skipBlankLines && ($outputLine =~ /^[$sep ]*$/) ) { $cumulativeBlankLines++ } else { print OutFile "$outputLine\n" } } close OutFile; print " (Ignored $cumulativeBlankLines blank lines.)\n" if $skipBlankLines; print "\n"; } gdata/inst/perl/xls2csv.pl0000755000176000001440000001322712163371440015253 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } use strict; #use Spreadsheet::ParseExcel; #use Spreadsheet::XLSX; use POSIX; use File::Spec::Functions; use Getopt::Std; ## # Try to load the modules we need ## require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX ) = check_modules_and_notify(); # declare some varibles local my($row, $col, $sheet, $cell, $usage, $targetfile,$basename, $sheetnumber, $filename, $volume, $directories, $whoami, $sep, $sepName, $sepLabel, $sepExt, $skipBlankLines, %switches); ## ## Figure out whether I'm called as xls2csv.pl or xls2tab.pl ## ($volume,$directories,$whoami) = File::Spec->splitpath( $0 ); if($whoami eq "xls2csv.pl") { $sep=","; $sepName="comma"; $sepLabel="CSV"; $sepExt="csv"; } elsif ($whoami eq "xls2tsv.pl") { $sep="\t"; $sepName="tab"; $sepLabel="TSV"; $sepExt="tsv"; } elsif ($whoami eq "xls2tab.pl") { $sep="\t"; $sepName="tab"; $sepLabel="TAB"; $sepExt="tab"; } else { die("This script is named '$whoami', but must be named either 'xls2csv.pl' or 'xls2tab.pl' to function properly.\n"); } ## ## Usage information ## $usage = < [] [] Translate the Microsoft Excel spreadsheet file contained in into $sepName separated value format ($sepLabel) and store in , skipping blank lines unless "-s" is present. If is not specified, the output file will have the same name as the input file with '.xls', or 'xlsx' removed and '.$sepExt' appended. If no worksheet number is given, each worksheet will be written to a separate file with the name '_.$sepExt'. EOF ## ## parse arguments ## # Handle switches (currently, just -s) getopts('s', \%switches); $skipBlankLines=!$switches{s}; # Now the rest of the arguments if( !defined($ARGV[0]) ) { print $usage; exit 1; } if( defined($ARGV[1]) ) { $basename = $targetfile = $ARGV[1]; $basename =~ s/\.$sepExt$//i; } else { ($volume,$directories,$basename) = File::Spec->splitpath( $ARGV[0] ); $basename =~ s/\.xlsx*//i; } my $targetsheetname; my $sheetnumber; if(defined($ARGV[2]) ) { if ( isdigit($ARGV[2]) ) { $sheetnumber = $ARGV[2]; die "Sheetnumber must be an integer larger than 0.\n" if $sheetnumber < 1; } else { $targetsheetname = $ARGV[2]; } } ## ## open spreadsheet ## my $oExcel; my $oBook; $oExcel = new Spreadsheet::ParseExcel; open(FH, "<$ARGV[0]") or die "Unable to open file '$ARGV[0]'.\n"; close(FH); print "Loading '$ARGV[0]'...\n"; ## First try as a Excel 2007+ 'xml' file eval { local $SIG{__WARN__} = sub {}; $oBook = Spreadsheet::XLSX -> new ($ARGV[0]); }; ## Then Excel 97-2004 Format if($@) { $oBook = new Spreadsheet::ParseExcel->Parse($ARGV[0]) or \ die "Error parsing file '$ARGV[0]'.\n"; } print "Done.\n"; print "\n"; print "Orignal Filename: ", $ARGV[0], "\n"; print "Number of Sheets: ", $oBook->{SheetCount} , "\n"; print "\n"; ## Get list all worksheets in the file my @sheetlist = (@{$oBook->{Worksheet}}); my $sheet; ## If we want a specific sheet drop everything else if ( defined($sheetnumber) ) { $sheet = $oBook->Worksheet($sheetnumber-1) or die "No sheet number $sheetnumber.\n"; @sheetlist = ( $sheet ); } elsif ( defined($targetsheetname) ) { $sheet = $oBook->Worksheet($targetsheetname) or die "No sheet named '$targetsheetname'.\n"; @sheetlist = ( $sheet ); } ## ## iterate across each worksheet, writing out a separat csv file ## my $i=0; my $sheetname; my $found=0; foreach my $sheet (@sheetlist) { $i++; $sheetname = $sheet->{Name}; if( defined($sheetnumber) || defined($targetsheetname) || $oBook->{SheetCount}==1 ) { if( defined($targetfile) ) { $filename = $targetfile; } else { $filename = "${basename}.$sepExt"; } } else { $filename = "${basename}_${sheetname}.$sepExt"; } if( defined($sheetnumber) ) { print "Writing sheet number $sheetnumber ('$sheetname') to file '$filename'\n"; } elsif ( defined($targetsheetname) ) { print "Writing sheet '$sheetname' to file '$filename'\n"; } else { print "Writing sheet number $i ('$sheetname') to file '$filename'\n"; } open(OutFile,">$filename"); my $cumulativeBlankLines=0; my $minrow = $sheet->{MinRow}; my $maxrow = $sheet->{MaxRow}; my $mincol = $sheet->{MinCol}; my $maxcol = $sheet->{MaxCol}; print "Minrow=$minrow Maxrow=$maxrow Mincol=$mincol Maxcol=$maxcol\n"; for(my $row = $minrow; $row <= $maxrow; $row++) { my $outputLine = ""; for(my $col = $mincol; $col <= $maxcol; $col++) { my $cell = $sheet->{Cells}[$row][$col]; if( defined($cell) ) { $_=$cell->Value; #{Val}; # convert '#NUM!' strings to missing (empty) values s/#NUM!//; # escape double-quote characters in the data since # they are used as field delimiters s/\"/\\\"/g; } else { $_ = ''; } $outputLine .= "\"" . $_ . "\"" if(length($_)>0); # separate cells with specified separator $outputLine .= $sep if( $col != $maxcol) ; } # skip blank/empty lines if( $skipBlankLines && ($outputLine =~ /^[$sep ]*$/) ) { $cumulativeBlankLines++ } else { print OutFile "$outputLine\n" } } close OutFile; print " (Ignored $cumulativeBlankLines blank lines.)\n" if $skipBlankLines; print "\n"; } gdata/inst/perl/supportedFormats.pl0000644000176000001440000000104612163371440017221 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX) = check_modules(0); $XLS_Support = $HAS_Spreadsheet_ParseExcel; $XLSX_Support = $HAS_Spreadsheet_ParseExcel && $HAS_Compress_Raw_Zlib && $HAS_Spreadsheet_XLSX; printf "Supported formats: "; printf "XLS " if ( $XLS_Support ); printf "XLSX" if ( $XLSX_Support ); printf "\n"; gdata/inst/perl/sheetNames.pl0000644000176000001440000000374312163371440015742 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } use strict; ## # Try to load the modules we need ## require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX ) = check_modules_and_notify(); use File::Spec::Functions; # declare some varibles local my($row, $col, $sheet, $cell, $usage, $filename, $volume, $directories, $whoami, $basename, $sheetnumber, $filename, $text); ## ## Figure out whether I'm called as sheetCount.pl or sheetNames.pl ## ($volume,$directories,$whoami) = File::Spec->splitpath( $0 ); if($whoami eq "sheetCount.pl") { $text="number"; } elsif ($whoami eq "sheetNames.pl") { $text="names"; } else { die("This script is named '$whoami', but must be named either 'sheetCount.pl' or 'sheetNames.pl' to function properly.\n"); } ## ## Usage information ## $usage = < Output is the $text of sheets in the excel file. EOF ## ## parse arguments ## if(!defined($ARGV[0])) { print $usage; exit 1; } my $fileName=$ARGV[0]; ## ## open spreadsheet ## open(FH, "<$fileName") or die "Unable to open file '$fileName'.\n"; close(FH); my $oBook; ## First try as a Excel 2007+ 'xml' file eval { local $SIG{__WARN__} = sub {}; $oBook = Spreadsheet::XLSX -> new ($ARGV[0]); }; ## Then Excel 97-2004 Format if($@) { $oBook = new Spreadsheet::ParseExcel->Parse($ARGV[0]) or \ die "Error parsing file '$ARGV[0]'.\n"; } if($whoami eq "sheetCount.pl") { print $oBook->{SheetCount} , "\n"; } elsif ($whoami eq "sheetNames.pl") { ## Get list all worksheets in the file my @sheetlist = (@{$oBook->{Worksheet}}); foreach my $sheet (@sheetlist) { print "\"$sheet->{Name}\" "; } print "\n"; } else { die("This script is named '$whoami', but must be named either 'sheetCount.pl' or 'sheetNames.pl' to function properly.\n"); } gdata/inst/perl/sheetCount.pl0000644000176000001440000000374312163371440015767 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } use strict; ## # Try to load the modules we need ## require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX ) = check_modules_and_notify(); use File::Spec::Functions; # declare some varibles local my($row, $col, $sheet, $cell, $usage, $filename, $volume, $directories, $whoami, $basename, $sheetnumber, $filename, $text); ## ## Figure out whether I'm called as sheetCount.pl or sheetNames.pl ## ($volume,$directories,$whoami) = File::Spec->splitpath( $0 ); if($whoami eq "sheetCount.pl") { $text="number"; } elsif ($whoami eq "sheetNames.pl") { $text="names"; } else { die("This script is named '$whoami', but must be named either 'sheetCount.pl' or 'sheetNames.pl' to function properly.\n"); } ## ## Usage information ## $usage = < Output is the $text of sheets in the excel file. EOF ## ## parse arguments ## if(!defined($ARGV[0])) { print $usage; exit 1; } my $fileName=$ARGV[0]; ## ## open spreadsheet ## open(FH, "<$fileName") or die "Unable to open file '$fileName'.\n"; close(FH); my $oBook; ## First try as a Excel 2007+ 'xml' file eval { local $SIG{__WARN__} = sub {}; $oBook = Spreadsheet::XLSX -> new ($ARGV[0]); }; ## Then Excel 97-2004 Format if($@) { $oBook = new Spreadsheet::ParseExcel->Parse($ARGV[0]) or \ die "Error parsing file '$ARGV[0]'.\n"; } if($whoami eq "sheetCount.pl") { print $oBook->{SheetCount} , "\n"; } elsif ($whoami eq "sheetNames.pl") { ## Get list all worksheets in the file my @sheetlist = (@{$oBook->{Worksheet}}); foreach my $sheet (@sheetlist) { print "\"$sheet->{Name}\" "; } print "\n"; } else { die("This script is named '$whoami', but must be named either 'sheetCount.pl' or 'sheetNames.pl' to function properly.\n"); } gdata/inst/perl/module_tools.pl0000755000176000001440000000522612163371440016354 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } use strict; use warnings; use Data::Dumper; use Cwd; sub check_modules(;$) { my( $VERBOSE, $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX ); $VERBOSE=$_[0]; # Check if we can load the libraries we need eval { require Spreadsheet::ParseExcel; $HAS_Spreadsheet_ParseExcel=1; print "Loaded Spreadsheet::ParseExcel\n" if $VERBOSE; }; eval { require Compress::Raw::Zlib; $HAS_Compress_Raw_Zlib=1; print "Loaded Compress::Raw::Zlib\n" if $VERBOSE; }; eval { require Spreadsheet::XLSX; $HAS_Spreadsheet_XLSX=1; print "Loaded Spreadsheet::XLSX\n" if $VERBOSE; }; if($VERBOSE) { print "ERROR: Unable to load Spreadsheet::ParseExcel perl module! \n" if !$HAS_Spreadsheet_ParseExcel; print "ERROR: Unable to load Compress::Raw::Zlib perl module! \n" if ! $HAS_Compress_Raw_Zlib; print "ERROR: Unable to load Spreadsheet::XLSX perl module! \n" if ! $HAS_Spreadsheet_XLSX; } return $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX; } sub check_modules_and_notify() { my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX) = check_modules(0); $HAS_Spreadsheet_ParseExcel or die("ERROR: Perl module Spreadsheet::ParseExcel cannot be loaded. Exiting.\n"); $HAS_Compress_Raw_Zlib or warn("WARNING: Perl module Compress::Raw::Zlib cannot be loaded.\n"); $HAS_Spreadsheet_XLSX or warn("WARNING: Perl module Spreadsheet::XLSX cannot be loaded.\n"); ($HAS_Compress_Raw_Zlib && $HAS_Spreadsheet_XLSX ) or warn("WARNING: Microsoft Excel 2007 'XLSX' formatted files will not be processed.\n"); return $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX; } sub install_modules() { my($mod, $obj, $here); $here = dirname($0); # load the module require CPAN; # initialize CPAN components CPAN::HandleConfig->load(); CPAN::Shell::setup_output(); CPAN::Index->reload(); # set the target install path CPAN::Shell->o("conf", "makepl_arg", "PREFIX=$here LIB=$here --prefix $here --install-base $here"); CPAN::Shell->install("Compress::Raw::Zlib"); #return 0; # install the libraries we want for $mod (qw( Compress::Raw::Zlib Spreadsheet::XLSX )){ my $obj = CPAN::Shell->expand('Module',$mod); $obj->install; } } 1; gdata/inst/perl/install_modules.pl0000644000176000001440000000064212163371440017037 0ustar ripleyusers#!/usr/bin/perl BEGIN { use File::Basename; # Add current path to perl library search path use lib dirname($0); } require 'module_tools.pl'; my( $HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX); # check if we need to do anything ($HAS_Spreadsheet_ParseExcel, $HAS_Compress_Raw_Zlib, $HAS_Spreadsheet_XLSX) = check_modules(0); install_modules() unless $HAS_Compress_Raw_Zlib; gdata/inst/perl/VERSIONS0000644000176000001440000000016211326756030014476 0ustar ripleyusersSpreadSheet::ParseExcel 0.56 Archive::Zip 1.30 IO::Stringy 2.110 OLE::Storage_Lite 0.19 Compress::Raw::Zlib 2.024 gdata/inst/perl/Spreadsheet/0000755000176000001440000000000012024144455015551 5ustar ripleyusersgdata/inst/perl/Spreadsheet/XLSX.pm0000755000176000001440000002004611326770634016722 0ustar ripleyuserspackage Spreadsheet::XLSX; use 5.006000; use strict; use warnings; our @ISA = qw(); our $VERSION = '0.12'; use Archive::Zip; use Spreadsheet::XLSX::Fmt2007; use Data::Dumper; use Spreadsheet::ParseExcel; ################################################################################ sub new { my ($class, $filename, $converter) = @_; my $self = {}; $self -> {zip} = Archive::Zip -> new ($filename) or die ("Cant't open $filename as a zip file\n"); my $member_shared_strings = $self -> {zip} -> memberNamed ('xl/sharedStrings.xml'); my @shared_strings = (); if ($member_shared_strings) { my $mstr = $member_shared_strings->contents; $mstr =~ s//<\/t>/gsm; # this handles an empty t tag in the xml foreach my $si ($mstr =~ /(.*?)<\/si/gsm) { my $str; foreach my $t ($si =~ /(.*?)<\/t/gsm) { $t = $converter -> convert ($t) if $converter; $str .= $t; } push @shared_strings, $str; } } my $member_styles = $self -> {zip} -> memberNamed ('xl/styles.xml'); my @styles = (); my %style_info = (); if ($member_styles) { foreach my $t ($member_styles -> contents =~ /xf\ numFmtId="([^"]*)"(?!.*\/cellStyleXfs)/gsm) { #" # $t = $converter -> convert ($t) if $converter; push @styles, $t; } my $default = $1 || ''; foreach my $t1 (@styles){ $member_styles -> contents =~ /numFmtId="$t1" formatCode="([^"]*)/; my $formatCode = $1 || ''; if ($formatCode eq $default || not($formatCode)){ if ($t1 == 9 || $t1==10){ $formatCode="0.00000%";} elsif ($t1 == 14){ $formatCode="yyyy-mm-dd";} elsif ($t1 == 20){ $formatCode="h:mm";} else { $formatCode=""; } } $style_info{$t1} = $formatCode; $default = $1 || ''; } } my $member_rels = $self -> {zip} -> memberNamed ('xl/_rels/workbook.xml.rels') or die ("xl/_rels/workbook.xml.rels not found in this zip\n"); my %rels = (); foreach ($member_rels -> contents =~ /\/g) { /^Id="(.*?)".*?Target="(.*?)"/ or next; $rels {$1} = $2; } my $member_workbook = $self -> {zip} -> memberNamed ('xl/workbook.xml') or die ("xl/workbook.xml not found in this zip\n"); my $oBook = Spreadsheet::ParseExcel::Workbook->new; $oBook->{SheetCount} = 0; $oBook->{FmtClass} = Spreadsheet::XLSX::Fmt2007->new; $oBook->{Flg1904}=0; if ($member_workbook->contents =~ /date1904="1"/){ $oBook->{Flg1904}=1; } my @Worksheet = (); foreach ($member_workbook -> contents =~ /\<(.*?)\/?\>/g) { /^(\w+)\s+/; my ($tag, $other) = ($1, $'); my @pairs = split /\" /, $other; $tag eq 'sheet' or next; my $sheet = { MaxRow => 0, MaxCol => 0, MinRow => 1000000, MinCol => 1000000, }; foreach ($other =~ /(\S+=".*?")/gsm) { my ($k, $v) = split /=?"/; #" if ($k eq 'name') { $sheet -> {Name} = $v; $sheet -> {Name} = $converter -> convert ($sheet -> {Name}) if $converter; } elsif ($k eq 'r:id') { $sheet -> {path} = $rels {$v}; }; } my $wsheet = Spreadsheet::ParseExcel::Worksheet->new(%$sheet); push @Worksheet, $wsheet; $oBook->{Worksheet}[$oBook->{SheetCount}] = $wsheet; $oBook->{SheetCount}+=1; } $self -> {Worksheet} = \@Worksheet; foreach my $sheet (@Worksheet) { my $member_sheet = $self -> {zip} -> memberNamed ("xl/$sheet->{path}") or next; my ($row, $col); my $flag = 0; my $s = 0; my $s2 = 0; my $sty = 0; foreach ($member_sheet -> contents =~ /(\<.*?\/?\>|.*?(?=\<))/g) { if (/^\"){$v="";} my $type = "Text"; my $thisstyle = ""; if (not($s) && not($s2)){ $type="Numeric"; $thisstyle = $style_info{$styles[$sty]}; if ($thisstyle =~ /(? {MaxRow} = $row if $sheet -> {MaxRow} < $row; $sheet -> {MaxCol} = $col if $sheet -> {MaxCol} < $col; $sheet -> {MinRow} = $row if $sheet -> {MinRow} > $row; $sheet -> {MinCol} = $col if $sheet -> {MinCol} > $col; if ($v =~ /(.*)E\-(.*)/gsm && $type eq "Numeric"){ $v=$1/(10**$2); # this handles scientific notation for very small numbers } my $cell =Spreadsheet::ParseExcel::Cell->new( Val => $v, Format => $thisstyle, Type => $type ); $cell->{_Value} = $oBook->{FmtClass}->ValFmt($cell, $oBook); if ($type eq "Date" && $v<1){ #then this is Excel time field $cell->{Type}="Text"; $cell->{Val}=$cell->{_Value}; } $sheet -> {Cells} [$row] [$col] = $cell; } } $sheet -> {MinRow} = 0 if $sheet -> {MinRow} > $sheet -> {MaxRow}; $sheet -> {MinCol} = 0 if $sheet -> {MinCol} > $sheet -> {MaxCol}; } foreach my $stys (keys %style_info){ } bless ($self, $class); return $oBook; } 1; __END__ =head1 NAME Spreadsheet::XLSX - Perl extension for reading MS Excel 2007 files; =head1 SYNOPSIS use Text::Iconv; my $converter = Text::Iconv -> new ("utf-8", "windows-1251"); # Text::Iconv is not really required. # This can be any object with the convert method. Or nothing. use Spreadsheet::XLSX; my $excel = Spreadsheet::XLSX -> new ('test.xlsx', $converter); foreach my $sheet (@{$excel -> {Worksheet}}) { printf("Sheet: %s\n", $sheet->{Name}); $sheet -> {MaxRow} ||= $sheet -> {MinRow}; foreach my $row ($sheet -> {MinRow} .. $sheet -> {MaxRow}) { $sheet -> {MaxCol} ||= $sheet -> {MinCol}; foreach my $col ($sheet -> {MinCol} .. $sheet -> {MaxCol}) { my $cell = $sheet -> {Cells} [$row] [$col]; if ($cell) { printf("( %s , %s ) => %s\n", $row, $col, $cell -> {Val}); } } } } =head1 DESCRIPTION This module is a (quick and dirty) emulation of Spreadsheet::ParseExcel for Excel 2007 (.xlsx) file format. It supports styles and many of Excel's quirks, but not all. It populates the classes from Spreadsheet::ParseExcel for interoperability; including Workbook, Worksheet, and Cell. =head1 SEE ALSO =over 2 =item Text::CSV_XS, Text::CSV_PP http://search.cpan.org/~hmbrand/ A pure perl version is available on http://search.cpan.org/~makamaka/ =item Spreadsheet::ParseExcel http://search.cpan.org/~kwitknr/ =item Spreadsheet::ReadSXC http://search.cpan.org/~terhechte/ =item Spreadsheet::BasicRead http://search.cpan.org/~gng/ for xlscat likewise functionality (Excel only) =item Spreadsheet::ConvertAA http://search.cpan.org/~nkh/ for an alternative set of cell2cr () / cr2cell () pair =item Spreadsheet::Perl http://search.cpan.org/~nkh/ offers a Pure Perl implementation of a spreadsheet engine. Users that want this format to be supported in Spreadsheet::Read are hereby motivated to offer patches. It's not high on my todo-list. =item xls2csv http://search.cpan.org/~ken/ offers an alternative for my C, in the xls2csv tool, but this tool focusses on character encoding transparency, and requires some other modules. =item Spreadsheet::Read http://search.cpan.org/~hmbrand/ read the data from a spreadsheet (interface module) =back =head1 AUTHOR Dmitry Ovsyanko, Edo@eludia.ru, http://eludia.ru/wiki/ Patches by: Steve Simms Joerg Meltzer Loreyna Yeung Rob Polocz Gregor Herrmann H.Merijn Brand endacoe Pat Mariani =head1 ACKNOWLEDGEMENTS Thanks to TrackVia Inc. (http://www.trackvia.com) for paying for Rob Polocz working time. =head1 COPYRIGHT AND LICENSE Copyright (C) 2008 by Dmitry Ovsyanko This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. =cut gdata/inst/perl/Spreadsheet/XLSX/0000755000176000001440000000000012164457166016362 5ustar ripleyusersgdata/inst/perl/Spreadsheet/XLSX/Utility2007.pm0000755000176000001440000011026611326756553020706 0ustar ripleyusers# This code is adapted for Excel 2007 from: # Spreadsheet::XLSX::Utility # by Kawai, Takanori (Hippo2000) 2001.2.2 # This Program is ALPHA version. #============================================================================== # Spreadsheet::XLSX::Utility; #============================================================================== package Spreadsheet::XLSX::Utility2007; use strict; use warnings; require Exporter; use vars qw(@ISA @EXPORT_OK); @ISA = qw(Exporter); @EXPORT_OK = qw(ExcelFmt LocaltimeExcel ExcelLocaltime col2int int2col sheetRef xls2csv); our $VERSION = '0.12'; my $sNUMEXP = '(^[+-]?\d+(\.\d+)?$)|(^[+-]?\d+\.?(\d*)[eE][+-](\d+))$'; #------------------------------------------------------------------------------ # ExcelFmt (for Spreadsheet::XLSX::Utility2007) #------------------------------------------------------------------------------ sub ExcelFmt { my($sFmt, $iData, $i1904, $sType) =@_; my $sCond; my $sWkF =''; my $sRes=''; $sFmt=unescape_HTML($sFmt); #1. Get Condition if($sFmt=~/^\[([<>=][^\]]+)\](.*)$/) { $sCond = $1; $sFmt = $2; } $sFmt =~ s/_/ /g; my @sFmtWk; my $sFmtObj; my $iFmtPos=0; my $iDblQ=0; my $iQ = 0; foreach my $sWk (split //, $sFmt) { if($iDblQ or $iQ) { $sFmtWk[$iFmtPos] .=$sWk; $iDblQ = 0 if($sWk eq '"'); $iQ = 0; next; } if($sWk eq ';') { $iFmtPos++; next; } elsif($sWk eq '"') { $iDblQ = 1; } elsif($sWk eq '!') { $iQ = 1; } elsif($sWk eq '\\') { $iQ = 1; # next; } elsif($sWk eq '(') { #Skip? next; } elsif($sWk eq ')') { #Skip? next; } $sFmtWk[$iFmtPos] .=$sWk; } #Get FmtString if(scalar(@sFmtWk)>1) { if($sCond) { $sFmtObj = $sFmtWk[((eval(qq/"$iData" $sCond/))? 0: 1)]; } else { my $iWk = ($iData =~/$sNUMEXP/)? $iData: 0; # $iData = abs($iData) if($iWk !=0); if(scalar(@sFmtWk)==2) { $sFmtObj = $sFmtWk[(($iWk>=0)? 0: 1)]; } elsif(scalar(@sFmtWk)==3) { $sFmtObj = $sFmtWk[(($iWk>0)? 0: (($iWk<0)? 1: 2))]; } else { if($iData =~/$sNUMEXP/) { $sFmtObj = $sFmtWk[(($iWk>0)? 0: (($iWk<0)? 1: 2))]; } else { $sFmtObj = $sFmtWk[ 3]; } } } } else { $sFmtObj = $sFmtWk[0]; } my $sColor; if($sFmtObj =~ /^(\[[^hm\[\]]*\])/) { $sColor = $1; $sFmtObj = substr($sFmtObj, length($sColor)); chop($sColor); $sColor = substr($sColor, 1); } #print "FMT:$sFmtObj Co:$sColor\n"; #3.Build Data my $iFmtMode=0; #1:Number, 2:Date my $i=0; my $ir=0; my $sFmtWk; my @aRep = (); my $sFmtRes=''; my $iFflg = -1; my $iRpos = -1; my $iCmmCnt = 0; my $iBunFlg = 0; my $iFugouFlg = 0; my $iPer = 0; my $iAm=0; my $iSt; while($i=0) && (($aRep[$#aRep]->[0] eq 'h') or ($aRep[$#aRep]->[0] eq 'hh'))) { push @aRep, ['mm', length($sFmtRes), 2, 'min']; } else { push @aRep, [substr($sFmtObj, $i, 2), length($sFmtRes), 2]; } if((substr($sFmtObj, $i, 2) eq 'ss') && ($#aRep>0)) { if(($aRep[$#aRep-1]->[0] eq 'm') || ($aRep[$#aRep-1]->[0] eq 'mm')) { push(@{$aRep[$#aRep-1]}, 'min'); } } $i+=2; } elsif((substr($sFmtObj, $i, 1) eq 'm') || (substr($sFmtObj, $i, 1) eq 'd') || (substr($sFmtObj, $i, 1) eq 'h') || (substr($sFmtObj, $i, 1) eq 's')){ if((substr($sFmtObj, $i, 1) eq 'm') && ($#aRep>=0) && (($aRep[$#aRep]->[0] eq 'h') or ($aRep[$#aRep]->[0] eq 'hh'))) { push @aRep, ['m', length($sFmtRes), 1, 'min']; } else { push @aRep, [substr($sFmtObj, $i, 1), length($sFmtRes), 1]; } if((substr($sFmtObj, $i, 1) eq 's') && ($#aRep>0)) { if(($aRep[$#aRep-1]->[0] eq 'm') || ($aRep[$#aRep-1]->[0] eq 'mm')) { push(@{$aRep[$#aRep-1]}, 'min'); } } $i+=1; } } elsif((substr($sFmtObj, $i, 3) eq '[h]')) { push @aRep, ['[h]', length($sFmtRes), 3]; $i+=3; } elsif((substr($sFmtObj, $i, 4) eq '[mm]')) { push @aRep, ['[mm]', length($sFmtRes), 4]; $i+=4; } elsif($sWk eq '@') { push @aRep, ['@', length($sFmtRes), 1]; $i++; } elsif($sWk eq '*') { push @aRep, [substr($sFmtObj, $i, 1), length($sFmtRes), 1]; } else{ $i++; } $i++ if($i == $iSt); #No Format match $sFmtRes .= substr($sFmtObj, $iSt, $i-$iSt); } #print "FMT: $iRpos ",$sFmtRes, "\n"; if($iFflg != -1) { push @aRep, [substr($sFmtObj, $iFflg, $i-$iFflg+1), $iRpos,, $i-$iFflg+1]; $iFflg= 0; } #For Date format $iFmtMode = 0 if(defined $sType && $sType eq 'Text'); #Not Convert Non Numeric if(($iFmtMode==2)&& ($iData =~/$sNUMEXP/)) { my @aTime = ExcelLocaltime($iData, $i1904); $aTime[4]++; $aTime[5] += 1900; my @aMonL = qw (dum January February March April May June July August September October November December ); my @aMonNm = qw (dum Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); my @aWeekNm = qw (Mon Tue Wed Thu Fri Sat Sun); my @aWeekL = qw (Monday Tuesday Wednesday Thursday Friday Saturday Sunday); my $sRep; for(my $iIt=$#aRep; $iIt>=0;$iIt--) { my $rItem = $aRep[$iIt]; if((scalar @$rItem) >=4) { #Min if($rItem->[0] eq 'mm') { $sRep = sprintf("%02d", $aTime[1]); } else { $sRep = sprintf("%d", $aTime[1]); } } #Year elsif($rItem->[0] eq 'yyyy') { $sRep = sprintf('%04d', $aTime[5]); } elsif($rItem->[0] eq 'yy') { $sRep = sprintf('%02d', $aTime[5] % 100); } #Mon elsif($rItem->[0] eq 'mmmmm') { $sRep = substr($aMonNm[$aTime[4]], 0, 1); } elsif($rItem->[0] eq 'mmmm') { $sRep = $aMonL[$aTime[4]]; } elsif($rItem->[0] eq 'mmm') { $sRep = $aMonNm[$aTime[4]]; } elsif($rItem->[0] eq 'mm') { $sRep = sprintf('%02d', $aTime[4]); } elsif($rItem->[0] eq 'm') { $sRep = sprintf('%d', $aTime[4]); } #Day elsif($rItem->[0] eq 'dddd') { $sRep = $aWeekL[$aTime[7]]; } elsif($rItem->[0] eq 'ddd') { $sRep = $aWeekNm[$aTime[7]]; } elsif($rItem->[0] eq 'dd') { $sRep = sprintf('%02d', $aTime[3]); } elsif($rItem->[0] eq 'd') { $sRep = sprintf('%d', $aTime[3]); } #Hour elsif($rItem->[0] eq 'hh') { if($iAm) { $sRep = sprintf('%02d', $aTime[2]%12); } else { $sRep = sprintf('%02d', $aTime[2]); } } elsif($rItem->[0] eq 'h') { if($iAm) { $sRep = sprintf('%d', $aTime[2]%12); } else { $sRep = sprintf('%d', $aTime[2]); } } #SS elsif($rItem->[0] eq 'ss') { $sRep = sprintf('%02d', $aTime[0]); } elsif($rItem->[0] eq 'S') { $sRep = sprintf('%d', $aTime[0]); } #am/pm elsif($rItem->[0] eq 'am/pm') { $sRep = ($aTime[4]>12)? 'pm':'am'; } elsif($rItem->[0] eq 'a/p') { $sRep = ($aTime[4]>12)? 'p':'a'; } elsif($rItem->[0] eq '.') { $sRep = '.'; } elsif($rItem->[0] =~ /^0+$/) { my $i0Len = length($&); #print "SEC:", $aTime[7], "\n"; $sRep = substr(sprintf("%.${i0Len}f", $aTime[7]/1000.0), 2, $i0Len); } elsif($rItem->[0] eq '[h]') { $sRep = sprintf('%d', int($iData) * 24 + $aTime[2]); } elsif($rItem->[0] eq '[mm]') { $sRep = sprintf('%d', (int($iData) * 24 + $aTime[2])*60 + $aTime[1]); } #NENGO(Japanese) elsif($rItem->[0] eq 'ge') { $sRep = Spreadsheet::XLSX::FmtJapan::CnvNengo(1, @aTime); } elsif($rItem->[0] eq 'ggge') { $sRep = Spreadsheet::XLSX::FmtJapan::CnvNengo(2, @aTime); } elsif($rItem->[0] eq '@') { $sRep = $iData; } #print "REP:$sRep ",$rItem->[0], ":", $rItem->[1], ":" ,$rItem->[2], "\n"; substr($sFmtRes, $rItem->[1], $rItem->[2]) = $sRep; } } elsif(($iFmtMode==1)&& ($iData =~/$sNUMEXP/)) { if($#aRep>=0) { while($aRep[$#aRep]->[0] eq ',') { $iCmmCnt--; substr($sFmtRes, $aRep[$#aRep]->[1], $aRep[$#aRep]->[2]) = ''; $iData /= 1000; pop @aRep; } my $sNumFmt = join('', map {$_->[0]} @aRep); my $sNumRes; my $iTtl=0; my $iE=0; my $iP=0; my $iInt = 0; my $iAftP=undef; foreach my $sItem (split //, $sNumFmt) { if($sItem eq '.') { $iTtl++; $iP = 1; } elsif(($sItem eq 'E') || ($sItem eq 'e')){ $iE = 1; } elsif($sItem eq '0') { $iTtl++; $iAftP++ if($iP); $iInt = 1; } elsif($sItem eq '#') { #$iTtl++; $iAftP++ if($iP); $iInt = 1; } elsif($sItem eq '?') { #$iTtl++; $iAftP++ if($iP); } } $iData *= 100.0 if($iPer); my $iDData = ($iFugouFlg)? abs($iData) : $iData+0; if($iBunFlg) { $sNumRes = sprintf("%0${iTtl}d", int($iDData)); } else { if($iP) { $sNumRes = sprintf( (defined($iAftP)? "%0${iTtl}.${iAftP}f": "%0${iTtl}f"), $iDData); } else { $sNumRes = sprintf("%0${iTtl}.0f", $iDData); } } $sNumRes = AddComma($sNumRes) if($iCmmCnt > 0); my $iLen = length($sNumRes); my $iPPos = -1; my $sRep; for(my $iIt=$#aRep; $iIt>=0;$iIt--) { my $rItem = $aRep[$iIt]; if($rItem->[0] =~/([#0]*)([\.]?)([0#]*)([eE])([\+\-])([0#]+)/) { substr($sFmtRes, $rItem->[1], $rItem->[2]) = MakeE($rItem->[0], $iData); } elsif($rItem->[0] =~ /\//) { substr($sFmtRes, $rItem->[1], $rItem->[2]) = MakeBun($rItem->[0], $iData, $iInt); } elsif($rItem->[0] eq '.') { $iLen--; $iPPos=$iLen; } elsif($rItem->[0] eq '+') { substr($sFmtRes, $rItem->[1], $rItem->[2]) = ($iData > 0)? '+': (($iData==0)? '+':'-'); } elsif($rItem->[0] eq '-') { substr($sFmtRes, $rItem->[1], $rItem->[2]) = ($iData > 0)? '': (($iData==0)? '':'-'); } elsif($rItem->[0] eq '@') { substr($sFmtRes, $rItem->[1], $rItem->[2]) = $iData; } elsif($rItem->[0] eq '*') { substr($sFmtRes, $rItem->[1], $rItem->[2]) = ''; #REMOVE } elsif(($rItem->[0] eq "\xA2\xA4") or ($rItem->[0] eq "\xA2\xA5") or ($rItem->[0] eq "\x81\xA2") or ($rItem->[0] eq "\x81\xA3") ){ substr($sFmtRes, $rItem->[1], $rItem->[2]) = $rItem->[0]; } elsif(($rItem->[0] eq '(') or ($rItem->[0] eq ')')){ substr($sFmtRes, $rItem->[1], $rItem->[2]) = $rItem->[0]; } else { if($iLen>0) { if($iIt <= 0) { $sRep = substr($sNumRes, 0, $iLen); $iLen = 0; } else { my $iReal = length($rItem->[0]); if($iPPos >= 0) { my $sWkF = $rItem->[0]; $sWkF=~s/^#+//; $iReal = length($sWkF); $iReal = ($iLen <=$iReal)? $iLen:$iReal; } else { $iReal = ($iLen <=$iReal)? $iLen:$iReal; } $sRep = substr($sNumRes, $iLen - $iReal, $iReal); $iLen -=$iReal; } } else { $sRep = ''; } substr($sFmtRes, $rItem->[1], $rItem->[2]) = "\x00" . $sRep; } } $sRep = ($iLen > 0)?substr($sNumRes, 0, $iLen) : ''; $sFmtRes =~ s/\x00/$sRep/; $sFmtRes =~ s/\x00//g; } } else { my $iAtMk = 0; for(my $iIt=$#aRep; $iIt>=0;$iIt--) { my $rItem = $aRep[$iIt]; if($rItem->[0] eq '@') { substr($sFmtRes, $rItem->[1], $rItem->[2]) = $iData; $iAtMk++; } else { substr($sFmtRes, $rItem->[1], $rItem->[2]) = ''; } } $sFmtRes = $iData unless($iAtMk); } return wantarray()? ($sFmtRes, $sColor) : $sFmtRes; } #------------------------------------------------------------------------------ # AddComma (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ sub AddComma { my($sNum) = @_; if($sNum=~ /^([^\d]*)(\d\d\d\d+)(\.*.*)$/) { my($sPre, $sObj, $sAft) =($1, $2, $3); for(my $i=length($sObj)-3;$i>0; $i-=3) { substr($sObj, $i, 0) = ','; } return $sPre . $sObj . $sAft; } else { return $sNum; } } #------------------------------------------------------------------------------ # MakeBun (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ sub MakeBun { my($sFmt, $iData, $iFlg) = @_; my $iBunbo; my $iShou; #1. Init #print "FLG: $iFlg\n"; if($iFlg) { $iShou = $iData - int($iData); return '' if($iShou == 0); } else { $iShou = $iData; } $iShou = abs($iShou); my $sSWk; #2.Calc BUNBO #2.1 BUNBO defined if($sFmt =~ /\/(\d+)$/) { $iBunbo = $1; return sprintf("%d/%d", $iShou*$iBunbo, $iBunbo); } else { #2.2 Calc BUNBO $sFmt =~ /\/(\?+)$/; my $iKeta = length($1); my $iSWk = 1; my $sSWk = ''; my $iBunsi; for(my $iBunbo = 2;$iBunbo<10**$iKeta;$iBunbo++) { $iBunsi = int($iShou*$iBunbo + 0.5); my $iCmp = abs($iShou - ($iBunsi/$iBunbo)); if($iCmp < $iSWk) { $iSWk =$iCmp; $sSWk = sprintf("%d/%d", $iBunsi, $iBunbo); last if($iSWk==0); } } return $sSWk; } } #------------------------------------------------------------------------------ # MakeE (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ sub MakeE { my($sFmt, $iData) = @_; $sFmt=~/(([#0]*)[\.]?[#0]*)([eE])([\+\-][0#]+)/; my($sKari, $iKeta, $sE, $sSisu) = ($1, length($2), $3, $4); $iKeta = 1 if($iKeta<=0); my $iLog10 = 0; $iLog10 = ($iData == 0)? 0 : (log(abs($iData))/ log(10)); $iLog10 = (int($iLog10 / $iKeta) + ((($iLog10 - int($iLog10 / $iKeta))<0)? -1: 0)) *$iKeta; my $sUe = ExcelFmt($sKari, $iData*(10**($iLog10*-1)),0); my $sShita = ExcelFmt($sSisu, $iLog10, 0); return $sUe . $sE . $sShita; } #------------------------------------------------------------------------------ # LeapYear (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ sub LeapYear { my($iYear)=@_; return 1 if($iYear==1900); #Special for Excel return ((($iYear % 4)==0) && (($iYear % 100) || ($iYear % 400)==0))? 1: 0; } #------------------------------------------------------------------------------ # LocaltimeExcel (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ sub LocaltimeExcel { my($iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iMSec, $flg1904) = @_; #0. Init $iMon++; $iYear+=1900; #1. Calc Time my $iTime; $iTime =$iHour; $iTime *=60; $iTime +=$iMin; $iTime *=60; $iTime +=$iSec; $iTime += $iMSec/1000.0 if(defined($iMSec)) ; $iTime /= 86400.0; #3600*24(1day in seconds) my $iY; my $iYDays; #2. Calc Days if($flg1904) { $iY = 1904; $iTime--; #Start from Jan 1st $iYDays = 366; } else { $iY = 1900; $iYDays = 366; #In Excel 1900 is leap year (That's not TRUE!) } while($iY<$iYear) { $iTime += $iYDays; $iY++; $iYDays = (LeapYear($iY))? 366: 365; } for(my $iM=1;$iM < $iMon; $iM++){ if($iM == 1 || $iM == 3 || $iM == 5 || $iM == 7 || $iM == 8 || $iM == 10 || $iM == 12) { $iTime += 31; } elsif($iM == 4 || $iM == 6 || $iM == 9 || $iM == 11) { $iTime += 30; } elsif($iM == 2) { $iTime += (LeapYear($iYear))? 29: 28; } } $iTime+=$iDay; return $iTime; } #------------------------------------------------------------------------------ # ExcelLocaltime (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ sub ExcelLocaltime { my($dObj, $flg1904) = @_; my($iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iwDay, $iMSec); my($iDt, $iTime, $iYDays); $iDt = int($dObj); $iTime = $dObj - $iDt; #1. Calc Days if($flg1904) { $iYear = 1904; $iDt++; #Start from Jan 1st $iYDays = 366; $iwDay = (($iDt+4) % 7); } else { $iYear = 1900; $iYDays = 366; #In Excel 1900 is leap year (That's not TRUE!) $iwDay = (($iDt+6) % 7); } while($iDt > $iYDays) { $iDt -= $iYDays; $iYear++; $iYDays = ((($iYear % 4)==0) && (($iYear % 100) || ($iYear % 400)==0))? 366: 365; } $iYear -= 1900; for($iMon=1;$iMon < 12; $iMon++){ my $iMD; if($iMon == 1 || $iMon == 3 || $iMon == 5 || $iMon == 7 || $iMon == 8 || $iMon == 10 || $iMon == 12) { $iMD = 31; } elsif($iMon == 4 || $iMon == 6 || $iMon == 9 || $iMon == 11) { $iMD = 30; } elsif($iMon == 2) { $iMD = (($iYear % 4) == 0)? 29: 28; } last if($iDt <= $iMD); $iDt -= $iMD; } #2. Calc Time $iDay = $iDt; $iTime += (0.0005 / 86400.0); $iTime*=24.0; $iHour = int($iTime); $iTime -= $iHour; $iTime *= 60.0; $iMin = int($iTime); $iTime -= $iMin; $iTime *= 60.0; $iSec = int($iTime); $iTime -= $iSec; $iTime *= 1000.0; $iMSec = int($iTime); return ($iSec, $iMin, $iHour, $iDay, $iMon-1, $iYear, $iwDay, $iMSec); } # ----------------------------------------------------------------------------- # col2int (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ # converts a excel row letter into an int for use in an array sub col2int { my $result = 0 ; my $str = shift ; my $incr = 0 ; for(my $i = length($str) ; $i > 0 ; $i--) { my $char = substr( $str, $i-1) ; my $curr += ord(lc($char)) - ord('a') + 1; $curr *= $incr if( $incr) ; $result += $curr ; $incr += 26 ; } # this is one out as we range 0..x-1 not 1..x $result-- ; return $result ; } # ----------------------------------------------------------------------------- # int2col (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ ### int2col # convert a column number into column letters # @note this is quite a brute force coarse method # does not manage values over 701 (ZZ) # @arg number, to convert # @returns string, column name # sub int2col { my $out = "" ; my $val = shift ; do { $out .= chr(( $val % 26) + ord('A')) ; $val = int( $val / 26) - 1 ; } while( $val >= 0) ; return reverse $out ; } # ----------------------------------------------------------------------------- # sheetRef (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ # ----------------------------------------------------------------------------- ### sheetRef # convert an excel letter-number address into a useful array address # @note that also Excel uses X-Y notation, we normally use Y-X in arrays # @args $str, excel coord eg. A2 # @returns an array - 2 elements - column, row, or undefined # sub sheetRef { my $str = shift ; my @ret ; $str =~ m/^(\D+)(\d+)$/ ; if( $1 && $2) { push( @ret, $2 -1, col2int($1)) ; } if( $ret[0] < 0) { undef @ret ; } return @ret ; } # ----------------------------------------------------------------------------- # xls2csv (for Spreadsheet::XLSX::Utility) #------------------------------------------------------------------------------ ### xls2csv # convert a chunk of an excel file into csv text chunk # @args $param, sheet-colrow:colrow (1-A1:B2 or A1:B2 for sheet 1 # @args $rotate, 0 or 1 decides if output should be rotated or not # @returns string containing a chunk of csv # sub xls2csv { my ($filename, $regions, $rotate) = @_ ; my $sheet = 0 ; my $output = "" ; # extract any sheet number from the region string $regions =~ m/^(\d+)-(.*)/ ; if( $2) { $sheet = $1 - 1 ; $regions = $2 ; } # now extract the start and end regions $regions =~ m/(.*):(.*)/ ; if( !$1 || !$2) { print STDERR "Bad Params"; return "" ; } my @start = sheetRef( $1) ; my @end = sheetRef( $2) ; if( !@start) { print STDERR "Bad coorinates - $1"; return "" ; } if( !@end) { print STDERR "Bad coorinates - $2"; return "" ; } if( $start[1] > $end[1]) { print STDERR "Bad COLUMN ordering\n"; print STDERR "Start column " . int2col($start[1]); print STDERR " after end column " . int2col($end[1]) . "\n"; return "" ; } if( $start[0] > $end[0]) { print STDERR "Bad ROW ordering\n"; print STDERR "Start row " . ($start[0] + 1); print STDERR " after end row " . ($end[0] + 1) . "\n"; exit ; } # start the excel object now my $oExcel = new Spreadsheet::XLSX ; my $oBook = $oExcel->Parse( $filename) ; # open the sheet my $oWkS = $oBook->{Worksheet}[ $sheet] ; # now check that the region exists in the file # if not trucate to the possible region # output a warning msg if( $start[1] < $oWkS->{MinCol}) { print STDERR int2col( $start[1]) . " < min col " . int2col( $oWkS->{MinCol}) . " Reseting\n"; $start[1] = $oWkS->{MinCol} ; } if( $end[1] > $oWkS->{MaxCol}) { print STDERR int2col( $end[1]) . " > max col " . int2col( $oWkS->{MaxCol}) . " Reseting\n" ; $end[1] = $oWkS->{MaxCol} ; } if( $start[0] < $oWkS->{MinRow}) { print STDERR "" . ($start[0] + 1) . " < min row " . ($oWkS->{MinRow} + 1) . " Reseting\n"; $start[0] = $oWkS->{MinCol} ; } if( $end[0] > $oWkS->{MaxRow}) { print STDERR "" . ($end[0] + 1) . " > max row " . ($oWkS->{MaxRow} + 1) . " Reseting\n"; $end[0] = $oWkS->{MaxRow} ; } my $x1 = $start[1] ; my $y1 = $start[0] ; my $x2 = $end[1] ; my $y2 = $end[0] ; if( !$rotate) { for( my $y = $y1 ; $y <= $y2 ; $y++) { for( my $x = $x1 ; $x <= $x2 ; $x++) { my $cell = $oWkS->{Cells}[$y][$x] ; $output .= $cell->Value if(defined $cell); $output .= "," if( $x != $x2) ; } $output .= "\n" ; } } else { for( my $x = $x1 ; $x <= $x2 ; $x++) { for( my $y = $y1 ; $y <= $y2 ; $y++) { my $cell = $oWkS->{Cells}[$y][$x] ; $output .= $cell->Value if(defined $cell); $output .= "," if( $y != $y2) ; } $output .= "\n" ; } } return $output ; } sub unescape_HTML { my $string = shift; my %options = @_; return $string if ($string eq ''); $string =~ s/"/"/g; $string =~ s/’/'/g; $string =~ s/&/&/g; return $string if $options{textarea}; # for textboxes, we leave < and > as < and > # so that people who enter "" into # our text boxes can't break forms $string =~ s/<//g; return $string; } 1; __END__ =head1 NAME Spreadsheet::XLSX::Utility2007 - Utility function for Spreadsheet::XLSX =head1 SYNOPSIS use strict; #Declare use Spreadsheet::XLSX::Utility qw(ExcelFmt ExcelLocaltime LocaltimeExcel); #Convert localtime ->Excel Time my $iBirth = LocaltimeExcel(11, 10, 12, 23, 2, 64); # = 1964-3-23 12:10:11 print $iBirth, "\n"; # 23459.5070717593 #Convert Excel Time -> localtime my @aBirth = ExcelLocaltime($iBirth, undef); print join(":", @aBirth), "\n"; # 11:10:12:23:2:64:1:0 #Formatting print ExcelFmt('yyyy-mm-dd', $iBirth), "\n"; #1964-3-23 print ExcelFmt('m-d-yy', $iBirth), "\n"; # 3-23-64 print ExcelFmt('#,##0', $iBirth), "\n"; # 23,460 print ExcelFmt('#,##0.00', $iBirth), "\n"; # 23,459.51 print ExcelFmt('"My Birthday is (m/d):" m/d', $iBirth), "\n"; # My Birthday is (m/d): 3/23 =head1 DESCRIPTION Spreadsheet::XLSX::Utility exports utility functions concerned with Excel format setting. ExcelFmt is used by Spreadsheet::XLSX::Fmt2007.pm which is used by Spreadsheet::XLSX. =head1 Functions This module can export 3 functions: ExcelFmt, ExcelLocaltime and LocaltimeExcel. =head2 ExcelFmt $sTxt = ExcelFmt($sFmt, $iData [, $i1904]); I<$sFmt> is a format string for Excel. I<$iData> is the target value. If I<$flg1904> is true, this functions assumes that epoch is 1904. I<$sTxt> is the result. For more detail and examples, please refer sample/chkFmt.pl in this distribution. ex. =head2 ExcelLocaltime ($iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iwDay, $iMSec) = ExcelLocaltime($iExTime [, $flg1904]); I converts time information in Excel format into Perl localtime format. I<$iExTime> is a time of Excel. If I<$flg1904> is true, this functions assumes that epoch is 1904. I<$iSec>, I<$iMin>, I<$iHour>, I<$iDay>, I<$iMon>, I<$iYear>, I<$iwDay> are same as localtime. I<$iMSec> means 1/1,000,000 seconds(ms). =head2 LocaltimeExcel I<$iExTime> = LocaltimeExcel($iSec, $iMin, $iHour, $iDay, $iMon, $iYear [,$iMSec] [,$flg1904]) I converts time information in Perl localtime format into Excel format . I<$iSec>, I<$iMin>, I<$iHour>, I<$iDay>, I<$iMon>, I<$iYear> are same as localtime. If I<$flg1904> is true, this functions assumes that epoch is 1904. I<$iExTime> is a time of Excel. =head2 col2int I<$iInt> = col2int($sCol); converts a excel row letter into an int for use in an array This function was contributed by Kevin Mulholland. =head2 int2col I<$sCol> = int2col($iRow); convert a column number into column letters NOET: This is quite a brute force coarse method does not manage values over 701 (ZZ) This function was contributed by Kevin Mulholland. =head2 sheetRef (I<$iRow>, I<$iCol>) = sheetRef($sStr); convert an excel letter-number address into a useful array address NOTE: That also Excel uses X-Y notation, we normally use Y-X in arrays $sStr, excel coord (eg. A2). This function was contributed by Kevin Mulholland. =head2 xls2csv $sCsvTxt = xls2csv($sFileName, $sRegion, $iRotate); convert a chunk of an excel file into csv text chunk $sRegions = "sheet-colrow:colrow" (ex. '1-A1:B2' means 'A1:B2' for sheet 1) $iRotate = 0 or 1 (output should be rotated or not) This function was contributed by Kevin Mulholland. =head1 AUTHOR Rob Polocz rob.polocz@trackvia.com based on work by for Spreadsheet::ParseExcel by Kawai Takanori (Hippo2000) used with permission =head1 SEE ALSO Spreadsheet::ParseExcel, Spreadsheet::WriteExcel =head1 COPYRIGHT This module is part of the Spreadsheet::XLSX distribution. =cut gdata/inst/perl/Spreadsheet/XLSX/Fmt2007.pm0000755000176000001440000001345211326760237017762 0ustar ripleyusers# This code is adapted for Excel 2007 from: # Spreadsheet::XLSX::FmtDefault # by Kawai, Takanori (Hippo2000) 2001.2.2 # This Program is ALPHA version. #============================================================================== package Spreadsheet::XLSX::Fmt2007; use strict; use warnings; use POSIX; use Spreadsheet::XLSX::Utility2007 qw(ExcelFmt); our $VERSION = '0.12'; # my %hFmtDefault = ( 0x00 => '@', 0x01 => '0', 0x02 => '0.00', 0x03 => '#,##0', 0x04 => '#,##0.00', 0x05 => '($#,##0_);($#,##0)', 0x06 => '($#,##0_);[RED]($#,##0)', 0x07 => '($#,##0.00_);($#,##0.00_)', 0x08 => '($#,##0.00_);[RED]($#,##0.00_)', 0x09 => '0%', 0x0A => '0.00%', 0x0B => '0.00E+00', 0x0C => '# ?/?', 0x0D => '# ??/??', 0x0E => 'm-d-yy', 0x0F => 'd-mmm-yy', 0x10 => 'd-mmm', 0x11 => 'mmm-yy', 0x12 => 'h:mm AM/PM', 0x13 => 'h:mm:ss AM/PM', 0x14 => 'h:mm', 0x15 => 'h:mm:ss', 0x16 => 'm-d-yy h:mm', #0x17-0x24 -- Differs in National 0x25 => '(#,##0_);(#,##0)', 0x26 => '(#,##0_);[RED](#,##0)', 0x27 => '(#,##0.00);(#,##0.00)', 0x28 => '(#,##0.00);[RED](#,##0.00)', 0x29 => '_(*#,##0_);_(*(#,##0);_(*"-"_);_(@_)', 0x2A => '_($*#,##0_);_($*(#,##0);_(*"-"_);_(@_)', 0x2B => '_(*#,##0.00_);_(*(#,##0.00);_(*"-"??_);_(@_)', 0x2C => '_($*#,##0.00_);_($*(#,##0.00);_(*"-"??_);_(@_)', 0x2D => 'mm:ss', 0x2E => '[h]:mm:ss', 0x2F => 'mm:ss.0', 0x30 => '##0.0E+0', 0x31 => '@', ); #------------------------------------------------------------------------------ # new (for Spreadsheet::XLSX::FmtDefault) #------------------------------------------------------------------------------ sub new { my($sPkg, %hKey) = @_; my $oThis={ }; bless $oThis; return $oThis; } #------------------------------------------------------------------------------ # TextFmt (for Spreadsheet::XLSX::FmtDefault) #------------------------------------------------------------------------------ sub TextFmt { my($oThis, $sTxt, $sCode) =@_; return $sTxt if((! defined($sCode)) || ($sCode eq '_native_')); return pack('U*', unpack('n*', $sTxt)); } #------------------------------------------------------------------------------ # FmtStringDef (for Spreadsheet::XLSX::FmtDefault) #------------------------------------------------------------------------------ sub FmtStringDef { my($oThis, $iFmtIdx, $oBook, $rhFmt) =@_; my $sFmtStr = $oBook->{FormatStr}->{$iFmtIdx}; if(!(defined($sFmtStr)) && defined($rhFmt)) { $sFmtStr = $rhFmt->{$iFmtIdx}; } $sFmtStr = $hFmtDefault{$iFmtIdx} unless($sFmtStr); return $sFmtStr; } #------------------------------------------------------------------------------ # FmtString (for Spreadsheet::XLSX::FmtDefault) #------------------------------------------------------------------------------ sub FmtString { my($oThis, $oCell, $oBook) =@_; my $sFmtStr;# = $oThis->FmtStringDef( # $oBook->{Format}[$oCell->{FormatNo}]->{FmtIdx}, $oBook); unless(defined($sFmtStr)) { if ($oCell->{Type} eq 'Numeric') { if($oCell->{Format}){ $sFmtStr=$oCell->{Format}; } # Integer elsif( isdigit($oCell->{Val}) ){ $sFmtStr = '0'; } # Floating Point else{ $sFmtStr = '0.000000000000000'; } } elsif($oCell->{Type} eq 'Date') { if($oCell->{Format}){ $sFmtStr=$oCell->{Format}; } # Fraction < 1 --> Time elsif(int($oCell->{Val}) <= 0){ $sFmtStr = 'hh:mm:ss'; } # Whole number --> Date elsif(int($oCell->{Val}) != $oCell->{Val}){ $sFmtStr = 'hh:mm:ss'; } # Otherwise both Date and Time else { $sFmtStr = 'mm-dd-yyyy hh:mm:ss'; } } elsif($oCell->{Type} eq 'Time') { if($oCell->{Format}) { $sFmtStr=$oCell->{Format}; } elsif(int($oCell->{Val}) <= 0) { $sFmtStr = 'hh:mm:ss'; } } else { $sFmtStr = '@'; } } return $sFmtStr; } #------------------------------------------------------------------------------ # ValFmt (for Spreadsheet::XLSX::FmtDefault) #------------------------------------------------------------------------------ sub ValFmt { my($oThis, $oCell, $oBook) =@_; my($Dt, $iFmtIdx, $iNumeric, $Flg1904); if ($oCell->{Type} eq 'Text') { $Dt = ((defined $oCell->{Val}) && ($oCell->{Val} ne ''))? $oThis->TextFmt($oCell->{Val}, $oCell->{Code}):''; } else { $Dt = $oCell->{Val}; } $Flg1904 = $oBook->{Flg1904}; my $sFmtStr = $oThis->FmtString($oCell, $oBook); return ExcelFmt($sFmtStr, $Dt, $Flg1904, $oCell->{Type}); } #------------------------------------------------------------------------------ # ChkType (for Spreadsheet::XLSX::FmtDefault) #------------------------------------------------------------------------------ sub ChkType { my($oPkg, $iNumeric, $iFmtIdx) =@_; if ($iNumeric) { if((($iFmtIdx >= 0x0E) && ($iFmtIdx <= 0x16)) || (($iFmtIdx >= 0x2D) && ($iFmtIdx <= 0x2F))) { return "Date"; } else { return "Numeric"; } } else { return "Text"; } } 1; __END__ =head1 SYNOPSIS $cell = $myworkbook->worksheet->{Cells}[$row][$col] my $type = $cell->{Type}; # Date, Text, or Numeric my $disp_value = $cell->Value; # displayed (formatted) value set in XLSX by $myFmt2007->ValFmt($cell, $workbook) my $fund_value = $cell->{Val}; # fundemental (underlying) value my $formatter; if ($myworkbook->excel07) { $formatter=Spreadsheet::XLSX::Fmt2007->new(); } else { $formatter=Spreadsheet::ParseExcel::FmtDefault->new(); } my $format_string = $formatter->FmtString($cell,$self->workbook); =cut gdata/inst/perl/Spreadsheet/README-XLS0000755000176000001440000000113411326733403017100 0ustar ripleyusersSpreadsheet-XLSC version 0.01 ============================= Spreadsheet::XLSX - Perl extension for reading MS Excel 2007 files; INSTALLATION To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES This module requires these other modules and libraries: Archive::Zip COPYRIGHT AND LICENCE Copyright (C) 2008 by Dmitry Ovsyanko This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available. gdata/inst/perl/Spreadsheet/README-ParseExcel0000644000176000001440000000453411326734150020471 0ustar ripleyusersNAME Spreadsheet::ParseExcel - Extract information from Excel file. DESCRIPTION This module allows you to extract information from Excel file. This module can handle files in Excel95, 97 and 2000 format. The module will work on the majority of Windows, UNIX and Macintosh platforms. REQUIREMENT This module requires these modules: OLE::Storage_Lite Jcode.pm (if you are using FmtJapan, or FmtJapan2) Unicode::Map (if you are using FmtJapan2 or FmtUnicode) IO::Scalar (if PERLIO is not available) Spreadsheet::WriteExcel (to use Spreadsheet::ParseExcel::SaveParser) INSTALLATION The module can be installed using the standard Perl procedure: perl Build.PL ./Build ./Build test ./Bbuild install or perl Makefile.PL make make test make install # You may need to be root make clean # or make realclean or using CPAN.pm or CPANPLUS.pm cpan Spreadsheet::ParseExcel Windows users without a working "make" can get nmake from: ftp://ftp.microsoft.com/Softlib/MSLFILES/nmake15.exe For FmtJapan2 If you use FmtJapan2, you must do following actions: (1) Copy "CP932Excel.map" included with this distribution to an applicatable directry. (2) To add "CP932Excel" as map name, append following lines to REGISTRY in the Unicode::Map hierarchy (changing map directy to applicatable directry): name: CP932Excel srcURL: $SrcUnicode/VENDORS/MICSFT/WINDOWS/CP932.TXT src: $DestUnicode/VENDORS/MICSFT/WINDOWS/CP932.TXT map: (which you copied directry)/CP932Excel.map # Don't remove this line AUTHOR Current maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori (Hippo2000) kwitknr@cpan.org SUPPORT Before you report problems, please check the "KNOWN PROBLEMS" section in the manual page for Spreadsheet::ParseExcel. There is a Google group for discussing and asking questions about Spreadsheet::ParseExcel. http://groups-beta.google.com/group/spreadsheet-parseexcel/ Bugs can be reported via rt.cpan.org. See the following for instructions: http://rt.cpan.org/Public/Dist/Display.html?Name=Spreadsheet-ParseExcel Test cases are always welcome. gdata/inst/perl/Spreadsheet/ParseExcel.pm0000644000176000001440000027723111326376247020170 0ustar ripleyuserspackage Spreadsheet::ParseExcel; ############################################################################## # # Spreadsheet::ParseExcel - Extract information from an Excel file. # # Copyright 2000-2008, Takanori Kawai # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use 5.008; use OLE::Storage_Lite; use IO::File; use Config; our $VERSION = '0.56'; use Spreadsheet::ParseExcel::Workbook; use Spreadsheet::ParseExcel::Worksheet; use Spreadsheet::ParseExcel::Font; use Spreadsheet::ParseExcel::Format; use Spreadsheet::ParseExcel::Cell; use Spreadsheet::ParseExcel::FmtDefault; my @aColor = ( '000000', # 0x00 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', 'FFFFFF', # 0x08 'FFFFFF', 'FF0000', '00FF00', '0000FF', 'FFFF00', 'FF00FF', '00FFFF', '800000', # 0x10 '008000', '000080', '808000', '800080', '008080', 'C0C0C0', '808080', '9999FF', # 0x18 '993366', 'FFFFCC', 'CCFFFF', '660066', 'FF8080', '0066CC', 'CCCCFF', '000080', # 0x20 'FF00FF', 'FFFF00', '00FFFF', '800080', '800000', '008080', '0000FF', '00CCFF', # 0x28 'CCFFFF', 'CCFFCC', 'FFFF99', '99CCFF', 'FF99CC', 'CC99FF', 'FFCC99', '3366FF', # 0x30 '33CCCC', '99CC00', 'FFCC00', 'FF9900', 'FF6600', '666699', '969696', '003366', # 0x38 '339966', '003300', '333300', '993300', '993366', '333399', '333333', 'FFFFFF' # 0x40 ); use constant verExcel95 => 0x500; use constant verExcel97 => 0x600; use constant verBIFF2 => 0x00; use constant verBIFF3 => 0x02; use constant verBIFF4 => 0x04; use constant verBIFF5 => 0x08; use constant verBIFF8 => 0x18; # Error code for some of the common parsing errors. use constant ErrorNone => 0; use constant ErrorNoFile => 1; use constant ErrorNoExcelData => 2; use constant ErrorFileEncrypted => 3; our %error_strings = ( ErrorNone, '', # 0 ErrorNoFile, 'File not found', # 1 ErrorNoExcelData, 'No Excel data found in file', # 2 ErrorFileEncrypted, 'File is encrypted', # 3 ); our %ProcTbl = ( #Develpers' Kit P291 0x14 => \&_subHeader, # Header 0x15 => \&_subFooter, # Footer 0x18 => \&_subName, # NAME(?) 0x1A => \&_subVPageBreak, # Vertical Page Break 0x1B => \&_subHPageBreak, # Horizontal Page Break 0x22 => \&_subFlg1904, # 1904 Flag 0x26 => \&_subMargin, # Left Margin 0x27 => \&_subMargin, # Right Margin 0x28 => \&_subMargin, # Top Margin 0x29 => \&_subMargin, # Bottom Margin 0x2A => \&_subPrintHeaders, # Print Headers 0x2B => \&_subPrintGridlines, # Print Gridlines 0x3C => \&_subContinue, # Continue 0x43 => \&_subXF, # Extended Format(?) #Develpers' Kit P292 0x55 => \&_subDefColWidth, # Consider 0x5C => \&_subWriteAccess, # WRITEACCESS 0x7D => \&_subColInfo, # Colinfo 0x7E => \&_subRK, # RK 0x81 => \&_subWSBOOL, # WSBOOL 0x83 => \&_subHcenter, # HCENTER 0x84 => \&_subVcenter, # VCENTER 0x85 => \&_subBoundSheet, # BoundSheet 0x92 => \&_subPalette, # Palette, fgp 0x99 => \&_subStandardWidth, # Standard Col #Develpers' Kit P293 0xA1 => \&_subSETUP, # SETUP 0xBD => \&_subMulRK, # MULRK 0xBE => \&_subMulBlank, # MULBLANK 0xD6 => \&_subRString, # RString #Develpers' Kit P294 0xE0 => \&_subXF, # ExTended Format 0xE5 => \&_subMergeArea, # MergeArea (Not Documented) 0xFC => \&_subSST, # Shared String Table 0xFD => \&_subLabelSST, # Label SST #Develpers' Kit P295 0x201 => \&_subBlank, # Blank 0x202 => \&_subInteger, # Integer(Not Documented) 0x203 => \&_subNumber, # Number 0x204 => \&_subLabel, # Label 0x205 => \&_subBoolErr, # BoolErr 0x207 => \&_subString, # STRING 0x208 => \&_subRow, # RowData 0x221 => \&_subArray, # Array (Consider) 0x225 => \&_subDefaultRowHeight, # Consider 0x31 => \&_subFont, # Font 0x231 => \&_subFont, # Font 0x27E => \&_subRK, # RK 0x41E => \&_subFormat, # Format 0x06 => \&_subFormula, # Formula 0x406 => \&_subFormula, # Formula 0x009 => \&_subBOF, # BOF(BIFF2) 0x209 => \&_subBOF, # BOF(BIFF3) 0x409 => \&_subBOF, # BOF(BIFF4) 0x809 => \&_subBOF, # BOF(BIFF5-8) ); our $BIGENDIAN; our $PREFUNC; our $_CellHandler; our $_NotSetCell; our $_Object; our $_use_perlio; #------------------------------------------------------------------------------ # Spreadsheet::ParseExcel->new #------------------------------------------------------------------------------ sub new { my ( $class, %hParam ) = @_; if ( not defined $_use_perlio ) { if ( exists $Config{useperlio} && defined $Config{useperlio} && $Config{useperlio} eq "define" ) { $_use_perlio = 1; } else { $_use_perlio = 0; require IO::Scalar; import IO::Scalar; } } # Check ENDIAN(Little: Interl etc. BIG: Sparc etc) $BIGENDIAN = ( defined $hParam{Endian} ) ? $hParam{Endian} : ( unpack( "H08", pack( "L", 2 ) ) eq '02000000' ) ? 0 : 1; my $self = {}; bless $self, $class; $self->{GetContent} = \&_subGetContent; if ( $hParam{EventHandlers} ) { $self->SetEventHandlers( $hParam{EventHandlers} ); } else { $self->SetEventHandlers( \%ProcTbl ); } if ( $hParam{AddHandlers} ) { foreach my $sKey ( keys( %{ $hParam{AddHandlers} } ) ) { $self->SetEventHandler( $sKey, $hParam{AddHandlers}->{$sKey} ); } } $_CellHandler = $hParam{CellHandler} if ( $hParam{CellHandler} ); $_NotSetCell = $hParam{NotSetCell}; $_Object = $hParam{Object}; $self->{_error_status} = ErrorNone; return $self; } #------------------------------------------------------------------------------ # Spreadsheet::ParseExcel->SetEventHandler #------------------------------------------------------------------------------ sub SetEventHandler { my ( $self, $key, $sub_ref ) = @_; $self->{FuncTbl}->{$key} = $sub_ref; } #------------------------------------------------------------------------------ # Spreadsheet::ParseExcel->SetEventHandlers #------------------------------------------------------------------------------ sub SetEventHandlers { my ( $self, $rhTbl ) = @_; $self->{FuncTbl} = undef; foreach my $sKey ( keys %$rhTbl ) { $self->{FuncTbl}->{$sKey} = $rhTbl->{$sKey}; } } ############################################################################### # # Parse() # # Parse the Excel file and convert it into a tree of objects.. # sub parse { my ( $self, $source, $formatter ) = @_; my $workbook = Spreadsheet::ParseExcel::Workbook->new(); $workbook->{SheetCount} = 0; my ( $biff_data, $data_length ) = $self->_get_content( $source, $workbook ); return undef if not $biff_data; if ($formatter) { $workbook->{FmtClass} = $formatter; } else { $workbook->{FmtClass} = Spreadsheet::ParseExcel::FmtDefault->new(); } # Parse the BIFF data. my $pos = 0; my $record_header = substr( $biff_data, $pos, 4 ); $pos += 4; while ( $pos <= $data_length ) { my ( $record, $record_length ) = unpack( "v2", $record_header ); if ($record_length) { $record_header = substr( $biff_data, $pos, $record_length ); $pos += $record_length; } # If the file contains a FILEPASS record we assume that it is encrypted # and cannot be parsed. if ( $record == 0x002F ) { $self->{_error_status} = ErrorFileEncrypted; return undef; } # Special case of a formula String with no string. if ( $workbook->{_PrevPos} && ( defined $self->{FuncTbl}->{$record} ) && ( $record != 0x207 ) ) { my $iPos = $workbook->{_PrevPos}; $workbook->{_PrevPos} = undef; my ( $row, $col, $format_index ) = @$iPos; _NewCell( $workbook, $row, $col, Kind => 'Formula String', Val => '', FormatNo => $format_index, Format => $workbook->{Format}[$format_index], Numeric => 0, Code => undef, Book => $workbook, ); } # If the BIFF record matches 0x0*09 then it is a BOF record. # We reset the _skip_chart flag to ensure we check the sheet type. if ( ( $record & 0xF0FF ) == 0x09 ) { $workbook->{_skip_chart} = 0; } if ( defined $self->{FuncTbl}->{$record} && !$workbook->{_skip_chart} ) { $self->{FuncTbl}->{$record}->( $workbook, $record, $record_length, $record_header ); } $PREFUNC = $record if ( $record != 0x3C ); #Not Continue if ( ( $pos + 4 ) <= $data_length ) { $record_header = substr( $biff_data, $pos, 4 ); } $pos += 4; return $workbook if defined $workbook->{_ParseAbort}; } return $workbook; } ############################################################################### # # _get_content() # # Get the Excel BIFF content from the file or filehandle. # sub _get_content { my ( $self, $source, $workbook ) = @_; my ( $biff_data, $data_length ); # Reset the error status in case method is called more than once. $self->{_error_status} = ErrorNone; if ( ref($source) eq "SCALAR" ) { # Specified by a scalar buffer. ( $biff_data, $data_length ) = $self->{GetContent}->($source); } elsif (( ref($source) =~ /GLOB/ ) || ( ref($source) eq 'Fh' ) ) { # For CGI.pm (Light FileHandle) binmode($source); my $sWk; my $sBuff = ''; while ( read( $source, $sWk, 4096 ) ) { $sBuff .= $sWk; } ( $biff_data, $data_length ) = $self->{GetContent}->( \$sBuff ); } elsif ( ref($source) eq 'ARRAY' ) { # Specified by file content $workbook->{File} = undef; my $sData = join( '', @$source ); ( $biff_data, $data_length ) = $self->{GetContent}->( \$sData ); } else { # Specified by filename . $workbook->{File} = $source; if ( ! -e $source ) { $self->{_error_status} = ErrorNoFile; return undef; } ( $biff_data, $data_length ) = $self->{GetContent}->($source); } # If the read was successful return the data. if ($data_length) { return ($biff_data, $data_length ); } else { $self->{_error_status} = ErrorNoExcelData; return undef; } } #------------------------------------------------------------------------------ # _subGetContent (for Spreadsheet::ParseExcel) #------------------------------------------------------------------------------ sub _subGetContent { my ($sFile) = @_; my $oOl = OLE::Storage_Lite->new($sFile); return ( undef, undef ) unless ($oOl); my @aRes = $oOl->getPpsSearch( [ OLE::Storage_Lite::Asc2Ucs('Book'), OLE::Storage_Lite::Asc2Ucs('Workbook') ], 1, 1 ); return ( undef, undef ) if ( $#aRes < 0 ); #Hack from Herbert if ( $aRes[0]->{Data} ) { return ( $aRes[0]->{Data}, length( $aRes[0]->{Data} ) ); } #Same as OLE::Storage_Lite my $oIo; #1. $sFile is Ref of scalar if ( ref($sFile) eq 'SCALAR' ) { if ($_use_perlio) { open $oIo, "<", \$sFile; } else { $oIo = IO::Scalar->new; $oIo->open($sFile); } } #2. $sFile is a IO::Handle object elsif ( UNIVERSAL::isa( $sFile, 'IO::Handle' ) ) { $oIo = $sFile; binmode($oIo); } #3. $sFile is a simple filename string elsif ( !ref($sFile) ) { $oIo = IO::File->new; $oIo->open("<$sFile") || return undef; binmode($oIo); } my $sWk; my $sBuff = ''; while ( $oIo->read( $sWk, 4096 ) ) { #4_096 has no special meanings $sBuff .= $sWk; } $oIo->close(); #Not Excel file (simple method) return ( undef, undef ) if ( substr( $sBuff, 0, 1 ) ne "\x09" ); return ( $sBuff, length($sBuff) ); } #------------------------------------------------------------------------------ # _subBOF (for Spreadsheet::ParseExcel) Developers' Kit : P303 #------------------------------------------------------------------------------ sub _subBOF { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iVer, $iDt ) = unpack( "v2", $sWk ); #Workbook Global if ( $iDt == 0x0005 ) { $oBook->{Version} = unpack( "v", $sWk ); $oBook->{BIFFVersion} = ( $oBook->{Version} == verExcel95 ) ? verBIFF5 : verBIFF8; $oBook->{_CurSheet} = undef; $oBook->{_CurSheet_} = -1; } #Worksheet or Dialogsheet elsif ( $iDt != 0x0020 ) { #if($iDt == 0x0010) if ( defined $oBook->{_CurSheet_} ) { $oBook->{_CurSheet} = $oBook->{_CurSheet_} + 1; $oBook->{_CurSheet_}++; ( $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{SheetVersion}, $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{SheetType}, ) = unpack( "v2", $sWk ) if ( length($sWk) > 4 ); } else { $oBook->{BIFFVersion} = int( $bOp / 0x100 ); if ( ( $oBook->{BIFFVersion} == verBIFF2 ) || ( $oBook->{BIFFVersion} == verBIFF3 ) || ( $oBook->{BIFFVersion} == verBIFF4 ) ) { $oBook->{Version} = $oBook->{BIFFVersion}; $oBook->{_CurSheet} = 0; $oBook->{Worksheet}[ $oBook->{SheetCount} ] = Spreadsheet::ParseExcel::Worksheet->new( _Name => '', Name => '', _Book => $oBook, _SheetNo => $oBook->{SheetCount}, ); $oBook->{SheetCount}++; } } } else { # Set flag to ignore all chart records until we reach another BOF. $oBook->{_skip_chart} = 1; } } #------------------------------------------------------------------------------ # _subBlank (for Spreadsheet::ParseExcel) DK:P303 #------------------------------------------------------------------------------ sub _subBlank { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF ) = unpack( "v3", $sWk ); _NewCell( $oBook, $iR, $iC, Kind => 'BLANK', Val => '', FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => undef, Book => $oBook, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _subInteger (for Spreadsheet::ParseExcel) Not in DK #------------------------------------------------------------------------------ sub _subInteger { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF, $sTxt, $sDum ); ( $iR, $iC, $iF, $sDum, $sTxt ) = unpack( "v3cv", $sWk ); _NewCell( $oBook, $iR, $iC, Kind => 'INTEGER', Val => $sTxt, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => undef, Book => $oBook, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _subNumber (for Spreadsheet::ParseExcel) : DK: P354 #------------------------------------------------------------------------------ sub _subNumber { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF ) = unpack( "v3", $sWk ); my $dVal = _convDval( substr( $sWk, 6, 8 ) ); _NewCell( $oBook, $iR, $iC, Kind => 'Number', Val => $dVal, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 1, Code => undef, Book => $oBook, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _convDval (for Spreadsheet::ParseExcel) #------------------------------------------------------------------------------ sub _convDval { my ($sWk) = @_; return unpack( "d", ($BIGENDIAN) ? pack( "c8", reverse( unpack( "c8", $sWk ) ) ) : $sWk ); } #------------------------------------------------------------------------------ # _subRString (for Spreadsheet::ParseExcel) DK:P405 #------------------------------------------------------------------------------ sub _subRString { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF, $iL, $sTxt ); ( $iR, $iC, $iF, $iL ) = unpack( "v4", $sWk ); $sTxt = substr( $sWk, 8, $iL ); #Has STRUN if ( length($sWk) > ( 8 + $iL ) ) { _NewCell( $oBook, $iR, $iC, Kind => 'RString', Val => $sTxt, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => '_native_', #undef, Book => $oBook, Rich => substr( $sWk, ( 8 + $iL ) + 1 ), ); } else { _NewCell( $oBook, $iR, $iC, Kind => 'RString', Val => $sTxt, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => '_native_', Book => $oBook, ); } #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _subBoolErr (for Spreadsheet::ParseExcel) DK:P306 #------------------------------------------------------------------------------ sub _subBoolErr { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF ) = unpack( "v3", $sWk ); my ( $iVal, $iFlg ) = unpack( "cc", substr( $sWk, 6, 2 ) ); my $sTxt = DecodeBoolErr( $iVal, $iFlg ); _NewCell( $oBook, $iR, $iC, Kind => 'BoolError', Val => $sTxt, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => undef, Book => $oBook, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } ############################################################################### # # _subRK() # # Decode the RK BIFF record. # sub _subRK { my ( $workbook, $biff_number, $length, $data ) = @_; my ( $row, $col, $format_index, $rk_number ) = unpack( 'vvvV', $data ); my $number = _decode_rk_number($rk_number); _NewCell( $workbook, $row, $col, Kind => 'RK', Val => $number, FormatNo => $format_index, Format => $workbook->{Format}->[$format_index], Numeric => 1, Code => undef, Book => $workbook, ); # Store the max and min row/col values. _SetDimension( $workbook, $row, $col, $col ); } #------------------------------------------------------------------------------ # _subArray (for Spreadsheet::ParseExcel) DK:P297 #------------------------------------------------------------------------------ sub _subArray { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iBR, $iER, $iBC, $iEC ) = unpack( "v2c2", $sWk ); } #------------------------------------------------------------------------------ # _subFormula (for Spreadsheet::ParseExcel) DK:P336 #------------------------------------------------------------------------------ sub _subFormula { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF ) = unpack( "v3", $sWk ); my ($iFlg) = unpack( "v", substr( $sWk, 12, 2 ) ); if ( $iFlg == 0xFFFF ) { my ($iKind) = unpack( "c", substr( $sWk, 6, 1 ) ); my ($iVal) = unpack( "c", substr( $sWk, 8, 1 ) ); if ( ( $iKind == 1 ) or ( $iKind == 2 ) ) { my $sTxt = ( $iKind == 1 ) ? DecodeBoolErr( $iVal, 0 ) : DecodeBoolErr( $iVal, 1 ); _NewCell( $oBook, $iR, $iC, Kind => 'Formula Bool', Val => $sTxt, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => undef, Book => $oBook, ); } else { # Result (Reserve Only) $oBook->{_PrevPos} = [ $iR, $iC, $iF ]; } } else { my $dVal = _convDval( substr( $sWk, 6, 8 ) ); _NewCell( $oBook, $iR, $iC, Kind => 'Formula Number', Val => $dVal, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 1, Code => undef, Book => $oBook, ); } #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _subString (for Spreadsheet::ParseExcel) DK:P414 #------------------------------------------------------------------------------ sub _subString { my ( $oBook, $bOp, $bLen, $sWk ) = @_; #Position (not enough for ARRAY) my $iPos = $oBook->{_PrevPos}; return undef unless ($iPos); $oBook->{_PrevPos} = undef; my ( $iR, $iC, $iF ) = @$iPos; my ( $iLen, $sTxt, $sCode ); if ( $oBook->{BIFFVersion} == verBIFF8 ) { my ( $raBuff, $iLen ) = _convBIFF8String( $oBook, $sWk, 1 ); $sTxt = $raBuff->[0]; $sCode = ( $raBuff->[1] ) ? 'ucs2' : undef; } elsif ( $oBook->{BIFFVersion} == verBIFF5 ) { $sCode = '_native_'; $iLen = unpack( "v", $sWk ); $sTxt = substr( $sWk, 2, $iLen ); } else { $sCode = '_native_'; $iLen = unpack( "c", $sWk ); $sTxt = substr( $sWk, 1, $iLen ); } _NewCell( $oBook, $iR, $iC, Kind => 'String', Val => $sTxt, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => $sCode, Book => $oBook, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _subLabel (for Spreadsheet::ParseExcel) DK:P344 #------------------------------------------------------------------------------ sub _subLabel { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF ) = unpack( "v3", $sWk ); my ( $sLbl, $sCode ); #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { my ( $raBuff, $iLen, $iStPos, $iLenS ) = _convBIFF8String( $oBook, substr( $sWk, 6 ), 1 ); $sLbl = $raBuff->[0]; $sCode = ( $raBuff->[1] ) ? 'ucs2' : undef; } #Before BIFF8 else { $sLbl = substr( $sWk, 8 ); $sCode = '_native_'; } _NewCell( $oBook, $iR, $iC, Kind => 'Label', Val => $sLbl, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => $sCode, Book => $oBook, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } ############################################################################### # # _subMulRK() # # Decode the Multiple RK BIFF record. # sub _subMulRK { my ( $workbook, $biff_number, $length, $data ) = @_; # JMN: I don't know why this is here. return if $workbook->{SheetCount} <= 0; my ( $row, $first_col ) = unpack( "v2", $data ); my $last_col = unpack( "v", substr( $data, length($data) - 2, 2 ) ); # Iterate over the RK array and decode the data. my $pos = 4; for my $col ( $first_col .. $last_col ) { my $data = substr( $data, $pos, 6 ); my ( $format_index, $rk_number ) = unpack 'vV', $data; my $number = _decode_rk_number($rk_number); _NewCell( $workbook, $row, $col, Kind => 'MulRK', Val => $number, FormatNo => $format_index, Format => $workbook->{Format}->[$format_index], Numeric => 1, Code => undef, Book => $workbook, ); $pos += 6; } # Store the max and min row/col values. _SetDimension( $workbook, $row, $first_col, $last_col ); } #------------------------------------------------------------------------------ # _subMulBlank (for Spreadsheet::ParseExcel) DK:P349 #------------------------------------------------------------------------------ sub _subMulBlank { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iSc ) = unpack( "v2", $sWk ); my $iEc = unpack( "v", substr( $sWk, length($sWk) - 2, 2 ) ); my $iPos = 4; for ( my $iC = $iSc ; $iC <= $iEc ; $iC++ ) { my $iF = unpack( 'v', substr( $sWk, $iPos, 2 ) ); _NewCell( $oBook, $iR, $iC, Kind => 'MulBlank', Val => '', FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => undef, Book => $oBook, ); $iPos += 2; } #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iSc, $iEc ); } #------------------------------------------------------------------------------ # _subLabelSST (for Spreadsheet::ParseExcel) DK: P345 #------------------------------------------------------------------------------ sub _subLabelSST { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iR, $iC, $iF, $iIdx ) = unpack( 'v3V', $sWk ); _NewCell( $oBook, $iR, $iC, Kind => 'PackedIdx', Val => $oBook->{PkgStr}[$iIdx]->{Text}, FormatNo => $iF, Format => $oBook->{Format}[$iF], Numeric => 0, Code => ( $oBook->{PkgStr}[$iIdx]->{Unicode} ) ? 'ucs2' : undef, Book => $oBook, Rich => $oBook->{PkgStr}[$iIdx]->{Rich}, ); #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iC, $iC ); } #------------------------------------------------------------------------------ # _subFlg1904 (for Spreadsheet::ParseExcel) DK:P296 #------------------------------------------------------------------------------ sub _subFlg1904 { my ( $oBook, $bOp, $bLen, $sWk ) = @_; $oBook->{Flg1904} = unpack( "v", $sWk ); } #------------------------------------------------------------------------------ # _subRow (for Spreadsheet::ParseExcel) DK:P403 #------------------------------------------------------------------------------ sub _subRow { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); #0. Get Worksheet info (MaxRow, MaxCol, MinRow, MinCol) my ( $iR, $iSc, $iEc, $iHght, $undef1, $undef2, $iGr, $iXf ) = unpack( "v8", $sWk ); $iEc--; # TODO. we need to handle hidden rows: # $iGr & 0x20 $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{RowHeight}[$iR] = $iHght / 20; #2.MaxRow, MaxCol, MinRow, MinCol _SetDimension( $oBook, $iR, $iSc, $iEc ); } #------------------------------------------------------------------------------ # _SetDimension (for Spreadsheet::ParseExcel) #------------------------------------------------------------------------------ sub _SetDimension { my ( $oBook, $iR, $iSc, $iEc ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); #2.MaxRow, MaxCol, MinRow, MinCol #2.1 MinRow $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MinRow} = $iR unless ( defined $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MinRow} ) and ( $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MinRow} <= $iR ); #2.2 MaxRow $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MaxRow} = $iR unless ( defined $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MaxRow} ) and ( $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MaxRow} > $iR ); #2.3 MinCol $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MinCol} = $iSc unless ( defined $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MinCol} ) and ( $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MinCol} <= $iSc ); #2.4 MaxCol $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MaxCol} = $iEc unless ( defined $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MaxCol} ) and ( $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{MaxCol} > $iEc ); } #------------------------------------------------------------------------------ # _subDefaultRowHeight (for Spreadsheet::ParseExcel) DK: P318 #------------------------------------------------------------------------------ sub _subDefaultRowHeight { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); #1. RowHeight my ( $iDum, $iHght ) = unpack( "v2", $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{DefRowHeight} = $iHght / 20; } #------------------------------------------------------------------------------ # _subStandardWidth(for Spreadsheet::ParseExcel) DK:P413 #------------------------------------------------------------------------------ sub _subStandardWidth { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my $iW = unpack( "v", $sWk ); $oBook->{StandardWidth} = _convert_col_width( $oBook, $iW ); } ############################################################################### # # _subDefColWidth() # # Read the DEFCOLWIDTH Biff record. This gives the width in terms of chars # and is different from the width in the COLINFO record. # sub _subDefColWidth { my ( $self, $record, $length, $data ) = @_; my $width = unpack 'v', $data; # Adjustment for default Arial 10 width. $width = 8.43 if $width == 8; $self->{Worksheet}->[ $self->{_CurSheet} ]->{DefColWidth} = $width; } ############################################################################### # # _convert_col_width() # # Converts from the internal Excel column width units to user units seen in the # interface. It is first necessary to convert the internal width to pixels and # then to user units. The conversion is specific to a default font of Arial 10. # TODO, the conversion should be extended to other fonts and sizes. # sub _convert_col_width { my $self = shift; my $excel_width = shift; # Convert from Excel units to pixels (rounded up). my $pixels = int( 0.5 + $excel_width * 7 / 256 ); # Convert from pixels to user units. # The conversion is different for columns <= 1 user unit (12 pixels). my $user_width; if ( $pixels <= 12 ) { $user_width = $pixels / 12; } else { $user_width = ( $pixels - 5 ) / 7; } # Round up to 2 decimal places. $user_width = int( $user_width * 100 + 0.5 ) / 100; return $user_width; } #------------------------------------------------------------------------------ # _subColInfo (for Spreadsheet::ParseExcel) DK:P309 #------------------------------------------------------------------------------ sub _subColInfo { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless defined $oBook->{_CurSheet}; my ( $iSc, $iEc, $iW, $iXF, $iGr ) = unpack( "v5", $sWk ); for ( my $i = $iSc ; $i <= $iEc ; $i++ ) { $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{ColWidth}[$i] = _convert_col_width( $oBook, $iW ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{ColFmtNo}[$i] = $iXF; # TODO. we need to handle hidden cols: $iGr & 0x01. } } #------------------------------------------------------------------------------ # _subSST (for Spreadsheet::ParseExcel) DK:P413 #------------------------------------------------------------------------------ sub _subSST { my ( $oBook, $bOp, $bLen, $sWk ) = @_; _subStrWk( $oBook, substr( $sWk, 8 ) ); } #------------------------------------------------------------------------------ # _subContinue (for Spreadsheet::ParseExcel) DK:P311 #------------------------------------------------------------------------------ sub _subContinue { my ( $oBook, $bOp, $bLen, $sWk ) = @_; #if(defined $self->{FuncTbl}->{$bOp}) { # $self->{FuncTbl}->{$PREFUNC}->($oBook, $bOp, $bLen, $sWk); #} _subStrWk( $oBook, $sWk, 1 ) if ( $PREFUNC == 0xFC ); } #------------------------------------------------------------------------------ # _subWriteAccess (for Spreadsheet::ParseExcel) DK:P451 #------------------------------------------------------------------------------ sub _subWriteAccess { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return if ( defined $oBook->{_Author} ); #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { $oBook->{Author} = _convBIFF8String( $oBook, $sWk ); } #Before BIFF8 else { my ($iLen) = unpack( "c", $sWk ); $oBook->{Author} = $oBook->{FmtClass}->TextFmt( substr( $sWk, 1, $iLen ), '_native_' ); } } #------------------------------------------------------------------------------ # _convBIFF8String (for Spreadsheet::ParseExcel) #------------------------------------------------------------------------------ sub _convBIFF8String { my ( $oBook, $sWk, $iCnvFlg ) = @_; my ( $iLen, $iFlg ) = unpack( "vc", $sWk ); my ( $iHigh, $iExt, $iRich ) = ( $iFlg & 0x01, $iFlg & 0x04, $iFlg & 0x08 ); my ( $iStPos, $iExtCnt, $iRichCnt, $sStr ); #2. Rich and Ext if ( $iRich && $iExt ) { $iStPos = 9; ( $iRichCnt, $iExtCnt ) = unpack( 'vV', substr( $sWk, 3, 6 ) ); } elsif ($iRich) { #Only Rich $iStPos = 5; $iRichCnt = unpack( 'v', substr( $sWk, 3, 2 ) ); $iExtCnt = 0; } elsif ($iExt) { #Only Ext $iStPos = 7; $iRichCnt = 0; $iExtCnt = unpack( 'V', substr( $sWk, 3, 4 ) ); } else { #Nothing Special $iStPos = 3; $iExtCnt = 0; $iRichCnt = 0; } #3.Get String if ($iHigh) { #Compressed $iLen *= 2; $sStr = substr( $sWk, $iStPos, $iLen ); _SwapForUnicode( \$sStr ); $sStr = $oBook->{FmtClass}->TextFmt( $sStr, 'ucs2' ) unless ($iCnvFlg); } else { #Not Compressed $sStr = substr( $sWk, $iStPos, $iLen ); $sStr = $oBook->{FmtClass}->TextFmt( $sStr, undef ) unless ($iCnvFlg); } #4. return if (wantarray) { #4.1 Get Rich and Ext if ( length($sWk) < $iStPos + $iLen + $iRichCnt * 4 + $iExtCnt ) { return ( [ undef, $iHigh, undef, undef ], $iStPos + $iLen + $iRichCnt * 4 + $iExtCnt, $iStPos, $iLen ); } else { return ( [ $sStr, $iHigh, substr( $sWk, $iStPos + $iLen, $iRichCnt * 4 ), substr( $sWk, $iStPos + $iLen + $iRichCnt * 4, $iExtCnt ) ], $iStPos + $iLen + $iRichCnt * 4 + $iExtCnt, $iStPos, $iLen ); } } else { return $sStr; } } #------------------------------------------------------------------------------ # _subXF (for Spreadsheet::ParseExcel) DK:P453 #------------------------------------------------------------------------------ sub _subXF { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iFnt, $iIdx ); my ( $iLock, $iHidden, $iStyle, $i123, $iAlH, $iWrap, $iAlV, $iJustL, $iRotate, $iInd, $iShrink, $iMerge, $iReadDir, $iBdrD, $iBdrSL, $iBdrSR, $iBdrST, $iBdrSB, $iBdrSD, $iBdrCL, $iBdrCR, $iBdrCT, $iBdrCB, $iBdrCD, $iFillP, $iFillCF, $iFillCB ); if ( $oBook->{BIFFVersion} == verBIFF8 ) { my ( $iGen, $iAlign, $iGen2, $iBdr1, $iBdr2, $iBdr3, $iPtn ); ( $iFnt, $iIdx, $iGen, $iAlign, $iGen2, $iBdr1, $iBdr2, $iBdr3, $iPtn ) = unpack( "v7Vv", $sWk ); $iLock = ( $iGen & 0x01 ) ? 1 : 0; $iHidden = ( $iGen & 0x02 ) ? 1 : 0; $iStyle = ( $iGen & 0x04 ) ? 1 : 0; $i123 = ( $iGen & 0x08 ) ? 1 : 0; $iAlH = ( $iAlign & 0x07 ); $iWrap = ( $iAlign & 0x08 ) ? 1 : 0; $iAlV = ( $iAlign & 0x70 ) / 0x10; $iJustL = ( $iAlign & 0x80 ) ? 1 : 0; $iRotate = ( ( $iAlign & 0xFF00 ) / 0x100 ) & 0x00FF; $iRotate = 90 if ( $iRotate == 255 ); $iRotate = 90 - $iRotate if ( $iRotate > 90 ); $iInd = ( $iGen2 & 0x0F ); $iShrink = ( $iGen2 & 0x10 ) ? 1 : 0; $iMerge = ( $iGen2 & 0x20 ) ? 1 : 0; $iReadDir = ( ( $iGen2 & 0xC0 ) / 0x40 ) & 0x03; $iBdrSL = $iBdr1 & 0x0F; $iBdrSR = ( ( $iBdr1 & 0xF0 ) / 0x10 ) & 0x0F; $iBdrST = ( ( $iBdr1 & 0xF00 ) / 0x100 ) & 0x0F; $iBdrSB = ( ( $iBdr1 & 0xF000 ) / 0x1000 ) & 0x0F; $iBdrCL = ( ( $iBdr2 & 0x7F ) ) & 0x7F; $iBdrCR = ( ( $iBdr2 & 0x3F80 ) / 0x80 ) & 0x7F; $iBdrD = ( ( $iBdr2 & 0xC000 ) / 0x4000 ) & 0x3; $iBdrCT = ( ( $iBdr3 & 0x7F ) ) & 0x7F; $iBdrCB = ( ( $iBdr3 & 0x3F80 ) / 0x80 ) & 0x7F; $iBdrCD = ( ( $iBdr3 & 0x1FC000 ) / 0x4000 ) & 0x7F; $iBdrSD = ( ( $iBdr3 & 0x1E00000 ) / 0x200000 ) & 0xF; $iFillP = ( ( $iBdr3 & 0xFC000000 ) / 0x4000000 ) & 0x3F; $iFillCF = ( $iPtn & 0x7F ); $iFillCB = ( ( $iPtn & 0x3F80 ) / 0x80 ) & 0x7F; } else { my ( $iGen, $iAlign, $iPtn, $iPtn2, $iBdr1, $iBdr2 ); ( $iFnt, $iIdx, $iGen, $iAlign, $iPtn, $iPtn2, $iBdr1, $iBdr2 ) = unpack( "v8", $sWk ); $iLock = ( $iGen & 0x01 ) ? 1 : 0; $iHidden = ( $iGen & 0x02 ) ? 1 : 0; $iStyle = ( $iGen & 0x04 ) ? 1 : 0; $i123 = ( $iGen & 0x08 ) ? 1 : 0; $iAlH = ( $iAlign & 0x07 ); $iWrap = ( $iAlign & 0x08 ) ? 1 : 0; $iAlV = ( $iAlign & 0x70 ) / 0x10; $iJustL = ( $iAlign & 0x80 ) ? 1 : 0; $iRotate = ( ( $iAlign & 0x300 ) / 0x100 ) & 0x3; $iFillCF = ( $iPtn & 0x7F ); $iFillCB = ( ( $iPtn & 0x1F80 ) / 0x80 ) & 0x7F; $iFillP = ( $iPtn2 & 0x3F ); $iBdrSB = ( ( $iPtn2 & 0x1C0 ) / 0x40 ) & 0x7; $iBdrCB = ( ( $iPtn2 & 0xFE00 ) / 0x200 ) & 0x7F; $iBdrST = ( $iBdr1 & 0x07 ); $iBdrSL = ( ( $iBdr1 & 0x38 ) / 0x8 ) & 0x07; $iBdrSR = ( ( $iBdr1 & 0x1C0 ) / 0x40 ) & 0x07; $iBdrCT = ( ( $iBdr1 & 0xFE00 ) / 0x200 ) & 0x7F; $iBdrCL = ( $iBdr2 & 0x7F ) & 0x7F; $iBdrCR = ( ( $iBdr2 & 0x3F80 ) / 0x80 ) & 0x7F; } push @{ $oBook->{Format} }, Spreadsheet::ParseExcel::Format->new( FontNo => $iFnt, Font => $oBook->{Font}[$iFnt], FmtIdx => $iIdx, Lock => $iLock, Hidden => $iHidden, Style => $iStyle, Key123 => $i123, AlignH => $iAlH, Wrap => $iWrap, AlignV => $iAlV, JustLast => $iJustL, Rotate => $iRotate, Indent => $iInd, Shrink => $iShrink, Merge => $iMerge, ReadDir => $iReadDir, BdrStyle => [ $iBdrSL, $iBdrSR, $iBdrST, $iBdrSB ], BdrColor => [ $iBdrCL, $iBdrCR, $iBdrCT, $iBdrCB ], BdrDiag => [ $iBdrD, $iBdrSD, $iBdrCD ], Fill => [ $iFillP, $iFillCF, $iFillCB ], ); } #------------------------------------------------------------------------------ # _subFormat (for Spreadsheet::ParseExcel) DK: P336 #------------------------------------------------------------------------------ sub _subFormat { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my $sFmt; if ( ( $oBook->{BIFFVersion} == verBIFF2 ) || ( $oBook->{BIFFVersion} == verBIFF3 ) || ( $oBook->{BIFFVersion} == verBIFF4 ) || ( $oBook->{BIFFVersion} == verBIFF5 ) ) { $sFmt = substr( $sWk, 3, unpack( 'c', substr( $sWk, 2, 1 ) ) ); $sFmt = $oBook->{FmtClass}->TextFmt( $sFmt, '_native_' ); } else { $sFmt = _convBIFF8String( $oBook, substr( $sWk, 2 ) ); } $oBook->{FormatStr}->{ unpack( 'v', substr( $sWk, 0, 2 ) ) } = $sFmt; } #------------------------------------------------------------------------------ # _subPalette (for Spreadsheet::ParseExcel) DK: P393 #------------------------------------------------------------------------------ sub _subPalette { my ( $oBook, $bOp, $bLen, $sWk ) = @_; for ( my $i = 0 ; $i < unpack( 'v', $sWk ) ; $i++ ) { # push @aColor, unpack('H6', substr($sWk, $i*4+2)); $aColor[ $i + 8 ] = unpack( 'H6', substr( $sWk, $i * 4 + 2 ) ); } } #------------------------------------------------------------------------------ # _subFont (for Spreadsheet::ParseExcel) DK:P333 #------------------------------------------------------------------------------ sub _subFont { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iHeight, $iAttr, $iCIdx, $iBold, $iSuper, $iUnderline, $sFntName ); my ( $bBold, $bItalic, $bUnderline, $bStrikeout ); if ( $oBook->{BIFFVersion} == verBIFF8 ) { ( $iHeight, $iAttr, $iCIdx, $iBold, $iSuper, $iUnderline ) = unpack( "v5c", $sWk ); my ( $iSize, $iHigh ) = unpack( 'cc', substr( $sWk, 14, 2 ) ); if ($iHigh) { $sFntName = substr( $sWk, 16, $iSize * 2 ); _SwapForUnicode( \$sFntName ); $sFntName = $oBook->{FmtClass}->TextFmt( $sFntName, 'ucs2' ); } else { $sFntName = substr( $sWk, 16, $iSize ); $sFntName = $oBook->{FmtClass}->TextFmt( $sFntName, '_native_' ); } $bBold = ( $iBold >= 0x2BC ) ? 1 : 0; $bItalic = ( $iAttr & 0x02 ) ? 1 : 0; $bStrikeout = ( $iAttr & 0x08 ) ? 1 : 0; $bUnderline = ($iUnderline) ? 1 : 0; } elsif ( $oBook->{BIFFVersion} == verBIFF5 ) { ( $iHeight, $iAttr, $iCIdx, $iBold, $iSuper, $iUnderline ) = unpack( "v5c", $sWk ); $sFntName = $oBook->{FmtClass} ->TextFmt( substr( $sWk, 15, unpack( "c", substr( $sWk, 14, 1 ) ) ), '_native_' ); $bBold = ( $iBold >= 0x2BC ) ? 1 : 0; $bItalic = ( $iAttr & 0x02 ) ? 1 : 0; $bStrikeout = ( $iAttr & 0x08 ) ? 1 : 0; $bUnderline = ($iUnderline) ? 1 : 0; } else { ( $iHeight, $iAttr ) = unpack( "v2", $sWk ); $iCIdx = undef; $iSuper = 0; $bBold = ( $iAttr & 0x01 ) ? 1 : 0; $bItalic = ( $iAttr & 0x02 ) ? 1 : 0; $bUnderline = ( $iAttr & 0x04 ) ? 1 : 0; $bStrikeout = ( $iAttr & 0x08 ) ? 1 : 0; $sFntName = substr( $sWk, 5, unpack( "c", substr( $sWk, 4, 1 ) ) ); } push @{ $oBook->{Font} }, Spreadsheet::ParseExcel::Font->new( Height => $iHeight / 20.0, Attr => $iAttr, Color => $iCIdx, Super => $iSuper, UnderlineStyle => $iUnderline, Name => $sFntName, Bold => $bBold, Italic => $bItalic, Underline => $bUnderline, Strikeout => $bStrikeout, ); #Skip Font[4] push @{ $oBook->{Font} }, {} if ( scalar( @{ $oBook->{Font} } ) == 4 ); } #------------------------------------------------------------------------------ # _subBoundSheet (for Spreadsheet::ParseExcel): DK: P307 #------------------------------------------------------------------------------ sub _subBoundSheet { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iPos, $iGr, $iKind ) = unpack( "Lc2", $sWk ); $iKind &= 0x0F; return if ( ( $iKind != 0x00 ) && ( $iKind != 0x01 ) ); if ( $oBook->{BIFFVersion} >= verBIFF8 ) { my ( $iSize, $iUni ) = unpack( "cc", substr( $sWk, 6, 2 ) ); my $sWsName = substr( $sWk, 8 ); if ( $iUni & 0x01 ) { _SwapForUnicode( \$sWsName ); $sWsName = $oBook->{FmtClass}->TextFmt( $sWsName, 'ucs2' ); } $oBook->{Worksheet}[ $oBook->{SheetCount} ] = Spreadsheet::ParseExcel::Worksheet->new( Name => $sWsName, Kind => $iKind, _Pos => $iPos, _Book => $oBook, _SheetNo => $oBook->{SheetCount}, ); } else { $oBook->{Worksheet}[ $oBook->{SheetCount} ] = Spreadsheet::ParseExcel::Worksheet->new( Name => $oBook->{FmtClass}->TextFmt( substr( $sWk, 7 ), '_native_' ), Kind => $iKind, _Pos => $iPos, _Book => $oBook, _SheetNo => $oBook->{SheetCount}, ); } $oBook->{SheetCount}++; } #------------------------------------------------------------------------------ # _subHeader (for Spreadsheet::ParseExcel) DK: P340 #------------------------------------------------------------------------------ sub _subHeader { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $sW; #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { $sW = _convBIFF8String( $oBook, $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{Header} = ( $sW eq "\x00" ) ? undef : $sW; } #Before BIFF8 else { my ($iLen) = unpack( "c", $sWk ); $sW = $oBook->{FmtClass}->TextFmt( substr( $sWk, 1, $iLen ), '_native_' ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{Header} = ( $sW eq "\x00\x00\x00" ) ? undef : $sW; } } #------------------------------------------------------------------------------ # _subFooter (for Spreadsheet::ParseExcel) DK: P335 #------------------------------------------------------------------------------ sub _subFooter { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $sW; #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { $sW = _convBIFF8String( $oBook, $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{Footer} = ( $sW eq "\x00" ) ? undef : $sW; } #Before BIFF8 else { my ($iLen) = unpack( "c", $sWk ); $sW = $oBook->{FmtClass}->TextFmt( substr( $sWk, 1, $iLen ), '_native_' ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{Footer} = ( $sW eq "\x00\x00\x00" ) ? undef : $sW; } } #------------------------------------------------------------------------------ # _subHPageBreak (for Spreadsheet::ParseExcel) DK: P341 #------------------------------------------------------------------------------ sub _subHPageBreak { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my @aBreak; my $iCnt = unpack( "v", $sWk ); return undef unless ( defined $oBook->{_CurSheet} ); #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { for ( my $i = 0 ; $i < $iCnt ; $i++ ) { my ( $iRow, $iColB, $iColE ) = unpack( 'v3', substr( $sWk, 2 + $i * 6, 6 ) ); # push @aBreak, [$iRow, $iColB, $iColE]; push @aBreak, $iRow; } } #Before BIFF8 else { for ( my $i = 0 ; $i < $iCnt ; $i++ ) { my ($iRow) = unpack( 'v', substr( $sWk, 2 + $i * 2, 2 ) ); push @aBreak, $iRow; # push @aBreak, [$iRow, 0, 255]; } } @aBreak = sort { $a <=> $b } @aBreak; $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{HPageBreak} = \@aBreak; } #------------------------------------------------------------------------------ # _subVPageBreak (for Spreadsheet::ParseExcel) DK: P447 #------------------------------------------------------------------------------ sub _subVPageBreak { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my @aBreak; my $iCnt = unpack( "v", $sWk ); #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { for ( my $i = 0 ; $i < $iCnt ; $i++ ) { my ( $iCol, $iRowB, $iRowE ) = unpack( 'v3', substr( $sWk, 2 + $i * 6, 6 ) ); push @aBreak, $iCol; # push @aBreak, [$iCol, $iRowB, $iRowE]; } } #Before BIFF8 else { for ( my $i = 0 ; $i < $iCnt ; $i++ ) { my ($iCol) = unpack( 'v', substr( $sWk, 2 + $i * 2, 2 ) ); push @aBreak, $iCol; # push @aBreak, [$iCol, 0, 65535]; } } @aBreak = sort { $a <=> $b } @aBreak; $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{VPageBreak} = \@aBreak; } #------------------------------------------------------------------------------ # _subMargin (for Spreadsheet::ParseExcel) DK: P306, 345, 400, 440 #------------------------------------------------------------------------------ sub _subMargin { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); # The "Mergin" options are a workaround for a backward compatible typo. my $dWk = _convDval( substr( $sWk, 0, 8 ) ); if ( $bOp == 0x26 ) { $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{LeftMergin} = $dWk; $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{LeftMargin} = $dWk; } elsif ( $bOp == 0x27 ) { $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{RightMergin} = $dWk; $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{RightMargin} = $dWk; } elsif ( $bOp == 0x28 ) { $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{TopMergin} = $dWk; $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{TopMargin} = $dWk; } elsif ( $bOp == 0x29 ) { $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{BottomMergin} = $dWk; $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{BottomMargin} = $dWk; } } #------------------------------------------------------------------------------ # _subHcenter (for Spreadsheet::ParseExcel) DK: P340 #------------------------------------------------------------------------------ sub _subHcenter { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $iWk = unpack( "v", $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{HCenter} = $iWk; } #------------------------------------------------------------------------------ # _subVcenter (for Spreadsheet::ParseExcel) DK: P447 #------------------------------------------------------------------------------ sub _subVcenter { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $iWk = unpack( "v", $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{VCenter} = $iWk; } #------------------------------------------------------------------------------ # _subPrintGridlines (for Spreadsheet::ParseExcel) DK: P397 #------------------------------------------------------------------------------ sub _subPrintGridlines { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $iWk = unpack( "v", $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{PrintGrid} = $iWk; } #------------------------------------------------------------------------------ # _subPrintHeaders (for Spreadsheet::ParseExcel) DK: P397 #------------------------------------------------------------------------------ sub _subPrintHeaders { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $iWk = unpack( "v", $sWk ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{PrintHeaders} = $iWk; } #------------------------------------------------------------------------------ # _subSETUP (for Spreadsheet::ParseExcel) DK: P409 #------------------------------------------------------------------------------ sub _subSETUP { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $oWkS = $oBook->{Worksheet}[ $oBook->{_CurSheet} ]; my $iGrBit; ( $oWkS->{PaperSize}, $oWkS->{Scale}, $oWkS->{PageStart}, $oWkS->{FitWidth}, $oWkS->{FitHeight}, $iGrBit, $oWkS->{Res}, $oWkS->{VRes}, ) = unpack( 'v8', $sWk ); $oWkS->{HeaderMargin} = _convDval( substr( $sWk, 16, 8 ) ); $oWkS->{FooterMargin} = _convDval( substr( $sWk, 24, 8 ) ); $oWkS->{Copis} = unpack( 'v2', substr( $sWk, 32, 2 ) ); $oWkS->{LeftToRight} = ( ( $iGrBit & 0x01 ) ? 1 : 0 ); $oWkS->{Landscape} = ( ( $iGrBit & 0x02 ) ? 1 : 0 ); $oWkS->{NoPls} = ( ( $iGrBit & 0x04 ) ? 1 : 0 ); $oWkS->{NoColor} = ( ( $iGrBit & 0x08 ) ? 1 : 0 ); $oWkS->{Draft} = ( ( $iGrBit & 0x10 ) ? 1 : 0 ); $oWkS->{Notes} = ( ( $iGrBit & 0x20 ) ? 1 : 0 ); $oWkS->{NoOrient} = ( ( $iGrBit & 0x40 ) ? 1 : 0 ); $oWkS->{UsePage} = ( ( $iGrBit & 0x80 ) ? 1 : 0 ); # The NoPls flag indicates that the values have not been taken from an # actual printer and thus may not be accurate. # Set default scale if NoPls otherwise it may be an invalid value of 0XFF. $oWkS->{Scale} = 100 if $oWkS->{NoPls}; # Workaround for a backward compatible typo. $oWkS->{HeaderMergin} = $oWkS->{HeaderMargin}; $oWkS->{FooterMergin} = $oWkS->{FooterMargin}; } #------------------------------------------------------------------------------ # _subName (for Spreadsheet::ParseExcel) DK: P350 #------------------------------------------------------------------------------ sub _subName { my ( $oBook, $bOp, $bLen, $sWk ) = @_; my ( $iGrBit, $cKey, $cCh, $iCce, $ixAls, $iTab, $cchCust, $cchDsc, $cchHep, $cchStatus ) = unpack( 'vc2v3c4', $sWk ); #Builtin Name + Length == 1 if ( ( $iGrBit & 0x20 ) && ( $cCh == 1 ) ) { #BIFF8 if ( $oBook->{BIFFVersion} >= verBIFF8 ) { my $iName = unpack( 'n', substr( $sWk, 14 ) ); my $iSheet = unpack( 'v', substr( $sWk, 8 ) ) - 1; # Workaround for mal-formed Excel workbooks where Print_Title is # set as Global (i.e. itab = 0). Note, this will have to be # treated differently when we get around to handling global names. return undef if $iSheet == -1; if ( $iName == 6 ) { #PrintArea my ( $iSheetW, $raArea ) = _ParseNameArea( substr( $sWk, 16 ) ); $oBook->{PrintArea}[$iSheet] = $raArea; } elsif ( $iName == 7 ) { #Title my ( $iSheetW, $raArea ) = _ParseNameArea( substr( $sWk, 16 ) ); my @aTtlR = (); my @aTtlC = (); foreach my $raI (@$raArea) { if ( $raI->[3] == 0xFF ) { #Row Title push @aTtlR, [ $raI->[0], $raI->[2] ]; } else { #Col Title push @aTtlC, [ $raI->[1], $raI->[3] ]; } } $oBook->{PrintTitle}[$iSheet] = { Row => \@aTtlR, Column => \@aTtlC }; } } else { my $iName = unpack( 'c', substr( $sWk, 14 ) ); if ( $iName == 6 ) { #PrintArea my ( $iSheet, $raArea ) = _ParseNameArea95( substr( $sWk, 15 ) ); $oBook->{PrintArea}[$iSheet] = $raArea; } elsif ( $iName == 7 ) { #Title my ( $iSheet, $raArea ) = _ParseNameArea95( substr( $sWk, 15 ) ); my @aTtlR = (); my @aTtlC = (); foreach my $raI (@$raArea) { if ( $raI->[3] == 0xFF ) { #Row Title push @aTtlR, [ $raI->[0], $raI->[2] ]; } else { #Col Title push @aTtlC, [ $raI->[1], $raI->[3] ]; } } $oBook->{PrintTitle}[$iSheet] = { Row => \@aTtlR, Column => \@aTtlC }; } } } } #------------------------------------------------------------------------------ # ParseNameArea (for Spreadsheet::ParseExcel) DK: 494 (ptgAread3d) #------------------------------------------------------------------------------ sub _ParseNameArea { my ($sObj) = @_; my ($iOp); my @aRes = (); $iOp = unpack( 'C', $sObj ); my $iSheet; if ( $iOp == 0x3b ) { my ( $iWkS, $iRs, $iRe, $iCs, $iCe ) = unpack( 'v5', substr( $sObj, 1 ) ); $iSheet = $iWkS; push @aRes, [ $iRs, $iCs, $iRe, $iCe ]; } elsif ( $iOp == 0x29 ) { my $iLen = unpack( 'v', substr( $sObj, 1, 2 ) ); my $iSt = 0; while ( $iSt < $iLen ) { my ( $iOpW, $iWkS, $iRs, $iRe, $iCs, $iCe ) = unpack( 'cv5', substr( $sObj, $iSt + 3, 11 ) ); if ( $iOpW == 0x3b ) { $iSheet = $iWkS; push @aRes, [ $iRs, $iCs, $iRe, $iCe ]; } if ( $iSt == 0 ) { $iSt += 11; } else { $iSt += 12; #Skip 1 byte; } } } return ( $iSheet, \@aRes ); } #------------------------------------------------------------------------------ # ParseNameArea95 (for Spreadsheet::ParseExcel) DK: 494 (ptgAread3d) #------------------------------------------------------------------------------ sub _ParseNameArea95 { my ($sObj) = @_; my ($iOp); my @aRes = (); $iOp = unpack( 'C', $sObj ); my $iSheet; if ( $iOp == 0x3b ) { $iSheet = unpack( 'v', substr( $sObj, 11, 2 ) ); my ( $iRs, $iRe, $iCs, $iCe ) = unpack( 'v2C2', substr( $sObj, 15, 6 ) ); push @aRes, [ $iRs, $iCs, $iRe, $iCe ]; } elsif ( $iOp == 0x29 ) { my $iLen = unpack( 'v', substr( $sObj, 1, 2 ) ); my $iSt = 0; while ( $iSt < $iLen ) { my $iOpW = unpack( 'c', substr( $sObj, $iSt + 3, 6 ) ); $iSheet = unpack( 'v', substr( $sObj, $iSt + 14, 2 ) ); my ( $iRs, $iRe, $iCs, $iCe ) = unpack( 'v2C2', substr( $sObj, $iSt + 18, 6 ) ); push @aRes, [ $iRs, $iCs, $iRe, $iCe ] if ( $iOpW == 0x3b ); if ( $iSt == 0 ) { $iSt += 21; } else { $iSt += 22; #Skip 1 byte; } } } return ( $iSheet, \@aRes ); } #------------------------------------------------------------------------------ # _subBOOL (for Spreadsheet::ParseExcel) DK: P452 #------------------------------------------------------------------------------ sub _subWSBOOL { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{PageFit} = ( ( unpack( 'v', $sWk ) & 0x100 ) ? 1 : 0 ); } #------------------------------------------------------------------------------ # _subMergeArea (for Spreadsheet::ParseExcel) DK: (Not) #------------------------------------------------------------------------------ sub _subMergeArea { my ( $oBook, $bOp, $bLen, $sWk ) = @_; return undef unless ( defined $oBook->{_CurSheet} ); my $iCnt = unpack( "v", $sWk ); my $oWkS = $oBook->{Worksheet}[ $oBook->{_CurSheet} ]; $oWkS->{MergedArea} = [] unless ( defined $oWkS->{MergedArea} ); for ( my $i = 0 ; $i < $iCnt ; $i++ ) { my ( $iRs, $iRe, $iCs, $iCe ) = unpack( 'v4', substr( $sWk, $i * 8 + 2, 8 ) ); for ( my $iR = $iRs ; $iR <= $iRe ; $iR++ ) { for ( my $iC = $iCs ; $iC <= $iCe ; $iC++ ) { $oWkS->{Cells}[$iR][$iC]->{Merged} = 1 if ( defined $oWkS->{Cells}[$iR][$iC] ); } } push @{ $oWkS->{MergedArea} }, [ $iRs, $iCs, $iRe, $iCe ]; } } #------------------------------------------------------------------------------ # DecodeBoolErr (for Spreadsheet::ParseExcel) DK: P306 #------------------------------------------------------------------------------ sub DecodeBoolErr { my ( $iVal, $iFlg ) = @_; if ($iFlg) { # ERROR if ( $iVal == 0x00 ) { return "#NULL!"; } elsif ( $iVal == 0x07 ) { return "#DIV/0!"; } elsif ( $iVal == 0x0F ) { return "#VALUE!"; } elsif ( $iVal == 0x17 ) { return "#REF!"; } elsif ( $iVal == 0x1D ) { return "#NAME?"; } elsif ( $iVal == 0x24 ) { return "#NUM!"; } elsif ( $iVal == 0x2A ) { return "#N/A!"; } else { return "#ERR"; } } else { return ($iVal) ? "TRUE" : "FALSE"; } } ############################################################################### # # _decode_rk_number() # # Convert an encoded RK number into a real number. The RK encoding is # explained in some detail in the MS docs. It is a way of storing applicable # ints and doubles in 32bits (30 data + 2 info bits) in order to save space. # sub _decode_rk_number { my $rk_number = shift; my $number; # Check the main RK type. if ( $rk_number & 0x02 ) { # RK Type 2 and 4, a packed integer. # Shift off the info bits. $number = $rk_number >> 2; # Convert from unsigned to signed if required. $number -= 0x40000000 if $number & 0x20000000; } else { # RK Type 1 and 3, a truncated IEEE Double. # Pack the RK number into the high 30 bits of an IEEE double. $number = pack "VV", 0x0000, $rk_number & 0xFFFFFFFC; # Reverse the packed IEEE double on big-endian machines. $number = reverse $number if $BIGENDIAN; # Unpack the number. $number = unpack "d", $number; } # RK Types 3 and 4 were multiplied by 100 prior to encoding. $number /= 100 if $rk_number & 0x01; return $number; } ############################################################################### # # _subStrWk() # # Extract the workbook strings from the SST (Shared String Table) record and # any following CONTINUE records. # # The workbook strings are initially contained in the SST block but may also # occupy one or more CONTINUE blocks. Reading the CONTINUE blocks is made a # little tricky by the fact that they can contain an additional initial byte # if a string is continued from a previous block. # # Parsing is further complicated by the fact that the continued section of the # string may have a different encoding (ASCII or UTF-8) from the previous # section. Excel does this to save space. # sub _subStrWk { my ( $self, $biff_data, $is_continue ) = @_; if ($is_continue) { # We are reading a CONTINUE record. if ( $self->{_buffer} eq '' ) { # A CONTINUE block with no previous SST. $self->{_buffer} .= $biff_data; } elsif ( !defined $self->{_string_continued} ) { # The CONTINUE block starts with a new (non-continued) string. # Strip the Grbit byte and store the string data. $self->{_buffer} .= substr $biff_data, 1; } else { # A CONTINUE block that starts with a continued string. # The first byte (Grbit) of the CONTINUE record indicates if (0) # the continued string section is single bytes or (1) double bytes. my $grbit = ord $biff_data; my ( $str_position, $str_length ) = @{ $self->{_previous_info} }; my $buff_length = length $self->{_buffer}; if ( $buff_length >= ( $str_position + $str_length ) ) { # Not in a string. $self->{_buffer} .= $biff_data; } elsif ( ( $self->{_string_continued} & 0x01 ) == ( $grbit & 0x01 ) ) { # Same encoding as the previous block of the string. $self->{_buffer} .= substr( $biff_data, 1 ); } else { # Different encoding to the previous block of the string. if ( $grbit & 0x01 ) { # Current block is UTF-16, previous was ASCII. my ( undef, $cch ) = unpack 'vc', $self->{_buffer}; substr( $self->{_buffer}, 2, 1 ) = pack( 'C', $cch | 0x01 ); # Convert the previous ASCII, single character, portion of # the string into a double character UTF-16 string by # inserting zero bytes. for ( my $i = ( $buff_length - $str_position ) ; $i >= 1 ; $i-- ) { substr( $self->{_buffer}, $str_position + $i, 0 ) = "\x00"; } } else { # Current block is ASCII, previous was UTF-16. # Convert the current ASCII, single character, portion of # the string into a double character UTF-16 string by # inserting null bytes. my $change_length = ( $str_position + $str_length ) - $buff_length; # Length of the current CONTINUE record data. my $biff_length = length $biff_data; # Restrict the portion to be changed to the current block # if the string extends over more than one block. if ( $change_length > ( $biff_length - 1 ) * 2 ) { $change_length = ( $biff_length - 1 ) * 2; } # Insert the null bytes. for ( my $i = ( $change_length / 2 ) ; $i >= 1 ; $i-- ) { substr( $biff_data, $i + 1, 0 ) = "\x00"; } } # Strip the Grbit byte and store the string data. $self->{_buffer} .= substr $biff_data, 1; } } } else { # Not a CONTINUE block therefore an SST block. $self->{_buffer} .= $biff_data; } # Reset the state variables. $self->{_string_continued} = undef; $self->{_previous_info} = undef; # Extract out any full strings from the current buffer leaving behind a # partial string that is continued into the next block, or an empty # buffer is no string is continued. while ( length $self->{_buffer} >= 4 ) { my ( $str_info, $length, $str_position, $str_length ) = _convBIFF8String( $self, $self->{_buffer}, 1 ); if ( defined $str_info->[0] ) { push @{ $self->{PkgStr} }, { Text => $str_info->[0], Unicode => $str_info->[1], Rich => $str_info->[2], Ext => $str_info->[3], }; $self->{_buffer} = substr( $self->{_buffer}, $length ); } else { $self->{_string_continued} = $str_info->[1]; $self->{_previous_info} = [ $str_position, $str_length ]; last; } } } #------------------------------------------------------------------------------ # _SwapForUnicode (for Spreadsheet::ParseExcel) #------------------------------------------------------------------------------ sub _SwapForUnicode { my ($sObj) = @_; # for(my $i = 0; $i{_CurSheet} ); my $FmtClass = $oBook->{FmtClass}; $rhKey{Type} = $FmtClass->ChkType( $rhKey{Numeric}, $rhKey{Format}{FmtIdx} ); my $FmtStr = $oBook->{FormatStr}{ $rhKey{Format}{FmtIdx} }; # Set "Date" type if required for numbers in a MulRK BIFF block. if ( defined $FmtStr && $rhKey{Type} eq "Numeric" ) { # Match a range of possible date formats. Note: this isn't important # except for reporting. The number will still be converted to a date # by ExcelFmt() even if 'Type' isn't set to 'Date'. if ( $FmtStr =~ m{^[dmy][-\\/dmy]*$}i ) { $rhKey{Type} = "Date"; } } my $oCell = Spreadsheet::ParseExcel::Cell->new( Val => $rhKey{Val}, FormatNo => $rhKey{FormatNo}, Format => $rhKey{Format}, Code => $rhKey{Code}, Type => $rhKey{Type}, ); $oCell->{_Kind} = $rhKey{Kind}; $oCell->{_Value} = $FmtClass->ValFmt( $oCell, $oBook ); if ( $rhKey{Rich} ) { my @aRich = (); my $sRich = $rhKey{Rich}; for ( my $iWk = 0 ; $iWk < length($sRich) ; $iWk += 4 ) { my ( $iPos, $iFnt ) = unpack( 'v2', substr( $sRich, $iWk ) ); push @aRich, [ $iPos, $oBook->{Font}[$iFnt] ]; } $oCell->{Rich} = \@aRich; } if ( defined $_CellHandler ) { if ( defined $_Object ) { no strict; ref($_CellHandler) eq "CODE" ? $_CellHandler->( $_Object, $oBook, $oBook->{_CurSheet}, $iR, $iC, $oCell ) : $_CellHandler->callback( $_Object, $oBook, $oBook->{_CurSheet}, $iR, $iC, $oCell ); } else { $_CellHandler->( $oBook, $oBook->{_CurSheet}, $iR, $iC, $oCell ); } } unless ($_NotSetCell) { $oBook->{Worksheet}[ $oBook->{_CurSheet} ]->{Cells}[$iR][$iC] = $oCell; } return $oCell; } #------------------------------------------------------------------------------ # ColorIdxToRGB (for Spreadsheet::ParseExcel) # # TODO JMN Make this a Workbook method and re-document. # #------------------------------------------------------------------------------ sub ColorIdxToRGB { my ( $sPkg, $iIdx ) = @_; return ( ( defined $aColor[$iIdx] ) ? $aColor[$iIdx] : $aColor[0] ); } ############################################################################### # # error(). # # Return an error string for a failed parse(). # sub error { my $self = shift; my $parse_error = $self->{_error_status}; if (exists $error_strings{$parse_error}) { return $error_strings{$parse_error}; } else { return 'Unknown parse error'; } } ############################################################################### # # error_code(). # # Return an error code for a failed parse(). # sub error_code { my $self = shift; return $self->{_error_status}; } ############################################################################### # # Mapping between legacy method names and new names. # { no warnings; # Ignore warnings about variables used only once. *Parse = *parse; } 1; __END__ =head1 NAME Spreadsheet::ParseExcel - Read information from an Excel file. =head1 SYNOPSIS #!/usr/bin/perl -w use strict; use Spreadsheet::ParseExcel; my $parser = Spreadsheet::ParseExcel->new(); my $workbook = $parser->parse('Book1.xls'); if ( !defined $workbook ) { die $parser->error(), ".\n"; } for my $worksheet ( $workbook->worksheets() ) { my ( $row_min, $row_max ) = $worksheet->row_range(); my ( $col_min, $col_max ) = $worksheet->col_range(); for my $row ( $row_min .. $row_max ) { for my $col ( $col_min .. $col_max ) { my $cell = $worksheet->get_cell( $row, $col ); next unless $cell; print "Row, Col = ($row, $col)\n"; print "Value = ", $cell->value(), "\n"; print "Unformatted = ", $cell->unformatted(), "\n"; print "\n"; } } } =head1 DESCRIPTION The Spreadsheet::ParseExcel module can be used to read information from Excel 95-2003 binary files. The module cannot read files in the Excel 2007 Open XML XLSX format. See the L module instead. =head1 Parser =head2 new() The C method is used to create a new C parser object. my $parser = Spreadsheet::ParseExcel->new(); As an advanced feature it is also possible to pass a call-back handler to the parser to control the parsing of the spreadsheet. $parser = Spreadsheet::ParseExcel->new( [ CellHandler => \&cell_handler, NotSetCell => 1, ]); The call-back can be used to ignore certain cells or to reduce memory usage. See the section L for more information. =head2 parse($filename, [$formatter]) The Parser C method return a L object. my $parser = Spreadsheet::ParseExcel->new(); my $workbook = $parser->parse('Book1.xls'); If an error occurs C returns C. In general programs should contain a test for failed parsing as follows: my $parser = Spreadsheet::ParseExcel->new(); my $workbook = $parser->parse('Book1.xls'); if ( !defined $workbook ) { die $parser->error(), ".\n"; } The C<$filename> parameter is generally the file to be parsed. However, it can also be a filehandle or a scalar reference. The optional C<$formatter> array ref can be an reference to a L to format the value of cells. Note: Versions of Spreadsheet::ParseExcel prior to 0.50 also documented a Workbook C method as a syntactic shortcut for the above C and C combination. This is now deprecated since it breaks error handling. =head2 error() The Parser C method returns an error string if a C fails: my $parser = Spreadsheet::ParseExcel->new(); my $workbook = $parser->parse('Book1.xls'); if ( !defined $workbook ) { die $parser->error(), ".\n"; } If you wish to generate you own error string you can use the C method instead (see below). The C and C values are as follows: error() error_code() ======= ============ '' 0 'File not found' 1 'No Excel data found in file' 2 'File is encrypted' 3 Spreadsheet::ParseExcel doesn't try to decrypt an encrypted Excel file. That is beyond the current scope of the module. The C method is explained below. =head2 error_code() The Parser C method returns an error code if a C fails: my $parser = Spreadsheet::ParseExcel->new(); my $workbook = $parser->parse('Book1.xls'); if ( !defined $workbook ) { die "Got error code ", $parser->error_code, ".\n"; } This can be useful if you wish to employ you own error strings or error handling methods. =head1 Workbook A C is created via the C C method: my $parser = Spreadsheet::ParseExcel->new(); my $workbook = $parser->parse('Book1.xls'); The main methods of the Workbook class are: $workbook->worksheets() $workbook->worksheet() $workbook->worksheet_count() $workbook->get_filename() These more commonly used methods of the Workbook class are outlined below. The other, less commonly used, methods are documented in L. =head2 worksheets() Returns an array of L objects. This was most commonly used to iterate over the worksheets in a workbook: for my $worksheet ( $workbook->worksheets() ) { ... } =head2 worksheet() The C method returns a single C object using either its name or index: $worksheet = $workbook->worksheet('Sheet1'); $worksheet = $workbook->worksheet(0); Returns C if the sheet name or index doesn't exist. =head2 worksheet_count() The C method returns the number of Worksheet objects in the Workbook. my $worksheet_count = $workbook->worksheet_count(); =head2 get_filename() The C method returns the name of the Excel file of C if the data was read from a filehandle rather than a file. my $filename = $workbook->get_filename(); =head2 Other Workbook Methods For full documentation of the methods available via a Workbook object see L. =head1 Worksheet The C class encapsulates the properties of an Excel worksheet. A Worksheet object is obtained via the L or L methods. for my $worksheet ( $workbook->worksheets() ) { ... } # Or: $worksheet = $workbook->worksheet('Sheet1'); $worksheet = $workbook->worksheet(0); The most commonly used methods of the Worksheet class are: $worksheet->get_cell() $worksheet->row_range() $worksheet->col_range() $worksheet->get_name() The Spreadsheet::ParseExcel::Worksheet class exposes a lot of methods but in general very few are required unless you are writing an advanced filter. The most commonly used methods are detailed below. The others are documented in L. =head2 get_cell($row, $col) Return the L object at row C<$row> and column C<$col> if it is defined. Otherwise returns undef. my $cell = $worksheet->get_cell($row, $col); =head2 row_range() Returns a two-element list C<($min, $max)> containing the minimum and maximum defined rows in the worksheet. If there is no row defined C<$max> is smaller than C<$min>. my ( $row_min, $row_max ) = $worksheet->row_range(); =head2 col_range() Returns a two-element list C<($min, $max)> containing the minimum and maximum of defined columns in the worksheet. If there is no column defined C<$max> is smaller than C<$min>. my ( $col_min, $col_max ) = $worksheet->col_range(); =head2 get_name() The C method returns the name of the worksheet, such as 'Sheet1'. my $name = $worksheet->get_name(); =head2 Other Worksheet Methods For other, less commonly used, Worksheet methods see L. =head1 Cell The C class has the following main methods. $cell->value() $cell->unformatted() =head2 value() The C method returns the formatted value of the cell. my $value = $cell->value(); Formatted in this sense refers to the numeric format of the cell value. For example a number such as 40177 might be formatted as 40,117, 40117.000 or even as the date 2009/12/30. If the cell doesn't contain a numeric format then the formatted and unformatted cell values are the same, see the C method below. For a defined C<$cell> the C method will always return a value. In the case of a cell with formatting but no numeric or string contents the method will return the empty string C<''>. =head2 unformatted() The C method returns the unformatted value of the cell. my $unformatted = $cell->unformatted(); Returns the cell value without a numeric format. See the C method above. =head2 Other Cell Methods For other, less commonly used, Worksheet methods see L. =head1 Format The C class has the following properties: =head2 Format properties $format->{Font} $format->{AlignH} $format->{AlignV} $format->{Indent} $format->{Wrap} $format->{Shrink} $format->{Rotate} $format->{JustLast} $format->{ReadDir} $format->{BdrStyle} $format->{BdrColor} $format->{BdrDiag} $format->{Fill} $format->{Lock} $format->{Hidden} $format->{Style} These properties are generally only of interest to advanced users. Casual users can skip this section. =head2 $format->{Font} Returns the L object for the Format. =head2 $format->{AlignH} Returns the horizontal alignment of the format where the value has the following meaning: 0 => No alignment 1 => Left 2 => Center 3 => Right 4 => Fill 5 => Justify 6 => Center across 7 => Distributed/Equal spaced =head2 $format->{AlignV} Returns the vertical alignment of the format where the value has the following meaning: 0 => Top 1 => Center 2 => Bottom 3 => Justify 4 => Distributed/Equal spaced =head2 $format->{Indent} Returns the indent level of the C horizontal alignment. =head2 $format->{Wrap} Returns true if textwrap is on. =head2 $format->{Shrink} Returns true if "Shrink to fit" is set for the format. =head2 $format->{Rotate} Returns the text rotation. In Excel97+, it returns the angle in degrees of the text rotation. In Excel95 or earlier it returns a value as follows: 0 => No rotation 1 => Top down 2 => 90 degrees anti-clockwise, 3 => 90 clockwise =head2 $format->{JustLast} Return true if the "justify last" property is set for the format. =head2 $format->{ReadDir} Returns the direction that the text is read from. =head2 $format->{BdrStyle} Returns an array ref of border styles as follows: [ $left, $right, $top, $bottom ] =head2 $format->{BdrColor} Returns an array ref of border color indexes as follows: [ $left, $right, $top, $bottom ] =head2 $format->{BdrDiag} Returns an array ref of diagonal border kind, style and color index as follows: [$kind, $style, $color ] Where kind is: 0 => None 1 => Right-Down 2 => Right-Up 3 => Both =head2 $format->{Fill} Returns an array ref of fill pattern and color indexes as follows: [ $pattern, $front_color, $back_color ] =head2 $format->{Lock} Returns true if the cell is locked. =head2 $format->{Hidden} Returns true if the cell is Hidden. =head2 $format->{Style} Returns true if the format is a Style format. =head1 Font I Format class has these properties: =head1 Font Properties $font->{Name} $font->{Bold} $font->{Italic} $font->{Height} $font->{Underline} $font->{UnderlineStyle} $font->{Color} $font->{Strikeout} $font->{Super} =head2 $font->{Name} Returns the name of the font, for example 'Arial'. =head2 $font->{Bold} Returns true if the font is bold. =head2 $font->{Italic} Returns true if the font is italic. =head2 $font->{Height} Returns the size (height) of the font. =head2 $font->{Underline} Returns true if the font in underlined. =head2 $font->{UnderlineStyle} Returns the style of an underlined font where the value has the following meaning: 0 => None 1 => Single 2 => Double 33 => Single accounting 34 => Double accounting =head2 $font->{Color} Returns the color index for the font. The index can be converted to a RGB string using the C Parser method. =head2 $font->{Strikeout} Returns true if the font has the strikeout property set. =head2 $font->{Super} Returns one of the following values if the superscript or subscript property of the font is set: 0 => None 1 => Superscript 2 => Subscript =head1 Formatter class I Formatter class will convert cell data. Spreadsheet::ParseExcel includes 2 formatter classes. C and C. It is also possible to create a user defined formatting class. The formatter class C should provide the following functions: =head2 ChkType($self, $is_numeric, $format_index) Method to check the type of data in the cell. Should return C, C or C. It is passed the following parameters: =over =item $self A scalar reference to the Formatter object. =item $is_numeric If true, the value seems to be number. =item $format_index The index number for the cell Format object. =back =head2 TextFmt($self, $string_data, $string_encoding) Converts the string data in the cell into the correct encoding. It is passed the following parameters: =over =item $self A scalar reference to the Formatter object. =item $string_data The original string/text data. =item $string_encoding The character encoding of original string/text. =back =head2 ValFmt($self, $cell, $workbook) Convert the original unformatted cell value into the appropriate formatted value. For instance turn a number into a formatted date. It is passed the following parameters: =over =item $self A scalar reference to the Formatter object. =item $cell A scalar reference to the Cell object. =item $workbook A scalar reference to the Workbook object. =back =head2 FmtString($self, $cell, $workbook) Get the format string for the Cell. It is passed the following parameters: =over =item $self A scalar reference to the Formatter object. =item $cell A scalar reference to the Cell object. =item $workbook A scalar reference to the Workbook object. =back =head1 Reducing the memory usage of Spreadsheet::ParseExcel In some cases a C application may consume a lot of memory when processing a large Excel file and, as a result, may fail to complete. The following explains why this can occur and how to resolve it. C processes an Excel file in two stages. In the first stage it extracts the Excel binary stream from the OLE container file using C. In the second stage it parses the binary stream to read workbook, worksheet and cell data which it then stores in memory. The majority of the memory usage is required for storing cell data. The reason for this is that as the Excel file is parsed and each cell is encountered a cell handling function creates a relatively large nested cell object that contains the cell value and all of the data that relates to the cell formatting. For large files (a 10MB Excel file on a 256MB system) this overhead can cause the system to grind to a halt. However, in a lot of cases when an Excel file is being processed the only information that is required are the cell values. In these cases it is possible to avoid most of the memory overhead by specifying your own cell handling function and by telling Spreadsheet::ParseExcel not to store the parsed cell data. This is achieved by passing a cell handler function to C when creating the parse object. Here is an example. #!/usr/bin/perl -w use strict; use Spreadsheet::ParseExcel; my $parser = Spreadsheet::ParseExcel->new( CellHandler => \&cell_handler, NotSetCell => 1 ); my $workbook = $parser->parse('file.xls'); sub cell_handler { my $workbook = $_[0]; my $sheet_index = $_[1]; my $row = $_[2]; my $col = $_[3]; my $cell = $_[4]; # Do something useful with the formatted cell value print $cell->value(), "\n"; } The user specified cell handler is passed as a code reference to C along with the parameter C which tells Spreadsheet::ParseExcel not to store the parsed cell. Note, you don't have to iterate over the rows and columns, this happens automatically as part of the parsing. The cell handler is passed 5 arguments. The first, C<$workbook>, is a reference to the C object that represent the parsed workbook. This can be used to access any of the C methods, see L. The second C<$sheet_index> is the zero-based index of the worksheet being parsed. The third and fourth, C<$row> and C<$col>, are the zero-based row and column number of the cell. The fifth, C<$cell>, is a reference to the C object. This is used to extract the data from the cell. See L for more information. This technique can be useful if you are writing an Excel to database filter since you can put your DB calls in the cell handler. If you don't want all of the data in the spreadsheet you can add some control logic to the cell handler. For example we can extend the previous example so that it only prints the first 10 rows of the first two worksheets in the parsed workbook by adding some C statements to the cell handler: #!/usr/bin/perl -w use strict; use Spreadsheet::ParseExcel; my $parser = Spreadsheet::ParseExcel->new( CellHandler => \&cell_handler, NotSetCell => 1 ); my $workbook = $parser->parse('file.xls'); sub cell_handler { my $workbook = $_[0]; my $sheet_index = $_[1]; my $row = $_[2]; my $col = $_[3]; my $cell = $_[4]; # Skip some worksheets and rows (inefficiently). return if $sheet_index >= 3; return if $row >= 10; # Do something with the formatted cell value print $cell->value(), "\n"; } However, this still processes the entire workbook. If you wish to save some additional processing time you can abort the parsing after you have read the data that you want, using the workbook C method: #!/usr/bin/perl -w use strict; use Spreadsheet::ParseExcel; my $parser = Spreadsheet::ParseExcel->new( CellHandler => \&cell_handler, NotSetCell => 1 ); my $workbook = $parser->parse('file.xls'); sub cell_handler { my $workbook = $_[0]; my $sheet_index = $_[1]; my $row = $_[2]; my $col = $_[3]; my $cell = $_[4]; # Skip some worksheets and rows (more efficiently). if ( $sheet_index >= 1 and $row >= 10 ) { $workbook->ParseAbort(1); return; } # Do something with the formatted cell value print $cell->value(), "\n"; } =head1 KNOWN PROBLEMS =over =item * Issues reported by users: http://rt.cpan.org/Public/Dist/Display.html?Name=Spreadsheet-ParseExcel =item * This module cannot read the values of formulas from files created with Spreadsheet::WriteExcel unless the user specified the values when creating the file (which is generally not the case). The reason for this is that Spreadsheet::WriteExcel writes the formula but not the formula result since it isn't in a position to calculate arbitrary Excel formulas without access to Excel's formula engine. =item * If Excel has date fields where the specified format is equal to the system-default for the short-date locale, Excel does not store the format, but defaults to an internal format which is system dependent. In these cases ParseExcel uses the date format 'yyyy-mm-dd'. =back =head1 REPORTING A BUG Bugs can be reported via rt.cpan.org. See the following for instructions on bug reporting for Spreadsheet::ParseExcel http://rt.cpan.org/Public/Dist/Display.html?Name=Spreadsheet-ParseExcel =head1 SEE ALSO =over =item * xls2csv by Ken Prows (http://search.cpan.org/~ken/xls2csv-1.06/script/xls2csv). =item * xls2csv and xlscat by H.Merijn Brand (these utilities are part of Spreadsheet::Read, see below). =item * excel2txt by Ken Youens-Clark, (http://search.cpan.org/~kclark/excel2txt/excel2txt). This is an excellent example of an Excel filter using Spreadsheet::ParseExcel. It can produce CSV, Tab delimited, Html, XML and Yaml. =item * XLSperl by Jon Allen (http://search.cpan.org/~jonallen/XLSperl/bin/XLSperl). This application allows you to use Perl "one-liners" with Microsoft Excel files. =item * Spreadsheet::XLSX (http://search.cpan.org/~dmow/Spreadsheet-XLSX/lib/Spreadsheet/XLSX.pm) by Dmitry Ovsyanko. A module with a similar interface to Spreadsheet::ParseExcel for parsing Excel 2007 XLSX OpenXML files. =item * Spreadsheet::Read (http://search.cpan.org/~hmbrand/Spreadsheet-Read/Read.pm) by H.Merijn Brand. A single interface for reading several different spreadsheet formats. =item * Spreadsheet::WriteExcel (http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel/lib/Spreadsheet/WriteExcel.pm). A perl module for creating new Excel files. =item * Spreadsheet::ParseExcel::SaveParser (http://search.cpan.org/~jmcnamara/Spreadsheet-ParseExcel/lib/Spreadsheet/ParseExcel/SaveParser.pm). This is a combination of Spreadsheet::ParseExcel and Spreadsheet::WriteExcel and it allows you to "rewrite" an Excel file. See the following example (http://search.cpan.org/~jmcnamara/Spreadsheet-WriteExcel/lib/Spreadsheet/WriteExcel.pm#MODIFYING_AND_REWRITING_EXCEL_FILES). It is part of the Spreadsheet::ParseExcel distro. =item * Text::CSV_XS (http://search.cpan.org/~hmbrand/Text-CSV_XS/CSV_XS.pm) by H.Merijn Brand. A fast and rigorous module for reading and writing CSV data. Don't consider rolling your own CSV handling, use this module instead. =back =head1 MAILING LIST There is a Google group for discussing and asking questions about Spreadsheet::ParseExcel. This is a good place to search to see if your question has been asked before: http://groups-beta.google.com/group/spreadsheet-parseexcel/ =head1 DONATIONS If you'd care to donate to the Spreadsheet::ParseExcel project, you can do so via PayPal: http://tinyurl.com/7ayes =head1 TODO =over =item * The current maintenance work is directed towards making the documentation more useful, improving and simplifying the API, and improving the maintainability of the code base. After that new features will be added. =item * Fix open bugs and documentation for SaveParser. =item * Add Formula support, Hyperlink support, Named Range support. =item * Improve Spreadsheet::ParseExcel::SaveParser compatibility with Spreadsheet::WriteExcel. =item * Improve Unicode and other encoding support. This will probably require dropping support for perls prior to 5.8+. =back =head1 ACKNOWLEDGEMENTS From Kawai Takanori: First of all, I would like to acknowledge the following valuable programs and modules: XHTML, OLE::Storage and Spreadsheet::WriteExcel. In no particular order: Yamaji Haruna, Simamoto Takesi, Noguchi Harumi, Ikezawa Kazuhiro, Suwazono Shugo, Hirofumi Morisada, Michael Edwards, Kim Namusk, Slaven Rezic, Grant Stevens, H.Merijn Brand and many many people + Kawai Mikako. =head1 DISCLAIMER OF WARRANTY Because this software is licensed free of charge, there is no warranty for the software, to the extent permitted by applicable law. Except when otherwise stated in writing the copyright holders and/or other parties provide the software "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 software is with you. Should the software prove defective, you assume the cost of all necessary servicing, repair, or correction. 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 software as permitted by the above licence, be liable to you for damages, including any general, special, incidental, or consequential damages arising out of the use or inability to use the software (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 software to operate with any other software), even if such holder or other party has been advised of the possibility of such damages. =head1 LICENSE Either the Perl Artistic Licence http://dev.perl.org/licenses/artistic.html or the GPL http://www.opensource.org/licenses/gpl-license.php =head1 AUTHOR Current maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori (Hippo2000) kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. This is free software. You may distribute under the terms of either the GNU General Public License or the Artistic License. =cut gdata/inst/perl/Spreadsheet/ParseExcel/0000755000176000001440000000000012164457166017617 5ustar ripleyusersgdata/inst/perl/Spreadsheet/ParseExcel/Worksheet.pm0000644000176000001440000005471011326376247022136 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Worksheet; ############################################################################### # # Spreadsheet::ParseExcel::Worksheet - A class for Worksheets. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use Scalar::Util qw(weaken); our $VERSION = '0.56'; ############################################################################### # # new() # sub new { my ( $class, %properties ) = @_; my $self = \%properties; weaken $self->{_Book}; $self->{Cells} = undef; $self->{DefColWidth} = 8.43; return bless $self, $class; } ############################################################################### # # get_cell( $row, $col ) # # Returns the Cell object at row $row and column $col, if defined. # sub get_cell { my ( $self, $row, $col ) = @_; if ( !defined $row || !defined $col || !defined $self->{MaxRow} || !defined $self->{MaxCol} ) { # Return undef if no arguments are given or if no cells are defined. return undef; } elsif ($row < $self->{MinRow} || $row > $self->{MaxRow} || $col < $self->{MinCol} || $col > $self->{MaxCol} ) { # Return undef if outside allowable row/col range. return undef; } else { # Return the Cell object. return $self->{Cells}->[$row]->[$col]; } } ############################################################################### # # row_range() # # Returns a two-element list ($min, $max) containing the minimum and maximum # defined rows in the worksheet. # # If there is no row defined $max is smaller than $min. # sub row_range { my $self = shift; my $min = $self->{MinRow} || 0; my $max = defined( $self->{MaxRow} ) ? $self->{MaxRow} : ( $min - 1 ); return ( $min, $max ); } ############################################################################### # # col_range() # # Returns a two-element list ($min, $max) containing the minimum and maximum # defined cols in the worksheet. # # If there is no column defined $max is smaller than $min. # sub col_range { my $self = shift; my $min = $self->{MinCol} || 0; my $max = defined( $self->{MaxCol} ) ? $self->{MaxCol} : ( $min - 1 ); return ( $min, $max ); } ############################################################################### # # get_name() # # Returns the name of the worksheet. # sub get_name { my $self = shift; return $self->{Name}; } ############################################################################### # # sheet_num() # sub sheet_num { my $self = shift; return $self->{_SheetNo}; } ############################################################################### # # get_h_pagebreaks() # # Returns an array ref of row numbers where a horizontal page break occurs. # sub get_h_pagebreaks { my $self = shift; return $self->{HPageBreak}; } ############################################################################### # # get_v_pagebreaks() # # Returns an array ref of column numbers where a vertical page break occurs. # sub get_v_pagebreaks { my $self = shift; return $self->{VPageBreak}; } ############################################################################### # # get_merged_areas() # # Returns an array ref of cells that are merged. # sub get_merged_areas { my $self = shift; return $self->{MergedArea}; } ############################################################################### # # get_row_heights() # # Returns an array_ref of row heights. # sub get_row_heights { my $self = shift; return @{ $self->{RowHeight} }; } ############################################################################### # # get_col_widths() # # Returns an array_ref of column widths. # sub get_col_widths { my $self = shift; return @{ $self->{ColWidth} }; } ############################################################################### # # get_default_row_height() # # Returns the default row height for the worksheet. Generally 12.75. # sub get_default_row_height { my $self = shift; return $self->{DefRowHeight}; } ############################################################################### # # get_default_col_width() # # Returns the default column width for the worksheet. Generally 8.43. # sub get_default_col_width { my $self = shift; return $self->{DefColWidth}; } ############################################################################### # # _get_row_properties() # # Returns an array_ref of row properties. # TODO. This is a placeholder for a future method. # sub _get_row_properties { my $self = shift; return $self->{RowProperties}; } ############################################################################### # # _get_col_properties() # # Returns an array_ref of column properties. # TODO. This is a placeholder for a future method. # sub _get_col_properties { my $self = shift; return $self->{ColProperties}; } ############################################################################### # # get_header() # # Returns the worksheet header string. # sub get_header { my $self = shift; return $self->{Header}; } ############################################################################### # # get_footer() # # Returns the worksheet footer string. # sub get_footer { my $self = shift; return $self->{Footer}; } ############################################################################### # # get_margin_left() # # Returns the left margin of the worksheet in inches. # sub get_margin_left { my $self = shift; return $self->{LeftMargin}; } ############################################################################### # # get_margin_right() # # Returns the right margin of the worksheet in inches. # sub get_margin_right { my $self = shift; return $self->{RightMargin}; } ############################################################################### # # get_margin_top() # # Returns the top margin of the worksheet in inches. # sub get_margin_top { my $self = shift; return $self->{TopMargin}; } ############################################################################### # # get_margin_bottom() # # Returns the bottom margin of the worksheet in inches. # sub get_margin_bottom { my $self = shift; return $self->{BottomMargin}; } ############################################################################### # # get_margin_header() # # Returns the header margin of the worksheet in inches. # sub get_margin_header { my $self = shift; return $self->{HeaderMargin}; } ############################################################################### # # get_margin_footer() # # Returns the footer margin of the worksheet in inches. # sub get_margin_footer { my $self = shift; return $self->{FooterMargin}; } ############################################################################### # # get_paper() # # Returns the printer paper size. # sub get_paper { my $self = shift; return $self->{PaperSize}; } ############################################################################### # # get_start_page() # # Returns the page number that printing will start from. # sub get_start_page { my $self = shift; # Only return the page number if the "First page number" option is set. if ( $self->{UsePage} ) { return $self->{PageStart}; } else { return 0; } } ############################################################################### # # get_print_order() # # Returns the Worksheet page printing order. # sub get_print_order { my $self = shift; return $self->{LeftToRight}; } ############################################################################### # # get_print_scale() # # Returns the workbook scale for printing. # sub get_print_scale { my $self = shift; return $self->{Scale}; } ############################################################################### # # get_fit_to_pages() # # Returns the number of pages wide and high that the printed worksheet page # will fit to. # sub get_fit_to_pages { my $self = shift; if ( !$self->{PageFit} ) { return ( 0, 0 ); } else { return ( $self->{FitWidth}, $self->{FitHeight} ); } } ############################################################################### # # is_portrait() # # Returns true if the worksheet has been set for printing in portrait mode. # sub is_portrait { my $self = shift; return $self->{Landscape}; } ############################################################################### # # is_centered_horizontally() # # Returns true if the worksheet has been centered horizontally for printing. # sub is_centered_horizontally { my $self = shift; return $self->{HCenter}; } ############################################################################### # # is_centered_vertically() # # Returns true if the worksheet has been centered vertically for printing. # sub is_centered_vertically { my $self = shift; return $self->{HCenter}; } ############################################################################### # # is_print_gridlines() # # Returns true if the worksheet print "gridlines" option is turned on. # sub is_print_gridlines { my $self = shift; return $self->{PrintGrid}; } ############################################################################### # # is_print_row_col_headers() # # Returns true if the worksheet print "row and column headings" option is on. # sub is_print_row_col_headers { my $self = shift; return $self->{PrintHeaders}; } ############################################################################### # # is_print_black_and_white() # # Returns true if the worksheet print "black and white" option is turned on. # sub is_print_black_and_white { my $self = shift; return $self->{NoColor}; } ############################################################################### # # is_print_draft() # # Returns true if the worksheet print "draft" option is turned on. # sub is_print_draft { my $self = shift; return $self->{Draft}; } ############################################################################### # # is_print_comments() # # Returns true if the worksheet print "comments" option is turned on. # sub is_print_comments { my $self = shift; return $self->{Notes}; } ############################################################################### # # Mapping between legacy method names and new names. # { no warnings; # Ignore warnings about variables used only once. *sheetNo = *sheet_num; *Cell = *get_cell; *RowRange = *row_range; *ColRange = *col_range; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Worksheet - A class for Worksheets. =head1 SYNOPSIS See the documentation for L. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 Methods The C class encapsulates the properties of an Excel worksheet. It has the following methods: $worksheet->get_cell() $worksheet->row_range() $worksheet->col_range() $worksheet->get_name() $worksheet->get_h_pagebreaks() $worksheet->get_v_pagebreaks() $worksheet->get_merged_areas() $worksheet->get_row_heights() $worksheet->get_col_widths() $worksheet->get_default_row_height() $worksheet->get_default_col_width() $worksheet->get_header() $worksheet->get_footer() $worksheet->get_margin_left() $worksheet->get_margin_right() $worksheet->get_margin_top() $worksheet->get_margin_bottom() $worksheet->get_margin_header() $worksheet->get_margin_footer() $worksheet->get_paper() $worksheet->get_start_page() $worksheet->get_print_order() $worksheet->get_print_scale() $worksheet->get_fit_to_pages() $worksheet->is_portrait() $worksheet->is_centered_horizontally() $worksheet->is_centered_vertically() $worksheet->is_print_gridlines() $worksheet->is_print_row_col_headers() $worksheet->is_print_black_and_white() $worksheet->is_print_draft() $worksheet->is_print_comments() =head2 get_cell($row, $col) Return the L object at row C<$row> and column C<$col> if it is defined. Otherwise returns undef. my $cell = $worksheet->get_cell($row, $col); =head2 row_range() Returns a two-element list C<($min, $max)> containing the minimum and maximum defined rows in the worksheet. If there is no row defined C<$max> is smaller than C<$min>. my ( $row_min, $row_max ) = $worksheet->row_range(); =head2 col_range() Returns a two-element list C<($min, $max)> containing the minimum and maximum of defined columns in the worksheet. If there is no column defined C<$max> is smaller than C<$min>. my ( $col_min, $col_max ) = $worksheet->col_range(); =head2 col_range() The C method returns TODO. my $col_range = $worksheet->col_range(); Returns 0 if the property isn't set. =head2 get_name() The C method returns the name of the worksheet. my $name = $worksheet->get_name(); =head2 get_h_pagebreaks() The C method returns an array ref of row numbers where a horizontal page break occurs. my $h_pagebreaks = $worksheet->get_h_pagebreaks(); Returns C if there are no pagebreaks. =head2 get_v_pagebreaks() The C method returns an array ref of column numbers where a vertical page break occurs. my $v_pagebreaks = $worksheet->get_v_pagebreaks(); Returns C if there are no pagebreaks. =head2 get_merged_areas() The C method returns an array ref of cells that are merged. my $merged_areas = $worksheet->get_merged_areas(); Each merged area is represented as follows: [ $start_row, $start_col, $end_row, $end_col] Returns C if there are no merged areas. =head2 get_row_heights() The C method returns an array_ref of row heights. my $row_heights = $worksheet->get_row_heights(); Returns C if the property isn't set. =head2 get_col_widths() The C method returns an array_ref of column widths. my $col_widths = $worksheet->get_col_widths(); Returns C if the property isn't set. =head2 get_default_row_height() The C method returns the default row height for the worksheet. Generally 12.75. my $default_row_height = $worksheet->get_default_row_height(); =head2 get_default_col_width() The C method returns the default column width for the worksheet. Generally 8.43. my $default_col_width = $worksheet->get_default_col_width(); =head2 get_header() The C method returns the worksheet header string. This string can contain control codes for alignment and font properties. Refer to the Excel on-line help on headers and footers or to the Spreadsheet::WriteExcel documentation for set_header(). my $header = $worksheet->get_header(); Returns C if the property isn't set. =head2 get_footer() The C method returns the worksheet footer string. This string can contain control codes for alignment and font properties. Refer to the Excel on-line help on headers and footers or to the Spreadsheet::WriteExcel documentation for set_header(). my $footer = $worksheet->get_footer(); Returns C if the property isn't set. =head2 get_margin_left() The C method returns the left margin of the worksheet in inches. my $margin_left = $worksheet->get_margin_left(); Returns C if the property isn't set. =head2 get_margin_right() The C method returns the right margin of the worksheet in inches. my $margin_right = $worksheet->get_margin_right(); Returns C if the property isn't set. =head2 get_margin_top() The C method returns the top margin of the worksheet in inches. my $margin_top = $worksheet->get_margin_top(); Returns C if the property isn't set. =head2 get_margin_bottom() The C method returns the bottom margin of the worksheet in inches. my $margin_bottom = $worksheet->get_margin_bottom(); Returns C if the property isn't set. =head2 get_margin_header() The C method returns the header margin of the worksheet in inches. my $margin_header = $worksheet->get_margin_header(); Returns a default value of 0.5 if not set. =head2 get_margin_footer() The C method returns the footer margin of the worksheet in inches. my $margin_footer = $worksheet->get_margin_footer(); Returns a default value of 0.5 if not set. =head2 get_paper() The C method returns the printer paper size. my $paper = $worksheet->get_paper(); The value corresponds to the formats shown below: Index Paper format Paper size ===== ============ ========== 0 Printer default - 1 Letter 8 1/2 x 11 in 2 Letter Small 8 1/2 x 11 in 3 Tabloid 11 x 17 in 4 Ledger 17 x 11 in 5 Legal 8 1/2 x 14 in 6 Statement 5 1/2 x 8 1/2 in 7 Executive 7 1/4 x 10 1/2 in 8 A3 297 x 420 mm 9 A4 210 x 297 mm 10 A4 Small 210 x 297 mm 11 A5 148 x 210 mm 12 B4 250 x 354 mm 13 B5 182 x 257 mm 14 Folio 8 1/2 x 13 in 15 Quarto 215 x 275 mm 16 - 10x14 in 17 - 11x17 in 18 Note 8 1/2 x 11 in 19 Envelope 9 3 7/8 x 8 7/8 20 Envelope 10 4 1/8 x 9 1/2 21 Envelope 11 4 1/2 x 10 3/8 22 Envelope 12 4 3/4 x 11 23 Envelope 14 5 x 11 1/2 24 C size sheet - 25 D size sheet - 26 E size sheet - 27 Envelope DL 110 x 220 mm 28 Envelope C3 324 x 458 mm 29 Envelope C4 229 x 324 mm 30 Envelope C5 162 x 229 mm 31 Envelope C6 114 x 162 mm 32 Envelope C65 114 x 229 mm 33 Envelope B4 250 x 353 mm 34 Envelope B5 176 x 250 mm 35 Envelope B6 176 x 125 mm 36 Envelope 110 x 230 mm 37 Monarch 3.875 x 7.5 in 38 Envelope 3 5/8 x 6 1/2 in 39 Fanfold 14 7/8 x 11 in 40 German Std Fanfold 8 1/2 x 12 in 41 German Legal Fanfold 8 1/2 x 13 in 256 User defined The two most common paper sizes are C<1 = "US Letter"> and C<9 = A4>. Returns 9 by default. =head2 get_start_page() The C method returns the page number that printing will start from. my $start_page = $worksheet->get_start_page(); Returns 0 if the property isn't set. =head2 get_print_order() The C method returns 0 if the worksheet print "page order" is "Down then over" (the default) or 1 if it is "Over then down". my $print_order = $worksheet->get_print_order(); =head2 get_print_scale() The C method returns the workbook scale for printing. The print scale fctor can be in the range 10 .. 400. my $print_scale = $worksheet->get_print_scale(); Returns 100 by default. =head2 get_fit_to_pages() The C method returns the number of pages wide and high that the printed worksheet page will fit to. my ($pages_wide, $pages_high) = $worksheet->get_fit_to_pages(); Returns (0, 0) if the property isn't set. =head2 is_portrait() The C method returns true if the worksheet has been set for printing in portrait mode. my $is_portrait = $worksheet->is_portrait(); Returns 0 if the worksheet has been set for printing in horizontal mode. =head2 is_centered_horizontally() The C method returns true if the worksheet has been centered horizontally for printing. my $is_centered_horizontally = $worksheet->is_centered_horizontally(); Returns 0 if the property isn't set. =head2 is_centered_vertically() The C method returns true if the worksheet has been centered vertically for printing. my $is_centered_vertically = $worksheet->is_centered_vertically(); Returns 0 if the property isn't set. =head2 is_print_gridlines() The C method returns true if the worksheet print "gridlines" option is turned on. my $is_print_gridlines = $worksheet->is_print_gridlines(); Returns 0 if the property isn't set. =head2 is_print_row_col_headers() The C method returns true if the worksheet print "row and column headings" option is turned on. my $is_print_row_col_headers = $worksheet->is_print_row_col_headers(); Returns 0 if the property isn't set. =head2 is_print_black_and_white() The C method returns true if the worksheet print "black and white" option is turned on. my $is_print_black_and_white = $worksheet->is_print_black_and_white(); Returns 0 if the property isn't set. =head2 is_print_draft() The C method returns true if the worksheet print "draft" option is turned on. my $is_print_draft = $worksheet->is_print_draft(); Returns 0 if the property isn't set. =head2 is_print_comments() The C method returns true if the worksheet print "comments" option is turned on. my $is_print_comments = $worksheet->is_print_comments(); Returns 0 if the property isn't set. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/Workbook.pm0000644000176000001440000001464111326376247021757 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Workbook; ############################################################################### # # Spreadsheet::ParseExcel::Workbook - A class for Workbooks. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; our $VERSION = '0.56'; ############################################################################### # # new() # # Constructor. # sub new { my ($class) = @_; my $self = {}; bless $self, $class; } ############################################################################### # # worksheet() # # This method returns a single Worksheet object using either its name or index. # sub worksheet { my ( $oBook, $sName ) = @_; my $oWkS; foreach $oWkS ( @{ $oBook->{Worksheet} } ) { return $oWkS if ( $oWkS->{Name} eq $sName ); } if ( $sName =~ /^\d+$/ ) { return $oBook->{Worksheet}->[$sName]; } return undef; } ############################################################################### # # worksheets() # # Returns an array ofWorksheet objects. # sub worksheets { my $self = shift; return @{ $self->{Worksheet} }; } ############################################################################### # # worksheet_count() # # Returns the number Woksheet objects in the Workbook. # sub worksheet_count { my $self = shift; return $self->{SheetCount}; } ############################################################################### # # get_filename() # # Returns the name of the Excel file of C if the data was read from a filehandle rather than a file. # sub get_filename { my $self = shift; return $self->{File}; } ############################################################################### # # get_print_areas() # # Returns an array ref of print areas. # # TODO. This should really be a Worksheet method. # sub get_print_areas { my $self = shift; return $self->{PrintArea}; } ############################################################################### # # get_print_titles() # # Returns an array ref of print title hash refs. # # TODO. This should really be a Worksheet method. # sub get_print_titles { my $self = shift; return $self->{PrintTitle}; } ############################################################################### # # using_1904_date() # # Returns true if the Excel file is using the 1904 date epoch. # sub using_1904_date { my $self = shift; return $self->{Flg1904}; } ############################################################################### # # ParseAbort() # # Todo # sub ParseAbort { my ( $self, $val ) = @_; $self->{_ParseAbort} = $val; } ############################################################################### # # Parse(). Deprecated. # # Syntactic wrapper around Spreadsheet::ParseExcel::Parse(). # This method is *deprecated* since it doesn't conform to the the current # error handling in the S::PE Parse() method. # sub Parse { my ( $class, $source, $formatter ) = @_; my $excel = Spreadsheet::ParseExcel->new(); my $workbook = $excel->Parse( $source, $formatter ); $workbook->{_Excel} = $excel; return $workbook; } ############################################################################### # # Mapping between legacy method names and new names. # { no warnings; # Ignore warnings about variables used only once. *Worksheet = *worksheet; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Workbook - A class for Workbooks. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for L. =head1 Methods The following Workbook methods are available: $workbook->worksheets() $workbook->worksheet() $workbook->worksheet_count() $workbook->get_filename() $workbook->get_print_areas() $workbook->get_print_titles() $workbook->using_1904_date() =head2 worksheets() The C method returns an array of Worksheet objects. This was most commonly used to iterate over the worksheets in a workbook: for my $worksheet ( $workbook->worksheets() ) { ... } =head2 worksheet() The C method returns a single C object using either its name or index: $worksheet = $workbook->worksheet('Sheet1'); $worksheet = $workbook->worksheet(0); Returns C if the sheet name or index doesn't exist. =head2 worksheet_count() The C method returns the number of Woksheet objects in the Workbook. my $worksheet_count = $workbook->worksheet_count(); =head2 get_filename() The C method returns the name of the Excel file of C if the data was read from a filehandle rather than a file. my $filename = $workbook->get_filename(); =head2 get_print_areas() The C method returns an array ref of print areas. my $print_areas = $workbook->get_print_areas(); Each print area is as follows: [ $start_row, $start_col, $end_row, $end_col ] Returns undef if there are no print areas. =head2 get_print_titles() The C method returns an array ref of print title hash refs. my $print_titles = $workbook->get_print_titles(); Each print title array ref is as follows: { Row => [ $start_row, $end_row ], Column => [ $start_col, $end_col ], } Returns undef if there are no print titles. =head2 using_1904_date() The C method returns true if the Excel file is using the 1904 date epoch instead of the 1900 epoch. my $using_1904_date = $workbook->using_1904_date(); The Windows version of Excel generally uses the 1900 epoch while the Mac version of Excel generally uses the 1904 epoch. Returns 0 if the 1900 epoch is in use. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/Utility.pm0000644000176000001440000015353611326376247021634 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Utility; ############################################################################### # # Spreadsheet::ParseExcel::Utility - Utility functions for ParseExcel. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; require Exporter; use vars qw(@ISA @EXPORT_OK); @ISA = qw(Exporter); @EXPORT_OK = qw(ExcelFmt LocaltimeExcel ExcelLocaltime col2int int2col sheetRef xls2csv); our $VERSION = '0.56'; my $qrNUMBER = qr/(^[+-]?\d+(\.\d+)?$)|(^[+-]?\d+\.?(\d*)[eE][+-](\d+))$/; ############################################################################### # # ExcelFmt() # # This function takes an Excel style number format and converts a number into # that format. for example: 'hh:mm:ss AM/PM' + 0.01023148 = '12:14:44 AM'. # # It does this with a type of templating mechanism. The format string is parsed # to identify tokens that need to be replaced and their position within the # string is recorded. These can be thought of as placeholders. The number is # then converted to the required formats and substituted into the placeholders. # # Interested parties should refer to the Excel documentation on cell formats for # more information: http://office.microsoft.com/en-us/excel/HP051995001033.aspx # The Microsoft documentation for the Excel Binary File Format, [MS-XLS].pdf, # also contains a ABNF grammar for number format strings. # # Maintainers notes: # ================== # # Note on format subsections: # A format string can contain 4 possible sub-sections separated by semi-colons: # Positive numbers, negative numbers, zero values, and text. # For example: _(* #,##0_);_(* (#,##0);_(* "-"_);_(@_) # # Note on conditional formats. # A number format in Excel can have a conditional expression such as: # [>9999999](000)000-0000;000-0000 # This is equivalent to the following in Perl: # $format = $number > 9999999 ? '(000)000-0000' : '000-0000'; # Nested conditionals are also possible but we don't support them. # # Efficiency: The excessive use of substr() isn't very efficient. However, # it probably doesn't merit rewriting this function with a parser or regular # expressions and \G. # # TODO: I think the single quote handling may not be required. Check. # sub ExcelFmt { my ( $format_str, $number, $is_1904, $number_type, $want_subformats ) = @_; # Return text strings without further formatting. return $number unless $number =~ $qrNUMBER; # Handle OpenOffice.org GENERAL format. $format_str = '@' if uc($format_str) eq "GENERAL"; # Check for a conditional at the start of the format. See notes above. my $conditional; if ( $format_str =~ /^\[([<>=][^\]]+)\](.*)$/ ) { $conditional = $1; $format_str = $2; } # Ignore the underscore token which is used to indicate a padding space. $format_str =~ s/_/ /g; # Split the format string into 4 possible sub-sections: positive numbers, # negative numbers, zero values, and text. See notes above. my @formats; my $section = 0; my $double_quote = 0; my $single_quote = 0; # Initial parsing of the format string to remove escape characters. This # also handles quoted strings. See note about single quotes above. CHARACTER: for my $char ( split //, $format_str ) { if ( $double_quote or $single_quote ) { $formats[$section] .= $char; $double_quote = 0 if $char eq '"'; $single_quote = 0; next CHARACTER; } if ( $char eq ';' ) { $section++; next CHARACTER; } elsif ( $char eq '"' ) { $double_quote = 1; } elsif ( $char eq '!' ) { $single_quote = 1; } elsif ( $char eq '\\' ) { $single_quote = 1; } elsif ( $char eq '(' ) { next CHARACTER; # Ignore. } elsif ( $char eq ')' ) { next CHARACTER; # Ignore. } # Convert upper case OpenOffice.org date/time formats to lowercase.. $char = lc($char) if $char =~ /[DMYHS]/; $formats[$section] .= $char; } # Select the appropriate format from the 4 possible sub-sections: # positive numbers, negative numbers, zero values, and text. # We ignore the Text section since non-numeric values are returned # unformatted at the start of the function. my $format; $section = 0; if ( @formats == 1 ) { $section = 0; } elsif ( @formats == 2 ) { if ( $number < 0 ) { $section = 1; } else { $section = 0; } } elsif ( @formats == 3 ) { if ( $number == 0 ) { $section = 2; } elsif ( $number < 0 ) { $section = 1; } else { $section = 0; } } else { $section = 0; } # Override the previous choice if the format is conditional. if ($conditional) { # TODO. Replace string eval with a function. $section = eval "$number $conditional" ? 0 : 1; } # We now have the required format. $format = $formats[$section]; # The format string can contain one of the following colours: # [Black] [Blue] [Cyan] [Green] [Magenta] [Red] [White] [Yellow] # or the string [ColorX] where x is a colour index from 1 to 56. # We don't use the colour but we return it to the caller. # my $color = ''; if ( $format =~ s/^(\[[A-Z][a-z]{2,}(\d{1,2})?\])// ) { $color = $1; } # Remove the locale, such as [$-409], from the format string. my $locale = ''; if ( $format =~ s/^(\[\$-\d+\])// ) { $locale = $1; } # Remove leading # from '# ?/?', '# ??/??' fraction formats. $format =~ s{# \?}{?}g; # Parse the format string and create an AoA of placeholders that contain # the parts of the string to be replaced. The format of the information # stored is: [ $token, $start_pos, $end_pos, $option_info ]. # my $format_mode = ''; # Either: '', 'number', 'date' my $pos = 0; # Character position within format string. my @placeholders = (); # Arefs with parts of the format to be replaced. my $token = ''; # The actual format extracted from the total str. my $start_pos; # A position variable. Initial parser position. my $token_start = -1; # A position variable. my $decimal_pos = -1; # Position of the punctuation char "." or ",". my $comma_count = 0; # Count of the commas in the format. my $is_fraction = 0; # Number format is a fraction. my $is_currency = 0; # Number format is a currency. my $is_percent = 0; # Number format is a percentage. my $is_12_hour = 0; # Time format is using 12 hour clock. my $seen_dot = 0; # Treat only the first "." as the decimal point. # Parse the format. PARSER: while ( $pos < length $format ) { $start_pos = $pos; my $char = substr( $format, $pos, 1 ); # Ignore control format characters such as '#0+-.?eE,%'. However, # only ignore '.' if it is the first one encountered. RT 45502. if ( ( !$seen_dot && $char !~ /[#0\+\-\.\?eE\,\%]/ ) || $char !~ /[#0\+\-\?eE\,\%]/ ) { if ( $token_start != -1 ) { push @placeholders, [ substr( $format, $token_start, $pos - $token_start ), $decimal_pos, $pos - $token_start ]; $token_start = -1; } } # Processing for quoted strings within the format. See notes above. if ( $char eq '"' ) { $double_quote = $double_quote ? 0 : 1; $pos++; next PARSER; } elsif ( $char eq '!' ) { $single_quote = 1; $pos++; next PARSER; } elsif ( $char eq '\\' ) { if ( $single_quote != 1 ) { $single_quote = 1; $pos++; next PARSER; } } if ( ( defined($double_quote) and ($double_quote) ) or ( defined($single_quote) and ($single_quote) ) or ( $seen_dot && $char eq '.' ) ) { $single_quote = 0; if ( ( $format_mode ne 'date' ) and ( ( substr( $format, $pos, 2 ) eq "\x81\xA2" ) || ( substr( $format, $pos, 2 ) eq "\x81\xA3" ) || ( substr( $format, $pos, 2 ) eq "\xA2\xA4" ) || ( substr( $format, $pos, 2 ) eq "\xA2\xA5" ) ) ) { # The above matches are currency symbols. push @placeholders, [ substr( $format, $pos, 2 ), length($token), 2 ]; $is_currency = 1; $pos += 2; } else { $pos++; } } elsif ( ( $char =~ /[#0\+\.\?eE\,\%]/ ) || ( ( $format_mode ne 'date' ) and ( ( $char eq '-' ) || ( $char eq '(' ) || ( $char eq ')' ) ) ) ) { $format_mode = 'number' unless $format_mode; if ( substr( $format, $pos, 1 ) =~ /[#0]/ ) { if ( substr( $format, $pos ) =~ /^([#0]+[\.]?[0#]*[eE][\+\-][0#]+)/ ) { push @placeholders, [ $1, $pos, length($1) ]; $pos += length($1); } else { if ( $token_start == -1 ) { $token_start = $pos; $decimal_pos = length($token); } } } elsif ( substr( $format, $pos, 1 ) eq '?' ) { # Look for a fraction format like ?/? or ??/?? if ( $token_start != -1 ) { push @placeholders, [ substr( $format, $token_start, $pos - $token_start + 1 ), $decimal_pos, $pos - $token_start + 1 ]; } $token_start = $pos; # Find the end of the fraction format. FRACTION: while ( $pos < length($format) ) { if ( substr( $format, $pos, 1 ) eq '/' ) { $is_fraction = 1; } elsif ( substr( $format, $pos, 1 ) eq '?' ) { $pos++; next FRACTION; } else { if ( $is_fraction && ( substr( $format, $pos, 1 ) =~ /[0-9]/ ) ) { # TODO: Could invert if() logic and remove this. $pos++; next FRACTION; } else { last FRACTION; } } $pos++; } $pos--; push @placeholders, [ substr( $format, $token_start, $pos - $token_start + 1 ), length($token), $pos - $token_start + 1 ]; $token_start = -1; } elsif ( substr( $format, $pos, 3 ) =~ /^[eE][\+\-][0#]$/ ) { if ( substr( $format, $pos ) =~ /([eE][\+\-][0#]+)/ ) { push @placeholders, [ $1, $pos, length($1) ]; $pos += length($1); } $token_start = -1; } else { if ( $token_start != -1 ) { push @placeholders, [ substr( $format, $token_start, $pos - $token_start ), $decimal_pos, $pos - $token_start ]; $token_start = -1; } if ( substr( $format, $pos, 1 ) =~ /[\+\-]/ ) { push @placeholders, [ substr( $format, $pos, 1 ), length($token), 1 ]; $is_currency = 1; } elsif ( substr( $format, $pos, 1 ) eq '.' ) { push @placeholders, [ substr( $format, $pos, 1 ), length($token), 1 ]; $seen_dot = 1; } elsif ( substr( $format, $pos, 1 ) eq ',' ) { $comma_count++; push @placeholders, [ substr( $format, $pos, 1 ), length($token), 1 ]; } elsif ( substr( $format, $pos, 1 ) eq '%' ) { $is_percent = 1; } elsif (( substr( $format, $pos, 1 ) eq '(' ) || ( substr( $format, $pos, 1 ) eq ')' ) ) { push @placeholders, [ substr( $format, $pos, 1 ), length($token), 1 ]; $is_currency = 1; } } $pos++; } elsif ( $char =~ /[ymdhsapg]/i ) { $format_mode = 'date' unless $format_mode; if ( substr( $format, $pos, 5 ) =~ /am\/pm/i ) { push @placeholders, [ 'am/pm', length($token), 5 ]; $is_12_hour = 1; $pos += 5; } elsif ( substr( $format, $pos, 3 ) =~ /a\/p/i ) { push @placeholders, [ 'a/p', length($token), 3 ]; $is_12_hour = 1; $pos += 3; } elsif ( substr( $format, $pos, 5 ) eq 'mmmmm' ) { push @placeholders, [ 'mmmmm', length($token), 5 ]; $pos += 5; } elsif (( substr( $format, $pos, 4 ) eq 'mmmm' ) || ( substr( $format, $pos, 4 ) eq 'dddd' ) || ( substr( $format, $pos, 4 ) eq 'yyyy' ) || ( substr( $format, $pos, 4 ) eq 'ggge' ) ) { push @placeholders, [ substr( $format, $pos, 4 ), length($token), 4 ]; $pos += 4; } elsif (( substr( $format, $pos, 3 ) eq 'ddd' ) || ( substr( $format, $pos, 3 ) eq 'mmm' ) || ( substr( $format, $pos, 3 ) eq 'yyy' ) ) { push @placeholders, [ substr( $format, $pos, 3 ), length($token), 3 ]; $pos += 3; } elsif (( substr( $format, $pos, 2 ) eq 'yy' ) || ( substr( $format, $pos, 2 ) eq 'mm' ) || ( substr( $format, $pos, 2 ) eq 'dd' ) || ( substr( $format, $pos, 2 ) eq 'hh' ) || ( substr( $format, $pos, 2 ) eq 'ss' ) || ( substr( $format, $pos, 2 ) eq 'ge' ) ) { if ( ( substr( $format, $pos, 2 ) eq 'mm' ) && (@placeholders) && ( ( $placeholders[-1]->[0] eq 'h' ) or ( $placeholders[-1]->[0] eq 'hh' ) ) ) { # For this case 'm' is minutes not months. push @placeholders, [ 'mm', length($token), 2, 'minutes' ]; } else { push @placeholders, [ substr( $format, $pos, 2 ), length($token), 2 ]; } if ( ( substr( $format, $pos, 2 ) eq 'ss' ) && ( @placeholders > 1 ) ) { if ( ( $placeholders[-2]->[0] eq 'm' ) || ( $placeholders[-2]->[0] eq 'mm' ) ) { # For this case 'm' is minutes not months. push( @{ $placeholders[-2] }, 'minutes' ); } } $pos += 2; } elsif (( substr( $format, $pos, 1 ) eq 'm' ) || ( substr( $format, $pos, 1 ) eq 'd' ) || ( substr( $format, $pos, 1 ) eq 'h' ) || ( substr( $format, $pos, 1 ) eq 's' ) ) { if ( ( substr( $format, $pos, 1 ) eq 'm' ) && (@placeholders) && ( ( $placeholders[-1]->[0] eq 'h' ) or ( $placeholders[-1]->[0] eq 'hh' ) ) ) { # For this case 'm' is minutes not months. push @placeholders, [ 'm', length($token), 1, 'minutes' ]; } else { push @placeholders, [ substr( $format, $pos, 1 ), length($token), 1 ]; } if ( ( substr( $format, $pos, 1 ) eq 's' ) && ( @placeholders > 1 ) ) { if ( ( $placeholders[-2]->[0] eq 'm' ) || ( $placeholders[-2]->[0] eq 'mm' ) ) { # For this case 'm' is minutes not months. push( @{ $placeholders[-2] }, 'minutes' ); } } $pos += 1; } } elsif ( ( substr( $format, $pos, 3 ) eq '[h]' ) ) { $format_mode = 'date' unless $format_mode; push @placeholders, [ '[h]', length($token), 3 ]; $pos += 3; } elsif ( ( substr( $format, $pos, 4 ) eq '[mm]' ) ) { $format_mode = 'date' unless $format_mode; push @placeholders, [ '[mm]', length($token), 4 ]; $pos += 4; } elsif ( $char eq '@' ) { push @placeholders, [ '@', length($token), 1 ]; $pos++; } elsif ( $char eq '*' ) { push @placeholders, [ substr( $format, $pos, 1 ), length($token), 1 ]; } else { $pos++; } $pos++ if ( $pos == $start_pos ); #No Format match $token .= substr( $format, $start_pos, $pos - $start_pos ); } # End of parsing. # Copy the located format string to a result string that we will perform # the substitutions on and return to the user. my $result = $token; # Add a placeholder between the decimal/comma and end of the token, if any. if ( $token_start != -1 ) { push @placeholders, [ substr( $format, $token_start, $pos - $token_start + 1 ), $decimal_pos, $pos - $token_start + 1 ]; } # # In the next sections we process date, number and text formats. We take a # format such as yyyy/mm/dd and replace it with something like 2008/12/25. # if ( ( $format_mode eq 'date' ) && ( $number =~ $qrNUMBER ) ) { # The maximum allowable date in Excel is 9999-12-31T23:59:59.000 which # equates to 2958465.999+ in the 1900 epoch and 2957003.999+ in the # 1904 epoch. We use 0 as the minimum in both epochs. The 1904 system # actually supports negative numbers but that isn't worth the effort. my $min_date = 0; my $max_date = 2958466; $max_date = 2957004 if $is_1904; if ( $number < $min_date || $number >= $max_date ) { return $number; # Return unformatted number. } # Process date formats. my @time = ExcelLocaltime( $number, $is_1904 ); # 0 1 2 3 4 5 6 7 my ( $sec, $min, $hour, $day, $month, $year, $wday, $msec ) = @time; $month++; # localtime() zero indexed month. $year += 1900; # localtime() year. my @full_month_name = qw( None January February March April May June July August September October November December ); my @short_month_name = qw( None Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ); my @full_day_name = qw( Sunday Monday Tuesday Wednesday Thursday Friday Saturday ); my @short_day_name = qw( Sun Mon Tue Wed Thu Fri Sat ); # Replace the placeholders in the template such as yyyy mm dd with # actual numbers or strings. my $replacement; for ( my $i = @placeholders - 1 ; $i >= 0 ; $i-- ) { my $placeholder = $placeholders[$i]; if ( $placeholder->[-1] eq 'minutes' ) { # For this case 'm/mm' is minutes not months. if ( $placeholder->[0] eq 'mm' ) { $replacement = sprintf( "%02d", $min ); } else { $replacement = sprintf( "%d", $min ); } } elsif ( $placeholder->[0] eq 'yyyy' ) { # 4 digit Year. 2000 -> 2000. $replacement = sprintf( '%04d', $year ); } elsif ( $placeholder->[0] eq 'yy' ) { # 2 digit Year. 2000 -> 00. $replacement = sprintf( '%02d', $year % 100 ); } elsif ( $placeholder->[0] eq 'mmmmm' ) { # First character of the month name. 1 -> J. $replacement = substr( $short_month_name[$month], 0, 1 ); } elsif ( $placeholder->[0] eq 'mmmm' ) { # Full month name. 1 -> January. $replacement = $full_month_name[$month]; } elsif ( $placeholder->[0] eq 'mmm' ) { # Short month name. 1 -> Jan. $replacement = $short_month_name[$month]; } elsif ( $placeholder->[0] eq 'mm' ) { # 2 digit month. 1 -> 01. $replacement = sprintf( '%02d', $month ); } elsif ( $placeholder->[0] eq 'm' ) { # 1 digit month. 1 -> 1. $replacement = sprintf( '%d', $month ); } elsif ( $placeholder->[0] eq 'dddd' ) { # Full day name. Wednesday (for example.) $replacement = $full_day_name[$wday]; } elsif ( $placeholder->[0] eq 'ddd' ) { # Short day name. Wed (for example.) $replacement = $short_day_name[$wday]; } elsif ( $placeholder->[0] eq 'dd' ) { # 2 digit day. 1 -> 01. $replacement = sprintf( '%02d', $day ); } elsif ( $placeholder->[0] eq 'd' ) { # 1 digit day. 1 -> 1. $replacement = sprintf( '%d', $day ); } elsif ( $placeholder->[0] eq 'hh' ) { # 2 digit hour. if ($is_12_hour) { my $hour_tmp = $hour % 12; $hour_tmp = 12 if $hour % 12 == 0; $replacement = sprintf( '%d', $hour_tmp ); } else { $replacement = sprintf( '%02d', $hour ); } } elsif ( $placeholder->[0] eq 'h' ) { # 1 digit hour. if ($is_12_hour) { my $hour_tmp = $hour % 12; $hour_tmp = 12 if $hour % 12 == 0; $replacement = sprintf( '%2d', $hour_tmp ); } else { $replacement = sprintf( '%d', $hour ); } } elsif ( $placeholder->[0] eq 'ss' ) { # 2 digit seconds. $replacement = sprintf( '%02d', $sec ); } elsif ( $placeholder->[0] eq 's' ) { # 1 digit seconds. $replacement = sprintf( '%d', $sec ); } elsif ( $placeholder->[0] eq 'am/pm' ) { # AM/PM. $replacement = ( $hour >= 12 ) ? 'PM' : 'AM'; } elsif ( $placeholder->[0] eq 'a/p' ) { # AM/PM. $replacement = ( $hour >= 12 ) ? 'P' : 'A'; } elsif ( $placeholder->[0] eq '.' ) { # Decimal point for seconds. $replacement = '.'; } elsif ( $placeholder->[0] =~ /(^0+$)/ ) { # Milliseconds. For example h:ss.000. my $length = length($1); $replacement = substr( sprintf( "%.${length}f", $msec / 1000 ), 2, $length ); } elsif ( $placeholder->[0] eq '[h]' ) { # Hours modulus 24. 25 displays as 25 not as 1. $replacement = sprintf( '%d', int($number) * 24 + $hour ); } elsif ( $placeholder->[0] eq '[mm]' ) { # Mins modulus 60. 72 displays as 72 not as 12. $replacement = sprintf( '%d', ( int($number) * 24 + $hour ) * 60 + $min ); } elsif ( $placeholder->[0] eq 'ge' ) { require Spreadsheet::ParseExcel::FmtJapan; # Japanese Nengo (aka Gengo) in initialism (abbr. name) $replacement = Spreadsheet::ParseExcel::FmtJapan::CnvNengo( abbr_name => @time ); } elsif ( $placeholder->[0] eq 'ggge' ) { require Spreadsheet::ParseExcel::FmtJapan; # Japanese Nengo (aka Gengo) in Kanji (full name) $replacement = Spreadsheet::ParseExcel::FmtJapan::CnvNengo( name => @time ); } elsif ( $placeholder->[0] eq '@' ) { # Text format. $replacement = $number; } # Substitute the replacement string back into the template. substr( $result, $placeholder->[1], $placeholder->[2], $replacement ); } } elsif ( ( $format_mode eq 'number' ) && ( $number =~ $qrNUMBER ) ) { # Process non date formats. if (@placeholders) { while ( $placeholders[-1]->[0] eq ',' ) { $comma_count--; substr( $result, $placeholders[-1]->[1], $placeholders[-1]->[2], '' ); $number /= 1000; pop @placeholders; } my $number_format = join( '', map { $_->[0] } @placeholders ); my $number_result; my $str_length = 0; my $engineering = 0; my $is_decimal = 0; my $is_integer = 0; my $after_decimal = undef; for my $token ( split //, $number_format ) { if ( $token eq '.' ) { $str_length++; $is_decimal = 1; } elsif ( ( $token eq 'E' ) || ( $token eq 'e' ) ) { $engineering = 1; } elsif ( $token eq '0' ) { $str_length++; $after_decimal++ if $is_decimal; $is_integer = 1; } elsif ( $token eq '#' ) { $after_decimal++ if $is_decimal; $is_integer = 1; } elsif ( $token eq '?' ) { $after_decimal++ if $is_decimal; } } $number *= 100.0 if $is_percent; my $data = ($is_currency) ? abs($number) : $number + 0; if ($is_fraction) { $number_result = sprintf( "%0${str_length}d", int($data) ); } else { if ($is_decimal) { if ( defined $after_decimal ) { $number_result = sprintf "%0${str_length}.${after_decimal}f", $data; } else { $number_result = sprintf "%0${str_length}f", $data; } # Fix for Perl and sprintf not rounding up like Excel. # http://rt.cpan.org/Public/Bug/Display.html?id=45626 if ( $data =~ /^${number_result}5/ ) { $number_result = sprintf "%0${str_length}.${after_decimal}f", $data . '1'; } } else { $number_result = sprintf( "%0${str_length}.0f", $data ); } } $number_result = AddComma($number_result) if $comma_count > 0; my $number_length = length($number_result); my $decimal_pos = -1; my $replacement; for ( my $i = @placeholders - 1 ; $i >= 0 ; $i-- ) { my $placeholder = $placeholders[$i]; if ( $placeholder->[0] =~ /([#0]*)([\.]?)([0#]*)([eE])([\+\-])([0#]+)/ ) { substr( $result, $placeholder->[1], $placeholder->[2], MakeE( $placeholder->[0], $number ) ); } elsif ( $placeholder->[0] =~ /\// ) { substr( $result, $placeholder->[1], $placeholder->[2], MakeFraction( $placeholder->[0], $number, $is_integer ) ); } elsif ( $placeholder->[0] eq '.' ) { $number_length--; $decimal_pos = $number_length; } elsif ( $placeholder->[0] eq '+' ) { substr( $result, $placeholder->[1], $placeholder->[2], ( $number > 0 ) ? '+' : ( ( $number == 0 ) ? '+' : '-' ) ); } elsif ( $placeholder->[0] eq '-' ) { substr( $result, $placeholder->[1], $placeholder->[2], ( $number > 0 ) ? '' : ( ( $number == 0 ) ? '' : '-' ) ); } elsif ( $placeholder->[0] eq '@' ) { substr( $result, $placeholder->[1], $placeholder->[2], $number ); } elsif ( $placeholder->[0] eq '*' ) { substr( $result, $placeholder->[1], $placeholder->[2], '' ); } elsif (( $placeholder->[0] eq "\xA2\xA4" ) or ( $placeholder->[0] eq "\xA2\xA5" ) or ( $placeholder->[0] eq "\x81\xA2" ) or ( $placeholder->[0] eq "\x81\xA3" ) ) { substr( $result, $placeholder->[1], $placeholder->[2], $placeholder->[0] ); } elsif (( $placeholder->[0] eq '(' ) or ( $placeholder->[0] eq ')' ) ) { substr( $result, $placeholder->[1], $placeholder->[2], $placeholder->[0] ); } else { if ( $number_length > 0 ) { if ( $i <= 0 ) { $replacement = substr( $number_result, 0, $number_length ); $number_length = 0; } else { my $real_part_length = length( $placeholder->[0] ); if ( $decimal_pos >= 0 ) { my $format = $placeholder->[0]; $format =~ s/^#+//; $real_part_length = length $format; $real_part_length = ( $number_length <= $real_part_length ) ? $number_length : $real_part_length; } else { $real_part_length = ( $number_length <= $real_part_length ) ? $number_length : $real_part_length; } $replacement = substr( $number_result, $number_length - $real_part_length, $real_part_length ); $number_length -= $real_part_length; } } else { $replacement = ''; } substr( $result, $placeholder->[1], $placeholder->[2], "\x00" . $replacement ); } } $replacement = ( $number_length > 0 ) ? substr( $number_result, 0, $number_length ) : ''; $result =~ s/\x00/$replacement/; $result =~ s/\x00//g; } } else { # Process text formats my $is_text = 0; for ( my $i = @placeholders - 1 ; $i >= 0 ; $i-- ) { my $placeholder = $placeholders[$i]; if ( $placeholder->[0] eq '@' ) { substr( $result, $placeholder->[1], $placeholder->[2], $number ); $is_text++; } else { substr( $result, $placeholder->[1], $placeholder->[2], '' ); } } $result = $number unless $is_text; } # End of placeholder substitutions. # Trim the leading and trailing whitespace from the results. $result =~ s/^\s+//; $result =~ s/\s+$//; # Fix for negative currency. $result =~ s/^\$\-/\-\$/; $result =~ s/^\$ \-/\-\$ /; # Return color and locale strings if required. if ($want_subformats) { return ( $result, $color, $locale ); } else { return $result; } } #------------------------------------------------------------------------------ # AddComma (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ sub AddComma { my ($sNum) = @_; if ( $sNum =~ /^([^\d]*)(\d\d\d\d+)(\.*.*)$/ ) { my ( $sPre, $sObj, $sAft ) = ( $1, $2, $3 ); for ( my $i = length($sObj) - 3 ; $i > 0 ; $i -= 3 ) { substr( $sObj, $i, 0, ',' ); } return $sPre . $sObj . $sAft; } else { return $sNum; } } #------------------------------------------------------------------------------ # MakeFraction (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ sub MakeFraction { my ( $sFmt, $iData, $iFlg ) = @_; my $iBunbo; my $iShou; #1. Init # print "FLG: $iFlg\n"; if ($iFlg) { $iShou = $iData - int($iData); return '' if ( $iShou == 0 ); } else { $iShou = $iData; } $iShou = abs($iShou); my $sSWk; #2.Calc BUNBO #2.1 BUNBO defined if ( $sFmt =~ /\/(\d+)$/ ) { $iBunbo = $1; return sprintf( "%d/%d", $iShou * $iBunbo, $iBunbo ); } else { #2.2 Calc BUNBO $sFmt =~ /\/(\?+)$/; my $iKeta = length($1); my $iSWk = 1; my $sSWk = ''; my $iBunsi; for ( my $iBunbo = 2 ; $iBunbo < 10**$iKeta ; $iBunbo++ ) { $iBunsi = int( $iShou * $iBunbo + 0.5 ); my $iCmp = abs( $iShou - ( $iBunsi / $iBunbo ) ); if ( $iCmp < $iSWk ) { $iSWk = $iCmp; $sSWk = sprintf( "%d/%d", $iBunsi, $iBunbo ); last if ( $iSWk == 0 ); } } return $sSWk; } } #------------------------------------------------------------------------------ # MakeE (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ sub MakeE { my ( $sFmt, $iData ) = @_; $sFmt =~ /(([#0]*)[\.]?[#0]*)([eE])([\+\-][0#]+)/; my ( $sKari, $iKeta, $sE, $sSisu ) = ( $1, length($2), $3, $4 ); $iKeta = 1 if ( $iKeta <= 0 ); my $iLog10 = 0; $iLog10 = ( $iData == 0 ) ? 0 : ( log( abs($iData) ) / log(10) ); $iLog10 = ( int( $iLog10 / $iKeta ) + ( ( ( $iLog10 - int( $iLog10 / $iKeta ) ) < 0 ) ? -1 : 0 ) ) * $iKeta; my $sUe = ExcelFmt( $sKari, $iData * ( 10**( $iLog10 * -1 ) ), 0 ); my $sShita = ExcelFmt( $sSisu, $iLog10, 0 ); return $sUe . $sE . $sShita; } #------------------------------------------------------------------------------ # LeapYear (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ sub LeapYear { my ($iYear) = @_; return 1 if ( $iYear == 1900 ); #Special for Excel return ( ( ( $iYear % 4 ) == 0 ) && ( ( $iYear % 100 ) || ( $iYear % 400 ) == 0 ) ) ? 1 : 0; } #------------------------------------------------------------------------------ # LocaltimeExcel (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ sub LocaltimeExcel { my ( $iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iwDay, $iMSec, $flg1904 ) = @_; #0. Init $iMon++; $iYear += 1900; #1. Calc Time my $iTime; $iTime = $iHour; $iTime *= 60; $iTime += $iMin; $iTime *= 60; $iTime += $iSec; $iTime += $iMSec / 1000.0 if ( defined($iMSec) ); $iTime /= 86400.0; #3600*24(1day in seconds) my $iY; my $iYDays; #2. Calc Days if ($flg1904) { $iY = 1904; $iTime--; #Start from Jan 1st $iYDays = 366; } else { $iY = 1900; $iYDays = 366; #In Excel 1900 is leap year (That's not TRUE!) } while ( $iY < $iYear ) { $iTime += $iYDays; $iY++; $iYDays = ( LeapYear($iY) ) ? 366 : 365; } for ( my $iM = 1 ; $iM < $iMon ; $iM++ ) { if ( $iM == 1 || $iM == 3 || $iM == 5 || $iM == 7 || $iM == 8 || $iM == 10 || $iM == 12 ) { $iTime += 31; } elsif ( $iM == 4 || $iM == 6 || $iM == 9 || $iM == 11 ) { $iTime += 30; } elsif ( $iM == 2 ) { $iTime += ( LeapYear($iYear) ) ? 29 : 28; } } $iTime += $iDay; return $iTime; } #------------------------------------------------------------------------------ # ExcelLocaltime (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ sub ExcelLocaltime { my ( $dObj, $flg1904 ) = @_; my ( $iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iwDay, $iMSec ); my ( $iDt, $iTime, $iYDays ); $iDt = int($dObj); $iTime = $dObj - $iDt; #1. Calc Days if ($flg1904) { $iYear = 1904; $iDt++; #Start from Jan 1st $iYDays = 366; $iwDay = ( ( $iDt + 4 ) % 7 ); } else { $iYear = 1900; $iYDays = 366; #In Excel 1900 is leap year (That's not TRUE!) $iwDay = ( ( $iDt + 6 ) % 7 ); } while ( $iDt > $iYDays ) { $iDt -= $iYDays; $iYear++; $iYDays = ( ( ( $iYear % 4 ) == 0 ) && ( ( $iYear % 100 ) || ( $iYear % 400 ) == 0 ) ) ? 366 : 365; } $iYear -= 1900; # Localtime year is relative to 1900. for ( $iMon = 1 ; $iMon < 12 ; $iMon++ ) { my $iMD; if ( $iMon == 1 || $iMon == 3 || $iMon == 5 || $iMon == 7 || $iMon == 8 || $iMon == 10 || $iMon == 12 ) { $iMD = 31; } elsif ( $iMon == 4 || $iMon == 6 || $iMon == 9 || $iMon == 11 ) { $iMD = 30; } elsif ( $iMon == 2 ) { $iMD = ( ( $iYear % 4 ) == 0 ) ? 29 : 28; } last if ( $iDt <= $iMD ); $iDt -= $iMD; } $iMon -= 1; # Localtime month is 0 based. #2. Calc Time $iDay = $iDt; $iTime += ( 0.0005 / 86400.0 ); $iTime *= 24.0; $iHour = int($iTime); $iTime -= $iHour; $iTime *= 60.0; $iMin = int($iTime); $iTime -= $iMin; $iTime *= 60.0; $iSec = int($iTime); $iTime -= $iSec; $iTime *= 1000.0; $iMSec = int($iTime); return ( $iSec, $iMin, $iHour, $iDay, $iMon, $iYear, $iwDay, $iMSec ); } # ----------------------------------------------------------------------------- # col2int (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ # converts a excel row letter into an int for use in an array sub col2int { my $result = 0; my $str = shift; my $incr = 0; for ( my $i = length($str) ; $i > 0 ; $i-- ) { my $char = substr( $str, $i - 1 ); my $curr += ord( lc($char) ) - ord('a') + 1; $curr *= $incr if ($incr); $result += $curr; $incr += 26; } # this is one out as we range 0..x-1 not 1..x $result--; return $result; } # ----------------------------------------------------------------------------- # int2col (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ ### int2col # convert a column number into column letters # @note this is quite a brute force coarse method # does not manage values over 701 (ZZ) # @arg number, to convert # @returns string, column name # sub int2col { my $out = ""; my $val = shift; do { $out .= chr( ( $val % 26 ) + ord('A') ); $val = int( $val / 26 ) - 1; } while ( $val >= 0 ); return scalar reverse $out; } # ----------------------------------------------------------------------------- # sheetRef (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ # ----------------------------------------------------------------------------- ### sheetRef # convert an excel letter-number address into a useful array address # @note that also Excel uses X-Y notation, we normally use Y-X in arrays # @args $str, excel coord eg. A2 # @returns an array - 2 elements - column, row, or undefined # sub sheetRef { my $str = shift; my @ret; $str =~ m/^(\D+)(\d+)$/; if ( $1 && $2 ) { push( @ret, $2 - 1, col2int($1) ); } if ( $ret[0] < 0 ) { undef @ret; } return @ret; } # ----------------------------------------------------------------------------- # xls2csv (for Spreadsheet::ParseExcel::Utility) #------------------------------------------------------------------------------ ### xls2csv # convert a chunk of an excel file into csv text chunk # @args $param, sheet-colrow:colrow (1-A1:B2 or A1:B2 for sheet 1 # @args $rotate, 0 or 1 decides if output should be rotated or not # @returns string containing a chunk of csv # sub xls2csv { my ( $filename, $regions, $rotate ) = @_; my $sheet = 0; # We need Text::CSV_XS for proper CSV handling. require Text::CSV_XS; # extract any sheet number from the region string $regions =~ m/^(\d+)-(.*)/; if ($2) { $sheet = $1 - 1; $regions = $2; } # now extract the start and end regions $regions =~ m/(.*):(.*)/; if ( !$1 || !$2 ) { print STDERR "Bad Params"; return ""; } my @start = sheetRef($1); my @end = sheetRef($2); if ( !@start ) { print STDERR "Bad coorinates - $1"; return ""; } if ( !@end ) { print STDERR "Bad coorinates - $2"; return ""; } if ( $start[1] > $end[1] ) { print STDERR "Bad COLUMN ordering\n"; print STDERR "Start column " . int2col( $start[1] ); print STDERR " after end column " . int2col( $end[1] ) . "\n"; return ""; } if ( $start[0] > $end[0] ) { print STDERR "Bad ROW ordering\n"; print STDERR "Start row " . ( $start[0] + 1 ); print STDERR " after end row " . ( $end[0] + 1 ) . "\n"; exit; } # start the excel object now my $oExcel = new Spreadsheet::ParseExcel; my $oBook = $oExcel->Parse($filename); # open the sheet my $oWkS = $oBook->{Worksheet}[$sheet]; # now check that the region exists in the file # if not truncate to the possible region # output a warning msg if ( $start[1] < $oWkS->{MinCol} ) { print STDERR int2col( $start[1] ) . " < min col " . int2col( $oWkS->{MinCol} ) . " Resetting\n"; $start[1] = $oWkS->{MinCol}; } if ( $end[1] > $oWkS->{MaxCol} ) { print STDERR int2col( $end[1] ) . " > max col " . int2col( $oWkS->{MaxCol} ) . " Resetting\n"; $end[1] = $oWkS->{MaxCol}; } if ( $start[0] < $oWkS->{MinRow} ) { print STDERR "" . ( $start[0] + 1 ) . " < min row " . ( $oWkS->{MinRow} + 1 ) . " Resetting\n"; $start[0] = $oWkS->{MinCol}; } if ( $end[0] > $oWkS->{MaxRow} ) { print STDERR "" . ( $end[0] + 1 ) . " > max row " . ( $oWkS->{MaxRow} + 1 ) . " Resetting\n"; $end[0] = $oWkS->{MaxRow}; } my $x1 = $start[1]; my $y1 = $start[0]; my $x2 = $end[1]; my $y2 = $end[0]; my @cell_data; my $row = 0; if ( !$rotate ) { for ( my $y = $y1 ; $y <= $y2 ; $y++ ) { for ( my $x = $x1 ; $x <= $x2 ; $x++ ) { my $cell = $oWkS->{Cells}[$y][$x]; my $value; if ( defined $cell ) { $value .= $cell->value(); } else { $value = ''; } push @{ $cell_data[$row] }, $value; } $row++; } } else { for ( my $x = $x1 ; $x <= $x2 ; $x++ ) { for ( my $y = $y1 ; $y <= $y2 ; $y++ ) { my $cell = $oWkS->{Cells}[$y][$x]; my $value; if ( defined $cell ) { $value .= $cell->value(); } else { $value = ''; } push @{ $cell_data[$row] }, $value; } $row++; } } # Create the CSV output string. my $csv = Text::CSV_XS->new( { binary => 1, eol => $/ } ); my $output = ""; for my $row (@cell_data) { $csv->combine(@$row); $output .= $csv->string(); } return $output; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Utility - Utility functions for Spreadsheet::ParseExcel. =head1 SYNOPSIS use Spreadsheet::ParseExcel::Utility qw(ExcelFmt ExcelLocaltime LocaltimeExcel); # Convert localtime to Excel time my $datetime = LocaltimeExcel(11, 10, 12, 23, 2, 64); # 1964-3-23 12:10:11 print $datetime, "\n"; # 23459.5070717593 (Excel date/time format) # Convert Excel Time to localtime my @time = ExcelLocaltime($datetime); print join(":", @time), "\n"; # 11:10:12:23:2:64:1:0 # Formatting print ExcelFmt('yyyy-mm-dd', $datetime), "\n"; # 1964-3-23 print ExcelFmt('m-d-yy', $datetime), "\n"; # 3-23-64 print ExcelFmt('#,##0', $datetime), "\n"; # 23,460 print ExcelFmt('#,##0.00', $datetime), "\n"; # 23,459.51 =head1 DESCRIPTION The C module provides utility functions for working with ParseExcel and Excel data. =head1 Functions C can export the following functions: ExcelFmt ExcelLocaltime LocaltimeExcel col2int int2col sheetRef xls2csv These functions must be imported implicitly: # Just one function. use Spreadsheet::ParseExcel::Utility 'col2int'; # More than one. use Spreadsheet::ParseExcel::Utility qw(ExcelFmt ExcelLocaltime LocaltimeExcel); =head2 ExcelFmt($format_string, $number, $is_1904) Excel stores data such as dates and currency values as numbers. The way these numbers are displayed is controlled by the number format string for the cell. For example a cell with a number format of C<'$#,##0.00'> for currency and a value of 1234.567 would be displayed as follows: '$#,##0.00' + 1234.567 = '$1,234.57'. The C function tries to emulate this formatting so that the user can convert raw numbers returned by C to a desired format. For example: print ExcelFmt('$#,##0.00', 1234.567); # $1,234.57. The syntax of the function is: my $text = ExcelFmt($format_string, $number, $is_1904); Where C<$format_string> is an Excel number format string, C<$number> is a real or integer number and C is an optional flag to indicate that dates should use Excel's 1904 epoch instead of the default 1900 epoch. C is also used internally to convert numbers returned by the C method to the formatted value returned by the C method: my $cell = $worksheet->get_cell( 0, 0 ); print $cell->unformatted(), "\n"; # 1234.567 print $cell->value(), "\n"; # $1,234.57 The most common usage for C is to convert numbers to dates. Dates and times in Excel are represented by real numbers, for example "1 Jan 2001 12:30 PM" is represented by the number 36892.521. The integer part of the number stores the number of days since the epoch and the fractional part stores the percentage of the day. By applying an Excel number format the number is converted to the desired string representation: print ExcelFmt('d mmm yyyy h:mm AM/PM', 36892.521); # 1 Jan 2001 12:30 PM C<$is_1904> is an optional flag to indicate that dates should use Excel's 1904 epoch instead of the default 1900 epoch. Excel for Windows generally uses 1900 and Excel for Mac OS uses 1904. The C<$is1904> flag isn't required very often by a casual user and can usually be ignored. =head2 ExcelLocaltime($excel_datetime, $is_1904) The C function converts from an Excel date/time number to a C-like array of values: my @time = ExcelLocaltime($excel_datetime); # 0 1 2 3 4 5 6 7 my ( $sec, $min, $hour, $day, $month, $year, $wday, $msec ) = @time; The array elements from C<(0 .. 6)> are the same as Perl's C. The last element C<$msec> is milliseconds. In particular it should be noted that, in common with C, the month is zero indexed and the year is the number of years since 1900. This means that you will usually need to do the following: $month++; $year += 1900; See also Perl's documentation for L: The C<$is_1904> flag is an optional. It is used to indicate that dates should use Excel's 1904 epoch instead of the default 1900 epoch. =head2 LocaltimeExcel($sec, $min, $hour, $day, $month, $year, $wday, $msec, $is_1904) The C function converts from a C-like array of values to an Excel date/time number: $excel_datetime = LocaltimeExcel($sec, $min, $hour, $day, $month, $year, $wday, $msec); The array elements from C<(0 .. 6)> are the same as Perl's C. The last element C<$msec> is milliseconds. In particular it should be noted that, in common with C, the month is zero indexed and the year is the number of years since 1900. See also Perl's documentation for L: The C<$wday> and C<$msec> elements are usually optional. This time elements can also be zeroed if they aren't of interest: # sec, min, hour, day, month, year $excel_datetime = LocaltimeExcel( 0, 0, 0, 1, 0, 101 ); print ExcelFmt('d mmm yyyy', $excel_datetime); # 1 Jan 2001 The C<$is_1904> flag is also optional. It is used to indicate that dates should use Excel's 1904 epoch instead of the default 1900 epoch. =head2 col2int($column) The C function converts an Excel column letter to an zero-indexed column number: print col2int('A'); # 0 print col2int('AA'); # 26 This function was contributed by Kevin Mulholland. =head2 int2col($column_number) The C function converts an zero-indexed Excel column number to a column letter: print int2col(0); # 'A' print int2col(26); # 'AA' This function was contributed by Kevin Mulholland. =head2 sheetRef($cell_string) The C function converts an Excel cell reference in 'A1' notation to a zero-indexed C<(row, col)> pair. my ($row, $col) = sheetRef('A1'); # ( 0, 0 ) my ($row, $col) = sheetRef('C2'); # ( 1, 2 ) This function was contributed by Kevin Mulholland. =head2 xls2csv($filename, $region, $rotate) The C function converts a section of an Excel file into a CSV text string. $csv_text = xls2csv($filename, $region, $rotate); Where: $region = "sheet-colrow:colrow" For example '1-A1:B2' means 'A1:B2' for sheet 1. and $rotate = 0 or 1 (output is rotated/transposed or not) This function requires C to be installed. It was contributed by Kevin Mulholland along with the C script in the C directory of the distro. See also the following xls2csv utilities: Ken Prows' C: http://search.cpan.org/~ken/xls2csv/script/xls2csv and H.Merijn Brand's C (which is part of Spreadsheet::Read): http://search.cpan.org/~hmbrand/Spreadsheet-Read/ =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/SaveParser.pm0000644000176000001440000001705611326376247022240 0ustar ripleyuserspackage Spreadsheet::ParseExcel::SaveParser; ############################################################################### # # Spreadsheet::ParseExcel::SaveParser - Rewrite an existing Excel file. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use Spreadsheet::ParseExcel; use Spreadsheet::ParseExcel::SaveParser::Workbook; use Spreadsheet::ParseExcel::SaveParser::Worksheet; use Spreadsheet::WriteExcel; use base 'Spreadsheet::ParseExcel'; our $VERSION = '0.56'; ############################################################################### # # new() # sub new { my ( $package, %params ) = @_; $package->SUPER::new(%params); } ############################################################################### # # Create() # sub Create { my ( $self, $formatter ) = @_; #0. New $workbook my $workbook = Spreadsheet::ParseExcel::Workbook->new(); $workbook->{SheetCount} = 0; # User specified formater class. if ($formatter) { $workbook->{FmtClass} = $formatter; } else { $workbook->{FmtClass} = Spreadsheet::ParseExcel::FmtDefault->new(); } return Spreadsheet::ParseExcel::SaveParser::Workbook->new($workbook); } ############################################################################### # # Parse() # sub Parse { my ( $self, $sFile, $formatter ) = @_; my $workbook = $self->SUPER::Parse( $sFile, $formatter ); return undef unless defined $workbook; return Spreadsheet::ParseExcel::SaveParser::Workbook->new($workbook); } ############################################################################### # # SaveAs() # sub SaveAs { my ( $self, $workbook, $filename ) = @_; $workbook->SaveAs($filename); } 1; __END__ =head1 NAME Spreadsheet::ParseExcel::SaveParser - Rewrite an existing Excel file. =head1 SYNOPSIS Say we start with an Excel file that looks like this: ----------------------------------------------------- | | A | B | C | ----------------------------------------------------- | 1 | Hello | ... | ... | ... | 2 | World | ... | ... | ... | 3 | *Bold text* | ... | ... | ... | 4 | ... | ... | ... | ... | 5 | ... | ... | ... | ... Then we process it with the following program: #!/usr/bin/perl use strict; use warnings; use Spreadsheet::ParseExcel; use Spreadsheet::ParseExcel::SaveParser; # Open an existing file with SaveParser my $parser = Spreadsheet::ParseExcel::SaveParser->new(); my $template = $parser->Parse('template.xls'); # Get the first worksheet. my $worksheet = $template->worksheet(0); my $row = 0; my $col = 0; # Overwrite the string in cell A1 $worksheet->AddCell( $row, $col, 'New string' ); # Add a new string in cell B1 $worksheet->AddCell( $row, $col + 1, 'Newer' ); # Add a new string in cell C1 with the format from cell A3. my $cell = $worksheet->get_cell( $row + 2, $col ); my $format_number = $cell->{FormatNo}; $worksheet->AddCell( $row, $col + 2, 'Newest', $format_number ); # Write over the existing file or write a new file. $template->SaveAs('newfile.xls'); We should now have an Excel file that looks like this: ----------------------------------------------------- | | A | B | C | ----------------------------------------------------- | 1 | New string | Newer | *Newest* | ... | 2 | World | ... | ... | ... | 3 | *Bold text* | ... | ... | ... | 4 | ... | ... | ... | ... | 5 | ... | ... | ... | ... =head1 DESCRIPTION The C module rewrite an existing Excel file by reading it with C and rewriting it with C. =head1 METHODS =head1 Parser =head2 new() $parse = new Spreadsheet::ParseExcel::SaveParser(); Constructor. =head2 Parse() $workbook = $parse->Parse($sFileName); $workbook = $parse->Parse($sFileName , $formatter); Returns a L object. If an error occurs, returns undef. The optional C<$formatter> is a Formatter Class to format the value of cells. =head1 Workbook The C method returns a C object. This is a subclass of the L and has the following methods: =head2 worksheets() Returns an array of L objects. This was most commonly used to iterate over the worksheets in a workbook: for my $worksheet ( $workbook->worksheets() ) { ... } =head2 worksheet() The C method returns a single C object using either its name or index: $worksheet = $workbook->worksheet('Sheet1'); $worksheet = $workbook->worksheet(0); Returns C if the sheet name or index doesn't exist. =head2 AddWorksheet() $workbook = $workbook->AddWorksheet($name, %properties); Create a new Worksheet object of type C. The C<%properties> hash contains the properties of new Worksheet. =head2 AddFont $workbook = $workbook->AddFont(%properties); Create new Font object of type C. The C<%properties> hash contains the properties of new Font. =head2 AddFormat $workbook = $workbook->AddFormat(%properties); The C<%properties> hash contains the properties of new Font. =head1 Worksheet Spreadsheet::ParseExcel::SaveParser::Worksheet Worksheet is a subclass of Spreadsheet::ParseExcel::Worksheet. And has these methods : The C method returns a C object. This is a subclass of the L and has the following methods: =head1 AddCell $workbook = $worksheet->AddCell($row, $col, $value, $format [$encoding]); Create new Cell object of type C. The C<$format> parameter is the format number rather than a full format object. To specify just same as another cell, you can set it like below: $row = 0; $col = 0; $worksheet = $template->worksheet(0); $cell = $worksheet->get_cell( $row, $col ); $format_number = $cell->{FormatNo}; $worksheet->AddCell($row +1, $coll, 'New data', $format_number); =head1 TODO Please note that this module is currently (versions 0.50-0.60) undergoing a major restructuring and rewriting. =head1 Known Problems You can only rewrite the features that Spreadsheet::WriteExcel supports so macros, graphs and some other features in the original Excel file will be lost. Also, formulas aren't rewritten, only the result of a formula is written. Only last print area will remain. (Others will be removed) =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2002 Kawai Takanori and Nippon-RAD Co. OP Division All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/SaveParser/0000755000176000001440000000000012164457166021672 5ustar ripleyusersgdata/inst/perl/Spreadsheet/ParseExcel/SaveParser/Worksheet.pm0000644000176000001440000000472111326376247024206 0ustar ripleyuserspackage Spreadsheet::ParseExcel::SaveParser::Worksheet; ############################################################################### # # Spreadsheet::ParseExcel::SaveParser::Worksheet - A class for SaveParser Worksheets. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; #============================================================================== # Spreadsheet::ParseExcel::SaveParser::Worksheet #============================================================================== use base 'Spreadsheet::ParseExcel::Worksheet'; our $VERSION = '0.56'; sub new { my ( $sClass, %rhIni ) = @_; $sClass->SUPER::new(%rhIni); # returns object } #------------------------------------------------------------------------------ # AddCell (for Spreadsheet::ParseExcel::SaveParser::Worksheet) #------------------------------------------------------------------------------ sub AddCell { my ( $oSelf, $iR, $iC, $sVal, $oCell, $sCode ) = @_; $oSelf->{_Book} ->AddCell( $oSelf->{_SheetNo}, $iR, $iC, $sVal, $oCell, $sCode ); } #------------------------------------------------------------------------------ # Protect (for Spreadsheet::ParseExcel::SaveParser::Worksheet) # - Password = undef -> No protect # - Password = '' -> Protected. No password # - Password = $pwd -> Protected. Password = $pwd #------------------------------------------------------------------------------ sub Protect { my ( $oSelf, $sPassword ) = @_; $oSelf->{Protect} = $sPassword; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::SaveParser::Worksheet - A class for SaveParser Worksheets. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/SaveParser/Workbook.pm0000644000176000001440000003457011326376247024035 0ustar ripleyuserspackage Spreadsheet::ParseExcel::SaveParser::Workbook; ############################################################################### # # Spreadsheet::ParseExcel::SaveParser::Workbook - A class for SaveParser Workbooks. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use base 'Spreadsheet::ParseExcel::Workbook'; our $VERSION = '0.56'; #============================================================================== # Spreadsheet::ParseExcel::SaveParser::Workbook #============================================================================== sub new { my ( $sPkg, $oBook ) = @_; return undef unless ( defined $oBook ); my %oThis = %$oBook; bless \%oThis, $sPkg; # re-bless worksheets (and set their _Book properties !!!) my $sWkP = ref($sPkg) || "$sPkg"; $sWkP =~ s/Workbook$/Worksheet/; map { bless( $_, $sWkP ); } @{ $oThis{Worksheet} }; map { $_->{_Book} = \%oThis; } @{ $oThis{Worksheet} }; return \%oThis; } #------------------------------------------------------------------------------ # Parse (for Spreadsheet::ParseExcel::SaveParser::Workbook) #------------------------------------------------------------------------------ sub Parse { my ( $sClass, $sFile, $oWkFmt ) = @_; my $oBook = Spreadsheet::ParseExcel::Workbook->Parse( $sFile, $oWkFmt ); bless $oBook, $sClass; # re-bless worksheets (and set their _Book properties !!!) my $sWkP = ref($sClass) || "$sClass"; $sWkP =~ s/Workbook$/Worksheet/; map { bless( $_, $sWkP ); } @{ $oBook->{Worksheet} }; map { $_->{_Book} = $oBook; } @{ $oBook->{Worksheet} }; return $oBook; } #------------------------------------------------------------------------------ # SaveAs (for Spreadsheet::ParseExcel::SaveParser::Workbook) #------------------------------------------------------------------------------ sub SaveAs { my ( $oBook, $sName ) = @_; # Create a new Excel workbook my $oWrEx = Spreadsheet::WriteExcel->new($sName); $oWrEx->compatibility_mode(); my %hFmt; my $iNo = 0; my @aAlH = ( 'left', 'left', 'center', 'right', 'fill', 'justify', 'merge', 'equal_space' ); my @aAlV = ( 'top', 'vcenter', 'bottom', 'vjustify', 'vequal_space' ); foreach my $pFmt ( @{ $oBook->{Format} } ) { my $oFmt = $oWrEx->addformat(); # Add Formats unless ( $pFmt->{Style} ) { $hFmt{$iNo} = $oFmt; my $rFont = $pFmt->{Font}; $oFmt->set_font( $rFont->{Name} ); $oFmt->set_size( $rFont->{Height} ); $oFmt->set_color( $rFont->{Color} ); $oFmt->set_bold( $rFont->{Bold} ); $oFmt->set_italic( $rFont->{Italic} ); $oFmt->set_underline( $rFont->{Underline} ); $oFmt->set_font_strikeout( $rFont->{Strikeout} ); $oFmt->set_font_script( $rFont->{Super} ); $oFmt->set_hidden( $rFont->{Hidden} ); #Add $oFmt->set_locked( $pFmt->{Lock} ); $oFmt->set_align( $aAlH[ $pFmt->{AlignH} ] ); $oFmt->set_align( $aAlV[ $pFmt->{AlignV} ] ); $oFmt->set_rotation( $pFmt->{Rotate} ); $oFmt->set_num_format( $oBook->{FmtClass}->FmtStringDef( $pFmt->{FmtIdx}, $oBook ) ); $oFmt->set_text_wrap( $pFmt->{Wrap} ); $oFmt->set_pattern( $pFmt->{Fill}->[0] ); $oFmt->set_fg_color( $pFmt->{Fill}->[1] ) if ( ( $pFmt->{Fill}->[1] >= 8 ) && ( $pFmt->{Fill}->[1] <= 63 ) ); $oFmt->set_bg_color( $pFmt->{Fill}->[2] ) if ( ( $pFmt->{Fill}->[2] >= 8 ) && ( $pFmt->{Fill}->[2] <= 63 ) ); $oFmt->set_left( ( $pFmt->{BdrStyle}->[0] > 7 ) ? 3 : $pFmt->{BdrStyle}->[0] ); $oFmt->set_right( ( $pFmt->{BdrStyle}->[1] > 7 ) ? 3 : $pFmt->{BdrStyle}->[1] ); $oFmt->set_top( ( $pFmt->{BdrStyle}->[2] > 7 ) ? 3 : $pFmt->{BdrStyle}->[2] ); $oFmt->set_bottom( ( $pFmt->{BdrStyle}->[3] > 7 ) ? 3 : $pFmt->{BdrStyle}->[3] ); $oFmt->set_left_color( $pFmt->{BdrColor}->[0] ) if ( ( $pFmt->{BdrColor}->[0] >= 8 ) && ( $pFmt->{BdrColor}->[0] <= 63 ) ); $oFmt->set_right_color( $pFmt->{BdrColor}->[1] ) if ( ( $pFmt->{BdrColor}->[1] >= 8 ) && ( $pFmt->{BdrColor}->[1] <= 63 ) ); $oFmt->set_top_color( $pFmt->{BdrColor}->[2] ) if ( ( $pFmt->{BdrColor}->[2] >= 8 ) && ( $pFmt->{BdrColor}->[2] <= 63 ) ); $oFmt->set_bottom_color( $pFmt->{BdrColor}->[3] ) if ( ( $pFmt->{BdrColor}->[3] >= 8 ) && ( $pFmt->{BdrColor}->[3] <= 63 ) ); } $iNo++; } for ( my $iSheet = 0 ; $iSheet < $oBook->{SheetCount} ; $iSheet++ ) { my $oWkS = $oBook->{Worksheet}[$iSheet]; my $oWrS = $oWrEx->addworksheet( $oWkS->{Name} ); #Landscape if ( !$oWkS->{Landscape} ) { # Landscape (0:Horizontal, 1:Vertical) $oWrS->set_landscape(); } else { $oWrS->set_portrait(); } #Protect if ( defined $oWkS->{Protect} ) { # Protect ('':NoPassword, Password:Password) if ( $oWkS->{Protect} ne '' ) { $oWrS->protect( $oWkS->{Protect} ); } else { $oWrS->protect(); } } if ( ( $oWkS->{FitWidth} == 1 ) and ( $oWkS->{FitHeight} == 1 ) ) { # Pages on fit with width and Heigt $oWrS->fit_to_pages( $oWkS->{FitWidth}, $oWkS->{FitHeight} ); #Print Scale $oWrS->set_print_scale( $oWkS->{Scale} ); } else { #Print Scale $oWrS->set_print_scale( $oWkS->{Scale} ); # Pages on fit with width and Heigt $oWrS->fit_to_pages( $oWkS->{FitWidth}, $oWkS->{FitHeight} ); } # Paper Size $oWrS->set_paper( $oWkS->{PaperSize} ); # Margin $oWrS->set_margin_left( $oWkS->{LeftMargin} ); $oWrS->set_margin_right( $oWkS->{RightMargin} ); $oWrS->set_margin_top( $oWkS->{TopMargin} ); $oWrS->set_margin_bottom( $oWkS->{BottomMargin} ); # HCenter $oWrS->center_horizontally() if ( $oWkS->{HCenter} ); # VCenter $oWrS->center_vertically() if ( $oWkS->{VCenter} ); # Header, Footer $oWrS->set_header( $oWkS->{Header}, $oWkS->{HeaderMargin} ); $oWrS->set_footer( $oWkS->{Footer}, $oWkS->{FooterMargin} ); # Print Area if ( ref( $oBook->{PrintArea}[$iSheet] ) eq 'ARRAY' ) { my $raP; for $raP ( @{ $oBook->{PrintArea}[$iSheet] } ) { $oWrS->print_area(@$raP); } } # Print Title my $raW; foreach $raW ( @{ $oBook->{PrintTitle}[$iSheet]->{Row} } ) { $oWrS->repeat_rows(@$raW); } foreach $raW ( @{ $oBook->{PrintTitle}[$iSheet]->{Column} } ) { $oWrS->repeat_columns(@$raW); } # Print Gridlines if ( $oWkS->{PrintGrid} == 1 ) { $oWrS->hide_gridlines(0); } else { $oWrS->hide_gridlines(1); } # Print Headings if ( $oWkS->{PrintHeaders} ) { $oWrS->print_row_col_headers(); } # Horizontal Page Breaks $oWrS->set_h_pagebreaks( @{ $oWkS->{HPageBreak} } ); # Veritical Page Breaks $oWrS->set_v_pagebreaks( @{ $oWkS->{VPageBreak} } ); # PageStart => $oWkS->{PageStart}, # Page number for start # UsePage => $oWkS->{UsePage}, # Use own start page number # NoColor => $oWkS->{NoColor}, # Print in blcak-white # Draft => $oWkS->{Draft}, # Print in draft mode # Notes => $oWkS->{Notes}, # Print notes # LeftToRight => $oWkS->{LeftToRight}, # Left to Right for ( my $iC = $oWkS->{MinCol} ; defined $oWkS->{MaxCol} && $iC <= $oWkS->{MaxCol} ; $iC++ ) { if ( defined $oWkS->{ColWidth}[$iC] ) { if ( $oWkS->{ColWidth}[$iC] > 0 ) { $oWrS->set_column( $iC, $iC, $oWkS->{ColWidth}[$iC] ) ; #, undef, 1) ; } else { $oWrS->set_column( $iC, $iC, 0, undef, 1 ); } } } for ( my $iR = $oWkS->{MinRow} ; defined $oWkS->{MaxRow} && $iR <= $oWkS->{MaxRow} ; $iR++ ) { $oWrS->set_row( $iR, $oWkS->{RowHeight}[$iR] ); for ( my $iC = $oWkS->{MinCol} ; defined $oWkS->{MaxCol} && $iC <= $oWkS->{MaxCol} ; $iC++ ) { my $oWkC = $oWkS->{Cells}[$iR][$iC]; if ($oWkC) { if ( $oWkC->{Merged} ) { my $oFmtN = $oWrEx->addformat(); $oFmtN->copy( $hFmt{ $oWkC->{FormatNo} } ); $oFmtN->set_merge(1); $oWrS->write( $iR, $iC, $oBook->{FmtClass} ->TextFmt( $oWkC->{Val}, $oWkC->{Code} ), $oFmtN ); } else { $oWrS->write( $iR, $iC, $oBook->{FmtClass} ->TextFmt( $oWkC->{Val}, $oWkC->{Code} ), $hFmt{ $oWkC->{FormatNo} } ); } } } } } return $oWrEx; } #------------------------------------------------------------------------------ # AddWorksheet (for Spreadsheet::ParseExcel::SaveParser::Workbook) #------------------------------------------------------------------------------ sub AddWorksheet { my ( $oBook, $sName, %hAttr ) = @_; $oBook->AddFormat if ( $#{ $oBook->{Format} } < 0 ); $hAttr{Name} ||= $sName; $hAttr{LeftMargin} ||= 0; $hAttr{RightMargin} ||= 0; $hAttr{TopMargin} ||= 0; $hAttr{BottomMargin} ||= 0; $hAttr{HeaderMargin} ||= 0; $hAttr{FooterMargin} ||= 0; $hAttr{FitWidth} ||= 0; $hAttr{FitHeight} ||= 0; $hAttr{PrintGrid} ||= 0; my $oWkS = Spreadsheet::ParseExcel::SaveParser::Worksheet->new(%hAttr); $oWkS->{_Book} = $oBook; $oWkS->{_SheetNo} = $oBook->{SheetCount}; $oBook->{Worksheet}[ $oBook->{SheetCount} ] = $oWkS; $oBook->{SheetCount}++; return $oWkS; #$oBook->{SheetCount} - 1; } #------------------------------------------------------------------------------ # AddFont (for Spreadsheet::ParseExcel::SaveParser::Workbook) #------------------------------------------------------------------------------ sub AddFont { my ( $oBook, %hAttr ) = @_; $hAttr{Name} ||= 'Arial'; $hAttr{Height} ||= 10; $hAttr{Bold} ||= 0; $hAttr{Italic} ||= 0; $hAttr{Underline} ||= 0; $hAttr{Strikeout} ||= 0; $hAttr{Super} ||= 0; push @{ $oBook->{Font} }, Spreadsheet::ParseExcel::Font->new(%hAttr); return $#{ $oBook->{Font} }; } #------------------------------------------------------------------------------ # AddFormat (for Spreadsheet::ParseExcel::SaveParser::Workbook) #------------------------------------------------------------------------------ sub AddFormat { my ( $oBook, %hAttr ) = @_; $hAttr{Fill} ||= [ 0, 0, 0 ]; $hAttr{BdrStyle} ||= [ 0, 0, 0, 0 ]; $hAttr{BdrColor} ||= [ 0, 0, 0, 0 ]; $hAttr{AlignH} ||= 0; $hAttr{AlignV} ||= 0; $hAttr{Rotate} ||= 0; $hAttr{Landscape} ||= 0; $hAttr{FmtIdx} ||= 0; if ( !defined( $hAttr{Font} ) ) { my $oFont; if ( defined $hAttr{FontNo} ) { $oFont = $oBook->{Font}[ $hAttr{FontNo} ]; } elsif ( !defined $oFont ) { if ( $#{ $oBook->{Font} } >= 0 ) { $oFont = $oBook->{Font}[0]; } else { my $iNo = $oBook->AddFont; $oFont = $oBook->{Font}[$iNo]; } } $hAttr{Font} = $oFont; } push @{ $oBook->{Format} }, Spreadsheet::ParseExcel::Format->new(%hAttr); return $#{ $oBook->{Format} }; } #------------------------------------------------------------------------------ # AddCell (for Spreadsheet::ParseExcel::SaveParser::Workbook) #------------------------------------------------------------------------------ sub AddCell { my ( $oBook, $iSheet, $iR, $iC, $sVal, $oCell, $sCode ) = @_; my %rhKey; $oCell ||= 0; my $iFmt = ( UNIVERSAL::isa( $oCell, 'Spreadsheet::ParseExcel::Cell' ) ) ? $oCell->{FormatNo} : ( ref($oCell) ) ? 0 : $oCell + 0; $rhKey{FormatNo} = $iFmt; $rhKey{Format} = $oBook->{Format}[$iFmt]; $rhKey{Val} = $sVal; $rhKey{Code} = $sCode || '_native_'; $oBook->{_CurSheet} = $iSheet; my $oNewCell = Spreadsheet::ParseExcel::_NewCell( $oBook, $iR, $iC, %rhKey ); Spreadsheet::ParseExcel::_SetDimension( $oBook, $iR, $iC, $iC ); return $oNewCell; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::SaveParser::Workbook - A class for SaveParser Workbooks. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/Format.pm0000644000176000001440000000247711326376247021416 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Format; ############################################################################### # # Spreadsheet::ParseExcel::Format - A class for Cell formats. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; our $VERSION = '0.56'; sub new { my ( $class, %rhIni ) = @_; my $self = \%rhIni; bless $self, $class; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Format - A class for Cell formats. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/Font.pm0000644000176000001440000000246611326376247021072 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Font; ############################################################################### # # Spreadsheet::ParseExcel::Font - A class for Cell fonts. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; our $VERSION = '0.56'; sub new { my ( $class, %rhIni ) = @_; my $self = \%rhIni; bless $self, $class; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Font - A class for Cell fonts. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm0000644000176000001440000000507011326376247022213 0ustar ripleyuserspackage Spreadsheet::ParseExcel::FmtUnicode; ############################################################################### # # Spreadsheet::ParseExcel::FmtUnicode - A class for Cell formats. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use Unicode::Map; use base 'Spreadsheet::ParseExcel::FmtDefault'; our $VERSION = '0.56'; #------------------------------------------------------------------------------ # new (for Spreadsheet::ParseExcel::FmtUnicode) #------------------------------------------------------------------------------ sub new { my ( $sPkg, %hKey ) = @_; my $sMap = $hKey{Unicode_Map}; my $oMap; $oMap = Unicode::Map->new($sMap) if $sMap; my $oThis = { Unicode_Map => $sMap, _UniMap => $oMap, }; bless $oThis; return $oThis; } #------------------------------------------------------------------------------ # TextFmt (for Spreadsheet::ParseExcel::FmtUnicode) #------------------------------------------------------------------------------ sub TextFmt { my ( $oThis, $sTxt, $sCode ) = @_; if ( $oThis->{_UniMap} ) { if ( !defined($sCode) ) { my $sSv = $sTxt; $sTxt =~ s/(.)/\x00$1/sg; $sTxt = $oThis->{_UniMap}->from_unicode($sTxt); $sTxt = $sSv unless ($sTxt); } elsif ( $sCode eq 'ucs2' ) { $sTxt = $oThis->{_UniMap}->from_unicode($sTxt); } # $sTxt = $oThis->{_UniMap}->from_unicode($sTxt) # if(defined($sCode) && $sCode eq 'ucs2'); return $sTxt; } else { return $sTxt; } } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::FmtUnicode - A class for Cell formats. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm0000644000176000001440000000505311326376247021741 0ustar ripleyuserspackage Spreadsheet::ParseExcel::FmtJapan2; ############################################################################### # # Spreadsheet::ParseExcel::FmtJapan2 - A class for Cell formats. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use Jcode; use Unicode::Map; use base 'Spreadsheet::ParseExcel::FmtJapan'; our $VERSION = '0.56'; #------------------------------------------------------------------------------ # new (for Spreadsheet::ParseExcel::FmtJapan2) #------------------------------------------------------------------------------ sub new { my ( $sPkg, %hKey ) = @_; my $oMap = Unicode::Map->new('CP932Excel'); die "NO MAP FILE CP932Excel!!" unless ( -r Unicode::Map->mapping("CP932Excel") ); my $oThis = { Code => $hKey{Code}, _UniMap => $oMap, }; bless $oThis; $oThis->SUPER::new(%hKey); return $oThis; } #------------------------------------------------------------------------------ # TextFmt (for Spreadsheet::ParseExcel::FmtJapan2) #------------------------------------------------------------------------------ sub TextFmt { my ( $oThis, $sTxt, $sCode ) = @_; # $sCode = 'sjis' if((! defined($sCode)) || ($sCode eq '_native_')); if ( $oThis->{Code} ) { if ( !defined($sCode) ) { $sTxt =~ s/(.)/\x00$1/sg; $sTxt = $oThis->{_UniMap}->from_unicode($sTxt); } elsif ( $sCode eq 'ucs2' ) { $sTxt = $oThis->{_UniMap}->from_unicode($sTxt); } return Jcode::convert( $sTxt, $oThis->{Code}, 'sjis' ); } else { return $sTxt; } } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::FmtJapan2 - A class for Cell formats. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm0000644000176000001440000001261411326376247021660 0ustar ripleyuserspackage Spreadsheet::ParseExcel::FmtJapan; use utf8; ############################################################################### # # Spreadsheet::ParseExcel::FmtJapan - A class for Cell formats. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use Encode qw(find_encoding decode); use base 'Spreadsheet::ParseExcel::FmtDefault'; our $VERSION = '0.56'; my %FormatTable = ( 0x00 => '@', 0x01 => '0', 0x02 => '0.00', 0x03 => '#,##0', 0x04 => '#,##0.00', 0x05 => '(\\#,##0_);(\\#,##0)', 0x06 => '(\\#,##0_);[RED](\\#,##0)', 0x07 => '(\\#,##0.00_);(\\#,##0.00_)', 0x08 => '(\\#,##0.00_);[RED](\\#,##0.00_)', 0x09 => '0%', 0x0A => '0.00%', 0x0B => '0.00E+00', 0x0C => '# ?/?', 0x0D => '# ??/??', # 0x0E => 'm/d/yy', 0x0E => 'yyyy/m/d', 0x0F => 'd-mmm-yy', 0x10 => 'd-mmm', 0x11 => 'mmm-yy', 0x12 => 'h:mm AM/PM', 0x13 => 'h:mm:ss AM/PM', 0x14 => 'h:mm', 0x15 => 'h:mm:ss', # 0x16 => 'm/d/yy h:mm', 0x16 => 'yyyy/m/d h:mm', #0x17-0x24 -- Differs in Natinal 0x1E => 'm/d/yy', 0x1F => 'yyyy"å¹´"m"月"d"æ—¥"', 0x20 => 'h"時"mm"分"', 0x21 => 'h"時"mm"分"ss"ç§’"', #0x17-0x24 -- Differs in Natinal 0x25 => '(#,##0_);(#,##0)', 0x26 => '(#,##0_);[RED](#,##0)', 0x27 => '(#,##0.00);(#,##0.00)', 0x28 => '(#,##0.00);[RED](#,##0.00)', 0x29 => '_(*#,##0_);_(*(#,##0);_(*"-"_);_(@_)', 0x2A => '_(\\*#,##0_);_(\\*(#,##0);_(*"-"_);_(@_)', 0x2B => '_(*#,##0.00_);_(*(#,##0.00);_(*"-"??_);_(@_)', 0x2C => '_(\\*#,##0.00_);_(\\*(#,##0.00);_(*"-"??_);_(@_)', 0x2D => 'mm:ss', 0x2E => '[h]:mm:ss', 0x2F => 'mm:ss.0', 0x30 => '##0.0E+0', 0x31 => '@', 0x37 => 'yyyy"å¹´"m"月"', 0x38 => 'm"月"d"æ—¥"', 0x39 => 'ge.m.d', 0x3A => 'ggge"å¹´"m"月"d"æ—¥"', ); #------------------------------------------------------------------------------ # new (for Spreadsheet::ParseExcel::FmtJapan) #------------------------------------------------------------------------------ sub new { my ( $class, %args ) = @_; my $encoding = $args{Code} || $args{encoding}; my $self = { Code => $encoding }; if($encoding){ $self->{encoding} = find_encoding($encoding eq 'sjis' ? 'cp932' : $encoding) or do{ require Carp; Carp::croak(qq{Unknown encoding '$encoding'}); }; } return bless $self, $class; } #------------------------------------------------------------------------------ # TextFmt (for Spreadsheet::ParseExcel::FmtJapan) #------------------------------------------------------------------------------ sub TextFmt { my ( $self, $text, $input_encoding ) = @_; if(!defined $input_encoding){ $input_encoding = 'utf8'; } elsif($input_encoding eq '_native_'){ $input_encoding = 'cp932'; # Shift_JIS in Microsoft products } $text = decode($input_encoding, $text); return $self->{Code} ? $self->{encoding}->encode($text) : $text; } #------------------------------------------------------------------------------ # FmtStringDef (for Spreadsheet::ParseExcel::FmtJapan) #------------------------------------------------------------------------------ sub FmtStringDef { my ( $self, $format_index, $book ) = @_; return $self->SUPER::FmtStringDef( $format_index, $book, \%FormatTable ); } #------------------------------------------------------------------------------ # CnvNengo (for Spreadsheet::ParseExcel::FmtJapan) #------------------------------------------------------------------------------ # Convert A.D. into Japanese Nengo (aka Gengo) my @Nengo = ( { name => 'å¹³æˆ', # Heisei abbr_name => 'H', base => 1988, start => 19890108, }, { name => '昭和', # Showa abbr_name => 'S', base => 1925, start => 19261225, }, { name => '大正', # Taisho abbr_name => 'T', base => 1911, start => 19120730, }, { name => '明治', # Meiji abbr_name => 'M', base => 1867, start => 18680908, }, ); # Usage: CnvNengo(name => @tm) or CnvNeng(abbr_name => @tm) sub CnvNengo { my ( $kind, @tm ) = @_; my $year = $tm[5] + 1900; my $wk = ($year * 10000) + ($tm[4] * 100) + ($tm[3] * 1); #my $wk = sprintf( '%04d%02d%02d', $year, $tm[4], $tm[3] ); foreach my $nengo(@Nengo){ if( $wk >= $nengo->{start} ){ return $nengo->{$kind} . ($year - $nengo->{base}); } } return $year; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::FmtJapan - A class for Cell formats. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm0000644000176000001440000001351111326376247022210 0ustar ripleyuserspackage Spreadsheet::ParseExcel::FmtDefault; ############################################################################### # # Spreadsheet::ParseExcel::FmtDefault - A class for Cell formats. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; use Spreadsheet::ParseExcel::Utility qw(ExcelFmt); our $VERSION = '0.56'; my %hFmtDefault = ( 0x00 => '@', 0x01 => '0', 0x02 => '0.00', 0x03 => '#,##0', 0x04 => '#,##0.00', 0x05 => '($#,##0_);($#,##0)', 0x06 => '($#,##0_);[RED]($#,##0)', 0x07 => '($#,##0.00_);($#,##0.00_)', 0x08 => '($#,##0.00_);[RED]($#,##0.00_)', 0x09 => '0%', 0x0A => '0.00%', 0x0B => '0.00E+00', 0x0C => '# ?/?', 0x0D => '# ??/??', 0x0E => 'yyyy-mm-dd', # Was 'm-d-yy', which is bad as system default 0x0F => 'd-mmm-yy', 0x10 => 'd-mmm', 0x11 => 'mmm-yy', 0x12 => 'h:mm AM/PM', 0x13 => 'h:mm:ss AM/PM', 0x14 => 'h:mm', 0x15 => 'h:mm:ss', 0x16 => 'm-d-yy h:mm', #0x17-0x24 -- Differs in Natinal 0x25 => '(#,##0_);(#,##0)', 0x26 => '(#,##0_);[RED](#,##0)', 0x27 => '(#,##0.00);(#,##0.00)', 0x28 => '(#,##0.00);[RED](#,##0.00)', 0x29 => '_(*#,##0_);_(*(#,##0);_(*"-"_);_(@_)', 0x2A => '_($*#,##0_);_($*(#,##0);_(*"-"_);_(@_)', 0x2B => '_(*#,##0.00_);_(*(#,##0.00);_(*"-"??_);_(@_)', 0x2C => '_($*#,##0.00_);_($*(#,##0.00);_(*"-"??_);_(@_)', 0x2D => 'mm:ss', 0x2E => '[h]:mm:ss', 0x2F => 'mm:ss.0', 0x30 => '##0.0E+0', 0x31 => '@', ); #------------------------------------------------------------------------------ # new (for Spreadsheet::ParseExcel::FmtDefault) #------------------------------------------------------------------------------ sub new { my ( $sPkg, %hKey ) = @_; my $oThis = {}; bless $oThis; return $oThis; } #------------------------------------------------------------------------------ # TextFmt (for Spreadsheet::ParseExcel::FmtDefault) #------------------------------------------------------------------------------ sub TextFmt { my ( $oThis, $sTxt, $sCode ) = @_; return $sTxt if ( ( !defined($sCode) ) || ( $sCode eq '_native_' ) ); return pack( 'U*', unpack( 'n*', $sTxt ) ); } #------------------------------------------------------------------------------ # FmtStringDef (for Spreadsheet::ParseExcel::FmtDefault) #------------------------------------------------------------------------------ sub FmtStringDef { my ( $oThis, $iFmtIdx, $oBook, $rhFmt ) = @_; my $sFmtStr = $oBook->{FormatStr}->{$iFmtIdx}; if ( !( defined($sFmtStr) ) && defined($rhFmt) ) { $sFmtStr = $rhFmt->{$iFmtIdx}; } $sFmtStr = $hFmtDefault{$iFmtIdx} unless ($sFmtStr); return $sFmtStr; } #------------------------------------------------------------------------------ # FmtString (for Spreadsheet::ParseExcel::FmtDefault) #------------------------------------------------------------------------------ sub FmtString { my ( $oThis, $oCell, $oBook ) = @_; my $sFmtStr = $oThis->FmtStringDef( $oBook->{Format}[ $oCell->{FormatNo} ]->{FmtIdx}, $oBook ); unless ( defined($sFmtStr) ) { if ( $oCell->{Type} eq 'Numeric' ) { if ( int( $oCell->{Val} ) != $oCell->{Val} ) { $sFmtStr = '0.00'; } else { $sFmtStr = '0'; } } elsif ( $oCell->{Type} eq 'Date' ) { if ( int( $oCell->{Val} ) <= 0 ) { $sFmtStr = 'h:mm:ss'; } else { $sFmtStr = 'yyyy-mm-dd'; } } else { $sFmtStr = '@'; } } return $sFmtStr; } #------------------------------------------------------------------------------ # ValFmt (for Spreadsheet::ParseExcel::FmtDefault) #------------------------------------------------------------------------------ sub ValFmt { my ( $oThis, $oCell, $oBook ) = @_; my ( $Dt, $iFmtIdx, $iNumeric, $Flg1904 ); if ( $oCell->{Type} eq 'Text' ) { $Dt = ( ( defined $oCell->{Val} ) && ( $oCell->{Val} ne '' ) ) ? $oThis->TextFmt( $oCell->{Val}, $oCell->{Code} ) : ''; } else { $Dt = $oCell->{Val}; } $Flg1904 = $oBook->{Flg1904}; my $sFmtStr = $oThis->FmtString( $oCell, $oBook ); return ExcelFmt( $sFmtStr, $Dt, $Flg1904, $oCell->{Type} ); } #------------------------------------------------------------------------------ # ChkType (for Spreadsheet::ParseExcel::FmtDefault) #------------------------------------------------------------------------------ sub ChkType { my ( $oPkg, $iNumeric, $iFmtIdx ) = @_; if ($iNumeric) { if ( ( ( $iFmtIdx >= 0x0E ) && ( $iFmtIdx <= 0x16 ) ) || ( ( $iFmtIdx >= 0x2D ) && ( $iFmtIdx <= 0x2F ) ) ) { return "Date"; } else { return "Numeric"; } } else { return "Text"; } } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::FmtDefault - A class for Cell formats. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/Dump.pm0000644000176000001440000001735111326376247021070 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Dump; ############################################################################### # # Spreadsheet::ParseExcel::Dump - A class for dumping Excel records. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; our $VERSION = '0.56'; my %NameTbl = ( #P291 0x0A => 'EOF', 0x0C => 'CALCCOUNT', 0x0D => 'CALCMODE', 0x0E => 'PRECISION', 0x0F => 'REFMODE', 0x10 => 'DELTA', 0x11 => 'ITERATION', 0x12 => 'PROTECT', 0x13 => 'PASSWORD', 0x14 => 'HEADER', 0x15 => 'FOOTER', 0x16 => 'EXTERNCOUNT', 0x17 => 'EXTERNSHEET', 0x19 => 'WINDOWPROTECT', 0x1A => 'VERTICALPAGEBREAKS', 0x1B => 'HORIZONTALPAGEBREAKS', 0x1C => 'NOTE', 0x1D => 'SELECTION', 0x22 => '1904', 0x26 => 'LEFTMARGIN', 0x27 => 'RIGHTMARGIN', 0x28 => 'TOPMARGIN', 0x29 => 'BOTTOMMARGIN', 0x2A => 'PRINTHEADERS', 0x2B => 'PRINTGRIDLINES', 0x2F => 'FILEPASS', 0x3C => 'COUNTINUE', 0x3D => 'WINDOW1', 0x40 => 'BACKUP', 0x41 => 'PANE', 0x42 => 'CODEPAGE', 0x4D => 'PLS', 0x50 => 'DCON', 0x51 => 'DCONREF', #P292 0x52 => 'DCONNAME', 0x55 => 'DEFCOLWIDTH', 0x59 => 'XCT', 0x5A => 'CRN', 0x5B => 'FILESHARING', 0x5C => 'WRITEACCES', 0x5D => 'OBJ', 0x5E => 'UNCALCED', 0x5F => 'SAVERECALC', 0x60 => 'TEMPLATE', 0x63 => 'OBJPROTECT', 0x7D => 'COLINFO', 0x7E => 'RK', 0x7F => 'IMDATA', 0x80 => 'GUTS', 0x81 => 'WSBOOL', 0x82 => 'GRIDSET', 0x83 => 'HCENTER', 0x84 => 'VCENTER', 0x85 => 'BOUNDSHEET', 0x86 => 'WRITEPROT', 0x87 => 'ADDIN', 0x88 => 'EDG', 0x89 => 'PUB', 0x8C => 'COUNTRY', 0x8D => 'HIDEOBJ', 0x90 => 'SORT', 0x91 => 'SUB', 0x92 => 'PALETTE', 0x94 => 'LHRECORD', 0x95 => 'LHNGRAPH', 0x96 => 'SOUND', 0x98 => 'LPR', 0x99 => 'STANDARDWIDTH', 0x9A => 'FNGROUPNAME', 0x9B => 'FILTERMODE', 0x9C => 'FNGROUPCOUNT', #P293 0x9D => 'AUTOFILTERINFO', 0x9E => 'AUTOFILTER', 0xA0 => 'SCL', 0xA1 => 'SETUP', 0xA9 => 'COORDLIST', 0xAB => 'GCW', 0xAE => 'SCENMAN', 0xAF => 'SCENARIO', 0xB0 => 'SXVIEW', 0xB1 => 'SXVD', 0xB2 => 'SXV', 0xB4 => 'SXIVD', 0xB5 => 'SXLI', 0xB6 => 'SXPI', 0xB8 => 'DOCROUTE', 0xB9 => 'RECIPNAME', 0xBC => 'SHRFMLA', 0xBD => 'MULRK', 0xBE => 'MULBLANK', 0xBF => 'TOOLBARHDR', 0xC0 => 'TOOLBAREND', 0xC1 => 'MMS', 0xC2 => 'ADDMENU', 0xC3 => 'DELMENU', 0xC5 => 'SXDI', 0xC6 => 'SXDB', 0xCD => 'SXSTRING', 0xD0 => 'SXTBL', 0xD1 => 'SXTBRGIITM', 0xD2 => 'SXTBPG', 0xD3 => 'OBPROJ', 0xD5 => 'SXISDTM', 0xD6 => 'RSTRING', 0xD7 => 'DBCELL', 0xDA => 'BOOKBOOL', 0xDC => 'PARAMQRY', 0xDC => 'SXEXT', 0xDD => 'SCENPROTECT', 0xDE => 'OLESIZE', #P294 0xDF => 'UDDESC', 0xE0 => 'XF', 0xE1 => 'INTERFACEHDR', 0xE2 => 'INTERFACEEND', 0xE3 => 'SXVS', 0xEA => 'TABIDCONF', 0xEB => 'MSODRAWINGGROUP', 0xEC => 'MSODRAWING', 0xED => 'MSODRAWINGSELECTION', 0xEF => 'PHONETICINFO', 0xF0 => 'SXRULE', 0xF1 => 'SXEXT', 0xF2 => 'SXFILT', 0xF6 => 'SXNAME', 0xF7 => 'SXSELECT', 0xF8 => 'SXPAIR', 0xF9 => 'SXFMLA', 0xFB => 'SXFORMAT', 0xFC => 'SST', 0xFD => 'LABELSST', 0xFF => 'EXTSST', 0x100 => 'SXVDEX', 0x103 => 'SXFORMULA', 0x122 => 'SXDBEX', 0x13D => 'TABID', 0x160 => 'USESELFS', 0x161 => 'DSF', 0x162 => 'XL5MODIFY', 0x1A5 => 'FILESHARING2', 0x1A9 => 'USERBVIEW', 0x1AA => 'USERVIEWBEGIN', 0x1AB => 'USERSVIEWEND', 0x1AD => 'QSI', 0x1AE => 'SUPBOOK', 0x1AF => 'PROT4REV', 0x1B0 => 'CONDFMT', 0x1B1 => 'CF', 0x1B2 => 'DVAL', #P295 0x1B5 => 'DCONBIN', 0x1B6 => 'TXO', 0x1B7 => 'REFRESHALL', 0x1B8 => 'HLINK', 0x1BA => 'CODENAME', 0x1BB => 'SXFDBTYPE', 0x1BC => 'PROT4REVPASS', 0x1BE => 'DV', 0x200 => 'DIMENSIONS', 0x201 => 'BLANK', 0x202 => 'Integer', #Not Documented 0x203 => 'NUMBER', 0x204 => 'LABEL', 0x205 => 'BOOLERR', 0x207 => 'STRING', 0x208 => 'ROW', 0x20B => 'INDEX', 0x218 => 'NAME', 0x221 => 'ARRAY', 0x223 => 'EXTERNNAME', 0x225 => 'DEFAULTROWHEIGHT', 0x231 => 'FONT', 0x236 => 'TABLE', 0x23E => 'WINDOW2', 0x293 => 'STYLE', 0x406 => 'FORMULA', 0x41E => 'FORMAT', 0x18 => 'NAME', 0x06 => 'FORMULA', 0x09 => 'BOF(BIFF2)', 0x209 => 'BOF(BIFF3)', 0x409 => 'BOF(BIFF4)', 0x809 => 'BOF(BIFF5-7)', 0x31 => 'FONT', 0x27E => 'RK', #Chart/Graph 0x1001 => 'UNITS', 0x1002 => 'CHART', 0x1003 => 'SERISES', 0x1006 => 'DATAFORMAT', 0x1007 => 'LINEFORMAT', 0x1009 => 'MAKERFORMAT', 0x100A => 'AREAFORMAT', 0x100B => 'PIEFORMAT', 0x100C => 'ATTACHEDLABEL', 0x100D => 'SERIESTEXT', 0x1014 => 'CHARTFORMAT', 0x1015 => 'LEGEND', 0x1016 => 'SERIESLIST', 0x1017 => 'BAR', 0x1018 => 'LINE', 0x1019 => 'PIE', 0x101A => 'AREA', 0x101B => 'SCATTER', 0x101C => 'CHARTLINE', 0x101D => 'AXIS', 0x101E => 'TICK', 0x101F => 'VALUERANGE', 0x1020 => 'CATSERRANGE', 0x1021 => 'AXISLINEFORMAT', 0x1022 => 'CHARTFORMATLINK', 0x1024 => 'DEFAULTTEXT', 0x1025 => 'TEXT', 0x1026 => 'FONTX', 0x1027 => 'OBJECTLINK', 0x1032 => 'FRAME', 0x1033 => 'BEGIN', 0x1034 => 'END', 0x1035 => 'PLOTAREA', 0x103A => '3D', 0x103C => 'PICF', 0x103D => 'DROPBAR', 0x103E => 'RADAR', 0x103F => 'SURFACE', 0x1040 => 'RADARAREA', 0x1041 => 'AXISPARENT', 0x1043 => 'LEGENDXN', 0x1044 => 'SHTPROPS', 0x1045 => 'SERTOCRT', 0x1046 => 'AXESUSED', 0x1048 => 'SBASEREF', 0x104A => 'SERPARENT', 0x104B => 'SERAUXTREND', 0x104E => 'IFMT', 0x104F => 'POS', 0x1050 => 'ALRUNS', 0x1051 => 'AI', 0x105B => 'SERAUXERRBAR', 0x105D => 'SERFMT', 0x1060 => 'FBI', 0x1061 => 'BOPPOP', 0x1062 => 'AXCEXT', 0x1063 => 'DAT', 0x1064 => 'PLOTGROWTH', 0x1065 => 'SINDEX', 0x1066 => 'GELFRAME', 0x1067 => 'BPOPPOPCUSTOM', ); #------------------------------------------------------------------------------ # subDUMP (for Spreadsheet::ParseExcel) #------------------------------------------------------------------------------ sub subDUMP { my ( $oBook, $bOp, $bLen, $sWk ) = @_; printf "%04X:%-23s (Len:%3d) : %s\n", $bOp, OpName($bOp), $bLen, unpack( "H40", $sWk ); } #------------------------------------------------------------------------------ # Spreadsheet::ParseExcel->OpName #------------------------------------------------------------------------------ sub OpName { my ($bOp) = @_; return ( defined $NameTbl{$bOp} ) ? $NameTbl{$bOp} : 'undef'; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Dump - A class for dumping Excel records. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/Spreadsheet/ParseExcel/Cell.pm0000644000176000001440000001737711326376247021052 0ustar ripleyuserspackage Spreadsheet::ParseExcel::Cell; ############################################################################### # # Spreadsheet::ParseExcel::Cell - A class for Cell data and formatting. # # Used in conjunction with Spreadsheet::ParseExcel. # # Copyright (c) 2009 John McNamara # Copyright (c) 2006-2008 Gabor Szabo # Copyright (c) 2000-2006 Kawai Takanori # # perltidy with standard settings. # # Documentation after __END__ # use strict; use warnings; our $VERSION = '0.56'; ############################################################################### # # new() # # Constructor. # sub new { my ( $package, %properties ) = @_; my $self = \%properties; bless $self, $package; } ############################################################################### # # value() # # Returns the formatted value of the cell. # sub value { my $self = shift; return $self->{_Value}; } ############################################################################### # # unformatted() # # Returns the unformatted value of the cell. # sub unformatted { my $self = shift; return $self->{Val}; } ############################################################################### # # get_format() # # Returns the Format object for the cell. # sub get_format { my $self = shift; return $self->{Format}; } ############################################################################### # # type() # # Returns the type of cell such as Text, Numeric or Date. # sub type { my $self = shift; return $self->{Type}; } ############################################################################### # # encoding() # # Returns the character encoding of the cell. # sub encoding { my $self = shift; if ( !defined $self->{Code} ) { return 1; } elsif ( $self->{Code} eq 'ucs2' ) { return 2; } elsif ( $self->{Code} eq '_native_' ) { return 3; } else { return 0; } return $self->{Code}; } ############################################################################### # # is_merged() # # Returns true if the cell is merged. # sub is_merged { my $self = shift; return $self->{Merged}; } ############################################################################### # # get_rich_text() # # Returns an array ref of font information about each string block in a "rich", # i.e. multi-format, string. # sub get_rich_text { my $self = shift; return $self->{Rich}; } ############################################################################### # # Mapping between legacy method names and new names. # { no warnings; # Ignore warnings about variables used only once. *Value = *value; } 1; __END__ =pod =head1 NAME Spreadsheet::ParseExcel::Cell - A class for Cell data and formatting. =head1 SYNOPSIS See the documentation for Spreadsheet::ParseExcel. =head1 DESCRIPTION This module is used in conjunction with Spreadsheet::ParseExcel. See the documentation for Spreadsheet::ParseExcel. =head1 Methods The following Cell methods are available: $cell->value() $cell->unformatted() $cell->get_format() $cell->type() $cell->encoding() $cell->is_merged() $cell->get_rich_text() =head2 value() The C method returns the formatted value of the cell. my $value = $cell->value(); Formatted in this sense refers to the numeric format of the cell value. For example a number such as 40177 might be formatted as 40,117, 40117.000 or even as the date 2009/12/30. If the cell doesn't contain a numeric format then the formatted and unformatted cell values are the same, see the C method below. For a defined C<$cell> the C method will always return a value. In the case of a cell with formatting but no numeric or string contents the method will return the empty string C<''>. =head2 unformatted() The C method returns the unformatted value of the cell. my $unformatted = $cell->unformatted(); Returns the cell value without a numeric format. See the C method above. =head2 get_format() The C method returns the L object for the cell. my $format = $cell->get_format(); If a user defined format hasn't been applied to the cell then the default cell format is returned. =head2 type() The C method returns the type of cell such as Text, Numeric or Date. If the type was detected as Numeric, and the Cell Format matches C, it will be treated as a Date type. my $type = $cell->type(); See also L. =head2 encoding() The C method returns the character encoding of the cell. my $encoding = $cell->encoding(); This method is only of interest to developers. In general Spreadsheet::ParseExcel will return all character strings in UTF-8 regardless of the encoding used by Excel. The C method returns one of the following values: =over =item * 0: Unknown format. This shouldn't happen. In the default case the format should be 1. =item * 1: 8bit ASCII or single byte UTF-16. This indicates that the characters are encoded in a single byte. In Excel 95 and earlier This usually meant ASCII or an international variant. In Excel 97 it refers to a compressed UTF-16 character string where all of the high order bytes are 0 and are omitted to save space. =item * 2: UTF-16BE. =item * 3: Native encoding. In Excel 95 and earlier this encoding was used to represent multi-byte character encodings such as SJIS. =back =head2 is_merged() The C method returns true if the cell is merged. my $is_merged = $cell->is_merged(); Returns C if the property isn't set. =head2 get_rich_text() The C method returns an array ref of font information about each string block in a "rich", i.e. multi-format, string. my $rich_text = $cell->get_rich_text(); The return value is an arrayref of arrayrefs in the form: [ [ $start_position, $font_object ], ..., ] Returns undef if the property isn't set. =head1 Dates and Time in Excel Dates and times in Excel are represented by real numbers, for example "Jan 1 2001 12:30 PM" is represented by the number 36892.521. The integer part of the number stores the number of days since the epoch and the fractional part stores the percentage of the day. A date or time in Excel is just like any other number. The way in which it is displayed is controlled by the number format: Number format $cell->value() $cell->unformatted() ============= ============== ============== 'dd/mm/yy' '28/02/08' 39506.5 'mm/dd/yy' '02/28/08' 39506.5 'd-m-yyyy' '28-2-2008' 39506.5 'dd/mm/yy hh:mm' '28/02/08 12:00' 39506.5 'd mmm yyyy' '28 Feb 2008' 39506.5 'mmm d yyyy hh:mm AM/PM' 'Feb 28 2008 12:00 PM' 39506.5 The L module contains a function called C which will convert between an unformatted Excel date/time number and a C like array. For date conversions using the CPAN C framework see L http://search.cpan.org/search?dist=DateTime-Format-Excel =head1 AUTHOR Maintainer 0.40+: John McNamara jmcnamara@cpan.org Maintainer 0.27-0.33: Gabor Szabo szabgab@cpan.org Original author: Kawai Takanori kwitknr@cpan.org =head1 COPYRIGHT Copyright (c) 2009 John McNamara Copyright (c) 2006-2008 Gabor Szabo Copyright (c) 2000-2006 Kawai Takanori All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =cut gdata/inst/perl/OLE/0000755000176000001440000000000012024144455013721 5ustar ripleyusersgdata/inst/perl/OLE/Storage_Lite.pm0000644000176000001440000015211711326376764016665 0ustar ripleyusers# OLE::Storage_Lite # by Kawai, Takanori (Hippo2000) 2000.11.4, 8, 14 # This Program is Still ALPHA version. #////////////////////////////////////////////////////////////////////////////// # OLE::Storage_Lite::PPS Object #////////////////////////////////////////////////////////////////////////////// #============================================================================== # OLE::Storage_Lite::PPS #============================================================================== package OLE::Storage_Lite::PPS; require Exporter; use strict; use vars qw($VERSION @ISA); @ISA = qw(Exporter); $VERSION = '0.19'; #------------------------------------------------------------------------------ # new (OLE::Storage_Lite::PPS) #------------------------------------------------------------------------------ sub new ($$$$$$$$$$;$$) { #1. Constructor for General Usage my($sClass, $iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd, $iStart, $iSize, $sData, $raChild) = @_; if($iType == OLE::Storage_Lite::PpsType_File()) { #FILE return OLE::Storage_Lite::PPS::File->_new ($iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd, $iStart, $iSize, $sData, $raChild); } elsif($iType == OLE::Storage_Lite::PpsType_Dir()) { #DIRECTRY return OLE::Storage_Lite::PPS::Dir->_new ($iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd, $iStart, $iSize, $sData, $raChild); } elsif($iType == OLE::Storage_Lite::PpsType_Root()) { #ROOT return OLE::Storage_Lite::PPS::Root->_new ($iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd, $iStart, $iSize, $sData, $raChild); } else { die "Error PPS:$iType $sNm\n"; } } #------------------------------------------------------------------------------ # _new (OLE::Storage_Lite::PPS) # for OLE::Storage_Lite #------------------------------------------------------------------------------ sub _new ($$$$$$$$$$$;$$) { my($sClass, $iNo, $sNm, $iType, $iPrev, $iNext, $iDir, $raTime1st, $raTime2nd, $iStart, $iSize, $sData, $raChild) = @_; #1. Constructor for OLE::Storage_Lite my $oThis = { No => $iNo, Name => $sNm, Type => $iType, PrevPps => $iPrev, NextPps => $iNext, DirPps => $iDir, Time1st => $raTime1st, Time2nd => $raTime2nd, StartBlock => $iStart, Size => $iSize, Data => $sData, Child => $raChild, }; bless $oThis, $sClass; return $oThis; } #------------------------------------------------------------------------------ # _DataLen (OLE::Storage_Lite::PPS) # Check for update #------------------------------------------------------------------------------ sub _DataLen($) { my($oSelf) =@_; return 0 unless(defined($oSelf->{Data})); return ($oSelf->{_PPS_FILE})? ($oSelf->{_PPS_FILE}->stat())[7] : length($oSelf->{Data}); } #------------------------------------------------------------------------------ # _makeSmallData (OLE::Storage_Lite::PPS) #------------------------------------------------------------------------------ sub _makeSmallData($$$) { my($oThis, $aList, $rhInfo) = @_; my ($sRes); my $FILE = $rhInfo->{_FILEH_}; my $iSmBlk = 0; foreach my $oPps (@$aList) { #1. Make SBD, small data string if($oPps->{Type}==OLE::Storage_Lite::PpsType_File()) { next if($oPps->{Size}<=0); if($oPps->{Size} < $rhInfo->{_SMALL_SIZE}) { my $iSmbCnt = int($oPps->{Size} / $rhInfo->{_SMALL_BLOCK_SIZE}) + (($oPps->{Size} % $rhInfo->{_SMALL_BLOCK_SIZE})? 1: 0); #1.1 Add to SBD for (my $i = 0; $i<($iSmbCnt-1); $i++) { print {$FILE} (pack("V", $i+$iSmBlk+1)); } print {$FILE} (pack("V", -2)); #1.2 Add to Data String(this will be written for RootEntry) #Check for update if($oPps->{_PPS_FILE}) { my $sBuff; $oPps->{_PPS_FILE}->seek(0, 0); #To The Top while($oPps->{_PPS_FILE}->read($sBuff, 4096)) { $sRes .= $sBuff; } } else { $sRes .= $oPps->{Data}; } $sRes .= ("\x00" x ($rhInfo->{_SMALL_BLOCK_SIZE} - ($oPps->{Size}% $rhInfo->{_SMALL_BLOCK_SIZE}))) if($oPps->{Size}% $rhInfo->{_SMALL_BLOCK_SIZE}); #1.3 Set for PPS $oPps->{StartBlock} = $iSmBlk; $iSmBlk += $iSmbCnt; } } } my $iSbCnt = int($rhInfo->{_BIG_BLOCK_SIZE}/ OLE::Storage_Lite::LongIntSize()); print {$FILE} (pack("V", -1) x ($iSbCnt - ($iSmBlk % $iSbCnt))) if($iSmBlk % $iSbCnt); #2. Write SBD with adjusting length for block return $sRes; } #------------------------------------------------------------------------------ # _savePpsWk (OLE::Storage_Lite::PPS) #------------------------------------------------------------------------------ sub _savePpsWk($$) { my($oThis, $rhInfo) = @_; #1. Write PPS my $FILE = $rhInfo->{_FILEH_}; print {$FILE} ( $oThis->{Name} . ("\x00" x (64 - length($oThis->{Name}))) #64 , pack("v", length($oThis->{Name}) + 2) #66 , pack("c", $oThis->{Type}) #67 , pack("c", 0x00) #UK #68 , pack("V", $oThis->{PrevPps}) #Prev #72 , pack("V", $oThis->{NextPps}) #Next #76 , pack("V", $oThis->{DirPps}) #Dir #80 , "\x00\x09\x02\x00" #84 , "\x00\x00\x00\x00" #88 , "\xc0\x00\x00\x00" #92 , "\x00\x00\x00\x46" #96 , "\x00\x00\x00\x00" #100 , OLE::Storage_Lite::LocalDate2OLE($oThis->{Time1st}) #108 , OLE::Storage_Lite::LocalDate2OLE($oThis->{Time2nd}) #116 , pack("V", defined($oThis->{StartBlock})? $oThis->{StartBlock}:0) #116 , pack("V", defined($oThis->{Size})? $oThis->{Size} : 0) #124 , pack("V", 0), #128 ); } #////////////////////////////////////////////////////////////////////////////// # OLE::Storage_Lite::PPS::Root Object #////////////////////////////////////////////////////////////////////////////// #============================================================================== # OLE::Storage_Lite::PPS::Root #============================================================================== package OLE::Storage_Lite::PPS::Root; require Exporter; use strict; use IO::File; use IO::Handle; use Fcntl; use vars qw($VERSION @ISA); @ISA = qw(OLE::Storage_Lite::PPS Exporter); $VERSION = '0.19'; sub _savePpsSetPnt($$$); sub _savePpsSetPnt2($$$); #------------------------------------------------------------------------------ # new (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub new ($;$$$) { my($sClass, $raTime1st, $raTime2nd, $raChild) = @_; OLE::Storage_Lite::PPS::_new( $sClass, undef, OLE::Storage_Lite::Asc2Ucs('Root Entry'), 5, undef, undef, undef, $raTime1st, $raTime2nd, undef, undef, undef, $raChild); } #------------------------------------------------------------------------------ # save (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub save($$;$$) { my($oThis, $sFile, $bNoAs, $rhInfo) = @_; #0.Initial Setting for saving $rhInfo = {} unless($rhInfo); $rhInfo->{_BIG_BLOCK_SIZE} = 2** (($rhInfo->{_BIG_BLOCK_SIZE})? _adjust2($rhInfo->{_BIG_BLOCK_SIZE}) : 9); $rhInfo->{_SMALL_BLOCK_SIZE}= 2 ** (($rhInfo->{_SMALL_BLOCK_SIZE})? _adjust2($rhInfo->{_SMALL_BLOCK_SIZE}): 6); $rhInfo->{_SMALL_SIZE} = 0x1000; $rhInfo->{_PPS_SIZE} = 0x80; my $closeFile = 1; #1.Open File #1.1 $sFile is Ref of scalar if(ref($sFile) eq 'SCALAR') { require IO::Scalar; my $oIo = new IO::Scalar $sFile, O_WRONLY; $rhInfo->{_FILEH_} = $oIo; } #1.1.1 $sFile is a IO::Scalar object # Now handled as a filehandle ref below. #1.2 $sFile is a IO::Handle object elsif(UNIVERSAL::isa($sFile, 'IO::Handle')) { # Not all filehandles support binmode() so try it in an eval. eval{ binmode $sFile }; $rhInfo->{_FILEH_} = $sFile; } #1.3 $sFile is a simple filename string elsif(!ref($sFile)) { if($sFile ne '-') { my $oIo = new IO::File; $oIo->open(">$sFile") || return undef; binmode($oIo); $rhInfo->{_FILEH_} = $oIo; } else { my $oIo = new IO::Handle; $oIo->fdopen(fileno(STDOUT),"w") || return undef; binmode($oIo); $rhInfo->{_FILEH_} = $oIo; } } #1.4 Assume that if $sFile is a ref then it is a valid filehandle else { # Not all filehandles support binmode() so try it in an eval. eval{ binmode $sFile }; $rhInfo->{_FILEH_} = $sFile; # Caller controls filehandle closing $closeFile = 0; } my $iBlk = 0; #1. Make an array of PPS (for Save) my @aList=(); if($bNoAs) { _savePpsSetPnt2([$oThis], \@aList, $rhInfo); } else { _savePpsSetPnt([$oThis], \@aList, $rhInfo); } my ($iSBDcnt, $iBBcnt, $iPPScnt) = $oThis->_calcSize(\@aList, $rhInfo); #2.Save Header $oThis->_saveHeader($rhInfo, $iSBDcnt, $iBBcnt, $iPPScnt); #3.Make Small Data string (write SBD) my $sSmWk = $oThis->_makeSmallData(\@aList, $rhInfo); $oThis->{Data} = $sSmWk; #Small Datas become RootEntry Data #4. Write BB my $iBBlk = $iSBDcnt; $oThis->_saveBigData(\$iBBlk, \@aList, $rhInfo); #5. Write PPS $oThis->_savePps(\@aList, $rhInfo); #6. Write BD and BDList and Adding Header informations $oThis->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt, $rhInfo); #7.Close File return $rhInfo->{_FILEH_}->close if $closeFile; } #------------------------------------------------------------------------------ # _calcSize (OLE::Storage_Lite::PPS) #------------------------------------------------------------------------------ sub _calcSize($$) { my($oThis, $raList, $rhInfo) = @_; #0. Calculate Basic Setting my ($iSBDcnt, $iBBcnt, $iPPScnt) = (0,0,0); my $iSmallLen = 0; my $iSBcnt = 0; foreach my $oPps (@$raList) { if($oPps->{Type}==OLE::Storage_Lite::PpsType_File()) { $oPps->{Size} = $oPps->_DataLen(); #Mod if($oPps->{Size} < $rhInfo->{_SMALL_SIZE}) { $iSBcnt += int($oPps->{Size} / $rhInfo->{_SMALL_BLOCK_SIZE}) + (($oPps->{Size} % $rhInfo->{_SMALL_BLOCK_SIZE})? 1: 0); } else { $iBBcnt += (int($oPps->{Size}/ $rhInfo->{_BIG_BLOCK_SIZE}) + (($oPps->{Size}% $rhInfo->{_BIG_BLOCK_SIZE})? 1: 0)); } } } $iSmallLen = $iSBcnt * $rhInfo->{_SMALL_BLOCK_SIZE}; my $iSlCnt = int($rhInfo->{_BIG_BLOCK_SIZE}/ OLE::Storage_Lite::LongIntSize()); $iSBDcnt = int($iSBcnt / $iSlCnt)+ (($iSBcnt % $iSlCnt)? 1:0); $iBBcnt += (int($iSmallLen/ $rhInfo->{_BIG_BLOCK_SIZE}) + (( $iSmallLen% $rhInfo->{_BIG_BLOCK_SIZE})? 1: 0)); my $iCnt = scalar(@$raList); my $iBdCnt = $rhInfo->{_BIG_BLOCK_SIZE}/OLE::Storage_Lite::PpsSize(); $iPPScnt = (int($iCnt/$iBdCnt) + (($iCnt % $iBdCnt)? 1: 0)); return ($iSBDcnt, $iBBcnt, $iPPScnt); } #------------------------------------------------------------------------------ # _adjust2 (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub _adjust2($) { my($i2) = @_; my $iWk; $iWk = log($i2)/log(2); return ($iWk > int($iWk))? int($iWk)+1:$iWk; } #------------------------------------------------------------------------------ # _saveHeader (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub _saveHeader($$$$$) { my($oThis, $rhInfo, $iSBDcnt, $iBBcnt, $iPPScnt) = @_; my $FILE = $rhInfo->{_FILEH_}; #0. Calculate Basic Setting my $iBlCnt = $rhInfo->{_BIG_BLOCK_SIZE} / OLE::Storage_Lite::LongIntSize(); my $i1stBdL = int(($rhInfo->{_BIG_BLOCK_SIZE} - 0x4C) / OLE::Storage_Lite::LongIntSize()); my $i1stBdMax = $i1stBdL * $iBlCnt - $i1stBdL; my $iBdExL = 0; my $iAll = $iBBcnt + $iPPScnt + $iSBDcnt; my $iAllW = $iAll; my $iBdCntW = int($iAllW / $iBlCnt) + (($iAllW % $iBlCnt)? 1: 0); my $iBdCnt = int(($iAll + $iBdCntW) / $iBlCnt) + ((($iAllW+$iBdCntW) % $iBlCnt)? 1: 0); my $i; if ($iBdCnt > $i1stBdL) { #0.1 Calculate BD count $iBlCnt--; #the BlCnt is reduced in the count of the last sect is used for a pointer the next Bl my $iBBleftover = $iAll - $i1stBdMax; if ($iAll >$i1stBdMax) { while(1) { $iBdCnt = int(($iBBleftover) / $iBlCnt) + ((($iBBleftover) % $iBlCnt)? 1: 0); $iBdExL = int(($iBdCnt) / $iBlCnt) + ((($iBdCnt) % $iBlCnt)? 1: 0); $iBBleftover = $iBBleftover + $iBdExL; last if($iBdCnt == (int(($iBBleftover) / $iBlCnt) + ((($iBBleftover) % $iBlCnt)? 1: 0))); } } $iBdCnt += $i1stBdL; #print "iBdCnt = $iBdCnt \n"; } #1.Save Header print {$FILE} ( "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1" , "\x00\x00\x00\x00" x 4 , pack("v", 0x3b) , pack("v", 0x03) , pack("v", -2) , pack("v", 9) , pack("v", 6) , pack("v", 0) , "\x00\x00\x00\x00" x 2 , pack("V", $iBdCnt), , pack("V", $iBBcnt+$iSBDcnt), #ROOT START , pack("V", 0) , pack("V", 0x1000) , pack("V", $iSBDcnt ? 0 : -2) #Small Block Depot , pack("V", $iSBDcnt) ); #2. Extra BDList Start, Count if($iAll <= $i1stBdMax) { print {$FILE} ( pack("V", -2), #Extra BDList Start pack("V", 0), #Extra BDList Count ); } else { print {$FILE} ( pack("V", $iAll+$iBdCnt), pack("V", $iBdExL), ); } #3. BDList for($i=0; $i<$i1stBdL and $i < $iBdCnt; $i++) { print {$FILE} (pack("V", $iAll+$i)); } print {$FILE} ((pack("V", -1)) x($i1stBdL-$i)) if($i<$i1stBdL); } #------------------------------------------------------------------------------ # _saveBigData (OLE::Storage_Lite::PPS) #------------------------------------------------------------------------------ sub _saveBigData($$$$) { my($oThis, $iStBlk, $raList, $rhInfo) = @_; my $iRes = 0; my $FILE = $rhInfo->{_FILEH_}; #1.Write Big (ge 0x1000) Data into Block foreach my $oPps (@$raList) { if($oPps->{Type}!=OLE::Storage_Lite::PpsType_Dir()) { #print "PPS: $oPps DEF:", defined($oPps->{Data}), "\n"; $oPps->{Size} = $oPps->_DataLen(); #Mod if(($oPps->{Size} >= $rhInfo->{_SMALL_SIZE}) || (($oPps->{Type} == OLE::Storage_Lite::PpsType_Root()) && defined($oPps->{Data}))) { #1.1 Write Data #Check for update if($oPps->{_PPS_FILE}) { my $sBuff; my $iLen = 0; $oPps->{_PPS_FILE}->seek(0, 0); #To The Top while($oPps->{_PPS_FILE}->read($sBuff, 4096)) { $iLen += length($sBuff); print {$FILE} ($sBuff); #Check for update } } else { print {$FILE} ($oPps->{Data}); } print {$FILE} ( "\x00" x ($rhInfo->{_BIG_BLOCK_SIZE} - ($oPps->{Size} % $rhInfo->{_BIG_BLOCK_SIZE})) ) if ($oPps->{Size} % $rhInfo->{_BIG_BLOCK_SIZE}); #1.2 Set For PPS $oPps->{StartBlock} = $$iStBlk; $$iStBlk += (int($oPps->{Size}/ $rhInfo->{_BIG_BLOCK_SIZE}) + (($oPps->{Size}% $rhInfo->{_BIG_BLOCK_SIZE})? 1: 0)); } } } } #------------------------------------------------------------------------------ # _savePps (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub _savePps($$$) { my($oThis, $raList, $rhInfo) = @_; #0. Initial my $FILE = $rhInfo->{_FILEH_}; #2. Save PPS foreach my $oItem (@$raList) { $oItem->_savePpsWk($rhInfo); } #3. Adjust for Block my $iCnt = scalar(@$raList); my $iBCnt = $rhInfo->{_BIG_BLOCK_SIZE} / $rhInfo->{_PPS_SIZE}; print {$FILE} ("\x00" x (($iBCnt - ($iCnt % $iBCnt)) * $rhInfo->{_PPS_SIZE})) if($iCnt % $iBCnt); return int($iCnt / $iBCnt) + (($iCnt % $iBCnt)? 1: 0); } #------------------------------------------------------------------------------ # _savePpsSetPnt2 (OLE::Storage_Lite::PPS::Root) # For Test #------------------------------------------------------------------------------ sub _savePpsSetPnt2($$$) { my($aThis, $raList, $rhInfo) = @_; #1. make Array as Children-Relations #1.1 if No Children if($#$aThis < 0) { return 0xFFFFFFFF; } elsif($#$aThis == 0) { #1.2 Just Only one push @$raList, $aThis->[0]; $aThis->[0]->{No} = $#$raList; $aThis->[0]->{PrevPps} = 0xFFFFFFFF; $aThis->[0]->{NextPps} = 0xFFFFFFFF; $aThis->[0]->{DirPps} = _savePpsSetPnt2($aThis->[0]->{Child}, $raList, $rhInfo); return $aThis->[0]->{No}; } else { #1.3 Array my $iCnt = $#$aThis + 1; #1.3.1 Define Center my $iPos = 0; #int($iCnt/ 2); #$iCnt my @aWk = @$aThis; my @aPrev = ($#$aThis > 1)? splice(@aWk, 1, 1) : (); #$iPos); my @aNext = splice(@aWk, 1); #, $iCnt - $iPos -1); $aThis->[$iPos]->{PrevPps} = _savePpsSetPnt2( \@aPrev, $raList, $rhInfo); push @$raList, $aThis->[$iPos]; $aThis->[$iPos]->{No} = $#$raList; #1.3.2 Devide a array into Previous,Next $aThis->[$iPos]->{NextPps} = _savePpsSetPnt2( \@aNext, $raList, $rhInfo); $aThis->[$iPos]->{DirPps} = _savePpsSetPnt2($aThis->[$iPos]->{Child}, $raList, $rhInfo); return $aThis->[$iPos]->{No}; } } #------------------------------------------------------------------------------ # _savePpsSetPnt2 (OLE::Storage_Lite::PPS::Root) # For Test #------------------------------------------------------------------------------ sub _savePpsSetPnt2s($$$) { my($aThis, $raList, $rhInfo) = @_; #1. make Array as Children-Relations #1.1 if No Children if($#$aThis < 0) { return 0xFFFFFFFF; } elsif($#$aThis == 0) { #1.2 Just Only one push @$raList, $aThis->[0]; $aThis->[0]->{No} = $#$raList; $aThis->[0]->{PrevPps} = 0xFFFFFFFF; $aThis->[0]->{NextPps} = 0xFFFFFFFF; $aThis->[0]->{DirPps} = _savePpsSetPnt2($aThis->[0]->{Child}, $raList, $rhInfo); return $aThis->[0]->{No}; } else { #1.3 Array my $iCnt = $#$aThis + 1; #1.3.1 Define Center my $iPos = 0; #int($iCnt/ 2); #$iCnt push @$raList, $aThis->[$iPos]; $aThis->[$iPos]->{No} = $#$raList; my @aWk = @$aThis; #1.3.2 Devide a array into Previous,Next my @aPrev = splice(@aWk, 0, $iPos); my @aNext = splice(@aWk, 1, $iCnt - $iPos -1); $aThis->[$iPos]->{PrevPps} = _savePpsSetPnt2( \@aPrev, $raList, $rhInfo); $aThis->[$iPos]->{NextPps} = _savePpsSetPnt2( \@aNext, $raList, $rhInfo); $aThis->[$iPos]->{DirPps} = _savePpsSetPnt2($aThis->[$iPos]->{Child}, $raList, $rhInfo); return $aThis->[$iPos]->{No}; } } #------------------------------------------------------------------------------ # _savePpsSetPnt (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub _savePpsSetPnt($$$) { my($aThis, $raList, $rhInfo) = @_; #1. make Array as Children-Relations #1.1 if No Children if($#$aThis < 0) { return 0xFFFFFFFF; } elsif($#$aThis == 0) { #1.2 Just Only one push @$raList, $aThis->[0]; $aThis->[0]->{No} = $#$raList; $aThis->[0]->{PrevPps} = 0xFFFFFFFF; $aThis->[0]->{NextPps} = 0xFFFFFFFF; $aThis->[0]->{DirPps} = _savePpsSetPnt($aThis->[0]->{Child}, $raList, $rhInfo); return $aThis->[0]->{No}; } else { #1.3 Array my $iCnt = $#$aThis + 1; #1.3.1 Define Center my $iPos = int($iCnt/ 2); #$iCnt push @$raList, $aThis->[$iPos]; $aThis->[$iPos]->{No} = $#$raList; my @aWk = @$aThis; #1.3.2 Devide a array into Previous,Next my @aPrev = splice(@aWk, 0, $iPos); my @aNext = splice(@aWk, 1, $iCnt - $iPos -1); $aThis->[$iPos]->{PrevPps} = _savePpsSetPnt( \@aPrev, $raList, $rhInfo); $aThis->[$iPos]->{NextPps} = _savePpsSetPnt( \@aNext, $raList, $rhInfo); $aThis->[$iPos]->{DirPps} = _savePpsSetPnt($aThis->[$iPos]->{Child}, $raList, $rhInfo); return $aThis->[$iPos]->{No}; } } #------------------------------------------------------------------------------ # _savePpsSetPnt (OLE::Storage_Lite::PPS::Root) #------------------------------------------------------------------------------ sub _savePpsSetPnt1($$$) { my($aThis, $raList, $rhInfo) = @_; #1. make Array as Children-Relations #1.1 if No Children if($#$aThis < 0) { return 0xFFFFFFFF; } elsif($#$aThis == 0) { #1.2 Just Only one push @$raList, $aThis->[0]; $aThis->[0]->{No} = $#$raList; $aThis->[0]->{PrevPps} = 0xFFFFFFFF; $aThis->[0]->{NextPps} = 0xFFFFFFFF; $aThis->[0]->{DirPps} = _savePpsSetPnt($aThis->[0]->{Child}, $raList, $rhInfo); return $aThis->[0]->{No}; } else { #1.3 Array my $iCnt = $#$aThis + 1; #1.3.1 Define Center my $iPos = int($iCnt/ 2); #$iCnt push @$raList, $aThis->[$iPos]; $aThis->[$iPos]->{No} = $#$raList; my @aWk = @$aThis; #1.3.2 Devide a array into Previous,Next my @aPrev = splice(@aWk, 0, $iPos); my @aNext = splice(@aWk, 1, $iCnt - $iPos -1); $aThis->[$iPos]->{PrevPps} = _savePpsSetPnt( \@aPrev, $raList, $rhInfo); $aThis->[$iPos]->{NextPps} = _savePpsSetPnt( \@aNext, $raList, $rhInfo); $aThis->[$iPos]->{DirPps} = _savePpsSetPnt($aThis->[$iPos]->{Child}, $raList, $rhInfo); return $aThis->[$iPos]->{No}; } } #------------------------------------------------------------------------------ # _saveBbd (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _saveBbd($$$$) { my($oThis, $iSbdSize, $iBsize, $iPpsCnt, $rhInfo) = @_; my $FILE = $rhInfo->{_FILEH_}; #0. Calculate Basic Setting my $iBbCnt = $rhInfo->{_BIG_BLOCK_SIZE} / OLE::Storage_Lite::LongIntSize(); my $iBlCnt = $iBbCnt - 1; my $i1stBdL = int(($rhInfo->{_BIG_BLOCK_SIZE} - 0x4C) / OLE::Storage_Lite::LongIntSize()); my $i1stBdMax = $i1stBdL * $iBbCnt - $i1stBdL; my $iBdExL = 0; my $iAll = $iBsize + $iPpsCnt + $iSbdSize; my $iAllW = $iAll; my $iBdCntW = int($iAllW / $iBbCnt) + (($iAllW % $iBbCnt)? 1: 0); my $iBdCnt = 0; my $i; #0.1 Calculate BD count my $iBBleftover = $iAll - $i1stBdMax; if ($iAll >$i1stBdMax) { while(1) { $iBdCnt = int(($iBBleftover) / $iBlCnt) + ((($iBBleftover) % $iBlCnt)? 1: 0); $iBdExL = int(($iBdCnt) / $iBlCnt) + ((($iBdCnt) % $iBlCnt)? 1: 0); $iBBleftover = $iBBleftover + $iBdExL; last if($iBdCnt == (int(($iBBleftover) / $iBlCnt) + ((($iBBleftover) % $iBlCnt)? 1: 0))); } } $iAllW += $iBdExL; $iBdCnt += $i1stBdL; #print "iBdCnt = $iBdCnt \n"; #1. Making BD #1.1 Set for SBD if($iSbdSize > 0) { for ($i = 0; $i<($iSbdSize-1); $i++) { print {$FILE} (pack("V", $i+1)); } print {$FILE} (pack("V", -2)); } #1.2 Set for B for ($i = 0; $i<($iBsize-1); $i++) { print {$FILE} (pack("V", $i+$iSbdSize+1)); } print {$FILE} (pack("V", -2)); #1.3 Set for PPS for ($i = 0; $i<($iPpsCnt-1); $i++) { print {$FILE} (pack("V", $i+$iSbdSize+$iBsize+1)); } print {$FILE} (pack("V", -2)); #1.4 Set for BBD itself ( 0xFFFFFFFD : BBD) for($i=0; $i<$iBdCnt;$i++) { print {$FILE} (pack("V", 0xFFFFFFFD)); } #1.5 Set for ExtraBDList for($i=0; $i<$iBdExL;$i++) { print {$FILE} (pack("V", 0xFFFFFFFC)); } #1.6 Adjust for Block print {$FILE} (pack("V", -1) x ($iBbCnt - (($iAllW + $iBdCnt) % $iBbCnt))) if(($iAllW + $iBdCnt) % $iBbCnt); #2.Extra BDList if($iBdCnt > $i1stBdL) { my $iN=0; my $iNb=0; for($i=$i1stBdL;$i<$iBdCnt; $i++, $iN++) { if($iN>=($iBbCnt-1)) { $iN = 0; $iNb++; print {$FILE} (pack("V", $iAll+$iBdCnt+$iNb)); } print {$FILE} (pack("V", $iBsize+$iSbdSize+$iPpsCnt+$i)); } print {$FILE} (pack("V", -1) x (($iBbCnt-1) - (($iBdCnt-$i1stBdL) % ($iBbCnt-1)))) if(($iBdCnt-$i1stBdL) % ($iBbCnt-1)); print {$FILE} (pack("V", -2)); } } #////////////////////////////////////////////////////////////////////////////// # OLE::Storage_Lite::PPS::File Object #////////////////////////////////////////////////////////////////////////////// #============================================================================== # OLE::Storage_Lite::PPS::File #============================================================================== package OLE::Storage_Lite::PPS::File; require Exporter; use strict; use vars qw($VERSION @ISA); @ISA = qw(OLE::Storage_Lite::PPS Exporter); $VERSION = '0.19'; #------------------------------------------------------------------------------ # new (OLE::Storage_Lite::PPS::File) #------------------------------------------------------------------------------ sub new ($$$) { my($sClass, $sNm, $sData) = @_; OLE::Storage_Lite::PPS::_new( $sClass, undef, $sNm, 2, undef, undef, undef, undef, undef, undef, undef, $sData, undef); } #------------------------------------------------------------------------------ # newFile (OLE::Storage_Lite::PPS::File) #------------------------------------------------------------------------------ sub newFile ($$;$) { my($sClass, $sNm, $sFile) = @_; my $oSelf = OLE::Storage_Lite::PPS::_new( $sClass, undef, $sNm, 2, undef, undef, undef, undef, undef, undef, undef, '', undef); # if((!defined($sFile)) or ($sFile eq '')) { $oSelf->{_PPS_FILE} = IO::File->new_tmpfile(); } elsif(UNIVERSAL::isa($sFile, 'IO::Handle')) { $oSelf->{_PPS_FILE} = $sFile; } elsif(!ref($sFile)) { #File Name $oSelf->{_PPS_FILE} = new IO::File; return undef unless($oSelf->{_PPS_FILE}); $oSelf->{_PPS_FILE}->open("$sFile", "r+") || return undef; } else { return undef; } if($oSelf->{_PPS_FILE}) { $oSelf->{_PPS_FILE}->seek(0, 2); binmode($oSelf->{_PPS_FILE}); $oSelf->{_PPS_FILE}->autoflush(1); } return $oSelf; } #------------------------------------------------------------------------------ # append (OLE::Storage_Lite::PPS::File) #------------------------------------------------------------------------------ sub append ($$) { my($oSelf, $sData) = @_; if($oSelf->{_PPS_FILE}) { print {$oSelf->{_PPS_FILE}} $sData; } else { $oSelf->{Data} .= $sData; } } #////////////////////////////////////////////////////////////////////////////// # OLE::Storage_Lite::PPS::Dir Object #////////////////////////////////////////////////////////////////////////////// #------------------------------------------------------------------------------ # new (OLE::Storage_Lite::PPS::Dir) #------------------------------------------------------------------------------ package OLE::Storage_Lite::PPS::Dir; require Exporter; use strict; use vars qw($VERSION @ISA); @ISA = qw(OLE::Storage_Lite::PPS Exporter); $VERSION = '0.19'; sub new ($$;$$$) { my($sClass, $sName, $raTime1st, $raTime2nd, $raChild) = @_; OLE::Storage_Lite::PPS::_new( $sClass, undef, $sName, 1, undef, undef, undef, $raTime1st, $raTime2nd, undef, undef, undef, $raChild); } #============================================================================== # OLE::Storage_Lite #============================================================================== package OLE::Storage_Lite; require Exporter; use strict; use IO::File; use Time::Local 'timegm'; use vars qw($VERSION @ISA @EXPORT); @ISA = qw(Exporter); $VERSION = '0.19'; sub _getPpsSearch($$$$$;$); sub _getPpsTree($$$;$); #------------------------------------------------------------------------------ # Const for OLE::Storage_Lite #------------------------------------------------------------------------------ #0. Constants sub PpsType_Root {5}; sub PpsType_Dir {1}; sub PpsType_File {2}; sub DataSizeSmall{0x1000}; sub LongIntSize {4}; sub PpsSize {0x80}; #------------------------------------------------------------------------------ # new OLE::Storage_Lite #------------------------------------------------------------------------------ sub new($$) { my($sClass, $sFile) = @_; my $oThis = { _FILE => $sFile, }; bless $oThis; return $oThis; } #------------------------------------------------------------------------------ # getPpsTree: OLE::Storage_Lite #------------------------------------------------------------------------------ sub getPpsTree($;$) { my($oThis, $bData) = @_; #0.Init my $rhInfo = _initParse($oThis->{_FILE}); return undef unless($rhInfo); #1. Get Data my ($oPps) = _getPpsTree(0, $rhInfo, $bData); close(IN); return $oPps; } #------------------------------------------------------------------------------ # getSearch: OLE::Storage_Lite #------------------------------------------------------------------------------ sub getPpsSearch($$;$$) { my($oThis, $raName, $bData, $iCase) = @_; #0.Init my $rhInfo = _initParse($oThis->{_FILE}); return undef unless($rhInfo); #1. Get Data my @aList = _getPpsSearch(0, $rhInfo, $raName, $bData, $iCase); close(IN); return @aList; } #------------------------------------------------------------------------------ # getNthPps: OLE::Storage_Lite #------------------------------------------------------------------------------ sub getNthPps($$;$) { my($oThis, $iNo, $bData) = @_; #0.Init my $rhInfo = _initParse($oThis->{_FILE}); return undef unless($rhInfo); #1. Get Data my $oPps = _getNthPps($iNo, $rhInfo, $bData); close IN; return $oPps; } #------------------------------------------------------------------------------ # _initParse: OLE::Storage_Lite #------------------------------------------------------------------------------ sub _initParse($) { my($sFile)=@_; my $oIo; #1. $sFile is Ref of scalar if(ref($sFile) eq 'SCALAR') { require IO::Scalar; $oIo = new IO::Scalar; $oIo->open($sFile); } #2. $sFile is a IO::Handle object elsif(UNIVERSAL::isa($sFile, 'IO::Handle')) { $oIo = $sFile; binmode($oIo); } #3. $sFile is a simple filename string elsif(!ref($sFile)) { $oIo = new IO::File; $oIo->open("<$sFile") || return undef; binmode($oIo); } #4 Assume that if $sFile is a ref then it is a valid filehandle else { $oIo = $sFile; # Not all filehandles support binmode() so try it in an eval. eval{ binmode $oIo }; } return _getHeaderInfo($oIo); } #------------------------------------------------------------------------------ # _getPpsTree: OLE::Storage_Lite #------------------------------------------------------------------------------ sub _getPpsTree($$$;$) { my($iNo, $rhInfo, $bData, $raDone) = @_; if(defined($raDone)) { return () if(grep {$_ ==$iNo} @$raDone); } else { $raDone=[]; } push @$raDone, $iNo; my $iRootBlock = $rhInfo->{_ROOT_START} ; #1. Get Information about itself my $oPps = _getNthPps($iNo, $rhInfo, $bData); #2. Child if($oPps->{DirPps} != 0xFFFFFFFF) { my @aChildL = _getPpsTree($oPps->{DirPps}, $rhInfo, $bData, $raDone); $oPps->{Child} = \@aChildL; } else { $oPps->{Child} = undef; } #3. Previous,Next PPSs my @aList = (); push @aList, _getPpsTree($oPps->{PrevPps}, $rhInfo, $bData, $raDone) if($oPps->{PrevPps} != 0xFFFFFFFF); push @aList, $oPps; push @aList, _getPpsTree($oPps->{NextPps}, $rhInfo, $bData, $raDone) if($oPps->{NextPps} != 0xFFFFFFFF); return @aList; } #------------------------------------------------------------------------------ # _getPpsSearch: OLE::Storage_Lite #------------------------------------------------------------------------------ sub _getPpsSearch($$$$$;$) { my($iNo, $rhInfo, $raName, $bData, $iCase, $raDone) = @_; my $iRootBlock = $rhInfo->{_ROOT_START} ; my @aRes; #1. Check it self if(defined($raDone)) { return () if(grep {$_==$iNo} @$raDone); } else { $raDone=[]; } push @$raDone, $iNo; my $oPps = _getNthPps($iNo, $rhInfo, undef); # if(grep($_ eq $oPps->{Name}, @$raName)) { if(($iCase && (grep(/^\Q$oPps->{Name}\E$/i, @$raName))) || (grep($_ eq $oPps->{Name}, @$raName))) { $oPps = _getNthPps($iNo, $rhInfo, $bData) if ($bData); @aRes = ($oPps); } else { @aRes = (); } #2. Check Child, Previous, Next PPSs push @aRes, _getPpsSearch($oPps->{DirPps}, $rhInfo, $raName, $bData, $iCase, $raDone) if($oPps->{DirPps} != 0xFFFFFFFF) ; push @aRes, _getPpsSearch($oPps->{PrevPps}, $rhInfo, $raName, $bData, $iCase, $raDone) if($oPps->{PrevPps} != 0xFFFFFFFF ); push @aRes, _getPpsSearch($oPps->{NextPps}, $rhInfo, $raName, $bData, $iCase, $raDone) if($oPps->{NextPps} != 0xFFFFFFFF); return @aRes; } #=================================================================== # Get Header Info (BASE Informain about that file) #=================================================================== sub _getHeaderInfo($){ my($FILE) = @_; my($iWk); my $rhInfo = {}; $rhInfo->{_FILEH_} = $FILE; my $sWk; #0. Check ID $rhInfo->{_FILEH_}->seek(0, 0); $rhInfo->{_FILEH_}->read($sWk, 8); return undef unless($sWk eq "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1"); #BIG BLOCK SIZE $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x1E, 2, "v"); return undef unless(defined($iWk)); $rhInfo->{_BIG_BLOCK_SIZE} = 2 ** $iWk; #SMALL BLOCK SIZE $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x20, 2, "v"); return undef unless(defined($iWk)); $rhInfo->{_SMALL_BLOCK_SIZE} = 2 ** $iWk; #BDB Count $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x2C, 4, "V"); return undef unless(defined($iWk)); $rhInfo->{_BDB_COUNT} = $iWk; #START BLOCK $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x30, 4, "V"); return undef unless(defined($iWk)); $rhInfo->{_ROOT_START} = $iWk; #MIN SIZE OF BB # $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x38, 4, "V"); # return undef unless(defined($iWk)); # $rhInfo->{_MIN_SIZE_BB} = $iWk; #SMALL BD START $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x3C, 4, "V"); return undef unless(defined($iWk)); $rhInfo->{_SBD_START} = $iWk; #SMALL BD COUNT $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x40, 4, "V"); return undef unless(defined($iWk)); $rhInfo->{_SBD_COUNT} = $iWk; #EXTRA BBD START $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x44, 4, "V"); return undef unless(defined($iWk)); $rhInfo->{_EXTRA_BBD_START} = $iWk; #EXTRA BD COUNT $iWk = _getInfoFromFile($rhInfo->{_FILEH_}, 0x48, 4, "V"); return undef unless(defined($iWk)); $rhInfo->{_EXTRA_BBD_COUNT} = $iWk; #GET BBD INFO $rhInfo->{_BBD_INFO}= _getBbdInfo($rhInfo); #GET ROOT PPS my $oRoot = _getNthPps(0, $rhInfo, undef); $rhInfo->{_SB_START} = $oRoot->{StartBlock}; $rhInfo->{_SB_SIZE} = $oRoot->{Size}; return $rhInfo; } #------------------------------------------------------------------------------ # _getInfoFromFile #------------------------------------------------------------------------------ sub _getInfoFromFile($$$$) { my($FILE, $iPos, $iLen, $sFmt) =@_; my($sWk); return undef unless($FILE); return undef if($FILE->seek($iPos, 0)==0); return undef if($FILE->read($sWk, $iLen)!=$iLen); return unpack($sFmt, $sWk); } #------------------------------------------------------------------------------ # _getBbdInfo #------------------------------------------------------------------------------ sub _getBbdInfo($) { my($rhInfo) =@_; my @aBdList = (); my $iBdbCnt = $rhInfo->{_BDB_COUNT}; my $iGetCnt; my $sWk; my $i1stCnt = int(($rhInfo->{_BIG_BLOCK_SIZE} - 0x4C) / OLE::Storage_Lite::LongIntSize()); my $iBdlCnt = int($rhInfo->{_BIG_BLOCK_SIZE} / OLE::Storage_Lite::LongIntSize()) - 1; #1. 1st BDlist $rhInfo->{_FILEH_}->seek(0x4C, 0); $iGetCnt = ($iBdbCnt < $i1stCnt)? $iBdbCnt: $i1stCnt; $rhInfo->{_FILEH_}->read($sWk, OLE::Storage_Lite::LongIntSize()*$iGetCnt); push @aBdList, unpack("V$iGetCnt", $sWk); $iBdbCnt -= $iGetCnt; #2. Extra BDList my $iBlock = $rhInfo->{_EXTRA_BBD_START}; while(($iBdbCnt> 0) && _isNormalBlock($iBlock)){ _setFilePos($iBlock, 0, $rhInfo); $iGetCnt= ($iBdbCnt < $iBdlCnt)? $iBdbCnt: $iBdlCnt; $rhInfo->{_FILEH_}->read($sWk, OLE::Storage_Lite::LongIntSize()*$iGetCnt); push @aBdList, unpack("V$iGetCnt", $sWk); $iBdbCnt -= $iGetCnt; $rhInfo->{_FILEH_}->read($sWk, OLE::Storage_Lite::LongIntSize()); $iBlock = unpack("V", $sWk); } #3.Get BDs my @aWk; my %hBd; my $iBlkNo = 0; my $iBdL; my $i; my $iBdCnt = int($rhInfo->{_BIG_BLOCK_SIZE} / OLE::Storage_Lite::LongIntSize()); foreach $iBdL (@aBdList) { _setFilePos($iBdL, 0, $rhInfo); $rhInfo->{_FILEH_}->read($sWk, $rhInfo->{_BIG_BLOCK_SIZE}); @aWk = unpack("V$iBdCnt", $sWk); for($i=0;$i<$iBdCnt;$i++, $iBlkNo++) { if($aWk[$i] != ($iBlkNo+1)){ $hBd{$iBlkNo} = $aWk[$i]; } } } return \%hBd; } #------------------------------------------------------------------------------ # getNthPps (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getNthPps($$$){ my($iPos, $rhInfo, $bData) = @_; my($iPpsStart) = ($rhInfo->{_ROOT_START}); my($iPpsBlock, $iPpsPos); my $sWk; my $iBlock; my $iBaseCnt = $rhInfo->{_BIG_BLOCK_SIZE} / OLE::Storage_Lite::PpsSize(); $iPpsBlock = int($iPos / $iBaseCnt); $iPpsPos = $iPos % $iBaseCnt; $iBlock = _getNthBlockNo($iPpsStart, $iPpsBlock, $rhInfo); return undef unless(defined($iBlock)); _setFilePos($iBlock, OLE::Storage_Lite::PpsSize()*$iPpsPos, $rhInfo); $rhInfo->{_FILEH_}->read($sWk, OLE::Storage_Lite::PpsSize()); return undef unless($sWk); my $iNmSize = unpack("v", substr($sWk, 0x40, 2)); $iNmSize = ($iNmSize > 2)? $iNmSize - 2 : $iNmSize; my $sNm= substr($sWk, 0, $iNmSize); my $iType = unpack("C", substr($sWk, 0x42, 2)); my $lPpsPrev = unpack("V", substr($sWk, 0x44, OLE::Storage_Lite::LongIntSize())); my $lPpsNext = unpack("V", substr($sWk, 0x48, OLE::Storage_Lite::LongIntSize())); my $lDirPps = unpack("V", substr($sWk, 0x4C, OLE::Storage_Lite::LongIntSize())); my @raTime1st = (($iType == OLE::Storage_Lite::PpsType_Root()) or ($iType == OLE::Storage_Lite::PpsType_Dir()))? OLEDate2Local(substr($sWk, 0x64, 8)) : undef , my @raTime2nd = (($iType == OLE::Storage_Lite::PpsType_Root()) or ($iType == OLE::Storage_Lite::PpsType_Dir()))? OLEDate2Local(substr($sWk, 0x6C, 8)) : undef, my($iStart, $iSize) = unpack("VV", substr($sWk, 0x74, 8)); if($bData) { my $sData = _getData($iType, $iStart, $iSize, $rhInfo); return OLE::Storage_Lite::PPS->new( $iPos, $sNm, $iType, $lPpsPrev, $lPpsNext, $lDirPps, \@raTime1st, \@raTime2nd, $iStart, $iSize, $sData, undef); } else { return OLE::Storage_Lite::PPS->new( $iPos, $sNm, $iType, $lPpsPrev, $lPpsNext, $lDirPps, \@raTime1st, \@raTime2nd, $iStart, $iSize, undef, undef); } } #------------------------------------------------------------------------------ # _setFilePos (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _setFilePos($$$){ my($iBlock, $iPos, $rhInfo) = @_; $rhInfo->{_FILEH_}->seek(($iBlock+1)*$rhInfo->{_BIG_BLOCK_SIZE}+$iPos, 0); } #------------------------------------------------------------------------------ # _getNthBlockNo (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getNthBlockNo($$$){ my($iStBlock, $iNth, $rhInfo) = @_; my $iSv; my $iNext = $iStBlock; for(my $i =0; $i<$iNth; $i++) { $iSv = $iNext; $iNext = _getNextBlockNo($iSv, $rhInfo); return undef unless _isNormalBlock($iNext); } return $iNext; } #------------------------------------------------------------------------------ # _getData (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getData($$$$) { my($iType, $iBlock, $iSize, $rhInfo) = @_; if ($iType == OLE::Storage_Lite::PpsType_File()) { if($iSize < OLE::Storage_Lite::DataSizeSmall()) { return _getSmallData($iBlock, $iSize, $rhInfo); } else { return _getBigData($iBlock, $iSize, $rhInfo); } } elsif($iType == OLE::Storage_Lite::PpsType_Root()) { #Root return _getBigData($iBlock, $iSize, $rhInfo); } elsif($iType == OLE::Storage_Lite::PpsType_Dir()) { # Directory return undef; } } #------------------------------------------------------------------------------ # _getBigData (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getBigData($$$) { my($iBlock, $iSize, $rhInfo) = @_; my($iRest, $sWk, $sRes); return '' unless(_isNormalBlock($iBlock)); $iRest = $iSize; my($i, $iGetSize, $iNext); $sRes = ''; my @aKeys= sort({$a<=>$b} keys(%{$rhInfo->{_BBD_INFO}})); while ($iRest > 0) { my @aRes = grep($_ >= $iBlock, @aKeys); my $iNKey = $aRes[0]; $i = $iNKey - $iBlock; $iNext = $rhInfo->{_BBD_INFO}{$iNKey}; _setFilePos($iBlock, 0, $rhInfo); my $iGetSize = ($rhInfo->{_BIG_BLOCK_SIZE} * ($i+1)); $iGetSize = $iRest if($iRest < $iGetSize); $rhInfo->{_FILEH_}->read( $sWk, $iGetSize); $sRes .= $sWk; $iRest -= $iGetSize; $iBlock= $iNext; } return $sRes; } #------------------------------------------------------------------------------ # _getNextBlockNo (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getNextBlockNo($$){ my($iBlockNo, $rhInfo) = @_; my $iRes = $rhInfo->{_BBD_INFO}->{$iBlockNo}; return defined($iRes)? $iRes: $iBlockNo+1; } #------------------------------------------------------------------------------ # _isNormalBlock (OLE::Storage_Lite) # 0xFFFFFFFC : BDList, 0xFFFFFFFD : BBD, # 0xFFFFFFFE: End of Chain 0xFFFFFFFF : unused #------------------------------------------------------------------------------ sub _isNormalBlock($){ my($iBlock) = @_; return ($iBlock < 0xFFFFFFFC)? 1: undef; } #------------------------------------------------------------------------------ # _getSmallData (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getSmallData($$$) { my($iSmBlock, $iSize, $rhInfo) = @_; my($sRes, $sWk); my $iRest = $iSize; $sRes = ''; while ($iRest > 0) { _setFilePosSmall($iSmBlock, $rhInfo); $rhInfo->{_FILEH_}->read($sWk, ($iRest >= $rhInfo->{_SMALL_BLOCK_SIZE})? $rhInfo->{_SMALL_BLOCK_SIZE}: $iRest); $sRes .= $sWk; $iRest -= $rhInfo->{_SMALL_BLOCK_SIZE}; $iSmBlock= _getNextSmallBlockNo($iSmBlock, $rhInfo); } return $sRes; } #------------------------------------------------------------------------------ # _setFilePosSmall(OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _setFilePosSmall($$) { my($iSmBlock, $rhInfo) = @_; my $iSmStart = $rhInfo->{_SB_START}; my $iBaseCnt = $rhInfo->{_BIG_BLOCK_SIZE} / $rhInfo->{_SMALL_BLOCK_SIZE}; my $iNth = int($iSmBlock/$iBaseCnt); my $iPos = $iSmBlock % $iBaseCnt; my $iBlk = _getNthBlockNo($iSmStart, $iNth, $rhInfo); _setFilePos($iBlk, $iPos * $rhInfo->{_SMALL_BLOCK_SIZE}, $rhInfo); } #------------------------------------------------------------------------------ # _getNextSmallBlockNo (OLE::Storage_Lite) #------------------------------------------------------------------------------ sub _getNextSmallBlockNo($$) { my($iSmBlock, $rhInfo) = @_; my($sWk); my $iBaseCnt = $rhInfo->{_BIG_BLOCK_SIZE} / OLE::Storage_Lite::LongIntSize(); my $iNth = int($iSmBlock/$iBaseCnt); my $iPos = $iSmBlock % $iBaseCnt; my $iBlk = _getNthBlockNo($rhInfo->{_SBD_START}, $iNth, $rhInfo); _setFilePos($iBlk, $iPos * OLE::Storage_Lite::LongIntSize(), $rhInfo); $rhInfo->{_FILEH_}->read($sWk, OLE::Storage_Lite::LongIntSize()); return unpack("V", $sWk); } #------------------------------------------------------------------------------ # Asc2Ucs: OLE::Storage_Lite #------------------------------------------------------------------------------ sub Asc2Ucs($) { my($sAsc) = @_; return join("\x00", split //, $sAsc) . "\x00"; } #------------------------------------------------------------------------------ # Ucs2Asc: OLE::Storage_Lite #------------------------------------------------------------------------------ sub Ucs2Asc($) { my($sUcs) = @_; return join('', map(pack('c', $_), unpack('v*', $sUcs))); } #------------------------------------------------------------------------------ # OLEDate2Local() # # Convert from a Window FILETIME structure to a localtime array. FILETIME is # a 64-bit value representing the number of 100-nanosecond intervals since # January 1 1601. # # We first convert the FILETIME to seconds and then subtract the difference # between the 1601 epoch and the 1970 Unix epoch. # sub OLEDate2Local { my $oletime = shift; # Unpack the FILETIME into high and low longs. my ( $lo, $hi ) = unpack 'V2', $oletime; # Convert the longs to a double. my $nanoseconds = $hi * 2**32 + $lo; # Convert the 100 nanosecond units into seconds. my $time = $nanoseconds / 1e7; # Subtract the number of seconds between the 1601 and 1970 epochs. $time -= 11644473600; # Convert to a localtime (actually gmtime) structure. my @localtime = gmtime($time); return @localtime; } #------------------------------------------------------------------------------ # LocalDate2OLE() # # Convert from a a localtime array to a Window FILETIME structure. FILETIME is # a 64-bit value representing the number of 100-nanosecond intervals since # January 1 1601. # # We first convert the localtime (actually gmtime) to seconds and then add the # difference between the 1601 epoch and the 1970 Unix epoch. We convert that to # 100 nanosecond units, divide it into high and low longs and return it as a # packed 64bit structure. # sub LocalDate2OLE { my $localtime = shift; return "\x00" x 8 unless $localtime; # Convert from localtime (actually gmtime) to seconds. my $time = timegm( @{$localtime} ); # Add the number of seconds between the 1601 and 1970 epochs. $time += 11644473600; # The FILETIME seconds are in units of 100 nanoseconds. my $nanoseconds = $time * 1E7; use POSIX 'fmod'; # Pack the total nanoseconds into 64 bits... my $hi = int( $nanoseconds / 2**32 ); my $lo = fmod($nanoseconds, 2**32); my $oletime = pack "VV", $lo, $hi; return $oletime; } 1; __END__ =head1 NAME OLE::Storage_Lite - Simple Class for OLE document interface. =head1 SYNOPSIS use OLE::Storage_Lite; # Initialize. # From a file my $oOl = OLE::Storage_Lite->new("some.xls"); # From a filehandle object use IO::File; my $oIo = new IO::File; $oIo->open("new($oFile); # Read data my $oPps = $oOl->getPpsTree(1); # Save Data # To a File $oPps->save("kaba.xls"); #kaba.xls $oPps->save('-'); #STDOUT # To a filehandle object my $oIo = new IO::File; $oIo->open(">iofile.xls"); bimode($oIo); $oPps->save($oIo); =head1 DESCRIPTION OLE::Storage_Lite allows you to read and write an OLE structured file. OLE::Storage_Lite::PPS is a class representing PPS. OLE::Storage_Lite::PPS::Root, OLE::Storage_Lite::PPS::File and OLE::Storage_Lite::PPS::Dir are subclasses of OLE::Storage_Lite::PPS. =head2 new() Constructor. $oOle = OLE::Storage_Lite->new($sFile); Creates a OLE::Storage_Lite object for C<$sFile>. C<$sFile> must be a correct file name. The C constructor also accepts a valid filehandle. Remember to C the filehandle first. =head2 getPpsTree() $oPpsRoot = $oOle->getPpsTree([$bData]); Returns PPS as an OLE::Storage_Lite::PPS::Root object. Other PPS objects will be included as its children. If C<$bData> is true, the objects will have data in the file. =head2 getPpsSearch() $oPpsRoot = $oOle->getPpsTree($raName [, $bData][, $iCase] ); Returns PPSs as OLE::Storage_Lite::PPS objects that has the name specified in C<$raName> array. If C<$bData> is true, the objects will have data in the file. If C<$iCase> is true, search is case insensitive. =head2 getNthPps() $oPpsRoot = $oOle->getNthPps($iNth [, $bData]); Returns PPS as C object specified number C<$iNth>. If C<$bData> is true, the objects will have data in the file. =head2 Asc2Ucs() $sUcs2 = OLE::Storage_Lite::Asc2Ucs($sAsc>); Utility function. Just adds 0x00 after every characters in C<$sAsc>. =head2 Ucs2Asc() $sAsc = OLE::Storage_Lite::Ucs2Asc($sUcs2); Utility function. Just deletes 0x00 after words in C<$sUcs>. =head1 OLE::Storage_Lite::PPS OLE::Storage_Lite::PPS has these properties: =over 4 =item No Order number in saving. =item Name Its name in UCS2 (a.k.a Unicode). =item Type Its type (1:Dir, 2:File (Data), 5: Root) =item PrevPps Previous pps (as No) =item NextPps Next pps (as No) =item DirPps Dir pps (as No). =item Time1st Timestamp 1st in array ref as similar fomat of localtime. =item Time2nd Timestamp 2nd in array ref as similar fomat of localtime. =item StartBlock Start block number =item Size Size of the pps =item Data Its data =item Child Its child PPSs in array ref =back =head1 OLE::Storage_Lite::PPS::Root OLE::Storage_Lite::PPS::Root has 2 methods. =head2 new() $oRoot = OLE::Storage_Lite::PPS::Root->new( $raTime1st, $raTime2nd, $raChild); Constructor. C<$raTime1st>, C<$raTime2nd> are array refs with ($iSec, $iMin, $iHour, $iDay, $iMon, $iYear). $iSec means seconds, $iMin means minutes. $iHour means hours. $iDay means day. $iMon is month -1. $iYear is year - 1900. C<$raChild> is a array ref of children PPSs. =head2 save() $oRoot = $oRoot>->save( $sFile, $bNoAs); Saves information into C<$sFile>. If C<$sFile> is '-', this will use STDOUT. The C constructor also accepts a valid filehandle. Remember to C the filehandle first. If C<$bNoAs> is defined, this function will use the No of PPSs for saving order. If C<$bNoAs> is undefined, this will calculate PPS saving order. =head1 OLE::Storage_Lite::PPS::Dir OLE::Storage_Lite::PPS::Dir has 1 method. =head2 new() $oRoot = OLE::Storage_Lite::PPS::Dir->new( $sName, [, $raTime1st] [, $raTime2nd] [, $raChild>]); Constructor. C<$sName> is a name of the PPS. C<$raTime1st>, C<$raTime2nd> is a array ref as ($iSec, $iMin, $iHour, $iDay, $iMon, $iYear). $iSec means seconds, $iMin means minutes. $iHour means hours. $iDay means day. $iMon is month -1. $iYear is year - 1900. C<$raChild> is a array ref of children PPSs. =head1 OLE::Storage_Lite::PPS::File OLE::Storage_Lite::PPS::File has 3 method. =head2 new $oRoot = OLE::Storage_Lite::PPS::File->new($sName, $sData); C<$sName> is name of the PPS. C<$sData> is data of the PPS. =head2 newFile() $oRoot = OLE::Storage_Lite::PPS::File->newFile($sName, $sFile); This function makes to use file handle for geting and storing data. C<$sName> is name of the PPS. If C<$sFile> is scalar, it assumes that is a filename. If C<$sFile> is an IO::Handle object, it uses that specified handle. If C<$sFile> is undef or '', it uses temporary file. CAUTION: Take care C<$sFile> will be updated by C method. So if you want to use IO::Handle and append a data to it, you should open the handle with "r+". =head2 append() $oRoot = $oPps->append($sData); appends specified data to that PPS. C<$sData> is appending data for that PPS. =head1 CAUTION A saved file with VBA (a.k.a Macros) by this module will not work correctly. However modules can get the same information from the file, the file occurs a error in application(Word, Excel ...). =head1 DEPRECATED FEATURES Older version of C autovivified a scalar ref in the C constructors into a scalar filehandle. This functionality is still there for backwards compatibility but it is highly recommended that you do not use it. Instead create a filehandle (scalar or otherwise) and pass that in. =head1 COPYRIGHT The OLE::Storage_Lite module is Copyright (c) 2000,2001 Kawai Takanori. Japan. All rights reserved. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file. =head1 ACKNOWLEDGEMENTS First of all, I would like to acknowledge to Martin Schwartz and his module OLE::Storage. =head1 AUTHOR Kawai Takanori kwitknr@cpan.org This module is currently maintained by John McNamara jmcnamara@cpan.org =head1 SEE ALSO OLE::Storage Documentation for the OLE Compound document has been released by Microsoft under the I. See http://www.microsoft.com/interop/docs/supportingtechnologies.mspx The Digital Imaging Group have also detailed the OLE format in the JPEG2000 specification: see Appendix A of http://www.i3a.org/pdf/wg1n1017.pdf =cut gdata/inst/perl/OLE/README-OLE-Storage_Lite0000644000176000001440000000167311326735243017611 0ustar ripleyusersNAME OLE::Storage_Lite - Simple Class for OLE document interface. DESCRIPTION This module allows you to read and write an OLE-Structured file. The module will work on the majority of Windows, UNIX and Macintosh platforms. REQUIREMENT Perl 5.005 or later. INSTALLATION The module can be installed using the standard Perl procedure: perl Makefile.PL make make test make install # You may need to be root make clean # or make realclean Windows users without a working "make" can get nmake from: ftp://ftp.microsoft.com/Softlib/MSLFILES/nmake15.exe SAMPLE Samples scripts are in sample directory. smplls.pl : displays PPS structure of specified file (subset of "lls" distributed with OLE::Storage) smpsv.pl : creates and save a sample OLE-file(tsv.dat). AUTHOR Kawai Takanori (kwitknr@cpan.org) gdata/inst/perl/IO/0000755000176000001440000000000012024144455013611 5ustar ripleyusersgdata/inst/perl/IO/WrapTie.pm0000644000176000001440000003464511326376512015543 0ustar ripleyusers# SEE DOCUMENTATION AT BOTTOM OF FILE #------------------------------------------------------------ package IO::WrapTie; #------------------------------------------------------------ require 5.004; ### for tie use strict; use vars qw(@ISA @EXPORT $VERSION); use Exporter; # Inheritance, exporting, and package version: @ISA = qw(Exporter); @EXPORT = qw(wraptie); $VERSION = "2.110"; # Function, exported. sub wraptie { IO::WrapTie::Master->new(@_); } # Class method; BACKWARDS-COMPATIBILITY ONLY! sub new { shift; IO::WrapTie::Master->new(@_); } #------------------------------------------------------------ package IO::WrapTie::Master; #------------------------------------------------------------ use strict; use vars qw(@ISA $AUTOLOAD); use IO::Handle; # We inherit from IO::Handle to get methods which invoke i/o operators, # like print(), on our tied handle: @ISA = qw(IO::Handle); #------------------------------ # new SLAVE, TIEARGS... #------------------------------ # Create a new subclass of IO::Handle which... # # (1) Handles i/o OPERATORS because it is tied to an instance of # an i/o-like class, like IO::Scalar. # # (2) Handles i/o METHODS by delegating them to that same tied object!. # # Arguments are the slave class (e.g., IO::Scalar), followed by all # the arguments normally sent into that class's TIEHANDLE method. # In other words, much like the arguments to tie(). :-) # # NOTE: # The thing $x we return must be a BLESSED REF, for ($x->print()). # The underlying symbol must be a FILEHANDLE, for (print $x "foo"). # It has to have a way of getting to the "real" back-end object... # sub new { my $master = shift; my $io = IO::Handle->new; ### create a new handle my $slave = shift; tie *$io, $slave, @_; ### tie: will invoke slave's TIEHANDLE bless $io, $master; ### return a master } #------------------------------ # AUTOLOAD #------------------------------ # Delegate method invocations on the master to the underlying slave. # sub AUTOLOAD { my $method = $AUTOLOAD; $method =~ s/.*:://; my $self = shift; tied(*$self)->$method(\@_); } #------------------------------ # PRELOAD #------------------------------ # Utility. # # Most methods like print(), getline(), etc. which work on the tied object # via Perl's i/o operators (like 'print') are inherited from IO::Handle. # # Other methods, like seek() and sref(), we must delegate ourselves. # AUTOLOAD takes care of these. # # However, it may be necessary to preload delegators into your # own class. PRELOAD will do this. # sub PRELOAD { my $class = shift; foreach (@_) { eval "sub ${class}::$_ { my \$s = shift; tied(*\$s)->$_(\@_) }"; } } # Preload delegators for some standard methods which we can't simply # inherit from IO::Handle... for example, some IO::Handle methods # assume that there is an underlying file descriptor. # PRELOAD IO::WrapTie::Master qw(open opened close read clearerr eof seek tell setpos getpos); #------------------------------------------------------------ package IO::WrapTie::Slave; #------------------------------------------------------------ # Teeny private class providing a new_tie constructor... # # HOW IT ALL WORKS: # # Slaves inherit from this class. # # When you send a new_tie() message to a tie-slave class (like IO::Scalar), # it first determines what class should provide its master, via TIE_MASTER. # In this case, IO::Scalar->TIE_MASTER would return IO::Scalar::Master. # Then, we create a new master (an IO::Scalar::Master) with the same args # sent to new_tie. # # In general, the new() method of the master is inherited directly # from IO::WrapTie::Master. # sub new_tie { my $self = shift; $self->TIE_MASTER->new($self,@_); ### e.g., IO::Scalar::Master->new(@_) } # Default class method for new_tie(). # All your tie-slave class (like IO::Scalar) has to do is override this # method with a method that returns the name of an appropriate "master" # class for tying that slave. # sub TIE_MASTER { 'IO::WrapTie::Master' } #------------------------------ 1; __END__ package IO::WrapTie; ### for doc generator =head1 NAME IO::WrapTie - wrap tieable objects in IO::Handle interface I =head1 SYNOPSIS First of all, you'll need tie(), so: require 5.004; I Use this with any existing class... use IO::WrapTie; use FooHandle; ### implements TIEHANDLE interface ### Suppose we want a "FooHandle->new(&FOO_RDWR, 2)". ### We can instead say... $FH = wraptie('FooHandle', &FOO_RDWR, 2); ### Now we can use... print $FH "Hello, "; ### traditional operator syntax... $FH->print("world!\n"); ### ...and OO syntax as well! I You can inherit from the IO::WrapTie::Slave mixin to get a nifty C constructor... #------------------------------ package FooHandle; ### a class which can TIEHANDLE use IO::WrapTie; @ISA = qw(IO::WrapTie::Slave); ### inherit new_tie() ... #------------------------------ package main; $FH = FooHandle->new_tie(&FOO_RDWR, 2); ### $FH is an IO::WrapTie::Master print $FH "Hello, "; ### traditional operator syntax $FH->print("world!\n"); ### OO syntax See IO::Scalar as an example. It also shows you how to create classes which work both with and without 5.004. =head1 DESCRIPTION Suppose you have a class C, where... =over 4 =item * B that is, it performs filehandle-like I/O, but to something other than an underlying file descriptor. Good examples are IO::Scalar (for printing to a string) and IO::Lines (for printing to an array of lines). =item * B (see L); that is, it provides methods TIEHANDLE, GETC, PRINT, PRINTF, READ, and READLINE. =item * B of FileHandle and IO::Handle; i.e., it contains methods like getline(), read(), print(), seek(), tell(), eof(), etc. =back Normally, users of your class would have two options: =over 4 =item * B and forsake named I/O operators like 'print'. =item * B and forsake treating it as a first-class object (i.e., class-specific methods can only be invoked through the underlying object via tied()... giving the object a "split personality"). =back But now with IO::WrapTie, you can say: $WT = wraptie('FooHandle', &FOO_RDWR, 2); $WT->print("Hello, world\n"); ### OO syntax print $WT "Yes!\n"; ### Named operator syntax too! $WT->weird_stuff; ### Other methods! And if you're authoring a class like FooHandle, just have it inherit from C and that first line becomes even prettier: $WT = FooHandle->new_tie(&FOO_RDWR, 2); B now, almost any class can look and work exactly like an IO::Handle... and be used both with OO and non-OO filehandle syntax. =head1 HOW IT ALL WORKS =head2 The data structures Consider this example code, using classes in this distribution: use IO::Scalar; use IO::WrapTie; $WT = wraptie('IO::Scalar',\$s); print $WT "Hello, "; $WT->print("world!\n"); In it, the wraptie() function creates a data structure as follows: * $WT is a blessed reference to a tied filehandle $WT glob; that glob is tied to the "Slave" object. | * You would do all your i/o with $WT directly. | | | ,---isa--> IO::WrapTie::Master >--isa--> IO::Handle V / .-------------. | | | | * Perl i/o operators work on the tied object, | "Master" | invoking the TIEHANDLE methods. | | * Method invocations are delegated to the tied | | slave. `-------------' | tied(*$WT) | .---isa--> IO::WrapTie::Slave V / .-------------. | | | "Slave" | * Instance of FileHandle-like class which doesn't | | actually use file descriptors, like IO::Scalar. | IO::Scalar | * The slave can be any kind of object. | | * Must implement the TIEHANDLE interface. `-------------' I just as an IO::Handle is really just a blessed reference to a I filehandle glob... so also, an IO::WrapTie::Master is really just a blessed reference to a filehandle glob I =head2 How wraptie() works =over 4 =item 1. The call to function C is passed onto C. Note that class IO::WrapTie::Master is a subclass of IO::Handle. =item 2. The C method creates a new IO::Handle object, reblessed into class IO::WrapTie::Master. This object is the I, which will be returned from the constructor. At the same time... =item 3. The C method also creates the I: this is an instance of SLAVECLASS which is created by tying the master's IO::Handle to SLAVECLASS via C. This call to C creates the slave in the following manner: =item 4. Class SLAVECLASS is sent the message C; it will usually delegate this to C, resulting in a new instance of SLAVECLASS being created and returned. =item 5. Once both master and slave have been created, the master is returned to the caller. =back =head2 How I/O operators work (on the master) Consider using an i/o operator on the master: print $WT "Hello, world!\n"; Since the master ($WT) is really a [blessed] reference to a glob, the normal Perl i/o operators like C may be used on it. They will just operate on the symbol part of the glob. Since the glob is tied to the slave, the slave's PRINT method (part of the TIEHANDLE interface) will be automatically invoked. If the slave is an IO::Scalar, that means IO::Scalar::PRINT will be invoked, and that method happens to delegate to the C method of the same class. So the I work is ultimately done by IO::Scalar::print(). =head2 How methods work (on the master) Consider using a method on the master: $WT->print("Hello, world!\n"); Since the master ($WT) is blessed into the class IO::WrapTie::Master, Perl first attempts to find a C method there. Failing that, Perl next attempts to find a C method in the superclass, IO::Handle. It just so happens that there I such a method; that method merely invokes the C i/o operator on the self object... and for that, see above! But let's suppose we're dealing with a method which I part of IO::Handle... for example: my $sref = $WT->sref; In this case, the intuitive behavior is to have the master delegate the method invocation to the slave (now do you see where the designations come from?). This is indeed what happens: IO::WrapTie::Master contains an AUTOLOAD method which performs the delegation. So: when C can't be found in IO::Handle, the AUTOLOAD method of IO::WrapTie::Master is invoked, and the standard behavior of delegating the method to the underlying slave (here, an IO::Scalar) is done. Sometimes, to get this to work properly, you may need to create a subclass of IO::WrapTie::Master which is an effective master for I class, and do the delegation there. =head1 NOTES B Because that means forsaking the use of named operators like print(), and you may need to pass the object to a subroutine which will attempt to use those operators: $O = FooHandle->new(&FOO_RDWR, 2); $O->print("Hello, world\n"); ### OO syntax is okay, BUT.... sub nope { print $_[0] "Nope!\n" } X nope($O); ### ERROR!!! (not a glob ref) B Because (1) you have to use tied() to invoke methods in the object's public interface (yuck), and (2) you may need to pass the tied symbol to another subroutine which will attempt to treat it in an OO-way... and that will break it: tie *T, 'FooHandle', &FOO_RDWR, 2; print T "Hello, world\n"; ### Operator is okay, BUT... tied(*T)->other_stuff; ### yuck! AND... sub nope { shift->print("Nope!\n") } X nope(\*T); ### ERROR!!! (method "print" on unblessed ref) B I tried this, with an implementation similar to that of IO::Socket. The problem is that I. Subclassing IO::Handle will work fine for the OO stuff, and fine with named operators I you tie()... but if you just attempt to say: $IO = FooHandle->new(&FOO_RDWR, 2); print $IO "Hello!\n"; you get a warning from Perl like: Filehandle GEN001 never opened because it's trying to do system-level i/o on an (unopened) file descriptor. To avoid this, you apparently have to tie() the handle... which brings us right back to where we started! At least the IO::WrapTie mixin lets us say: $IO = FooHandle->new_tie(&FOO_RDWR, 2); print $IO "Hello!\n"; and so is not I bad. C<:-)> =head1 WARNINGS Remember: this stuff is for doing FileHandle-like i/o on things I. If you have an underlying file descriptor, you're better off just inheriting from IO::Handle. B it does B return an instance of the i/o class you're tying to! Invoking some methods on the master object causes AUTOLOAD to delegate them to the slave object... so it I like you're manipulating a "FooHandle" object directly, but you're not. I have not explored all the ramifications of this use of tie(). I. =head1 VERSION $Id: WrapTie.pm,v 1.2 2005/02/10 21:21:53 dfs Exp $ =head1 AUTHOR =item Primary Maintainer David F. Skoll (F). =item Original Author Eryq (F). President, ZeeGee Software Inc (F). =cut gdata/inst/perl/IO/Wrap.pm0000644000176000001440000001162311326376512015070 0ustar ripleyuserspackage IO::Wrap; # SEE DOCUMENTATION AT BOTTOM OF FILE require 5.002; use strict; use vars qw(@ISA @EXPORT $VERSION); @ISA = qw(Exporter); @EXPORT = qw(wraphandle); use FileHandle; use Carp; # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "2.110"; #------------------------------ # wraphandle RAW #------------------------------ sub wraphandle { my $raw = shift; new IO::Wrap $raw; } #------------------------------ # new STREAM #------------------------------ sub new { my ($class, $stream) = @_; no strict 'refs'; ### Convert raw scalar to globref: ref($stream) or $stream = \*$stream; ### Wrap globref and incomplete objects: if ((ref($stream) eq 'GLOB') or ### globref (ref($stream) eq 'FileHandle') && !defined(&FileHandle::read)) { return bless \$stream, $class; } $stream; ### already okay! } #------------------------------ # I/O methods... #------------------------------ sub close { my $self = shift; return close($$self); } sub getline { my $self = shift; my $fh = $$self; return scalar(<$fh>); } sub getlines { my $self = shift; wantarray or croak("Can't call getlines in scalar context!"); my $fh = $$self; <$fh>; } sub print { my $self = shift; print { $$self } @_; } sub read { my $self = shift; return read($$self, $_[0], $_[1]); } sub seek { my $self = shift; return seek($$self, $_[0], $_[1]); } sub tell { my $self = shift; return tell($$self); } #------------------------------ 1; __END__ =head1 NAME IO::Wrap - wrap raw filehandles in IO::Handle interface =head1 SYNOPSIS use IO::Wrap; ### Do stuff with any kind of filehandle (including a bare globref), or ### any kind of blessed object that responds to a print() message. ### sub do_stuff { my $fh = shift; ### At this point, we have no idea what the user gave us... ### a globref? a FileHandle? a scalar filehandle name? $fh = wraphandle($fh); ### At this point, we know we have an IO::Handle-like object! $fh->print("Hey there!"); ... } =head1 DESCRIPTION Let's say you want to write some code which does I/O, but you don't want to force the caller to provide you with a FileHandle or IO::Handle object. You want them to be able to say: do_stuff(\*STDOUT); do_stuff('STDERR'); do_stuff($some_FileHandle_object); do_stuff($some_IO_Handle_object); And even: do_stuff($any_object_with_a_print_method); Sure, one way to do it is to force the caller to use tiehandle(). But that puts the burden on them. Another way to do it is to use B, which provides you with the following functions: =over 4 =item wraphandle SCALAR This function will take a single argument, and "wrap" it based on what it seems to be... =over 4 =item * B like C<"STDOUT"> or C<"Class::HANDLE">. In this case, the filehandle name is wrapped in an IO::Wrap object, which is returned. =item * B like C<\*STDOUT>. In this case, the filehandle glob is wrapped in an IO::Wrap object, which is returned. =item * B In this case, the FileHandle is wrapped in an IO::Wrap object if and only if your FileHandle class does not support the C method. =item * B which is assumed to be already conformant to the IO::Handle interface. In this case, you just get back that object. =back =back If you get back an IO::Wrap object, it will obey a basic subset of the IO:: interface. That is, the following methods (note: I said I, not named operators) should work on the thing you get back: close getline getlines print ARGS... read BUFFER,NBYTES seek POS,WHENCE tell =head1 NOTES Clearly, when wrapping a raw external filehandle (like \*STDOUT), I didn't want to close the file descriptor when the "wrapper" object is destroyed... since the user might not appreciate that! Hence, there's no DESTROY method in this class. When wrapping a FileHandle object, however, I believe that Perl will invoke the FileHandle::DESTROY when the last reference goes away, so in that case, the filehandle is closed if the wrapped FileHandle really was the last reference to it. =head1 WARNINGS This module does not allow you to wrap filehandle names which are given as strings that lack the package they were opened in. That is, if a user opens FOO in package Foo, they must pass it to you either as C<\*FOO> or as C<"Foo::FOO">. However, C<"STDIN"> and friends will work just fine. =head1 VERSION $Id: Wrap.pm,v 1.2 2005/02/10 21:21:53 dfs Exp $ =head1 AUTHOR =item Primary Maintainer David F. Skoll (F). =item Original Author Eryq (F). President, ZeeGee Software Inc (F). =cut gdata/inst/perl/IO/Stringy.pm0000644000176000001440000002751111326376512015621 0ustar ripleyuserspackage IO::Stringy; use vars qw($VERSION); $VERSION = "2.110"; 1; __END__ =head1 NAME IO-stringy - I/O on in-core objects like strings and arrays =head1 SYNOPSIS IO:: ::AtomicFile adpO Write a file which is updated atomically ERYQ ::Lines bdpO I/O handle to read/write to array of lines ERYQ ::Scalar RdpO I/O handle to read/write to a string ERYQ ::ScalarArray RdpO I/O handle to read/write to array of scalars ERYQ ::Wrap RdpO Wrap old-style FHs in standard OO interface ERYQ ::WrapTie adpO Tie your handles & retain full OO interface ERYQ =head1 DESCRIPTION This toolkit primarily provides modules for performing both traditional and object-oriented i/o) on things I than normal filehandles; in particular, L, L, and L. In the more-traditional IO::Handle front, we have L which may be used to painlessly create files which are updated atomically. And in the "this-may-prove-useful" corner, we have L, whose exported wraphandle() function will clothe anything that's not a blessed object in an IO::Handle-like wrapper... so you can just use OO syntax and stop worrying about whether your function's caller handed you a string, a globref, or a FileHandle. =head1 WARNINGS Perl's TIEHANDLE spec was incomplete prior to 5.005_57; it was missing support for C, C, and C. Attempting to use these functions with an IO::Scalar, IO::ScalarArray, IO::Lines, etc. B prior to 5.005_57. None of the relevant methods will be invoked by Perl; and even worse, this kind of bug can lie dormant for a while. If you turn warnings on (via C<$^W> or C), and you see something like this... seek() on unopened file ...then you are probably trying to use one of these functions on one of our IO:: classes with an old Perl. The remedy is to simply use the OO version; e.g.: $SH->seek(0,0); ### GOOD: will work on any 5.005 seek($SH,0,0); ### WARNING: will only work on 5.005_57 and beyond =head1 INSTALLATION =head2 Requirements As of version 2.x, this toolkit requires Perl 5.005 for the IO::Handle subclasses, and 5.005_57 or better is B recommended. See L<"WARNINGS"> for details. =head2 Directions Most of you already know the drill... perl Makefile.PL make make test make install For everyone else out there... if you've never installed Perl code before, or you're trying to use this in an environment where your sysadmin or ISP won't let you do interesting things, B since this module contains no binary extensions, you can cheat. That means copying the directory tree under my "./lib" directory into someplace where your script can "see" it. For example, under Linux: cp -r IO-stringy-1.234/lib/* /path/to/my/perl/ Now, in your Perl code, do this: use lib "/path/to/my/perl"; use IO::Scalar; ### or whatever Ok, now you've been told. At this point, anyone who whines about not being given enough information gets an unflattering haiku written about them in the next change log. I'll do it. Don't think I won't. =head1 VERSION $Id: Stringy.pm,v 1.3 2005/02/10 21:24:05 dfs Exp $ =head1 TO DO =over 4 =item (2000/08/02) Finalize $/ support Graham Barr submitted this patch half a I ago; Like a moron, I lost his message under a ton of others, and only now have the experimental implementation done. Will the sudden sensitivity to $/ hose anyone out there? I'm worried, so you have to enable it explicitly in 1.x. It will be on by default in 2.x, though only IO::Scalar has been implemented. =item (2001/08/08) Remove IO::WrapTie from new IO:: classes It's not needed. Backwards compatibility could be maintained by having new_tie() be identical to new(). Heck, I'll bet that IO::WrapTie should be reimplemented so the returned object is just like an IO::Scalar in its use of globrefs. =back =head1 CHANGE LOG =over 4 =item Version 2.110 (2005/02/10) Maintainership taken over by DSKOLL Closed the following bugs at https://rt.cpan.org/NoAuth/Bugs.html?Dist=IO-stringy: =item 2208 IO::ScalarArray->getline does not return undef for EOF if undef($/) =item 7132 IO-stringy/Makefile.PL bug - name should be module name =item 11249 IO::Scalar flush shouldn't return undef =item 2172 $\ (output record separator) not respected =item 8605 IO::InnerFile::seek() should return 1 on success =item 4798 *.html in lib/ =item 4369 Improvement: handling of fixed-size reads in IO::Scalar (Actually, bug 4369 was closed in Version 2.109) =item Version 2.109 (2003/12/21) IO::Scalar::getline now works with ref to int. I =item Version 2.108 (2001/08/20) The terms-of-use have been placed in the distribution file "COPYING". Also, small documentation tweaks were made. =item Version 2.105 (2001/08/09) Added support for various seek() whences to IO::ScalarArray. Added support for consulting $/ in IO::Scalar and IO::ScalarArray. The old C is not even an option. Unsupported record separators will cause a croak(). Added a lot of regression tests to supoprt the above. Better on-line docs (hyperlinks to individual functions). =item Version 2.103 (2001/08/08) After sober consideration I have reimplemented IO::Scalar::print() so that it once again always seeks to the end of the string. Benchmarks show the new implementation to be just as fast as Juergen's contributed patch; until someone can convince me otherwise, the current, safer implementation stays. I thought more about giving IO::Scalar two separate handles, one for reading and one for writing, as suggested by Binkley. His points about what tell() and eof() return are, I think, show-stoppers for this feature. Even the manpages for stdio's fseek() seem to imply a I file position indicator, not two. So I think I will take this off the TO DO list. B you can always have two handles open on the same scalar, one which you only write to, and one which you only read from. That should give the same effect. =item Version 2.101 (2001/08/07) B This is the initial release of the "IO::Scalar and friends are now subclasses of IO::Handle". I'm flinging it against the wall. Please tell me if the banana sticks. When it does, the banana will be called 2.2x. First off, I, who has provided an I service by patching IO::Scalar and friends so that they (1) inherit from IO::Handle, (2) automatically tie themselves so that the C objects can be used in native i/o constructs, and (3) doing it so that the whole damn thing passes its regression tests. As Doug knows, my globref Kung-Fu was not up to the task; he graciously provided the patches. This has earned him a seat at the L table, and the right to have me address him as I. Performance of IO::Scalar::print() has been improved by as much as 2x for lots of little prints, with the cost of forcing those who print-then-seek-then-print to explicitly seek to end-of-string before printing again. I Added the COPYING file, which had been missing from prior versions. I IO::Scalar consults $/ by default (1.x ignored it by default). Yes, I still need to support IO::ScalarArray. =item Version 1.221 (2001/08/07) I threatened in L<"INSTALLATION"> to write an unflattering haiku about anyone who whined that I gave them insufficient information... but it turns out that I left out a crucial direction. D'OH! I Enough info there? Here's unflattering haiku: Forgot the line, "make"! ;-) =item Version 1.220 (2001/04/03) Added untested SEEK, TELL, and EOF methods to IO::Scalar and IO::ScalarArray to support corresponding functions for tied filehandles: untested, because I'm still running 5.00556 and Perl is complaining about "tell() on unopened file". I Removed not-fully-blank lines from modules; these were causing lots of POD-related warnings. I =item Version 1.219 (2001/02/23) IO::Scalar objects can now be made sensitive to $/ . Pains were taken to keep the fast code fast while adding this feature. I =item Version 1.218 (2001/02/23) IO::Scalar has a new sysseek() method. I New "TO DO" section, because people who submit patches/ideas should at least know that they're in the system... and that I won't lose their stuff. Please read it. New entries in L<"AUTHOR">. Please read those too. =item Version 1.216 (2000/09/28) B I thought I'd remembered a problem with this ages ago, related to the fact that these IO:: modules don't have "real" filehandles, but the problem apparently isn't surfacing now. If you suddenly encounter Perl warnings during global destruction (especially if you're using tied filehandles), then please let me know! I B Apparently, the offset and the number-of-bytes arguments were, for all practical purposes, I You were okay if you did all your writing with print(), but boy was I a stupid bug! I Newspaper headline typeset by dyslexic man loses urgency BABY EATS FISH is simply not equivalent to FISH EATS BABY B I =item Version 1.215 (2000/09/05) Added 'bool' overload to '""' overload, so object always evaluates to true. (Whew. Glad I caught this before it went to CPAN.) =item Version 1.214 (2000/09/03) Evaluating an IO::Scalar in a string context now yields the underlying string. I =item Version 1.213 (2000/08/16) Minor documentation fixes. =item Version 1.212 (2000/06/02) Fixed IO::InnerFile incompatibility with Perl5.004. I =item Version 1.210 (2000/04/17) Added flush() and other no-op methods. I =item Version 1.209 (2000/03/17) Small bug fixes. =item Version 1.208 (2000/03/14) Incorporated a number of contributed patches and extensions, mostly related to speed hacks, support for "offset", and WRITE/CLOSE methods. I =item Version 1.206 (1999/04/18) Added creation of ./testout when Makefile.PL is run. =item Version 1.205 (1999/01/15) Verified for Perl5.005. =item Version 1.202 (1998/04/18) New IO::WrapTie and IO::AtomicFile added. =item Version 1.110 Added IO::WrapTie. =item Version 1.107 Added IO::Lines, and made some bug fixes to IO::ScalarArray. Also, added getc(). =item Version 1.105 No real changes; just upgraded IO::Wrap to have a $VERSION string. =back =head1 AUTHOR =over 4 =item Primary Maintainer David F. Skoll (F). =item Original Author Eryq (F). President, ZeeGee Software Inc (F). =item Co-Authors For all their bug reports and patch submissions, the following are officially recognized: Richard Jones B. K. Oxley (binkley) Doru Petrescu Doug Wilson (for picking up the ball I dropped, and doing tie() right) =back Go to F for the latest downloads and on-line documentation for this module. Enjoy. Yell if it breaks. =cut gdata/inst/perl/IO/ScalarArray.pm0000644000176000001440000004226511326376512016371 0ustar ripleyuserspackage IO::ScalarArray; =head1 NAME IO::ScalarArray - IO:: interface for reading/writing an array of scalars =head1 SYNOPSIS Perform I/O on strings, using the basic OO interface... use IO::ScalarArray; @data = ("My mes", "sage:\n"); ### Open a handle on an array, and append to it: $AH = new IO::ScalarArray \@data; $AH->print("Hello"); $AH->print(", world!\nBye now!\n"); print "The array is now: ", @data, "\n"; ### Open a handle on an array, read it line-by-line, then close it: $AH = new IO::ScalarArray \@data; while (defined($_ = $AH->getline)) { print "Got line: $_"; } $AH->close; ### Open a handle on an array, and slurp in all the lines: $AH = new IO::ScalarArray \@data; print "All lines:\n", $AH->getlines; ### Get the current position (either of two ways): $pos = $AH->getpos; $offset = $AH->tell; ### Set the current position (either of two ways): $AH->setpos($pos); $AH->seek($offset, 0); ### Open an anonymous temporary array: $AH = new IO::ScalarArray; $AH->print("Hi there!"); print "I printed: ", @{$AH->aref}, "\n"; ### get at value Don't like OO for your I/O? No problem. Thanks to the magic of an invisible tie(), the following now works out of the box, just as it does with IO::Handle: use IO::ScalarArray; @data = ("My mes", "sage:\n"); ### Open a handle on an array, and append to it: $AH = new IO::ScalarArray \@data; print $AH "Hello"; print $AH ", world!\nBye now!\n"; print "The array is now: ", @data, "\n"; ### Open a handle on a string, read it line-by-line, then close it: $AH = new IO::ScalarArray \@data; while (<$AH>) { print "Got line: $_"; } close $AH; ### Open a handle on a string, and slurp in all the lines: $AH = new IO::ScalarArray \@data; print "All lines:\n", <$AH>; ### Get the current position (WARNING: requires 5.6): $offset = tell $AH; ### Set the current position (WARNING: requires 5.6): seek $AH, $offset, 0; ### Open an anonymous temporary scalar: $AH = new IO::ScalarArray; print $AH "Hi there!"; print "I printed: ", @{$AH->aref}, "\n"; ### get at value And for you folks with 1.x code out there: the old tie() style still works, though this is I: use IO::ScalarArray; ### Writing to a scalar... my @a; tie *OUT, 'IO::ScalarArray', \@a; print OUT "line 1\nline 2\n", "line 3\n"; print "Array is now: ", @a, "\n" ### Reading and writing an anonymous scalar... tie *OUT, 'IO::ScalarArray'; print OUT "line 1\nline 2\n", "line 3\n"; tied(OUT)->seek(0,0); while () { print "Got line: ", $_; } =head1 DESCRIPTION This class is part of the IO::Stringy distribution; see L for change log and general information. The IO::ScalarArray class implements objects which behave just like IO::Handle (or FileHandle) objects, except that you may use them to write to (or read from) arrays of scalars. Logically, an array of scalars defines an in-core "file" whose contents are the concatenation of the scalars in the array. The handles created by this class are automatically tiehandle'd (though please see L<"WARNINGS"> for information relevant to your Perl version). For writing large amounts of data with individual print() statements, this class is likely to be more efficient than IO::Scalar. Basically, this: my @a; $AH = new IO::ScalarArray \@a; $AH->print("Hel", "lo, "); ### OO style $AH->print("world!\n"); ### ditto Or this: my @a; $AH = new IO::ScalarArray \@a; print $AH "Hel", "lo, "; ### non-OO style print $AH "world!\n"; ### ditto Causes @a to be set to the following array of 3 strings: ( "Hel" , "lo, " , "world!\n" ) See L and compare with this class. =head1 PUBLIC INTERFACE =cut use Carp; use strict; use vars qw($VERSION @ISA); use IO::Handle; # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "2.110"; # Inheritance: @ISA = qw(IO::Handle); require IO::WrapTie and push @ISA, 'IO::WrapTie::Slave' if ($] >= 5.004); #============================== =head2 Construction =over 4 =cut #------------------------------ =item new [ARGS...] I Return a new, unattached array handle. If any arguments are given, they're sent to open(). =cut sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = bless \do { local *FH }, $class; tie *$self, $class, $self; $self->open(@_); ### open on anonymous by default $self; } sub DESTROY { shift->close; } #------------------------------ =item open [ARRAYREF] I Open the array handle on a new array, pointed to by ARRAYREF. If no ARRAYREF is given, a "private" array is created to hold the file data. Returns the self object on success, undefined on error. =cut sub open { my ($self, $aref) = @_; ### Sanity: defined($aref) or do {my @a; $aref = \@a}; (ref($aref) eq "ARRAY") or croak "open needs a ref to a array"; ### Setup: $self->setpos([0,0]); *$self->{AR} = $aref; $self; } #------------------------------ =item opened I Is the array handle opened on something? =cut sub opened { *{shift()}->{AR}; } #------------------------------ =item close I Disassociate the array handle from its underlying array. Done automatically on destroy. =cut sub close { my $self = shift; %{*$self} = (); 1; } =back =cut #============================== =head2 Input and output =over 4 =cut #------------------------------ =item flush I No-op, provided for OO compatibility. =cut sub flush { "0 but true" } #------------------------------ =item getc I Return the next character, or undef if none remain. This does a read(1), which is somewhat costly. =cut sub getc { my $buf = ''; ($_[0]->read($buf, 1) ? $buf : undef); } #------------------------------ =item getline I Return the next line, or undef on end of data. Can safely be called in an array context. Currently, lines are delimited by "\n". =cut sub getline { my $self = shift; my ($str, $line) = (undef, ''); ### Minimal impact implementation! ### We do the fast fast thing (no regexps) if using the ### classic input record separator. ### Case 1: $/ is undef: slurp all... if (!defined($/)) { return undef if ($self->eof); ### Get the rest of the current string, followed by remaining strings: my $ar = *$self->{AR}; my @slurp = ( substr($ar->[*$self->{Str}], *$self->{Pos}), @$ar[(1 + *$self->{Str}) .. $#$ar ] ); ### Seek to end: $self->_setpos_to_eof; return join('', @slurp); } ### Case 2: $/ is "\n": elsif ($/ eq "\012") { ### Until we hit EOF (or exitted because of a found line): until ($self->eof) { ### If at end of current string, go fwd to next one (won't be EOF): if ($self->_eos) {++*$self->{Str}, *$self->{Pos}=0}; ### Get ref to current string in array, and set internal pos mark: $str = \(*$self->{AR}[*$self->{Str}]); ### get current string pos($$str) = *$self->{Pos}; ### start matching from here ### Get from here to either \n or end of string, and add to line: $$str =~ m/\G(.*?)((\n)|\Z)/g; ### match to 1st \n or EOS $line .= $1.$2; ### add it *$self->{Pos} += length($1.$2); ### move fwd by len matched return $line if $3; ### done, got line with "\n" } return ($line eq '') ? undef : $line; ### return undef if EOF } ### Case 3: $/ is ref to int. Bail out. elsif (ref($/)) { croak '$/ given as a ref to int; currently unsupported'; } ### Case 4: $/ is either "" (paragraphs) or something weird... ### Bail for now. else { croak '$/ as given is currently unsupported'; } } #------------------------------ =item getlines I Get all remaining lines. It will croak() if accidentally called in a scalar context. =cut sub getlines { my $self = shift; wantarray or croak("can't call getlines in scalar context!"); my ($line, @lines); push @lines, $line while (defined($line = $self->getline)); @lines; } #------------------------------ =item print ARGS... I Print ARGS to the underlying array. Currently, this always causes a "seek to the end of the array" and generates a new array entry. This may change in the future. =cut sub print { my $self = shift; push @{*$self->{AR}}, join('', @_) . (defined($\) ? $\ : ""); ### add the data $self->_setpos_to_eof; 1; } #------------------------------ =item read BUF, NBYTES, [OFFSET]; I Read some bytes from the array. Returns the number of bytes actually read, 0 on end-of-file, undef on error. =cut sub read { my $self = $_[0]; ### we must use $_[1] as a ref my $n = $_[2]; my $off = $_[3] || 0; ### print "getline\n"; my $justread; my $len; ($off ? substr($_[1], $off) : $_[1]) = ''; ### Stop when we have zero bytes to go, or when we hit EOF: my @got; until (!$n or $self->eof) { ### If at end of current string, go forward to next one (won't be EOF): if ($self->_eos) { ++*$self->{Str}; *$self->{Pos} = 0; } ### Get longest possible desired substring of current string: $justread = substr(*$self->{AR}[*$self->{Str}], *$self->{Pos}, $n); $len = length($justread); push @got, $justread; $n -= $len; *$self->{Pos} += $len; } $_[1] .= join('', @got); return length($_[1])-$off; } #------------------------------ =item write BUF, NBYTES, [OFFSET]; I Write some bytes into the array. =cut sub write { my $self = $_[0]; my $n = $_[2]; my $off = $_[3] || 0; my $data = substr($_[1], $n, $off); $n = length($data); $self->print($data); return $n; } =back =cut #============================== =head2 Seeking/telling and other attributes =over 4 =cut #------------------------------ =item autoflush I No-op, provided for OO compatibility. =cut sub autoflush {} #------------------------------ =item binmode I No-op, provided for OO compatibility. =cut sub binmode {} #------------------------------ =item clearerr I Clear the error and EOF flags. A no-op. =cut sub clearerr { 1 } #------------------------------ =item eof I Are we at end of file? =cut sub eof { ### print "checking EOF [*$self->{Str}, *$self->{Pos}]\n"; ### print "SR = ", $#{*$self->{AR}}, "\n"; return 0 if (*{$_[0]}->{Str} < $#{*{$_[0]}->{AR}}); ### before EOA return 1 if (*{$_[0]}->{Str} > $#{*{$_[0]}->{AR}}); ### after EOA ### ### at EOA, past EOS: ((*{$_[0]}->{Str} == $#{*{$_[0]}->{AR}}) && ($_[0]->_eos)); } #------------------------------ # # _eos # # I Are we at end of the CURRENT string? # sub _eos { (*{$_[0]}->{Pos} >= length(*{$_[0]}->{AR}[*{$_[0]}->{Str}])); ### past last char } #------------------------------ =item seek POS,WHENCE I Seek to a given position in the stream. Only a WHENCE of 0 (SEEK_SET) is supported. =cut sub seek { my ($self, $pos, $whence) = @_; ### Seek: if ($whence == 0) { $self->_seek_set($pos); } elsif ($whence == 1) { $self->_seek_cur($pos); } elsif ($whence == 2) { $self->_seek_end($pos); } else { croak "bad seek whence ($whence)" } return 1; } #------------------------------ # # _seek_set POS # # Instance method, private. # Seek to $pos relative to start: # sub _seek_set { my ($self, $pos) = @_; ### Advance through array until done: my $istr = 0; while (($pos >= 0) && ($istr < scalar(@{*$self->{AR}}))) { if (length(*$self->{AR}[$istr]) > $pos) { ### it's in this string! return $self->setpos([$istr, $pos]); } else { ### it's in next string $pos -= length(*$self->{AR}[$istr++]); ### move forward one string } } ### If we reached this point, pos is at or past end; zoom to EOF: return $self->_setpos_to_eof; } #------------------------------ # # _seek_cur POS # # Instance method, private. # Seek to $pos relative to current position. # sub _seek_cur { my ($self, $pos) = @_; $self->_seek_set($self->tell + $pos); } #------------------------------ # # _seek_end POS # # Instance method, private. # Seek to $pos relative to end. # We actually seek relative to beginning, which is simple. # sub _seek_end { my ($self, $pos) = @_; $self->_seek_set($self->_tell_eof + $pos); } #------------------------------ =item tell I Return the current position in the stream, as a numeric offset. =cut sub tell { my $self = shift; my $off = 0; my ($s, $str_s); for ($s = 0; $s < *$self->{Str}; $s++) { ### count all "whole" scalars defined($str_s = *$self->{AR}[$s]) or $str_s = ''; ###print STDERR "COUNTING STRING $s (". length($str_s) . ")\n"; $off += length($str_s); } ###print STDERR "COUNTING POS ($self->{Pos})\n"; return ($off += *$self->{Pos}); ### plus the final, partial one } #------------------------------ # # _tell_eof # # Instance method, private. # Get position of EOF, as a numeric offset. # This is identical to the size of the stream - 1. # sub _tell_eof { my $self = shift; my $len = 0; foreach (@{*$self->{AR}}) { $len += length($_) } $len; } #------------------------------ =item setpos POS I Seek to a given position in the array, using the opaque getpos() value. Don't expect this to be a number. =cut sub setpos { my ($self, $pos) = @_; (ref($pos) eq 'ARRAY') or die "setpos: only use a value returned by getpos!\n"; (*$self->{Str}, *$self->{Pos}) = @$pos; } #------------------------------ # # _setpos_to_eof # # Fast-forward to EOF. # sub _setpos_to_eof { my $self = shift; $self->setpos([scalar(@{*$self->{AR}}), 0]); } #------------------------------ =item getpos I Return the current position in the array, as an opaque value. Don't expect this to be a number. =cut sub getpos { [*{$_[0]}->{Str}, *{$_[0]}->{Pos}]; } #------------------------------ =item aref I Return a reference to the underlying array. =cut sub aref { *{shift()}->{AR}; } =back =cut #------------------------------ # Tied handle methods... #------------------------------ ### Conventional tiehandle interface: sub TIEHANDLE { (defined($_[1]) && UNIVERSAL::isa($_[1],"IO::ScalarArray")) ? $_[1] : shift->new(@_) } sub GETC { shift->getc(@_) } sub PRINT { shift->print(@_) } sub PRINTF { shift->print(sprintf(shift, @_)) } sub READ { shift->read(@_) } sub READLINE { wantarray ? shift->getlines(@_) : shift->getline(@_) } sub WRITE { shift->write(@_); } sub CLOSE { shift->close(@_); } sub SEEK { shift->seek(@_); } sub TELL { shift->tell(@_); } sub EOF { shift->eof(@_); } #------------------------------------------------------------ 1; __END__ # SOME PRIVATE NOTES: # # * The "current position" is the position before the next # character to be read/written. # # * Str gives the string index of the current position, 0-based # # * Pos gives the offset within AR[Str], 0-based. # # * Inital pos is [0,0]. After print("Hello"), it is [1,0]. =head1 WARNINGS Perl's TIEHANDLE spec was incomplete prior to 5.005_57; it was missing support for C, C, and C. Attempting to use these functions with an IO::ScalarArray will not work prior to 5.005_57. IO::ScalarArray will not have the relevant methods invoked; and even worse, this kind of bug can lie dormant for a while. If you turn warnings on (via C<$^W> or C), and you see something like this... attempt to seek on unopened filehandle ...then you are probably trying to use one of these functions on an IO::ScalarArray with an old Perl. The remedy is to simply use the OO version; e.g.: $AH->seek(0,0); ### GOOD: will work on any 5.005 seek($AH,0,0); ### WARNING: will only work on 5.005_57 and beyond =head1 VERSION $Id: ScalarArray.pm,v 1.7 2005/02/10 21:21:53 dfs Exp $ =head1 AUTHOR =head2 Primary Maintainer David F. Skoll (F). =head2 Principal author Eryq (F). President, ZeeGee Software Inc (F). =head2 Other contributors Thanks to the following individuals for their invaluable contributions (if I've forgotten or misspelled your name, please email me!): I for suggesting C. I for suggesting C. I for his offset-using read() and write() implementations. I for the IO::Handle inheritance and automatic tie-ing. =cut #------------------------------ 1; gdata/inst/perl/IO/Scalar.pm.html0000644000176000001440000003416210451013017016314 0ustar ripleyusers IO::Scalar ZeeGee Software

IO::Scalar


Top NAME

IO::Scalar - IO:: interface for reading/writing a scalar


Top SYNOPSIS

Perform I/O on strings, using the basic OO interface...

    use 5.005;
    use IO::Scalar;
    $data = "My message:\n";
    ### Open a handle on a string, and append to it:
    $SH = new IO::Scalar \$data;
    $SH->print("Hello");       
    $SH->print(", world!\nBye now!\n");  
    print "The string is now: ", $data, "\n";
    ### Open a handle on a string, read it line-by-line, then close it:
    $SH = new IO::Scalar \$data;
    while (defined($_ = $SH->getline)) { 
	print "Got line: $_";
    }
    $SH->close;
    ### Open a handle on a string, and slurp in all the lines:
    $SH = new IO::Scalar \$data;
    print "All lines:\n", $SH->getlines; 
    ### Get the current position (either of two ways):
    $pos = $SH->getpos;         
    $offset = $SH->tell;  
    ### Set the current position (either of two ways):
    $SH->setpos($pos);        
    $SH->seek($offset, 0);
    ### Open an anonymous temporary scalar:
    $SH = new IO::Scalar;
    $SH->print("Hi there!");
    print "I printed: ", ${$SH->sref}, "\n";      ### get at value

Don't like OO for your I/O? No problem. Thanks to the magic of an invisible tie(), the following now works out of the box, just as it does with IO::Handle:

    use 5.005;
    use IO::Scalar;
    $data = "My message:\n";
     
    ### Open a handle on a string, and append to it:
    $SH = new IO::Scalar \$data;
    print $SH "Hello";    
    print $SH ", world!\nBye now!\n";
    print "The string is now: ", $data, "\n";
    ### Open a handle on a string, read it line-by-line, then close it:
    $SH = new IO::Scalar \$data;
    while (<$SH>) {
	print "Got line: $_";
    }
    close $SH;
    ### Open a handle on a string, and slurp in all the lines:
    $SH = new IO::Scalar \$data;
    print "All lines:\n", <$SH>;
    ### Get the current position (WARNING: requires 5.6):
    $offset = tell $SH;
    ### Set the current position (WARNING: requires 5.6):
    seek $SH, $offset, 0;
    ### Open an anonymous temporary scalar:
    $SH = new IO::Scalar;
    print $SH "Hi there!";
    print "I printed: ", ${$SH->sref}, "\n";      ### get at value

And for you folks with 1.x code out there: the old tie() style still works, though this is unnecessary and deprecated:

    use IO::Scalar;
    ### Writing to a scalar...
    my $s; 
    tie *OUT, 'IO::Scalar', \$s;
    print OUT "line 1\nline 2\n", "line 3\n";
    print "String is now: $s\n"
    ### Reading and writing an anonymous scalar... 
    tie *OUT, 'IO::Scalar';
    print OUT "line 1\nline 2\n", "line 3\n";
    tied(OUT)->seek(0,0);
    while (<OUT>) { 
        print "Got line: ", $_;
    }

Stringification works, too!

    my $SH = new IO::Scalar \$data;
    print $SH "Hello, ";
    print $SH "world!";
    print "I printed: $SH\n";


Top DESCRIPTION

This class is part of the IO::Stringy distribution; see IO::Stringy for change log and general information.

The IO::Scalar class implements objects which behave just like IO::Handle (or FileHandle) objects, except that you may use them to write to (or read from) scalars. These handles are automatically tiehandle'd (though please see WARNINGS for information relevant to your Perl version).

Basically, this:

    my $s;
    $SH = new IO::Scalar \$s;
    $SH->print("Hel", "lo, ");         ### OO style
    $SH->print("world!\n");            ### ditto

Or this:

    my $s;
    $SH = tie *OUT, 'IO::Scalar', \$s;
    print OUT "Hel", "lo, ";           ### non-OO style
    print OUT "world!\n";              ### ditto

Causes $s to be set to:

    "Hello, world!\n" 


Top PUBLIC INTERFACE


Top Construction

new [ARGS...]
Class method. Return a new, unattached scalar handle. If any arguments are given, they're sent to open().

open [SCALARREF]
Instance method. Open the scalar handle on a new scalar, pointed to by SCALARREF. If no SCALARREF is given, a "private" scalar is created to hold the file data.

Returns the self object on success, undefined on error.

opened
Instance method. Is the scalar handle opened on something?

close
Instance method. Disassociate the scalar handle from its underlying scalar. Done automatically on destroy.


Top Input and output

flush
Instance method. No-op, provided for OO compatibility.

getc
Instance method. Return the next character, or undef if none remain.

getline
Instance method. Return the next line, or undef on end of string. Can safely be called in an array context. Currently, lines are delimited by "\n".

getlines
Instance method. Get all remaining lines. It will croak() if accidentally called in a scalar context.

print ARGS...
Instance method. Print ARGS to the underlying scalar.

Warning: this continues to always cause a seek to the end of the string, but if you perform seek()s and tell()s, it is still safer to explicitly seek-to-end before subsequent print()s.

read BUF, NBYTES, [OFFSET]
Instance method. Read some bytes from the scalar. Returns the number of bytes actually read, 0 on end-of-file, undef on error.

write BUF, NBYTES, [OFFSET]
Instance method. Write some bytes to the scalar.

sysread BUF, LEN, [OFFSET]
Instance method. Read some bytes from the scalar. Returns the number of bytes actually read, 0 on end-of-file, undef on error.

syswrite BUF, NBYTES, [OFFSET]
Instance method. Write some bytes to the scalar.


Top Seeking/telling and other attributes

autoflush
Instance method. No-op, provided for OO compatibility.

binmode
Instance method. No-op, provided for OO compatibility.

clearerr
Instance method. Clear the error and EOF flags. A no-op.

eof
Instance method. Are we at end of file?

seek OFFSET, WHENCE
Instance method. Seek to a given position in the stream.

sysseek OFFSET, WHENCE
Instance method. Identical to seek OFFSET, WHENCE, q.v.

tell
Instance method. Return the current position in the stream, as a numeric offset.

use_RS [YESNO]
Instance method. Obey the curent setting of $/, like IO::Handle does? Default is false in 1.x, true in 2.x and later.

setpos POS
Instance method. Set the current position, using the opaque value returned by getpos().

getpos
Instance method. Return the current position in the string, as an opaque object.

sref
Instance method. Return a reference to the underlying scalar.


Top WARNINGS

Perl's TIEHANDLE spec was incomplete prior to 5.005_57; it was missing support for seek(), tell(), and eof(). Attempting to use these functions with an IO::Scalar will not work prior to 5.005_57. IO::Scalar will not have the relevant methods invoked; and even worse, this kind of bug can lie dormant for a while. If you turn warnings on (via $^W or perl -w), and you see something like this...

    attempt to seek on unopened filehandle

...then you are probably trying to use one of these functions on an IO::Scalar with an old Perl. The remedy is to simply use the OO version; e.g.:

    $SH->seek(0,0);    ### GOOD: will work on any 5.005
    seek($SH,0,0);     ### WARNING: will only work on 5.005_57 and beyond


Top VERSION

$Id: Scalar.pm.html 625 2005-06-09 14:20:30Z nj7w $


Top AUTHORS


Top Principal author

Eryq (eryq@zeegee.com). President, ZeeGee Software Inc (http://www.zeegee.com).


Top Other contributors

The full set of contributors always includes the folks mentioned in CHANGE LOG. But just the same, special thanks to the following individuals for their invaluable contributions (if I've forgotten or misspelled your name, please email me!):

Andy Glew, for contributing getc().

Brandon Browning, for suggesting opened().

David Richter, for finding and fixing the bug in PRINTF().

Eric L. Brine, for his offset-using read() and write() implementations.

Richard Jones, for his patches to massively improve the performance of getline() and add sysread and syswrite.

B. K. Oxley (binkley), for stringification and inheritance improvements, and sundry good ideas.

Doug Wilson, for the IO::Handle inheritance and automatic tie-ing.


Top SEE ALSO

IO::String, which is quite similar but which was designed more-recently and with an IO::Handle-like interface in mind, so you could mix OO- and native-filehandle usage without using tied().

Note: as of version 2.x, these classes all work like their IO::Handle counterparts, so we have comparable functionality to IO::String.


Generated Wed Aug 8 03:39:45 2001 by cvu_pod2html
gdata/inst/perl/IO/Scalar.pm0000644000176000001440000004054111326376512015365 0ustar ripleyuserspackage IO::Scalar; =head1 NAME IO::Scalar - IO:: interface for reading/writing a scalar =head1 SYNOPSIS Perform I/O on strings, using the basic OO interface... use 5.005; use IO::Scalar; $data = "My message:\n"; ### Open a handle on a string, and append to it: $SH = new IO::Scalar \$data; $SH->print("Hello"); $SH->print(", world!\nBye now!\n"); print "The string is now: ", $data, "\n"; ### Open a handle on a string, read it line-by-line, then close it: $SH = new IO::Scalar \$data; while (defined($_ = $SH->getline)) { print "Got line: $_"; } $SH->close; ### Open a handle on a string, and slurp in all the lines: $SH = new IO::Scalar \$data; print "All lines:\n", $SH->getlines; ### Get the current position (either of two ways): $pos = $SH->getpos; $offset = $SH->tell; ### Set the current position (either of two ways): $SH->setpos($pos); $SH->seek($offset, 0); ### Open an anonymous temporary scalar: $SH = new IO::Scalar; $SH->print("Hi there!"); print "I printed: ", ${$SH->sref}, "\n"; ### get at value Don't like OO for your I/O? No problem. Thanks to the magic of an invisible tie(), the following now works out of the box, just as it does with IO::Handle: use 5.005; use IO::Scalar; $data = "My message:\n"; ### Open a handle on a string, and append to it: $SH = new IO::Scalar \$data; print $SH "Hello"; print $SH ", world!\nBye now!\n"; print "The string is now: ", $data, "\n"; ### Open a handle on a string, read it line-by-line, then close it: $SH = new IO::Scalar \$data; while (<$SH>) { print "Got line: $_"; } close $SH; ### Open a handle on a string, and slurp in all the lines: $SH = new IO::Scalar \$data; print "All lines:\n", <$SH>; ### Get the current position (WARNING: requires 5.6): $offset = tell $SH; ### Set the current position (WARNING: requires 5.6): seek $SH, $offset, 0; ### Open an anonymous temporary scalar: $SH = new IO::Scalar; print $SH "Hi there!"; print "I printed: ", ${$SH->sref}, "\n"; ### get at value And for you folks with 1.x code out there: the old tie() style still works, though this is I: use IO::Scalar; ### Writing to a scalar... my $s; tie *OUT, 'IO::Scalar', \$s; print OUT "line 1\nline 2\n", "line 3\n"; print "String is now: $s\n" ### Reading and writing an anonymous scalar... tie *OUT, 'IO::Scalar'; print OUT "line 1\nline 2\n", "line 3\n"; tied(OUT)->seek(0,0); while () { print "Got line: ", $_; } Stringification works, too! my $SH = new IO::Scalar \$data; print $SH "Hello, "; print $SH "world!"; print "I printed: $SH\n"; =head1 DESCRIPTION This class is part of the IO::Stringy distribution; see L for change log and general information. The IO::Scalar class implements objects which behave just like IO::Handle (or FileHandle) objects, except that you may use them to write to (or read from) scalars. These handles are automatically tiehandle'd (though please see L<"WARNINGS"> for information relevant to your Perl version). Basically, this: my $s; $SH = new IO::Scalar \$s; $SH->print("Hel", "lo, "); ### OO style $SH->print("world!\n"); ### ditto Or this: my $s; $SH = tie *OUT, 'IO::Scalar', \$s; print OUT "Hel", "lo, "; ### non-OO style print OUT "world!\n"; ### ditto Causes $s to be set to: "Hello, world!\n" =head1 PUBLIC INTERFACE =cut use Carp; use strict; use vars qw($VERSION @ISA); use IO::Handle; use 5.005; ### Stringification, courtesy of B. K. Oxley (binkley): :-) use overload '""' => sub { ${*{$_[0]}->{SR}} }; use overload 'bool' => sub { 1 }; ### have to do this, so object is true! ### The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "2.110"; ### Inheritance: @ISA = qw(IO::Handle); ### This stuff should be got rid of ASAP. require IO::WrapTie and push @ISA, 'IO::WrapTie::Slave' if ($] >= 5.004); #============================== =head2 Construction =over 4 =cut #------------------------------ =item new [ARGS...] I Return a new, unattached scalar handle. If any arguments are given, they're sent to open(). =cut sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = bless \do { local *FH }, $class; tie *$self, $class, $self; $self->open(@_); ### open on anonymous by default $self; } sub DESTROY { shift->close; } #------------------------------ =item open [SCALARREF] I Open the scalar handle on a new scalar, pointed to by SCALARREF. If no SCALARREF is given, a "private" scalar is created to hold the file data. Returns the self object on success, undefined on error. =cut sub open { my ($self, $sref) = @_; ### Sanity: defined($sref) or do {my $s = ''; $sref = \$s}; (ref($sref) eq "SCALAR") or croak "open() needs a ref to a scalar"; ### Setup: *$self->{Pos} = 0; ### seek position *$self->{SR} = $sref; ### scalar reference $self; } #------------------------------ =item opened I Is the scalar handle opened on something? =cut sub opened { *{shift()}->{SR}; } #------------------------------ =item close I Disassociate the scalar handle from its underlying scalar. Done automatically on destroy. =cut sub close { my $self = shift; %{*$self} = (); 1; } =back =cut #============================== =head2 Input and output =over 4 =cut #------------------------------ =item flush I No-op, provided for OO compatibility. =cut sub flush { "0 but true" } #------------------------------ =item getc I Return the next character, or undef if none remain. =cut sub getc { my $self = shift; ### Return undef right away if at EOF; else, move pos forward: return undef if $self->eof; substr(${*$self->{SR}}, *$self->{Pos}++, 1); } #------------------------------ =item getline I Return the next line, or undef on end of string. Can safely be called in an array context. Currently, lines are delimited by "\n". =cut sub getline { my $self = shift; ### Return undef right away if at EOF: return undef if $self->eof; ### Get next line: my $sr = *$self->{SR}; my $i = *$self->{Pos}; ### Start matching at this point. ### Minimal impact implementation! ### We do the fast fast thing (no regexps) if using the ### classic input record separator. ### Case 1: $/ is undef: slurp all... if (!defined($/)) { *$self->{Pos} = length $$sr; return substr($$sr, $i); } ### Case 2: $/ is "\n": zoom zoom zoom... elsif ($/ eq "\012") { ### Seek ahead for "\n"... yes, this really is faster than regexps. my $len = length($$sr); for (; $i < $len; ++$i) { last if ord (substr ($$sr, $i, 1)) == 10; } ### Extract the line: my $line; if ($i < $len) { ### We found a "\n": $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos} + 1); *$self->{Pos} = $i+1; ### Remember where we finished up. } else { ### No "\n"; slurp the remainder: $line = substr ($$sr, *$self->{Pos}, $i - *$self->{Pos}); *$self->{Pos} = $len; } return $line; } ### Case 3: $/ is ref to int. Do fixed-size records. ### (Thanks to Dominique Quatravaux.) elsif (ref($/)) { my $len = length($$sr); my $i = ${$/} + 0; my $line = substr ($$sr, *$self->{Pos}, $i); *$self->{Pos} += $i; *$self->{Pos} = $len if (*$self->{Pos} > $len); return $line; } ### Case 4: $/ is either "" (paragraphs) or something weird... ### This is Graham's general-purpose stuff, which might be ### a tad slower than Case 2 for typical data, because ### of the regexps. else { pos($$sr) = $i; ### If in paragraph mode, skip leading lines (and update i!): length($/) or (($$sr =~ m/\G\n*/g) and ($i = pos($$sr))); ### If we see the separator in the buffer ahead... if (length($/) ? $$sr =~ m,\Q$/\E,g ### (ordinary sep) TBD: precomp! : $$sr =~ m,\n\n,g ### (a paragraph) ) { *$self->{Pos} = pos $$sr; return substr($$sr, $i, *$self->{Pos}-$i); } ### Else if no separator remains, just slurp the rest: else { *$self->{Pos} = length $$sr; return substr($$sr, $i); } } } #------------------------------ =item getlines I Get all remaining lines. It will croak() if accidentally called in a scalar context. =cut sub getlines { my $self = shift; wantarray or croak("can't call getlines in scalar context!"); my ($line, @lines); push @lines, $line while (defined($line = $self->getline)); @lines; } #------------------------------ =item print ARGS... I Print ARGS to the underlying scalar. B this continues to always cause a seek to the end of the string, but if you perform seek()s and tell()s, it is still safer to explicitly seek-to-end before subsequent print()s. =cut sub print { my $self = shift; *$self->{Pos} = length(${*$self->{SR}} .= join('', @_) . (defined($\) ? $\ : "")); 1; } sub _unsafe_print { my $self = shift; my $append = join('', @_) . $\; ${*$self->{SR}} .= $append; *$self->{Pos} += length($append); 1; } sub _old_print { my $self = shift; ${*$self->{SR}} .= join('', @_) . $\; *$self->{Pos} = length(${*$self->{SR}}); 1; } #------------------------------ =item read BUF, NBYTES, [OFFSET] I Read some bytes from the scalar. Returns the number of bytes actually read, 0 on end-of-file, undef on error. =cut sub read { my $self = $_[0]; my $n = $_[2]; my $off = $_[3] || 0; my $read = substr(${*$self->{SR}}, *$self->{Pos}, $n); $n = length($read); *$self->{Pos} += $n; ($off ? substr($_[1], $off) : $_[1]) = $read; return $n; } #------------------------------ =item write BUF, NBYTES, [OFFSET] I Write some bytes to the scalar. =cut sub write { my $self = $_[0]; my $n = $_[2]; my $off = $_[3] || 0; my $data = substr($_[1], $off, $n); $n = length($data); $self->print($data); return $n; } #------------------------------ =item sysread BUF, LEN, [OFFSET] I Read some bytes from the scalar. Returns the number of bytes actually read, 0 on end-of-file, undef on error. =cut sub sysread { my $self = shift; $self->read(@_); } #------------------------------ =item syswrite BUF, NBYTES, [OFFSET] I Write some bytes to the scalar. =cut sub syswrite { my $self = shift; $self->write(@_); } =back =cut #============================== =head2 Seeking/telling and other attributes =over 4 =cut #------------------------------ =item autoflush I No-op, provided for OO compatibility. =cut sub autoflush {} #------------------------------ =item binmode I No-op, provided for OO compatibility. =cut sub binmode {} #------------------------------ =item clearerr I Clear the error and EOF flags. A no-op. =cut sub clearerr { 1 } #------------------------------ =item eof I Are we at end of file? =cut sub eof { my $self = shift; (*$self->{Pos} >= length(${*$self->{SR}})); } #------------------------------ =item seek OFFSET, WHENCE I Seek to a given position in the stream. =cut sub seek { my ($self, $pos, $whence) = @_; my $eofpos = length(${*$self->{SR}}); ### Seek: if ($whence == 0) { *$self->{Pos} = $pos } ### SEEK_SET elsif ($whence == 1) { *$self->{Pos} += $pos } ### SEEK_CUR elsif ($whence == 2) { *$self->{Pos} = $eofpos + $pos} ### SEEK_END else { croak "bad seek whence ($whence)" } ### Fixup: if (*$self->{Pos} < 0) { *$self->{Pos} = 0 } if (*$self->{Pos} > $eofpos) { *$self->{Pos} = $eofpos } return 1; } #------------------------------ =item sysseek OFFSET, WHENCE I Identical to C, I =cut sub sysseek { my $self = shift; $self->seek (@_); } #------------------------------ =item tell I Return the current position in the stream, as a numeric offset. =cut sub tell { *{shift()}->{Pos} } #------------------------------ # # use_RS [YESNO] # # I # Obey the curent setting of $/, like IO::Handle does? # Default is false in 1.x, but cold-welded true in 2.x and later. # sub use_RS { my ($self, $yesno) = @_; carp "use_RS is deprecated and ignored; \$/ is always consulted\n"; } #------------------------------ =item setpos POS I Set the current position, using the opaque value returned by C. =cut sub setpos { shift->seek($_[0],0) } #------------------------------ =item getpos I Return the current position in the string, as an opaque object. =cut *getpos = \&tell; #------------------------------ =item sref I Return a reference to the underlying scalar. =cut sub sref { *{shift()}->{SR} } #------------------------------ # Tied handle methods... #------------------------------ # Conventional tiehandle interface: sub TIEHANDLE { ((defined($_[1]) && UNIVERSAL::isa($_[1], "IO::Scalar")) ? $_[1] : shift->new(@_)); } sub GETC { shift->getc(@_) } sub PRINT { shift->print(@_) } sub PRINTF { shift->print(sprintf(shift, @_)) } sub READ { shift->read(@_) } sub READLINE { wantarray ? shift->getlines(@_) : shift->getline(@_) } sub WRITE { shift->write(@_); } sub CLOSE { shift->close(@_); } sub SEEK { shift->seek(@_); } sub TELL { shift->tell(@_); } sub EOF { shift->eof(@_); } #------------------------------------------------------------ 1; __END__ =back =cut =head1 WARNINGS Perl's TIEHANDLE spec was incomplete prior to 5.005_57; it was missing support for C, C, and C. Attempting to use these functions with an IO::Scalar will not work prior to 5.005_57. IO::Scalar will not have the relevant methods invoked; and even worse, this kind of bug can lie dormant for a while. If you turn warnings on (via C<$^W> or C), and you see something like this... attempt to seek on unopened filehandle ...then you are probably trying to use one of these functions on an IO::Scalar with an old Perl. The remedy is to simply use the OO version; e.g.: $SH->seek(0,0); ### GOOD: will work on any 5.005 seek($SH,0,0); ### WARNING: will only work on 5.005_57 and beyond =head1 VERSION $Id: Scalar.pm,v 1.6 2005/02/10 21:21:53 dfs Exp $ =head1 AUTHORS =head2 Primary Maintainer David F. Skoll (F). =head2 Principal author Eryq (F). President, ZeeGee Software Inc (F). =head2 Other contributors The full set of contributors always includes the folks mentioned in L. But just the same, special thanks to the following individuals for their invaluable contributions (if I've forgotten or misspelled your name, please email me!): I for contributing C. I for suggesting C. I for finding and fixing the bug in C. I for his offset-using read() and write() implementations. I for his patches to massively improve the performance of C and add C and C. I for stringification and inheritance improvements, and sundry good ideas. I for the IO::Handle inheritance and automatic tie-ing. =head1 SEE ALSO L, which is quite similar but which was designed more-recently and with an IO::Handle-like interface in mind, so you could mix OO- and native-filehandle usage without using tied(). I as of version 2.x, these classes all work like their IO::Handle counterparts, so we have comparable functionality to IO::String. =cut gdata/inst/perl/IO/Lines.pm0000644000176000001440000001033411326376512015227 0ustar ripleyuserspackage IO::Lines; =head1 NAME IO::Lines - IO:: interface for reading/writing an array of lines =head1 SYNOPSIS use IO::Lines; ### See IO::ScalarArray for details =head1 DESCRIPTION This class implements objects which behave just like FileHandle (or IO::Handle) objects, except that you may use them to write to (or read from) an array of lines. They can be tiehandle'd as well. This is a subclass of L in which the underlying array has its data stored in a line-oriented-format: that is, every element ends in a C<"\n">, with the possible exception of the final element. This makes C I more efficient; if you plan to do line-oriented reading/printing, you want this class. The C method will enforce this rule, so you can print arbitrary data to the line-array: it will break the data at newlines appropriately. See L for full usage and warnings. =cut use Carp; use strict; use IO::ScalarArray; use vars qw($VERSION @ISA); # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "2.110"; # Inheritance: @ISA = qw(IO::ScalarArray); ### also gets us new_tie :-) #------------------------------ # # getline # # Instance method, override. # Return the next line, or undef on end of data. # Can safely be called in an array context. # Currently, lines are delimited by "\n". # sub getline { my $self = shift; if (!defined $/) { return join( '', $self->_getlines_for_newlines ); } elsif ($/ eq "\n") { if (!*$self->{Pos}) { ### full line... return *$self->{AR}[*$self->{Str}++]; } else { ### partial line... my $partial = substr(*$self->{AR}[*$self->{Str}++], *$self->{Pos}); *$self->{Pos} = 0; return $partial; } } else { croak 'unsupported $/: must be "\n" or undef'; } } #------------------------------ # # getlines # # Instance method, override. # Return an array comprised of the remaining lines, or () on end of data. # Must be called in an array context. # Currently, lines are delimited by "\n". # sub getlines { my $self = shift; wantarray or croak("can't call getlines in scalar context!"); if ((defined $/) and ($/ eq "\n")) { return $self->_getlines_for_newlines(@_); } else { ### slow but steady return $self->SUPER::getlines(@_); } } #------------------------------ # # _getlines_for_newlines # # Instance method, private. # If $/ is newline, do fast getlines. # This CAN NOT invoke getline! # sub _getlines_for_newlines { my $self = shift; my ($rArray, $Str, $Pos) = @{*$self}{ qw( AR Str Pos ) }; my @partial = (); if ($Pos) { ### partial line... @partial = (substr( $rArray->[ $Str++ ], $Pos )); *$self->{Pos} = 0; } *$self->{Str} = scalar @$rArray; ### about to exhaust @$rArray return (@partial, @$rArray[ $Str .. $#$rArray ]); ### remaining full lines... } #------------------------------ # # print ARGS... # # Instance method, override. # Print ARGS to the underlying line array. # sub print { if (defined $\ && $\ ne "\n") { croak 'unsupported $\: must be "\n" or undef'; } my $self = shift; ### print STDERR "\n[[ARRAY WAS...\n", @{*$self->{AR}}, "<>\n"; my @lines = split /^/, join('', @_); @lines or return 1; ### Did the previous print not end with a newline? ### If so, append first line: if (@{*$self->{AR}} and (*$self->{AR}[-1] !~ /\n\Z/)) { *$self->{AR}[-1] .= shift @lines; } push @{*$self->{AR}}, @lines; ### add the remainder ### print STDERR "\n[[ARRAY IS NOW...\n", @{*$self->{AR}}, "<>\n"; 1; } #------------------------------ 1; __END__ =head1 VERSION $Id: Lines.pm,v 1.3 2005/02/10 21:21:53 dfs Exp $ =head1 AUTHORS =head2 Primary Maintainer David F. Skoll (F). =head2 Principal author Eryq (F). President, ZeeGee Software Inc (F). =head2 Other contributors Thanks to the following individuals for their invaluable contributions (if I've forgotten or misspelled your name, please email me!): I for his $/ patch and the new C. I for the IO::Handle inheritance and automatic tie-ing. =cut gdata/inst/perl/IO/InnerFile.pm0000644000176000001440000001264311326376512016035 0ustar ripleyuserspackage IO::InnerFile; =head1 NAME IO::InnerFile - define a file inside another file =head1 SYNOPSIS ### Read a subset of a file: $inner = IO::InnerFile->new($fh, $start, $length); while (<$inner>) { ... } =head1 DESCRIPTION If you have a filehandle that can seek() and tell(), then you can open an IO::InnerFile on a range of the underlying file. =head1 PUBLIC INTERFACE =over =cut use Symbol; # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "2.110"; #------------------------------ =item new FILEHANDLE, [START, [LENGTH]] I Create a new inner-file opened on the given FILEHANDLE, from bytes START to START+LENGTH. Both START and LENGTH default to 0; negative values are silently coerced to zero. Note that FILEHANDLE must be able to seek() and tell(), in addition to whatever other methods you may desire for reading it. =cut sub new { my ($class, $fh, $start, $lg) = @_; $start = 0 if (!$start or ($start < 0)); $lg = 0 if (!$lg or ($lg < 0)); ### Create the underlying "object": my $a = { FH => $fh, CRPOS => 0, START => $start, LG => $lg, }; ### Create a new filehandle tied to this object: $fh = gensym; tie(*$fh, $class, $a); return bless($fh, $class); } sub TIEHANDLE { my ($class, $data) = @_; return bless($data, $class); } sub DESTROY { my ($self) = @_; $self->close() if (ref($self) eq 'SCALAR'); } #------------------------------ =item set_length LENGTH =item get_length =item add_length NBYTES I Get/set the virtual length of the inner file. =cut sub set_length { tied(${$_[0]})->{LG} = $_[1]; } sub get_length { tied(${$_[0]})->{LG}; } sub add_length { tied(${$_[0]})->{LG} += $_[1]; } #------------------------------ =item set_start START =item get_start =item add_start NBYTES I Get/set the virtual start position of the inner file. =cut sub set_start { tied(${$_[0]})->{START} = $_[1]; } sub get_start { tied(${$_[0]})->{START}; } sub set_end { tied(${$_[0]})->{LG} = $_[1] - tied(${$_[0]})->{START}; } sub get_end { tied(${$_[0]})->{LG} + tied(${$_[0]})->{START}; } #------------------------------ =item binmode =item close =item flush =item getc =item getline =item print LIST =item printf LIST =item read BUF, NBYTES =item readline =item seek OFFFSET, WHENCE =item tell =item write ARGS... I Standard filehandle methods. =cut sub write { shift->WRITE(@_) } sub print { shift->PRINT(@_) } sub printf { shift->PRINTF(@_) } sub flush { "0 but true"; } sub binmode { 1; } sub getc { return GETC(tied(${$_[0]}) ); } sub read { return READ( tied(${$_[0]}), @_[1,2,3] ); } sub readline { return READLINE( tied(${$_[0]}) ); } sub getline { return READLINE( tied(${$_[0]}) ); } sub close { return CLOSE(tied(${$_[0]}) ); } sub seek { my ($self, $ofs, $whence) = @_; $self = tied( $$self ); $self->{CRPOS} = $ofs if ($whence == 0); $self->{CRPOS}+= $ofs if ($whence == 1); $self->{CRPOS} = $self->{LG} + $ofs if ($whence == 2); $self->{CRPOS} = 0 if ($self->{CRPOS} < 0); $self->{CRPOS} = $self->{LG} if ($self->{CRPOS} > $self->{LG}); return 1; } sub tell { return tied(${$_[0]})->{CRPOS}; } sub WRITE { die "inner files can only open for reading\n"; } sub PRINT { die "inner files can only open for reading\n"; } sub PRINTF { die "inner files can only open for reading\n"; } sub GETC { my ($self) = @_; return 0 if ($self->{CRPOS} >= $self->{LG}); my $data; ### Save and seek... my $old_pos = $self->{FH}->tell; $self->{FH}->seek($self->{CRPOS}+$self->{START}, 0); ### ...read... my $lg = $self->{FH}->read($data, 1); $self->{CRPOS} += $lg; ### ...and restore: $self->{FH}->seek($old_pos, 0); $self->{LG} = $self->{CRPOS} unless ($lg); return ($lg ? $data : undef); } sub READ { my ($self, $undefined, $lg, $ofs) = @_; $undefined = undef; return 0 if ($self->{CRPOS} >= $self->{LG}); $lg = $self->{LG} - $self->{CRPOS} if ($self->{CRPOS} + $lg > $self->{LG}); return 0 unless ($lg); ### Save and seek... my $old_pos = $self->{FH}->tell; $self->{FH}->seek($self->{CRPOS}+$self->{START}, 0); ### ...read... $lg = $self->{FH}->read($_[1], $lg, $_[3] ); $self->{CRPOS} += $lg; ### ...and restore: $self->{FH}->seek($old_pos, 0); $self->{LG} = $self->{CRPOS} unless ($lg); return $lg; } sub READLINE { my ($self) = @_; return undef if ($self->{CRPOS} >= $self->{LG}); ### Save and seek... my $old_pos = $self->{FH}->tell; $self->{FH}->seek($self->{CRPOS}+$self->{START}, 0); ### ...read... my $text = $self->{FH}->getline; ### ...and restore: $self->{FH}->seek($old_pos, 0); #### If we detected a new EOF ... unless (defined $text) { $self->{LG} = $self->{CRPOS}; return undef; } my $lg=length($text); $lg = $self->{LG} - $self->{CRPOS} if ($self->{CRPOS} + $lg > $self->{LG}); $self->{CRPOS} += $lg; return substr($text, 0,$lg); } sub CLOSE { %{$_[0]}=(); } 1; __END__ =back =head1 VERSION $Id: InnerFile.pm,v 1.4 2005/02/10 21:21:53 dfs Exp $ =head1 AUTHOR Original version by Doru Petrescu (pdoru@kappa.ro). Documentation and by Eryq (eryq@zeegee.com). Currently maintained by David F. Skoll (dfs@roaringpenguin.com). =cut gdata/inst/perl/IO/AtomicFile.pm0000644000176000001440000001134411326376512016173 0ustar ripleyuserspackage IO::AtomicFile; ### DOCUMENTATION AT BOTTOM OF FILE # Be strict: use strict; # External modules: use IO::File; #------------------------------ # # GLOBALS... # #------------------------------ use vars qw($VERSION @ISA); # The package version, both in 1.23 style *and* usable by MakeMaker: $VERSION = "2.110"; # Inheritance: @ISA = qw(IO::File); #------------------------------ # new ARGS... #------------------------------ # Class method, constructor. # Any arguments are sent to open(). # sub new { my $class = shift; my $self = $class->SUPER::new(); ${*$self}{'io_atomicfile_suffix'} = ''; $self->open(@_) if @_; $self; } #------------------------------ # DESTROY #------------------------------ # Destructor. # sub DESTROY { shift->close(1); ### like close, but raises fatal exception on failure } #------------------------------ # open PATH, MODE #------------------------------ # Class/instance method. # sub open { my ($self, $path, $mode) = @_; ref($self) or $self = $self->new; ### now we have an instance! ### Create tmp path, and remember this info: my $temp = "${path}..TMP" . ${*$self}{'io_atomicfile_suffix'}; ${*$self}{'io_atomicfile_temp'} = $temp; ${*$self}{'io_atomicfile_path'} = $path; ### Open the file! Returns filehandle on success, for use as a constructor: $self->SUPER::open($temp, $mode) ? $self : undef; } #------------------------------ # _closed [YESNO] #------------------------------ # Instance method, private. # Are we already closed? Argument sets new value, returns previous one. # sub _closed { my $self = shift; my $oldval = ${*$self}{'io_atomicfile_closed'}; ${*$self}{'io_atomicfile_closed'} = shift if @_; $oldval; } #------------------------------ # close #------------------------------ # Instance method. # Close the handle, and rename the temp file to its final name. # sub close { my ($self, $die) = @_; unless ($self->_closed(1)) { ### sentinel... $self->SUPER::close(); rename(${*$self}{'io_atomicfile_temp'}, ${*$self}{'io_atomicfile_path'}) or ($die ? die "close atomic file: $!\n" : return undef); } 1; } #------------------------------ # delete #------------------------------ # Instance method. # Close the handle, and delete the temp file. # sub delete { my $self = shift; unless ($self->_closed(1)) { ### sentinel... $self->SUPER::close(); return unlink(${*$self}{'io_atomicfile_temp'}); } 1; } #------------------------------ # detach #------------------------------ # Instance method. # Close the handle, but DO NOT delete the temp file. # sub detach { my $self = shift; $self->SUPER::close() unless ($self->_closed(1)); 1; } #------------------------------ 1; __END__ =head1 NAME IO::AtomicFile - write a file which is updated atomically =head1 SYNOPSIS use IO::AtomicFile; ### Write a temp file, and have it install itself when closed: my $FH = IO::AtomicFile->open("bar.dat", "w"); print $FH "Hello!\n"; $FH->close || die "couldn't install atomic file: $!"; ### Write a temp file, but delete it before it gets installed: my $FH = IO::AtomicFile->open("bar.dat", "w"); print $FH "Hello!\n"; $FH->delete; ### Write a temp file, but neither install it nor delete it: my $FH = IO::AtomicFile->open("bar.dat", "w"); print $FH "Hello!\n"; $FH->detach; =head1 DESCRIPTION This module is intended for people who need to update files reliably in the face of unexpected program termination. For example, you generally don't want to be halfway in the middle of writing I and have your program terminate! Even the act of writing a single scalar to a filehandle is I atomic. But this module gives you true atomic updates, via rename(). When you open a file I via this module, you are I opening a temporary file I, and writing your output there. The act of closing this file (either explicitly via close(), or implicitly via the destruction of the object) will cause rename() to be called... therefore, from the point of view of the outside world, the file's contents are updated in a single time quantum. To ensure that problems do not go undetected, the "close" method done by the destructor will raise a fatal exception if the rename() fails. The explicit close() just returns undef. You can also decide at any point to trash the file you've been building. =head1 AUTHOR =head2 Primary Maintainer David F. Skoll (F). =head2 Original Author Eryq (F). President, ZeeGee Software Inc (F). =head1 REVISION $Revision: 1.2 $ =cut gdata/inst/perl/Archive/0000755000176000001440000000000012024144455014663 5ustar ripleyusersgdata/inst/perl/Archive/Zip.pm0000644000176000001440000016612311337525124015776 0ustar ripleyuserspackage Archive::Zip; use strict; BEGIN { require 5.003_96; } use UNIVERSAL (); use Carp (); use Cwd (); use IO::File (); use IO::Seekable (); use Compress::Raw::Zlib (); use File::Spec (); use File::Temp (); use FileHandle (); use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; require Exporter; @ISA = qw( Exporter ); } use vars qw( $ChunkSize $ErrorHandler ); BEGIN { # This is the size we'll try to read, write, and (de)compress. # You could set it to something different if you had lots of memory # and needed more speed. $ChunkSize ||= 32768; $ErrorHandler = \&Carp::carp; } # BEGIN block is necessary here so that other modules can use the constants. use vars qw( @EXPORT_OK %EXPORT_TAGS ); BEGIN { @EXPORT_OK = ('computeCRC32'); %EXPORT_TAGS = ( CONSTANTS => [ qw( FA_MSDOS FA_UNIX GPBF_ENCRYPTED_MASK GPBF_DEFLATING_COMPRESSION_MASK GPBF_HAS_DATA_DESCRIPTOR_MASK COMPRESSION_STORED COMPRESSION_DEFLATED COMPRESSION_LEVEL_NONE COMPRESSION_LEVEL_DEFAULT COMPRESSION_LEVEL_FASTEST COMPRESSION_LEVEL_BEST_COMPRESSION IFA_TEXT_FILE_MASK IFA_TEXT_FILE IFA_BINARY_FILE ) ], MISC_CONSTANTS => [ qw( FA_AMIGA FA_VAX_VMS FA_VM_CMS FA_ATARI_ST FA_OS2_HPFS FA_MACINTOSH FA_Z_SYSTEM FA_CPM FA_TOPS20 FA_WINDOWS_NTFS FA_QDOS FA_ACORN FA_VFAT FA_MVS FA_BEOS FA_TANDEM FA_THEOS GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK GPBF_IS_COMPRESSED_PATCHED_DATA_MASK COMPRESSION_SHRUNK DEFLATING_COMPRESSION_NORMAL DEFLATING_COMPRESSION_MAXIMUM DEFLATING_COMPRESSION_FAST DEFLATING_COMPRESSION_SUPER_FAST COMPRESSION_REDUCED_1 COMPRESSION_REDUCED_2 COMPRESSION_REDUCED_3 COMPRESSION_REDUCED_4 COMPRESSION_IMPLODED COMPRESSION_TOKENIZED COMPRESSION_DEFLATED_ENHANCED COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED ) ], ERROR_CODES => [ qw( AZ_OK AZ_STREAM_END AZ_ERROR AZ_FORMAT_ERROR AZ_IO_ERROR ) ], # For Internal Use Only PKZIP_CONSTANTS => [ qw( SIGNATURE_FORMAT SIGNATURE_LENGTH LOCAL_FILE_HEADER_SIGNATURE LOCAL_FILE_HEADER_FORMAT LOCAL_FILE_HEADER_LENGTH CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE DATA_DESCRIPTOR_FORMAT DATA_DESCRIPTOR_LENGTH DATA_DESCRIPTOR_SIGNATURE DATA_DESCRIPTOR_FORMAT_NO_SIG DATA_DESCRIPTOR_LENGTH_NO_SIG CENTRAL_DIRECTORY_FILE_HEADER_FORMAT CENTRAL_DIRECTORY_FILE_HEADER_LENGTH END_OF_CENTRAL_DIRECTORY_SIGNATURE END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING END_OF_CENTRAL_DIRECTORY_FORMAT END_OF_CENTRAL_DIRECTORY_LENGTH ) ], # For Internal Use Only UTILITY_METHODS => [ qw( _error _printError _ioError _formatError _subclassResponsibility _binmode _isSeekable _newFileHandle _readSignature _asZipDirName ) ], ); # Add all the constant names and error code names to @EXPORT_OK Exporter::export_ok_tags( qw( CONSTANTS ERROR_CODES PKZIP_CONSTANTS UTILITY_METHODS MISC_CONSTANTS ) ); } # Error codes use constant AZ_OK => 0; use constant AZ_STREAM_END => 1; use constant AZ_ERROR => 2; use constant AZ_FORMAT_ERROR => 3; use constant AZ_IO_ERROR => 4; # File types # Values of Archive::Zip::Member->fileAttributeFormat() use constant FA_MSDOS => 0; use constant FA_AMIGA => 1; use constant FA_VAX_VMS => 2; use constant FA_UNIX => 3; use constant FA_VM_CMS => 4; use constant FA_ATARI_ST => 5; use constant FA_OS2_HPFS => 6; use constant FA_MACINTOSH => 7; use constant FA_Z_SYSTEM => 8; use constant FA_CPM => 9; use constant FA_TOPS20 => 10; use constant FA_WINDOWS_NTFS => 11; use constant FA_QDOS => 12; use constant FA_ACORN => 13; use constant FA_VFAT => 14; use constant FA_MVS => 15; use constant FA_BEOS => 16; use constant FA_TANDEM => 17; use constant FA_THEOS => 18; # general-purpose bit flag masks # Found in Archive::Zip::Member->bitFlag() use constant GPBF_ENCRYPTED_MASK => 1 << 0; use constant GPBF_DEFLATING_COMPRESSION_MASK => 3 << 1; use constant GPBF_HAS_DATA_DESCRIPTOR_MASK => 1 << 3; # deflating compression types, if compressionMethod == COMPRESSION_DEFLATED # ( Archive::Zip::Member->bitFlag() & GPBF_DEFLATING_COMPRESSION_MASK ) use constant DEFLATING_COMPRESSION_NORMAL => 0 << 1; use constant DEFLATING_COMPRESSION_MAXIMUM => 1 << 1; use constant DEFLATING_COMPRESSION_FAST => 2 << 1; use constant DEFLATING_COMPRESSION_SUPER_FAST => 3 << 1; # compression method # these two are the only ones supported in this module use constant COMPRESSION_STORED => 0; # file is stored (no compression) use constant COMPRESSION_DEFLATED => 8; # file is Deflated use constant COMPRESSION_LEVEL_NONE => 0; use constant COMPRESSION_LEVEL_DEFAULT => -1; use constant COMPRESSION_LEVEL_FASTEST => 1; use constant COMPRESSION_LEVEL_BEST_COMPRESSION => 9; # internal file attribute bits # Found in Archive::Zip::Member::internalFileAttributes() use constant IFA_TEXT_FILE_MASK => 1; use constant IFA_TEXT_FILE => 1; use constant IFA_BINARY_FILE => 0; # PKZIP file format miscellaneous constants (for internal use only) use constant SIGNATURE_FORMAT => "V"; use constant SIGNATURE_LENGTH => 4; # these lengths are without the signature. use constant LOCAL_FILE_HEADER_SIGNATURE => 0x04034b50; use constant LOCAL_FILE_HEADER_FORMAT => "v3 V4 v2"; use constant LOCAL_FILE_HEADER_LENGTH => 26; # PKZIP docs don't mention the signature, but Info-Zip writes it. use constant DATA_DESCRIPTOR_SIGNATURE => 0x08074b50; use constant DATA_DESCRIPTOR_FORMAT => "V3"; use constant DATA_DESCRIPTOR_LENGTH => 12; # but the signature is apparently optional. use constant DATA_DESCRIPTOR_FORMAT_NO_SIG => "V2"; use constant DATA_DESCRIPTOR_LENGTH_NO_SIG => 8; use constant CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE => 0x02014b50; use constant CENTRAL_DIRECTORY_FILE_HEADER_FORMAT => "C2 v3 V4 v5 V2"; use constant CENTRAL_DIRECTORY_FILE_HEADER_LENGTH => 42; use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE => 0x06054b50; use constant END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING => pack( "V", END_OF_CENTRAL_DIRECTORY_SIGNATURE ); use constant END_OF_CENTRAL_DIRECTORY_FORMAT => "v4 V2 v"; use constant END_OF_CENTRAL_DIRECTORY_LENGTH => 18; use constant GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK => 1 << 1; use constant GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK => 1 << 2; use constant GPBF_IS_COMPRESSED_PATCHED_DATA_MASK => 1 << 5; # the rest of these are not supported in this module use constant COMPRESSION_SHRUNK => 1; # file is Shrunk use constant COMPRESSION_REDUCED_1 => 2; # file is Reduced CF=1 use constant COMPRESSION_REDUCED_2 => 3; # file is Reduced CF=2 use constant COMPRESSION_REDUCED_3 => 4; # file is Reduced CF=3 use constant COMPRESSION_REDUCED_4 => 5; # file is Reduced CF=4 use constant COMPRESSION_IMPLODED => 6; # file is Imploded use constant COMPRESSION_TOKENIZED => 7; # reserved for Tokenizing compr. use constant COMPRESSION_DEFLATED_ENHANCED => 9; # reserved for enh. Deflating use constant COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED => 10; # Load the various required classes require Archive::Zip::Archive; require Archive::Zip::Member; require Archive::Zip::FileMember; require Archive::Zip::DirectoryMember; require Archive::Zip::ZipFileMember; require Archive::Zip::NewFileMember; require Archive::Zip::StringMember; use constant ZIPARCHIVECLASS => 'Archive::Zip::Archive'; use constant ZIPMEMBERCLASS => 'Archive::Zip::Member'; # Convenience functions sub _ISA ($$) { # Can't rely on Scalar::Util, so use the next best way local $@; !! eval { ref $_[0] and $_[0]->isa($_[1]) }; } sub _CAN ($$) { local $@; !! eval { ref $_[0] and $_[0]->can($_[1]) }; } ##################################################################### # Methods sub new { my $class = shift; return $class->ZIPARCHIVECLASS->new(@_); } sub computeCRC32 { my ( $data, $crc ); if ( ref( $_[0] ) eq 'HASH' ) { $data = $_[0]->{string}; $crc = $_[0]->{checksum}; } else { $data = shift; $data = shift if ref($data); $crc = shift; } return Compress::Raw::Zlib::crc32( $data, $crc ); } # Report or change chunk size used for reading and writing. # Also sets Zlib's default buffer size (eventually). sub setChunkSize { shift if ref( $_[0] ) eq 'Archive::Zip::Archive'; my $chunkSize = ( ref( $_[0] ) eq 'HASH' ) ? shift->{chunkSize} : shift; my $oldChunkSize = $Archive::Zip::ChunkSize; $Archive::Zip::ChunkSize = $chunkSize if ($chunkSize); return $oldChunkSize; } sub chunkSize { return $Archive::Zip::ChunkSize; } sub setErrorHandler { my $errorHandler = ( ref( $_[0] ) eq 'HASH' ) ? shift->{subroutine} : shift; $errorHandler = \&Carp::carp unless defined($errorHandler); my $oldErrorHandler = $Archive::Zip::ErrorHandler; $Archive::Zip::ErrorHandler = $errorHandler; return $oldErrorHandler; } ###################################################################### # Private utility functions (not methods). sub _printError { my $string = join ( ' ', @_, "\n" ); my $oldCarpLevel = $Carp::CarpLevel; $Carp::CarpLevel += 2; &{$ErrorHandler} ($string); $Carp::CarpLevel = $oldCarpLevel; } # This is called on format errors. sub _formatError { shift if ref( $_[0] ); _printError( 'format error:', @_ ); return AZ_FORMAT_ERROR; } # This is called on IO errors. sub _ioError { shift if ref( $_[0] ); _printError( 'IO error:', @_, ':', $! ); return AZ_IO_ERROR; } # This is called on generic errors. sub _error { shift if ref( $_[0] ); _printError( 'error:', @_ ); return AZ_ERROR; } # Called when a subclass should have implemented # something but didn't sub _subclassResponsibility { Carp::croak("subclass Responsibility\n"); } # Try to set the given file handle or object into binary mode. sub _binmode { my $fh = shift; return _CAN( $fh, 'binmode' ) ? $fh->binmode() : binmode($fh); } # Attempt to guess whether file handle is seekable. # Because of problems with Windows, this only returns true when # the file handle is a real file. sub _isSeekable { my $fh = shift; return 0 unless ref $fh; if ( _ISA($fh, 'IO::Scalar') ) { # IO::Scalar objects are brokenly-seekable return 0; } if ( _ISA($fh, 'IO::String') ) { return 1; } if ( _ISA($fh, 'IO::Seekable') ) { # Unfortunately, some things like FileHandle objects # return true for Seekable, but AREN'T!!!!! if ( _ISA($fh, 'FileHandle') ) { return 0; } else { return 1; } } if ( _CAN($fh, 'stat') ) { return -f $fh; } return ( _CAN($fh, 'seek') and _CAN($fh, 'tell') ) ? 1 : 0; } # Print to the filehandle, while making sure the pesky Perl special global # variables don't interfere. sub _print { my ($self, $fh, @data) = @_; local $\; return $fh->print(@data); } # Return an opened IO::Handle # my ( $status, fh ) = _newFileHandle( 'fileName', 'w' ); # Can take a filename, file handle, or ref to GLOB # Or, if given something that is a ref but not an IO::Handle, # passes back the same thing. sub _newFileHandle { my $fd = shift; my $status = 1; my $handle; if ( ref($fd) ) { if ( _ISA($fd, 'IO::Scalar') or _ISA($fd, 'IO::String') ) { $handle = $fd; } elsif ( _ISA($fd, 'IO::Handle') or ref($fd) eq 'GLOB' ) { $handle = IO::File->new; $status = $handle->fdopen( $fd, @_ ); } else { $handle = $fd; } } else { $handle = IO::File->new; $status = $handle->open( $fd, @_ ); } return ( $status, $handle ); } # Returns next signature from given file handle, leaves # file handle positioned afterwards. # In list context, returns ($status, $signature) # ( $status, $signature) = _readSignature( $fh, $fileName ); sub _readSignature { my $fh = shift; my $fileName = shift; my $expectedSignature = shift; # optional my $signatureData; my $bytesRead = $fh->read( $signatureData, SIGNATURE_LENGTH ); if ( $bytesRead != SIGNATURE_LENGTH ) { return _ioError("reading header signature"); } my $signature = unpack( SIGNATURE_FORMAT, $signatureData ); my $status = AZ_OK; # compare with expected signature, if any, or any known signature. if ( ( defined($expectedSignature) && $signature != $expectedSignature ) || ( !defined($expectedSignature) && $signature != CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE && $signature != LOCAL_FILE_HEADER_SIGNATURE && $signature != END_OF_CENTRAL_DIRECTORY_SIGNATURE && $signature != DATA_DESCRIPTOR_SIGNATURE ) ) { my $errmsg = sprintf( "bad signature: 0x%08x", $signature ); if ( _isSeekable($fh) ) { $errmsg .= sprintf( " at offset %d", $fh->tell() - SIGNATURE_LENGTH ); } $status = _formatError("$errmsg in file $fileName"); } return ( $status, $signature ); } # Utility method to make and open a temp file. # Will create $temp_dir if it doesn't exist. # Returns file handle and name: # # my ($fh, $name) = Archive::Zip::tempFile(); # my ($fh, $name) = Archive::Zip::tempFile('mytempdir'); # sub tempFile { my $dir = ( ref( $_[0] ) eq 'HASH' ) ? shift->{tempDir} : shift; my ( $fh, $filename ) = File::Temp::tempfile( SUFFIX => '.zip', UNLINK => 0, # we will delete it! $dir ? ( DIR => $dir ) : () ); return ( undef, undef ) unless $fh; my ( $status, $newfh ) = _newFileHandle( $fh, 'w+' ); return ( $newfh, $filename ); } # Return the normalized directory name as used in a zip file (path # separators become slashes, etc.). # Will translate internal slashes in path components (i.e. on Macs) to # underscores. Discards volume names. # When $forceDir is set, returns paths with trailing slashes (or arrays # with trailing blank members). # # If third argument is a reference, returns volume information there. # # input output # . ('.') '.' # ./a ('a') a # ./a/b ('a','b') a/b # ./a/b/ ('a','b') a/b # a/b/ ('a','b') a/b # /a/b/ ('','a','b') /a/b # c:\a\b\c.doc ('','a','b','c.doc') /a/b/c.doc # on Windoze # "i/o maps:whatever" ('i_o maps', 'whatever') "i_o maps/whatever" # on Macs sub _asZipDirName { my $name = shift; my $forceDir = shift; my $volReturn = shift; my ( $volume, $directories, $file ) = File::Spec->splitpath( File::Spec->canonpath($name), $forceDir ); $$volReturn = $volume if ( ref($volReturn) ); my @dirs = map { $_ =~ s{/}{_}g; $_ } File::Spec->splitdir($directories); if ( @dirs > 0 ) { pop (@dirs) unless $dirs[-1] } # remove empty component push ( @dirs, defined($file) ? $file : '' ); #return wantarray ? @dirs : join ( '/', @dirs ); return join ( '/', @dirs ); } # Return an absolute local name for a zip name. # Assume a directory if zip name has trailing slash. # Takes an optional volume name in FS format (like 'a:'). # sub _asLocalName { my $name = shift; # zip format my $volume = shift; $volume = '' unless defined($volume); # local FS format my @paths = split ( /\//, $name ); my $filename = pop (@paths); $filename = '' unless defined($filename); my $localDirs = @paths ? File::Spec->catdir(@paths) : ''; my $localName = File::Spec->catpath( $volume, $localDirs, $filename ); unless ( $volume ) { $localName = File::Spec->rel2abs( $localName, Cwd::getcwd() ); } return $localName; } 1; __END__ =pod =head1 NAME Archive::Zip - Provide an interface to ZIP archive files. =head1 SYNOPSIS # Create a Zip file use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); my $zip = Archive::Zip->new(); # Add a directory my $dir_member = $zip->addDirectory( 'dirname/' ); # Add a file from a string with compression my $string_member = $zip->addString( 'This is a test', 'stringMember.txt' ); $string_member->desiredCompressionMethod( COMPRESSION_DEFLATED ); # Add a file from disk my $file_member = $zip->addFile( 'xyz.pl', 'AnotherName.pl' ); # Save the Zip file unless ( $zip->writeToFileNamed('someZip.zip') == AZ_OK ) { die 'write error'; } # Read a Zip file my $somezip = Archive::Zip->new(); unless ( $somezip->read( 'someZip.zip' ) == AZ_OK ) { die 'read error'; } # Change the compression type for a file in the Zip my $member = $somezip->memberNamed( 'stringMember.txt' ); $member->desiredCompressionMethod( COMPRESSION_STORED ); unless ( $zip->writeToFileNamed( 'someOtherZip.zip' ) == AZ_OK ) { die 'write error'; } =head1 DESCRIPTION The Archive::Zip module allows a Perl program to create, manipulate, read, and write Zip archive files. Zip archives can be created, or you can read from existing zip files. Once created, they can be written to files, streams, or strings. Members can be added, removed, extracted, replaced, rearranged, and enumerated. They can also be renamed or have their dates, comments, or other attributes queried or modified. Their data can be compressed or uncompressed as needed. Members can be created from members in existing Zip files, or from existing directories, files, or strings. This module uses the L library to read and write the compressed streams inside the files. One can use L to read the zip file archive members as if they were files. =head2 File Naming Regardless of what your local file system uses for file naming, names in a Zip file are in Unix format (I slashes (/) separating directory names, etc.). C tries to be consistent with file naming conventions, and will translate back and forth between native and Zip file names. However, it can't guess which format names are in. So two rules control what kind of file name you must pass various routines: =over 4 =item Names of files are in local format. C and C are used for various file operations. When you're referring to a file on your system, use its file naming conventions. =item Names of archive members are in Unix format. This applies to every method that refers to an archive member, or provides a name for new archive members. The C methods that can take one or two names will convert from local to zip names if you call them with a single name. =back =head2 Archive::Zip Object Model =head2 Overview Archive::Zip::Archive objects are what you ordinarily deal with. These maintain the structure of a zip file, without necessarily holding data. When a zip is read from a disk file, the (possibly compressed) data still lives in the file, not in memory. Archive members hold information about the individual members, but not (usually) the actual member data. When the zip is written to a (different) file, the member data is compressed or copied as needed. It is possible to make archive members whose data is held in a string in memory, but this is not done when a zip file is read. Directory members don't have any data. =head2 Inheritance Exporter Archive::Zip Common base class, has defs. Archive::Zip::Archive A Zip archive. Archive::Zip::Member Abstract superclass for all members. Archive::Zip::StringMember Member made from a string Archive::Zip::FileMember Member made from an external file Archive::Zip::ZipFileMember Member that lives in a zip file Archive::Zip::NewFileMember Member whose data is in a file Archive::Zip::DirectoryMember Member that is a directory =head1 EXPORTS =over 4 =item :CONSTANTS Exports the following constants: FA_MSDOS FA_UNIX GPBF_ENCRYPTED_MASK GPBF_DEFLATING_COMPRESSION_MASK GPBF_HAS_DATA_DESCRIPTOR_MASK COMPRESSION_STORED COMPRESSION_DEFLATED IFA_TEXT_FILE_MASK IFA_TEXT_FILE IFA_BINARY_FILE COMPRESSION_LEVEL_NONE COMPRESSION_LEVEL_DEFAULT COMPRESSION_LEVEL_FASTEST COMPRESSION_LEVEL_BEST_COMPRESSION =item :MISC_CONSTANTS Exports the following constants (only necessary for extending the module): FA_AMIGA FA_VAX_VMS FA_VM_CMS FA_ATARI_ST FA_OS2_HPFS FA_MACINTOSH FA_Z_SYSTEM FA_CPM FA_WINDOWS_NTFS GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK GPBF_IS_COMPRESSED_PATCHED_DATA_MASK COMPRESSION_SHRUNK DEFLATING_COMPRESSION_NORMAL DEFLATING_COMPRESSION_MAXIMUM DEFLATING_COMPRESSION_FAST DEFLATING_COMPRESSION_SUPER_FAST COMPRESSION_REDUCED_1 COMPRESSION_REDUCED_2 COMPRESSION_REDUCED_3 COMPRESSION_REDUCED_4 COMPRESSION_IMPLODED COMPRESSION_TOKENIZED COMPRESSION_DEFLATED_ENHANCED COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED =item :ERROR_CODES Explained below. Returned from most methods. AZ_OK AZ_STREAM_END AZ_ERROR AZ_FORMAT_ERROR AZ_IO_ERROR =back =head1 ERROR CODES Many of the methods in Archive::Zip return error codes. These are implemented as inline subroutines, using the C pragma. They can be imported into your namespace using the C<:ERROR_CODES> tag: use Archive::Zip qw( :ERROR_CODES ); ... unless ( $zip->read( 'myfile.zip' ) == AZ_OK ) { die "whoops!"; } =over 4 =item AZ_OK (0) Everything is fine. =item AZ_STREAM_END (1) The read stream (or central directory) ended normally. =item AZ_ERROR (2) There was some generic kind of error. =item AZ_FORMAT_ERROR (3) There is a format error in a ZIP file being read. =item AZ_IO_ERROR (4) There was an IO error. =back =head2 Compression Archive::Zip allows each member of a ZIP file to be compressed (using the Deflate algorithm) or uncompressed. Other compression algorithms that some versions of ZIP have been able to produce are not supported. Each member has two compression methods: the one it's stored as (this is always COMPRESSION_STORED for string and external file members), and the one you desire for the member in the zip file. These can be different, of course, so you can make a zip member that is not compressed out of one that is, and vice versa. You can inquire about the current compression and set the desired compression method: my $member = $zip->memberNamed( 'xyz.txt' ); $member->compressionMethod(); # return current compression # set to read uncompressed $member->desiredCompressionMethod( COMPRESSION_STORED ); # set to read compressed $member->desiredCompressionMethod( COMPRESSION_DEFLATED ); There are two different compression methods: =over 4 =item COMPRESSION_STORED File is stored (no compression) =item COMPRESSION_DEFLATED File is Deflated =back =head2 Compression Levels If a member's desiredCompressionMethod is COMPRESSION_DEFLATED, you can choose different compression levels. This choice may affect the speed of compression and decompression, as well as the size of the compressed member data. $member->desiredCompressionLevel( 9 ); The levels given can be: =over 4 =item 0 or COMPRESSION_LEVEL_NONE This is the same as saying $member->desiredCompressionMethod( COMPRESSION_STORED ); =item 1 .. 9 1 gives the best speed and worst compression, and 9 gives the best compression and worst speed. =item COMPRESSION_LEVEL_FASTEST This is a synonym for level 1. =item COMPRESSION_LEVEL_BEST_COMPRESSION This is a synonym for level 9. =item COMPRESSION_LEVEL_DEFAULT This gives a good compromise between speed and compression, and is currently equivalent to 6 (this is in the zlib code). This is the level that will be used if not specified. =back =head1 Archive::Zip Methods The Archive::Zip class (and its invisible subclass Archive::Zip::Archive) implement generic zip file functionality. Creating a new Archive::Zip object actually makes an Archive::Zip::Archive object, but you don't have to worry about this unless you're subclassing. =head2 Constructor =over 4 =item new( [$fileName] ) Make a new, empty zip archive. my $zip = Archive::Zip->new(); If an additional argument is passed, new() will call read() to read the contents of an archive: my $zip = Archive::Zip->new( 'xyz.zip' ); If a filename argument is passed and the read fails for any reason, new will return undef. For this reason, it may be better to call read separately. =back =head2 Zip Archive Utility Methods These Archive::Zip methods may be called as functions or as object methods. Do not call them as class methods: $zip = Archive::Zip->new(); $crc = Archive::Zip::computeCRC32( 'ghijkl' ); # OK $crc = $zip->computeCRC32( 'ghijkl' ); # also OK $crc = Archive::Zip->computeCRC32( 'ghijkl' ); # NOT OK =over 4 =item Archive::Zip::computeCRC32( $string [, $crc] ) This is a utility function that uses the Compress::Raw::Zlib CRC routine to compute a CRC-32. You can get the CRC of a string: $crc = Archive::Zip::computeCRC32( $string ); Or you can compute the running CRC: $crc = 0; $crc = Archive::Zip::computeCRC32( 'abcdef', $crc ); $crc = Archive::Zip::computeCRC32( 'ghijkl', $crc ); =item Archive::Zip::setChunkSize( $number ) Report or change chunk size used for reading and writing. This can make big differences in dealing with large files. Currently, this defaults to 32K. This also changes the chunk size used for Compress::Raw::Zlib. You must call setChunkSize() before reading or writing. This is not exportable, so you must call it like: Archive::Zip::setChunkSize( 4096 ); or as a method on a zip (though this is a global setting). Returns old chunk size. =item Archive::Zip::chunkSize() Returns the current chunk size: my $chunkSize = Archive::Zip::chunkSize(); =item Archive::Zip::setErrorHandler( \&subroutine ) Change the subroutine called with error strings. This defaults to \&Carp::carp, but you may want to change it to get the error strings. This is not exportable, so you must call it like: Archive::Zip::setErrorHandler( \&myErrorHandler ); If myErrorHandler is undef, resets handler to default. Returns old error handler. Note that if you call Carp::carp or a similar routine or if you're chaining to the default error handler from your error handler, you may want to increment the number of caller levels that are skipped (do not just set it to a number): $Carp::CarpLevel++; =item Archive::Zip::tempFile( [$tmpdir] ) Create a uniquely named temp file. It will be returned open for read/write. If C<$tmpdir> is given, it is used as the name of a directory to create the file in. If not given, creates the file using C. Generally, you can override this choice using the $ENV{TMPDIR} environment variable. But see the L documentation for your system. Note that on many systems, if you're running in taint mode, then you must make sure that C<$ENV{TMPDIR}> is untainted for it to be used. Will I create C<$tmpdir> if it doesn't exist (this is a change from prior versions!). Returns file handle and name: my ($fh, $name) = Archive::Zip::tempFile(); my ($fh, $name) = Archive::Zip::tempFile('myTempDir'); my $fh = Archive::Zip::tempFile(); # if you don't need the name =back =head2 Zip Archive Accessors =over 4 =item members() Return a copy of the members array my @members = $zip->members(); =item numberOfMembers() Return the number of members I have =item memberNames() Return a list of the (internal) file names of the zip members =item memberNamed( $string ) Return ref to member whose filename equals given filename or undef. C<$string> must be in Zip (Unix) filename format. =item membersMatching( $regex ) Return array of members whose filenames match given regular expression in list context. Returns number of matching members in scalar context. my @textFileMembers = $zip->membersMatching( '.*\.txt' ); # or my $numberOfTextFiles = $zip->membersMatching( '.*\.txt' ); =item diskNumber() Return the disk that I start on. Not used for writing zips, but might be interesting if you read a zip in. This should be 0, as Archive::Zip does not handle multi-volume archives. =item diskNumberWithStartOfCentralDirectory() Return the disk number that holds the beginning of the central directory. Not used for writing zips, but might be interesting if you read a zip in. This should be 0, as Archive::Zip does not handle multi-volume archives. =item numberOfCentralDirectoriesOnThisDisk() Return the number of CD structures in the zipfile last read in. Not used for writing zips, but might be interesting if you read a zip in. =item numberOfCentralDirectories() Return the number of CD structures in the zipfile last read in. Not used for writing zips, but might be interesting if you read a zip in. =item centralDirectorySize() Returns central directory size, as read from an external zip file. Not used for writing zips, but might be interesting if you read a zip in. =item centralDirectoryOffsetWRTStartingDiskNumber() Returns the offset into the zip file where the CD begins. Not used for writing zips, but might be interesting if you read a zip in. =item zipfileComment( [$string] ) Get or set the zipfile comment. Returns the old comment. print $zip->zipfileComment(); $zip->zipfileComment( 'New Comment' ); =item eocdOffset() Returns the (unexpected) number of bytes between where the EOCD was found and where it expected to be. This is normally 0, but would be positive if something (a virus, perhaps) had added bytes somewhere before the EOCD. Not used for writing zips, but might be interesting if you read a zip in. Here is an example of how you can diagnose this: my $zip = Archive::Zip->new('somefile.zip'); if ($zip->eocdOffset()) { warn "A virus has added ", $zip->eocdOffset, " bytes of garbage\n"; } The C is used to adjust the starting position of member headers, if necessary. =item fileName() Returns the name of the file last read from. If nothing has been read yet, returns an empty string; if read from a file handle, returns the handle in string form. =back =head2 Zip Archive Member Operations Various operations on a zip file modify members. When a member is passed as an argument, you can either use a reference to the member itself, or the name of a member. Of course, using the name requires that names be unique within a zip (this is not enforced). =over 4 =item removeMember( $memberOrName ) Remove and return the given member, or match its name and remove it. Returns undef if member or name doesn't exist in this Zip. No-op if member does not belong to this zip. =item replaceMember( $memberOrName, $newMember ) Remove and return the given member, or match its name and remove it. Replace with new member. Returns undef if member or name doesn't exist in this Zip, or if C<$newMember> is undefined. It is an (undiagnosed) error to provide a C<$newMember> that is a member of the zip being modified. my $member1 = $zip->removeMember( 'xyz' ); my $member2 = $zip->replaceMember( 'abc', $member1 ); # now, $member2 (named 'abc') is not in $zip, # and $member1 (named 'xyz') is, having taken $member2's place. =item extractMember( $memberOrName [, $extractedName ] ) Extract the given member, or match its name and extract it. Returns undef if member doesn't exist in this Zip. If optional second arg is given, use it as the name of the extracted member. Otherwise, the internal filename of the member is used as the name of the extracted file or directory. If you pass C<$extractedName>, it should be in the local file system's format. All necessary directories will be created. Returns C on success. =item extractMemberWithoutPaths( $memberOrName [, $extractedName ] ) Extract the given member, or match its name and extract it. Does not use path information (extracts into the current directory). Returns undef if member doesn't exist in this Zip. If optional second arg is given, use it as the name of the extracted member (its paths will be deleted too). Otherwise, the internal filename of the member (minus paths) is used as the name of the extracted file or directory. Returns C on success. =item addMember( $member ) Append a member (possibly from another zip file) to the zip file. Returns the new member. Generally, you will use addFile(), addDirectory(), addFileOrDirectory(), addString(), or read() to add members. # Move member named 'abc' to end of zip: my $member = $zip->removeMember( 'abc' ); $zip->addMember( $member ); =item updateMember( $memberOrName, $fileName ) Update a single member from the file or directory named C<$fileName>. Returns the (possibly added or updated) member, if any; C on errors. The comparison is based on C and (in the case of a non-directory) the size of the file. =item addFile( $fileName [, $newName ] ) Append a member whose data comes from an external file, returning the member or undef. The member will have its file name set to the name of the external file, and its desiredCompressionMethod set to COMPRESSION_DEFLATED. The file attributes and last modification time will be set from the file. If the name given does not represent a readable plain file or symbolic link, undef will be returned. C<$fileName> must be in the format required for the local file system. The optional C<$newName> argument sets the internal file name to something different than the given $fileName. C<$newName>, if given, must be in Zip name format (i.e. Unix). The text mode bit will be set if the contents appears to be text (as returned by the C<-T> perl operator). I that you shouldn't (generally) use absolute path names in zip member names, as this will cause problems with some zip tools as well as introduce a security hole and make the zip harder to use. =item addDirectory( $directoryName [, $fileName ] ) Append a member created from the given directory name. The directory name does not have to name an existing directory. If the named directory exists, the file modification time and permissions are set from the existing directory, otherwise they are set to now and permissive default permissions. C<$directoryName> must be in local file system format. The optional second argument sets the name of the archive member (which defaults to C<$directoryName>). If given, it must be in Zip (Unix) format. Returns the new member. =item addFileOrDirectory( $name [, $newName ] ) Append a member from the file or directory named $name. If $newName is given, use it for the name of the new member. Will add or remove trailing slashes from $newName as needed. C<$name> must be in local file system format. The optional second argument sets the name of the archive member (which defaults to C<$name>). If given, it must be in Zip (Unix) format. =item addString( $stringOrStringRef, $name ) Append a member created from the given string or string reference. The name is given by the second argument. Returns the new member. The last modification time will be set to now, and the file attributes will be set to permissive defaults. my $member = $zip->addString( 'This is a test', 'test.txt' ); =item contents( $memberOrMemberName [, $newContents ] ) Returns the uncompressed data for a particular member, or undef. print "xyz.txt contains " . $zip->contents( 'xyz.txt' ); Also can change the contents of a member: $zip->contents( 'xyz.txt', 'This is the new contents' ); If called expecting an array as the return value, it will include the status as the second value in the array. ($content, $status) = $zip->contents( 'xyz.txt'); =back =head2 Zip Archive I/O operations A Zip archive can be written to a file or file handle, or read from one. =over 4 =item writeToFileNamed( $fileName ) Write a zip archive to named file. Returns C on success. my $status = $zip->writeToFileNamed( 'xx.zip' ); die "error somewhere" if $status != AZ_OK; Note that if you use the same name as an existing zip file that you read in, you will clobber ZipFileMembers. So instead, write to a different file name, then delete the original. If you use the C or C methods, you can re-write the original zip in this way. C<$fileName> should be a valid file name on your system. =item writeToFileHandle( $fileHandle [, $seekable] ) Write a zip archive to a file handle. Return AZ_OK on success. The optional second arg tells whether or not to try to seek backwards to re-write headers. If not provided, it is set if the Perl C<-f> test returns true. This could fail on some operating systems, though. my $fh = IO::File->new( 'someFile.zip', 'w' ); unless ( $zip->writeToFileHandle( $fh ) == AZ_OK ) { # error handling } If you pass a file handle that is not seekable (like if you're writing to a pipe or a socket), pass a false second argument: my $fh = IO::File->new( '| cat > somefile.zip', 'w' ); $zip->writeToFileHandle( $fh, 0 ); # fh is not seekable If this method fails during the write of a member, that member and all following it will return false from C. See writeCentralDirectory() for a way to deal with this. If you want, you can write data to the file handle before passing it to writeToFileHandle(); this could be used (for instance) for making self-extracting archives. However, this only works reliably when writing to a real file (as opposed to STDOUT or some other possible non-file). See examples/selfex.pl for how to write a self-extracting archive. =item writeCentralDirectory( $fileHandle [, $offset ] ) Writes the central directory structure to the given file handle. Returns AZ_OK on success. If given an $offset, will seek to that point before writing. This can be used for recovery in cases where writeToFileHandle or writeToFileNamed returns an IO error because of running out of space on the destination file. You can truncate the zip by seeking backwards and then writing the directory: my $fh = IO::File->new( 'someFile.zip', 'w' ); my $retval = $zip->writeToFileHandle( $fh ); if ( $retval == AZ_IO_ERROR ) { my @unwritten = grep { not $_->wasWritten() } $zip->members(); if (@unwritten) { $zip->removeMember( $member ) foreach my $member ( @unwritten ); $zip->writeCentralDirectory( $fh, $unwritten[0]->writeLocalHeaderRelativeOffset()); } } =item overwriteAs( $newName ) Write the zip to the specified file, as safely as possible. This is done by first writing to a temp file, then renaming the original if it exists, then renaming the temp file, then deleting the renamed original if it exists. Returns AZ_OK if successful. =item overwrite() Write back to the original zip file. See overwriteAs() above. If the zip was not ever read from a file, this generates an error. =item read( $fileName ) Read zipfile headers from a zip file, appending new members. Returns C or error code. my $zipFile = Archive::Zip->new(); my $status = $zipFile->read( '/some/FileName.zip' ); =item readFromFileHandle( $fileHandle, $filename ) Read zipfile headers from an already-opened file handle, appending new members. Does not close the file handle. Returns C or error code. Note that this requires a seekable file handle; reading from a stream is not yet supported. my $fh = IO::File->new( '/some/FileName.zip', 'r' ); my $zip1 = Archive::Zip->new(); my $status = $zip1->readFromFileHandle( $fh ); my $zip2 = Archive::Zip->new(); $status = $zip2->readFromFileHandle( $fh ); =back =head2 Zip Archive Tree operations These used to be in Archive::Zip::Tree but got moved into Archive::Zip. They enable operation on an entire tree of members or files. A usage example: use Archive::Zip; my $zip = Archive::Zip->new(); # add all readable files and directories below . as xyz/* $zip->addTree( '.', 'xyz' ); # add all readable plain files below /abc as def/* $zip->addTree( '/abc', 'def', sub { -f && -r } ); # add all .c files below /tmp as stuff/* $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' ); # add all .o files below /tmp as stuff/* if they aren't writable $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } ); # add all .so files below /tmp that are smaller than 200 bytes as stuff/* $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { -s < 200 } ); # and write them into a file $zip->writeToFileNamed('xxx.zip'); # now extract the same files into /tmpx $zip->extractTree( 'stuff', '/tmpx' ); =over 4 =item $zip->addTree( $root, $dest [,$pred] ) -- Add tree of files to a zip C<$root> is the root of the tree of files and directories to be added. It is a valid directory name on your system. C<$dest> is the name for the root in the zip file (undef or blank means to use relative pathnames). It is a valid ZIP directory name (that is, it uses forward slashes (/) for separating directory components). C<$pred> is an optional subroutine reference to select files: it is passed the name of the prospective file or directory using C<$_>, and if it returns true, the file or directory will be included. The default is to add all readable files and directories. For instance, using my $pred = sub { /\.txt/ }; $zip->addTree( '.', '', $pred ); will add all the .txt files in and below the current directory, using relative names, and making the names identical in the zipfile: original name zip member name ./xyz xyz ./a/ a/ ./a/b a/b To translate absolute to relative pathnames, just pass them in: $zip->addTree( '/c/d', 'a' ); original name zip member name /c/d/xyz a/xyz /c/d/a/ a/a/ /c/d/a/b a/a/b Returns AZ_OK on success. Note that this will not follow symbolic links to directories. Note also that this does not check for the validity of filenames. Note that you generally I want to make zip archive member names absolute. =item $zip->addTreeMatching( $root, $dest, $pattern [,$pred] ) $root is the root of the tree of files and directories to be added $dest is the name for the root in the zip file (undef means to use relative pathnames) $pattern is a (non-anchored) regular expression for filenames to match $pred is an optional subroutine reference to select files: it is passed the name of the prospective file or directory in C<$_>, and if it returns true, the file or directory will be included. The default is to add all readable files and directories. To add all files in and below the current dirctory whose names end in C<.pl>, and make them extract into a subdirectory named C, do this: $zip->addTreeMatching( '.', 'xyz', '\.pl$' ) To add all I files in and below the dirctory named C whose names end in C<.pl>, and make them extract into a subdirectory named C, do this: $zip->addTreeMatching( '/abc', 'xyz', '\.pl$', sub { -w } ) Returns AZ_OK on success. Note that this will not follow symbolic links to directories. =item $zip->updateTree( $root, [ $dest, [ $pred [, $mirror]]] ); Update a zip file from a directory tree. C takes the same arguments as C, but first checks to see whether the file or directory already exists in the zip file, and whether it has been changed. If the fourth argument C<$mirror> is true, then delete all my members if corresponding files weren't found. Returns an error code or AZ_OK if all is well. =item $zip->extractTree() =item $zip->extractTree( $root ) =item $zip->extractTree( $root, $dest ) =item $zip->extractTree( $root, $dest, $volume ) If you don't give any arguments at all, will extract all the files in the zip with their original names. If you supply one argument for C<$root>, C will extract all the members whose names start with C<$root> into the current directory, stripping off C<$root> first. C<$root> is in Zip (Unix) format. For instance, $zip->extractTree( 'a' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x as ./x a/b/c as ./b/c If you give two arguments, C extracts all the members whose names start with C<$root>. It will translate C<$root> into C<$dest> to construct the destination file name. C<$root> and C<$dest> are in Zip (Unix) format. For instance, $zip->extractTree( 'a', 'd/e' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x to d/e/x a/b/c to d/e/b/c and ignore ax/d/e and d/e If you give three arguments, C extracts all the members whose names start with C<$root>. It will translate C<$root> into C<$dest> to construct the destination file name, and then it will convert to local file system format, using C<$volume> as the name of the destination volume. C<$root> and C<$dest> are in Zip (Unix) format. C<$volume> is in local file system format. For instance, under Windows, $zip->extractTree( 'a', 'd/e', 'f:' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x to f:d/e/x a/b/c to f:d/e/b/c and ignore ax/d/e and d/e If you want absolute paths (the prior example used paths relative to the current directory on the destination volume, you can specify these in C<$dest>: $zip->extractTree( 'a', '/d/e', 'f:' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x to f:\d\e\x a/b/c to f:\d\e\b\c and ignore ax/d/e and d/e Returns an error code or AZ_OK if everything worked OK. =back =head1 MEMBER OPERATIONS =head2 Member Class Methods Several constructors allow you to construct members without adding them to a zip archive. These work the same as the addFile(), addDirectory(), and addString() zip instance methods described above, but they don't add the new members to a zip. =over 4 =item Archive::Zip::Member->newFromString( $stringOrStringRef [, $fileName] ) Construct a new member from the given string. Returns undef on error. my $member = Archive::Zip::Member->newFromString( 'This is a test', 'xyz.txt' ); =item newFromFile( $fileName ) Construct a new member from the given file. Returns undef on error. my $member = Archive::Zip::Member->newFromFile( 'xyz.txt' ); =item newDirectoryNamed( $directoryName [, $zipname ] ) Construct a new member from the given directory. C<$directoryName> must be a valid name on your file system; it doesn't have to exist. If given, C<$zipname> will be the name of the zip member; it must be a valid Zip (Unix) name. If not given, it will be converted from C<$directoryName>. Returns undef on error. my $member = Archive::Zip::Member->newDirectoryNamed( 'CVS/' ); =back =head2 Member Simple accessors These methods get (and/or set) member attribute values. =over 4 =item versionMadeBy() Gets the field from the member header. =item fileAttributeFormat( [$format] ) Gets or sets the field from the member header. These are C values. =item versionNeededToExtract() Gets the field from the member header. =item bitFlag() Gets the general purpose bit field from the member header. This is where the C bits live. =item compressionMethod() Returns the member compression method. This is the method that is currently being used to compress the member data. This will be COMPRESSION_STORED for added string or file members, or any of the C values for members from a zip file. However, this module can only handle members whose data is in COMPRESSION_STORED or COMPRESSION_DEFLATED format. =item desiredCompressionMethod( [$method] ) Get or set the member's C. This is the compression method that will be used when the member is written. Returns prior desiredCompressionMethod. Only COMPRESSION_DEFLATED or COMPRESSION_STORED are valid arguments. Changing to COMPRESSION_STORED will change the member desiredCompressionLevel to 0; changing to COMPRESSION_DEFLATED will change the member desiredCompressionLevel to COMPRESSION_LEVEL_DEFAULT. =item desiredCompressionLevel( [$method] ) Get or set the member's desiredCompressionLevel This is the method that will be used to write. Returns prior desiredCompressionLevel. Valid arguments are 0 through 9, COMPRESSION_LEVEL_NONE, COMPRESSION_LEVEL_DEFAULT, COMPRESSION_LEVEL_BEST_COMPRESSION, and COMPRESSION_LEVEL_FASTEST. 0 or COMPRESSION_LEVEL_NONE will change the desiredCompressionMethod to COMPRESSION_STORED. All other arguments will change the desiredCompressionMethod to COMPRESSION_DEFLATED. =item externalFileName() Return the member's external file name, if any, or undef. =item fileName() Get or set the member's internal filename. Returns the (possibly new) filename. Names will have backslashes converted to forward slashes, and will have multiple consecutive slashes converted to single ones. =item lastModFileDateTime() Return the member's last modification date/time stamp in MS-DOS format. =item lastModTime() Return the member's last modification date/time stamp, converted to unix localtime format. print "Mod Time: " . scalar( localtime( $member->lastModTime() ) ); =item setLastModFileDateTimeFromUnix() Set the member's lastModFileDateTime from the given unix time. $member->setLastModFileDateTimeFromUnix( time() ); =item internalFileAttributes() Return the internal file attributes field from the zip header. This is only set for members read from a zip file. =item externalFileAttributes() Return member attributes as read from the ZIP file. Note that these are NOT UNIX! =item unixFileAttributes( [$newAttributes] ) Get or set the member's file attributes using UNIX file attributes. Returns old attributes. my $oldAttribs = $member->unixFileAttributes( 0666 ); Note that the return value has more than just the file permissions, so you will have to mask off the lowest bits for comparisions. =item localExtraField( [$newField] ) Gets or sets the extra field that was read from the local header. This is not set for a member from a zip file until after the member has been written out. The extra field must be in the proper format. =item cdExtraField( [$newField] ) Gets or sets the extra field that was read from the central directory header. The extra field must be in the proper format. =item extraFields() Return both local and CD extra fields, concatenated. =item fileComment( [$newComment] ) Get or set the member's file comment. =item hasDataDescriptor() Get or set the data descriptor flag. If this is set, the local header will not necessarily have the correct data sizes. Instead, a small structure will be stored at the end of the member data with these values. This should be transparent in normal operation. =item crc32() Return the CRC-32 value for this member. This will not be set for members that were constructed from strings or external files until after the member has been written. =item crc32String() Return the CRC-32 value for this member as an 8 character printable hex string. This will not be set for members that were constructed from strings or external files until after the member has been written. =item compressedSize() Return the compressed size for this member. This will not be set for members that were constructed from strings or external files until after the member has been written. =item uncompressedSize() Return the uncompressed size for this member. =item isEncrypted() Return true if this member is encrypted. The Archive::Zip module does not currently create or extract encrypted members. =item isTextFile( [$flag] ) Returns true if I am a text file. Also can set the status if given an argument (then returns old state). Note that this module does not currently do anything with this flag upon extraction or storage. That is, bytes are stored in native format whether or not they came from a text file. =item isBinaryFile() Returns true if I am a binary file. Also can set the status if given an argument (then returns old state). Note that this module does not currently do anything with this flag upon extraction or storage. That is, bytes are stored in native format whether or not they came from a text file. =item extractToFileNamed( $fileName ) Extract me to a file with the given name. The file will be created with default modes. Directories will be created as needed. The C<$fileName> argument should be a valid file name on your file system. Returns AZ_OK on success. =item isDirectory() Returns true if I am a directory. =item writeLocalHeaderRelativeOffset() Returns the file offset in bytes the last time I was written. =item wasWritten() Returns true if I was successfully written. Reset at the beginning of a write attempt. =back =head2 Low-level member data reading It is possible to use lower-level routines to access member data streams, rather than the extract* methods and contents(). For instance, here is how to print the uncompressed contents of a member in chunks using these methods: my ( $member, $status, $bufferRef ); $member = $zip->memberNamed( 'xyz.txt' ); $member->desiredCompressionMethod( COMPRESSION_STORED ); $status = $member->rewindData(); die "error $status" unless $status == AZ_OK; while ( ! $member->readIsDone() ) { ( $bufferRef, $status ) = $member->readChunk(); die "error $status" if $status != AZ_OK && $status != AZ_STREAM_END; # do something with $bufferRef: print $$bufferRef; } $member->endRead(); =over 4 =item readChunk( [$chunkSize] ) This reads the next chunk of given size from the member's data stream and compresses or uncompresses it as necessary, returning a reference to the bytes read and a status. If size argument is not given, defaults to global set by Archive::Zip::setChunkSize. Status is AZ_OK on success until the last chunk, where it returns AZ_STREAM_END. Returns C<( \$bytes, $status)>. my ( $outRef, $status ) = $self->readChunk(); print $$outRef if $status != AZ_OK && $status != AZ_STREAM_END; =item rewindData() Rewind data and set up for reading data streams or writing zip files. Can take options for C or C, but this isn't likely to be necessary. Subclass overrides should call this method. Returns C on success. =item endRead() Reset the read variables and free the inflater or deflater. Must be called to close files, etc. Returns AZ_OK on success. =item readIsDone() Return true if the read has run out of data or errored out. =item contents() Return the entire uncompressed member data or undef in scalar context. When called in array context, returns C<( $string, $status )>; status will be AZ_OK on success: my $string = $member->contents(); # or my ( $string, $status ) = $member->contents(); die "error $status" unless $status == AZ_OK; Can also be used to set the contents of a member (this may change the class of the member): $member->contents( "this is my new contents" ); =item extractToFileHandle( $fh ) Extract (and uncompress, if necessary) the member's contents to the given file handle. Return AZ_OK on success. =back =head1 Archive::Zip::FileMember methods The Archive::Zip::FileMember class extends Archive::Zip::Member. It is the base class for both ZipFileMember and NewFileMember classes. This class adds an C and an C member to keep track of the external file. =over 4 =item externalFileName() Return the member's external filename. =item fh() Return the member's read file handle. Automatically opens file if necessary. =back =head1 Archive::Zip::ZipFileMember methods The Archive::Zip::ZipFileMember class represents members that have been read from external zip files. =over 4 =item diskNumberStart() Returns the disk number that the member's local header resides in. Should be 0. =item localHeaderRelativeOffset() Returns the offset into the zip file where the member's local header is. =item dataOffset() Returns the offset from the beginning of the zip file to the member's data. =back =head1 REQUIRED MODULES L requires several other modules: L L L L L L L L L L L =head1 BUGS AND CAVEATS =head2 When not to use Archive::Zip If you are just going to be extracting zips (and/or other archives) you are recommended to look at using L instead, as it is much easier to use and factors out archive-specific functionality. =head2 Try to avoid IO::Scalar One of the most common ways to use Archive::Zip is to generate Zip files in-memory. Most people have use L for this purpose. Unfortunately, as of 1.11 this module no longer works with L as it incorrectly implements seeking. Anybody using L should consider porting to L, which is smaller, lighter, and is implemented to be perfectly compatible with regular seekable filehandles. Support for L most likely will B be restored in the future, as L itself cannot change the way it is implemented due to back-compatibility issues. =head1 TO DO * auto-choosing storing vs compression * extra field hooks (see notes.txt) * check for dups on addition/renaming? * Text file extraction (line end translation) * Reading zip files from non-seekable inputs (Perhaps by proxying through IO::String?) * separate unused constants into separate module * cookbook style docs * Handle tainted paths correctly * Work on better compatability with other IO:: modules =head1 SUPPORT Bugs should be reported via the CPAN bug tracker L For other issues contact the maintainer =head1 AUTHOR Adam Kennedy Eadamk@cpan.orgE Previously maintained by Steve Peters Esteve@fisharerojo.orgE. File attributes code by Maurice Aubrey Emaurice@lovelyfilth.comE. Originally by Ned Konz Enedkonz@cpan.orgE. =head1 COPYRIGHT Some parts copyright 2006 - 2009 Adam Kennedy. Some parts copyright 2005 Steve Peters. Original work copyright 2000 - 2004 Ned Konz. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO Look at L which is a wrapper that allows one to read Zip archive members as if they were files. L, L, L There is a Japanese translation of this document at L that was done by DEQ Edeq@oct.zaq.ne.jpE . Thanks! =cut gdata/inst/perl/Archive/Zip/0000755000176000001440000000000012164457166015440 5ustar ripleyusersgdata/inst/perl/Archive/Zip/ZipFileMember.pm0000644000176000001440000003233311337525116020464 0ustar ripleyuserspackage Archive::Zip::ZipFileMember; use strict; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw ( Archive::Zip::FileMember ); } use Archive::Zip qw( :CONSTANTS :ERROR_CODES :PKZIP_CONSTANTS :UTILITY_METHODS ); # Create a new Archive::Zip::ZipFileMember # given a filename and optional open file handle # sub _newFromZipFile { my $class = shift; my $fh = shift; my $externalFileName = shift; my $possibleEocdOffset = shift; # normally 0 my $self = $class->new( 'crc32' => 0, 'diskNumberStart' => 0, 'localHeaderRelativeOffset' => 0, 'dataOffset' => 0, # localHeaderRelativeOffset + header length @_ ); $self->{'externalFileName'} = $externalFileName; $self->{'fh'} = $fh; $self->{'possibleEocdOffset'} = $possibleEocdOffset; return $self; } sub isDirectory { my $self = shift; return ( substr( $self->fileName, -1, 1 ) eq '/' and $self->uncompressedSize == 0 ); } # Seek to the beginning of the local header, just past the signature. # Verify that the local header signature is in fact correct. # Update the localHeaderRelativeOffset if necessary by adding the possibleEocdOffset. # Returns status. sub _seekToLocalHeader { my $self = shift; my $where = shift; # optional my $previousWhere = shift; # optional $where = $self->localHeaderRelativeOffset() unless defined($where); # avoid loop on certain corrupt files (from Julian Field) return _formatError("corrupt zip file") if defined($previousWhere) && $where == $previousWhere; my $status; my $signature; $status = $self->fh()->seek( $where, IO::Seekable::SEEK_SET ); return _ioError("seeking to local header") unless $status; ( $status, $signature ) = _readSignature( $self->fh(), $self->externalFileName(), LOCAL_FILE_HEADER_SIGNATURE ); return $status if $status == AZ_IO_ERROR; # retry with EOCD offset if any was given. if ( $status == AZ_FORMAT_ERROR && $self->{'possibleEocdOffset'} ) { $status = $self->_seekToLocalHeader( $self->localHeaderRelativeOffset() + $self->{'possibleEocdOffset'}, $where ); if ( $status == AZ_OK ) { $self->{'localHeaderRelativeOffset'} += $self->{'possibleEocdOffset'}; $self->{'possibleEocdOffset'} = 0; } } return $status; } # Because I'm going to delete the file handle, read the local file # header if the file handle is seekable. If it isn't, I assume that # I've already read the local header. # Return ( $status, $self ) sub _become { my $self = shift; my $newClass = shift; return $self if ref($self) eq $newClass; my $status = AZ_OK; if ( _isSeekable( $self->fh() ) ) { my $here = $self->fh()->tell(); $status = $self->_seekToLocalHeader(); $status = $self->_readLocalFileHeader() if $status == AZ_OK; $self->fh()->seek( $here, IO::Seekable::SEEK_SET ); return $status unless $status == AZ_OK; } delete( $self->{'eocdCrc32'} ); delete( $self->{'diskNumberStart'} ); delete( $self->{'localHeaderRelativeOffset'} ); delete( $self->{'dataOffset'} ); return $self->SUPER::_become($newClass); } sub diskNumberStart { shift->{'diskNumberStart'}; } sub localHeaderRelativeOffset { shift->{'localHeaderRelativeOffset'}; } sub dataOffset { shift->{'dataOffset'}; } # Skip local file header, updating only extra field stuff. # Assumes that fh is positioned before signature. sub _skipLocalFileHeader { my $self = shift; my $header; my $bytesRead = $self->fh()->read( $header, LOCAL_FILE_HEADER_LENGTH ); if ( $bytesRead != LOCAL_FILE_HEADER_LENGTH ) { return _ioError("reading local file header"); } my $fileNameLength; my $extraFieldLength; my $bitFlag; ( undef, # $self->{'versionNeededToExtract'}, $bitFlag, undef, # $self->{'compressionMethod'}, undef, # $self->{'lastModFileDateTime'}, undef, # $crc32, undef, # $compressedSize, undef, # $uncompressedSize, $fileNameLength, $extraFieldLength ) = unpack( LOCAL_FILE_HEADER_FORMAT, $header ); if ($fileNameLength) { $self->fh()->seek( $fileNameLength, IO::Seekable::SEEK_CUR ) or return _ioError("skipping local file name"); } if ($extraFieldLength) { $bytesRead = $self->fh()->read( $self->{'localExtraField'}, $extraFieldLength ); if ( $bytesRead != $extraFieldLength ) { return _ioError("reading local extra field"); } } $self->{'dataOffset'} = $self->fh()->tell(); if ( $bitFlag & GPBF_HAS_DATA_DESCRIPTOR_MASK ) { # Read the crc32, compressedSize, and uncompressedSize from the # extended data descriptor, which directly follows the compressed data. # # Skip over the compressed file data (assumes that EOCD compressedSize # was correct) $self->fh()->seek( $self->{'compressedSize'}, IO::Seekable::SEEK_CUR ) or return _ioError("seeking to extended local header"); # these values should be set correctly from before. my $oldCrc32 = $self->{'eocdCrc32'}; my $oldCompressedSize = $self->{'compressedSize'}; my $oldUncompressedSize = $self->{'uncompressedSize'}; my $status = $self->_readDataDescriptor(); return $status unless $status == AZ_OK; return _formatError( "CRC or size mismatch while skipping data descriptor") if ( $oldCrc32 != $self->{'crc32'} || $oldUncompressedSize != $self->{'uncompressedSize'} ); } return AZ_OK; } # Read from a local file header into myself. Returns AZ_OK if successful. # Assumes that fh is positioned after signature. # Note that crc32, compressedSize, and uncompressedSize will be 0 if # GPBF_HAS_DATA_DESCRIPTOR_MASK is set in the bitFlag. sub _readLocalFileHeader { my $self = shift; my $header; my $bytesRead = $self->fh()->read( $header, LOCAL_FILE_HEADER_LENGTH ); if ( $bytesRead != LOCAL_FILE_HEADER_LENGTH ) { return _ioError("reading local file header"); } my $fileNameLength; my $crc32; my $compressedSize; my $uncompressedSize; my $extraFieldLength; ( $self->{'versionNeededToExtract'}, $self->{'bitFlag'}, $self->{'compressionMethod'}, $self->{'lastModFileDateTime'}, $crc32, $compressedSize, $uncompressedSize, $fileNameLength, $extraFieldLength ) = unpack( LOCAL_FILE_HEADER_FORMAT, $header ); if ($fileNameLength) { my $fileName; $bytesRead = $self->fh()->read( $fileName, $fileNameLength ); if ( $bytesRead != $fileNameLength ) { return _ioError("reading local file name"); } $self->fileName($fileName); } if ($extraFieldLength) { $bytesRead = $self->fh()->read( $self->{'localExtraField'}, $extraFieldLength ); if ( $bytesRead != $extraFieldLength ) { return _ioError("reading local extra field"); } } $self->{'dataOffset'} = $self->fh()->tell(); if ( $self->hasDataDescriptor() ) { # Read the crc32, compressedSize, and uncompressedSize from the # extended data descriptor. # Skip over the compressed file data (assumes that EOCD compressedSize # was correct) $self->fh()->seek( $self->{'compressedSize'}, IO::Seekable::SEEK_CUR ) or return _ioError("seeking to extended local header"); my $status = $self->_readDataDescriptor(); return $status unless $status == AZ_OK; } else { return _formatError( "CRC or size mismatch after reading data descriptor") if ( $self->{'crc32'} != $crc32 || $self->{'uncompressedSize'} != $uncompressedSize ); } return AZ_OK; } # This will read the data descriptor, which is after the end of compressed file # data in members that that have GPBF_HAS_DATA_DESCRIPTOR_MASK set in their # bitFlag. # The only reliable way to find these is to rely on the EOCD compressedSize. # Assumes that file is positioned immediately after the compressed data. # Returns status; sets crc32, compressedSize, and uncompressedSize. sub _readDataDescriptor { my $self = shift; my $signatureData; my $header; my $crc32; my $compressedSize; my $uncompressedSize; my $bytesRead = $self->fh()->read( $signatureData, SIGNATURE_LENGTH ); return _ioError("reading header signature") if $bytesRead != SIGNATURE_LENGTH; my $signature = unpack( SIGNATURE_FORMAT, $signatureData ); # unfortunately, the signature appears to be optional. if ( $signature == DATA_DESCRIPTOR_SIGNATURE && ( $signature != $self->{'crc32'} ) ) { $bytesRead = $self->fh()->read( $header, DATA_DESCRIPTOR_LENGTH ); return _ioError("reading data descriptor") if $bytesRead != DATA_DESCRIPTOR_LENGTH; ( $crc32, $compressedSize, $uncompressedSize ) = unpack( DATA_DESCRIPTOR_FORMAT, $header ); } else { $bytesRead = $self->fh()->read( $header, DATA_DESCRIPTOR_LENGTH_NO_SIG ); return _ioError("reading data descriptor") if $bytesRead != DATA_DESCRIPTOR_LENGTH_NO_SIG; $crc32 = $signature; ( $compressedSize, $uncompressedSize ) = unpack( DATA_DESCRIPTOR_FORMAT_NO_SIG, $header ); } $self->{'eocdCrc32'} = $self->{'crc32'} unless defined( $self->{'eocdCrc32'} ); $self->{'crc32'} = $crc32; $self->{'compressedSize'} = $compressedSize; $self->{'uncompressedSize'} = $uncompressedSize; return AZ_OK; } # Read a Central Directory header. Return AZ_OK on success. # Assumes that fh is positioned right after the signature. sub _readCentralDirectoryFileHeader { my $self = shift; my $fh = $self->fh(); my $header = ''; my $bytesRead = $fh->read( $header, CENTRAL_DIRECTORY_FILE_HEADER_LENGTH ); if ( $bytesRead != CENTRAL_DIRECTORY_FILE_HEADER_LENGTH ) { return _ioError("reading central dir header"); } my ( $fileNameLength, $extraFieldLength, $fileCommentLength ); ( $self->{'versionMadeBy'}, $self->{'fileAttributeFormat'}, $self->{'versionNeededToExtract'}, $self->{'bitFlag'}, $self->{'compressionMethod'}, $self->{'lastModFileDateTime'}, $self->{'crc32'}, $self->{'compressedSize'}, $self->{'uncompressedSize'}, $fileNameLength, $extraFieldLength, $fileCommentLength, $self->{'diskNumberStart'}, $self->{'internalFileAttributes'}, $self->{'externalFileAttributes'}, $self->{'localHeaderRelativeOffset'} ) = unpack( CENTRAL_DIRECTORY_FILE_HEADER_FORMAT, $header ); $self->{'eocdCrc32'} = $self->{'crc32'}; if ($fileNameLength) { $bytesRead = $fh->read( $self->{'fileName'}, $fileNameLength ); if ( $bytesRead != $fileNameLength ) { _ioError("reading central dir filename"); } } if ($extraFieldLength) { $bytesRead = $fh->read( $self->{'cdExtraField'}, $extraFieldLength ); if ( $bytesRead != $extraFieldLength ) { return _ioError("reading central dir extra field"); } } if ($fileCommentLength) { $bytesRead = $fh->read( $self->{'fileComment'}, $fileCommentLength ); if ( $bytesRead != $fileCommentLength ) { return _ioError("reading central dir file comment"); } } # NK 10/21/04: added to avoid problems with manipulated headers if ( $self->{'uncompressedSize'} != $self->{'compressedSize'} and $self->{'compressionMethod'} == COMPRESSION_STORED ) { $self->{'uncompressedSize'} = $self->{'compressedSize'}; } $self->desiredCompressionMethod( $self->compressionMethod() ); return AZ_OK; } sub rewindData { my $self = shift; my $status = $self->SUPER::rewindData(@_); return $status unless $status == AZ_OK; return AZ_IO_ERROR unless $self->fh(); $self->fh()->clearerr(); # Seek to local file header. # The only reason that I'm doing this this way is that the extraField # length seems to be different between the CD header and the LF header. $status = $self->_seekToLocalHeader(); return $status unless $status == AZ_OK; # skip local file header $status = $self->_skipLocalFileHeader(); return $status unless $status == AZ_OK; # Seek to beginning of file data $self->fh()->seek( $self->dataOffset(), IO::Seekable::SEEK_SET ) or return _ioError("seeking to beginning of file data"); return AZ_OK; } # Return bytes read. Note that first parameter is a ref to a buffer. # my $data; # my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize ); sub _readRawChunk { my ( $self, $dataRef, $chunkSize ) = @_; return ( 0, AZ_OK ) unless $chunkSize; my $bytesRead = $self->fh()->read( $$dataRef, $chunkSize ) or return ( 0, _ioError("reading data") ); return ( $bytesRead, AZ_OK ); } 1; gdata/inst/perl/Archive/Zip/Tree.pm0000644000176000001440000000147411337525116016673 0ustar ripleyuserspackage Archive::Zip::Tree; use strict; use vars qw{$VERSION}; BEGIN { $VERSION = '1.30'; } use Archive::Zip; warn( "Archive::Zip::Tree is deprecated; its methods have been moved into Archive::Zip." ) if $^W; 1; __END__ =head1 NAME Archive::Zip::Tree - (DEPRECATED) methods for adding/extracting trees using Archive::Zip =head1 SYNOPSIS =head1 DESCRIPTION This module is deprecated, because all its methods were moved into the main Archive::Zip module. It is included in the distribution merely to avoid breaking old code. See L. =head1 AUTHOR Ned Konz, perl@bike-nomad.com =head1 COPYRIGHT Copyright (c) 2000-2002 Ned Konz. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =cut gdata/inst/perl/Archive/Zip/StringMember.pm0000644000176000001440000000331011337525116020361 0ustar ripleyuserspackage Archive::Zip::StringMember; use strict; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw( Archive::Zip::Member ); } use Archive::Zip qw( :CONSTANTS :ERROR_CODES ); # Create a new string member. Default is COMPRESSION_STORED. # Can take a ref to a string as well. sub _newFromString { my $class = shift; my $string = shift; my $name = shift; my $self = $class->new(@_); $self->contents($string); $self->fileName($name) if defined($name); # Set the file date to now $self->setLastModFileDateTimeFromUnix( time() ); $self->unixFileAttributes( $self->DEFAULT_FILE_PERMISSIONS ); return $self; } sub _become { my $self = shift; my $newClass = shift; return $self if ref($self) eq $newClass; delete( $self->{'contents'} ); return $self->SUPER::_become($newClass); } # Get or set my contents. Note that we do not call the superclass # version of this, because it calls us. sub contents { my $self = shift; my $string = shift; if ( defined($string) ) { $self->{'contents'} = pack( 'C0a*', ( ref($string) eq 'SCALAR' ) ? $$string : $string ); $self->{'uncompressedSize'} = $self->{'compressedSize'} = length( $self->{'contents'} ); $self->{'compressionMethod'} = COMPRESSION_STORED; } return $self->{'contents'}; } # Return bytes read. Note that first parameter is a ref to a buffer. # my $data; # my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize ); sub _readRawChunk { my ( $self, $dataRef, $chunkSize ) = @_; $$dataRef = substr( $self->contents(), $self->_readOffset(), $chunkSize ); return ( length($$dataRef), AZ_OK ); } 1; gdata/inst/perl/Archive/Zip/NewFileMember.pm0000644000176000001440000000424511337525116020454 0ustar ripleyuserspackage Archive::Zip::NewFileMember; use strict; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw ( Archive::Zip::FileMember ); } use Archive::Zip qw( :CONSTANTS :ERROR_CODES :UTILITY_METHODS ); # Given a file name, set up for eventual writing. sub _newFromFileNamed { my $class = shift; my $fileName = shift; # local FS format my $newName = shift; $newName = _asZipDirName($fileName) unless defined($newName); return undef unless ( stat($fileName) && -r _ && !-d _ ); my $self = $class->new(@_); $self->{'fileName'} = $newName; $self->{'externalFileName'} = $fileName; $self->{'compressionMethod'} = COMPRESSION_STORED; my @stat = stat(_); $self->{'compressedSize'} = $self->{'uncompressedSize'} = $stat[7]; $self->desiredCompressionMethod( ( $self->compressedSize() > 0 ) ? COMPRESSION_DEFLATED : COMPRESSION_STORED ); $self->unixFileAttributes( $stat[2] ); $self->setLastModFileDateTimeFromUnix( $stat[9] ); $self->isTextFile( -T _ ); return $self; } sub rewindData { my $self = shift; my $status = $self->SUPER::rewindData(@_); return $status unless $status == AZ_OK; return AZ_IO_ERROR unless $self->fh(); $self->fh()->clearerr(); $self->fh()->seek( 0, IO::Seekable::SEEK_SET ) or return _ioError( "rewinding", $self->externalFileName() ); return AZ_OK; } # Return bytes read. Note that first parameter is a ref to a buffer. # my $data; # my ( $bytesRead, $status) = $self->readRawChunk( \$data, $chunkSize ); sub _readRawChunk { my ( $self, $dataRef, $chunkSize ) = @_; return ( 0, AZ_OK ) unless $chunkSize; my $bytesRead = $self->fh()->read( $$dataRef, $chunkSize ) or return ( 0, _ioError("reading data") ); return ( $bytesRead, AZ_OK ); } # If I already exist, extraction is a no-op. sub extractToFileNamed { my $self = shift; my $name = shift; # local FS name if ( File::Spec->rel2abs($name) eq File::Spec->rel2abs( $self->externalFileName() ) and -r $name ) { return AZ_OK; } else { return $self->SUPER::extractToFileNamed( $name, @_ ); } } 1; gdata/inst/perl/Archive/Zip/MockFileHandle.pm0000644000176000001440000000247111337525115020576 0ustar ripleyuserspackage Archive::Zip::MockFileHandle; # Output file handle that calls a custom write routine # Ned Konz, March 2000 # This is provided to help with writing zip files # when you have to process them a chunk at a time. use strict; use vars qw{$VERSION}; BEGIN { $VERSION = '1.30'; $VERSION = eval $VERSION; } sub new { my $class = shift || __PACKAGE__; $class = ref($class) || $class; my $self = bless( { 'position' => 0, 'size' => 0 }, $class ); return $self; } sub eof { my $self = shift; return $self->{'position'} >= $self->{'size'}; } # Copy given buffer to me sub print { my $self = shift; my $bytes = join( '', @_ ); my $bytesWritten = $self->writeHook($bytes); if ( $self->{'position'} + $bytesWritten > $self->{'size'} ) { $self->{'size'} = $self->{'position'} + $bytesWritten; } $self->{'position'} += $bytesWritten; return $bytesWritten; } # Called on each write. # Override in subclasses. # Return number of bytes written (0 on error). sub writeHook { my $self = shift; my $bytes = shift; return length($bytes); } sub binmode { 1 } sub close { 1 } sub clearerr { 1 } # I'm write-only! sub read { 0 } sub tell { return shift->{'position'} } sub opened { 1 } 1; gdata/inst/perl/Archive/Zip/MemberRead.pm0000644000176000001440000001636711337525116020006 0ustar ripleyuserspackage Archive::Zip::MemberRead; =head1 NAME Archive::Zip::MemberRead - A wrapper that lets you read Zip archive members as if they were files. =cut =head1 SYNOPSIS use Archive::Zip; use Archive::Zip::MemberRead; $zip = Archive::Zip->new("file.zip"); $fh = Archive::Zip::MemberRead->new($zip, "subdir/abc.txt"); while (defined($line = $fh->getline())) { print $fh->input_line_number . "#: $line\n"; } $read = $fh->read($buffer, 32*1024); print "Read $read bytes as :$buffer:\n"; =head1 DESCRIPTION The Archive::Zip::MemberRead module lets you read Zip archive member data just like you read data from files. =head1 METHODS =over 4 =cut use strict; use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); use vars qw{$VERSION}; my $nl; BEGIN { $VERSION = '1.30'; $VERSION = eval $VERSION; # Requirement for newline conversion. Should check for e.g., DOS and OS/2 as well, but am too lazy. $nl = $^O eq 'MSWin32' ? "\r\n" : "\n"; } =item Archive::Zip::Member::readFileHandle() You can get a C from an archive member by calling C: my $member = $zip->memberNamed('abc/def.c'); my $fh = $member->readFileHandle(); while (defined($line = $fh->getline())) { # ... } $fh->close(); =cut sub Archive::Zip::Member::readFileHandle { return Archive::Zip::MemberRead->new( shift() ); } =item Archive::Zip::MemberRead->new($zip, $fileName) =item Archive::Zip::MemberRead->new($zip, $member) =item Archive::Zip::MemberRead->new($member) Construct a new Archive::Zip::MemberRead on the specified member. my $fh = Archive::Zip::MemberRead->new($zip, 'fred.c') =cut sub new { my ( $class, $zip, $file ) = @_; my ( $self, $member ); if ( $zip && $file ) # zip and filename, or zip and member { $member = ref($file) ? $file : $zip->memberNamed($file); } elsif ( $zip && !$file && ref($zip) ) # just member { $member = $zip; } else { die( 'Archive::Zip::MemberRead::new needs a zip and filename, zip and member, or member' ); } $self = {}; bless( $self, $class ); $self->set_member($member); return $self; } sub set_member { my ( $self, $member ) = @_; $self->{member} = $member; $self->set_compression(COMPRESSION_STORED); $self->rewind(); } sub set_compression { my ( $self, $compression ) = @_; $self->{member}->desiredCompressionMethod($compression) if $self->{member}; } =item setLineEnd(expr) Set the line end character to use. This is set to \n by default except on Windows systems where it is set to \r\n. You will only need to set this on systems which are not Windows or Unix based and require a line end diffrent from \n. This is a class method so call as C->C =cut sub setLineEnd { shift; $nl = shift; } =item rewind() Rewinds an C so that you can read from it again starting at the beginning. =cut sub rewind { my $self = shift; $self->_reset_vars(); $self->{member}->rewindData() if $self->{member}; } sub _reset_vars { my $self = shift; $self->{line_no} = 0; $self->{at_end} = 0; delete $self->{buffer}; } =item input_record_separator(expr) If the argumnet is given, input_record_separator for this instance is set to it. The current setting (which may be the global $/) is always returned. =cut sub input_record_separator { my $self = shift; if (@_) { $self->{sep} = shift; $self->{sep_re} = _sep_as_re($self->{sep}); # Cache the RE as an optimization } return exists $self->{sep} ? $self->{sep} : $/; } # Return the input_record_separator in use as an RE fragment # Note that if we have a per-instance input_record_separator # we can just return the already converted value. Otherwise, # the conversion must be done on $/ every time since we cannot # know whether it has changed or not. sub _sep_re { my $self = shift; # Important to phrase this way: sep's value may be undef. return exists $self->{sep} ? $self->{sep_re} : _sep_as_re($/); } # Convert the input record separator into an RE and return it. sub _sep_as_re { my $sep = shift; if (defined $sep) { if ($sep eq '') { return "(?:$nl){2,}"; } else { $sep =~ s/\n/$nl/og; return quotemeta $sep; } } else { return undef; } } =item input_line_number() Returns the current line number, but only if you're using C. Using C will not update the line number. =cut sub input_line_number { my $self = shift; return $self->{line_no}; } =item close() Closes the given file handle. =cut sub close { my $self = shift; $self->_reset_vars(); $self->{member}->endRead(); } =item buffer_size([ $size ]) Gets or sets the buffer size used for reads. Default is the chunk size used by Archive::Zip. =cut sub buffer_size { my ( $self, $size ) = @_; if ( !$size ) { return $self->{chunkSize} || Archive::Zip::chunkSize(); } else { $self->{chunkSize} = $size; } } =item getline() Returns the next line from the currently open member. Makes sense only for text files. A read error is considered fatal enough to die. Returns undef on eof. All subsequent calls would return undef, unless a rewind() is called. Note: The line returned has the input_record_separator (default: newline) removed. =cut sub getline { my $self = shift; my $size = $self->buffer_size(); my $sep = $self->_sep_re(); for (;;) { if ( $sep && defined($self->{buffer}) && $self->{buffer} =~ s/^(.*?)$sep//s ) { $self->{line_no}++; return $1; } elsif ($self->{at_end}) { $self->{line_no}++ if $self->{buffer}; return delete $self->{buffer}; } my ($temp,$status) = $self->{member}->readChunk($size); if ($status != AZ_OK && $status != AZ_STREAM_END) { die "ERROR: Error reading chunk from archive - $status"; } $self->{at_end} = $status == AZ_STREAM_END; $self->{buffer} .= $$temp; } } =item read($buffer, $num_bytes_to_read) Simulates a normal C system call. Returns the no. of bytes read. C on error, 0 on eof, I: $fh = Archive::Zip::MemberRead->new($zip, "sreeji/secrets.bin"); while (1) { $read = $fh->read($buffer, 1024); die "FATAL ERROR reading my secrets !\n" if (!defined($read)); last if (!$read); # Do processing. .... } =cut # # All these $_ are required to emulate read(). # sub read { my $self = $_[0]; my $size = $_[2]; my ( $temp, $status, $ret ); ( $temp, $status ) = $self->{member}->readChunk($size); if ( $status != AZ_OK && $status != AZ_STREAM_END ) { $_[1] = undef; $ret = undef; } else { $_[1] = $$temp; $ret = length($$temp); } return $ret; } 1; =back =head1 AUTHOR Sreeji K. Das, See L by Ned Konz without which this module does not make any sense! Minor mods by Ned Konz. =head1 COPYRIGHT Copyright 2002 Sreeji K. Das. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =cut gdata/inst/perl/Archive/Zip/Member.pm0000644000176000001440000007742211337525115017210 0ustar ripleyuserspackage Archive::Zip::Member; # A generic membet of an archive use strict; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw( Archive::Zip ); } use Archive::Zip qw( :CONSTANTS :MISC_CONSTANTS :ERROR_CODES :PKZIP_CONSTANTS :UTILITY_METHODS ); use Time::Local (); use Compress::Raw::Zlib qw( Z_OK Z_STREAM_END MAX_WBITS ); use File::Path; use File::Basename; use constant ZIPFILEMEMBERCLASS => 'Archive::Zip::ZipFileMember'; use constant NEWFILEMEMBERCLASS => 'Archive::Zip::NewFileMember'; use constant STRINGMEMBERCLASS => 'Archive::Zip::StringMember'; use constant DIRECTORYMEMBERCLASS => 'Archive::Zip::DirectoryMember'; # Unix perms for default creation of files/dirs. use constant DEFAULT_DIRECTORY_PERMISSIONS => 040755; use constant DEFAULT_FILE_PERMISSIONS => 0100666; use constant DIRECTORY_ATTRIB => 040000; use constant FILE_ATTRIB => 0100000; # Returns self if successful, else undef # Assumes that fh is positioned at beginning of central directory file header. # Leaves fh positioned immediately after file header or EOCD signature. sub _newFromZipFile { my $class = shift; my $self = $class->ZIPFILEMEMBERCLASS->_newFromZipFile(@_); return $self; } sub newFromString { my $class = shift; my ( $stringOrStringRef, $fileName ); if ( ref( $_[0] ) eq 'HASH' ) { $stringOrStringRef = $_[0]->{string}; $fileName = $_[0]->{zipName}; } else { ( $stringOrStringRef, $fileName ) = @_; } my $self = $class->STRINGMEMBERCLASS->_newFromString( $stringOrStringRef, $fileName ); return $self; } sub newFromFile { my $class = shift; my ( $fileName, $zipName ); if ( ref( $_[0] ) eq 'HASH' ) { $fileName = $_[0]->{fileName}; $zipName = $_[0]->{zipName}; } else { ( $fileName, $zipName ) = @_; } my $self = $class->NEWFILEMEMBERCLASS->_newFromFileNamed( $fileName, $zipName ); return $self; } sub newDirectoryNamed { my $class = shift; my ( $directoryName, $newName ); if ( ref( $_[0] ) eq 'HASH' ) { $directoryName = $_[0]->{directoryName}; $newName = $_[0]->{zipName}; } else { ( $directoryName, $newName ) = @_; } my $self = $class->DIRECTORYMEMBERCLASS->_newNamed( $directoryName, $newName ); return $self; } sub new { my $class = shift; my $self = { 'lastModFileDateTime' => 0, 'fileAttributeFormat' => FA_UNIX, 'versionMadeBy' => 20, 'versionNeededToExtract' => 20, 'bitFlag' => 0, 'compressionMethod' => COMPRESSION_STORED, 'desiredCompressionMethod' => COMPRESSION_STORED, 'desiredCompressionLevel' => COMPRESSION_LEVEL_NONE, 'internalFileAttributes' => 0, 'externalFileAttributes' => 0, # set later 'fileName' => '', 'cdExtraField' => '', 'localExtraField' => '', 'fileComment' => '', 'crc32' => 0, 'compressedSize' => 0, 'uncompressedSize' => 0, 'isSymbolicLink' => 0, @_ }; bless( $self, $class ); $self->unixFileAttributes( $self->DEFAULT_FILE_PERMISSIONS ); return $self; } sub _becomeDirectoryIfNecessary { my $self = shift; $self->_become(DIRECTORYMEMBERCLASS) if $self->isDirectory(); return $self; } # Morph into given class (do whatever cleanup I need to do) sub _become { return bless( $_[0], $_[1] ); } sub versionMadeBy { shift->{'versionMadeBy'}; } sub fileAttributeFormat { my $self = shift; if (@_) { $self->{fileAttributeFormat} = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{format} : $_[0]; } else { return $self->{fileAttributeFormat}; } } sub versionNeededToExtract { shift->{'versionNeededToExtract'}; } sub bitFlag { my $self = shift; # Set General Purpose Bit Flags according to the desiredCompressionLevel setting if ( $self->desiredCompressionLevel == 1 || $self->desiredCompressionLevel == 2 ) { $self->{'bitFlag'} = DEFLATING_COMPRESSION_FAST; } elsif ( $self->desiredCompressionLevel == 3 || $self->desiredCompressionLevel == 4 || $self->desiredCompressionLevel == 5 || $self->desiredCompressionLevel == 6 || $self->desiredCompressionLevel == 7 ) { $self->{'bitFlag'} = DEFLATING_COMPRESSION_NORMAL; } elsif ( $self->desiredCompressionLevel == 8 || $self->desiredCompressionLevel == 9 ) { $self->{'bitFlag'} = DEFLATING_COMPRESSION_MAXIMUM; } $self->{'bitFlag'}; } sub compressionMethod { shift->{'compressionMethod'}; } sub desiredCompressionMethod { my $self = shift; my $newDesiredCompressionMethod = ( ref( $_[0] ) eq 'HASH' ) ? shift->{compressionMethod} : shift; my $oldDesiredCompressionMethod = $self->{'desiredCompressionMethod'}; if ( defined($newDesiredCompressionMethod) ) { $self->{'desiredCompressionMethod'} = $newDesiredCompressionMethod; if ( $newDesiredCompressionMethod == COMPRESSION_STORED ) { $self->{'desiredCompressionLevel'} = 0; $self->{'bitFlag'} &= ~GPBF_HAS_DATA_DESCRIPTOR_MASK; } elsif ( $oldDesiredCompressionMethod == COMPRESSION_STORED ) { $self->{'desiredCompressionLevel'} = COMPRESSION_LEVEL_DEFAULT; } } return $oldDesiredCompressionMethod; } sub desiredCompressionLevel { my $self = shift; my $newDesiredCompressionLevel = ( ref( $_[0] ) eq 'HASH' ) ? shift->{compressionLevel} : shift; my $oldDesiredCompressionLevel = $self->{'desiredCompressionLevel'}; if ( defined($newDesiredCompressionLevel) ) { $self->{'desiredCompressionLevel'} = $newDesiredCompressionLevel; $self->{'desiredCompressionMethod'} = ( $newDesiredCompressionLevel ? COMPRESSION_DEFLATED : COMPRESSION_STORED ); } return $oldDesiredCompressionLevel; } sub fileName { my $self = shift; my $newName = shift; if ($newName) { $newName =~ s{[\\/]+}{/}g; # deal with dos/windoze problems $self->{'fileName'} = $newName; } return $self->{'fileName'}; } sub lastModFileDateTime { my $modTime = shift->{'lastModFileDateTime'}; $modTime =~ m/^(\d+)$/; # untaint return $1; } sub lastModTime { my $self = shift; return _dosToUnixTime( $self->lastModFileDateTime() ); } sub setLastModFileDateTimeFromUnix { my $self = shift; my $time_t = shift; $self->{'lastModFileDateTime'} = _unixToDosTime($time_t); } sub internalFileAttributes { shift->{'internalFileAttributes'}; } sub externalFileAttributes { shift->{'externalFileAttributes'}; } # Convert UNIX permissions into proper value for zip file # Usable as a function or a method sub _mapPermissionsFromUnix { my $self = shift; my $mode = shift; my $attribs = $mode << 16; # Microsoft Windows Explorer needs this bit set for directories if ( $mode & DIRECTORY_ATTRIB ) { $attribs |= 16; } return $attribs; # TODO: map more MS-DOS perms } # Convert ZIP permissions into Unix ones # # This was taken from Info-ZIP group's portable UnZip # zipfile-extraction program, version 5.50. # http://www.info-zip.org/pub/infozip/ # # See the mapattr() function in unix/unix.c # See the attribute format constants in unzpriv.h # # XXX Note that there's one situation that isn't implemented # yet that depends on the "extra field." sub _mapPermissionsToUnix { my $self = shift; my $format = $self->{'fileAttributeFormat'}; my $attribs = $self->{'externalFileAttributes'}; my $mode = 0; if ( $format == FA_AMIGA ) { $attribs = $attribs >> 17 & 7; # Amiga RWE bits $mode = $attribs << 6 | $attribs << 3 | $attribs; return $mode; } if ( $format == FA_THEOS ) { $attribs &= 0xF1FFFFFF; if ( ( $attribs & 0xF0000000 ) != 0x40000000 ) { $attribs &= 0x01FFFFFF; # not a dir, mask all ftype bits } else { $attribs &= 0x41FFFFFF; # leave directory bit as set } } if ( $format == FA_UNIX || $format == FA_VAX_VMS || $format == FA_ACORN || $format == FA_ATARI_ST || $format == FA_BEOS || $format == FA_QDOS || $format == FA_TANDEM ) { $mode = $attribs >> 16; return $mode if $mode != 0 or not $self->localExtraField; # warn("local extra field is: ", $self->localExtraField, "\n"); # XXX This condition is not implemented # I'm just including the comments from the info-zip section for now. # Some (non-Info-ZIP) implementations of Zip for Unix and # VMS (and probably others ??) leave 0 in the upper 16-bit # part of the external_file_attributes field. Instead, they # store file permission attributes in some extra field. # As a work-around, we search for the presence of one of # these extra fields and fall back to the MSDOS compatible # part of external_file_attributes if one of the known # e.f. types has been detected. # Later, we might implement extraction of the permission # bits from the VMS extra field. But for now, the work-around # should be sufficient to provide "readable" extracted files. # (For ASI Unix e.f., an experimental remap from the e.f. # mode value IS already provided!) } # PKWARE's PKZip for Unix marks entries as FA_MSDOS, but stores the # Unix attributes in the upper 16 bits of the external attributes # field, just like Info-ZIP's Zip for Unix. We try to use that # value, after a check for consistency with the MSDOS attribute # bits (see below). if ( $format == FA_MSDOS ) { $mode = $attribs >> 16; } # FA_MSDOS, FA_OS2_HPFS, FA_WINDOWS_NTFS, FA_MACINTOSH, FA_TOPS20 $attribs = !( $attribs & 1 ) << 1 | ( $attribs & 0x10 ) >> 4; # keep previous $mode setting when its "owner" # part appears to be consistent with DOS attribute flags! return $mode if ( $mode & 0700 ) == ( 0400 | $attribs << 6 ); $mode = 0444 | $attribs << 6 | $attribs << 3 | $attribs; return $mode; } sub unixFileAttributes { my $self = shift; my $oldPerms = $self->_mapPermissionsToUnix; my $perms; if ( @_ ) { $perms = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{attributes} : $_[0]; if ( $self->isDirectory ) { $perms &= ~FILE_ATTRIB; $perms |= DIRECTORY_ATTRIB; } else { $perms &= ~DIRECTORY_ATTRIB; $perms |= FILE_ATTRIB; } $self->{externalFileAttributes} = $self->_mapPermissionsFromUnix($perms); } return $oldPerms; } sub localExtraField { my $self = shift; if (@_) { $self->{localExtraField} = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{field} : $_[0]; } else { return $self->{localExtraField}; } } sub cdExtraField { my $self = shift; if (@_) { $self->{cdExtraField} = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{field} : $_[0]; } else { return $self->{cdExtraField}; } } sub extraFields { my $self = shift; return $self->localExtraField() . $self->cdExtraField(); } sub fileComment { my $self = shift; if (@_) { $self->{fileComment} = ( ref( $_[0] ) eq 'HASH' ) ? pack( 'C0a*', $_[0]->{comment} ) : pack( 'C0a*', $_[0] ); } else { return $self->{fileComment}; } } sub hasDataDescriptor { my $self = shift; if (@_) { my $shouldHave = shift; if ($shouldHave) { $self->{'bitFlag'} |= GPBF_HAS_DATA_DESCRIPTOR_MASK; } else { $self->{'bitFlag'} &= ~GPBF_HAS_DATA_DESCRIPTOR_MASK; } } return $self->{'bitFlag'} & GPBF_HAS_DATA_DESCRIPTOR_MASK; } sub crc32 { shift->{'crc32'}; } sub crc32String { sprintf( "%08x", shift->{'crc32'} ); } sub compressedSize { shift->{'compressedSize'}; } sub uncompressedSize { shift->{'uncompressedSize'}; } sub isEncrypted { shift->bitFlag() & GPBF_ENCRYPTED_MASK; } sub isTextFile { my $self = shift; my $bit = $self->internalFileAttributes() & IFA_TEXT_FILE_MASK; if (@_) { my $flag = ( ref( $_[0] ) eq 'HASH' ) ? shift->{flag} : shift; $self->{'internalFileAttributes'} &= ~IFA_TEXT_FILE_MASK; $self->{'internalFileAttributes'} |= ( $flag ? IFA_TEXT_FILE: IFA_BINARY_FILE ); } return $bit == IFA_TEXT_FILE; } sub isBinaryFile { my $self = shift; my $bit = $self->internalFileAttributes() & IFA_TEXT_FILE_MASK; if (@_) { my $flag = shift; $self->{'internalFileAttributes'} &= ~IFA_TEXT_FILE_MASK; $self->{'internalFileAttributes'} |= ( $flag ? IFA_BINARY_FILE: IFA_TEXT_FILE ); } return $bit == IFA_BINARY_FILE; } sub extractToFileNamed { my $self = shift; # local FS name my $name = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{name} : $_[0]; $self->{'isSymbolicLink'} = 0; # Check if the file / directory is a symbolic link or not if ( $self->{'externalFileAttributes'} == 0xA1FF0000 ) { $self->{'isSymbolicLink'} = 1; $self->{'newName'} = $name; my ( $status, $fh ) = _newFileHandle( $name, 'r' ); my $retval = $self->extractToFileHandle($fh); $fh->close(); } else { #return _writeSymbolicLink($self, $name) if $self->isSymbolicLink(); return _error("encryption unsupported") if $self->isEncrypted(); mkpath( dirname($name) ); # croaks on error my ( $status, $fh ) = _newFileHandle( $name, 'w' ); return _ioError("Can't open file $name for write") unless $status; my $retval = $self->extractToFileHandle($fh); $fh->close(); chmod ($self->unixFileAttributes(), $name) or return _error("Can't chmod() ${name}: $!"); utime( $self->lastModTime(), $self->lastModTime(), $name ); return $retval; } } sub _writeSymbolicLink { my $self = shift; my $name = shift; my $chunkSize = $Archive::Zip::ChunkSize; #my ( $outRef, undef ) = $self->readChunk($chunkSize); my $fh; my $retval = $self->extractToFileHandle($fh); my ( $outRef, undef ) = $self->readChunk(100); } sub isSymbolicLink { my $self = shift; if ( $self->{'externalFileAttributes'} == 0xA1FF0000 ) { $self->{'isSymbolicLink'} = 1; } else { return 0; } 1; } sub isDirectory { return 0; } sub externalFileName { return undef; } # The following are used when copying data sub _writeOffset { shift->{'writeOffset'}; } sub _readOffset { shift->{'readOffset'}; } sub writeLocalHeaderRelativeOffset { shift->{'writeLocalHeaderRelativeOffset'}; } sub wasWritten { shift->{'wasWritten'} } sub _dataEnded { shift->{'dataEnded'}; } sub _readDataRemaining { shift->{'readDataRemaining'}; } sub _inflater { shift->{'inflater'}; } sub _deflater { shift->{'deflater'}; } # Return the total size of my local header sub _localHeaderSize { my $self = shift; return SIGNATURE_LENGTH + LOCAL_FILE_HEADER_LENGTH + length( $self->fileName() ) + length( $self->localExtraField() ); } # Return the total size of my CD header sub _centralDirectoryHeaderSize { my $self = shift; return SIGNATURE_LENGTH + CENTRAL_DIRECTORY_FILE_HEADER_LENGTH + length( $self->fileName() ) + length( $self->cdExtraField() ) + length( $self->fileComment() ); } # DOS date/time format # 0-4 (5) Second divided by 2 # 5-10 (6) Minute (0-59) # 11-15 (5) Hour (0-23 on a 24-hour clock) # 16-20 (5) Day of the month (1-31) # 21-24 (4) Month (1 = January, 2 = February, etc.) # 25-31 (7) Year offset from 1980 (add 1980 to get actual year) # Convert DOS date/time format to unix time_t format # NOT AN OBJECT METHOD! sub _dosToUnixTime { my $dt = shift; return time() unless defined($dt); my $year = ( ( $dt >> 25 ) & 0x7f ) + 80; my $mon = ( ( $dt >> 21 ) & 0x0f ) - 1; my $mday = ( ( $dt >> 16 ) & 0x1f ); my $hour = ( ( $dt >> 11 ) & 0x1f ); my $min = ( ( $dt >> 5 ) & 0x3f ); my $sec = ( ( $dt << 1 ) & 0x3e ); # catch errors my $time_t = eval { Time::Local::timelocal( $sec, $min, $hour, $mday, $mon, $year ); }; return time() if ($@); return $time_t; } # Note, this isn't exactly UTC 1980, it's 1980 + 12 hours and 1 # minute so that nothing timezoney can muck us up. my $safe_epoch = 315576060; # convert a unix time to DOS date/time # NOT AN OBJECT METHOD! sub _unixToDosTime { my $time_t = shift; unless ($time_t) { _error("Tried to add member with zero or undef value for time"); $time_t = $safe_epoch; } if ( $time_t < $safe_epoch ) { _ioError("Unsupported date before 1980 encountered, moving to 1980"); $time_t = $safe_epoch; } my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime($time_t); my $dt = 0; $dt += ( $sec >> 1 ); $dt += ( $min << 5 ); $dt += ( $hour << 11 ); $dt += ( $mday << 16 ); $dt += ( ( $mon + 1 ) << 21 ); $dt += ( ( $year - 80 ) << 25 ); return $dt; } # Write my local header to a file handle. # Stores the offset to the start of the header in my # writeLocalHeaderRelativeOffset member. # Returns AZ_OK on success. sub _writeLocalFileHeader { my $self = shift; my $fh = shift; my $signatureData = pack( SIGNATURE_FORMAT, LOCAL_FILE_HEADER_SIGNATURE ); $self->_print($fh, $signatureData) or return _ioError("writing local header signature"); my $header = pack( LOCAL_FILE_HEADER_FORMAT, $self->versionNeededToExtract(), $self->bitFlag(), $self->desiredCompressionMethod(), $self->lastModFileDateTime(), $self->crc32(), $self->compressedSize(), # may need to be re-written later $self->uncompressedSize(), length( $self->fileName() ), length( $self->localExtraField() ) ); $self->_print($fh, $header) or return _ioError("writing local header"); # Check for a valid filename or a filename equal to a literal `0' if ( $self->fileName() || $self->fileName eq '0' ) { $self->_print($fh, $self->fileName() ) or return _ioError("writing local header filename"); } if ( $self->localExtraField() ) { $self->_print($fh, $self->localExtraField() ) or return _ioError("writing local extra field"); } return AZ_OK; } sub _writeCentralDirectoryFileHeader { my $self = shift; my $fh = shift; my $sigData = pack( SIGNATURE_FORMAT, CENTRAL_DIRECTORY_FILE_HEADER_SIGNATURE ); $self->_print($fh, $sigData) or return _ioError("writing central directory header signature"); my $fileNameLength = length( $self->fileName() ); my $extraFieldLength = length( $self->cdExtraField() ); my $fileCommentLength = length( $self->fileComment() ); my $header = pack( CENTRAL_DIRECTORY_FILE_HEADER_FORMAT, $self->versionMadeBy(), $self->fileAttributeFormat(), $self->versionNeededToExtract(), $self->bitFlag(), $self->desiredCompressionMethod(), $self->lastModFileDateTime(), $self->crc32(), # these three fields should have been updated $self->_writeOffset(), # by writing the data stream out $self->uncompressedSize(), # $fileNameLength, $extraFieldLength, $fileCommentLength, 0, # {'diskNumberStart'}, $self->internalFileAttributes(), $self->externalFileAttributes(), $self->writeLocalHeaderRelativeOffset() ); $self->_print($fh, $header) or return _ioError("writing central directory header"); if ($fileNameLength) { $self->_print($fh, $self->fileName() ) or return _ioError("writing central directory header signature"); } if ($extraFieldLength) { $self->_print($fh, $self->cdExtraField() ) or return _ioError("writing central directory extra field"); } if ($fileCommentLength) { $self->_print($fh, $self->fileComment() ) or return _ioError("writing central directory file comment"); } return AZ_OK; } # This writes a data descriptor to the given file handle. # Assumes that crc32, writeOffset, and uncompressedSize are # set correctly (they should be after a write). # Further, the local file header should have the # GPBF_HAS_DATA_DESCRIPTOR_MASK bit set. sub _writeDataDescriptor { my $self = shift; my $fh = shift; my $header = pack( SIGNATURE_FORMAT . DATA_DESCRIPTOR_FORMAT, DATA_DESCRIPTOR_SIGNATURE, $self->crc32(), $self->_writeOffset(), # compressed size $self->uncompressedSize() ); $self->_print($fh, $header) or return _ioError("writing data descriptor"); return AZ_OK; } # Re-writes the local file header with new crc32 and compressedSize fields. # To be called after writing the data stream. # Assumes that filename and extraField sizes didn't change since last written. sub _refreshLocalFileHeader { my $self = shift; my $fh = shift; my $here = $fh->tell(); $fh->seek( $self->writeLocalHeaderRelativeOffset() + SIGNATURE_LENGTH, IO::Seekable::SEEK_SET ) or return _ioError("seeking to rewrite local header"); my $header = pack( LOCAL_FILE_HEADER_FORMAT, $self->versionNeededToExtract(), $self->bitFlag(), $self->desiredCompressionMethod(), $self->lastModFileDateTime(), $self->crc32(), $self->_writeOffset(), # compressed size $self->uncompressedSize(), length( $self->fileName() ), length( $self->localExtraField() ) ); $self->_print($fh, $header) or return _ioError("re-writing local header"); $fh->seek( $here, IO::Seekable::SEEK_SET ) or return _ioError("seeking after rewrite of local header"); return AZ_OK; } sub readChunk { my $self = shift; my $chunkSize = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{chunkSize} : $_[0]; if ( $self->readIsDone() ) { $self->endRead(); my $dummy = ''; return ( \$dummy, AZ_STREAM_END ); } $chunkSize = $Archive::Zip::ChunkSize if not defined($chunkSize); $chunkSize = $self->_readDataRemaining() if $chunkSize > $self->_readDataRemaining(); my $buffer = ''; my $outputRef; my ( $bytesRead, $status ) = $self->_readRawChunk( \$buffer, $chunkSize ); return ( \$buffer, $status ) unless $status == AZ_OK; $self->{'readDataRemaining'} -= $bytesRead; $self->{'readOffset'} += $bytesRead; if ( $self->compressionMethod() == COMPRESSION_STORED ) { $self->{'crc32'} = $self->computeCRC32( $buffer, $self->{'crc32'} ); } ( $outputRef, $status ) = &{ $self->{'chunkHandler'} }( $self, \$buffer ); $self->{'writeOffset'} += length($$outputRef); $self->endRead() if $self->readIsDone(); return ( $outputRef, $status ); } # Read the next raw chunk of my data. Subclasses MUST implement. # my ( $bytesRead, $status) = $self->_readRawChunk( \$buffer, $chunkSize ); sub _readRawChunk { my $self = shift; return $self->_subclassResponsibility(); } # A place holder to catch rewindData errors if someone ignores # the error code. sub _noChunk { my $self = shift; return ( \undef, _error("trying to copy chunk when init failed") ); } # Basically a no-op so that I can have a consistent interface. # ( $outputRef, $status) = $self->_copyChunk( \$buffer ); sub _copyChunk { my ( $self, $dataRef ) = @_; return ( $dataRef, AZ_OK ); } # ( $outputRef, $status) = $self->_deflateChunk( \$buffer ); sub _deflateChunk { my ( $self, $buffer ) = @_; my ( $status ) = $self->_deflater()->deflate( $buffer, my $out ); if ( $self->_readDataRemaining() == 0 ) { my $extraOutput; ( $status ) = $self->_deflater()->flush($extraOutput); $out .= $extraOutput; $self->endRead(); return ( \$out, AZ_STREAM_END ); } elsif ( $status == Z_OK ) { return ( \$out, AZ_OK ); } else { $self->endRead(); my $retval = _error( 'deflate error', $status ); my $dummy = ''; return ( \$dummy, $retval ); } } # ( $outputRef, $status) = $self->_inflateChunk( \$buffer ); sub _inflateChunk { my ( $self, $buffer ) = @_; my ( $status ) = $self->_inflater()->inflate( $buffer, my $out ); my $retval; $self->endRead() unless $status == Z_OK; if ( $status == Z_OK || $status == Z_STREAM_END ) { $retval = ( $status == Z_STREAM_END ) ? AZ_STREAM_END: AZ_OK; return ( \$out, $retval ); } else { $retval = _error( 'inflate error', $status ); my $dummy = ''; return ( \$dummy, $retval ); } } sub rewindData { my $self = shift; my $status; # set to trap init errors $self->{'chunkHandler'} = $self->can('_noChunk'); # Work around WinZip bug with 0-length DEFLATED files $self->desiredCompressionMethod(COMPRESSION_STORED) if $self->uncompressedSize() == 0; # assume that we're going to read the whole file, and compute the CRC anew. $self->{'crc32'} = 0 if ( $self->compressionMethod() == COMPRESSION_STORED ); # These are the only combinations of methods we deal with right now. if ( $self->compressionMethod() == COMPRESSION_STORED and $self->desiredCompressionMethod() == COMPRESSION_DEFLATED ) { ( $self->{'deflater'}, $status ) = Compress::Raw::Zlib::Deflate->new( '-Level' => $self->desiredCompressionLevel(), '-WindowBits' => -MAX_WBITS(), # necessary magic '-Bufsize' => $Archive::Zip::ChunkSize, @_ ); # pass additional options return _error( 'deflateInit error:', $status ) unless $status == Z_OK; $self->{'chunkHandler'} = $self->can('_deflateChunk'); } elsif ( $self->compressionMethod() == COMPRESSION_DEFLATED and $self->desiredCompressionMethod() == COMPRESSION_STORED ) { ( $self->{'inflater'}, $status ) = Compress::Raw::Zlib::Inflate->new( '-WindowBits' => -MAX_WBITS(), # necessary magic '-Bufsize' => $Archive::Zip::ChunkSize, @_ ); # pass additional options return _error( 'inflateInit error:', $status ) unless $status == Z_OK; $self->{'chunkHandler'} = $self->can('_inflateChunk'); } elsif ( $self->compressionMethod() == $self->desiredCompressionMethod() ) { $self->{'chunkHandler'} = $self->can('_copyChunk'); } else { return _error( sprintf( "Unsupported compression combination: read %d, write %d", $self->compressionMethod(), $self->desiredCompressionMethod() ) ); } $self->{'readDataRemaining'} = ( $self->compressionMethod() == COMPRESSION_STORED ) ? $self->uncompressedSize() : $self->compressedSize(); $self->{'dataEnded'} = 0; $self->{'readOffset'} = 0; return AZ_OK; } sub endRead { my $self = shift; delete $self->{'inflater'}; delete $self->{'deflater'}; $self->{'dataEnded'} = 1; $self->{'readDataRemaining'} = 0; return AZ_OK; } sub readIsDone { my $self = shift; return ( $self->_dataEnded() or !$self->_readDataRemaining() ); } sub contents { my $self = shift; my $newContents = shift; if ( defined($newContents) ) { # change our type and call the subclass contents method. $self->_become(STRINGMEMBERCLASS); return $self->contents( pack( 'C0a*', $newContents ) ) ; # in case of Unicode } else { my $oldCompression = $self->desiredCompressionMethod(COMPRESSION_STORED); my $status = $self->rewindData(@_); if ( $status != AZ_OK ) { $self->endRead(); return $status; } my $retval = ''; while ( $status == AZ_OK ) { my $ref; ( $ref, $status ) = $self->readChunk( $self->_readDataRemaining() ); # did we get it in one chunk? if ( length($$ref) == $self->uncompressedSize() ) { $retval = $$ref; } else { $retval .= $$ref } } $self->desiredCompressionMethod($oldCompression); $self->endRead(); $status = AZ_OK if $status == AZ_STREAM_END; $retval = undef unless $status == AZ_OK; return wantarray ? ( $retval, $status ) : $retval; } } sub extractToFileHandle { my $self = shift; return _error("encryption unsupported") if $self->isEncrypted(); my $fh = ( ref( $_[0] ) eq 'HASH' ) ? shift->{fileHandle} : shift; _binmode($fh); my $oldCompression = $self->desiredCompressionMethod(COMPRESSION_STORED); my $status = $self->rewindData(@_); $status = $self->_writeData($fh) if $status == AZ_OK; $self->desiredCompressionMethod($oldCompression); $self->endRead(); return $status; } # write local header and data stream to file handle sub _writeToFileHandle { my $self = shift; my $fh = shift; my $fhIsSeekable = shift; my $offset = shift; return _error("no member name given for $self") if $self->fileName() eq ''; $self->{'writeLocalHeaderRelativeOffset'} = $offset; $self->{'wasWritten'} = 0; # Determine if I need to write a data descriptor # I need to do this if I can't refresh the header # and I don't know compressed size or crc32 fields. my $headerFieldsUnknown = ( ( $self->uncompressedSize() > 0 ) and ($self->compressionMethod() == COMPRESSION_STORED or $self->desiredCompressionMethod() == COMPRESSION_DEFLATED ) ); my $shouldWriteDataDescriptor = ( $headerFieldsUnknown and not $fhIsSeekable ); $self->hasDataDescriptor(1) if ($shouldWriteDataDescriptor); $self->{'writeOffset'} = 0; my $status = $self->rewindData(); ( $status = $self->_writeLocalFileHeader($fh) ) if $status == AZ_OK; ( $status = $self->_writeData($fh) ) if $status == AZ_OK; if ( $status == AZ_OK ) { $self->{'wasWritten'} = 1; if ( $self->hasDataDescriptor() ) { $status = $self->_writeDataDescriptor($fh); } elsif ($headerFieldsUnknown) { $status = $self->_refreshLocalFileHeader($fh); } } return $status; } # Copy my (possibly compressed) data to given file handle. # Returns C on success sub _writeData { my $self = shift; my $writeFh = shift; # If symbolic link, just create one if the operating system is Linux, Unix, BSD or VMS # TODO: Add checks for other operating systems if ( $self->{'isSymbolicLink'} == 1 && $^O eq 'linux' ) { my $chunkSize = $Archive::Zip::ChunkSize; my ( $outRef, $status ) = $self->readChunk($chunkSize); symlink $$outRef, $self->{'newName'}; } else { return AZ_OK if ( $self->uncompressedSize() == 0 ); my $status; my $chunkSize = $Archive::Zip::ChunkSize; while ( $self->_readDataRemaining() > 0 ) { my $outRef; ( $outRef, $status ) = $self->readChunk($chunkSize); return $status if ( $status != AZ_OK and $status != AZ_STREAM_END ); if ( length($$outRef) > 0 ) { $self->_print($writeFh, $$outRef) or return _ioError("write error during copy"); } last if $status == AZ_STREAM_END; } $self->{'compressedSize'} = $self->_writeOffset(); } return AZ_OK; } # Return true if I depend on the named file sub _usesFileNamed { return 0; } 1; gdata/inst/perl/Archive/Zip/FileMember.pm0000644000176000001440000000251011337525115017772 0ustar ripleyuserspackage Archive::Zip::FileMember; use strict; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw ( Archive::Zip::Member ); } use Archive::Zip qw( :UTILITY_METHODS ); sub externalFileName { shift->{'externalFileName'}; } # Return true if I depend on the named file sub _usesFileNamed { my $self = shift; my $fileName = shift; my $xfn = $self->externalFileName(); return undef if ref($xfn); return $xfn eq $fileName; } sub fh { my $self = shift; $self->_openFile() if !defined( $self->{'fh'} ) || !$self->{'fh'}->opened(); return $self->{'fh'}; } # opens my file handle from my file name sub _openFile { my $self = shift; my ( $status, $fh ) = _newFileHandle( $self->externalFileName(), 'r' ); if ( !$status ) { _ioError( "Can't open", $self->externalFileName() ); return undef; } $self->{'fh'} = $fh; _binmode($fh); return $fh; } # Make sure I close my file handle sub endRead { my $self = shift; undef $self->{'fh'}; # _closeFile(); return $self->SUPER::endRead(@_); } sub _become { my $self = shift; my $newClass = shift; return $self if ref($self) eq $newClass; delete( $self->{'externalFileName'} ); delete( $self->{'fh'} ); return $self->SUPER::_become($newClass); } 1; gdata/inst/perl/Archive/Zip/FAQ.pod0000644000176000001440000003033611337525116016550 0ustar ripleyusers =head1 NAME Archive::Zip::FAQ - Answers to a few frequently asked questions about Archive::Zip =head1 DESCRIPTION It seems that I keep answering the same questions over and over again. I assume that this is because my documentation is deficient, rather than that people don't read the documentation. So this FAQ is an attempt to cut down on the number of personal answers I have to give. At least I can now say "You I read the FAQ, right?". The questions are not in any particular order. The answers assume the current version of Archive::Zip; some of the answers depend on newly added/fixed functionality. =head1 Install problems on RedHat 8 or 9 with Perl 5.8.0 B Archive::Zip won't install on my RedHat 9 system! It's broke! B This has become something of a FAQ. Basically, RedHat broke some versions of Perl by setting LANG to UTF8. They apparently have a fixed version out as an update. You might try running CPAN or creating your Makefile after exporting the LANG environment variable as C L =head1 Why is my zip file so big? B My zip file is actually bigger than what I stored in it! Why? B Some things to make sure of: =over 4 =item Make sure that you are requesting COMPRESSION_DEFLATED if you are storing strings. $member->desiredCompressionMethod( COMPRESSION_DEFLATED ); =item Don't make lots of little files if you can help it. Since zip computes the compression tables for each member, small members without much entropy won't compress well. Instead, if you've got lots of repeated strings in your data, try to combine them into one big member. =item Make sure that you are requesting COMPRESSION_STORED if you are storing things that are already compressed. If you're storing a .zip, .jpg, .mp3, or other compressed file in a zip, then don't compress them again. They'll get bigger. =back =head1 Sample code? B Can you send me code to do (whatever)? B Have you looked in the C directory yet? It contains: =over 4 =item examples/calcSizes.pl -- How to find out how big a Zip file will be before writing it =item examples/copy.pl -- Copies one Zip file to another =item examples/extract.pl -- extract file(s) from a Zip =item examples/mailZip.pl -- make and mail a zip file =item examples/mfh.pl -- demo for use of MockFileHandle =item examples/readScalar.pl -- shows how to use IO::Scalar as the source of a Zip read =item examples/selfex.pl -- a brief example of a self-extracting Zip =item examples/unzipAll.pl -- uses Archive::Zip::Tree to unzip an entire Zip =item examples/updateZip.pl -- shows how to read/modify/write a Zip =item examples/updateTree.pl -- shows how to update a Zip in place =item examples/writeScalar.pl -- shows how to use IO::Scalar as the destination of a Zip write =item examples/writeScalar2.pl -- shows how to use IO::String as the destination of a Zip write =item examples/zip.pl -- Constructs a Zip file =item examples/zipcheck.pl -- One way to check a Zip file for validity =item examples/zipinfo.pl -- Prints out information about a Zip archive file =item examples/zipGrep.pl -- Searches for text in Zip files =item examples/ziptest.pl -- Lists a Zip file and checks member CRCs =item examples/ziprecent.pl -- Puts recent files into a zipfile =item examples/ziptest.pl -- Another way to check a Zip file for validity =back =head1 Can't Read/modify/write same Zip file B Why can't I open a Zip file, add a member, and write it back? I get an error message when I try. B Because Archive::Zip doesn't (and can't, generally) read file contents into memory, the original Zip file is required to stay around until the writing of the new file is completed. The best way to do this is to write the Zip to a temporary file and then rename the temporary file to have the old name (possibly after deleting the old one). Archive::Zip v1.02 added the archive methods C and C to do this simply and carefully. See C for an example of this technique. =head1 File creation time not set B Upon extracting files, I see that their modification (and access) times are set to the time in the Zip archive. However, their creation time is not set to the same time. Why? B Mostly because Perl doesn't give cross-platform access to I. Indeed, many systems (like Unix) don't support such a concept. However, if yours does, you can easily set it. Get the modification time from the member using C. =head1 Can't use Archive::Zip on gzip files B Can I use Archive::Zip to extract Unix gzip files? B No. There is a distinction between Unix gzip files, and Zip archives that also can use the gzip compression. Depending on the format of the gzip file, you can use L, or L to decompress it (and de-archive it in the case of Tar files). You can unzip PKZIP/WinZip/etc/ archives using Archive::Zip (that's what it's for) as long as any compressed members are compressed using Deflate compression. =head1 Add a directory/tree to a Zip B How can I add a directory (or tree) full of files to a Zip? B You can use the Archive::Zip::addTree*() methods: use Archive::Zip; my $zip = Archive::Zip->new(); # add all readable files and directories below . as xyz/* $zip->addTree( '.', 'xyz' ); # add all readable plain files below /abc as def/* $zip->addTree( '/abc', 'def', sub { -f && -r } ); # add all .c files below /tmp as stuff/* $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' ); # add all .o files below /tmp as stuff/* if they aren't writable $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } ); # add all .so files below /tmp that are smaller than 200 bytes as stuff/* $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { -s < 200 } ); # and write them into a file $zip->writeToFileNamed('xxx.zip'); =head1 Extract a directory/tree B How can I extract some (or all) files from a Zip into a different directory? B You can use the Archive::Zip::extractTree() method: ??? || # now extract the same files into /tmpx $zip->extractTree( 'stuff', '/tmpx' ); =head1 Update a directory/tree B How can I update a Zip from a directory tree, adding or replacing only the newer files? B You can use the Archive::Zip::updateTree() method that was added in version 1.09. =head1 Zip times might be off by 1 second B It bothers me greatly that my file times are wrong by one second about half the time. Why don't you do something about it? B Get over it. This is a result of the Zip format storing times in DOS format, which has a resolution of only two seconds. =head1 Zip times don't include time zone information B My file times don't respect time zones. What gives? B If this is important to you, please submit patches to read the various Extra Fields that encode times with time zones. I'm just using the DOS Date/Time, which doesn't have a time zone. =head1 How do I make a self-extracting Zip B I want to make a self-extracting Zip file. Can I do this? B Yes. You can write a self-extracting archive stub (that is, a version of unzip) to the output filehandle that you pass to writeToFileHandle(). See examples/selfex.pl for how to write a self-extracting archive. However, you should understand that this will only work on one kind of platform (the one for which the stub was compiled). =head1 How can I deal with Zips with prepended garbage (i.e. from Sircam) B How can I tell if a Zip has been damaged by adding garbage to the beginning or inside the file? B I added code for this for the Amavis virus scanner. You can query archives for their 'eocdOffset' property, which should be 0: if ($zip->eocdOffset > 0) { warn($zip->eocdOffset . " bytes of garbage at beginning or within Zip") } When members are extracted, this offset will be used to adjust the start of the member if necessary. =head1 Can't extract Shrunk files B I'm trying to extract a file out of a Zip produced by PKZIP, and keep getting this error message: error: Unsupported compression combination: read 6, write 0 B You can't uncompress this archive member. Archive::Zip only supports uncompressed members, and compressed members that are compressed using the compression supported by Compress::Raw::Zlib. That means only Deflated and Stored members. Your file is compressed using the Shrink format, which isn't supported by Compress::Raw::Zlib. You could, perhaps, use a command-line UnZip program (like the Info-Zip one) to extract this. =head1 Can't do decryption B How do I decrypt encrypted Zip members? B With some other program or library. Archive::Zip doesn't support decryption, and probably never will (unless I write it). =head1 How to test file integrity? B How can Archive::Zip can test the validity of a Zip file? B If you try to decompress the file, the gzip streams will report errors if you have garbage. Most of the time. If you try to open the file and a central directory structure can't be found, an error will be reported. When a file is being read, if we can't find a proper PK.. signature in the right places we report a format error. If there is added garbage at the beginning of a Zip file (as inserted by some viruses), you can find out about it, but Archive::Zip will ignore it, and you can still use the archive. When it gets written back out the added stuff will be gone. There are two ready-to-use utilities in the examples directory that can be used to test file integrity, or that you can use as examples for your own code: =over 4 =item examples/zipcheck.pl shows how to use an attempted extraction to test a file. =item examples/ziptest.pl shows how to test CRCs in a file. =back =head1 Duplicate files in Zip? B Archive::Zip let me put the same file in my Zip twice! Why don't you prevent this? B As far as I can tell, this is not disallowed by the Zip spec. If you think it's a bad idea, check for it yourself: $zip->addFile($someFile, $someName) unless $zip->memberNamed($someName); I can even imagine cases where this might be useful (for instance, multiple versions of files). =head1 File ownership/permissions/ACLS/etc B Why doesn't Archive::Zip deal with file ownership, ACLs, etc.? B There is no standard way to represent these in the Zip file format. If you want to send me code to properly handle the various extra fields that have been used to represent these through the years, I'll look at it. =head1 I can't compile but ActiveState only has an old version of Archive::Zip B I've only installed modules using ActiveState's PPM program and repository. But they have a much older version of Archive::Zip than is in CPAN. Will you send me a newer PPM? B Probably not, unless I get lots of extra time. But there's no reason you can't install the version from CPAN. Archive::Zip is pure Perl, so all you need is NMAKE, which you can get for free from Microsoft (see the FAQ in the ActiveState documentation for details on how to install CPAN modules). =head1 My JPEGs (or MP3's) don't compress when I put them into Zips! B How come my JPEGs and MP3's don't compress much when I put them into Zips? B Because they're already compressed. =head1 Under Windows, things lock up/get damaged B I'm using Windows. When I try to use Archive::Zip, my machine locks up/makes funny sounds/displays a BSOD/corrupts data. How can I fix this? B First, try the newest version of Compress::Raw::Zlib. I know of Windows-related problems prior to v1.14 of that library. If that doesn't get rid of the problem, fix your computer or get rid of Windows. =head1 Zip contents in a scalar B I want to read a Zip file from (or write one to) a scalar variable instead of a file. How can I do this? B Use C and the C and C methods. See C and C. =head1 Reading from streams B How do I read from a stream (like for the Info-Zip C program)? B This isn't currently supported, though writing to a stream is. gdata/inst/perl/Archive/Zip/DirectoryMember.pm0000644000176000001440000000371711337525116021072 0ustar ripleyuserspackage Archive::Zip::DirectoryMember; use strict; use File::Path; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw( Archive::Zip::Member ); } use Archive::Zip qw( :ERROR_CODES :UTILITY_METHODS ); sub _newNamed { my $class = shift; my $fileName = shift; # FS name my $newName = shift; # Zip name $newName = _asZipDirName($fileName) unless $newName; my $self = $class->new(@_); $self->{'externalFileName'} = $fileName; $self->fileName($newName); if ( -e $fileName ) { # -e does NOT do a full stat, so we need to do one now if ( -d _ ) { my @stat = stat(_); $self->unixFileAttributes( $stat[2] ); my $mod_t = $stat[9]; if ( $^O eq 'MSWin32' and !$mod_t ) { $mod_t = time(); } $self->setLastModFileDateTimeFromUnix($mod_t); } else { # hmm.. trying to add a non-directory? _error( $fileName, ' exists but is not a directory' ); return undef; } } else { $self->unixFileAttributes( $self->DEFAULT_DIRECTORY_PERMISSIONS ); $self->setLastModFileDateTimeFromUnix( time() ); } return $self; } sub externalFileName { shift->{'externalFileName'}; } sub isDirectory { return 1; } sub extractToFileNamed { my $self = shift; my $name = shift; # local FS name my $attribs = $self->unixFileAttributes() & 07777; mkpath( $name, 0, $attribs ); # croaks on error utime( $self->lastModTime(), $self->lastModTime(), $name ); return AZ_OK; } sub fileName { my $self = shift; my $newName = shift; $newName =~ s{/?$}{/} if defined($newName); return $self->SUPER::fileName($newName); } # So people don't get too confused. This way it looks like the problem # is in their code... sub contents { return wantarray ? ( undef, AZ_OK ) : undef; } 1; gdata/inst/perl/Archive/Zip/BufferedFileHandle.pm0000644000176000001440000000533611337525116021433 0ustar ripleyuserspackage Archive::Zip::BufferedFileHandle; # File handle that uses a string internally and can seek # This is given as a demo for getting a zip file written # to a string. # I probably should just use IO::Scalar instead. # Ned Konz, March 2000 use strict; use IO::File; use Carp; use vars qw{$VERSION}; BEGIN { $VERSION = '1.30'; $VERSION = eval $VERSION; } sub new { my $class = shift || __PACKAGE__; $class = ref($class) || $class; my $self = bless( { content => '', position => 0, size => 0 }, $class ); return $self; } # Utility method to read entire file sub readFromFile { my $self = shift; my $fileName = shift; my $fh = IO::File->new( $fileName, "r" ); CORE::binmode($fh); if ( !$fh ) { Carp::carp("Can't open $fileName: $!\n"); return undef; } local $/ = undef; $self->{content} = <$fh>; $self->{size} = length( $self->{content} ); return $self; } sub contents { my $self = shift; if (@_) { $self->{content} = shift; $self->{size} = length( $self->{content} ); } return $self->{content}; } sub binmode { 1 } sub close { 1 } sub opened { 1 } sub eof { my $self = shift; return $self->{position} >= $self->{size}; } sub seek { my $self = shift; my $pos = shift; my $whence = shift; # SEEK_SET if ( $whence == 0 ) { $self->{position} = $pos; } # SEEK_CUR elsif ( $whence == 1 ) { $self->{position} += $pos; } # SEEK_END elsif ( $whence == 2 ) { $self->{position} = $self->{size} + $pos; } else { return 0; } return 1; } sub tell { return shift->{position}; } # Copy my data to given buffer sub read { my $self = shift; my $buf = \( $_[0] ); shift; my $len = shift; my $offset = shift || 0; $$buf = '' if not defined($$buf); my $bytesRead = ( $self->{position} + $len > $self->{size} ) ? ( $self->{size} - $self->{position} ) : $len; substr( $$buf, $offset, $bytesRead ) = substr( $self->{content}, $self->{position}, $bytesRead ); $self->{position} += $bytesRead; return $bytesRead; } # Copy given buffer to me sub write { my $self = shift; my $buf = \( $_[0] ); shift; my $len = shift; my $offset = shift || 0; $$buf = '' if not defined($$buf); my $bufLen = length($$buf); my $bytesWritten = ( $offset + $len > $bufLen ) ? $bufLen - $offset : $len; substr( $self->{content}, $self->{position}, $bytesWritten ) = substr( $$buf, $offset, $bytesWritten ); $self->{size} = length( $self->{content} ); return $bytesWritten; } sub clearerr() { 1 } 1; gdata/inst/perl/Archive/Zip/Archive.pm0000644000176000001440000007132311337525116017355 0ustar ripleyuserspackage Archive::Zip::Archive; # Represents a generic ZIP archive use strict; use File::Path; use File::Find (); use File::Spec (); use File::Copy (); use File::Basename; use Cwd; use vars qw( $VERSION @ISA ); BEGIN { $VERSION = '1.30'; @ISA = qw( Archive::Zip ); } use Archive::Zip qw( :CONSTANTS :ERROR_CODES :PKZIP_CONSTANTS :UTILITY_METHODS ); # Note that this returns undef on read errors, else new zip object. sub new { my $class = shift; my $self = bless( { 'diskNumber' => 0, 'diskNumberWithStartOfCentralDirectory' => 0, 'numberOfCentralDirectoriesOnThisDisk' => 0, # shld be # of members 'numberOfCentralDirectories' => 0, # shld be # of members 'centralDirectorySize' => 0, # must re-compute on write 'centralDirectoryOffsetWRTStartingDiskNumber' => 0, # must re-compute 'writeEOCDOffset' => 0, 'writeCentralDirectoryOffset' => 0, 'zipfileComment' => '', 'eocdOffset' => 0, 'fileName' => '' }, $class ); $self->{'members'} = []; my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{filename} : shift; if ($fileName) { my $status = $self->read($fileName); return $status == AZ_OK ? $self : undef; } return $self; } sub storeSymbolicLink { my $self = shift; $self->{'storeSymbolicLink'} = shift; } sub members { @{ shift->{'members'} }; } sub numberOfMembers { scalar( shift->members() ); } sub memberNames { my $self = shift; return map { $_->fileName() } $self->members(); } # return ref to member with given name or undef sub memberNamed { my $self = shift; my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{zipName} : shift; foreach my $member ( $self->members() ) { return $member if $member->fileName() eq $fileName; } return undef; } sub membersMatching { my $self = shift; my $pattern = ( ref( $_[0] ) eq 'HASH' ) ? shift->{regex} : shift; return grep { $_->fileName() =~ /$pattern/ } $self->members(); } sub diskNumber { shift->{'diskNumber'}; } sub diskNumberWithStartOfCentralDirectory { shift->{'diskNumberWithStartOfCentralDirectory'}; } sub numberOfCentralDirectoriesOnThisDisk { shift->{'numberOfCentralDirectoriesOnThisDisk'}; } sub numberOfCentralDirectories { shift->{'numberOfCentralDirectories'}; } sub centralDirectorySize { shift->{'centralDirectorySize'}; } sub centralDirectoryOffsetWRTStartingDiskNumber { shift->{'centralDirectoryOffsetWRTStartingDiskNumber'}; } sub zipfileComment { my $self = shift; my $comment = $self->{'zipfileComment'}; if (@_) { my $new_comment = ( ref( $_[0] ) eq 'HASH' ) ? shift->{comment} : shift; $self->{'zipfileComment'} = pack( 'C0a*', $new_comment ); # avoid unicode } return $comment; } sub eocdOffset { shift->{'eocdOffset'}; } # Return the name of the file last read. sub fileName { shift->{'fileName'}; } sub removeMember { my $self = shift; my $member = ( ref( $_[0] ) eq 'HASH' ) ? shift->{memberOrZipName} : shift; $member = $self->memberNamed($member) unless ref($member); return undef unless $member; my @newMembers = grep { $_ != $member } $self->members(); $self->{'members'} = \@newMembers; return $member; } sub replaceMember { my $self = shift; my ( $oldMember, $newMember ); if ( ref( $_[0] ) eq 'HASH' ) { $oldMember = $_[0]->{memberOrZipName}; $newMember = $_[0]->{newMember}; } else { ( $oldMember, $newMember ) = @_; } $oldMember = $self->memberNamed($oldMember) unless ref($oldMember); return undef unless $oldMember; return undef unless $newMember; my @newMembers = map { ( $_ == $oldMember ) ? $newMember : $_ } $self->members(); $self->{'members'} = \@newMembers; return $oldMember; } sub extractMember { my $self = shift; my ( $member, $name ); if ( ref( $_[0] ) eq 'HASH' ) { $member = $_[0]->{memberOrZipName}; $name = $_[0]->{name}; } else { ( $member, $name ) = @_; } $member = $self->memberNamed($member) unless ref($member); return _error('member not found') unless $member; my $originalSize = $member->compressedSize(); my ( $volumeName, $dirName, $fileName ); if ( defined($name) ) { ( $volumeName, $dirName, $fileName ) = File::Spec->splitpath($name); $dirName = File::Spec->catpath( $volumeName, $dirName, '' ); } else { $name = $member->fileName(); ( $dirName = $name ) =~ s{[^/]*$}{}; $dirName = Archive::Zip::_asLocalName($dirName); $name = Archive::Zip::_asLocalName($name); } if ( $dirName && !-d $dirName ) { mkpath($dirName); return _ioError("can't create dir $dirName") if ( !-d $dirName ); } my $rc = $member->extractToFileNamed( $name, @_ ); # TODO refactor this fix into extractToFileNamed() $member->{'compressedSize'} = $originalSize; return $rc; } sub extractMemberWithoutPaths { my $self = shift; my ( $member, $name ); if ( ref( $_[0] ) eq 'HASH' ) { $member = $_[0]->{memberOrZipName}; $name = $_[0]->{name}; } else { ( $member, $name ) = @_; } $member = $self->memberNamed($member) unless ref($member); return _error('member not found') unless $member; my $originalSize = $member->compressedSize(); return AZ_OK if $member->isDirectory(); unless ($name) { $name = $member->fileName(); $name =~ s{.*/}{}; # strip off directories, if any $name = Archive::Zip::_asLocalName($name); } my $rc = $member->extractToFileNamed( $name, @_ ); $member->{'compressedSize'} = $originalSize; return $rc; } sub addMember { my $self = shift; my $newMember = ( ref( $_[0] ) eq 'HASH' ) ? shift->{member} : shift; push( @{ $self->{'members'} }, $newMember ) if $newMember; return $newMember; } sub addFile { my $self = shift; my ( $fileName, $newName, $compressionLevel ); if ( ref( $_[0] ) eq 'HASH' ) { $fileName = $_[0]->{filename}; $newName = $_[0]->{zipName}; $compressionLevel = $_[0]->{compressionLevel}; } else { ( $fileName, $newName, $compressionLevel ) = @_; } my $newMember = $self->ZIPMEMBERCLASS->newFromFile( $fileName, $newName ); $newMember->desiredCompressionLevel($compressionLevel); if ( $self->{'storeSymbolicLink'} && -l $fileName ) { my $newMember = $self->ZIPMEMBERCLASS->newFromString(readlink $fileName, $newName); # For symbolic links, External File Attribute is set to 0xA1FF0000 by Info-ZIP $newMember->{'externalFileAttributes'} = 0xA1FF0000; $self->addMember($newMember); } else { $self->addMember($newMember); } return $newMember; } sub addString { my $self = shift; my ( $stringOrStringRef, $name, $compressionLevel ); if ( ref( $_[0] ) eq 'HASH' ) { $stringOrStringRef = $_[0]->{string}; $name = $_[0]->{zipName}; $compressionLevel = $_[0]->{compressionLevel}; } else { ( $stringOrStringRef, $name, $compressionLevel ) = @_;; } my $newMember = $self->ZIPMEMBERCLASS->newFromString( $stringOrStringRef, $name ); $newMember->desiredCompressionLevel($compressionLevel); return $self->addMember($newMember); } sub addDirectory { my $self = shift; my ( $name, $newName ); if ( ref( $_[0] ) eq 'HASH' ) { $name = $_[0]->{directoryName}; $newName = $_[0]->{zipName}; } else { ( $name, $newName ) = @_; } my $newMember = $self->ZIPMEMBERCLASS->newDirectoryNamed( $name, $newName ); if ( $self->{'storeSymbolicLink'} && -l $name ) { my $link = readlink $name; ( $newName =~ s{/$}{} ) if $newName; # Strip trailing / my $newMember = $self->ZIPMEMBERCLASS->newFromString($link, $newName); # For symbolic links, External File Attribute is set to 0xA1FF0000 by Info-ZIP $newMember->{'externalFileAttributes'} = 0xA1FF0000; $self->addMember($newMember); } else { $self->addMember($newMember); } return $newMember; } # add either a file or a directory. sub addFileOrDirectory { my $self = shift; my ( $name, $newName, $compressionLevel ); if ( ref( $_[0] ) eq 'HASH' ) { $name = $_[0]->{name}; $newName = $_[0]->{zipName}; $compressionLevel = $_[0]->{compressionLevel}; } else { ( $name, $newName, $compressionLevel ) = @_; } $name =~ s{/$}{}; if ( $newName ) { $newName =~ s{/$}{}; } else { $newName = $name; } if ( -f $name ) { return $self->addFile( $name, $newName, $compressionLevel ); } elsif ( -d $name ) { return $self->addDirectory( $name, $newName ); } else { return _error("$name is neither a file nor a directory"); } } sub contents { my $self = shift; my ( $member, $newContents ); if ( ref( $_[0] ) eq 'HASH' ) { $member = $_[0]->{memberOrZipName}; $newContents = $_[0]->{contents}; } else { ( $member, $newContents ) = @_; } return _error('No member name given') unless $member; $member = $self->memberNamed($member) unless ref($member); return undef unless $member; return $member->contents($newContents); } sub writeToFileNamed { my $self = shift; my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{filename} : shift; # local FS format foreach my $member ( $self->members() ) { if ( $member->_usesFileNamed($fileName) ) { return _error( "$fileName is needed by member " . $member->fileName() . "; consider using overwrite() or overwriteAs() instead." ); } } my ( $status, $fh ) = _newFileHandle( $fileName, 'w' ); return _ioError("Can't open $fileName for write") unless $status; my $retval = $self->writeToFileHandle( $fh, 1 ); $fh->close(); $fh = undef; return $retval; } # It is possible to write data to the FH before calling this, # perhaps to make a self-extracting archive. sub writeToFileHandle { my $self = shift; my ( $fh, $fhIsSeekable ); if ( ref( $_[0] ) eq 'HASH' ) { $fh = $_[0]->{fileHandle}; $fhIsSeekable = exists( $_[0]->{seek} ) ? $_[0]->{seek} : _isSeekable($fh); } else { $fh = shift; $fhIsSeekable = @_ ? shift : _isSeekable($fh); } return _error('No filehandle given') unless $fh; return _ioError('filehandle not open') unless $fh->opened(); _binmode($fh); # Find out where the current position is. my $offset = $fhIsSeekable ? $fh->tell() : 0; $offset = 0 if $offset < 0; foreach my $member ( $self->members() ) { my $retval = $member->_writeToFileHandle( $fh, $fhIsSeekable, $offset ); $member->endRead(); return $retval if $retval != AZ_OK; $offset += $member->_localHeaderSize() + $member->_writeOffset(); $offset += $member->hasDataDescriptor() ? DATA_DESCRIPTOR_LENGTH + SIGNATURE_LENGTH : 0; # changed this so it reflects the last successful position $self->{'writeCentralDirectoryOffset'} = $offset; } return $self->writeCentralDirectory($fh); } # Write zip back to the original file, # as safely as possible. # Returns AZ_OK if successful. sub overwrite { my $self = shift; return $self->overwriteAs( $self->{'fileName'} ); } # Write zip to the specified file, # as safely as possible. # Returns AZ_OK if successful. sub overwriteAs { my $self = shift; my $zipName = ( ref( $_[0] ) eq 'HASH' ) ? $_[0]->{filename} : shift; return _error("no filename in overwriteAs()") unless defined($zipName); my ( $fh, $tempName ) = Archive::Zip::tempFile(); return _error( "Can't open temp file", $! ) unless $fh; ( my $backupName = $zipName ) =~ s{(\.[^.]*)?$}{.zbk}; my $status = $self->writeToFileHandle($fh); $fh->close(); $fh = undef; if ( $status != AZ_OK ) { unlink($tempName); _printError("Can't write to $tempName"); return $status; } my $err; # rename the zip if ( -f $zipName && !rename( $zipName, $backupName ) ) { $err = $!; unlink($tempName); return _error( "Can't rename $zipName as $backupName", $err ); } # move the temp to the original name (possibly copying) unless ( File::Copy::move( $tempName, $zipName ) ) { $err = $!; rename( $backupName, $zipName ); unlink($tempName); return _error( "Can't move $tempName to $zipName", $err ); } # unlink the backup if ( -f $backupName && !unlink($backupName) ) { $err = $!; return _error( "Can't unlink $backupName", $err ); } return AZ_OK; } # Used only during writing sub _writeCentralDirectoryOffset { shift->{'writeCentralDirectoryOffset'}; } sub _writeEOCDOffset { shift->{'writeEOCDOffset'}; } # Expects to have _writeEOCDOffset() set sub _writeEndOfCentralDirectory { my ( $self, $fh ) = @_; $self->_print($fh, END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING) or return _ioError('writing EOCD Signature'); my $zipfileCommentLength = length( $self->zipfileComment() ); my $header = pack( END_OF_CENTRAL_DIRECTORY_FORMAT, 0, # {'diskNumber'}, 0, # {'diskNumberWithStartOfCentralDirectory'}, $self->numberOfMembers(), # {'numberOfCentralDirectoriesOnThisDisk'}, $self->numberOfMembers(), # {'numberOfCentralDirectories'}, $self->_writeEOCDOffset() - $self->_writeCentralDirectoryOffset(), $self->_writeCentralDirectoryOffset(), $zipfileCommentLength ); $self->_print($fh, $header) or return _ioError('writing EOCD header'); if ($zipfileCommentLength) { $self->_print($fh, $self->zipfileComment() ) or return _ioError('writing zipfile comment'); } return AZ_OK; } # $offset can be specified to truncate a zip file. sub writeCentralDirectory { my $self = shift; my ( $fh, $offset ); if ( ref( $_[0] ) eq 'HASH' ) { $fh = $_[0]->{fileHandle}; $offset = $_[0]->{offset}; } else { ( $fh, $offset ) = @_; } if ( defined($offset) ) { $self->{'writeCentralDirectoryOffset'} = $offset; $fh->seek( $offset, IO::Seekable::SEEK_SET ) or return _ioError('seeking to write central directory'); } else { $offset = $self->_writeCentralDirectoryOffset(); } foreach my $member ( $self->members() ) { my $status = $member->_writeCentralDirectoryFileHeader($fh); return $status if $status != AZ_OK; $offset += $member->_centralDirectoryHeaderSize(); $self->{'writeEOCDOffset'} = $offset; } return $self->_writeEndOfCentralDirectory($fh); } sub read { my $self = shift; my $fileName = ( ref( $_[0] ) eq 'HASH' ) ? shift->{filename} : shift; return _error('No filename given') unless $fileName; my ( $status, $fh ) = _newFileHandle( $fileName, 'r' ); return _ioError("opening $fileName for read") unless $status; $status = $self->readFromFileHandle( $fh, $fileName ); return $status if $status != AZ_OK; $fh->close(); $self->{'fileName'} = $fileName; return AZ_OK; } sub readFromFileHandle { my $self = shift; my ( $fh, $fileName ); if ( ref( $_[0] ) eq 'HASH' ) { $fh = $_[0]->{fileHandle}; $fileName = $_[0]->{filename}; } else { ( $fh, $fileName ) = @_; } $fileName = $fh unless defined($fileName); return _error('No filehandle given') unless $fh; return _ioError('filehandle not open') unless $fh->opened(); _binmode($fh); $self->{'fileName'} = "$fh"; # TODO: how to support non-seekable zips? return _error('file not seekable') unless _isSeekable($fh); $fh->seek( 0, 0 ); # rewind the file my $status = $self->_findEndOfCentralDirectory($fh); return $status if $status != AZ_OK; my $eocdPosition = $fh->tell(); $status = $self->_readEndOfCentralDirectory($fh); return $status if $status != AZ_OK; $fh->seek( $eocdPosition - $self->centralDirectorySize(), IO::Seekable::SEEK_SET ) or return _ioError("Can't seek $fileName"); # Try to detect garbage at beginning of archives # This should be 0 $self->{'eocdOffset'} = $eocdPosition - $self->centralDirectorySize() # here - $self->centralDirectoryOffsetWRTStartingDiskNumber(); for ( ; ; ) { my $newMember = $self->ZIPMEMBERCLASS->_newFromZipFile( $fh, $fileName, $self->eocdOffset() ); my $signature; ( $status, $signature ) = _readSignature( $fh, $fileName ); return $status if $status != AZ_OK; last if $signature == END_OF_CENTRAL_DIRECTORY_SIGNATURE; $status = $newMember->_readCentralDirectoryFileHeader(); return $status if $status != AZ_OK; $status = $newMember->endRead(); return $status if $status != AZ_OK; $newMember->_becomeDirectoryIfNecessary(); push( @{ $self->{'members'} }, $newMember ); } return AZ_OK; } # Read EOCD, starting from position before signature. # Return AZ_OK on success. sub _readEndOfCentralDirectory { my $self = shift; my $fh = shift; # Skip past signature $fh->seek( SIGNATURE_LENGTH, IO::Seekable::SEEK_CUR ) or return _ioError("Can't seek past EOCD signature"); my $header = ''; my $bytesRead = $fh->read( $header, END_OF_CENTRAL_DIRECTORY_LENGTH ); if ( $bytesRead != END_OF_CENTRAL_DIRECTORY_LENGTH ) { return _ioError("reading end of central directory"); } my $zipfileCommentLength; ( $self->{'diskNumber'}, $self->{'diskNumberWithStartOfCentralDirectory'}, $self->{'numberOfCentralDirectoriesOnThisDisk'}, $self->{'numberOfCentralDirectories'}, $self->{'centralDirectorySize'}, $self->{'centralDirectoryOffsetWRTStartingDiskNumber'}, $zipfileCommentLength ) = unpack( END_OF_CENTRAL_DIRECTORY_FORMAT, $header ); if ($zipfileCommentLength) { my $zipfileComment = ''; $bytesRead = $fh->read( $zipfileComment, $zipfileCommentLength ); if ( $bytesRead != $zipfileCommentLength ) { return _ioError("reading zipfile comment"); } $self->{'zipfileComment'} = $zipfileComment; } return AZ_OK; } # Seek in my file to the end, then read backwards until we find the # signature of the central directory record. Leave the file positioned right # before the signature. Returns AZ_OK if success. sub _findEndOfCentralDirectory { my $self = shift; my $fh = shift; my $data = ''; $fh->seek( 0, IO::Seekable::SEEK_END ) or return _ioError("seeking to end"); my $fileLength = $fh->tell(); if ( $fileLength < END_OF_CENTRAL_DIRECTORY_LENGTH + 4 ) { return _formatError("file is too short"); } my $seekOffset = 0; my $pos = -1; for ( ; ; ) { $seekOffset += 512; $seekOffset = $fileLength if ( $seekOffset > $fileLength ); $fh->seek( -$seekOffset, IO::Seekable::SEEK_END ) or return _ioError("seek failed"); my $bytesRead = $fh->read( $data, $seekOffset ); if ( $bytesRead != $seekOffset ) { return _ioError("read failed"); } $pos = rindex( $data, END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING ); last if ( $pos >= 0 or $seekOffset == $fileLength or $seekOffset >= $Archive::Zip::ChunkSize ); } if ( $pos >= 0 ) { $fh->seek( $pos - $seekOffset, IO::Seekable::SEEK_CUR ) or return _ioError("seeking to EOCD"); return AZ_OK; } else { return _formatError("can't find EOCD signature"); } } # Used to avoid taint problems when chdir'ing. # Not intended to increase security in any way; just intended to shut up the -T # complaints. If your Cwd module is giving you unreliable returns from cwd() # you have bigger problems than this. sub _untaintDir { my $dir = shift; $dir =~ m/\A(.+)\z/s; return $1; } sub addTree { my $self = shift; my ( $root, $dest, $pred, $compressionLevel ); if ( ref( $_[0] ) eq 'HASH' ) { $root = $_[0]->{root}; $dest = $_[0]->{zipName}; $pred = $_[0]->{select}; $compressionLevel = $_[0]->{compressionLevel}; } else { ( $root, $dest, $pred, $compressionLevel ) = @_; } return _error("root arg missing in call to addTree()") unless defined($root); $dest = '' unless defined($dest); $pred = sub { -r } unless defined($pred); my @files; my $startDir = _untaintDir( cwd() ); return _error( 'undef returned by _untaintDir on cwd ', cwd() ) unless $startDir; # This avoids chdir'ing in Find, in a way compatible with older # versions of File::Find. my $wanted = sub { local $main::_ = $File::Find::name; my $dir = _untaintDir($File::Find::dir); chdir($startDir); push( @files, $File::Find::name ) if (&$pred); chdir($dir); }; File::Find::find( $wanted, $root ); my $rootZipName = _asZipDirName( $root, 1 ); # with trailing slash my $pattern = $rootZipName eq './' ? '^' : "^\Q$rootZipName\E"; $dest = _asZipDirName( $dest, 1 ); # with trailing slash foreach my $fileName (@files) { my $isDir = -d $fileName; # normalize, remove leading ./ my $archiveName = _asZipDirName( $fileName, $isDir ); if ( $archiveName eq $rootZipName ) { $archiveName = $dest } else { $archiveName =~ s{$pattern}{$dest} } next if $archiveName =~ m{^\.?/?$}; # skip current dir my $member = $isDir ? $self->addDirectory( $fileName, $archiveName ) : $self->addFile( $fileName, $archiveName ); $member->desiredCompressionLevel($compressionLevel); return _error("add $fileName failed in addTree()") if !$member; } return AZ_OK; } sub addTreeMatching { my $self = shift; my ( $root, $dest, $pattern, $pred, $compressionLevel ); if ( ref( $_[0] ) eq 'HASH' ) { $root = $_[0]->{root}; $dest = $_[0]->{zipName}; $pattern = $_[0]->{pattern}; $pred = $_[0]->{select}; $compressionLevel = $_[0]->{compressionLevel}; } else { ( $root, $dest, $pattern, $pred, $compressionLevel ) = @_; } return _error("root arg missing in call to addTreeMatching()") unless defined($root); $dest = '' unless defined($dest); return _error("pattern missing in call to addTreeMatching()") unless defined($pattern); my $matcher = $pred ? sub { m{$pattern} && &$pred } : sub { m{$pattern} && -r }; return $self->addTree( $root, $dest, $matcher, $compressionLevel ); } # $zip->extractTree( $root, $dest [, $volume] ); # # $root and $dest are Unix-style. # $volume is in local FS format. # sub extractTree { my $self = shift; my ( $root, $dest, $volume ); if ( ref( $_[0] ) eq 'HASH' ) { $root = $_[0]->{root}; $dest = $_[0]->{zipName}; $volume = $_[0]->{volume}; } else { ( $root, $dest, $volume ) = @_; } $root = '' unless defined($root); $dest = './' unless defined($dest); my $pattern = "^\Q$root"; my @members = $self->membersMatching($pattern); foreach my $member (@members) { my $fileName = $member->fileName(); # in Unix format $fileName =~ s{$pattern}{$dest}; # in Unix format # convert to platform format: $fileName = Archive::Zip::_asLocalName( $fileName, $volume ); my $status = $member->extractToFileNamed($fileName); return $status if $status != AZ_OK; } return AZ_OK; } # $zip->updateMember( $memberOrName, $fileName ); # Returns (possibly updated) member, if any; undef on errors. sub updateMember { my $self = shift; my ( $oldMember, $fileName ); if ( ref( $_[0] ) eq 'HASH' ) { $oldMember = $_[0]->{memberOrZipName}; $fileName = $_[0]->{name}; } else { ( $oldMember, $fileName ) = @_; } if ( !defined($fileName) ) { _error("updateMember(): missing fileName argument"); return undef; } my @newStat = stat($fileName); if ( !@newStat ) { _ioError("Can't stat $fileName"); return undef; } my $isDir = -d _; my $memberName; if ( ref($oldMember) ) { $memberName = $oldMember->fileName(); } else { $oldMember = $self->memberNamed( $memberName = $oldMember ) || $self->memberNamed( $memberName = _asZipDirName( $oldMember, $isDir ) ); } unless ( defined($oldMember) && $oldMember->lastModTime() == $newStat[9] && $oldMember->isDirectory() == $isDir && ( $isDir || ( $oldMember->uncompressedSize() == $newStat[7] ) ) ) { # create the new member my $newMember = $isDir ? $self->ZIPMEMBERCLASS->newDirectoryNamed( $fileName, $memberName ) : $self->ZIPMEMBERCLASS->newFromFile( $fileName, $memberName ); unless ( defined($newMember) ) { _error("creation of member $fileName failed in updateMember()"); return undef; } # replace old member or append new one if ( defined($oldMember) ) { $self->replaceMember( $oldMember, $newMember ); } else { $self->addMember($newMember); } return $newMember; } return $oldMember; } # $zip->updateTree( $root, [ $dest, [ $pred [, $mirror]]] ); # # This takes the same arguments as addTree, but first checks to see # whether the file or directory already exists in the zip file. # # If the fourth argument $mirror is true, then delete all my members # if corresponding files weren't found. sub updateTree { my $self = shift; my ( $root, $dest, $pred, $mirror, $compressionLevel ); if ( ref( $_[0] ) eq 'HASH' ) { $root = $_[0]->{root}; $dest = $_[0]->{zipName}; $pred = $_[0]->{select}; $mirror = $_[0]->{mirror}; $compressionLevel = $_[0]->{compressionLevel}; } else { ( $root, $dest, $pred, $mirror, $compressionLevel ) = @_; } return _error("root arg missing in call to updateTree()") unless defined($root); $dest = '' unless defined($dest); $pred = sub { -r } unless defined($pred); $dest = _asZipDirName( $dest, 1 ); my $rootZipName = _asZipDirName( $root, 1 ); # with trailing slash my $pattern = $rootZipName eq './' ? '^' : "^\Q$rootZipName\E"; my @files; my $startDir = _untaintDir( cwd() ); return _error( 'undef returned by _untaintDir on cwd ', cwd() ) unless $startDir; # This avoids chdir'ing in Find, in a way compatible with older # versions of File::Find. my $wanted = sub { local $main::_ = $File::Find::name; my $dir = _untaintDir($File::Find::dir); chdir($startDir); push( @files, $File::Find::name ) if (&$pred); chdir($dir); }; File::Find::find( $wanted, $root ); # Now @files has all the files that I could potentially be adding to # the zip. Only add the ones that are necessary. # For each file (updated or not), add its member name to @done. my %done; foreach my $fileName (@files) { my @newStat = stat($fileName); my $isDir = -d _; # normalize, remove leading ./ my $memberName = _asZipDirName( $fileName, $isDir ); if ( $memberName eq $rootZipName ) { $memberName = $dest } else { $memberName =~ s{$pattern}{$dest} } next if $memberName =~ m{^\.?/?$}; # skip current dir $done{$memberName} = 1; my $changedMember = $self->updateMember( $memberName, $fileName ); $changedMember->desiredCompressionLevel($compressionLevel); return _error("updateTree failed to update $fileName") unless ref($changedMember); } # @done now has the archive names corresponding to all the found files. # If we're mirroring, delete all those members that aren't in @done. if ($mirror) { foreach my $member ( $self->members() ) { $self->removeMember($member) unless $done{ $member->fileName() }; } } return AZ_OK; } 1; gdata/inst/perl/Archive/README-Archive-Zip0000644000176000001440000013411111337525124017665 0ustar ripleyusersNAME Archive::Zip - Provide an interface to ZIP archive files. SYNOPSIS # Create a Zip file use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); my $zip = Archive::Zip->new(); # Add a directory my $dir_member = $zip->addDirectory( 'dirname/' ); # Add a file from a string with compression my $string_member = $zip->addString( 'This is a test', 'stringMember.txt' ); $string_member->desiredCompressionMethod( COMPRESSION_DEFLATED ); # Add a file from disk my $file_member = $zip->addFile( 'xyz.pl', 'AnotherName.pl' ); # Save the Zip file unless ( $zip->writeToFileNamed('someZip.zip') == AZ_OK ) { die 'write error'; } # Read a Zip file my $somezip = Archive::Zip->new(); unless ( $somezip->read( 'someZip.zip' ) == AZ_OK ) { die 'read error'; } # Change the compression type for a file in the Zip my $member = $somezip->memberNamed( 'stringMember.txt' ); $member->desiredCompressionMethod( COMPRESSION_STORED ); unless ( $zip->writeToFileNamed( 'someOtherZip.zip' ) == AZ_OK ) { die 'write error'; } DESCRIPTION The Archive::Zip module allows a Perl program to create, manipulate, read, and write Zip archive files. Zip archives can be created, or you can read from existing zip files. Once created, they can be written to files, streams, or strings. Members can be added, removed, extracted, replaced, rearranged, and enumerated. They can also be renamed or have their dates, comments, or other attributes queried or modified. Their data can be compressed or uncompressed as needed. Members can be created from members in existing Zip files, or from existing directories, files, or strings. This module uses the Compress::Raw::Zlib library to read and write the compressed streams inside the files. One can use Archive::Zip::MemberRead to read the zip file archive members as if they were files. File Naming Regardless of what your local file system uses for file naming, names in a Zip file are in Unix format (*forward* slashes (/) separating directory names, etc.). "Archive::Zip" tries to be consistent with file naming conventions, and will translate back and forth between native and Zip file names. However, it can't guess which format names are in. So two rules control what kind of file name you must pass various routines: Names of files are in local format. "File::Spec" and "File::Basename" are used for various file operations. When you're referring to a file on your system, use its file naming conventions. Names of archive members are in Unix format. This applies to every method that refers to an archive member, or provides a name for new archive members. The "extract()" methods that can take one or two names will convert from local to zip names if you call them with a single name. Archive::Zip Object Model Overview Archive::Zip::Archive objects are what you ordinarily deal with. These maintain the structure of a zip file, without necessarily holding data. When a zip is read from a disk file, the (possibly compressed) data still lives in the file, not in memory. Archive members hold information about the individual members, but not (usually) the actual member data. When the zip is written to a (different) file, the member data is compressed or copied as needed. It is possible to make archive members whose data is held in a string in memory, but this is not done when a zip file is read. Directory members don't have any data. Inheritance Exporter Archive::Zip Common base class, has defs. Archive::Zip::Archive A Zip archive. Archive::Zip::Member Abstract superclass for all members. Archive::Zip::StringMember Member made from a string Archive::Zip::FileMember Member made from an external file Archive::Zip::ZipFileMember Member that lives in a zip file Archive::Zip::NewFileMember Member whose data is in a file Archive::Zip::DirectoryMember Member that is a directory EXPORTS :CONSTANTS Exports the following constants: FA_MSDOS FA_UNIX GPBF_ENCRYPTED_MASK GPBF_DEFLATING_COMPRESSION_MASK GPBF_HAS_DATA_DESCRIPTOR_MASK COMPRESSION_STORED COMPRESSION_DEFLATED IFA_TEXT_FILE_MASK IFA_TEXT_FILE IFA_BINARY_FILE COMPRESSION_LEVEL_NONE COMPRESSION_LEVEL_DEFAULT COMPRESSION_LEVEL_FASTEST COMPRESSION_LEVEL_BEST_COMPRESSION :MISC_CONSTANTS Exports the following constants (only necessary for extending the module): FA_AMIGA FA_VAX_VMS FA_VM_CMS FA_ATARI_ST FA_OS2_HPFS FA_MACINTOSH FA_Z_SYSTEM FA_CPM FA_WINDOWS_NTFS GPBF_IMPLODING_8K_SLIDING_DICTIONARY_MASK GPBF_IMPLODING_3_SHANNON_FANO_TREES_MASK GPBF_IS_COMPRESSED_PATCHED_DATA_MASK COMPRESSION_SHRUNK DEFLATING_COMPRESSION_NORMAL DEFLATING_COMPRESSION_MAXIMUM DEFLATING_COMPRESSION_FAST DEFLATING_COMPRESSION_SUPER_FAST COMPRESSION_REDUCED_1 COMPRESSION_REDUCED_2 COMPRESSION_REDUCED_3 COMPRESSION_REDUCED_4 COMPRESSION_IMPLODED COMPRESSION_TOKENIZED COMPRESSION_DEFLATED_ENHANCED COMPRESSION_PKWARE_DATA_COMPRESSION_LIBRARY_IMPLODED :ERROR_CODES Explained below. Returned from most methods. AZ_OK AZ_STREAM_END AZ_ERROR AZ_FORMAT_ERROR AZ_IO_ERROR ERROR CODES Many of the methods in Archive::Zip return error codes. These are implemented as inline subroutines, using the "use constant" pragma. They can be imported into your namespace using the ":ERROR_CODES" tag: use Archive::Zip qw( :ERROR_CODES ); ... unless ( $zip->read( 'myfile.zip' ) == AZ_OK ) { die "whoops!"; } AZ_OK (0) Everything is fine. AZ_STREAM_END (1) The read stream (or central directory) ended normally. AZ_ERROR (2) There was some generic kind of error. AZ_FORMAT_ERROR (3) There is a format error in a ZIP file being read. AZ_IO_ERROR (4) There was an IO error. Compression Archive::Zip allows each member of a ZIP file to be compressed (using the Deflate algorithm) or uncompressed. Other compression algorithms that some versions of ZIP have been able to produce are not supported. Each member has two compression methods: the one it's stored as (this is always COMPRESSION_STORED for string and external file members), and the one you desire for the member in the zip file. These can be different, of course, so you can make a zip member that is not compressed out of one that is, and vice versa. You can inquire about the current compression and set the desired compression method: my $member = $zip->memberNamed( 'xyz.txt' ); $member->compressionMethod(); # return current compression # set to read uncompressed $member->desiredCompressionMethod( COMPRESSION_STORED ); # set to read compressed $member->desiredCompressionMethod( COMPRESSION_DEFLATED ); There are two different compression methods: COMPRESSION_STORED File is stored (no compression) COMPRESSION_DEFLATED File is Deflated Compression Levels If a member's desiredCompressionMethod is COMPRESSION_DEFLATED, you can choose different compression levels. This choice may affect the speed of compression and decompression, as well as the size of the compressed member data. $member->desiredCompressionLevel( 9 ); The levels given can be: 0 or COMPRESSION_LEVEL_NONE This is the same as saying $member->desiredCompressionMethod( COMPRESSION_STORED ); 1 .. 9 1 gives the best speed and worst compression, and 9 gives the best compression and worst speed. COMPRESSION_LEVEL_FASTEST This is a synonym for level 1. COMPRESSION_LEVEL_BEST_COMPRESSION This is a synonym for level 9. COMPRESSION_LEVEL_DEFAULT This gives a good compromise between speed and compression, and is currently equivalent to 6 (this is in the zlib code). This is the level that will be used if not specified. Archive::Zip Methods The Archive::Zip class (and its invisible subclass Archive::Zip::Archive) implement generic zip file functionality. Creating a new Archive::Zip object actually makes an Archive::Zip::Archive object, but you don't have to worry about this unless you're subclassing. Constructor new( [$fileName] ) Make a new, empty zip archive. my $zip = Archive::Zip->new(); If an additional argument is passed, new() will call read() to read the contents of an archive: my $zip = Archive::Zip->new( 'xyz.zip' ); If a filename argument is passed and the read fails for any reason, new will return undef. For this reason, it may be better to call read separately. Zip Archive Utility Methods These Archive::Zip methods may be called as functions or as object methods. Do not call them as class methods: $zip = Archive::Zip->new(); $crc = Archive::Zip::computeCRC32( 'ghijkl' ); # OK $crc = $zip->computeCRC32( 'ghijkl' ); # also OK $crc = Archive::Zip->computeCRC32( 'ghijkl' ); # NOT OK Archive::Zip::computeCRC32( $string [, $crc] ) This is a utility function that uses the Compress::Raw::Zlib CRC routine to compute a CRC-32. You can get the CRC of a string: $crc = Archive::Zip::computeCRC32( $string ); Or you can compute the running CRC: $crc = 0; $crc = Archive::Zip::computeCRC32( 'abcdef', $crc ); $crc = Archive::Zip::computeCRC32( 'ghijkl', $crc ); Archive::Zip::setChunkSize( $number ) Report or change chunk size used for reading and writing. This can make big differences in dealing with large files. Currently, this defaults to 32K. This also changes the chunk size used for Compress::Raw::Zlib. You must call setChunkSize() before reading or writing. This is not exportable, so you must call it like: Archive::Zip::setChunkSize( 4096 ); or as a method on a zip (though this is a global setting). Returns old chunk size. Archive::Zip::chunkSize() Returns the current chunk size: my $chunkSize = Archive::Zip::chunkSize(); Archive::Zip::setErrorHandler( \&subroutine ) Change the subroutine called with error strings. This defaults to \&Carp::carp, but you may want to change it to get the error strings. This is not exportable, so you must call it like: Archive::Zip::setErrorHandler( \&myErrorHandler ); If myErrorHandler is undef, resets handler to default. Returns old error handler. Note that if you call Carp::carp or a similar routine or if you're chaining to the default error handler from your error handler, you may want to increment the number of caller levels that are skipped (do not just set it to a number): $Carp::CarpLevel++; Archive::Zip::tempFile( [$tmpdir] ) Create a uniquely named temp file. It will be returned open for read/write. If $tmpdir is given, it is used as the name of a directory to create the file in. If not given, creates the file using "File::Spec::tmpdir()". Generally, you can override this choice using the $ENV{TMPDIR} environment variable. But see the File::Spec documentation for your system. Note that on many systems, if you're running in taint mode, then you must make sure that $ENV{TMPDIR} is untainted for it to be used. Will *NOT* create $tmpdir if it doesn't exist (this is a change from prior versions!). Returns file handle and name: my ($fh, $name) = Archive::Zip::tempFile(); my ($fh, $name) = Archive::Zip::tempFile('myTempDir'); my $fh = Archive::Zip::tempFile(); # if you don't need the name Zip Archive Accessors members() Return a copy of the members array my @members = $zip->members(); numberOfMembers() Return the number of members I have memberNames() Return a list of the (internal) file names of the zip members memberNamed( $string ) Return ref to member whose filename equals given filename or undef. $string must be in Zip (Unix) filename format. membersMatching( $regex ) Return array of members whose filenames match given regular expression in list context. Returns number of matching members in scalar context. my @textFileMembers = $zip->membersMatching( '.*\.txt' ); # or my $numberOfTextFiles = $zip->membersMatching( '.*\.txt' ); diskNumber() Return the disk that I start on. Not used for writing zips, but might be interesting if you read a zip in. This should be 0, as Archive::Zip does not handle multi-volume archives. diskNumberWithStartOfCentralDirectory() Return the disk number that holds the beginning of the central directory. Not used for writing zips, but might be interesting if you read a zip in. This should be 0, as Archive::Zip does not handle multi-volume archives. numberOfCentralDirectoriesOnThisDisk() Return the number of CD structures in the zipfile last read in. Not used for writing zips, but might be interesting if you read a zip in. numberOfCentralDirectories() Return the number of CD structures in the zipfile last read in. Not used for writing zips, but might be interesting if you read a zip in. centralDirectorySize() Returns central directory size, as read from an external zip file. Not used for writing zips, but might be interesting if you read a zip in. centralDirectoryOffsetWRTStartingDiskNumber() Returns the offset into the zip file where the CD begins. Not used for writing zips, but might be interesting if you read a zip in. zipfileComment( [$string] ) Get or set the zipfile comment. Returns the old comment. print $zip->zipfileComment(); $zip->zipfileComment( 'New Comment' ); eocdOffset() Returns the (unexpected) number of bytes between where the EOCD was found and where it expected to be. This is normally 0, but would be positive if something (a virus, perhaps) had added bytes somewhere before the EOCD. Not used for writing zips, but might be interesting if you read a zip in. Here is an example of how you can diagnose this: my $zip = Archive::Zip->new('somefile.zip'); if ($zip->eocdOffset()) { warn "A virus has added ", $zip->eocdOffset, " bytes of garbage\n"; } The "eocdOffset()" is used to adjust the starting position of member headers, if necessary. fileName() Returns the name of the file last read from. If nothing has been read yet, returns an empty string; if read from a file handle, returns the handle in string form. Zip Archive Member Operations Various operations on a zip file modify members. When a member is passed as an argument, you can either use a reference to the member itself, or the name of a member. Of course, using the name requires that names be unique within a zip (this is not enforced). removeMember( $memberOrName ) Remove and return the given member, or match its name and remove it. Returns undef if member or name doesn't exist in this Zip. No-op if member does not belong to this zip. replaceMember( $memberOrName, $newMember ) Remove and return the given member, or match its name and remove it. Replace with new member. Returns undef if member or name doesn't exist in this Zip, or if $newMember is undefined. It is an (undiagnosed) error to provide a $newMember that is a member of the zip being modified. my $member1 = $zip->removeMember( 'xyz' ); my $member2 = $zip->replaceMember( 'abc', $member1 ); # now, $member2 (named 'abc') is not in $zip, # and $member1 (named 'xyz') is, having taken $member2's place. extractMember( $memberOrName [, $extractedName ] ) Extract the given member, or match its name and extract it. Returns undef if member doesn't exist in this Zip. If optional second arg is given, use it as the name of the extracted member. Otherwise, the internal filename of the member is used as the name of the extracted file or directory. If you pass $extractedName, it should be in the local file system's format. All necessary directories will be created. Returns "AZ_OK" on success. extractMemberWithoutPaths( $memberOrName [, $extractedName ] ) Extract the given member, or match its name and extract it. Does not use path information (extracts into the current directory). Returns undef if member doesn't exist in this Zip. If optional second arg is given, use it as the name of the extracted member (its paths will be deleted too). Otherwise, the internal filename of the member (minus paths) is used as the name of the extracted file or directory. Returns "AZ_OK" on success. addMember( $member ) Append a member (possibly from another zip file) to the zip file. Returns the new member. Generally, you will use addFile(), addDirectory(), addFileOrDirectory(), addString(), or read() to add members. # Move member named 'abc' to end of zip: my $member = $zip->removeMember( 'abc' ); $zip->addMember( $member ); updateMember( $memberOrName, $fileName ) Update a single member from the file or directory named $fileName. Returns the (possibly added or updated) member, if any; "undef" on errors. The comparison is based on "lastModTime()" and (in the case of a non-directory) the size of the file. addFile( $fileName [, $newName ] ) Append a member whose data comes from an external file, returning the member or undef. The member will have its file name set to the name of the external file, and its desiredCompressionMethod set to COMPRESSION_DEFLATED. The file attributes and last modification time will be set from the file. If the name given does not represent a readable plain file or symbolic link, undef will be returned. $fileName must be in the format required for the local file system. The optional $newName argument sets the internal file name to something different than the given $fileName. $newName, if given, must be in Zip name format (i.e. Unix). The text mode bit will be set if the contents appears to be text (as returned by the "-T" perl operator). *NOTE* that you shouldn't (generally) use absolute path names in zip member names, as this will cause problems with some zip tools as well as introduce a security hole and make the zip harder to use. addDirectory( $directoryName [, $fileName ] ) Append a member created from the given directory name. The directory name does not have to name an existing directory. If the named directory exists, the file modification time and permissions are set from the existing directory, otherwise they are set to now and permissive default permissions. $directoryName must be in local file system format. The optional second argument sets the name of the archive member (which defaults to $directoryName). If given, it must be in Zip (Unix) format. Returns the new member. addFileOrDirectory( $name [, $newName ] ) Append a member from the file or directory named $name. If $newName is given, use it for the name of the new member. Will add or remove trailing slashes from $newName as needed. $name must be in local file system format. The optional second argument sets the name of the archive member (which defaults to $name). If given, it must be in Zip (Unix) format. addString( $stringOrStringRef, $name ) Append a member created from the given string or string reference. The name is given by the second argument. Returns the new member. The last modification time will be set to now, and the file attributes will be set to permissive defaults. my $member = $zip->addString( 'This is a test', 'test.txt' ); contents( $memberOrMemberName [, $newContents ] ) Returns the uncompressed data for a particular member, or undef. print "xyz.txt contains " . $zip->contents( 'xyz.txt' ); Also can change the contents of a member: $zip->contents( 'xyz.txt', 'This is the new contents' ); If called expecting an array as the return value, it will include the status as the second value in the array. ($content, $status) = $zip->contents( 'xyz.txt'); Zip Archive I/O operations A Zip archive can be written to a file or file handle, or read from one. writeToFileNamed( $fileName ) Write a zip archive to named file. Returns "AZ_OK" on success. my $status = $zip->writeToFileNamed( 'xx.zip' ); die "error somewhere" if $status != AZ_OK; Note that if you use the same name as an existing zip file that you read in, you will clobber ZipFileMembers. So instead, write to a different file name, then delete the original. If you use the "overwrite()" or "overwriteAs()" methods, you can re-write the original zip in this way. $fileName should be a valid file name on your system. writeToFileHandle( $fileHandle [, $seekable] ) Write a zip archive to a file handle. Return AZ_OK on success. The optional second arg tells whether or not to try to seek backwards to re-write headers. If not provided, it is set if the Perl "-f" test returns true. This could fail on some operating systems, though. my $fh = IO::File->new( 'someFile.zip', 'w' ); unless ( $zip->writeToFileHandle( $fh ) == AZ_OK ) { # error handling } If you pass a file handle that is not seekable (like if you're writing to a pipe or a socket), pass a false second argument: my $fh = IO::File->new( '| cat > somefile.zip', 'w' ); $zip->writeToFileHandle( $fh, 0 ); # fh is not seekable If this method fails during the write of a member, that member and all following it will return false from "wasWritten()". See writeCentralDirectory() for a way to deal with this. If you want, you can write data to the file handle before passing it to writeToFileHandle(); this could be used (for instance) for making self-extracting archives. However, this only works reliably when writing to a real file (as opposed to STDOUT or some other possible non-file). See examples/selfex.pl for how to write a self-extracting archive. writeCentralDirectory( $fileHandle [, $offset ] ) Writes the central directory structure to the given file handle. Returns AZ_OK on success. If given an $offset, will seek to that point before writing. This can be used for recovery in cases where writeToFileHandle or writeToFileNamed returns an IO error because of running out of space on the destination file. You can truncate the zip by seeking backwards and then writing the directory: my $fh = IO::File->new( 'someFile.zip', 'w' ); my $retval = $zip->writeToFileHandle( $fh ); if ( $retval == AZ_IO_ERROR ) { my @unwritten = grep { not $_->wasWritten() } $zip->members(); if (@unwritten) { $zip->removeMember( $member ) foreach my $member ( @unwritten ); $zip->writeCentralDirectory( $fh, $unwritten[0]->writeLocalHeaderRelativeOffset()); } } overwriteAs( $newName ) Write the zip to the specified file, as safely as possible. This is done by first writing to a temp file, then renaming the original if it exists, then renaming the temp file, then deleting the renamed original if it exists. Returns AZ_OK if successful. overwrite() Write back to the original zip file. See overwriteAs() above. If the zip was not ever read from a file, this generates an error. read( $fileName ) Read zipfile headers from a zip file, appending new members. Returns "AZ_OK" or error code. my $zipFile = Archive::Zip->new(); my $status = $zipFile->read( '/some/FileName.zip' ); readFromFileHandle( $fileHandle, $filename ) Read zipfile headers from an already-opened file handle, appending new members. Does not close the file handle. Returns "AZ_OK" or error code. Note that this requires a seekable file handle; reading from a stream is not yet supported. my $fh = IO::File->new( '/some/FileName.zip', 'r' ); my $zip1 = Archive::Zip->new(); my $status = $zip1->readFromFileHandle( $fh ); my $zip2 = Archive::Zip->new(); $status = $zip2->readFromFileHandle( $fh ); Zip Archive Tree operations These used to be in Archive::Zip::Tree but got moved into Archive::Zip. They enable operation on an entire tree of members or files. A usage example: use Archive::Zip; my $zip = Archive::Zip->new(); # add all readable files and directories below . as xyz/* $zip->addTree( '.', 'xyz' ); # add all readable plain files below /abc as def/* $zip->addTree( '/abc', 'def', sub { -f && -r } ); # add all .c files below /tmp as stuff/* $zip->addTreeMatching( '/tmp', 'stuff', '\.c$' ); # add all .o files below /tmp as stuff/* if they aren't writable $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { ! -w } ); # add all .so files below /tmp that are smaller than 200 bytes as stuff/* $zip->addTreeMatching( '/tmp', 'stuff', '\.o$', sub { -s < 200 } ); # and write them into a file $zip->writeToFileNamed('xxx.zip'); # now extract the same files into /tmpx $zip->extractTree( 'stuff', '/tmpx' ); $zip->addTree( $root, $dest [,$pred] ) -- Add tree of files to a zip $root is the root of the tree of files and directories to be added. It is a valid directory name on your system. $dest is the name for the root in the zip file (undef or blank means to use relative pathnames). It is a valid ZIP directory name (that is, it uses forward slashes (/) for separating directory components). $pred is an optional subroutine reference to select files: it is passed the name of the prospective file or directory using $_, and if it returns true, the file or directory will be included. The default is to add all readable files and directories. For instance, using my $pred = sub { /\.txt/ }; $zip->addTree( '.', '', $pred ); will add all the .txt files in and below the current directory, using relative names, and making the names identical in the zipfile: original name zip member name ./xyz xyz ./a/ a/ ./a/b a/b To translate absolute to relative pathnames, just pass them in: $zip->addTree( '/c/d', 'a' ); original name zip member name /c/d/xyz a/xyz /c/d/a/ a/a/ /c/d/a/b a/a/b Returns AZ_OK on success. Note that this will not follow symbolic links to directories. Note also that this does not check for the validity of filenames. Note that you generally *don't* want to make zip archive member names absolute. $zip->addTreeMatching( $root, $dest, $pattern [,$pred] ) $root is the root of the tree of files and directories to be added $dest is the name for the root in the zip file (undef means to use relative pathnames) $pattern is a (non-anchored) regular expression for filenames to match $pred is an optional subroutine reference to select files: it is passed the name of the prospective file or directory in $_, and if it returns true, the file or directory will be included. The default is to add all readable files and directories. To add all files in and below the current dirctory whose names end in ".pl", and make them extract into a subdirectory named "xyz", do this: $zip->addTreeMatching( '.', 'xyz', '\.pl$' ) To add all *writable* files in and below the dirctory named "/abc" whose names end in ".pl", and make them extract into a subdirectory named "xyz", do this: $zip->addTreeMatching( '/abc', 'xyz', '\.pl$', sub { -w } ) Returns AZ_OK on success. Note that this will not follow symbolic links to directories. $zip->updateTree( $root, [ $dest, [ $pred [, $mirror]]] ); Update a zip file from a directory tree. "updateTree()" takes the same arguments as "addTree()", but first checks to see whether the file or directory already exists in the zip file, and whether it has been changed. If the fourth argument $mirror is true, then delete all my members if corresponding files weren't found. Returns an error code or AZ_OK if all is well. $zip->extractTree() $zip->extractTree( $root ) $zip->extractTree( $root, $dest ) $zip->extractTree( $root, $dest, $volume ) If you don't give any arguments at all, will extract all the files in the zip with their original names. If you supply one argument for $root, "extractTree" will extract all the members whose names start with $root into the current directory, stripping off $root first. $root is in Zip (Unix) format. For instance, $zip->extractTree( 'a' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x as ./x a/b/c as ./b/c If you give two arguments, "extractTree" extracts all the members whose names start with $root. It will translate $root into $dest to construct the destination file name. $root and $dest are in Zip (Unix) format. For instance, $zip->extractTree( 'a', 'd/e' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x to d/e/x a/b/c to d/e/b/c and ignore ax/d/e and d/e If you give three arguments, "extractTree" extracts all the members whose names start with $root. It will translate $root into $dest to construct the destination file name, and then it will convert to local file system format, using $volume as the name of the destination volume. $root and $dest are in Zip (Unix) format. $volume is in local file system format. For instance, under Windows, $zip->extractTree( 'a', 'd/e', 'f:' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x to f:d/e/x a/b/c to f:d/e/b/c and ignore ax/d/e and d/e If you want absolute paths (the prior example used paths relative to the current directory on the destination volume, you can specify these in $dest: $zip->extractTree( 'a', '/d/e', 'f:' ); when applied to a zip containing the files: a/x a/b/c ax/d/e d/e will extract: a/x to f:\d\e\x a/b/c to f:\d\e\b\c and ignore ax/d/e and d/e Returns an error code or AZ_OK if everything worked OK. MEMBER OPERATIONS Member Class Methods Several constructors allow you to construct members without adding them to a zip archive. These work the same as the addFile(), addDirectory(), and addString() zip instance methods described above, but they don't add the new members to a zip. Archive::Zip::Member->newFromString( $stringOrStringRef [, $fileName] ) Construct a new member from the given string. Returns undef on error. my $member = Archive::Zip::Member->newFromString( 'This is a test', 'xyz.txt' ); newFromFile( $fileName ) Construct a new member from the given file. Returns undef on error. my $member = Archive::Zip::Member->newFromFile( 'xyz.txt' ); newDirectoryNamed( $directoryName [, $zipname ] ) Construct a new member from the given directory. $directoryName must be a valid name on your file system; it doesn't have to exist. If given, $zipname will be the name of the zip member; it must be a valid Zip (Unix) name. If not given, it will be converted from $directoryName. Returns undef on error. my $member = Archive::Zip::Member->newDirectoryNamed( 'CVS/' ); Member Simple accessors These methods get (and/or set) member attribute values. versionMadeBy() Gets the field from the member header. fileAttributeFormat( [$format] ) Gets or sets the field from the member header. These are "FA_*" values. versionNeededToExtract() Gets the field from the member header. bitFlag() Gets the general purpose bit field from the member header. This is where the "GPBF_*" bits live. compressionMethod() Returns the member compression method. This is the method that is currently being used to compress the member data. This will be COMPRESSION_STORED for added string or file members, or any of the "COMPRESSION_*" values for members from a zip file. However, this module can only handle members whose data is in COMPRESSION_STORED or COMPRESSION_DEFLATED format. desiredCompressionMethod( [$method] ) Get or set the member's "desiredCompressionMethod". This is the compression method that will be used when the member is written. Returns prior desiredCompressionMethod. Only COMPRESSION_DEFLATED or COMPRESSION_STORED are valid arguments. Changing to COMPRESSION_STORED will change the member desiredCompressionLevel to 0; changing to COMPRESSION_DEFLATED will change the member desiredCompressionLevel to COMPRESSION_LEVEL_DEFAULT. desiredCompressionLevel( [$method] ) Get or set the member's desiredCompressionLevel This is the method that will be used to write. Returns prior desiredCompressionLevel. Valid arguments are 0 through 9, COMPRESSION_LEVEL_NONE, COMPRESSION_LEVEL_DEFAULT, COMPRESSION_LEVEL_BEST_COMPRESSION, and COMPRESSION_LEVEL_FASTEST. 0 or COMPRESSION_LEVEL_NONE will change the desiredCompressionMethod to COMPRESSION_STORED. All other arguments will change the desiredCompressionMethod to COMPRESSION_DEFLATED. externalFileName() Return the member's external file name, if any, or undef. fileName() Get or set the member's internal filename. Returns the (possibly new) filename. Names will have backslashes converted to forward slashes, and will have multiple consecutive slashes converted to single ones. lastModFileDateTime() Return the member's last modification date/time stamp in MS-DOS format. lastModTime() Return the member's last modification date/time stamp, converted to unix localtime format. print "Mod Time: " . scalar( localtime( $member->lastModTime() ) ); setLastModFileDateTimeFromUnix() Set the member's lastModFileDateTime from the given unix time. $member->setLastModFileDateTimeFromUnix( time() ); internalFileAttributes() Return the internal file attributes field from the zip header. This is only set for members read from a zip file. externalFileAttributes() Return member attributes as read from the ZIP file. Note that these are NOT UNIX! unixFileAttributes( [$newAttributes] ) Get or set the member's file attributes using UNIX file attributes. Returns old attributes. my $oldAttribs = $member->unixFileAttributes( 0666 ); Note that the return value has more than just the file permissions, so you will have to mask off the lowest bits for comparisions. localExtraField( [$newField] ) Gets or sets the extra field that was read from the local header. This is not set for a member from a zip file until after the member has been written out. The extra field must be in the proper format. cdExtraField( [$newField] ) Gets or sets the extra field that was read from the central directory header. The extra field must be in the proper format. extraFields() Return both local and CD extra fields, concatenated. fileComment( [$newComment] ) Get or set the member's file comment. hasDataDescriptor() Get or set the data descriptor flag. If this is set, the local header will not necessarily have the correct data sizes. Instead, a small structure will be stored at the end of the member data with these values. This should be transparent in normal operation. crc32() Return the CRC-32 value for this member. This will not be set for members that were constructed from strings or external files until after the member has been written. crc32String() Return the CRC-32 value for this member as an 8 character printable hex string. This will not be set for members that were constructed from strings or external files until after the member has been written. compressedSize() Return the compressed size for this member. This will not be set for members that were constructed from strings or external files until after the member has been written. uncompressedSize() Return the uncompressed size for this member. isEncrypted() Return true if this member is encrypted. The Archive::Zip module does not currently create or extract encrypted members. isTextFile( [$flag] ) Returns true if I am a text file. Also can set the status if given an argument (then returns old state). Note that this module does not currently do anything with this flag upon extraction or storage. That is, bytes are stored in native format whether or not they came from a text file. isBinaryFile() Returns true if I am a binary file. Also can set the status if given an argument (then returns old state). Note that this module does not currently do anything with this flag upon extraction or storage. That is, bytes are stored in native format whether or not they came from a text file. extractToFileNamed( $fileName ) Extract me to a file with the given name. The file will be created with default modes. Directories will be created as needed. The $fileName argument should be a valid file name on your file system. Returns AZ_OK on success. isDirectory() Returns true if I am a directory. writeLocalHeaderRelativeOffset() Returns the file offset in bytes the last time I was written. wasWritten() Returns true if I was successfully written. Reset at the beginning of a write attempt. Low-level member data reading It is possible to use lower-level routines to access member data streams, rather than the extract* methods and contents(). For instance, here is how to print the uncompressed contents of a member in chunks using these methods: my ( $member, $status, $bufferRef ); $member = $zip->memberNamed( 'xyz.txt' ); $member->desiredCompressionMethod( COMPRESSION_STORED ); $status = $member->rewindData(); die "error $status" unless $status == AZ_OK; while ( ! $member->readIsDone() ) { ( $bufferRef, $status ) = $member->readChunk(); die "error $status" if $status != AZ_OK && $status != AZ_STREAM_END; # do something with $bufferRef: print $$bufferRef; } $member->endRead(); readChunk( [$chunkSize] ) This reads the next chunk of given size from the member's data stream and compresses or uncompresses it as necessary, returning a reference to the bytes read and a status. If size argument is not given, defaults to global set by Archive::Zip::setChunkSize. Status is AZ_OK on success until the last chunk, where it returns AZ_STREAM_END. Returns "( \$bytes, $status)". my ( $outRef, $status ) = $self->readChunk(); print $$outRef if $status != AZ_OK && $status != AZ_STREAM_END; rewindData() Rewind data and set up for reading data streams or writing zip files. Can take options for "inflateInit()" or "deflateInit()", but this isn't likely to be necessary. Subclass overrides should call this method. Returns "AZ_OK" on success. endRead() Reset the read variables and free the inflater or deflater. Must be called to close files, etc. Returns AZ_OK on success. readIsDone() Return true if the read has run out of data or errored out. contents() Return the entire uncompressed member data or undef in scalar context. When called in array context, returns "( $string, $status )"; status will be AZ_OK on success: my $string = $member->contents(); # or my ( $string, $status ) = $member->contents(); die "error $status" unless $status == AZ_OK; Can also be used to set the contents of a member (this may change the class of the member): $member->contents( "this is my new contents" ); extractToFileHandle( $fh ) Extract (and uncompress, if necessary) the member's contents to the given file handle. Return AZ_OK on success. Archive::Zip::FileMember methods The Archive::Zip::FileMember class extends Archive::Zip::Member. It is the base class for both ZipFileMember and NewFileMember classes. This class adds an "externalFileName" and an "fh" member to keep track of the external file. externalFileName() Return the member's external filename. fh() Return the member's read file handle. Automatically opens file if necessary. Archive::Zip::ZipFileMember methods The Archive::Zip::ZipFileMember class represents members that have been read from external zip files. diskNumberStart() Returns the disk number that the member's local header resides in. Should be 0. localHeaderRelativeOffset() Returns the offset into the zip file where the member's local header is. dataOffset() Returns the offset from the beginning of the zip file to the member's data. REQUIRED MODULES Archive::Zip requires several other modules: Carp Compress::Raw::Zlib Cwd File::Basename File::Copy File::Find File::Path File::Spec IO::File IO::Seekable Time::Local BUGS AND CAVEATS When not to use Archive::Zip If you are just going to be extracting zips (and/or other archives) you are recommended to look at using Archive::Extract instead, as it is much easier to use and factors out archive-specific functionality. Try to avoid IO::Scalar One of the most common ways to use Archive::Zip is to generate Zip files in-memory. Most people have use IO::Scalar for this purpose. Unfortunately, as of 1.11 this module no longer works with IO::Scalar as it incorrectly implements seeking. Anybody using IO::Scalar should consider porting to IO::String, which is smaller, lighter, and is implemented to be perfectly compatible with regular seekable filehandles. Support for IO::Scalar most likely will not be restored in the future, as IO::Scalar itself cannot change the way it is implemented due to back-compatibility issues. TO DO * auto-choosing storing vs compression * extra field hooks (see notes.txt) * check for dups on addition/renaming? * Text file extraction (line end translation) * Reading zip files from non-seekable inputs (Perhaps by proxying through IO::String?) * separate unused constants into separate module * cookbook style docs * Handle tainted paths correctly * Work on better compatability with other IO:: modules SUPPORT Bugs should be reported via the CPAN bug tracker For other issues contact the maintainer AUTHOR Adam Kennedy Previously maintained by Steve Peters . File attributes code by Maurice Aubrey . Originally by Ned Konz . COPYRIGHT Some parts copyright 2006 - 2009 Adam Kennedy. Some parts copyright 2005 Steve Peters. Original work copyright 2000 - 2004 Ned Konz. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. SEE ALSO Look at Archive::Zip::MemberRead which is a wrapper that allows one to read Zip archive members as if they were files. Compress::Raw::Zlib, Archive::Tar, Archive::Extract There is a Japanese translation of this document at that was done by DEQ . Thanks! gdata/inst/doc/0000755000176000001440000000000012164370064013107 5ustar ripleyusersgdata/inst/doc/unknown.pdf0000644000176000001440000032232512024144455015306 0ustar ripleyusers%PDF-1.5 %ÐÔÅØ 28 0 obj << /Length 4211 /Filter /FlateDecode >> stream xÚÍ;ïsã¶±ßï¯Ðd¦3º !@ :Mg.Í]rmÆéó9½Î$ù@I´Í%ª¢dŸÿû·‹]’ Ù²sïµ8— °ö÷.“Éõ$™|ÿêÛËW_¿Ónâ„3ÊL.¯&©Î„4ùÄæNäÐ^.'¿L?þtñ·÷çß¿ž)L?¾¿üz?Ÿÿíü§çtó×RÊé›~ûáõo—}õöòÕ¿_IX%™È L꜂IHr5Y¬^ýò[2Y³¿N‘º|rçG®&Y.Eî [O>¼úŸWIˆ¨I&*6·1íæÌR‘Ⱦ¶Ù´Ù~ªÖׄÕ]µ»adןÖÍÝ:D¶¨÷e‹Èú©‡=H&3• 'iÎË›’^º^»‚º›bñ©¸.ù]5z7‰µôòüž^ø~ûZæÓòºÙò}³ýW±^ðidÓ­^µôÊmu½.w;Fæ¦`ð¼,ù£6ûy]µ7å’n»ÝRþæ×D'*I,´RôŸ.3‘fð´|ª…J-ÿ~½Û6ËýbW5ë#Ȧ"Q)î÷8Kð°M§«ªmýy ð–öÜ÷œ—4’öhCM[®wø)8 òkãjR §ykn‹mÕìa²4•ӻ⾯gZgÓw¸2ÂÊÏÅjS—x£¦Þ| è¾í]Ÿ"-bŽë'‘¯Í…VýÜÉe³Ã<ƒ‰µšÞÝTµ' @ÓæÂ%ŠñÕôÆ §²cë§F¤*ëf? ¼AA&"ËzÎhFXxqÃÝ’Z¿·ZiÞÓbI`¤ lÏ›uÞ¼v 6²ª‹y] B>3Âj¸¼A*ËRçWÀ¶ZmšíŽúÄYšÃIí‚]œQÛ÷Ô¹­Šè¶çÂÚ¼û"@wZÂUÀµ„KÀµãû9\µþp_fÝ<X{L“iµC’S€h¹­n‹]u[¶ˆžÕÓE³¾-·-’·Ñ\Ñ+óºX¢î¯I¢ÊzÉSÀ÷=ü ¥¡‡s9vz³nÜ–HIÅbÑø£Z’èÊÓøB&èïÜ-­g»InÊzƒTŒ«ª©—6°ú²Y—Ô»Ä"bµp™íæÀ…¸®áªàZ0udq t¥ ?œ¶)™±λæ,y-l·/Zà ¥{nÃi÷p­ú)»Ïx8u–ˆ\÷']¬—1rB‚ç1 Þœ}ÓŸŠœ~~röE]´ -@®åÚNß,—ÊáËàScõ¡L,êúÞë6”IY>ÝÝ”1Y“ edøõSOËÜíÀš7ºSQ6|eáÉ÷z¿¹ k«œdP ,ƒò ù–A!vS.øs\*ljGG~…²CªAm@wS Ø‘é´½iöõ’ EÝ6ÔóÚZâlÒ!øZ”o ß Ÿ'uMø¾;…(˵¢P)‡³P6Á³ i ·Æ§A‹»äÛp#‚R9¡;<´ª Ž]ÏÛÕ:6“mßOtœvÇZ§ÊFI@Ä ¸!`CJ3:K/ƒSëe0ÌÇb˜`¤4 nŽ4¤ UÔ°Âs>P[‘)ø…ð=û…Y–²¯eÞÚ'…F°d¾#=#sßwö}ÃsPFçç\ˆ}ÏKØÜ*~2/wwž¿ñ¦ã‚à –ž9²yʼÄd3Ó7ÞtjÛÝC—¸ŸöÜŽÏ®Ë5, ºAþzqï·ÆÀ1ŽÝ|ÚgÀSîç;Üä’ŸxoÇð?pªV<Ôû 8Á¶Âs!íâÇ6ü Ù~ŠmiŒÀʇÈÅ—u¤ŒÈ3÷Gê™S£uÃ6é–ÛEðÛclŸ¼ÄÕhÚæØ¦€­NÇü;žvwÄŠ4|úÓâ¿Ã|?Áõ®÷pý³Gý%›ƒ˜îI$6uýe¦®™$Ú#ÓùÝ'O· 6·sb¯Y ØÐ›:âÆ«ÐM^+utý9ŠÛŒd{ïÉ?re­ÿ×ðqŰ9 Ù>‰Í µÞÔusוúü8ÐwØË¦mE‘R„î[4|%‘E%µ!É©Á§ibþ¦IÅ C-Ê+ɧÎ(ËžÍÀÀŸÎŒ¢,gèÙ…6&EY ¥*©2FXÙÅ’ÈÊVFÁ«–ÑM&’Ä=OËq´|ÁþÜ[Ëp† öZø¶kjC­<³ 2¤|v§_òñ)¡sNücËiÏéó€±½‡ ¿š¯XýŒ¹ø+"c>Ïþ™m0"&útgÔ] kàuFP3t¨ºùÐuC·3Ì`¤0zÚ0íqBä¿áö<àˆn…1Ðþfý Œ”pýFë¾cô~dýö?–If½ézÁ[ð6F¯ìd„ÔâE†+–åU±¯}Ô# |Z“ö>¨ID´2)¬‘¿ÇCЉ0ÉàcD3D‰°ƒ¢;5CC“˜þfó{×UN Ëh=ÎëÊ>«›LŒA?0¦uDsSÇ^TÇðuY´ž*¯`Œm׬Ð(Gà%7©G†rë3V~\ÁQ½ Œ'GÈ„)ÅfhE>í,F*ëšóʆ1&eUGø p@¿éП³rÊ3°3GBúPÌy`æ¨còˆ;I¿´?Ë U%ÕkR…@4!XpýùÜÀxN¤)³+õмz,6ðßÀ³A¤ö´3~AX"Â.ïl"fþeàì˲ãmwAùYûÄ P—‚IÈãÀøâûº*0ùÛq§€rvÅ,îõf^ÐTãÒ÷QÎ-û".0§a¹7Pòª¹–Äg0vˆÉ>ÇG‡7Ýsr'Ût`KÃâÏ&f0¨±J -ðŒkƒt†uí]AçC4].œr_BݦêP[¼\2ÕŽ° 2ðˆuø€ˆ© j½„|’®j8¨ ŽɹƒÉðU`„~ ‘ç&–ÏL’N»PéÝF“(ð‚°°¤—ŽúañàõžÿX1¹:8œ±á•0˜ž]ô³b57ÃËsP}&öPÒâ#ª…«ûˆ•ËsE+Ôvrá ¬(äê];f ¥H¸)ð›ó> stream xÚåÙ’ÛÆñ}¿‚Qå[G˜ƒqŽ*É‘lÙÊÊ‘Öqªl?€$¸DLk\JŸîéÁÉáòص¥TPsbŽîž¾ýÑÍÈ}uñâúâÙ+©GšéHD£ëùH†Lk1R±fq®g£½¿¿|ÿå»×ß]¿~{u9Ò÷~x}ý5Õ^þûù?¾{óòý嘇‘#oß}ûúê«á´ï¯¾½zûƒýû_—œsïù›ïá·Ÿ¯¿¹xy}ñë‡óø#Þî1?£éêâÇŸýÑ Æ¾ù,Ðñhkf®FaÌY¬¡º½¿øç…ß½œ|÷J’³ ºÒß.ÇR^vɽ¾ïáËáûÅ–|[[ÿÉ—>àû«-_Á—À7¥aŽ×€MegS4œù*¢ý~„™¾Ÿi_\à9|oà{ßËGêæ~¨¼k¨¿³—Ú;•N;N,BOi¥Í=+àoþ9À<þ¿e÷çÌi»’ßþueOnÀü9Aû1è6ú¬@ýª5¸Ÿ rùÉ Ü±ßÿ*ÈÏ"zùi‰þà©ù TLJ!{mÛ€=&[?ôõáëÙ›¾0Í1—ŠàT×»ýŽß¨ û㎜3--')|w¶\ZBþ¢·]»„©¾«W;Šó…œú¼5"~G™{¦ã[Š}1„ËpõÄ]È£pà‹Š svŠ_öñq½HËôr*éUÛ‚*é‡du»LKl…Þ6«Ô?]&e Ý»PÝ3†K˜Eœê•=ü¾Ì`b÷P!gB…õŸI>s,'çQŸLçüV™kÇAÈÂ@7;Àab8Õ8à7O²õò#ÕËlu‹€¶CxSÙÚŽi±YÚ®›´ÂŠðª…,“UjÐ8¶»õI[–›e0¡´0aäyJ]ÅšJƒYfyj§s*ßÑÈ´˜¥ öõcDõÑÉ’&NÒ|좪ô'ßxö€›E±¤;@¥L{#Âx“O«¬ÈKê¹µ7Ió*ÑäEÚZYiËÜFÁ}Æ}^cbi©¢4øÛÅÛ¸žß»‚›B8T"šY¨lÉà›[2L²ÜÝPJ EU¯²J«E1+sð¦¶Í=w7W!“@”¾;¡p,|É|Ù‡ŒŒÇ†œ±±²gD’ÆövÜÞ¦k;u^¬] ¸8)"` 0btPH&‡øúáR <×¾—§H5XKf³ é Û@—Aú!›dˬúH]{ްãèèãú,Ž›Ë=s,vu Š»1û< uŸAµ$4÷fÄRz>ð8ðn‹²Ì&WÐZ$wY~CõpŠìv™Rk“ÿ’ÛÜõžï’åÆ0‰@Á;N*¬ÅÞ4É©k’RÇ,›#]Ì-yä '«vtqó€Å~|Iˆ°á´XÝS˫҅ú’CòuS"âƒ_ȸö(ËÍ*/‘U*á½2VùÈðPä ЊˆÙ*¿‹*–hEL«ÿ10¼Ù¬Œ»—#‡ yî×7‚Ðg¡n˜£Áa #ƒC,S€?¨â\Lˆ³¨AY­5Èsš=ÝX/Äyïí©e`"†«‰>'©ºóÂxHÒ LëØ{;§>½ë2E¨öÆŠº ¡ÿ·¼Ã)ó CA@qf$`n^öµ/ [õKƒFм-¸5‡Š¡î±KiF’FgTGÃré%Beb9t2]dérAßI À~ä#Å‚ˆŸúfvÍ’®È[*; Û€†XÂ9rZš”.}´¹Ø˜øý7ù‰0ð–ÉÔÜOšôH(ð·X3¿%ÄSø[3-Â.Ãí,S#"@I9À>N0†«îX'alÂŒFÌáCÝ Xwéûä¬8Á<‰î×g8‹eð(¯;<æ-¼žØ–i~S-JRÈWÕ5ÏÆÓý°EœBs2>F%Å#hë²ÕYf– Í}«ÚøLÂsïÁÔPÒSÒœˆÂ¦§K2Ÿ «˜NA_$¤Ô>¯.—5N“@ĵ£ Xî²ØR¶\nÊj *fIä#I`O/³i‚¦+&aýî>ö˜Ö³¢¼YZN×Ù„\&‘7ï:U”y X&T,³²¢yÛE6]PgfçéˆÀ¡è·MÈk'Í]VlJãÜ …gõ^s˜BÎ-¨¬ŠY†#4 ¼¸È:›Ò ñ©:Ü8~Ô•·¬g™~‡8píVÅ×¢@øË]ï\lÕdZ¡¨ÃúžsàlÕã¾Ç÷¨c˜Å­S$ƒT¡÷ Ÿè'èõq]cÊù`ÁÖës8ØãôLë³P¡44°ûD¹Þ[oï;–‡á¨™ØUY k¶¦tu!)直Rê%‡‚9@mƒ)?ÄúB]Rš²Á;°åPãoÅúçí¾™sµÏÍ †tØìLÈÄ”Ü[$¶c’¢„5óL±bÔ3+Õj«i¤¬gln>Ðà CaçÄAÞô˜ò0ÒgÙM¼#éÄ;®:^wï˜Ü—¤ÑÆ8šd‘^ê‰Ð’iPTB¸ȺAê oOü‘„Š;3Oºø |X±ŸxòGs*7FëˆI4h+[ƶÔ‚[¸áäÀ†Ÿg(gHMÀþbõç7Úzœ<^|"’ +ÿÎ9ŽsCDŸMrˆ3(à ò¾‡>àÜzè±f´(“™KŸTÁQœ8`²õù„+æT¶"µ uà}]lǵs`;ô¤w`]‚¬¶ àÖºÖŒö¥q¿`ÅDé°B\\"㹪½omT®ž–ÙHÉ6ùø‡½®Û'ytMdú•¿2ÜƒÞæ5Ѥ^]R *Æ‚†ÒCHIÆü6Z e¿sûÓÂþ}Àià´gN²Iu7ªhÔz!Ãntȴ͹¤Û¯§Á8ÔüË3ÔsÙöÂqô +úʅɳB‡èìYxœ5ƒì÷‘Sïvå§CÙÿÆ^¤’ÅêójrNNëS—“è VÅ6L5;(µÕñR»cDÔ6Ó°ë·2›/=±ßuº]õâ„„¸ŽÄýr‘ä7™3/"„×$Žs?t¼&O¬ ²,V)Õ ͇ª‘Ó¤#9e¤ Ë÷8…Ÿk‡ƒöãûfÄhd$)š$#Ê!ÀŽdŠ“7<Žà³Ç‘yáž(¿8Z~`Âæ.ÏØÿ˜¢˜ó‡¾ê'ß: ÒÉIÉ '*Ô‹?êµ1º{€šKWs¿…aog.Uá½õW;âé=§œÆZpBõ>MJ+ækÝj"ÜD!RyH¬3l¹G ‡!‹ƒF2×9ì—¸C'T„#B'º‹ØpdøLù[–Â`â`ŽBPRçÆ†ÚPy?q?,ÏÆŒ©o•&”ƒ#õĬ¢ö6[.éZ²@IG@&úFûÁb7Œ½6áÅ×u¶'=Éþj¬Sùè pÏJX#_õØtæj¼ÔןL"Yä=/i¯rcî¬,°´#wéú#ÕÀd¨]ójÄ …y³´ñ9E#šQ¾YMŒ€€:å㪎ñdZÒOUJ²‰0À™ìäqèw|.¡ï“àAžX’ÌÀ x,—–"Ñ'£"á}Yäe63)W>¦+™I[èq³ÅîîHˆ ÛÌpâ »›¼*Ù DÎÆÐl ¥wê­sAÁóù ؃-_¡,>S”›†`^d);@_–¥jj5HÆÕê„^RÚÑ%fž1æœi|Ñsì#ý±P"ÃvV ,1tþÿ»nÇÆ endstream endobj 53 0 obj << /Length 1872 /Filter /FlateDecode >> stream xÚÕXYsãD~ϯPí“\¬&sé˜- Øp„PËŽŠZ¶(Y–m%:ŒŽ„ü{zfZ¶d+a— ¦æjõL__÷ˆ:‡:—g‹³ó¯|å(¢8‹µãK¢wÂH‘(ˆœÅÊyë^¿ùöÛ—ó™ÝŸgïß8’„q8˜í‹«‹WWß]Î_~ÿµÙ?ûrqöÛƒmê°ÀЈ;IqööuV°÷C‰P‘so( GFŒD †¹s}öÃÞ®rzGŸɸ½Ä§3ÏçÂmgÌ- íìôczv˜Ã0ƒÖ@ÓT¿PŸBG ­ ¥ÐÖÐbh´É>¦éžÉ©ã1F”ïÛC?šyAĘ›A…1üH Úøãàñ9~ü oQB»Å^ÓÜãø™€M] 5ò­P.~¢§ø/pþÚ˃²~ÇëõLS c”>}À'¨^k+æ ÜœQ"%s<_ úÆ:75y²$N—¤ÀëùÅžœ*ŒoûÄòÃ^%Ãñ„8~Ô3YÍ' 'Æ'Â{¾ï'>”¢Þƽá>Å-1ü´+†Ú…p’Òñ%¡ÄpºZÏ<én»Më‹ <Ì4ktjeèi™¦+¤«l_Õ·vT•ùƒ%®J»ÒT²IªÂCÍãÙCqvU™–msžTyW”p"©ûPuvÄ¥Tk\¨ººIíøÎEs›í —ý®e2€÷Y»"æ»M—«ØºÒ+;·Ešlã2kŠæ9,€n3’3äîòÁ’6ݲIµ/·Y¹™p^ÞÅ(ëÑrŒC§Öðzú‘Nªz*,/ƒ= ¯½Zì ió Ü逦Ús©–7iÒ6/p»^ÐÝÈOlG»ó8L £±9ù:9`†¼cœ}f0ÈPoó÷CÉÎõþ¿õí3÷íA%cÕ2÷Ý?‘ž<ïñÌÇd²ÏÿlúÍéÿ/mì+²Q}Ç•O”FDEÑqÇöåuDĉˆ‚ÉúŽê4$dÀµÁž¦¾æº+Џ~˜À/ŠsF(ÕW]™´Ye!ÿȤOx z¨ë£ûÍ£^xz˜ @HÙsx>uñ©è Þ?À&pYÁž$¨)ÏŽHô$½ñzÆ"—ÇBI"!Ž2±I‰Õ]¶Òù5ŠŒC×5éºËí8+Û´^lj¡M! —m!`F6ÍÂè.®³ªkìÄ–;oÊ3í^U@lMéq¥lÂWpzy[V÷åy‘5N¹fó.λ´!º¾ðÝÅ6Íj»W:A2\JHðqÙê¡Âfàa™®Zôκªí ÙÆ;{ A=dWWqÛ¥x °‹Y±«êÖ›Â<ÃA a+%è5{Ý/S}–X0O×<œ»kk‚ÂnΉí¯lwŸæ‰-ª`—S’A¡Ë)¸¡OÍ©ºoºÍ&mŒr ºÃ(‰O ŸxÙ2ϪMï¶#(èû§còR_;âîeUßÄeBÌ Aº?͇ÝZaaߺŠ¡íÄÚöÅÌ Ck-¦9l,êÆEòÀÝÅÉm¼I{Ùøàna`^4sKÿ:½o&ÂBâGüîž„’2Ô©é|ô‚K¨4w8¥!§MßÌ_MÄ«–›øáQÁ»ÅT×bª{íÛçÐæد±ª›Û .•¡®1´oð› '‚ëzƒÜV¸–à|ŽÐ"44O¬ÿ:å֟Ǻ…ûk1<~·/&à üã”dÒ« ää$ B"T…“Q÷‹ô.Í«vnX`ÊýüG°½ÐΕÆÅ” 0‰ G> ­÷§+Çç_šPœ¸»„ÓqÐu;”\etJðAЦ]"’$Tû×ÁS® Šù5\ÿEW07Æ£G.t8î :Íf;(Ëò ÕhƒIÿ`VOÔ½º¾xmqGxŠRˆ¨™<ú˜ÑCàAC4zt€E¹A@E…ÅŽ¸.ÓfÊÀ* ‘Ü'zƒ ,€'ݳPº}"2m‡¹0®›FÀœd¬ƒUÒ8^år›*ôšÅ=*àÕ¸ër“¾&ŸÜ0fþX" ……aø(~à‡ï§ÓX/¨øÑÃ%~Sã£i¹w²£lôÒ ®–áµ[÷ {0Ú Š?nÿÌ™öŸpàŠLçè¹®vÃ>AèIàÞ¥uƒ†‚ëÚÏÆaLaÚ™uî-“¼[¥žïÑ‹MÕÿÑež'Õ*µP¸kÿЫ«*é4^Å“%‚ñO ¾.Û:[v­ù½ ú_ƒî/R¤¸¨ò[¨:À•ÍãKº—û6¦¬LµS6Ð¥¤ ÆÅ¶*b, ^uEž>ÌcîT@y˜n¡( ²Ïêƒ#5‹'Ž|SfFÇí–!k<õ¦[æðQüÜίóê.-³xÂõ8nÐyRtÞSÉÑüfàûÚá>Cï\<Ÿ žà™‰ ‹y7¸×˜õ!VTÏœH_ÿBóáŠþavôhú}ƒue endstream endobj 66 0 obj << /Length1 2196 /Length2 13065 /Length3 0 /Length 14376 /Filter /FlateDecode >> stream xÚ¶eT›Û.ŒC±â.ÁŠCp+îw×â´¸w‡RÜ¡Škqw·¢Å¹éÞçìîs¿ïÇ#É3ý™kÎõ¾4*êÌ¢æ¦`){Wf6 ?@\Q]ACƒ 9X€@vd kW[ð 2ØÙÅÚÁžÿ_6âÎ`+D&r…˜*:ØäÜll6n~6~ Àòý×ÐÁ™ r·6(²äìÁ.È4âŽ^ÎÖ–V®Lÿý  3£°ñññ0ýåµ;[›ìŠ W+°$£È î`f võúŸto­\]ùYY=<2„làïÏ?ÿ !sfî`oëõÇü¯ƒfÕ“—SÐcü‡ô?j11O€3;ÀÌÎÁàfãpóqüþ7Ð?-ø/ý¿¤* ëÿ”÷¯€²ö¾¿Y@Ú÷_&îÿºÿl=à3(9@Æ  û³@. ä‹íÿyþrùÿ[ßQþ¶àÿ®IÊÍÖö/ ºÿšü,@vÖ¶^ÿ± ¶›+dI «bÿ›jƒÿÞmE°¹µ›Ýÿ­•uA–EÔÞ2ðÌ|,œÜ‹­]¤¬=Áæ*Ö®fV Ï’ÁÖÚ¬âàbýû0³ý÷PþÑA6ÐÌrɸ@í/²`ÿ›UÒÞÌÁü÷&²sq@ÎÎ /d dÔØ¹¸>l•5{þ5åV{Wˆ ÂÐ`áàŒüûh¹¹¬¢¿E#n«ØÄ`•üñ¬RÄRáâ°*ýƒxÙ¬j'€Uã‚äÓüññXA$ŠéÄAÎ 30ä·pý#çøGþ÷ý£€”köℤ…ÜSvÂÿn/«ù¿ $øé+øâqÿÖ;¹Afó „™Å¿ ¤Ë?ö¥åï‡d~þ©B×ÊËÑ rÕþñ‚Ȭÿ!=°ù„4áOFnHɶ¿ÏÿÂÒî„ܬbsAbÙCææ_z ‡?å@œþG ©ÙñÌòÔ°ÿŸ†s²ýGú¿í†Ì7«#d“þ´”ÒG[·?Õr@ÁÉÍÁlnú¯.²A¤Îÿ‚~üqáúÀîÿjÄÜr[þq€dþSd3X]=þ¥†4Áí_ÂÙã„Ü’¬ÿŠÅ!çõ‡¤ùÞ`翃ýÏž™¹9C:àúוYÂÿâ¿`°'Ø yaÖÁL ä]mHûíQbæ1ŽnÍ›7rNä¶Ð[,0ß”lʈ9ó®y“³$T†­„>ëÃ*ÂB‡ÅK~äñ°áë`AÄÂÅ‚‘‰$:f©{«Äú‰nâØCÿ 5ç@Ü«O挢âF—FH|K=Ì7€ôVooßI˜¬¢ ê•òþ,=Þ}𩲌­¿*?Âô`§ð]px*Š\Wãä­œJãñ/ìª,“™Ù^14®€é0id×ÚŸ¦Äºe<ü£]ì÷Vò"Ð_™Š¢ri÷.™Š-(À&øSQ :ó¨âµEܾ%KHÍžŒ²·^Ë~T6tôŸfáŸEýôî•…GÐQ‘•ÌiŒw6OÙÑ` ÷” ÝYÖ.ë#&T;p9JÑoñÂòd©ÃÅçµ£Æ-dBE[šŽ o^lãw¤¸ãŒë _é>Î$õ»®£#jÈiUìaž€™Pàa•%º§LäAú$'¾ŒtéÃûò³8þ’Rú¼íl- Ϥ-Ú…‚~³Þî†z?»+w?{…Õ+N²1Æ—éxOÖ¹s‹V>·Q &`ˆNÌCïNç“ÝŸOÉу«º(Ð1p­÷#6{4ØŽNÎP¿OÉ@ûµèuC½”‹ŽÐyµÃ }F1K­DfÞ½ûg¾DûÆl^Ç€È|å)òCç}*¯ÉØ8P‡¸l8ƒyó1mÁÃi툅 Ï—6þd ºHªö,o¯ ½…q÷6š×¡†/Å—JOƒÔ¾zòŽ÷Ì E ´$K¾õ;|Ýèèƒ*üÈD½‘£„áÜ8ØWbrâ¤ÈÃfÚ?ÊŽâí'f M…•I¹Ö4°Î¶veój§Ä<üø¢ †7‡£p”íêú›:—'൮2UÐï>Ë:&c˜}Õ¼f5œš`!¤!Pg1Ÿ¶uéW þÔٙΉ|>ã¡ «¦¸.cÆÚY÷¶Ävãà:k§´ä$rHÐL vî 4»©½ ØIýŒPâËEðêsÓñ#«ô÷d~==Z{UCqEvô\„ÌÔ"8åŒLG뼸r—a$ºVt›fQ"2zEtÃÛî:5]£©7ïÖM5LŠvO›3Ž«MÅŒ—à *‡ìž(S!rt÷€e©Ú߇ªjA·ä"o ” ¹ë|©—˜'¸ÿ,˜H:ÿôùñDI<’nÊ®pên ê[z Ðû"è¬pÒ.%j²[_̺æY£¥¶¹׸Hxÿ£GÆL'ù¤b&χæËlšú³™>1Û]–ÔîÆ&ÎN¸Ñ7Ø?_:Ü[ٿμEn Y¢2~ÔýœµQŽh?hBSTÂ÷3”LõM:,ñý”.ùØ¢¡2lÄ>Ë6ql¼;…‘/ÞîHƒûÅ´pôLÐGM[çîù¤vÇVÍ„Ïk¬‰Ñ´m/R ˆ˜yt³—D¥»¨õšt\÷ì–å¢d.65\ôê<`(t4\6™—‡]ÄôVT65°ÃæD7‰¨y¿¬À t‰·¨O1Qÿ¨Î° OÿÌœ {ꔣ¡+4ðý×Ú¡G¨>”O:!öÙóQîý†ù5ÝÉ—Þ4¤'ÚÏùòµüš‘ÝEAB‡Í¡—Ù©e¨³ZEÔË‘ÊÅì H–Ðw˜o|£=ï‚$/‡Ç»«¢¿âÖÉ•ä_óUF gzÏU wu¼'½3ó ç•'>‘gÈíÌÌŠ¹¢LZ“‘üÌÞµoʧÉ4/D±ñU¹Aí܈„oy?»©}†~ 8à‚Â¥U:×W¸öȘÂæ"X¹p(¹Ñø:C³4p˜,?Ñb%²&3ê€j>[øƒ6wÇ”QéǼÅ^0Óû28û±ÐèL†ꔄû å]ãB,õ´0—Ä«¯ÏD|[Î0MÖ†MˆšÄ„¦ÒÌ/Xõ¯ÆÏ4‹Qüž bŸ:!ï4R­Î(&r°”ª/•rîÚ©M‘^ó}ë#<Âui•›3ˬ®-uþh_VŽ˜û÷ —¶ Õ]™Ì;çã–Ý·Äã2(Üå,-‡®Ö¬Öý²µ·ä²H ÔÇ9îz è›ÍÂý¦* ĶqC¦Æîù`˜ØónÓ˜{^±û2Á’IwÓo¶âÉ, y–íi¢|ådiðÕã¢Ö7±æ{"¶eÁEYƒÿáƒ%3Ó•¬†~‡r6LÿñØ‚9ëÙ.Àî}ëö!:c‚Œ1çhEl-“Õ<ñ°§$ï%ZßÊÈØÀ‰Ö´¢°+¥E*éj…8n{pœ3SQšmѹl»B%Í´Lý:Xà(«¢»9‹ñ'yöB^ÔÌŠ>&[+Á»_*ö¯ 6ïÌ«ê˜)º¢¤æÂ Ç[³ópð ksÄÃ|Zî í•£Ý^DšO JW¤‰qF&Mqé}°B9ëZA%/0^*Nì”å~—F‘h$Ô¾u1cáZ•&nÓ:à¦×d^ƒý5ÑɚҤׅ©ÄP |,g«}-ÿõ;Âð KÙà³éM‰+iK joí{P¨ü*c9žÔáñ2Iô6ß» •o ¢MÓéá¸ÖŠÃ&“2“µº‰Œ³½` Éä9’õ0¾¯_Üd…šÇ>P6Kš¯†A‘Ø2 ™™üøb8s;Sƒr H±\–šï7-Ó/ÑV!CžxD“¼Å"PêçÚϺ¶ìyúÑEÆò•ªc£®×{³Ð*îy;Ïù:Gã+Ú+í¶âoÛáþÐTž{8!pÁ¦¥H+’i¿œÀ¾®·E ¿' O^$æ'u­Û! ¹ÓL[€j©]u¦U>}ÆS%ï‘>+g>ìû¬Ouµ>BüAO‚U j*É$‹ ÇÆáë˜ÉĹ%¬QyV7<ÈyôB<øaÖgE“ôú³³ü7€æ€U^²¿çSâè æ™P¢>ú‘—<|’šZZPfÆAp°G OƒJ4VKq:¡B«÷zÔ!Tþg×ø%×Gã´nÏÙ”$ÞÄÀâÀxuüË÷ip<ínÛ5‡ÂC¡A¹od·–·e×r}Ži¦—Ì~"dÁò&×»·¤>H=•LI³Kž¢ržTIüiôIïúý¼ˆw-ºyg‹Åp~êyû€VǺߩ²×üGuþç³²õa™—Kœpfìi8âˆhŽ,þw[© '8Ýwñ';…1²\-· ©y‹ÙÏ)¬‘æ£C5L7Ý–aìâA}âß¿¶|Âõ#×Z’™ùú«qeqDôÑúU›ó9ÖèÊeSAÂå›&‡Ö[7ëÅñýê&ŽŒµŽŠî(ÝÓFè0 |oGYEɺ•~Ñ(î«vî•æÕ¤1…Ùs]³»,WÌìæçS›%ŸÖé9‘Üâß3?ê«?7òàzÎf_Öîé·Æ_>do‚Øff— d<¦˜Ö”bX´Œ Ú&s©Ÿ#b…ÌÐ(ÐÝ ½ÕxÎÅŸ®·}/Ûý dèP¹W Ÿìe¿jõ ÎÓÅrL®Ô©i›Økï.º=½r»†¢<Ú"_\@~K·^.Yj:·&Pmµ–¬ >(Št[ßñW‹IinQ=>?qà™³»l_‚ù8ëâ€O—°Ö´üÆ»`Žjc+×Ç€AçœÏé2\…ñ;®Ç!•“è©Aæ¼×(®]õ Ã,¥aÞQ·«<#¸Uˆ˜ äÍ /QÇK-„DȃUOèüRW—gá4£¼‡…+gïÅ­ŒãÒ™p¼¾0äcàôsz,ÁYœY¯Æ=›wý<‘‘XñÆ]þã­ð¥¨­[ZùZBYMÃGg':EÕN¨À¶`6?ܦë¹Wá ̲1Jº¥È i6p•&p;T+Æý=-/Õ $3sï?1KÌO®M)K¦iRÁÍÁEœ`™ó5מí1qÕÛÈF‹jêÒýp@X»ûÌ“r—5ÑÄÑq:ÉJ.• W‡¥²Ýí*2Ñã¯âè•=AAÚãjF}7ò½A­¤&4*áøÙÒ÷‹AJ×l‰ûç• zDð5\ëÅ#*¦Ûpu¸. ¾…y$x„ʬ!qܦ³tøÒ}§Qs·ßÛ \·’Æp¶Žßxù)9ŽˆP£Hlí6ªãúø—+î ÉT回1ƒ+â4|¶5ûa0²¬£[¯ÓÏ­ŸÓJÂOléš ¢=rÔJJ%W(¾OD{jËŽs‹õ òº»k ‘!% òfQ;H\RÞ.]:=²SªW0êö€2ëÎ{$Pãiƒ‘æóñ aÝj‚¾¦°U †ù‹©€ C9¡^}ñwSæxô ï2Ké&ç“ÿ3ï§™)ÒîÞoŒ«rM áË¡ü/†Y6 ÌæJx9Ìc>V¢²‚ÕÃùŠ2?iôù˜…lÏåHݧdr¾ ‹®±Bí©ôkÏè}³AXO_ÐyÙÝ`i£Î›Šø²âµÃòütUÍ•„¸ºÙÒWù^L#QÞ!E¸ú'‘†IgW£ƒr\ŠGß¼Øãsp¯†¾2½òÛÁâ¾w„8àË– ”¥ëD–½ð|Y5¡<4jS<ÔÐ,SÔ¨/œp2ù'JfÉDÆwb²7D\å#"_IûÆ Á‡õ|‡b¿ð™˜r=øÁž wê"ª¶Í—í””H‡äŸ&¼ØÕv·KgÚƒ˜>)–<i½Þ;ãÒ²AR5cF ã ,(œ ȳZ«»‘¯5m5’Å)<¦cðdjw¾t{¯~çÍfK‰LI% W¨zî3 ˆåqv•šè<ݸÆLºð:Èœl~ šNŽr½û¹ë• P8p ŠykÀŒqß Çzrn¸qYí@ÇZn&‰ý¾}Šè§ŸŽ²^ 3³¶<¼ÈŒí‹²•–kÞÁq劺j.‚—Õôk]Éòl²›uqðË«Ÿˆë•ã£5Úi$È0N}Ÿ¶¥¢ý Ü8¼{ß>ÿÊœÇ Æ×ñŽS/D©*ÆP/ˆÒïâ”hô“ ÄÃjy TÄT#Ppèô$è°uvG&ï.V…óùðJåúÝ_Ž]á¡Ae æ2Œtï ÚT0qÒɆ¼]V¼WÝÌ"ñø© ¸ö™y¯ › ±ÓÕ„§Áß“—þéÍ17z8¾9™p ¥q)¥îº(l‡IµlÍÕ¢Ö6 Ìf–QÊ2õV:TUQ Å¡óÉbGøÍ«âäÛ;)Cé€*6Còû‹Ù´wv46¯š ´ Læ œjLŤ¿Ö…ªIƶj”Žh3%ž˜˜ß9ióú4Üì4):øzm£\)K1‰“ŸÂ¯:½¾è;йî+7cƸ쯹m¶:÷f#Ä¡C;:®gŸG lgÔ*I_ôÍ€'eöªrOóz´3^£4H›tXqÓÒøªÖòu´½ùÛ? Åa²Ãú»³Õ^‚iñŽx"ª £ ß±†tÁfOZ½‘þ±%AäÑ)ÆÓIž‹*%ZU…?ìvó«ˆbgQÀÞc]ø´â‘,¥CÇl®zÃΔ;½•oä'°‘+·Ý!ÜA=ÔH¸z/”¥MܘúnÓÛbÙ{üé1qóùžÏ‚*Æ…ÙúNèâC€J€aÜ;–cƒ4õná{çáéR ‚;íýStÇî9ò | ÕHGà%Œh¶/™[>_œ  Û¥Qƒƒ/cX6øGË)ž/, q¸¸^!÷‹z}}õøZhfíR}™7!挑£N5s”ÐÒ´Æ&¶B}öœIÙ¥oâ^ëêC™ø¯ÊÅ‹ XX¥»%‰]þfÿ/©e¥ÅÏŽ‡vÜŸ“2F5ïÏ O#š«Û?dÄqy%-òÛMPÇø»A·o¿G-t˜¨;êdÃ(U±n—fÕt«á>¶ü2¡-«&cýlfRþÆÛͯªÍàù½ìwc/ùdS¦»À´ñów››kA›žÔÉŸõÌ·æ.8ÚàtaPü—Sͯí»ƒ/šßͪ1B/E¦%‘—ošéʦ¢k7FdM"Þ/,kóÎ KK@á\¢•¼µEkM¬Óû0Q§i±ºNYi¬ ~Œ•–ÑúÆ _-M q¥¼‡mm&†?ƤǞ‡'²ð˜ü¥›è|š¢ˆæ ï¶ÂF^6=|]O¹Õ#0j gvå¡Wú åfžæuªÏ÷÷1:æóa›¹H¨WkCc;ªBÕBq¼^èáôŒ½)OÑÙ‡„X*ñ‘ËÓ–ŽÉè˜<®o^rîi¤cÃ'LŽæ_]ªw²ˆ{ƃ£ó>­P=Š–ºD¾gosð•´˜ÕK‡#Þí½ÄÙ)T&Oùœ†ÿ¶ Õß03e*¸> 2MéŒí4Ókû\eyähdn¤õ¶C5“7’´“;•î8¥÷«ºZŒUÙé#O}þÊíf¬ +“áµ,ÚŽº{f™þ…ƒmZÀ¬€ë²vlÆ`Ø9 ?ôûФ߀5+«ø|VîØÌ!© ¶2î W±±®Ú q»}a¤1© ÏAàPšÏ}mC²,÷õ¸D}n¯¯Û=¶º©å|°yãQ0ü+?P)W?RôO«µÇ1þp*g*lE4$­{#õÚZõé´êÁDözÃéur)V ŽðZüø<ÒÚ¡u;f¦*"4µçJú¢æx©uGeÛPrdÂ[jµÁ‰Pmºw{¼zØNº)¦`¡äp«Š<ÿ¤ä<ÅÈ0¸”7÷Ëvn·œ˜½„*r¯'¿'‡‚Â[ )fx‡ºW1?ãQp6h»bysFfå²kGÍYLµ  j_›òv¼B[«[ï­¡nÕþ.‰gJ­–FФd°f5ûüuSìÔ@ߤ¿¡Ÿ`3á¾ ¨¶­njêDpGµ€/ªàñ§ˆRþÚG›"Š2‘cò|U6c‘JAkЬëéâ+/©žhÓ–)åz)S¾çnúÕu¥+×”oÓ‹1¹FxæêÓLѼ÷—a½iÁçÉ}ºtc"»lŸ¯¬L:ŠföX‚Ÿb{äêìÈÖº,pK+ºQW YúÍ‚B=-|,?P¶W Ãmœú«>8yM*ã_R+4eñƒ¸y@ó°e’`÷N©^è0#‹éÌ´+ÛÛ Ñ…>ÜáO±"‚Aff8ŒÌ#–M‰.Ž1¤Ì¿¦¼¨R“,“ä7.@J³}UkR†­n Wç\ˆí™•âà¡÷&‡»"R¶í©af·Hº[Êñ5Ö-'\ìªø†µŒ½Fèô5&h åÓa#ŒL¡ ¼XÑSÎÊM*ƒNJÅ^þÇ:¾”péšg­ è6àDGFñYkêaàM”† òxÓøhè!>3n/ÊöÚbnOb5éø'-Ü;ô8×îCUIŸów`Á•Ô7aï®´ŠÛæô£ß¨£½=¸Ç“õPkåÍ÷œ«ÝÚà õŠÁÂO3)î„ £MÛÀ ¶c$%áÏ¿½g:r±â$Í;aëíøúñpýý5ò/Ò JvëÕ\q§(®Ç\¢>@òËbi}´Ú¦þHRÃ|yå@-S`„²þ{!ûhÀúãmôÐ~¯ÓÑÖ}ñ¾qÅsð$ŒÂÏ7ŸYØuúZ‡P  G*ª¬¿TÜŸ’d`„gîbú̉%|œ¿ñh¤ÄÙ`z{ïI÷³ÍuŬsMDW#j¦®s-Ïu41N2‚8ùÝPO{%(¾3TxFë•#–]œš¹ ù¡¢ÖäU†RM/b ËÈrpZh¸ŽºŠÐxóäc‚ìž#E¸ j~n´q)…­¶#°k9"ò8’ÐÔ ÊYr©í=€ŠüÚó’æ=$K‰÷8ÃC‡K{u´úèw׆uEíò ¸Â4¾R•ßJcA{±sÁ#+xÕŠï®Æúâ]˜j–¯(ï]Dƒ£ƒ¿>–&£ -ŒuBW~sBÏžuÓIªDnšéÁgIBeןææ[ M1MqÚRkçlÓÇÔ²f]þ{WÑ/ÕƒÙ¯ç”"R1¼ Ïb\ê_ðR©2FB/•ãNäí Æý6~õ¦óê˜××ìM™Ÿ‘d½ä%²s9¥ð‚hoHvVðó’V)ë¬kæG ÒÇ?ç!/sì§zÚ`ŠÀÊÜÚ9˜2åß5îúÆ£൉“Ì· ãè^ß‘ÑR·®A6ú¡ª;1€Ø¬à1ZÔüú¡¹u!3ï?±È‘>;0£y)†òîz.³F‘‡÷´çü«DOq¶çT€{¡†–š@mUé¬0Ê2”Æ¥X?›Ù\‡2œ•žmÉ{`“*Toßë¦Öù¨‰ùV¤n¿nŒ·™´f˜l®&‹'šÚv0-® _ÄW^/âˆ]ÃñcÙëFuYGƒv÷Ã·ÕØ×È4ó¼2å^xŠŒk—ì1ÚÏ_ßP{£QŒÕXö< y_ÿ*¤JÌ\ñÁði»­$ŸœþvðnA|¯Ã>¢Lo¦T Å×Q5ÂоÉXÏ24We¶øøQ…•°x¹÷ÝìVºò¹LXPÀ¿Ú£ˆ-Ævtœ÷.BÚKöð¬3Mû¡ž £ú¤JöåiâçõÒn BPòäQPN<­M«r©Ò˜º[ë,e{½y‰•9…}Hg³ÝϪI«NŽ¡µ!’mÇ*öÆéøý§_ ûçâ«4ñ¡W!åsb=šÅ-Bsùâù… •å°Sh2æYÛȵWP3€E@¬Ÿ…EFVœgPf#êú«üÕèó/•Ýõ>žiNƒ ƒ~–ä]ý'œÓ1Qî7•&³ðpøžiîarãdÒþ¹¯Ð„,¨ƒ n„Òé­V/n•Áü£.Ä–[vâãïg1¾#ú²ûß ::JUÇà²ÂÚÙ±uš%º ³ø‰"^Ð0®\tÔRç#¬î€`æúZÊÑÞ¾`@ùí®ÊðÞ×›™eÕ¡÷D)çÍñä·Îæá\ÒQ¬:Øt=¡íÂÆúqrâ dµ0LþpTí'ÖMiåDÑE_ÏJ ›ˆÐ~sç%$È!®ý‚lŒ£¯–8AEDã®ãSòu)ªfަÚxÛ, qŸ¯[Ó\öp(ŸÄòR)ˆ;³@6ì鈑­÷mEòX‹sÝÛ]Xô‘—¬Î³xÀZh'€«ÔbÐÈ=‹·Ý·ñˆDF¸«Æ3øC¤Ê2x¶t$Ø@¡æ¡Z˜lÜÿýQQ¾_›¬ÉAÇËšLXsÈÖÆБНL^öÞbÄœÁ#Ì'qbJÇaÿ¸t{鬬º’%º½"öú %@ˆH+hKgE}Úc©%“·\U,£:c¸ Çßd·i]:hn¦òí‡WX Û3‰åè›ì˜ÙÉb}ÛÒþ¬XvÇuûcohW©‚ÏxùzJC=$š^ÖøÞ1Ò‰ª¦v¢¹€¤jݯnìð"øÂç˜tH™S5×ø»Ž!®Ø+ƒòC%]ëÛŒº8цA¿æ_ûÏ<^bè%öÉÚf_d‡’k Úf~ñ«í®KBFînî£òtÉàÙ ÅT³&A¹õÖž:í6«t1íðUSx–òf×ÛûwóNûãµ.öž<–¸Td<š©k®ó$Ñ/ƒœs²ŽîŽÐÚIWÄž)—FZÁ¤!ió;øDöÇ>ß%è±7—~°Ž%Œ¸nô2ãJ·)ݦjYD*~ÀI6@"ÓL_¤–Hiü…g‘#òR7¨Ðb~rbp„ãJ_€õÅÝBßeîQ±+fcM+’ÔD¨l¥`儞fð6|‹GQb¾Q¬öJ Á+”ñ+ž\ÌÙøUeSZéü ­¾wNßİo= `õŠ·¢xæf0,Ú ‘ý8™oGòÆÛÝ¡}só‚îj‘cÚúý°qÕÛÒiÄn¨‡Îíùãú£Ïª:ž]%]¿ÈZ9(#àD‰ÀìO/]‹šM ïýϾÖeK }ÃÌR CÆdûÒý.ºCkLbüãX/'ÚU ‡¿Eÿèj°lS»Äæe™ ´Õ‘÷•tÍG]KÚNÔì«æœèk,#YœKÒ½Þ–ÄPÜêæÆj;/K蓬Q"B³í>{÷룵ÄUå ¼Û$ùùÚ_b0÷… íX*4Ô |ÍZL¨Î±ý]”ågÇn _ ÙR¶ÚÙÛ¼EÄyÐKß-†;Jˆ²Ñ ä†Á°¶À¦¦c96ßkrÎx¿Fý6`i.ÀË( ºÒàHseŽtC2¥È¸€›†á#U²ï;ì'VëdOo—L|Y¤Ón²~ïXœ/§f(Ž H>°™IÓÓ¸7¶*_ÒæçŒÃ&FMbË{s3ÙçÒc¿jhãÈMêóíçÛý¤Û¦Ük㙸„{òÎnlV—˜1[¥³i¾‘¶Õ×ÇÑ‚Ž\;Íg£æ*<ãdB̶è·Œo”W¶¸¡¢¿ÝŸ‰=Œ¾h´)UÓ¿¶+÷GÅ«—«¨ÝfœT©qÍ1ýr/ïlžU TÒÈ·^OzŸ¾uýÙê½ÕËxp="’’é®"°Ç–fZH%êE»R®=­Ú;Ýõ§ö’Ðk_t˜í¿¸á7Û‡j{3”¶JÚ—|kÁ÷Þû`­˹&”˜¤ôk’K »ö¾½?¡Ã-¢˜*£?yʑ아ÛÒ6Sõ * É£eè@Éòëûáq€Yƹi¬çß0Êí¥Ã£fQÝÛ±rì´èwÕ±¶Gæ7¢]Œ¶%cêÁèU²0¶á*Ÿ»¤›Œñ¹jÚP]4¶f7¯,ÿÍÍÝOAnǰbÙÑÒÕÎ}ÞQM‹N3*&›¥¶ý¼Øòo²gCÊEF’‰ò5°MTró¨û]êÅ(_:ÌéðËÊä«Ä¿¡6YaàÑÒ¿…ÔÁKtiQÖ ËΩÌÓ{Y¸–Nõq,Œºå0Ê=¶í2p¡æŠr—£,Y7©»…piRè\©6m<»×J¹Ë¼_v™EçÕƒÃúò»ÄŠÏ~| ×¤)ÃgÖÔÔf wõ¬.#XVŒ@o‹3î’iw2b–¶¨„3vM$5_Ö©Ù´‹øïf¿)}ÜÚØÞÁ¢×ÉÇô¦øpʪþúÃöE½ï}X¼ã&¢FÙ®â,L Áû6• þ¨jGbú[«µyveoê/vWz•· ¬ŒÈêÈpZºVý Ïyçî˜ú •˜­?Òê^I2EßX$p}—*ìQ¨¢71¸°V*?ŒfS†m ¢s¬‡éÑ>x"ÀêB£û<Üx-395’.$çL£Ýá…vhµ‹ÖM`9¦$r uÑ9÷Ue±Žh ,ñgXº¥^v4¬Œ‚ª=c•6zox‰U­-ç+Pº1u ´;wu^ˆ»öôS§H§ø…ù ¿ÏæÔ>ß*Ó,ÝW‰äÃ17Ò5NnhÀÄ[³žÒy~ŸþIèÈ«–¶¶Ø6h­‹ß={z‡“¹¢ÒF£'’t(yKv ##w^, Þx áåÿVÖ=ÉJèrU€(ÑZ¢î,J?&BY!(“F[Úm¸‡&í㸫³ÂHvûí^çAbÉn¦ÿñä³=«· A^4ߥªàT¼ &f³e·ªC˜†ClhÞEM$p6͉Sï3˜ú«à:ËÂÝ‚é§DÔ‹æ|¨£Mœ¹ÑÕ‰<ÛÌ täå`èVMê“«ˆ4ôõ<…-Â6dÕ¨øÝáâÌóË[y•¢»>œgñGDZý8MöÈÏ´e;b?µ”2}]í«3oDiÓ²éí÷ÅñÚ0[âÓë bv‹î<›4ú®d„»ŠW°ïí6¾ÓWË&c¦={Nû"âeœzU^/f”åûA21ø5ukÿÛ/k?Có˜jªs‚èì4™“­}Xg¢Ÿz¡¹Óµ™‰Tó€“Ę«×%ëïfS^/U*d½m ·iúájP#‰°Ã9Žûª…ö<4g ÷ÁìŠ~$ÔŠŸ‡ž… º ;*Q„Ò¢h?Ñ‘+`váu‚óšõó÷ë ½¨Ä`¿Ë¥·kib-ô‘S‚ÕÉ_–ØV?F¬rù„ÖÔ˜s𳯔L§¨Ý‘¦i úz­ÚÌÑtû†e÷õ ²«>(žŒ )¢¤®{¾&à©zU{‘9ßÓì4-"ÿ¾Û½¾ó—ÕrŠçîá¬ï¬@ˆ^LÓî‡ÓSgfß £jøœ„fSÿšfR)UþWwWþ—}(TVO-†ÞõVP½ºŸó³5˜|$áÄx½ui«¿W± ;¹ÝifP8Så:!n±§× 0-ndœÙÈßïÁð)ù"vþ‚º •µI&ÚXåhžl© §Û=­„ŸÉåÚ_6ØUc[ßk'EçÔ™“sf œ•7LJ+„\'“’<µƒË]¶‹p…º ‚hPcs%ñë·fž¹UM{u(wClIc€3WíeFVV´çê&eç××ç÷Ÿsf+bvަaÒ·gø(ûG§J*8k9\—PW-Þ«€éçK¶ÐdQ’/OËzMü­* ?¨VZ³%+qJþ¢ôvs0øÖ~Ò%û-„Ò(HXõź?ÝGýâD&±M0šá)l~tÄ;ÊSø ­øú¹[l¢ c| F ³ ØÑQ%ñKtßñÁÂNm¾µc`ÍÙóeEßò ^êXÚ…€1SâÖª"E×…¡ˆ]?…‡ ».Cül^øœ»hÉ[¦`R¿ïHdI[Ì/ú+š‡(D1(·«§V³£ï±‰²pƒîÚÔõ¿ºT*¯µ"WûZ¼#Ö\¬f/s:xŒuëºâùcŠCÕDp¥—_´ýõ”ÕñvŸùMðÒÈ?3°¸l_5¨·¯Œ]\ ð?êâ‹E3RæDìÝ:2êˆ5öˆÁ°„Æÿ¸%¨£+à|·Y¦•òl)qÕÓOŽÛåÓ¼”[QæËm|W©Äh- -,­Å·oß…æ7¾…òLÏQºV8Mq™i™÷ÔH@ÊŠ¹°+c“35ÿvܲ–Ó¥+èÔ³fÕnNÕqÉx¯Ö††ªR¦oƒzзíÞÌÞú 7¼ƒ”Ê«NõëÙù›‘>¡Wš…˜ZÁíIB³•BJ9ßφpi/Ä3º1r Ç ‹‰:-ö<Ï¢"©èV)Ëyïk_rPµSŽ1cÖ|k:¼æ3ˆ´Û^X8•×"¡$ϵÜÇ—‡Fu*ð‹Oãäž\VËŒOzð9^P“¹â\ï+5W÷V#}¼Õ2?û~å ÛóúAÏ¢z:ô¾ÔT ÂÖSØ­qiÈ&JîîÇPg¢ rêo÷³ØÞpÖÒrxÛsû„ê8ï’OÌ]y ̵¾…2ß‘cnÛùM†¦œŒðˆ±ûg4Xä‘”i<zìô˜¿T¿Ë{ësUãû²üð–y_ÀøÄwVð /‚DÐ|ɧ°ÃÙK‹Ó#Ñ[î/1Îw÷OßMR5Ž?³•ì´#¯£ŠÒ“ó ½\]Ç$ÙŒôoÍL¯Nz„Ï8·÷PV›á¡l~©µ•*ÂMÖõoó-‹xN •ɦÒÑÝä客ÂÎ%yÂX’â¶•X=”ƒb{öý ²[ÿ©¤;ä^Ñ1äMÚP* -j“DßÖ¼|›­;š‡ˆ,çÀÊS®j(õþ9*5nE sÑñÝß¡®²ªAèS±ãíÊ’>*R…8ܬl¯£—µ5¡e•nh’I {³Ïýî°1Œq#¦W–kõ)•0¬ØHÌYÏ)çõ^‡ò§é;. ßüXIÞ%ìÍ,äªjbêç\JJ׎¹p©Ü-žàw¤ÜC»ña<„µâpÙæ«ž(NŸjrkfïÍ>ÛŽ<È0pïFh°àÓ"v|"ÀˆP˜84ðƒ¼{™dÉ“#ë[ î&LŒÁX<Ôïaa/LªôÊ f1(Y²K§ãíÐX>Eë—êP®õ¹#K+K01¯¾³šgøê‰³{$ï_ íD‹êtóÝGÔ²dnZLC¤É¸۠ͱ™TP<8”¦Ø±õcãé¯b¡V|æ•ï½õ¨ƒ€Œš¦§w?OЙ;³ÏMª‹Iz˜¾™XŽgL9%'n0èýŸ-a¡Ð5#-M‘5CXUQÌu%i ]‹Á=š*­5^Hi¾kýØ#/´úG7ò0¢óàðý9ö«´aŸ.;þ±ÔÕ@Šë±m~‹¬p¶O7w_¤æ²€ÛCøû£Xe¢™`D¤e7‘5Cnֹ̠¾e'{ÞAû§©ìax¸;2-dß~•],Á§DºOHcHn³·Ø-›¦ ¡Ó§ïÙ-š?ýÜ¥æQi`™9E.9Õq$Ð(G »8 þ.|U endstream endobj 68 0 obj << /Length1 2371 /Length2 16433 /Length3 0 /Length 17834 /Filter /FlateDecode >> stream xÚŒ÷P\ÛÖ ãîN°†àîîî48 4»{àîÁÝ=X‚»[p‚,¸>ι’s¿ÿ¯z¯ºª»Çô1לkצ"WUg3›€¤Áö.Ll̬ü % 6V++3++;•†•‹-è?r$*-“³ØžÿN  Ë›Lèòf¨¶È»ÚØ8lÜül<ü¬¬vVV¾ÿ‚ø’@7+3€3@lrF¢’;x:YYXº¼åùÏ_­)€‡ñow€˜ÈÉÊhPºX‚ìÞ2šmê`S+‹çÿ„ ´tqqàgaqwwgÚ93ƒ,„éîV.–53ÈÉ dø‹2@hú75f$*€†¥•ó¿ê`sw ð&°µ2Ù;¿¹¸Ú›œoÙêrŠý¿ŒÿeÀøwslÌlÿ ÷oï¿YÙÿí 45Û9í=­ì-æV¶ €Š´"³‹‡ #hoö—!ÐÖüætZÙMÞ þ.û¾1ü7?gS'+gfg+Û¿8²üæ­ÍRöf`;;½‹3Ò_õIZ9LßúîÉòïõ±»Û{ÿ™[Ù›™ÿEÃÌÕEÓÞÊÑ$'ùo›7Ò™ÈÀÅÊÊÊËÁ9@¦–,%Ððtý­dûKüÆÁ×Ûì0£òµ2½ý y;Ý@'W¯÷?ÿ‹ØØfV¦.…•=ÒŸèobù¿ðÛù;YyôX߯ Àú×ç¿ÿ Þ&Ì loëùÇüï#fÑ•ÕÔ–gø7åÿ*ÅÅÁo&N;€‹ƒÀÍÇ ðýß(ÿåÿîKUVÿ®íñäìÍÁ¾QxëÝh¸ý{.hÿ½4t€ÿÍ  ~›f€öÏðë³r±š¾}±ý^¿]þÿMþ_Qþ_‡ÿÿV$íjkû·žö_ÿ?z •­ç¿-Þ¦ÙÕåm3”ÀoûaÿMµAÿZg%™•«ÝÿÕʹß6DÌÞÂö¿´r–¶ò™©Z¹˜Zþ=1ÿ9†·è¶Vö U°³Õ_÷ €‰•õÿèÞVÎÔæíNq~;¬¿U ·úߌRö¦`³¿V‹trz"±¾Í;À›ímGÍ@6€…Ùìòæxcç 0;!ýu¤Ü\±¿DÿBÜñ?ˆÀ"ññX$ÿ >‹Ô+€Eúâ°ÈýAo1ÿ ·(ÊÐ[•ÿ"Þ·(ª;€Eíz‹©þqX4þ 7šÐ[†ÿE|o€ª~óºüQ¾™šüAloÈ hjz{D˜ÿÊã¿òMóoÕ›þq½3Û¾ä$'‹Ù!Ç[#ÌÀ¶¶@§X¼åý ñfúŸÜé]ßöâË[_Ìÿ¸ü…À®ÿ ùV®ÅŸoz‹¿T š¼µÁò¿ó­}–ž– Vþ&³ú|+Ìúð­©6ÿ€oÌÿÈýFÚö¯‘ý£ë“Ýøvc±üIÅõËþmÔÿ¡ã þSÝ›3øÔoŒþ4õÍÝäôöPúÓ4Nî¿eVàôþ±£+ØdfòV²½IÿѶ7ÒÊæú ÜþÑ®7sç·»ú¿yÞr;Û-ÿâ-õŸBÞî;K'Ð?Nø»‹;øo1\ÿLÔ[οËΦ`§r~ë°Û?à[OÜÿ@ö· ÿ¨êÍÖ äô¯ÿsW˜º:9½õéïëüí"ùþû™ y€L‘–À¦!Öõ!_ïjňܙv'„f©vµÓ蘼—:]Ðà“éj²‚6œnÄ’‡¿a¬îHÑ^‹®={·5‡·'~èxôy2ŠW›Þí@ZšÂ˜,<kè'A$fÒÝóyvôÑ ´nƒì–§ÊståESý‚}çÞ'ãÑÐ_þc,la÷Ã^ ·òSù SŒf´~`ÉU¾Iö<œ  =Ö¹úÜõÍ,Vîä+™|<’ïI G‘·î&ûçûy¯µJ vçBJB]èk¬±ijoñƒyüEïÒâè ¡ÅV:fˆ±~2ŸÑnò_üzŠrXø¬¶NË|2c”¾ ,¿£ fíª;Ð×;£-0˜»»KË|Qi-î3Ü G¼pb0Sr‹…WöôÞÛZ†¹Ö9¾V8þU?©ç5¢g¾ˆ´»Ú"¾&ùîè‹£G|µÇÛãShYFYçýÝzòÄaÖcÏC½s BêÔ ¾09»0£™‡j8þº›S±†¯ÃQ¿—No˜pEZó³ãÅÞ ç¯ü1Ý4^…G/wwâ&OÛ¤Éb9.¬2kÓø_º¸•Ph鑌‰<¹… Ãå uüwïEå˜U‹NwHŸ@Ž+…ïßö•ç?ša¾·`¨8j9>Ž„™ÓÍú·¶¤jG*_ãDÊré°¬ìêÖæ‡÷'BâIéNPçÅÈ!ã<˜¿½Aþ —‚N`é`cÞ¡¬W•E…'þ4Ü¢û¹‡ÙG,5]–>“SÌw%jb0ëõ sÐvY¶7†«ÔÚ«øQkƒÞ¤-_Οí¤ûÞ­Ud7¦v­Ì§sÄI+øÉá…ñˆâiðˆ­*=ª¨¢E2 |^‹‹–a° ûX—#à[Ÿp—ƒ³gݯóñZjѵ‚ìk×`‡Ã8q¹¯Å[ù‘ê¼§²<‡1œ¬¦²ésóœç®z'¨î:ßS2rv³Ù¿ê¹LÍ ¤¬D7f‰X^¥G¶šdm½Ð/“@Q ™ GRTCQB3?ñbPå]”Ñ}.óÑœ>(;Ž6LJ»¯À–l*t¹Ã˜3KýV’'T™™Å5þû«?Qsá©5O/Õ±•èk*Þ6ö&!ätĨ Ä”cÄ;ÍÕ)éú۸6¶$©É ™–µ/¢¨Ó_ðÙ¿ÔKª‰¤0e'g_~+vÄ 7Ì"Œ†¢g³p¿ÝgïÉçd)ÎËmåè­ØÖ¯åñúô:šf#>¤ûÔ¼™~þ;0JÊ#H‡¦}¨üöˆ+BÚÔ_ÈÞº‹}»snÁç Î %æénì€#À$WÎ <+²×³µžÿóØOTó…ü²Õ£¨ÄÝ£‹âÇRs‹ªn‡üGA« 2RZï²ØùúQ4÷Šõ=uP& ¯äëÅè4ÑvûäDÏž/é­tU€ø|)x6¦=þ¶!Lpoê©nq.òñò+Mr\U¤Š÷´tÚ§ïÀ­Lí¡ÀÇ»I®µ¬BU;±¹!†<­Å¯µ‘‚„LS<²pcC 4¤\U7$êwµµ;½G•ñ·jj™åE0†5\Ï|ï¯Ä~m1ˆ ŠSî¯Ò‰&Ôó—ÐjÓì1B‡C¼ˆ÷Ë”£29%Œiä‡%ÏãéXÀ ‡ˆ3ÚdC—îScøOTHQdº^t,ël>”Ÿ cN“B4Ò&WÍÒÀÙ¥? +Р+lÏ¢ÒçbfImª*3ò+xGªsȰ«¡‰rëçnŠ0Ïâ}Œ¡ øqpí/Çìh™ööV‡(÷òÑ6X^ê>¶¬\­é0^b\Uuµ¡ÄW÷ÓGÞbÆÄ|;eì«s_àˆÆLD•d´IÐ0¿¶#¹¿Õ@¾{G¢ñëAa |4Íî7ãMKC¸o(±rö²Ÿ@¶?›¿`vŽ'\~¾ýžgŒµv³°˜p³¸ )%uˆØ@£‚©ÐakÛ»©ø”§Ù=]YÊr¢ò«DeL}BìBK ÐÏÏ,qb5®À÷¥ÛC¶Ÿ Ûm[êiŽÓÈ‹4b76o¹ý)2£ñ*§ÄlÛ–‹ÆdÔdÍ‘1Eö† ’X{ÀÛ¿…¨¬l«Û's ïè:NÚ2X· ”ÕuÕkñx8gÆ Å þåGß×™‚µÕÞ…>Ò Âq¸mBb;­÷£(@œÐ¦œy‹½›rVÚ!1`¢ä4úbø`]faA`•ά”Ð>®°u»å*A~|Z³Ž#ׂùlÃ%t4@©“bEºìþ;lÔ¿” ;ÌM¢&Jäµ# S·sh,¼-¯BÞSñâ5?ø½@Й޷@,ËŘ!u|´|”„P]…ì…c¼Gîóâ_¤¯7Û×DŽƒ§cv‘#¶tŒ_|‰ ¥g…Îs< h¯ ¨ÞQÆÔDìç ŠÝäAï àSqiÖãð‰9çrb…þÝæ0°ôò¸Ä ¿‘¬Fì(©Øßùõ³÷ê/ãzœÄ!3÷$"ŸÅTùW/––¬Yš.]ÊOËéKJ…¼1…›Ÿct1Æ">C"òlx×(:¬c~¿Õ¢£ÂÆÚ:°Yå9I×>IØûr ·è¾: Õzw8á÷jê¾òI•ç.ÌÉTo¹Æsò­oƒ »ÆY‚ ·üÑ<¶SbÕC}²ÌùÈ+Ez>^0»‰{˜Ë˜H=1»k <†¦ƒ{ñ‹Ämlš¼áùÌ,,ž!m}*¨¿Ì ) é æ(o>‘t»½_m>áÑ<1=ôÿÞ _AÓ…nߪŒ>•>Á±_¬½>Pñ_ºüªµŠR–¦ì ÇÀ÷º‚ÎɃå)ƒN;ýíecµ4õ[O$E•×È6Xå›Q’O¥©î ±—xá^°h‹n€ÙZ×ý¦(°ä‘²Kd"·/L1› ù: ¯Ózvšµ€ÿéP£ØB¼Ñ{9†OóYúH¾F„KÏÁàò ìˆÃ„eôRoÞDOBéE˜&oÀä|¢Wþþz—b˜HCÀT"þ?©B”@õõC¾ö+ÕØÇ¤kÊ¥p~|“a>‡FiC³ ñ Òy5ZHn=& ú_œäY1Óž:Æ4JMÏ´ÐÈU5¿F”°+TÅÞ˜ÇhP˜GSÀˆ€nS_>–P'¨uõI #”²+…õApà\ˆXÒñRᲈ1̃oRÉñÛY#šÎ]0Z”û£ ?²Bzu²mPrSâ¶ø>j n°YïZmópï?SvqÖ kûeŠ»Œnù®Àmük—B¾$MR£¥´;ê#£ã¬Ì‰Ý5ŸÙÖéÍñ¢‚ßÿ‘ƒèP5ÀÇênºhÃSƒì~I~:Hn—ƒfL¢ÉÌN ¼Ù1ÏœzZäõYý!3™³¾v¦/Ð.‹‚d?°gʱQãAöq'\„w ³-eÏå=é÷M<ª¶éÛd‹HõnžWF.h"Ô0²aI—ú y‚mÍôŠÒw¢ÂívíåZ'jŒÕhåÑh:°fìô‹Ú©gŸMîä+–0v¥ÍH!•MýHÝ ö ‚`W‡ò4Ô˜®ð[ÕõtÁ"?l$Þiw2¦ò–Á”´\µ†Çy¦µ…IŽl¢3-?RïöYE1sôT*U¡ƒcwù•0ž¥°á¡—㊷a¸©Sæ67¸º%¬©í:h½ÒE6QcUâyr¬"0å¸hÀ{O‰ãÙÚ"VtB ð2ïi®¤¤HßõûÒ_SÝÓG¡a=”?¸˜9ÁË”€Tö2mîÈ(y â’ñ÷_úÖš±G‘Ì™UcAFî˜8{ÑtñïNµÅËÓ…9 ž¡Š¹\7„äI5.ªe#p!yKu¶Zðì[±§&½Ÿê˜Ñ¿Þ= ä¸¼Îøª>$¹ôá~)‘÷hHæ]šU#þ±ÅŒ¯ï=bìºöª‡ADÖTrEuØÆÑûÊóMÞÉ>(LYž¬éè%jò2ý9OºÊ¦²¹ö²Kź;µó]õÆÊC#¼6èÝü”s™Ò¼Vj]ù]ZÊïÞMørù ­‹ÑLÞÆ“¶Þg8³÷òŠlx"ØJC"Øý™&%czшϺÚÌM[¦fs;k-lýbÎRã¹tj&…Õw/ ŽÍD# Œà¹æe7ƒ¯WqŽX.·Û£Æl´ˆ×\÷,~ú'=çG-œbøÒpÚ&O%íŠÞ×t©Èm´ñfN²xÇÂxy2™9x šåwŽ‘=`ñÈoL/\Ü…,ÎöÜ6ªg—íÐä¾#òò&l;6i*š5µQ5Að„XBbͯûöý®xÜ‹hGn¶Š<U#¸5J­œr–±ˆ4¨ô„%ï@¢ðd;Z* Ž··!}ðI Ñ]ó6ë„3ui¥1kÓª8\Çx£´d Ããx¥_Hß’í×NÔãµÚ.¸î¨¹'1%–ªSF”+iÐ>ºaçš6Áýè«rH(ŬaÒ¤‹9ßæ—iÄ©õ¥ñ”0®‘ˆSí"–¯°~ªéè| µ &ŸúY»—º·ÍG[—ö>ähJVqXt/|‚ÇLå{ÁÞHˆ£vT0þ’°fµ ?‡ßŸ Þ”žBIp Ž4ÍópqÛšOYN6m€+Ær~ I?1òþ§"©Én/c…Š= /îðÓPyU59þ;©¹0’—P6<@øNXÖˆ? áo îÀvŸ¸t¶ò†çž"Â$@cF4…âQ’»Ã„u&nâ¼åG¶ÛšëÒ)ØFÃbGtÁIÚ³ßþ½\2=È! ^ £8à„!2™¢Y*ƒm……7©w­‘›“–ʼ/aqæp)û¹Aå–Á,éùµÊÓ¿f5ÙE.-$Nq>Và¼w@òÕ‘ƒWÐ ºï`ìš½K;SS#ƒWµ±¼ÕÖ€ÜM,ŒCÝ<6Žp™P‰HPȰ‹½Ñð¦×gÕ@'¥_ÙÍSÎC©eMJu |ýõ¢xÞ˜ô±±ueý^2 ¨ ·+ Ärúʹ˜8/JxoÖUžÚ›´ïVÃ…ÓuÔžÅÂí“4Wch1Rµ‚zu®øñ1ž—ä%cnÊÎ.* ㇀TUâQŸA–¬O•zâ·ÚºðÀûë¡nøî’ó»Q’Æ’ÝýÚžŽôrÛ}´ëz¢ûôÀÐméeˆ:7Þ}äÞ9¨ð´·›œ2A\GÃ# n®ÎO#_˜6‘[1 eŽ›9g‘[Ü1÷rþ±ØˆÁ%‰-ŸNlÍ{£ôîlÇ4x±6/¾¢ÔK•þÃhYªú¢Ú®=Ù¾­ò/ü¥Xlëáð2(÷NW£þhbÖ Ž"£n»ïBÐ,þ.®\ͯ¶¿ ]ÐÈ!*Ã|騯v´.¿H§Cù|œ1[ÏÓœ/†58M2åôe»£Œ›Zv*I‚oÁÎ Öç;S=Öo™{*þðKy§—fÁuÚ Ão} ~5ª‡p† Ûës„ø½›::¡’£‰w­I”8"æ-<¤©+¾˜m G‚"ö9ž²h¶4BA><×~¹w|Ò] p#‰€dW¤±³´$«K$>eLB’„P¾ W+Ó=çñŸòîH¦º>ͽ8°”CzÓ¤V‘‹ ó`äŠ[ˆÇúÍ®w>bñ^Ò[:œ7ÚðKêIJ#iò[%9‡t~¯8TY%&zݘ*"ß/úpsÕÜÃ7Ú¥ª¸ D(r´w}æ«å¸Oc ’>BÑè›E(Ü_9û²Gz£s'äÿqó3®‡k´”F¦#W¼‰©ßñC‚à!ûc¡‰˜oh`nú»"Ås*Üû,4PÆüd“sPÝñ¥¤í¸¼Ñr”×2ŒÉ¯cJÆž¾2GÅYø#"t¦ «°ë¿S2^y¶ÉyÅG:?ÛB3¯¢@¯I'ñšæ]#ÜZBÔEÆYuËI¾^*急 ¶Î’P?F˜A ¨†~ƒ›- ˆäh]›‚v2mn1ž¬|Â%¤l‡Å¿ô«@•rÍ(êΘÃâr-Ñósn—XË ƒ¦|2Dµ7[JŸ*«ÛVG‡óN¤ÓNàÙ‡ én^û™ýÁç ˆå ÎXãÒÁ1P™ÉmZ»H…M Ðã—åýÖ8â`>d‡_”Ò®„ÄÕ—OÕI׬3NDΙêÕ{PBßfdg·‚.}pE¤eÑëÝñ(Þ€0:qï̼F Ñne„ú* ¡‚wóéÃÉ'ãÒ}cy#ñšMRË’9Ç‹Cl^raæËÉA¢nú¾nE¥ÛÊÁ³ýL“î¤b%ÂT · X!SnÏ~Z3ÜJä>oArÉ‘Ð;ã¯ÖåH"‚y^AóP†¾©þ°–[ÐÒïƒÿa`µ a1£g´¡ÛdtbF\]ð’ÄUXSJ£Ì뎮AÏ Åï9BÝ:[~Væ¿•,öÀ˜ÔAùlÜ`‡r[71й<;+£0qÞ´rfì{§k?Bò½4“cï[4hjŒ¶¨Îb` üXŒû Dy¢vßòšÛô²Zù[“K½-Ïoj]ÎQdÎŽ¤œÐÄÏ!!' ‚1âF!è7Ô &Â'Ô=L˜%òÆyxPíˆl¾¡öUܳwÍ.ö'(âü‘«¥7¶ÉÀüÅ(Ô䨔Òå¦"Žíˆ¹Ùwxap¶×tú©Æûg… `¦ÛÉíjëÞ˜×ÂU¸àò8ÄEÊÐTÁߘÜ:AS E–IKsúH¥çáTùB¾Ö À@;…àÛÂÌœpÁÚ+tæµ?™j¡xB‹6=‰®Äð@f¤JΑz`â1kÃaÀ<0¿=hb¡§nW=¤Žk"ù–É—çSÂÜÞ2So&=~«œDu¬7ÛP[˜XdÚ†nÃOøjB'•xZäwöiXÜ;d8_c¿ðYípm˜`J>+ßÖ“‘Ò¸+~CE…ÜeĪ·¦H>„ÐvkðTš01wËl+¼'¦fœ“…¯ Ƙnþ*£dú«—:±LµÇ£µ‘Z‹ #ýõ¸0ÖJˆ}45ïÀ‹?HÏAyô ¼3mИ¿/gëVí©zµüd=«G ä‚Ùî5íþS`Ú´ˆ/¥æð#Š:ï –wv<Ú|¶N¥<§ ®sÛ9 ¥C¦KÆsø]݆u”¢ö؇9ÔEžDºª‹›€–À°ÅßñãñÍÌ=__ÍR™ÏôÛHèµøJ#7Aü<Ä5×Öïì2Ó QÊÉ›hŠaºq8Ú\wˆê©÷K»›•Øý¤®Æç\±ŸÓ>‘çn÷`ò…B+kQÉö|¸óŠ|_QÎS¥ãígSÏ^>‹s+¤Ùí—ÓÈ<­Óô#==ß}…±©Šd»CÓPpì(y Ëoâç·ÕA¢ÉóU÷çà/lð6Ke*m'™õÕF Ð{ô>ª\¼÷Çöî-lžnhö^×µ&ð_•‚É%Ùû[;µµ{übvûG ÔQ~»íR³0á¨kìœÅ:#A$­¯­ÊXT“‡}µ·Ë+§;ŠJiûœU‰žÊëíL&Ùý~ òÓ¨ÓP82ïÐݯœÑðU›Ò¦ƒÄ mÌ×çæç{n\ÀÌž`-î`ÊHO²¹$B†Œo:DÊ@š¨œ®}>ýI‘+®æ¨êÏ¥²3öº/#µÓÚ7]³bâù&ky±Ò©]Zï«PýѤÎ~?g€| Ö9ØØ…>JCÔnÝŧw«8nÝx[}ç=x5yHòtš Oã‚BP5I–…·çã¯Ò­•m‹y6U:2#ÕáøVb+íºX«&ü†Ì.“\:6>Ý6ËØ.Ò¾êF¢®Ñ¶ŒÒ !Q ±faæ(žŸhzvlÍ·8_žD\¢çŒŸuŸ¤¶TÔ™}Æ/W$~ˆÃXœ‡'Ôv欌?ôŒÙs;ÄÀ}Rc#qC"‹Ó“ ¬7P%18.Mì‰!Æ´=ãg‰JÏŠv/½E•(­ì‹}m±*¿Î'ã>ƒÐ€ºY)«Ø{˜A‹6Zጎñºµ¬½¢e±=¾Ø‹Ö*ÉWÅs°>’DpݱT#FÿÍ ²k1šg ’jµJ„Ëkc£‘€!±X0\¤áx =:K‡rÞ94¤—.ûÓ#HŸ¥5r0›áÖ%)cuÈ¿>¦µ(B?"ó²±JfŸûTy¦`g}¢‹¬ È4›åæ¥^3Bøsü=é°ÈÛgŒ|I"õÓ³ÚÃÚÖ÷]8CÍVJüªjƒßq0 |¡AÛ' fºÞ嚯¢ñÕ&á.ÓïL\rÑ*´:dï¯ód’”d'Y¹–ü‡>ôo×E3;6ň²#¼t2TëÔ 5¹«32R†ã4SYÁ1¶¡ò­.Ðɇ§»ÏϷبQ Ò®»i¦¹9(²8ˆ¦Q þ/<ÐÅ7ÈÄ'ù/ò“iy¿Ó*…ÝÎÞ³¸ OõÜ7 ŠÀÛ¿Žixx‘y}^m¤ŽlþÈA ‰ÛÞÜu‡=š]ïÃ9º•­E4Îæ™ï3?JÉ .hDm„Ã{A—•à&JeÆ}]Åd‘iÇýMä(ÅD†ûT·óó{ë[š,ÇkÒUëIýÕH Æy‡K'éý­]+°íuZ%ÍU³A¨´úèüýùÉÂÒË•ÎÛƒåÝ»h¥Ý CBLîÀkÅnø¨Â‹AÁ§aΰ ¦w&* 4§áÍP?Ë]Zw?¦Ê­|úÍCµÜ ö“Z“¸"­nWié¹@Ozc'J%õ±…uÌSFË ’MØëqZhré—È“p¾k èuZnªËöùË–ú:šâGG¦kiØ(»–=W~ú¨×ËœþÁ@„²œŽÐ·æL鎺ùN»xÊÕhS]$ù/`Â;N4ÙG¢S±Í…½í:—rEçšô F™Ë)Øf§Í-7¸£/ÅM1³5¬ÈJ…Ußr«HgëBçñ}°òBV Žnx{êEÃÇA0{)D¦—ˆ¦ÖÀÏ6Ñ Ük6Å?÷‡5h!ú݆“]g"×\αŒ™"xO&è•JU…Q"YË!ž2Ÿ"[ … )Ôz:tF#Ç(ô>t×¹í¸0­‘úí@¸8vÒJ²äCRƒ9ï‘H‚‡T{zo«v…JPå?—ÅLöDCç,xâ7C+Êæ‹Äþ‚Ûš–×<öÑ–Xñì¡\_*Œq&JNÖ½Ú©)L)ùÅf·OÖ“ÅEGãΞ(zBW¤ùò•ôÝ=W¹‰1)–—j(pgÓÖmß7‚!#£òw^NÉùNHÒA:®ÍúÃò•KŠ addQçúft5bõ™³@-ƒ½ ¾å•Ä÷š9‚hDÙ O5{ßíD¾ œKÄÁšwå·¸’TŒé"„h„¤ ¸ä…BYñ+ë'T/sžw}ýÈÓcìçí›Í‘Ì"?#øSûéLÁñ§¦ø„\M©ö@¢°í^p*UN0Í~²VáQcÃfë¡à&OtŠƒ‘mjÄØ¼£™°Ò»˜hü‰4/Ånÿ&Guš!ÐmÓzt®y.ÙÂC;Aa›|-‹BÍ{2Ëg¢Bö|>›MÛù“ÁºÈQf{å;t4"+zI¿Ñ=ÅË_†0äé'×ÉÑ=¤(¡ ½.#ô).Ýf½hÏo½…‡/[q½é̬0ê‹ÄWÙ¾|bG_›}×'äRb‡75rö1ãà\Žô<ú½ðDú9üK9k1J»+è¸Ïú'Á%ÅV„_çÁ­Ë°¶2û±@¦ÿ]Jæíá«ÐÒÓk‚” k×ÉOÕW4u-SH˜Mê0hˆç"$ÖÔ¢“k²MãñE§ÚÖ5z3°Îüò8LØÂÏTÓ¤©^ßöfâMæÙ:[…àý† ¸…eáPÈ¡Îc£­”¸Ýû.06Ô¢ Çâ¸P1? Yòà·$šªŽRºEôûà]BØ-|)„7€CÏpÛŸi´WÔäµDåænª:VŽÚi]UÀ:#äàŸ ‡Eî‹]»[ßÀé{Wò]¬!÷гd¾K*ÃÍê œïE%>$ýX'î…C«EÁãi&/˜ÄÐoÒâì^Év¥$G›hùV­èÐVÕQƒ˜RÑ‚‘gŽˆ® 9Ø`0äé£C¾ëæpøMmåÅlj¿FÃcAŒÈv§BûvRƒ»~-¸¿CòŽM©2b¸1No½¨OQ‘>µªCZQEUD¦ë´HT¬—§V}©­ÿ®5 {ÒP’íh߆®"oŒùN¯b¾1¢¸6·›˜ÄvˆûýLG+^rkÁÖ16“L¸Wlxo+„‹ÖøHÙB™ÄSð¶ Ä'¡ä3ÉŸ.–þ¿!­¬ÍŽ—Eú)úuªñ¢cMgÈ7ä8rþ%ë›4³—ÑX»ã·Ì*A9D²i?Ë|õÚZÄÎ#ˆ:1à¾ffÇë!Ÿ¦=fµ„àŸe*Äu%\ú=š–>~Šþ6‘Û‹ëÐ<Þu­}ó<'Õ–¸ÕrnùÛçYãòbv†¦¯¶ ‘/ôuZêâÆŽØcKàˆl“•4jzOéž2ÖI/#FÔ¯œšÇØ÷âw1uŒªч_t…8pN ¯‘&ÐYPáö©wžXÉŸŠRd;Eðî~XKR®Bòäv¸×uNÖ(ÇNNøÛøi’ìøcÚDÏ–”‡ãôwåäˆ Û%Þñqß´é8sÃá+Ϙr'‡˜ëƒœ[dÇû6àœìk[n. ®gé褜 ¬<ƒ&3£Ô<˜øe'7îd!Ò«–ܧL¾]Ë;ÔÑ?~)æš›L?úÉ\ª¬ ¡;‡V‚êSòðž„™6´4ËýP‰€™n÷ x8¼„ZLþ2uÅÉï:&×mb0Ûìva½UÇ5Åb 7ø{«|eýcÞV€ Ÿ²æz7)| T¬Rg/áPò´ÅÈÀ!€w:uBèÑsÖØ§d½Y:UIªc¡ê(KCxb”8kËK8Ÿ§ZnΨ®sígéhQë•ÒèÒÌ÷ìÜwÂr@ÿúó>çÌP ¾ëøgíÛZÊ’¬ C(:ŒHìU D%¿o‡H¿l#ÕvzÕá‡ãlQ¯’"àªv&) «×ݘ«‹ I6Óƒ<å´É%`®×÷äÖŸëpí×޳ΙÖTÅ‘"AP &,íSÜê'[o£ùá_#‹Ï¨ð¹Þ@‹½Ã½"Š’ÐC.5”®¿âEÒ%vHÊáþ,ÿ™au¥À¿)pÅä<€ðÁ>{÷2wëV·˜É#ÑG,´Ž¡»´„åŸZIÆbíú³M_Ö%p8µ¦`½;eI$xºΊÃÖ7< ©øe¿gàÆk¢\=Ã_àÄ„%õ9u… í¬Ñ`^nß>Îå°”XŸx·{#¾ÇÚvB¬i¨Š8Újš@½ôqD×ÎXöhJ@^Õ5?séWÖwð„Å•ássµ8ÖCE~*Rý‰† tF]®Šÿ"}|g1°¶ÆjTõû÷þ*ê3}í¥\ßm2ŶGõN°f4L+ŽÝã™óÖI0È{’%—ù»žàî?ïn+õP»˜pî»æâùQkÃì6÷»ÏBR~]涬î<¥˜gDWDc›jéÜ.†%™Æ#5k¢É©§ E:’ÐX«ýfª¨Æží ¤–wfpÕŠ]ì:L§åz ÀP–¿bý@Û̲¶sËÇ(¥åñ“’±b•VUg< Ò þ§R'¶ ´&Ò»sJžÄçôXŠÄk[êé½ck¶ØÁ+s¸ä!)1;¨{ô1ÍÖö~wdǶÒ7rõWáïk™\½F"¥F«v·Ã[ÑÐtí¯¯VÒõÇÎn–¿ á˜Ók™¾Ýi¦W$/°bO$|dJŠmÿj8ÔÞZdƒ.I\VóŽOˆšœ¯vZ´]“ÐM¸älßšú¤9êÐ9RZ°Y¾XB†ûÇ]&Æž1p!†÷Ã^!© ½§ ¹œ2(i[wý‘¿3éi½©äƒá!¯ý"'+´YE¢ânoJ"8æš#¥ªµ^°N÷¥hàɃu$ øLG.º<¿'V—0{ÕJæI¥ìˆé—ܹæ÷òžûh˜àM•¹ú;U©Úï÷ßìJ«ñû¸€œL_‘h èãâÏt?q+ÂY¿¬(¾s³×~.±ÁÑ©XWJ ú…ßfäU/¯Ä£àíU&‚yP¬g#ïê ð˪Rg­ÐIôRÛ÷¶'s,G’#ÍIÿmGeIÒz°ü-HXØâ·µ×ØŽáͦ,¾w‹ÀLJ­ øØylO_DmÎ'C[øa y”xµ7èŸï¸©ÀK:ñâÉCSnžEt×å?áG†ïöï—?Ã}}JÑdPaHV‚ Ç âl÷bûà4¥^¤F•†®¥sinC‘§ôЬ ¿MRˆX¸¹âö%#¡a“‰«ûÊÂ4—µbm¯´CêûuÛ a(VàQm+Òñ}I&ý#Uñ,4ââAeDDË:l×ýªCŸ«aDŸ í’)løY‹ù)1,F] p¢r^þ>¨•Í×@u186;܇¶Œ4ì&¨••©åˆµo>þƒñ,2o”¡¥Êžš¥š¡½'ók°`Ím]ä5øá'7^:4¥=s3ô!ñ£Ü&ÆmVÊi`€nKzx¹Xy]Œ!@×åÇn Ùãså@y€dй™m0öÎ⇵P]ã/ç;k4唆™+´¥XË2.­ñ>áóCmŽdñìƒO,]ê6^sHü/”RË_âð<Ÿónìd$óà”Q¿)E|Ga²õu•Çl¸Ù’ü>…E8ÎïØ_îªÐª(}ÏIrPêi-ó"ËñQyÿòãœÑ‹_èLÏÂ^“‡„³)’œ] m¨G Л¶Ä™Øäà+aQy¬µühá˜ê6‰vF…-îTí'w³¼‡O¶ê¦Ï sú‘°GSˆ _$¯á1'xK›µ¡s» ¦¶ç8CÍ´n‡ø>Ýñ¨7MšóÓmeQ?÷òK¯ôÍcñ¼<­p¿/N¤óc:h­•`Ô5ymFéY.¦Ì¨Z«fM[úg‘•Ð,ßdE ö3lØÜ ×ITDìAÝ  )‚Œ‹«¬\ÈñÚKo¼qNN8‰/ÜR©ÔyI§ðUtyI,!ÛüÒªM€DÚh(â:AlX–Šc´‚ !ÅcS”‰}õ'pÉzú#DeÖ03îÐĤy­ŠZ¡»+{ôþ9ÃCløkœhðU7z¸-¾LýmIC“5%Ñ5K‹¼>7Ä‚At5ô.Ó7oÔ#W‰ÞÎ|œ§§¡¸Áâ‹âx½ø¸Ü¬åhf÷JºÈÃôµ Gæ’2xÔþ¨›¯‡I8W°ÙPH±–›ÖÈ`Ò8щ ÂY²¿ãYˆ—'–A6Pàuv‡N©¢âh£«Èr[éiË¿Z´ö[)õ—@>'gç‘kÆ®ú5øóx(¡¥)3Ý]íðxf8Q|f!jÙ r*§­`D?ªN]‹+WlTö(8+ ÿí9Úž‰é³J8õí êOžŽº|SÙ4謟÷›ÌØ-÷3 ¨7ùó§šä‹(ä¡2|Tˆ<ØúsÊ©ûðMG?š9LÈÆìÆÎ“;ß'WÇhr£8øI˜*ñ]— A(´îx@JŸ²Aù·c‰ñŠ¢^" rH"-ý™Â õÜ’§ÿ½"£ùo³ºÊ~ó ÅÈìÉ/pquå×2B…h‘§«Å•ÇY [7¢n;hqæ9@–ÖÆ!sYáûOdÛѲûy–ýeqžÞsŠP{…¼rEqć Iíˆg› ™}ð “DÙ2cšE±Û\Œ_52C&Œ„áÙÇ}c{,Ä¿sÐñ}.! ¤O'áß[ŸªÜ|m~.¿rGœ§ãŸÕˆhÍ&(Mžaõ:Æè¾,¾ 5Ïà³¹Gü)5*Þê«€§VNèÈü0Y£70·™†VÄñ«ÛÞ™¤ œ‰^(Žãø<éc2"<ÂãÞóŒÚ+âñuøaú/t^6HÎMÕf}zÓ†¾/WOleÕUif­«‘ÃÜžJI­Û¯´®\T/ïˆçE!Z‡'v†´ÇîbÙŒ1FGæ¸ß1*U §«µëåÏŒ= ÆöTóe ùÕòÁÕê7ï_à"ÀábF[zÒèqï>*‘ j5°Ç¥EšDå |†4¸#Õ?‘P8Ò6BŒ_/NÎ^óÙ8™÷!rú— M‹éã½æ+¤¹ 9Óª0ð»„i'*³5R•¤±w¦ºdzDûŸX÷ZjóÍÊ[Y8bϬÖGçÓŽ”¤ø]bMGi ±FÔñ›·¿¶ØijyhñÚ8)?ò¢²‰®¼ŒÑ;9À¢k]ƒÉºó±®Ê~7jV@¥™§‰6x¿.'¤èiê¯&ÿp¸àþ{û©·q,Gy/N¢tÇ2¥†H”ö¦ ÂåulhÁC)j\µÂÛŒRnÐãÇ map”)Ç ìü©òXIçK1Q¦ÇÈÔ*wwðB4TQ‘Nóá Æ„pDåÃÝ~¿ÌÚå?s/ã±Ê^ÔÃÌJWS³‘¢”AÀjT™ÕÜçŠAµÅÕÓ3ZkŸãWyîS,gN†ÒWV™y»&c×½J|éæÕ ùÎûäÑ#G§F «n½™»–˜U|†ž×ÝkoßB›í®¬éùÚwZ§’_ÐøÿÒ>?RûõtµÚ|Iiã&ynDQ]”ƒ¢ìàq€I9ô÷Ø=^…ˆÏÀma‚€]f¶aË.£€6¸ú5‹³TMPÎë";'Qj8a#ô¦ÐÄ_̱)Kp¾ÍbDuYâÌvÔ€‰Tõœ’$/Lo²8:;¯)¢¿!-ßz›_¦"Ó\ æOˆÔ^‚[±ÕXnþ“‚¹D3¥¤t†ÅfAàÐMïû Q÷é‹$^›Ú`)µjxÓx&:ciXi¯¹ñlî„ Þ짉Ùs“2Urät«×ùê<Wí+IŽzÁû¼èòèœ1|ç%$ðS—†C*æŠnÔPWûŽ”&¨6tf–R©ôZŸE˜"lÍw¬«÷«ü õÏãùÉøDq@O[TN·oøb˜±Î­?’fÐS?kì¦âÜ®èêo¹Ì©i¾çì\T’Û¬ >×Ô¯[¼Ï›Ì>Š˜ÜFeŠCö*Š™#†Ë÷V>Ò*Ñ«Õ200’5doî‡Ö8øSýpßaµ0äÑ,„´G" Còä.FðVüÅRO0'ýˆLÍ»šz¤¶C5ÖÒ&8n§B ÿ$"z@§;"SeKÏ7Pqj‘Må«çÍô›¶nÌ_$JÿèUè?¿;8ó%ªz@‚ü00_i:ëAÒ|—G(0fný5HRGCÂwlæ«÷‰Ž<<âÄDâ`D‡tÌ:VCCÖxÜ–÷×Ý>>¬Õ‰ãƒÊûEö(lânA¾Ú¸Æ~NŽwHÑár(PpxØš§Ú_o;ˆ_~À]Í–ÕR ,X'†F£>X¤¯]ENþ˜„=œFb0·º┲]'~­øL?L#=ăÎ-RU•餦í;vIâ ªwV”AÊ­.ÎþNú{µ"„ÞvÖ¸µ]`¢²Ó$¥’-Ü¢uâ F0>×ÝtøýÆzæ•圲òùéw{²ÿC¸é©`퉂Ã:³y¾áJÏ[0B]°lw;Ë8)_üÓ(LZ65jJÞ$Cª$¿kQ•é`¾‹t^æá¬œÓÑ.ßKú9 Lˆéf·¤¿Â™õ“ö2R0AB´ŽÆb­gàs¥Ì¹çOM/¹ÂT†àhäÜOÕE˜O¦¸œ(8HmÐ6ÉJR6-±Rš=ä!ÓLŠÄX;b…—nW®×çU¿(8)&EñÎ}W§Õ=i lÝU“ÙzˆÀZsÝtW ÂûeÎÀºÖ+ý{Ëb—6Ò×|… ÍjzÎ,'J~<âüGðS!õ£E-?ôC)=‰ˆw„Òø%×ÏÓïÎØ¤ÚÕ‘¤î«P\ ÕFšqÙ;²ul­"3øI÷WÃà8ù O笢ËôvÔð•Õ4CÁR.ËÕ~ߌb |Ú¥œœ!r¥î *FU8‹Q•w4´ãÇ|æŠl0rüÊ%wwÁšÈTPõøÝ¶â‹Ž¯—KßÍnͲ¸fŠÏ˜VÈt»qonéNuºd~ðó­ú=ë Á\+CӲ׫ ÐCºî×¢±’"„E~eޤ¾Öþ¥;ÏÓüñ³Ïu!}”-—}ܱ¡vò­HxÐé¾}n TÖóKªE}1œÖ­ôÁ&·šÃËh=+´ ˆß/?C–‡Ú‚ˆŽŠ¢ ne+E£M²(¿!ãÔÁŸœƒP=º E³ÜÐAÔàIôˆÐÈ|ŠË‚M{“¥—. [ÌËÊ1 eŠ—,/L‚¯ Ù8…Xp–”ÌI“xÓW·>Œ¦Žx*‚,ß(öË?Ýöü±²Ou~ÏCò‹È©ÿñjÝçh9»½¼a2J÷…48Ôl…W{¼ç´ìUœø£º¾\2‚׳™¥µ¾§8idé%Ly‰?墷ßá&r`mméAK÷ëeàpèÑyü Jß±,ÿ/ ÌWùôD‡!”ù'é{ºn/)O¡BS³¤,ëü—D.ÁŽÊ~ó)„·KÐÓ~„VžÇîE÷D̃¥†lì®Q_ºž6ä^=‚@[#:ïiÇwýÌŸ]G±Ï‹¢79Ä·››äa)=õ_чëëíÒŽ÷W2N„¸9ˆšhUJ«V:fù€×É·¬Ñv׆s‘‘Ü.)µ–ª¾cß nœEí Ñj…`³6|Óœ•°{{W÷ÃU|Í£Mœ»Òûâ½$ò%H½^QàB r¼4»'%GšÌ‘çú©’¦·P>ý ¹ï.XÌŠrj榵ß匽+„½×P¤nqp ˜ò¤¬0¾ò€vOßBØØ›Òe7ª„. ݽMüžìë³v¶a=€+ê6‰ê‚Þ€aNF+º~ÙJ…Bà£vNNa5}‚ì‰ã¶+2”Wt¾bYÏ&†ÝšpŒ¼·ŒÑ`ò€QšcÔŽ×ÝÊ÷¿ÚnŸ÷Ú‚°¹§M`b Ík•>îCâÔ Kãür„ƒÝ P7iq»2.FÒJ¡µ°À¸ÍöÅ8G 3}¹õ”ŸöJœäSU½a©­  !I…¢ÂjþIý»P]:ÂÜÁuq‚yÍ]º9‰gO’ŒÐ”@ èÛËYU’ĉ^c­¯úüά¦¦Ûz e-– 7d:hè>×ýFœÛäç*Êú»uÜgÚÁÓ^´!,6 3Ϧ¸ì”›:6ƒ fý9t’1?…e»H¹¢ˆ,’š­OâVŸñ‹¾“…­Z˜ŸUcº,]·Öȵ¸XUèæEùÙµn”;2³[9¯Îïó"¾{ªÁ*ýT*-UødËHÜU¤Cò#27 þeya{3U¢Š«¿¡,NªMx—ê4»0a§Ó£0Ïbá<ŠSÖÓP;úšk[_žgnÞ܃¶>Ý.*“~/L¬×kj9IÜ_mYrN#ûúÚ©·Ñ§˜Ôœé‘­E­xÍ…ñÿþü¡^LFgÅ'ë£DI ÎÂP´Én<áŽòÆ*‹gaBä²Dæj…›—?¢K­ŸÜ)G¤= àž®ŒÏFH¢­˜YyhЂë'!3Q¸ù´X**TŧzÅ™–öq­‚:€13ëšb…þ6kXªO±B¬ôi‹X×17Õ( ·L¼j”¢‰® RjÀ ©SÜ0`½ž¡ÌÀ z²)¨aiV¢½LìEXN`ÍeôQGæð8ª,¾(¸mm¤íb}· Ü¦Î¼qØ—Ê2¸]£e«¨1¾5ÑÕ0#f –Jzw#@5Ò¬n:T#ÒN»ý0 ¿Â†Xì2–¸·µBêüôñÑ„ÇëQØÉ÷´ÐÆ.x“²‹ «=ÃïþxåÈÔPcrˆ¦Ärß+ÄŒ?Ïq²r YÁÐõœÿ,Ú¾@jmd¤¤ÿl×=m¨ÀOÕHˆé¾wŒgý}ºFJôç bó|9ƒÀYF&ÂÌòõþ«/†È#5ˆ}cRûÔÕº@%+ÏäÿVWRi5nÜŽZ9«Ùs+èõ#Ô£Ü)ï¼…,µÓ.÷® C'¨|J‘ÌÜDáü]øÙö+†>’¦JïÅ(Ђ>ì½îaíG°fTNiûiž^÷ŽËÄ÷ãM vå™…Sk"TÏC]6Æ¿ÓÉ¡5ʸšTöq–ü(¯o«ø;ñ3RD›Q*×å_y—Ý"-è•—mæþo[½¶ŸZÀŒ ÂýÎõbàw {Gȓ咿Cy±»ÝNQfè©æGŽtüZßó WÈŸÞt‰€œŠK"lŸgt„g˜åDk¦tµ,-“¦ÿp¯öÚ-#µ Úáxµk"[ÁÔ \UFme>˜ãBnŸµeƒ—Uß0Ô¬|ÒòŠ]®£è‚þ±Ð¹xI4(Õï#Žwç«X[¼Íü2¯Ön¡`͆}†wÉ^/{e¥_=nXŸµÜÖ¤G˜# Ÿƒ>xo°Ëoƒvj÷u.;ç(ÂBE+‡UóÛðë³Óà endstream endobj 70 0 obj << /Length1 1614 /Length2 13308 /Length3 0 /Length 14132 /Filter /FlateDecode >> stream xÚ­wUT]Û–-ÜÝÙ¸»„àînÁ}㲃[pîîÁ]ƒ»»»,¸Ëãœ[·nµ[õU¯>Vkké£Ñçœm-JR%UFaS{c „½#+ @]å«’‘‘©¥½£ˆ½)àÃÌ OI)ê4r²´·3rò¾Mb@€õË—/ð”Q{»ƒ¥¹…€æƒ–žžá_–¿BÆîÿô|d:ZšÛ¨>^\€6ö [ ÓÄÿ:Q8Yf–6@€¨¢’–´‚$€FRA ´:Ù”œm,Mr–&@;G -ÀÌÞ`óÀÄÞÎÔò¯Ö™>°„FGÐÄò# èfýåb€€¶–ŽŽïKG€¹ƒ‘ÓÇ œì–v&6Φø°›ÙÿMä`ÿaûáûS²wtr4q°9>ª*‰Iüƒ§“…‘Ó_µ-?Ü{³HS{ç¿ZúÛ÷óáu2²´s8Ýœþªe ˜Z:‚lŒÜ?j€,ÿ¦áìhigþ/  ¹‘ƒ© ÐÑñæû¯éü«OÀéÞ²qÿ;Ûþï¨ÿä`éä´1c‚geû¨iâôQÛÜÒžù¯­"mgf`eù‡ÝÔôOŸ ÐáïÑüµgh?H™ÚÛÙ¸LfðÌ öN%4ÿ;•™þïDþ?øÿDàÿyÿÿÄýwþË!þÿ=Ïÿ-álc£`d ü; ðÏ; øë’ùoÁF¶–6îÿSø¿G~þƒãÿ„"ídô1a;ó1X˜Xþa´t”°tš*Y:™XÌŒl>¦ô·]ÝÎè`ciüPóïAYYXþͧfaibm÷ר9ÿáÚ™þ;õþ&ά"".­ FÿßoÔ¿ã”>”wRs}PûNäíMÿsñŠˆˆ½À“‘•“ ÀÈÎÂúqà>ø|açüþ?Tüˆõ_ky#'K7€ÎGÛ™5ÿÏ¿Vzÿ#ngboú×^Qu2²3ýØ^ÿiøËmâìàð¡êß'þ£é®ÿÞè@ Ð~yÁÞ„7Ð*%=Õ©'{`LL§§‹r T\§Vç[iß铲õ¥Ìð¥*ˆ©~‚ç­Å}þôº'C·?Ô…mCÝ™<Ï%üNNÛ‡¶NÕö™~ߟY¿)õäk„çŸ9¹M(m.ýí1eý¢h¢‰6vØ?÷´¾ä.y¾˜w do“äÚh¬_¨õ`èÕùÇ'TñG÷wÔ}Ãý—Ÿº÷è³¢á(yp¼IœÜ nêLÞ>=¹pÆþ„S t#â£ßPQ Ü“û ™}¤åëa”õ•_´Ràè'A±O£G7ÅÄ.÷Ô>¼#µÇ«â;«@^çUãì®Ãd‘;)¡z ZnÉÉÀ‰bðÜ-¦±_4ð`)Œ—,Ái³e•O>&)n’~:a„%Ú+Üa|J –oÑÏ~¶S|GNRâÆ ã|Ó­Ïr£Ü“@Oà«xé¦}û ¹õþ“É1Ø·l\®[Ý >¨a¦Ì··†‚Vî¨hÉMþS˵á4Ëmà¦þËl«N²z½ÎïéfݵóÚT€KÞÛR<â VÔ£¯­çuǼ/zõ«Ùc%À ªb.Ÿ!ª7oÇObìC*yü¡‡a*I¢Öˆ#á\¶QÙbUyO“=Ø8Y#^‰Éªjiý"LŽ6üL™…Þ»–y¯d¹‘éãÍôk§‰¾Àv‰GY€$TœÌ#<¦ÍÐ}ÝXj2â9‹<àŽ‡mâGò¦C¢¹tKÄé•nE1­â/B¸øò2Øá˜®Á,*‚ŒÄrs´¾²@¿Â¥ çÄ9Àî´¢H¾ Do“¨žæ­àÏ}~Hi´n/2±‹ß `*ùŒ ¸Žýdx¿±à#öóꔸ,SìûL¾ï,ÅR” sX$:‚WòòR©^š»”#7Uɯ3‡é§ ·@Å| ßðŠw¸>¶ÓóÙÄ67ÊŒh-ìU}†tqãoJz¨¸Ôrÿ”Q¥x¼qn…ЫȌ™ÜzH jYƒƒÅ´$ãÉ!}4)¨ZÉnãî­ Mû#­NŸÕsè@|ßùxÕpÃôâ³!-²p•¶¹£BÒ†±¯ C ‡7™òÈE´׺Æù½×ùlÀ%«Ê"R„ËVšb`0“µ?urŽ—9®R2#ßr©Ó¹Ž¡–’FêéþvJQ?ÛW€÷å¦XDò¸—WV¶*}éÉPMƒ VÖI=%¯ü ¹ A*ÅFÖz£Ãþ¤éþCF-m@Ê;ßÁ£=…–škU’Sfœ9Fpný#ùz#Yø§Jƒ"HAø_Å:_¡£ )UÊ„-¢š‚ccº½‘Ÿ¸‚tûÖô‡#í¸TCöP憠KÀb‡›~~“â( ,HôD³˜Þ¾1Y£íX/ÔOÍÀ¦ø}Æ"P= )/ë¯*_ˆœWr}0ß–»Ãš<“i{Eb#`¢£ä™¦l¦rªJì!/4è4‚mIç·ú{?Ì…®·)këâË;N{—î MË~0.ØX<\˜ÝìsøjSŽ•I[ºØàC™,§žIjì<â¶\ždö›°Ôª(‹¹P sqþÒýʵ°INö|›âììÅõ¹OY«™†E“‘ЈX˜)ßѵ/ W´€¦ò&F&zè§Å•[«çØq 庇PO>,W•b ð öÒónexW±Û+ –‰ô÷|c¬ä`ç’Bc µES°ÔÏÝVÅeÉèìèŸQ>|n36¡—šJ¸s¼éºr½Ì¨Q-ƒq€}M21)jIW›8ÁhFB½Ày ã"­POÞ¶Û •Ë.<:ü5áÐmiÁ­àdÙ‚…øŽ[GÝo°Ì }Æq‚`SãÄÏ[åUàÙŽÖ;dŸ¾ÅÉÒÁœYQ‚vLÊ;Šèé~ â_ Ïä+º¹N:ù/vÔpŒ,#òãô›V;ª”Èlý@£%ÑÂV7/±º½{gÐ+Ú¾?Zü>Ãõ)1¢!ÜÃÙÞ­| 5Šyù‹ñ¼‡Ï´­yÅ^š gÑ]™‚«MðáRŠtáü]¼û¹TYS-–¹iÞ‰# ·á,–Eª:Š¥¦FÓe+!¬ÚÝ\›²<SáDø Q3ëϺl8¸H²í¥ó„{ô C?LRG†9EòYë}$–]xŒ)Ò‹!‰ä“7È|»a4VúÈ.š$¸µ0¿Ã^ét ¬éé…iŸ¼ÖA›óÀÓ¥!sûgå~:ÁIïö”ß|äO¶&ƒ¼Ø€øDdo¿HeRZ°ÒÝ,š ’ƒ¶âY¡ Dhñ^ý8œPáót’êd3Œp/e ¼ /ðs¶ñ‰ᮿðjêçФ>ãwÚV"‘öÕ¢ÄZƒ÷A3{ðö‹(52ü êÄNó›WOõPÐ1˜qêìKž•O2æ_~ÐO{µêµµ½ðòfh-òq\¦O'ÔF¹‹I7"to1æc~)‚*x@jWH²TÇ ºò2ŠÀN|—iˆ†;ÈQ"ÑäphÅK rX.û ¹wãi5B ÎÔg/*é x7n·.Ú±aN>×Ð3å¶ÜЙ·I•XK¾švC‹þ»÷.âq+ ygÊ7›O!Æ>”ubÈ”†E ü äÈ]¨íB}SÓœ°9½¶ì*‰gT]±ßµWÁÓBïjDv—Ñ:€ò£ot¶'óÛBq5ä(u ™·?<ŒÅ§& <µ¨ÓýRĬ˜Î0â ÎØßj\ll„˜\é÷œá¯oêGMšµC«lHZm®2=Å*TíiÐLXvƒß4”Å <­D0ök¿(a?3(:Öû (;‹”ýV™ÖŠÑ“¥iF‚B¸j{Ý(æºÈÙËPÒ2×e]ôPoÎhMvŠ|”„l?}Ò#‚å½Ó± RÈ>².ÒT§´}ûUzˆmájÈ?……¶®&ïý¶K(Õi$ÀQborº/•†dV Ñãß„~GÑÎÇ6œ©‚±‹)ê[YX:ÿÑå®PÇ|¢ˆÛ·/.´ŸëWܱ[Ïжø'ê;¾¾g4XRü²g¦Žp«·’ÚŽ!ËjðèÅÎCæL-5"ï‘1¬~ ž,1Á-þóhSk3ÂNžÁßÌuIrqvì-’Çg4€]¥~ÃøAçU‚voœ‰}µ:;]áGÓñó×*‰Á7J[ ¬Æ «Û$°>×Ñør}h”˜WÕ^”ÍâP†#(«–bÍ^}™ò!.mØûì¡­JÖ†ß-²€…‘‡ª—˜'w» ZWdðà “¡/%IåW~5ùsæ&X™’59€y%Wz憤Jwr劉)pC2Ê‘ƒ ß ÉÌ¢²ü83Ž2×vHäq*çØ g#á¼½ï+T:[ßÐóQ¤½¦‘ 0i÷Þ¥Ò‘Ö°=œuÞ7âï–² eødåÙÌoû½kär²[D4tám»±ÀK Á†e%"ÍìöµœŽ=¶…[(¢tÚoÅ¥*‘ðvñÄm¿\ÉüBJ¬XrŲ éÞ8Ë›D`·¦âß%gÏLÐØ‰Åÿ4-®¥&Êbï ï»â<³/Ô‡­àåçÛ땽¦«¢µ5 ÷­S(ʵJÕ`£9ò„åõ¬Ü€zhk£Å$X*='áüî±€2i—¾püP3Ýc›•óÎüÀ-O€wUWZ‰L°E†7Â~5ƒø¸óN’B’ÄjOäø+£»˜I”i«=ËdyH9«áî佇K76–xrÒÂÂZJRy–oðöÍ}Îj/šÛ›’¼7kåvÜB7Æt1Áÿr}û¤A0Ò1 yâ´ó;öçùă¹4«Æ +%òã¶WTú¹èKCÝ'ˆ«ØoØ0¥Ê†&YÁÜÚ‚:¹\™µÈCˆ¾Á»ü°õkû›ýÀÉÍ #¸ÏZ¿‰‹¢:ÕOá”x/«–⨠Ú#íšNV-yÞ)¬jüÝójt”òÞMøÚÎÇ–¹™ÄI±\0øÛVtû4zšï$]^çÔp[¿Ÿ/÷–—“x~c¹ÓÜ;r}XYŸ3¡» ,è}G×FHIõ\Ùûƒùx€,åŒ3t:âwF4iO‡+bø:ÿó¼<ËNÜ„‰tª+;Ý}QÚšz½²ïíÆê1ú†—ˆüŒz\/M¼*O&:µ 7¹Ìs£-d¦ú Ü ÞN…)LùÀGÍv¬ëJÖï’%‘èÿÔC`œ±‡áHUmGtjÆN½·3—0ßQGšÜ©ÒºŽ«÷ÔÚ׃Z2l6ö‡kNK©’èx>A_¼‚DšÌIÊp=²§ïšÚö`)¼§&ú~ir)ÒiÛå|ÿHQk»¤²Èw{^ôŒ=Ñ ¥ ŽxXP‚Fì‰cwè*½L½?U@q©vÓò”]刭‘¥!k`v#GïIA͈…,|™#OÀ8lE~>>Ú¶ªÛ ¼žH§ÔíÓZ±§‰#m¤¸œÍD3G(!ð‚œw:0 ŒâÏ÷`šÍÝd ÿ.QOÃ'dŠÑl-ko¢Êdý®Òªè.Yî¼Ç¤—Qï0ýø>íÓRTtåž9ìÈš!ɲ/Ê{ïâT¤°À½…b*eú–é€J”2†‹‚ÐFÙÞRkd‰–‰6ššé¹®ŸXv4DÉšÁÔãŸËBxDn¬uʇ  KþÁlø iª\¡·ºXÝK0Ž.è®ÇÓNBÞ‚ ¾ñ,*¬$÷y’Ü–"ó ¼˜Þò¼ÐE¯ ù)BÏ€ÖáH‚”WózتßïøÖ¼ ÁN¾¦à}ƒµsÃsá"EÃýEQôLü¨¨rËkçØSÍ=83U«°³nRï@{ž§§ðèEw ëhÙàÖp°éÖ¢Úl<†ãÒT•«òax4I}ÅÒ'–ðăWØêÙ}[µ-7y¢÷ß`®Žæ8S§kþQÐää*dBù!8™{3—±þ­|ü‚й)¬P¯Ÿîêªô͆ü»JëɤÌù˜œDV=eÙljÊÆpÔnePÜõl©05YqÅœ ý^Æ^`n^¦…½‰[_YTt(ôáߌ⓽|—÷DPh»NI\VlÔaÓ®—õ¿P¼ñFÞ ía@ì'×è2›"–ØÓâHNðyNGF1fU\™PÙ 9ÅÚÉjºqÖ§C”?q øPõå[$ô¡#Zw·ã›áy™;çâ45Ât”z=ú1¯üò‘båºÊ(â7™q5¤¿¼°0Æ"B »CÄŒh˜BÖ«mßð÷÷äÄ%òóbøhv¨š9Qrª—d(¬Nï÷¿6ŠK4B& Tl-Åâ»™šþ,Ίݡœªœ7‚i·P‰à×ÜZ0æŠ=y\ŽÓHEØóØ—‰b¾Ðk±÷Ô^«QÏ ?¡0x*NTQºˆŠÖjiêËQtËù’6Í­æ'Wç:ô$æß.سØ5Ü/’Avwc’ehÈÞ|OÖô÷ÄËžr«ããᙼZ$ÃŒqaM‡¼s­‡‡…á¿øìQI§âž?’¿7à~Fhè,ká]rûKPxÝè9x†¯-Ïœ×û„&îdR|wŒÍÑ_jg8í†o —¦t¾Xó(áùI,”å'æY¯ÑIx‚‘ÅëB„­trn¹ÍbŸn:R£¬Œ¼ö«Z¾N;„ÝiÅuc&Ãÿ[Ô¦) Qk9Âá‹#ê¶LÎe‰›;ë>ˆ aðë·»½zb’ßF¥2{®—‡Å3ÏT.<ä¸r!—×dÑ_q„Ë,5÷^STY ¸-§ÞCSó!#mŠ#Šß£Wüj&ŠÎn¡Ã·V_˜µø×œÞbÌÒt™¬¼E#´RfK({µ"mñ¸¨}qObLiýËJÄRSµZ↠ÚÏGëZ;Í¡üõÝ'²Â¤Í^Ëe[ccQ=0Ù¿ïåUWªQK!uoíÁx[¢h­…GWz ž±Â/à3¢1ÁV;Ëá/àì Ã|K&=Û Žüàn]8'R`êt{¢± ²uðÂàjBný¥c¤Ñ7–±ŽØ$ûW r_ŸãØ+Ý«í:ˆšý­m`c§{50í^8\jŠº4K1(µŽÇ»â“<;(w½š*nd}dÀ@ÆB&áëòÞ¶Ëäù’\u_I¯º° L”iÈø[aNûµZpºâí%ÓRçfLC4È Ô–ñõ›e““ÏÆ´L¶6ÆÒø×ì*OþþÅLHô¶Æâ:ØÂ~¹!QÁ»¥Z ¯]ããªå¨"gKi¿áUÇ$újÇøÎІ¯‡˜Œ„žŒPbÜÂw)tm( Þ¶R­¿ØÐ( ºÁ ~³à"ø¦h€\×쯒ýþ³0szƒa—,°ûõ×|bùc¿kÙÅ|;³Òêíu‹¼^\n»Òiä&°ÑeÀS?Õ°ª0ïϦH õxî6Xv÷×éBÝ[t¯™Ci‰üðQ¼È¯àòvÉ¿¡‹+Õ½Ú~ž`Â5äÚèJYë¬ă”mrü4ª2Øg/ÄÜœ¿~_?Ž®t†WéѤµABcièbf5Q‰ÖW&l"P–Ùd÷ˆQ G¬V~}Ñ ÿªlk-¬>¶LW¬A—yqóõ(šã¨°œŠª<»=q¾‡™*g¢|ÿæoÅIGt¯Aó6R ³§ƒ¨/¨2tL°YbK†x0j3ÃÄ;°›|´¬Š¦†Œ,~ÌvbšF+ õ q‰Øn¾\1¾¹¥‹ÅéøÿK'3Å3¡)ʨ$âŠÇhB‹6Ÿã½½lßZ®¶š·8ÕG‰éØÕƒ œúÇÛÒ­ ¦ˆª—$þLJ´ ‡fˆGBˆ–ÀÛd{½jcxûMŒÁ/íf)-š~\}".±Òå"M%øÐð28½cs‰ÔĆz®Ðk‹î‡îâSý%ùô‚0NÈ7iz$}ÛÄÀ%ë'ŒÌ9§úqÑop»nO<íUVÔŸo-°j²qŒ| W±ð¿¬uéèa @ˆêS´NHYèqyŸ¼05yƒ×… Q•|¯XPUÔrN¡£ì]Eaâ¤6†w}†›rKµï”¼@ú3Šs¿m4¼t ·ýÁz21[I$ÕÂ.4=‰ÒTN~“p^õT¿#k1ÌWöû €Êz^(•Ë¢TMF*¶b5©WÍÙk>4½’¨^°Ýô:n¯È÷À‡·õŠáàÐ[@d4yì‚|beá/¤4îsÐP£Ô‘ 5|¬˜Ú†–ãI.©¦Y¶‰"‹6 Ó–GøLù ÇÑ–9 VDþ¼°÷:ݱäú;\Ny\$½Ds^‘;6īвç›þ§‚Å©²ÀGJU¼XÚ‹$¥3P=+ÌhܹáËà¼Þeæ5s¡¢R<¶ÒÓaËÍ¢Å\ŠËÂÕ½ßY’'J6Y@!팽 ˆœùY,Hëa4h=®Xf!»jµò…ÃÿÇpïS8G±™ÚºÇBœ“Qgë•ð –.1Ô'½S2éU•K„Æ×Ù9r[gfõÖU³ï5à†§„âB¸f‹…ôÚ÷ œ|8"ö”=µ’ïsËÍô¯&ä\#¤›ÂV;nºjŒpF:XðÜíœÉ»ìpýßcÖ8ûJí¡Ž‚ì$zd¯¡Ü./‰f 8~K7™Ru °íe&Ó‡ÒöMAqŽU\rVÆ:ä¥]_êÈžò6Ó±Õ…¤î'¯K•#ÕgðE“c¿&,bä)ДÝJ ]õ$ªŸ-\W;‹p ¡‘¶Ð¾KÂ$Û»ôã.$ê¶S•„•OÂDÙ;MþÞãë1|ú¹LùÃxì÷ÔDcÕKÚ¹œP<ms…lúéXÕb&‡Ì c¾uóY%¡‘C òmn¶òÒ——>ë¼äÑh CçÅ›‹øJ0zûÉ]’¡ãqܾ;òŽ2šE·jJs=.wÆÏ·2 7á3™EKvØcO†øFä‘Õ¼¨X»Ñï&Ú‚_iŽ– ¾uƒ¾p¼ú[ñ;l‘YXJÛxùAf ðÄ0ÅÐÛ ¿n¦Râ’â0”zÁ½'£ ’Ïãp.Ì­kƒ§N!‹rÓß &x³n×<Ê›®lKÖç´í~y{eÅ:mX•Ö]?„F¾5ÎÝ_» „„×âC—ÏŒ÷- D;Žº¦]q±›¿¬HÐ$)z@€éÔ€öë¿=˜*üÜ*³ÀeÞ Ž~„Ôϯ©Ìÿ ±Wäš±SO`B ÜCâÅ&.Ìw ËÓ]<–ÚR¯Œ<¡b¾ôÍ_<:Žý޵™/®=؆÷ìõ5¨`»®[Ð^þ¡Ÿ;}°~½Öš»Îq¯ñš#i4};Þ*<ºNæ;²Ñ“OX$–%ʘÕûF…ãÆÌ­’—ÞBà¸ðPá6>¿‡ßúoÕM’VwBÅ4+‘zÞÐã: x0mÛ{¼«sxîÍNå8;oÊgížEXÞÀʼ·lGQhæòÅC^y@øœ|·&4&a¯öŒ°Ð~JÉõ‚ 3É6€¸u2Áf2ŠŽ´%Yª–?ËÚ;é ‘)>‡afËÖ‹4ï'¦Ä§¬ª×ÏâYì‡sâð·ÞûjÃç­ßþ¡ÎîgÓ.vhS­ˆ4+$ì‹ãŒå êÎ+{œÏšÑ§*˜“‘QlœŸû½ä㥂¨ï¯DýqZ•IÇÌ5‘êfýæÍAxÝÎYÖcq:)c±n—ƒK&Þ%fŸ÷YéJðM †hŠT¸/!Ã1¼BÙ}­ÄpZîÌ!7HÕÉ:ó$ç,åU×HB©D™§ûVAR fìQçýþ$-¶óä ËK"*˜P1?L¨Ùº„§ØV¬>=÷>mïš¿iyÒ¢.Nw](1Ó:õ¬B)ëÒÒ Ù&åÔAâ6É̆yÈ, kVîŽAꇛ-¤[ò‰—œaÏz)æþü#½ø[õX½%5{²Ç†éÂÊ2)dYÞŸGõ­EþZÎÇ7‰Ì蟀im9â8$Âùª¦ûŽløq6^üÛìÜ·Ì Ù¾Ð××ájjg¶ƒ´cJ y‚¥÷.;Ë÷»Þ[–AÛêi›Ö)Áí‘à¾àê•ÜH§Ü"Έ‹L&Î*)äaÜ¿Çâ[*ÑLDzTÕøÙBôî ¿o‘Õh=9HV kÆ y0¤¥šK%lN&8]Inš)3‚ËëzÏ$õŠ&â/4ïC°‹ ¿8ß’õ]wXênR«ã®ïÅåÓ£ v¹ÔÖ/¡–+iS¨ßâŽ!¯±Z1‡}‹]B6¶¨¶Ã|`E“¢F¡yœZe4掾~:Žéºk*ÑÄezyŒÅ ,Yìtv¸ ËÜI#š‡xÚd¶*?R žï/k‹´®ˆÃ@Á7™¤tdù)Lñ>X¼}Ŭ9îûSõ§’ïÀuYg¿.œ?Õ0Öè¥ÛÌ&~š#zÔì.OP}s4ÄÎmQô^¡éÌm …e«¿K§ˆ:ò²cŒË ‹äwqÝïW”4h¡¿O7¾>£à8½ÍZ¨e›ÙîAilO\C²T—ÛñT÷†ÐשFaµto¸6<ù«ÿx_Xû*kA²ôBNÁÃ]Åà ¦™¬ÇòbuXÎl|,23\âP©pv:‘ )ÿ¥m|LòI>B$K÷çö{V¥„AÇýùê™çüb@þ y&×,±&l³ë”åYíNÅ娏ßH>Ô%|a†Å{ìjòÚ†ú=x°!Øã§¬ 5t¦Ñ÷Z~ç ›p;´j<]„̰=à^w2Êû /LÝâ÷jPmÎ’GÞÕN E†h.’.³±)öX¬Sigô -cH’ý-–»Àla·¨mXY¯Í̼€œY’5$Údãñ+ÆÃ`L»ÞQiÚ9Ž'¤`ºan¸­ÝÞþt>€ªa+±k"¾¢~ç­™æÝVæI„“îSW°ÅKÄkp5­ç¯exࡊ‡½ò'Ø~e2äxn]Úž£&3G´. ÚÉÖéÌ"h+ã‡Æ¨“ ml,ä§«à-™þª¡š“;‹vž½HöŽ#êá5™…?v[ÓÚ{ª¤ëð´pô…ð4tô øü{VEE ]²htß&¦Šj»¿Çªèô×Üö—:rÞøä“eF˜P G…ç9ÏwÒ×1©GÚà[¬Iôyb²^¾næNáqžÿ¦1}Ê ".ˆ~k1ÃOëû°û·Ž³w3[gy†Owž‘G¯vÌoxe¡Ä9à4µý‹…NFÙÏO,zºpשÉñhz§} å™öÀBYM6™€«ÆÝTå#™¢ö”Cô‚Gû×rÙ-ÅTÕÑÒªžãñ¼™Ð&džËÝ[ÕΕ*]ywƒý™±™¼Å#¢!Æ>eqw˜Diýz¶ðyY»=ÆÆ²J?öÁöÂ^g¬Z)ô¼Ubåí‰Ê2½ËˆñûR8(ÿÈÃY”ôãê!Á_ÒH ö­lò§ÕÁ£\ýš"X¯;(?Ö ÖÄ7îê+~)õ:-ýàxžFur¸ FgÚ “õ/ÞjúWÁã-õÊžZ7Ê"ˆ0^n~÷³Þl™½§KG†!Í~)¨âÔxÔK¤‹—0æO¤í=-1Ññ€8ªà&>Jj;,ó‡sÒT'›µ3Xõ‡d•ý\qn*éÊLsqFmú“ŸS!Zu”½3­nüªçWçª`$ü†‘c+¥€bTktQHµêÉ™ÂìœÊãJ_˜g3âùÔ'DP†6[4f·ª}‡ù×–Z¼Ïík_ñÈ ÿè)Ñà Ù’á+«?Ê$ °‘ ?+¦ÞÞñ…ÎidÇLmûΤ?)/9Zî–Î!Ÿ Ÿ~mº:Ô•” •±=€=càsð\‚4¶;kt8ÅçâÛ,×YRÔƒsÞJX˧‡Ýàs® hõPB>‚J:é/ 6­âIbN~Ñ=£µP\þaÍU"ÿü½aË8™¢Wuˆ|ŽžPZ_“î©Ïu ˘zH¾Ø±£øT¦ms—I˜b•,÷‹Yº !N‘?ܧe™W¬.ìéš5iˆÇŸwç´ß‰Õ>ppdœô% ¥¾ÕŒ×Óoj7á‹tÍXTÑ”L9‘Aså/S?:ão;8û:`êNŽØo”“k~{a5èMЬ™E8Dµ¯>/Vš\¹Æ­\Íñ§þ¶èÚ¥›z;<;:æ À¬Oe¥4ìóó’ØÎ5~u Ï=ñ kyTsê±éͧϑÑ2f¶)Ÿ“óRº0hÙ$ÀŸIÓ—l}}&Oè'ÛWËá‹‚aœ9v«Œ=sQËd}·¾#Ѻ'çbìËŒóu£ñôxëmÎpP/b%„XíÆ4©äæžÉý¦S~PQÊcOÖD¨2¼¾7gP·›sþ¬áj? U~ ù²`°P• øÍN¼ (Œ<ßd3áÇ}¹/WÖfc$ÔceŠBr+g*ç†o,ô='Ö lƒ¬¤sk_zÞ æ OÒZô…@ÛuY®Ó]Aqÿªz͵¹¼­A3¯ˆáxŽŽ{4iAi—Í”¬¿ÏUBٻŶ‘³ØÓã¿´È=Æ:`žÑ¼ÃŽŽ¾BQ×ÖóZ|¸Ö– ÇÉøæÂ3‘Ëe.Ab¿ Ôž¼åºsxsžu&™ô¤Ưú´"WÐ8ȧr5â^ƒb˜®Ù"iIêÛ6Ÿ1mäN±."Òr ÎPí˜v}Âwfî]Bà…к°0™™ZÂhªþ¼I6ÌwpÑ›¦a’™ƒÑ2.Ö–!²$u „\xï!%‰[!uíiaþÝÜ›ž5žn‘ òdzËȃ˜?´ø:Ž£üy®ÿ±ÀŒm¤·.°Ù.®È(6Ìñrò”NM$d.^bïKÑþTŒ¾Š/*W6îNý>¸~'äWQ•=œjFšƒ¥HÖª02¥b÷rÅMâº÷*Ž ïNƒ5Üëbp¨Y)w.f¶¦ž fͶíßÒ–QåN|¼é†¯uö«¾Ô´`BŸ5ÏL µv÷tu4××³Ð¨ÇØi3޶g>7ã–‡¶;·3Ìç¼Äy¢ÏòrPó‹nByŸžÿøº[sdHž×YÞ+3„ûI‘AH¡yTS>;}ï¸*¢Ž<f}| ˜EúSö Brj<ÒËO&nJ.l'¥á‰°{“3Ñ%Íñ*|xšò׿a¯šÉudŸ“Ū\N7¹Þ£ïF–ÂÎÂõú¥ÎHK§(éíO‡ïÖµï¦a–/+™‘H˜0»ˆtŠ%‚±VÇ×åM‹÷p¸§ª@æeá­t»Þ(»n€Z‡q÷‚†ó¿r¶ï:6§ÑIÇEê/ç:îB0]Ù£vˆw4[s+ã,£d¢–ίäK4î¾Ü¼%ÓzŸ€õ=µA;u¯Pô¾¼ºÉ6¯ùLF8ÕùÖµi™,(yÑÏÌMlÿ6Ÿ/^‘U˜@Czy™º6§1ó 7Ü`ðÍ{©Dà—8rˆH¾$Ý»SØ3p™sŒ,ð“¸Gx«_ýsYi&–”+(_Üøƒ¦ªÊKynÏDº—W΃hP}ý9‰N|æÏ {"c×ÅÇçRóSp|z¯¡Ý°CgS9 ¸¨¢ˆi´´ þ #BG\V~²â|ìJ ¼”ÕžçY­~ù©zÚnypYù¦m/ ÚÎaÜ;Ca;ö›øgk7üf—Ñwíœéw6•¿ïejxÁMDäS.fãrqd¹ªJH÷ŽÎlU8ÌÔF/¤Ji{CA ñk§DÇW:u5…$„ÄóP=šj+Þ?½6­5ÉVoÆìÚtå"¡ÇˆmåºBºvŸìJj¬AÿÞ1»ýúÛgU±¼!ë'ÇåY݆*ºNetÝD‚ñ%­Êüuý6;6n£à]Úbá‡Ä² fF1 “ZýA-VR?‰c‘1ÛQ7i7z#C±þF“½@7ïKïژőXß]—Œg¥÷ËÂiK/ö÷P²‹?²õÐÝCï0£`„:ª ®´d'ÐzŠfƒðeµ•»wDÖP-…¸züèPi‡¢‹ºÒ…\ûâ»”¢iÊh‘›¾SK­ú ¶ªQÛÜMz«'†f„“dÝuýèåXv䀞°5½Zಔè—?€¥ÙÇ«a›îðÒãÄêY3TYH°þc‡f oj/¿rº›i†“#š´A¹êUä·|D2‚bAÂKå3¦ó‡g¨Ð"e Î>[˜ÅL‰ ¿‰Ñ3u¥Ò›­ ­+ÀÓÞ$-æ<¿w1G³”@†©ÙÐd'sr*Ä:vx#v17hŒûBQ·wÕ{¨¤aI1Ÿ—ÂBS`c¥T¥b#œ*)‰µiVÖ [Ó¦œ‚¦mÇ#«|’{ |nF÷Es‘qÉ«C(¶Ù?n7]Úä9Ÿ×ݧþš¡NPÓ$Þ¸«;áÄm’nä–ÖÂuÑÔ‰-GF²–‡³~«S+–uëõ&bo2ÈIÿ. ÞQg¼Þ`NÚó ŽRŽ€Úømh©n Í㜺ÈàÛb«.ZÈoM4|Ï=ž¯ðˆ^þ+°a\]´¨«TtÍÛôêb–Æô°Þõ˵£¶Êå:²Ý®¸þ¬ª.<2¢ÕUEˆÊúÒT-AÊ`Eì6¾Ž(Ñ}Ê 4A:åíЉÙ\{®h1cT)9üG‡ 4çÌîJ’ÍìÏuü·Dª6|2>TÙbŠÙzq9>ºÕš¯Ïå_­§MJzî]ìJ½·ˆž Æ—x¼ƒ%ê? äS/g7°­Xñüø¬ ›Y 7J &ØMŠÁÌ×éÞ†þ˜b÷Üј›> stream xÚ¬zePeÏ“%îîÎÃÝoÜÝ݇»;;4î»»Kã4îîî¶ýûÏÌÎÆì|Ú/âVfÖÉ“yªêÞŠx$Š* B¦öÆfâöv. ,ŒÌ<5e E##S ½,ƒ²½­௙Ž‚BÄÉÌÈho'jäbÆÐ03ˆš™XY,ÜÜÜp{O' …¥ €ú/ ýZþ {þ‡çïLg …€ò™½ƒ­™Ë_ˆÿç‰*ffK3€9ÐÆ ¢ ¨%%/ –WH˜Ù™9Ù]m€&Y ‰™³ ÀÜÞ `óo€‰½)ðŸÒœÿb 9ŒÎf&À¿Ó̳¥­¶ðôŒ2éøé‘jpldx¨ç²oŸ.'–‚×Û/ù”ä§‹§¡Ó}ƒÉ'ä«{ü³qS§Fy[º×eL=™Å–9øvÜJ­Hl'›2¦¼]ÑLõÜßžM25t' £ÎåÃãÌÚÉ8WÍ磖\ÕžnÁºsI²=‹©z]Ïi&H¢j$øNmÎÝÕ‰9¼.¬9[$uC˜xÄIªÍ ×MéQ"ÆÓ*^ðsod0FL©j£¸Gwè×Á8’¯gL«ÔOÂuã·@*õ[ŒiÖ€¸f¨ÓÏ$’þ¢0ˆßEdr')Iþ´ÚRÍ~3z©êÜ@’>,Þý¡è¨ÓóÝŠVØüÖ­¾›ÖËɇâ¢pNOZ0 ƒž Ê©ˆlÕÊNõ…ßmý¡eFÎ/¾á*¼©J[êÔЊqI´z|Ìò%Oñ r˜Ã{Lè‘4 j"à>¶è6þû€eö+WÜýræ2MA}'jÚL*jÿa¶M«Ñy5ƒ˜Kà#‚*iüûÍj“>‹ßødëƒcí¾a2RñØî‰ád[Ê=FÝn¯MT;ÂçƒÃ•CÆþL5™Ò‘“jŒ4¡¾šò­Ú•ÇY –À»·i›CA)M´‘7YÔ®ÍPOþXJrªÐ»ä®m{iŠl+û$ ‡Zøï=eJ j¦ †·ÏØíõp lݸö&¼²gYf©ü¢îÛ?FN‡lÅj ß‹ŸNÙF,È…JÖÙßw;€Oëê"&_áÌSu×ßÂX‘Š’'O¶„àΤqÉ”Ô GW/­Î¼÷ý˜ÍdwúÕl\¥éa÷€+æÃÛTk¿,sÇ8ó2áªÉ9v·;#yÌ#4º¾¯!q 2PÐ8ènO›}ZŒ_m¥né’æ½Å}q“dYDŒ J„ËÚ¾ö;3wAH‹Ùù$P’«ô…䶼Ύê‚ÛCýúúø¾ÖçZ­ýÁ×¥—o‹`¥‰˜t¸ë l)Ó›TìXk GƒÒ Ù¦2 x‘…(^|óíšÖâÿµÀk ñtû` ºW3Šlê_–ýäoo£o]™ Ú3nkš˜©!¢ZjtÛB¿Ðr4óí¬[&±‹MUÜ\‚gŸÕ«€ÒÔ3ª¼d˜:¼ÙÜÉÐc›Â›TÌtüˆ_ßû*aÌk-”ADOÃb7¸õïMíÒz¯B¶Šê»dÌŸ’I.«X©ƒ$€ «:ÍÚÑwL-qTÍTÍ·©i#)û°x…Nty6ЈlšFS¼Ìƒ=Þ vÆ`ÖüGCFnd'õE¸m‹ż‰ÂðNœÎrtÿ-!àqxfx›ùãU¹(oÃû.ªs˜ò’oqHLûqi¾§Il²/îjý[—Æ­êÖ c Qˈ8ÆFóHÀ’»Š>¥ª<ÖþëV9‰k¡¼^èv^fqþå%Å’g­ÄƒóhT`²zâtL\©Ì[ÔÞcô#z§íç÷ä»5ï&ZY¹íúdŒY’Ð=‚Xä¦sÑScibƒ]}úNDš½ ŽHЧõÖšúXŽ»Ïúƒî›‘Øø7 ¢ƒjGp0SMøÐ¢tü0+ÊË2l-pÆ3A`¼ËQÕòT½„W‹v`Èè<þ‰$U\V˜S{–—&¢¡ÍŸ¥øBÁ¾KJÓJ·5íÅ¿ròh^t‚âM¸“‚ßM¹:»á„óo„ÓzYAõ±¡ü( Räíí@ó§lHÛƒ‘¾¢æ.˜œT„ÅȈMRä±4_,ê‘nùŸÇÄi:!e—dtxÄ19M¥Ë•Í Š£cèzm ‹ÿœ£ùÞk··~fBYÖŽ³¸cCq­Ïîw¸óSf,Æ•ï>H2´I›‘.J$Ý2œrO¢ð`äÄÛT©ïý"çÈÚæmp1ò3.^¸Gð/‚N Î© AÄ&»Œ†> d9ÞwZK™Í¹Ì7L„Ð÷Ôl°6«žÙ¥¸ â×ÃùnLn©ãÜ*K;/°úRxr‡øÃ¯ÓaÜzY×¾£n€ÖJª\ßYä‘îõ™}ã ÒÌZ°€Ï·î¾ÚŸñ~9êþ¹0è5XÏ«‹o)Â(¶¤{ݰ¦¢íNIåú© º±[ƒ²kèp²Gðf¯%Çj;AÒÆ“祱Jÿ9;×IÞâ*ys@„ž¶ô|>T µ,>Á¼±´oî:¯v³â=:¯66ªè#o‘ñÉŽj¹SñbÚìéŸ1ðÓŒN-zÃ!Øâ{/BŒ@-ÊGp‹ñ ¦kU­\©SÑÀKŸ1—“üvÖqñ·ç0yGãr ïûr8/N ^Q:#Üy‚*‡ýÂɆN[BÑ·4#â`ÙSL*\QÌ8š.£ï•qÖ‹<"ÚÄòï AM0źöœb&»eèvÎûŠ˜|• šáü³Þ<¶}Ðï?mž×—¹a|ž&÷îyL2>6ÑÇe´Êi”eË 9ŒJ¡(°ôõÞ§T›'BzV»t ùjJÈfÝ%¤ßåµ§íàE&ÕÅ뙯aÓZ¼Ëø^@Gø0Ô‹{†Ší+îÖ})?°";1Ì÷ CéŽkR¨èÔÅPe»R¼÷jBJPȽóŽÞö˜¸oU¦Ê\l˜¢.ïq×äsþ”e?ÉWšÄ=Y6&) Ö~Œ ~±8´œ™>Q©~¥^˜ ŠkðÉ.eÌ/WÊÌßôGü«„kŸî°Ÿn\®yyðEËŒeswÙaD¨ÎÁäË/oênö´NM±VŒ…9:¨õ,*xRP­“²bì!‚=˜\k±hC¯50Y§ù S2ÜdÌ`avÀÏAŠXÑ×rÑNàÛ Â¬ç°Dq ›)AkQUä“Ê”§NB›eK¬ð+)b-*lj¸y Ù^^;x†÷µ½ða6í,Ô¦‘C†ëãÈ¿gŒ“ßr6 à¤gÚ¤² ‡ñ…ÞBŠý˜†±nêÆÁ<1àhò½ÌÌxq¢qžµ­&¸äº¨#£§7ã¬Âðh xô•¸³qÝK®:€@,† ¸ £C0Æ%–ªÕ—KpÚA7#v­´ âòôA#zÛÅÏ2|”¡d[™EénëÅ0®}N)ZÅÅKŠØ¨ ¢àžK”‘.¾Ý±2£ioGtÆ °—ÇÕ,J€w»ÜV>5Úÿ)åc©A+Ol´©?eÛ}×™wB¬ñ˜Ígç _“ÒØ ¢¶úIè¤ÅCFÚ˜¸oýc‘ú3“7‡ØÍA¹›méÝ@Srų•ZÖïÈŠq}›Ï!Í»JÍ¿ã±;gÊÛZ«ÄßKw#Ä"s}>8™rEXÁÛËG³ÉÐQ!×У Ž&è ¼‘˜ôµ^bÐú\4Mc]öéç>¡áh .cv”!aë@a±o1X¼AYj‡ ~ŒîåÀ»…c†¢,”«MÜbÏA™îòØöKÒàçIšFÏ“Œ]÷Ï%‚oG½t×{´¹féÖ ‰İó2–D Ü?ê¥û-: ¬‚ È ž$‰nîk‚u˜õ>ðl °oƒäxV_çÙLKÌD‘,7†p6ǰ *.Ñ#¾—ßN°…èS ^¹ÒÒnhpW¿w†–µÜGgà§ñ15gõV)Bw-–ˆEçõqù°ù‰™çŠ€uþÐÃZ˜éÓ±Ó#E×€¬íÇeðD¨Š“ ËqÀ/À‰TbžkI ßÇ„¤¨¹L=L]75{ºËr@žìŸ8öœ;P¾×»1>Çæ|¢–’[N›mešùELDÒNšRñJâ(B‹Wz¨]©<¿#äZi½Ó f&ôY÷zêñÍÓX#ìboìåÖ ù1O(ˆ”üH½2«!ú_¥âˆÇ»zñŒ,~‰,«Êpz}jV?æ*Æå¼›IqÇ!n¾ô†V$(ö»Ô.x§/–LĨúªåˆ LDÝ÷¬®ª,N)ãü’™âï%*=TìhÔZq»S–ø×O k'^Š÷ѵÀ=,$ú¼»i{´J ›¡±znÖ`Ì+ö·ÕgO˜›pO’¢WÈk‰öÀø×i/Õ0M9kõäR#ô›ß#³8EDŽ=ɬcî¹g°±Xß®QMy–ðÄBRɵØ^.[=Ý;¶èÇ-Zuêì8é+·!ìZ*9.¼â €ÅaZ\.áØ%9~â8×ZØöÐÇIæ1Ûªõ·—¿ÀXbRFÏl$ó˜ qäø¹ oP^ÏóÃz`\••u•µ…äÙ <¤{öÔÏ2ÑóHHŒÆ¶º›.Š_r°%§k‡XÀŸt\§9S¤ž”Œ‰UQ°ùêmûxž»ÄˆÒ÷©èÈ Õäéó eÔ|p@¬-?ÅͱTSɆäàÚí¾ôñ¶C—êŒá‚U"¼Èó7÷&š×ŽõIk6£ëÌÎòœ CùO LW=¥Ø'D%‡jp£"äÊ_³)IŠÍ¸'ML4ƒEåQݞĉ¢&ç›ÛÕùçÔpþǬu¤š°êƒcCi ªv…§Z‘‹w{t[©ˆ_÷ÕZš––žï­éS‰—Š0¹ÌwƒU¦hpñ¦ Ûufºq©¾¹%ÏØ=JÀn)|ðåö)ÐÀBd$’Z–iùüÈ6ÇÒÆŸMäo({MÂó@/~j%oÅm¹t%¡çpÒj&ã \½;#ü7‡ü Š@æ õQPßK×ÅRzuë‰c ¿¹Îë½¹+Ö?5±îkÍÒ8×Èg%Rˆ{~ëø:%:RD)ÿÍ¢†j­±âDÈ„>õãE=ýÖ—×ɱØIoüZ;rÔæEøQWæÇ`|I›¥eUÂ1Üœ™ÑÝY\’´ßíDö.¶$·ÐböŽÍeVâáA~'Aý3n9½‚ùµ ‰ûþù®A®4£‚rã­Á-Ã=øÙêxÜùg^SÛû](~ŠízkÀ‰½¿¾$µ8Ï;³‡ÙkÌÑîBöð Ó°µõ#×LÉ|¼Ði¤êpß}³¾M¤'˜#«w…UVY2êO<Ü£*ºîûÔf%Q‹>ºXú'MµOÄ¥j¡T…›ÞÿÌuêäM€[N>ÏE,‚(Áƒ:-™ôÝ&3˜õ.°°ÆV äFâŸU«/X‰Ä÷¬&‡ZßÛ$Q†¬·_ªø¦!ãf¨ýe¹ËÑ…QaµàTHWn 0²â=½‚Ó¬™YãM$¹jÞågèü’Wã}#I³¡SzÆ:|.òC$ûc·Õ÷–ŽôúáB@¿ ælhZªX_4{]4Äî#ýXMú–zå\ˆ…ÜK§F%Œu&@f«q°]ô¦”ñ¾æ‰ç@óD·®Œ@°Œ<!Ô£îvºÿþÃå*’MiC/,9Ly(6æÝ¦~æÛŒæh_­ãûáÖŒ¦SB)Hœr—IôQ5Ýœ„<Æ‚Z›cÌTN(ìõ¼`Súö‰ ¥7Kㇵ›‘k‹Ýõ†Á´ø|˜‡sÅØ†žAœcûψ°~§‚Íž?Z¶Æk`â^ϲhAöÞw6+ʾøù>ÆëB<@v„Ú4kîv„9~¿óQˆû‚^8XxçÇÔ”Lê.-HTÒÓÌL"d‘oº®Ø /r`ÇϦD&ôM?Ñ©éÇêd Ô‚/IA¸/8²×<¼)ù£+ÝÏ]­m“{²òsL§Wö¾uQ ËUeà ÅËdgâ4~Ï Çª¼³ wF|wæÄŒªâ(ÕaáÍøºeÊ9ç;¼©Q§€ûiaUÍ?>Ræ@ç5_ˆ(½™z6^Â,PsƒvÎÀ†¯ëy]Ã>¨¡u²D¤Éô šu%ïlê¶Êü"䟼£°6ýÙçÎbݔŕ{hÏ¡ñÍófáw8•?h'IË¥€<ø ŽÌסµRÙ–Á(2SØDË$1[®Ô—sŠ¥Š8Ñ)ùãÆBŽGK¼ßˆ¦„xœˆ°<‡û0‚†ômÇÑÅùÎB$6­ë6x}cÏÉXŸAüéñ/æeÂÀö­JúYW…QY¨Npœa-w2ÂÐÑîV¥6›¥žð—J6(ìá)[㚪,‰]=¬î$N|’g,A‘‰!òe;ƒ^8^ìßvl‹Ÿ2‘éXÐð¹׋Òìkåí?íimÅ–SÓȆÝhO„⊧í˜O_`ãß!î—J•èÆPEÈqÛ(Œ3©JY¤{_¾•DˆøaŠ•ƒÅ!Û…Øì¤y۳שôgB×sŠI¾?±0ÁWߍ™¹ˆ =5úõŸLPÐNÛ&K7³É¸7*·,+ ^"un]¬ŠŒëJÍŽ6ƒÜôž1÷a¢FpñDz·ñ­)ìêP4` Ÿ‹·~Kí ª”)–Rµv®õUFjU H loKò„1;nyx§“¡J/Ý9“•àê:]ªã _d”XÄûº ¢^‡¤›•ˆ¯ˆB¦û¾@Ûhá<‰ ^éû¡Þ…¾LHË`sj®µyYà‰¯Â\°j“'a€_¹ÖÌÑ8öë^ˈÂÓu&Eç ⪒Q;("“”ÚÊF™‚4LK¿1óª] A7?nagךëd,Ý•7¼‰˜¿”0ßÌ’ κ?ü9bÛÊ¦Š¬@S4³~ƒµ‚áIì•ä‹9€Ï°µ£þzì&,®† ºà½sDB5L¤b|nÙÚÄ—¥~gòÿéŸÕ›é G—$¼qbP¼ žó6™>=í:ê&±‚ÒZÕj* çAòü¬í­»(‚²ø“ÄXw”ȇži0Ê~àf™×ÁnSÅ^ägJûcÍ\…ò厃y–^ûf ¯ìâ3ÃÔF x–+§²áæð°Ð¶à·3S]rY”""‡> % ¨æÐ/-SéÍc’ð3²ëûÖÝãÏOúE´^Ú‰ÓáXo­ý|~[N(ÿïbú$] ÙžFNõ‹i7ÑlPE¢a¸HWθ²~Us-êb—î‘MîCmOI{°§´O³çÉí¶k…Ik¯Ñß“¶¸Æš·îNß1æìUT)Bêz× [îXv„#vsÉÑ7Úû1#çâ eè³iŒŒðø £å\YVl܇ìÅÇ¢f•NF‡]…Y+yÂûƒšÒ4ÄtËcFªÍ :@²fnªSI†'œsd`TØE¿>#³,-‰0JJ|š¦íÿ¨µ‘ã“#OÔv¸Hén‘€¸ 2Îì´R6¾Ÿ<)™TF¾Ô¡¤GÒèÿ]ÏÔ®o‡Áwê鹕ƒ­ºÉÄSŽÜþ²œîÀÉ­}xî+lçîñ=›;Ýx»–@ï%C4& ÂéÅ`qj‡Š»ø1{»d—§ÿéÜpfŸo†œ_õœ6ùÕˤˆ~Û/<°¡9z®'j¸Hzkˆƒ·ôz+S„Ø¡yPŒ'L²ŒÌtÑM¨š5Ak@Ó{+MgI%”¨rqŠ#`à™{Œ†!úÕÙžLûÙeÔrî·“+­<^,Vr÷ȵy¶—£üB±yJ±õõo„¹ÈâN*–vÁrŒÆÌ€CU!)ͧáâš5”4†þ8O’gaz¾¤ÂEçSµ'óXRTFDAßÛ0õÛ!äé¬Û†©ª6¡h¶¯Ü•%2<+mY–Fükã+vï{Æ»U—dÅ Aº…YãþÜ%%=¡C²Ý» Ãû_tS½§É›}u¬ô,h#q²)ØÊ@! ,{¨¤:°†ß+¡qÞìÚˆÞt}_FK¤o½Ns*ïÀÌ®ÁÛ941Ò'H {fÔÔÝ.óVþwT“" .0™ Èñà°¸QbÃ~˜Õ¤á…sUA³¸i<|^ÿ€Bnú™@ÀÊ-û•ÁËmÒÎw*vÓ4YB- š£ÂûËì52¨šîRmñ0ø©ÀhVEÃÅ,w ’L­ÀQKçŠ*3/ŠÇ £ãNÊ…xpå`x>˜X W®ÂóÕœ R©~Ãp€¡Ä£ "õ|)*)#Êî¯xÈKëbF“¢”ój<»ç$že™Ã}rOLE¶µ_x¶Nè¥}Î’²¿b}±Ö|Î:ß?µ1†ö]ÁÙteT#  𙽑Óg»²¢¶Å'7Œu‰›^ñŽ¯È¿hOô˜HX°·1U¯Ì‡$f+rÑ`ؘQÒçÐû±ûbAÅçî»·ú`<» ©ØšmwdÓ['Xü¹©gríõ±ļGT×vg›Ë.2U-Zã[-ÂÜYÃ]ýà¤ý Ô)M¤%¬«é/®O·«•@,,­Ê1Y*î}2äghEò_Žˆ?P¡$ù?Ñ;[s"ÞFOaLyœVóšC;„e)§‹âÄ‚Zéi`d²L”Ò}ƒÂdåhŸ¨‚®H¡æ8ü-ÒpÖ|}¬2‹‘B "9€’ 嘌 ™Î÷~õ‹fÓ;Úúì+—“E³¨sº•’¬ß¹égýsd²äîd@9v«@².H7Cÿ²=ÒL¡<‹óÊmJÃŽ}´@¨æ¾ÖP”RÝÑÌ#âÛB]Ë6ÑcdSMæOûC¯7A™Hu””:r¤uœ¼Ó¢þØr'ÜÒö s„‹¢ýìØ7àµÉœ(ø{ ÿ°Øwl9%é,1owW lçpÊ=³SƵ}À™ v§Í€fË8½[ÂmXµb‰¢+‘!s5>µÍ¨ý"˜ý0Úñy.µ5ÔÆK¼“d¦ n“?øB*P R PÂUŽúC:p¸L|Cbª=ºá•åwäiD]Á šy¢eyc·4P{_»tW“¢¬Çy§@¬øƒ¡8áIx tµd.+9•wß Îê7¬û¥¯/|?mp›a3ùC(ªL/ï^ÌÏ5<ÕÊÎ/† l¦N9ÎAÉFÎ|Ñ1âÁ¬-ÇîÞÒÐëÇT"“Èä3V$ê;2ã ñ‘…CrvvWã]M%ÜÄ=,)e5!1{n9>Šþé.ðö ½we¼‘¤.êwŠ©ÉÜ.šQÏn-‘;ã3ŽzuS­ø19Vò# Sž^àìîÂã Êe°…ï3VŒ7®œÆåTßGcßIiÓEQ¨†Ÿ*cc ¿ ‘Ô/¨ ¶pº ‰>]K-.0«Þ¼ hµ°¬+,z9ôQ ðÓ+†\b°C°/ƒizþKš}à—LÌ [¡P4JRÎÏGšRU—NVåÉàH|ÌlE$ðˆ‹ç€YÓ,¡4©o÷xª" ªø³ª÷ͦVI ý免¸l;¨â÷+G”uÌw¼ûºãþÒá#Êæ!Ò?KN€‰šDHï~.µáãoXbgR h™u*¸YlÐ:4Úk%Örºhš f÷›„¦×©Q£½œ;j䯉)3&›o0¹½Z!& ,3¢ßjTSg;Z&ö3Ìþ^Ù}sÄÒÕ“EsJ°Ø ªïæ±……Z¾:†zûR©sê bèägñÔZõÆ[x—íT fdÔ:øp¬OÑr%¡~}QÚ!’Q Ÿ|÷–0_ØíͳûêŠTiÄËðòuåÃ8(ùI tÞþ‰±ŒÞŒ§=K—úE°¡péÝ^ü-fÃQ¬nXsæ‹T ¸¯~«|[çkî`º´–]ÝÏÖrŸ›dã’Ðóhl~OH®š£n_dW¬î1×*{œŽIûÿ’nò·Wp]=eôôî"·æ8êª,½qEÓŠ\¬ ¹Ñæ÷:(®Ñª°H§Ë]`ŽkÒºýã4Kó1NOÌï{ αȰ1~Ë8Ý\Ìcôcî5Ä„Œâæ-m²Y9‡X¬ˆjÚêIëÃ¥Îs¤]‘Ð1Ì}Qœ¢¶§wùpÊ%çR¥ÆöƒÛe^bwfË‚¾Éc0±È§ÏÙŽªGò-89÷S‚ä@‰”ƒèž¸ö”áä2Zz†ý«uU–(J˜ÎFàä’m{ƒ—T il¯ºHß ¥uf*@‹‹ 6J×wú.kÔÕj6͇㒠5Qðý²kEQa\É#€=Œ1ñ}º¥NÙ†ˆÖZ!GtÔˆ=6Ô¡ ô†ñ›Œê@{&Þír5ßÕ ©‡Ã€I7QÁ£AÏгÿ,ñ ÃPÒþégÜ.ÝØ66/‡þ袪iÖðM=+ÅÇkº Ë,9õ†’“óÞ¼üÇ®z‘ÿp$4Zú Ò‰òÇvPÁ§×¹)çÜøwÉGmkà­¶žK]#œÝœ Xøsû­Qy³š™G”³ƒ²‹é†ñ¹8³%H‹úÍœeB ¹6¬At «(ó›Õí:*\ãú 5ÜæçõÏ(4XÀÒsúzM’ÕÞݽ7id|{„›ÒÆÙn"Dˆk¹Û3š^ùE×aÛg¾LíæM Q››¤§Ô/˜ WêEA"@>Öf›(ôå'+ÔŽMÉŠZâÂÛÒýxmÅÒ΄O#‡bœÕþ/{OzçÇéæ`¢ô+šóýóê4î¨wÃ$½'Ÿ±› ? o$þ‡*ªM2НYOgvT•^Žñ } ¤•P-t LÂsñ&OôójôýB¥Ù'ÅÊo«šrŒ@ΉçÖ}&HŒAA Õ 2Ó$ÜuΑ‹ èp«°£ëŠÛaOµ‹fÑ@"“™h÷ p†ÁV9{]Œ5…!Ä.Á›<)–L¼€X–û°Ã¤ô*õ†«íkéð )‚Ôè!zØŠ ÙuŠóXÈõs?‘ÀµÏjàÈqãC5´\¡ÉÔ·9H‹uJJÂêÂår|í³`)‘HëOÆU»ŠcoB/¡Ê}ÛåóïDwú—=¥îRøÞ Hï)\üÖÙ‚úã'ŸqdXø.î´¤äï¼ÓÎzŒ}x÷ 3DêMn,%ü¯3SKòM¿ (]¨Jiuq|ÔÄnµÈÖà@D‚þ¹Ñ•™r°@<ApãÓl±ÃOà#ÊÝÁ¦GO° ¹ˆ®ŒN¯v;JrGÝîLðøRñGý9Í’Ýc~8s+Y½Éánr¿Û<þpuE\+½ÆiõѧÂF½1|e®Ú. ìù¼·±1¥tâÒÛϵdÊx›±'³f7¨-('c©þ:¦ ûeb@Þfœœý÷Þ ŠŽÞžR@|Y®æ+¥=«]ÐäÔqaÀž3Ô)H.ÜQÈKi²h*NPlE.ÅÚ¹ìGó«Pµ¢»MFþ÷÷Ç;¹¦óƒ`xŽEñpp»hô޼8»C8hHeH§©N!]ÔšõæÈSœvæ–ƒÜÕdUÎØëûD³ÚŸÍ1/׿a¨‘¯úxmßæBвt¥Œnâ†7ôÑ4~ms® YWwF{"ÌÃg}}Á€]%õE‚|л\½‚h¿ =rù±‘Äè¤T„} €B]¬=¿¶çF˜ÎkþrÛLôçÒõ¶¯­¬ŠŽñ‘Ôo;õEù?’Mmx‰Â²ïqHT>Å9¡Ùê7!*I37+ïYª(Ó£S"ŽÄ%ŠšÇ ÐS!ÌÔH*…<4p²HU8—êªÐëeÉ­¸( ›ÑŽ¿NÓ­h[}U‚t‘¾öHPQØÿΨ›Nåþð®P·!Ž%E‚;ý‰¡x8ŠTOÙˆXªm¤ì*³$jQ,—3 -ºÆboñ?xú©7g Š…B+$ä†q²:®öV•˸…ß$–n°ÿU&ò*Sc_úXM®~™t¤ÆÇ‰ÄÏó5a&iˆ_·±£%1«¦ýí ›€þ¸w$Pø"=Ö¨ßPÄ8¾Ý^»âî’»Mþg ¦ÖÚì›#¿¹xG~ ÔSOІz„­:ÒÆr9()\ê^׿¿BŸU}Pc·³?ùxyáOQº¥NlëŸaÝ.ÂVÄZ ¸%C¹ÉïØ \„-õê²:xj_€›˜_¹!iU n[­nú¥²µåpÆyúH–*eÉœw!£Ye…A©Œ0öAþ/œÂg "_ˆæƒ|lææ¶pÛˆèæ&Ò“aXÆYD{!ón5šUóÆr…»°»¿‘]Œ¨™“¬½º§fVpÈ»˜^ÅÛ®@Å\1/E¬Ñ ö”‚0fM ô÷ì p é¹ný0­vgã]”È.5). o¡/lz7£Ç›!Ž2{‚ ¢bÝÉç*VbØór’÷’Ùé}Çð S¼¤G/uóRÐóìKBòñ=È!ZIúæÄïÆ´Ý~cŸò{&Ä-~î€F<èáO‰l?^ËAw…°±÷à±%¥&6¹¡f̘ÞÅ)â XÂ⬾Št ë½*›Ðè—áÑŸ¿hKÕç0IWæy€Ê6Ö=·uk>P8†ù3i¥óE ˆPw¯Rw^ñâžLPwšhÃvÛsÃd4ùỶð´ %¨ý 2]Ö¯‘èOãßsi6ªŠÐ/Ù#ƾ‚žƒÔ/yÀÊ'~G×MÆ·&ñªVÊÂ~ËÖL£Ç“ïJ®šxrr’©Å:VRz¯ÂÇ“«ÇÛyWvGWU’Rü\1Xï9›R¾Dé\™£?©~á<õ1è’ áïW0ÀÄ¡ð‚ R)tWÓµ™[1¤‡A.Y[GZDG(ЗKBE„gù¦µÅõsA˜J3”w'Wt¬T"òPznŸpD–Üƨ0˜qD½^VaõP«¼¥|ŽÆÃ£Ênáð1ûƒ9—‡*FŸt2¤0¶ë™ÓúÁ£ÉZ†„¥ÎðHxzîšÏÆÀÈí.óY,ÔÔƒ+4Ô»¦±áÿüøÙw¯dÛN¼Æ4†Ÿ•1÷ï÷«/&ÃExV˜_Û7ÉB穾oú“çGR‰:Êå`; ­¾ÍH}šfÐbw·\I“ºþK2úò÷i‘…H•Ñ3¾(¸:>%v_ªñƒzŒLwÊ‘{»|¬ßœnMªœ½¼êþ°%­IóTseíTöªéÊþ»þA¯0ÒΦø•¥ô¦$ž@z€ÞŠ4°75èȬXQ­GzP{XÊû¿úØ•)ˆn;x~ÒÑ«\b´’ÕLC#Q¼%B˜Wåætƒþfbc‚š <‰,† Ž7Ã<ò›#Üò) ±2Š·n!eØg2»ÿIù¼\`3ØB· ûÒÂ3ü¹2×ÿ÷öêhû¡7Ë«å9g£öv¸¼>ïèXaŽ[$ÚaÆÛ/»X`ñ¾tÆÖHL ¢ˆt°rÝø"¨«Àº~g+WÆOß×°‹I› æWŠ ÓE+åcDL<åq3fžF*m|2ql&‚š§g}ƒ Ù@Ÿñ Ölò©_åô<“‚جêñ5ˆpaig°ò¨•{Ø•úé¸ç.EŒ{¿)´%zx‡Ø¡:ĺÿ×ï?gø:7ÏÇÓ!ìÕ ®'ú}?!ÐkØ\Ùá”ìÆ‹Ø•bž?7v¿.•ÐIÁ‰ °‘3£:†¬âV>ÇIú4ÞÕtäRùÉ!àêÞ–í¶^ì<îdæÍTœ4vÈ@þ»?5L«yŠi¤Éw¨‹Íº*j¿á ME±€r¥:Ÿ˜G²xåÖÀ2ùðÉ4?ü\í¼œ¡€’­~Ú(}¥i¶d´†ÎîG[¹ÚÄáÒcÅjD%×CÏ£ï\0œÞ!^ï~ ÂX›ãÙôÜd`oX0×4YÎM’¦¡à‚ò ¨yïéZWóäóýN ÒvkKóŠóºo ¸ð_÷SÙ¡Tgc§76þö ;ÉûnÇ4)ü>óêÜÝÒ…\¾`b+ooÎFýluµW¼+æ”ÕÎWÙ~A`£/2Ã3uw8í›ö@Å šbnµš§™”K(ŠìÒñö(©Ä¬ú]©„­IõA—AÓ‹º˜Õ°ùÌgaÛé6‘ò+ˆ[m zÀ1Õc¿p° u߃.ž“àªY¥ ‡g^„Al#9çW>Aí÷^†´ÆÂ_¹cQ?šYu6{€#c4q Ôê”BÈ Ø·.¯xîþ^i¡|øõ=j…úP(r¶IS޽Ä4#­þEÑ}skX4÷ɰ—-lÿÒW=ÝÉ3|¡$—þûçˆÇ3p<&2óž­GÚÜï­Át:ëBø¨  c€T¡ä×=E܂֫U-&_Ê5Üô:-«kÑiÇð>µpÙM[‚àJº³YZ¹EÖÞšWcßPe5¤æzx”ïHJdî…JR~²aŠ}#‡÷`è„›ÿÝœâsÆàÏ,Æ`@Ÿ!ZÊtM‰ò³ÍçÂW™±‘éê:yU’V>ñ„„XVóP‚¸WÐea%ñeMÆô}·dDHü—Ë[e#ü´ëÝþ Ž5…ƒG‘4³:§Ð T_·+?]З+ ÍW#B.iÂk Êg´ìoÒ²±hÔ¤]Dð†Y•uÜ`µã[8êDqŽõŠ|vOŽ Û2H޲Œ²üXi#ëé½,a¦Ñ‰ÊÝ÷N¾^p)ò ª]-ßùuCm¬;ué¯ÑB¿ß¨¿ä®|—®yù¹æ·ZðA­¢š07Bnúãµ|‘’ê:ÈS»2ÍŒa[M¯Ú‚‘ ë×?o¿“iM.uÁo­mñ“±ùNèà>ÌÁNÄ´—°y)Œ@+SÚ'hÙh.”è%Q¯8y¢Y-íë+&ö&¢ 7cò5l³ñö—ä&#KÂ`û}bƒû†UûL¦:ò=î8syÆP!f€&V¨S7“Qž.i')$Q5´h¡ò[/`¤ñÐýÅŽ÷³“åßOt5Û.ÕaX%ÿÞ àoRC Ðó¥Þâ¯üÏјÎ7%œ*å-¯E Oy€­Ê²eöµ¶>Êrô8GFp8ÞHFû rWT“h“×4Sî1?¿%J& rÙbRðELj©ÇÏÕ5#ÈJQbWñrR Í97ØŽÁ‡£?Åë$l,ÜwÔG'Ô4@P—Š*‚ÓÄA™AïßøsT¼vzÏníþ…Ò̾…žÛ‘gßÂõwŠŒü¾P1ô„Ï=ƒª“@¸bC>!¬¯û ¡±ÚFúÌ™]Ãò¡ºà•‚H´ŒŒ ï'÷N¼9A¬êñ”ÝÈ1X¬†Ÿlò/Íá¹pŸ^ ê? bA£ëHEG 1\x $?¼È#ê¯Q–¦ˆûÀ„~ü°½Ï*^$ ÙÎÜü¬xp©*üŽàªî¶!á˜]³&Çm¶^/“‰7úIJy¦è.Fͨ_,n„—ø`æ6”d³Dséö´\­Ïƒ¦áò~N7°žŠP1ÜAP©{o í’Gõu„6Ë":!õé 2ÚElìˆ"\J7wÿht|ªKÃÌÙéw; nCEžý€„2¤ÚiasÍ:ûBËÒÓò7:D§,EžÔÌÑiÇ8»‰îÀ–¥š³B¿Ï}ý áÿ)7ý5>˜â©AíÏ6°Ó‹ðš8›±$Ĭ„ã½Òø(,D;‡ž{Øý¾ëìôˆ™úh×Ùîtf T‡kwšp§‹ô J\² 8*ã‰ðFÂ#ßüS?δþçnco@ 5Ö{ùtŽGØ% úw%¯NC(~UõCŠÑ€{¨KÍF _9ÆÔNÎ$Þ‚j’ï ¡2'AÍ€d?[îÝÆÐ©Ø€?²#u ‘rö‘¾‚b@`¿Í,’väTÎÓÒrl䬾…þǤ; RØ»‡(ÛvÞ\ˆVÍÊ¡³ôkÌé6Xƒª¤òCíÂ8ÓjìÇØ1QÉ®$lý¸|•øBNZæÂI öª@­©„¡çñ€ÿO=ä¬Ð™xZ¬« û]]b®xòõÒÝÿ<œÔ sÊýbüÍ*/™“»S{Ð: ô˜'Oªx–ˆWü°½U0S˜·T G¦¹J,âš© *zÂXðå *TšÂ¤Þ‡|iÚ¯yŠÖôÂêµ-\ÝÅZo4+÷÷qbZ¡þtkÝEo­Ò¾. ñ»•dhäÉú(±í]β ۔6ÃfUgha[W5ͯ¢{æØ=e4£Üú.¯ÓÏPvÑö[”Ž£„< ÛÒO|`Îð²Vsƒ"¯¼%ó›nÅ'Ïœ²7·l#;•ªl>8}3òßýÙÔ£®H¼D¢ qãJÍò\õm/ô˜OŽYez'F¬ÌEjG×CÔW™Oé ÊÖ4"C\ØCT(Èøz‚ >Ôâs”¶±6”¾Õ„®€km6+Ñ&±-•'›§­MÕ#ÚøBœ ) Ž‹# j,P ®¾ôGp?ªb&)ÆTIÀ˜JçX}¼¨J ´µi¬¶À} ]EË:= 8X2 Ý­W$É=4%#ñ},& ÒyFt©=þ²po••mÕ ÿ&í…ÍÞ”Z‹þ¸5õ¾1-‡ƒÒWáZ·Ø¤"ƒc¦éj/7w†ó~Þ¯ÊËæyØWDzi’¨€¤ë;_Œ©Bq-É?Yã9HyÏ“j`¸1U¼‡TŸ3^c=Ðû /xX`XÐTcó©Œ2? öY³«²Ðæ^2^ÄrêpÂÀµ®4qðƒÖ>8…¼’:¡–Æš¬FÔ~qHõEÏ‘µóYy ¦g¶ãl‰À—¿U‚íC¾àõ!QZÂÐAâÝkk¨( 8'Lh)'tÜ|–Šõ¼âµhBë–;ñ`ƒ^*å¬~ñ¡aøÀHédðŠ‚Úsˆ-ƒ¯‘ZzígE‚LHýñÛEDAì–†úuŽQánõ×DÀÅVN×k!Ĥʃ˜ä9¦f<õ‹lóîÎG_ÇdEÉM}äg"wG^Ð"±‹:¬Ínˆ6eþ>á%S‰¾Î·e9xÍQSþ†GÉqð‚2s ºhƒ~a»xU‰#K„‘["¨ÖqXÍ[ÐÁQíøÎÔŠÓiWch°8ÁÌ*†ÃQÊ¥ñq6Э ½Ì5:kñ”Eõ‘{¢(Uˆv£œoß¾ÝÂø¨S;ç¬É±É~J¯!YãภB mhu2±TÌÈ1°4’<È̪‚›íÓK£Þ•äðPá4¹iÄ=YorY~s–ƒñƒZæ.Àpê§ü.EÏ×·ÂÍ7Þü7ˆ'3ÏeP~CaãÊ0!jCƒ_•ƒ=÷bÒõÑ'>Y5•bR¾ƒeD^nœñ{޽¿Ï9^²µBpcifIÔt:£\7KÒ©ŠÔèÞLÞfÆX H êãçýÁÑÆrYš½Û»ŠôåRuÉ1œXV†¦—dõt/ZG0å|®à^]¬–³L*‡BŸævËdÒC£ H{›OyòvÛí×q³fS‚‘„Ríg‹õÒGdž·H–úJiõTœùxÈŽ—æâw¯òÈ{ðhäÞ0@Ãù?¤r‰=§Öqý©Ë53ÐÒ¾¥|tHÿ΋¨zü'¾xXXûJî6EöœõeNò»Ä²o =K1Ü‘¹æq5zfS»ï²)'7©èíéUfÙ÷m9¦!îÛE¯QˆÊú?r® 5êˆo»®YBðü‘ñЋAX[D×ÁOÕÿä”m¨fŸQ­œT½ãt7o¸ÓnK0R‚î¼(ªëE"VrÒÙ:å:SB¬aÌF]qÔ+Êêè¿éÉl5ý xTfsÔvßD³^øb5w¿Bƒ/0NÊýâ.ë‡ðÉårPƇ£¼  ð¨Yˆj®¨ö_¤lEžæQL"Fn꿦ðäyñÊÚ롊-Âa½v£¦;QÁnûÛ±… ËÜù’º£ÝZ•­ÔðÆé ­Ìùp œô6_ô0(‡œ©lÅÂvO¶$ç0)m@‘7b6"”É–ÖMöäáOj¦á$­ÇNR‰Ê¶xø˜\W­“\³ïãLJX·‘õ¶\X¼G†W2½E”³B{«2P¨¸‘.I6iÊV"àõÒ<ܵkÍÅŸÔÇÝ0S‰ «»åËÞdGŒWÝ‘i(f•†(P=·\ú1cF zˆ·[ÒMeÚ[LH¼‰¶àT Eþýò†TP÷Ìóba/Ô åå™É}~ ç->\¨±áÂÖ«’'ï&;*Ù\~ùÂ^È&Õ¹ªŠõRŠA˜ÅÚp‡“ä§ô•¼°Õ}¿˜ß/âÆw԰̨ý’—ÆT–²´ú—…$ç³®Û(<#¶©—(bTS‰È{M¹T¾ç<_ƒ*2?¤nuÇÒ˜Ç 0jfA9„öøäª>©¨½¤F›áø-ú=¹`+"ÚÕ¡N±qñ‹µ°hꨱ|duUwÒ+Á^Ÿ>9&”Á)ªŒþý*¯(²/áKD>Öÿͪ`´š>¶ÅÕɪ§Ï7€MõùÀ†å‡BÁx GñOÅbÿòTÖýb€Œ$@W÷Äôr¨Ôd0d}³œåÜÛÜ{Õn(>âu#»À“頩뜺]®{BØóófR~ž»aËŸZ%Më²a ú±£“|ý,¶[1“Úv´9Û €hÙ™sy&ñ \·ÍBfdŠ?SŒó°æ–Âã†c-ˆ0Žyà #îã JÒôaÆ-E"ʼn±Õ™Ý“"ôªAdLZ‚~‹ñVÜêÇaÒÐò,>±©óÏßÍÖ¼"PhÀx¦Ä<ô õ¦÷ß•Zoߌ;MC|/Î$=Ñ9eÛÀÇ#\áñ$šìÁm@Æv¸6ËÔ£ ¸‰$®K¹2G…* `zÕÏÃEÅK´BÞ|/²•ùH¦ºØ2S°¢ ϸS ZâÍç‰-°Ô >í„\+e?üà¿ë$È õ€wÃéZišö’Ä@Ÿ!'…ÚÍ»3béá?V_·Sâ9@þGZµ`æ<¬[«&â½ §ÏÎûz8„Jâ°Ý²ú_aZ¾Ùç@©RÕ›xµqI(JÛo®V‰×”<’ÕœŒµÙ½göP&ýÜ…ŸáÚÅMsy®jK¸ CJAÇòÔÏÔñÍ8Ì‹ïù*5¦êCø@5R@¨ÐýÍQdë—žAfËr¦×Ú¼‰¯!dã7>lYÂõŽšÑÍÈt­)ÔöË DøÑHI}`ȶâ÷èr.)ªÜ€˜Õ,ú¥3Ó ÀfœQˆFvnÎcE˲²1NCFŸ©ã„¡xÚë@®\¦ë17žqhïí´¼W<µg¨¢õµËô¯Ï—DÚx0áÌR>Æ`†5§hE–|aû Ë"¥ú0G±¸*AIΟe"ÎÁ’©uÑ9ãÂÚ— o£ R3ÿÁòLêo²+9q=ƒŽu6|Ý­ ¼­‡öŠüE6 ‡HÑX´$ôæaêÖ`ÊR¡Ú}ë_JW$ –'˜Ëÿå¶tR@z±)Òyo˜âP‹2ݯ b1†²WÎɦ蔵/EnÂcoF¹Äp á¨*¹Ëƒ ÉyõBsHòmc¬Ë°ùì@€–Ío%±%&¯¤œ])¯%ü„)Ýd{Êæ½ûkÕnÝ·mÅËTR&üîE4l–ÞñTWÿ‰a$u½ÃÖäöv’û]®K¶@ËöA›¤½lu’´|¼¹W¦îåh\­ã†¬ç\ÊVû@±Fÿ3–A†eàC6˜#lËvÕüåbõ’?ì˜]yÚaT¿Ÿýö$˜¡ò)_ß©`^ÔfÞk„P}m”R3o…Õ{Ë÷Wj8ÄfkŸÖ9„)äÿÁü™«ÍøE(ŠN Áñ…¼I¿†þG·¡;©Pè-´÷<>S«ópAÄLôôw ¿öΟS‚Ú61 ·ú9bÒWrDŸºH»65³‡wm½/*QŠ·(eë]¡¨¦N@ÁX~`íYJD¤VAj¾ ÿÜø©¥‡ˆø±âzmêP›w^ÅÙq½ zøû¿€ù^ÏŠË/í¤.‹…–Ɔóü²tåï "©s9gçw8—Sý HkÓ]¤Âó‘ÐDŒËí³€4ß$òa·žW,¼ üpßÚë*ÝY¨æb­VóèÞEÂ5]ѯéyørþšHç]urV;ãÂp2æšeXJ"Ô™kê<S¥‡¨§j†¥t^ÒÜÓzð@ü¤©‹P©;“ UGuBXÉØ?ÑJ?GM©xb»Ò~ 2p-iá_k`šª¬È« %òÅP+“ÏB6]81“ÝÏÐÞ”‰{£û¤•'Bµîêû ¼ÄCØFúÙÖ)fñï9,ŽƒHr=¯JvˆhùNP¥Ÿýp¾%ç÷^FUÛǹ sÀM¢ŒÐ!Ü”‘ÈÍÌÑÉÐC¾›jIêr:“Mbïˆ.Á20 µF 5Œç½Œ#75ðwŸoÓî'™ÇäG‚lö8Ÿ¥—Â>g£2ðù&ï|&^!5g=N%–lÙµw;Ö¢>=ÂóæÍÙýèøo©¢÷¸¢€ˆN¨…nx®Ø ºíٯסœ°ylÔ°7oëÖ8=üœ“–@ZXmðѧΆ„´œ+7àb7Å ¼òôæªP`=‚uö93RŽû©€Woß©QNTÄBTÕÁ±A·–¸S ]éKë·ÈI|Z%Yîn‰Lp‹‡Ès€mm>ÇÔ£ïh‘v _2³‡Z&¬ߚ0…Žæï¼ÎÏU‰>Q¾ÃåUg«y[øŒú‚5¤/øyFâ^ÞÏF¡ê¯"AG·Û-¤Êà2©]28“v„{ñ.¥Ÿn¨P—šåv7•!÷|Ep}`ÙjÇå×Cd¶ÆIÀAN '‡3ù¢ ñŸDi¸87V¡Ô%u#'™*_VCÍ~?í\([åߤN©~|xÅõwmÏl¯AžÙ‹ÎH‘ä\G°‘˜ïkŽŽÌiÐÇhàŸ·»-Á‘6Qò~F€@ü®¦sýÞËE2P H²† àéQeXâØ§„ žÄ#ÿKb×f²WÛ.ÉTQؘ#p@øÕE¶‘p[Òjiït¥Lú“ƒVxeÛ¤ÛÒ±ð»ÞL!ãÜÜŽûãÀ+ª¿ ܶQŸÈè‰'¨ÙIŠÌe-§žÁ 9ç×Ôo¤]¿¢âeuE˵E>“h¸«ÙYHêÎ>·›Æ àmñ˯S¢¿KoÓñIY7™T6ÿ¬Û`ËÙz(•8¨¿·³ó\¨‰s0SÞ“ú9ÜP¹/ endstream endobj 74 0 obj << /Length1 1630 /Length2 11468 /Length3 0 /Length 12314 /Filter /FlateDecode >> stream xÚ­weX]]“%î\sƒw îîîv‹»»;w ÜÝ îÜÝ î y¿éîy¾é_3ýëœ]«jUíZµ÷sùe:A[# ˜­=#7@UI]ÁÐÊÊÐd+C§dkmø0³!“ ; @¶6"†N@n€:Ð 403˜¸¸¸È¶vî 3s'À×*Úÿ²üu¹ÿòé2³P|¼¸­lí¬6NÿÏÊ@ ÀÉ0YÂò š’r ârªq  ÐÁÐ  àld2È€Œ6Ž@*€©­Àê_ €±­ èïÖé?¸†G; 1è# èf ´û Ñì€Ö GÇwÈ`æ`hãôÑ'[ÈÆØÊÙäovSÛ ²s°ýð°þÀ>Èl@vN€¬ "bÿªÓÉÜÐéonGÐ °5ýð4±5vþ»¥°šÔÉdãpº9ýÍe˜€í¬ Ý?rÙ9€þ)ÃÙdcö_Ѐf†&V@GÇšî¿Ýù¯}þÝÚÙY¹ÿmû×ÖrrZ™Ò#01ä4vúÈm²A`ø;*’6¦¶&ÆÙMœíþs:üÓ ¯g†ê£C[+w€ ÐAÎÖé#%àëÿ›Êôÿs"ÿHü?"ðÿˆ¼ÿâþ»FÿÇ!þÿ=ÏÿN-æle%gh ü'ðw @ð÷’±ù¿¼ ­AVîÿÿ¿{ªÿUäK#édøÑ A³9è¸èY9¹þ€Å@n@“±9ÀÔÐê£WÿØUmL€V à‡¦ÿ´@ÇÄÈøo˜Š9ÈØÒæoóÙþmLþ½þ™þ©žABKBBXŽæÿºWé”­>æKŸ‰ã_ “à¤ânüïtê²¶&ÿ¹øË'$dëð¤cbgÐ1s²|@f&+‹÷“û"¦ÿZË:9€ÜÚŒôŒŒL¤ŸŒsÿ§ ûo4¢6ƶ&gGÙÉÐÆäcÜþÓð6vvpøPùŸàcûÿ±þgð@7 1ÂÒo[ãoA©iNÕ89c"Ú½ÝLÁvÅu*?òý*m»|SÃ6¹Ê ^ª‚éë'¸ßZÜçí^w¥¨÷†º±­(»’çy„Þ¤T=ùèkm4{ zÅÈi'êQžs2PZìŒj{[cŠJzE/0Dm,p÷T~¤.ù~˜dwv(>Æ)µ±Xíhõ`Ÿª ŽO(ïï( ôwýîÙ% ÉŽ…'ÿfˆã“tü%ÑÉÝÀá¦Îø úÉ…-îÁè;C»úÏ–4óèZR³ /SÈÍP„Q¼ueåjá˜v%¾ 9›Jâ©Ü¯3=c¨ëLBŸÉCÄËŸ¶‘v¬˜ÌÃð/º¨>Þ€wå”`yUñ¸œÑø.Q þÝ{bsæºFÔîin¹ßÑ,¡ÊØ-VBYpZ¨fB—9ŽZáŒk->|BE Í5ª#_¯ΞlåsúĈrí$qua Z’Ǧ€&¸ÌsâåÃC¦{9b(VèvÏaÁ;’P˜A(¿›˜Wq<}æYO(œ±7‹‹Tùµíè©S)è½ûUn8V͆§•t¢NþwH*$qïl–ô˜F ÌV¯ª•³”-ühtÉt`“r¥Ô®*Ê¢ku(Š(ȹ @Ÿ¼)ÏÒP@¼‡Î¥%‘ —W€¢™Èu?÷Í×mð“öQ„kj®]ð ÞÖQýl25£òlj7p$JW[\}n†\—r¢`ò»­ª`ØÍ¦ÉãK$@™Æ0#bÎ…Õ㦻˜Ft5ÊK÷PqÖ/FŸµ:ã1±™{ðÁšœ¨Ö¢å3„Àû:æÐH´ÙKbšÙ0 ©}\iˆÕ™Îgcœ–#6lÍXÐD»Ý½çQ~M’‰cÛkù¼­ZadI÷ƒIÇŽÃøw–{~©}]†ÇÕúÚ 1ì-ÅsïÃms”(Öw«Z¢Xy^7-¦žIm²iÊÉ©/¿ƒª‚JÆ:æl+Êò-UXfe¨O` ˜‚ˆsý)DÌw^¼ð.‚p@®^ ô² r*Ã_|žÐZb•[UPSa åWÓÞXîsU@çAØrÞ%gXêyievRKˆýï<-³¿ÝŒ_¯üFõÓc•käUôUÿ¢éþ¤ö[ÐŽh©r„&Ò7¦œÙÙÙúdµ+7Úkf<¥ÿwèÉ’*ã²à(ŠB£«1Áêk0|[[?ë÷߸bø°c1?]ãF`礞``~gÂY°Š<6 )áéØÒáþóJÕùº5[{Ñ©k õÖ°1À ">€ì ,Ú0«iæŽÅ˜Q©`‚㮎IØïÄürZ!`üü—Y‘$ÊHÊk)· Ð_΀+‡“½0Üžya7Z+aÙ­ãúØ£‘Û´ÁŠÎš;˜×Þâ§þ)O“§|Ï©·­Ìöe™`=Õ赸1í¤SZ÷(8¨V¤ÌT0U™€Vš'p)XÿÊ&oø6ò”˜Lý‚DØò<^wË~w²zŠzc¹U†¶r ïjn0‚…Dð–¨ëô‘Pm¯ÞØ$:f{»z¸VWÕ1weRØŸ×Þ-5Ñ`;¸êp-W¤&9’›Q}<¹K°oåÍù–À<Ý|¿GéE`¥âËÊ ±2‹…5wv €]ý"˜,÷I=¡Þêé­ç&µÅ¢ng+`{wÞgÞ0îÐzå˯ܨ®o)…Ë’V1”ÝTZÙr©ò3le®Ø¢–/åOólÜæçè%HÆ×H¿®nà ˜_ôV¼ô#(3Ä1ÑzcóRcËÑ )ôÄ\!OèEgcâø=ù_‰‹Æá \ÍŒVŸÖ›pÅÖ(É Ö›üòÐÚBÜS„ð/ï·=“Hnøª´f®Øi.|‹Å‚]¿ëûcAˆ"°Cи/ö‹çŠå%|ÿ^"LÎcÐYIý’÷ÞéäFY®I]‘tȾiÄZÆÔ›4Û”o!y|”iÈÖV:¦º¼Eø%Ç[2¬óªÑrT±EåÙÖ¦ÒÁ¤áÓ°ùÙ[•V£±¹.^¼Ìb΃÷s?GèŒ÷µ<¿Xû]‘¸¶`ܰ?ì{PÉÉJ\ öeû©ŸQÑ¿¹'QRò믦Ÿß“⪒SБy*ã'ÐÅ´8+F¼{ «ðèܼPI6¿ýcÈáÍ¿xëL ­ô…/êä€wŸ‹)Æ·Ÿô‘$ *öS(’ó=ÆÉn<ýzçX¹xà–I+žO½ÆíøÛ³ ^¶ÏÍTÖòîö%f~-R`:=ufe(’Ñ,Û|çÐt³—ÊÍËj‡æ—¨Æú¶_û¹Žúã ;9ÉU%Ç]»µ·†ž|9èÅ¡D>þšèE ªË©SÙS-ž€oº÷V¹%á: XƒƒÒ¼ŸÛÕúÄ6þàS^ª‚ØöÏãÓÚÄï¼—_g%š"ÔþLŠßv±j-1OrtEN³OÛp2ÀÎßó¹Åù“ªÏ³'Ìžì·‚`èý#Jc²/ì¶¢ÀÉ1¶ÏôÞqO8Aô °³&‚°$wÓ¹ríÃÕôür¼p–µmPÁ¤‘*@޽³ÙÀ@ðL“ÔÖr£ N%Ü|Â…v“¶‰²¹ñöóùiRñª€ÈâLfª‘°´ľd5š¬àë³Ýmöá—^~ô–¨Um{t'˜&ŸúíLÅfM &°Ÿ¡y¬Fü°“TË$æ®Ï7¡Nö§Öü\V›Ã½q¬c¿„ßNP_É=ádc^Ž7]nw¨ÂHXù^i`´Å2aQge†{©¥°ë¹ýì. ôƶ´(Í´ÃÔ>ö2A4R;ùêò&¨hºÒÿÚËæþ1Tï•çO.f°†{ÞápÔrc1N ïzîíaü£Ù‚A³ZsÍãÛô„ a XÿwÓŒØè8É–sׂ¬ÒzmãÕ«&Êß fæpl÷@D»{p–N”ª‹¨kÝ4¥Àè7,¤ôØ ÊiNwMÅÿ´˜ÝÀi!Ýô.lLNÀqsáœÏ¾‹Rú€‘ÜÞù„—Á,ý7­©30a„=§‡ø¾›3áArÙ(O'ú:«X±ì›gªÃùû!”rÐðüù3_´siªøÃÝ_Q –ƒÔÀzâ·~/wöÐÓûlÝr¬üýU#öý¹`±h[DŽÇm¹÷Q5ë&ê3ü¬´9±|‹`ƒ:ʦt¤–í~v¾[’ÌÈ™+Øñ·ö›Ü$®N9ô˜ºU€¡3"2ŠV÷ZÅmW²Ô¡?ç(×E-ÌSBv†˜?æCkP±7´ÇH"ΓÙU|ñþÕŠ(ϱm“>ŽEAU ·Æ½v?‡Šý8¼N§Œö C´1wù‘&Û1é¨~†x³:YëQ²cQ¤üMT ÑÈ<8„ƴχƒYÉLãcå¦×böm°Óht.×6xe·P‹ï2¼Rॠ.¤…òúòcÀ RFÍF#œšjȱL§$ÛçÑ”n°àKî†jT“æ}0MÃ5‹‹-‚‡øoðùP£ÑcÚÀ†ÀP%edS>3?¼I3÷Ø!ùBG [ÒgÈÏä©6…iâ:[jeç¿XÁ»F©ÆGiB½ª1&1ˆÜ2hpeÙþ°òÔdN·t[Ðnqr‰œÀ»ð·ó3×ðÒ¥á=1釽*ëYrêô‚±‡­JGƒá‰~PtÝ/l Í¼Žs'¸¾[²FàF2vص.?~m0Ñ—¥)@rcËÖ4ðq su?›~<•ëì$ò}“§É¼_ (æÐæÑ1¤ ¦H^@D? h?2xÃY;GÔ×<Ήvè‚C ~¨`[ræ½q¾E€çg+ dK d•à™Ïì9®\wý>÷¨‚Q¸®–§±ï³~$¦rŽI-;/¾–‹ÐþNebÔÛ÷†36˜Q“©‡‡Æš:I,eå+ÎH¿á[HÕíÒö‚ý«s3û$G"€¯d¶ì±(h–?ê1Ȳ†>ºKMΩŽUp°jiJaÇKÖÁV0]3™­ûžS}WË›QÙViŽcrå¸ãPÌó»i<9–Ukr‚ÌR··²MÀo§j|&‰ÏƒA#–?ë€3”Íl¢—×Ý$×cCå07³Q·Á4rô¨ï=>†{¾QlÁÅŸ>}~ŒGWèD5ôÂ'KÑξ©ú”p@ÑŽ±ÀšCD徊øÂFGëz@D_½}''KJZó o€i1Ó+‡0¤\NéÑÿóÝ@ž[Œ2ç' F²‹kŸ€¡ÍìçË‘³u­‡FáCxá%¤_<Ú‘â«d´8ÿŸíÓsz/v]ëSjÕ¾ÝѪs:hÈ‚2›Ë ò£bPµ¾b]*²„y]•ùx¿u9CtùÆòcó_(ÑG‹åßSNGn&UÏCëcÁ¢QïóRˆ¹^•ó¿ï0ŠDÁÃr;Þ~~ ¾i&`Y`ZÎå”$p Õ©X@‹$ý1O–»˜¤Ìá…cñ3¥ £éئǨä­mT¿»ñ*Ëÿ7Ö^IÚ‰Èxw,ûy`ðE 2QXT¸ç©$ój´û:JN=vã§T foSŸˆH² W¼²È­ñ JUÉ’—yCÿtúK2A]W8c~ôÒ;±Å€=’íÓr—_e±EF“÷OßèT €ÄÐ)ŽÿÀIåP26ƺµ-:ZŠ=xÔM}VO“ÃFæ'ìZ¿³¡áaÀ± í½0Ot€ãVµ–ÝQ±ÊÐ5—¤Ñ‚¹@‚+‹˜,­öŸ©w/†‰nZ¨\òÔŠYÛ¡ À¦ør£\+ñ…¾ª„e[x»ý©à“ñ aVÞç3Öš Œ:ÎHUVj2£ô6ŽÂ*üÖï‚ u:“êÊêÅÁφ”™áUÌšetC¨Pí,J8äW ^F÷Úê4‚©ô¦cjë¶ íäl×/ïp¤¢M(ßÌR‰2É/žhˆdC fˆ¾âa/ûC<¬Zž?¸gFãÑm}áOÕ²\ÿŠ ý2˜IµËµ¨M¹âZ&oŸdì"Ïn'ÝÙ½¹’)«'$Y¨ò˜Õ:ŽÄƒFÊ—7ëuú|C¤EmÍú,šÈìŠ Åý(Ý=Œ^<î¢òѺ‰ôŒæŽž`ã©÷9v¡©h À7î!¡Õ!jŸ9µíxkjÅ—õå€ýd>úØáÝ6rjm™ q:­eðQ+7êè·Øj œZð,‘}ÏJ¬6òès¦›6²ˆ(gzo#™m¥Wkœ=‰§ÃBO©ÚƒHß´Aš\Ççý‡-I\c¢ròZNö­=}D¶9êwú¨hµ7׿.5Y,Õ[:‚Œú3c/¯r“®[a‚˜áS±+¸ü[€L–ƒ-û¹Œb_€òÇ»œ4Ûc"Ì)SzåJËË##;Ò|Èazp‰pm:Ê‘b+ùg‚a.­Ï±pÉw¾óyÈ6p‘ºÈÑâY o²Ïüíè'A›‘•*¬>Ž*[8ƈŠ'2öIÁ÷×Ç#—ÒŸ,ñ[Ó“ÖXAª¢Í÷.«I¼Zª^© ´\V+ºj•ÜNûu¥æ‚çcAÚ¯!ë¯*Æ®?ƒpýp '½$B…FÂÔ5”„Y q•»ÜRáMÕ_5ã¢'#Z¡0n8)åˆÙEHþçyøÝŠÎò%›€{ ]»C„ųí®poø©àH%þ·”ƒ¡Ì·Q²^sHéÁ@ˆµÆ?„VQAm êK:ó,̲qÆ*Ñü´¶ù¬ L<ü¶ÎÌPTÍ žB‚WhðÊ_šÍ|O@á*3Ÿå©L[VtQ‚Ѥ!”É÷…¬eVhRªé¡}ÛËq#Í@gÿºk;bÝaëÞléðZ³5…5§Ü‘êm'¦Ý²H¹¾Ô‡5-ò®y¡;²ˆ“EY«„•ÿ(µ´3á™þ¡†ØMryóÉ,¡Ù»|³»˜¿ž4¿0ÖÖ­—ƒ‰LåS xàeı*^€¦ƒ]/I³òâWìÔ<ûw †¬©'$éµÉh}Z·T%ÍMÑ×øÜ›—àØÕm9™o£1j2J•yCöüÙY­-ó€:ëáñP½+Úçjû‚¸¾†„çž|’•¢§9 bfÇ–U„§ÁŽ›Û_ÉG.VÓf A¸ §eç3eã¯À×2¥q°ÌL:²Aä†ï# »Â+]I?ùU±¬ß¶ØÙÖ W°º8a×zÅØ)ä¶°»¹Ö'Þȳ°*ÜhÎþ‚$~…— ¹Ä™jÄ0›Išu©æÉT¿Æµ3?í¬J àYxОóáq¯¯pù¸Nd ìt HsTTrqÊô¤Y.Ù^s£z‚:ßz%§$é_7,³¤Òj¹âDKCë »ïÌ o}Š{þiH[…Ýø=šè(ï9þOhCO˜_ìHdáw•E +Ü܆(6ûVÆðDqRÕ— f=Òh¬×wÍ|hÍOߊf %õ挛†¬Í3ÉõÁ±‹Ùˆª0=­$Í¿·\ À8é Šr¨6ŸV®G¸Ž}…×<á‚/ÙÉ·rLŽ"ƒ/í[3áCyÃU÷ó|BŒÃ'n߇É?JY1Ï<\ÕLX«àÑéf0®³‹²o{üf}6•/3Akq,)®F®ÇŠÞHò¼¹ÃÈ¥¢âܬ¡eØ}?y¬ß=l–•ußäAÛM丩!èâ Ñ&} kœPŒ¸†KÜüóØãöÊüLéùKþÃ’b¢; |ŽøJ|hƒ+Y­½PÿZIty®¸P»×–5ß—Ê"3§iOÚ5Î%uy¿[áòïëf]å82Cʇ$ö±þ¶ÜWÌ·á¢c¥Øm‹ûÒKÃ&~¹ ‡n„­OŒO{wé#[Ø6¹ÅÛó”¬t8ñGxHéÝT±û嵞.o©„DN#§ÝíÜá Tþqæ‰Ul4–GÛš®ÔD”¡¤{ßìk DâÿP¸:$ÈQ#™|›L¦!ò¤3ç6°—´>¶ï,ÓþruÀ÷ôm @Ö{‘D¾Þ>uk¬ä(¼Å㊠?3#( ›'TÙ™ëóbx!¾·Í/ÊLï±ï sþø®6ˆ,x+(I‹‚€š{TQÊ"Mú÷™9à¶´¯‰6û5œð¶6ô+ýX÷’Bz>åü– vܧEt!É8²¹ºd‰^×OqbCY ÍÉ@žº*«DÓ.íbÂnf2ø¸q] )Q/DïD@è4š¥öZâüóô~­PÖcQB£ÁÑÈžTdw¨žg’t««ÖɉÄé.C¿|·žôçö­çS?WÏft8YëE½ü”BöXqËW#8G žó,Ýo^%hŸH3ÀÝ'½÷€^ß»˜°Ï=«w>Ó%gW7m¦ NɆE%C—JÞ7­ì]¤§[ûp·í}<—R^š_Ù~t K•ÎÙþ¾±Ò´wA7s@RFH_´¼p:°óˆ^½%nÞì‹B2…^n„jÄÆâ.›#;rû¿£ßø°ÊæÔ5I)Þ&ŒÇ6ìÑhx½‹TgåSù3ÃXÅ^ÛçF6×MÊR†šžµ&í¢‹vsœ‰KvTa™ã"G 1Dú@g9¼ èâès%LЫ»?)·À˜‘&Ýû6l Xšøž°üÅè˃Ð+*O{ÁY› ¸hDŽ{9A ü §µü„@$\y£Åk¶5<^FÞ× GWÌþwllÖˆçÔ¥&ô©•×#!è;èºFBZ?ö?Ž»`|ž¾;ÈLª$‰×•UV™·2鍨-÷ÒçJohD_SÀ²çÒØ“ Ùz«èRQ>¬Ùû4¿f~Vt¡“ô»øEžüvá°£øé u]òÇ€'ŽC|Z$îÄK)”iœ$¬÷’Η!{›çùÏU[8>†RU¬<-ñsî?3z{¶_-^õ—|J1“Ì¿Wgå°ÞvÅãûBÑÄ*î^b)&[xö¸×‚÷ð¬3úEîc2š1µÁB¿GÖÓ£•#UÕ }Ú$CÄ»{¶R”%-þq+ ”“›ÙÀªß±¡0ŸHh¤¥@8¹•¬¢)Ú’»ûj™˜¡b1—EPcx¡Q³iAœõ¼úuA„é:/ž¿ ÿ>#‚otËí¼¡z@³õKÆk;PfˆÛʹ«³º÷Úql5¿3‚R·Ý×T’6HˆcÌP‹û§°Xµðç¯{e?Œbú’F6šöΕ±ú°¹õ€Q‡"s—kMÓ¾ý™UǾß?/ÌüƒB´enت4º^ÈF æFhXú[ätº½'wóÌS¦"gÉDa c\N1(ä@ ºxöãØRàºIŸ"¤ÕW¹ªpùU]*²0¹ôæh¹{ä¢ œÆÔ¯ÍM¬êôYXØÎ¤ýuW9‚ ß·n¸«—Ü0‡]Ði²ö‘h²÷á‘"DϤ3…FÅ7zçë"uŽÎd;´è®0µÔjF‚× ù¦¨2ñ¥ˆµTð0|’yËÅLÄ!b1²2­Æm•—‰ßŒ’Él)Êz+GÒøgºAÐ2BX4àNwreÕÅNü¡•K Uª²Èš¼s=.ÿ¤ãª ‡Nì»v_bÔ”}gºÏ»BFyX˜"¥ÞKTžƒJrEéROèg‘=¸2ˆz&’H3dà:s‰¨þ†râgöPW23P⻌z‘ÙÓ-{­‹œõŸ¶¿%N‹µžF•Š¼Ç‡^Ý쓪iª¢Y0<½MØñ—y—syY†>†#Qò?̘‡zqÃÇþݯÇ9º?V’â uøw!¡Ê5¸Ã$FZ‰ú-0ê›(å±$ÕîÀþ[ÐV^Ý×ìn“ÆeȾ â” Ä{y3[—+üü)2ÓýZ*æìŒ ñÁ0.ªºª$il@WÝ4æ:D–ö— l¨6ís¯<£K’ì–oWQ»¼V¥µuÃV„”Hn;"caFìP—ÅF(¾F°†.WõºßŠÚv GsÞÞ1·„a?ÁæqfwbñùƒËWM6>á*Ω¹}³pÓÕcÅ_…aüß¶DH‘W9VÛLš/RÛ¦¤xT¹³ø‹ i÷¾b‘#ˆÓDöÇä£w‚j²N;àg¸FÕ(qx lãï6ª<‰ó.$ˆ&u¤er3-“º¾hßà·oîJË•ePÕÉͰ¹ "Ï­ÍèCÉ.Lç=ãRšªikþÀ‚/9¿ÏDˆNü¼©fç ¬|o,SæÖY¢•ÿ"=&ù_0ÊÈÆÛé²¥¡U-<¦…X•c‚?×›m~ &°ƒÈ¤Jâ…? _i ´]•|ºâçl;È (°-yé­_Ø–£Á}BÖò,m¦cNžX<šR·ÓsÔ<Ù® “ù „µeØÃŠC›…]î5>v©†çy˜ìnªÏÏ>UÚÊ!øeŸÿ€)qt01§ðñýnð(#dÁ3‚ ½Ö+ãNk‰ºuäñnÒ¥JˆÍ³eÉUMa\œP¹+IóaލÑOæ1„šr¯(ˆ­Üú—¦“Kàx2%·æ«Ÿ­Akq¼ðjÙÒ\Áx}©(ýŽå¶9º2ôî8Á½t•$ü•8˜túÇ«49%~È(Ò~0KƒñºGåET]ÑβŒ»û'(âP¦•Úé Úw7 g;ÿž¨qçÛ|•§â+äagS`/ÌÚ’Fè³´w *”èêBæ¯ÙÆ·Üil°:Û£z¼>ÿ¥q3“Á/J„•ï£U3Ó a=«xv>ƒÜøÁ³CåiY²&ªJË ‚+¿H¥nê*c”‚“lØ—Y ¤Húœp^’ñ¯yÿ$€Woê‘´4–}J7¿BhJôÃx˜LÙÜ*´²œŽ´¼ÆÈ¿vì…²¥³ ܨ·SGÍyòRb æájŘªiÆKк_&õD|Àr-ØIÛ“4†Jl{›j¥9\F ;2KHG¸¬@}Q8å^g…6ê×·ï›Ð öü.Ö“ Öë±²Õïà)kÕ>´Ç³ˆçI§‡X!}dµ>ÈöÙᤋVµŒvXxá–bCM¥‰úªðQC¥IFrŠ_™é‰¸,ó=½é« ©«Á¡ë§+lœbº~òhš´¶Ÿ|!`SG£³L§E`Qý+óK_/×µ¨Åñ`æ¼È]h½S’W”áð>?v!Ê.™G_[ÄÒ6›ÜE šQ’ÛDÆõ’{Ê'¨¬ÆÁOÀ´ü<U‚ ¡³îüJ“«kL=è0T®¢|Þ]$'%å›Ûƒo»W^¿µˆr´¹Õ¤siEÕÑúć]èæ»Î‘Ñ޹DŽ™M³|šœ4?ãÉõœ<Ĉ·®Gy[û)-ëË ÏlGMÍÓ LR$kr3ÞpXœÌË ßUkÉåób–ìrna •H ‘59:ļš8ݹN|ª"Äë•ü/2o¥Pö…ÌŽ/¨˜UŸã1ÏêWýRº—ªP~Ú4f|2q£l?ÍB©‰Ñ^’ Š+2§XÒÌLÒ%‰v®O6CšâÒì—¸"¸#)ê#‘;Ä:Pn/œæ0&:°¯{ŸŠo["âØXªÁfÍŠŽg¿ $ø7¨++‚ P”SN!K<€[0¦ì}ˆÙ8ìÇù“ah—Ë*s”!MˆŽ4añš¬ýX’eˆZ‹Ty3Y‡2µ«ì°E½°~3oœZ~@_“…óqØà½ü$>ž‚¼IÎ?aŠ~ÿ[Ò/ù º¶Ò”½DÞ¾¸—ƒ/KÔœ¨ÆÝ€[B÷5A1„I¯¾BbSçÏKÀ“4†œJ¤?ÕÛ¨‘ã7C?O žv¾¨ô´{(m(œ46â:^J!¥ t…–W›±x¯ÇDU"Bm{^ò±îñÌr¬ÞËL8–í˜(.ø1ÁëÂK$RYg.³¥Ï3ÛÈ58/,nÌʈ¡Pö(*l• ö^]ö¼Zyìötfd[2û²¹¨VÓÚŠÜÒ¨v¿íªlŒT¹ñxLƒÃxÙæ‘²†€",ÍŒ½´È/•~1Êý|}dÁ˜iÓJãÉÔùµ^¬^3F›?êÊrÂV]‘€És§Ï”|€äðÅk‘¢¾-nœ)êq0*Q~ø4¸Dî.§z‡åÐþAÝø3·¾¥\ǛړQ±S$«GœöÔ‡f¢"Aü¦œ"ûÒç¶°‡øµ’!Ûì,#ËYÊPžÞ¸,ùV©OÐåH\ß»žFFwóœS4¨±´Zâ#âqû s7… È›œç¯Ì6ß‹çÖÒ v´ÇTªÞOf‹x n?'HsVðÃ×Pt`¬;R¥…{¬–·ä‘*X%H!ž`“ ‡˜ ÚÝ_ñÓBà¼î¸\íi efñ'‡F7°àN e¨¡^=íöZXŒËŠ•Nì@—Ÿ5ñEAÔLev©Îîý`è&–• y ;ŠºmzpÙËz1¨ÃýÓì‘®9æü›ä˾GÔ%S•™jYQë%ï˜&¬aÏ-ídUíeòP~~ k/Æ« îûŸfƱ0ס€7ý‚üH¸¦ÍQZ˜|¦WŒûCëkyõê­Š+&‹IrŸã·ÃUW÷j­VUn9ôK ÕM½ŽÌ2þB_éIÙ’‡â߀T‡ŸiØFpm¥7ßa²fÃ?…iØÓwOj…a•j·å@"jd[ c†+ixãàߎ§ßŠñ0»~[ž¨9?§±ärĽðÛèpýSt¥“áÓp9ÿ#¥QAŸ;j¶oÖÐZÖ–TÉã€ÇõèÛi“‚ ¹¡HZ¨NšW>¥ÅuÁ»­å–ÐÓUþ„lÓðºQÿbQ»/X1ÓƒÊú½þWt½ÇêãGí¼½%‡à+%(¬MÁÍWÐu.<6¢þª™0… I*Ç(¹ôå< õöq@ÓÜ㣠nyšœ;:”ýcÒ{v%>C‚¤³9ÝŠÛ£ ¥ãpÔoÅÉqð˜,c4q3×ÎA».ýúÆ•ˆMSZV Ž}¬Ÿ s¹åV(pa€rcÏ÷K¸Xí¹ÿÛÃr ÿqëÃÕåÞ–õ~:yó^‘iNJ@XQÓL ä{^IÇEd¡3§÷”¼.ÿ“ibÔu*ázá\–±Œ—Ä•‹ÿTófk6š<ç3éCAY\Ý=ÅQóûS"%AÊâB#-ÛJäy ÈÊ'½ Œ8Ê<éz6ú_u¿'Y gù&>gÆéÕ¡‘FšJLRþ–$ÅͺÎí+.Ô៳…úÌ(cQ²Oå½IiHî°¡œ£^€qd¬•göCŸÉØX.FJoiòÖ Òã…°zö&º2”í÷Êô®¾}ˆÕüF@ЊÙUP6FÀ‘Äò[:„xêçh%¾àêx¬Ÿ$|i'‡îÔû³F7UHߌjíWÚ; A£Ô*]äC¦8S ‘´Yçþ&ýÀ)ð¢+mQ'XÁíYÿ”B'æiQM‰å¹Á•«ý—X@úÏÛp4ÒŠ·3O0ZÞýoaÙõ«bä‚èIÜf´Ö: Ɖd%\Ej3ä~ û3èšñߢ;)°ëáã°_æN£Š·Œ4È/eáÅØöP—y6Û¦ªœm¸Ý q:ŠÖC"KX«ÄÁª¯ íŸßEÓDâß–¸!î$ ƒÀ£FkAM×ó÷úõÚG€qÍ"µ0SÝrõòcior¡Nùx¬UèÄÉxŒî_·SöâÕ8žn!¿ô›ÈÚè:2}‹z/_äœ#S‘Q"SiËñu§ú»ÙD{ŠR…›-ÃRx°„þlS&ÚUàæ|N …9à€!µ«l&ic ÛNãœÇNaëÄë×ì{f‚ôÔ4‰=¸ÅñY:wu¯†œð6!íS¤jJÓ^“iƒIqvBS G{0]íß73AŒ!/XèŽÉ°X?áÑ(2õR÷¢ÁoL~Î@ÕïDË;B"åòÑ$‰è®®kÎÙܽ.ð‡¼Q„l¿ª LHD³‚ïAq°™R*'¼Ñó½ Ë SaöPÜqc1@µwÍ•ªUz®ùùnGØq#ÿ/uFŒ4 endstream endobj 76 0 obj << /Length1 1620 /Length2 12546 /Length3 0 /Length 13375 /Filter /FlateDecode >> stream xÚ­wcx¤í–uÐul§bÛ¶mwX±ÍŽmÛêNÒ±mÛ¶Ù±“/ï{¾3g®3ókf~T]Ͻ×ÞkcÝû¹ªH ”im b¶6N´Œt \U%u++cs[ZI'+À§™†”TØhàdnk#bàä¨"@#€‘““† lkçî`njæ øä ¤¦¦ù—å/€¡û?‘ÏHGsSÙçƒ ÐÊÖÎhãôIñ?TNf@€‰¹ ,¯ ))' —Sˆm€ŸM(8Z™dÌ€6Ž@J€‰­Àꀑ­±ù_­9Ò}r : Žv@#óÏ0 ›Ðî/ˆ`t°6wtü|˜;L lœ>gàd 0·1²r6þ«€O»‰íßÙ9Ø~zXbŸd ¶ŽNŽFævN€Ï¬ "bÿ¨ÓÉÌÀé¯ÜŽæŸ0ÀÖäÓÓØÖÈù¯–þÆ>i>Q'sG€ÐÍé¯\†@€±¹£•ûgîO2;ó¿Ëpv4·1ýW4 ©ƒ±ÐÑñ“æ“û¯éü«OÀêÞÀÎÎÊýïhÛ¿½þ£s'G •  #ÓgN#§Ïܦæ60ô]I[#Ã?ìÆÎvÿÄ\€ˆâ¯;CùY„±­•;ÀhC/gëô™@ñ?S™îÿNäÿ‰ÿOþ?‘÷'î¿kôŸ–ø»ÏÿN-æle%g` ü;ðÏw @ð×KÆÜ迸X›[¹ÿwÿî©üG•J@Sg+‡‡ÿA/hcú©-'ë?¬æŽbæn@cs'#3€‰Õç¬þ¶«Ú¬Ìm€Ÿšþ=N-#ÿa*fæF–6 ŸõÐÆøßËÿ”éïâé5e„´¨ÿë{õo?…OýTÜ퀀ÿŸD]ÖÖø?± Ùº¿ÿùù×I÷ßhDmŒlÿº1ÊN6ÆŸ—ì? ÁFΟÚþ½÷ŸMÿóü÷uÝ€F0Ë ¶FÜ©iNU9c"Ú=]ŒàAv%µ*…ù¾¶>©¡[œeú¯•Atu\ïÍîó'vo{RTûC]èVäÉÀ‹<\obÊî|¤u²Vvê}úï%pi§ê‘ž—s2›_´ØÔö·Ç•¾¿BàM´2;@]>Pú»äû¢’ÜÛÁÿ0J©‰AkC¬A®*89%K8z¸'ïèï¼úÚ½‡CMÊm€ñ#é„0ÑÉ]ßá¶Öèýë³ »ýÄ·ç¬T³Ð׈rémLÿ+åMÞ&Qêû^qÅ?bÅÉíáM§ñêj²¯gÍFšØT+Òðôæåy»£æÜiN)å¢êmS$ë··@ß0[L‘´LJ¼ýoÙà[‚ù ANÚ{ìa ïCzªT"€oywíŠ p਷š·.B|‘\)ÄÎŽØ×ž0‘e‰Áw³´[–n…Üΰ`[ƒÖ;Âèw®êªûØô«‡Ì –W¥GL¶žÉž-¡®Ð}u÷õƒ¿ L2øh7ó!2žTAdeéC» ÌãLR’龯ö½l8k»mV’ÅñÊ!ýÈ%ãW‰Ý«÷Uh¤©m¥Cq§Å0¸Pn²BS ¼Heƒ ^ç' ŨLžY5ÄŽôWG^Ǫr®W Þ÷‘û½˜†kOU6¹ |mû}ÏC¥6Qa“e¾¯ßŽ4Ÿj+xÍP® çÕ‰ø•RA·_Èx½GNŸÆ´Ç'/´î FU€ÿ÷ŒO¯ÏñóIóƒÇó*Dµ´{ÊUòh[v'?©q¨®mÏ'Œo$Þ°§L³K{øÒÛ P÷M?ë × MùÒ+µéqQBÍ»3)6®'@‘ ƒžc Ž©6,ò'ŸjH5ŠãQøàb3†@ ¡àÄLzL_jÖœx5’çOð÷ޅ¨†ì¼íT¢okÍd7Û]n¯¶›LAóž{Š÷`®ö„Ò\sb ЏM&Èø(‹•–‘Zš ö Oá·1×µDºWÕI ær%!¢‘Õ:xÈQQV¨Eçi9ò™nœEJË®ü´âr0Ç6mé pß#JI VÜŸÃ)ÙŒúVT æFüÑÉn»´KC¼bØ .É5|¸úãá‰ìd5‰o&¾°™÷–«Þ"!óŠþA%û`ôfžæNÖm¡OÚJµÂQˆÒpMQ[ a ·G¤J5á9¦C9Ïélù‡‚T ;Š õ^ÌAkÁò”¬+Usú¸㌅ 3/7»¥ÌK¬GØ·MuÌb\ÛYY¦ë‡.°D=JŠ|ÌO“Ç©ùú×âkꬫ"ë{?‡üg™ƒßp;ŠòÕ˜œ™¼ ·º%åS‡ä–¬a´?/–ý²fÞ}ʤ7¦Q„€03BŠî)?_Ì&°é–mž§ÆŽÜ*“Ì!"’*¤)Üë_à( 3;<ŠçjÊ'ÖͦŒÆ†–8ÊÚãàQ42ïNû×ôî{%p-3qØM;ºø[xIí££¶q&¿Ü‹½¸~ÙÜtãV-ö'p3¨¦pív—f¨á |[ÆwÊœ<¿ß‹H¯ò‹ÌH¤Â|¡„ðîj€w—Ò<øâG9ÜI}·¬…¢ù— Â^¦l¼úSŸu#Æ ðB4ÌÜÉüsÓŽ–EaæÜËQ—MàÙL|†´>ekÎùfk¡æÕN˜ÐnÇÌæ5Úº!œ¬lîèƒ!qÙ¡dËÅ!€IÏzV‡ þr^7BÙ¦øBÝ5@³]û¾­YҎ捻VDZչ¡ÉïÞâéöX ÀDz%ötFÅ“;õeWË¥ ÅSŸ#Àf~]˜Í³GL'…Âê¹Óιâ§Ë္ÀÊ¸Š‰6“- s–-WŽRñPp ·Èq”eë†Or{yÅÙŸ~x<‚cO†@•A˜¢iq(H7dö%’e©äÊË]t.ŽGÞ}o’@‹×%eÊ›JÕ„+œQûí&cN#žÒqq¿çrä"îëæðR°:«$æ÷ä½§7®õ0f•)/&¼õ#3”þ°bƒ@(a‹!¼ª~áÜ׆ȹÌs²è”¨°1‡û…ÓеSÑMY{*=bÂE”T9x ÿ*/¼,™#.‘£°Qû™­ù´“úèÔ³õ‘­ð—@µ}‘#!¢M¾œ‹ÉvD?™üû:ÛèÚHùLMÚacd¿E[4pÙ¢0-(üTP%‚s¢ßHšƒ«Õ²+ŒsÈV‘KJ¤Ë¹ü"OšªÀÄ!nÀÊyˆ=š©üÜêÛ“ÔmÓJÉÙÓóNFÌ£ËZ}÷…$¾jpUôö£TmÜMè4ƒ•„ôÚ¼â ;eg“‰%ÉûÙËþ6W¯[\uˆy‚ÁbÅÅáý8]†ëïBèx]VKÊn…Z2fâaÔl­R.÷?n_4¿D ú.o©¡ñ<_}qýSE¹ŒÀ3ÈGFn”¿.'ÖiÈ㰪؈•£jà8†ÜXX½Ù3*ÒÍb2nÂì;b}Ñ<Í je9…dM½r œ!ö³5Ÿ1Ý™¾/\Ekï"k¾s+Øü`;_‹ÒcmŒ\"V£D„¼¯€èâL)8z+ÆWír  ¥Óº!‡˜Z! ^Má)§æ´NÊEÇvBk:†3ŒpÏJç?ÅpŠ4©/Ó1ô¬¥dp¬P”<~>î ú¾á9`øýUp³ó`ÞwÂYÂÚÁâCPÅ€‰ùEÛÉè1s‹°ÃÉ–²ß‰VS 1–ZìdÚ`7,“/‰åb‘qmÒó½Ìmûê«¶žìòVãž &΂å`†¼¡Aµ²Ó0ßãP ³-_T²:œ.P®žh®„j<â:»æ}eSŽ8×Ç %d]ån¨W.5n¢+±§ý ¨,|)‰¥F©'ˆ™ke„—Y{´Þq¡Ú¬·™.;AqUQA ¯ÈE¼e†2úÁŽíoiìEòï"Ëü¹scØI×¼…صB–¡1ñ§n"W¨(5Ú {œR9Eá("U3O¾Ù© )¶)ˆÞø1øCד³Úe‰¿Ïü¶–+æ±íŸæŒýâ£T]Ý€í ±†óÝ1 ±¶a#ƒÍù`ì”l7á½Ó:Ó—$Plç\=ߨŠy%ï©K ›°ÙK`•85Ñð=·,üóEªÚGlÜ" qºçWü`Wjä |ÅUh‘T’ª‡¾»¥’³ƒ8Æ`A->ptžþ`Lîhba³¿w&Qií§‚{©ÔYu1ËV\o› š@7þ!Ý͜őÆÏHˆ:‰¼¤¬Õ«šR|òxºL¨Û–bPLÚÏÏ`#–È#³ºž&§¼ u^s˜ rßï`¦æSa²`RØ )n !f-Apb6sNW‚¶tׄ¾}:'ÁÐäQ„@žy*t¢ýÆÒÞÒs‘Èjò„Ѹ;PcûÐåü3pózòÑjis~À$R¯ƒ½Ýó¶y÷´ßòf‘/ÅîÉPp—duo.Œ¡S}p·%`¯ªœXüUQF†1Z/E§ñ­ýªùxJxFÜ- 0Í–~oGbJŠ`zÆâ…qËI!„õ î‡o£Ósó0XסM2X‰,G}–#º¢ÌûDe3žR°ÒJ±•é·«³ç%Ç-ÕÓ”ÝÐ^é°fx\LãS­Š9g³ö ú ÊÜ=«÷ξ5,Á‰ŸÆ$Ò«%'TC¡ É "Å$õ ƒkqqÄ/_åßhúFðC<$ÍïéŽo »ŽŒï8‚P@¶¥;Y?@#ÔTUÏÞ-Gį/À£ÍóæÅÅϾ•Z9•)=¼›£& kÛxÒæYaPPZ,nh´>zJQîA!üvÎ71Ä]‰\¦P¨ªÂ¥“Á0ÞÈÛ#᦮¹ÿę̀ÖËd”pƒ£ —[ÿÑßXjyËp/&1jŸ1_«Ñ°Ì#1QJó¼dвŸœnxsÙÃpO¤Ü†7$±–=]É áu©úMŸÚHp·Béuw´ÿÕœ©¨ŽR"ÞYÀòîõ4_çšmxH±ñÁ†îhæ[N`FÁp€ËÖœüëUqØžî´°’nàqè/¦I|ÔV/ù¤8Ñ’ÍT6ãKè‹ßyd¼w/`Áékè5&5‘@£ýâé$Ü_´Œ›ú´2Qþ¸m³¯Ã±,Zóîm§Å€%뼄!†-·•b`¤qæ…jP‘Rµ¼$O1{‰<7{íÓ}±=R{<‚-æ7=j­„¥Wù½T êRš yã’¨¿ÙÄ÷¨ËDÏ Ë miéæ… ôBÍ¡¦˜^œ90²¢†Âq¤…ôu,Ío¶Ì¿ùìšÇC¿Éò ÝÉÛbU1©Yiš© Ą³í \/>ºx~ññ˜Ik<=‹±ߘjÜf Â:'Ë8Ÿn¸L£ï/|»ú #}FEiX_0zÔ¨ð¥Øi!¿$ð÷¹Î„Í!þ¤&}8¿æú"Ç?u;²EÏq£‰`K8öuw›“ž2L{ŸO2§žÃ¸|Ç©”c½Û¡öRpAQs¥Û1LÓ“©íC»n=(÷å‘9ÚSB{]’¸nWVõÁùúŒ~ož§˜Â,jÒ©¶óñDÚV’µ>1…°åš¦UŸÞâ¼÷;‹€ü~aÍpMX9ø4w°‚›Ç6O3㊫AuîÌ"X ožT×â“5ˆO²cÆ Í0hCԢ܊¯1kΖð”eß§íçlUʧ}Bð¤9·~í)ÜN½X9>R‹Ò¸ê!VìŒà*ïì° ü¦Dâ`9sç­upÁâ y,† :Câ.섯žÎå¤Û»‹x®ÀÀƒ´B¬4¸.†«Ý"¢(”»p{ò!K ßnf–rRŠ;&^H°êî“ûÉõ#%ÁU¶Y ¦¸ý~= MYìøò䘔Còg+E#!óonfqrw7üØ÷;¤ÝÀ<ÅÆ‚]Q©™^$–Ò®ðÊ®Ç__«^‡L%ïW2=)YNZ´´„9 èûñH”vkÄIQ ›7Ô˜-ô©^††‘6‘ûSí=À ÐRŽ,i´'6ëëí%J:Žbvy H3â|qiwµ}Ù“‚ ù¦0ß-Ôã-AÍH`ˆ×XŽTOðšxX8Pî:ÎÞM÷b›ûË—:‚hå°MaŸ(øàŸK±/ =ÙMûJ×åNÔM_ÁÞ­àFô&醿œ¦Z;$–îËv¤Í@†Êƒ÷«¢„:ª†åbDñ‹®ãâ1%„›>m]‰°½¼.΅ᇖ:l K$—Òxé}ÿWä?؆u¦ E" `“Ûd›„%ËîxòK“‹¹0y´ˆ<”i+îâ—¤¢w²Ê:_éHtúQ,ñxV ÁPM{¿^%nÈ‹dÖíÁ¦³…#A¶a—8É‹ ÈˆÚåøªÃˆx5yÙœ*n$NYäÖeßVç qFênŸ9ò|鎦U§“@ß[zûÄÍ**‹Q-Ïu<ü_Å€L•ö«+¦¸#æ@*x‰qþMç¥>¤Âî &·&> ÿã y_Š*û¡jEᮂ‚ æ&]ä *Ð)u ÊôYºd¸I:žÌ_²Â;XÌâŸÏîD‚¹„ßR“©ÒÙ0ð‘sf§Îim8†/˜ôOÞpq~dVd!Ö f¬lï `E‰ö¾œrzW%>nNd\³^ˆ¯ˆ©OTó‚ÉIkµÄúçËU^ "uÛ#.¶Xo+‹iYÂt¯«¾°ŽÆ^˜žo:ú"‡#ø0ÁFûÓËÐÛ¨s»2àø²®ØÃ.77Ùñ;òB=ÿÛ˲óQ.l{u¡"F É_,I¯Äw4•J’–çIû5_œtœÜï ©L‘B32Vú1–ÚL\Ç µ‰P±zz¥(){Sã Ô{Äo°6U¬ƒ¥óœƒÅ—ê|¯¤³Òµa‘¤½²ËŒWõÙÀú×)]4q }u44à½*»²‰Ù¥&5=(ä~ZvT3Kõ5c” LëÀWïtà”#H¶0甿ÊOMbµ’h¿ŠÜ`e¸ C‹ð³êDk!qK€TèEiͳH⎖õ¦ÍáD¦?Ø/ʯ¬eéÄtø¹ œ‚nØ”‘¡±"tùY4 Íœ567cBPϘcͼ›ìS*¥OºýÑ{/At€‘Y]Ñ߯3É…Â)?)o”—XÇï\6Päú–}¿ÑIM,oÑfO"÷W‹‚¢N˜E¬=Œ™ZâÖ(É`…§2ªŽ&ñdæ›Äì" ç¢~ ^ª­,DUHZKÞH—“>ghÛŸ>E"rí—KÉ›å°O `¶ïü >¶Ý*Oˆé%ò-íªôɺœn "I ÌlNwžH|ãaN ’¶v ¤dÔ\FÏ»¤Åëµt²•~Þ]-“Î>t©s3ÛÍ%`¡§]#‘À„‚WÞ¶ƒ8 %øª¶yº š¯èâ!×f¾µ9`Àõ,Èÿ¡îž10nòòêõdË Hk%Þ-ÅëÄSÿ9Wiï€qÜc*âýÞ®'ªÖTL~,0€²­#DKú{r 4Û•ò(ïB•là9UC-òû¹È†D_»3æQB± é•a_ÙÃ}½Ã%ÀÚ†ðTwÈûýÒ÷”+Z]×»™â/V!0[ÚY¥˜g²˜•*j -WÆ‹/bM}h|ñ.Æmã! ãöõ°}ÀÊüC”P]NTH82:†K@”Øø•I£40vÕ–<-)YOÛÒ¢ÙÒ“Ó RK …Mh¾„TV¸@y«ZšÄ#$,<î>ö[¥±Ýœoò’N_óF–9ú²…¤«3î±DðµÑ5ßW"˜jD<à^HQH[An¸Ø*½qï$Õ6¾J>ÃWÿ‹ô˜­†ü¹¦å0õÚ¯µ©ˆd®ZîtIjW¥ 0£EN¹p© Dz—mXÈVŸmÊ=™ Þ™¦np-ËråŽ[(g¾R¶‡ì!ßHAöáì–OÞ¼†Àz\…Œ›^ÓdYdƒïEEá‰-fR‰^ÅSÓ«#9Ü ¨¯Ñ6{pÂ÷stU\e]œ¡ÊS7÷e¸£bhµsúúž( SZ`öæí÷MP&xÝ~Û¢ÅÚL©,Êå#iOýZD–12B#É,Ũß_ÁAše™[Ê9¸«42o–¯Æ/|3å}²pHê(OYªpxÈV°GøüÔZKŠÊÞUkcõ(IxÑ‚Îds$œü²w±õ)f%}õåäãéyW ¶·6-\T1RGx#‘%°™…ãZ.ž¨š‰ý„>–׋–¿øX7Ûóë.m„‚;; f6ÄûŸ;¦KÀÐOiÔqÞ-øŒJ "u­m&ôFFðÊ¢ü¶ßw|$t¹¢qZ—zHa)º:k.¼9|G¦‘—d/Ÿãˆ®ÿ’Ý;2QCTy˜¬OXNÍ8Wx[[ä§£ð‰oŠ^ͯÙÕNvúºÚø6hò>àníãG·L Â(K[4e¶jk½@+Ï+ ·ÿÍ2!l¯D‚RÄÜ«•mîOù-¤&wñîÚ ¹°í«Žl5øNg¦áÏe±ÞE=ÀÏÛ£š”˜»h{ûÜ·5Çg©R€NÏôˆ‹{ùILèÊu€™fÔ6„,/GÛ[‚NJz²;g*,xž¨=ÚM7¾Óysí•£IÌ´9L¥Ò÷€è¦þ㥖X¢¾QÐõC2uA’¡Çt9MÇÖ)±÷)û%­ù'¯S?ä=&Åı¨¤^¼žR˜‹@ôñÎñœ2¢ý¡þ2BªØx´ïÕŒÒ1¼1†­‹1¯y•;Í‘6xU1¬ ‘‚½ñ_]H™ÆŽ_0½Ì˜o_¿l"ÈlyªÒ1VþLì~¥Û¹e;WቋeiªÀXâQ79kŒ»tڻɱ$z>T¶iÊÛIå”ÝË$ŸÞx±¨ŒVÝJ%Õf÷Û¶ðxUïË_›0n 3~I$gɽ”æ(D/ hÝ­ ¿}í予Pݒ؆¼™æsÓÔi6~aƒN“<"$('ÊĆò 2WêuõG©IQIÌÌB…&õæ·ઔ[J¦_Ž<ìPlw<ŽÄ¡8êÚ;Á¾ v¨ŒW¶ÛtÕúÂ>›á±$¢#IÞÐÊžìÆÍúålyD÷¯ 6TŒ #p>°c«N'øÁý˜0û)ÓB,žÚRâ¿f–Eš£eš§vµ5XÛzâ­T›²—]ów%<à"‘/fÍ·j.?¤ºé´´÷DQT$‚¥Oñ;È ¸ ¬x¢i;ÌH)ÇùM{®yiøÍ`¶7¯z5 Õ;¬¼MŒý:ÕÖ1¬ã3½±‚v.PWÑkPîIg¢^þØÐ0¥oµâëÙYSã[ÛG)L`f¸Ú º¼oNÚ?Hi‰)*[­íëö"Š©Ù„þ°—ˆ‹…(¸üÊvÇ R8 îÀÕ ±eë ¨aÞ£ºÁ¦z ©7vxRIôrÐQygi-à&3š7Cò½šHwViVë=káQ(Ðé8BÚÖX£…àŃàØ};×Ïå?ë9±ýpÑ]p²¬xæ¸I(9Ð`ÛS«Èé‹b?Ô'ø…¡9…ÚÖ—·r]@ÿ;(9vg…yÔÓ·§#š¸ÿröì"³’mHá`~ŽIK5³!%qËó»uñ~+y£Ð­–ËCbÄä×ÕÝ–\³ßÙHG sÙž„y » a›cˆ§D➇˜mœ GáªÅ³ö¬êMN.QP36ÙâcüßêSHp '®íë´B­UæÑåpÿî¼’®þvùZÄΛƒ¶i[ñûJÔ/YC¬¹=‰òü7Ad[¡¾ îèŒ;œ®´a@/”kac+‚VŸ‚²ÉE+NvöãñKèn šàÂ~ª T7>×Xá…õ¶#a‘D½]šgãXK Z“úâ9âÎ-±Ó¹… û¾u²Ç†?BôÌôˆ‘(M_.ŠÅ‘)z{ð:”rœ4j§7¾hqrt½‚Ù1:8Ûýê‘Ò>ë/ñˆy 檿¨õçª)´žhdAøñA4ˆ8Lf¿g2Æ07 òí§¯I«ûì ÈÑììäÎÙð|ÃÿõšOƒñõù±B|@AËoTŽJÒ·ù»…ø¢ D«„È¡sL>ôuJB ŠÓ Ú'%…ófôƒæ¤Ì[…?YUÇ$¤}œœ‚ßÙ¡«÷ÄÇú¢Çø¡êm‚ŒAÕ͵©Š–DI¾ÌýXžde©Âø,‰FÞ¿qwKJ””m*¶pçAþm~š~)óÕhQð µ¾gœÎhÒþ[P©eñnÞú-çY’rïüÑú°Šµ¼± /ÒܻDz RFh•F°â_2=ÄfÑKÜŠ²Ü•šd8é8Lð3(߬Æ/óO<[í¨\Æ ÛÚƒ¤xbZP|íJMI®æò-  * V‰v-Ôwï¢+ïéIá^Õ RiŽ&ó°êƒòÅœH˜ÿA ‡Žœë"û¥kê‚1r!SXã?´Ý¢ÿÕX‰ ·„Ïî¹gìt2å«q'ÙQ¤oе„h£§EÝø¦”ËvZXk÷y}¤+Vµ”=J–@ø Aâ?-µ×>Ê^‚ìHG͎ݶò1Û â=u x‡4(†Ë`‘ÃÌëU¨}«Z&m}+¬ ~ZÌŸëܤś–zdXù@ÁøvMÖðËð±EYË/ËkÊÜ/$ß5áwÑëqrQH‹H\ÐqPg]V‰]0 lúö{Âsã›û¬ëÃpµ%À»Ää':UOY©!Ò#N«Ì¤áÞ|7A ÕB¬ÿ0«µ#ï†çýÒÁÿˆÿÄd¶ÈñøA™ ¾¡.?oyûk´r“§½'Æró qé…!î~êµ””ä5‹s’0…/§ûxëø°¥ž;¾;©Ü8ʵº{U×{(\ dS.J V4DD†ÕaêIjÁ‘É$­=UÿeJq(õ£À›uû@1$ˆØêy S¦ñŠñháñzÞÓ·sÔtÙŸ5¡ÜßhЍ"$nøoÍä)^ë yóXñÀfvŽäB€µz,­†|‘ÎkÑ5˜bÂY"Ù©Êéî…ù¼^ÆØ‹øož5•û¹‚=e"ÂØŸ&'³ðw1BûÓ{·såÀwÒåqJCnx3¶Õ×ò•}Q1ÙûÝÅA¾©¬T—è̘§jª´ÖÐ*ÌÙ‚÷Âæg,)3KÒX÷Ñö¤/`ñ_L~g‘*ºû~¼xp®pë÷IDX<Ú6Ùæ'Šû2}?~[ÈëóVsPûÞæ»…1zD’ŽÚë©Ò/³õ›J‡0‘~6a.8K$erZ×ìâ0N­z9zæÉÒІùÓ”ø±A·HT éõD 2ë’/ŠaBm$Ó`ÌmîI·Peê4xá•›¯cv³Ô"¢¡mÃ!誻/-åøŒ oqÝOi0»Â|ô×Å7þ²ê¼ùãÖI±g®ÃõÇmóg9øŸÌâ­@Ÿ®õ~ø Iêég`f±n¬ò+`•ôZ¢Œ L:ÞÇ»; ô¢‚{ý@¹™ ái’x¨¶JOv1»çú“µ©ÉHЮC%¬”&zöSgŒÝ4Òr¡t]T[½×ðÔnª ìâÑÓ7ÎÁT4ŒÁož(3 pF³³h•.²€›Ž9’Cä«`+£¶dØKpUþ°yÂ@(‚ôóŒÈZE±ÝvÒ“}X{›´¦Æ]4&<Ì&ÚIBзE;Ê#„œ¬¨nÅäÁ;¦"ÝK§ñúK{«TË|œ˜ÌLjbc¶Ì–°™ÒèÖFËoc4;éN ´Zd¦É‘ºæòœ„´b£ìD,ò8Áìíb_N–1M%É? TUñyâÒ׿»Ü ùÿ^Ö/ i–Ç#7m‡ ,çÂ5ˆû ÙÄUEéz„dªß–`°a…cPÁËŠeþ.ä÷Sð¢·|É;xµ${È„–‰§]úëP—Õ± ÐáÔŠ]7›Ù4» 0wÃ)$QÛÏï?¶Ô+-ID‹ÄJöSxC\£BñnË€æõˆ+uaû•; y°ìF”rè¥èN“€a>?<À7ài„µ¯WHj{¸ébÇßü›|ÏKªÐ¼ÊÊâ¨TßûùŠ.wêØ"±N﬽°5ìüÙñž€¦`Ó…S[YzżL¿³5kò†ág"%ËK°®ä‡âtzê`WÒ¼Êð¡å"Ÿ:G©jñF¸ñ—“êÚÎH4Öñ-Yý˨_Ì‘=íŸ)æ/Ñ–b¶aFØàœÓü#~ Ü­U øw GóbT¸Rµüد{S&—Îs Î nÊá3(ù؃„ðÑ67žÂL«ôøfØßÑðÑëc±ãr#Y3i¶‚ݸáî}¬¢‰ªÍk×_¥ç„hêß`Ðh¡LðJÖšÝïÓ Œ+íF=¼!'‚« !KnÀnI-} Åí¾¶â»8 ŸPsB…aý–7x# :µ¢ëÉ q¦ã•PLµ ×§ññ1áò¶mÓ ž¯ŒØÀÇê¸ÅQáÚ–“ÕÃ)ȸewÂSÖÜWWN r¨êš5«œ3åÌ[ѹn“Èé¢+–è%X¸–ìr,&èöÇTžÁôq£%ž¿o'¯ ¼SowÌÆæ*ë}ž ç L™“agL†Sz9áM¤X”t6É w¾/§”SOÖæ¨ÞåûÀ®]³íHÄìâ}áß§_Ò7ÇxV MØkM ÊN=Ûm~;$!$N–‰ôN+4²ÀÚzr¬ ßéÀ¸ú*v®•NáLûîÓÌR©]6AE÷îûŠ.#Q/Üò1“ÞÎBÃí±‚ŸëѨó6 t¿­v’Œvòqc©Ü4„©ÎcÔw¾ñ†ÿéÍÓŒ£Lî‹{¦L¸|YðMWÁoö‡ñ½$lèÆÆvfä&t%”½¶5ðù²"eÍÿ–Ì R. ×_›Ûɼµj…0ä®MOœE1½¼ý9Ñ>-¿³D‰:/.ßõ£¾—m~ 1ºÉSNP*`HÎjn›Ò™.Âj-3¥ÁuþF^X³Ù÷‹6—Ø`ç“ÕµJsÖçÔ®¤½nð+ÃrF”¿¦ ÆŒðˆ)_a@ÉœPÃWË–úw){ó~ªvoö?ÓÂd:‹"ËÓ´h§ÀòÄ}É™d0a-´‡¾‘fl>ë.EçÃì/.u¨’ìñh1Ì…î忨 ª6±hqN±¿wÕÒE3X†ÔÁ¦¯»‰˜êàøFT_ró›!ðýŸi èX 4¿güüázUô¼Ùˆõ+9vˆÎ[Ÿ&wñ¸ ³s™(>ì 9¤p‡sH!Ô 3w¶(éTKäÐùPåèá{Úê2ðÎÇÄì@“Ô(—áÄ7ÂFusÝ£ ü\Î#5æ¹ì˯ùÖÅ1XY‘ÔÚA†ìcæ,sÎ%<~÷CÁhEïÌëB %޵Y =„j¼U‘À¸‹¯ÞØP0Ö0kJ5½ µeŽa0·+•ñóÖ¨d¹ÛW3W|cälUf`àßJÂZÇøyt±QÖh“êU£E^×_…œÚÛ!øÂ¿+Ή­ÝÃf&.AsŒ:…ÇTwñS!àþž¼àöé½iBÄ;ê°Qžˆ-JKƒ-g’|›/‰ŒŸ„SÊŸ«ÜÐæ¿*Wv6ý˜a\•Ȉê,»ðÔ‰â$ÃÏç$÷È&OcÔ8¢çΚv¿„`Q‰ÎJä›óZÿ¦óÞ¾¹š ï$_Ia4=†$ÊW´¨v7¦jI…a{BÞÞ÷ˆ™ ?!d¥¸´·d wý?¥7‘ì endstream endobj 85 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.13)/Keywords() /CreationDate (D:20120912134101-04'00') /ModDate (D:20120912134101-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012/MacPorts 2012_3) kpathsea version 6.1.0) >> endobj 2 0 obj << /Type /ObjStm /N 74 /First 564 /Length 2968 /Filter /FlateDecode >> stream xÚíZ[sÛ6~ׯÀc¼Ä•`'ÓYÛ‰coËØI“&ãé0-3‘D…¤rÙ_¿ßH™’%ÇnÝn:6E<Àùpî)XÌ S‚YfKY*™ˆñŸ0¡ðï˜ÐLXËRŽIz–2©ÒŒ™Jq)˜Q–IÉl¢ñ€9R³4‰™4LˆØ0‰!¤Æ9¥Qâ(´Bœ5P8a†6$xjcɈ¿¥^h·è¥ÆÅ‚iŒ–Æ1Óè–¢ÑHÀRšé`R=0@£Ð®±˜!Ú°ÖëRÇŒc*NÑÒIf4SÄ¢Ð)¦ƒ³&ç&1-˜²˜»$kAû$¶ P•ƒÀB Ì´ÁÌ­ÂÐg@Sàg 3"°  Èt`SHt änŒb‰bÖѽa‰t¸Op pPIâ09•0‡‰ƒ9s òW’9e˜3Î 0u—€u.%­°4F¿Ä±TħÅ „„‚¡'4KL*Rej EAj¥8B(Lê,±diJ¬AŸ;xøñ3ÆŸ”/KƱu>lŠrö¯Hì°Ÿ~ºØÙkî;‘JO¨2 ÊDãddõ·… [µP£Ñq¤Pˆ/¥mD¤urgØÃ*›EÕ ì©ÏlutÙL'÷ _  •ùoìËxäù÷ªÉ~=à QMöëô}­«!ÂÓ«â=ïÚ5SŠº/ü "Öšé$EE­B–Tü1VŒø‰ ¡VI‡0‹JÄ9q{øÓ¬˜4åã*—U4uì¿ß_Te´˜»“Q]ì¬FÞº蓪õ"jP"|Ÿõò«º‘RºüQŸKÔíâV¤¥=<þv´4,RĽd¸meÀÍ™¸°vÿçø³Žó$üçJׯXNÇ´†‰£-%ÁhïG!æ*EåýÚ˜ÆÒþTZ¤#wÚüçŸÇ´·c‰Nž'|?:œŽ±Šp¡]Ê¥žÑû¾´µEÛgmŸïžOÛ§;4Jâq„xÑœ’Á¶àmßY:Åm‘Ѷx&´ý†g©¦ -ÚW£qt8#zĬP~¼DÒ.hÒ˜º³F% DL€ˆ¦õ/hª2/l‰XC÷tí°º1~Ï‘,…¥Ô0µ”"1Iè#l'ޝñªX"ˆã¹»!2!üÞ(Â!&œ¦nE‰a7ê {éëH¦LGÔîuD[à ‰±Ó—ב”þ¾³oh§-]¯‡N·tnŸu÷Ô×ÓÑØßQ©F[ÚÎmíöØœlí•èdË—xÑ==§¾ÔÇjinàÝŽAžfÃLqogH×N]õîfäUÕ=¤çMtULtÜÉ ½ùµfØÍ³“ÙRÆíµ#ŸlQz¦ÔŽ6ê¯ÖfLÜbŽ…·÷Ê1Jö]éVV!ù?˦xòöÉÁNÞþpðôìäåKãÑ$chöýÊsWÆlWúÉ`äÔÒÖK=¤u'°a›Íòb|ÙÞz¶+¥ðã&›ýÙx’³Ýå\“OÁ þ¦í¤q™UT9<à{|Ÿ?æ‡ü„?ã§ü%Å3þž¿¯²áǼ™äMw]QoN¥étšñϹ矰,à|ÌQ fM^ñËoóË|Æ þ‘Oø$¯k>å3>+f9/y‰ß9ŸÓ:Úî¯ÂØó¼*ÊŸO5ÿ´(›|ô~Â+^ó:ÿŒñêâ+oxó¥ä þ…åßøóªÜ ’;,0akûûßUÅÑ«×ÇûPÅvEè ,Rþˆâ[ªá€?òª8öÊxÎ_@!g^%o ”¬ùž^&¨ÐGXO&YuM=å¢êëèJKnÒS^Ѥ:ÕlÑJ=ÉêKÒÍe•ç­†3¬DêaYåü³W×5e¹»(ëtÿññ³—?¼:}ý"ÃüFEy²»_NF›õ&P–視 XíÎwPO»Õ%²¯:k·¨NHÕÓ]²¢»}èí¸ÕÔ/üµw ¡÷1äÜ€$[B $¸¦3à¾8’ø.âøõÅ›“ç/VÅqZN³-â€cìÒ :K nª'aVÄáâ¾8Ü6Kvº' 2ëÍ–üįA×­¹“P°Ø^<™ŽÈŽòY8}N²)YnÿÏ9¿˜tF|Íxï_>-ÍØt7&ö´Øn6ñÏ[ÂP"ï¢Ê£·GGÏ®«r÷l’ÍšßPÿÉJ½J·ÒjÐéÏÐêÓ5½’í¿á¿®ˆBßɪ÷Nöß®Y5!Ý"¸ œÜ@N®EO‚{HÕŠ“‹mH\O$§+„©·yòÌOw³S*ìÙçªïwv´´žimÈ_gÃrTÌÆ˜@qq‘Øi»úôn1AÕÒ: ªÄVʨÅÖbj½ !Óõ.ClÛû˜w8o÷äÌ$Á½:¯hýƒYsÝÝYbúÖÁœ\7–&½yÑFÉ+qòÓ2R¶r¢.np\z]µŒ>Žœ_·ºÞ[1j„ìguîwf6f+fJß@ø-ÿâª2 ¦`Ž'Y{#$F{]ŒšËš>¯Øhô7²_+FÖ˜§ßa/™ÛøîÌoH®«8±ŽƒæF!ØàùKû¥Bî ì†4·L­“}\¦‡KÞ®íj ×5«Ñ۬ƪ{v«d²Ñ\Ó©éAtéBs „ô¦­¦Wm zO6à?£zù´}6M×ôù¢™ ÆÔ-ÖÚé®Ã bÙ¯@!LŸx…wqôÍ—¿j_ÒuwUþ™¾ ê# Õ²c¼µcû­Ì3ÚYöú Ý‹@f7 ºmàm–¬Wº%®§‹Ž·—@Ë»Á®ê†£Ä ù>xTwÏš¬jvè5òê *¼}|0¼Ìæ¨ÿ}“j›V¾DÑq¯uã7Zô(V^þëV¯ü¤˜Í¬ëôç듘Ãv™ Öîå}7wu¯vè»7ßÿ‚K­5¡[²Ö„žB¬#ìxöÉ®ë„%ÌÚ°f‡>¼[¶ß£Oº:øEfê‚иI~›FƒÎm(8 áI9‡\¾±î¼lijaŠNuv8Ο–£œ¿ªó+‡|>Ïgá }IÙ²ú–¹© endstream endobj 86 0 obj << /Type /XRef /Index [0 87] /Size 87 /W [1 3 1] /Root 84 0 R /Info 85 0 R /ID [<426AD3D315CAE99CEC7D0C21BE3FFAC8> <426AD3D315CAE99CEC7D0C21BE3FFAC8>] /Length 213 /Filter /FlateDecode >> stream xÚÑK6ÂÇñßý“T¨H*‘<zÉ«ÇLœ†öÐ:²m ¡m·“øÞÉç|÷ÜsϹ’4 ¤@fŸSQ+ð¬Â=ÌÀ,¤¡ !˜ƒt ó(Ä`a ‌Iq¿ 7° mHÁ5\Á%´` n¡ ûpë5%~|i6¡Û°‡°aÊg}nö [P„#8†&œ@N¡j*}û‚3Óû›×¹i4ðº0MÊ^5³ê‡WݬÿëÕ€;x„<Á3¼À«Ùpüÿ£¯þ’= endstream endobj startxref 107269 %%EOF gdata/inst/doc/unknown.Rnw0000644000176000001440000002336512164370064015307 0ustar ripleyusers %\VignetteIndexEntry{Working with Unknown Values} %\VignettePackage{gdata} %\VignetteKeywords{unknown, missing, manip} \documentclass[a4paper]{report} \usepackage{Rnews} \usepackage[round]{natbib} \bibliographystyle{abbrvnat} \usepackage{Sweave} \SweaveOpts{strip.white=all, keep.source=TRUE} \begin{document} \begin{article} \title{Working with Unknown Values} \subtitle{The \pkg{gdata} package} \author{by Gregor Gorjanc} \maketitle This vignette has been published as \cite{Gorjanc}. \section{Introduction} Unknown or missing values can be represented in various ways. For example SAS uses \code{.}~(dot), while \R{} uses \code{NA}, which we can read as Not Available. When we import data into \R{}, say via \code{read.table} or its derivatives, conversion of blank fields to \code{NA} (according to \code{read.table} help) is done for \code{logical}, \code{integer}, \code{numeric} and \code{complex} classes. Additionally, the \code{na.strings} argument can be used to specify values that should also be converted to \code{NA}. Inversely, there is an argument \code{na} in \code{write.table} and its derivatives to define value that will replace \code{NA} in exported data. There are also other ways to import/export data into \R{} as described in the {\emph R Data Import/Export} manual \citep{RImportExportManual}. However, all approaches lack the possibility to define unknown value(s) for some particular column. It is possible that an unknown value in one column is a valid value in another column. For example, I have seen many datasets where values such as 0, -9, 999 and specific dates are used as column specific unknown values. This note describes a set of functions in package \pkg{gdata}\footnote{ package version 2.3.1} \citep{WarnesGdata}: \code{isUnknown}, \code{unknownToNA} and \code{NAToUnknown}, which can help with testing for unknown values and conversions between unknown values and \code{NA}. All three functions are generic (S3) and were tested (at the time of writing) to work with: \code{integer}, \code{numeric}, \code{character}, \code{factor}, \code{Date}, \code{POSIXct}, \code{POSIXlt}, \code{list}, \code{data.frame} and \code{matrix} classes. \section{Description with examples} The following examples show simple usage of these functions on \code{numeric} and \code{factor} classes, where value \code{0} (beside \code{NA}) should be treated as an unknown value: <>= library("gdata") xNum <- c(0, 6, 0, 7, 8, 9, NA) isUnknown(x=xNum) @ The default unknown value in \code{isUnknown} is \code{NA}, which means that output is the same as \code{is.na} --- at least for atomic classes. However, we can pass the argument \code{unknown} to define which values should be treated as unknown: <>= isUnknown(x=xNum, unknown=0) @ This skipped \code{NA}, but we can get the expected answer after appropriately adding \code{NA} into the argument \code{unknown}: <>= isUnknown(x=xNum, unknown=c(0, NA)) @ Now, we can change all unknown values to \code{NA} with \code{unknownToNA}. There is clearly no need to add \code{NA} here. This step is very handy after importing data from an external source, where many different unknown values might be used. Argument \code{warning=TRUE} can be used, if there is a need to be warned about ``original'' \code{NA}s: <>= (xNum2 <- unknownToNA(x=xNum, unknown=0)) @ Prior to export from \R{}, we might want to change unknown values (\code{NA} in \R{}) to some other value. Function \code{NAToUnknown} can be used for this: <>= NAToUnknown(x=xNum2, unknown=999) @ Converting \code{NA} to a value that already exists in \code{x} issues an error, but \code{force=TRUE} can be used to overcome this if needed. But be warned that there is no way back from this step: <>= NAToUnknown(x=xNum2, unknown=7, force=TRUE) @ Examples below show all peculiarities with class \code{factor}. \code{unknownToNA} removes \code{unknown} value from levels and inversely \code{NAToUnknown} adds it with a warning. Additionally, \code{"NA"} is properly distinguished from \code{NA}. It can also be seen that the argument \code{unknown} in functions \code{isUnknown} and \code{unknownToNA} need not match the class of \code{x} (otherwise factor should be used) as the test is internally done with \code{\%in\%}, which nicely resolves coercing issues. <>= (xFac <- factor(c(0, "BA", "RA", "BA", NA, "NA"))) isUnknown(x=xFac) isUnknown(x=xFac, unknown=0) isUnknown(x=xFac, unknown=c(0, NA)) isUnknown(x=xFac, unknown=c(0, "NA")) isUnknown(x=xFac, unknown=c(0, "NA", NA)) (xFac <- unknownToNA(x=xFac, unknown=0)) (xFac <- NAToUnknown(x=xFac, unknown=0)) @ These two examples with classes \code{numeric} and \code{factor} are fairly simple and we could get the same results with one or two lines of \R{} code. The real benefit of the set of functions presented here is in \code{list} and \code{data.frame} methods, where \code{data.frame} methods are merely wrappers for \code{list} methods. We need additional flexibility for \code{list}/\code{data.frame} methods, due to possibly having multiple unknown values that can be different among \code{list} components or \code{data.frame} columns. For these two methods, the argument \code{unknown} can be either a \code{vector} or \code{list}, both possibly named. Of course, greater flexibility (defining multiple unknown values per component/column) can be achieved with a \code{list}. When a \code{vector}/\code{list} object passed to the argument \code{unknown} is not named, the first value/component of a \code{vector}/\code{list} matches the first component/column of a \code{list}/\code{data.frame}. This can be quite error prone, especially with \code{vectors}. Therefore, I encourage the use of a \code{list}. In case \code{vector}/\code{list} passed to argument \code{unknown} is named, names are matched to names of \code{list} or \code{data.frame}. If lengths of \code{unknown} and \code{list} or \code{data.frame} do not match, recycling occurs. The example below illustrates the application of the described functions to a list which is composed of previously defined and modified numeric (\code{xNum}) and factor (\code{xFac}) classes. First, function \code{isUnknown} is used with \code{0} as an unknown value. Note that we get \code{FALSE} for \code{NA}s as has been the case in the first example. <>= (xList <- list(a=xNum, b=xFac)) isUnknown(x=xList, unknown=0) @ We need to add \code{NA} as an unknown value. However, we do not get the expected result this way! <>= isUnknown(x=xList, unknown=c(0, NA)) @ This is due to matching of values in the argument \code{unknown} and components in a \code{list}; i.e., \code{0} is used for component \code{a} and \code{NA} for component \code{b}. Therefore, it is less error prone and more flexible to pass a \code{list} (preferably a named list) to the argument \code{unknown}, as shown below. <>= (xList1 <- unknownToNA(x=xList, unknown=list(b=c(0, "NA"), a=0))) @ Changing \code{NA}s to some other value (only one per component/column) can be accomplished as follows: <>= NAToUnknown(x=xList1, unknown=list(b="no", a=0)) @ A named component \code{.default} of a \code{list} passed to argument \code{unknown} has a special meaning as it will match a component/column with that name and any other not defined in \code{unknown}. As such it is very useful if the number of components/columns with the same unknown value(s) is large. Consider a wide \code{data.frame} named \code{df}. Now \code{.default} can be used to define unknown value for several columns: <>= df <- data.frame(col1=c(0, 1, 999, 2), col2=c("a", "b", "c", "unknown"), col3=c(0, 1, 2, 3), col4=c(0, 1, 2, 2)) @ <>= tmp <- list(.default=0, col1=999, col2="unknown") (df2 <- unknownToNA(x=df, unknown=tmp)) @ If there is a need to work only on some components/columns you can of course ``skip'' columns with standard \R{} mechanisms, i.e., by subsetting \code{list} or \code{data.frame} objects: <>= df2 <- df cols <- c("col1", "col2") tmp <- list(col1=999, col2="unknown") df2[, cols] <- unknownToNA(x=df[, cols], unknown=tmp) df2 @ \section{Summary} Functions \code{isUnknown}, \code{unknownToNA} and \code{NAToUnknown} provide a useful interface to work with various representations of unknown/missing values. Their use is meant primarily for shaping the data after importing to or before exporting from \R{}. I welcome any comments or suggestions. % \bibliography{refs} \begin{thebibliography}{1} \providecommand{\natexlab}[1]{#1} \providecommand{\url}[1]{\texttt{#1}} \expandafter\ifx\csname urlstyle\endcsname\relax \providecommand{\doi}[1]{doi: #1}\else \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi \bibitem[Gorjanc(2007)]{Gorjanc} G.~Gorjanc. \newblock Working with unknown values: the gdata package. \newblock \emph{R News}, 7\penalty0 (1):\penalty0 24--26, 2007. \newblock URL \url{http://CRAN.R-project.org/doc/Rnews/Rnews_2007-1.pdf}. \bibitem[{R Development Core Team}(2006)]{RImportExportManual} {R Development Core Team}. \newblock \emph{R Data Import/Export}, 2006. \newblock URL \url{http://cran.r-project.org/manuals.html}. \newblock ISBN 3-900051-10-0. \bibitem[Warnes (2006)]{WarnesGdata} G.~R. Warnes. \newblock \emph{gdata: Various R programming tools for data manipulation}, 2006. \newblock URL \url{http://cran.r-project.org/src/contrib/Descriptions/gdata.html}. \newblock R package version 2.3.1. Includes R source code and/or documentation contributed by Ben Bolker, Gregor Gorjanc and Thomas Lumley. \end{thebibliography} \address{Gregor Gorjanc\\ University of Ljubljana, Slovenia\\ \email{gregor.gorjanc@bfro.uni-lj.si}} \end{article} \end{document} gdata/inst/doc/unknown.R0000644000176000001440000000627312164370064014741 0ustar ripleyusers### R code from vignette source 'unknown.Rnw' ################################################### ### code chunk number 1: ex01 ################################################### library("gdata") xNum <- c(0, 6, 0, 7, 8, 9, NA) isUnknown(x=xNum) ################################################### ### code chunk number 2: ex02 ################################################### isUnknown(x=xNum, unknown=0) ################################################### ### code chunk number 3: ex03 ################################################### isUnknown(x=xNum, unknown=c(0, NA)) ################################################### ### code chunk number 4: ex04 ################################################### (xNum2 <- unknownToNA(x=xNum, unknown=0)) ################################################### ### code chunk number 5: ex05 ################################################### NAToUnknown(x=xNum2, unknown=999) ################################################### ### code chunk number 6: ex06 ################################################### NAToUnknown(x=xNum2, unknown=7, force=TRUE) ################################################### ### code chunk number 7: ex07 ################################################### (xFac <- factor(c(0, "BA", "RA", "BA", NA, "NA"))) isUnknown(x=xFac) isUnknown(x=xFac, unknown=0) isUnknown(x=xFac, unknown=c(0, NA)) isUnknown(x=xFac, unknown=c(0, "NA")) isUnknown(x=xFac, unknown=c(0, "NA", NA)) (xFac <- unknownToNA(x=xFac, unknown=0)) (xFac <- NAToUnknown(x=xFac, unknown=0)) ################################################### ### code chunk number 8: ex08 ################################################### (xList <- list(a=xNum, b=xFac)) isUnknown(x=xList, unknown=0) ################################################### ### code chunk number 9: ex09 ################################################### isUnknown(x=xList, unknown=c(0, NA)) ################################################### ### code chunk number 10: ex10 ################################################### (xList1 <- unknownToNA(x=xList, unknown=list(b=c(0, "NA"), a=0))) ################################################### ### code chunk number 11: ex11 ################################################### NAToUnknown(x=xList1, unknown=list(b="no", a=0)) ################################################### ### code chunk number 12: ex12 ################################################### df <- data.frame(col1=c(0, 1, 999, 2), col2=c("a", "b", "c", "unknown"), col3=c(0, 1, 2, 3), col4=c(0, 1, 2, 2)) ################################################### ### code chunk number 13: ex13 ################################################### tmp <- list(.default=0, col1=999, col2="unknown") (df2 <- unknownToNA(x=df, unknown=tmp)) ################################################### ### code chunk number 14: ex14 ################################################### df2 <- df cols <- c("col1", "col2") tmp <- list(col1=999, col2="unknown") df2[, cols] <- unknownToNA(x=df[, cols], unknown=tmp) df2 gdata/inst/doc/mapLevels.pdf0000644000176000001440000030524112024144454015534 0ustar ripleyusers%PDF-1.5 %ÐÔÅØ 26 0 obj << /Length 3580 /Filter /FlateDecode >> stream xÚÍÙŽãÆñ}¾BüÀ V »I6É 6°ëÝ5Æðï8¼öGâHÌJ¤BR£¿O]ÍCjͱky ººØguuÌV³`öÍū닿½³YægF›Ùõí,L?޲Y’f~jÒÙõröÞûþåO?]ýðÍå\Ç÷Ý›½ùîÃ?¾åò%o/“È{ùõõ¥J½¾üýúÛ‹7×ÿ½P0Y0S³8ò³LÃØÆR=[l/ÞÿÌ–ðïÛYà‡Y:;PËí,J•Ÿfnfï.þyŒ×k‚™Žü$M.ØŽ…~dŒ¬7ßíÊjÅ‹ÚwŦe¸¾å2çâ6_tuƒë¤Q*³¹ýLñp×ë‚Û¯–y']wùâC¾*¤¯>íËZnî¹Ã7 R¥XÁ|\¯›ÿäÕ¢Ÿ\E~Á@2Œ†<ÂUÕ5õr¿èʺ’æÑÑ|È‘që·´'Øo˜Þ¾-P=™w]SÞì;ùÕÕŒn‘¸DF—ÕmÝlsš”þóä8R°½˜§Ûö¤ŽRï¦èEQa%ƒº¢©ò ÿÂÚªh¸²¨—EË­òj)¸uÞ䋹kŽŽú…‰w—oöÔàÒ/|XXËÞ¨b¼·eÓvÜ‚ð¯”N¸ÚbÉ0ëÏ,‡×¯:ŒZ5CŠ Z;mÍe]Á*L ½—›n]ïWkû{+á<èh\Ö®­V5,>LŒ·)? 1“¶/.çQzݺ(þÁ‡›ðî°Üµâ+¿^”E%Ö—°åmëZÞÐdÄ ÈßPÁIóŠÑ·È¾ðqu—Ê+sWÐ:‘Æx/—Ëy'ßlî/•RÞ çÉ®‹~É 8s\ÙæÕ=C·ûŠ˜¿å*í!ȼ›¼•¦?sËìÚÑ@õ]¹´#/œe׈G¢˜½Ô²OÀ õaWq{ïà$»r[´ü³?NíUE±ddç<ØCÝ|À‹{‡²[34º!Rã›þ†žoÃUƒ PnëâØK°Ž4å{&VÈdFÒÚ+Ú]±(é`¨áaW›Ò‚ =Í‚¿ŠŽ»!;¯š|‹äIt8È]ì; ˆhy–|C÷0Äl) >z¸»Ž©Jl§ƒ »h5bݳ‹¶R½å6€náFn– ¯ó»Âþ—þm¾-\s·‰Ña07!¨-Þ\Ô:óàä `‹V„u<Ö*Ò¾NS˜„¥'ÜŸ¾|ßá]‚ïNÊ |­CÞG™¯“ÐŽ`ï_¯¹Ê”uÄ{ër,lJ«B/¯¸¾ïÊMÙÝsÅŽÅMè z$â5Ó ÷j@å¦J–à²r(ÛÈøQÛ ±ŽµÛNü8QÔJ'` $³Ð7JX]9ˆcü$‰góQ+«¨iþß‚8ø÷e¦uªE*"uø¡|—.žƒ=dLCF`‰F~M'¼ZÁöNpcòínS´OPÔ–Ú§\)_©ðéL¢hc\¸¨g~˜Fv<ä•%Ä*3Ô÷]H] ¿*ª¢)\x‚»,…Ï‚-9•qxíLâ¹·ƒ©¦zΕm-àC=RÃ×8„Ï’ž=dG#k0Zµm‚®eðæh’âÌ$1œrhúIºz‹À,6yÛ¬Ö望ýÇÚWZOe/ ¶H*”@ÐI‰DùAœØéðK9Èα8û©~Œ`/™m³”mwRúðݎȱ%R8Èø*ê×UßütºìƒXœ÷žÀzÂÔ¥ Š»²Þ·¨XLœy[0;€uP1"í,Uñ×@U‡ÙCwáØÞü‰ ‡©^æŠÞƒšÕxŒ‚*Œ"±âboª‘•yìý¦uòŠˆ|Ó±y•oùšÏæ2ÁTú¡ÚŽU,F+îT}úõ¢½ú ‹ÓhfhØ›bÜ›áEî4ÁoPƒ¥csÂÖØt…Š˜Ö‚Â[¿«Û¶¼a;þ ze1€U«ç3²Ö °Ê͆!Z”p²M‰V'‘›œì÷0±öqy_ãñóo²´1í˜cš»lr§^Õ~`âñ…rIÉï{æq¨UãgƒŒÄƒˆS4<sú–c©ÀW¦—G¥‹­¨¨è“ðFû¡éå×!—Kk¯ ¢Æ±Œ¹2‘é#ƒa*ίé!z&@ƒ¸¿tÄ[‡ v4–æ\Ü:×d ˜HæÉÂ1ôU=,áÄ”ù\Ùr/ëâèšÕCÊ‘ö“6›úÀ¶0TÅ*×j]ˆÕ±>ÑbY[!xbK±€ž \ìzßMãí~±žD6FwÈš5é‰)dßù ¸ÌwKê›5°¼Øoß1-K_TUzêž°ÿpΠÛè§\ à_à{%å îŒàËSÔ¯§¨×‚¢åN §ÖAÅb𽇖Øúwî/¹ø•‹×®s;wsþ>á•AÆ;{`v=SÒâ㘴Ï,áûrrNϤÑù½Eñ?ÍEÈEä’£`úEÑ”W¯H_dÞ¡àR\9€ÈáÅ?äjÄÊ:£lu#TH7Z÷I&œXµ¨‰3Ö¾tM^µèÛrÕú7ô«ÆÒ  ’-ÚŽ´%‚«¢s]¼¶ìÁGÚ°t@ nÊUI«Çš*…amõŒpa¬ûK1Äí´BÓíØxhâQÞå †òl Y¨õŸ¬elà`¤ÿÆLòˆLq>ì“Æ­I¸þÂ,öƒ°_XaßËý#®\Lð…Õ çzéz½>Û+| ×¯g{E®^#«£;¥î_§¾îBXÔÚ(íÔ÷ý’[Ú@y3t|\Öã@§<—gESVràÚ,_`IŒmÞÜs¥&lº¼Z(—M(Ñ@üu túh ›Ïbó\GŠâ‘”á"ïGsb–0j1%ëeóS‘š$µò–qâ‚ Ô‡S„ô~ÉÜ„¡÷õèJ…1k]¹ï½Ëbp±â’ƒ@1½NLþAPõ‰7iå˜ÇÞexЮ°›ŒWe9Є¥#¥J)% ì³ëàT6Œ½bÜÒ¦]Öä”ÇàDó @˜€÷¸dT=ü)ÍÂ9_¬)˜ÈKpý‘8É‹ÙG±YlÌLÃúúÃJ„«’ÀiRdàg~BÚ z ~.™ àÁç÷nUa†Pg#Wg!ƒ/ÏÄÃÈÔIŒ8˜ÈýqÚn‘»–©À1½šÂdç\¤}J# œ­q"ômýñLôynÄ{ù4«½Áúé®Ò(â§¹¦O§3¾ÆöÈ0}@ÇL}‚§Ç® a=N¾?Ï«| Uþÿ<¿ì!ÏïÕŸf=ëDÉ¢~ÙqæÂ‹‘ay`DŸê'4ª‰3YCLž"Ö\é_»ÌÏ+4U"õúP%*lIãiy€M"ÌÒôð8cÒ’–èxh”í*.ȳЉ²ê7Q£WIP™dæ!h³+Û¡`@¤>‚kNZ$ÅŠæœ뉅ïöèRYÜo±´ DÚ #’f°o†l&6e3± åÔ-¬A²T|9,™¢ØúIô»È»½MØ"Âþȹ¸!Ÿ0ÃÄòR~s¡ü&*m¹Zw/œ·È S±e„-@ˆÓ?YÄþ¦à–ÄŽC„¾JãGS‹FMŒ ý¤‘ÈœMãcÍœxÉN@첦£,›Ï€ât¢ä²ŽX{ŽlRuÂà>¿fÆgXRò¨€o ¦›}ÍÔ–Ý>ç(ÅÙP¬<»6ÚÃô¡—Ü™ë‹C±‚ÀqË’„ã챟Æ0`ì›àäeWÍzçúQš€Yã§™$œ†X 9¬EÓöï±`N_MoËc_$™c\§i:š~¼íÿ†¦› endstream endobj 45 0 obj << /Length 3425 /Filter /FlateDecode >> stream xÚÕksã¶ñ»…ÒOòô„/L›ÎØ÷È\æ.IïœÎtœ| %ÊR*‘Š(Ùçß],øè‡ì&ÓKX,ö½P4ºE£ïNÎ/N¾~§“QÂ’XÄ£‹ùH+–$bdlÂllG³ÑåøóÏ?ž}:•füïÓ‰0*2ãg?ýôþ‡ï`¨£ñ‡·ÿzûá3õ|Gí5ïNŸ½¾8åvüã§Ó_/¾?y{qòû ‡å£o–‹YdÅhº>¹ü5ÍàÙ÷£ˆÉÄŽnݛ둲œÙº«Ñ瓞Dí¢‡;М).hÿ8h!Ç¿D::åã9ü8AþÝ ušÂo ¿ü ømáç?š6Ý¿ÀïÌ·¯ècì¾9½ö ø÷  ®[ˆG£‰€=džp¾tXòñ¯4Ý5o¨yß㜳Dkúâ¼ÁïÆ·+ø•ðû¦3Ãëj"ÂÀcpH5ñLªÿÑT;6Õ΃TS- 80œR]4ÞÏÿ£d|›AË£ñm±ý‡,w ‚íË’`ótº+¶å+„›ú›<Ëfô|Wä*£ñ4Ý¢@eóýÊíhR¡ÐÞWê&×°Lv‡½x<+’;ê,Ò›¬~‰Þ)Óµ•™«˜S»Ên²UÉ`èñ…G>drzØÈ[«܇‘ß»À2›ÛB±Ù.Ó]¶º£ÊM6]Îï–ùuह ``~7ï*xl‡§#5ÓœW_á®÷¢›ˆ “–w1^g9î<±ã%î,z¹ÓݲÈ鉣IRŸœe,„·4,âú~ÄùøÛG)™F‚èàýÜ´˜VhËP@ÒZ‚Ô&”J˜1q…e±…=ÙêÈ„åãêÀ2ÿd_fÔZn:1Lˆä¡=“" ࢘Ö5.ó}>EÒ3¿ç„3÷í=Ù›2½£N[;i€v¹ó­ßd[ÿÅ.[ovÈy4*¨…]~óhM‰ÊðÂo±t 1¤.yHLü C„jéàîþ8ûë<…‘ôî=<3€ö!^Gš·×•Ò=Ú¼§¯Ï® T…Êšqö%]oVõ`—å³’N#b¥[ÒˆH.¯öþiº*‹aµ<]¤ùu3jÐØ%‚ ‘Ϩ“VéXyF¯e«Œô>ýtHg Æ7t4mŠˆ˜ñHT_|åu£°LpÙÅþ§–X)“P„•@;ìX%>a³äfb\µ\·9­$A,™–âKaêõÙjã ÐðJ‡›ô:#ÉC-q[ìW3ê^ý_ê ünÙ})òzãÛ°9o=ꥨkþz:áàz©¾è©š7­G´Êy¾G}œÊyç­Zo%!„©ÍßÚ»Øø}x$/Cðc…­fð~—QûlÁeqâ Ã_„ët"݅Ω.1,Ü!‡“‰‰4äžZô°-÷Ó…ïM³<Ý. ÷wvÔ}ƒ_G]ÒšÔwJŽ&B¤@·LBç§ %¥5îµkÄ^âfŠ*R„§ä¢¥—°Æ–>Š+' æÙuê°†·Ðë ¬†Îú>Èh û|æVÄÝ8¯{Þ¿˜f¥,Ëë§,ÓÉñP3¥“¾TyAŠ„t1ŸVk ÓÍø*u.ô>}Eí=<Ç£”µ}<Ó £GŒÛš}Û—;Z}Zä;B!ÕL8|Gª«9Ò²\^çÞÉrN·HkFp\+îöšßms8vEÐfÂæã:¶ø’(ðgkã¬$# LvSšÅ¶'.ŽË•Pv:a‘â÷-™0¥ê°a·Hw4Û:ÝMÔíÊ/nÒÕ>ó«VdÚ:é!<ˆhei¨€žsâ% ´5Ò[’V"(Ž}艃È;33zâDÚRÈ!¦ô³"N›¢ y¹¼rq VãcKÝöú8v>´• ÈˆvñN€UqÇ pk ½¯â+™÷¢k)¼RS;ÐQA#nl]ÄêìÚ„D8ˆ(¬ ”)ú1)gQ"+Ü~p69`k€•U›SqÂ÷ù¤åÌÈžOZéTˆë»‡Þc“2Qº¯–îÌD”ƒý’¶FýŠÜûHúkßnC7¦„†Âi&£¤íÞæŸçÊ™5J¯W%¢«unKôþeÔ±–2êÓ¦J}ÈÈÓ m¢!ÚX´íµšE´~ ÛÞV†h4©æèœa˜Vœ~­DG×éñ§¬Ü¯PKvöÁ]7/b>tžG´ ÔaÍtu›ÞUýÀò:b‘yêNÁŠ&,î)AŸòÀ$ø¤”p„ÇO2 L°ÉfÞ¦À“*3†LŠù.N1Fí±Ë5‘RóŒ ¿ËÜÃÚ 'zîæN+ Ýòo„óo&Ãg•Y´‚2‹FW™E£)Íaâñf¿#@“ЂËÁÓt@È#ÙÉj-ï 1%‹…¾_°1n­9hæpç[æÃ™JJÖŽ›BGj,3Æö\‰Ü…gÂg­ Seѽ¹n6=ÙSä¡Y+àÀxå‹Å?Ãïm˜Ys&"Øz ³¿îðÊ“5÷ 룞Oðûy`ÁX°¸ñXHÕyÖøì¼v¡c°Kìxu°À9\ÖY»XæŸôÄ;õªœz{bÇqê].®öåœ%„=µ8QÑ mËÇZ÷ô£ÜÇh%?áOìÀxîCÉWM0*šRÅ«Ðv1æZ˜'0Ócgz§µ¯}ûÆëÿI»&WÐË5öòŒ½#–«¢^§D(íH¦!ôJ„¼.F#h(ì‚9cI°@ø©8 ˜N ³ãp2ã‰ëŠã×’(CEµ‚¸?%qbˆØ´Å“Ñ>ÿ³ÑžöÄtÖœjêbÞi¹ß' 3a­Ú“ ;ßÓ„UŽŒcó<ÅKà)Ôb>—Ý¡ÿ¥[³Ã H‚ä!H9R?›:—µ5¨¿liA)ãÆ¼7>ïE¥ûÔ¿ô{ó¿é}¯zãðóùåáü¯{ßËÞ8ü|8û qEÌyS —\:—Trå"e»H;¾*- ¦›÷ÙÞ’†h#nW tÉL@Âeû»&Oe öïgÝfٔؾ°ë¤ó‹«:A3Ãã®»ò[6ݹ æðŸ¢2ŒÛ—<284̰ƒì%\>‹"é†n³UZ™» »›¤u!š²˜îݻР`Á¤“QLróB¹ÛÔ3æaÝ¡×É£ù0bÖÖ3~ªæ Ì˪¢û„ïS6½›®ÜE,Óé~ë«J·.&Fè*˯1K$í@éâ3Æ•|af4†[V,"$³@înh]øLt¯+Iª{]r7a’ï×W.èn]gšëM‘cFäëi8í×¹vÙ÷BzÈ@&žtüü¡ã·ÿ“ã‚ÆÎ–ƒx˜Ä¼³Ù+d.·YJÌçË,ŸfXg¸ö¢ÀK!8nê!8À«®·Ä;$÷då0í”ͺw2ª×¹ BV],p÷uÔÊJ¶uô7¸ͶÅ*TÛÓ‚×tç­ÃqÔhÍeË'?F—u“O!“¯˜nN¢¿ÜseÄJwUãåk±LŸ¹Û × ìL/?`'8³ÍÆÓ—Þ8h²Ætyb•Äã]VÒ6•ø¼B§E;-çjý¢_ëŸÒ]G‘r «p>G7Ë~‰"‘WüÛfÈW]†œxîÂp,æöŽÄÈâr(²°`j:æˆnî¯Êl‡Q¡y6Óí™¶¶ƒ„”¨9ÖWË<|•5n'—tž¤æ¥Ó/i€&\â•0ÞõͼÃò7,ÍD´zÈ6€ÿ LËKw‹c ·÷Z¼ôˆÞ·€(þîÑyPiB‚á’O@•­¿N ”Ϥy„ßmå³¹¥ë%Á&p¤‚ÐÒé€Xù >S–EFU…¤õ:ÝÞ¦ÄL¨qäé\z EÜx½‰¸Ê•šÓ0ø¾È%'ÉLå8˸um”[xÙöêhCÝ…1íoÆi*½IWm­îêT#º•aš›n­Ï¨PK}_| ùçÎ䛺T§ŒªKuv·iv›­VmH|^cƒ›ÐjëÂ…M cšudZð”•xU°$˜ÈÊqÎï ªÈ:0ñùÁE¡ýõ5ú5ÀF¬/ä‚)­œŒÛ*û+úµ¥ÿ˜úáq endstream endobj 49 0 obj << /Length 889 /Filter /FlateDecode >> stream xÚUÝ“›6÷_¡G˜9t’å)qÚ¸ws3m§N&0‡Èåãšûï»BË;N&;+´_ÚÝß.Œ”„‘Íj½[ݾ‹4ÑT+¡Èî@"Iµ$N4MTBv9ùè­ïÖw¿o¶oþøíÿÓîžH¦(¸¸*_ýº[ý»â f„õ¨(KÉšÕÇOŒä »'Œ†:!ÿMš ‘ §‰†cMÞ¯þ\±å#¸’4”J,_qʘÆWTûº2e—žŸ§WÌö3'r‘)#©Šcg~Oý€kæ½3_¨5m±Ð ULÏgi÷ÊD¼·¦9¥meZg=˹÷ætª«"w—Û¢ì|žxEß[Eç|ù ªà½ß€k&<Á Ìp ¹÷aû€fÑÂ,à1§!ΩŽ"güèso@:½ºEê P†ç^æ=Ñ+rË+”5ømyŠòaტ<ÅXG úû2Ý}›·`!´šó†dHv;a,˜…gÙÒìsZP•ˆyOE7túà”œ^m< lÈ\‚§á²hª¼xèýíká¥][ô×Ú¯MäKûË<RW<òþòc †•{ôèØiê¹d¸Œ`’ä"¡¦jK?P:蘺·GáLçîlwjd§±N‡ï H™G %"ˆÇqü]¡áOc(Ã~Û>·ØwûøÔ“v‡]?":2ôDñÞÊË";Ô™½ô< Ì"p?#襩g;Fè:‹!†N_,þ²b@J¢8¿ºc–• yÐíÉ…+Ì/˜R¿(D…Eð> stream xÚ¶eXœë.Œ»»3Xqww+îî ƒ»;w+…âîn¥@‹»w-E ÅÎt­½W×>ß÷ã\s]3ïäIrçIò …ª³¸%È(rrgfgaH*i(jj²³ØØ8YØØ8hh4mÝ€4H4Ú@W7[“À¿l$]fî`™”™;ØT äxëá`ç°ó°ó °±8ØØøÿkrH™yÚZ”XoAN@7$I³«­µ;8Òtôv~~^¦¿ŽÄ®¶fN%3w #8¢…™@da t÷ùtB6îîά¬^^^,fŽn, Wkz&€—­» @ètõZ~Ó(›9ÿ!Ç‚Dд±uû[¥²r÷2sÀ[  “ø‡“%ÐŽÐW¨8þ6VüÛ€ ðŸòØYØÿq÷ŸÓ¿Ù:ýuØÌÂäèlæäcëd °²uTdYܽݙfN–¿ ÍÜ@àófžf¶fæ`ƒ¿’7Ȉ«ÌÀÿÃÐÍÂÕÖÙÝÅÍÖá7KÖßnÀ…–v²”9:ÜÝ~ç'eë ´WÞ‡õŸ+¶wy9ùýÁV¶N–V¿©Xz8³j9Ùºxå¥þc!ý‘YÝÜlll|à‹º€Þ6¬¿ƒhú8ÿR²ÿƒyø9ƒœV`*À[+ øÉÏÍÌpwõøý[ñ¿‰`iká0ZÛ:!ýñ­þÆà.pµõ°›ÀöûóÏ“¸Ï,AN>ÌÿºhV9I-)uÆHÿ£–yü˜9ØÌœœv^? àýS‚ÿÒÿKªjfûŸôþåPÞÉ àÿ›¸|ÿeâùŸö ûÏôÐþ7‚2ÜÖ@ÝŸ)0dãf³±ÿ?ÏÂ_GþÿFà·—ÿ‡)ø¿s’ñppøË‚î¿&ÿ 3G[ŸÿØ€ÛÃ<$J ð¨8ýߦ:À¿g[ hiëáøkåÝÍÀÃ"îd nxf~.ž¿Å¶n2¶Þ@KU[w ›¿šç¿×Žà`ëT¹Ùþ^@föÿ^Ê?:ðZ؃—ŒøÒþRÁö¿Q¥,@–¿'‘ƒ›`æêjæƒÄn5nn€;xd-Þu9€•Å ä>3 X\‘~_-7€Uü·èoÄ`•øƒx¬’€Uêâ°JÿƒxÙ¬2Ø‹âö¢ôâã°ªÿAœV?ˆ Àªù3Óúñƒ#èÿA`Ÿf83ó?ˆŒ\Í,ìàåoåþGÎùüïæüG¦bñâ'ÞoŽÜÿ¾VËApàŸBüF.àþcæhõ/lýǬ´þý*wÙpP›?)€™Ûø8Û€÷ó °Ìö_LùODp‚¿»äÌÉño Ö9o(VПp`[ð›ì_jpŠÎÔà³ÎàW‰ÓÿT“‹ý?Òÿ­%¸éYÁã úS/.0}g?Éq‚ɺx€Ü–æÿ*;Xú¯Š°ƒùþ‹;ØïŸ(àa`u÷ýK .‡çÞ„¬Þÿ‚à\}þ‚ÿ3:®àüÝÿÚrà¹ú/þëz-VA‚áváÝ÷õâÄ^Ìû“œ^ÅÈÙKdjž!\`%ËÑÊ+ä´ÄFî{‚o>oÅéH0ÏœÝŬÙ>ÛÙqSª}˜Êï„ð" å©£$—ub§¬å"Ä;ÚÎï^’÷ex’Mš õžÒ¾ºo¡! k¾Õ®:Ä<2!úB«HõÏ™*˜‘œû3NÓåŒ)l/âJËhðu³w˜y§íÒ®-X Îzéÿè¯>¨õ‰lšRšagL®Ðõ=›i"óœâ4 ¯!|é¢NÁ7š^†<$œÿHöërî-=°¦ ×ö(ºeg@“ýôüehN2 C¿âµR|œÎ§F¤Ù"³‰QôàaÆòí‹eC"Ëõç˜c ݰL>ÓÉ)6]âŠU¶Ì»øì/—ÍS*<Úäóo%2uÐ…SxÕ¨h-,°ð³Ø¨>'šþõÕÞ†™_šÉ{˜J(ZhI¾Eû7ïcðcô£¡¨ MÆxMàÆâxp°o$ÞJ’z!YèÌVJú$;M/š‹ªsoj®`]ìÈ6®ÎIxð¿3EÚ‹ÅQqlúÚÖ»6 «}“§ŠöP+otNǰø¤uËj47?ÌBHC Áb9ïàöU‘:«·7‡ íå‚—‚¬jŒ>ú¶4’kË×Ûƒ“û¢›Òš‹ÈY0E+…Øu Øâ®ñ:h?³®Ìš›±¶íì ‚Uv(]@_ŸVó—š‘¤Z\^f ŒJn¯³maR¥Û]'œ}»8½ šÑ}“ºžñÜ»MïZ¬ŸFóÊ’?q=w»Ä $ÜÊC—Ú˜»ÆˆÉ×_‘Ü3q³4OƒÓyBmžé‡3<¾,âa Érå– ñ1:=ž¤„‘@I“3  vÕ]aQIn³í}äÑÛ€ª&SЋŒå î96œïSý[)¬¤Doxôl\“Ú×Þ4ÛÄ2äl‹ƒV»ó²Š×k垎n’<ÑÖ—Ê~n„Òè87ª,WaÖBHC«Çq›wh®s–ëKNOèãÑØ×MÍšlñáüL çäÄoUÍœ/‚…3W?"@¹Ñè2ÁY§ŸÞ©…_ÍÜA–ÚBûX.í·Õ‰òá}û9²OØÏ%&ônöc›•ÕÐÓX)0«Ÿ®,åÙю⬽ô¡MVTÅÕ:ŒÅ³E´9­z޳k¾¦RÝËðÆ—mšÉS‹jIúG¡÷·Â\é§¡ñ[È*²ëÜP,#„ƒ¿c§:1DÅÀ’Ñõ:oôž]­êò¿lÞiÞÎRYëÊ.ó&ÌΣf.Zå¢G›ÑûyÊâ+Î@´€U”ôåײ§…îQâƒ*–¶V ™§¦Á§ƒ‹Êø-yÕ—›tEñªÖ䢫Ïå;ë6oe¸Î›µa\PN3Õn1ß+K´ ä.=z“ͽ<¶ìûrÁ=ÿäW’øèbŒ%"4·51æ+™ñ¼ÍhtÇÅýޛπö¼îsÕÆ]Ð#L›Êõçïþν$Ñ)>Ê¡ß2ûs|1Ó{<¥Ð^Æ,ìdÈXÇÖ²dž Bi CŽ\Œ[“èØ±hÌKŸ'L¤2N$)=ÅÔ°ns|†MJïÖ²hGå)Ø@¦ð—oZàÕ1Õ|$«åö½Ò7)Yñ +5 Ž- º1,“5-â¬B‚£È>ø²T唓‡1žiì5é*wo!âjíáp#ï~Ú S|‘D¯æO=9åb9/«ù~dQ,ÞOÍ?óA=Ù36y]º§ßaX+$¬ïCQ[7šÍéh Ù›Ë„Ia‹ÈÃÔ?ž³8G, ‘¡S¶Z¤ í¡Ww—ª-.Á IJ_DyŠ1¸Ç,ßêý jVôÊ®¢ñ†#Èú.¿ ó†~½¥f#]~ ©}:W–Œ¡›s,ž{‡€øœÓÀæ{rQ<ã˜;Óo aÛð„¤YÌÒØÞ%€kR"zï•û ×K~,­”Ç×~OÓ|±ðEÂá€%³±«fâ ö×ÏNŽO BH-$ߨÌÇžtÌ~,Ú«D·O·¡*Ž(ãIgú§ûgåH?uhªŽs,2dOŸ™Ìa|”ìv¦Á­7/ž2{!øBMÛäéý¬þÀ‰ZÇ„Ëg¢…Ѷç$ÖÀ½ðäá$ByÕè3ã¼åÝ/ÏMÉ\jn´êÓ/|ÌPìl´fž°¬½Šé«¤bnèˆÍ…fݶ¦ÈÊæn&Ù¡1?ÊD=[—k•SËœýÝåC‚¦žÈTÐÐÏÍg„„_!öÅË6QÁ¯mË[ºóúÁl„gÚÚÓ Z1WýV%!"š'í×ù™(‹Ú%Ô µ•«RŽkHЇVÌ7þŒï¼B¤¯Ç¦úkb‘>á6½-ûxËRÃV¼°Ú2èz©ft Ûâ;ã›W¹¬2ME>Ä?Ñ›÷>áZ„2mSNJ¸–£ïÈœ_‹iY:„bû“Jœú¥1 ÿÚQ v[÷ýpiÐ…[§l¿Ûæck¤›pCÌʉôv+z!†.fyðÙÇT«õ˜&¨¼Øcªå|Ñ8ž\Î9ãòøÂs¥A SXŒÓdD<“%áQJ%FÜ” g3-Ô5ñÜ6ú…˜Ç¦éæ¨`«)Q›„È\¶å«ÁÍÔ…fT)rÀ³aâÙs/ø?Lçö“+²é[hJµ×ê·ž:™m1>Ë_¶¢ÇyE›²«wÖXÝ;šQë×Ï@Ì_¿íi¸3Yö.'­yîJ&åR{¾µ¶½Ù´Ù È×Ù}›LZ,¨1Åù0ÐjHßl™0Wm(±‡>ÿ#ñÐÃÔ‰ooŠÆÒû*„ß šLö¬Ÿ~§OnUÄ»âP ùK‹¿>7µ©-ÿ3¹¨ .ò&ì¬>ö{¹…¾tu´ä‹1úø³Àiæ÷·HŽAŽa{'hŒ)r&\U=Ð_™l– ˆÇ¼¥Íð^ߨ›ºÐšW÷etȤݬ'íLq%a¾…—¥@]u­Ø«RÍ6¯Pç¸ <}_Õßþž‘‹<¥0vaÝ“=’•Àîg•ª:cÑίÙe5] %wäÌhÑdkb^N^$Îd¨,6ëýÑò3Ôû«Ë9ai“ªl ®˜´¹Ižý!+„+±ž Dú ãµÒô~EÁ,²T+¡Î½›ù ÷†,yh—ÞÜ1½ó&ôÏé^ÖŒ6ý>Le†"•³·šØ·Â°Ÿ^°£Þ°„XŒ¼˜ß•¹“vÄ"£ 6†™E(l0& TâÉœœ­‘¤@îñÛ…ˆ©Æ ¾3Ï¡‡áiÙ,œIËK×î'2É÷‚t%SàL×Çø ¼}õkŸŒ£l—¶Üˆ„ q`@°0­7M¸‡j@>¦X«ËÎü0/÷Uª«JŽ,*õ”èNú.S¸`y€ûWÖÍ5_Ìïñnrž”ˆŠ(Î…tÎz^Üa+~f –ݼ—[œMŒˆTDWöÒÏ{RQTÞ‡8EÛá0Ó¡æåÃëÒÙ?]€þî÷ñâ„C©¢3W©Óú¶áF=iæ?¯@t4n¸Òª|ÁS#ï1#}QžÊ{<>òÛšëë|"΂Ÿ¥'Á*R3—f’Ga‰äôwÎcâÚÕ¬þÙ46ÂuúJ<· í·®Ez[ëªð 5lS˜èýœ:qŽy!’j€¶D䣛截ž’—;MãCê•ÀÛ¢ú«#›8‡P±Ów¶eEàÅ=ù›û“Iv¿wü>r_êppip2²þu˜W6 o·Ç^ÉèhDHÁùݵ=ùÍ¿3š9Æo?ŽßCó¥¼ÈȸsÇÇ$?¸AÅ"ƒò a %l'*ÙýèdFËïÙw¸Ù:ÁižRå+2`”’´_:oLÞ‹Ûàë—ÛRKïEm×RÛ5@ŠèµW`àÙL]2£C>¿ÚÁŠÆñ4­.§ÊO- ®‡hŒPÏ¥SÒg¨^¦UgM<ë_A†-‹ù9 YövX}̼¬àÖîÙ ø®â³¯!äºoQ±U&*÷zÅŒ=CÉùˆ%`·›iö £g—|¾_T 0%+Ðö‘Y¶Z¬Í`Á°œmØfºë·Žäà” áü"9ô©› w1€\û›ÜB}ÄÏÖõ=@ô)Q¼-b—ë%ÖÄúu[QÊõ›6P罇íêÔQ]/gîfOÕO¬Þ÷VÈýNN ì`O$YU É–AÉ.âÏzûFÚ¤ââ%”žÅCËM³!‡åöåÜN™WÖ=œGòjó¡ºÉK+/®÷bþuã¡AgòõcþŽ}aqm„@>È[pŽ9eS9EçÔ$¸¨ûG°€úì%:QÄ•ÍsvTHó¥¾ÙáeR²âH2âC/€Ê³fìà$ÿI{°Dx™.‘sf½I]ÇÔIgŸpÕã]2Öã‚òt—|uIˆn«RºÜ eiS°Îf3]x\’0â±µ¨žÑ.Ù¡vvyâ]r¼îþ¿è§KÙìƒY{ã[´D q€±[àgÈ {Éïr¥Ê8„ëuBå"¾Dj˜·ì3ëX÷ʰHiTxÚ¯Í*Ëì!æ6óePjâ£A äÅh&t}mj*´rYP9Ä•N2„õáQÁqëM9ÛZõ3tù1?™â*ɬßà™Ïw„v™ÊH¬tå©ï(z-îà‘]¹™REÖÐïêB§¤Ö 1| ØÎ€ÙqŸ]BŒb`–OPÖ+GJɶ‡©6…Ù§Z7¹ú:ÐñZÇ@@²°–Å,µ<³9§";.œ­E³< }ŽeÉßÞ”(4`*殿ÛÖ§wLØxð›ñðb8·³ç þ•eX¸ê÷Ç"^~’¸m+„9°åG†.–¿§A´i=›áb ¿õ:+=‰ˆP³Dbõ>¶çöì§;î;;É\õ›IÃâl|öMÝ_c@$ygöA¦»?æ•EŸ‡ÙŸr´ÄÞR++—÷Ü û?ª¯9/­6ÙU6-8Þò²)RBÁ!í”t›IJ+8æÈæÄôÊ ê&¼#ñÃ=ùN¼í1²ýâS¶l¦éŠ;% ˜ëÍå* õ›KyÚò¦ÞM"ó­±”ïp=¾ðe-Ì‘ö~fÜxÛÖŠZ‹x5zo¿Âl©Œ÷¹gÒÏF\^¸n죠’Ü~f‡Ë·¤žsr-êKDÅ7Y !`T¿ê,°Áûç›a=·Ö£ñqx@ÓÆ^¶•ð¿OÖ‰, \ÑS³TáîgÏÙà5A^±CˆvL#`#]ÜxòÁ­tâÍ«>çÓSmG/wë¹rGá[˜ÙeŠöÊÓÔÍ"§ú™ÙÒû‹÷¸Çâ=§Ä2o€R‰—í©kn)kurf=WÊzsáÛÀpG´¯Í ÎB™ˆÈ'¤|r¼ë×âí[)ÁšWâG.J…àMþ*(úêœêÏÇ«G¾Ñ’€ú]{J÷é÷N~¢Ëu„ (mÉ£‹L± >ÑHäY”ÌÒ©ŒvòwDÜ•ãbŸH¿OOšùO¶%~â31 x ½ÍÂí4ÄÔÚ¯»))Nȳ¦}8ÔÛŽ÷ß.tF0ý2 ­½x«²}÷§dAò!2 “Æ S),È\+H‹ÃÚ1èZšé’^ó‰ <¹Æýúã~ß!¾|öŒ˜ ¨L²(Åš—CŠD^W³rSÝç;÷„7>ÜùN|È|&ÛÄ WâäŸÅJÀYˆ*AÈã{ò ëù¥Ñöu[k °$qhï;¼_’AòV‘zÂÂæÚØ*3¶?ònvekô;ZĆ¥Þû¶Ÿ[ÊÖ3ýä(«#õˆ?à·ŽE«§&@:Ù$^HP._²ödÞšypú ½üÌ[Æ Å×…òKÒ(F®)ÅÐ(ˆÓà”i~™"L†ÖöB®J¨ƒ£àÔ0LÑe éíI?X­‰â÷ã“)ø5´–¸ÎKƒÂÊm<ãù%dGÑÔEk<üï²*Lí`Bø=‰×5ÈàÍZæÃ>l‚ø^wSÞ–@o>úç7gTÜ/ëÓ.øLÐ lïÐÅ ÏÚðÐÒø«5ò÷t½–:=&arÀ¾öç«¿†ÒâòF׿s)›d ï?…Ο±±—ÝŠ•"òî•àí%/@‘¯©û8æqõ³„bUÐÉkK—íyÝ+]FŠŽÙR펃é}âüîGK6{)1˜J‡}Â}”Í”›0‘÷:Ä­™vc˜¾Vk¾SÏO©;/¿˜ñ¬¨ܘmD®â‚TƒŒ’ìXÎ ‹P5úEã/£rd„÷»¿ÎÑy~PPäO©C8~S”#ÁxÇ^Ÿ·ëWïaÔ-‹jrŘÀ²-0QLñŒe…PŒÃ͈ôUÜw¤äâºÈÂ:êµÆ_J Ô#g“Z סµyƒTb•Æâ%“8’Û—é_Úˆ(’?«W¯¦¡¡•¾I ›i}ý)³F¢¼Zûä|âÈS›–;¡õëÂè{Ìp{]w\nשOÚª€ã´ uB d÷^J1hºqò´—O°\]̶[–UË£çÌúsø´Ž¼Z¤œí‹…iå_€š.×0ù!…ts¦‡àì©cK»ÍoêôZ}ËÝ¥k8Î.XA=(äÀµÕLË[§þÔЫv»EµQFÈo1Ùiä•;zò™h:­ÑïgàïBWÖ´MøÆd¥ p®QË„P;S›ô㦛´¬6¶(«Murΰ²s;ë¡|ðÕ³eà×+¿â°o.¤pA $¸™és≭<¥×÷]ÎS”мáÛSÜ.̧‡m¨À#·yb‹@ÀYÜF~ìÇ•e¡Ü)Ôz ~â7– k¹<¹S€€r³9:¹¯&R'’$XÅçƒEÄ8˜ñü.ÿ„K5ù*fmÞÚ9 “×ýÍë‡_4²‰QÓ¦§Ë'ˆ×€ºý÷DðS¡ï ³Ö©ƒÅËÝbÂ8º@þÒV‹ú90ă÷18ûÅ*äµÙøBE™Fys¡Í±p”ÙÊìßó|ö.U×ÖÌœ Ù˜[‚i}Q,ŒÝä.åû.ÙÄ¢jîV“5öÆHsDµŸx<œBت#+äø¬KvÇb%½0ŠàÏÿÄÁ6/bVÄ ÿyfÁ`Ô»;úœˆÈo¦ Û‚±(¯ôrQéÜ’Î)­´1×¥jïôR³îqm¬9œ§ËI*ÿÈsœèB°®ô÷ºFyénn:8³¹käz´ãû>ºhìçÇ,wö¨«\¹þ|SfÄÑÚdן>ÏB‚êá_žê‘ý.œd«‹àI‡¡M$p.ç¾ôáµèC%äE´®§£û¬ÞE¨`¤ËŽ”íí÷Í ÍF(rÒ£AÕ W£yà – ÃE‘¸£ "˜R›¥oêÕžqe¿ )ÇODòyr  ôƒË)fãwevX©e-SZ2÷ ¥¤d~ì Ù pv6g§âµ@›¢ìü\Ú©Èš*|{UÒíïu.öyš4ìÆðÈVË™ãrú§a~]ûŠ AºÊªªYšû5Κ¥ ?ñ&mQ‡íà ›`ùÊØ«8ô›ÉÏN“«ž‚2ãÀÖÒ<‡¢q+t9Ì DÎùº|‰µ&Ž—ðN Fö^c£¨UÅhNž™_}ä)(pLúÃG@a›Ìgž‡u ÈtG“èN­R{ÍJ{;ç±ÆO¨ ‡mÆOO]Ç.?2ójüšWô°z­æ¹J´³\%b 71Mòºô©²¶KéÉЄžBð8K¥©ÐÑ爔9Þ†qŒI|P^BhÃtÜ‹=™Ã½ÛvÊh²ÐH.áÓ·Ê·P²_¨º½¶ÑwÞ*O5Û0.Ï펶˜fñïé’ r3ÊIäŒìXk(TÉILßuiuäf¬Á>ªù+Ý '»q˜{Ð?öñ-×½„&`¥àQä2‘qÍnµÿ„dZ×:ºUh¡+@䇣­uíÛ.­ä~³G¸Üò[4Ž6Éã.i¬ª¡ï•ïô¬ú¦À.uC¼‹hÞþDÈFâ:u¼qÓHq³ùCþ~^«fèv5V´ˆ¼«ø4ï^`Ôˆ–]’ßÙ" ìÎúXÜFÀ>4nM¯€Ÿ5Ù¨Vv#‘w.Òn—1§­Ký(ÜöË8_½ô°¹70ÍTc›AËè•I ¾Á’n.¥èâú¨ny-C”g37ªÄX^8„8qÀvSI¹ª“a‚=è¿Í´g?©é³Ïö5-£µ‘2ü¸$>KƒüMþ¯;©/NÔˆ’ñ¸R£N g?ž¾ðÂdƒ[,õ«Ï÷­Œ-ãöñæÑ¹Ü|­=ŸæZ®klž»¶ò úôÐJýRarÿÒ5Æ‚_}¹á-ü*ÓTä=â! nþÏ$¶’I|ÿx…¡›èóO¼£g[Ÿrs Ÿ‚o4ä\à8ëlV„úWT†4½ Ó°…Ó¦7rªµÓzµ/~H¸+µƒÜey'¬´›×Ø•ißó…6mKooÊç«ÝÄ)Œ´` ³›åœ`EÄ€`R ä1'‘¾?nÚ§fN|» ÀWË/Êäæ *üÒÿxâŽ[y“ ï  ÇVGx¡æï›Í9+òúεš{™ïL|\* ^ºIwxÎoÀx"™Ÿð?â1ÂòÖSgN÷8ã 6†Ý´GË#ÍàíöÔ—2+kÎ>Ób˜lm$–+p6î[/ˆvÊ‚—X@«ÒZp/ÀùᇇÎé»±¢ØœB éJY¹WŒšb±JûGdÜF¾ÄŒ[Å5”"îŽø:ø<¸èÛ5׆­ý9åùãéËh)lÛŒvJ‹ º¹b³JÅcÂêeše< ¿ÃÓçT8ßq.¡S±J]µˆo òQ×åãݹ„«tŽTkØñhs»_tò[¡vkŽQø ØÍ‡ÌŠ:¾~;—¬Cøž!Áéý"ÇÔõàR#·"»\µñi8+š] ΢ Ád˜0C8± ¡âñª\ ±fjômu§¬¾‹Å“dz:×õ±pÇé×ô$ I¥äûŒLé@”ÇíуI½ØîÒ¥xÕªØWZ¸U<ýÞ`)íŽt]a•™Ìþ½w«Áãj¿ì MƒLÍ»ÓÃ’7¯T¢Dnmoc]Û»û JoiÊ2 9nÎX!ºÒŒ¬åÓû$T¿(ô3lã keɹŒÅFX6q8ü\tA¾±\ÐüÓÊhû^Ó¨GòF’™ôŽc_%nÔjߨý ’~j±{ß•þú5î\ƒ§?¹lðbfÎðU´_JlÜûgõ6¼$84f~_kyþU¿Ó‡Âüšµ /¾%ç„ݤ³ë²»ë,n2F£*rô³¹(âöb™;ÙýÇ>s¼§BÐËñ§Ð ˆ5éh5oÊÀ˜‹`§œ $#:ÒÍ,ÏW>X<(þ>™·ˆˆœ·%ë¡r¡ò‘[âP·i\ª¡Òq‹æÞÉÄ{„… %‚wwtÛ²ëÇØQ^{„•âdøŽÍжBK²oÛ¾ë3§*Ð*Ù81KmŒk{3 ”Ð/ëñÊjîª,”¡üoµ  û:‰»ßbqÓÌd|h$5¨QÒt….E*²j8 εÌEÑ/WÆžŽÚ 9Ö r-Áññx«HÁâ|!ûÇBQ!X£Þ£¡óµÇz_À9öÚù—O±bsgFsˆ´h§d,¢k­ª:TRu ë߬ËພlÜ™GŸëlÄ Ä¼åÕQú0ü¥&à×XGö×÷j©jµS«|÷+®Õ©G/»Ûg%ÅÌÄ;õ”`oÞûÓ”äxMk:=wý4)Š…õ•ìVšt"þC:"þZsíS”› ™ Nˆ&ŽáÓ‹€à˺qlDÄ·ýÙj8sÆÕ¹g{3ÜÞ§ÐË^òTÍC3K n‘+§ðñKá¥:VïKÊ,±)ͽ{=«ŽïåÄÐ4Xw¢ãf R‡=…ˆRc ‘¾’@LÁ–—¶qj©YŽ Vb ëÎëYT¥FÿÜŠR¾N"!Ì<ö¢»˜£©!uw0Â-/ñŽêî¸5|Œ3£B~9îÑš¡Ä=øl¾‚Ä:)€+¨.ëзe»Þ2˜xf¾ÿ½æ]“óä¨DÐÈ 4ì^?¢üa7¢Ð/êë’¤úQ‘Dã©ÊØÅ…áÂÝîݲe:ZO_¾^Ó_°ÑBjº«¹õ ]—¨m®Zñ .t«bŒWªh6‰x•ýÞàrÑ'~!$„Àc¥!¶_¤M¥“ʺ¸sõ~"2t †]¼8 S´?¤­®UCê ˆ„Ž°Ížë”Eåî(Èéòq2]ÓøÜQy1±8ûÉX±V? ÂŒ] VµôÉùÎú§Ý}bXP·FO§/ÕR÷yÊCp¯Q2—ãiÙr¸Þ$óR®ï­1¡ie´ec^c.q­'ôa tO¶²»'HnæJ‡é ¯ÌwVÈI33Cõ°/ǦT–íí»xý-zjÝö¾SY|ImꤕøFËÀ2šá‹Ñê}Œš©ØÜ Çì¡hYú+8zØâôÅgg8•æç^-g(UwZx]Mu?¦Òcä„{`G%§ lÁÀ¹ÂGÁý@¶‘-j)œêå3bs©©ñ&‘^¥g¯uR“ž›ÏžîÜ4Y[Øañ ØŸ7V×Ó÷ŽÓ '}b‘‘gøiÒŠaña8ÎQÛµF,‚žY›œæ$ßeø¥³í©¹8O.[‹Ûùi½Çªë\ºiàhDÃLfW¶O·«•EQ‡©­ˆª€}cÌÉPЉË3´*Äørz öÅkSbóÖüþXÿçK§,8ǤtÚrÕ¬§=2_ßɨ…wˆë£üŸq¾ `­µÄBÒCs5®û6¿æYŽ¢Zâe¹’ÿ•n5.-çûv®?ŸmaT ø SQ§Ò§û?WÈ64ë·=͈wBC!´ê‡á¦äpÄ-ùZd¼››èU„¯ù¶øD/5yÜ£Óve6n寉^ÎGÈùž…®fu×¥…›fAu¼w¤8Ì~&‰X~XüÌ©fÈÇ3ì¢Ã2±©—:Cüzng6؆Áù4;¥¬°„ª#ߣ<º‘ì_®²¼~=»|ˆ¨â]Ï•§ÐZÒ먑‡›¤=¥®¶’=Éd ä(!S̨j¹¹°F Ñ©SBLäS{Óløú#fBa7`‚)]LoßÖð8ÃÄuÛúEïÚGüJØ ;^úúÃê%“‚‚+Jw¯ùGº09ÃØ'"ø y¾ „I˜9–\Á/TÊÎnü6á4OqÕðá‹0!WÒ<~‚â»!áÄJì†Á½,­ªMy/ÓÕ$$Ô©;!nÇ·‚K'öÌšõ^å…çåeïìûn}eÚ½œ¥‡£gâððÒÅ¿h&ÆMS¨«­-Òæö‰Ëf@ß›`sþÖ3[ç `Ï)¶yéo/Èn™|U`!ôÕƒ¸ ·´eim•B±W¯{NÌ&2맆 ú ð푯*Uf[&„ú÷JŒˆ”ãˆÎG*ú 4UsÞoßÏËZì]óäTBŠà£†žPÛÚ%ÂJŒJ*®²r.ö}ä´îî„Ö#‚•©×šøð0îs¥m’ ™~ÍX™ë=îå&|oR¢v·G]H ö,NÊ+¾ŠØiu»KjÝ‹EÖw ·HS[ù~X8¬ òVuµ4_ý$zè"Wšá ìÞûFY¦—ɸߦ+-gº áýþd̶«êzÆ©‚”'ĸ©ùa£±û¼r©6î$äõ¢#”_e75æÉÆç Ëw?Ø+¶±ì¥R&1Ç=¿ÏJùíÑ1Ò—"Œœs¥*½­è¼ùQ¤‰ðÆ{Fÿ Ì-Ô¢,`üÀ øeúÝ8AO¢‰{µW†2H%—ï1\ “dìßtœ}¶<…`UkióÅÇÆfËÙ¥µÃ-ü HiÏ7%Ãç,ï_>Ð,fGþl t‹±Áw¸€Ð¨È¾0¬Nx±ÀhÛØðÜãüšP†T4<4@&ãúñ°ôfŒi™X^–dúÓ^ð]qí,3Œi=<•çûW«jˆ‚Oe»p5ÇôÜIóÙ ÙûRŠA~¿y\dœ·¶g–=‘¯²3Y’Ÿ§™“Á^'Ô~æ®”1Õ`W%¸tfqæ -Ä<ÐÉ_ly£ßeöÑ`i~ÈËJkÞLœ~«U’[Á |1|=éøI€•E¥²aa43ÔW•V„}‘'ÐlGoîŽèÂ"ܺƒÿ„Sµz<—'¢kÀ{CØœ8Y4±¬riiIxw£0*Àö´0î”'z÷qêƒå$-÷Æ·êvûȤњG…v"ÈClÝ B­eTßðÓÌ=Л{NéÀ1u?èX¨3íiˆòUq‹|êù™[‚‚×j:7ªß¹_“°˜µw4~n?®]Œ=> stream xÚ÷PÚÒ ãîÁu ¸»ww÷‡ÁÝ=Ü-H$¸»»»»,,Àãœ+9÷ûÿª÷ŠªaVûêݽw ¹Š:“¨9Ø$vpebcfåˆ+jh°±XY9˜YYÙ‘¨¨4¬]í@ÿ‘#Qiœ]¬Áüÿ°w]ßd@×7CE°@ÎÍÀÆ`ãægãáge°³²òýÇì̺[›™r` •8ØÑËÙÚÒÊõ-ϾhÍèl||<Œ»DíAÎÖf@€"ÐÕ dÿ–Ñ hP›Yƒ\½þ'­€•««#? ‹‡‡3ÐÞ…ìl)DÇð°vµ¨\@Îî sÀ_”J@{п©1#Q4¬¬]þ¥P[¸zA€7µÈÁåÍÅÍÁä xËP—U(;‚þe¬ð/FÀ¿›`cfûo¸{ÿÈÚáog ™ØÞèàeí` °°¶”¥˜]=]@ó¿ v.à7 ;ÐÚhúfðwé@€”¨*øÆðßü\Ìœ­]]˜]¬íþâÈòW˜·6K:˜‹ƒííA®.HÕ'aí 2{ë»Ë¿×Öìáàódaí`nñ s7GMk'7¬Ä¿mÞDHd– W+++/;äyšY±ü•@ÃËô·’í/ñ?G°#ÀâÈÏÚôöÉÇè¸:»ü|þ©ø_„ÄÆ0·6s˜‚,­þDƒ,þ…ßÎßÙÚ Ïú6~lÖ¿þþûÍðmÂÌÁv^Ìÿ>bE5QY†Sþ¯RL ì ðaâ0±sp¸8xÜ|Ü¿ÿò_þÿáþ·ThýïÚþOÖÁ àû…·Þý‡†û¿ç‚ößKCøß Jà·ihÿ ¿+«ÙÛÛÿçøÛåÿßäÿåÿuøÿoERnvvëiÿeðÿ£Ú[ÛyýÛâmšÝ\ß6Cü¶ÿ×Tô¯uV™[»Ùÿ_­¬+ðmCD,íþÛHk)kO¹Šµ«™ÕßóŸcx‹ngíR»XÿuߘØXYÿîmåÌlßî—·Ãú[zÛ¨ÿÍ(é`6ÿkõع¸@gg ëÛ|±sq|ØÞvÔäù÷hX˜À®o.€7v~ °3Ò_GÊÍ`ýKô/Ä `ûƒx,â/€Eââ°Hþñ°X¤þ ·( Ð[Å?è-ŠÒ/;€Eíâ°¨ÿAœ?è­NÍÿ"¾·|zÐ[àç[L ËÛZ»Øþ)÷-ÐõÇ[¦ÛršÙ‚ÞÞ‹XqüWþ¯1þ¯â¼Ù×[03°ÝÛ þ·ο$ööŠúëhYÌÿ 9Þ:d¶³:ÿÃ⭠П‚ÿBNno ñÇà˜ÅŸ¬!°Û?¼•kùøV„ÕŸ’Þúgååhrø‡Å›Ìúð­(›À7Z²s¿Õo÷× þÑ¿5Áþ|»‡XþûíæcÿÉþfûö6þCýV½ãõ›¯ãÛóäð?íçdû·ô›ÏùV¦ãÛé‚ÍÿîºÓŸî¾1wr»‚ÌMÿÑ>¶7é?ºÅöFþηr±ºXýÃà-ÏŸ¬oW‹«•3臷dqõÿÃá-†Û?à[ÿÜÿ@ö7sÏ¿áÿ쯙›óC׿¯Ø·åþþûËÎínhð)t•ÙÁ›Î¿DS†{0Öv%ioEVÈž}N›ëà#Z’T[Ÿ|'¨Mï·"-MáLžŠÖö“ 3iˆø>;ùjÙB7CvÊQå9¹ñ¢©¼»÷è“ö¬í/] _ØW=¨ä–Gþ]:ãùÉ ¨xŽ*ß4gŸΕ‰ëÒ}îö×,Vîä+™\’ßY ÇW½-ö؇yïõr v—.J=|è[¬±ij±£T9¼EŸ’¢O›‚‹ŸYé˜!6ÇúÉ|G;Éðë+Èbá±Ú9/óIQúµÖ²éô¢ fï«›8Ò×8ž¢-â3XxxHI(7õ E ÞE:3˜+ºÇÁ+yùl/ÃÜêžÞÊŸþ¨™Ô÷Ñ·ØADÚÁYk[—xŽpòÃV„#¾9àíò-´ÉúFYíÓk3yæ8ëyà©Þ>P&y_˜’Žñ®0³‡j8á¶ú§b%_«)¢A7þ0ÁŠ”æ*³ÓÕÁ çü1½t^ù'oâz/»äÉ"Y.S¬F2³„z8åPhQŒI<¹… Ã¥òÕü÷ïEäVÍ¿‹L·JAŽ+FÞu—æ?™c¾·d¨y<l<:‚™Óˉ45¦iG)ÝbGÉp鲬ì èÕ æGô'AâIŽÕ Î‹‘Eîá<š¿û…úi.ßÊÑÖ¢1RI¿"› Wì÷ðÈu¥T°¥Z†ü·ZÃãñê³*ÁM]¯èqå_oKwôLj{“– «Þû§éÍvë-yxU~ª‰¨ Ò¦–ÐO˜=†È¢Æªßo™ÿ@ÁGܦâ÷àב°ÙÙ; ¼]°a6~žˆÉ[•!«_w8ˆ1:¹ðˆžUlœ¥÷´ošÇ=Ðýž†=&t¶†Êì¼ÿ®<ÞчU¢Ë—[¤ì0÷8çƒá Ke‡•ïäó}±š(ÌÆp•ü´}¶Ý/£5jíµ@¼èõAÒÆ‚Ëg{©>Âõ‹2’œº´N¢•ùŒaŽx)yYÜð¯<"¸<¢kŠOÊ*hQÌb×ã?ÉŒ0X‡ëTþàW“xÿûÀ¦_WçVrÑ­Œ¬í ×`«ãj¼˜l[Ñv~”:÷÷·<GÕöNV3H™Œ¹yÎK7ý3TÝöÞÔÌÏû9ìmú®S3Ã#©+_>Õe [ÝdD5™fo¿Ð/“@Q"™|5‰¢¨„¡„e}ä λúFûÍWsúbàÛé' <¸‡²wõ…®÷sæi=Åy‚åYÙ\ã?Ûˆ Ïmxº©N­E^ÓpwÞ aÒ@NGŽj°@L9Ej®MIWßÅ7³%»JNÏ4®ˆ Nâ±ô~©‘2RNeÊIɹî)r …7Ê&úEÏféqwÈÞ•ÏÉR”—ÛÄÑ)R¶cPÅã½ ô>™f#>¦ûØÈ¼•qù3(ZÒ3X—¦e¨ôî„+RÊ,@ÐÁ¦ƒ}§}nÁ û(Þƒ %æ÷ýØG i®¬aDvT·WS ìØªÅBþ·µ“è¤ý“«¢§ Ë3ªNÇü'ë+2eRZŸoqó5£he/êê ,^‰×«Ñi¢Zöɉ®?Ò;©Š@±ùðlLKÂwF0!ÝiçzE¹pȧ˯4)ñáhÊ>ÓRé{ÛYÚCAO÷“¸Ö³ UìEç†ò´G¼×G¾$f™á’Eà›pi !媸#QVUívŸ”'Þ©©e•Ї1ªäzæ{#úc›AxPì”òpmîD$±†¿˜V›æ€:âE¬_º…€É9qL#?#ö ¥Å—ïçg?³—ç+èô”égzç¾#ù{ŽÓÓ˜‹4r?.o¹åwTfãÍçbó;.ÓQÓu'ÆT™_Ì太#ÞþmD%%‡;½>ékXx'·qÒÆÁêÅd¨Ž›n˧ã9sh(fxðú¾öT¬í–ô‘N¶ãýh=Ûy=PâŒ6õÂG”pÊEq—ÄD€‰ò¹~ÔÃë: «Ähf¥˜öi…­Ó=WRç÷’¨M<¹ÌÏ[.Á“ê,Ýü3kÒeŸá£¾x%ø9áîâ•Ñ* ï])˜ê˜c©9xeò®²ïüÁÞ/’Ìt¼_D³]MÒ&À'Ë'Éß+PC¼±MÈ}_*€ôßÇÍ5‘ãaàé˜]e‰­œ_"IéY¡óœÎ[ª+…C•p5û9Ȇâ¶xÐûù”]ô9|c.¹œY¡6;,½<-ñÂo¦h§;I(ô··Åú¬ý0©ÁN2÷H&ò] E•–{õfiÌ>’¡éУ ý¸ ‘±¤8QÈS¸7 ‡1 Yˆ À³éS©à¸Ù{§EGõkûÈvd#$ô,C\ø[ÜÁS¨QïÕy¨Ê§Õ¯[Sï•O²4waNúû¶['ߊЖ ˜À©cœ%¸pÛÿÍs'5N=Ì7Û‚l±\¸KçŠÙmHÌÓBÚTò7³‡ö‡§° 0c"ÞW1[[ùzx> KËߌvǾeÔmD3øhŠC@ú/s”¿>’tº¿_k:ãÑ<3;ïm€/ƒ i„ÂŽphRBŸÊ˜`û”yX¤½1Pö_²üªµ†ò-]É Žïu“3ÚKvºçesµ$µ§+Š¢Â{d ¬Ücœì[n¦÷Bì-Vx"Ò¨(J¶Þñ°%üòLÝ'2Ž?¢˜ÀI|†×í »8Ï^Àûx¬Qd)Vgón9†OóYêD®R˜KßѰyvÄqÂêÓRwÞDWbÉU¸&oàä|’wþáF‡B¸pmà#TÞo~Rùèßoóµ_©Æt’Coa(—"øñL‡ùw뤌Ì3Å&HäÔh!¹õ™4èp’gÇL{éB˜Ð(Ö?ÓB#W TþQ|W¦"ú~À"!PƒÂ‚øŒ0è.íE§˜:Q­£OrðÙ°„]!ð$¼‚åJØŠŽ—z ‡E ˆaò+5‰¯…5²þÒ£QQ ?Z‡Ò»m“’›§Ñï)H[`“Ífßz‡‡û𙲃³YUW 8ü¦°Ïè>‘¯á¦znæ_¿¼ò#©—¬-¡ÝUgeNꬌeÛ C6ÂyÿsDnüCk Š!VûpýU3®dçKÊYhÆdŠ!ᬜ¤ _»¦b¹“C¿y}×V¥'?o¬_|h‘AAr؆3cܬô$Ó™€ÃÎc#æßÂÙÆlNÝÇÀu}OÚ»…+LÕ<}—b¥Þ Ò÷ÎÌC„ùF6­èÒ%ÎP m˜ÃBûΔC¹Ýo½Ý ãELC£û­=ëÌÖMœW±¨»‰QÑdÏNà°ââVš…0‚PÙÔOÔÍao ð÷u)ÏÃLè {*n§ûðùa£pÏ;S0 ‘ïÕ° §¤d¿kØz^fÙXš~–I2G`¦åGêÞ¹(Ë&fþ4•FUèèÔYz#„P.dtìíɸâc”8nf蜵à þÞ^ß|›?´Qî*“¤±&þ<¹HQþ0å´dÈû@‰íÕÔ( VpF ô´èj(§¤HÝ÷ûÑ߆P=ÐG£a=–>ºš»àf‰C*y›5´f?sIû,õ4}NØ£IæÌˈ± £v M]¼i:‡ø÷'Ú¢u¥Bœø HÏPE\n›‚r¤×I2‘8¼%ºÛ¸Mï¦&}~W3¡·Ý?"|v}ñSù}–ìÚ‡SP,çY›Â»84«F¼ºÍŒgà3bâ¶þªIDV_|CuÜÌÑ÷;Œ§Ç`ÞÙ!8\Iެþä%zò:ã9OªÂ¶¼¹öºCÙ¦3­ðûæÊC¼6ˆp~Êå›â¼VZ4]é}zêÏî-øR¹+]­«Ñ,Þº³.¶îg8ó÷r l¸Âï놄ßQôg™©v£_t4[˜5NÍæ:×µW" XÚùÇ\¤%péVÊO ©ï_žš#‰DÃsÍ˸l?Ý®á œ°\ï´DÙj¯»Xî$?çG/œcøÑpÚ¥L%ï‹5­ÿ:kf«bŠà?±„Äš_ÝÓ{_4îM´+;[AŠªÒ­VJ9Ëø•4¸äŒ%ïH ¢ðl'ˆZ2Ž·»6cð·"¢‡æ]ögÚÒJcö–uQ„®Éf3=hÉP—!ÆéF1¡¾1Ç¿…¨Ë{­E`Ã+Hó@|J$%YØô®«ùut&ƒ¤¨‡=RÓ9œnÆJKe^œáßC¥ßÉñ%çÂi>¼„±á"vóGh~õv‡Ä%³å¿x(ò'L5fDR)T‰’='l²p’æ­tØîj?ÐÜ–LÁÖ9¡ LÒ^ü xìæ’îBñbÇ'Œ‰ÈŒÍÓìÊ4(|H­¹«ŒÝµ”Wq  ã-àRsƒK­B6-Y2<[󫔦 Ìj² _[ŠŸc«•a¿wDòÓ•…—×~èd옽M¿PS#ƒW±µ¸ÓÖ€ÜO*ŒGÝ:5‰tPŽLTÈ´‹û¥áCoÀªt¯ä®…:iÉæáôIX¨14š ªXC½º”­ê$ð’¼dÎMÙÛGf®~¬¨T8é3Ì–ñ­POꩪŽh¼¿ê„ï,¾¼%©+Þ?¬êj@/µ;D»­!zÈØ Ý•\‡ªs£á>D\‚ Ï»;É9 Ät5,1ÒaàVàªýp5ò5€é‘Á‘¹e“P8Ys–¹E­s/—:EÆ ®Élùìt¢ h>›%÷»f!‹Uy e%Þ*ôª£ßÒÔÕöÍéÉí”~à-Å™¾³Žø† åÑîfÜ_ O̺‰ÏñÕ¸Ó¾Wšåh3@õê¦ÖÍâf§éŠFQ ¦ uGxø“MéUÒHìiæl Ãç†|Q¬Ái’)ç‚ÖoÜÔ2SÉâ| öΰ¾½<Î5X?¥¨ø#®åœ_6hË,¥zúêjý+=UŽáŒåw6æðº·tuÃ$F“(î›’)±…-yHÓV27ý0›uF÷ÀG‘‡¿³iv4Â@¾<·þ¹ž÷|R‰ p#I€l7¤±‹ôdë]+$>%WL’Ä0¾àV7k³—ñ=¹@$3=߆nlXJñ!ýiRë¨EÐeò ÅÄSÍVÇÀB_Ño©m]Î_ÚðKêÄ2#érÛÅŸéü_±©²‹Mõ;1•…{¯ú?àäªyDl6JVp}¦ø¬½ïøaþ»,÷y T²yÔ‘üËû'UQ:B¹Wx­Xk·OjXPYN\ ¦¾¤þ§‰ÇìO]<¦¢~aA¹„_t改ŸX0h LøÉ&ç®Ú¡ê:ëJH[ q®x-?ÉBRÞJ3¦¼Ž)šxùIŸeãÓ™%®ÁnüLÍ|åÙ–G&çiµƒf^Cß’NâÖÏ»Eº#É7†ª ³ê ”’´]+}KBm/\$£ èDšAò¨Fþƒ[ ˆäh[öÒÍî1^–¬|BÅu¤lÇE? *@å² (ê.˜Ãb²Ÿæçܯ±–AGõùdˆj­¶îv”¾Öwg¬NŽ—íHªžÓÎà]™GÕÈÚ wï«Ã¬þKPäògœIÉàè›é]z‹p™M%Ð󇥇~{q0²Õ?Zq_\ü¦àã÷ä[Ö çL"—¬ uñïP‚=3^#(OúsOsFäLEl”U\ ÉŠ˜˜²LB/¸óɲçlæï³±äøÎ©3dã ÃÞW&û-c7Ìè[Å0!J*pÖ¤´ÌÃý&ÕtÝ2LU ƒ+Ü3Í„-m¹ôÀ}àuì=â’ÜÚ‹¼ph¼ÍÒ=Bs¿—êOÇ#s1òÊÓw-m‡ ¡$yß5 C§ç.™#•XLáŠÑ'vŽÙÙ­¡K]GiYôûDv}?ˆmB¹wçunQCµ›¡ÚÄ££ ”q}T=û¨kRrh"g,V¹EjU<çtuüŽ…üÃ0óõä Q'}_§‚â]ùàÅa–igr‘¢³ 'þþå%™«°²„F‰×]1’ žA’ßýRÔE(tÓléÅ·€í$`‘'î‡I]”X“Z{”»ê‰PÌõÅÅ7 S—-k'!Æ>B=‡’Þ’,ŽƒžO ©1Ú¯Õ–Kà§"œ6€ å™ÚCãknýËZù#le. ôŽ¿™M)GQ°;’Rb=?‡¸xüeŒw Ü¡ZQa>Áι`â,þöã£âhkTÃ/j?…·œ¢ü¯œ«¹Zúc[ ÌÆa¦'%”®¿ÊâÙN˜ü†g»Í¦Wúì• d¹ŸÝ­5mâŽy/ÜD<"C\¥M}Y‡às†ÛÀ¯¢È6 vmÈI§ô:ž*]È×:j§â÷,ÌÌ }Yße…þŒy@¦R(–بMO¢'><¥üùD=(ñ”µö8p‡×<±ÐÕ·¯ZÍ5‘rÇäÇó1anw™©;‹¯IVü{œÛPs¸hTú¦^íüwgåZidB‡t,î]2춸>ë]®MSL‰g¥»2R…TTÈ}F¬Š”cm÷Z/Å S ÷¬æÂbjÆùpøïá!Ó mÒúÁa?úp¨“¾©ty6ÕQËbágf¼žÆY Ò¢¦åyóëû2)O…`¦ ëòeíÜ¿{©Ü,ÿ6ÿ4«O ìŠÙâ=í±÷aÚ Âì+_j届:ï–ONÚ|Žn¹§-ŽKó% ¥3C–kæsÄ](ݦ=u´‚ö˜êê®O]E­å¯ÀÆ ðÅŸ ã Ì‘]m¯€H ɬgú$ô*<Å‘_Áü<Ä•·6„öYéÐ(¥äõ4E0ØÍžØ}Dú΀ó½2˜óy§ñëF.-Ãü¹FiŠ>½|’IýØÓÄPc¼Óëb»®+ÚïOkµ]V9ýz0‚ü '•DŸ§ý/b‡ž¤Z»l_§§Ç8œú#©fY}@.ÂטõûþªRyÍŸÍ“´Úª”Éß~(Žx܇`¤Ð%cJv˜èzŽc”Ó1ûÖúë·p¥ô£’‚½~P­ÊO*i¢#9¤¯ÈSÝ šgäÍË4’ñ²]™‹z4ó³Z+튎pÀƒ›ð¥hüõ/uÈiæ²_d’0Þ1“¯¸™ï„2̸l²³> )@iômõ1 è[,L¦&)UhÐs'‰åyÂL_&=[ÍT±q¡z‹´iDVQ†`l¼19\ô›º¹àŽé¡&Gz™ÓÕ¡.%éõ”Q’q~ dˆ>¹l‘£jÔIAÈ’ õº[®…gØNr6ô¸¹#•x@9 _å˜!Ú¶¼6ÃŽ‹“§ýžPÚæ]Þò9©:7¶ØEkch‡Æâê)Ò*ºá`ˆ¡§'ÐäÉo@.’°‡'¤w)\D—Öîò?Îd…8;ãÀ5Öy¾L8Å­Ét›ùÉ ò€ØìÝ¥Î3*>Dëá韴¯~i¢{ÌG‡ÅÀ(7ÙÂa‡ Õƒà‚:Òrh §,ùb¦/¥À§d—Zöœ1­gí/ÃÎÓ¨WqXeg£ž_Ü_ªj &?‘BXl‹™ÄC–õ-M••€;jÎ?Sùù ]Ž™\ÂÒù_Ë£h‘~«ü ^²wæŠSïߦT#Ú9+,¯%ÏÑà xƒCTé3\'7r| ö:ÒVuÐdYÜñN.¢øûÝ×õr¶ä=Ú>¾Ûe¬@´<ÌÆ|6ª¾Í¸-ïWy$PÏr±[wWù{7±áwƒ}\3ÿ“G,°¦©Ç†ôÕû0DaŸS¿…üƒà/ßj,ɰòîTu¦Ä™Oƒßça¸áôÁÌOù·]ç`ï^&ù÷ E¢þ FU*Ñdޯ렽Ʀ‡TPñ°\Ü^*y¨DV:–ÅO=’;aôÖX†×5-ÁTá}ΔåïÐtQì¦_QÔì"hœ”ÚVØœ ñj—ŠsÝL·¸Ò^V?¬#Ó̤Ÿr,//+ÇW¼£²áAƒj;½wsRê—ÍËwioë²Ú+ìáúQ½Ö³dnƒ>b\M'‡§D/™Aïü Ü 8nøøÁ¬ü=êÅõ ¹å9ú†çÚ´¾‚§aí¹We ¬ê¾Ãäãæ ûÉ‚]ûï2hxë~IN84¿4‰zTä!î_¨Ö MKr¾‹*J:cõºr0CßAQÀư¦ï/9-†Nžr“¬rÁ‚x!…àý.©]t·£$ã¹uôêŠþ# uÔÅDÚZ ?C<Àü­­˜ÆM7÷Q:zúãÖ`¢~~:a 6W[ùÂÒÖKQG þv½í ÊRçp©€.ôpd;¸diÙ|5œÉ‘-máÐh_˜uéÿˆ[Ó»çgc«¨$eS$Ç*<'òz°°ÈÖçgJÙ÷t¤/“ʪPÖøÁ…vo$ýµHf¯]ù»Å 3_†3n™êo Þ—B³' Z¿©Ë¡¦ü×ßàÔ©Cî¶ÇYZìñU#tîaÑ<[yQn{€Þ͘;l:RÖhèRßn°5/†Úæ1x†ÂB%Â#c¼“"qm\ *Fx¾mžw£ú´3â½Ï…^ ƒ+jE3ÂÅB5À½.*ÏÇHš¬]â–“½q ÒU¿ÃJŸOo§Ré¾®çÜ.|”ev±Ì9Iã#Vq¤!K‘åq®%‹°ŒgS Žö“W¥¥T„} u׿MÎ6I{|„Àýâ:«+y¨Ô/"~²[ö¾þ]›òEƒ¡»æü´Ò!Ž!ñj“›ˆu»¾Ê*´WÈé™>¤ƒºôt Ô9ÜÇ…§Ê|R¬kZ*œH¼\Jª·‘ò\byA¸g™!ÜfU~ ä½äqRÐãCT¢Ët³z!6|ù„DX|Ù¼yÈ}»w|å{+LÀ·L+\!ìR=³&'-aZÞ#1ìêB;½RY!¯—Λ¨FÌŒ›¢"=Þ¾]Ê ¥4Ó«Z“ûc¯ñ¿º7w½68<$žÊ}ò÷Ì—=,#…?Õw3¥­FN-6àhwðÓ¦Ñ%æ¥ôž†Fƽï ìÒ  ":F\Éп—~þ,Z³ã\ÃËåŽ"^Iaúž 1Í´ƒöÞcaò#('¹,Û=f5ƒÆ‘+ÏCF”Ñ@Þ z*è;bÀ¢*ªO³ö.ÌÝÉÓ¤œ¤ó‡ï7˜¬ô’í…^ÄdÄ{*dËe?Mosœ5ïDíêO%±QP/ØãœÓ´v¤î48®DE}‹5>3lµ1 Œ¡Jû¦³Î#Õ $RðRôWÙ¸EªCê“ûræw AWq’Ô7Ñ*ªðo¼›]ªN©Î0 JHâš2—…‡,‹î©1Ÿ'ˆ¦S§C苃äàtqóRÂüÆêDóFéò3Mªá_F©ÖF¨Äº©-èÖ‰õŠ-l"/Önœà %|ÝK´.Ó–½To‡ÙÒ†P$›õ¿ë™4`Œq7ÐEuÛ&ÒA]ïéWTÝ[½·åL7•Í*€àÌ&Û$MRð’6±æ÷ú\òîÙ[‘@Êhž˜^M˜&]ý¡Û³îóg?êè¿$•à2¹šàà87iódy^ò0ˆrÊŠµòÑŠ?cœI&ý«‹?âûÓ!yiDˆ¸3d8‹+äâ‘Ãqï¤8zÍ\E0b<ˆ¯¤õ›ƒ¦ÐÍö¡Ä׎À\7:0>uÛC_Õ5¥Vüâ¸<ž3vIÚ²øb6º>ZòN\#äŒnn¹×§*š23• R¾ó &-ÇsÄ(X‘U9\Cö³~¼74ç«»þ#.ªrTŒ„2.`æð·'0Þšê5²”Ùm×O¦9N) ]b®×‹{Ýÿs}”>Ák¼»n­zÈhúsI4un-ÜF奋$¢D_µÇ+ÿ!¦¦=l°›'ÿn!Sß>‹¥ŠçÏL}ÕV·FN2¸¥Ý˜C:57¢Ìïôõ6›-#„=µ}ÖWà4=Ê­éyo§vwJßÖ{#o˜}»’ï‡Bó*­ª¨1Úw†·Î´Ô•Õ6ÑVúƒþÛëçê7£Þs¸÷Úˆ#û&mÆíÉ×0›95½&ß—Œ»r„uhƒÏ s§¹#÷U×\3ÙÇÃSKyçáS^1•Æfªž[Ù´N°•õ®c¾ÇCë}@ Cy™Î¸ÉMl䓤ÿG…0ó¼™­\¢Ú=Ë2æE¸Î7ô{Žêžô‰Ã‹kžM§¦i›oA‘Ý¥Ìb%ŒðÞÔ^¬ù{‰ì¢Ÿ(Îkÿ'ˆµ.º…F%ôýU¼{쪘ß~œ¿Çàd"‚,Xnü²:Ö6A±*lóã×2s„!=tø÷wÕÏT½_N¾®§`fšŠ­ÿ´É±5‰iàt·3lÖéºn¦~ßÿýt.$ÓG{(5†á70ÿ„8’%çŒÜu]ÃX4’oêÆ„7¸m‘Q/È7ýã¾J‚̪òçHcù²ÀÓj©ö-«A\áµø=Ni¬!‰9ÔX)¡kLj'WêÐÊotïd& Y+á(l3¾_†ä;ûš‚¸x¿3!¢˜·T<dhkj\í4ìæu#Æ-Ʊ˜SE©³ø'_" % h—î TÅ619Ðü+Û÷tì/—ïÌûãóEèÉæ¾¤B$!IÖ¼èU;íÉ2F–àÇØN«HÝyÄsëgߟ¬fV°øD'‹§HâdL` Œ(:J×M~¬˜9–tøNJ"‚‚õž êf`oa–¤QbÇýFéÛÞZX¥:ìi[÷ßå'wÙ#ÿqTîÌÖRLÐLÃÏn{Xd!/„šyÅÉç¾i‹[|y°ìÂ'©.è ’f6Áh“܉3/7 -Ä8ÌŒ˜ó°•Z„îæÌŸÅ}¶¼Î*bÅ…Ü·íLÀp@®%xÞñi(Ë£ž]±Œg}’k<º[“Õ&nsÚ»ô5krFŒ3СKXªÊÆ[ˆc>+JÙXS—eÞdãž¾64ö†B]e¤È LïÿHk˜$O^âùPC`LÇ“-ÙŸ÷4¬ÍîÖhõ}PœRQØŽ-#ÕrãéóÜÉ J· <\1[×{{¹q(33[Žá½®½K¿+¬YÊÃÁµ#… ú â˜c†K1ª ½2$’ ´á¨êƒ//‚š[Å3ÛXc‹P#ð˜Õ8¹~Ÿð¶1ô^Í̃0¥qQ¯µp\ ¨w£”^ê©ßŸœ÷ôSºÜ·>놫ýܤ›O+¤–ˆË–*¡%¨ÐHm‡Ã»œ€…6W/ 6ÒµŠN†Cä€v;gšFÃ$)Æöêû*Ù³‡ŠÈÖ7|[•Yç„· ÝÇ®ü­Â¡»UiI³¥eƒ­ýiê2c&\­?.~‰3Ùz–¬¹!9Âu¢ÂTð$½ŽünÜ(åÅ.Eu·àµ„4 +<øéí÷_ò„âÅ]tnÂ>4E;ÞÎ]¼Õ,äìöz\}æ~7<´Ê“£6n©c¢“zᄀú·¶›Ê,{\œVoYÛ¢#…ëÊýz^#­30™r!:4ßÐývô·–UpË»s“º¤Ÿ˜eÊ7[$xóº_^¥4œ´-™ŠÄæêkðçq Q­ôb‰1å¸ò&ʰMKœ¹™¡Þɧ‹C>¬”KlÝ}kâNc%,(é5,i“ìž²ÜN…‰Å¬#]‰Ñö5p1¯·Éšª¶3É>q ìcãÚ(2 OÂŒâ‹UÐ(¦Œ6?“ŠðÝ ú–KÍà·ÉâÛ?ÐZáib-ôÄ™¥H"¸nd¨Ku±A!_뢧h+Œñ¾æÍ*¯¦*OJ„Aæ}Iw½ätø¡¥ÔJÒF&ôk¯Ð[G%ÝÊik¤ä.Ér›Z–U|þÍ‹âKßZ¾ˆedftfî“ËâÁSjÛ%Ä0wÙ£t=²ïhë‹ôîÈÍ3‘wÎVÙê»°µWHïäq¿¾ÖØÁ¾´C„¾=ÕÞ’«†$-—¼Wž‚Óù°–"7ÿ-„öOØ>«äB/ؾK]cCZ"¼†…ˆ#}Á1Î×yfÆ–YV¸d<° Þí¾gž-t.]Nz¼ûƒº²—Þˆ'r4ób°‡?M‡© 0ç8‚DiÎáG~Æÿ¢%ÃLì|Y•|ì“ÿ!-•PÌZŸlSÙuñÙIC‘š€ÊEÏ^“ðœ™!$q¬uŃ22)p£‰ 1\%8‹¢1%(¦´Yè¥(š3²X…GÆùÜY8*³ÿøÊ'•†KEIÞvÓ´b0_á”­qˆ¯'ãùÒ'21—Q|9Œe…’è¶ñ*²ûÍ•ù¸X¤ à ýJ¶gŠª#VV¹•™îÆ/„@Ð.2,ƪ•ž2U‰¦èg{Jµ#—¨=FpŒâä2O}ýSò‡ýXí¥ˆ)†¾†³Hr¤GmªÐ¸^|Á‘õ*y¿ã°›\Ðjý¯!•KÑo-¼}-š>ud1ªlJ7[{aðBÝVB HIRËZ›¬éõÓ¬{"Æ}6EPO„¦qì{§̆»‚pIÓù%{Å“©x7Ó1c΄‰UM,­ªj°{}ÔËÌ—ÌF‡äyÑæ|0 Øë¦™3¤•„‰˜HI¹ÀŸ£ÌŠÑrÊ‹[¡mÈ6:M…ýÍ1Ñ?RëÇZÕœŽÊg½C×»T"˜5©!›c[ýFFä0l‘¤Çwšmép¢Â@0Ø‹XÁ>˜ÐP½^k®ÊXls—ѦμseE¥A(·c~Åüòþ®[ǨOÝKW=Ý"7ðøsa.W¤ë•xÓØpÆ9½TbçJoB Øžž"×Ö}чP>==µ~ì gNïRÑm)!€Ï]ìr¡LÆ1=ÁÃùnœ [Õ:sN’ Ó ?¬Ý¯ú/QÉÚ¸<ᩚa•Xò|;È%…ÔàÈ€<¾¼ùXõüÀ+ÊżlŠÄQPlXøzg‰„‹±Ø*‡ÝX\Ôo>† ËØÄÔ¾\ÿmfež×­L­A”'ýB"ÖÏ{­’ßj¼dHÅÙi™Œ?A÷L‘‚)diŸ ¤‹†®mNs9ÝÏŸIös¿ÖÛÄs9ü„¥Í£}EGfô3‰Ð>fÏ>¶šûéÇR «@WC}ëÆx^œ—ì%b’^ô:#.œ6ú1S>n!Í Ú-DFÑŲDŽpK‘gvx;ˆA‡¥ T˜v—ƒØÙt5¬-e˜æõê‘ýÐO˜u˜§@E§ÚÀºŠ\+t«n#ìÝØVä€PªLÕKµ¶[Ÿ% öyS‡N‰TÌ&ˆ‹‘¨WÞ³îU&/ëûh€EÃ"¹~¥W*U=/Êöâ vTv,ìó;Wk+É`¦ý¹®(Ú~ª[Stü¨þ‰Üšžë=P˜Ûr©þm’ì¡øøtì¹AºP¹£qY\cÕ=­2\%ùÅk£r™®h´Bq¡"Ñ&åŒ4=^“žˆÊw5þ>¼j‘V{Ñ#m5ï­¦‹$r1_Mù²pðßÑê{³‘4ÚÍÆ(:×Ìr¦`¨Âvx¡ó8Ëf ñO¶Ï½ÇRëÇsûR¯%TÀö$žޅêü"“Á}„‰';+ƒA ýÕ%ºÅ÷÷mÖ<{ÖÔÑ]pó × _9÷Qc`† ô)?ä/^ÓYðgø=Ͱ¬³ “Žbü¿Â”i÷zÀø/&œ÷'`ÄÆ[nâb¢`&R/2¯LâDGÖúJvÓeš1MèòýíñË«Ë[°>žhÝ€p¢º¼jKDòO=ßä0èmþŒp„dÄf„âלÞú“ÿ»–æQ¬îf®e”¹Ú‚”¹¹ë~9 »’ô¢KEº©Ub›w‚ŠÁÁü+ÔÊਲ਼N¢ äK}p@(¬»Ù:ÃフZ²­’™tåÝRÒæž“TpOw'-tï÷I™º¥®¢þ4L«4¸ˆ-^$ivŠàœ= ]J!n‚£N2©oî N:% «DÍåÖ[äøòAç>Õû ùÝNö“mé‹ÔzMÁp€lM›³_àw°¤ÃËŸ^¼ÜkÕYc”fHºâ·F‚ÿ£z¿f惓£íeQÍúefK•ƒaøO¿ÄsÏþ™êÇg/²ÑÍÏÒ–7÷C¡¶e³ë Å'¢æ¬5¿….…D¤¦ëMÕ%äÍGaýwwÓ3Íz«nmÝ ?ÛLƦevW3è3⑘Žôcž… c)Ìî¹&G˜U†£â.¨–ð|ô:‘ Í©¸](òÆ3|ðM?É-'®¾@½,Ø(Køaá_ Ai£ežœ²ækEK¸Äw5w9‹ ~¥Îòh¼6@FS€%ìèb½‘l~Q™ÞvZʲžC­ÃƒÚÞYÊ{¬%™˜_|uÙ×­4EIŠU¯”Ÿâ2a‘{%¡ò ɶ0 ¢+ÿáœH0²â:‹Ùò¹‰x‡Õ™#•Ö¢¦æŒw±‚/ )®ÆÌ`˜†íÅ£Kǹf°5÷a®ž“aNæÂ¤ýÈz4 Þ° ·0£Ã:+þq¢¬ä5çW£(kÙ ùÒìÄŽ}OŠø®•þŠ#ÿ°*ò«Ù™ÅÌÓ5šKøgk¿Ùü…Îcÿb?gîÀòìBãšÿÑâ¢î·±tá>¾Zw!Wî/T®Á4-¨íì£="<'{›/úC„þ9ÑÏ©ÕØ¢~ñ'ÿ•ÎBõøžw²ÛèŸ+¢ 1Ú†2õè'Õ= ÄPϰvÊϸ îÂ/JÖ÷¢s;Ž—U·[`|þ5¶\(×rÎ*dá­nÉ›Ns’€FñáNqÞ´S½º<™½Š‹Èá½~üå9#÷´‹Óáè\Û.dxd?Œä[J ;’D¼ Ñq6ô²æ+Góî}ÇwÓqÄIóvËÀEÜò"Öó»8“ó­`I@.Vãˆe!Q—D[<ºà¡©ÙÝŠ éîËåû½!ŽoÊö¢åä¨R¤–Œê»¸§añ½FÔ<„‹Ü0^‰æÊ)·(óçqŸ\Êöá„|'ÝU$GôâŒö {¤ýšVÛ}5zn¬RsÈQ»lÏZòÛçˆzB}¥œì…lGìÞûðJW¤k«¨/öÐ1"ã¿Zw"=¡g¾oËøb–¸«Õ‰fL‡=>Ýyk¼? èDÚí©¨zïþÜäAÆp–æ‰vn«ÝÇçg¼´e ¿ó^©©ƒBל1ywrsÅùå³m°æ&.rÊ·£.üÅ,>ìÐÀ‹Ò­³O§Iø7E+… Ÿ’c­3Àgf9iø¾é:rÒÊ"re0a_ƒ¬d8D™bWåÀ?¯~̓ʜ†1‘}¼Ì`¥‰§NŸžák r>6w6ÿ´´:¨æÍF)¥YH/Ã)ô ׎‘Z´*æ\ƒ<'§ÔÓ3•ÖÔØÛ:K6lcxªq壪Ý~òÆ‹¹ászÃÂ&]íÅÃ……ÅW‘Ú¥V?—jÙn«¼/!Ûš‹Á'·†«°æ¶1`$5lÌõá篙pͤ¡±¼íž ÜR÷œ†¥|Éc¨_» Ô¿®=Æ‹ú-R „"´ÈâN?Ë,j€×š¶0k%(d(9гéHö\ëzNnZ†–Üdž6HìaTa7Ù¡gž&gÔG/1W}p™ífÞ‡ÍI™oÎG«Ïœ=*ePž–öät"é4º•¬-óX¾½S†@ÁßiJp-{¨“â§"Ñ5‰ÍL¨ŽK½¾Pâdž$Z¿Ç'[QX¸Æ¿ßŠzª¤74F‘ åÃ;ù´¼w«ðIe<ûeÀ;]×v0¼NYgpcßw²å ªïˆ¤¿ÏH¬aˆ×Ŷ’¦šs 5]:0E+„ˆT}­Fx€‹Ïì¨ìõxëô[Ïp³ñ(«Kï vWxnóáÈB̘ø ®4@ÎÈ- MY6::m᪂tèx<œ_¹¾gò¨DU£¨¾‹m¡;ÍÕ ¤Ë${Ø(-¨RäËÍÓø~ôõÝƤ¡Û‰öG/f]£áïðçT[2­ÓÅÑÂl¿z™ºô& üb}Ö”€R×Ο¼‰HcQAÒ2L~”Ìgù$r »g.£w Ç=*dtp›kíwƒÐWGK¼ïÍ>%£à+ªý—ÎÍ‘&i9Y°9ñËsÛÉÅb×pEÂ\7éŠÙ¶`qO€ê’²þ¾%\?jS=æÔÙ3Ô %Ü AÂpî—l-åêsÚf:¡n”Éýrí¨ÀŸÓ 9M°ùÿÅD­¾ endstream endobj 64 0 obj << /Length1 1614 /Length2 13484 /Length3 0 /Length 14314 /Filter /FlateDecode >> stream xÚ­zep\Í’¥Øb‹[ÌL33[Œ-Æ33X,YÌÌ –Åh133ZóÊßÛ™Ùx;¿vçGGÜJ8y2OÕ½QMA¢¤Ê ljo ”°·sf`ad樫h*ÙØ™ZÚË1ˆØÛ˜>Ì𢠠‘³¥½˜‘3  4ˆM¬¬nnnx €¨½ƒÈÒÜÂ@ýACGGÿ_–¿!cÿð|d:YšÛ(?\6ö¶@;çˆÿçDU àl˜YÚ¢ŠJZÒ ’jIu€$Ð2²(¹ÛXšä,M€vN@€™=`ó¯ÀÄÞÎÔòokNŒXÂN#€“ÐÄò# èntøë¢8A¶–NNÏK'€9ÈÈÎùcÎöK;Ó¿>ìföÿrÙDØ~ø>À”ìœL@–΀ªJbÿâélaäü·¶“å‡`oöijoâò·¥|0^g#K;'€3ÐÝùo-c ÀÔÒÉÁÆÈã£ö˜Èò.N–væÿÅ€šLm€NN0اó_}þîl<þɶÿ'ê?9X:;mÌáYX?jš8Ô6·´ƒgú»U¤íÌì,Ìÿ²›º8ü‡Ïúg@Ô÷ Í #S{;€)Ð žIÁÞù£$€úÿMeÆÿ9‘ÿ$þøDÞÿ?qÿ]£ÿãÿÿžç‡–p±±Q0²þ“øw @ð÷%óÙZÚxüwáÿ© üÇÿEÚÙècÂvæb032ÿËhé$aé4U²t6±˜Ù|L黺)dciüPóŸAX˜™ÿͧfaibm÷wìÿríLÿú‡@ÿg’—ÔVÐT£û¿ß¨ÿÄ)}(ï¬æáðAíw"ooúŸ‹¿(""öî/V3ËÇûàÃÍÆáóßTüˆå¿ÖòFÎ Kw€ÎGÛ™›ÿß¿ÿZéýŒ¸‰½éß½¢êldgú±½þÓð×mâ}¨úωÿhú?Öÿlt Ðh¿¼`oÂl•–ñݹ'gpLL§·›r0Ä¡¤A­0߿ھË/-|‹»Âð¥&„±q‚ç­ÍcþÄáuO†v¸Û†ª+x‘GàCFÓ“¶NÙÁE·Ȥ_‚ôýT3ÚërNnJ›“Yc{LYE¿ø†p¢ƒ {yOãOæšïI~ç€ìk’Zÿ ëj#zmÁÉ)eâÑýUÿÈÐà@×tÏ>]ö78 ^#ßä’$gCÐMƒÉô“+G|œ;á—1º ÅàýH¹cÈœ#-ÿ£lM~A’j£2ü¿fÏò‰Ý/SûðNÔÖž¯Šï,ù‘"fwAaÈ"wRB@µ¼:“ÓÁSÅй[Lã€:iàÁR*/i’ófÛ* ®|\JÂ$ÝtÒ(ó7ï(Ðø”,ß*b€?ül—øŽœ¤ÄÁwŒ‹M÷~ËÊÀ!z¾¿àE¤‡æíGä^ì{£S¨Ÿ\º3|HÓ*ħ ÿ¾:r¹£â=$wyè¶kÃiæÛàMý—ÙvTõFãéVݵ‹úï%æü·¥DÄS¬Ø0#Íö‹†ÂÞ½ÆA„Õœ1ŒRàe §ß0囯´Û°J~&Äa¤JЍ5âhçå6ª€"k¼*ïYª'+3rô+iM=M@´ÉÑF€)“0è½{™÷ìdºD3ýúiBnØnñX  góhzzÏi3twæºÌDŽbO¸“›ÄÑü©æðoœº¥âtJ·Š¢'˜V‰¿Ã9ùéó3Ùà¯Á,ªBŒÄòrµ4™aÞ‚a ÓGrãCC@°;í(’/ƒß6‡ˆˆUÏ 4«øóžÒš­;‹MìbÆ7ð™¡J¹×a2°Ÿ ï7£üÄʡΈ*²Ä|f ügÉÃHP’0Ìa‘hñ_5*›ÈÊ¥nx©ïÒŽÜU%sV¼ÏAqÒOîÁ<::(ŠÀ€‘/QúØÎÏçÛ_Pæ1Bt¶Ý¦¬©m–¹%Æv(ýT9‹˜e:Adb [½ïUúƬøJGPâöןòȪ>‰ ¥Jšç åa„£ØÖ²P0tú ©,Ñ‹õ­I|P"(4¡E¾»­ö•„ÿ´m†´Ô“ÛÑÁo-&ïÒ…Uü7ód‹•Î6íL9[þ•ªí8ïvâS2¡ÆŠ…=f‘Œ@D.!2´ï³M£BBª\ãj¯,j‚NO޾$œ÷®…œÆ—o™…œ²„:Akcªù!/ñE'³—éÝR«h(n:çàN¯F!Vï<B ¤³b¤Ø9ÚÌU¡{fÁ+ ‡Õy®?@»Ö ŠmY¢”36þ|`².|?]¼ö2ó=~IJ ú}&zh)O¤SBµ°)ßËÈËÅŸøD×AÈþÕaÜhxÒ³tcö J^Ýq†Sà/ˆ€¡KÒ¯jÐû9Äã#ˆæ ø{5\ð€î/x›R‡ž*®õ_ÊdTio\Ú!ôª²â&·’(ÛÖà`1-IyrIM kVòGšÇ¾ôUѤ_Ê„ÀS§Ëî=Ýw=þiºaä†à2¤A®Ñ6wRHÙ0vç•¡oc÷%UýýMs]ãâÞûâ6èŠEe)Úu«M18”Ñ:*5×Ûü³R*ßr¹ó…Ž¡–’Æ÷³ýí´âVM€ïÕ¦Xt긷wv¯¶*]ùép>uS`°Vöi#¯ü)™ þwòìõfÐþ¤éþCf> MPÚ;ßÁ£7¹–š[MŠsV‚9FhþçÆG²1ôfÒhpèjƒhBHAø%:š0 ±0*±-¡ñq݇¾ÈOœ!ºýkú#1vœª á{(sÃ0¥`ñ#-eŽRì¥Á…É^hÓÛ7æ"k4?׋ôÅ¿gb“Ÿ3 ÔNBÊ äÀÁ«Ê!ç—^Ìwäí°d"e:^‘Xñi)x¦)Z)kÒ{ÉŠ ºŒ`Ûg2ø­ aïG8Ñõ6em=øòOÒߥ»#ÒsŒ 7/f7ûAš&Ÿ*±²¨ãË›ü(RåÔ³HŒ]Fý"—+SÌ^㳂6CÚe1JÄ\]¸{^96ÉHŸoÓ\\¼9¹ú•µº ب™õ0Œˆ„sñ¬ÝúÓ!?‹RWßÄI~Š‚.³øãÞî5 v‡@±î)”ÍSËY£X|ƒ½2Ƽ[ÙUìüâ ËHr<ß/9Ôµ¤Ð\Je1ÐjU¶Û®¸,ù-§¦,ÖÏ}Æ&âê«Òç9Þ ]¹>&ÔØ¶¡„ÀþWR1)*I7›R8ÁŸ0" Ÿô‚ç5Œ‹µ"¼x;n«\uãÒÓâ­ GlK j…¦Ê. &ž²ß:é:²Ã2Ñ÷'‚M=nUÖ€ç8Y#ìB;&ÈÒ~:·¢pØ1©üYLG6„÷}¦@ÑÝmÒ9pñgûè2"?΀i­“JyÌV ±¶ºy©Õï_×bïôÚQ‘ÅÛ÷G‹>3<±ÐÉÑMQž.öî•K¨±LËÜÆóž~Ó¶æáä{é®Åw n6¡‡KiÒEów±ðR-õXæ¦ù§N¬Ä_‹Â°˜U(È—ZLg”q¬@BXM4»y67¤ù&¦ÂÉð¢fÖ\º¬8Ÿ‘d;Ëç öè’†ÃL¾Ž°Š°4úI,»ò“g”@ʧnú÷|ÒXé'ýÝ"Á‰¬…éûG§K`û§ƒ^¤ö¹þË÷Ÿ¾ð«ÏþöÕ¿9‰´™WÜí´rœˆ ~Üx㯼#hD\ÿEÇBs;âÛy;`Cy×^;_)Oî!¼?8êêßë„:£‡Ö¯$qÆVëlùàx ðV/QĨÅ•T,hv8ê‚Ü «êó¸Ô‹ b%k™ÃŠô±:\Ö^®MYÛeÕûø§}ÛSó1e¬-ùñA‰ÉÈľ1Ê$4`å»ÙԙĽD;²Bˆ0âƒ}ú 8Âĵ©*fQÞʸ¿½‰Á/XÇ'ÂØ£Ü~àÖGÖΡ#HÓCãuÙV#‘ô×£Ä[ƒ÷Ã0yòˆ(5Ó_†t b§Ì«§üòTÐ1˜qîêO•O 1æ_~ÐOµê³µŽøííËÐZäã¸NŸ O¨ýúRB²­{‹1÷CÑ¡ŠÇAí’,å ½®¼Œ"° Ïu¢éò¡hj>Œâ,§ýo¹wãRi5 ŽïÏÞ”Ò!‰î_Ü»izÅÚ„9øÜ"Ε;ò"fÞ&Uâ-ùê: -îÞ»‰Æ­€æ]A(Ž6ÐáÆ~ bȆÅIüIdÈݨBýSÓì° Ü>[6•äsÊîxíU0Ï\Ìo¡¨ýGÌøŽÏ¬‚uMR³ó×MÆV’žµ.몇zsNc²Sì§$d ­GË{§c¢6˜sd]¬7¤N>tÊÔ’¬aãëB:™ åê™§0¦fÜ#ˆ‹£Ñõ™]†üÎ'v¯’_É¢¼Îy+ÅÀé°å4˜ýÊ ‹JJèg«ÈW?Þôsè6÷íÌÃûuIPo¿Üç&Fï_þŸŒ}Ùô‡ñ^¯ïhîS¼"j³_`I×Ö¶(•ëj,d.”уJ šDTlÊ9›;|´BŒ’wW¥ˆ-p¸$!ƬeÃ"éô4ˆSq ÙJ * -ž¸kãÔ3;;¢‰FðºŸÌì­„´³¯"µR\iÎ7gÙ]ž{:‡ØÙWÜ0–pÝsæ:öþüfe•Brz«ÑtNZ ÍÞ¾Õ”f]x£ÜòOa¡­«É&ú¾íHuɱ—Ú›9Ü—KC2…ªD%†ëño¼£h¼cÎÔ|²‹+î_YX¾k‚òPh`:UĈïßÚÏ (ù¹ÛHß±x냧ïU–’¸lÁ‘¥#Ü¶£AÀ¼úë÷ÎCÖL="ï‘1¬~Â'\Y"ü[¼ç_-í­—wk²<ÇâÂZ‹H«DV·Ç^uîá‡Þ2~ °Œ§Ìa~[°^¦‰¤QÂwÃÆ -^ƒ'©ñ!(‚CjŠ´‘$/tŠLÅy{ î/ý6^|iWoˆòòŽ0yî¸"îsG6'¿lß!();—©¶Ò/"Ã8»ø´ðG4ç„ Ø‚959г tbV¸Rjƒ“âáq*{¯¦?µbOÄ£Æ÷)Ón΄«œ0—^`³è)nòÓ©œ—‰Ù¯>‚¹î±Hë³pɼ$åÚÒ .}·¢§ÅdÃIˆ#b{â’§=Œ ‰ܺ% õ[¯XUÂY$…ÝnBT•¾R¤RMÖž-°¤B÷fˆá3μÉ#Ÿ}·™×OPb2‚'SK@aBÎVÏ5èETr t¾Ñ™V2¬Uy+â”ë¼”wÐæ­ZUPdV𓍵úøía…+žÌÆÑÈEMànÚÕlIºï|±BjÁD)2C×WõBr'^(%iŒ–ÇfÞÙ+©]ÙG¬b¿ø®<Ù!@vlã.>‘Ë[aüu;'O‡îêŽÓ®Æ!ßÁá6~ u’³ùü¨âx’~䘗6~÷ Œ8Ÿ ðbí ¢[“þž\[a¡¨ ¹¹ÂÏ^8WµÖ$ÒaåôÀKc6ǧ¯`×6=hþUi4 ™Êž?°Ë &åw᢭K°‰¼œzdìSÖC@=/¡pY ©ÖŸ® –jºrkTŸŒ9Òüb«.)§ž)·Žë…‹€ˆ´"ïI,ƒêvçiMŒjüR,ÕÎÍFÍãétƒXüâV•%¾/u[Ý+õD…êåÁfH]=ñÇGž·ÔÓšþøò(½!Á™NÄ#$âµõ*Z|¤¤<-ãä#2:‡?ÚûVj9UÀ Y•ŒDÔ¶Ú(ÅlBŽdæ bj,êP9~\mÛV²Fp˜hÍ7LÓ^*Šñz·±Kíƒõmwø=æ-[ºœãH¸¢SèbúöØù­žn)œ®ˆéêSþŸ°.è14¼TwÆ…ù¾íéInÏAn'Q‘xÄ6¤D·AQ& Ld`:Çš»?Ìû _ûm|YñZÄ!ÞÀ­ò‹àWh ÚrÖDVÆv®K9¯½Øè·KHšK±™Lø3b>3Týháx[à1Z¦O ˜R2°|OÆÞ”sh>°n R]år†ÊšS9 &˜uå£wŠD™wa^yç?ÊéŒtœ²6‡U9_¢gþácŸ¹U¹†ìô€®Ýˆðˆe¢(ÞÞòïwcqîQ”Ç¢¢(ª¹hzÔƒ‘dØfVf¸CÃî|’qr 'ûÙ½;Ø-Úï}j„|JàÍ,& +ƒöÊŽðg 1µî«¬/˜2ªï¡{rïI~É8Ómû{âiÊï’öŸFÚ45ù °q–0xAù©º+ßµ™[1e4÷sz ݶŔPb²P,”iBªN•°e?èZÜ®õSUm³=QÏÔ½xç4¹ÝRën·7¯í|‘Jý5ðŽm#5¹~óNØHH8É‚9s¸ *5 Òœö†¶üþztÛÕgUÅöð½ÊIÍ6î,\¥¿Šøë,CÀÌ®@¿p $ƒ×2è"÷ÂÄŽÉZ]uÍžd&Î °¹<9)é¡ Mi²™;D¤îƒ)aÃ3ÉqцPú™¬S­ã©ØáMÒJ˓ؾþiùTÁåíöBèNçó­çÙ ×&£ÏbQjõ½¹ÏæYYu$Óu ‹%n¶Ô äs*]ÿÒ;ÿ¢3þƒCVG~rg°ØÆÔ¾YÉBƒšeð6¾ÿ«ÑJUBœpïy®ÏçÅŽQðBŒÁ;õQ¡‚ˆ8±¥˜èuÿÎK²ð0»<‡K ž¦!QR¾%÷—5r&Xt1º}3¾7$æý¶.¢@aM‰“ÄØðQVx+ýîp¤O{äìõ•]æPÍõF L‰¯Õ.Ÿë¶ƒ=ÄKÏ«Ž©±!%S_~¨ÂÕ–•¢Ï,„zÞßq\ž†õ®œÔÅŠn»Ø‹Ý0kN;DM#ñÿ~ì3|­ÆðG@:‹yœƒ'Î}Zg7ò†VË9¯ÚŠ\¾S¨WàA©.„J=ý3‰Ke× [nst~îH‚sCF"ŒòŠaœ»ÑêÓŽ’-ýOÂÔµ$ñLÔOÊlr'P<†å_´›ÂJŽö±!ï¹_.º†šjp²‡ C«Çf ŸŸ„HÖb²Q>3§D3˜Z5‰Î(¨L „Ÿ­3zÊI[€« µ…€Q»vl3ü „äȳ}8Ðmˆa›áïpc¯ÇVj‹6¹Y 'Ž«ôø+8'úlFT6ÙwÙ¿šæ‡ßÏuÊTnþùOØqK$Œ|(½edCI,Ÿö-ñƒF¸uƒwy8£vb¤åó'Ú€¦QJ2ÛÇýÎ+£§Ñöz &Gs¸¯plÄéØäPYo#øs…°Ã×,åÇËß¶6ƒ~%z¬o¡¼ÁOTïÜç­ÊtJ¤v½ðé+P#ioÁAm;" GfÓò¼¾l7Å£E|£S”Ã){Pôç|¦j›ÍÄнŠ*<ðC¼$#>ñQÈÝÜp“+ËYKãúÇŽ›Ií~<ÜÇfŽx ]ÛšBK·ƒïKÖ{–´ä¸ˆ]£ñÂa?iÔOýN­ú^x"‡ ‡ž°ÓgÃÅ¡@ü×HT}O]ÀãÑ]PLº 54Ø`s$°¹Ã3½ºVÑØ“Z¸T¸: é×ÙL0ɨ{¢…ZTymqqök›ëI3YàlP+9t,¾ùD”¶ZÁaR¼%¶XL7@b º3W³óSÍJRäYøt+§:0BehcjgX|„¿N[¶Üÿnv„£èü-G×Î;[¼';Cw‹¡,èøªÊ¾=à) p?SiŒcå&w×G.Gynw"Ùç‹_LÀb;9øâ;ÜNEïºD™³6 ¾‰ô©o*ç¥j½ó­<í\ñ•Þœ3ŠºiD S«ë²ó\\÷ ]>©r:ØëKóü¢×лû*£SR¡Å”ú ú‰Ò*ÐÞ`i„_¶Ø¾Øê——g!NÑ«˜·íÍÐæ{DëÍîFÎ;~è )aw|Üd /ÏÒ¯)"õÃ"ŒËF !~Ç=JF^n±™²COÀ/´ä!+«Å?¡wõc×#Q=!Ê sýì$kª­±{ *žvAÑeÇ™{ú7ûwž *ÅÓ('¡Im«®‘з6ì z¸ÂŠi«{bþª‰èò’oÇCt6¥â=È¡ÓÅpšÌèÕ%OPÎ1:·[õÁ§ä}Í¢Â0\õO>`¯˜O](¥P!hh¹NÕó<3Ƥ ;ý¡ÍT¨äºô†ÊþIëHð[p=,>ë ü‘·ÉÇrÈ’2 çk»ZiâåÉj)¦ šëÖ˜0,f î£Ïo_i·Å.i+G´àêòë ˜m¡p@IEóýL=óÆgÂQgÌ›ÐjùY> nEÍ÷ë‚Ðå#8M×¼¹Åw'ǺýŸÎÚË1²jôcþe†ziü?é‘‚ç !át› ‡IýÎ]$Ï ‹wUTz2½ï§ˆ<š\à§œÅГ>¦!›ÎÚ’Ùþ2FeéŠO5¸èC PÝ2û.ºv«š5ü Ê:‰-™™(Jt+9²ê°î"gË9b⦒gähܽŸyqÓ¸ù Ÿ@B¿kŸ°Uȵ1õb‰ ¸”eCzh63íž jGŸÛ=yÏì¸9žp lˆå‘Ûed~q°„*E‹´AéóÕ™fx¢Q%®­½¤>‹àoÊv† š\~&štd€çÚ å“ân­ í@pÂ#ÅüÈ<uéQhÍ)7Ÿ~|M¤ 2¢}5ÎëUúut¸X !1o³ËŸr>8ω™úÕ¾‰a ¼Xê§—†ŸíŸ b/É Õ¼þÕtnZû#‹u±T§ÎSÇ®A¸R–ÞÞ­s9‘ ^¶agÅù,³-[Aa£ˆ÷(eÇ«(xßú挖Ђù©J’+Ä+:—À5öÔ±´c›_é‹’rï¥7Û4Ä6¥/ßÛÓ‡_Xëìœ~†ÄÝýF­äžñ8QuüšÉ»r4h©RÌùLðÇÉüd7c´å¢{ü¶JܯÅÞ<õîi‘¬>¿€ºÂÎÉ´þYFtÒ)U£í€rÀJ /f¥=^Õ¸3ÖòäÍE &géòÙ7XâCëêç§p²ÉOæà 'Á8øåÑì‹|HÂp,–åh{ ^LÙÜRßuˆçœzÛý¢ÆåIÞÚ-iKl_¶ÃFF½Õ¶FžÖ ¿³7ðÔˆòH¢ŽÓá2GÛ.QÄâˆ*¬ñ0s–ž‚.öÌßzpçEo»Px›D‹-âOÜ;«l[‘„ñÆ*`¨?„Á ˜Ñ¿úyV'rŽÂíf3¹]ýŠÛb=ï ¥mPåµUúBœØ`/öîöÍ +Δ_õWè¢Ñ&éë ¿>Åð<1» LFvª2¦ÌÓãRIÿr3GT%4&@ÚÒìZcÝpŒBiíÍ··R©Ïml#ÞÓt´¬çEß"ÓeZ`ÿÆR Ç ù9Çm´v«˜¯â½$Í.]7J#_|ºä©  ûJNè2³›–É;g…ŒûØhÝöpúƒTUŠBÒRÚQA(á2£ŒBI]ðË ÖÏ|¥ç¾'^1#ö*[¯F™®pÀs–g1ˆ›h@Ô 6/4eDfÔó‹|†"û´|ÙåNqÕiÏGÒIé]RfÇgöl•8E˜Îþâ Þ袩>TjŽæ^ø]ܸ…‹oì<Êï8‘O"2U”4q–=E¨Sê¨OÅ_Ÿ]¡™_=ÊO“DËãIcAØpý±¯ŽÚŠ«^؃ N®Û¿zÙD`£³d¯ZR–n¼é…¼Ö+Æû ž ºAíjÝU>$¡?G;õ’±;KäÕeBŸíõ{5šÃêJz_C 5øZíñ’Ü´–îCrœ7š#¯ö«nåe¦ˆ ¥Ø£Êj‡I÷ ÉήÔÖOtHòáGÝ8UŒb¿×” ’Â0zOFSA‘%¢Og'Qo˜V¶Ê$´¾9ŸAÚ·5 ÷Îv*ltE[žžàÎÖ¸Üuyoã:½¡ô˜*6CL{&ÕxP†ò¸ï·Ã€óV*ÆæqO¥êsjò4$^hºâsWñ__@¾ÝÖ#oI­©’­„¨¾~?÷i×4bŸ\äR#Öy{6QD}n¯Œvª¶{E†U÷íE`Íãø:æýj»m!~¡[ýñ”›eçè¿£â¹(—÷ì·ùKTN¦’¯WJ=¢d-4?³©ÂpI5UÄ£Do>i‡°M¶Ô–D@rÁ~lGq&„ܹþÉÙŠARàzÖ¼)ú^†döøJI.¦¡ï¡AŠº©[‘}BE‰Fò‘•¦Á3°QÌ£‰ç¾_ ì[2Ë7Aø-˜qbÍŠåÍÌÑçLwi³ä?y Öƒ@è¹Þ~¥<“šÕâ‚~]­Ø@TV˜?),n4>cLN’ûýÒ7ÐÆ÷Ñko9\ïú3@¦@÷fѧšá¾=P½bÆq§[Ésþý!oÞÏ a‰9òá{)_ƒ l§K:àñ2&/â­i6QbQò| %µÐi/­½ó赺ÄY7†11¤Æ³ÄêÐ7J&¬ùS`Åúø8€¾Q¯å§-zWÞx²¤gçC<}Z•é±&w…†¥¸KíHxž§A½Ëa­é¡ÀŽk‘…³¦2q!rJ,–S×Ãe•C-¬ÛÌ´ùõAî2H…ïÑšÃîêçÙ!›ƒNêì¥+a¯Kº²Œ:›Š\ËC×þ¬Ô@E¨7¹Òé­Dr-±K?mèâ°y4º,ÆlþïU–úQä{3ìŽóüë×?ˆ×_î9óÔ7ü „O=ã_Ò[1CñX½àwûºqUXPpÑŒ¹®®¿ê„'í뽫ò-Zê‹¡¤ÿòŸz¨8öò±b~}ˆxHÆ5Éß„U«XÙࣚ:V&$vѯ~·zÂPåÓ@GGVè © ƒR™íΔ*øìÇ^—oo~kÿêh¼æ‚bí“ Pꎋ´ƒî[78-Ö颚 #1".Cˆ'>˜WIeÚ¨gd¿}k¿ŸŸ‚[°JûÊwIÝ-•çÊÇ?;^"•ùØÎp­Odîn½ž“ïÆÖÊ¢ý¹¥Fb&¡1Ç÷ïã|NwSÐŒ™ß~ª\’—ð‡.šGíƒâaO¸L3!áKU(<{¾¾×Z1ÿ ó@ûòZºBÃGz¡Ë> |6ɱ†[é3a5éK¹eÀ“]ãUyoñBšíYŸ¥U˜k¥n¤mStU_äæÖ)_òB“ÅØ²+ˆ%ç€ZsóñÄ%eÛí¨¥»»­ãrç~—hŽ)ZH׬ý¦Ê7šž@U¥P0Ì[Ø)e¾VGŽì§ faœýb7Œ‡ù‡Âœ~–þÊúA½^–4èןð2ªzûòoš·˜ Qˆ¦†#î`£ „õ¼4¸×­LBà…õ¢D÷ûÓÀÌm„,D!ƒhÆòÜIeW‚ìÏ!›°?"¹]ü¾˜ ~Ó×CËh!~g¯×"ëÎwk¾pžÒ9tø/¤È ¾Ùkt“ÃB¥˜‘Õ^ÑŒûc ]ÌìÆ½¹ ˜ëùØOüµ²@ä¡!¸òàÊã½Ü…"4Ý@9s¥7²…\ë@ÚdT{T±ËænÖ­DÄjg¤ð…MÏ×Ú'œnÒl­ ùS‰þ*$’.µÜüáÚ^Î0"5hfÄyl݉¸Ècÿ©X1f3ý5µ{íì pz©2è×ü”ŸJʱGОÌâÕát­xksöj“‰@ë̆ííZéFÁ$v^Ä%ð·@j0‰U&]Zk g0ÿÜ$¦Þ/]ëѰßz`A¯|Š`ÆÉI)—X!L¨÷†ò?Z9eÄ”À– ³sh‰L½‹©u'F{²Ÿ¡—s§¿½sãzp~/W_þ%íƒYnúÄeÑAOzÁî;Y–ˆJœoïª)Æ[1CèȇÄ”ôqˆÌ¾± %´ ‘ËY~µ°HµKÕ/xÙY»‘Ç=Ï-“pR­¨YKÞÀ©þ$*‰½¡ãÀSÖ..à ¹r»Äa½ÓO*í÷†?­>˜äÔ‡™4â+'2 ÂÖITá™Mò™÷˜ÑTã7~½AÌ¥†sÄÞøþÀ(…cÕš1x†˜Éô«&­p ³Æ10„Wbt“óe‘L\\ªãÌÛûÖŒ±+_Õ:‡B¿áë'>›”¢'ßÓ9š2aÅj¿M]œXÞ_lŸ"ì2ûªoÑVóÜsº¤›bÍPüñ…>UuyÀKIŸz Ì»Á6NÓ¨†n$mg‘u…TÔCñ…+`}ѧÄZ0¬¨@°ÚÇ€æËÂ÷äS$˜\’„~‡›¯ˆ..ÆÁÊPu osI¢iÄ}íÉéÿÚÔ{EóXrÐ1‘dà3¡ÈN…ªAöœø!‡‰žy !"sô h§ Ê ÛTâ •Èÿ˜K?5 endstream endobj 66 0 obj << /Length1 1616 /Length2 18911 /Length3 0 /Length 19746 /Filter /FlateDecode >> stream xÚ¬´ct¦[´%Û¶íTP±mÛÉÛv*¶mÛNŶU±mã«snß¾=n÷¯þúÇ3Ƴ4×\kî½É‰”éMìŒbv¶ÎôÌ L\DªJê †ÖÖ†&v2ôJv6†DÝl0ääÂŽCg ;[Cg‘:À„H`Lôã3''' 9‘°½‡£…™¹3Õ_ jZZºÿòü“BdäñŸ‘¿•Nf¶D\Övö6[ç¿ÿ×…Ê‘³9€ÈÔÂ@$,¯ ))'ND%.§J$°8Z)¸Y[ÉXlÔD¦vŽDÖÿaÛÙšXü3šÃ_,A'"C"'{€±Åß2€»1ÀþŸ‘=ÀÑÆÂÉéï?‘…‘™£¡­óß8ÛYØ[»˜üCà¯ßÔî_BöŽv3lþÆþ‚)Ø99;;ZØ;ýíª "ö<Í ÿéídñ7Ldgú7ÓÄÎØåŸ‘þý…ùu6´°u"r¸;ÿÓË@dbádomèñ·÷_0{G‹i¸8YØšý:"G€™¡£‰5ÀÉé/Ì_ì¶ó_sý/ÓÚÛ[{ü[m÷oÖÿä`áì°6e€aþñ·§±óßÞf¶0ŒÿI[S;"f¦ÿð›¸ØÿgÌàøï‚¨þ93ÔIšØÙZ{™Laåìœÿ¶$¢ú¿S™áÿÈÿ$þ"ðÿyÿÿ‰ûß5ú_.ñÿßûüß¡Å\¬­å mÿýçC$CôÏ#cû¿eÚXX{üŸòÿ{¦:à?Hþa$ ÿ®BÐÖì¯L Lÿá´p³p˜(X8›™ZÿÝÓ¿~U[€£µ…-௞ÿ®’ˆž™‰é¿ÅTÌ-Œ­lÿY<Û„¶&ÿû_‰þeÎ(£,¡,#Oû¿¿©ÿæ)üÕÞYÅÃþ/µÿ1ЬÉÿ4þA²s'ò¢gfg'¢ÿÁÁò÷Êý`&âdeñù?tüˆù¿lYCgG w"í¿c31ÿ;üÿøþËÒýo0¢¶Æv&ÿœegC[“¿ì:þ »8:þÕõß;ÿwèÿ´ÿ=ê€;ÀfmÙΘ;Ø2-3ݹ3wxRD»¿—t8ľ´Q¥¨À¿Æî·_ZØg¥ÁGmCÓ4×W»ÇÒ™ýçÍáh/†5åïÀU>ž)u_òŠÎŸ´‡Œz¥ðéçêQ^׋2Û`ZìLj‡»“ŠJz%øÓ,ŽP×ÏÔþ¤®þhdOö¾Æ© ±è]HM@(u…gç‰'ÏO”ƒc#ÃC¿oÁûpisb¡É¹ 1}“ψ“œ= ¿Àß\Ùâ^Œâ»ÔËÛÓ=¯¢HͶ½MAwBa&°·”•ë„cºX”ø2ålû( fó¨æÿîl’±±'Yy>»`ÎVÚ©z45 äºîlÚC‚åETÅóf^#^µP=Þgzçhþ¾^Ôþmq}ÈÉ,±ÌØ=VBYpN¨~Z—>ŽFá’óOCø´Š’[Tw^=”ÙaÆô¸rà 4Hn+¸b¿Ù˜F-K†ÝlI¹~Ü<£qIò7ºå¶JFлákuשc‚á½`íß<–4B¦w® =4ž6Þä—…óºR‘ht¤ŽE¤ë–¶*—H|®›­³²¾q×aÍÕZ’g¦D­P¿Ð®ÖON˜Ÿ!äÀXÁ‡Ù½ÆŸHB!FÀübŠîâx̳ß8bV3W© ºÓfS‘ûjÝ1­Û /jèEžàTHâ¾Ùn×›õ˜=yÇ'Û uÉÅc{§“í)‡thõ{½Ö’p_ö×ö³5¤ŠÇŽêÈÑRøzªJw֪׊ìç­òD^½Í;ìòŠ9("MÜÉ"¶0íºr'’Ó…^%´í;+Ó¤ÛÙ§þ9TB¯ècB` Mô‚]Æ^¯»C@ÛŸ/ük;æUæJ‰oª¾ƒÄtð6ŒÖ°ý¸™”ø‚\ˆdíƒ×CØôÐîn<‹äk¬Êž†;(KQ²äÉÖÜÁÙ4é’: üQ£õ+Ës¯¿&€Ìn¿ªµ‹”ô¾ÅÄšéðåF…yîØÏ¼LØÆ2ö½®.Ópõnž vxzrj{™ãÀ—%ÞøõÃÔm’¼÷ØoNâ,³ðxñ0›·~'¦np})Q[ïx 2å¾ÜÖ·YQP›ˆŠïOžÕP>—­OÞnÝ|K øÄ£=‹Ö2ÝI…ζ0ÝJÿW°â¥wŸîM¾ŠEns°çÛ˜GàýÚQD3X\d¿²|Ì÷@?;k=«²Pð<‹À½Q£öæ‰ÙZÊ%Á&×!ÔKM€OWý*mLªÂÖ¢ ,Ûœn%„†®aÕýôÑíÖ>P†.Ë4ΤBæé«Kh®@ø ³ÕðUóK²ÕÁo„ Ý jpÆÑWÇùœN¼Öí³ËÏ4pŸµ€Ü*¡Uäç‘”Ëà„PWÔz䨹­Ya í˜ÅÌý\A›9*Ãõ]‹Á“ߺx¾W°OÖD ·xþÍEå€ ®³TòäNZ,=%|šqçr„?:¬=,—2Eä¶Õ¼HZyr\CS̘ ñÆxúe?ìã~B× ŒˆÙ´Æ~Nuöl ¥1’†¨ƒ ›‰ @ÀKØ_Š ’é:Oxn9_'ʸJ2’œs«Çð‚ýÎö½’+ápíä§Ñ®—žì_ð-Òì ¢S\ù½a"÷| &ì©þ[‡…é@_‹M'“Y÷Þ¿^nä3Bõ–‘ŸŠ•Eã^b1I†DÀ‹±,ònt¦ð‰DÆDÙ<ض®`F¨ ìœ>ÎR²„4œ/ghºA=JUÇéåO‹‡ÔwߙӞ6ƒ Ž”aÛüæE)ÎN|¼Bò(â ©ÄÇeÕ§~YÛFƒWëFé¡ÀÏéFdœ‰~ö=ú$ª+èŠÍ××@¾ô¸WÓ2¡K‹Ží*º9ùQÄg°€€¡_&6p‚ɺO?Ô–~2Z–íjx4å÷‰wŠâ–P?r÷ÓÇô! ®ôO^dä´C¯ã¾¨ì@«þVlœÛý¥¥°8} z>òBN0åÕâl>Ûz#ŠÒ‘†c[¦ƒªo@f#~1î&gO|áWö¢Þÿ(GXÑO¼<ìȾ味LsÆóiʉa—¼–^ùx,³ÆFìNìî—ýÅLwçŸF Lj¤}€#ØtÂ]í@ùÛŒ¾tè>².ílrCÿquv¼@¶§)îXÙƒV¿ƒ×åöú™F6w¨¥4õڢϣ¦ÊYÏù=+fkÑd hjk|²ßP:·k?èyž{¢SÙ a!™G'Çd±õlXÜA¥e,þ:3ôr u–Ëó¶6è•×ïÒÙyÙ¿0³Ÿ‰³Z ® B+£#KÁóqíR¯RÏødë¡ ¡“¬vVµu¡n…ßB¶!÷îºï(&ú { |]!Lû™¶y—Eð½p\È,!݉¢^ _t:U" l:Ùt5°kBO‹:Áõ£…•«ØJ´ )JU¢ì˜’Гð”IËqòbHtú|ðãj¿Š'²ÓËœ zDÖÔºF“éS#v ~hbÍúôàÀè0‚šg®KŽ ¶vòtBBÊŽ E¨@o‹%hÂ¥‡öìiDE_Ù; ©wjSÚâ—ÂheìËõè:ë¨Ó¡GþCèOGT7ßžb³ŽFW¡Àu÷ưyO› ¤ÝÎ-im&µD®ŸLó Jë ¾©‡¬5oö¤šÌF?àYá´~åÅTÏaF§ BÖæúq‰gÂsYjx(í}Ê’~·±;‹¶Ä‘éÔÀpXðƒb•àÀë!¸èCˆ®\#L‚ ÚN3Bà}výÀXø%™_ßh€áRórç"!3m+Êí0y£$:XãxŸ‘*0<¡»Q?[㎊qᔵˆ2‚“—=Å$nÜ™_ðº"Möæ[uÝUå¸áÉK—÷È·`uO0´’¼ê_„w˪äy05]ËÑÛ•#€Á\õ“[³`Ò¬ŠÙj“pgoòdMÛR9VgnÎÅ:ËlLK1Bî†ùñ­T*ü)|¶D”Xíª»¤ç´Zm^ÓLƒ5 "¬iiûS^ÄÏð5]ü8ä´yÝZo5 ’ãˆu^rÂU'y(9r¸¦Õu#ÂQ·Õj;møÀÀæ1\¶™!#B¹ûŽiô…Œ·Acyó‘.·o /QZtª^¢äД0þ¨†ˆ¼ ÓË÷ å´§kŸè»¿eoŠ–<ÉEŒ„Kn÷±«ý6|*O3KjûAù)ˆÙàœ/XTŸc¡ƒ7®Â1ó…þþgK†*ôÁ “l?NG®ñÀ÷Z¹X5FI‰/»7Æ¿gÓîᓵsu±ÿqðâ Ž€–É2 ä\ñêç…ƒldó7ç¹Z¬¨ßfÁK^Ùo$Cµ zmˆ/b[ &ÑMˆýâ­%=O*S–ÃòT)(lí9 íL&TòS.=ëlëØ¸mЦÒ£ÑöçÕ­ÔÃ~§Ò5#²‘€þX½Þ™Ù0ðjì`¥J²_lbp3,ÀÄ·bM±ËH»eˆÑªpòg1fÕoÖ„ûÌ6´ÙöËÜæjÕ ù³k[1¤¯7_&sгD1pYÔÞLF¬œŽÙI áèä`ëû±w¥sþj—zPz×ðûƈgQÉ]ªÜgHËÏ€Ôu±{.2³rv‘ب)Y×EßSœ†ËNIcïíÓÙ%L>0[ΖG²ž5I 6ÈÄOEØëÙ¦pÒ2jñ ÅéEŽhÕˆA†&ýßü›©¾v¥lغ5ñ–’¸I`<Û'VÉeßÊt÷2ãtŠYÆKd0oÝ¥ícŸƒg%†˜‚ä~Ç+Lëü¸«¿)Ð;Œ\qTI«èî%ÎC M3ªîôm²ªÎI“ýœpäùï|ˆ‡0ÛØY܇ëX‹rƇ(@Ö6Ou-Ý×é¨ÎãŠÊVÅ™4ÉCóôo I¦˜µÅZÏkeÉ#fý$ËÌ¿5„$€}í$sС"³ß7sð¿¢oJhÌœëUÀ_ÕÑ“¹®ì'·‘:FÑ,Ädºg.¯|ãOLƒ1 ¤£±e½üä·¼œB€÷£"౉84³¦ >˜lP¯i€i?Ýø~9.r‚–{ЧØÝ^˦M§èâeBŸ›NÈXx·G®€Pâ·@I ƒV½%_jCú}ƒ¢ÍëyàÈñ¥);áñ&ùy+ÜžÃ!OnÊ: fˆïM$wºøŸ¤úÌ‚æÓ ÎbÓŽ¶2Â}&Âç<ÎukS¯M‰Znðöv¤Y[Ÿ;!p¦P`A¸tËé—^ëÖšà9:g7ãN½r¼¯¼ÙØQæ‘„=Æݵ÷–Þè3Tƒ?×Óý¼íj|Í,ÊîMΖèvþ1S5DúÅÆ!Ò±¨Þ1Åç7Ïž×ha$vJ­R¨ï-uÃ92·QöD¢è £1ãë.k´WîË"\›yùy ½.d2 º¡ª84ÇAþ³—`NF a)m9÷n±É¼Ò”5AÏ#‹Ì E¸šýÒ<ËÀs†s×È ïøÚÅ””ÆV‘ÇYyÎwwPOaS⃠½Ä_}x¥ßÞ¹f·°ÖT6¾nS†¬Á:¥5ü\¬*§ ZÊâ”i9ý«XØz ºé†ÏݑȊcû\¦„ÅÛ¢Ùwx7î ÍäkkŒ¶ ”¤â©ú—~Ì¢ºâ"ãÔ[EÝîOM2Õ~E®ÞW]‰SäŒj¾*bĤôaÓ ï¶UÁ.!úP¹™%ÊxÄÌýC×Þ \èº/¡‹E¯8 ÊWŒKlra!^´Ý[‹‡R4mýkEsˆˆCd¾[ÙBf*§¶ØàžXQTÃÀg:½ÜÙâ|:ëØþ0ú1wD`ûi-ÏŒÒðX4’çâµocøþ¹´<[ ºßJß³7`9³÷/s1eÄ_QAÓk•[Uœ”dlyj¡Ö„ja÷—pºS&>á}½¥ó£ã¥÷Ú¬ÅY¢¤±ä+áÝ»k(ÌÊ4Uñ6Öìm•Á- ¶-:µ¡Ù@ÃêŒG]‰ŠìV3 ¶k'@FÑâÊ^Á2ö­¯]ÅŽ5DìuÌÅSð!ÓܲɢΰɡñÎ` ÜþûÏb|bÏU¦4mõtËÐøvÉ=B7az hñDØÖšªB«±Àd/Ö#õF™#ïþ‚°ªÎšçpyy_u}h°ø¹ßélñ>6ÀÂÊøŸÑ# :N"íF×È"iA•*Þœ8&“°;| “ûÒ€_jþóvGA°jÌ2Ý›‰l1’¿ªJy{¾hÊ:…Þ6\-ÂóA4'G‚wŒzÀpw#(ŒâP݈ Í>í´¶ï£+´Ú¬esVÜáìFúwG1¯ÁiTVoøÕ ˆÑÝV“Ið[žH2rI‡R÷5—–}m:++‡œÖûõd,hêvkàdÚ2ÑEˆì˜;2­O‘WTztŠ@C ïG@®-£rEZ]×@#V°†;´Ý8‹î´‡Ÿ‚ÐÒµ>Yv8«Õk`ðº¶nôâ¢Å"оƒ¨ï—¨ŸÏèÞ6˜s¬vVmÁ¶ƒzyƒBàæøôî=«4)F:¯Vs4Q<µB&kDÚÝOQ2{rA:æµê „ðÑÏhüaÁפèÖ“ ¬Ñ§CO~²ÝÒx͹©é¶¡eñ 0ì+Y~j°p«âgq§°7EÞ+IЀþžPxG•,þ1ÏÔ›À}º£¬Z Œö£Þƒ«¨õ”Íc´Pcé­-éüuû›´\èù]yn”UºÑ»8 úg ÒQO¬½)Mµ¹ÆÔ$î,`òëL¯ÍK/éÃ3íùO+áBÄ:™9<jçÏ!+Évñd4åC½ùZ”9n¦ÒŒTT†uëØ¾}ˆf´Ä,ú‘Bø‚=Àt¾I¶XWær=uPÍ´d@@¿Òº"[üŒ>fü†[Ó·»=¼í`wv~ÙË2:'úw*4ÓKc67có¾Äöò€w“Éž@Ut{äF7V559Ÿ¬~5+GÀFÄãj)Y€¿¢#l’Àœõh ÂdDÄ ÝKn{˜ ?´—x­Ëž–í®¾ÆÓ³b FTµµ.7ëø÷-±¡Ô’(-¾À=kœv“T²/lé¸B¬Eç°ãÕª0F^Î÷äúayœÍðO+,Ü!¯Ð)BIôçOšÇ· ¡r!‰5¶*¼Ýç¨j9ªùû Ë«sOIâ–ó—jÈö”—€+ˆ‘ýÔøw¬wð}V†"ê'c+f¸óæ³x//ÃdÊànÚžŠ ]¹Š”Çø 1¹,h¡ q%Ÿˆfü.Dû!të؃¶–íAojD bnB¶z‚UU#ÿã\U!òõ|oµ…@‹»®–tÅ"Q_B¢‰$P4Çìj’‰#ã¡^,<åƒùÑÖt©¾2Œ gŸÊøëÉK6}Ú¯ÊO+Í&ÁÍê9®ª{Éߣr‡gAu-àßí5u¦­µÀîLùŽÝ‰äWŸ#VþÀã™k“OјAÇFçÃïÝšM'”t÷gÈQg£èW7WX«¯†özS¥ñJö'­A‘éDíX8YŒ 5ÃfSç‰EáƒãIo¯b3é‡ÂK˜„Þi—Ô._æ{˜è¬]e‘|jü<·ã5™Ì qËu¯} Ħx؆€¬%• øü è k«ì®Ð's™ 6¦kmŒ7S‡´ ¤Õ|Ëõ‘¥:Ò^ñÂnY¹G]†ä³Ñ'ü¹0 Ö g– b›‘Úi<9ó]Ô–ÞòƒDæÍ¯M O<¢|lÕf“רºøVÅâh”rÉö£“‰ñq3‹†”ÄG $ð5¸Â`0Ý~Îŧv>ë¾lÆ¢ÖG`o× ²©^1 @Ïž“QC»Š#÷’xñ‡H¿Üñ.uyARåäJ^îÒ,ÊX’vrtÒ’ Ç·iLg¨û{ÿJbÏHX—hô<ÉrÏ›¢uõËÛ `SP,£ŒW£‹ä÷"uù(!"ÖùcƒQ³ìÃã©OgkŒ.±ÚF…QBNˆ^ÿ†ò?˜Eö)ë´Bb¸§c$VŒÀ°ÚѼ"Èvú b$ Îðti>ô·.!wæû¨x<Ù úZÚŠô_pMÆb¿™aNm*‹Â8=Ã×JBãøG¼âP‰%ôû%HnœNQ êœ óFKçhBL9 ¢V‹! Ë4ó÷ˆU";€×%8/¢P÷ƒŽÖ³[HqéX±]ò›g匳"X£0¸ð+/wG;Ïê9 bù˜I£q¸9N@œè¥I«¡ŽdfÏ¢Û ÝYf|É~¿ZC´x²Ýrô¯F͹¯è\±Àv,ó“FºÁNaÍ¡ö»vÚâ4 ‡"¥$@®Xaqì%ò%h¸û¾”V‹}< è…(;ŽÐ6ýêæ"®˜T¼j©¼1Âfœ´O}èðçšs‚Õvœ‘˜Øèß*ºz†iÛÞ’ÚÉÅúZ«DþÒ®ü[)hÝ —ŸX}ð|vÕú›à5’ ³xð˜‰,¡Ï¼èÒÍL8—ZÇí©R0tÎ’#F‹"sô¨ Ò÷–޲~‚’-¼‚¹Ò¢ h¡ÄÈCDdö´;+Yš>’¿AhèCpÄ (7è6NŽˆb›”í˨T/œ~,úåž“Å--]ìàP>X#’.‡&ŸÈüÉšN\‚à÷ =zÖ,ÈýQý[÷gKê^c×QãkS–ëú=rÃìfe† K4AI10*¾ºbÊbµÉSÞ´¦’`W;[‡Ìl¸‚`7á|¦/ö2¿õ`{ê¯1eû;· Pв‹¹…ý'ŒÏ{Œó{âs/c4$†2¬™,p±b˜IxÈÌ-:öe`C“äOn•-øUJ+õ„ -¹åâv„VÚÖ‘~n¯ ?ä ²-E z¼bÓÞp¯ÊISõr°g{˜º›iÆL½‰óN}v›Àt;Ï>/(a¨Ѽ83) Âuã€bƒR¹÷á &Qâ̪°Ýë‘ê¥È2Ý£Üb!/ra¥ß½5D…Ñ£`ý?Ä-#Ø‘/¡œ›µ9»¬.Úúº³)Ì$1aÁ¬(sî8@³žûLv Ú Ê å6Ó”Xmà†HÃ~"0'>ÂݯùŽ¿&í”…Á7Ì›’‘øª¬0}"ˆ Àg ¨ý¡²ºŒ2¤ÅZ¡}è1\º *¨èB’N­tVüD\¹nãŠV²|&œh’Ù4yMt–Ùl¾s‹AÌÀùy¤ ,ƒÕW´m@a¤èvIùà ‚Co ³áñáSeb¥ç'¥¶NªÌˆ»84k€½û¢#Uhˆ²ìD[z„ôi35ieyÅÖxäVÌÀ§–Ûˆšyo6H†é h…’–•æ' ¶cá‚KÓEQ<˜Ã¶‰ƒâö ~_ᔿ‡"} ¹R¥ yLëѯø¸Þc_„·ŸÛE@€5¤$.Öçr)ÑÙ¤õâ+}òO•0£=‹ ˜Iúµö$Ýô’ ýÚfØÙAÝ•/…ÔXݺ!ÑÑNÓ÷÷Òl’zw,n—µ­•Í ºY#LôÞêçÁ9´‘d9f Yú¼ÞÊW´o .Ì#£ýn’€—ólmÆ}0dà+‰>ÜZLø+C)ÒDlk0‘X…A}Ï„cøçňâa¦ Jñ‹N“×%H`tD+£]ZP¢élÔ°s¨×2&ÞêÈ­«Ø¡¢á>"H¾”?R'¹é@üËa±UT2£¬1ìX——GšÞþæQtõEÉwd‰u~g™ú†·}³Gž—ßÊZk·ºtÜÇŒNº5¨Ä0È¢Õo#ôóðc5&ê?¨Âp§š7 £Q`2×j/U­‹DBƒJÜÛAE9О'YaœÔj fBÈ:K‘>F}ÐÃÏ}Ýì~3SÍìqvâæ Ms)É£…o¯9k x™p¤@ óxönÄ•ûœðØõïÚÄ•«¦^²½d¬³f´¡M‰ö  • ÇâÊ—z"#•F¼†»,¥=ßDz}û/Ð0xl¹ŠŒ0p¬xåµ& 5É2ÿ€'ü\‘¥›ÿ1=Q *“éî wÂ>Õ®–Af棒•VÍÕâ®`'% DŠ'rMC&H¦“Ý]}ÁGö[Âaƒ!ŠsÔU7wáçàœÒP¾-ßdö‹&ÿç<¼þ}íÇl$ûÄUŸ–ó³h;¿øGv%q•­Õ7ú«Èë$ªxÓb5óq};O}Á2ضõJùµÔ˾§Ä©Sœ@§“.,,=˽/®þ¥ÛÖ˜I͆8ñ­ÛGxq%jaxñ¯ÃÜϰŠfKThòš©Z²âØÒRÙRòcj$láw$'4Ýæ­¾nð48]Q—ÀÓ¼ÖÂówp¨2§!±S¹ 8Ûc[,wLBi¯°+œ1 ¶ _zܸù“üZAú:]…ùœO° ikÉH–Ë´<{¬êÀ-ca©¬MÂÀK•XX‘EÏ ‘èÙ ‹©f}Šé€%TdK†Û†·úÊ §¶{ÁŒ×kÀ„´wð̧³À¢7GÙ¹¦ç¤|;,´âºË¤NO¼·Ïëò©?¥ÎEß@YÒ‰Ûrä~,r#?ØPmõøáö\Eáøã›F톻ðE]xŒ{¥š‘€YFdc::mLv‰'Vë¾õ¼tHq×V³*’ºHnúÁ'+§û;Ùzµ—Iia$}rØ¿=ž¯¢¥$ GÁ`ËùôfÅØµN¯ž,žYõ]7GKL>py¼Ÿ¦xB—•„{?¼*àÏX|l+"8x[çnø!NBÔÉÏÑÿºìµOgâá2Xƒg§dWK¾¢îå91 ɼ¹cÝjî蕲—΋Á&Uóé+GYÉgÄuA]§•¼ötH¥0]Âô¼~rC aH_C)N6÷¥8< ¿™* ÿªšg+S†ª¯¶³ÀZF×úX×bPÏhWŠ Œ£½Û4ð Íÿ˜ØÍÄó©t¤¹Ëì¦g—œ¦ÔÕÄ“ÈÀ¥(Â7ÑJÁŠDƒíì-®ã’y)¦» œÙlD¶±ž§d*˜Z?›ºúN·ç]½²+Tæ‡3×£ëÜÕð¯C‰\›îng=Ï[Ùå…)éVI"ÛV)ðÝùð}Hº}Î è±>S|;W”áÃjÔIÇþ¡L¶ð³Új ~Ol‰®cp@jÈîp¸atÈb" .³#éÆÙ[±V,ÖV}~kð‰ÿKÀ5x“Z¿8žáúä±ËÜÒ¸¶oÞt`J–~'ƒÖÚýdt³­îXÈ¡mýw7ËG½¥æhµôœ8JW=Ú˺YEÄ D²ì@n¨ãlCP’§#4Ÿ¢?¸MNy\\yI¾ÖæžÞ½òXç¿»ÑÀï`Ïà«Üâ$„q&×QSã"Zušƒ8E>X¿Ç<[2â«á6$xE$UæbËï?\B๋¢ž¡‚Âý¹a±.ǯ‘qoSš…Á’Z ÅQ öP±>÷ŒÃ^Q(U 2`5W•.‡ŽÓC%ÄõÀºdÄ_èôQB]¼2¬¸þsÙø»5Ò™†F3ÎÚÏéd3þâ{ô( êM&5±ôš»"ˆ§ãR¿ïUm·sõk­Ðoéñ¾úù²×~ˆÓ)œþFŠ5 …Ásè ɲ‰… }?¸Ú·÷4ÜÓÊ}9¿“s¬˜“,d袈v«‡j8´iãØAf0C‡¬Yß/‹4$i.Ê|ÒD‡¾m ‚òóà°hóÞ û‹cÂ>•²Å@±„<÷ì•C2ìÎpÂä%ÃûˆÞº ¯0'‡nñ•jb š±†?—oðúfluëJ8yü ¸‚±ª-Å8²^üÆã0:"ÔR§íö™cdy¾:’), †õÓ Ö®¸ò%õ~Î)ÓþÀ¾´¢G<\me3 ¦œVvµÉ;îÚèœ~B¿—,ƒŸëî¨~˜­IXIxª7¨=tïÌs"ën„†ùVø37P°tA÷k¤˜°A=±•gvÙ—–è-à÷\¸ÊIuWöýq2ˆ Ê=îòfÌ:Ût7)«‡†¶q̉£¨“ømè)CìÊû ¸*3¡2eòZ.CδK/ì_Ïêq â\2 öç2£;¥}´¾ëÃUœö°zÀ ç;]¯ØÁÿ£|àÿtÕwÒÓ^^“ìP±b+Û¿D¢z­Æ‡\«ñÌ×)ß™ÈZùŽ!Äøh.R)È FÇCžAo5ÑðGZt£Ï*•9¹kZR:®Óh$Úî·54ÇC ä<8G1!Ò‚F‚zû<Ô|X¼¨U²‰?fpÓ*Ã8ÖŽïFÖÄÔB©JÅ»–÷é|ªµö¼\ŒæÛ‡à¬Ðm`þxŠT`âº[ë\ä^V»º†ƒ‡Š å,w\Ùò`xç)/,~ò\‹ë#ØÝÍ,êKQEÓóòb2Ö«Üꃡz0 ö´¬Wª¼”ÞåÎ!²Š— ¡ø¦ÓÏG"Hvýå ŒÑbλ ¡$‘,&úá„C‰Ÿ UVT¶‹@¾€``ÆyJ˜ßAa3§¶ Ë+0ï<ÓRPB6U±‹¡ëzûK`86Q¾æâso`ÀjyÕË 4M§5}”úüðó¹Ð—SçU–¨ó2à ínÁþ•~ÑGèЧÐAÖ´òºûåse&iÂAw®s Äý[Ò.îÉôr®¿‰ÐÐUB7‰¹`Ûä|rỊ̄÷Ó9A¼â£ÜCº<*:[ø ùG÷r'ázg7¯µå½¡\³^_jŸø¶S\þý¦ážÕ ¸†Qm= =~T%ÙãÍë´ÅÉvÒ£ÞÚ3ˆ®üVlùš°†Ë8ÇìE›½˜lÔÜß]Ñ g VK–Iƒ­L.8 ¡‡×LÅ£”ðÈæ¾¥„ ;L!`2Ù8œ ‚°ß¾yNùíÁávk댺ÄùÓ­xþM|UvÃ’gy£¦mB@r«e—¿Â¢×™b)’µ5'zð’ÂÚ6¬ n#8:\n[&‰5»–Õêx… ¶‰&åRÙÀÏZññPcSHkóxìŸ{@Ãï¨Ë‚øžÒÎ5Á}ÎÕg~!q\¥ëþ½lû&ÖF©/ìøKCÝV0¯ú‘;È÷e+ ¿lh5ò…)Œ“ðrŠ•©=/u_㈭XÐ#ùÁ’#R®Ã%·š—S¨fæh§,¤¢B|q¿\zBGõå*`ܘ¿D¯¨ˆ¥ð xÛ×%‘ÿQidȉ°Ë²žú’HÄw)y…™ Æä‡ÒöY¼Ò„Cxe—<Ôh$K ¼Y )š§ ÎðI_xfÔª¶^jyœÉlÁ-í\սɶšöO8‚ «†kÄvcX‹OQ÷ U°TÕÛæƒ¤âe•èo•ûþþnªÛ[©²g;l¹›Ü>`ZÁÊbó¦À«eBSœ-¼}˜r¤> ÛäC:§Š5cæ_Æo¹ª^oÊ· ƒÁ¹±ÿ´³(‹¸`ø¨¯­_Ýlh-b7MKwVáfíS¥iV„4\tûÍà`§5t `vRöZr¯ÔI—Ü© H<ίÀÖ9$pÕÙ vȇœ>ž©n"GòÓzÍ{ÖG!j.QâTþ׎AŸ2äÃÄ|4Ä"edŒGˆ:Óìb²¹˜ v yñG6î½qˆŠÉoc\Š,ø'H³dÑ:k°›œ¿­ý³%°ÐsÃmxIµà¾‰Ù Ì!ë?¤ÊYmðÔòˆ£vvéúĸ¶Z"§‡…e–«²º} ÅÜvaÙòñ߸üËt/¡­›y•äßáôÌÏ)hÂ.ȇ¯m é{nÿ´<͵%šˆ‘{¦'5a;¬8ÏÁõ å¶ÐüÙ,ùòÝ­Òà?ž²hÇõæšÐ/œž™zéé~„N¤Qó¨Ÿ48Í”„ãVGëù˜˜ËÕû 4Š ÀΆÞpÓZ¦-ï©ÙÑ·qòp}oÞõ”ÍÅú/yûÍóbµ4±S±#ÇݲÄ(;r&º©˜Ýb4ø]þ‰(4ß«ä"ÆŒœ¼ç8Áúš¨ËÒ‹™cPY?W ´_GhsN8Sjw&±ÃayœqyóXUxì&jŽÜ°t¢¿ò-5 ‘óa±d´)&üú‹A ]x7ç¥UÏ—+\ñõAk#PA²|õfqãº>L¥^øå HCN¢PnTìZ}1Ê#£ä{~Eê/°Å8iTÞ‹¶N,ò~|d Jå)ÂŒKåK~š¦_÷Ñ¿cñ¸”‚w}Ó<ü ê†ÀÎCÍI½^ס5Ü]ªÇ#è\3ýUŠEâ@X£]ìíÛˆéÓU™…(¢ëÀ”Í/ÆÃ7(ÏaªC¹Da¿ ~¾g DÏ<}v$Zï˜ò«Ÿ7éü,Û:0ý§Ù1YÖk€S4q¨md’cîо3¿‚§A8×ê1FQ‚µoÜÚÇmCü-Â¾æ™ Æž‘Ð ;B'•®Yu®¹ì|v&Z¿~YÿÉÓÔ~C(Ñ5êž¹ÃÛ]3Œb}Ñ‘¼1üÅc–ƒõ5L“ĨažˆÍZéêðÚP_ˆžâÑQ1]™Œ÷AêiÜ;Ÿ§àæ ûkÆæuMÜåØrÔ™o’)>?“‘ êúà(É廵ŸÜKqЉ̧ìÌö͈1°¼ªÈÕéÈN}º¯Íö°B^Dej$¤hÑù”¹`”žû'¤ý?*#—Â¥Fˆá9ýƒ81IR€{®Èû[:Àrå«CâÔ%ÂÏ©›ŽûX¸ð`Õ騦ð!w÷Ð_NêG~t:íjåÃQPz¡ ›µ—ŒåùfõU' <ä} ô»Rš‰Uõ|n¬Ìš‡ÅêrU‰’¢Õg6M›-ÒuÎÃÐ2VfYáq^¸k>â¬3?úÈuý|¥<ûûžÖÕÆŒ4ÇzosÞØX ÏZ 3X¼í¤ùÿH÷X?&oÉMǵh+—¦A—?uèK³~æ±ìÿ 4ŽÁ»&ƒpSǘ€ºƒr1¼šì?¦>…²ò=!Knr?ª•ü˜CD€„.›´Ž.Ö ¤þ5ÝF(ÉÖ W•™ör÷ú3õŸ”4\~hªÈG=UÚWç=ªai§3§!ŽŸs>AZªû¥‡XøÌ0Ée í¨èi>2~·“±é†e³¬·*·u†x…™R,z^ 9LùgÝód#fê´fBôm—0éV/yÖò)™U†Áj·cW°¥jYìöç* ¾6㥣ý{¤+}“–@ßÜ03¤t/ûN <Ìq$MB ›÷£êhÉ¥ÌF$&Vc$æ`äÇÊ °Õbù7Ð0Ö¨Gܵe™ÑsEZ)K“…Cô—!WÆlu;»Û PŽH²MÉ ’²Î;rãs–{œ‰ÖÄOÍeÑ1ÆÏ48ÎÆžæMÆfWt¬d…MÅ|…áMˆ-d,2)´9™n㑪QË'FüÁVvç›{J(ª ‰³žÕU‚Ôîªü¯RÈI¿XàíŸn…!O'"Ò‡ÀVÎÈF,™öW(´?g«MøÀоÂTÁH UV%Gù~ø@l®†?ÜÐH-wƒTìªG¿#šÐ¨—á›,Ï‚~¿DfanÅCœâFÿÊÂïÝza±fù-9¾6Dì¥ ãÁÁ¢,^ÆÊ&pH¼¯…˜@zϵIêB"á¸(fXœe{dá.‚ë»Ía% ߦX%{ƒëótî¢ëÔ5‰ =mò×ù?É zDU±àU¡Û²ÐõÔm!ßÎò| ö­Y3J*ÎŒÈöŒâ¹` À0™¯ 46†“\ÍuEA»n®¥Œuév÷¦vÞ©’éÌõSvã”Úy“5ÑŽ9¶áÒ@.Y™>N(™â$¾ƒ<ÌCÕ¡¸c‘Þ‰°6Å»§Ñë[U¦A\fµÛr˜Â|â7f G¬TA}»h»lm×z‹Cc’Í~žH‰cŠ¡¨ÿ~–¶­æLíDRO÷Ò˜Róã@]ýFš 3¥ðXnI í…µó]ñ6Ùþ’_7ehÓ_«Xú`qD)׌5½Õ¥¥Évæ ¦VÖ¦í1SooÈЛ»6>NQy·Ä ?½ØRG,ÂvþZ1WÉ5µ9€;±õñ^1«Qæ*AÒàÀ¶%¯õÒߺ²þtMýβLë}•#Cá'™¢éîùÚ’ü.È«ÉáœÉ2ôocÑo|€øúÕ]ÌÇYß6«¦á§µˆ’ýÄI6Ð@+܉6“¼ÃÛGíÖ ¸_ˆ“ëœ ¯'â}&}v·Wõ"m_T1owh™ÔrÃcˆŸ(R*Ûã‰+ÇƖâÂï#SÃPø¬»ù¼%etú6Z1mPß`VPˆrÝFsoÜpžŽt0w‡°¾¢j–>òßÿ©Ài3ß^öôk¹A“d=,z‡Ç´¥œ…TÈŠ3›Ú^¸áY͹êö½Ïüx›[ø£il“R4‹ºR3­"âîE5þVYÝFÔçÉc(éušíšNa¼É‹pJSaAOIÈ¡Yƒ¾q¢A'Í]%yx©â‹ƒ•%¾¿ÈmbîÚ¥Y¯ ,N²hÎ_Tö}V8çÌEƒélCyá—néñÁ ÉPÅy­í£(”}„¼[5DcW¯œ_¦hÏWM5¢CP‰©W'Ú¿•Bµé£U×'vßäøTr23¯ÔØû*ÙñOõËÊ›žôN;™$ßLK,I©ÇÊ*†Q6á®w/ÑU¼¦*Eˆ»Ö]ì+¨^a]XÕ 2åQþn oà30ä“t™…M:MÑÊN®ÕÑ­Øbù¦ûö[ëØ‚žë÷Ôþ¦ãöû>=Ä*Ð#Tà58C—[×P¹f¤C7DmÁŠGyX¬þ|·õæ6? ÈbÇåõ{Yöt» Ó+Ì˰>ñý)yÇÙ=ͺ{b•ûyµ˜=¹‚dPïÊÉìÙ+Ðú ÜnaÊD1ù~»4XT^kh3dtãVâ2Ÿ“>g` \ P<¦»ò¡0ç;#Òd¶'Fþî jSÙ¾uï‘ôK›Í-ýŸpÿ?¼º{W‚!CŽjO“4Gì¢~fçM…e¢Žr ¥ÎØ{ˆ5-™¿ÇË)›À¶Báôþjÿ ÂL mηÏ"‹ËQnYEÔG):†Q@MtG]Ñ·‡$”[ ÀQ‡TÚQZú…óàußú{‹o‡£ôË~Z«œÖW¾·¯;DZ˜Z¯ÈQàÞ¹ý¼÷9؃żk7-üÖ•x* î:Ö^»j0ØLOf;Ä×ѨX*¯ýñkþBX[m 90g= |K¾¢}FQ½R~8hÆ‘b™ó‡yõ8>õ7ìôºèGW¥ÊÒÞ˜âx¾¿Î†úUhÅñQFÀÌR+Þ Ì`/ûRº¡wòh8¬lbÿýz"˜$aAõ—jÇ…pðV6Þñ K[’y| m¤Ï\¦7ÙnMÌ1Æ#cåZðááò&ñ¯Ã×àÍñë+“Ë6΀-&*Õ-XNqw¨š,É佬?hø^?ú]I©ÝÚDY¸ÂG”ó`ÁÄœ}ø(?™¶x‹Q»&‘!òèP^éhJ2NênLjí¿ÔŒ eI'|×ê6#áß|›T¦¤7xéìšB&yBö;`žZêÔ¶ 8Nsº!ɌѬ µd?̆ líRÃc…ÿQ¹6)iM^e¤Ï_]K*çÖðØ`Á .AÂW®á£‹‡ƒ8{æ<ž…ÆÄ*wŽ¢ï;{3C®á›—œ÷5!è%ÀÉU—$ äô²Y\=*§¸è²èb«Ü$¿ÜªßánïgPàwS o'ÅI²¸E«;ˆªè8‰•Éz Ûb+†É^Záz1( Šç0Íź—7ä¨s/¸@£XM0Ó‰/Ä>ú|»AÝnËè4!V!hjp†fw­{«><ŽCzíõ×>’w0V5ƒ:iÈð'J³úRèÐÝŸ2)-ħH㨬‚‘N㨾S^•Š«ž©‹&er™ƒ¿Aâà…•ãLâT$ªEõÕÁY‚òó?i.b‚‘êŸW}±¢(Ë•Uà¼æ·qã˜ë.4á–Wð• ï*OÀ¥q3ªyž†×‚Ú/‚¤ÌÔ¿ôz†;š•S¼Œ†Óa#\Ù)ìÆéw*úHR›Ž:WáóåWªÐpÞf˜Úº‹b2p±›‰¨ñqÞwÝpbò´2œÑ°£|Måê éÿp†rzø_²VS¼¸Êꊻ0:ÑOÚ[ö|¤j¥¾¥0i¢öbj¹÷ÑbL1–Ø#¡j–R£Õ¼Ò[¨wJŸ\ذøF—«ôËž”Í0‹B«çâoÏ×Èßzf8€Yö±¶'@rdn>¥ƒ¤²”_üB|eE©À@FËÞK¹#N£ BRt¥ ªÁ³×ïduñ#Mà ïfð!¤4ø˜ìp_‚Ï‚q¤·œý‰uŽF^ vJªPTŒlÊo7w=hþŠŸ+ZYi—É ,l{};凾c¤fD X)ˆ^7 k9`QÚòõö«â z͇ƒLý†¤J*Cj2ì;ÙqŸ6e–êìy@ ÷ë¶»E`׸NÑí)ÉîHòdö¼9̩γ¯Xí°­Ö‚ô.Èë ÆñÞw¬ PÇ ƒ(~¦%ßʳeÎ $µkóÆlÂØ@b<$ßC+2ñòÆ7@®Ù'ëPÊpŘã­0ñ¢±c% _Þ:ãɬ̲¨}€ÿäD_óÍ%н àÍzhûUòL}ÆoÑ£z¼š˜[¤HDõ­” ZEà…Í,ªuw¯Á|㈠7¾úpfD—ÑÓÒÐJ4ÎYúoIO‡ŽÍ4 Í;uK†»|oÈJ&¡¬4âTÙÆm¤&“¯3À,4Úk?¤‚Ðê…èD®ûâ8–(…`ªº2û³¶gr¤6ãnr”°¥ ž@ÊÄüªˆä” ­êÉâèW_x-ç_³°¨ámÌQ¯ŽÞ„–3žO8 ôÞóg<)»›%|;ÆÔ¸šXaJYþÀÍ­^ôP ®Ê`üÉ[7¸‰9ãæ»Øˆ®zšÉß™oœy:ÿ'v8þU«ÃŸ–“‘—.á|›Žê”¢Ì¼Køa•9Ch&»¯B„)Íä–|§(¨*W'=4ëÒ9…xóñýÂkP¤ ùAi­å\¡Á=S?‹¾Ç@toC€® ’x•zR±‹MF:èçŸðªÊ¸mçˆÄ“Nç 6'ÿÅÜ/öúFî°Ï±†" ÉŒJ3þ¯ñY´dbnš_"ëk½'­K5‘Sä3雃ýyÆÑýÎYëÎkó:Ï©(ð%¸MÀÖHŒ qÊ^VÑ¥å{;jq¦½i„ÃpCVñèmNáúDÆÙ“Ù‚­LÒÞC¸by‚·Œü6“:>í~¼òŒ9>üÛÓÕº`ÁŠx¬±µùŽ*Í|ý"º™ðRËáh[äÞ”¨?Ödó€‡mjÃt³£!Y_ŠÒ%~ЛC;˜ Púß ÒIäÓ¶üùÕØ?w¼Á¸–'¯V^ɦ£°¢‡ÉÊ1 T±)¦êjP9,½Q>—AÈK§ùìÑ®ªÊ-Pvb¶ÒÛ[DBºRý¹%ÄN[+¼¯´Ÿm;¶gŒ½Än gö”?gúãÉF¿-Rvã×áPÜÏü§™<ªüõÂÛ™ÝjuF>Að¨$ ϦiGÉÓT²[ƒ²2^½3ÝÜ:Û$ÉXÞ}clA8/“§,‰qð ÛW{ßGy¤èl%â& ·ÀU:N¸‡ï}¦J%rÈ|äê²™iôÜ‹›ÁDÑ­7$[¬u¯OúxÆ×–.6:ÍÓ?I-aÇ"Ø& ¸ð׋a8ÁéÆÙ'Öà&1„CŽç0ÝmlGàÞYã‚F^{î`ε ¦™(ã )å&V×JéFr&-híRÉßËwv—"/·5åÀ·uÓ,tc²ì(Özu¡ÔÑ…@›!Ž,ñŠl3åÝ÷:­ŽtHƒs޶;Ídü’€° ±l[È£¦Í[ÆÁÈ´ÖËVn脜à üa»t¦ëv +–I×—GÃÙÖ#–…yö ¢9¾#ü«0A×a¤ 9+³¦o#•ˆ;ªÐóð6ÜëÇ2™*ýu®ºÚ†S?Y¿R¸d^T‚!—Ú^HNžíÌ(뮈«Š‘ÔÎn>úq·&4ÿñÌìJŒ]ê†a—=zšæêå—Á¤R-¦ÞÌzì­ÎOO"¿ôç:Ç%á` ̵¤J ‹¬¾Çvz§ügh33_œ~*ýAö•œê•MÁ P>ÓôLæ‹Ý[ìv“õ1`(r€ú@EþÜéÿ( ×óTf¾r1(ï;@ SŠkŸ÷«o¹âB‚g’~ÄgSþ&[ Ûì,aõp7:‡“¨s¼"+‰´:¼®à͇©=Q7ºƒÉhq×5É…Ân»±†(#è\ÆíÛUÏÔͺ4)3¬÷’h2©8ä7P h@›õ&ê{ÝÇqªKÅ¿%]ä‚ ²H"õ8-®µ+ç¯W¼Ï¡{Œ°†n0Ëi>yñŠÊ(³W¡1št¯ŽsŸA`“Yî̸™]ÿ@Á¾âN0Ž®¨ÚÒ2eó.Hd,Ø·ùÂ}S6¸£¶2oö­´j©òåkQÄ–%Ëaÿ¨¦¹ ¼"ÚG&ø»¬ñ³v¯¥ªÓ«Kdã~¤1¼ $åh[Hk°ö˜½‰éR¼bŸ¡™n<­XÙõã}»mÿT !äŽÍú8Y͉ˆÂÿlrvc9SüÉ/LIvUI&Ý÷0 ÖPÊúÚï:à¤ý1Gzaç×4@ÎŽÁð™¦ù(ýJÇSè‚ O/Dé^pæÁ“[]/G#ò<Ð~˜HÞNG±±1çÐ"Ô$ôW ð€x¹^_YØjƒ9iûW2ÏÀ÷8¥%Y"fƒÂNT¹‹_aöl¬ÕÍHãÐýèäøíÑzÔly<Çïüî1Ž·r'?䩲ØÓŠ»~–Œ;rÕø&à¥Ö[gïÌL‚.IûáË©ìÿð•2`ÅŽ1Ž¿C}¥øÝ{Møç«rçÐËÔ“üàÔ%Ì ¨eÃP<ϨmªlNšËY Ä»îÔaàim)’>I4JÀàä1q,]éE@AÔm[‰ã0RfÉ©£¿:¹Ñˆ?¶°Ž2u•ja·”°hd‰ýX›êùüþ­Åì1IÝ*¬Q¨‚Õìê›–)ÌÚî ê{}ãWŠ“Ò:vÁ|8£iã¦RÒ”0Äå–¨6L}ÄxÉ%UµZdgÿ¹PàQÑkhCL¨–ït¡}9¦º™?‰A±?….Í­ü\ÝÏ•èÔQGÞô_±'|\HÅz%©4lŠ„zw½[¤#"·ªÊY„â°gõd)Ì©Ž†ó@äs Ö7á×ߨ`Q@€Èž°=þ-¸ÌêQ³a¢òTGaHíã›èYá¤a~ÿ]a‹ÊÙ†¾É`Ëjœvhë4~™M ï>J&”¾ø°7—-¯åŒd½ Úª ,ŽÂ;u çuŸÀ©­ÃÊH»âWÀ¨Àå9°YB)dÇhßíeÇæ¦ùÛÛ‘ŒB?iõº•^Äò¶»rˆÁwÓÚ0@Y(m‰’Ê.ØYºÝ@ŒÜtAŒiä¨ R27oöÎ6í9ÁŽ ÙÞõ2UhpÒ‚Í›üª&¢iy€&ËðöK<ÿ*(©ö³1rò ±œÊ$ùž1vÿÅ‘g8 ¦9–Âägƶða¢oýœÚ¢óŸ 9QQÙLÅ­~b¡¼2¼")©Ü` ùþl.M`aŽ9ßÑ_çõ8´žùTp.s+úii‹¢ÍmÞÐÈü"öAPh¨–cñâç#¿…«²Pá9x½ðõ0Îe×·¾òÂïµ=& Üèy>&HC~ Û{Âΰ-ùE¬vÆú£€Çk Ü‹ž6ÓsÏJR¥bìU/CRë|œó·¡bÄíü¯Nè7Üïù¢nÎËúãÖ 6-úÓï§÷€9zª„F…‚3.yèòì¤ÏšZÜó¡&¹Üå=´ øDŸS2J ›Xó¦̉ñ¨6æösZÆcÞÖóØFò|xŸiàuWÓ˜"Ï Y.ÓŽµØ¾y8†jÃ*¥šóZ ×ÓÒ„ßšç@î÷µ´EzqjrÆoVfä¥yJ–ÖƒÈ þiD$&ÿ²®‹çÉ;šP:Ö¢ãô¸¨ãñ)÷þ½v(ß%–‰“wüš+[Ú· 1›…\¶‰KÑBcÿ“À“_]§ÿ³úÝ;‚±É ÍgÌŽ8v´µ¤t™X FIwô(±mÈ#Ÿ,taW˜p3ª ˆ¯ÇBŒM2­²ºW‡Do†É@Œè°¹Ó»u9ÃK¦5â_nP¢íâ8–¨Q4N.U¡˜gÖDŽZ<3Œz M CìMC¥ý"Å®š‘³Ò2ŠmÞ‘oVXãÕœs£*ñvŸ»À’h©àðCUïÂ1õägßC’}FøòÚŒ™|“ rž‘‡.»ósÙ+ZLŒsá#ðô°m”™¶-_2t‰f¡§Ù YK\ï N3‡:]¯6xãõÌ\üINIãüK5¸K£‹Í>—f6ãVÞW…ÝÀÄ ÒcÚTâ²r0ÈÔ¦b<·Ï¡›kxÃäLìF³Ö~ lmÐÈL½F¨ÞA$Ìàòox§<,×Þ2Êщ3sÎ]´&Cª/Ýs¨û(’çëGƒÐ6 ,ä‰ R‘$ÝmÀB›Ðç§šŸß_ %¶¥þj|–)8_(ã6Ì=ªÕðâUÊ}]¤„8 endstream endobj 68 0 obj << /Length1 1630 /Length2 10669 /Length3 0 /Length 11507 /Filter /FlateDecode >> stream xÚ­yUXœ]–5Ü ÁÝ‚Cpww( €Â w®ÁÝ%H‚kpw îîÁ!ð“ïû»{žž¹šé«zÏ^{¯-kŸsSÔ*êÌ¢æSÄÞ…™… ©¦­´µšƒ! Ìj; àÕü™šZÜ tCì%€. ~€6È 2ppØùøø©âO'°¥• €î•ƒž‘‘é_–?.SÏ ¯‘Î`K{Íë‡Èâ`²wy¥ø_ªƒ@+Àl ˆ+«èÊ*I褕4Ò {Рâjj 6(€Í@öÎ z€Ä `û÷`±7ÿiÍ™å•KÔ8;€ÌÀ¯a 3È àr²;;¿~ÀÎK' ½Ëë \ °½™­«ùŸ^í¿ rp‚¼zؽb¯d*gg3'°ƒ à5«Š„ÔßuºX]þäv¿ÂˆÅ«§9ÄÌõOKa¯4¯¨ lï py¸üÉe ˜ƒlž¯¹_ÉœÀ•áê ¶·üWL'%ÐÉÜäìüJóÊýg:ÿêð_º:8Øzþ ùËëŸ5€]œA¶,Èì¯9Í\^s[‚í‘Yÿ¬Š¬½ÀÎö·ÝÜÕá˜Èé¯ÑýÙú×"€æ{[O€9È™U âòš@÷¿S™å?'ò@âÿˆÀÿyÿoâþ»Fÿåÿ_ïó¿SK¹ÚÚ*í@þñÆûÿæ ´ÛzþOþÿî© ú»Èÿ‘FÖø: Q{ËW9˜ùX¸xÙøþÀÎR`¹ ØÅÌ `´}Õ_vM{s“-Øôªé_ã0³³±ý¦a6³±ÿ3ü÷C {ó¯ÿU¦¿ªgÕS—RÖ`üoï*³ºíë~³sóü¡òº .ž ÀÿO§­1ÿç៘ÄàÍÌÎÍ `æàå|½€ì>.Nßÿ!÷_Dìÿ:+]œÀ}666öWÒ?¿lrÿÓ0ü7I{3ˆùŸÝQwÚ›¿®Û? `3W'§W•ÿz^ÛÿÇù¯Å<@fÈ?ç fÁÖi™é.Õø¹ý#ú=]ì°ý!Ÿë4Š *!þiáë|&OU!,õcüÏ-ž³‡¿·åvºÞÚÒv¦€NóI|ßÑw`­Ð´ò0î±}FK?ÒŽö>›QXƒÓãfÓÚÙQU3*yB kåtB<»¥xçV€Kuã€îg–Z‡×†Y…]]xxD“¸{Cû}ðG_ç|÷61cNµß/ù"ÉÅÓÄéªÎìþÁíý§;ÓxÖ6í²–t¯Ó˜Úw–k>°ëaÈÄ«êêÕâ±mœj™JöÝ´dytS¯3a­ëHÚÊG!,˜´—wþ:›XrV}¸†äÎ+Ãy'©áu>¥/ƒS¨ï;¶¾;õ«FÒáaf±ÏÙ2±ÎÌ#NF]tR¬fÌíƒÊ‰0ßJKʆ¦{t{Q ¢#ÕyÆØzí8Lq¼jå N”k†ÓDe9µñ§M4VwŠ’ä<ë5ŒÀû¯m+èr{"ý›Á*Žú‚Ö b—nµ ^vè>Ô'…S†r"Q¸LÞ-ZÛkœ` »-_7M(ú}ª; oøª'{hhB Å=%[Üßg¿EP"ƒã‚ïçö½¡ Cøp[tùI°×*û7îj!s¾ ¶ +m"«g·Êß¶x\É,éxƒªAùéåýÅbƒ»—ÐÐHó5ˆ¥zÛ$½xpóÀd¤%e ·f³Ë6HöêóµÃ™CÆöDå;Õ='m¬9R#MµK[Í3U·ÊﮆuneÕl‰zd {äC¥}Y™±Bï’'Æ–õù±wkÙ9tb¯—õ5!¨‘á#Ò4$c³ËÃ1°yåÜ›ô ¾À^ óB×½½‘ßü¶)|ëÓxÊ:ZA.B²þö¶ÛJzX{; 8ùŒ`š¶£öÑšRÒ„*y¤)„øûD¯|I5˜tÀtñÔúÈ{Û¿— ¤°Ñ£ië*§Â„´þiÑ¿N»Tn•;È“—‰RWI޹ÞÉo¡Ý.¸„ÎÆLMï`°>¾·z¶&:[¦®Pæ=ƽðQdYFü@‘W°{èqfk‡7–“´÷‰§¡RïÉmz˜0€µÛG(ù-¸ÓíZ©÷[¨Ý0ߎ(ÀZ-qwÓÜTj8¢ÒºÔŽ`²Nkp¯W<ûèÛ>®+\>#`w{{m½U5€a‰BŒå_šÿä±5²) ƒÏmÆJš¶4 OT‘ÑΊֻ­÷áœè:‚|ÛjH ìcSUVgDߢ¼Ÿ4¬@Ð1~9eÛ½XÝ‚Ê0ä#Qɶ¢cE*ÊDbU7‹`rK–ÞâyÔ=‹¨U K| ÿn6 înL·â>â)Í~WÜ>ÖúͽˆN:nÞAF¦©AøtGú;”{MöVm×÷S['¾·˜±”6Äý¶_}ŸªðC4£Ý¦T—œŠ7¯œ9ÕäèÚ¦Sv«IïÍK{t÷W|¾O””u–ËÞùŒ7ÏO´d}÷VõæØSɺƒvï Û_R‘Ž+ûrψj¦×¯>pÃf†¢+&j”ňò1¨a½ˆ>ÞîG›“ÌÈÝž¨ ?(ÐF²<öñ^/dÑÎ˾#ƒµLßè$¯ZõcÞ‰sŸd“Ï+°Ðƒ“Ýý)¸Î/$R×ëC›³L+Ut Ó²g ÔSÒ Ë¹ŽþNö6ÎÇ4Õd¹ð`NeJÈ.#™á8ÈóÁ­:ÌÅçdb9brë*–ÕÏ失¯ë×0„ŠóîjœyŒöãLM ¢Œá ÊèS«,²È™å<ü|Ô¨ýy<üæ"p€?zóH@û%Õ1ƒ²ózš$Ëã’)t‘Âó¾ò^q®4”¼mÇ|ù.“»ø¢ŸâÞ½e«ñ©ÑMŒ¶|xR $A9?ú6,ñ+£v¡^¡€>œ—º í‡löJ‰Ø„r}fî&©|©d¤âç«g#3o°º+üé¯û^DÍ~Næ‚€Ü\?G“SûÂÝýGöOM ŒÓË‘aNè½Ô|#è_ßR|Ï!NÆm[ŸGJôaô%­ v>¥µÖhë9¹ÛÌ¥Òö ©¥³7/sÔVf>tZº1RšÐ¦'Zw‚úé?ë2|ÊPŽxÜÜ:}Ša¨<Û¥»ºó ìj­ÐUFC‚[ã!Ô1_8b,tepI ^’AJ'÷»ÃŠùŸ:ä­NiGóhŒ4¹Í¤_À|´c°‘1« ~I-@LêCwåt™£¬çfJR-ÇÐWZ&³Ãhf qÀÎý}'‘¢@1¨VÃêð=å¹FrÆÒq= KTç.õAÕÒ"¶¦çů~sR~kÌâgÞL¢sœ£áò­‹R”žoÐF‚ñUA³\l^Ä~NÍo„›%ª-ÐÞÝÍ_—-<¸êÐȓϲ¾°1ËÝ4¼¡êwÕ®Ïöl¬ªl<šO?Ÿ3ýÀpÁ€wN¯³2FGÓ0‹‘Õþ£nvR"4s' *á‚^­f¼Qtãœí,Oº|G€yùÂI QùpþfÝ(G6ûMP$Aˆ"¥Ù¬¨óéÅ_·ˆ;cAÁw~Ó~tÖ覣‰·tÀûn¡;o§?çÃÉCÿ H×Dv6c« =‹Î¿µähä±Çæ}»’xþ\’ã˜Í¤ çŽìoa?síIù…2–3®J&!æ½ãÁ‰|JkËéÏœ·y`ÂçlìpßËß(} r÷Ð)¤o®Ÿšd£ÑË.÷R”¿Ô¤9˜öšªhò¾›FEÙ¯üIuÀ¥ÿfÕ¼’Œ3 1b›êLN³fizÚL%DwËF쎫̺EìQ·š–*s›HŸ`3…ÕiIމøÕGAò­S¨Žã'¶½bž„øhPLÀ~lá2­aÚåÐþ³¹jùc¥8$W¯ÆŽwÖÈT¿!±>ça&2R€­vר!¸¼-Èâzñ´ÏØTák¥]A¿/U¬?çÎ¥Sùh8ÎÚ¬WbåªÚ 5óöOŸ‚}Ù ìèó¦áÎÀ%§õm<¬#Kn¼Ç mÝä>ß¹¦Í„gÃÝM¡E7ry,S z©,ó6œ$pÜû4¯:3¦Üš$ßs‚$æeâSÐn¿ˆAVQÔÅË¡5Ìí€ã}ß¾šRç‘?3«AlÕ—kÆÂZIPõå‡dèôŠ‚¿»çÏE„l‚¬â¯Íç§qÖ›xwš†Ý]óÆ?$¬q·pêÑ*+O½¾–³xÞòz.«”z©Õn¡ä$‡tÈ4{I‘÷l’ÉfÁÆhhRû |Á_¾ ¶[Eu&ðÕßû®ˆòG§¸\öÂÎs˜ÏN^wN{Fx`©yïaŽxØó¬Ï2 ®S0Õ© ÎÔËfa<>Ñã3þU.Á:¥Nß_KKúÝÜå~º,Z÷å WöþlŠ0¯Ñ'£_H‡QÐy‹ %C!ÃGÅ•°¨ÁH6†< ”o¼K«ãëæZÇ䣸D-Ã@[œey)ÖÂêH(PÀòÜÛÁƈ'¥y\HMA)¯”óìNy\­œ‰/‘ân?õ©ƒÃý.<|³)ÞÕAZ·wõ|‚p4¢4ýã]\:¥‘ÄØ4‰ÓÁ>pŸVHç®#ýCÜr7a3²QodGƒe7tÓ[±žJñ{g½€«Ù€ZÙjWé¨_t ¶n‡!.41Cð†ÝÖrVŽQüª¤UüÛóBZ¢>ƒãL¾8•Ö= óv„Ï­øAvkÐÜn‚q¬9|…õ¬º‰ÉÉ2×qÐ2>Ö2ÏPËø¾#(>s/9Mó©òfÇF™Y޾Ñj ìíç‹K§*žh XEÖ]ô%Òßå}û§¢!¾ª©Éµ§.aþBl‘Yg~.]Í9›Ïô•´]ÇÔ³„Ä“”¡5ú>céW×OË*3•å,ÊÐûBY,Vš£<û íäè´=ßImZÁôCÈ)h®ëF©¼êJ}zˆˆÞVœ56ì{iV“[<Ï÷Äbë PzFü¥2_çBñí¯úA13%Ôõ=Õa9‹s'”Coæ»0 Âr C]ißdK¬È\œäÅn¥Pz¤ÝÕmgv “}?¹÷üâ:æ¸">Û›ú†™élÛP°%· ÏÕ$È|™þNîóݦ‡< sÇRhå´bÌ%&ëÑg°úu"ËüQ³<ó›üŠ3§ü-µL“@Gœ%EÂî—ù¦x6ÄçªQ÷É”ò_¢ÚEW0óÂt£Úîׄ+²TÒ†’–º+sˆK'5zæüÈJOÆo¬51¾xd·©ÌŸ ‹ {ÃøîÈ5Oð6Ám5ÞUs+®^ì·¿¯z“Î]?'¬ˆC¢Ñ`N +aK¼0÷‹ñÚ{}Eɉ³UœFÎ+#˜iLx!º¦¢°¢ØâKÎH¯“…›—ªšI·ädËð» HÂÊÄ·9ÒÑK2Ònô® Ú£B¶k9–Æ–ë< Ï)Q\¥<ø€&ö^ (§Ãv%UN]Ï÷R§<Õ^ížY– ÓäTOõ‚ ;ž7•O7×b1‰ª‘"[HωiK“[ôûÞ„ë+a°–Ie%Å‹ê˜; çhä´þ)ü”-‘ÃÜögf¤…°°¡¦`#pçU­¬;^®n‡G±¾DQÜ¥îZˆ­³Ë?/èy÷wÅÓÊʤGUY‚Z´¯$mãIIN.ÒÜ‘Ñ(k†œöw}P{š€÷Ò´¬;ǃ ‚†ü{EG¹C þXÁ-ä®l… ^7[‘ò‡$ÅŠ-_K´~Nc±‚¶ 5¼°ÐŽM³êÅC+ø÷Ü©c2^Ø[C63âDhúOOó¢¢±@ß“'tw-;%ÑóZL| nYõ·ŽäÔÛ•íÛÊT/òiû{ƒiF$wìSìÑöæòæÏãÚ×§gEïZ+·àY·Ìš¬ñ)î,02råø’Ç€<Ì+&{^?Ï“XvÛc°•i hyý¸P©24fs ²¹fS„©ºû”“1ýñ„?<9th¶qŸ˜êø2óyr© +°{£iïœæÖK-·!Û¼Ä^¦¹?$†”}]?˜µH gZ V©ðZ·ÜeX“M æ?–yúœóÆ»]gDÎ< ÉäRþ>¢–ê›é¢)3´œ0ö¤s?×Öd$ª–|›­Þáî«¥îÝV¬É{¦ÇfPG+m†ŠCÖŒ«\/ýaÀŽúð¥‰VÚ­›Z~\ÌÌþ€ùúr®Ÿ-™õ!Ù´¼à(·JÔó…™ç+¾Ù'ް4s}áÊNç7øµ×kZUb4彉°aÐ&´4éñµXÉÞÓeÄCY” ›+º(6^úuÂÝõ»™¡øž"~ЊÇ5ÐÐXé‡)b`&5‹5YøW"à÷)&¢)‡YÞßA°ÉSýÈe8@™Sœ Žw’6$MÞqZËýÚ3}Y«t·Õ¨ôãZÏß·­ñs_WÿÆ7㻜/qðø-7°.°]dŸfÔóÙñt¡Ýo܃žÙ‚‘,~µ¾ê÷K'<ƒ]—Ö,û•IÓ}yݵÜ=ßÑó9ÉYÚn\j8Æ$<—ÑùElt;§™Q:Í+1ä]´Y¾®e_ƒõ&uü]x ÷FæÏpûú`ɱ¸PûÁp,%£Ñ<ÛVAŒ'>D’Ô¦P‹ïÓ=à)}WýýN8uáò:Úç1˜CC 0AÀéŠM:ƒ3ÃÑ&»!†-+ˆ¯'' ’ƒ.TE=Ií'TdœÓ@¹K|çí›Uî²¾ùs@>æC ‰8bå-Ú'Hº±T! †:Ë©$Æi§Œ3=Ré狵9æEº9ö>ÝÆ>U>fÿÑÀ74»Ñ^¢ê"œìw{˜“ˆ{4œrιvKM2r7Cp‰„í±jazoæí¤6"}ƒ”³Äzu* g‹õü:-\$½~Q¨¶ÖiùÿæéPR0R*êÓŽ;xù¬A)½Ó}•ÞoX-)t“^N4Db“9êð8—»Wq-hñÍ™c·.ìLàvtÙÏý(ø•à{°Öhá -ÅújåŠÄj¹>3/× xzòyv³¶l^Ë•©Îs°j6¡O{‚­X©{ÄÚ§žC½x»´‘:M¾Š Mc_d¦›"ZÓ]°°ɪ-7£#áB…ÍV5”3«mÝtÑ*Èù¥A—q[»±æmŒPÊdôî³²|–çåÄAã%6Ô;„RÏßbá„{І&Ì·…Uˆ-'&znˆÌ#9Ζ û&$õÍ »ŠšÚ#äjÕ˜"ªv0óÁ瑟È1ÄäFa%m?@qìÚ4Ã(-}ü¼ï™äÙÕàçK`%d*Í©. èþCk½!­É‘2Á¬…·0¹{îv(z#É™»`0á/Xs 41"¹NP$a{C˜àksÈð VãBµ{ÉûÂ4jeÅUò­Å~ýÊ9‹Oï–r¨K¹m)CSÌÚ° îC‘Ð#V)‹‘ØŽ™¸øv‰Å?ë–ÙînÉê;-y;Ú ~%wSbš´6"«}W«R‰Ó¼XyZ~¨aÃÀqÒÂ+Ñ btù¶5ÎiØmÓôKÕ]zCP`v©À¾.£]Ån"Â<×—0×À ³Åço•Æ>sm R¨ÖN*ŒBìm>ˆCÍj:Ž~êGáì™h:|ùˆ8­»ü0ÁÎ[¥Ohßé–à~=ö‘¦ñKÍ;iO„šV)‹â#Ö™cû/Aäè†OT²ƒ‹büSÈz»] ·!Aé©Z'pˆ9d˜E„(ªÖŸúBÛšv-òL¶RÀ4ÑE‹¢ø-·cþžöVŸ’ZŠ_鹈±ì6D[ÅŸ1ø Ù´íзâ¾l¿co™zÆÙ‘àÔ¶Nî¡a©ô¾L¢½üRlÖXœ‰mîAÛÁjcœ=‹¹ÈîŠzÿ=ž‹ÈPÃEùͼçÏ]eª6å­È_¾o9Œ[²O£éd\ 䫲È=)k³è¾þ¬ÕaºéŃڱë+Ÿ8dKXóWɸÀ6Yi ¿fviëTµ/Ù\­ƒ[ÔyfœÍ‘å(ô##u”•(¡·•BiîørÝÝ »éÙ¿2HözÖ ãi@>åâ!ˆÔ´øl/óHNâ~ ýº—}þëk¸b$Žû¬tÚ ›K)3—K¼b{ÎOâH­½`Ó<:‚‹«o“PDcn è2 }°Ï›÷£âÝ×:çâ†öšYQe^äëʲß#t¤Vtúùtë™Áè~{î0?ºüíaîã0u¾#êÅżǃ ö8&ЦáÕ±Å(å™Elhd‘‚9o›#¿ŠéÅBJd%[Õ/‚Ãö[ASΣ4JYçQÄÊ­ÓÂ9[ÁÔ4ìiZõ*,wçxQ½{a ” Ð#DQÖå7šƒåƒvðV2¬j(I®Eç¾Æ;Lª‚µ¯C‚Se'eÅÛÛà‡‘FÛÁú ‰HçÛ+ø}6Üœ¢‡Í˜ˆ¦Áж¹/Ša–N'Uä×½Ø(䱆FPTið~(WIjwt£GŸz Yéa˜ŽÒ1uŒ†¶2]Õ~ª2¾¼5£Ê|zRN‘²¬äÑÍ÷ÂWÓ‚iw ë¿‚·‹ÅO@:¬ §íoiܰ»~ãK®ƒˆ?™èAÂ7:¼í®jJíÕ®˜2´‰öØ'ohžýƒ¹0Ž%PÓ?4ã@~r;qŽšå3Õì¯!Læ Kȵ$X™9EM§v&ê­¯2‡óñX{Ìc)ºTáÌ6¶ký ÀHƒ 40$+JËçÕ;‰É÷‹!G´û ³±H°-Ty¦ ©ºáûXQɱ´¶°#圫&ª)(…”ç­\FV&Óô¦©c'¯ºC$¹~AIû‰47M h~ÌuÑ šb,T&Î'ÿ!–ïÏ—KCÃÙý T±´²°D)ÚŸ¡­¢ÊŸÔ!†¿:ÄJÐ )czŒÑÚÁW¦s™Àn‹¥h õ1;z7?À•£ˆ¯< ……Îå•Ä‘×âi­ô,*ä*]À{(z–Þ†®¥ ¢Éô划%Zä2n8—¤4HjÕûÒJÕĻڴͭª+³=ñi 1táb aËRÍ4¿˜â´ÁÐÞ\Ü&ª”1q=¼šˆF~sûbÉz;&©½¹¿ØAÁ‡1ÄVÜúߪÄq|!iØ&ü‰•¡÷Dµ°ÌíÑ}ãHÕ0.ÃáÿÍÜ )dB‰Èåi£w§mw¦Š…= s™4Å­ýÒaUÂ=r9/MÎo½pû]cÔÝP<;ò°¹ƒ8 ®…˜È7J;¥Ø}¼Ó8îÀùo?ÆÛ?b!ôt'O±`u>°Œ§¾íÈô˜¸Zx7—¡³9ÀDxK„Ÿm°½ÅåUôÿH!Ÿª?y4¿ƒ·8É€ Ô*gÖ÷Dþ}ö®Z®N*Í"ÂÙ” µo›ƒÒ.XÕÌŸ2öáØ4|ûÞ7‹~+pZn´jkŒ]OX—0ûPRbU«£'d‚`ÅAyî]sî`í³××̦Ú&õ½ù“¸À¿*£©°éE+4°œÊDzˆ~ÈF‚õp•ZÁ5h…ŽÒÖð|T1j+©‡“­e½ìïö²ß~æ‚ÓhÔök#ƒIÙi0Š›‚d >y®#b¢ÆÑ¤[¤jkË\ù\‘Ku”ŸúãcmãâÜÜÏѬذÓG°‹ôžOæÃ]*ŠÚN¸EiŒcmÐâ!|ú-Ç•Œ°ÈF"cˆX”ºVwyE´°NO/àâ4òDÛw”TÏà ôoût+î=ÇËdZÌUZ&|A%Ozª{×°!ßó1ݤ|õ°*‚5ÛZüà»7X3:•ЖßÁŒÎã®Z.O ÿXˆTèxÖŸ&ÑÇ­†ý›?/%<—UŒŸ¥+Ú‹6Ô€eeÍN ©u,Œ*XÒVn¾îƒíÓ7ÈáÚZìÈ=ËÎýbþˆú?bìò¸qyEŽß^O¹4•»#U1¦£ÁêÈ=kÆ¡š{Ù õƒ…÷w YBÒ&y¤ªÙ+ìšÔcÖÆR§²·¹çª±S%S@ªÙ¢Ïy†›î¡ÚI6Ž~¥¢ÆÞíÃyÉ6¢òS¼|³S‡–Ð2*lx™ÆÛ\›ºQýbncp‚ðÎÄNêª~ÿôÜRÁÛFÈÉt1çyÝ΂wÈŒhSÓûÀ™˜˜~}Á%^†‡ñ¾¼ÏT`¸Ê¶oJyh¿Î¡|mÁš²CW'Ãô¶Øc¬ÑpºEþ8ÓÏü†¢ µñŠçÓH±‡Hî\£ü9¿Ô†ó›RÏY³ö•ðÚÀB>}ø»B ♟rDNÂÇ,…’Vä°ã…Çs³O°‡x³6=ÇÙïHPÛLÑ|†ò¶Ø¼ª«LGœ“Ao\9OÒò¾­š‰Ëe-“ RŒSø{gh ض'G<àR’gŒÑ^ÏV ÉIßF‰[=é'[é¸5yJîò{HŠ>£ÝãÚ#~´¼©ð‚q±¾þž%¼1‹ãïá›P=­6}4‰,%ÖgHSLsÆHà+?ÅœbFI›fÔ9b¦÷*„Rê!׌٪ÃÜ_•1ç. ZÉùšûqCG2Àfµh7Nkù™½v ˆ$kj+Ò¿©øŽa¯ù­I’ç]h„¼ÒÇCÅéJà¥ÆÁ{«Á%ˆ1¢BÒ“]ùK™½šê€Il[„¸nTpöè‚Xß ûû­ “¿Šª,'w.+ŒÉºRQš¹fgÆùa—tņ1¨F·÷ÐZé±ì=¸¥¡È°ÞÙ¥ªý´²‰‚&O‘숓H@ì¯ëÎÎijé—™Á®­Þ3}³ýÈ ®ø´;`ªä/e$:˜”\É5;f&ˆbÞð>i:^e5MÀmpûïqv-züËÙ32elçªØ¡E‰ØëiÉ6êϱu‹xá§C?·â3)kÂ!?ܤ@©£îV8½' Ñ.L˜rŽ 6Uù(æÈ!3D*Q×X¼ŽfCxûkr9µ„–Òïèè&Õ÷á='Hgl>Îx5`JMë™Æ#ò€$À¤*]ƒØ÷žª"˜—Ÿp± u'­*'>¾zØÐ”HÐé­m¦Úø‡}ð“K»È^÷ÌôNÁ9}®D=¤ÆßŒfSºo“’\Ç¿å äÍÄP””¿3Á%l0"·fL²ê]ÈÆñ¢j0³Ë/UØ›qš(ÊŸ²+¾ê[ʽ/Þ–±Sé|W^ü¶ÏbÏÖ¥¡GÉUe‹áܶX®ÿ2•Ä}ÿ`2fIm®µéD|Z’ÏÌuo¿ï¥Ž7ÏåkCè0gÁgÆy„ê ‘VÜ‘ÿ _doàÍ¿­!¹ _ô³Káëç RÚ±§ MÙ¤V¥O‘˜.z‘ œÇsÑÔA›Ê(ª¹Cm4†O'¼G,¥Ga¹• å`ÖF+¥I8¯¦Ë˜ „Èòro坸ó¸˜ðRë·\Äq<}ažÑG`ù’2žj-¥'0?ÃPO¥äµÄîÅšŒÜ59®»UâÉ';Ÿ¼‘ú¦ÈÄPëZA£·¤àÄ=ðãJƧ1ì#’S'Q¤bíÉçÏVNF{1>CzÝøöÛåŠù¯––nô|ÌÝ<ª·äYÚ¾»¨Nͤoo.›5)2 Œ~ax× ü$†=ƒnRêðÝØ™SB¢jb«S_£QÛ±¬Œ5¸µ3Þ(þ²ü˜xÞ•p rcpÈÃú*/Èsù¤M2m(ÿöúŠn¦ð1|ÿG*L•GHø,Ó¸`Ä”4øM·Pgø³i—OUYô˜—‚ÁÄï!ôHõ½ºíËÕ³€÷ìÖUµ.±ŽÇUåÊѪ¢Ô$Qü*•¡ µ{ôÞpDß¿ Ÿ’}⌞ Îšß› ­­qžíI.€ZEÀ[\"UµNF×EÞåTfk|Å7Û·yÐFrã»gÔo|vc K¡¬‰ÕüTƒ¢™®en9TEÖ๷SÒCKÆÖ¾Ý☫¾Î£Öh+×:ÈD¸ÆÊR†§¼ „²Ù„ǃyM›„í»’ê++Á]´ôò®Qù÷á*‡6ô-®¿Ðm}Æ0æŠ9X™~ŽôÖéú©MéÁéÙñ¿÷èÂV®7Ê÷ˆ`nâ¼î¥½Ìe`CÉüžàÜòí—i¢+† T¦‡Ìè”lw/4ÐÐøF/é&4í¦¬8ª‘F 7¶PØÆŽŸ”ȼð»yd.®§óyráÒ‚Ö|]~·–¼&U¤j¶v——áY ]ÑÿX°|6ˆaUT`YT$Në¦uܽCÄ2é¨Y+Wú ù§à™osLQ5„òÍÜã·¾)Ad œŠ’ª‹`î0'¼$Œ-RO‚Fâ!ªÃҨƩHÔëó7¸b #T€Ã­¡G²sfPýÂíeš¦YZ$Óˆy%y‰M«©A;Ç¥þÉ”†çŒ‰Ãä¨O€2¦#˜’~ØÂ1V~ß8è‡üvˆc5ä’MôÍ,"à’µ¬{œüm»„aºai”» £cÙI¡8­~á 3z–äÙø‹EV¬Ð˜êïmÿGøÀÑ%c‚ÃÚõ’Ҭʣ(Ed‘YpdG¢ž·qï÷s}kØ;ãšen¸E| 0Tj°Lž€f—ññ)’,™rÅà.Ç>VÆ‚œŸë¨ñÎ÷›ü7ÑýÕÆ3RùëÑ⑼øœÓÚŸÚ±¬LÐáçm‰Ø!Ì7î5ݬÎj[~è‚¢xÚDªEGXÜôþžUÀþ`ô5T9 +’Ž8;Öº‡©Ö¸ÂåƒÿÖŸÝÍ €nû+扚õºvöZÈhU×°ÙÖß.kž´ÏmµW•Ǭ±øØþÄàú[KÝRZÞË5ê €Øcs¢!R/0}”9jºÕüG/#+ñMÔ±tÿò€åü§þ™VŒØìð{ž-üwÖ|(¦[>nÞ‚õk·t­ÝÝ–¹©œ‹Á<Ýy÷NÕ°u> 3‚ȸoIýÕ:üŠA´÷9›Œ—ói¶ ]¬—Gþœ]qâB–š(˾³8¸8?Ê7œY™p‰Q±wYC¶U3’ôŒõÒ€ŒZU‹)èyÃ…‘ñ\ØH˜½úúÜãêßâ§r§ó[U§†ªJfA²ñÉóe!ë’qšÙȈ!¬m”ˆiÝèüBÁÑ_­¡‡1üœ¤“1L§ZH¢Þ‘ î¼Q€ ûEÍ)Ÿ"g•޽KnBN¦ç¥PAùsû÷LÉÉ€rÏű•_EBŸ[¾þþêÛ¸¥T /"<¦Õ©uj:~”7kD eÔç©ýbI¨ÂÚ"†¶x™qqúä†Óæ~ÌÙ¼‘á:ÂSÅ+^uƒëy²P [ñʵnZOC÷imÏó0¾I”1_Ò¦s—Ìqm:ŽŠ>·«I¦b¨²½1‰qÐ(&LÀ>Âh HìÓcAŠ •SÆÐ9â ,bN?vF£¨•{*¾Tȶàü‚*ÈÙ>›ØqÇÄ&³ÑMe‡³÷+B±©¤Óø¶ÑÒ¾ßÕä§WÎáÊ,ô´žFV…‡­'oê°q5Iya‡*R}QÎÿK«õ¦ endstream endobj 70 0 obj << /Length1 1620 /Length2 11407 /Length3 0 /Length 12232 /Filter /FlateDecode >> stream xÚ­weT\Ý–-Ü!8îî®Á!¸§( VxwwàîîNpœ@p÷Ç÷Ýwû¾w»u÷sÆÙk®5—̽÷‡ŽJ]‹MÊÒÁ$ç²q±s t4õÔÍíìÌ-Á*lŠPs;À«™•ŽNÆd;@dÍ¡ a€È ¸¹\BBB¨tGOg°µ ÀøÊÁÄÂÂú/Ë_. Ï"¯‘.`k€þõà dçàh‚@_)þÛZ jXí@™÷êŠjòFy5€<r~mBÝÕ ¨€ ˆ ˆ `åà °ûÇt€X‚ÿjÍ…ý•KÊ`pqÁ¯a  Èñ/ˆàr¶»¸¼~À.kgsôuP´sµü«€W»•Ãß9:;¼zØ¿b¯dê.P 3Ø xͪ.+÷:¡6æÐ¿r»€_a€ƒÕ«§¥Ðõ¯–þÆ^i^Q¨9 < å²,Á.Žv枯¹_ÉÁ—áê†Xÿ«V€3ÈÚÜÙÒäâòJóÊý×tþÕ'àÿéÞÜÑÑÎóïh‡¿½þ£0ÔdgÅŽÊÅýš}Ím † rüµU!V.ÎØ-]ÿ‰¹œÿã_{†éµsKˆ'Àd…Ê¡æ}M `üï©Ìþ¿'òÿ‚Äÿ+ÿ¯Èû?÷ß5úñÿô<ÿ;µœ«š¹=èï À?ï€ à¯K üOîæö`;Ïÿ*àß=õ@ÿ¨Rdíjgîüïð?è¥ Ö¯Š° ±óýà v‘{€,ÕÁP  ÀÊÜîuVÛu – g;0ôªéßã°qqrþ¦mÚBþ>ß? ÄòßË•éïâ9äuTÕ¥Yþó½ú·Ÿú«þPmOGàÿ&ÑSu°üÅ_,ÒÒo6.N'ßë±{=xB¼\>ÿEÆ¿‰¸þµV5‡:ƒ=†œìœœ\€×÷?Ÿ­Œÿæè`ù׎тšC,_7Ùþ‚®ÎίÚþ}î_›þçúïíy€€¨Kó@‘À©iÐ*Âì1YÞ..ø ÇoµÚy~¾©¡¿„JÍ+ƒØë&„Ÿ›=矶•˜w†ºÞÚ1t&ƒŽsÉ|h˜ºópVé[Xvü9L¾a¤êEzŸÌª¬#|àçÔÝÙÓÐ4)z|C>ÑÊãŒ|rÃäGã–ç‡O{íˆù˜RCІ]ƒ[•pHŸ°sÍÐ7<8Ðßy†Ø½MÊ’ƒB'bNø9é€*êiæ|Y |F¼wpš@»ï Nµ }Œ(S>0ô"ò?ÓZkzÇrÝ+¯q*W”ÜÞt¯§«úø§h@¼¬ŒÉ.ËÝ‹¤ASÊÞ èµ1NÑ®^^‚üÂTˆdÓ2™ÈwвàIå%A õ ·Âž‡Ltv™eh¹úWío40àñ/ œ/ݤÅ;"…Sh\]H΋°üP#Kƒ(¯fØ~Ùæ¿xˆ¸¢Ãý´ß”y{å®§³3@ÂñsÆöìû>·ƒw²wKèéÙ[?cD3ì`ÉINß¿›Å±¹Žò«Þ|ýj†ân>0G:ÉDgüü³ïaÍÕÐc½’>N¢@ çs½„®lìv½Ÿz##Lm+;ž'¡ù±V“nàq*?RèðªU(aeòôO ’Hõq,ùèUâ*×zíà_µò…¬0{ÖY'-š¡:#ÒÞÉV|ޏmèýù wxiÞ/¤¯T®#¾á3¿==1A´•8èOºI'%ÑybÝV¸D™g½QG°ûðV¦…ߨšLð´¸n™ú ©|<&ÏÄ×ä09ª‚(ó¢ç̬Ÿå4Pk"ŒÅŒ.ŸÚ«ó>„ã „ŸNËÏÜÄ<ÛËE™¦åÝgŽ—âíãíÊh‰G”|êáŸ5ô†=t»±»ÎË”jA›{×¥ê¯Æ©žEKÍÑðAÀð£~ÉÙ5$ç)©SŸ€5€uÂì03âæËwže.ÙLœ¡[l³fd“ÀL_?`%J2Uótb$ìw÷;¿J›D~*|&5«`Y¹å º8\ÂÈ<y8Oâí#B¸ ËÕû 𮡅}ÍÛ·»·Ÿ1htð§±C¦Ù‡)úª-šSYõp.¬ŸŽÁúú`ÕËVJ8¯P7a_ÔóUô Éó‰'URR+VV­4ê4žûÌJÑGGì0h·æ‰2‰pïÞkls¥#LœoY/²|ÁõîÕo1Lù3 [‰0g WƒÊø ODJyJ¿u(ú¨,qîð6m*íÜÎËã½ô5Ýúú'Ñ›&¼WlxG®UÜ€•õ™¦qŸàŒ›ž’€m‹Óè´ÊÉŸ r‡cò^Ü륋fÎ ‹J•÷æR#¾eK¶?Ä)(CB)Ú„}¬‚½–ŒÚ?/FÅt8ÇkD*L»¦itìl–N’ ’ÂJlÔDlt›¨ž“ˆˆG†¨2âú§ï×ÿÜßÅ"…î|Â+!O¹Ù’™‡ÿ±65™©5p5Ôî2ÿDxÒóMýy6tÄ{‡µöb09 y«Û«'Pƒÿ.÷yP¯\w¿¦6¿ûåºaõ¹ wJæ=èÀ¶¨¦SPWЄ¹öËj=| ±ì]aæ6à.8h [9zQƒ‹á ¨$„Ýr1Â|°ÑDÕm]›ÓÞq…ÊlQÜG·ná¸xJ%ê¡Höwå%4)L6›¦`û5|x^·U¦øaþ'GMJcâ«ã`ô@jù$^¢WðÇð `«¿]ÔáIi1@¾U†Ù°>V¥È§EZëaÇ)f€$o~1>_Hª‹í«´,ðXké¿ô»•/ª¿<ðÀkÄâ2*µìæ'kñ'1LeÎ3%,XFÄû‚8ðoºä]¤PBWù|.a£lRË¢­ÓZ+wŽ/uQùf/Ó*EÏD½çOÝ=~FÎ,÷ª;D·qðq™ôƒÉáî Ìé QãÛk:ÎDXR™Rl»ãPš²y•+#•ÍV÷Ç¥ é1L‰B†ì2‹4«„\¶Ìjþ‘A"`[=jÐ^ÿÛ›ÈH"jƒr¦É=§8`Hhï7L-Ý\‘õ’ ]ÔùbVdœ¥5uC>°F·X.ªøib ê³–ÎEïT¼&F­žÍ</êð„Ab8IÍäÓ—¸S£9_YS•›4ú¼?>?hk¯éšƒ ,^Ú"ûíõ‚ªV‰Ä¥oN3 æv µñòGÊÍÕùB«~…ª}~Ôº?uÉ@pKPÞ‹°‘Í8M~r*þ!ÄùlðñžYýÈwމ4Õéúñ‹¶ÀC!øÃM¸ò6/ò` Dkµ^ÞS9­>ä§n:6$äK²´ílØ€w©ÒCsõþZ &_ºþí£ò Ӳѣ­œ¬·ð7'9Þé—2\s§ —_’]ì^Q² lvà—âxʪ‹¤šÍj Ù†?£¿™XSqcžRÅœ¥ïƒ¤xú]j’ßJÃÌS©²“¶€¸ÜáÑÑZPÙÃ71dWM1w)ÒxPÁ·4˜T=^­CéS1¥ÂøTâöf¬(Ñn»Ì&ƒá™¾2‘ëa²«Þè »"Å%"¾„y‘Iëùƒ…àjB5á)!î)5vøc±Z6ÀÒ懲YĨë)Æ€{`YiÄÅ"¦‡`©Ù/xË™…Q[ÓŠy×êðcþ÷sUû‚O@é*^8#n™ ^]Ðu¨’·.V©/fýõ½ór»Ú^ÈÇKZé]‘}µïf/ݸ³‡Ñ?-Ììªó‹û½üŽ0£ïÜ5N¢ŠÃ³vBÚ¦œ#Y gPuå®·¿£P}µÀ~ç€÷øCó„Ž%C2¹W÷”$FœðyuN’] Eµ£^z#é#:ï“Åx]Âû¶z:>ïì.ÉDIß±«pÒ˜kÓÐÈå)i™»0vK¨—rJý€+驌WKK:üZ=¦ T-÷¤žg·þ¨Ð ¸¬µ'†8»ôä'ªYóñ:îÍWžõe7 _ïŠ'SîÓÜFÙ/u>y¬ý ±C?¢”¨,<¯6¸ÿ*ÌÕ±wG‘å„ç­A0À*¾Çòý"@<Îÿ3ÊØ"ËçºKÄa» ’ÝíT¸K*óMɶ’oSòσ¾?êâ·æfÜš{g¶™9 aª<×£X9pÙdŸè-ýÛ®&¼5Q~)R¶¡´‰™Ù›8¥µ€1á¥Íí$«ƒ8Ä.Î_¹m3Ù˜3˜5' }BDØþ3“xÁ0«ñ@-ƒòˆÂ?~.â#8k0 J.ñûþZV¸³mÅ0:;>¼³ÙÖ³ÉÇÌÊÄü¸<‹¿ üt""ò¨?år4Î]<² ”è}é"&ÏŽ‘ˆÅá‹ÈÑ¿Ì{íâ6®G¹AÓ&ËãÏjõjŽ]íÜ phß|êÒðd}pÑÌ4rØÃÍRž$¨ ã"(T ŸúÎ?{v­k~Ç#tÀ‰­Ìü†ï»DK­Â gw¹‚j=PnØ-"9A‚ä<6|üÞåiï@Žw+•$¿Î' «~ü™þødî}+ɰY ±T¯Ívàn¸}4é~ŽVœðÒ'ßSÖÑ]CGØUÅËmÔpqÑK*¥Ižˆ‰¥/n$Öq,°\BäØ 'ª¦„@ .óû°ñêtƒsL©T׊]à•0¾)/*ÄÝq07V1ÞDz˜òSÔgi´‰ ËÞ?j?™SrZjÔŽ_¯c*nê³3‰J oÒ‘rn‹¦»ÅÖ¿ïigÃýžŠó,ðBÕ&ê°”¾ðõª^دzˆù¥P™N–ZŸ q8Ù1¦'Üju<‰ÙAc6dU·äín,œÉXâ×Ú+‡çIp6µ¿TÑf,Õŵ"d1£ÏU'°Çߦøþ JR*}eZÞ~‘äK”ÂIÊÊIí¢?44Ñc(^wŽ0>8n¥‰r£ŽË„‚ú& RBÙón¦Ó[¾鹈„ú,¯øå‹ÜHÝëZýÞ ¥=ÖãI¸lÄAÚíðŸPõ 9;^ÐÅ{m‡ÕÄLœÅ¦Ø–Çö¼…™Á§º¤‘; ¢÷ÞpI4ƒœ¤¤:Dcœ~mö2"¤!$»ðZ×xÌCV:=­Ì…_"¹›¨UvÚ»¨Ç„Aij޲\_ša”lô)¬Ç©2X•{ŠL‰i‘ú+¯Ô¢UP?Ø{É?ª‚Öç^ŽJ3ÙxÍõ }س\ ë q¿)UÖ*Sª¢ô„øpì]öÓOÐ,¿!‹]}è.#²’P÷/&D§GbÈuIä]•&é$ͪj16F…|ÑK»éø°SžSfZ£³4ñO;l¨vÑXL"nµq՛㷲7èaY`ŸÜŃõh¨dnD^Tü»‡AiÂûõ»NÕùoôž¯?Ùã`· ŠâèË„é25Ãä—•XÇmÅý‘x7ÃBÄ_LcÏ)ëM¯ÁŽÇu ÎÊÌŸäÝ\ø¹Ž>Ýãq!Ö‰+Ðæ£QIجKïä£_&xÏ1б%7úXÍ€×Ø¨ÔŠe,Âþ ¨~hÿüŒZ /Šôžfbù˜©4©´ ¦ÙNI9xÞK3Ù,ê¸ó\BB|‚~Ác7•Ðt ¬ßö—噟žtTÑ„ô´%Â|À)ž½³ùmºfi›“ÉhVOÎÜmoùÑ›!ÎG¬óòØýž~@¿±ÞnbMàÂÉúa2o,ý¹ì\Àpb”A†ª/xëï¦Ë›à霉s¹ò‘b#â^é0:f’¤€>™çÞrÓ]ÏüÆ+´É¾?ýk—ÅȸÃ{µ&ª©_~¼gÿ½®£¬ éO_¹{ …˜Cê-iö*ļ…FæAxá…â)T‡Ÿ›†?ãï NµN?âT…ÑfÔ1°fg׬#ùÉ|£Õå9¹]? þ›ÌQóV§À—«N †®&²ŸåÑÍ£©‹|È„Ej˜œˆ1oùþ’›>6»:C!m?_Qé‘5‡TÄñ-MÊ…òŒWæ¨q`FòoLg£G*êÁkaB+œ…4ö’sYr¥§´.îƒêlŠ?Añ—ËĆÃÖ¸’¥xl×lQïÑ»€%aþ+dØCI\7°¢›N¥‰’ü ôFg y0_ ¿§ZÝ’Àµ_(ÞW3‹·[<"æÈé¸eõôI©/*æ .YÕƒD׉ó—ŠOxÖRcf]ÑÈYÞ8õ³æUÆÙÈ|Â>”q£XÁ´*üE¿QÑØ Y…þ¦4‘Î+x'MË’ÍŽqt.z°&Rõ¡ÑÔÿ@ÕÓÕÆ¬ Ì2ªÐLËþnéôX§Åü¤ ¬NIa_vPüƒ É·£§ ±°Î×å·æ&«ENûö?ùŽ ~îÙ¢ÁM¾öŽñ ˜Õ§RELeÞó¨ÈåÁP]¥?3Á@áUO¥!:sª@¯b<ìNÖä·CÉoŽsšzÔ„žóûðS?BqÍQ²­¬ÏŠç=ãC ‰Òä8¬ží1gNƒéÅÍÒőޅ(ÉÄëÁǯî÷|.ïpDË_ø #ÍvO¾æ5ý¬S¾R¶ váú]¯z!Êw{qЙ `‘^^Xi¦t¥¡Ý²sâª Ü WÌ ý>ïJ’ßïøüí·2tßc-ä>ÿZOçH(9ðW«Oé®Bu3êpYdÔJ*ˆõ§ä1 DÙê{t‰*’7xýÉ_\ÏqjÇ èñ²¬§2¨¡šltŠd®ö hò®+J ÷}?’@ϫݟ:Õ´b¡!w,Œ‰H×jY?Ò]Çx6¹Ì¥s®ÒùSbïedz}Qï"j[Õ>Sį ±©± ¥±2›ÁÛQA ]°W?¥›Å\.»Ñîg[¦óÝÚb _àªzäçEã#cáoN5HY|̸cAžw¹ gU ã/T¥¦N "0ô6Z/“ÖuQg>±V²—ñMƒ~âµXlz€ÉrÅïí,-5¼‹•±  àeݘ.ß&N5HOQ]ÁŒ˜ä/Sj~F’¿`Ã:É}oÅ_¥ùÙtÎÎcîe]Œd¶Ã=K9n.Î`i%‘ȯ'[æ34CW:€±ÿéGq“cí]o“笟a $C|nÓÍU[®zÇÑÔ¾ñ„ m£)Úïv½j¢ØÈVl±•^±ºzeadžÂÆw´ÊL+¶(‰f‹8ÄCy2ÚíǯËJûblÏ79Ó®µãDæ_<4ö8ÍÄM fdñviX’·ªPJNÒZŽ@_Ö4½AUÊ©Ãq?Ñý’Ny‡ëî.lJþh å¿óŒ&ÆQXnæù6L]%¬ÓŽD]1Îí ðœhxO=! JtbëÇ~ž•Ý"ÎÒON³×(ì¹§PRv½öÙä]œì#Ѓu_Üt­€€÷*¬jy¡û?ïýÛÓQ)b—b(•¸8o)*Ö;a?ö¾èþß18.JG/hä°{aÛüç­1Ez´kÑjÆO½#E‹Øž0I&Žjƒ%ój„ï¸5¹„›!Š8èÅd:0]Ñí+ÇLájOš>Ÿd¶o9×çää™Í`NMѲŠÔ€ñÔ¶syù¼ÛaJÚ`0ˆ/ݳýWøÊ|ÖÌ@@sSL{–œÛŠ[´Éãwrµ!ÒŽÔE  èù R)¾%@%K§„®‰†rØ.۽①9:^¬d|Û†¶Âà{_™×C‡¥%oÀ°cH¶š+éw=)bS)·%ÔœühŸóÀü[YÍ®ëÒ7@Oé%—¯œ'Ù,éËVCnJ%à”XAˆÔ›aZ¸i‹™ë(†ŒÎOø·•¦Y“q1Œ´&Ã27}å}í!n’y#¬AJ/±1mºÕäèÖÖ¦ãbq¡=ÝÅ0‚0|›Y cb^Q÷ e‘™…°GDß)ŠV`ž©O‘¤ê]7ÎßuÃ'E™¦#m؇ .~™¯Ú¯¾àÌ÷ 9²¶.‘µ nv©Z4ïóA˜âË|³^Ñ`¼À"Õ2|ålcWRH•/J6ûÑgò¢ï[ÔŸîÊM?ª3ä[{Ð3Åh1.‹Úãê}Ö¾ƒ[ùØœ0½‹Â«‹#¨àGþ¶Šù*SÎ$ü”¦LFý(ÿš †EþîÜ:ÉÒÝQØfñMhq0î[d'ü3© ½&ì™Ø|­&×õ ¬Ô±!¶ÏØÒžÁNâ ôñÓ˜HÂ=¹pÂÂÑná5–²*‘é¹? jH+bæÎ`¹ã“ÕÚMY2°I‡©' û“:U½?ýûõ‡ñUúlÑ!ƒÔ‚ Å2]¶D3|&°hâÛO#“'z$ Qø_èE­Ý/…VÝE®:Úr'?SÂå×ð!ü´… ·JýÆ0últ4×%ó­©<7g¸€íM¸YÃËš),V×ÁÀÁ¶*„{ãâ¶M)äœBN[.¬Î]ŸfùÏetì]–; SbcåQ-øa%7£óé¨ÜÙîÀȉÔ˜Þ«p¤¸I¦)ì;t„ñÉŠk&ÔÝcAçäå¹AÔlµ ÎÖ ÕVA«™ j¬éç±*n`Å>Šñ;8ÿˆ?Rj›bÔ;ØO7à›ì%8÷+yZ°d[¢Á(Dø¥ïÏÐæÛ‰¤«B¬i23û¶¿ï½ù!a|«WóÀ!)²ŸƒC^3jÓí h8Îv_ ˆÖµbeó„Ë$ç‹Ãôûôó€d@Žy1»MáÏ‘!ϵ°NÚø¥™•™ ”Ìi£2efB½P_~Ò>*JÀ~ÎÅ<¢›‡.ÎÅð¥‘n.s¼Aû Gü]B•%F®òRí¢Ò)鄘‡Þª‚È Ô$>¦J:½%lxûþü»õ± æ¡~û,‚»éNûc"Oçñ³ÒáL™BÚ “É•.ôö³†K|’=Á›×êbÌúyøiD°ûŒÏG”’¤4ó0ñ9:ÙúãQz »“½€>QÞzž~øÒͼŒU"¢$EHéGQ<¼I´!Ï»¶D¯Ýš*„I6Ì|l2»ï_\²ñI#”‘NGØKl¥ ÷n> ä„p ·ýùHå-¼ºRƒFд[•‚fï%â"Q÷\‘ÃÓC<†§Òºà wØ¥ 8`÷ ÚúÌû!ÆmÝâ÷.âŸÃT!6‚Í«œñg—E1Ìk½KQeÅy²ùUŒ^q‡c—ÐC€+üC‘sr™Pw ÙAé@éûJȉ8‘í°ÂšÖedð=“—}˜ÞFfO2KÏOú0k·Ï’…¦rͰÈùþ«¿/7]<·> ¢ÌK+LÜŠvö7™tØO'Â}¸ÑŠÚ'5TòRê¿ÎY§ô‹êê©dÀ¹jç¤F^ŒÃ,G+’s½Q‚õ¤“x{§Ü5Œã[Jü CD†Ñ!£%¨4ðò€èBò¡‰±ñKŸN{XSZù½©’Ž×¤ Þd¼¦#½Å^äl¿6ì;A{D㉱žÄèñ=Ö?#‡°Q€©9ä‹Õ acÞ–SØÁkÀÙ½Ðcô÷4dÉ®}Ķ…bÔÐÝ@Ÿ }gVnÛbšƒ½Tyÿ~„›ù_%uûýw>”yʸõK ¶F1v&¤½úNHñµtÆÄBÛXÄÞ-0sí´Ï©ËEÙEŠÓdÜ7œtX†QÃÏòÀ ß\.õ¨?$R? WâløGÌ0þHP÷¯s¬C¹+™blL—>ïå û>Úéê½—„ÁÆè7¤æM;°Ùžãtvç³Ò«€¶»aÁböÌØ[ù²)4ðÍëM{U[1‘Üß, ÷"Ê7r.èýX©±µ¯Öµ ¦c˜£ Ãòl†°Sê†g—>Ÿã/º²7ÄwÐ<‡¨ íŽÄ:ü’S+Êfì£TÆzýݳ,q]Ò*Xg×è!w9°bý³‰>ošÐmÆí1ìËuµ#™{³J´B)˜mqYô<£¾°Ž4›=³îËJµnÇá[ûÁÙn8{Ç·§”ÑõGD"{Hº°¯ìØ|5u‘r²Ž®ÜéNÝÚ{úâ÷=Ï[Šè¯E„9qH}38ì+ýêËî¢æ7Ð\'Λº—,럪œfñÉi2î-¼2:ãð¡5ÜÄû5Jäê,´â6µGã=F =½wü’á‰Á®¿"¿JLs¤ #˜ ëíÙÅÀ=ÀWuúÈx?¡ÛµíXjÊÐ3xëÂ8Sáðî1Yù´}ž ïw@®U]h¯ñ°ÅÅÓ©ÿ¶W/#$ŒİÔ+¼¨¸UÜR‹ð^”.ê3àƒÙ¯°³ÜÊwx:1rmRÛ\€Ü› ÕvÁÔƒ‚n­íÉ/¹>ƒ©i‡<‘ðž <]x£§uŸ µÊ-{.„å5cÎsüÈãAÑ/% w)–[N‘Wß6Ì*–#†ë¬}k—³¹‡HVfÏïx¡âÕåÉ&áÄ'/åcç|‚Ü-KݘbÛ2œ{ú3pÞr'õÚÞcŒµH>1§MÆå™ž²sGLt[®b2|oOa mv.¾a"ønTm3ëv8 }ÇDœÜôoŸ¥8(ÔŒo‹¦[‹nIXÖ휴‹¦•S:å«Ö[c•QÎä°Òèï€w´ÎÂI’Î2u³ ôÅÊ;Íß-×u¥‹IšðÃ9ëy⬠Wy&Q0¼þIŸy¥ŒÎ·S:·1}M=𰣦QV¢Xâ…6€ûSðI–ÇÜ’¾yœ¿·‘"Z)b²æ4pÖ!Ú ˜¾/ˆXƒvðsÑ!,Þ\—!’m…²Õªaû OYÊÞ¥a^Êåà|[ëà/VúÑ#ä+à1H¼bp§º<È•í+2íÈù|K¦JµTwppK&¼ßgYœÍ³½€^º¯ë!¨‡ôiܳdÅ¥„Yi*K¯  ÚWÑÞþ$^u<6:°_˯“3å8ŸûdþιeÎGæ¢Úâž”¯—Ǽ>F°¬#ÔfŒ^ )áIídªêýŽÐ¬~0¸ùq>¨—ó%C§Ûß+™Ï[¨e'éa¦Ec¨lY¡ŽC!®eÒG“j ¼i1ùË~Q ¶´@ãË¥Â$0 øSÓùá7º’ÿ-öìLPlÌwàM j·mùÛY²ÉÑìÔ=KfB.©‡Á¼ö©76 ×Ô‘m4 þLÏ©¨{8ÉŒñà¯V½‚ Æ½}ªhJÛÀ„Dî[Ú¯ž¹@kJ‰å§Fæ“Eq#ôËž<*ìÅ Å3'XEr›xÛë÷fsÛVéî›—ßA)E h@NÑÓbFÑ„“¤2þ}ïwØõ*æ?‹ï5ÇÝMÎ×~¢í¬ci\çp ¼6 ”lþ£‰ñ^$—XÐÐRVkä!„ÒµšH}ãÍÐÁ+a£¡Øöa YØNç6ÿ·¿/Dž³új\b€V¢²;ó±ùÇ£¡B ðŠX("ìÈšô{è™ö¡®¾ž;âÉÉÿ÷7?Ä‹ wE c[>QgTe=XNiŒIëÊYá1í«û_CÒnªDÄHcÛ<ÕK}昕¢ÞÁÙyàX‰l¿.ŠÅL}1´òâÃÜÙw¡•Ÿj¤RK[ãqLáøEW'Ä;&ëáˆë­ÙºC¶uÕÛ·–þ#;¿"ê%ú÷ØÄ;‰¦é'Õ„g½ÕÓw¯úªa:xK7Ì6{Q Òí1Šà¢dÀœ¥iƒÀnÖî}€úÑ“Ý`Ê2ÖI–…éíá„©ÚžWCÞ“ïDÒ$j‡Ž-ÅÉwó<É@ˆØêí€)ÕÅoº–ƒ |æe„2)7)3̳²*(šDnÍ{+Î ŠX‹h<©‘,8¶üèï—„ËïÙ/â~ì‰ïH˜4éƒ,2´Eçiu Üå“´5kb|6 ´zÆõp°ÜÅ­Ý}Ÿð^°S¢U|7—Ðõ K??ÙgÓ!áð6qSn”ß÷›ü¯œÇû_ötæY.ME³>ÂjJÆ JP%Ã!È•¨¾ôt £ßž~;÷afh:!›zR¦º|‹þƒÍï¢&TÀªB(wô–´P*o\ƒvÌzAÇÉ/:¾ŒÆ°ºWzj^îa@Ëû"½Ç 1ÞW­$»WN¦+½—òÎÏ@K-S*E„Ä+Ê®Nª"‘çð€mSÑ¡QFá<6 ’ƒ4£+Õø›âäù< àU™ÚoõÚ†º<&+!͆f¿˜¾u W5 |'[N˜ä o~¬5å¡ÌÑÙŠy so# 01ÆAu~ÒG*ÛÝKa]E÷¦i´6½à¦+ Ñ l¼GûPÊÀh]_æ5ýŒÜ©\E5Sÿ'„O¥Ó­¦‡íÑ]­’D£"B÷{còNyk"ìÎÆYŸò¯ZV©8ƒáŽfð/3Ù†­Jêäž?v³pËY‹ìXÚ,¤ySrÀ+ˌߗTª–;®mC¸Çp"_¿qÇòYýÆþ)5±æjóØPçò~ý™\k–ÀÆc¬¢ÂRæ@B9·Óç¶{I¢ˆMÜ$@¹Z‚E1K‰0]QŒ¿œÀÊyÐÈšz'Ù “@Yˆ¥3Hz9mä÷fàd=yß,á¤x0-åFˆV#5m í}̺w¼©ž½ÂcÖÎú'²¶rp…¸{óÔÂñK~Gô‘Ä:·c6hIˆ²é.na?l¤B ê Ü£ùóEdV©ñESª}tM%ôí÷xH-´ŠôXúL'†ç£€b cƒ‰5u¥{þ™ÄH¹ãNc÷÷ Æx#†Õ'ÃÇUI¾Ðgùà=À‘ a7~›i\mªÈ†ð6AÕ¢pN1‘⣺ИÂE¼„R¼¹†6•+MÎ|…¹IY'çÏø'ù/ícjkgåîÃ~ôôEÏÃÍjv\¢;†®ì ᯚ9Ý™—£Ê!}Ì–Œ×6Ú\LH;¨‚#)YOư³aŸ‘€åIœ=c}±ÃF‚•¾.l) -4ómQô-\‚ÒÐ|œ|ë›E%ùbªhg‡™%YÀhI»² eH–ÿœö$èDpAìkÎ 'rñýš™³ˆ}4ÇÀ ú³@ê¬Îtö Ðt„!Ö©ž8Ž ½¯T2ñ¡v4ÞäWÌì¨H’¨ƒ–ÁÎ3Nty žR²Ù¼0;AÆ•8'-dSžtŸ¹½M²Úy2Ð>è»0ÈXuáKá×*8ÍÙS9ÁK¯¼_FDâqQHx·AQ‡îrÒ0H³ÁK# õVb0Ò›úÝÛ–à˜K»i³{r]*Dy4{ø¤ÛkšÁÃ벃îš"O¤2JôC ØÑ<ïȻٯy&|Ÿ9Ê’,e ×Ó¿µY1DÅÖŒGk)/0T‡{Uåc\ -ÏÉÚ‹v Ìþ­³îüŸz8Gª_#YU[ò¸œôgª¦†OÁ Ú¬â§ñw?Xq­`9d»œ?˜!Œà‘V#eº.&Nºë;ñf‚< ‘¥…Õeî3ÅëIJ[4וJÕ}n™B(}™¦ŒÐúŒ¦ í)–¨’ñb}¬'êM…n•züþ>z-Kâ„;.mä¶3éì!:VÌÄ¾× ˜×P¡‡Ö?á ‹õ¨wÐ6UçøŒYÅaŽÄŽßócœåç#¢Š¦‚æ¤ ~4ê%à<‡ÛäµÐ÷NnÃ¥óliÅ—Ð}ïéò)ÄçQ#6?œb(²W/ƒÄsgöbiÄ{M®U×Ðu1Ý›m”.k±ÜïIž8}%‹)à˜³'‡àIS;@©›ajéŸF}ÓÍwý蟾n®²,,ˆÔÓ•,òÅè>ñÜÞ.h±²' E¢ýæY2–ݱ|êOg/§àõÈ#ãð:qÄ`„/zÉM'y"œ-€¡f“tÈèþzffÛŸó‹ëˆhívxOލ8¬p'ØÝyüL3“zz'ò V09ÝjHí ®†Öh2™cÞãÈ)4½½™ ÛÛGÍËÀo:æÆ:< ¼1BRÍÖf„Īÿ6ò‘Y¤›˜è2%j§ձj§%6…PËCNÄZìö–=¤b%†¿×&GŸÁƒãþå`èŠ|ü½½WF´.s-À6ÜEw;ÌsòñLôwN`yã½”è9Z[{mSð³l{„Öýå¼êÚ…‘Ñ›-|»¼Qß‘ ¯8y—uí…O¨ûJ“¡Y+[ôÿmù+ï endstream endobj 79 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfTeX-1.40.13)/Keywords() /CreationDate (D:20120912134100-04'00') /ModDate (D:20120912134100-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012/MacPorts 2012_3) kpathsea version 6.1.0) >> endobj 2 0 obj << /Type /ObjStm /N 68 /First 516 /Length 2739 /Filter /FlateDecode >> stream xÚíZmSÜFþ¾¿b>šK¡Ñ¼R®Ô6 Ø.Àqbu%ï ­]m$áàûõ÷ôHZ´»,âÜ݇”-$Íôt?ÓoÓ³#Ábf˜Ì2³„%‚‰ÿ- ÿš k˜ÀS‚FÏ$õ%L*?’1S^3)˜¡ɬ¡æÜ4K”eãb§˜L˜Â20 ‚@!cÉÐ+µ zõè%± •†d ¦!\{Ã4Ú $ ´[é™ëb¦=€9É4 '`¢àùxd$ÐÐxܵUÌÄLZ…™¢ß‚Gh08Ú1éÇÐX3£™’Æ3Cb?2¬A‡&­1> ‰¡4ˆð 'Â%˜?3x­)[41kΠËËd¤ š0¥™“h4§@§ ;ƒ? š±àçvðq "‰;Àºd ¼ <ósÒ¸%`©˜WøãðNRaÞ&`…Q¸y; ó&=}Êø ãÏËÓ’ñgìI›¼œý#[ì‡FOŽÒù<Ÿ]°"ûœ5+ÏYÊÎÓqSV[›ÇÊvìÁ¬©ÊÉUh¼ƒZµÔϲz\åsjcäÍ%Ë®Óé¼Èê;†êvèÉÕtšV_ÖßÃ3cvÌø~ÞœåÓ§#~úež1þ:½ÈF|¯œ5Ù¬©áD8âÇY]^Uã¬&7 -GÙ$OwËkö>¦pIL$I—ZD>9Od¤@½3›•`÷®$#<ÂM¶7ÕÞt¸–…¡#~rõ¡ ï‡ùìÓˆï–Õ$«‚lqÆ_ð¾÷žxÆgvÜ`ŽÒEÞÃ9ˆàJG³ˆœHYª¶ª¾çeÙ@XÖù‘0ð8„áldÓÁBD|ŒqoÓj–ÕÏ'i“~;,RèH#”:,ÊFʈÿ%mÇ”STäay¥a J?ÊD^éÍhöËë½´ú†@´‹Dln€Ø$Šá‘2ˆ¬_{‡Ì%‰¤ÌA×lvUg›HuKjE¤¢îCê¬w?RKÊ}H­Wѽjãèw“B‘ ‰ÚÊH ­.Qî#Á­îÓêè»l„ÕVÅý³¤Œß=kZºgC+D÷ŒU ¤#²]•ã“ E{¶Ïøivݬ&“•ô¦ÍjzÓêéífúZßL*-1ì?¤U±‰P h¸œÕ÷RÕbê+*ªj¡ÎǪ'YSûSÙ_·pt›ýMk_-ïHû›âW,â×"Ê ÔHðмΦC8KïÎ!$¾óôiÀwÂRÉOø›ãºž\6Íü{Îër\gÕçˆîã<šŽ§iÝdU4NùÇóòšomÈ;÷Š¢‡Ò-Li£„Š k"íÕƒŽ«tUÛóªüöQY]ðºó1ŒWåø l¨ùåîè²™‡¯°xxkQA¹È¢ÞÕÈ* c&‰¬°ÿÿøcd®X-ôOL¢>°VGÖ<ÿ4Í‹¦üþ¢Ê.Ê*Âõ1ÿùá¼*£«Y¾]|Œê|kiQÐþÞ‹Âi¿(ø(AÜEªâ(FmìTBNR›(ÔOËÃü2LÑ‹tw®yoP@þ}ýe×ÙßþkµkQ*bûK{mFÛS‹-¶LvïT2RhÐ_Jè£=oܶPXÆþ…~ð”´'w´µa]k¦s¾mW­ å“ èÃXÜé½óµ+ÈéÆôíJ­›Csr1mŠux6ض;K;hD<u’é°5¤¾DcÝW ÷ÄG·wT'¤1 ?‡}ž ½:)¤¿z5õ÷ ĤQ Ð. 4Âx”-‘kèž±míF€¥tE.ªå $r¾Azò4ŒÀ'Ž×ä·¦X ˆãrÿBdBMLaÂI◌؂Üdh™ü9ÓP{0 ýš$DÐ^o¦`)Ã{ïÁíОIIý½IéÞõõï46Ðï¯X&l\á:îÜÚ'Kú’›ìä’,z§~KcÂÕ[4ü‚#{`¶©'éÝ éÙ«›ÑýŒ‚…úNjðÁ3—ÕD׃¼/x]ç}ý<{-tÜ={ ÅeJíh£ñje­g“wü7‚ìlP$ѺÞTeÕ®ó/Ó)z^ì½yöêø»½£“ÃÓS£«H/Pç·4»¡Äß–1Û–a2àœP©´S©À6lÒù‹,¿¸ì^IõmK)Gü I‹|¼3»(2¶ Æj²é/`2â¿vƒ´"—iEþÃwùÆäûüñcT^§ü ÇSþ¨Òñ§¬)²ó¦®ˆ §Âq:Mù„g<ûý*-ø9¿à¨ÑRïü’_~™_f3žó‚Y]ó)Ÿñ’—³ŒÏùœv+exjγ*/'|^\Õü÷«²É& ^ñš7¼ù£äŸù5ÿ²Õji?Çäl<Ü ~MíG¯w¡öÍJ×­ÎúS:¡ò—KJÛŸ¼þÄÓæk(P'÷f˜”E‘Vkœc “ Lññ¡Æø}Ùu‘Ö—dË*Ë‚U®È.KV‘²Êów/ßž~÷æøíëè'yy¸½[“Û $°ÝVq—…enläb¿d#'‡6²vƒ„T#¹%#íÂ@0†"a\ý¹ ¯®š"ŸÑØ€„µ~€ôÏ-S±—£0¥Ï2ÚSúN#’YÁÖË’­[ô™-úNf…Űwø²`Óººka»ÖÕ¹KK·qAh‚ÎÝRîÁEy1jclqÜÖÎÂ{Úé8×»ÖEvTN2þ¦ÎnbìÕ<›µGôAS'ê? [tà endstream endobj 80 0 obj << /Type /XRef /Index [0 81] /Size 81 /W [1 3 1] /Root 78 0 R /Info 79 0 R /ID [<382015842B56E58A011B3FD96FFAE5F1> <382015842B56E58A011B3FD96FFAE5F1>] /Length 204 /Filter /FlateDecode >> stream xÚÑ9VQFá¿´›AœÔv@çQÐÔÜ€%¸É]‚[!3`&n¼•|çžwNUO’fÈl<µ}0` iXƒ,À"Tà2…%X†"ÈA6L*øÝÜ@.¡×ppëp ;ЂjЀ*lšò#__†]Ø2Å‘¿mCê° œÁ>À!™¿>Ö6½…^Ǧ¯©×‰é'ñ:5«{uÌ^Û^]¸ƒGx‚ á^Ì>ÞÿáóOsP $ endstream endobj startxref 100570 %%EOF gdata/inst/doc/mapLevels.Rnw0000644000176000001440000002014712164370064015533 0ustar ripleyusers %\VignetteIndexEntry{Mapping levels of a factor} %\VignettePackage{gdata} %\VignetteKeywords{levels, factor, manip} \documentclass[a4paper]{report} \usepackage{Rnews} \usepackage[round]{natbib} \bibliographystyle{abbrvnat} \usepackage{Sweave} \SweaveOpts{strip.white=all, keep.source=TRUE} \begin{document} \begin{article} \title{Mapping levels of a factor} \subtitle{The \pkg{gdata} package} \author{by Gregor Gorjanc} \maketitle \section{Introduction} Factors use levels attribute to store information on mapping between internal integer codes and character values i.e. levels. First level is mapped to internal integer code 1 and so on. Although some users do not like factors, their use is more efficient in terms of storage than for character vectors. Additionally, there are many functions in base \R{} that provide additional value for factors. Sometimes users need to work with internal integer codes and mapping them back to factor, especially when interfacing external programs. Mapping information is also of interest if there are many factors that should have the same set of levels. This note describes \code{mapLevels} function, which is an utility function for mapping the levels of a factor in \pkg{gdata} \footnote{from version 2.3.1} package \citep{WarnesGdata}. \section{Description with examples} Function \code{mapLevels()} is an (S3) generic function and works on \code{factor} and \code{character} atomic classes. It also works on \code{list} and \code{data.frame} objects with previously mentioned atomic classes. Function \code{mapLevels} produces a so called ``map'' with names and values. Names are levels, while values can be internal integer codes or (possibly other) levels. This will be clarified later on. Class of this ``map'' is \code{levelsMap}, if \code{x} in \code{mapLevels()} was atomic or \code{listLevelsMap} otherwise - for \code{list} and \code{data.frame} classes. The following example shows the creation and printout of such a ``map''. <>= library(gdata) (fac <- factor(c("B", "A", "Z", "D"))) (map <- mapLevels(x=fac)) @ If we have to work with internal integer codes, we can transform factor to integer and still get ``back the original factor'' with ``map'' used as argument in \code{mapLevels<-} function as shown bellow. \code{mapLevels<-} is also an (S3) generic function and works on same classes as \code{mapLevels} plus \code{integer} atomic class. <>= (int <- as.integer(fac)) mapLevels(x=int) <- map int identical(fac, int) @ Internally ``map'' (\code{levelsMap} class) is a \code{list} (see bellow), but its print method unlists it for ease of inspection. ``Map'' from example has all components of length 1. This is not mandatory as \code{mapLevels<-} function is only a wrapper around workhorse function \code{levels<-} and the later can accept \code{list} with components of various lengths. <>= str(map) @ Although not of primary importance, this ``map'' can also be used to remap factor levels as shown bellow. Components ``later'' in the map take over the ``previous'' ones. Since this is not optimal I would rather recommend other approaches for ``remapping'' the levels of a \code{factor}, say \code{recode} in \pkg{car} package \citep{FoxCar}. <>= map[[2]] <- as.integer(c(1, 2)) map int <- as.integer(fac) mapLevels(x=int) <- map int @ Up to now examples showed ``map'' with internal integer codes for values and levels for names. I call this integer ``map''. On the other hand character ``map'' uses levels for values and (possibly other) levels for names. This feature is a bit odd at first sight, but can be used to easily unify levels and internal integer codes across several factors. Imagine you have a factor that is for some reason split into two factors \code{f1} and \code{f2} and that each factor does not have all levels. This is not uncommon situation. <>= (f1 <- factor(c("A", "D", "C"))) (f2 <- factor(c("B", "D", "C"))) @ If we work with this factors, we need to be careful as they do not have the same set of levels. This can be solved with appropriately specifying \code{levels} argument in creation of factors i.e. \code{levels=c("A", "B", "C", "D")} or with proper use of \code{levels<-} function. I say proper as it is very tempting to use: <>= fTest <- f1 levels(fTest) <- c("A", "B", "C", "D") fTest @ Above example extends set of levels, but also changes level of 2nd and 3rd element in \code{fTest}! Proper use of \code{levels<-} (as shown in \code{levels} help page) would be: <>= fTest <- f1 levels(fTest) <- list(A="A", B="B", C="C", D="D") fTest @ Function \code{mapLevels} with character ``map'' can help us in such scenarios to unify levels and internal integer codes across several factors. Again the workhorse under this process is \code{levels<-} function from base \R{}! Function \code{mapLevels<-} just controls the assignment of (integer or character) ``map'' to \code{x}. Levels in \code{x} that match ``map'' values (internal integer codes or levels) are changed to ``map'' names (possibly other levels) as shown in \code{levels} help page. Levels that do not match are converted to \code{NA}. Integer ``map'' can be applied to \code{integer} or \code{factor}, while character ``map'' can be applied to \code{character} or \code{factor}. Result of \code{mapLevels<-} is always a \code{factor} with possibly ``remapped'' levels. To get one joint character ``map'' for several factors, we need to put factors in a \code{list} or \code{data.frame} and use arguments \code{codes=FALSE} and \code{combine=TRUE}. Such map can then be used to unify levels and internal integer codes. <>= (bigMap <- mapLevels(x=list(f1, f2), codes=FALSE, combine=TRUE)) mapLevels(f1) <- bigMap mapLevels(f2) <- bigMap f1 f2 cbind(as.character(f1), as.integer(f1), as.character(f2), as.integer(f2)) @ If we do not specify \code{combine=TRUE} (which is the default behaviour) and \code{x} is a \code{list} or \code{data.frame}, \code{mapLevels} returns ``map'' of class \code{listLevelsMap}. This is internally a \code{list} of ``maps'' (\code{levelsMap} objects). Both \code{listLevelsMap} and \code{levelsMap} objects can be passed to \code{mapLevels<-} for \code{list}/\code{data.frame}. Recycling occurs when length of \code{listLevelsMap} is not the same as number of components/columns of a \code{list}/\code{data.frame}. Additional convenience methods are also implemented to ease the work with ``maps'': \begin{itemize} \item \code{is.levelsMap}, \code{is.listLevelsMap}, \code{as.levelsMap} and \code{as.listLevelsMap} for testing and coercion of user defined ``maps'', \item \code{"["} for subsetting, \item \code{c} for combining \code{levelsMap} or \code{listLevelsMap} objects; argument \code{recursive=TRUE} can be used to coerce \code{listLevelsMap} to \code{levelsMap}, for example \code{c(llm1, llm2, recursive=TRUE)} and \item \code{unique} and \code{sort} for \code{levelsMap}. \end{itemize} \section{Summary} Functions \code{mapLevels} and \code{mapLevels<-} can help users to map internal integer codes to factor levels and unify levels as well as internal integer codes among several factors. I welcome any comments or suggestions. % \bibliography{refs} \begin{thebibliography}{1} \providecommand{\natexlab}[1]{#1} \providecommand{\url}[1]{\texttt{#1}} \expandafter\ifx\csname urlstyle\endcsname\relax \providecommand{\doi}[1]{doi: #1}\else \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi \bibitem[Fox(2006)]{FoxCar} J.~Fox. \newblock \emph{car: Companion to Applied Regression}, 2006. \newblock URL \url{http://socserv.socsci.mcmaster.ca/jfox/}. \newblock R package version 1.1-1. \bibitem[Warnes(2006)]{WarnesGdata} G.~R. Warnes. \newblock \emph{gdata: Various R programming tools for data manipulation}, 2006. \newblock URL \url{http://cran.r-project.org/src/contrib/Descriptions/gdata.html}. \newblock R package version 2.3.1. Includes R source code and/or documentation contributed by Ben Bolker, Gregor Gorjanc and Thomas Lumley. \end{thebibliography} \address{Gregor Gorjanc\\ University of Ljubljana, Slovenia\\ \email{gregor.gorjanc@bfro.uni-lj.si}} \end{article} \end{document} gdata/inst/doc/mapLevels.R0000644000176000001440000000346012164370064015165 0ustar ripleyusers### R code from vignette source 'mapLevels.Rnw' ################################################### ### code chunk number 1: ex01 ################################################### library(gdata) (fac <- factor(c("B", "A", "Z", "D"))) (map <- mapLevels(x=fac)) ################################################### ### code chunk number 2: ex02 ################################################### (int <- as.integer(fac)) mapLevels(x=int) <- map int identical(fac, int) ################################################### ### code chunk number 3: ex03 ################################################### str(map) ################################################### ### code chunk number 4: ex04 ################################################### map[[2]] <- as.integer(c(1, 2)) map int <- as.integer(fac) mapLevels(x=int) <- map int ################################################### ### code chunk number 5: ex05 ################################################### (f1 <- factor(c("A", "D", "C"))) (f2 <- factor(c("B", "D", "C"))) ################################################### ### code chunk number 6: ex06 ################################################### fTest <- f1 levels(fTest) <- c("A", "B", "C", "D") fTest ################################################### ### code chunk number 7: ex07 ################################################### fTest <- f1 levels(fTest) <- list(A="A", B="B", C="C", D="D") fTest ################################################### ### code chunk number 8: ex08 ################################################### (bigMap <- mapLevels(x=list(f1, f2), codes=FALSE, combine=TRUE)) mapLevels(f1) <- bigMap mapLevels(f2) <- bigMap f1 f2 cbind(as.character(f1), as.integer(f1), as.character(f2), as.integer(f2)) gdata/inst/doc/gregmisc.tex0000644000176000001440000000637611367120435015444 0ustar ripleyusers\documentclass{report} \usepackage{Rnews} \begin{document} \author{by Gregory R. Warnes} \title{The gregmisc package: something for everyone} \subtitle{} \maketitle The gregmisc package is a repository for functions that I find myself needing but that don't seem to be available somewhere else. In contrast to many packages, it is not organized thematically, rather it contains a hodge-podge of different routines that make my life a little easer. I've taken the time to bundle these functions up as a package for three reasons, first to share my efforts with others, second to get feedback (particularly bug reports and feature enhancements), and third to force myself to properly document and test the code. The function in the gregmisc library fall into six general areas: permutations and combinations, tools for linear models, plots, data manipulation, fixed or extended versions of existing functions, and other. \begin{enumerate} \item{permutation and combinations} \begin{description} \item[combinations]{ Enumerate the combinations of the elements of a vector} \item[permutations]{ Enumerate the permutations of the elements of a vector} \item[factorial]{ Compute the factorial function} \end{description} \item{tools for linear models} \begin{description} \item[ci]{ Compute confidence intervals} \item[contrast.lm]{ Compute (and test) arbitrary single-term contrasts for regression objects} \item[estimable]{ Compute and test estimable linear functions of the fitted coefficients (including contrasts) of regression objects} \item[glh.test]{ Test a general linear hypothesis for regression objects} \end{description} \item{plots} \begin{description} \item[boxplot.n]{Produce a boxplot annotated with the number of observations} \item[plotCI]{ Plot error bars} \item[plotmeans]{ Plot group means and confidence intervals} \item[wapply]{ Compute the value of a function over a local region of an x-y plot} \item[space]{ Deterministically space points in an x-y plot so they don't overlap.} \item[hist2d]{ Create and Plot a 2-dimensional histogram.} \item[bandplot] {Plot x-y points with locally smoothed mean and standard deviation} \end{description} \item{data manipulation} \begin{description} \item[combine]{ Combine R objects (such as dataframes) and add an additional column labeling the source} \item[rename.vars]{ Rename variables in a dataframe} \end{description} \item{fixed or extended versions of current functions} \begin{description} \item[lowess]{ Extend built-in \verb+lowess+ function to handle model formulae } \item[plot.lm]{ Extend the built-in \verb+plot.lm+ function: } \begin{itemize} \item residual plots: add rug, zero line, mean and 1-sigma smooths \item residual quantile plots: add \verb+qqline+ \item add plots of each predictor against the residuals. \end{itemize} \end{description} \item{other} \begin{description} \item[running]{ Apply a function over adjacent subsets of a vector} \end{description} \end{enumerate} I welcome comments and contributions. The current package includes code by Ben Bolker, Bendix Carstensen, Don MacQueen, and William Venables. \address{Gregory R. Warnes \\ Random Technologies LLC. \\ \emph{greg@warnes.net} } %%!!!%% \end{multicols} %%!!!%% \end{document} gdata/inst/doc/gregmisc.pdf0000644000176000001440000034353510451013020015376 0ustar ripleyusers%PDF-1.2 6 0 obj << /S /GoTo /D (chapter*.1) >> endobj 8 0 obj (The gregmisc package: something for everyone) endobj 10 0 obj << /S /GoTo /D [9 0 R /Fit ] >> endobj 21 0 obj << /Length 22 0 R /Filter /FlateDecode >> stream xÚÕZYܸæÑ/ù ý¶ÀbD‘Ôá§xíYïdáµ3;Ø H‚»ÅéÖZG[Çþõ©*RêC=Ñ ‘E6É*Öñ±H¾à/”di.b1‘¤‹Uù‚/ìß§ÅPú h¶w°L%vûþúÅb‘²4‹ëêqýÝ»þñâÜUཻºx÷þò—7¶öñ< ½×o~zýîâPdêýòáýÅõ—?¿³~øpe ¿^\‹ØûÛ‡Ÿ/Îÿyýç×/‚…/Xš¨…L8K’d0‘&‹Æ,nÆÅ Mþ¸Æ¯±âÝeÈ®v<ÉE(YœÄLmŒ]ܺ1ë2oW¶¶Õ«Ozm€!Á¯­KÓmòjmoê—#øaJSáHæÖ4ue° &SûôÄ…X~Ë'Åæœ'žY×#\1ûýëyxº©L놊vCqØUàÃ眥Jí8Bv@ËR¶’·øUž¶UÛy[·yG+@2f }µò‰Gÿ`ƈfìòº‚ÁDxÝFwXJ½KK8«2[/ZSÜXbeLFÒÆeßÿ6««ï±5¦„»ÇdWƒlø±±_}«óB/ WÅ ºÛà)õÉ­Ê0ö.+KZÕU×è¶³µaÈRW'ft²k_Â<òr\_’E"¼ªv„š¹ÖUþÅd¶­Û˜RwùJÅÃ9çÜ£1”×è×H}`¼éœ¸@£lHEÛϦÎÖÆßâK¨Aª ´2Ëopêc·²êl3Õê¾ËQˆB‚žÎVêON÷K§E~ã(z t]áHF·0S¬t‹Ø¥È—FŸG¿+~I ­ÍïÕ¹µ©L£á'a„^Úi aÃ4eßi§½ÔyŪ.—ye›^")yÕE{Z£ CÃB+£]¹Y¤²`ÑÛ¢î†r¦;íº€ÚöÍáÏîÑ)aã.fíÍdî;SeÔÄ ¬u+‡º²ûû¼ílìƒØ>çKç(*÷cÒøóXZ÷€¡}‡-ü0X©§B7™TŠcÈŽ¦0„O&ˆ(·ýÕ×F‡½Løƒïmàûûw¼ß퇜qÿÛ눧ëøÚlì_¿áü^T`——ÐàÒÀY^Êç§&P2 ©X ùi{5…õ-‡ ¤íZuV DÃ85`*ŸCt6x,º€%1Ÿ]tBðÁß„G>›FÑÒjFÑ7bVÙÝhœ(÷v4—ˆY¦óØØ›ºÜöã{Ànê?3a:Š™â‘³µh>§G±N~<78Xåü:b/òëÿ’O™Œ%†-°s–™jåªVMs«OðÈa€¯b€}æq›á³¢<žM,3sË@…Ù(J@M¤Ah媺Yæ òB°( …ÐZdTS»S ‚÷È) ÒŒ±Ÿ¶¥…ôzy •þ.c*qð* a)b‰»yI±£¹¤„¯œYà"zL•EDÚ-‚œy‘ÄÑ7†ñ!¼Ú/àLn}m$'ÂY×"Úª6tÆ:[åÎ9GvÃójUôÙ)ÁY‚q­:ì»õS[‰N¯^žÞ6²™qÛÖņ èûÀÏ ð|ržy‰!Ú£PÆÊೃÏ2ÚùAhØ¥Û’3ðªsº;&ÜÚ•5£ŠM6S‘Œ³pjš¯¢CÑ´eØÊe²Ða%·ÚŠšò䎒™Û\Ÿ<€Çœ :C„,о EÉ'˜•ω¢\~ßË>zà†è™ÊùRxÇ>LÃÙÜ>MásHá-O+m¿ÚPUà•‰Õ’ u˜‹BAÝ€ wbQAâÌ ÙP¨FBÞ ¶ õU]œº±èK§k…^šb<ð­­{R»©÷%H £¶ X(gj©€=v»š†ô€bA<\»¢i\êN79žLÛ!rØE>a>‰¢AÕ,V¦žÓÊÜE†«f¸7xänA¦#dXõÍîò’RdãÙüÙí³¨ïàÐ81Ï~*fÊ“Àðà¼ìó¢óóÊ]é'»Þ˜Ðj²¨Ã!áÈŠhÈÒŽè GÆK+ünt5Gü𔜠׸”oó‘%¸Ã–B³†L:`N“rCÒ0šGi¸—ÇÅž¨éÒŽdž²€Npû25Íb*X\J© !žtS ÍxÀUNþ0;öÿStÉ’<ëÉqG‘Í2¼:÷S¼H'/Ħ_¿<÷#‘x_ìó‚ÚÒ1cóòÔ[‚)¦à~›¯Kçè,9‘N0+‹çû Mþ¿d‡l}îuÕåƒi ’Ä‹W”äDçx(À0•úü¹8‘€ s)þ×EB Ãá”csUPLȹ#ÉhBéð Àd9]cQ£^ãC—ÎVÐ\§:µ/îvŠë#1O¹SÐ,2zÎiïÇŸ=ª5}U!ÊšÞßÉ<[þš’¾À—&ö³÷j”M€¸‚ìw8!Ó« ·½»¨ðÃTû0ËК'¯>a§ñ]ßÑ“#›#¾3Àmc3ÇP®R¥;`bÊÇçËžà³Vj_ÿáoì;ÿÑg;˜"E°ÿ°1Þ˜ÖÖðÍ ¾åIé¡R¾Ç§PT¨‹Oö= RØ’¹§&‡ªÿ*D³ÖTî™ÅÛ!Ùò^¯þÒK§Œi6<TÊË‹"×¥%üJ/ω"ød§%bÐÂôo|Œx´Ìg_†Ô뻢^^ñʴƾŒA° °Þ·æÖõ–ÞMnp*¯Kú­ùíήλޟè¿ËvuŶ´ |™[?=ÿó˜%±Â £WO™P$ßò ešpLŽ{düÿ_Ýendstream endobj 22 0 obj 2867 endobj 9 0 obj << /Type /Page /Contents 21 0 R /Resources 20 0 R /MediaBox [0 0 611.998 791.997] /Parent 29 0 R >> endobj 1 0 obj << /Type /Encoding /Differences [ 24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde 39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright /minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron /Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot /.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine 188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] >> endobj 2 0 obj << /Type /Font /Subtype /Type1 /Name /ZaDb /BaseFont /ZapfDingbats >> endobj 3 0 obj << /Type /Font /Subtype /Type1 /Name /Helv /BaseFont /Helvetica /Encoding 1 0 R >> endobj 4 0 obj << /Fields [] /DR << /Font << /ZaDb 2 0 R /Helv 3 0 R >> >> /DA (/Helv 10 Tf 0 g ) /NeedAppearances true >> endobj 19 0 obj << /D [9 0 R /XYZ 54.992 736.389 null] >> endobj 11 0 obj << /D [9 0 R /XYZ 54.992 711.482 null] >> endobj 5 0 obj << /D [9 0 R /XYZ 54.992 711.482 null] >> endobj 12 0 obj << /D [9 0 R /XYZ 54.992 657.34 null] >> endobj 13 0 obj << /D [9 0 R /XYZ 54.992 436.382 null] >> endobj 14 0 obj << /D [9 0 R /XYZ 54.992 339.327 null] >> endobj 15 0 obj << /D [9 0 R /XYZ 54.992 190.981 null] >> endobj 16 0 obj << /D [9 0 R /XYZ 305.899 505.734 null] >> endobj 17 0 obj << /D [9 0 R /XYZ 305.899 419.704 null] >> endobj 18 0 obj << /D [9 0 R /XYZ 305.899 277.102 null] >> endobj 20 0 obj << /Font << /F43 23 0 R /F44 24 0 R /F45 25 0 R /F46 26 0 R /F47 24 0 R /F48 27 0 R /F14 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 28 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 127 /Widths 30 0 R /BaseFont 36 0 R /FontDescriptor 37 0 R >> endobj 30 0 obj [ 778 278 778 500 778 500 778 778 778 778 778 778 778 1000 500 500 778 778 778 778 778 778 778 778 778 778 778 778 1000 1000 778 778 1000 1000 500 500 1000 1000 1000 778 1000 1000 611 611 1000 1000 1000 778 275 1000 667 667 889 889 0 0 556 556 667 500 722 722 778 778 611 798 657 527 771 528 719 595 844 544 678 762 690 1201 820 796 696 817 847 606 545 626 613 988 713 668 725 667 667 667 667 667 611 611 444 444 444 444 500 500 389 389 278 500 500 611 500 278 833 750 833 417 667 667 778 778 444 444 444 611 778 778 778 778 ] endobj 31 0 obj << /Length 32 0 R /Length1 33 0 R /Length2 34 0 R /Length3 35 0 R >> stream %!PS-AdobeFont-1.1: CMSY10 1.0 %%CreationDate: 1991 Aug 15 07:20:57 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.0) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMSY10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle -14.035 def /isFixedPitch false def end readonly def /FontName /PAAAAA+CMSY10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 15 /bullet put readonly def /FontBBox{-29 -960 1116 775}readonly def /UniqueID 5000820 def currentdict end currentfile eexec ÙÖoc;„j—¶†©~E£Ðª/ ùÈ­éÙÀX¸~›id}S5žQ!gt¤ê¡âµŽÃkÑJc;•r´NŒ^ô¢¬µŠ ¦X€5¿.ØSyƒŠ– þ+'êIÃqV˜œ…â:¿r㚉#,Ùô#È ždèBZ£¾÷ÞÖ *R’*"7Ù¨ÝyÝçÓò¸—Ç=cîÍÚLIPsFŠ'Ñf> bôaöä ]fvÑÑ+QæAÁÔèâwdüOŒ¿[xìˆ"‡%ñÄS¦xõŠ~{×ÊpÒˆë¡õ|O ¿BÅÝÐÄÇâ/€G¾LÈã3hûÈ+N–g0Þ3²æ¸ËjäU±¯1‡ÿè¥~ø¦akœ·”Dìzq§»=÷U}.K¶˜Y碌à ֻ1?ÔÙCùŸ NÌŠ2Muµö–¸hŽë/åí4ÌÖÐG¤ã€m&v¨ˆ•ü.žðd¯ËÄ)%\‰éо óÀ.¯ušáÿ «39:ÈÒ8š*v††<¬Tt«ó­*‚ ‘Žé´nÒ¶©0÷G‰àÖ,ÙíäƒêÚ@±Cf’½Èêe6Uñ@rºÊÆA,Õw“ÔØ$z õŒmNêM2&ÿS¦…–ƒ@¡ù àÀ>žðÎØö€Þ¦Ð]/¾}’éãpŒùÛÌ2ò…°ÁV&dÑþg#Uí…§IÀ’!ÓzˆðFèó[ +´2C?lÍ#‰Ü"¶³¾UêcÍ_™W£cóýž¤ùƒ9ú0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark endstream endobj 32 0 obj 1898 endobj 33 0 obj 772 endobj 34 0 obj 594 endobj 35 0 obj 532 endobj 36 0 obj /PAAAAA+CMSY10 endobj 37 0 obj << /Ascent 750 /CapHeight 683 /Descent 0 /FontName 36 0 R /ItalicAngle -14 /StemV 85 /XHeight 431 /FontBBox [ -29 -960 1116 775 ] /Flags 4 /CharSet (/bullet) /FontFile 31 0 R >> endobj 27 0 obj << /Type /Font /Subtype /Type1 /FirstChar 0 /LastChar 127 /Widths 38 0 R /BaseFont 44 0 R /FontDescriptor 45 0 R >> endobj 38 0 obj [ 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 ] endobj 39 0 obj << /Length 40 0 R /Length1 41 0 R /Length2 42 0 R /Length3 43 0 R >> stream %!PS-AdobeFont-1.1: CMTT10 1.00B %%CreationDate: 1992 Apr 26 10:42:42 % Copyright (C) 1997 American Mathematical Society. All Rights Reserved. 11 dict begin /FontInfo 7 dict dup begin /version (1.00B) readonly def /Notice (Copyright (C) 1997 American Mathematical Society. All Rights Reserved) readonly def /FullName (CMTT10) readonly def /FamilyName (Computer Modern) readonly def /Weight (Medium) readonly def /ItalicAngle 0 def /isFixedPitch true def end readonly def /FontName /QIQTAA+CMTT10 def /PaintType 0 def /FontType 1 def /FontMatrix [0.001 0 0 0.001 0 0] readonly def /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for dup 46 /period put dup 101 /e put dup 105 /i 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 115 /s put dup 116 /t put dup 119 /w put readonly def /FontBBox{-4 -235 731 800}readonly def /UniqueID 5000832 def currentdict end currentfile eexec ÙÖoc;„j—¶†©~E£Ðª*Bg·N³ÀÓ½ ƒØ‘l¦ÊKq*Þ²Xú«šææwüsм|QÍFïq˜Õþæv`æšz¹XòšMyåp"÷ƒë»¶Ôôì5OÒÞË©”Y¤ÅðÆë¡P(DTçÜ!Á[v´Á›„67XFšlU‡…²&3!R˜q©ˆ4‡Ýw”’Ýσ~j‡¸+Ûño¼uú£ “þ_ùc‹‚2BžØ·Ïj=‡š-8Ý\DgùÝŒ] ³¦¿/%b›®Á™®‹ÔºnÙ»÷Ú¿ÐáSº±ÁyÔüâ b*ÍçÇL(Ð9sWí«F Rë:E·¬Mks­ƒH…02§Eô”?›Oíe+ƒZ¤—'¨´zÿK΃µ¶…–оi‚·f Ë<àÂ,¬ÝE“òDÁNìZ|JÄ#’ø¼BWþ¯3ô¿ê‘ÿÏ—MÖìp¢ÄÁäó(¡ë%ä5%ûÀ~(Ì5öBk}Aêj „Ýc'S•¥ªéáÈ-8ŸÑ*!èi™yž$©”G.¡®w g ¾ ªÒJ0Ùn¥r û;Òà¬Á¡ Kèr^×ã©o™x¼7p4Ù= C‘åyÃOùü#yËŸ[¾©â4éê¨9'nÀÙ*¹xÁxÛ/J}û¥oÖ¯†pë6OÞÊû¯e}hà1‘W6Ϋª‹¥À¬%(ƒi]I½‰«ïèiš ãí…´ŠË""žb3™É=çÙ5sJÚÚzbÁÔJÕ>£[Wåеü H ä2"ÛŽüÕÓùº0O¨y9.à¼Àá¦t³¡ü:=×$E€Çª Æ]t¥þoŒ¿`% Ì'EK¿—ÊKœƒ¥fr•‡RíK^yá†`vO^†ðžúŸv…òõ~ÈZwR‡³ iÞNMWçÐ3HS¢p+§T,q!s0Ï(عÆ;U–©´+3çÙ"”J8q3ƒÓdŠJñ`£°Èó7›¤7+åkX©Ö»øvšuGga懨ÀOü|?Ja \´âL‚p¢©|–äj¸ ž5ú Õ¬õÎÐò–hE·…ÎRý5’ÙÊ} Ëd˜߀˜Ø?eu6°¾æ¬sÔjDh*ï/Ó"„qJêrƨý«Wxíë #‹˜1™]¾Õ.²kKy;‰¥ö"%oÚ×ÓÜó(UÛY’Oâý![xµÔéíá;å–oÜÿ_*íAˆ*O˵c¬¨TtEîQ ã®&…Ä+KÔŒ PJ>è–»—¦CÔç¬êy–_Ùò–¥¿5žÔXKåÓà" ÉðÛÙè¨0¾Šá,pö–r0Æáý ÇBZo•¼3ë ¿ijŽ>žrÌ:ÅÔ«vÃÔÊö0…ùð¨ÓààIÄ7vç qŸtÀ@©'*ST‡g¶‚“8Eô.ÞZÚQpì׊Pæ%²äxž^òaé&(-X–%¯O¨ÀfµCmT¹sŸCJzª´Zø×¤…4¥k^H… J=o¸áì9vM¹ÓLg'ªÏ!ï¬Txå}á’¥©ô–M ì©F Ä{è'óãçtV ¾2‰A´NX§ªèã8 ÁFÓ]E­˜Ï ’{³æb&‘bfo—_ø%p–T1†Ž}ãÄ*‡ÏêÚ¢ÍUªëO˜4WÍ^êtÔ6U¶:05:aµ³¼ƒ"ª™¢0~Õr¼±n:ï%g@€†A—É e®`Š„OÚ€j’|Y¥€}#xH®ÎŠÍR~@äpaAY¸<î ßZŽ.#0ìȼ. ¿ Dk¸Q6Mç¶ßgDÈ›ƒH¿hr§øtàm”¼l)!|=îÎ~ÜtWPAß¾­âXx›ÔÉ®'é[ÒöY"£fý6S2P)õQ1åÑþÝùDõ¯¬Àl¸œ;†ž;æS¨z úý®$Ì¢!Áª)Q\·Ðdí’ ¤–D}N\½ip, ¼ª×ëÌâ‘:2Ô2N”÷ì^x"¹À6¶§õÏ?à_Oki³¦Ö§@’Ó2|•[¢Î(±ˆ_cô6ºw¨Lé*Üð^ÈÍû,&l»ýì¢!üàÉ+ŽÓÆU+¢.¯>êAZÄœ‚¸öÐXÈËYêÂVχ®ª% ðCšNí+´7an;H#¤áe2{f3zúU§IÝÁ9ØãxaÆ]X¥7ôW^¤^Ú.Øüø=Å…SÏ¡ p†Ý¬@ºÀAýäØÎµr$4í±ƒäq^š®§Ò‚’òfÞŒö¸‘]¾ÌøòZ^¨óX˹}ðù‹ãh¹©rÐÔl%ŽHb–÷% ð¢½møæ•„{¡ó‰nþ±I(ZR¼oèzV‹…TQu;Úei}ˆ%#{½>q¢[’yUˆ¥ L"'¹ä„ˆH%WÆýAóà^çí¹~-iƒÃØ,Ÿ–S&5Ü.ØéœSæØð³»§cL3Í &Ík§ 2:0wCÕ­‹ug×måxºÇ à$Šë–²ñ5_kðÐ-Ö9 ®‚\ˆWø4ȸløLSmD[ønLÉñyÂâ>Às Y€h¢;‹¯ßoIî˜ÆÌ½ÂË͵Eâ9ˆòC¯51ÃÏx} ‘¢ª‹Ô†šÔm>…ïžêƧð:#R<åæ6ãÒê•ù*KdqüèûqMO¨òE¨ÙXy…¨G}Ù-ú ^>ÝvTv€ ¯„æÃnÕ2à DH“›nÝaӇǡ%ña[ÌÀ•oÛÒ¶›„~36|ÂúªÃ³®Ä€üë8bšLž Ã/†qaþ»¤v?t ‡u=5™Â÷ª: £‹#žU†ó€Ý÷é’½@¡QÍSX®½;,E (qÁ'6aŽø›-̸u¸Æï:[+Ý9Ž<¶µÞMÝ Œ–Ø_×8…[Zÿ64'çnR'”ëÕS&s§ÍS*[×8d )›_âöÄhR¤¹‹g£º¼B_¿â¯¢áM-é4Õoy€3Íó¶‰yPò½gôcÄÖÿ»îûª[Héõ—ŽÉø+ò"’›>w_¹Ð_¸K¿Sÿ(Ó‹VUó€æìoº0tco7]ñ0À›˜e·Ã¦uŽò Å—Ü´_e¦i7&â>‘¥í5)ù©CE&œRE4ÂÏH£6É‹” õèð«4e[¿Üb¬¢ï'LÇÔDøñ|€T.ËVæÒ¯.£>)kÈ.›Íœúò*ÒñÇôóÆl죆Åë:8ò_¾3ǶI‘mއɒ“³“\wÊùâmcÐú:6#…!°À³i€ª%ž‡ 0‰NÔü_¿¥³À~šÜ¸ä.î@¨€KdÐw(E€¼`©a–0rÍ\]´@ ©ÑÒ};Ø¿<Ïã&Ý 0“íæÁ¼—×_f2M;×T…F5áØr:¸Ž ]1ÈÈD%[ê`f˜·Ç4Éì~*Ýë½v¿ñžô¢å[ö)õưðyÂâïpór³ÝU¾G—zcä}öKAGëäHl$©áäÁÜU—ãѱôÓâ}¡[¸ŽµæìB:vDöJé˜kÐ=kbÒqêÞç[~׿xeìnî/Ïš©Wá5ž4Õ†Q‰Ñù‰½Æ›÷ˆ ÛZ“ ”D÷ÀM’µU¿#èܧKú6†ÞVd]í~Sk˜BL-y.FŽ+ö(Wfê»Ø-Efʸqö 1êT÷CØó˜äûrþ€VÔÚ’[œõP€Xe¬n!o[ôLZòÈidÍù)zTjá9¸†ƒX}Ab$Lxì3í©P2?Œ6ÔœÅènèÚõPgV' Üu½>‚ êÞüö§!Rä6ƒ2ÍŒôššè¿žHt7Û:¢ø ªNh½$«ï5’b]›#Ùx†‡Â 2IycP(aó™û.Q/WM˜aÓa¼ä­{z˜$lMw};âOÍaÿ|ê‘…’éœQ·­„ãÒ+hËo'©uJ«…ŠˆÓ=_«$ôLa8Ž{F^§Jò‘MqwN,mö‡h‚¨ûBðÎ ,ï^…i®6v®´ÍÖE\øŸÖUEµŽ+ðЧZÚAä÷.QõÛ ûÕù¨[ö¿ôØÂÖ€·†£Õ±ÿû”Ë/Ëó •–ƒÒÌ?阹Z»"÷hФAHuša4†¯ß9 "øòìeªÃPÏ:ø…Âóô{ Ls"5uÔë.Ì î/ ö„ŒíÕQÒåœZÒ°§žx|^î§d'C­Ös»'ê¸dÍNš¼B@#YxÀÑ}z4î#Dœxëšè›êÙ.ÍÅ çOKã`´ýÑ‘Ë=Ò‚ëí{ÂÁ´˜]„X5žœÊ*CäÖb\a+DÚPˆòE_eн,í81ŠÚŸIcÀiZîTK umKq4yŠŸárùhƒ"TR5íeßz¥Rõô‚™{õ/Ã6*†àb8/ks»}ÛWxpC7*C¤Ýå¬ 2oñÛÏ•‹˜Ãì]iq’0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark endstream endobj 40 0 obj 5052 endobj 41 0 obj 932 endobj 42 0 obj 3588 endobj 43 0 obj 532 endobj 44 0 obj /QIQTAA+CMTT10 endobj 45 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName 44 0 R /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [ -4 -235 731 800 ] /Flags 4 /CharSet (/period/e/i/l/m/n/o/p/q/s/t/w) /FontFile 39 0 R >> endobj 46 0 obj << /Type /Encoding /Differences [ 0/.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl 22/.notdef 30/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 130/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE 141/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe 157/.notdef 159/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 26 0 obj << /Type /Font /Subtype /Type1 /Encoding 46 0 R /FirstChar 1 /LastChar 255 /Widths 47 0 R /BaseFont 53 0 R /FontDescriptor 54 0 R >> endobj 47 0 obj [ 250 605 608 167 380 611 291 313 333 0 333 606 0 667 500 333 287 0 0 0 0 0 0 0 0 0 0 0 0 333 208 250 278 371 500 500 840 778 278 333 333 389 606 250 333 250 606 500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444 747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786 604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500 278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546 601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 0 0 0 278 500 500 1000 500 500 333 1144 525 331 998 0 0 0 0 0 0 500 500 606 500 1000 333 979 424 331 827 0 0 667 0 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333 400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444 778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337 774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556 500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287 546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556 ] endobj 48 0 obj << /Length 49 0 R /Length1 50 0 R /Length2 51 0 R /Length3 52 0 R >> stream %!PS-AdobeFont-1.0: URWPalladioL-Roma 1.05 %%CreationDate: Wed Dec 22 1999 % Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development % (URW)++,Copyright 1999 by (URW)++ Design & Development % See the file PUBLIC (Aladdin Free Public License) for license conditions. % As a special exception, permission is granted to include this font % program in a Postscript or PDF file that consists of a document that % contains text to be displayed or printed using this font, regardless % of the conditions or license applying to the document itself. 12 dict begin /FontInfo 10 dict dup begin /version (1.05) readonly def /Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file PUBLIC (Aladdin Free Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def /Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def /FullName (URW Palladio L Roman) readonly def /FamilyName (URW Palladio L) readonly def /Weight (Roman) readonly def /ItalicAngle 0.0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /FontName /XSEYTV+URWPalladioL-Roma def /PaintType 0 def /WMode 0 def /FontBBox {-166 -283 1021 943} readonly def /FontType 1 def /FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def /Encoding StandardEncoding def /UniqueID 5021141 def currentdict end currentfile eexec ÙÖoc;„j˜›™t°ŸÆÌD[ÂÀ1Æ…p§³T¤¢€®o¿˜ˆà9«`ü¯….´Î:þ¹yÕêpýäJ*åÈÀl'¿–eî¡}#)Á¢Ý&»7+å‚/^§ ™ëWŒ{ïÔLßZ60VåáÌQR^¦üλ3rï÷)€#v¢€$öp~c—²¼´°£êë&“è÷ö'ÄÉÇÆÅ¿ñÁä+ž %;v &‹€qž?ZUªE¬·V¸â¿[7b~FÚýJOt…›µ÷×ÇǪ–îjÉ<Ê‚›þ1ã-YÆÞ±¿;lÌ\<’–܆ЇðжhöVÍØŽ¸®ÝúGðÿYŽxÉxßøö`W5ÉkHZòàž>1€SéRé­@7¿ÇîùËý{ÃWFV[~ûòAc—“®5r „1GúÛ’Ÿ½$ÈŠ8/¿yUM\T4U3°þm"˜0G xTxÚÕ>|a›‘!Zà%øaDüšÚD`5¸ëœ=iºtjÐ̪äÙß?HÒ)à*#û#öµqÝȲÏpC­kÙ*,BÊí”ùqODãÎ1û¯# dª*Öå7Ž(SŸ 2:Uå‹§VJ@‹,#r¤#ÚjnTí*ûøúß§[ üd]¦ì1%b¹ö­”`‡nïË#iÊ0U‚S?<GÕ¢ï—aŸÂÇ€¼ÙT ‚H6Ÿý«RI/ ÃÈàÈswÚl!ñÞBœª“˜w‡o„`_g…µ­ê—2òï6’¯S^ïè—_”dRr!(£þȱ¼ënW¸5 µÄÝi6ÛŒÞö䛉DÊ1ÅŸ‡Í?íXñ-šÆÜ²×[H´0Æ}·i´t^¥B3ÍýV»*– šƒýÁ=J¤®'ÞÙ}%“öý¥öGìz(™¬˜½ˆy¦£H&X2™L;­€áÑ"‘Ë’C·€D:v ž'èÜÜØþ;á}àBGs<+×#œ‡iBX4eYˆ¯Œ­˜Bø¡ã»Ò®3H½ÉŸâíVCìM‡‡uî·cšÍ€ïOT+»ÀŸ˜ø¹‰Æ‘¿8ÎB9± šk†GSâÀ¼Ë >Ÿaþ„ß,b†å¿âàGýVЉ³‡,‡÷ž¼©Ï$r„ˆçÄ!åÎiÚÑ#¸NlØ\†ÇD5¿ÊâŒ+\­WÙ›Dsm@…µ3klmœé”Ò³3ôp­2Ó¼(º-i›zæ+hœÕ âÔXP¼Ò840Þܢ-ŸÊÍËYÀé`÷ÜžÄ ¦‘OŸ·•´Õªú¡5Á}]dÍ„Š2Ç\…lÉÉO$¶É¯…KƒwxÀ°´Æ¤ÙÀZÞiåÀF—‡Qñ*Ðc§@Ó+—&°‚dS=S#~Ô*½ß4RN½³´²1nvÉ4¸ƒX/Ù†¼%º­—q÷=mbv]Ó§UÑù^=cÄÓ»˜; ÎÅÈhDcà´½;Ó~¦Ó7ªG ŒZ@±¶™†~±}ºgè¾D:ÈÀôIÆùþzcPïüùFÆÚÛÂAÙº×ãÕÐ8TQÝzyßë§F4»fj㇠姷\÷†2m9«W¿DË]r½’æÌÅ?ËÈýCZÕÂ6k†o—vÔðqÆi—ùcu£õGƒXNãìÑÒƒ°†°ßü@ìvR›;%¦ÓŒ´³B±Hª“¨«ÝLJV…Û0HþLŒCJhEvä-«â0ô±’’`ŒÙ*°á+­…Õܱ›DrI¾’hTää“î{sÕr=‘Ã%Çj·5Š!)¾+2Zü(~œ$!Á¿Áß-DÅl®Ø-è2Xe§›:>Ñj¤-aYqÉÒÄÈ"»¹#È‹”ãÈŽM¤hù#ÏžwžDaåÀ#Á7Çãƒä»NN,2ØßÜM¬"R†Í¨8eYåƒó¨d@ž´$•ÑOùÚƒ1°ß ›AG†Øѓ좤šœÌIÜ%_ >*9!1û–ÁL9ã–Ã4à%P_ŸYÝrvgÛHjwrYˆâÚEd…1Ö–îAÒÐÖˆUNú/2=ýHylª´¿Sö)®Š[‘/Í0à£mhV&S –'vûï¹ò‘;E²¡]ª‚]*¿WVîV´5†òB;QÉD¸Ãù û.E’¹¶h“ºH¿gÑHtû€\ä k·|ÇúCÕ ‹“íE¹îÛTë8º$>6Ùq_uñ$½3[ÃîRa¶Ü­¦Ø³…¬‰OüiGͱD7ýtO”FÌL7æÿI¥ºMŒ¸óJ€ñÞs~ªh7y«y?â`j³ïïo€ù<(Öf÷þqªçºÊÙ W)ènM>™¼À¦ãlQr…Ÿ©5¾SÛ…!¶fô‰‘ÃSù‰÷ñ+©"üXTKq=?àGÇ,»©ŒhÁ·+dÝ)–Í±O¨Ìhݵ–Ð*Æhàä9n»ÂÞã ½³¨hêéO½„ räZ\'­Qi›édá¢AXÂøïæëó\œhz0´íòÌŽ]õ½ežÑP¤yWI¬ü³úC„%Íø­û‚k+$3ʉrˆ‹›îЙ³˜31mä4ùº¦eüó%¤ÝìÓ(qO0¶– Éû›.êvKzàŽ`¿S¯ŒÑP(Õ@ƒý…x¶×³„Ä ´32EcKn•%hÎ!}ì"ng3 Ŷ)”¯gÿ¹†æü:¨1—ã·ØÑ¶à] .Èù©@wyšW¸”“’Ö\³aµ¥™ü²;¿``–h1^’bÁDVæàE…´ÚTê‰)²&¸{æ¥dJY¶úü0ú$Jh16Že;Æ1,—Æ|]Š‡ÏŠß^¢>rꨨ–zéYpåîtDÑ„V±÷úû\  «›$üŽÒwŸY¤Àñ%YÒNmàÈ!@ç£<ƒŽQ´U,÷5@ÊÌO:¿6 °€º›ñùZ6äpªd»õÆ›`OÖ_™GÍrÂÀ6šwô™n–Ðäá+|p¼}ÓõÜ3z³B¾í=îÆ5¿ÇvA]6S yìÖ¢xöI3 éŒHìRt— gA`?&-›u bñÃXë-)z©<·ÍÛ‘DzÝVûv& 6ÛÒJŽÜXCÅ!4j‡¢‘éîÁ:ß]RI¬ BõÆDí?Yü*xŽÛ­Y!–ƒºb¥,õÊV(œ¨½eÜêì× œípëÃ~Q©F’Þq(óq3Žaï–ལ?ÌÍyZè=`è)ÌeàÀ­ÜyÓÍ7ÎŽ>r´WÓñAh.,Uã«3²ó'„+|íß>’!¥¼í…ïLS£Éƒ…=é”íÑ]˜›£§"H¡ˆñ¾²7°8Ïù;d°æ?~°0ÒÄÀm£^\¾®ìçu®”h{ 4Ô;š$õY[ëB'?=v–·õ´às®% ¥V0‹FèŽ1ÛòGѪ ê)N§³¶¾bx®²‡ü(Žæszò"_xøró®BÙaræø±•H¬ÎÅ›W1…²—6^¶PÑœçèŸéfHœ(p5’S0ìr0‡+âÒùܤ„9¡bžÈÝÄdÞ¸ÈQ RH½+P”Hà+Œ»?ÑââÆäú¤iõö+ù±U+½¡ž¾ž-œ›× Ïø@tóPõ}wUFµ$Ôå\5€[y&O$0 ªÉOÿÞ[ò>WN[¶ á/øÉ[¤Åˆl;nº1Ý=“Õ³Í`ÇŽ}CÜ×÷Z,cÄ•Ïð¯S·ŸõD ¥œµSkbŒùåDv´Í^6A7+Ú—,áf?íª‚·[žžœâÓñ¨Žg™"Nc?ú ÄÓ»ØÿÉÿ18Ð{¨ð{ËŸCÝ NÛ½!cкÁöÁ¶F2²ý ¼•=‚ê+·òü¨!ÿñÃ1çiŸnfi,¾¤@xNOPs×2‰¢¨¦µgígÞŽ[ÞE’¥Êæ3Úêø‡ãa뀡ÀK""ÉãåÁ”˜{q3+¬hŒŒí—~‹ZÙ(ôFEFâêZ>J¡Rå@!wP¶Ü«aí§°Ö.›r¦{¤²UHháËœ5‘ÝL)„Ö`Šß†µøÚΖ ª)[Âú~ϕϟ‰·ØÐ+Á^C̪PÑj…Èü¹z·¥ë|P÷,ì¦J7¬WNæ)¶ rà”‰›Í/mÅ6óâýÚg š‘ÞÕýÆÎiÁŒjÜU_ÉTŸ±àD½£· ɶ°6xv=)>\¶]Åè!f…!’+¥D“ŽO­0-…´~­ïHߊ—üÜKS{ã ½žbo3§Û³Cö¡«°ÙÇ(kÞ„FŒ1ä@ÆõÞîH;º³Ç__Ö¯£àx!$4~ç6Ë4Ä^£Áº:Ù!SkdÊf…®m>•ý;^ÕE[2ÈÒÀ‹ÿD.î{äæ ÁÞŒk¤m^¡±’)5Ñp^~ Ñwj#Ñÿ›Á?`Ù8)/IµÄšÍØ úõý-òÈ'K(uÎ>î…· Œ€…K¢—ÖF Hi˜ªÂ+LZ'DçZ²òÜäùyvwpûUjÞ}7`/ëA"ìû|0ñ!qßÀíâÇûO/ŒÜ ÁÕõV¹Êæ~ÈÀA‚õE Ñx Ÿ«4œjólD¶±g¸ ­‚»¤ïŒyOw½"üÚ·X#ŽÓ?Œ[CìžfæE(U¢CvÐ"ûä#ªo}]­³Ø&çw¡#Þ¾Ÿf78¶ÂÕr×3_U\ɤ¥d[Gj¢SÇmFJX‘÷øµöΪAºT+‡ìwµ³/3Õ8 ÛPÕúƒ»Ç%¨D¼î¨¸g-iÄÉnÓ¢Äç¾i/tÍ|ƒO:×½”Ý1q©â–•j›«Y…Ôè“¥pÃxm3rº‘‘¢´*,ÂûÓ{Ó†MþÅÛñN—ùØ),€""rÐa:V»`ã«pûñ¤^Ú\l/D¿ƒ.MÔq‘ 7œGøîÜ üœ'ó¶y‹}P‹ÏgCÃc!ç?ŽeF–ùKuáð²Óÿˆ®Æx²V*¬ˆ±/ù¨Úøêî…~pg÷¤b¨Ô´ƒO»\üc³§§C¯áÀ EÞ;M'½Ý*·¸¤FwHŠ­É/y[x²:ã˜ÌüÓ­¶=™X£Gn˜a_Åαa@Õùh‘‹äds¼F¯€5Yþ¢ ‚‡œ¾·‚SæøúzM=ÄU “ܵ>zK7…ƒ²5"'ðþF¦¢6¿Ðx-'"Û‰Tª?NdòaîÃÔÿ‡yéhîz2“§6 Í‹ø¢Áì+iqœíC\¤y®ËÊ./ŽeÙ·7aÜF«6ÉÛ[ru ²ͱèKÚª}ÿ%l"zŇaM3me'÷…!>*艃8Nø]ïD'›M&‰–:ÉH~Šðûü1P 7(“¿©Ç#3eêÒ®Z&Ꟛ-’F6‰æðº/>.{ÿS»ÀMFr7¦ð§Ñ4:íâ!©k=VÃ~UÉM(¾ãß¶pµÄÏ'ÞÎLzH÷{#ú X6NCv ÚÇ£Ž¬4!‚u%Êñý00ÛRy$¦› õA4 ÕÁX™y<–éngÿaee´M„;‹‘=?¾þ ç5èSnÞ×Ù¯BÀSÀ¯'~~Õg‚´Zô¯Á™šzQP7DŠ@óͼE@$/JT‡v¨"òã3z{­R‰vÓœ­ÿÇ­ƒ‹ ¥‰7ÙH©Ã¸4D¹Jmň15¿ñØÂнÚäºfͰªk§+vt±SÉT=\¡Xí|›ù•À¡Ù>ŒˆË@ f±£K_[ê]EdUu'|°¿ÈREDFEzò‡"¤EŒ»Ñ#¨Iÿ •;.O¸štÝäÛæk Ø´Òp5&"‚sïȟ߀]²>´nŠôŸR2ìÎ(¨%å9DÞ Ë_—¶èRÛ¸Os½ÁnÉ1Lkœyê—Ÿó8²(] žw¢W‹am§ªqri¤èý%ㆪCtúí%§aHÅt¯áE­ú‘ Ÿ (¾9èecn\úuzW’÷†®m9Œà_Ýó† †ŽþMHÝ*D|qî^rVx@ný;ŠÜ… ŸÏ@çè¯%Y»_®?ZÖ:—ÁB‚ƒÇ2,nÔ=Ë Ó6蛪^›» ‡ ;Èç‹sÖ®$ÁQ®è0{…Ad‡ncèã¶;ü´°C•Õ¦B˜R±¦¦Šÿðò>ÿr/mÿ«ó2Ýp*ăæ¢ß(í,TX®Ø_Ø[DVl é§„‡ËÅ`ÌϰO_÷—¿XÅ–µúûë—ÒŽYÒ0Ü`ìÏ͹ç\|ÎöŠ]ŽÙªó¡q¼ttÐé'ïMဠR ªœâ?ÖKGøÚ¡á>Uyв™H»Äiÿ^µ&¾‰žXß‘§½ø'd,Ï(æÙï-¹*r¿Ô/²òQhý¼#‚k¹ØÓ÷Ié9áÔ§­¹ ìþˆlCï­J6‘õ –ãªì’”*àå-œ>¦Þ<çñ³½=ëXAçY§Ê|½­Y·AL„ÇÃijØUdˆûvQyËxú§kýîÕcMù¶þç·¥†ƒ¸ÆøŠ(¿r¶ðwIÔµ8èÒüͦø)3®B³6->å};²û¡]Ýð <±é!šŒ åÐ kq##Ö¤Pi?¨É GíE‹½£?Öºûô´ˆåL¶cm%¬‚¼fåêg!×t7“ëý¼%ôˆ¼8ò""7¸‘„œàBóåHsù¾ØÎ¥ ¶¡*ÂX-ú¬g©òuŸ¹ªGX3èµ[i¸°íàÊö…¢SˆŸˆwàˆµã=Q˹ië)bÜFnôÄgºAÁ )ßúî…¥ÎN@C*0bßa;l™!m%´/¢„4éû}+?¯1‰“‘¦~÷0©ãºOÙGŒ ¯"Ýž€yûó©°ÄZË~ÜÚ[¬q—ò€ZÓEw͆‹_=l­I›ä‡¥•Î*Éš±KSCœÁiË-Õà@’~²NÈùDþ„&XS¤ìjç ‚×…Ùr š‰ ‰‚%xy°¿™N ¨ê4Lt*Æ£BŸÁòð³%^ôÃyQ©h^qG¯YûO­åƒLø £þz1°=A¼ °"VØGýNs³˜yti] yâÕ¢ý=œç-5dÈb]á8·Ò cË©Oµ¢Lf—J´j!Ô ¯XA1H5 ª•³Žÿ2+ÛL§±ñLÀXOíckšÅVäK ËÖĪÓôÓ½lÞXwCˆ3¡yž »”t{ê|'–Ò*(þºÑe^†}Kz¸¥Å¢»tÎ"–4öϹê®yÜøÄ( ?”¢kíZñnñº,]‰»ë­ÈJ~Ä4^–4ÕØ"À K­bÛëÍ7YÉÅkÚbe‹n¹ÍV¥Δ 1“ñ¹äÞ{|¸©«>•1šúT K$õäᨙT·ÆãñuŽækY"¶K5ÁÎ3¤{ðF§ŸÆ¦P`&[IÿCv÷³:·T¦â3sû+IÕ'ü;ÉYF¨RoaE÷2½t+ÐÉÿ™)H¿cs ¾‚`— r¾'$´PË—=Ýð»RO[QFÀ\+ =Tgf1ªqäárá„5 ÎV7hg¥yñâ±¼ûÎA<A·ªâ¯Úa¾±†…=ó´zöô’âFcàÄ»‹eÕÉ5ǹ•‰­©¢jóhdšLÅ‹[GaÀÎðlB#i’}³¿ûH4=—Ýã=Í–}~™×ô]Õ»Û¾˜lŽFÄ)‹â‡èeÿ¾5FôCd_‹/Ѐ¾ë„}Œ¬ÓKi½%¥Ñ¢Ð€!ý„Áó`äÝ`Sl d;ÿð‹Ð7­V¦Ê mÈZsStƒ"Ho™àS äG*œÒȇ£N7a»·„rÐ0Κ?³üK–çVá,jnÛÉLUŠE„?M{2p. düÙ±Â.ùxpm¥ö¶mûW¤Ž¨]¥qBDK²0©QÛù¥G:¹‡Ïö+áä‹ÍÍGÝwëÇâ§Æ&^ý’Ý„Í FÉ„<‡oѤë‰@k<~)Ü×!& RŽ Hë= iÂS'+1T͆·a–ãPI^<ˆ‡Ñu¿ˆ×áøÿ7ÎËñ£ÅInm¤1“Z·Þd{s£/—Ðd¶š {æé_PsÕ‚%B`¢Z6¥¤6|_‹Ìžßƒ7÷ëõ¯2b0ÌØ«XV î$ã` ZO¼Ü$m©’çÂt¶Ù8‹‹X_‹L²AÖßü“‚*Gad˜œÌk¥¡¯„,†µrT&c> \³V1ÏÌlð¦„n|w(qÚŒXꊫkB¬àøK¶çç±»OÉ£sØ5údµgh™[+‡nèà ÎBs¼H¹¶˜TçmTÙÒ¿ç(¿DÁUêEuž~/Bõ6>j²gÖÍbÙóƒƒÕù€…®f3—w÷ø£‘&{£ëÜy-˜¾Þ½'7é ªü?gB…ÅöÂa¹h;"Òùù·Ë?å¡®D²Œá Ëú¨´Ì:–%HÜß?+ÿ´›K7øñw›RA¿Ý]í“-\ Ãh®`rìKÉ –ÃmkàAdžŸtÛBªY=Žu.%y|²5 ºÃ¢PÉ‘¦ÄùøCÆΖÞ‹å1@6šªµcÜ;A+d‰—Óf@C;rÿX° °N½~Of–^$V«ssbfÀÜeëm*+Û-üàG>« £'qÄSu¢02ó¯3á?YOÜlMÚ…Ø(ªÓ »Â¶CöxÆÂ:§cYùÚ¡_˜ÕþNáéXrT†ü‰š4XK?&:å:}†O,žóeâ+0éD¨}â!ü9P5…ëöÿã¡sÄËSÒîEì~ü¥YM B H‹Ø–™TúW³$÷lxçå¥àÎ5i„Ä"¡dƒÊÕ½JT[—OE,Çþ £[•_‚žQ¡¡œþ*6[“ÖHõ­Õ<2±²%óC@—€)ÂØ¿ À^=ŸD¹éÇCçW-ÒJøin°:PäËÔm àá®®°o´ ã%g»Pé3ì¾p¾È=IAÂ…Â*-mo¹ˆÊôÛ×y>¶aœ^¨•D¨”±q?CÖÎê§ùàá¦ÿöŽÄí̶³¶8×øù8Ïi~å®ݸ*Caá¶µ,Ë .^:Žoæ2äKÈ«*²=$¿ñÏNkO9) føxcçŽz|iÁÜ´oŒhߨ7·OÙóäêô!5¼à7Í ™†•2Ô°q;oŒ^c—R/aX¸N¢î8òêX]³VŠÊFÜ8{LN3wW‘'ßLž¿ý´Â†– lF樨œÇ¦Ž²oæÛº. ùeïIóªtm¡f*À· 6J%ôŽÏ4Û@­5ų©E¹1@«V³Ë¨Ï‡'G¥½>¡ó}˜ï >G<4­Æ¾|úù_ÒY[~Zé¾X6­­J©_Ò§àÀ´><|!nn ˜Î“踣w‘Ζ„›sØH4@(­¸OŸ­-,¥`iÞ öÖoÒ"ºvï^bK'‡¿»Ûäâ1°Aékéé…³iÍ Aýj$‹“õOfjë¦kXex¶šøÞEÔP‡§NÞŠàÆZŒHæÐ߸kº°añ°8 àõà fTûú{PèEúŠ>ƒBæ_½ó|†ð¶¶´—Óž‘C_®‡B±xºø·TÇX*Œ wPäÚL¾!·Zu–*õs‘{.ö1(Û;Ð΀Y8' †U”"}{­ÝL½Vèð¹!6ýç ŒFXŧ¸ä!†&&akÅä²D…ÔKSÝýÍ&Ì7CÓµjcþP-YTH -ìËBº‡ºHpûÍõ‹­IúBf BëpC }Çm-âǘ;Šz®‚·çùì^_LGÅÌ/'¿Yaë£:ÝÑIõ¡¨ð8[~s·>`ÕH€ ù2*qï!_Pc¿§[èWÛ}Š-Z}ö2jK´“Ž—Y°À¡Sz)2­²÷Òê-¼4Ya”jßR}Ú:Q*fº”·~aÖ ':ªçjüqõ¬syŒ–hcؼÿ¢W•û'ɱqSu1ÒùðÉ/pH›n.´ï˜Æµé–ÿÎÞs¨¢fbk]€¢ ØD$ª˜ÚŒÈ‰¯©9„žNÌèq-¤±ôrµBc QUTp)æ‘w†@Ê?ªíÄ·ž¦ùr@œVpïš.ƒ‚JÒ‰‡» WúJ¬•Z´3˜{"•2fa ²DT¨ýâå‰% [wº×SNHÀï€á·hO±\r^<û8Ï»ÞAO%58ÅàÐg*—•ß•Zòïý–J¸î×£+zXûu˜Q³°¹Ð&4hUÊÿ‡š¨2Ùdæž|4Þÿ‰F.F<«ý§åÒuLPîËÆ]•Ôöü„ì’Í+âTÈ⮈åúH%0l‰Ò‰ \Tn;ÎxOc>1aúíûZ²oÇü…gæíšÜD¿ûm¯©7Ëø¸ä/Q ›5ˆ¦0ò-òj|jHõ£7“ôOeZÖü@•ÙÑéLÚ­‘<rP¦Ñ „å9K»þiMoµ#J˜}±ª¯5îîL$MiÞ”Ôq"Ø|`—ÇiGyyNx4û(úh³xHA—î3:ì1 ˆÓlPy”ˆV é嫞rÁà†­vÁUÐsHsìóëõˆ-\c+iRG:]"2òÕ$“´ì†°’t´ž€JVâ#;ƒ!p?7¹;Å™½KóEÖÑíð¼ÃüâÅ_ì+$‘Yÿ‘"§ªxSEË“• G—›Zèáð£ê8Uy{„2 ¥Pš-îÅ¿+ Ïc_ü¶•…Uü*ÐîX޵­¥DåÐzë²>Øþv·Vº$ÛQ¢¡‰„ød]5ûËÂó1ü’|uW-s#6ðä΄W6é›y,r¸¾“(Òîþð@­!QÐKá¹÷ÉAx–J©jß–;'#g åý$¥6“ÞW½êÞ…ÒÒ¥¸eŒ5Ø”ÒÐ † _‡Á%A«Ks6<µÊ…WÔ©îÚÜ‹Ì1Ä É}äVœÍq_安ã j«*½<%ÕÉ¢ ­,è‚ 5ÀÃ2"/ÌþÍ>ªkKð4¯sòóÿ4dü"_ÓÔ’2FA‰†tTRò]É´:õák‹°XŠ:Õ«ÿ(Û D^`=Œ¦ Pù)9ÀÎJÖ4{…¯"Ç wï«àßÑ Z…Ò8Ñ=°x³V>âà[õ1 Ðë~hC1™Ô?Ø`í­>@-ëF¾°s½?ƒÂâó}=bW± í"AÙhÏÏóÌ "B½TZkçh+{Ñ÷à;‘AdÛcóZ¶¢ÕYËßä_ãïc‹! 1w+UK 9’üMc.$ðµc’ª;ý'î´XPë‘liÐéû—‘¿óy„J«ÒîsîždØšRþÐè“ôvtsU?X)…ÊtJÃ/ãëpø™Dåú‹ÒCß_ÄÆ‡¦{õ~:‘(êM¦|U€—ødßl.ôpš(¨ >oÑ̓$¸ þ 'hf}FwÐÌd0%>‰A¯îXŠã¹ ûLáÝ¿<8 h¹Í®?;þÀHë #Tó1Ós 1eD41äĉk‹r”ÔôMþî¾°™mî-g&¹D›œrD«<²¥Â}e,AÊþ÷©C”ýQys‡ITÓ6ñÃOŽÂO–Ëik²›c€Êåç]ó;›,‘䲃ŸÒðUéFm.hÕ¹Ÿw™Šû›†ßÝ0ó®R&³ûA]›:Ò5XY9~Ú0w÷!»Ì&Ë´z±%0!:»h’DòHðnoôôé©À¹š ‚8¬BRç.´@ Ê6"S!0šÑ~8¢§FpF.£ 3Œ/LÈÊò$U‹ÐÆ8L*·yh¸®ÊÞkñðnu\v2ym Š\b¥gºI°£MÏy[ÅFOHòɇ}¢àzqíXkŒØÊ„ V¹æ"Ç@h´y‡G™©ýÝ_ÐWí«ÇçùíFv…Ör‡ì„ΖOÏŠäNå,/Ð눋¾ñÖ]/êh!A³pÇ#Íôìž“V ÅÉæ N3n„@e§i9`¤ËÇ~¸£jÒsŠßQ{Ƚñ p8 Î\vÆ×k’íN˜ëðT8¼m_r…ãÑ4Œ‡Ý›N˜YÁ¶Þ„hÔ#tBþTô<VENÃg­2›1´ç¼IÆGîÜfé‹'nÿÐŽ‰éÓæ0œþÖÞý"e¡ÿk°òQì—À¢.ÐmLØ„Ð7µÿ®ò/Õk2ù§Éwìf†›Ü|Ó2ÔúÕ¿?cIQûô„©Rï‰Íâ•ou˜)¨ûYvG…#;„ø¢¨Å]#z7RÃUÖžB„M†1ŸG…$'ŸëÁ@bô„Ò÷1ÉÉ´,!뛤Ž_•Äìß2ò²^¢ûí†îØNåÀ5œ±·tŽ5¾ËÅÔë«Gn*—ÿ_ï‹öafeGŽð$iš&]­ÔãÉöÖ‹.QÛê##èQ’ÕrÈ·Nï¾~P“ê–G^ÝrüÙöM**@³‡Ew?óä2ÔQÇÚîô)yS\éΪí˜"€aõÓ5Ñ[Cs»Uéêy]?gîlß:aŒæ9ž(/½s{Ð…"œ×Æ„vIz÷ù:½•s ëÐTÐ gkF_¨üÁ)µñïYDc˜ówðJÝÄx·øZV©JFżⲂÑC<| W”p« Óxf//ˆ“ˆ§lÁ¼ÏÏ÷ð42ö°bwØÒj̯'"^ü{ñ6ÈìëÚª‘ükÖT®t§ø±MòTωëóaÓÜo:¡ž„Ç>øk ,)Ê1_•¡¨¡4gyÌS-ºÅªÇí?‰ ú¿hÍ*Fõ©[eó3Åi9Ô…&œ—†R\Y%  r)p5¥ÉÕ.ƒÙåÁ`žàãDS×·Oþ$0c[tʈhÝý1¾hy6~l—‡›X¥º<´ƒ‡ÂC¦î£Ì=¥mœö ØÃfìp¢kS¶3€«?T5uµ‚ΖÃRwµ †Ý›µŸ³»9xs)ñ!%V÷u¸|î¾ÈÜ\D'·¤1’hô'7;–¤¨Vd|2@£±^É%sY’õ‰¶&"aQ3Ù#CH„sÞQ±äúKij¢h‘B/$\’m=DÑŠåݳïõøÇüÜWÛµ’{åsm‡nƒj` ¾T |Dd¤í¥²7ü3´‰ICª,:àYí‘ްv¤”—[¡£m˜Ñúa­ŠšÖÇܰ4Ðï]@.–\3"Í*k–xÁfçå±XÀ©tTø,ÑhÓ[RɆs“¹û¼ø±õªNM.ø¨`3Odü qkUš“ùd.,Wш,õóÑ£Gqãgé#ïÜ Á¡ø(²"¸¥hü‘ÇDX“µÇTgeºEYsdÛ°Z¤êÉ×5©êÔÆ èHVú‘ÒÂÖNlµïèçUÖ+ô_7óÓî…“ñ´½-|¿#–Ð%ØJ7{¶•ê¸:„ž´@ÌuIoläÚ»ìäýQ5¹ ÆYSã,ýªÇv DÞ±Ð0A³›Eú̹=ß7cl\Ctø0/¸µÜü.ѹ³V£¼ñ‚ËéV¦wòOþ$ÑÌIcAÄë ‚~­ž•¡¯‰}ÇÓ«`ijè‚r–“9ÙÓóB¬”Ÿ€Î%LÛd'ûÁPwá|·XíjI¹Yy½r·Õð`ѧR¶k5.ÙÕÈ6= ¼I—bZe‡‡Ýpš#š@¾ºðßE]5{»¶*®Vœ§3æÃ“ô€à¹’ј¥W„­„pQ‹µ*‘Ò>v‰¶HÈù*:FhGþ®à®¸.ç–ÊmC>Lñh©ÆŠ½kÄ~EL’1™¼áëÁ ·²´P@ü(«)tˆÞ$ô*ÐÒk®èô4Y9óxÊcUTFþœçæ÷K´E)ŒU{€õeðŽÐmœ3®*ê¦Üð¥Áb8òË ‹#ß"è³"³ŠEc[«]Ÿ³rºŽÎ0Âù;MÌZ¡óeð% Ñ0Q¼MV°­«J1IyŽàëtk#ËRòØ» é9v£(h¾jÕ[BgùìH—º÷Ïr悉Iu&9÷#v–8Ýöb£}¦ˆxüœQb0 é85Jð,)n†”tÖR.BC а™|™Åõ[“å®QKÛL—íå¾›—oÉ7«xD’ì|Vo{Hò©éÌ“”UæÈŠÄÍ@Tu9+K’´%v´‡qG¿œËxùø£vÛ7ô–3Ê[ž_/qfn¬ …Ê—¶´K„ý YäÂ,ÚŒø¸»½ñÎÝ™^½òÓ‰4;¦¹Èwñ,ÿ Ù¹X¤ ”jÝþäM=J´À1ù ö—A€i‚ù—^+¾°5n»õ+g`ƒ‘ægòÕ`s‹F 5¥™Ð>¸=}°=ŠÖ\JŒ¿Ü ˜G| î祠ÕþLZ®Af·×a‹Üb']0²œ±-‚­îñ¡8Èš;fŽ£ü&±ð‘í#"4·Xäg¿|8ê$¦6»®È§9EÇÙ—ÔË­è›Ê²¡m~¬U˜¶Ä9¢é ð}Û|³.ÔV3fÿ¸0˜•ª?l½IñÄãóØ*~rC1ý£ é¼ªâ:ÅÎ<»å¡¡\—FæÂžÌB†JZ¢V³wÄÔ´Ånïù‡,š*3#ËYIn”ßϤœäöݵ£QºWâðw`Ë}É‚:^2:Ì×)í“QGc?bBÛ"3µ ˜‰tâæãÚ©ñ]Ò*.ˆhfgí¦¯$Êöº<2^_ÿÛy ~ö)%‘¼+Ξy%þüêàa…WÙìNªV]}!têósD!Ô;DÖø8±ÉN¡^“=Ï)®MêJ O–ˆ™²?ÔöÜJ@ï•2§(Nc"8$ôn|~è8;nH>MQh70}¸¬ï¶Ééªý°À½ösNÆ(݄͖®¦[™·1ýif㜖 s&²µ_¿5ME°ðÖÝÞ-c`WyŠªiO_œ°ý‹ßtã´Óe=ôŒ{ƒÏ~ \±qoüY߈#UC—=S\|ÍñÜãÙðü–ÌüÔë%6Í;¬œÖ1§-w\‹+üv7SHx›â ¹½Öˆ2VÝ¿Å7\ŒÎ*à@R| … ư²Û4 ' ðÞ9wüÊY«×Î•ŠšõCˆ ñ¦;ŒêT¦'À¹Oì±ÎMÚ4OQ¾!HÆPùç !7ÇI¸^¾'Ci5L¬šõ‰ ÌF'áÀ–!ÎOâÉLÌD£Œ¯3ëžk¡÷¶yàÀQ‘˜ÑM¿!P’ýÉÕÿäOŒyÄ7Zý&ÚòBO÷;ùÝ‚Ì?ÿy©€ó¼èY 5ß0õ´¢|di†¥–Êõ—wÿ <£~ ¢YÇÄÝ#wѱ0§¶à] .Èù¿"I<]!¾»y*Mó3Š¿ 3:Ev2åMjßãÙÂÖþT2o¸=Š=‚ö™ª‚È£X—\[­Ñuš’óÚÁý^D¹6#mÛ BÑ܆.0÷ý;ºŸESæîók2Z½Âã5õÎï´$÷=·Q ŽÕ!èx U¶Y…A†Tx‰ŒdR—.>7Y86©JØŸQ{ÇÓv)EYÎ&H~°'"Ú‰Eêº:*B¯´áš•ÇZxÉÒéFSÊ”x@ö$NÇG`ß¾’Ÿì«KëO¢Âcq0]χ—êèz×ulÎP:ŠÜx×XdØî䯰¿OX3kI×H®R™˜ã§rUQ{(%ê\i®ÑÜ4ˆçGpÀ}óN,vŠ5FÉ*åø%®æÃͽKæca÷VZÍ,É%oTS•ú àïg!ÑVJ >/ó1e™\uôäŽ)e×Ôϰ÷,DÒé=Ûú«ð ›pM×츑 @ûf7 jÈ’®Îáîb’:áÙÃ12 ìÌ÷H4Ü4îð{cÉýÀ²â¥9ø:sðób—.ðnë›Í¸¬Ei­™Çl³úÕKõ½kúŠ€×ßþ%¹Iæ4HxÐÿÛd+¶†hª±C=›ŽÜëȉŎ¬£OàèÁ?Ü”ßG©16 kˆ¦iÆiÅì@7rQéó¯R{Eg›Uï‡M²aú•´Ï6ž%¨î¶ Ó=d§Œ'£³ÿö?ÁHÚKSˆýË`–ßu´á$ŸL ôL$^{8TþM¡ïÒ„Pûº8;ý"ÈqTòo£¨9(ÿ~¢q9ÙàmwÂ-ؾ±êl ¸yj“v¿"Çæ,… 6&ø*zõo šîŠÆìÛ^¸5_‹}4*ŒväRö:ȹ+=éþC·ý4&œÇå÷äÙ7ÀËÎÕñexÔâÚNöIëp!:¿0ï™h¬Q¡FQ²)Zø¾=MìÆy~“ñu»TŽIˆ¥€$&‚W~Tœ½a±3½Ò_Š¿¶Ì¥ÉÙép‹Ù/·i2ùVDìyTª 6Ó»b~Ú¿Ôã ÙasçÔ%3cÚô íß,V©* Q® †¥††Yi%—c³T–¤(`¨B8ÃÜrÄeSŒ» ¶¦}f>4å§^y÷éQ°JMòIÈáÒšLæ@ äý»Ò+¬Díj%Mõ_\ö@`ñöÏiåÐÌÈ|¿ç¾Öçq^Ú]w„êâ»óˆ(ë-FÂ<@•`²¸s}ñ {‚·´¯ñÌ•HxrX\4L8IVR°ýA«~#þ)ïz$YÕ””UC¡t a8¢Ú{çùz …o\ f+¤Ë›¨JõLFA p/JyÚ€b°'D)NüšK‡D‡îÝ;°ð$#Ñm¼gNV¯ä“£œt?AäoPu× à.˜5zà¶ëUí­ÏºŒyЋ'Œ¸*üþeÃN`ËéÅ®³•xÖÓ=ï°üñ cÊú„v2ßf] ”‹Î< ÷ˆÓ¥t€Ï¶ZÊ÷‡ÈB¢]Ú‰öü¡¼ÅŠ3 ·ÁQ=)ªnOrý…–tKÈNÖòåUŸ8œƼ׺Á¥ZMäÊ“9ËY¹éœ ºÔbýÁb-ø×bèe}ózq|É Š| ¨>õøêTƒ·~ö9¹@¥[=¦Ý½ØiƒgÓ±ÝØ\Ÿa^È0¦“ûÐÒH·$øYÇU¶ÊcEX0 \øéö¨¸Û;S¥Bɧ7<:DìŶç‰9zg}2Þí›»¶¢Ò¬Ù.Í3AĆv4,²x.wÕ·uŠCùM7hjRùæ5âgb£×”·Ð4*V•(µæ“©÷ EyÆT(Ç@dï+UŽŸÝVÑ~>°¨ªôwçæˆYc3&%¦ pËX«ízêLµBf„!n ùûàCï|.›ê©[XèÈôIrØYpÌEÿºžƒ¦Jý l¼BñX5ßG’ ³qÕšîsoµÛØcëOæwÖÎÿÙVJÖIÊ¿9 ø¬D—ðh1‚V§õ÷yÃlo §›Ew9¡jñË»¶1ÂrŽÎ!/S‰pêŠ!ÿDÏp_}bñc}$¦/#nmRCFö%ÆŸ–~8ã5ºZ´šÀÂû8¦ I ÛVÍd¿nÍ ùBIÈ™^B¾;öß=&øzæ»v~a® ë¼!åóåµÁsÊ(4m“‚¶³†—˜Ä†2y«ž™ îRÏÙÝU   ¾Á2hÐnÜœ–¶™À(sç~Øåó.µØ¦jÀ¡zþöÒ4´¬[_Ï:!!¡ÚædfywKø2ÜSBelÝQõd½dõØFò"¿†ŸÓ†§ìò¼ÌOQçxEØ’XL ßÜgø¼SÓ­Œu&.öÅ6[›ƒd’ÚL÷$ŸÆ‹¢s²ޙÝ,ËÁóäT~ìhñ’‚OO¶K±µÝð žGí{®.çC¿FQÚYÐñ²6ÿüƒô3*]·ÿú!ß'ˆÀ3™õ²ï6¢!L¶ ;ÕØeQl_*ÉŽ¯#Ÿýy¼¼Ó‡ºÿÆÉ:øþ°#ÕŠI¹ –ëzòg.'?Œ›¯ì¼rè–Ì—âf¾¤EÀ8´ g^;ËÜÙ颿´$BÖx¬÷ÙòS÷en@ŒÝŠ¿2عd* îµœ‹‡}þêBQ³çžnæ ¥T* ò Qz0¿fÚ$ž‘8E~ëE‹B©Â†=2q4*—`2œ(†º‚mæû•aÉ.¼Çý[E8LO°žxŒŽ"ˆì'çrž¸)•)6´,þV®ÚÙ×κ9›MJ®=Ï· B,¿ÒøsïGgMñ:†µM…jš»Ùའ8g³UVƒª¡D_U„ég˜ KŠyÛ!Fþ6©¾äuÈÇá &5>;ªkæ5lúÝåH»XN†ôÁ€ž¥z£›Á‡òCûŽwj?ØnÈF¿ß+·Í2WèèËaW»,ëxP¢ÁÍò³0ÁÒ¡ do¿Ëa€ µêqUQ5ØÕý Ef «ÛüvÑsÏJÁHÆŒêø¿æ$-JЇÖrËÊ!+öötúÝG’¸l’ÝgØtyžõ]9!Ó@»1DNÌïæ"c”s¹²ìöËâîí8Z6&°ÍY]y6 ók:M: cQÛpŠw£´±ÀI ¾‚bF-e+:E†Ý+9O…Çðt÷OÑ?£è¯šríW‚tk¦7:SB.¨'¤?Mw­{ºðÄò 1‹Îå—ð’âW 6ÎùçêûóP©S• ÐAÕÌK£hC›:Õ°+²%^çýShõ÷ÿÐA•[ Üâ‚£s˜;† 2ËÞ2Åqêw&ÆÊLBÑ/e‡Ì‰çˆ”*Í-ïÑ÷iúiÞ<´6®—kpÌpRù­Áõ‹>êöVãa>Ã×<‚û¬J5ÒP~)¬µ?i±žË‰¹Úš“zÚ«ÆsÝïa½½×æ¥ØbæT`âèì²É>©:OŒÂädÆŒ™éh  [‹‰%ªxî$ˆ[º¼Pâæ›| ×°¾ñ×q4a–|÷pÎ)7Ë[݃ÂX†Ž/­¤$ÂÌŸÊgíxâS©tªÙ®”B¤å¥„P‹ÐÕzÞ|T1õÐKLðïã5Ej7ÄܽV%=”öHcI‚ÔP³õS|i§’“ŽS ™’3Æ×†NËNÿ÷Ñ\»RÛ4#¡Ž¶<1C¬ð/XÓo-sÇüHJÇBõЧL4eYû¶âÕ­µkT<@0St¥0B=?/èPýi ™qÀI‘ ê¦S(áÁ@T—7µl•ró7 «fWúa¦GÝP ©·Ãí&ø‹-Ñ=ž3€þWâê ßïP˜ÖMxËX&p©4Ëêl]ÿ„ÁGmdŠ¢;Ê£©¶¡}´@ô_Âæ2“…1»®‡îò¹¹A”Vîs ØŠv“åB7©›0´ä@Ø—øÎcˆiT^Wˆ&à› ”S?Y"ÄŠkö¾“ç[ý“ÍI¦Žœdaný£ʪE¾‚æegAR†w–._Kꑼ߻êé?Ñgßh¢`¡uaq¨ä µá‚˜39¦ðüæ~’"fa¼Å}-‚ÁøÓÖd»48iTØ ÀAïÁð…ðË/Ø‘°WÕ.!7ÓÐÇZÆ«QUôƒW5[í¸sGŒ® ©îæ< ˆËÙÝCEÄ»¨ˆË<º³~‡Ã,|÷êââ]£\i]w{ÓFõ»©m=s‚>T4\¦=*[íÝÛ˜IræHEƒ)C"Ô,v¹ˆQ^ý²ÀÎåµ1~ÈK6¼|Èœ;%¹b½Žåçíð—£6¼Qøwlï³8o~¸Þ° uZË™üz£îM1äOpŠüE žå±Î”ÿ7®å ¼ê^=pPÑ >)”ËÈfäeÞ~ÑJ¢"‰_c³•!ìÿÁ K‚"ÛÅäöÞRðÌÊØ.±ÒOj—db…‡ViXwûýaßž"%é~± û/õ‚D dÆ28ð±~=F<—º{b ù/÷ì|M¬dJü†cÙò™‡@]è±dâÌ_€³êŒ‘'>7þ€øò‚ωPþ ]Œ¹Û4¼X<$ŽŸð­êoªjsPMÁÑcŠ,G·,®D·QT¤í[nfÂ%šCØAΞêÀ°žNT¦ªÀäA¸b·/ú~{Vó¿›0·8‘(Ñ,ÿ¶5§y3pD`£bGxÖŒÆwQá«C­&fºÝª-ߞȋ别:ÕÊðþ¹f’_7}ÉÈm̲9ÚÃíO¸ö2*Ób؃? ü‡iSûÂ{Žfæ…zçœN Q‡š¸¶U hš²þUÔ;2)įx¡`É,!‚˜%€cÈì4º––!Ù‡ûFæô¾ŒÐ~†ß/\ß¾Ó¥]º\æòfZAEbÖ´.ƒždKº™uŠo¼Ê´>ËD‚O{—á!yÓ`#îåGjmy¤ŒEÌ çÆª+áy÷¹)I·–‚â!3©02ÇëÁâxQ]â o}¾'h“y§PÑ4ð5ŠF½¤Ê?á`7;¿X}_ ìA^ÃôA.‰Yd‹qï­Í³±Z¼ÁÌ¿FÖþÓP4OÌ(Ù±Isk¡‘¡®G#¸)U­÷;#ä._}DZ¦Oµ\9¤JV.¤¿"àw¼‘XEa'ÕiP´ ¾U—œ˜F®§ˆ+^ÿ,µs¸lpz°"Z9’4r‹5 !B¶"º¯Å‹i©ôI$LIJ´)Q2ˆIÅ¼Çø·½:@‡ÖøS¢žŽÛøKÂò›~`m—PLÑŸÃÛjýø|­GáhRXy$"7"äB¢/'{ÏŠRƒp¦øfÔHL²× $ªÓq‹P2“Â~y‡òÃfÀ¶L‡Ó„”‘7‡ró˜úò«¥, KvI<@S¾]üÉò,üO=2@Ò–Î#Pˆ{Îå>q€­”ÏË`d©vI'!úí¤JZÛpãwÊiù³uøîryw4gGÖïUŽÞŒfOŒ²ÿ5ã ÿb.i(€÷q˜ÑN ] Âé¾&S!ÂÂ8<™Ñ€µxÙÏ ˜ `š˜-çñPüªÙ^‹&3Αº¡Z¹ŒÔž-Þ{Â;³-‘Œp~…³K\ý¨ƒÃpÕ*h˜’(}–úvtœðÿzçᦕ×6¸¸Ó?Jfp⌣j;)**Éû±{ãúø¦E)2øñj?ÉNch—ä3?®©~}‡AÍEc+žXjñb¬æ%ý¹ž›®ÚÒeù”ìŸ__d&},T}/ª·$XR^8Œol0yËŠ+.°~X*ôeí­¨ÓMkò0ž;yVM‡ÁÏÌ ƒ]ël¿ ¤‡´*Zznæ>ÊDßíô[¯r›~Î¥½:[ñ±2ʨ¶‡°ì+¶ÓÚË쯿ïŽíyéúýE=©ýÁÊ\¸¸ZH6ë/ÚÁè0Ÿaló Aý`t…­wÍ-‹©U£aÿJXç&'báb #Ôázg'‹ÂçI¥Ó. M˜úWÔØ˜ÿ  &WϱlQ%¾ßÌÖ lÀïœÇBciFBNýÎbÕ$œEà ÒÿžEÔ„âÌØY]J ÷*X\^óÿì[(ÞÞtè¿ >’L¿cÚ9tØä=)´{Õ29üQ‰²òNI^ÁÉtó Å \€-ˆ°¡ŠG‰yí¿è&¯®‡¸}×[}õ†Fd”ÃÎ:É¢„ ¥ÍfMІŒwîáIVÒbM0·µ÷}Ðé¥BXni0%ÙüÎ>Ë¡Q k­òåìã%1JbÇ¥üml®ü˜ìlã_F¦Ÿ#` ”¬{dÓNg++ŽåáOœŒè‚¾˜Sk}²®þÿ"TkÁÇE€ îX_5ø±¹5B5O·ºËæLÀäÔmŸ_˜„tc¦‡´!P×¥¬jÊõ&ðF ƒsèltDø!.%ä¥T9|¬?‰oÍi“޾má§yæ¾W8õuÙ–”£ä¬å¥Öé¾qµØ!~ÎÀ¶]·(ŽOÑ÷0î]}6«høÙÙJäÉëa$yƒ #¯~·øãE}}0 B3E!Þtœ´SfBë÷XhNqÂ^H;È^}­%l<•%Ç´+ʸ*²Š‚ºO·"#ÛõAЂšþ†7ß\¹œèNïn!¥ùìdyˆ°¦ 2ˆ’9â3üÒ×Â!þùŸpzç8+Â"è¶2gV½™hÊø:4Ïg¶ðÌàvÞ“ ° Ñ]×éØ=.7@]é"a°²n´úårݤ£ fª,®Çí¨~ƒ´V^ofMs6–cµar5"”yáò"åþA6ö`npUw0pP‡®Fæ¬$Oœ%*fw›R\›GÛÁ]^lfßp/&Éu¿ÑEyã+:«“îú’^U^wB56§³Ìœ9ö´ÊEˆÕC§]¿ÂK]†À÷ˆøÊ<fJ§ùcËÀ@dŒ–ä{Œ”ìfHYd‰<0Žæmì¬~Š™ªÂ Øõ+iSœ ­Ê%XûÊ6`åÛ µºe!§d+ÔºBi½r CÖy&€]½3òí,e„^3@ÔœŠO7Ö $Àyû¦o¥w‰Ïp._\Ãé¾QФŠj‚$MîHß3“ð‹8HÕýrzÙ¯p$Å2®• m÷N¬>@ETAYÍrWÒ¹A[''C‚zv4BŽƒ‚=9€€Ýòï…ùбÕY©’Á&hÙl‚}­¡Â-x3E/Qd0S^©½‘ó²<ß-=Qî`)Ö61‘×ì2~”ñ¨"œÆ¹Dõ½O’"hÇ+þ’¡S!.£’oOœº9dþˆJoüñA¸g¶ŽÑ”±hÏü+€Õþ÷ÜQ·2v£áá9­NÍðš²QÛ@a—9 ߀õ¢H[Xh;»¨õ &t °Ãp{øÝ¥_$#Ží‘’¯£Ò²ÂSÀz5¦þ ?s€FJ™?s¬K]S5Tv¦·>¤gé¾>¿ûÿÙ 5i˜Û]Êv ©9‹ÀËFàJ÷,V9-?Œ¬ç1iL?EÒ•¢µ8˜“?Y:n‘ð´$"âÛFFÒÊÝÏð p(fŸ³ ·¡^;Œ‰XŠÿ®q?G,+°ýð‹1Q3¢¾„ zu+ÔJg©„ýßóÝQz8«mTØÖ£ƒÐÍÊkèú²ÿÙ©£2œ2I‚ï“ÊRåÑ‘±tÆrË^Ñ ‹åý]”ÆïÌ/¯-„Øn,¤[§ƒnrÂÀü2s_ܱÎ<Û©“ Ê^}mÇ“êÐk ÅP’Žõþ?çšð? >©qPš¸=í— ¨u SâŸ{®gë`ïvÉþ°ý^8Ä*”9£¿aüc\\(Û™$*ƒ™ªK,Æî¥B'®ò$5*c,@ƒÄó”}н%S“1ý˜š&?;ȃÅÉÃOÆDo©ˆØ:jkpZ5X÷¾ÓI ¢Š].ÆT—ÄR™¸ÀȇÔØ P %Fmo9+Èôscü6<*/%7LWŒú[¶óF¦bŸ´›BwóÙ m×I1ܸ¨@A⥲éòÝåå<°–Åšz‚dæ¿kÆ}>F±§9ôÀ=ÊÔ¸R ~•´ÏCßàÞ^Ð㘥HN– *Ô]6¥ñ¬f[Ú~O “_ÛÛ²÷fbNP‰#ŸÝ2Ë a‘sM~9˜CÊ*ÊÔ¤õ)rgk"q½„9ö"é—Z7æ·J—éé ¢ay~†T.ÙhXò ïrZ£Tuå_í=¥5È6¨^Kè BNlKÍ«øÈ,ýšm‘ö Ê<ÑÅ•B‘´Ž6´Ù)Ñg[ò°'FˆÏ(ÏÏ/ž‹b1gBe3j×¹Ý,¯¦5æ™üí}å S·‚à»ò©ñ{CÙô èj#¬æŽã4 LE`ØßAƒÓÉO-~Ç7_¹C XØoY?€¹‚väDÙf§ºú²ž¹cìð©Û3mÐÑOž =ÓµIàÏ$L:Û9ÔÛ¿vÓOŒg!!‰ÑÅÎm~”D[‘óá[„¿£ ëïW!Å¥›ì Ûcúl9 À±ç?ÙÈ{꡾ô<0ŠQŸð^D{þèíid¦UQЂý ë*¸ÓÒGÃ]$Ãé¹ 2H‘ÔŠø—G™8˜>ž,ЗJåü+R·rËýÂ;˜åÉ!9sΞðÖÍ-n÷z'=u®º¤Ö˜ûJ Ì€x$ÍøXT…oÓ,¾Óþœ@¡Èùäí£‘j6, VñûÑ3Ì<ûcêÆþ½Æû¿ÇÞº/ðçÏ÷´àžÞ&I«´¬z.¿d-oð/'MçV„4ä9 âÅÒ¦6-D+¯WÐ’jY5í›@-ÚGeA%Ð=X$Œ nÉš¨q|Êe%ü˜ÜО„.™Â óÈ}âFÍ•”íá9õäuèY¶6VKŽÛ_û©ªÀ0ø·#jΡµbó÷8à™Qrº£(ïwÂ.‚G¥æË\U(~¬–cßÿJð Xω,š¾-FžN •Ü=R\4uµÙ2_‡@ÀK¡ÚÅQŒU®ójI=Î%¤ê­ð޹`ÂTôÕZ=öÿµîð0Í8‘Í2½EåQ3³vy÷ e%|D塪H(ºÜÜ7ì$U b&TðL¨Ž*}}a\d•_ÇŒ–Íc é‘ì& @ëAüyÊöZµUxDâð[älZ èÙ!âéÓ¨ÿ § Bõ…ø0ÚnŸtIùvàA Í D”•âº_J×/ÝÂ2 Ô¤èÑÀáw*ÞLprô'E˜™Í5ã<·ný| Á¶jaâ-%ÕUñ²5EñEZe‹ÇŽKÊBçì¦áDqü§ËÏ›Š…¹ÿp¼kpl'=¼bÈz!éHæ°×Ń™n¥»H• ËAÄAöÃs<ˆs6×Ðê×®d‘§G\ŸûR/š¶bû¹öã¥ÂtV¦7äÜÂáR€¥pwH¶ö¢”VSÐÑLkÅíAî¹Z¼›Ì&°ð’å7?·eË8‘›…—«=4ŽY™›tÉtVgþZŸLþ­%#Ãà*¾¤‘’Ç•9!¾…Ýz'¦dТƒJ1Ï=ôdñå]ì ÔÁ-_ÒaA<û"&ï¶zü¶¾ÚÝéê£7# ò6šÏ~éóîèØöé_0v5/3މ QåZÚ^ɤ8½›|‘ÈhýC†ÅÄò¶Ð\µKø”øæèþ±>–ß4ÓãhÊ­1ºhüÛLRË!4ÄV *ÂtL¡BR¾€öލªìç4%ï„1bë5&Õ³5ÿòhedÿµî™¡G&É¥¦“‹´²LºT@ëiæšÐñì 0bÿ ̼ïÆ,!þqCÔé«-ÐDPAnÓgñ›ãî_CH*£ã/9äø Kâ8|%D>Z‘“ÀÙ/“ KZ[ªgã0xæÒˆ©~sÞ/Ò2ݬSbgÀL®Ê¿†­•UPâ™@:dÿTg[)?Ëìc¢ïv0Aõ÷ËŸÞµ‹4Èw£„ŠZíéæ‚sQ¨Ñ =` únrÇܵüE&ÑùN2ûŒÖ²aç$ÉÛÚTô ¾ãÐdvŒ7ؽÃ{µU‰$s-žPéÛàëš¿ðóhŠ&cG&™£ÉÚÁb5Ý“™¥Œù#.ÌE¨l”ýc͙ހÉîòÈ¥…倳h‚ñûç÷;²™l<ÚŠüN·n°ˆñ(R/1–ˆÌ§WÍ¡1žU4o£)¥ ìŠ:^`»Ô5“k‘²Ð¡ÿŒÊ%y}“4(Ð u2ν±Ô@Ûä*ên¥J”/n­Ù¸;àÅ3{ó7Ú‹™9‹OAD®6‡/_²ŠŠ¬‰0¾Ù·¶ˆÑêrK©öYB0È)ù¿3dz’ñ10úÒst¶¼Œ«s<9[`ÊG‚^tò s#"#9hógÞãDhér/‹þÔ  j^ž¸Ö,ÉIüSŒ™ã¸5²R¾ÐF“¾†ŒƒdÎlýmAí@³¥³™ÏÎ ýÃâ«üúðÏDæ&uÎÜ3K¾?´§æ4J÷öT3s¨¤7ýÛ_0^®fÖ’õüZYÄaUÇ<Žªæ60ú²íH¾:’þ]\½ù‹²ï|÷ì0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark endstream endobj 49 0 obj 26621 endobj 50 0 obj 1638 endobj 51 0 obj 24451 endobj 52 0 obj 532 endobj 53 0 obj /XSEYTV+URWPalladioL-Roma endobj 54 0 obj << /Ascent 715 /CapHeight 680 /Descent -282 /FontName 53 0 R /ItalicAngle 0 /StemV 84 /XHeight 469 /FontBBox [ -166 -283 1021 943 ] /Flags 4 /CharSet (/fi/quoteright/parenleft/parenright/comma/hyphen/period/one/two/three/four/five/six/colon/at/A/B/C/D/E/I/M/P/Q/R/T/V/W/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 48 0 R >> endobj 25 0 obj << /Type /Font /Subtype /Type1 /Encoding 46 0 R /FirstChar 1 /LastChar 255 /Widths 55 0 R /BaseFont 61 0 R /FontDescriptor 62 0 R >> endobj 55 0 obj [ 333 528 545 167 333 556 278 333 333 0 333 606 0 667 444 333 278 0 0 0 0 0 0 0 0 0 0 0 0 333 333 250 333 500 500 500 889 778 278 333 333 389 606 250 333 250 296 500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 500 747 722 611 667 778 611 556 722 778 333 333 667 556 944 778 778 611 778 667 556 611 778 722 944 722 667 667 333 606 333 606 500 278 444 463 407 500 389 278 500 500 278 278 444 278 778 556 444 500 463 389 389 333 556 500 722 500 500 444 333 606 333 606 0 0 0 278 500 500 1000 500 500 333 1000 556 333 1028 0 0 0 0 0 0 500 500 500 500 1000 333 1000 389 333 669 0 0 667 0 333 500 500 500 500 606 500 333 747 333 500 606 333 747 333 400 606 300 300 333 556 500 250 333 300 333 500 750 750 750 500 722 722 722 722 722 722 941 667 611 611 611 611 333 333 333 333 778 778 778 778 778 778 778 606 778 778 778 778 778 667 611 500 444 444 444 444 444 444 638 407 389 389 389 389 278 278 278 278 444 556 444 444 444 444 444 606 444 556 556 556 556 500 500 500 ] endobj 56 0 obj << /Length 57 0 R /Length1 58 0 R /Length2 59 0 R /Length3 60 0 R >> stream %!PS-AdobeFont-1.0: URWPalladioL-Ital 1.05 %%CreationDate: Wed Dec 22 1999 % Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development % (URW)++,Copyright 1999 by (URW)++ Design & Development % See the file PUBLIC (Aladdin Free Public License) for license conditions. % As a special exception, permission is granted to include this font % program in a Postscript or PDF file that consists of a document that % contains text to be displayed or printed using this font, regardless % of the conditions or license applying to the document itself. 12 dict begin /FontInfo 10 dict dup begin /version (1.05) readonly def /Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file PUBLIC (Aladdin Free Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def /Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def /FullName (URW Palladio L Italic) readonly def /FamilyName (URW Palladio L) readonly def /Weight (Regular) readonly def /ItalicAngle -9.5 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /FontName /REMBJF+URWPalladioL-Ital def /PaintType 0 def /WMode 0 def /FontBBox {-170 -305 1010 941} readonly def /FontType 1 def /FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def /Encoding StandardEncoding def /UniqueID 5021143 def currentdict end currentfile eexec ÙÖoc;„j˜›™t°ŸÆÌD[ÂÀ1Æ…p§³T¤¢€®o¿˜ˆà9«`ü¯….´Î:þ¹yÕêpýäJ*åÈÀl'¿–eî¡}#)Á¢Ý&»7+å‚/^§ ™ëWŒ{ïÔLßZ60VåáÌQR^¦üλ3rï÷)€#v¢€$öp~c—²¼´°£êë&“è÷ö'ÄÉÇÆÅ¿ñÁä+ž %;v &‹€qž?ZUªE¬µùsÞÌTÈ ¾Èâ<€gü@º#¤iÜ|lO~íÃÚXŽãŲ‚>’—‹ù0Á‘!ƒÛbºH”¦Œ;ÔEf`6súþl=×ßÁö „ úDêØ¥e=ß/èk‹ßg'ÒªÇlãvÂÉån¹_0Íu±ã¾w~­uï¢3Q0ÝÅY¬Á¡DT9y„Ö$î´:ǽhŽ'%£J‘(„ß8wDF.Of`™A_%øi™³ˆWb–WŸi5•'$E-tšæbeqðLj²^þˆüøŠ r•ŒuöÙq¯³Ùnç¶l9ÚD©u ÞzÁVËCŨUæadåüaùÆNá8Ê š¾CÏ?ºÑ€•Û/õ‘Ja»Ý°MoÅ]Q°ƒXïrS›ŽâeaÍ\©f‘Òd³ 7¾7;öoËD7^Êö¾Üa×¥ˆ_BìY)XÈ ¹¸6]f¨àu¨‡‚ļaaöµ$oI±NNoÑíê]• ö}ŸmÀ“̘ke+`·ûÔQå69ç¨Ø¸àt(RO¥Ïs[¼r¹vùUû?…¹x}ÁúkBÿ„¹òg†1 ë{DVe6 sô'\›€×M£ï#º(ù „M-JÂÓçÇ]Â5%”lIîgºSw«®›Y˜%ꨛ«kV¼w³+Hc ÌtH°'Ùö º½ÞÖ•ÏMê‘p»Ïé‚ûÿaµð£ãšäYl¶´xöê…ÔdF ><0’A@í)1ÐoUÚ’WV'·6:{/RÂëË?1h¬êÛÂt´`K2£z5àŽakLXíKÈ- áŸ*ý ¦pÔÍFGˆÇ¯<"ªæ²¶½r"qcåmk  ’åÕXàN˜C½fÁI%v-º)„ënÊZ ‡þeS[’?؇ Ÿ>œ2 W«pÆD³±6ÿ) Ë›VOQ r¬„X¹ß…{ö‹È…úàš”F_uê‹›ië‹÷û"wLjU¿dì›ÇSq©€û”$ C‹gº>¬ìá!ì -‘t¦Xªäƒ¶¿Œ.Vì+R ¼áiqI׺ÎÏÄwÉCåòžä¼Ÿq“ú¶“b™kSëT¡f€ë#ô&ËVé´§+•X”3h©UK`ª‰Q1Ë~mßà,PªðÓëâÝŠ)m¹k°Ž¶{Bƒ5ñ§6Q¶pRÍÓÖ«¥OV¤L²ò¨DJâuÓi¿­Lײë_5ŧ[pG¿}æ[ö:‡ï“.’ŽŠxí°`H^Ažà”v'žrÖ¢ðe4þ9LBε¾ -´µ\½ r,iN8ئµ¾Þ\>#tÙÆ··ØÏg˜?WEA­u–ôçòcU9s¼BH¯ßäOìVxãî Bæ—€ ê^æCáŒÕ)þ²8ÝØºL®•“ŸõtûFibÄLE3‡‰<€ÁU:‘ð$ç Ù–$TH7ÝÇŠý6bá3¼G©–ög¦V®1¡ËZ*¡šäª¡4UUáûkÒ3n´í‰#™'hÑŠf•ÛÓ|”À’î†Cžó=Ám%wYͶ³ðC¯3nòÊyüÌ®G ^Õ‚_wÃ&l4Ó“¯±ÎcW¸üÛgy¸…€i0×û`âæÞzñ`ë‡ËïåjíLÙI-±HÆ}¬d›–&ïpßmmÊ¥^9LJgÆÔŸ®úIºe2ÎÓ.qðõ~jã >‰#º°m£¦>ÞGpZYy‡–,žŸ{¼~ÎøkW­ñ®éA××HÁzD­6sÚ­ÓíZÎ×"oV‹¨£æ~3Ge$è à‰Â>“ÔU‰›@WÁ³âcåt)Y­„mä2xSò`(=çMÚ:jÁ#Ù¸àäȤW`hz´N§xÁ55á|ˆ„O“ΞÞÅ£n›loÖœ·÷èÈÅ Xt±ÿÆ4®#ž}> ÷Õ_GåòÂ-Ö[ǰ•-i—ûf»Wº!¯4*vnà’-]^:Œú˜–Ó+>×pÕŽ›®½›ã” “§çh2äœè¾ÝÈ,6³‡~%ÿ•‰ "»Â+¡’ÚÆczs=Uô]o²þ `q—£Íž ¼±É[¿úTCb ?”⧦¸Õî¨C›ïg…¨2™7å²1oH_beß>XÇÔL·qžPvdQˆufÒ'È™VÌ2CDn…¼ mVÉš¶"½;É«Lƒe¼ˆŸ\Iû£Ó%N€ *Aù.¿ŽÊÚíL½¦yËG6ÃãJ’&“µãð3ã-f鬛˸ …·è[eûGðœ×,Òp Ívµ® iW V7Ü&V‘[z0p˜#ÊÎÇOÿ×ÑNÞ> ípê9ªZ%£ð? õD¼â#*¥¼oÅË<6ÀPI·ÌßÉãƒ&+BIºšÌì²+o.+ÜWÔPW³à“¸þÆ3ßµ-ÔÈëš¹r_õñÀ[7ÇÐk´øWò·:“}çÍׯ®`’å@eAÔŽÀh¶§)œÉÊS‡¿%] ™'Mb'…ñ7§»m5+Ÿë²Dkû¤¦ù„'×·_µ˜3ÈÀ9ãÙš‰*”“[ñîqÉÎ ·®†wSÏwâi——¹3ª?Tf`TÆîF@o€ŸÂŽr/ Wtr5V{U»ux“S1ã.¬{áŸHÁM±Ïu®9åf’ÎÁ¸œæª˜~Òú“;4¯Kz@Å¡ú¿ñc†s±&{h„Ï‹ví¨š¶J@ÑKq?øGÁÒävÜj8»Ò³Á‘Á¨a}-eŒuŸøœ1‡É¥ã„ââ{ZÓ–@ö;g¨fñŸ§m+æý@˜¯ØAfÕÏàñG¶:5b¥ADÁ¦uB¸`µ©Åð¾k¡§tO@äNÕÛnx?WEyOÉÛ?µTò5*eìx¼ ÓwÖùŒÉGú%âO6ƒÂ80TMHý:–¸¢m´•b½"ZHû´ª–íôPáÆY.âd¹€¡HqK¬Òÿh=ºNõöáéþòè­}p–@[¿y ‡_µ~´{I=ÿ®’Ì‚Œ#‘ú÷]™‹ ÿ¼³’-WÒ5GÓíéYÉ—»QÀ®ìV| aP—Ô¦W½ièŒaèñ[ÆÈ[Oü} #º~Hâyñ{ñl/Ü]kÚ¤/¸Ä*~ÕkŒŠîL\±ŒRñ`^ÿ ¬Ö$o¦ƒY,ó‘|ÿ(}£N=›Ø¥ñlx¥Ï‚¶)JLh%`~@YqƱ‘¸ÓíöoR»¿Ëß°<¬äÏm)?K2x;8–x¼"˜=øqáoR) Ûöc˜rÅ9f¹¹º-Õ†H®†ƒѤŠßÐÀÓG½J"éDþþEhâáveL> ý¼A”<zRáâL—wjÈÛ¨¶°?ýÛûËÿGè!LrÚN,_ÌÂ\ªQ »©5‘ò’!”p¡e@Ö}‡6–f”â¿8]À q}'2YYåy§º» ’ñªóç¶ p¶··cžÙutÂ/Ždµ¼Ïðoò%ìoVr°qÀeŒù¶ésÛÁyJTî|éèð09s@‘oÛNºU¥ÕÏçt–OÁ…£¼;¦ž | ºv-›\TG£;ŒòJaç~Ì #‡"Þ<Ó/º³ëpÀ=Xlr‰&ÕVÓÓ[:=8šƒÁD-‚%‘2ÇŸ$<•¥.) …ýÖ_—ðÝÜÖž9ÿx&àgMöJßH\9@j vxÿdœ¾×G®š/¬EÙ´ MŸ ŸÛ¼J\ ¥ÊTif% \ÑÛ»*eâr¨ܯºríuò*G™ÇAÍL„ Å0UKÇ!÷´# Ø&ûTÓýä ·T¾:W©%QÛ£ äôòU®"Ý9–Î× ‚G£(U¢½ j F\˜´éÉ~)ÐÞÍQš.¼&™ñÿ?pýB›KóÑ_lrž ó‰±Kô°_ŠbKÉaC+³ \T™µ6ܱ ç°`2e=KDžü"õ–™ órÛ-_‰Þˆó< 7ßÀUõô'Ãe‹/&àô%†­àèÙÒÖ6¥Š¡h‡›kŽM„K'­ÚiL{ÔÝ}&Åð`€W#5FÖÞ5ÊõåÓ»¢Á-ÉV÷é~†¤žcAplmÉßüG ÐuÏÎ Qk‚B>rîþ§¸eE#Ëê“àzÁêBÕñÃ:ØPŸ Ì¹Hælm4Ë¢¢F'/sNû6öZÄDΓ^1GsË.N¼÷„·vÓÁÎÎÓ†ïeUÃX×ñIÃ,VÎæ8¸bv»‘e&§Ëš‚ëŒýS^¨ÈÈXB=â@ ³âk"gyÔFÁä†,P¢Šž_á!S+ÄŒ¶TÐXøeÇéa&‘¬›Ï„eîžð“i—YzQëÐQ—¡êíNz© –ï¾én¡ +«+”÷ÀÐ ™8Ú$c Ð:žã’+¥äÕº |T‡T4ÕŸÛf9zuhæ Ç·v°hÖ÷}'Pðr‚Ëž\¡Nœ•ý…z.!DÄ~ÑŽÑÕ¹_fNyŒRàÄÇ]| †sÇÊW¤>t%]ï\Ç÷Æb0TO/~ε‡Çª Æzœ5„MfÈ>FnIêŒLã#R#Öî›Ænô› Qå(Ps%ùsIÉax­Ø(žð†o”]Ì!Åà¸ù¾—J®ÞõHœªAèëÔ`‰˜)Ù;Ü:µé¾>ŒÿÃmS™R`\P¨ÀqýR¥ÂMIPÏ-ŒîÓ}á*; ,”û€7n´ö‚œ¢ít*R6§TÛ:r ›/$íá1F"_qZ™Í‘jäYO¹g%èÉö딌ºo™ÞÿQ&«?¸½Î/⾈FF?ëÌú”õ(ñÞ@Ä’ñcQ¦åä^rì*~ÿrîîœ?Ö¨\SÜ>š%ÉV@ ™;ÓGë4Y!ÎÔ¶ŸžÎø8ÓTŽò¼J§ï̱¿õc(¢Iš–F¹fÕyZ‚EhºÅZšÉÀ®@´Ç¹Ù@DRP·ìÆ|Ñväˆg,¡/‰±^¥ÿ2ŒØ„O¦’Ú¡Dšš,²¢°ªÏë~k“¶€•TÑN¸:_ÜU„¹ùAœ9‘<ïd7±·wÉylT§iìŸo—ËŠ@Û°¾Ù,ÂØeêCóš:òH¢ôG}éü «â½~]ÜŸ­”Þ‚{×–ÃèâÆ8—@ÊáéeKMMÝ Ë /ݦhņyYbºÕ˜¯SôÖÀPð9ªísCóëí:¼tý>é| s›÷Jàg~i‘Ø5‘‹J©Bº‘#½G.:{ýK6áÛ¨·iðYü*xŽÛoñ Ã:Ô {ì¾n»:Zæ¡Þ‡˜ÊKhß e­ÒœïF—â @6ä:ÑjI¡¦oK#7µp+´¸<ÑÖ•Ú/îöQÄ #›T=רâ™+s‚'ÔBÿy Â7ÜÇ]|º;þ vˆÓanGÒµþ;*òSM[Ûð)•é–¸ÐÃì º«ÉWͤ3"¯¯ps ó6p8Ëftñ8BÕTyt£LÃo½õåÕ&3Ü_ãxµ` Ûö ÖH§d¿ŒœE…´ÚTê‰)²·d$áúÝúóÕ—@Íãæå§™mJf¶$‰í š¯ì>Þ†Bÿà°3Ž8¨—\d7žѰ§š€ÿéÂGÊ¿{8ÊHc«Üv‡$V¸õT|N³`›]Á™,é0î;¯·jä-û¯±áŒðÔ˜ý‹cýrê=oíb|FdªS53¨¶‡ kæ}Õ5q&˜uv_}ÕYróJdv?ߺPÁß^ *-±Éùÿj6âÝ·ú=FH*¶‚pPY”õƒç,²„´·ƒä*ßt¦rË%ƛ؀0ð*Ð:úñ<ÐBý>ÎX§òWè B]ÞËïþ’¶§E›ÃC»K0˨BƒÞrV蚌S¶BCäÛ½D1<4à¢þÀi›(wmâx+Òåt¾ž¦„y칩áfïnj뛿r'„4ë 8ŸS-pÃùåéJ×EƒÉÔ¥ÐsÏ5ÉÇ#Jç.5årÌjiÞèçØÃý@S²Õ5q‘kæ x¥"X‘1}j‚$V5W½˜ñÞ(ÓÀLm”Ðáž^ü§‹qÊALø#¢(‘'õ¼b›½Ølµ°çXQ³ÝOš3 —)X8§í¼ÃèŠðœŽf¦òŽÐÁ䱨s÷}Æ–ãSZv§¶Ëd«FÄ6áV ý‰<î¹¾^>´S{JcÏRÿèÑÇ÷Ÿˆè@OÞ{s†É©*Û0y¦èÁ`°C`k/œí•LÀ3 lJ¸60½Â»“ý}›iÅ ‘Žz°Y‹pSuÚéWV8×e7.¾c`zaUŽÖÑ&íît•øÆ¤>>*I*µ}Ò«”¬–—9Ä5éãÒÛØñ)Ù…¡7£ƒTÍ#=±Äˆäîk–‡I·ÒÅ/Q˜½$-¤YÀfrkæ£Eš u»( øK]xh †Òî‹xéÙ‰HæËqx¿‡ÑØÁP¡p_–ü†ƒ`ÈIî¬r¼ü^°‹ÉÊd7f/œ=¸DGð6—ñ¥ã+ LàO ¢œA Ì@:Ë¡ Ó (w“[ìõá„Àª€¦ý¥³Î/é ¸D&˜Ð-¬Ë/pwÆBO{uÐu¥Ô_ȵ‹òùì'9,øç<Õ‹·x2éJÉ«½0Æ…¥ßª¿âÎ1Ô?- #hÏÄáÂo¤†/Ê7§eu=ÃQòótÈ4f/¢ƒLÁСËU²k Ï§;„÷8 v;{¨ï¹+ & úrÚÅnÕü˜¯³ü÷ÇçɽØú’«9ÑíïÊçvЮj}$ö¥zkØš'eïr}Bv¾ª¡hnÇíëU ñìuŒ[@lí­#¾ÛîzúzDEŽï×Sßéµ¡ê šÔÕ0Ô…œ,…¢BO&Ý­†ï,'# wž¬&{nªI1¯JR‰Ú»aàìm;m`®WRYhb¹ó@êñÖ ¨B»ê½¨w¶QÖÐk·*üŒ"’r|²Á«8V¬WC .l†"48uÔÃÉäÎù€p„^æÎ9Râo‚8Œ]Œ&5Ñ2UÙu¶¸¯†ñ]Tj+ìT¸Q€F_Ñ‘à'#|µù™œ¶x>0Ï…hðêæÑÉÖZ;‡ž‡,‡Ñ?Ó¯ÜYyíjP NQþ%§•Uز½q‰®;[1þ–˜È1ΡvÛ,—Õg4††ô_ô‰íÏ…QdÖ_ÛÁvÄ¢h0òÖ›ITåKÆ,Y®] Gö$TÚ§µOž×L)h\Ô(²y3x•ôÌ—ëÝŸ'Ã$‹ëÖæ-µµÓ/öóѰe†fUæ˜ÞÂÜÿnF2ü9Cwó‹›%Çõ‰¯¢¬Y|ºQ\CêT&!ÀX/À˜¬´~>ø»øä Õµ±qî9¹–‡tOä¨oášG3=ÄÒ œ™éΡE,ý=_Yк$/_X£Ë›±ösÓ¢R†ˆÖ%Èç4G]Ö³+WÃROwؘr+GêØl#<FÛY·¬oŠ=LLIêÈ #îq2,0<CÀgµŒÑó‡~ZÅdÙÝäj†3Gëß6Ve¨ûízq‚ ÛÌùÜíÙÆ¾I_£çy4 "<’̲÷±ªÞ£ÅùFÐEó6’ºþR—~Ëz Ã}\Õt彬€ËÝ™>kg¬a,J{£ŸQ×,àóݧî_§dKþß„©:§8 ½š…âF5¤‹|f¸Ph6ãÍ2;†|¦|ÀŸ‹Œ]°ušûwCµ÷>ÙõÅ Y1)®ÆCf¤1û%›0kê§H¿3þ:#æ‹í5óh©?jhNÅçQì¥ÂIAß}œßu€Á°b{D·„×.´AEÐEbmôØ·’éÁáðe;ag¾òòo)öª:{Ñy‡AŠ‚9[íþ™ûì]Ž˜GÝl’$qûÖöf’ÿ E²r#ñ2kv²r/~Ý~+I?v«ˆ½YnÛÀä×~ú{080ûcÛZ,‚êu,—¢i™¨‘òåvùÃäµÔŒtôf†¤hâ*EV£JùvRÉ¡ªÞK…òPkü+l&Eå7‰#A;Gc8ý9ܳ–uƒOE±4]UÞ|fÕÓGzô,šr!+Á Ίå§:»m`A5‚^Ð\hÚÉó{§"ØÚ%"ŽŸÕ‘̺TP>'B˜Îõ`ïã÷§ù¡Ûì° -ží&$âÄ 4ÇÞò—lÈ·@›þ§¢Òd‹Tb^Q¶c¾JÕFR¾GÝW…ÿ8Ï_¬½ÀiܰlÇûДÿ¾è›šµooøB¤¨ý>õÉèò„µƒËÉ8,Hxþ\ÞŒ¥¹"Ü›òä{á1„¼‡ý‰ {æ±[$ ªYE¶ïèº/Ñ—ÉM·—kÛ ©T[w¡²Yû£èh:×jExøâVÀò|vD-Τ^[Ì“¾iˆ.þÝÇçVá¶U;}ÑØ•.©%€©õÖdÿeÿß Ø™‘}‰¼ílý ÏßîÅ+ðÙ>Ùc@‡­…2ké)‘B!@8U]yƒQptÄ×áIúnæ†ö|µ³7 âM)¢~ï-Ÿ‹HMŸ€j1ï„vÈÔS¯àíø¡Ô‡ÿ¬IØ=¨çŠc-™`.~‰ÚcQJ÷–¼Ý…”"Ë ¿°éÃlxã ÌÎN|–MÃÐë·RÄ `>߉i/g-㦠…%ã¶°Â}˜ˆ°¾¸õ8Æ XíxÄ3àyÝ6N€>†¿˜rÒîe î÷R+Î×Ñ^0̱“ß.¿Qˆqj› ^iä)|i*@ÑÛ&Ùu†B¼¹b'v䃅M]}ðÌ.(¡é¼ð+Ì0½g±m¸uº| ʴ·àK‡^öubƒ4m%¿±ÌøLDÆâ"ón€¬'hJ˜»±DS’®‰OM´%S{®tµÕ̼²îê’<ÞfʆGxœÿ‚Rº)úÓŠü–úùŽÁzJšÇüûÐ.%2ÃTÿZê‰|cò¥ùîZS)u¯äêùÍW”âa«„5XmÝœALXßg~£ý:ŸÉukùËîž-Èðw®çjú.AŽAfð¸#6,WaÁ¹ÏÈÃN›JcJýç›7,°ñü úø_é1ÛIò›B¨ûcÜ,›Õh—æ:i$mwPIG£~{98(úì(o´µ‹j³«ÚVmïÁà‰$ºï´NÂÈYíÁ·RQ¿qê.Y"Qjg,éiÀB‰´æ¿ó†{½µ=%’/=(YÍ×±@Dº_ ÑÒQ¸ØÉ¶®©'g2@q‘ÜBkd‡€œ6þÀñ&M’Ëúüž¿(ŠãDY| Ùž£‰_bƒßðêåÏ0³Ì£™Ýçû™nšÊ «(³ç$Ùàyîñ'Q¾ƒ ÝG_5Û-Õ©ölO€@B¬v…Fèž;X.éš I6Ó5ˇk눦Ïð—‰O%’ 9eUÚ"p ‡Ib÷î—aÞˆŽÍ Wk˜ƒ–ß;.ð“`Šg² â}Gðép«úáï°óµˆº­¸T Xí„…0Bkâ£A‘'㑨2ó|ßÖ?#ýåÔKdTÖz+i»Ùíæêx@´Ó. Ϫ‡¡Ý—‹úYúFjQuæž΋~^%Ï3Çðº-o-’¿¹(ÚºV¶.¥‰Jc]ßq›ñ¥Sz·í†ç™r¨ë®Ÿ6Øð  ZªÉÿ2µX¬ÑÔ•£ynÚ%®Ueõ·xk}ÕÑbÕ}†ö÷m]pZáƒwîMYýi±vçû†yè|AŒ§ Ûš”Ý”™W¿Uè—X?´—‚6ï-@±ÛCû‘ˆ¹”;"9:m‘° (S9é½¥ºMeæB ùµ ~ ç\,ÆY£®MŠÖ+§ŒÂ‚漟èè"0FFÏŒyä~ìq§™Ké1i›D©d}gMd`øj-A“ ®f¤ÔêIÀƒ›KÈEz‚Õ ¬OË‚à<¾*(a¢ÿhæ*bqVa·$í! qv€À‚.©ª³º—‡Óì²­,ë"o¯£b8$ÈßK-O …æl`kkøíÜ—ÆÜVH0ö4•ö~Àr-¯:äÓvGØôhü"·«Ü9~ßj·þf\]Óm,E‡tt^‘ÄÑújV~/‡`­‡\)œ¬ºÚE­b ü·åÈ\K\wÚúvlíBˆô¸;7ì Çö£yÙo^—-lzÖ ¤UmK„Õ83à不¥öèuÆÅ‘¢P‰òµÑòÐzC)”_­šåÎ÷¤h5ØÖÛQ~:~RÆB¦D_‘ gÃ=¨L'›©ˆÅÉ„ƒ¿£h{­}óóD1C* òõ2 ÀÿKܲjŠº¼ÓÅ­pðïšxñøñ¬úK®‡æçÙna“k¤ÛIEëëN¡YáQ€S*ÜZb‚²ÅRy¶w ‰lL¯´šÄ øÓ_{?Þýï°™‰Õ“°GûЃMüý(Ï—¹O+–{oò¤õ¹}NL‡ËúÙÖ¾tƒý$ª Ü^R9ݳJ,4ju_З"ÃXÂïÖ‡w‹ÝH#œpÐeÌÖâ}4´) ©Žw'¤‡b½{Ö¶]æMá¡ÿîX#f­Fñ‹–| ®Š{W¨&ÇÄ_5ИfV#·‚LÝÊrköïøœ—·Š~VTÏÊ[¾–³žç}ïôâ™7<xâ=^‰ñöÆhij¤Î Q ñÌúþ G4òLB(…™Z{<–F£ƒ=PñÇä7 "¯ÙÓ>]æ¬WÜÅ÷Søh)…&º`Ù¯‹o_Qõ ^Ns—¯½ˆf7]ŽEÏR$ìë:öÄ6â<½‚×Íòø:Âèç]WØvë”lõà=ª2i¬Ò4“7£rè¶\¸½û_XŸóì.E+ظmÆ÷N;¶…iºÔ’Uum”§¡ìÚ.÷ÙêGõ½ô]…{R ¤?xÜø‡·öÿ;Z²Œu `W®Îl’UH„Ýž¦a7“ý5«YâÌ€©¸?•\ð– d[Læ]èÑðR>Ïö‡Ñ^Lç¶ß yÁw§ú–ß6Ýük"T«û~霰ýð««µêO1øÛtû_¦«zî^ ­èõq}ª&ÏR™=pÏÉ÷æãk’Ÿ!Š:ûç™=è#{+»[b ðsD“rqqGý€bNšÿÙ¯›RŸãó VN0ms¶ì@~:c¨\M¨N…©—ÏëÙ—Öô<ñO½’7ítb©•¨ÃÑ7SòðÖ–uÅ&ÜÀs¤ ±­†KÜ5ó2i[“m6G'êû€#.ä Ð` šæô™Y¢ãï7èZãº-ì* šQ®ÏoB$<#DWÚ.¿L¢ÐWõwkÓ®"®»ò;ÙáâÇ'"ïìk¼ÛùF'N€OÃ(²¬ÔFjUûàóÆö›Ð–íe„»WÈ\DRˆr>ížè2éž?¼Ãõ4ÃÊ0/0¨¥(š»§˜å÷{‹[—fú›Mൾ„)Ñ´¦ZM^¶AVÔ1ÒÙÅ{{-F>ç41j³ÀBù¡GÈ”¸”õõjLÖª"D© R@6\¥øšùyóT´G×ò7:dîÄ_Ýd]¯[”2ÜrÝŒ x™ƒ¸žÿ #£Q}(×ö/„é¶Õ1Ù[M7·†:³¦Ô÷V/y‘÷þµh¨7;vmq¶ó».ùÚ°`Fýê~W]¾mœJ; ‚¡ì[$iJz²Þ:|‹J#Ž!Wr™úù ‰®ß¥U-tS‚<Æ~6réYŒ^èÙº› ÐË?+ÊÇí—ê¦ÃÃ:Þ»T¾oœ~ƒ»}}`¼E“#5á…'ÍMËŒßø ÍSÅE–1 àKävùp­?Í• ¨â¢+æÚÈÇÇô‚¹‹zâ j/·¿³û¹f‘ä4ûÍó¨C;ªTßíÿP*ô'9‹žäÕº£8@‘";p\hºœR®Îvõ»·†B/ïœÈc?Á§Q¼ÚÛà<|Íë•€Á<æPÈ•9²¯®Øn/hµþ>¬énÉ4~fµ¨|^){‰øÄ¢ü$Á9«PÂÍýé Íq…¨¬o4§îo{bÆå*œ%ø Êt¹­Äê3pù„BÎÜ(§;cÓ2EJK­HëèËªËØ)бÅ©ÐSùž–]@³Sæè %ãF]@›?ô'm€³aöÂØI‰Õîÿ<|%q?táÐh_¯é²$Œ€ÅŽ4ß> òÑF*%ˆûRìÀd¢9Ô§YðV³Éo³eÌßžJÞ¨]ŸŒçJµ©eõ/ã:r/ñÎŽq`¨Ù3tã:ÄògÍÚ6CÈÏ30‘IÑ£gj._ €úád°ÓJD?&;A£2_“劋óVÆŽswaP óûöÆ<)ÎÉ#å<~G ½F8iã ^9’lÌßôG ]è/&–á–xäÓáVÖ{Þ3OJÂBUÖõØ”l†^Þ¾(‡2TáÃÔâ²5Ë¢Œ¥àžÞyÅiþG·W€[;gÓˆRÙ&‹UÕtKL{/ÝÎ%rÒ÷-uŸN•ÔÕ޽Z5Îrü»ÉóšÇÃc`‚çï -Î&o`’‹yÅîûÍ$!}ô4M©2 r¸ZoµŠãooE†“8Ã0•U貿‘æO­/QÒ!‰Ø¹]Ô(u?Ü^¼¸8ò%ÏkJßpÝÊêÓŤ7|¿{$a«RˆwQüËÅ6+3®*ê¦ÜóÂá‘>¤p(tÞ¯®Wˆ7-CòÒu!ªdKyâ’e™šèé֣ᛰ’èÔº‹nâJ?7^|WÃM?n•}«Õ"i2ÛšùØÒAŸ¯:@ýwÁqCÊ>ÚA×­÷-· º­rÏ{CÔ^ý‡ç?y“ßyÏ1Úùè pþXNq>T 6‘±3ìj*碯%IÈ|\a±¢Î ö '‰tõænÆï6{ælx†T7àOQ:¢â!ߥ½=¡†m'uñHî©¿q^Û»c0$A¢®±Þß~å$·ÁÀ  PPÿœ °ÌŽ‚þ„«±€5ðI_‘Ã[(LãöúnqÀ\Ôø_Õžd0Ä®²}ÍÃÊ—‚,(C'™”¦¹¸¹ÈcuêÕiç¾øð!ħÉ9ÝäòÉÖx§Y¨_w¿×BÛÔp×9HwÈŠAzÄ_? 0da‡®íg[FÂÐëû"Ú*5î$©¨Õa™`_-r°»èÚ³£îi“|ã ÅÎ\rQ-oëÐ&¬Á%­”ÞÝΚMsŰD!ûÕT‰wP/ä@×íÆëÍÙ"Ë٣د¾ k§q ÛJ,{ÜïzKHJUÿ¥KÁë’á0¿ì¡í==Œ¡¦-æ9 ްëä SÅ•)̰“Jœ$Óɳù…AÅæû·HkéÔ“û´5Çê¶÷Á9vYÓgl^Å"ø#[j"=ÓÚp2Ùÿá‚bfÜÒ°`i­úµxGŸ´ð î”;Tdu¼ÿ‘Å™÷Pü ëí!\ü$u´ ©yÔ2÷X`n^u.i5”{PŠÐ㺪SáĤ*7´m ’Òw´›‹aD¦3±›%räÍñÆåº¯k¾¯ÀI¢¶“ÙéÁ™Yß¡#…¡“Ÿ«¦^(PH/&:=Û¾ÂZÕ¼v©K# ïüxí P FƲ(7ãî]ÀŸ©Óê§: æÃŽ“×Šª°è¦±ÏcSêÝôŠöŠTs ϵý4oÔÙU¢yB¦;ËCI8¿Ês¨ãÊ6µ|ó<¥p€®\@h9^+ÿ›ƒ¢Æk%ú‚Á‚*c ‘ÓI šTž ]E 5'ñaØRsˆ*¹—òÄ)ϘѸ/Ъ°´^‘• ‘æß@5j½‰æXEÙ„ë.Z–¸yGð7$.¨ü¿¥Ç™^‰„a|É´o¿/rð£JOˆõ1ûä­c†WÉò#ö®Ý Ù÷⟚~,ïØ¼C"h¬Ý0•Œe:e¼ŠØ3X|Ëqâ¯÷\†J‹[ö%ºzϦ©ÌÌkº=èÒœZã]q"ñì°‡ïAVÏMV¶^Í(^9ßPPp©ÄÞ˜Ô¸8—¼R¶µ«Ú7ù Lðy¹>ãwÁDY„Ùëz!ƧÆõ ,ŸÇòÒ9-ÖÁîÝŽs0¢œþ¡‡L]»¾_~悈¿¾§CM˜£͇pLK!›ÕE¸ïJÞlS¾ÑÇö±ÿÅÃ78¦ Ä‡NHj.i˜_íÄ[¨û}}‘«¡ì;ÇÛ¶F¤’:þNôd9:m‘° (P’âUå1°´x+¦ÔŠe_;AD*’FÞµåQ6RD0÷p”Õ®»)+x J€’@\$áœöØDY”¥)¨Ÿ¹ ˆ ™ÙI;%O 0ÆõBý6[ŸÁÔA‰ =Dî“иßdÃÚl©>Àø…ó?ÂÜÿz¥J׌ˆÜORæßC­€Dæ‚r\Ó.‰µÂöetgRëÁö~G».¥ð“æº.XHgv°%»ÿ7Vܤ¦f{²,„êúNÎ&í>ΔÀ7ÑÍ›ôO~!Ð.b¡¿†° gÊÃ×;ê2>@ „ÎQ?µCžõŠû\ãøè9#ÊØ[¼vÏ9 ¦‹QêÞ‹/ÂXzF÷%L´ó ÕCKN0ŠŠQòE¾;,®ètæw ªÆÜØÍé|ï‘iêlUà [a^ÒåŇØduKŒêc&QDê#íºÏIÏ ¹¶Zè½b>lšE»˜â³û8b†tóE5Wø‚mذ塂úÿäñ?؇¡T bÏÇ;ÔÈ4tÖ´s1÷ólYLþ>ßÂa>ícr¶Ùo–ÿ÷•©Ü8Pˆ„£¼èŒ›Óœa´Éá~-¦q§úˆÓú"L«Úk[:0Ï(عÆ;S/fÆ‹"¸@%'PHZØWáÇb‚êŽa<§#£ÿìeÔŸèk¢t˜JrÐRY6…ëëòbO›ÒXá²3EÀÙè§M¶Ý5¿Ú·Î¥À/Í£òœáÝg2h¡· A9]}|Z²ƒâ•Ÿ>WÅ/‘Ã%_Ù,Û•vb/óÉlhÔÿš&“)± (Jú³ÎÃNü®œ„ÙÁn' %8PÚÅ$ R>dmKüš¯B ÈH+JJt¶»8ɯY” )ð%[ùzŠ6ºN²ñ~¤…ÓÄb1Q|Ûšú¸NþÞýo©ççê7«HÜÖsÌÕû÷zBì)ÎàmbYN6?ìR$›Xîଦ¶ƒäó¼‘öœ8Ìb’´ &/·mÿDJ¡ç ÇÍ4<?è¿*÷ÂJ¸—h<Dœ·š®Ìlåþ77¶Ò—Ù4ÇðM_Ø;õ;BŠƒYŽ¥)âø¹Âþ†…ûϽTê ÀâüèÐ9Ž·Ó¬ fkˆ65"a *1Æ–ôÓÐËýo¦~¦LnQ†™qæ'b.~Á >aNçBIÌú/§.Ë"•Ï&§þ÷«Î*ä‡ WžÝÐs†qltÁ®n?…1EŸÀœ&lâªÿ¬ßH–Gúÿ5†V ÏE(iÞüÐ*ìn¸¤DËàÿWÕ‚–™Ž¨Í¡ŠÓì3CE—Q?Å^¿Í“—dþÅn9š âË{jëu>XÞ–ŒÅkÒÐÉ„ø‚IÊÛ_GÔÂôª¢~ާÁÍâ³|€OPØ:¬— N×)dZýlƒè-ecJk¬lü=szÂÆ¾‹©7ÚyšgG¥„ˆbVóO)ëºö»‡€¢Úv>,ÈìÚÆJz˜iMìc²¤­í2òL  ÑÉä¹ßÎï;F² æaá‹’ŽÊ.ÿ`©Š^é`kÑÏ’Þ %×±‰¥snö$Ó­ ´^×3bñDÏöhD_- ²Å˜™ÿ9"wéù(`]¢/ßÂP]Ö4™9¸öÍ¿8h÷ý½¶”9ãÉB© Ñ6m‰àì%á8“x”âSH†.éŠMäø£+áÌ„î¢Ow»3ÏVŽŽø=c„£íGÒö’îdÿ¼i0rÒ¢3ÃÿNy«vÄû.0æ¡xEH†¥ºÑŠEÇo÷«=Ž¢]¾ÛulIØGX ÿ¾¸­É¿ü»ÜѼÕâ+€¯U”ó.¼…¡ð°$€`Ÿ|å͘ýùª¡ßcî SúÕ¶¡¼,Ù|œ2°¿)Àèí¤,ö¸‹“8ˆ^ J<´W†eþ ­dx;Î0ñNã,8­¢·.årÏ]?Â6šk¼'U Õ™è¢õ5¾ÑHò²Ú8{Á§À‹'Òz€8”»ðd$æ.ò¹r‚•ὈæìŒ rî‰q/qKÛÁ00R‡wÀÁÚ.ÈsS_8(¹8ï\âÖ¾.iS9xgØ/Ôå\5€[y&±øýÙ‰3Ñ©¨ò¥‰Oö¥eШáFû þ…-áéþ“Ž3Øþ0Ö9|@uе¶~28q×;ÄDÖ/x3“þ2z×™ ’ æfñÙ=I+ýE¯uJS6ƒ&duQž PGêî½VTBoõ¤„i, ÿríªhnh‹{M#j‡—=}’x%#ëwëÖΗx¢ëZu—€;Fkw*Éêl·ÕçOÄÒ´éš9"è>ñ@Ì5:²Ða\#D™ñªFİdë3Ôm‡Jª¤½fÝÜÚa6Êyq ðÝFw&¬5ß/úLc’-ƒ$ìõùÒ30aö·áztð!m”Ÿ³ úùu©0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark endstream endobj 57 0 obj 19638 endobj 58 0 obj 1642 endobj 59 0 obj 17464 endobj 60 0 obj 532 endobj 61 0 obj /REMBJF+URWPalladioL-Ital endobj 62 0 obj << /Ascent 722 /CapHeight 693 /Descent -261 /FontName 61 0 R /ItalicAngle -9 /StemV 78 /XHeight 482 /FontBBox [ -170 -305 1010 941 ] /Flags 4 /CharSet (/fi/period/D/G/P/R/W/a/b/c/d/e/g/h/l/m/n/o/p/r/s/t/v/y/z) /FontFile 56 0 R >> endobj 24 0 obj << /Type /Font /Subtype /Type1 /Encoding 46 0 R /FirstChar 1 /LastChar 255 /Widths 63 0 R /BaseFont 69 0 R /FontDescriptor 70 0 R >> endobj 63 0 obj [ 333 611 611 167 333 611 333 333 333 0 333 606 0 667 500 333 333 0 0 0 0 0 0 0 0 0 0 0 0 333 227 250 278 402 500 500 889 833 278 333 333 444 606 250 333 250 296 500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444 747 778 667 722 833 611 556 833 833 389 389 778 611 1000 833 833 611 833 722 611 667 778 778 1000 667 667 667 333 606 333 606 500 278 500 611 444 611 500 389 556 611 333 333 611 333 889 611 556 611 611 389 444 333 611 556 833 500 556 500 310 606 310 606 0 0 0 333 500 500 1000 500 500 333 1000 611 389 1000 0 0 0 0 0 0 500 500 606 500 1000 333 998 444 389 833 0 0 667 0 278 500 500 500 500 606 500 333 747 438 500 606 333 747 333 400 606 300 300 333 611 641 250 333 300 488 500 750 750 750 444 778 778 778 778 778 778 1000 722 611 611 611 611 389 389 389 389 833 833 833 833 833 833 833 606 833 778 778 778 778 667 611 611 500 500 500 500 500 500 778 444 500 500 500 500 333 333 333 333 556 611 556 556 556 556 556 606 556 611 611 611 611 556 611 556 ] endobj 64 0 obj << /Length 65 0 R /Length1 66 0 R /Length2 67 0 R /Length3 68 0 R >> stream %!PS-AdobeFont-1.0: URWPalladioL-Bold 1.05 %%CreationDate: Wed Dec 22 1999 % Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development % (URW)++,Copyright 1999 by (URW)++ Design & Development % See the file PUBLIC (Aladdin Free Public License) for license conditions. % As a special exception, permission is granted to include this font % program in a Postscript or PDF file that consists of a document that % contains text to be displayed or printed using this font, regardless % of the conditions or license applying to the document itself. 12 dict begin /FontInfo 10 dict dup begin /version (1.05) readonly def /Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file PUBLIC (Aladdin Free Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def /Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def /FullName (URW Palladio L Bold) readonly def /FamilyName (URW Palladio L) readonly def /Weight (Bold) readonly def /ItalicAngle 0.0 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /FontName /XHKPLQ+URWPalladioL-Bold def /PaintType 0 def /WMode 0 def /FontBBox {-152 -301 1000 935} readonly def /FontType 1 def /FontMatrix [0.001 0.0 0.0 0.001 0.0 0.0] readonly def /Encoding StandardEncoding def /UniqueID 5021142 def currentdict end currentfile eexec ÙÖoc;„j˜›™t°ŸÆÌD[ÂÀ1Æ…p§³T¤¢€®o¿˜ˆà9«`ü¯….´Î:þ¹yÕêpýäJ*åÈÀl'¿–eî¡}#)Á¢Ý&»7+å‚/^§ ™ëWŒ{ïÔLßZ60VåáÌQR^¦üλ3rï÷)€#v¢€$öp~c—²¼´°£êë&“è÷ö'ÄÉÇÆÅ¿ñÁä+ž %;v &‹€qž?ZUªE¬´+‹d<ãô¶DžÕ§3YOpÌÍ{Û>c “¥Glë¥tîå“Î>w™j,Vë®R²pëÉ^6>™ZÎíýøíÇ'h•…¹„ø"%³»Ž•"ç„{Šñ=p²Í?uÍ“3ëš(ÍV‚Nš:h—AÔWwwg`r==(+2$Qá]Òqºh1û¹Sð=´åšÌýl-oâ¶ÈªÇî—ÔÅkR¼­É܃ÕÇÄ_\n`ߟ”qÔ+oEï˜ëä—¾÷Õišè˜¯¡`‰©T­°®&1S’bÄ;Å ml·8g±žßùOœ<}y FóGB¦ˆ¿Ñƒ¡0vI£ox-®ª-ŽX‘´$…DÎ_ûùñÙ˜ÅÆЕc;ASxdŒ¦_-o@÷Ì#‡R!TÌ3”„œN_&¾Î·ŠàìQ7Lfï ywÂÂÎ_Øç tÚ™hÇQo‰ûZ%…ߟ^•Ró‘™™’â9u9 õ9¢™ï œ¡n”aJO¨ÆÓIYuö­ÊR%W³ð/¬Ú¶Ž¿û¸W˜vð˜•×#ä‚Ýôý®d\Òuó¨ÞDªÑÔ˜{lÓ_»1(QØXâó‚ü`nA·¹9>¥z¹<è5¿ŽgÁ^ȯ˜ ú±¥nñ¦.T3£a`@ÞCÔÈò€PJ¿¥¾@ߥ-4¯%)§hs².ÈxI Å/ã·M%ž`9–ªõ w0J‹f1ÆRä‚ÔÃj^¢B³ö©y3µ“íòŸ-Ƴ[³šXvå7ŽqÏ ½KuSv+± Þ]E)Þ‡|¨æ— dvȤñ¾(æûÍÖwÔ7ž–©xí©z%e4¦A|Fðczh†Ïáë×V‰ÓÊÔÖ o‚P6¿åšP¥PðüÉxïå`:b1`®}ÿëhF©Dºa–ßð骫?4ê%©Š¼PÞ,GÍŠ~/+û•D¸E?Í;ŸFÑÄ„b¨éæÕë7¶_½å uhg18!–Êî1aëø™DøŠ¥ÍÌ¢€Å¤|íÞ¸&°ŠÁXv¾•m7—ßh@ly¤µßdwj鼪mQbç ß,šm@öMÚKpo«r‹oo©0+DUf€qž—Ï·¡6NAy„†-­v%‘ñãR둘qÏ´ûL–Á–ñ|Úƒày'úq ¥êîsÖè,b…|¬Pï§åqjUˆ×‘J À[ibh ¥Î¹•`”Â2¾†µ,6 }µ/N‡U‘-ã6ŒK\v/J¶,„`)˜vr6î›U&E¸=ç~’Þ™¨Ë"¬ö O†ï)ºl±u¡W©&=oÁO®¶&ó* ÃàFT¯bþPbAAÅéP,$—'¦@YºÿžÈ ¤R[D34Ü%~ZÆÓÝ4¾1ÿ9¯AgC¡Ã nQ-M!ú·ñÔAç½ G²A€<8jš£awÔ] s:+ûkE²úS ¹= iãEx5×Þ]|.2 x$èÙ,2¯1×OÛÀÛŽ^[|ᛩ‚=L£¢6¯=±=ëG‹/ÁOÄ–Oo:<âÝC=´–rè{¦Fbz{`eŒ’ŒëÃX .!p7Ž›Eš€ŸÓï­i=P—3 úŽÔÈàþ "+¡ùkÛ+湌j©ä'*<ß–Cí±õ°£xyœYÇþ‚Wý¬éÜ´ƒ˜xB‹óеÎJ0½;$Ç)fàiø^Ûë[¬²ÓJÂÆ¡©Fìï¥?o:dg ) nGÆ8%ô•R ÀpàqDNa_ŸÞ]'1£oSÎ (€¥"EiÔ&:ÃwÄ?1ÙN™ØKwUÕ|•_VÇÖ€ÛÄÉÀ¨¸›£öA4D£CjM6)[ãó FæxºÐ§Ïê©I(þdOï••œ5€ó»§·õ#»-—îà™¶ Ù MœäÂÊ–Ñ„GJ=nŒLzýëkÂpAçÖ¨$a«ï)œ˜LÁ°z}†¼±¿Ÿ~tiñYˆŸí}ÒÕk#(£s_ÏmiðÔ3éíKg«¾Í«Þj°U®Æºõ듉úÈFîã”Ù*Ò_Œfâîi&û¢`!´µPK_tÓE[éw0›VÎ$ú° Ð$|Šj3/w×yÚ æüû"xü»xmX ¦Žq5ËóàφHÒDsÕ~üN%fõ4YÖë3<~Ž’=?Õ>âGŠjVI 5<«·;z»»ƒ¢ËŠvšCƒYâkÈaùç~ü–Jõë‘k(ÍÖ–¶;T­ù¨À#ãŒÁ÷ÓmU°vjD§êäÕ–Œ8ÃïË|+nÈûéÁ=ÕW¢v†tc—ÙϾÌ×iéwU[š¯‰]ª'Ò­1OŸÌÈD[坿Ñ`–.ˆüUí§–p\ì×–áhxéQÒ©°yñ»~`09MU!xº&׎üõá²è')z)»›­a¨î¥ð ®Om¸^$šÄq'µ’›uLÜeGù'ˆÌ7‰Ç®y¿Q׌푉ÒÙãZnä²r‡š8¿ ›Îµ;©:¸‰àRã9£àÙ”ZÜá™”H5/ƒ†ŠBÄ)ªõ³5Î8~ç'…®õ>¢šzF«îÝÿ"¾Ží°)l6uÈT½©ZŽ}oü–™FÌ´¬8øNî–#/Äi±õVWv¥è[v@Ãn­ÍðhäHp-`Þ£èvr@qUªP¯´_i Çyhä,Žurzy UÒ 4ë(¬~Ç3Û"º ¿Ó¯g-Uà@:vîŽû‰ŽÆfíÓ—uåS³ ¡™¤I˜…Í—ÚMŽÝ¡3Y•p~IÉŒ"…yäãmj” .¸»…¬ä7)}¸*~ÁÐzá#M™§Û9W®–£°Ð?1ú à] 'PÞÈ«%6¤EýSlû¹§–­ Bÿ q ~JR£KliGšDi¦vk¢iǵ1=tÙ%°z̳lkH„\Æ‘Jg˜ŽÁ؉UHEü Iîa`±3ZîÈ éž`ÝOÃÚê˜x ß‚ôr~ó èKrk¸Å¾åïeÏÙŠ§ȆŬï^T)³Mdvκ¯^Å6>é4xóøšÔÚ95ÖceÈø•™9{6Å™%Ë1«·ådÏ|Á„‘š"TLX¼„F_ò·yÖžüËjø~<÷‹hF#±+åææ5f˜êë_'+—Ùû *“±ÃLí¢—wmªCUǃÙ̶̺ˆÒÎs–Ó§¤:ˆ<å Ö¬Ï&Q0‹º‡uÇiÁm=E#¤Õ$ Ø•SrÁc¡˜ïŸùn,°ƒ¿ù$_pÍaÈÏz¨ÞÖ<[€ªŠÇŸT²P\ub×u¾`V0}nÄqu{Mo£¡ ±MViý»å7,<ƒ¼;6ÉÈ/ŽyL´AzÞFܓ׹Vã7Ú›l9ÈÖÄ÷‘›_V«/r±òûÄO-ªk„ mBþ„ÛpÄ”¨ Ò5d²“q¶e.¸nÒ•}f­×0È­f¦1}Àñ^Mƒ©ÄhT ô*Aúè‰áw'CY¸ÎÙ‘;O­÷¿ë„Zf˜Í“Iîº1¾¯ñò™ñ06Úr¯ ‚#Q«ýÄ=Q9.’­‘«m ~•BW´oب.eB!0P'z–ìÍ)È”ømqÔ!~O\ÌðòAgZæœõ‚¾'ÛbE¬&Ç1$ñ.·.aÔ.o„CÞE7–ÿ ’ÊyJýfKœ!•þ5{örq€—Úí`9kéäf쩱®×ûÓÁámªüÄÉÿoÈÕ(LH”ö¿í ª%×FBë?«çÈ$æDô+?›Ù-;äçy\ƒ3 ö åK{ Gà·,¤/@E§zË~Ê> Û“ú‘þ~P}¼ÇsͪoaA¼x–~h í¹xÄ<[w)4Ba®:çS•+(ÉóÀt¬¸Å^¿xÚyH ›$롗ǃ²¶«›. ôxRùr¢”Œ>¦˜aØÖuOf A˧äÌ⺬ð22”LFE[`Ýre{:¤ÁÌ íû¬³±Ž>ã‡þKU‚û,» >Ç‹¤[PÔB0)quÙðc3q²‡i–’Fm¢#€8ÌqBp¨ƒÐÚÂ=cfd[of3m¯áa´à D&7ÖÓºŒ)QeOå‡óÒ?<îx´?öH ~è÷À ×*¬‰dOþ×sáéP”_³×Št` y³ÇcÎópåUI…ª"ü$»’!źžÉ ðƒ…~/-.«:^Läf_ŽÉÅw†mï4ªeZ€ÿ BÀ¹¿L4#œ•Ö-€‰ä®û0ç»ñèºØvå;\¢Šîumaô,[›n´aþ/zDtæD£ñ‹ž+Gô‡@ߎþ;6@ë<ËAÕ€ê¨6ï™i¯"ñ~ôƒ©¸<ÙaL°,Ì+AxDæÞ I³¥/óô!6h™KëL·ÕNR+ë›F·Y x!ö¤Q°ò%÷=szÂÆ¾‹­yª^²±s)YáÿžD1zÈçâ3:Ío}¥Ü:jf·ïg×ðx€Äs§¥FëJÞ ð0þDÝ[|óxKGbL'\÷úÆÕ»6Y·é¢ŠÂ.ðÜEPÇk¾«½ÄeƒBC˜ ò‡Ž‡I =ò„†c|þýßXf¢±F©£¸sÖ=·uæOÁé JzH·7œçJÔ°wñ-æ®D—çp|`-@WAoá#ÎFXfÀ3»ÁüþfÏ­ÝÆ©®ñîéV0ă|pIÖ¦Yí¡‰õ›=Y]ÓGzpð,}:veV‡¦‘bûN·¾Ž†ÍF.ˆ4qî£Æf°ÀóýýúYÁò`„ŸüyVÓnÁ^õÚv5•ÁgM]ß@â *Þg8§îíÔ…ÖöÌ™ ì-Ò ZÎô‰tí!MZIù_r1(0pãŸÏîÊ·ù1µ¦)/ܤTQ¨†„ ² UÌ‚5k¨V,|X‹h™NwìÈ(“£}ób”â>Á¥®Ë!™õZ{} ¦~Ha¸ÀDÇlc}”†èë5¤µ%öÄT¶ÔoÈl'ú¶0Í$'»ÓÞ<Ô$èRÁÀ»1 ̺ž`ÃÑ8…\<{ïÀÞÀ’Ïz~C=±¹°0¤xÀØÌgwoõžV3Êž3.ÖOC[Âýlsâ–· ¶¨øR¹‘èÌ"?ãUË´ÅAN‚÷h˜Q—GmD2e³tÄ…e8[I*µ}Ò«”¬ßlóæºt hˆ\ýv>OS?¬¾j§“vß[â¿ÔlžZÄ `Y+vÚïð¦;Ró‘L'ä<=*Š7_4M°Eƒs>7s÷Ö“À\7?Wó5k—€N!q££J÷YŘâõ ¡oìkÅCæ-í}êcŽ4gˈØfä?KÇ8šâ9@`lðàJö[BmK§˜¼þì¬ÇŽ—·^±#u¤~¼çƒy.¹Šô?•ëØ¡<ɾòÚQ­_ˆ ÚvmØŸJtZó—¸txAÑO:YEÀÊÈd³emEœ2©Î_sW®YÄ~¸çÌqø÷Þ.Ó‰úZ>ÀÈLJï¯zWêêÁÍNEªš!E.†ŒüÈ•#”É0v¤™º r˜jI©îdlj†m«dô«%£îÑ~K¹Úo;ºü÷‰Ä åÉæÙöR¾ S tK"…?65Ãk2BâTâ“TK‚®µÝ8"É5ý°hˤ†åFT«ú‹RðZ÷o»w!˜/l ’Ü3ÕKÿ˪fè’²g"u'¦‡ìÔ­Û> Ãr 4t¸;ùhº†ý.œ úȇ•8å¢xY­Ö¥®(TÑ!nK%õz¥ &º& ¾˜ˆ¸!*¬sIªa?º;²ò›ä›E+¯+5û-~{ÜȉÆu^gəѳÄ3Zð–¿;fgˆ!Íe'ò:éóvm àd³¨Fõ\w3üõ‡¹îñ¬hÅ­RQœX¬YÖ£J`ÖŸJìÒrÆéÆf Gv÷ ÝœlZÎVöIÜÉ—Ñ‘P¢s%S½Íê½qîØ½~Ïx)0î>gIìÖ2kcÔ7┘‰´¸è—¸¡S#¯h¬€}gŒWJ«OîÚo µ•ot þ™'óGh_—,Õà«b¼8øt¶¾02Ëè]§å^ƒ:t¤«ØKqä+÷Æië’7þô\‰SÈ`Ö§”wZùeE± 0ØÀ9FÎO!zéa9ö `¨ÁÁmûâ¢ÚÌ…VÝEÌ•"؇#ö>GçíIÒÛÀ7vEaÊJý_xxŸÕ±k0ŒH’ Õ#sü† ê~ª' ²É2ÀŠKÊhŸä«½¾økuð2…ßI¾¯Žì…Æ™* _Žøpb/“õ^8€ÁÔ®˜¬„ º¸2 „ëðÐ癩k=VÃ?³¾\Öⱌ ñrÁbßLÝ)‹¿u‹9à 0÷-–ýE®ÑÏ´Ýî(Õ¶2Ûm0>S$7^Rhgt”ëü»¿‰Xï˜ÜôùKõE»c|&û ÇB‘J½«±ØÊÃWÃg¡ù7ÆË‚qÞƒ[A€}9Kð1Ĉ²'àâò<¨²¦uœ”WýžúéÉwU9åòœÌúà|ý!¡MûûB6¨í2çº^¡ NÀs=õ_&ƒP€ý*Çk’ê¥#dÑL;Ë6©“pÂKKžú×w£ g«¼a}4~1Fžey~Å7ân±$VPåÈŒÉ$Ëi?@š &£Ü7Ç킌ˆjŽL-¹¦§ÂæÅ¬±/0’Ì÷n´gAmÙ¢bŠR Méû‡ Û-V§.M³}]ÐòvÖø²kÂEqŠˆº¾-£–dGTýOŠ­ÍsË_zsv›ÎÞ?P§äm Û݇G|?óéYùóí»¥ Æ|ñ}Zà%³àM¿Œó­‹qé4 9ôÛìê5%Õh:RƒïLjõçÔmJNìÞš~ŸÏsF]ùæ‘.ÞIÞµÅ\½ ͆ðZ…1%at,, Õè}6ÐåÉÞEê%KûY ~ˆ\ü‡ dd†3¼$9ò¥Ä<°˜¤Å›þ7{µÖ/Þ¹æÿy¸ÊÚr÷%Ê*5¡&Z¨RY·Ü5 ÷1~·Ä ÍÏŒAÿGÎŒ±€ªì4¨A}|{ÛŸ-Gú¼/å7™nä͆‹D–òo0ÕØ®ã3.žvÜ^ù-í:Zéÿ.ŽW‡3i¸­à±Ž}?`¦:å\>„vähÑÌXzs/ùÀ¸i¤ö»|B«ó_%çwã´héŠèÿ¦ {n²ÆcEŒ”¼§Úˆg±Ú£·#S–˜åÆžÌÿ`YZº¹o zóˆè¥ª¢Îß ¸Aü¬ñq¡24_G9±u\ø8j¨ïH0}‚L0+ÈÌ|χ¼1ÚKa:éˆNâØþ˜:X³Ø®TwSÀþ1Âû7{†¾äÒ[‰>8ïqÐŽY/n¬»R*ÃÇEdl#gt‰ú¸ñrâ¹HÇJÔ {öRשZRËBxS°r]Ñ>`(©á—cXÈÜq`OÊÑp°o’ÎSÝÖµ5øS‰|æhJ†­B<þûÓõóu fF7[nÁ@’Xt7mÚ:ÙØ‘.4n=!_l ø…!‘R^±½°e,QQ'›ÿƒ1²Û¨ì7‘c˜ûâ.{íû9 ¬ nÛ§¹iŠ»ëΖ·É®7-Ü~2íz–¶Cðζí3‡xŸÛ-;‘ «ÌZ„'<Éì­ge€ôÍà.?ˆSRÇ ìð`’Nµ#h|^. %Tk?'ánÖ‚<”Ä1³ÊÓÍÁá'ð:0'm+&o·4[§ m ¼Ñqð­æcmâN¢®‚êäÈ'`Âx H TŒ±,XÓmû \ƒ&± -Ë?¿¢ßž€A³$ƒ™ÐÍ +æLWeˆïàbכּéW`Í‹G!M˜._§ õ~5]o{f®˜Û¡ëYåŒ'žö• ,:T©º³üðØ©è YH¥÷¯ÎÁyÅi}5å|˨Å@²ç;ð8SáÀöÕ%h­7¥JÃ,özíjsº [t÷o(1|oþ:-5ó®“•i?Õã"%Þï”&ó¨ÞA!¬°X⨋8Š&wµÊNâTbÈèß• ™:¬ù,t2ðWóWKzô/Û\°ÏK18Š{ŦØÝëâ!Q Qßêíý˜}Ù“ÚT.¸Ãî…šWúcŽ»s÷X)dÜM§Ï0à A¹A1€ÐAN#os)Âwé]±Ná c Ú#mN{HaÃb2?ù68Ñ)§Ã9lˆôD'cê+`Àßü­OŸÃàêv«§ßÅS'ìÏYÄþé Ñu¼êó˜qðK }rœmd™OJÕ"ŸË÷ãé„úuÙ–I½Š„nkÓPÓ³6k|_ë’åž1»ÿŠƒ´(xé‰ã»¤7T\Gv‡Jˆ–Ù2× oðcPˆÑà}é¢59³™Úù\kгÀ’-Ë¡>¨åÉ· ˜U2§~z¾feå'‡6¬5Í Ø/'œ?1aš˜1|°&Nœß²Ì® CÑÇŸŠfö´4µy_¢H«A_‘V zÇ} Pa¯Y€RP¢âÛ‘¢0—˜8Á(2¶ÉéÕŠ*þE·W-ÌÜb;ž¡z­4s3È CëPÀ1ŠþWõ!^ïÓœN?çÿHô^pàÛÅ%-8H5ck3/w×yÚ æüû„«lÖ[Xò¤‹ÄÔ¤79ÇlÅ*íÞ÷û¢Tj6.ËÉŠH;,¨ûWyXs{(PÎ%ÙüŠ{¥]3·cÒĈm'¥%ñpBž>Ê`w_Š‹väÉYßGzEwÖÂìc”fÎÂæPæ‹3Ì`²…(¯* ‚{nx-ñØ„¦ª;a~ æÄ PÆö¸}`ÒOCª`(L±oÑû_/MºËö]ŽƒïYÔ¿A]õƒD²C©¦ZÖ&ÌGÒGÌâes.8ÂLì'õ5œ*ÃíQ£³i6{km’!¯. p/˜ˆµ±ëùÿ1‡æè UQ%~‡8ÆÆ2-ãÅ9¿"žÚýèÃöÍ¿Œq‰hðÊqb ãP9ܬáúï¯Ã¶0¡E¥Z,QA«ÉŽÿ/ÙC¤>Hr Œ ø/IJ2Ã^¯eP/óUVã÷2…IÔ©ãƒU |]SoÀÕ¹Z=½Î±‡'ƒ ÷OnO>ÿï|G86!Ñày[# ÁƒC¥#ø âY˜v'qk甥{ìE›em`t-ëéµJÐ!>ÁçºÛx¯—Äkާ%;µÎHWÓæ˜p‘“ãE£m‡û¥c;;÷¥‰9“­›¢ 8„è‘j°!£'ëì¯ÄF3§¼Ä§SŽ!>’ 院äÿnß=elRl%饕í‘T@ Ö€ Oª$ÍFüÏ©BÚÜïìàœöú¨ô š†‰+«´ºÏÚƒGÿ‘FmGØ2_ûôŠæß7DÈjå_"\h^Ñ@÷fø¾k9fÕ„e@Yú?N=LUŽT6V}j£-ô‘¬’c|ÉŒÊiê±§öw¾j÷`&/‹ÑA4rÀõq3ï0°F½#”øˆžIÖåP/´‡ùDÈrÁüG ðZ6áH^ƒËÄyN]ÖHCËZé´ÒvÉóRa2ˆ=·jî¼ÂœzÄêÒ”¹ðq’~X^2Êð”& ¢Æ” ÏV;ÄE=ÑH,§Àp`XKëÑÖLð\,¸b§1ÆÛ.œ›3¹\á«öŽ%"„³ÑånѤö`ŒD-ƹ'w î°¡Å/zŒ;Pð4Ú¬J.ÅÄE‘ìë;àá7,³ÃÜ1ûJzcë½o™’æ0YHèIÖåA ½-ÑpÒl×tWMV«ó>ŸG¬ß!À©ZAº-â* ¶‚¾H‹¿¶`Þøn¾Ê!Mò3 ù™'®ýE ‰{ÀÄÇ2sL€ |~çv4Èi7e_¨—»KÇœIsßÁ•ýF Q™Y´÷~cRfäÏj®8(Æò§ÅµýåÕÉãBšK•€¶™-u! D¢ps!¤ÂÂÊ“–é$ÙœÝiÅoÌ l‘|ÝBÐo¶¿˜ùF÷r祔 ÅP’|(0\æ>ÜW:9Ö°{BÒo' S Ü(>»©›™j>¯°a¤í¼nˆ*µŒg ˜—¸ ·|o²†—¨*MÕkÏ%ŽKGm–k6W·Í[|Ô¡Åd‰ít9±séÏuüóiMWGÝe¦µ`ú’m~¡#NÁ¾1Av¿>&žPg_†¿”ÃÝk_JMD¤þ|\¹™¡íÚ7Ò’C°>­Ï ’š–"v!m‘ ¼‹Q …OÄ’Ьº®óPgU×b ,9#âN©Ð€¯zÞ›ýtä¾GLÏëdˆuh´Ñ“ª=“ž§o·93¨ËùBð»¿NBÉ. «FÖÙªÅc¥ªÊÚó|V"§N{4feÉJ›ÑÉ Pݲ uÈü‰‚¾£—«æ€>îYõ4¾ŽŸRÇSI¡W#Dú]ž¦’…G8+á·‰„:¯äãKUý.!ú6 ~F‘µãpߨ›uÓ~`p®#wHjŒúÏך(qq,méÛ ”pº ƒ"Á…¾£ß,‡6¨º—ýD\–³=Ó–%µˆ`Š£âƒž5w(P$:#l 4‰U{=9Gœ¤v^NȶµÄ#å1ê'etÊ5›êÚMž".__tŸ{h¤ÃF¡Kæ%üÝ=í°Ìšä(qÍ›ZŒ!0]†Ž¨æùïT±U€vP½Ï¶4çcM›–ÎÌ EÈi–ÒTÕegÆ·:áoZÐH“GŽ:׫€Y†"_¿ÒuØ&„·Dê°ÚvP€81ÞyŠÕx®8K«”’[ùÌ L0˜ßœHÔ·í0¼pVÓçø×;~¶‘cMŠjˆ°J¢ÑpÌT™ö.!ØÇ˜Vrû½Ùlˆ~œäãÈ+Ñ~€/i‚•Ê>þZ^Æ‹<噌'“_wJö:c:²8[qEáÿÏÛ¸èNSç \†8Êxt–ëöì,Å·Þ•îç KÂ7‡+L‚ ÓyÂðN8€Cs*ê IÀøTuÌt±íŒ¡!ÐÈ4¶»š¦4QÍ…X[2#Šàóêu.À<ŠZ´¾Ë<9)Ê6P qï^»‹Â¿™„w±ÛJ„¡*†Š^#›îÐð¿ Nu1ÂÖøÿ6½á­ø_§¶*ý@%½¯É‹IÎPÿï;J=ÐíHp™˜Ò¦–¹AvWo€zÇK¼Ýéà›é¤5IâÄ­¦t%Wí¬îÉþZÀX¾Gôî°ð’ü-Úqû¨|W¦¢yBš,_éýÌvò/y°bà"p-‡Ö¾à.¾Ë•t^òVÿÍ÷´VDò¦Öøq?,!wDíÝ}Ö›²|y°šÄòmseâÖ\p¼‚Æ(ÁÚˆ™ [Ñoà‰!.’Ÿ¼úDwh²¹n²ÓÒP»URüYø÷‹ŠŠ\£ºë*O j©òPÓÍq¸GPåÿr´”žÕ¥Žcqlµºí#ÐÖˆw\˜δká?(ÕnòAeKÏð{ù*Dž äZß5œÍYúI²(ÆÊÏ£gì©þËîƒnò“³À„Mb„9÷l ÷'ÛiaŠ“Ë.u)Ag§*uÄs¬tV[¬ØÁtÔkh.º]ž “!†¥ƒÎÑaœ˜ÕúÒSÀÀԉͦhnùÛÝ·Ø8¾ÂÐ 5a–Ê‘O¯òHÏ͹êIÈq3ÅäT–ÆæÆQhŠ!_YE(M˜._§ õ~¶¹, 쎳Oœ¬øYÌ#²xMË7¯G¨”ëMÖ¥@açïa^VdQßóöTsŽ÷*ó̺4ü-—™S6ð–xónFÑ7†‰r:eÙßÏÃLñy!O’AÉhŒøAt Os’ ÷ÅÑ"…?Gf£=!&ÀëðÌaÛ…"Öš…•BˆÆfi÷Eˆ_}ó2]ÁåùÈ1ZGɇ¡::—qI°U¶ë$Õ“iž’T\ÇÚ©EhÁ_†§ãæ˜Æ”5XJ´jÈ©iµÙöÁE‚Tß(^X«ûÚFd6KÝ×ÜSY:æ”HAå¢ôs§û P¤’ºvʸ†e²ª¯qÆQݓ۾xÇ/«ê¯ÇÏñW–?÷îÿƒõ±IÌz·ÂAwf0á?|ùÓ:‚ P^‡Þw•K•uMhzk WÄ» ¼¸†¶ÎŸžV¾X!ϸÚìå¼X®»É¥ ® aÍ¿Êà‚+¯ÚNñŠ%iö{øŒìo_O¨ìçë1êÀ±àw %2î…}gä4^Û%fTcCº6W^`ãKÌë¾,Ï+¾þwò§_;9GÏ?Ë:ršé˜wE¿ÃNØØÙÍõ%s±;9hŽUì]¾À´<•˜nÄ*ȵ‘ò¸w_0Lù‹°‚½¤3Š,³Ïܯ™”ýÑö!ö$½"0x=ê§0¡¸3áÈ6ô´$ID;Žvr_#rA\£JF§“ŽJž¤ÆÞUð2f-ôëúé¢a‘ímiöÛJsI½,<(CryšbM˜—ŸTÖþyà]Òëbæ lh’ËS-LD˜eX§€/–TvNÊ’ ‹mHmšÃçýòd8ûh’r~탈zNõîÛ-©qS3{ª3›×tlðÕw Ïê©Ígó¿O?À7hUlÒ,:Jý·PšÏxÑvç¶8ƒlß½pkœ†Á7žÉø¿6lùY‡û­#m‰h1täQ&ŸD–”e"‘6¶V3wÃ)±Ž*¹få?*W{³[:µèXdQšðM~Å4¤V©›©kö‡fµ Aï„óq)z†¶]‚g•_Pcª>.º«Ö‘‚<Œ€2‹¢Vð>Û!á:¨"õÖú¥¦@|RŽ_ Ç8eØ8“E¬Æë© ã9¢ ä$ðˆÿ(ßå5Öþä\}O&Oß+cŘǼ¥þ?= ­,„Ï1ßçéˆ ÿÖK§Cöm†\IX>J#Mé‚K©c®ßÆ»l|§ ÝHC›FŽeq¼zñ-ßZŸU49)Ë¡ö0²´%xû«E·ºtÜF®»%0S8Ç\J󄸑¯†æýÃ'äühµ,`î÷kýÈ%Ý_8?¬p;È[¬òÐÃ5u—onI@ߣÑÖ½qõrºÖâ¸Ôâàž/†¼¢4Íò¢¬Êèw$G«iòÚ$&Î ¼—þ¨b`¶S­!Ã%„£ÎìšÃç7 Xí.‹:án5+£#Í Í˜åWfúO5WЄö‡>»Ûgyfœa>Ÿ¡¡œ~lç*^œ,ŠëýoËQ<R.ã7¶(9wóÁ“ƒv"múŸu­r®í9B+ýA 8ìHؼü©3éÑ) ÞÃ1öe0o&* “§kQZPÔÀÉ·3FNW£Vý‚n-{Þ<ájöLyËO<ç÷€Æ£Ìq á(CŠÿ·¨Ù:5 (¥"¨_RXØÊ7#%ÍÔ LÞ¹{éSÁúZ—Å2Tü•zûÃê€uÔA²®ÜØN#—¼š¨I}[ô_0JèÇ*Œð­²xqç·ðóF¥påÄx£1'‚;¥{ÙœªÔ’ükú1UhG9–q´2œG… ìšü'Ö‘1l†È‡´ô^‡÷Lû‰ËG½n/ÿÝckêÞ<â“Òô­š9ö½éº<ºøçô=¼x68_|1;OdkµãƒQXÿ ‘» å'ùÎÙðnº½3ÉÆËäÇ—b›mÓêØeå×~æä/]íέÂûQ!Ìî7 B)@¨Ãi’ÉE‹Ð|º< fäÓÁM‰OݰI§M÷0)廄¼ï--ÝuÌý·#âJì“çŒ=LHðX"L1¤| þ$gáDZ^x8p 4yUvžõr€D ¸A@]¸:®¦5ÉpÝëôMS™Û6ÝÇ_÷m«\œL‹¯ÕûñåÜñK°ùáì_Ã]òm4Ò‰ÃE ~ÀK!rdz~v‰½\xï·d¿Èmþ<ä!´h¤sYb±P“Õ͂˘ÁëÁV‹‡÷°â—¬û˜ÓAµS•+3´fŸV Ü<<‡Ó͸°(ÌPœ¸W,oŸÓ„HÊŠO·…ß?¡t^O¬´Ö¥†!1Opµ‚¯²rÊ߬tš˧åñ_ÎLáÙû1È vÊ)ö­®ï^{­î`›&åD3ŒR#³íž&¥Þ¾|RbÖþCËØú\…m|•ËiwͶìöçÄíUÑø^šýjÃmCk‰ð|~..û*…§Éòà¢xn••NñÙodÒ܈Q‘H쎋(¯‹G/éı*ëc˜»i­Õ.säŒÊh}TÔŠ°v¤”—[W^°=¢½_ Èä·tÇ‚9Â/ˆ²vå¡®¥¬4µÅÞÈhi½dÍGžÃ˵ÿ—£觡Â’]ìaP&ë?œK8“ßN%4Öôxx09åÈÚ7y³S¿\t“—RBf@XŸ_½1’Y¿ŸŽ‡]·rZ6GuèË?e¡¹,?$ÔÔvrïCû¨6ŠÁæK¢ÏWéÞWÞÔ·ßâ¤BNú¹› ÊòËÀ}„¼]dèÅx2^”F잃 ù"l;œ`z=–ù¥cÓ¯Öl‹B5k¥ƒì$9Vu!ñõ>Gç!éÀIÉf˜äYWÖ{¨â ÃG㘪öÃ|°Xi.Š‚ù~Ÿ¹eÉUQ’wr€=–¹¼ªá_C±¶ü•ej¾Odv3d®ôNl….äíÙG¬õÃB?Ó~XmAOÑFLR¤€éÀ¶X¢Áøf?zÑRùIc¾îörs²8°\¥Ö)`èZÂEKfþMÚ“lÆ# ¨¦@f¬ËlßË­ž©‹f‚ÆfÎÝy]óàú¾$ÎIàóH삘±ó(¢ú{kÛ›—è¼€¤]å³RÆác98úuþ±ON9ŒÂO@t¹lFU[V\î¶Û£ç‰‹ÇÏ3™åõ¸’tJ5„ ì;Hæ&/G®KàŸ˜óªâ(’†–êÌʯ´t­“Üfë÷Àût»1bÉMTµ]œÀ«Å^¼…¨ z.¶”æþÜûâÊrPYæ 0 ¢ØÎ $ËND˜³Ÿ€Ê¥€êb3$ø¤LÅy¦ß–:gkûcs[àyZ½s™)ïQ¸v§Yâ­89¡WÀ1<ðÍ)¬‘Ò_û9y`8ü‚÷³B:(ÛàÓ¹BáÝ{ÅQ\ËoÖz`<>òºj3%°7­Æyg^g€Ç²È,þáÄE2_ê¢'X°æƒ£ëj¥†eÅIß–ò§ÜºT缸8k¥mG¾+\ãEWÖÔìš¡Q.4Qï~ʲˆÓAµÂ±Ö(Ó¹íü×£O2[ OQ^»ÙhÅŸð6ûN ðÃuK¸1ù ïþ:þ’kÈj}XvÜäÇUo¢#U3ÕÙ‹VnÒÏò£5Øâ^ùgv’ò’Õ¿Y£{¡'¢þ4¥CHöe;Ücä=õe«É|s‚Äb;ØRR5ÛqçEx&Ñý¸Ð)P§Ó¦×™uj 0sÏm*k«[Œ"VÝ9OX¦œ'-Í1Å<Ðû0MÍ®Ül~7íÚoqë€a¸>_˜sw«x[‘^^*Ovq¶°Tq¶òñóùIñ†‰&˜iaæ]y¢Iª>ʪ)±Ù&ªD;ksè ôŠ2ò$·´¤KÖ„7m%U ¸ÌñºÛË@Ô!;ñé` ƒ, l@Iƒ€…®¦†ïaG„Ít³K“ÒZ눘$Ö¼yê:c¹·Žóq†4ö¯˜â84³ž­èäSEÆÏ333\\ÅËmÜs“ò›M“°ÍL³™¢ÏX+2H?«æÎÁåµÌ H¡®£S®Ã뚟IÁØ&ºÀÉÚ‚bGÈN·\W&ërŸ5ÎßRñëN^Ï¢Ù¥XNtU’·q’ ¦YäGóYT]³„Â=ù_lêFB~ç.$Z Ûa×–„Üý¶K B-ñß}x@ WK‘•pòåðmr”õÝt†ðEŸ_¹™tqß™xÖ“SÎV:ÿÐbþ[$‘oþé¹ý¹ø\ "ëòõ‡ ïÁfßÕ34N è ¯z®Ô¨\“ÑyµŠ®M\#óZ–°“Ø:ÄX pztŒÉw…=±òó¨ÐŒx\VK®{8éøfFúë¥BM$:¨¼~óƒì „p0÷R,àpV×Y=6t®¶ùgP¡ëAˆ¤)j~Ê&×Äùl1êÒ¥?5Þ#0‹škÂGfÙ™ ΕæÜ¢Oç^÷VgÇJvhqke¸ÏÌ!òu©„OÁɹ‰„n–…«´v1çº^¡ NØ‚z†gã'S;Á£îõ;e–ÃÛÛÛôfEÕ˜þqPÁûÛö ×h¬n+âê%+ w3)Ž€ŠùY¬¤ðf Wà° Vv ^ö¤Ÿòªïke7%QQ­ÿÊ9¦ =.M»¦|Ýs ”Ÿ0Q¼Fo‚‰AŒÑò4LP¡"ɋޑJšîÑ›Ò/n ¡í‹ìéÍ6óð1@'$-˜*3G7›l {$óžnû¯ )GîK{ÂÓÔÔ•ðöe”ÂqOÜážz5Ç_–Û¯í÷2nõÅËÉòPõ‹e«t»’CdŠâV0›'•arõÖRø´,`O#C‘°91DÕkáÕýIUÕÈž|m´^½¢Ïwò'ާxß{¹v?GEmé·¿T¦ˆXŽ\!lî¨ãDÕŸ ;õR7dk‰>µ"tÏý½Äñ¼Ÿ+gÊ`õåÉt¯¿ PCŒ€yÝtÜe]dqÒ";ÐÐŽ„ÀñN…Vðÿ²2\ÙíýIèGqž÷lì”ßPð]Þé¸'-Jìƒrˆ7‘±¸ÞA‘^Tßgßp"&SÁ<ÞYËoš¨8™P½ï3ZnŒ?´¥-Åï~5ñ¶ÏŠ]k@¹¶”O}ø Dbüj0T Sr8ù LšË¯Þ(z2ôfwóƒ—±„»r÷ËwÕÀ•ïžB•iz[0An^N6ÙÅ>vû!iƒßa)&B7 \·z3Àâ°Ž‚µ‚ë+þx»4º [g !IÈ0iÃ7½øÜ†å ÞugSŒÑPvÐx©@ W·ÁIh­›‡·éN%OØ”¯žÏUA³äê’üP¼rÿ ÁÏ‚ “Řu¨ôYï*¢ I¾•}定w„Ý—AOá€0÷œeþ$r™:œÑ ™Õ¥þ»tùV8 áª0÷X5h5¯l¡{’ËS¶.ôJ¡’Í-ÎEɇ;CŠÇm½§”^7¼9…ÆYÜ;‘PžÅmHú&éhkʃ ûœ$Ì“¨—ò$\Y\‘áeZ‰É\·³bÝÛ:T9é/ï(r,ñš8¦~ý$ˆ=· Q‡ šÝ”;!þ­#·˜É…p†…Ý™ §JÖŽ¥¶†Ф‹dË‘›'N§ÙO™%X6²ÇŒû×-«w]Úÿo8ڈǂ›°7yâROFË©˜¤à‚´†{§<ŒÚµeô~†¨2.žš"Èîa¿]hDßG$bC—¡¨­bZB€ é n¼Èõ&©#À'ôe'˜pʃr±žAñ.<òR"1£ìåÂÕHúØÃö¸`ú*¡}b> èL䵟˜•ìÞ’“-¨úÉ„ïËEV®%Œ’‡´úÓœû£Òtw8kf!Ϲ.;ÑT¯RÍà„Ú<ž¸¨Âî¼ezÁ]ÓÃÕôÅ#B&O$Úªª¹¦æm†ÙÉÖ=²T+o øÔžD÷[É6°ãÀ¤+Ë%º›ö)$ÅuACd@G§ Ød¥ŽuÚµ/$ß¼›âBO&~ÿwªÇÙ”·08¿Â[Sͼ‹­Ž€È m¼â¯É8âŽ=*ݾ®I?íÓxb¢9PâGÀÀPÑd÷:ŠDYhÝ”!xÒRhnãrÂbgQЮ*´>{Î9ä?EôeöôÌŽ‘>ʫߋtmNþçÛ›Ë1N†î¬3äÒBÇÁëß½­«Ý‹ö ]; mœ/ξºÙEÈÏ^à °®LÔð\‡9Éaë6¤-ܘ‹Ùä<‚0îÖþKL&JøÎºŒ¼®¤Hµ@%ÀDŸy*.ºYu–1Ø áÛæðb–DÜ–¦n… ¤9Þó}‰šÍ¦ŠW!=ߪÍu¥$(ÕÁ 3ìhT€ü’ øÒ»Âæ² ­$ØÁÌD ­!3©£ëå6fL‰Q0‰fõÁ‰¸ b¢ü›`*Xs ¼þû@ê=Ó=r~ÇÁ øØÏŸôLw”F/†<èáh»6Ýr$î Æ—T‹þ| —a“މW„¹×D$ÿ´žbX›4´ÑµˆÒa+¯µZ&)ÈW$ÌðÀñN|ŸÓ—×ÃcÎO¾¿ÒŸd4}Ñ*þrâú¦“bXÏà;´ÙD ¸Ü+ž Œµ}'d=ZD#PéCâ×ﯦ€Ð’“b(tëÔ&ã{(Ù´½WÍÖgx6O÷+P—cÇ™ÃLæj>³€nÅGn?(|ï\¥§ q¤ÒÁœP•aJÙƒ âº¢ÊFj>©¡ë³M"ðsçÚì¡Tb])‡¬Döò1¸gc~%qMª^“‚÷wTÏöŽ.§“ëÒͯæ`jÌEá`jf}T&\Ê€«N’qîZ%y›ØVª°è™hô抈¾yP.VÝ}Þ]Œ ™C‚è2õ71ô!Ÿm îl :j–öJ/ ËéÝ€‚VÞðoÓfya1 ôË÷Rã§¶ÝçÌ”B ·æã‘È&N/êå[UÞ¤u# ¸õf,7Ë/·Ä±@¥/cc–ïn¨ú_EF^„ìTäF¤X6¼Jr€I±ñ j©ä­£"#Ärº|wãÍÞ£8_îRÕW¬›þ#;­¾:„6>î0—Õ±#ÇÓ©aZ²«¬ü¬ØÜÀÞ–Sé\ZÁÁ~"_ÿØÊõv:”˜ÑÂ3î7’ïÄó¶•¾;Í«üO%‚ü+q¼:JYáo£í¦=#Sü7†  .øö< W¸(°0Ìëû’ͳù(®>Õ^ï9œ¡‡ÖØçÿL*ª£NmGD8¿>̽îÙäåµ¹ñ‹ÁÉí~§8õ?P¤²]Ƹ¶Ýñè%\{¤Å>ƒ]M‚V,¬˜´õg¹ŸMIߨ!èG`mp„Xð?w'ʵêõcvëŒ=Çå£ÝóKZŒŽ›5+ÜašÏïÛ uz W[OÍ»(Døÿ£œS½ŠZ¢¦ oÈrSÅIÝ~v¥ÃÏoý¨H O¢á"!ÁZàt<»ðÜU*¶Ú£G"g¨mŠ ;jVl¹–&=ðοUûþÀ—dлW?—Â;OÎ-†–K}mÌše䢆áb:wæÇúW¿Ãr0$â:¨„½÷wG».¥ð“æÈ”ô×P9›!bìp¶þó[ ¯Ð± ¦_)/) èKgšK-ŠéØÙ³ÉšQabŽx[QZ.)G•z©£«…†[ò7瀃‚­m[ÿ¤Ì»jÕùÒ‚¢tβ®[dPªÉã&s÷ TS¯Þ½±®‰%™D±'ØN¨àãeÄ'²Öœu¤+t}L˜>”¾*¡ÞEü—„cžÓ½È}œoJâ\‹‰ð÷áÍ\Óé†.1¯‡‡ÌÝÂÑáA°™žè»yÁT¸G¶îyáÆZãLÚ\Ч;yD33éíý(Þ.µWÂdsHuÐVì ]K Ú*Wò9Ö÷¼KÞ«5ùd]÷–®—ÒÚý{‚®©‹ób:Ù{¡£_•`à ÈF2Á9̪òC~Ñ3Å¥ YVµ¦Ûˆuòý•«>+×aÀ¥5ì¾wꨥ§qÔtYV+£ˆÚ4”ð…<þN´k‘î“%_#À¾7mèÏÒêR.­¾ñK?ʪû$pxzÚrW£FÅA|;Ÿ§¸Á™ºG™k¥™é÷NùV»ƒIÞITбá€'ù,Ɉ,Û¥0éy\¾ët–G]Ì»Ou‡r{dÒÕeÊ‹6몪~í ,ÅŒŽÝ«`3ùm$””‰•®5rO¸ÅE¯‹Ó)tRº~¡ÊÝ„ku)t{ŠÄ‰ñl±/lws<óú²<ýuÕ, ›‰axo—ÕBzP8ÞµN:b2zÔ‡äÌ7<àXEnïH³¹ªv?Vÿÿé¾™ÖÍ̉=3ï1âx’½ÊÑôXÅÔý±„ñý@udȱ⠋|Â¥[VÂõŸlš -m3™n°÷Ræ¾-¯;>l¡CHK‹%õÙl]s-ùrl'=µ§§2ôhÏXRŠž·@¥ˆæ©'M«e']v·óc*Ö„¹s9jƒÿPXÒ¹9àÞðs‘f Ê¢dºô,ÇcÞx¤»~Ì™JÔ½eÑ"X0è#Ar\¡Ï«|6¥¶ƒØ ·Ÿ?“¾¿WT)Ͳ÷¬.ø,Í„– kTng÷±*N4E&¾xŠB†¦ ò/ɼ%¹O'œ­ehf$IIȪ¿ZyDÄQx\Ä à7T®Q€çʵ‘>òL˜<9ŒU™gÇΦÁåGý÷º^᪛ìïØè&gÌ9<P…Öó<ðÙ·…± QªíКìV¨žg☌Q¸s¦$½MÚš¤K,×|6ÏGžroF6ºd¬Ô³„õÊÔÌuW%Xѧ<'ƒ±[+ƒ2Çã‘€ÊuÈÝË=¯‰%¹©WÏ{± ” ¨Êœ¿™éž«Rkñ^?$bWa•h.£cstn/,ûs?WÍ+c^¢LPܬqBjã¯úæ5í#¨ñB†ú–X…EŸâP»UosOu ¯‡÷‘ŸNHY*!i¦ƒ/¾§e6¶- çìâï`ýU¶^sr…iAá;2q9ãëŸg¿vHᙈ\ÍÁŽÐÍÆYo®.Ð8»ƪfRæ?G9j4ÜÛÐ&‡ ôT }h±‰°åæ¡EÔ"’ UgI@ËJŒXˆçµ"1I¾6ý¢®ÁŒìª[pƒís鵈ìöÖ L)/U\XUÈçZ™ŽÕz7 ìéKšš{ØèÇ.<É»5 Ltpwrëý—Ü®óÝÂ)›Í,ª \ãEȰyê£È¶¢à)Šù^]ü—Òsnþ±ã7VÚK\%ê4È£‘"Å+|?Ç=±aºø}¸ÄU‚$Å µI—NO{g‚?¨aÃàä[YHB$.oùýzR”Ú5Ë¿7adÅQbJ›<(ç Ùö¬êÕºvU @0h¿©ª[Â98JA^Xñj!áìx]—–€jEr£lH1¹H& os±ª¦vþDêÏÁ Á´òöÔ°Ð{ÀUsܺ¯¤·'å]Ô¬e‡™ÓlÙš)53Þ"²™ë¥~QÊuöýHñ|)Ç”YFf`¸„dÅ<ÿt¸¢ÞÆmÇf‡•$K™Ìmš!ùÊJ‡HjÃÅS]©«àŠ­! jJPï~Ü\‘ì™d|âµø:Ry†¨}<7È7BºNHÛYÙâ1æù+#ª $³yó“A>gç¨üÀ±Á°©î5ç²\Ci¬A/CˆÏà-iîð²–E% "YO­\Ô(¤ô”Y3QàÝ„¨tË5Ê¢«\7˜f¯BwÂXK Ã’žæýmÎà|4«’áishÓ%ûúà›,Û„³@)>/Ÿ±ûÊa³®ŽôàŒ Þ3ÆßLß4Èʵ]è{rõà D÷f¡çbü&þ²¯W¦G¬â§ ®4]ý…kÃck‰dx\×ôëïì–²àIñÓ?ò~¥H`Ó„¶p ß·YJß` '†D!wäÒZ@~à‰únö|ÒÔˆp’ÈÎÇ›ÞÉø]žIV¿§- Y>[ˆ*C†Ç:S¡x.ÙLéGÎâ2{§½ ÄCd(®þ*‚[hzEgÀ‘‘§DJ/J%õ| b¢ªÐÓŒ \±ÿ¾}qg£ªß|Wk5ÂUG%nµážP~ž’Ñëw{ŽœK5ÄÚdmtHmÀZ R©’%Ùðß{.‡Ä*Ž|TBùù¥9‹áLõ¾Æ%Êä˜ ,ùYcêŸS%Öiàú­!’ž'œ—0ÄO¬J6Vvþ˜ }Jç¨D®3o{ækå¯éb@PÔßÚ%{|<úÌíô‘\§ˆœäP+Õ‰T*€%ûî*DŠjˆ°J¢¼©£ìgR_x¢ jóâ._ÑIôÊÅg¸YLªúM™”N H…=|©²!0¦l}*Èöý!àY»ÃÒAB L``°u™÷—Ñ‘|<-™¹ºÂŸ…X†CE·d¸œ0É.N£ÀRÇ#»5†CžÃÄá I /Ëÿ÷ï¹ÕÉþî‰"H½ ¹È¯æ°¼ð["åm³Ö(Ö>T*8ðÜA²¬åF f1PŠQ2ö¸MR±0ÌÝõLdTA¸!› ¥.¥PÝœôÁcØ}W–l#p Ç[”$F›Y¬‹x(Af´3¦Ùؾ{á 2? îR<ªcˆòBíls©ƒ¯Ï¸%ÉN#NOÙ—¢Cõ³kž!’1õ¹VFhN¿½ !Ö£š F½Qå±UB·DÚ%F(œmÃC,„ëwå‰QvŽëV«ªÿ•Šá~’Q÷µBã(þÜ4‘,§$Âä¨þò;~ÑOEÇü.ðæMJ³µÂZA¤f½µ*X úëšeóðø0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark endstream endobj 65 0 obj 22483 endobj 66 0 obj 1636 endobj 67 0 obj 20315 endobj 68 0 obj 532 endobj 69 0 obj /XHKPLQ+URWPalladioL-Bold endobj 70 0 obj << /Ascent 708 /CapHeight 672 /Descent -250 /FontName 69 0 R /ItalicAngle 0 /StemV 123 /XHeight 471 /FontBBox [ -152 -301 1000 935 ] /Flags 4 /CharSet (/period/two/colon/C/I/T/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 64 0 R >> endobj 23 0 obj << /Type /Font /Subtype /Type1 /Encoding 46 0 R /FirstChar 1 /LastChar 255 /Widths 71 0 R /BaseFont 77 0 R /FontDescriptor 78 0 R >> endobj 71 0 obj [ 250 605 608 167 380 611 291 313 333 0 333 606 0 667 500 333 287 0 0 0 0 0 0 0 0 0 0 0 0 333 208 250 278 371 500 500 840 778 278 333 333 389 606 250 333 250 606 500 500 500 500 500 500 500 500 500 500 250 250 606 606 606 444 747 778 611 709 774 611 556 763 832 337 333 726 611 946 831 786 604 786 668 525 613 778 722 1000 667 667 667 333 606 333 606 500 278 500 553 444 611 479 333 556 582 291 234 556 291 883 582 546 601 560 395 424 326 603 565 834 516 556 500 333 606 333 606 0 0 0 278 500 500 1000 500 500 333 1144 525 331 998 0 0 0 0 0 0 500 500 606 500 1000 333 979 424 331 827 0 0 667 0 278 500 500 500 500 606 500 333 747 333 500 606 333 747 333 400 606 300 300 333 603 628 250 333 300 333 500 750 750 750 444 778 778 778 778 778 778 944 709 611 611 611 611 337 337 337 337 774 831 786 786 786 786 786 606 833 778 778 778 778 667 604 556 500 500 500 500 500 500 758 444 479 479 479 479 287 287 287 287 546 582 546 546 546 546 546 606 556 603 603 603 603 556 601 556 ] endobj 72 0 obj << /Length 73 0 R /Length1 74 0 R /Length2 75 0 R /Length3 76 0 R >> stream %!PS-AdobeFont-1.0: URWPalladioL-Roma 1.05 %%CreationDate: Wed Dec 22 1999 % Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development % (URW)++,Copyright 1999 by (URW)++ Design & Development % See the file PUBLIC (Aladdin Free Public License) for license conditions. % As a special exception, permission is granted to include this font % program in a Postscript or PDF file that consists of a document that % contains text to be displayed or printed using this font, regardless % of the conditions or license applying to the document itself. 12 dict begin /FontInfo 10 dict dup begin /version (1.05) readonly def /Notice ((URW)++,Copyright 1999 by (URW)++ Design & Development. See the file PUBLIC (Aladdin Free Public License) for license conditions. As a special exception, permission is granted to include this font program in a Postscript or PDF file that consists of a document that contains text to be displayed or printed using this font, regardless of the conditions or license applying to the document itself.) readonly def /Copyright (Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development) readonly def /FullName (URW Palladio L Roman) readonly def /FamilyName (URW Palladio L) readonly def /Weight (Roman) readonly def /ItalicAngle -9.5 def /isFixedPitch false def /UnderlinePosition -100 def /UnderlineThickness 50 def end readonly def /FontName /RIOVQB+URWPalladioL-Roma-Slant_167 def /PaintType 0 def /WMode 0 def /FontBBox {-166 -283 1021 943} readonly def /FontType 1 def /FontMatrix [0.001 0 0.000167 0.001 0 0 ] readonly def /Encoding StandardEncoding def currentdict end currentfile eexec ÙÖoc;„j˜›™t°ŸÆÌD[ÂÀ1Æ…p§³T¤¢€®o¿˜ˆà9«`ü¯….´Î:þ¹yÕêpýäJ*åÈÀl'¿–eî¡}#)Á¢Ý&»7+å‚/^§ ™ëWŒ{ïÔLßZ60VåáÌQR^¦üλ3rï÷)€#v¢€$öp~c—²¼´°£êë&“è÷ö'ÄÉÇÆÅ¿ñÁä+ž %;a~•ê!”ty`rô³cþúv5øb‘/¼W©¹™zî²#gß|fà‡ ËÞSS°C޼3R>›NnÁ'Р(ÒeadÌ/³¾•BÒ¡ ¢ÑnKs­Ò¡¦ï°êß w8H3øETzðÒX‘H£W‘}ÎàæÒó±EpúÔÚÅsg“¾cxHSAÑB±Î]& *Pí>9Ýš.‰ÎTZwŒ½¢^±q$ÛšÎÊS²Ï ¾·QÂgÉX¯ušV,Ð’"ª%_â /w!¦•ÿjßTšƒûaù­¼ÝJç@¢Æâ„Pq[¿vÜõ·ÐM~³ïˆµ­ZIêf ·†îÚèè1÷N4Æ6{ÉAö"‡Ç€ôޤò<Ãhú8ôØ›Ø)¢²¼˜Ð—Âæ¯xl¸aì®-Etö T"ÿ5ñÚµ^1z=Ê̸õe.°ä`•¥Éâé`̹–å,±âÀl‚Iº þõpïpšäЮ#QçrWJ^URòlUïQ6ë·O {Àµà6OQžD´;•Dn ¹`]NèIHΣ{¦ü+¹à×Î#ß逞(BUndê/’‚¶*ƒ ÓošâÀxq¸Ýð{ïo1Ø1«€Hÿ(Áä虸·ˆãÏ–à ¢Ÿ•[äävå ™‡½½i•ïÓ'¾²òj"E`$•Ì·…ÄИ8K¦°iÈbÚîjë{äÃ0eLáÂUluJP, ãiËÙfÆà'ÛªhŸÉ7 › ³®$6â༊:f‰W½<Û6 -%)p\àÏçèeþjÊïÝa—ß\" ûÿ9!œg‰Ç @GˆLmúÂs0½_JEn|‘&$SÁ…Ÿ·úÐ@È\mèªÿý<؇Áu®Zý=½]¡m€jX “æâ}i·¨]ÌP»Û¸ˆ]…à'`€ùL¥Õû}½ÏY>ªÔ;h÷ñŽõdã¯Èg ¨¡û‚ol^k¨‡ i‚âŽEb¹µËЯ'ÕA´vàÅíYqe}¼±ØnŽ—PÞÔA 5Ñ]«X]a¬î-ÎæñÞãš]3ÎÌP›ì|pyjEK¢uýOLÿš8WŸçç¹¢òîîa÷}§Ýª' Ù( 6Ö˜sX·UêØb;Q5¨Û—¶¿ökÏj…ª1Á¸À±t3Më”ÚÈÒæ©eê:¹Å”/ðm–»d<‡Ý”Ê+±…Ò WZ‘|ž± ïSY²Ú¸yz#d馊>RDº}Ù~>ñÜ"t°?³¶‚½éÛ ð}=ÝÞ@®φü‡—JÐJw ôÇFÍj®ËìæÙZ+zDº©M[«ë·{IèÝáx`&WA 窦ZòS_¡Ñ¥ûÓÅw9óÚO1]å ëUÓþÙÎüOÛçNq6ïNLC¦sßäÃS¢yw¿Ç‹ŽºÌ-ót²Í¦DÇžtñe@`éliŠcôå?Á=Ks]9ÀAi—>1…åÙÐmS擈ÏÀ¸cÐ5” Ë=ªÁ>nÆ~±Äx!ÜWDXÓ³þfu!ÕæûHãû3¦‹U'ÜìõÒ`À„:¸;Ì)ñF亢¹˜ù-§°T 4ÈFè¾ÀO‘7¥»† &‹¢¹ÿ™Í‹†ë£ÅX¡‰%íOu…p? ûpãz¦Â¸û× …žMèœ2í(Øí*ZrâBYévT27U¹jl‹yÒÑšÒé`‹VOe·ÁvŠ©Y R™Ð(~€[JèYi*¡£?š=ŒåÕfTT7Kh*0WÕD~Öž–ß6ðãj²Óšù1ЬQ‡ÐZ{ëÿÿ»td>W¯v 1Õ[¿Ú ‹ rûb²K=륄fÞXƒ.`ÂîŇÑ.(Ôr Þç Ž%=ÀýÆLÎcþˆÿª àÜªÆ à©Pw¹ËæŒÿ€î Çæú·×'h\îŒefïÚÒ€¹¿ZÊ÷‡ÈB¢] °¹æ”Ýg¼¾–×LÒ¿É) °¬{‰ñãjÖ¶nþÛE%žårœäõ0Gäß>"ÖŒ™ú°þ Vˆ]œðÙ¦ô…û(õ£rœS ‰ß3–Š sá«’¿µKT¨cí.ɲUäpÒtŽùrý2é¬ÝI@‡Ûz`#úäÒUšZúñ6ì¥øT,˜Ûi±Œ•([¡·¤@ÆsÖ%Ã1V›1Æ‚àÙ£»Øp½¹š®¯"cá?kíú(Á‹Î‹ª´]L—4ò-ÕÙuNÙq{üØêÕꣷ™]{`\K…†ü‡¢Ë\¥ýüwÅX"ש‰‰;Q'óP"–(ø8œ¯87BAYW–ß,Âg|‹ìúõµÇ©’V¢ƒ.LË7|ÍÏ‚žëðãŠ}=2m¸U.|_;<º;9P¡ ö,}¦Ô?¡á7¤ dÍ7öwÿöòt3Þ(ÛF¶èWÉ@2£>‚ŸžíËU½-Ǒҟð!°ÏŽ^Qѱm2¤@b¤,‘ÿLqüzž6ŒÀÓìf&]’ìYmÈ3H¹ÿC:’‡Vü›ãQjÇa />ùð€Áú}‹9L*¿˜ú'󯙵Ò>Gga`&pÌù°xepšÉA~&ï/Ý[Xs\€.±Ú º¯`%k#û›éesEƒï_‚Z_š?«2IáÛ¨ayDc´àÑÄÕ~{À+t`ÉJͽ4œ½èmÚ‰”Ù<Ë<pJJõ?}̉.‘ú¨ENë&Nf'˜w5…ê^M1jjCyX™˜_i¸ScÉL²Èwã¨'rüÿi¥¾Žb’2;À˜¤¯:ÿplQ#ƒÈ“õ>|+£åÖcP¬Oy‚ŽÌ Á5ÜC_F囹I§X½‚­Ð:°Iüôµß+ûžåB°Gp¿á„ÕÎBîZ4ü+ãåÖb!t½ã«9•bBÖux¡Ž¹ ¾·~?>¼Ç;µôOü¿@™ àýË«ùgêI£aÜNÜLåN.-s™öÜ\Ñ‘n<W«Û·.íXð‘ù[ª¾ƒO2¼ØMާZ=oÿ,—4ý°ŘÙ+¬ûÜàG#ß3·ñn¤¡“lI¾6"öêWP%I°°Ò¯Ìšª©²x(©p{Ÿü5@¹Õí•°‘a@dð*˜ $$¼Ö¹žL—Óïò¾¿‘Šù'øÑ–ýt”Ö vžÚšŒÀ›ßßÞ=mfn4‘g*òWsIPwLßÖ²±ˆÜð(8®þ‚9ü¿&ü]÷z¸ Ý‰qRIË}HÞƇäÂ@÷ép?{U¶ ~sÕúgâÃ,C«nkcå»úf N­•ÄÇ'_º»Òãû~lø¨âˆ£ /ŒVVFa p&+ VÕø²Øâì³çÞíéÒÏÿèåÖªo=h@[²‹Óv`Ìrj@d™›º°yBèž@nE[ÆO¸ž€øH‚ÙÞ鬧MÓqËÿ&·={è±°/ȨY`§YoëŽ"]Jpž’s‘­h°¾ ÍÊ•}PT0›y(TÌy—„žëı¾â øÀóZ‡ôL—œÇǹ›öÌ,Ç=³;‚g¶kI³K‰”˜×:I"½~5ºu)~tã´ÌÚoïE$!¯ ÚPÈbÚÏ“Ûw`bå&¹Ðy Ö…ê¹7談Îyk. ÎÛ X5YTk"Ï› '¹“ý¤Û+„òòÅÅ„É둜÷ÛóÞ4r !¸¦¯EZY0ëΚÂXhp /‡sʆŠ9--FUÐeË—×É’£MŒŸ“ _ü‚¼Nù=T“ÛÈÓƒ10—6š¤Ó6‡¯Õ¥Ö›?üÄ›{Ò?rÚ€¾ú²séAtP­‚ /ãCÉraÙtÜhÕÿ?¾ûŒKÐ@6@»y8P»Ñ}N_ð4ΦÍù˜¹>k3—O¬Ñ`Ôœ¡³BÏgв¶Ò@{™cèš È?¶¢¨ÝD š£È*äL:7LÛZñ gŸ“ìÜ ®Åd¸ý ±æ¶6*9!1û–ÁLK?M¨&B÷È3¹Œt±T $ýguE4F?%×Ë(b,l>ýA M¯Ë£ºî 1­™¿Ì–µ\u˜V+û3þë<½P ÞÑŠJ Á“xÌ7 Ë$9”®ªQ£ |ž›tþ«96î>¶¿ç3*ÿõ¥µï:õ]ϧfª8sZÌzÔd%¤™$ Ë´ö^u…,qY,¶Ši’,Il´ïã¾…ÞI ¹Ó÷*›"0Go5uÁ©^RyiuËý°LÐŒ]¢·„Èñž1ªE:gøåÞ*Áä‡XÏf(ó‚‰l“^Þvе‹¨ 6 (Ï~ #µ<èY {ë¯'óëÙKÊãFø{0?K0¥³#~.ØûlYN›-¹ƒÙM¨^F£οÖÀÌå€-a€#§7r´1Æ# D`C¯àbé:}‰H`¤_ôò†ƒÑaÅ5E˨î¹WrŸ¿òu“$j¡—wQ,Fcò­)ØÓÿ²6âÐzãbÎ+Ûo}(–ÁÙ¯/¥YYyú‹ÍËM¼ Þl—ÇM…‰Y–C–åÒ”z ¡“\†%dÌc×HÇ’ ­êhJÅÔÌ–Q0ŸS„¡t'ñ‰_"×ÞuNã(®²¡´šÓ‡Ì^z\Ìs¥à}Ýî:A} %T*£D7ûpÌ¥í±O €¼R‡¨­‚ÞḠ‘hý#.uÕ}$É(ÐÝs ¯‡bê!7ñuu>6‘<™ŸX¾»g›“ÈæÇ5¼n/z8¤65Ä;ñy‰^@ÆòD‰ÈÞ©Pw™NºläG%5žèAF,–S?˜$ÙÕÔäºÃd|A*·Œ- ‹Ö;*%Ô†Gù8¯v©~Ý@4c 0ªÁWÛ„¾6×°÷WG¦g4‰€æ¦Ò<ñT¿;h›6“ï‚ NžòâÏ“6F øRÃbXO`Ø“žÄÒÔoj÷’£sÚ+4i1t’Ô8Cvæ>èÁ IxôãmO|¸•øì²øº‘ò>ml°›Œ+NÂŽÑõ¤.}X6SÄežš±RÀ8¹L®Ô±åZæ—zÚoKB¯o4ã!V ‰#´¥, Š ¡—Œ\!®ºØ{{8SñÁ) xÂé7è“rˆÛÄùf{;§@(0/%­%=èÕÈtvm‘’µoíÏ7!5¸ußv}2º‰èzÚ:PLU³Ï¤9¬;PØ>Y—_ºâR˜Ÿ–ã)(CB~†4›‰ç¯XÐzw«±§c?FôhaêUåÝtè´éN„™¼áëÁ ‹Qð¿ B `DôpÇ#÷¡Cü&“h¯/þïQQ_F}ºþÏ´×%:Ø+8B¿\~ª "&ÕO‡©ð ƒï+ €1£ªu§(Qºu ü%xÞÆÊBˆnº;öØIÔ÷{«ƒ$럗¾®+íâÊz=`@‰4ŒÊÑÄ©‘ÆN/±ô˜}>v¼]0Oøü&@­¤›3zs·ÇQVùN±[¢PBÂO8á&§F )KÜó¯4qño÷Ú­¤l¨Ydæ„ g=: ·›œ0ñ…Í~¼Ù鶪ö=³/ÍüAôg½¯l^‡%€2¹''.b\Í*]ãÅÜójßRLºfº'á»×”{vŠw¥Òn2cvf ÇÆ!œ¯þ/D« zÎÌ®¶-üž”ÞÜs¼-…>PšÑ°™5:hBöcì¼Ý‹Ú#ØùGËî,lîÞýÁCuÕ‰ ®ÝXªñ†ñv½7p1ÔÑ“áèÝæ"§ioÙEÑoæ³èw¥eRÞYŽG«°­¥£}ÊàžÃ"‹'yÔSö„¬ÙQŸâ>¢¢-Oxð·¿ÅN gY¢_¯ãrM4Já@Ù*Ç<Ñ<ïgBç¯BÆÑ^ÏpÚªšÂvò&•æ–|ñª›Oü™ä;#'FcÞù<÷‹M¿né@‹ÙÀèe:€8õA18Š{ŦW¾Õߘ®6ïÞ¨»¡Dåún9€tmÛI$n±^Â?7ÿq&ÇʨÿfîvExзRÄÖ§2bžíýÇGãÐ’Ôþºø‰ê¤ Pd \WB:ÛÄvµ> ׺ÏCß±ÿhDYH­1ìyú)ðð‘®z­<þ¢ôöbáKaàbEÑvÚÆïâàó?Te”>«9ç=ßú-¥—i?/Ã9G6c~¯˜¥eœÖK®3""Š&°3 Í(ø"ºÌ“9Qt,˜Œ{)î+c.ÌH®³e¯ç*‹ôÁ2`2‹B,éõlºkN„ S³Ðxrr_oÆÇ švZ8¸Ö™‹»u{CájrêÀ%°"‰›(î±px]û±š(kãvÌ}?ÔŠ”€Ö–Cèü[ÿ‹—! “¦9Ü7Iðe¿¶¶®…ÖŒ,ìÆ»šWФZqôœÈƤVÉwåÕ4©ð˹|GOÀÛ z†R³ ÃLÅ6{ƒ=0r>¾Š¸y-i DU†o¿1ø±@/sç#V+>¿ed¿«rîíu‡Òá³eá‹H…×pp7j]ßµF«ÓØ­[GLÜræŒñ…\/RŠ1†ßA7ci„;cB NeŽn ô¿ªìwåÅîÃZ¾¢ ¼:¢ìó3p†V•ñF¨€QK«ËòW²ÈyëmVç`dyq–'™yLVí] Kj›egeB'©2kzi&ó–Ã×ýI T·’5—´‡oŒ®j!‘YYL¼Ëa\JÀbKvõ†Õ+fÚIùA3ÈôGêé`Å%¶¿ŽûR׋–p⇛]½óýÊénNÞ„\gå2Þ«²XnÝrNɦ8AåW˜øeÔµM°ì#Þ@ë"¢Q±ë#q=©³fžÜ­+C# Á£.¡‚s46ÄÏ÷IÝj^lÞê©_39 {PL ƒáÙ £Ù¦»r”†²H}sÓ亻õ72-Û û[>:q $IíÉã|yÒ¾ý.¥>ô¹…D&EÖCçŒo¸HßëÔŽçœOðÿ@IJq€«r¤Bç%ÑAqú’ íxŸŒì]2y*.¬ü/Ö09¸‰ò‹¼5¯²½áåÀPáâƒFÌWCÏñªRþX©Á¿ÇPz 3ö^AøÆ6%ª¨=läJÏ#`Ÿ‹LiƤkm͉0£¿†`ѯ]ü:[¬ŸA–u±ßL€\pVŸßä ˆs9º:†ÃÔfA^¡w2ÐN -?ˆ+NJ‘ØPx71>Gi±ûŇVÂäb`´…ÓD׎žÏ‚_«R0€5æ;ðØ-Kí@ó<ŠÞ`Ñî:r Û©ÿéeC²]û´€f*”…O¼P:çP\?¡Ñï´¡o}·JöØ·V]@‘”â¹ãçɦ"ÚÓoÆE¯¿Wcw¤€«­vÈ]T©ì •¾ÉWâôÉ…P¼ÜT'ðP*Ææ‡œ ‰°°íÊø ›cnfe*™ô¦DÑx}iÅSŸíTöé†÷ÍÒ.—irǾ¯0[Õ _¹F3Èê˜Mö¿P~bb"l细ã´<Ò š@ê BW«« íIðUêú7½­!k¸'ÍЉáÈ ÚYi¦'*c$c€oæiF›­ûãlÿöQÚŒ*ôóipä\*[H»ÙÈ[ùc4]´¦¼¢X)ÑjÆ¡/[û”ǾÀBQ\gêurÛ«Xdzœú Û‰ ‰àGi%Y'ýôC(Ë^c8¸ÖßÑãƒPË£î*ój4Ý)¼~î[l±dË÷õÒl¯¬ÍG¬öºvã•׉±”0Ê2Øûu,×.q I,É# òƒ¶¯Ñ³àô›vL«â‚wÙÉ»îó½ÛµüUhB)èµ€† äùÇãëŠ&ÃÞ¨t†4² ‡êƒô¬ 8|´ê~ ÖÔ ¶K B-ñß~,÷S'¯âL] #Ás±šÔ\TâNs­ÅŠFÆDQ˜<]]‘z—¼°¿P¨Îè’BÞb G¯z–çTT²âD§ 'ˆ(Ëøi×å Kƒús‡|ãeŽXm¥~{%Í.,Öf)ç}<©½Rü)ü}úˆøáLówCZÞn#¸x""¯ïþãCÈ8f[°#® ‚ÆoDè#BÉ/„0ê‹Æ·º–€IY~&Üù?ÂÇçÊ$ø,œ‡>Úy»òúewÕÈz¶p& 嘎Dv–I¯´Ù5°Ÿ6§B¬€ô½évÛ.¨æ.Úc*úŸ±Öq”«éÛ-zŒ ì›°›«áÞjŸ!ˆ³›ño‚›™C†¯uq˜È+˜bÁ±^އªÝdt•'ŽÿàºSW9 ¿1õ9²ïQú3p¬ Ò¨eÅóÜ6T!«¹«&C[¿¹â>“4)¾KÍzZáÒ*Gj/Üc~bËŠ,{` ç{B+£«Ùg|†+ïù‡•Ò£­Å Ü(Ævi™Û<ï•HRÚ9 çI c 3_¹ÀÎ7}®«µõ9"nÄZˆm)—\•GU·„¨º‹±dïT$î´•+@Hí`÷·»£CÁ«l’Gvaþr–6VIAyИ·Î·Z=m)î½±-Öá0`˜qd6[šcNMÜ¥«eà ¤io»sóΟ2ëær™,V7 'û²“R£Ñ|ŸºóG 'ŠÄ>—Ñ2ü£Ó¦ë¼;m5€S«Ç˃£dÉîJÃõ4ÃÊ0/0¯êŒ¶œú,™ðXõ„üGÉJq:¥w8~¨ìA„Q„þü¼D¿c>ŽÝ‹Z§JôŸÕ45ëK¿«OÿØ'èxFvï êôñÂÏúË#]õT¦2ç°šnONéS'i×V÷*]Øõ\Ï(2Íi)4kÊí)BÑwÅÈáÂÔxÛæVÂäÏd·aL mÉ¢õØÄ¶Ó‡x¹@¡´­OêšýsVÍ¢óÓ/e[[:Õ—º’Ðn7m1µE!ÄD®zJïZ·­Té!‘}ÕØ3“G?ͽŽIq _±â?¤žq"ƒëµÎÞ¤Qÿ› WH•  ¨Ã׋båyÊòÜÚlàŽÄÈàghª™çiY¢¡M·ý3÷;èØí¾›/®|.k+£ºÒz…‚]ØEDk߸ ;%Ði²×Ë”~'cGü£ßWy ‹þ”ò÷?>/±Ro¾î½&ÃäþøEá„Ì”5ᙕÎG3Š‚8ãZbC2×ÉÍüÿÆÊ¹Òš‚ˆ¨ƒ˜9 £,][\xäYY½}<Ê™iW]2uÀZo^×ûKˆ!i['íU,ìûZ¨+g´Ë›Év'ò#mi`Ç- ÈaMO±^\ Æ.žóÞQ ðïÙ®iðáÏù°¯¤ŠÂ}ÝívRY™ –%V ˆÏ@M&mÕ{ǶSIÈÁÐß‹$¹“$: Ù©ÍÔXDí{*n„@q-Ę‚‰zb"4ØÌùÄ\@>ù=µ„÷/ÙíYœR ¢ýÚg™YÖ’äDªƒ¨Ez';}\ü—$‹à7cÔ’­Ê^ÕÌê(›)@§èxÂ.¯‰ìQè)H\v)^®ÂB ÊnX6SWq9M«djÝ0ûÏñXF†éÞ¦È'y€üÚ¨˜=è kWö+hµÞø5wµAÙÎl>˜dKìi¥Õ•½zÏ´¨sÏãÔ«ó÷A$Å…[÷ÕQ·ã£07ð¬›ûfœì™ˆÇa`¼îGà&¨ÎŒ G{Ús¾jVTt=eÚìrj¸Ÿaèb–CYʽßk¯ÒE* ;À”ÒqðŠÔ€ ¢¹bÝ6ÊÖÛþÎßïgS6FX$Ð?ï'>–"W#©`‘ËAÖÔf/c…Ìš¨ÇÃùrW Ç<yÄi èìš„£¥ˆMä«cü_(/²8g­çpO;²2 +ðŸqV£SVøÚþ]Z³º½Í˜¦;óÚr­øÇT&ï«ê¦ÆRmaã|–¨‡×gN\ö½ÐãR+{xNOø¯ÿÇ©Wî­Xº‰mB¿°DKûùóâænÔœµ´áƒkix5¨6ÇÃr€(:$ëÀ›áŒ,6•<„ïAÞîÉ‹iû&VƒvØøõ¡ÁÑuw’šxÁ}- 3È$UH³.ÿ…Ôuä[Z%á’éêði?|`ݜްižo<¶b±ó³86͸õ|*‡bÍ;¨bmÐj Nòù¨ªEH©=RøûáM‡q<&«7‚/Ã1?€# ”ŠþŸî¾%OÄ~roú®¬îä!˜ÜÅÚÙ“œƒq¨ùòè;Yl'ÀùæeéØS(ÓþqÀ¸õG€žG·Ýo?®ÿ#ëÉÓÜŽ¥¬ ô㕟‡Rªl¡¹ÑÇuÖcò$X¶?hoЙQIöh ?}‰õ§m.÷„¾þÛd™ ¦aRRk÷t™?ølÇø¿ Ε/ûuûbBCÁÇÉy¼×Ò`ÒÇ`„À¹Y½-Ð-eÀ·3^>³rè½ZIvgŒW Œ}‡ØõˆšÃoiZ_‘8Ræx„É·™T5zðˆ!bû â—º¨›±ÇTuˆŒ³‰`ËÔÜc¢™àLÜ38Ç©JÃâß\ ±êNI÷º—`R±£©mÈ…(­‘+Éþ.s)þµ>„Ek=N×t¤;îæò Å£pðp¤|D½n—Cañº 9: ºvh£ûêƒ}Ûu,ldŸii!×pÔ£énÞî4Ü|ì9ÏÁŠ/~æH¯`5CFy Ç„e‚÷;ÌÒhB‹‘ßmž&‰ˆ°v¤”—[¡©K÷[vüÃ^é3H¼qÞY¯ßòtI‹¹ƒµð^:Qô‹Ã.©pš´gï¼@‡:på/Ü·ìÃn~!õ²*™%•Ò|ä ù™ÈqY¢h'¿¥KËÚ—; ĵu Pg›s3I;äÀ§Â®è¤nIÎÄ p’7LÃ_ß›e„oéDZ>u~Ö(æè…ê˜96¦Ëie’ýðßëq±z¶la•~,¿b Åïý1†Ð'À·ÈØ#O¢àu¹þ#ofÕŸ™ab$"ï}3®RUÏiÉÂfG©¼™=dA=!dú¿0‹7ñ´Ëa³|2À³*ÜìZ¢Fë«+ôÿ¸ú¢>*Ï”4u o°)ºãQ zý˜ì£ëøPQ³×C¯ïÙú ¡ˆIšL(r#–œù>=tk eh¾¼Hnq|é¡Ù3øBƒäá!åb…Ñh#úϽ-Øhã@*ïAéÿ ÙFŠC¦ƒtzqIs˜Õ˜f¬uŸÑƒ0 ,½­S\ð9>&2ÞMùè)Íu>9ÍFz%’îÜT”5jŠà{jK!, FÆ£TéGíH«CÝi ^}If­zAí<5M±»qóí½/[/D`·l@°8¾ŠPmh‰+!n?¡Ž·r? üc¸¡”Ý{>ø‰ªç2 ¨½Å&Ì·otúê×óÔTPï _°­êÁ•\èÔh‘ËwåÀ£våß·ÄÊw+ þz†(¹ëe(xÒ×êV€*–õÚäÚ(Å”›ž°tç±& º>ò˜M£¬@Ê4l HÙ˪ߎù:"ÊÍ1g⇦ÙJóæ»’N‘U±z¹;|«O…ÙàŽi*†¹¢½ˆqg0è‹êÈrՙʀêI¬Ë:b@®WR« ”»ŽrÄ-#å=€Ã 5¡’ })I3¥I+ê‚§ج¯œáâ? ô—Y j­X7…; hÒÇ`ŽÐÙþGD(«gž(Ð’{ÞQö}Ë|ÐQV”K‚ æSªr Þßµ|Ãø½R%b)E¨ t¡¬§`pä|;‘ï¯ò«v‰r {Œúšä_Ó¨Lf;¿I`ë|ç€cù2l7Ï Ä4ýEð)ù8‘ü–¥ÿäçVêÂîñCÏøÁqÜò9´´Ñ†j°¤Ö9ÇæT<‘1¸®½fh²¥­”¥#3Élï.R¹syÒŸP¾Á½$N†§x¬æ²¹YVju…fõ¯bË£hd¡ÀëS–ßÁùv³pàaÃhãWåx(E„øt\ðê´IŽ…ô-~§÷_ÆxØ€'­>WåäxÔ„½–1¹2Êúeú\f°ºïx‹=–¡PG•Ñ5¹*M*µÁø)Z}gø£Ê¥Ãßòàû뜲¹ÒîjO¢çªs÷1[ÞpsЬ„6>ŒíƒMÔ†ÍRàɈzØÓìµ Šò;1:%ú|©#W%X06—8ò.A_}•ùO‘hÐý>j àõ úw>ÐÅÞ Æ® ·2®u~/´0…½êóè+”Ød€Füòä}³LÁû¥Ë[˜Ȧ–Â@Ûè !'޶Œ¹ú'½¨£µ‚Q›É‘ à­q½$iŸ œV¬`0.ŠYR_gû°°BžW¡¾Ý2]¶8LƃÁ×_ºKÌŠå”:áAt›G‹ÕãR~¸åo” M†‚ЮÞbyNÇ¡ìp›gÆêÚÙä{¶½—`ùÖø|”"Ïmõe&¤±FÙô‚k§&ÇÓA`Ô/6?­!³o«JVf û!éÐqtÅa_Ìà\nHÛ…õÜ£MnLÍ}‘–&xõð,¾ù3T˜8?’$9(„ Uõ|RÅoíÁvÚcIÃÜÞÍ×PŒ;ú×6Dzc„ë ¼‰$Nf`6± Zü.8öÙ:Ú|Î-kœ‰6•üô+×ÐJˆo—_RóXêF'*Ðý!^›îàÛÚAh_C·Cõé ý[.`µGÞa3CÔÑEš:8›„ ¾2‰ZÒ^¬É®1IiJ¬‹Ë¬c¸°–z”%¾«i4¿õ<ì¯=î‘7A ÞËNÔÂ¥ÅGñ¤$åـЇ³õSo4qÀi­lå Ü®´èiÎäP‚…ŸÎ%ÄÝo>êê-Ê]? èâmUKÚ Œ½zÄ„¸MÔÝØ¿”3&Œ S'î –¤GO]µh cÂs‚Ø yáu&:‘…æ×þG¼)+$–PïkÏÃXaÙ¥o®W®¹bú†@HΤdRBõ¼ºœZŠÂ‘8í•£ ‡Øî}RÇ~3iŽ‹ŒùÜg}.¶7'e‘Û>œÝSý2*ðÉ€Ig?ú: ÉQ+ÏDt™ÂƒBwÂ~†¹@—á´?ó}ƒOªY£êªÐC\ £Ox:B€…‹­Ûa‘½1öZ´=}‰22¢¶oÙ¤ *§›YuzΞ"FÑ5ëÖç­uÅ_sÙ*j‡ÈÔ^½/šhMHÈ”¯ÉˆiÁáWˆuʧSi¿È\'5ìÔ¯1Wm:ß¡VJ…ÿg½q{jâtæ4»D67w„ >?p‹²|ña¶ï87ý¹úÔë|SN¥Œ×åiùjyÍ«æ¾çm¡y§äºÅ€ÅZU7®7Ç8ïØ\Û(—Qé‰ ©Cz¤¨íßÁ‹¢|ò_Á­ßrDìã£v-ƒíËÖÐô1yö!6ôÌZ9—|àìÑ‘¶Y—ëÓâð:Ó¼qòŽ§ÚÆÔÙŒ}ír‰1ÆŸÁ%` ÀÅ|Ó»\…C¯¶K=6¬> áäóÀX¸-•hKžz±=Š=‚ö™ª6qj±=åÜþ3bU3ï6;5Y2ì¨ÒxÐZø‰iLfdPŸ´‡_ØZw}½ˆ¿X×”mX lnñ˜µN:äŠAdqDhÎQ°‡¾ÿº¸P6 KuìLàÓõDàqÖBÔQpÔùD±ÕÀ¬ðOZä»95FÖ¥™ ÙÎÖFû8~0 Oš0îŠM ’CÖö´%NH'òÉzULâ`‡&È—¡æ´âꯑ;Š×2¿µò ŒT‹oÚᶺæ“0.ËÜ_œ·í¿ Ò^Ì>Yø%¹Ä%­¡°‹r«BìmÃã%¼Q4µ¸KÛ&Z7½Á¢JŸ`ñìÛŸµóŠéØ™Èü8QkÁ[¨=ÊQ y+¡SH‡Š$V¿Á‡^òÇ=¨ÐåÙíãÈ’‘´a(D­òw£5”uHŒn¤¥Øx§½l«^®´1ã?‚D—d–ÄؒŒhö{$6-»õûì÷™ø9ûAµÐÄúS‡#uðð²/Þ¯f‡@<^¼°x]­)ìÈ8»^a•¯ò£i<9ÿàîá°Ü5 †Æ„ˆœ¼ þç.}Ý“wH÷lÁbSGk”aÆ åù°üD»K¢ Oåá .È(PÕÒÜ®ô§^Ãr®\„úsÁë˜Ó4ƒÎy6Éù½î*@ÿïëã€UÛ39к—m TQiM¯ž›B˜Ø²™¼9„úf8Së€÷Âβ¥f¬t¹\gƒÃJ‡ÃÈ0ÛM®êŠ^Æœ²Çp•c|¿Y»¶5˜IH‰Üï·ÊéSéDúÚü[¯gnûdñ $[É|޶uZC‰¥\U|3KÖÿ³z?Éš¡ÏEÏv‹«Üp㕤®é8×ÑÙ ‚îü]ÍØ\éuÔñ~`ÓÎàrââÎn›2¾ÁTy¿¶>YÁLNù;?× W·üΦ 8Rq­ÃX›úé(Z,1(êhÒ>V¡lÂfVÙä(Ô; _ßp—ì!°~Ýa½± èûCšÝœQW±]”s{ž]¦oÖ­ÉW|@±ÏG§¤I"qðî7´²†‹}owÓQß‘N“8ÃÛ%¥CMù^ ¸sÒ&åò£Á!¶3:–­ ËÓÝÔ—ë“jaê1¬¦O'ㇵtó«…c›¼oàU‰6)ÊJ–öÍ*|Ù¹IÊDð—£Pç–—YPÙÖÖ zU(ÉÛ‡µÄ9xrí UgaR_o;Ì‹Þß÷€A š®{¥î$ûAdTMp5ê.iÁN÷òÄt+æ« hQ­Â=j½£îÑ͘$]]r!r’­í DDmhô”GÜ×s½}N_}J€À] «E„§$<Š´¢BwG — Ï(Ãí`ïÐÅIŸÛóËkío —%°²¾*rIÄ«y€u×éG<µ‰ÌM#‚äëî”j((6î7®°TδòÉ0$Ó}£l˜ î’Ew›Ÿ#¿%tâF/®®ƒÔ™yeƒÄlêùLôº ¡.í$ðÆÕù¨»Y¨F£ÛZI÷õ¹ŸnÊõî«öûë)6õÔQˆq¿Þy¤~{¶¿JamE\K.3y¿úGþ(IDÅC³ÌàD×å޵%|ç,åè.iòªI§ ÛÕ "ªòA«êT±=„'ëÛ+&°è¢ Š‘Žðþ°oßVPŠg¯²‘¦·ZY8ÇR 8zˆ” ÊdÌo,Ý´Ä‚¼J~ÔÔŽ¹Ü™ÞÛ€"£ ð¸Œ&L‹®PµâkŸß…`eË%­ñ¤Nð~¤ÜzjÛÅÌ[…77>‚é£HOŠ»Z¥p‹«<™¼¥‘’_L;jŽ¥vžÉZçÏ$¬*«±þ‡ VbpK+éeÚ.p §!tŽÿ`’Ó7 ~”aOº ßßá_f «Vû@ý=ñz"ûx»ò#¦$²·Ý†áúÞº!YîM¯ÑL—ÄU7çï6R*­»42$O¢2aÈæ&Ãn `ˆ©É, ±KBmDðd’Xÿp„aƲŠ8ó(ª@üÕTTÀäú<1UÄÂÉ[®tÔ×_3»§»¤"ã‘ê;4mÚ%rŠ˜NÍ)ÅËâ»Óœg#=sT+²kÌžÇÃ4ýû{Ñèò⿆šÊì ùR‡×ð¾Øs*Œ­CVÑEö~”ÀÈåT•û-v.¥´ä­-Rx¤rÒÂ-UOµC¬sÏš[±žÚÖ}Ø# oµX…º¶´æ“¡ÑXí0Õ&³}ì7/þuʪ»â&2ž6Ú!í8qÔcð&â_5ÄŠxî_Ê’¸²íW#¬jäz,ÑÐéD¦ž…#<-âÍdá¢[O W¥ª ‚®QõÎ(ÆÛõ w©Ú¡ ¾8ÕM÷ÿé&к)Ùõ« ÄòÚNͼ‚ߊ.ŽÌ>;7Ð~WW?CÏ QL(, M݉ù¼§;Ê8„4=ÛYãýÙžéDB†yS6u¦s—l}Ó'Ì{è+zƒïâbK-HÙ¥Ƶs1ãuì¢übêÚ²A1±gˆ>݈*zj?…5 ñ%™!ÄÕÁ¤$å× u§ ™5Ê|}$RιA1îÖ¬¤çO¯O©ã\Èœ> •^ï;#㊲°Ï:³ž±~/ŧ8(yÄ`³¶+v õ‰û*å•ÉÃ0dè+(:¤îûX=‰­ì+ Œµ€Ç‰[÷cU³,Hfפ7FElÓ”»†{¦Ó¬7NÓËûââØ{U™ûˆ!ÖCŒªñ­¨Ë¨*˜‰1Hj‘,ß•è(…wªÔ¯ëWlí¯’æÆJ©uÆ®²b§-¡p@9ÚüYáxÝ;M÷Ô®-+·„Li©vÚr$å¥ÛÜcå*ƒÚ>Н6‚¾Ãúp£no.y0C^A3nŽsÎ=þ*»8•p¾« pƒ¾ô« `L.r§2k=*àMϸ“Ò)¶óåÒQ3N1‘tr1ÄŠà÷°k Þ¬“7’ rr= ·«Ì1yŸÏŸ9µ‡¡´’xk­9½ÃO4Ú‘3~ÔÐ?Y§_èßîÈ8ÊÖW_u•…£Ááx³-QáÝ/@2á¦pøP7Êßa;ƒyih0û¦Y^Ó?DÚ.}AÙ²éS­‘.^°XJÿñR›á¾ðÕJ«J¡±L3úúa"g¤#<¿„¤ýcŒÃ½Ö‹MQÍÃE©MQ¢MLLdHÍRÞ¼ý–+–þ^Ûˆ…gÁÁq}zN²šõê‡UFèË ¿¬Ì<¬úÄÏT$ÑeSÜž |i²~—9h0Wó.µYU®¹Ãz‘×fvèeûÜ)ÐbhP?xO™oj„Äúh£HvË]ËWZ#Я~!¥‰ì‹b¾{ì%AÐzüé{8χ„:&šî %#KíÍÞ íßj"x›ö[/ÔèÌ#ö->Ýêïø¸NŽxëÀ‰*º ::·–pÓTÓ)!æ¬Ôº™púá›bnFš`ZûO™“Ptµ6RÆÆ¨¯ö(ßÍ Ûe—‡5\_|‚+²ÓVa1‰p Ñ©ÆjiÕÃjyí‚kÖY2¥óKÙp7“Ä©þѯ;Âq‚äüˆ{ì|ô3f$>7Z­¶ôH¯ût×QˆLöý½Š dà¬NæŠ| ¯IÌ Áë.¦‘ á\*±RŠx «£ÑXºGö›zSâx=ž­ôI”ví¬6vÅ´>Lóò"s Æc͘µÿÅcç²½µ”ã ‹…'¸› Â>§"+ý—C¬8`ªï™W›nÖµˆ‹´í`;¿Û¬'׎cÒËÙ^`ßaÌÈ.•9ü¡ ‡¯2%шKÏô§“¦ñèE̓¡Z1;»¦Þ1±!+6?šÈÉtP}L¿Ñm Y­‰j‹ê|VÌ€ŽYtW‚A^x1åÇo‚=)ÓPø8&zp»l´wâgŒçª¯`5OÒí/ïÅ,^ŽT1|ºÆUe¸ÿ4dq™'%ÐÊž û¾›ßѪ xmMMÊFý ˆ6o’­Ú·]îÆ63 G‡¹]zºŸÏe\éZ‹œÑ{”èÀ< 0’¬ÅŠïÄZ•h…u¤Òœ™@xgñò¤óC.4ï:¼!Ÿú´H¡óvËF©zévÓm´Ò—Ò¯Eô-äÜÌÊ„®ÞÜžœË ·\ëR·BÒÒ.¶[¹ý–è®ã˜(®Ú°(¿ñ§… Š”.Ä*sh´ sèPñ}9QžŸ%Jª¼8ÌaÎô$¥Nbýî«]°i7RJŠpP„Ø¿q^€ÆÄ¹JËnÎ÷…C(",Ù[›È©ÆøÙ´ Kº#i‚T;©ö’9.¸!âåªÌ ¢u[ûŽª? ƒ ·úO„Y†bëµ0D>šìÊqT@€Ñ¯ÿOóµ]õ_è6lþ¹êqa¯ºös¸:‰È=#¿ EÁçµó(åK}™$z¨[¼ç^v­8 ¦¬‡ÔÔ°Xê´d³‚ýñO›D+ËϤS7<Ѭͯ \7Ùúõ´»ìTP’"ÿb¹èdÍ‘`©’…M†ÈÝÇð§‹ÐnÒ¯ay©Œ}z;$X4>•—Œilª\dR¶îEAfœ­§f»ÞîôjIn|w: ZZ~ÛĦX¥ð)ïqŠ °ùrÛ–·qÊ;/Á.AW0Zx¥d H«»¢t’‰.=¶Á!‰ñv¹1Q®HPÆýÖº[vµ™¹jew ž`çBÃO0£šYêœÀ#i}ã‡;ç¸!ÅWz¾–‰ˆÞÆTJ¦!·¬À„8S6Ш€Y#NŠ—PŠ<„ox>Çm$È"dh]šÄ% à…¼³%qžJUå#}Èf鹤Rúämͯ‹vÀ›ÁVbaÒ³ð§@©©×4sGrI¨S…^c)n2^,5*\îljJå×íž­¨’ÆHQBüóç:KÂבØWêÔâ¶á k ð¦@òYæK.fü+ºXùuÑ#\ƒÉNp"ªLçeº~Ú»Ìð˜á‰ü Zª3æ›äôf ²_®4tëægÞˆ:ý®Ik]|?•˜¿?¿`³à¤¼µäÎ0密gÀÝ¥uÈžÓ‚ÎÔ«ôB«p™5~ý;ÏÅÞË#FèãºN/Ž‘vôd)rv67¶Ÿ™ØÈú7ˆ™6ø#Ú–†è,è×ί.Æv¿|g[?„ô…s¾DNΟêú]¹( øMÉ©$ËêGÿÇŸ«D®rÈ 8S‰€p=¾ÆÕ|ñ!®idƹ.S_ñü&@­¤›Ì‡¿¤ƒqͨՂAß(HnŠõA‘y/î©ú*NÔŒ©çù 'ãTJQöÑßÈÉ\Ã+TE±¥:«ùøZzÓ¡†’ì‚‚y^× ·%èî#ÎFT-aÌ ÉQ •d{kþ7Ö§õÔviœ)ˆ½ð4wÝ5ÿãZ®ê¡{9AôÁ?lÖ·AE<ßI†)9"bÍ.ü¶C]§œ¤~ÃpˆÖé¼_Ss(CÁd(8Ïꆠ %€kθk“¼À °SÅ›Ór%½Ëy½Œ†“ÖÆhuý€xó§êW¡I”×›jÑ4æ,>.+¸úH{Õ½ô§¯íPжܾiXÓEY¾­S=\mÍMëÎ8Iê­Ç‘E¶Uxý@ø”òE˜ä 5\'D)0 p·&æ=b7Zï[½kÃ1<=¥3°zŸt¹½ù“Éž÷Á Ùô‹Ü“|ÃäJ¡ê ¹ÑGUsŠaänö…¢Îx®õ~Š\ªÔµÑ¤3ލ̶ŒúîaY§ð#¹ÿƒëµÎÞ¤Qý>6ãmV%¿ø´yÊ7€côÖs@oòŠÊKÎóF,¢Ívi3h!©¦³#zÎÑêrŸ»óÙBÃu¢{€»Rº©Tý¯¡ ª¸í|_žh×H¾vy÷Ö ¶ÝCÊ4¹ ¥Æ¾tºá¾iòÞY™D@K|0‰ÞÁ∠xêhÛ-›d㋥ťiJ¬§á»§À¸gM"1?B1rv¶¥ñƒqÑ’(nÃ!ݱ×9§” ?W¯¸Fe|ΔÓõÊ@Lë#wa9D¢„1©7Š6n³cäÖZŠ%HªfKù]* ² ìÖúG®]œc¨lõq ­éY£:Ú |šöb1ZÄ4ù xì0¾ëu½Œ‹¶“'Uh‡pZÛu–ÐâhõßDܹžyC^`Òà"1—4P¨¿%,ÏZF^Ÿ/§šT”ÐÂË|ÒXÄ­õ;æŸ;º= Q¢£ñýiMÅ J$ø¤¡« ŽÙ BŒ)„æúpð•¡ÕI¬¾¹”‹´ Ыg/îé^ÜC`z}ûБ/ÞPýbhì—© !6ªdÌÍ·(j½‰½9ø NKeÁ¸â…eåT2?ÖJ,+ß-Òý|Éåd§»1^fNöŽí“uºAD v)àV¬´²õ7Ûd(/7pyÁÓ±…Õ|9×1ÿ~.AC’;öº¦„†]˜³‹Ëå®w×* .Ò.4Ç®-|Ê•¶öU)äk·ËÕÖuì5ùªŸBÁ3 tñ=/¤·õ|\ùÊzš¢®œ’õ›?Sý2*ðÉ€Kß2 ïzE޶b˰Ùü\΄QĬ5NØŸFjM§àZWÑ‘Öiõ¬ôþ€Ñ¢åÍ4<ÝŠFtÉ}Ìsk}•Q7ò!¸v…ÿ!óbQ¹ÑFÆCKú„ Þ4ÊÆµúô-¨~~hýZÛ|T€ Ñæ#X‚C˜%ó˜ ƒ5NÙt@ô§ç ¨²’Ä©³l`‹n>á4ªt|Nžìr 9IèjPãéUÛ6ÀR¯o”ãáñ³jz¬$XsžEw3IYçù°¯‹†µiwKª–v@Z÷(µ†w0`±ŠQCùhœ)]·&Ðæ#Ÿ!§]pÌUx5{tîðY¥´æo5M¥õ8dS°+"$OÕ¶Ü…Q^–±$Ü BÏ$=Ú]6l!À”væ¡%3ûÐ ~Õ¦ßâ}„ýݪ€œ–‚8ÊÝä‰+°§­«Ç)¾hîPLÒ„4D€æÝ&áýMQ¯GQË}í$îI”`Ršó©â¬ˆ­\x|7¤F™â*hÆQ‚‚k™Ü›–n¡_uáxÒ Cÿ•†ÑxÑvs<¡ByU£mJB†ÞçXõ¾¿Qw©{;µYëÙ²ã!”‡èeÿ¾5DOÛÕš›‡ò°6’Ç\ #¥_Z²¨4oýñQÀôº“^-ߺÛ„³+þZQçõ…Ä¡×lŠ÷-ÖŽ1iW³N†«Bb¥ æü” àÿè”e$"±2k¿¶k¤i´G°¢šP#ÅEù$ö±My&ÉÙ9k$pR*йW •刮.d½gm˜.eå84Ssh–¼Eùâ6Ünø˜tX`°ÊJÚvªH 'Aê*vOøT7‚nSîë¨ z¡D"4¬ˆcZ»M•${ÆWîºR“ñm®õzœØ(áah ̓¡Q-×I‚p¼¤QžZኜE&–@𖊳•øSCŸdí¦ÎaÓôDCÓ±ð»ÞL!ãÜàÓ¾¸$¥C3öPv§À÷0õž±|†²H@`ÿxb3{´¢B~†ƒ¹6«„ºì?v¼\g¥Tc\&‚ïσG™•Wm²]4å6°¾e LqÏvoœt±‡x³ÆN¾Í®ÅÝeé–-E/F.λÙW<{†Cq‡Ù¹ß'íjŽN¯Ët3µË·ãsøœ]ËÂ#x@ðÌňó{ßŸê· §úÊ·Yx–?kCß´”ž¹b·âŠs¾ Ûàx<ž nʳF8[6‹ïâ Ý»JZ3ç(+ÍZ¬™p€¨^©X àk`C¹¥¦.ïmK‚• „o3:× ‹E~ac#€ «)ž«wÌI½.WK5kt?.‡·U±0;¡ÁùZ’Ä5&¶ÊºsÐVAøïO]ö,¼_Õœ…Þ/Óhú@ƒýö¸0jªæ1ÝÀ’Ëñ\Õ1ã‘T+$­KòPEMR’’ŠÒOtÊ>(Rù3‘òO^ŒV [¤ý:ŒŸ&BÈC*ª±žL"éÊs·‚ÛîúJâÚ~ ä¤P &ärDGX :g©ljªl67N·XO7+:”e+ì|Õ|t>ÚŠð¿\g«X‡ÊRÉ•ÿ¾¾È3òôÍ8Ï#wZOc~që)²* e÷*©»–À‹uÀ-*rþÒÀ‘·›ÖßãÓâû…\¯ŠÈ>œ%!V˜D+«6~¹)Õû›Nòfß#Ñ6Ìèµ.ˆ’J¾âA¿mxU¸„”1Z˜ÅjY$ï vÛ¾5xy“à›í]ì=Ÿˆ¤°?YãêVÄÃJÕ͆7÷,ÝždNã 5xó£$ÉXË€‘÷ƒ|ö—¡‚šÂîI{+£åÖcP¬=ŸyÓ!,ÐCýª8lÒ¯!¥4!‹iÕq>?¡¥µð ð(¢ïq¿Š[ ‚]¹Ãi s4Nö@£^©,«AóìI…#†w’™’«•Å#*†ŸA}ä‰î˜±ï(“—oœ’5§ÕVdKþYÞ}^š&Ì®¹:uÄÎPÐ9¹È¸ìâ¯÷\†J‹ZÁöÍ¡hý@êë^«on-ád `ÐC’¾¼ýº`b¡NÉêáâ? ô—[âff¡¦’ë ß°¹VH˜~ €ìX숿”¤Óò á~´i)®ØÌ¹°òu~%‚ ŽÕÜH[¸46-«æDû«ºÚð‹ìüÚ]ì KåÐTf¡ü:˜ Pý÷%µOÚäË…3—ÌÆ6~»ùŠÈþ•mô¬‘:X³Ò®6Ö²â}¹´Ål‚ŽÅu|Œ¶~Y&Tâ4&¬ä×Ä$_çœãµný²P(4ŽíW4Py6Ý¥Ž'„Jæ#uÁS](ŽxKÇ7âáo5_YØ>ú‡=³TKÜò‹íí¨Mcífd~Àƒá§A ü)AŠ¥‡4.©þKë—¤­hÇQ6¡UˆéÆOþÞkju9„Kt=X°{ŸiŽâövJ“žá•8E±ËÐ¥””’a‡{fÍ ÷œmWF9Ö¿ð ¯áH±mcÈÑ./?=Þi}ÊÓjx3æj¢Ãy£8ˆØ· 0ÝVôr[‰ÃÞ,#<à°M*Gây5ê00`Å£­Xײ¤ú<Ìèx½q貟L2W6ßÉ¡ªŽpœïÜBÜjkoŽk™´¢|å¿W/7ú¢á7Bòpyp÷Ô|„d'Äù0k,…‹(±òzªÝŒDþpÚ.¾ Žžt€¿Ç§¨q$°ó0àÏu5ãHéè 7Î*C‡Ar®žŸ&þVÝŸ3jT—Ǻ@ò-…’2èÌÄ J!ÇIÈçõLÔ‹cRZ#¨Æ’•«°+m ­;þŸÅ.ÝxH4Æ5ŽÃú"á_Ƥ²¨½3òS QñƒUQí§4Ÿ;$aëLi3jRãØgà<<¶á5É6Q’WÉ"7NÌéP{S8M(ä\k_‰»8*hãG·›¦%1sã‡îU/NôÁYi¸Cž 5½mtOO“©|ÏŽÁ,Ë”ßr4' :ßéêîE5vnÇøòozAà43n@ýŸÔ¦L_(Æ`dß+oYPÍL'\£¼Ên:H–‹Inl¼¥»‘Q¿œ{Ò+`¢àjÿ°Ä¬«Ì7ˆ~:e»Ø06lÖ:· LouìX—Ï”KnØ?£Œz¶ˆ€¸&¾¾Y˜ÁÕkTâ|§Ýa²æP\¶…F+s6P‰mä6¾eÈÊd‡&¡ØÍÇqÛnT¹¿¶2˜'I·]ÿÉf¶©›:pLö@P9'b»½ƒ4z‘¢ö7G¨XÃKÃøä™z—1™ÐšŽ'$êÖNÆŽîd"ö%à%ÙÓ6 ˜TªúÐã4Þq_áîý~ºÕñ['ëù¯™-$”+Ú¡÷_œœèŒÞñnT· :3}¢SMoYpòÑÔø¡ý‹ÚºpƒÐ!$b_d§Q+¥Œi~Y/eâ·Õö¯k1‹D•MXÎP ü£¨_§–Pœ÷\•G…Ô´MÛG A ØoÊ©©àûÿtE*Z!Ǻé«À 1¾Ñûª?‡s0¼iø ”¤`ë¹Õï£ÂœöÖ²-Š{†óbUÏMÌšÃ~J\ ck¾Afa±<¨È ìr«ŽŽåBÑ[B¥òlÊ~“cýM­‰{Úþ =oP“°X¹škÕLj‘Y÷ÓªA#è_»h²wy]ŽŠËéEÝÔo¼i„^y,«‰Ü)Žô#ÕLjˆ ½`V÷þ2’Ü¡«3B!ëjaîÔØÃëu¹âcŽüí„üДœèé3,º¤W½I³Çl{´lþí%J}u!བÐQe’$…3$c§“ä ÅPñc›KþšVHžUúÚHXAÎ(@3žìÞWxFòÎðxÑÅïuO-…ó¾¯ûߏ֯í´[E¤îõÊTŤ|½8‰wŠQ¼³Oú‹ïÚãˆjÅEçw ¼qH`nFŽ ±b õC¡&R˜˜+yÈ RZ(þIP¤;ÇXÂøyŒ“ú5ëXpQðQÈoa…K:£Öx_ý\²¸ïëgþÝ!\¨hü5¶äEìÂÜÆbÚÈ@ªÁ¢4ã}•# yÙ‘2ýAÞ—=uóÓ~Ó£zj†3 ÐÕ ƒkÓû'²ªª{7÷1À.ndâÃ’ï¶(ÀSc5EŽÀ/-AƒïtÞQg¢Í˜Ã”i  br‚¦£ 9¤û ÊjlTƒäˆ…8ïq6#K³I‹ì…wã$k"³&„ñØ~iíü méµ,æG‰ªM¹)›ÐÑÚ`áÐÉUeçµ4ÍÎJ¶çgÝu'jüªÇõg½á£7~e[—Ã}²°ï„x-O'Øó¬OC×åX` ¤Ë{ãØ_}MI¸Óõï‰Ú,IÓi¯ø1Cøgw|q!•C{SÔ墷‡®R*naËÁK?—€\òÌŒ™ˆØþÁÚœQ+ôn^q…u4õ¨FO-×*¯±ëÚæ òHþã÷µœO/ 6†à “¤FrïÞ&¡=IÿÑîn¸J>UÛü˜¾c§d šñ Í%"ªa¾7n/ìì‹. ç¯Ëá½áhd+ËÓ·Qj‰²^oê@Ê0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 cleartomark endstream endobj 73 0 obj 22071 endobj 74 0 obj 1627 endobj 75 0 obj 19912 endobj 76 0 obj 532 endobj 77 0 obj /RIOVQB+URWPalladioL-Roma-Slant_167 endobj 78 0 obj << /Ascent 715 /CapHeight 680 /Descent -282 /FontName 77 0 R /ItalicAngle -9 /StemV 84 /XHeight 469 /FontBBox [ -166 -283 1021 943 ] /Flags 4 /CharSet (/colon/A/C/E/F/G/H/I/K/M/N/O/P/R/S/T/V/Y) /FontFile 72 0 R >> endobj 29 0 obj << /Type /Pages /Count 1 /Kids [9 0 R] >> endobj 79 0 obj << /Type /Outlines /First 7 0 R /Last 7 0 R /Count 1 >> endobj 7 0 obj << /Title 8 0 R /A 6 0 R /Parent 79 0 R >> endobj 80 0 obj << /Names [(Doc-Start) 11 0 R (Item.1) 13 0 R (Item.2) 14 0 R (Item.3) 15 0 R (Item.4) 16 0 R (Item.5) 17 0 R (Item.6) 18 0 R (chapter*.1) 5 0 R (chapter.1) 12 0 R (page.1) 19 0 R] /Limits [(Doc-Start) (page.1)] >> endobj 81 0 obj << /Kids [80 0 R] >> endobj 82 0 obj << /Dests 81 0 R >> endobj 83 0 obj << /Type /Catalog /Pages 29 0 R /Outlines 79 0 R /Names 82 0 R /PageMode /UseOutlines /URI << /Base () >> /ViewerPreferences << >> /OpenAction 10 0 R >> endobj 84 0 obj << /Author () /Title () /Subject () /Creator (LaTeX with hyperref package) /Producer (pdfTeX13.d) /Keywords () /Creator (TeX) /Producer (pdfTeX-0.13d) /CreationDate (D:20020325161700) >> endobj xref 0 85 0000000000 65535 f 0000003244 00000 n 0000004562 00000 n 0000004649 00000 n 0000004749 00000 n 0000004990 00000 n 0000000009 00000 n 0000114054 00000 n 0000000055 00000 n 0000003129 00000 n 0000000117 00000 n 0000004932 00000 n 0000005047 00000 n 0000005104 00000 n 0000005162 00000 n 0000005220 00000 n 0000005278 00000 n 0000005337 00000 n 0000005396 00000 n 0000004874 00000 n 0000005455 00000 n 0000000166 00000 n 0000003108 00000 n 0000090243 00000 n 0000066128 00000 n 0000044873 00000 n 0000016512 00000 n 0000008578 00000 n 0000005597 00000 n 0000113924 00000 n 0000005729 00000 n 0000006272 00000 n 0000008272 00000 n 0000008293 00000 n 0000008313 00000 n 0000008333 00000 n 0000008353 00000 n 0000008384 00000 n 0000008710 00000 n 0000009242 00000 n 0000014396 00000 n 0000014417 00000 n 0000014437 00000 n 0000014458 00000 n 0000014478 00000 n 0000014509 00000 n 0000014724 00000 n 0000016661 00000 n 0000017653 00000 n 0000044376 00000 n 0000044398 00000 n 0000044419 00000 n 0000044441 00000 n 0000044461 00000 n 0000044503 00000 n 0000045022 00000 n 0000046015 00000 n 0000065755 00000 n 0000065777 00000 n 0000065798 00000 n 0000065820 00000 n 0000065840 00000 n 0000065882 00000 n 0000066277 00000 n 0000067272 00000 n 0000089857 00000 n 0000089879 00000 n 0000089900 00000 n 0000089922 00000 n 0000089942 00000 n 0000089984 00000 n 0000090392 00000 n 0000091384 00000 n 0000113557 00000 n 0000113579 00000 n 0000113600 00000 n 0000113622 00000 n 0000113642 00000 n 0000113694 00000 n 0000113982 00000 n 0000114112 00000 n 0000114343 00000 n 0000114380 00000 n 0000114416 00000 n 0000114588 00000 n trailer << /Size 85 /Root 83 0 R /Info 84 0 R >> startxref 114793 %%EOF gdata/inst/doc/Rnews.sty0000644000176000001440000001556411763451335014766 0ustar ripleyusers%% %% This is file `Rnews.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% Rnews.dtx (with options: `package') %% %% IMPORTANT NOTICE: %% %% For the copyright see the source file. %% %% Any modified versions of this file must be renamed %% with new filenames distinct from Rnews.sty. %% %% For distribution of the original source see the terms %% for copying and modification in the file Rnews.dtx. %% %% This generated file may be distributed as long as the %% original source files, as listed above, are part of the %% same distribution. (The sources need not necessarily be %% in the same archive or directory.) \def\fileversion{v0.3.6} \def\filename{Rnews} \def\filedate{2002/06/02} \def\docdate {2001/10/31} %% %% Package `Rnews' to use with LaTeX2e %% Copyright (C) 2001--2002 by the R Core Development Team %% Please report errors to KH or FL %% %% -*- LaTeX -*- \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{\filename}[\filedate\space\fileversion\space Rnews package] \typeout{Package: `\filename\space\fileversion \@spaces <\filedate>'} \typeout{English documentation as of <\docdate>} \RequirePackage{ifthen} \newboolean{Rnews@driver} \DeclareOption{driver}{\setboolean{Rnews@driver}{true}} \DeclareOption*{\PackageWarning{\filename}{Unknown option `\CurrentOption'}} \ProcessOptions\relax \ifthenelse{\boolean{Rnews@driver}}{}{ \RequirePackage{multicol,graphicx,color,fancyhdr,hyperref} \newcommand{\volume}[1]{\def\Rnews@volume{#1}} \newcommand{\volnumber}[1]{\def\Rnews@number{#1}} \renewcommand{\date}[1]{\def\Rnews@date{#1}} \setcounter{secnumdepth}{-1} \renewcommand{\author}[1]{\def\Rnews@author{#1}} \renewcommand{\title}[1]{\def\Rnews@title{#1}} \newcommand{\subtitle}[1]{\def\Rnews@subtitle{#1}} \newenvironment{article}{% \author{}\title{}\subtitle{}}{\end{multicols}} \renewcommand{\maketitle}{ \begin{multicols}{2}[\chapter{\Rnews@title}\refstepcounter{chapter}][3cm] \ifx\empty\Rnews@subtitle\else\noindent\textbf{\Rnews@subtitle} \par\nobreak\addvspace{\baselineskip}\fi \ifx\empty\Rnews@author\else\noindent\textit{\Rnews@author} \par\nobreak\addvspace{\baselineskip}\fi \@afterindentfalse\@nobreaktrue\@afterheading} \renewcommand\chapter{\secdef\Rnews@chapter\@schapter} \providecommand{\nohyphens}{% \hyphenpenalty=10000\exhyphenpenalty=10000\relax} \newcommand{\Rnews@chapter}{% \renewcommand{\@seccntformat}[1]{}% \@startsection{chapter}{0}{0mm}{% -2\baselineskip \@plus -\baselineskip \@minus -.2ex}{\p@}{% \normalfont\Huge\bfseries\raggedright}} \renewcommand*\l@chapter{\@dottedtocline{0}{0pt}{1em}} \def\@schapter#1{\section*#1} \renewenvironment{figure}[1][]{% \def\@captype{figure} \noindent \begin{minipage}{\columnwidth}}{% \end{minipage}\par\addvspace{\baselineskip}} \renewcommand{\theequation}{\@arabic\c@equation} \def\equation{% \let\refstepcounter\H@refstepcounter \H@equation \def\newname{\arabic{chapter}.\theequation}% \let\theHequation\newname% \hyper@makecurrent{equation}% \Hy@raisedlink{\hyper@anchorstart{\@currentHref}}% \let\refstepcounter\new@refstepcounter}% \def\endequation{\Hy@raisedlink{\hyper@anchorend}\H@endequation} \renewcommand{\thefigure}{\@arabic\c@figure} \renewcommand{\thetable}{\@arabic\c@table} \renewcommand{\contentsname}{Contents of this issue:} \renewcommand\tableofcontents{% \section*{\contentsname \@mkboth{% \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% \@starttoc{toc}} \renewcommand{\titlepage}{% \noindent \rule{\textwidth}{1pt}\\[-.8\baselineskip] \rule{\textwidth}{.5pt} \begin{center} \includegraphics[height=2cm]{Rlogo}\hspace{7mm} \fontsize{2cm}{2cm}\selectfont News \end{center} The Newsletter of the R Project\hfill Volume \Rnews@volume/\Rnews@number, \Rnews@date\\[-.5\baselineskip] \rule{\textwidth}{.5pt}\\[-.8\baselineskip] \rule{\textwidth}{1pt} \vspace{1cm} \fancyhf{} \fancyhead[L]{Vol.~\Rnews@volume/\Rnews@number, \Rnews@date} \fancyhead[R]{\thepage} \fancyfoot[L]{R News} \fancyfoot[R]{ISSN 1609-3631} \thispagestyle{empty} \begin{bottombox} \begin{multicols}{2} \setcounter{tocdepth}{0} \tableofcontents \setcounter{tocdepth}{2} \end{multicols} \end{bottombox}} \setlength{\textheight}{250mm} \setlength{\topmargin}{-10mm} \setlength{\textwidth}{17cm} \setlength{\oddsidemargin}{-6mm} \setlength{\columnseprule}{.1pt} \setlength{\columnsep}{20pt} \RequirePackage{ae,mathpple} \RequirePackage[T1]{fontenc} \renewcommand{\rmdefault}{ppl} \renewcommand{\sfdefault}{aess} \renewcommand{\ttdefault}{aett} \definecolor{Red}{rgb}{0.7,0,0} \definecolor{Blue}{rgb}{0,0,0.8} \definecolor{hellgrau}{rgb}{0.55,0.55,0.55} \newcommand{\R}{R} \newcommand{\address}[1]{\addvspace{\baselineskip}\noindent\emph{#1}} \newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} \newsavebox{\Rnews@box} \newlength{\Rnews@len} \newenvironment{bottombox}{% \begin{figure*}[b] \begin{center} \noindent \begin{lrbox}{\Rnews@box} \begin{minipage}{0.99\textwidth}}{% \end{minipage} \end{lrbox} \addtolength{\Rnews@len}{\fboxsep} \addtolength{\Rnews@len}{\fboxrule} \hspace*{-\Rnews@len}\fbox{\usebox{\Rnews@box}} \end{center} \end{figure*}} \RequirePackage{verbatim} \def\boxedverbatim{% \def\verbatim@processline{% {\setbox0=\hbox{\the\verbatim@line}% \hsize=\wd0 \the\verbatim@line\par}}% \@minipagetrue \@tempswatrue \setbox0=\vbox \bgroup\small\verbatim } \def\endboxedverbatim{% \endverbatim \unskip\setbox0=\lastbox \egroup \fbox{\box0} } \pagestyle{fancy} } % \ifthenelse{\boolean{Rnews@driver}} \newcommand\code{\bgroup\@codex} \def\@codex#1{{\normalfont\ttfamily\hyphenchar\font=-1 #1}\egroup} \newcommand{\kbd}[1]{{\normalfont\texttt{#1}}} \newcommand{\key}[1]{{\normalfont\texttt{\uppercase{#1}}}} \newcommand\samp{`\bgroup\@noligs\@sampx} \def\@sampx#1{{\normalfont\texttt{#1}}\egroup'} \newcommand{\var}[1]{{\normalfont\textsl{#1}}} \let\env=\code \newcommand{\file}[1]{{`\normalfont\textsf{#1}'}} \let\command=\code \let\option=\samp \newcommand{\dfn}[1]{{\normalfont\textsl{#1}}} \newcommand{\acronym}[1]{{\normalfont\textsc{\lowercase{#1}}}} \newcommand{\strong}[1]{{\normalfont\fontseries{b}\selectfont #1}} \let\pkg=\strong \RequirePackage{alltt} \newenvironment{example}{\begin{alltt}}{\end{alltt}} \newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} \newenvironment{display}{\list{}{}\item\relax}{\endlist} \newenvironment{smallverbatim}{\small\verbatim}{\endverbatim} \providecommand{\operatorname}[1]{% \mathop{\operator@font#1}\nolimits} \renewcommand{\P}{% \mathop{\operator@font I\hspace{-1.5pt}P\hspace{.13pt}}} \newcommand{\E}{% \mathop{\operator@font I\hspace{-1.5pt}E\hspace{.13pt}}} \newcommand{\VAR}{\operatorname{var}} \newcommand{\COV}{\operatorname{cov}} \newcommand{\COR}{\operatorname{cor}} \RequirePackage{amsfonts} \endinput %% %% End of file `Rnews.sty'. gdata/inst/doc/Rnews.dtx0000644000176000001440000004601510451013020014713 0ustar ripleyusers\def\fileversion{v0.3.1} \def\filename{Rnews} \def\filedate{2001/09/04} \def\docdate {2001/09/04} % % \iffalse % %% %% Package `Rnews' to use with LaTeX2e %% Copyright (C) 2001 by the R Core Development Team %% Please report errors to KH or FL %% %% -*- LaTeX -*- % % \fi % % \iffalse % \changes{v0.1}{2001/01/05}{First draft.} % \changes{v0.2}{2001/07/01} % {Added macros \cmd\P, \cmd\E, \cmd\VAR, \cmd\COV, \cmd\COR, and % \cmd\operatorname. Require \pkg{amsfonts} to produce symbols for % sets of positive integers etc.} % \changes{v0.3}{2001/08/02} % {Add package option `driver' for typesetting the driver. % Change article environment to use chapters. % Ensure unique figure labels.} % \changes{v0.3.1}{2001/09/04} % {Remove redefinition of |\caption|, which had figures hard-wired. % Instead, have our |figure| environment set |\@captype|.} % \fi % % \MakeShortVerb{\|} % % \newcommand{\AmS}{$${\protect\the\textfont2 A}\kern-.1667em\lower % .5ex\hbox{\protect\the\textfont2 M}\kern % -.125em{\protect\the\textfont2 S}} % \newcommand{\AmSLaTeX}{\mbox{\AmS-\LaTeX}} % % \title{The package \pkg{\filename}} % \author{Kurt Hornik \and Friedrich Leisch} % % \maketitle % % \section{Introduction} % % The \LaTeXe{} package \pkg{\filename} provides commands for formatting % the R Newsletter. % % \section{Documentation} % % \subsection{Marking Words and Phrases} % % The \pkg{Rnews} package provides roughly the same commands for marking % words and phrases as does Texinfo (but note that the \LaTeX special % characters still need special treatment). These commands are % \begin{description} % \item[\code{\cmd{\code}\{\var{sample-code}\}}] % Indicate text that is a literal example of a piece of a program. % \item[\code{\cmd{\kbd}\{\var{keyboard-characters}\}}] % Indicate keyboard input. % \item[\code{\cmd{\key}\{\var{key-name}\}}] % Indicate the conventional name for a key on a keyboard. % \item[\code{\cmd{\samp}\{\var{text}\}}] % Indicate text that is a literal example of a sequence of % characters. % \item[\code{\cmd{\var}\{\var{metasyntactic-variable}\}}] % Indicate a metasyntactic variable. % \item[\code{\cmd{\env}\{\var{environment-variable}\}}] % Indicate an environment variable. % \item[\code{\cmd{\file}\{\var{file-name}\}}] % Indicate the name of a file. % \item[\code{\cmd{\command}\{\var{command-name}\}}] % Indicate a command name (such as \samp{ls}). % \item[\code{\cmd{\option}\{\var{option-name}\}}] % Indicate a command line option. % \item[\code{\cmd{\dfn}\{\var{term}\}}] % Indicate the introductory or defining use of a term. % \item[\code{\cmd{\acronym}\{\var{acronym}\}}] % Use for abbreviattions written in all capital letters, such as % \samp{NASA}. % \end{description} % If this sounds rather confusing, please see the Texinfo documentation % for more details. % % \DescribeMacro{\strong} % There is also a |\strong| command for emphasizing text more strongly % than with |\emph|. For example, |\strong{Note:}| gives \strong{Note:}. % % \DescribeMacro{\pkg} % Finally, use |\pkg| for indicating R packages. % % \subsection{Quotations and Examples} % % In addition to the standard \LaTeX{} for quotations and examples (such % as |quote|, |quotation|, |flushleft|, |center| and |flushright|), the % \pkg{\filename} package provides the following environments. % \begin{description} % \item[\code{example}] % Illustrate code, commands, and the like. The text is printed in a % fixed-width font, and indented but not filled. % \item[\code{smallexample}] % Similar to \code{example}, except that text is typeset in a smaller % font. % \end{description} % % \subsection{Mathematics} % % \DescribeMacro{\P} % \DescribeMacro{\E} % \DescribeMacro{\VAR} % \DescribeMacro{\COV} % \DescribeMacro{\COR} % The commands |\P|, |\E|, |\VAR|, |\COV|, and |\COR| produce symbols % for probability, expectation, variance, covariance and correlation. % For example, Chebyshev's inequality % \DeleteShortVerb{\|} % \begin{displaymath} % \P(|\xi-\E\xi|>\lambda) \le \frac{\VAR(\xi)}{\lambda^2}. % \end{displaymath} % can be coded as % \MakeShortVerb{\|} % \begin{quote} % \verb+\P(|\xi-\E\xi|>\lambda) \le \frac{\VAR(\xi)}{\lambda^2}+. % \end{quote} % % \DescribeMacro{\mathbb} % The symbols % \begin{displaymath} % \mathbb{N}\quad\mathbb{Z}\quad\mathbb{Q}\quad\mathbb{R}\quad\mathbb{C} % \end{displaymath} % for the positive integers, the integers, and the rational, real and % complex numbers, respectively, can be obtained using |\mathbb| from % package \pkg{amsfonts} as % \begin{quote} % |\mathbb{N}| |\mathbb{Z}| |\mathbb{Q}| |\mathbb{R}| |\mathbb{C}| % \end{quote} % % \section{The Code} % % \subsection{The Batch File} % % First comes the code for creating the batch file \file{\filename.ins} % which in turn can be used for producing the package and driver files. % % \begin{macrocode} %<*install> \begin{filecontents}{\filename.ins} % Simply TeX or LaTeX this file to extract various files from the source % file `Rnews.dtx'. \def\filedate{2001/01/05} \def\batchfile{Rnews.ins} \input docstrip.tex \preamble \endpreamble \generateFile{Rnews.drv}{t}{\from{Rnews.dtx}{driver}} \generateFile{Rnews.sty}{t}{\from{Rnews.dtx}{package}} \Msg{***********************************************************} \Msg{* For documentation, run LaTeX on Rnews.dtx or Rnews.drv. *} \Msg{***********************************************************} \end{filecontents} % % \end{macrocode} % % \subsection{The Driver} % % Next comes the documentation driver file for \TeX{}, i.e., the file % that will produce the documentation you are currently reading. It % will be extracted from this file by the \texttt{docstrip} program. % Since it is the first code in the file one can alternatively process % this file directly with \LaTeXe{} to obtain the documentation. % % \begin{macrocode} %<*driver> \documentclass[fleqn]{ltxdoc} \usepackage[driver]{\filename} \renewcommand{\pkg}[1]{\textsf{#1}} \begin{document} \DocInput{\filename.dtx} \end{document} % % \end{macrocode} % % \subsection{The Code} % % Now comes the code for the package. % % It the current format is not \LaTeXe{}, we abort immediately. % Otherwise, we provide ourselves and show the current version of the % package on the screen and in the transscript file. % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{\filename}[\filedate\space\fileversion\space Rnews package] \typeout{Package: `\filename\space\fileversion \@spaces <\filedate>'} \typeout{English documentation as of <\docdate>} % \end{macrocode} % % Next, we set up a more or less trivial option handler. We use option % `driver' for conditionalizing package code we do not want executed % when typesetting the driver file. % \begin{macrocode} \RequirePackage{ifthen} \newboolean{Rnews@driver} \DeclareOption{driver}{\setboolean{Rnews@driver}{true}} \DeclareOption*{\PackageWarning{\filename}{Unknown option `\CurrentOption'}} \ProcessOptions\relax % \end{macrocode} % % Now comes the real code. % % \begin{macrocode} \ifthenelse{\boolean{Rnews@driver}}{}{ % \end{macrocode} % % First we load some utility packages. % \begin{macrocode} \RequirePackage{multicol,graphicx,color,fancyhdr,hyperref} % \end{macrocode} % % \subsubsection{Basic Structure} % % Issues of of \emph{R News} are created from the standard \LaTeX{} % document class \pkg{report}. Individual articles correspond to % chapters, and are contained in |article| environments. This makes it % easy to have figures counted within articles and hence hyperlinked % correctly. % % Basic front matter information about the issue: volume, number, and % date. % \begin{macrocode} \newcommand{\volume}[1]{\def\Rnews@volume{#1}} \newcommand{\volnumber}[1]{\def\Rnews@number{#1}} \renewcommand{\date}[1]{\def\Rnews@date{#1}} % \end{macrocode} % % We do not want numbered sections. % \begin{macrocode} \setcounter{secnumdepth}{-1} % \end{macrocode} % % \begin{macro}{\author} % \begin{macro}{\title} % \begin{macro}{\subtitle} % An article has an author, a title, and optionally a subtitle. We use % the obvious commands for specifying these. % \begin{macrocode} \renewcommand{\author}[1]{\def\Rnews@author{#1}} \renewcommand{\title}[1]{\def\Rnews@title{#1}} \newcommand{\subtitle}[1]{\def\Rnews@subtitle{#1}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{environment}{article} % Environment |article| clears the article header information its begin % and restores single column mode at its end. % \begin{macrocode} \newenvironment{article}{% \author{}\title{}\subtitle{}}{\end{multicols}} % \end{macrocode} % \end{environment} % % \begin{macro}{\maketitle} % The real work is done by a redefined version of |\maketitle|, which % also switches to double column mode. Note that even though we do not % want chapters (articles) numbered, we need to increment the chapter % counter, so that figures get correct labelling. % \begin{macrocode} \renewcommand{\maketitle}{ \chapter{\Rnews@title} \refstepcounter{chapter} \begin{multicols}{2} \ifx\empty\Rnews@subtitle\else\par\addvspace{\baselineskip} \noindent\textbf{\Rnews@subtitle}\fi \ifx\empty\Rnews@author\else\par\addvspace{\baselineskip} \noindent\textit{\Rnews@author}\fi} % \end{macrocode} % \end{macro} % % Now for some ugly redefinitions. We do not want articles to start a % new page. % \begin{macrocode} \renewcommand\chapter{\secdef\@chapter\@schapter} % \end{macrocode} % TOC entries for articles (chapters) should really look like sections. % \begin{macrocode} \renewcommand*\l@chapter{\@dottedtocline{0}{0pt}{1em}} % \end{macrocode} % We need to adjust vertical spacing in |\@makechapterhead|: extra space % before the title only if not at the beginning, no extra space after % it. % \begin{macrocode} \def\@makechapterhead#1{% \addvspace{2\baselineskip}% {\parindent \z@ \raggedright \normalfont \ifnum \c@secnumdepth >\m@ne \huge\bfseries \@chapapp\space \thechapter \par\nobreak \vskip 20\p@ \fi \interlinepenalty\@M \Huge \bfseries #1\par\nobreak}} % \end{macrocode} % We want bibliographies as starred sections within articles. As the % standard |thebibliography| environment uses |chapter*|, we simply % redefine the latter according to our needs. % \begin{macrocode} \def\@schapter#1{\section*#1} % \end{macrocode} % % Package \pkg{multicol}, which is used for producing two-column output, % only allows for starred (single-column) floats (figures and tables). % Therefore, we provide a simple non-floating |figure| environment % ourselves. % \begin{macrocode} \renewenvironment{figure}[1][]{% \def\@captype{figure} \begin{minipage}{0.9\columnwidth}}{ \end{minipage}\par\addvspace{\baselineskip}} % \end{macrocode} % Equations, figures and tables are counted within articles, but we do % not show the article number. % \begin{macrocode} \renewcommand{\theequation}{\@arabic\c@equation} \renewcommand{\thefigure}{\@arabic\c@figure} \renewcommand{\thetable}{\@arabic\c@table} % \end{macrocode} % % \begin{macro}{\tableofcontents} % Need to provide our own version of |\tableofcontents| (no fiddling % with the number of columns). Note that |\section*| is really the same % as |\chapter*|). % \begin{macrocode} \renewcommand{\contentsname}{Contents of this issue:} \renewcommand\tableofcontents{% \section*{\contentsname \@mkboth{% \MakeUppercase\contentsname}{\MakeUppercase\contentsname}}% \@starttoc{toc}} % \end{macrocode} % \end{macro} % \begin{macro}{\titlepage} % The title page of each issue features logo et al at the top and the % TOC. We start with the top. % \begin{macrocode} \renewcommand{\titlepage}{% \noindent \rule{\textwidth}{1pt}\\[-.8\baselineskip] \rule{\textwidth}{.5pt} \begin{center} \includegraphics[height=2cm]{Rlogo}\hspace{7mm} \fontsize{2cm}{2cm}\selectfont News \end{center} The Newsletter of the R Project\hfill Volume \Rnews@volume/\Rnews@number, \Rnews@date\\[-.5\baselineskip] \rule{\textwidth}{.5pt}\\[-.8\baselineskip] \rule{\textwidth}{1pt} \vspace{1cm} % \end{macrocode} % Now set up the header and footer information for the rest of the % document. % \begin{macrocode} \fancyhf{} \fancyhead[L]{Vol.~\Rnews@volume/\Rnews@number, \Rnews@date} \fancyhead[R]{\thepage} \fancyfoot[L]{R News} \fancyfoot[R]{ISSN 1609-3631} \thispagestyle{empty} % \end{macrocode} % And finally, put the TOC at the bottom in a framed box. Note the way % |tocdepth| is adjusted before and after producing the TOC: thus, we % can ensure that only articles show up in the printed TOC, but that in % the PDF version, bookmarks are created for sections and subsections as % well (provided that the non-starred forms are used). % \begin{macrocode} \begin{bottombox} \begin{multicols}{2} \setcounter{tocdepth}{0} \tableofcontents \setcounter{tocdepth}{2} \end{multicols} \end{bottombox}} % \end{macrocode} % \end{macro} % % \subsubsection{Layout, Fonts and Color} % % \paragraph{Layout.} % We set the basic layout parameters in a way that printouts should be % fine for both A4 and Letter paper. % \begin{macrocode} \setlength{\textheight}{250mm} \setlength{\topmargin}{-10mm} \setlength{\textwidth}{17cm} \setlength{\oddsidemargin}{-6mm} \setlength{\columnseprule}{.1pt} \setlength{\columnsep}{20pt} % \end{macrocode} % % \paragraph{Fonts.} % We use the following fonts (all with T1 encoding): % \begin{center} % \begin{tabular}{lp{0.8\textwidth}} % rm & palatino \\ % tt & almost european (computer modern working with T1) \\ % & Reason for aett: uses less horizontal space than courier, % which is better for example code \\ % sf & almost european \\ % math & palatino % \end{tabular} % \end{center} % % \begin{macrocode} \RequirePackage{ae,mathpple} \RequirePackage[T1]{fontenc} \renewcommand{\rmdefault}{ppl} \renewcommand{\sfdefault}{aess} \renewcommand{\ttdefault}{aett} % \end{macrocode} % % \paragraph{Colors.} These are actually used for |\hypersetup| but we % do not call this here, although we should. % \marginpar{FIXME} % \begin{macrocode} \definecolor{Red}{rgb}{0.7,0,0} \definecolor{Blue}{rgb}{0,0,0.8} \definecolor{hellgrau}{rgb}{0.55,0.55,0.55} % \end{macrocode} % % \subsubsection{Miscellania} % % \begin{macrocode} \newcommand{\R}{R} \newcommand{\address}[1]{\addvspace{\baselineskip}\noindent\emph{#1}} \newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} % \end{macrocode} % % \begin{environment}{bottombox} % Used for creating the TOC and the back matter editorial information. % \begin{macrocode} \newsavebox{\Rnews@box} \newlength{\Rnews@len} \newenvironment{bottombox}{% \begin{figure*}[b] \begin{center} \noindent \begin{lrbox}{\Rnews@box} \begin{minipage}{0.99\textwidth}}{% \end{minipage} \end{lrbox} \addtolength{\Rnews@len}{\fboxsep} \addtolength{\Rnews@len}{\fboxrule} \hspace*{-\Rnews@len}\fbox{\usebox{\Rnews@box}} \end{center} \end{figure*}} % \end{macrocode} % \end{environment} % % \begin{environment}{boxedverbatim} % This does not seem to be used any more. % \marginpar{FIXME} % \begin{macrocode} \newenvironment{boxedverbatim}{% \begin{lrbox}{\Rnews@box} \begin{smallverbatim}}{% \end{smallverbatim} \end{lrbox} \hspace*{-\fboxsep}\fbox{\usebox{\Rnews@box}}} % \end{macrocode} % \end{environment} % % Finally, we turn on fancy page style. % \begin{macrocode} \pagestyle{fancy} } % \ifthenelse{\boolean{Rnews@driver}} % \end{macrocode} % % \subsubsection{Marking Words and Phrases} % % Simple font selection is not good enough. For example, |\texttt{--}| % gives `\texttt{--}', i.e., an endash in typewriter font. Hence, we % need to turn off ligatures, which currently only happens for commands % |\code| and |\samp| and the ones derived from them. Hyphenation is % another issue; it should really be turned off inside |\samp|. And % most importantly, \LaTeX{} special characters are a nightmare. E.g., % one needs |\~{}| to produce a tilde in a file name marked by |\file|. % Perhaps a few years ago, most users would have agreed that this may be % unfortunate but should not be changed to ensure consistency. But with % the advent of the WWW and the need for getting `|~|' and `|#|' into % URLs, commands which only treat the escape and grouping characters % specially have gained acceptance (in fact, this is also what % \pkg{alltt} does, and hence environments based on it such as our % |smallexample|). Hence, in the long run we should implement the same % for |\code|, |\kbd|, |\samp|, |\var|, and |\file|. (The other % Texinfo-style commands do not need this.) % % \begin{macrocode} %\newcommand\code{\bgroup\@noligs\@codex} \newcommand\code{\bgroup\@codex} \def\@codex#1{{\normalfont\ttfamily\hyphenchar\font=-1 #1}\egroup} \newcommand{\kbd}[1]{{\normalfont\texttt{#1}}} \newcommand{\key}[1]{{\normalfont\texttt{\uppercase{#1}}}} \newcommand\samp{`\bgroup\@noligs\@sampx} \def\@sampx#1{{\normalfont\texttt{#1}}\egroup'} \newcommand{\var}[1]{{\normalfont\textsl{#1}}} \let\env=\code \newcommand{\file}[1]{{`\normalfont\textsf{#1}'}} \let\command=\code \let\option=\samp \newcommand{\dfn}[1]{{\normalfont\textsl{#1}}} \newcommand{\acronym}[1]{{\normalfont\textsc{\lowercase{#1}}}} \newcommand{\strong}[1]{{\normalfont\fontseries{b}\selectfont #1}} \let\pkg=\strong % \end{macrocode} % % \subsubsection{Quotations and Examples} % % \begin{macrocode} \RequirePackage{alltt} \newenvironment{example}{\begin{alltt}}{\end{alltt}} \newenvironment{smallexample}{\begin{alltt}\small}{\end{alltt}} \newenvironment{display}{\list{}{}\item\relax}{\endlist} % \end{macrocode} % % \subsubsection{Mathematics} % % \begin{macro}{\operatorname} % The implementation of |\operatorname| is similar to the mechanism % \LaTeXe{} uses for functions like sin and cos, and simpler than the % one of \AmSLaTeX{}. We use |\providecommand| for the definition in % order to keep the one of the \pkg{amstex} if this package has % already been loaded. % \begin{macrocode} \providecommand{\operatorname}[1]{% \mathop{\operator@font#1}\nolimits} % \end{macrocode} % \end{macro} % % \begin{macro}{\P} % \begin{macro}{\E} % \begin{macro}{\VAR} % \begin{macro}{\COV} % \begin{macro}{\COR} % Next, we provide commands for probability, expectation, variance, % covariance and correlation which are obviously useful in probability % theory and statistics. % (Of course, originally |\P| gives \mathhexbox27B.) % \begin{macrocode} \renewcommand{\P}{% \mathop{\operator@font I\hspace{-1.5pt}P\hspace{.13pt}}} \newcommand{\E}{% \mathop{\operator@font I\hspace{-1.5pt}E\hspace{.13pt}}} \newcommand{\VAR}{\operatorname{var}} \newcommand{\COV}{\operatorname{cov}} \newcommand{\COR}{\operatorname{cor}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % Finally, we load package \pkg{amsfonts} so that |\mathbb| is available % for producing the symbols for positive integers etc. % \begin{macrocode} \RequirePackage{amsfonts} % \end{macrocode} % % This ends the implementation of the \pkg{\filename} package. % \begin{macrocode} % % \end{macrocode} gdata/inst/bin/0000755000176000001440000000000012024144455013110 5ustar ripleyusersgdata/inst/bin/xls2csv.bat0000644000176000001440000000011111326503712015174 0ustar ripleyusersREM @echo off SET PERLPATH= %~dp0\..\perl\ perl %PERLPATH%\xls2csv.pl %* gdata/inst/bin/xls2csv0000644000176000001440000000011610451013020014416 0ustar ripleyusers#!/bin/sh PERLPATH="`dirname ${0}`/../perl/" perl "${PERLPATH}/xls2csv.pl" $* gdata/inst/NEWS0000644000176000001440000003501612163435365013053 0ustar ripleyusersChanges in 2.13.2 (2013-06-28) ------------------------------ Enhancements: - Simplify ll() by converting a passed list to an environment, avoiding the need for special casing and the use of attach/detach. - Working of deprecation warning message in aggregate.table clarified. Changes in 2.13.1 (2013-03-24) ------------------------------ Enhancements: - Replaced calls to depreciated function ".path.package" with the new public function "path.package". Changes in 2.13.0 (2012-09-20) ----------------------------- New features: - New 'duplicated2' function which returns TRUE for *all* elements that are duplicated, including the first, contributed by Liviu Andronic. This differs from 'duplicated', which only returns the second and following (second-to last and previous when 'fromLast=TRUE') duplicate elements. - New 'ans' functon to return the value of the last evaluated top-level function (a convenience function for accessing .Last.value), contributed by Liviu Andonic. Bug Fixes: - On windows, warning messages printed to stdout by perl were being included in the return value from 'system', resulting in errors in 'sheetCount' and 'sheetNames'. Corrected. - The 'MedUnits' column names 'SIUnits' and 'ConventionalUnits' were reversed and misspelled. Changes in 2.12.0 (2012-09-12) ------------------------------ Other Changes: - 'stats::aggregate' was made into a generic on 27-Jan-2010, so that attempting to call 'aggregate' on a 'table' object will now incorrectly call 'aggregate.table'. Since 'aggregate.table' can be replaced by a call to tapply using two index vectors, e.g. aggregate.table(x, by1=a, by2=b, mean) can be replaced by tapply(x, INDEX=list(a, b), FUN=mean), the 'aggregate.table' function will now display a warning that it is depreciated and recommending the equivalent call to tapply. It will be removed entirely in a future version of gdata. Changes in 2.11.1 (2012-08-22) ------------------------------ Enhancements: - read.xls() now supports fileEncoding argument to allow non-ascii encoded data to be handled. See the manual page for an example. Bug Fixes: - The perl script utilized by read.xls() was incorrectly appending a space character at the end of each line, causing problems with character and NA entries in the final column. Changes in 2.11.0 (2012-06-18) ------------------------------ New Features: - read.xls() and supporting functions now allow blank lines to be preserved, rather than skipped, by supplying the argument "blank.lines.skip=FALSE". The underlying perl function has been extended to suppor this via an optional "-s" argument which, when present, *preserves* blank lines during the conversion. (The default behavior remains unchanged.) Other Changes: - Add SystemRequirements field specifying that perl is necessary for gdata to function fully. Changes in 2.10.6 (2012-06-12) ------------------------------ Bug fixes: - gdata::nobs.default() needs to handle logical vectors in addition to numeric vectors. Changes in 2.10.{3,4,5} (2012-06-08) ------------------------------------ Bug fixes: - Mark example for installXLSsupport() as dontrun so R CMD check won't fail on systems where PERL is not fully functional. - Correct name of installXLSsupport() in tests/test.read.xls.R. Other Changes: - Add dependency on R 2.13.0, since that is when stats::nobs appeared. Changes in 2.10.2 (2012-06-06) --------------------------------------- Bug fixes: - Fix issues in nobs.default identified in testing with the gmodels package. Changes in 2.10.1 (2012-06-06) ------------------------------ Bug fixes: - Undo removal of 'nobs' and 'nobs.lm'. Instead define aliases for 'nobs' and 'nobs.lm' to support backward compatibility for packages depending on gdata. Changes in 2.10.0 (2012-06-05) ------------------------------ New features: - New ls.funs() function to list all objects of class function in the specified environment. - New startsWith() function to determine if a string "starts with" the specified characters. Enhancements: - Add 'na.strings' argument to read.xls() to convert Excel's '#DIV/0!' to NA. Bug fixes: - Correct various R CMD check warnings Other changes: - Base S3 method for nobs() and nobs.lm() method removed since these are now provided in the stats package. Changes in 2.9.0 (2011-09-30) ----------------------------- New features: - Add centerText() function to center text strings for a specified width. - Add case() function, a vectorized variant of the base::switch() function, which is useful for converting numeric codes into factors. Enhancements: - Minor improvements to xls2csv() man page. CHANGES IN 2.8.1 (2011-04-15) ----------------------------- Enhancements: - nPairs() gains a summary method that shows how many times each variable is known, while the other variable of a pair is not Bug fixes: - Fix errors on windows when R or Perl install path includes spaces by properly quoting the path. CHANGES IN 2.8.1 (2010-11-12) ----------------------------- Enhancements: - Minor improvement to Args(), read.xls() man page. Bug fixes: - Modify write.fwf() to capture and pass on additional arguments for write.table(). This resolves a bug reported by Jan Wijffels. - Modify xls2sep.R to avoid use of file.access() which is unreliable on Windows network shares. CHANGES IN 2.8.0 (2010-04-03) ----------------------------- Enhancements: - When loaded, gtools (via an .onAttach() function) now checks: 1) if perl is available 2) whether the perl libraries for XLS support are available 3) whether the perl libraries for XLSX support are available If perl is not available, an appropriate warning message is displayed. If necessary perl libraries are not available, a warning message is displayed, as is a message suggesting the user run the (new) installXLSXsupport() function to attempt to install the necessary perl libraries. - The function installXLSXsupport() has been provided to install the binary perl modules that read.xls needs to support Excel 2007+ 'XLSX' files. CHANGES IN 2.7.3 (2010-04-02) ----------------------------- Enhancements: - New xlsFormats() command to determine which Excel formats are supported (XLS, XLSX). Bug Fixes: - No longer attempt to install perl modules Compress::Raw::Zlib and Spreadsheet::XLSX at build/compile time. This should resolve recent build issues, particularly on Windows. - All perl code can now operate (but generate warnings) when perl modules Compress::Raw::Zlib and Spreadsheet::XLSX when are not installed. - Also update Greg's email address. CHANGES IN 2.7.1 (2010-02-19) ----------------------------- Enhancements: - on Windows attempts to locate ActiveState perl if perl= not specified and Rtools perl would have otherwise been used in read.xls and other perl dependent functions. CHANGES IN 2.7.0 (2010-01-25) ----------------------------- Bug Fixes: - Fix building of Perl libraries on Win32 CHANGES IN 2.7.0 (2010-01-25) ----------------------------- Enhancements: - read.xls() now supports Excel 2007 'xlsx' files. - read.xls() now allows specification of worksheet by name - read.xls() now supports ftp URLs. - Improved ll() so user can limit output to specified classes New Functions: - sheetCount() and sheetNames() to determine the number and names of worksheets in an Excel file, respectively. Bug Fixes: - Fix formatting warning in frameApply(). - Resolve crash of "ll(.GlobalEnv)" - CHANGES IN 2.6.1 (2009-07-15) ----------------------------- Bug Fixes - Modify unit tests to avoid issues related to time zones. CHANGES IN 2.6.0 (2009-07-15) ----------------------------- Bug Fixes - Correct minor typos & issues in man pages for write.fwf(), resample() (Greg Warnes) - Correct calculation of object sizes in env() and ll() (Gregor Gorjanc) New Features - Add support for using tab for field separator during translation from xls format in read.xls (Greg Warnes) - Enhanced function object.size that returns the size of multiple objects. There is also a handy print method that can print size of an object in "human readable" format when options(humanReadable=TRUE) or print(object.size(x), humanReadable=TRUE). (Gregor Gorjanc) - New function wideByFactor that reshapes given dataset by a given factor - it creates a "multivariate" data.frame. (Gregor Gorjanc) - New function nPairs that gives the number of variable pairs in a data.frame or a matrix. (Gregor Gorjanc) - New functions getYear, getMonth, getDay, getHour, getMin, and getSec for extracting the date/time parts from objects of a date/time class. (Gregor Gorjanc) - New function bindData that binds two data frames into a multivariate data frame in a different way than merge. (Gregor Gorjanc) Other Changes - Correct Greg's email address CHANGES IN 2.5.0 ---------------- - New function .runRUnitTestsGdata that enables run of all RUnit tests during the R CMD check as well as directly from within R. - Enhanced function object.size that returns the size of multiple objects. There is also a handy print method that can print size of an object in "human readable" format when options(humanReadable=TRUE) or print(x, humanReadable=TRUE). - New function bindData that binds two data frames into a multivariate data frame in a different way than merge. - New function wideByFactor that reshapes given dataset by a given factor - it creates a "multivariate" data.frame. - New functions getYear, getMonth, getDay, getHour, getMin, and getSec for extracting the date/time parts from objects of a date/time class. - New function nPairs that gives the number of variable pairs in a data.frame or a matrix. - New function trimSum that sums trimmed values. - New function cbindX that can bind objects with different number of rows. - write.fwf gains the width argument. The value for unknown can increase or decrease the width of the columns. Additional tests and documentation fixes. CHANGES IN 2.4.2 (2008-05-11) ----------------------------- - Enhancements and bug fixes for read.xls() and xls2csv(): - More informative log messages when verbose=TRUE - File paths containing spaces or other non-traditional characters are now properly handled - Better error messages, particularly when perl fails to generate an output .csv file. - The 'shortcut' character "~" (meaning user's home directory) is now properly handled in file paths. - XLS files created by OpenOffice are now properly handled. Thanks to Robert Burns for pointing out the patch (http://rt.cpan.org/Public/Bug/Display.html?id=7206) CHANGES IN 2.4.1 (2008-03-24) ----------------------------- - Update perl libraries needed by xls2csv() and read.xls() to latest available versions on CRAN. - Add read.xls() to exported function list - Correct iris.xls example file. It didn't contain the complete & properly formatted iris data set. Fixed. - Fix typo in win32 example for read.xls() CHANGES IN 2.4.0 (2008-01-30) ----------------------------- - The keep() function now includes an 'all' argument to specify how objects with names starting with '.' are handled. - keep() now shows an informative warning message when a requested object does not exist - New vignette "Mapping Levels of a Factor" describing the use of mapLevels(). - New vignette "Working with Unknown Values" describing the use of isUnknown() and unknownToNA(). - Several enhancements to read.xls() (thanks to Gabor Grothendieck): - New function xls2csv(), which handles converting an xls file to a csv file and returns a connection to the temporary csv file - xls2csv() and read.xls() both allow a file or a url to be specified - read.xls() has a new 'pattern' argument which, if supplied, will ignore everything prior to the first line in th csv file that matches the pattern. This is typically used if there are a variable number of comment lines prior to the header in which case one can specify one of the column headings as the pattern. read.xls should be compatible with the old read.xls. - Minor fixes to drop.levels(), is.what(). - Implementation of unit tests for most functions. CHANGES IN 2.3.1 (2006-10-29) ----------------------------- - Arguments as well as their position of reorder.factor have been changed to conform with reorder.factor method in stats package, due to collision bug. Argument 'make.ordered' is now 'order' and old argument 'order' is now 'new.order'! Therefore, you have to implicitly specify new.order i.e. reorder(trt, new.order=c("PLACEBO", "300 MG", "600 MG", "1200 MG")) - trim() gains ... argument. - Added "unknown" methods for matrices. - Added c() method for factors based on mapLevels() functions. - Added write.fwf, which writes file in *F*ixed *W*idth *F*ormat. CHANGES FROM 2.1.X to 2.3.0 (2006-09-19) --------------------------------------- - Added mapLevels(), which produces a map with information on levels and/or internal integer codes. Contributed by Gregor Gorjanc. - Extended dropLevels() to work on the factors contained in a data frame, as well as individual factors. - Add unknown(), which changes given unknown value to NA and vice versa. Contributed by Gregor Gorjanc. - Extended trim() to handle a variety of data types data.frames, lists, factors, etc. Code changes contributed by Gregor Gorjanc. - Added resample() command that acts like sample() except that it _always_ samples from the arguments provided, even if only a single argument is present. This differs from sample() which behaves differently in this case. - Updated my email address. CHANGES IN GDATA 2.1.2 ----------------------- - Fixed bug in interleave.R - option to covert 1-column matrices to vector (based on Andrew Burgess's suggestion) - Updated Greg and Jim's email adresses - ll.R: Suppressed warning message in attach() call. - frameApply.Rd, reorder.Rd: Remove explicit loading of gtools in examples, so that failure to import functions from gtools gets properly caught by running the examples. - upperTriangle.R, man/upperTriangle.Rd: Add functions for extracting and modifying the upper and lower trianglular components of matrices. - is.what.R: Replaced the "not.using" vector with a more robust try(get(test)) to find out whether a particular is.* function returns a logical of length one. - DESCRIPTION: Added Suggests field - Updated the example in frameApply CHANGES IN GDATA 2.0.8 ----------------------- - Added DESCRIPTION and removed DESCRIPTION.in - Updated ll.Rd documentation - Fixed bug in Args.R, is.what.R, ll.R gdata/inst/ChangeLog0000644000176000001440000015246612163435173014134 0ustar ripleyusers2013-06-29 warnes * [r1691] R/ll.R: Simplify ll() by stuffing list arguments into an environment, avoiding the need to use attach/detach. 2013-06-28 warnes * [r1685] inst/NEWS: Update NEWS for gdata 2.13.2 * [r1684] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Minor update to tests/*.Rout.save * [r1683] R/ll.R: Add on.exit() handler to ensure a matching detach occurs when attach is used in ll() * [r1682] DESCRIPTION: Update for gdata 2.13.2 * [r1681] R/aggregate.table.R: Improve deprecated message 2013-03-24 warnes * [r1645] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update test files for code changes * [r1644] inst/NEWS: Fix formatting in NEWS * [r1643] DESCRIPTION, inst/NEWS, man/read.xls.Rd, man/sheetCount.Rd, tests/test.read.xls.R: Replaced calls to depreciated function ".path.package" with the new public function "path.package". 2013-01-14 warnes * [r1639] R/installXLSXsupport.R, R/sheetCount.R, R/xls2sep.R, R/xlsFormats.R: Replace (obsolete) '.path.package' with 'find.package' function. 2012-09-20 warnes * [r1622] man/MedUnits.Rd, man/ans.Rd, man/duplicated2.Rd: Correct .Rd file errors detected by 'R CMD check'. * [r1621] NAMESPACE: Add duplicated() and ans() to the NAMESPACE. * [r1620] DESCRIPTION, inst/NEWS: Update for gdata 2.13.0. * [r1619] man/ConvertMedUnits.Rd: Fix typographic error. * [r1618] R/ans.R, R/duplicated2.R, man/ans.Rd, man/duplicated2.Rd: Add 'ans()' and 'duplicated()' contributed by Liviu Andronic. 2012-09-19 warnes * [r1617] data/MedUnits.rda: Correct column names. Unit columns were reversed and misspelled. * [r1616] R/sheetCount.R: Add ignore.stderr to system command in sheetCmd() to prevent stderr messages from being included in the captured output from the perl script. 2012-09-12 warnes * [r1606] DESCRIPTION, inst/NEWS: Update for gdata 2.12.0 * [r1605] R/aggregate.table.R, man/aggregate.table.Rd: 'stats::aggregate' was made into a generic on 27-Jan-2010, so that attempting to call 'aggregate' on a 'table' object will now incorrectly call 'aggregate.table'. Since 'aggregate.table' can be replaced by a call to tapply using two index vectors, e.g. aggregate.table(x, by1=a, by2=b, mean) can be replaced by tapply(x, INDEX=list(a, b), FUN=mean), the 'aggregate.table' function will now display a warning that it is depreciated and recommending the equivalent call to tapply. It will be removed entirely in a future version of gdata. * [r1604] .Rinstignore: Don't ignore .Rnw files, but do ignore .svn files. 2012-09-11 warnes * [r1603] man/interleave.Rd: Clarify workding of DROP argument to interleave(). * [r1602] man/interleave.Rd: Replace call to aggregate.table() with equivalent tapply() call since aggregate.table() is being depreciated. 2012-08-22 warnes * [r1601] DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for gdate 2.11.1. * [r1600] man/read.xls.Rd: Add example for read.xls() that shows how to use the fileEncoding argument to read in latin-1 encoded data. * [r1599] tests/latin-1.xls, tests/test.read.xls.R, tests/test.read.xls.Rout.save: Add XLSX test for latin-1 characters, and look for them in their new location in inst/xls/. * [r1598] inst/xls/latin-1.xls, inst/xls/latin-1.xlsx: add XLSX version of latin-1.xls * [r1597] tests/latin-1.xls, tests/test.read.xls.R, tests/test.read.xls.Rout.save: Add test file and code to ensure that read.xls() can properly handle files with alternative encodings. latin-1.xls contains each of the non-ascii latin-1 special characters in both the column headings and the body of the file. * [r1596] R/read.xls.R: Change code to have R read the csv/tab data from the file rather than from the connetion we made, so that file encodings can be properly handled. * [r1595] R/read.xls.R: Always close the connection. 2012-08-13 warnes * [r1594] inst/perl/xls2csv.pl: Remove trailing space from output line. 2012-06-18 warnes * [r1567] inst/NEWS: Update NEWS for 2.11.0 release. * [r1566] DESCRIPTION: Bump version number and add SystemRequirements for perl. * [r1565] R/xls2sep.R, inst/perl/xls2csv.pl, man/read.xls.Rd, tests/test.read.xls.R, tests/test.read.xls.Rout.save: read.xls() and supporting functions now allow blank lines to be preserved, rather than skipped, by supplying the argument "blank.lines.skip=FALSE". The underlying perl function has been extended to suppor this via an optional "-s" argument which, when present, *preserves* blank lines during the conversion. 2012-06-13 warnes * [r1564] DESCRIPTION, R/nobs.R, inst/NEWS: - nobs.default needs to handle logical vectors in addition to numeric vectors. - update DESCRIPTION and NEWS for 2.10.6. * [r1563] R/nobs.R: nobs.default needs to handle logical as well as numeric vectors. 2012-06-08 warnes * [r1562] DESCRIPTION, tests/test.read.xls.Rout.save: Update DESCRIPTION and tests * [r1561] tests/test.read.xls.R: fix incorrect function name * [r1560] DESCRIPTION, man/installXLSXsupport.Rd: Mark example for installXLSXsupport() to not be executed durin R CMD check. * [r1559] DESCRIPTION: stats:::nobs.default and stats::nobs.lm require R > 2.13.0, so add this as a dependency. 2012-06-06 warnes * [r1552] DESCRIPTION, inst/NEWS: Update for release 2.10.2 * [r1551] R/nobs.R: Fix bugs in nobs.default. * [r1550] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update to reflect warning on startup that 'nobs' hides 'stats::nobs'. * [r1549] man/nobs.Rd: Remove stray non-ASCII characters. * [r1548] R/nobs.R: The nobs() dispatch method must be defined in the gdata namespace to pick up the definition of gdata::nobs.default. * [r1547] DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for 2.10.1 release. * [r1546] NAMESPACE, R/nobs.R, man/nobs.Rd: Define aliases for 'nobs' and 'nobs.lm' to support backward compatibility for packages depending on gdata. * [r1545] DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for 2.10.0 release * [r1544] NAMESPACE, R/startsWith.R, man/startsWith.Rd: - Add manual page and NAMESPACE entry for startsWith(). - Add 'ignore.case' argument to startsWith(). * [r1543] tests/test.read.xls.Rout.save: Update to match new code. * [r1542] man/read.xls.Rd: Replace non-ASCII characters. * [r1541] R/read.xls.R, man/read.xls.Rd, tests/test.read.xls.R: Add na.strings to read.xls call to convert "#DIV/0!" to NA. 2012-06-05 warnes * [r1540] NAMESPACE: Remove nobs method dispatch and lm methods since these are now provided by the stats package. * [r1539] R/env.R: Spell out arguments to ls() to avoid R CMD check warnings. * [r1538] .Rinstignore: Add .Rinstignore file to omit latex style and source files from distributed inst/doc directory. * [r1537] R/ConvertMedUnits.R: - Add NULL definition of MedUnits to avoid R CMD check warning. - Specify local environment when calling data() so that MedUnits gets defined in the function's environment rather than the global environment. * [r1536] R/ls.funs.R: Fix error in ls.funs() that occurs when there are no objects in the environment. * [r1535] R/object.size.R: Avoid warning by calling utils::object.size rather than Internal(object.size(x)) 2012-05-31 warnes * [r1534] R/nobs.R, man/nobs.Rd: - Remove dispatch function 'nobs' and method 'nobs.lm' since these are now provided by the R 'stats' package. 2012-05-04 warnes * [r1532] DESCRIPTION: Update for next release * [r1531] NAMESPACE, R/ls.funs.R, man/ls.funs.Rd: Add ls.funs() to show functions defined in the specified environment. * [r1530] man/is.what.Rd: Fix enumerate syntax. 2012-04-03 warnes * [r1522] R/startsWith.R: Add startsWith() function. 2011-10-05 warnes * [r1516] man/read.xls.Rd: Fix typo 2011-09-30 warnes * [r1515] inst/NEWS: Update DESCRIPTION and README for 2.9.0 release. * [r1514] DESCRIPTION: Update DESCRIPTION and README for 2.9.0 release. 2011-09-20 warnes * [r1508] man/read.xls.Rd: Improve xls2csv() man page * [r1507] NAMESPACE: Add case() function, a vector equivalent of the switch() function * [r1506] R/case.R, man/case.Rd: Add case() function, a vector equivalent of the switch() function 2011-09-02 warnes * [r1500] NAMESPACE: Add 'centerText' function to center text strings for a specified width. * [r1499] R/centerText.R, man/centerText.Rd: Add 'centerText' function to center text strings for a specified width. 2011-04-16 warnes * [r1469] DESCRIPTION, inst/NEWS: Update for release 2.8.2 2011-04-15 warnes * [r1468] R/dQuote.ascii.R, R/installXLSXsupport.R, R/read.xls.R, R/sheetCount.R, R/xls2sep.R: Fix errors on windows when R or Perl install path includes spaces by properly quoting the path. * [r1467] R/xlsFormats.R: Fix error in xlsFormat() on windows when R or Perl install path includes spaces by quoting the path. 2011-01-15 ggorjan * [r1465] NAMESPACE, R/nPairs.R, inst/NEWS, inst/unitTests/runit.nPairs.R, man/nPairs.Rd: Adding summary method for nPairs 2010-11-12 warnes * [r1462] inst/NEWS: Update NEWS for gdata 2.8.1 * [r1461] DESCRIPTION: Update DEScription file for 2.8.1 release * [r1460] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update test output to match latest code * [r1459] R/write.fwf.R, man/write.fwf.Rd, tests/test.write.fwf.eol.R: Modify write.fwf() to capture and pass on additional arguments for write.table(). This resolves a bug reported by Jan Wijffels. 2010-11-01 arnima * [r1453] man/Args.Rd: Minor improvement in Args.Rd help page 2010-10-19 warnes * [r1452] R/onAttach.R, R/xls2sep.R: Avoid use of file.access() which is unreliable on Windows network shares. 2010-07-08 ggrothendieck2 * [r1448] R/xls2sep.R: findPerl call added to xls2sep 2010-07-07 ggrothendieck2 * [r1447] man/read.xls.Rd: small improvements to read.xls.Rd 2010-05-03 warnes * [r1439] NAMESPACE, R/installXLSXModules.R, R/installXLSXsupport.R, R/onAttach.R, inst/NEWS, man/installXLSXsupport.Rd, man/xlsFormats.Rd: Rename installXLSXModules() to installXLSXsupport() and provide documentation for it. * [r1438] inst/NEWS: Update news for gdata 2.8.0 * [r1437] DESCRIPTION, NAMESPACE, R/installXLSXModules.R, R/onAttach.R, inst/perl/install_modules.pl, inst/perl/module_tools.pl, tests/test.read.xls.R: Add .onAttach function to check & inform user if perl is available, to check whether XLS and XLSX formats are avaiable, and to run the (new) installXLSXModules() functon to attempt to install the necessar libraries if not. Added installXLSXModules() function. 2010-05-02 warnes * [r1436] man/xlsFormats.Rd: Correct error in xlsFormat example * [r1435] DESCRIPTION, NAMESPACE, R/dQuote.ascii.R, R/findPerl.R, R/read.xls.R, R/xlsFormats.R, inst/doc/gregmisc.tex, inst/perl/install_modules.pl, inst/perl/module_tools.pl, inst/perl/sheetCount.pl, inst/perl/supportedFormats.pl, inst/perl/xls2csv.pl, man/ConvertMedUnits.Rd, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/read.xls.Rd, man/rename.vars.Rd, man/reorder.Rd, man/resample.Rd, man/sheetCount.Rd, man/trim.Rd, man/unmatrix.Rd, man/upperTriangle.Rd, man/xlsFormats.Rd, src, tests/test.read.xls.R, tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update perl code to work (but generate warnings) when Zlib or SpreadSheet::XLXS is not instaled. Also update Greg's email address 2010-02-21 ggrothendieck2 * [r1423] R/read.xls.R, man/read.xls.Rd: isOpen problems fixed (isOpen must have changed in R since this worked in earlier versions). Also nba.xls link in read.xls.Rd disappeared. Replaced with similar link. 2010-02-20 ggrothendieck2 * [r1422] INSTALL: improved INSTALL file 2010-02-19 ggrothendieck2 * [r1421] INSTALL, R/dQuote.ascii.R, R/read.xls.R, R/sheetCount.R, inst/NEWS: added findPerl to locate ActiveState Perl on Windows if perl= not specified and Rtools perl would have otherwise been used. Also added INSTALL file. 2010-01-28 warnes * [r1419] DESCRIPTION, inst/NEWS: Update for release 2.7.1 * [r1418] R/xls2sep.R: xls2sep(): Show output of perl call when verbose=T * [r1417] src/build.bat: More Win32 fixes * [r1416] src/Makefile, src/Makefile.win, src/build.bat: More work on Win32 building * [r1415] src/Makefile, src/Makefile.win, src/build.bat: Support building Compress::Raw::Zlib perl package under windows. 2010-01-26 warnes * [r1413] inst/NEWS: Fix typos * [r1412] R/sheetCount.R: Show more details in sheetCount() when verbose=TRUE 2010-01-24 warnes * [r1411] R/xls2sep.R: Replace two calls to 'dQuote', to 'dQuote.ascii' * [r1408] inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Remove auto-generated pdf files from svn * [r1407] src/Makefile: create 'distclean' to remove perl binary dir, currently mac-only * [r1406] R/read.xls.R, R/xls2sep.R: Make read.xls() and xls2sep() quieter when verbose=FALSE * [r1405] tests/test.read.xls.R, tests/test.read.xls.Rout.save: Add tests for read.xls, sheetCount, and sheetNames * [r1404] src/Makefile: Modify makefile to 1) clean up after build, 2) make tar non-verbose * [r1403] R/read.xls.R, R/sheetCount.R: Close connections when done. * [r1402] man/read.xls.Rd: Fix typo * [r1401] man/read.xls.Rd, man/sheetNames.Rd: Fix R CMD CHECK errors * [r1400] src/Compress-Raw-Zlib-2.024, src/Compress-Raw-Zlib-2.024.tar.gz, src/Makefile: Use the original gz file for Compress::Raw::Zlib to avoid issues with 'non-platform-independent' filename error in R CMD CHECK * [r1399] inst/perl/Archive/README-Archive-Zip, inst/perl/Archive/README-Archive::Zip: Rename files to remove R CMD check error * [r1398] DESCRIPTION, inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update for 2.7.0 release * [r1397] NAMESPACE: Add new functions to NAMESPACE * [r1396] src, src/Compress-Raw-Zlib-2.024, src/Compress-Raw-Zlib-2.024/Changes, src/Compress-Raw-Zlib-2.024/MANIFEST, src/Compress-Raw-Zlib-2.024/META.yml, src/Compress-Raw-Zlib-2.024/Makefile.PL, src/Compress-Raw-Zlib-2.024/README, src/Compress-Raw-Zlib-2.024/Zlib.xs, src/Compress-Raw-Zlib-2.024/config.in, src/Compress-Raw-Zlib-2.024/examples, src/Compress-Raw-Zlib-2.024/examples/filtdef, src/Compress-Raw-Zlib-2.024/examples/filtinf, src/Compress-Raw-Zlib-2.024/fallback, src/Compress-Raw-Zlib-2.024/fallback/constants.h, src/Compress-Raw-Zlib-2.024/fallback/constants.xs, src/Compress-Raw-Zlib-2.024/lib, src/Compress-Raw-Zlib-2.024/lib/Compress, src/Compress-Raw-Zlib-2.024/lib/Compress/Raw, src/Compress-Raw-Zlib-2.024/lib/Compress/Raw/Zlib.pm, src/Compress-Raw-Zlib-2.024/pod, src/Compress-Raw-Zlib-2.024/pod/FAQ.pod, src/Compress-Raw-Zlib-2.024/ppport.h, src/Compress-Raw-Zlib-2.024/private, src/Compress-Raw-Zlib-2.024/private/MakeUtil.pm, src/Compress-Raw-Zlib-2.024/t, src/Compress-Raw-Zlib-2.024/t/000prereq.t, src/Compress-Raw-Zlib-2.024/t/01version.t, src/Compress-Raw-Zlib-2.024/t/02zlib.t, src/Compress-Raw-Zlib-2.024/t/07bufsize.t, src/Compress-Raw-Zlib-2.024/t/09limitoutput.t, src/Compress-Raw-Zlib-2.024/t/18lvalue.t, src/Compress-Raw-Zlib-2.024/t/99pod.t, src/Compress-Raw-Zlib-2.024/t/Test, src/Compress-Raw-Zlib-2.024/t/Test/Builder.pm, src/Compress-Raw-Zlib-2.024/t/Test/More.pm, src/Compress-Raw-Zlib-2.024/t/Test/Simple.pm, src/Compress-Raw-Zlib-2.024/t/compress, src/Compress-Raw-Zlib-2.024/t/compress/CompTestUtils.pm, src/Compress-Raw-Zlib-2.024/typemap, src/Compress-Raw-Zlib-2.024/zlib-src, src/Compress-Raw-Zlib-2.024/zlib-src/adler32.c, src/Compress-Raw-Zlib-2.024/zlib-src/compress.c, src/Compress-Raw-Zlib-2.024/zlib-src/crc32.c, src/Compress-Raw-Zlib-2.024/zlib-src/crc32.h, src/Compress-Raw-Zlib-2.024/zlib-src/deflate.c, src/Compress-Raw-Zlib-2.024/zlib-src/deflate.h, src/Compress-Raw-Zlib-2.024/zlib-src/infback.c, src/Compress-Raw-Zlib-2.024/zlib-src/inffast.c, src/Compress-Raw-Zlib-2.024/zlib-src/inffast.h, src/Compress-Raw-Zlib-2.024/zlib-src/inffixed.h, src/Compress-Raw-Zlib-2.024/zlib-src/inflate.c, src/Compress-Raw-Zlib-2.024/zlib-src/inflate.h, src/Compress-Raw-Zlib-2.024/zlib-src/inftrees.c, src/Compress-Raw-Zlib-2.024/zlib-src/inftrees.h, src/Compress-Raw-Zlib-2.024/zlib-src/trees.c, src/Compress-Raw-Zlib-2.024/zlib-src/trees.h, src/Compress-Raw-Zlib-2.024/zlib-src/uncompr.c, src/Compress-Raw-Zlib-2.024/zlib-src/zconf.h, src/Compress-Raw-Zlib-2.024/zlib-src/zlib.h, src/Compress-Raw-Zlib-2.024/zlib-src/zutil.c, src/Compress-Raw-Zlib-2.024/zlib-src/zutil.h, src/Makefile: Add Compress::Raw::Zlib code * [r1395] man/read.xls.Rd, man/sheetCount.Rd: Add/Update documentation * [r1394] R/xls2sep.R: Minor formatting change * [r1393] inst/xls/ExampleExcelFile.xls, inst/xls/ExampleExcelFile.xlsx: Add additional example files * [r1392] inst/perl/sheetCount.pl, inst/perl/sheetNames.pl, inst/perl/xls2csv.pl: Combine sheetCount.pl and sheetNames.pl and modify to support Excel 2007 'xlsx' format * [r1391] inst/perl/Spreadsheet/XLSX.pm, inst/perl/Spreadsheet/XLSX/Fmt2007.pm, inst/perl/xls2csv.pl: Complete changes to handle Excel 2007 'xlsx' files * [r1390] inst/perl/Archive, inst/perl/Archive/README-Archive::Zip, inst/perl/Archive/Zip, inst/perl/Archive/Zip.pm, inst/perl/Archive/Zip/Archive.pm, inst/perl/Archive/Zip/BufferedFileHandle.pm, inst/perl/Archive/Zip/DirectoryMember.pm, inst/perl/Archive/Zip/FAQ.pod, inst/perl/Archive/Zip/FileMember.pm, inst/perl/Archive/Zip/Member.pm, inst/perl/Archive/Zip/MemberRead.pm, inst/perl/Archive/Zip/MockFileHandle.pm, inst/perl/Archive/Zip/NewFileMember.pm, inst/perl/Archive/Zip/StringMember.pm, inst/perl/Archive/Zip/Tree.pm, inst/perl/Archive/Zip/ZipFileMember.pm, inst/perl/OLE/README-OLE-Storage_Lite, inst/perl/Spreadsheet/README-ParseExcel, inst/perl/Spreadsheet/README-XLS, inst/perl/Spreadsheet/XLSX, inst/perl/Spreadsheet/XLSX.pm, inst/perl/Spreadsheet/XLSX/Fmt2007.pm, inst/perl/Spreadsheet/XLSX/Utility2007.pm, inst/perl/VERSIONS: Add additional Perl modules to support Excel 2007 'xlsx' files 2010-01-24 ggrothendieck2 * [r1389] NAMESPACE, man/sheetNames.Rd: added sheetNames.Rd (documenting sheetNames/sheetCount) and updated NAMESPACE file. * [r1388] inst/NEWS: fixed spacing problem in NEWS 2010-01-23 warnes * [r1387] inst/perl/xls2csv.pl: Check if parsing the xls file succeeds... Current code doesn't handle new XML-based format * [r1386] inst/perl/Spreadsheet/XLSX: Remove perl 'Spreadsheet:XLSX' module since it depends on Compress-Raw-Zlib, which probably won't be available on most machines, and I don't have time to figure out how to get R to build it properly when gdata is installed. * [r1385] inst/perl/Spreadsheet/XLSX, inst/perl/Spreadsheet/XLSX/Fmt2007.pm, inst/perl/Spreadsheet/XLSX/Utility2007.pm: Add perl 'Spreadsheet:XLSX' module to support new Excel XML format files * [r1384] R/xls2sep.R: Add xls2tsv() convenience wrapper to xls2sep() * [r1383] R/read.xls.R, R/xls2sep.R: Update to match new xls2csv.pl code, allow specification of sheets by name, support CSV and TAB delimited files using the same code, other minor changes. * [r1382] R/sheetCount.R: Add sheetNames() function to extract the names from XLS files * [r1381] inst/bin/xls2csv.bat: Fix xls2csv.bat * [r1380] inst/perl/xls2csv.pl: If only one sheet is present in the file, don't insert the sheet name into the filename * [r1379] inst/xls/ExampleExcelFile.xls, inst/xls/ExampleExcelFile.xlsx: Add additional test/example Excel files * [r1378] inst/perl/xls2csv.pl, inst/perl/xls2tab.pl, inst/perl/xls2tsv.pl: Modify xls2csv.pl script to: - Use tab-delimiter and .tsv or .tab extension if called with the name xls2tsv.pl or xls2tab.pl, respectively. This allows a single source file and two symlinks to be used intstead of maintaining several almost-identical files. - Allow selection of sheets by name - Provide better error checking - Other code improvements * [r1377] inst/perl/sheetCount.pl, inst/perl/sheetNames.pl: Add perl scripts to extract worksheet names and sheet count from Excel files 2010-01-22 warnes * [r1376] inst/perl/OLE/Storage_Lite.pm: Upgrade Perl OLE::StorageLight module to version 0.19 * [r1375] inst/perl/Spreadsheet/ParseExcel.pm, inst/perl/Spreadsheet/ParseExcel/Cell.pm, inst/perl/Spreadsheet/ParseExcel/Dump.pm, inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm, inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm, inst/perl/Spreadsheet/ParseExcel/Font.pm, inst/perl/Spreadsheet/ParseExcel/Format.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser, inst/perl/Spreadsheet/ParseExcel/SaveParser.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser/Workbook.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser/Worksheet.pm, inst/perl/Spreadsheet/ParseExcel/Utility.pm, inst/perl/Spreadsheet/ParseExcel/Workbook.pm, inst/perl/Spreadsheet/ParseExcel/Worksheet.pm: Upgrade perl Spreadsheet::ParseExcel to version 0.56 * [r1374] DESCRIPTION: Add complete list of contributors 2010-01-22 arnima * [r1373] man/keep.Rd: Minor improvement in help page * [r1371] R/Args.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R, man/Args.Rd, man/env.Rd, man/is.what.Rd, man/keep.Rd, man/ll.Rd: Many small improvements to documentation of Arni's five functions 2010-01-22 warnes * [r1370] R/dQuote.ascii.R, R/read.xls.R, R/sheetCount.R, R/xls2sep.R: - Move xls2csv(), xls2tab(), xls2sep() to a separate file - Move qQuote.ascii to a separate file - Bug Fix: xls2csv(), xls2tab() failed to pass the provided 'perl' parameter to xls2sep() - New Feature: xls2sep() (and hence xls2csv, xls2tab, and read.xls) now supports ftp URLs. 2009-12-06 arnima * [r1369] R/Args.R, man/Args.Rd: Minor improvements of Args(). * [r1368] R/ll.R, man/ll.Rd: Improved ll() so user can limit output to specified classes 2009-11-16 arnima * [r1366] R/ll.R: ll(.GlobalEnv) does not crash anymore 2009-08-20 warnes * [r1357] man/cbindX.Rd, man/getDateTimePart.Rd, man/mapLevels.Rd, man/nPairs.Rd, man/trim.Rd, man/trimSum.Rd, man/unknown.Rd, man/write.fwf.Rd: Replace \ldots with \dots to make the new R CMD CHECK happy. 2009-08-19 warnes * [r1355] DESCRIPTION: Update for 2.6.1 release * [r1354] inst/unitTests/runit.getDateTimeParts.R: Modify unit tests to avoid issues related to zime zones. 2009-08-05 warnes * [r1353] inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update vignettes for 2.6.0 release * [r1352] man/frameApply.Rd: Fix formatting warning in frameApply man page 2009-07-16 ggorjan * [r1350] man/write.fwf.Rd: Reverting recent change and clarifying the meaning. 2009-07-16 warnes * [r1349] inst/doc/mapLevels.pdf, inst/doc/unknown.pdf, man/resample.Rd: Add contents of \value section for resample() man page * [r1348] tests/tests.write.fwf.Rout.save: Update test output to remove R CMD check warning * [r1347] inst/NEWS: Update ChangeLog and NEWS for gdata 2.6.0 release * [r1346] DESCRIPTION: Update DESCRIPTION file for gdata 2.6.0 * [r1345] inst/doc/gregmisc.tex, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf, man/ConvertMedUnits.Rd, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/rename.vars.Rd, man/reorder.Rd, man/trim.Rd, man/unmatrix.Rd, man/upperTriangle.Rd: Correct Greg's email address * [r1344] man/write.fwf.Rd: Correct minor typos in write.fwf() man page * [r1343] man/resample.Rd: Correct page for resample() * [r1342] NAMESPACE, R/read.xls.R, inst/perl/xls2tab.pl, man/read.xls.Rd: Add support for using tab for field separator during translation from xls format in read.xls 2009-04-19 arnima * [r1314] R/env.R, R/ll.R: Changed object.size(object) to unclass(object.size(object)). 2008-12-31 ggorjan * [r1312] NAMESPACE, inst/NEWS: Documenting changes and exporting the functions. * [r1311] R/object.size.R, man/humanReadable.Rd, man/object.size.Rd: Enhanced function object.size that returns the size of multiple objects. There is also a handy print method that can print size of an object in "human readable" format when options(humanReadable=TRUE) or print(object.size(x), humanReadable=TRUE). * [r1310] R/wideByFactor.R, inst/unitTests/runit.wideByFactor.R, man/wideByFactor.Rd: New function wideByFactor that reshapes given dataset by a given factor - it creates a "multivariate" data.frame. * [r1309] R/nPairs.R, inst/unitTests/runit.nPairs.R, man/nPairs.Rd: New function nPairs that gives the number of variable pairs in a data.frame or a matrix. * [r1308] R/getDateTimeParts.R, inst/unitTests/runit.getDateTimeParts.R, man/getDateTimePart.Rd: New functions getYear, getMonth, getDay, getHour, getMin, and getSec for extracting the date/time parts from objects of a date/time class. * [r1307] R/bindData.R, inst/unitTests/runit.bindData.R, man/bindData.Rd: New function bindData that binds two data frames into a multivariate data frame in a different way than merge. * [r1306] R/runRUnitTests.R, inst/unitTests/Makefile, inst/unitTests/runRUnitTests.R, man/gdata-package.Rd, man/runRUnitTests.Rd, tests/doRUnit.R: New function .runRUnitTestsGdata that enables run of all RUnit tests during the R CMD check as well as directly from within R. 2008-12-20 ggorjan * [r1305] NAMESPACE, R/trimSum.R, inst/NEWS, inst/unitTests/runit.trimSum.R, man/trimSum.Rd: * [r1304] tests/tests.write.fwf.Rout.save: To remove some output in the R CMD check 2008-08-05 ggorjan * [r1300] DESCRIPTION, NAMESPACE, R/cbindX.R, R/write.fwf.R, inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf, inst/unitTests/runit.cbindX.R, inst/unitTests/runit.write.fwf.R, man/cbindX.Rd, man/write.fwf.Rd, tests/tests.write.fwf.R, tests/tests.write.fwf.Rout.save: - Increased version to 2.5.0 - New function cbindX that can bind objects with different number of rows. - write.fwf gains width argument. Unknown values can increase or decrease the width of the columns. Additional tests and documentation fixes. 2008-06-30 arnima * [r1299] R/env.R, R/ll.R, man/env.Rd, man/ll.Rd: Simplified default 'unit' argument from c("KB","MB","bytes") to "KB". 2008-05-13 warnes * [r1270] inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update NEWS file for 2.4.2 * [r1269] R/read.xls.R: Use path.expand() to give proper full path to xls file to be translated by read.xls() * [r1268] R/read.xls.R: Modifed read.xls() failed to return the converted data... fixed. * [r1267] inst/perl/Spreadsheet/ParseExcel/Utility.pm: Correct broken patch for open-office support * [r1266] DESCRIPTION, R/read.xls.R: For read.xls() and xls2csv(): - Implement more informative log messages when verbose=TRUE - Quote temporary file name to avoid errors when calling perl to do the work. - Add better error messages, particularly when perl fails to generate an output .csv file. Update version number in DESCRIPTION. 2008-05-12 warnes * [r1265] inst/perl/Spreadsheet/ParseExcel/Utility.pm: Patch to correct issue with OpenOffice-created XLS files. Thanks to Robert Burns for pointing out the patch at http://rt.cpan.org/Public/Bug/Display.html?id=7206 2008-03-25 warnes * [r1250] DESCRIPTION, inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update for version 2.4.1 * [r1249] inst/xls/iris.xls: Example iris.xls file didn't complete & properly formatted iris data set. Fixed. * [r1248] inst/perl/IO/AtomicFile.pm, inst/perl/IO/InnerFile.pm, inst/perl/IO/Lines.pm, inst/perl/IO/Scalar.pm, inst/perl/IO/ScalarArray.pm, inst/perl/IO/Stringy.pm, inst/perl/IO/Wrap.pm, inst/perl/IO/WrapTie.pm, inst/perl/OLE/Storage_Lite.pm, inst/perl/Spreadsheet/ParseExcel.pm, inst/perl/Spreadsheet/ParseExcel/Dump.pm, inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm, inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser.pm, inst/perl/Spreadsheet/ParseExcel/Utility.pm: Update perl modules to latest versions 2008-03-24 warnes * [r1247] man/read.xls.Rd: Fix typo in win32 example for read.xls() 2008-03-11 warnes * [r1246] NAMESPACE: Add xls2csv to exported function list 2008-01-30 warnes * [r1241] ChangeLog, DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for release 2.4.0 2008-01-29 arnima * [r1240] man/keep.Rd: Added argument 'all'. * [r1239] R/keep.R: Added argument 'all'. 2007-10-22 warnes * [r1196] DESCRIPTION: Clarify GPL version 2007-09-10 ggorjan * [r1169] man/upperTriangle.Rd: removed unmatched brace * [r1168] man/gdata-package.Rd: adding alias 2007-09-06 ggorjan * [r1162] man/gdata-package.Rd: keyword 2007-08-21 ggorjan * [r1154] man/gdata-package.Rd: package help page * [r1153] NEWS, inst/NEWS: move * [r1152] NEWS: move 2007-08-20 ggorjan * [r1151] inst/doc/mapLevels.tex: clean * [r1150] inst/doc/mapLevels.Rnw, inst/doc/mapLevels.pdf, inst/doc/mapLevels.tex: a real vignette * [r1149] inst/doc/unknown.Rnw, inst/doc/unknown.pdf, inst/doc/unknown.tex: a real vignette * [r1148] man/unknown.Rd: additional keyword for searchig 2007-08-17 ggorjan * [r1147] man/unknown.Rd: keyword 2007-07-22 arnima * [r1103] R/Args.R, R/keep.R: Reverted back to as.character(substitute(x)), so user can run keep(x), keep("x"), Args(x), and Args("x"). 2007-07-21 arnima * [r1102] R/keep.R: Changed as.character(substitute()) to deparse(substitute()), following help(substitute) recommendation. * [r1101] R/Args.R: Changed as.character(substitute()) to deparse(substitute()), following help(substitute) recommendation. 2007-07-10 warnes * [r1099] R/read.xls.R, man/read.xls.Rd: Update read.xls() code and docs with enhacements by Gabor Grothendieck 2007-06-06 ggorjan * [r1097] inst/doc/unknown.pdf, inst/doc/unknown.tex: last edits from newsletter * [r1096] R/drop.levels.R, man/drop.levels.Rd: drop levels as suggested by Brian Ripley * [r1095] inst/unitTests/Makefile, tests/doRUnit.R: better integration of unit tests * [r1094] R/mapLevels.R, R/unknown.R: making codetools happy 2007-01-28 arnima * [r1042] R/keep.R: Throw warnings rather than errors 2007-01-27 arnima * [r1041] R/keep.R: Meaningful error message is given when requested object does not exist * [r1040] R/is.what.R: is.* tests that return NA are not reported is.what recursion is avoided 2006-11-30 ggorjan * [r1035] R/unknown.R: minor commet to the code * [r1034] inst/doc/mapLevels.pdf, inst/doc/mapLevels.tex: description of mapLevels methods * [r1033] inst/doc/unknown.pdf, inst/doc/unknown.tex: description of unknown methods 2006-11-16 ggorjan * [r1013] R/c.factor.R, man/c.factor.Rd: seems that c.factor was not a good idea and there were better examples posted on r-devel list 2006-11-14 ggorjan * [r1012] man/combine.Rd, man/frameApply.Rd: Removed executable property 2006-11-10 ggorjan * [r1004] NAMESPACE, NEWS: just formatting 2006-11-02 ggorjan * [r1002] man/mapLevels.Rd, man/unknown.Rd: typos 2006-10-30 ggorjan * [r1001] man/write.fwf.Rd: some more examples for use of read.fwf after write.fwf * [r1000] inst/unitTests: ignore for report files * [r999] tests/tests.write.fwf.Rout.save: Id tag from source * [r998] NAMESPACE: removing unused import * [r997] R/write.fwf.R, inst/unitTests/runit.write.fwf.R, man/write.fwf.Rd, tests/tests.write.fwf.R: Id tag * [r996] NAMESPACE, NEWS, R/write.fwf.R, inst/unitTests/runit.write.fwf.R, man/write.fwf.Rd, tests/tests.write.fwf.R, tests/tests.write.fwf.Rout.save: write.fwf * [r995] inst/unitTests/runit.reorder.factor.R: Id tag * [r994] inst/unitTests/runit.reorder.factor.R: added unit tests for reorder.factor * [r993] R/c.factor.R, R/mapLevels.R, R/unknown.R, inst/unitTests/runit.drop.levels.R, inst/unitTests/runit.mapLevels.R, inst/unitTests/runit.trim.R, inst/unitTests/runit.unknown.R, man/c.factor.Rd, man/unknown.Rd, tests/doRUnit.R: mapply keeps names in R 2.4; POSIX unit tests solved; $ should work now 2006-10-29 ggorjan * [r992] NEWS, R/unknown.R, inst/unitTests/runit.unknown.R, man/unknown.Rd: fixed problem in tests; added unknown methods and tests for matrices * [r991] R/drop.levels.R, R/mapLevels.R, inst/unitTests/runit.mapLevels.R, man/mapLevels.Rd, tests/doRUnit.R: sort is generic now; mapply keeps names in R 2.4.0; some codetools suggestions fixed * [r990] DESCRIPTION, NAMESPACE: sort is generic from R 2.4.0 * [r989] DESCRIPTION, NEWS, R/trim.R, man/trim.Rd: trim() gains ... argument; version bump * [r988] NEWS, R/reorder.R, man/reorder.Rd: Fixed collision bug with stats version of reorder.factor 2006-10-27 warnes * [r987] R/c.factor.R, man/c.factor.Rd: Add c() method for factor objects, submitted by Gregor Gorjanc 2006-09-19 warnes * [r986] NEWS: Update NEWS file for 2.3.0 release * [r985] inst/unitTests/runit.trim.R: Explicitly set the local in runit.trim.R to one where leading spaces affect sort order so that the unit test works properly. 2006-09-18 warnes * [r984] inst/doc/Rnews.sty: Update Rnews.sty to the latest version * [r983] R/trim.R, inst/unitTests/Makefile, inst/unitTests/runit.trim.R, man/trim.Rd, tests/doRUnit.R: Integrate fixes for trim() from Gregor and myself. * [r982] inst/unitTests/report.html, inst/unitTests/report.txt: Remove unneeded files. 2006-09-13 warnes * [r981] R/unknown.R, inst/unitTests, inst/unitTests/Makefile, inst/unitTests/report.html, inst/unitTests/report.txt, inst/unitTests/runit.drop.levels.R, inst/unitTests/runit.mapLevels.R, inst/unitTests/runit.trim.R, inst/unitTests/runit.unknown.R, man/unknown.Rd, tests, tests/doRUnit.R: Add unknown() and unit test files * [r980] NAMESPACE, R/drop.levels.R, R/mapLevels.R, R/trim.R: More fixes from Gregor Gorjanc * [r979] DESCRIPTION, NAMESPACE, R/combineLevels.R, R/mapFactor.R, R/mapLevels.R, man/combineLevels.Rd, man/mapFactor.Rd, man/mapLevels.Rd: Add mapLevels functions from Gregor Gorjanc, along with associated unit tests. 2006-08-03 warnes * [r978] DESCRIPTION, NAMESPACE, R/combineLevels.R, R/mapFactor.R, man/combineLevels.Rd, man/mapFactor.Rd: Add Gregor Gorjanc's mapFactor() and combineLevels() functions. 2006-08-02 warnes * [r977] inst/doc/gregmisc.tex, man/ConvertMedUnits.Rd, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/read.xls.Rd, man/rename.vars.Rd, man/reorder.Rd, man/trim.Rd, man/unmatrix.Rd, man/upperTriangle.Rd: Update my email address * [r976] data/MedUnits.rda: Remove MedUnits.rda to convert to binary format * [r975] data/MedUnits.rda: Remove MedUnits.rda to convert to binary format * [r974] DESCRIPTION: Update version number * [r973] NAMESPACE, R/drop.levels.R, R/trim.R, man/drop.levels.Rd, man/trim.Rd: Integrate changes suggested by Gregor Gorjanc 2006-03-14 nj7w * [r940] NAMESPACE, R/trim.R, man/resample.Rd: Fixed R CMD check errors and added trim.default to NAMESPACE 2006-03-13 nj7w * [r939] R/trim.R: Added trim.character and trim.factor as per Gregor's suggestions 2006-01-03 warnes * [r839] NAMESPACE, R/resample.R, man/resample.Rd: Add resample() function, which generates a random sample or permutation from the elements of the supplied vector, even if the vector has length 1. This avoide the problems caused by base::sample()'s special case for vectors of length 1, where it attempts to sample from 1:x. 2005-12-13 nj7w * [r806] ChangeLog, NEWS: Updated news and removed changelog 2005-12-12 nj7w * [r798] DESCRIPTION, man/interleave.Rd: Updated version number for CRAN release 2005-12-08 warnes * [r789] R/interleave.R: Andrew Burgess reported that interleave() converts 1-column matrixes to vectors and provided a patch. A slight modification of his patch has been applied. There is now a 'drop' argument, which controls whether 'unnecessary' dimensions are dropped. The default is FALSE. 2005-12-04 warnes * [r779] man/interleave.Rd: Andrew Burgess reported that interleave() converts 1-column matrixes to vectors and provided a patch. A slight modification of his patch has been applied. There is now a 'drop' argument, which controls whether 'unnecessary' dimensions are dropped. The default is FALSE. 2005-12-01 nj7w * [r775] man/combine.Rd, man/reorder.Rd: Updated Greg's email address * [r774] man/drop.levels.Rd, man/frameApply.Rd, man/ll.Rd, man/read.xls.Rd: Updated Jim's email address 2005-11-21 arnima * [r744] R/ll.R: Suppressed warning message in attach() call. 2005-10-27 warnes * [r716] DESCRIPTION: Bump version number again to show that I fixed a bug. * [r715] DESCRIPTION, R/upperTriangle.R: Update version number * [r714] man/frameApply.Rd, man/reorder.Rd: Remove explicit loading of gtools in examples, so that failure to import functions from gtools gets properly caught by running the examples. * [r713] man/upperTriangle.Rd: Add missing close-bracket * [r712] NAMESPACE: Add upperTriangle and friends * [r711] R/upperTriangle.R, man/upperTriangle.Rd: Add functions for extracting, modifying upper and lower trianglular components of matrices. 2005-10-19 arnima * [r695] R/is.what.R: Replaced the "not.using" vector with a more robust try(get(test)) to find out whether a particular is.* function returns a logical of length one. 2005-09-12 nj7w * [r671] man/aggregate.table.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/read.xls.Rd, man/rename.vars.Rd, man/trim.Rd, man/unmatrix.Rd: Updated Greg's email 2005-09-06 nj7w * [r661] man/reorder.Rd: Added library(gtools) in the example * [r660] NAMESPACE: Removed gtools dependency from NAMESPACE, as it was being used only in an example, and was giving warning * [r659] DESCRIPTION: Added Suggests field 2005-09-02 nj7w * [r658] man/frameApply.Rd: Updated the example in frameApply * [r656] NEWS: Added NEWS * [r654] ChangeLog: ChangeLog 2005-08-31 nj7w * [r644] DESCRIPTION: Added DESCRIPTION file * [r643] DESCRIPTION.in: removed DESCRIPTION.in 2005-07-20 nj7w * [r631] man/ll.Rd: updated documentation * [r630] R/Args.R: ## Args() was using a different search path from args(), e.g. rep <- function(local) return(NULL) args() Args() ## Fixed * [r629] R/is.what.R: ## is.what() was giving needless warnings for functions, e.g. is.what(plot) ## Fixed * [r628] R/ll.R: ## ll() was crashing if argument was a list of length zero, e.g. x <- list() ll(x) ## Fixed, and added sort.elements (see new help page) 2005-06-09 nj7w * [r625] R/Args.R, R/aggregate.table.R, R/combine.R, R/elem.R, R/env.R, R/frameApply.R, R/interleave.R, R/is.what.R, R/keep.R, R/ll.R, R/matchcols.R, R/nobs.R, R/read.xls.R, R/rename.vars.R, R/reorder.R, R/trim.R, R/unmatrix.R, inst/perl/IO/AtomicFile.pm, inst/perl/IO/InnerFile.pm, inst/perl/IO/Lines.pm, inst/perl/IO/Scalar.pm, inst/perl/IO/Scalar.pm.html, inst/perl/IO/ScalarArray.pm, inst/perl/IO/Stringy.pm, inst/perl/IO/Wrap.pm, inst/perl/IO/WrapTie.pm, man/aggregate.table.Rd, man/combine.Rd, man/drop.levels.Rd, man/interleave.Rd, man/nobs.Rd, man/rename.vars.Rd, man/reorder.Rd: Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. 2005-06-07 nj7w * [r622] R/drop.levels.R: Reverting to the previous version of drop.levels.R by replacing sapply(...) with as.data.frame(lapply(...)) because sapply has the undesirable effect of converting the object to a matrix, which in turn coerces the factors to numeric. 2005-05-13 nj7w * [r621] R/read.xls.R: 1) Using dQuote.ascii function in read.xls as the new version of dQuote doesn't work proprly with UTF-8 locale. 2) Modified CrossTable.Rd usage in gmodels 3) Modified heatmap.2 usage in gplots. 2005-04-02 warnes * [r600] NAMESPACE, R/drop.levels.R, man/drop.levels.Rd: Move drop.levels() from gtools to gdata. * [r598] NAMESPACE, R/frameApply.R, man/frameApply.Rd: Move frameApply() to gdata package. 2005-03-31 warnes * [r586] man/elem.Rd: Comment out example to avoid R CMD check warnings 2005-03-22 warnes * [r578] NAMESPACE, R/ConvertMedUnits.R, data/MedUnits.Rda, data/MedUnits.rda, man/ConvertMedUnits.Rd, man/MedUnits.Rd: Fixes to pass `R CMD check'. * [r577] R/Args.R, R/env.R, R/ll.R, man/Args.Rd: Integrated fixes from Arni. * [r576] man/read.xls.Rd: Improve documentation of 'perl' argument and give examples. 2005-03-09 warnes * [r573] R/ConvertMedUnits.R, man/ConvertMedUnits.Rd, man/MedUnits.Rd: - Add ConvertMedUnits() plus documentation - Add documentation for MedUnits data set. * [r572] data/MedUnits.Rda: Update MedUnits data file. * [r571] data/MedUnits.tab: Don't need both .Rda and .tab forms of the data. * [r570] data, data/MedUnits.Rda, data/MedUnits.tab: Add MedUnits data set, which provides conversions between American 'Conventional' and Standard Intertional (SI) medical units. 2005-03-01 warnes * [r566] man/elem.Rd, man/ll.Rd: - Remove 'elem' call from ll example. - Add note to 'elem' man page that it is depreciated and 'll' should be used instead. 2005-02-26 nj7w * [r565] NAMESPACE, man/elem.Rd, man/env.Rd, man/ll.Rd, man/read.xls.Rd: *** empty log message *** 2005-02-25 warnes * [r564] NAMESPACE: Remove ll methods since the base function now handles lists and data frames. * [r563] R/elem.R, R/env.R, R/ll.R, man/Args.Rd, man/env.Rd, man/ll.Rd: Integrate changes submitted by Arni Magnusson 2005-01-31 warnes * [r529] R/read.xls.R, man/read.xls.Rd: Add ability to specify the perl executable and path. 2005-01-28 warnes * [r526] DESCRIPTION.in, NAMESPACE: Add dependency on stats. 2005-01-12 warnes * [r515] DESCRIPTION.in: Add dependency on R 1.9.0+ to prevent poeple from installing on old versions of R which don't support namespaces. 2004-12-27 warnes * [r509] man/unmatrix.Rd: Update usage to match code. * [r508] R/unmatrix.R: Replace 'F' with 'FALSE'. 2004-10-12 warneg * [r465] R/unmatrix.R, man/unmatrix.Rd: Add unmatrix() function 2004-09-27 warneg * [r461] DESCRIPTION, DESCRIPTION.in, NAMESPACE, man/.Rhistory: Updated to pass R CMD check. 2004-09-03 warneg * [r455] inst/xls, inst/xls/iris.xls: added to cvs. * [r454] inst/perl/xls2csv.pl: Checkin xls2csv.pl. Should have been in long ago, must have been an oversight * [r451] R/read.xls.R: Need to look for files using the new package name. * [r449] man/read.xls.Rd: Need to use the new package name when looking for iris.xls. * [r448] man/ll.Rd: Add ll.list to the to the list of functions described * [r447] NAMESPACE: Add ll and friends to the namespace * [r446] DESCRIPTION, DESCRIPTION.in, NAMESPACE, R/Args.R, R/aggregate.table.R, R/combine.R, R/elem.R, R/env.R, R/interleave.R, R/is.what.R, R/keep.R, R/ll.R, R/matchcols.R, R/nobs.R, R/read.xls.R, R/rename.vars.R, R/reorder.R, R/trim.R, man/reorder.Rd: initial bundle checkin 2004-09-02 warneg * [r442] DESCRIPTION, DESCRIPTION.in, NAMESPACE, man/.Rhistory: Initial revision 2004-08-27 warnes * [r441] R/reorder.R, man/reorder.Rd: Fixed bug in mixedsort, and modified reorder.factor to use mixedsort. 2004-07-29 warnes * [r427] inst/perl, inst/perl/IO, inst/perl/IO/AtomicFile.pm, inst/perl/IO/InnerFile.pm, inst/perl/IO/Lines.pm, inst/perl/IO/Scalar.pm, inst/perl/IO/Scalar.pm.html, inst/perl/IO/ScalarArray.pm, inst/perl/IO/Stringy.pm, inst/perl/IO/Wrap.pm, inst/perl/IO/WrapTie.pm, inst/perl/OLE, inst/perl/OLE/Storage_Lite.pm, inst/perl/Spreadsheet, inst/perl/Spreadsheet/ParseExcel, inst/perl/Spreadsheet/ParseExcel.pm, inst/perl/Spreadsheet/ParseExcel/Dump.pm, inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm, inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser.pm, inst/perl/Spreadsheet/ParseExcel/Utility.pm: Add perl modules to CVS. 2004-07-27 warnes * [r425] man/read.xls.Rd: Fix typos/spelling. * [r424] man/read.xls.Rd: Add note that Perl is required for read.xls to work properly. 2004-07-16 warnes * [r420] R/read.xls.R: Remove the temporary csv file if reading it in fails. 2004-06-22 warnes * [r377] R/ll.R, man/ll.Rd: Add S3 methods for data frames and lists. 2004-06-08 warnes * [r371] inst/bin, inst/bin/xls2csv, inst/bin/xls2csv.bat: Moved from gregmisc/src/. * [r370] inst/tools: Remove the files in src, instead provide "pre-installed" perl packages in inst/perl. 2004-06-05 warnes * [r365] inst/tools/Makefile: Fix typo. * [r364] inst/tools/Makefile: Fix Unix makefile so that it works when invoked directly. * [r363] inst/tools/Makefile: Fixes for Windows * [r362] man/read.xls.Rd: Minor enhancment to read.xls example. * [r361] inst/tools/Makefile, inst/xls: - Merge Makefile.win into Makefile. Makefile.win now just redirects to Makefile. - Update xls2csv.bat and xls2csv shell script to correctly obtain thier installion path and infer the location of the perl code and libraries. - The xls2csv.pl script now assumes that the libraries it needs are installed into the same directory where it is. 2004-06-04 warnes * [r360] inst/tools/Makefile: More changes, indended to improve installation reliabilty and to make Makefile and Makefile.win as similar as possible. 2004-05-27 warnes * [r358] inst/tools/Makefile: Clean should remove scripts from source directory. * [r357] inst/perl: Moved to xls2csv.pl.in. * [r354] inst/perl/xls2csv.pl, inst/tools/Makefile: More fixes. * [r353] man/elem.Rd: Fix missing brace. * [r352] man/elem.Rd: Add explicit package name to see also links. * [r351] inst/perl/xls2csv.pl, inst/tools/Makefile: More xls2csv perl module support changes. * [r350] inst/tools/Makefile: More changes to fix local installation of perl modules. 2004-05-26 warnes * [r345] man/read.xls.Rd: Escape underscores in email addresses so Latex is happy. 2004-05-25 warnes * [r339] inst/perl/xls2csv.pl, inst/tools/Makefile: More changes to xls2csv code. * [r337] R/Args.R, man/Args.Rd: Add Args() function contributed by Arni Magnusson . * [r335] R/read.xls.R: - Change to call perl directly rather than depending on the installed shell script. This should make the code more portable to MS-Windows systes. - Add additional commants.. * [r332] inst/tools/Makefile: Makefile now modifies xls2csv.bat xls2csv.pl and xls2csv to contain an explicit path to the perl script/libraries. * [r330] inst/tools/Makefile: R CMD build calls the clean target to purge build files from the source tree when packaging. To get use this behavior correctly, I've renamed the clean target to cleanup and distclean target to clean. * [r329] R/read.xls.R, man/read.xls.Rd: Add read.xls(), a function to read Microsoft Excel files by translating them to csv files via the xls2csv.pl script. * [r326] inst/tools/Makefile: More fixes. Seems to work now. 2004-05-24 warnes * [r325] inst/perl, inst/perl/xls2csv.pl, inst/tools, inst/tools/Makefile, inst/xls, inst/xls/iris.xls: Add files to enable inclusion and installation of xls2csv.pl as part of the package. 2004-04-01 warnes * [r312] R/rename.vars.R, man/rename.vars.Rd: Add function remove.vars(). 2004-03-26 warnes * [r307] man/reorder.Rd: Contents of package 'mva' moveed to 'stats'. * [r298] R/is.what.R: - Fix is.what() for use under R 1.9.0 - is.what() now uses is.* functions found in any attached frame 2004-01-21 warnes * [r282] R/reorder.R, man/reorder.Rd: - Add ... argument to match generic provided in mva. 2004-01-19 warnes * [r275] R/elem.R, R/env.R, R/ll.R, man/keep.Rd, man/ll.Rd: - Integrated (partial) patch submitted by Arni Magnusson to clarify help text. - Modifed code to use match.arg(). 2003-12-15 warnes * [r271] R/env.R: - Applied patch from Arni that fixed a bug that caused env() to crash if any environment was completely empty 2003-12-03 warnes * [r253] man/elem.Rd, man/ll.Rd: - match function argument defaults with 'usage' 2003-12-02 warnes * [r249] man/ll.Rd: Add one argument, to match code. 2003-12-01 warnes * [r244] R/elem.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R: - Apply changes submitted by Arni Magnusson 2003-11-19 warnes * [r229] man/env.Rd, man/is.what.Rd, man/keep.Rd, man/ll.Rd: Changes to pass R CMD check. 2003-11-18 warnes * [r224] R/elem.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R: - Convert from MS-Dos to Unix line endings. - Reformat to 80 columns. 2003-11-17 warnes * [r223] man/elem.Rd: Replace 'T' with 'TRUE' to remove R CMD check error. * [r222] man/aggregate.table.Rd: Fix syntax error. 2003-11-10 warnes * [r220] R/elem.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R, man/elem.Rd, man/env.Rd, man/is.what.Rd, man/keep.Rd, man/ll.Rd: - Add files contributed by Arni Magnusson . As well as some of my own. 2003-06-07 warnes * [r198] man/aggregate.table.Rd, man/interleave.Rd: - Fixed error in examples. Had sqrt(var(x)/(n-1)) for the standard error of the mean instead of sqrt(var(x)/n). 2003-05-23 warnes * [r197] R/matchcols.R, man/matchcols.Rd: - Fixed typos * [r196] R/matchcols.R, man/matchcols.Rd: - library() backported from 1.7-devel. This version of the function adds the "pos=" argument to specify where in the search path the library should be placed. - updated .First.lib to use library(...pos=3) for MASS to avoid the 'genotype' data set in MASS from masking the genotype funciton in genetics when it loads gregmisc - Added logit() inv.logit() matchcols() function and corresponding docs 2003-05-20 warnes * [r195] R/interleave.R: - Omit NULL variables. * [r194] R/trim.R, man/trim.Rd: - Added function trim() and assocated docs. 2003-04-22 warnes * [r188] R/reorder.R, man/reorder.Rd: - The mva package (which is part of recommended) now provides a generic 'reorder' function. Consequently, the 'reorder' function here has been renamed to 'reorder.factor'. - Removed check of whether the argument is a factor object. 2003-03-03 warnes * [r165] man/reorder.Rd: - Updated to match reorder.Rd which was exetended to handle factor label names in addition to numeric indices. * [r164] R/reorder.R: - Added handling of factor level names in addition to numeric indexes. 2002-09-23 warnes * [r118] inst, inst/doc, inst/doc/Rnews.dtx, inst/doc/Rnews.sty, inst/doc/gregmisc.pdf, inst/doc/gregmisc.tex: Added inst/doc directory and contents to CVS. * [r117] R/aggregate.table.R, R/combine.R, R/interleave.R, R/nobs.R, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/nobs.Rd, man/rename.vars.Rd, man/reorder.Rd: - Modified all files to include CVS Id and Log tags. 2002-08-01 warnes * [r112] R/reorder.R: Added reorder() function to reorder the levels of a factor. 2002-04-09 warneg * [r109] R/rename.vars.R, man/aggregate.table.Rd, man/interleave.Rd, man/reorder.Rd: Checkin for version 0.5.3 * [r108] R/interleave.R: - Properly handle case when some or all arguments are vectors. 2002-03-26 warneg * [r104] man/reorder.Rd: - Changed methods to include '...' to match the generic. - Updated for version 0.5.1 * [r102] R/nobs.R: Added ... to methods. * [r101] man/nobs.Rd: Updated to add ... parameter to function calls. * [r98] man/reorder.Rd: Initial checkin. * [r95] R/nobs.R: - Added CVS tags 2002-02-21 warneg * [r87] R/aggregate.table.R: - Fixed bug where row and column labels didn't always correspond to the contents. This only occured when a factor was used for by1 or by2 and the factors levels weren't in the default sort order. 2002-02-20 warneg * [r86] R/aggregate.table.R: New function. * [r85] man/aggregate.table.Rd: Initial checkin. * [r84] R/interleave.R, man/interleave.Rd: Initial checkin. * [r83] man/nobs.Rd: Noted that specialized methods exist. * [r82] man/nobs.Rd: Incorrectly had contents of nobs.R here instead of help text. Corrected. * [r81] man/rename.vars.Rd: Minor changes, typo and formatting fixes. * [r79] R/nobs.R, man/nobs.Rd: - initial checkin. 2001-12-12 warneg * [r53] man/rename.vars.Rd: Added omitted documentaton for 'info' parameter. Changed example code not to use 'Orthodont' data set so that the nlme package is not required. 2001-12-08 warneg * [r47] R/rename.vars.R: Changed 'T' to 'TRUE' in parameter list. 2001-12-07 warneg * [r45] man/rename.vars.Rd: - Fixed see also link. Mis-typed 'data.frame' as 'dataframe'. * [r44] R/rename.vars.R: Added attribution. * [r43] man/rename.vars.Rd: Added proper attribution to Don MacQueen. * [r39] man/rename.vars.Rd: Initial checkin. Unfortunately, I've lost the email of the person who sent this to me. I'll credit him/her when I find out who it was! * [r38] R/rename.vars.R: Initial checkin 2001-12-05 warneg * [r34] R, R/combine.R: - Renamed 'concat' function to 'combine' to avoid name conflict with an existing S-Plus function. * [r32] ., man, man/combine.Rd: - Changed function name 'concat' to 'combine' and renamed concat.Rd to combine.Rd gdata/data/0000755000176000001440000000000012163373035012276 5ustar ripleyusersgdata/data/MedUnits.rda0000644000176000001440000000714112163372574014530 0ustar ripleyusers‹íškU€7»³ïM²1/ò 4˜P³$Ëfž»[HMÏÎnv–Ì&“ìäQ…Þ™Þ™†žî¦»'ÉD|K±j ©¤ÄR …‰R˜BS¨DAA|¡çöãÜîÙéÝ¡ÄNÕnß{îã;÷œsϽ½;[‡w†;vv444464vÃï&(áל†@C;<ÛÆùÂ6I円¦…Po†èØpÈjo˜åÙ”Ì ùìún=©ìHÖg߯TrZiöùÓ›3ÓæÙv’Z6¥¶Žx†Ó#~•y·ŸÍé¡d(åwÍéÑ!,×ÚpÖÑc£IZ¦ÅZ¥Åñÿ’š2'½’ÿ?ß™gc.:kÈÿˆ®ÓŸîÄ;7™çu®,H²Râ%KØM„2¿„<Ãå…‚%o5äU‘“gu²3YÕΤX5W逶¤H:TÊV}A’€'+zUuƒæBƒ® Š^éüÝÉrY–Ž r³)é±äó“RA%$‰/67)¤š 1c–pžKhKÛ“ dŠœb %%](Õ°@IV˲C hÓKª\ž4æ°'y'*%.Ôk4«UE¨9YYQ c’ò!4“Z†íHj §rE*éòœ:)Kœn‹Ú‡QP+“Hm…¶§z^Ñ©`q*ÄðÄ?œÆ3‚T&]Vmã¥"L^.+"_æ%…ÑéÂŽ'æa¤DÁ†\S—2gÀU{©2m %nAç¥xµ"ÊŠÈi4¢ÚR%QVé ÎTI%È"ÂÀöÔ(-)YQx{QKSÄÔŠ¬*%8Ic‚xðv-JÉ*¸[Ö¡x#˜LåÒ=ˆ&mr ®;]Ô–RyNw¸ÌªSÉ"*aò"þ”ò¸sRUØH¸®Ó‡ùRBšWÎ m²‰˜ 9 m:‡yMPT²uQ‰aÛÇ+Z~X(‚‘qCŽÀ²x¥¤Òí#˜ \ö#‚š* ý¥#z‰“d‘ òz©*2àX\€q„HÁ‰LQ¬æ©­6ðª*訇¹Q˜Þ K¬Ð·­¶A˜íä"f¢¶ bÅéò– ²HÝ»j¢ÖìÕt¡\‰}‹5ÛµmƒZÉ벆KåDÎ)h+y®(cø’º³¿XÑVŽÂâ@‡SâËrQ”I+ÖªbmC2´~Rh"2˜Ä+œRy ½V"vlï4§èÖ ¶iÒ|™Óå<Ò’¬M;ð{ÈN`&EY.ô0㜦ÁF…ø’ÈfpiëÒB±Ô[ ÙO¯2ÎÔ“§;‰ ©5nO É…4ÓrYÎW52bR—u#à¬t¥Ì³AI:Á¬\wT:5j÷\˜&¾·Z'ùϳš@7Gö_2V.W$cÁ‘– Žq7Ô¶“Öa¯ÖÒ:âÕ:JZG½ZÇIë8:nLÒˆØvÜì–uŒa;F‰ˆ'Hlæ9VªWÝ}:DÈ,|Å !¹Šì6;_g l!¼˜ ‰_Ëd¶çØ3uÀ2Òº&óÒ¾j™‡\—õf†cöˆ@†çð\ϸàó2‚"´ßÎÏ8â%È¡2pÒô¾6#ï™=Â2ÎkÉT5GJ犤6œ±ž@*r Â<ΛyÉ6'©“øsLZuo§¶M$Ñ;‚zœÄjëI–ÜYiÞ&Yå§§ÎͪDVN]¶V'çÉa‡©dó^Α®f!ëCŠTe¡P“¥æfáö%OÂÑ(а0„R\·¬vC¨Ë43dK²¦ÀtÍÖ$k›Ž/L‘8‡ ]ɼ¬é÷ê$RëNf‰V=í×1¼Z%]È‚ì(ÈVÕÊnÇjKhg®Û ÙÜȪLžEHª¼ø4oåé§c‚ƒƒ¨êpvË3 &—$&ë-™ ŽÜÍ£·Â„\ Æí™IÎ/õVêM1AÁÌ5¢p)œ°ª¼G/1Sä(SÑàæb?Ô¬+¨¹‡wåJ<Ü÷«¢Ãð9Ø2y¸‡8Ì‘+©¼sÍÍ‘àµS¡m#C× ~CÎ4&˜‹Ú -v´îr6væà¤M‘Ë„U('$ùv8/¡ Ã)Bæ2îOL ¾¬˜Ö#gÁ°Ë¢¹ùû1A¸;.?½-7­­#GœÆâ0uäâHXs·ÁÅŽ‘¬üa›n[ֲ͡sûÌíœ&Û\½aƒ¿@_x¨º/é · F„㎼ŒHô¶µÔnŠ3AB¼`Ún^‰Í¡0¬ +ç!ÁˆDf÷Yf÷I‘wª¼ ÙÇ}¬œiwfBë±ÞaÁ Ýݶܾ²ÒŽÐ-]¿S»Ýi¤V°Ñ¶íNâh<,ÙQtÞk.¤|ƒû}6Pì+Ûi.û ³WΩ¦â1™³Å{¼â杖G.ëóhñ¥³ïŠ“ãÝÍ{¡åš¯õxC•À)êéßZì G™’ZOZø°nK9ÓGß4ÐT‚Ç×o˜Áñµ“y,Ô¿Ö6õ{µ”ǶùŠ/a¸x #OYÉœ¾çœ\XÎY3{@xX£¥,ú[Í)WœV x¡·ÓNa¹ok{qE¬—ŠMTîÙÇ;@¼F+~Ðþ2¶;Š[÷2¡õ‘úI¦µlf†zëoòZšW>w®l†¬äV,~’¨ÙÔ^Λ–Hêjà“"ù‰èiî÷sNúË·~+þÒºwêòN¾3ùß+ÐL à%~±Ë÷=7zç¢%î]²mc׉#Ó®Ó_Âîêz>?bW7ŸÄ—?¿’ÿü7·¼õHy×ßï`w²†œí"Ã÷=—øÕ¾=¸³{2qó Ꭱ‡MüΨnJüñ¦vCSâUkž—?Ý¿ñÈ¡WqÞ£ŸÝüËó &>eéa=ÙÌÝòa·þÁÐÃφ–ÝŸZãb ?ç«™¹OZÏg­§-¿®óÙÇ®|ÇÛò¯ØÝ3ß`/h™"ŸÄÆY>šxS:H4N<|ýû×ìêaÏ;Øq¾rëqvÉ=[~Ū{؉î[wœ»ÝÒóÀ²'Z/’±ý¤WÇùl'Œ ¾þ;ÏZO—5ï_>ò·ŸŸõäoØÅÇÍùæ~0–¸üålçáK å½ìÐÇL½;r蕯|«—]¿ÒP€c »õþꊶ+kØ 2¦ÿ™‡¿ôõçsh¿ÚO—PRï:õ¬y²­Vµ+f¼Üß·ü¦ö°Û¾kÄö³í»ö¨i‡kÙONm‘Ø]FXO±md¸ò5œÿúá'ÞvÎúćÝu÷k ìŽÇÍý·'õbþéK±Ÿ>o&ž·öï͇Ýqh?»Ä\'²ž¹º÷oÏý溭'úe?xñêׯ×\ÕÞx¢á>k׾܌û×û-ñSÓîì¸5ï¶‹Ýö²òÛM̳û‡‰ˆ·¶ØLÞX70×Ç6—`&¶ÀÜÇslûÖ쯇¾ðñ–ÕÏô5¸ßؚ˲è¸Þy×\s‹äÙË=·w?wS‹2C­ìÝæ>zë+ÛäÑe+Ìd É‹_оLMjcõp_Æ}jÝìœÎTºPß¼’OÕè”éÓêZËït'ÓzŽùò›â~ã5÷_–ðt°«Ûª¬ñPò¯¡ßæ|Y{²Ð¹ëëìÑcãdWéñ¾1{ü»½às}3E¹çÚ})ÿöRߌWò;É {a†ýÎáŒÃÍìkó8£Â¸‘Δ© uÕ ׿ɹÙ35¶ÕBa_'‡ßp[e.‚ æe®hü‡"Íü«?36ÖSŸä3mz¨3Ìæ¹§}:Õóo¦(«=b|ìúY ç5£kŽšˆ´†¹¿ÿÚ,qe^k0o>Í–°+99©ò»ç¿è;ÇyN«¨ÎoØt§di7T¡'’/ÑZòC®jtpËĘÑîf·«òžs|ûæ5'dÂvÁþÚÚûnsbv!núí€]´ ¡õX a)Œ¥–¢XŠa)Ž¥~, ` ad„‘FFad„‘FFad„‘AFdDAFdDAFQdD‘EFQdD‘EFQdD‘CF 1dÄCF 1dÄCF qdÄ‘GFqdÄ‘GFqdđь~dô#£ýÈèGF?2ú‘ÑŒ~d cÈ@Æ21€Œd cƒÈDÆ 2‘1ˆŒAd "cƒÈ´M¡õëi1D‹aZŒÐb”c´§Å~Z EJ QZˆÒB”¢´¥…(-Di!J QZˆÒ”¦´0¥…)-LiaJ SZ˜Ò”¦´¥E(-BiJ‹PZ„Ò"”¡´¥E(-JiQJ‹RZ”Ò¢”¥´(¥E)-JiQJ‹QZŒÒb”£´¥Å(-Fi1J‹QZŒÒâ”§´8¥Å)-NiqJ‹S䊚Ó5/rš}ºÙÂŽ§sçN©pðAí-òób`¨2gdata/R/0000755000176000001440000000000012164370064011566 5ustar ripleyusersgdata/R/xlsFormats.R0000644000176000001440000000152712163370447014064 0ustar ripleyusers## s$Id: read.xls.R 1423 2010-02-21 17:12:30Z ggrothendieck2 $ xlsFormats <- function(perl="perl", verbose=FALSE) { ## determine proper path to perl executable perl <- if (missing(perl)) findPerl(verbose = verbose) else findPerl(perl, verbose = verbose) ## ## directories package.dir <- find.package('gdata') perl.dir <- file.path(package.dir,'perl') ## ## cmd <- "supportedFormats.pl" sc <- file.path(perl.dir, cmd) ## ## ## ## execution command cmd <- paste(shQuote(perl), shQuote(sc), sep=" ") ## if(verbose) { cat("\n") cat("Determining supported formats...\n") cat("\n") } ## output <- system(cmd, intern=TRUE) ## if(verbose) cat("Results: ", output, "\n") ## retval <- unlist( strsplit(output," ")) retval <- retval[ -c(1,2) ] return(retval) } gdata/R/xls2sep.R0000644000176000001440000000703112163370503013307 0ustar ripleyusers## s$Id: xls2sep.R 1639 2013-01-14 20:47:57Z warnes $ xls2csv <- function(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., perl="perl") xls2sep(xls=xls, sheet=sheet, verbose=verbose, blank.lines.skip=blank.lines.skip, ..., method="csv", perl=perl) xls2tab <- function(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., perl="perl") xls2sep(xls=xls, sheet=sheet, verbose=verbose, blank.lines.skip=blank.lines.skip, ..., method="tab", perl=perl) xls2tsv <- function(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., perl="perl") xls2sep(xls=xls, sheet=sheet, verbose=verbose, blank.lines.skip=blank.lines.skip, ..., method="tsv", perl=perl) xls2sep <- function(xls, sheet=1, verbose=FALSE, blank.lines.skip=TRUE, ..., method=c("csv","tsv","tab"), perl = perl) { method <- match.arg(method) perl <- if (missing(perl)) findPerl(verbose = verbose) else findPerl(perl, verbose = verbose) ## ## directories package.dir <- find.package('gdata') perl.dir <- file.path(package.dir,'perl') ## ## ## filesheet tf <- NULL if ( substring(xls, 1, 7) == "http://" || substring(xls, 1, 6) == "ftp://" ) { tf <- paste(tempfile(), "xls", sep = ".") if(verbose) cat("Downloading", dQuote(xls), " to ", dQuote(tf), "...\n") download.file(xls, tf, mode = "wb") if(verbose) cat("Done.\n") xls <- tf } if(method=="csv") { script <- file.path(perl.dir,'xls2csv.pl') targetFile <- paste(tempfile(), "csv", sep = ".") } else if(method=="tab") { script <- file.path(perl.dir,'xls2tab.pl') targetFile <- paste(tempfile(), "tab", sep = ".") } else if(method=="tsv") { script <- file.path(perl.dir,'xls2tsv.pl') targetFile <- paste(tempfile(), "tsv", sep = ".") } else { stop("Unknown method", method) } ## ## ## ## blank.lines.skip ## if (blank.lines.skip) skipBlank="" else skipBlank="-s" ## ## execution command cmd <- paste(shQuote(perl), shQuote(script), skipBlank, # flag is not quoted shQuote(xls), shQuote(targetFile), shQuote(sheet), sep=" ") ## ## if(verbose) { cat("\n") cat("Converting xls file\n") cat(" ", dQuote(xls), "\n") cat("to", method, " file \n") cat(" ", dQuote(targetFile), "\n") cat("... \n\n") } ## ## do the translation if(verbose) cat("Executing '", cmd, "'... \n\n") results <- try(system(cmd, intern=!verbose)) if(inherits(results, "try-error")) stop( "Unable to read xls file '", xls, "':", results ) if(verbose) cat(results,"\n\n") if (verbose) cat("Done.\n\n") ## ## check that the target file was created ## if(!file.exists(targetFile)) stop( "Intermediate file '", targetFile, "' missing!" ) ## Creae a file object to hand to the next stage.. retval <- try(file(targetFile)) if(inherits(retval, "try-error")) stop("Unable to open intermediate file '", targetFile, "':", retval) return(retval) } gdata/R/write.fwf.R0000644000176000001440000001453611467310235013634 0ustar ripleyusers### write.fwf.R ###------------------------------------------------------------------------ ### What: Write fixed width format - code ### $Id: write.fwf.R 1459 2010-11-12 19:08:12Z warnes $ ### Time-stamp: <2008-08-05 12:11:27 ggorjan> ###------------------------------------------------------------------------ write.fwf <- function(x, file="", append=FALSE, quote=FALSE, sep=" ", na="", rownames=FALSE, colnames=TRUE, rowCol=NULL, justify="left", formatInfo=FALSE, quoteInfo=TRUE, width=NULL, eol="\n", qmethod=c("escape", "double"), ...) { ## --- Setup --- if(!(is.data.frame(x) || is.matrix(x))) stop("'x' must be a data.frame or matrix") if(length(na) > 1) stop("only single value can be defined for 'na'") if(rownames) { x <- cbind(rownames(x), x) rowColVal <- ifelse(!is.null(rowCol), rowCol, "row") colnames(x)[1] <- rowColVal } colnamesMy <- colnames(x) nRow <- nrow(x) nCol <- length(colnamesMy) widthNULL <- is.null(width) if(!widthNULL && length(width) != nCol) { warning("recycling 'width'") widthOld <- width width <- integer(length=nCol) width[] <- widthOld } ## --- Format info --- retFormat <- data.frame(colname=colnamesMy, nlevels=0, position=0, width=0, digits=0, exp=0, stringsAsFactors=FALSE) ## Which columns are numeric like isNum <- sapply(x, is.numeric) ## is.numeric picks also Date and POSIXt isNum <- isNum & !(sapply(x, inherits, what="Date") | sapply(x, inherits, what="POSIXt")) ## Which columns are factors --> convert them to character isFac <- sapply(x, is.factor) x[, isFac] <- lapply(x[, isFac, drop=FALSE], as.character) ## Collect information about how format() will format columns. ## We need to get this info now, since format will turn all columns to character tmp <- lapply(x, format.info, ...) tmp1 <- sapply(tmp, length) tmp <- t(as.data.frame(tmp)) retFormat$width <- tmp[, 1] ## Collect other details for numeric columns if(any(isNum)) { ## Numeric columns with digits test <- tmp1 > 1 if(any(test)) { retFormat[test, c("digits", "exp")] <- tmp[test, c(2, 3)] ## Numeric columns with scientific notation test2 <- tmp[test, 3] > 0 if(any(test2)) ## adding +1; see ?format.info retFormat[test, ][test2, "exp"] <- retFormat[test, ][test2, "exp"] + 1 } } ## --- Format --- ## Formatting (to character) for(i in 1:nCol) { if(widthNULL) { tmp <- NULL } else { tmp <- width[i] } ## Due to na.encode bug in format() in 2.7.1; na.encode=TRUE should ## return NA values and not "NA", but even then we rely on the ## following test to "fiddle" with the value in 'na' argument since - ## NA should not increase the width of column with width 1, while wider ## value for 'na' should increase the width test <- is.na(x[, i]) ## Make a copy to make sure we get character after first format() - Date class caused problems x2 <- character(length=nRow) ## Add formatted values x2[!test] <- format(x[!test, i], justify=justify, width=tmp, ...) ## Add 'na' value x2[test] <- na ## Replace the original x[, i] <- x2 ## Collect width (again) tmp2 <- format.info(x[, i], ...)[1] ## Reformat if 'na' value change the width of the column if(tmp2 != retFormat[i, "width"]) { retFormat[i, "width"] <- tmp2 ## ifelse() makes sure that numeric columns are justified to right x[, i] <- format(x[, i], justify=ifelse(isNum[i], "right", justify), width=tmp, ...) } ## Reformat 'na' value if it is narrower than the width of the column if(nchar(na) < retFormat[i, "width"]) { x[test, i] <- format(na, justify=ifelse(isNum[i], "right", justify), width=retFormat[i, "width"], ...) } } ## Number of levels for "non-numeric"" columns if(any(!isNum)) { retFormat[!isNum, "nlevels"] <- sapply(x[, !isNum, drop=FALSE], function(z) length(unique(z))) } ## Check that width was not to small if(!widthNULL) { test <- retFormat$width > width if(any(test)) { tmpCol <- paste(colnamesMy[test], collapse=", ") tmpWidth <- paste(width[test], collapse=", ") tmpNeed <- paste(retFormat$width[test], collapse=", ") stop(paste("'width' (", tmpWidth, ") was too small for columns: ", tmpCol, "\n 'width' should be at least (", tmpNeed, ")", sep="")) } } ## --- Write --- if(colnames) { if(rownames && is.null(rowCol)) colnamesMy <- colnamesMy[-1] write.table(t(as.matrix(colnamesMy)), file=file, append=append, quote=quote, sep=sep, eol=eol, na=na, row.names=FALSE, col.names=FALSE, qmethod=qmethod) } write.table(x=x, file=file, append=(colnames || append), quote=quote, sep=sep, eol=eol, na=na, row.names=FALSE, col.names=FALSE, qmethod=qmethod) ## --- Return format and fixed width information --- if(formatInfo) { ## be carefull with these ifelse constructs retFormat$position[1] <- ifelse(quote, ifelse(quoteInfo, 1, 2), 1) if(ifelse(quote, quoteInfo, FALSE)) retFormat$width <- retFormat$width + 2 N <- nrow(retFormat) if(N > 1) { for(i in 2:N) { retFormat$position[i] <- retFormat$position[i - 1] + retFormat$width[i - 1] + nchar(x=sep, type="chars") + ifelse(quote, ifelse(quoteInfo, 0, 1), 0) } } if(rownames && is.null(rowCol)) { retFormat <- retFormat[-1,] rownames(retFormat) <- 1:(N-1) } return(retFormat) } } ###------------------------------------------------------------------------ ### write.fwf.R ends here gdata/R/wideByFactor.R0000644000176000001440000000267711227511623014304 0ustar ripleyusers### wideByFactor.R ###------------------------------------------------------------------------ ### What: Reshape by factor levels - code ### $Id$ ### Time-stamp: <2008-12-30 22:17:32 ggorjan> ###------------------------------------------------------------------------ wideByFactor <- function(x, factor, common, sort=TRUE, keepFactor=TRUE) { ## --- Setup --- if(!is.data.frame(x)) stop("'x' must be a data frame") if(length(factor) != 1) stop("'factor' can be only of length one") if(!is.factor(x[[factor]])) stop("column defined in 'factor' must be a factor") if(sort) x <- x[order(x[[factor]]), ] ## --- Extend by factors levels --- y <- x[common] if(keepFactor) y[factor] <- x[factor] levs <- levels(x[[factor]]) ## Remove common and factor from the list of column names other <- names(x) other <- other[!(other %in% common) & !(other %in% factor)] ## Add all other columns but as a set for each level of a factor for(level in levs) { for(col in other) { ## add a column col y[paste(col, level, sep=".")] <- x[col] ## fill with NA for other levels than level y[x[factor] != level, paste(col, level, sep=".")] <- NA ## This filling migth be inefficient if there is large number ## of levels, since there will be quite a lot of filling. } } y } ###------------------------------------------------------------------------ ### wideByFactor.R ends heregdata/R/upperTriangle.R0000644000176000001440000000057010451013016014520 0ustar ripleyusersupperTriangle <- function(x, diag=FALSE) { x[upper.tri(x, diag=diag)] } "upperTriangle<-" <- function(x, diag=FALSE, value) { x[upper.tri(x, diag=diag)] <- value x } lowerTriangle <- function(x, diag=FALSE) { x[lower.tri(x, diag=diag)] } "lowerTriangle<-" <- function(x, diag=FALSE, value) { x[lower.tri(x, diag=diag)] <- value x } gdata/R/unmatrix.R0000644000176000001440000000100510451013016013540 0ustar ripleyusers# $Id: unmatrix.R 625 2005-06-09 14:20:30Z nj7w $ unmatrix <- function(x, byrow=FALSE) { rnames <- rownames(x) cnames <- colnames(x) if(is.null(rnames)) rnames <- paste("r",1:nrow(x),sep='') if(is.null(cnames)) cnames <- paste("c",1:ncol(x),sep='') nmat <- outer( rnames, cnames, paste, sep=":" ) if(byrow) { vlist <- c(t(x)) names(vlist) <- c(t(nmat)) } else { vlist <- c(x) names(vlist) <- c(nmat) } return(vlist) } gdata/R/unknown.R0000644000176000001440000001421410644743570013421 0ustar ripleyusers### unknown.R ###------------------------------------------------------------------------ ### What: Change given unknown value to NA and vice versa ### $Id: unknown.R 1094 2007-06-06 10:15:49Z ggorjan $ ### Time-stamp: <2007-04-26 13:16:10 ggorjan> ###------------------------------------------------------------------------ ### {{{ isUnknown ###------------------------------------------------------------------------ isUnknown <- function(x, unknown=NA, ...) UseMethod("isUnknown") isUnknown.default <- function(x, unknown=NA, ...) { if(is.list(unknown)) unknown <- unlist(unknown) ret <- x %in% unknown if(any(is.na(unknown))) ret <- ret | is.na(x) ret } isUnknown.POSIXlt <- function(x, unknown=NA, ...) { ## FIXME: codetools say ## isUnknown.POSIXlt: wrong number of arguments to as.character if(is.list(unknown) && !inherits(x=unknown, what="POSIXlt")) { unknown <- lapply(unknown, FUN=as.character, ...) } else { unknown <- as.character(x=unknown, ...) } isUnknown.default(x=as.character(x), unknown=unknown) } isUnknown.list <- function(x, unknown=NA, ...) { unknown <- gdata:::.unknownList(x=x, unknown=unknown) x <- mapply(FUN="isUnknown", x=x, unknown=unknown, ..., SIMPLIFY=FALSE) x } isUnknown.data.frame <- function(x, unknown=NA, ...) { x[] <- isUnknown.list(x, unknown=unknown, ...) x } isUnknown.matrix <- function(x, unknown=NA, ...) apply(X=x, MARGIN=ifelse(ncol(x) > nrow(x), 1, 2), FUN=isUnknown, unknown=unknown) ### }}} ### {{{ unknownToNA ###------------------------------------------------------------------------ unknownToNA <- function(x, unknown, warning=FALSE, ...) UseMethod("unknownToNA") unknownToNA.default <- function(x, unknown, warning=FALSE, ...) { if(warning) { if(any(is.na(x))) warning("'x' already has NA") } is.na(x) <- isUnknown(x=x, unknown=unknown) x } unknownToNA.factor <- function(x, unknown, warning=FALSE, ...) { ## could put this func into default method, but I need unlisted unknown ## for levels handling if(warning) { if(any(is.na(x))) warning("'x' already has NA") } if(is.list(unknown)) unknown <- unlist(unknown) ## Levels handling - read help page on this levs <- levels(x) levs <- levs[!(levs %in% unknown)] factor(x, levels=levs) } unknownToNA.list <- function(x, unknown, warning=FALSE, ...) { unknown <- gdata:::.unknownList(x=x, unknown=unknown) x <- mapply(FUN="unknownToNA", x=x, unknown=unknown, warning=warning, SIMPLIFY=FALSE) return(x) } unknownToNA.data.frame <- function(x, unknown, warning=FALSE, ...) { x[] <- unknownToNA.list(x=x, unknown=unknown, warning=warning) x } ### }}} ### {{{ NAToUnknown ###------------------------------------------------------------------------ NAToUnknown <- function(x, unknown, force=FALSE, call.=FALSE, ...) UseMethod("NAToUnknown") NAToUnknown.default <- function(x, unknown, force=FALSE, call.=FALSE, ...) { if(length(as.character(unknown)) != 1) # as.character allows also POSIXlt stop("'unknown' must be a single value") if(any(isUnknown(x, unknown=unknown)) && !force) stop(sprintf("'x' already has value %s", dQuote(unknown))) classX <- class(x)[1] classUnk <- class(unknown)[1] if(classX != classUnk) { tmp <- c("integer", "numeric") if(!(classX %in% tmp && classUnk %in% tmp)) { warning(sprintf("'unknown' should be %s for %s 'x' - will try to coerce", dQuote(classX), dQuote(classX)), call.=call.) } unknown <- do.call(paste("as.", classX, sep=""), args=list(unknown)) } x[is.na(x)] <- unknown x } NAToUnknown.factor <- function(x, unknown, force=FALSE, call.=FALSE, ...) { if(length(unknown) != 1) stop("'unknown' must be a single value") if(any(isUnknown(x, unknown=unknown))) { if(!force) stop(sprintf("'x' already has level %s", dQuote(unknown))) } else { mapLevels(x) <- c(mapLevels(x, codes=FALSE), mapLevels(as.character(unknown), codes=FALSE)) } x[is.na(x)] <- unknown if(!force) warning(sprintf("new level is introduced: %s", unknown), call.=call.) x } NAToUnknown.list <- function(x, unknown, force=FALSE, call.=FALSE, ...) { unknown <- gdata:::.unknownList(x=x, unknown=unknown) x <- mapply(FUN="NAToUnknown", x=x, unknown=unknown, force=force, call.=call., SIMPLIFY=FALSE) x } NAToUnknown.data.frame <- function(x, unknown, force=FALSE, call.=FALSE, ...) { x[] <- NAToUnknown.list(x=x, unknown=unknown, force=force, call.=call.) x } ### }}} ### {{{ .unknownList ###------------------------------------------------------------------------ .unknownList <- function(x, unknown) { ## --- Setup --- n <- length(x) unkN <- length(unknown) namesX <- names(x) namesXNullTest <- is.null(namesX) unkNames <- names(unknown) unkNamesNullTest <- is.null(unkNames) defInNames <- ".default" %in% unkNames defInd <- unkNames %in% ".default" def <- unknown[defInd] if(defInNames) { ## Remove default unkN <- unkN - 1 unkNames <- unkNames[!defInd] unknown <- unknown[!defInd] } if(!namesXNullTest) { ## Check for nonexistent name test <- !(unkNames %in% namesX) if(any(test)) stop(sprintf("name(s) %s not in names of 'x'", paste(sQuote(unkNames[test]), collapse=" "))) } ## --- Recycle --- if(unkN < n) { if(unkNamesNullTest | defInNames) { if(defInNames) { # handling .default names(def) <- NULL unknownDef <- rep(def, length=(n - unkN)) names(unknownDef) <- namesX[!(namesX %in% unkNames)] unknown <- c(unknownDef, unknown) } else { unknownDef <- unknown unknown <- rep(unknownDef, length=n) } } else { stop("can not propely recycle named 'unknown'") } } ## --- Names --- if(!namesXNullTest) { ## no need if namesX NULL if(unkNamesNullTest) { ## missing unkNames names(unknown) <- namesX } else { ## unkNames known unknown <- unknown[match(namesX, names(unknown))] } } unknown } ### }}} ### {{{ Dear Emacs ### Local variables: ### folded-file: t ### End: ### }}} ###------------------------------------------------------------------------ ### unknown.R ends here gdata/R/trimSum.R0000644000176000001440000000154611227511623013354 0ustar ripleyusers### trimSum.R ###------------------------------------------------------------------------ ### What: Sum trimmed values - code ### $Id$ ### Time-stamp: <2008-12-20 12:11:27 ggorjan> ###------------------------------------------------------------------------ trimSum <- function(x, n, right=TRUE, na.rm=FALSE, ...) { ## --- Setup --- if(!is.vector(x) | is.list(x)) stop("'x' must be a vector - for now") if(!is.numeric(x)) stop("'x' must be numeric") if(length(x) <= n) stop("'n' must be smaller than the length of x") ## --- Trim --- N <- length(x) if(right) { x2 <- x[1:n] x2[n] <- sum(x[n:N], na.rm=na.rm) } else { k <- (N - n + 1) x2 <- x[k:N] x2[1] <- sum(x[1:k], na.rm=na.rm) } ## --- Return --- x2 } ###------------------------------------------------------------------------ ### trimSum.R ends here gdata/R/trim.R0000644000176000001440000000143510521462300012655 0ustar ripleyusers# $Id: trim.R 989 2006-10-29 15:28:26Z ggorjan $ trim <- function(s, recode.factor=TRUE, ...) UseMethod("trim", s) trim.default <- function(s, recode.factor=TRUE, ...) s trim.character <- function(s, recode.factor=TRUE, ...) { s <- sub(pattern="^ +", replacement="", x=s) s <- sub(pattern=" +$", replacement="", x=s) s } trim.factor <- function(s, recode.factor=TRUE, ...) { levels(s) <- trim(levels(s)) if(recode.factor) { dots <- list(x=s, ...) if(is.null(dots$sort)) dots$sort <- sort s <- do.call(what=reorder.factor, args=dots) } s } trim.list <- function(s, recode.factor=TRUE, ...) lapply(s, trim, recode.factor=recode.factor, ...) trim.data.frame <- function(s, recode.factor=TRUE, ...) { s[] <- trim.list(s, recode.factor=recode.factor, ...) s } gdata/R/startsWith.R0000644000176000001440000000040311763533445014072 0ustar ripleyusersstartsWith <- function(str, pattern, trim=FALSE, ignore.case=FALSE) { if(trim) str <- trim(str) if(ignore.case) { str <- toupper(str) pattern <- toupper(pattern) } substr(str,start=1,stop=nchar(pattern))==pattern } gdata/R/sheetCount.R0000644000176000001440000000326512163370523014037 0ustar ripleyuserssheetCount <- function(xls, verbose = FALSE, perl = "perl") { perl <- if (missing(perl)) findPerl(verbose = verbose) else findPerl(perl, verbose = verbose) sheetCmd(xls, cmd="sheetCount.pl", verbose=verbose, perl=perl) } sheetNames <- function(xls, verbose = FALSE, perl = "perl") { perl <- if (missing(perl)) findPerl(verbose = verbose) else findPerl(perl, verbose = verbose) sheetCmd(xls, cmd="sheetNames.pl", verbose=verbose, perl=perl) } sheetCmd <- function(xls, cmd="sheetCount.pl", verbose=FALSE, perl="perl") { ## ## directories package.dir <- find.package('gdata') perl.dir <- file.path(package.dir,'perl') ## ## ## ## files tf <- NULL if ( substring(xls, 1, 7) == "http://" || substring(xls, 1, 6) == "ftp://" ) { tf <- paste(tempfile(), "xls", sep = ".") if(verbose) cat("Downloading", dQuote(xls), " to ", dQuote(tf), "...\n") else cat("Downloading...\n") download.file(xls, tf, mode = "wb") cat("Done.\n") xls <- tf } ## sc <- file.path(perl.dir, cmd) ## ## ## ## execution command cmd <- paste(shQuote(perl), shQuote(sc), shQuote(xls), sep=" ") ## ## ## ## do the translation if(verbose) { cat("\n") cat("Extracting sheet information from\n") cat(" ", dQuote(xls), "\n") cat("... \n\n") } ## output <- system(cmd, intern=TRUE, ignore.stderr=TRUE) if(verbose) cat("Results: ", output, "\n") ## tc <- textConnection(output) results <- read.table(tc, as.is=TRUE, header=FALSE) close(tc) results <- unlist(results) names(results) <- NULL ## if (verbose) cat("Done.\n\n") results } gdata/R/runRUnitTests.R0000644000176000001440000000161511227511623014522 0ustar ripleyusers### runRUnitTests.R ###------------------------------------------------------------------------ ### What: Run RUnit tests (wrapper function) - R code ### $Id$ ### Time-stamp: <2008-12-30 20:59:11 ggorjan> ###------------------------------------------------------------------------ .runRUnitTestsGdata <- function(testFileRegexp="^runit.+\\.[rR]$") { ## Setup .pkg <- environmentName(environment(.runRUnitTestsGdata)) .path <- system.file("unitTests", package=.pkg) .suite <- file.path(.path, "runRUnitTests.R") ## Some checks stopifnot(file.exists(.path), file.info(path.expand(.path))$isdir, file.exists(.suite)) ## Run the suite .way <- "function" source(.suite, local=TRUE) ## local=TRUE since .pkg and other vars do not exists in .suite environment } ###------------------------------------------------------------------------ ### runRUnitTests.R ends here gdata/R/resample.R0000644000176000001440000000170310451013016013506 0ustar ripleyusers## The S/R 'sample' function behaves differently if it is passed a ## sampling vector of length 1 than if it is passed a ## vector of length greater than 1. For the 1-element ## case it samples from the list 1:x, instead of from the contents ## of x. This function remove the special case: it always samples from ## the provided argument, no matter the length. resample <- function(x, size, replace = FALSE, prob = NULL) { if(length(x)<1) if(!missing(size) && size>0) stop("Requested sample of size ", size, " from list of length 0") else x[FALSE] else if(length(x)==1) { if(missing(size) || size==1) x else if(size>=1 && replace==TRUE) rep(x, size) else if(size < 1) x[FALSE] else stop("Cannot cannot take a sample larger than the population", " when 'replace = FALSE'") } else sample(x, size, replace, prob) } gdata/R/reorder.R0000644000176000001440000000133310521462300013341 0ustar ripleyusers# $Id: reorder.R 988 2006-10-29 12:55:08Z ggorjan $ # Reorder the levels of a factor. reorder.factor <- function(x, X, FUN, ..., order=is.ordered(x), new.order, sort=mixedsort) { constructor <- if (order) ordered else factor if (!missing(new.order)) { if (is.numeric(new.order)) new.order <- levels(x)[new.order] else new.order <- new.order } else if (!missing(FUN)) new.order <- names(sort(tapply(X, x, FUN, ...))) else new.order <- sort(levels(x)) constructor(x, levels=new.order) } gdata/R/rename.vars.R0000644000176000001440000000224510451013016014121 0ustar ripleyusers# $Id: rename.vars.R 625 2005-06-09 14:20:30Z nj7w $ rename.vars <- function(data,from='',to='',info=TRUE) { dsn <- deparse(substitute(data)) dfn <- names(data) if ( length(from) != length(to)) { cat('--------- from and to not same length ---------\n') stop() } if (length(dfn) < length(to)) { cat('--------- too many new names ---------\n') stop() } chng <- match(from,dfn) frm.in <- from %in% dfn if (!all(frm.in) ) { cat('---------- some of the from names not found in',dsn,'\n') stop() } if (length(to) != length(unique(to))) { cat('---------- New names not unique\n') stop() } dfn.new <- dfn dfn.new[chng] <- to if (info) cat('\nChanging in',dsn) tmp <- rbind(from,to) dimnames(tmp)[[1]] <- c('From:','To:') dimnames(tmp)[[2]] <- rep('',length(from)) if (info) { print(tmp,quote=FALSE) cat("\n") } names(data) <- dfn.new data } # GRW 2004-04-01 remove.vars <- function( data, names, info=TRUE) { for( i in names ) { if(info) cat("Removing variable '", i, "'\n", sep="") data[[i]] <- NULL } data } gdata/R/read.xls.R0000644000176000001440000000426112015177224013432 0ustar ripleyusers## s$Id: read.xls.R 1596 2012-08-22 15:45:22Z warnes $ read.xls <- function(xls, sheet = 1, verbose=FALSE, pattern, na.strings = c("NA","#DIV/0!"), ..., method=c("csv","tsv","tab"), perl="perl") { con <- tfn <- NULL on.exit({ err <- FALSE if (inherits(con, "connection")) { tryCatch(op <- isOpen(con), error = function(x) err <<- TRUE) if (!err && op) close(con) } if (file.exists(tfn)) file.remove(tfn) }) method <- match.arg(method) ## expand file path, translating ~ to user's home directory, etc. xls <- path.expand(xls) ## translate from xls to csv/tsv/tab format (returns name of created file) perl <- if (missing(perl)) findPerl(verbose = verbose) else findPerl(perl, verbose = verbose) con <- xls2sep(xls, sheet, verbose=verbose, ..., method=method, perl = perl) ## While xls2sep returns a connection, we are better off directly ## opening the file, so that R can properly handle the encoding. So, ## just grab the full file path to use later, and close the connection. tfn <- summary(con)$description close(con) if (missing(pattern)) { if(verbose) cat("Reading", method, "file ", dQuote(tfn), "...\n") if(method=="csv") retval <- read.csv(tfn, na.strings=na.strings, ...) else if (method %in% c("tsv","tab") ) retval <- read.delim(tfn, na.strings=na.strings, ...) else stop("Unknown method", method) if(verbose) cat("Done.\n") } else { if(verbose) cat("Searching for lines tfntaining pattern ", pattern, "... ") idx <- grep(pattern, readLines(tfn)) if (length(idx) == 0) { warning("pattern not found") return(NULL) } if(verbose) cat("Done.\n") if(verbose) cat("Reading", method, "file ", dQuote(tfn), "...\n") if(method=="csv") retval <- read.csv(tfn, skip = idx[1]-1, na.strings=na.strings, ...) else if (method %in% c("tsv","tab") ) retval <- read.delim(tfn, skip = idx[1]-1, na.strings=na.strings, ...) else stop("Unknown method", method) if(verbose) cat("Done.\n") } retval } gdata/R/onAttach.R0000644000176000001440000000413411377234365013464 0ustar ripleyusers.onAttach <- function(libname, pkgname) { show <- function(...) packageStartupMessage( paste( strwrap(x = list(...), prefix = "gdata: "), collapse="\n",sep="\n" ) ) try( { ## 1 - Can we access perl? hasPerl <- try( findPerl(), silent=TRUE) if(inherits(hasPerl, "try-error")) show( " Unable to locate valid perl interpreter \n \n read.xls() will be unable to read Excel XLS and XLSX files unless the 'perl=' argument is used to specify the location of a valid perl intrpreter. \n \n (To avoid display of this message in the future, please ensure perl is installed and available on the executable search path.) ") formats <- try(xlsFormats(),silent=TRUE) msg <- FALSE ## 2 - Are the libraries for XLS present? if( !("XLS" %in% formats) ) { show( "Unable to load perl libaries needed by read.xls()", " to support 'XLX' (Excel 97-2004) files." ) msg <- TRUE } else { show( "read.xls support for 'XLS' (Excel 97-2004) files ENABLED.") } show("\n") ## 3 - Are the libbaries for XLSX present? if( !("XLSX" %in% formats) ) { show( "Unable to load perl libaries needed by read.xls()", " to support 'XLSX' (Excel 2007+) files." ) msg <- TRUE } else { show( "read.xls support for 'XLSX' (Excel 2007+) files ENABLED." ) } if(msg) { show("\n") show( " Run the function 'installXLSXsupport()'", " to automatically download and install the perl", " libaries needed to support Excel XLS and XLSX formats." ) } }) } gdata/R/object.size.R0000644000176000001440000000464611763530311014137 0ustar ripleyusers### object.size.R ###------------------------------------------------------------------------ ### What: Print object size in human readable format - code ### $Id$ ### Time-stamp: <2008-12-30 08:05:43 ggorjan> ###------------------------------------------------------------------------ object.size <- function(...) { structure(sapply(list(...), utils::object.size), class=c("object_size", "numeric")) } print.object_size <- function(x, quote=FALSE, humanReadable, ...) { xOrig <- x if(missing(humanReadable)) { opt <- getOption("humanReadable") humanReadable <- ifelse(!is.null(opt), opt, FALSE) } if(humanReadable) { print(humanReadable(x), quote=quote, ...) } else { class(x) <- "numeric" NextMethod() } invisible(xOrig) } is.object_size <- function(x) inherits(x, what="object_size") as.object_size <- function(x) { if(!is.numeric(x)) stop("'x' must be numeric/integer") class(x) <- c("object_size", "numeric") x } c.object_size <- function(..., recursive=FALSE) { x <- NextMethod() if(is.numeric(x)) class(x) <- c("object_size", "numeric") x } humanReadable <- function(x, standard="SI", digits=1, width=3, sep=" ") { ## --- Setup --- if(any(x < 0)) stop("'x' must be positive") if(standard == "SI") { suffix <- c("B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") base <- 1000 } else { suffix <- c("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB") base <- 1024 } ## --- Apply --- .applyHuman <- function(x, base, suffix, digits, width, sep) { ## Which suffix should we use? n <- length(suffix) for(i in 1:n) { if(x >= base) { if(i < n) x <- x / base } else { break } } ## Formatting if(is.null(width)) { ## the same formatting for all x <- format(round(x=x, digits=digits), nsmall=digits) } else { ## similar to ls, du, and df lenX <- nchar(x) if(lenX > width) { digitsMy <- width - (lenX - (lenX - (nchar(round(x)) + 1))) digits <- ifelse(digitsMy > digits, digits, digitsMy) } if(i == 1) digits <- 0 x <- round(x, digits=digits) } paste(x, suffix[i], sep=sep) } sapply(X=x, FUN=".applyHuman", base=base, suffix=suffix, digits=digits, width=width, sep=sep) } ###------------------------------------------------------------------------ ### object.size.R ends here gdata/R/nobs.R0000644000176000001440000000114211765764211012657 0ustar ripleyusers# $Id: nobs.R 1564 2012-06-13 01:10:28Z warnes $ ## Redefine here, so that the locally defined methods (particularly ## nobs.default) take precidence over the ones now defined in the ## stats package nobs <- function(object, ...) UseMethod("nobs") nobs.default <- function(object, ...) { if(is.numeric(object) || is.logical(object)) sum( !is.na(object) ) else stats:::nobs.default(object, ...) } nobs.data.frame <- function(object, ...) sapply(object, nobs.default) ## Now provided by 'stats' package, so provide alias to satisfy ## dependencies nobs.lm <- stats:::nobs.lm gdata/R/nPairs.R0000644000176000001440000000307711552125074013153 0ustar ripleyusers### nPairs.R ###------------------------------------------------------------------------ ### What: Number of variable pairs - code ### $Id$ ### Time-stamp: <2008-12-30 18:29:58 ggorjan> ###------------------------------------------------------------------------ nPairs <- function(x, margin=FALSE, names=TRUE, abbrev=TRUE, ...) { ## --- Setup --- if(!is.data.frame(x) & !is.matrix(x)) stop("'x' must be a data.frame or a matrix") k <- ncol(x) if(!margin) { ret <- matrix(nrow=k, ncol=k) } else { ret <- matrix(nrow=k, ncol=k + 1) } ## --- Count --- diag(ret)[1:k] <- apply(X=x, MARGIN=2, FUN=function(x) sum(!is.na(x))) for(i in 1:k) { for(j in i:k) { ret[i, j] <- ret[j, i] <- sum(!is.na(x[, i]) & !is.na(x[, j])) if(margin) { if(i == 1) { ret[i, (k + 1)] <- ret[1, 1] } else { ret[i, (k + 1)] <- sum(rowSums(!is.na(x[, c(1:i)])) == i) } } } } ## --- Names --- if(names) { tmp <- colnames(x) if(abbrev) tmp <- as.character(abbreviate(tmp, ...)) rownames(ret) <- tmp if(margin) { colnames(ret) <- c(tmp, "all") } else { colnames(ret) <- tmp } } class(ret) <- c("nPairs", class(ret)) ret } summary.nPairs <- function(object, ...) { n <- nrow(object) ret <- matrix(data=0, nrow=n, ncol=n) for(i in 1:n) { tmp <- 1:n tmp <- tmp[!(tmp == i)] ret[i, tmp] <- object[i, i] - object[i, tmp] } dimnames(ret) <- dimnames(object) ret } ###------------------------------------------------------------------------ ### nPairs.R ends here gdata/R/matchcols.R0000644000176000001440000000157210451013016013657 0ustar ripleyusers# $Id: matchcols.R 625 2005-06-09 14:20:30Z nj7w $ # select the columns which match/don't match a set of include/omit patterns. matchcols <- function(object, with, without, method=c("and","or"), ...) { method <- match.arg(method) cols <- colnames(object) # include columns matching 'with' pattern(s) if(method=="and") for(i in 1:length(with)) { if(length(cols)>0) cols <- grep(with[i], cols, value=TRUE, ...) } else if(!missing(with)) if(length(cols)>0) cols <- sapply( with, grep, x=cols, value=TRUE, ...) # exclude columns matching 'without' pattern(s) if(!missing(without)) for(i in 1:length(without)) if(length(cols)>0) { omit <- grep(without[i], cols, ...) if(length(omit)>0) cols <- cols[-omit] } cols } gdata/R/mapLevels.R0000644000176000001440000002147110644743570013655 0ustar ripleyusers### mapLevels.R ###------------------------------------------------------------------------ ### What: Mapping levels ### $Id: mapLevels.R 1094 2007-06-06 10:15:49Z ggorjan $ ### Time-stamp: <2007-04-26 13:16:18 ggorjan> ###------------------------------------------------------------------------ ### {{{ mapLevels ###------------------------------------------------------------------------ mapLevels <- function(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, ...) { UseMethod("mapLevels") } mapLevels.default <- function(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, ...) { stop(sprintf("mapLevels can only be used on %s and %s atomic 'x'", dQuote("factor"), dQuote("character"))) } mapLevels.character <- function(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, ...) { mapLevels.factor(x=x, codes=codes, sort=sort, drop=drop, ...) } ## Could coerce character to factor and then use factor method, but that ## is more expensive than simple unique and length used bellow in factor ## method mapLevels.factor <- function(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, ...) { ## --- Argument actions ---- if(is.factor(x)) { # factor if(drop) x <- factor(x) nlevs <- nlevels(x) levs <- levels(x) } else { # character levs <- unique(x) nlevs <- length(levs) if(sort) levs <- sort(levs, ...) } ## --- Create a map --- map <- vector(mode="list", length=nlevs) names(map) <- levs if(codes) { map[1:nlevs] <- 1:nlevs } else { map[1:nlevs] <- levs } class(map) <- "levelsMap" map } mapLevels.list <- function(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, ...) { map <- lapply(x, mapLevels, codes=codes, sort=sort, drop=drop, ...) class(map) <- "listLevelsMap" if(combine) { if(!codes) { return(c(map, sort=sort, recursive=TRUE)) } else { stop(sprintf("can not combine integer %s", dQuote("levelsMaps"))) } } map } mapLevels.data.frame <- function(x, codes=TRUE, sort=TRUE, drop=FALSE, combine=FALSE, ...) { mapLevels.list(x, codes=codes, sort=sort, drop=drop, combine=combine, ...) } ### }}} ### {{{ print.* ###------------------------------------------------------------------------ .unlistLevelsMap <- function(x, ind=FALSE) { y <- unlist(x, use.names=FALSE) len <- sapply(x, FUN=length) names(y) <- rep(names(x), times=len) if(ind) { return(list(y, rep(1:length(x), times=len), len)) } else { return(y) } } print.levelsMap <- function(x, ...) { x <- gdata:::.unlistLevelsMap(x) print(x, ...) } print.listLevelsMap <- function(x, ...) { class(x) <- "list" print(x, ...) } ### }}} ### {{{ [.* ###------------------------------------------------------------------------ ## We need these two since [.list method drops class "[.levelsMap" <- function(x, i) { classX <- class(x) class(x) <- "list" x <- x[i] class(x) <- classX x } "[.listLevelsMap" <- function(x, i) { classX <- class(x) class(x) <- "list" x <- x[i] class(x) <- classX x } ### }}} ### {{{ is.* ###------------------------------------------------------------------------ is.levelsMap <- function(x) inherits(x=x, what="levelsMap") is.listLevelsMap <- function(x) inherits(x=x, what="listLevelsMap") .isCharacterMap <- function(x) { if(is(x) == "levelsMap") { return(inherits(x=unlist(x), what="character")) } else { stop(sprintf("can be used only on %s", dQuote("levelsMap"))) } } ### }}} ### {{{ as.* ###------------------------------------------------------------------------ as.levelsMap <- function(x, check=TRUE, ...) { if(check) gdata:::.checkLevelsMap(x, method="raw") class(x) <- "levelsMap" unique(x, ...) } as.listLevelsMap <- function(x, check=TRUE) { if(check) gdata:::.checkListLevelsMap(x, method="raw") class(x) <- "listLevelsMap" x } ### }}} ### {{{ .check* ###------------------------------------------------------------------------ .checkLevelsMap <- function(x, method) { xLab <- deparse(substitute(x)) also <- "\b" if(method == "class") { also <- "also" if(!is.levelsMap(x)) stop(sprintf("'%s' must be a %s", xLab, dQuote("levelsMap"))) } if(!is.list(x) || is.null(names(x))) stop(sprintf("'%s' must be %s a named list", xLab, also)) ## Components can be of different length ## if(!all(sapply(x, FUN=length) == 1)) ## stop(sprintf("all components of '%s' must have length 1", xLab)) } .checkListLevelsMap <- function(x, method) { xLab <- deparse(substitute(x)) also <- "\b" if(method == "class") { also <- "also" if(!is.listLevelsMap(x)) stop(sprintf("'%s' must be a %s", xLab, dQuote("listLevelsMap"))) } if(!is.list(x) || any(!sapply(x, FUN=is.levelsMap))) stop(sprintf("'%s' must be %s a list of %s", xLab, also, dQuote("levelsMap"))) lapply(x, FUN=gdata:::.checkLevelsMap, method=method) } ### }}} ### {{{ c.* ###------------------------------------------------------------------------ c.levelsMap <- function(..., sort=TRUE, recursive=FALSE) { x <- list(...) class(x) <- "listLevelsMap" ## we use recursive=TRUE here because ... is a lists of lists c(x, sort=sort, recursive=TRUE) } c.listLevelsMap <- function(..., sort=TRUE, recursive=FALSE) { x <- list(...) lapply(x, FUN=gdata:::.checkListLevelsMap, method="class") x <- unlist(x, recursive=FALSE) if(!recursive) { class(x) <- "listLevelsMap" } else { if(any(!sapply(x, FUN=gdata:::.isCharacterMap))) stop(sprintf("can not combine integer %s", dQuote("levelsMaps"))) if(!is.null(names(x))) names(x) <- NULL x <- unlist(x, recursive=FALSE) ## how to merge components with the same name? class(x) <- "levelsMap" if(sort) x <- sort(x) x <- unique(x) } x } ### }}} ### {{{ sort ###------------------------------------------------------------------------ sort.levelsMap <- function(x, decreasing=FALSE, na.last=TRUE, ...) x[order(names(x), na.last=na.last, decreasing=decreasing)] ### }}} ### {{{ unique ###------------------------------------------------------------------------ unique.levelsMap <- function(x, incomparables=FALSE, ...) { ## Find duplicates y <- gdata:::.unlistLevelsMap(x, ind=TRUE) ## Duplicates for values and names combinations test <- duplicated(cbind(y[[1]], names(y[[1]])), incomparables=incomparables, ...) if(any(test)) { if(any(y[[3]] > 1)) { # work with the same structure as in x j <- 1 k <- y[[3]][1] empty <- NULL for(i in seq(along=x)) { # how slow is this loop? tmp <- !test[j:k] if(all(!tmp)) { # these components will be empty empty <- c(empty, i) } else { x[[i]] <- x[[i]][tmp] } j <- j + y[[3]][i] k <- k + y[[3]][i + 1] } if(!is.null(empty)) x[empty] <- NULL } else { # simple one-length components x <- x[!test] } } x } ### }}} ### {{{ mapLevels<- ###------------------------------------------------------------------------ "mapLevels<-" <- function(x, value) UseMethod("mapLevels<-") "mapLevels<-.default" <- function(x, value) { ## --- Checks --- classX <- c("integer", "character", "factor") if(any(!(class(x) %in% classX))) stop(sprintf("'x' must be either: %s", paste(dQuote(classX), collapse=", "))) gdata:::.checkLevelsMap(x=value, method="class") ## --- Mapping levels in x --- char <- all(lapply(value, is.character)) int <- all(lapply(value, is.integer)) if(int) { # codes=TRUE if(is.integer(x)) x <- factor(x) if(is.factor(x)) levels(x) <- value if(is.character(x)) stop(sprintf("can not apply integer %s to %s", dQuote("levelsMap"), dQuote("character"))) } else { # codes=FALSE if(!char) stop("all components of 'value' must be of the same class") if(is.character(x)) x <- factor(x) if(is.factor(x)) levels(x) <- value if(is.integer(x)) stop(sprintf("can not apply character %s to %s", dQuote("levelsMap"), dQuote("integer"))) } x } "mapLevels<-.list" <- function(x, value) { if(!is.listLevelsMap(value)) { if(is.levelsMap(value)) { value <- as.listLevelsMap(list(value), check=FALSE) ## no need for check as default method does checking anyway } else { stop(sprintf("'x' must be either %s or %s", dQuote("listLevelsMap"), dQuote("levelsMap"))) } } x <- mapply(FUN="mapLevels<-", x=x, value=value, SIMPLIFY=FALSE) x } "mapLevels<-.data.frame" <- function(x, value) { x[] <- "mapLevels<-.list"(x, value) x } ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### mapLevels.R ends here gdata/R/ls.funs.R0000644000176000001440000000052311763454144013307 0ustar ripleyusersls.funs <- function (...) { mycall <- match.call() mycall[[1]] <- as.name("ls") nameList <- eval.parent(mycall) if(length(nameList)>0) { funcFlags <- sapply( nameList, function(x) is.function(get(x)) ) return(nameList[funcFlags]) } else return( list() ) } gdata/R/ll.R0000644000176000001440000000444212163434435012326 0ustar ripleyusersll <- function(pos=1, unit="KB", digits=0, dim=FALSE, sort=FALSE, class=NULL, invert=FALSE, ...) { get.object.class <- function(object.name, pos) { object <- get(object.name, pos=pos) class <- class(object)[1] return(class) } get.object.dim <- function(object.name, pos) { object <- get(object.name, pos=pos) if(class(object)[1] == "function") dim <- "" else if(!is.null(dim(object))) dim <- paste(dim(object), collapse=" x ") else dim <- length(object) return(dim) } get.object.size <- function(object.name, pos) { object <- get(object.name, pos=pos) size <- try(unclass(object.size(object)), silent=TRUE) if(class(size) == "try-error") size <- 0 return(size) } unit <- match.arg(unit, c("bytes","KB","MB")) denominator <- switch(unit, "KB"=1024, "MB"=1024^2, 1) if(is.character(pos)) # pos is an environment name pos <- match(pos, search()) if(is.list(pos)) # pos is a list-like object pos <- as.environment(pos) if(length(ls(pos,...)) == 0) # pos is an empty environment { object.frame <- data.frame() } else if(environmentName(as.environment(pos)) == "Autoloads") { object.frame <- data.frame(rep("function",length(ls(pos,...))), rep(0,length(ls(pos,...))), row.names=ls(pos,...)) if(dim) { object.frame <- cbind(object.frame, rep("",nrow(object.frame))) names(object.frame) <- c("Class", unit, "Dim") } else names(object.frame) <- c("Class", unit) } else { class.vector <- sapply(ls(pos,...), get.object.class, pos=pos) size.vector <- sapply(ls(pos,...), get.object.size, pos=pos) size.vector <- round(size.vector/denominator, digits) object.frame <- data.frame(class.vector=class.vector, size.vector=size.vector, row.names=names(size.vector)) names(object.frame) <- c("Class", unit) if(dim) object.frame <- cbind(object.frame, Dim=sapply(ls(pos,...),get.object.dim,pos=pos)) } if(!is.null(class)) { include <- object.frame$Class %in% class if(invert) include <- !include object.frame <- object.frame[include,] } return(object.frame) } gdata/R/keep.R0000644000176000001440000000132311326374545012643 0ustar ripleyuserskeep <- function(..., list=character(0), all=FALSE, sure=FALSE) { if(missing(...) && missing(list)) { warning("Keep something, or use rm(list=ls()) to clear workspace. ", "Nothing was removed.") return(invisible(NULL)) } names <- as.character(substitute(list(...)))[-1] list <- c(list, names) keep.elements <- match(list, ls(1,all.names=all)) if(any(is.na(keep.elements))) { warning("You tried to keep \"", list[which(is.na(keep.elements))[1]], "\" which doesn't exist in workspace. Nothing was removed.", sep="") return(invisible(NULL)) } if(sure) rm(list=ls(1,all.names=all)[-keep.elements], pos=1) else return(ls(1,all.names=all)[-keep.elements]) } gdata/R/is.what.R0000644000176000001440000000135011326374545013274 0ustar ripleyusersis.what <- function(object, verbose=FALSE) { do.test <- function(test, object) { result <- try(get(test)(object), silent=TRUE) if(!is.logical(result) || is.na(result) || length(result)!=1) result <- NULL return(result) } ## Get all names starting with "is." is.names <- unlist(sapply(search(), function(name) ls(name,pattern="^is\\."))) ## Narrow to functions is.functions <- is.names[sapply(is.names, function(x) is.function(get(x)))] tests <- sort(unique(is.functions[is.functions!="is.what"])) results <- suppressWarnings(unlist(sapply(tests, do.test, object=object))) if(verbose) output <- data.frame(is=ifelse(results,"T",".")) else output <- names(results)[results] return(output) } gdata/R/interleave.R0000644000176000001440000000214610451013016014036 0ustar ripleyusers# $Id: interleave.R 789 2005-12-08 20:18:15Z warnes $ interleave <- function(..., append.source=TRUE, sep=": ", drop=FALSE) { sources <- list(...) sources[sapply(sources, is.null)] <- NULL sources <- lapply(sources, function(x) if(is.matrix(x) || is.data.frame(x)) x else t(x) ) nrows <- sapply( sources, nrow ) mrows <- max(nrows) if(any(nrows!=mrows & nrows!=1 )) stop("Arguments have differening numbers of rows.") sources <- lapply(sources, function(x) if(nrow(x)==1) x[rep(1,mrows),,drop=drop] else x ) tmp <- do.call("rbind",sources) nsources <- length(sources) indexes <- outer( ( 0:(nsources-1) ) * mrows , 1:mrows, "+" ) retval <- tmp[indexes,,drop=drop] if(append.source && !is.null(names(sources) )) if(!is.null(row.names(tmp)) ) row.names(retval) <- paste(format(row.names(retval)), format(names(sources)), sep=sep) else row.names(retval) <- rep(names(sources), mrows) retval } gdata/R/installXLSXsupport.R0000644000176000001440000000212012163370426015527 0ustar ripleyusers## s$Id: read.xls.R 1423 2010-02-21 17:12:30Z ggrothendieck2 $ installXLSXsupport <- function(perl="perl", verbose=FALSE) { ## determine proper path to perl executable perl <- if (missing(perl)) findPerl(verbose = verbose) else findPerl(perl, verbose = verbose) ## ## directories package.dir <- find.package('gdata') perl.dir <- file.path(package.dir,'perl') ## ## cmd <- "install_modules.pl" sc <- file.path(perl.dir, cmd) ## ## ## ## execution command cmd <- paste(shQuote(perl), shQuote(sc), sep=" ") ## if(verbose) { cat("\n") cat("Attempting to automaticall install Perl libraries to support XLSX (Excel 2007+) file format...\n") cat("\n") } ## output <- system(cmd, intern=TRUE) ## if(verbose) cat("Results: ", output, "\n") ## if( "XLSX" %in% xlsFormats(perl=perl, verbose=verbose) ) { cat("\nPerl XLSX support libraries successfully installed.\n\n") invisible(TRUE) } else { stop("\nUnable to install Perl XLSX support libraries.\n\n") invisible(FALSE) } } gdata/R/getDateTimeParts.R0000644000176000001440000000464711227511623015127 0ustar ripleyusers### getDateTimePart.R ###------------------------------------------------------------------------ ### What: Extract date and time parts from various date and time classes ### $Id$ ### Time-stamp: <2008-12-30 22:42:58 ggorjan> ###------------------------------------------------------------------------ ### {{{ getYear ###------------------------------------------------------------------------ getYear <- function(x, format, ...) UseMethod("getYear") getYear.default <- function(x, format, ...) stop("'getYear' can only be used on objects of a date/time class") getYear.Date <- getYear.POSIXct <- getYear.POSIXlt <- function(x, format="%Y", ...) format(x=x, format=format, ...) ### }}} ### {{{ getMonth ###------------------------------------------------------------------------ getMonth <- function(x, format, ...) UseMethod("getMonth") getMonth.default <- function(x, format, ...) stop("'getMonth' can only be used on objects of a date/time class") getMonth.Date <- getMonth.POSIXct <- getMonth.POSIXlt <- function(x, format="%m", ...) format(x=x, format=format) ### }}} ### {{{ getDay ###------------------------------------------------------------------------ getDay <- function(x, format, ...) UseMethod("getDay") getDay.default <- function(x, format, ...) stop("'getDay' can only be used on objects of a date/time class") getDay.Date <- getDay.POSIXct <- getDay.POSIXlt <- function(x, format="%d", ...) format(x=x, format=format) ### }}} ### {{{ getHour ###------------------------------------------------------------------------ getHour <- function(x, format, ...) UseMethod("getHour") getHour.default <- function(x, format, ...) stop("'getHour' can only be used on objects of a date/time class") ### }}} ### {{{ getMin ###------------------------------------------------------------------------ getMin <- function(x, format, ...) UseMethod("getMin") getMin.default <- function(x, format, ...) stop("'getMin' can only be used on objects of a date/time class") ### }}} ### {{{ getSec ###------------------------------------------------------------------------ getSec <- function(x, format, ...) UseMethod("getSec") getSec.default <- function(x, format, ...) stop("'getSec' can only be used on objects of a date/time class") ### }}} ### {{{ Dear Emacs ## Local variables: ## folded-file: t ## End: ### }}} ###------------------------------------------------------------------------ ### getDateTimePart.R ends heregdata/R/frameApply.R0000644000176000001440000000322710451013016014001 0ustar ripleyusers# $Id: frameApply.R 625 2005-06-09 14:20:30Z nj7w $ # frameApply <- function(x, by = NULL, on = by[1], fun = function(xi) c(Count = nrow(xi)) , subset = TRUE, simplify = TRUE, byvar.sep = "\\$\\@\\$", ...) { subset <- eval(substitute(subset), x, parent.frame()) x <- x[subset, , drop = FALSE] if(!is.null(by)) { x[by] <- drop.levels(x[by]) for(i in seq(along = by)) if(length(grep(byvar.sep, as.character(x[[by[i]]])))) stop("Choose a different value for byvar.sep.") byvars <- unique(x[by]) BYVAR <- do.call("paste", c(as.list(x[by]), sep = byvar.sep)) byvars <- byvars[order(unique(BYVAR)), , drop = FALSE] splx <- split(x[on], BYVAR) splres <- lapply(splx, fun, ...) if(!simplify) out <- list(by = byvars, result = splres) else { i <- 1 ; nres <- length(splres) while(inherits(splres[[i]], "try-error") & i < nres) i <- i + 1 nms <- names(splres[[i]]) # nms <- lapply(splres, function(xi) { # if(inherits(xi, "try-error")) return(NULL) # else names(xi) # }) # nms <- do.call("rbind", nms)[1, ] splres <- lapply(splres, function(xi) { if(inherits(xi, "try-error")) { return(rep(NA, length(nms))) } else xi }) res <- do.call("rbind", splres) res <- as.data.frame(res) names(res) <- nms if(length(intersect(names(byvars), names(res)))) stop("Names of \"by\" variables are also used as names of result elements. Not allowed.\n") out <- data.frame(byvars, res) } } else { out <- fun(x[on]) if(simplify) out <- as.data.frame(as.list(out)) } out } gdata/R/findPerl.R0000644000176000001440000000140311367161300013445 0ustar ripleyusers## s$Id: read.xls.R 1342 2009-07-16 02:49:11Z warnes $ ## findPerl attempts to locate a valid perl executable. If the 'perl' argument is missing, findPerl <- function(perl, verbose = "FALSE") { errorMsg <- "perl executable not found. Use perl= argument to specify the correct path." if (missing(perl)) { perl = "perl" } perl = Sys.which(perl) if (perl=="" || perl=="perl") stop(errorMsg) if (.Platform$OS == "windows") { if (length(grep("rtools", tolower(perl))) > 0) { perl.ftype <- shell("ftype perl", intern = TRUE) if (length(grep("^perl=", perl.ftype)) > 0) { perl <- sub('^perl="([^"]*)".*', "\\1", perl.ftype) } } } if (verbose) cat("Using perl at", perl, "\n") perl } gdata/R/env.R0000644000176000001440000000212211763416242012501 0ustar ripleyusersenv <- function(unit="KB", digits=0) { get.object.size <- function(object.name, pos) { object <- get(object.name, pos=pos) size <- try(unclass(object.size(object)), silent=TRUE) if(class(size) == "try-error") size <- 0 return(size) } get.environment.size <- function(pos) { if(search()[pos]=="Autoloads" || length(ls(pos,all.names=TRUE))==0) size <- 0 else size <- sum(sapply(ls(pos,all.names=TRUE), get.object.size, pos=pos)) return(size) } get.environment.nobjects <- function(pos) { nobjects <- length(ls(pos,all.names=TRUE)) return(nobjects) } unit <- match.arg(unit, c("bytes","KB","MB")) denominator <- switch(unit, "KB"=1024, "MB"=1024^2, 1) size.vector <- sapply(seq(along=search()), get.environment.size) size.vector <- round(size.vector/denominator, digits) nobjects.vector <- sapply(seq(along=search()), get.environment.nobjects) env.frame <- data.frame(search(), nobjects.vector, size.vector) names(env.frame) <- c("Environment", "Objects", unit) print(env.frame, right=FALSE) invisible(env.frame) } gdata/R/elem.R0000644000176000001440000000037610451013016012625 0ustar ripleyusers# $Id: elem.R 625 2005-06-09 14:20:30Z nj7w $ elem <- function(object=1, unit=c("KB","MB","bytes"), digits=0, dimensions=FALSE) { .Deprecated("ll", package="gdata") ll(pos=object, unit=unit, digits=digits, dimensions=dimensions) } gdata/R/duplicated2.R0000644000176000001440000000035712143472611014114 0ustar ripleyusersduplicated2 <- function(x, bothWays=TRUE, ...) { if(!bothWays) { return(duplicated(x, ...)) } else if(bothWays) { return((duplicated(x, ...) | duplicated(x, fromLast=TRUE, ...))) } } gdata/R/drop.levels.R0000644000176000001440000000073110644743570014156 0ustar ripleyusers drop.levels <- function(x, reorder=TRUE, ...) UseMethod("drop.levels") drop.levels.default <- function(x, reorder=TRUE, ...) x drop.levels.factor <- function(x, reorder=TRUE, ...) { x <- x[, drop=TRUE] if(reorder) x <- reorder(x, ...) x } drop.levels.list <- function(x, reorder=TRUE, ...) { lapply(x, drop.levels, reorder=reorder, ...) } drop.levels.data.frame <- function(x, reorder=TRUE, ...) { x[] <- drop.levels.list(x, reorder=reorder, ...) x } gdata/R/combine.R0000644000176000001440000000125110451013016013310 0ustar ripleyusers# $Id: combine.R 625 2005-06-09 14:20:30Z nj7w $ combine <- function(..., names=NULL) { tmp <- list(...) if(is.null(names)) names <- names(tmp) if(is.null(names)) names <- sapply( as.list(match.call()), deparse)[-1] if( any( sapply(tmp, is.matrix) | sapply(tmp, is.data.frame) ) ) { len <- sapply(tmp, function(x) c(dim(x),1)[1] ) len[is.null(len)] <- 1 data <- rbind( ... ) } else { len <- sapply(tmp,length) data <- unlist(tmp) } namelist <- factor(rep(names, len), levels=names) return( data.frame( data, source=namelist) ) } gdata/R/centerText.R0000644000176000001440000000104011743412031014022 0ustar ripleyusers## Function to center text strings for display on the text console ## by prepending the necessary number of spaces to each element. centerText <- function(x, width=getOption("width")) { retval <- vector(length=length(x), mode="character") for( i in 1:length(x) ) { text <- trim(x[i]) textWidth <- nchar(text) nspaces <- floor((width - textWidth)/2) spaces <- paste( rep(" ",nspaces), sep="", collapse="") retval[i] <- paste( spaces, text, sep="", collapse="\n" ) } retval } gdata/R/cbindX.R0000644000176000001440000000242111227511623013114 0ustar ripleyusers### cbindX.R ###------------------------------------------------------------------------ ### What: Column-bind objects with different number of rows - code ### $Id: cbindX.R 1300 2008-08-05 11:47:18Z ggorjan $ ### Time-stamp: <2008-08-05 13:39:14 ggorjan> ###------------------------------------------------------------------------ cbindX <- function(...) { ## --- Setup --- x <- list(...) ## Are all objects matrices or data.frames? test <- sapply(x, function(z) is.matrix(z) | is.data.frame(z)) if(any(!test)) stop("only matrices and data.frames can be used") ## Get maximum number of rows tmp <- sapply(x, nrow) maxi <- which.max(tmp) test <- tmp < tmp[maxi] ## --- Core --- ## Adding additional "empty" rows so that all objects have the same number of rows for(i in 1:length(tmp)) { if(test[i]) { add <- matrix(nrow=tmp[maxi] - tmp[i], ncol=ncol(x[[i]])) if(is.data.frame(x[[i]])) { add <- as.data.frame(add) } colnames(add) <- colnames(x[[i]]) x[[i]] <- rbind(x[[i]], add) } } ## Column-bind all objects ret <- x[[1]] for(i in 2:length(tmp)) { ret <- cbind(ret, x[[i]]) } ## --- Return --- ret } ###------------------------------------------------------------------------ ### cbindX.R ends here gdata/R/case.R0000644000176000001440000000063711743412031012623 0ustar ripleyuserscase <- function(x, ..., default=NA) { magic <- "....default...." alternatives <- c(...,"....default...."=magic) x <- as.character(x) retval <- factor( x, levels=alternatives, labels=names(alternatives) ) levels(retval)[length(alternatives)] <- as.character(default) retval[is.na(retval) & !is.na(x)] <- default retval } gdata/R/bindData.R0000644000176000001440000000241011227511623013411 0ustar ripleyusers### bindData.R ###------------------------------------------------------------------------ ### What: Bind two data frames - code ### $Id$ ### Time-stamp: <2008-12-30 22:01:00 ggorjan> ###------------------------------------------------------------------------ bindData <- function(x, y, common) { ## --- Setup --- if(!is.data.frame(x)) stop("'x' must be a data frame") if(!is.data.frame(y)) stop("'y' must be a data frame") ## --- New data frame --- ## First add common column and a dataset indicator column z <- rbind(x[common], y[common]) ## Other columns ## - remove common columns in x and y namesz <- names(z) otherx <- names(x) otherx <- otherx[!(otherx %in% namesz)] othery <- names(y) othery <- othery[!(othery %in% namesz)] ## - add all other columns but as a set for each input data frame rx <- nrow(x); cx <- length(otherx) ry <- nrow(y); cy <- length(othery) z <- cbind(z, rbind(x[otherx], matrix(rep(NA, times=(ry * cx)), nrow=ry, ncol=cx, dimnames=list(NULL, otherx)))) z <- cbind(z, rbind(matrix(rep(NA, times=(rx * cy)), nrow=rx, ncol=cy, dimnames=list(NULL, othery)), y[othery])) z } ###------------------------------------------------------------------------ ### bindData.R ends here gdata/R/ans.R0000644000176000001440000000003612143472611012467 0ustar ripleyusersans <- function() .Last.value gdata/R/aggregate.table.R0000644000176000001440000000224512163370623014730 0ustar ripleyusers# $Id: aggregate.table.R 1681 2013-06-28 20:26:56Z warnes $ aggregate.table <- function(x, by1, by2, FUN=mean, ...) { warning("'aggregate.table' is deprecated and will be removed in a future version of the gdata package. ", "Please use 'tapply(X=", deparse(substitute(x)), ", INDEX=list(", deparse(substitute(by1)), ", ", deparse(substitute(by2)), "), FUN=", deparse(substitute(FUN)), if(length(list(...))>0) { l <- list(...) paste(", ", paste(names(l),"=", deparse(substitute(...)), sep="", collapse=", ") ) }, ")' instead.") tapply(X=x, INDEX=list(by1, by2), FUN=FUN, ...) } ## aggregate.table <- function(x, by1, by2, FUN=mean, ... ) ## { ## ## tab <- matrix( nrow=nlevels(by1), ncol=nlevels(by2) ) ## dimnames(tab) <- list(levels(by1),levels(by2)) ## ## for(i in 1:nrow(ag)) ## tab[ as.character(ag[i,1]), as.character(ag[i,2]) ] <- ag[i,3] ## tab ## } gdata/R/ConvertMedUnits.R0000644000176000001440000000340211763462122015002 0ustar ripleyusersConvertMedUnits <- function(x, measurement, abbreviation, to=c("Conventional","SI","US"), exact=!missing(abbreviation)) { MedUnits <- NULL ## Define to avoid R CMD check warning data(MedUnits,package='gdata', envir=environment()) to=match.arg(to) if(!missing(measurement) && missing(abbreviation)) { if(exact) matchUnits <- MedUnits[tolower(MedUnits$Measurement)== tolower(measurement),] else matchUnits <- MedUnits[grep(measurement, MedUnits$Measurement, ignore.case=TRUE),] } else if(missing(measurement) && !missing(abbreviation)) { if(exact) matchUnits <- MedUnits[tolower(MedUnits$Abbreviation)== tolower(abbreviation),] else matchUnits <- MedUnits[grep(match, MedUnits$Abbrevation, ignore.case=TRUE),] } else # both missing or both specified stop("One of `measurement' or `abbreviation' must be specified.") if(nrow(matchUnits)>1) stop( paste("More than one matching row. Please use 'exact=TRUE' ", "and supply one of these matching strings:", paste('\t"',matchUnits$Measurement, '"', sep='', collapse="\n\t"), sep="\n\t")) else if (nrow(matchUnits)<1) stop("No match") if (to %in% c("Convetional", "US")) { retval <- x / matchUnits$Conversion attr(retval,"units") <- matchUnits$ConventionalUnits } else { retval <- x * matchUnits$Conversion attr(retval,"units") <- matchUnits$SIUnits } retval } gdata/R/Args.R0000644000176000001440000000121111326374545012607 0ustar ripleyusersArgs <- function(name, sort=FALSE) { a <- formals(get(as.character(substitute(name)), pos=1)) if(is.null(a)) return(NULL) arg.labels <- names(a) arg.values <- as.character(a) char <- sapply(a, is.character) arg.values[char] <- paste("\"", arg.values[char], "\"", sep="") if(sort) { ord <- order(arg.labels) if(any(arg.labels == "...")) ord <- c(ord[-which(arg.labels[ord]=="...")], which(arg.labels=="...")) arg.labels <- arg.labels[ord] arg.values <- arg.values[ord] } output <- data.frame(value=I(arg.values), row.names=arg.labels) print(output, right=FALSE) invisible(output) } gdata/NEWS0000644000176000001440000003501612163435365012076 0ustar ripleyusersChanges in 2.13.2 (2013-06-28) ------------------------------ Enhancements: - Simplify ll() by converting a passed list to an environment, avoiding the need for special casing and the use of attach/detach. - Working of deprecation warning message in aggregate.table clarified. Changes in 2.13.1 (2013-03-24) ------------------------------ Enhancements: - Replaced calls to depreciated function ".path.package" with the new public function "path.package". Changes in 2.13.0 (2012-09-20) ----------------------------- New features: - New 'duplicated2' function which returns TRUE for *all* elements that are duplicated, including the first, contributed by Liviu Andronic. This differs from 'duplicated', which only returns the second and following (second-to last and previous when 'fromLast=TRUE') duplicate elements. - New 'ans' functon to return the value of the last evaluated top-level function (a convenience function for accessing .Last.value), contributed by Liviu Andonic. Bug Fixes: - On windows, warning messages printed to stdout by perl were being included in the return value from 'system', resulting in errors in 'sheetCount' and 'sheetNames'. Corrected. - The 'MedUnits' column names 'SIUnits' and 'ConventionalUnits' were reversed and misspelled. Changes in 2.12.0 (2012-09-12) ------------------------------ Other Changes: - 'stats::aggregate' was made into a generic on 27-Jan-2010, so that attempting to call 'aggregate' on a 'table' object will now incorrectly call 'aggregate.table'. Since 'aggregate.table' can be replaced by a call to tapply using two index vectors, e.g. aggregate.table(x, by1=a, by2=b, mean) can be replaced by tapply(x, INDEX=list(a, b), FUN=mean), the 'aggregate.table' function will now display a warning that it is depreciated and recommending the equivalent call to tapply. It will be removed entirely in a future version of gdata. Changes in 2.11.1 (2012-08-22) ------------------------------ Enhancements: - read.xls() now supports fileEncoding argument to allow non-ascii encoded data to be handled. See the manual page for an example. Bug Fixes: - The perl script utilized by read.xls() was incorrectly appending a space character at the end of each line, causing problems with character and NA entries in the final column. Changes in 2.11.0 (2012-06-18) ------------------------------ New Features: - read.xls() and supporting functions now allow blank lines to be preserved, rather than skipped, by supplying the argument "blank.lines.skip=FALSE". The underlying perl function has been extended to suppor this via an optional "-s" argument which, when present, *preserves* blank lines during the conversion. (The default behavior remains unchanged.) Other Changes: - Add SystemRequirements field specifying that perl is necessary for gdata to function fully. Changes in 2.10.6 (2012-06-12) ------------------------------ Bug fixes: - gdata::nobs.default() needs to handle logical vectors in addition to numeric vectors. Changes in 2.10.{3,4,5} (2012-06-08) ------------------------------------ Bug fixes: - Mark example for installXLSsupport() as dontrun so R CMD check won't fail on systems where PERL is not fully functional. - Correct name of installXLSsupport() in tests/test.read.xls.R. Other Changes: - Add dependency on R 2.13.0, since that is when stats::nobs appeared. Changes in 2.10.2 (2012-06-06) --------------------------------------- Bug fixes: - Fix issues in nobs.default identified in testing with the gmodels package. Changes in 2.10.1 (2012-06-06) ------------------------------ Bug fixes: - Undo removal of 'nobs' and 'nobs.lm'. Instead define aliases for 'nobs' and 'nobs.lm' to support backward compatibility for packages depending on gdata. Changes in 2.10.0 (2012-06-05) ------------------------------ New features: - New ls.funs() function to list all objects of class function in the specified environment. - New startsWith() function to determine if a string "starts with" the specified characters. Enhancements: - Add 'na.strings' argument to read.xls() to convert Excel's '#DIV/0!' to NA. Bug fixes: - Correct various R CMD check warnings Other changes: - Base S3 method for nobs() and nobs.lm() method removed since these are now provided in the stats package. Changes in 2.9.0 (2011-09-30) ----------------------------- New features: - Add centerText() function to center text strings for a specified width. - Add case() function, a vectorized variant of the base::switch() function, which is useful for converting numeric codes into factors. Enhancements: - Minor improvements to xls2csv() man page. CHANGES IN 2.8.1 (2011-04-15) ----------------------------- Enhancements: - nPairs() gains a summary method that shows how many times each variable is known, while the other variable of a pair is not Bug fixes: - Fix errors on windows when R or Perl install path includes spaces by properly quoting the path. CHANGES IN 2.8.1 (2010-11-12) ----------------------------- Enhancements: - Minor improvement to Args(), read.xls() man page. Bug fixes: - Modify write.fwf() to capture and pass on additional arguments for write.table(). This resolves a bug reported by Jan Wijffels. - Modify xls2sep.R to avoid use of file.access() which is unreliable on Windows network shares. CHANGES IN 2.8.0 (2010-04-03) ----------------------------- Enhancements: - When loaded, gtools (via an .onAttach() function) now checks: 1) if perl is available 2) whether the perl libraries for XLS support are available 3) whether the perl libraries for XLSX support are available If perl is not available, an appropriate warning message is displayed. If necessary perl libraries are not available, a warning message is displayed, as is a message suggesting the user run the (new) installXLSXsupport() function to attempt to install the necessary perl libraries. - The function installXLSXsupport() has been provided to install the binary perl modules that read.xls needs to support Excel 2007+ 'XLSX' files. CHANGES IN 2.7.3 (2010-04-02) ----------------------------- Enhancements: - New xlsFormats() command to determine which Excel formats are supported (XLS, XLSX). Bug Fixes: - No longer attempt to install perl modules Compress::Raw::Zlib and Spreadsheet::XLSX at build/compile time. This should resolve recent build issues, particularly on Windows. - All perl code can now operate (but generate warnings) when perl modules Compress::Raw::Zlib and Spreadsheet::XLSX when are not installed. - Also update Greg's email address. CHANGES IN 2.7.1 (2010-02-19) ----------------------------- Enhancements: - on Windows attempts to locate ActiveState perl if perl= not specified and Rtools perl would have otherwise been used in read.xls and other perl dependent functions. CHANGES IN 2.7.0 (2010-01-25) ----------------------------- Bug Fixes: - Fix building of Perl libraries on Win32 CHANGES IN 2.7.0 (2010-01-25) ----------------------------- Enhancements: - read.xls() now supports Excel 2007 'xlsx' files. - read.xls() now allows specification of worksheet by name - read.xls() now supports ftp URLs. - Improved ll() so user can limit output to specified classes New Functions: - sheetCount() and sheetNames() to determine the number and names of worksheets in an Excel file, respectively. Bug Fixes: - Fix formatting warning in frameApply(). - Resolve crash of "ll(.GlobalEnv)" - CHANGES IN 2.6.1 (2009-07-15) ----------------------------- Bug Fixes - Modify unit tests to avoid issues related to time zones. CHANGES IN 2.6.0 (2009-07-15) ----------------------------- Bug Fixes - Correct minor typos & issues in man pages for write.fwf(), resample() (Greg Warnes) - Correct calculation of object sizes in env() and ll() (Gregor Gorjanc) New Features - Add support for using tab for field separator during translation from xls format in read.xls (Greg Warnes) - Enhanced function object.size that returns the size of multiple objects. There is also a handy print method that can print size of an object in "human readable" format when options(humanReadable=TRUE) or print(object.size(x), humanReadable=TRUE). (Gregor Gorjanc) - New function wideByFactor that reshapes given dataset by a given factor - it creates a "multivariate" data.frame. (Gregor Gorjanc) - New function nPairs that gives the number of variable pairs in a data.frame or a matrix. (Gregor Gorjanc) - New functions getYear, getMonth, getDay, getHour, getMin, and getSec for extracting the date/time parts from objects of a date/time class. (Gregor Gorjanc) - New function bindData that binds two data frames into a multivariate data frame in a different way than merge. (Gregor Gorjanc) Other Changes - Correct Greg's email address CHANGES IN 2.5.0 ---------------- - New function .runRUnitTestsGdata that enables run of all RUnit tests during the R CMD check as well as directly from within R. - Enhanced function object.size that returns the size of multiple objects. There is also a handy print method that can print size of an object in "human readable" format when options(humanReadable=TRUE) or print(x, humanReadable=TRUE). - New function bindData that binds two data frames into a multivariate data frame in a different way than merge. - New function wideByFactor that reshapes given dataset by a given factor - it creates a "multivariate" data.frame. - New functions getYear, getMonth, getDay, getHour, getMin, and getSec for extracting the date/time parts from objects of a date/time class. - New function nPairs that gives the number of variable pairs in a data.frame or a matrix. - New function trimSum that sums trimmed values. - New function cbindX that can bind objects with different number of rows. - write.fwf gains the width argument. The value for unknown can increase or decrease the width of the columns. Additional tests and documentation fixes. CHANGES IN 2.4.2 (2008-05-11) ----------------------------- - Enhancements and bug fixes for read.xls() and xls2csv(): - More informative log messages when verbose=TRUE - File paths containing spaces or other non-traditional characters are now properly handled - Better error messages, particularly when perl fails to generate an output .csv file. - The 'shortcut' character "~" (meaning user's home directory) is now properly handled in file paths. - XLS files created by OpenOffice are now properly handled. Thanks to Robert Burns for pointing out the patch (http://rt.cpan.org/Public/Bug/Display.html?id=7206) CHANGES IN 2.4.1 (2008-03-24) ----------------------------- - Update perl libraries needed by xls2csv() and read.xls() to latest available versions on CRAN. - Add read.xls() to exported function list - Correct iris.xls example file. It didn't contain the complete & properly formatted iris data set. Fixed. - Fix typo in win32 example for read.xls() CHANGES IN 2.4.0 (2008-01-30) ----------------------------- - The keep() function now includes an 'all' argument to specify how objects with names starting with '.' are handled. - keep() now shows an informative warning message when a requested object does not exist - New vignette "Mapping Levels of a Factor" describing the use of mapLevels(). - New vignette "Working with Unknown Values" describing the use of isUnknown() and unknownToNA(). - Several enhancements to read.xls() (thanks to Gabor Grothendieck): - New function xls2csv(), which handles converting an xls file to a csv file and returns a connection to the temporary csv file - xls2csv() and read.xls() both allow a file or a url to be specified - read.xls() has a new 'pattern' argument which, if supplied, will ignore everything prior to the first line in th csv file that matches the pattern. This is typically used if there are a variable number of comment lines prior to the header in which case one can specify one of the column headings as the pattern. read.xls should be compatible with the old read.xls. - Minor fixes to drop.levels(), is.what(). - Implementation of unit tests for most functions. CHANGES IN 2.3.1 (2006-10-29) ----------------------------- - Arguments as well as their position of reorder.factor have been changed to conform with reorder.factor method in stats package, due to collision bug. Argument 'make.ordered' is now 'order' and old argument 'order' is now 'new.order'! Therefore, you have to implicitly specify new.order i.e. reorder(trt, new.order=c("PLACEBO", "300 MG", "600 MG", "1200 MG")) - trim() gains ... argument. - Added "unknown" methods for matrices. - Added c() method for factors based on mapLevels() functions. - Added write.fwf, which writes file in *F*ixed *W*idth *F*ormat. CHANGES FROM 2.1.X to 2.3.0 (2006-09-19) --------------------------------------- - Added mapLevels(), which produces a map with information on levels and/or internal integer codes. Contributed by Gregor Gorjanc. - Extended dropLevels() to work on the factors contained in a data frame, as well as individual factors. - Add unknown(), which changes given unknown value to NA and vice versa. Contributed by Gregor Gorjanc. - Extended trim() to handle a variety of data types data.frames, lists, factors, etc. Code changes contributed by Gregor Gorjanc. - Added resample() command that acts like sample() except that it _always_ samples from the arguments provided, even if only a single argument is present. This differs from sample() which behaves differently in this case. - Updated my email address. CHANGES IN GDATA 2.1.2 ----------------------- - Fixed bug in interleave.R - option to covert 1-column matrices to vector (based on Andrew Burgess's suggestion) - Updated Greg and Jim's email adresses - ll.R: Suppressed warning message in attach() call. - frameApply.Rd, reorder.Rd: Remove explicit loading of gtools in examples, so that failure to import functions from gtools gets properly caught by running the examples. - upperTriangle.R, man/upperTriangle.Rd: Add functions for extracting and modifying the upper and lower trianglular components of matrices. - is.what.R: Replaced the "not.using" vector with a more robust try(get(test)) to find out whether a particular is.* function returns a logical of length one. - DESCRIPTION: Added Suggests field - Updated the example in frameApply CHANGES IN GDATA 2.0.8 ----------------------- - Added DESCRIPTION and removed DESCRIPTION.in - Updated ll.Rd documentation - Fixed bug in Args.R, is.what.R, ll.R gdata/NAMESPACE0000644000176000001440000000626012163371056012611 0ustar ripleyusers export( .onAttach, ans, Args, aggregate.table, bindData, case, cbindX, centerText, combine, ConvertMedUnits, drop.levels, duplicated2, elem, env, frameApply, installXLSXsupport, interleave, is.what, keep, ll, ls.funs, lowerTriangle, "lowerTriangle<-", matchcols, nobs, # default method now provided by stats package nPairs, read.xls, rename.vars, remove.vars, reorder.factor, resample, sheetCount, sheetNames, startsWith, trim, trimSum, unmatrix, upperTriangle, "upperTriangle<-", wideByFactor, write.fwf, xls2csv, xls2tab, xls2tsv, xls2sep, xlsFormats, ## Object size stuff object.size, as.object_size, is.object_size, humanReadable, ## getDateTime stuff getYear, getMonth, getDay, getHour, getMin, getSec, ## mapLevels stuff mapLevels, as.levelsMap, as.listLevelsMap, is.levelsMap, is.listLevelsMap, "mapLevels<-", ## unknown stuff isUnknown, unknownToNA, NAToUnknown, ## Unit testing .runRUnitTestsGdata ) importFrom(stats, reorder) importFrom(stats, nobs) importFrom(gtools, mixedsort) S3method(reorder, factor) S3method(summary, nPairs) ## drop.levels stuff S3method(drop.levels, default) S3method(drop.levels, factor) S3method(drop.levels, list) S3method(drop.levels, data.frame) ## getDateTime stuff S3method(getYear, default) S3method(getYear, Date) S3method(getYear, POSIXct) S3method(getYear, POSIXlt) S3method(getMonth, default) S3method(getMonth, Date) S3method(getMonth, POSIXct) S3method(getMonth, POSIXlt) S3method(getDay, default) S3method(getDay, Date) S3method(getDay, POSIXct) S3method(getDay, POSIXlt) S3method(getHour, default) S3method(getMin, default) S3method(getSec, default) ## mapLevels stuff S3method(mapLevels, default) S3method(mapLevels, character) S3method(mapLevels, factor) S3method(mapLevels, list) S3method(mapLevels, data.frame) S3method("mapLevels<-", default) S3method("mapLevels<-", list) S3method("mapLevels<-", data.frame) S3method(print, levelsMap) S3method(print, listLevelsMap) S3method("[", levelsMap) S3method("[", listLevelsMap) S3method(c, levelsMap) S3method(c, listLevelsMap) S3method(unique, levelsMap) S3method(sort, levelsMap) ## nobs stuff S3method(nobs, data.frame) S3method(nobs, default) S3method(nobs, lm) # now provided by stats package ## Object size stuff S3method(print, object_size) S3method(c, object_size) ## unknown stuff S3method(isUnknown, default) S3method(isUnknown, POSIXlt) S3method(isUnknown, list) S3method(isUnknown, data.frame) S3method(isUnknown, matrix) S3method(unknownToNA, default) S3method(unknownToNA, factor) S3method(unknownToNA, list) S3method(unknownToNA, data.frame) S3method(NAToUnknown, default) S3method(NAToUnknown, factor) S3method(NAToUnknown, list) S3method(NAToUnknown, data.frame) ## trim stuff S3method(trim, character) S3method(trim, default) S3method(trim, factor) S3method(trim, list) S3method(trim, data.frame) gdata/INSTALL0000644000176000001440000000444611342322711012417 0ustar ripleyusers Windows ======= The instructions below relate to Windows only and are not relevant to other platforms. On Windows, the perl based routines (read.xls, xls2sep, xls2csv, xls2tab, xls2tsv, sheetNames, sheetCount) will work with ActiveState perl but not with Rtools perl. If you have ActiveState perl installed and the pl extension is associated with it (which the ActiveState installer associates automatically) then read.xls and other perl based routines in gdata will automatically locate ActiveState perl if you omit the perl= argument on these commands even if Rtools perl is ahead of it on your path. e.g. read.xls("mysheet.xls") Alternately you can use the perl= argument with a path to ActiveState perl to ensure it uses the right one. e.g. read.xls("mysheet.xls", perl = "C:\\Perl\\bin\\perl.exe") Also ensure that gdata was built with ActiveState Perl and not Rtools perl. This may require rebuilding gdata yourself like this: 1. Download and install the following (which all have automatic Windows installers and are therefore very easy to install): R (you likely already have R so you can likely skip this one) http://www.r-project.org Rtools http://www.murdoch-sutherland.com/Rtools/ ActiveState perl (ActivePerl) http://www.activestate.com/activeperl/ 2. If simply installing gdata in the usual way from within R results in read.xls and associated perl-based routines not working then re-install gdata yourself like this: Download gdata_*.tar.gz from: http://cran.r-project.org/web/packages/gdata/index.html and install it at the Windows console (not from within R): Rcmd INSTALL --build gdata_*.tar.gz Note: Rcmd is normally found in C:\Program Files\R\R-*\bin and if that is not on your path the above command should be written: "C:\Program Files\R\R-*\bin\Rcmd.exe" INSTALL --build gdata_*.tar.gz where the the path to Rcmd.exe should be replaced with the output of this R command: normalizePath(file.path(R.home(), "bin", "Rcmd.exe")) Note: On Vista and above you may need to run Rcmd as Administrator. Note: In the above the * in gdata_*.tar.gz should be replaced with the current version of gdata as found on: http://cran.r-project.org/web/packages/gdata/index.html gdata/DESCRIPTION0000644000176000001440000000111212164457167013100 0ustar ripleyusersPackage: gdata Title: Various R programming tools for data manipulation Description: Various R programming tools for data manipulation Depends: R (>= 2.13.0) SystemRequirements: perl Imports: gtools Version: 2.13.2 Date: 2013-06-28 Author: Gregory R. Warnes, Ben Bolker, Gregor Gorjanc, Gabor Grothendieck, Ales Korosec, Thomas Lumley, Don MacQueen, Arni Magnusson, Jim Rogers, and others Maintainer: Gregory R. Warnes License: GPL-2 NeedsCompilation: no Packaged: 2013-07-01 21:10:12 UTC; warnes Repository: CRAN Date/Publication: 2013-07-02 07:00:38 gdata/ChangeLog0000644000176000001440000015246612163435173013157 0ustar ripleyusers2013-06-29 warnes * [r1691] R/ll.R: Simplify ll() by stuffing list arguments into an environment, avoiding the need to use attach/detach. 2013-06-28 warnes * [r1685] inst/NEWS: Update NEWS for gdata 2.13.2 * [r1684] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Minor update to tests/*.Rout.save * [r1683] R/ll.R: Add on.exit() handler to ensure a matching detach occurs when attach is used in ll() * [r1682] DESCRIPTION: Update for gdata 2.13.2 * [r1681] R/aggregate.table.R: Improve deprecated message 2013-03-24 warnes * [r1645] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update test files for code changes * [r1644] inst/NEWS: Fix formatting in NEWS * [r1643] DESCRIPTION, inst/NEWS, man/read.xls.Rd, man/sheetCount.Rd, tests/test.read.xls.R: Replaced calls to depreciated function ".path.package" with the new public function "path.package". 2013-01-14 warnes * [r1639] R/installXLSXsupport.R, R/sheetCount.R, R/xls2sep.R, R/xlsFormats.R: Replace (obsolete) '.path.package' with 'find.package' function. 2012-09-20 warnes * [r1622] man/MedUnits.Rd, man/ans.Rd, man/duplicated2.Rd: Correct .Rd file errors detected by 'R CMD check'. * [r1621] NAMESPACE: Add duplicated() and ans() to the NAMESPACE. * [r1620] DESCRIPTION, inst/NEWS: Update for gdata 2.13.0. * [r1619] man/ConvertMedUnits.Rd: Fix typographic error. * [r1618] R/ans.R, R/duplicated2.R, man/ans.Rd, man/duplicated2.Rd: Add 'ans()' and 'duplicated()' contributed by Liviu Andronic. 2012-09-19 warnes * [r1617] data/MedUnits.rda: Correct column names. Unit columns were reversed and misspelled. * [r1616] R/sheetCount.R: Add ignore.stderr to system command in sheetCmd() to prevent stderr messages from being included in the captured output from the perl script. 2012-09-12 warnes * [r1606] DESCRIPTION, inst/NEWS: Update for gdata 2.12.0 * [r1605] R/aggregate.table.R, man/aggregate.table.Rd: 'stats::aggregate' was made into a generic on 27-Jan-2010, so that attempting to call 'aggregate' on a 'table' object will now incorrectly call 'aggregate.table'. Since 'aggregate.table' can be replaced by a call to tapply using two index vectors, e.g. aggregate.table(x, by1=a, by2=b, mean) can be replaced by tapply(x, INDEX=list(a, b), FUN=mean), the 'aggregate.table' function will now display a warning that it is depreciated and recommending the equivalent call to tapply. It will be removed entirely in a future version of gdata. * [r1604] .Rinstignore: Don't ignore .Rnw files, but do ignore .svn files. 2012-09-11 warnes * [r1603] man/interleave.Rd: Clarify workding of DROP argument to interleave(). * [r1602] man/interleave.Rd: Replace call to aggregate.table() with equivalent tapply() call since aggregate.table() is being depreciated. 2012-08-22 warnes * [r1601] DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for gdate 2.11.1. * [r1600] man/read.xls.Rd: Add example for read.xls() that shows how to use the fileEncoding argument to read in latin-1 encoded data. * [r1599] tests/latin-1.xls, tests/test.read.xls.R, tests/test.read.xls.Rout.save: Add XLSX test for latin-1 characters, and look for them in their new location in inst/xls/. * [r1598] inst/xls/latin-1.xls, inst/xls/latin-1.xlsx: add XLSX version of latin-1.xls * [r1597] tests/latin-1.xls, tests/test.read.xls.R, tests/test.read.xls.Rout.save: Add test file and code to ensure that read.xls() can properly handle files with alternative encodings. latin-1.xls contains each of the non-ascii latin-1 special characters in both the column headings and the body of the file. * [r1596] R/read.xls.R: Change code to have R read the csv/tab data from the file rather than from the connetion we made, so that file encodings can be properly handled. * [r1595] R/read.xls.R: Always close the connection. 2012-08-13 warnes * [r1594] inst/perl/xls2csv.pl: Remove trailing space from output line. 2012-06-18 warnes * [r1567] inst/NEWS: Update NEWS for 2.11.0 release. * [r1566] DESCRIPTION: Bump version number and add SystemRequirements for perl. * [r1565] R/xls2sep.R, inst/perl/xls2csv.pl, man/read.xls.Rd, tests/test.read.xls.R, tests/test.read.xls.Rout.save: read.xls() and supporting functions now allow blank lines to be preserved, rather than skipped, by supplying the argument "blank.lines.skip=FALSE". The underlying perl function has been extended to suppor this via an optional "-s" argument which, when present, *preserves* blank lines during the conversion. 2012-06-13 warnes * [r1564] DESCRIPTION, R/nobs.R, inst/NEWS: - nobs.default needs to handle logical vectors in addition to numeric vectors. - update DESCRIPTION and NEWS for 2.10.6. * [r1563] R/nobs.R: nobs.default needs to handle logical as well as numeric vectors. 2012-06-08 warnes * [r1562] DESCRIPTION, tests/test.read.xls.Rout.save: Update DESCRIPTION and tests * [r1561] tests/test.read.xls.R: fix incorrect function name * [r1560] DESCRIPTION, man/installXLSXsupport.Rd: Mark example for installXLSXsupport() to not be executed durin R CMD check. * [r1559] DESCRIPTION: stats:::nobs.default and stats::nobs.lm require R > 2.13.0, so add this as a dependency. 2012-06-06 warnes * [r1552] DESCRIPTION, inst/NEWS: Update for release 2.10.2 * [r1551] R/nobs.R: Fix bugs in nobs.default. * [r1550] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update to reflect warning on startup that 'nobs' hides 'stats::nobs'. * [r1549] man/nobs.Rd: Remove stray non-ASCII characters. * [r1548] R/nobs.R: The nobs() dispatch method must be defined in the gdata namespace to pick up the definition of gdata::nobs.default. * [r1547] DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for 2.10.1 release. * [r1546] NAMESPACE, R/nobs.R, man/nobs.Rd: Define aliases for 'nobs' and 'nobs.lm' to support backward compatibility for packages depending on gdata. * [r1545] DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for 2.10.0 release * [r1544] NAMESPACE, R/startsWith.R, man/startsWith.Rd: - Add manual page and NAMESPACE entry for startsWith(). - Add 'ignore.case' argument to startsWith(). * [r1543] tests/test.read.xls.Rout.save: Update to match new code. * [r1542] man/read.xls.Rd: Replace non-ASCII characters. * [r1541] R/read.xls.R, man/read.xls.Rd, tests/test.read.xls.R: Add na.strings to read.xls call to convert "#DIV/0!" to NA. 2012-06-05 warnes * [r1540] NAMESPACE: Remove nobs method dispatch and lm methods since these are now provided by the stats package. * [r1539] R/env.R: Spell out arguments to ls() to avoid R CMD check warnings. * [r1538] .Rinstignore: Add .Rinstignore file to omit latex style and source files from distributed inst/doc directory. * [r1537] R/ConvertMedUnits.R: - Add NULL definition of MedUnits to avoid R CMD check warning. - Specify local environment when calling data() so that MedUnits gets defined in the function's environment rather than the global environment. * [r1536] R/ls.funs.R: Fix error in ls.funs() that occurs when there are no objects in the environment. * [r1535] R/object.size.R: Avoid warning by calling utils::object.size rather than Internal(object.size(x)) 2012-05-31 warnes * [r1534] R/nobs.R, man/nobs.Rd: - Remove dispatch function 'nobs' and method 'nobs.lm' since these are now provided by the R 'stats' package. 2012-05-04 warnes * [r1532] DESCRIPTION: Update for next release * [r1531] NAMESPACE, R/ls.funs.R, man/ls.funs.Rd: Add ls.funs() to show functions defined in the specified environment. * [r1530] man/is.what.Rd: Fix enumerate syntax. 2012-04-03 warnes * [r1522] R/startsWith.R: Add startsWith() function. 2011-10-05 warnes * [r1516] man/read.xls.Rd: Fix typo 2011-09-30 warnes * [r1515] inst/NEWS: Update DESCRIPTION and README for 2.9.0 release. * [r1514] DESCRIPTION: Update DESCRIPTION and README for 2.9.0 release. 2011-09-20 warnes * [r1508] man/read.xls.Rd: Improve xls2csv() man page * [r1507] NAMESPACE: Add case() function, a vector equivalent of the switch() function * [r1506] R/case.R, man/case.Rd: Add case() function, a vector equivalent of the switch() function 2011-09-02 warnes * [r1500] NAMESPACE: Add 'centerText' function to center text strings for a specified width. * [r1499] R/centerText.R, man/centerText.Rd: Add 'centerText' function to center text strings for a specified width. 2011-04-16 warnes * [r1469] DESCRIPTION, inst/NEWS: Update for release 2.8.2 2011-04-15 warnes * [r1468] R/dQuote.ascii.R, R/installXLSXsupport.R, R/read.xls.R, R/sheetCount.R, R/xls2sep.R: Fix errors on windows when R or Perl install path includes spaces by properly quoting the path. * [r1467] R/xlsFormats.R: Fix error in xlsFormat() on windows when R or Perl install path includes spaces by quoting the path. 2011-01-15 ggorjan * [r1465] NAMESPACE, R/nPairs.R, inst/NEWS, inst/unitTests/runit.nPairs.R, man/nPairs.Rd: Adding summary method for nPairs 2010-11-12 warnes * [r1462] inst/NEWS: Update NEWS for gdata 2.8.1 * [r1461] DESCRIPTION: Update DEScription file for 2.8.1 release * [r1460] tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update test output to match latest code * [r1459] R/write.fwf.R, man/write.fwf.Rd, tests/test.write.fwf.eol.R: Modify write.fwf() to capture and pass on additional arguments for write.table(). This resolves a bug reported by Jan Wijffels. 2010-11-01 arnima * [r1453] man/Args.Rd: Minor improvement in Args.Rd help page 2010-10-19 warnes * [r1452] R/onAttach.R, R/xls2sep.R: Avoid use of file.access() which is unreliable on Windows network shares. 2010-07-08 ggrothendieck2 * [r1448] R/xls2sep.R: findPerl call added to xls2sep 2010-07-07 ggrothendieck2 * [r1447] man/read.xls.Rd: small improvements to read.xls.Rd 2010-05-03 warnes * [r1439] NAMESPACE, R/installXLSXModules.R, R/installXLSXsupport.R, R/onAttach.R, inst/NEWS, man/installXLSXsupport.Rd, man/xlsFormats.Rd: Rename installXLSXModules() to installXLSXsupport() and provide documentation for it. * [r1438] inst/NEWS: Update news for gdata 2.8.0 * [r1437] DESCRIPTION, NAMESPACE, R/installXLSXModules.R, R/onAttach.R, inst/perl/install_modules.pl, inst/perl/module_tools.pl, tests/test.read.xls.R: Add .onAttach function to check & inform user if perl is available, to check whether XLS and XLSX formats are avaiable, and to run the (new) installXLSXModules() functon to attempt to install the necessar libraries if not. Added installXLSXModules() function. 2010-05-02 warnes * [r1436] man/xlsFormats.Rd: Correct error in xlsFormat example * [r1435] DESCRIPTION, NAMESPACE, R/dQuote.ascii.R, R/findPerl.R, R/read.xls.R, R/xlsFormats.R, inst/doc/gregmisc.tex, inst/perl/install_modules.pl, inst/perl/module_tools.pl, inst/perl/sheetCount.pl, inst/perl/supportedFormats.pl, inst/perl/xls2csv.pl, man/ConvertMedUnits.Rd, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/read.xls.Rd, man/rename.vars.Rd, man/reorder.Rd, man/resample.Rd, man/sheetCount.Rd, man/trim.Rd, man/unmatrix.Rd, man/upperTriangle.Rd, man/xlsFormats.Rd, src, tests/test.read.xls.R, tests/test.read.xls.Rout.save, tests/tests.write.fwf.Rout.save: Update perl code to work (but generate warnings) when Zlib or SpreadSheet::XLXS is not instaled. Also update Greg's email address 2010-02-21 ggrothendieck2 * [r1423] R/read.xls.R, man/read.xls.Rd: isOpen problems fixed (isOpen must have changed in R since this worked in earlier versions). Also nba.xls link in read.xls.Rd disappeared. Replaced with similar link. 2010-02-20 ggrothendieck2 * [r1422] INSTALL: improved INSTALL file 2010-02-19 ggrothendieck2 * [r1421] INSTALL, R/dQuote.ascii.R, R/read.xls.R, R/sheetCount.R, inst/NEWS: added findPerl to locate ActiveState Perl on Windows if perl= not specified and Rtools perl would have otherwise been used. Also added INSTALL file. 2010-01-28 warnes * [r1419] DESCRIPTION, inst/NEWS: Update for release 2.7.1 * [r1418] R/xls2sep.R: xls2sep(): Show output of perl call when verbose=T * [r1417] src/build.bat: More Win32 fixes * [r1416] src/Makefile, src/Makefile.win, src/build.bat: More work on Win32 building * [r1415] src/Makefile, src/Makefile.win, src/build.bat: Support building Compress::Raw::Zlib perl package under windows. 2010-01-26 warnes * [r1413] inst/NEWS: Fix typos * [r1412] R/sheetCount.R: Show more details in sheetCount() when verbose=TRUE 2010-01-24 warnes * [r1411] R/xls2sep.R: Replace two calls to 'dQuote', to 'dQuote.ascii' * [r1408] inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Remove auto-generated pdf files from svn * [r1407] src/Makefile: create 'distclean' to remove perl binary dir, currently mac-only * [r1406] R/read.xls.R, R/xls2sep.R: Make read.xls() and xls2sep() quieter when verbose=FALSE * [r1405] tests/test.read.xls.R, tests/test.read.xls.Rout.save: Add tests for read.xls, sheetCount, and sheetNames * [r1404] src/Makefile: Modify makefile to 1) clean up after build, 2) make tar non-verbose * [r1403] R/read.xls.R, R/sheetCount.R: Close connections when done. * [r1402] man/read.xls.Rd: Fix typo * [r1401] man/read.xls.Rd, man/sheetNames.Rd: Fix R CMD CHECK errors * [r1400] src/Compress-Raw-Zlib-2.024, src/Compress-Raw-Zlib-2.024.tar.gz, src/Makefile: Use the original gz file for Compress::Raw::Zlib to avoid issues with 'non-platform-independent' filename error in R CMD CHECK * [r1399] inst/perl/Archive/README-Archive-Zip, inst/perl/Archive/README-Archive::Zip: Rename files to remove R CMD check error * [r1398] DESCRIPTION, inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update for 2.7.0 release * [r1397] NAMESPACE: Add new functions to NAMESPACE * [r1396] src, src/Compress-Raw-Zlib-2.024, src/Compress-Raw-Zlib-2.024/Changes, src/Compress-Raw-Zlib-2.024/MANIFEST, src/Compress-Raw-Zlib-2.024/META.yml, src/Compress-Raw-Zlib-2.024/Makefile.PL, src/Compress-Raw-Zlib-2.024/README, src/Compress-Raw-Zlib-2.024/Zlib.xs, src/Compress-Raw-Zlib-2.024/config.in, src/Compress-Raw-Zlib-2.024/examples, src/Compress-Raw-Zlib-2.024/examples/filtdef, src/Compress-Raw-Zlib-2.024/examples/filtinf, src/Compress-Raw-Zlib-2.024/fallback, src/Compress-Raw-Zlib-2.024/fallback/constants.h, src/Compress-Raw-Zlib-2.024/fallback/constants.xs, src/Compress-Raw-Zlib-2.024/lib, src/Compress-Raw-Zlib-2.024/lib/Compress, src/Compress-Raw-Zlib-2.024/lib/Compress/Raw, src/Compress-Raw-Zlib-2.024/lib/Compress/Raw/Zlib.pm, src/Compress-Raw-Zlib-2.024/pod, src/Compress-Raw-Zlib-2.024/pod/FAQ.pod, src/Compress-Raw-Zlib-2.024/ppport.h, src/Compress-Raw-Zlib-2.024/private, src/Compress-Raw-Zlib-2.024/private/MakeUtil.pm, src/Compress-Raw-Zlib-2.024/t, src/Compress-Raw-Zlib-2.024/t/000prereq.t, src/Compress-Raw-Zlib-2.024/t/01version.t, src/Compress-Raw-Zlib-2.024/t/02zlib.t, src/Compress-Raw-Zlib-2.024/t/07bufsize.t, src/Compress-Raw-Zlib-2.024/t/09limitoutput.t, src/Compress-Raw-Zlib-2.024/t/18lvalue.t, src/Compress-Raw-Zlib-2.024/t/99pod.t, src/Compress-Raw-Zlib-2.024/t/Test, src/Compress-Raw-Zlib-2.024/t/Test/Builder.pm, src/Compress-Raw-Zlib-2.024/t/Test/More.pm, src/Compress-Raw-Zlib-2.024/t/Test/Simple.pm, src/Compress-Raw-Zlib-2.024/t/compress, src/Compress-Raw-Zlib-2.024/t/compress/CompTestUtils.pm, src/Compress-Raw-Zlib-2.024/typemap, src/Compress-Raw-Zlib-2.024/zlib-src, src/Compress-Raw-Zlib-2.024/zlib-src/adler32.c, src/Compress-Raw-Zlib-2.024/zlib-src/compress.c, src/Compress-Raw-Zlib-2.024/zlib-src/crc32.c, src/Compress-Raw-Zlib-2.024/zlib-src/crc32.h, src/Compress-Raw-Zlib-2.024/zlib-src/deflate.c, src/Compress-Raw-Zlib-2.024/zlib-src/deflate.h, src/Compress-Raw-Zlib-2.024/zlib-src/infback.c, src/Compress-Raw-Zlib-2.024/zlib-src/inffast.c, src/Compress-Raw-Zlib-2.024/zlib-src/inffast.h, src/Compress-Raw-Zlib-2.024/zlib-src/inffixed.h, src/Compress-Raw-Zlib-2.024/zlib-src/inflate.c, src/Compress-Raw-Zlib-2.024/zlib-src/inflate.h, src/Compress-Raw-Zlib-2.024/zlib-src/inftrees.c, src/Compress-Raw-Zlib-2.024/zlib-src/inftrees.h, src/Compress-Raw-Zlib-2.024/zlib-src/trees.c, src/Compress-Raw-Zlib-2.024/zlib-src/trees.h, src/Compress-Raw-Zlib-2.024/zlib-src/uncompr.c, src/Compress-Raw-Zlib-2.024/zlib-src/zconf.h, src/Compress-Raw-Zlib-2.024/zlib-src/zlib.h, src/Compress-Raw-Zlib-2.024/zlib-src/zutil.c, src/Compress-Raw-Zlib-2.024/zlib-src/zutil.h, src/Makefile: Add Compress::Raw::Zlib code * [r1395] man/read.xls.Rd, man/sheetCount.Rd: Add/Update documentation * [r1394] R/xls2sep.R: Minor formatting change * [r1393] inst/xls/ExampleExcelFile.xls, inst/xls/ExampleExcelFile.xlsx: Add additional example files * [r1392] inst/perl/sheetCount.pl, inst/perl/sheetNames.pl, inst/perl/xls2csv.pl: Combine sheetCount.pl and sheetNames.pl and modify to support Excel 2007 'xlsx' format * [r1391] inst/perl/Spreadsheet/XLSX.pm, inst/perl/Spreadsheet/XLSX/Fmt2007.pm, inst/perl/xls2csv.pl: Complete changes to handle Excel 2007 'xlsx' files * [r1390] inst/perl/Archive, inst/perl/Archive/README-Archive::Zip, inst/perl/Archive/Zip, inst/perl/Archive/Zip.pm, inst/perl/Archive/Zip/Archive.pm, inst/perl/Archive/Zip/BufferedFileHandle.pm, inst/perl/Archive/Zip/DirectoryMember.pm, inst/perl/Archive/Zip/FAQ.pod, inst/perl/Archive/Zip/FileMember.pm, inst/perl/Archive/Zip/Member.pm, inst/perl/Archive/Zip/MemberRead.pm, inst/perl/Archive/Zip/MockFileHandle.pm, inst/perl/Archive/Zip/NewFileMember.pm, inst/perl/Archive/Zip/StringMember.pm, inst/perl/Archive/Zip/Tree.pm, inst/perl/Archive/Zip/ZipFileMember.pm, inst/perl/OLE/README-OLE-Storage_Lite, inst/perl/Spreadsheet/README-ParseExcel, inst/perl/Spreadsheet/README-XLS, inst/perl/Spreadsheet/XLSX, inst/perl/Spreadsheet/XLSX.pm, inst/perl/Spreadsheet/XLSX/Fmt2007.pm, inst/perl/Spreadsheet/XLSX/Utility2007.pm, inst/perl/VERSIONS: Add additional Perl modules to support Excel 2007 'xlsx' files 2010-01-24 ggrothendieck2 * [r1389] NAMESPACE, man/sheetNames.Rd: added sheetNames.Rd (documenting sheetNames/sheetCount) and updated NAMESPACE file. * [r1388] inst/NEWS: fixed spacing problem in NEWS 2010-01-23 warnes * [r1387] inst/perl/xls2csv.pl: Check if parsing the xls file succeeds... Current code doesn't handle new XML-based format * [r1386] inst/perl/Spreadsheet/XLSX: Remove perl 'Spreadsheet:XLSX' module since it depends on Compress-Raw-Zlib, which probably won't be available on most machines, and I don't have time to figure out how to get R to build it properly when gdata is installed. * [r1385] inst/perl/Spreadsheet/XLSX, inst/perl/Spreadsheet/XLSX/Fmt2007.pm, inst/perl/Spreadsheet/XLSX/Utility2007.pm: Add perl 'Spreadsheet:XLSX' module to support new Excel XML format files * [r1384] R/xls2sep.R: Add xls2tsv() convenience wrapper to xls2sep() * [r1383] R/read.xls.R, R/xls2sep.R: Update to match new xls2csv.pl code, allow specification of sheets by name, support CSV and TAB delimited files using the same code, other minor changes. * [r1382] R/sheetCount.R: Add sheetNames() function to extract the names from XLS files * [r1381] inst/bin/xls2csv.bat: Fix xls2csv.bat * [r1380] inst/perl/xls2csv.pl: If only one sheet is present in the file, don't insert the sheet name into the filename * [r1379] inst/xls/ExampleExcelFile.xls, inst/xls/ExampleExcelFile.xlsx: Add additional test/example Excel files * [r1378] inst/perl/xls2csv.pl, inst/perl/xls2tab.pl, inst/perl/xls2tsv.pl: Modify xls2csv.pl script to: - Use tab-delimiter and .tsv or .tab extension if called with the name xls2tsv.pl or xls2tab.pl, respectively. This allows a single source file and two symlinks to be used intstead of maintaining several almost-identical files. - Allow selection of sheets by name - Provide better error checking - Other code improvements * [r1377] inst/perl/sheetCount.pl, inst/perl/sheetNames.pl: Add perl scripts to extract worksheet names and sheet count from Excel files 2010-01-22 warnes * [r1376] inst/perl/OLE/Storage_Lite.pm: Upgrade Perl OLE::StorageLight module to version 0.19 * [r1375] inst/perl/Spreadsheet/ParseExcel.pm, inst/perl/Spreadsheet/ParseExcel/Cell.pm, inst/perl/Spreadsheet/ParseExcel/Dump.pm, inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm, inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm, inst/perl/Spreadsheet/ParseExcel/Font.pm, inst/perl/Spreadsheet/ParseExcel/Format.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser, inst/perl/Spreadsheet/ParseExcel/SaveParser.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser/Workbook.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser/Worksheet.pm, inst/perl/Spreadsheet/ParseExcel/Utility.pm, inst/perl/Spreadsheet/ParseExcel/Workbook.pm, inst/perl/Spreadsheet/ParseExcel/Worksheet.pm: Upgrade perl Spreadsheet::ParseExcel to version 0.56 * [r1374] DESCRIPTION: Add complete list of contributors 2010-01-22 arnima * [r1373] man/keep.Rd: Minor improvement in help page * [r1371] R/Args.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R, man/Args.Rd, man/env.Rd, man/is.what.Rd, man/keep.Rd, man/ll.Rd: Many small improvements to documentation of Arni's five functions 2010-01-22 warnes * [r1370] R/dQuote.ascii.R, R/read.xls.R, R/sheetCount.R, R/xls2sep.R: - Move xls2csv(), xls2tab(), xls2sep() to a separate file - Move qQuote.ascii to a separate file - Bug Fix: xls2csv(), xls2tab() failed to pass the provided 'perl' parameter to xls2sep() - New Feature: xls2sep() (and hence xls2csv, xls2tab, and read.xls) now supports ftp URLs. 2009-12-06 arnima * [r1369] R/Args.R, man/Args.Rd: Minor improvements of Args(). * [r1368] R/ll.R, man/ll.Rd: Improved ll() so user can limit output to specified classes 2009-11-16 arnima * [r1366] R/ll.R: ll(.GlobalEnv) does not crash anymore 2009-08-20 warnes * [r1357] man/cbindX.Rd, man/getDateTimePart.Rd, man/mapLevels.Rd, man/nPairs.Rd, man/trim.Rd, man/trimSum.Rd, man/unknown.Rd, man/write.fwf.Rd: Replace \ldots with \dots to make the new R CMD CHECK happy. 2009-08-19 warnes * [r1355] DESCRIPTION: Update for 2.6.1 release * [r1354] inst/unitTests/runit.getDateTimeParts.R: Modify unit tests to avoid issues related to zime zones. 2009-08-05 warnes * [r1353] inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update vignettes for 2.6.0 release * [r1352] man/frameApply.Rd: Fix formatting warning in frameApply man page 2009-07-16 ggorjan * [r1350] man/write.fwf.Rd: Reverting recent change and clarifying the meaning. 2009-07-16 warnes * [r1349] inst/doc/mapLevels.pdf, inst/doc/unknown.pdf, man/resample.Rd: Add contents of \value section for resample() man page * [r1348] tests/tests.write.fwf.Rout.save: Update test output to remove R CMD check warning * [r1347] inst/NEWS: Update ChangeLog and NEWS for gdata 2.6.0 release * [r1346] DESCRIPTION: Update DESCRIPTION file for gdata 2.6.0 * [r1345] inst/doc/gregmisc.tex, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf, man/ConvertMedUnits.Rd, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/rename.vars.Rd, man/reorder.Rd, man/trim.Rd, man/unmatrix.Rd, man/upperTriangle.Rd: Correct Greg's email address * [r1344] man/write.fwf.Rd: Correct minor typos in write.fwf() man page * [r1343] man/resample.Rd: Correct page for resample() * [r1342] NAMESPACE, R/read.xls.R, inst/perl/xls2tab.pl, man/read.xls.Rd: Add support for using tab for field separator during translation from xls format in read.xls 2009-04-19 arnima * [r1314] R/env.R, R/ll.R: Changed object.size(object) to unclass(object.size(object)). 2008-12-31 ggorjan * [r1312] NAMESPACE, inst/NEWS: Documenting changes and exporting the functions. * [r1311] R/object.size.R, man/humanReadable.Rd, man/object.size.Rd: Enhanced function object.size that returns the size of multiple objects. There is also a handy print method that can print size of an object in "human readable" format when options(humanReadable=TRUE) or print(object.size(x), humanReadable=TRUE). * [r1310] R/wideByFactor.R, inst/unitTests/runit.wideByFactor.R, man/wideByFactor.Rd: New function wideByFactor that reshapes given dataset by a given factor - it creates a "multivariate" data.frame. * [r1309] R/nPairs.R, inst/unitTests/runit.nPairs.R, man/nPairs.Rd: New function nPairs that gives the number of variable pairs in a data.frame or a matrix. * [r1308] R/getDateTimeParts.R, inst/unitTests/runit.getDateTimeParts.R, man/getDateTimePart.Rd: New functions getYear, getMonth, getDay, getHour, getMin, and getSec for extracting the date/time parts from objects of a date/time class. * [r1307] R/bindData.R, inst/unitTests/runit.bindData.R, man/bindData.Rd: New function bindData that binds two data frames into a multivariate data frame in a different way than merge. * [r1306] R/runRUnitTests.R, inst/unitTests/Makefile, inst/unitTests/runRUnitTests.R, man/gdata-package.Rd, man/runRUnitTests.Rd, tests/doRUnit.R: New function .runRUnitTestsGdata that enables run of all RUnit tests during the R CMD check as well as directly from within R. 2008-12-20 ggorjan * [r1305] NAMESPACE, R/trimSum.R, inst/NEWS, inst/unitTests/runit.trimSum.R, man/trimSum.Rd: * [r1304] tests/tests.write.fwf.Rout.save: To remove some output in the R CMD check 2008-08-05 ggorjan * [r1300] DESCRIPTION, NAMESPACE, R/cbindX.R, R/write.fwf.R, inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf, inst/unitTests/runit.cbindX.R, inst/unitTests/runit.write.fwf.R, man/cbindX.Rd, man/write.fwf.Rd, tests/tests.write.fwf.R, tests/tests.write.fwf.Rout.save: - Increased version to 2.5.0 - New function cbindX that can bind objects with different number of rows. - write.fwf gains width argument. Unknown values can increase or decrease the width of the columns. Additional tests and documentation fixes. 2008-06-30 arnima * [r1299] R/env.R, R/ll.R, man/env.Rd, man/ll.Rd: Simplified default 'unit' argument from c("KB","MB","bytes") to "KB". 2008-05-13 warnes * [r1270] inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update NEWS file for 2.4.2 * [r1269] R/read.xls.R: Use path.expand() to give proper full path to xls file to be translated by read.xls() * [r1268] R/read.xls.R: Modifed read.xls() failed to return the converted data... fixed. * [r1267] inst/perl/Spreadsheet/ParseExcel/Utility.pm: Correct broken patch for open-office support * [r1266] DESCRIPTION, R/read.xls.R: For read.xls() and xls2csv(): - Implement more informative log messages when verbose=TRUE - Quote temporary file name to avoid errors when calling perl to do the work. - Add better error messages, particularly when perl fails to generate an output .csv file. Update version number in DESCRIPTION. 2008-05-12 warnes * [r1265] inst/perl/Spreadsheet/ParseExcel/Utility.pm: Patch to correct issue with OpenOffice-created XLS files. Thanks to Robert Burns for pointing out the patch at http://rt.cpan.org/Public/Bug/Display.html?id=7206 2008-03-25 warnes * [r1250] DESCRIPTION, inst/NEWS, inst/doc/mapLevels.pdf, inst/doc/unknown.pdf: Update for version 2.4.1 * [r1249] inst/xls/iris.xls: Example iris.xls file didn't complete & properly formatted iris data set. Fixed. * [r1248] inst/perl/IO/AtomicFile.pm, inst/perl/IO/InnerFile.pm, inst/perl/IO/Lines.pm, inst/perl/IO/Scalar.pm, inst/perl/IO/ScalarArray.pm, inst/perl/IO/Stringy.pm, inst/perl/IO/Wrap.pm, inst/perl/IO/WrapTie.pm, inst/perl/OLE/Storage_Lite.pm, inst/perl/Spreadsheet/ParseExcel.pm, inst/perl/Spreadsheet/ParseExcel/Dump.pm, inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm, inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser.pm, inst/perl/Spreadsheet/ParseExcel/Utility.pm: Update perl modules to latest versions 2008-03-24 warnes * [r1247] man/read.xls.Rd: Fix typo in win32 example for read.xls() 2008-03-11 warnes * [r1246] NAMESPACE: Add xls2csv to exported function list 2008-01-30 warnes * [r1241] ChangeLog, DESCRIPTION, inst/NEWS: Update DESCRIPTION and NEWS for release 2.4.0 2008-01-29 arnima * [r1240] man/keep.Rd: Added argument 'all'. * [r1239] R/keep.R: Added argument 'all'. 2007-10-22 warnes * [r1196] DESCRIPTION: Clarify GPL version 2007-09-10 ggorjan * [r1169] man/upperTriangle.Rd: removed unmatched brace * [r1168] man/gdata-package.Rd: adding alias 2007-09-06 ggorjan * [r1162] man/gdata-package.Rd: keyword 2007-08-21 ggorjan * [r1154] man/gdata-package.Rd: package help page * [r1153] NEWS, inst/NEWS: move * [r1152] NEWS: move 2007-08-20 ggorjan * [r1151] inst/doc/mapLevels.tex: clean * [r1150] inst/doc/mapLevels.Rnw, inst/doc/mapLevels.pdf, inst/doc/mapLevels.tex: a real vignette * [r1149] inst/doc/unknown.Rnw, inst/doc/unknown.pdf, inst/doc/unknown.tex: a real vignette * [r1148] man/unknown.Rd: additional keyword for searchig 2007-08-17 ggorjan * [r1147] man/unknown.Rd: keyword 2007-07-22 arnima * [r1103] R/Args.R, R/keep.R: Reverted back to as.character(substitute(x)), so user can run keep(x), keep("x"), Args(x), and Args("x"). 2007-07-21 arnima * [r1102] R/keep.R: Changed as.character(substitute()) to deparse(substitute()), following help(substitute) recommendation. * [r1101] R/Args.R: Changed as.character(substitute()) to deparse(substitute()), following help(substitute) recommendation. 2007-07-10 warnes * [r1099] R/read.xls.R, man/read.xls.Rd: Update read.xls() code and docs with enhacements by Gabor Grothendieck 2007-06-06 ggorjan * [r1097] inst/doc/unknown.pdf, inst/doc/unknown.tex: last edits from newsletter * [r1096] R/drop.levels.R, man/drop.levels.Rd: drop levels as suggested by Brian Ripley * [r1095] inst/unitTests/Makefile, tests/doRUnit.R: better integration of unit tests * [r1094] R/mapLevels.R, R/unknown.R: making codetools happy 2007-01-28 arnima * [r1042] R/keep.R: Throw warnings rather than errors 2007-01-27 arnima * [r1041] R/keep.R: Meaningful error message is given when requested object does not exist * [r1040] R/is.what.R: is.* tests that return NA are not reported is.what recursion is avoided 2006-11-30 ggorjan * [r1035] R/unknown.R: minor commet to the code * [r1034] inst/doc/mapLevels.pdf, inst/doc/mapLevels.tex: description of mapLevels methods * [r1033] inst/doc/unknown.pdf, inst/doc/unknown.tex: description of unknown methods 2006-11-16 ggorjan * [r1013] R/c.factor.R, man/c.factor.Rd: seems that c.factor was not a good idea and there were better examples posted on r-devel list 2006-11-14 ggorjan * [r1012] man/combine.Rd, man/frameApply.Rd: Removed executable property 2006-11-10 ggorjan * [r1004] NAMESPACE, NEWS: just formatting 2006-11-02 ggorjan * [r1002] man/mapLevels.Rd, man/unknown.Rd: typos 2006-10-30 ggorjan * [r1001] man/write.fwf.Rd: some more examples for use of read.fwf after write.fwf * [r1000] inst/unitTests: ignore for report files * [r999] tests/tests.write.fwf.Rout.save: Id tag from source * [r998] NAMESPACE: removing unused import * [r997] R/write.fwf.R, inst/unitTests/runit.write.fwf.R, man/write.fwf.Rd, tests/tests.write.fwf.R: Id tag * [r996] NAMESPACE, NEWS, R/write.fwf.R, inst/unitTests/runit.write.fwf.R, man/write.fwf.Rd, tests/tests.write.fwf.R, tests/tests.write.fwf.Rout.save: write.fwf * [r995] inst/unitTests/runit.reorder.factor.R: Id tag * [r994] inst/unitTests/runit.reorder.factor.R: added unit tests for reorder.factor * [r993] R/c.factor.R, R/mapLevels.R, R/unknown.R, inst/unitTests/runit.drop.levels.R, inst/unitTests/runit.mapLevels.R, inst/unitTests/runit.trim.R, inst/unitTests/runit.unknown.R, man/c.factor.Rd, man/unknown.Rd, tests/doRUnit.R: mapply keeps names in R 2.4; POSIX unit tests solved; $ should work now 2006-10-29 ggorjan * [r992] NEWS, R/unknown.R, inst/unitTests/runit.unknown.R, man/unknown.Rd: fixed problem in tests; added unknown methods and tests for matrices * [r991] R/drop.levels.R, R/mapLevels.R, inst/unitTests/runit.mapLevels.R, man/mapLevels.Rd, tests/doRUnit.R: sort is generic now; mapply keeps names in R 2.4.0; some codetools suggestions fixed * [r990] DESCRIPTION, NAMESPACE: sort is generic from R 2.4.0 * [r989] DESCRIPTION, NEWS, R/trim.R, man/trim.Rd: trim() gains ... argument; version bump * [r988] NEWS, R/reorder.R, man/reorder.Rd: Fixed collision bug with stats version of reorder.factor 2006-10-27 warnes * [r987] R/c.factor.R, man/c.factor.Rd: Add c() method for factor objects, submitted by Gregor Gorjanc 2006-09-19 warnes * [r986] NEWS: Update NEWS file for 2.3.0 release * [r985] inst/unitTests/runit.trim.R: Explicitly set the local in runit.trim.R to one where leading spaces affect sort order so that the unit test works properly. 2006-09-18 warnes * [r984] inst/doc/Rnews.sty: Update Rnews.sty to the latest version * [r983] R/trim.R, inst/unitTests/Makefile, inst/unitTests/runit.trim.R, man/trim.Rd, tests/doRUnit.R: Integrate fixes for trim() from Gregor and myself. * [r982] inst/unitTests/report.html, inst/unitTests/report.txt: Remove unneeded files. 2006-09-13 warnes * [r981] R/unknown.R, inst/unitTests, inst/unitTests/Makefile, inst/unitTests/report.html, inst/unitTests/report.txt, inst/unitTests/runit.drop.levels.R, inst/unitTests/runit.mapLevels.R, inst/unitTests/runit.trim.R, inst/unitTests/runit.unknown.R, man/unknown.Rd, tests, tests/doRUnit.R: Add unknown() and unit test files * [r980] NAMESPACE, R/drop.levels.R, R/mapLevels.R, R/trim.R: More fixes from Gregor Gorjanc * [r979] DESCRIPTION, NAMESPACE, R/combineLevels.R, R/mapFactor.R, R/mapLevels.R, man/combineLevels.Rd, man/mapFactor.Rd, man/mapLevels.Rd: Add mapLevels functions from Gregor Gorjanc, along with associated unit tests. 2006-08-03 warnes * [r978] DESCRIPTION, NAMESPACE, R/combineLevels.R, R/mapFactor.R, man/combineLevels.Rd, man/mapFactor.Rd: Add Gregor Gorjanc's mapFactor() and combineLevels() functions. 2006-08-02 warnes * [r977] inst/doc/gregmisc.tex, man/ConvertMedUnits.Rd, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/read.xls.Rd, man/rename.vars.Rd, man/reorder.Rd, man/trim.Rd, man/unmatrix.Rd, man/upperTriangle.Rd: Update my email address * [r976] data/MedUnits.rda: Remove MedUnits.rda to convert to binary format * [r975] data/MedUnits.rda: Remove MedUnits.rda to convert to binary format * [r974] DESCRIPTION: Update version number * [r973] NAMESPACE, R/drop.levels.R, R/trim.R, man/drop.levels.Rd, man/trim.Rd: Integrate changes suggested by Gregor Gorjanc 2006-03-14 nj7w * [r940] NAMESPACE, R/trim.R, man/resample.Rd: Fixed R CMD check errors and added trim.default to NAMESPACE 2006-03-13 nj7w * [r939] R/trim.R: Added trim.character and trim.factor as per Gregor's suggestions 2006-01-03 warnes * [r839] NAMESPACE, R/resample.R, man/resample.Rd: Add resample() function, which generates a random sample or permutation from the elements of the supplied vector, even if the vector has length 1. This avoide the problems caused by base::sample()'s special case for vectors of length 1, where it attempts to sample from 1:x. 2005-12-13 nj7w * [r806] ChangeLog, NEWS: Updated news and removed changelog 2005-12-12 nj7w * [r798] DESCRIPTION, man/interleave.Rd: Updated version number for CRAN release 2005-12-08 warnes * [r789] R/interleave.R: Andrew Burgess reported that interleave() converts 1-column matrixes to vectors and provided a patch. A slight modification of his patch has been applied. There is now a 'drop' argument, which controls whether 'unnecessary' dimensions are dropped. The default is FALSE. 2005-12-04 warnes * [r779] man/interleave.Rd: Andrew Burgess reported that interleave() converts 1-column matrixes to vectors and provided a patch. A slight modification of his patch has been applied. There is now a 'drop' argument, which controls whether 'unnecessary' dimensions are dropped. The default is FALSE. 2005-12-01 nj7w * [r775] man/combine.Rd, man/reorder.Rd: Updated Greg's email address * [r774] man/drop.levels.Rd, man/frameApply.Rd, man/ll.Rd, man/read.xls.Rd: Updated Jim's email address 2005-11-21 arnima * [r744] R/ll.R: Suppressed warning message in attach() call. 2005-10-27 warnes * [r716] DESCRIPTION: Bump version number again to show that I fixed a bug. * [r715] DESCRIPTION, R/upperTriangle.R: Update version number * [r714] man/frameApply.Rd, man/reorder.Rd: Remove explicit loading of gtools in examples, so that failure to import functions from gtools gets properly caught by running the examples. * [r713] man/upperTriangle.Rd: Add missing close-bracket * [r712] NAMESPACE: Add upperTriangle and friends * [r711] R/upperTriangle.R, man/upperTriangle.Rd: Add functions for extracting, modifying upper and lower trianglular components of matrices. 2005-10-19 arnima * [r695] R/is.what.R: Replaced the "not.using" vector with a more robust try(get(test)) to find out whether a particular is.* function returns a logical of length one. 2005-09-12 nj7w * [r671] man/aggregate.table.Rd, man/interleave.Rd, man/matchcols.Rd, man/nobs.Rd, man/read.xls.Rd, man/rename.vars.Rd, man/trim.Rd, man/unmatrix.Rd: Updated Greg's email 2005-09-06 nj7w * [r661] man/reorder.Rd: Added library(gtools) in the example * [r660] NAMESPACE: Removed gtools dependency from NAMESPACE, as it was being used only in an example, and was giving warning * [r659] DESCRIPTION: Added Suggests field 2005-09-02 nj7w * [r658] man/frameApply.Rd: Updated the example in frameApply * [r656] NEWS: Added NEWS * [r654] ChangeLog: ChangeLog 2005-08-31 nj7w * [r644] DESCRIPTION: Added DESCRIPTION file * [r643] DESCRIPTION.in: removed DESCRIPTION.in 2005-07-20 nj7w * [r631] man/ll.Rd: updated documentation * [r630] R/Args.R: ## Args() was using a different search path from args(), e.g. rep <- function(local) return(NULL) args() Args() ## Fixed * [r629] R/is.what.R: ## is.what() was giving needless warnings for functions, e.g. is.what(plot) ## Fixed * [r628] R/ll.R: ## ll() was crashing if argument was a list of length zero, e.g. x <- list() ll(x) ## Fixed, and added sort.elements (see new help page) 2005-06-09 nj7w * [r625] R/Args.R, R/aggregate.table.R, R/combine.R, R/elem.R, R/env.R, R/frameApply.R, R/interleave.R, R/is.what.R, R/keep.R, R/ll.R, R/matchcols.R, R/nobs.R, R/read.xls.R, R/rename.vars.R, R/reorder.R, R/trim.R, R/unmatrix.R, inst/perl/IO/AtomicFile.pm, inst/perl/IO/InnerFile.pm, inst/perl/IO/Lines.pm, inst/perl/IO/Scalar.pm, inst/perl/IO/Scalar.pm.html, inst/perl/IO/ScalarArray.pm, inst/perl/IO/Stringy.pm, inst/perl/IO/Wrap.pm, inst/perl/IO/WrapTie.pm, man/aggregate.table.Rd, man/combine.Rd, man/drop.levels.Rd, man/interleave.Rd, man/nobs.Rd, man/rename.vars.Rd, man/reorder.Rd: Updating the version number, and various help files to synchronize splitting of gregmisc bundle in 4 individual components. 2005-06-07 nj7w * [r622] R/drop.levels.R: Reverting to the previous version of drop.levels.R by replacing sapply(...) with as.data.frame(lapply(...)) because sapply has the undesirable effect of converting the object to a matrix, which in turn coerces the factors to numeric. 2005-05-13 nj7w * [r621] R/read.xls.R: 1) Using dQuote.ascii function in read.xls as the new version of dQuote doesn't work proprly with UTF-8 locale. 2) Modified CrossTable.Rd usage in gmodels 3) Modified heatmap.2 usage in gplots. 2005-04-02 warnes * [r600] NAMESPACE, R/drop.levels.R, man/drop.levels.Rd: Move drop.levels() from gtools to gdata. * [r598] NAMESPACE, R/frameApply.R, man/frameApply.Rd: Move frameApply() to gdata package. 2005-03-31 warnes * [r586] man/elem.Rd: Comment out example to avoid R CMD check warnings 2005-03-22 warnes * [r578] NAMESPACE, R/ConvertMedUnits.R, data/MedUnits.Rda, data/MedUnits.rda, man/ConvertMedUnits.Rd, man/MedUnits.Rd: Fixes to pass `R CMD check'. * [r577] R/Args.R, R/env.R, R/ll.R, man/Args.Rd: Integrated fixes from Arni. * [r576] man/read.xls.Rd: Improve documentation of 'perl' argument and give examples. 2005-03-09 warnes * [r573] R/ConvertMedUnits.R, man/ConvertMedUnits.Rd, man/MedUnits.Rd: - Add ConvertMedUnits() plus documentation - Add documentation for MedUnits data set. * [r572] data/MedUnits.Rda: Update MedUnits data file. * [r571] data/MedUnits.tab: Don't need both .Rda and .tab forms of the data. * [r570] data, data/MedUnits.Rda, data/MedUnits.tab: Add MedUnits data set, which provides conversions between American 'Conventional' and Standard Intertional (SI) medical units. 2005-03-01 warnes * [r566] man/elem.Rd, man/ll.Rd: - Remove 'elem' call from ll example. - Add note to 'elem' man page that it is depreciated and 'll' should be used instead. 2005-02-26 nj7w * [r565] NAMESPACE, man/elem.Rd, man/env.Rd, man/ll.Rd, man/read.xls.Rd: *** empty log message *** 2005-02-25 warnes * [r564] NAMESPACE: Remove ll methods since the base function now handles lists and data frames. * [r563] R/elem.R, R/env.R, R/ll.R, man/Args.Rd, man/env.Rd, man/ll.Rd: Integrate changes submitted by Arni Magnusson 2005-01-31 warnes * [r529] R/read.xls.R, man/read.xls.Rd: Add ability to specify the perl executable and path. 2005-01-28 warnes * [r526] DESCRIPTION.in, NAMESPACE: Add dependency on stats. 2005-01-12 warnes * [r515] DESCRIPTION.in: Add dependency on R 1.9.0+ to prevent poeple from installing on old versions of R which don't support namespaces. 2004-12-27 warnes * [r509] man/unmatrix.Rd: Update usage to match code. * [r508] R/unmatrix.R: Replace 'F' with 'FALSE'. 2004-10-12 warneg * [r465] R/unmatrix.R, man/unmatrix.Rd: Add unmatrix() function 2004-09-27 warneg * [r461] DESCRIPTION, DESCRIPTION.in, NAMESPACE, man/.Rhistory: Updated to pass R CMD check. 2004-09-03 warneg * [r455] inst/xls, inst/xls/iris.xls: added to cvs. * [r454] inst/perl/xls2csv.pl: Checkin xls2csv.pl. Should have been in long ago, must have been an oversight * [r451] R/read.xls.R: Need to look for files using the new package name. * [r449] man/read.xls.Rd: Need to use the new package name when looking for iris.xls. * [r448] man/ll.Rd: Add ll.list to the to the list of functions described * [r447] NAMESPACE: Add ll and friends to the namespace * [r446] DESCRIPTION, DESCRIPTION.in, NAMESPACE, R/Args.R, R/aggregate.table.R, R/combine.R, R/elem.R, R/env.R, R/interleave.R, R/is.what.R, R/keep.R, R/ll.R, R/matchcols.R, R/nobs.R, R/read.xls.R, R/rename.vars.R, R/reorder.R, R/trim.R, man/reorder.Rd: initial bundle checkin 2004-09-02 warneg * [r442] DESCRIPTION, DESCRIPTION.in, NAMESPACE, man/.Rhistory: Initial revision 2004-08-27 warnes * [r441] R/reorder.R, man/reorder.Rd: Fixed bug in mixedsort, and modified reorder.factor to use mixedsort. 2004-07-29 warnes * [r427] inst/perl, inst/perl/IO, inst/perl/IO/AtomicFile.pm, inst/perl/IO/InnerFile.pm, inst/perl/IO/Lines.pm, inst/perl/IO/Scalar.pm, inst/perl/IO/Scalar.pm.html, inst/perl/IO/ScalarArray.pm, inst/perl/IO/Stringy.pm, inst/perl/IO/Wrap.pm, inst/perl/IO/WrapTie.pm, inst/perl/OLE, inst/perl/OLE/Storage_Lite.pm, inst/perl/Spreadsheet, inst/perl/Spreadsheet/ParseExcel, inst/perl/Spreadsheet/ParseExcel.pm, inst/perl/Spreadsheet/ParseExcel/Dump.pm, inst/perl/Spreadsheet/ParseExcel/FmtDefault.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan.pm, inst/perl/Spreadsheet/ParseExcel/FmtJapan2.pm, inst/perl/Spreadsheet/ParseExcel/FmtUnicode.pm, inst/perl/Spreadsheet/ParseExcel/SaveParser.pm, inst/perl/Spreadsheet/ParseExcel/Utility.pm: Add perl modules to CVS. 2004-07-27 warnes * [r425] man/read.xls.Rd: Fix typos/spelling. * [r424] man/read.xls.Rd: Add note that Perl is required for read.xls to work properly. 2004-07-16 warnes * [r420] R/read.xls.R: Remove the temporary csv file if reading it in fails. 2004-06-22 warnes * [r377] R/ll.R, man/ll.Rd: Add S3 methods for data frames and lists. 2004-06-08 warnes * [r371] inst/bin, inst/bin/xls2csv, inst/bin/xls2csv.bat: Moved from gregmisc/src/. * [r370] inst/tools: Remove the files in src, instead provide "pre-installed" perl packages in inst/perl. 2004-06-05 warnes * [r365] inst/tools/Makefile: Fix typo. * [r364] inst/tools/Makefile: Fix Unix makefile so that it works when invoked directly. * [r363] inst/tools/Makefile: Fixes for Windows * [r362] man/read.xls.Rd: Minor enhancment to read.xls example. * [r361] inst/tools/Makefile, inst/xls: - Merge Makefile.win into Makefile. Makefile.win now just redirects to Makefile. - Update xls2csv.bat and xls2csv shell script to correctly obtain thier installion path and infer the location of the perl code and libraries. - The xls2csv.pl script now assumes that the libraries it needs are installed into the same directory where it is. 2004-06-04 warnes * [r360] inst/tools/Makefile: More changes, indended to improve installation reliabilty and to make Makefile and Makefile.win as similar as possible. 2004-05-27 warnes * [r358] inst/tools/Makefile: Clean should remove scripts from source directory. * [r357] inst/perl: Moved to xls2csv.pl.in. * [r354] inst/perl/xls2csv.pl, inst/tools/Makefile: More fixes. * [r353] man/elem.Rd: Fix missing brace. * [r352] man/elem.Rd: Add explicit package name to see also links. * [r351] inst/perl/xls2csv.pl, inst/tools/Makefile: More xls2csv perl module support changes. * [r350] inst/tools/Makefile: More changes to fix local installation of perl modules. 2004-05-26 warnes * [r345] man/read.xls.Rd: Escape underscores in email addresses so Latex is happy. 2004-05-25 warnes * [r339] inst/perl/xls2csv.pl, inst/tools/Makefile: More changes to xls2csv code. * [r337] R/Args.R, man/Args.Rd: Add Args() function contributed by Arni Magnusson . * [r335] R/read.xls.R: - Change to call perl directly rather than depending on the installed shell script. This should make the code more portable to MS-Windows systes. - Add additional commants.. * [r332] inst/tools/Makefile: Makefile now modifies xls2csv.bat xls2csv.pl and xls2csv to contain an explicit path to the perl script/libraries. * [r330] inst/tools/Makefile: R CMD build calls the clean target to purge build files from the source tree when packaging. To get use this behavior correctly, I've renamed the clean target to cleanup and distclean target to clean. * [r329] R/read.xls.R, man/read.xls.Rd: Add read.xls(), a function to read Microsoft Excel files by translating them to csv files via the xls2csv.pl script. * [r326] inst/tools/Makefile: More fixes. Seems to work now. 2004-05-24 warnes * [r325] inst/perl, inst/perl/xls2csv.pl, inst/tools, inst/tools/Makefile, inst/xls, inst/xls/iris.xls: Add files to enable inclusion and installation of xls2csv.pl as part of the package. 2004-04-01 warnes * [r312] R/rename.vars.R, man/rename.vars.Rd: Add function remove.vars(). 2004-03-26 warnes * [r307] man/reorder.Rd: Contents of package 'mva' moveed to 'stats'. * [r298] R/is.what.R: - Fix is.what() for use under R 1.9.0 - is.what() now uses is.* functions found in any attached frame 2004-01-21 warnes * [r282] R/reorder.R, man/reorder.Rd: - Add ... argument to match generic provided in mva. 2004-01-19 warnes * [r275] R/elem.R, R/env.R, R/ll.R, man/keep.Rd, man/ll.Rd: - Integrated (partial) patch submitted by Arni Magnusson to clarify help text. - Modifed code to use match.arg(). 2003-12-15 warnes * [r271] R/env.R: - Applied patch from Arni that fixed a bug that caused env() to crash if any environment was completely empty 2003-12-03 warnes * [r253] man/elem.Rd, man/ll.Rd: - match function argument defaults with 'usage' 2003-12-02 warnes * [r249] man/ll.Rd: Add one argument, to match code. 2003-12-01 warnes * [r244] R/elem.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R: - Apply changes submitted by Arni Magnusson 2003-11-19 warnes * [r229] man/env.Rd, man/is.what.Rd, man/keep.Rd, man/ll.Rd: Changes to pass R CMD check. 2003-11-18 warnes * [r224] R/elem.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R: - Convert from MS-Dos to Unix line endings. - Reformat to 80 columns. 2003-11-17 warnes * [r223] man/elem.Rd: Replace 'T' with 'TRUE' to remove R CMD check error. * [r222] man/aggregate.table.Rd: Fix syntax error. 2003-11-10 warnes * [r220] R/elem.R, R/env.R, R/is.what.R, R/keep.R, R/ll.R, man/elem.Rd, man/env.Rd, man/is.what.Rd, man/keep.Rd, man/ll.Rd: - Add files contributed by Arni Magnusson . As well as some of my own. 2003-06-07 warnes * [r198] man/aggregate.table.Rd, man/interleave.Rd: - Fixed error in examples. Had sqrt(var(x)/(n-1)) for the standard error of the mean instead of sqrt(var(x)/n). 2003-05-23 warnes * [r197] R/matchcols.R, man/matchcols.Rd: - Fixed typos * [r196] R/matchcols.R, man/matchcols.Rd: - library() backported from 1.7-devel. This version of the function adds the "pos=" argument to specify where in the search path the library should be placed. - updated .First.lib to use library(...pos=3) for MASS to avoid the 'genotype' data set in MASS from masking the genotype funciton in genetics when it loads gregmisc - Added logit() inv.logit() matchcols() function and corresponding docs 2003-05-20 warnes * [r195] R/interleave.R: - Omit NULL variables. * [r194] R/trim.R, man/trim.Rd: - Added function trim() and assocated docs. 2003-04-22 warnes * [r188] R/reorder.R, man/reorder.Rd: - The mva package (which is part of recommended) now provides a generic 'reorder' function. Consequently, the 'reorder' function here has been renamed to 'reorder.factor'. - Removed check of whether the argument is a factor object. 2003-03-03 warnes * [r165] man/reorder.Rd: - Updated to match reorder.Rd which was exetended to handle factor label names in addition to numeric indices. * [r164] R/reorder.R: - Added handling of factor level names in addition to numeric indexes. 2002-09-23 warnes * [r118] inst, inst/doc, inst/doc/Rnews.dtx, inst/doc/Rnews.sty, inst/doc/gregmisc.pdf, inst/doc/gregmisc.tex: Added inst/doc directory and contents to CVS. * [r117] R/aggregate.table.R, R/combine.R, R/interleave.R, R/nobs.R, man/aggregate.table.Rd, man/combine.Rd, man/interleave.Rd, man/nobs.Rd, man/rename.vars.Rd, man/reorder.Rd: - Modified all files to include CVS Id and Log tags. 2002-08-01 warnes * [r112] R/reorder.R: Added reorder() function to reorder the levels of a factor. 2002-04-09 warneg * [r109] R/rename.vars.R, man/aggregate.table.Rd, man/interleave.Rd, man/reorder.Rd: Checkin for version 0.5.3 * [r108] R/interleave.R: - Properly handle case when some or all arguments are vectors. 2002-03-26 warneg * [r104] man/reorder.Rd: - Changed methods to include '...' to match the generic. - Updated for version 0.5.1 * [r102] R/nobs.R: Added ... to methods. * [r101] man/nobs.Rd: Updated to add ... parameter to function calls. * [r98] man/reorder.Rd: Initial checkin. * [r95] R/nobs.R: - Added CVS tags 2002-02-21 warneg * [r87] R/aggregate.table.R: - Fixed bug where row and column labels didn't always correspond to the contents. This only occured when a factor was used for by1 or by2 and the factors levels weren't in the default sort order. 2002-02-20 warneg * [r86] R/aggregate.table.R: New function. * [r85] man/aggregate.table.Rd: Initial checkin. * [r84] R/interleave.R, man/interleave.Rd: Initial checkin. * [r83] man/nobs.Rd: Noted that specialized methods exist. * [r82] man/nobs.Rd: Incorrectly had contents of nobs.R here instead of help text. Corrected. * [r81] man/rename.vars.Rd: Minor changes, typo and formatting fixes. * [r79] R/nobs.R, man/nobs.Rd: - initial checkin. 2001-12-12 warneg * [r53] man/rename.vars.Rd: Added omitted documentaton for 'info' parameter. Changed example code not to use 'Orthodont' data set so that the nlme package is not required. 2001-12-08 warneg * [r47] R/rename.vars.R: Changed 'T' to 'TRUE' in parameter list. 2001-12-07 warneg * [r45] man/rename.vars.Rd: - Fixed see also link. Mis-typed 'data.frame' as 'dataframe'. * [r44] R/rename.vars.R: Added attribution. * [r43] man/rename.vars.Rd: Added proper attribution to Don MacQueen. * [r39] man/rename.vars.Rd: Initial checkin. Unfortunately, I've lost the email of the person who sent this to me. I'll credit him/her when I find out who it was! * [r38] R/rename.vars.R: Initial checkin 2001-12-05 warneg * [r34] R, R/combine.R: - Renamed 'concat' function to 'combine' to avoid name conflict with an existing S-Plus function. * [r32] ., man, man/combine.Rd: - Changed function name 'concat' to 'combine' and renamed concat.Rd to combine.Rd gdata/.Rinstignore0000644000176000001440000000005412024120012013645 0ustar ripleyusersdoc/.*\.tex$ doc/.*\.sty$ doc/.*\.dtx$ \.svn