From a4cc026e38da0a35e6f8238e3581d1f3a2cad170 Mon Sep 17 00:00:00 2001 From: scheianu Date: Wed, 6 Aug 2025 02:27:50 +0300 Subject: [PATCH] changes --- src/scripts/install_offline.sh | 36 +- test_centering.py | 143 ++++++++ test_image_display.py | 54 +++ test_imports.py | 38 ++ test_scaling.py | 97 ++++++ test_touch.py | 230 +++++++++++++ tkinter_app/resources/log.txt | 325 ++++++++++++++++++ .../logging_config.cpython-311.pyc | Bin 1379 -> 1379 bytes .../python_functions.cpython-311.pyc | Bin 14937 -> 14937 bytes .../tkinter_simple_player.cpython-311.pyc | Bin 64515 -> 117855 bytes .../virtual_keyboard.cpython-311.pyc | Bin 0 -> 17542 bytes 11 files changed, 908 insertions(+), 15 deletions(-) create mode 100644 test_centering.py create mode 100644 test_image_display.py create mode 100644 test_imports.py create mode 100644 test_scaling.py create mode 100644 test_touch.py create mode 100644 tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc diff --git a/src/scripts/install_offline.sh b/src/scripts/install_offline.sh index abe4e2c..19d8b40 100755 --- a/src/scripts/install_offline.sh +++ b/src/scripts/install_offline.sh @@ -5,7 +5,7 @@ set -e # Exit on any error SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +PROJECT_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")" echo "=== Signage Player Offline Installation ===" echo "Project root: $PROJECT_ROOT" @@ -45,10 +45,13 @@ fi echo "Step 2: Creating virtual environment..." cd "$PROJECT_ROOT" if [ ! -d "venv" ]; then - python3 -m venv venv - echo "Virtual environment created." + python3 -m venv --system-site-packages venv + echo "Virtual environment created with system site packages access." else - echo "Virtual environment already exists." + echo "Removing existing virtual environment and creating new one with system site packages..." + rm -rf venv + python3 -m venv --system-site-packages venv + echo "Virtual environment recreated with system site packages access." fi # Activate virtual environment @@ -57,35 +60,38 @@ source venv/bin/activate # Install Python packages from offline wheels echo "Step 4: Installing Python packages from offline wheels..." -if [ -d "src/offline_packages" ]; then +OFFLINE_PACKAGES_DIR="$PROJECT_ROOT/src/offline_packages" +if [ -d "$OFFLINE_PACKAGES_DIR" ]; then pip install --upgrade pip - pip install --no-index --find-links "src/offline_packages" \ + pip install --no-index --find-links "$OFFLINE_PACKAGES_DIR" \ requests pillow pygame certifi charset_normalizer idna urllib3 echo "Python packages installed successfully." else - echo "ERROR: Offline packages directory not found!" + echo "ERROR: Offline packages directory not found at: $OFFLINE_PACKAGES_DIR" exit 1 fi # Copy shared modules to tkinter app echo "Step 5: Setting up shared modules..." -if [ -d "src/shared_modules" ]; then - cp src/shared_modules/*.py tkinter_app/src/ 2>/dev/null || echo "Shared modules already in place." +SHARED_MODULES_DIR="$PROJECT_ROOT/src/shared_modules" +TKINTER_APP_DIR="$PROJECT_ROOT/tkinter_app/src" +if [ -d "$SHARED_MODULES_DIR" ]; then + cp "$SHARED_MODULES_DIR"/*.py "$TKINTER_APP_DIR"/ 2>/dev/null || echo "Shared modules already in place." echo "Shared modules configured." else - echo "Warning: Shared modules directory not found." + echo "Warning: Shared modules directory not found at: $SHARED_MODULES_DIR" fi # Create necessary directories echo "Step 6: Creating application directories..." -mkdir -p tkinter_app/resources/static/resurse -mkdir -p tkinter_app/src/static/resurse +mkdir -p "$PROJECT_ROOT/tkinter_app/resources/static/resurse" +mkdir -p "$PROJECT_ROOT/tkinter_app/src/static/resurse" # Set permissions echo "Step 7: Setting permissions..." -chmod +x run_tkinter_debug.sh -chmod +x install_tkinter.sh -chmod +x src/scripts/*.sh 2>/dev/null || true +chmod +x "$PROJECT_ROOT/run_tkinter_debug.sh" 2>/dev/null || true +chmod +x "$PROJECT_ROOT/install_tkinter.sh" 2>/dev/null || true +chmod +x "$PROJECT_ROOT/src/scripts"/*.sh 2>/dev/null || true echo "" echo "=== Installation Complete! ===" diff --git a/test_centering.py b/test_centering.py new file mode 100644 index 0000000..a4e75fd --- /dev/null +++ b/test_centering.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 +""" +Test script to verify window centering functionality +""" +import tkinter as tk +import sys +import os +sys.path.append('tkinter_app/src') +from tkinter_simple_player import SettingsWindow, SimpleMediaPlayerApp + +def test_settings_centering(): + """Test settings window centering""" + root = tk.Tk() + root.withdraw() # Hide main window + + # Create a mock app object + class MockApp: + def __init__(self): + self.playlist = [] + self.current_index = 0 + + def play_current_media(self): + print('play_current_media called') + + app = MockApp() + + # Test settings window centering + try: + print("Testing settings window centering...") + settings = SettingsWindow(root, app) + + # Get screen dimensions + screen_width = settings.window.winfo_screenwidth() + screen_height = settings.window.winfo_screenheight() + + # Get window position + settings.window.update_idletasks() + window_x = settings.window.winfo_x() + window_y = settings.window.winfo_y() + window_width = 900 + window_height = 700 + + # Calculate expected center position + expected_x = (screen_width - window_width) // 2 + expected_y = (screen_height - window_height) // 2 + + print(f"Screen size: {screen_width}x{screen_height}") + print(f"Window position: {window_x}, {window_y}") + print(f"Expected center: {expected_x}, {expected_y}") + print(f"Window size: {window_width}x{window_height}") + + # Check if window is roughly centered (allow some margin for window decorations) + margin = 50 + is_centered_x = abs(window_x - expected_x) <= margin + is_centered_y = abs(window_y - expected_y) <= margin + + if is_centered_x and is_centered_y: + print("โœ… Settings window is properly centered!") + else: + print("โŒ Settings window centering needs adjustment") + + # Keep window open for 3 seconds to visually verify + root.after(3000, root.quit) + root.mainloop() + + except Exception as e: + print(f"โŒ Error testing settings window: {e}") + +def test_exit_dialog_centering(): + """Test exit dialog centering""" + print("\nTesting exit dialog centering...") + + # Create a simple test for the centering function + root = tk.Tk() + root.withdraw() + + # Create a test dialog + dialog = tk.Toplevel(root) + dialog.title("Test Exit Dialog") + dialog.geometry("400x200") + dialog.configure(bg='#2d2d2d') + dialog.resizable(False, False) + + # Test the centering logic + dialog.update_idletasks() + screen_width = dialog.winfo_screenwidth() + screen_height = dialog.winfo_screenheight() + dialog_width = 400 + dialog_height = 200 + + # Calculate center position + center_x = int((screen_width - dialog_width) / 2) + center_y = int((screen_height - dialog_height) / 2) + + # Ensure the dialog doesn't go off-screen + center_x = max(0, min(center_x, screen_width - dialog_width)) + center_y = max(0, min(center_y, screen_height - dialog_height)) + + dialog.geometry(f"{dialog_width}x{dialog_height}+{center_x}+{center_y}") + dialog.lift() + + # Add test content + tk.Label(dialog, text="๐ŸŽฌ Test Exit Dialog", + font=('Arial', 16, 'bold'), + fg='white', bg='#2d2d2d').pack(pady=20) + + tk.Label(dialog, text="This dialog should be centered on screen", + font=('Arial', 12), + fg='white', bg='#2d2d2d').pack(pady=10) + + # Get actual position + dialog.update_idletasks() + actual_x = dialog.winfo_x() + actual_y = dialog.winfo_y() + + print(f"Screen size: {screen_width}x{screen_height}") + print(f"Dialog position: {actual_x}, {actual_y}") + print(f"Expected center: {center_x}, {center_y}") + + # Check centering + margin = 50 + is_centered_x = abs(actual_x - center_x) <= margin + is_centered_y = abs(actual_y - center_y) <= margin + + if is_centered_x and is_centered_y: + print("โœ… Exit dialog is properly centered!") + else: + print("โŒ Exit dialog centering needs adjustment") + + # Close dialog after 3 seconds + root.after(3000, root.quit) + root.mainloop() + +if __name__ == "__main__": + print("๐Ÿงช Testing Window Centering Functionality") + print("=" * 50) + + test_settings_centering() + test_exit_dialog_centering() + + print("\nโœ… Centering tests completed!") + print("\nThe windows should appear centered on your screen regardless of resolution.") + print("This works for any screen size: 1024x768, 1920x1080, 4K, etc.") diff --git a/test_image_display.py b/test_image_display.py new file mode 100644 index 0000000..f221d0f --- /dev/null +++ b/test_image_display.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +""" +Test script to verify image display functionality +""" +import tkinter as tk +from PIL import Image, ImageTk +import os + +def test_image_display(): + # Create a simple tkinter window + root = tk.Tk() + root.title("Image Display Test") + root.geometry("800x600") + root.configure(bg='black') + + # Create image label + image_label = tk.Label(root, bg='black') + image_label.pack(fill=tk.BOTH, expand=True) + + # Test image path + test_image = "/home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg" + + try: + if os.path.exists(test_image): + print(f"Loading image: {test_image}") + + # Load and display image + img = Image.open(test_image) + img.thumbnail((800, 600), Image.LANCZOS) + photo = ImageTk.PhotoImage(img) + + image_label.config(image=photo) + image_label.image = photo # Keep reference + + print(f"Image loaded successfully: {img.size}") + + # Close after 3 seconds + root.after(3000, root.quit) + + else: + print(f"Image file not found: {test_image}") + image_label.config(text="Image file not found", fg='white') + root.after(2000, root.quit) + + except Exception as e: + print(f"Error loading image: {e}") + image_label.config(text=f"Error: {e}", fg='red') + root.after(2000, root.quit) + + root.mainloop() + print("Image display test completed") + +if __name__ == "__main__": + test_image_display() diff --git a/test_imports.py b/test_imports.py new file mode 100644 index 0000000..7986826 --- /dev/null +++ b/test_imports.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +import sys +print("Testing imports...") + +try: + import tkinter as tk + print("โœ“ tkinter imported successfully") +except Exception as e: + print(f"โœ— tkinter import failed: {e}") + +try: + from PIL import Image, ImageTk + print("โœ“ PIL and ImageTk imported successfully") +except Exception as e: + print(f"โœ— PIL import failed: {e}") + +try: + from virtual_keyboard import VirtualKeyboard + print("โœ“ Virtual keyboard imported successfully") +except Exception as e: + print(f"โœ— Virtual keyboard import failed: {e}") + +try: + from python_functions import load_local_playlist + print("โœ“ Python functions imported successfully") + + # Test loading playlist + playlist_data = load_local_playlist() + playlist = playlist_data.get('playlist', []) + print(f"โœ“ Local playlist loaded: {len(playlist)} items") + + for i, item in enumerate(playlist): + print(f" {i+1}. {item.get('file_name', 'Unknown')}") + +except Exception as e: + print(f"โœ— Python functions import/execution failed: {e}") + +print("Import test completed") diff --git a/test_scaling.py b/test_scaling.py new file mode 100644 index 0000000..5d62495 --- /dev/null +++ b/test_scaling.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +""" +Test script for full-screen image scaling functionality +""" +import tkinter as tk +from PIL import Image, ImageTk +import os + +def test_scaling_modes(): + """Test different scaling modes for images""" + + def scale_image_to_screen(img, screen_width, screen_height, mode='fit'): + """Test scaling function""" + img_width, img_height = img.size + + if mode == 'stretch': + return img.resize((screen_width, screen_height), Image.LANCZOS), (0, 0) + + elif mode == 'fill': + screen_ratio = screen_width / screen_height + img_ratio = img_width / img_height + + if img_ratio > screen_ratio: + new_height = screen_height + new_width = int(screen_height * img_ratio) + x_offset = (screen_width - new_width) // 2 + y_offset = 0 + else: + new_width = screen_width + new_height = int(screen_width / img_ratio) + x_offset = 0 + y_offset = (screen_height - new_height) // 2 + + img_resized = img.resize((new_width, new_height), Image.LANCZOS) + final_img = Image.new('RGB', (screen_width, screen_height), 'black') + + if new_width > screen_width: + crop_x = (new_width - screen_width) // 2 + img_resized = img_resized.crop((crop_x, 0, crop_x + screen_width, new_height)) + x_offset = 0 + if new_height > screen_height: + crop_y = (new_height - screen_height) // 2 + img_resized = img_resized.crop((0, crop_y, new_width, crop_y + screen_height)) + y_offset = 0 + + final_img.paste(img_resized, (x_offset, y_offset)) + return final_img, (x_offset, y_offset) + + else: # fit mode + screen_ratio = screen_width / screen_height + img_ratio = img_width / img_height + + if img_ratio > screen_ratio: + new_width = screen_width + new_height = int(screen_width / img_ratio) + else: + new_height = screen_height + new_width = int(screen_height * img_ratio) + + img_resized = img.resize((new_width, new_height), Image.LANCZOS) + final_img = Image.new('RGB', (screen_width, screen_height), 'black') + x_offset = (screen_width - new_width) // 2 + y_offset = (screen_height - new_height) // 2 + final_img.paste(img_resized, (x_offset, y_offset)) + + return final_img, (x_offset, y_offset) + + # Test image path + test_image = "/home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg" + + if not os.path.exists(test_image): + print(f"Test image not found: {test_image}") + return + + try: + # Load test image + img = Image.open(test_image) + original_size = img.size + screen_width, screen_height = 800, 600 + + print(f"Testing scaling modes for image: {original_size}") + print(f"Target screen size: {screen_width}x{screen_height}") + + # Test each scaling mode + modes = ['fit', 'fill', 'stretch'] + + for mode in modes: + final_img, offset = scale_image_to_screen(img, screen_width, screen_height, mode) + print(f"{mode.upper()} mode: Final size: {final_img.size}, Offset: {offset}") + + print("โœ… All scaling modes tested successfully!") + + except Exception as e: + print(f"โŒ Error testing scaling: {e}") + +if __name__ == "__main__": + test_scaling_modes() diff --git a/test_touch.py b/test_touch.py new file mode 100644 index 0000000..ab3b82d --- /dev/null +++ b/test_touch.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python3 +""" +Touch Display Test - Test the touch-optimized interface with virtual keyboard +""" +import tkinter as tk +import sys +import os +sys.path.append('tkinter_app/src') + +def test_touch_interface(): + """Test the touch-optimized settings interface""" + try: + from tkinter_simple_player import SettingsWindow + + # Create main window + root = tk.Tk() + root.title("๐ŸŽฎ Touch Display Test") + root.geometry("1024x768") + root.configure(bg='#2c3e50') + + # Create welcome screen + welcome_frame = tk.Frame(root, bg='#2c3e50', padx=40, pady=40) + welcome_frame.pack(fill=tk.BOTH, expand=True) + + # Title + title_label = tk.Label(welcome_frame, + text="๐ŸŽฌ Touch Display Digital Signage", + font=('Segoe UI', 24, 'bold'), + fg='white', bg='#2c3e50') + title_label.pack(pady=30) + + # Description + desc_text = ( + "Touch-Optimized Features:\n\n" + "๐Ÿ“ฑ Virtual On-Screen Keyboard\n" + "๐ŸŽฏ Larger Touch-Friendly Buttons\n" + "โŒจ๏ธ Auto-Show Keyboard on Input Focus\n" + "๐Ÿ‘† Enhanced Touch Feedback\n" + "๐ŸŽจ Dark Theme Optimized for Displays\n\n" + "Click the button below to test the settings interface:" + ) + + desc_label = tk.Label(welcome_frame, text=desc_text, + font=('Segoe UI', 14), + fg='#ecf0f1', bg='#2c3e50', + justify=tk.CENTER) + desc_label.pack(pady=20) + + # Create mock app for testing + class MockApp: + def __init__(self): + self.playlist = [] + self.current_index = 0 + + def play_current_media(self): + print("Mock: play_current_media called") + + mock_app = MockApp() + + # Test button to open touch-optimized settings + def open_touch_settings(): + try: + settings = SettingsWindow(root, mock_app) + print("โœ… Touch-optimized settings window opened successfully!") + except Exception as e: + print(f"โŒ Error opening settings: {e}") + import traceback + traceback.print_exc() + + # Large touch-friendly button + settings_btn = tk.Button(welcome_frame, + text="๐Ÿ”ง Open Touch Settings", + command=open_touch_settings, + bg='#3498db', fg='white', + font=('Segoe UI', 16, 'bold'), + relief=tk.FLAT, padx=40, pady=20, + cursor='hand2') + settings_btn.pack(pady=30) + + # Instructions + instructions = ( + "Touch Instructions:\n" + "โ€ข Tap input fields to show virtual keyboard\n" + "โ€ข Use large buttons for easy touch interaction\n" + "โ€ข Virtual keyboard stays on top for easy access\n" + "โ€ข Click outside input fields to hide keyboard" + ) + + instr_label = tk.Label(welcome_frame, text=instructions, + font=('Segoe UI', 11), + fg='#bdc3c7', bg='#2c3e50', + justify=tk.LEFT) + instr_label.pack(pady=20) + + # Exit button + exit_btn = tk.Button(welcome_frame, + text="โŒ Exit Test", + command=root.quit, + bg='#e74c3c', fg='white', + font=('Segoe UI', 12, 'bold'), + relief=tk.FLAT, padx=30, pady=15, + cursor='hand2') + exit_btn.pack(pady=20) + + # Add touch feedback to buttons + def add_touch_feedback(button): + def on_press(e): + button.configure(relief=tk.SUNKEN) + def on_release(e): + button.configure(relief=tk.FLAT) + def on_enter(e): + button.configure(relief=tk.RAISED) + def on_leave(e): + button.configure(relief=tk.FLAT) + + button.bind("", on_press) + button.bind("", on_release) + button.bind("", on_enter) + button.bind("", on_leave) + + add_touch_feedback(settings_btn) + add_touch_feedback(exit_btn) + + print("๐ŸŽฎ Touch Display Test Started") + print("=" * 50) + print("Features being tested:") + print("- Virtual keyboard integration") + print("- Touch-optimized input fields") + print("- Large, finger-friendly buttons") + print("- Enhanced visual feedback") + print("- Dark theme for displays") + print("\nClick 'Open Touch Settings' to test the interface!") + + root.mainloop() + + except Exception as e: + print(f"โŒ Error in touch interface test: {e}") + import traceback + traceback.print_exc() + +def test_virtual_keyboard_standalone(): + """Test just the virtual keyboard component""" + try: + from virtual_keyboard import VirtualKeyboard, TouchOptimizedEntry, TouchOptimizedButton + + root = tk.Tk() + root.title("๐ŸŽน Virtual Keyboard Test") + root.geometry("800x500") + root.configure(bg='#2f3136') + + # Create virtual keyboard + vk = VirtualKeyboard(root, dark_theme=True) + + # Test interface + test_frame = tk.Frame(root, bg='#2f3136', padx=30, pady=30) + test_frame.pack(fill=tk.BOTH, expand=True) + + tk.Label(test_frame, text="๐ŸŽน Virtual Keyboard Test", + font=('Segoe UI', 20, 'bold'), + bg='#2f3136', fg='white').pack(pady=20) + + tk.Label(test_frame, text="Click on the input fields below to test the virtual keyboard:", + font=('Segoe UI', 12), + bg='#2f3136', fg='#b9bbbe').pack(pady=10) + + # Test input fields + tk.Label(test_frame, text="Server IP:", bg='#2f3136', fg='white', + font=('Segoe UI', 11, 'bold')).pack(anchor=tk.W, pady=(20, 5)) + entry1 = TouchOptimizedEntry(test_frame, vk, width=40, bg='#36393f', + fg='white', insertbackground='white') + entry1.pack(pady=5, fill=tk.X) + + tk.Label(test_frame, text="Device Name:", bg='#2f3136', fg='white', + font=('Segoe UI', 11, 'bold')).pack(anchor=tk.W, pady=(15, 5)) + entry2 = TouchOptimizedEntry(test_frame, vk, width=40, bg='#36393f', + fg='white', insertbackground='white') + entry2.pack(pady=5, fill=tk.X) + + tk.Label(test_frame, text="Password:", bg='#2f3136', fg='white', + font=('Segoe UI', 11, 'bold')).pack(anchor=tk.W, pady=(15, 5)) + entry3 = TouchOptimizedEntry(test_frame, vk, width=40, bg='#36393f', + fg='white', insertbackground='white', show='*') + entry3.pack(pady=5, fill=tk.X) + + # Control buttons + btn_frame = tk.Frame(test_frame, bg='#2f3136') + btn_frame.pack(pady=30) + + TouchOptimizedButton(btn_frame, text="๐ŸŽน Show Keyboard", + command=lambda: vk.show_keyboard(entry1), + bg='#7289da', fg='white').pack(side=tk.LEFT, padx=10) + + TouchOptimizedButton(btn_frame, text="โŒ Hide Keyboard", + command=vk.hide_keyboard, + bg='#ed4245', fg='white').pack(side=tk.LEFT, padx=10) + + TouchOptimizedButton(btn_frame, text="๐Ÿ”„ Clear All", + command=lambda: [e.delete(0, tk.END) for e in [entry1, entry2, entry3]], + bg='#faa61a', fg='white').pack(side=tk.LEFT, padx=10) + + print("๐ŸŽน Virtual Keyboard Test Started") + print("- Click input fields to auto-show keyboard") + print("- Type using virtual or physical keyboard") + print("- Test touch-friendly interface") + + root.mainloop() + + except Exception as e: + print(f"โŒ Error in virtual keyboard test: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Touch Display Tests") + parser.add_argument("--keyboard-only", action="store_true", + help="Test only the virtual keyboard component") + + args = parser.parse_args() + + print("๐ŸŽฎ Touch Display Digital Signage Tests") + print("=" * 50) + + if args.keyboard_only: + test_virtual_keyboard_standalone() + else: + test_touch_interface() + + print("\nโœ… Touch display tests completed!") diff --git a/tkinter_app/resources/log.txt b/tkinter_app/resources/log.txt index d6a140a..5576e56 100644 --- a/tkinter_app/resources/log.txt +++ b/tkinter_app/resources/log.txt @@ -859,3 +859,328 @@ [INFO] [SignageApp] python_functions: Starting load_config function. [INFO] [SignageApp] python_functions: Configuration file loaded successfully. [INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=192.168.1.245, host=tv-holba1, quick=8887779, port=5000 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=192.168.1.245, host=tv-holba1, port=5000 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://192.168.1.245:5000/api/playlists with params: {'hostname': 'tv-holba1', 'quickconnect_code': '8887779'} +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-server.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-05 19:12:35 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Loading configuration in settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-server.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in settings +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-05 19:12:55 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-05 19:13:10 - STARTED: SampleVideo_1280x720_1mb.mp4 +[ERROR] [SignageApp] Error playing video /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4: name 'ImageTk' is not defined +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +2025-08-05 19:13:16 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[INFO] [SignageApp] No playlist updates available +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] Loading configuration in settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-server.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in settings +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-server.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 01:11:39 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 01:11:59 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-06 01:12:14 - STARTED: SampleVideo_1280x720_1mb.mp4 +[ERROR] [SignageApp] Error playing video /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4: name 'ImageTk' is not defined +[INFO] [SignageApp] Loading configuration in settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-server.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in settings +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +2025-08-06 01:12:20 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[INFO] [SignageApp] No playlist updates available +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 01:12:40 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-06 01:12:55 - STARTED: SampleVideo_1280x720_1mb.mp4 +[ERROR] [SignageApp] Error playing video /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4: name 'ImageTk' is not defined +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 01:13:00 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[INFO] [SignageApp] No playlist updates available +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] Loading configuration in enhanced settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-server.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in enhanced settings +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-server.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 01:31:08 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 01:31:28 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] Loading configuration in enhanced settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-server.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in enhanced settings +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-server.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 01:51:49 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Loading configuration in enhanced settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-server.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in enhanced settings +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 01:52:09 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-06 01:52:24 - STARTED: SampleVideo_1280x720_1mb.mp4 +[ERROR] [SignageApp] Error playing video /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4: name 'ImageTk' is not defined +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +2025-08-06 01:52:30 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[INFO] [SignageApp] No playlist updates available +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 01:52:50 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-06 01:53:05 - STARTED: SampleVideo_1280x720_1mb.mp4 +[ERROR] [SignageApp] Error playing video /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4: name 'ImageTk' is not defined +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +2025-08-06 01:53:05 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[INFO] [SignageApp] No playlist updates available +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-server.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-server.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-server.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist: HTTPConnectionPool(host='digi-server.moto-adv.com', port=8880): Max retries exceeded with url: /api/playlists?hostname=tv-terasa&quickconnect_code=8887779 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known')) +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 02:02:39 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg ((1600, 1000)) +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-signage.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-signage.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-signage.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist. Status Code: 522 +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loading configuration in enhanced settings window +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Config loaded: {'screen_orientation': 'Landscape', 'screen_name': 'tv-terasa', 'quickconnect_key': '8887779', 'server_ip': 'digi-signage.moto-adv.com', 'port': '8880', 'screen_w': '1920', 'screen_h': '1080', 'playlist_version': 5} +[INFO] [SignageApp] Configuration values loaded successfully in enhanced settings +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 02:14:39 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 3840x2160, Mode: fit, Offset: (192, 0)) +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 02:15:03 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Successfully displayed image: wp2782770-1846651530.jpg (Original: (3840, 2400), Screen: 3840x2160, Mode: fit, Offset: (192, 0)) +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-06 02:15:23 - STARTED: SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] Video dimensions: 1280x720, Screen dimensions: 3840x2160 +[INFO] [SignageApp] Media paused +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +2025-08-06 02:17:55 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 3840x2160, Mode: fit, Offset: (192, 0)) +[INFO] [SignageApp] Application exit requested +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Configuration loaded: server=digi-signage.moto-adv.com, host=tv-terasa, quick=8887779, port=8880 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] python_functions: Starting load_local_playlist function. +[INFO] [SignageApp] python_functions: Local playlist loaded: {'playlist': [{'file_name': '1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'url': 'static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg', 'duration': 20}, {'file_name': 'wp2782770-1846651530.jpg', 'url': 'static/resurse/wp2782770-1846651530.jpg', 'duration': 15}, {'file_name': 'SampleVideo_1280x720_1mb.mp4', 'url': 'static/resurse/SampleVideo_1280x720_1mb.mp4', 'duration': 5}], 'version': 5} +[INFO] [SignageApp] python_functions: Finished load_local_playlist function successfully. +[INFO] [SignageApp] Found fallback playlist with 3 items +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Initializing with settings: server=digi-signage.moto-adv.com, host=tv-terasa, port=8880 +[INFO] [SignageApp] Attempting to connect to server... +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[ERROR] [SignageApp] Failed to fetch playlist. Status Code: 522 +[WARNING] [SignageApp] Server returned empty playlist, falling back to local playlist +[INFO] [SignageApp] Loaded fallback playlist with 3 items +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 02:20:20 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Starting Simple Tkinter Media Player +[INFO] [SignageApp] Playing media: wp2782770-1846651530.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/wp2782770-1846651530.jpg +2025-08-06 02:20:40 - STARTED: wp2782770-1846651530.jpg +[INFO] [SignageApp] Successfully displayed image: wp2782770-1846651530.jpg (Original: (3840, 2400), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] Playing media: SampleVideo_1280x720_1mb.mp4 from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/SampleVideo_1280x720_1mb.mp4 +2025-08-06 02:20:57 - STARTED: SampleVideo_1280x720_1mb.mp4 +[INFO] [SignageApp] Video dimensions: 1280x720, Screen dimensions: 1920x1080 +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] Playing media: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg from /home/pi/Desktop/signage-player/tkinter_app/src/static/resurse/1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +2025-08-06 02:21:44 - STARTED: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Fetching playlist from URL: http://digi-signage.moto-adv.com:8880/api/playlists with params: {'hostname': 'tv-terasa', 'quickconnect_code': '8887779'} +[INFO] [SignageApp] Successfully displayed image: 1307306470-nature_wallpaper_hd_hd_nature_3-3828209637.jpg (Original: (1600, 1000), Screen: 1920x1080, Mode: fit, Offset: (96, 0)) +[INFO] [SignageApp] python_functions: Starting load_config function. +[INFO] [SignageApp] python_functions: Configuration file loaded successfully. +[INFO] [SignageApp] Application exit requested diff --git a/tkinter_app/src/__pycache__/logging_config.cpython-311.pyc b/tkinter_app/src/__pycache__/logging_config.cpython-311.pyc index b5f8328dae97810c2351a6af9369c99252982b46..3cd240a9c46b4223ecce45de9ef7b4dfa13d6acb 100644 GIT binary patch delta 20 acmaFN^_Yu$IWI340}$-joV1ZUf)xNfAq7ML delta 20 acmaFN^_Yu$IWI340}!}8nz)fWf)xNg6$OC+ diff --git a/tkinter_app/src/__pycache__/python_functions.cpython-311.pyc b/tkinter_app/src/__pycache__/python_functions.cpython-311.pyc index b2535e92a24f0ba20fdd4f3cdc9b7cd2fb6e043e..2dc78479e3cebfe8e9b0075930cf7340ba1393ef 100644 GIT binary patch delta 20 acmcavaGkyX zjwwaErX6*g-I1r6j=N3A>V)ZZPx#H(-c=vTD4Fz36~5Y!SZuVT>8vMFvb&+j-Sc_9 zlW+I;e|4Y=0A<7o4(>2EgUQAFB&WEFGdd8 z{UzgpdRwTp!6y1~pVMEGWeWua?z<@U`}kK6yX_gtVeUc)|N!2kMD`_2^%pWjkUM^1f;leBaH&8~kf; z+SnUE-sGpeX&182*jfvs4?Jftjf_V^V(`q!*yLy^*c%c?27{+Y2e0B;d$2n=I&$G+ zYskts10?((z;d&UMY zgo46IcoMnce*a*2WGF~Cqa)!+aBOfK@5e&pksw~42}L3!;}^ogp^5R~kqcAeU<6;n zi|(n&MEk`N0WaxYM4T86#Igo{-mk;8t@UOIa? zdi1I8(|tXCN4kQidQJq#CnCYYmj_2i2hWd&I;_{<)hAs|-Ln59SuM@fKi)td&Kl{YQg$p4O zP33!1ZN=kSBPI%2v!7I3J0u)JcU(;rSs(77ibN*H6K;%xi79a?6prQ%PEKlN>WEy4 z3~9rY{pf@B<6q+TEnCReZwJ@`xcREB-yvinbP5iHF2RW~TWA%sziJ1l$-x~ba0uOk z8=*(=Aj}nV5%L0$&?|Tm=F!9ec<~|h3z!N3E%^uwgaU+xLLtH;p$K8IP>irdC_z{% zlp+iW0fc2j8Nza*9ASk}fv{4jL|7$MA*>dv5!MJb2!lcpVXaV$uuiB$STEEgY!Dg{ zHVTahn}jBW%|bK67NG@`a9yHEoqKHRsWY#8a&pK3WM~){{%OL0{0iFZEnCF&?nUGJ zyNK{U{?%jJHlVkyZQ8bAfD8RS{aRDlZ5I%8z^TU&?6{*ZvqQ+jUAA%Oz@5HaV4=Vr zXS}03x8;s4IrJn_sz0~cUgY&_YdMhGtG{76=UMK2mOH=YF5kGL@)a0&PTUphcWzt6 z1e#wg)}LETVYfw0ApXS?J=TH|Uw=ZsscFYM>TQvZWDG1-wKMj}rsR_s%k*o(HEsW0 z+uK=IKu^n;V4JbOVjt(!-^+G=F++cr>#5DZsii=?3iEsYIzzll{hj$YHJ)I@c+Kt; zX+Ge3Q=FKH0QiO?Q>W`XziQJzKW)3gn1WQ{Bmj^|bmQ&kgY9vvUY*GVU zLzlwuWhI>9(CBc&9tu-m1%sa+-EeVYEVN;A zWW&Kw_)=tIazl9J0xiJp)Z`&?Lqx>`1^}x!gvBA_UR@m7*F$2*fIb+$UA^-Q9!$r_7&J_>)rF`3a6y2c@QqY@6Hry7#*Gn(u~h*2ivFxV9MACUYGM z*CBBo+OxVCS0{4~3fCa%XE=aX{YmYn1BJGq7J3fsb^Nrd^uSKXPj|X-ZCNt15s@t! z{~KE}rfo0cfqE<$ONRc0eg%6f0J5Yp786UFtlN&%Q~< zC0D25vf``OZ_H#pQZCs-&O>u?toeOTa9dMi`Jnb>$9Q4A4fKKMIkd=3){H}No8N-w zaHtfArS(iLqUVG9XZ@~C$enfo_@}j^CAG1%Cexz7h!Q{HSEbT=*YWegg^6zec}lOHw|gW6BO_WJ4$zxrlXVaD=E7T2rFM zDwG0&!{D7p+az4)M+b*4y=PBkoxhOa)Wu}r@`G2=Q^xJZ2RncbiEa3p>86 z>cP_}cEWz;)7XL<-8(@5es5oEo=8h^!W9{bjD`|! z725`>BoaQ8aDWI)I4*=D>|+V;LI}{BkZaFiBqENSpNfDEaGpnv68yyY0H~UQNg&wa zL>}(OCa^FL42_NqT}t?j`!V+AgnM{m2+J3ilvby>oxYW=emmj1JR(FcCbBOw;x0^h zUl5150~aFU1JT-y0N%V}KZ|JLQw+%8=lC1$*L~N0QecD3ZB)3861Ne+{)T&ntB7$G z^OphYWv*G_nkBAzHJfuc-75~haqi~1*~9mWO6Rk`<@u&(p=&WB2evAKt#Z*erD)si zp?k%F`I2vyf3tky*pgE&+oqIllZ&@2#oK2O-w!su>-n~4aqsdrIoPcPyJrt7e3isk zeX^RBt12h1(!;8?=&F z#<*YoBsFF2LpCYjr;aGND=GfTo=OfQ^O8h6OtPKDbk zaXXVQq6=G<`c9eKp>R7SZilIPWUfl#swDjk(;WHJ?hX5!Z9i$w+uvyg?gUO4aQ|yG z{aW+@CK|@6dIemh-q9e82G=QmVP6qn->kBEjVsFt+@hgHZ3kM8bH(h zg^Xn}03>1>*Z(!jBDe%B6t}tWqE_!4HACwdKo?kaMo^jxiV)8LtfuBl16hb?0MLiU z6Wjo8o@m(tAgmD;u3?^wK(oQG86F%8iMxPKYVSHc~j3%-}S0)DmC0v&;g3~}; zjBXJ)`2zx92^&Db9=gaHzJU1PrX-w^(3MDED=!i`l5ia+v{r>w4AmtJTt#)AlK__q z=l+vtk0x9v2sIX)kwhdSDNzJmTw^>C$_-R~9H_H5d~xD35&jGfPn3j#oeEQf4fqi1xCVBqqsBBK!}k%qYWr2TtvYz?=>_4Pk)Mb-k6j^!L6)m`#bjkftVD=^h6BfI`d@2mve=}+eNA6 zeUuU)cVps)vxMStyHJ8>1~wy<3IU<)mXlaTz%3sEe>s=}9JKlv3=iaPT(4Q5iZ5Cp zp%VEg*(v50HP|YMVO+0Sf~+rGf-2;nWZF~M*Fqe&tUu@cjJ1^(tE#H>4jS4 zZZMUEI*j-Fhm7|Ib-dqh{4U1D`^MP7=q;idP6zTcuGcJWQ>M})r7`YtZHyUQ8@-2X zqb+c4d}-Kq&~~nL2JF4etgY!Z#?*~~(2S+2CAvdjnurA29a5SfW(;)plAPnUJjlouzwltj=64_#CbR;yKz?vgmVd2%keeU(2{Ho=- zf83YI3WwfvfO`}g#VdqY6WL(>T$~V*=@xc~&mg}~bLzLTgK?`K(8~OP;NE+VPq{Op z3lpK>6FuS;JOElfF^UEAB9_g~tsYhi@f^MI4}yjNa_Br3z6;{S6joL32^d--^@%u6 z5p&N^h(btY__TNiPsFnnJWubk!N>|vh*Jc)e)0Mr22Y8hms_*M0eY7+G%*G-i12{$ z4iZg>;DG@>ADtQ-7bo!SSJbP&czro|ig;hYVtIW1UosK~wcXq~7}~y(s=ZCv*|`;q zJLM{Vg#udU#a9qmmJR~uG-N-nL-3Yu1Vio|&j?vN1^_tkFWdjfJ#C-P`kkyB-ZQrM z>?o;`(|c&UL{`Vfg#A*&{&JWaQzsWd^nm*mL3JkgM)zc-8Zu!B9lM$QBfPgGnS7aw z*NWg(o0NA>J-^|cx6f}{&X@K-C+(zj_NBR6^$MXlg4hpe1!0Zc2ZSd0i`Tz5MWgB$ z-~7fuF28O_m(W%_&u`m#emgGCpWiV&6#8|VN4$nFh}S9jZ3LDU5nsoXU$ZIxigKQ# zfNH3Ypto-X4?W#;7Ud6hZXMb(L>EJy8@F$HK!XE#T*?rjfy~B%_}|bK4Oj713arCa z{AYOffQCn3YYD>z#TO_Rqgk_0clVq*bWo&TNw~l-9110zhfj2$O=N4ro;(nvFOPr> z9bj@R@NscJa6U4ga9$8c1hIxv=0_k`0`^A?N0phIZ~;dh0}-2i#1eVN(T93g?3%Lj zPC(E|ge>E@GS0Eed!?6thHHkdfHA2G@)8`op?3{~f-n#v7&R~)3JElyajPSy11d~v zb*R*_SH0EbRf%j3Vwp#~7(#WTt&cp+|9eCa{|7)i16Kv&c%vuo3&ef?dxga}cLH-H zNAtGRf+YNLR+`JT69hA((mf?Hz2Epl+165NIda^5*5 z?;M&#i%Bg}p|wQC3ddUF@x_;xUSchw5!on2#=6}+`D<1Un0}8@wJNk&9ji~1QJ*TR z4}#CGj}}uU3)G%1Tj8o>T=l}H#mAQ(m$+(~>r}W-iR-k~C$4ovMsD^2q9}2 z`VGj_q2>8clr{?NeI{qxHJ#0_xM^-W=Mu|JteJMqxGh{|$21p39a1>Y9^~VR0+|q; zQIvKjS8&bnQTi}D|sn6LcczDkjKWg8N7d`SA zS!?|MCVMnxT&9h(U!w(ExxsaqkRD)r>^K9_W+=#nq$KuLdFLvcFN_Qihe&Q4B)KQl zfb=x&!DdK{o4bO&V9iH}JwF(p3=KtsOwp$;h$TA6IP$^sgJL*1G8`PoQVm+7WfTj3 zNQ9yegqNcrBXHGf&31Hj?Ru*l<~%Lyk{1_;<-7@WO)67&ushyQ*J7T#i(%=mNwIBhYyoz#|Yc zDDJ=&?e}V!=zM)R7{5%~05LWVDWoE~J5V#VRMB-AQLKz{{}!2tCm4>knrEwRc!vW+ zebznKbwAfPw=&>qD>BVzW^{x+|_|ZAJ@VHWV{O*%d;TefPbKjdk z_vH2GXP>`c(Y)9$S9H#vhzDvHj>&+IX=ebu|v*2BF%fX#; zWtURfHRq03wk+ai>vFza(KW{b4V&ZUI4rMKt#j^sRl$WyM6cZ`S9K{>U2`7xK3>_n zcucO`zPw4U*v%qWRDWyTH`gtUER{=*yFUp1XiP3Yp_HGPJx=&Q^)2^8<6_&gS86?c zH%AVfQUa%Dd+-T=nO?YfdHuquT)uhfCAnX|>y&i* zIcdW=x%zpf`uVwBwH&^(`QDhXRr0mQ%NrJEmHfktMGdzes8?6a{kI6>gUJ%|I^EOb=_^%9c#6HRnMs ztJi00cf9xljTR3yEL@cX8lWT&rZj+--`Cc9ZPE;pSbkbg+N?&<8*G6){9i*ln|x&h=F9TwE-uwV%5#ZV+n z0M*Jh(&#S6ey|Yf)V7R=aTFI{dr136OudqngxyY4b0Dpz_p)q3|7&eyYRI+`+$*<`Mr4H8;16_!hOt-PHE*pbB8gg$Bc+Xz!QP zB3gDk*JzU?tWDY!zD?54|C((Au7NRH#II#+6B;8xH$vir_MZ`OBd%tA;GIeN@ALtJhFGjH^%cHQkES>KKEH#iu#D4^iXN#R)0{ zR4pJ29U@hVUL#*c+kiZ~MNkJ=32m}l;on*a=A6lBsqpbwu`Sj8DdB+U#@U_EQzZuW8XN~?!pUJsv#)a@aWqk3|xpQ{0 ze2tbUv&{QkYYoxs<yD(w2Udqt^oDsp8dfYqZEB8C0Dg6i97zX@ z9S_a1E<=t_t&yVv#~+$weTE!6BF6l;*^s(!#=8C`YuG^RpU{}z*AH0%-QlB_k&qcK zHGL^_Y@6Py=sglwvO{Q2t+S;(k2*3x2h@f-#Oa=-0Ssv&lT?$LI+Dc((@Rz@?}9L) zWOf@@AhGl{s7v`?%;eWF!|N&O&b#4~bcmYAPr2bml-8temGQqRkX zW7sHm1*7!`CdS7>aFaD9KBktZqoc!fiVPyfGn0qV-10(1%%}bvbUAR){^(oVMV_ ziExBnP^vxAZM`GmFs0Di4H+kGL)(H=>|I)g4@c{|!7?6$X^mP-tvr?rN88tG2~%1v zAr!b1IhqY6_73OPDECS)0C}9S<`oK0UzeEB@BEfBu z02l)ei2|DE1G=@GrhXxYSeu0to{(;11}zJ1#Gh3=E8z->;)Iy+X^%0=53vV1dITpm zdBPPQ4TUCKy{fz+Kdn?`$!s=a9)Jn*pvo_!8Yi;DY@{ZfG`Y#{4iG}TPj4#KH>7I8 zU=r8}VPpI!inO;n9Ao*C#hul7IZu0_&Cf8kj3Hg13zd-Hg2&OV843B%u(3M=)H(cj z;Of3=1E;yFR^rN5v$EX>?Dy)n$#tDdT_;S$;=wH|!OmE)bJ=rezZ^WG1i_f9iu-~f z@A*q^=1P_Q9~_V#dtBaqTG@RXcj_topH=+NO8#d*(T&UwFe5WP)Qrr!mj|Va zZk#f|U*Y#lX{T;vc7Pd~aZGIl$_1n>AvK*~ni9PV*DG>$(xWvk)XBa^#n(9N{E*AL0XD>Q z%S{My-Yrspr6>E<3z<8oaOWiM+CHW>w(R^D?DvYwZyuL|=YAL_RI1)E+M?pF8{^a_p1ppO=dU zl%fHNogZQXon%IAtfM+;&Mn!z6M3YIkn8-}Ym_r+b&<$K|En+Z{jN?!xt- z*B<72i*0|kz7^rmi(5|acKm!_Gs1t{LgBy5cT-p%IN9m=cbzU=TV!KIvk@=j<2(RW zQUntF%^bp1eh5^8NSbC7k3c8YHh?thVWGv6ypb$RUbYvF_*Pl~)QlsYngNf7eM|p_ z{+mXJy3SZ>L4z(7(s&KX)1XrI{OC7Ro~_x@O@wM>K;SQ541r)!@x767(1e_**l0DS z10JU@%?6gDBBbK~f=@=bKAbjaW7sC)IYMYmmBj(+?*se%Z;+ay8VtV?e?hlI8!*f! zQNd6ZN;5DaruZX)@-P`3imM1TJ9Kq1{*QPNU7v9=&W!o|3tEGJ8>zrX&#eUDac}re zq13otuI*H6JC|!?wY#L+UGd8H*@HKj2{+*PnGXt=&qBn%^SH8;Zq-xf&no;`i9d^J zv%=TM_i7dN${P zI!7>16QxZ3d0bU$#ser%Gyg{V6#NJ&EmQDQJcw>wdkSWr(Tg+>e~zR~leq>M%@(B^ z8o(9t!1|TIhFD<3l4p6p9N4D>_L1r-ly7bTPjI*kX$izEeCC7jovlCHBky}$+4neZ z)l=sC6&`q1fBK|k_!)2#w~r9T17<8$#cgG-PT}e#uFm+@`t)4X+0E2fTVi~R%&$}U zb&`HQM3yCBKEDOOI51H|t@R_hvMd<$QGZ9jYs4kkkak2&BiA}}$OW2J)&s`}ru3## z7;BK}HPmIT`H7d!5Xoeln-UM^K<8&1(~d`(wVCIgkmAlj+_^@%GqxTnty($dkV@Gz z%fz7O=oH{C;#SHR?Y0|3)AsP!h3pyE8sE;`W+~81oLZyJQsSY_UigyRtaI%;uTi7S ztqJ+1wKdmhuR&mA9SqMhIK!E}H3>NpgU<@NMv4pz*cF$KT?x66Ymq@H>#GZd%^6>z zcddN1Ml&WeLtN%M2(AwZID?S@Pdp<-i5%z}!lo+J>ipE%@#5r#PhAK@7jQE8=eMo(he^;t7`7c&>TTV?Mkz7ZbG}ovR8c&G?p3I90JYo%sp35Q(e_ zcy^eC%ejQ}#fcGc8if&&l^Bk8Sn&tQs2dAZIFUo#WV}weMkg-A&k+a5dtq8{U;;Nu zUieb+G+H%UvsKPbE(7UI#S(lWwJl*QBQnErc%&enBg}G;8OLJcRhV!Am6@UMut`CN3>e}2?AhkC4t#ofN|KTJoVOdZ$9^(x_6r2-SF)VKWvffb}4ncmY=?J zRW5#9DSmv`b1&C>qx1E>*Z0n^lXDxD+{RTK=Ptb$D8B{w5YWX`0v)io@RqV*&KWN( zC9TdkcHi8+QrHqJY>`@zsd}A6pqAbX*1ePSF8^(Qv46Qp4(?Tgd*^!MMKvo$O|hb; zcw=k4rX}9cxSHc^DFHK~rQ{=#>3y_`ILBA zs*I~BjL_FGLkDbe!&VEP2*7w}I8l(%Q{x7a69i3VuzQ(M172ZVY@$Su0fAHb^%|y? zj0u?u08!YmEhI3IHqr4wV{LYb2{e)Tzf$nm6p%Ef?>(pLMS<~#8JCzbh%e%u*&)I| z;Xc}yao(+g`27u z2Q~K>dhcgu1DiV*A2beH5*QfxK1e=m$BJalZ^Sh-Y0SXFI=L?~G>nmZ87Foc2?qrk zb8hA@8q#o}>p-4RzVt)L0&o-9hSX;q0?E-mWi2YFxqf7$FQ~=!M zuPj}m2E=zpar(4F@L0dGwjxw&FR$5hDQZ4q5ML)d@3dn&3m!)7|6NvcOr)#3ld=`Q zL}I(N!&;(+{Im#o0RL;&ek?_43Npn^CB-y#7NdnNy`E7WCN&3f->+5jyp)m$P;%2) zN!9_xSelstwVP$67)mn&>;p3?OJbIm=y@)f#+d#LZ3+87N_jiqS~8~IXeiDsB)c=2 zlob4IFP7^MtYZ#@hC!@QxmydP6{jFEWqcn^YO1a9q(jjsW}{10I1dl!HZg|+auX5t zsVMUXjr!OS^-(^=F=Yq>1k2f~pgECq=4|)rvxg2wb2LKX0Zr*vXVlp-Hn|ny;L9U) zJ@GPymtKbJ3p;%#ivkA)P6T*&erz&Y{ls{9YLfIJz~Kc$YD`m!&_7zO>qy|;lqstE z-ow_X2eTMc5LGjtQZ>q=GIa^7V3KP_4u}y(N{Ad4z)gXNf?NvVxZT8zO1R-Ddm!{O zF`m3bwZ=v6HOos@C0%4yUcku0LoR|)Un`7j)4zza6LNTXngg|@~@%SvYvq<@4$ zhPMDt0*Ue!-k2ebsE~ZVZ3c?n@S}El`%z{4(OB@P6eM3zE4+od#8_ANA%OGF3rh7y z#lHzM(4w-pdfx1r4=tRQi&~VTmRYy{=+Yu2V;xFS2Obp$-rD)*&iQ@_R14db!nRp5 zBjbx#a%*C_H4tA0<&$G!tavwGwv;Uec<|l?5$S3 z)hpiSm>2Tcqq4V0@%9j*$8uq|WIZz9r0`9We%|x?Zanq+^VgrB?~%Ptinod60KN9b zoqx3N5BACHcPs06udF{5TYpG8JRz^2RMtVUB+2j73J>|))AyU!y)*Le#J4Awgyn-jIw?1u zP?}DVo56aCoex2YZ(vxxrkaL*CJ|*_hoFXN!al;`HCXT|EEyPUnZJ`6C&}Q+)siY3 z6DREeI|mG%+u2q&CHvlIU@<}tayM`mE6l!TW)5*@Y_s-R+i(`#ymM<|C|K=1w{xwz zWX4KT+fzXPU_LQe9%P`2X=X(m(>(lRHw3^sQeq-Np~j7FM6?a3U{MV6(y||bM^ku8 z##J@GGSLen_M5Qv5k_wu#2h0$;N!nXZ+$K6wY;}%R%41Jo_)<{T`^}!9AYNLj7+U{ z4;Pq6k6^#%OJBLa0!CeCeAmK)G)7cPNq~h5x}Sl9hzUy+fJdkMM}R*yCwkZv?~%T4 zj5O=lt#?pw{k-`ajCpHL*1H+!HGgs(XZG4GkTa8QHt2ZKsHcIqJHeFoFoOsfXQG$Wc1l5s3{}^NNzotA4eZ!j?@O$( zP|vSN90NO^vxh5iZ{WaqUx+@;h|yYGh4}%=nSn=+uzmdhwlLidymXqgj5-7Bw9fk( z4l|`a*_JOF_~vv^Oy8%c(Jh0`eFW?`&G9!HPqQ@Gl4EWCR5k0h0hP8Y@i+psbh!0PkYnn zv9_6j_Z9E>acm}l-=w)xWS^cE`2_WAKvd>0CABQ5$rlO8R?)jngtZi-rjk zefi0&w&k-cd!C5xc|v;fDS6M+%ATiRRV`$r)oSywk_9Kl2~x8r;*GJ^x`LL~mmoh| zea~ynVTMQ7V59}yg+XJyUSq8lvJl7MXjvhY6f6c=C1TH7%~#Ar7gFjp%C zvfiDsiDY7nk(NKeXi0UTus%&V;DklD+$TLGHVR+;O|;!GwH;BcXuHL;EA0nj?Fats zz+L-~5C812+}IdyR&GSNehUEs@}$oYX0VKk)b#{UCF`@bmoM~Vxu z%||N@PGWzV$#B9YgfQ(BxoXdIqsL1zcu~l^c%0-d<80}`G`>7AT=Jp<3@l}^#vmpod5}r zm>1r>@b-{W-65B3P)at;IpXU(mh%6gbFuSn$Na&CE#Ely4c{%_yl**c&IQ?PP2EEM zyUpKj{$9PZZogc2K&d+*S07ZW56uGDOe)ohh(wktK;=lFQA;T`u%aC4Z$Cn-JWk*T zAyQF@rl?R#TE4esF>-rGUcX0Kzb96*M=sfONBG$|exzs4DbIv(5wC4{H}LJi@0Gt( z{>HJn1M|iAE2@!4adkXUh4!fm-a4^Z{6mMbv0JX(uT<`zJG7deS6qFsy8hP0Vo0vu zs#I^Cci?;Nn^xKm$J!3x3Ew>-^GEf#273Q6rxn@>6LjG}8peez*N12|2^D4QPK3sm3YrN+naj3B@% z2Tm)2(^B9xN3CrM6EAsb`*JJ@Xvv8Eg0nTBN8794icZ zb4ZpEyi|2?sRsehJNfFbp`A_)H0{gk956!Je?sw}kTRXDEpq5vxC#>%^wq;f#~N*a zUe?`w)NZ?Lv*YHj-E*|faW}X0XtU#Por|6{yXZ+^R=;_&4n? zT$7jmY}mGtiB7gK2z`)oZ0pfNfaXI2G+rX z#}MXPbivUzesqmX)zSk)>@k_|R`_m-@3u0+&M^kq^9ujG#6PdUA|2Yr!lf?m_>(~^$(`)=^lbeE9yn$pdLwmT*1LeifsLjW=U(=p2*~m5mwu4kYZp?fv_XR^XJDJ$sAGr8q@$H88pbg3Bp$|=!>(W-nCHzX zsA`5*MvLA?x+VIaG2ivk_5{7^#8az3<1IAWGOPY%!2QYXW_TKzV5M_9-Fw(zsZ++uvAT2NGnB= zhOtni73u^aN+3D@S)MfhJtpzeTEIB-oJhD?CIe&P3mIlc7tM^OjBq%OC?OhzIRv74 zLDCByimH-^!^=CRb%*IBNy8C^hZW%wJ<8_=w5l9JolaQ{*d{}5Ms>l3a#NVnZPr{DU!HC55@l$1+@rtKs`VYNIq=^)Jg|jm> z9BE~HR4uUu)%m#QM+!J?ee*l5q{w-X_swzhTi@`>d{BYiBMi_^e&ll0LzN5xIlQic z<{3_Pkv5M9(%)d?;rnRoM+3m$MUwaNuO5#Cc4-4Fw2T>8M~r^7*}$n@W7$qsa3(eH zU>H5yKsO6vL+poPd)e6ZxJ|WfIKeHCqswezaAnq0%+g7OyCRx}qWzrZ@z> zD?ZqAQgiHxJC82z(B&UoTd)_-$kkUTnfL0h;HUQ1XiiUW_mM+*4oi)eo^jCJC^5lEfyhP&(TczpA}S3*xN7;$XN88v(O~#B2u!K{)khV56|}W7<2Z-X9E=o<)$F zz^~gCzFp$mKlD|8WD9zqv42=nar4E6GPz{EQnDW0)L{KP9AkccIs8vxOO3574SQn^ zdzZs^PDrN*q`{CfD9R0Cr6DZ)YvoldwTDVs6sGs67gIO=R`&JLER z#t9^DBHTngW%$29<2A2W^|bE!3+Il`N8UIo`x_L019`^q0Yh!h1BTk1XVTmv?y0|w z_+iALN`@NE)V)+Dm38BULl*XHIApOfIWWY)EthIWToQu+Upcbt z$UfV@-sd@9;<)QRkaaxY@o(~7xUqU5#NeSMuD-fWe{)d_0n#3V3=f>AXlW;zDW!ilptvZuwbl|dK~&q zuSsT|{M2|%(>Oa?&^z%mGY=dm>W?X{_A$3nOq73Cd>Yk+(RU+$Qgw5mqi5$3BucPr zDmJVl(G!{fY0S2;_&mk7R1kGzt^bjr=Ie;bNWT;fPfgp^ z?k-f7SgY%xz`C>vB9IRp(01&VcN|l89Fwb#se4pGH`TA?RxRYma_gkrx_f*v7<#m= z>b|>9_)<}ws;uy5V*DAIe?sA(koYHHm86;^$y}|%!K;#Xs`Me%Mn8;Ew}dBO;;4g; z-4`8o3sk1GBjYG=L`(Ehpl_099tqI>&eZ)G`}G_6VzfRZqe;(N?c1MI-}WQ+uiv*Y z68gN|)P~NpvUPZxv_^AbA{y7?M)PD}gLKM3x&!o>SqMgcsa-I>;SuuBNLW2u7n|8d zX7FOEW0v58Y9lG$rLiD{9I%PFXz5wDH6GKT*f2?ZJ(7b+2+LnX%~U4QKgU%xyEla0 z?ShGH7DrG`p#fLOPfHC&{TCE4aT6O=Y#1f+yi`DOi}K9OxlG%uZ-vIx+em;hRaJWn zZj9E$!$TfdXu9i1u_;-#RCRd%>G`LZpOK1=;*_}_h3k>@GaY)+Fkx$! zfD7xe6k9%faF{#Nx)zZQk9k-V%x7>vi>YwIC?ZJogt~_)^Ij;1`@p-aMLATx3|`fT z7-AL_X;7RxFj|*!wyP;Ln~M*rWA>^Ylj~D*>wti{$p;2GCS%I@*mB;&;5FeoK;_)) zS%UPIGXx_vo>E$_#@sGzac#+g1$eM%{p8+bs_Pi$h{Y9EO)SZ>7Mq3#*>17oOVm6f z1z`km=FhgBRLPOl@jHwdYcvrf544=a|B%u|5O&(#M^)Z?wW{U6*syf=PJ@~44$eDH z=pG=Z8b7^>kgqzpj^QGui7Gz3iBh4JX$Tb@g*KmcOBACmKE%gThfBh1*;IXvRODyfC9_;ILNdVAB|lvOdPIH}F?bNjRx3V0w=ry(OG_OAt&+X$cxE#)6(1#+%zJ zb(&dHXN3AR5tAN>tcaauie{0rU9{nhwh?_0?LmSfeVhc@goGam;94X8W*UAjv5s1s z@#0@XB~)sd^Z`?QK)is6Yk0K^Yag`keE%!zfFnqybwE9nc&5zUq_7j3H1F(uci*@7 zEp1zFP`XaY^}R}cFJWLonDydRdxgfNe$X`oeox|pdSyX>WBE-ThlpqNmpNi;JPq6x z9>pHU*b#0F8^B`Bj>5rbnD)$}>B(9J*TmL?$5FBwQ?)@g3jZXYuYuFR9Vp9jfaUoA zpe`R1FC!C9!>|QrVpAuxj{fIpCUmrEhs{UnO4^LW*nhJa-ESU5$XY#8yMO$DN2)9m^`l6X zib{}nq^0@`(k(ZoBG8d`q^0^pq;i^4(dv|Tq^0^Dq;i>3Wv3;sYvI+ZU@hN1Uux}CH!>@Rg-2jQ=6WPcze07W&ml_*O6USNQDvPuV zi9|1{V$DBdsy1j2Rk>Qzj%goD0A!`fg;_TdIP z3nOEbqalWkpJH0+-IJ3Yn68MfZV2W=qA=0#09Sd1H%3?Tg0Z}yoL8sh)y+EY=jP4T zU+zJ6}@9D7?6<7;HTR^e+UcAC?Y)uYT; zf$a%j#N>_``5wJKFgw6f*2ef+nXfkt7U}JQ>;1E;6E=Fg&?xgQ3g05JGsAn}?5zsl zDzP)e`&PsEE;i?idkbznJHG{npM-BV#(f2IL)W9TQ840G{B<#ZoywP!{0)pXV6ixT zbofqFmHO-BzeC%<22f}=VkB1&FfPPv^)M@%C;id@n}D8{fVc=9Z>Mo))~w z3oH`#7|Obmr3#?MfZ6mPaf~!pyzLT8C~h2wK|6tiYqkYm&&~Xs3OW$a5I{dH9_6Y3 z1JrCfaB*<_0+?-Z=cvtbwgqhvs7X)^4Z~{xV$fpm4=4UAEKuVOvGj1FN_#alN3)wr zM%DbOy*Zkv$J3-pWu8rY4v$2F!Oi#qg%{ki=Zv~*Y|^;%!Z*J`$9wydzJ5j|^vsaC zO4Rlw-u{@7BW87D;*31XvTc|@n1n+Hjbt`-=*$SOQsH5`WlbAFu@aQ-lUHrDL3rm% z)4^ENLAmL$(scM$6%S#&OgJ)A1x-n2Lkp6rtcW9Y^>qr8DlI9l2n=q84t;-!=m`$u zGX|+u#aCS_G>fSnZG5CE1*rn0x`+zEX|+<=Fw4a&gKPu#d#dyCo~0J4s0Sy=KlY1I z=8h@cF^M|{`GMyChp9yCI{LZ~}n z)*S6bmX9(gOotTiki;+v*ebtr{{|Z(+W$Cl>yS>K>DL0kEk@pr(8Xk@o_6$4ca-vG~yD z>X8|jWF(s&C1txe01TB-E790u$%UQGRq+rK5-TN$Uv*5KpetkOYqZ5{G)^AM-b!Y? zg$4?VJ26gb8m5+{V&F?(i#PT;=?^#e+)QUYXmcaQh_vd`L4%$nP!79(dDW z5n17`xXVo6id)ThnVZfEF-77tBpVymNI$G8)aEq{NsxoFTEW84vMzvrHgeaxrHHJR z;L0#UZW+UHlsGO-To%{iyHGMtmkzciam|HNnRVstm!1YQl<7yQyIhBnEX-pU1EmC^Ut@OMY z>v>V`8C7~l*;C8~XsfO8jWHg`PP2l|0r+Mn^Z2l)eNnhQ0-u33dzG5KG!`l)cBXeY zEo{{AAHM()56=#s*K%LuU-Q0}_nPlDf2!rawKE>(3L5TTEnRWlKklx#QTJW7G{I4vM$Wmz1O^%k&{%ntw0I9nVm4FyE;cq1Mxsh7zgtXfdORJ zyF*;gh+w){yUeU42BKj~l16zTZv$yD#{MRZ!Ml^8CugmPwKr2XCZpw-9iRg91Rr$2Jn*Q5$^E`D z!I_)d&n{cOo|8}@6x=Sf*6$%-bqGZnze*cRey*?HE>7*QHG9A%ln5oaORc(%(6e+s z!WRpSdIoNnJ@kvowsi^RLIrB+N^4taXJ-DUPup=`&-NpY_h>&H85jAY`(IhOcthb7#FEX&Q0mv9y-C$FhVb zl&0A_My~VM_{^nwXblZL$mtxR<(fxmMGvgAlt0-6CBk~4?RLAh7vSfD%lutSE{1Ok zq2u-jYdfa2xw%9eujK+Jeclqer`?~YM7KAkj%JJ%LzB=vV1&)Hx#*oO83<1A8Y#BU zdXQpUdJ17X_)4A8b!V76SFmuzafpq=;mZ@E&<-8L2)3PrVj!@M2%H@Z!cCd@?@<<} za3A#_qQ_v=fI$sM(zL1D){PslY~Hvrnp3}7pg(apVjq4mhXw1wU0mYD(9lL459kHh z*n23qvk0(TJn^QcXxab8Hy416lDz!^%};Tff@cuGyDKpp#OEnEM*&MeO0OIVXBZ+L zae^LCBG9v-q0h2_=!^EfU@yhr#npQbHNBDKtoS4%M@tXU4%kLR5aCKK(1i?Gp@?ON zvSS{quI#YEAAK-kU-y7|43*rvk^WS#+3o~S3XCrgiX(&PVW~}pM_JM0;u*?;Re>s# z@Q;kcpLK+`nY$p;26*B)MHoY%e~zj;gn#28q=eDDeW=javcaEmEEq4%7uE@QO=tbC zySB#88P@n%++B}?Jp-A78;(aSgV+m%f%-e`&;*?pK!*}!Ef^@6If>vj@4cDS8c3bs zNS_gZj}5R*>l>kOZKl*{OctBTy-NmmZwT)pwz}eoyF$PMqH@;q6Oon z`6AN@Q5|L2#oL&70A7ELAEq;=vWXJ8L#iJ~YR+ia=WXs}+J8oEO#~gaHD9{Ir!uI) zre-zMffHf%0DVa~N$@3+eLz);xQrWsJpyCQ3#STOe@DNC@*GR}6?$L*CKcW?SY&`o z2D>oy$(1LAgt%tVm0~2Ehfr;RMS2qDcAsWDWA3%+J{pZri!wESmhGC|+Rz$1PP~p7 zs9q<1>Ic-$ls5PX{J1s8v+gqIYt*_vR9TKH}6+A?|)Tual`FC6ea=6ms0S5 z`K1>8>r`+;|55P8-&*{w_hxR-XvOYpEoXaRG9aV^7w+r?q$@9nMpfnx;~yTU);x*; z_VVH&JRAX{B)ALW;CW&NB-~)|jznp}N|dVG)oL(kfOeH+rUv2*l*M_#KNGe2bD3$P?!&g6lN%u+od`)_hg} zofKsf{KXJ<;}Qp$-F3n<0_B1M4KzkZBG`_C-H3xMF20XFTebK6`Kd?*v9*-ij65G1 z7vDi-k$QxUCvl0cXaR|xtr%^565d7zZLyvR9d%t`Mg}yt<=C(KqbykR~<6PkiR~F;Sr1CbIYgagIzSzzlGB(>YGS{qd%@Wtl zo>j%Ts)aI%tCBg*?$CHVFWee2ZE1&GDFd0SR=8@3t4_uXEj(eQW(?OAt|7)XEIhkZ zzZ90aT?)5L;&!2^f%2PI7IK%|cj~0lLvraMrS#A&ALokH^1dzJieUdwnQKtE25cC~ zUXb3w!XcSkr*P{eZrz8)r8l3RA6+Vz_MDCfn-_baHdE3Gu5d{wn8GEUv!4500dafZ zK7H${#m!6mXMHl)sc@YV*ZCp#$GA8@Ep0v+uivr!)ZH?qEj?>TVuVPIa5ncowH|HH z`S$r+7Z&0E0Q+=qP`C{ew}Gq&DsFKL6-#Az3hvfPfnGV#s|0#yy>YHs)$#pK);l>% zPVDI^bK4Ydo5XF?YweY`_Qo4FEnT?Niq8gm>9Yv&S%kCveZ3LpFS91lx=2mUJl4$e z_we<=Li_S)ylKmF{hibChW4fAyGQP|th=4F)V-SHC`UsefXaP&=WHIfp>UV3a1}AG zVxbhfNXeYBF+oYn?oLJ_ms+LL-E!$}rF8d0I%d_$kzU*935qauiC>=@{EDOTdvShd zY4h@lc9Cl7m-EIuXeI>ojMSt?kr zy|Wp46&<0x5F#&x%vrEI|8?(m@7tSi?U?l%!<9z9*532Sq?Y~0X*dC9Gls_2e7V%P z+c;%zkHYPd^fOHCyXy@bY=7j0Z8xBgaR73toX`baSXtjmCN)^#NMq&*LfC5E=8p1V zM`je-y6!RygJcSW)1~J@zo{w6*#;YS+fX?q940>+eq^X_ zgt(rr2;E6Iv9WQ4VOME#i0`4cYk*#cy_!BfPoVcO@&h+p6;ExHxlIbUN#ZueODmyq z3t$9+#Ov_WEOP<4MZxsfL=*&2Wv)WuDlnDQQ^g?x$&G{1Eo!Qd{~m=RMWF@bmH8sI zxe(9X%|=vfJho34Avq1Y>5$nlW?C5{;By5VNPX zZ&+z8>m9yjVlk)WkfVRwn#Otu=9WD(!<=apz;GNAeXfz+< zWn`gS+Zp*~Pv;DiFwGV1Isl9bY=S|JGos0Df)fzssHT`==mL~2wH25jY5v-JkVV2VHh2ZW$hgQ5 zyWhd+O5_et3{8b;6ZD}Fh*F{qL3FBY9L9Pe#*6qT6#RhRaT=m`#kji4Ad`;&sEE(c zX!d2^J7*0<@mrW6A4AT9NqC>jOEG_lmsYKmZitm`kV`iyrJJw@1*%s9n__`Ya$t)R z*fQ(IQdLws&o4~LaP(zIG`VoIQn-1RyH{8;?_JEs7FJ8Oa_JViaH~?db(UlC=U#fd ze*WSjzceMc?3T;-DCK+P!o5o2UY1OI>s`*4TlUK3`;_v1a^Yi2;bXHLO2|aV+oV7@ z&V}vj@8VJQcj=1yYq(0HHNf|J?)BVj-Wy)R3s6CeuFZX4>3l!}Y0RmFngzaRqum+! z_*V$OJjoWE)0m*Pbr3UoMMmHQM>;7IG5{b<^h*rjiGN`R9Z6{zCLpQzxX4RDx@T9j zK}SkCTow<~uFL>Y$WGnBHFd3v5dEed*kmzt&C+s7--Y90C7pic(qY{-00~=#4G_3S z>!pLNN7Nl8Wt}zhO!JXTapA&Ivb-x~e_uosghPeX11`5ju;jAOutol1~7 zPoqyBnrDi=KJ%))cAkVKu;Zb5rfGF*<*d_FGxtsP)`c)BIfO3@7#6{oMVhZ0%4a6~ zm26c>impsH`@ZPD17udnOw)DK!k`M#!>SIHwpAh9&NjKTw8~>A=DA-_Ht=#tB!|Q5 z0`VVE?r0(NSw^b$dL&rcJA>_egX$i-RirdY){NRGgmw zwrGozY#qNb`!bp z*K%a;3Dj?V!3=w~B5HW!uUo#lq{jfYPI}4p)II|?39@b?sKqTv6a;QypxBLdi<(UPq)i@j{yV`FIiXL|7o1s_pBtg$d5 zcG^;{uGFMpxP}3R#?Vc%f&C#Cq3}8&oW!7Lbzih6ITV$3-#YfqV^Z_ZFIGJT$o^Kv-zw>6 zT2#cw`N@aAQpH!N_%;#kJHa&8^pFhRu@(B5%#SPlxMVu-X^F4}jom%Y66v9qXjJCM z6n;!Hoq8f{7GrmhvP62QC3;cjFDd*b$#mZH1t|JO7F`du=)-sHQpK=(%KQa|zaV8g ziGu~A9eLm)Oe6Ix2a6AGu>Gv8h{6pmN6H<4R^E*8&z&snaMN{X;7GCKUl+S@ZE;^l z!OV1|Z4RaxK1A~ypJ{I#Yi|^SjYqp0d%GIXeChz$X0BhvVbn>a5`CHj z!F5OEN+e+)>@$0d!DBV2u3)Pd+w_8O9f7<5gkyZ-a)N{KZkTS9?p#uL@VbC6BwUw8 z>~xmu=ujoM)P1y=<%65Df_=o;WFi;e)pw~(aCAfa5{olbUIxhtgR~M|4R{x=&L~Er z^vn+A7X-aY3{245nQ-maQkGA}Q(Jx?Q(zYNooU@Wwn3GP%r>H&y7t4@ahs2Qy zVPq(Y2r?XiZG4KNs0R^^Od|RpaiQ*8k%YkFMQj8^W!Da~g-0ssjadxxN!yskW+u#%(tRSX)_@_78QUwiaSpzJ@tcGo<}xh}tKNYb)3R~Dp>YA$ zCAsHU(RjVZ)P{OMei))%4AKJu@$jJvn@;Lgu(Rb^4o85f#PCxY#>q?5|*tGA#D& zDmhibUM*I^7TF(}`1vsGrO7~)r`pNEvzJB~8&>t?L3D6Pj22o14z!sHoYz&N@%y0R zkfhLEU%`rC0m>Q1;G7dYu z`G0AUeSkEE5CUG;H4*7*R<^qqTJz*w!eUjTdi8*}VVa6=T1T~jnVX~<8>-%@7;>NG zt|e7`HPF_)&5Q6$ycws=Z&COy62IjhpFh_=-#ynp*KYPAqJGr~*<6MhOD(N~)LLIJ z+hqIW>is@A{&rJX(YoK`_=(4bYiwJ@%uHKb6WqW6`Met#NO%Uw-e?L^`hf&LF!0jU z;HdgW+=<-8N(#tjf*7LUClq{#f-Mx#A|!rF!GEFPpD3uN4q*gzGhJ<=fE-4PO%#xS zJJmw<8x;8#1K>;zrSU_Za_zle2SB<~btY#Mw9V0kxFLl9W(+D<~x?m+_1e>3>yWjxE z6h^Xo?5-`VwzTlctU_1os?7-2Jz;lsuG&oDcoyf{0I{te6cxB2#WjMKMwf5ZW(0lq zY}X;cd{gLmvL~jHZ*Y+tH&b}Re%kIjfM=GUi&@z&m{|RP?Y#+j9Oro^*bQ_8g+>Et z+&9>`@B82l9soh`0x1$a#6u9s0!fGgv+sR~hQ!IX{uKMf0 z>Oa2w(}9m;@0nm$lH2pxp@WfJ=5o8W1u*A0|b2Sq7vGMF>Lk|cL2^{O2xqm>5g1^m|! zZF~9nk8taC$B5&!lXskk^MaQhry&jiM9_9XH}3*Os6@a-J^_&969JQW4$y;OqK?y0 zlLqu60G9B6zzuvUpr0=TK35^!!3?#q7+h!@+kflu zgoLzaCnkup4YVC^C1`J9Kh}3q?H>L8 z2L8XJ-(dT;X)o6wL`$bj8jMs?^YfUWYuEO2NeLEl)CLiY&chE2SB9_=UmdAUCRbSk zsfxv8S7zE}!hLjVI6<{qBOXN9_xz|ZiKU**_nD&tw$MWh6}UA5Nkf#0kS_toISuDQ z+idFE(B#C_h08+|*FYsh?Toa^f%GvP@4wP|`*#3VzX7y=1aqyHZ%so(qvOz)9rEHU z1Za(h(qs-v`IAGLIrzgpfF8+}xhg5AR?exV`ydocTNYjKCd0Fy|B&QAB>R~Qm||u$ zZ&3k&T7aTkBXPwtR}2Lzc89b(bWIhK1|qz3X)eVhpe!yM76Cqqs}Hilh3lhWeb86 zb$0RD_BM?tlI5Xcb%^zVL$`OPUi@`o?haV6ilA3b3_XdAAU43Y@?jq~+m#Em_k@ z1*yDQ<~EDmX40#|ZJSOilokssLPeD!z?=re$&-I%0CRvS1p>noo zE>ri0^*F(mln%d&uN_$N`j@@_xg4`+7pAtG4mxe7mslXmmcZ0w2k%)GWGy8xR=iuk zbXjiOE1o^an(~ayJtJyofXo2DS5nZk+3~&2aXs6uY(-i-*k1B?SRZ3?7_56dvy{fb zi#($2Gcg!=#Dp_pJn^R0#dQffA#YJ^2aF3N(lb`sSa~rQESKQ9$&zQXk*DRp*SJr+ z*FxGi(DHZm-GP-8mE(bZ&u7Ug-N*?MhBGYBGR@CWH|v{O=BKtdEzd5+!TJ{8$LzN; zWn@WJKE%y0$^t~Q>EQDXFhvCEr@9SwSd6gKoTG(LiXJ&mK6(2D3$qeT{ z*c%Z^W}(#HpD}6_dk&Q?lv_s))7@ITCORg;>QQ0M1EVHBy6Ygm(vGFXsByfd=S;Ic zqUXp;J!*XsvVs;g?fd9h(?XTC?`_{v|EAL}zM3b0vr$Kb<-WOowKm&*vT2V|zlFM0 zd&684SR`9YG_6gR`>WL?rf}A}YTNolU+;*DHTA`6qnRwmqqaHv7r|(TC^*V!Cgec- ze!AEi7Tj^L&bF*m%sTtYN+kPi`+Dh!?!jR?LfZ|vH1T*Nj;JY3LUZGVs3~>N21Yv2 zK+#Gk5n99%HKj>lZoFWR6NMS;h#rl|J~sFk;P0)$O+AdzHY4zi;*N>I!#g(A$Hp&( zT^A4oKA74I+`egW0QTSKCnl~4351^#s!;0^uHX+dY*wz=-FRTyx(H3Ug%n}WcuVFYT)`*EzS_%O|iNmh(iSZHggL7?|C-1U~ zHDW%Vhdoej9#KuDZ&6y@fW|XJgCW0%c`cc*3ml~dl0P{LygrFC_5whLM41R10D{R% z75gX}DEQd)K)ZL4%y41d$ZGilN&#a+f00#2OSy-cwGlF3n;1^JI65-Mo4SR{0o}of z0;Pr?hUP2RNgzwEuuGO@I9ag;SMC@j1T5fBq6)$(0uuzT0er|<*>onY%xeMT!f?bm7UK!+NQqV^2b<_Lt%hTX>~Ek*PN znK=Y+xC(8PNnHtzca;J4EM>%Kq4RWgfx!1^IQ@VCkDp;q8_VGml?g=z5QYaBO+y%} zu%}kY+Hj%zTy2H*VUhZ9n17xT!PcjF>QiWB1guZ;wfD|LsnYr=M}2gD0=9}*hfpnY z-W>=hjZF;mLzERnR*VtWM6LFav`VpP6#fmG7fw@*An83k0loPnx|Nxw9xS%ecWT{KhTR_QwSi24TMn?z(h*1ci^+GAXWSt!g{jOZNZbY` zE+Nr1OpRX5s|l4=-K(D;m&>+?$}2);O>+%%4UZEYNqMkbOKO3tUQ!DH?BV0BBt>n-W5pofj9k z%hkI~@55pB*7+CY@=c~*DXj$cdrmIh8Y*fakJek~Uy{qaAE&XtNle;_Ium@%;7_w0 zV1S+?iWttgt}HdkO?$=cekr?O&hDS_giMB%gGZXi75>GgZn=5C zcEpbc9hoh!RXG0f*)khm6^YZ18?wG?KJ zdq~fb-L+WDp+j*h>}{+e`axtCE#e>l5G%&#J+YV)EEc%_9`7`fVRmB_C>zXCju8i( zbHy*XtVkyiWh{i+VW7qgQI1+3bFPH^4I&-xkIZ@K>;#mT_=?A1SOfJoa^#E_Sneko z_ZK`iG9=zoj$Y;~#0oKTUafD4(9($kt=04w{%OhiPc;9up6E7jd0rTI%AioL(MeP2vx4=`XD{T~iRx9}$mR3+e7<0z(AwJ! zoz_WYb6=s|MSQWXP81B*M5-F;5jd8)3wwe(CGe$u86=|>3zbh$rz*bMR;R@1<7GP0 zGG0t05n(Vfjtth(Dh{)Z2AYD*@-+*!)*M(b>SjKsmp~Hnb*P6CD?o27ZJ& zP$`pesWm1rN{EpET30v$!5<-{5I%$CEO9s)h~m_x%Zx+_CT~N&3RZ4)S3-*xQ|UZ` z3q_@K4p)&!EJsjwZm>O~Dw7jK96UA#4y5F=F8=6!cJ?D>nHH#^8Cuiy~`W-ipS5a9DjEC z__N~hMd|n@`S>Mq<6ddwWqIS}TdMxfx2RHav6g^OWcrZ77QOQol1L+kK(J6sqYa3K0yKRr5KLDy*>|M5cY<*G zE#VX;_0Z_GA$W5N7LPPtYHDEARipBxY2*c{kB^Nsp;GAUWEd@JAyI?wBNM{pmN0h> zf9Q2#jN0Yev}sez+i{Acv4iOHDPlN0e)G%!v%h!b`Oym_x`-}Vw2#N|8ohV}GQH6N ziVcuW6zWUKf?hTG0O;c_;WWi0SyA$$y5=Z#9h*3R{zjwvYGX@lF#V}1h^x>!^a=e? zuiFy#!LI)TC|!1oYC0Iq2H}ieV#Fkg;9xHe#R15|IL*D4V5<9_*G)a|AB0YQu#lkI z^Y$KR9*WQfjKU=15;!n*0kUClsg=WUWqbmKwekDdf`v~5VC+snC78U$A#@FMaAc6G zI*~2hqNL6nC`M00reQQ_gl7pT6e}1Q%o7vFKm6ganR1@|;oNwBbmY2l2noX}I?2VH z0Qb|qc!=4;S?U8^GdICQ7hqc+&QR};j$Z>|$yg4|BM+m0^>>K%0XkQ4hXaZcy+wqk zwha9-wN4E=+l@g2dK(n6;x#8pnFdr%pK?h)fz*e|>WF1kNmho6Qm-VX45}hzq$mzv zchr|S?YFQOWd&#>)+kZGf2Tr>cHl{{@rf3M-=OLL1H6an|0pZxPXFvFM*T6$E~`(< z>XWnjW|9c2_P*-9{j^xwHRIKZ3gF-wS$FbhHzOok;o>uLZLj$BX)*nblzv7|KQoi? z0689<%U|4b|M@?fR>-WIa{2c6JASxTJb6Jrz=NF3zDOQk0Aa=eIFs}U^v$NZK7(K? zJRlVwkP8n0Uw+8tDbmZ?t77A2{gk*-nHv?kQD#TZB&8?BhHdu;83m*|QD@JHnwd{p zNMZC$m&|pETo;h@+`^Td=H;Ab5HjNKbD`$pkKkVA0#ykRq!2vBKtF|fPEQsaciwLf z)$fNAbP{v3P9bNVNfdIHL37&qlZ(&29~Y``)f2ZkIkNLtvKp7O8o?eA zcb*6}>_h3<2PhTbOcK6sK@lA3)H3SqkleCg%s(LIACU78%%p}m_{Jd#@7FW#Ws&ljN@l}yW&_puSg5{PuHSJ#>yHZGKPB%vfg-X_Q4xUTHo&0P(ur16T`Q40 z0XPSk&6&H1fM{{=XUrr^+(DT;C~^lwTsl!wvwP>uXW)ILN#>eF?TnpXcSTdAjI&R(N!R{`)ipr#x8U7lc)0vV|!a|}IPXw0dh~X0? z9)b#+n`v0}=`}^(`t`KSQfrTal}2F7BqGAv5_wo^tYxjKKr3bQIkEcOa^Iw)w2)`T z*4I%tof2gN?bYgLjD-YC`Kyfu5}mExKYATNd7>1v@*R{Sir#V(_0{V*xAQFK^Ub82 zo}0yOi{ESj6UVyR~u7l(`oCdgR#C;N6tBnsv3+c-?XpSaoc&Wg^jE9n;ADV zExl)q__TG`E^9jLiE398SvyM|bRp_=)^rAHp?~M;^jLMW+&6tq+j>%Ktl^e7Onq;; zZ_0_;VAj3NE!2Ml=;%8-Z|G+BboM%0ug^2fj-Zd4g$C*TQDyXDF5k{~ ztgH7rjo#zC7B+qZ>c{WkzjEBnn})1F`(^$c;~Ph;^!z3;Mm7g4?3^Nvu-53fsBEHN zdyn`Gy$TJ^*hGVj1{G?trdW9qAOI0O=IBUZVr+`2ykI3LT2(x&l?7j}>QkLNrSO(W zoGlzfp26gkqx|G$f6cWQYPT>h4ssp3ZsH`gZf{2c#X;2Ee_ln$Lk!`;4O?H(9XnqVe;&^o$R{SRU1D=gMcwC`g@Uk zdskODeq+}rJfKO^pOo)J**>D4HgKFQh6> zQ*AyAP#X_PIlVSTD-@c?MhQZv1)C3ngGBOQ|8U?Mv04N&p=j`f;ov_HF3}Y~2>5`1 z^rC-!WP~5#Rf+o)%^R>n{s%t=UJJIy$OVjwYvjTQUJAzi#3Vwq6b=ybd7J7(>OUWR z?ha#)DWThf_4_W3Lp#G(A^21nnY?gW&rQjO=}2Ed9{PcHD_qM4T&&+Uw-&(78O~I_ z=>?Q;#iE`WjwH=|$8FKs4C;5Y2rsLpB=b`1!LsI8qx%2QXg}+$q zVIH-?)Ybg|zd+yA82c<702nExtDlo@4xd;MK(!N>xEN9!xS?dzE@Jrdo>j zOYwLO#;fv>45cQ<17SDCT@64h1b@&dtR(8Sl0J#uM~VyTZI!7fP|JxY2jeb0RQ+YA z>0?1{fawOyFF;%7vj(@$dZn=LI?;Ksz_;27s9efubL!t=mks|nd;R`a%K}eNGG)zdN_ZZ z;ArjqE!Q9Hey{ib^+lJ|a#(ITEVdk0dbyD)YNW^=17iMRDgUsXf7sm1ZTH|80lc#s znX3`Gn#V3@CgafQa3&FbUJn;nal|$Rki1nh2WGS95<(d{D;f368TIo6O9$T17LS~e zGET}FCue#>-n1|DzuNys+1=`S=c03_U-Gue-Zqh)$PUgca$A;jTNX>iU1vfqqxgh* zSLhQ0&Un#prRDd$KiVq}o{|U8iqDKm2d~NpuZrz2EOxxRNp9~KaRy!x{Wm244cUK# zqS6&V$}51&@1n)Sp$bLmXkJ%8Vroq2wEP|DwEP{=+{xcDlR`{Y@DR!C=hw^bRluXP z$s711a2_=!7uI(LhoyqUa=~Gfk_&t5DaPVeIgcvQHfn=ycQ&}BA2BF- z8)x>XK5)pvr!x{$nhNUqtfTn)%IJ)yeYq1MiK3zyEyt@}e=Ths!St0uYY zsZir#Q9B=Jd-9(`-3b1K!I^!Ja~vr-Ul@3GfSjcNcHFzJnE~DDjxwg|#P;5$d;pxG z$_|6G&aTAf9dh|ja&x{LITJ*W1J3M6m#5^aZOi@bjCZq^_EP(LWpA(O?ZpLHz9#LW zRXZM^3))4h7LD?`c07)A)a;52RqqT{*1~3|SgzcmTouWc-J!;o$I0%(wvQYDKOr!a zM%rND=o81DRs@!%>U>?~YH>!|e-e2C;>z*yZvm{w{?n@M3!faiLW<26(;gDD2qJhY zi5=0&8oPxv+y})SW0um!n?rheYT(Lh=9V%_kYFI9`)WdPF~_qq60ZS|{)Iq_}_zj%ty-kZNWA zGKG^^B_J}Rja})sFe!BQJBu+0q|ji>!sgjvAH?vz3r2kg`cqG5Ez8ExS-mWsxr83j zSwxl|fT|P9($oC{Wf6(Yj#bLaLRoq`ds%!om>4-=DcICqH2r6toe+hK@xfPro#??` zs;YDZ7b6Qb1MT^;|JaT33zvn7and)`?aIFMv61 zg#+F~wYCU*~4{!qz;ul_rhIttBrmTkmBHAbH**!5aHZnYZ0<4w{trkP97L24x zQxR?EA`D75;j{}>Cpa5Komh%g>e3+);ld62jWwCpTtTOMgwIhqNdbHlRgzD=z%E%- zF$LvUQ2j3IlX}~dtkysqAr|_1JFU&vG5dZV5&bWO>T3ex`Ejv(Fx2oA$%mN~8E_^E zh@>tRPZH~U#lEwIix28Z`&L5Qw-VC6)g*1E%npYd4p3$+t_vU&HkVi4Yh2{TvaM3t zR=I2|VU-)0imhV$EY|eB?~?n6B<@+6dsgJ0eYBzU?oGHA+ptO6uu0yqi3LZtywG!h zP~L+$KBr~ww8)))RN}vTb+JM$*(jB4luI_!3x$>!_S~P8_nwxxGctEZ)XvDgi)KFC zy9k%~|L@*q*()$Um1COh95Kd~V^!5;Qokj9F5kHnm+9|x;&Zx9CG6BA#-~yKlZm$~ZZ`ZYrs06V zxYEpCkz`9SU9)n2g?W?(UMypG8^)2^9g{t$UPjnO%wiCSpP>R74|yMIr7^q>b*V31y^4Eg^6Da-rbK55^wZnt za20kwt;W@{BTycE!yzSbVK`aCNQvJHKmM1PksnB7xRYT&brs7f(RMbXm|%5u91B@l z?F^sBAP!JH*N0!togocKH5%5>k6wY*!i>ts7qh@CdPZ(NC}tm$vJc7Ghs-8rgY$`G zPNrHHDXhr?v23%>nk0s#!lYb}Y%RNr4KtNMaIRyE;%ycG=czcYuTB36|A5_=gyS@lTM`wN)6gu;}kVk&k zOv=O9A^(V>hA`}*igv{^Zwy$U$!@Qu14d!}a?75O?TT2|52|YJT?&;|JgBI;xA$>o zQhwt{4uGE!fUlbrIG#lXy>sW5dfz)Fqm{a4Al0ykbWQ=Ojy+DQr1v#d!E^qm+`Lod zHb~qqncF3DyVPflPYH(Hx6dzJTH+b6vPb56M6Smi)R2SS-6VUc+VCNA9?nPyTC?tBrtY`TD859z>Suyk=t!zmfGsKL@!o{2gc`-4;EcZ>wjvbMWjiT}C3mJCA zz=E)tYXVy`ONp^+l5L=A5jBaa3ux~TKIbMEqbBjwoCR6Xk#IhDUG+2d6m#c>HX1IF zm_^mv=&X*~M}*;Ll`%CyYn-~(nXlwu;=~Ig#jN*SFlmoKdPjYr8qir6?XTA-+l0# zpeS+`+${C+@K_@ShtPRk#C$O^#FS#9v78X)=^7dQuoOMQL?F-zvHT=4t&rK(Yv4EzCP6%Div{q{1;bKjlmRe8Gq%c;040#>ChK2@IQMmuw@c77>M+qs8hb&Smgd@LAe5@pyJmjgCz!jsD<`d-Qpx0`&2Y+?c!!Yr`td0lLsg z6QTz*0X#hl;vP^f8y7vXOYGIX|sa3~-tjZ$7B4U&z(mEifMohPQ=KLo)=c1+5UQ7PLaJ zTF?q_3lOZT-WI-YQ!#*+0nSK_ly-WCk)Fa(cyf%?vLjPI>|jw?u$!9LMTj7^4t9gV zSa2=4?JNKbUVt&H9I<^Az?~u{gJE039Kx-=#~X}CI9UYi5v?*9FpR;cV@FyY=r2Tf z{l|u%A0bO`rpwMSB*8L4d&Hv*wj4#UCs@2sP@PxvX{I4@io)$nco(kl z2+Oi*@`5Y*Jl!P?T&Bt%X$H=CjE0f6!G;Vc2he0<4x%Q)Fv+?q!&od8Is&8t;)c35ob*Ze1FD@67x8@^)e+W-(SG;3}rRy0tK} zcnAF!EnKjbnMpH|>#UYZAg4{o1Sy-(nSCY~m9trcBg zl$#fp;uw=pb({SVg7WO9Un@eM%#@2;1GK|D4{;2-_%ku7%=!cxAiPZ==<9Voi z3p+Kxi&(ox=}d9vzSUkV< zDUmDJ`JZ5c;#BZOGtNZ#4Z|1z2IKG_5MNv$US!%iB0W;sxNDey%7HNL<~_~C&w~9l zT4ll**M|!kwSY}E{8ia7M$68sV=2>ac*aVORTIm7lYlaUv$j6mNXJ;$5D=Sd7ynD( zK&}sK(rd@~l9n&B-NlCuP6e4B*nGvR4q^>ipt6@Y zqh+dXlHp-R+5On&&K#$xmMCoFuEz_iEK+zA!`Cj0B))_|`zzaN!P_Ibqry47Mz5;O zKEf9udb4paNP1`5S$XJtSAtH5$#p^7UWZt@hybcsS?A;BH9l3 z3?2r{qwjDUuE3P0{uAwQN>qeL*|~7Nc#(M+IVaclFoDma6Z>0EJNCC6a;TBhZeCX* zGFu#`m6c)*BIqF2b(0Uq?Q-)zF?YX|yI;=TZ{6M|=gSs1vh7V>*B?PbcX@Vtu~KIb zFqe_K_e3xmVzLLIylwTG$l5WsSQsj6RoD~=nzMyn!BvUu-%cD0QjpIf1^JvECXU4$ z!rjUFDr%7`b<}n$#cv|>%#n9M$~z$E9f+`OScKUIY#X-A+;)-M{xFSL3~Vv~u$(^h zS%AI^`ncs`MCIY~uOT%CL4F^)(Tz0tURH42!i%r$qqD-g~;SCE{#*H##IX(AGNAQxSJy_4PgS++h zoW;~?RAXvE<&;^eK{FM8sg>1T4bx>Z22|t;$|}zma3&ui3t`~~0TQ@;NGdvE=XI6O zY-cYY!&8L_BE1sfcj+~z5W-|Ss#b`D?$Xdx%-^CYi3qv^h;R?-;C%XF25;%BJ{ zq84j?_ATH%J+iT_nI+&xdYcRb!-)t!Has~g2-FUN)r4&v{rDM9gUKw>Tbg4v%`X-s zm^_R}tuU_1pp!X3Gn}glM^U+OGV5TKq;e~Ec=1Rac0=ML+^{*k@+&NE((VnGM&D0N zzP&h1+`tty0@M;)(Vu5NuCB^;y<*NDDQAzIvu7qbWTFiC`3y!GG{{_o$Td9jW!&Lr z3+K0liaSGv8}4qMyD1l{S1-whU7-^Hd?v8#^d?}}>2OU90OKR(m)P^F=Z(0#i8CIF z^UIuHwKie;* zR?4ZBGx2yey<+Y_sAH4du`krp9;$5$)ocn?)xkq^gIu*kxguZ9NCN-B9Fje#Ygnib zRnLn8F-zlJIVOQJ6h z+DompGQ5rAu`*<4-`OHU#P7MajLG$Z3mSr@_YU`B_ZoDG?56x89U$%_c#@klXcZo26gLO>vkhElgbKex4@hbBg8uFBgT6m= zPfM;jzY_nt18!(>6?wc8KWBbVPwblPT!6jfF1~&@Kjl_bQuni z!s2qk|B2#{fz9!+D9<XZvhV;6I{&R(s#ggSzk;37r>n&ir{PWl(s3XM zBf|Sn`=eUXTO@f8%HD&bb}G}! z+(lF?*0uX_@s+q$x;AbS14lcIr9XP72@jB1_#u*mj@SD`c!;}7gjTH|mXYMi`vK-n z&yPGs{ZN7TE&bpojYZb-F4@~9YG-82Y2ve%)8|~x=W)z-qaV#g5e*jM`^ZfA0fF}c z$Xkr=!1zya{p3w0FA#x2G*$Rh%5@aLGB^GKn?av1vKc?3W^8=Ykt;x%dpIz1k{a@F zwT1{XUHzCqAAx@d@U~l^ufm++Dmy2`yAR=>rd49>j-R2FG^hlcPXY}lfx20sO0p>! zAerm4P!^&8n&;SO@kT7hjAioeKy?FI_|6E?h&?mCa_(ZNt|`>m5vpmln7}`1Xj<4C zs%xOLp*>Vn3rqKmdKkKA)Wgm_qkbmgae*_5Vxq4DCODH|#UBgcDWbJU0eH|z4&tm=92RaAwPhiTa}5c8mGFPQgc9p}A> zF2mj&AANVG-E<}%`>FF~&az9#8Cay{z9}Rc?~1;5E5V9^OIm1hws$+!-I{i8x~BbF z*|}-IR(5VgK3HYvPI-czJM{^6?zAV^xqUHq?(|@5%$-~DAmcYF9xAxz1$;RD(070q z+*);Wg%ejR@?dyU$_|W7Lhz_5I3o5fdG*5DKZr~fU9e-gVr##?2XaUWG%K=XLQY_K z!Z3Qaim(lSRlLNq?CQPtEHYYs-;9oiMjys@cA|oUAjZ0)?D}U|xKsqhv_KNt@wR!J zW%ved48S)O*1>A%MvSi3(2a5G>Uv~m*=Ai(K_kVpKREy1DBEq}{Gead&d6=*AHBcW zmyh0GY(x1FUAcZ#Bz7M$ROC}J`{_7uqZ90~j83q_GCF~eH#O57D>i0RRTYGVXP9=tR9{uku~&_|3o zUWqrkfM4|k5LHJ1Yh43MTNyS$N*oYP5Ya3APlOaO`u#g}MdTpcT;YfG2Hp7IkT&cy zbtL2MGo;2!)Q6L?XR_d;@GBB*w~Wx=keCY0d9QE&(&jI2y#ucwaVg#U*Ae|KlCM?v zwTix0^T(N%%eT?T*)IFGi`x0vjaS+G?DGVZw)Ihb+I{2QL635IcxtkH0BGM&&>~X< z8Atn7eTXj(4pAUVD27VWVso&}Ly2lT`zq0OrTO`LRl>l~tCsG=z<9b%f>+vebn zZH-tM)PA=56I!UF&bgncw1FFFU5= z)_4OHFtq1QvJgJuU%GI|Bu!E8n4+}Noi|);g|9qFnwBsh8univc>(IFV-tcO+Mxc+ z6BJQuo@+Hr0JoW+?I>sR1nY}&~?h;aH< z)9gfVVI?PQ(fDEAHMDRh(}k#Q>zS`|vJ^z}N66>>M?*|J0yfKTFznX=Hrl zg=<20u-P^pE&NquwbWnuH5#j%k@F{i?f7fQEr*!79q0V;S9)gMv%_=Fxzex2&yK(* z`n;4?D`(Xz&&`m{H&hRmRoyw?!Ih=2INV@;MT@fDQx(>p;vMEMk3Mq-G4`yZBWj;j zDt-3h-y`!&?dGQ|l&i&fiduOGhHo2$`k8CIFE!J1z_?EU8Sln&)wc*+!VGLT-qu0Xj z$tig3#ZpDZu+JTi7cQL-Co3OQ7{U)_&(xQtKc}V?t@iD|O!fXWGNdI*-2jhCzEas& zI^%wjnrZ%|i<|LF%G@pkrf!#0x6i~s$SG7>vebjWQsGV+FlVQnvlBw_w8OWz&VK4n zx0rSq=iG~nt@mD1u9vpn|I~ZxeY(RPR(4M_I+BD+u@&Y&;Co>XIp=UA^02NNuv>|N z6j{^VbRiuL&4|O6&OK?;XM&DrTo61kj6q1TtYh$If+eMUIzDE~#7SzKdO%`^ytHFF zK`X;LrmeqFR_q)Sp##dww!UNi1(z?*7|sIY{-uM5Lqb5;bOM8kh=`DAZ7u6(Q_pDi zN3Y=0Kvr2gn&%NmM7o6O#EWovS?dnAD>2Zq@LnIK7;J{$c5vG+K~oTp-2(oJi>eEB ze_%8?V$xFVMOlJOll;d3kSw$L!gTcwvhrV1qIU^App<_G5XJXL4$Yq`+x)q}1Vuwi z-G+emD8{Q_O+Y?>PMM7&TgyVHZeyD`MDP@}UBH1OCIf{7f5PLUJ) zsSB4IFH$5;9`4Om)hK3M5{T%tO!UgfuL6(+$-I3+4FVml9MNf=NzjuTX^)0{uKsifF=f(`A3<>*t*BQ zeRSc}k2mfY8xBaB2j$FzkZz=Og?w4EuX4rLzU*t4e4VndQ`Amq$)M{Q)& zY&Tu?09?R-{h%SqJ|M${7;j*$fo|{gI7Aw=-(!M6_7UO~%`pz+6T74j(OF?r4{wuD zEQU?Z4TXlJTBv;5uulsXt0f8UdgAW2XYs#M$2Ou6B3ZmXIH_InHZOadC2yY!@4~Bgw4-NJ1Ik;zV&(O(z1HFe&4!~JITc?Qn5VBBrfms)EWR5-o z3{>0vlh9_tOCTA5ZTi^rcPg|<9Nvp?SQKmEEK>bxy(XIEaYB3&K5-O4mL0DpE7mTv zMPl{#rGUh#K5LloMtVpg{APRRGWF>0cv9rQyHzekRK2{%adAl-$m@7?z&SQF!`V)< z;zp6OBUg>^5-hgvlDOS6hq!?1sVuN)xPG7!3a*fV*+-H2EK8NXROsn(5$SFj@6c#r zNA!gliyQJXi>2|7UXK_{BJh0dqF7Y1i;~_9Z3gV%O_I0B*y%_~tzt)XN4>n8Z6a8* zBbMAm?4ul`!Oik1aHkX|sGr3t2q@|%&yNPChR6ID5tfA9flX~dkssXsRZ~D4?Jedi zVT9k}7uXi-q47zb@!=9Mmgv-8SMCN2yDn-h(Ig~ zh-SV=*E(Yze51m8IjsT4 z^|kw;cNJIb`3Zqr%Jx41w1e1m%t@JWm9A{nWb?chy$2eJAt=XC3}bmS!HJH-{}tX1 zR;;J`KcLEfOQ|dzO)(3v;$;qty~I_>T!qM0Xog?x_CiDGc*s2fTO0D1x%}A*%4u>{zIkqBP|J#EPPQ*=MyGlYa%+uyuY3 z6dR02I6LM{rE2$Rb%~BvM51JClx@>gV`b}j_Y;<#Xh#RvDBHHKu(EZu>IutE;yu=0 zT%+t{Yid@uPV+or+1@8?x6KywD?tzC>!LX;wNbJc>XqxtlD*Kn@YmYg~9g_`4o)wPUaY7Mz z)h3Mdxm@izU(Im9C*5rd*4}NfzS;0n+YV;mMJUfTc9AvnwC@g-=Nh{M_JGyvXiR|tkPJESI^VF0#cr9tbkbOR?pMEvQeIEtZbOa ztLJH7u_(_qR;)Giw68>z=Nc=~nt9q+m_FpW)(TTI*{aP};BdB?%GdIBW?2oWy81Wb zk*l#LHLSKKJ?-FYZ^pe8N9%_9TDg1OdEN0s{L_x>&f3Oc>p{e&@L!k`1n?Sl&nSwM zy6dBe5~{Hwbh1r(h1}9+v}1rJ~nDTwYPwrVh~hdDZdH^N~=qy$-agy@t% zLk}=hUf}@!d_X@B(bYq`8lbDE2>dzyWHe4UU5(K_M(FIMpX2nC1skIEk;Tju-oU-E zPxHmBMF$angOU<6KAde0sG)}S7!=;3hsmZu8p3bV9gh)7gHcygl_-ixSEXH3N>mWF zdGOSTP$7W;c}~2c_^~0{Rq%n@_{XDNg$xuYWD>ZH$_7vahpI)$6gC@dgdTkw)gMhH zb^3QE>U7a1xAd*F99eET63Q*S^P*VZF6VZDI&GzpU~#P(Air8OZYk7haJ#jKRCa(e z4lEr7i`B^S6Kv>HBB+3&K<}tSE^68>{;3xFDqo!=$B8G0g>j6)E%-uHFo7MPm{c+t zc>$h+jKRCbKk#82-uhX5Q&SUjAcW|Uv>pf_5TMmY317tqEcpRflug)xWn-0%P&PQ( zkYodqh94VeY&@|c6q6_ysM5lJB(N3VNTbn@(hah>u+r#MpgO5|7O_ z;7rPR;LUjLfCxi-&4lDZw*QOg?wp(HQ=hcWSBZITICb+))znigZj#cPpl-4Mxkpg>4ukv2m zimz(fS2g$iH-m2l7weYE5Ho0t@u6e=UqVQg6Epi&ddpT1El;Xfwu3h%k&R2b>?pt+Y=ic`- zq`HH0-9gEBNcJ5PeTOt_)@P)&2I8&Y)js9b(iLCjvJVyl-+b<^=N1c=PDoX~a#gS7 z+avq-h`v2aO@Ge!EOk8;rLK$5+&?bW9gyn|NWO!z@1W>AsDF)iDXl|J>!7+0DzDbA z_!^gejq?}3^W3+d6E`1te^6>VDmNXKe8*(pG0}HS?VwgEtxZltG)8C2N#)Jz6<__b zuYSJoJNv)2U)(q#9vPGxj>`?lCEp3zcS7`?P+v6-f&I#>_94(A)%MG^{gQ8=?As^$ z_Ngy6N@-1US`(G2j-B!qU-h!DdOqPho^N>;x82W@YWn0FW9;Y+ZIRMi<+Rqv4lX5= zjk>B8U(2$uC6vFDtvGX=<=jRvh|=LaGCm#a4FDKK03Jtr_MK#P)DVNH77r`{D^z+W zR;ct$JV?(()X0=fnja@6?}wQ#jY^KDk*g%s2mF&K)EjOZnjNfkZDjJ2uU+=Fi@tWXo~EJL z#!_k{5i?9xwNg`>I}v6ovqw(E)U{K6$(ugA9L}EyQOJ zc@L#Kew3bkd{g|7iu#j}x5xju-Hjg>sU;SAg?;&#xO&}@gnwpY@Edsi4*o00P3L%0 zITVCO9XFj%JI3P`^v|O10#ySmX)919No-`wF$Y8<^01Zy*>T)9B(mjeXKGTu22*o= z`MRRyYm+#$`syswb=Ef_O1?HTT$V5OHapgtFBc_Wn|V9S*C378*AJd3`PxZY>R*FA zUSGc6DEZpSS<2TSk=K`RYLt9!Y)aM-2ARCRe0@>!O^-5u4N`f1`DR4P*Uqe@elVDo z>&rJQO1?I>r7(zm4KjRv`Q}9CYmnW%ozO3T;u1_myeT%6U!4s2vlgK{S!JZPlKWs@ zl^V|sCK}u$k$Y3DJn!hM4@55YMp|>8yp8eD>9`p`*=VFSm|{?ajOPm$BH}&qMfA^J z-gt7kqZRV*>v76j=>#F|#6L6H{+v#O^Tp;mMHBSExle&nE8~hUvGxi|Ago_Ko-5L> z_zegnS-MbW)y)wQ+G4I)OJn|PU75+r@^dBH^Enc{MjZAx_#(!1+-W4NK=h=WE=v#S zUyv`KcExCSnURBW#aBd64|YY-P1j2@ zXvC(lR-at2@?_5uEVa_g$^$bqp)}~TJG~7ajPg>c|0JV&Z%j=2$40LpX!8W5^Gc{M ziq)+7nDt*2Ca%I2pg?NI;}h3+gt<>mL8k>C{84k)C@LDPHYjkakU^tcTCv3+EU_iD zJ+CddQ`7s=K?>(58X+BxhGyOUcc795#_HkdDv3Zc0Nk(~9_ZV*cc^dQ!98K_>hKi= zLKOnSC3@z1E-*13cJWhJuNmZhxHxcm;yS!BTqflzen{;0 z2_P24cj>D#VLGYG7<7BM(3;JNAWR5aCeX8CGIyfq;e3#>!G=&T;U?w52z{B$Tv zHTO|W1c^^wuX1OqfHMUCcZ@!w@V6x$b3$J~rRYI^#jh9NExw&_JK>YZan6*YP<|o( zz|T)U(Xn3>PTk{#nVDR(ZKY=Ca?MVuW;epYBl%6qSE&#RCK`o2G|5$)R;sowS8bE3 zy5*{FBz;lxl`Bb2R7z(Eeg=zIO52u8+oaMCxwHc*pZ{X2imIE)lzmS4nUNcJuQc{8 zH}*-5{cr<(J3-8?1qq~NYa&&)BO<$8*|k!+Ww~;TRJl#A+=hIElCSIulIq=HB3D3! zQ!V;d8uu?Z?w1-5%8dstwGfL$#+78QYhbeWF6@RCg~|cT3ef&HUAORm|(h zDS7wF-hHBXAN0Ob(pS7q%iboj`KaVQCVP*G-ec5b1#()MSl$^byB4Z$g>{Y(jyC~7 z`}^9#El6p?yXn~qA4I1UA0j&ZffetDW$y;bTdD_w7rmtlLm-ak8#GHasPY8*?zf8h zeK;lWUfH`>^zLO&#u}Er4PxU{?+*jul)Oh}?@=+@iI#tYIwD_O1ZZXaY-)z%i_U`$ zjxV|L;(u*l3$Fe&A#ZAKFfzbWxgo8sxZ)k)WFyEfs+4;ws(TH=4$)qJQv z{zvt0TwlO~q9267W9@K!{Fi`MRaZj-31mTk$BLei%5HQLC{jx%R>Tb6ChY)n5*I`M zY|>1#>9Aq-G;7Bp2c4AC+lq_WEn%hVWRm$EJ0gUU=8O6<16R;LCEhSo`Bp5X`)r8Ns^nflo zT*&zb#)`?0DtXC{+JhiOB4nxf!n(ZB)WH-#C2u;;AcriqHT9b<@&)<7j#_qz(c`L@d;ZzMhRAidM zR!T~tufj=J1DDi@R|ykWh7d*}K#LKfbT|~Ot`eORw9DMAc%zoT`bjP#j{sSVK#v|C z{tM>@@12qITjhKNN(xa}1SP<{#Hqne*}V1iEeNM_gCug5Chl)KpKS;KxZ8Fy;a&6kH&&^L!Tm=>) zYoF}zTIzUj>-}kY>mYg1K0$F%0m+B<2_rbc>`BU~Qsyc}t`Zr+b#?#j>G@0Iw!zSb z^1Cn2cgq{LEKR=m;``g=9j8Lob-%s)-F?_}v*EuQ0Ej{Mj+rECR>l`nUrn9eJCmxb zv*K<>&PsaSa(dnTmc>a#zTJKd2-rg5;?r{N4#Y~x*hSR=oJn}7xMX@I<+T*V%0hMs zX~n+P;9R#{zFFe7$lMlDI~B!Lj3xchx9G)x-lF5?{&|bWz_6hTrj7BRx9ER5TQr{! zV~B!aQ^aP=I07-ZTK67e7zp*4?eZ$oi+y9J54BGR`J)q1 z2(FOCXIjWUU82TkA$UV}6es1;>p*0(tqyz+*7w|Cv9i9i_{E48ZKI@wI*iwFVmnby zZ7spX@;1J6xQ!QxauOaR#}6qif=VNO8R}lA>A@KS(*&L-z?O0rERP5!*z&SObmPOH z0f4DIM9H2ZU?Y`2OZRArN6{VpM!tg=eiwN#B2Dvs{uxTMU4NNnGfqDz2wVdgs7+mi zy!tL>$|x&FR1p=W5LL5u#W>`z;|kuH^u0i6N41n_!N%%Oz6_>?PHXZ>YK)(fL5oJ%qx8?ny6FUF&Oe!&+nrZnu6U?uwMXUc|J;X zj2d>~QC1G9m}eHN@27+|RLyU`pNZG9`)FYY#EXD4Ne{VnMzZW8lBEQJ(Xe?vO3%EL zKij?NS{j$T2SdeG^Bcv@0}l{#Efkkn7Gpy8)-%;6(M9=y|TVM+WlV;PLjSF|sBW`7jcXE$O0 z8l8{G$6vC!JOv*!R@w+x28g>GCp?(c7m^5@KbIwrj%&SjurDu`XglzIZ|CJq>e}Df zJ|aBS#jf9a>w|BhFNH(;63b#08Ta+2b{*e4VY1K|1$G^G=(H!k5g&C#=%pDvQK8UW zyXdibtfK+$AP_x*{;#8^Tx31yP1xM%LUV@$;_nlPYO(e>Pckbuz~?Y#gMkw89zNNo z+wYCm50m9a-#w>u{&@H>jwWV@*xYl|{gPX0GhLa)=BdHTK8h`>%Yfm~B$@~~Sf)ys zNk2MT0@9HVqgp~SfqzeckeJ|xBWlo6t%MQ2)ZaUCeO%S^4yJ(k;YWuNj|dJ`n#dUf z6FCd;F(HgY`aN>>+T;zr$ROW}M8j5^@eu!l+C=2FqUKGAj6hRCpfM@X5+E@7GwT2v8^Zrd;I9ZU zMQ+mJRwT^-5%;v+@4wLVza{VqfsY6<*{^N)V>0H5XsXcz!+xK(yPu&rk^`3}ZHMSe z_Li-9nb4{2gy?OMyeDPvNzr=}!YGnzl`MNpB(Gog`b96r^QqV@m2Z*Dx8PT(q-~|7 zYq_LrF$kURl0LblZ{~2QxOJttbGf*4arAz=RNNyM_sk4DOe=Zp$V_?B`KW5MRJB#E z+A2Z}?1QMSYo&b4a`~2}E%ybfe7{`2U-BK0eFsF}0hEq3Mo8^klD;3+9E4D8^_kNjFaY(K>blY`@gNLY4ZJlye^^lZXRi#a_>%||R zIwPLFBAptOPmSTHdivnFZ(8~nh47<)C98Qkt69owm9tt! z?Zm#C-p114mGo>=AvZ+IFDUzhqIPQ1!0jXqQ~>kIq4)o@KR$9y96T-^IUyf8A)Y)< zRNcwb@{u!Q+q3FPA81(i4vXGlRgAcG397|gaZ288vUi&p?bIZN+euJJiaej$leDM7 z@%^+yf(@R%-uUl#?MmL882`tKZv2S8YyTeR#y{q+jaAcyy0Rnseq>#}v6q|VPV0Ij z4sQ@vvi>qCT9VFQTvr(`%O1=k)J(fBxvVREpcwgT6>-GCg`(_yJiGy7wbGKi+pI~Gg57kowWaXOkZs%lbE1`x9o=;^`K4qw zD%h22N6!uB3_?#Ua)%6N(|y&xN!>NIT{~EMgaz-QU3kntjQ^&cl?Ad33Iht|3bV8&{(FFM;_>k-P%|56_`_5U`tgIiUnUzmswv?NDqf%!>4#og0Lp04 zE{kjM2Xj;`VsvukYQR7IJWRue&yS6$eq>(PGQtb~i;CG;%`p}%9R`OZD1R!4m1s%G z7>RhUV+;s07!4<2I)wZ2zG9)s%)yurVJ~Ku@Yi^NknT!kcGel?gn=;JKt~H|y$UJ( zfO2_A;Lqqauem3M1nR6Fyd37>pZywwvyVV+ZFq8+p2DOFHMY?q5)@!S7J~3k(&Uu&e7jUNMVNrFc5_&)JIjPY0$w{5*`>Dr~=f5*O*Rz;#KaL8? z?U8ePX8Iqd<;rR0bAjcwIx(#-l)K^en_s&5#ZTY)^lcYv|7OisYoJE7cta}KB^T_v zo%o<=!<_4z+*{my!QxTLze)CQl8QFVMVoIYnd=(LzjlAGn12oD`!|%ofH0FJtED)y zS^^*&Bs1X5h({>@=+Y*6>tQkfsB*6U@+Yum^5p}8!M8L+>vui#qxSbd^(S3F>=KV2 z7mpnW{NYxy4Oj^~>6@RGy=TQ}C&N7ADSJXaDlzgt)05Db?)aW(_Xhm=etiYt57Iq* z3*vuJ*s(V|{*SZWxQ>p1_<;@(0%GCSVeBgh+2}?dG16kPL>^C+R!0J`5uy$Tv1a|n z!@kAJRfW4BQ_+S3RrJl%?g&iyGc(c7JTIc%@91rZE<34P=}3*KDEo#Tk8K72>@0(r zTI}gYUUpUj@4muNHNgXwmIU5q-mJ!HH&YO%UDe*er^adPOiTPBEs% zf9tv;h%sYa*uDrubBJ+4$gj)BxJVA>9we)8VT3%P!hrh{6qw+lcqAZXVTcHi@Ug>A zVSq8WNB`5`|NY-zQbx|>9n7ylFnxgR#xF6x13YR^jq|}Qg>gWf2||$-iE94{xisvoN2< zx$fM>#+{OHm+XV8vwCW5fIUnpSc8Nv9a{0S5W|^YKY#C{8GclDK?@l%33a*q7^Vi?}WVwM`_y>bwArgP%p& zeYK^+-%|5GA@KhY*o@l(v3~?7rRpHiN#I2SL^%r^32Y*;nZPpyh6sF(0Mm#1EM18N zC_;jwfJ|w-{ZIxH+F9wl+?I~F#Ak!(0S772FYlGLR`BWMmsuq&iSm`lUxE89@-@Ltb?(l`4jr6wZgbZ@cIaT*S?%79H%#!Tv%p^jilzojz)b4l3O4BPi4aQ?uMh&I&it?;^}5nxO(p@QDqPB}DE zqWB~G4hpm!2}ENHXDFNGeOIqd2$KvC7k)~2eAjMFUZ$WzwEBb*8}7;e}vsb-Oi(9J=!g@{|lF+NGm6$?=tQeR4QiAYOj23cp-&$w+@ zC-|wck#2#u4AjsO=tsub&782dl{C$v*(_IGkmo zqttw2xp$s&ijI@9P9y+PbLk6Xua3>O-QD=+j<4>RZ(G>-ogLrWv9w95@0II&rNTXO z;hy_1ii5nAIwGfz+)94zI+^Ay#Yz|ze#Gwo#Qb!!`HTdH!WjVMf`Wmoq+!@3!v*z delta 18830 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 diff --git a/tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc b/tkinter_app/src/__pycache__/virtual_keyboard.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b664ca894768fddb46ad109378af99c1b8c9c8df GIT binary patch literal 17542 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