From 19f2b7a7fa745435428a2bc2427133464664ea0c Mon Sep 17 00:00:00 2001
From: Anthony <bouillant.anthony@gmail.com>
Date: Thu, 3 Apr 2025 15:43:26 +0200
Subject: [PATCH] Create game file

---
 Makefile              |  16 ++++--
 puissance4.c          |  88 ++++++++++++++++++++++-------
 puissance4.h          |  29 ++++++++++
 src/actual_output.txt |  15 -----
 src/game.c            |  77 ++++++++++---------------
 src/game.h            |  11 +++-
 src/test_board.c      |  42 --------------
 src/test_game.c       | 128 ++++++++++++++++++++++++++++++++++++++++++
 tests_board           | Bin 0 -> 26728 bytes
 9 files changed, 274 insertions(+), 132 deletions(-)
 create mode 100644 puissance4.h
 delete mode 100644 src/actual_output.txt
 create mode 100644 src/test_game.c
 create mode 100755 tests_board

diff --git a/Makefile b/Makefile
index 6d85b74..bc8b3ac 100644
--- a/Makefile
+++ b/Makefile
@@ -3,11 +3,12 @@ CFLAGS  = -g -Wall -Wextra -Wpedantic
 LDLIBS  = -lm
 LDFLAGS = -fsanitize=address -fsanitize=leak
 
-puissance4: puissance4.c src/board.o src/game.o
+puissance4: puissance4.o src/board.o src/game.o
 	$(CC) $(CFLAGS) $^ -o $@ $(LDLIBS) $(LDFLAGS)
 
 board.o: src/board.h
 game.o: src/game.h
+puissance4.o: puissance4.h
 
 clean:
 	@echo "this rule must clean everything up (including candidate files in testbed)"
@@ -29,8 +30,13 @@ tests_rand_ai: puissance4
 tests_smart_ai: puissance4
 	$(MAKE) -C testbed/smart_ai
 
-generate_board_test: src/test_board.o src/board.o
-	$(CC) $(CFLAGS) $^ -o src/test_board $(LDLIBS) $(LDFLAGS)
+tests_game: src/test_game.o src/game.o src/board.o
+	$(CC) $(CFLAGS) $^ -o tests_game $(LDLIBS) $(LDFLAGS)
+	./tests_game
 
