diff --git a/README.md b/README.md index 083f7d8..ae063dd 100644 --- a/README.md +++ b/README.md @@ -82,29 +82,9 @@ Install packages for `flutter` apps: ```sh flutter packages get ``` -Setup API: - -* Upload file: ```index.php``` at ```store-pattern/server/Normal``` to your host. -* Edit ```index.php``` - ```php - $servername = "Your servername"; //recommend localhost - $username = "your username"; - $password = "your password"; - $dbname = "database name"; - ``` -* Edit line 1 ```evn.dart``` at ```store-pattern/admin_app/lib/Constants/``` -and ```store-pattern/order_app/lib/Constants/``` - - ```dart - const String URL_EXECUTE = "your domain/index.php"; - ``` - -* Edit line 17 ```store-pattern/kitchen_app/src/Constants/Constant.java``` - - ```java - public static String urlConnect = "your domain/index.php"; - ``` -* Run script sql in your PhpMyAdmin ```store-pattern/database/mysql.sql``` +### Setup API with php [see here](https://github.com/uiters/store-pattern/blob/e16c6fa32853c6c61a0c1fcbd9cde57d0241f073/README.md) + +### Setup API with docker [see here](./server/README.md) Run: diff --git a/server/Dockerfile b/server/Dockerfile new file mode 100644 index 0000000..88b2245 --- /dev/null +++ b/server/Dockerfile @@ -0,0 +1,15 @@ +FROM google/dart:latest +WORKDIR /app + +COPY . /app + +# Install dependencies, pre-build +RUN pub get + +# Optionally build generaed sources. +# RUN pub run build_runner build + +# Set environment, start server +ENV ANGEL_ENV=production +EXPOSE 3000 +CMD dart bin/prod.dart --address=0.0.0.0 \ No newline at end of file diff --git a/server/LICENSE b/server/LICENSE new file mode 100644 index 0000000..52a1469 --- /dev/null +++ b/server/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 angel-dart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/server/Normal/index.php b/server/Normal/index.php deleted file mode 100644 index 0c3f51f..0000000 --- a/server/Normal/index.php +++ /dev/null @@ -1,48 +0,0 @@ -connect_error){ - echo 0; - return; - } - else - { - $data = $connect->query($query); - $connect->close(); - echo $data ? 1 : 0; - } -} - -function executeQuery($qeury) { // null is false - global $servername, $username, $password, $dbname; - $connect = new mysqli($servername, $username, $password, $dbname); - mysqli_set_charset($connect, 'UTF8'); - if($connect->connect_error) { - echo 0; - return; - }; - - $data = $connect->query($qeury); - - $rows = array(); - while($array = $data->fetch_assoc()) { - $rows[] = $array; - } - $data->close(); - $connect->close(); - echo json_encode($rows); -} -?> \ No newline at end of file diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..82e7166 --- /dev/null +++ b/server/README.md @@ -0,0 +1,28 @@ +### Store pattern server ✈ + +#### Getting start 👍 + ++ Step 1: Add username and password of MySQL in file `server/docker-compose.yml` + ++ Step 2: Run script + +``` +docker-compose up -d +``` + ++ Step 3: + +* Edit line 1 ```evn.dart``` at ```store-pattern/admin_app/lib/Constants/``` +and ```store-pattern/order_app/lib/Constants/``` + +```dart +const String URL_EXECUTE = "your domain/"; +``` + +* Edit line 17 ```store-pattern/kitchen_app/src/Constants/Constant.java``` + +```java +public static String urlConnect = "your domain/"; +``` + +⚠ Becareful '/' at the last url \ No newline at end of file diff --git a/server/Security/Model/Adapter.php b/server/Security/Model/Adapter.php deleted file mode 100644 index 61a70e2..0000000 --- a/server/Security/Model/Adapter.php +++ /dev/null @@ -1,51 +0,0 @@ -server, $this->user, $this->pass, $this->dbname); - try - { - $connect->set_charset('UTF8'); - $data = $connect->query($noneQuery); - $connect->close(); - return $data ? 1 : 0; - } - catch(Exception $e) - { - http_response_code(503);//Service Unavailable: The server is currently unavailable - } - } - - public function executeQuery($query) - { - $connect = new mysqli($this->server, $this->user, $this->pass, $this->dbname); - try{ - $connect->set_charset('UTF8'); - $data = $connect->query($query); - $rows = array(); - while($array = $data->fetch_assoc()) { - $rows[] = $array; - } - - $data->close(); - $connect->close(); - - return $rows; - } - catch(Exception $e) - { - http_response_code(503); //Service Unavailable: The server is currently unavailable - } - } -} -?> diff --git a/server/Security/Model/Login.php b/server/Security/Model/Login.php deleted file mode 100644 index ebf4467..0000000 --- a/server/Security/Model/Login.php +++ /dev/null @@ -1,168 +0,0 @@ -adapter = new Adapter(); - } - - public function builder($header, $body) - { - $header = $this->_valid($header); - $body = $this->_valid($body); - - if($header == null && $body == null) - http_response_code(404);//Not found - else - { - if($header != null) - { - date_default_timezone_set("Asia/Ho_Chi_Minh"); - $data = json_decode($header); - $this->user = isset($data->user) ? $data->user : null; - $this->pass = isset($data->pass) ? $data->pass : null; - if($this->user == null || $this->pass == null || $this->_login() == false) - http_response_code(401);//unauthorized - else - { - $token = $this->_createToken(); - $json = $this->_getJson($token); - echo json_encode($json); - $this->_saveToken($token); - } - } - else - { - $token = $body; - $status = $this->_verify($token); - switch ($status) { - case 0: - http_response_code(401);//unauthorized - break; - case -1: - $this->_updateToken($token); - case 1: - $this->row = $this->_getInfo($this->row['Username']); - $json = $this->_getJson($token); - echo json_encode($json); - break; - default: - http_response_code(401);//unauthorized - break; - } - } - } - } - - private function _getJson($token) - { - return [ - 'status' => 200, - 'Username' => $this->row['Username'], - 'DisplayName' => $this->row['DisplayName'], - 'Sex' => $this->row['Sex'], - 'IDCard' => $this->row['IDCard'], - 'Address' => $this->row['Address'], - 'PhoneNumber' => $this->row['PhoneNumber'], - 'BirthDay' => $this->row['BirthDay'], - 'IDAccountType'=> $this->row['IDAccountType'], - 'IDImage' => $this->row['IDImage'], - 'Token' => $token, - 'TimeOut' => $this->timeOut - ]; - } - - private function _updateToken($token) - { - $$this->timeOut = $this->_getDateOut(); - $user = $this->row['Username']; - $noneQuery = "call USP_SaveToken('$user', '$token', '$$this->timeOut')"; - $this->adapter->executeNoneQuery($noneQuery); - } - - private function _verify($token) - { - $queryVery = "call USP_CheckToken('$token')"; - $this->row = $this->adapter->executeQuery($queryVery); - if(count($this->row) < 1) - return 0; // unauthorized - $this->row = $this->row[0]; - $this->timeOut = $this->row['TimeOut']; - - if(strtotime($this->timeOut) > time()) - return 1; // OK - else return -1;// expired token - } - - private function _valid($str) //try decode base64 - { - if($str == null) - return null; - $listString = explode('.', $str); - if(count($listString) < 2) - return null; - else - { - $key = hash_hmac('sha256', $listString[0], 'flutter'); - if($key == $listString[1]) - return base64_decode($listString[0]); - else return null; - } - } - - private function _login() - { - $this->row = $this->_getInfo($this->user); - if($this->row == null) - return false; - $hash = $this->row['Password']; - if(password_verify($this->pass, $hash)) - return true; - else return false; - } - - private function _getInfo($user) - { - $queryLogin = "call USP_Login1('$user');";//------------ - $rows = $this->adapter->executeQuery($queryLogin); - if(count($rows) < 1) - return null; - return $rows[0]; - } - - private function _saveToken($token) - { - $noneQuery = "call USP_SaveToken('$this->user', '$token', '$this->timeOut')"; - $this->adapter->executeNoneQuery($noneQuery); - } - - private function _createToken() - { - $this->timeOut = $this->_getDateOut(); - return hash_hmac('sha256', $this->user, time()); - } - - private function _getDateOut() - { - return date("Y-m-d H:i:s", time() + 2592000); // 3600 * 24 * 30 = 2592000 = 30 days - } -} -?> \ No newline at end of file diff --git a/server/Security/Model/Verifier.php b/server/Security/Model/Verifier.php deleted file mode 100644 index 96a4c9a..0000000 --- a/server/Security/Model/Verifier.php +++ /dev/null @@ -1,91 +0,0 @@ -token = $this->_valid($header); // $header = token + '.' + sha256('token', secretkey); - $this->query = $this->_valid($excuteQuery); - $this->noneQuery = $this->_valid($excuteNoneQuery); - $this->adapter = new Adapter(); - } - - private function _valid($header) - { - if($header == null) - return null; - $listString = explode('.', $header); - if(count($listString) < 2) - return null; - else - { - $key = hash_hmac('sha256', $listString[0], 'flutter'); - if($key == $listString[1]) - return base64_decode($listString[0]); - else return null; - } - } - - public function builder() - { - if($this->token == null || !(($this->noneQuery == null) ^ ($this->query == null))) - http_response_code(404);//Not Found: The requested resource could not be found. - else - { - $check = $this->_verify(); - if($check == 0) - { - http_response_code(401);//Unauthorized - } - else - { - //$idType = $row['IDAccountType']; - //if(!checkPermit()) http_response_code(401) // 401 UNAUTHORIZED: - // if($check == -1) // expired token - // $this->_updateToken(); - if($this->noneQuery != null) - $data = $this->adapter->executeNoneQuery($this->noneQuery); - else $data = json_encode($this->adapter->executeQuery($this->query)); - echo $data; - } - } - } - - private function _verify() : int - { - date_default_timezone_set('Asia/Ho_Chi_Minh'); - $queryVery = "call USP_CheckToken('$this->token')"; - $this->row = $this->adapter->executeQuery($queryVery); - if(count($this->row) < 1) - return 0; // unauthorized - $this->row = $this->row[0]; - if(strtotime($this->row['TimeOut']) > time()) - return 1; // OK - else return -1;// expired token - } - - private function _updateToken() - { - $timeOut = $this->_getDateOut(); - $user = $this->row['Username']; - $noneQuery = "call USP_SaveToken('$user', '$this->token', '$timeOut')"; - $this->adapter->executeNoneQuery($noneQuery); - } - private function _checkPermit() - { - $str = ['Admin', 'User']; - $permit = str[$this->row['IDAccountType']]; - //check - } - - private function _getDateOut() - { - return date("Y-m-d H:i:s", time() + 2592000); // 3600 * 24 * 30 = 2592000 = 30 days - } -} -?> \ No newline at end of file diff --git a/server/Security/authentication.php b/server/Security/authentication.php deleted file mode 100644 index cc12002..0000000 --- a/server/Security/authentication.php +++ /dev/null @@ -1,10 +0,0 @@ -builder(); -?> \ No newline at end of file diff --git a/server/Security/index.php b/server/Security/index.php deleted file mode 100644 index 7ee7349..0000000 --- a/server/Security/index.php +++ /dev/null @@ -1,8 +0,0 @@ -$body"; -$login = new Login(); -$login->builder($header, $body); -?> \ No newline at end of file diff --git a/server/analysis_options.yaml b/server/analysis_options.yaml new file mode 100644 index 0000000..2981164 --- /dev/null +++ b/server/analysis_options.yaml @@ -0,0 +1,8 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + strong-mode: + implicit-casts: false +linter: + rules: + - unnecessary_const + - unnecessary_new diff --git a/server/bin/dev.dart b/server/bin/dev.dart new file mode 100644 index 0000000..343cc3d --- /dev/null +++ b/server/bin/dev.dart @@ -0,0 +1,28 @@ +import 'dart:io'; +import 'package:store_pattern_service/src/pretty_logging.dart'; +import 'package:store_pattern_service/store_pattern_service.dart'; +import 'package:angel_container/mirrors.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_hot/angel_hot.dart'; +import 'package:logging/logging.dart'; + +void main() async { + // Watch the config/ and web/ directories for changes, and hot-reload the server. + hierarchicalLoggingEnabled = true; + + var hot = HotReloader(() async { + var logger = Logger.detached('store_pattern_service') + ..level = Level.ALL + ..onRecord.listen(prettyLog); + var app = Angel(logger: logger, reflector: MirrorsReflector()); + await app.configure(configureServer); + return app; + }, [ + Directory('config'), + Directory('lib'), + ]); + + var server = await hot.startServer('127.0.0.1', 3000); + print( + 'store_pattern_service server listening at http://${server.address.address}:${server.port}'); +} diff --git a/server/bin/prod.dart b/server/bin/prod.dart new file mode 100644 index 0000000..92fc8af --- /dev/null +++ b/server/bin/prod.dart @@ -0,0 +1,30 @@ +import 'package:store_pattern_service/store_pattern_service.dart'; +import 'package:angel_container/mirrors.dart'; +import 'package:angel_production/angel_production.dart'; + +// NOTE: By default, the Runner class does not use the `MirrorsReflector`, or any +// reflector, by default. +// +// If your application is using any sort of functionality reliant on annotations or reflection, +// either include the MirrorsReflector, or use a static reflector variant. +// +// The following use cases require reflection: +// * Use of Controllers, via @Expose() or @ExposeWS() +// * Use of dependency injection into constructors, whether in controllers or plain `container.make` calls +// * Use of the `ioc` function in any route +// +// The `MirrorsReflector` from `package:angel_container/mirrors.dart` is by far the most convenient pattern, +// so use it if possible. +// +// However, the following alternatives exist: +// * Generation via `package:angel_container_generator` +// * Creating an instance of `StaticReflector` +// * Manually implementing the `Reflector` interface (cumbersome; not recommended) +// +// As of January 4th, 2018, the documentation has not yet been updated to state this, +// so in the meantime, visit the Angel chat for further questions: +// +// https://gitter.im/angel_dart/discussion +void main(List args) => + Runner('store_pattern_service', configureServer, reflector: MirrorsReflector()) + .run(args); diff --git a/server/config/default.yaml b/server/config/default.yaml new file mode 100644 index 0000000..86a46c6 --- /dev/null +++ b/server/config/default.yaml @@ -0,0 +1,3 @@ +# Default server configuration. +host: 0.0.0.0 +port: 3000 \ No newline at end of file diff --git a/server/config/development.yaml b/server/config/development.yaml new file mode 100644 index 0000000..4bed71e --- /dev/null +++ b/server/config/development.yaml @@ -0,0 +1,2 @@ +# Development-only server configuration. +debug: true \ No newline at end of file diff --git a/server/config/production.yaml b/server/config/production.yaml new file mode 100644 index 0000000..f1af8d8 --- /dev/null +++ b/server/config/production.yaml @@ -0,0 +1,2 @@ +# Production-only server configuration +debug: false diff --git a/server/docker-compose.yml b/server/docker-compose.yml new file mode 100755 index 0000000..54a5692 --- /dev/null +++ b/server/docker-compose.yml @@ -0,0 +1,42 @@ +version: '3.3' +services: + mysql_db: + restart: always + image: mysql:5.7 + container_name: mysql + command: mysqld --user=root --verbose --lower_case_table_names=1 + volumes: + - ./mysql_init:/docker-entrypoint-initdb.d + ports: + - "3306:3306" + environment: + MYSQL_DATABASE: "storepattern" + MYSQL_USER: "" + MYSQL_PASSWORD: "" + MYSQL_ROOT_PASSWORD: "" + MYSQL_ALLOW_EMPTY_PASSWORD: "yes" + networks: + - store_pattern + + store_pattern_service: + container_name: store_pattern_service + restart: always + build: + context: . + environment: + MYSQL_HOST: "mysql_db" + MYSQL_PORT: 3306 + MYSQL_DATABASE: "storepattern" + MYSQL_USER: "" + MYSQL_PASSWORD: "" + depends_on: + - mysql_db + ports: + - '3000:3000' + networks: + - store_pattern +networks: + store_pattern: + +volumes: + mysql_db: \ No newline at end of file diff --git a/server/lib/src/config/config.dart b/server/lib/src/config/config.dart new file mode 100644 index 0000000..b048df8 --- /dev/null +++ b/server/lib/src/config/config.dart @@ -0,0 +1,23 @@ +library store_pattern_service.src.config; + +import 'package:angel_configuration/angel_configuration.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:file/file.dart'; +import 'package:store_pattern_service/src/routes/controllers/store_pattern_controller.dart'; +import 'package:store_pattern_service/src/services/store_pattern_service.dart'; + +/// This is a perfect place to include configuration and load plug-ins. +AngelConfigurer configureServer(FileSystem fileSystem) { + return (Angel app) async { + // Load configuration from the `config/` directory. + // + // See: https://github.com/angel-dart/configuration + await app.configure(configuration(fileSystem)); + + // conect to mySql + app + ..container.registerSingleton( + app.container.make()); + await app.mountController(); + }; +} diff --git a/server/lib/src/models/query_request.dart b/server/lib/src/models/query_request.dart new file mode 100644 index 0000000..ded76f4 --- /dev/null +++ b/server/lib/src/models/query_request.dart @@ -0,0 +1,16 @@ +class QueryRequest { + String query; + bool isNoneQuery; + + QueryRequest.fromJson(Map map) { + if (map.containsKey('executeNoneQuery')) { + query = map['executeNoneQuery'].toString(); + isNoneQuery = true; + } else if (map.containsKey('executeQuery')) { + query = map['executeQuery'].toString(); + isNoneQuery = false; + } else { + throw Exception('Query incorrect'); + } + } +} diff --git a/server/lib/src/pretty_logging.dart b/server/lib/src/pretty_logging.dart new file mode 100644 index 0000000..532c7ac --- /dev/null +++ b/server/lib/src/pretty_logging.dart @@ -0,0 +1,38 @@ +import 'package:angel_http_exception/angel_http_exception.dart'; +import 'package:logging/logging.dart'; +import 'package:io/ansi.dart'; + +/// Prints the contents of a [LogRecord] with pretty colors. +void prettyLog(LogRecord record) { + var code = chooseLogColor(record.level); + + if (record.error == null) print(code.wrap(record.toString())); + + if (record.error != null) { + var err = record.error; + if (err is AngelHttpException && err.statusCode != 500) return; + print(code.wrap(record.toString() + '\n')); + print(code.wrap(err.toString())); + + if (record.stackTrace != null) { + print(code.wrap(record.stackTrace.toString())); + } + } +} + +/// Chooses a color based on the logger [level]. +AnsiCode chooseLogColor(Level level) { + if (level == Level.SHOUT) { + return backgroundRed; + } else if (level == Level.SEVERE) { + return red; + } else if (level == Level.WARNING) { + return yellow; + } else if (level == Level.INFO) { + return cyan; + } else if (level == Level.CONFIG || + level == Level.FINE || + level == Level.FINER || + level == Level.FINEST) return lightGray; + return resetAll; +} diff --git a/server/lib/src/routes/controllers/store_pattern_controller.dart b/server/lib/src/routes/controllers/store_pattern_controller.dart new file mode 100644 index 0000000..57b25b4 --- /dev/null +++ b/server/lib/src/routes/controllers/store_pattern_controller.dart @@ -0,0 +1,47 @@ +import 'dart:async'; + +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_serialize/angel_serialize.dart'; +import 'package:store_pattern_service/src/models/query_request.dart'; +import 'package:store_pattern_service/src/services/store_pattern_service.dart'; +import 'package:http_parser/http_parser.dart'; + +@Expose('/') +class StorePatternController extends Controller { + final StorePatternService service; + StorePatternController(this.service); + + @Expose('/', method: 'POST', middleware: [parseRequest]) + Future handleRequest(QueryRequest request, ResponseContext res) async { + if (request.isNoneQuery) { + return service.executeNoneQuery(request.query); + } else { + final value = await service.executeQuery(request.query); + if (value != null) { + final r = json.encode(value, toEncodable: dateTimeEncoder); + res + ..contentType = MediaType('application', 'json') + ..write(r); + } else { + return 0; + } + } + } +} + +Future parseRequest(RequestContext req, ResponseContext res) async { + return req.parseBody().then((_) { + final query = QueryRequest.fromJson(req.bodyAsMap); + req.params['request'] = query; + req.params['res'] = res; + return true; + }); +} + +dynamic dateTimeEncoder(item) { + print('item:: $item'); + if (item is DateTime) { + return item.toIso8601String(); + } + return item; +} diff --git a/server/lib/src/routes/routes.dart b/server/lib/src/routes/routes.dart new file mode 100644 index 0000000..cac1d8d --- /dev/null +++ b/server/lib/src/routes/routes.dart @@ -0,0 +1,33 @@ +library store_pattern_service.src.routes; + +import 'package:angel_framework/angel_framework.dart'; +import 'package:file/file.dart'; + +/// Put your app routes here! +/// +/// See the wiki for information about routing, requests, and responses: +/// * https://github.com/angel-dart/angel/wiki/Basic-Routing +/// * https://github.com/angel-dart/angel/wiki/Requests-&-Responses +AngelConfigurer configureServer(FileSystem fileSystem) { + return (Angel app) async { + // Render `views/hello.jl` when a user visits the application root. + app.get('/', (req, res) => res.json({'data': 'Hello 😍'})); + + // Throw a 404 if no route matched the request. + app.fallback((req, res) => res.json({'data': 'Not found 😭'})); + + // Set our application up to handle different errors. + // + // Read the following for documentation: + // * https://github.com/angel-dart/angel/wiki/Error-Handling + + app.errorHandler = (e, req, res) { + res.statusCode = e.statusCode; + return res.json({ + 'error': true, + 'status': e.statusCode, + 'message': 'Are you kidding me? 👍', + }); + }; + }; +} diff --git a/server/lib/src/services/mysql_connectior.dart b/server/lib/src/services/mysql_connectior.dart new file mode 100644 index 0000000..1c9ab31 --- /dev/null +++ b/server/lib/src/services/mysql_connectior.dart @@ -0,0 +1,37 @@ +import 'dart:async'; + +import 'dart:io'; + +import 'package:mysql1/mysql1.dart'; + +class MySQLConnector { + Future _connectMySQL() async { + final host = Platform.environment['MYSQL_HOST']; + final port = int.tryParse(Platform.environment['MYSQL_PORT'] ?? '3306'); + final user = Platform.environment['MYSQL_USER']; + final password = Platform.environment['MYSQL_PASSWORD']; + final db = Platform.environment['MYSQL_DATABASE'] ?? 'storepattern'; + final settings = ConnectionSettings( + host: host, + port: port, + user: user, + password: password, + db: db, + characterSet: CharacterSet.UTF8, + timeout: const Duration(minutes: 1), + ); + return MySqlConnection.connect(settings); + } + + Future getConnection(ConverterFunction converter) async { + MySqlConnection con; + try { + con = await _connectMySQL(); + return await converter(con); + } finally { + await con?.close(); + } + } +} + +typedef ConverterFunction = Future Function(MySqlConnection conection); diff --git a/server/lib/src/services/store_pattern_service.dart b/server/lib/src/services/store_pattern_service.dart new file mode 100644 index 0000000..dcfe575 --- /dev/null +++ b/server/lib/src/services/store_pattern_service.dart @@ -0,0 +1,25 @@ +import 'dart:async'; + +import 'package:store_pattern_service/src/services/mysql_connectior.dart'; + +abstract class StorePatternService { + Future executeNoneQuery(String query); + Future executeQuery(String query); +} + +class StorePatternServiceImpl extends StorePatternService { + final con = MySQLConnector(); + + @override + Future executeNoneQuery(String query) { + return con.getConnection((conection) => + conection.query(query).then((value) => value.affectedRows > 0 ? 1 : 0)); + } + + @override + Future executeQuery(String query) { + return con.getConnection((conection) => conection + .query(query) + .then((value) => value.toList().map((item) => item.fields).toList())); + } +} diff --git a/server/lib/store_pattern_service.dart b/server/lib/store_pattern_service.dart new file mode 100644 index 0000000..65be971 --- /dev/null +++ b/server/lib/store_pattern_service.dart @@ -0,0 +1,18 @@ +library store_pattern_service; + +import 'dart:async'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:file/local.dart'; +import 'src/config/config.dart' as configuration; +import 'src/routes/routes.dart' as routes; + +/// Configures the server instance. +Future configureServer(Angel app) async { + // Grab a handle to the file system, so that we can do things like + // serve static files. + var fs = const LocalFileSystem(); + + // Set up our application, using the plug-ins defined with this project. + await app.configure(configuration.configureServer(fs)); + await app.configure(routes.configureServer(fs)); +} diff --git a/server/mysql_init/mysql.sql b/server/mysql_init/mysql.sql new file mode 100644 index 0000000..5944219 --- /dev/null +++ b/server/mysql_init/mysql.sql @@ -0,0 +1,987 @@ +-- phpMyAdmin SQL Dump +-- version 4.6.6 +-- https://www.phpmyadmin.net/ +-- +-- Máy chủ: localhost +-- Thời gian đã tạo: Th5 22, 2019 lúc 06:29 CH +-- Phiên bản máy phục vụ: 5.7.17-log +-- Phiên bản PHP: 5.6.0 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Cơ sở dữ liệu: `storepattern` +-- +CREATE DATABASE IF NOT EXISTS `storepattern` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; +USE `storepattern`; + +DELIMITER $$ +-- +-- Thủ tục +-- +DROP PROCEDURE IF EXISTS `USP_Admin_AddAccount`$$ +CREATE PROCEDURE `USP_Admin_AddAccount` (IN `username` VARCHAR(100), IN `name` VARCHAR(100), IN `sex` INT, IN `idcard` VARCHAR(100), IN `address` VARCHAR(100), IN `number` VARCHAR(30), IN `birth` DATETIME, IN `type` VARCHAR(100), IN `pass` VARCHAR(128)) BEGIN +insert into ACCOUNT +values(username,pass,name,sex,idcard,address,number,birth,1,3); +update ACCOUNT +set ACCOUNT.IDAccountType=(select ACCOUNTTYPE.ID from ACCOUNTTYPE WHERE ACCOUNTTYPE.Name=type) +where ACCOUNT.Username=username; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_AddFood`$$ +CREATE PROCEDURE `USP_Admin_AddFood` (IN `name` VARCHAR(100), IN `category` VARCHAR(100), IN `price` DOUBLE, IN `images` LONGTEXT) begin +insert into IMAGE +values('',images); +insert into FOOD +values('',(select FOODCATEGORY.ID from FOODCATEGORY where FOODCATEGORY.Name=category),name,price,(SELECT max(IMAGE.ID) from IMAGE)); + +end$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_AddFood2`$$ +CREATE PROCEDURE `USP_Admin_AddFood2` (IN `name` VARCHAR(100), IN `category` VARCHAR(100), IN `price` DOUBLE, IN `images` LONGTEXT) begin +insert into IMAGE +values('',images); +insert into FOOD +values('',(select FOODCATEGORY.ID from FOODCATEGORY where FOODCATEGORY.Name=category),name,price,(SELECT max(IMAGE.ID) from IMAGE)); + +end$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_CheckLogin`$$ +CREATE PROCEDURE `USP_Admin_CheckLogin` (IN `username` VARCHAR(100)) SELECT ACCOUNT.Username,ACCOUNT.Password, ACCOUNT.IDAccountType +from ACCOUNT +where ACCOUNT.Username=username$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_DelAccount`$$ +CREATE PROCEDURE `USP_Admin_DelAccount` (IN `_name` VARCHAR(100)) BEGIN +delete from ACCOUNT +where ACCOUNT.Username=_name; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_DelBill`$$ +CREATE PROCEDURE `USP_Admin_DelBill` (IN `_ID` INT) BEGIN +delete from BILLINFO +where BILLINFO.IDBill=_ID; +DELETE from BILL +where BILL.ID=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_DelFood`$$ +CREATE PROCEDURE `USP_Admin_DelFood` (IN `_ID` INT) delete from FOOD +where FOOD.ID=_ID +and not EXISTS (select * from BILLINFO where BILLINFO.IDFood=_ID)$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_DelFoodCategory`$$ +CREATE PROCEDURE `USP_Admin_DelFoodCategory` (IN `_ID` INT) begin +delete from FOOD +where FOOD.IDCategory=_ID; +delete from FOODCATEGORY +where FOODCATEGORY.ID=_ID; +end$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_DelTables`$$ +CREATE PROCEDURE `USP_Admin_DelTables` (IN `_id` INT) BEGIN +DELETE from `TABLE` +where `TABLE`.`ID`=_id; +end$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetAccount`$$ +CREATE PROCEDURE `USP_Admin_GetAccount` () BEGIN +select ACCOUNT.Username,ACCOUNT.DisplayName,ACCOUNT.Sex,ACCOUNT.IDCard,ACCOUNT.BirthDay,ACCOUNT.Address,ACCOUNT.PhoneNumber,ACCOUNT.IDAccountType,ACCOUNTTYPE.Name AccountType +from ACCOUNT INNER JOIN ACCOUNTTYPE where ACCOUNT.IDAccountType=ACCOUNTTYPE.ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetAccountType`$$ +CREATE PROCEDURE `USP_Admin_GetAccountType` () BEGIN +select ACCOUNTTYPE.ID,ACCOUNTTYPE.Name +from ACCOUNTTYPE; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetBillInfo`$$ +CREATE PROCEDURE `USP_Admin_GetBillInfo` (IN `_ID` INT) select BILLINFO.IDBill,BILLINFO.IDFood,FOOD.Name FoodName,BILLINFO.Quantity +from BILLINFO,FOOD +where BILLINFO.IDBill=_ID +and BILLINFO.IDFood=FOOD.ID$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetBills`$$ +CREATE PROCEDURE `USP_Admin_GetBills` () BEGIN +select BILL.ID,BILL.IDTable,`TABLE`.Name,BILL.DateCheckIn,BILL.DateCheckOut,BILL.Discount,BILL.TotalPrice,BILL.Status,BILL.Username from BILL,`TABLE` +WHERE BILL.IDTable=`TABLE`.ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetDelCategory`$$ +CREATE PROCEDURE `USP_Admin_GetDelCategory` (IN `_ID` INT) select count(*) +from BILLINFO,FOOD,FOODCATEGORY +where BILLINFO.IDFood=FOOD.ID +and FOOD.IDCategory=FOODCATEGORY.ID +and FOODCATEGORY.ID=_ID$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetDelFood`$$ +CREATE PROCEDURE `USP_Admin_GetDelFood` (IN `id` INT) select count(*) +from BILLINFO,FOOD +where BILLINFO.IDFood=FOOD.ID +and FOOD.ID=id$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetFoodFromBill`$$ +CREATE PROCEDURE `USP_Admin_GetFoodFromBill` (IN `_ID` INT) select BILL.ID,BILL.IDTable,BILL.DateCheckIn,BILL.DateCheckOut,BILL.Discount,BILL.TotalPrice,BILL.Username,FOOD.Name,FOOD.IDImage,FOOD.Price,BILLINFO.Quantity,CONVERT(IMAGE.Data USING utf8) Image +from BILL,BILLINFO,FOOD,IMAGE +where BILL.ID=BILLINFO.IDBill +and BILLINFO.IDFood=FOOD.ID +and FOOD.IDImage=IMAGE.ID +and BILL.ID=_ID$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetFoods`$$ +CREATE PROCEDURE `USP_Admin_GetFoods` () SELECT FOOD.ID, FOOD.Name, FOOD.Price, FOODCATEGORY.Name NameCategory, CONVERT(IMAGE.Data USING utf8) Image, FOOD.IDCategory, FOOD.IDImage FROM FOOD + INNER JOIN FOODCATEGORY ON FOOD.IDCategory = FOODCATEGORY.ID + INNER JOIN IMAGE ON FOOD.IDImage = IMAGE.ID$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetIDLastCategory`$$ +CREATE PROCEDURE `USP_Admin_GetIDLastCategory` () BEGIN + +select * from FOODCATEGORY where FOODCATEGORY.ID=(select max(id) from FOODCATEGORY); +ENd$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetIDLastFood`$$ +CREATE PROCEDURE `USP_Admin_GetIDLastFood` () select * from FOOD +where FOOD.ID=(select max(FOOD.ID) from FOOD)$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetIDLastTable`$$ +CREATE PROCEDURE `USP_Admin_GetIDLastTable` () BEGIN + +select * from `TABLE` where `TABLE`.ID=(select max(id) from `TABLE`); +ENd$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetOrders`$$ +CREATE PROCEDURE `USP_Admin_GetOrders` () BEGIN +select BILL.ID,BILL.IDTable,`TABLE`.Name,BILL.DateCheckIn,BILL.DateCheckOut,BILL.Discount,BILL.TotalPrice,BILL.Username from BILL,`TABLE` +WHERE BILL.Status=0 +and BILL.IDTable=`TABLE`.`ID` +order by BILL.DateCheckIn ASC; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetReport`$$ +CREATE PROCEDURE `USP_Admin_GetReport` (IN `date_` DATETIME) BEGIN +select * +from REPORT +where YEAR(REPORT._Date)=YEAR(date_) +and MONTH(REPORT._Date)=MONTH(date_); +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_GetTables`$$ +CREATE PROCEDURE `USP_Admin_GetTables` () SELECT TABLE.ID,TABLE.Name,TABLE.Status FROM `TABLE`$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_InsertFoodCategory`$$ +CREATE PROCEDURE `USP_Admin_InsertFoodCategory` (IN `_Name` VARCHAR(100)) begin +insert into FOODCATEGORY(`Name`) +values(_Name); +end$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_ResetPass`$$ +CREATE PROCEDURE `USP_Admin_ResetPass` (IN `username` VARCHAR(100), IN `pass` VARCHAR(128)) update ACCOUNT +set ACCOUNT.Password=pass +where ACCOUNT.Username=username$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdateAccount`$$ +CREATE PROCEDURE `USP_Admin_UpdateAccount` (IN `username` VARCHAR(100), IN `name` VARCHAR(100), IN `sex` INT, IN `idcard` VARCHAR(100), IN `address` VARCHAR(100), IN `number` VARCHAR(30), IN `birth` DATETIME, IN `type` VARCHAR(100)) BEGIN +update ACCOUNT +set ACCOUNT.DisplayName=name,ACCOUNT.Sex=sex,ACCOUNT.IDCard=idcard,ACCOUNT.Address=address,ACCOUNT.PhoneNumber=number,ACCOUNT.BirthDay=birth,ACCOUNT.IDAccountType=(select ACCOUNTTYPE.ID from ACCOUNTTYPE WHERE ACCOUNTTYPE.Name=type) +WHERE ACCOUNT.Username=username; + +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdateBill`$$ +CREATE PROCEDURE `USP_Admin_UpdateBill` (IN `_ID` INT, IN `_Date` DATETIME) update BILL +set BILL.Status=1, BILL.DateCheckOut=_Date +where BILL.ID=_ID$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdateFood`$$ +CREATE PROCEDURE `USP_Admin_UpdateFood` (IN `_ID` INT, IN `name` VARCHAR(100), IN `_foodcategory` VARCHAR(100), IN `price` DOUBLE, IN `_image` LONGTEXT) BEGIN +DECLARE idimage int; +SELECT FOOD.IDImage into idimage from FOOD where FOOD.ID=_ID; +update IMAGE +set IMAGE.Data=_image +where IMAGE.ID=idimage; +update FOOD +set FOOD.Name=name,FOOD.Price=price,FOOD.IDCategory=(select FOODCATEGORY.ID from FOODCATEGORY where FOODCATEGORY.Name=_foodcategory) +where FOOD.ID=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdateFoodCategory`$$ +CREATE PROCEDURE `USP_Admin_UpdateFoodCategory` (IN `_ID` INT, IN `_Name` VARCHAR(100)) BEGIN +update FOODCATEGORY +set FOODCATEGORY.Name=_Name +where FOODCATEGORY.ID=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdateInfoFood`$$ +CREATE PROCEDURE `USP_Admin_UpdateInfoFood` (IN `_ID` INT, IN `name` VARCHAR(100), IN `_foodcategory` VARCHAR(100), IN `price` DOUBLE) BEGIN +update FOOD +set FOOD.Name=name,FOOD.Price=price,FOOD.IDCategory=(select FOODCATEGORY.ID from FOODCATEGORY where FOODCATEGORY.Name=_foodcategory) +where FOOD.ID=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdatePassword`$$ +CREATE PROCEDURE `USP_Admin_UpdatePassword` (IN `username` VARCHAR(100), IN `pass` VARCHAR(128)) update `ACCOUNT` +set `ACCOUNT`.Password=pass +where `ACCOUNT`.Username=username$$ + +DROP PROCEDURE IF EXISTS `USP_Admin_UpdateTable`$$ +CREATE PROCEDURE `USP_Admin_UpdateTable` (IN `_ID` INT, IN `_Name` VARCHAR(100)) BEGIN + update `TABLE` + set `Name`=_Name + where `ID`=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_CheckToken`$$ +CREATE PROCEDURE `USP_CheckToken` (`token1` VARCHAR(100)) SELECT * FROM `AUTHENTICATION` WHERE `Token` = `token1`$$ + +DROP PROCEDURE IF EXISTS `USP_DelBill`$$ +CREATE PROCEDURE `USP_DelBill` (`id` INT) BEGIN + DELETE FROM BILLINFO + WHERE BILLINFO.IDBill = id; + DELETE FROM BILL + WHERE BILL.ID = id; +END$$ + +DROP PROCEDURE IF EXISTS `USP_DeleteAcc`$$ +CREATE PROCEDURE `USP_DeleteAcc` (`username` VARCHAR(32)) DELETE FROM ACCOUNT + WHERE ACCOUNT.Username = username$$ + +DROP PROCEDURE IF EXISTS `USP_DeleteAccType`$$ +CREATE PROCEDURE `USP_DeleteAccType` (`id` INT(11)) DELETE FROM ACCOUNTTYPE +WHERE ACCOUNTTYPE.ID = id$$ + +DROP PROCEDURE IF EXISTS `USP_DeleteCategory`$$ +CREATE PROCEDURE `USP_DeleteCategory` (`id` INT(11)) DELETE FROM FOODCATEGORY +WHERE FOODCATEGORY.ID = id$$ + +DROP PROCEDURE IF EXISTS `USP_DeleteFood`$$ +CREATE PROCEDURE `USP_DeleteFood` (`id` INT(11)) DELETE FROM FOOD +WHERE FOOD.ID = id$$ + +DROP PROCEDURE IF EXISTS `USP_DeleteTable`$$ +CREATE PROCEDURE `USP_DeleteTable` (`id` INT(11)) DELETE from `TABLE` +WHERE TABLE.ID = id$$ + +DROP PROCEDURE IF EXISTS `USP_GetAccounts`$$ +CREATE PROCEDURE `USP_GetAccounts` () SELECT * +FROM ACCOUNT A, ACCOUNTTYPE B, IMAGE C +WHERE A.IDAccountType = B.ID and A.IDImage = C.ID$$ + +DROP PROCEDURE IF EXISTS `USP_GetAccountTypes`$$ +CREATE PROCEDURE `USP_GetAccountTypes` () SELECT * + FROM ACCOUNTTYPE$$ + +DROP PROCEDURE IF EXISTS `USP_GetBillDetailByBill`$$ +CREATE PROCEDURE `USP_GetBillDetailByBill` (IN `id` INT(11)) SELECT * + FROM BILLINFO A, BILL B, FOOD C + WHERE A.IDBill = B.ID and C.ID = A.IDFood and B.ID = `id`$$ + +DROP PROCEDURE IF EXISTS `USP_GetBills`$$ +CREATE PROCEDURE `USP_GetBills` (IN `currentDate` DATETIME) SELECT A.*, B.ID as IDTable, B.Name, C.* + FROM BILL AS A, `TABLE` AS B, ACCOUNT as C + WHERE A.IDTable = B.ID AND YEAR(A.DateCheckOut) = YEAR(currentDate) and MONTH(A.DateCheckOut) = MONTH(currentDate) and DAY(A.DateCheckOut) = DAY(currentDate) and A.Status = 1 and C.Username = A.Username + ORDER BY A.DateCheckOut DESC$$ + +DROP PROCEDURE IF EXISTS `USP_GetFoodCategories`$$ +CREATE PROCEDURE `USP_GetFoodCategories` () SELECT * from FOODCATEGORY$$ + +DROP PROCEDURE IF EXISTS `USP_GetFoods`$$ +CREATE PROCEDURE `USP_GetFoods` () SELECT FOOD.ID, FOOD.IDCategory, FOOD.Name, FOOD.Price, FOOD.IDImage +FROM FOOD$$ + +DROP PROCEDURE IF EXISTS `USP_GetFoods1`$$ +CREATE PROCEDURE `USP_GetFoods1` () SELECT * +FROM FOOD +WHERE FOOD.IDImage$$ + +DROP PROCEDURE IF EXISTS `USP_GetFoodsPlus`$$ +CREATE PROCEDURE `USP_GetFoodsPlus` () SELECT A.ID `IdFood`, A.Name `FoodName`, C.Name `CategoryName`, A.Price `Price`, B.ID `IdImage`, B.Data `Image`, A.IDCategory `IDCategory` +FROM FOOD A, IMAGE B, FOODCATEGORY C +WHERE A.IDCategory = C.ID and A.IDImage = B.ID$$ + +DROP PROCEDURE IF EXISTS `USP_GetFoodsPlusByIDBill`$$ +CREATE PROCEDURE `USP_GetFoodsPlusByIDBill` (`idBill` INT(11)) SELECT A.ID `IdFood`, A.Name `FoodName`, C.Name `CategoryName`, A.Price `Price`, B.ID `IdImage`, B.Data `Image`, A.IDCategory `IDCategory` +FROM FOOD A, IMAGE B, FOODCATEGORY C, BILLINFO D +WHERE A.IDCategory = C.ID and A.IDImage = B.ID and A.ID = D.IDFood and D.IDBill = idBill$$ + +DROP PROCEDURE IF EXISTS `USP_GetIdAccTypeMax`$$ +CREATE PROCEDURE `USP_GetIdAccTypeMax` () SELECT MAX(ACCOUNTTYPE.ID) as ID +from ACCOUNTTYPE$$ + +DROP PROCEDURE IF EXISTS `USP_GetIdCategoryMax`$$ +CREATE PROCEDURE `USP_GetIdCategoryMax` () SELECT MAX(FOODCATEGORY.ID) as ID +from FOODCATEGORY$$ + +DROP PROCEDURE IF EXISTS `USP_GetIdFoodMax`$$ +CREATE PROCEDURE `USP_GetIdFoodMax` () SELECT MAX(ID) as ID + from FOOD$$ + +DROP PROCEDURE IF EXISTS `USP_GetIDImages`$$ +CREATE PROCEDURE `USP_GetIDImages` () SELECT ID FROM IMAGE$$ + +DROP PROCEDURE IF EXISTS `USP_GetIdMax`$$ +CREATE PROCEDURE `USP_GetIdMax` () SELECT MAX(ID) as ID + from BILL$$ + +DROP PROCEDURE IF EXISTS `USP_GetIdTableMax`$$ +CREATE PROCEDURE `USP_GetIdTableMax` () SELECT MAX(`TABLE`.`ID`) as ID +from `TABLE`$$ + +DROP PROCEDURE IF EXISTS `USP_GetImageByID`$$ +CREATE PROCEDURE `USP_GetImageByID` (IN `_id` INT(11)) SELECT CONVERT(DATA USING utf8) "Image" FROM IMAGE WHERE IMAGE.ID = `_id` LIMIT 1$$ + +DROP PROCEDURE IF EXISTS `USP_GetImages`$$ +CREATE PROCEDURE `USP_GetImages` () SELECT ID , CONVERT(DATA USING utf8) Data FROM IMAGE$$ + +DROP PROCEDURE IF EXISTS `USP_GetTables`$$ +CREATE PROCEDURE `USP_GetTables` () SELECT TABLE.ID,TABLE.Name,TABLE.Status FROM `TABLE`$$ + +DROP PROCEDURE IF EXISTS `USP_HasBillDetailOfBill`$$ +CREATE PROCEDURE `USP_HasBillDetailOfBill` (`idBill` INT(11), `idFood` INT(11)) SELECT * +FROM BILLINFO +WHERE BILLINFO.IDBill = idBill and BILLINFO.IDFood = idFood$$ + +DROP PROCEDURE IF EXISTS `USP_HasBillOfTable`$$ +CREATE PROCEDURE `USP_HasBillOfTable` (`idTable` INT(11)) SELECT * +FROM BILL +WHERE BILL.Status = 0 and BILL.IDTable = idTable$$ + +DROP PROCEDURE IF EXISTS `USP_InsertAccount`$$ +CREATE PROCEDURE `USP_InsertAccount` (IN `username` VARCHAR(32), IN `password` VARCHAR(128), IN `displayname` VARCHAR(100), IN `sex` INT(11), IN `idCard` VARCHAR(30), IN `address` VARCHAR(100), IN `phoneNumber` VARCHAR(30), IN `birthday` DATETIME, IN `idAccountType` INT(11), IN `image` LONGTEXT) BEGIN + DECLARE idImage int ; + + INSERT INTO IMAGE(IMAGE.Data) + VALUES (image) ; + + select MAX(IMAGE.ID) into idImage + FROM IMAGE ; + + INSERT INTO ACCOUNT(ACCOUNT.Username, ACCOUNT.Password, ACCOUNT.DisplayName, ACCOUNT.Sex, ACCOUNT.IDCard, ACCOUNT.Address, ACCOUNT.PhoneNumber, ACCOUNT.BirthDay, ACCOUNT.IDAccountType, ACCOUNT.IDImage) + VALUES(`username`, `password`, `displayname`, `sex`, `idCard`, `address`, `phoneNumber`, `birthday`, `idAccountType`, `idImage`) ; +END$$ + +DROP PROCEDURE IF EXISTS `USP_InsertAccType`$$ +CREATE PROCEDURE `USP_InsertAccType` (IN `_Name` VARCHAR(100)) BEGIN + insert into ACCOUNTTYPE(`Name`) + values(_Name); +END$$ + +DROP PROCEDURE IF EXISTS `USP_InsertBill`$$ +CREATE PROCEDURE `USP_InsertBill` (IN `_IDTable` INT(11), IN `_DateCheckIn` DATETIME, IN `_DateCheckOut` DATETIME, IN `_Discount` DOUBLE, `_TotalPrice` INT, IN `_Status` INT, `_Username` VARCHAR(32)) insert into `BILL`(`IDTable`, `DateCheckIn`,`DateCheckOut`, `Discount`, BILL.TotalPrice, `Status`, `Username`) + values(_IDTable, _DateCheckIn, _DateCheckOut, _Discount,_TotalPrice, _Status, _Username)$$ + +DROP PROCEDURE IF EXISTS `USP_InsertBillInfo`$$ +CREATE PROCEDURE `USP_InsertBillInfo` (`_IDBill` INT, `_IDFood` INT, `_Quantity` INT) insert into `BILLINFO`(`IDBill`, `IDFood`, `Quantity`) + values(_IDBill, _IDFood, _Quantity)$$ + +DROP PROCEDURE IF EXISTS `USP_InsertBin`$$ +CREATE PROCEDURE `USP_InsertBin` (IN `IDCollect` INT, IN `ID` INT) BEGIN + insert BIN(`IDCollection`,`IDElement`) + values(IDCollect,ID); +END$$ + +DROP PROCEDURE IF EXISTS `USP_InsertFood`$$ +CREATE PROCEDURE `USP_InsertFood` (`name` VARCHAR(100), `price` DOUBLE, `idCategory` INT(11), `image` LONGTEXT) BEGIN + DECLARE idImage int ; + + INSERT INTO IMAGE(IMAGE.Data) + VALUES (image) ; + + select MAX(IMAGE.ID) into idImage + FROM IMAGE ; + + INSERT INTO FOOD(FOOD.Name, FOOD.Price, FOOD.IDCategory, FOOD.IDImage) + VALUES(name, price, idCategory, idImage) ; +END$$ + +DROP PROCEDURE IF EXISTS `USP_InsertFoodCatetory`$$ +CREATE PROCEDURE `USP_InsertFoodCatetory` (IN `_Name` VARCHAR(100)) BEGIN + insert into FOODCATEGORY(`Name`) + values(_Name); +END$$ + +DROP PROCEDURE IF EXISTS `USP_InsertPending`$$ +CREATE PROCEDURE `USP_InsertPending` (IN `ID` INT) BEGIN + insert PENDING(`IDBill`) + values(ID); +END$$ + +DROP PROCEDURE IF EXISTS `USP_InsertTable`$$ +CREATE PROCEDURE `USP_InsertTable` (IN `Nametable` VARCHAR(100)) BEGIN + insert into `TABLE`(`Name`,`Status`) + values (Nametable,-1); +END$$ + +DROP PROCEDURE IF EXISTS `USP_IsAccExists`$$ +CREATE PROCEDURE `USP_IsAccExists` (`username` VARCHAR(32)) SELECT * + FROM BILL + WHERE BILL.Username = username$$ + +DROP PROCEDURE IF EXISTS `USP_IsAccTypeExists`$$ +CREATE PROCEDURE `USP_IsAccTypeExists` (`id` INT(11)) SELECT * +from ACCOUNT +WHERE ACCOUNT.IDAccountType = id$$ + +DROP PROCEDURE IF EXISTS `USP_IsCategoryExists`$$ +CREATE PROCEDURE `USP_IsCategoryExists` (`id` INT(11)) SELECT * +from FOOD +WHERE FOOD.IDCategory = id$$ + +DROP PROCEDURE IF EXISTS `USP_IsFoodExists`$$ +CREATE PROCEDURE `USP_IsFoodExists` (`id` INT(11)) SELECT * +FROM BILLINFO +WHERE BILLINFO.IDFood = id$$ + +DROP PROCEDURE IF EXISTS `USP_IsTableExists`$$ +CREATE PROCEDURE `USP_IsTableExists` (`id` INT(11)) SELECT * +from BILL +WHERE BILL.IDTable = id$$ + +DROP PROCEDURE IF EXISTS `USP_Login`$$ +CREATE PROCEDURE `USP_Login` (IN `username` VARCHAR(32)) SELECT A.Username, A.Password, A.DisplayName, A.Sex, A.IDCard, A.Address, A.PhoneNumber, A.IDAccountType, A.IDImage, CONVERT(B.Data USING utf8) `Data`, C.Name, A.BirthDay, C.Name + FROM ACCOUNT A, IMAGE B, ACCOUNTTYPE C + WHERE A.IDAccountType = C.ID and A.IDImage = B.ID and A.Username = `username`$$ + +DROP PROCEDURE IF EXISTS `USP_Login1`$$ +CREATE PROCEDURE `USP_Login1` (IN `user` VARCHAR(32)) SELECT * FROM `ACCOUNT` WHERE `Username` = `user`$$ + +DROP PROCEDURE IF EXISTS `USP_LoginAdmin`$$ +CREATE PROCEDURE `USP_LoginAdmin` (IN `username` VARCHAR(32)) SELECT A.Username, A.Password, A.DisplayName, A.Sex, A.IDCard, A.Address, A.PhoneNumber, A.IDAccountType, A.IDImage, CONVERT(B.Data USING utf8) `Data`, C.Name, A.BirthDay, C.Name + FROM ACCOUNT A, IMAGE B, ACCOUNTTYPE C + WHERE A.IDAccountType = C.ID and C.ID = 1 and A.IDImage = B.ID and A.Username = username$$ + +DROP PROCEDURE IF EXISTS `USP_SaveToken`$$ +CREATE PROCEDURE `USP_SaveToken` (IN `user` VARCHAR(32), IN `token1` VARCHAR(100), IN `timeOut1` DATETIME) BEGIN + DECLARE count1 INT; + SELECT count(*) INTO count1 FROM AUTHENTICATION WHERE AUTHENTICATION.Username = user LIMIT 1; + IF count1 < 1 THEN + INSERT INTO AUTHENTICATION(`Username`, `Token`, `TimeOut`) VALUES(user, token1, timeOut1); + ELSE + UPDATE AUTHENTICATION + SET `Token` = token1 , `TimeOut` = timeOut1 + WHERE `Username` = user; + END IF; +END$$ + +DROP PROCEDURE IF EXISTS `USP_ShowReport`$$ +CREATE PROCEDURE `USP_ShowReport` (IN `_Date` DATE) select * from REPORT + where REPORT._Date = _Date$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_DeleteBill`$$ +CREATE PROCEDURE `USP_TVC12_DeleteBill` (`id1` INT) BEGIN + DELETE FROM BILLINFO + WHERE BILLINFO.IDBill = id1; + DELETE FROM BILL + WHERE BILL.ID = id1; +END$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetBill`$$ +CREATE PROCEDURE `USP_TVC12_GetBill` () SELECT BILL.ID, BILL.IDTable, BILL.DateCheckIn, BILL.DateCheckOut, + BILL.Discount, BILL.TotalPrice, BILL.Status, BILL.Username, TABLE.Name + FROM + BILL INNER JOIN `TABLE` on BILL.IDTable = `TABLE`.`ID`$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetFoodFromBill`$$ +CREATE PROCEDURE `USP_TVC12_GetFoodFromBill` (IN `_id` INT) BEGIN + SELECT BILLINFO.IDFood, BILLINFO.Quantity, FOOD.Name + FROM BILLINFO INNER JOIN FOOD ON BILLINFO.IDFood = FOOD.ID + WHERE BILLINFO.IDBill = _id; +END$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetOrders`$$ +CREATE PROCEDURE `USP_TVC12_GetOrders` () BEGIN + SELECT BILL.ID, BILL.IDTable, BILL.DateCheckIn, BILL.Username, TABLE.Name, BILL.DateCheckOut, BILL.Discount, BILL.TotalPrice + FROM BILL INNER JOIN `TABLE` ON `TABLE`.ID = BILL.IDTable + WHERE BILL.Status = 0 + ORDER BY BILL.DateCheckIn ASC; +END$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetReport_Month`$$ +CREATE PROCEDURE `USP_TVC12_GetReport_Month` () SELECT SQL_NO_CACHE DATE_FORMAT(_Date, '%Y-%m-01') '_Date', SUM(TotalPrice) 'TotalPrice' + FROM REPORT + WHERE YEAR(REPORT._Date) = YEAR(Now()) + GROUP BY DATE_FORMAT(_Date, '%Y%m')$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetReport_Today`$$ +CREATE PROCEDURE `USP_TVC12_GetReport_Today` () BEGIN +DECLARE check1 int DEFAULT 0; +SELECT COUNT(*) INTO check1 +FROM REPORT +WHERE Date(Now()) = _Date; +IF check1 = 0 THEN + INSERT INTO REPORT(_Date, TotalPrice) VALUES(NOW(), 0); +END IF; +SELECT * FROM REPORT + WHERE Date(Now()) = _Date + ORDER BY ID DESC + LIMIT 1; +END$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetReport_Week`$$ +CREATE PROCEDURE `USP_TVC12_GetReport_Week` () SELECT * FROM (SELECT DISTINCT * + FROM REPORT + ORDER BY REPORT.ID DESC + LIMIT 7) as tb +ORDER BY tb._Date ASC$$ + +DROP PROCEDURE IF EXISTS `USP_TVC12_GetReport_Year`$$ +CREATE PROCEDURE `USP_TVC12_GetReport_Year` () SELECT SQL_NO_CACHE _Date, SUM(TotalPrice) 'TotalPrice' + FROM REPORT + GROUP BY YEAR(_Date)$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateAccAvatar`$$ +CREATE PROCEDURE `USP_UpdateAccAvatar` (IN `username` VARCHAR(32), IN `_image` LONGTEXT) BEGIN + DECLARE idImage int ; + SELECT ACCOUNT.IDImage into idImage + FROM ACCOUNT + WHERE ACCOUNT.Username = username ; + UPDATE IMAGE + SET IMAGE.Data = _image + WHERE IMAGE.ID = idImage ; +END$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateAccInfo`$$ +CREATE PROCEDURE `USP_UpdateAccInfo` (`username` VARCHAR(32), `displayName` VARCHAR(100), `sex` INT(11), `birthday` DATETIME, `idCard` VARCHAR(30), `address` VARCHAR(100), `phone` VARCHAR(30)) UPDATE ACCOUNT + SET ACCOUNT.DisplayName = displayName, ACCOUNT.Sex = sex, ACCOUNT.BirthDay = birthday, ACCOUNT.IDCard = idCard, ACCOUNT.Address = address, ACCOUNT.PhoneNumber = phone + WHERE ACCOUNT.Username = username$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateAccount`$$ +CREATE PROCEDURE `USP_UpdateAccount` (IN `username` VARCHAR(32), IN `displayname` VARCHAR(100), IN `sex` INT(11), IN `idCard` VARCHAR(30), IN `address` VARCHAR(100), IN `phoneNumber` VARCHAR(30), IN `birthday` DATETIME, IN `idAccountType` INT(11), IN `image` LONGTEXT) BEGIN + DECLARE idImageDelete, idImage int ; + + SELECT ACCOUNT.IDImage into idImageDelete + FROM ACCOUNT + WHERE ACCOUNT.Username = username ; + + INSERT INTO IMAGE(IMAGE.Data) + VALUES (image) ; + + select MAX(IMAGE.ID) into idImage + FROM IMAGE ; + + UPDATE ACCOUNT + SET ACCOUNT.DisplayName = displayname, ACCOUNT.Sex = sex, ACCOUNT.IDCard = idCard, ACCOUNT.Address = address, ACCOUNT.PhoneNumber = phoneNumber, ACCOUNT.BirthDay = birthday, ACCOUNT.IDAccountType = idAccountType, ACCOUNT.IDImage = idImage + WHERE ACCOUNT.Username = username ; + + DELETE FROM IMAGE + WHERE IMAGE.ID = idImageDelete ; +END$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateAccPass`$$ +CREATE PROCEDURE `USP_UpdateAccPass` (`username` VARCHAR(32), `newPass` VARCHAR(128)) UPDATE ACCOUNT + SET ACCOUNT.Password = newPass + WHERE ACCOUNT.Username = username$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateAccType`$$ +CREATE PROCEDURE `USP_UpdateAccType` (IN `_ID` INT, IN `_Name` VARCHAR(100)) BEGIN + update ACCOUNTTYPE + set `Name`=_Name + where `ID`=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateBill`$$ +CREATE PROCEDURE `USP_UpdateBill` (IN `_ID` INT(11), IN `_IDTable` INT(11), IN `_DateCheckIn` DATETIME, IN `_DateCheckOut` DATETIME, IN `_Discount` DOUBLE, `_TotalPrice` INT, IN `_Status` INT, `_Username` VARCHAR(32)) UPDATE BILL +SET BILL.IDTable = _IDTable, BILL.DateCheckIn = _DateCheckIn, BILL.DateCheckOut = _DateCheckOut, BILL.Discount = _Discount, BILL.TotalPrice = _TotalPrice, BILL.Status = _Status, BILL.Username = _Username +WHERE BILL.ID = _ID$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateBillInfo`$$ +CREATE PROCEDURE `USP_UpdateBillInfo` (`_IDBill` INT, `_IDFood` INT, `_Quantity` INT) UPDATE BILLINFO +SET BILLINFO.IDFood = _IDFood, BILLINFO.Quantity = _Quantity +WHERE BILLINFO.IDBill = _IDBill$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateFood`$$ +CREATE PROCEDURE `USP_UpdateFood` (`id` INT(11), `name` VARCHAR(100), `price` DOUBLE, `idCategory` INT(11), `image` LONGTEXT) BEGIN + DECLARE idImageDelete, idImage int ; + + SELECT FOOD.IDImage into idImageDelete + FROM FOOD + WHERE FOOD.ID = id ; + + INSERT INTO IMAGE(IMAGE.Data) + VALUES (image) ; + + select MAX(IMAGE.ID) into idImage + FROM IMAGE ; + + UPDATE FOOD + SET FOOD.Name = name, FOOD.Price = price, FOOD.IDCategory = idCategory, FOOD.IDImage = idImage + WHERE FOOD.ID = id ; + + DELETE FROM IMAGE + WHERE IMAGE.ID = idImageDelete ; +END$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateFoodCategory`$$ +CREATE PROCEDURE `USP_UpdateFoodCategory` (IN `_ID` INT, IN `_Name` VARCHAR(100)) BEGIN + update FOODCATEGORY + set `Name`=_Name + where `ID`=_ID; +END$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateReport`$$ +CREATE PROCEDURE `USP_UpdateReport` (IN `_Date` DATE, IN `Price` DOUBLE) BEGIN + declare _count int; + select count(*) into _count + from REPORT + where REPORT._Date=_Date; + if(_count>0) then + update REPORT + set REPORT.TotalPrice=REPORT.TotalPrice+Price + where REPORT._Date=_Date; + end if; +END$$ + +DROP PROCEDURE IF EXISTS `USP_UpdateTable`$$ +CREATE PROCEDURE `USP_UpdateTable` (IN `_ID` INT, IN `_Name` VARCHAR(100), IN `_Status` INT) BEGIN + update `TABLE` + set `Name`=_Name , `Status`=_Status + where `ID`=_ID; +END$$ + +DELIMITER ; + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `account` +-- + +DROP TABLE IF EXISTS `account`; +CREATE TABLE `account` ( + `Username` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `Password` varchar(128) COLLATE utf8_unicode_ci NOT NULL, + `DisplayName` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, + `Sex` int(11) DEFAULT NULL, + `IDCard` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL, + `Address` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, + `PhoneNumber` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL, + `BirthDay` datetime DEFAULT NULL, + `IDAccountType` int(11) DEFAULT NULL, + `IDImage` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Đang đổ dữ liệu cho bảng `account` +-- + +INSERT INTO `account` (`Username`, `Password`, `DisplayName`, `Sex`, `IDCard`, `Address`, `PhoneNumber`, `BirthDay`, `IDAccountType`, `IDImage`) VALUES +('abc', '$2a$12$y/LcCe4dcYZQztVb/I.Op.aP.n2ZRmjYzccunqiskETZdPG4rjSZe', 'a', 1, '111', '1414', '123', '2019-01-15 00:00:00', 1, 1), +('admin', '$2a$12$3GnsmKfVT1Okpmp2ZOMGAOvOJ0M9WhLT0pp8nuyTFx5rENV4XdQ3O', 'admin', 1, '111', '221', '113', '2018-12-12 00:00:00', 1, 1), +('ivo', '$2b$10$Rd3wHvxLv4cr8HAd.ROMzu0RS2G3FJ7MXLUcnXQKvfFn9fsUv289G', 'ivo', 1, '', '', '', NULL, 1, 1), +('jade28', '$2b$10$aiZSFGwOUQdQIqc/7uBpu.FWyMLSfcNeQ.hPUmNscoJXpK3x1eHXa', 'Nguyen Duy Cuong', 1, '206117926', 'HCM', '0348222347', '1998-04-06 00:00:00', 1, 1), +('lht', '$2a$12$0Qh4b2gkMS47QC89aSSbi.ihwMw4UWINx5hPZl/bcpzMYSyzUNX36', 'Thang Le', 1, '14', 'Ho Chi Minh', '131', '2018-12-11 00:00:00', 1, 1), +('ndc07', '$2b$10$SOZJzBBodmIeadXt1c2i4uk.GotJIvffZpJEAfx0CKftdvM1X.wM6', 'Cuong Duy Nguyen', 1, '16520147', 'VietNam', '0348222347', '1998-04-06 00:00:00', 1, 1), +('test', '$2b$10$yxtjD0.OMqyWdsN0dpG9MuTbBeAZbqJBlzQueNWKOIGQfyOxmf.Ay', 'Nguyễn Xuân Hưng', 1, '', '4, Best address road.', '012344040030303', '1999-06-20 00:00:00', 10, 1), +('tvc12', '$2a$12$27LEJSAs2XcHhzyhcn7pwO56OBaJ5zFgjbVm4TQDr6MnCWzP88bCC', 'Vi Chi Thien', 1, '272639520', 'Ho Chi Minh, Vietnam', '0907889396', '1998-06-06 00:00:00', 1, 1); + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `accounttype` +-- + +DROP TABLE IF EXISTS `accounttype`; +CREATE TABLE `accounttype` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `Name` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Đang đổ dữ liệu cho bảng `accounttype` +-- + +INSERT INTO `accounttype` (`ID`, `Name`) VALUES +(1, 'Admin'), +(10, 'Staff'); + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `authentication` +-- + +DROP TABLE IF EXISTS `authentication`; +CREATE TABLE `authentication` ( + `Username` varchar(32) COLLATE utf8_unicode_ci NOT NULL, + `Token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, + `TimeOut` datetime DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `bill` +-- + +DROP TABLE IF EXISTS `bill`; +CREATE TABLE `bill` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `IDTable` int(11) NOT NULL, + `DateCheckIn` datetime DEFAULT NULL, + `DateCheckOut` datetime DEFAULT NULL, + `Discount` double DEFAULT '0', + `TotalPrice` double DEFAULT '0', + `Status` int(11) DEFAULT '-1', + `Username` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Bẫy `bill` +-- +DROP TRIGGER IF EXISTS `UTG_Report_Delete`; +DELIMITER $$ +CREATE TRIGGER `UTG_Report_Delete` BEFORE DELETE ON `bill` FOR EACH ROW BEGIN + IF old.Status = 1 THEN + UPDATE REPORT + SET REPORT.TotalPrice = REPORT.TotalPrice - old.TotalPrice + WHERE DATE(REPORT._Date) = DATE(old.DateCheckIn); + END IF; +END +$$ +DELIMITER ; +DROP TRIGGER IF EXISTS `UTG_Report_Update`; +DELIMITER $$ +CREATE TRIGGER `UTG_Report_Update` BEFORE UPDATE ON `bill` FOR EACH ROW BEGIN + DECLARE id1 int; + SET id1 = 0; + IF OLD.Status <> NEW.Status THEN + SELECT REPORT.ID + INTO id1 + FROM + REPORT + WHERE + DATE(REPORT._Date) = DATE(NEW.DateCheckIn); + IF id1 = 0 THEN + INSERT INTO REPORT(_Date, TotalPrice) VALUES(DATE(NEW.DateCheckIn), NEW.TotalPrice); + ELSE + UPDATE + REPORT + SET + REPORT.TotalPrice = REPORT.TotalPrice + (IF(NEW.Status > 0,NEW.TotalPrice,-NEW.TotalPrice)) + WHERE ID = id1; + END IF; + END IF; +END +$$ +DELIMITER ; + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `billinfo` +-- + +DROP TABLE IF EXISTS `billinfo`; +CREATE TABLE `billinfo` ( + `IDBill` int(11) NOT NULL, + `IDFood` int(11) NOT NULL, + `Quantity` int(11) DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `food` +-- + +DROP TABLE IF EXISTS `food`; +CREATE TABLE `food` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `IDCategory` int(11) NOT NULL, + `Name` varchar(100) COLLATE utf8_unicode_ci DEFAULT 'No Name', + `Price` double DEFAULT '0', + `IDImage` int(11) DEFAULT '1' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Đang đổ dữ liệu cho bảng `food` +-- + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `foodcategory` +-- + +DROP TABLE IF EXISTS `foodcategory`; +CREATE TABLE `foodcategory` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `Name` varchar(100) COLLATE utf8_unicode_ci DEFAULT 'No Name' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Đang đổ dữ liệu cho bảng `foodcategory` +-- + +INSERT INTO `foodcategory` (`ID`, `Name`) VALUES +(1, 'Starters1'), +(2, 'Burgers'), +(3, 'Salads'), +(4, 'Fish'), +(5, 'Chicken'), +(6, 'Dessert Bar'), +(7, 'Meat'), +(8, 'Tapas'), +(9, 'Sea Food'); + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `image` +-- + +DROP TABLE IF EXISTS `image`; +CREATE TABLE `image` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `Data` longblob +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Đang đổ dữ liệu cho bảng `image` +-- + +INSERT INTO `image` (`ID`, `Data`) VALUES +(1, 0x2f396a2f34414151536b5a4a5267414241514141415141424141442f37514345554768766447397a6147397749444d754d414134516b6c4e424151414141414141476763416d6341464331564e6b706d526c46545a4730336556687962456b7a5630316c4841496f41457047516b31454d4759774d4441334e7a41774d5441774d44426d596a45334d4441774d44417a4d7a67774d4441774d47557a595441774d4441774f544e6b4d4441774d4751304e4451774d444177597a6b344e6a41774d44426b596a67324d4441774d502f6241454d41437767494367674843776f4a4367304d43773052484249524477385249686b61464277704a4373714b43516e4a793079514463744d4430774a79633454446b3951305649535567724e6b3956546b5a555145644952662f6241454d424441304e4551385249524953495555754a7935465255564652555646525556465255564652555646525556465255564652555646525556465255564652555646525556465255564652555646525556465255564652662f4341424549416f594368674d4249674143455145444551482f784141624141414341774542415141414141414141414141414141434177414242415547422f2f4541426f4241514542415145424151414141414141414141414141414241674d454251622f3267414d417745414168414445414141415046514c3833307a57794653366c6b6b697956566a434569795863706d457136756f73674e5a5a41315a67544a30556d716c466378676b305630514d4b795556676c4c4b75527146635a7536764f376867516975726f6d776c756b324d6c6432737a6a683668576e6e4337446d75434854796d557443383758446a5155774762716d4e424a55585668414f6c564b7467465759754d414f5348693745752f6c6857436c4c6b41617a6937714a437545495946424b704a49453669736c573144417958567979364b786755536b5133566d4d696a4732724d49455957464b724f577932416c7237436565364870646a48473264676e506d76364673495930357a565472316e5057754c687a39594a6650386e32797339506e3839626b6e6f38376b3671473855315337794163554959545277685357514c4a4c49733541526b7438544a5052354c7572576d41575a4a4b6c4f536b4b77675630514a695651776b53484645684a624d4b6159513258596b4d697a7375354c534b727947454179784a4a4a616b643955776462716452797739497a7a694f707a416e4a4d4559457a63756179645357535346793751626c67413856352f6e2f584a7830384a6b394c794a37654d375969645554526e624d533047476d304163697747564653704a347970667138746b4d6b6c794c566e4a41596f3175364b4c6f534a6448624a4a466c4956634e6f44456b7371494570476d4d585a4a56315a53524a4c4b7368513947666f7375394d72646e446946376d545961586430784c4b4d6c6369474575777055737543526371496468646c324e6b41786c7a594f756e4858795750312b58486f383672304743394f49727034585a5153537953377156647a59793478346d56667038736c5753355a4a426b49674e5a4c71533771536e4b75324542785a31433451726347786b4532694e5a4258544262416341526147633961575a754a7139517a30346248467256745a5935546b593044786b3671745a4b5664686e6d4f48477174355953534c6b6759534955754a526a4335496c51496f4b304b7a307a354f674765766e755637546e5a362b545633655937354934485159564c63754a3461435870385a446445757049565853334b75726c32736c6a69464b75626a5336706a36695177726d3950464e4c6e565470676e54704d4c584e564c32364b796a3139757078745733517a797a37724d3535477254454f787444317074477653346151316e426e5632517175797064456c31566b4d686b586157785232584b757958564441675a52534d303739466e4636566879535a697a756135584e3946793531382b6e6f5970365157794e706a5965427158365046646e734f6366533078794b377478776839444c4f4271324b44612f666938504836334d766e47576936597a4e706d744f6a5a69357a587434326954566d314856367030645a557a527030793234573253453573456b36794f61557359426a4e4765387454637a6b65374b354830444a6931746a49774a644f695742536f6c574d6c4b56564e4561523636464749646e6d736d545869656b75696b376e537a42726e4f7a6f706c6544667a35766735756c6a65724c477964565334766764367a362b4856574f5a6a36534e765351476c68443843744f37717964484144775a72742b6e6c646b326566394255654c31394c6c56315578575236633356443361396c4b3135706271537362547a775a58362b5a70546f70556e584b6d4c4e59702f4e54637a7a654e76324e2b503135333657656261767139506c74326364742f4f63353942516c704735356c70693559613770626b6f75566147444b5a4e4c5557382b4357665331716c58476f766c5072375058737a766e4b593932575868594f6a784d2b756f45646445795272786c39585472352f45336455717848725a5a6b592b584330624b756a5967315941486b5a707a3661356b596a69426d61557146364b3044706474717a365131556b53576969366c613749323839424a4a6730446a42517a49327a4b4b3774646e6c74334f356a5a7271644c6761493952743450537a6a734f7762584a7972626d43563156796f533543537244675244564c5849765971394665583952345733796d6e4f48546c396a36587a2f364c7935524c465a33774f56337650543169463150524a63545049642b6644584e68427558556f597069347364563135366a524d30616373564a71764a4e5a36624f54654e39712b53356e766448792f627436416d79645157396135776247735961637130374b786836785568357856633541333531536a6e354e4f756936744a7564383650666a3645313075747a74334c5057646a3158477149596a7243356b35636b7553564a4a456b6c53366b577479365434623371472f69772f5675467250472b752f503841333035566a31633664664f346e4978367173593746426959797a6e72352b6c67545349656f534f6c464a55354f3852564b6b59745930364a433630557473574f3751764f323757574831655a3032642b3744727830576a5370764b6a586e6e544c6e305a377056414c4c677056356a326566706d46665076536557317a74637270672b78786e5a3333534c735a39664e6430327958313850523535626f51366d576b637454736573656136764d71564a57586d4131326f37546f4532624c53316d774f7a4d546c7a5766536b7775647635324c353166543562303274644f78795134374d6464666c396c77464e414a6d4a706f4c6d793951457a5067617853593350544a65717a497a73587648496d72456d68326271304731355454647550705453776574724d6e65764f75526d365754572b637432646269343564666939626833485034586f4f48766d67546d737a547139486a70782f556a30755870653353396a4d65786a4f51644370724f30446d6a596b6a524d366c31594d6d345056697256334679796d756e5850744e626344626e6f74357a3963396f3057654b61634d306e4430553531357a4c324f585052695672794f785149313562463634505238727a756e73336d353375717336357a73363363702f583150506458444a4e4c636d6a47396d6b4e387566587133644a7a3237347a6a617751584c61736144464d6c4a5631574d316c7864446e5870687936736775786c35364d476853633348314c316a6b396a623070526d734f6653644c48736a5a73715757415171575a644e465543396332766c6255585630704e3636427a6a4e365a6e74303046694a6463775670314e66416463656733656131547a656c6d4c626a7730706f357643342f712b4e505678624272766b6c7876715563395879704853464270595a382b34563434396e4d6e447a2b69305a7643302b673152784e76544e636c505379706455314a5267737369474a457a3646745a325447317035376372706e357a30524b584f6d577454716d464870444f707079626c31326e587a4a365766576d725059366831634757754c644778563831575057394f484b6e6670314a517250546f4e3557784e64704e576a4445493038647651664e4c586f3675726a616e5030487066446472487a7652314a6a784b356e567934362b587939666c7655714d6c33303659666f2b59464e6c44475a6247567763646e70632f4e37476265386450505a746f6b4f344b426e4e5a6e456f6f6b4a4b34306b6c7952594e7856673953342b64317563317a557552617170656f37544e4d7a694871737a70543636616939684d354e6b724b71427a556b674e774d375a6e5a353356516c4f6272366d7a476d62657a6d4c74374f6e6e767a4e377565394e7a75652b3450796672664d4e4b31593361396d787566566c7433382f573833734838337063766c5262417a655677665765636e626e7952323774315054383243766a6278733448506236754a394658523464645051547634645464523531625532795143424b7462564c4b6972754157516b67304f41597953375174596e59727057653057725974316a64656430576464504e30364d6232744235797a496b625733534b77437a326151786f6c36586976542b523133616d4c36646b5a4849617a307a537a6f665556757243795457376e3654704a4856584876733635726c61644b367a3354493946303857766a382b366b7a6e4e792b7a6b31767a45335231667a4f427a2f6f664a646e486233356872306e6a5a64586e39447739393276487278765159453253576f5a7342574f4663436936616153594855456c4c69584b425a6e4e4e4c794e784b764f314f6f6246754861556c4c7330354853376d383835586163597936485a55787564676572425572523259634f6436764f396e6a33712f51477670766a4a397270764c77372b72686e544f68756475704c725153577936585957746133633472656974446f6d7066663563756c616a7834325773376d6b6d454c6a70724879445366522b7a387a50714f633069396e6e394c64523666503348524835475132334d7a637a4e56466a4a566c514b493156335272474267464d79437372506558564849533751714c7a57747a3762477341326a4b6f7569495a6d365478314c7153764b616d63626f74624671517a76795a52644344475374315a6776667176354c3937313839715a6e4d68796c70674f73714d71436843335a69355a727271383836394750566a79366d5170794b55786d694c524f5978736d506c62467a37667a57314c7a746574442f4e362b727678362b485a7067655151775653585a456c5541776b47565547303471366146416855464c4241424f5a75656c7249416271314c5768394d4b7169375647326e6e5a6e54545171484a464b766d567070696c69544e44644b6371366d7a46625771314f6453504e6f56493667316e4e47686c70766d504e525a796c334568724f702b54627a787333493135354e4953754931546335304e793538382b724f664a6a357a64582b682b5535463179367536504a3365543364702f4e36584c646e5235324b6d715a51673156564c42576b695531596970335149344b477730306b4d4a6e576b45744b473657727177394f643676457861565a795742565a304d4b695577576c496374463079366a6b4b62314c52644e73467476646a6c4f46567a623870307154644345545974314d776155644d73364754644d6133705a6e6b3867694661305a62654c727763393979636d5235677058364c344b3674336d3946624b6435765157374337485463616e4e4368755a417a4e52614b724457534a5a724772464752426a466749564343696f6c6f745a676f3349536968484a3072707169614357706175367a7170636c75537741636852456f6930756c5351706f5264473839615a7135356f6767374e734475355464623545756a4d72665235772f556a577731716d3577563161566c64687a70576e476a47796a5a584571302f552b587531386f2b585475743432334733684a4f6a4e6544524b37497a4a59764b53556c564e5a74715147306b773756616b7136534161675632414e535779774f536f564b524c6b7576566c314e4c466f4b4e4d444f6770674c4a54434b61464a6b4f6158547146577768564d69685a576f464364417430464e61374f52655455524e42433369334d5a70512f4f574d456d446f6f7a69353364342b6438736776485970636c34704e66395834774e667334397346644e63365a535168765957497a636d4b5a7056685a4b475777774b515469376267416d6c596747454569324c555a524a4c71426c4a41794572744758517272713836584752704e4f6b7136634b706a317a53544e6c496a67416a4a4b754d4f7a4e4778554d4a726179593343694f37676d302f494962525436504b6d69317a4d6762636c73572f65436f71336a6c3862314263752f6a35366563396542304a64394c357258356e2b6673795a776d3259617a61304b6b704f6d376a763164395a6f793642564d5a6e75526f6a4e4371686d6a71446d464a4669726956494a436c7164695353355570614d7a70725331444a546c4871315a544e43374b56635a4d376f5851524747714a714578733151787a5a444f5769784a3643795648784536714f42594c51446c7a4559576d35585a636a5471592b5a6a334f75684f375448314f6c75597a54544c6a35736364303431524c3539697a4f544e354d65376c365a30466b756447726c4f314f316548564b386c544e62416779444e4c74647159574b4d4778614f716b7a636777636b574d577953355631445755726d4a624e75626e4d64466e4e47616d796c4a41717573377547534164584c5a516f45355a4b736d524f4558414d6b6b686b5842326764544d3170306234342f4e64704b6a753075365348566168536f68515a487a676776575743495459484d306f632f586b314f646d305939597069623232626561374e36624d6a357031704f47674a57334b754a51324d4770626342755a64727156784c4f773741346c314975784a5449626d794e646d6738725a58476b3570305751364c6d64754a526a6f6b677a4152785a6e42326d493641525a4a6d544a6d62593943516d505362634f357a4d6c4f75655557522b39644377766374744b47316e464e30775250496f4a53725531537a4f4b6457736a4d374f54487079394f49797061783256713774584e304e64416b73795a6134724942426a49314a513572526c53585958617869434e4d43386d5353535154556958633077684b364f36764f6d514c686c726738465274724d737a64565a576d7853434e5a5a57446f69476b56694d76473652724d6d697179626558636579305a686d4f694f5a6247523250587431547a46714f4a615454574e4a7367773851465a6e516c72534d7a36633935356b364d65383545476e664b716c706471597264474e6a58513063353264626a794e7366615a4e4f454b477855566c716d61776b7931316f5a4a71504a6f74635372784367484b526863746d733232476f70544b696c6f7a4271434e4b5546597942464d3076566c714e5752567374524d785a355735626465545a637479624d63783147386b4e5a362f4e6e46543048663841506274353663676f476a6e6b7258703435306f4d6a7a41613033766d7a3679593575666678396357595272654d53484c316971756d616b7374697a6159334d78725537473572537a504239716d5461436c5a46794730755532315445304d7a4775316d4e6b756d4155706b746b70515a646d31457a7256455358544557724669454646793768434b367a79746b6459537731676f597055435a6e646d39445a6833617a70357652777a484e5845334c38386f3962727a6a764856666c536d7549777a57726d6a755255564a567767765a4b39574e6a4e357230666c75764450514e336846624661786c6a77316c5a6d596d5044465156796168444774466f4931336e4964614a6b2b6c336d6d576137725246574d4c4f77306e6a3053616e596e336577383775644f42545a414e79754a4c4a7068726b336172697141376f69546372584a7a7070576f4c484a4664724b536150305a4e4d62397548644a6f77374d546e684672624d7965686a733648657a31633748386e534244356d57705571364f496d706f7a507a34364d504a4c7a346647326f39504a424e6e58414b4d66523568625772664e436475666a7247476c584c717169766e746450755645624a514b6a744531304f705635724b455a746f4c75444e42566f504a5a76667a74475a3148344e6b303461725057795654545735546c304c573262494c70734c456856306d3431414a534a47497558414132744a62686d724c706d7475374a72786b38577846776e5a6f664d34655a364867616439334c32614d566f6a4363683556616f4d394e6d4b6276714d507175667a6e6d2b5836756d66416c39496e61664e462b353862333559363068362f4e547432753435756a724e357a694b33597558624b6e73596558626e6a72546d7157326c4347454344527445714f4672644a70466c5761454943344e446d494f4e2b2f6c375a726f4263787571754e584b6b7474555630796c453252424d45354e574e7a75305465644b31455843466f32726132657a4c6f4e32376c39446e687072305847683272517a352f6b64376757396f636d7656596a6375347a5a4f767778655973795642683957624a6e456b4f73626e48586d3850734a5a34586a2f5270317835486a66514d7165477a2b323575742b53334b7a335864352b64565a5675544d716f786941517a51776d556879706e4c516830713245316b703453716a5677425655614e5748546d6456334e3135302b4163365370553159776d6f594d624b5757626d78394c4978684669643879734b7031724e577357366447755331646d7a4276786c32724631574c304e6178357a6d397a6853394856796e39497a5330726e467a646d4b314f632b356d4e6e72706e4a4d7a755345716161725442746a59636b6b74646b4c567046666e6e482b747336506c5744374278362b5834666f7669394f63505635326f6f62724e6f7a50544947786379676f3352556b57674a63727175516b69756b4d5765576a5a7a6e3476526667307a627745733668674454694570707a45757a735675484e3539613161353831585635653869785a3035796e7a545771644c6f325974755a70656e637a305354717a7a3835693363323636577a6c50365a3278716b356550713436352f30446c657178416d7159787a44584e365957613954525379566872596a564843476c6777774a4c6934724a41524f62654b2f4d4f4439743564664941395278656c5776516d7a475253305930444f6431714f7a4e454131484c546c45566e63434131557a647a75612f44653345374f3945475454474a624e4f626e504f7451444d394354706d70693566597873637739754c6554666c65316f666c30743639665032346d37667a647565666f6b594f69352b63776238647651587276724f5431554f6b467839574e485379364f634f535448477569365553494b4f774b306d6f6b6a7955327259697874717364456e426a554e4643646b6878423576556835487950316c545877752f70486c756a7a70327a567a7173716f37554c4d6f414a416c5564536a446b696f3046633349656274626a626d3747346e7a6272546375776b6e4e75626e644c655061735378523833495833756473682b625430317131344f686d39445a6e3354485466685a6e6a784d622b6464622b69335630786c584f394a6b366a52346e45736d616a4a6c787a5850524c6b6f736c74565a4c464775794d707a5575577271444c42736b67474e745471496769484b69584b716953635879767a4837623479337746395046307564686f31494b3255456b7a64436771787136614b45776c416a6d464e7979613375776e6d6279783648586246484c6f646a3035322b4950476a526f576c456c6b6d494f7678377254302b5632745864304d65316b3932633838754a7a4f6e78745051715058764733574c664f65535835794a5a2b66316465636955776f4f387754734667504d72705a52304e484c67563163744d535963456b635379434e5255344a646c79695358494c566f435879766a507150674634326671352b6c346566734a334f5a65684c4930785530324c716f74774a62564f7a5255594e4c596f7058617565374d3644734f6961304f7a484e36547a4e7876557a4f39564a31343874717366516a4e3175583164756875783632746f30656338446b656b3870636572313465685a304863752b5453376d6964416c394b387a6c54576562486e3169547543367543356f7146453236515a41425435676c746c6f4e3342744657566b4e374d67476b756a737578744b75354c6e3837365655313878523748796475564f6a50746a783949626e6b693565305353326e5143437344416f344b6d754e597249496537472f44637a46706d394c736a6336317479747a765368745969483559646f3850556d3261387a4633757a363656387a2b70636258484830632f453654536e464a4e576e702b6934584a32306e6e4254484d74396c50587a585a6e436c75454348424c59645a7a6b69416469343443413061753557567355645761323251704568564c4343576c51686d6c6556395a675835756a3050477538434f6e6a314f6544785a794a336875344c30424b753649706b67614c59716b3637584555474e4463353531736669646e57742b44544e3633356447627a3570356d5a304f6a77746d4c36626f65623738316f446c636a726a76636855337a704d43355a313866744f577430624d5a616b42356e775a577370505a7a4735494b704a42715357564a7131556b484a4b717045734a4975354b7370434d6b5170496b75516f3545475345435336356669354a76454d6c6d524d6c5a4653624b435346444a544a4a6f565343436b614f535a7a59535462354a7a3037524a4e6148795a32336a53414e6b5462726b356b444a3235614d556d3548535a653536386e6e7231795a746c4a43704a622f41502f45414445514141494241774947416745454177454141674d414141414341514d524568416842424d67496a46424d6c45774252516a516a4e41595255475569516c4e502f6141416742415141424277474e493058706a706a3845644b2f3645644b78637357495335796d4d646f4d4d624c69594d6b32774c46745072722b5263767248526653784769365272476c68656d50774c703961652f3962346d4e794b554d6674646c50327659725665437a524a66684d6d552f625931466d722b6e74475466743573782b326c657a6c5370793278766a6b574a39486d6677574c61322f4648345636463058534e66662b71717978533461574b584262577063424378616a776e4c672f616f63713659716e62426a6377324f5759624455596d772f4371787848427a55534966676d73777178386d544b7152356a544874766a616e456e31722f553964642f7878304c353666732f71522b4f507866517365424b457a4e71584232453462774c527377716b4b522b484578477077323162675666416667757932482f7743624376515a624c56703874376352474d6f6773584a2b54614a472b6e686236657456734c2b4b434e59382f36556178315745707a4e69687772735575466d4c43714b7535612f77436578694e515739367642776a387871633573395464496b54334b3732472b6378345379726e654966507579493175523072317872486e726a534f69507772304b737a5970634d386c486856384b754e6a456950795231794d687876447455774f4a7038704552364f4e686c376355584c6c43726d374e684c4e642b326c67716247426a4a437a724339454564433963645561582f30466770556d596f3073594951734c30572f77424a6c794870643254556d71535661554f3844554a5770666c344a792f2b4973315a6c6d64544b57303336592f30343650725378596a3850735570497a4844304f5773466849464d543370473335593638526b375261434c4e35705a586d716a33782f62532b315875374f7248383864567459312b7677657a48665465707477394b6168516f34514c4236463068763969785939444b562b5978794d59316a706a7267556a705856667872726a755738484c6b685a4f586e42793857776f555a5a69685178694a566a364d5a5858474a2f3137365730784d423646797077386b704a747073572f77424e5579456f544c43384e466f4b2f4459783054364938696b6552666b52455363686856786b52436e52324f546a5567626857575439747a345630704b6b6e6f6e304c4f384374456e73576334506a70485442342f4e6b5a4766544b4438503548704969474e4956455935546c6d4c36526f76345631386c4a4c79517172427a59672f64626e376a496c64796e772b3044634e693548426a634a59354651564a384c53632f62356230316e782b334f524d795546796735476470356553437067625a483051783546552b6a59386e782f417652483457626154493533645a4e34365738465664683772424a61564c755a614c304b747a6c4f706a4a684a694c467861586770384c453250324a2b796c526c355972626a565a595567576c3777685a6756736d46386c525a387138774c61536c54675368377779467053323337646c4d4e6a6c37777932694c62444c4f78385a4d5a766f6a785956376e73553843744461656a30654347306a727670666f5a75307166455a2f425354797964734376666f6d437275737879354a5863774949333067536b7a43634a4d69384a417442564d68566777556d6b6c6a6c51706778772b30454d6631486f4b3846576a4e4a6a4c6367706477736678365135545a704661574f566b553652547043724239526b63307a735a584d6f48776d44346c7a4b464d6c6178736639553355353843326e646168353076596d33342f726f62777350364c64776b6247526b493253367356687076744d51756e6b6954486370556f58666d78427a704f5a4a4653526536444c79633070316939354651526354484c64366b7178777a356a553059346a6873642f6a4a5262637a78675a7269696c504a704552796d757774745a766f726269507554596c69354e744c484e576d4a5870534b354658636d7646684b323847654c774b322b4d4e3652746652362f48364a2b554574354d595967566446494930654370657a537a5a4966384159597879466b7938454d5a61306d786b656c4c37757270496a6543676f33677a37546e4f7044544c77552b335a6641316d4b2f42724d5a496a724a69306b6f785469626c46436d6c374564716d5a6d5a626c795a6e534a73492b526b4d3252434e4a68596d63597533456a385a3348376947754a78557154577a4d78654932457135646c4b73336947683743746b4b543966517243394564666f6e774c474561566138554b44762f414f6a5772506e2b6e667145566f7754774c6f2f67722b426e466e495579734d78356753697a43634f525167576b707959465135454363417437725368544831796c4f576c7a6c71786a477549744e5a4d564d49465252494657464e394a61544f574d573079495979796768747a4b494f6150784445315a615362484c515a43525746664b525879456678464b72346c4b7550636a51316a63697a7242695448345949306277596c7450317976687745777257534970314a69782b6e38542b38344e586a522f412b5577787958735733312f6169554657434b6667784c46695a37594d785869544c794c554c69754b34726e4e49664b42544d7a334d7469434938464f43354e7a4f356335684c4d327578654e4c6a5a457a344a7767646f4771475a49336b794c2b42666b4b38724a5165465551537074615055722b4f2b77756e737473665a2f3868376f346447523869316a2f414f505638654b6d6e61326a576c53765877516d717a514c3431783039786f336f7a476d35344d6f4d7957334d7a4d7a6b7a6b796d54504535684654774b32526d55366b435656595574344a55384539786a305a436d526e73537a5767766d56666d637249616b537075704a41724332754b6a4c4a53713471554956564d4d6c4b666a2f4145763178486d307a525a6a452f52592f77443248446e75644b6a647058715a473769363537436b47524e6965346b6a7076706376305a5745716d303730766b55524c6b544f523747316c6f4731794d68727366493466686239334763596e433353727864565969463474784b30566f307437565a6d52566e4b794a4b32452f6b4b535442536247534c437466534e492f486a636c526b5778503666515a704f492f5134382f706642765234315a3072393231535a326a47626e79333331585953656d59366369356c706375584d6a47346c49536e4369434d706a41304745474a6253574d68644761422f76684b4746506e316133387453726c6e55686e664f70635635526f45666d514b75786952694a386c696c4e564a4b624f49394a324a54452b6a497975527066584c384c4c6b516b51656a354366456b71654236736f7a527a324f644d6e624f6d347369726338454e426a63324d644c6a4f5a4735666f57374338503445346542615347516e79454b556236596c6f4d626b76694e61537863587562526a6861584f726e46562b5a515a6137396b48392b696d2b4d784e46736861454e422b32533845384c344b54536f69764e6a45562f526b4c7552706b5a6153367241723545474a754e5578456547364c46694e473367714939344b744b4f365753353730334d68436e6c45437359584c574c6d4d484c6b776b5868546b4a417949637457503238585032782b30496f7974686e6b5772657772614b7369714a754b7332306c5a4a516e366d68376b5a643450374755795439554a35504231472b534e465738725a2f5536717374614b534f7051373155704c755978734c3239764e6d5465526b563446764235334663766f3157465737566e7139744f6e454757786d63307a4d726d43434e4b6b4e6c305750527659713832784b4c556d377a3274482f64495969746949356b5a486b39614c636c6f553573534d356c6b4c625247744a457779334b39484935556b4a4e796c534c456568424c6b72637878735a4572466a47537034473648712f787176787350327a4136796a3278395738484463464e617a4c77384a596968427730646b526a45326949796b78557353786c344a7958547a70456c5772796c46797174457732786b5a6d5a6d5a6d64786167726b4d4c5546624c5778492f6764567152497a39396d705951666347524e5337332f647673552b4b6b537663794a637a477254454431616a47626c4e386c6738693930434b51676b54417153776c4169677079554f5757334d534c54706b5a4d655a474748476a6f6132536a2f49623671726c59586857636f63456c495663597469314e6f684b6254535a36486942624e7371444b705079764d5a474268754e477276676f717a566650495a79573845795a475a6b51354e513568465157727441727955717558524a5770576e4f703364795066617047325a2f35696e2f6a6f6638416b4b522b6b4b4c2b6d48374b594b6e43756f334d51704e6b787955735656334b666b76755566416b5349676c45576e695248527630574d38544b4366517855474a30386b724d7241367a4a792b2b2f4c7037437262474d45704b55452f742b336e63793562576f4a4d69325759686e784d344c33506b517474506b5933477373486e66496c79584d76476d586a6f794d794b684469754c554b466650625634324b314b4a794c5a43364b51574d44457365594f51724463416a53636a596e6738694f423346344a536e7755465067786548734c544c644b376c7462474e7a4b46597979476134796a6b33794c574d69505a53677179336a42544557696b796652335746534733526252426a734d386546685a677849316a375a386438737433635a3969574763687a314242633961354766615255324663577155717530464b727a45315a6369716d586455577a74425958543636464a307930707063576841744a564c46693274792b693945364d75524f614757384474754f592b37334d694c79526b306e776b647558525759655a6c56576e464b3552737a47567861596e67626578426b5a4755324d6f5969644b31664e78717a57477147526c73544972454d584c79526f2f78477137327a38784469734b32346a7a65446861306f7939447245784a785650614a79676a47592f426c69632b444f355451565254332b42664a42596a706c526c685233476e49614c6b6b4c344557356e734f38772b4b792f4756696e52536b6d644b6d3774456f746f7446506c6272484d61366a4e417a486e565633504a785662436b4d2f615a6d527a444f57466252574d6a497946334b762b4d2f753473692b42573843744a6c657854596f507a4b617a706259713971744c34754c4e6f4967694378695867715631533556343835395a696a6d306c4f6e41734369395536714c4a636779365a4b67336a583255303852734b693355574653444f616c557032784664456d317659306b595849794f3653326e6b547473636257356e453259793938775a2b30697154574666744d7468574d74685732455962654469365745354b514b496b324551703367344675796568753644696c786b6273324c48736d7069564f496a475a72766b553438464a5a4b5369714970454336535a66677565544c534e4d68323844534d4e4a635264377363504f4c47584d6e4b6d7a3133676f553751544f5176627666323765737a50754675625359474f6d6334335a38366a746c4178556d474730746c61463947573043735a697473513367526972536971682b796d3553344b71347643636f78783058796342384a315962756772445535536457714c427866475245484d6c784b6353556b4b53574b6343437157317931767076704261644c615a626c394748596562794f336e534e3546466a775a524f314e6645492b4d455663684c544a6c76412f66743243704730737362436a6544346c523968587a4b39567166444d552f69626a2b427647744e4256507253347245656853346f6c643659303879444933754963497370773639457756467a5571557057544f4c46666a30534a48347836702f6b6b355254515259324b666f70354361324a755a644f526b5a47524c644f5249777a446166516e6b55396943364b78386a496943464a573476614d7a4372456c584246676d764a58713833686e565070554f5645307875486b2f6273527733673556686c4e7446384369734b786d513472374763364b5536664d6545743278486a70684c6c5469716c5461594c464b6c6b5962466849454575495270505638756859303861584d687075534d4e4a4d6e3974466a7446464674735a346b506b354c4339746a5a544c496c4261636e64344d7a69477969433677704c64686a6a63566f7845376d7653656e4f4b31486f595172523870626f552b68375a4558496d2b6b4e3446592f714b737a74517038745930383658364d353246526d453461425669433471334654774b6854555558384f576d526c305a47517a444d4e4a6666566674644939454e7649734373586752705976466a4d35744f54766b56716c68636d50695a6d655733784a745563792b517237697355367333675a68394a767074436f793972452f61393069576b2f74496c696b497671685352494638696b4732716f4b70546f37774b753351676c6856496a775746307553584c6b4e3133364c6a444e33444539435270394732724e436d636b637a49636535334d55346b617153384456356e624f564d653636744d515779552f714b356c695a446b6a65465a5645694879536c2f4c4b5179343147524e6d516e357a6f712b424b57396b38454e6b4a3449315558635653494d534e62324b54334b59713947556b6b3672727558504a477468703065526d4a36463869365a615830324d766564344d6f48376958576e454331336b2b523272764e5a6d6d33774a50526c694c5a37444c33534a666d4a484d336d5a6a2b42682b37646c6e425a746b72546a65496e47467331706265313938626e4c58744978565261757772514b6f6b6245614c3446463349496e52496d77766a54433553535645555352664f6d576b79547172437a4f6d526b516247576d576d5977303948304c35493169326b6165686e2f7275586b386272473845385243795373315a4c347861664a6a32334c5830526a4c474a49584a6c5865312f3677334c2f68766c436f6332316f335a574666794a4d774c354c4337576e4831536a774c344538614b32696c7836324f314e37774c344661786b5a64776a626c4b6f4a693238433658316c744e75692b6d3559396c795730794759393953483170396135612b594c454a3764706468594d6862775a49684a62544558546d6e506e416171307966313055677838482f314c615241736251556f4638433652706b5a6244393965536e454b756b515239437833434646344659555856756d474d7462696e784a76717a586b627158756d4e62644679306d4a34506f61356a596c63564d533935746a756279537a47556e4d597a59796d54485845784c43786f73436977574b6169514a30732b4931582b7662353578596a54794c41676f6e67334c6c7962365332742b6a4c54305a367a705056416b37775235366474502b6d335836743945376b7874424b69715730735738614b70695176616568534646675742525264636875395a4a6243304c545371686857575a5055467a794b6f716c6942474b62364e6333316e54492b5669335250524f6b3961514c3065756a2b32766b747245482f64506f6c544854457470596942564957366d50614b6552564b63486f58783053316833373557616b4f6b693163474a3431354c614a694a674a6a4a797369615242547362614d5a444d5a5250526c76302b39474a4c3678304b4b776d6b6e30596c7459364a4c584d5359324c4669324e6a3636665a5978465156646f4d53304750675666496f676f6f757458775650356b766b4b5242633246454565564b645535686d4b346c525a4a6143574f595a613547524e79444d793175582f46483076694253786278707357506966576b36596b6553786a376b574269336a5352595051716d506159396f7137515531764d6b4b53704b2b43336756635377756b616375354e447448705052655234786d3648737a463768594655565a4d6f67686a6d475246744a62532b6c354d7a4938365a4564475263747047735270596758304c7259747262784d6c746257677434474d666675444578306c626b467642436972344557425259334d6469786a344d5332326936723549555877596c54676b715a533342505469546c3249694e7845455577324d5355475753484d78484d79574d744d6a655259677931794d692b357630543072724769543057307830685353786a344d64344d534639324a676b74344c4674725962466932777132734c3868664c4351523844364a58775151657446464655555a6f6a544f4a673259616e546152525252587363302b5177777a6d65516a74427a636a49794c33316a572b6e767038394d61333058534e5967747269596d4a625445774d5346753048737879495863784d66426952472b6c6a3257327445486f2f774371523345526957323035384b662b6a457a617278755377542b6f4d3853513953724251344b6f6f6c44474252534f6961673157444d6c68584663796776706b5a463530763052503449366f306a30582f444d474a59784d53464d4445565441784d546c6d5062426a345037612b6a304b5969706b70506771567075566e6171734e536f3830586832676f63446d31366643716845454369365a53784a4a734d53786b4b346a3346307631334c2f414a34496e7870355072543170376a7074304c476c74624831704878316a6f52636846375949517266346d4556716a43634e6b66746b577879315a42624c423530786868594e6f50524c6c384e3735324b673178686d4d6864696d7772454d58496e386366696a53356b6657766b3964586f742b4c365052476a46796c4751716945654439515a2b5868773147565253466c624472474a532b4f6e7846572b6e6f557975514e6b7838526d47396a45364b776a694f4c70452f676a574e622f6a39693666527566577347576d524f73433965523947516a6e44726b7434375334747975333836484e524949624e43456d316b7063714435516631757247517361657958786758376c6d6468764e6e38444454716b69436973626b46795078722b664c53444c5968746373695845334a595354497938482f31472b4a2f57444979324659794d385845376e4b485a52506b73454b5a5163582f4143316c696c776e74507162734c75536c6c6b53386c5276365563386263724753594e344e68686d395a574d726b6a623678497243734b786b4c2b4b2b73437a7066702b7568534e626c7954496a75307978676872324662456c736a2b734871444969647a497a37625a39706c2f46662b347678486a744b565863704c7a4b6343646d79764868326a47422f354a6c7548346e42384c64393864685837594d686d78735a626c5372684e70715378764f374d66524c37795a586b6c766b4e38527570524253432f35564c6b66686a534f706e5055452b432f614d33694e4c6c7a2b724870535769636f5674696e4e397368504136375870726b38433335634755744d4372346176562f69614f47717256734a7733383262586c536c7368465a4a67664b556b6f4d7a6256616d4b694c465a623434365a48735955596e36627179465952685746597630652b753470446668586f6a53326b6c346932762f46466157364c33322b4a3239776a3478416a3935374b5a2f55565035436c5539637a63357a7874784e6370306f6c55546c58534633796947707a4f3752536673697043706932584d7652776c53737a556e4d70734d3073574c794b7431496759596658305271766b566847495976704854636a534a4c6936665834563173664538375730596c72437663767063383635626a54636139695041766f3379675162775a54544a72484f676e694f306c706d6f556e696d6b5077484753395356715656735a73744f4a35584d3730794f616a4a4a56797050644b334e327359474179624878676d666257617a56504a5064316539466b56685746627870483431495967763172706c4244482f544935686e74704e7a4c7846397a3058306b793847524e547530574436454c465670556d7151354e586179797a4844727a61454330596f706d73632b6c41715930724b7a4b6379475972786a7633764f564f4d727a4b6d356d595a4b4d754f517a4764695a796739395545614c4a6b5a454d5a475834726d5172475172462b6d35466a4975626d2b75786c7035456258497947312b684a4662774b58324b6e67644a4c6166314f47614b58444a464c4f766b6c4f6736706a7a3570624a7836316471723733576f316f47724b714b7437365935484b764e387353743853715a454d652b6d78695936726f724547576c79356b5a6544497930794d6a4c786f706358707552704536334a612b6b74704878505631595a72574e7870324d7247554373514c6f6b6e6f7154694e66597746534d53666e425356334b5438716b7372782b4c6b716c6452364849734c6777395075757652636452616d3878562f79756552554d5445784c4371574c45394d47526c305836495979307930686a49535347366c6a775a4547566a7a596e5445755a654e48596b5a704d354a59386969774b4c36455052556d4c5159334f57316a6c5a4b5934314969685753496861743679524653684c54454e4470694f7a70462f6e5567764d51517837303969324a7469777a64306d4f5754594372304c5376766862587a3057306a3857526c704172437351776b696e676b2b74596d4432596e6b3753326a6e305a446a656a6d5867386a65694a3054774b656f454a48376861516c34694971354b6769355042792b536b4e4c71715159797935633137483770716c5042587861426d6c74792b76784b6a7867704e544a6d4c4669784f6b4366574979457159654441685441747059735736492f41736d5172434f4a50524e3959572b754d4d5934364f5a654e4d6a34364c6f756969692b424333615370515653614d4d34362f78695756326d6b37505970556d38752b53776a736b6f4c2f6a505a4d6b735a4538504b346c576c796d7333784b39582b49566642684a76734e6339614c4731314570794a77724d547756393334574c32616963715271654a69596c76426959574c61592f695764456b54313054637357506b5932553231386c576468703847526d51384e30714b5236465958525a55704c456e4b79736352535a584b62516b6c4f6c444b55367a705677584c754a57456a4e477857382f4c5744482b7a38473164354a2f536e502f4353595038417a61464b6a616a2b6e306145483668516f30715755344d3138425633463457796c50685967576161485053457533474738794e5252564e6a50636d626b6157316a534378686378744a627151515673534e3939593250725461354461547670553857316a79656568644b66784538434e73665253783871716c4e6c6b34317057536d755443565a704f4e6c5271772f50374c79714e426a6e5447664c664979334e7a45566359316c636d7459722f7076372b7465503046626c62394853684d314b55497a5a4c776c576f73545659643863542f4a4a4f557a626836584d6b696b725378565643322f34564c6e765333543730687243454e36313936653946394749766f5a6641796b77535836593843697749494b665253533669503232575a356348455673784473737048454c6a4d5a5336336c73714d433157777762355976356a54675030336e55722f393869365270394777394c6e465067364e4b54694b46546965315030656b70562f52556b71666f6272544b79545461595739796369564a5669657248584c587a596d4e504a4b6b2b6a4558794b776a475756756c5349793066774a2f6a504e693251394d614e5959755846464949464638527077373743556f7666465675635654547a5458354e53547669624e53715a3158696f75644a387165443035797332784e7a394d34546e744d78535646694b66786a53442f696e6b6a5730466a4577755074762b6f493739333748696f584f6e2b6d3853307846536c6934337730744f6c75686a3649316a6f7354364d64506f57424838526c34306e54795a5971552f73555558366d4445644361553943696b43696c4d6a304c473554627430346a504570647832706a4b507a626d4d556b4b546f313565704c314a5a766c64467a6d44677148496f774c646d6b5167754c6f7247517261584d7647754f51744e465049796a2f414b5a5171334f4a2f52364358714c7738314a4e75354a375366576b4c323666496e525270506c476b2b6857394d70596c636a48525749595276476d576d52506f2b6a7a592f3539482f526c30784a2b576c78535047692b42424253677556796b7453342f774154696d6e78543370694c2f43633347595769394f70425878384f73537177394737342f7066423938314c432b426571425a36464536734d6831524559723844784f545056704e652b4f6c4e4d396d57564e353073535370486b78754e473547306e7946734c5966565252574d692b6d31394c37696c7a3051665179365656373949494949496b5555566967324c464a38344b33386148452b496e682b34656e4579685534667479524a75663564736338596a68752b4a7055735969467462532b6c794e59466a574e46315858473569596e45667079563078347239497170636167397a4e565759666459467463617a546967337930746f327369774e35364d6847495967793167795052345558566c4870354837654747526b466b55583469696969626c505a6845656e5548584f6d6356384468587770755536634e535535635575336c387870466875486945526262384f76675a4c374c385253336a5342646672532b73467857306776703531783072384453347153762b67554b6c6a6a2f30312b446b786c54484554794d7551756b71595359346c69646947364a6773657854495853504170376779376a363058366e523445475747577a634d314f53346e675555702b424932466b704e32777a786b70785a777171794d636c6d6a464b453873576f6c424476725444307162565a6757794b656864344a62485738615730394564475678645930547a724852694d734e42786e4156754c6955722f70466568526d6f767947476b543758754d6d53525a794d68685430625936547551573055797846613470636739775a4354636a58452b4d437432365661453379512b69424675556a485934662f366478786535516a65543571725571384e732f77444c566b6f5550346f6a4730474a50635230727036494c69747565534265694e4646316a716459654c6358775843554b54764b7575324a4d78625330615433452b6a77786a42686957323074706962324c6d517247522f5556726c786532444c5976326b4e7062745042476c576a6a33587573432b696b4c35464632654a582b534469304b444c38556f4e68616c526d6f355270386938383647694752386f3057352f5579306a6f3961326b556943356b5a456269365151527048566956654753724278763661797a4d31714f4e784b57616a72434573657a627a4a3947556d572b6d50733275596d326b46394d68504239433658456e356179747a36496249694c784d53764c71537146457069466948786933455a464c2f497054725956594b546379735370796c7355355843444c596d7243584834373144566e4c43787042426b596e4c676a5743494c454639562f46596b34394b44524d796e6777794734574a4b6977753037324c654f6857476231695730516c544854495668544957534e7a34696b543236757044796f726544694b643479702b6856324b596d34735154427874785778714b647468463564694c544d442f41426b6f4a4f497a62784837645745344246467034716564464d5445325072586652644c6c3979534f69434f7578695656584269736e4c5a6f476735433375394b474758543172665431706b5430514c635675306952664266327248316f704935452b442b6f71795576525445326e586a497970534b305a714c697272507967664874467177325248452b7566456c437442446d597347497357366245474f69696d5170476b45486a526677743362667156484a62376a6150424b4430354d5a366c4d756932712b6a49794638456574626b446e6b56747a46584957556b687243734b4c38526c764278575338545554675038412b4e475771324c485071307a393039686137484338505772314c555030354b574971777045376d50675664565577465178496a5353444744434256464c644545666873536b48472f70756665795444576b6230534e34504f6d2b6b4d65656c426b476a566652456c7934766f754c3446627756666a64505a545952796d32555154544b596b3346307263507774546963754a717252524665765571726178437a736342774763785635555059777442364968727a725955735731747059587258534e5658726a53664a2b71634e767a6d336b64646f4d5a3062367847535a4f5759376e76534e466a5364476a48574a384379514b4c754c6f75366a396772475a53636f56627a6155677039736c666955576d667575346d3952704a66476261667031444e37325a6f4d63635276416d545270486a5445574e62615271756b6157306a7a717573644e2b69594f49346561795938587779304361647869704861596c6954456d786142685352544a686a6178474c6a4c7039437958465956744e6853736b5655504d69734c556a596f56345570316c3770666a6334596c383546515a3467794d6a684b4531337853683251693374624b4c45506362356c4f70486a2f52396e73673936652f796354515373685651637767656e424e4d6c543054704f6c7a3265423932302f714b53576a526c6c6261514c6f682f55716472365241716b544f424f3473376d566f4739693769786b667074434b564757795036692b4749324e7046693079662f45414341524141494341774541417745424141414141414141414141424542454349444241417849545544482f32674149415149424154384168386c2f4a5861696974567663767a6f576c46496169792b56655a545a596f63564c2f6a74644c4c47324a6c6c6f76716877743256705a5a596d57574e69656a4569764d78513563707862316f72564c74576947747275614b307270525251317a782f3061476c446c6130554a51304a46626f516c4c487a2b3850524b554a79687768634d4d59614757506f396130546366635752646c6c6c376f554e6a63765a735772326f6f554e435853787362326f534b686f5574443456315772377444577977732f4d665263735a6f72646a6c474744624668534d3878752b616c384d65545978695252683842676b6a504d796667634b4b6c636d35544c687379592b46654651745778773475475a4432584e647248466a4c4c6a4a47624874586b715844315a544c4d3878765265653476647373736559796f722b4538474e55575a71687375614b36765339376d78754b4569683448356d5178654e38374846436d69686a307277506e52516f5331626968436d757a35316f746b4b4b384c3556716c7368654e2b4a46776865422b5334714559717a3643775a2b62454e64484c3455564b34596d43456a44456148675041614b30613756713473766645576448787578483251386b5a74654e505a797462305764432b632f59575a664a38554c67744734576968437a50754c4f4c68624f48756e44486f746c795445792b4451316f3945783634797873766f6d4a6c69316374537970756d4c4f4b6c513871486c717569596e752b4643656d4d5a75784747445a2b634c572b4b457937693961484c5736474f466d3066667770776e7534634d714c4c6a412b6f30683861315847397148446c78694a51387830587174314b454c5263474d63754644474b662f45414345524141494441414944415145424151414141414141414141424168415249444144456b41684d524e422f396f41434145444151452f414b512f6d3063304b61464e4873686471487a5859356a6d4f62484e6a6b7a325a3773586b614965646938347037775878364b397073636873623562536b516e68436161365536542b46736657694538597649526e74726b7154376d33787777777a6c676d4a344b5a47584c4f4b704b744e4e4e4e477a5275337a7761744968416c444c677863644e4e4e45324a306e673374376236465747474743516b4967534773714246695a67756a546130335249796e7753464139454f4134433435532f744d7a526b50365246576d6d6d6d3170707642634861704d326d68726b78436d4e6d6d2f70462f704452634d4d344e30687354452b44564933443349766264595a79516d5953583651524664794549564d644e313433625972614d4d72444b5447514973566278775542774d744b6b784d564f706d4549553378773942515038682b49666a48427174457948465768504452753970434e7030316f6f43354977554251456b5965694834744a2b41616159763651597539436473596c6270584344305542496461516573394277505034663841714551494d32307a52635677326c4d3062704f6d2b4d46724572644d386373596d4e6e6b2f5553574d5242316f356e753251572f4d6946616268747238593576507755354d6c2b496c2b756f76443348354279306768432b56486a474f623054307a6868684f6635624e714a436c386d43522f43443063455a6e48527a4a4f6d4e6d314167766e56524e4e4e4e766162706e6f3266354d30682b73674c357474616279593677696a30596f4549594a43565a3879364737526c4b43516b4958774c706a656d6d6a6643445659516e6f684d5878627a5276466a7073517074482b70343049584c5454506a336978752f77636a5751516c624e46324c697574736245787332344c454b744736544e4e2b5844444b59786d63556a424448783336474f6e7853746a76654b364e74636e62764269345a54474f31316261346f7a6b2b44745778303361457a6230584e55717a6f66564e334f5a72497a452b784d564c67326161627766526f33544a474d394751677a3050557a6f5649326b375a76466a363848424d55456a3152366d646959686347725171592b2f627a7356626544564b6d506b3332623249305445375a68476d4d644f33334c71326c5732377761474a443638354b6c31614a6d69644f39474e4347594e474764366644654f306a524d584e6956594e4d782f5968552b4448787a76564b38343777544e7455324e384d363177593656726f564c693658482f3851414e52414141514d434241554441774d4442414d4141414141414145434552416745694578515441795146425241794a43556d475259484742596f4b5345794f6873544f6977662f6141416742415141495077487563316452792f6f70796679522f4931332f413568365735483775484d396f3163557159644d68334d4b52784d5064305177696f4f7a454d4e4949736a4d67626c41727661703847366631487861496e4e37712b653951704851526b6653666b616e7567794e524e4c6468543675346230626b4f666e306b5a6e4d4f33304e394b66516b6e33707534385a7233434a4e4b62644f324430306c366a6a386d306e336f31646458556a7437382b7168444254614951616d4a33314878334e6b31472b3774795a6e79717164536847593461334c645434376a662f4142702f3764716972687947464d564936397263687a694f302b4b596379427868784c5366615152317a576a63304d466b644e484232383055647562486b324e78746d4873456d4e544e554d7872312f6b314d505178534b75746b61325237584450384163614e6c6f394a54366a6d614e3578636c545642434d74794d71345443546c5454714e784c2b5977316b69794b77515265366b334c565256477162696a565158576d314a71744d4d566d78776d6e516f4968757641787a2b343576344732774c56554970465672427459677473446b455169374353514b4c54557855634e485762473351546c574c6378576a6a444a41744869556b6d79624730586c4947336f326a6843536246494d4970717445614f584962714937386a486d524975346f764d4c306331533142325a7149763546626e77476b5557725a48494e306f71446452794745696b453169753149707349535970706a4d434c3931484d2f784a47306a496479726f4f584652315534336d726c35527a317a35554838396b446c47706c775949716f6c6d47695656444453434b525974557361334d6969747068704a4e59457a5962694b6239463961785270766f746a573470386a7542465574645765477265453531464d644a3443663544746154304b6561375053786e755558674a63336a515a3278642f324c6f6255696d316a6876755162376d376e77576a75695366344558456e334a745a6b664c71467569693057785242315056796e595a71664a6452776c556f31666365713341375a7a54386a6332394734774970364834484d684553795033454e2b726d6b6b334c53425431663757692b3645486272566f6c666b7449794d434b63722f754e364a534c73464d48544f75676969446b4731327176785043384455696a4a484d2f6b564d644531344371496c696f4976422b4a4d2f7742504253353149716e436b53716f4e57354f5a36486d364c4e78695334576e79716c696a50616e6b584f354f463654382f41354f476e475775496d78614c61326e6b64796955636d5178707549684a466d4554334a613766516470776b34487052694e5a31616f336c7338436143306b6d31527459717449756e682b61515152694a6c33306973314551634d35664e6d482b62467139663245346b334d5454567041375868514f4949366c71473645446a4e7a6c47742f754a7844394e69635431386a56502b784b4e457a4675636d584833486132777369486b586759534c493479556d794c6b5a375671392f39704e696d42584545584c7835766d48494f58455a64664e4974324e476971664a2f774152764f637a6c462f7848633330306353534a5a464e7246736e682b626349354f76636c36364452716675346a4a75673733504e4547366a3039773753725753525674506b76475735747353614f46626e657969394e467938702b476a303147734738706e686f7134763661366a576a714f476d3539466d3576307230794d56386454467264787962446c79516765687057594d52694a4d7848474f696f66666a7454454977666b7642656d4a696961574a5a48584e494d4e727152575361543043434b4f584f78626d325432655a4e78326446645677316b7159507752574d794342322f445769634c615256374d6c4a47714b34594f654e576b306b7a6b383077353039564567597a50674e766a687232534279324e5352787549366a6b706845484b66456a2b536548397175625664654d765a74687a73526b53535a715a6a476a73787938487a5279375a562b35397a7a564f50464a3743326a736b704a4275514b5050545a427a4c5934626f4e54516a555856644b4e3049304769487a544f6e6b6b62724a683134433973564457766b776a6c4d4f4a52796a4c74547a523377484a6d6f696b366a6442524f552b717631483436464f7978563375743163546330696972723058783443396e6452447a52744a7048553638434435646e587344686d6f71585232694f77664b6a54447756374a7432483570775a37556c79327230614a775934636479383852647a596a67522b6a6f756e39413452744772446e432b6f546450364333536a524b4b62666f7442654b766630746276776c2f515331536a755771715477642b366565686374454843446871446b755265356565443971654c58434472597358754c65483975487367356371507137764363447a547a656d68756f31633173586d70385948434a33354279573756614f6f366d6f30665664726468427662597651647846704f6463493461616f4c574b6f4a327465484e36695a325a5a6936434b6378686f75726871584e37656e514c5652456f34634e335042367534337545634f614c7758473146516b52434e784b4f535534436e6738726442485970724a4e7a654e46506b34626e354a48495954786367763646646f6244535a6464386e56516246485875532b4f34744a794f5959496b6b4734747136695a4959687a786a45782f63636d4a37682b582f7742477052556f356174536a6e5a72734a334a3145544f72647a444a677a5564756654623573546c7036372f5a7362474f6673523774694d68747276794a306355546f6b347a6b7a70754f7a473655386a61727756355247445834476935725271356a6d35695a474c58757143566a49394a6f724c4632454a347a4759705039455668487551634e704853526537703155626d505a37614c6b4e484879552b533639416a54616b616a6c3230455975616b5a373977634e35717558552b4935526a63687152522f53366a50547a4539486d4d432f66754355324738707361494e35556f694733554f79515a36587350555a683749362b4b4e5855645343655963754a6f30636735447a3166716f4d396b435339463747336c7457784671315948616e7a48706b52376575564a45394a6a452b78367133496f377132384e6e4e755047494f4572743172306b617a337546544d64303662384676423347714f374b316b69706e32447a7746713142316a6871446576776538676752527479396374573164544e5557354f72776d6446716e574c656f3163545275686a7a4a4545556d354f7352434f772f476e6d7a384474524d6b2b34373350724d4975356a565651546a78305548706667646b7657654c5574656e755052484579655431453047657a39695a374933547246745551634d57584372734f553571716e73515a705242776e597046584e664176475771634c644c563045455164596935626a636d702f7a574f79716c73394450446d394c2f77442f7841416e454145414167494341674943417745424151454141414142414245786f5348425156455159584868675a48777366456730662f6141416742415141424868424c4c613939784c4167763775627663494443755050654a6843444e3375446465626e392f67684e335533334e334e33756633766549467762727a334344662b7a69432f75393468624f397735727a33434d433333333862376d3733436276654a522f764f49462f64377841337547666665506753796276634c3972334b6675397a6768336d41596e454465346e354349445331346971696c334272514c653479596f38505036675067466d4d376e41515167657935753977665a64774e37684144673576634e3979364d2f7645492b4a65397a6663486535654266336534567a7a653552494b34347663746151552b2b385330496566766345466a4a727a66654a75397762447a3343337a66636f39333350372f4238446333653575397774787a653579487a336944446c3875356630512b707a4f397a666337334e3375506a7a6535753934672f7a33694b4c376844345048467a666371447562377841337562766549416c564b665639346750736c7668642b764d415552456e676870574d5773547a686764555669634f5679537263617156375544456c343169734a752b376e464331754c6b346871504d4f6a45466750784e45506a2f41506351565655653552515863416a6267487562684b672b4c686258417776364c675751743939346c575975643768434443435164377843553438337544623775424362376955464e3977355437334142393343636b382f4241767a64376770786665494b3669763737784f397855384639774431647937775833694c36774d65623341766e50654a754548653445432f4e3375454a633365353376454951566e44417545435654576233483656755a2b4f48527550326748494145355733452b5a634d4c6b6b434b5971557134674b714234706d57394b4d4d7a5a626c6271336a5770674f324a78707a444e776732766768417a5538505a414b744c3769442f4e3469732b37596948393778454b5a7a65385134487a5738516e4c3764784b425639774c4d484f34464d333343303939772b4673477a3333427546666d397768436d424334454f44333344413375444355506539346d373369453333694543434243377572372b424c39337548444236682f3363474549507749547562766333653853723858653851494441625050654948486c3342756861376774545774794a7771333468544c797969486767595a56314167536f45715663646f7759726b7a46665762683774793271692f6f4563754e7341626e676b496264626c49556c316d63452f7a6943677a58454a61363442634c6642766c2b6a69416b6a6e5934686165373341762f5a784175743568635363506d66327665494e7347484f584f3463774a75397768414a2f6139346e4e654c76654a6b6650634434542b2b38516d3767517966363851732f6e6344653465727a7645455a7545494549462b4c3767622f4146417439337634377663333841507a336a347665344d434465413565587a4658463648507a423364426943736f754542415149576843454745494d474241674d44347058326d59466b6a4f5879776d626b7432443473593271577451527465617a666e4549464e6c5837577061314d77617965347278375730764a4465454e3876504a76412b434676755852722f3345473576754b726875397931546437687a433241503365344b542b4a666972756276634c59514f5066634466362b4f2b34634875393468736562334e77723164776d37334e33754e79354e397a4f42436437686843627639546437684e397a64376d2b3854384c7663373343444865534d3645447042476f436c755776334c636a41716a6c67655349454977674d495168386a3449454347344350466c52537152506c5370554e655479774146547a4a4a3153762b51714d37794d7164417644364a586b7937627953322f423442686373796746304d4b4d4377383375414f656538527177454a7539772b43337645753167774c2b34376666654a337645503776654a75397746672f7741393468503739346843454f61347539774948383376453366366968504e37675938397a766549544b656538515a6b497a4d49516d2b38516365626d373341624f4c376a4b575766586d5942746c434b7954416a634c6e72764544576275474347494757484f324b6e4a7a334432775951495334517145496642426838446b466b715a57694b566771705533486549722f6246455a4f57433046774d33797937316356384d5731646e41766e455257734c494d455951476a7a65344e376745546348653442442b2b38514332444167372b4275426465623342563933554a753977687a5846337555536a436d764e376759347675414e66645170664b39346853774c4f5437376e4a504e37784c5639334c74504e774e37684e33756275756f6f4e484e2f7145446d556e63653435584977467055466c546c69506d376e70416f6a44424947346279724c7a33436d46664170443479526878442f414f4a43584356515243636c78686e6b785762736a7232754e513155502b65497174442f41504544554b67333342557248632f454342417637766549534a554865344a4e77494f2f31433747373767734f667534664263454348776637766349514e37784e3375416d373344344463494a39694262373778434d433347647a64376762334170704d377841736e50755747504d4c634664346741467a3459347461776a555941756d2b385145755775484674647838507557656e7555744f59584c7470673138435a71376777626844344748774d49503841384877776c32694b34486b75747774565333465867706e555165524962676e6869487a66634558336535753977626d7669546437684e3375455068596666667752682f643767516c326f7775663376654945455769575173635865385158692b653851686b673348783937676e712b3579547a6534465a4b7663433368753977424e785a7a65344e453378622b6b434b5772516b57367338444d68325242554255355757637034447546437272634b345777775878547549425332484657584c4b733554634b5a64306b49494d47716e44426f7250637544422b5343516a426f4951677871652b5957793059574b38735456454f37493677637a695875434f506534423445376765743977426d3365495577687a666d39342b4342417576506333334f39776843454342766341597042696644422b4c4d57306b7453792b3851746c584462777539782f6e334c4b75622f55496a69373369634f5a637379793254436a324f474a534b395850454c49756474474158532f395968527841564b493438754376755267494f57553856316b6e4138344e567177334270797743427373354745437873684356635365724b6c687943512b435843444434494e6b5863516c3567415663774c424539392f4177414a6469415649777772496b4b68376c68645a537a5861565a515176415a663166633365357a587a41682f33634a75397a643768442b37334269474c396a634658496b52594672334d7558334f5533784c6c4559333469376c6a547a754733467246704c706c627a456f6b5634497055305053524d6d4667632f494b6a6541514c36673162515948444470436e6c79596942797534454b59735948457034366c68553275355a56756233694f6f474d4579704b65524d6744586d344a4b35744243435833467346572b7948474967747745795171696e34473653627541496c525348784a634f422b4d457543786477426d4a58326f546c536a426838465654415041754f75386f4c356c754663687a75484f46653558686f775a6b50385464376a75483362436e4368786d3376456267577a673544764576503976454a6847656538512b495a336941675a77496a614f464856432b3452636a56637233453379336373754237784c75586e39515a7064626742347265497a4e6663653062377848515265385334577139786476376351754b37446e733465547a4f454149635259774662443456414c4b737a586d454e6165344955456233455571445535634f62676c324b69764475634763317542536b34656156396e6e45642b625a5452464466746c4a534d626547594e56684632726934752b47624a5649516a55486b4d39776168634b7357685a7a427a6535646e753474515a59334e77715970416c6d5941516e7a726d75494a7a61775a5550684b593165346e616f6a696247306a686b427971695337513778445734692f6665494e376c4b454e5750676659734146417850763369433148764c7645764d5a5772643934674264586534557163647463577457355239373348622b64774370353778413438452f5556564952614f6233455978377663356253722f41464c73327556665a4657496479364f5233466b4c516d486d463978454652376c536f62386a6e45616f6a66512b5931524572754b4b733375495277376748425237664d4c6175525271306434677064583341576b73524541774d376c6d4c6378516c6b5255614c334b3346774e66613343684b497356342b4c484753436f5334533168636a5a446d34636c7557486938724344626d6f337277584e6b5175676b4b6e43564f664a61344d4147487748466f7064554e2b6358474b4650696e68674b434876454f47627645515545343153446b6a68432b3474774639784e794c6838336c726f4d51745676454e344b4e3276634266643376344b46702b38514e30534e6865474e5656306c376467434f3034434a6c76455377776179774c474c37766375746e41537467764a444d7833414b2f7878433135726538526273623376454b506663476e33334d4f37754157447a6a55614c513979343542427251734d524f6b466648686c723939346a6a61514256366e50735434574372536933556d5a69524636377349596a693152744c587864776265616d4755414b464a79336355436c714b6e697242457675444c2b426c77566777554d6373756738334f514b7973626e6b6e6d707a3367414273496b74624c415332434456684f4e76433536336345334c33325647476272467967534b736b624c46445a694b586172343838536e496e7a35676f4b5833464a7775397831664d41315547446543373347707a33694165526757376477486879334c4b524763777364346978414e5142566c776159466e414262334862727a754171735863493862687476755752736b53354e7a6a5576754176677354374f38515a45574e6d30767645486446494e716c33754e4638397a793235517763736247793778455259465a314b46652f366a554935456f51484e55477a427263556271444c3266576d63626963326f555663616a44797335494d6f46554c6c687445354f76492f4a69414b6c5a7a6e683861684f6a617931566b4e7869336a6835455234654f346c4b59773567524561677867776930652b34384b476c52616f4a317a6371776e46754d5836465246384d4a546351796f726676465461784d454a4f6368676c5865344c4c706538515847496c6a42524d346e4d6c742f486e706665494b376b484562397765784c57446b427141517041735a6570465243714c44636f47686e63446534683858334637747665497269425234712f3138434b3057376d634932384b647746744262334270664e376c2b6a6939774c6c5863476d3675347759576c58634266693978453872334c6a63456c4a6263786d3178714a44656f32744377677374334132385545386264696376494949705a6149586452693277634d6134583659306c6f376a79476c6479774e316a5969436565344e416b47454a752f6b2b61344f634c46766d46336e7875503841647878386e5045567278483030544651782b63614b445978426463626a5764594d764c59514a57376167496e6e754a4176444f426c777a68356854786437685a35744530465551674b554e77415879496374386d35645456682b6f6b4c337a612f714b484c3934684b71726534504a476c6e4c7550773839784b437346456d663778433938397832486d393467657a653553326559432b656269504944334c506c4f34437853634d41647a4f464554323365344e2f663841694376767645474b57324369656534566234596c615a33694538693733456c4b6c78714161424847724876455851637269766b62376a7138553468644a7a33694a6150432f714d616276654a7943323674384f4943764a656652687065686869745469397969385363354a514166417a4966497768774d4b467a4574726867524c74566b567a4332355455464f346b536141536f4e337973625079457770733575433477324154356d71386a4f647339346e4f4c7534514c4f41594a494a63734c676a494e793154446b2b5233696551613767324f6c387477612b2b344d34712b385371424b6a43556548506345356267774b7536754650463376457446713375593571345372752b385153354a7a4841376772764d422f4c65493850464734303470376d5849376948752b3452564c753733694a654c76754c76696d49634c664c356b447764536b51636d4466417477426f78336963345a754b6e4c634b34306c31584737744f346c65527545464f4b6935594a5258454f5342744b5877787056434f496363694e3767704d30357543546c6a634c534877664441734945707155387178535048342b5a4d742f4c356b53587874772b3866487466455972617558336e52355975596f48384f493346636d344351667067437565355646717833485a5a7a334250476534786e7a4150344f4a664f6267344b753934685a35753977574466753978626664376e495949635a33694c2f5065494d4763466a4b4c67567062334b47433978492b694a6c336663626863436d744f3451384b2b434a5a58447645767755797a5154755774524f6477752b516233427339397846634c3767546c462f5a6d42426158755044466a694f7562785337795a4939504a49586e667830332b6233424c77752f774251576638417245436c78334833517647627844784b33367a4b68712f52386e4561327952577335377844343163427063793073726a6d2f6a334345595045416745494d737143686f6d70753432743648766e764d6f436e7246694177656d79754d5475464a644563534b506770754f6c5278665063717638415a78454a653977424c74623369477468666337336a343366366c6770436e442f414f34686678666335667a7544766343734a496f6c6635784273446d342b45767645654f6237784853587a334c674e6d47593035686c35333459453233376c6e504e376a37463978612b376741636a6534626269466255533767414f5863584e692f694335585544414b75457335745246694b3243763363624b4131634f2f4a2f55564a57594b3778573555484b374a65344a6534376555477835562b58453458625a4a5657726c694d3558634b2b4c75566b67434d4666674977654957776a3342334c4d6a6349537867376732652b34515251754c71636d584e55624b6c416b536b4958656535653057792b71436d466b5333425067533934695377556339797a386d38524a7050754e752b566c6e5a7865346945712b346e3833754a766361314e6d344f577065445a6d3767337144544374566e63544c7a42334269414771753978414772376a486b586e63344e68446e3275467975586353666478627052726c7737784b39692b3431792f7645344b52466c324e77695877743467305948345a31586562616859683850455379424e786a7a45446d6e4c44716b55536b4c473559686136654945586279654c69315561626c52656a36586c6e447a79395036676f3574524334306732437474367a4b47467a793242676a44635342726533442b4667333842754d4d6d2b4575344b34494868617558657879626a3641484b7977303856574268535174486341763365385161516b714e433375483262674f6f684c5a37686b65563341766937334c4d586355474c315a7834534d6c7966635741786c75634f6765344e496149484c344639346763634c764562346f725044385a754a2b51597731627645547772376a556a656b754b7647647879356d42795247726d39346e4268643769694e77357666787269766d42592b346e317353574a71705a7a2f6944536565385374376a674a37784b4b2b4f3433684c5764526353797373567141746c754c794c446a3265385170734b4865494955714b4b4974655741666d3344696e6c3342436e6e754459494673544d424b486c2f507a4662566f556b6e2f714738426e79547957466d5762376777516c583845703077694f4d6a39434f4635754d49724d4d53717a766346537176763473767a65347451626c344c794a4b31596e4f34444a6233414c2b62334143727a334d72613733417675356e6b594c7062376c4c5876634130566535584c4c69473537684145443675397a4a49433351796c7375324556533733694243676835464a33694658787663384c2b324978676b69323433795845636564784a73354a523833633877497751506663752f7539774136784972646d6d70697362596a7472544f4a6c7546574532695254586376306c306c634b4b4b313768326841334375374339774a344875474b4350303559746f425956486c5a49665544337539776c344c7747344e334a77545076784a52576776632f7743647867345133334277636f792f6868764d496659774243424b734934615953366968754e4b49525843735962414335523561326e496f556d34574c4368656534674556556545724d5a524254794c4d3977754a4b4c537437692b692f684132377875574a57753471375766314b575771626d4f32376c6a584b5577656631507365385330726c6538513253435a737741335664346e4130333369557a6d35354264376772554547597534634456397932394c69587866634e764c58632b3870567578695270676e687a45457956445375674839346a744f62334756697077783269672b70684c6f426f735544424253422b30444d7130513378697a6b4d6b495630486c356351417374376a555a785156755779374f3841746a6d4b53384a4543777548494971397a6663766d683769577836736f634377333853315349563937676a6a50634b65496c4f4f65346b767175653462626d45433554357233444167563342434d43353343436f32515258716d4f526e4564467a637439787858755858507634526f664361707a4334505a7a634f5250634169486d74477051776934654c377846726f7675465a5538304c4c696c7a7645432f64773445635a33414c3933756437686347334a4e33754148382f71434d35313537784f5645767544654b376d61393768743933763459525162617a6534326773376861633759754c6e764576644b54554f4d484f4437686c64764d4956574f5833694866495635706c34687a726f3466456945754e5545376c6e4a34544c4848684974514c764c376a6c582f366748414a653577514643444567582b357844637a3347737843574557464b793378635730725036676f6a533934696c565865344c4262343879374948787a3369576a6865653853384a763369412b61697163416855492b4c685045465a54774e53553470737a666d4662347345786a544d47716233413361353369466f49787a6464515a39332b6f4e65526763614c46484e706253566c637769786961584d316544347a784c674833336955475855416675392f494a4a474665727663457463726a77476233414962647767526f7076634a61724d2b746f3137584b354e58414c773533694a733267775262567239524452633735596659727761676e674b4863762b48453059575444344d5143564546754a585658424c586d3977735555533656544f45497638415555565453636a6b7535653978557039376c6e6a434532735364342b45354d727a653866426350463977566b4667306639654946653937694e652b355352427146725864376966627645737a5739346e386e635a6536522f76454f5130525a55674d44344b527a5176496e467755756c6b6141316d5578563375483258653465465865344c43425265622b536c434e47717539346744796339774b4b523872436868574269596b562f4e37687675473843414931446d464469356352474b7236376a69696c66314d4a4651736c44635a655863564e7474796f33686e532b355162712b346d4d4433434e4737692f6549305a61686271654363666f516175584e2b43484d484d5953504a4d44793851584f7a67787a57307269355173755865496c5749526f716c3768594b484f3561676746367675474f58634e6f59414338334c304769314f4a7668334c3673767555634b33476a466137696c666534692b37336a347730504a34673369782f556371597676654946344f4a654e78714f6276654a5a5579546d39346770655168302f4255516c4c634c754b31796b61366f2b794b694c78436e69336e63432f77445a78442b3733424639397749584165544e3778413555397847497835376c33776e653463593333433369727639547665496f76753576754d62395865357539783350392b38525a4276633365357778426358334b2b713768506b376962554e34465068587776676a58673837784875335063566a774759314a64356f2b357a4b5879386470516a364e526d4338473549334555354363397a537950696a7545726b7338456f56345a79466f69424c5a413375484a6c4c3342357239346c7272795a50632b6934534b55636d34336a7676456546485063356c6c707645574373386a7a6534587169373369436851477237697237376854386f716e77726334306a4a6f4b46397744426d6d566a595639732b39536d437037376862454c486d74774a6b6b6a51366d587255336e347949466666654947414673476e6a6f356934672b48786b2f746534622b376762334269723933482b373369454e767675643778414639337566327663543166654977726666632f3633694442484464376d373345763776634b74384b33446174514959697473536938397735726c38616c69797757366774746145346944596746302b5a6d5a627a71437751476451486b49634437677571575949587a7a4359586768707772334f4c6d30624f4d4958306a6e634375565a625842623369414333544c4b777769654d4b2b66573552456c3978696c75494c793874786d6b65422f764575484e3977746e66637465472b34586e3062376d79446a532b35536963485044754b736c3277325655567a4637784566454f446d3977452f5444345542574d557137673330724445414670363870754655747a76454f5066754c435730433142346a647830742b32506d5a77504b74376c2f77423978552b2b34496b56666663615646594d55675841334e3934676f2b373338524f563133414c467637377848526a4f344c372f654937372b49716c323769704c3537784e6d34786b343761532f395331623679664f496a6c2f4f456152305133514c6a73716751673933635146674a61574e397741565a376751565738635378717a334b72744e626c584b337544546d31376d4573454e784a73614c6c325044497356443548637276416268737063376a7a677675445754755841706a634b536148317675666b334f4c79766346506867355938684978614e6d6a697a3369496966653851303579664e73793369397a766356474c7545394b376851714d726e4a636b4c6263337564376c69732b7a6f6a706246754d575a4e7979427a4d6f6e724f3851573158377848667676454754643767396452586b2b4233754d502b2b38514841633166637436767543504a666344632f3733414239337548355a77617a334e33754d6646393467306358334b6d70516a4e37693143546f324a647a6e43324f58334537794478667547433271434955446371514a417574346c446976754a48494b39656351415772596c7373647756716e6341345658633531757534304c5365713878446957397873314b71576c6371706348427a7549322f65385233494a546534446676764532626a6e38376c59657477594d4974524c4470504e377841556d626a716e68334b774249743649626d504a643769724f68334f5a63426f74687a475768443969532f7052695a626f6c444d5773676f33627645414a4b4f595567655050634d636e336538516f68793156397a6c4748336535623833754442583775492f6e76454b59562b34507958336945435668533937687951673733476b5376486e63465a62766347304f62334862473242544e6c327a494343465357634e39346942424c75436a5a78334b437235596c7145687752654141484c376c78644c5a547a4b5768753934684e55666f6a4d4b43457969546b71313649454a4271454875544b67445541305861786275673348484d5546386e4953745971417573797176506549714837334141697632766371385a37784b484c5571572b62336946386c337562705457476a6876754b35345875637453766f454e7a5145475343735249696c356c473258654538536a65344b71432b3866484b556565345963586535536837334b684c764e39346e3937334f6633653444783537784778566c3358463977626666634650767544663365344c3544573851356666634a3375624e346741766e7543534d6476696c4936714d2f50654a5a64467a622b6f6378375356676165345051315071586538526a6b79714c58635378747145386c544556724970464a61487951516f565a45457656334874736b4146366538524479464e796f68593375634f5a556270576d4349436e7959457137563431483836474441734e3467794d7a6e395a784c774152626f6e4d736a644c3733465678666363666e3951344b754454626b576c4954564b4247416333754f4b664f3471495666654974426c68565865345532715641746346685373464738397771526f39337546347a6b674d4c5347642f47353834637539784e315639777076466e754e4e6d345744653851697865596e383934687a342f654a76764552764639346e6535774f432b3465336e754732347069696763332b6f415378467a634c507675636e3333384c58527a63655072754b4c373767302b37334d7251327773717562336958756e4652722b436d666365377575564672773767356279657665494c53674f346767456557653345724a4833457937524179557a78437247565751614e3833754a71305065497030566535643678504f6f544b316c6334494c463853727a69724266635055437370454772334b474750504935334359464633643769574b376167744c736a7531526646454a534e6a2f624534504e4e7874573171496973727541756b556552664f493670464c2f414c784b6a5a42486a646a7565613833755538463977555656337542455a595777516a4e2f6e6549526a6343792f57344d4f58456f4a533733437031645334345644662f414f4262334b7a677933377663456c6c2b37334c3375484d4b4a642f64376c7a486e654a5976506e634737676b62507675436e33652f6957573176754f4d713561674250356538514c7a7a3369417041444c6663556175776769304e6a75444141397857726956676f6671447a65647930766d4d4c4d7a754371326a75446456335137535370794c6c656c5a334c764b7379477733456b336a6357724843372b4946504d4e387a6e7a3733456a5658334c6a532f2b73537770617663504741753465576f4e34677144613850754a4763685438346e47766b4d59714b562f3841715a434b4f35392b483669726975397877766a2f414d68617562336947424434553470586341683143746636385146636339774c50666372482b764535373937695a5768483637784c75655865494e2b496347494b6331632f6e7665496c6664376c50372f55756e33336956766550674e6e395175344c6666636f4e586242612b4c3369476835753472587534463872643768745855463858635736726e754d35663369624e78334e397a6665494f397a68373376457444495a3769686f4c376861327362316548634c614241504b2f764546644d37566259486979376e4a664b2f31454a623943556251494c7a536a7645516646344a586c6a41796266384155566b46483937676b4a4739394476454f336b7478382b56746856504c614b574f62684c4368514156376a41724f3456326c59565a6446763342374b6f73496e76537433326351626131625a417061722f77415251614c784664436d7151446e622f71496f4337674e656535646c642f71656c3333437854334c4d38347731477044714c754c536564774d3050333369425644624d6f545a464b69763337672f42572f643769787242356c7843666c58754d562f653851522f73346a766a4e2f71434a79595731786e63597679747868577a62385641507a65355138432b3452713878322b37334f3977712f674b3958334c43337a5a42454f58754b46322f5139346a705468647857653733694a635862415a3757305835676a4d7667384d4b312f786b34436f774c6e623559304974334f495266634256722f334535626347344e34613769496878676a6a61617556702f3769476146614f6f4158334b536c6b686470377847325341675561305145456f4d59577252453052662b6f30597431754252573375456146344d4b71327735316770356434674f64524a57723768565856397977704c37687839334876395234652b34467035386e4b372f7743346d46567776464d587963664b484f344e376968544b2f6d39346c57715037784658556f617a65356476767557443365344e2f7a7645497476752f3148626347434d743978767a65647a504346386e37784e32347178423933756264346c332b65385368727a65344543363839346d3733417638416e636255386662654a53337866634f4f584d436e6c73647753724f65355a2b376c76486e2f45464f57313778475a5975366c467131354957444b516348466376336957446a6b64784541586344316b334372626139786f4b6564346c576c524c5677673164516f4837334f4b4a74594172737242616b4c655432784e39774a6834636e764535436a593768513458653457384f61334336707a6342534b792b70767645635747352f763369437057623338436d414d2f384175492b2b794c674b38495847467a662b6f7258323345734f62376a743833754e4f6333464e43723369446970796e39723369495033476c39392f49656565596f34357663474b3835377844447a6534454169334850635377625270354c48635877457349487476654a6b567a334764376d3733436276634a5961377842466f4c7663474e306339784a76755a3479532b417a76487768344674676d42624f65517368554d6642655855347735664c2b6f41346551334638344476454b5a3365345732554f494b674c376c5a374f345a45767542423937677633653851323338623768484a764e37687675434b70416970692b34462b3733694e4276336535732b4368417237754436357638415549663333694e6b5a334b4254643768515464344c307775585633754863524638337645432f754f4a35766354683576654942716f355a716f494c7a6534425064796f336d4d4e68666358344c6768417761494e74504e377842494251472b34743462766347727064372b41706c76755a47574f5065343238524a467339397a76637576396e454567453576504962674a562b3854687a3548635942426f393375467279333369634f612f65494b2b494655692b344e387650654a64377a334c55586b47346346316e6333334f566f3547587542626562334e2f4c4146343365344a704b72757065482b76456f714c675268465549454345585759462b336549666a2f6c6d37634f397a6b664476633365356176624c6b59375a5a46643655417a7246546d754636674c2b4a3243726d31376e2f41487562647a495a3778436b2f4f3451506d49543365347178467935334744692b34494a6364747a2b4c76343375484c4c434b3638337564376c7671376c304e3833754f4c62385762766347457134462f477261712b342f3365385149583435766378373467586774643467576938727645376c72794c3767567a7737696a616c3978476f7a696f7433754a58423533456c2f2b7a6958617743303537674c6353384c3778476947754945356c6635784373426a742b6f3046357a3369636738317546672b39773051452b37334c494365385135756333755772664d334b47484a79324f3447484c4b30464c4546336c45714b4d71514b4759524835493977594b61334f4f7a44755672434237376a623558414b413333476c626276632f37334657317a3338424355313537682f6437672b5569324672485066785952562b3733433333376d37715759305064376a643933754c4c3375663337784342766344344b723664773354634350367539346c58776e2f41467565743077414b472b345563792b6372782f55453857397857424b69567a63476f6761797853706c334339427a3348666361497076793769576e6d397755614337334342357535512b2f654978576963457065472b344459776f4677376c465952414f6133384b666d39774365373346446b393375587663383431573436537a3463764a5839346a483776654956546e4c68744e743375574833334c612b52334643697842504c7a6535537a692b34426b767563706b5a796152376c396e754e6c446d3977626b7a755642443776634e34702b373348686d39783146732f362f5556667675414d4166374f49336666635977647939314268372f414d3468667137676233424f614c376976687a336947697a66366876786e63624f4c7563324546765063524e2b5a7a2f414a33464d4332484b6e2f334543303839342b484b567959764c6c3344523839777a586e764547386d45446a4d70444a6775486f76754443434d473035516f644764346c6b41775845746d41307371456865562f76454b374f61334f48793778424235397a6965623342432b62334f5a4344653446776e625750567055714f527a795158545759464b70655868556f356a6e694773723934676d6c334f487977442f4f3866466f6c586876754f4b4a6d4c41745157424f4c68642b2b344e674b76506357383839785456633375472b567a4233754447555a7a347a65356638414e376c62333841597833373778413375634833634b3435377846667433384133764537336a344d564b726b4c76654947304c59732b5633427a6477675974326b51555a376c476b524c34726e4e466849565571446e754868586c64786f484b7a68576f366662654a594b6c32754c72634f7453313735706946734c424142666d393468775947734c713833755772463934676233696276633430525268454e73796d343273634d51426244736377726977704e586538514a76336946697a4f2f65355a644550555561594a42684667327a6b6751547a3533436c6358336943393358654a6c4c647743304633754533336a34692f50654958392b344b2b373369577a66654a7675472b6339774d6358334f393467774e775639334d366a5450727a336944384737336962766344486e7544483365347774456d3734387675397777566663776e7a75494833653446332f415063546e7a456f4d397a676763397771576a546835376a63446e75635435586366354a75434765393468663735784252586d6d4e446a50382f71472b584e376765484e37784465484b5156596c337545444e3375425a347676454b543333452b7237784265532b385379464546767545723564775150566332775a52754463575063765547346f714179753470677946766433653555447a634e73706664376c5a784e6a2f754a52486d397853782f6e336944783537674c6e6e75444c764a4638726663464b534f3234564243653934685455555076764545497a33764877572f6477693342757650633344626345597243764f3851724f6233417037372b6433362b46573846784643636f6375444f352f31763449762b7a694d386f462f326352596968727945467a43376c685057596c543633473542695a726677777a786e65494e31416f6c58334172426d566e753558467a6538536a6a5075663276395155722f4f49734835653854647869737a614b37772b437566757a6955544467455133586d344c773468464635766333336950753749724a6d57373343744e71376957773575452f64376945466165653851547864776b512b376a74764573635a766348672f5639793855436b767562376e6534627738337645373342334d7a503347627570565635372b4f2b34663365344739774c385865346633653852376d2b3852315372376e4748393375444675754c37684b48373768512b2b3554417470353778385a424e474143445668446c6458334466636f48323778425653586535784d58334135716c33694d5849427535666351774c7545336538515334773863397939454e397a45467975587a575433424d73704f5141776b514e4b4c4f64356434672b503853494c497149594647436837376c6f38447545583764773159784b4b7931743839346756472f4a7a334c5736767645444269737a64376773484233754c7663496356797663477648377842654c353767344e6773474e733365344d486376653454643768442b37334e39346842474c6538546b6762667a7558784b7675445a356479362b4f34412b6134426675626a4575697237687476454333333341755663742b34473977674c707a33417637766343514f667475484e2b6538546747725a512f41474255795976754276395149455635376c46717535516267786b315634596a675751546753436946454b463363476d7333755a437747584142757139346857415833416853504f656233454252797871454d743347682f4c76456672642f71556b736e316676455067696268416933434450314f39346c3733422b72377838434677675476635037766333334362766550674d4e2f77425148446c676a37587544427835377842494c50653977353858653451706d373342733939774c7637334373416e65357539776437684e39773550663841694544367675447835587645552b33636648767544766355416738753446784334775656702b7064465331687330336534537462414e6c687841534944454970736767307741426564785661325143586676334742634c34684f432b6538524a53585446437746464c376976675a334f594b583348766343713839784f452f3978455961562f6e45562f662b494e2f64372b4d594a42335547584233435748336534314c334676633365344d4e39342b43484b666538546663376c7759562b62334c7143655a642f6e76455673576d733375486c6e7558773475344b636f493856647761727a653853396e6d393468417373527753755337334f347861506747347343794630635865344e745a755751734e633979774746337549757276755569433659515345585633754e58375169586878674b486c64777972686a755a376a4c7a5968614f59707a38706943742b4863524867492b2b344b31717868573361376c533232747a6942776269746a4445444971506663566358653575393467314c4d63393467563939346a583737784566352f5549634c5635376a7439337562376777674e336e7645472f4639346d2b3851642f7145334c2b42416d37334345494d33653451663537784267322b37334b754559572f7676456451704736445463486a696d484278647a5a754c3446537166534f6d344a3972334235476233466765647765652b44634261336e65506a5336752b355a714c497a65356c65336b3979384c51465855774c4169574668587a4c6e47317775345535592f554463775978466d4f70355847417633474679434b417a6534672b324b7935495765532b346b5a566b6478536f3537694c656233486c7a65343178574462376c5033635963336538526c3939776a2b66314330566e76764550377665494d4863472f396e45333369444e33754533334342767866654a76764555746358336944412f6d392f47386451622b2f774445742f4d486a793778434c7544634739346a337544386638415738542f414b334742576534555068454f446d346d4b734266654937764e376a6862735545506f336958666d37694a646631754a344d334769455155502f6351735a756c397a7a39726c6839386957536b3657747539785633746c363468754e7649515276626e4274736351413234796d55334f53332f376943325776686c432f6833414951437774674f7651377847536a42754369727535524d4374583369636e6c65346b397534796e3733504f4c376d2b35753977677837334578623347666d397a6e34767645432f75397a76634c594f35753934673733424249497a63486350446e7562376a49584363705966643767775a6d62766347464d45536344336534542b33654a64745a4a76754256743567766c71397931627669586354614d5a64782f6d75344d7565594345336636676c486d754b3977642f7146536d4f2b344b4a414c6d49576c6b3047565733465858395154793833754f7a4f65572b38532f58546351726243506d31626e4b50504e51786b5a4e305546354c3459787857764e51675046626a644331334c715330316477626a4242383376456241566f6a66485063424c76506549544a7a6534717157744b73754b37746663633733466737673767322b37684a2f6e764877624e3467573341745135587a3341337544755a7776454c654c75393468426777663567334346616645454f612f774265494549516c33426875764d336534387a6665506966526437784f484e3365346f7769633864777341767543503837784555437337696f5a4c33694f30694e764e626c6e35766347736c3375446242587a766355797745744b7a534454624469476338375162726e754f77726b64784b3446334c6b3146425553475751376a2b6156316951313277676d68596269793275357a70536c533870456945467972797a6c714b7841505446362b397769727359764e333347463035535a4679626e446972372b44763776634571307675484c6937336942792b41572b2b344a654c754b70614b353537784157456a663365346f742f64376843445a4330583166654a61317864372b413233487665494c3675344e30764f3451583166634b2f4e37675167306e6e754c64516269594e2f6437676233434f49706b4d63333345756371726767497145627a6451344c6e754a56447a334767476534592b622f5557714d337645624d63397834654d376c6e33653458356b33474e614746746b514c6d3977316a6d392f454a484d62747747574e686d38372f414642546b3450677441744d35486f7939383849354e64774268624d6d55593452356d724f513058334c65726c313669747079743468486d486549786b3558472b34614e386f78352b376737677a6437674a3933425754783576667977537a327663486534594f397a6437673733442b37334133754558486d39346778622b7944583363642f642f71584a35377848634e6f50314b33756276667765504e314f353466653851532f59376e7135376e6c434c7a626c67334b47573733694a386c44754672706663796d5863714b43436d746d2f457546412b3977356a514d75346330715930594e4372754871374863724b634c4158327663664e505065496d7257634a566b345a6578436f7a756335424a79454356514b364b59315676764578504233424f6c6b4f334b47516776355579696d6d56654930756a4f355a5946564b57684b464f513769326e4c76454936357846356d626d2b3447397a64376751494479336a71663276634b494a347539774455422b62334c4946727a33437a693733694442487864376765617539775672373343794434752b344a36753977642f71574e656268494437377838426234437a4168634865344e73705a4568747534414d5a3369445336692f3233695735623676755668356479774638397744564e39346c32577564774755716e6e75446465626c304833754e6b4b76755741755755436b392b3472677a2f555832446636676355627663654d666c754734336d716a6c33445749444373555963555737334c2f716b612b5234314344524a7830554a6453557161724a45633866676c6a52694f6343386c39774e6c674869676f6337784f525261785a6f75386e76356c4b334e37674a393934687a453376454436767544594a677946663375455351666765393468417743316d345734752b346262677834667645624f4d37674972367675433951322f554f5543483363554c2f41673733694242705a562b37334656656233466c7643356758687364346d2b3467793333476c6c534850754c596565344c734e33754256334e377843533249715255576d58694f38793733427233653851664e69376e67597056712b65344e3145504639346a79664e376d4e797646777568427037766344595844613352526555676361626832517352544c6835596242525a727463454c61504e376e4173546538533648692b346361774d51567178674479314a53753752674b39333846556c3344434b4c37766677445a63594742374c766349473977647831586e7547323457673335753977615975346237784249557433666376653564582b764534474c37676e3537784151526f71372f553251745542674c42507a6538516f2b2b385161587a2f69446353796a7a75414b57376c486b7433456f555a336949456175712b35517758334b464635766372643164787241495065355a362f654974576355786a534e574c71754b3369586c51416a6d3979773355596e504d36356e377663646f596274662f6352546a643978354b3633427268754b32684648776478516467334c72716b74656948345036526976314339383342464a646e476f303778336956634a4c74577a6663566c30565979524f54694d4c35326c6d6d594b6d364b76454f4f482f414e78456f393375563657496a695876654932735676332f4149677437675166352f784e337558674d4368432f77417a6663434345452f4e37677934636e50506347663962682f4c7645586534724c7a33384c457535494c50376434676e6a42754477446d3934675647567a7a6346585672494a4c572b35527878334546486e754a666675577357397752504c7541674b396a75497069303342654e58654a5a6c7a6636697632376e4237766344653565626c465833417473397935545639346a7543745159736c766364517063612b7849584f33454a614b7563616b69743467746167676972684263467969766e754c5a64334773536937736c6a71585a7461376a6b344953303574676b6f6e2f57385171327445473557397969315639346c3652595166794b365762334250334c3457707a334b48774e2b356366666549656b586534446e4e77586a69373344664f65347a6437784262504e37677763656233415639337562376c506937676d764e3767466562334e3235733342574d436e333338472b3449467266635a6a6464776645492f77417a3951612f334f4952706b7563714264376767347534484762334f45656535564b686e63516b7a342f654a79314e3375572f4e3778436b782b6538664576544b376e315864526c447973717438424361764e5268532b385235757755616c39714c33695054414d7345695549456451557259334159774d537765786152316266467371687171334f5943576c69726c6c5665624f413877416b492b6e7a694a656a75484630675658463934674e304634744973614c684e78656b6a454177614b717a65345867484675356e42646a424c4176486e63475a6276654953726664376c454b685570677346594d53444c34384b684b7845747a634641717965464639346c667a65385276694651414372334270377665496f737a7974337555562f31346c5a386b537146587544546c7539346874764548706731592b64346e6535646e753977443164793054466b6d595258466a416f305857344e38766e3951796c586534476c56334f4c6d4559334354456143783357773564546a6973535678376a6d30317838763668704b5a334c73665063564c4a785734473868334836685442524372766a6662375335726c4f48586341466763455866753977754b4e3856454e4f4c6c4d7a7766506355476e30532b2b47344e314c566756753570614e70513369562b2f6375634639346a543767572b37696a6b5a5635627663554534767547452f7665357a2b3733424f496a567758334b586862675535767562376866712b344f505063444769413333446f6e6e6351654633756237784249744e4371777372776a2f7742784c4444613769677266424562617a764576653557766e754454576534376e7539346c51556945745833427637756276654a7534636c3537784d4437336948332f414f3469756e7663466e37334f4478642f714c77733375454e563375636c75782f55757970622b426f366c39792b4e4256414c705a795470415738574571555644584c595264315633754e76516950444b3463775874784174726c376752683430774a7730312b6f36584279592f316c6272316d314b326f5333715147724b4e51714b763278717379626a736b6133454e595a56556b5369474943566663537075397735314f5762766549633135376859506d39773563667645412f64376a6237766376382b3443754c376c6a4a65496e4f4d3767572b37334172786e6343484669336346763333694e69746478746c743934686f55673733442f7534466f3158635752474368734876457578574653473465653443316e75574b4f65385179424c48336534634b67594f56376773486538516e50382f314459656233426c42505065493673432b3476465a33694c5a7776754b336d3978426a4c7545594b54634e31456755744755366d7a7549443445426b573835694b6b457256417038684f635135423558654a5954415579376c755848636f53386358653866414276675957684d4734414d5865342f41556f4e625a54306e63752b616642334f2b615742695a573934786c587441484e734133796b4a646e4e376a43412f6e764542676233434b426c7041706a4f344256734566463934696c56586534612b37675533432b4a7a3348484e397772773537676a3737784f4a6333755850422b3853347547427a65344f356477457835714e42616975344e3778452f4159417442563769654935675a53697a653431336d39783438704730754348333369586666654a7a6838493375663278314d59716664376e4a67767542634152436c6c3279674f46747364525278546e764574653533694237734755636843355178684a53626c3162436d6a6d39346855646b442b416c327931377841572f766375745664376c3030353768444c666346544c344a767546504630513852436248492f76454c4c57346d7938455235654c454e6d633458485935634c714f71486c596f635549733473346877333562784f6631653457774c636676454c65446e7645462b4c7663546e79376869555644675050633435497177616557373341613964774546504c39346c6835496f745663486e7937784465465735796a514e7744414871373345783562656534583937334b4f484c4851354863432b61752f3148527a7a3344763953334c626965656233694f38464b712b3454446d5672634a75392f4a2f65397a2b2f654a557a353369634c61735979686e754963572b3479544e376732703564793569326a44537142334f616744654961343048474c4833766648786b43317933754d6335674a61726b6d2b7047416d65344e2f714f596641552b4932334159432b6b59454958345159557970706d485a79456f5641573671633371787a2f31786b7a78345532676e6853365450634b73467975776676454371446e754f64354951726937334e3979706e7a756234444776435169697337674b5a647846717168664c6462685137376e41652b3579556564346e6949446866654950316663422b623342754b536a6d39796f6a4b62673057355669334155514b444f397a434c75355674716c58624c41676233464e337a6636687067584e393467316e39723348636e39334c4138392f446a6b456c546d73376733484e314165594e3468756c42514e6b75355a2b4f526c64725651737a6449766948524151347959516972676b594f546d3861686a6751584a7a336946515a7676454f59422b2f38514667704b5678643768582b38346971316e4d563575437359524f4b68795243744150434a47596d655971304b32594e474252383375425a6132473555345a3345473236336943316e2f75492f7742337542537a7a76454831484563773165426c795365337566327663417a7a653866416143415069444c5a4559514c752b35666a6d397744393977393278687a794e58464636767645486b766b676d624e432f76456f2b4c72634b2b2f63554b576b7a707a6370596d4d4959443833764551784441666a2f31764573416a576e6e65495a31797857496a52726d446c6b444c766853413877754f34745762673878445a4c6f414b2f5551754865494e64544f5341454467784369466675344f39777446425539332b6f663333694d666c33652f694e2f466737334676633365344e7675344f79744241515a5a646a47316355513741364f5941764c433572653559783576384155586b7268704135754b75554b553834687a393342523933764577507663482b65385161672f6e764574506479725450632b677675564b723737685a43564e533169476f4343764e3342576b6275433238337645514635766347796557577953306539776a7a773839796c5949754e52493351736c33773551684469376a474f76463934694d37647a6958794f3563575346462f39596e45656167486753714d46312b596a65464c344358664c6943366e676c59336b686a526f6e436a624d4956524c4763302b3934677057434c424d5550634830474476634c734c67334f42377663462b623345395833422b504e725065495050767548476e6d344243317134587a417267706c3867652b61655035647130533275534b5670616e455347764f385368615865344b48446534437676754d56664e376a586d2b355a5857647758486d39796e2b357838547933376a796e6e7541746358652f6a47385a377843797351426650634152572b2b3450766e7645465336507a764546545334577037334c4b3458336943744d4e68416c4352535661347539346a716c3375586a6c4239616c6d3658334f4665626933485474642f71566530487958334f6252775174335056693074734c4f6f5a65743263465751544b49684e52764548474c594e5863314b57733441515654693733436d5751525571372f554151637373666539775757632f346737334c507a65344a41596c33754c325865344a4c597850696e3375454b6c446b38777467664149334274754853506e342b386a77727468744b3576636461432b34674c46332b6f7263383978523565346f5737634664504e7a6b2b373369416267424c653262334356674447375a414744786433754575486474785161653733485a627a426b574b7137334256426a65493656686a463977503537784778547a6535793346332b6f5477382f71465669786a7130576562626c7152656945437a39346e716c4543767a3369457079377841416c3045737058567a5445463551776e4a3964346a725842776169453042676f677645502f414f7079437550674348753977426944434e317a653564767675465838332b702f65397759634e334d3237376c6e2b5a78455971373369634d633977576237784248344c7663583839346a337544634650674877536745676b586c4574566a474377743469377058334b45717767576a64562b6f563238737531357539346c6547566c6e67583342434b7a7557385a37694269372f554138656534637465397752393338457173632f714272336534443166654a6a383375466f4e653363736e6f33443135476f2b486c2f3169495435377843356f6a56543533434e714a6663534f5a37486549496c504e3768634742537843514d507639516c6650634a44556339346a484b714552746b74734b37533778436841694962514a67307335306f52677037314352507a653431487a63713874397a66634c66767541737476463333427667633768647751713038397852393376454c79692b37694a586d663841754a794a7676487745796d2b343667777543785667626e4b566c6866424b4a514d6542324c376c5166653432687a334b4c78746478706e6e754a796e4c75414e764e37696e6d51557751484d72664b5a6c4c382f31414d52594f502f41436237685341723363476948673839346a4833377842464445582f414c6e4533334263567a65385162747a66366770425837766334504e39776f6556707549726541334355354e6f45554a552b304e704c45444563656434697133415a6433507645562b523369436a577538515869694f346c554367684a564c3549616c55472b64444c4845342f64376849774357574d47656c5833424b63443369416e484b3767534145753667584264774b665063416e4a642f714263454b66374f494e7939376c77594e512b436f4d47467767455179766b7558544d69462b43784970434d353558764566493250444d354545644f385466654a593071376c6e4744513839346a3168612b2b344535532b34795944754e543365344d4f487675413835754d68622f5a784c66767645556a437357723778475177626f7a33446e48502b4a63574673716a50634c7a4876454579636b356953584650694346474d376c6e332f69475a444f623341584545503141544d5a376c6971714c75684a59536b446d4c68584d44385541424370357468635a766350446c33426a3776634c654c7663796f3537676b4c2f76654a647944525765357a3833334c764443784364376f42376c664a643768793475344c4773735178516841334149422f3841414a6b4e6c5468564b7848465a335046774a576d7238596d4f567971675837397748383375666e2f414e784573586a336535566d4461555833426e464564775650643778413348672f4f35616f6847637276634869635065397734387272635a507a754750747544534d644a584e3767572f4e376733754d4d433373767645714b4c76654a524456334b724552454c726d397765432b65346b4c575649316351686163713859624c554d4a54635a54544145584b4373646b747758434d74425962377842527866654967653363475773503758395166357663432b4c76654a796d2b35792b373369636d41654b7a75446534624c3937682f64372b4e6d442b56376768386867774c59417753584c43496647794d7370527268634e2f666337334268354f65343147727663414b6562334f5239397a4a37376d373369414d416741732f3978465a432b34493166506343494c477763582f69424c69723276634e747773652b38526562454835627842744c357663556757764e797a3939776377356e6d2f314c7a7a64627843483339596c793762616a634f59615835754a50613978755576754a57565463692b6369785866427874346a634b737655703962336949737531336950697071455a47344233425678446a62344b33754850465a2b45764f4b4637506538517753763369427663613442687476506549514f534350767547463667467a64376a45507734386d594a38427a44344a517844775264435568742f6e6c674b65345942706d2f314c2f6d393467707565385256576c33754a636f56357663466c547758634f5a35376c45454b695869504d42684c6a44596c4f38536e7864376c692b2b385166476534674c662b3468494762334b74427a3343586546397a6d7a6e4e43594f5249564b53374a394553435a4a6557496b4b6561334b337675466f617a2b6f6b6458354b36724a34376a4638743137664f4a39773752784f6f76426c4d4d6d4b6c4732424d6559633051726e7a6535544f626773694a57414d4b696d412f4543636564774e37674c583375424e34366843662f69627663352b4c376d2b3463776f417371487752686966445469536e6c4f4b6c546b57755574337a6535527747397742384b463872466c547a754258506e755970712b34422b3733415239337543754d3778467237377848624161724f496b427663554b34755665313778462f50654939376a45764e37784861496767435a6479696e4b397937704a58566d6434684173556975346a6e6c6636684256515a5a657a6c79526c6c72753368664d6f5356597176767541423776654a35664d3471682f3369484543717979677a496a6f71716c6537554e53473977674335567a65495155776c7770697730652b34573139372b4e583841733939346e4f53424c443737784342384434494d704257455a644b346e7a76694a643342736f4a545135766678753462376c6d49666976627a336a344465344d2b653455446d2b38537839397744527976654a783972334b43504678525257536d7552653448467565353950377844666549464e4639796f504e3767674663397756555a367535624469496e4c6b334b582f63346975484d57495956644c497835344668534d6e6b6d3448547833694454454538316e63483171334442342f6c3877772f4133464b7264376955444c39516f417367525469455950775250682b552f77446b6a43544b435a674c5959454953346642434d495269543151446943675a64464d72494969664577533671436c334a57526346537749385172677542634e7361764556584b346646636b49754744536865466751344845486d6c37322b4a56466f4b325051704b32596d56724252616b7952576a4d536d794353662f454142635141414d4241414141414141414141414141414141414145526b4d442f3267414941514541487a38516b4137614847322f2f396b3d); + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `report` +-- + +DROP TABLE IF EXISTS `report`; +CREATE TABLE `report` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `_Date` date NOT NULL, + `TotalPrice` double DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- Cấu trúc bảng cho bảng `table` +-- + +DROP TABLE IF EXISTS `table`; +CREATE TABLE `table` ( + `ID` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `Name` varchar(100) COLLATE utf8_unicode_ci DEFAULT 'No Name', + `Status` int(11) DEFAULT '-1' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; + +-- +-- Đang đổ dữ liệu cho bảng `table` +-- + +INSERT INTO `table` (`ID`, `Name`, `Status`) VALUES +(1, 'Table 1', -1), +(2, 'Table 2', -1), +(3, 'Table 3', -1), +(4, 'Table 4', -1), +(5, 'Table 5', -1), +(6, 'Table 6', -1), +(7, 'Table 7', -1), +(8, 'Table 8', -1), +(9, 'Table 9', -1), +(10, 'Table 10', -1), +(11, 'Table 11', -1), +(12, 'Table 12', -1), +(13, 'Table 14', -1), +(14, 'Table 15', -1), +(15, 'Table 17', -1); + +-- +-- Chỉ mục cho các bảng đã đổ +-- + +-- +-- Chỉ mục cho bảng `account` +-- +ALTER TABLE `account` +-- ADD PRIMARY KEY (`Username`), + ADD KEY `IDAccountType` (`IDAccountType`), + ADD KEY `IDImage` (`IDImage`); + +-- +-- Chỉ mục cho bảng `accounttype` +-- +-- ALTER TABLE `accounttype` +-- ADD PRIMARY KEY (`ID`); + +-- +-- Chỉ mục cho bảng `authentication` +-- +-- ALTER TABLE `authentication` +-- ADD PRIMARY KEY (`Username`); + +-- +-- Chỉ mục cho bảng `bill` +-- +ALTER TABLE `bill` +-- ADD PRIMARY KEY (`ID`), + ADD KEY `IDTable` (`IDTable`), + ADD KEY `Username` (`Username`); + +-- +-- Chỉ mục cho bảng `billinfo` +-- +ALTER TABLE `billinfo` + ADD KEY `IDBill` (`IDBill`), + ADD KEY `IDFood` (`IDFood`); + +-- +-- Chỉ mục cho bảng `food` +-- +ALTER TABLE `food` +-- ADD PRIMARY KEY (`ID`), + ADD KEY `IDImage` (`IDImage`), + ADD KEY `IDCategory` (`IDCategory`); + +-- +-- Chỉ mục cho bảng `foodcategory` +-- +-- ALTER TABLE `foodcategory` +-- ADD PRIMARY KEY (`ID`); + +-- +-- Chỉ mục cho bảng `image` +-- +-- ALTER TABLE `image` +-- ADD PRIMARY KEY (`ID`); + +-- +-- Chỉ mục cho bảng `report` +-- +-- ALTER TABLE `report` +-- ADD PRIMARY KEY (`ID`), +-- ADD UNIQUE KEY `_Date` (`_Date`); + +-- +-- Chỉ mục cho bảng `table` +-- +-- ALTER TABLE `table` +-- ADD PRIMARY KEY (`ID`); + +-- +-- AUTO_INCREMENT cho các bảng đã đổ +-- + +-- +-- AUTO_INCREMENT cho bảng `accounttype` +-- +ALTER TABLE `accounttype` + MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; +-- +-- AUTO_INCREMENT cho bảng `bill` +-- +ALTER TABLE `bill` + MODIFY `ID` int(11) NOT NULL AUTO_INCREMENT; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/server/pubspec.yaml b/server/pubspec.yaml new file mode 100644 index 0000000..4af3649 --- /dev/null +++ b/server/pubspec.yaml @@ -0,0 +1,19 @@ +name: store_pattern_service +description: Service for store pattern +publish_to: none # Ensure we don't accidentally publish our private code! ;) +environment: + sdk: '>=2.0.0-dev <3.0.0' +dependencies: + angel_configuration: ^2.0.0 # Loads application configuration, along with support for .env files. + angel_framework: ^2.0.0 # The core server library. + angel_serialize: ^2.0.0 # Serialization runtime support + angel_production: ^1.0.0 # Production application runner. + mysql1: ^0.17.1 +dev_dependencies: + angel_hot: ^2.0.0 # Hot-reloading support. :) + angel_migration_runner: ^2.0.0 # Runs migrations + angel_orm_generator: ^2.0.0 # Generates ORM libraries + angel_test: ^2.0.0 # Utilities for testing Angel servers. + io: ^0.3.2 # For pretty printing. + pedantic: ^1.0.0 # Enforces Dart style conventions. + test: ^1.0.0 # For unit testing. diff --git a/server/test/all_test.dart b/server/test/all_test.dart new file mode 100644 index 0000000..85acc69 --- /dev/null +++ b/server/test/all_test.dart @@ -0,0 +1,43 @@ +import 'package:store_pattern_service/store_pattern_service.dart'; +import 'package:angel_framework/angel_framework.dart'; +import 'package:angel_test/angel_test.dart'; +import 'package:test/test.dart'; + +// Angel also includes facilities to make testing easier. +// +// `package:angel_test` ships a client that can test +// both plain HTTP and WebSockets. +// +// Tests do not require your server to actually be mounted on a port, +// so they will run faster than they would in other frameworks, where you +// would have to first bind a socket, and then account for network latency. +// +// See the documentation here: +// https://github.com/angel-dart/test +// +// If you are unfamiliar with Dart's advanced testing library, you can read up +// here: +// https://github.com/dart-lang/test + +void main() async { + TestClient client; + + setUp(() async { + var app = Angel(); + await app.configure(configureServer); + + client = await connectTo(app); + }); + + tearDown(() async { + await client.close(); + }); + + test('index returns 200', () async { + // Request a resource at the given path. + var response = await client.get('/'); + + // Expect a 200 response. + expect(response, hasStatus(200)); + }); +}