From ac1ece6e15b9cde804ecbe67f146456e5c532a34 Mon Sep 17 00:00:00 2001 From: Thibaud Dupuis <124290694+ThibaudDps@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:27:44 +0100 Subject: [PATCH 01/10] init --- backend/database/schema.sql | 68 +++++++++++++++++++++++++++++++++++-- backend/package-lock.json | 35 +++++++++++++++++++ backend/package.json | 1 + backend/src/app.js | 4 +-- 4 files changed, 103 insertions(+), 5 deletions(-) diff --git a/backend/database/schema.sql b/backend/database/schema.sql index d7542a2f..09d5d5d8 100644 --- a/backend/database/schema.sql +++ b/backend/database/schema.sql @@ -1,4 +1,68 @@ -create table item ( + +create table pkmn_type ( id int unsigned primary key auto_increment not null, - title varchar(255) not null + name varchar(50) not null, + image varchar(255) not null ); + +create table pokemon ( + id int unsigned primary key auto_increment not null, + name varchar(50) not null, + description varchar(255) not null, + image varchar(255) not null +); + +ALTER TABLE pokemon +ADD COLUMN pkmn_type_id INTEGER, +ADD CONSTRAINT fk_type_id FOREIGN KEY (pkmn_type_id) REFERENCES pkmn_type(id); + +INSERT INTO pkmn_type (id, name, image) VALUES +(1, 'Grass', 'http://www.rw-designer.com/icon-view/21171.png'), +(2, 'Fire', 'http://www.rw-designer.com/icon-view/21169.png'), +(3, 'Water', 'http://www.rw-designer.com/icon-view/21170.png'), +(4, 'Bug', 'http://www.rw-designer.com/icon-view/21178.png'), +(5, 'Normal', 'http://www.rw-designer.com/icon-view/21168.png'), +(6, 'Flying', 'http://www.rw-designer.com/icon-view/21175.png'), +(7, 'Poison', 'http://www.rw-designer.com/icon-view/21183.png'), +(8, 'Electric', 'http://www.rw-designer.com/icon-view/21179.png'), +(9, 'Ground', 'http://www.rw-designer.com/icon-view/21172.png'), +(10, 'Psychic', 'http://www.rw-designer.com/icon-view/21185.png'), +(11, 'Fighting', 'http://www.rw-designer.com/icon-view/21181.png'), +(12, 'Rock', 'http://www.rw-designer.com/icon-view/21174.png'), +(13, 'Ghost', 'http://www.rw-designer.com/icon-view/21187.png'), +(14, 'Ice', 'http://www.rw-designer.com/icon-view/21176.png'), +(15, 'Dragon', 'http://www.rw-designer.com/icon-view/21189.png'), +(16, 'Steel', 'http://www.rw-designer.com/icon-view/21180.png'), +(17, 'Dark', 'http://www.rw-designer.com/icon-view/21184.png'), +(18, 'Fairy', 'http://www.rw-designer.com/icon-view/21188.png'); + + + INSERT INTO pokemon (id, name, description, image) VALUES +(1, 'Bulbasaur', 'A grass/poison-type Pokémon with a plant bulb on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/f/fb/0001Bulbasaur.png/70px-0001Bulbasaur.png'), +(2, 'Ivysaur', 'The evolved form of Bulbasaur with a larger plant bulb.', 'https://archives.bulbagarden.net/media/upload/thumb/8/81/0002Ivysaur.png/70px-0002Ivysaur.png'), +(3, 'Venusaur', 'The final evolution of Bulbasaur with a large flower on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/6/6b/0003Venusaur.png/70px-0003Venusaur.png'), +(4, 'Charmander', 'A fire-type Pokémon with a flame on its tail.', 'https://archives.bulbagarden.net/media/upload/thumb/2/27/0004Charmander.png/70px-0004Charmander.png'), +(5, 'Charmeleon', 'The evolved form of Charmander with a larger flame.', 'https://archives.bulbagarden.net/media/upload/thumb/0/05/0005Charmeleon.png/70px-0005Charmeleon.png'), +(6, 'Charizard', 'The final evolution of Charmander with powerful fire attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/3/38/0006Charizard.png/70px-0006Charizard.png'), +(7, 'Squirtle', 'A water-type Pokémon with a shell on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/5/54/0007Squirtle.png/70px-0007Squirtle.png'), +(8, 'Wartortle', 'The evolved form of Squirtle with a larger shell.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0f/0008Wartortle.png/70px-0008Wartortle.png'), +(9, 'Blastoise', 'The final evolution of Squirtle with powerful water cannons on its shell.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0a/0009Blastoise.png/70px-0009Blastoise.png'), +(10, 'Caterpie', 'A bug-type Pokémon with a voracious appetite for leaves.', 'https://archives.bulbagarden.net/media/upload/thumb/5/5e/0010Caterpie.png/70px-0010Caterpie.png'), +(11, 'Metapod', 'The evolved form of Caterpie, undergoing metamorphosis.', 'https://archives.bulbagarden.net/media/upload/thumb/d/da/0011Metapod.png/70px-0011Metapod.png'), +(12, 'Butterfree', 'The final evolution of Caterpie, a graceful butterfly with powdery wings.', 'https://archives.bulbagarden.net/media/upload/thumb/5/55/0012Butterfree.png/70px-0012Butterfree.png'), +(13, 'Weedle', 'A bug/poison-type Pokémon with a sharp stinger on its head.', 'https://archives.bulbagarden.net/media/upload/thumb/3/36/0013Weedle.png/70px-0013Weedle.png'), +(14, 'Kakuna', 'The evolved form of Weedle, hardening its shell for protection.', 'https://archives.bulbagarden.net/media/upload/thumb/f/f3/0014Kakuna.png/70px-0014Kakuna.png'), +(15, 'Beedrill', 'The final evolution of Weedle, a menacing Pokémon with poison stingers.', 'https://archives.bulbagarden.net/media/upload/thumb/f/f7/0015Beedrill.png/70px-0015Beedrill.png'), +(16, 'Pidgey', 'A normal/flying-type Pokémon with a keen eye and excellent flying abilities.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0c/0016Pidgey.png/70px-0016Pidgey.png'), +(17, 'Pidgeotto', 'The evolved form of Pidgey, a bird with larger wings and more powerful attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/8/82/0017Pidgeotto.png/70px-0017Pidgeotto.png'), +(18, 'Pidgeot', 'The final evolution of Pidgey, a majestic bird with impressive wingspan.', 'https://archives.bulbagarden.net/media/upload/thumb/7/73/0018Pidgeot.png/70px-0018Pidgeot.png'), +(19, 'Rattata', 'A normal-type Pokémon known for its speed and agility.', 'https://archives.bulbagarden.net/media/upload/thumb/a/aa/0019Rattata.png/70px-0019Rattata.png'), +(20, 'Raticate', 'The evolved form of Rattata, a fast and aggressive rodent Pokémon.', 'https://archives.bulbagarden.net/media/upload/thumb/2/2c/0020Raticate.png/70px-0020Raticate.png'), +(21, 'Spearow', 'A normal/flying-type Pokémon with a sharp beak for hunting.', 'https://archives.bulbagarden.net/media/upload/thumb/2/2d/0021Spearow.png/70px-0021Spearow.png'), +(22, 'Fearow', 'The evolved form of Spearow, a large bird with powerful beak attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/9/92/0022Fearow.png/70px-0022Fearow.png'), +(23, 'Ekans', 'A poison-type Pokémon with a serpentine appearance.', 'https://archives.bulbagarden.net/media/upload/thumb/d/d2/0023Ekans.png/70px-0023Ekans.png'), +(24, 'Arbok', 'The evolved form of Ekans, a large cobra Pokémon with a hood.', 'https://archives.bulbagarden.net/media/upload/thumb/5/51/0024Arbok.png/70px-0024Arbok.png'), +(25, 'Pikachu', 'An electric-type Pokémon with yellow fur.', 'https://archives.bulbagarden.net/media/upload/thumb/4/4a/0025Pikachu.png/70px-0025Pikachu.png'), +(26, 'Raichu', 'The evolved form of Pikachu, an electric Pokémon with enhanced power.', 'https://archives.bulbagarden.net/media/upload/thumb/b/b0/0026Raichu.png/70px-0026Raichu.png'); + +UPDATE pokemon SET type_id = 1 WHERE id IN (1, 2, 3); \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index 996593d9..97820bf0 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "mysql2": "^3.5.2" @@ -2203,6 +2204,18 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -5375,6 +5388,14 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -8785,6 +8806,15 @@ "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -11120,6 +11150,11 @@ "path-key": "^3.0.0" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, "object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", diff --git a/backend/package.json b/backend/package.json index 292e378f..0adab400 100644 --- a/backend/package.json +++ b/backend/package.json @@ -8,6 +8,7 @@ "test": "jest" }, "dependencies": { + "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", "mysql2": "^3.5.2" diff --git a/backend/src/app.js b/backend/src/app.js index 22be9ab9..e9c4310a 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -25,7 +25,6 @@ const app = express(); // 4. Be sure to only have URLs in the array with domains from which you want to allow requests. // For example: ["http://mysite.com", "http://another-domain.com"] -/* const cors = require("cors"); app.use( @@ -34,10 +33,9 @@ app.use( process.env.FRONTEND_URL, // keep this one, after checking the value in `backend/.env` "http://mysite.com", "http://another-domain.com", - ] + ], }) ); -*/ /* ************************************************************************* */ From 945e4895adf34e3ed39df50a512f64f8dc53b273 Mon Sep 17 00:00:00 2001 From: Thibaud Dupuis <124290694+ThibaudDps@users.noreply.github.com> Date: Thu, 30 Nov 2023 17:30:58 +0100 Subject: [PATCH 02/10] init --- backend/database/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/database/schema.sql b/backend/database/schema.sql index 09d5d5d8..6a663f16 100644 --- a/backend/database/schema.sql +++ b/backend/database/schema.sql @@ -65,4 +65,4 @@ INSERT INTO pkmn_type (id, name, image) VALUES (25, 'Pikachu', 'An electric-type Pokémon with yellow fur.', 'https://archives.bulbagarden.net/media/upload/thumb/4/4a/0025Pikachu.png/70px-0025Pikachu.png'), (26, 'Raichu', 'The evolved form of Pikachu, an electric Pokémon with enhanced power.', 'https://archives.bulbagarden.net/media/upload/thumb/b/b0/0026Raichu.png/70px-0026Raichu.png'); -UPDATE pokemon SET type_id = 1 WHERE id IN (1, 2, 3); \ No newline at end of file +UPDATE pokemon SET pkmn_type_id = 1 WHERE id IN (1, 2, 3); \ No newline at end of file From 406559f5e4bd488548f9265d3f24d06d95c3bf84 Mon Sep 17 00:00:00 2001 From: Thibaud Dupuis <124290694+ThibaudDps@users.noreply.github.com> Date: Fri, 1 Dec 2023 00:31:12 +0100 Subject: [PATCH 03/10] css + route + ajout footer + pages --- backend/database/schema.sql | 54 +++--- backend/package-lock.json | 69 ++++++-- backend/package.json | 1 + ...{itemControllers.js => pkmnControllers.js} | 30 ++-- backend/src/models/ItemManager.js | 30 ++-- backend/src/router.js | 16 +- frontend/index.html | 8 +- frontend/package-lock.json | 154 +++++++++++++++++- frontend/package.json | 3 +- frontend/src/App.css | 35 ++-- frontend/src/App.jsx | 42 +---- frontend/src/assets/favicon.svg | 15 -- frontend/src/assets/favimon.svg | 1 + frontend/src/assets/logo.svg | 7 - frontend/src/assets/logomon.svg | 9 + frontend/src/components/CardPkmn.jsx | 30 ++++ frontend/src/components/Counter.jsx | 16 -- frontend/src/components/Footer.jsx | 9 + frontend/src/components/Navbar.jsx | 7 + frontend/src/main.jsx | 23 ++- frontend/src/pages/AllPkmns.jsx | 7 + frontend/src/pages/Home.jsx | 20 +++ frontend/src/pages/PkmnPage.jsx | 7 + frontend/src/style/CardPkmn.css | 28 ++++ frontend/src/style/Footer.css | 14 ++ 25 files changed, 459 insertions(+), 176 deletions(-) rename backend/src/controllers/{itemControllers.js => pkmnControllers.js} (61%) delete mode 100644 frontend/src/assets/favicon.svg create mode 100644 frontend/src/assets/favimon.svg delete mode 100644 frontend/src/assets/logo.svg create mode 100644 frontend/src/assets/logomon.svg create mode 100644 frontend/src/components/CardPkmn.jsx delete mode 100644 frontend/src/components/Counter.jsx create mode 100644 frontend/src/components/Footer.jsx create mode 100644 frontend/src/components/Navbar.jsx create mode 100644 frontend/src/pages/AllPkmns.jsx create mode 100644 frontend/src/pages/Home.jsx create mode 100644 frontend/src/pages/PkmnPage.jsx create mode 100644 frontend/src/style/CardPkmn.css create mode 100644 frontend/src/style/Footer.css diff --git a/backend/database/schema.sql b/backend/database/schema.sql index 6a663f16..8d319127 100644 --- a/backend/database/schema.sql +++ b/backend/database/schema.sql @@ -38,31 +38,31 @@ INSERT INTO pkmn_type (id, name, image) VALUES INSERT INTO pokemon (id, name, description, image) VALUES -(1, 'Bulbasaur', 'A grass/poison-type Pokémon with a plant bulb on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/f/fb/0001Bulbasaur.png/70px-0001Bulbasaur.png'), -(2, 'Ivysaur', 'The evolved form of Bulbasaur with a larger plant bulb.', 'https://archives.bulbagarden.net/media/upload/thumb/8/81/0002Ivysaur.png/70px-0002Ivysaur.png'), -(3, 'Venusaur', 'The final evolution of Bulbasaur with a large flower on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/6/6b/0003Venusaur.png/70px-0003Venusaur.png'), -(4, 'Charmander', 'A fire-type Pokémon with a flame on its tail.', 'https://archives.bulbagarden.net/media/upload/thumb/2/27/0004Charmander.png/70px-0004Charmander.png'), -(5, 'Charmeleon', 'The evolved form of Charmander with a larger flame.', 'https://archives.bulbagarden.net/media/upload/thumb/0/05/0005Charmeleon.png/70px-0005Charmeleon.png'), -(6, 'Charizard', 'The final evolution of Charmander with powerful fire attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/3/38/0006Charizard.png/70px-0006Charizard.png'), -(7, 'Squirtle', 'A water-type Pokémon with a shell on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/5/54/0007Squirtle.png/70px-0007Squirtle.png'), -(8, 'Wartortle', 'The evolved form of Squirtle with a larger shell.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0f/0008Wartortle.png/70px-0008Wartortle.png'), -(9, 'Blastoise', 'The final evolution of Squirtle with powerful water cannons on its shell.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0a/0009Blastoise.png/70px-0009Blastoise.png'), -(10, 'Caterpie', 'A bug-type Pokémon with a voracious appetite for leaves.', 'https://archives.bulbagarden.net/media/upload/thumb/5/5e/0010Caterpie.png/70px-0010Caterpie.png'), -(11, 'Metapod', 'The evolved form of Caterpie, undergoing metamorphosis.', 'https://archives.bulbagarden.net/media/upload/thumb/d/da/0011Metapod.png/70px-0011Metapod.png'), -(12, 'Butterfree', 'The final evolution of Caterpie, a graceful butterfly with powdery wings.', 'https://archives.bulbagarden.net/media/upload/thumb/5/55/0012Butterfree.png/70px-0012Butterfree.png'), -(13, 'Weedle', 'A bug/poison-type Pokémon with a sharp stinger on its head.', 'https://archives.bulbagarden.net/media/upload/thumb/3/36/0013Weedle.png/70px-0013Weedle.png'), -(14, 'Kakuna', 'The evolved form of Weedle, hardening its shell for protection.', 'https://archives.bulbagarden.net/media/upload/thumb/f/f3/0014Kakuna.png/70px-0014Kakuna.png'), -(15, 'Beedrill', 'The final evolution of Weedle, a menacing Pokémon with poison stingers.', 'https://archives.bulbagarden.net/media/upload/thumb/f/f7/0015Beedrill.png/70px-0015Beedrill.png'), -(16, 'Pidgey', 'A normal/flying-type Pokémon with a keen eye and excellent flying abilities.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0c/0016Pidgey.png/70px-0016Pidgey.png'), -(17, 'Pidgeotto', 'The evolved form of Pidgey, a bird with larger wings and more powerful attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/8/82/0017Pidgeotto.png/70px-0017Pidgeotto.png'), -(18, 'Pidgeot', 'The final evolution of Pidgey, a majestic bird with impressive wingspan.', 'https://archives.bulbagarden.net/media/upload/thumb/7/73/0018Pidgeot.png/70px-0018Pidgeot.png'), -(19, 'Rattata', 'A normal-type Pokémon known for its speed and agility.', 'https://archives.bulbagarden.net/media/upload/thumb/a/aa/0019Rattata.png/70px-0019Rattata.png'), -(20, 'Raticate', 'The evolved form of Rattata, a fast and aggressive rodent Pokémon.', 'https://archives.bulbagarden.net/media/upload/thumb/2/2c/0020Raticate.png/70px-0020Raticate.png'), -(21, 'Spearow', 'A normal/flying-type Pokémon with a sharp beak for hunting.', 'https://archives.bulbagarden.net/media/upload/thumb/2/2d/0021Spearow.png/70px-0021Spearow.png'), -(22, 'Fearow', 'The evolved form of Spearow, a large bird with powerful beak attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/9/92/0022Fearow.png/70px-0022Fearow.png'), -(23, 'Ekans', 'A poison-type Pokémon with a serpentine appearance.', 'https://archives.bulbagarden.net/media/upload/thumb/d/d2/0023Ekans.png/70px-0023Ekans.png'), -(24, 'Arbok', 'The evolved form of Ekans, a large cobra Pokémon with a hood.', 'https://archives.bulbagarden.net/media/upload/thumb/5/51/0024Arbok.png/70px-0024Arbok.png'), -(25, 'Pikachu', 'An electric-type Pokémon with yellow fur.', 'https://archives.bulbagarden.net/media/upload/thumb/4/4a/0025Pikachu.png/70px-0025Pikachu.png'), -(26, 'Raichu', 'The evolved form of Pikachu, an electric Pokémon with enhanced power.', 'https://archives.bulbagarden.net/media/upload/thumb/b/b0/0026Raichu.png/70px-0026Raichu.png'); - +(1, 'Bulbasaur', 'A grass/poison-type Pokémon with a plant bulb on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/f/fb/0001Bulbasaur.png/600px-0001Bulbasaur.png'), +(2, 'Ivysaur', 'The evolved form of Bulbasaur with a larger plant bulb.', 'https://archives.bulbagarden.net/media/upload/8/81/0002Ivysaur.png'), +(3, 'Venusaur', 'The final evolution of Bulbasaur with a large flower on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/6/6b/0003Venusaur.png/600px-0003Venusaur.png'), +(4, 'Charmander', 'A fire-type Pokémon with a flame on its tail.', 'https://archives.bulbagarden.net/media/upload/2/27/0004Charmander.png'), +(5, 'Charmeleon', 'The evolved form of Charmander with a larger flame.', 'https://archives.bulbagarden.net/media/upload/0/05/0005Charmeleon.png'), +(6, 'Charizard', 'The final evolution of Charmander with powerful fire attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/3/38/0006Charizard.png/600px-0006Charizard.png'), +(7, 'Squirtle', 'A water-type Pokémon with a shell on its back.', 'https://archives.bulbagarden.net/media/upload/thumb/5/54/0007Squirtle.png/600px-0007Squirtle.png'), +(8, 'Wartortle', 'The evolved form of Squirtle with a larger shell.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0f/0008Wartortle.png/600px-0008Wartortle.png'), +(9, 'Blastoise', 'The final evolution of Squirtle with powerful water cannons on its shell.', 'https://archives.bulbagarden.net/media/upload/thumb/0/0a/0009Blastoise.png/600px-0009Blastoise.png'), +(10, 'Caterpie', 'A bug-type Pokémon with a voracious appetite for leaves.', 'https://archives.bulbagarden.net/media/upload/thumb/5/5e/0010Caterpie.png/600px-0010Caterpie.png'), +(11, 'Metapod', 'The evolved form of Caterpie, undergoing metamorphosis.', 'https://archives.bulbagarden.net/media/upload/d/da/0011Metapod.png'), +(12, 'Butterfree', 'The final evolution of Caterpie, a graceful butterfly with powdery wings.', 'https://archives.bulbagarden.net/media/upload/thumb/5/55/0012Butterfree.png/600px-0012Butterfree.png'), +(13, 'Weedle', 'A bug/poison-type Pokémon with a sharp stinger on its head.', 'https://archives.bulbagarden.net/media/upload/thumb/3/36/0013Weedle.png/600px-0013Weedle.png'), +(14, 'Kakuna', 'The evolved form of Weedle, hardening its shell for protection.', 'https://archives.bulbagarden.net/media/upload/thumb/f/f3/0014Kakuna.png/600px-0014Kakuna.png'), +(15, 'Beedrill', 'The final evolution of Weedle, a menacing Pokémon with poison stingers.', 'https://archives.bulbagarden.net/media/upload/thumb/f/f7/0015Beedrill.png/600px-0015Beedrill.png'), +(16, 'Pidgey', 'A normal/flying-type Pokémon with a keen eye and excellent flying abilities.', 'https://archives.bulbagarden.net/media/upload/0/0c/0016Pidgey.png'), +(17, 'Pidgeotto', 'The evolved form of Pidgey, a bird with larger wings and more powerful attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/8/82/0017Pidgeotto.png/600px-0017Pidgeotto.png'), +(18, 'Pidgeot', 'The final evolution of Pidgey, a majestic bird with impressive wingspan.', 'https://archives.bulbagarden.net/media/upload/thumb/7/73/0018Pidgeot.png/600px-0018Pidgeot.png'), +(19, 'Rattata', 'A normal-type Pokémon known for its speed and agility.', 'https://archives.bulbagarden.net/media/upload/thumb/a/aa/0019Rattata.png/600px-0019Rattata.png'), +(20, 'Raticate', 'The evolved form of Rattata, a fast and aggressive rodent Pokémon.', 'https://archives.bulbagarden.net/media/upload/thumb/2/2c/0020Raticate.png/600px-0020Raticate.png'), +(21, 'Spearow', 'A normal/flying-type Pokémon with a sharp beak for hunting.', 'https://archives.bulbagarden.net/media/upload/thumb/2/2d/0021Spearow.png/600px-0021Spearow.png'), +(22, 'Fearow', 'The evolved form of Spearow, a large bird with powerful beak attacks.', 'https://archives.bulbagarden.net/media/upload/thumb/9/92/0022Fearow.png/600px-0022Fearow.png'), +(23, 'Ekans', 'A poison-type Pokémon with a serpentine appearance.', 'https://archives.bulbagarden.net/media/upload/thumb/d/d2/0023Ekans.png/600px-0023Ekans.png'), +(24, 'Arbok', 'The evolved form of Ekans, a large cobra Pokémon with a hood.', 'https://archives.bulbagarden.net/media/upload/thumb/5/51/0024Arbok.png/600px-0024Arbok.png'), +(25, 'Pikachu', 'An electric-type Pokémon with yellow fur.', 'https://archives.bulbagarden.net/media/upload/thumb/4/4a/0025Pikachu.png/600px-0025Pikachu.png'), +(26, 'Raichu', 'The evolved form of Pikachu, an electric Pokémon with enhanced power.', 'https://archives.bulbagarden.net/media/upload/thumb/b/b0/0026Raichu.png/600px-0026Raichu.png'); +(27, 'Sandshrew', 'A ground-type Pokémon with tough sand-colored skin.', 'https://archives.bulbagarden.net/media/upload/thumb/e/e9/0027Sandshrew.png/600px-0027Sandshrew.png'); UPDATE pokemon SET pkmn_type_id = 1 WHERE id IN (1, 2, 3); \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index 97820bf0..3c5e9ed3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "axios": "^1.6.2", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", @@ -1657,8 +1658,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/available-typed-arrays": { "version": "1.0.5", @@ -1672,6 +1672,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -2131,7 +2141,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2487,7 +2496,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -3322,6 +3330,25 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -3335,7 +3362,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -5854,6 +5880,11 @@ "node": ">= 0.10" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", @@ -8408,8 +8439,7 @@ "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "available-typed-arrays": { "version": "1.0.5", @@ -8417,6 +8447,16 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, + "axios": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -8748,7 +8788,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "requires": { "delayed-stream": "~1.0.0" } @@ -8988,8 +9027,7 @@ "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "denque": { "version": "2.1.0", @@ -9639,6 +9677,11 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -9652,7 +9695,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -11479,6 +11521,11 @@ "ipaddr.js": "1.9.1" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", diff --git a/backend/package.json b/backend/package.json index 0adab400..714bdc33 100644 --- a/backend/package.json +++ b/backend/package.json @@ -8,6 +8,7 @@ "test": "jest" }, "dependencies": { + "axios": "^1.6.2", "cors": "^2.8.5", "dotenv": "^16.3.1", "express": "^4.18.2", diff --git a/backend/src/controllers/itemControllers.js b/backend/src/controllers/pkmnControllers.js similarity index 61% rename from backend/src/controllers/itemControllers.js rename to backend/src/controllers/pkmnControllers.js index fca2dc2d..0695abed 100644 --- a/backend/src/controllers/itemControllers.js +++ b/backend/src/controllers/pkmnControllers.js @@ -4,11 +4,11 @@ const tables = require("../tables"); // The B of BREAD - Browse (Read All) operation const browse = async (req, res, next) => { try { - // Fetch all items from the database - const items = await tables.item.readAll(); + // Fetch all pokemons from the database + const pokemons = await tables.pokemon.readAll(); - // Respond with the items in JSON format - res.json(items); + // Respond with the pokemons in JSON format + res.json(pokemons); } catch (err) { // Pass any errors to the error-handling middleware next(err); @@ -18,15 +18,15 @@ const browse = async (req, res, next) => { // The R of BREAD - Read operation const read = async (req, res, next) => { try { - // Fetch a specific item from the database based on the provided ID - const item = await tables.item.read(req.params.id); + // Fetch a specific pokemon from the database based on the provided ID + const pokemon = await tables.pokemon.read(req.params.id); - // If the item is not found, respond with HTTP 404 (Not Found) - // Otherwise, respond with the item in JSON format - if (item == null) { + // If the pokemon is not found, respond with HTTP 404 (Not Found) + // Otherwise, respond with the pokemon in JSON format + if (pokemon == null) { res.sendStatus(404); } else { - res.json(item); + res.json(pokemon); } } catch (err) { // Pass any errors to the error-handling middleware @@ -39,14 +39,14 @@ const read = async (req, res, next) => { // The A of BREAD - Add (Create) operation const add = async (req, res, next) => { - // Extract the item data from the request body - const item = req.body; + // Extract the pokemon data from the request body + const pokemon = req.body; try { - // Insert the item into the database - const insertId = await tables.item.create(item); + // Insert the pokemon into the database + const insertId = await tables.pokemon.create(pokemon); - // Respond with HTTP 201 (Created) and the ID of the newly inserted item + // Respond with HTTP 201 (Created) and the ID of the newly inserted pokemon res.status(201).json({ insertId }); } catch (err) { // Pass any errors to the error-handling middleware diff --git a/backend/src/models/ItemManager.js b/backend/src/models/ItemManager.js index eeeae9f3..ce92cf11 100644 --- a/backend/src/models/ItemManager.js +++ b/backend/src/models/ItemManager.js @@ -1,59 +1,59 @@ const AbstractManager = require("./AbstractManager"); -class ItemManager extends AbstractManager { +class pokemonManager extends AbstractManager { constructor() { // Call the constructor of the parent class (AbstractManager) - // and pass the table name "item" as configuration - super({ table: "item" }); + // and pass the table name "pokemon" as configuration + super({ table: "pokemon" }); } // The C of CRUD - Create operation - async create(item) { - // Execute the SQL INSERT query to add a new item to the "item" table + async create(pokemon) { + // Execute the SQL INSERT query to add a new pokemon to the "pokemon" table const [result] = await this.database.query( `insert into ${this.table} (title) values (?)`, - [item.title] + [pokemon.name] ); - // Return the ID of the newly inserted item + // Return the ID of the newly inserted pokemon return result.insertId; } // The Rs of CRUD - Read operations async read(id) { - // Execute the SQL SELECT query to retrieve a specific item by its ID + // Execute the SQL SELECT query to retrieve a specific pokemon by its ID const [rows] = await this.database.query( `select * from ${this.table} where id = ?`, [id] ); - // Return the first row of the result, which represents the item + // Return the first row of the result, which represents the pokemon return rows[0]; } async readAll() { - // Execute the SQL SELECT query to retrieve all items from the "item" table + // Execute the SQL SELECT query to retrieve all pokemons from the "pokemon" table const [rows] = await this.database.query(`select * from ${this.table}`); - // Return the array of items + // Return the array of pokemons return rows; } // The U of CRUD - Update operation - // TODO: Implement the update operation to modify an existing item + // TODO: Implement the update operation to modify an existing pokemon - // async update(item) { + // async update(pokemon) { // ... // } // The D of CRUD - Delete operation - // TODO: Implement the delete operation to remove an item by its ID + // TODO: Implement the delete operation to remove an pokemon by its ID // async delete(id) { // ... // } } -module.exports = ItemManager; +module.exports = pokemonManager; diff --git a/backend/src/router.js b/backend/src/router.js index 38f375d7..de02f721 100644 --- a/backend/src/router.js +++ b/backend/src/router.js @@ -6,17 +6,17 @@ const router = express.Router(); // Define Your API Routes Here /* ************************************************************************* */ -// Import itemControllers module for handling item-related operations -const itemControllers = require("./controllers/itemControllers"); +// Import pkmnControllers module for handling pkmn-related operations +const pkmnControllers = require("./controllers/pkmnControllers"); -// Route to get a list of items -router.get("/items", itemControllers.browse); +// Route to get a list of pkmns +router.get("/pokemons", pkmnControllers.browse); -// Route to get a specific item by ID -router.get("/items/:id", itemControllers.read); +// Route to get a specific pkmn by ID +router.get("/pokemons/:id", pkmnControllers.read); -// Route to add a new item -router.post("/items", itemControllers.add); +// Route to add a new pkmn +router.post("/types", pkmnControllers.add); /* ************************************************************************* */ diff --git a/frontend/index.html b/frontend/index.html index fa61a372..7d2abe63 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -2,9 +2,13 @@
- + + -Hello Vite + React !
- -
- Edit App.jsx
and save to test HMR updates.
-
- - Learn React - - {" | "} - - Vite Docs - -
-- -
- ); -} diff --git a/frontend/src/components/Footer.jsx b/frontend/src/components/Footer.jsx new file mode 100644 index 00000000..86707c99 --- /dev/null +++ b/frontend/src/components/Footer.jsx @@ -0,0 +1,9 @@ +import React from "react"; + +import "../style/Footer.css"; + +function Footer() { + returnPoképedia v.1
+Poképedia v.1
+Pokepedia v.1
mw-z7*|9y6OSHG zTP^mR{nY&0{_mOuMskS(p72OyPaa!S|{g$Msn#P{7cscq>i$kAaO1-T%42l(ddL?=95sPzdN)Mmx@M- z4#6?m1@!#CF$5?ejW-^P4E7p+K~)zRZelIA?5qAb(k(sSq*!(qKK^874!!R1mfrn0 zKy>M5g}=|XJz>-PnwF$s*0Sv0>ZsCF p4z|vmN ;fV@Z%j_sCi96g&YIO&F^NBhzO4(b z!8L-mX54E}EU}{02_YtJYWkgC-}8JD6j)y7$$XH$XljbLvHfmS f*qhxt6rzCj1IZ~gmqC$lhuPe5Zp27S6MTAuOV;-K>}%zOSl z7%d#b=eR@l{nsFU>oWwOFgXy7;aPd;M1N2 }VhlVdh^4}a<5(-s0SM-;#b-yJ316mbpwYcW=tJ%0GpO*Tou zg7Zt*L_p4m5dMm3CjH;TB&vdrIV%{!e%gAsU!uAhvgXYZ{mtbO-=LSWR@MJHy3z(k z-;jLxcobO=ap=Tkf6*jX{bJb8e*2Ab2aX8tqOFTi7LO#VS- ~#Zi~UfAW*HgsD~G=_}E_)w5pH z@oh#Oh~d|rZu;}uY1c&B2`s!l{eAnj+)>_ATMJ70qF5*YoPvu5gsA#L{&l!K5PQ-e z8s1(z|K3UE_5H1P#H~YC!l#L04EvcwKc-nt+z{|WfX)C5poB4{#<=O~yriWn;hk@t zT0SL4^3YL7(&PMUJ#|HDI&jmJw2k)gZdnzK>=mv@h6OZ}{> NG%t7_x?zy8{&}BEU1_|{< zXaP;*S8^VmRDWxSC-!Mq49G&5{HN)^TsFDifsvmFEI@=W#_yPZ$8L4wS_X#|W&9Pz z1QO*nJnJZfhD{S@iJjpIzxrwCm6b12s}47pOMT{G=fU-tTXnwQZka>gzx4ZBA@%aX zW0D02>G$~iBuxiNLO;2-Z~yFnA8cloe;})(wmuwqPv5y~-xp888+!-fTEJ*}2YvMR z-TvVm_rP!UlM5e ZzWD84(=1O#zU!1C`~mW|F}3Y$r}PNVFSjVUIP?+b pMq7&6VG2JvxUv#NOr2WU z93nns+fI|1i5qM8?qXHLawXGbekY$xrb%Qw%UAd+sD-(6dz<;_ ZT#;e|58_Y5WZwZ5rE*=lz1_T%>RQ6y9t3efk~f7@=`Ry_ za^k}7Wbx;O!`R`vN1)4aUbbOaKu69`149fvL_#&!LMoU1JYw4uNt+#_KALTKry$-d z)zvP~0!DnT0*x}q>ro5q9?i*DOYf%6ouNrD$;l^a&(Bs#_swup>B#2DiFEp%z-yS- zQc>`ifb9|w+_3|0e!t!|jMmgQL=<`)Mg_TK<@dC`sy_53!Xyl16TXk8L)0vmcyq#r zgRfTOq5yD !}jK_q0Q^(UInQY zucOM~$>#+-qj@;eb#|msz%SxsNB*r!55h4ICYK;8>?^`^Q)F5CCOVZCgA}tSod2CE z+xbQw37jh+{virAREk~oi XB+O&YQ~=fIy_7@8LLU;oPt z9^hpJbS^u?(Qm?Yk;bua7U-;Fb6>Y10DLs8Ik!f6yJmN-W*b?(+gTxEPz$dF!? ob&u!orQy@x4M#R1m|3xHYRI_9RB*r3?feQTb`p2C$c`CJ8)FtoR zFbC8CMAzeZthRrwfo!{>*1lXkv;2xLr)~8O7>D54uF<3~5jPIXK4?Z6H|ef>FbG4> zuO2bdH=M?n5uZHP7L#IjDB#E|=UOl4p@$CCH*0FNIR9yNi7O;81SyOGFGAc00|R2K zHR*tDidM!yO?UGEMTb@{|7IK#>Xv+ymxV>R{%L<17nXWbdq=f|m#>nczAWcYZ5gut zC>LNnCyF$#xi$i{u BNj%jnXIUtezQ@~D2hyYf%xoXopZ-X8M$&I|vZtMRs5xgF~#U7PgStv?{1CU%#< z`;&h!as$LO&x@spO~|08=phuE? JGSR$y{qfbyA6i{9H5Eo*Qs?6X~YlEB@by2 z_X)-WTAIV84E ppor_om8a-AKKV;)L#F;-9r8&V-J*3WnyKG|O?-==?vBbY)UGcQInwzcWSh4Ix zfBaBi{LRG3#)#v_n8(S)r;Q16f-pMOVE7-nM`rjs_N$2DhfPA87KX9;?yn678Z z_zApanM6_G_rD_tsPW{93EG-j#_L&OqIoj >eQeuH&5lzrdu >Td>2j!3TWkEXZvx^> zV2HqyahZ&85hFLRE4LhGx=iXY-a3J&mb?^IfKV%(iDz7Oxn50^TWbwyXzd2GYgY5l zkTG&=wSp_8{tcy0tC t(Gad-2Tc2lB)NxWvk_2v&7 zC1)GW3F95{OO=5e-;!66L?31f#ybMW+qyvw^rk)*$T9t}BuM)4;if)%^K^2vePeU? z;bxTi=D{R`KnmV|AZ@zB*3XAT5|dj5?4-Hz>%ivL()AYX)%J4WM#%pYwBe$yy8s#B z4gCKUB$@aNynAs}k$vGY6wxm@VxFTE&CBcmkD!eM{`^G*lJrTX$*8DR7?Qfbo>r}? zbTUa9Wu>qxdJmeV5R5!CWKAB*Q%wsM7Ztfb{)W=a8k-yvim0T`hk1_Pv% b+(X=FGrG6uH;;Px;(N)-)eFe;h4T zm bkjE5(@3J>YYtVby<5V z3}cQ9etDzyPX7A5FN6N#d9PK3#L=wf143GO=A5Sxw$Rk#R}W@@kWGQ-c{r*1%C>7+ zOksw)X#}acs O~=3HF}#ZoT8J*BHrVv0kg|QpdN@|_G(rRfw5(? z1v$#CyoeW`D&J2Pm-b<|_}H*O=_g0!p+Lh~?ExZdN)A87s)_QlBVULj-bQSK+z^ +mbJ(j0+M0&1jB%E&zqf^J$Hb3V9~ ziMLOyPjPBQ5da{={E(IK*O_YvWg$$J#o;7WHVjC5*o~f|6DV4kfh5)C+i)4OLhh7W zTp?`B!%Fe(jfSZB59=#xk6% gA zs^|=tjw^Mg`{i+FO<9j|KwwIv%feMAY|G0AOZm^SW3g1nsajs#kQRYS89g!x{I*Sa ze?;7ackhvYrwtGbb80wKm}Y%r@zw9$xJ^NUkJUkn=OK7x`~N|f+9)Bi+^al$?2%tS z1SW5BE;hnMNF)yDMQv2Xzq?0x&$E5(xc;FKJK(OK0YTP=N&eBWZ9L!-{4s3-y>>_1 zyk%@&fxL}9jyLIwR$O>|mv0Hw=Kz}Uh$e0vA#jy$VZ14oU*ly%hm{FlYu5B1+V>Jk z7)4j! C-sTq|_;sED(40FUG zc&I|4aBm%7Pnd`LjWcHaUheMcot|so^RVTnXM4_30>BC dwZJXk)0H zXcS(t3T9+3nDOh-j2mVGshsUti3+uG6=K)am9AH}^+(3toXN5o{GO}K+2F$U`B>;7 z!257U6Rq$jxl%La-`vX0B*NM~?`EKsyk+$v8x?8vl~|$F?CN+V7g{{!$p{m(`5+ER z$?-qIk{{ct1|I9=)_QO#Af$W0+RYa)i`xmB*$uHnL?XI2Ebou=Hc7K3;~zgzz1r}d zAh=A2e#6`UL#40k7nGi16JMh6$mmIWW_pFzBo~K{ bFt!I@kiZ9_EVip6jfd(2n@Opi0w@)qDXiT`3E1N_gZ-S zC!JqyYiwmmG&7g8 v9^p?v{+O*kNF+KFaRL4ruBiysrWB6^JUZ|w%FU}scSnL zwbY75oZaFdPbIw3On?Q|6p6e))`8+lgc1p}znC=|PrJ8R!xw!jlr_Gw*tb-h{&D{n zyG!V!P4hC!4}vzh6HNT)vq+`@PWpoEC;LKoIu4cU?9 KDSW4-WAbpAqGi9=rHX6LIrr4v>!{muStbg6rn_Wt;Q5EZ_)ahzG!{oxd158qIE zl2kIBaOAJ_chimSvYRv0DS&yS53XH^z(3+wlBhC!edPgr{W0$e!NfMjpA{^ZR$UUK ziH_SR30!+;!}H>D`D{%R20N@H0@wDKjemD=1l5JT9p5d_V1YJwyhLq|&eyM9j*@S? z;IY>~qlE9^1Z|08`J*vfTT1wVESaj=EyuwRxxYt|BMo@!=hn}tjHaS{zd63GT1*e1 z1%#KrXZMT^U%!%qy_j^}B6d1_;J-HJZTiD8P>NEOkR$L5M^oDLUkuHF&V0eY=4wv< zc{a0_SzcbxY!XZu%|!NGrnM)EYx{#B%y(%-NJO~gq>C`!2=DnDMHJWMye`3?(GAKU znQ4L!kGG6EIm;CgaCSPliT9f2XS)Q$561+6!g~HEug3d=tMI+CRT?xAuKtFhSuvkD z>priHV6;*kmzj-AtkF9=JgwL_76+uU&4Er6nD1YwPlK?LJAvnqxbruEX|dveO9-XS z?%cY4W9yAwuQ0W=?p~zgxjk{U^p*K#&PcPBj~)hwd6kA7x>mlUBpCD+_09wuy6G`V zY5EfG{$xXep#z~<_=Q?@drOq&yS^3nTZjz Q(cE^|w>@nKQ5Y3M|a`e`{$hzMT0|E%OgFroL=hC4%yX zC4LgJQ<%G%`q7y8VPIFNd#7Z|>ot8SsGrn@YSr@H{3lhd%~icgU+Aj{^ 2C V%091}vj5=L7N&XffkMVeofLUxC&SJS=TwYlTB zhjLu--tqvF3Br!Nt)Ci%(O!U((SR5LrD_MDKqR4X 9~+(#XVA6 ZAiGq4Yh_+ul5XLT{kUwL%WuaPk9daAMC-K&2~sCO zvCrX!&~<~zv*H9i!( iq^ kC|K%dK9a^TGWO66 ^Byu*;@WO*W578`P0k$RPtpta(6;<7lReAtl{WqFYCf&uw)1?Nk%)Ts*s^ zH?+~vnA~SHF0C|a@jQ7=6$ueB+2+}4@<wcHzo5*$*kD;#Ji03s&57M9?U7Mqx+( zI3oA4VeWKA!uhIJ6%Pp3M?a&@TQv;X=m37xignWDbadpwbW_&b+;d`H<^5J8&`vG3 zO}^m8>DZEKjFN@TL4S(^v5Eo~>AZ-Tkae2O!aZA_tH_iiimAv%r;frtL>5JI&LC}& ze?&ft<@H3xTMGNvlSdh0A9L$}XRt^YapopNE6L NUg$GK zZh$@TdaW!<&7dwOJDjh`5?KfzO`utHT;NPm$xd|lA# wI-6{_l!6 ze3dN77z9viZcuC~orfdbgU9YTjg=?zrQi1@n>VT=q$~UEQxTq0v7|)ihpc|bSIuD$ z7Slz-4a;RE0jA^-xKy0o?Z6Cp#Ug2yfO?G~DJ88TC9mY$%-kvf4a%~be)NHlM`EKkwK2#AnU9}Fu^rmIQnB!5XqnQlb68e1XYgU_T`PmtGm z+}X$xTkmHSa%;SiCJ$gXudTYVkBqYgtE2(waW%a|;k}N`1*0k!eo9xq#_P@+KpOx~ zNR<^JOy@OQ$R=U``lH-vQU4HfVLe14h?D}QWk9O9WDA)%XrX4YM !Ez7MYux+Exc4o8 _LXYrn#;=G=u%CC-3iR4z&9Z zsczJ;KtMv5J}248N1B7qCWBGN!%_4Np4Cl;-NVe7U~>UbuKNx`c<3HOpP1i3IPQpZ zV@ Ryld@pS-=P%8;Y`P26I83|#9%=FAXpCuZ}f|yMiAOV5heo^n1Q$eat;7w zMGq&VMjH)AGX!wYtx@ZPxz)q|6T{5s i_+!92}r|B1=1_(5iKaQE*x-8Mj12*6E)gHR)4e`nAIz= z72R@gT$C+{+eaqg5~EubNc}^ zh_eMDr=_3XD?jc8N0|m+lr8D?fL}~Fp$^M|3CqMTtJwvs*^|qffvcfstH?9JhH*Z+ zU?s*hIF@K0-zAuSW{q9}kO`DO0zt3B)mFi^teP2ugw;o9s~u-^MNTVE64t)!Zwv)) z3_e^N48(W6=0eYm |_$>6m+N;5kQLOZ{xciH84 zMND=$wa96D@gV PAKbrj8GZXswgsESo8}wB8X!(lC z`ro*7(1FkAPfkGxbwmel@&_+NKWdmC)I9_uoDZWJHxFt}2|R%<3*tkV(5KLU };+PWC|MP|k0s@)<5#R-Q{BO3>_ 7QSlSq+|#am^$H<`!kFjtMXCJN6~2&=SgY6#U#k+k__LKhOD z^@=+}y?`%yNSR9A(@!=8gktJgtOI`ffxJ3NDJ$BhRo^tTOV!ye&!z82#ev?YhY@e? z)Fm=X|BJ@Dq+6@L;$7vFZ~r8ymqN)CeQDuc7snX*`*^UcqluXDmbE3%# OVUh>lNKCF6Svm%=UEVI=)DbinNFQ)T8NTE5=+40VD+EY@6 -z}B~#F0Sjeo^^17zM&IQYZ0mi8J zgssm 263yD4o8OuJJEXnpvR9ts?s;RE*&^`?i<64+Q$_R@86D-9CQ zXO)>_Nvj`QDn6&7p2MFx`o$3?Z4?7ZbZE`l%hg?5vGC{Y#e@b5lwVqr)l?+k%L!Dx zgBNAHCTW$&!@-9O& G|(JUOQ0uLH(@C^hJ_u?O^8*&!K6akpG z)wRgbsw(N5&cosiNc&ES&?U=GI3-OAGr~g^9fB0l#oTkhg^GO;RoW|6QCS^2!v|lG z=BsI`RPQ>jOwhBl^Y7v_1XFZPNvrW*6ahRTW6Hj^m9s_~XWc)RWL_36@2)%L1JC$O z+w&8 @MVBPpAgd;`)OpoW C>$#YTJ1DL$0U8&*XTa{%R_v8mYTp>xzYu;8~Tb%^!0g24KzZ~Z+i-EyphZ#2fZ z!>l^w-;9unxWG}cg~VpK$2&k`p=(~_` Gv($5LIZnYu zw#2XyIJb-VI_>#$9}V-RkvpB=C4>WM70giVs`qE#lUNUQz5eHw{jSuff^8{}5p`pU z0~A>l+=#HGmwj2-EkshJsQ7z)O>{q{rYpWk{tk+9M1IyZ;hE_u7Um02WkS}l*^#rN zm{|HC&1aSrSO)Upg9p NZ6`W^%UPBA6hYXZO-Oxe{?5cZ9JbeW9 zu8?$bgI*5h;i(U#N&XW6Pn2(nwvkBs6M>H`%ggt8pDCoo>=%m5tfZ5$afGK>?m;?5(}=2#}cum-rQEb_ax78 z0ZYos9pVrIAbU29@gDvj_O5IyAQ60zWI7)8>YYy)PJe+=M^8TYqzJyyWq44Jn30eN zvhXq#@Q*2{B9J=iN1A01*!kwOoju-C_SiC6WKa3^lI6yU?~#y*jypoq6Yy0l@SXq> znu*^lj`aoy!@5qdMv 5{2(?B*x&hLY)gp| zv~U4Nqu=6D =qIRi8$jSB3@=^of)yPqenz1*a*-&U#m*c!rwll0&zLS!b zU>$lfwplf{+{!#C=%o}2MxyoslFM4be*R5@ LAzZ#D0y}-eejiC{!CHOm^YByT@Jr+9)V(<25^$1%;c(N)V z`R_3U;%@;>4nuHrg+~P1C+I+#HPK-J7K88V{?z; fGs(eZQyFM=%79y=KTc)6`kUM=+rr!S5^ z&a<0>7*=AmwTM{GbT`$PM1)bAIf=|T*(d%2?-g~*l`s5kg^Eq9 uU=`U5Bx-61}$-Zv#IS^GQ@MS>MTTi{D=|RoFC3S)j|US+a>*nzMR_ zbwSXDU ;;0z33@=x01AEK^0I{vvq5*0=#{ukcL+22J4X9jEb!~9^x-6~ zD4Po+A0)m^wJ}I&>HgXwQgEdA?(YEYR`q)ldFrI#h)n=3HR_bScYWMduXX!0m|LhL zmYH$geW@MEhy9Ufc6y4mQJB^cwBt(4S$60S!G{P|*WH(#mFKiDj77*L{keXcdKJ5% zk?@lC)cajpt$5w=`nNmmSBozePnFrVHB0lbd!w*`DJ2#++T@Mzucn17n-cffZf~}V zg~*0~tR5L#BC-=B+QB fZZbH|lYsV?(Qr>-~Sj0d<=uu`GEM1@5d--+)Ny57x zoqssNXU|8GnID$^gZzktzaxsTpATF-`}m3K%?<3(IiQohA)eXl-=6p72ApHGl;D;> zO5}?-uq}JuR@eDiiNy8%fCk2F9R#rzmH^$e7lXd&LuSh`IM|UuMQI@lY>o; ZT>PNVRDj2juN 5g+vJiOwKNi`;o21xg?^p_CugGUHvYt8CM{Ob1* zH3(eR4~blX6 TiS8YIh*ttStA@Awgtw`NJ4>pmem9@-fV{d4N ?hU>lyOA_?vo#K6qKm%5nx z%+U9e@zmQ S@MY}SO zRDwe@U~2%hz!N1pG6=EYM_aHTpUkR1^t4@((gk99KpG5>ZcqV7ZIhT00CA&bq<$() zJ5}^Ny(uh}XEkXhOm59b6fO+5w`Yjs)*-p1eWbz2NIev|jM1ivC6Y`Jp$Q4nPf8q$ zk9m&wVK~V*ChNY3TM$C+ZH$~|YXTVyAX*U@c@&9~0*HAN$yU=|t%TB4WZLB9(eb|g zwU?O{lTLYPIDHuFWSixill90hx5zi2kQch=o!lOsUAGz;{W~%yCXI0Bp-|Rc3#oWD zw@iQT9LpP(94EUR n&Qj5b6^^imS7(NA2<_gE yC?=M7-{+<)j~FGW^cVG%Cp+GZx2|4Iqp2kKZsKM zszKSd^*(*w?g$77YlApC6ALn!H^&h+lB~8C+1F%@H@En8bayr4Ym|88)^m{7lBSd} zDRkOubSn9DZ$-CG@FzZy1l4VYA?HoiYweP>3W8Z(uIoKr{vA0t#`U>>x-xTJ@Ud;^ z5Yl1)?qd4H&wqN)|Mb$$JcOVDy5t7p-{3qyX5&xKKL?6lsowmPMtlX(-@k+}gmh=5 z_vr2G4>CAWi_q4%9k3*yAq|Ab}tJ&d0rQDCAk_NeyOM5RW2&z(_F z!~~#pe2-9g|I48nOnwh@Zzn43m)YpQ`?m`p1t7ZcUOSMAV_~e@pgJm%)x1vaZ}Km? zycPdp<*SCcs#X^MF8i)`lJSx7^TC^w_q#GfR+=E<#uykFCqrY0)EI`{WI<1p;q=qw zOwF!l+{*|X8@h($WZs3+j=<7@E{Bm^!ai)r$a5BGgDz<@!!UoqsGG@n_TSDr e?_4>Gb0S(w!00RRq{^zWi_K!K?NldR~j)$U0K?dH{q zVSD4|ZH9?L*$HNsse}A*h(~`^900GM*jWcreA6g(AhtRlKVZm?fubQ`5*MH~$UttY zTOo2Y5Yw4`lPUYSDO3%3Xad|8s65>Of1LJHnB!Xd)7B`!wwuNQH44Z<*yLt7h{oWI z6Q49EP(5=8)gbXUAjH^DKQl#kb2e3^K0BE|9g9o!oCtQ_!#IQ?tSoZ`*C4yg6mCC( zK+l3^!j$m!0umPy3okw~#dYci&rYX4$IsI^P0L On+3_*7xQj165HxE3e3*l4=k_;7XN;bPPEh8N?9Hm7y3hk#hY z`sZ$t-UYuu5RJYuCn&1{Mu|S`Kitfb`*4`Bif_KITm3=odXt`Ism_GM%Y1XzbQ9OH zhTKVgydkwt%3`f2IIlFP=Wj#s?>~LLmOnz*Wf9))nIpns{fvXOoI)8&7^4@84Fo z(>6k$6qlai7C1nH)+si(uCKSKop%I!cZ7nbuva_e&k0x)cW*!2p_|&3`n)TvwJj{P z$CrW!livk;caKfi8Jzd|H+SVW|6?l!Sobk!TS|p{g0(v`o4CYm2M@i(jNa2`qQLav z89)1EJ+)^l6#9tilMd@g%b-ujn;&&$57?up)PPTpQ&i5cKDlch=;nW7haZMGANW4w z@Fre4U}HF35)7qBA0{wuG1udnB_2duafL*A?fYsY!TJktf8YYu1Cr&hKd~FiNY3R`?keO#i_jR zMUGguzNuF-PgC L(Vm@Vc z7dEj|_~OgucW-Y+*>*c-mP<-Snv+pWJZC8@0OB@ybihbPtUR*i^HGq%j1b>zAxBLv zL?Qo0(ua#}Lbh^Gsu-J+=%pCW<2ySq*}@lfIB2aY3Ty-{wO@E`DZ*Lfc#E=MSSnUV zXNK+d02njM?WgRD904qf&NM6{%yw+4(M8G1UPqi+M!Wj?#B2tan{{jr>oqrF`uL? ;{Ow_9Yp4 zAr4>h0QF^Mg`qRNNbBFLA2TD!ylu56<$M7I9?Q+SEk4tW(bpwen-#oe#p=Jx%8S3* zXBxh8^E-~I=mkRKQzUa%K{Vd>;ah;^BDBQwICr-+-;dAUa66I^0_?&FD;vuEmU9~? ztm-#Gl%}= JAmW&0P zN0>?cnETcGKiX3)Xn_{)faLktr(^|1DR$*5qQYQ|Be4LO_RQa@l@CeiX2^E2AqJ;0 zPlmwnhy4|K4HW(@fb%!0TRe+W0Kz~zO$`7P+vse7s~nCVwcW(#^-WupX}8W;5ER^= z*-e$Ltbk{&aKosDRkrm|szgu}Qt~Djy9l7(H1tZHFu1KMl-0D)*yo+KPjd$QH>T{p zFz1Sjp&P`q>U0#oUKobetJziy%z zslQkt={~hR6kqR >`hOr~Kk{SQT{V-_2DPctZI#n&b5KT4r{ii=hy-Gp^`&5w64I`5;g@S@BQv zB?i>ggh(&!lm@{EC^%;ERJ$< cer7yxg(rk->%jC0?NRM0Mz&~h#-ySZ3cWK~0}wjuhpWf3E#tvdCS z*$9Dh44)K%s=k&sbkLuIjkjJ^Id?LgU7U++n0LZ0H7!3UpF{Mc?E|V$iLvM6qr8Sd zf1EJjb2ff}=OlR}h!}YSOoxRMyp!tlfP63Hthc;JZLby9IGZrSuzN v#_C*$znL=2r-(EwAR6ks0%6saYor`}o^xvp(|k zMY Wh_q6s4jGM~b{1<77Y5bNmJlAL$gK zeGrXrm3ypjGe_Xy)gLL>?t5Gj6;E^5S}MIwdAP{!bqY2c%Dz We8Hp3jG&n~EfAlp{h|d4H7?Z-1*u zXE=~7>s(#CnfsL}+H-6M{xN)=*;p^9xCP4k87&McKz|m|KtuuK@>ky*b9$ {=&zsL8{~p${cJqvGsm(ARf)gHXT Jg+z#*)P9m z#g>G;rzbwlDsSUalygJzWH*@zFXssj_y@IjZ7I{~=E|K#6S|D$KWG}VgvkqL%3Whv zbOgN1ZhKaGf7reLG~2dmihuzMq&|a%x%#)o-@FtCNp&=rEkCt17fjgnwfb?=()^;O zihycyug}Q;5 xzn9yGU=&FEssZE8O}T|^gg_c z{ATdhAmn)%@DO$Qi)z~F< 0EX|3hI`L;hl$0_UMVnar%at80c zTaApl$y6A;4s@-*GJN&96o6TuyV5zX!SYKlsuPS)qQiVYrqp^Vi3l0_x^+jp9O<&g zV}bm*zaR$1k@R@n(IzWzmp`jH=;lmQ{Nyu)VHhyn7KKvKC~iuA;pu@+7(f9mZWHLw zC1~PfZ*K;GiCWP-TgWY?OzxP2pe^Zsfvwtb!SuqfmPZ=eAfA`WCl^}%)ttod&0BdH zIx01wb+Vf~v*Ahd?Y~Qc4Cmp>*episuJ>tL?!6bLuwi*GBX8#~prqG=FI8Z+aqkB+ z8Q)n-^8mytlXwov`W{PR2b{&_d&=;$^Os8s2lEeq6cPl^#?>0%V|;z)7{~Z!|ApL5 zL!OX%z60qmqkw-Ob>j3`R5reMsC55ys+Or+n#?jk=)D*&@=NlU6=uPD*IxvPx&$@1 z29Z;|aJhK-oxty%{`2-Q8OlP43}wLOfwOJ8(-490h>BM_wf~`tgY2+Dw4RUrEa3c& zhe((bb?9cL7aSKUBO?*kD;@wJ2+Y(87$%_JDGLa&3DTwxhtY)3aLcw1>+xo}@vpeK zAL#tNW4huE;S&zQB{RCw!HHQRT=gN>!(lG2)M1f9jVj@N{YpwavU6GC_T{0ScdR@1 zv=$^nxP`;khkfp-22d1+DDFl0X7LaJ{ Bn-A`>6FM~NTf z9UdrpsFC2U;8hltdl-@5&V$m%gzI4jd?L#S?-*y|xEKJ6Yu}y6&-~ZE0~K3CWtEgZ z4`@E~^y|=xpz;Yul*DyqhvmY3_wTt^P{a@GVYIW9KKn%4DEU-B1!idyCTx>d28 O_3bjPr_8&YX|CIfytKNkrKJqS{a+UFZXz*xCUlPE`?bJ06OSXBbWS zNh6{- sk22vyM=7DY)ZMWY{y5-xgB z7JJ%`6vhrfxdR|KPoEx%$E^WnjY*)1lHop2x;6;$QcY%D4ul`Y0WQ?_RPm^sG^rdV zVg!^7p=xuK_!+K>#2VoN2`auxu)-A8oOJr%@mewdG!ZH~@G#IWqOUCVDl1CpccAd^ zIBDg0lA~l|M2d7rrhiykGA|S_68ENns}!IkmX&`LuUe5lVGBBxxULX{nO!7ZsKju* z2{t-P70yXM*Ry(_lO}=9e!;6~RiR{sko9*DPr8@nx|-8Bn)4cwtBTKiZIH_qqC)1A z`oD;J>$j%<$N&GF0i$trrzqVjjRU1a6qUvyNQ<#+TO|ZlMku}vQ~y-9y{bdO?#)w{N^tvLh?MrYCnYtl!#o+ zh8ku@J7(f#QfV7x&!HOotvPR6a~Krz^v`p~v=G!MdPYO=rM)<-Us(wIu*$NOPGq(l z?_&sUbgVbFFC9zagq4>E7m2ex9rHd9=Zv=$Fro6e<1H3s(M(V1IR9jc^u!=Q&kODB z;Pb@3(0p`{wY=MdYm3 qu(L06m-d5ll1E3*P91&T{R+d0CS*m?rnlu9M zv8Q|Dkh|bn#$OvXQ--ctESq;Edqm+3i%;T`#0>gW7XHbv_>~$WjF~J=;DS|s*pGJj zlN0Ae2Oh+wn$g9aR%y58Y7Q29MwXxxY{GZ*M@G_*+A80qheG1ZF{V{Sl2zeOH6IrW zw9_%d;hL++!c%fjprVjNw%X=nF5V}bP-?`Qz0jCUA9l+7tWfUcl=JpH`phhjC90Ov ztx9Y0f#7D Li@fQs zdCjku`VTsY$eTEgqnP!!jCM2J-{CSm1+%0nU|B{hc@#aJQEA&=YpL5*9r>6T*2Li! zcjgmEDOqKGQJF9A)byuCoxPRB9GBeFKro;n6^N)RXsI?q>GtLT^EheBn8 cR;GR2#NE0WZ>4?hMKW1Eb+>Wk(5` zt&v>5S-VWFnu_g>x~;nH4VjVc$TnPGIjmc^$@eO=<-Rv&Y#$8Q?c&}LB)HZ>$~*p; zVam_CD6s$^v|UrNbC$9>h2SIeO=CbbQ&x~k5;Dj57N}nGCucmVOY$f7JZ?8D62q3y z?U4+XHD6hQU%uV^yzO=7?a8WiJCW^%qd^<9v{XHKK@JQ-N#=eIK1&9UDRbX0_U=I2 zXB68xv$`d`JNf)duGkwpoJnQCdQn1IFsmGl*C!{~G;tmOXK{07ybikf_MPjtbBp%2 zI5*$50K}bpVeu`zFpQ1T0Lw`4=geddEchee;$ qg+uo;4)!5!n zyxLAnVAeh<4p0)fv6Zf{tbw;z=>sktgH8@_e?9N>ita~N_DhiC?;a1De}wT)4u@C_ z@JfPtq9dQ32SOA^9DJ$>O9T(2wXE+G%Cdk 1 zu)yQtyp`d6rICWHF?v)n?_@z4+4y8-$2ZFH6#4$9=u!TJ(N;Z>6VAHsGCW6)?>Hh! zC)m^`hYu?!%2^;B8xtpE1oWz>V!!KWM ^6M0+~0B0 zpZRy X1I_iwh%-Rsv(w2I01J2(-*5t4xAINmXrG9GY|YpBKcqh zyBW-I;W~b?>v9<{wiKejkmtV?Tm=keuZ(bt*neJnIXhRUzihw> Qdd$QGM#s^uOTzOIT~?a+dPiZ~yhPDqxqB;3HfA zqbzZ-y5vSB2Uq~QCtwoiI T&*c`Q z%Fg|O9VxC+or(3mPSC(=+n|eBablYp1hr4L)hE|Y19mJ7Hg&(ufWRjM Ftt&pfQdZ{$*EBeD5-Q$2wr|dG(IB0U-+m9J@Zb7;L@zGNX>&332^|bpE&N zGqD%Fwog3yQ8%6#ZN>1EX4b!JFKTT+ 7*Xyj5$o`I&7=nD6c-u|8h9&dW`-b zwss2;wF5~0m%lmwFMs1wa^s2U3!`!5Fx0Be? Vzl4vDQ-u*mwgX#+)3J#x=^Os-n7n{(9^=L*3UG^iwh(qN-8Omy zNm~q+kb{)8fM9T;g6!DpC =l@5q9?F*)iVj4%@+I}x?HHMG3eibZfA~jk}8&2{d zi}hb5jip@G*Lo+Tt1p~>4YACCT7W;NujkY1X7xw#Z_k?@)_b2lp0B=?^QxZ>E4kwQ z+e;dn$mgXYxwEnlD(cNdjR7p~n Ckt@R;-C=pV3#0~>Gu zoS#DI)+2a$-}RN<=tb$0Jm=A%V(BG@&}H%WI`se2 $(d>pWYCri02_y_Wy> zcq5EViiZs3*MWg#5@ezIkuoD^TZwvI`+bR0sk_et96RyW2C3hWlf3*4@hD Y`&$`=3Cw+LAX8g$;w7VinzQ^9 zTmhQYO&*0o=t%Y@_*b9VCkcA636k-lC?FI-{E}l?FxS$v6yyAPNE|8rN)iRq!%l8M zh-aF)>9l~uva+IBHc^U#94FCo^quq_uk%h6`jK4cl2s-2afK==-A0D 9~|qm1KQy`xNRVn12!Bw)SXh z?X6bhUlmCJgamWch44qY1^48XXNg035b W#NfRnNV8{XUGC6i4n zDSa;?(Dh81%Gr*&tMAu?F5kno!S K&d=6&yuy2w@y^U0*eV5B(*Z)l@@m>@rxybO*(Om$96aX( z0`g;GR6wOSR*Qe1ZTboSqp?07=xsq|@F$fuDUmAK)eUAm1EKV}b&roO&fz^IpvL#L z4dzrD=wW618fg^49Zt}GiO+on5gk|zF @wb L&m~WVGP(J*h^D2hR7Pss|H(%LG20M-_l84 z9@p8QIN&J-lhQ|RKkbY6q8yu~qoqtx01UX&<(`{L74j&!Ip}EM)%J$O_r8NXxx&QT zPjyJ)aEJS~ChA#PkD`>#)_A` m7> zds8o#W|0144~d2IA3lBk(^*mwfY5F95%Z%US2Ccu_L6QI+f31ew`GqD{>-2sJxaXY zFC_Hpa4bsLHvZXPAwzrMW hW!Zg!HdExtbd9NqmNKdH z(1rhJXUelgVpt~1T>4iGW|sejz3%ex71z%~kyRJ_R~bg+I`Jf23S>mYB2WF;P(X^b zFhm%?px@ijbo)uM#}gjQrKZPq?W@kj^12VBV#OhMDoY-GBiEQtWll&j6N4zkt5tA$ z6eSl`OP{kCA1=+eWz34%w~nrV_(YZgk;gkkEswA;-056YL+NoIEm*ZN z({1^-sfas4{C6Z&YyhGiz80e7#|I(5Mt5!=%?}t1xQA5@ZI{4}@Y{?P-qe*KaZp(q zbFpMhf!-%+S=09AU&q`Ju OEapQ@mo6TKrbz0VEXCU-sNk#@s1RG9Z49w z?5oG4H@kY=J6C}Jppe*Dk6eLHbLp=wBh`8EysySXTN!isYdjSg5hXjF%(khM;|eS( zrxscgHBB7)gUD49%~RC;F O_*cX*o zjFVlz-AELO0wX&9EM>>u_KrDzsf_tE#-{QsH&1z2n7alN0K$3HIf(WeFLDL~PUqW> zU)-8EpT`V%8Pt+}3)jtpUR@2`sclpOTzFaLdDedwjf#D*{$2!O*{8CF45OTb%-q7L zL ?PaZnZw2ewPG0;SIxC5+8eC%!(NJ+ Xm 3TCBD#5*qyBx@!y{2a7C|n{pu;uI}g^(JRZ7h_08gs*Z2pOy-7^lUXk6~7WTB$ zg%8ND H1_M*#bx1yJ@wBwR=&&IR(u8B0SDf9e?AEN7_grryXL;K z9wB}g;`h@lpjoqy8F>@$ePryLv&R%F;3FOHe+_x}XY-4t->yW4_9<$9+g`7zO1y3} zfuqKtFe2a`Gcv>L{vk8d;tXq(y>boT^L7ERYY2D5{dY?@ZSOzzSbXig`P6$DW8>qc z{`Kd(QBvQ1uSX=|_nk=JQaJd!hWX#wP-4;yf*6~9n{z)%ps(6 NXA V8Nq6VYl(Se6Oj-+8oEsb7$ZQaUNhMljSM zEZjaE<+Kp!`jA J(NEHRUOXX?cpwoW#EXw39QsH${FR2h@`v=+SwbC3Ame*}b%SiX3jxhxQlva# zi~=Fj2ta24w$Z*X>tiCTAK)SjaMlvXR~E-7PXJEieI2~>1cR*v75c9SN}4L=5z*Pn z`LY_uR$VOw8q*>Y&rlQeaTY&gzl0~e(F(H)dVY`su;JqVEF_-~CExH4OPO*&Lm&EW z>XFE!#${vs`oaen0u}ip>Ky<^(}W4FWR3$Rs|KBGSl}Q8;EpF`3m6YmjA42l1;Y99 zaH9YHU`e4+;EchbBxSoaJZsRKMjJW)@PW!=8Wa|1tDS1$p?Xg~IqIp9t|`Vt2tz3e zW-cbXI@%KnMRvVS5hD*|1k%b%BXtVHqlW@q$beQ&80|q)yeUz_IlyF^U}2lkwU~L$ zEriYx$dbp@*GWNfarC$>gI1trA?&f860d4xiIBp(Q--}T&l{L @p%O8CkQ^023njO&KUOr*bJocg36*5S9V3 z#cmB{hq3zC3S}1C5KF`2u0>`swo1wRg)Z?)a1CG%-X#PYXu zQRx}5u fJBj7#LqqUB{z*)mB0z!M9DZD0#@%7>gx=-kSg4$JMz%gaYfe>)a3(bEO8 zFeV>*6q7OE8m=(%Nqfec8Hz6 cFNt=CLIT%^VZUa7(E*@=-t5N`d2q*qhs5#Zb zJUWQ@x0t)YMz=)4$YWiy=9Ko>C(W1w=*cL8f?z>;b^Ui7)U9$*K9>?@;bxj!^QZh* zTkTY2oQ6-zf>U<#ABKmU9)=)u G)FPF>d)_kC7QHjb^ zU;(lnLDh?7d)-6=o9EaLxCryRR#YU5;8qlxLl^7133^%_2~|7oHOiI%k+$CoEgX>+ z5Y&GP{qfe82l8OWXjU2F0hEkx6%8-})-}`S&2pR!>Y?m?NP%Jv7dEb6q$OIhhT`M~ zF)oV<)l#*btbg7yR#xe|&ybSY=}t-4*8VEJy*2v^-E0msV{!+2b=z!3IuA1A1}oy| z2~61|V4|Y<&^+%$W)lZ0k?y2s!MA;RwDaOq=UaBxXF^?g#YP%MOuu;tg+=#(V-`J6 z3dv;Nsc!cV_V&?qA8L4Oa%ATfCF5#EYX&=O4_g;$G%YN?i>fkRv@)Ft4+3yLVz)Q~ zfXC?9$Fb4z)1>|1MGwHy%SYAKV+L6BG|JG5i0NT? 2LC0B(RXBx4ukS5rC%$$ z39ZwWwoYYH9Gv65moA88uQYdKsHKDSM-9AbeeZmn?iyWA$Sb`bJtf8hj-y$xIe;=v zKI-@emA~D*9C*avlmm?cA6 m(D9xZHd@Ou+@LhvB-+o09b|FvQ0*OjM@3gC zI>fn=-6z^ha*`5pZ=lbKnVNSLr!+drF+4E_^1}OXTl8JB03?&3`s@QmExwK8z8uk! z96hk_xKmXRc$zUrvD~WR$2@*KHpMY|$6}lb@gdf?`?_2A9ld_;lMh!^?JO7L2)>cL z _122wm^vETB8NX@N@TGOvH08 z_WzwK5uGp7o4$QHVOBR!V>m-ts aSJyOJ6SBsUMl5W>8%3T5K9zpD?|EIvExe)jg!=3%Mm}Mye_3E+DXiT zs5Z<0BD=!um9?wO)eX)ywG>39@?#F-)jDcvTF&WPFIN|{VawyIgdXHi%XJV7oDzaR z!?j)iH4m{>o;S<4$BA1n*Pw*t4Yqb3v;J#* +X;VQxy3tV)95(eA1J4y5q+hFLnyemS Yp}5#O_+`DA0TVVA?`fFqHDPrFo)zx%S6Cbsuld?S== zFYSRopa 75>)EcW z^MZ%r(}%YIcJ2ghm#l5ZTOH*D9OYOY)qVMYj2j_idjmiSqnrPKHT3^wY&VtS`N@Mr zssCTb#-}vdYlx+wRSR{Ie8fLYhVE6G8LBJNjpiVV$kI;ak4mC-n;T=z3(VuEe@4OS zBc;s}f7AO8g11gBgvuakLNr~*FbaFW-cFfEW@o&N88|!1`>zNpKJriKqIZxAU_b`M zoZN T7nDZK5bDqkGV{ELMrW2{L}s&*b>Z=e;G=nA;WGAyLeIAtlP~3n$zZ zJa )=9j$&|0v4A~b|;DCZiBq~LOp zWCA=8q$Eb<5t9LK8Kyj4lX+wk;n?k1g-?Qk*W|Y3Hr$8Aj8n;Oh9(n7G7!vL08~#4 z?n(~BqHXqz<~L(hJr8!{l>VgI#E>#IZ#@1X vX=6sK6pjzMBwP+S5n@^!o#NsWGEy zS+PHi1zQeE>P?~vde19303 ?#at6=bgbJ|Y<9`@M$hox+B%jMNPYyD)f#@F1;< zoSlz?&YkITGpYFc0m&1NJi-PoTiv9>;U8(dW(fd+@)V-bOAZD8zelzxRzzwI6f3tE z3#J%**pQ}IRrPZbKC7zpYNza{ADwOD<(BQ5$A2$6WKzqvc a!!K5?K4vt9E5c0{f9wvUT&Zp_&V=Eqn$v?&G;PSK!qF zKd_|ac}?&>aQbf5h^YAgnzNU v+9W;4DF1PP;3`PT4M7{rOqd2EbCY_A>Yza^rPm 3#zn%hQWVrGJiP;;DW5HiAC;X8PEbssT{q?TYeivE@bG~RUnMP q-Oz%e@6&R#C@6>QX`z6$bE#etPq!S(II@=L zF4c1}&Vy0PN_^%9m4Mt^ZG$@*Z-TE^T7ggS28K83<9uu>)`ef!8fnm{$eI*^m8Mq; z6ynk`@jr|ChlM6y#s0wV5`X%qaMmuQ@H1Pq5-#(AeB4)sCpS14yh{)7;R$fd moDsA!ZL7YjM)e$Igz%q+!Bc#VJVb`a{gc?kstX;wQ#L4 z-a?iCnh!d;xS`DOwxbdC$dtCh_pH`nK1FVwX+s0`d zraYjY_)*G{YlVg^o8Z5+E?4lfylGYum1HH=3f&%D>lTc^?tCh zPl#bE4=lej+2E886j;EdhGPr;CG*Rz(_UdgJO6Kg*3)Sg`bw0mjLF)UaxzRh4{yUs zZ7COrp5CcmY&`M5j-6$zm+3~Xx`ahgE^I}%*!eLGd4FA8d7m!_B|u0auu0&i$lGRx zn=kKqiSDwSFLYgzNW`g%E^r%fNRuMPe6lO7a-ncVNj2c*Lmlg@PZ)wsZLRj{=HJZ| zNLq-mh^Vu9rd5BrF_A-Pf-6$jjQ9Qd __&9}%0oS76XI(*MR z)kkD6TjUDM&rzRAl R{Qn({1qb0KDXf4`~yz~M}eY@42-Ijw(tX$?{~ z2{EJz5XDD-);9NntP+qrC$TR+_t@WC_RDw)d!i(3GNzW+p5Ja4Gpd?eUVA+Ey_Bfq zXj+8?u--p?9uzaema{OcrQ(TAia9ad^BILq$TG?R0PvHYH0tVQbAn|j!gY{s#atOV z$gKQDBlBYAK_2{zLC))(SoxmtPBh7u@~gBD95WQM;uv+VL`r hL0xZB7g4#OgjHqJm3!k&nq{dyJdB!S_Oda-F8&W;or1-Do zuiguSR+89u%U9LDf7^?ozS1&bU>#=VSYOMR$_48=S*FxOH2GoRmpKyeV>SPw$rmZ& z1`a58?eL|kQqJk0M-0M4A77pOB(1!RT~;`_wJsg!FKWf6iT&9l )4JN&CCD5`&)O{l#r&~eJGJg@!MuEhnP_3&p#EZOh93jKYu@R zMb#6PCl_~$GzJ5rX5XpY2-sqF14`A!nH@qky*_@j$s2q^rDa32@VG0