-tests_board: generate_board_test
-	./src/test_board
\ No newline at end of file
+tests_board: src/test_board.o src/board.o
+	$(CC) $(CFLAGS) $^ -o tests_board $(LDLIBS) $(LDFLAGS)
+	./tests_board
+
+run_tests: tests_game tests_board
+	@echo "All tests executed successfully."
\ No newline at end of file
diff --git a/puissance4.c b/puissance4.c
index 85b0e6b..f216479 100644
--- a/puissance4.c
+++ b/puissance4.c
@@ -1,19 +1,16 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include "src/game.h"
-#include "src/board.h"
-
-#define AI_SEED 0
-#define MIN_COLUMN 4
-#define MIN_ROW 4
-
-void flush_input();
-bool is_valid_game_mode(int game_mode);
-bool is_valid_board_size(int rows, int cols);
-bool is_column_full(int col, int rows, int** board);
-int select_random_column(int number_of_columns, int number_of_rows, int** board);
-int select_smart_column(int number_of_columns, int number_of_rows, int** board);
+#include "puissance4.h"
+
+// #define AI_SEED 0
+// #define MIN_COLUMN 4
+// #define MIN_ROW 4
+
+// void flush_input();
+// bool is_valid_game_mode(int game_mode);
+// bool is_valid_board_size(int rows, int cols);
+// bool is_column_full(int col, int rows, int** board);
+// int select_random_column(int number_of_columns, int number_of_rows, int** board);
+// int select_smart_column(int number_of_columns, int number_of_rows, int** board);
+// void announce_winner(enum GAME_MODE game_mode, int current_turn);
 
 int main(int argc, char const* argv[]) {
     if (argc != 4 || !is_valid_game_mode(atoi(argv[1])) || !is_valid_board_size(atoi(argv[2]), atoi(argv[3]))) {
@@ -26,10 +23,63 @@ int main(int argc, char const* argv[]) {
     }
 
     enum GAME_MODE game_mode = atoi(argv[1]);
-    int rows = atoi(argv[2]);
-    int cols = atoi(argv[3]);
+    int row_count = atoi(argv[2]);
+    int col_count = atoi(argv[3]);
     srand(AI_SEED);
-    return play_game(game_mode, rows, cols);
+
+    int** board = create_board(row_count, col_count);
+    if (board == NULL) {
+        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
+        return EXIT_FAILURE;
+    }
+
+    fill_board(row_count, col_count, board);
+    printf("Board size is %dx%d (rows x col)", row_count, col_count);
+    print_board(row_count, col_count, board);
+
+    int current_turn = 0;
+    struct coordinate empty_slot;
+
+    while (true) {
+        int selected_column = get_selected_column(game_mode, current_turn, col_count, row_count, board);
+        if (!is_valid_column(selected_column, col_count)) {
+            continue;
+        }
+
+        empty_slot = find_empty_slot(selected_column - 1, row_count, board);
+        place_token(current_turn % 2, empty_slot, board);
+        print_board(row_count, col_count, board);
+
+        if (does_player_win(empty_slot, row_count, col_count, board)) {
+            announce_winner(game_mode, current_turn);
+            break;
+        }
+
+        if (is_board_full(current_turn, row_count, col_count)) {
+            printf("\nIt is a draw.\n");
+            break;
+        }
+
+        current_turn++;
+    }
+
+    if (destroy_board(row_count, board) == EXIT_FAILURE) {
+        fprintf(stderr, "Error: Unable to free memory for the board.\n");
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}
+
+void announce_winner(enum GAME_MODE game_mode, int current_turn) {
+    const char* winner = (current_turn % 2 == 0) ? "Player one" : "Computer";
+
+    if (game_mode == PLAYER_VS_PLAYER) {
+        winner = (current_turn % 2 == 0) ? "one" : "two";
+        printf("\nPlayer %s won!\n", winner);
+    } else {
+        printf("\n%s won!\n", winner);
+    }
 }
 
 bool is_valid_game_mode(int game_mode) {
diff --git a/puissance4.h b/puissance4.h
new file mode 100644
index 0000000..ba2d9cc
--- /dev/null
+++ b/puissance4.h
@@ -0,0 +1,29 @@
+#ifndef _PUSSIANCE4_h_
+#define _PUSSIANCE4_h_
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "src/game.h"
+#include "src/board.h"
+
+#define AI_SEED 0
+#define MIN_COLUMN 4
+#define MIN_ROW 4
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include "src/game.h"
+#include "src/board.h"
+
+void announce_winner(enum GAME_MODE game_mode, int current_turn);
+bool is_valid_game_mode(int game_mode);
+bool is_valid_board_size(int rows, int cols);
+int select_random_column(int number_of_columns, int number_of_rows, int** board);
+int select_smart_column(int number_of_columns, int number_of_rows, int** board);
+bool is_column_full(int col, int rows, int** board);
+void flush_input();
+
+#endif
diff --git a/src/actual_output.txt b/src/actual_output.txt
deleted file mode 100644
index 8885cb0..0000000
--- a/src/actual_output.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-┌─┬─┬─┬─┬─┬─┬─┐
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-├─┼─┼─┼─┼─┼─┼─┤
-│ │ │ │ │ │ │ │
-└─┴─┴─┴─┴─┴─┴─┘
- 1 2 3 4 5 6 7
\ No newline at end of file
diff --git a/src/game.c b/src/game.c
index b80875a..530c90f 100644
--- a/src/game.c
+++ b/src/game.c
@@ -23,60 +23,41 @@ struct coordinate find_empty_slot(int x, int rows, int** board) {
     return coordinate;
 }
 
-int play_game(enum GAME_MODE game_mode, int rows, int cols) {
-    int** board = create_board(rows, cols);
-    if (board == NULL) {
-        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
-        return EXIT_FAILURE;
-    }
-
-    fill_board(rows, cols, board);
-    printf("Board size is %dx%d (rows x col)", rows, cols);
-    print_board(rows, cols, board);
-
-    int player_selected_column, player = 0;
-    struct coordinate coordinate;
+bool is_valid_column(int column, int col_count) {
+    return column >= 1 && column <= col_count;
+}
 
-    while (true) {
-        if (game_mode == PLAYER_VS_PLAYER || player % 2 == 0) {
-            printf("\nColumn number? (starts at 1):");
-            scanf("%d", &player_selected_column);
-        } else {
-            if (game_mode == PLAYER_VS_RANDOM_AI) {
-                player_selected_column = select_random_column(cols, rows, board);
-            } else if (game_mode == PLAYER_VS_SMART_AI) {
-                player_selected_column = select_smart_column(cols, rows, board);
-            }
-        }
+int get_player_input() {
+    int column;
+    printf("\nColumn number? (starts at 1):");
+    scanf("%d", &column);
+    return column;
+}
 
-        if (player_selected_column < 1 || player_selected_column > cols) {
-            continue;
-        }
+bool is_board_full(int current_turn, int row_count, int col_count) {
+    return current_turn + 1 == row_count * col_count;
+}
 
-        coordinate = find_empty_slot(player_selected_column - 1, rows, board);
-        place_token(player % 2, coordinate, board);
+int get_selected_column(enum GAME_MODE game_mode, int current_turn, int col_count, int row_count, int** board) {
+    if (is_human_turn(game_mode, current_turn)) {
+        return get_player_input();
+    }
+    return get_ai_move(game_mode, col_count, row_count, board);
+}
 
-        print_board(rows, cols, board);
-        if (does_player_win(coordinate, rows, cols, board)) {
-            if (game_mode == PLAYER_VS_PLAYER) {
-                printf("\nPlayer %s won!\n", player % 2 == 0 ? "one" : "two");
-            } else {
-                printf("\n%s won!\n", player % 2 == 0 ? "Player one" : "Computer");
-            }
-            break;
-        }
-        if (player + 1 == rows * cols) {
-            printf("\nIt is a draw.\n");
-            break;
-        }
+bool is_human_turn(enum GAME_MODE game_mode, int current_turn) {
+    return game_mode == PLAYER_VS_PLAYER || current_turn % 2 == 0;
+}
 
-        player++;
-    }
-    if (destroy_board(rows, board) == EXIT_FAILURE) {
-        fprintf(stderr, "Error: Unable to free memory for the board.\n");
-        return EXIT_FAILURE;
+int get_ai_move(enum GAME_MODE game_mode, int col_count, int row_count, int** board) {
+    switch (game_mode) {
+    case PLAYER_VS_RANDOM_AI:
+        return select_random_column(col_count, row_count, board);
+    case PLAYER_VS_SMART_AI:
+        return select_smart_column(col_count, row_count, board);
+    default:
+        return -1;
     }
-    return EXIT_SUCCESS;
 }
 
 bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board) {
diff --git a/src/game.h b/src/game.h
index f9dc934..75d431c 100644
--- a/src/game.h
+++ b/src/game.h
@@ -1,5 +1,5 @@
-#ifndef GAME_H
-#define GAME_H
+#ifndef _GAME_H
+#define _GAME_H
 
 #include <stdbool.h>
 #include "board.h"
@@ -15,9 +15,14 @@ struct coordinate {
     int y;
 };
 
-int play_game(enum GAME_MODE game_mode, int rows, int cols);
 struct coordinate find_empty_slot(int x, int rows, int** board);
 bool does_player_win(struct coordinate coordinate, int rows, int cols, int** board);
 void place_token(int player, struct coordinate coordinate, int** board);
+bool is_valid_column(int column, int col_count);
+bool is_board_full(int current_turn, int row_count, int col_count);
+int get_selected_column(enum GAME_MODE game_mode, int current_turn, int col_count, int row_count, int** board);
+bool is_human_turn(enum GAME_MODE game_mode, int current_turn);
+int get_ai_move(enum GAME_MODE game_mode, int col_count, int row_count, int** board);
+int get_player_input();
 
 #endif
diff --git a/src/test_board.c b/src/test_board.c
index 050c064..018c493 100644
--- a/src/test_board.c
+++ b/src/test_board.c
@@ -4,23 +4,18 @@
 #include <string.h>
 #include "../src/board.h"
 
-#define EXPECTED_OUTPUT "src/expected_output.txt"
-#define ACTUAL_OUTPUT "src/actual_output.txt"
-
 #define GREEN "\033[1;32m"
 #define RED "\033[1;31m"
 #define RESET "\033[0m"
 
 void test_destroy_board();
 void test_fill_board();
-// void test_print_board();
 void test_create_board();
 
 int main() {
     test_create_board();
     test_fill_board();
     test_destroy_board();
-    // test_print_board();
     return EXIT_SUCCESS;
 }
 
@@ -38,43 +33,6 @@ void test_destroy_board() {
     printf(GREEN "test_destroy_board: PASSED\n" RESET);
 }
 
-// void test_print_board() {
-//     int rows = 6;
-//     int cols = 7;
-//     int** board = create_board(rows, cols);
-//     assert(board != NULL && "Board creation failed");
-
-//     fill_board(rows, cols, board);
-
-//     FILE* expected_output_file = fopen(EXPECTED_OUTPUT, "w");
-//     assert(expected_output_file != NULL && "Failed to open expected output file");
-//     freopen(EXPECTED_OUTPUT, "w", stdout);
-//     print_board(rows, cols, board);
-//     fclose(expected_output_file);
-
-//     freopen("/dev/tty", "w", stdout);
-
-//     FILE* actual_output_file = fopen(EXPECTED_OUTPUT, "r");
-//     assert(actual_output_file != NULL && "Failed to open actual output file");
-
-//     char actual_output[1024] = { 0 };
-//     fread(actual_output, sizeof(char), 1024, actual_output_file);
-//     fclose(actual_output_file);
-
-//     FILE* expected_output_file_read = fopen(EXPECTED_OUTPUT, "r");
-//     assert(expected_output_file_read != NULL && "Failed to open expected output file for reading");
-
-//     char expected_output[1024] = { 0 };
-//     fread(expected_output, sizeof(char), 1024, expected_output_file_read);
-//     fclose(expected_output_file_read);
-
-//     assert(strncmp(actual_output, expected_output, strlen(expected_output)) == 0
-//         && "Output does not match expected output");
-
-//     printf(GREEN "test_print_board: PASSED\n" RESET);
-//     destroy_board(rows, board);
-// }
-
 void test_create_board() {
     int rows = 6;
     int cols = 7;
diff --git a/src/test_game.c b/src/test_game.c
new file mode 100644
index 0000000..3cd6b99
--- /dev/null
+++ b/src/test_game.c
@@ -0,0 +1,128 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "game.h"
+
+int** setup_board(int rows, int cols, int default_value) {
+    int** board = create_board(rows, cols);
+    if (board == NULL) {
+        fprintf(stderr, "Error: Unable to allocate memory for the board.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    for (int i = 0; i < rows; i++) {
+        for (int j = 0; j < cols; j++) {
+            board[i][j] = default_value;
+        }
+    }
+
+    return board;
+}
+
+void test_place_token() {
+    int rows = 6, cols = 7;
+    int** board = setup_board(rows, cols, EMPTY);
+
+    // Player1
+    struct coordinate coord = { 2, 3 };
+    place_token(0, coord, board);
+    assert(board[2][3] == PLAYER1);
+
+    // Player2
+    coord.x = 4;
+    coord.y = 5;
+    place_token(1, coord, board);
+    assert(board[4][5] == PLAYER2);
+
+    destroy_board(rows, board);
+}
+
+void test_find_empty_slot() {
+    int rows = 6, cols = 7;
+    int** board = setup_board(rows, cols, EMPTY);
+
+    // Search for an empty slot in a column
+    board[5][2] = PLAYER1;
+    struct coordinate coord = find_empty_slot(2, rows, board);
+    assert(coord.x == 4 && coord.y == 2);
+
+    // Search for an empty slot in a column with multiple tokens
+    board[4][2] = PLAYER2;
+    coord = find_empty_slot(2, rows, board);
+    assert(coord.x == 3 && coord.y == 2);
+
+    destroy_board(rows, board);
+}
+
+void test_is_valid_column() {
+    int cols = 7;
+
+    assert(is_valid_column(1, cols) == true);
+    assert(is_valid_column(7, cols) == true);
+
+    assert(is_valid_column(0, cols) == false);
+    assert(is_valid_column(8, cols) == false);
+}
+
+void test_is_board_full() {
+    int rows = 6, cols = 7;
+
+    assert(is_board_full(41, rows, cols) == true);  // Full board
+    assert(is_board_full(40, rows, cols) == false); // Not full board
+}
+
+void test_does_player_win() {
+    int rows = 6, cols = 7;
+    int** board = setup_board(rows, cols, EMPTY);
+
+    // Test horizontal win
+    board[5][0] = PLAYER1;
+    board[5][1] = PLAYER1;
+    board[5][2] = PLAYER1;
+    board[5][3] = PLAYER1;
+    struct coordinate coord = { 5, 3 };
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    // Test vertical win
+    fill_board(rows, cols, board);
+    board[5][2] = PLAYER2;
+    board[4][2] = PLAYER2;
+    board[3][2] = PLAYER2;
+    board[2][2] = PLAYER2;
+    coord.x = 2;
+    coord.y = 2;
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    // Test diagonal win (left to right)
+    fill_board(rows, cols, board);
+    board[5][0] = PLAYER1;
+    board[4][1] = PLAYER1;
+    board[3][2] = PLAYER1;
+    board[2][3] = PLAYER1;
+    coord.x = 2;
+    coord.y = 3;
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    // Test diagonal win (right to left)
+    fill_board(rows, cols, board);
+    board[5][3] = PLAYER2;
+    board[4][2] = PLAYER2;
+    board[3][1] = PLAYER2;
+    board[2][0] = PLAYER2;
+    coord.x = 2;
+    coord.y = 0;
+    assert(does_player_win(coord, rows, cols, board) == true);
+
+    destroy_board(rows, board);
+}
+
+int main() {
+    test_place_token();
+    test_find_empty_slot();
+    test_is_valid_column();
+    test_is_board_full();
+    test_does_player_win();
+
+    printf("All tests passed successfully.\n");
+    return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/tests_board b/tests_board
new file mode 100755
index 0000000000000000000000000000000000000000..74e2f07dd6600edda11e746f20c1c567898064ad
GIT binary patch
literal 26728
zcmb<-^>JfjWMqH=W(GS35YIsnBH{p{7+%Cd84L^z4h$9yybKNuY7D9jYzzzxEMPH+
zJWM@|zQF_$htV7mE(0@Ep9F}(z`%e`%Rtq^XpoygLLeGsABc?&dq6FK(F_6*RUmz=
zASRR#6Nk~JoFGXC1{e(!2k8UbrvQ;>K%*tVk_-$m8d)DGY%Fvk`YdcwX;^stfQAoD
zABYRm7XZ~40M!Sh4L}MQ7#LtQ)Vts~06E118lLF10mOO+7>%wk1F8?5c7f`H(I7iO
zLcvc<Qb25UdtiK+Jun((UjS6!7e$aM3=HUW2}GCyMuY4C2?ahaNdbimh)oQJMRO3;
zK3wr|0vet$8Wi6k^YwEwlgv!?b5eA3GV@9+bSo^(bj?ikiu3i1K+@pw1|<bhnsWCG
zWnf}pH~?}hG#D9}8X$a_c_29v1_p4t2dNKpjWXTCzDCyfnuYs|68#C*K8KHj)PUR#
z(gRWhvIt}z)QKQ2$Q}kh1_p2*1&0S?BS@SHB*xFcz;H43T(0G(ZdkSf$)VsN1_lNp
z6cGr=4Tm_$Eg*kFR3XUqIMg@b5MPc%JPU_7C>*fatHZzm&w>coFfb(GFeeg+cpnb&
zR2<@k3=9lP$QDA`3m6y}1R10m6rcqjES)pN$EWA!=fxM7Bo>v#$1}uxhWN&(q!y*7
zXBL;F7KQja=j7+5h9oBCq(bDd%fu%ZC+5Xx=4F;Jq?H$CmZUNi6lLa>q%ouwrKU0z
zl$I1T<R<3i<R>%4$0t`L#;0ZGCFW#Sr830FCl(i{7L~-OC1&O@#K-4kCM821lbe{C
z$5337l3G**G9fu5v4|nHBC~`cCo>6T9Vn5TfjGHvRx*U;?&Im?9B-s&Y{CFz8tIvW
zQzIh-BLfo{f>;pD3>5<f6-f3p0|Ts>W7slr8XG7#T!o62N@a2~FfcJZ04WC5C(v>a
z7M=>wMC*Yj{s3A}aiE1ij1Mb!LFpJdAKkErSOm&LpgacQF)%zp5{KChl6!$94y`Ic
z!VDjf#6fuwEXcsX@B>Ml2POzgyHIz6$_-F{g-OkTs%Hm>CQOupVF8jjsC<CQtUwY6
znFSNyfFus`8%%r$k~qi?nD_xCaW0r30|UbeBynye@e4@eyh!4s%+U}S4S~@R7!85Z
z5Eu=Cp%Vh1`Q?6jG{52S=w>~s&%of(dZ2{q{{@fcBOHgpp7?K?q|d<c>Az~SJ_7^4
zJOfC521w@9%ZLB}|DOQngBn+#US5RrK@F`>FAu``pa#~bmmA@HP($X^%Y|@0r~&io
z<wQ6i)NuLqvJuV)HCR5qEQIkt{Z};wyT*k9?4D2mRnO{yT!-KvMdR;9<8MXduSMf8
zMdQy!<4;BA8@~1Iycp-v`N*UB$%lXtSHlB_Cp~&?Pcbks{1=_9$H4F<O^;u`1r%xw
z9=*0R^%xjDdRZrdD9axuq8{C>VIX$vffCOD5BTLlT_}dbP}-x{HWMV-YnlY2H2-;Y
ze(*T>&feqT4`vU>V;&d(m56wBv&w=bTMv|Q{C|+fFYm$t*AI%H23uP_1_p*w?NE<q
z+h3r81&_|BB|IM8wrqL~3@=vx`~Uw%%K!iWkFkpCF)%R39_E)v(f_ji|Ns9WgF-zz
zpY8y8<HchJ1_lUg8zYPbiY2gE>|vN<kLEW5$6Y^w;`6xc7m$MP&@bJtA3Cpf9)Hot
z%D~{!>H5Q?x%LM`sjf#iYrif?<lrtf1_p+GphV@-%bLv#5<C7v_}~Bk`$1waB>(;Y
z@6jFlquUp3)Va>%FPxbe7{EfVA3VTj&t_s^XgyG(;nB<5#RoFr;4W1LaIiap%{%7N
z%jyYc9e;82@BjZEy{uUfF4zYzSpWV1Kj9>@KNN8K;}{Fb0+>HQR+>Yt1a-DOdRfo&
zfE0kN)PvaZBJJ=0|Hob5fP(V1N4M)6j~O1lB1b`7k8al=9*h?}x*0rL50ruodj-~W
za91eA{Y`Mg1i=!=Ur7G_|G(Mw4P&?K8*A4OH5)v7S=As?5WiT0{09mzSm4w#GB6P9
zxtGi!w<CM53T*blU7#MfM=$FqZjb_y=K{elJN}~c4@UefW?*1A?)n1c!Pi+ZkB4@<
zzQE#f0Z4cpe8A+vc%d5>i!4xE(;%Tx1GhC1YOC-cq)_-$v$)yy1!K4C3s8vkdGxY|
zK$Jm3L>=ZrScv2>poB<g?VHZh7apCV501P306W_0xa%J<Ll+c3$g%YR99sh2u75mc
zct9L|9Hf$=+4T=&x9cBk*B3RXn_Yh}cDw$tc70Q`ZNdbU{GrfU`^KZQ^a0EQWr#_L
z<N&dN!K3r|i}>FlKSGUtQ*+g$+w}oR-2M0e|6re?q*#N_+B==4H#|B+FL?B_UIvHQ
zaj>!%YQI704-y~d9=)u)ktI2Q|Nr0ZdZYOTqowPMS`m+4)&<DYuYQ3X0S(+6H3vO<
zSz93TFYf;W84FI<FWDKv*)10$1+jKLSpEYjcwR?Bq8Z`O3$TFv01wD+hR)+Jf|(c?
z`1c*?JpRJr7s6p5zz*X_Ha!sRun&ygt{<#jZ`929=w*G+1xlR9U$}vF-T`~*O>MSE
zFY8T+48&dHV0V21y9*Q?Ymg;>{Y2RM1#Ig=Wa-;KLBa8bvD@_v$W~Brv_j-xTmVZ!
zGv*!sp0}WatCuwkA`P*6&QDN~K@u6rYC~kndL*lVfUPz{mQDbh4^3H+m=J@=zX$~z
z`v+8BzLxEF{nH7`pno~Rp#ia28LSzUmTp+P{;9n^0jWd?_Go^i0ZBdGu6MxE!3;`g
z=YRbF@6qY{!lSwN1w$zp*r1nd!Fd}zZu4>?0|P_1>kY6DrtZ)O9?6$HdU-%&JfPzF
zg-5T9Ajq6{usO`2)Qg;zUVu{oxZra??)n5A9m?IVPf!X8n4-?(F9Lpmg8m6(x9byY
z*9YM2@B(DK#Sdt9crDWG`hc<9^?|kP9sZu=|DbZo^@T@w><>gn>8$<JT>IyL32$@l
zAI4I?9T5x+46k{1_=70c9iSn|SWrs{RHK30N${2t$a$l9Gz3ONU^E0qLtr!nhGqzW
z=4FswE*))XZEToZl3H96pORW!Qj}jApOl|ilwzge=IH6;>cS-*ZIH`QT$HR2Rs)vP
zOJ+b(t5K9+UaX@4meW+QwN-G9@C=C$4s~{R4GxCb2DZltt33gZ!ND+l7{F#IDB3Fc
zh5Gm?sHrI^Ie}cGkX)3SSdy8arvRGYN=<=J&4JZNXU3vv3Cb^50MC+PYC(1f*vwRz
zcafa|Gc`IZ7VI70fDq8cA_D^hvi`KpoE&VrAwGtX;6OtOEQmOa1j{2k1SSEc!SV=;
z7`Pry>0x*@rGeqmlr;>Grc7XXG^L5*(Udt1kEZNlcr;}R!=ouv7#>a8!tiLy3<d?&
z6p%5D(#+Nc3=9mQ`5T>g|Nk#xU|`tu?*IQY3=9ls-u?d%YI*s*|Np;-fq}vF!~g%F
zo=?(;|Nmte85p!a{{L^o$iTq<>Hq&2Mg|7S&;S3|FfuSSeg6M{4kH7@ozMUO?*WN_
z`~UwABLf5L_y7Mvlh&ZQZ?N4}K@5x)0*ul;>>Lvq85ls~pvmeT@BaS>b^94y*g;dj
z3@Qu^3?>W=3=MDp|DOQT$S2^&C*j4<UCz<KU@v8*Wvl{@bCCWR1_p)~Z~y-XYXqrf
zfS3zfL-643|Nr0t6{tAKE|9+r-~ay)8VO-=<r8RQa^_`A;b8~O_krZsFfcIKz5oCJ
z1V|4|o@qZ=0Z1McPS4)||9=-n{t8?k)B#%j;s1XjQ1ct6pP7>pqyVI!hmnC{>c{{8
zGg0&>fTS5f@;ZzR4EH|%{~v`S9|)KCVPs&C`1Jq3Eoht#ZoUZ<NCBw9n#0JzVEX0%
ze~>%i{&Q_+X1WJb!2q@c6!w3={QnP{Plu~XhRB1g9mS&|Fd71*Aut*OqaiRF0;3@?
z8Uolu0Jbg-whj%{<O8YP0wR#savenDgVw@<gy3t#pp92hn;ayrAqgT8YaL<h*r3a1
z89;4SkP4_W1_$W6IBAd|0|Q)M3d)DAn*+5kK|(P7U;q8j2k|$6=4crh7(i38Abtdt
z0h+o4@ozxoVQa*|ZA%6Q2H4s#36LTN1_n_m4Wppi7#g7K#z0M0klX<f0d1#)n4q~q
z5G@WO7#J8jpaM{eVFuJ8Fn5C|5f~U4U~BPU_RB%_!_@u$5Ah!(G)VqI`5932{zLh&
zc>4h5yFlfCLisR%K#ivw1zXpRZlD1)Jvcz=04SXRr3;{R1C*Wsr58YHbn^)DVe2K`
zot>=|G(wX~^GZq;3=Q>6^bB+jOTk>jIwK=J0~1ZCFt{55iB4Exqgn#$S}-w8V1<S}
zgC=wd=M#t~RK*Mo3=s7zxM1pep=k-ev>r`I4=X6SGJ-7^{>I9{0L~l6P*ozuEDQ{c
z&D=Rm3=E<lSs54@yTof)7#P^K7#JA%ij9pJW{DJl_|_nPsj(5mG%=7`c5g7>%!FaO
z%nXoxGy?+zQy>ci1Ctt$87OBlxq?L0!5jxBaYhCPCQS&3AGDg8NgK>z5a3wB#K6F$
z3*j*^IB?{G`1-;iLqH3-#rA;s#@wJOO{k*<#6hzuOwo+o<)AeZECO>G7#MCafpiEQ
zW@TWw31&)s1-a%vGdF0_c0GR|3j+hQm{1tV3`WU2%nS?y%$gjLObiTytxOCITKpeC
zW(h{KFfeF?ea9hHl9<lGtOMroaPqS<FzA8uGuTefovaKD`nJpr3?MEerzaBwgFz~k
z%fz{bg@M7)ixDE5!UeL;n0Y@71H&{%1_sao05`~S3}6Wp=1K+zhV_gL44{d7ummf}
zEv%p*hA1&*e#^+faEXzD;W;A%1DX=3I?&|4C5Jo%1H&&+E@fh1;Qj^jk<b-J1_o>X
z3Cs)(Nh}Nul1vN?tRM!1v;i{%1G6(fD1m@tTL>iOBIdx#zyRVpffRxm3^MycEAn0W
z8Cf7QtYA?Fc2Q8A9s(IM4;)(p3~VgyQp^ktETEx}d5m2ksrihcvWADn2CVu#D+2?|
zByhC-VyXmjCWASDnMxQL7+9u&IUkvxgAADp=6qt>0g{;p=6q%{V_{%mnGWWBWfEs+
zU|^X6=6qw42AMV!%=ymro{52hWfqw8hp8LHnGNRrV7da@Q8Ne3`N=dFWZGOX=O5Ee
zkg|DT&KjnEkfrm%oZU<hK*|<?Ij5M^Kr#!#oYPEaK@MF4=A7XG6~Zjbz(KLOYpWwi
zD9FI&U_PJO16KwXXGR8wg^Y7S!LkS(EDS6!Ss56XFoLQT=A}>}Py$`fco?K=1ytx6
zBLl-K#%my<)leaIW(J0}j2}Qk>%c<H2f!2q%W_5rh7F9&pya+0DrCyez_6K73?#G#
zDrCXRz_5)`6C|`9DkQ|jz_63i1|+l#Dpb$Hz_5qWA0)IFDzuJ~f#DD%C<QSeh6u4S
zG8r*3Ft9PQU14HikY!=b%qwAF2bCIZ9PFaZ3=C`>tP9ye3OG)K)G@Iquz&>F1(+Ea
z7_&jue+7tW1rd`#1ZcYe;|355Q~@%A;*1frmWJ^iNbDyA0|O7M1Sl2quu6go9v)UH
zP-bBS&8G8$iUD3wYU2fEZpJt!1_n7^7EsaF!^FVAI1@xH0}-1+!~qa-7DU_v5zj%y
z7ZAY+avUFskOmPNAi@+xIDrU%5D^0+GC@QoGXsM>8^2&N69a=nC<6lnn>ZIMD+2>3
zGrUD&4$4pRY78RK@|Yh~@*HDlV34(CWMJ@PWWXr-!$HMpF*^eT(?xMBP!@!QCNm_H
z32`tpg2R&;5}wSAY#?tiGqJjJGB5~3Vu2YF@*FPg3=GUOBy&L~HghsCFwc|*u~|Sf
z(aex|;{>rq)HxX#Zm<|~u!Dl2n1g}Am>pd3GRCtrFqm<I#soPSLpT^1%)x8{#$HYa
z1`9A-g7G;g1A`@)t-yGQgMq;c%+_G!<78m42D1$qJJ}f+Y`|;_#wrd523s)Of$;(d
z1A_yY?ZLR8lYzkz%no3j&B?&v1ZGDt8gMc&xQHn*F)$=B=CCs`xQVDTF)(B>?qg?Q
z@Bq8Bfbj_j1A`}+UBWnzgMq<|8#KOI!Pv&Zz~Czs2pTJ8jOS!v@Z$$fVK*^Wu`@9E
zb7(O!Ff=pX<6vM2<hNpCVCZ06#KFK2$qO12oxnJigMlGh+=YpOVFqIeCj&!_q#qLl
z!ve<hoD2-HU^lE_+{(eg5Xb4k0LptSI2jn?xj>7_b}+u-U|>i9yXOGodQJw0Bo5F@
zjUx;k+MEmwtn8AYs!LRclYxOnn~!T12Ll6(G^p4B3A2G>1mqfaQ0y}>un03TFmO!*
zsj&yK0ztY!6%SZpG7|#>SfMZj3n=!)c5pH<uubFxi8FJs&H<$W4se!ZnZdxoAkGA`
zp9K`T94u^WK&wZlfeJAGPaF&kj1s>%7#QjqByB<2HieM~r0fW&9&Tb{V31;vw&Y}B
zV0Yzx3KL=ii8DEZYJ3ojK_HNwfq|D5r0qXQ4T!-6Vll9=fQn2IU#5bSfq{dYO_iB}
zfe9o4A;79+^Eeq8I189~K^x`3;tT?591ILx>>%kN6derQ#h^I(Eet9+85qFB$)I9l
z&I@J+2G$mK28LKpu<;WUSnqOzVhO@aVa?@WV2I}inaDITgJ%^x1H%tyP@dfYZXz)-
z@MeL=%^4UNsv$-*@MSWj@IiD(@D@WQL41%rUlv2E5QxJx5j51!1`1`6dEiLlXW#@m
zhdYsjfx%A>>QwN^IM}JBEKsNVqc}AH%7ZvH5XGsjEFh;&fH}1aY9@5T1?1Eas8eGY
z7{HDJ=>R)Mkbx6qA-4}Z1A}xJw7m%)#s@p*3CuAvQ0pP#CJW_393zL~m@i<*6hIvV
zu?{2#woZtF6J(^^BTfbeMqzNGfHiW#a|>Wg8P<bhi-D2jGBX1MH@I9(VS<#4=q=n0
zj0_AspmLD~rCj7iDe_=R9<_{w6rHF=B_9X01mp)rGczQQ2tcw2C`Gffux$pFo8auh
z0nQ$RknF*!%EiFIB*Vl9YQTZkv4R$gGB9w0at(6|BM(UTBT!`kB7_*&n-~}vgcU$~
zw3&E+fh0g08ALd^7#J9%*+AC+g!a%tt$a|TVw|JR$iTq(jgx^PS|79<k7;5K0~aVO
zc(QL{WMJThss}YpA?iV*jG$ESDFL#dX`&A!DAju^L3kdbpj6N3#SK!&G%<q34Qj$l
zkakc8&Sdc8gQyK)nE{mq%`t)GnX(uH#UPR)3=9nHJ3(_?AimfiP~?iTU4ZsRz>_ZE
zh`kD`NkHxqg=&PjM^pi%jcK9>Bgj3XIuPeLu>OJ?04hmAHiAlKrsVt_1_`L6A{bZ$
z#XvF)4Dz6cE&~I@Bv27klwZ!E2vrlqS_oAF>S}-#7lM?4j8PSW*qgw>!U^p~!>j^Z
zV+eI+3MfOODcA-x#1?8#1_R4&s2Wgd53-0UlfeZlo5R4s1t|wXR+d3M2A-}0hm0Yp
z<p2s9UU85Drin4&u;5jOghc>LCsYeO^fMXw5N3;m%1=gCHdyum&y#@-21h@uD9lh$
z^s~xCcoASLShZnR$V07w&NnkKWiqfqt;k@}fJ)kdJO)Y{Sq$vZ-~%lMWneU6a2IA^
zU@~D~=Ck6q=C<Va6t<C+;bvf9wqmeSWVB|rR1}mDW?*2kWMt-p3UD(DGcd5SGI$Cz
zFtDjGaC6&nGxISpu&aSZIMB>uV_@I}3n?;Nb6YBk<neh5+e<<$;nHKYmjsy$lH$(e
zvyn^@1{ux`GTcOxfq{pE0qiVA5s)Kz`5CwsIY8F(i7_y9fSdz%F#`iX*an0LSQ!`u
zz(R^lATRKMeWfVCz#zyA@+sIU+@8V~+zbptXl?*01-U_3kWrOSn44K%T3$e$fk6Zu
z0AL$HvZ7)jbHH4Xd&Iz&LAf@PGVBZt;!q)0Xqd7xFi4;Y@iH(-3NteEadU$`2@Y2&
zUXahACV|{1t;YZkBd`!C@N6U*7-XQ1MiG>S#svohgB&Q{<*gur#|;WQ1*qNN0JE25
zl3-v^L^c^@Dgz@VbXXt>0c1N9C?*&fn4w1VF)*;eBY_ocq#`3kHONFZMn+F?1hOkK
zcna%tGca(Vh7%_wjc^GwF!O<I<c9hKY=|P8AfphwgG7xaD1>=Hrh5vTfSt<A%?OfX
zVBj+W1rJy`x2G`3PJRsrW<F4g6@Zz=0dkPKBrGBY5fKS80~DD;{0!XO3=G0hUvV%n
zh@i&<QUo(FphPby@iH)ovoJFA*>Q7odkP~WPXg=~P_#nb!fnlJ$&GM|6sRzkhRbn-
z<k}e}ZNMHziBol`pe$T5*dVxKIpnzW6b5+=6mX!zgB6rAkwXZSyAhcM6lTcL2@6?P
z2m=)KY>-H2hsQJr*k9ZX44kOWfdw%<AA{2Z$iFZLfsEtEi~t_gWWkGw2tG*E@Iw-c
z0JcyT1iOZpfk6lqoWiJ1f`p|ATo4?_umGw82ec?CWkDhhl7z%iRU^Ay9Gg@XXfPU7
z-m)@qFo3(QjEukeco`TO!3T_hs(VI8d1lZET|EN>!$MHO%P7yp&kkD2!FV3TeF-8!
z>rI%1LCTdu1Xwl{w3dW{g8@|SF=8{89n{g3XMzkwfySF2fd-VA7#Ji#bsNYUE=Q1Q
zU_u!rro+U*z-$8QlURcY@UV~<s4olZ$FN0%Sgbq@oJ_DL9kUQ4D{J%o`K&w(SQ#T(
zr43j)cbBpXm$Gtj=(BQ`GARqQvM%J%XJBGsWaIE+W6}_2W#q7Bm10)6fvIGLN|&(m
zu`y|gu(Fo0azZt%VO3yYVqs!q(hy`72btl;%G$<Z%gV?h%qn4rVE|Y=ABO?R2qAq|
z&JtE$h(S!6LaZuqlcXUgfsJm2o7({~mx-BykrC7l1I3pYD34$ZSQc2oazg``2^5%Y
z8KBk=m;i+o6DahUK*7ok3Oz<vBL+?;Sp6-=%EzIIaHtRi6AQCGt0;)#NMn@*(YwHI
zW=>_r>R`rpRxKY^J`R15A;KW_`mCHFio*sRYRs$QUTbCL*$s*vV*^%Jjwn_>4qK2O
zPJLDh4qH~9G*;e7Ry9!Qa9F~uV(nn%dk$6<#VW*M2MS7aeO4QeG*+oyth^IgW#+RA
zq_GM{vT8x~$wR`Fvy)ZgIn+oo4qH~<5>`QdRs{}QR*^JT(MVQ3sB&e9a^4Pz#mrex
z;5IW$?;_TPPr)t(`B@(lR2=Z=WNc;C@L?6^&}Ze~@MaY#W#wA{QY;e5$~S>kgd>7g
zsL7U<ha-(uEE42MPzW>YvkHRD;;>;=1<|Wnp`PMxWfj>C4pS!P$`V+p@-TDlVrBGZ
zHOpXSUCS!4r@Wk%F`9{qfsrvjKBqV_k0IN+w5TXGuOzr6F*)0<C^0wHH!(dknIS&P
z&)d*2KE60HFS8`GDz(Va0IVdWC^0$JGyrszg=-l@c6feKN^oXXs%M^4W=S#Vw2J)X
z#2m=k7X?MB;Nvf{eG@AJ5=%0CQuESFGC(HdG}zh1HNZPJiy_-LKczG$H8j-I1!Ot{
z$cW(5+}y;XN~kIBsU?1?6(yc|#U(|h$)NRw0m%&6j>U<2?m78Mi8(>3DOLG-2+!cO
z($Fx((LFxY&)d&G+|QLE+c_~gBh@D}FBM`j$V5lbF&&9PnduoN(7*wEkRd)k1r&tw
zQGU2hHvpOL92y+r@9PS2A2=9&QqxLMoCtQhXI@EBqJL6WYBEfcAwIqYY)5=<YHmSM
zej1V)U<aWX5}uip6Iz_=mRMX8npd8gm%<Pqp9|KG$BED|&tiy=uP92aWN=R{2`EY}
z%giq=Mh)Gh{Cv=PB%p&vAm^HZQvn0WgD$R)K0f}=4B0`cC7DI3DPTV$rKW7xqN4mF
z-_+vb#Pn3B(zLYHB5?4QfKn5ZmqLqE9n(rui-ME$3!rfaiu#a@qSQo)p<r#<t`#Mz
zMR|!i0nSdDB@Cr`#hK}OsVNHJ15v;s=~z^hSm~UfpPdOa1{9Ib`FSOo>81Il#UNH<
zW?pKMzrPbCPIL0}(iOl2+&IvfaeRD6ImpMLV1Z_p0C4WW8ReFs009SwE8esYNqEqZ
zBcRkABW7Kb7$Dgd5+ESo1!p9t<d?fA7BGN=ADmN>!qzu41tqcIOSVP^*z%WaE|PKJ
zcnV4_DJ{x_1R%UDU?>J1V^f@wUsR%i7MAeRgdsjYGp{7IC^@wNly@1j5l;3^tbkbK
z2~v=knB$R}SOBpC6ta-Kgg0cJO+ZBxC`ceV7nIo`24n}N=A<STr-tPF2ZN0-OU&_0
zElVu|r($R!0I@x^IJGDsKeISLFEzzCH8;Pg5@JMrd}$J)EM;VZD-*$j5acJfqEu+&
z#1|EYM((L4@Ra9T26ibpc|l6W)O5eZ+*F90L8gK{iyF`IDQO@Fmll*1F}VAMDmZIv
z8=63;f)#Xgi!+K#vK4f5OG@)nZPQcpQj0Q^6?AhGi;^>JA!lbP=%y>^`Wq?e7MG;h
zrstJ{_3NeucseWSrsd`9CY5I9lw{^XIH?uTI4y?oi%Lo|6?D_`b2CeH(?Io$Zb3dc
z>J@a;O2LJcZVBitC6My6%;L<X%$&@UO52Rgl$2Dck(mXFx|zvo3c6{@X}SeP`6a2~
z0^c^RG$%(vH!ZQaGA}u!C_gX1v{)D2$YM~v2Gf*ZqzhUXpO>znn+B0c&PgoJfJtZO
z=Rv~J6IADcPGbVEI`=P1NiBj!esOYXN<Qo;r}+5%w6ypV2Jq5u)TQC^p8oNmLMt8=
z>hZ}L;FFs&t5V}j7~;WMBdIiv0kqhj0i-giG%Y?Uu{f2%6}&zjTnvE;ND&ke<QftZ
z8SfVA=N#hc?*}@RDlIc7H7_3$pN8g$*d!2(R1GZj2myNq?CI3J6iA?;tcQ<J%SlWx
z2CD*j7^EmZxwI%gIX|Z~HxDeHoS%}KTvoympP!QwpP!aioLT}F&rK}KPAy`H2OXYO
zlv*4Q3O!K3m4i;!f`qZBe|&LbSt=wP<8$(pvl$>38ZpG@=BK1G1o${cx&|3SX(I+F
zf5#w~_}~!75Ld7r5VOFp^7IEA0E#S6|9Ce~A6JHWh!a3<9OU!4z;USnjwVn4`0~t@
z)cBOdl0=61GH|Mf`2l=N7dV+9?EnBLA2SoEE#QCyCjyYiz+M5nCB7gr#grkwG_SNc
zHN^;a{1-?~Qetv;X#v#3u#m~gEG}V4&d&iIFO~@jREWpGMi-YP!cHQC>~~-&DN4*M
zPRlRK1)VWgk{Vx<4@#{?kYmcACzR>w>BA9d|42?Is0f6#3-v*@BbbPXHu&_C3kn$Y
zL4`t!etL4UuA!lBL~4j-P9%&6S)2k@QDI>gZ)TzkIjb){uM~8AAH13Xo67*VTTf3P
ztM&L*z)g!!&d<%w&tpIcfD59$#GLq))U;x~3?vzdQWPO@i2-i0=w&c~d=06>@)C1U
z_-TpBsmL-Q7lUIy3AFu1FPT9<BR@A)KQXT)DZf-d7u?V-)-U!9c8)hRGKw!K%1<v!
z%*_QCJ@Lh<g{7%^C7G!?IjM&FB?bBgrJ2RWiFwJXCJg$e#YLdd0tKr+Mlc#0>SyL9
z=ai<TLKH$dm<p3X4R^3vc$MgvR2HNbqnHKWO9Y7%P_j%(P1DO@04oE98@OE#&O2aU
zN@hMdm_SF{>19B62SFrqGLt}zqGWwo2tmhou~VP{b{2+@|IuYZ>&X}ySQvVs3%)@6
zDL`sKlTg^ygVumBF$gdeK+mBAsRdz>K9KkVG;z@22S^;YUJ#@fggrssZw6@w4e0rB
zAoqd9K~wIG4B`y1^?M*O5Uv3YlrRV|z}6pv#6Y+MY>pUwJs?O7ghA&oVsk%e4>vY(
z&|wse3_=XBnJ<w4LFU{Bn=ixwo1TNtu`zsvio<3YVaw3=f>xzq31^Ub*z5%@bYNr<
zVGsdr00LQvgt4gyEr(!W5Qd*43RA8D8tY+@gs(e<iQ9q2B^c1x-N}O1H!w(n4!4CV
z1=EU5pz|^X7+~k&g7+vfFfh0?g2cf}Pzcaq2`o&ICFVfQfsKj4<}{)h5o<h=)o0=`
zzY2%=6p%QRAOmdOD9o%`AaNK6i3Tlp5n>QvK%dsyg+u*8Mg|5!CQ$|p=sHvIsyhY-
zhHE(7{|TfXbkZm&BY@KY#BxS(I78UTBxr4b0G9CAV8VXxCTLNZAd?h>05reA%<_kZ
zGx|()B4|+xlN1ANog++r2vj}#bYmV=9DUldjR|yyr8I`UpqV-W25ANZH1|x0nu9)x
zzZ@!#K1mH)uK<b{^hvc{AopWAXB4zD23vZ&1a>E8_<+`eVN?GA>>gOCAn3n1#F>~u
z>0bc8v<Eid9Rf-}Ogx}KLKp&K1t%Ak80zJN4kk^?j0Y`1OfD)ZE-6h*1MeP%9e)~M
zk{h24IvN$!L`unzPX~{~#HW<x7Zt}RmR2w%=jRsWq?V+n=ox^9PB2w~&OptKPXu+{
z<5TlWiYghv9ftUn(%jrihWL0S9(Vu(MJc#KMs9(i)VcBT7;R`hBL-}uhFC>GE_MrY
z^mUDQ^>YEWzvJEgLgQUM;vs?_E<p_O?mqrbjz01JZf?P@A@L!OPCl;j4Dl|JevZDL
z&agvZL8rSWLeGUoJ7^ZvMsz?vofV`OR9%8kf<=`{%goD!9RZ6X13qLn9$b+k&X>)>
z9F)U<s;z%~aY;&MUOcGDiT99OP+J$&a4af8JH{5pQStF1zRu8)14j#Lw;(>HI6pok
zF)t-26=!oaK0c|q7-kcwT?{q{sWA=aqxQidC*`8J1k_4qh))GM8_|hFJ7E{D!Po>8
z#L$K`gI;lEZb@PigI;k-5rocwvB1s90tUUj{E}3?^t@8Nf};F_)S{9~Bq4BnST{2T
zD&*+osSC<VVC5N!#Tg8GDV2G}mAMeQq=*45Q<hp(4C<C5bK;8_^omk*5<wcEtb&{p
z20id#t6o7)iC%hs2?Ll>oSMv_SCU#$!k`CEF?vP$V6W??W<YaOMoJL_oX4OC%|P+s
zOb9U&#s(PxW2aQ+CFW)(Gw4A~ODZmA&;zxYQ}ap~^ioojO4H*LixTtFQ;T8T%)GRG
z7&|d3sVKD!#>>gfONFtELH>s52MNc6_@E+)5)9f`0cw-M)~@3^uO4OxNG*&FqLo35
zO2BP45RZWYwEPRig3+*Z(m`S%469#3Y!C*m{RFLIgV~RMPCI&Y3A8{Oqz{Hc?Mr0+
zu=XvChE~%s<>2$p;T#4A2GEktZ~y=2!|Vqw>;=igXblhtwD1Q?qq{#5x>p3IAGV(a
zMmInM4CF=-6Q*ARY96S)1ZtAQ^uzY2z-ZVqA*gcj`RFh<hz6bC4chAg(+}I<0i$95
zhi>~|fT@Ggbqov)puHn7K5YL8jE2P@y8A(PgK#gj4FuB<+s^`{Vf$HN_M`iMI#j<C
z$S|b+F|d6ypyk9MDUg29G%UJ)&}1tpTtV_6b?}3@p$&CV`UZ<b3H0<c2i(4AV1VgY
zfa-(M;63_Ky&wuI4Yvl=|3J2X15^QwhH^n#!5GGe(cm@HNa^bUR02kW*0X{&LJ6oe
z-2R<t?uWJKVf0f_#6k6fD42c_8-zhS1(4kjYiGk~*uE{0S`bDLKS+NHbiz4E7IY9e
zD*X{;I8+Ekq1%5J>V8=I!F6u}NG}MZ+YjltA?(ip&8jmnFu-Wg(nF9w7>1=E82>5s
zoOVzi1c|}=0kC@&(AC5EFdB5Y8t8m<n10xPH3w+J5vC4gHVDJ`FdCGhLFc8z^uzkY
z9z^N~ow)!?yD<H*{vYg~4cL7euw($U7Zwkzq2UkH58Kbypbv5_0|R>cgXxFSpnfVS
ziedU0VEqJW!2z=eVj64<6pY8fAPwEX2Gb9_Z$JQtepq=1GeH5|?`44B{{a(+>DPt{
zKxvR$K};B}3Dpl0L&nxn`_cUm(+5*)fkXdpsQzeB;(#fJhBXqG!3BqYG3dTRYv_JO
zm>zWdgK+2%gkEg&4i>Ob1JL!yLG?qO3suFyU=LkmsRP>>36+8AhtZ(^Jcy01KO1yL
zC<6mS0W4$V&=1m!rUb0=0cf=<s6K%DAJh&2E!>2qJ6Qb*8rMSeB3OS0bk!z1nk2|R
ZumUIn8pc9X0+z{-1yc-_Xd2MC3;^qZ25JBR

literal 0
HcmV?d00001

-- 
GitLab