ࡱ>  /1&'()*+,-.7 hbjbjUU -7|7||kl .g.g.g8fgbhonZr4rrr Oooooooo$q s:o+h++:oo rrOoooo+01 &rroo+oooB8X^r~n `-^˿lW.g[\f^eo0ov\/t/t^o  Design Specification Version 1.0a  Sports Score System A Speech Enabled Application Sponsor: Jim Larson Development Team: Dan Corkum Jason Nguyen Dan Ragland Quang Vu Andrew Wagner  TIME \@ "MMMM d, yyyy" May 31, 2000 Table of Contents Introduction  PAGEREF Introduction \h 3 System Overview  PAGEREF SystemOverview \h 2 Design Considerations...  PAGEREF DesignConsiderations \h 4 Assumptions and Dependencies....  PAGEREF AssumptionsAndDependencies \h 4 Goals and Guidelines.  PAGEREF GoalsAndGuidelines \h 5 Architectural Strategies.  PAGEREF ArchitecturalStrategies \h 6 System Architecture...  PAGEREF SystemArchitecture \h 7 Web Viking..  PAGEREF SubSysArchitectWebViking \h 7 SSDB (Sports Score Database) Interface.  PAGEREF SubSysArchitectSSDBI \h 8 Server Component  PAGEREF SubSysArchitectServer \h 9 Server Communications.  PAGEREF SubSysArchitectServerComm \h 10 Client Communications..  PAGEREF SubSysArchitectClientComm \h 11 Client Component...  PAGEREF SubSysArchitectClient \h 11 Dialog Database.  PAGEREF SubSysArchitectDialogDB \h 13 SSDB (Sports Score Database)..  PAGEREF SubSysArchitectSSDB \h 19 Dialog Generation Utility..  PAGEREF SubSysArchitectDialogUtility \h 19 Policies and Tactics  PAGEREF PoliciesAndTactics \h 19 Detailed System Design.  PAGEREF DetailedSystemDesign \h 20 Web Viking.  PAGEREF DetailedSystemDesignWebViking \h 20 SSDB (Sports Score Database) Interface. PAGEREF DetailedSystemDesignSSDBI \h 20 Server Component..  PAGEREF DetailedSystemDesignServerComponent \h 22 Server Communications.  PAGEREF DetailedSystemDesignServerComm \h 22 Client Communications..  PAGEREF DetailedSystemDesignClientComm \h 23 Client Component...  PAGEREF DetailedSystemDesignClientComponent \h 24 Dialog Database  PAGEREF DetailedSystemDesignDialogDatabase \h 24 Dialog Generation Utility Detailed SubSystem Design...  PAGEREF DetailedSubsystemDesign \h 24 Web Viking  PAGEREF DetailedSubSystemDesignWebViking \h 24 SSDB (Sports Score Database) Interface..  PAGEREF DetailedSubSystemDesignSSDBI \h 27 Server Component..  PAGEREF DetailedSubSystemDesignServerComponent \h 27 Server Communications.  PAGEREF DetailedSubSystemDesignServerComm \h 27 Client Communications.  PAGEREF DetailedSubSystemDesignClientComm \h 32 Client Component..  PAGEREF DetailedSubSystemDesignClientComponent \h 36 Dialog Generation Utility...  PAGEREF DetailedSubSystemDesignDialogUtility \h 68 Glossary.  PAGEREF Glossary \h 68 Acronyms and Abbreviations.  PAGEREF AcronymsAndAbbreviations \h 69 Bibliography.  PAGEREF Bibliography \h 69  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC4" Introduction This document is designed to be a reference for any person wishing to implement or any person interested in the architecture of the sports score client application, sports score server application, dialog database, or the sports score database. This document describes each applications architecture and sub-architecture their associated interfaces, database schemas, and the motivations behind the chosen design. Both high-level and low-level designs are included in this document. This document should be read by an individual with a technical background and has experience reading data flow diagrams (DFDs), control flow diagrams (CFDs), interface designs, and development experience in object oriented programming and event driven programming. This design document has an accompanying specification document and test document. This design document is per Sports Score System Specification version 3.0. Any previous or later revisions of the specifications require a different revision of this design document. This document includes but is not limited to the following information for the Sports Score System; system overview, design considerations, architectural strategies, system architecture, policies and tactics, and detailed system design.  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC5" System Overview  The Sports Score System is a system  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC6" Design Considerations This section describes many of the issues that needed to be addressed or resolved before attempting to devise a complete design solution.  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC7" Assumptions and Dependencies This design of the Sports Score system makes several assumptions about software and hardware, and has several software dependencies. All environmental requirements of both the server and client applications can be found in the Sports Score System Requirements 3.1. Both the server and client applications make the following assumptions about their environmental environments; The system can be described by the environmental requirements associated to this document. The system the application is executing on will have the required resources available as necessary. This entails sufficient memory and permanent storage space, an adequate CPU for the necessary application, and a TCP/IP network connection. The client application makes the following assumptions about its operation environment; The client machine will have MDAC 2.5 (Microsoft Data Access Components) installed. The client application is dependent on this set of component. These components are required for our implementation of access to the dialog database. The client machine will have the necessary databases setup through ODBC (Open DataBase Connectivity). The client machine will have Microsoft SAPI 4.0 (Speech Application Programming Interface) installed properly. This is necessary for speech recognition with this design. The client machine will have an appropriate sound card installed which supports full-duplex. This is necessary for speech recognition Barge-In technologies. The client machine will have an appropriate microphone and sound system for speech recognition. The server application makes the following assumptions about its operation environment; The server machine will have MDAC 2.5 (Microsoft Data Access Components) installed. The server application is dependent on this set of components. These components are required for our implementation of access to the Sports Score database. The server machine will have the necessary databases setup through ODBC (Open DataBase Connectivity). Preferably the server machine will have TCP port 12345 free for use of the server application. This is the default port for the server to listen on, though it is not required to listen on this port.  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC9" Goals and Guidelines The major goal of the Sports Score client is that it be extremely simple and intuitive to use. The application is geared towards the sports enthusiast, not a technically inclined individual. It is very important that the prompts for the user be clear and concise since this will be the highest level of interaction between the application and the user. It is also important that series of prompts and responses be tested with users before being deployed as part of the product so that all interaction is approved by a potential user. The second major goal of the application is that the user gets a response in a timely fashion. Intuition tells that a user will lose interest if they have to wait long times for software to respond. This is why the design has minimal data transferred between client and server. In this design, a minimum set of information is transferred to the server in order to retrieve the necessary information, and the server only returns the requested data that is then formatted into a readable phrase on the client side. A third major goal is that the client application could possibly be stored on a wireless cellular device. As voice recognition improves with time, the size of the footprint of the application decreases relative to memory available. In future revisions of the client application, there is a great possibility that the Sports Score client be stored on a cellular telephone. A user could then request sports information, or any other type of information, from anywhere in the world at any time. This design attempted to keep the client application as data independent as possible. All prompts and responses on the client side are completely data driven, so any prompt or response can be changed by a simple voice database change without changing any code. This makes the client capable of prompting and responding to any structural type of data. Theoretically the client could be loaded onto a cellular device and have the types of information available changed with a simple database change. Potentially this could be done remotely from the server when the client application loads. The Sports Score server is intended to have a simple interface that is relatively easy to administer. A minimal yet complete set of options is provided for the server administrator to have control of resources consumed by the server application. These options include, but are not limited to; controlling the limit of clients able to connect to the server for maximum efficiency, ability to configure which port the server listens on, ability to change the Sports Score database location, and control how often the database is updated.  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC11" Architectural Strategies The sports score system design has been divided into four major sub-systems; server application, client application, Sports Score database, and dialog database. The server application is then separated into five major sub-sections; the server component, server communications, server GUI (Graphical User Interface), the Sports Score Database (SSDB) interface, and the web viking. The client application is separated into two major sub-sections; the client component, and the client communications. The server applications major design considerations include easy sports score data retrieval, easy database updates, multiple client support, and a minimal set of administrative features. The server application has been designed to be as flexible as possible, trying not to design the server for specifically sports score information, but for any type of information. Given the projects constraints of human resources, software resources, and time, the server is not completely data independent. Portions of the server application are specific to this sports score system. These portions are discussed in the server applications detailed design strategies. The client application is designed to support the following major features; a simple and intuitive vocal user interface (VUI), easy to understand dialogs, flexible dialog structure support, and support of an internet transport for sports score information retrieval. Unlike the server application, the client application has been designed completely data independent. No portion of the client application is implementation dependent (excluding dialog database access). This provides maximal flexibility for other potential uses for the client application. Given the systems requirement that the client application must be supported on a Windows platform, this design uses several Windows specific technologies such as Microsofts SAPI (Speech Application Programming Interface), ADO (ActiveX Data Objects), and JDBC (Java Database Connectivity). These technologies were chosen because they required the least amount of research and learning time, both of which we are limited in.  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC12" System Architecture  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC13" Subsystem Architecture 1 - Web Viking   Web sites Error messages   Time Formatted data Figure 1 Web Viking Program Level 0 Continued refinement to primitive transforms       Figure 2 Web Viking Program Level 1 Retrieve HTML files: Well first retrieve data from MLBWS ( HYPERLINK "http://www.majorleaguebaseball.com" http://www.majorleaguebaseball.com) if the data retrieved OK, then use this data as the input of the parse subroutine. Otherwise, log errors and retrieve data from ESPNWS ( HYPERLINK "http://espn.go.com/mlb" http://espn.go.com/mlb.) If the data retrieved OK the use this data as the input of the parse subroutine. Otherwise, log errors. Parse HTML files: Well go though each line of the HTML file, check if the line contains useful data; if so parse the line and get the data. Format outputs: Put parsed data in the format that well discuss in the interface section. Then check if we get the correct data. The reason that we wait until this part to check the data instead of doing that right after we get the data is efficiency. We dont want spending too much time checking data. If the data is correct, then write it to file. Otherwise, log errors. File maintenance Create the directories data and logerr under the directory contains the programs to store results and log errors, respectively. The programs (schedule.pl, scores.pl, and standing.pl) should be executed right before midnight to ensure the stable format of the web site. So, well have more chance getting the correct data. To run the schedule program, type: perl schedule.pl To run the score program, type: perl scores[ mmdd]+ Example: perl scores 0507 0523 0612 0507 means May 7 To run the standing program, type: perl standing.pl 2 - SSDB (Sports Score Database) Interface The SSDB class has two distinct components: The Database is implemented using MS Access. It functions as storage to keep track of the entire team names, scores associated with each team and the schedule of date and time of game taken place. The Handler written in Java, its primary purpose is to query the database and fetch the results to the sport score server. 3 - Server Component/Server GUI (Graphical User Interface) The server component can be broken up into three distinct sub-components; The GUI, the logger, and the server properties. Sports Score server GUI  The GUI (Graphical User Interface) is how the administrator interacts with the Sports Score server. The GUI provides the details/statistics about the server log, server TCP port, client limit, data fetch time, data source, and number of clients currently connected. The administrator is provided the ability to configure the maximum number of clients, the time the server fetches sports data, the sports data source, the port the server uses, the database location (via ODBC Manager), and if debug logging is on or not. The administrator also has the ability to start and stop the communications service on the fly. This is useful for pre-disconnecting users before the server terminates, and changing the server port on the fly. The logger will log information about the server application, communications, Sports Score database, or webViking. This log is written out to file in the event that the server unexpectedly terminates. Optionally the log can be displayed in any Object. The logger has two states it operates under; debug or not debug. In debug mode, the logger will log any request to log information that is called upon it. In non-debug mode, the logger discriminates between mandatory logs, and debug logs and records only the mandatory information. The server properties sub-component is used to store the properties and state of the server that must be maintained when the server is terminated. Such properties include; server port, maximum number of clients, debug mode, data server, and sports score data fetch time. All server properties are retrieved and stored in a properties file called options.txt. When an property is changed, it is written out to the properties file. In the event that a property description is not found in this file, a default is assigned to a given property. 4 N/A 5 - Server Communications serverComm internal structure    The server communications can be separated into three sub-components; the serverComm interface, the server communications thread, and the server client threads. The interface to the Sports Score server provides a set of methods to use the server communications module. Once the server starts the communications, a server communications thread is started. If any interaction/information is required between the server application and communications, this interface provides those services. The server communications thread (serverCommThread) is responsible for managing the user connections. When started by the server, this thread listens on a specified TCP (Transmission Control Protocol) port for Sports Score clients. When a client requests a connection, the serverCommThread spins off a new serverClientThread. Each client connected to the server is associated with one serverClientThread. The serverCommThread also keeps a vector of serverClientThreads in the case that these need to be terminated, counted, or interacted with in some manner. The server client thread (serverClientThread) is responsible for direct communications with a connected Sports Score client. When a client makes a data request, the serverClientThread forwards this request onto the Sports Score database interface which will then parse the request and retrieve the requested information. The serverClientThread then packages this information and forwards it onto the client. The client is then ultimately responsible for terminating the connection to the server. When the client terminates, the thread notifies the server communications thread that it has been terminated and it is then removed from the server communications threads vector. 6 - Client Communications clientComm internal structure   The client communications module provides a very basic and simple interface for the Sports Score client application to use. The client connects to the Sports Score server via the connect() method. This method will inform the client if the connection to the specified server and port is successful or not. The client can then transmit sports data requests via the write method, and can receive results via the read method. Internally, the client communications module will packetize any data being transmitted to the server, and will de-packetize and data coming from the server. These packets provide a method of both label data with a type (data request, ping, etc) and putting a terminating character on the packet so the server knows if the complete packet has been transmitted or not. This provides the ability for multiple types of information to be transmitted to the server, and provides the server an ability to route that information based on the label of that packet. 7 - Client Component The user interface will be designed as two separate pieces--the dialogs, help systems, acceptable user commands, etc., and the infrastructure that will present this information to, and accept responses from the user. The distinction between the dialogs and the code to present the dialogs is made to increase modularity and ease of updating dialogs. Since the same rules are used to present each prompt to the user, it makes sense to keep all of the code in one place. The dialogs themselves will not be hard-coded into the system. Rather, they will be read and interpreted from a database structure. A separate utility to manage the dialog database would make the dialog-building process much simpler than if each dialog had to be coded into the system (see the Dialog Builder, implemented and used to build the dialogs for this project). Moreover, an end user needs to know nothing about programming to build a front end to a voice-activated application with this method. The user interface infrastructure is quite complex, requiring the use of recursion in building grammars, putting together dialogs, etc. However, the code should be fairly compact and easy to maintain. The alternative, coding each dialog separately, would greatly expand the code, would most likely duplicate much of the common functionality several times, and would require generating grammars by hand. Included in the design of the infrastructure is the design of the dialog database. The database structure is tightly coupled to the infrastructure and thus needs to be defined in order to build a meaningful control flow. The design document is written to include all functionality that may potentially be implemented during the course of this project. Some of the features, however, will not be implemented unless time allows (see the requirements document). The system should be implemented in such a way that the architecture remains open to these features even if they are not implemented at the current time. It is also important to note that many of the requirements are not met by the user interface infrastructure alone. The infrastructure provides all of the functionality to meet the requirements it refers to. However, if the dialogs themselves are not designed to take advantage of this functionality, some requirements may still not be met. The purpose of the user interface infrastructure is to take input from three sourcesa human user, the dialog database, and the Sports Scores server, and to make the three interact in a meaningful way. More specifically, it must read information from the database defining the interface to be presented to the human user. It must present the information to the user and accept responses. When the user has completed a query, the query must be sent to the server. A result is read from the server and read to the user. The process then begins again. The following components will be implemented in the user interface infrastructure to achieve its functionality. A database initialization routine will be implemented to load the user dialogs at the start of the application. This routine will not only need to open the database and set it up to be accessed, but will need to verify that the database has not been updated since the last time all grammars were built. Grammars are used by the Microsoft SAPI voice-recognition interface to determine what the user is expected to say. At each prompt in the system, the application will need to know this information. If the database has been updated since the last build, the grammars will need to be updated to reflect this change. A client communications initialization routine will be implemented to establish communications with the server. Its only other responsibility is to inform the user if the server is unavailable and to exit the program if this is the case. 7.3., 7.4., 7.6., 7.7. A routine will be implemented to establish the topmost flow control. This will call all initialization functions, will present the user with a task objective if testing is active, will load up the first prompt, and will set user interaction in motion. When the user has completed a set of prompts, the routine will send a query to the server and read the response to the user. If in testing mode, the routine will then offer the user a series of questions about the task performed and will log the responses. The next task will then be loaded and the process will begin again. If the user is not in testing mode, the routine will act in the same manner, only it will allow the user to perform any allowable task until the user decides to exit the system. A subsystem will be implemented to present any necessary prompts to the user and compile the responses into a query string. This is the most intricate portion of the system and will need to be implemented through a series of recursive calls. A screen will need to be put together that acts as a questionnaire for the user to fill out after accomplishing all tests (if in testing mode). This will simply be a data entry screen and will store the results in a file for future reference. All testing design has been included to help establish that usability requirements have been met. 8 - Dialog Database The dialog database structure is as follows: TableFieldTypeLengthDescriptionCommandKeyLong IntegerUnique Identifier (primary key)GlobalBooleanYes if the command is globally available, no if for use in a promptPrompt IDLong IntegerThe prompt that this command is associated with (if not global)Spoken TextString50What the user should say to access this commandEnumeratedBooleanWhether or not this command is to be enumerated during the help (when commands are read to users)Return ValueString50The value to be associated with the prompt parameterwhen this command is selectedActionLong IntegerThe action to be taken when this command is selected. See design document for more infoCall IDLong IntegerThe prompt or script ID to call if the action indicates we must call oneEnabledBooleanWhether or not this command is enabledHelp TextKeyLong IntegerUnique Identifier (primary key)Prompt IDLong IntegerThe number of the prompt ID with which this is associatedUser LevelLong IntegerThe user level at which this text is readHits Before EscalationLong IntegerThe number of times a user can visit this prompt before they should move to the next help levelTextStringMemoThe number of times a user can visit this prompt before they should move to the next help levelGlobalBooleanWhether or not this help text is globally availableRead All CommandsBooleanWhether or not we read all of the commands available at this prompt.MacroKeyLong IntegerUnique Identifier (primary key)TextString50The text the user will say to access this macroQuery StringStringMemoThe string that will be sent to the server to perform the queryPromptKeyLong IntegerUnique Identifier (primary key)Prompt IDLong IntegerA unique identifier that is referenced by its detail tables.NameString100The (relatively) short prompt name for reference purposesDescriptionStringMemoA longer description of the prompt and what it representsGrammarStringMemoThe grammar to be used when this prompt is called upParameterString50The name of the parameter that gets assigned a value for this promptTestBooleanWhether or not this is a prompt to be used in test mode after a query is completedPrompt TextKeyLong IntegerUnique Identifier (primary key)Prompt IDLong IntegerThe prompt to which this text belongs.User LevelLong IntegerThe user level at which this text is readHits Before EscalationLong IntegerThe number of times a user can visit this prompt before they should move to the next text levelTextStringMemoThe text to be read to the userResponse ComponentKeyLong IntegerUnique Identifier (primary key)Response IDLong IntegerThe response definition to which this component belongsOrderLong IntegerThe order in which this part of the response is read (low to high)TextString255The text to be read or the variable to be inputIs VariableBooleanYes if this is a variable name, no if it is literal text to be read.User LevelLong IntegerThe user level at which this response is read.Response CriteriaKeyLong IntegerUnique Identifier (primary key)Response IDLong IntegerThe reference to the response to which it belongsParameterString50The name of the parameterthat this criteria is concerned withValueString50The value of the parameter that is required to meet this criteriaClient GeneratedBooleanTrue if the client created this parameter, false if the server didResponse DefinitionKeyLong IntegerUnique Identifier (primary key)NameString50The description of this particular response definitionResponse IDLong IntegerThe unique identifier of the responseScriptKeyLong IntegerUnique Identifier (primary key)Script IDLong IntegerA unique identifier that will be referenced by script stepsNameString50A short name of the script to be referenced in lookupsDescriptionStringMemoA long description of the scriptScript StepKeyLong IntegerUnique Identifier (primary key)Script IDLong IntegerThe script to which this step belongsPrompt IDLong IntegerThe prompt which this step will callOrderLong IntegerThe order in which this script step occurs in the grammarGrammarStringMemoThe grammar that is loaded when this script step comes upQuery AfterBooleanYes - Query after this step is performed. No - Don't do that.System ParametersKeyLong IntegerUnique Identifier (primary key)Last Grammar BuildDate/TimeThe last date and time that the grammar was builtLast ModificationDate/TimeThe last date and time that the prompt structure was modifiedFirst Prompt IDLong IntegerThe prompt that is the first to be calledHost NameString255The name of the host where the server residesPort NumberLong IntegerThe port number where the server will be listeningTest CaseKeyLong IntegerUnique Identifier (primary key)Preceding TextStringMemoThe text to be read to the user before the user is allowed to query the systemSuccess TextStringMemoThe text to be read to the user if he or she meets the test objectiveFailure TextStringMemoThe text to be read to the user if he or she does not meet the test objectiveExpected User ResponseStringMemoThe expected query string to come out of the user interaction with the systemExpected Server ResponseStringMemoThe expected response to come back from the server if the query is correctEnabledBooleanWhether or not this test case is enabledOrderLong IntegerThe order in the test case sequence in which this one is used. The dialog will have a structure that supports the following guidelines: 8.1. All tables will contain unique record identifiers as in a normal database structure. 8.2. A table will be created to store prompts. 8.2.1. Each prompt will contain a description and short name to be used for reference in building the prompts. 8.2.2. Each prompt will store a parameter with which it is associated. When a user visits the prompt and a value is returned, this is the parameter the value will be associated with. It will be sent to the server as part of the query string. Each prompt will contain the base prompt grammar, or the grammar that the prompt will accept if it is not called from a script. Each prompt will contain a flag indicating whether or not it is a debug prompt (to be read when a task is completed in testing mode) 8.3. A table will be created to store commands. 8.3.1. Each command will point to the prompt to which it belongs or will contain some information indicating it is a global command. (CF2.6.5.1) (CF2.6.5.2) 8.3.2. Each command will contain the text that will be accepted from the user. 8.3.3. Each command will contain a logical flag that will indicate whether this command is to be enumerated during help. That is, if the user asks for help and the help menu reads options to the user, the flag will determine whether this command is among those options. Each option will be given a number so that the user can say the number rather than the option text. The motivation behind only enumerating some of the commands is so that different pronunciations or representations of the commands can be entered without the computer reading all of the synonymous options to the user during help. (CF2.6.2.1) (CF2.6.2.2) (CF2.6.4) 8.3.4. Each command will contain a return value to be associated with its prompt parameter value. 8.3.5. Each command will contain a code to indicate the action to take when the computer recognizes the command. The action may be to return a value, to call another prompt, to call a script, etc. It may also indicate a change in system behavior or a navigational command. 8.3.6. Each command will contain the ID of a script or prompt to call, if the action referred to in 8.3.5. is to call either of these functions. 8.3.7. Each command will contain a flag to indicate whether or not the command is enabled. This will allow dialogs to be built ahead of time for functionality that may be implemented in the future. Disabling it will make it invisible to the system. 8.4. A table will be created to store prompt text entries. 8.4.1. Each prompt text record will contain a pointer to the prompt with which it is associated. 8.4.2. Each prompt text record will contain the user level at which this text is read. 8.4.3. Each prompt text record will contain the text to be read to the user by the computer. (CF2.6.1.1) 8.4.4. Each prompt text record will contain the number of visits required to this prompt text level before the user is elevated to the next level. This will be used along with the system user level to determine which prompt level the user hears. This is included because the user may be a low-level user but may visit the same prompt many times. After visiting the prompt a certain number of times, he or she may no longer need to hear all of the text of the low level prompt texts. 8.5. A table will be created to store help text entries. 8.5.1. Each help text entry will contain a pointer to the prompt with which it is associated. 8.5.2. Each help text entry will contain the text to be read to the user. (CF2.4.1) 8.5.3. Each help text entry will contain the user level for which this text is read. (CF2.4.2) Each help text entry will contain information to reflect whether or not the help is available globally. Each help text entry will contain the number of hits required before the next lowest help text entry is read. Each help text entry will contain a flag to indicate whether or not the command options are to be read at this help level. 8.6. A table will be created to store scripts. 8.6.1. Each script will contain a short name. 8.6.2. Each script will contain a long description. 8.7. A table will be created to store script steps, or each of the individual tasks performed by a script. 8.7.1. Each script step will contain a reference to the script to which it belongs. 8.7.2. Each script step will contain a reference to the prompt that will be called at this step. 8.7.3. Each script step will contain the grammar for that step. 8.7.4. Each script step will contain information indicating where in script sequence this step occurs. 8.8. A table will be created to store system parameters used to provide preferences for the system. 8.8.1. The system parameter table will have only one record. 8.8.2. The system parameter entry will contain a date and time of last database modification. 8.8.3. The system parameter entry will contain the date and time of last grammar build. 8.8.4. The system parameter entry will contain a reference to the first prompt to be executed by the system. 8.8.5. The system parameter entry will contain the identification of the host containing the server. (CF1.5) 8.8.6. The system parameter entry will contain the port number used to connect to the server. (CF1.5) 8.9. A table will be created to store user-defined macros that can be executed in the system.(CF2.6.6.1) 8.9.1. Each macro entry will contain the text that the user can say to execute a macro. 8.9.2. Each macro entry will contain the query string that is to be sent to the server when the macro is executed. This corresponds to the query string that was formed when the user navigated the dialogs when the macro was created. 8.10. A test case table will be created to store the test scenarios the system will run in test mode. 8.10.1. Each test case will contain text to be read to the user before the system starts that will explain the test objective to them. 8.10.2. Each test case will contain the text of the query string that the user will generate if he or she successfully meets the objective. 8.10.3. Each test case will contain the text of the expected response from the server. Each test case will contain a flag to indicate whether or not the test is to be executed. This will allow some test cases to be enabled and disabled quickly as desired. Each test case will contain the text to be read to the user if he or she does not meet the objective. Each test case will contain an order field indicating the order in which they are read (low to high). Each test case will contain the query expected from the user in the scenario. 8.11. A response definition table will be created to store descriptions of each response the computer may read to the user, based on the users query string and the servers returned parameters. Each response definition will have a unique identifier to be used in child tables. Each response definition will have a name to allow a dialog creator to recognize it. A response criteria table will be created to store the necessary criteria for a particular response format to be used. Each record will contain a reference to the response definition record to which it belongs. Each record will contain the name of the parameter, the value of which will be required to determine the format. Each record will contain the value of the parameter of the record that will be required to determine the format. Each record will contain a flag to indicate whether the parameter is a server-generated or client-generated parameter. 8.13. A response text component table will be created to define a portion of the response to be read to the user. Each record will contain a reference to the response definition to which it belongs. Each record will contain an order field to indicate where in the sequence of the response that it is read. Each record will contain a text field to be used as a variable name or as literal text to be read to the user. Each record will contain a flag to indicate whether it is to be read to the user or to be interpreted as a variable. Each record will contain a user level, describing the user level for which it is a component. 9 - SSDB (Sports Score Database) 10 - Dialog Generation Utility  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC14" Policies and Tactics This design was attempted to be made as modular as possible. This provides flexibility between component developments. In design, we attempted to partition the development into sections that each individual could create independent of another, and have a clearly defined interface between components. This would make compilation of the client and server applications trivial. For example, the communications components work together, and are nearly independent of the data that they are transferring. With a clearly defined interface for the communications components, integration of these components is made simple and painless. This design also took the policy of using coding standards such as standard Java/C++ variable prefixes and caption. Generally method/property purposes are easily deciphered by their descriptive name.  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC15" Detailed System Design 1 - WebViking Classification Modular subsystem of the server. Purpose This class implements the html parser/stripper necessary to derive sports information from the Internet. This class is used as part of the server application. Uses/Interactions This module is to be used by the server. This subsystem will be invoked when the database is scheduled to be updated. Method WebViking( boolean bDebug, String strSSDBLoc ) Purpose constructor for the web viking. Parameters bDebug boolean indicating if the application has been started with debug on. values true if debug is on, else false. strSSDBLoc String noting the location of the sports score database. Method pillage( serverGUI ServerGUI ) Purpose Invokes the beginning of web page pillaging and sports score database updating. Parameters ServerGUI Pointer to the currently allocated serverGUI object. Provides an interface to output logging information. 2 - SSDB (Sports Score Database) Interface Classification Modular subsystem of the server. Purpose This subsystem is designed to provide an interface to both insert sports information into the sports score database, but also to extract it in a formatted fashion. Uses/Interactions This sybsystem will be used by the web viking to insert sports score information into the sports score database. This subsystem will also be used by the server to request sports information from the sports score database. Method SSDB( boolean bDebug, SSDB ssdbLoc ) Purpose Constructor for the serverGUI object. Parameters ssdbLoc String indicating the location of the sports score database. bDebug boolean indicating if the application has been started with debug on. values true if debug is on, else false. return value None Method String clientInfoRequest( String strClientRequest ) Purpose Method to provide a client the requested information from the server in a readable fashion. Parameters strClientRequest String indicating a client request for sports data. Values string formatted to the grammar defined by the hierarchical structure of the user dialog. Return value String formatted for the text-to-speech synthesizer to read to the client. If the requested information is not found, an appropriate phrase is returned to the client. If the request is incorrectly formatted, an appropriate phrase is returned to the client. Method boolean updateGame( date dteGameDate, String strTeam1, String strTeam2, int iScore1, int iScore2, int iHits1, int iHits2, int iErr1, int iErr2, String strComment ) Purpose Method to insert/update specific game information into the sports score database. Parameters dteGameDate Date indicating the games date. strTeam1 String indicating a team in the game. strTeam2 String indicating the other team in the game. iScore1 Score of team one. iScore2 Score of team two. iHits1 Number of hits by team one. iHits2 Number of hits by team two. iErr1 Number of errors by team one. iErr2 Number of errors by team two. strComment String indicating any commentary of the game. Return value true if the database update was successful, else false. Method boolean updateSchedule( date dteGameDate, String strTeam1, String strTeam2, time tmeGameTime ) Purpose Logs a scheduled game into the sports score database. Parameters dteGameDate Date of the scheduled game. strTeam1 Name of a team in the game. strTeam2 Name of the other team in the game. tmeGameTime Time that the game is scheduled to begin Return value true if the database update was successful, else false. Method boolean updateStandings( String strTeam, int iWins, int iLosses ) Purpose Updates a given teams winning and losing record. Parameters strTeam Team to be updated in the sports score database. iWins Teams game win count. iLosses Teams game loss count. Return value true if the database update was successful, else false. 3 Server Component Classification Modular subsystem of the server. Purpose This class implements any graphical interactions necessary for the user. Uses/Interactions WebViking and serverComm subsystems of the server will interact with this module. This is necessary to log any information pertinent on the server. Methods serverGUI( boolean bDebug, SSDB ssdbLoc ) Purpose Constructor for the serverGUI object. Parameters ssdbLoc String indicating the location of the sports score database. bDebug boolean indicating if the application has been started with debug on. values true if debug is on, else false. return value None 5 serverComm (Server Communications) Classification Modular subsystem of the server Purpose This class implements the server side network communications necessary for the sports score system. This network communications layer uses the TCP protocol as its transport. Uses/Interactions This is used by the server system. Methods serverComm( boolean bDebug ) Purpose Constructor for the serverComm object. Parameters bDebug boolean indicating if the application has been started with debug on. values true if debug is on, else false. Return value None 6 clientComm (Client Communications) Classification Modular subsystem of the client. Purpose This class implements the client side network communications necessary for the sports score system. This network communications layer uses the TCP protocol as its transport. Uses/Interactions Methods clientComm( boolean bDebug ) Purpose Constructor for the ClientComm object. Parameters bDebug boolean indicating if the application has been started with debug on. Values true if debug is on, else false. Return value None Method connect( strServerName, iServerPort ) Purpose Opens a port on the client, and creates a connection to a specified server and port. Parameters strServerName string indicating the name of the sports score server. May be either an IP address, or DNS name. iServerPort integer representing the port that the sports score server listens for clients on. Return value true if the connection to the server succeeded, else false. Method disconnect( ) Purpose Disconnects the sports score client from the sports score server. Parameters None Return value true if disconnect succeeded, else false. Assumptions In the case that the client is not connected, this method will return true indicating that the client is disconnected. Method read( ) Purpose This method is designed to retrieve data sent to the sports score client from the sports score server. Parameters None Return value A string of data transferred from the sports score server in a response to the client initiating an information request. Assumptions This method assumes that data coming from the sports score server is purely textual. Exceptions Thrown ServerMIAException This exception is thrown in the case that more time has ellapsed than an acceptable response time from the server, or the sports score server has not responded to a PING, or the data received from the server is incomplete. Method write( strOutput ) Purpose Parameters Exceptions Thrown ServerMIAException This exception is thrown in the case that more time has ellapsed than acceptable, or the sports score server has not responded to a PING. 7 - Client Component 8 - Dialog Database  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC16" Detailed Subsystem Design 1 - Web Viking 1.1 - The schedule program Program name: schedule.pl Input: None Output: a file contains schedule information of the MLB Procedure: For each month from the April to October do the following: Create a link where the link is the url of the web site that contains the schedule of that month Use that url to open a connection between client and server Use CPAN the library function, Request, to get data from the server. If we get the data successfully Call the subroutine to parse data Otherwise, Call the error handling subroutine. Parse schedule subroutine Split the data getting from the server into lines Store each line in an element of an array Create a file, schedule.txt, to append under the directory data For each element (line) of the array do the following: Check if the line contains a date. If so, parse the line to get the date, format the data in the form, Date|the actual date, and write to file. Check if the line contains a schedule. If so, parse the line to get schedule, format the data in the form, teamName|teamName|time, and write to file. Close file Log error subroutine Create a file, schedule.err, to append under the directory logerr Write to file explanations why the program failed Close file 1.2 - The score program Program name: scores.pl Input: dates of the day we want the result Output: a file contains baseball scores of the MLB Procedure: Check the arguments. If the arguments are missing, log errors For each argument, a given date, create a filename (e.g. sco0506.txt) Create a link where the link is the url of the web site that contains the scores of the given date. Use that url to open a connection between client and server Use CPAN the library function, Request, to get data from the server. If we get the data successfully Call the subroutine to parse data from MLB site Otherwise, Call the subroutine to parse data from the ESPN site Parse scores subroutine Split the data getting from the server into lines Store each line in an element of an array For each element (line) of the array do the following: Check if the line contains a date. If so, parse the line to get the date, format the data in the form, Date|the actual date, and write to file. For each game find the lines contain information about the first team name, the number of runs, homes, errors of the first team. Do the same thing with the second team. To find the lines contain this information, study the html file that we retrieved, Find the patterns to search. Combine these data together with the | in between. Check if we get the right data. If so, write to file that we created. Otherwise, write to the error file. If its the first time we encounter an error, create a file named scores.err. If its not the first time we encounter the problem, append error messages to the file scores.err and close error file. Close file Parse data from the ESPN site: well do the same as we do to get data from the MLB site. But, the url is the address of the ESPN web site. In addition, if this subroutine is failed the program will fail. 11.3 The standing program Program name: standing.pl Input: None Output: a file contains baseball standing of the MLB Procedure: For each argument, a given date, create a filename (e.g. standing.txt) Create a link where the link is the url of the web site that contains the current standing. Use that url to open a connection between client and server Use CPAN the library function, Request, to get data from the server. If we get the data successfully Call the subroutine to parse data from MLB site Otherwise, Call the subroutine to parse data from the ESPN site Parse scores subroutine Split the data getting from the server into lines Store each line in an element of an array For each element (line) of the array do the following: Check if the line contains a date. If so, parse the line to get the date, format the data in the form, Date|the actual date, and write to file. For each league find the top three teams For each team find the number of win and lost To find the lines contain this information, study the html file that we retrieved, Find the patterns to search. Combine these data together with the | in between. Check if we get the right data. If so, write to file that we created. Otherwise, write to the error file. If its the first time we encounter an error, create a file named standing.err. If its not the first time we encounter the problem, append error messages to the file standing.err and close error file. Close file Parse data from the ESPN site: well do the same as we do to get data from the MLB site. But, the url is the address of the ESPN web site. In addition, if this subroutine is failed the program will fail. Interface/Exports The interfaces are output files from the Web Viking program. The DI will use these files as its input. There will be 3 files, scores.txt, standing.txt, and schedule.txt. Format of the file scores.txt: Date (e.g. May 12 , 2000) Team1|#Run|#Home|#Error|Team2|#Run|#Home|#Error (e.g. Chi Cubs|3|7|3|Montreal|8|10|0) Team1|#Run|#Home|#Error|Team2|#Run|#Home|#Error Team1|#Run|#Home|#Error|Team2|#Run|#Home|#Error Format of the file schedule.txt Date|date (e.g. Date|Sunday, April 30) Team1|Team2|time (e.g. Boston|Cleveland|1:05 PM) Team3|Team4|time Date|date Team1|Team2|time Team3|Team4|time TeamN-1|TeamN|time Format of the file standing.txt League|ALE Team1|W|L Team2|W|L Team3|W|L Team4|W|L Team5|W|L League|ALC Team1|W|L Team2|W|L Team3|W|L Team4|W|L Team5|W|L League|ALW Team1|W|L Team2|W|L Team3|W|L Team4|W|L Team names are Anaheim Angels, Angles, Anaheim, Arizona, Arizona Diamondbacks, Diamondbacks, Atlanta, Braves, Atlanta Braves, Orioles, Baltimore, Baltimore Orioles, Chicago, Chi Cubs, Chicago Cubs, Cubs, Chi White Sox, Chicago White Sox, Chicago, White Sox, Chi W Sox, Chicago W Sox, Reds, Cincinnati Reds, Cincinnati, Indians, Cleveland, Cleveland Indians, Rockies, Colorado, Colorado Rockies, Detroit Tigers, Tigers, Detroit, Florida Marlins, Marlins, Florida, Houston Astros, Houston, Astros, Kansas City Royals, Kan City, Kansas City, Royas, Los Angeles Dodgers, Los Angeles, Dodgers, LA, Brewers, Milwaukee, Milwaukee Brewers, Twins, Minnesota, Minnesota Twins, Expos, Montreal, Montreal Expos, New York Mets, NY Mets, New York, Mets, Yankees, New York Yankees, NY Yankees, New York, Oakland, Oakland Athletics, A's, Athletics, Philadelphia Phillies, Philly, Philadelphia, Pittsburgh Pirates, Pittsburgh, Pirates, San Diego Padres, Padres, San Diego, Giants, San Francisco, San Fran, San Francisco Giants, Seattle, Seattle Mariners, Marines, St. Louis, St. Louis Browns, Browns, Devil Rays, Tampa Bay Devil Rays, Tampa Bay, Texas, Texas Rangers, Rangers, Toronto, Blue Jays, Toronto Blue Jays, Boston, Boston Red Sox, and Red Sox. 2 - SSDB (Sports Score Database) Interface Classification Class Definition It's a class that will handle the database Responsibilities This class will act as a container for the database handler. Constraints None Uses/Interactions This class will be used to by the server Resources This class will utilize the sport score database. Processing See the description of each method. Interface/Exports SSDB(); //a constructor which will initialize the Database Drive Public int getStanding(String filename); Public int getSchedule(String filename); Public int getScore(String fileName); private int fileSetup(String fname) private int monthStringToMonthInt(String m) private String convertStringDateToIntDate (int d) private int today() private int yesterday() private void getScoreForAnyDate(String date) private void getScoreForATeam(String team) private void getRank(String division) private void getScheduleForLeague(String division) private public void getScheduleForATeam(String team) public String UserInfoRequest(String strQuery) SSDB() Classification Method Definition Name: SSDB Input: None Output: None Responsibilities This routine will be responsible for initializing database drive when an object of this class is created Constraints None. Uses/Interactions Will be called automatically when an object of this class is created Resources Database drive name Database file name Processing SSDB() { Initialize the database drive } Interface/Exports None. string UserInfoRequest (string) Classification Method Definition Name: clientInfoRequest Input: string Output: string Responsibilities This routine will accept the input string as a paremeter, then it will parse the string into apropriate format. Then, it will execute SQL from the string to get a desired result which will be formated then send back to server. Constraints None. Uses/Interactions Will be called by the server Resources Require the input string and the database to do the query Processing String UserInfoRequest(String X) { xmlQuery=new ServerXML(); xmlResults=new ServerXML(); UI_Node_Wrapper nodQuery; nodQuery = xmlQuery.getDocument(strQuery); // use nodQuery.getParameterValue(strParameterName) to get the value of any parameter. String strResult = nodQuery.getParameterValue("FUNCTION"); if (strResult.equals("SCORE")){ String strTeam = nodQuery.getParameterValue("TEAM"); if(strTeam.equals("DAY")) getScoreForAnyDate(nodQuery.getParameterValue("DAY")); else getScoreForATeam(strTeam); } else if(strResult.equals("RANK")) { getRank(nodQuery.getParameterValue("GROUP")); } else if(strResult.equals("SCHEDULE")) { String tmp=nodQuery.getParameterValue("TEAMLEAGUE"); if(tmp.equals("LEAGUENAME")) getScheduleForLeague(nodQuery.getParameterValue("LEAGUENAME")); else getScheduleForATeam(tmp); } else ;//debug "Unregconize FUNCTION name="strResult" in function x return xmlResults.getResultString(); } Interface/Exports None. void update() Classification Method Definition This is the update routine. Input: None Output: None Responsibilities This routine opens a file which was created by the Webviking and read the infon line by line as well as concurrently update the database. Constraints None. Uses/Interactions Will be called by the server Resources Require a text file to read and a database to update or store info Processing void update() { getSchedule(schedule.txt); getScore(score.txt); getStanding(standing.txt); } Interface/Exports None. void fileSetup(String) Classification Method Definition This is the file initialize routine. Input: the name of the file (String ) Output: a file pointer Responsibilities This routine opens a file which was created by the Webviking Constraints None. Uses/Interactions Will be called by the update() function Resources Require a text file to read and a database to update or store information Processing Void fileSetup(String) { Open the file using the paremeter Set up the pointer to point to the file } Interface/Exports None. void getSchedule(String) Classification Method Definition This is getSchedule routine Input: a file name Output: None Responsibilities This routine opens a file which was created by the Webviking (schedule.txt) and read in the date/time and teams to insert into schedule table of the database. Constraints None. Uses/Interactions Will be called by the update() function Resources Schedule.txt file A database with a table schedule Processing Void getSchedule(String fname) { FileSetup(fname); While not end of the file { Read in the data line by line Update the database (table schedule is used) } } Interface/Exports None. void getScore(String) Classification Method Definition This is the getScore routine. Input: a file name (string) Output: None Responsibilities This routine opens a file which was created by the Webviking (score.txt) and read in the scores and the team associated with that score then insert into the score table of the database. Constraints None. Uses/Interactions Will be called by the update() function Resources Score.txt file A database with the table score Processing Void getScore(String fname) { FileSetup(fname); While not end of the file { Read in the data line by line Update the database (table score is used) } } Interface/Exports None. void getStanding(String) Classification Method Definition This is the getStanding routine. Input: a file name (string) Output: None Responsibilities This routine opens a file which was created by the Webviking (standing.txt) and read in the win and looses score and the team associated with that score then insert into the standing table of the database. Constraints None. Uses/Interactions Will be called by the update() function Resources Standing.txt file A database with the standing table Processing Void getStanding(String fname) { FileSetup(fname); While not end of the file { Read in the data line by line Update the database (table standing is used) } } Interface/Exports None. private int monthStringToMonthInt(String m) Classification Method Definition Name: monthStringToMonthInt Input: a string Output: an integer Responsibilities This routine will parse and convert a month in a string format to an integer format Constraints None. Uses/Interactions Is private, will be call by member function of SSDB class Resources Require the input string Processing private int monthStringToMonthInt(String m){ process input string m return the month in an integer format } } Interface/Exports None. private String convertStringDateToIntDate (int d) Classification Method Definition Name: convertStringDateToIntDate Input: an integer Output: a string Responsibilities This routine will parser and convert a date in integer format to a string format. Constraints None. Uses/Interactions Is private, will be called by the member method of SSDB class Resources Require an integer input Processing private String convertStringDateToIntDate (int d){ parse the integer d return the result string } Interface/Exports None. private int today() Classification Method Definition Name: today Input: None Output: an integer Responsibilities This routine will find out what the current day and convert that date object into integer format (Y:MM:DD) Constraints None. Uses/Interactions Is private, will be called by member methods of SSDB class Resources None Processing private int today() { find out what today is return the date in integer format (Y:MM:DD) } Interface/Exports None. private int yesterday() Classification Method Definition Name: yesterday Input: None Output: a day in an integer format (Y:MM:DD) Responsibilities This routine will find out what date is yesterday Constraints None. Uses/Interactions Is private, will be called by member methods of SSDB class Resources Require function today(); Processing private int yesterday(){ call today() function minus 1 return the date } Interface/Exports None. private void getScoreForAnyDate(String date) Classification Method Definition Name: getScoreForAnyDate Input: a string Output: a string to XmlServer Responsibilities This routine will get a string date and find out all the scores for every teams that plays according to the date variable Constraints None Uses/Interactions Will be called by the member method getUserInfoRequest(String) Resources Require the input string and the database to do the query Processing private void getScoreForAnyDate(String date){ query the database put each record (recordset) in the xml server } Interface/Exports None. private void getScoreForATeam(String team) Classification Method Definition Name: getScoreForATeam Input: a string Output: a string to xmlServer Responsibilities This routine will query the database to get the score for a given team according to today( Y:MM:DD) Constraints None. Uses/Interactions Will be called by the member method getUserInfoRequest(String) Resources Require the input string and the database to do the query Processing private void getScoreForATeam(String team) { query the database put each record (recordset) in the xml server } Interface/Exports None. private void getRank(String division) Classification Method Definition Name: getRank Input: a string (ALW, ALC, ALE, NLW, NLC, NLW) Output: a string to xmlServer Responsibilities This routine will get the top 3 teams standing according to the input division Constraints None. Uses/Interactions Will be called by the member method getUserInfoRequest(String) Resources Require the input string and the database to do the query Processing private void getRank(String division) { query the database; put each record (recordset) in the xml server } Interface/Exports None. private void getScheduleForLeague(String division) Classification Method Definition Name: getScheduleForLeague Input: a string Output: a string Responsibilities This routine will get the schedule for a league Constraints None. Uses/Interactions Will be called by the member method getUserInfoRequest(String) Resources Require the input string and the database to do the query Processing private void getScheduleForLeague(String division) { query the database return the result string to the server } Interface/Exports None. private public void getScheduleForATeam(String team) Classification Method Definition Name: getScheduleForATeam Input: a string Output: a string Responsibilities This routine will. Constraints None. Uses/Interactions Will be called by the member method getUserInfoRequest(String) Resources Require the input string and the database to do the query Processing private public void getScheduleForATeam(String team) { parse string team execute SQL queries from string team get the result return the result string to the server } Interface/Exports None. 3 - Server Component/Server GUI (Graphical User Interface) 4 N/A 5 - serverComm Classification Class Definition This is the interface class used by the server application. Responsibilities This class is responsible for setup of sockets, interfacing between the server and the client. Constraints None Uses/Interactions Resources This class will consume a TCP port for each client. Processing All processing will take place through threads used by this class. (serverCommThread and serverClientThread). Interface/Exports openSocket, getPort, getClientCount, die boolean openSocket( int liPortNum ) Classification Method Definition This method is used to open the server socket to host clients. Responsibilities This class will open a serverSocket to host a specified number of clients. Constraints The expected server port must not be in use before calling this method. Uses/Interactions Resources This class will consume a TCP port for the server to listen on, and one socket for each client. Processing This method will open a serverCommThread which will spin on a port listening for client connection requests. Each client will be processed through serverClientThread. Interface/Exports int liPortNum port to attempt to start the serverSocket listening on. int getPort() Classification Method Definition This method returns the port the server is listening on. Responsibilities None. Constraints The expected server port must be connected before this is called. Uses/Interactions Resources None Processing This method will return the port the server is currently listening on. It will return 0 otherwise. Interface/Exports None int getClientCount() Classification Method Definition This method returns the current count of clients connected to the server. Responsibilities None. Constraints None Uses/Interactions Resources None Processing This method will return the current number of clients connected (via vector of serverClientThreads). Interface/Exports None void die() Classification Method Definition This method initiates shutdown of server communications. Responsibilities None. Constraints None Uses/Interactions Resources None Processing This method will inform the serverCommThread associated with this to terminate. Interface/Exports None 5.2 - serverCommThread Classification Class Definition This class (and classes/Threads it uses) does most of the work associated with clients. Responsibilities This class is responsible for listening on the serverSocket for clients to connect to. When a client attempts to connect, the serverCommThread spins off a new serverClientThread associated with the new client. This class is also responsible for maintaining a count of clients connected. Constraints None Uses/Interactions Resources This class will consume a TCP port for each client. Processing All processing will take place through threads used by this class. (serverCommThread and serverClientThread). Interface/Exports getPort, newClient, run int getPort() Classification Method Definition This class returns the port the server is listening on. Responsibilities Constraints None Uses/Interactions Resources None Processing Interface/Exports Returns the port the server is listening on. If the server is not listening on a port, this returns 0. boolean newClient( Socket clientSocket ) Classification Method Definition This method is responsible for starting a new serverClientThread to maintain the newly connected client. Responsibilities Issues a new serverClientThread to deal with client io. Also adds the newly created serverClientThread to a vector for access to all client threads. Constraints None Uses/Interactions Resources None Processing Interface/Exports clientSocket new socket associated with the newly connected client. Returns true always. void run() Classification Method Definition This method executes the body of the serverCommThread. Responsibilities This method is responsible for looping while the serverSocket is open accepting clients. This method continually checks the vector of serverClientThreads to check for termination of threads. This is also a requirement to keep a client count. Constraints None Uses/Interactions Resources This method is responsible for the serverSocket. Processing This thread is terminated by the die() method. Interface/Exports 5.3 - serverClientThread Classification Class Definition This is the interface class used by the server application. Responsibilities This class is responsible for setup of sockets, interfacing between the server and the client. Constraints None Uses/Interactions Resources This class will consume a TCP port for each client. Processing All processing will take place through threads used by this class. (serverCommThread and serverClientThread). Interface/Exports getPort, newClient, run 6 - clientComm Classification Class Definition This is the interface class used by the server application. Responsibilities This class is responsible for setup of sockets, interfacing between the server and the client. Constraints None Uses/Interactions Resources This class will consume a TCP port for each client. Processing All processing will take place through threads used by this class. (serverCommThread and serverClientThread). Interface/Exports getPort, newClient, run String packetize( String cHeader, String cEndOfString, String strData ) Classification Method Definition This method is used to packetize user data to be transported to the server. Responsibilities This method is responsible for packetizing user data to be used by the server. Constraints None Uses/Interactions Resources None Processing All processing will take place through threads used by this class. (serverCommThread and serverClientThread). Interface/Exports String depacketize( String strPacket ) Classification Method Definition This method is used to depacketize user data received from the server. Responsibilities This method is responsible for removing packetizing characters encapsulating the user data from the server. Constraints None Uses/Interactions Calling this method will cause the first and last characters to be stripped on the string. Resources None Processing Interface/Exports boolean disconnect() Classification Method Definition Disconnects the client from the server. Responsibilities Responsible for disconnecting an existing TCP connection to a sports score server. Constraints None Uses/Interactions Calling this method will terminate a TCP connection between the client and server. If no connection exists, a true is returned anyways. Resources None Processing Interface/Exports boolean connect(String strServerName, int iPort ) Classification Method Definition This method is used to connect to a sports score server. Responsibilities This method is responsible for opening a TCP connection to the specified server and port. Constraints None Uses/Interactions Calling this method attempts a connection to a sports score server. Resources This class will consume a TCP port for each client. Processing All processing will take place through threads used by this class. (serverCommThread and serverClientThread). Interface/Exports Socket openSocket( String strAddr, int iPort ) Classification Method Definition This method is used to open a socket with the sports score server. Responsibilities This method is responsible for opening a TCP connection to the specified server and port. Constraints None Uses/Interactions Calling this method attempts to open a connection to a sports score server. Resources This class will consume a TCP port. Processing None. Interface/Exports This method is used by connect(). Upon failure to open a socket, this method returns a null. String read() Classification Method Definition This method is used to read a line of data from the server. Responsibilities This method is responsible for reading a line (CR terminating) of data from the server. Constraints Must be connected to a sports score server. Uses/Interactions Calling this method attempts to open a connection to a sports score server. Resources This class will consume a TCP port. Processing None. Interface/Exports This method is used by connect(). Upon failure to open a socket, this method returns a null. void write( String sOut ) Classification Method Definition This method is used to write a line of data to the server. Responsibilities This method is responsible for sending a line of data to the sports score server. Generally this line of data will be a data request in the form of xml. Constraints Must be connected to a sports score server. Uses/Interactions Calling this method attempts to send a line (CR terminated) of data to the sports score server. Resources This class will consume network bandwidth. Processing None. Interface/Exports None. 7 - Client Component User_Interface Classification Class Definition This is the container for the user interface. This class controls all processing. Responsibilities As the class that controls all flow control, it must also declare any data structures that are required within the system. Constraints Only one instance of this class should exist at any time, as it is the application. Uses/Interactions No external components refer to User_Interface directly. It makes use of the Client_Communications class, calling the methods connect(), disconnect(), read(), and write(). It also makes use of the UI_Tester Object and its Start_Test(), End_Test() and Present_Questionnaire() routines. It also makes use of the UI_Dialogs() class and its Build_Grammars() routine, as well as its Present_Prompt() routine. Resources This class requires the existence of the dialog database and of the classes referred to in the Uses and Interactions section. Processing All processing will take place through the main() method of this class. Interface/Exports Int main(int argc, String argv) public UI_User clsUser; //Contains the user definition class. This is visible throughout the //program and is used for variables such as use level. void User_Interface::main(int argc, String argv) Classification Method Definition This is the main function for the user interface infrastructure. It is what initializes and controls the flow of the application. Responsibilities This routine must initialize variables and present the user with the various prompts, interacting with the client communications and the database, as well. It must also parse out anything brought in on the command line to determine whether to put the system into test mode. Constraints None. Uses/Interactions No external components refer to User_Interface::main() directly. It will be called when the application begins due to naming conventions. Resources This class requires the existence of the dialog database and of the classes referred to in the Uses and Interactions section. Processing The main() function should follow roughly these steps: { Determine Whether We Are In Debug Mode (from the command-line) Create A UI_Dialogs Structure (which will initialize the database send in a database location) Create a UI_Response_Formulator Object Call the Client Communications Connect() method. If (test_mode) { Create the UI_Tester object. } do while (User hasnt quit) { if (test_mode) UI_Tester.Start_Test(); Query_String = UI_Dialogs.First_Prompt().Present(); If (User hasnt quit) { Client_Communications.write(Query_String); Client_Communications.read(strServerResponse); Response_String = UI_Response_Formulator.getResponse( Query_String, strServerResponse); Read Response_String to user. If (test_mode) UI_Tester.End_Test(Query_String, Response_String); } } Client_Communications.disconnect(); if (test_mode) UI_Tester.Present_Questionnaire(); } Interface/Exports When the user interface calls upon the client communications to send a query string to the server, the query string should be in the following format: = = = Each parameter/value pair is to be separated by a carriage return (character 13). This will be the format in which parameters are accumulated as the dialogs execute. The order is not significant. When the user interface receives a response back from client communications, the response should be in the same format. The parameters received from the server will not necessarily be identical, but they must follow the same format. UI_Dialogs Classification Class Definition This consists of an array of UI_Dialog_Components. It acts as a container and allows prompts, scripts, and script steps to be accessed by ID. Responsibilities This class will act as a container for the dialog components. It needs to provide access to any prompt, script, or script step through a simple interface. It also needs to be the starting point for grammar building as well as application dialog interaction. Constraints The class will contain a data structure containing every prompt, script, and script step in it. They will be stored in an array and referenced by a long integer. Therefore, the sum of the number of prompts, scripts, and script steps cannot exceed the maximum length of a long integer. Uses/Interactions This class is referenced by User_Interface and uses UI_Prompt, UI_Script, UI_Script_Step, and UI_Dialog_Component. It will also be referenced by each of the latter four classes. Resources This class will utilize the dialog database in the building of dialog components and their grammars. Processing See the description of each method. Interface/Exports UI_Dialogs(String DBLocation); // Just call refresh grammars to get it all set up. public void Refresh_Dialogs(String DBLocation) public UI_Prompt First_Prompt(); // Return the first prompt to be read by the system. public UI_Prompt Prompt(long Prompt_ID); // Return the prompt object corresponding to the ID public UI_Script Script(long Script_ID); // Return the script object corresponding to the ID public UI_Script_Step Script_Step(long Script_Step ID) // Return the script step object //corresponding to the ID public UI_Command Globals[]; // Array of all global commands. public UI_Command Macros[]; // Array of all macros. UI_Dialogs.Refresh_Dialogs(String DBLocation) Classification Method Definition This method will cause the dialog array to be completely rebuilt and grammars to be recreated and stored in the appropriate grammar files. Responsibilities This method must destroy any existing dialog structures, rebuild a single structure for each and every script, script step, prompt, command, and help level in the entire dialog database, and rebuild grammars as necessary. Constraints The dialog database must exist in a well-known place (to be passed by the main program). This routine must be able to access the database. Uses/Interactions This method will only be utilized internally by the UI_Dialogs class. It will only be called under two circumstances the start of the application or on the addition of a macro. Resources This class will utilize the dialog database in the building of dialog components and their grammars. Processing The routine must perform the following steps: { Release any currently existing structures (prompts, scripts, etc) Open the dialog database. Compare the date of last build with the date of last update. if (last build < last update) { On each load for a prompt, script, and script ID } Open up the prompt table, script table, and script step table. Initialize an array of UI_Dialog_Components of length of the sum of the record counts of each table. Load up Globals[] array with all global commands in the command table. Load up Macros[] array with all macro commands in the macro table. For each prompt in the prompt table { Set the lowest unused element of the array to a new UI_Prompt with the proper ID If this prompt is the start prompt, remember it as such. } For each script step in the script_step table { Set the lowest unused element of the array to a new UI_Script_Step with the proper ID } For each script step in the script table { Set the lowest unused element of the array to a new UI_Script with the proper ID } First_Prompt.Build(DBNeedsRefreshing); // This will kick off the building of all //prompts, scripts, and script steps that are //used in the system (pass in whether or not //the grammars are to be saved) For each test prompt in the database { that_prompt.build(); } } Interface/Exports None. UI_Tester Classification Class Definition This class acts as an external-testing library. It has a very simple method of access so that it is unobtrusive when called in code. This class helps test the usability requirements defined in CF2.1. Responsibilities The UI_Tester has very few responsibilities. It must initiate a test and evaluate whether or not the user passed. It must also provide for user feedback that is recorded for future reference. Constraints The UI_Tester is only instantiated when the system is in test mode (see the User_Interface::main() routine). Only one copy of this object needs to be created. It makes use of the dialog database, which must be in place. Uses/Interactions This component uses no other components except for the dialog database described in 8.1-8.10. It is used by the User_Interface class. Resources The UI_Tester uses the dialog database. It also will create a text file to store test results in on the system. This text file will be generated with a unique name and will not interfere with any existing files. Processing See UI_Tester::UI_Tester(), UI_Tester::Start_Test(), UI_Tester::End_Test(), UI_Tester::Present_Questionnaire Interface/Exports UI_Tester(String DBLocation); // Initialize the database to start reading tests (gets passed the //file location of the database) public Int Start_Test() public Int End_Test(String strQueryString, String strServerResponse) public Int Present_Questionnaire() UI_Tester::Start_Test() Classification Method Definition This method will begin a test as defined in the dialog database. Responsibilities This routine will find the next test to be executed and will run the test by reading information to the user concerning the objective of the test. Constraints The dialog database must exist in a well-known place (to be passed by the main program). This routine must be able to access the database. Uses/Interactions This method will be utilized from the main() routine of the User_Interface module. Resources This class will utilize the dialog database in determining what test to run and what text to read for that test. Processing The routine must perform the following steps: { if there are no records in the test database { notify the user that a testing error has occurred exit the program } else { Read the text from the current test record to the user. } } Interface/Exports None. UI_Tester::End_Test(String strQueryString, String strServerResponse) Classification Method Definition This method will end a test as defined in the dialog database. Responsibilities This routine will take the query sent to the server as input as well as the response from the server and will log whether or not the query string was as expected and if the server response was as expected. It will then let the user know whether or not they succeeded. If they did not, it will give them the option of starting again. If they did or they do not want to try again, it will read some debug questions to the user regarding the tasks usability and log the results. Constraints The dialog database must exist in a well-known place (to be passed by the main program). This routine must be able to access the database. Uses/Interactions This method will be utilized from the main() routine of the User_Interface module. Resources This class will utilize the dialog database in determining what test to run and what text to read for that test. Processing The routine must perform the following steps: { Compare the user results to the expected user results for the test If (results match) { Log the information in a debug file Log whether or not the server returned the right results in the debug file For each test prompt in the dialog database { .present() log results in debug file } Move to next record If eof() User_quit = true } else { If the user wants to try again { dont do anythingleave record pointer the same. } else { Log the information in a debug file For each test prompt in the dialog database { .present() log results in debug file } Move to next record If eof() User_quit = true } } } Interface/Exports None. UI_Tester::Present_Questionnaire() Classification Method Definition This method will provide a GUI user interface for the user to fill out and will record the results. Responsibilities This will let the user know that the monitor can be turned on (in case it was off before) and will ask them to fill out the questionnaire. It will present a GUI form for the user to fill out and will log the results. Constraints The name of the debug file must be known and it must be able to be opened for write access. Uses/Interactions This method will be utilized from the main() routine of the User_Interface module. Resources This method will utilize the debug file used in all other debug actions. Processing The routine must perform the following steps: { Tell the user to turn the monitor on if it is off. Ask the user to fill out a questionnaire. Present the questionnaire. Wait until the user clicks an Okay button. Log the results in the debug file. } Interface/Exports None. UI_Enum_Command_Functions Classification Enumerated Type Definition Defines a set of functions that can be available when a command is selected from a prompt. Responsibilities This is only a data type that represents functions that may be called when commands are selected. Its only responsibility is to provide this representation. Constraints None. Uses/Interactions This type is used in the UI_Presentable interface. Resources N/A Processing N/A Interface/Exports cmdReturnPromptValue //Dont return this prompt value, return another prompt value. cmdReturnScriptValue //Dont return this prompt value, return a script value. cmdCallPrompt //Call another prompt and return both that value and this prompt value cmdCallScript //Call a script and return both that value and this prompt value cmdPromptThenReturn //Call a prompt, but at the conclusion of the prompt, rerun this prompt. cmdScriptThenReturn //Call a script, but at the conclusion of the script, rerun this script. cmdInvalid //The text that the user said was invalidused to weed out close //matches. cmdBack //Go to the previous prompt cmdRepeat //Read this prompt again cmdStartOver //Go back to the start prompt cmdHelp //Read the user some help cmdMacro //Call a macro (then start over) cmdQuit //Quit the entire program cmdUserLevelAdv //Change the user level to advanced cmdUserLevelNovice //Change the user level to novice cmdUserLevelInt //Change the user level to intermediate cmdRecordMacro //Record the last action as a macro cmdReturnValue //Just return the value recorded with the command cmdReadOptions //Read off all of the possible commands at this prompt UI_Presentable Classification Interface Definition Defines an interface that, when implemented, allows a grammar to be built for this object and the object to be presented. It is created as an interface because different objects require grammars but have different rules for building those grammars. Also, different objects need to be presented to the user but have different rules for being presented. Responsibilities The UI_Presentable interface must provide a standard way of handling grammars and presenting data to the user. It will do nothing on its own; rather, it will be up to the object implementing the interface to handle the code. However, it will provide standard ways of accessing grammars and presentation. Constraints None. Uses/Interactions This interface is implemented by UI_Dialog_Component, UI_Prompt, UI_Script, and UI_Script_Step. It references UI_Dialog_Component in its function calls, as well as UI_Dialogs. It also uses the enumerated type UI_Enum_Command_Functions. Resources None. Processing The interface processes nothing on its own. See the classes that implement it. Interface/Exports private UI_Dialogs Dialog_List; public String Grammar public String GrammarHeader public UI_Dialog_Component arDependencies[] public Int Build_Grammar(Boolean DBNeedsRefreshing) public String Variable_Name public String AssignmentString public Int Present() public UI_Enum_Command_Functions enumLastAction private Boolean Has_Been_Built private aPrompt_Text[] Text_Levels private int Times_Visited UI_Dialog_Component Classification Class Definition This class contains the basis for a prompt, script, or script step. It is abstract and should never be instantiated. It contains information that is necessary for proper handling of the sub-structures. Responsibilities This class is responsible for representing a prompt, script, or script step. It must be able to generate its own grammar and present itself, as well as call any sub-prompts. Since it is abstract, however, much of this functionality will be left up to the individual subclass. Constraints None. Uses/Interactions The dialog component implements the UI_Presentable class. It is never used directly but the UI_Prompt, UI_Script, and UI_Script_Step classes are all based on it. Resources None. Processing See subclasses UI_Prompt, UI_Script, and UI_Script_Step. Interface/Exports private UI_Dialogs Dialog_List; UI_Dialog_Component(Recordset RSTable, int ID, UI_Dialogs); // Just load up the appropriate entry in the appropriate table. Initialize the //Variable_Name, aText_Levels and aHelp_Levels public String Grammar; // The grammar string to be loaded upon presentation. public String GrammarHeader; // The string for the first level of commands available. public UI_Dialog_Component arDependencies[]; // An array containing components that the //current component is dependent upon (and // thus need to be included in the grammar) public Int Build_Grammar(Boolean DBNeedsRefreshing) public String Variable_Name; // When a value is returned, the name of the variable to be //assigned a value. public String Assignment_String; // The string that will be used added to the query string from //this element. public Int Present(UI_Dialogs clsDialogs) public UI_Enum_Command_Functions enumLastAction; // The last action that was taken at //this component. private Boolean Has_Been_Built; //Whether or not the grammar has been built yet. private Prompt_Text[] aText_Levels; // The array of text that can be read for different user levels private int Times_Visited; // The number of times the user has visited this prompt. UI_Prompt Classification Class Definition This object represents a single prompt and contains the necessary data structures and routines to build a grammar for the prompt and present the prompt to the user. Responsibilities This class is responsible for representing a prompt that will be presented to the user. As such, it needs to be able to present itself and accept a response. It must be able to build a grammar of acceptable commands for itself. It also must be able to accumulate a return value based on subprompts and scripts and return that value upon presentation. Constraints None Uses/Interactions This class is a UI_Dialog_Component and is referenced by UI_Dialogs. It implements the UI_Presentable interface and also makes reference to a UI_Dialogs object. Resources This class utilizes the dialog database. Processing See individual methods. Interface/Exports private UI_Dialogs Dialog_List; UI_Prompt(Recordset RSTable, int ID, UI_Dialogs); // Just load up the appropriate entry in the appropriate table. Initialize the //Variable_Name, aText_Levels and aHelp_Levels public UI_Command arCommands[]; //Set of all available commands public String Grammar; // The grammar string to be loaded upon presentation. public String GrammarHeader; // The string for the first level of commands available. public UI_Dialog_Component arDependencies[]; // An array containing components that the //current component is dependent upon (and // thus need to be included in the grammar) public int Build_Grammar(Boolean DBNeedsRefreshing) public String Variable_Name; // When a value is returned, the name of the variable to be //assigned a value. public String Assignment_String; // The string that will be used added to the query string from //this element. public int Present(String strLeftOvers) public UI_Enum_Command_Functions enumLastAction; // The last action that was taken at //this component. private Boolean Has_Been_Built; //Whether or not the grammar has been built yet. private Prompt_Text[] aText_Levels; // The array of text that can be read for different user levels private int Times_Visited; // The number of times the user has visited this prompt. UI_Prompt::Build_Grammar(Boolean DBNeedsRefreshing) Classification Method Definition This method is used to build a grammar for a particular prompt. Responsibilities This method is responsible for building any dependencies that may be required, building the grammar for a single prompt, and storing that grammar in a text file for future reference. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component or any subclasses. Resources None. Processing The routine must take the following steps: { if (has_been_built = false) { if (DBNeedsRefreshing) { Grammar_Header = [Grammar Name]->|| } for each dependent command { Put another command in arCommands[]; Switch(arCommands[LastAdd].Function) { Case uiCallPrompt: WorkComponent = Dialog_List.Prompt (arCommands[current].Call_ID) Case uiCallScript: WorkComponent = Dialog_List.Script (arCommands[current].Call_ID) Case uiCallScriptStep: WorkComponent = Dialog_List.Script_Step (arCommands[current].Call_ID) } WorkComponent.Build_Grammar(); If (DBNeedsRefreshing) { Compare WorkComponent.arDependencies to this.arDependencies, adding any dependencies that exist in WorkComponent to this.arDependencies. Add all of the commands for this object to the grammar with the header. Go through each prompt and script step this is dependent on and add the grammar headers and commands to the grammar (Not only will you add the commands to the list of availables, but the header will need to be updated for optional trailers to the current prompt grammar header). Add all macro and global commands to the header. Record the grammar in the grammar field of the table. } else { Load the grammar property from the appropriate field in the table. } } } return 1; } Interface/Exports None. UI_Prompt::Present(String strLeftOvers) Classification Method Definition This method is used to present the prompt to the user and accept a response. Responsibilities This routine must load the appropriate grammar, read the appropriate text to the user, accept a response, evaluate the response, and choose the correct course of action based on the response. It must also take any left-overs, or strings that were said in a previous prompt or script step, and try to apply them here. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component. Resources None. Processing The routine must take the following steps: { do while true { if (strLeftOvers.Length == 0) { Load the grammar from its grammar property into memory as the current grammar that the speech recognition is listening for. Go through each prompt text entry and determine based on the current user level and the number of times this prompt has been visited, what text should be read. Increment the number of times the prompt has been visited Add any help text to the beginning of any prompt text. Begin reading the text to the user. Begin listening for a user response. Begin timer testing for a timeout. Do while no response and no timeout Wait; } If timeout and strLeftOvers.Length == 0 { // The user said nothing. User.UsedHelp(); Go through the help levels and determine which should be read to the user. Store it to be added to the prompt text in the next loop iteration. } else { // The user said something. Go through each command and attempt to match the recognized text to a possible command. Take the longest string possible as the match. Switch (function associated with selected command): { case uiUnrecognized: User.UsedHelp(); Add text to be said letting the user know it was not recognized. Go through the help levels and determine which should be read to the user. Store it to be added to the prompt text in the next loop iteration. Break; case uiHelp: User.UsedHelp(); Go through the help levels and determine which should be read to the user. Store it to be added to the prompt text in the next loop iteration. Break; case uiBack: Flag last action as uiBack. Exit loop. Break; case uiStartOver: Flag last action as uiStartOver. Exit loop. Break; case uiCallPrompt: Store the appropriate prompt as WorkComponent Break; case uiCallScript: Store the appropriate script as WorkComponent Break; Case uiCallMacro: Assignment string = Macro.Querystring Exit loop case uiReturnValue: Set the assignment string to = Exit loop } if (uiCallPrompt) || (uiCallScript) { WorkComponent.Present(); Switch (WorkComponent.LastAction) { case uiStartOver: LastAction = uiStartOver; Exit loop. Case uiBack: // Do nothing-stay in the loop. Default: // They got a return value. Add WorkComponent.Assignment_String to this.assignment_string and add = Exit loop } } } } } Interface/Exports None. UI_Script Classification Class Definition This object represents a script, or series of prompts to be read in succession, and contains the necessary data structures and routines to build a grammar for the script and present the script to the user. Responsibilities This class is responsible for representing a script that will be presented to the user. As such, it needs to be able to present itself, meaning every script step within the script. It must be able to build a grammar of acceptable commands for itself. It also must be able to accumulate a return value based on subprompts and scripts and return that value upon presentation. Constraints None Uses/Interactions This class is a UI_Dialog_Component and is referenced by UI_Dialogs. It implements the UI_Presentable interface and also makes reference to a UI_Dialogs object. It also references the UI_Script_Step class and other UI_Dialog_Component objects. Resources This class utilizes the dialog database. Processing See individual methods. Interface/Exports private UI_Dialogs Dialog_List; UI_Script(Recordset RSTable, int ID, UI_Dialogs); // Just load up the appropriate entry in the appropriate table. Initialize the //Variable_Name, aText_Levels and aHelp_Levels public String Grammar; // The grammar string to be loaded upon presentation. public String GrammarHeader; // The string for the first level of commands available. public UI_Dialog_Component arDependencies[]; // An array containing components that the //current component is dependent upon (and // thus need to be included in the grammar) public Int Build_Grammar(Boolean DBNeedsRefreshing) public String Variable_Name; // When a value is returned, the name of the variable to be //assigned a value. public String Assignment_String; // The string that will be used added to the query string from //this element. public Int Present(String strLeftOvers) public UI_Enum_Command_Functions enumLastAction; // The last action that was taken at //this component. private Boolean Has_Been_Built; //Whether or not the grammar has been built yet. private Prompt_Text[] aText_Levels; // The array of text that can be read for different user levels private int Times_Visited; // The number of times the user has visited this prompt. UI_Script::Build_Grammar(Boolean DBNeedsRefreshing) Classification Method Definition This method is used to build a script for a particular prompt. It does not actually need to build a grammar for itself but it does for each script step underneath it. Responsibilities This method is responsible for building any dependencies that may be required. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component or any subclasses. Resources None. Processing The routine must take the following steps: { if (has_been_built = false) { for each script step defined for this script { WorkComponent = Dialog_List.Script_Step (Dependent Script Step ID) } WorkComponent.Build_Grammar(); If (DBNeedsRefreshing) { Compare WorkComponent.arDependencies to this.arDependencies, adding any dependencies that exist in WorkComponent to this.arDependencies. } } return 1; } Interface/Exports None. UI_Script::Present(String strLeftOvers) Classification Method Definition This method is used to present the script to the user. Responsibilities This routine must simply call up the appropriate script steps one-by-one and return the assignment string for use by higher level routines. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component. Resources None. Processing The routine must take the following steps: { for each script step in the script { Current.Present(strLeftOvers); Switch (Current.LastAction) { case uiStartOver: LastAction = uiStartOver; Exit loop. Case uiBack: If (Current = first) { LastAction = uiStartOver; Exit Loop. } else Current = Previous; Default: // They got a return value. StrLeftOvers = Current.LeftOverString Go to the next script step. } } for each script step in the script { Assignment_String += Current.Assignment_String } } Interface/Exports None. UI_Script_Step Classification Class Definition This object represents a single prompt within a script and contains the necessary data structures and routines to build a grammar for the prompt and present the prompt to the user. Responsibilities This class is responsible for representing a script step that will be presented to the user. As such, it needs to be able to present itself and accept a response. It must be able to build a grammar of acceptable commands for itself. It also must be able to accumulate a return value based on subprompts and scripts and return that value upon presentation. Constraints None Uses/Interactions This class is a UI_Dialog_Component and is referenced by UI_Dialogs. It implements the UI_Presentable interface and also makes reference to a UI_Dialogs object. It references other UI_Script_Step objects as well as UI_Prompt objects. Resources This class utilizes the dialog database. Processing See individual methods. Interface/Exports private UI_Dialogs Dialog_List; UI_Script_Step(Recordset RSTable, int ID, UI_Dialogs); // Just load up the appropriate entry in the appropriate table. Initialize the //Variable_Name, aText_Levels and aHelp_Levels public UI_Script_Step Next_Step; // Holds the next step in the script to execute. public String Grammar; // The grammar string to be loaded upon presentation. public String GrammarHeader; // The string for the first level of commands available. public UI_Dialog_Component arDependencies[]; // An array containing components that the //current component is dependent upon (and // thus need to be included in the grammar) public Int Build_Grammar(Boolean DBNeedsRefreshing) public String Variable_Name; // When a value is returned, the name of the variable to be //assigned a value. public String Assignment_String; // The string that will be used added to the query string from //this element. public Int Present(String strLeftOvers) public UI_Enum_Command_Functions enumLastAction; // The last action that was taken at //this component. private Boolean Has_Been_Built; //Whether or not the grammar has been built yet. private Prompt_Text[] aText_Levels; // The array of text that can be read for different user levels private int Times_Visited; // The number of times the user has visited this prompt. UI_Script_Step::Build_Grammar(Boolean DBNeedsRefreshing) Classification Method Definition This method is used to build a grammar for a particular script step. Responsibilities This method is responsible for building any dependencies that may be required, building the grammar for a single prompt, and storing that grammar in a text file for future reference. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component or any subclasses. Resources None. Processing The routine must take the following steps: { if (has_been_built = false) { If (DBNeedsRefreshing) { Build the prompt that this script step is based on Build the script step that follows this step (if any) Compare Prompt.arDependencies to this.arDependencies, adding any dependencies that exist in WorkComponent to this.arDependencies. Compare next script step dependencies to this.arDependencies, adding any dependencies that exist in the next step and not this one. Use the prompt grammar header and add optional next script step trailers to it. Go through each prompt and script step this is dependent on and add the grammar headers and commands to the grammar Add all macro and global commands to the header. Record the grammar in the appropriate field in the table. } else { Load the grammar property from the text file indicated in the database } } return 1; } Interface/Exports None. UI_Script_Step::Present(String strLeftOvers) Classification Method Definition This method is used to present the script step to the user and accept a response. Responsibilities This routine must load the appropriate grammar, read the appropriate text to the user, accept a response, evaluate the response, and choose the correct course of action based on the response. It must also take any left-overs, or strings that were said in a previous prompt or script step, and try to apply them here. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component. Resources None. Processing The routine must take the following steps: { do while true { if (strLeftOvers.Length == 0) { Load the grammar from the appropriate field in the table as the current grammar that the speech recognition is listening for. Go through each prompt text entry and determine based on the current user level and the number of times this prompt has been visited, what text should be read. Increment the number of times the prompt has been visited Add any help text to the beginning of any prompt text. Begin reading the text to the user. Begin listening for a user response. Begin timer testing for a timeout. Do while no response and no timeout Wait; } If timeout and strLeftOvers.Length == 0 { // The user said nothing. User.UsedHelp(); Go through the help levels and determine which should be read to the user. Store it to be added to the prompt text in the next loop iteration. } else { // The user said something. Go through each command and attempt to match the recognized text to a possible command. Take the longest string possible as the match. Switch (function associated with selected command): { case uiUnrecognized: User.UsedHelp(); Add text to be said letting the user know it was not recognized. Go through the help levels and determine which should be read to the user. Store it to be added to the prompt text in the next loop iteration. Break; case uiHelp: User.UsedHelp(); Go through the help levels and determine which should be read to the user. Store it to be added to the prompt text in the next loop iteration. Break; case uiBack: Flag last action as uiBack. Exit loop. Break; case uiStartOver: Flag last action as uiStartOver. Exit loop. Break; case uiCallPrompt: Store the appropriate prompt as WorkComponent Break; case uiCallScript: Store the appropriate script as WorkComponent Break; Case uiCallMacro: Assignment string = Macro.Querystring Exit loop case uiReturnValue: Set the assignment string to = Exit loop } if (uiCallPrompt) || (uiCallScript) { WorkComponent.Present(); Switch (WorkComponent.LastAction) { case uiStartOver: LastAction = uiStartOver; Exit loop. Case uiBack: // Do nothing-stay in the loop. Default: // They got a return value. Add WorkComponent.Assignment_String to this.assignment_string and add = Exit loop } } } } } Interface/Exports None. UI_Command Classification Class Definition This class contains information about commands the user is allowed to give to various prompts. It contains both the text the user is allowed to say and information about what is to occur when the command is said. Responsibilities This class does very little except to act as a lookup. Each UI_Dialog_Component will possess a list of available commands. The commands will contain the allowable text and the function to perform when the command is selected. Constraints None. Uses/Interactions The command uses the type UI_Enum_Command_Functions. It is utilized by UI_Dialog_Component and all subclasses. Resources None. Processing See individual methods. Interface/Exports public UI_Command(String strText, UI_Enum_Command_Functions enumFunction) //Initialize the properties. Private boolean IsMacro; // True for macro, false for global command. Private String Macro_Query; // A string containing the query text to be sent on a macro (if macro) public UI_Enum_Command_Functions Function; //The function code to be executed when this //command is recognized. public String Text; // The text to be recognized. public String ReturnValue; // The value to be assigned to the variable if //this command is used. public int Call_ID; //The ID of the dialog component to call if //applicable. UI_Help_Level Classification Class Definition This object contains text that the computer may read to the user when the user is in need of help, the user level required, etc. Responsibilities Each help level simply contains the text to be read, the user level at which to read it, the number of times visited, the maximum number of visits before the next help is reached, etc. Its job is simply to return the text and accumulate the number of times it is visited successively. Constraints None. Uses/Interactions The class is used by UI_Dialog_Component and all subclasses. Resources None. Processing See individual methods. Interface/Exports int User_Level; //Defines the user level for which this text is presented int max_visits; //If the user has been to help in this prompt more than this many times, read the //next help level. string Return_Text(); // Simply returns the text of the help for the current user level. UI_Help_Level(String strText, int iUserLevel, int iMaxVisits); // Initialize the properties. UI_Prompt_Text Classification Class Definition This object contains text that the computer may read to the user when the user is at a prompt. Responsibilities Each help level simply contains the text to be read, the user level at which to read it, the maximum number of visits before the next prompt text is reached, etc. Its job is simply to return the text and accumulate the number of times it is visited successively. Constraints None. Uses/Interactions The class is used by UI_Dialog_Component and all subclasses. Resources None. Processing See individual methods. Interface/Exports int User_Level; //Defines the user level for which this text is presented int max_visits; //If the user has been to this prompt more than this many times, read the next //prompt text. string Return_Text(); // Simply returns the text for the current user level. UI_Help_Level(String strText, int iUserLevel, int iMaxVisits); // Initialize the properties. UI_User Classification Class Definition This is the class that represents the user. It contains information such as user level, etc. Responsibilities This class is used to store information about the user. It needs to keep track of things such as barge-ins and use of special features in order to come up with a user level. Constraints Only one instance of this class should exist at any time. Uses/Interactions The UI_User class is referenced by User_Interface, UI_Dialog_Component and all subclasses. Resources None. Processing See the description of the methods. Interface/Exports UI_User(); // Just initialize the user level to the lowest possible user level. public Int Change_User_Level(int New_Level); //Update the user level manually to a new level. public void BargedIn() public void UsedMacro() public void UsedShortcut() public void UsedHelp() Public int User_Level; // The user level of the current user. Private float fUser_Level; // An internal user level that is a floatthis provides some flexibility in //adjusting it. UI_User::BargedIn(), UI_User::UsedMacro(), UI_User::UsedShortCut() Classification Method Definition This method is simply used to notify the user class that the user has used an advanced feature and the user level may need to be adjusted. Responsibilities All this routine must do is evaluate the users current level and adjust it based on the use of the advanced feature. It will use the internal user level, which is a float rather than an integer, so that it may advance it by some amount. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component or any subclasses from the Present() routine. Resources None. Processing The routine must perform the following steps (notethe adjustment may be changed according to the spacing between user levels and the weight given to the feature): { if (fUser_Level < MAX_USER_LEVEL) fUser_Level = fUser_Level + 0.5; User_Level = floor(fUser_Level); } Interface/Exports None. UI_User::Used_Help() Classification Method Definition This method is simply used to notify the user class that the user has used help and the user level may need to be adjusted. Responsibilities All this routine must do is evaluate the users current level and adjust it based on the fact that the user has asked for assistance and may be less advanced than previously thought. It will use the internal user level, which is a float rather than an integer, so that it may advance it by some amount. Constraints None. Uses/Interactions This method will be used from a UI_Dialog_Component or any subclasses from the Present() routine. Resources None. Processing The routine must perform the following steps (notethe adjustment may be changed according to the spacing between user levels): { if (fUser_Level > MIN_USER_LEVEL) fUser_Level = fUser_Level - 0.5; User_Level = floor(fUser_Level); } Interface/Exports None. UI_Response_Formulator Classification Class Definition This is the class that will put together responses for the user based on what the user asked for and what the server sends back. Responsibilities The class must be the starting point for loading up all of the possible response scenarios as well as deciding what responses to read to the user. Constraints Only one instance of this class should exist at any time. Uses/Interactions This class is referenced by the User_Interface::Main() routine. Resources None. Processing See the description of the methods. Interface/Exports UI_Response_Formulator(); // Default constructor UI_Response_Formulator(ADOConnection conDB); string getResponses(String strClient, String strServer); private UI_Response_Node Response_Nodes[]; // Array of the possible response scenarios UI_Response_Formulator::UI_Response_Formulator(ADOConnection conDB) Classification Method Definition This method gets passed in an ADOConnection object that will connect it to the dialog database. It returns nothing. It is used to initialize the response formulator class. Responsibilities This routine will open up the appropriate database structures and will call the constructors for each response node with a response ID. This will cause the response nodes to be filled up with the appropriate information. Constraints None. Uses/Interactions This method will be called from the User_Interface::Main() method. Resources None. Processing The routine will need to count the number of responses available in the database and allocate an array of response nodes large enough to hold them all. It will then construct a response node for each array element, each corresponding to an available response definition in the database. Finally, it will sort the response nodes based on the number of criteria for each one (in descending order), so that the first match found will be the most stringent match. Interface/Exports None. String UI_Response_Formulator::getResponses(String strClient, String strServer) Classification Method Definition This method gets passed a string strClient, which contains the parameter definition for the client query. It also gets passed a string strServer, which contains the parameter definition for the server response. It will use these to create a response and will return that response in a string. Responsibilities This routine will accept the client and server-side communications and will create a response based upon the parameters within them and the response nodes set up. It must parse out the variables and find the best criteria match. Constraints None. Uses/Interactions This method will be called from the User_Interface::Main() method. Resources None. Processing This routine will need to perform the following steps: { Parameter_Parser ppClient, ppServer; int iServerCount = 0; String strResponse = ; ppClient = new Parameter_Parser(); ppServer = new Parameter_Parser; if (ppClient.setVars(strClient) == False) return strError; if (ppServer.setVars(strServer) == False) return strError; while (ppServer.setVars(strServer,iServerCount) { for (int j = 0; j < # of Response Nodes; ++j) { if (Response_Nodes.getMatch(ppClient, ppServer)) { strResponse = strResponse + Response_Nodes.getResponse(); break; } if (j == # of Response Nodes 1) return strError; } ++iServerCount; } return strResponse; } Interface/Exports None. UI_Response_Node Classification Class Definition This is a class that contains a single response scenario and the response format to use if it matches. Responsibilities This class must load a scenario from the dialog database, determine whether or not a given scenario is a match to this scenario, and formulate the proper response given the client and server side parameters. Constraints None. Uses/Interactions This class is referenced by the UI_Response_Formulator::getResponses() routine. Resources None. Processing See the description of the methods. Interface/Exports UI_Response_Mode(); // Default Constructor UI_Response_Mode(ADOConnection conDB, long ResponseID); // Load up the appropriate //structures from the tables in the database. Boolean getMatch(Parameter_Parser ppClient, Parameter_Parser ppServer); String getResponse(); // Just returns the Response variable. int getCriteriaCount(); // Return the number of criteria that have been defined. private String Response; // String set when getMatch executes to put together the response string. private String ClientReqs[?,2]; // The array of client requirements (Parameter Name, Value) private String ServerReqs[?,2]; // The array of server requirements (Parameter Name, Value) private String Rcomponents[]; // The array of the component text to be read back. private boolean Rcomponentvars[?,2]; // The array of booleans indicating whether or not the //corresponsing Rcomponents[] entry is a //variable name. The second element is true //if it is a client variable, false for server Boolean UI_Response_Node::getMatch(Parameter_Parser ppClient, Parameter_Parser ppServer) Classification Method Definition This method gets passed a parameter parser for the client and for the server which contains the parameter definitions for each. It returns a Boolean true if it found a match and a false if it did not. Responsibilities This routine will accept the client and server parameter definitions and will compare each parameter in its own definition with the parameter stored in the Parameter_Parser definition. If the parameter is not defined in the Parameter_Parser or if the parameter has a different value, it will not be a match and a false will be returned. Otherwise, we will formulate the response and return a true. Constraints None. Uses/Interactions This method will be called from the Response_Formulator::Formulate_Responses() method. Resources None. Processing This routine will need to perform the following steps: { String strValue; for each parameter defined in ClientReqs { strValue = ppClients.getVarValue(ClientReqs parameter name); if (strValue != ClientReqs parameter value) return False } for each parameter defined in ServerReqs { strValue = ppServer.getVarValue(ServerReqs parameter name); if (strValue != ServerReqs parameter value) return False } // At this point if we havent returned we found a match. Response = For each element in Rcomponentvars[] { if the element is a variable { if (Rcomponentvars[current,2] = True) { strValue = ppClient.getVarValue(Rcomponents); if (strValue == null) { return False; } else { Response += strValue } } else { strValue = ppServer.getVarValue(Rcomponents); if (strValue == null) { return False; } else { Response += strValue } } } else { Response += corresponding element of Rcomponents[] } } Return True; } Interface/Exports None. Parameter_Parser Classification Class Definition This is a class that will act as an interface to the parameter strings that get sent from client to server and vice versa. Responsibilities This class will be responsible for taking a string and parsing out the parameter names and values from it. It will need to have the ability to pull out the nth occurrence of a set of parameter values within a string. It will also need to provide a simple method for accessing the variables, by name, to determine whether they are valid or invalid, and if they are valid, what their value is. Constraints None. Uses/Interactions This class is referenced by the UI_Response_Node::getMatch() routine. Resources None. Processing See the description of the methods. Interface/Exports Parameter_Parser(); // The default constructor. clear(); // Clear out all of the parameters that were obtained in the last parsing. Boolean setVars(String strVars, int iRecord); Boolean setVars(String strVars); // Simply calls setVars(strVars,0) String getVarValue(String VarName); // Just look up the variable and return the value (or null for //non-existence). private String Params[?,2] // The list of parameters parsed and their associated values. Boolean Parameter_Parser::setVars(String strVars, int iRecord) Classification Method Definition This method is used to pull a set of variables out of the string set in.strVars is the string from which the parameters are to be extracted. iRecord is an integer indicating the occurrence within the string to use. This second variable is necessary because a string may contain multiple records to be read. Responsibilities The method must parse out the strVars variable into its given parameters and values. strVars will follow the format: = = If there are multiple records in the string, strVars will simply contain duplicate instances of the same parameters. The parameters, however, must follow the same order in each record and must be of the same format. iRecord, ranging in value from 0 to the maximum number of records 1, will be passed in and must be used to determine which set of parameters is retrieved. Constraints None. Uses/Interactions This method will be called from a UI_Response_Node::getMatch() routine. Resources None. Processing The routine must perform the following steps: { int RecCount = 0; String strFirstParam; Int ParamCount = 0; Parse out the first parameter name and store it in strFirstParam while (RecCount < iRecord) { Parse out the current parameter. If we ran out of parameters Return false; If the current parameter name == strFirstParam { ++RecCount; ParamCount = 0; } else ++ParamCount; } // We found the right parameter set. Allocate an array of size ParamCount + 1, 2; Store the Parameter/Value pair in element 0; ++elementCount; While (strFirstParam != Current Parameter Value) { if end of string return False; Store the Parameter/Value pair in element elementCount. ++elementCount; } return true; } Interface/Exports None. 8 - Dialog Database 9 - SSDB (Sports Score Database) 10 - Dialog Generation Utility  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC17" Glossary Query Strings are the final result of the user's interaction with the application. They are sent to the Sports Score Server where they are interpreted and acted upon. Prompts will be defined as the point at which the computer and the user interact. These are decision points in the control flow of the program, allowing the program to branch based on the user response. Prompt Text is the text that is read by the computer to the user at any given prompt. There may be several levels of prompt text for any prompt; the actual prompt text read to the user depends on the current user level. Commands are the legal responses the user may make at any given prompt. Scripts are series of prompts that are executed in succession. They may be used when multiple pieces of information must be determined in order to form a query string. Help Menus are sets of text that may be read to the user when help is requested at any prompt or at a global level. Help Text is the text read by the computer to the user at any given help menu. There may be several levels of help text for any help menu; the actual help text read to the user depends on the current user level. Global is the term used to identify commands and help menus that are available at any prompt within the system. Local is the term used to identify commands and help menus that are available only when the user is at a specific prompt. Acronyms and Abbreviations WV Web Viking SSS Sport Scores System MLB Major League Baseball DI Database Interface MLBWS Major League Baseball Web Site ESPNWS ESPN Web Site CPAN Comprehensive Perl Archive Network  HYPERLINK "http://www.enteract.com/~bradapp/docs/sdd.html" \l "TOC_SEC18" Bibliography Sports Score System Requirements revision 3.1 Software Engineer, by Dick Hamlet and Joe Maybee Software Design Template, by Brad Appleton Web Programming with Perl 5, by William Middleton Brad Appleton < HYPERLINK "mailto:bradapp@enteract.com" bradapp@enteract.com>  HYPERLINK "http://www.enteract.com/~bradapp" http://www.enteract.com/~bradapp PAGE  PAGE 35  FILENAME \p C:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.doc Error Messages Web sites (HTML files) Format outputs Parse HTML files Retrieve HTML files Formatted data Time Error Messages Error Messages Web Viking Program serverClientThread serverClientThread serverClientThread serverCommThread Interface to Sports Score server Interface to Sports Score client application read write connect disconnect %+?[\^`itu01Jܻ~s~kff`f\T\j5U\5\ mHnHu jU5B*\phCJ OJQJ^JaJ CJOJQJ^JaJ5CJ OJQJ\^JaJ #5B*CJOJQJ\^JaJph#5B*CJOJQJ\^JaJphB*CJ,OJQJ^JaJ,ph#5B*CJOJQJ\^JaJphCJ aJ 56CJHOJQJ\]^JaJH5CJ4OJQJ\^JaJ4%&'()*+?\]^$a$$a$V$$Ifl#$04 la $$Ifa$ $$Ifa$$a$g^_`ituOX   !  ! $a$$a$JKLMN{|+,STUVW  ;<[\]^_`߾߳ߨߝߗjUj0J6U] 0J6]j45U\j5U\j5U\j5U\j5U\j{5U\5\5\mHnHuj5U\j5U\4X `m( 4 J r 7 23Z  EFhijkl" # $ & ' W X z { | ~   . / 0 2 3 h i 5\j7UjUjUjUjUjfUjUjNU 0J6]0J6]mHnHuj0J6U]= " # D E F H I J t u   ; < l m n p q   1 2 3 5 6 f g μıΩıΡıΙıΑıj^ Uj Uj Uj U0J6]mHnHuj Uj0J6U] 0J6]jY 5U\5\mHnHuj5U\5\j5U\6 13gh*+TUVXY!"#%&WXнȴܬܤܜܔ܌jpUjUjUjUjU5\mHnHujM5U\j5U\5\j U 0J6]0J6]mHnHuj0J6U]j U7'abQRTU^[$\$  )*[\]_`b12KLMOPQUVнȴЮЁȴ|t|jU jUju5U\5CJ\mHnHuj5CJU\j5CJU\ 5CJ\5\mHnHujo5U\j5U\5\jU0J6]mHnHujU 0J6]j0J6U]-'(rstbcd""`"a"b"v"w",,,B-C-D-\-]-^-55666-6.6/60616|6}6~6666jZUjYCJUaJjXCJUaJjWU0JjVUjVUjUmHnHujCJUaJCJaJjCJUaJ jU 0JCJaJ9&'WHI; L!" & F. h88^8 & F- h88^8""x"$$&&((**,,^-_-U/V/11224 4555/6066[$\$666666667(7071727Y7Z7[7\7]7^7_7`7777770]0 h@ ! h[$\$66666666666627Y7777777772878=8>8?8J8K8N8\8]8^8b888888888999999999N:^:`::::T<d<e<<<<<>>5@p@@AAɾɾѱ jP]Uj\U0Jj|[U jUCJ 5CJ\CJ 5OJQJCJjUmHnHujCJUmHnHu5\F728:8>8K8]8`8a8b8888M:N:`::::S<T<e<<<==>H> $[$\$a$0]0 h0]0H>`>>>>>>?3@4@5@p@@@AAAACCFF%H&H.H/H ! $[$\$a$[$\$ & F1A&H.H/HhHjHlHvHHHHHHQOlOmOnOoOOOOOOO}SSh.h\hhhhhiipiqiii3j4jjjkktkukkkkkkkOlPlllm mmmmm?n@nJnCJOJQJ^JaJCJaJ#5B*CJOJQJ\^JaJphj5CJU\mHnHuaJmHnHujUmHnHujCJUmHnHu 5CJ\aJA/HIHJHhHkHlHwHxHyHzH{H|H}H~HHHHH&I'IsJtJLLPOQOROlOmO !mOOOOOOOOOOOOOOOOOOMQNQ}S~SSSmUnUiWjWXYYYYi[j[\\^^]_^_aabbbeeffhhh.h/h\hbh$If & F^ & Fbhhhmhthhh.$$IfrH , ''T'''  2X 62 22 22 22 22 24a$IfhhhhhhhhhhO`$$IfrH , #T## X 62 22 22 22 22 24a$If hhiii!i.i0ipiqiOpO$$$IfrH , #T## X 62 22 22 22 22 24a$If qisiiiiiiiiF$$IfrH , #T## X 62 22 22 22 22 24a $$Ifa$$Ifiii3j4j6jCjJjMjOF $$Ifa$$$IfrH , #T## X 62 22 22 22 22 24a$IfMjjjjjjjkkkOO$$IfrH , #T## X 62 22 22 22 22 24a$If kk)k+ktkukwkkkkO$$IfrH , #T## X 62 22 22 22 22 24a$If kkkkkkkkO,$$IfrH , #T## X 62 22 22 22 22 24a$Ifkkkkkk4....$If$$IfrH , #T##  2X 62 22 22 22 22 24akkkklllOlOX$$IfrH , #T## X 62 22 22 22 22 24a$IfOlPlRl]ljllllUOOOOO$If$$IfrH , #T## X 62 22 22 22 22 24allllllmU$OOOOO$If$$IfrH , #T## X 62 22 22 22 22 24am m"m'm.m3mmmmmUOOOOOU OO$If$$IfrH , #T## X 62 22 22 22 22 24a mmmmmmmmm?nO$$IfrH , #T## X 62 22 22 22 22 24a$If ?n@nBnDnFnHnJnU,OOOOO$If$$IfrH , #T## X 62 22 22 22 22 24aJnKnQnUnbndn4....$If$$IfrH , #T##  2X 62 22 22 22 22 24aJnKnnnnn"o#o-o.ohoioooppcpdppp q qpqqq{q|qqqqqErFrrrss ssTsUsssttHtItttttttCuDuuuuu=v>vvvvvvv:w;w~wwwwwwxxexfxxxxxxx.y/yoypyyyzzjzkzuzvzCJOJQJ^JaJCJaJ_dnnnnnnnnOF $$Ifa$$$IfrH , #T## X 62 22 22 22 22 24a$Ifnnnnnn"o#o%o'oUpOOOOOU,OO$If$$IfrH , #T## X 62 22 22 22 22 24a 'o)o+o-o.o5o.$$IfrH , #T##  2X 62 22 22 22 22 24a$If5o9oFoHohoiokouoooOd$$IfrH , #T## X 62 22 22 22 22 24a$If oooooooppO4FOT $$Ifa$$$IfrH , #T## X 62 22 22 22 22 24a$Ifppp$p)pcpdpfpnpupO0$$IfrH , #T## X 62 22 22 22 22 24a$If upzppppppp qOpF $$Ifa$$$IfrH , #T## X 62 22 22 22 22 24a$If q qqqqqpqUOOOOO$If$$IfrH , #T## X 62 22 22 22 22 24apqqqsquqwqyq{qU,OOOOO$If$$IfrH , #T## X 62 22 22 22 22 24a{q|qqqqq4....$If$$IfrH , #T##  2X 62 22 22 22 22 24aqqqqqqqqqrO O$$IfrH , #T## X 62 22 22 22 22 24a$If r rrrErFrHr_rlrnrO$$$IfrH , #T## X 62 22 22 22 22 24a$If nrrrrrrrsO$$IfrH , #T## X 62 22 22 22 22 24a$Ifssss s s sU,OOOOO$If$$IfrH , #T## X 62 22 22 22 22 24a ss!s%s2s4s4....$If$$IfrH , #T##  2X 62 22 22 22 22 24a4sTsUsWscspsrssOX$$IfrH , #T## X 62 22 22 22 22 24a$Ifssssssttt tUlOOOOOU OO$If$$IfrH , #T## X 62 22 22 22 22 24a tttHtItKtWt_tatFx$$IfrH , #T## X 62 22 22 22 22 24a $$Ifa$$IfattttttttO0$$IfrH , #T## X 62 22 22 22 22 24a$IftttttttU,OOOOO$If$$IfrH , #T## X 62 22 22 22 22 24attuu!u#u4....$If$$IfrH , #T##  2X 62 22 22 22 22 24a#uCuDuFuRu_uauuO@$$IfrH , #T## X 62 22 22 22 22 24a$IfuuuuuuuuuUTOOOFOUTO $$Ifa$$If$$IfrH , #T## X 62 22 22 22 22 24auuuu=v>v@vQvYvF$$IfrH , #T## X 62 22 22 22 22 24a $$Ifa$$IfYv[vvvvvvvvO,$$IfrH , #T## X 62 22 22 22 22 24a$Ifvvvvvv4 ....$If$$IfrH , #T##  2X 62 22 22 22 22 24avvvvvww:wO$F $$Ifa$$$IfrH , #T## X 62 22 22 22 22 24a$If:w;w=wIwVwXw~wUOOOOO$If$$IfrH , #T## X 62 22 22 22 22 24a~wwwwwwwU,OOOOO$If$$IfrH , #T## X 62 22 22 22 22 24awwwwww4....$If$$IfrH , #T##  2X 62 22 22 22 22 24awwwwwwwxO`$$IfrH , #T## X 62 22 22 22 22 24a$Ifxxx$x+x.xexfxhxU$OOOFOUO $$Ifa$$If$$IfrH , #T## X 62 22 22 22 22 24ahxtx{xxxxxxxxO,$$IfrH , #T## X 62 22 22 22 22 24a$If xxxxxx.$$IfrH , #T##  2X 62 22 22 22 22 24a$Ifxxxxxxyy.y/yOO$$IfrH , #T## X 62 22 22 22 22 24a$If /y1y;yHyJyoypyryxyyOH$$IfrH , #T## X 62 22 22 22 22 24a$If yyyyyyyyzzODO`$$IfrH , #T## X 62 22 22 22 22 24a$If zz!z)z+zjzkzmzozqzO,$$IfrH , #T## X 62 22 22 22 22 24a$If qzszuzvzzz.$$IfrH , #T##  2X 62 22 22 22 22 24a$Ifzzzzzzzzz{OP$$IfrH , #T## X 62 22 22 22 22 24a$If vzzz{{n{o{{{||Q|R|\|]|||}}i}j}}}G~H~~~~~OPRMVWXYb&)0./elō̍|&yϚor`ajCJUaJ0JjU jU5\CJ 5CJ\5 5CJ\CJaJCJOJQJ^JaJJ{{{${.{0{n{o{q{{U|OOOOOU0OO$If$$IfrH , #T## X 62 22 22 22 22 24a {{{{{{{{{OF $$Ifa$$$IfrH , #T## X 62 22 22 22 22 24a$If{||||||Q|R|T|ODO,$$IfrH , #T## X 62 22 22 22 22 24a$If T|V|X|Z|\|]|.$$IfrH , #T##  2X 62 22 22 22 22 24a$If]|g|k|x|z||||||O$$IfrH , #T## X 62 22 22 22 22 24a$If ||}} }}}#}i}j}OO$$IfrH , #T## X 62 22 22 22 22 24a$If j}l}y}}}}}}}}O$$IfrH , #T## X 62 22 22 22 22 24a$If }}G~H~J~c~j~o~~~OO$$IfrH , #T## X 62 22 22 22 22 24a$If ~~~~~~~~O\$$IfrH , #T## X 62 22 22 22 22 24a$If OPQROMMMMF @$$IfrH , #T## X 62 22 22 22 22 24a$If(Ƃd2;78u׉/ @0^`0 & F  @R^`R @n΍6 O~t֐"ڒH @R^`R & F  @0^`0ʕ˕1FHbc&yΚϚF & F & F  & F$ & Fa$ 0^`0 & F  @R^`RnÝ.pqr^_`ƣǣգ֣[$\$ ^` & F aģţƣǣգ֣:Apxbicde§ɧoahƩժݪ9D^f^k'2ڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽڽ OJQJ^J6CJ]aJ5CJ\aJ 5CJ\CJaJ 0JCJaJjCJUaJjCJUaJCJaJJ89:Apxbibcde^`§ʧno`ahƩ \ժݪ9D^`=nĮ+Qw^fѰ`^'^k'2m ;<D5`^2 <C6>xyѵصǶԷշٸ%0DO"/ls˻ֻۻ$)7#2j #$6OJQJ]^J6CJ]aJ 5CJ\5CJ\aJ OJQJ^JCJaJR56>h9cwxyеѵٵǶ o^`ԷշѸٸ%0D^`DO"/kls˻ֻۻ$)7#`^#2:EWj  !"#$&$a$`^$%pqrvC\DJbZ`xz{|$45u 2CD,;Eu 6]aJ6aJ 6CJ]6CJ5\ B*CJphCJaJCJ 5CJ\0JjpU jUL&6v%s4p/u-BC[\y $|^`|a$$a$$a$y56DEbp^# $|^`|a$$a$$a$#< EUVLZ[x)$a$$a$)Dw<X{|?@_y/1h^h$a$ $|^`|a$12Ry +5?IS]hr|#$5tu 1 !^`12D(T 0c -^-&:;FGQqtu^u+LU BL sjt*4u&1;Lxj{ (1eo!*CR]g 5CJ\CJ6CJ`  ,JLVHI^=[F~ V[^!ABMN^|^ 3Zrsiju^!)*5Rftu%&2:;Mvx^5dgij| &(2Bd^`depq ")*CT\]h^`+,78Yl#4<=Hfw`,6#2=GW`|L[fp*4E$5>Ralv$/9J #;JU_Xa~.9C'/@LCJOJQJ^J 5CJ\6CJCJ\wUWa{|L]e^efq+34F #$6=>`^>Rcklw#$089K ^ "#;LTU`qVXb}~^089D^o(./A^HKL^efuv^L]fv%/ k{6?| GVakYb!2;p   c l   e v           3 D  CJaJ6CJ]aJ5CJ\aJaJOJQJ]^JaJ 5CJ\CJ6CJR$%0]r Iik|4`^46@{| GX`al^WYc !3:;p`   ! a c m       ' 8 a d e w ~       !`^       2 3 D                    !^`                 I Z    z.@^pq{  /7CM_degr  (y$5Wck5CJ\aJ6]CJaJ6CJ]aJ[     H I Z      yz-.@^` ]^pq{    /67B`^LM_efgr`^  (xy#$5VWcjk`^k}~67Ibcdr` !^k}~7Ibdr!"4Te"#-3>?Q%&.@AK} FW(2C5\5CJ\aJaJCJaJ6CJ]aJZ!"4STe"#-23>` !^>?Q%&-.@AK|}^` !EFW(^` !12C ^` !    j {       ! !|!!!!!!#"4"""""&#0#6#A#C#U#k#z#####$($0$B$$$$$$0%?%G%S%%%%& &&e&o&&&'0'a'p'x''''4(@(H(Z(((((((Z)j)y)) OJQJ^J5CJ\aJaJ6CJ]aJCJaJY    i j {         !! !{!|!!!!!!!!""^`""#"4"""""""%#&#0#5#6#A#B#C#U#V#k#z#######$`^$$($/$0$B$$$$$$$$$$$0%?%F%G%R%%%%%%& &`^ & &&d&e&o&&&&''0'1'2'a'p'w'x'''''3(4(@(G(H(Z(`^Z((((((((((Z)[)\)j)y)))))))3*4*@*m*n***`^))))4*@*n*****++!+++++++ ,,,,,X-b---------------.\.m...M/_/011111222222z334444Q5[55599C<N<`<g<r<<<==>$>D?V?r???? 5CJ\5CJ\aJ OJQJ^JCJaJ6CJ]aJX*****+++!++++++++++++ ,,,,,,,W-`^W-X-b---------------------.[.\.m..`^...L/M/_/001111111222222222y3z3344^44444P5Q5[55556 6a6d66666"7#74787X7\7]7{777^^777778 8;8<8o8p8888883989;9=9b9c9s99999 p^p`@ ^@ 9E:F:^:v::::B<C<N<O<`<f<g<r<===>>$>C?D?V? @ @@y@`^??????? @@z@@@@7CeCfCwCCCD'DEEEEEEfFpFFF5LGLOLYLZLkLrL}L@MEMHMYMN(NOOOOPPP QQQR.R?RGRRRRR9SESSS TT T.T8TBTTTUUUVV0V8VCVVVuXXY YFYJY\YjYtY~Y5CJ\aJ6CJ]aJCJaJ]y@z@@@@@A@AAARBBC6C7CeCfCwC~CCCDD'DEEE` P^`P^EEEEeFfFpFFFFGGWGZGvGxGGGG HHHTHHHIIKILI^LIrIvIIIJJJ6J:JJJJJJKKKKKLL-L1L4L5LGLNLOLYLYLZLkLqLrL}LGMHMYMNN(NOOOOOOPPPPP QQQQ ^`^`QRR-R.R?RFRGRRRRRR8S9SESSSS7T8TBTTTTTT U$UYU^`YUmUqUxU|UUUUUUUUVV0V7V8VCVVVVtXuXX YY YsYtY^`tY~YYYY*Z-ZrZZZZ[/[4[C[a[f[}[[[[[[[[[ \\\^~YYY\]]8]9]K]S]^]]]^^_+_Q_U_g_u_____``aaa/a@aKaaaWbcbkb}bbbbbbbbb|gggggi'iZjfjnjjjjjjjjjjjk%k/kokykkkkkllElFlmmmmmmnnoooopp5CJ\aJ6CJ]aJCJaJ]\\F\v\|\\\\\\\\\\\\]]]9]:]K]R]S]^]]]]^^`^^^__+_~______ ``E`q````````aaaa/a?a`?a@aKaaaaVbWbcbjbkb}bbbbbbbbbb8ccc,ddd=eae^`aeeeeefQffff4gzg{g|gggggggii'iYjZjfjmjnjj`^jnkokykkkkkkkl(lElrlllll+mKmommmmmmmmm`^mmnnnooooooppppppppp qHqqqrkrr ^``^p;pDpFpOpUpcpppppppppppppuuuuuuvvx"x)x;xKx^xtx~xxxxxxxyy7yIy`~~~~~~ 0:AL Xiχ!őבߑ ܒgsz5CJ\aJ6CJ]aJCJaJ]rrsPssst/tYtttuyuuuuuuuuuvvvx` ^` @ ^@ `^ ^`xx"x(x)x;xxxxyyy6y7yIyiyyyz\zzzX{{{{>| ^`@ ^@ `^>|R||||D}V}} ~_~`~~~~~~~~~ ` ^`^ @ ^@ `/0:@ALx{ $'NQx|ҁ*E`ق߂hi&Ʉʄ27@F WXiχ!MP^`^`ډۉ;?hiÊȊɊ,ɋ΋vwÌ֌ύЍ`ahiw ;DXΏڏ܏1;<>?ce֐!@đőőבޑߑ ےܒfgsyz•ەܕ^`zŔϔ%FUex•ܕŚ Ǜ؛(4;Mmas|ɞğ 1CKZ[ls~4EѤ *8akȥ)X5CJ\aJCJaJ6CJ]aJ]AdI(P pĚŚ  ^` @ ^@ ` ^` ^`p^p^ ƛǛ؛'(4:;Mݜ,/rw|^`KLQS]`asz{|ɞ^`ğ  BEhjӠߠ!.5?Yb`¡ǡˡΡ)-01CJKZ[lrs~34EҤ^`Ҥɥ*JӦTP|ܨ6J @ ^@ ` ^` ^``^<NWX ĬŬѬ׬ج12<B` ^`^ ŬЬج 2;CMذ19D .ADMU_ +,=DO&6t'0A\uĿοm|!1Q\evu"-6G]5CJ\aJCJaJ6CJ]aJ]BCNz}&,38/0jow|ðȰʰʰ԰װذ 189DCDNTU`^`?@SU|ѵҵ  5:Xm /X.78L||ɺҺԺ2r|}%4Wb +,=CDO%&7(/0Bÿ^`ÿĿϿEc lm{| !2` p^p` ^` ^`^2PQ]dewGtu ^``^!".56H123; p`^p``^`3;<KR^~   6?GQxRFVGRZk-.@HS%6Wj|!,k|FGY5CJ\aJCJaJ6CJ]aJ];<KQR]}~56@FGRwx9Ph^`QREFWFGSYZl`^./@GHS$%7^`68[}~{| !-jk}^`}DqGHY`al,  ^`Yal+ /Tjt}_py&!2WmwJ[evw +R\emws~ 0:KL[bm5CJ\aJ6CJ]aJCJaJ]0st~^_qxy'  !3v^`vw #$HjkMQ`/2GIJ\cdevw^` [\flmx^5S^`rs CEWX1`^14rs&)HLuz!&XXqv  189:KL[ab^bm45GxU%&efw5F&dewclt~s456>?@MCHקj>CJUaJ5\CJ 6CJ]6] 0JCJaJjWCJUaJCJaJjCJUaJ 5CJ\5CJ\aJCJaJ6CJ]aJBw~IJbz|}bcmst56RTvx>m   H[_`ors@BC0MxL}^*+-.\]^~  #$345\klqrCDIJPQY 5CJ\OJQJCJ 5CJCJCJmHnHuCJ jCJU0JmHnHu0J j0JUj΢U0Jj%U jUD  #$345FG[\klqr$a$h]h&`#$CDIJPQYZefgh^$a$YZehCJ+ 01hP/R / =!"#$%{DyK  IntroductionDyK SystemOverviewDyK DesignConsiderationsDyK AssumptionsAndDependenciesDyK GoalsAndGuidelinesDyK ArchitecturalStrategiesDyK SystemArchitectureDyK SubSysArchitectWebVikingDyK SubSysArchitectSSDBIDyK SubSysArchitectServerDyK SubSysArchitectServerCommDyK SubSysArchitectClientCommDyK SubSysArchitectClientDyK SubSysArchitectDialogDBDyK SubSysArchitectSSDBDyK SubSysArchitectDialogUtilityDyK PoliciesAndTacticsDyK DetailedSystemDesignDyK DetailedSystemDesignWebVikingDyK DetailedSystemDesignSSDBIDyK $DetailedSystemDesignServerComponentDyK DetailedSystemDesignServerCommDyK DetailedSystemDesignClientCommDyK $DetailedSystemDesignClientComponentDyK #DetailedSystemDesignDialogDatabaseDyK DetailedSubsystemDesignDyK !DetailedSubSystemDesignWebVikingDyK DetailedSubSystemDesignSSDBIDyK 'DetailedSubSystemDesignServerComponentDyK "DetailedSubSystemDesignServerCommDyK "DetailedSubSystemDesignClientCommDyK 'DetailedSubSystemDesignClientComponentDyK %DetailedSubSystemDesignDialogUtilitysDyK  GlossaryDyK AcronymsAndAbbreviations{DyK  BibliographyDyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC4DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC5^?Dd%5bJ  C A"">6c .>5@=>6c .#;]b>x˒$uUKU5&4L4 EHFN' ]YŵqOw*-*>/w/;W_W?OW_^}W u}:vy]/ˉo}ﯿ}}ر/:?AAAAAAAAAAAAAAAAA ?I/?~?X^:F-?^oɛ : .^\O?qd`zp }w 6>Ǐ>kd޿Hil% E&p f#z"l(8$1ƢѱȹJ4pR.B.Lmr$.B/}TKiI^^Z0?^(Uu)zEdX8nۇ!LB'Rx]î0tߔ֑uF|AgL =@zYH$µƧO:.\__7""I\%*(h>ћ:@Bف.Ok+5qbdOfa 2=(\^^֐0 HU^;h9 &!@ +jN_]9O9S 6{~@ ^^ZVR .} hsrz=2nدX'LET\ȘE o)R§nI}$l.x,u=[4Թƥьlk4־r9tТRA0_`h.[g\}e`o@o#IFT8Ƶ'?jO].!?UToM}7V@5z)zi/^888WQ}qk^BD^^|LWZ@wF/khgQxrr묻kc:NRߪtbH]qY띺#g~ |b#e5zq`3``:\'tֆz7}7.#}W f]]kp&}31qr;%%%A X  򃅣}PV*Q Rtu1uRz.\*>#FJis5Ӛ}%R]][ی^^Zk:b0zFpnXoެ&[_D=kLdŇ." ~Tߺ M3Aׯ;y@>D2d~pݔ3zQ B^5t} jfT0db...Dp}X%NnfwM-SEau@bꜚ,:K\Lz!TI* ׵tomNB=A U;m%KASoJ\r@%<י+3[>)y]nP ER7Ƨ襇6 VH>}T$s_5uF^NτJ&74rԕM ~򓟸 ڭTR:zk1ε*µ*W0x!NXטYP5I+䧳tHUf7yyץ.8 y}Qˤ[;~`XDUo-kp#ARO9Tp( =c-r|ΪǮE?Olax)~ID5-^P?-l8%yRk,sդl)b h|^J6%M߶^v;bwI5|*8q6EӍD ezz~B~7g\*a D!*9hbA!k{45 !l>vV4B4.xX rN5F 9bܰs:s'D9?,juȁ{V;gH?~񧧧} ^XqI'Ұ_ѿn­u|ߠ2;ѳzQ3\*$(VIjuV e:aۅz"*E҅iJI]S׺n`^?ͮoMC_RoVQIJE3fS6eģry{Sn Toȵ7Dk,0t Ve%}x.4+yaE/&+6FhFcI&7/Xw5Bz j ?}ݯ%E̹o*~6;J^ʡ}Šq幖4cY&?|YO5+eYp>'bxSmi#^Eb|c_14 4=pk9iJ0oy( o|@>P"aeXGķ޲!S C.;E/KiF,H 9P=:'.~[0= ۾S]W4Ck~`]ǐ4b6@!ZԶ K[ʾ/~yզ ~ߧYcSpKKkYY^Gzh,MB_:Y\ί}H/ѕQ-xlu5%]#)1.G6}HBuTw y YG$?ԁ7L5Vy5Ve$p3( r=oH%ў g+CLs:ȣb[Eox}:?F8:Y切 n0<?XŬ1Z%kj'jAu驗O}vqtz߷i>ތ{.~u_6b QҮo;9u{u#'?GC_4LKLK/II)OW$a]'''jYǔ2K++oQg ii-4b_U`*㷚f+{Wzv kJM9%8kf&ϟx4%Tsf6JY-|e|Eae_Pgʴj5QKX_%Waы/խ_ |e|H*J<PTM=>>nFLK/ %NV+ dz[d>MTKROa} [\+l|j@rBS՗JDJtM ?W6֜ fWL/-\kFD_Y|$X#Y؈pރ _%_i@z=(9tM{uuNpXWW]}_gS4k^_$[xHW^GPC`Yac޽{J+;n .YI@E)5xJ0S/JD?W"8ɉc+zi(bVD,sGHG} .+W$l^De X'C81O^H;s6|ԃyW+/[-(n7Nmx3G3;UX\w{d++џ&93Kzj(twDW3,ҞϼivٚPc˗/U?G2i|yePh4pAծ_fBޯ_>%ԋs^R8$rv@dOvgf _ԛZX=&!Jg+8M<٦Hx޼y듓aҠ_3\^^ex?W>AS_J0YzKGDH4f|S޸0V,zwҙeUG@_U4B(|%|e uS;硗!mKo˃ jQ(\yg#_:|eͮV#O}/ϥx'-l g8Ҳrڹ^8::ZX/~ceoQ!zrrL/ ]lAۂF|X Dk8(@yeEz}ⴁƨ([7GE]j]N~bƓ_Sןj:#+M#lzq;}FD3ay:%=ؿ%iz䏕Sz=i6 QLgJzlf\!ݵՊ:ݡ%(Ksۀk+Գ`!& 18Ϣ}$!-v^O\W4Yݴ0qY{#]$ .3aZ/l V/sE:Q4*R<ƫtp?Z/Q#BxS )y7˥7GH=kCտ.%@DSc=[ 7]10x/t?lx EuօƏ}E.ym,xPgw_VߢQ44ZgI %`3KSNm j\%G-vQWÍ`xgo߾:nviX\1_ -i]uR`2jU Z#"|剦u\Ok8XJɾދh6%8jvyIXۥJqAU[GFB' np?M͞C<]V++Xϸ>T/iB$*,|-Z ~O3r,| tЭ6M (>Z/-YGm32(˺UGMõZt:~>L#3u?*B*=ѓѧ_ }l=4GO"BWTXL_S ƨeH,dN]/-gK^9}AwEVT25ůcw+axf 3XwSGpq~%ZdžeӤk-s)2WGVfEoL3?ӟK=u@\6[Yzi@੤B**?ȐEh+z`'UAgZ_O ײM-ύ_giN]/#C%lIRwN&N}Vl=b\y 9nXPԧ5%\٦su]ԹiXʌg~p^s lϞqzi|>^X/ZDҠلZǕ56=["tZVy %p{ ۊ'sy4_rOZ6zGwuuųՑk8uP>'T `t,ir'g[fڳڂ1ljU[o ܸ^~"iMֶ[" ӂtj״\@5őԱ.Hx}I%/$ Kٓ"t~m߫m_˃ *-T5(#+>7r+J(+!,Q#Ӏ-(=<`ܲc7ol[_IWo@vss">@/=RrttD5WGfK.V@,-3 ^ݻFS|<[Z;ާ<`}}G[7~*J,+e7[tA?%ϼEyy[}^B[%y~Ӥo׫zM/I^_qº/z[ ꯨYcrX)cl ?ԇx?tM=t o"_*M*oB %u3`gǮSKut.S|\.ǃwE[$*___kˮn"H$nq F&cw9lIܵݕ4:: dYj}赈t<"nXψYTpL.U{ ѽs@u*y SNŴx1pzWWFJJVOL S,Ф3_Wtr~TB>ќjdnr,<ǮSKA2o䤭?iOך[7-SJ-tnʳC 庠'l3Ԭ1b1x||1J.x53S\\\Td:UnNI_p]z%rDC\˗/X֩OYIͦ=ZTk+l?==| j w~CXc6 j z6IW&WPMPs+ ~mh;]=v}^"xOEK'O-{WXHhZr7[0j=u39쬖OgO^Hܬ7TįLtp;Iz@9KPĶ4e HPc?_H8T?'7M ShHhJwA7}?)fUW Wim#l!+2u j]Qs\?S׋QQєێH#UBwInnnNOOg_*t 3*R4=}8b+K EJ&G~ _ВxۙQZyȭߝ'X(Dzޕm+K§O}<꺙c7 MkJxlF펖 Q[y ԩ,PSoZmgW,k^ |ʣ 8^K ۉ"^bz Tg%Ecug+sw*@5ȌY- ֛j%$AG>Ҝe!ʜJT r M>ݯ=f!yDMJ6{G|!FWg(/ypWhW̴Vkc5YeZL]/q48 `rV4!}6@vv].R00?R#85.қ1n:Hc_(՘&W&GWfWd,mavi5E"eٽ̌Ȧ"*@aq'ӇenWWr_r@.S;++vDÎy1_OKnǬ<]/&|e|F\} 5q(]=WWT_;N@/=LS+v#l*Zտ鉣cOQ+ 5;tEZCoZJ+v ]:NkL+{b__WM<{JW$34AB_1|e~|_cП8_q=++++++++++AJJJJJ+++++AJJJJJJJJJJ+++++AJJJJJJJJJJ+++++++AJJJJJJJJ+++++AJJ+++++AJJJJJJJJJJ++++++W< _^̱?99w?̞j菏ʧ&OTG.￟^}%|e|>Ӛf?c۷惃R_%_y^.//Kv2u͈eM+qW>iWꘛfw8NQ|uՊXWfi_RC?fĩ;nAE^ _ _(_!{~q復 _7_9<<ǴիqBM\B5J8W|^ _ _"_o&XiQFj1K;;>}{WJbkXEV|a4eꚙJߺy%+ϟ'WW&j_5hPL+`_}EC/=Bh*pƾ gi'nmBʌE=??vQA׆_ᅬ}e|EHg 8%5V+@zILZ4o_ _ W4ߴ*SD ԵVTC_Wj_[^ 2)]sA+36Q =+%M {Vݠ++bpf:~ht_2M)%]0KtA5ԍ("vDQ;|ʴ+lX)5:!9<==}UIc߿ߥV鉦x3<1륺 pk TYԴvQAUqR3C;`vߚb}lB/_$֒0"9pp!,8=w|T?w}}-0`zɉ@|j0g8 1\x`~0(?PsrA+-ﳻ}[MʼnW\ C+nx ^,bƬeά6z~V %a޻ΓhPpzz*,@_)a40"bӚn.^E:b09Pt^SihN:U \ۃdZTʳZX^BdFSF?)#/0qѵ/iRσ1367beо[]Mʥ9Z~JfT%mTПnb]nPF0\]/a]]]1*8xa~ {tw~y XV{(zTSmA0+Sǐ&#|Em`}t֢Ũ~_0!}cK$bXtGk]]+7op?O}P72SDy6ZAnn>Н ]egK#ޕ .rDOIybRggg9GRt,$-h`W06[s bU#qlj*؉|MTUjYX<86 $.7P-rJ$RS5j*"?jC+6pXԠ>?LtJ< ?2 J DXTvGq5 ydFT^X5h,6 {L r&* "@qw0Z shkPǤMȍee,E75*V`+ zeH0*^Mݺ r-dAiU۟ds馯AlH\ u9xUiwk#5:Y#iRa 1+'jr̬ZcܴPϺlW/mذ59AzWF D*蟙,'d2|m*,}OwڣHiƥB,U{:XT#$So^}x| SguzS]uuX}cؾxI ,QkLQ0̒7oP}p}}ԨzUR0AO9N\j&Xce Wim*I&KبG(w^RuwĂm>}QR+AJ0O.!o5V/jELxa05FĴTM!:RsGwۦJLnY9==%@gX#Tz}U~Jp4<S)-Ib W1_qiJvbc2*RL 81pI^6+/bߐ |%f N憍Tձy(.}8ta<\OH0<LBUF&P*̈AL)9| mJ8ܾB x.W&/9<<]"u8\Ls]"(F VѾ;U;ZKw~J@u4-(ŎT}n[kꅔ &Ʉ+A%SFbV WWW@ דXhЈEeWDtb v"%%mr7t vѴU~lwJ50:P<ܬ$A;+oȅLCDE[%ŤvPK}g- DJK7 }uurgLJZc)c`PeƦ"Ex>jBn੐bPe!_ תab9=4d2 /5 j vGhy@ׯE%a*+ASȸR{'f":؎2ً/(5,Y/p$}!r,;:>>U8=Rw瀐,_sU[ȬB7 %z0`er y.KSjn`NHJE=ęJʨhFGD@Fj, Or%{w0sb*b*-'ZNOOI' r}}7uEEJ'?ILDƝ>!y<9s_=OvҕRIP0^Hk".sų%c''' a )Kȃ4qF "M銅2FEK0 xIֈ{0P5ziKeOZ&RP/>| g[V9??ݭC&;XQIQmg7=iRBneIɠ9=<M4N=yK(O{rWVVBe&V (䘠^R5R3دygy/..2GzJw aB,/\i.jhSԬ:1}2y_%;4#E5s4I܅yb/^<9{k4<;;#N@_#}j>fEJ63zClSTeTBy\OA7X.X}.SRKѵguҌx, 66 %cZ)#B},?:jQAhmUğttt2qv+EH-D>"Ԁ&>nRIʾ¬gkμFzAU OP׾.~ILPER5h] Xk[UӔ`<-Q"=יn4d2I{hMD.jPRWyˏJZ*bִ#%n+z2/I냲xe,k#ue7yyGkRܢ#(kŲ,[`N,Yӿx5VPdS,Bp4gc -u̙.&4Κ pdMb,d YY8dPqPgA -(|7S2nt}P,Gfخ_c/zYXd1[ Qѵ_t*'Azz'u? g7ٙOȅN&H QNFkݺ=cy;kC  :99D]UQOvA@1T*. P!6Ք֧QM[Sb :f-+&G@i 2eM>iCPJ-tq/4?jGmMd]{fXJD)$V!89a}ؗz ON>C€Hha}؋/4vŕDHMjo=;;S==p[35^)5VD[GJ-_ '(_isuu }+Ҥܣ/Ui+Od-Jl.$փ/e%f6~AA+'ӑ:E[kznnnHA~.XWjקѪ{/鿇١;Q> A S4W3'k{lȞ+j( Rux6&He"LWWg}4i e1C׆kNi/SR ~ ҌA0RU$dYm[J֛q4K5lܣhw_l6q3(!{e%M] *uD*8ӊI MWI\{bMxԏ+<yC^'fP]-mհ dxϘ(0ԦO^{yˏ)y M%Ԏj7A0 U(sT-{@*(Ç_yO1Ro;5x_nrI*ARFqfG1hDT&A2OՕ!9Ԃ`h,/]9+$ AJȎ}bS hF(_f$6C5ߚZӍbV !'ա ^H/ho鿳7A&y-xHK>%-o|qqAl č1|~?b~hj } &'|}m2N܍[2SiެaRPhJSBX !5bAmMoܟ򥅉,UšJ:Ey׷Ģ'|zz ky?»YEU|̠^eMOR+Sӝ[VhGPKRГOQ%ím5_&Q.//MCӾOk5OK~'1AiD9Sǯh":W5 .]ڿ˿ xk"3cfkWe n Fussz(mJZJ}:nnW^_fo&g 3+4u}>9֢8̟쓳4Yd{C/pU0XbpR W`q)9ݏ{ 8im^buҔb-^h E?~4`':O,}G.%|i5TSQ,js }T؟C  !/͎_EGHq+=J=yyJ߽o(i_ԙ('4nT3_3אpҕu5D أYKgYP.߿Ē )YQǥk>z+^<^#3;|P*eGAj23IEwwLXǸt ,̟+?;Q[^E >9Ճ,fJ~LT ?mB-fX\GiYYj0?_+,ʤ~x+2NJTMĥ/(-3{ttD $a fAݫ04Fo)}Egz|`R'xj7a3g4='^ I\<^ ,t\d鲦8ǾOP~ڻ֑bMm+;ڼt33Q<`P}#gH-=J} ,K`)JHk |]:.D'{=<-Zk uw?YI FZ}WpΠoT$/GfZܝWs{a_Yؿ `HP9x u\,;ur+4&o*]s(E _$b  v1)b5ej<%BAP.,(J|.kDz,\Jo(H XPxϓ%wE7U# yCMmY= fͦhͦ f6R|߾} F,Vn$ )uuXauĺ5kSTAF9J2Q¡XKcm^`1,-ZإtyBObYG Es70hQVGi f|΂GT<8ZmbJ*VU V'QH}Is/顾ү9A$"Hj͢,rIhEE+mtw-c@N܈ų_ݼ:F(Z *S½rnn$GFuQNMӂmS?`**w\ JsS ` _-t4F7Jeyp%Od)k/.g=74XYFRv}x>Lߥl7`P?q~ +6$vopA ث tT5W" kwzM 7 2# eQq?Juw:PgkN9h}oJu a.:AYӪh1R/e/UփTTӾ1[g{^gE[ p~EK=ב@#OUΔ~!w4̞N s_pɰqv#_| yUbud 40Y{1>7a<=)_'' 5lH,X)`E_u{V&HY%{8|*KKA0%WmI0HD#.nMb'BEoޚ~ uup|P-Uaܚ{!)&D\`H ܔFSZݡ2繄ʕ̍*\E%fx(J*Nu >- Rn'j6XS tvj.uq!AS E|Uɫ8c_ &a_iit"Qgq-MAE٦^w5_` Xk<&~W7Bh-e&Y̓WѯBAC4-QJۖvX]eSS('|%'/,-NOOմ޼ҧtJΣb'8Yv!?eR?OƃFi^4!sdM v<>=72}}Zc:0Ί3㯙GZUb+bDڔfvHnnnH\ݙiM,‹FV͛7<-cM=bw>y@:'h q$ZuxGWm|Rs@[/WxA얬R^!S3RI+W*̖duj*/+x(GGG^8@[z{S$ɦRĥBkE,+!V:'ʡ^4,Vg:WuT|7twəSRaʁa?u_OOOiK`#AB5bD.5Aޱ/P3_嵐XS^R71ik@)C xNRҵ|Hϥefo͸nnna_!zEf-"ٵ{?+2 FIQfu3͜#XEbV$ $.Y>JeQd{Rw.sխZj;H*y6ֶM$z_0(*z'FVAIvn+|<o@m 0^]+{q(mz}o̧Y2{9w PMԷ yĦT׫Z/2A튩.6E<' RGtǃBP"s [%o2WhN{VP@T3?wo݅VkLAAAgOPcmL,.)t}kfZts/;o -ޗvei:-c!dY\Owi&׏_y0f5[wu;L3+3A<jkktCyi*K۷oG~rj #Ygu̚UuYcEr||\yUe`v{M3u-]v*ku#X/_hɗ}$+{}\\B鵈fՊc UO}b ܴÍZ Hq>T^*u'yEso$@}Ulz[G%1*?ȩTR&6` VmTV[DSP |PðQQ\tIۘOrKdT 3͟'[f)JFE1( _*)P.%f7-E ._ə¡/A/_,gyFXE$ʥ2?rrAE fы_>-hphm`x=k_"/Bhy;WWW%BT zْLa TǀQ"~ YT-YWrڻA6xnSP}ΟBCSk Yq]/)i;ݻ. ,(K:'+$x" x]/q2Db0T꯺yw[$& x6R|_|YJ| 7'ob>+%_әOFr5$ΝrAKe~o߾֔گk Y9?9P6]//W:?bN] [A<z}tլ!wuИ1]K%'% ̪kSLa VXˆ[Ή0*~wV,EqB ;VD+@B3LAp{CwWB燯LΚb brBC6.C؈JQޗdJzIԧKF'`A[$]Y탘wڀ M? ޴AL煔]磆Lb!cuol4}Kb1T,-"N3bBAA졌 E 4`WHVs2*{lyB§ C¨u$?9`S+gOP>0캞z(ACI:,ϣ]푝! %%ג AsTNhz~u+ey@<=I[ !U^zKy08+A׎Ew zyyKZ'WYr|hY"YـBAXcSQƲǸ`&* x,['j,,S_9ۇϬ1iAAh\6+6ģU$.WaBAޡ7t%e|}|+caAP"x9گڔrAa* nQ[Q-fzsus+m4~34L)Q=?};wɲQ`Jɀx9zWVd4=nA0Eh|C^?kw1,~(LܗES.//#k~ALc JZS:88etss A;V)?=<S<ٜ0^0QEҕVD[lr2_p`e 1ubbb <@W,XND nKE*M\˨@MYkVCS3b=pĝYPˤ6΢Db{u\-aFW^hzőڈAEN-EM5:Rh>ԵAev/݅W5K%{zz r׹iDvCR*ww1"}7DZb_ A˗[x"8k[s UU@T &|#▏+ŒH˖QN⭤zLiua=^] Ur. 4܊gquuӎ@Eݦ ̃$&Nz4(Xp367Rֵ`4:L1ܼk)sȚ֑#ՠ\-D4N/_\\^W׏oJu3m*_zh"#vu+ǝ[y`(P+#;RIa7)~ㄮ޿˿~wwg0o߿ۨ  f_^esɣ_\T 3mjlqq;bA<3y 07a5Nx0_7aC RB 20x4E(LL@P>֎&@UW[좒r[׌|@ۭg0 hNq _ _ XZk:I L0o!E|zGP =Jo6i8GiRy(ys(cws&QYJ<5OFxzS>O;"si)n6Xi4nKQ^ww t/^(~Qݝm8ʄV U FvJ‹pxٴ~)xIDTN_t!))0'uaNnp- |A-G@;eRcGNJ_ W  "=%7SHw=ҡɂ1iQ&թoσrR-vd_.Z)-6#Qp_ W y{wWyTA}VlB[ NCVXOi y"%.UdQ!A>?jZV .| BEEѼb=MgTYfN1V~@T 6hK˒u2^ӝYX`!sLnJJXW,-}?R>2ƽoCMwSӷ٫cr,_leXdhJ 6~ԓNz'|%A5}VͲޑ3cWkeɑEyC^ Z@y@/v\-(G93ۍ[lգqY/~[3YYarGiV,׬E}ԋx}X;".JL7Fu4Ua!TW,VVW!c3WX/?s+A>|`4R ,Ss uɬ1b0B$O'+b.!s7+uu+uؿ75b_(WL巿$~%g@)<ɃF/WCZ]` ~r;*Ҝyw`~MgigsƂL^aߪ!`'j Q_!2^AnD/~W xԩn|A޼ (~l/p|.`5 '1xrNY`¤,-C=Uw+A Zƴ% ˗ajMVJyַlѲv9]ḷ@F+5ur@ԇybY®yerbWOʯ_+A<}( 1UN[hej{Ԅ? K(橲~ V_d yI7ExZjn ϡm/7g  k[Vw*B-1gQG ٹSbDǓf^,:j{iN\t W5`sEs%أǞGNOO`::˗/  踊$6g,rQYKYWMNt꜍ĩ0Cs7Oo5/d0bA:n+>7n}Dn*dEl*s$9yµTܙ˃C߾fR;:ѝN}t=l*͕+n3vgvOF3 -nP=4@Yf_ѵVazm\ozz+ "rJ\+女RrNb[#Yx(-4dTo6Ck=o#9U2lt997:xJwژd(I++A/v@0GE h4jY=?Cuwջ61]/?huqaSi[Vl6^םՒԧ_S45"O&_ _ 5{@ 43}êbir`1s|#J^hW ;;PDB=_ܢbiҘˤg? ]FB8WJ-"u'ѧ"4Mղ_ `pӑnr Ow7 @>S0<5E(y|ynFAQ8_ M=1zn^UWíO FqSS<Ͽ 'U)AGXhݝo?^"qqq}h:+DϹsxXq`8~GY7Tk49~QO~,^MJ]m!+|%}bl~uRhI/2-*,M]Xm"^_b@)a/*;C#D .HifvWVK‰.`;q'69)NIhdUUy.yw޼L+Ab60*קZk g-ݬ׬ǯlWL\ ֭VnʼdœK>~(?X6`ˮ]K+ZELwvjȺ3W]|(zԑ2AIɿ[F'.:|dnvJ󴯔U)bYYak0Y/&޴@՞թOwY 5B? p&aEœHp*j?jg-%"C ~Q)EėX>}_ހ8Xx4*.h ~z&V{K /M+ZZQdy>0.Ll E4_!9qX|49̝:;o<)rg4h+A,u]qlm`bkKr[TWeol_polJYQMHu60z푧_c|EQd?ѯyv~J' ܸNޟ WC.yQ oF~Žl?w [o.\Hͅ+f-.#_K-|b̞^yy+A;%$*[U\KA-o߾kw%z"y- MkYx~/^V;zuhkPc>~.Ա<>>V@$^(bfH"b]݆o7a3Oi1C=/uݕfJs+{i.SmM>zU/|1)YLjˣcOe \a,㿥kP+A+n8::bYWE5i)J b-UVh>bzAc^~>_TOAo:@тBHD/T8xʣ}AlӾRЧsW$ԋ J}Lmw[jYD=Ŋ)16,2u¹kg(]BttEN+$7\B%߀w &>z fk_:~[ZS# \c+PR/?۲Svk%6{fPcƾˆsZEAj+ 7 b_Y`; S 'iYE8Uw^ڏYW`JG2g/W+΃}j5,_1ZN3\:+, j]/_G%+Ad]#YAI1D59>`3^Vǻ5nY%_'Lt)|a<ށ\ /7BDbAʴ+PU>zIv+޽EJ^P(e(oޖz!1 # vN<$qau TgzGxl +^7ӾGc/!_ѐ1pZ E\ 8ԛM4(~X)Mb^_= ߖlW Ⱥ_ "" FWmE4inE&zuuzS)*pGJɌȄN+ ܅{6+k[G4P")4QsJ)QToVp}[ $ @$9!daw7muyyZJ+fLMl-鼷5M)kpAm@|z%X^>^.ךVPdž\GӖM8-cQRgJU ,..ֽX 9Ҟ6e:κ9 H<z`J] "0zۥ#7k|mv׺inQ [[[dS#OkIZXXM{x^]<Sj@|z%5XU& <ܾkDK%H)/^z:DJ曦 JS4G 7+N0Z˙]9B)Cz_ٔDuQtcYt%]gdpvkoU *w&kJ$q n:ybݻ] ۷o.% + -{])k׮e_y7z^AL>vŋuLqwiwji zGÙfNn57^AWo4w޽}}.W+8uwxNOz>Vd^AW&~?VxVAJiO#"}T=^4od"2@)txh>g z+^9Qb+VLQWWs z+^9_zjUr)DW<W>~RvAWc-,,8唾ff$'}Mh WޞW,T  WW< bV}2 ͡W+^^'W耳9׮W;_CB6xi8H<4聝4a_dT# @W&H?b7vSI ͛[[[nݺO?tܹs=-%>oɍ7MEsyasccFGMmOĜX ze+&O^%82 |R=Չ4õk~:Ŷ;h :?R6xu+! kej˗-~+B @W]B$jnG_ >|9ꃥB<Ů\%^*1*}aCϟ7ω4-3ce}V3\nW+SW\̡iu`_4:c}c|O w@ xpDEkyF"c&  96sSBCT:QP:B_:^AL} c$~]B]˗=wssSfc鿢e'OpHH^KQ\?9t KiLNz++zwO)'w-1H Xcp?k-յĊ=ZFokt}mS#]վns:%ׯ/32TW$S;šP *6`H3=3> U]9u|hcG-ik֒$^M;z囩qvMi{8L/_K%A==<>~[ y82 Y,,,Vq#IKnգ=cC䛉'rS^<渪32aGEmũh$b ׋F|^xqJ7㩞ŶտVO> z߶O" L^i-%u2a8ӬW{#!BeZ|DI{NdRW΋U4%(LTk$#Zfjk׮[aWT!I\"C`;F桜)+-Ajr qn[uz˾Po{vn.i+(_]/;lŅ%|bx헤]e%wBIf]"W&[ĥ4Z b$#'SƆz˾Vǭ˜wBWotHǾ2 `s]#eBWzB|9ǏSWL/WǁpDs4%e^v`j:+:{U_vMe_Y^^ΰL!Mh6"+-(/ G,om']\\\~zq@ˁbxckKva^Tj%m2#7"cf@b"pql`h_S~k#T/Z˸BUmK uշWj>:m})E^)+5[w9)wH9+!+c˗/֬MZVC5d' ȯŭ"Y;VÈi>m. L}<槹ShZ"ze|9+++_9mJy9 jJQ{#[BD4wԃf|E2E}z``d0\dPB66;ze/zl`_^G%ŋ|3^h,/3 Fp/Y|z9:W8.Om9o[W+dJMj%WR@1!˸pB /L<[Z҆qZ^3HףB@&!eyy9~vXN^ԭ&hVȾFuzQ+~4ivyD̶Fo#e^1W} wrE(0|{Шhm 49c=2|z4H[@q3KrBDHLD=07,2ӭ[dʳuh?VȨ6#qC+Hѿ:J{ ϶mC(UaxZ~r`+&adGr*SWeDғA8۶^k;JH^LJJ5%TͦѸ59gǍm)u3Zx@hn3/zKHaPiMtwwR/U[t_GWjF"z2흚`qHIWkT5 B6Bnغg5e\T)Tx!X$ J##>:}QıLhmT A]}%VN$]dBW8sMPjϒ&cM _}EkkkNUojXKD3|q!0UꩅO.+ȷ%CYE7 ^95QbaZYY(gzòeÂYa`zEV& [(/fSŋ])oz%+( 7n6ٸX1hS)uSK]k:Ú?ޠvׂ^^IwrLaѦZNԋm&Ym\[{ꕖkf10g?J^MN W$m; &JEB$4W,zd (+5ՄwU`ٶ|^;n|ycC: Ym3"e}ELSE4%G?k>5)^^XĈ]j>,V\uތ%zy!hXښjEߴrl--)赼orfuoVojpo 0JGt\?xΞd_iWgWCV `9PK[vFGhݞ5Jss&V+^?oll-v+@WNOČpq:5>VvLu[UyWSmSXJZ.}#=zrwEruJVvKKKug+0uz% 8J}¥ݴ&jљ>YYxPt˒AO)Cٜ^茦W~kT=t_A/)8"/㪊6HԀg Ww>ވ}~+z]sߥf4Uk,ϟ^ޞtuʊls ^;CuPMz3 0JJ͚t!OeO-xT}srg&=7l9j>+Q ƿZJ\/V^8FA/_tj W>+zĵ:*/v:qٲv7 1^9 }()Av]sl]3BVǩe2T4*ؖǃRЇKKK/^Fe-x˵'zu@fꬃaQ{8M_ѱegp)*1i㏵ f5hd^Ŧ-QrxOĵ?i4NƃξG0g(/߿[W ]9tZXi^TJj f-1??L *5ȋi0tVz/{jN0$^^czqq(NN4}Q& ˗/S:}iI2aTի[;/RZ$va6] wgDL~].;+N/L'R lЦfOJz̳2͍&^-0yiajV_6\u.2 >ӫWC<Gmt:2#¾_ITNmv̿}z-++aOAWRgeOzW+DN/^ԱzΝ;+׮]k-az 0b -__}ZZk|h` z4$K|&MkξW~w^Z+bii)ϟ?*V2j{Q޵ % .+'lc־=txW޽{ }ױy ]Ar3/5'Ibfxf@LOHgr$⸡Wkr^# "Iqr}`VQᅰe ^-B⧑w2s=WW\ЋkeJϫײ,_ʱX=m{ի(_n޼)rΝ7nܺu._^ܯt?~i%ʔW*tHϫT7'u6:Hj>7 {cJDQY9I= N_k˗/߿_bEem|z w>,jHEL}ŞLvP0 Qc::B|>O3ȗ96/-MZFܖ#۷W=zM\z 0SW{?8lwImY4^jj khLLkkوM%mVU$r+O +u]CJ5;]+F^x/|~TהRS6X$}Z;z6tyix#w5MLӱOHvnjpr]]wJ=Vrjkђ]{n+n<+zbthԌh ?mAL6qED%NNLKWzEm$JA"~ ֯8&7p#b3,i}:zeiiiR3 VN3t'|9u1:a\4Eƨ)sw>7.@G/p&=;bW&ϟG:ÀkRk:PӴ4T+u0XZZA2ٴRΧ*"st?C%PӉr)j ze:q3x;]uɈRZ$u-;'+JQp$tURey^AWG gkgCS)M&Ӎps\ `*J1¯9#|Jڑ/^dn5n=2[& UKquHW{ۅSIy93(}jny3IJAik[>- TژV`Y{_\?$JڼE*H=3qGiz_J<QEjJ#"G=DO\-_+T{05nf W$IaHI+[!>15uf33 IS|z95G1I+٦+N c-z="u^Xsl[^?hr2a iZ ƪINUœ[V<0uL3tVw]C}d; ziEpP"uIR z'@M''­f$.>H/..f^AgggA1ڔ2%{L' &r@WF<++CRmfZlE\XXxY#O?z2gӞb^~ӻdI3B*-^ YXqtMvrgDyxD(CTsss1+qT*/zͶMi.//x^htV+2!%:#MMEڵ\N| +ꐢWjE@W$J,@xumZ%Stl;3Lm g[ zeZ8*J|Y,2[9Mg1OFM N?ýϫmH߿үKsvl$Mt+xjhg3o#۩zV YDO>#ҥorhN5JԵ‚]X^~} do$sZ~T `Г1=+yUZz=.U,--p믿6%E)WpnsjyVj䎛㓫!$V^Հ-ЛC JMMS<4ܡwHh2bEpyV6zeem@b(Er5c$y1^>:A{: gŶ4ָϫW"Ek'fc0vYMͩWp4Zfyyؾ2D uZ;6/>Ά~e8<+MV#(ƒ!ef/WlȶAQT~,B Jj>_ ˸Y>/KTKFhN!D0Xw6z/--GnyDrO{ggEcnnc+|l{J3[';/E<(13\8t;mѲ3/Ez "v"u=Sr33$9J$fl!CojVfrT^ u 4\gI +jE/^Z4̳2`陗=r)(WT$8uh<+6œy)Rtղr/;%lhoyV00Kє?)gT¾2zI|:*J spM۳'W6ʋS/w}@Y~xO?yݻwo޼ݻ~5Zcw;wܾ}֭[>? I^7hm->Rgگ&7nܐbL@ّ@S鉫W>yD_]$nDC[GQv(Aҡ`a|q^o-f6@?>Wt}u/L) MtPg㎧z !V;ollH*݆3AgW^*QũFgyٕh޼QܥYĸoL/8xȶ#PpZ'9Wa^SgE}>ՙ'.,:33J,S{|%WJ>24QV'E@V& !L^޶9C9.뎂V*5D#zc^\\}8_R 1\|x۷oA@W ++wܱo$|,IDCN(XCTZҒC)w`z^sggg{{[eyZa-v`И때9gƊg~~]HV w 8ɛ˗/9>*Ol Ռ> RqX^j?/9IZęQXt>Q48z ΄7;xkkիAܓjkɋ? ĤאgN=lsK.ǿzPcbMɹ ,jIr=WW677Nϟ{aAx ^j4O>J ~閧AR׮]+vww[ytSHO0ގY"?XL5B= ըɓ߻wO(re_n[V2,)}.z.Y+<܍o<`CEw YX|wvv$G'_eJYC]Wz4Xˠ>ׯ_~K;Ϭ+Vn'g _R\F$2tѝƍ;;;~CYjIm/? =]%޽ѣADTw]MĪ W`0"u"?ɓ'I=XXD$l^[w^k1 W<ٳ~͛+YTfggkB/ L^իW?~4n>|Fiɳxkk -W`0"sҥ5YO&ϯ6"Wz˫JRyVΈO YŋނuLRWDzݻN_#yV7\e$&$>W76l_zѣG+ʳJ18?88Eٵkn޼iHʈ2 @IQD]}ss֭[#ɳTKp+0Qsss7nxΎ*ϊCS˰gK W'tc|^~ hl۵pCs8 4<+QJ 7W`0lQ2 @p5]}ks Ԧe) L^~:?q;tzbHdR_/O0]yVrβfX,Ip`^l"޲9WJ.8K>~Y`ի+QDx<hJ*B翟 yVr~ 1/|TU Zlhi5}U֙tU Ko'Y]oF[qnFy܊g^ȋׯ_///G9v(<+^9kS9/Fkݾ,ʇUVM_[zxx<"?;_q=*6֔੖QW<+^9:Dλ~O'yG㰒0>.,Y +Q t~_\\LQdCi:xCnҒ>8j6H`1;;e}ˬ OO -C+չDٸ6GBTӣ`*J)23mHNg6S~T ËYpxZ[0I++L1zH=}+ͤƊ}eJ)eSE@5 p(`IlI+鉝UVϳ#Z{r=49@?Dm:+3Žpg-St.ۯQ=0WIt: dW EU>@-_cιjbQ^?tGvjZOMݕG%DxoDZsiiukVUc=uX]/^_O &Tƌ^|N}&=|Xib}}=\U`+/_LGt:F=n(k]qO_٘1$+BSom -Wl%hU+??k&iE+'mK:䀉$x-OeI6.?yOɡ9ʱnFx333 kQr䧟~^фG2%rҠf_%%+++ףHL4V4uuҔjT޸qʕ+ W9fji%= 4GS׮]{ǻwjz&Y4%|sE⯭H$PNQ-qz=lMOz?~֖TO+0z"W W W^AW Wu͛7S6(e=8u޿ۛwӧwRҏ^#*>~?ϟw7T W,T/k$YWT^{bubAQ! : 'Z * WԑuWZab  HjYAǦx*pf cMޒ_zu`M] ;߿&fggs2%=] ߰c_)!1#>|qE,--5?a..A0/<88v L6к `y'^~Wm[V躦AʢKj +Yfff=77 `tu=X;B dž$W^b}߾}.g7y}Lb:H˧C$|;5v԰DA"u1JXXXМx&qpnjo"k$ XI R.\`iOg5*D^~=??$Q*U"D `9 fӧ9xYŧOݻwG^8#,VRhvv /,+W`4Ce`,JsX$+ u `)c .$+?X' yQ.//[pZ`AEL0\]]uÄ i-.Ǐw;"V`,W`xMA&>gk:x 0vA޽`\xꕔ 0Ve~~ǏA.۷o%V 1bE?~ÅVC\X`XY[[k bb1۷InRcuuuffz%aAr \fy r}uH30FvqqOJɠO2SE $D~sW$h<g ΁o6ĸ"bYsښʊ!18b\O+(8ÇVZ+,`B~[8l\yUmc_g[M޽{gE"U4žbg֋i-1ZE8@`H=$)n+JtoM4-Q3+<#kTŊ&VVVT#8C?YB$FXhfYeA!Y`xZƕAXyx\ynn"_iZ}땵yi*S4(!-:$-bHOe/j <$8::__xsϟ7gմč6U%-%1,,,dzeCvgggkg^~W9 kMHTܭWm'⢟0|fF6J}Hڇ=B`D$O|n>Aia!!,\Dsh… =>|^Y[[KrO,h2rOi/-H-;860[$ pHde k/)С>ݙZFٚfk133#Y=۷;SDzECZ`fXi3 8^~4338o߾}ݻwW`xꪓe&=0^\8_8'0^PMƨ(5-JAO>Y|2;;J`f87"PZ$VVWWb?8I?@dʯpvĸ{D5"/e8cp.~Abe[8E }7,2k2pyuc4d8OZ$Թ94ôFX{NbevvzjPmJќD2r 熄J+KKKiEppp HHJi-' 4`P*5s5#2??/ibJV'λ?33377WLӱ`\sS*-ۉYx( P?΁Hw-//`,CbAᡟ=}`h%ݷ^xÇq:1+>`,p-7o4%?ƥnJ֜t.?ujxǏ~dn:gbwKVOgggGz?M猺ݧ9K>}y]7o޹sƍg]2]Zӱ^OH1Ȝգ3h4nFP6%?/׿>xvvv9*W[tңGrKOyv5JD+#_pSsOY1W'AB'DE'ٳg:(++߿}9Nڲ...fիi ѵ}34}aި^Q򗿨kT7M/ Yzk׮ _6N޽{ڲd}u>AˀᎶv?9V#⁡JڅvԲ/&9_q}MTζ䅾JHjh¾M6K m풃Ա Soy/R-S̛t-Pݘ:Buc GZ3ӄwGW#7;KaXEea U:+m ye⼋1=}K/fL?}u>5-%a"Es>Isu2uY#MxLnڝɿpyߡy⿢ uHMݕ$wPfC4u~'vg,a0Ukڝ5ÇDla)+QC(-L[_ l'v`4SӃg۱p`9ؖ9z9_{km AgOC?~Q6#pOG/\) aߪZWWV8GKƗB%Wa nRݒzQu6XXx=Mz˗\k~mfffaaAmmڗ0t0:$ u(6rsv,amӋΠ9cLV*ޣ55.j55`` u*yqB$d8¯k-%;cKǛ|)բifʽ=O|\5:Ӟ. jF;N8/rY|d8̗=šb2>=I8*z)+sۀLL\=3@.ez_Yݡ$+_r%w)mq($&<nҞ(q*>+HF$eń[{u3o]Smi)9ڈ6e9r#<ޅ>'D>Eqf:LդNkn[Oy6]>766>}h-?ڰ1(6C,dޘp#]]gN[^t2<88ȴS[/|ZI#Ttz=ZBGѦAr |nF̵G3C|9q}&D*RaT]XܶX:?hpm LmhAw7}7#Jc_c!,s>>bEh?yיrńNΉE٣N>ڔŊ6nvmVY1xlF'MK$Sm5z &ТV[Vdn=+WF=]>={NN"C_5OSJNN螄8V'Ot&HN~h>;HZ=)|Y5nA[X/-Z@W8\5c+$[O⫍˗X?Y|> G=@?9Tt: JL⿩<nqqѝ&ѐR6h/_m) ,|*Raj+-탒8N}iǑ'0}J6Sja=m{Y%w%l=eIq&HZ& s]r;qH S#D["Q=DwWT N /V0&As[Yx|ZL ۃ=d>AvU)z)Cdl*eS;0>(9?)#nIbCC[~s襨@3}Fo?<3| 0;;{^e %@ݿF+c_zL:DnTK4i|=G.}N˛$o:h95T;uȑŢ£fj6N럒'ȫ?_K6KlH^No;K< ^-iY0??^% )r]ppaAZH9+:L_~qXt>4<*_K\<|jƔN;fGNu0vXy|9xr$1btY\\r ԭ ^~Yjjȏ=ۣV#qSiw1z:#> -_}Lﮬto_{k[P奡9>_^ܽ9@.v.?6OkIUm joo/1G൚m" NȣL͉1#Göeh}}]W~UUuU㎻Xk6_`>lۯyN|,Jvwwkz.H: Rivyq!ƙ<wzM%ݺ:89ϭz^2lhhC~ͭ.XƃzkljFp>C$e]!gV[Ќ8v3$ڡ`,mHԘY GD4ΧyLDC2z[UOe,lLYu<1AkfWhwҥ% [N .]quN nAGn"O8cfhGcKy8ƹ~QHZݺD[>1ZmW>f-k֍^&ٷJ]n>_{?2[Ԝu F}~48&[do93ϨceCt>=gzCjjhvDOD=A}[:]R.vtw2333GS.8K1 .Sy6hRh؋m*֙WAD9+E,Y2,rRW0'c@Ƶ.OşsqE@g>ꧧ6YEdjs&SU}Jy))|ޞΧ=,?HHX 좻4B-iB~ڬmK&\cY8X?&)]NGgqq1KdիWvܜ^Rݧ_.Oib6s6byyQZ99 ŪiuȎ!ƃIgϞ9k2bCl%h:|,MRl-Zf E.X+] BTyXE% a$۪#>~Xwǵk77Ar&666>|Y_f!Vt% sЅ#UbooZRꮊ58VNs'7ooo| ~8" I<{I%Y.]!ik =y `xjGxgvvz/M3n(g)YԒe" 8z~4yëWۊ00I H1t J`pǗ>Ւ,5?+ovԐZú$&k=Zb<gF''L Л$KH ֭[O΀mIGT$gfdhƖj)ٶdANC焹۷9C>#ng?k@f<}]+eH氼f+ZQ2ņMGjFޮ>F}XUHgeJ1yt[M?#2333 @n:'NCO^~(b*R-7:xl>%=ip; )XJ'zu,(mJFe 7olI 6[y\I71'`s5-s/l>teHf?iRw·FTeyyٶ>y|u\9薼~Ċskkkggђ8}ơ677oqI{ppPi؄pN{9AOOR an X=|ǏuI1|r.؄ʑ2ՌJI#>ms~~0djMqnRgg9/SfcU؊00KzH8-z a_ckjH8 mnnDz7x'O._|^zEQ7T֖_W{Q1 Q]-#4GNzQwMJءO/ sAFi,Ϟ=qCV-?u~Ego,0{[ƝQR/?8w'-V$") Yp7y'ahZŦYI(%)È*z8X@2Ůszi'.˖]nmHUnRߘ,V ;M\"G&$k- ƆDɳg,MoJ~wpM=ne` ~^3M7UnO-ۼq.7ߵyNr-GO=el>qՉ;56}EϦ1aprJN_M/--9NS9Iɱ`k=s-0&(y9W"?V4ф[x\~gwx¦=(J5+9#1MNj%^ =g$tф" v$?=z䴐~1PNK5>(X)ZƌVΰI9-i3R^OFt 6KmE"0]7:,VwoR }]t#bxz4_w; B{Ӗ,b)[&?ӳ =l4\?~􉐴pf}gY֊H#g[NS n~~~ޖQ¯覾u^Xw9ߣr = lrJb}ṼUJ>Ĩ20\XV,UE^?<֣O0Y ueMHv\x!z,saaAKKKp|d]KI.ݘ?^'Sݤ[BAu fc̹Z@i{/N4?P7V'a-iBg}~ŘQU<0ѳgn~B陵Eg㐽|Lh G*#$77(Π ߳N|ݛyuj]?|/k]ۓWEDo;(R=g{z, Zñcv '0;Dɭ6HyфJzNTm0[l/^h>7cfwwWϟ?o_o:rpp_wZW e$M3F,..EFBɓ'v[_zZK"WМK.W4ZL^իW־)~EXsu-CuE2ދVuRNte(Jϔ6zZGfnn+>2t:)yhI_?~,=GVa^@j@ŊQnsss~~~vv6Fͫ[m]Lj U1 0ZltFo]Ƒu_8DMu:`&%Cmʒ<LXS,R\лxla69XR)[??_Y,0X$xҋ/-3/,0F't1[ePڍy71`2Kɕ+W3o `KennΖ i'vGpqCZ z`Y%)-^ ^xFI\~]z~聐qe]9)Yxωnڦx D2OcCB>ڊܠu)v_L~X=eZigNH,ҔrA" Ɔw%\2~# `Ye~~ʔpĔۊ:v"Wvd/C (RӟtBW`{>dZ9O$ˠz_83kȮ0F G,}_% Hq[ `(tWWeer͛TBeFAsdKb%EqE.ϹY}bn߾CX`n>kkk.Hj)C޸qٳgnDp>4 T d ~dIcZ-+YBXګhs~!!ܹsŋBX$0|e}}}kk J%ƕ A$ e1\:'V8A3CL UBsA:gYe@ܸqZ?wEp)%ppNK fwww>}:WhVy۷o!,XilPJboeA֭[?͛7jRO=z a!Y^^f[|XB_?4?Zmh;w p3g}PT05BoC܇uAZFh!mLa 8a4~Ǜ7oߺu B~OH(Nf}C޿OB !,GGG2`ĵhT߁,3@R]d\tl{켈 DiGOt@Q'~UbJt)s@XҘe3>rN^]]9^ ]`$ʯx&.)!Ex뀵5‹:rэ$84fi[[[[eyf) k9u=П@L<2_)dΎ sA@mZY9,Ϟ=P-ye%sZO* ?AC&) -YW^GEܓ t_-LP).63%؝h_/S'TP[yQuhې{wҥH {N r9;~K ),Rh Ev|UW,RuU)s \L[LCv: !̻^@كzt|fOHdP+"hT:5YT 0m̷W֔6\y\)'ufL\mt+wB'@xǭ-=NR˩1‡R|%"5s3=eΡ EـFQ[}9]!ydF&/MսR\|~nJ(*b3>* c$58k)z\pP ~> / $εk|? *>)u:synoo76R "7GIٰ#a), ӧ~7n@<~8mCX)hȆ/fbqK]8fݰ~9QLIE++ՋЋ+M2icYZEZ\Cd_rb* {EFy"MȷmA*_f.i%m! u@ @,!0ם%׌pK[ə/oyش?榵Fg\I(>~tڻŊEhu ? Kc$Rz#g[zҳ%v()3p;I[Pf}I²Yf1UWK*%^ʸ 7oޤ w}#m!9crN_\XS~:% u!BU4zM4phss7e??m㧎WIh'xT~:`kkK BSNH>-~\F jaSV'h 7-كW;*=̻̃i}o y[2y0o^SH@q2u)e\ptq@yauo:({&)ʎ>/s1_dkcQe'V=<]1~G*RMPG?=nӕ84^?͹E;w@&W0>FW ny/ژw;n/_)mIj}+jE֥m-~"26yG{0ƨ!ݻw>q C+4wDJ Q֖4!謬ܿbE07G{|BFJ='s,(!,6 $=_h-{{7߿A ķP_H, !,[^={{{W\wދ/GKů6E(Y^!G_h~K!T Mɣj B8JFSé} +޶B`ooo}}}4i( >ؠ "SB'[rܗV^(4gBFE+%BvA¨MQ-!A!*ѨxiooO@'Bl5枓]!4PhRx&pvZК{C-ˇ1cj%QThS&)?S/n2LQ6=4JQvTY|Tt)\-"Բh4R8|$p!٠L N([sK҈D+CKǃ7o]0$8ܘD'\89k8᷼lNf,VHj>fcc :9JTN3jj4y isxaV*=kי2Ơb _iDpMU7F#%p.-kkk@ OXڻMtN;wa&JUpIiҞ0jl8n~oy$Ba5jlĴe{;VUFR(rxiNŝ%Paŋ?1t=մ0P`}b8! v.f[0l/xnہ5ZZ Cn TEhFĻw>C԰FC C[V+w`^p^aŚb΂L,E:k7@\Xiln~RW4PK=zٳgwqx #- K}}QCO)03:FTDRY'KzH%JdXmQ9߿O?ݻwÇ^C6tܦ?AwYBFuMHNk}B0T[n=x`wwɾ`!p4aZXkbb\{I3fiq!.rJB8%d1 >^sN3AR !E&La#A˜"8AvBSGґI(DLJ!.JbFSA Uymb B,hInnn&J#Uχ]C!L#űIev60UURGm̗D[IBck[Of7mOi߯{Gnd&AmB:Ǩ )VbD !sQ*߿gm`u>YrXGP#t,AʹK $}(b-B!.R9e_+ C5OTB84ˮNPmCh } Nh{,-56!ʔe|;CjeV$ Mٴ6fT}qY=e_ayg\Qe/լBO;Qr ԕ(KQzq)o1P3BsTJ\4 ͂\fp4u{M,({rG_!., i2IٕF\+J;ƆoBF_\|¯m'HhaQ/Z O*^" GX1E=.,c) gĻ1S3the]pOvEE$lGwFo63dl w-Kv0ŇܥvyyYNM}r?99[VVV1^ "(dVTPs|%!ŀgz& 7qY~rZ]]ejG>"K-4=gc2$Bᒀh4 z8-9t䤥Jݤ!fzVw!j/_^hW}K,aW3wHwF\ %UBÉSO<]CuW0*,~ Cy9b7M+T+o MH0#K_|Y!@c\\V\E7β*#KW~|X[xB_L Mה]\s[7n/NsssF:*6yF=5^+Bh+eGU݉E*`?~ }9oY %3 J( '#f>׾BCN49F;N?KBi{r4w;8iE @z<|ls|O%V_:C9I4]*k nt+蒢dOv󕖣Zt|+!>ߥ` 0_BBknoo.sAa/ȧZ̜|tӭ@IܔB `چ-ȈYE^26j2K璆ɗ N@lCFyST4BaS*(EYf①Ƒ}\Em Ct7ǃFi2Ɯ8%{7%\#o 9z_7{)Z ܳg/GٹNl4FiYy M !002\Ssl&-vz&]B h6,4q!āBz:zF!C"u$nJ!9L x8 ފ34x{1WKZhp)@Ks|kc0BaNlKY.-+muҺ`e:~}GbN}\ΖEeecHizIܔB ~q !Α߿}ɐvP|CrxxxttDRDL!fzYZ>~<P$ \31 dqpၬ/!B8}31O[r)B8/d G  ]|>asd !,A74fkkkssɓ?(T$ȟU/$B!s]_44S.U!% m*wq^yuu59C4YGhHfZG`!nUn+t@ Fދ3 7%EZkdxb5<o޼Q:q)}0mzk|KEөR:[tq^W `-Jw>W|!E]{> %5 iSo:블,.Q7%T};8iŽ\詊766ʊ~W}+oqMhC㢍' yq̯(bp;c^屴"_,e>\! F}ro{vu)~% t8awx W.roշu?>^.9g^[jM'Cr7HoI2?RŻSȎŗ:FZRC!,4O4 5sO(Mp>˲ ǿmzp=URm$P0Z\46aoe,nȑ/ŧ|B {\UcvAP-+y2i5Qd/*ߢ ׯ_ǥ;~K;o$ߏQR%( h%jl2ˆ`ΐ=x[F"l 2 @A+-;\!"Q8{2tijѯsfA#/|W`}L3Y ^v9$O' 7#d{{?zţ{BS)=(tmWe!`o\AgNwggG(#N˫Wx+\=.'2H7E?$_Si9ĕi# P0H'&"9 3 }+imq1`?dҿ}B!,}匉U4W3;8MT^G9"yA_BV}QꀉAoSLQom\N.'vm!07y1 Xbc@]o=4gyp/^_0CrEvE<&ϞLBW^iׯp) / &ExӳWpId2E s!HbE=6˃DݛiH^'s@FѹjDI"W':1oRcIBqIvŻsXݝR* =¬rWs4i@./C+̤ys|! 4.<8fOhփ()dphR6B@ՃwP huH,~SJsOrqan )4eh(L*yiC|FFw).7n\a߁|!I,`רewD;_lw2Kyēyq_›j%Q1}yΔ{xi&d)9T2#"jHd}) v$^vEp>BX0V h9 hOw 2Q_y-C!)kT|;t6OJ!;$c'凌V~S|uR$=c9B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B?߿_>#">|O>𴣣#9Et#^߯oqw_|[>ԍpi y}ݻw0^e$ ySGg+]gH'{] <$9px0\N۷oưΪ3KF w~{ppp0\8|S澝?U:ai!'R+Ћ{}M׷VJ'&<@9|_3Ӷ}}oNlB\eBz]T[,//xeeEgRz ~YX~Z7R)W^:;OQnh UyxDן6=p8:͇bO.tLU}0\No1~~ygJ{SYݙ+J<9M9죔O\M௲QEbYZv(*Ln߁ME4K666wss=WN@9KR:˿-,6xhpfUhR'VAxiwH*EګȾ .8Mr}?dej&cRgO<ן*=z|NR?Uzv lY>HKh'͛7W0K/Ň*o}a=!O,mf^tSZ|}EvCK ,|&b޹e4W\iڍWV.ApWk?o_9x_/Ӷ}}oð&ł.^ҪHQJ?gqw.vc&/WNnHexsÎKM}-qHOxე8y -ʉ[y=~2֗ϼ53t6~{sdYg>JdTV57sn'xӦ귝y.;Ӽӷ﷯ss(2t*]y+bvuv>snyɩ3YXP\BIh9I"q}o ܗ5M)Rp;Cgj:SS*?!uxwMO$1ȜW5UCI_ ʉ2_߬[_>1,=y/3$ɨ\ms}/D{sྜྷ?m:!y⦥zvoBdyy44x}tNۮv>iB"/Ҭ4W2>,8,_˸w).M]zyrN'T 3UST63Tz;]+͖;M>{rΒTHϩ)yFu3y/*<#~> gO!=E9?iW=u>?v\Rkv7s>|ܼvK+'﫳sv|mX0Ԫ]OWԼBѯJ\zN^0~P奟e^vŸ4|VA[H:Cz:}ן6=}|pO71r;/NqxASgH|Nyvyb:RBg>OtO9zjvOξrLc#a4ӴV?uƦj7R>ܾRbFh{޾ryg:mWgӶoaN 8ݵG&hY(d,}7ظ{ R/PRL?C~'NyӦjԢ\|uJL+eS٪v^ t5@9WͰW >Lw+rʉ|WeSogOξr_*w2%?e~ʛ4|!dI$2S~޾rړt]ϥ{ņH{31m'j)TU#“zcjY>݈J/նvWy _V|^8V8qTW SJ9*O(W)<z ƥ>tW| ɔ#-_"z X}hL+% LPM-?Of+$/=Q^̵*fY?j%=ޕ:)F߶?t W^XlS\~_WNxⲸ=R{2f>Lfj]j2{gyOxI}-m1l7\2eo]븤Ox2&Y]./*.&=jnsxe>2̧AcSZqDhD""'5L\DUOq~zmϯ]wJ b)['=J]v` vu)&CO݀WT\=A@SŇ9V>_IFggSU sEYzs>ǡ:A:^I'ZT,4.8xj5\ CM\ʳWĨRx 9:߻ yxӥMn^ j|U t@QSv?5{a{u{N ^=movج䞤n[ C34l=a40畁(_@Ppe]RQWڿ˿yq/Enp.s18G}+c)\г;=~.+Gx\^ \ħ+JVׯKg}S>y᭜ L+-a3HY<ދ/ +ybkX$u-oZY.RSB>\*`}rJ8a,l9 մ1qdSjMA06,.̟ƾĖNf뉓o޹2yӋ5VIZ9f‡j9BU2A,RKREG7O}UF+˄jQh6lOѼQ>'U>^XAQx[*Qth&8Y*KTze&i*+$N 8-I5<^ZnP)3캵Xhu ^_ h'ŭ>#χD.=H |V%U&z%to oݼԪR!壌F!QlPI$F% "a 龝w]U>VP M𭮩(^ta鱉5@1_9 w&zEآQ5SdSI{zR!QwtQ,oFlY/:<$O2 ,eتvɮ6x/^դϫ][_Ylp7V+UmK*Sgj/TWkBx?_?hưmm2Je~jh`>sDAwOաT6R DFupO:%&ܫ~m^K @ャV8?»/M\*Ꙋ&n`}<حzqE^3>ġ6%~D! TA&R=i;/Ř)Z]Ji3$m_i)_K]~)ˠzL7[5C]3S)׶XwaGhhU$o 4Gx+kUbyvU إ֓aؔ^j ؞uFu*]T-+^jz=s{_|U"k_re(.}e=v1Y0l_q~ץ!+kkOmۊioޱzkO7uBBvɝO \3nrǓmq%Çe<8R]pgX6#U,2O/I |"CJAYp:NY*}{wp^Q4_fv\TN_8C]3'=. G O)ӶlX=i(Weiw"5UbN LO>BK'TːR=%hl3/Y"a_>.[QҦ~w;g8zٟ2@ ː5ujqPE4zJYfYn:\Z2j`Oϴv~FͫD~c⽸ٌ/mzKy.~VKҝ0pb믿?K Q.(m2 (uz.]tmE|KYWd=wUe;3~0OBfa*`U 'eKGs9UW”іX v(wA!`&351DO_/B8R갘1(oXjԭͭ4IG__d?}7_*4_2yٛrS"7cO fOW|MO]dP^?m'p#<5E)YLIfBez9m)KiMKUO X,NWА9j&#Uw/2h% A M> G:OޭK/IK Id- }\{u*[۳-;e;Y-0.>|cy]­NqʬJEg˥,vi%wsPd#=f:]1ڳ4s$6+E7 !11>Õ7Qڛr-jyļ_~EODE~#qQ YTnOo[>}-eyz_1)EWƔ"39Sc %}'\dJfJǸ y 5|]r5bX6`8zEe>q';I ]AWV E/S4䭩\2<{K$TJreQkDq| Zſ (/J3WTmo|w 圾XH47$K?$s7 yt||7c Y2~uRÏ |]CztKc?]v]fH$usٞr{q=DA^J4x TYKˮZ]- 5jjw7m,|K[/X]DEsz'OThkXf JPH߽lViLxhɃ{#)gcei?ig/oL:4Lj,kqz Op8՜o'҂)RwWͱZ%p*ߐ!WaF٨~;9QzU6įYӦM2EeAu3;O3Y@AxAU<}Em>'&է?J,b'jTZ1\)(VR;_=b6c]I?XUMUFna{WuCe?y.r JҴ~aA{=|z'O/JWm)PBKIAA\ezjyeNy[칪1ʋ X̙rR&Kg^7mz/uj>=iJi^Y3w>Zw9C:ۅI#z5]rE˘tTz/\j=| w(^WdU"_uX_K̎2`]S.eZXx9RkkY*Y)|P) fOO͙8@g gܯ } {#>'xQ零ogS}>3Oc9}E,!;g/^,1hT0c$W}Oβ+bL)9eċC;z-]WʀjOZܸ=Z4];qϡ몋t/.c܅ߋe0p&)GWN):₩(XB-x`xiBgl@C ePkL /58EBwTHVF\hO> uvPvy}M!c{{+Ife{-*%2여Z6[ MW} [NH\Qb28 ~ߋu |~!$?Q+}k1gO|73Xs+ACfR㲂xw2};clJ}iuݳvsh, ]Aʌ|fu t?fBe S$\- ȅ+EopnX`4~oso%$s B#f6vTbooObN"߬)=|n+w•21~\sLXśrAR5;elQRMGMk9Xp.C qU >#Z/'-=aW7zՙV岡kp'=J/^i˳s8s&%]88eAŬUK.=/jx!E@}(65w0ӠՏS#6Wyq rNEk; 4fysnu4Ba|wޝ6$x`*xQ*O?'(1TzbV#}Ngzpr=Ry\"TK./p<9QCmyEӴP+-6di c.@ϗkb9?wqfd]cHzvJܔC{(6WMsB!B!B!B!B!B!B!B!B3^^.DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC6DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC7DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC9DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC11DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC12DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC13DyK #http://www.majorleaguebaseball.comyK Hhttp://www.majorleaguebaseball.com/DyK http://espn.go.com/mlbyK .http://espn.go.com/mlbR@DdN0  # Ab?$w.429Hhg?]6n?$w.429HhgPNG  IHDRO>sRGB pHYs+?6IDATx^?-y^ҥ[v!+ ! opv7EBHo/XE@SF*bܪty/Xp}f}3s>瞻g͇'^ 7q엟rCMx~+'ax@_\PY!@=兗v9w>I~zrtI~:=9ݹ{LO;'~^;'J {_B[Ntd{{w>{|TN?>>}鏧;O-ll_ƒBiO!K/SNC0rZg8t̛>ʹwϞbk^#W{طν'=ޛ#]h43|`1gXM>9g>wzӽWq'{/Ln{okI3 Aoixv%3͙5g:gs3mIף${39.Rf0}#88~ۍW>pOcˏ 9wz'ξbV$Ay?DɷmW!D[RrdX9W~~qfx"$ON]'վ; ikioV|GiN-!*G)IɭTt$;BƿzWB=EHdhe0tbCú}hFN4MK4goyzx>㇧OIILhkɇ3Bf^HZ9{E{Ba"EtiTN"'mixڶ{u O}#Z_X_`"|hY1?{Ms&g9)'wOZ w^Y|gH`NN>(?46hPƊ=)ad48Ӕ3֔_H\b.~ YYR::əщ(arbIBwe5He8:9OpF]ߋZpD;/:IG2L<;ךYoMF'~G@ur ,җ3IҾ~91Vt3|9^\J$3f4Ʊ~:b!dZbtr iM7^>L \/"l2OQ5^J-v-YtO@.!pxB]Nw\2 nK$$I wgÓDWmp3:_>$d,gfc[#f9%Σ壓HHB_+i/&ٌ,>3w/~<3v\]t.p%$$e,,>ca7 ;}g3Rs'fÓ9S)YxΣӧbNJWbu׉%VNRtȲy}g:&4=X撈֗ӍrL}A6eϼ~JVJ Ī ir]kr2>AV)ܝZM̔}Io|> { G"W>MP~nOrަr6yoQsExWf4ږ]rzVi M#3n9Ya(;& =Y (y5$ݫ⏶](99qC^~ncm%ͨLkYOC̷ח|,hxsϴ}I '$ "-nGj$Ä&dqpyBUja(!L+B~܏m9;ǻ1Ut}g 7%<~hzA磷AOf!4l,ygG3~ѱus_yaoazKjF<=_?u;(n>ySʠlGo֍ ~C>G~(>_?|Mw§ӯ ~QQ~_}W(W{U}9"]ﺱbG.it_}!+X\wȊV-p%If7O^ovm3w)쵻N {Ÿ?_|mJDщ,|s/>住NE:٢t~G*>Ng~fmn'UI{I>)lZ藿%/YhKOWgٱ,tAJ2R2?kZ?c>OܹېsE* ׻D}$k_ 1dv vEF^_3i| ?wѧq{Wg's||~s}?Oݻ /uo?OŸ9O>´W Qe[ӽ|9՝~kf#o>OH`/~S}zݑo2ĸCs[#oLMo5ݑHK^*w1G䠬M?GK|]▿#'$휴\8h:QQ.vtrQ>JvU^~+-&b$Gu]2]ծC_(;2Dz>x?$eA6+ U^~__5g.JA鮴1J\^2tX?Z^Y]\CT3%r O(nKC/'rԉJҁ}tt7=zmBQ_4iCIwG~hXņv'nhW_uQK'WF8 K gKů7iGS.64Q7Ar_ugH(nYTII&kM'՟A2t*⎸w9ȉפuVH䠓_[ِww^:Ůw.ړ! nNKK)rF`dnEqGwўы}7Q'"9r⪘G0{~ӓ|O|`!}6EgsOH3(ͱO?I{ zי9-wQ4\ޛҽ~%[v*!F`H܏,sW^?7[쉋N\F$vyB̽\Pb#9+4A%k5+nhv!71kNiܻ${M`dAP⛫:!q\Z"ܕb_Ni4Rv9_vtw,ԩ$SVZk٨/E X(UऎQ^dÉH5:+׫MvxJ,I0}nIO~344w뮀h$FqD*fu~Ejtc~|yfRcT|h%q~G%ybYjcd,}q "$._4EwVMrDb}^7o97./M_Ȼ"W ҜAG1ʼw쩌Q^]Dӛn}ʗ:74~M*3v~*3F64|ѫ\~9fp|3X4h;I}(,M-Raɲ^bKJU;:.ޤQxOU>U^s53n֥嵘v$x.\@)gPj+A]>իQL]9hdɫ%7wnyE5_'H{}w{C[@yjCOUG0y|g5~DS>d`ڶKmަXMMH[uf+\03I쀶];Y(%w^>ʙ ݖy{'.kj?E}Ư`Ŏ$6_1؊nKrZrK]anoOn]1l"zn O,{mv^oD;.T>; eMq7NJwMW9%ۭr dCWFHe+E_.v-W")IlJ#\:,Ka^޻}jlʘTj7TfvĉJw(͕ng}.r=UDwÞ+d,{qbM2p缋KF"M +| !uW-Z4967EuN89{cWsu$nw0uM=\epkVb}fޝlv!"=rΝݵI*A uW7u" {L⊯kR`z]xy.vᣓY=>487}A}+ǯ4t֬kwKMcw·DCEҎrSXlwH\/QxBCS˅F-XAQ,`J\r~rR*A r|Clu8 @[X굵Y@#e @`P: r8a0 @Qv̂ p8(\vJE٩c0 p\N`WӭgሢTsr{ho͓5m@Q&L(C@GE)(\@~(J>CEgjV^[U@yܺ_^INy1]GL>Lxbe61pj{WJCg,F^yUe9megOE5ɖ$b'K[@ ȷ[kl [YU஘Gpͩzn:i[K"]J>^EQ.H1v~-8uD** #Z` YfkE6fZK%<u,͘kr bC!>FOʙ幫%zmN9fWke111k)(M2$˱EfE#%S]16!]%hsńI2#BO M_ܔ([Nem #VKV09U<]qgQ朙mh̴fc\,)GzH]"$*' gX<,E ؐ3v?;d Oɼv@؞b{grLx⿵=ˏ;bq<|\\.4<.g';M~~NIJ 1̯:NLsŞi:Kh_rsJ;>-Y\"e8Y`hhWG5)*:ygU$0RdY9䎔"_\i$)5bI% c{2"8S{S3x0M ȉ|A_VB2H.qYf!*&"G[lˡ̓"7tb hz /+{^nx'C:fkzeƉ.LBԕ}P7m1lukaiz#sWl9q!5q@0&'3`f(~\hg:rd AeqZlTf9A^)VoȄ)#I,Cr$vFZDhd6dfXAQIQeJT+-< Ak*JuZ*g$tH.@Ycɑz2JQdi7i2 ph*JnȒN 6)'5^몝]˟\%L`ʬ6GHb;%C%"#_(М+z"V'2M" u l(v5Ų1ҪUڬ)߲EOTx1Ir"ʠ!LC$Ґ(elJ%(?YcSwnƽ3$ɞd X3n zۏ?a0 6%0._=Z!Fٴ@G!S @`P{ rOa' @Q! p(Q<NEٻQ(GvB;e>@G!S @`ƞ²w۱E`\AEq@ 0 E9@0A'EX@I@4@-PZF61#,1Аh2KݽA <񃅊2*q$a#%G?& R5UC:\(;q,n:@uX3/  <8)3qGp  pPc;Sn;4 ^aُ_A WCJoGN,n6F!C` C33FC^53DQeDt"WDH}[!\F](\ @Q  e@*ӧO]qYuK9H^q.[Ѽ=~o( 9.劢JPs>;l3}d״̘Fܵ qIN4)1Dvq=(!P{\q$dCr:R2mdүs6I>w!f,8:⌳89);B8 vߑ0%68ܮ`K[I {d-$)%N|A[Qԕjъ\~Q)bٮ乖L4U$A^e& *˸H%Dk<> tqɒyaƑ]k^B#sٮ乖L7US.IcHp+JNwL3^I9%-YQras\QGr휼C;CŎT7nI$i6j\b瑹N5^7c*&KaEN(-kPk;YZ!#6[ܬa `2\I {#\QNٞ W̘4c蠥?t㱝#%eCLk[f ۺ4SeqbA+mʸ]I8ڮeC`Nkct¡V[l{ݰ.RK [++ʬsNİ[p\[ [XYQiؤ [|ʇ$,x"/CpXGh8٘ 'ãaq2y)Ь h.G,ȩ4Ɇ'$Hzr7jx+3i- "劒o+HVt:FmQ|[~,ZkRf9 ژ$l-[Р\H`}E fO8dC 6~mGLjN~AlN2Y=I}Q1劒3N3^ 9%-8ed!¶O6`\ƒL5/:c;XA 6uH-e ,W`ghdwfLS|q2Jcm(O*/Ԟ(fYs kvjmd dviu2vB X(rK `mϵ2&:h?2j#%x!Ǔ0>.Gӏwx!Cce-(j(WNAz$9X5sŶXۜ&Ǹ,m-s^ƸHQv̀ =XYQ&ԓM]qd@u(1Z @`P: rHa4 PQ_&8bRu%\QMN-L[1ȫMJbo %K Wj$yn(}fc7=8e",,H X(mɻ.T6ܷr{[1YZA$598P쿋,Y P+ekg4)Nܕ9> ͅGd kDGFl)\+AE0T wjɁZ`NXGN&[9:@J)╍#oC#$CKZFQ J8^Jzoɒ CbC` GhY/θx? ',OQ#Y㸝ۜJ T=`<8 t+ p;+J>#Wg):u>bsVꂢls((j!ZMX_Q YQ}peQ>9`9HbqZkfiε<\OJ%XII3^9 56!,#끙%%lP \Vf >KL Vz3$*&\QeA'X:X7c*&KvErX<$cP{8i!d*+=vXKH^rE M0LI_]1iA뉡O. e[=r$ΜO"J?+ƠCiWRmmf1~kYPNH \(ӡ O`eEYL$ ( ]!ÑR @E@:Pu8R  (@XGJ >@@QH) 0@bS'F 0D x I@}L\$ ( ]!ÑR @`Z/湯P=)[ƛ*/~\[fuSm!VA{ݮLe3v杢<}4%sX݆R(!]9K'PQnUsW&*nqە:[Q8id=6dnۇJu@2{ ze" d`g>  @`D7iA&S_Ѱ8Af+LEq &Ƀ K؁CІ 9;J䕗_rq**9꒓fV( no_fuY72~oZsyoˈC=$>~hk D9C(+5%w9ٕo[oxΕɘ*v."҃\OQz؃?]46XϚeq] Kva'^7KfւA;>KЕ5o>[Udbtۙ_rr)L)Cȯ:)G\M=?>x;j C$+`,hv%MkcF#3_{IJZNEX]lXFEiɏtn+i' d|6m%@p?_qA21dk9_IQ!II#ʌ #+i6WNH8 /kzB $}zW,0ސSiY< ?q8t'NN_Zz"6 ,Ah#9idտ*;X=4[:ɕerC'dQ%l`$ MV77b䀲Eӊ9JgqeX +-ېo䎑nQX+vvV˕mF,dsE?$VhvQfY^Y+725d.s2j~ʱ xLš?C#X7=frhfHP/dN񙸓X>us=ys GAc7]]A@AɉۓW^<)2TN#M??jzͲ0ӹjJ1$(om,H#EdXN0ֲziRs~gm䛕JW)v7@;2Uyީgz݈u\[}.]ӊGN{s䯜cFij˄)*ʋr,}Z3(7J6W9T*hە2OQ2 =n2J7ې_2[kP?5=zr|9PI@I@;6Z @`Pݺ r0a. @Qv  p0(vKE٭k0 (sB-e0@#a @`Pݺ r0a. @Qv  p0(vKE٭k0 (sB-7swkA!4 \  @tTnbmIENDB`DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC14DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC15DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC16DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC17DyK  yK ^http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC18DyK yK 8mailto:bradapp@enteract.comDyK yK Bhttp://www.enteract.com/~bradapp- i8@8 NormalCJ_HaJmH sH tH R@R Heading 1$<@&5CJKHOJQJ\^JaJF@"F Heading 2dd@&[$\$5CJ$\aJ$F@2F Heading 3dd@&[$\$5CJ\aJ>@B> Heading 4dd@&[$\$5\B@B Heading 5$$ h@&a$OJQJ@@@ Heading 6 <@&6CJ]aJF@F Heading 7 <@&CJOJQJ^JaJL@L Heading 8 <@&6CJOJQJ]^JaJ4 @4 Heading 9 $@&CJ aJ <A@< Default Paragraph Font:^@: Normal (Web)dd[$\$.U@. Hyperlink >*B*ph>V@> FollowedHyperlink >*B*ph&X@!& Emphasis6]0h@10 HTML Variable6]"W@A" Strong5\(a@Q( HTML Cite6]2`@b2 HTML Address6]4@r4 Header  !CJaJHC@H Body Text Indent$a$5CJ\aJ20@2 List BulletCJaJ\R@\ Body Text Indent 2 0^`0CJaJ4B@4 Body Text$a$CJaJHS@H Body Text Indent 3hh^h`h, @, Footer  !&)@& Page Number8P@8 Body Text 2$a$5CJnOn xl24T dd$d&d'd-DM NPQ[$\$nOn xl25T!dd$d%d&d'dNOPQ[$\$O" xl26T"dd$d%d&d-DM NOP[$\$5B*OJQJ\^JphzO2z xl27C#dd$d&d-DM NP[$\$5B*OJQJ\^JphOB xl28T$dd$d&d'd-DM NPQ[$\$5B*OJQJ\^Jph^OR^ xl29C%dd$d%d'dNOQ[$\$^Ob^ xl30C&dd%d&d'dOPQ[$\$rOrr xl31C'dd$d%d'dNOQ[$\$CJOJQJ^JaJrOr xl32C(dd%d&d'dOPQ[$\$CJOJQJ^JaJO xl33T)dd$d&d'd-DM NPQ[$\$CJOJQJ^JaJrOr xl34C*dd$d%d'dNOQ[$\$CJOJQJ^JaJrOr xl35C+dd%d&d'dOPQ[$\$CJOJQJ^JaJrOr xl36C,dd$d&d-DM NP[$\$CJOJQJ^JaJ(8K`pvHNU^jh   $./023(8K`pvHNU^jm     h%&'()*+?\]^_`ituOX `m(4J r7 2 3 Z ' a b QRTU&'WHI;Lx ""$$&&((^)_)U+V+--..0 0111/202222222223(3031323Y3Z3[3\3]3^3_3`33333324:4>4K4]4`4a4b4444M6N6`6666S8T8e88899:H:`::::::;3<4<5<p<<<====??BB%D&D.D/DIDJDhDkDlDwDxDyDzD{D|D}D~DDDDD&E'EsFtFHHPKQKRKlKmKKKKKKKKKKKKKKKKKKMMNM}O~OOOmQnQiSjSTUUUiWjWXXZZ][^[]]^^^aabbddd.d/d\dbdhdmdtdddddddddddddeee!e.e0epeqeseeeeeeeeee3f4f6fCfJfMfffffffgggg)g+gtgugwggggggggggggggggggghhhOhPhRh]hjhlhhhhhhhi i"i'i.i3iiiiiiiiiiiii?j@jBjDjFjHjJjKjQjUjbjdjjjjjjjjjjjjj"k#k%k'k)k+k-k.k5k9kFkHkhkikkkukkkkkkkkkllll$l)lcldlflnlulzlllllll m mmmmmpmqmsmumwmym{m|mmmmmmmmmmmmmn nnnEnFnHn_nlnnnnnnnnnoooo o o oo!o%o2o4oToUoWocoporoooooooppp pppHpIpKpWp_papppppppppppppppqq!q#qCqDqFqRq_qaqqqqqqqqqqqqq=r>r@rQrYr[rrrrrrrrrrrrrrrrrss:s;s=sIsVsXs~ssssssssssssssssssttt$t+t.tetfthttt{ttttttttttttttttttuu.u/u1u;uHuJuoupuruxuuuuuuuuuvvv!v)v+vjvkvmvovqvsvuvvvvvvvvvvvvvwww$w.w0wnwowqwwwwwwwwwwxxxxxxQxRxTxVxXxZx\x]xgxkxxxzxxxxxxxyy yyy#yiyjylyyyyyyyyyyyGzHzJzczjzozzzzzzzzzz{{{O{P{Q{R{{{{{(||}~~~~d2;78uׅ/nΉ6 O~t֌"ڎHʑˑ1FHbc&yΖϖFnÙ.pqr^_`Ɵǟ՟֟89:Apxbibcde£ʣno`ahƥ \զݦ9D=nĪ+Qw^fѬ'^k'2m ;<D56>h9cwxyбѱٱDz oԳճѴٴ%0DO"/kls˷ַ۷$)7#2:EWj  !"#$ؼ&6v%s;4p/u-BC[\y56DEbp^#< EUVLZ[x)Dw<X{|?@_y/12Ry +5?IS]hr|#$5tu 12D(T 0c -&:;FGQqtu  ,JLVHI=[F~ V[!ABMN^| 3Zrsiju!)*5Rftu%&2:;Mvx5dgij| &(2Bdepq ")*CT\]h+,78Yl#4<=HfwUWa{|L]efq+34F #$6=>Rcklw#$089K "#;LTU`qVXb}~089D^o(./AHKL^efuv$%0]r Iik|46@{| GX`alWYc !3:;p!acm'8adew23D   H I Z         y z  - . @               ] ^ p q {           / 6 7 B               LM_efgr  (xy#$5VWcjk}~67Ibcdr!"4STe"#-23>?Q%&-.@AK|}EFW(12C ij{ {|"#4%&056ABCUVkz  ( / 0 B           0!?!F!G!R!!!!!!" " ""d"e"o""""##0#1#2#a#p#w#x#####3$4$@$G$H$Z$$$$$$$$$$Z%[%\%j%y%%%%%%%3&4&@&m&n&&&&&&&'''!'''''''''''' (((((((W)X)b)))))))))))))))))))))*[*\*m****L+M+_+,,-------.........y/z//000000P1Q1[11112 2a2d22222"3#34383X3\3]3{33333334 4;4<4o4p4444443585;5=5b5c5s55555E6F6^6v6666B8C8N8O8`8f8g8r8999::$:C;D;V; < <<y<z<<<<<=@===R>>?6?7?e?f?w?~???@@'@AAAAAAeBfBpBBBBCCWCZCvCxCCCC DDDTDDDEEKELErEvEEEFFF6F:FFFFFFGGGGGHH-H1H4H5HGHNHOHYHZHkHqHrH}HGIHIYIJJ(JKKKKKKLLLLL MMMMNN-N.N?NFNGNRNNNN8O9OEOOOO7P8PBPPPPPP Q$QYQmQqQxQ|QQQQQQQQRR0R7R8RCRRRRtTuTT UU UsUtU~UUUU*V-VrVVVVW/W4WCWaWfW}WWWWWWWWW XXXXFXvX|XXXXXXXXXXXXYYY9Y:YKYRYSY^YYYYZZZ[[+[~[[[[[[ \\E\q\\\\\\\\]]]]/]?]@]K]]]]V^W^c^j^k^}^^^^^^^^^^8___,```=aaaaaaabQbbbb4czc{c|cccccccee'eYfZfffmfnffngogygggggggh(hEhrhhhhh+iKioiiiiiiiiiijjjkkkkkklllllllll mHmmmnknnnoPooop/pYpppqyqqqqqqqqqrrrtt"t(t)t;ttttuuu6u7uIuiuuuv\vvvXwwww>xRxxxxDyVyy z_z`zzzzzzzzz {{{{{{{/|0|:|@|A|L|x|{|||||}} }$}'}N}Q}x}|}}}}*~E~~~~~~~~hi&ɀʀ27@F WXiσ!MP^`څۅ;?hiÆȆɆ,ɇ·vwÈֈωЉ`ahiw ;DX΋ڋ܋1;<>?ce֌!@čō׍ލߍ ێ܎fgsyz‘ۑܑAdI(P pĖŖ ƗǗؗ'(4:;Mݘ,/rw|™KLQS]`asz{|ɚě  BEhjӜߜ!.5?Ybǝ˝Ν)-01CJKZ[lrs~34EҠɡ*JӢTP|ܤ6J<NWX ĨŨѨרب12<BCNz}&,38/0jow|ìȬʬԬ׬ج 189DCDNTU`?@SU|ѱұ  5:Xm /X.78L|ɶҶԶ2r|}%4Wb +,=CDO%&7(/0BûĻϻEc lm{| !2PQ]dewGtu!".56H123;<KQR]}~56@FGRwx9PhQREFWFGSYZl./@GHS$%768[}~{| !-jk}DqGHY`al,  0st~^_qxy'  !3vw #$HjkMQ/2GIJ\cdevw [\flmx^5Srs CEWX14rs&)HLuz!&Xqv  189:KL[abm45GxU%&efw~IJbz|}bcmst56RTvx>m  H[_`ors@BC0MxL}  #$345FG[\klqrCDIJPQYZei000000000000X00?0?0?0?0?0?0?0?0?0?0?0?0?0?0?0?0?0?h0?00 0000000000000000000000000000000000000000000000(00U0U0U0U0U0U0U0U0U0U0U(00000(00'0'80'80'000- 0- 000. 0. 0. 0. 0. 000. 0. 0. 0080'000000000(0(00(0(0(0(0(0(0(0(0(0(0(0((08018018010202020202020202020202H020230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230230231 0231 023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023 023023 023023023023023 023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023023 023 023023023023023023023023023023023023023023023023023023023023023 023 023 023023023023023023023023023023023023023023023023023023023023023023023023023023023023 023 023 023 023023023 023 023023 023 023 023 023 023023023 023 023 023 023 0230000000(000000(000000000000000x00x0000x00x00x000000000000000000x00x00000x00x00x00x00x000x00x00x00000000000x000x00x00x00000x000x00x00x0000x00000000000000000000000000000000000000000000000000000000x00x00x00x000x00x00x000x000x00x00x00x0000x00x00x0000x00x000x00x0x0x0x0000000000808000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000@0@0@0@0@0@0@0@0@0@0@00@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#@01#0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000x0000000000000000000000x0x0000000000000000000000000x0000000000000000000000000x00000000000000000000000000x000000000000000000000000000x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000(000000000000000000000000000000(0000000@0@0@0@0 0000000000000000000000000000000000000000@000 {{{~J 6AJnvza2$uL k)?~YpzYYh%)+,-/047Kt^X"67H>/HmOYbhhhqiiMjkkkkOllmm?nJndnn'o5oopup qpq{qqrnrs s4ss tattt#uuuYvvv:w~wwwxhxxx/yyzqzz{{{T|]||j}}~5D#&y#)11-dwe> 4  k>""$ &Z(*W-.479y@ELIYLQYUtY\^?aaejmrx>|ő ҤBʰ|ÿ2;}v1Xbw h&(*.1235689:;<=>?@ABCDEFGHIJLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrsuvwxyz{|}~g'0KM{+TV;\^Eik#&W{~ /2h"EHt ;mp 2 5 f g * U X " % W ) \ _ 1LOU'scav(C)\)12-202}22445555`ğ$q5>*-]~h %t%%%%%%%t%t%t%t%t%t%t%t%t%%%t%t%t%t%t%t%t%t%t%t%t%t%t%t%t%%T%tXXXXXXXXXXXXXXXXX %w~!!44867@/6f(  (2 6 % \B  S D"NB  S D\B  S D"\B  S D"H2  #   V  # " H2  #   H   #   H   #   NB   S DH   #   NB   S DH2  #   NB  S DNB  S D NB  S DNB  S D H  #   H  #  NB  S DNB  S DH2  #   (  H  #   H  #   H  #   H  # ! NB  @ S DNB ! S DNB " S DN $ 3   ' p W?clientTimes New Roman"  ( p W?clientTimes New Roman$  ) p W?clientTimes New Roman# NB * S DNB + S DNB , S D ( - ( T . C .) H / # /, H 0 # 0+ H 2 # 2* H 3 # 3-  4 ( W?Sports Score serverTimes New Roman& NB 5 S D'B S  ?22222333333332434445464>4K4L4M4hDiDlDmDnDoDpDqDrDsDtDuDDDDmKnKKKKKKKKh@ at tH$t, ,tH`t <e,"t5t  <!t tuu4YtY`t$  t\ aa4l}<4 <,"%t } t ?t4t$  t@ @ 4 ! t$* !t":lt!:t T:t d&t4&t &t+,& t*T&T t,&l t :t'Ct)Ct(xCHt6 t4\ 0t5,2,t- ! t. ! t2 t0@  t/T@  t3  t6SystemOverview _Hlt483878373 _Hlt479343391 _Hlt483878378 IntroductionDesignConsiderations _Hlt483878374AssumptionsAndDependenciesGeneralConstraintsGoalsAndGuidelines _Hlt483878379DevelopmentMethodsArchitecturalStrategiesSystemArchitectureSubsystemArchitectureWebVikingSubsystemArchitectureSubSysArchitectWebViking _Toc426338916SSDBISubsystemArchitectureSubSysArchitectSSDBI$ServerComponentSubsystemArchitectureSubSysArchitectServerServerCommSubsystemArchitectureSubSysArchitectServerCommClientCommSubsystemArchitectureSubSysArchitectClientComm$ClientComponentSubsystemArchitectureSubSysArchitectClientSubSysArchitectDialogDBSubSysArchitectSSDBSubSysArchitectDialogUtilityPoliciesAndTacticsDetailedSystemDesignDetailedSystemDesignWebVikingDetailedSystemDesignSSDBI#DetailedSystemDesignServerComponentDetailedSystemDesignServerCommDetailedSystemDesignClientComm#DetailedSystemDesignClientComponent"DetailedSystemDesignDialogDatabaseDetailedSubSystemDesign DetailedSubSystemDesignWebVikingDetailedSubSystemDesignSSDBI&DetailedSubSystemDesignServerComponent!DetailedSubSystemDesignServerComm clientComm!DetailedSubSystemDesignClientComm&DetailedSubSystemDesignClientComponent%DetailedSubSystemDesignDialogDatabaseDetailedSubSystemDesignSSDB$DetailedSubSystemDesignDialogUtilityGlossaryAcronymsAndAbbreviations Bibliographyz&U''x(1/222`3::5<5</D/DDRKKOdr`ǟey $)i@@@ @  !"#$%&'()*+,-./012345zW'w(]).22223::o<o<HDHDkKkKOO-dşԟӳ )?i< E /34<**88899999 ::::-:1:::N@W@_CjCJDTDDDFFGGGGG HH!H9HLHHHNI`IIJoKyKMMMMxffqq˟ԟAJLSTZcm&r{|#nuv|ƥͥ ¦ҦDT )MPZ]gjsvw'P['2­˭ҭԭ׭حݭ߭29mr>GIPQW^e}DzѲӲڲ۲ &)0ٴ069@ʵ׵ٵO\̶#5px&/WiɿJ`9CPSfr *0<S]R[bm *]g!) !&034Ic}=QwOX}%(<=ERlm}3CQ_qr &6PSTn"-=Fd~T]kp_jlx}z>INWv~/:u=HPUZcdiOd)CEHyFI+.K]fx+4=@s=M^g+!5s<NObFXYinq }    + A D E N n z         6IDTdp !3JQS\dgho*rR^Vbnzl|Xhm3<Qafx\gV] !!"!$!'!(!-!"###9#C#L#S#U#X#Y#^#''(())++++&,/,?,I,M,U,\,q,,,,,,,------..............00m2w222)323F3O3333333334+4,484@4Z4[4l4p4444444444445555!505>5^5h5q5u55C8M888r;;;;;;;;;;<<<<=,=4=>=G=P=Q=]======>>>Y>g>h>s>y>>>>>> ??7?Q?Y?c?AAkDDDDEE$F/FnF|FFGG,G-G>GH)HOHXH]IfI,J5JtJJKKKKLLLLLLLL MMM(MMMMMMMMMMMMMMMMNN*N P.PQQQR RR\UjUWWWWXXXXY6Yg[u[]]^^^^8_L_____,`?`````=aDaaajaaaaaaaabb,bQbcbbbbbbc4cBc|cc+e9efffffffffg%g/gSglgghhh7hDhMh`hahohzh}h~hhhhhhhhhhiii*iJn{ȶڶ#0Q]ɷ ,2ɸո *t\u 67Ckrszļ-ɽԽ%()0mz GJKU$,3589CEHISu]p&3:   EM\etRcgy}+Wj=H\gju(DZ[hinx12?@EThvWk%-4DIQXhp$'Xopxz !-:Eeu+Ofnobjbm~MUw&06>AUV`y#Sa~ *25IJU_g:JGW '.BI\gov.GOVX[\c)0W^<V'4>FIPZd:FMYv|i  ( ++..::<<sCuCJDTDIIoKyKXL`L^^{{{{0|4|||~~~~lp:>CG=>}߅7;ˆƈ!%vz%&W['+|ތ#*-PSz|ёґ’ƒOS6JSx&ip^luƥͥ \bݦ8DT =EnvĪ˪ +0QVwëѬ٬'2ko29mr:>G9?ciDzѲ &ouٴ$06ȵO\̶/3s}$#)27AEPSKP ]cnrEJ (/T[ 07cjHMXY%NQ4@B_q"To]c6}NR_j}QYzdk5zv*.=IZd! >E!#*tzfy fmjs07_dtw,<O;BFY ),:@Yi  A D     gk JQdgR^l|XhQaV]  !"#C#K#%%c%h%9'A'''++E,J,,,----. ...001133_3a33333334,4G4[44455E5_5d5f555<<==@=F=====R>X>>>??J?R?AACCDDEE G-GHHJJxKKLLMMMMMMMMN N PPPP'Q-Q\Q`QsQwQQQFUKU8W@WGWJWWWWWWWXXXXXXXXY!YQ[V[^^8_L_____,`?`````=aDaaajaaaaaaaabb,bQbcbbbbbbc4cBcffgghh)h/hFhLhshyhhhhhhhhi,i3iLiSipiwillmmHmmmmnnknqnnno"oPoVooop.p/p5pYp_pppppqqyqqIuPulusuuuv"v\vbvvvvwwwwwwwRxXxxxxxxxDyUyVy]yyy zzizkz{|}||||| } }@}K}S}Z}}} ~~n~y~~~eh;?ƁȁPRac†ۆ)ćȇňӈ̉fgjnBCEI݋?Af|AǒdjIO'(.PV• pwΖЖSYEHjz:>Нӝ*1TYTZܤJP<MNU fh}rvʬЬ/\j  569=жѶ"xkr $wGJ%H39?PVhnY[ "9;\a)P[qwbdeg%-IQln"TV !-39ACfo5<SZLXY\ 6>uw$+-OQ~ *2[]zQXx} \h>@)0W^LN6;MYbhDHJOQXZdi33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 --;E+LUBL jt*4;Lx(1eoCR]g,6#2=GW`|L[fp4ERalv9J;JU_Xa~.9C/@%/ 6?|GVakYbp clfidancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancQC:\Documents and Settings\danc\Desktop\capstone\Software Design Specification.docdancuC:\Documents and Settings\danc\Application Data\Microsoft\Word\AutoRecovery save of Software Design Specification.asd0NB >`] !s zG Zd98 GhXcod>88D|(}P-F"Xk  cJ?,"5R E(h:_s-*[jEoS.b|S1`HV:58#9'=JCx:>/X?> ;BwCcEzMJZfJhM.=pifQ YFQXh7V0q"V>'WH_L>g~Z0(Aq[{P^pơfFfpjTJNYjfDkZ1X6nr=pł~^qcIdlrRF;x(Yy8ow.~MDhh^h`OJQJ^Jo(^`o(. LL^L`o(..^`o(...^`o(....   ^ `o( ..... @ @ ^@ `o( ......   ^ `o(....... x`x^x``o(........ `^``o(.........hh^h`o(.hpp^p`OJQJ^Jo(h@ @ ^@ `OJQJ^Jo(oh^`OJQJ^Jo(h^`OJQJ^Jo(h^`OJQJ^Jo(oh^`OJQJ^Jo(hPP^P`OJQJ^Jo(h  ^ `OJQJ^Jo(oh^`OJQJ^Jo(^`OJQJ^Jo(^`OJQJ^Jo(opp^p`OJQJ^Jo(@ @ ^@ `OJQJ^Jo(^`OJQJ^Jo(o^`OJQJ^Jo(^`OJQJ^Jo(^`OJQJ^Jo(oPP^P`OJQJ^Jo(h ^`OJQJo(h ^`OJQJo(oh pp^p`OJQJo(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJQJo(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJQJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(^`o(.h^`OJQJ^Jo(pLp^p`L.@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(hh^h`.88^8`o()^`. L ^ `L.  ^ `.xx^x`.HLH^H`L.^`.^`.L^`L.^`OJQJ^Jo(^`OJQJ^Jo(opp^p`OJQJ^Jo(@ @ ^@ `OJQJ^Jo(^`OJQJ^Jo(o^`OJQJ^Jo(^`OJQJ^Jo(^`OJQJ^Jo(oPP^P`OJQJ^Jo(hh^h`.0^`0o( 0^`0o(.0^`0o(..0^`0o(... 0^`0o( .... 88^8`o( ..... 88^8`o( ...... `^``o(....... `^``o(........hh^h`o(hh^h`o(.0^`0o(..0^`0o(... 0^`0o( .... 88^8`o( ..... 88^8`o( ...... `^``o(....... `^``o(........^`OJQJ^Jo(^`OJQJ^Jo(opp^p`OJQJ^Jo(@ @ ^@ `OJQJ^Jo(^`OJQJ^Jo(o^`OJQJ^Jo(^`OJQJ^Jo(^`OJQJ^Jo(oPP^P`OJQJ^Jo(^`o(.hh^h`OJQJ^Jo(^`o(.LL^L`o(..^`o(...^`o(....   ^ `o( ..... @ @ ^@ `o( ......   ^ `o(....... x`x^x``o(........ `^``o(.........^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(hh^h`OJQJ^Jo(hh^h`OJQJ^Jo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(^`o(.h ^`OJQJo(h ^`OJQJo(oh pp^p`OJQJo(h @ @ ^@ `OJQJo(h ^`OJQJo(oh ^`OJQJo(h ^`OJQJo(h ^`OJQJo(oh PP^P`OJQJo(hpp^p`OJQJ^Jo(h@ @ ^@ `OJQJ^Jo(oh^`OJQJ^Jo(h^`OJQJ^Jo(h^`OJQJ^Jo(oh^`OJQJ^Jo(hPP^P`OJQJ^Jo(h  ^ `OJQJ^Jo(oh^`OJQJ^Jo(hh^h`OJQJ^Jo(0^`0o(.0^`0o(..0^`0o(...0^`0o(.... 88^8`o( ..... 88^8`o( ...... 88^8`o(....... `^``o(........ `^``o(.........h^`OJQJ^Jo(h^`OJQJ^Jo(ohpp^p`OJQJ^Jo(h@ @ ^@ `OJQJ^Jo(h^`OJQJ^Jo(oh^`OJQJ^Jo(h^`OJQJ^Jo(h^`OJQJ^Jo(ohPP^P`OJQJ^Jo(^`o(.h^`OJQJ^Jo(pLp^p`L.@ @ ^@ `.^`.L^`L.^`.^`.PLP^P`L.0^`0o(.0^`0o(..0^`0o(...0^`0o(.... 88^8`o( ..... 88^8`o( ...... 88^8`o(....... `^``o(........ `^``o(.........0^`0o( 0^`0o(.0^`0o(..0^`0o(... 0^`0o( .... 88^8`o( ..... 88^8`o( ...... `^``o(....... `^``o(........h^`ho(. h^`ho(..0^`0o(...0^`0o(.... 88^8`o( ..... 88^8`o( ...... 88^8`o(....... `^``o(........ `^``o(.........^`o(. LL^L`o(..^`o(...^`o(....   ^ `o( ..... @ @ ^@ `o( ......   ^ `o(....... x`x^x``o(........ `^``o(.........h  ^ `OJQJ^Jo(oh^`OJQJ^Jo(oh^`OJQJ^Jo(hdd^d`OJQJ^Jo(h44^4`OJQJ^Jo(oh^`OJQJ^Jo(h^`OJQJ^Jo(h^`OJQJ^Jo(oht"t"^t"`OJQJ^Jo(0^`0o(.0^`0o(..0^`0o(...0^`0o(.... 88^8`o( ..... 88^8`o( ...... 88^8`o(....... `^``o(........ `^``o(.........hpp^p`OJQJ^Jo(h  ^ `OJQJ^Jo(ohxx^x`OJQJ^Jo(hHH^H`OJQJ^Jo(h^`OJQJ^Jo(oh^`OJQJ^Jo(h^`OJQJ^Jo(h^`OJQJ^Jo(ohX X ^X `OJQJ^Jo(^`o(. LL^L`o(..^`o(...^`o(....   ^ `o( ..... @ @ ^@ `o( ......   ^ `o(....... x`x^x``o(........ `^``o(.........^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(^`o(. LL^L`o(..^`o(...^`o(....   ^ `o( ..... @ @ ^@ `o( ......   ^ `o(....... x`x^x``o(........ `^``o(.........^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(h^`OJQJ^Jo(h^`OJQJ^Jo(ohpp^p`OJQJ^Jo(h@ @ ^@ `OJQJ^Jo(h^`.h^`OJQJ^Jo(h^`OJQJ^Jo(h^`OJQJ^Jo(ohPP^P`OJQJ^Jo(^`o(.^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(hh^h`OJQJ^Jo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(opp^p`CJOJQJ^JaJo(@ @ ^@ `CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(^`CJOJQJ^JaJo(PP^P`CJOJQJ^JaJo(^`o(.LL^L`o(..^`o(...^`o(....   ^ `o( ..... @ @ ^@ `o( ......   ^ `o(....... x`x^x``o(........ `^``o(.........1(YyIdlrP-1X6n> ;BYj'=odXEoS.zG ?,ow.~ q"VpjDk8#9g~ZhM_s-7V{P^E(>'WkwC]|S1R8DYFQ~^qifQp!s MJAq[fCx:>:5F;x/X?fJEd98 c00         40                 &'24R88/d\dbdhdmdtdddddddddddddeee!e.e0epeqeseeeeeeeeee3f4f6fCfJfMfffffffgggg)g+gtgugwggggggggggggggggggghhhOhPhRh]hjhlhhhhhhhi i"i'i.i3iiiiiiiiiiiii?j@jBjDjFjHjJjKjQjUjbjdjjjjjjjjjjjjj"k#k%k'k)k+k-k.k5k9kFkHkhkikkkukkkkkkkkkllll$l)lcldlflnlulzlllllll m mmmmmpmqmsmumwmym{m|mmmmmmmmmmmmmn nnnEnFnHn_nlnnnnnnnnnoooo o o oo!o%o2o4oToUoWocoporoooooooppp pppHpIpKpWp_papppppppppppppppqq!q#qCqDqFqRq_qaqqqqqqqqqqqqq=r>r@rQrYr[rrrrrrrrrrrrrrrrrss:s;s=sIsVsXs~ssssssssssssssssssttt$t+t.tetfthttt{ttttttttttttttttttuu.u/u1u;uHuJuoupuruxuuuuuuuuuvvv!v)v+vjvkvmvovqvsvuvvvvvvvvvvvvvwww$w.w0wnwowqwwwwwwwwwwxxxxxxQxRxTxVxXxZx\x]xgxkxxxzxxxxxxxyy yyy#yiyjylyyyyyyyyyyyGzHzJzczjzozzzzzzzzzz{{{O{P{z $4G\lrIPYei@sh`@UnknownGz Times New Roman5Symbol3& z Arial5& z!TahomaCFComic Sans MSC"UniversArial;Wingdings?5 z Courier New"h:EMEfkimJ<!20d 2Q(A Software Design Specification TemplatedancdancOh+'0 $0 L X dpx)A Software Design Specification Templateord Sodanctwaancanc Normal.dotDdancl.d107Microsoft Word 9.0p@]n2@}^ÿ@!%^˿mJ<՜.+,D՜.+,h$ hp  Trillium Software Inc. )A Software Design Specification Template Titled  8@ _PID_HLINKSA fXW!http://www.enteract.com/~bradapp1mailto:bradapp@enteract.com~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC18~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC17~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC16~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC15~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC14q~http://espn.go.com/mlbx>$http://www.majorleaguebaseball.com/~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC13~I/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC12~I~/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC11~A{/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC9~Ox/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC7~Nu/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC6~Mr/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC5~Lo/http://www.enteract.com/~bradapp/docs/sdd.html TOC_SEC4  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~      !"#$%0Root Entry F~-^˿2Data  1Table/tWordDocument-SummaryInformation(DocumentSummaryInformation8CompObjjObjectPool~-^˿~-^˿  FMicrosoft Word Document MSWordDocWord.Document.89q