REBOL Personal Patterns Date written: 17-AUG-2020 Date reviewed: Date revised: A large number of programs written by a small number of people can take on a similar appearance. If you have an understanding of the similarities, it can help with understanding one of the programs when you run into it and must work on it. This document shows many of the patterns you will see when you look at programs from a particular author. ===The target audience This documentation was written at a particular installation and is aimed at programmers who encounter REBOL programs from a particular author and must understand what they are doing, perhaps for the purpose of modifying them or replacing them with programs in some other more common language. The best use of this documentation probably would be to just read through it. You will see little bites of how REBOL can do various things. With that background, when you then look at a larger program, you will see these patterns in it and you will understand what it is doing. There is another possible value in this document, depending on your own learning style. If you were to read the REBOL user guide and look through the function dictionary (which you should do) you will see all the little things that can be done with REBOL, but then you might wonder how to put those parts together to do something you might have in mind. This document works from the opposite direction. This document assumes that many of the things the author has done are things you might like to do as well, so you can use this document to find out how to do them. \note A note about the code samples. These "patterns" are the way one particular person writes his REBOL code. The specific feature of note is the use of lower case for REBOL functions and upper case for everything else. This convention was established early as a crutch so to speak when the author was not familiar with all the REBOL functions and wanted a way to differentiate them from other words in the program. You generally will NOT see this convention in other REBOL code. /note ===The REBOL header and the halt function Every REBOL program must start with the word "REBOL" followed by a block, that is, a pair of square brackets. In that block there actually can be anything you want, but there are some items that are officially used, and in that set of all officially-used items there are some that are almost always used, namely, the title and the purpose. That word REBOL is what the interpreter uses to locate the start of the script. Normally that is the very first thing on the very first line, but it does not have to be. You could put other documenting text lines in front of REBOL and they would be ignored by the interpreter. Normally, in the world of REBOL programming, that is not done, but it could be. An additional item we must note here is the "halt" function. The "halt" function makes the program stop and produce a command prompt. At the command prompt, you can examine the values inside the program with the "probe" function. Here is what the header looks like with the two most common items. It is presented in the form of a complete skeleton program that does nothing besides execute the "halt" function. This is a good way to start a script. Type the header and the "halt" function, and then run it to make sure there are no syntax errors. Then start adding code after the header, and at convenient points save and run the script and let it get to the "halt" function. Then probe around inside to make sure things are running as you expect before you go down the wrong rabbit hole as it were with ideas that don't work quite right. REBOL [ Title: "Demo program" Purpose: {This is a program to demonstrate how to code a program header. Note that the purpose can be a multi-line comment and so is enclosed in braces.} ] print "Done." halt Running the script produces a command prompt window, and the "probe" functions shown below show where the title and the purpose can be found. Done. >> probe system/script/title "Demo program" == "Demo program" >> probe system/script/header/purpose {This is a program to demonstrate how to code a program header. Note that the purpose can be a multi-line comment and so is enclosed in braces.} == {This is a program to demonstrate how to code a program header. Note that the purpose can be a multi-line comment and s... >> If you back up a level and probe the system value called system/script, you can what other item might be expected in the header. >> probe system/script make object! [ title: "Demo program" header: make object! [ Title: "Demo program" Date: none Name: none Version: none File: none Home: none Author: none Owner: none Rights: none Needs: none Tabs: none Usage: none Purpose: {This is a program to demonstrate how to code a program header. Note that the purpose can be a multi-line comment and so is enclosed in braces.} Comment: none History: none Language: none Type: none Content: none ] parent: make object! [ title: none header: none parent: none path: %/c/REBOL/ args: none words: none ] path: %/I/PatternSamples/ args: none words: none ] >> ===Including common data and functions It does not take the writing of many programs for one to realize that one is coding the same things over and over again. A better way of doing that would be to write that code in some more general way so that it could be used as-is, and then put it into every program NOT with copying and pasting, but in some other way so that the code exists in only one place. A way to accomplish the including of pre-written code parts is to write them in a complete REBOL script, and then "execute" that script in your program, somewhere near the beginning, with the "do" function. If that script that you "do" contains values and functions, those values and functions will become available to your program. It also does not take the writing of many programs to realize that all those re-usable bits need some sort of organization. Here is one idea. In the example below, the program includes two files. The first one, cob.r, contain values and functions that are specific to the installation that owns the programs. These would be things like logos, definitions of file paths, whatever is specific to the site. The other, glb.r, contains values and functions that are NOT specific to the installation but are used in almost every program, so much so' that we can package them all up into one file and just include it in every program as a standard procedure because it is almost certain that some parts of it will be needed. Here is the sample. REBOL [ Title: "Testing shell" Purpose: {General testing skeleton for demo programs.} ] do %/COB-APPS/VOL1/COB_REBOL_MODULES/cob.r do %/COB-APPS/VOL1/COB_REBOL_MODULES/glb.r print "Done." halt \note Note that the above "do" functions refer to scripts stored in a particular place, identified by a UNC path. This is just a sample of how do do this. This example was taken from a particular installation, and your locations would be different. /note We can run the sample and let it halt, and then see what is inside those common modules. Done. >> source GLB-SUBSTRING GLB-SUBSTRING: func [ {Return a substring from the start position to the end position} INPUT-STRING [series!] "Full input string" START-POS [number!] "Starting position of substring" END-POS [number!] "Ending position of substring" ][ if END-POS = -1 [END-POS: length? INPUT-STRING] return skip (copy/part INPUT-STRING END-POS) (START-POS - 1) ] >> The glb.r module contains assorted functions that are used often. One of them is to extract a substring based on starting and ending character positions. We can "probe" that function, but in the case of a function the appropriate method to examine it is the "source" function as shown. ===Basic VID GUI Some people like to plod along in their coding, and find beauty in something that others would consider inelegant. This is an example of a plodding way to start writing a window with the Visual Interface Dialect. In this case, we use a word to refer to the layout, and later in the program use the "view" function to show that window. This all could be done in one combination of statements, of course, as in "view layout [...]". The first thing we do is use the "across" keyword to establish the top-to-bottom left-to-right ordering of items on the window. This is just personal preference. This way, we have to use the "return" keyword to go to the next row. The function to be performed when a button is clicked is contained in the block after the button declaration. This can be a whole bunch of REBOL code or you could put just a function name there and define the function elsewhere in the program. Note that we include a "Debug" button that will halt the program so we can "probe" around and check things. This button might be taken out once a program became a production program. REBOL [ Title: "Testing shell" Purpose: {Basic VID GUI.} ] system/console/prompt: "Use 'probe' to look around: " MAIN-WINDOW: layout [ across banner "GUI demo" return box 50x50 red box 50x50 green box 50x50 blue return button 120 "VID documentation" [browse http://cobolrebol.com/pages/documentation/VIDforCOBOL.html] return button "Quit" [quit] button "Debug" [halt] ] view MAIN-WINDOW ===VID stylize If you are making a VID layout and are producing a lot of things that are the same, like a lot of buttons of a non-default size, there is a way to reduce the coding. That is with the "sytlize" function where you define words that refer to VID object with certain values. The example below shows a very simple example of defining a new kind of button. You can do a lot with stylize and so the way to make friends with that feature would be to just try it as appropriate and see how far you can push the concept. REBOL [ Title: "Testing shell" Purpose: {VID stylize.} ] LOCAL-STYLES: stylize [ BIGBUTTON: button 128x128 font [size: 14] ] MAIN-WINDOW: layout/tight [ styles LOCAL-STYLES across space 0x0 at 0x0 BIGBUTTON "Quick help for this window" [alert "Button pressed"] at 128x0 BIGBUTTON "Quit" [quit] ] view center-face MAIN-WINDOW ===VID "at" keyword for positioning VID was designed to be simple for simple things, where items will be placed on the window with default positioning. However, you can exercise more control with the "at" keyword that allows you to specify pixel positions for items. The following basic example shows the concept. REBOL [ Title: "Testing shell" Purpose: {VID AT keyword.} ] MAIN-WINDOW: layout/tight [ at 0x0 box 100x100 red at 100x0 box 100x100 green at 200x0 box 100x100 blue at 0x100 box 100x100 beige at 100x100 box 100x100 brick at 200x100 box 100x100 tan ] view center-face MAIN-WINDOW ===VID GUI panels Sometimes, when making a GUI window, just placing items on the window top-to-bottom left-to-right does not give quite the look you want. It is possible to make "sub-layouts" using the "panel" feature of VID, as shown in this example. REBOL [ Title: "Testing shell" Purpose: {VID GUI panels.} ] LEFT-PANE: [ backcolor tan size 200x200 button red button red button red ] RIGHT-PANE: [ backcolor beige size 200x200 button green button green button green ] MAIN-WINDOW: layout [ across panel 200x200 LEFT-PANE panel 200x200 RIGHT-PANE return button "Quit" [quit] ] view center-face MAIN-WINDOW ===VID scroller The VID scroller is a fussy little thing that is used a lot, and so that fussing must be done a lot. In the sample below, there is a function for displaying text with a scroller that shows the fussing. REBOL [ Title: "Quickhelp" ] QUICKHELP: func [ TXT ] [ QH-WINDOW: layout [ across banner "Quick help" return QH-TXT: info 300x300 wrap font [size: 14 style: 'bold] QH-SCROLLER: scroller 20x300 [scroll-para QH-TXT QH-SCROLLER] return button "Close" [hide-popup] ] QH-TXT/text: TXT QH-TXT/line-list: none QH-TXT/para/scroll/y: 0 QH-TXT/user-data: second size-text QH-TXT QH-SCROLLER/data: 0 QH-SCROLLER/redrag QH-TXT/size/y / QH-TXT/user-data inform QH-WINDOW ] HELPTEXT: {Quick help This is a function to be included in another program, and that will, when called with a string of documentation, pop up that documentation in an 'inform' window. Normally, documentation would not be coded into a program because it takes space. This function is meant for a minimum amount of documentation (or text for any purpose) that is meant to be accessed quickly, like with a button. Items worth noting in this program: When you load up a text area of significant size (we are not able to more specific on that) you have to set the various values as shown in the above code sample. Of particular importance is settingthe line-list to none. If you do not do that, and if you later change the text value, you will get little artifacts of the prior text hanging around in the text area. This feature is documented in the official REBOL documentation, but it is something you have to stumble across. } view center-face layout [ banner "Quickhelp test" button "Quickhelp" [QUICKHELP HELPTEXT] button "Quit" [quit] ] ===VID timer It seems that it is possible to attach a "rate" to any item on a VID window, and then specify the "engage" function of the "look and feel" attributes of that item, and that function will be activated at a time interval specified for the "rate." The following example is offered without comment, other than to say that it does work. You can use it as a model. REBOL [ Title: "Testing shell" Purpose: {VID timer demo.} ] TIMER-INTERVAL: 00:30:00 COUNTER: TIMER-INTERVAL START-TIMING: does [ COUNTER: TIMER-INTERVAL MAIN-COUNTER/text: to-string COUNTER show MAIN-COUNTER ] MAIN-WINDOW: layout [ origin 0 MAIN-TIME: h1 100 red black (to string! now/time) rate 1 feel [ engage: [ MAIN-TIME/text: now/time show MAIN-TIME COUNTER: COUNTER - 00:00:01 if COUNTER < 00:00:01 [ COUNTER: TIMER-INTERVAL ] MAIN-COUNTER/text: to-string COUNTER show MAIN-COUNTER ] ] MAIN-COUNTER: h1 100 (to-string COUNTER) button "Reset" [START-TIMING] ] view center-face MAIN-WINDOW ===Building code with build-markup REBOL contains a function that looks like it was created specifically for generating HTML code, although it could be used in other situations. If you write a string of HTML code and leave places for various data items marked by the angle-brackets and percent signs, as shown in the example, and then in those places you put REBOL code, then the build-markup function will go throught that string of code and execute the REBOL code inside the markers. In this example, the places where replacement will be done are just REBOL words, and those words will be replaced with their values. However, the code there could be more complex. REBOL [ Title: "Testing shell" Purpose: {Building html with build-markup.} ] HTML: { Demo page

Report for <% now %>

Information about <% NAME %> at <% LOCATION %>.

} NAME: "Steven" LOCATION: "City of Bloomington" print build-markup HTML print "Done." halt ===GO or CANCEL A common situation when running a program is to get to a point where the operator must decide if he should proceed, or if something has happened that would require the program to be canceled. This is a way of coding that. A seemingly-undocumented feature of the "alert" function is that it can take three arguments. The first is the text to be displayed, and the other two are the texts for two buttons. Clicking the first button will produce a true value, and clicking the second button will produce a false value. REBOL [ Title: "Testing shell" Purpose: {GO or CANCEL.} ] GO?: alert [ "OK to proceed?" "OK" "Cancel" ] if not GO? [ alert "Operation canceled" quit ] print "Done." halt ===Files in directory A very common operation for file management is to find all the files in a folder, usually the current one. Here is how that is done. When you code "read %." what you get in return is a block, and that block contains all the files in the current directory. In the sample below, we assign a word to that block so we can loop through the block and list the file names, just to show that things worked. REBOL [ Title: "Testing shell" Purpose: {Files in directory.} ] FILE-ID-LIST: read %. foreach FILENAME FILE-ID-LIST [ print FILENAME ] print "Done." halt ===Making a context for word isolation In a big program you can start to have problems with a lot of words that mean almost the same thing and so should ideally be the same, but you can't make them the same. REBOL has a way to isolate words in what it refers to as a "context." This is the idea of global and local variables in other languages. This is a simple demo of how that is done. Note that there is a word TEST-STRING in the global context and in the context called ISOLATED-WORDS and those words do not refer to the same things. REBOL [ Title: "Testing shell" Purpose: {Show idea of context.} ] ISOLATED-WORDS: context [ TEST-STRING: "In a Chevrolet" ] TEST-STRING: "See the USA" print TEST-STRING print ISOLATED-WORDS/TEST-STRING print "Done." halt ===Making an object for code isolation Another way to handle the issue of word "collisions" and to reduce some of the coding you might have to do, is to create objects. An object is an encapsulation of code and data in such a way that you can make instances of an object (or not; you are not required to use an object by making an instance of it). In the example, there is an object (OBJMODEL) and then we make two copies of it with modifications to what is in the model. Words in one instance are the same as the same words in another, but they are not the same, and are referenced with the "path" notation as shown in the example. REBOL [ Title: "Testing shell" Purpose: {Making objects.} ] OBJMODEL: make object! [ ID: "Objectmodel" INFO: does [print ["I am " ID]] ] OBJ1: make OBJMODEL [ID: "Object 1"] OBJ2: make OBJMODEL [ ID: "Object 2" NOTIFY: does [print [ID " is running"]] ] OBJ1/INFO OBJ2/INFO OBJ2/NOTIFY print "Done." halt ===Email sending This is how to do REBOL's signature operations of sending email. This sample show sending a subject and an attachment. REBOL [ Title: "Testing shell" Purpose: {Email sending.} ] ADDRESSES: [ admin@dummyaddress.com techsaur@dummyaddress.com ] SUBJECT: "File attachment" ATTACHMENT: %EmailSending.r MESSAGE: {The attached file in for your reference. Plese look it over and reply with any questions. } send/subject/attach ADDRESSES MESSAGE SUBJECT ATTACHMENT print "Done." halt ===Embedding the user.r function When REBOL is installed, and you do those initial settings, a script is created called user.r, and REBOL then runs that script whenever it starts. The script contains information needed to make emailing work. That script goes somewhere (but where?) and normally can be found by REBOL, but if you put the interpreter elsewhere for any reason, sometimes that file can NOT be found. You will know that has happened when emailing does not work. To fix that situation, one thing you can do is hard-code the contents of user.r into your program, or copy user.r to some place where you know it is, and the "do" user.r in your own scripts. That code would look something like the following example, adjusted for your own situation. REBOL [ Title: "Testing shell" Purpose: {Embedding the user-dot-r functions. The email addresses below and the smtp server address would be replaced with real values.} ] set-net [swhite@dummyaddress.com "10.1.0.100" "" none none none swhite@dummyaddress.com none] if (not none? system/view) [ system/view/screen-face/options: none ] set-user-name "Mister White" print "Done." halt ===Function definition with refinements and nested function Defining functions is something you have to know how to do, so here is an example. This example is a little more complicated than a basic example, but not so much that it can't be followed. Note that this example shows how to use the refinements (those words after the slashes that you sometimes see in function calls) and that it is allowed to embed a function in a function. The sample below shows hot to reformat a date, but what the function does is not relevant; this just shows how to code a function. REBOL [ Title: "Testing shell" Purpose: {Function definitions, with nested function and refinements.} ] to-yyyymmdd: func [when /hyphens /slashes /local stamp add2] [ add2: func [num] [ ; always create 2 digit number num: form num if tail? next num [insert num "0"] append stamp num ] stamp: form when/year if hyphens [append stamp "-"] if slashes [append stamp "/"] add2 when/month if hyphens [append stamp "-"] if slashes [append stamp "/"] add2 when/day return stamp ] print to-yyyymmdd/slashes now print "Done." halt ===Running a script with a DOS batch file When you set up a program for someone else to run in a production environment, you want to make that operation as smooth as possible. With REBOL, you are allowed to put the interpreter anywhere, and there are run-time switches to run the interpreter without installing it. You can take advantage of those features to make a DOS batch file to run your program. The example below was taken from a particular installation, so you would change things to match your own situation. Note that the interpreter is on a server accessed by a UNC path, and the script is on a mapped drive. In other words, you are not required to run REBOL from where it is installed on the C: drive (in Windows). The "-i" swicth runs the interpreter without installing, and the "-s" switch suppresses the security warning you might get if you access files outside the current directory. start "" \\cob-apps\vol1\REBOL\rebview.exe -i -s --script /I/PatternSamples/LaunchTest.r ===Running a scripts with a Powershell script Running a REBOL script from Powershell is about the same as running with a batch file. I the following examle from a particular installation, the REBOL SDK installed on the C: drive is used to run another script on the C: drive. As long as none of the file paths contain spaces, the syntax is easy. C:\rebol-sdk\tools\rebcmdview.exe -i -s --script C:\COBscripts\Falsealarms\printbills.r ===Two ways to for a script to run other scripts Sometimes you will want one of your programs to start another REBOL program. This is very handy if you use REBOL VID to make a little program launcher, where clicking a button starts another program without causing the launcher to quit. In Windows, you can make a DOS batch file as shown above and "call" it as shown in the example below. In any platform, you can use the "launch" function to start another run unit of REBOL to run another script. REBOL [ Title: "Testing shell" Purpose: {Two ways to launch.} ] view layout [ across button 200 "Run with launch function" [launch %LaunchTest.r] return button 200 "Run by calling batch file" [call "LaunchTest.bat"] ] ===Changing part of a string Processing text can involve the operation of inserting characters into a string at a specified character position. Here is an example of how that is done. The goal of the one line of code below is to insert a string of nine characters into a larger staring, starting at the sixth position. The way to do that is to skip five characters into the string, and then change part of the string, nine characters of it, to the new value. That is done with the handy REBOL syntax of stringing functions together. REBOL [ Title: "Testing shell" Purpose: {General testing skeleton for demo programs.} ] TEST-STRING: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" NEWVAL: "123456789" change/part skip TEST-STRING 5 NEWVAL 9 print TEST-STRING print "Done." halt ===Reducing and joining There are several ways to string things together in REBOL, but the procedure that seems the most useful is the "rejoin" function. It takes a block of anything and strings all the parts together. The data type of the result is the data type of the first item in the block, as shown in this example. By the way, "rejoin" seems to mean "reduce" and "join" which has the effect of evaluaging the words in the block. REBOL [ Title: "Testing shell" Purpose: {General testing skeleton for demo programs.} ] FILE-ID: rejoin [ what-dir now/year "-" now/month "-" now/day ".txt" ] print rejoin [ FILE-ID " is a word of type " type? FILE-ID ] print "Done." halt ===Requesting a file name A very common operation is doing something to a file, and asking for the name of the file at run time. There is a function for that. If you use the "request-file" function with no refinements, you will get a requestor box that will allow you to select several files, and the result will be a block that contains all the selected names. If you used the "request-file" function with no refinements and really wanted just one file name, you will have to refer to the "first" item in the block that was returned. Most of the time, however, you really will want just one file name, so the way to get one file name is to use the "only" refinement as shown in the example. If the operator uses the "cancel" button on the file requestor window, the "request-file" function will return a false value. You can test for that and then take appropriate action if no file was selected. In the example below, we assume that most of the time the operator WILL select a file, so we go ahead and assign a word (FILE-ID) to that file name so we can refer to it later. REBOL [ Title: "Testing shell" Purpose: {Requesting a file name.} ] if not FILE-ID: request-file/only [ alert "No file requested." quit ] print "Done." halt ===Playing a sound REBOL can use the sound port on your computer. There is documentation on the REBOL web site for this. What you might find yourself doing is wanting to play a sound and that is all, and you might be happy to find one way to do it and use that over and over again, like the following example. It seems that REBOL can play only WAV files, and not all kinds. We have seen some failures to play certain WAV files. If you find one that does not play, try another. REBOL [ Title: "Testing shell" Purpose: {Playing a sound.} ] SOUND-1: load %complete.wav wait 0 SOUND-PORT: open sound:// insert SOUND-PORT SOUND-1 wait SOUND-PORT close SOUND-PORT print "Done." halt ===Basic table lookup with select REBOL has a function that seems designed for table lookup. If you can create a block of values where you have repetitions of some key value you might want to look up and some attribute value associeated with the key value, you can use the "select" function to find a key value and return the item immediately after the key value. The following example shows a very simple case. REBOL [ Title: "Testing shell" Purpose: {Basic lookup with select.} ] STATES: [ "MN" "Minnesota" "WI" "Wisconsin" "IA" "Iowa" ] print select STATES "WI" print select STATES "MN" print select STATES "SD" if not STATENAME: select STATES "ND" [ STATENAME: "Not found" ] print STATENAME print "Done." halt ===Creating a more advanced lookup table If you need a lookup table where you look up one key value and then need several associated values, you can put the several associated values into a block after the key value and still use the "select" function as shown above. The "select" function will return the block after the key value, or a false value if nothing is found. Here is an example of a program that will use data that might have come from a database and convert it to a form that works with the "select" function. In this example, the lookup table is saved to a text file for later use. Another program would "load" that file to have access to the lookup table. REBOL [ Title: "Testing shell" Purpose: {Creating a lookup table.} ] DATABASE-DATA: [ [12345 "R" 300000 250000] [12346 "R" 300100 250100] [12347 "R" 300200 250200] ] LOOKUPTABLE-ID: %lookuptable.txt LOOKUPTABLE: [] foreach ROW DATABASE-DATA [ append LOOKUPTABLE ROW/1 LOOKUPBLOCK: copy [] append LOOKUPBLOCK ROW/2 append LOOKUPBLOCK ROW/3 append LOOKUPBLOCK ROW/4 append/only LOOKUPTABLE LOOKUPBLOCK ] save LOOKUPTABLE-ID LOOKUPTABLE print "Done." halt The above script will produce a text file that looks like this: 12345 ["R" 300000 250000] 12346 ["R" 300100 250100] 12347 ["R" 300200 250200] Note thay the key values are the five-digit numbers, and when you use the "select" function to look up one of those keys, you will get back the block following the key value. You then would refer to the items in the block with the "first," "second," etc. functions, or with the path notation of (block name)/n notation. ===Lookup table creation function Creating tables is done so often, and so often from SQL queries, that we have a function to turn the result of a query into a lookup table. To make this work, you have to be sure that the first column of the result set is the lookup key to the table. Then you can feed that result set to this function. REBOL [ Title: "Result-set to lookup table" Purpose: {Given an SQL result set, which comes in the form of a block of blocks, generate a lookup table where the key is the first item of a row and the attribute for the key is a block containing the remaining items from the row.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a specialized function for a specific project. It starts with ] ;; [ the result set of an SQL query, which is a block of blocks, where each ] ;; [ sub-block is a row of the result set. It transforms that data into a ] ;; [ lookup table where the key to the table is the first item of a row, ] ;; [ and the attribute of the key is a block containing all the remaining ] ;; [ items in the row. ] ;; [---------------------------------------------------------------------------] LOOKUP-TABLE-OF-RESULT-SET: func [ ROWBLOCK /local LOOKUPTABLE ATTRBLK ROWLGH ROWSUB ] [ LOOKUPTABLE: copy [] foreach ROW ROWBLOCK [ ROWLGH: length? ROW append LOOKUPTABLE first ROW ROWSUB: 2 ATTRBLK: copy [] loop (ROWLGH - 1) [ append ATTRBLK pick ROW ROWSUB ROWSUB: ROWSUB + 1 ] append/only LOOKUPTABLE ATTRBLK ] return LOOKUPTABLE ] ;;Uncomment to test ;TBL1: LOOKUP-TABLE-OF-RESULT-SET [ ; ["AAAA1" "BBBB1" "CCCC1"] ; ["AAAA2" "BBBB2" "CCCC2"] ; ["AAAA3" "BBBB3" "CCCC3"] ; ["AAAA4" "BBBB4" "CCCC4"] ; ["AAAA5" "BBBB5" "CCCC5"] ;] ;probe TBL1 ;halt ===Lookup file creation function As a variant of the function just shown, this function allows for a mulit-part key, and will save the lookup table to a file so it can be brought into another program with the "load" function. Documentation in the code. REBOL [ Title: "Result-set to lookup table" Purpose: {Given an SQL result set, which comes in the form of a block of blocks, generate a lookup table and put it into a file so it can be loaded by another program. Make the file somewhat nice-looking so it can be scanned visually with a text editor.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a specialized function for a specific project. It starts with ] ;; [ the result set of an SQL query, which is a block of blocks, where each ] ;; [ sub-block is a row of the result set. It transforms that data into a ] ;; [ lookup table. The key to the table is formed by combining one or ] ;; [ more of the columns in a row. Which columns to use is specified in ] ;; [ another block passed to the function, a block that contains one or more ] ;; [ field numbers from the row. The function will create a lookup key by ] ;; [ taking the specified fields and concatenating them. ] ;; [ For example, if the result set look like this: ] ;; [ [ ] ;; [ [dataname11 dataname12 dataname13 dataname14...] ] ;; [ [dataname21 dataname22 dataname23 dataname24...] ] ;; [ ... ] ;; [ ] ] ;; [ and the block of field postions looked like this: ] ;; [ [1 3] ] ;; [ then the resulting table would look like this: ] ;; [ [ ] ;; [ dataname11-dataname13 [dataname11 dataname12 dataname13 dataname14...]] ;; [ dataname21-dataname23 [dataname21 dataname22 dataname23 dataname24...]] ;; [ ... ] ;; [ ] ] ;; [ and one would look up an item in the table with the "select" function ] ;; [ using dataname111dataname13, etc., as a key. ] ;; [ An additional argument to the function is a file name, because the ] ;; [ resulting table will be written to a file with that name. ] ;; [ As a final feature, the lookup table will be written to disk with one ] ;; [ entry per line of text, so it can be scanned visually. ] ;; [ ] ;; [ The expected use of this file is that it will be read by some other ] ;; [ program using the "load" function, which will bring it in as a block ] ;; [ that is compatible with the "select" function. ] ;; [---------------------------------------------------------------------------] LOOKUP-FILE-OF-RESULT-SET: func [ FILEID KEYBLOCK ROWBLOCK /local LOOKUPTABLE TEMPKEY KEYLGH KEYCNT ATTRBLK LINELIST ] [ LOOKUPTABLE: copy [] foreach ROW ROWBLOCK [ ROWLGH: length? ROW TEMPKEY: copy "" KEYLGH: length? KEYBLOCK KEYCNT: 0 foreach KEYNUM KEYBLOCK [ KEYCNT: KEYCNT + 1 append TEMPKEY pick ROW KEYNUM if lesser? KEYCNT KEYLGH [ append TEMPKEY "-" ] ] append LOOKUPTABLE TEMPKEY ATTRBLK: copy [] foreach ITEM ROW [ append ATTRBLK ITEM ] append/only LOOKUPTABLE ATTRBLK ] LINELIST: copy "" foreach [KEY VAL] LOOKUPTABLE [ append LINELIST rejoin [ mold KEY " " mold VAL newline ] ] write FILEID LINELIST ] ;;Uncomment to test ;LOOKUP-FILE-OF-RESULT-SET %lookupfile.txt [1 2] [ ; ["AAAA1" "BBBB1" "CCCC1" "DDDD1"] ; ["AAAA2" "BBBB2" "CCCC2" "DDDD2"] ; ["AAAA3" "BBBB3" "CCCC3" "DDDD3"] ; ["AAAA4" "BBBB4" "CCCC4" "DDDD4"] ; ["AAAA5" "BBBB5" "CCCC5" "DDDD5"] ;] ;TBL: load %lookupfile.txt ;print ["TBL is type" type? TBL] ;print ["First TBL is" mold TBL/1] ;print ["Second TBL is" mold TBL/2] ;print ["Value for AAAA4-BBBB4 is" mold select TBL "AAAA4-BBBB4"] ;halt ===Multi-block lookup table Here is another version of the lookup table issue. In this situation, we need a lookup table where the thing you look up is a block that contains sub-blocks. In the original use of this application, the key to the table was a property identifier, and the thing being looked up was a block of one or more garages, and for each garage there were several relevant data items. REBOL [ Title: "Multi-block lookup table" Purpose: {Provide an object that is a lookup table that has a single key value and a block of attributes, but each attribute is itself another block. Originally written to make a table of properties with multiple detached garages.} ] ;; [---------------------------------------------------------------------------] ;; [ This module provides an object for a particular type of lookup table. ] ;; [ The table has one key value, and a block of attributes. The block of ] ;; [ attributes is a block of blocks. Something like this: ] ;; [ ] ;; [ key1 [ [attr-1-1-1 attr-1-1-2 ...] [attr-1-2-1 attr-1-2-2 ...] ... ] ] ;; [ key2 [ [attr-2-1-1 attr-2-1-2 ...] [attr-2-2-1 attr-2-2-2 ...] ... ] ] ;; [ key3 [ [attr-3-1-1 attr-3-1-2 ...] [attr-3-2-1 attr-3-2-2 ...] ... ] ] ;; [ ... ] ;; [ ] ;; [ Functions are provided for adding new keys, adding new attribute ] ;; [ sub-blocks to existing attribute blocks. ] ;; [ ] ;; [ Adding items. ] ;; [ When we add an item, we would like to have a key, and one of the ] ;; [ sub-blocks, and get those into the table. In this situation, the key ] ;; [ might not be in the table at all, or it might be in there from a ] ;; [ previous addition. If it is not there at all, we would want to add ] ;; [ it with an attribute containing the given sub-block. If it is there ] ;; [ from a previous insertion, we would want to find the attribute block ] ;; [ for the key and add the sub-block to the existing attribute block. ] ;; [ ] ;; [ Searching for items. ] ;; [ Because of the power of REBOL, it is not necessary to write a ] ;; [ search function. The caller can use the existing "select" ] ;; [ function to return the attribute block for a given key. ] ;; [ ] ;; [ Saving and loading. ] ;; [ The expected use of this module is to create a lookup table and then ] ;; [ save it to disk for use by some other program. That other program ] ;; [ would use this module to load the file for lookups. ] ;; [---------------------------------------------------------------------------] MBLT: make object! [ FILE-ID: %MBLT.txt TBL: [] ;; The whole table REC: [] ;; Attribute block for one key ;; Add an item. ;; Call the function with a key value and a sub-block ;; to be added to the attribute block for the key. ADD-ITEM: func [ KEY BLK /local INSERTPOINT ] [ TBL: head TBL either INSERTPOINT: find TBL KEY [ INSERTPOINT: next INSERTPOINT REC: first INSERTPOINT append/only REC BLK change/only INSERTPOINT REC ] [ append TBL KEY REC: copy [] append/only REC BLK append/only TBL REC ] TBL: head TBL ] ;; Save the table to a file for later loading. SAVE-TBL: does [ save FILE-ID TBL ] ;; Load a saved table. LOAD-TBL: does [ TBL: copy [] TBL: load FILE-ID ] ] ;;Uncomment to test ;MBLT/ADD-ITEM 1 ["1-1-1" "1-1-2"] ;MBLT/ADD-ITEM 2 ["2-1-1" "2-1-2"] ;MBLT/ADD-ITEM 3 ["3-1-1" "3-1-2"] ;MBLT/ADD-ITEM 4 ["4-1-1" "4-1-2"] ;MBLT/ADD-ITEM 2 ["2-2-1" "2-2-2"] ;MBLT/ADD-ITEM 4 ["4-2-1" "4-2-2"] ;MBLT/ADD-ITEM 5 ["5-1-1" "5-1-2"] ;MBLT/ADD-ITEM 2 ["2-3-1" "2-3-2"] ;print "TBL after a few additions:" ;foreach [KEYVAL ATTRBLK] MBLT/TBL [ ; print [KEYVAL ":" mold ATTRBLK] ;] ;print "--------------------------" ;print "Find a few:" ;print ["5:" mold select MBLT/TBL 5] ;print ["2:" mold select MBLT/TBL 2] ;print ["6:" mold select MBLT/TBL 6] ;halt ===Multi-category description table Here is yet another lookup table situation. It seems they never end. In this case there was a need for descriptions of codes. The codes were in several categories like a category for wind direction, and then several values for wind direction. We wanted (as an exercise mainly) to put all those codes and descriptions into one structure, and then look up a description based on a category and a code. The script below has functions for doing that, and some documentation. REBOL [ Title: "Multi-Category Description Table" Purpose: {An object for create a description lookup table that can combine several tables into one, with the tables identified by a category code.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a module to address a situation that comes up in database work. ] ;; [ If a database has various codes that represent things, it is nice to ] ;; [ provide descriptions of those codes in anything produced for human use. ] ;; [ If the actual code is the description, that can use up space in the ] ;; [ database, and the description never can change unless one wants to go ] ;; [ through the entire databse and change any descriptions that already are ] ;; [ in there. So it is customary to use codes to represent things, and to ] ;; [ put the human-readable meaning of the codes in another table. ] ;; [ If a database has many codes, that can result in many description ] ;; [ tables, OR, one can find a way to put all such codes and their ] ;; [ descriptions into one big table. This module is a way to do that. ] ;; [ ] ;; [ The end result of this will be a bunch of description tables, each ] ;; [ consisting of a bunch of codes with a description for each code. ] ;; [ Each table will be identified by a category code. ] ;; [ So, to find a description for some code, you have to find the table it ] ;; [ is in by supplying the category code, and also the code for which ] ;; [ you want the description. This will be implemented in a big block ] ;; [ that will look like this: ] ;; [ ] ;; [ [ ] ;; [ category-1 [code-1-1 desc-1-1 code-1-2 desc-1-2 ...] ] ;; [ category-2 [code-2-1 desc-2-1 code-2-2 desc-2-2 ...] ] ;; [ category-3 [code-3-1 desc-3-1 code-3-2 desc-3-2 ...] ] ;; [ ] ] ;; [ ] ;; [ With a structure like this, if we want to find the descripion for a ] ;; [ certain code in a certain category, we just have to "select" on the ] ;; [ category to get the table, and then select code to get the description. ] ;; [ This module provides a function to do that. ] ;; [ ] ;; [ Also, we have to build that multi-category table in the first place. ] ;; [ A function is provided so you can supply a caegory, a code, and a ] ;; [ description and they will be put into the table. ] ;; [ In case you can get your table data into a block of blocks, perhaps ] ;; [ as the result of an SQL query, a function is provided to load the ] ;; [ table from that direction. ] ;; [ ] ;; [ More specifically: ] ;; [ ] ;; [ LOAD-ENTRY category code description ] ;; [ This function is called repeatedly to load codes into the table. ] ;; [ If you want to save the final table and have it look nice, you could ] ;; [ provide the items in category-code order, but it is not necessary. ] ;; [ It should not matter what types of data you use for the category, ] ;; [ code, and description, but usually these would be strings. ] ;; [ ] ;; [ LOAD-RESULTSET resultset ] ;; [ This function is called with all the table data in a block of blocks, ] ;; [ where each sub-block contains a category, a code, and a description, ] ;; [ all of them strings. The function will call LOAD-ENTRY repeatedly ] ;; [ for all the sub-blocks in the outer block. ] ;; [ ] ;; [ GET-DESCRIPTION category code ] ;; [ This function returns the description string for the code supplied. ] ;; [ ] ;; [ SAVE-TABLE file-id ] ;; [ This function saves a finished table to a text file. ] ;; [ ] ;; [ LOAD-TABLE file-id ] ;; [ This function loads a table previously saved with the SAVE-TABLE ] ;; [ function. ] ;; [ ] ;; [ And finally, all this is packaged into an object so you could have ] ;; [ several such table in your program, although the purpose of this ] ;; [ object in the first place is so that you don't need more than one ] ;; [ table. ] ;; [---------------------------------------------------------------------------] MCDT: make object! [ DESCRIPTIONS: [] LOAD-ENTRY: func [ CATEGORY CODE DESCRIPTION /local LOC BLK ] [ LOC: head DESCRIPTIONS LOC: find DESCRIPTIONS CATEGORY either LOC [ BLK: first next LOC ;; a reference, not a copy append BLK CODE append BLK DESCRIPTION ] [ BLK: copy [] append BLK CODE append BLK DESCRIPTION append DESCRIPTIONS CATEGORY append/only DESCRIPTIONS BLK ] ] LOAD-RESULTSET: func [ RESULTSET ] [ DESCRIPTIONS: copy [] foreach SUBBLOCK RESULTSET [ LOAD-ENTRY SUBBLOCK/1 SUBBLOCK/2 SUBBLOCK/3 ] ] GET-DESCRIPTION: func [ CATEGORY CODE ] [ either TBL: select DESCRIPTIONS CATEGORY [ return SELECT TBL CODE ] [ return none ] ] SAVE-TABLE: func [ FILE-ID ] [ ;; save FILE-ID DESCRIPTIONS ;; Instead, make it look nicer... if exists? FILE-ID [ delete FILE-ID ] foreach [CATEGORY TABLE] DESCRIPTIONS [ write/append FILE-ID rejoin [ mold CATEGORY " [" newline ] foreach [CODE DESC] TABLE [ write/append FILE-ID rejoin [ " " mold CODE " " mold DESC newline ] ] write/append FILE-ID rejoin [ "]" newline ] ] ] LOAD-TABLE: func [ FILE-ID ] [ DESCRIPTIONS: copy [] DESCRIPTIONS: load FILE-ID ] ] ;;Uncomment to test ;MCDT/LOAD-ENTRY "WIND-DIR" "1" "North" ;MCDT/LOAD-ENTRY "WIND-DIR" "2" "Northeast" ;MCDT/LOAD-ENTRY "WIND-DIR" "3" "East" ;MCDT/LOAD-ENTRY "WIND-DIR" "4" "Southeast" ;MCDT/LOAD-ENTRY "WIND-DIR" "5" "South" ;MCDT/LOAD-ENTRY "WIND-DIR" "6" "Southwest" ;MCDT/LOAD-ENTRY "WIND-DIR" "7" "West" ;MCDT/LOAD-ENTRY "WIND-DIR" "8" "Northwest" ;MCDT/LOAD-ENTRY "WIND-DIR" "9" "Shifting winds" ;MCDT/LOAD-ENTRY "WIND-DIR" "N" "None/Calm" ;MCDT/LOAD-ENTRY "WIND-DIR" "U" "Undetermined" ;MCDT/LOAD-ENTRY "TAKEN" "0" "Taken to other" ;MCDT/LOAD-ENTRY "TAKEN" "1" "Hospital" ;MCDT/LOAD-ENTRY "TAKEN" "2" "Doctor's office" ;MCDT/LOAD-ENTRY "TAKEN" "3" "Morgue or funeral home" ;MCDT/LOAD-ENTRY "TAKEN" "4" "Residence" ;MCDT/LOAD-ENTRY "TAKEN" "5" "Station or quarters" ;MCDT/LOAD-ENTRY "TAKEN" "6" "Not transported" ;MCDT/LOAD-ENTRY "ACENGINE" "1" "Jet" ;MCDT/LOAD-ENTRY "ACENGINE" "2" "Turbo Prop" ;MCDT/LOAD-ENTRY "ACENGINE" "3" "Propeller" ;MCDT/LOAD-ENTRY "ACENGINE" "4" "None (Glider)" ;foreach [CATEGORY TABLE] MCDT/DESCRIPTIONS [ ; print [CATEGORY mold TABLE] ;] ;print "------------------------------------" ;print ["ACENGINE 2 = " MCDT/GET-DESCRIPTION "ACENGINE" "2"] ;print ["WIND-DIR 6 = " MCDT/GET-DESCRIPTION "WIND0DIR" "6"] ;; error ;print ["WIND-DIR U = " MCDT/GET-DESCRIPTION "WIND-DIR" "U"] ;print ["TAKEN 7 = " MCDT/GET-DESCRIPTION "TAKEN" "7"] ;print "------------------------------------" ;MCDT/SAVE-TABLE %tbltest.txt ;MCDT/LOAD-TABLE %tbltest.txt ;RESULTSET: [ ; ["ACFUEL" "1" "Jet Aviation Fuel"] ; ["ACFUEL" "2" "Aviation Gasoline"] ; ["ACFUEL" "3" "Other type of fuel"] ; ["PAT_STAT" "1" "Improved"] ; ["PAT_STAT" "2" "Remained Same"] ; ["PAT_STAT" "3" "Worsened"] ;] ;MCDT/LOAD-RESULTSET RESULTSET ;foreach [CATEGORY TABLE] MCDT/DESCRIPTIONS [ ; print [CATEGORY mold TABLE] ;] ;halt ===Substring to position What is a programming language without a good substring function? Actually, REBOL does not need one because other functions do the job, but as an exercise it might be fun to write one anyway. That was done early in REBOL's history and posted on the rebol.org web site, and is shown below. In this version of a substring function, the function returns a substring from a given position up through another given position. An "ending position" of -1 goes to the end of the string and this feature requires a bit of extra coding. REBOL [ Title: "Testing shell" Purpose: {Substring function.} ] GLB-SUBSTRING: func [ "Return a substring from the start position to the end position" INPUT-STRING [series!] "Full input string" START-POS [number!] "Starting position of substring" END-POS [number!] "Ending position of substring" ] [ if END-POS = -1 [END-POS: length? INPUT-STRING] return skip (copy/part INPUT-STRING END-POS) (START-POS - 1) ] TEST-STRING: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" print GLB-SUBSTRING TEST-STRING 6 6 print GLB-SUBSTRING TEST-STRING 10 20 print GLB-SUBSTRING TEST-STRING 21 -1 print "Done." halt ===Substring for length A more classic substring function seems to be to obtain a substring from a given position for a given length. Here is where other REBOL functions can handle that without having an official "substring" function. With a starting position and a length, you can "skip" into the main string and the "copy" for the given number of characters, all in one line of code. REBOL [ Title: "Testing shell" Purpose: {Substring function.} ] TEST-STRING: "ABCDEFGHIJKLMNOPQRSTUVWXYZ" print copy/part skip TEST-STRING 5 6 print "Done." halt ===Control break In the world of batch processing, a common operation is to read through a file of data that has been sorted by some key value, and do something with all the records that have the same key value. Probably that would be to add up some numbers. The problem is how to detect when that key value changes, and how to set up things to move on to the next key value. In the sample below, we start by saving the key value of the first record, in a holding area. We are going to compare the key value of every record to the value in the holding area, and we don't want to detect a change on the very first record. Then we loop through the data and for each record we compare the key value to the holding area. If they are the same, we just do whatever it we want to do for all records for the same key, which in this case is to add up a number on each record. We want a total for each key value. When we get a record that has a different key value, we want to add our total for the previous key value to a grand total, and then move the new key value to the holding area. When we get to the very end, there is not going to be a new key value coming in, so we have to do our control break processing one more time for the key value we were processing up to the end. This is not the only way of course. You could NOT save the key value of the first record in a holding area, but then the first record would cause a control break, but it would not be a real one, so you would have to program around that. Everythig is choices and trade-offs. REBOL [ Title: "Testing shell" Purpose: {Control break.} ] DATA: [ ["AAA" 1] ["AAA" 2] ["AAA" 3] ["BBB" 4] ["BBB" 5] ["BBB" 6] ["CCC" 7] ["CCC" 8] ["CCC" 9] ] CURRENT-KEY: "" CURRENT-TOTAL: 0 GRAND-TOTAL: 0 CURRENT-KEY: DATA/1/1 foreach ROW DATA [ if not-equal? ROW/1 CURRENT-KEY [ print ["Total for " CURRENT-KEY " = " CURRENT-TOTAL] GRAND-TOTAL: GRAND-TOTAL + CURRENT-TOTAL CURRENT-KEY: ROW/1 CURRENT-TOTAL: 0 ] CURRENT-TOTAL: CURRENT-TOTAL + ROW/2 ] print ["Total for " CURRENT-KEY " = " CURRENT-TOTAL] GRAND-TOTAL: GRAND-TOTAL + CURRENT-TOTAL print ["Grand total = " GRAND-TOTAL] print "Done." halt ===Write CSV file A CSV file is almost a standard way of moving data around, so it is likely you will have to make one at some point. There are several ideas floating around, but at the core is appending data items, and commas, to a string and then writing that string to disk. REBOL [ Title: "Testing shell" Purpose: {Write CSV file.} ] CSVFILE-ID: %test.csv CSVFILE-DATA: "" CSVFILE-HEADER: rejoin [ "NAME," "ADDRESS," "CITY" newline ] append CSVFILE-DATA CSVFILE-HEADER append CSVFILE-DATA rejoin [ "Steven White" "," "1800 W Old Shakopee Rd" "," "Bloomington" newline ] write CSVFILE-ID CSVFILE-DATA editor CSVFILE-ID ===CSV module This code sample is not really a pattern, but it shows a concept worth noting. When you do the same things ovef and over again, it does not take long to realize that there must be a better way. One better way is to try to make a generalized version of that thing you are doing and then use that like a layer of abstraction or a black box. The sample below is code for reading a CSV file and taking it apart. The "pattern" would be parsing the data on the commas into individual data items. But that "pattern" is not something you would want to code fresh every time you had to take apart a file. Instead, it would be nice to encapsulate that pattern of parsing on commas into some sort of function, and then use that function. The sample below does that. REBOL [ Title: "Make a csv file easily readable" ] ;; [---------------------------------------------------------------------------] ;; [ This is a module for making it easy to read values in a csv file by ] ;; [ creating words and values from a csv file. ] ;; [ to be more specific, we start with a csv file that has a line of ] ;; [ headings as the first line. Each word in the line of headings ] ;; [ is going to be the name of the corresponding item in each following ] ;; [ record of the csv file. For example: ] ;; [ name,address,birthdate ] ;; [ "John Smith","1800 W Old Shakopee Rd",01-JAN-2000 ] ;; [ "Jane Smith","2100 1ST Ave",01-FEB-1995 ] ;; [ "Jared Smith",3500 2ND St",01-MAR-1998 ] ;; [ The above text file is like a little data file. ] ;; [ We will "open" the file by performing some function, and then we ] ;; [ will "read" "records" from the file until the end. ] ;; [ Every time we read a record, the words 'name, 'address, 'birthdate ] ;; [ will have, as values, the values from the record we just read. ] ;; [ In other words, when we "read" the first record, the following ] ;; [ situation will exist: ] ;; [ name = "John Smith" ] ;; [ address = "1800 W Old Shakopee Rd" ] ;; [ birtdhdate = 01-JAN-2000 ] ;; [ Then, when read the next record, those same words of 'name, 'address, ] ;; [ and 'birthdate will refer to the values from the second record. ] ;; [ And so on to the end of the file. ] ;; [ Then, when we try to read beyond the end, we will get an indicator ] ;; [ that we have reached the end of the file. ] ;; [ ] ;; [ As an additional service, we want to provide the ability to rewrite ] ;; [ a csv file after we make changes. So, when we "open" a file, we also ] ;; [ will copy the headings to an output area just in case we want to ] ;; [ rewrite the file. Then, we will provide a "write" procedure that will ] ;; [ make a csv record out of the current data and append it to the output ] ;; [ area. A "close" procedure will write the output area to disk. ] ;; [---------------------------------------------------------------------------] ;; [---------------------------------------------------------------------------] ;; [ These are the data items used to get the csv file into memeory, ] ;; [ pick off the first record of column headings, and so on. ] ;; [---------------------------------------------------------------------------] CSV-FILE: none ;; Name of the file, will come from caller CSV-LINES: none ;; The entire contents of the file CSV-HEADINGS: none ;; Words from the first line as strings CSV-WORDS: none ;; The words from the first line as words CSV-WORDCOUNT: 0 ;; Number of heading words CSV-RECORD: none ;; The current data record, in the CSV-READ procedure CSV-VALUES: none ;; The parsed values from a single data line CSV-EOF: false ;; End-of-file flag when we "read" beyond last "record" CSV-LENGTH: 0 ;; Number of lines in the file, including heading line CSV-COUNTER: 0 ;; Record counter as we move through the file CSV-VAL-COUNTER: 0 ;; For stepping through values in one record CSV-OUTPUT-LINES: none ;; Copy of the input file, with modifications CSV-OUTPUT-FILE: none ;; Name of output file CSV-OUTPUT-REC: none ;; One output record CSV-COMMACOUNT: 0 ;; Used to NOT put comma after last field of record CSV-IN-FIELD: false ;; Used in comma-replacement operation CSV-COMMA-MARKER: "%C%" ;; Will replace comma temporarily before parsing ;; [---------------------------------------------------------------------------] ;; [ We will need a function to clear the above items so that a calling ] ;; [ program can read more than one file. ] ;; [---------------------------------------------------------------------------] CSV-CLEAR-WS: does [ CSV-FILE: none CSV-LINES: none CSV-HEADINGS: none CSV-WORDS: none CSV-WORDCOUNT: 0 CSV-RECORD: none CSV-VALUES: none CSV-EOF: false CSV-LENGTH: 0 CSV-COUNTER: 0 CSV-VAL-COUNTER: 0 CSV-OUTPUT-LINES: copy "" CSV-OUTPUT-FILE: none CSV-OUTPUT-REC: none CSV-COMMACOUNT: 0 CSV-IN-FIELD: false ] ;; [---------------------------------------------------------------------------] ;; [ Procedure to "open" the file. What does that mean? ] ;; [ Read the entire file into memory. Parse the first line into a block ] ;; [ of words. Make a note of the number of lines in the file. ] ;; [ Set up a counter so we can pick our way through the file and stop ] ;; [ when we reach the last record. ] ;; [ Since this module is designed for use inside another program, ] ;; [ this function normally will be called with a file name as argument. ] ;; [---------------------------------------------------------------------------] CSV-OPEN: func [ FILE-TO-OPEN ] [ CSV-CLEAR-WS CSV-FILE: FILE-TO-OPEN CSV-LINES: read/lines CSV-FILE CSV-LENGTH: length? CSV-LINES append CSV-OUTPUT-LINES first CSV-LINES ;; preparation for possible writing append CSV-OUTPUT-LINES newline CSV-HEADINGS: parse/all first CSV-LINES "," CSV-WORDS: copy [] foreach CSV-HEADING CSV-HEADINGS [ if not-equal? "" trim CSV-HEADING [ append CSV-WORDS to-word trim/all/with CSV-HEADING " #" CSV-WORDCOUNT: CSV-WORDCOUNT + 1 ] ] CSV-COUNTER: 1 CSV-EOF: false return CSV-EOF ] ;; [---------------------------------------------------------------------------] ;; [ The (optional) procedure to "close" the file. What does that mean? ] ;; [ To mimic the idea of opening a file I-O, meaning that we can rewrite ] ;; [ a record after we have read it, we can write the data we have read ] ;; [ into an output area, which will be a copy of the input file (or at ] ;; [ least those records we have chosen to write). The "close" procedure ] ;; [ will write that file to disk. You have to specify a file name, ] ;; [ which may be the same (which will be like "saving" the file) or may ] ;; [ be different (which will be like "saving as." ] ;; [---------------------------------------------------------------------------] CSV-CLOSE: func [ FILE-TO-CLOSE ] [ CSV-OUTPUT-FILE: FILE-TO-CLOSE write/lines CSV-OUTPUT-FILE CSV-OUTPUT-LINES ] ;; [---------------------------------------------------------------------------] ;; [ Procedure to "read" the file. What does this mean? ] ;; [ Obtain the next line. This is determined by "picking" based on the ] ;; [ record counter. If the counter becomes bigger than the file size, ] ;; [ that means we have reached the end of the file. ] ;; [ Parse the line into a block of strings. ] ;; [ For each word in the block of column headings, set that word to the ] ;; [ corresponding item parsed from the data. ] ;; [ We have to be sure to return the value of CSV-EOF so any calling ] ;; [ procedure can use CSV-EOF to decide when to quit processing. ] ;; [ There is a special little thing we do with each line before parsing it. ] ;; [ It is possible that the data could contain commas. It is customary ] ;; [ that in such situations the field is enclosed in quotes. ] ;; [ We will assume that our data follows this custom, and take steps to ] ;; [ to handle the possibility of commas in the data. ] ;; [ Before we parse a line on commas, we will go through the line one ] ;; [ character at a time. When we hit the first quote, we will assume that ] ;; [ we are entering a fields. From then on, we will replace commas with ] ;; [ special place holders. When we hit the next quote, we will assume ] ;; [ we have left the field and we will stop replacing commas. ] ;; [ The next quote takes us into a field, the next one out, next in, etc. ] ;; [ When we are done replacing embedded commas, we parse the line on ] ;; [ commas. Then, as we load each field, for each string field we check ] ;; [ for our place holder and replace it with a comma. ] ;; [---------------------------------------------------------------------------] CSV-REPLACE-EMBEDDED-COMMAS: does [ CSV-IN-FIELD: false foreach CHARACTER CSV-RECORD [ either equal? CHARACTER {"} [ either CSV-IN-FIELD [ CSV-IN-FIELD: false ] [ CSV-IN-FIELD: true ] ] [ if CSV-IN-FIELD [ replace CHARACTER "," CSV-COMMA-MARKER ] ] ] ] CSV-READ: does [ CSV-COUNTER: CSV-COUNTER + 1 if (CSV-COUNTER > CSV-LENGTH) [ CSV-EOF: true return CSV-EOF ] CSV-RECORD: pick CSV-LINES CSV-COUNTER CSV-REPLACE-EMBEDDED-COMMAS CSV-VALUES: parse/all CSV-RECORD "," CSV-VAL-COUNTER: 0 foreach CSV-WORD CSV-WORDS [ CSV-VAL-COUNTER: CSV-VAL-COUNTER + 1 TEMP-VAL: pick CSV-VALUES CSV-VAL-COUNTER if equal? string! type? TEMP-VAL [ replace/all TEMP-VAL CSV-COMMA-MARKER "," ] either TEMP-VAL [ set CSV-WORD trim TEMP-VAL ] [ set CSV-WORD TEMP-VAL ] ] return CSV-EOF ] ;; [---------------------------------------------------------------------------] ;; [ Procedure to "write" the file. What does this mean? ] ;; [ We are not really writing the file. We are formatting the current data ] ;; [ into a csv record and appending it to an output area. ] ;; [ If we do a "write" procedure for every "read" procedure, we will, ] ;; [ in effect, copy the input file. If we read the input, and then maybe ] ;; [ or maybe not write to the output file, we will, in effect, filter the ] ;; [ input file. This is not quite like the COBOL operation of opening ] ;; [ a file for input and output. In COBOL, you could read a record, and ] ;; [ then maybe or maybe not rewrite it, and at the end, you would have the ] ;; [ same number of records in the file and maybe some of them would be ] ;; [ altered. Here, if you don't write the file, you don't get a record ] ;; [ into the file, and when you close it you either write over the input ] ;; [ file if you use the same name, or make a copy if you close under a ] ;; [ different name. ] ;; [ Note that performing this procedure makes no sense if you don't first ] ;; [ perform CSV-READ to read a record. ] ;; [---------------------------------------------------------------------------] CSV-WRITE: does [ CSV-OUTPUT-REC: copy "" CSV-COMMACOUNT: 0 foreach CSV-WORD CSV-WORDS [ append CSV-OUTPUT-REC mold get CSV-WORD ;; strings might contain commas CSV-COMMACOUNT: CSV-COMMACOUNT + 1 if (CSV-COMMACOUNT < CSV-WORDCOUNT) [ append CSV-OUTPUT-REC "," ] ] append CSV-OUTPUT-LINES CSV-OUTPUT-REC append CSV-OUTPUT-LINES newline ] ;; [---------------------------------------------------------------------------] ;; [ These are helper functions for reporting selected columns to ] ;; [ to an html file. ] ;; [---------------------------------------------------------------------------] ;; [---------------------------------------------------------------------------] ;; [ This function accepts a block of words, which usually are the column ] ;; [ names from the file but need not be. It converts each word to a string ] ;; [ and emits the beginning of an html table with a row of table headers ] ;; [ consisting of the supplied words. ] ;; [---------------------------------------------------------------------------] CSV-REPORT-HTML: "" CSV-REPORT-HEAD: func [ CSV-REPORT-COL-NAMES ] [ CSV-REPORT-HTML: copy "" append CSV-REPORT-HTML rejoin [ {} newline "" newline ] foreach CSV-REPORT-COL CSV-REPORT-COL-NAMES [ append CSV-REPORT-HTML rejoin [ "" newline ] ] append CSV-REPORT-HTML rejoin [ "" newline ] ] ;; [---------------------------------------------------------------------------] ;; [ This function must be performed to close the table that we use for ] ;; [ the report. Note that the html string we are creating is only a table ] ;; [ and not a full html page. This is by design. ] ;; [---------------------------------------------------------------------------] CSV-REPORT-FOOT: does [ append CSV-REPORT-HTML rejoin [ "
" to-string CSV-REPORT-COL "
" newline ] ] ;; [---------------------------------------------------------------------------] ;; [ This function accepts a block of words which MUST BE words from the file. ] ;; [ It puts the values of those words into td elements and appends them to ] ;; [ the html string. ] ;; [---------------------------------------------------------------------------] CSV-REPORT-LINE: func [ CSV-REPORT-COL-NAMES ] [ append CSV-REPORT-HTML rejoin [ "" newline ] foreach CSV-REPORT-COL CSV-REPORT-COL-NAMES [ append CSV-REPORT-HTML rejoin [ "" get CSV-REPORT-COL "" newline ] ] append CSV-REPORT-HTML rejoin [ "" newline ] ] ===CSV module demo With the above module for reading CSV files, we can make a "pattern" from that. Assuming the above module has been put into a file called csvfile.r, and we have a test CSV file called CSVdemo.csv that looks like this... NAME,ADDRESS,CITYSTATE "White, Steven",1800 W OLD SHAKOPEE RD,BLOOMINGTON MN "Johnson, John",1801 W OLD SHAKOPEE RD,BLOOMINGTON MN "Smith, Mister",1802 W OLD SHAKOPEE RD,BLOOMINGTON MN ...we can show a pattern of using the csvfile.r module that we could use for many CSV files. In this sample, we bring in the above module with the "do" function, "open" the file with the function provided, "read" the first record, and then process each record until we hit the end. REBOL [ Title: "Testing shell" Purpose: {CSV module demo.} ] do %csvfile.r CSV-OPEN %CSVdemo.csv CSV-READ until [ print [NAME ":" ADDRESS ":" CITYSTATE] CSV-READ ;; Returns true value at EOF ] print "Done." halt ===CSV extraction with Powershell It seems that there is not a way to use REBOL to get data out of a spreadsheet, but it is possible with Powershell, so if you can use a Powershell script as an intermediary, you can call that script. Here is an example. ################################################################################ # # This script seems to save a spreadsheet as a csv file. # # It is slightly generalized to get the name of the spreadsheet and the # name of the output file as parameters. # # Trial and error indicates that the file names specified as the input # parameters must be full path names. It appears that quotes around the file # names are optional. # ################################################################################ param ($XLS, $CSV) #write-host $XLS ## for debugging #write-host $CSV $saveascode=6 $spreadsheetfile=$XLS $csvfile=$CSV $spreadsheet=New-Object -comobject "Excel.Application" $workbook=$spreadsheet.workbooks.open($spreadsheetfile) $worksheet=$workbook.worksheets.item(1) $spreadsheet.displayalerts=$False $workbook.SaveAs($csvfile,$saveascode) $workbook.close() $spreadsheet.quit() if (ps excel) { kill -name excel} Here is a way to call the above script that works at least in some situations. ;; [---------------------------------------------------------------------------] ;; [ Build the command to run the powershell script that will extract ] ;; [ data out of the spreadsheet file and into the csv file. ] ;; [ And yes, even though XLS-FILE and CSV-FILE are file! datatypes, ] ;; [ it seems that the to-file function below is necessary. ] ;; [---------------------------------------------------------------------------] CMD-STRING: reduce [ " powershell -Command ExtractCSV.ps1 " to-file XLS-FILE " " to-file CSV-FILE ] call/wait CMD-STRING ===CSV to Excel with powershell On the subject of CSV files, it is possible to have a REBOL program produce a spreadsheet, but, it seems, not directly. Here is a way that has worked. Put the spreadsheet data into CSV files and then call a powershell script to do the dirty work. The has worked on Windows 10 with the "call/shell" function. The following example was created with some help from the internet and some trial and error. It loads not just one, but three CSV files into three tabs of a spreadsheet. The script was written to be used over and over again on CSV files created from some other application, and differentiated by a "batch ID" as part of the file name. That batch ID is passed to the script so that it can build the file names, thus giving it some generality. But first, here is a way the powershell script could be called. One would adjust the file path for one's own situation. ;; obtain the batch id from somewhere and name it WS-BATCH ... CMD-STRING: rejoin [ " powershell -Command PaymentRecovery.ps1 " {"} WS-BATCH {"} ] ... call/shell CMD-STRING And now here is the powershell script that would be called PaymentRecovery.ps1. ############################################################################### # This is a script developed by trial and error to load three CSV files # into three tabs of a single spreadsheet file. # This is a sanitized part of a project to recover some payments reports # from data produced by three SQL queries that put their results into # three CSV files. Parts of this script were borrowed from the internet. ############################################################################### param ($BATCHID) # Three csv files produced by three SQL queried $FILE1 = "I:\IS_Apps_MyReports\PaymentDetail-$BATCHID.csv" $FILE2 = "I:\IS_Apps_MyReports\PaymentDistribution-$BATCHID.csv" $FILE3 = "I:\IS_Apps_MyReports\PaymentPosting-$BATCHID.csv" # The final spreadsheet file we will create $OUTFILE = "I:\IS_Apps_MyReports\PaymentRecoveryReports-$BATCHID.xlsx" # Create a Excel Workspace $excel = New-Object -ComObject Excel.Application # make excel visible $excel.visible = $true # add a new blank worksheet $workbook = $excel.Workbooks.add() # Adding Sheets $sheet4 = $workbook.Sheets.add() $sheet4.name = "PaymentDetail" $sheet5 = $workbook.Sheets.add() $sheet5.name = "PaymentDistribution" $sheet6 = $workbook.Sheets.add() $sheet6.name = "PaymentPosting" # The default workbook has three sheets, remove them ($s1 = $workbook.sheets | where {$_.name -eq "Sheet1"}).delete() #Start row and column $r = 1 $c = 1 #Begin working through file 1 $file = (GC $FILE1) ForEach ($f in $file) { $arr = ($f).split(',') ForEach ($a in $arr) { $sheet4.Cells.Item($r,$c) = "$(($a).replace('"',''))" $c++ } $c = 1 $r++ } #Select all used cells $range = $sheet4.UsedRange #Autofit the columns $range.EntireColumn.Autofit() | out-null #Start row and column $r = 1 $c = 1 #Begin working through file 2 $file = (GC $FILE2) ForEach ($f in $file) { $arr = ($f).split(',') ForEach ($a in $arr) { $sheet5.Cells.Item($r,$c) = "$(($a).replace('"',''))" $c++ } $c = 1 $r++ } #Select all used cells $range = $sheet5.UsedRange #Autofit the columns $range.EntireColumn.Autofit() | out-null #Start row and column $r = 1 $c = 1 #Begin working through file 3 $file = (GC $FILE3) ForEach ($f in $file) { $arr = ($f).split(',') ForEach ($a in $arr) { $sheet6.Cells.Item($r,$c) = "$(($a).replace('"',''))" $c++ } $c = 1 $r++ } #Select all used cells $range = $sheet6.UsedRange #Autofit the columns $range.EntireColumn.Autofit() | out-null #Saving File $workbook.SaveAs($OUTFILE) #Close Excel #$excel.quit() ===Base 64 image Something that comes up a lot is embedding images in code. The way to accomplish that seems to be to encode it in base 64 encoding and then put the result into the source code The sample below does that, encapsulated into a function that you could save and use. REBOL [ Title: "Testing shell" Purpose: {Image string.} ] IMAGE-STRING: does [ system/options/binary-base: 64 IMAGESTRING-FILE: request-file/only if not IMAGESTRING-FILE [ alert "No file specified" exit ] IMAGESTRING-STRING: read/binary IMAGESTRING-FILE save clipboard:// IMAGESTRING-STRING alert "Hex representation of image is on the clipboard" ] IMAGE-STRING print "Done." halt ===Base 64 image in VID layout If you make a base-64 image as shown in the previous example, you can paste it into a script and put it into a VID layout as shown in this example. This example might not be the most efficient. If you look around on the internet, especially in Nick's documentation, you will see that you can combine functions for converting to string, compressing, uncompressing, converting to binary, and so on, to accomplish this same thing, perhaps more efficiently (that is, in a smaller size at the insignificant cost in more processing). Feel free to experiment. REBOL [ Title: "Testing skeleton" Purpose: {Show an embedded image.} ] system/options/binary-base: 64 DEMO-LOGO: load 64#{ iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAABmJLR0QA/wD/AP+g vaeTAAABzUlEQVRYhdXZzYrCMBAH8HHFJ9h3KgV7Ujyo9erNl/HmO3j1WfYBeigM 1GuhrcwexN1KTTMfiewOOYVCfvwDZZJMvgA+4bmyDE4nmM3gDdW2sN/D5dKfqwAA AWg40pTqmmJXXVOaDldHJ+sNMofJxwKg5ZKaJoqpaWixcK3rY0XKzJ0TmxVc5jM9 WPO5hxVwN0f37peVZYBlSXnul9kzY+REALTbYVkCIlLXRZexTdR1iAiISERxZRIT EfVY8WRC04AVQyY3vWKFlalMDlYomdbkZtllBtMoyyKzmXwsncxsYrCkshAmHosv SxJKEruJzeLLQpgkrCAynknIMsrYJjlLLZOYVCyFTGjSsu6y9Zpl2mykpjvrQ3nm vF5ZX1YVtK1mCXFazH/mz5B3jvJNlJpUMiFLZ5LLJCyLSShjs+wmiYzHYprynLbb IDIGS9SrBDoH+FiK/imEbJSl7unMMjfL2GfaZA5WkN7XIHvFCtSPW2QDVkCTQfbM Cm7SynqsSCaV7MGKapLLEBGwKKKbhDIsij97pfuGnPrFyIxxLx/WxJP9x8eVGDn1 y52ZmxXbNCpDgMmLZ87VCo5HmE415ztp3W5wOMD53J+rAL4B3kFQEgTgjAIAAAAA SUVORK5CYII= } view layout [ image DEMO-LOGO button "Quit" [quit] ] ===Compressing an embedded image Look at the previous two examples. In the first example, the image that will eventually be put on a window is brought in with the read/binary function and the saved on the clipboard. In the second example, what is pasted into the program did come from the code in the first example, so we assume that it is binary data. It is put into the DEMO-LOGO word with the "load" function which is the opposite of the "save" function. That means that what you "load" to make an image must be somthing that is binary. The code sample below was copied out of Nick's Big Book. http://business-programming.com/business_programming.html From the above examples we know that if we want to create an image we have to load something that is binary. From the REBOL function dictionary, we know that if we want to compress something, the "something" has to be a string. In the code sample below, the word "picture" refers to a compressed string that was created by reading a file in binary and converting it to a string, and the image was created by decompressing the "picture" string and converting it back to binary, and then "loading" it. Thank you Nick. alert "Select a picture from your hard drive:" system/options/binary-base: 64 editor picture: compress to-string read/binary to-file request-file/only view layout [image load (to-binary decompress picture)] ; This example embedded image was created with the script above: logo-pic: load to-binary decompress #{ 789C018A0375FC89504E470D0A1A0A0000000D49484452000000640000001808 020000008360CFB90000001374455874536F667477617265005245424F4C2F56 6965778FD916780000033249444154789CD599217402310C86F7CE6227B1481C 1637874362B1382C1687C4A15168240A89C5A2B058ECDEBE47DFFA429276DCEE 10FDCD582F97267FD33F2D7CF47ABDCF32D1ED76E7F3F9ED76FB4EE0743A8D46 A3B6A683A80FFE540562381C1E8FC7144D12DBEDB6951C3B9D4E91648DC7E34C 41B925465D349C14A2CA230BA65EA729E27C3E37CCB43CB228905A3525B1DBED 9A4CED93851C7C193088A0667C0D0603FB5640BFDFB7F648C0D0836B1C41C22E 11D7EBF57038F074BFDF534429BE2693891B4626CE1C59BC7CB95CDC99EEF7FB 66B349F922D65A4B4A8DE0D0B547B9DD85212B6B4CB4D3E994B055FEE8943566 30134626BBDA64052C974BD757A637B1DA2E599959A05EE61F4032D62C55EFBC 6EED01878954188DC80AE714C07126D24F91BBBE6265A129B3D96C2A4085BB64 459FEBF51A1B2692E5A9FA17A428B562EBE595A1F29650AD5C6B9525FD4621E0 A95D73491606F9046C94101A06178B4518E19122023655DA184B03ECA15BE98E 6D9D302E536E8D2C96A5FF0061458FEE9EAA045958720EDCFC82CF145A9E2C7C 52BC6CF0503B8C2B2200DAACD24698A4B710361E6421930E05A85E9484BE51B3 0885AE9727CB22A5591981B73D1AC6A58D2ABD5892DF46C5993DCFF25BC8828E 14538AACEB3390A43C59D890213B5D2AA3D2AC3C59ABD54ACE2E85C29E36DE42 162B8C0AC47F0942B512972CCCF0D91170ED6594ECC130288549ED44744DE52C 771381C571D5AFEDB14B2E79CB022F13C834A056049EFCE35C2A7449877A2B00 2D872635082FEA2D267D8BC047AD910D3875CE9247078A826259FC8234F264E1 9FAD4AAC52015465D973193B3755B611B417FB562A0C66C77EF7001F5463FD83 2CF20F83B2B8E0C22DAE760FA556B32AAF87B86A18C18259CFAA3567C250C7C3 1AE72CD95350531BD93FAE3B6CEADB33188174FCBBD77B7B7A0841DAB6C3EBEE F13DE8696B6455E222ADCE23F162ECF644064709A47AA8FD3632BFAD78EA5E92 D947500C3BB04CAD419F3D5B05580DC127118E3D2866CAFB8AC6CAFCEB68F895 56796455CF47AAD741F5B957D4D751245980BD569729B723D742A964558FFB4D EAB6A440BF6ACE54157EB028F7A730B695BDF749D05EA9C1B612C4CF0F396EDC 8E943F5C020000000049454E44AE426082CAEBA2D78A030000 } view layout [image logo-pic] ===Compressing a script Here is a little programming aid that will load the clipboard with a compressed script of your choosing. The idea behind it is that you then would paste the clipboard into your source code if you wanted to embed a script in your code. REBOL [ Title: "Script compressor" Purpose: {Ask for the name of a script, read it, compress it, mold it into a displayable format, and put it on the clipboard. This is a coding aid.} ] if not FILE-ID: request-file/only [ alert "No file requested." quit ] system/options/binary-base: 64 write clipboard:// mold compress read FILE-ID alert "Clipboard loaded." ===Compressing scripts into a package One thing you will see a bit of in the REBOL world is documentation that includes a big script, but the big script, instead of being included in the documentation in its "raw" form, is compressed so that you can copy out the compressed script, paste it into an editor, save it and, depending on exactly it is packaged, either decompress it or run it if it is presented as a runnable script. Here is a sample of how you can use to compress and package a script into another script, such that if you run that other script it will unpack and saved the compressed script. REBOL [ Title: "Script packager" Purpose: {Package up one or more script (text) files into a REBOL script that will unpack them.} ] PACKAGE-STRING: "" PACKAGE-HEADER: {REBOL [ Title: "Script unpacker" ] } PACKAGE-FOOTER: { alert "Done." } SCRIPT-HEADER-MODEL: { write %%OUTPUT-NAME%% decompress %%SCRIPT-STRING%% } SCRIPT-HEADER: "" if not FILE-LIST: request-file [ alert "No files selected" quit ] append PACKAGE-STRING PACKAGE-HEADER system/options/binary-base: 64 foreach NAME FILE-LIST [ SCRIPT-HEADER: copy SCRIPT-HEADER-MODEL replace SCRIPT-HEADER "%%OUTPUT-NAME%%" mold second split-path NAME replace SCRIPT-HEADER "%%SCRIPT-STRING%%" mold compress read NAME append PACKAGE-STRING SCRIPT-HEADER ] append PACKAGE-STRING PACKAGE-FOOTER write %package.r PACKAGE-STRING alert "Done." ===Base 64 IMG tag It is possible to hard-code an image into a web page, in contrast to linking to an image file. This can be done by encoding the image in base-64 encoding. The code below is a function you could include in a program to create such an image. REBOL [ Title: "Make an html img tag from an image file" Purpose: {Request an image file, read it, convert it to base 64, and put it into an img tag for embedding in a web page.} ] ;; [---------------------------------------------------------------------------] ;; [ It is possible to embed an image into an html document if the image ] ;; [ can be incoded as base 64, whatever that means. This function takes ] ;; [ a file name and a text description, reads the file, converts it to ] ;; [ base 64, and makes an html img tag. It uses the passed text description ] ;; [ as the "alt" attribute for the image. ] ;; [ The function does no checking about the existence of the image file. ] ;; [ That would more appropriately be done by the caller. ] ;; [---------------------------------------------------------------------------] IMGTAG: func [ FILENAME ALTDESC ] [ return rejoin [ {} ALTDESC {} ] ] ;;Uncomment to test, provide your own image called TestImage.png (or jpg). ;write %imgtagtest.html rejoin [ ;{ ;IMGTAG test ; ;

IMGTAG test

;} ;IMGTAG %TestImage.png "Elbow image" ;{ ; ;} ;] ;browse %imgtagtest.html ===Date and time stamps Fixed-format dates and times are useful for including in log files and file names. Once you have had to make date or time stamps a few times you will weep at the prospect of doing it again and will want to find a way to ease the pain. The way would be to make a function that could do that for you. Here is a sample that you could include in a program. REBOL [ Title: "Date and time 'to' functions" Purpose: {Some functions for formatting dates and time in useful ways.} ] ;; [---------------------------------------------------------------------------] ;; [ Some functions borrowed from or inspired by the REBOL cookook for ] ;; [ putting dates and times into useful formats. ] ;; [ The important feature of these functions is that for single-digit ] ;; [ items (January = 1) the function puts on a leading zero, so that the ] ;; [ resulting dates and times all are the same length. This is useful ] ;; [ in, for example, date and time stamps in file names. ] ;; [---------------------------------------------------------------------------] to-yyyymmdd: func [when /hyphens /slashes /local stamp add2] [ add2: func [num] [ ; always create 2 digit number num: form num if tail? next num [insert num "0"] append stamp num ] stamp: form when/year if hyphens [append stamp "-"] if slashes [append stamp "/"] add2 when/month if hyphens [append stamp "-"] if slashes [append stamp "/"] add2 when/day return stamp ] to-hhmmss: func [when /colons /local stamp add2] [ add2: func [num] [ ; always create 2 digit number num: form num if tail? next num [insert num "0"] append stamp num ] stamp: copy "" add2 when/hour if colons [append stamp ":"] add2 when/minute if colons [append stamp ":"] add2 to-integer when/second return stamp ] ;;Uncomment to test ;print to-yyyymmdd now/date ;print to-yyyymmdd/hyphens now/date ;print to-yyyymmdd/slashes now/date ;print to-hhmmss now/time ;print to-hhmmss/colons now/time ;halt ===Calling a Windows executable file The REBOL "call" function does not always seem to work, but here is an example of something that does work, the calling of a dot-exe file. In this case, voice.exe is a text-to-speech program downloaded from the internet. REBOL [ Title: "Testing shell" Purpose: {Calling Windows executable.} ] ANNOUNCE: func [ NAME ] [ CMD: copy "" CMD: rejoin [ "voice.exe " {"Welcome } NAME {"} ] call CMD ] ANNOUNCE "Steven" print "Done." halt ===CGI reading module This example is a complete module that can be used to get the input of a CGI form. The significance of this module is that at some point someone beat his head enough on the coding for CGI forms that he could not take it anymore, and wrote a module to do all that fussing. The next sample will show how the module might be used. For now, here is the CGI module as a background for the next "pattern." This example also shows how comments can be put in front of the REBOL header. TITLE CGI common procedures SUMMARY These are common procedure that can be used in CGI programs to make it easier to write them, without having to remember some of the technical details of CGI programs. DOCUMENTATION Include the module in your program with do %cgi.r If the module is not in the current directory, specify the full name either with a drive letter or a UNC name in the REBOL syntax. Usually, your program will be executed by the web server in response to a request from a web browser. Also usually, there will be data availble from some sort of HTML form. In the HTML form, the INPUT items will be identified by the "NAME" attribute. To get your hands on the data from the form, use this procedure: CGI-GET-INPUT This procedure detects the proper source of the input data (GET or POST) and reads the data, and then assembles it into an object. Each data item can be referenced using the "path" syntax of CGI-INPUT/data-name-1 where "data-name-1" is the name sepecified in the "NAME" attribute. After processing any input, your program will display some HTML output. There are two main ways of doing that. What you are going to do in general is build up a full HTML page in memory and the "print" it with the "print" function, which will cause the page to be sent back to the web server and then the web browser. But before you do that, you must print some special headers with this function: CGI-DISPLAY-HEADER. To build up that HTML page that you will print, there are two ways. Each way has the common end point of appending some HTML coding to the end of that big page in memory. The first way is to construct HTML in your program. You can do this a line at a time, or several lines at a time. The HTML can contain rebol words, because it will be reduced. Build you HTML in a word and then do CGI-EMIT-HTML data-name-2 Where data-name-2 is that rebol word that contains your HTML line(s). The second way is to make a separate file of HTML. In this HTML file, you may embed rebol code inside <% and %> tags. This code will be evaluated, and the results of the evaluation will replace the rebol code and its surrounding tags. This is sort of what PHP does. The rebol code can reference words in your program, so that is how you can get data that is in your program put into HTML. Do this: CGI-EMIT-FILE file-name-1 Where file-name-1 is the name of that file of HTML code with the optional embedded rebol code. When you have built up a full HTML page, it is your own responsibility to send it to the web server with the following command: print CGI-OUTPUT There is another somewhat-related service supplied by this module. Sometimes a program is written to display HTML not to be interpreted by a browser, but to be shown as HTML. That can be done with: data-name-3: CGI-ENCODE-HTML data-name-4 where data-name-4 is an HTML fragment, and data-name-3 is that same fragment with the tag markers ("<" and ">") replaced the the code that causes them to be shown by the browser. SCRIPT REBOL [ Title: "CGI common procedures" ] ;; [---------------------------------------------------------------------------] ;; [ This is a module of common procedures used in a CGI program. ] ;; [---------------------------------------------------------------------------] ;; [---------------------------------------------------------------------------] ;; [ This procedure is used to gradually build up a string of HTML ] ;; [ to return to the browser. When this module is first loaded, ] ;; [ it makes a string to hold the HTML. Then, is is called ] ;; [ repeatedly with a block of REBOL code and data as a parameter. ] ;; [ The procedure evaluates any REBOL expressions ("reduces" them) ] ;; [ and then appends the result to the end of the string we are ] ;; [ building. Finally, it puts a line-feed at the end so we don't ] ;; [ create just one gigantic string as the final result. ] ;; [ (This will be appreciated by anyone who tries to view the ] ;; [ source of the resulting page with the browser.) ] ;; [---------------------------------------------------------------------------] CGI-OUTPUT: make string! 5000 CGI-EMIT-HTML: func [CGI-OUT-LINE] [ repend CGI-OUTPUT CGI-OUT-LINE append CGI-OUTPUT newline ] ;; [---------------------------------------------------------------------------] ;; [ This little procedure displays the header that is required ] ;; [ when sending an html page back to the browser. ] ;; [ The procedure is separate because, while it must be done, ] ;; [ and it must be the first thing done, the caller might be ] ;; [ sending back a regular page, or a debugging page, or ] ;; [ who-knows-what, so we will let the caller do this when he ] ;; [ wants to. But he must. ] ;; [---------------------------------------------------------------------------] CGI-DISPLAY-HEADER: does [ print "content-type: text/html" print "" print "" ] ;; [---------------------------------------------------------------------------] ;; [ This procedure uses the above procedure and is an alternate ] ;; [ way to emit HTML. This procedure accepts a file name as a ] ;; [ parameter and reads that file into a string, and then calls ] ;; [ the above procedure to add the file to the end of the HTML ] ;; [ string that is being built up by the above procedure. ] ;; [ Before this procedure calls the above procedure, it runs the ] ;; [ build-markup function on the file it read. That function ] ;; [ locates special tags (<% and %>) and runs REBOL code inside ] ;; [ those tags, similar to what PHP does. Inside those tags ] ;; [ there can be REBOL words to be evaluated. It is the job of ] ;; [ the caller of this procedure to make sure that any words ] ;; [ used inside the build-markup tags are actually defined in ] ;; [ the calling program. ] ;; [---------------------------------------------------------------------------] CGI-EMIT-FILE: func [ CGI-FILE-TO-EMIT [file!] ] [ CGI-EMIT-HTML build-markup read CGI-FILE-TO-EMIT ] ;; [---------------------------------------------------------------------------] ;; [ This is a procedure that attempts to do as much as possible ] ;; [ to help in the processing of CGI data. ] ;; [ The procedure CGI-GET-INPUT reads the CGI data in whatever ] ;; [ form it is presented ] ;; [ (POST or GET), and then puts the raw data into a string ] ;; [ called CGI-STRING. Then it uses the decode-cgi command to ] ;; [ break it apart into name/value pairs. ] ;; [ It passes the name/value pairs to the construct function ] ;; [ which makes them into a context called CGI-INPUT. ] ;; [ As a context, the data can be referenced as ] ;; [ CGI-INPUT/data-name where data-name is a name specified in ] ;; [ the "name" attribute in the HTML form. ] ;; [ ] ;; [ The procedure CGI-GET-INPUT seems to hang up on IIS. ] ;; [ As a workaround, there is a separate procedure for IIS that returns ] ;; [ the same CGI-INPUT context, but by different means. ] ;; [ The "different means" is to read a fixed amount of data out of ] ;; [ the system/ports/input port. ] ;; [ These two procedures are mutually exclusive. Use on or the other. ] ;; [---------------------------------------------------------------------------] CGI-STRING: "" ;; -- Apache version CGI-GET-INPUT: does [ CGI-STRING: CGI-READ CGI-INPUT: construct decode-cgi CGI-STRING ] CGI-READ: func [ "Read CGI data (GET or POST) and return as a string or NONE" /limit CGI-MAX-INPUT "Limit input to this number of bytes" /local CGI-DATA CGI-BUFFER ] [ if none? limit [CGI-MAX-INPUT: 100000] switch system/options/cgi/request-method [ "POST" [ CGI-DATA: make string! 1020 CGI-BUFFER: make string! 16380 while [positive? read-io system/ports/input CGI-BUFFER 16380] [ append CGI-DATA CGI-BUFFER clear CGI-BUFFER if (length? CGI-DATA) > CGI-MAX-INPUT [ print ["aborted - form input too large:" length? CGI-DATA "; limit:" CGI-MAX-INPUT] quit ] ] ] "GET" [ CGI-DATA: system/options/cgi/query-string ] ] CGI-DATA ] ;; -- IIS version CGI-GET-INPUT-IIS: does [ CGI-STRING: CGI-READ-IIS CGI-INPUT: construct decode-cgi CGI-STRING ] CGI-READ-IIS: func [ ] [ CGI-DATA: make string! 5000 switch system/options/cgi/request-method [ "POST" [ read-io system/ports/input CGI-DATA 5002 ] "GET" [ GGI-DATA: system/options/cgi/query-string ] ] CGI-DATA ] ;; [---------------------------------------------------------------------------] ;; [ This procedure exists for those cases where a CGI program ] ;; [ is going to display HTML code for the purpose of actually ] ;; [ displaying the code and not having that code rendered into ] ;; [ an HTML display. It accepts a string and replaces the ] ;; [ less-than and greater-than signs with the escape sequences ] ;; [ that will cause a browser to display those signs instead of ] ;; [ interpreting them. ] ;; [---------------------------------------------------------------------------] CGI-ENCODE-HTML: func [ "Make HTML tags into HTML viewable escapes (for posting code)" CGI-TEXT-TO-ENCODE ] [ foreach [CGI-TAG-CHAR CGI-ESC-SEQ] ["&" "&" "<" "<" ">" ">" ] [ replace/all CGI-TEXT-TO-ENCODE CGI-TAG-CHAR CGI-ESC-SEQ ] ] ;; [---------------------------------------------------------------------------] ;; [ Here is/are some debugging procedure(s) we can use to find ] ;; [ out where things might be going wrong. When a CGI program ] ;; [ doesn't work, many times it doesn't produce any output at ] ;; [ all. ] ;; [---------------------------------------------------------------------------] CGI-DEBUG-MESSAGE: "" CGI-DEBUG-PAGE: { CGI debugging page <% CGI-DEBUG-MESSAGE %> } CGI-DEBUG-DISPLAY: func [ CGI-DEBUG-BLOCK [block!] ] [ CGI-DEBUG-MESSAGE: reform CGI-DEBUG-BLOCK CGI-EMIT-HTML build-markup CGI-DEBUG-PAGE print CGI-OUTPUT ] ===CGI form processing With the above CGI module pre-written, we can see a pattern for CGI form processing. The above module would be like black box, and we would call functions in it to get data from a form. The code snippets below are just an example pulled from a larger program. First, we have the html form taken from a web page. Note that one of the "input" items has been given a name of ENTERPERMIT-NUMBER-KEY.

Enter 7-digit permit number:  

Next we have a snippet from a REBOL program that gets data from that form. Note that we need just a function call to get all the "input" items on the form, and they are named with the same names as they were given on the form. Another little trick worth noting is that there is a switch in the program called DEBUG. If we set that to true, and run the program, then it will ask for input from the operator and display its output to the screen. This is a way to debug the program if it is not producing the expecte output. And finally, note that after we get the input field, since we are expecting in this case seven characters, we chop off only seven characters. This prevents an SQL insertion attack. (The GLB-SUBSTRING function is a function written elsewhere that extracts a substring given starting and ending positions.) ;; [---------------------------------------------------------------------------] ;; [ Get the permit number from the input form. ] ;; [---------------------------------------------------------------------------] either DEBUG [ RAW-INPUT: ask "Enter permit number: " ] [ CGI-GET-INPUT-IIS RAW-INPUT: copy CGI-INPUT/ENTERPERMIT-NUMBER-KEY ] WS-PERMITNUMBER: GLB-SUBSTRING trim/head RAW-INPUT 1 7 ===Next ID number In some situations you might want to add records to a database where the key to the record is just a sequential number. Somehow, you have to be able to find the next number to assign. Here is a function that does that by just storing the highest assigned number in a plain text file. REBOL [ Title: "Get next ID" Purpose: {Get a number one higher than the number stored in a specified file, and store the new number back in the specified file.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a function written for the situation where you are assigning ] ;; [ ID numbers to things (like data records) and want to keep track of ] ;; [ the highest number you have assigned. The highest number assigned is ] ;; [ kept in a one-line file, and the function reads that number, adds 1 to ] ;; [ it, saves the new number, and returns the new number so you can ] ;; [ assign it to some new thing. ] ;; [ This is an operation one wants to do with as few instructions as ] ;; [ possible. ] ;; [ Because the name of the file is passed to the function, this same ] ;; [ function could be used in a program that has several such ID numbers. ] ;; [ To save the trouble of initialization, if the specified file does ] ;; [ not exist, we will assume we are starting with ID number 1 and create ] ;; [ the file with that number in it. ] ;; [---------------------------------------------------------------------------] GET-NEXT-ID: func [ FILE-ID ] [ either exists? FILE-ID [ save FILE-ID HIGHEST-OPEN: add 1 load FILE-ID ] [ save FILE-ID HIGHEST-OPEN: 1 ] return HIGHEST-OPEN ] ;;Uncomment to test ;print GET-NEXT-ID %HighestOpen.txt ;print GET-NEXT-ID %HighestOpen.txt ;halt ===Find files of a given type This is an operation that keeps coming up, to the point where it was necessary, for sanity, to encapsulate it in a function. The problem is to find all the file names of a given type, in the current directory. Carl showed how to do that in one of his sample programs. The procedure is shown in the function below. REBOL [ Title: "Function to get all names of certain file types" Purpose: {Generalized version of a function from a program by Carl. Given a block of file types, return a block of all the file names in the current directory that are of that type.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a function borrowed from Carl's picture viewer program. ] ;; [ Pass to it a block of file types, and the program will assemble a list ] ;; [ of all files in the current directory of those types. Return the list ] ;; [ in a block. For example: ] ;; [ FILE-LIST: FILES-OF-TYPE [%.jpg %.JPG %.png %.PNG] ] ;; [ Note how you can make a function within a function. ] ;; [ General procedure is to get a list of all files in the current folder. ] ;; [ Go through the list. If a file has the desired suffix, go on to the ] ;; [ next file. Otherwise remove it from the list. At the end, reposition ] ;; [ to the head of the list and return it to the caller. ] ;; [---------------------------------------------------------------------------] FILES-OF-TYPE: func [ TYPE-LIST /local FILE-ID-LIST ] [ OF-TYPE?: func [ FILE-ID ] [ find TYPE-LIST find/last FILE-ID "." ] FILE-ID-LIST: copy [] FILE-ID-LIST: read %. while [not tail? FILE-ID-LIST] [ either OF-TYPE? first FILE-ID-LIST [ FILE-ID-LIST: next FILE-ID-LIST ] [ remove FILE-ID-LIST ] ] FILE-ID-LIST: head FILE-ID-LIST return FILE-ID-LIST ] ;;Uncomment to test ;probe FILES-OF-TYPE [%.txt %.TXT] ;print "-------------------------------" ;probe FILES-OF-TYPE [%.png %.jpg] ;print "-------------------------------" ;probe FILES-OF-TYPE [%.r] ;halt ===Hexadecimal value of a byte An operation that is done often enough to be important but not often enough to remember, is getting a printable representation of the hexadecimal value of a single byte. So, once we figured out how to do that, we encapsulated it so we can use it again without having to read the reference manual again. REBOL [ Title: "Hex byte" Purpose: {Convert a one-character string to a two-character display of its hex value, suitable for printing.} ] ;; [---------------------------------------------------------------------------] ;; [ This little function is part of a project to print a string of bytes ] ;; [ that has some unprintable characters. It takes one character and ] ;; [ returns two, that are the hex representation of the byte. ] ;; [---------------------------------------------------------------------------] HEX-BYTE: func [ BYTE ] [ return reverse copy/part reverse to-string to-hex to-integer to-binary BYTE 2 ] ;;Uncomment to test ;print ["X =" HEX-BYTE "X"] ;print ["7 =" HEX-BYTE "7"] ;print ["! =" HEX-BYTE "!"] ;print ["[ =" HEX-BYTE "["] ;print ["# =" HEX-BYTE "#"] ;halt ===Hexadecimal value of a string This is not really a "pattern" in that it is something that we do a lot. It is included here for completeness because it shows the application of the above function to produce the hexadecimal value of a byte in a printable form. Comments are in the code. REBOL [ Title: "Hex print" Purpose: {Take a string of characters and return it formatted in a way that if the result is printed one can have a hex representation of the string.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a helper function for a project of printing a string, that could ] ;; [ contain unprintable characters, in a hexadecimal format. ] ;; [ Input to the function is a string. Output is a block. The block ] ;; [ contains strings of up to 60 characters, occurring in pairs. ] ;; [ The first string of a pair is up to 30 characters of the input string, ] ;; [ with each character followed by a space. If the character is ] ;; [ unprintable, a dot will be returned in its place. ] ;; [ The second string of a pair is a hexadecimal representation of the ] ;; [ same 30 characters. ] ;; [ If you would print a pair of the returned strings one above the other, ] ;; [ you would have a "hex dump" of the string. ] ;; [ The original goal of the project was to print strings of comments ] ;; [ from a database text field, to search visually for unprintable junk. ] ;; [---------------------------------------------------------------------------] HEX-PRINT: func [ STR /local BLK S1 S2 CNT ] [ BLK: copy [] S1: copy "" S2: copy "" CNT: 0 foreach BYTE STR [ either (BYTE < #"^(20)") or (BYTE > #"^(7E)") [ either ((not-equal? (to-char BYTE) #"^(0D)") ;; CR and (not-equal? (to-char BYTE) #"^(09)") ;; HT and (not-equal? (to-char BYTE) #"^(0A)")) [ ;; LF append S1 "? " ] [ append S1 ". " ] ] [ append S1 rejoin [BYTE " "] ] append S2 reverse copy/part reverse to-string to-hex to-integer to-binary BYTE 2 CNT: CNT + 1 if greater? CNT 30 [ append BLK S1 append BLK S2 S1: copy "" S2: copy "" CNT: 0 ] ] append BLK S1 append BLK S2 return BLK ] ;;Uncomment to test ;TESTDATA: { ;Abcdef ;123456 ;!@#$%^ ;} ;DUMP: HEX-PRINT TESTDATA ;foreach [PLAIN HEX] DUMP [ ; print PLAIN ; print HEX ;] ;halt ===ODBC submission module This is another case of encapsulating functions into a black box and using the functions to make a program shorter and its operation clearer. The module below allows one to make a file of ODBC connection strings for all the commonly-used databases at an installation, and then connect to one of them in a streamlined manner based on the database name. Comments in the code below explain. REBOL [ Title: "General ODBC functions" Purpose: {Isolate ODBC connection strings for easy maintenance. Store them in a format such that they can be a Python module and still be used by a REBOL program.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a generalized module for reading data from databases by ODBC. ] ;; [ It seems that ODBC needs a "connection string" that identifies the ] ;; [ server, the database, and a user ID and password. This string is ] ;; [ not specific to REBOL but applies to other languages, such as Python. ] ;; [ It also seems that the Python syntax to define a variable with a value ] ;; [ of a connection string can be put into a format that is parsable by ] ;; [ REBOL. Therefore, if one worked at an installation with several ] ;; [ databases and wanted to streamline the ODBC access to them, one could ] ;; [ gather all the connection strings for all the databases into a file, ] ;; [ code them in a Python syntax, and use that file of connection strings ] ;; [ in Python and REBOL programs. There is an example of what those ] ;; [ strings could be like: ] ;; [ ] ;; [ DB1="DRIVER={SQL Server};SERVER={SERVER1};DATABASE=DB1;UID=user1;PWD=pwd1"] ;; [ DB2="DRIVER={SQL Server};SERVER={SERVER2};DATABASE=DB2;UID=user2;PWD=pwd2"] ;; [ DB3="DRIVER={SQL Server};SERVER={SERVER3};DATABASE=DB3;UID=user3;PWD=pwd3"] ;; [ DB4="DRIVER={SQL Server};SERVER={SERVER4};DATABASE=DB4;UID=user4;PWD=pwd4"] ;; [ DB5="DRIVER={SQL Server};SERVER={SERVER5};DATABASE=DB5;UID=user5;PWD=pwd5"] ;; [ ] ;; [ The function below assume that such a file exists, reads it, and ] ;; [ parses it into a "select" block of database names and connection ] ;; [ strings. There is a function to open a database given a name as ] ;; [ defined in the file, and a function to submit SQL to that opened ] ;; [ database. Rounding out the services is a function to close the ] ;; [ database. ] ;; [---------------------------------------------------------------------------] ;; -- Connection strings are stored in this file. ODBC-CONNECTIONS-FILE: %/SERVERNAME/PYTHON/PYTHON_MODULES/ODBCconnectionstrings.py ODBC-CONNECTIONS: read/lines ODBC-CONNECTIONS-FILE ;; -- Parse each line on the first "equal" sign, dividing each line into two ;; -- parts. Append the two parts to the accumulation of connection names ;; -- and strings. ODBC-CONNECTIONLIST: copy [] foreach ODBC-LINE ODBC-CONNECTIONS [ ODBC-NME: copy "" ODBC-STR: copy "" parse/all ODBC-LINE [ copy ODBC-NME to "=" skip copy ODBC-STR to end ] append ODBC-CONNECTIONLIST ODBC-NME append ODBC-CONNECTIONLIST trim/with ODBC-STR {"} ] ;; -- Given a connection name, get the connection string and open ;; -- an ODBC connection. ODBC-OPEN: func [ ODBC-CONNECTIONNAME /local ODBC-CONNECTSTRING ] [ ODBC-CONNECTIONSTRING: select ODBC-CONNECTIONLIST ODBC-CONNECTIONNAME ODBC-CON: open [ scheme: 'odbc target: ODBC-CONNECTIONSTRING ] ODBC-CMD: first ODBC-CON ] ;; -- Submit an SQL script and return the result set. ODBC-EXECUTE: func [ ODBC-SQL ] [ insert ODBC-CMD ODBC-SQL return copy ODBC-CMD ] ;; -- Close the ODBC connection. ODBC-CLOSE: does [ close ODBC-CMD ] ;; -- Test the parsing ;foreach [NAME CONSTRING] ODBC-CONNECTIONLIST [ ; print [mold NAME ":" mold CONSTRING] ;] ;halt ===ODBC example Given the above module to encapsulate ODBC operations, here is an example of how easy it can be to get data from an SQL Server database. Shown below is a generic code snippet. It is assumed that the SQL is in a file in a folder of SQL queries. The SQL could be hard-coded into the program, but if we put the SQL into a file by itself, then we could run the SQL manually if debugging were necessary. If you are runnint this query just once, you don't have to clear RESULTSET first, so the above module makes it possible to query a database in three lines of code. Remember that the result of an ODBC query is the result set in a block of blocks, where each sub-block is a row of the result set. RESULTSET: copy [] ODBC-OPEN "DB1" RESULTSET: ODBC-EXECUTE read %sql/SQLcommand.sql ODBC-CLOSE ===SQL "as" column headings This script is part of a process of streamlining the processing of an SQL query. It shows what can be done with a little discipline in the coding of a query. The dccumentation is in the comments, but basically, the script will parse a carefully-written SQL query and locate all the selected column names, and return them in a block. The purpose of this script might seem a bit obscure, but things will become clear farther down in this documentation. REBOL [ Title: "SQL As columns" Purpose: {Given a carefully-formatted SQL query where all selected columns have the "As" feature specified, extract those column names and return them in a block.} ] ;; [---------------------------------------------------------------------------] ;; [ It is possible to do useful things with source code if is is written ] ;; [ with some discipline. In this case if one has an SQL query and every ] ;; [ column in the "select" statement has the "As" feature specified to ] ;; [ name the column, then it should be possible to extract the column ] ;; [ names from the SQL. Any string after the word "As" is a column name, ] ;; [ and the word "From" indicates the end of the column names. ] ;; [ This function will make that scan and return the column names as ] ;; [ a block of strings. This function was written as part of a larger ] ;; [ project to automate the running of SQL queries. ] ;; [ ] ;; [ This "markup" of the SQL must follow a particular convention. ] ;; [ The "As" specification for a column must use the word "As" in this ] ;; [ manner, that is, upper-case A and lower-case s. This will distinguish ] ;; [ the word from "AS" and "as" and let you use "AS" or "as" in the ] ;; [ query according to your case preferences. Similarly, the word "From" ] ;; [ that indicates the first table to select from, must have the upper-case ] ;; { F and the r-o-m in lower case. This will distinguish it from a "FROM" ] ;; [ or "from" that might be used in a sub-query. This case-insensitivity ] ;; [ works in SQL Server; I don't know if it works elsewhere. We are able ] ;; [ to make this work in REBOL because of the strict-equal? function. ] ;; [---------------------------------------------------------------------------] SQL-AS-COLUMNS: func [ SQL-CMD /local COLNAMES WORDS LGH POS TESTWORD ] [ WORDS: parse SQL-CMD none LGH: length? WORDS POS: 1 COLNAMES: copy [] while [POS < LGH] [ if strict-equal? "From" pick WORDS POS [ break ] either strict-equal? "As" pick WORDS POS [ POS: POS + 1 TESTWORD: copy trim/with pick WORDS POS "'()" append COLNAMES TESTWORD POS: POS + 1 ] [ POS: POS + 1 ] ] return COLNAMES ] ;;Uncomment to test ;SQL-CMD: { ;select ;cast(COLUMN1 as int) As COLUMN1 ;,COLUMN2 As COLUMN2 ;,COLUMN3 As 'COLUMN3' ;,COLUMN4 As 'COLUMN4' ;,(select ITEM1 from TBL1 as T1) As ITEM ;From TABLE1 as T1 ;inner join TABLE2 AS T2 ;on T1.COLUMN1 = T2.COLUMN1 ;order by COLUMN1 ;} ;probe SQL-AS-COLUMNS SQL-CMD ;halt ===CSV file from a block of blocks plus headings This is another encapsulation of something that is done a lot. It is a function that takes a file name, a block of heading strings, and a block of data blocks like one might get from an SQL query, and creates a CSV file out of them. The details of use will be shown just a bit farther down in this document. REBOL [ Title: "CSV file from a block" Purpose: {Create a CSV file from a block of headings and a block of data.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a piece of a larger problem. ] ;; [ The purpose is to create a CSV file after we have assembled data into ] ;; [ a specific form. That form is a block of column headings plus a block ] ;; [ of sub-blocks where each sub-block is going to be a line in the CSV file. ] ;; [ So to call the function, you must specify a file name for the output ] ;; [ file, plus a block of heading strings (or words because we will convert ] ;; [ them to strings to be sure), plus a block of sub-blocks of data. ] ;; [ For example, ] ;; [ CSV-FROM-BLOCK %csvfile.csv ["COL1" "COL2" COL3"] [ ] ;; [ ["A" "B" "C"] ] ;; [ ["D" "E" "F"] ] ;; [ ["G" "H" "I"] ] ;; ] ] ] ;; [ The result would be a file called csvfile.csv containing: ] ;; [ COL1,COL2,COL3 ] ;; [ A,B,C ] ;; [ D,E,F ] ;; [ G,H,I ] ;; [ Note that you must provide clean data. The number of heading items ] ;; [ must match the number of data items in each data sub-block. ] ;; [---------------------------------------------------------------------------] CSV-FROM-BLOCK: func [ FILEID HEADERBLOCK DATABLOCK /local DATAFILE COLS CNT ] [ DATAFILE: copy "" COLS: length? HEADERBLOCK CNT: 0 foreach HDR HEADERBLOCK [ CNT: CNT + 1 append DATAFILE HDR if lesser? CNT COLS [ append DATAFILE "," ] ] append DATAFILE newline foreach BLK DATABLOCK [ CNT: 0 foreach ITEM BLK [ CNT: CNT + 1 append DATAFILE ITEM if lesser? CNT COLS [ append DATAFILE "," ] ] append DATAFILE newline ] write FILEID DATAFILE ] ;;Uncomment to test ;CSV-FROM-BLOCK %csvfile.csv ["COL1" "COL2" "COL3"] [ ; ["A" "B" "C"] ; ["D" "E" "F"] ; ["G" "H" "I"] ;] ;halt ===Parse structured SQL comments This is another packaging of a useful thing that can be done with an SQL query if the query is written with a bit of discipline. Documntation is in the comments, but basically, if an SQL query in a file has a structured comment block at the beginning, those comments can be coded to contain useful information. REBOL [ Title: "SQL comments" Purpose: {Extract structured comments from an SQL script.} ] ;; [---------------------------------------------------------------------------] ;; [ This function is part of a larger project to smooth the running of SQL ] ;; [ scripts. It takes an SQL script with a comment block like this: ] ;; [ /* ] ;; [ DATABASE: "database-name" ] ;; [ AUTHOR: "J Smith" ] ;; [ DATEWRITTEN: 29-JUN-2017 ] ;; [ KEYWORDS: ["keyword-1" "keyword-2"] ] ;; [ COLUMNS: ["colname-1" "colname-2"] ] ;; [ REMARKS: {Multi-line free-format description of the script.} ] ;; [ */ ] ;; [ and returns a block containing the values of DATABASE, AUTHOR, ] ;; [ DATEWRITTEN, KEYWORDS, COLUMNS, and REMARKS. ] ;; [ This comment block must be at the start of the script, where one ] ;; [ normally would place it. ] ;; [ The way this is written will cause DATABASE, AUTHOR, DATEWRITTEN, ] ;; [ KEYWORDS, COLUMNS, and REMARKS to be global words. ] ;; [ COLUMNS is an optional list of column name literals that could be used ] ;; [ by other automated processes to identify the names of the colums ] ;; [ returned by the SQL. ] ;; [---------------------------------------------------------------------------] SQLCOMMENTS: func [ SCRIPTCODE /local COMMENTBLOCK RETURNBLOCK ] [ COMMENTBLOCK: copy "" RETURNBLOCK: none parse/case SCRIPTCODE [thru "/*" copy COMMENTBLOCK to "*/"] if greater? (length? COMMENTBLOCK) 0 [ DATABASE: copy "" AUTHOR: copy "" DATEWRITTEN: none KEYWORDS: copy [] COLUMNS: copy [] REMARKS: copy "" do load COMMENTBLOCK RETURNBLOCK: copy [] append RETURNBLOCK DATABASE append RETURNBLOCK AUTHOR append RETURNBLOCK DATEWRITTEN append/only RETURNBLOCK KEYWORDS append/only RETURNBLOCK COLUMNS append RETURNBLOCK REMARKS ] return RETURNBLOCK ] ;;Uncomment to test ;SQL-CMD: { ;/* ;DATABASE: "database-name" ;AUTHOR: "J Smith" ;DATEWRITTEN: 29-JUN-2017 ;KEYWORDS: ["keyword-1" "keyword-2"] ;COLUMNS: ["col-1" "col-2"] ;REMARKS: {Multi-line free-format description of the script.} ;*/ ;select * from TABLENAME ;} ;probe SQLCOMMENTS SQL-CMD ;halt ===SQL query to CSV file With the above three modules, plus the ODBC module shown earlier, we have the pieces of a "pattern," that is, a way of doing things that is so smooth that we do it this way a lot. The code below is part of a script that runs an SQL query and puts the results into a CSV file. Here is how it does it, using the four code modules we have shown. Step zero: Code an SQL query according to the standards described above, where column names are specified with the "As" keyword and the first "From" keyword is coded with the upper-case "F." Step one. Read the script into the program because we will use it several times. Step two. Parse the comments to get the first comment item, which is the name of the database being queried. Step three. Use the function shown above to parse out the column names from the SQL script and return the column names in a block. Step four. Run the SQL query using the ODBC module shown above. Note that you will have had to write and store the appropriate connection string for your database, as explained in the ODBC module comments. This operation will return data in a block of blocks. Step five. Using the function described previously, pass to it the name of a file, the block of column headings, and the block of blocks from the SQL query, and you will get a CSV file. Here is a code snippet from a program that does that. SQLFILE: %sql/LNDcheck.sql CSVFILE: %LNDcheck.csv ;; -- Load the SQL into memory because we will use it multiple times. SQL-CMD: read SQLFILE ;; -- Find the database that this SQL refers to. DBNAME: first SQLCOMMENTS SQL-CMD ;; -- Get the column names. COLUMN-NAMES: SQL-AS-COLUMNS SQL-CMD ;; -- Run the SQL. ODBC-OPEN DBNAME SQL-RESULT: ODBC-EXECUTE SQL-CMD ODBC-CLOSE ;; -- Make the final CSV file. CSV-FROM-BLOCK CSVFILE COLUMN-NAMES SQL-RESULT ;; -- And that should be it. alert "Done." ===Wait for a file Here is an idea for a function to be used in a multi-language job stream, where a REBOL program might execute some other program, and the other program would indicate its completion by creating a file. We would need a way to wait for the file and not proceed until it came into existence, or give up after an appropriate period of time. Here is a function that does that. REBOL [ Title: "Wait for a file to exist" Purpose: {A function that can be called to loop until a file of a given names comes into existence. Can be used for coordinating several programs running as a job.} ] ;; [---------------------------------------------------------------------------] ;; [ This module provides a function that will loop, and in every pass it ] ;; [ will check for the existence of a file, the name of which was passed ] ;; [ as an argument. When the file comes into existence, the function ] ;; [ will exit with a value of true. If a certain amount of time passess ] ;; [ and the file has not appeared, it will pop up an alert box to ask ] ;; [ if it should continue waiting. If the response is yes, it will begin ] ;; [ the waiting process again. If the response is no, it will exit with ] ;; [ a return value of false. The "certain amount of time" is hard-coded ] ;; [ because a time-out hardly ever will be an issue. If you want to ] ;; [ change the time-out, you could just change the value in the code. ] ;; [---------------------------------------------------------------------------] WAIT-FOR-FILE: func [ FILENAME /local TIMEOUT TIMER INTERVAL KEEPWAITING ] [ TIMEOUT: 00:00:10 TIMER: 00:00:00 INTERVAL: 00:00:01 KEEPWAITING: false forever [ either exists? FILENAME [ return true ] [ TIMER: TIMER + INTERVAL wait INTERVAL if TIMER > TIMEOUT [ KEEPWAITING: alert [ rejoin ["File " FILENAME " has not appeared"] "Wait more" "Give up" ] either KEEPWAITING [ TIMER: 00:00:00 ] [ return false ] ] ] ] ] ;; Uncomment to test; create your own file called exists.txt. ;either WAIT-FOR-FILE %exists.txt [ ; print "File is there" ;] [ ; print "File is not there" ;] ;halt ===Launch Windows File Explorer The REBOL VID is very useful for little menu programs, and a common use of little menu programs is to open file explorer windows. Here is how to do that (works on Windows 10). REBOL [ Title: "Testing shell" Purpose: {Launching File Explorer to a directory.} ] call {%windir%\explorer.exe "\\servername\vol1\REBOL\"} print "Done." halt ===Recursive file and folder lists If you use REBOL a lot for little file maintenance tasks, then a common operation will be to find all the files or directories in a given directory. The functions in this sample, borrowed from a now-forgotten location, accomplish that. REBOL [ Title: "Recursive folder and file lists" Purpose: {Create a block of all the file names in a specified directory, recursively into sub-directories. Do a similar thing for all folders in a specified directory.} ] ;; [---------------------------------------------------------------------------] ;; [ I tried to make this into a function that would return a block of ] ;; [ file or folder names, but could not. To make it work, I had to put ] ;; [ the final results into words not local to the functions. ] ;; [ This probably is a fault of my lack of understanding of REBOL. ] ;; [ If you call this more than once in a program you will have to clear ] ;; [ out the lists or you will get things doubled-up. ] ;; [---------------------------------------------------------------------------] RECURSIVE-FILE-LIST: [] RECURSIVE-FOLDER-LIST: [] FIND-FILES-RECURSE: func [ FOLDER ] [ foreach FILE read FOLDER [ either find FILE "/" [ FIND-FILES-RECURSE FOLDER/:FILE ][ append RECURSIVE-FILE-LIST FOLDER/:FILE ] ] ] FIND-FOLDERS-RECURSE: func [ FOLDER ] [ foreach FILE read FOLDER [ if find FILE "/" [ append RECURSIVE-FOLDER-LIST FOLDER/:FILE FIND-FOLDERS-RECURSE FOLDER/:FILE ] ] ] ;;Uncomment to test ;RECURSIVE-FILE-LIST: copy [] ;RECURSIVE-FOLDER-LIST: copy [] ;either FOLDER-NAME: request-dir [ ; FIND-FILES-RECURSE FOLDER-NAME ; FIND-FOLDERS-RECURSE FOLDER-NAME ; print "------------------- files:" ; foreach ITEM RECURSIVE-FILE-LIST [print ITEM] ; print "------------------- folders:" ; foreach ITEM RECURSIVE-FOLDER-LIST [print ITEM] ;] [ ; print "No folder selected" ;] ;halt ===Check for safe file name A common maintenance task is to do things with file names, and people seem to love to put any characters they want into file names regardless of what effects that might have. The function below is used to check a file name and see if it has only letters, numbers, and approved special characters. It is just a true/false check, it does not do anything with a file name that might be a problem. REBOL [ Title: "Safe file name" Purpose: {Check a file name string for characters that might cause problems in certain situation.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a function written for one purpose, to check a file name for ] ;; [ characters that might cause problems with certain automated procedures. ] ;; [ A file name that generally will NOT cause problems is one that contains ] ;; [ only letters, numbers, hyphens, and underscores. Not that other ] ;; [ characters WILL cause problems, but they could, so this function just ] ;; [ checks the file name to see if it MIGHT be a problem. ] ;; [===========================================================================] SAFE-FILENAME: context [ UPPER: charset [#"A" - #"Z"] LOWER: charset [#"a" - #"z"] DIGIT: charset [#"0" - #"9"] SPECIAL: charset "-_." OK-FILENAME: [some [UPPER | LOWER | DIGIT | SPECIAL]] CHECK: func [ FILE-ID ] [ return parse/all to-string FILE-ID OK-FILENAME ] ] ;;Uncomment to test ;TESTID: %TESTFILE.TXT ;print [TESTID ":" SAFE-FILENAME/CHECK TESTID] ;TESTID: "TEST FILE.TXT" ;print [TESTID ":" SAFE-FILENAME/CHECK TESTID] ;TESTID: to-local-file "TEST FILE (1).TXT" ;print [TESTID ":" SAFE-FILENAME/CHECK TESTID] ;halt ===Space or zero fill Formatting data for reporting often involves lining things up in columns. That means that things have to be the same size. Here are functions that padd a string on the right with spaces, or on the left with zeros. REBOL [ Title: "Space-fill and zero-fill functions" Purpose: {Provide two useful function, in as little code as possible, one of which pads a string on the right with trailing spaces out to a specified length, and the other of which pads a string with leading zeros up to a given length.} ] SPACEFILL: func [ "Left justify a string, pad with spaces to specified length" INPUT-STRING FINAL-LENGTH ] [ head insert/dup tail copy/part trim INPUT-STRING FINAL-LENGTH #" " max 0 FINAL-LENGTH - length? INPUT-STRING ] ZEROFILL: func [ "Add zeros to the front of a string up to a given length" INPUT-STRING FINAL-LENGTH ] [ head insert/dup INPUT-STRING #"0" max 0 FINAL-LENGTH - length? INPUT-STRING ] ;;Uncomment to test ;print rejoin ["'" SPACEFILL " TEST STRING " 30 "'"] ;print rejoin ["'" SPACEFILL " TEST STRING THAT IS LONGER THAN 30 " 30 "'"] ;print rejoin ["'" ZEROFILL "123" 6 "'"] ;print rejoin ["'" ZEROFILL "123456" 6 "'"] ;halt ===VID button "click" A fun feature we tried was to produce a clicking sound when a VID button was clicked. Details in the comments of the following script. REBOL [ Title: "Click" ] ;; [---------------------------------------------------------------------------] ;; [ This is a function that will play a particular canned sound. ] ;; [ It original use was to play a clicking sound when a button was clicked. ] ;; [ The canned sound was produced on a GNU/Linux computer with a sound ] ;; [ recording program that would save a sound as a "wav" file. ] ;; [ The recording procdedure was to place a microphone right next to a ] ;; [ key on a spring-operated IBM keyboard, then, as fast as possible, ] ;; [ start recording, press the key, and quit recording. ] ;; [ The way to use this procedure is to code the following as part of the ] ;; [ code for a button or whatever you want to produce a sound: ] ;; [ attempt [CLICK] ] ;; [ The use of "attempt" will allow the program to continue running if ] ;; [ no sound hardware is present and the sound can not play. ] ;; [---------------------------------------------------------------------------] CLICK-DATA: 64#{ UklGRmQFAQBXQVZFZm10IBAAAAABAAIARKwAABCxAgAEABAAZGF0YUAFAQDhB0AG WQnIBzoMrAppCg0J3w2cDLYNDgw8BMoCXAiYBtYSURGiCRcIOAC6/owNQAy2EkER HQbEBEkF4AMuDswMIQ2cCy0H2gVlBdoD2wZMBRcLzgkhDMUKbAUsBA0DqgG2DQsM QRDMDsQBngCLAVsAEhCjDvQKsgmn/XH87QWLBDQP9Q18BzMGTAPwAcgIUAe4CTAI +gZyBYUFBgQjBKsCXAUWBFkJ2AebBjYFygFSADYIiAapDRQMfwXtA5gF0QNkELYO 2ApcCWIC8wCmDdUL7xAeDwYEpAKIB/EFoBT2EnANBwyeAxYCTQycCsMTVxIuDaUL hQbhBPEIlQe5DTEMbQ7YDKgIEweYBQ0ETQ6/DCUTcREaBpgEWAEcAHES6RDZFNwT WAL2ACIBuv9eEgsR6RJhEZgGfAU9BzkGVw7oDLkORw2yCzcKPQkKCPEJlQiNDxsO vA5wDYUEIwOSBFIDYRHlD04QvA45BL4C3gdyBrkRLhCADC0LIwXnA9sHMwYkC6UJ QwvICQQJggfdBIgD7geLBj4P/g3hCo8JwQIpAfQIiAc+D/4NfwYTBYsBTwCWCkYJ CA1pC3IFCgTtBVkEUwu7CbsKYAlTCd4HhQgzB18G+gSfCBcHNwpNCUYF8wNZBf0D xQySCxEKbwinAVUA1AdyBrwNJwwpBasDqwIvAf4LrArOCD0HQv/D/asGOQVED8IN UAe0BXIC2gA9CtsI2AxdC7UHaQY5BuoE1AdiBtUJYwifChQJuwVyBPQEkQP7DcUM CA6vDF8C8wCCBC8DRxHPDxcNqQu0AQ8AjAcNBpAPNA7qB1YGXwMQApwK9AjICz0K QwbtBBoGvgS4CH8HiQkHCI8IWQd1BBADmAJbAf0HpQYRCZUHLALqADAFxwNKDdIL 0Qc2BrcBYgDICGMHNwvuCXIDFgKVAykC0Qh1B5IGSQU5Bg0FmQlGCH8FJgQGBPAC 2AuDCnMJPQgcAL3+TwUgBO4MfAuVA0ICHP/J/RoKnwjLClwJ1AE4AEIE5wJvCSAI QwWoA2IE3QJvBwcG3QO+AgMEpALxCW8IzgYwBboBWACcCUAInAsaCkUBMgC6AzwC wg5gDWYIywZY/gL9Rgb0BDcLywnBAkwB0AJ+Ac4JRghyBiwFkQL8ANQEIAMDBb4D mwUGBCMGzgTtAJf/EgDA/owJxQfuCGwHJf7f/FgD4wGzDkENqwQ8A6b7O/pgCRoI RA4eDeb+h/2X/hL9XQwXC10K+gjjAH7/sQRcAw4L2wlDCS0IygRrA1ICCQH9BeEE +Au4CssGggXj/cb8PAbnBPIQgw/HBWUE1vtq+o8IfAdhEBEPNgIpAQz98vsHCPQG 7gq4CZsEbwMAAgkBCgTQAn8HVgY9CeoHugJSAcD+yf1cCEYHpQsdCvb+cf3y/K37 rAs3CnMM+woMAL3+VQEDAEkJ5AdMBxAGkgQTA5UENgOuA4ECZgYgBW8HKQYZAI7+ CQDs/lMLGgodCmYIwP22/AMCAAHVDHAL/QXHBJ3+tv2LBjwFdgj3BqQBTwCSBE8D jAkgCJgFNgSFBUkEsgh1B0YEAAN1A08CpQqGCdsHiAYAAKT+EAa0BDQLyAmhApcB mAOFAqYMZguhBWgEpP5L/egJsghTDBEL8/6X/QYB0/8nDd4LIweYBTL97/tPBe0D WgwUC0kF2gMMAMr+aAQ5AyMI/Qb0BpgFEwLgACwAwP6MB1MGAQzbCuoBugCH/kX9 QAw0C8kOiQ1e/wb+7/3m/DQLMArYCXkIJf4i/Q8B1v8KCtQI6gfUBogCJgHBAjIB TAXNA7gGVgWxBDkD1v6k/YsB7f9pCUMIHQXUA+D9p/wTBfcDBArRCBYCqgCE/1j+ 9wWhBHUGxwS6ApcB6gLUAdACngFSA0ICYgYpBccEaANIAT8ARgUQBNEHuwZFARkA JQAc/9EHngY5BvQEIv78/N0B4wCyCJgH7QTHA18BSwD6BOcDrgSOA5sCjgFcBFID bwQ2A/ACxAF8BV8EPwUTBOYAwP8pBLoC6wlvCDMEzQIl/+/9uwdTBlkKzgjdAHv/ ngFCAAoK8QihBYIEe/9R/jwFygOcCEYHCgR4AuABhAADBIUCeQbqBFkGGQVYARYA /P66/QMF7QNcB9QFGf90/Xf+L/3OCFYHiwZvBQv7zPkM/9D9jwlJCKsCLAF9+jf5 kQImAasHPAZuAfP/OP/j/Y4EOQMjBtQEAAOXAYQAA/+0AXsAdQXtA08EAwNr/+z9 LADN/rEGeAXhBagEfv4Y/b0BEgAzCOoGcgI/ASX9FfzHA2gC8QaoBRYB1v8///b9 YgI1ARAEygLRBJ4DiwMjAp4AP/8pA70BHQa7BHsCQgGk/17+kgQsA5IGJgXEAXsA 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 GvET8HD3svYS/lT9DP5h/WYHeQYDHPAaVRomGVIFewT+8uTx6OAx4MnmG+acCp8J ZClXKHUbjhpSAUsApvYE9sUHEAeQ9+j2oTLEMURVO1Tmj3iPFfya+zVFH0QAgACA OdjH1/9//3+P2dHYvOL+4cg2zjXQK/kqq9lP2euB64F4ALf/dXUNdHmwxa8AgACA T+qa6QhotWbQKtwpAIAAgFQTbhL/f/9/GLmzuACAAIC/+dz4/3//f1NO20wAgACA k4k+if9//39lL6QuAIAAgBgQkw//f/9/CN9N3gCAAIAKTd5L/3//f7qjkaMAgACA zxE4Ef9//39rucm4AIAAgNdgq18ge7h5AIAAgACAAID/f/9//3//f4vYENgLns+d /3//f8h7gnoAgACAAIAAgP9//3//f/9/ppsXmymnkab/f/9/QE/3TQCAAIAAgACA HxZRFaJP0k5v2rvZH0HmP/9//38F9yr2AIAAgPgmAiYWSNpGFsCuv7PO5s3/f/9/ /3//f0gAUv8AgACAAIAAgJqPP4/rHi0eFlzwWvBc0FuGJX0kHrTFs02CQ4LHu3S7 D89xzmTjtuK3AgYC7LZUtuK0d7RsTEZLq2F8YA3vOe7hq1yrsekc6UMJXAiC8wHz VjZGNVtbNVp297z2AIAAgOOPdY/IY39i5X6ifXCyRLIAgACAgbnfuL3++f0lQdw/ /3//fxck/iIAgACAAIAAgFoofSf/f/9//3//f83THNMQlG+T0ItRiwCAAIABhMKD mVCWT/9//3//f/9//3//f/9//392I58iAIAAgACAAIAAgACA/3//f/9//3+6z+PO AIAAgACAAIAAgACAAIAAgOc03jMu+3f6AIAAgACAAIAAgACAkb/9vv9//3//f/9/ pqFxoQCAAIAAgACA5fbY9f9//38hUxtSAIAAgACAAIAAgACAAIAAgP9//3//f/9/ SOqe6QCAAIAAgACAAIAAgACAAID/f/9//3//f596dnnPzTTNvgkKCT0iISEAgACA AIAAgP9//38DdQ10/3//f/9//3//f/9/CFbDVACAAIBc25/aAIAAgACAAID/f/9/ /3//f/9//3//f/9//3//fwCAAIAAgACAAIAAgACAAIA39KXz/3//f/9//3//f/9/ AIAAgACAAIAAgACArJlmmf9//3//f/9//3//f7C4JbgAgACAXYdRhwCAAIDWiKmI W44vjgCAAIAAgACA3XGKcAyMeosAgACAAIAAgMccDRwwYwFi/3//f9NakVlt+oP5 AIAAgACAAID/f/9//3//fz1RWlBkuu+5AIAAgACAAICy98/2sFlrWHMgqB/s4j7i AIAAgACAAIAAgACAAIAAgE32j/UAgACAAIAAgPO6d7oAgACALQhsB+1g7V8AgACA AIAAgACAAIDEwjPC/3//fxBix2AAgACACgRSA74FCgXmjpGOE9rO2ceSiJIAgACA YMj1x/9//3//f/9/Wd2s3ACAAIDvjMOMLoj7hwKjo6L/f/9//3//f6f92fz/f/9/ ZOXi5ACAAIAlWBVXEWXCY3vU6tNLFDgTyyDFH1qxHrEPt522iXozeVx6Nnkv1ZfU RsSuw+X5LvlfTGZL/3//f2XWrtUAgACA/3//f/9//38AgACAJPd99gOTq5LDoY2h /3//f/9//393bXFs9wQjBIOFVIWsJsYl9hM7EwCAAIAAgACAeuHr4EnZqNgAgACA AIAAgA2XbJaWtA60rgbRBbdZdFjUHfQcXqIJogCAAIAAgACAAIAAgACAAIAAgACA Gaqeqf9//3+IYllhAIAAgACAAIBPSUZI/3//fwCAAIAAgACAAIAAgP9//3+i2TbZ AIAAgP9//3//f/9/euQC5AR8mHqnWjJZAIAAgACAAICjPI07/3//f/9//381c/Zx AIAAgACAAIAAgACA/3//f/9//38nrsutubJgsq+YOpgAgACAUdCaz8iraauKjBWM AIAAgACAAIBZHIgb/3//f+5+qX17RHtDCyQeI5TSzdEAgACAAIAAgGwfgh5+kCmQ AIAAgO+flp//f/9//3//f/9//39HfQd83LY7tgCAAID5AEUAFTyyOgCAAIAAgACA rwq7Cf58c3v/f/9//3//fwCAAIAAgACAKoHxgLO1IbXsQcxA/3//f/9//3//f/9/ 7vY99l3GAcbTFy8X0Ld0twCAAIBEEY0Qh21ObFZPIU7/f/9//3//f92PaI8AgACA AIAAgACAAIDLT6VO/3//f/9//3//f/9/edvU2gCAAIAAgACAOe5v7awP4g4oPyE+ /3//f/9//3//f/9/0grLCQCAAIAAgACAAIAAgDoLbAr/f/9//3//fwJUo1IAgACA AIAAgACAAIAAgACA0gzYC/9//39hQI0/wxWqFG0mWiXBYLRfdmcnZrs0yzPmLfks JRJaEZ/xHfHpPfI8DRwZGwCAAIBl6afo/3+DfxxEFUNmew16p1iNVwCAAIAAgACA juvm6nG3D7deF3QW/3//fw7ieuEAgACAEJLBkQCAAIA5kwaTqB/bHkBlF2T/f9h/ 1F6nXaLEX8QAgACA3/xL/P9//3/HQ8BCij1qPP9//395NlM1KJ+Znm3fyN5vBmIF 7b+Cv8kSzxH/f/9//3//f2fNycwAgACAKLXotBDabNmolUmVrdAl0C48Hju4CfcI YpBikFKQ4I8ZGwkanyCYH13M78v7ODQ4/3//f+g64jl6WHdX/3//f/9//3//f/9/ t0eURvwUHxSOF3gW1uQC5ACAAIDS3jre1mqmaXfR+dAAgACA2YydjACAAIAAgACA YPS/8wIpCyjUCCoIaawHrACAAIAj7ULs/3//fyQ6FDm3qTypjLEtsXzGDsZHPTQ8 /3//f/9//38pXu1cU7HYsITRvdBpOXw4/3//f/9//3//f/9/nGNcYpOxOrG2tXS1 3elh6dXJo8lLFmQVAU70TKDlH+W55CXk7BXpFACAAIAAgACAqfgu+GH58vhMkT+R SRm3GM1GzUXIrzevAIAAgAnnmuYeJEAj0dg52CITSBKgEgUSX6gWqPTuRu4dBl8F rqxfrEwGwQUOf8x9I105XGsruipYE8YSbO8W71/Z19jLrFasRY3cjDHemd2E+236 0dgN2KVfmF7/f/9/JNx82wCAAICl2EzYd40/jYLACsD/f/9//3//f5XWLNY3ODM3 QTpgOUwYnhf/f/9//3//f/9//3//f/9/v2boZX0+tj3/f/9//3//f+QyEzJTTU1M /3//f1l1A3QV6ITnq8RcxF/UytPm0ZHRH/6B/TRREVD/f/9/lUqhSW7q2ul6+sb5 3h8qH3Ierh2dQ6BC1iwGLG78W/sTG08aDa3UrACAAIBP1YHUrbsluwCAAIAAgACA CoLugQCAAIAJ6G7n/3//f/9//3/SDPsLAqK5oQDtb+wbPhE9x8FywQCAAIBanjGe /3//f/9//38zYU9g/3//f/9//3+chNKEAIAAgHqIbYhkQqdBIF4ZXf9//389OGY3 xNR11DkB2gCGmVCZAIAAgACAAIAePBE7/3//f/9//3//f/9//3//f/y3prcAgACA AIAAgACAAIBHyuvJ0Fa8Vf9//3//f/9/J2cnZgCAAIAAgACAAIAAgACAAICuHgce /3//f/9//3//f/9/2LJmsgCAAIAAgACAAIAAgNm5H7leLTss/3//f/9//39vMYsw oq/urniUHZQAgACAAIAAgP9//3//f/9//3//f/9//3//f/9/PXr0eHbEDcQAgACA AIAAgCqynLGl2yDb/3//f/9//3//f/9/HuOZ4gCAAIAAgACAYYhOiAH2c/VRPVQ8 ljjIN7k9gzwYQPg+8JKrks6tY63eNPozAIAAgOHFdsX/f/9/ZBF9EOsNUA3/f/9/ CUXpQxL8kPtPXxNeKt153FA5djhWY/dhl4tIi9k/0z7/f/9/L0Y1RRcJRghBP0s+ A9gw1wm+p72UK7YqDC8cLiMzJjL/f/9/thPvEiud5ZyiHNcbDNJC0QCAAID/f/9/ /3//f2nC4cH/f/9//3//f52LcYubYphh/3//fz/B18BZXz9e/3//f9GtbK32pKSk fDOlMiRo22YNB0YG+f01/QdQ0k6SCeQIed/C3nkjvyLsQglCXVN2UqsHAAeMsT2x wCvmKkdQNE9227va1kDGP/p1p3SfyTTJ8vsu+/9//3+kLXQs4cAzwHdXOFb/f/9/ ahKaEZBUo1P/f/9/jQ+mDhAGPAX/f/9/Avob+XEqwyn/f/9/On/1fTQ8/jqMZFZj xfJD8mLWtNVK+HP36IeTh0bZi9j/f/9/rA0RDbnlNeX/f/9/TkFkQDWKw4lTCY8I d0GaQD64JbjWJtwl/3//fzssOysm65fqB/RD8wCAAIAAgACAK+KQ4fTwPfApHWkc 10S3Q+oGSQZp87vycgR4A/70bfSIF7oWJyUnJM7z+/JdD2AOqkOKQuMY4xfoDxEP CFHxT0A4IDe29+L22REoEYUcxxs27brsqfX+9O8QFRCp+cn4KvGf8HIHtQYF5zjm 8ZnhmTDcnNusxSTFAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACA AIAAgACAAIAAgACAUaHvoGZ8BHv/f/9//3//f/9//38GFiUVR+Kc4Y8cqBtKUydS /3//f/9//3//f/9//3//f2ZjUGIkDU0M6wvuCiojHiKGOM43Z2wba8V6RnmkLXEs odIv0lWk06MAgACAAIAAgGeKQYr2puamvMlHyaoBIgEI9332Xd/l3mfOvM0Yy3rK ENuu2iLpgeh588XyOiSfI+1GLEZANzo21TmvOLMQ6A9k0QLRh7oSul6hbqEaxILD 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 K+TA47biPuK840Hjs+JB4u7dkt2S2knaldtZ233h2ODW5XHlSOUo5eLhfeEu4Zzg BuiN593tTO397oXu0e+i76XvFu9c8f3whvgI+J4BDAGlBwoHfwb6BaEDsQK7BA0E 3gtjCyIUhxMsFsoVwxMbExITmhJrFXcUnhgWGHId/RxNINEf2x5GHq4cxxtpHHsb bx3UHIUfAR/RHvodyhgpGI0RBREFD3oOsBAVEAEMgwvzAzwDbgDT//X7h/sE8ozx 5uhF6D7mzOXp5H3kAd6v3avXSdfK10/Xu9iV2NfTP9NUzuzND9Gz0IzaGto04P7f Kt/C3tnhTeEA7JjrNPaZ9Qv7ZPrD/Sv94wIvAhcINgeJDI8LkRSqE2MemB3CIN4f bBu7GrEYCRiJH9sezyj1J1cnrCbnHTkdtxf5Fs0VIhUSFV4UsBT5E9YSFRIHDHAL sQHmAH377Pqt/DL8tvvA+rz1F/Vv8bjwEO1F7A/pRejK517n/OV65SThkOBm3Srd YNzC2+vdfN3V3kfeUNyr287aKtpZ3RrdHuJn4RjliuQ75cPkw+V35f/ouuie7Bzs QPK48Tf5iviQ+Pj3DfOJ8mP1r/QD/zj+5AZWBqgK9An4ClkKJAyiC4APoA44E3oS ABlVGOocIxyuGeoYQhSjE4QTAhNxFdYUqhUVFRIVsxQSE3cSrw0eDRcIaQeuBQ0F 5AVGBTYDygLG/A/8mffo9oP2+/VQ9Z/0afIg8hbuju3558Dng+Ix4t/fgN9N4Lzf ++Gj4d/ho+Fg3+veEdyi21Da7tlm3C3cJODb3yviyeGX5PjjreZ35nHo/Oeu62Xr HfC471D0wvMV+3f6PwOUAiAHXAYAB0YG5wgUCHYOzw0yFqcVohzkG0Aezh30HI8c 9BtZG54cExwaHm8dJx/kHvQfbx8XHYIchBbsFeIQPhC8DhgO8gxaDIIJ7ghJBccE lP///kr5s/hH9NLzrvFD8UzwCvDd7YXtvehL6IPiROKT4WrheuQ75KDjGONR4bzg +N+v36LfR9+c4FTgsONq43Hp4+jk7Ijskew27ELtDe1W8vTxTvtL+yYEtwOCBg0G CgahBW8JwgjPDkoOFRKEESUUkBNMGsQZQCCVH+sekh4WG1IaZRr9GSAcdRsmGoUZ 4BZFFmEUURMhEaYQZw3YDLIHBAeLAxwDsQJfAnH/9v40+vL52PYX9lb01fN28u7x y/FZ8QTyVvGh7j/upOoy6jzrquoQ7Xjsp+tb65TpP+na6Evox+h76DXo0+cJ6qfp A+577dfuXO7N61vrnulL6eDpi+km7d3ssvEB8Xb03vNw9Q71bfTx83zyI/Kv9FP0 ffsI+4EBAAGhA34DXAWoBE0JjAhjDAEMTQ2ADPIQ/w/WFjgWvhkQGX4a7RkzHWkc wh+uHnYerh2rGsEZ8BdSF5oX4xbcFDgUqRDSD/4MXQxNCZIIRgWCBAkAh/9d+ZD4 kvIR8mzt5+wZ65vqeOq36cPncee54W3h/tx/3Fbev91N4evgs+Fq4YbhCOEY42Hi 1uZu5ojqAOqo7QPt3vJj8sz4OvhU+sb5l/vp+vABWwGJCvEJfRDiD9MRVBFeE9AS ihXZFF4VuhQ4FbMUbhanFU4VkRSjEtYR2RAlEEoPYw5wCxcLkgauBRYFVQTkBUwF DQQgA0L/uv56/SX9OP6U/Uv8tvtq+hL6Avpq+XD5v/iA99j2KvWZ9Gb1+/S292P3 C/em9u7xWfEj7b7s4OuB6wDteOwT7qTtu+6V7hrve+7B7XLtWe3a7CDwuO8H9Y/0 JPlz+A/9lPxFApsBLASoA1wDvgJ1AwkDVgbLBX8I8QdjB7sGQwaLBRcIXwc6Cq8J PQuDCoYM1QsODawMUAusCg0JeQjYCUMJagyyC8wMUwx2DMULHg59DZYPDg92DOUL FAmCCHkHxAaeBhoGuwb3Ba4E7QORAtoBxAAyACX6o/mv8zPzafTb8zH3n/Yk91f2 M/Pe8gDvm+677Vzt1+xl7E/r1+o87KrrT+6Y7Qruoe207Bbs5+x77F/tCe1l7ODr lOwQ7KjwcvC29iH25vo7+of9//wyAY4AYgPXAvADQgP6B2wHoA65DewRKxFRE8YS URWqFFgXqhbdGE8YUhjEFyIWmhUfFr0VqhYGFgYVWxSgET4RCA6JDSQKkgmYBiYG IwWYBN0ClAKH/Tv9xvlR+Yr6C/pR+vz5JPfF9nn0GvSZ8zrzTfLO8UnuKe7X7Ivs 5PB/8Hb09PPR8T3x3e1Z7bvwJvBk+Pv3Pv7Z/XH+/P3s+oP6Ffm5+OL5SvkP/0j+ 8QU8BcgGZgbjAWgBGP2g/Bv7cfqE/RL9AARVA8gHIAeFBPcDev13/Jr7RPukATUB QAi7B2kJ8QgNBosFBgRvA+EFXwVJCNsHcwnbCK8LFwumDSQNRwt/Cs4HNgeoCBcI rAr0CToKqAmSB+cG/QNJA/wAWwCR/+D+9v+B//D+fv6q+z77gPjv9zH2yPWW9CH0 afMw87LyIPL08XLxjPAX8K7tYu3E63Xrvu5Z7rLz+/Jz9MjzAfSZ86X0N/Tb9YP1 evkb+UIAh/+YBAoEbATKA28DsQJcBPcDIwdvBkMLogpHEKwPjRLDEc8Q7A9tDq8N 9Q5dDt8QKxCEEgISahG8EAEMZgszCIUHqAn+CPcJjAmuBRAFUgHdAKf/KP9k/gn+ 0/yK/Hr8+fvM/CX8KPua+gv4lvev9Vf13vRp9Kb1N/WA9hf2Kvav9Uf1v/Rp9Pvz bPP78lbzpfKv9Tr1vPcx96P3Mfdt+Av4evko+Wf4Bfhq+Oj3RfwY/LD/Mv+H/yj/ fv8f/x8BhwB+A/oCLQaVBXYIuAdWCMgHEQljCGANnwy/DwIPiQ62DQsMiQsECUYI uAdAB0MKpQnPC2kLGgqyCVMHvgYdBagEQgOLAk8CjgGxBSkFZgfEBscBHAH8/EX8 Jf+n/mICDAKhAfAAMv/G/gn9h/yH+//6tvxL/C//xv5F/u/9RPv/+k756Pip+A74 AvmZ+L/5ZPmm+CT4bfXr9MvyhvJd88jyf/P78nD1OvUI+cn4evkL+ST3vPbJ91r3 SPvG+sb8evyH/Rz9ugBPAE8FygTRCBQI9AhpCGkHCgc3CcsIvA5RDsMSSBL/EYAR eg/rDusOJA4YD6AOoxAxEP8SfRKsECEQaQvSCvEImAgwCK4HUweeBsgHLQc2BrsF 6gBiANn6evpN+Pj35fmm+dX4Ufgd8/vyefE98eL0ifT19sz2UPaW9Yzy7vEQ8fHw Y/Ye9qD5d/ms9lP2hvbl9Zr7NfvG/pH+eP8y/zwB4wB4AAAAIv+n/s0CpAJyCC0I uApDCmkK2wnkB38HiAQjBLsGIAYRDI8LBQ5wDa8KGgqrAz8D8P97//cDbwOyCk0K 1Qp2Ch0FfwQ8AtQBiAPnAuoDjgN/BscFbAkNCa4FQwW2/Ej8KPuz+kwC7QH3BnIG TwS6Ayj///4S+636s/pa+p3/Xv+IBeEEywVPBen+aP5q9gj2vPQw9KD7avunAhkC xAAyAKD6S/r1+Hf4XvoF+r37kPvc/S/9Mv7j/aD6CPrS+GT4gf0J/UkD2gL3A34D WP/Z/vz7wPug/l7+rgQDBHwJ2whNDAEMcAzxC/EHUAeRA08DQAbOBS4N1Qx9ELYP mQ0ODd4KDgrkCU0JQwmVCN4JQAmcCiEKRgioB3UEDQSbAyADdQMDA4gBKQGd/yL/ pP04/TH5qfgB83byfPIN8iH3+Pa2+VT5cPfy9nP0+PM98wHz3vOS8zr10vTi+Jz4 lPxh/Nn7nfv193337/eZ9+P+aP6SBCAEEwTRA54CEAIpBccESQjLB5wKLQqWDTcN Jw3iDDcKtQkaCLsHdgr+CQUPag4YEHMPLQyfC28H9AZ/BtoFRgiyB+gKfwqpDDoM JwqCCSkEugPXACIAwQFfAeEFdQWIBhMG9gCaAP/6w/rv+bD5YfwI/Bz+l/3v/WH9 Ff2n/Jr8Jfxx+wj7Tvrf+X36KPpB+536o/s1+9n7nfvG/Rz9VP32/Bv7qfqQ+xL7 yfwo/AX8hPsC/Mb7Yf3s/Nb9VP1b/fn8aP7m/WIB9gBlAR8Bw/5o/jj+8/0MAW4A +gNMA4gGMwaoCBoIMwnICNEHTAf0Bk8GFwioBwQLhgq/DRsNqQ9HD+8PkA/yDWoN FwulCp8I9wfbBmwGMwbaBdQGPAbxCF8I4Ql5CTAHogb2AnUCQgHTAEwB0wCEADUA Iv+H/un9Z/13/dn8ufpe+k33+/bI9m32GPey9lr2C/YO97b2w/p9+of8G/z1+YD5 nPc398P6FfrT/3j/LACt/6r9KP1o/gz+tAImAtsGAwayCScJWQq1CUAHwQYjBKQD 7QWbBbILQAuQEO8PzA9tDxoKmQnqBZsF/QZ5BsIKzgnbCwsLvgcgB64BKQFoAOP/ xAMpA6gF/QSkAkwCrf0l/QX7sPpL/Kr7D/87/gMCdQGYAtQBd/se+4z1GvXV9mD2 d/nc+CT5hvj1+4f7l/0r/Wf8yfslALf/oQLgAWIBrQBlArQB6gBIAFj+3P2nAhYC qAX0BOcEeATuBl8G6gViBTkBrQDnBG8EOQebBqsELARTCdgIUwrbCVgBmgCrBPoD uAvICmMHuwZ/CtsJiQ6yDf0BPwEo/Wf8ngTKAzYCZQFfB3wG8hI4EtEJ7gj5/Wv9 fgHHANb8//uN/Az8uwo9CjAIjwed+zH7ZQL5AagF8ASw/Bv8HP2n/A/7sPoU9H/z O/qz+Xv+2f0u+436HP+n/oD6G/o57sftYPLk8bb7W/vD+iv67/2t/Uj/8/6v9VD1 NPXI9Jf/S/8zBMQDGQSkA4sB/ABF/db8AwK6AawKYApUDswNihAuEHAOPg6rCEMI IAnCCGoMQAwLDcwMihAhEPUQVxCiCxcLDgqiCbIKHQqlB18HeQfxBo8IAQgDBXUE ngHwALEAAADd/07/tABrAGX/2f5k+vz52PZg9h30yPPY9UD1S/zf+6T/Cf+K+wX7 GvVt9AHzb/Ll90T3Z/3m/If8Jfw++QL5Mfn/+OL5sPlF/cD8Uwa+BTAIjwcs/3v+ V/ri+dP8O/wyAJH/WQeVBjEOTQ15DKULhQZ1Ba0A/P8J/ZD8AAFuADMJbAhzC68K LQmVCKsFEAXXACwAO/97/k8AwP/HANr/Jf1b/Nz4NPgL+3f6PAahBRsQHg9tDVAM 1ANMA536Hvrl9IP0avqj+a4GywVQCXwIiwPgAqQAsP9O/rD93P0S/eoBUgGxAR8B Pv6E/Rn+Pv3j/Tv9H/6d/RMBjgDK/lH+6Pcx9zf3gPb4+nH6d/3m/AACSAE/BJ4D uv81/wz8oPu6/Gf8K/7Q/b3+Cf4fASIAtAEpAZ4BQgFvBcQE4QlJCXMK0QlsB5gG 8AP9AhMBQgB4AZoAFgUvBPEHPQf9B2wH3QQ8BM0B+QBMAVsA3f5I/g/7h/o4+4r6 hP0S/db8RfzW+tz5Qfhg93P0NPTO83bzAfdE9pb45ffl93P3Dvh69zH4nPf1+mr6 AAAv/2sA0/84/MD7tvgC+AL6O/n5/oH+dQX0BKgIvgeFBcoEJgHqAGgDtAKiBx0H zggXCDAIhQeYBfcEjgEPAcEDIwN8CcUIAQpjCaUGOQbHADwA0/t0+8b+W/4DBWwE 1ARJBFIAwP9r/q39Xv/s/rEBIgGRAr0BBgFlAJT9DP0++sz5rfsu+8oBJgFpBssF LQaoBY4D7QLW/3j/s/wY/JD8JfwpAG7/IwJoAcQBPwG3ABYAiv+6/vb/Mv/XAGsA mgADAMEBPwEvAZEAlvr4+d71N/XJ+i76lAEZAV8BygD/+5D79feQ9y740vfZ+2H7 kQD5/64CXwLQAUUBnf01/ZP7BfvW/kv+OQS+A/oGlQb0BHgERQKhAWsDCQO+B2kH Jwu1CuILFAsECYwI1ARGBJsE/QOVCNEHJApvCSoHkgb9A5UD6gB4ABkAdP9PA9cC bAXnBEUC1wHp/Y39k/vv+kT7w/qw/RX9sP5V/or7Ffuv9zT3evfl9gX6O/l6/O/7 CPzM+9z5Svk++cz4cfsl+xz/0/4DApQBtwBFAAX9h/zv/Q/9FgBY/+MASwCuAwAD KQaSBWUFmwSrBEIE8ASCBIgE8wMHBY4EmAX3BJsDLAObAwkDQgPHAkgA4/+eABkA jgP9AgYCiAGg/mT+oP0r/RL7qfoh+qD5Yf75/X4B6gBb/8P+dPvf+oP49fdL+6n6 AAFPACwDfgJSAZEAe/8M/0X/Uf7jASYBTAZ4BeEFBwW9ATkBFf8+/n7+2f0cAX4A ngX3BP0EdQQyAIH/7/w4/GH8nfv8/WH98wA4AD8Ah/8y/KP77Psx+0j+l/3p/xX/ O/9e/iv8wPsS+k75EvxB+9P/+f5uAKT/xAAJAGgA3f+O/rP9zf4r/nsCGQLdA2sD AwM5AlUDjgKSBP0D1wRVBFwDxAJPAsEBBgJ1AVgDqwK0BRAFfAa4BRMDTAJU/ND7 mfc996D6NPpPAMf/vQH5ABj8o/v09G306/Ij8g75g/hI/63+O/2w/B73ifYH9Inz yPZQ9or92fxlApsB9gFPAWv9yfzp+m36bv7Z/dQELAQ9CI8HPAbeBeAAWAAv/pH9 WAP2AqwMHgxND+sOiQggCBYBhADmAFsAZgbEBQ4LmQqGCQoJHQRvA7T/Vf/m/kv+ awEJAa4FLAXhBmYGHAGhALz6Ifp3+vz5Ff93/ogBHAHT/zX/tvsL+1T6/Pm9/j7+ UgTdA0MGEAaCAxADqv4C/hL+lP2IARwBlQMgA+cCgQIWAqQBugB1AKT/Tv+n/yL/ OADN/6EAmgAJAI7/qv0y/cD9Tv3m/4f/h/8D/xX+fv1Y/eP8mvwy/NP7gPvQ/U79 6gBVAP0CdQI2A8EC3f9u/3r8/PuU/Aj8kf8J/yAFlQQwCnYJxQgNCKED9gIZAoQB 2gRJBAoIZgdJCcsIZgfEBosE7QMpBXUEzgX9BJUFAAVPBuQFjgQKBE7+pP3c+yL7 lwAvADwEQgMcAlgBwP9Y/9z8W/x9+N/3Qfha92H8pvss/07+oP3W/K37yfqm++L6 DPyd+9/6HvpU+bn4OPu8+jX/pP6hASIBiAHmAFgAw/+RAMr/vQBLAIQApP9FAIH/ 9gEJAcoDAwNfBAAEkgT3A6QEMwTXA2IDHAKeATIA1v9lAAYAXAOkAhkEfgPXAGsA bv0Y/Wf8H/wo/dD8Ev+k/h8AtP9e/cn8Ufrc+ar7SPtb/br8p/0y/V7+Cf6K/Ev8 +/hn+Dv5rPiq/TL9vQD8/8oAHAC9/xL/Qv7D/RL+kf3//lX+ewHmAMcDzQI8AnEB SwB7/ykBpAA/AngB4AE8AXEA8/8S/3f+SP/8/ub/bv9I/cn8D/yE++D/jv9YA8oC +QCnAL38PvxO+p35Evu8+l7/5v4QA5gCIwOrAk8A5v8C/of9Cf1x/L3+Mv7gAj8C BgR1Ax8BhADm/n7+S/8G/z8BrQCkA+cCDQRlA08A8P/j/Jr8fv4i/tQBYgHzASYB 2v8l/wn9yfx9+S759fg6+Bv8ivuz/Sj90/tR+5b5CPmT+O/3CPiT95b5K/ln+9P6 R/qp+fL3XfdK+A74qvwr/LQB+QDnAkwCOADT/63+Ev5h/wz/wQIJArUGMAb3CH8I XwiyB2IFuwSxAwkDPAalBdgJJwnbCJUI1wYzBlwGuAV4BbcEugP2AkIEqANDBaEE YgP6AlgB7QDXAF4A8wG3AW8D+gIJAlUBEv53/cn7S/vc+5D7yfte+wL8evsS/nf9 sP4Z/pr8s/up+hX6DPxb+0v+4/2w/yj/tAA/AKoAJQDt/zL/4P84/+oC7QGIBPcD 5wI/Al4A4P9S/3H+sP/A/t0BVQGRAykDqwJYAk8Aof8C/m79kf3c/Pb/SP/gAp4C iAHXAPn8Qfw0+uX5ufsi++3/Qv8JApEBVQDz/0H97/wu/Nb7pP7m/YsCFgLOBKEE 8wNVA3gBOQE1ALf/WAHNAOcETAQqCLIHQwjRB1wEsQPt/6T/8wB+ANcFlQXnBoIG IwKbAYH/bv/D/1v/Uf7N/Y396fyt/y//JQB7/5D7Evuj+Ff4OPrD+YT8Jfxh/s39 gf4C/kH9Bf13/O/76fum+/b8jfya/xX/RQK9AYUCFgI8AW4ApwA/AK4CYgKRAwAD hQJFAiMEXAPHBQcFvgRMBIUEEATtBU8FqwU5BcQDMwPNAUwB4AA1ALcA8//d/0v/ Pv7A/XH8/Pv8+z77Nfu8+lr6GPoS+qb54vmN+Qv6oPmN+hX6evoY+hX60vk4+uz5 5vt3+4f9HP0P/cn8MvzQ+9n9bv0ZALD/PAGXAAwCaAG0AjIC4AJPAsoCRQKLAv0B cgMNA3wF3QTRBDkEcgK0AS8BgQAJAkwBFgN+AkUDiALXAjYCewHQAPz+Yf50/uP9 1wAsAFICtAHa/1L/mvwF/Dv80PuQ/Pn7nfwS/Ob+dP4fAaQAzf9x/zj+nf0c/6f+ VQEGAU8D7QIDAoEBa/4J/lj/jv76AlUCcgTBA5EDzQIWAlIBiv8M/9b9HP2H/un9 KP+O/jj+S/3f/If8d/u5+ij6cPkC+236avv1+p36z/kY+Zn4CPg994P3G/dO+tn5 sP0v/cP9Jf0r/F77Ev2H/JT/9v4lAHv/ngAAAKECEwLUAk8CkQEMAXICzQEdBaEE Mwd/BlkH5AaCB+4GOQeSBu4GfAYgB4IG2whACKIJFwmuBi0GpwIyAksA2v+h/yj/ EgCE//AASwCHACUA3f6w/sn8Z/wV+4r6l/sb+2v9vfzc/W79yfxh/Ev9s/zA/UH9 Jf7g/Tv/1v6B//b+8P5+/lH+0P3D/hX+twASACkDvgIsA44C0wCHAD8AwP/tAKcA JgGaAEICqgGbAxAD4wFFAe/9SP3y/Gr8nf47/vz/W/8iAJf///6d/jL+uv0F/aD8 Nfy5+4H9Ff0c/sD9vfw7/Hf8/Psv/rb9kf9F/4sAPwB7APD/9v94/8cAHwBJApEB kQMDAwAFtwTkBWkFfwQQBMECawIZAoQBmwPXAhYFlQQsBMQDLAOBAjYDtAI2AqEB Yf/p/un+wP7Q/6T/lP4P/nf94/zJ/VH9KP7m/cP8ffxU+/L6+fuj+5D8IvxO/Aj8 1vyd/IT99vyE/fn8HP7N/XsA2v9+Ae0ASAAGAPb/fv+nASYBewMzA6gDAAPHAUwB of8s/1v/4P4cAZQAxwMsA4sE0QN7AqQB5v5F/h/9XvyR/tz9oQDQ/7QA/P9S/7P+ oPzi+z76yfko+4f6SP6g/Z3+Ev5n+xL7nPjr96n4Qfjm+4D7Xv+K/nT/4/4M/X38 Avua+oD7yfpR/tb9ugEyATMDkQL5/z//PvxR+6f9/PwDAz8CkgXUBNQDIAPXADIA WP7J/dD+KP4JAngBggTtA6sCPAJV//n+5vx3/Jr9Mv1uAK3/MgGeACX/h/7W/DX8 4vt3+2v9yfzm/0L/RQG0AOb/fv9e/Mz7avrW+Rv8nftu/7f+OQF7AGUAe//W/iX+ Pv3D/MD8DPzp/UH9Zf/z/uP/dP8s/93+O/6K/QL+VP2z/vP9Cf9+/of///7w/yL/ SP6H/cb8Mvyt/RL9Ev9+/lj+tv3m/JD88vuA+xX6dPlE+tn5//2z/dcAhAAf/4T+ mvsx+9b7W/vj/ij+VQCh/7EAGQCBAfkAxwEiAbcAAADwAGsA2gIDArQD7QKuAvYB 0wApAJoAAwC6AhkCcgTEA4IDqwLnAgwCHAORAsEB8wAvAFj/5gB1AOYBSAGhAOb/ +f8o/3UAvf/z/x//D/9O/rD+zf0+/of9OP50/dz8cfyg/CL8fv3f/HH9D/0C/Ff7 bft0+hv8h/ua/Ob7qvwr/K39Jf3g/zX/QgGhADwAl//5/kj+5v4y/vP+a/5VAND/ hQLzAVUC5gEPAI7/lP8J/3gA0P/dAO3/vQAvAL3/6f4V/of90P4i/tcAMgA1AdMA HAFxAE8A0/8+/tn90/wF/Bn/Qv7QAQYBKQGtAH7/Bv9I/3T+xv0M/Xf82fvD/hz+ 8wFFAUgBmgA4/63+L/+B/vn/O/+nAN3/JgG3APMBYgGqAeAA8ABPAEwBZQC0AvYB cgPnAqEB6gBO/5H+9v50/pQAAABfAaEAYgG9AH4BtADW/xz/rf0r/Zf9K/0f/qr9 Ev53/VH9s/zG/E78qvzy+3T9yfwV/5r+FgB4/17/qv7j/mT+fv7G/eb+Nf5VAZEA 8wNlAxwDkQL8/2j/x/9S/4QB4wDqAGsAAAGUAK4CEwIyAacAMv7D/S//wP5lAYsA GQF1AC//t/7y/If8//uX+wL8evuN/eb8sP4G/mv95vzy+lT6JPnP+FT6AvrD/Dv8 Z/0M/Xf8/Psy/Kb7uftB+5f7KPvA/R/98P+U/0j/vf4V/X38KP7T/c0BZQF1AwAD wQI2Al8C8wEJA1sC6gMsA7QEAASIBaEESQSOA2UBpADZ/iv+8P5b/vYAaAD5ADgA jv7N/WH9p/wS/of9Xv22/Nb7GPtb/Nz7l/3M/FT8wPuz+z77iv01/Vj/uv5V/rb9 7Px6/Mn8KPy6/Uj96f5o/tP/Nf8MAFj/cQDm/4gBBgHmAT8BjgDW/3v/w/5L/+z+ 0P5R/pH/vf7QAH4AKQBu/3H91vz8+2r73Pso+z795vz//oH+Rf6g/S77z/p6+tL5 Ufy5+3T+7/1r/un9jfzy+wX7S/oi/HH7LP/D/jIBiwDmAVIBOQGLABn/Xv4M/6D+ 4AJPAssFIAUTBI4DhwAlAND/Iv8WAboAEANSArQCGQKkAeoAGf+K/mr8JfwC/VT8 Jf+X/pQACQC3/kv+OPu5+v/5gPl3/Mz7Pv6U/SX9sPw4+8b66fqK+pD7Ivun/S/9 QgCw/24A1v+R/Sv9oPs1+2H95vz8AHsA5wJCAvkBYgEDALT/pP8y//MAYgDgAk8C 6gMWAxYCtAHW/3T/0/90/+MBawFJA5QC7QFSAfP+mv4S/br8w/xu/ND9h/1h//z+ Jf/W/or9+fxb/fn8ZP4J/qD+O/4r/tP94/5b/or/HP/g/zj/p/8f/1X/3f4G/3T+ KP+g/sP+Mv4c/3H+9v9o/1IAwP93/hz+yfwM/A/+O/0PAGX/tP9F/8P9cf10/Q/9 Uf72/Q//s/4i/9n+mv4J/of9Tv3W/J38Ff5+/b3/Rf97APP/FgCt/2j/A/8J/5f+ Nf/w/pcAMgAMAX4A8P97//b+W/5e/83+dQAcAE8BAAGxALEAaP8P/6r+ZP4J/9P+ NQCk/wkBsQBiAbcAHACn/1v/Ev/g/zL/4ABVALEASwBx/wz/rf5V/g//dP5O/7D+ KP8P/w//t/6g/jv+H/6K/QL9gfzs/GT8DP5h/SX+qv1I/b38zf1B/VX+8/16/Rj9 mvte+3H7Avvy/Kf8kf5C/or+bv5r/ub93P01/WT96fyX/UX9w/4+/pf/yv63/zL/ EgCU/27/L/90/93+9v+q/7EAUgBiAPb/Xv/j/gkAXv9iAQMBTwLwATIC0AGuATwB yv8//3v+K/7m/oT+ngASAMAAaABiAO3/bv/2/sb9ZP3c/Dj8CPyN+1v89fte/dn8 vf4+/or+Bv4r/Q/9bvz8+7P8OPwf/sP9uv5o/gn+zf0f/af8Xv0V/fP+d/4sAcoA oQFlATUApP8J/n79Bv5e/YsAHwA5AvkB+QFIAdD+Nf4f/Mb7s/w1/Dj/vf51AC8A 4P5b/qD7KPs7+tz53PyN/F4ASACkAEsA5v3D/WH79fpX+hX6HP16/DUBjgCLAscB of8y/y78xvtx+8z6yf1R/UIBpwA8AfYANf+O/kX+2f2X/07/EAKeAe0DbwMcA7QC kf/p/nr8VPwl/tz9jgEMAVsBMgEG/4T+Mv3//I38Ffxe/MP7cf04/cD+Iv5F/cn8 CPt9+vz6gPpI/fL8Iv/Z/nT+HP4f/dD8Iv2X/PP9oP2h/wb/aAD5/xkBhAChATUB RQHjABkBlwAWAZoAHwG0AJEBMgH6AsQCTAPdAtABTAFiAPn/8/9o/9D/a/+U/1L/ //53/rD9Ff3m/Dj8UfzT+zj82fvG/Bj8qvzv+4D62fkL+H33WvnV+D79yfxY/rb9 TvzA+1H7ffpk+6P6oPsb+8D9OP3zAFIAlwAyAD79vfz/+337dP4v/iYB1wC6ARwB vQAfACwAuv9VAM3/wABSAF8BzQAfAZcAa/8f/+b8ZPzW+5f7uv1U/Wv/0P7z/hz+ OP2d/GH82fvp/Az84/2g/VX/dP41/27+cf62/T7+Yf1+/53+LwCH/3gA0/8mAYcA WwHXAAABUgBiAccAfgEfAbEBLwFrAQwBLAHtAG4B4wD5AW4BSAHQAAP/hP5b/tb9 LP+a/uD+WP7m/VT9a/0S/br8Z/xO+w/73PpO+rD7VPv8+5f77/qK+k77w/pF/Jf7 7/uK+2r71voF+2f6HvuQ+qr8Qfz5/r3+l////i//mv57/9n+0/9e/yIAsP8DAcQA ZQHgADwAjv/N/27/rQAlAFUBxwDwAEgArf8//1j+Bv6a/Xr9wP5F/vb/fv8DAJ3/ Uf7N/d/7nfuw+1v73P2E/aT/LP+K/gb+oPwY/HT80/tU/b38lP4V/nsA4P8mAbEA e//w/nr9GP2E/gL+ugBCAHsB/ADmAEUAhP8S/9n+Av5r/6f+RQGkAEwBlAB7//n+ w/4l/iL/WP4yAN3/ngEiAR8BqgBI/tD9evvi+s/6WvrM+4T72fw7/ND9cf3z/Y39 XvwI/E776fpu/O/7xv0+/ez9iv3A/tz90P5x/jL+sP3g/hz+AACK/+P/of8s/47+ 2f47/vb+p/6t/1j/bgDm/5QA4P9o/xL/jf1b/WT89fvf/EH8dP8G/x8A4P8+/dz8 w/pU+lf7Bfua/T79Cf+g/uz+hP5x/Qz9UfsF+4D7Ivvj/Zf9jgAPADUB6gDN/07/ cf0c/RL90Pzt/9r/PwIsAnEBJgEv/8D+vf5e/ub/Uv9iAeYASQIMAiYBygCX/g/+ tv1r/Yr/LP+9ATIBOQKnAbD/L/+H+yj7R/rp+cz8dPxl/+n+kf/s/mH+Av4V/dD8 ZPvM+qP7Ffuw/gn+WwDj/0v+H/5B+8P6w/pO+u/93P3mAGUASwDN/+z8qvzc+p36 W/vc+lH9HP3Q/2j/qgAWAGv+2f2a+iv6VPr/+Xr9K/20/1L/D/+g/sD8SPzs+lT6 Avug+p39d/3s/rr+2f16/fL8h/wo/en86f53/uYAiwB1AvMBmwFFAaT/Zf/s/j7+ Bv+R/hkAvf+IAVsBZQLEAbcAOAAM/6D+LACH/2IBrQCRAOP/Vf/G/v/9mv1+/f/8 zf1B/bD+Mv4l/7r+rf0o/fn7VPt9+yj7G/yT+6P8D/w4/fb8D/7D/fn9s/1L/br8 KPyw+1T8+fu9/Vj9SP/Q/rD/Ff+a/ij+WP0r/Vv9mvyX/k7+AwDD/7T/Rf9r/QL9 AvuK+tP6evpY/f/8MgCX/5T/1v7m+4T7xvhz+H35Ifmq/GH8WP/z/jX/s/7m/BL8 0/pn+jX83/sl//n+WwDT/3H/4/4+/e/8mvwi/Ej+wP1YAQABMwOkAl8B/AAC/o39 SP3G/H4A9v+xA1gDqAMQAxYAp//M/Fv8k/tE+7r9O/01AK3/XgC9/wL+fv34+lT6 oPo0+jj9/Pwl/63+W/75/Zf8Ivz4+rP6jfso+5r9Qf2B/yL/nf8y/1j9H/3f+537 nf1I/RwBWADUAYQBcQAiAGj/D/9l/0L/6f+a/4sAVQDHAEIAKQCa/6D+Vf4l/sb9 OP7p/VH+lP01/ZT83Pt3+8D7RPt9/Az8lP0S/cn9Uf0P/cD8G/z8+w/86fu2/Wf9 kf5L/qD9WP0r/Oz73Pt9+6397PyU//z+GQCw/7r/LP+E/+D+Rf/G/kL/w/6h/yj/ hP9L/93+mv5o/u/9w/5r/nUA/P+HACIAs/5o/ij+l/17/lX+1v57/uD+gf6U/0j/ kf9o/8P9rf07/bP8ZP72/Wv/H//W/lX+HP6n/cb+W/4JAEj/LACE/7r/SP+U/yL/ PADW/xkBeADXACkAPwDQ/wAAp/8y/+n+0P6H/tD/DP8ZAKr/Qv+B/un9SP3J/Sv9 qv75/XT//P54//z+oP1U/Qj8nfsi/K37s/1F/VH+0/38/Lb8vPpt+jv6nflq/Aj8 h/5R/qf+Rf5k/Rj9BfyA+177D/t0/Cj8OP8D//n/rf+N/QL9jfsi+8P8gfzZ/rP+ t/9l/wAAgf+9/2j/yv5h/vD+jv7aAF4AAALHASYC9gHdAGIAW//g/sD/Tv/BAXUB UgIDAvkAsQCO/y//wP6R/nT+Iv6t/kX+sP9I/1IAzf9u/5T+Qv4P/h/+//3//ar9 w/1r/UL+6f1Y/g/+h/0v/en8w/xh/Tj9jv4r/qH/Qv/z/6f/uv9l//P+mv6O/l7+ bv/p/jUADAAZACUAK/7//Y38Z/y6/ZT9pP9h/17/Ev8c/tb9K/wF/KD6VPpk+wj7 4P2n/Rz/4/41/Rz9Z/qH+pn5evn/+u/6Xv1B/VX+L/4Y/db80/t0+wX8+fuB/U79 Vf8v/+MAkQBiAAAA0/29/Yf9rf1VAAMALALEAVsBBgHa/63//P66/qD+e/6K/17/ LwGxAFgB+QDT/5H/7P63/pr/O/8J/wz/Qv4c/vL8rfzM+4T7+fud+739Tv23/jX+ sP16/SL8ufsb+9/63P1u/QkBvQAAAH7/KP3G/KT9Iv0AAHj/ngAiAGsAMgDEAGgA DP97/qT9cf2d/xX/wQFFAXUBIgHG/jX+cfz/+1T9DP08AMD/iAEyAUX/s/5E+xj7 d/ku+Xr6JfoC/af8P/+n/uD9cf1q+jT6Lvkb+aD7VPuU/jL+e/8l/07+//3i+5P7 h/oL+qP8YfzAAE8APAEGAY7+O/7D/GH8Ff7D/fAAmgBJA9QCrgJPAvz+d/41/ND7 s/xX/E7/2f5CAb0AxABCAOP9Yf2E+yj7GPzZ+0X/yv4WAJ3/l/5b/uP8VPyQ/BX8 OP4J/h8AGQDzAMQAfv8c/2T+Ev5h/xX/sQBiABMCoQGbAi8CbgH5AOP/mv9C/x// SP8D/14Avf/HAWIBtAFfAe3/dP/A/mH+sP4P/vz9iv1F/q391v8f/93/L//v/XH9 JfzQ+6D8//v5/Ir8ev3m/Gv++f2E/Rj9PvvZ+rb6V/rT/H38mv4f/s3+WP62/UX9 wPxq/HT9GP0l/6r+aADz/3T/+f6k/TX9ZPwY/Cj9mvwP/53+/ACUAOD/of/2/Kr8 S/z/+2f9S/0G/2H+h/8Z/1X+w/04/LP70/pq+rD8ivz5/27/5gCkAFX/yv75/IH8 8vyK/Kr/Gf9FAtQBPwLQAY4ALwAc/73+0/41/iwAgf+uAW4BngHQAN3+pP6d/UX9 Bv5k/Xf+Bv5I/8D+Nf+6/hL+s/1L/ZD8Xv3f/Gj+9v0l/pT9wPwu/DL80/th/fn8 WP4C/vb9l/1O/Rz9//yq/H79H/2t/ij+7f8//+AAPwAJALD/0/04/QX9s/y6/mj+ BgDa//b+WP5L/bb8a/3v/DX+yf0v/8r+vf8v/5r/0/4P/of9hPzv+0H9DP3w/rf+ Tv+k/pf8cfyt+kv6h/si+5f9Nf2O/kj+Tv7T/aD9mv38/Lb8Uf0c/af/bv+qAXEB 4ABCAGv+5v16/TX9Qv/p/scBMgF+AsQBawAsACL+sP0f/vP98P+X/ykBBgGnAXUB eADg//n9h/1Y/fL8Nf4Z/gz/wP7G/nT+Rf7m/TL9p/xF/Nz7vf32/LD/Rf9PAM3/ hP4S/s39Pv3z/tn+HAC6/xkAof+w/0X/6f9u/zj/0P4c/pT9pP4l/iIAuv9FAA8A l/8y//D/Xv8ZAHj/gf8M/5r/Gf9V//b+ZP4o/lH9//z8/Hf8ZP32/MD9sP2n/Uj9 mvxI/L37Lvtq+w/7nftB+0j8tvtO/bb87/2g/db9+fw1/cb8O/32/FH+tv23/kX+ 4P5V/g//cf7z/oH+8/5V/tP/Vf9PAfMAPwHmABkAp//H/17/jgAWAAkBngBlAc0A AAJ7AYEBAwGt/zL/e/4P/kj/s/6EAG4Avf9e/63+K/47/uz9kf4S/vz+gf5l///+ kf9L/3T+Cf5B/Z385vxL/Nn9lP2B/1L/AwCt/8D/Xv/s/m7+xv5Y/mj/Ff9xADUA 9gDdAAABxwCxAG4Arf+t/83/cf9IAOn/cQAZAA//4/6U/U79h/xO/IT88vvZ/EX8 W/3f/HH95vzy+5r7ZPvp+lv7Avvi+437V/zf+5f8FfwS/Zf8Rf3J/Pb8ZPzc/J38 KP66/eb+aP4v/+D+CQB7/x8Ap//p/4f/DADH/4gB8wC6ASkB2gBPANb/cf+3AFsA qgEvASkB3QADAKr/pP9b/83/Uv9b/7r+4P5k/s3/Yf8cAKH/gf4Z/hz98vwZ/q39 vf5O/h/+sP3z/aD9e/4C/lX+yf0i/o39Ev9o/o4AEgBoAPD/nf9L/2j/5v4WAMr/ LwGhAPABNQHBASYBygBeAOz+sP5h/tn90P9r/wABeAB+AOP/Cf6q/cn8//vZ/JD8 vf1b/Xf91vzf/Ev8bvwb/Jr78vqN+wX7s/wu/CX9qvzs/Fv81vxX/L38EvzJ/DX8 sP3s/BX+W/3v/R/9uv4P/s3/Iv+9/2X/4/9+/+D/hP+K/iX+DP6d/cr/Rf/zAHgA DwCk/9D/9v4vAJr/+f6n/rb9h/2E/gn+Tv/5/rP+Ev7Z/UX9Tv72/cP+S/5V/un9 Pv6N/Vv+5v2B/g/+Uv9x/pr/H/8lANr/ZQDH/27/3f7A/jj+Rf/g/s3/O/9L/6r+ jv8M/wMBtABbAd0ArQBVAB8Aiv+6/1j/gf7A/YT9GP2q/lj+DwCh/17/Ev+w/Sv9 evzp++n7Yftn/DX8Rf0P/fb91v13/i/+6f2z/Qj8qvs1+yX7l/0+/Vv+Cf6U/WT9 5v16/d3+Rf4P/rP9Bv6k/UX/3f4V/xz/Ff7Q/fn9qv1u/wn/nf9+/5r+lP7s/UH9 6fyz/Dj93PxI/tn9vf81/wkAtP9u///+ZP4G/kj+4P1+/zj/hwAAADwAmv+H/xX/ qv8Z/4f/Bv/N/0X/8wBoACIBugCt/1X/Uv84/+ABpAEZA80CDwHaAL3+ZP4C/mf9 dP4+/hIAuv91AfwACQGRAP/+fv5F/CX88vuN+3v+Jf6HABIAkf9O/3v+Bv41/uz9 8/5u/k7/wP7A/1v/L//G/rb9l/1k/eb8e/5I/mgAKQC3ACwApP6K/sn8h/z8/Hf8 P//2/qoBgQHQAIQAuv1h/WH8w/vf+6P7Iv3A/N3+Uf72/37/Vf7s/d/7Tvvy+3f7 0/29/Vv/+f7w/oH+SP7s/XT9Yf3s/TL9P//A/q0A0P/N/1L/cf4G/vn9ZP2t/yz/ RQKqAZ4CVQKhAHUA0/6K/iL+5v2U/pT+6gCOAJgCJgIPAYcADP7J/dP8jfzj/WH9 rf5k/lX+yf2B/B/8gPtL+538SPwi/73+x/+O/yX+5v1b/Cv8SPz/+2H9L/0ZAEL/ ewE8AV4AIgDv/Y39O/wf/JH9Iv20/0j/8wCeAG4A6f8D/7r+h/47/kj/8/6k/zL/ kf53/rP9Xv3f/Hf8Bf2w/MD9nf0c/tP9W/32/Bv8l/tL+yX7dPtB+5r8Nfw+/ez8 9vyq/HT8Avy9/FH8Tv1F/TL+5v2z/qT+4P6R/or+Qv5R/jX+4/6B/qr/OP+3AHEA mgBiAI4ASAD8AIEADwG0ABYA4/9o//D+h/8v/5H/HP+R/gb+6f1u/ZH+Vf7//nT+ qv1r/eb8d/wv/dz8/P3Q/dD+e/6X/0X/DwB4/27/Iv/p/pr+DP+X/ub/wP9xAeoA kQH8AJQAZQD5/4r/LwDW/9cASABuAAwALwDK/9r/Vf8s/83+pP9F/1gA/P8WAHH/ 4/2a/dD8ZPxr/dn81v1e/Yr+Gf6q/kX+lP0J/VH76fqt+n36qvx6/Dj+D/63/mH+ Mv0c/SL8Avwi/fb8l/5k/n7/Iv/Z/qf+p/2t/VT94/w1/tz91wCUAG4CHALjAKcA Yf4P/q39VP0l/5r+iwBPAMcASwD2/qf+wPyQ/Cv80/vv/N/8h/4G/pf/aP+k/qD+ a/1U/cb9d/1h/0j/twCLAGgAGQA7//n+bv78/eb+Tv5FALr/+QFVAXUB8ADA/0X/ Gf9h/t3/Tv+3AC8A5gB4AC8Ajv90/hX+uvxe/Ej9Av2a/zL/0ABoAAMAnf8S/rD9 zPx9/On8oPzc/Xf9mv5Y/i//yv5u/wz/Xv4c/iX9zPxh/Qz9lP5L/uD+kf7G/Y39 iv0P/dD9Xv1u/k7+aP+6/m7/Gf97//D+Pv7g/Rz93Py9/Wf9yv9S/0sAw/9O//n+ hP7g/Qz9ivzp+4T7uvw4/Dj+8/0v/3v+oP2E/Zf8Tvxb/Q/9Xv44/lL/5v7K/7f/ 0/+H//D+p/69/m7+RQDw/6cBSAHEANcAbv8y/yj/sP57/y//OADQ/0gAHABF/+b+ mv16/VT93PxY/vn95v+K/zwB5gAiAOb/K/3v/AX8qvth/Sv9jv87/z8AEgC9/3v/ Bv/A/uz9vf3z/Zf9Jf/Z/rcAewB7ADIAvf5R/hX+p/2a/kv+nf90/yUA8P/m/0v/ oP5L/qD9h/3s/aT9iv9u/70AcQCO/zL/KP0C/Vf89fvZ/I381v07/SX+7P10/kL+ 6f2g/YT83/s1/Mz7p/13/f/+nf5b/vb9ZP3v/On8kPzs/YH92f5r/pH//P6H/0L/ pP84//z+bv4M/7D+SAAGAOAApwBYAOD/KP8G/8r+h/7G/tP+OP8M//z/4P+w/5T/ Qv4f/jL9Ff3//cD9Bv/z/o7/Zf+d/zj/7P6g/hX+7/2O/iv+of9b/5QATwBxACIA of9I/5H+Pv53/hz+rf8o/0IAAwCH/3T/xv6H/oH+bv44/+z+1v+H/xwA0P9r/wz/ 0P2g/Yr9rf2n/hL+4P6g/kL+wP0S/cb8KP2z/M39hP2U/hz+gf4M/mT9Rf3j/Hr8 ivwy/C/9qvw4/uD9/P2z/b38ffxe/PL7/P2N/YH/Iv9u//z+Tv7j/Xr97PxU/dP8 a/7W/UUAkf8iAL3/kf44/jX+wP13/h/+/P7W/jj//P4v/63+iv47/gz+7P3K/nf+ W//w/un/Vf/2/7f/t/5Y/oH9VP1R/un9CQCR/0sA3f9C/+b+8P53/tD+WP7Z/mT+ of8V/73/Yf///nH+bv7s/Tv+yf2t/jL+t/8//2X/H/+g/kL+Iv6n/X7+8/07/4T+ e//j/r3/fv+q/1X/qv5R/iX+yf1F/sn9Gf7p/R/+yf1o/gL+OP7p/br9KP3Z/W79 kf41/lL/Iv+X//b+zf4+/of9OP2k/Vv9Ff7//af+Uf7W/pf+Av7G/Z38W/wP/ND7 SP0l/TL/Gf9V/xn/6f3N/TL95vwC/e/8w/2q/XT/DP81AMP/Bv/G/qf9OP2t/Wv9 hP5V/jj/Ff9o/xz/w/6K/vP9hP0Z/ub94P97/8QAWAD8/1L/l/4M/s39h/1I/sP9 e//2/jwAmv9F/93+Ev7A/fP9S/23/lH+RQDH/0UBpABPAOn/wP5h/nf+//2E//D+ aADp/4sA9v9x/yj/lP4M/qD+Uf54/w//+f+E/+n/p/9S//n+jv4v/oH+D/5l/x// WwDz/53/aP9F/hz+kf1u/cb9l/0v/rb9oP5I/kv+6f1+/QL9nfw+/IH8O/zA/WT9 gf4f/l7+Gf6a/YH9/Pzv/Gv9DP1o/vP9kf0o/bD8YfyH/dP8Pv6z/ZH+OP7z/mH+ 0/5V/l79H/3s/If8ev32/EX+/P23/kL+Nf78/Vv9/Pz//Hr8cf0F/RX+jf3Q/jL+ 7P5+/q3+Pv5V/uD99v5+/oH///5Y/9n+Bv+O/nT/5v6d/zj/fv8l/53/Qv97/6T+ sP7//Qz/a/6H/xX/L/+k/iz/s/6k/17/W//8/ub+l/5C/6r+hP8P/xL/pP5b/vn9 7/2K/Z39D/3W/FH88vyN/Kr9HP3D/VT9Tv7T/Wj+H/6t/W79Qf3M/OP9xv3s/dP9 a/1I/Yr9Xv2X/nf+D//A/lv+DP66/Wf9cf0S/YH9KP0r/p39Pv7//br+Mv7Z/m7+ OP7G/R/93Pz//Kr8K/6n/UL+vf2d/Tj9Av4C/pT+Iv6B/g/+WP7j/V7+Av5e/9n+ 8P9C/8r/Rf/a/0v/IgDH/8D/kf8//+D+A/+9/rD/Zf9IAO3/mgBPAOYAqgATAboA awC6/4T/DP/K/3H//P+q/xYAvf/j/73/qv9C/xn/vf5e/gn+Pv4M/ij+H/53/UH9 S/0r/eD9vf13/m7+lP4y/or+L/7//YT9gf0l/TX+pP3W/nH+fv4l/kL+Ff7s/cD9 4/1+/XH+9v2B/xn/bv84/1H+H/4J/cP8Tv3p/PP9jf1V/iX+Pv7p/WT93/y2/GH8 ivzf+9D8S/ya/Dj8Yfzi+2f8KPyz/Fv8K/0P/Yr9Rf2t/TX9W/07/Z39Mv10/UX9 rf1x/YH+8/0S/4H++f50/sb+fv5C/93+rf8M/6T/Tv9VAMr/hAApAPz/fv8o/5r+ O//w/pf/Gf94/wP/DP+d/pT+SP5u/un9Uf4V/pf+SP50///+aP9S/wz+uv19/Fv8 Yf3y/HH/vf7W/zv/t/5Y/tD9pP10/vn9aP4y/rr+9v04/7r+S/8S/7f+Ev6z/WH9 lP7v/bf/of/A/zj/Uf7W/Uj9yfwP/b381v1b/R/+mv3//XT9Tv3A/Ej86fvG+z77 RfyT+4f90/wP/oT9Ev19/C78rfsM/LD7d/xI/AX9zPxL/fb8Xv0c/YT91vxx/f/8 Tv7J/XT/6f50/wP/s/5Y/lX+//2R/i/+Uv/5/kIA0P8PAGX/1v5e/rb9Rf2H/SL9 xv47/lv/4P5x/93+s/4M/gz+3P0i/rD9wP44/mv/0/41/6r+Xv7g/VX+Ev7w/oH+ Zf/T/of/Mv/N/lj+9v2H/en9h/3A/hX+DP+t/hL/0/4M/9P+zf7A/lH+H/4+/hz+ zf5R/gb/kf7d/kj+s/5C/s3+Vf4G/lH9Qf3D/Fv9/Pzs/Vj93P1e/WH9K/3J/YH9 lP1O/Xr9D/1+/QX9nf04/ar9KP1O/Z38iv38/Az+iv1R/ub9Iv7N/TL+Ev5h/jj+ Iv7m/f/9nf2w/hz+LP+6/vD+6f5x/hn+Jf7Q/Vv+//0J/qr9fv75/Tj+2f0+/q39 SP72/Rn+zf07/tP97P6K/i//4P6U/jL+vf50/qT/KP/z/37/4P6X/rr+OP69/1v/ FgDK/x8Avf/5/4T/tP8v/2H/xv5S/5r+dP8G/93/cf/T/zj/Jf+n/r3+Gf4r/tb9 yf10/eb9L/2a/R/9Gf6z/VX+yf0C/kH9Yf3c/EX98vx3/QX9//2X/Sz/dP5I/4r+ OP6w/WH99vzc/HT8l/32/LD+aP63/oH+Ev6E/cP8d/yt/JD8Av6g/br+S/5O/tb9 lPyE/I37KPtb/Pn7cf01/Sv+sP1F/Rz9K/z/+zX7O/ua+x770/yg/On9kf2H/S/9 H/zi+178H/yq/SX9Pv7c/Wv+K/4c/q39Mv3W/Cv97Pxu/jj++f9Y/5T/OP9+/kL+ Bv6U/Uv+mv0y//P+gQDd/14A4P+U/0j/lP5R/tn9fv1x/iL+wP9r/4T/Cf/g/Wv9 Qf3D/Bn+h/0c/73+bv8V/7P+Nf5F/fz8ivwF/K38Nfzz/YH9A/+d/vz+nf5V/uz9 SP38/Hr9GP3z/Yf9Cf7D/Q/+pP3m/bP9Jf7J/RL+zf1h/jj+yf2X/a38Pvya/E78 l/1L/Q/+tv0G/kj99v1+/Yr99vxh/B/8kPz5+4H93/x+/Sv9Xv0S/SL94/zJ/Jr8 uvx9/If9L/3g/YT9Jf3m/I39H/1e/vP9gf4M/p3+Ff6B/hL+gf4G/tP+Jf5b/+b+ vf9F//n/bv+a/wb/l//8/lL/4/4//73+t/8Z/zv/lP5u/tb9hP4i/kj/7P4o/6f+ h/4f/mj+2f1r/gL+KP6k/VH+Cf4c/+P+h/84/xL/xv66/Wf9Rf3G/Az+l/35/mj+ a/41/pr9h/1r/Rj9Qf0C/cb9Yf01/tP9l/4c/kL+9v0C/l79Iv6R/YH+6f26/j7+ 1v5o/nT+DP6N/QX9uv0V/Vv+7P2q/jj+Ff7c/X79Ff0P/Y38S/3p/CX+mv0y/gL+ bv0i/db8d/x3/Az8nfzs+0v93Px+/gn+DP9+/ij+4/1k/R/9Ev66/TL/yv7T/1v/ bgD8/2UAHABC//P+ZP7v/VH+Av6U/wb/JQCt/+3/bv8G/4T+sP5e/un+p/5h//z+ sP97/73/dP+U/m7+uv1u/W7+L/6H/27/vf9b/2j+yf07/af8WP3v/On9w/3W/k7+ 4/5r/kX+yf2q/SX9lP0V/WH+9v2d/y//mv9r/xz+xv10/fn8iv4v/u3/W//g/1v/ aP+q/uD+WP4o/vP9Mv7N/TL/oP7d/2X/OP/p/kj+yf0+/en85vzM/Kr9Bf38/Yf9 tv01/XT9Cf22/Qz90/1u/Xv+OP7K/kL+0/5+/nH+HP72/W79h/04/dz9kf0G/6T+ eP8V///+qv5u/h/+SP4Z/oH+DP6U/iv+jv4v/sr+h/6X/07/5v+6/3j/2f7K/m7+ 8P6B/uP+jv66/i/+8/6K/o7/W/+k/2v/s/5O/qD9Xv1L/dP8HP2j/EX9kPwy/oH9 xv4r/g/+oP1n/eP8jfwl/AL9ffwr/n79qv5V/ub+Mv6H/jL+4/2n/eD9Qf1u/h/+ Rf8S/yL/0P4y/ub9kf1O/Q/+oP2K/hL+nf6B/kX/0P72/or+//2B/W79zPzJ/Z39 HP7G/X79Mv1L/dz8WP0C/S/9xvxY/en89v2w/cP+mv7g/p3+Ff6a/U790Pxn/fb8 OP7G/R//oP4J/7P+Yf7//br9W/2K/Uj9Nf7Z/UX/Jf8MAKT/dP8c/6T+OP6g/kX+ Zf8f/zgA2v/Q/1X/w/5Y/hz+0/1O/uz9t/57/iX/w/4v/63+9v13/Rz9xvyB/RL9 5v6d/rT/lP/W/qr+Yf0M/aD8O/zJ/JD8Qv7s/eP/rf8MAOD/5v6E/qD9OP13/TX9 OP72/V7///7a/7r/S////kv+//1F/hL+wP6d/p3+a/6a/j7+Bv6U/Wv99vx0/S/9 cf4r/iz/8/47///+oP50/sP9cf2R/Y39kf5C/sb+mv5V/vz94P1+/bD9Iv2N/Uv9 dP1U/dz9h/13/vb9Mv7p/bP9bv2U/Uv9gf0M/db9dP0c/2j+LP/Q/vn+gf57/v/9 w/26/dP9ev3Q/or+LP/8/uP+kf4P/qr9yf1r/bD9Tv2t/lj+cf/w/qD+Mv72/YT9 l/0o/Vv+8/0o//P+pP8v//b+sP5L/QL9qvxn/HT+Mv5IAOn/JQCH/6D+WP5r/dz8 Ff3//OP9ZP2w/zX/SwDm///+hP6B/Tv9s/01/d3+lP69/17/0/9I/8r+SP75/ZH9 jv78/Uj/zf6B/yL/Gf+9/rP+OP7p/XH9Qv69/aH/L/8GANb/Jf/s/g/+7P0+/QL9 DP2K/Pb90/2t/zL/tP9L/zX+kf3y/FH8hPxB/OP8gfxe/hL+//6w/nv+HP5k/fz8 oPxk/CX93/yK/lH+0P9l/zj/Cf8y/pT9Ev6R/a3+Vf47/7D++f9S/47/Ff93/uP9 oP04/XT+9v2R/+n+3f9u/1v/xv5F/qD9ev35/Pz9p/0o/73+W/8f/7f+Xv7p/Wv9 cf1L/YH9W/1b/mH++f7N/pr+OP6g/V79bv0C/bP9SP32/sr+HwDN/7D/Uv+6/m7+ uv5V/or/Jf8vAN3/TwAiAL3/cf8M/+z+0P6X/kj/HP9VABIAmgAGAGH/3f5r/Tv9 9vxR/C/+qv3g/2H/+f+q/zX/4P4o/rb9Ev35/EX99vyO/h/+3f7T/lj+e/5u/kv+ 7P6H/hn/nf7w/pr+3f5+/oH+Xv50/hn+LP+6/rr/P/9r//n+4P6q/nH+OP72/db9 kf41/rr/LP9l/zv/KP6z/ZT9W/1F/gn+A/9u/jL/hP6q/mv+h/47/tP9Qf3Z/X79 dP4y/gP/wP4c/9b+hP4V/sn9l/3p/bb9sP5L/mH///5C/7r+0P6w/un+sP5o/yL/ uv9h/5T/Qv+X/07/Xv8c/2v/Rf9b//n+D/+d/hL/nf7N/of+d/5u/pf+dP4//yX/ Ff+O/m7+/P3g/Zr9OP7N/Z3+SP4J/53+e/8J/w//zf5V/rP90/1k/Vv+3P1C/9n+ 9v8//3H/8P4M/qD9oP07/fP9h/1x/ub9Ff+E/kj/7P7d/mj+/P1+/fb9l/2a/vP9 t/41/rr+Xv5O/v/92f1B/Uj++f1Y/wb/Vf/d/k7+sP3A/V793P1k/V7+//3g/oH+ aP/p/jv///50/ij+Ff7W/Zf+Gf6R/xL/8P+q/7D/OP8v/8P+vf5b/tn+d/5o//D+ Uv8f/3T+Qv5I/uD9DP6k/Uj+7/38/qD+gf/j/iz/xv7W/b39Pv3j/Gj+1v2O/0L/ 6f+O/5H/L/+H/vP97/1+/Z3+dP4sABYAxwBxAAMAsP/W/qD+OP4C/kX+3P3s/mT+ BgBr/17/6f5+/SX9yfxx/K39Qf1o/vz9/P3T/V79Nf1b/QX9Yf3p/Nz9Pv07/gL+ 2f2N/Uj9D/3A/Ir89vy6/C/+qv10/w//1v6B/nr9+fzv/Hr8Cf6U/Tj/7P4GAHj/ AABb/6H/O//W/uP+Uf4v/gP/zf7t/8f/3f94/4H/Cf9l/93+WP/z/jv/7P72/qf+ 6f6n/r3+dP5b/j7+//3D/Yf+Xv7z/sP+w/5h/n7+H/6a/jX+Cf78/V7+aP6R/3v/ TwBrAB8A0/84/xL/nf6d/tn+rf7T/2j/cQASAF4A9v8o/wP/1v5k/ub+fv4v/9n+ Qv/s/gn/l/4Z/rP9ZP07/Vv+5v0o/5H+p/5e/gb+0P0v/Qz9vfyE/A/90/yE/jL+ Iv7m/eP8l/wu/Ob7h/wi/ND9WP1I/gn+1v6H/sD+d/7z/aT9Uf3f/CX+/P10//n+ w/+w/2j/Uv84/9P+0P6w/uz+zf7j/nv+l/5+/iL/0P72/sP+uv5o/qT+Vf53/kX+ //0M/sb9rf3W/a39jv5b/gn/pP57/m7+Uf41/mj+aP7p/qf+3f63/h//8P5e/0L/ tP9+/xn/SP9S/wz/hP/8/hn/9v4G/+P+Uv9O/8f/0P/H/1X/Nf8P/4r/Vf8pALD/ yv9u/xwAiv8cAOb/OP9O/7r+a/44/+b+qv97/wP/0P44/iL+D/7W/fn9wP1+/j7+ yv6R/tP+1v6E/lj+xv1+/dn9rf2E/lv+H//w/uz+2f5u/hz+OP4l/lX+Mv6O/pT+ w/6H/vD+e/7K/rf+l/4f/rr+lP6q/wz/Tv/s/nH+KP5Y/gL+//6n/m7///50/x// SP8o/9P+oP6H/kX+yv6g/pH/DP8vAK3/vf9o/+n+qv6t/pH+Yf9F/+D/mv9S/yL/ 4P6X/vb+s/6K/m7+d/41/t3+zf5I/wz/Iv8Z/wb/s/6w/5T/FgAGAB8AAADN/8P/ 9v7T/uP+h/6h/3v/+f/Q/9D/w/9l/wb/Ev+3/vb+uv4y/7f+W//z/lL/D/9x/kv+ 7/3c/Tv+H/6n/mT+//6a/lj+Ff5L/QL9mvwr/Dj9yfzG/YT9Av6X/Qb+l/3G/Uv9 Xv3//J39L/2X/v/9xv6E/mH+Ev6K/UH9Gf6d/V7+HP6z/lH+Bv/A/un+p/7d/pT+ 4/6g/mj/yv4//8b+W/81/wz/p/4P/gz+W/4C/vD+S/6z/j7+Ff69/Zf9bv2R/Uj9 ev1x/RL+4P3A/jj+8P6n/vn+oP50/lv+7/22/bP+Nf5S/+n++f7W/uD+fv5+/xz/ AACk/0j/3f7Z/m7+eP/2/rT/Mv90/wP/2v9O/+3/e/8D/6f+nf47/rr+Jf69/mv+ jv4r/gb+w/1e/Rj9Rf3y/L39xv35/Yr9yf13/ZH9Rf2g/WT93P2R/Sv+oP1I/ij+ Pv7g/ar9bv2w/V79Ev75/YT+h/7m/sr+aP5u/tP9sP0V/ub9xv57/t3+p/7T/qr+ nf5O/nf+6f2H/oH+Iv/d/vz+uv5O/g/+2f2k/RX+xv38/pr+Tv8P/x//0/5R/tb9 6f1h/WH+Iv4S/7P+SP8D/0L/Bv8s/+P+3f6K/nH/1v5CAPb/hABCAHT/OP+X/nf+ KP/d/t3/e/8SACwAKQAZAIT/O//Q/pH+yv5o/mX/HP+U/2j/A/+z/sD9p/1Y/f/8 Yf5O/gAA8/8fAND/rf5Y/rb9W/3//Z39zf5e/t3/e//W/27/0P6n/qT9a/3s/af9 DP/g/u3/hP/p/4H/qv5r/q39h/0l/hL+Zf/z/pH/A/9Y/vz94P1n/cb9a/07/vP9 Bv+9/kX/8P4r/h/+fv0i/Wf9D/1F/hL+Ev/W/lX/6f5V/qf9p/2E/cD+lP7t/83/ PADH/8r/qv9Y/+b+uv6U/kX/Xv8DAb0AjgGqAbcAeAC6/0j/dP9V//b/zf9bADgA WwAfAFX/Mv/K/nf+oP4+/tP+yv5O//b+/P6w/o7+Rf6t/VT9hP2U/Zr+W/4l/7f+ xv6E/rD+Yf4D/8b+O//5/tb+bv6B/jL+0/5I/mH/rf5b/+n+HP+a/hn/xv7w/rD+ jv5I/rf+OP7z/oT+3f6H/gb+sP3A/VT9//2k/dP9bv2a/W79W/0Y/e/8kPxX/Ej8 Ff3Q/D79Qf0c/eb8w/yg/Bj95vxU/SX9ev0v/Tv+//2a/k7+Iv6z/RX+nf3K/jj+ P/8S/5H/Nf/5/8P/0/+w/0j/KP/T/2H/OADp/3H/Tv+6/nH+w/5h/kj+OP5V/i/+ xv6q/kL+HP41/Sj9Ff3Z/DL9K/38/db9Uf4C/ij+6f3W/bD92f29/WH+Qv6O/or+ Zf/j/vz+p/6n/mv+1v7D/vD/eP8iAMP/p/8i/yL/gf4V/7P+Zf87/6f/mv+n/1j/ 2f6z/rP9fv2K/VH9fv4C/vz+pP6w/lH+wP0l/fL8lPz2/J387P22/XH+Jf7G/ZH9 lP0S/S/93/yX/QX9SP7g/a3+fv6U/mv+p/1b/ZT9Jf1k/hn+cf8M/07/Ff9Y//z+ /P6t/mv+Vf6w/qD+nf97/8r/e/+9/mj+Bv66/e/99v1b/jX+oP5e/k7+Qv5C/gz+ DP7J/XT+Pv4G/7P+LP/s/jv/3f7D/nv+0/57/kj/9v6X/3H/H//8/rf+a/7W/k7+ S//Z/o7/L/8PAI7/vf90/yX/0/7w/rD+s/5b/rP+bv7m/nv+oP5+/uP+kf5b/+n+ P//g/mj+K/78/Z39+f2n/S/+8/1Y/vz9l/5k/rP+Tv4y/sP9SP72/fD+e/5h//n+ 7P7W/tD9zf2K/Zf9WP4l/tP+l/4M/+z+0P7Q/lj+SP7v/cb9L/4i/t3+ZP7D/n7+ S/5F/sn9pP1k/UH9Pv4c/sP+lP5C/vn9bv1b/V79Rf3D/YT9WP4i/tD+1v5I//P+ cf5+/vP95v1L/gz+fv5b/un+1v7w/tn+Ev/W/g//1v5I/yj/OP8V/7f+cf5I/jX+ L/4v/oH+ZP69/un+HP/W/n7+a/4o/gn+6f3p/Sj+sP3Z/a39Gf7j/fP+S/5r/k7+ hP4c/sr+lP7p/qr+cf5F/pH+Pv63/1X/8P/t/5T/nf8V/73+4/6K/rr+Rf4M/73+ OP8f/4r/Xv8o/yz/t/6X/hn/sP5C/wb/Uv///hz+7/01/Qn9GP0S/YH9w/01/ij+ iv4+/g/+s/1O/R/9vfyz/L39rf0f//n+LP/p/kj+Bv4P/sP9Qv7z/fz+pP5+/yz/ Tv8P/4r+jv5F/gb+fv4+/hX/8P5b//D+8/66/ij+8/35/Xf9WP7N/af+O/6t/hz+ Nf69/aD9cf10/U798/2g/Sj+yf3s/cD9Z/0y/R/9GP1B/Q/9Cf6g/dn+3f50/mv+ KP7z/XH+Pv6z/or+4/6w/iL/0P57/1v/tP9O/9P/Mv+6/3j/W/9C/7r+fv5C/iv+ +f6a/nv/DP+H/x//zf50/lH9Qf1e/Qz9Nf75/ZH+Xv7c/ZT9Nf0l/cn9p/3K/oT+ Zf9L/37/KP8f/v/93/yg/Lr9Nf17/+n+pwBSAJQAQgA1/6D+d/3y/JT9D/3w/nT+ NQDW/3T/8/7Q/Zf9Rf38/Fj+4P2k/zL/Nf/T/gb+h/2q/Ff8V/wS/Jf9K/1F///+ SwDg/8D+cf50/CL8O/wV/Nb9Xv0D/8P+Xv+z/tD+d/44/hn+Xv4S/gYAlP+tAHUA x/9o/wn+l/16/Qz9Xv41/p3/eP94AAwAW/81/839a/07/Vv9yf13/R/+yf2O/lv+ KP72/T790PzD/J38Gf4M/gn/KP8f/vn9W/35/HT9WP3z/ZT9l/4i/rr/W/8ZAAYA h/+B//D+6f7N/pf+Tv/p/vD/zf/g/63/Ff+9/g//pP7w/p3+Vf4S/jL+zf2t/kL+ Gf7Z/WH99vxL/dn87/2X/ez9pP1r/Vj9mv1r/XH9VP1L/RX9l/1h/Sv+4/1C/ub9 Yf53/n7+H/5V/uP9S/4G/uD+l/4M/wP/bv9h/4r/W/+t/nf+d/4f/h//nf5o/wz/ 5v6z/sb+rf4Z/wb/rf6B/uz94P0G/pf9mv0C/fn8kPyq/KD8S/0C/Yf9D/1h/fL8 Ev29/Kf8YfyX/If84P2N/cP+fv7j/l7+sP4v/sD+Yf63/oH+x/8V/2sA6f/8/63/ Ev/m/v/+HP/p/7T/0P+X/9n+0/5o/lX+D/7c/Sj+yf1r/lj+vf6H/iv+Jf78/Bz9 UfxL/MD8uvw+/iL+p/5+/lT9HP1L/DL82fxx/KD9dP1O/hz+LP/K/mX/+f4v/s39 s/1r/Zf+Xv5O/wn/bv/p/qD+t/5L/vn9a/4o/jL/6f6H/2H/8P6t/uP90/3s/Pz8 +fzA/Hr9Uf2R/l7+bv5O/uP8sPyz+8D7EvwY/H38YfyQ/Fv8H/3y/Hr9Ev29/K38 //y2/GH9Pv2R/Wv9Av5k/X7+Ff5R/gz+mv6K/tb+s/7N/pr+p/6B/uz+sP5x/zL/ sP6H/rr+a/6n/pT+4P6q/vn+iv4y/hn+Rf0o/Sj98vz2/db9w/5b/lH+Mv7D/X79 OP38/EX95vyz/Zr9sP6K/hz/5v5b/j7+Jf0P/TL9D/1k/hX+Ev/A/vP+xv4i/tP9 7P3Q/UL+Mv6R/nv+5v66/kX/DP+O/kj+ZP32/Kr9ev0D/8D+Iv/s/jv+3P2g/Vj9 HP3m/P/8s/yw/YH9l/47/k7+Av5B/ez8h/xI/PL8bvy2/Yf9vf41/or+KP62/Y39 jf1h/Rn+5v3G/of+Ff/8/qf+gf44/hX+SP7W/T7+4/3G/nv+Jf/8/sP+iv4G/rb9 w/2w/XH+HP4l/7f+Tv8P/zj/+f66/o7+Ff66/fb9yf35/o7+WP8f/yj/A//W/qf+ cf5I/iX+D/7j/qr+fv+E/9D/4/+E/zj/kf5R/hL+6f38/f/9mv44/vP+oP7g/nv+ Mv7p/Zr9kf2R/Wf9OP4P/qT+Vf5V/gz+Uf3y/ND8mvy9/YH9S/4C/qr+cf5F/gb+ Z/0+/QL91vyB/XT9nf5+/vb+h/47/j7+iv1u/YH9W/17/g/+bv/p/pH/9v6a/kj+ bv0o/eb8sPxx/SX9W/4S/vz9s/0P/cb8Bf3c/DL9GP3v/aT9l/4i/s3+Yf7z/cD9 s/yt/KD8VPzW/aD9s/5o/nv+K/5O/v/9Ev7J/Zr+Uf7s/rf+A//K/lL/Ev9O//b+ L/8//3v/SP9Y/0v/Ev/s/rr+gf6K/h/+xv5I/vz+qv66/lX+9v2k/Qb+hP01/vb9 wP2d/ZH9VP1u/Tv9gf0o/VH97PxR/Sv9vf2U/X79iv13/Xr9cf1L/Rz+0/0P/tz9 L/01/SL9w/yk/UH9sP5L/iz/8/4S/wn/hP4r/or9GP0S/fL80P3J/cb+lP6n/pf+ 9v3Z/Uj9Av0i/e/8wP2U/Uj+Bv7J/br9O/26/H38SPzy/JT8//2k/ZH+cf5O/tz9 cf0C/XH9GP3T/Yf9+f6E/g//3f7D/tb+Tv7D/fb9nf2O/k7+D/+n/jX/wP7j/m7+ 9v6X/kv/7P6k/0v/Gf+9/or+Ev7Z/Y39WP0+/fb91v3D/rD+yv5C/mv9Rf2q/If8 6fz5/Ab+mv2g/lH+hP47/r39ZP1I/Qn9dP0+/RX+7/2E/vz9DP7J/bP9a/0+/Rj9 xv2w/Zr+Vf4i/g/+//zG/Pn8hPzj/a39e/47/lH+Ff7G/XT9l/xq/Bj8tvv8/L38 cf4r/sr+bv7j/Yr90Pyn/LP8gfzm/XH9Nf9S/x//A/8S/v/9Rf0v/XT9L/2k/k7+ vf9e/3j/DP/8/Wv9iv0r/W79Qf1u/gb+Nf/Z/kj/+f63/mv+7P3c/SL+DP6n/qf+ s/53/nf+Vf4v/ub9h/04/TX+7/3Q/rP+wP63/qr+kf4o/8b+Vf/g/g//0/4l/+D+ a/8Z/wz//P6H/lj+s/5r/sb+fv47/jj+Iv5L/vD+s/6R/nT+0P16/VT9Mv29/YT9 Rf4V/mH+Yf4G/rD9+fyz/A/89ftx/EH8bv3v/F7+Ev78/e/9VPw4/GT7MftL/AX8 3P2w/WT+8/0l/sb9kf2U/cz8rfwl/R/9bv47/vz+wP4i/sP9+fzM/BL95vwi/hL+ xv6k/rr+wP69/dP90/yg/Nn8w/x+/V79Tv4i/tP+l/62/ZH9W/wi/CL96fzA/eD9 H/7c/fn9zf3J/Zf92f2R/dn9wP3N/pr+1v+a/6r/eP8G//n+rf5u/nT+cf4c/0X/ FgDj/83/t/9L/0j/w/7m/n7+d/5L/hn+dP4l/un+rf44/hX+a/1b/WT9S/07/Rj9 D/3Z/BL92fyd/UX9Jf3c/CL89ftU/HT85vzj/GT9nf2z/YT9s/2U/Vv9Mv04/dn8 qv1x/SX+Jf5k/kL+nf2H/ez8tvyw/Lb8W/1U/bb9WP1b/Vv9bv1L/V79Av3p/Kr8 +fzj/NP9oP3T/YT9jfxn/GT88vvy/MD8fv0S/Z39Iv04/fz8mvw7/AX9bvzW/VT9 Tv4P/nv+WP5u/jX+Av6K/af9bv2E/lj+vf+H/2X/SP+n/nH+l/6K/gb/8P7N/rf+ t/6R/qD+jv4l/w//Jf/z/iL/Iv8J/+z+h/5o/tP9/P0Z/sn9W/4o/uz+2f6z/oH+ zf2g/ZH9a/0M/sb9l/5C/ij/zf7D/qT+zf3Q/br9l/2R/qf+hP+H/0X/Cf8c/vb9 4/yU/MP8Z/yw/VH9uv57/pf+S/5O/RX9KPzW+0X8+fuR/Wv9Tv72/RL+tv2d/If8 FfzM+9P8nfzg/cD9Uf4v/lH9W/2K/Jr85vzj/GT+H/5+/6T/L/8i/7r9jf0+/SX9 vf1B/a3+WP66/5r/zf9l/yv+Mv72/AL9d/1b/W7+SP4y/+P+H//m/hL+7/2q/Uj9 4P2d/Xv+SP7W/nH+gf5Y/jX+Gf6w/ZT9Gf4l/o7+Yf6H/j7+HP7G/Wj+9v2k/yj/ LwD5/xkAFgBL//P+Ev7G/RX+9v0P/8P+LP/D/hX/lP66/lH+Ff6w/dP9d/0o/v/9 kf47/pf9Rf2E/GT8mvx0/EH9H/2U/WT9oP1O/Sv9wPxL/Cj8Pvw1/CL9L/3W/aD9 0/2w/Zf9l/2N/Vv9rf1r/Rn+7/23/ij+nf4y/jj+H/6X/jv+0P5x/uD+e/7N/mj+ aP41/gz+Cf4o/uD9p/44/uP+nf69/p3+Gf7J/UH9Av16/VH9Ev7J/Qb+4P0P/rr9 9v3D/bD9bv3T/Yf9dP4+/g//w/5r/9n+Cf/2/lv/SP+X/2H/uv+B/xkAyv+0/53/ e/9L/4H/Uv/2/7r/zf+6/73/qv8s/zX/aP4o/g/+3P3G/db9Ff7Z/X7+Qv4f/ub9 xv1u/UX99vyQ/Jr8s/yd/EH9Cf3D/aT97P1r/bP9dP1n/Sv9fv04/br9hP0S/pT9 6f3G/Tj+7P01/gz+OP4G/n7+Uf4M/9b+2f57/hL+vf3c/Y39Nf4c/sP+0/7G/pr+ WP5L/p39gf0S/db8fv1B/TX+Tv6q/lX+9v16/W79H/0J/QX9ZP1U/X7+Yf4y/y// fv57/jL9Bf0l/B/8SPwV/KD9oP0+/iv+SwAGACkCHAIDAtABVQL2AeMAzQDs/dn9 yfy6/Ob8o/wV/tn9LAAMAPn/t/8f/uD9d/0y/U79Iv1b/i/+eP9F/0X/Ev87/uP9 4/3G/cn9lP3G/X79//3c/dP9dP38/cb9aP8P/6f/S//s/eb9lPy2/MD8bvwV/Z38 cf4C/hkB5gA/AiYCeAEWAW7+cf7G+qP6Qfl9+b37qvtr/TL9KQDz/+0DiAMpAtAB 9v2R/XT5K/kU9Qv1Y/UX9SX7+PquA7EDDgrkCRcIHQgs/yX/v/aT9v7y2/Ky9lf2 sP+K/xMHCgcaBw0HIwLtASX87Psr99v2WvgI+Gv9O/0pAi8CQgQjBCwCKQK9/1v/ 7/3N/a38VPyz/FT8V/wV/CX87/uU/E78Mv3A/Jf+Yf4vAMf/cQAPACUA7f8JAOb/ lP5O/oH8RfwV+/z6sPpe+jv8LvyhAKoAjgRPBDYERgTgAL0Aqfqz+iH22/Uh9+v2 Xv2n/RAE8wNTBkkGawM2AwX97/xa+JP4bfiA+Bj7KPtY/Xf9rf13/SL+/P1+/3v/ PAH8ALEB1wH8/vD+zPmw+Y/1YPU39x73pP6R/nIFZQXqB+EHqwSkBCv9K/00+Bj4 Qfgn+Mb6mvrv/br9DAEZAdACxwIcAxYDawI/Aub+s/56+Ur5J/Yx9pn3UPcr/f/8 YgNMA9cFxwUjA8cCKP35/DH4NPic9kr2ffmG+YT/SP+OA1IDggRsBO0C2gL8/pf+ 7PrW+oD5Svln+yL7Jf8Z//YA8ABSARMBxwDAANn+Ff/M/Lr8jfvA+0T7D/sF/ND7 Cf4V/qr/fv/N/6r/Uv///k79Jf0S+9P61vp9+uL7sPvJ/MP87/26/Qz+Cf7g/af9 iv1F/dz8yfyH/aD9uv5x/qr+bv6t/Zr9cf0r/Yf9Tv0V/gn+fv8//4H/Vf9Y/i/+ 5vy9/KD7jftb/Aj8wP2d/c3+uv6t/07/Tv/Z/j7+yf0G/rb9Jf7Q/cD9lP1Y/Q/9 Tv3m/G79Pv0v/uz9mv5u/h//Gf8lAMD/L/87/0j+1v1V/uP9hP41/pf+Vf7W/4H/ x/+O/73+rf7m/p3+L/4f/vn9Cf7Z/q3+Jf/z/mj+Xv7m/br97/38/Yf+gf72/vz+ Zf84//z+s/4y/d/8Jf2z/FH+Pv75/uz+//7g/or+gf6k/dD9w/2t/fb9+f2U/h/+ W/5V/lT9DP1O/cn8Nf4P/t3+nf47/xz/0P7W/mH9K/1U/UH9h/5b/vn+s/69/qD+ SP5V/gL+tv0c/s39DP/m/sP/Xv9L/xX/Pv4l/gn9DP3G/F78h/4l/qQAeADqAJoA eP8c/4r9cf1n/H38Uf0P/Q//kf6kAEgA/P/N/1X+Mv50/Sv94/yU/Ev9Ev3W/rP+ rf9x/47/gf/w/hX/Nf7Z/dz8dPwC/YH8DP7W/V7/a/8fAeMADwETAQn/1v4f/e/8 9fsV/Pb8sPyB/nT+dQAWAGUBQgEDAdoAIv/W/i/96fzv+8P7h/s7+8D8ivxO/wP/ 1wCXAMoAqgB+/w//KP2X/Dj7qfob+7D6rfwP/Jf+Yf7t/53/gf8c/3H+Mv5k/Q/9 sPxR/Oz8o/zs/Yr9LP/A/gYA0/8sAO3/2v+H/wb/w/75/U797P2n/ar+Yf6O/n7+ qv6d/h//wP4c/93+l/5h/rf+Xv5O/v/9Iv66/Yr9K/2E/TX90/1R/Qz+uv1V/ub9 e/4i/oH+3P26/VH9W/0v/YH9DP2H/U79Rf7v/SL/uv5S/w//dP/Z/uz+rf53/hL+ W/72/UL+5v2X/jv+sP5k/uz+lP4l/+n+L//d/hz/A/9u/h/+vf1b/eP8oPz//On8 fv3//Nb9l/2g/jj+Cf+g/jL+//2g/SX9cf3//Dv97PyK/RL9ZP72/cP+Yf75/tD+ Xv8D/wP/0P6K/Uj9tv0v/Qn+rf0V/qr9Jf+3/l7/+f78/o7+zf5r/lX+sP01/gL+ hP41/lX+D/6H/nH+S/4J/pr+L/7A/mv+gf7p/Y39fv2n/Sj9Ff2z/Lr9a/0v/9b+ Zf8f/47/aP+H/z//Tv/j/mv/8/4V/7r+6f2X/db9WP2k/l7+FgDK/yYBzQBlAEsA L/4i/nf8RfwS/Nn7hP0y/VX/5v4SAI7/3f+k/zX/wP4S/qT9l/2K/Wv9L/1k/Qz9 pP13/Sj/1v5uAAYAlwAfAAn/xv5Y/Vj9ivxF/Nn8h/wZ/sn9Vf8//73/jv+a/1j/ Ev+a/rD9WP0V/db82fyQ/JT8SPxh/RL9zf6X/m7/1v6w/mH+zf16/b38cfwr/BX8 mvxk/Jf9Jf1h/rD9uv5C/kX/6f4c/63+mv6H/p3+Pv7j/Y39kf1L/aT+bv5uAPP/ BgGaAHgA1v9Y/9n+4/2k/b39Qf0V/vb9hP5o/vP+xv66/mv+tv1h/YT9SP35/Qb+ qv5F/of+bv4y/tD9VP32/Fj9/PwG/n79wP5O/pr/Uv+O/17/qv5o/pT+WP6w/n7+ SP8y/8D/p//Q/3T/lP8y/zL/3f7A/3j/lAA/AAkAp//G/pH+wP1r/cP8Yfx3/VH9 Nf/m/lUADwAPAM3/qv6U/kv8TvxX+/X6BfwI/D79w/xR/j7+W/9C/07/8P6q/nH+ d/0J/S783Psb/NP7Jf3y/Fv/LP/wAPwAHAEPAZoAFgB0/ij+jfyX/EH8//s+/S/9 KP///vMAhwAiAdoA1v9V/5r9Pv3y+4T7Evya+179H/26/qD+iv+O/1j/Bv8C/tb9 /PzA/Nn8kPwS/eb8a/4v/tD/nf8GAKf/hP9b/9n+0P6z/XH9O/3v/Bn+6f1u/1L/ rQCHAEUB9gD5/7T/vf2d/ZT8Rfxk/EX87P2a/dP/bv/QAHEATwA1AJ3+SP72/Jr8 Nfzc+7b8SPy2/WH9dP47/rf+Pv5k/h/+zf2z/cD80/xI/AX8Rfwo/PL8tvxL/hL+ Jf/N/iz//P5h/mT+DP7//Yr9cf01/vb9d/5F/tb+oP4M/8r+0P53/pf+OP78/db9 rf3N/Qz+6f0l/+n+W/9S/47+ZP5r/U79Tv0l/ZH9fv0S/sP9ZP47/tz9oP1h/fn8 0P2B/XH/Jf8PAA8ARQAMAKH/Nf+d/jL+Ev/A/vn+xv7D/pr+fv+a/+D/hP/A/n7+ hP6E/vP/hP/QAJ4A1wCLAGj/cf8C/d/8EvsL+zj85vvz/mj+GQGUAAkBzQAD/8r+ Qf0M/QL+8/2EAA8AAwGtACz/t/53/N/7d/pB+qb7Ivsr/tn9QgC0//z/pP/A/pH+ aP78/T//xv7p/7D/zf6B/iL9wPwP/Mb7H/zJ+wn+vf1rAAYAMgDT/1X+Ev69/FH8 Yfwu/Hv+Ev4WAJ3/O//d/vL83PwI/Mn7bvxe/Jf9Ff1C/s39W/4l/vb9qv2O/gn+ tP94/2gA8/+a/wP/7P2q/YT9L/2H/g/+EgC3//kA3QDp/4H/SP3D/EH7wPpb+7n6 Iv2Q/Kr/Ev/W/3v/sP53/hz+vf2g/k7+D/9e/lv+Mv7s/Z398/2X/Zr+S/5+/0X/ UgAsAK3/SP+U/uz9Qv72/aD+Mv7W/oT+l/5e/tP9oP0F/cn87PzZ/HH+a/6h/0j/ h/9C/4r+a/4c/Q/9Ev2q/BL+pP3m/rr+jv5k/v/98/2w/YT9Tv0V/eP9tv1F/tb9 9vyw/MD7d/vc+6D7bv01/dr/mv8GAeAAKQCX/9D9cf0Y/OL7V/wY/HH9KP1k/jj+ zf6K/l7+K/7v/dz9bv4y/p3+l/4Z/j7+W/1h/a38o/zA/IH81v2k/br+bv5O/gL+ /PyH/MP8XvwV/e/8jf1L/Sj+7P26/lj+gf5I/k7+Pv7K/qD+A/+H/gb/nf6n/lX+ S/4V/mH9DP2K/UH9oP5e/lv/HP8V/+z+SP8c/2v/OP/s/t3+3P3Q/dP8uvwf/af8 l/1k/bf+OP5V/zL/lP8//7r+nf5F/W797/y6/CL9L/38/Z397P22/UX+2f2n/nT+ 8/5x/i/+3P0V/fz8ffwu/Lr8p/wS/rP9L/+3/gP/t/6R/lH+Ff7c/UX9xvzv/Lr8 Mv0i/Qz93/wJ/bb80P1U/Qb+w/2n/VT9yfx3/Hf8O/yq/G78Pv0F/TL+0/1k/tn9 1v2E/WH9GP2R/Tj9dP4Z/m7/zf5h/+n+Nf4S/vP9S/3T/V792f10/Qn+p/0v/uz9 8/5h/kX/2f6U/zv/zf7d/kX+//2z/Yf9SP3//M39ev1b//z+ZQAvAHsAFgAy/9b+ Ff6q/aT9K/2X/T79H/7N/Tj/zf6w/4T/Jf8V/6D+aP4f/sP9H/0Y/R/91vx3/Sv9 Pv4f/mT+Gf50/jj+Bv6n/Tv94/y6/J38Yfw4/MP8O/xe/fL8Yf4C/i/+3P2w/Xf9 //zJ/E78JfyK/E78Mv0P/eD9jf1r/kj+h/5C/lv+Gf7T/Zf9GP0i/cP8vfxe/EH8 9vzQ/Fj+Iv5h/2v/l/9C/yv+Bv7p/PL8EvzJ+4D7gPuQ/D78//2d/dD+jv6H/mv+ Xv4C/lH9ev3s/NP83Pyj/Dv9Ev0c/tP9Jf/T/kL/8/7Q/oH+K/7g/dn9wP0y/vn9 8P7g/ub/iv+n/17/7P6H/of+a/4v/hn+Iv7z/eP+d/6a/k7+O/78/VH++f0G/rb9 sP1F/V79Iv2E/RX9L/3m/Bz93Pyk/Tv9zf10/WH9Bf3D/JD8vfxu/Jr8Z/yj/Dj8 H/2H/Pb9Xv0V/tn9Ff69/eP9a/1n/Rz9dP3v/K39ev0i/p39KP7J/ar9S/2k/Tj9 OP0C/Sv96fxu/Tj9fv1F/U79+fzT/H383Pyg/FH9Qf3W/Yf9OP3J/ND8Z/zM/K38 Ff2a/G799vzs/c39cf4S/k7+Iv4P/hL+Cf7z/UX+4/1r/uP9Yf44/ij+1v1b/uD9 1v5R/s3+dP6U/lj+rf6B/n7+Rf4P/qD90P2U/b39l/2t/XH9uv2H/Uj+rf1+/u/9 Cf7J/ar9Qf1b/RL9lPw1/LP8lPx+/SL9nf1O/eb9lP2N/Tj9OP2K/L38UfzD/CL8 KP3G/Hr9O/3W/Vv9/P3A/Qb+xv3p/YT9Tv3Q/IT8H/xq/Aj81vyX/Gv9Nf29/W79 lP01/Zr8hPzW+2T7oPuH+078FfzT/JD8gf0J/Wf9Nf1k/f/8s/x0/Gr8Ivy2/Ir8 xvyn/D792fzQ/W79O/7D/Qb+7P0i/s39uv16/YT9Pv3Q/Vv9HP6a/W7+/P04/rr9 Gf7N/TX+/P1V/tP9Gf7m/Vj+4P3Z/ZT9H/3D/JT9Ev3Z/Xr9D/7c/S/+0P0C/oH9 s/1B/bb9ZP3A/Uv9jf0S/Z39Nf2z/Zf95v2z/WT+Cf7g/nf+pP53/hn+6f16/SX9 L/3Z/Lr9gf1r/vb9gf5V/iX+6f2B/Rj9Jf3Z/Mz8Z/yH/Dj8w/xk/Bj9sPzG/I38 KPzi+078H/x9/Ev8nfwb/Nz8wPw7/QX9S/0C/Vv9Bf2E/Wf9rf2X/eb9p/3T/Wf9 qv0Y/UH9oPx0/TX9iv75/cr+Qv6w/jX+sP1O/dP8l/wJ/Zf8Yf0J/Sj++f3//dz9 S/04/Yf9Uf22/VH90P2E/Qn+rf3g/YT9Nf3s/Oz81vzc/aT9Xv7j/ar+aP6B/m7+ K/4J/nT+Yf6a/p3+7P7A/qf+mv6K/n7+ZP5R/s3+l/6E/2H/mv90/xX/9v7D/oT+ e/4+/jv+8/2E/Z39zf22/WH9bv1B/R/9Gf7g/UX+SP7s/br9Iv3v/PL8wPyj/Jr8 1vx3/E79GP0v/sb9w/2k/Rj9Pv0S/bP8H/0l/VH9Ev3p/Kr8Cf3A/D793Pyg/Yf9 K/4P/rr9w/01/SX9/Pyz/MP8lPwY/ZD8HP7m/cb+gf4Z/un9SP3s/Jf8UfzJ/D78 +fyH/Bz9o/wC/bD8Iv3G/HT9+fyB/Sj9Tv0v/XT9Xv04/d/8Yf3c/An+0P2z/pT+ zf6R/lH+5v2w/W79rf1h/Vv+/P38/sr+bv84/7P+s/6O/lH+bv5F/pH+W/63/nH+ l/4v/tz9pP3v/Yf9h/5F/qf+ZP7j/VT9S/32/FH9xvwy/dz8uv1R/Wj+HP5x/iX+ vf2K/T79Av13/RX9h/01/Yf9Pv13/W79mv0y/XT9Qf35/af9Jf7c/dz9sP2N/br9 O/3j/A/9jfxU/ez8Ev6q/UX+zf01/nT9p/1x/S/98vzc/LD8Iv3c/B/96fwF/en8 SP0c/YT9Xv1+/TL9hP0o/Zf9L/1r/Uv9l/0M/Yr9Qf1k/Wf91v1I/VX+sP1C/vb9 H/7j/fn9yf2E/kL+Yf7//T7+9v1u/lj+Pv4C/sP9W/3c/Z39S/7s/QL+qv0P/uP9 ZP4Z/lj+L/5u/g/+S/4M/lH+Qv6E/hn+sP6k/vn+wP7Z/pf+aP6B/rP+kf6H/j7+ 0P16/XT9WP3N/b397P2N/b39Yf0G/rP9DP7p/Z39W/2U/U79zf2X/ar9jf3D/aT9 7P3A/c39iv3T/af9Ev66/db9mv04/dz8mv1R/dD90/35/cD9fv50/uD+gf5u/nf+ D/7p/fn92f3//cD9//2X/Vj+D/5I/uD9gf78/Vv+Gf6B/iL+/P3J/dz9jf3s/aT9 HP7c/VH+D/5x/hL+K/7p/dD9fv2d/TX90P1r/ZT9Nf22/YH9yf1+/W79KP2N/Uv9 zf2N/XT+Iv41/r39L/78/UL+9v1e/tD9Mv7p/VX+Gf6t/jv+a/4l/oH+D/6O/i/+ mv7//Wv++f3v/bP96f2E/TL+0P1o/hn+7/3N/X79OP1+/R/9S/3Z/O/8nfxr/Sj9 pP1r/V79Cf1k/f/8Yf0S/eD9ev0v/u/9L/7g/fP9hP3A/a39vf2H/e/9fv0c/sP9 Iv62/Tj+Gf5x/hX+a/4r/pH+aP4V/tz9h/1L/dn9mv0c/ub9Gf4C/gb+/P29/Yr9 ev0+/Vj9wPxn/e/8SP0Y/Tv9+fyt/Tv94P2t/Tv+w/1u/lH+5v5+/kv+Av6E/Yf9 uv1+/QL+sP1+/kL+5v6a/uP+t/4+/iL+zf3T/eP9l/3W/bP9DP7//Sv+Iv4V/sn9 s/2E/a39l/2g/Vj9Qf3c/DL95vzW/MP89vy9/H79bv3W/YH9iv1L/Sj9DP3j/J38 8vzy/FH9Yf0y/iL+lP5L/hX+9v3z/Y39Av7D/Tv+0P1u/ij+S/4l/mv+HP5C/hz+ Nf7s/SX+5v38/bP9//3W/Qz+1v3Q/eP96f3g/VX+Iv4S/sn94P2k/VH+Jf5e/jL+ Iv7m/VH+4P1x/jj+hP5x/q3+qv7w/t3+5v7K/s3+2f4M/wn/aP/m/j//6f7D/k7+ Tv7m/dD9bv0i/uP9s/53/pr+dP5b/hn+Tv4+/s39/P3z/cn9Av4C/uD9wP2n/Yf9 9v32/UL+8/1e/jX+Qv4C/tz9mv3s/Zf92f3s/f/9D/7G/qT+Jf+9/s3+kf6H/kv+ Mv4c/ub93P3p/ZH9Mv75/Sj+0P01/hX+jv4c/hn+6f2k/Uv9rf1n/ZH9Qf2N/V79 0P10/ez9iv1+/X79xv1U/eD9W/0C/sP9Pv72/Vj+Ev44/gn+SP72/VH+H/41/iX+ hP5b/uz+yv7p/tD+dP5Y/pf+SP6E/nf+cf44/n7+Pv7m/of+5v6H/rr+bv6a/o7+ l/6B/k7+D/4i/tz9HP6z/R/+uv1C/uP9Nf7m/S/+H/4y/sD97P16/db95v3m/bD9 Iv7G/Wj+Uf50/gn+ZP4J/tb+l/4G/83+0/6k/nT+bv6z/oH+Cf+q/sr+e/5e/k7+ ZP4V/qD+aP53/lH+mv5o/m7+L/7p/b39tv1u/Zr9S/3G/YH93P2z/aT9cf1U/WH9 sP2U/SX+oP3Z/aD9+f3Z/cb98/2R/V79/P2w/U7+/P07/kL+Rf4M/qr+qv7G/nT+ gf5O/n7+cf6a/mj+Vf5I/mj+SP5+/k7+kf5I/pf+SP6R/mT+e/47/lX+Cf5o/gz+ K/7Q/eb94/3A/ar9w/1x/cD9iv3Q/ar9Av7p/fP97P0f/iL+Jf7//fb9xv0M/tD9 hP4r/pf+h/75/r3+4P6w/uP+xv6B/k7+O/78/Yf+gf63/n7+gf5L/sP+l/7A/of+ Tv4+/k7+Jf4l/iv+Av6k/Zf9S/3p/cn9Rf72/cn9zf35/fb9ZP5V/hn+7/3g/cD9 Av7p/Sj+vf0l/g/+bv5Y/s3+p/6d/o7+gf4+/j7+7/1F/iv+Mv4r/rD+WP6K/m7+ S/5R/jL+Cf5L/j7+pP5I/sb+l/6K/lX+O/4i/kj+/P1Y/lj+cf5L/kX+DP4+/g/+ K/4+/un96f3N/Y39/P3p/UL+7/0G/h/+4/38/Rn+wP3Q/dP9Bv7z/SL+//0Z/sP9 OP4f/pT+fv5V/hz+Av75/V7+Jf50/kv+Tv4V/iX+Gf5F/kX++f2w/XT9iv3z/eP9 Jf7s/Qz+zf0S/qT97P2w/dP9sP0v/un9a/4G/iv++f04/gL+s/5b/qf+e/5F/un9 dP4c/rf+Iv4l/uP9L/75/br+W/6B/lv+SP4Z/kj+Av4c/hX+HP7v/Uj+Gf5x/h/+ D/4C/hz+Gf4c/vP9D/7Z/Vv+4P2g/k7+fv5b/mj+Qv5x/lj+e/4o/m7+K/5O/h/+ nf4y/rf+kf6w/or+4P6t/rr+S/57/vP9S/5F/kX+L/4i/u/9Ev4M/pf+t/6n/mH+ Vf4f/iL+Jf4o/gn+qv2N/b39dP0P/tn9Ff7c/en91v0P/s39kf2q/Wv9bv3N/aD9 //3A/e/9p/0V/vb9nf4J/gz+4P0V/hL+jv5k/or+hP5k/g/+Jf4f/gL+6f0y/tz9 Jf7Z/Qz+uv3g/br9Bv6U/RX+tv3c/aD97P1h/eD94/2X/aD9lP1I/Tv9//yE/U79 sP16/fb9hP0J/tb95v26/ar9VP3A/Z39Ev7A/Tj+5v2H/ij+uv5x/rD+bv57/jL+ bv4P/lH+8/0J/rr9SP4i/lX+Gf5L/un9OP7m/fb90P2d/ZT9rf2k/bb9p/0M/sn9 6f3G/fP9iv01/vP91v3c/RX+nf38/c39zf2E/Qz+pP1F/vb9W/4G/u/90P0c/vP9 KP4o/kv+cf4+/jv+lP5R/nH+Qv4l/gL+7P3T/aT94/32/db9dP44/kv+//0M/un9 Iv7T/Qn+2f2q/Yr9l/1F/cD9L/3G/c393P3Q/Q/+5v3G/eP9w/2t/Wf9ZP3A/WH9 rf2a/Rz+3P17/h/+W/7//U7+Iv6a/jj+4P53/jX+Iv44/hX+cf4f/lv+DP6w/jj+ l/5e/of+Qv5V/h/+gf5F/pH+K/6k/iv+W/7//Tv++f0v/oT9O/66/Zr+ZP7G/lj+ d/47/iX+1v2B/hz+Mv4S/rf+Iv6O/kj+e/5o/s3+sP7g/r3+wP6w/qr+hP6O/kv+ SP4c/mv+6f1h/kL+lP5C/jL+D/7p/c39K/4Z/mj+9v07/vz9Bv7//SX+5v1k/g/+ a/4f/mH++f17/j7+lP53/lH+//1Y/tb9dP5O/pH+KP5x/lj+WP4M/nT+H/7G/nv+ kf5e/lj+WP6O/of+Yf5O/mv+Xv6E/pH+fv4v/ij+9v0P/vz9H/4G/gL+8/1V/iL+ KP41/vP99v3Q/cP9jf2R/cb9mv0V/vz9Xv75/T7+Cf78/dP92f3A/UX+DP5r/kL+ O/4l/j7+Ff6z/lH++f6E/lj/Ev90///+0/6E/r3+Pv5R/uP9Tv72/Yf+Ev6E/i/+ s/47/m7+/P0P/tP93P2U/ZT9l/3j/cn9rf2k/db9jf3v/a39Ev7//S/+Jf4M/jX+ //0Z/uD92f0J/sb9bv5u/hz/4P4v/8r+4P7D/qD+gf6U/oT+aP5R/rr+sP7//tP+ 7P7T/sD+e/4v/hL+Nf7j/VH+L/57/kv+K/4f/jj+7/04/gb+Nf7W/eb9//3Z/Rn+ 0/2z/XH9Tv04/Qn9fv1F/f/9wP0G/hX+L/7//f/9vf0J/qr9Gf69/Qb+0/23/jv+ HP+k/un+rf7z/qD+A/+3/iz/6f7Q/qf+l/5L/oT+Qv6B/nf+Nf4f/kj+7P17/iL+ Vf4Z/jj+4/29/Xr9+f2E/Qn+iv04/tP9Tv7//dz9yf0+/s39cf4i/m7+dP5O/h/+ fv44/j7+Nf4r/uz9S/4l/n7+aP7T/or+vf6K/p3+WP5F/vb9K/7m/VX+Iv5L/v/9 S/4S/jv+O/5x/ij+Jf7g/TL+5v0Z/qf92f2n/SX+mv0i/tb9Iv7m/f/9Cf4G/rP9 8/2z/fP98/3v/c39Qv5I/gz+0/1b/jj+oP6n/n7+Mv5C/jj+d/5e/nv+Rf5R/i/+ Qv4v/pr+Xv6k/nf+sP6B/vn+oP5+/kL+Rf7v/ar+Yf7K/pf+l/5h/qf+bv7G/nf+ ZP4f/jv+/P1+/o7+qv5V/kv+2f2z/lv+8/6t/r3+t/6q/or+3f50/n7+WP50/l7+ 0P6n/gz/p/4c/8D+1v6K/pf+aP5k/kX+wP6E/s3+Tv6B/kj+uv5x/t3+sP6n/sr+ l/6R/nf+Bv4f/sb9lP1e/ar9Xv1C/u/9/P3J/TL+mv0v/vb9Ff4P/v/9vf3J/Zf9 w/26/eD9wP38/dz9Nf7m/cn9sP0P/rb9Gf4i/rb9zf2w/Zr9oP2B/af9a/1k/R/9 bv38/H79Pv2k/WT9Yf1U/dn9rf26/cn9W/0S/a39bv3c/dP9Bv7c/fP9yf1O/u/9 Yf7//RL++f0r/g/+W/7Z/Q/+0/1x/g/+d/44/vz+SP7//q3+p/6U/l7+cf4v/hn+ iv5C/mj+O/4f/un9/P3m/VH+DP6R/hX+Jf4V/mT+KP5V/mT+S/4f/uz9tv0o/rr9 Vf5R/l7+Uf6O/mH+wP6k/uD+hP6t/m7+Yf5F/mH+O/5x/nf+p/5R/l7+L/7D/rP+ Nf/j/jj+cf4v/hL+a/4c/nf+H/4G/ub9S/7j/TX+sP3J/Wf9rf1U/Z39iv2n/aD9 rf2R/c39p/2d/Z39gf1x/fn90P01/uD9ZP7Z/R/+K/5V/hL+d/5I/kv+Ff5+/ij+ ZP7J/R/+7/10/k7+SP5C/jv+3P10/jX+aP4+/i/+1v38/eb9iv41/mv+//0y/gn+ cf4r/lH+Bv4v/rP9/P2n/SX+Bv4i/tP9w/3G/Rn+4/3W/X79vf2R/Qz+1v0y/tb9 Pv7m/V7+Iv6B/kj+Mv7m/Qn+0/01/tb9Uf7m/RL++f07/jX+Nf4S/kL+Ff53/g/+ a/4l/gb+p/2q/Vj9iv1b/Yr9WP2a/Yf93P2g/en91v3D/c394/3c/eb97P2z/bb9 qv3Q/en93P3m/dn9DP7j/SX+Ff5L/u/9DP62/TX+7P0i/rb96f2k/fP9vf0V/uP9 //3W/Tj+4/0r/kv+Mv5L/pT+W/5V/jL+O/4V/v/94/1x/lX+hP5b/lX+Pv44/g/+ Nf5I/kv+Jf4f/hn+oP5o/qD+e/5Y/j7+Rf4Z/lj+Vf57/nH+Vf4o/nf+cf44/k7+ //3p/Qb+3P0v/vz9Jf4v/nT+H/7m/dD9oP26/dD9tv3J/Yr9/P3W/eD9l/3Q/bD9 Bv7v/cn91v3D/en9//3j/TX+Av7//SL+Gf4v/g/+8/0+/un9Bv7W/RL+wP32/dz9 +f0C/lX+Vf4y/g/++f3j/TX+//1L/ij+0/0C/vn90/1e/vz9Uf4i/gb+0P0i/u/9 Nf4V/tP92f3G/RL+Qv7p/S/+4/0y/gL+S/5L/uD94/0v/vb9Jf4r/iL+Ff4Z/rb9 +f3D/Wv+Mv5x/iL+WP5Y/nv+Iv5I/jj+Vf4r/jX+6f0c/tP9Mv7T/X7+e/5r/iX+ /P3m/RL+0P3z/cP9wP3G/cD9kf2t/ZT90P2a/Yf9Pv2K/Yf9nf16/Y39rf2N/Vj9 WP04/Xf9Iv2d/ZH9pP2d/dn9jf3Z/af9uv3v/Vv9nf1k/Wf9uv2z/c392f2H/aD9 w/2k/bP9qv07/WH9d/10/WT9d/1n/VT9l/1Y/YH9l/2g/Y39Nf1I/aD9dP29/ZT9 qv1b/U79KP07/ez8Rf04/Y39lP0v/sD9//3s/ez9iv3//dP9uv26/bD9ev07/rb9 bv4J/jL+6f3g/dz9OP4M/lj+Nf4l/gn+7P3G/br90P38/dz94P3D/br9wP3//e/9 gf2E/XH9W/16/WT9SP0M/Wf9bv1h/T79cf0c/VT9H/1x/Rz9dP13/Yr9Xv2t/V79 lP1I/W79a/3N/ar96f22/en93P3m/cn9sP2N/Y39iv3g/eP9Qv44/gL+xv26/Z39 2f3j/fn93P2n/VT9p/1e/bb9lP1e/UX9ZP1R/dz9vf3g/cD94/1+/ar9fv2a/ar9 zf3T/eP90P3c/cn93P3//SL+HP4S/vb98/32/Sj+DP6R/nT+jv5C/hz+sP01/g/+ hP5r/nf+S/5k/j7+Pv4i/gb+0/2n/aT9vf2U/UX+7P0C/v/9KP7Q/dz9kf2R/VT9 4P04/Sv+mv0o/rr9yf3A/db9lP3v/ar9Ff7//TL+tv3W/af9Av6q/dP9a/2k/Vj9 3P1k/aT9a/2z/Tj9WP0Y/Qz93/yE/SX9jf2R/Yf9Nf0o/db8S/0J/Tv9Ff38/L38 DP3W/Ej9Av0P/fb8Rf0c/Yf9iv3W/ZT9lP2K/XH9dP3g/WT9ZP01/YT9ZP3D/VT9 zf2d/eP9fv1V/hX+bv4J/uz9uv3G/af9yf2K/fz9p/0C/rb94/0C/vP9Av4S/u/9 0/22/Zr9d/16/X793P2X/eD9a/1n/V792f2R/V7+Mv78/eP9sP29/bb9vf2K/X79 nf13/f/90P0l/vP9wP2k/fz97/1F/mT+KP4v/h/+/P0f/v/9vf2k/ez96f3g/eb9 DP4M/uD9oP3s/a394P2w/YT9jf2a/WT9nf1k/af9Qf13/UX9tv2H/VT9HP1F/VT9 sP22/Z39qv1Y/fn8rf1+/R/+7P3Q/bb9xv2B/UL+/P0o/jv+a/5e/nv+Bv7//ez9 HP7T/Yf+Pv6H/k7+Uf4l/nH+Nf4J/tb9Nf4i/j7+Cf4+/h/+d/5V/kv+KP4Z/ij+ aP4y/jX+Gf5R/vn9Vf5V/m7+Ff4Z/vP9KP7j/fz9//3z/c39Iv78/SL++f01/vz9 H/4c/iv+Nf41/iL+WP4c/of+dP4y/ij+Gf7A/Uv+zf10/jX+a/4y/jX+7P2E/j7+ d/4f/tP9VP3c/Vv90P16/dn90/3A/aT9oP1x/c39cf0C/qf9w/1h/Zf9ZP3T/aD9 8/3A/Rn+4/35/dP9Vf7//WT+Cf57/jL+bv5Y/p3+l/6q/or+aP7z/S/+2f0Z/tD9 8/0S/vz9//1O/hn+SP7T/fz9wP1k/hL+ZP4r/gL+Bv5Y/tP9OP7//e/9w/0o/uP9 O/47/i/+D/4o/v/9jv53/pr+dP6O/lv+h/6R/oH+Rf5C/gb+//3s/Wv+Mv5+/v/9 HP78/W7+Nf50/mv+HP4V/s39sP3j/fb9DP6z/R/+pP0f/tD9DP7Q/fz9yf32/eP9 uv10/V79Tv2t/W79/P3A/fz9yf3c/cn9K/7T/TL+K/4M/uD9Iv62/SX+Cf7T/bb9 7/3T/Vv+Iv5h/lj+H/4S/uz9vf2w/Yr9qv1h/cb9jf0c/ub9+f3N/SL+xv0i/gz+ +f22/fP9w/0r/jv+5v3g/cP9nf0S/sn9Nf66/Tv+Bv6z/mj+5v6X/qT+Yf63/nf+ 1v6k/rP+d/6t/lH+pP6E/tb+e/5L/lH+a/5r/pH+Xv4r/kL+K/78/TX+1v07/v/9 O/7N/RX+3P0o/hX+Ff4V/gz+4P0P/g/+Av7z/fn9vf0l/gL+H/7g/Rn+9v2O/jv+ bv7//UL+8/1I/u/9Xv4f/mj+Rf5r/kj+oP6B/j7+8/07/ub9W/4C/j7+H/4l/rb9 OP7z/R/+2f1b/tD9DP7j/Vj+Bv4S/s39xv2N/db9kf2H/XT9hP1I/Zf9dP2N/af9 3P2t/aT9cf2q/ZT93P3A/en9dP0Z/tD9Vf7N/T7+//1k/vn9S/4C/g/+w/01/un9 e/5C/o7+Uf6t/kX+d/5h/lv+Cf6O/ij+d/5I/l7+Ff4Z/tn9K/5I/jj+5v07/vz9 HP4V/pf+ZP6B/lj+Iv7G/Qn+h/0l/uP9aP4f/kv++f2B/vz9p/5C/q3+Nf7A/mv+ 0/5u/sD+nf6w/m7+t/5V/nT+Ff5+/mj+9v53/ub+pP6O/kL+nf47/kX+OP5b/gz+ Yf41/g/+w/0P/rb9D/7c/bb9Z/0C/m790P3W/en9vf0C/tn9mv2n/en9uv01/gn+ Cf7z/TX+xv3//a391v2K/a39W/3v/Xr9Nf7Q/QL+sP1k/uz9Jf7G/Vv9VP2w/Wf9 kf1B/XT9Rf16/XH95v2a/Qb+p/0C/pH99v3G/cP9uv3D/Yr9wP2N/eP9sP3g/bP9 OP78/SL+vf01/tP97/2n/fn9qv0+/ub9//3s/f/9oP3j/cn96f3Z/S/+8/3//fP9 S/7z/WT+//2K/j7+mv6g/rr+ZP69/or+pP57/o7+Uf5h/h/+e/5k/k7+Pv5L/ij+ 4P6R/sr+kf6z/nf+bv4r/o7+DP53/kX+Rf5R/pT+bv6t/oH+uv6O/tn+pP7g/qD+ mv6z/lX+Iv5+/jj+dP5Y/nT+Cf5R/g/+cf4f/nf+Bv4+/hX+Cf7D/fz9pP3p/aT9 KP4J/vP90/3c/db9Cf7p/db9nf3N/b391v2a/b39ev3T/V79vf2z/UX+//17/jL+ Yf5h/kj+K/7G/cP90P2a/Uv+1v13/jj+ZP5O/l7+D/6R/iv+SP7j/db9qv0y/hz+ 9v3J/eb90P3T/aD91v2k/e/9zf0+/iv+KP7//fP9xv3//en94/3g/fb99v3//Zf9 //0G/gb+Bv5+/k7+l/5R/uz+l/7d/pT+vf5r/qT+W/6R/nf+p/5u/un+kf7G/nT+ uv6R/s3+pP7m/nT+Uf5I/jL+4P0i/uP9Av7J/fz95v07/un9Vf7//fz95v2t/aD9 wP3N/a39fv2z/br9K/4M/lj+//1V/sb9jv72/VH+2f32/bb9Ev7m/RL+Bv4+/iX+ S/75/Tv+Cf5o/ij+ZP4J/kv+Jf44/vn9DP7N/eP9zf32/c39//2z/T7+Av5O/hn+ /P2t/Qz++f0v/gn+HP7Q/Tv+Cf4+/v/9Uf4J/l7+Iv6d/mv+qv6E/rP+Uf63/sr+ p/6k/qD+jv6R/kX+yv6n/uz+qv6R/m7+gf5x/uP+h/6a/l7+l/44/nf+O/6E/jL+ H/7z/WH+yf1R/h/+L/5C/jL+//0P/gb+Rf7J/Rz+2f17/jj+Iv4J/gn+zf0c/jj+ a/4v/tD9//0M/gn+kf5o/nH+Rf4i/hz+a/5o/nH+Qv5k/kX+cf5R/mH+Xv4l/qT9 O/6t/Tj++f0G/sn94/3W/UX+6f1L/hz+8/3W/Uv+DP4+/tn9Jf62/fz90P1k/uP9 e/4G/pr+Mv6k/k7+e/44/mj+Mv5Y/iX+O/4G/kL++f2B/jv+1v5I/sP+kf7D/pT+ 6f6K/qf+oP6H/i/+bv4c/qT+Pv7K/lj+0/5u/p3+jv5k/kj+xv5O/tb+l/6O/k7+ bv5R/qf+kf72/t3+sP6n/uP+yv4M/7D+1v6R/rD+Uf7W/qT+0/6n/sD+t/7N/pr+ 5v6d/mj+aP5e/lH+h/5R/pH+Xv5u/kL+a/5u/mH+e/4+/jv+Jf7//Rn+DP4S/uz9 nf04/cD9qv32/ZT9d/2z/bP9kf22/Xf9lP10/c39jf3Q/bD9mv16/c39sP0P/uP9 Uf4P/l7+/P1C/gb+Nf72/QL+5v3//f/9Uf4C/o7+W/5I/h/+Yf4y/lX+HP5C/v/9 WP4r/h/+Ff4V/tn9Nf4P/jL+Gf4+/gn+Tv44/n7+W/4l/iL+Ff7//VH+aP6z/mH+ nf5V/pT+fv7m/qT+xv6t/h//4P4o/zL///4J/wn/4/4v/8r+LP8c/xX/A/8l/wn/ Rf/Z/g//vf6z/nT+8/6K/sP+zf7T/pf+l/5e/qf+qv5u/vz9Jf7s/SL+Av4i/tb9 Jf4M/hX+K/4M/tn9L/6N/QL+3P0i/v/9Ff7//Tj+H/41/s39Ff7A/Uj+9v2O/i/+ uv5o/oT+DP6B/jX+iv41/nf+//07/kL+Tv4+/vn90/2w/XT9Mv4C/h/+4/0S/vP9 aP5o/oT+WP5u/gL+WP4C/n7+Nf4G/tn9KP7D/WH+Gf5F/lj+dP4S/rf+kf6X/pT+ e/4o/kj+K/5k/kL+Qv4l/kL+Tv5O/lj+e/57/rf+h/5+/n7+Xv4l/jL+KP50/qD+ 1v6H/mH+d/6a/of+xv6q/sr+t/6n/l7+wP5e/qf+s/66/nv+jv6X/qr+l/6d/pT+ mv6O/kj+O/5b/lX+Xv5F/l7+Yf6q/nT+2f6k/r3+gf4f/9b+uv5k/oT+W/5r/lX+ Vf7//ar+S/6E/pH+xv53/r3+hP7G/or+qv57/iv+6f0J/uP9Uf75/Uj+L/4v/uz9 Xv5F/n7+ZP5r/k7+jv6O/sr+gf6O/jL+uv5V/un+yv4Z/+P+//69/ub+iv78/tD+ A/8f///+Ff9O/w//Ev/d/vP+l/7g/pf+yv6U/o7+ZP6d/pH+e/6H/qr+e/6g/mv+ pP5I/pH+S/5O/vn9SP4S/lX+Jf5L/vb9hP5e/qf+h/6O/nT+hP5Y/of+mv53/nv+ uv6d/rP+nf6t/pT+8P6t/tn+t/7Z/rD+0/6O/rP+lP7W/rr+kf4r/qD+Yf7G/sb+ rf6B/l7+K/6B/lj+SP44/iv+DP5L/gn+bv53/sD+jv7j/lj+w/6E/vn+zf7g/tn+ wP7A/g//vf4P/+b+LP8Z/3v/KP9r/xL/cf9F/37/Mv9Y/+D+//7p/ij/8/4D/wn/ L/8v/2H/Tv9V/y//Gf+6/qf+e/6O/sb+qv66/rr+qv4P/+D+S//j/gb/8/4v/3H/ KP8f/6f+8/69/s3+a/8y/x//Iv84/xz/eP+K/3v/hP8c/xn/5v7//hL/Qv8G/1X/ 5v4Z///+/P63/n7+gf6R/pf+sP7s/qr+Ev+6/pr+kf47/lH+Tv44/jL+S/4+/gb+ 9v3z/Q/+zf0l/u/9gf4P/lj+Qv6E/kv+Uf4r/hn+8/2H/jv+mv6X/sr+qv7Q/qD+ 4P6d/hz/5v4v/93+Gf/2/ub+2f7g/tb+8/6n/tD+hP6d/kj+5v6K/tP+4P6O/q3+ lP6E/tP+t/6w/rD+dP5e/nf+gf6n/or+8P6a/tP+oP41/93+DP+U/gP/w/4c/+b+ yv7G/sb+w/7Z/tb+D////mj/Tv/g/un+//7p/g//3f7T/s3+Ev/d/un+8P6t/sb+ wP6H/qf+qv5C/iL+d/4l/mv+Xv5b/lj+Xv5L/pH+Pv6U/pH+bv57/p3+dP5h/j7+ HP5C/ij+L/6g/l7+d/5L/nv+a/6O/qD+e/4+/j7+4P04/gn+Uf5L/kL+Mv4o/jv+ SP5o/jv+OP7c/fb9Mv41/sb+p/6a/qT+nf50/qf+pP5r/mj+iv5e/tD+h/6z/nf+ pP5e/rr+l/4P/9n+Qv8D/0j/KP8i/+P+6f6k/r3+iv7d/rf+LP8D/0L/A/8P/yz/ //4l///+Cf///uP+8P69/s3+kf5e/pT+lP6q/sD+4/6w/rf+sP63/sb+2f72/rD+ 0/6R/rf+lP7K/qf+0/7G/hX/zf4c/93+yv7D/gz/5v78/tb+t/6g/rr+lP66/pf+ 6f6k/qf+e/7D/nT+uv6a/pH+a/6R/j7+iv57/lj+DP53/iv+Xv47/hz+K/4+/gn+ SP44/jv+Vf5F/lv+Nf5V/kj+H/5O/k7+OP4V/lv+Jf5u/kX+W/5u/uP+kf6z/nH+ d/5r/sP+oP6B/nH+ZP50/pf+jv4P/w//L//d/vP+qv7//hX/OP8f/xX/DP8P/wb/ A////v/+7P4V/9b+8P4D//P+5v5h/0X/Cf9I/7P+0/7s/sP+Rf9I/yX/2f4V/yX/ iv+H/07/O/8y/xL/8/75/lj///5I/yj/LP///gP/Cf8V/zX/9v7G/rf+l/50/qD+ cf4+/qT+jv6E/of+cf5b/pH+Yf57/kv+a/4y/mT+2f0l/kL+O/5k/mT+Mv4C/ub9 1v35/Sj+Nf4o/gz+Gf78/Q/+Bv7//fz9/P3Q/Rz+Av5b/jX+Vf5R/pH+Xv63/mH+ qv6E/lX+Vf6X/lX+SP4v/iv+Nf66/n7+Rf4f/lH+e/6k/qr+Vf72/Yf+L/6E/nT+ d/5r/oT+Pv7D/sD++f7D/pf+t/6H/o7+D//j/vD+2f75/v/+5v7p/gP/yv7Z/rP+ Cf/m/hL/P/9C/1L/8P4P/yX/9v72/hX/s/6K/un++f6k/t3+cf6E/qf+p/6O/p3+ e/53/mj+ZP6H/jv+cf5+/h/+Cf4y/sP9Mv4S/jX+Pv4+/jX+W/4v/lX+WP4P/gb+ S/7W/Tj+DP50/lj+dP5O/j7+L/4f/v/9Cf4C/mv+a/5+/jv+bv5C/k7+Ff5R/gn+ Nf5F/n7+SP4f/ij+O/7m/fz9+f0P/iX+bv47/kX+iv6X/pf+KP4S/gz+7/1C/iL+ SP4C/lX+Xv6g/rf+WP/5/vP+4/6a/qT+0/6n/tP+qv6d/or+vf6K/i//Ev8y/yX/ Qv9C/yz/5v6a/s3+uv7W/sP+nf5u/oH+yv5r/iz/wP4J/7P+sP6E/pH+O/5x/i/+ SP4V/oT+Uf53/lv+h/6U/nH+l/7j/rr+yv7A/nT+Yf6R/m7+zf7K/vz+w/7s/qr+ KP8//07/+f78/sP+uv7W/vz+8P7W/tb+3f63/tD+3f63/tb+zf6g/iL/zf4D/9D+ fv5O/lj+Uf5I/vz9HP7m/Wj+OP6k/kL+WP5O/iX+H/5Y/lv+WP44/pr+iv6g/mv+ h/5O/r3+jv7N/n7+zf6a/gz/p/7G/sb+qv5+/tb+h/6a/nv+s/6t/qr+l/66/qT+ l/5o/k7+dP53/i/+HP4J/gz+9v1F/hL+Rf4Z/pH+Tv4+/gL+Rf4f/nf+Bv5L/hn+ Iv4Z/kj+K/6B/n7+Pv47/nH+Ev5C/lX+iv6B/j7+7/0S/gL+W/5o/or+WP6U/n7+ fv5F/lv+L/4v/jv+KP4i/kv+Cf7Z/SX+ZP44/nv+ZP4i/jv+aP5o/l7+Xv5r/hn+ SP7z/U7+Av4y/vP97P29/Qn+wP1u/j7+gf5C/mv+H/5F/iL+S/4G/mH+K/5O/hz+ K/7j/S/+8/1C/jL+fv5k/mj+KP5R/ij+a/41/gz+Ev7c/eb9H/4J/j7+H/5e/lX+ nf6B/jL+Jf4J/sD9D/4J/uz9Cf4l/vb9Uf4r/nH+Tv6K/mT+Vf5o/pT+W/6a/nv+ hP5I/mH+/P2O/lX+fv4y/o7+KP6O/n7+oP53/or+aP6k/m7+fv4v/jj+Gf50/lv+ oP5k/qT+gf6B/jj+a/5F/iL+H/5L/ub9Xv5V/lH+D/4J/vz9H/7s/VH+Mv4y/hL+ W/4c/o7+Xv57/kL+Qv4J/of+Mv7g/p3+mv50/pT+Rf5b/mj+yv66/ub+Xv6K/jv+ pP5h/nH+SP4+/hn+Xv5V/rr+gf6d/mv+kf5b/qD+K/41/h/+aP5I/kL+H/4l/gn+ jv4i/qf+e/5+/jv+oP5R/mv+Iv5x/hn+Rf4y/mj+Tv5b/iv+d/5F/o7+cf7Z/p3+ gf5h/lv+HP4o/g/+7P2w/fz9KP5F/ij+S/7//XT+Rf5V/oH+WP5R/tD9tv3W/Zr9 +f3J/en91v0S/uP9Nf4r/j7+Bv7v/Qb+KP4C/jX+5v1Y/hL+Rf7//X7+K/6w/lX+ qv5r/kj+d/6E/hz+Nf4i/jv+K/4c/tb9S/4G/lX+L/5I/jv+Pv72/fP9zf0G/sn9 2f3v/eP9sP0V/gn+6f3s/cP94P04/vn9Vf4l/kL+HP5h/jj+SP4S/lj+6f07/jj+ OP44/lX+K/6B/kj+hP6K/oT+O/6t/of+nf6k/rf+p/6k/pr+Yf6B/nH+a/69/s3+ iv53/lH+Uf5I/mT+a/6K/k7+W/5r/pf+W/5I/jv+Av4v/g/+yf3T/cb97/0f/iL+ L/4i/hL+0P1C/vz9d/4i/kX+Rf5L/hL+S/75/Sv+Mv4y/iX+h/5o/qf+Yf5F/mj+ Mv4o/tn96f2t/eD9rf2R/dz9rf3m/br92f3Z/Tv+Ff4S/rb9xv2n/VH9Xv1F/SL9 jf1I/cP9mv1e/hL+aP47/hX+Gf7N/cD9vf16/a39jf22/Xr9Gf7//RX+7/01/vP9 Uf5b/or+Tv7D/bD9pP1x/eD9pP3g/a39Ev72/Vj+SP6O/lj+bv47/jX+Mv4P/tn9 Jf78/Sv+Vf5h/nf+WP4+/mH+KP6B/nH+fv4+/gz+D/5r/lj+mv5+/p3+a/6g/nT+ 8/6H/vP+wP7s/t3+Mv8G/2X/Ff8M/8b++f6d/uP+4/7A/m7+Iv+k/m7//P5V///+ 8P6z/tn+jv7N/oT+mv47/of+KP4y/h/+Xv5r/qf+cf5k/kX+oP5x/k7+S/5k/k7+ Vf5C/jX+Gf7T/v/+s/7j/pr+mv5x/lv+O/4i/gb+//3c/aT9Tv5I/kX+OP4c/gn+ Ff7Z/bD9l/1r/UX9h/1I/a39tv3A/br9uv2U/U7+Bv47/j7++f3//fz96f0v/kv+ Rf7z/UL+Gf5h/pf+s/6R/of+lP7K/tb+t/6R/nf+dP6E/kL+O/5e/iX+K/5O/kj+ lP5+/pf+cf63/qf+0P7Q/of+lP4Z/ij+W/5h/qD+Uf6H/qD+7P7g/jL/KP8P/wP/ 8P7Q/tD+yv63/oT+ZP6a/l7+gf7D/qD+sP6a/qT+sP5e/rr+gf50/ij+7P3T/ez9 K/47/l7+WP7N/qT+fv6k/hL+Cf4f/kX+O/5u/i/+O/7v/dn9w/3T/Z390/3g/dn9 6f0C/tb92f16/b39hP1x/Yf9dP1x/Vj9l/2E/cn9wP3D/dP9w/29/db9yf2n/cP9 qv2z/a39pP3D/eD92f3Z/dD97P1V/kX+8/3z/dn9/P0r/kX+8/0P/gL+2f0i/uz9 KP4M/jX+W/4o/jj+Ev78/SL+L/7z/RX+Gf7z/UX+Nf41/jX+Iv4c/m7+KP4l/ij+ e/4o/mv+Vf4P/iL+D/47/oT+W/6H/tn+dP6k/or+WP5b/jj+Ev5R/un9HP44/k7+ d/57/nH+Yf6O/qD+l/6n/mj+Yf5h/kL+SP5o/v/9D/4i/hL+3P3N/Sj+1v1V/jX+ Xv50/ij+9v3m/cD9KP4M/gn+5v0v/tP9H/4G/gn+DP5F/jX+D/7j/Wj+Vf5V/k7+ HP4C/vP9//07/vP9KP4V/gb+Cf5O/iX+WP4Z/mv+SP4y/kv+O/44/of+OP5F/j7+ Xv5x/nf+Uf5k/lH+aP5+/lX+SP5b/i/+WP4P/jX+Iv6U/j7+kf53/o7+cf6a/pT+ a/5e/oH+Yf6U/p3+nf5u/tP+w/44//b+4P7N/kv//P4S/9D+qv7N/qT+nf6B/nT+ yv63/uP+0/7A/rr+qv7z/vb+6f7N/uD+wP7T/pH+w/7Z/rP+4P6k/pH+0P7G/vz+ 4/4l/83+9v7D/tD+w/69/sr+rf5k/nT+dP6B/tP+1v72/rP+lP50/pT+d/6w/nv+ a/5O/qr+dP6t/n7+aP5x/n7+bv5b/j7+aP4M/nv+SP50/oT+jv5R/kj+L/5L/hX+ Xv57/pf+p/63/p3+w/6n/o7+mv6K/lH+cf5R/qr+t/72/qD+7P7w/g//2f7s/qf+ wP7d/vn+mv7z/qT+pP6X/rP+dP6k/oH+t/6X/t3+8P7A/sb+qv6U/sD+zf7D/r3+ rf6H/or+oP6q/s3+vf7s/oT+qv6z/rD+9v7W/t3+yv7K/r3+HP/D/gz/7P6n/nv+ p/5r/oT+jv5u/kv+cf5F/nH+Vf6H/nf+h/5u/nv+Rf5+/jL+KP44/j7+L/41/hz+ SP41/lX+Tv6R/mj+hP6H/k7+S/53/ij+s/5k/o7+Mv5+/s39O/7//TL+6f0r/hL+ a/5C/mv+bv6a/oT+hP5R/kX+WP50/j7+S/5C/lH+Ev6w/jv+d/5k/tP+dP69/nf+ 4P5k/nT+Iv5L/iv+Tv4l/lH+Qv57/hz+lP5r/rD+d/6U/or+W/47/lj+WP6X/of+ Cf7z/Uv+Ff69/o7+zf6q/gn/0P7s/qr+4P6U/p3+bv5h/kX+W/5C/oH+iv63/pT+ sP5e/pH+oP6O/mT+d/5r/qD+Xv6B/kX+d/4l/pT+Mv6g/qD+wP57/hX/oP7A/pH+ ZP5o/nf+Pv5V/jj+Tv53/of+Gf5+/oH+Pv4S/mH+Nf53/hn+Iv7//dP96f3z/fb9 Bv78/R/+/P0v/vb9cf5O/lH+Iv53/mv+kf6H/of+Xv6B/pH+8/6t/vz+3f6R/mT+ rf6E/pH+aP6n/oT+OP4y/or+Pv72/qf+w/6t/rP+wP7w/uD+uv6O/tb+iv4D/+D+ 8P7D/r3+wP7w/pH+Ev+n/gP/jv4V/7f+/P6a/tD+w/7D/pf++f6t/tP+5v7Q/qr+ 0P66/r3+wP63/rP+oP6O/rf+ZP6O/n7+WP4o/j7+Ev4y/vb9h/4r/qf+Xv5o/ij+ Vf5F/iL+Rf5k/vn98/26/Tj+Jf5Y/mj+l/5V/qr+OP6d/o7+h/6O/or+e/7T/pr+ mv5R/rD+Vf6B/mv+lP6O/o7+Xv5Y/kj+W/50/mT+ZP5b/kj+dP5L/m7+W/5u/lv+ bv53/q3+zf7p/pT+0P6t/iX/6f41/9n+/P4G/yL/Ev8Z//b+Iv8D/w//1v4c/xz/ Nf8D/yX/9v75/hX/0/7j/sD+w/7W/qT+8/6d/qf+pP7G/nH+w/6w/iX///7Z/tP+ wP7G/tb+l/6k/of+t/6B/s3+lP6a/pH+nf6w/pr+bv6O/kv+bv4r/mj+Bv6q/kL+ xv57/rP+a/4G/8D+wP6X/pH+SP6U/ij+dP5F/tb+ZP72/o7+8/7D/uP+3f63/qr+ wP6a/rD+h/63/nv+l/6t/tP+sP7K/pf+6f7D/qD+zf6B/k7+hP5u/o7+WP7p/rr+ /P78/kj/8P41/7r+/P7d/vz+0/63/oH+2f6g/vb+rf47/93+5v6n/iX/8P4f//b+ 0/6K/q3+h/6g/mv+pP5x/n7+jv7A/s3+4/6z/gz/qv7N/nv+t/5O/or+jv6k/mH+ bv5h/qD+bv6k/k7+qv5x/uz+pP6w/qr+Iv5L/gn+Av7v/fn94P2t/e/98/0M/vn9 Rf7m/Vj+WP6O/q3+Xv4+/mj+HP5I/l7+Tv75/WH+OP6H/kL+jv5C/nH+H/5V/kL+ Iv4+/hn+6f35/af97/38/Uv+H/5I/kj+KP7z/fb94/0Z/un9KP5Y/oH+uv63/qf+ Cf84///+4P6E/or+Tv5O/nT+h/4v/n7+S/5O/t3+8P66/r3+xv63/rP+xv6X/rD+ 1v7N/rP+d/6g/pr+3f6R/pr+pP7T/qD++f7N/vD+3f7j/vD+Cf/d/t3+iv6n/mH+ 6f66/s3+oP6U/lj+sP6a/sP+1v7m/sb+HP+w/vP+Iv/w/uP+mv5Y/r3+rf7W/nv+ 0/7G/sD+0/4D/83+1v63/tD+mv7G/sb+s/6B/oH+e/6U/n7+jv5k/mj+aP53/mT+ xv63/p3+jv5L/kL+d/5C/n7+S/7G/sr+w/7A/sb+w/6g/o7+ZP5h/nT+cf66/pH+ mv6t/qf+mv6t/pT+qv57/i//2f7w/q3+4/69/vz+8/7z/tD+zf6z/gb/Ff8V/yL/ Nf/5/gP/yv4Z/wb/OP8//2v/W/+q/0X/e/90/37/Jf+O/w//iv9o/6r/lP9+/4H/ fv+X/5H/fv+q/2H/p/84/1v/OP8//zX/Ev8o/z//A//W/vD+OP/Q/jL/9v7w/vP+ 5v6U/t3+p/6z/q3+iv6O/r3+iv7K/sb+5v7K/gb/0P7m/pf+8P7T/sr+jv78/sD+ 0P6U/sb+rf6q/s3+LP8S/0j/Iv8P//P+vf7D/rP+S/5h/lj+h/47/or+a/7A/mH+ a/5e/lj+OP7m/fP9Iv7T/S/+KP7z/en9H/7W/VH+KP6R/lj+L/4M/m7+HP6B/or+ hP6O/or+dP7T/r3+A//Z/uP+nf7T/rD+6f7W/hX/2f7G/tP+zf4J/wP/2f4V//D+ 6f7W/vP+nf4D/7P+wP6t/vz+yv4M/wn/4P7d/un+0/7K/rr+h/6R/g//oP4f/xn/ 5v7z/vz+wP7s/s3+t/6X/s3+3f7A/tb+s/7D/vn+9v7p/uD+4/7//sr+7P7Z/tb+ vf7d/gP/2f7Z/tb+8/7s/vD+Bv/Q/vD+p/6a/qT+ZP6E/pH+nf6R/kj+aP6O/oH+ sP4J/6r+uv6B/o7+Nf5+/lv+Uf4v/oH+Vf5Y/p3+rf6n/un+0P6H/sr+t/6O/p3+ kf6K/of+t/7d/rf+5v7d/qf+zf7K/sP+2f66/kX+ZP6E/mj+pP6U/lj+h/6g/lj+ hP5+/pT+e/50/mj+cf53/mH+Vf5r/pr+rf7d/uD+zf7W/vb+yv7g/nT+fv6R/l7+ hP6a/uD+uv4v/wz/Ev///jL/L/9F/0v/LP/p/vn+3f4f/yL/1v7D/uD+8/4P/wb/ KP8G//b+Bv8c/+n+DP/j/gb/+f7A/sb+xv6q/qT+oP5R/nH+yv6w/hn/Cf8l/wP/ 8/7z/gb/qv6R/r3+iv50/s3+0P6a/vn+5v4s//D+Ff8D/yj/L/8s/9P+vf4M/93+ hP6O/q3+l/4G/9b+6f7s/gP/Cf///vz+4P7D/n7+qv50/rr+rf66/rD+t/6X/p3+ rf6w/pT+p/7Q/n7+0P6g/tn+qv6d/mT+sP7A/qD+w/7K/vn+Bv/s/sr+s/7D/tn+ uv53/pr+mv6d/nT+xv66/sD+fv6w/qr+bv50/nv+O/7K/pH+cf6K/rf+l/63/rr+ 0P7W/q3+t/6z/pH+2f7z/t3+sP6H/or+l/7s/uD+wP75/qf+Cf/W/lL/L/8i/wz/ L/8G/x//H/8G/9n+L//8/vz+D//z/vD+vf66/uz+rf7m/tn+//7Z/t3+s/7N/uP+ lP63/or+d/6O/rr+oP6n/m7+bv50/pf+hP5k/nT+kf6k/o7+xv6X/pf+cf5x/oH+ bv5R/oT+Uf6K/lv+wP6X/tb+mv63/sb+4/7d/uz+A/8D/7D+rf5+/rD+xv6n/sD+ kf5+/t3+t/6q/pr+aP5x/l7+d/5O/n7+W/6U/kX+Iv47/jj+e/5h/mj+a/6w/pr+ qv7A/qf+oP6t/pT+lP6U/mH+hP5o/nT+mv6t/pT+nf6E/or+0P4M/0v/Mv8i//D+ uv6z/sD+0P7Z/tb+7P4c/wz/2f4V/0v/HP8Z//P+Jf/2/vb+4/7s/iL/DP8D/9b+ wP6n/qD+Xv7j/s3+yv7Z/gb/A//p/sP+1v69/sb+oP63/vD+2f4i//z+D//j/sr+ 8P4P/83+Ev8l/yj/O/9C//P+LP/Q/qr+sP6X/pr+pP6H/nv+nf6O/tn+0P6a/p3+ vf6X/pf+oP6q/oT+iv44/k7+W/6R/kL+WP4r/nH+aP5F/kL+kf5V/r3+iv6B/p3+ xv6O/qT+fv6H/oH+zf6n/rf+uv4i/7r+P/8J/w//Iv8c/wz/Jf8J/xL/6f7j/un+ wP6z/s3+rf7j/qf+8/7Q/lL/Jf8f//D+mv5+/q3+e/6k/pT+sP6R/s3+wP4M/xL/ Ff8M//z+Cf8V/yj/LP8f/wb/L/8v/yX/Uv9r/yz/Qv8y/2v/Nf9o/1v/hP9Y/4H/ Yf9h/yj/Uv/Z/un+HP8Z/1j/a//5/vz+6f78/gz/Mv/j/iz/+f4V/xn/L//8/vD+ 8P4J/8r+LP/d/iX/7P4J/wn/P/8P/xX/4/4S/8P+Bv8M/wn/3f72/un+Ev8v/2H/ +f4M/zv/Nf/Z/hX/6f7z/vD+w/7W/sP+l/6k/nT+bv5r/rP+yv7g/tP+zf6X/oH+ lP6n/qf+d/4+/nv+hP5L/rr+pP7T/tD+zf66/g//D//w/gb/sP6d/of+jv7Q/sb+ 2f7g/hL/Ff8Z//D+Gf8l/+D+/P6w/rP+DP/m/pf+rf7p/tb+Cf8M//P+yv7p/gn/ Ff8c/wz/DP90/o7+p/53/gn/w/4S/7P+O//j/vz+rf72/sD+Iv/2/jj/Ev/p/vP+ Bv/m/sb+9v4G/xL/3f7Z/hn//P5L/17/H//8/vP+Cf8f/xn/Cf/w/un+6f7j/tD+ pP6O/i//4/4G/+P+7P7N/nH+d/6K/oT+Xv5u/kj+Ff44/jL+Nf5b/lX+Cf5L/kj+ L/4c/kv+e/4r/hL+zf3T/db9w/32/e/9iv4Z/lH+Uf6q/nv+e/4P/mv+Mv5o/jj+ Yf5O/lX+lP57/m7+0P6a/qf+jv7N/m7+xv6U/qr+gf50/nf+lP6U/sP+jv6t/q3+ t/6g/rD+t/7g/tP+w/7D/uP+D/9Y/xn/vf7N/sP+7P7D/rr+p/6n/tD+p/4D/47+ rf6n/gz/oP7g/qD+w/6g/rP+jv7A/qT+zf6B/sP+l/7A/q3+uv6X/n7+fv6w/p3+ uv5x/nv+jv5b/k7+Uf5e/of+jv6a/mj+jv6X/oT+Yf4c/jv+Xv41/lv+7P0v/iL+ SP47/n7+jv6t/pH+WP5+/nH+Qv6a/mv+l/5I/rf+h/69/p3+qv6k/p3+h/7K/o7+ 0P6U/sr+iv53/mv+mv6w/qf+h/7K/sD+A//W/un+iv63/p3+l/6w/q3+rf6E/nH+ nf6g/gz/Gf8Z/zL/+f5C/yX/Gf8J/yX/dP9O/3H/Rf8s//b+Mv9L/3H/Jf+n/1v/ kf+O/4H/e/9L/xz/uv7A/pT+wP6q/nH+sP7W/tP+A/81/yL///4D/8r+wP63/or+ wP6H/rr+dP6a/j7+0/6n/sP+rf6t/qD+rf6a/tn+DP+6/t3+s/69/rD+oP6k/s3+ yv7z/r3+Gf/Z/rD+pP6t/sD+2f7W/tb+jv4l/83+Jf/W/gn/4P6t/q3+w/7m/vb+ 9v7Q/t3+sP7z/tD+D//s/i//DP9V/wn/OP9I/z//Gf8s/xn/9v7Z/ij/4P4D/8r+ LP8i/4H/Uv97/1v/aP9+/17/e/+E/5T/Zf9I/0L/Vf8o/9n+Qv8Z/yz/qv5O//z+ Ev8V/zj/A/8G//n+0P7g/sr+wP7K/r3++f7g/gP/LP8l//z+D//m/tb+9v7G/tD+ 6f6K/vz+0P7K/vD+6f66/sr+t/7Q/qf+yv6n/rf+nf5Y/l7+Mv4i/mv+Nf5x/or+ Pv5L/iX+DP5k/mj+hP53/sD+lP57/nf+ZP53/nv+Qv53/ij+Iv47/ij+WP6R/q3+ lP5u/jX+S/5Y/mH+dP5x/mH+WP5Y/m7+cf5h/nv+a/5R/k7+O/5F/nv+Uf5e/k7+ dP5F/or+p/6a/of+pP6H/l7+fv50/qD+iv6U/s3+1v7d/pr+6f7W/tD+DP/K/sb+ yv6k/r3+nf7N/sP+xv7Z/sD+0P7N/qT+yv69/pH+fv6B/nf+l/6K/o7+dP6K/sP+ 6f6t/iz/5v5b/0X/Rf9C/93+2f6t/t3+/P7T/vn+DP8y/xz/Bv8D/93+wP7d/uD+ sP6d/r3+nf7d/sD+8/7p/jL/P//W/vP+4P7d/jL/6f7K/uz+7P6w/hn/D/8D/1v/ 4P4i/yz/S/9b/3j/Nf9F/+b+//7Z/vz+2f4M/73+xv7z/s3+Iv8o/1L/Iv9L/xX/ Nf8V//P+mv6z/nv++f78/s3+nf78/t3+Gf8S/1j/Qv8G/0j/e/9b/2H/gf/d/vz+ vf78/oT/Xv8v/07/5v4l/2X/O/+k/2X/Tv9Y/zX/P/8v/yX/Yf9h/2X/Tv8Z/xn/ L/9S/1L/KP9b/0L/Nf9h/+z+2f7Q/rf+Ff9L/y//Ff/m/v/+Mv8i/3H/LP8M//b+ 8/4l//D+Bv/D/v/+sP4P///+4P7w/gb/kf66/tP+2f4o/w//6f6w/tn+s/7Q/uD+ 1v6k/vD+t/4V/w//P/8y/0j/Gf8s/y//8P4S/+D+t/7G/rr+0P7A/qD+nf6R/tb+ 3f4M/+n++f7T/t3+oP6k/hL/4/78/vP+9v4P/+b+yv7W/tD+w/7T/s3+1v7Q/vb+ yv6n/ub+4P7m/sb+6f6k/sr+2f7Q/vP+dP6R/mv+zf7Z/tb+0/7w/rr+4/6z/tn+ uv4c/73+/P7K/rf+zf63/gz/9v4S/xX/8/7p/tP+9v7D/s3+t/63/r3+uv7w/tP+ /P72/hn/wP7d/q3+4/66/sr+jv7Q/rf+jv53/nv+kf7N/rD+p/69/q3+fv6O/pf+ cf4+/t3+l/7K/rD+WP5I/kX+L/5R/iv+S/4r/uz9+f0S/vz9Jf4M/jj+2f1C/gz+ L/4r/iL+6f1r/j7+Jf4S/kv+ZP6q/mT+mv6O/oH+e/6n/nT+fv6k/tD+4/63/rP+ sP6k/tP+s/7//g//sP5o/gP/Bv8l/xX///4P/wP/zf75/sb+Ev///hL/HP8M/xL/ 9v7s/gz/H/8v//b+Bv8M/zL/OP87/xX/P/8f/yz/Jf8G/xL/Gf/2/lj/L/87/1j/ Mv9I/z//Vf9C/17/Vf9b/2j/Tv9V/yj//P4c//D+4P5L/0v/Rf90/xz/OP87/yL/ 8P4M/+P+Cf/5/iz/5v4c/9D+t/7w/sr+Gf/2/g//2f4V/x//O/8y/wn/5v7Q/sb+ vf7W/o7+kf7D/r3+A//z/sP+l/5L/or+cf6w/uD+/P7m/g//p/7K/oT+d/6H/pf+ ZP6t/qT++f7W/sb+8/7N/uz+wP7Q/vb+/P7m/vP++f4Z/xn//P69/sP+pP7Z/vb+ Gf8V/0L/HP9I/1v/h/+q/5T/uv+0/3j/dP+E/4H/aP97/3H/pP+d/8f/qv+E/3H/ h/97/2j/WP8v/wn/H/8i/yz/DP9e/0X/Mv9O/z//SP+R/1L/e/97/4f/Xv9Y/2v/ D/8J/93+Cf8S/2v/Ff9L/4T/bv81/1j/H/8D/wz/3f4f/9n+HP8D//P+2f7m/or+ yv6E/s3+uv6O/qD+5v78/sP+4P4G/wP/zf7p/iL/+f4V/+P+7P7Z/g//yv7m/rD+ DP/d/gb/9v4V/w//1v4l/73+oP4c/xX//P41//b+0/7z/hn/zf66/uz+s/7j/tD+ Ev8P/1L/Zf9x/5H/e/9h/17/S/97/6H/gf90/5H/lP+O/4T/e/+X/17/eP+E/3v/ x//d/37/aP8v/0X/cf9V/x//Nf94/3T/bv9Y/07/eP8o/1X/5v72/h//W/9o/3T/ Qv9V/yX/SP/w/mX/KP8S/3H/W/8Z/zL/W/9b/xn/Vf8Z/yL/Iv8o/z//LP9O/yz/ Xv9L/xz/HP8c/xX/Mv8G///+7P7//ub+Cf/m/i//Rf+w/iL/gf6d/pf+h/6X/m7+ ZP5r/rr+rf7w/uD+pP69/tn+xv4S/83+0P7A/tD+DP/w/tD+s/6a/v/+0/4f/yL/ H/8l/0L/Bv8f/yX/zf72/uz+Ev8i/xz/Cf8f/z//Jf9V/z//Yf9r/z//DP8v/xX/ Ff8P/9b+Iv8f/wP/WP9F/2X/pP9r/1v/O/9Y/4r/h/+K/2j/lP9b/5T/kf+0/6T/ AwDm/1IAFgAGAO3/9v/j//n/rf+w/6T/hP9o/0j/Xv9x/5H/Qv9b/2H/jv94/1X/ fv9x/3j/cf9Y/yL/Qv8l/xz/HP8S//b+Qv8J/2H/Qv97/37/kf9V/3v/Zf9O/w// Tv8//1X/HP8o/wP/Ff8M/xX/D/8M//P+7P7G/sr+9v7W/hz/Cf8D//b++f7K/gP/ pP7K/qD+vf72/g//L/8y/93+7P7m/vz+4P7z/tD+7P6n/tb+Bv8s/1L/Jf8s/zX/ LP84/0j/Nf+O/5H/Mv+R/0v/mv+H/4T/l/9l/6f/kf94/4H/of+O/73/tP+t/8P/ nf+X/7T/mv9+/4H/S/9F/zj/Iv9L/1X/h/+k/73/vf8sANb/HADd/6r/sP+a/3H/ lP+U/3j/e/94/3T/kf+q/73/t/9L/6H/cf+B/0X/Gf8v/0L/Zf9O/yz/SP8c/+P+ Ev8v/yL/LP9V/0X/Xv9C/4f/a/8v/0j/4/7W/vz+5v4Z/yz/0/4J/z//O/8v//P+ Bv/z/iL/wP7w/vb+wP7N/pr+jv7A/qT+8P6t/hL/4/7p/hL/Bv8G/xn/DP9O/0L/ H/8o/x//HP8//yj/iv9e/7T/qv+R/4f/dP+R/8P/jv+K/37/eP+R/5H/hP8v/3H/ L/84/1L/KP9b/2H/SP8//0j/P/9r/17/Nf8S/yL/1v4M/w//jv9r/6H/WP+d/3T/ rf+H/3j/hP90/6T/t//D//P/uv8pABkAHwD2/wMA7f/z/7r/3f+6/9b/0P+O/3j/ Tv9l/2v/aP9V/zj/WP9V/07/Nf9L/3v/HP8S/0v/HP8s/wb/Gf/s/l7/Cf81/+P+ aP/5/l7/8P5C//z+dP9O/zj/a/9e/yj/Nf8s//z+2f5r/y//P/8P/3H/Ff9l/27/ p/+H/5H/of9C/3j/S/+E/zj/P/9O/27/OP8Z/+z+KP9r/0v/e/8i/17/kf90/6H/ bv9x/2H/a/9I/xL/Qv9r/5T/fv+a/4T/zf8SANP/4/+6/63/lP+a/27/e/+K/7f/ qv/g/47/zf/D/47/tP/K/6r/sP+a/73/Yf+B/4H/e/90/3v/e/9+/37/qv84/2v/ O/84/4H/Tv8//wP/Cf87/w//LP84/0X/KP8l/wn/DP9V/0j/Zf+E/0j/Qv9V/yL/ Nf9r/0j/Uv84/wz/aP84/yz/Mv8c//P+cf9u/zj/Ev9F///+L/8c/1X/Yf9I/0X/ dP8s/2X/SP+B/yj/Xv8y/4r/O/+O/zv/a/9o/5r/cf+t/37/aP8v/xz/Mv9l/0X/ kf9L/5H/tP+6/6f/4P+X/wYA3f+n/9P/fv+a/7f/jv8cAMD/BgC9/+3/x/8vAN3/ GQDH/8P/nf+K/5H/dP94/4T/qv9o/5H/O/9S/1j/iv9L/2j/Ff8v/y//LP9r/27/ Iv87/8b+HP8D/0X/LP8f/07/Nf9Y/3j/hP+a/6r/p/+R/6H/cf9S/07/Qv8o/xL/ Rf8f/yj/Cf8o/xn/Ev8V/9D+2f4D/8b++f7Z/vz+0/7T/sD+xv4P/93+xv4Z//b+ Jf/p/gz/7P75/sb+6f7d/kL/DP8Z/yX/e/9+/4r/cf9x/z//Nf8M/zj/Bv9x/y// Vf81/2X/Nf9r/zX/kf9S/0j/eP+h/6T/x/+t/zj/Uv+X/2X/l/9I/6T/dP+q/6r/ tP+k/5H/aP9e/0L/Gf9S/xX/a/+h/7D/SP9C/xz/L/9h/1v/Rf81/xL/Zf8D/xX/ Ev8G/wb/L/8V/x//Rf9C/z//Tv9o/1j/LP87/wz/A//8/mH/Uv9I/2H/Cf8//yL/ aP8P/07/Jf8P//z+Cf/g/iz/P/81/y//A//w/jL/8P41/xz/2f7G/s3+0P4P/yz/ DP8c/xn/Tv9r/0X/Yf9V/yL/Ff8l/zj/Uv8v/0L/Zf9C/4T/Qv90/5f/l//T/73/ of/t/8r/qv+X/4r/Zf81/5H/a//A/9D/4//N/8P/of/g/53/0//K/6f/iv94/2X/ Vf9O/37/kf90/4r/gf94/5r/nf/H/53/iv+E/2j/hP9e/2X/of9L/7D/dP+U/6f/ mv97/53/Vf+9/27/mv81/37/OP/D/37/of9x/2X/aP+6/5T/hP9u/0j/Xv+B/0j/ h/9e/3T/Tv+w/6H/pP+B/4r/SP+X/2v/w/9r/2v/Qv9r/2X/Yf84/4r/L/+0/2j/ kf9V/6r/KP8v/xn/Ev/G/v/++f5b/y//gf9e/3j/Zf9x/0L/Ev8S/1X/iv+h/63/ gf9F/6T/p//D/4f/wP+K/6T/sP+n/zL/pP+U/63/h/+O/27/Zf9e/9D/WP/H/5r/ 1v9o/6H/Mv+n/1j/x/9x/5r/of/t/wwA4//H/7D/jv+O/5f/6f+q/zIA/P8sAAkA yv/g//b/4P9IAOD/AAAZAJEARQCUAPz/w//a//z/of/Q/4r/tP/p/+n/4P8iAKH/ 0P+h/+3/wP8lAOn/of+a/17/bv+q/1X/iv9h/5f/WP+n/4T/0/+k/9P/0//W/6T/ jv+H/37/a/+n/5H/e/9S/7r/gf+t/37/Yf87/17/OP9V/yL/eP8c/27/Qv87/zL/ e/8i/zj/8P4l/9n+Mv/p/i//5v4i/wb/KP8s/7D/e/97/3T/e/9h/3H/Qv90/xn/ h/9V/4r/iv+R/2v/p/9l/5f/nf/j/5f/8P+q/5f/Xv+q/3T/5v/K/+n/2v/A/6H/ GQDD/xwAIgASAAAA } CLICK-SOUND: load CLICK-DATA CLICK: does [ wait 0 SOUND-PORT: open sound:// insert SOUND-PORT CLICK-SOUND wait SOUND-PORT close SOUND-PORT ] ===Add and remove commas in numbers These are functions used quit a bit in processing spreadsheets, where data come with, or is expected to have on output, commas for the thousands separators. One function takes them out, the other puts them in. REBOL [ Title: "Decomma-encomma" ] ;; [---------------------------------------------------------------------------] ;; [ These are little procedures to deal with "numbers" that are present ] ;; [ as strings of digits separated with commas every three digits, ] ;; [ a format that REBOL does not recognize. ] ;; [ There also is a procedure to format an integer with those commas, ] ;; [ for presentation purposes. ] ;; [ Spreadsheets are evil. ] ;; [---------------------------------------------------------------------------] DECOMMA: func [ DC-INPUT [string!] /local DC-OUTPUT ] [ DC-OUTPUT: to-integer replace/all copy DC-INPUT "," "" return DC-OUTPUT ] ENCOMMA: func [ EC-INPUT [integer!] /local EC-WORK EC-LENGTH EC-LEFT EC-123 EC-OUTPUT ] [ EC-WORK: copy "" EC-WORK: reverse to-string EC-INPUT ;; must work from right to left EC-LENGTH: length? EC-WORK EC-LEFT: EC-LENGTH EC-123: 0 EC-OUTPUT: copy "" foreach EC-DIGIT EC-WORK [ append EC-OUTPUT EC-DIGIT ;; output one digit EC-123: EC-123 + 1 ;; count a group of three EC-LEFT: EC-LEFT - 1 ;; note how many are left if equal? EC-123 3 [ ;; if we have emitted three digits... EC-123: 0 if greater? EC-LEFT 0 [ ;; ...and there are more to emit... append EC-OUTPUT "," ;; ...emit a comma ] ] ] EC-OUTPUT: reverse EC-OUTPUT ;; undo that first reverse return EC-OUTPUT ] ;; -- Un-comment to test: ;X: DECOMMA "123,456,789" ;print [X " is an " type? X] ;Y: ENCOMMA 123456789 ;print [Y " is a " type? Y] ;halt ===Base fllename This is a function that is used a lot. It does one bit of file name manipulation that seems not to have a REBOL function, and that is to take the suffix off a file name. This is useful if you want to make a new file name that is the same as an existing one but has a different suffix. ;; [---------------------------------------------------------------------------] ;; [ This is a function that accepts a file name (string or file) ] ;; [ and picks off the extension (the dot followed by stuff) and ] ;; [ returns everything up to the dot. ] ;; [ This can be done in a one-liner, but I have trouble remembering ] ;; [ that one line, and also had a little trouble making it work ] ;; [ at one point, so I made this procedure that works all the time. ] ;; [---------------------------------------------------------------------------] GLB-BASE-FILENAME: func [ "Returns a file name without the extension" INPUT-STRING [series! file!] "File name" /local FILE-STRING REVERSED-NAME REVERSED-BASE BASE-FILENAME ] [ FILE-STRING: copy "" FILE-STRING: to-string INPUT-STRING REVERSED-NAME: reverse FILE-STRING REVERSED-BASE: copy "" REVERSED-BASE: next find REVERSED-NAME "." BASE-FILENAME: copy "" BASE-FILENAME: reverse REVERSED-BASE return BASE-FILENAME ] ===Make a filler This is a function used a lot in formatting fixed files, where things just line up. It returns a string that is a given number of spaces long. ;; [---------------------------------------------------------------------------] ;; [ For use in creating fixed-length lines of text (perhaps for ] ;; [ printing), this function accepts an integer and returns a ] ;; [ string of blanks that many blanks long. This filler can ] ;; [ be joined with other strings to space things out to a certain ] ;; [ number of characters. This would be useful mainly when ] ;; [ printing in a fixed-width font. ] ;; [---------------------------------------------------------------------------] GLB-FILLER: func [ "Return a string of a given number of spaces" SPACE-COUNT [integer!] /local FILLER ] [ FILLER: copy "" loop SPACE-COUNT [ append FILLER " " ] return FILLER ] ===Pause This is a function used in debugging a program that prints output to the console. It starts a loop of "ask" to get operator input which is assumed to be a REBOL command like "probe," and then attempts to "do what was entered. ;; [---------------------------------------------------------------------------] ;; [ This is a function that can be used to pause a program and allow ] ;; [ commands to be entered at the pause prompt. ] ;; [ To use, call GLB-PAUSE with a string parameter. The string parameter ] ;; [ will be displayed as a prompt, and the program will wait for input. ] ;; [ Enter any REBOL command at the prompt, and the function will try ] ;; [ to execute it. To display a data value, just type the word whose ] ;; [ value you want displayed. To continue with the program, press the ] ;; [ "enter" key with no input. ] ;; [---------------------------------------------------------------------------] GLB-PAUSE: func [GLB-PAUSE-PROMPT /local GLB-PAUSE-INPUT][ GLB-PAUSE-INPUT: "none" while ["" <> trim/lines GLB-PAUSE-INPUT][ GLB-PAUSE-INPUT: ask join GLB-PAUSE-PROMPT " >> " attempt [do GLB-PAUSE-INPUT] ] ] ===COBOL-like edit mask This is a function used often in creating fixed-format reports. It takes a string to be displayed, plus an "edit mask," and returns the input string reformatted according to that mask. ;; [---------------------------------------------------------------------------] ;; [ This is a function for a COBOL-like editing of a data item ] ;; [ with an "X" picture. ] ;; [ Call the function with a string and a mask, and the function ] ;; [ will return a string that has the format of the mask with ] ;; [ any character "X" replaced by a character of the input string. ] ;; [ For example: ] ;; [ SSN: "111223333" ] ;; [ GLB-EDIT-X SSN "XXX-XX-XXXX" ] ;; [ and the result will be "111-22-3333". ] ;; [ Note the line of code that compares the character from the mask to ] ;; [ the letter X. In REBOL, "X" is a string and #"X" is a character, ] ;; [ and they are not the same. ] ;; [---------------------------------------------------------------------------] GLB-EDIT-X: func ["COBOL-like edit of string using mask" XSTRING XMASK /local XINPUT ; trimmed input work area XINLGH ; length of trimmed input XINSUB ; subscript for trimmed input XOUTPUT ; final output area, returned to caller XMASKLGH ; length of edit mask from caller XMASKSUB ; subscript for mask ] [ XINPUT: trim XSTRING XINLGH: length? XINPUT XMASKLGH: length? XMASK XINSUB: 1 XMASKSUB: 1 XOUTPUT: copy "" if equal? XINPUT "" [ return XOUTPUT ] while [<= XMASKSUB XMASKLGH] [ either (XMASK/:XMASKSUB = #"X") [ ;; potential "gotcha" if (XINSUB <= XINLGH) [ append XOUTPUT XINPUT/:XINSUB XINSUB: XINSUB + 1 ] ] [ append XOUTPUT XMASK/:XMASKSUB ] XMASKSUB: XMASKSUB + 1 ] return XOUTPUT ] ===Launcher skeleton We make a lot of little program launchers that look a lot alike. Below is a skeleton that gets copied and modified. REBOL [ Title: "Support reminders" Purpose: {Gather some links to important resources that must be available without fussy searching.} ] CENTER-PICTURE: load to-binary decompress 64#{ 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 QVaEQUuv/E+WXT638ElVtyMo5Tx3K0VEw8xAHhMbDctXI/s3kQuSDqjufKucyMK6 FGOxxr7Eg8daaxtUu9J7BKhBlJkh/kwk18gxDHjV375R0BbbVS5bLrwu1v6s4BPJ NmcMQ3u//UWWtcbNVcjOd996V79pvXcdkbLPrdxGsnZ/ldGeungbqpDfZWnfvFWJ 5FiKc727PYn6tyT8N76y2wejTtdfPPCSZHlIt2hf6djuo6kiLl2tc7d/9WwZXXnz JEuewKlGqyDOaZYAoZ4g6apdnahyaYGYSwdPFCd2NKuOU4dFDL8soytr9R3x6gm6 gLfRlGltdVe6creDYdairL65TXqVu968/WkeCSfqbW8RbcZBPAwDep5/mbSIdxh5 fGCVMWiDATQTejjdxKPBIso+u37a0jfpHxfYt8+8+qYa3ctUM7Nvo5TntH8g/VWc b61NEq0tSjBocnxhM+Uij8qAc8vMrGVqvJrOJxaXskeSPqU9xRNLyU9y7fdQU9OP j8f56DZlJ8/fv72przB84KVFYlsx15tur2SxqD1dPJCZZ0MXPW5UlyGhRWLVu6sz 9Oguch96RBIV1NF1lmmqYVfzPDBA6rOnreNghd5AQnvKtC8UHT+BpNufV3zf1sj7 6DEyU/1igXAyjrQ0j7Xy9TKsR0PQHMajzWY71PCoC9UL6QnGksblGeVDktqetvz+ 9J2Cx5qK7vPlD6yQbHNFe6KKLBpwNkoqWJ5MVaLL1il7PAwTI1BtNtCYHssgO4jZ ZNgO6JunuhW00Z2H3Mg3aDNc0K5/e7r5iac1BtimosXQlvvmnyncMh1Tvvmf00pT zRtczSNSsevOJ9lz1X4+bHh/UHYTT1lHJi9mS3MFuW+Tuu3/heE0LUGJ54u5XbEK 7or2xjl3u+ZrnaySbmGQmiqhQ3t3ebeLmrm+rShbzSn8Gc8ZPeFjdNlqUq3luavS RGikVSfVKqTTyxPW1Hu6Mpo6R8i4vRil36d9uWxxR/+KzSKnRtHVCyeUJVP47Thp 5w68exmmzOvke0Ts+5lX3En4XGNZTYYl0dI8H/NOrpvhzHxIiu53ldYjILhORZ7Z MkHdVeOV6y71kiBe48m4/ERABM0ufWw+XzwG5FZvoSwN0Wy5tA7cxyP5rpdnhj7L /XLAup14paKoTNTW1WXE4FL2+avvxeh4U9eyhH0lVGk0q0sqbeKX+JhSY2lPt3x1 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 QUk96WxNvxivrGw67jEXbmK1842Psz/qeaUbIodDdQXNo2sEk09cLpX0MpKp+Sgm EI3G3t5+AcNZlnvq3bo3ahlylST1fOv5v3xc/XjHOLaPyH3rvnPp5P9PEckMD87a jNfnFTlYSL9qJs+5jIha0hHu+f5yJy2oi9S3mjALHgFbdk6oqrn7Nfd1u6dXg/mU gaGW213IbZLQ3be6gg2t+iuPxlfLJH2C/nD4hFDl6sMPPaiRiayeCcl3Kx28KeVg f9f1pnUoEBcN6cmMiu+QI21oumFKin3VmebJ66OIo2LR/XHC6OR9asujVq0Pwqjv a2L5Zr9KNKQgPcco2XbujaX9MrdmkUxVvz9UnT7SONB1Jk8gqS/UeK4I5MDfpGg9 +34stOSrUgguLikZ09/jqdjqW6fC6ru8IrWdNQUipSbUUvSLF1s7VuzM3/DYt90d 6tDAQowY+k/+uGhxlh8bd1Haav3hlY5xIisNI5W4wVeho5zW1wXcYwdu4ciSY7kK SG/dXVGggVP+sF8h6K89X1PSD6ztMwuC4M9PceIoPGL+jaAz9az/yRmPnBzOOghL L0cw0elcHq5pDMAWK2/8mHXtgA33gOiL18Zbo7W2tDGcGTTdLNkY6MsEQpSATAQl ki54OvgtYjxbzF/mrn1xMP2x1hv3dEk2DjF2nx5pyw3SnSBcDzuQbm8g8KlUedA+ 45O9472tUwLfMOyt0t2vYH7fzIWFXZWKZ4fG34RWBlt+ZwipfRlBPYJ6DDG+oe4D InQS45l4Hcb5tdDTSNBRUjdnOyiRYo21wyVOGWUiZvhscUI4ExlksJleWwS+S5lY uDVMeKG+YrQknZx9SZwVinmKeVOMGOz+8/5QabawMaKgY+5XuqkS7ZbYrPFnI4tI TpKwRQLL41CWi73JeLqFj9f0135AlIzqx8JT9oXc4Kjy4DFmhI6GwgbnABEJyGRe 9qW9GX3EldmS0aHOuJurTLoRlRhUQMJd9t/hRCDksg1dvglZYrssR2r1yVDs9S0F dbb6sV8u3DS82fuvItRgzHc7+B3gmZCEhET3bx6gdSKlvRNx5/vGoh6xddsUlS35 /RbBDybUzGzuoZFKwrncibFAm9FqYge3xfFK6KsBPIolsWSabWee1bDEPyFuLfqC PfNtpTSjpjmd5jw6aMuF3KAJ/XuAdqYUWNDLzRUZh7sqpiXZm/4O3wy9+wNxzMc6 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 } QUICKHELP: func [ TXT ] [ QH-WINDOW: layout [ across banner "Quick help" return QH-TXT: info 600x480 wrap font [size: 14 style: 'bold] QH-SCROLLER: scroller 20x480 [scroll-para QH-TXT QH-SCROLLER] return button "Close" [hide-popup] ] QH-TXT/text: TXT QH-TXT/line-list: none QH-TXT/para/scroll/y: 0 QH-TXT/user-data: second size-text QH-TXT QH-SCROLLER/data: 0 QH-SCROLLER/redrag QH-TXT/size/y / QH-TXT/user-data inform QH-WINDOW ] HELP-TEXT: {Launcher program skeleton This program is an idea for a simple program launcher. It is an approach that has been used many times and so we have created this skeleton so we can do a little copying and pasting when we want to make Yet Another Program Launcher. This text in the HELP-TEXT word would be replaced with appropriate information for this instance of a launcher. Each button has a function linked to left and right clicking. You would code those functions to suit your goals. } INFOTEXT: {Right-click a button for a summary of its function.} BUTTON-01-LEFT: does [ QUICKHELP HELP-TEXT ] BUTTON-01-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {This button displays a window of instructions about using the program.} ] BUTTON-02-LEFT: does [ QUIT ] BUTTON-02-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {This button closes the program immediately} ] BUTTON-03-LEFT: does [ alert "No function for button 03" ] BUTTON-03-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 03} ] BUTTON-04-LEFT: does [ alert "No function for button 04" ] BUTTON-04-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 04} ] BUTTON-05-LEFT: does [ alert "No function for button 05" ] BUTTON-05-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 05} ] BUTTON-06-LEFT: does [ alert "No function for button 06" ] BUTTON-06-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 06} ] BUTTON-07-LEFT: does [ alert "No function for button 07" ] BUTTON-07-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 07} ] BUTTON-08-LEFT: does [ alert "No function for button 08" ] BUTTON-08-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 08} ] BUTTON-09-LEFT: does [ alert "No function for button 09" ] BUTTON-09-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 09} ] BUTTON-10-LEFT: does [ alert "No function for button 10" ] BUTTON-10-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 10} ] BUTTON-11-LEFT: does [ alert "No function for button 11" ] BUTTON-11-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 11} ] BUTTON-12-LEFT: does [ alert "No function for button 12" ] BUTTON-12-RIGHT: does [ hide CENTER-IMAGE set-face CENTER-INFO {No information on button 12} ] LOCAL-STYLES: stylize [ BIGBUTTON: button 128x128 font [size: 14] ] MAIN-WINDOW: layout/tight [ styles LOCAL-STYLES across space 0x0 at 0x0 BIGBUTTON green "Quick help for this window" [BUTTON-01-LEFT] [BUTTON-01-RIGHT] at 128x0 BIGBUTTON red "Quit" [BUTTON-02-LEFT] [BUTTON-02-RIGHT] at 256x0 BIGBUTTON "" [BUTTON-03-LEFT] [BUTTON-03-RIGHT] at 384x0 BIGBUTTON "" [BUTTON-04-LEFT] [BUTTON-04-RIGHT] at 0x128 BIGBUTTON "" [BUTTON-05-LEFT] [BUTTON-05-RIGHT] at 0x256 BIGBUTTON "" [BUTTON-07-LEFT] [BUTTON-07-RIGHT] at 0x384 BIGBUTTON "" [BUTTON-09-LEFT] [BUTTON-09-RIGHT] at 128x384 BIGBUTTON "" [BUTTON-10-LEFT] [BUTTON-10-RIGHT] at 256x384 BIGBUTTON "" [BUTTON-11-LEFT] [BUTTON-11-RIGHT] at 384x384 BIGBUTTON "" [BUTTON-12-LEFT] [BUTTON-12-RIGHT] at 384x128 BIGBUTTON "" [BUTTON-06-LEFT] [BUTTON-06-RIGHT] at 384x256 BIGBUTTON "" [BUTTON-08-LEFT] [BUTTON-08-RIGHT] at 128X128 CENTER-IMAGE: image 256x256 CENTER-PICTURE at 128x128 CENTER-INFO: info 256x256 at 0x512 info 512 INFOTEXT ] view center-face MAIN-WINDOW ===Customized makedoc2 For our documentation, we use a customized version of the program called makedoc2.r from rebol.org. We would like to have our own logo and heading on our documentation, so we modified the source code to accomplish that. Originally, we did this modification by hand, but here is a script that will produce a customized version of makedoc2 with a logo from a file of your choosing. To create the customized makedoc2, just run this script. When you select a logo file, it will have to be a jpeg or gif, and it is your job to make sure the image is of an appropriate size, like about an inch and a half. REBOL [ Title: "Makedoc2 customizer" Purpose: {Use an embedded version of makedoc2 from rebol.org and customize it with a web site link a custom document heading, and a logo created from a file selected by the operator.} ] system/options/binary-base: 64 ;; -- This is a function that takes the name of an image file, ;; -- converts it to base-64 encoding, and creates an IMG tag ;; -- that will embed that image in a web page. IMGTAG: func [ FILENAME ALTDESC ] [ return rejoin [ {} ALTDESC {} ] ] ;; -- This is compressed copy of makedoc2.r from rebol.org, ;; -- with some place holders for a web site name, an h1 ;; -- heading, and an embedded base 64 logo. MAKEDOC-TEMPLATE: 64#{ eJylPP1z2zayv+uvQJjz2U5NSZbTvqsky5MmaZubtsnUTjtv9NgZSIQknimSR1JW 3DT/+9sPAAQo2k3v3MYmwd3FYrHYL4CcTISYh//lT9SbIBlxs0kqAf/LTMhYFrWs kzwT+Ups5a2K8+WoX4pVmW/Fz6+/efuDuFHLTZan+TpRlYAfQ6beyFpsZCUWSmVi m8fJKlGxWOWlKFRZ5ZlMxa5SfdH9Y8i8qZGXhaySpUzTeyCrRCW38GtZJkV9JhY7 7kaKqshrUapKlXfQkU8Gu5UCuMyZMRxiBpA1QC7u4dFyV9X5NvmdR1uU+bqU236L m/9exEjn8q/+INI1DXfsTAK2xvk+S3MZo2BhSsZiv9/3aV76eblGiDwbi9Ew/Ocu DUfD4VfYJGtsGl+Mxs9H4v3NSwLbZ6oci6UsUzFn0Yo0WZSyvBdbtV2oUuw3OTzP xK6IZa0QqUZNYeDoPxsYq9C8hzK+SepUjUXwI4zwVb4UIxGCLiqtZte1zGJZxgIe 7bYqq8W3ebmVda3KgNB/AaVKaLT9L/tfUdPLvLgvk/UGxht0KOv5119/jUL5kgm8 2NWbHGQQvEQhXMuqUlkp6w0//TZB5o4c8WPrK5AE9Pg/4T9lRqSo9d2uLPIKHnzs GQUyiwrVN1+tkmUC6m9GGpshrcyQrJLCCkEFtXQ6hkGqnaaWCmlwXy8c7G8lq1pV NSzo2NJRsKCwbS9hScG8lgpGItZ5HsMiyW+TbO3TA0awTWYArj7UDZ04qaH/E3UH izzPVMWcx7nIYDHKXZ2H+1IWhHRKTHFXAIfTXZ1ZShslY+iiOhPLPKuh3wrXdpoq vMh2qIIgijSp8D7JYoCAe/VBbguPDvSrxCLNl7cAB0MG01OClQFt8Ud0RpAaJgc5 lUB1lVs6d0mVgGWp62I8GOCyKtUiT/uZqgdApxpoTehv6m1KSJ/o9/tKrr2Zf8mi lSSCZqqTjITJ8uuLa1XIEuGUXG4EXoP9KTaWyj6pN0BjkcrsFoSQwYh+3mXuCqRx gN26S2Il7vNdyR2uQG/7jhqC+u3qYscPgCwozkI1VjXDX9QZDQyUK03zPU59Ujdk 3qywB1ROVsjBL4nas253EI+TqkjlPcxWklkSxOFeLcSizPdgiAWY8L1K037Pgvwv dIEGR6YVWh4g5g6XXBDPG7dUoIX9dV+8/O7NqTdi4FKWML5dUeRo8MdNF/gDuuou 69azgSzXlQsgjswc9mtYCH8Kfoz2Ocyz9L4FuhwD42A24Aq8lozFEc1V7awu/KlU Lea0WFC4kVirLMSpGeQFqnGFlMT8RN+dRh7yvkxAp44AkacTLhxd/YEN/FgbYPxJ YSGnY3GcwOoqt6CdaOrNQ5jFGk0UPIfZsM31fQEaP6/zPG16j/OtTMAaz6nf5ToB z1Xe7ooGAm2SisMdLGWwuhkYD/tIT1WrNU2WKkOzevzN9asGVqkQNcQBjnroaMU3 ClSXFBW1qCrUMlndY1jz/c2PPxhNrdUWh6XQCqI+G2tK+okLvQ+UrhUvkVit5C6t Q4ukzQ9oOXbFUUgtyxoXTLVbr2GIaIx7BiFcsRsx9zwrYiJeM6H2IxwGaHDJGlxv SmAEjAPoep27q2EMcEKc92mBOzYGR4hKBs69TyCjFohZr9bxnKAAUECnjHDBCMs8 Vtq0K5A2mwimT/azWfYgsN4z3eezMRtzsENzGEoYildqAWIB8Yx7d6pckJcEfyh6 MT4Yi9UuA22GAENGYp6shAYS86IElRT0IGJSP+bxDkT/iywTuYB+xz3sSKsBWlB9 iazry5pDDLpO1aoOV6lcEwM9WD8VaGskJvMsD2tYU/AH3E4V9WBw/MQ1n+RhxEmF zmR5BgsYPfVpj5eh7gLZDMU7WaJ9K4FZdtaoST+ygWAbDUZ9vQO3IU7qvAgxpjsF G0UI0HGVb1H+2y0IGrgxV2bVZmqP/oCuUVPG4oRkKeYB9P7uxc/Xr8cB4Bf3A9Qc goGJgkmjK40enbIlozkyylGpJRmVMT36AyhCzBbARRCeh0FEzIeIDZZ3m9Shhhfn pxYBWGCE0WMIowbhiy++YISLxxAuGoR+v88Izx9DeG4QgqdPnwa4ehRIgGDoCufr FGZYorurTGiAssZIBOHZEzZSegnPgLCdDk3/afAscOwpJA3BbEYMPntm+NO6Q51z iHNBLv/UouHAAIvQAvEg2ugA7QFABy6yjD71GSU+D/AVrIFD7oi5TtjPYAnBOhkC PQULi5MHy8hopkbSDyAG3C3BHNC6QRqouBPDvUn+uGU6dVrsvL1Gz0bZoqIgXGtI M3//1xJLkgWaB446QwjdSF1ceaDCBG3tIzVCcIp+XfAaLdYhPDV3IqzLfFcYPuim k40lRsWlgeO7bsA83W3twPjOB4wckX0AmEckNvgziYHNfEhkjqA6obSkXPl0wnUI qBOuU0LdkF0i8iE9GUHOgnm4MQjiRFL4C86OvWVwGZw2Mpt4a23SmBp0p5skBrk1 aUBl0S59UVOD9kjMpwlrymQ7wPSLPLc3rmQLriYQ9MdthzjclzM0fJ5UrPWk4AHc GuVWTKXysHWU6g9CUCbkt+BPVcgluEx0XYIRO4C0yoHDDjqfoaKBF3/wIWvow7h5 +OcQj3bOUcSj6DriexQGI5cHAfI0Dmu5friXMs/BbuGMd8BEoKpFgV4QgyCBKXte xlrkpx54E71H3iI1IxAYrITLDYQ84qRUDdH5sY2ZZUVRMKl/dLCO3oHiYtEpAWis F9o1QGmGdbMm8DZqiNGpVflYgeo5iv+HQ+WkKV0klDxyajUnOgjGXoXv+ZmOGqmd sA3V6jYpTLQVXF1d/fri55/GQrzPSrXM11nyu4qDU8hFSJEhFEaxgC8OxG9h0Mty vPdbfxsEPbrHuBnHR2EYQzIVDPtwtdANULbiNoEiPeA1Qz6So0eEiHrW3QCTDRUH GBKMnY0Ie419cjt1ZOl4aYyOk3WWQ0SZciGHoc9gpmoQ6k8/iCcgoZ5FBpLUL4mc mJyz2ng8RD1lEiOhEWiuGcFWgf7gBhMxmHZAN5c4Ylc+h1312HJiR9rMtOWpc6AG h6DIdgUYF8+D3zjYBXsUPSBVu9SYGLp5yFYx/VnxvJhhMmYOxIDmiFWtmRAY2Jbq TMwp5jJXomtGm+l3NB/yKnw4OBeX4EGOgPNSbfM7vSRhJvUtFSScfB2zK3f1NkuJ fD1y1ArQEvBtc+ROe9pI2LRLLyUB64PY9xU4wDbwMm6Wlp2CcNHV+M2rFYiwp/ky GWRVQ19zMGXMLJgGgU2cOb5lH4lcA09gU3p4aVCPyfrpFJSYNPkUZD+vf3xzM4ZJ QRgeAQiTpuSK2sQcf4+xqEQgYnKFaq8BgQVYGVdEHLhDg1XLJOXOCMjYTGBv3vCB 9Qw3nTGsgmcxPNIUzI3t/lcOUUeA0IEgIDtd2pjV5U71tDhef8BiC5EkJwtah/k7 OvK++FnVuzKrdIWAh9rvocE6ttUrK3Jhi1KspZq3JZiE0tae3CTcCMagzV0dpSSV 46Nj4wJ1KYwHEDn5Awc/mgy6HF7CNVhYEgZyF/w2+G1A+d+E9lG4PF6g/eWCOBf1 qWFAJXVyJIhKybjh1hYlmqLzWJzbGxAVVXGdCeQJ9VwpFzTcSXafQi8nWEYQX0A2 LWbiSzFfANXbtgPm3xwigXwjM6dU4tJ6/p3KVCmxTP+f7Fn1es+wEnVYyqEuVnlB erFO8wWkBjpMu2tqMjr+Ics2Ea94XwALbbakb6oMPY6kCLIBXTPziqNJ3IY02wM9 oxPjTnipvTcMe5GDESgp+ujZgG7sIHEL1941Oz0nMBv7nMumaEgyKDCQNiEYM/MC awUC2nTVE5m+gy5QOCcVPFPlac8JyrCHN3Qlqk2+A7wFONJ8KdG7lQr6Su6oRDng mg+tHRBWSPVaQL/AXn+gG6Swz3CD4UBkAHP966/i+vWNuHkrLtiJhIWswR0HuCre wSV2w1z1eJ2birNe52wSsehMa/MJq+DAXXutRziQ1ARTtt66LXpRyz5gCmEqafiA 87hlvsPpGuogUbzVPVU1bjBkCkQEq+j2yZMnWjisceYGdcpek76YO60I9qGZbmqw E8p22ZmrZtVbEwZyCl0BjDksYFlE0QFMpVJQM5LisW4zxsXpCSIcZ4KOBiZMFjdG iGimQVP0tg9usIhLK+G8NBsuE+HZZWdXx4blfdzUcVmZ0K76sSOXMzSXmdnb81dC 37CPjxwcx+g1q4lko0VAImqSA1cwjaq41fPGApKLSNVVo1Nzp48ar2sMbWRsISIP m5LUDlw3k/AL/sboagm9bpIETNsdOzNuy8NzXuTLGRqH2qLXXrXjZpFQAFC1aedL R8xEu+ZdZdvYRtY9gg/Ky3C5jZ3NE/BeFGzGtAXf0J2gguCuJTN4xh5XQmAHi5As Z51sna1G4A9dqO/0kiwkbK/xd1XmV+5aFxOjZLpIA3QS6pyAPGSEokBh3hSHbPki wlFAmPsohjGUjGBF0jhafwgsX0JAxjoS4mqf1LiJ2wiXuWj5f0x89A9lmyG1IOjI jwVw2s49SGwR5w/Bjg5hRw/BXhzCXjwE+/wQ9nkXrC45O7AJrB9SKBJEF/ToL0Ff fCY0VZo9rv8MevSXoC8+G5rSPQNNe7+EQs1kAVxgXcP7PGBdGHf4gJZDMM7OPHap pWP+7LKwoGySHgTNiVkHNIQcpgsQK4o+IK45X1C2Zq0BxZSbZp1w1LWGG3QCmhp8 Mxo6IdIxGFuE9iAPx2LL7wjnhSiuDYPAvQtNy8pD28oPYughh23kZuvBDpdc+b93 wOKsE9YTzYPATenfAH+c8nQvIDNR5eWQ7G8hYyzqXD4X+ySuN5fnw+HRbFqX8C+G cD9N1tllnRezT53UHVY+Tgd1PINfJf7CjrpxRDNhBufBntxUiJYLniWy/u9QAjbt 7IhSnODKZjGiVcn/WxPTbIuxqbZorAn6qaWE6Ag3IhRENxzRWhxI8VO55AQT8EXw Ny7uciDxCFhMFdYs3w9i91SGBtRAOmgIbLqNP7SDjQF3Iydbp7EnSzB1dGJUU2PQ tyaXp7Ajg6DLpuzqQ1JHJnSgQADrgvPW0qKYvO2IMU5pN7H2HgBq8R60ezKjseq4 3Wt0gmqWwdzUF5yoHWNSCki5uOCPCeWgSzqtoeG49Ph8k8dnCNpD1LmmP9JH+KEC wUqmFXIUmVMUFJZy+nlj05ZeO1zFc2hTTN1mvemTMHyHBt8kyHTulU5vhSE8xiUD f0ieM9ZIWHV015tW9T2mbveFugyocrisqmDWQ8pnYCfi+zNRQHYQn4k0ER9XoILh Sm6T9B7icFhDAFTJrIKQoUxWZ7A60ztVJ0s5EQRaJb8Dp+fDop586m3ONQHd+hW0 im+x4VfFRzkXMMMIOPIBnyMg2A48wvl0NLwYymEXItsv7G54NCHZs52DcLyu8QTt efFBVHmaxOLpcvj18Ksh9nXh9zX6vL4A8bmPOPxsxC87ELsA67ol8AA8SJlAYpGp fXAmtnmW60q8fmAZiGV5uy6VyoBMUSqmw4Spw0dJZSAjpQUol7fovLI4NENTQ/xv IrTboHn8MNGiHhv5yiH+hxIHDvqwUGDut7IEOxtigRewlltfR0jw1LD3xYDYoxb2 qI39gBC5rh6rZV7K5vSOJnrRInrRSfQxCs9bFJ53UtCSg/m4f4Scjgw/GjkP4ecf w5ZIMizVpghOkc7HjvlZwex8PfQXw1+bLCxbf7RMy3tvSP+gpTwdkN0A+zFg69Kb oq0QizXhXQb7DYTMAVodCjg4sgiQmcALOoIh36PymXsdncAl4pdIvIPKAdQUAwkp NqVaXQZHRy/fX9+8/TH89fU3129uXh8dAZht/OHtd2+PjoB5OaP4g3G/P59ZiO9f v3j15qfvjo6mA2jWQAPqRoc2PXNfl2D2cHqQs2A25RhIB0I9HUjNjPd2Hmm2N6Uh 3dCGmAbECXBs4T85ZVkqJLyvkzSp78W3urCPGx0UCWDtW+9FPMG5Hw79HRDanhjw tt5clybMvixFU2arQFc56EUK84c0AwM+HWEQMbNhBv5rXxUHm55An3RBb5RW6Ezk Ak/V4eaD3vuAOBwdu2ESLhvuaLwyo6Nc8IAPB2OlYs0FCcJrzsAhCBWhyOXiHXDF nNdmZ8oOZ00nXJpQElrsfozLD23YATQdAEVOGvbe4yl+PHOG+OYYDSxpWC5YtWvK jCCFVG+ejTkeMGTdsIO35/RQ6AChytb15opYs+EH0TCjoL1AZKz7uSMMhERR4xRp kdCuoNJvD2AQYp43EzkPYC6DU/gXwb8+/DsLcL8lQElVS1koKiG7woqMdF5ibbyk 3U55l4OtMRIiVebdbT8Wo+mt80ggTcqLKyz0OQEzHX3XUD0zXOC8QRgDz38HHv8u t8UEt2yneJPWdD3D6zVcm4lG7a087n3dq8z5fQIUdJIKrTBZRV1CbvNntoSnC1jW jXoxo81abr/wgmVbd0nb2tFj7Jm3Z+y5Od6ENyG9CZoP6oigz4QSTJcok2ld058B /n0QdE8wi5kLDcbqEYzKYCSMkDjwzv7efFrMGGU6KGbNtigf8dXGK196e6JTCG1m 7uJq1+m6inO6XMPp59xRYF036KzXaOgpWDHIAFNZVZcBPwpm4oAGDAEBZ9FBHssl n6YI6wgAhm1G4wOFIysMfTJAb8rCUrIbMAcWk0D74hqBLsUx109w30AnEvgG0TFG LX1nDppJ5AM02AUMp8GHWRKcp5vTdrMIZ64ZKO3IfpwmW7CW5fIy+CTmJ9TW7Hcw 2fNT8TFwU32cd2uGeosd7n3NdcHRVBJ1jRDNFO08zqkMyNU9qtoxZgiLgo62wG2x qzYhtBmxwWVk810yjriZcH8lLB6VIsV0JmCe66bZKRZP9A7vMRIn6C1G1g2ohdRH QhracOUtFX2QYrpLZ9M8nUVgVSCau9I75CAEi0FiKfKiNRijAnjkW7PIZ8Ubw2/I MFESHd5GnUvnsLLP1XpfRu3K7aG4PIjuU4BImE6qT+hSzzXoKLJ4AE3MZ2ghCOeR 3uwwWBBGBs0M6DOMSXrFYvOwDxdtx7znxaPT7s7sAKd20D23DwxCH9LB6J79tA/S WEesSzvWUVCd2rEJzLpZAvTYNblpMrMWC66Zf61i9ODC9gRmo8MMG2NjTmtRxTrh MgeFsn18u7PkN0lwIWAsV8EsLlVVQcxp9xaxs3CEWnSsq96+u7KlSy9Z+MpNA0x6 8PWXEOt/OvAvjZ3RpU0NPoKYHSKCbFFhrMCRfgNq65JBnRe2i39g0mGBFjPWb5Ik +BtDLMLS5Oxxih7qCAOtqM0DpQbNaLSwLjxZ2VqqqbqaacM0sTt40PPCL1VisLqQ 5ZmuvcNM4pvS6GxcdYmTO+P86IT3DCw/jl67bRyr67pNiR03yVTVaAyogd+t44Km A+hkhiTMfiIGsiEmmZiwUrHMBuj01KHdoNAZKN1kcG1bVyn8IA89b+Wpz4MmuX36 5RD/c3UAkkD7uErSO/SMlAkuQBUjl+MDiTRc8+gsi8FhPT1o0UIWDTHRYLLl+WjV z3ByWG5ntW6n7Z+iRnCtHst83+benxxHwg37/m7CA52a0Phav9izAaOR0vtkPWeT 2/Sub4Z9+g9Q0TW0T9HRGRpjEBe7bQEJcnXbLAI+AsdexbxPxKeX+uIlHV2pdgvd UrGaUkrkkGJZW02YnzND4twwZp8M++f6yfnBE3pGT84PnsAz/UTvHEX8Lidd67c6 8Qyf0CKhP+ILHu8zYpNA+SwOOR+WS9AfBg0RFD+WD0L9urYvQ4yz6Bgg1r61QNPs 1mZ6+NYbLOuizAtVmje+MWW6RYd+8/Yl+INyrXS4ORGvFL6FisaLYPgh9oAvTMsS gnd84WDO7aiOmPPhW40rQ1xbDY5U+aQfMthMRTDnl+OQTzpvGzVZCoiJXxRru3g6 Vsj60JyWdVhswwPtsXMmExQopHOZvsXWxzko8ppTF6UipDm9MEUqFPRFwA6AJX4p zulgq9nUIXhzst07FwIrXRrDDE8+aQIfA10Me/qJRIDhNokI614HsQ0Q2RjML6Dr jyKJMXz3MGFN+0AmgPfPsfqqQ2rDGlNlTuUk0/sldJpCK7INzDF801LTYExseolH plHDwdPOxDB6eB+0yngm7ZuCzaohFFfZNfWKTpN+FhNR52atNZaYwjVxmR7+3hOA PsP5wKEg7XM3I4hOXponGKBAS2v/ivaR6Fh07OkFDGGvw985nzThMyR8OoTOfUT6 aLMXAe/HFNF9uBJ7rx3p4dib04ldr/a0pb4/AOGhueInq7LX4qeqyZ/E5FbQfNSq Q9a8+4nffaAN3EOxYwjP57ScY136FJefr3gn17xdSfcJSbgxPu8zAo07Kh2b85lm D2bzvHM2wVN2zSY+wmwcaxiHZ5dgeTrKSKFHG4SrXUi+C5viBYeEj+/WJkmpaNjE y8jPB/E4c2vG9AicE1r+mVG7F8366JyIjpqJwVmH/+M81F9hGNNJxjkEIXeJ2l/x xym2FX3hBGfchCj0dMwLGsa+U1fimDHoN74Y8QJyyr3SH0PBj15cmaN736maP7aC xOkrGlx+3Cj7fY5yTXU8XcuklxWq+woGN2AI+naEU3QIzesCRHPOGOaVBjoKac+x 8xGEPDfcvEEhMp45G3pmThbv8fALMUaJJQHJtUwy+5qCn93zbDj6rD7gR1iuxBHi h/zRCnO2oEFjdvHjF12ARIfdFFi0VQKBCXghjE/mwc8KeMbcL2Dmgqugvel+KLfW tyJah/aYGR9C682hxOhcsT7sCmERiWqHr/Cbl/ftHHunPFd+iUSPzmpdF0Ol+vdO adEMvE+EdPKPzAT4ISLs+0oEXSDGG+laDL35wu/AuIrzkBR+ailNxwD5uIeG/5aW 0g7UiJTCAzdq0pILLLxxM9evyzIvx2aiKWi3uEH0sDBlijsGQAs0A8WCV66C1v64 riUen8fvZciqpfpa18xYK4T0FZa1X1N6x+BWD5o3ZLSxsifvuECrQL1j+9GW1hdf XML6O0HuB3QaFTMvjdngfNAM4Cltt9DnQlgj+KMv9AzPQHmr2koQpXy4iiI0qvg9 HkdNiNBE78XhpgW3nODrDCW+PlNvTvmDK1wt0AIVJ/hlNvxsD0zcVt4bZcfqDqo6 v+GAny47Hffw3agDZqh4Yb+eg37bWHTsbSNTPChMbxybj4qIXu//AVjni9gLTwAA } MAKEDOC-SCRIPT: decompress MAKEDOC-TEMPLATE WS-LOGO-FILE: none SELECT-LOGO-FILE: does [ if not WS-LOGO-FILE: request-file/only [ alert "No logo file selected." exit ] ] WS-WEBSITE: "" WS-HEADING: "" WS-IMAGETAG: "" GENERATE-MAKEDOC2: does [ if not WS-LOGO-FILE [ alert "No logo file available." exit ] WS-WEBSITE: get-face MAIN-WEBSITE WS-HEADING: get-face MAIN-HEADING WS-IMAGETAG: IMGTAG WS-LOGO-FILE "Logo" replace MAKEDOC-SCRIPT "%%CUSTOM-WEBSITE%%" WS-WEBSITE replace MAKEDOC-SCRIPT "%%CUSTOM-HEADING%%" WS-HEADING replace MAKEDOC-SCRIPT "%%CUSTOM-LOGO%%" WS-IMAGETAG write %makedoc2-custom.r MAKEDOC-SCRIPT alert "Done." ] view layout [ across label 200 "Website address under logo" MAIN-WEBSITE: field 300 return label 200 "Heading for top of document" MAIN-HEADING: field 300 return button 200 "Select logo file" [SELECT-LOGO-FILE] MAIN-LOGO: info 300 return button "Quit" [quit] button 200 "Generate customized makedoc2" [GENERATE-MAKEDOC2] ] ===Fixed-format file processing. Fixed-format files still are "a thing" in the world of data processing. Taking them apart is simple enough because every "field" in a "record" is a substring, and the "copy/part" function can copy parts of a string, thus being a de-facto "substring" function. The example below is from a program to process a fixed-format NACHA file used for transferring money. The file has different record types, each with a different format, and the records are in a fixed format, meaning that, for example, an account number appears in the same character position in each record that would have an account number. ;WALKTHROUGH:Documentation TITLE NACHA file SUMMARY This module provides procedures for reading a file in the NACHA format and taking apart the fixed-format record into its individual data items. DOCUMENTATION Include the module in your program with: do %nacha.r NACHA-OPEN-INPUT Perform this procedure first. It will read the file into memory. If you don't like the default name of the file (which is meaningless, really, because it is the name of a NACHA file from the vendor), assign a new value to NACHA-FILE-ID. NACHA-READ Do this proceure until NACHA-EOF is true. After each call, use NACHA-CURRENT-TYPE to decide what kind of record you have, and then refer to the appropriate data names (in the code below) to access the fields in the record. SCRIPT REBOL [ Title: "NACHA file" ] ;; [---------------------------------------------------------------------------] ;; [ Substring function used for extracting parts of a fixed-format record. ] ;; [---------------------------------------------------------------------------] GLB-SUBSTRING: func [ "Return a substring from the start position to the end position" INPUT-STRING [series!] "Full input string" START-POS [number!] "Starting position of substring" END-POS [number!] "Ending position of substring" ] [ if END-POS = -1 [END-POS: length? INPUT-STRING] return skip (copy/part INPUT-STRING END-POS) (START-POS - 1) ] ;WALKTHROUGH:Purpose ;; [---------------------------------------------------------------------------] ;; [ This module defines a text file in the NACHA format for ] ;; [ getting money electronically from the bank, ] ;; [ This is the file that Cogsdale makes and that we send every ] ;; [ Monday. ] ;; [ This file differs slightly from the file we get from the bank ] ;; [ every DAY with internet payments, but the difference seems ] ;; [ to be in field uses and not field positions. ] ;; [---------------------------------------------------------------------------] NACHA-FILE: [] ;; Holds the whole file in memory NACHA-FILE-ID: %NATC0001.TXT ;; Default name of the file NACHA-EOF: false ;; End-of-file flag for reading NACHA-REC: "" ;; One record, for reading or writing NACHA-REC-COUNT: 0 ;; Counter, upped by 1 as we read or write NACHA-CURRENT-TYPE: "" ;; Type code of record in memory ;WALKTHROUGH:Data fields ;; [---------------------------------------------------------------------------] ;; [ When we read a record, we will take it apart in to its ] ;; [ fields and store the fields below. The CURRENT-TYPE field ] ;; [ indicates which record we currently have our hands on. ] ;; [ For those record that contain numbers or amounts, some of the ] ;; [ numbers or amounts are converted to appropriate data types ] ;; [ so they can be used in appropriate ways (currency, for example). ] ;; [---------------------------------------------------------------------------] NACHA-1-RECORD-TYPE-CODE: "" NACHA-1-PRIORITY-CODE: "" NACHA-1-IMMEDIATE-DESTINATION: "" NACHA-1-IMMEDIATE-ORIGIN: "" NACHA-1-TRANSMISSION-DATE: "" NACHA-1-TRANSMISSION-TIME: "" NACHA-1-FILE-ID-MODIFIER: "" NACHA-1-RECORD-SIZE: "" NACHA-1-BLOCKING-FACTOR: "" NACHA-1-FORMAT-CODE: "" NACHA-1-DESTINATION-NAME: "" NACHA-1-ORIGIN: "" NACHA-1-REFERENCE-CODE: "" NACHA-5-RECORD-TYPE-CODE: "" NACHA-5-SERVICE-CLASS-CODE: "" NACHA-5-BILLER-NAME: "" NACHA-5-RESERVED: "" NACHA-5-BILLER-ID-NUMBER: "" NACHA-5-ENTRY-CLASS: "" NACHA-5-ENTRY-DESCRIPTION: "" NACHA-5-DESCRIPTIVE-DATE: "" NACHA-5-EFFECTIVE-DATE: "" NACHA-5-SETTLEMENT-DATE: "" NACHA-5-CONCENTRATOR-STATUS: "" NACHA-5-NACHA-ID-NUMBER: "" NACHA-5-BATCH-NUMBER: "" NACHA-5-EFFECTIVE-DATE-E: "" NACHA-6-RECORD-TYPE-CODE: "" NACHA-6-TRANSACTION-CODE: "" NACHA-6-NACHA-ID-NUMBER: "" NACHA-6-MERCHANT-ACCOUNT-NBR: "" NACHA-6-AMOUNT: "" NACHA-6-CONSUMER-ACCOUNT-NBR: "" NACHA-6-CONSUMER-NAME: "" NACHA-6-NACHA-FLAG: "" NACHA-6-ADDENDUM-RECORD-IND: "" NACHA-6-TRACE-NUMBER: "" NACHA-6-SEQUENCE-NUMBER: "" NACHA-6-AMOUNT-N: "" NACHA-8-RECORD-TYPE-CODE: "" NACHA-8-SERVICE-CLASS-CODE: "" NACHA-8-ENTRY-ADDENDA-COUNT: "" NACHA-8-ENTRY-HASH: "" NACHA-8-TOTAL-DEBIT: "" NACHA-8-TOTAL-CREDIT: "" NACHA-8-BILLER-ID-NUMBER: "" NACHA-8-MAC: "" NACHA-8-FILLER-1: "" NACHA-8-NACHA-ID-NUMBER: "" NACHA-8-BATCH-NUMBER: "" NACHA-8-TOTAL-DEBIT-N: "" NACHA-8-TOTAL-CREDIT-N: "" NACHA-9-RECORD-TYPE-CODE: "" NACHA-9-BATCH-COUNT: "" NACHA-9-BLOCK-COUNT: "" NACHA-9-ENTRY-ADDENDA-COUNT: "" NACHA-9-ENTRY-HASH: "" NACHA-9-TOTAL-DEBIT: "" NACHA-9-TOTAL-CREDIT: "" NACHA-9-FILLER-1: "" NACHA-9-TOTAL-DEBIT-N: "" NACHA-9-TOTAL-CREDIT-N: "" ;WALKTHROUGH:Open-close-read-write NACHA-OPEN-INPUT: does [ NACHA-FILE: copy [] NACHA-FILE: read/lines NACHA-FILE-ID NACHA-EOF: false NACHA-REC-COUNT: 0 ] NACHA-READ: does [ NACHA-REC-COUNT: NACHA-REC-COUNT + 1 NACHA-REC: copy "" NACHA-CURRENT-TYPE: copy "" if none? NACHA-REC: pick NACHA-FILE NACHA-REC-COUNT [ NACHA-EOF: true ] if not NACHA-EOF [ NACHA-UNSTRING-RECORD ] ] NACHA-CLOSE-INPUT: does [ NACHA-FILE: copy [] NACHA-REC: copy "" ] NACHA-OPEN-OUTPUT: does [ NACHA-FILE: copy [] NACHA-REC: copy "" NACHA-REC-COUNT: 0 ] NACHA-WRITE: does [ append NACHA-FILE NACHA-REC NACHA-REC-COUNT: NACHA-REC-COUNT + 1 ] NACHA-CLOSE-OUTPUT: does [ write/lines NACHA-FILE-ID NACHA-FILE NACHA-FILE: copy [] NACHA-REC: copy "" ] ;WALKTHROUGH:Unstringing data NACHA-UNSTRING-RECORD: does [ NACHA-CURRENT-TYPE: GLB-SUBSTRING NACHA-REC 1 1 if = NACHA-CURRENT-TYPE "1" [ NACHA-UNSTRING-1 ] if = NACHA-CURRENT-TYPE "5" [ NACHA-UNSTRING-5 ] if = NACHA-CURRENT-TYPE "6" [ NACHA-UNSTRING-6 ] if = NACHA-CURRENT-TYPE "8" [ NACHA-UNSTRING-8 ] if = NACHA-CURRENT-TYPE "9" [ NACHA-UNSTRING-9 ] ] NACHA-UNSTRING-1: does [ NACHA-1-RECORD-TYPE-CODE: copy "" NACHA-1-PRIORITY-CODE: copy "" NACHA-1-IMMEDIATE-DESTINATION: copy "" NACHA-1-IMMEDIATE-ORIGIN: copy "" NACHA-1-TRANSMISSION-DATE: copy "" NACHA-1-TRANSMISSION-TIME: copy "" NACHA-1-FILE-ID-MODIFIER: copy "" NACHA-1-RECORD-SIZE: copy "" NACHA-1-BLOCKING-FACTOR: copy "" NACHA-1-FORMAT-CODE: copy "" NACHA-1-DESTINATION-NAME: copy "" NACHA-1-ORIGIN: copy "" NACHA-1-REFERENCE-CODE: copy "" NACHA-1-RECORD-TYPE-CODE: GLB-SUBSTRING NACHA-REC 1 1 NACHA-1-PRIORITY-CODE: GLB-SUBSTRING NACHA-REC 2 3 NACHA-1-IMMEDIATE-DESTINATION: GLB-SUBSTRING NACHA-REC 4 13 NACHA-1-IMMEDIATE-ORIGIN: GLB-SUBSTRING NACHA-REC 14 23 NACHA-1-TRANSMISSION-DATE: GLB-SUBSTRING NACHA-REC 24 29 NACHA-1-TRANSMISSION-TIME: GLB-SUBSTRING NACHA-REC 30 33 NACHA-1-FILE-ID-MODIFIER: GLB-SUBSTRING NACHA-REC 34 34 NACHA-1-RECORD-SIZE: GLB-SUBSTRING NACHA-REC 35 37 NACHA-1-BLOCKING-FACTOR: GLB-SUBSTRING NACHA-REC 38 39 NACHA-1-FORMAT-CODE: GLB-SUBSTRING NACHA-REC 40 40 NACHA-1-DESTINATION-NAME: GLB-SUBSTRING NACHA-REC 41 63 NACHA-1-ORIGIN: GLB-SUBSTRING NACHA-REC 64 86 NACHA-1-REFERENCE-CODE: GLB-SUBSTRING NACHA-REC 87 94 ] NACHA-UNSTRING-5: does [ NACHA-5-RECORD-TYPE-CODE: copy "" NACHA-5-SERVICE-CLASS-CODE: copy "" NACHA-5-BILLER-NAME: copy "" NACHA-5-RESERVED: copy "" NACHA-5-BILLER-ID-NUMBER: copy "" NACHA-5-ENTRY-CLASS: copy "" NACHA-5-ENTRY-DESCRIPTION: copy "" NACHA-5-DESCRIPTIVE-DATE: copy "" NACHA-5-EFFECTIVE-DATE: copy "" NACHA-5-SETTLEMENT-DATE: copy "" NACHA-5-CONCENTRATOR-STATUS: copy "" NACHA-5-NACHA-ID-NUMBER: copy "" NACHA-5-BATCH-NUMBER: copy "" NACHA-5-RECORD-TYPE-CODE: GLB-SUBSTRING NACHA-REC 1 1 NACHA-5-SERVICE-CLASS-CODE: GLB-SUBSTRING NACHA-REC 2 4 NACHA-5-BILLER-NAME: GLB-SUBSTRING NACHA-REC 5 20 NACHA-5-RESERVED: GLB-SUBSTRING NACHA-REC 21 40 NACHA-5-BILLER-ID-NUMBER: GLB-SUBSTRING NACHA-REC 41 50 NACHA-5-ENTRY-CLASS: GLB-SUBSTRING NACHA-REC 51 53 NACHA-5-ENTRY-DESCRIPTION: GLB-SUBSTRING NACHA-REC 54 63 NACHA-5-DESCRIPTIVE-DATE: GLB-SUBSTRING NACHA-REC 64 69 NACHA-5-EFFECTIVE-DATE: GLB-SUBSTRING NACHA-REC 70 75 NACHA-5-SETTLEMENT-DATE: GLB-SUBSTRING NACHA-REC 76 78 NACHA-5-CONCENTRATOR-STATUS: GLB-SUBSTRING NACHA-REC 79 79 NACHA-5-ID-NUMBER: GLB-SUBSTRING NACHA-REC 80 87 NACHA-5-BATCH-NUMBER: GLB-SUBSTRING NACHA-REC 88 94 NACHA-5-EFFECTIVE-DATE-E: rejoin [ GLB-SUBSTRING NACHA-5-EFFECTIVE-DATE 3 4 "/" GLB-SUBSTRING NACHA-5-EFFECTIVE-DATE 5 6 "/" "20" GLB-SUBSTRING NACHA-5-EFFECTIVE-DATE 1 2 ] ] NACHA-UNSTRING-6: does [ NACHA-6-RECORD-TYPE-CODE: copy "" NACHA-6-TRANSACTION-CODE: copy "" NACHA-6-NACHA-ID-NUMBER: copy "" NACHA-6-MERCHANT-ACCOUNT-NBR: copy "" NACHA-6-AMOUNT: copy "" NACHA-6-CONSUMER-ACCOUNT-NBR: copy "" NACHA-6-CONSUMER-NAME: copy "" NACHA-6-NACHA-FLAG: copy "" NACHA-6-ADDENDUM-RECORD-IND: copy "" NACHA-6-TRACE-NUMBER: copy "" NACHA-6-SEQUENCE-NUMBER: copy "" NACHA-6-RECORD-TYPE-CODE: GLB-SUBSTRING NACHA-REC 1 1 NACHA-6-TRANSACTION-CODE: GLB-SUBSTRING NACHA-REC 2 3 NACHA-6-NACHA-ID-NUMBER: GLB-SUBSTRING NACHA-REC 4 12 NACHA-6-MERCHANT-ACCOUNT-NBR: GLB-SUBSTRING NACHA-REC 13 29 NACHA-6-AMOUNT: GLB-SUBSTRING NACHA-REC 30 39 NACHA-6-CONSUMER-ACCOUNT-NBR: GLB-SUBSTRING NACHA-REC 40 54 NACHA-6-CONSUMER-NAME: GLB-SUBSTRING NACHA-REC 55 76 NACHA-6-NACHA-FLAG: GLB-SUBSTRING NACHA-REC 77 78 NACHA-6-ADDENDUM-RECORD-IND: GLB-SUBSTRING NACHA-REC 79 79 NACHA-6-TRACE-NUMBER: GLB-SUBSTRING NACHA-REC 80 87 NACHA-6-SEQUENCE-NUMBER: GLB-SUBSTRING NACHA-REC 88 94 NACHA-6-AMOUNT-N: to-money divide to-decimal NACHA-6-AMOUNT 100 ] NACHA-UNSTRING-8: does [ NACHA-8-RECORD-TYPE-CODE: copy "" NACHA-8-SERVICE-CLASS-CODE: copy "" NACHA-8-ENTRY-ADDENDA-COUNT: copy "" NACHA-8-ENTRY-HASH: copy "" NACHA-8-TOTAL-DEBIT: copy "" NACHA-8-TOTAL-CREDIT: copy "" NACHA-8-BILLER-ID-NUMBER: copy "" RPPT-8-MAC: copy "" NACHA-8-FILLER-1: copy "" NACHA-8-NACHA-ID-NUMBER: copy "" NACHA-8-BATCH-NUMBER: copy "" NACHA-8-RECORD-TYPE-CODE: GLB-SUBSTRING NACHA-REC 1 1 NACHA-8-SERVICE-CLASS-CODE: GLB-SUBSTRING NACHA-REC 2 4 NACHA-8-ENTRY-ADDENDA-COUNT: GLB-SUBSTRING NACHA-REC 5 10 NACHA-8-ENTRY-HASH: GLB-SUBSTRING NACHA-REC 11 20 NACHA-8-TOTAL-DEBIT: GLB-SUBSTRING NACHA-REC 21 32 NACHA-8-TOTAL-CREDIT: GLB-SUBSTRING NACHA-REC 33 44 NACHA-8-BILLER-ID-NUMBER: GLB-SUBSTRING NACHA-REC 45 54 NACHA-8-MAC: GLB-SUBSTRING NACHA-REC 55 73 NACHA-8-FILLER-1: GLB-SUBSTRING NACHA-REC 74 79 NACHA-8-NACHA-ID-NUMBER: GLB-SUBSTRING NACHA-REC 80 87 NACHA-8-BATCH-NUMBER: GLB-SUBSTRING NACHA-REC 88 94 NACHA-8-TOTAL-DEBIT-N: to-money divide to-decimal NACHA-8-TOTAL-DEBIT 100 NACHA-8-TOTAL-CREDIT-N: to-money divide to-decimal NACHA-8-TOTAL-CREDIT 100 ] NACHA-UNSTRING-9: does [ NACHA-9-RECORD-TYPE-CODE: copy "" NACHA-9-BATCH-COUNT: copy "" NACHA-9-BLOCK-COUNT: copy "" NACHA-9-ENTRY-ADDENDA-COUNT: copy "" NACHA-9-ENTRY-HASH: copy "" NACHA-9-TOTAL-DEBIT: copy "" NACHA-9-TOTAL-CREDIT: copy "" NACHA-9-FILLER-1: copy "" NACHA-9-RECORD-TYPE-CODE: GLB-SUBSTRING NACHA-REC 1 1 NACHA-9-BATCH-COUNT: GLB-SUBSTRING NACHA-REC 2 7 NACHA-9-BLOCK-COUNT: GLB-SUBSTRING NACHA-REC 8 13 NACHA-9-ENTRY-ADDENDA-COUNT: GLB-SUBSTRING NACHA-REC 14 21 NACHA-9-ENTRY-HASH: GLB-SUBSTRING NACHA-REC 22 31 NACHA-9-TOTAL-DEBIT: GLB-SUBSTRING NACHA-REC 32 43 NACHA-9-TOTAL-CREDIT: GLB-SUBSTRING NACHA-REC 44 55 NACHA-9-FILLER-1: GLB-SUBSTRING NACHA-REC 56 94 NACHA-9-TOTAL-DEBIT-N: to-money divide to-decimal NACHA-9-TOTAL-DEBIT 100 NACHA-9-TOTAL-CREDIT-N: to-money divide to-decimal NACHA-9-TOTAL-CREDIT 100 ] ;; ------------------------------------------------------------------- ===Fixed-format processing module The example above is a bit of fussing we would like to avoid if possible. Once you have taken apart a fixed-format record, you will do the same thing for any other and the only difference will be that the record will contain different fields at different locations. The script below encapsulates some funtions to ease the operations one has to do on fixed-format files. If you can specify the field locations on a record and provide them to these functions, you can access the fields on a record by name, and if you trust the functions enough to consider them a black box, the coding of your own program can be streamlined and thus a bit easier to understand. REBOL [ Title: "Fixed Format Text file functions" Purpose: {Useful functions for working with a text file of fixed-format records.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a bunch of functions for working with a file of fixed-format ] ;; [ text lines. It was created originally as the base for a program to ] ;; [ provide minimal, carefully controlled, editing of such a file by those ] ;; [ not familiary with text editors. ] ;; [ There will be procedures to open a file, read the next or previous ] ;; [ record, delete a record, add a new record at the end, and save the ] ;; [ file under its same name or a new name. ] ;; [ This module is not an independent program. It will be called by a ] ;; [ controlling program. ] ;; [---------------------------------------------------------------------------] ;; [---------------------------------------------------------------------------] ;; [ Items we will use in processing the file. ] ;; [---------------------------------------------------------------------------] FFTF-FILE-ID: none ;; File name we will be working on FFTF-FILE-ID-SAVE: none ;; File name for save-as operation FFTF-FIELDS: none ;; Field names and locations in a record FFTF-DATA: [] ;; Whole file in memory as a block of lines FFTF-RECORD: "" ;; One line of the file, the one we are working with FFTF-RECNO: 0 ;; Index of the record we are positioned at FFTF-FILE-SIZE: 0 ;; Number of lines in DATA FFTF-EOF: false ;; Set to true if we try to read past end FFTF-FOUND: false ;; Returned when searching ;; [---------------------------------------------------------------------------] ;; [ Open an existing file. ] ;; [ This function requires two items. The first is the name of the file. ] ;; [ The second is a block. The block will contain repetitions of a word ] ;; [ and a pair. The word will the the name of a field in the fixed-format ] ;; [ record. The pair will the the one-relative starting position of the ] ;; [ field (x) and the length of the field (y). ] ;; [ The "open" function will bring the whole file into memory and set up ] ;; [ various pointers and such for working with the lines in the file. ] ;; [---------------------------------------------------------------------------] FFTF-OPEN-INPUT: func [ FILEID [file!] FIELDLIST [block!] ] [ ;; -- Save what was passed to us. FFTF-FILE-ID: FILEID FFTF-FIELDS: FIELDLIST ;; -- Read the entire file into memory. Set various working items. FFTF-DATA: copy [] FFTF-DATA: read/lines FFTF-FILE-ID FFTF-FILE-SIZE: length? FFTF-DATA FFTF-RECNO: 0 FFTF-EOF: false ] ;; [---------------------------------------------------------------------------] ;; [ Read a record indicated by FFTF-RECNO. ] ;; [ "Read" means to copy the specified line into the record area and then ] ;; [ use the field list to set the words in the field list to the data ] ;; [ indicated by the position-length pair. ] ;; [---------------------------------------------------------------------------] FFTF-READ-SPECIFIC: does [ FFTF-EOF: false FFTF-RECORD: pick FFTF-DATA FFTF-RECNO foreach [FIELDNAME POSITION] FFTF-FIELDS [ FFTF-RECORD: head FFTF-RECORD FFTF-RECORD: skip FFTF-RECORD (POSITION/x - 1) set FIELDNAME copy/part FFTF-RECORD POSITION/y ] ] ;; [---------------------------------------------------------------------------] ;; [ To read the first/next/previous/last record, we will just adjust the ] ;; [ RECNO and use the above READ-SPECIFIC function. ] ;; [ Notice that we don't let RECNO get out of bounds, just in case we ] ;; [ misuse these procedures and try to read out of bounds. ] ;; [---------------------------------------------------------------------------] FFTF-READ-FIRST: does [ FFTF-RECNO: 1 either (FFTF-RECNO > FFTF-FILE-SIZE) [ FFTF-RECNO: FFTF-FILE-SIZE FFTF-EOF: true return FFTF-EOF ] [ FFTF-READ-SPECIFIC return FFTF-EOF ] ] FFTF-READ-NEXT: does [ FFTF-RECNO: FFTF-RECNO + 1 either (FFTF-RECNO > FFTF-FILE-SIZE) [ FFTF-RECNO: FFTF-FILE-SIZE FFTF-EOF: true return FFTF-EOF ] [ FFTF-READ-SPECIFIC return FFTF-EOF ] ] FFTF-READ-PREV: does [ FFTF-RECNO: FFTF-RECNO - 1 either (FFTF-RECNO < 1) [ FFTF-RECNO: 1 FFTF-EOF: true return FFTF-EOF ] [ FFTF-READ-SPECIFIC return FFTF-EOF ] ] FFTF-READ-LAST: does [ FFTF-RECNO: FFTF-FILE-SIZE either (FFTF-RECNO < 1) [ FFTF-RECNO: FFTF-FILE-SIZE FFTF-EOF: true return FFTF-EOF ] [ FFTF-READ-SPECIFIC return FFTF-EOF ] ] ;; [---------------------------------------------------------------------------] ;; [ Operations for saving the data or making a new file. ] ;; [---------------------------------------------------------------------------] FFTF-SAVE-FILE: does [ write/lines FFTF-FILE-ID FFTF-DATA ] FFTF-SAVE-FILE-AS: does [ FFTF-FILE-ID-SAVE: request-file/only/save either FFTF-FILE-ID-SAVE [ write/lines FFTF-FILE-ID-SAVE FFTF-DATA ] [ alert "No save-as ID requested" ] ] ;; [---------------------------------------------------------------------------] ;; [ We are going to have to be able to delete records, and also to update ] ;; [ them if the values of the fields are changed by some calling program. ] ;; [---------------------------------------------------------------------------] ;; -- Build a record using current values of the field names. FFTF-BUILD-RECORD: does [ FFTF-RECORD: copy "" loop 1024 [append FFTF-RECORD " "] foreach [FIELDNAME POSITION] FFTF-FIELDS [ FFTF-RECORD: head FFTF-RECORD FFTF-RECORD: skip FFTF-RECORD (POSITION/x - 1) change/part FFTF-RECORD (get FIELDNAME) POSITION/y ] FFTF-RECORD: head FFTF-RECORD FFTF-RECORD: trim/tail FFTF-RECORD ] ;; -- Delete the line pointed to by RECNO. FFTF-DELETE-RECORD: does [ remove at FFTF-DATA FFTF-RECNO FFTF-FILE-SIZE: FFTF-FILE-SIZE - 1 ] ;; -- Add a new record at the end of the file. FFTF-ADD-RECORD: does [ FFTF-BUILD-RECORD append FFTF-DATA FFTF-RECORD FFTF-FILE-SIZE: FFTF-FILE-SIZE + 1 ] ;; -- Change the record pointed to by RECNO using the field name values. FFTF-CHANGE-RECORD: does [ FFTF-BUILD-RECORD poke FFTF-DATA FFTF-RECNO FFTF-RECORD ] ;; -- Search for the record where the value of a given word is equal ;; -- to a given value. Return true or false. FFTF-SEARCH: func [ SEARCH-WORD SEARCH-VALUE ] [ FFTF-READ-FIRST until [ if equal? SEARCH-VALUE (get SEARCH-WORD) [ FFTF-FOUND: true return FFTF-FOUND ] FFTF-READ-NEXT ] FFTF-FOUND: false return FFTF-FOUND ] ;; -- Search ahead from where we are. FFTF-SEARCH-NEXT: func [ SEARCH-WORD SEARCH-VALUE ] [ FFTF-READ-NEXT until [ if equal? SEARCH-VALUE (get SEARCH-WORD) [ FFTF-FOUND: true return FFTF-FOUND ] FFTF-READ-NEXT ] FFTF-FOUND: false return FFTF-FOUND ] ;; -- Search backwards from where we are. FFTF-SEARCH-PREV: func [ SEARCH-WORD SEARCH-VALUE ] [ FFTF-READ-PREV until [ if equal? SEARCH-VALUE (get SEARCH-WORD) [ FFTF-FOUND: true return FFTF-FOUND ] FFTF-READ-PREV ] FFTF-FOUND: false return FFTF-FOUND ] ;; Uncomment to test ;FID: %fftf-testdata.txt ;; 123456789*123456789*123456789*123456789*1234 ;write/lines FID {11111111 22222222222222222222 3 4 5555555555 ;FIELD-1 TWENTY CHARACTERS... X Y 1234567890 ;AAAAAAAA BBBBBBBBBBBBBBBBBBBB P Q 0987654321 ;CCCCCCCC DDDDDDDDDDDDDDDDDDDD J K **********} ;FFTF-OPEN-INPUT FID [F1 1X8 F2 10X20 F3 31X1 F4 33X1 F5 35X10] ;foreach line FFTF-DATA [ ; print line ;] ;FFTF-READ-NEXT ;print rejoin ["F1 = '" F1 "'"] ;print rejoin ["F2 = '" F2 "'"] ;print rejoin ["F3 = '" F3 "'"] ;print rejoin ["F4 = '" F4 "'"] ;print rejoin ["F5 = '" F5 "'"] ;FFTF-READ-NEXT ;print rejoin ["F1 = '" F1 "'"] ;print rejoin ["F2 = '" F2 "'"] ;print rejoin ["F3 = '" F3 "'"] ;print rejoin ["F4 = '" F4 "'"] ;print rejoin ["F5 = '" F5 "'"] ;either FFTF-SEARCH 'F3 "P" [ ; print "P found" ;] [ ; print "No P found" ;] ;either FFTF-SEARCH 'F1 "FIELD-2" [ ; print "FIELD-2 found" ;] [ ; print "No FIELD-2 found" ;] ;FFTF-READ-FIRST ;F2: copy "New value" ;FFTF-CHANGE-RECORD ;foreach line FFTF-DATA [ ; print line ;] ;halt ==="Printing" to CSV It seems that REBOL was not designed for applications where printing on paper is done a lot, because there is nothing in the language that refers to putting things on paper. This is in contrast to a language like COBOL that was created in the days when the primary computer output was lots of paper. In COBOL you can "select" a file and "assign" it to "printer." But even in these times, one must put things on paper, so how is that done? In REBOL, it is done by letting other applications do it. In this example, we put our desired output into a CSV file, by just stringing them together separated by commas. Then, to get that output on paper, we open the CSV file with any popular spreadsheet program and use the spreadsheet printing function. One could code that stringing-together fresh each time we want some printed output, and that would not be too big a chore, but we can make the operation easier by writing some general-purpose functions for that. The example below shows that idea. Documentation is in the comments. REBOL [ Title: "PRTCSV: Format print lines for a csv file" ] ;; [---------------------------------------------------------------------------] ;; [ This is an object that can be used to define a csv file that will be ] ;; [ used as a "report." The general plan of action is that a program can ] ;; [ use this module to put reportable data into a csv file, and the ] ;; [ operator of the program then will use a popular spreadsheet program ] ;; [ to view the file and optionally put it on paper with the spreadsheet ] ;; [ programs own "print" feature. In other words, this module is a way to ] ;; [ handle "printing" in REBOL by ignoring the problem and letting ] ;; [ someone else (the spreadsheet program) do the work. ] ;; [ ] ;; [ To use: ] ;; [ ] ;; [ Make an instance of this object with: ] ;; [ MYCSVREPORT: make PRTCSV [ ] ;; [ FILEID: file-name ] ;; [ COLUMNS: [column-name-list] ] ] ;; [ ] ] ;; [ The reason we make an instance of an object is so that we can use this ] ;; [ one module to produce more than one report in a single program. ] ;; [ The column-name-list is a block of words that will become the column ] ;; [ headings of the csv file as well as words that you may set to values ] ;; [ to get those values into the output file. ] ;; [ ] ;; [ For example, say you want to produce a csv file with columns for ] ;; [ NAME, ADDRESS, and PHONE. You also want those words to be column ] ;; [ headings. (Note that a common way to use a spreadsheet is a little ] ;; [ "data file" where each row is a record, each column is a field, and ] ;; [ the first row contains the "field names.") You also want to create an ] ;; [ output file called csvreport.csv. ] ;; [ You would code this: ] ;; [ CSVREPORT: make PRTCSV [ ] ;; [ FILEID: %csvreport.csv ] ;; [ COLUMNS: [ ] ;; [ NAME ] ;; [ ADDRESS ] ;; [ PHONE ] ;; [ ] ] ;; [ ] ] ;; [ Note that CSVREPORT is a name that you make up, NAME, ADDRESS, and PHONE ] ;; [ are names that you make up, but PRTCSV is the name of the model ] ;; [ object, COLUMNS is the name of a data item in that model object, ] ;; [ and FILEID is a word that specifies the name of the file, ] ;; [ so PRTCSV, COLUMNS, and FILEID are words that must be use as they are; ] ;; [ they are not words that you would make up. By the way, make sure ] ;; [ the FILEID is a REBOL file name with the percent sigh in front. ] ;; [ ] ;; [ After you have done the above, you must perform a procedure before you ] ;; [ can "print" anything. You must call the function: ] ;; [ CSVREPORT/OPEN-OUTPUT ] ;; [ What this procedure will do is initialize some areas, plus create a ] ;; [ sub-object called RECORD, and inside RECORD will be words that you ] ;; [ may set to values. These words are the ones you specified when you ] ;; [ created the instance of the object. Using the above example, you will ] ;; [ have available the following data items: ] ;; [ CSVREPORT/RECORD/NAME ] ;; [ CSVREPORT/RECORD/ADDRESS ] ;; [ CSVREPORT/RECORD/PHONE ] ;; [ The above words are words you will set to values, for each row that ] ;; [ you want to put into the output file. ] ;; [ ] ;; [ When you want to "print" some data, you set the words you created to ] ;; [ values, and perform a procedure to create a row in the output file. ] ;; [ That procedure is called: ] ;; [ CSVREPORT/WRITE-RECORD ] ;; [ Now the obvious question is, what is the data type of each of those ] ;; [ words, so that I know what kind of values to set them to. ] ;; [ The answer is that they all are strings. Why is that? ] ;; [ Reason number one is that this is a basic module and it is easiest to ] ;; [ just use strings. There also is another reason. If we had some ] ;; [ method of assigning types at the time the words are created, then we ] ;; [ might end up with some situation where some sort of conversion was ] ;; [ being done at a low level, and something might not work, and one could ] ;; [ end up wrestling with this module to make it work. Generally, we like ] ;; [ to follow the principle of moving decisions up and moving work down, ] ;; [ which in practice means that this module will just "do what it is told ] ;; [ and not ask questions." ] ;; [ ] ;; [ When you are done "printing," the data you have "printed" will be in ] ;; [ memory, so you must put it on disk. You perform the procedure: ] ;; [ CSVREPORT/CLOSE-OUTPUT ] ;; [ The result will be that a file called csvreport.csv will come into ] ;; [ existence. The first line of the file will contain: ] ;; [ NAME,ADDRESS,PHONE ] ;; [ and the following lines will contain whatever data you specified for ] ;; [ those fields as many times as you specified it. The data fields ] ;; [ will be quoted and separated by commas. ] ;; [ ] ;; [ Remember that the purpose of this module is NOT to create a data file ] ;; [ for some sort of data manipulation, but rather to make a report. ] ;; [---------------------------------------------------------------------------] PRTCSV: make object! [ ;; [---------------------------------------------------------------------------] ;; [ Items the caller must set. ] ;; [---------------------------------------------------------------------------] FILEID: %csvreport.csv COLUMNS: [] ;; [---------------------------------------------------------------------------] ;; [ Working items. ] ;; [---------------------------------------------------------------------------] FILE-DATA: [] RECORD: none COLUMN-COUNT: 0 COLUMN-NUMBER: 0 ;; [---------------------------------------------------------------------------] ;; [ Open the file. ] ;; [ Using the supplied column names, construct the first line of the ] ;; [ output file, and create a record with words that the caller can set ] ;; [ to values. ] ;; [---------------------------------------------------------------------------] OPEN-OUTPUT: does [ COLUMN-NUMBER: length? COLUMNS FILE-DATA: copy [] HEADING-LINE: copy "" COLUMN-COUNT: 0 RECORD: make object! [] foreach COLUMN-NAME COLUMNS [ COLUMN-COUNT: COLUMN-COUNT + 1 append HEADING-LINE to-string COLUMN-NAME if lesser? COLUMN-COUNT COLUMN-NUMBER [ append HEADING-LINE "," ] RECORD: make RECORD compose [ (to-set-word COLUMN-NAME) {""} ] ] append FILE-DATA HEADING-LINE ] ;; [---------------------------------------------------------------------------] ;; [ Close the file. ] ;; [ Write to disk the lines we have been generating. ] ;; [---------------------------------------------------------------------------] CLOSE-OUTPUT: does [ write/lines FILEID FILE-DATA ] ;; [---------------------------------------------------------------------------] ;; [ Write a record. ] ;; [ Generate a text line from the words supplied by the caller. ] ;; [---------------------------------------------------------------------------] WRITE-RECORD: does [ COLUMN-COUNT: 0 DATA-LINE: copy "" foreach COLUMN-NAME COLUMNS [ append DATA-LINE mold RECORD/:COLUMN-NAME ;; mold adds quotes COLUMN-COUNT: COLUMN-COUNT + 1 if lesser? COLUMN-COUNT COLUMN-NUMBER [ append DATA-LINE "," ] ] append FILE-DATA DATA-LINE ] ] ;; End of object. ==="Printing" to TXT Another idea for printing, if you have a fixed-format page, is to put the "print lines" into a text file, and then use a text editor to print it. The sample below shows some functions for making this work, and documentation is in the comments. REBOL [ Title: "PRTTXT: Format print lines for a text file" ] ;; [---------------------------------------------------------------------------] ;; [ This is an object that can be used to define a fixed-format "report" ] ;; [ that is basically a text file of fixed-format lines, which when ] ;; [ completed may be printed through any text editor. ] ;; [ This is a solution for making basic columnar reports. It works as it ] ;; [ is, but may be used as an example or as a starting point for something ] ;; [ tailored to your own situation. ] ;; [ ] ;; [ The object provides basic functions that you would expect to perform ] ;; [ when printing a basic report. You will "open" the print file which ] ;; [ means to generate heading lines and provide instructions about where ] ;; [ to put data on a fixed-format print line. You will "close" the print ] ;; [ file when you are done which means to write your "print lines" to a ] ;; [ text file. Between opening and closing, you will "print" lines of ] ;; [ fixed-format text which means to format those lines based on data ] ;; [ you have submitted and then add those lines to a block of text that ] ;; [ represents the whole printed report. ] ;; [ ] ;; [ To use: ] ;; [ ] ;; [ Make an instance of the object with: ] ;; [ MYPRINTFILE: make PRTTXT [] ] ;; [ By using objects, this module lets you put several reports into the ] ;; [ same program. Optionally, you can set a line of text at the very ] ;; [ top of the report, and a line below that, this way: ] ;; [ MYPRINTFILE: make PRTTXT [ ] ;; [ SITE-NAME: "My Installation Name" ] ;; [ REPORT-TITLE: "Title of this report" ] ;; [ ] ] ;; [ ] ;; [ Before you can "print" to the report, you must "open" it. ] ;; [ This is just a way to get you to perform a procedure that does some ] ;; [ setup for you. You must provide two things to the "open" function. ] ;; [ You must provide a file name that will be used when you "close" the ] ;; [ report to write it to disk. You must provide a block that contains ] ;; [ repetitions of a word and a pair. The word will become a word that ] ;; [ you may set to a value when printing. The word also will become ] ;; [ a column heading on the report. The pair represents the column ] ;; [ position and the length, where the value of the word will be placed ] ;; [ on a fixed-format print line. This will look something like this: ] ;; [ MYPRINTFILE/OPEN-OUTPUT ] ;; [ %myprintifileid.txt ] ;; [ [word-1 pair-1 ] ;; [ word-2 pair-2 ] ;; [ ... ] ;; [ word-n pair-n] ] ;; [ The result of the above procedure will be that there will be an ] ;; [ object called MYPRINTFILE/RECORD ("MYPRINTFILE" is a name you choose; ] ;; [ this is just an example) and that object will have words, specifically, ] ;; [ the words you specified. You will set these words to values, ] ;; [ and when you "print" them they will go on the "print line" at the ] ;; [ spots indicated by the pairs. ] ;; [ ] ;; [ When you want to "print" data, you set the words you specified to ] ;; [ values by referring to them in the RECORD object. For example: ] ;; [ MYPRINTFILE/RECORD/word-1: value-1 ] ;; [ MYPRINTFILE/RECORD/word-2: value-2 ] ;; [ When you have set the values you want to print, you perform the ] ;; [ procedure to put that data into the file: ] ;; [ MYPRINTFILE/WRITE-RECORD ] ;; [ ] ;; [ When you are done producing the report, you have to get it into a disk ] ;; [ file with: ] ;; [ MYPRINTFILE/CLOSE-OUTPUT ] ;; [---------------------------------------------------------------------------] PRTTXT: make object! [ ;; [---------------------------------------------------------------------------] ;; [ Items the caller may override when creating an instance of this object. ] ;; [---------------------------------------------------------------------------] REPORT-TITLE: "" ;; Text to put at the top of the report SITE-NAME: "" ;; Your installation name at the very top of the report ;; [---------------------------------------------------------------------------] ;; [ Working items ] ;; [ Note that the SPACEFILL function expects a string. It is the job of ] ;; [ the caller to do any necessary conversion. ] ;; [---------------------------------------------------------------------------] FILE-ID: none ;; Name of a file we will create FIELDS: none ;; Fields submitted at open time FILE-DATA: [] ;; All the data in the above file RECORD: none ;; An object we will create for loading data PRINT-LINE: none ;; A formatted line to put into FILE-DATA HEADING-LINE: none ;; A line of column headings HYPHEN-LINE: none ;; Hyphens under column headings SPACEFILL: func [ "Left justify a string, pad with spaces to specified length" INPUT-STRING FINAL-LENGTH ] [ head insert/dup tail copy/part trim INPUT-STRING FINAL-LENGTH #" " max 0 FINAL-LENGTH - length? INPUT-STRING ] ;; -- Not sure if we want to allow for right-or-left justification. SPACEFILL-LEFT: func [ "Right justify a string, pad with spaces to specified length" INPUT-STRING FINAL-LENGTH ] [ trim INPUT-STRING either FINAL-LENGTH > length? INPUT-STRING [ return head insert/dup INPUT-STRING " " FINAL-LENGTH - length? INPUT-STRING ] [ return copy/part INPUT-STRING FINAL-LENGTH ] ] HYPHENS: func [ "Return a string of a given number of hyphens" SPACE-COUNT [integer!] /local FILLER ] [ FILLER: copy "" loop SPACE-COUNT [ append FILLER "-" ] return FILLER ] ;; [---------------------------------------------------------------------------] ;; [ Create the RECORD sub-object from words provided. ] ;; [ Create a heading line by converting the words to strings and putting ] ;; [ them into a heading line at the spots indicated by the pairs associated ] ;; [ with the words. ] ;; [ Put the SITE-NAME, REPORT-TITLE, and HEADING-LINE into the first lines ] ;; [ of the output file. ] ;; [---------------------------------------------------------------------------] OPEN-OUTPUT: func [ FILEID [file!] FIELDLIST [block!] ] [ ;; -- Save the data from the caller. FILE-ID: FILEID FIELDS: copy FIELDLIST ;; -- Initialize the output area. FILE-DATA: copy [] ;; -- Make an object (RECORD) that the caller will load with data. RECORD: make object! [] foreach [FIELDNAME POSITION] FIELDS [ RECORD: make RECORD compose [ (to-set-word FIELDNAME) {""} ] ] ;; -- Build a heading line out of the words from the caller. HEADING-LINE: copy "" loop 256 [append HEADING-LINE " "] foreach [FIELDNAME POSITION] FIELDS [ HEADING-LINE: head HEADING-LINE HEADING-LINE: skip HEADING-LINE (POSITION/x - 1) change/part HEADING-LINE SPACEFILL to-string FIELDNAME POSITION/y POSITION/y ] HEADING-LINE: head HEADING-LINE HEADING-LINE: trim/tail HEADING-LINE ;; -- Make a line of hyphens under each column heading. HYPHEN-LINE: copy "" loop 256 [append HYPHEN-LINE " "] foreach [FIELDNAME POSITION] FIELDS [ HYPHEN-LINE: head HYPHEN-LINE HYPHEN-LINE: skip HYPHEN-LINE (POSITION/x - 1) change/part HYPHEN-LINE HYPHENS POSITION/y POSITION/y ] HYPHEN-LINE: head HYPHEN-LINE HYPHEN-LINE: trim/tail HYPHEN-LINE ;; -- Put heading lines into data area. append FILE-DATA SITE-NAME append FILE-DATA "" append FILE-DATA REPORT-TITLE append FILE-DATA "" append FILE-DATA HEADING-LINE append FILE-DATA HYPHEN-LINE append FILE-DATA "" ] ;; [---------------------------------------------------------------------------] ;; [ Close the file by writing the data block to disk. ] ;; [---------------------------------------------------------------------------] CLOSE-OUTPUT: does [ WRITE/LINES FILE-ID FILE-DATA ] ;; [---------------------------------------------------------------------------] ;; [ Write a print line. ] ;; [ The operator has set the words in RECORD to values. ] ;; [---------------------------------------------------------------------------] WRITE-RECORD: does [ PRINT-LINE: copy "" loop 256 [append PRINT-LINE " "] foreach [FIELDNAME POSITION] FIELDS [ PRINT-LINE: head PRINT-LINE PRINT-LINE: skip PRINT-LINE (POSITION/x - 1) change/part PRINT-LINE SPACEFILL RECORD/:FIELDNAME POSITION/y POSITION/y ] PRINT-LINE: head PRINT-LINE PRINT-LINE: trim/tail PRINT-LINE append FILE-DATA PRINT-LINE ] ;; [---------------------------------------------------------------------------] ;; [ Allow for double spacing in case the resulting file is used like a ] ;; [ report, that is, examined visually (which is the original design goal). ] ;; [---------------------------------------------------------------------------] SKIP-LINE: does [ append FILE-DATA "" ] ] ;; ----------------------------------------------------------------------------- ==="Printing" to HTML Another way to print is to generate an HTML file and let a web browser print it. That could be a lot of work if you have to output the markup as well as the data. If you are willing to accept restrictions on the look of the output, in other words, if you do not insist on things that look really fancy, you can make some functions that wrap your output in some modest HTML markup and let those functions to the markup, while you worry about only the data. The example below shows that, and the documentation is in the comments. In this example, the "report" has the look of a fixed-format report. It is the job of the caller to produce a fixed-format "print line." Sending that pre-formatted line to the appropriate function wraps it up in the "pre" tags and other appropriate markup. REBOL [ Title: "Printing module using HTML" Purpose: {A COBOL-like method for printing basic text-oriented business reports in an html file with markup such that we can get proper page breaks.} ] ;; [---------------------------------------------------------------------------] ;; [ This is a module for primitive printing. ] ;; [ It puts pre-formatted lines of text into an html file that includes ] ;; [ markup such that if the html file is printed then requested page ] ;; [ breaks will ge made correctly. ] ;; [---------------------------------------------------------------------------] ;; [---------------------------------------------------------------------------] ;; [ These items are the ones that would have to adjusted for a particular ] ;; [ installation. They could be pulled out into a configuration file ] ;; [---------------------------------------------------------------------------] HTMPRT-INSTALLATION-NAME: "INFORMATION SYSTEMS" HTMPRT-FILE-ID: %printfile.html HTMPRT-REPORT-ID: "" ;; [---------------------------------------------------------------------------] ;; [ "Printing" is going to mean appending a print line to the end of ] ;; [ this big string. When we "close" the print "file," this big string ] ;; [ will be written to a file. Actually putting it on paper will be done ] ;; [ by reading the file with a web browser and using the browser to print. ] ;; [---------------------------------------------------------------------------] HTMPRT-FILE: "" ;; [---------------------------------------------------------------------------] ;; [ Here are some other important items, defined here so we can keep ] ;; [ track of them. ] ;; [---------------------------------------------------------------------------] HTMPRT-PAGE-SIZE: 57 HTMPRT-LINE-COUNT: 0 ;; [---------------------------------------------------------------------------] ;; [ This is the html markup we will need to make this work. ] ;; [---------------------------------------------------------------------------] HTMPRT-HEAD-DOC: { <% HTMPRT-REPORT-ID %> } HTMPRT-HEAD-FIRSTPAGE: {

<% HTMPRT-INSTALLATION-NAME %>

    }

    HTMPRT-HEAD-NEXTPAGE: {
    

<% HTMPRT-INSTALLATION-NAME %>

    }

    HTMPRT-FOOT-DOC: {
    
} ;; [---------------------------------------------------------------------------] ;; [ This procedure "opens" the print "file," which means we will clear ] ;; [ out the string and put some initial printer control characters ] ;; [ into it. In this module, "control characters" means the html markup ] ;; [ to cause the proper page break before each new heading when we print. ] ;; [---------------------------------------------------------------------------] HTMPRT-OPEN: does [ HTMPRT-FILE: copy "" append HTMPRT-FILE build-markup HTMPRT-HEAD-DOC append HTMPRT-FILE build-markup HTMPRT-HEAD-FIRSTPAGE HTMPRT-LINE-COUNT: 0 ] ;; [---------------------------------------------------------------------------] ;; [ This procedure "closes" the print "file," which means we will ] ;; [ put the appropriate closing markukp at the end of the string and ] ;; [ write it to a file. ] ;; [---------------------------------------------------------------------------] HTMPRT-CLOSE: does [ append HTMPRT-FILE build-markup HTMPRT-FOOT-DOC write HTMPRT-FILE-ID HTMPRT-FILE ] ;; [---------------------------------------------------------------------------] ;; [ This procedure causes a page skip by adding a heading line with the ] ;; [ "break" class so that if we print the page, the browser will eject ] ;; [ a page. ] ;; [---------------------------------------------------------------------------] HTMPRT-EJECT: does [ append HTMPRT-FILE build-markup HTMPRT-HEAD-NEXTPAGE HTMPRT-LINE-COUNT: 0 ] ;; [---------------------------------------------------------------------------] ;; [ This procedure "prints" a line passed to it, which means we will ] ;; [ append the passed line to the file, and add a newline. ] ;; [ The refinement of "double" puts an extra newline at the end for ] ;; [ double spacing. ] ;; [---------------------------------------------------------------------------] HTMPRT-PRINT: func [ HTMPRT-PRINT-LINE /DOUBLE ] [ append HTMPRT-FILE HTMPRT-PRINT-LINE append HTMPRT-FILE newline HTMPRT-LINE-COUNT: HTMPRT-LINE-COUNT + 1 if DOUBLE [ append HTMPRT-FILE rejoin [
newline] HTMPRT-LINE-COUNT: HTMPRT-LINE-COUNT + 1 ] ] ;; [---------------------------------------------------------------------------] ;; [ The procedures below use the procedures above for printing in a ] ;; [ classic COBOL manner. They print headings automatically, checks for ] ;; [ page skips, and so on. ] ;; [ The caller of this module should "do" it early in the program to define ] ;; [ the items below, and then set the following items to desired values: ] ;; [ LP-PROGRAM: Name of the program making the report. ] ;; [ LP-REPORT: 50-character report description. ] ;; [ LP-SUBTITLE: not used until we figure out how to center it. ] ;; [ What these procedures are going to give you is a report of text lines ] ;; [ in a fixed-width font, like the line printer of the COBOL days. ] ;; [---------------------------------------------------------------------------] ;; -- Items to be loaded before first use HTMPRT-LP-PROGRAM: "" HTMPRT-LP-REPORT: "" HTMPRT-LP-SUBTITLE: "" HTMPRT-LP-PAGE-COUNT: 1 HTMPRT-LP-TITLE: copy HTMPRT-INSTALLATION-NAME HTMPRT-LP-HEADING-1: "" HTMPRT-LP-HEADING-2: "" HTMPRT-LP-USER-HEADING-1: "" HTMPRT-LP-USER-HEADING-2: "" HTMPRT-LP-USER-HEADING-3: "" HTMPRT-LP-USER-HEADING-COUNT: 0 HTMPRT-LP-PROG-LGH: 0 HTMPRT-LP-REPT-LGH: 0 HTMPRT-LP-PROG-20: "" HTMPRT-LP-REPT-50: "" ;; -- Helper functions for the main printing functions HTMPRT-SUBSTRING: func [ "Return a substring from the start position to the end position" INPUT-STRING [series!] "Full input string" START-POS [number!] "Starting position of substring" END-POS [number!] "Ending position of substring" ] [ if END-POS = -1 [END-POS: length? INPUT-STRING] return skip (copy/part INPUT-STRING END-POS) (START-POS - 1) ] HTMPRT-FILLER: func [ "Return a string of a given number of spaces" SPACE-COUNT [integer!] /local FILLER ] [ FILLER: copy "" loop SPACE-COUNT [ append FILLER " " ] return FILLER ] HTMPRT-SPACEFILL: func [ "Left justify a string, pad with spaces to specified length" INPUT-STRING FINAL-LENGTH /local TRIMMED-STRING LENGTH-OF-TRIMMED-STRING NUMBER-OF-SPACES-TO-ADD FINAL-PADDED-STRING ] [ TRIMMED-STRING: copy "" TRIMMED-STRING: trim INPUT-STRING LENGTH-OF-TRIMMED-STRING: length? TRIMMED-STRING either (LENGTH-OF-TRIMMED-STRING < FINAL-LENGTH) [ NUMBER-OF-SPACES-TO-ADD: (FINAL-LENGTH - LENGTH-OF-TRIMMED-STRING) FINAL-PADDED-STRING: copy TRIMMED-STRING loop NUMBER-OF-SPACES-TO-ADD [ append FINAL-PADDED-STRING " " ] ] [ FINAL-PADDED-STRING: COPY "" FINAL-PADDED-STRING: HTMPRT-SUBSTRING TRIMMED-STRING 1 FINAL-LENGTH ] ] ;; -- Main printing functions HTMPRT-LP-PRINT-USER-HEADINGS: does [ HTMPRT-LP-USER-HEADING-COUNT: 0 if (HTMPRT-LP-USER-HEADING-1 <> "") [ HTMPRT-PRINT HTMPRT-LP-USER-HEADING-1 HTMPRT-LP-USER-HEADING-COUNT: HTMPRT-LP-USER-HEADING-COUNT + 1 ] if (HTMPRT-LP-USER-HEADING-2 <> "") [ HTMPRT-PRINT HTMPRT-LP-USER-HEADING-2 HTMPRT-LP-USER-HEADING-COUNT: HTMPRT-LP-USER-HEADING-COUNT + 1 ] if (HTMPRT-LP-USER-HEADING-3 <> "") [ HTMPRT-PRINT HTMPRT-LP-USER-HEADING-3 HTMPRT-LP-USER-HEADING-COUNT: HTMPRT-LP-USER-HEADING-COUNT + 1 ] if (HTMPRT-LP-USER-HEADING-COUNT > 0) [ HTMPRT-PRINT "" ] ] HTMPRT-LP-OPEN: does [ HTMPRT-OPEN HTMPRT-LP-PAGE-COUNT: 1 HTMPRT-LP-PROG-LGH: length? HTMPRT-LP-PROGRAM either (HTMPRT-LP-PROG-LGH >= 20) [ HTMPRT-LP-PROG-20: HTMPRT-SUBSTRING HTMPRT-LP-PROGRAM 1 20 ] [ HTMPRT-LP-PROG-20: HTMPRT-SPACEFILL HTMPRT-LP-PROGRAM 20 ] HTMPRT-LP-REPT-LGH: length? HTMPRT-LP-REPORT either (HTMPRT-LP-REPT-LGH >= 50) [ HTMPRT-LP-REPT-50: HTMPRT-SUBSTRING HTMPRT-LP-REPORT 1 50 ] [ HTMPRT-LP-REPT-50: HTMPRT-SPACEFILL HTMPRT-LP-REPORT 50 ] HTMPRT-LP-HEADING-1: rejoin [ HTMPRT-LP-PROG-20 HTMPRT-FILLER 43 HTMPRT-LP-TITLE HTMPRT-FILLER 52 now/date ] HTMPRT-LP-HEADING-2: rejoin [ HTMPRT-LP-REPT-50 HTMPRT-FILLER 13 HTMPRT-FILLER 39 ;; subtitle, eventually HTMPRT-FILLER 52 "Page " to-string HTMPRT-LP-PAGE-COUNT ] HTMPRT-PRINT HTMPRT-LP-HEADING-1 HTMPRT-PRINT/DOUBLE HTMPRT-LP-HEADING-2 HTMPRT-LP-PRINT-USER-HEADINGS ] HTMPRT-LP-CLOSE: does [ HTMPRT-CLOSE ] HTMPRT-LP-PRINT: func [ HTMPRT-LP-PRINT-LINE /DOUBLE ;; not used at this time ] [ if (HTMPRT-LINE-COUNT >= HTMPRT-PAGE-SIZE) [ HTMPRT-LINE-COUNT: 0 HTMPRT-LP-PAGE-COUNT: HTMPRT-LP-PAGE-COUNT + 1 HTMPRT-LP-HEADING-2: copy "" HTMPRT-LP-HEADING-2: rejoin [ HTMPRT-LP-REPT-50 HTMPRT-FILLER 13 HTMPRT-FILLER 39 ;; subtitle, eventually HTMPRT-FILLER 52 "Page " to-string HTMPRT-LP-PAGE-COUNT ] HTMPRT-EJECT HTMPRT-PRINT HTMPRT-LP-HEADING-1 HTMPRT-PRINT/DOUBLE HTMPRT-LP-HEADING-2 HTMPRT-LP-PRINT-USER-HEADINGS ] HTMPRT-PRINT HTMPRT-LP-PRINT-LINE ]