From 18ba24b742e1d007f84da2cf061c672ab77f33ff Mon Sep 17 00:00:00 2001 From: Satakun Utama Date: Thu, 4 Dec 2025 09:05:30 +0700 Subject: [PATCH] Minor Improvements & Updated Flutter section --- .gitignore | 1 + Chapter2/AppDev.typ | 148 - Chapter2/Chapter2.typ | 7 +- Chapter2/Flutter.typ | 569 + Chapter2/Flutter/desktopExampleApp.png | Bin 0 -> 37840 bytes Chapter2/Flutter/flutterHotReload.svg | 11 + Chapter2/Flutter/homePage.png | Bin 0 -> 38346 bytes Chapter2/Flutter/mobileExampleApp.png | Bin 0 -> 63062 bytes Chapter2/Flutter/newProjectPage.png | Bin 0 -> 64692 bytes Chapter2/Flutter/vscode_play.svg | 1 + Chapter2/Git.typ | 15 + Chapter2/OpenSSL.typ | 25 + Chapter2/PIR.typ | 46 +- Chapter2/TLS.typ | 2 + Chapter2/x690.typ | 25 + Chapter2/สารบัญภาพ.typ | 2 +- PageTemplate.typ | 13 + References.yaml | 69 +- nktc.jpg => assets/nktc.jpg | Bin demo.pdf | Bin 24942 -> 0 bytes demo.typ | 16 - main.pdf | 50433 ----------------------- main.typ | 22 +- ปก.typ | 2 +- ภาคผนวก/ภาคผนวก.typ | 4 +- 25 files changed, 787 insertions(+), 50624 deletions(-) create mode 100644 .gitignore delete mode 100644 Chapter2/AppDev.typ create mode 100644 Chapter2/Flutter.typ create mode 100644 Chapter2/Flutter/desktopExampleApp.png create mode 100644 Chapter2/Flutter/flutterHotReload.svg create mode 100644 Chapter2/Flutter/homePage.png create mode 100644 Chapter2/Flutter/mobileExampleApp.png create mode 100644 Chapter2/Flutter/newProjectPage.png create mode 100644 Chapter2/Flutter/vscode_play.svg create mode 100644 Chapter2/Git.typ create mode 100644 Chapter2/OpenSSL.typ create mode 100644 Chapter2/x690.typ rename nktc.jpg => assets/nktc.jpg (100%) delete mode 100644 demo.pdf delete mode 100644 demo.typ delete mode 100644 main.pdf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a136337 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pdf diff --git a/Chapter2/AppDev.typ b/Chapter2/AppDev.typ deleted file mode 100644 index dae2aec..0000000 --- a/Chapter2/AppDev.typ +++ /dev/null @@ -1,148 +0,0 @@ -#import "../PageTemplate.typ": i -#import "@preview/treet:1.0.0": * -#import "@preview/cades:0.3.1": qr-code -#set heading(numbering: "1.1", offset: 1) - -= Flutter - -#i Flutter เป็นชุดพัฒนาซอฟต์แวร์ UI แบบโอเพนซอร์สที่สร้างโดย Google -สามารถใช้พัฒนาแอปพลิเคชันข้ามแพลตฟอร์มจากฐานโคดเดียวสำหรับเว็บ Fuchsia, Android, iOS, -Linux, macOS และ Windows โดย Flutter ได้รับการพูดถึงครั้งแรกในปี 2015 -และเปิดตัวในเดือนพฤษภาคม 2017 และ Flutter ถูกใช้งานภายในโดย Google ในแอปพลิเคชันต่างๆ -เช่น Google Pay และ Google Earth รวมถึงโดยนักพัฒนาซอฟต์แวร์รายอื่นๆ เช่น ByteDance -และ Alibaba - -#i Flutter จะสร้างแอปพลิเคชันที่มีเอ็นจิ้นการเรนเดอร์ของตัวเอง ซึ่งส่งข้อมูลพิกเซลไปยังหน้าจอโดยตรง -ซึ่งแตกต่างจากเฟรมเวิร์ก UI อื่น ๆ อีกมากมายที่อาศัยแพลตฟอร์มเป้าหมายเพื่อจัดหาเอ็นจิ้นการเรนเดอร์ -เช่น แอป Android พื้นฐานที่ใช้ Android SDK ระดับอุปกรณ์ หรือ iOS SDK ที่ใช้ UI stack -ในตัวของแพลตฟอร์มเป้าหมาย การควบคุมขั้นตอนการแสดงผลของ Flutter -ช่วยลดความยุ่งยากในการรองรับหลายแพลตฟอร์ม เนื่องจากสามารถใช้โคด UI -ที่เหมือนกันได้กับทุกแพลตฟอร์มเป้าหมาย - -== โครงสร้างโปรเจกต์ Flutter - -ในโครงงานนี้ โปรเจกต์ Flutter มีโครงสร้างคร่าว ๆ ดังกล่าว - -#tree-list[ - - android - - app - - src - - main - - java: โคด Java - - kotlin: โคด Kotlin - - res: โฟลเดอร์ทรัพยากร เช่น ไอคอนแอพลิเคชัน - - AndroidManifest.xml - - build.gradle.kts - - settings.gradle.kts - - assets - - certificates - - rootCA.crt: ใบรับรอง Root (ดู@x509 สำหรับรายละเอียด) - - build: โฟลเดอร์สำหรับเก็บไฟล์ไบนารี - - ios - - lib: ซอร์สโคดของแอพลิเคชัน - - linux - - macos - - test - - windows - - l10n.yaml: ไฟล์ตั้งค่าฟีเจอร์แปลภาษา - - pubspec.yaml: ไฟล์ข้อมูลโปรเจกต์ Flutter -] - -(รายการข้างต้นรวมถึงแค่ไฟล์ที่สำคัญที่จะถูกกล่าวถึงใน@flutter นี้) - -== Android - -#i ในการพัฒนาแอพลิเคชัน Android โดยใช้เฟรมเวิร์ก Flutter จำเป็นต้องใช้ส่วนประกอบเครื่องมือพัฒนา Android ดังนี้ - -- Android SDK (API Level 36 ณ เวลาที่พิมพ์) -- Android SDK Build-Tools -- Android SDK Command-line Tools -- Android SDK Platform-Tools -- Android Emulator (ไม่บังคับ) - -และแนะนำให้จัดการและติดตั้งเครื่องมือเหล่านี้ผ่าน Android Studio - -#i ในการติดตั้ง Android SDK ควรติดตั้ง Android SDK ล่าสุดถึงแม้ว่าอุปกรณ์ของคุณจะใช้เวอร์ชันที่เก่ากว่านั้น เพื่อความมั่นใจว่าแอพลิเคชันจะสามารถใช้กับอุปกรณ์ที่ใหม่ล่าสุดได้ - -#i แอพลิเคชัน Android จะมี SDK/API level เป้าหมาย (Target SDK/API level) และ SDK/API level ขั้นต่ำ (Minimum SDK/API level) โครงงานนี้ ณ เวลาที่พิมพ์ ใช้ API level เป้าหมาย 36 (Android 16) และ API level ขั้นต่ำ 24 (Android 7) ซึ่งรวมกันแล้ว แอพลิเคชัน Android จะสามารถติดตั้งได้บนระบบตั้งแต่ API level ขั้นต่ำจนถึง API level เป้าหมาย หรือก็คือ แอพลิเคชันในโครงงานนี้สามารถติดตั้งได้ตั้งแต่บนระบบ Android 7 ถึง Android 16 นั่นเอง - -=== Java - -#i Java เป็นภาษาสำคัญสำหรับการพัฒนาแอพลิเคชัน Android ถึงอย่างไรก็ตาม แอพลิเคชัน Flutter นั้นถูกเขียนด้วยภาษา Dart แต่ยังจำเป็นต้องมีโคด Java เล็กน้อยเพื่อเริ่มต้นแอพลิเคชัน Flutter - -#i โครงการนี้ใช้ Java 21 (JetBrains Runtime/Azul Zulu OpenJDK) เป็นหลักในการทำงานกับ Gradle แต่แอพลิเคชัน Android ที่ผลิตออกมานั้น เพื่อให้เข้ากับเวอร์ชันที่เก่ากว่าของระบบปฏิบัติการได้ ใช้ Java 11 - -=== Gradle - -#i Gradle เป็นเครื่องมือสร้างระบบอัตโนมัติสำหรับการพัฒนาซอฟต์แวร์หลายภาษา จัดการงานต่าง ๆ เช่น การคอมไพล์ การแพ็คเกจ การทดสอบ การปรับใช้ และการเผยแพร่ ภาษาที่รองรับ ได้แก่ Java (รวมถึงภาษา Kotlin, Groovy, Scala ที่ใช้ JDK), C/C++ และ JavaScript Gradle พัฒนาต่อยอดจากแนวคิดของ Apache Ant และ Apache Maven และนำเสนอภาษาเฉพาะโดเมนที่ใช้ Groovy และ Kotlin ซึ่งต่างจากการกำหนดค่าโครงการที่ใช้ XML ที่ Maven ใช้ Gradle ใช้กราฟแบบอะไซคลิกกำกับทิศทางเพื่อจัดการการอ้างอิง กราฟนี้ใช้เพื่อกำหนดลำดับของงานที่ควรดำเนินการ Gradle ทำงานบน Java Virtual Machine - -#i Gradle คือเครื่องมือหลักที่ใช้ในการจัดการโปรเจกต์ Java ส่วนใหญ่ รวมถึงโปรเจกต์ Android โดยในโครงการนี้ จะใช้ Gradle เวอร์ชัน 8.14.3 เป็นหลัก - -== Linux - -#i Flutter ใช้ไลบรารีดังต่อไปนี้ในขั้นตอนการพัฒนาแอพลิเคชันบน Linux (development dependencies) - -- curl -- git -- unzip -- xz -- zip -- glu - -#i การติดตั้งไลบรารีและโปรแกรมที่กล่าวไปข้างต้นจะแตกต่างกันไปแต่ละการแจกจ่าย Linux และ Flutter ใช้ไลบรารีพื้นฐานดังกล่าวในการทำงานของแอพลิเคชัน (runtime dependencies) - -- GTK 3 -- blkid -- LZMA - -แต่โดยทั่วไปแล้ว ไลบรารีเหล่านี้ควรถูกติดตั้งมาอยู่แล้วหากคุณใช้ graphical desktop ทั่วไป - -=== Debian - -```sh -# Development dependencies: -sudo apt install -y curl git unzip xz-utils zip libglu1-mesa -# Runtime dependencies: -sudo apt install libgtk-3-0 libblkid1 liblzma5 -``` - -=== Fedora Linux - -```sh -# Development dependencies: -sudo dnf install curl git unzip xz zip mesa-libglu -# Runtime dependencies: -sudo dnf install gtk3 libblkid xz -``` - -=== Arch Linux - -```sh -# Development dependencies: -sudo pacman -S --needed curl git unzip xz zip glu -# Runtime dependencies: -sudo pacman -S --needed util-linux-libs xz gtk -``` - -== Windows - -#grid( - columns: 2, - column-gutter: 1em, - [#i ในการพัฒนาซอฟต์แวร์บน Windows ด้วย Flutter คุณจำเป็นต้องติดตั้ง Git สำหรับ Windows ซึ่งคุณสามารถดูขั้นตอนการติดตั้งได้โดยการสแกน QR code ด้านข้าง หรือที่ https://git-scm.com/install/windows หรือเพียงแค่ใช้ WinGet ในการติดตั้งโดยการใช้คำสั่งด้านล่าง], - qr-code("https://git-scm.com/install/windows", width: 1in), -) - -```sh -winget install --id Git.Git -e --source winget -``` - -= Git - -#i Git เป็นระบบซอฟต์แวร์ควบคุมเวอร์ชันแบบกระจาย ที่สามารถจัดการเวอร์ชันของซอร์สโคดหรือข้อมูลได้ มักใช้เพื่อควบคุมซอร์สโคดโดยโปรแกรมเมอร์ที่พัฒนาซอฟต์แวร์ร่วมกัน - -== Gitea - -#i Gitea เป็นชุดซอฟต์แวร์ forge สำหรับการโฮสต์ระบบควบคุมเวอร์ชันการพัฒนาซอฟต์แวร์โดยใช้ Git รวมถึงฟีเจอร์การทำงานร่วมกันอื่น ๆ เช่น การติดตามบั๊ก การตรวจสอบโคด การผสานรวมอย่างต่อเนื่อง (Continuous Integration; CI) กระดาน Kanban ระบบรายงานปัญหา และวิกิ รองรับการโฮสต์ด้วยตนเอง และยังมีอินสแตนซ์สาธารณะของบุคคลที่หนึ่งให้ใช้งานฟรีอีกด้วย Gitea เป็นส่วนหนึ่งของ Gogs และเขียนด้วยภาษา Go Gitea สามารถโฮสต์ได้บนทุกแพลตฟอร์มที่รองรับ Go รวมถึง FreeBSD, Linux, macOS และ Windows โครงการนี้ได้รับทุนสนับสนุนจาก Open Collective - -#i โครงงานนี้ใช้ Gitea (self-hosted) ในการโฮสต์โคดของโครงงาน diff --git a/Chapter2/Chapter2.typ b/Chapter2/Chapter2.typ index f5e3b5a..9148ddd 100644 --- a/Chapter2/Chapter2.typ +++ b/Chapter2/Chapter2.typ @@ -1,6 +1,10 @@ #import "../PageTemplate.typ": page-theme +#import "@preview/i-figured:0.2.4" #show: page-theme +#show heading: i-figured.reset-counters.with(level: 3) +#show figure: i-figured.show-figure.with(level: 3) + = บทที่ 2 \ ทฤษฎีและเอกสารที่เกี่ยวข้อง #include "Intro.typ" @@ -12,4 +16,5 @@ #include "NFC.typ" #include "PIR.typ" #include "CLanguage.typ" -#include "AppDev.typ" +#include "Flutter.typ" +#include "Git.typ" diff --git a/Chapter2/Flutter.typ b/Chapter2/Flutter.typ new file mode 100644 index 0000000..a29eaa8 --- /dev/null +++ b/Chapter2/Flutter.typ @@ -0,0 +1,569 @@ +#import "../PageTemplate.typ": * +#import "@preview/treet:1.0.0": * +#import "@preview/tiaoma:0.3.0" +#set heading(numbering: "1.1", offset: 1) + += Flutter + +#i Flutter เป็นชุดพัฒนาซอฟต์แวร์ UI แบบโอเพนซอร์สที่สร้างโดย Google +สามารถใช้พัฒนาแอปพลิเคชันข้ามแพลตฟอร์มจากฐานโคดเดียวสำหรับเว็บ Fuchsia, Android, iOS, +Linux, macOS และ Windows โดย Flutter ได้รับการพูดถึงครั้งแรกในปี 2015 +และเปิดตัวในเดือนพฤษภาคม 2017 และ Flutter ถูกใช้งานภายในโดย Google ในแอปพลิเคชันต่างๆ +เช่น Google Pay และ Google Earth รวมถึงโดยนักพัฒนาซอฟต์แวร์รายอื่นๆ เช่น ByteDance +และ Alibaba + +#i Flutter จะสร้างแอปพลิเคชันที่มีเอ็นจิ้นการเรนเดอร์ของตัวเอง ซึ่งส่งข้อมูลพิกเซลไปยังหน้าจอโดยตรง +ซึ่งแตกต่างจากเฟรมเวิร์ก UI อื่น ๆ อีกมากมายที่อาศัยแพลตฟอร์มเป้าหมายเพื่อจัดหาเอ็นจิ้นการเรนเดอร์ +เช่น แอป Android พื้นฐานที่ใช้ Android SDK ระดับอุปกรณ์ หรือ iOS SDK ที่ใช้ UI stack +ในตัวของแพลตฟอร์มเป้าหมาย การควบคุมขั้นตอนการแสดงผลของ Flutter +ช่วยลดความยุ่งยากในการรองรับหลายแพลตฟอร์ม เนื่องจากสามารถใช้โคด UI +ที่เหมือนกันได้กับทุกแพลตฟอร์มเป้าหมาย + +#pagebreak() + +== การติดตั้งโปรแกรมเขียนโคด + +#i จริง ๆ แล้วนั้น Flutter สามารถทำงานกับโปรแกรมเขียนโคดใดก็ได้ แต่มีโปรแกรมเหล่านี้ที่อาจมีประสบการณ์การพัฒนาที่ดีกว่าโปรแกรมอื่น: + +- Visual Studio Code (VS Code) +- Android Studio +- JetBrains IntelliJ +- Firebase Studio + +#i โครงงานนี้ใช้โปรแกรมเขียนโคด Android Studio เป็นหลักเนื่องจากแอพลิเคชันโครงงานมี Android เป็นเป้าหมายหลัก และ Android SDK สามารถจัดการได้ง่ายกว่าใน Android Studio + +=== Android Studio + +#i Android Studio สามารถดาวน์โหลดได้ผ่าน https://developer.android.com/studio หรือสามารถถูกติดตั้งและจัดการผ่านแอพลิเคชัน JetBrains Toolbox ได้เช่นกัน (https://www.jetbrains.com/toolbox-app/) + +== การติดตั้ง Flutter + +#i การติดตั้ง Flutter สามารถทำได้สองวิธีด้วยกัน คือการติดตั้งผ่าน Visual Studio Code (VS Code) และการติดตั้งด้วยตนเอง โดยหากต้องการใช้ VS Code เป็นโปรแกรมเขียนโคดอยู่แล้ว สามารถติดตั้งผ่าน VS Code ได้เลย + +#i แต่ก่อนอื่น ต้องทำการติดตั้งโปรแกรมและไลบรารีพื้นฐานที่จำเป็นสำหรับ Flutter ก่อน + +=== การติดตั้งโปรแกรมและไลบรารีที่จำเป็น + +==== Windows + +#grid( + columns: 2, + column-gutter: 1em, + [#i ในการพัฒนาซอฟต์แวร์บน Windows ด้วย Flutter คุณจำเป็นต้องติดตั้ง Git สำหรับ Windows ซึ่งคุณสามารถดูขั้นตอนการติดตั้งได้โดยการสแกน QR code ด้านข้าง หรือที่ https://git-scm.com/install/windows หรือเพียงแค่ใช้ WinGet ในการติดตั้งโดยการใช้คำสั่งด้านล่าง], + tiaoma.qrcode("https://git-scm.com/install/windows", width: 1in, alt: "QR โคดสำหรับหน้าการติดตั้ง Git สำหรับ Windows"), +) + +```sh +winget install --id Git.Git -e --source winget +``` + +==== Linux + +#i Flutter ใช้ไลบรารีดังต่อไปนี้ในขั้นตอนการพัฒนาแอพลิเคชันบน Linux (development dependencies; ยังไม่รวมไลบรารีและโปรแกรมที่ต้องมีในการสร้างแอพลิเคชัน _สำหรับ_ Linux) + +#grid( + columns: 2, + column-gutter: 2in, + [ + - curl + - git + - unzip + ], + [ + - xz + - zip + - glu + ], +) + +หากต้องการคำสั่งในการติดตั้งแพคเกจเหล่านี้ โปรดดู@flLinuxDetails + +#pagebreak() + +==== macOS + +#i จำเป็นต้องทำการติดตั้งเครื่องมือ command-line Xcode เพื่อเข้าถึงเครื่องมือที่ Flutter จำเป็นต้องใช้ รวมถึง Git + +ในการดาวน์โหลดเครื่องมือ ใช้คำสั่งต่อไปนี้ในเทอร์มินัลที่คุณเลือก: + +```sh +xcode-select --install +``` + +#i หากคุณไม่ได้ติดตั้งเครื่องมืออยู่แล้ว จะมีไดอะลอกเพื่อคอนเฟิร์มว่าคุณต้องการที่จะติดตั้งมัน กด *Install* และกด *Done* เมื่อทำการติดตั้งเสร็จสิ้นแล้ว + +=== การติดตั้งผ่าน Visual Studio Code + +1. เปิด VSCode +2. ติดตั้งส่วนขยาย Flutter \ + อยู่ภายใต้ ID `Dart-Code.flutter` ทั้งบน Visual Studio Marketplace และ OpenVSX +3. ติดตั้ง Flutter ด้วย VS Code + + เปิด Command Palette ด้วยเมนู *View* > *Command Palette* หรือกด Ctrl + Shift + P + + ใน Command Palette พิมพ์ `flutter`. + + เลือก *Flutter: New Project* + + VS Code จะให้คุณเลือก Flutter SDK บนคอมพิวเตอร์ของคุณ เลือก *Download SDK* + + เมือหน้าไดอะลอก *Select Folder for Flutter SDK* แสดงขึ้น เลือกสถานที่ที่คุณอยากติดตั้ง Flutter + + คลิก *Clone Flutter* \ + ในระหว่างการดาวน์โหลด VS Code จะแสดงการแจ้งเตือนนี้: + ``` + Downloading the Flutter SDK. This may take a few minutes. + ``` + การดาวน์โหลดนี้จะใช้เวลาสองสามนาที หากคุณเชื่อว่าการดาวน์โหลดหยุดชะงัก คุณสามารถคลิก *Cancel* แล้วเริ่มต้นการติดตั้งใหม่ได้ + + คลิก *Add SDK to PATH* \ + เมื่อเสร็จสิ้น จะมีการแจ้งเตือน + ``` + The Flutter SDK was added to your PATH + ``` + + VS Code อาจแสดงการแจ้งเตือนเกี่ยวกับการเก็บข้อมูลของ Google หากคุณยินยอม คลิก *OK* + + เพื่อความแน่ใจ กรุณาปิดเทอร์มินัลทุกหน้าต่างหรือรีสตาร์ท VS Code เพื่อให้แน่ใจว่า Flutter จะสามารถใช้ผ่านเทอร์มินัลได้ +4. เมื่อเสร็จสิ้น ใช้คำสั่ง `flutter doctor -v` ในเทอร์มินัลที่คุณเลือกเพื่อตรวจสอบการติดตั้ง Flutter ของคุณ \ + หากคำสั่งไม่เจอหรือเกิดข้อผิดพลาดขึ้น ตรวจสอบ https://docs.flutter.dev/install/troubleshoot สำหรับข้อมูลเพิ่มเติม + +#pagebreak() + +=== การติดตั้งด้วยตนเอง + +#i แนะนำให้ทำตาม https://docs.flutter.dev/install/manual#install-flutter เนื่องจากกระบวนการนี้ต้องใช้ข้อมูลที่ใหม่ล่าสุด + +1. ดาวน์โหลด Flutter (สามารถหาปุ่มดาวน์โหลดได้จากลิงก์ด้านบน) +2. สร้างโฟลเดอร์สำหรับเก็บ Flutter SDK +3. ทำการแตกไฟล์ที่ดาวน์โหลดมา +4. เพิ่ม Flutter เข้าไปยัง PATH ของคุณ (วิธีการขึ้นอยู่กับระบบปฏิบัติการ) +5. ยืนยันความถูกต้องของการติดตั้งของคุณด้วยคำสั่ง `flutter doctor -v` + +== Dart + +#i Dart เป็นภาษาโปรแกรมที่ออกแบบโดย Lars Bak และ Kasper Lund และพัฒนาโดย +Google สามารถใช้พัฒนาแอปพลิเคชันบนเว็บ มือถือ เซิร์ฟเวอร์ และเดสก์ท็อปได้ และยังเป็นภาษาหลักที่ใช้ในการพัฒนาแอพลิเคชัน Flutter + +#i Dart เป็นภาษาเชิงวัตถุ อิงคลาส และรวบรวมขยะ (garbage-collection) ด้วยไวยากรณ์แบบ C สามารถคอมไพล์เป็นโค้ดเครื่อง JavaScript หรือ WebAssembly ได้ รองรับอินเทอร์เฟซ มิกซ์อิน คลาสนามธรรม เจเนอริกแบบรีไฟด์ และการอนุมานชนิดข้อมูล + +== การสร้างโปรเจกต์ + +#i ตั้งแต่หัวข้อนี้เป็นต้นไป จะเป็นข้อมูลสำหรับการทำงานกับ Android Studio เป็นหลักเนื่องจากเป็นโปรแกรมหลักที่ถูกใช้งานในการพัฒนาแอพลิเคชันโครงงานนี้ + +#i หากยังไม่ได้ติดตั้งปลั๊กอิน Flutter โปรดติดตั้งปลั๊กอินก่อน โดยหากอยู่ในหน้าต้อนรับ สามารถติดตั้งปลั๊กอินได้โดยการเข้าไปยังแท็บ *Plugins* หรือหากเปิดโปรเจกต์อื่นอยู่ สามารถเข้าถึงหน้าปลั๊กอินได้โดยการกดที่ไอคอนฟันเฟืองในแถบเครื่องมือ แล้วกด *Plugins...* หลังจากนั้น ในแท็บ *Marketplace* ของหน้าปลั๊กอิน ค้นหา *Flutter* (ผู้ผลิตปลั๊กอินคือ Google) แล้วกด *Install* + +#afigure( + image("Flutter/homePage.png", width: 60%), + attr: "ส่วนหนึ่งของโครงงาน, ศตคุณ อุตมะ, ภายใต้ CC BY-SA 4.0", + alt: "หน้ายินดีต้อนรับในแท็บ Projects ที่กำลังแสดงรายการโปรเจกต์และปุ่มในการสร้างโปรเจกต์ใหม่", + caption: [หน้ายินดีต้อนรับใน Android Studio], +) + +#i เมื่อคลิก *New Flutter Project* จะมีหน้าถามสถานที่ติดตั้ง Flutter SDK หลังจากนั้น กด *Next* แล้วจะมีหน้าต่อไปนี้ขึ้นมาเพื่อให้คุณกรอกรายละเอียดโปรเจกต์ + +#afigure( + image("Flutter/newProjectPage.png", width: 80%), + attr: "ส่วนหนึ่งของโครงงาน, ศตคุณ อุตมะ, ภายใต้ CC BY-SA 4.0", + alt: "หน้ากรอกรายละเอียดโปรเจกต์ใหม่", + caption: [หน้าโปรเจกต์ใหม่], +) + +รายละเอียดที่จำเป็นต้องกรอกในการสร้างโปรเจกต์ใหม่มีดังนี้: + +- *Project name:* ชื่อโปรเจกต์ +- *Project location:* โฟลเดอร์ที่ต้องการเก็บโปรเจกต์ +- *Description:* รายละเอียดโปรเจกต์ +- *Project type:* ประเภทโปรเจกต์ ในกรณีนี้เป็นค่า *Application* เนื่องจากเราต้องการสร้างแอพลิเคชัน +- *Organization:* โดเมนเนมย้อนหลังขององค์กรที่พัฒนา (Reverse domain name notation; Reverse-DNS) +- *Android language:* เลือกระหว่าง Java และ Kotlin เป็นภาษาหลักที่ใช้ในแอพลิเคชัน Android +- *Platforms:* แพลตฟอร์มที่โปรเจกต์จะรองรับ อย่างไรก็ตาม การสร้างไฟล์ไบนารีสำหรับแอพลิเคชันขึ้นอยู่กับแพลตฟอร์มที่พัฒนาแอพลิเคชันเช่นกัน หมายความว่า ถึงแม้ตามทฤษฎีแล้วแอพลิเคชันของคุณจะรองรับ iOS คุณต้องมีอุปกรณ์ Mac ในการสร้างไฟล์แอพลิเคชัน iOS ออกมา + +เมื่อทำการใส่รายละเอียดทั้งหมดแล้ว สามารถกด Create เพื่อสร้างโปรเจกต์ได้เลย + +#pagebreak() + +== แอพลิเคชันตัวอย่าง + +เมื่อกดรันแอพลิเคชันด้วยไอคอน #box(image("Flutter/vscode_play.svg", alt: "Play"), baseline: 15%) (หรือ Shift+F10 ใน Android Studio) จะได้แอพลิเคชันดังรูปด้านล่างออกมา + +#box( + afigure( + grid( + columns: 2, + align: horizon, + image( + "Flutter/mobileExampleApp.png", + height: 2.5in, + alt: "แอพลิเคชันมือถือ มีแถบสีม่วง ตัวเลขแสดงจำนวนครั้งที่กดปุ่มและปุ่มกดเพิ่มจำนวน", + ), + image( + "Flutter/desktopExampleApp.png", + width: 90%, + alt: "โปรแกรมคอมพิวเตอร์ แถบหน้าต่างโปรแกรมสีดำ ในหน้าต่างประกอบด้วยส่วนประกอบคล้ายแอพลิเคชันบนโทรศัพท์", + ), + ), + attr: "ส่วนหนึ่งของโครงงาน, ศตคุณ อุตมะ, ภายใต้ CC BY-SA 4.0", + caption: [แอพลิเคชันตัวอย่างบน Android 15 และ Arch Linux], + ), + height: 3in, +) + +#show raw.where(block: true): set block(below: 2em) + +_*หมายเหตุ:* โคดในห้วข้อนี้ถูกนำ comment ออกเพื่อความรวบรัด_ + +ภายในโฟลเดอร์โปรเจกต์ใหม่ จะมีไฟล์ `lib/main.dart` พร้อมแอพลิเคชันตัวอย่าง + +โดยในบรรทัดแรก จะมีการนำเข้า Material UI + +```dart +import 'package:flutter/material.dart'; +``` + +และถัดมา จะมีฟังก์ชันหลักชื่อ `main` ที่ทำหน้าที่ในการรันแอพลิเคชัน โดยมีการรับอาร์กิวเมนต์เป็นวิดเจ็ท ซึ่งในกรณีนี้เป็นการสร้างวัตถุจากคลาส `MyApp` ที่เป็นวิดเจ็ท + +```dart +void main() { + runApp(const MyApp()); +} +``` + +ถัดมาจะมีคลาส `MyApp` ที่สืบทอดมาจาก `StatelessWidget` ซึ่งคือคลาสสำหรับวิดเจ็ทที่ไร้สถานะ ("Stateless") + +```dart +class MyApp extends StatelessWidget { +``` + +ซึ่งในคลาสจะมี constructor ที่สามารถรับค่าคีย์ได้: +```dart + const MyApp({super.key}); +``` + +และจะมีฟังก์ชันในการสร้างวิดเจ็ท ซึ่งฟังก์ชันนี้เป็นการสืบทอดฟังก์ชันมา สังเกตได้จาก `@override` + +```dart + @override + Widget build(BuildContext context) { +``` + +และในฟังก์ชันจะมีการสร้างวัตถุ MaterialApp ซึ่งมีหน้าที่ในการเก็บข้อมูลเกี่ยวกับแอพลิเคชัน Material UI รวมถึงข้อมูลเช่น ชื่อแอพลิเคชัน (`title`) และธีม (`theme`) + +```dart + return MaterialApp( + title: 'Flutter Demo', +``` + +โดยข้อมูลธีมนั้นถูกเก็บด้วยการสร้างวัตถุ `ThemeData` + +```dart + theme: ThemeData( +``` + +และมีการสร้างธีมสีจากสีหลักโดยการใช้เมธอด `ColorScheme.fromSeed` แต่ในโคดด้านล่างนี้ +คลาส `ColorScheme` นั้นถูกอนุมานขึ้นมา โดยใน Dart 3.10 มีฟีเจอร์ "dot shorthands" ซึ่งเป็นทางลัดในการข้ามการเขียนชื่อคลาส ซึ่งชื่อคลาสสามารถถูกอนุมานขึ้นมาได้เนื่องจากอาร์กิวเมนต์ `colorScheme` นั้นคาดหวังค่าที่เป็นวัตถุจากคลาส `ColorScheme` อยู่แล้ว + +```dart + colorScheme: .fromSeed(seedColor: Colors.deepPurple), + ), +``` + +และต่อมา อาร์กิวเมนต์ `home` เป็นอาร์กิวเมนต์ที่รับค่าเป็นวิดเจ็ทซึ่งจะเป็นหน้าแรกของแอพลิเคชัน + +```dart + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} +``` + +ถัดมา มีการสร้างคลาส `MyHomePage` ที่ถูกใช้ด้านบน โดยคลาสเป็น `StatefulWidget` ซึ่งหมายความว่า เป็นคลาสที่มีสถานะ (State) + +```dart +class MyHomePage extends StatefulWidget { +``` + +โดยใน constructor มีการรับค่าพารามีเตอร์ `title` + +```dart + const MyHomePage({super.key, required this.title}); +``` + +โดยคลาสนี้เป็นคลาสที่เก็บการตั้งค่าวิดเจ็ท และเป็นคลาสที่เก็บค่าพารามิเตอร์จากวิดเจ็ทที่เหนือกว่า และตัวแปรในคลาสย่อยของ `StatefulWidget` นั้นจะมีคีย์เวิร์ด `final` เสมอ ซึ่งหมายถึงว่า ตัวแปรนี้เปลี่ยนแปลงไม่ได้หลังจากสร้างวัตถุจากคลาสแล้ว + +```dart + final String title; +``` + +ต่อมาจึงมีการสร้างวัตถุ State ซึ่งในฟังก์ชัน `createState` ที่ถูกสืบทอดมานั้น จะมีการสร้างวัตถุ State จากคลาส `_MyHomePageState` (โดยที่ `_` หมายถึงว่าคลาสนั้นเป็นส่วนตัวและไม่ควรถูกนำเข้าโดยไฟล์อื่น) + +```dart + @override + State createState() => _MyHomePageState(); +} +``` + +```dart +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { +``` + +โดยในฟังก์ชัน `_incrementCounter` มีการเรียกใช้ฟังก์ชัน `setState` ซึ่งจะแจ้งเตือน Flutter ว่ามีการเปลี่ยนแปลงสถานะ ซึ่งจะก่อให้เกิดการเร็นเดอร์วิดเจ็ทใหม่ และในอาร์กิวเมนต์ของ `setState` คือฟังก์ชันไม่ระบุชื่อ (anonymous functions หรืออีกชื่อหนึ่งคือ lambda) ที่เปลี่ยนแปลงสถานะของวิดเจ็ท + +```dart + setState(() { + _counter++; + }); + } +``` + +โดยต่อมา มีฟังก์ชัน `build` เช่นเคยที่มีหน้าที่ในการสร้างวิดเจ็ท โดยฟังก์ชัน `build` ของวิดเจ็ทที่มีสถานะนั้นจะถูกรันใหม่ทุกครั้งที่มีการเปลี่ยนแปลงสถานะ + +```dart + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( +``` + +*การทดลอง:* ในระหว่างที่รันแอพลิเคชันอยู่ ลองเปลี่ยนสีพื้นหลังของวิดเจ็ท `AppBar` (เป็นค่าอื่นเช่น `Colors.amber`) แล้วทำการ hot reload โดยการกดไอคอน#box(image("Flutter/flutterHotReload.svg", alt: "สายฟ้า", width: 1.5em), baseline: 20%)เพื่อเห็นการเปลี่ยนแปลงของสีแถบแอพลิเคชันในระหว่างที่สีของวิดเจ็ทอื่น ๆ ยังคงเดิม + +```dart + backgroundColor: Theme.of(context).colorScheme.inversePrimary, +``` + +โดยในอาร์กิวเมนต์ `title` นี้มีการใช้ค่าที่รับมาจากวิดเจ็ทที่เหนือกว่า โดย `widget` ในที่นี้คือวัตถุของคลาส `MyHomePage` ที่ทำหน้าที่เก็บค่า `title` ของเรา แล้วเราจึงทำค่า `title` นั้นใส่ในวิดเจ็ทข้อความ (`Text`) + +```dart + title: Text(widget.title), + ), +``` + +`Center` เป็นวิดเจ็ทจัดเลย์เอาต์ โดยจะทำให้ลูก 1 วิดเจ็ทของมัน (`child`) อยู่ตรงกลาง + +```dart + body: Center( +``` + +#pagebreak() + +และ `Column` เป็นวิดเจ็ทจัดเลย์เอาต์เช่นกัน มันรับลูกหลายคน (`children`) แล้วจัดเรียงมันในแนวตั้ง โดยค่าเริ่มต้นแล้ว มันจะจัดให้ตัวเองกว้างเท่ากับลูก ๆ ของมัน และพยายามจัดให้ตัวเองสูงเท่าวิดเจ็ทที่สูงกว่า + +วิดเจ็ทคอลัมน์มีหลายคุณสมบัติในการควบคุมขนาดของมันและการจัดวางลูก ๆ ของมัน โดยด้านล่างมีการใช้อาร์กิวเมนต์ `mainAxisAlignment` ในการจัดลูก ๆ ของมันให้อยู่ตรงกลางในแนวตั้ง โดย "main axis" หรือ แกนหลัก ในกรณีนี้คือแนวตั้ง เพราะคอลัมน์นั้นเป็นแนวตั้ง (และ "cross axis" หรือแกนไขว้ จะเป็นแนวนอน คือแนวตรงข้ามกับแนวหลัก) + +```dart + child: Column( + mainAxisAlignment: .center, + children: [ + const Text('You have pushed the button this many times:'), + Text( + '$_counter', +``` + +การเข้าถึงธีมของแอพลิเคชัน (```dart Theme.of(context)```) แล้วนำธีมข้อความ `headlineMedium` มาใช้: + +```dart + style: Theme.of(context).textTheme.headlineMedium, + ), // Text + ], + ), // Column + ), // Center + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} +``` + +#pagebreak() + +== โครงสร้างโปรเจกต์ Flutter + +ในโครงงานนี้ โปรเจกต์ Flutter มีโครงสร้างคร่าว ๆ ดังกล่าว + +#tree-list[ + - android + - app + - src + - main + - java: โคด Java + - kotlin: โคด Kotlin + - res: โฟลเดอร์ทรัพยากร เช่น ไอคอนแอพลิเคชัน + - AndroidManifest.xml + - build.gradle.kts + - settings.gradle.kts + - assets + - certificates + - rootCA.crt: ใบรับรอง Root (ดู@x509 สำหรับรายละเอียด) + - build: โฟลเดอร์สำหรับเก็บไฟล์ไบนารี + - ios + - lib: ซอร์สโคดของแอพลิเคชัน + - linux + - macos + - test + - windows + - l10n.yaml: ไฟล์ตั้งค่าฟีเจอร์แปลภาษา + - pubspec.yaml: ไฟล์ข้อมูลโปรเจกต์ Flutter +] + +(รายการข้างต้นรวมถึงแค่ไฟล์ที่สำคัญที่จะถูกกล่าวถึงใน@flutter นี้) + +== การนำเข้าแพคเกจ + +#i ไฟล์ `pubspec.yaml` เป็นไฟล์ที่เก็บข้อมูลเกี่ยวกับโปรเจกต์ Flutter ของคุณ เช่น ชื่อ คำอธิบาย เวอร์ชัน และรวมถึงสิ่งที่จะกล่าวถึงในหัวข้อนี้ คือการติดตั้งและนำเข้าแพคเกจภายนอกมาใช้ในโปรเจกต์ + +#pagebreak() + +#i โดยหากไม่รวมรายละเอียดโปรเจกต์เบื้องต้นเช่นชื่อและคำอธิบายแล้ว ไฟล์ `pubspec.yaml` จะมีรายละเอียดดังนี้ + +`environment` นั้นจะกล่าวถึงสิ่งแวดล้อม ซึ่งในกรณีนี้มีเพียง `sdk` ที่ระบุเวอร์ชันของ Flutter SDK ในการคอมไพล์โปรเจกต์ + +```yaml +environment: + sdk: ^3.10.1 +``` + +`dependencies` จะกล่าวถึงไลบรารีที่โปรเจกต์พึ่งพา ซึ่งโดยค่าเริ่มต้นแล้ว ในโปรเจกต์ตัวอย่างจะมีการติดตั้งเซ็ทไอคอน Cupertino มาให้ (`cupertino_icons`; หรือเรียกอย่างง่ายว่า ไอคอน iOS) ซึ่งแน่นอนว่าหากคุณไม่ใช้ สามารถลบทิ้งได้ + +```yaml +dependencies: + flutter: + sdk: flutter + + cupertino_icons: ^1.0.8 +``` + +`dev_dependencies` กล่าวถึงไลบรารีที่โปรเจกต์พึ่งพา#emph([ในการพัฒนา]) หมายความว่า ไลบรารีเหล่านี้จะไม่ถูกใส่เข้าไปยังแอพลิเคชันของคุณโดยตรง โดยตามค่าเริ่มต้นแล้ว จะมีแพคเกจ `flutter_test` ที่ถูกดึงมาจาก Flutter SDK โดยตรง และมี `flutter_lints` สำหรับการตรวจข้อผิดพลาดในโคด + +```yaml +dev_dependencies: + flutter_test: + sdk: flutter + + flutter_lints: ^6.0.0 +``` + +`flutter` เป็นการตั้งค่าเกี่ยวกับ Flutter โดยที่ตามค่าเริ่มต้นแล้วจะมีค่า `uses-material-design` มาให้เป็น `true` ซึ่งจะเป็นการบอกกับ Flutter ว่าแอพลิเคชันนั้นใช้ Material design + +```yaml +flutter: + uses-material-design: true +``` + +และนอกจากนั้นแล้ว ในส่วนของ `flutter` นี้จะเป็นส่วนที่ลิสต์รายการไฟล์เพิ่มเติมที่ต้องการใส่เข้าไปในแอพลิเคชันด้วยเช่นกัน ตัวอย่างเช่น โครงงานนี้มีการเพิ่มเติมในส่วน `flutter` ดังนี้: + +```yaml + assets: + - assets/certificates/rootCA.crt +``` + +โดยจะเป็นการเพิ่มไฟล์ใบรับรอง `rootCA.crt` เข้าไปกับแอพลิเคชันเพื่อใช้ในการส่งคำขอ HTTPS ไปยังอุปกรณ์ของโครงงาน + +#pagebreak() + +== ระบบการดีไซน์ + +โดยใน Flutter แล้วนั้น ไม่รวมแพคเกจบุคคลที่สาม จะมีระบบการดีไซน์อยู่สองแบบคือ: + ++ Material Design: การดีไซน์ของ Google สำหรับ Android ++ Cupertino Design: การดีไซน์ของ Apple สำหรับ iOS + +*หมายเหตุ:* Cupertino Design ถูกแทนที่โดย Liquid Glass แล้ว โดยในปัจจุบันทีม Flutter กำลังทำการตรวจสอบและแก้ไขโครงสร้างระบบดีไซน์ ดังนั้น หากมีผู้พัฒนาต้องการใช้เอฟเฟกต์ Liquid Glass ในแอพลิเคชัน Flutter จึงจำเป็นต้องพึงพาแพคเกจบุคคลที่สามก่อนในขณะนี้ (Flutter เวอร์ชัน 3.38.3 ณ เวลาที่พิมพ์) + +#i แอพลิเคชันในโครงงานนี้ใช้ Material Design เนื่องจากมีเป้าหมายหลักเป็นแพลตฟอร์ม Android โดย Material Design คือภาษาการดีไซน์ที่ถูกพัฒนาโดย Google และถูกเปิดตัวครั้งแรก 25 มิถุนายน 2014 และมีเวอร์ชันหลัก 3 เวอร์ชันด้วยกัน โดยที่เวอร์ชันที่ 3 ถูกเปิดตัวในงาน Google I/O 2021 และมีชื่อว่า "Material You" (แต่ชื่อธรรมดา "Material Design 3" ก็ยังถูกใช้งานกันอย่างปกติ) และในงาน Google I/O 2025 มีการเปิดตัว "Material 3 Expressive" ซึ่งเป็นการปรับปรุงต่อจาก Material You เดิมสำหรับ Android 16 และ Wear OS 6 และสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับ Material 3 ได้ที่ https://m3.material.io/ + +== ข้อมูลเกี่ยวกับแพลตฟอร์ม + +=== Android + +#i ในการพัฒนาแอพลิเคชัน Android โดยใช้เฟรมเวิร์ก Flutter จำเป็นต้องใช้ส่วนประกอบเครื่องมือพัฒนา Android ดังนี้ + +- Android SDK (API Level 36 ณ เวลาที่พิมพ์) +- Android SDK Build-Tools +- Android SDK Command-line Tools +- Android SDK Platform-Tools +- Android Emulator (ไม่บังคับ) + +และแนะนำให้จัดการและติดตั้งเครื่องมือเหล่านี้ผ่าน Android Studio + +#i ในการติดตั้ง Android SDK ควรติดตั้ง Android SDK ล่าสุดถึงแม้ว่าอุปกรณ์ของคุณจะใช้เวอร์ชันที่เก่ากว่านั้น เพื่อความมั่นใจว่าแอพลิเคชันจะสามารถใช้กับอุปกรณ์ที่ใหม่ล่าสุดได้ + +#i แอพลิเคชัน Android จะมี SDK/API level เป้าหมาย (Target SDK/API level) และ SDK/API level ขั้นต่ำ (Minimum SDK/API level) โครงงานนี้ ณ เวลาที่พิมพ์ ใช้ API level เป้าหมาย 36 (Android 16) และ API level ขั้นต่ำ 24 (Android 7) ซึ่งรวมกันแล้ว แอพลิเคชัน Android จะสามารถติดตั้งได้บนระบบตั้งแต่ API level ขั้นต่ำจนถึง API level เป้าหมาย หรือก็คือ แอพลิเคชันในโครงงานนี้สามารถติดตั้งได้ตั้งแต่บนระบบ Android 7 ถึง Android 16 นั่นเอง + +==== Java/Kotlin + +#i Java และ Kotlin เป็นภาษาสำคัญสำหรับการพัฒนาแอพลิเคชัน Android ถึงอย่างไรก็ตาม แอพลิเคชัน Flutter นั้นถูกเขียนด้วยภาษา Dart แต่ยังจำเป็นต้องมีโคด Java และ Kotlin เล็กน้อยเพื่อเริ่มต้นแอพลิเคชัน Flutter + +#i โดยปกติแล้ว Flutter จะสร้างโคดพื้นฐานขึ้นมาให้สำหรับการเริ่มแอพลิเคชันแบบพื้นฐาน (อยู่ภายในโฟลเดอร์ `java` และ `kotlin` ตามที่ถูกกล่าวถึงใน@flStructure) ดังนั้นจึงไม่จำเป็นต้องมีการเขียนโคด Java หรือ Kotlin เอง แต่ในบางกรณี อาจต้องเขียนโคดเพิ่มเองหากมีความต้องการเข้าถึงฟีเจอร์พื้นฐานระบบที่ Flutter ไม่มี API เพื่อให้เข้าถึงได้และไม่มีแพคเกจเพื่อรองรับฟีเจอร์ที่ต้องการ + +#i โครงการนี้ใช้ Java 21 (JetBrains Runtime/Azul Zulu OpenJDK) เป็นหลักในการทำงานกับ Gradle แต่แอพลิเคชัน Android ที่ผลิตออกมานั้น เพื่อให้เข้ากับเวอร์ชันที่เก่ากว่าของระบบปฏิบัติการได้ ใช้ Java 11 + +==== Gradle + +#i Gradle เป็นเครื่องมือสร้างระบบอัตโนมัติสำหรับการพัฒนาซอฟต์แวร์หลายภาษา จัดการงานต่าง ๆ เช่น การคอมไพล์ การแพ็คเกจ การทดสอบ การปรับใช้ และการเผยแพร่ ภาษาที่รองรับ ได้แก่ Java (รวมถึงภาษา Kotlin, Groovy, Scala ที่ใช้ JDK), C/C++ และ JavaScript Gradle พัฒนาต่อยอดจากแนวคิดของ Apache Ant และ Apache Maven และนำเสนอภาษาเฉพาะโดเมนที่ใช้ Groovy และ Kotlin ซึ่งต่างจากการกำหนดค่าโครงการที่ใช้ XML ที่ Maven ใช้ Gradle ใช้กราฟแบบอะไซคลิกกำกับทิศทางเพื่อจัดการการอ้างอิง กราฟนี้ใช้เพื่อกำหนดลำดับของงานที่ควรดำเนินการ Gradle ทำงานบน Java Virtual Machine + +#i Gradle คือเครื่องมือหลักที่ใช้ในการจัดการโปรเจกต์ Java ส่วนใหญ่ รวมถึงโปรเจกต์ Android โดยในโครงการนี้ จะใช้ Gradle เวอร์ชัน 8.14.3 เป็นหลัก + +#i โดยปกติแล้ว ผู้พัฒนานั้นไม่มีความจำเป็นที่จะต้องแตะต้อง Gradle ด้วยตนเอง และ Flutter จะทำการจัดการเอง แต่หากมีความจำเป็นต้องใช้คำสั่ง Gradle ด้วยตนเอง จะมีสคริปต์ `gradlew` (หรือ `gradlew.bat` สำหรับผู้ใช้ Windows) ภายในโฟลเดอร์ `android` ของโปรเจกต์ Flutter เสมอเพื่อเรียกใช้ Gradle ที่ถูกดาวน์โหลดมาสำหรับโปรเจกต์นั้น ๆ + +=== Linux + +#i เช่นเดียวกับ Android ที่กล่าวไปข้างต้น Flutter มีการสร้างโคดสำหรับการเปิดแอพลิเคชันแบบพื้นฐาน แต่สำหรับ Linux แล้วนั้น Flutter ใช้โคด C++ และเฟรมเวิร์ก CMake ในการสร้างรากฐานของแอพลิเคชัน + +#i ในการพัฒนาแอพลิเคชันสำหรับ Linux ต้องติดตั้งโปรแกรมเพิ่มเติม (build dependencies) ขยายความคือ ด้านบนคือสิ่งที่จำเป็นหากมีระบบอื่นเป็นเป้าหมาย แต่หากต้องการพัฒนาแอพลิเคชัน Linux ต้องติดตั้งโปรแกรมในรายการด้านล่างเพิ่ม + +- GTK 3 (ไลบรารีสำหรับการพัฒนา) +- Clang +- CMake +- Ninja +- pkg-config +- ไลบรารี GNU Standard C++ v3 + +#i การติดตั้งไลบรารีและโปรแกรมที่กล่าวไปข้างต้นจะแตกต่างกันไปแต่ละการแจกจ่าย Linux และ Flutter ใช้ไลบรารีพื้นฐานดังกล่าวในการทำงานของแอพลิเคชัน (runtime dependencies) + +- GTK 3 +- blkid +- LZMA + +แต่โดยทั่วไปแล้ว ไลบรารีเหล่านี้ควรถูกติดตั้งมาอยู่แล้วหากคุณใช้ graphical desktop ทั่วไป + +#pagebreak() + +==== Debian + +```sh +# Development dependencies: +sudo apt install curl git unzip xz-utils zip libglu1-mesa + +# Linux build dependencies: +sudo apt install clang cmake ninja-build pkg-config libgtk-3-dev libstdc++-12-dev + +# Runtime dependencies: +sudo apt install libgtk-3-0 libblkid1 liblzma5 +``` + +==== Fedora Linux + +```sh +# Development dependencies: +sudo dnf install curl git unzip xz zip mesa-libglu + +# Linux build dependencies: +sudo dnf install clang cmake ninja-build pkgconf gtk3 + +# Runtime dependencies: +sudo dnf install gtk3 libblkid xz +``` + +==== Arch Linux + +```sh +# Development dependencies: +sudo pacman -S --needed curl git unzip xz zip glu + +# Linux build dependencies: +sudo pacman -S --needed clang cmake ninja pkgconf gtk3 + +# Runtime dependencies: +sudo pacman -S --needed util-linux-libs xz gtk3 +``` + +=== macOS/iOS + +#i การพัฒนาแอพลิเคชันสำหรับ macOS และ iOS นั้นต้องทำบน macOS เท่านั้นและจำเป็นต้องพึ่งพาเครื่องมือ Xcode แต่เนื่องจากในโครงงานนี้ไม่มีผู้ใช้ macOS จึงไม่สามารถสร้างไบนารีสำหรับ macOS และ iOS ออกมาได้ และไม่ใช่เป้าหมายของโครงงานนี้เช่นกัน diff --git a/Chapter2/Flutter/desktopExampleApp.png b/Chapter2/Flutter/desktopExampleApp.png new file mode 100644 index 0000000000000000000000000000000000000000..5eb21c79205c925a3f74ba24d5d810a4a6b006f0 GIT binary patch literal 37840 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 literal 0 HcmV?d00001 diff --git a/Chapter2/Flutter/flutterHotReload.svg b/Chapter2/Flutter/flutterHotReload.svg new file mode 100644 index 0000000..364c6ef --- /dev/null +++ b/Chapter2/Flutter/flutterHotReload.svg @@ -0,0 +1,11 @@ + + + diff --git a/Chapter2/Flutter/homePage.png b/Chapter2/Flutter/homePage.png new file mode 100644 index 0000000000000000000000000000000000000000..db27f47609d7b7bd3cd02d0e603db6ec2dc99388 GIT binary patch literal 38346 zcmeAS@N?(olHy`uVBq!ia0y~yV1B{Cz^u!`#=yY9(-!@hfq{Xuz$3Dlfr0M`2s2LA z=931=mAFQf$fk71{T%MVil3yN@ zS(1~=5T2TooS&PjP?E3Un3qzNpP8Z%TvD2nneW>!kjucJz~JfP7*Y}U=5A?)$Z_cd zAK%|QD(d9K(`3#0jzwQLccN73a;7P#*1vQ0^6urDa%o!7(xX};+Ia_UnH-sp+_l|# z`@Xzq-<@ZADvVwW-aoIbkTcqBZf(80di(oxZ`Lps+?M@rvoxv3PFr1D-_&xeYhhuh z@&bhx0VfW{76GRY?^DOz*5A5)Tih(`iQwZ$k8XtpR#e@56u&ub;&zr4&a3@U7$9ye4y-nI$ zT4lxM<=Kl*pE;>B?LiFKRu09M9Y#e(#dC}|8;8b*rTKa1E`w=P{AYXfrloEv>(5HQ zTRb2)g0=jq{#5)~Ca1@3>$%Nax98k!vOa$Q+yTbFHw8CMKI%P9P_)!-_YAlhs}e&( zU0+_*H#Fy8ij|r=YO#*!}bVyEzI!eth!m*~Cec4oT&z%K6R}+_S4a^vF5`+pP1O#t&uS0Ei0ZhG5)%+usL$`C;v8n=~ZW$5`tYc ztNosQK7CCmSByc~jVJkPm%W5l$_6uUu$Mu^(^b3|Y;B~Bo^QTsl5-Whpvw$g^*yZt|Y$$_}fhmDngN$u~lTPYv)Kjz(;5oq3XQ~TSOiP<`P z^N#25tY`js^7vND>bT06tjGHHMb6gI+WGcc;U4Q+t*X6ovr8{pmA*Q`{{H-ty^hSe zVRQffdF-U-TjMl4=h(%I6Z!AW_xzrBcS~ei)%RB?x0K&YIe7i^jK3e*ZN8roY0{A? zpFU~nuB$1tK~9j|wr$(3CElm*-kqB}`+D*9x#by~&)g|}E}L_E&%SGpRa+UW5}y0r zQZa5{lzZa*Sw&;x$#dr9T$4F*T`y@_@NvFdDj?5unwy);ReuqD^Y-nTOUHX9&#v9x z^K{zA#b+-uf`n`K?A?0uKj-=X?;~gZ_?qAqs?Nj&E6gv8M(*&wR2qcQ`OauzhcYp9n4<8=ScNtI~DEIpB6v3b|XVr z%OvZ`!MEG*F7h=ysoQedHP>_N>+>_J=RKRFC@|;GNqwV7DfyP~_W#`$9l7Cy`=!g5 z!AbAcPTT5lMjtzmzYr2Ra;j^tZH~=Nfm6Qw_FHewxyj^z-tEn;y~nq_ zsc&7qTKoI`YIE)Iwb#;Or#K#DE-Wog{oB@i$1G1KdRxwAy`cAdett8_4Vvpy^Qh1) z_ue7n^LrDf#rqHT^sLz}0*|t;Z%XCP+fk?TdH+AL=7S5)u5(&{{qvE> z!V$mETP<32E@QL4S3pAgv-7jNH*Yrn{QT_G&d$k}Qc}xe-%R?E`!R?C6c(HJKddRR z`}~*x%%$v8Sq=Yww79RHTU+ZKq50EQ%kS;GM>jRU8$IkczH#%$htumarnt@iQ2sH! zU~&4yG%QYSH@2(Qvx6f|RpI5KX zRK1V2+LG^nWaDFpn*}MMp*MGz&tKVdu(@gH?{y!4{Q5O%!h{3<_WDXG&-H@$sp>|X zJb&0Ow;*_V-wLfcHlU-dt#W^eE}uTl)jsxy2^U zo48PO<*Mj>$L z+;usB=OzM&{ql8!|789a8R_`RQRzrT*SeR)^d89?si+JUAlY z1T+71+gAaXx7kZcox7BJ+BdVjZ~t7w#remM9&PRD;Mh0k`&P~KQsUz2i;|PJo)i%k zWiI%8;&nyZsgyY~vOiy))@O+L_gj9={SBSx)9R1dzrMD)>a6{;^Dj%R_RaY$xnJj3 z?_2A0_KU(N?~1&&to!DACyv6cK_acc-|ua2Xjr!A-?7_Q*$jOcvwvL^<-DYCX3?J2wu4{J$leIU&|8O8moR< zYJcx~-o@2c1{xa}_0I9V=`Bfn`ts@@(XB$#u~&c8&p7i;uSFny>7`3Sd~!BE@9*vP z$!un4ojh;exmjCZcl7%we0bovY|lO0>Y_(SJcApI%FdjvG5f8&XwkV3SO2Wt z{%&q;@6XTi>wourzWKV`y`@&I9iJS^-`}gvxwWTtvAZ*4#`Sf&`~Ur6uB+Sk=hN%_ zKYO!G4<2NW_;Q+m$IhLhdds-<_5GWg**86UKlKgAO;0~Ry=3><_F)O>>E|2%{r!>l zFXq6VNAIc+bHRF7Gea@_Kw?L6+HFmQU1InIx1Q&053c)h zmnX04UlQ-BQ=(2Bg{8Olrt_b-`76@b*C!$(Vvuoxp{(VNQ)uY6_Z*2YCODq?{VH3; zb)ozDcWWXx3TgaKtb160{^Mi+{U1&)pU=D@?XA_Gz0$^&k0!6VzhUL4ET4JRWn3pu zYTo&NKv_h5`qwF81sk?MuRm{hcGJ^(gVJ9=pZE34Sf2V*S{&8_~0l&AcfAHqbnZx|H2Og=OuE@XE{&eO4 z3DajE-+bOCb=#V2U&`-;^3=!UpN{_7oX6ZfUFY$Gh0e?V=tgh5xUjZ*SLy3hla@ZO z-j@9;=~WpdQIxqmAFfDxl=AHS?9;oAmxaCbyw3J~`X={i={ezRt|u6L_$8hH`CZS- z|6cx8{c?AACO#=$6TAK2qNd^%%h+pgf0IqCH!lddbDok=tytA!t+~nybZBn3arq{RNz`14hoSdCovaViw zl)YEPbz%Pedu!r0Z}TePyRb3YJtj7GwaxRr#n~O}H1~?=y=yPN{`%$B&F1=RYt45ToIGGrn?T3^@t1d1H%l|B5* zG~4&~hNP!jvrM@SUcX(xq4IUu=Kb1LT6?6;*%m}^UpHmiv`vYNfAY5J-qx|dyf5Wt zQE&m@*8JaGvesLUAG|luH2XZiDf{c!YjxDrrdc1mf4F+H-IChhWq&q&kly#Z%+Aj4 zdG!H(x7gRv*bo(U+_g>puNTX6QLUygr|(X#yFRzP;BTpN#O^%X>+$A?UL7ekP2I|F ztEd<_`^W=6Gn;4z?(NfJWlV~$em>H~^y%{_3+efe+soo4LaP1dd`^EQ`~Jf9=YI@N zaCLTiLfUYhU5c-5tG^w%c~es4=og)D`)Yq{>S!rhR4|m4m5GRp7e7ddw53KYYR(D4_>=AZON0ATrtm+C%?SE?mj!`(q{K^CZ<_M z#m#{{@^)8r-d~G8HuKg_r>I#!Q`WF0-`u9PYt!#fywWBLy1Hvm9rbydentCoobZ)x zZ?#P_BEJ1Hd;5IN+VIsIR&*Top0=^#q){8c^r_qV`_A1tpI&_X$L_7&*P`H|s(NeQ zm#*}K`tAkyR)wC&K> z;Z1v7_&=TKjf^65o$~U`w)w@)@echMQWf%VM(5U|Rsp9g^{ZBG%D-Q?tNe9S_hw`F zei>DDb#@KzdEegMb$=hX_rgmNK6y*8#6-o0mEXU9R96q5*>Pr8Qxg-zoi#oYv!=#w zi}U`uZk^tf=hJKVHEp!F(W_)mOG}x}7I`{ATfUALozS zU*247o_L-2`QAwR3A3yBwf}ay9TgGLF?sW5Gf8%K_FSQWZTGcT=iUz2(9y7#n=|K} zzXJDzjMTkXZ|=x6uB+R(=gXo0AHIK9*0YP-?Xh*s`=x8M@9L%P=Tbbfby?Abx`g+B zMa7@>Dhv2h_j}v_-L%4O^YL(&m;N?(3s1ejdGrF?^MuMrJ8o^VIhxIW8md_Mi8pU&@iWu@m^(k@?lw!?B7>)Y2(y7l*>b~~nVuii(O_{cxYEs;Z0Y+=cn^r)?)3SLzFliSe=b zt=pW&_~Z9aK{2_!X>sDEE6p7;e;#e>J^S5IqE6(lJ*W2j+y7^>wzhV=ThRP1`KndrE0J}2dRsE@-qP9Y++LPeA02#s zn|k&JD_#A% zPSmL*JJfZ;yy@kYO~nl>Rv6b<=Ko`D{>;VJ+^GNj?EaMXWt&Cjgs-qEjEQaA9nE`T zdp`fe^`iCJlRZ!A?bg1(xK)=|=HT(zg|5lA>-wy6z7)hJ+~j|}bIPjTug~MPZ|vLq zYKb8z;N*6fzdw5O=1jh~w>O3w$DiExR`JKrUze72?!Wo_ys`1-h)p?`{WhNjzTc@; z_x-X>Lk+xnI#QCi5&rfl-FYk|E4pzIoC(?M9dG;}1^S(n@kG9Ua6H^!Y zMY`YalY#Pj>BiZ!rQhD#ntJVwWo=%yHS=@WrAwD)d^I-HJBPoGU1MGC z?+33QIbGLtw6RT{R2FFL`{!@vzn$qEauyBO)<#`iR9SqiZ|BVAYQ846-}wZjrQ4gE znXmWn;bUiK4_;rE5y4`9w}ScZuF|7NkIu}C-TmRsW&fF9mt5JJ7qI=WR*S&(O^X*M zvhYh5MmBxcK704>-0=9ii%A7>3za2Bv^lQPb+woqj=%WlzoYZ-R{*?OHI!UXcTbj&{j0l>$|bT zA}2T3vhdN8$hf2=rR9F}j~%~#`^&10T=I1$v;X{Inm5a4Vt9O=poX;5zsLUjXXu9C z{B-~Sk&`DoIs5I-B=_6#IAmo>DO#5^eYp9&Si@9ehTT`)%NL$7v-2B1{OFnHyieaP z_SM`eQ;wM5uRE^HZ+~L%_d7@bF|$|xxOn{LKINA1`0B~e=gmD7Jb50=DK-1*UpJqx z{kG+vRh~}twmfxZ<>1+@2juJj9bNPN-qPIJ*Oo1OEli2!6ckjMev2or{%h*nMQW-`m$LB7 z9B}5pm+z&mq4D6m{lBDl)8l7eGRwK+apIix&lk<#8Gd|Py?*BRtJiD(oLpXGkgaB~ z_eZSZOApVz`Ck=<=hxi%61gJ!ZiCg^aK)A#*Fxvb_!>27>eQnP7G4jXdD!js_M_gB zo6GL9PQM&vRq`$>_spB8Pfs5En!QnTerNuxNj`CVuku<;ub%sUiqylk@t0>*=HFB? zT*}6L*exc1*J0fjfk*qj*I&Q9W21Q2q6t%`#4LW8Sv8k${juJ_Ubmp2;MF$Cx!Kv? z$@=<5Ma3u2oijVVJLFYRzO}WrRCVRVDRXkl7B0H{^24VuF0QJUJ72kE|5tl|tk-bW zF>b%MG~d|U_wL@6O;1;!BsAG)@{QPz=DoJOwo*YsK~7OoyRN2l#>U1J6qYI)8lKFN z3>O!Vxf`RuxYySZ2a%h{uOSvFGRmo z$vU&~KfC+#eMHS%kJdMDa_&{7OU*XRH9VW54I9(sc%3D>ApFDEj}O;BP~i@lFwe%Nh1Ity-nwb+h_Be3&z^{Mz!Q^^Bb7 zU?Lsfj~6kOz;(q)2`%7;@xC^&yny@9R)KMs0F)QVf8)v1lIP4j5bgBf*&nK%cG3@yE8j-WBq z|Ge9_m6?3_aNyp(xY?>lOc$?M(Q)QWiI-Q`*2t@qK0BY-7;Jx~)IMhI6u-vU(A-4= zPBC1TH*eljQFO6=`27BqW4*NjC0t9Fs!o|QB|}{B(W><9?C#!P-Bp3AmX;HL?2ve? zBzE$r;*%RI+e)RV7>3{y%1O*9c>S|uqQ#xXL_}DczeSP^o zwKa@-6^;7O+gB(Y_xl@g`)|S4$>|qb1)Mtm3q(g-OI81#Fn_+gQ_Y$fhpz0nOixYD zj~kyne}3`CZT9GB>$gg3MRgsgKvrgLmS4vTiS_@Ayf#vcG`Lot^t`2`xGr<$Nl%R~ zC+7aPTROs)_ARPKZ?5p0-sHc|#0j&=`uC>iO5RU*dVIVe6cpu@naR1W?3((!NuQk~ zlt9j!{I@`N0z)i^V#^Qyi<(_NQ7Zp7dwF?X(Cjk1>2i)gu~)|W>*3aKhqpQ)a={`w zhz@XaU%{^8APz~&9Ez_PEBSW`Jeu|7)hn-n>Fa*{{55g*boVPSgI(O@uIs6_2rRnx z#pIPmhupg5H@B(Ja?0H%5O#8-@~d`6W;P}Pp-s+{i=TQn=(X%vcH`EqqWgdO3oiRE z*3{8aQL~a#PfurJV(RGYd$zi=*s@H=>9=9vdku>!v%|Ob=HB>`^CWlE*QxWuzSo{R zUT&sZ{JGl3wp#q=s-Hq;chx@MwQjcjbZ>9Xp5I=+3qk_Vr@h!3*)VH+r{wqgL-&Nz z+xGo5KELDtnI+Sw3FlwY%bdHmT9`>n(!+ALL)p^vk>2~itjb%wN=oCLr=nVodi~#D z($VLiEWT-5ntXYtb$nf)bj-KFPX|iOo@a{hsQ4eZJJv7!{ZGZ?et*-SU!5y`yg$*S zzwF2E+d*?gkDvTI`$zH1EWYJ2E0bTo5)cqL(5=6h$>GctPZxLh>}fkTfr2x}I43u^ zGW}J_p1rj{UNnEdxjSFqE&1m9;=^rncdFmlo~ih5n|5~A$$PfdCiB-x&utbzdwcux z%*SmztZpwBc|K`k$+XGG{U%IFzn~ZAf8*ko{}ELdEt?WQ7Z&NC485+pEZb+dU2R69 zcz@#4vLwC3Tiedv;|+ILW{un_a{aj3j#V!{NPOY=o?~$+-2L;`nP1x#XX)CnQP^|9 zCerjs@wY{O;j;6b=RaJ`UNrOb0~51nAu<8iF6k>DwlvfG)7??ykls8wT>4k9#Np!i z+Ydi}dj03$H>x}ChDsfK#BcX>%k9jv*lBlbS#Q1Fv@7Zyzh&7vKCW}J@1LzTf48XF zm+N@{nyC(DJrBw+7<2Or{xz^54W(s{d7x#mm z<>L9{lbxf>3f9HB?GI;6Hkw%deM07J$3v+c=Nu1ijLdH<(R=pcRPG$@YtOo)G;JJR ze2m@vcFgV7|8wHxuUqqug*ci2J-lm8_K!U#%LF&3?!9TYE~36^yZ!7Fx!b=dy>;Kc zfeZZ>3->4K8OF_zcS_f zKNu{ZH}f>(PPUC2_V)eDm-}2&yDt4TX_CcUKll4~dw|JKT5o0#BWoja{PmZ9UVYbKfmpaG~G|&%Ym^YxBPCV!53OO3syy&*SQw z60X0xCm8Yh>no|UN6XajKU%E6KmFtT`b|%c>(BgnM)u1WvwVT*?`m7JUUo-+J$iN0 zvU#TW>^{ane)jBGulc<*=AWO3N>}Jd?`moJQE{wKdimK^s;z8mn=@WbaD8&^>l-VP zQzs`Mx2&tMj@~AxdiGd9U+&)5$EUvu^<1j(R44uM=9G%xR~@FGTITxNgID5k%j{X# z9_$D&$gt{YkNZ94eO>gqOY`?9e#_=J+OSet^!}SN+j-BH+t)vPDOdK~KJEJC^t!l% z@%MceEY4iB%c*(d<%oaJr{B4L>Jr1Z?uTbCnE!upzCZ8q`cG~z_w1;AHvf;^TQ;d1 zTb}IG|M%dvyLCeH?e28(zh~q3+j#R=YrkB!ZX)+~$D_agSCs3>vfG^MSznj>^HMlx znSpMA^06lZWisXuE-hpB{aUcF=uXxmrM2YWjX2YpVz_~{$#@2+uQli`&4qp+sAitaew^$*?HrKLqF%) z?)v=J{BvOF)E_@8WMpJKy}X`GzBzyMZy{d)wew_U*}pAx43g1|`zvwhrS&1c>(_73 zd+K#K;?KY1E>`nYo(S>04wU-#_$7aQ;*4k}cC-A1kGpDQ_E;MwykOpQbu)8u+^mDU zSd&$k)zV7ac^XJp=|Es;FW4vnBrp(W5ZoRuY zTkq>$NW0!7Cmt?7<MxN=%FI$6;&({K(C zue#pyPtV_e%(yu7+uGR=9wxO1&2o49liAlkS7GalM>F)L7u~!2Ov8GSOy>Qatn>Iz z%0x&yWp?OpaP1`EFUl>zjS^9N&H@+S?Tt_?~Fis=4L;HAZ=J+oLyMs<^ug6l%@flyz-OA8)~hsS{?4ou1hdaBhj{ z)aw^N8T^^G^&#smhwBsi4!d7ExA#r?^4~LdzX&U7dptd>9<~-BcJ;RjDJ&w@Qd{{J zITy#@nfo@Nd$XslwA+o16`!7FA2&M6cerz@&MoVX=g0gX?2--ssebg=;rYMR%s<`w z?SDZr+kAChtn-|M-FnK$KRh}f`=S1As@Qz3g+FdM9_nhlthvH+7qhwn(=M^bk`l%k zt4kN%-CgDg7A!~(i2m|&wnfRiMaNcN?=_s*8}Fx__=9Cxk4D1LcKc!t>$#UzPacW( z(qEtCduu_{x$kcC=4L3Q9nYG!WS-)#ZHv9GByn-^CSYbI0%Z)?RScPn`QLa&A%U!`C;(th=JC%9bAN+PY-A`L0KnEt>k~ zOA5|w)!hi_D&PKE;_C)BuEMsIs^+H!t!diYP1_45{K{P_Kw`NE2c?8W&*Z-7% zv7J99Ain(Ex_>Rr%=4e`a%`-r{=x9|_XOh!VjEj~Z#}WPc=^?{-;%EirybSbe@0(j z``N8Ob5sA{IrxQN{=vQIrW=2rCT3Ny4Je;p^!v!xBbQHiA8Dz$Z2bIcXMgwNjp50; zMY@tFPM>xDn(O5Kf3i&1*~food7t#{T2@rCZpXHT=O4VQ5IHI+TG$nHm2 zhI-NFf-@5tzL>nRXlay%FS^P%frklEyX}Q1A?`d0d%^T`=oz3C%Ub|)f(Mq!$uZ(Z}IV_Yn)J;yXoiiyS^!6ErlNXsGg(_rs(vD{T(96poLH6}=W#yA-7z7_de8gh z9tHg5eUhX7(loER>!|d!O`oqm|M{;%_W7P|oC`{gqkB$rs)YXIyEtvN#pUn!*k7)^ ze_nk3{?o@kDHJ_k*1V+NpgUTvC-LzAI^`(o4_8X63zltf{d7Iw%IDjf@RzrC>-HtK zuif_i>T4}K`zJS6#+UqK`SJ3kb;YS)D%09B{N`yMS{7{lr({B0Vep0RlC1HzXRTKY zpRPN8E$7jV;`yIW&G;>`@0oAd(p^__;-{FeJa@kJ@p_x%haRU+ym%}29=H*tdbGn5E8=fDIG%hUIv8P!> zrm5-W(|JcGHdk8|Sg?M-*UV9LMepgE3)}xa>3_MHVmapQIt$OYM@7Il*7Z+NuXLs`M^ZgqT)L)=*>d&GDKkjJlt0)(X z&-Zt^xc$jK%lc2gM<*clyNk(SwmXl(Z7FIz45y!b>g{Sriw_DDB?ci`3h2TH>Q8)JLEs_*`1XE-|}ys+?m9Gt1P3-wjrr|oyN=?9Rl0lbE>|&V|mW?UHbct zA|-NXKNOnjM{YEqu%TFXH@~c^kgJ`Dr;57Up8UP7z~GTepnCtN{Nsv~c+dSX|G4MD&c(&0%fH+ZE0gV0(0XOD(As>n z{Vta4*BV(Y=B`igeI+4!t}!>-a^iEh(|WmUZPbDfn;mib8G38Mlsj8gf{MKzbd{_v z8=p*BvuXDFE@L}isfFI$>F*bMBt1&95Enf3j`?`!>A?Sgci#%;q*tn0GB}Ecv9N^d{j*YyN`UW$CBR*MI(gUt9a{@8*~0CR<{z zpI*8wH{hJa=H|2NuRhIPdidaG-NWFRiDy%9iApn;SX*ORIh= zckj^THBrKix7O&_o~=7``f5q_nyK*u2fv@UJF)q`?6IQx53at`va~;QVq>trrk{nS zQ)1jxKSo{UpOrr!Jn2bZs%HM|UFz9qpB~6KoK1OuN>}B^mgVjfjJuO@gw-26Y;*QNIDv-6q%jc=}1*_E`J zk>XLO(*KKme4${S_cr(M!uNi2tv()ozPa-A+LbD5YFV508P#{Od_Sa{YyEq1m&MD1 z2|X7N^1OO=#E$#2-z%H;k5`PV9&Oiq{##eBWM`sD^8EQ-cF97Yolo<{%@*7K=~+*E z#@x~gTlecLTzlcZ{&oDLpNEu6mdu#`yjuCZuaUs!WYO;6^V9fcclAwApUV3-a%Y9y zMOQhNK8fRxjjg8e%35Vrz6i*@mc4GuksT^m?3j0Kyszc=*2Aja+~=(Nw-0Nq~bXi>v{yB{;1Ei<>u1%+I%y0$g;$kwMoy#1oMWovjZTaU%V7YtK(KfO9fBI%O$-No0cAHB}?54_`< z#HA(sb?M5M+#lSbruM=;mWD^t=KS9iHNh*3ufobQk^5@gnUzOBy0|_M+vT94^6^UK zr&-$$-ab8TMe)Qnbj~a$Rg#M8Khy_xGoke&ETgDzTA1EMDZbx#iqm!?U+bLPk@+Rs1a<-2&*l7Jf;2mE z-|hc+1O}E)pS<~jZJ?%(%xzTJAG zS5Mc!Fe+nzZT>FdeB92uzGLExZtQ-rU3QCs%upcchQOKF~Tc%Mm||p zHD}J;0Ig@g*1F1e7j4oEn*H$2ng%t8^_kLIRj;2$XEm?t>a><~+sqjI!YE1S?dD4! zo_*?y&tyKnoVxFOODSujPTYo>jQKrjhhF&ZDfB9yn`V%39)!#w@MdU*4|atL)gP?CY8O($M-wido4D;o9mQ6L%)F-agaD zH#gzxERMX&Me?9tW)}CgUDq}rdt2n0rTNM*H1y}I)jNIW+fANwMP!;@WX#j{JJ+vI?@zCHi*d5C zE^nLhG}dP7q&q1|%9A^LyVMF^1VnAiKiApv_{mDPkPsukcPdH;54HA1x#V#!*dcJC z+~V#ZS%YWk6X#8IO!_3bsi*hlm4%Jpg2iU6n{a0G>cG#cXEoiF-QKo~KK;YLH}vY& zK-Z(E{x;6qws7CBPua&N)XkYtFZAIP|AFhrrPn`;&A7CSIrHId4$FCIOOHFvSw5-w zfqUJJ%iYiOY8wuI4nBM9%#5iHPI4@h9Dhvg(At}r#uF%GGwJ9HKG~O3?#cDfsBKAK zDN)>4V3N%vYgKY+_gr1W*L)LeBKJKD?O{7`kFk35<4c_B>a3fzmtT!pduzcqojqEs zm-R$;s)%Z^n0<8h_gZ?toHe}O{*H%|;?h@=0gvBqjIz6N<7SeM-cFP2B449yp=l{o z#!8^|_ zb<#&$-!)e~n6q>K+=rs`AobvxV;K8_wO8)@S#2F6L1= z5?Up z&4i!Z&QVXRJ2GV-@2YLCvRAgwE6o)z%(W5|JlMYZ-s5S}dCwpF+a-T_v9aXkrK$gz z**-iuaUpTV?sDCpGLiB>x62px&dS7}XV&Fg*Bk$=$Xye?d)kE9Y6~ejPoJu@^K3)Ai#0Vu3yMlt z2C2`Di&uTS$YS^7Rh7y8j~?}Lvwix^wTkV+(^ab%&s{Ce=ViB3Y?;^kOzE)jy4+g_ zBIdYWni;_N{?>tCq1l#`mOQw)kGbwD{~ICEo|iel^8^?Ens=wr+4%Es)uV!MZcXpK zzTviH)KAm-R{3uGei-K4-{9sCF5;Zn-WMbwaN>j>oPIjX5-tIK_Kx$#_^^VhF#`^oT&b;kc~5}~3Ok{4U*>nyvziua%EQNcHs zGrSKsnj0?&T*`H0>yu-znJ>D(PmN#GI&Iy{ZxPz}_vx0`f8oAwXMVxteb3Rd-C;4t z&)rq8eOoJIJ$=T+A78z1OnZ0SH+Wt`!}QAd)xM7zZT?;9tyrF)cvJ23>-4$a`FS!A z+gC=G@V>OJ;;>tK+)`jxd(`DxMZMjpZ#CcBFgEn2I&&Q|iuSbSSB-|rw-Z%03{f7DT?JFyH&gru{`o`ZrE!~4d zd7bphBc1*WHMm}1|GQXs(Xp6WCCi%UYX6k1?pR&Y?)O~6p<%mjR#@82HLu%39tm@2 zN?n+@Og-2#T(CjwoXPvU{QLiK@UFj|KpU;=M!#MT&Oz{z_jVx#>)7Tt>>p*pOW<4f3?^;l{q@{Uh6C#T;C;m?wE<+ zauMb*rO52kE9Og5x%H>Kd8`su<+7|THzH$g4R>yU*&(O&d&%p+FG&5aU~`GDKw(wQ zZLi`JXLMY0bArnbhCgm^{C~TrGy7-N%L2Q~1;*c=2q&I8`TW45);BNz@k~zhU4He| z+c_sTs4n=Q;r6{m@zHA*BkkI^;;r(JB+g&h?rkO=Hb-;+1D!`V9t!X9ed)XS&DTE? zp^=)mvj6(=&zJ6; zYmv8bO3C5#`}g+ct4wgb0!8@5ey`gd>cDcR<%Z&pj5 zot?e8_B&0t1;Ebsbn~pBD$Bz^j``Tzsl53>$J)*6`xyW2czLOl$KE~iemSS- zLwApyJMHV7+b=vQF_C1oiurr{(y8lxTMq9OS-s%dl8J%0*ydl$&74x(<1rJCrN)_@_Iqzj(L5G$6vIhZ{EhTDgw^FW#3- z+L0rgK0j>Bm(8l`MpH7lZ67?3T#@`U`x?`oPaU@;BmeC(UOQ{+!lR#bw>5eNmYKP- zTv(Hw?G?P)qu*EYeuP7(FY_!G*2OpE)$MLK)E;Jt+FH0&#jxp!_tl2~oNSB2&pdyx zxOs=}0h{A9Hg)#LpL=@k_c7x?(~e7IhI>@`Sk%{V>bSpc=J#(ace-1aT=IBtCMaVW zS6J?%YW~F_Fw38*Pwvr}KNepK70S!6lc={nD_(xfI9(pT$@mz?rtx76QifK zGtvI@vCYSKyzJY^^IGuC3%hMoQjQfTy>@!0AA9oPlU3!Du6_}CRyX(f+5Y=STVBha z=(9cet@ZPdOxK&%7ZyJI{V41ClP70>Z?IOb~zf|b$@+l$5?wY|6*ZJoWHMizu5Yx z8=iTeRa>Wdxayuq!G5`2}}KZ!yx_Y`nabG zwzj&x%Mp?OBeuzv+I=y(d^7EqiQHjFGVNjq*Pdg*Tte?+N&Pep9|T zXRdX*$^u{WS+99T(v}xgDqly+Ls^u*lZ@N z;dkeBzWm##P5W;h3klm>$Gv*X$&>XTKk3$I2Cd!cVC(zohRt6wv)M~U1@|X2zJGJ! z&Ijuv?$rBAPkSU~ewIp2u3tMR!q>_)liB<0#%0THbBJqg*U)R3pVszavf1LMMb7Kl zLrvvvD;~bpEI#;Y;jOaWRWS+kV@jX1pV$~&FQP8{px=`Hhx6>jsb2q9n%4X}BxQFs zEwt!iZQ@f2gJl~&Z7p1LW!ZJ-dGmTXI5-Uc+FSjy7h1s1FXQmP?(de9Vyfw@=Xe@k z$hncNA{TY0>1nm)tb46a_g~)>n&zHWra3Q9d|lRjyS&|=7 zRE^C!`YpT36`8WXpOo2m`=xz4b3NnNcfX`A>5DISZH&3D(-?aB-xiya7fIK$ZH~W^ z|CjjU_2P<$!S=uMZk~R5C1_5~?aTEZ@k}{>A8+eNdjvCHp0G%9 z845+!9G#1geR^QM{zAf2#-O>k3@R#$y|noG*JRtizNP0BAhslZ$#P+F`PFAvDNbGV z<#NkAo7`R3Lu8ZVWR8D768d?U-qbrU_U3r@EO2BF&*^1NNlgjLXb@J{(hv7Jb8hLa z?N?_=6eV@s5Dm^ev1HoR^Q(Wl*q-xuR9YJtuu}*}_XcNqsr$&pOm%IT&AT`25bbU#zN2dD7aR3c*7{mSrw~ z1!QH_s<^t+qrQ{G&eUh zn{C_nXY2PrzstIKRaMfWDxZoOAr&-wOjp)3>a4Tg2P@ArSP(>_;e_~qa7 z%3mJ~OZ09Y-k!hb*!K3d{IaWlSA}lkKlAu#`2K{@B~HH|KCXOm@wcS8Lc^VA?;j6- zUjJ$O>CcnUROc?ILWvI?=k03E_nub&sKNJt;!62{o;x<$E|#zD+1-5C!sLB%u>Q`M zpG()I$KH13XkcdlHhIQ`6~6lx^&H)~L|uKtlqj(||G#UznEUrbS-64NlVAW7FtYI<@*@T;fC2|g#MvW&^ES(gSUT=%YfS^WIR?aI%+ z*SDTzSn_;T4u|&AcxhYT)66?E>!)n8-6XL%aA`HSt^B>W2beb}N7S3}M@!o_o_)I` z@l6$%@TVOcZ}-0GhpAyWE#o zFHSttVQ?-rwzgd0@1NO|X3uuc`C^$XrttjuQt8ba1VM}+jo2MM_ z6w1l@GROC#u;}FD7f)Q3F_lRSx_(?+JkquFwYU>Up`n*Y=Z$lIvFDyv%UPSxx)96x zWV!0((2|{DN-Zn6ldo}pdvj?SS7Bn&n;1>DON;p?uJaZ98us>B#`O!=a&MoGj}M+& z@7yZXJW=^M&z`+&CcK@f)%lcvp~a0u8~RcYe*K`3USlIuxMlm{g9rJ(FDl$&R<63- zVD^L?bEkHjEMBD*y*>B38nRS8u=j^9Wf2QBKb!%2^dDh9Fifbk&FR$Bip>Bs*%(V0i zj9p!8{2eds@16JkeNn>8IOT;GRhND7eYiA-M_YCOf{vawHkUSk;>daJa%r|I5mE5WUQHCBec_XREg6AuZBY3c3N-Db9J%9MHk zdBq+@rDrFD7VxPay|!NT=^ue<;1z%=_A%Ug(fqsCuU~I=(#Ja9wrkOZ_?mxw9!Jj# zxGrCy!DYpoB)r+@XZtye4*~6*Va>%mK2(7h>}@*pg(oER=;n>v&AdCZXQe0ShlHvc z+d9uqReIjO!KH8RuZ3#AA4V12thyj=`ssq&%$pL43U+rBxK7E-rnx6h^vde<%3RsB zxL0m}o1TnK=z&IyfX1ez8}(l2JIjRCZJ5fUeZ*9n050O*eZdbD`mRo!*m-lAD`mD|<;^yjiuiU$*;-+ST5BlIx%4 zW;}b{xq7c$vZvn6&U6b|QUAQXcGq(XvoB2xJG-ZF`}M#%vz`8|^f&Nu<=JT_$R%N#(iU@4Z=bk8eZ65E=f}No^c09Vj zP&&7EuHlil>FyO?ORK^*9N+&tz^Y>2`reIOCfwOlac-WCV^Q5z{}>@J=UaSldOy!R zE7P_1=yccKZJr#8di`DBznJB{ao(J^Rzp{J;S!g&l&CJityjbT z?yOt8`rIy8Z4Qmu2AdTePN-DJU3+@$`*(MtqMa%N9tT+L*W25Cu9;uG&-kI;cbog~ z4;PdRbylC6&6HN1dc51Q;E&0&-fh8i<{dF>_bj-ham;6SYw72xZ=t4c4&FaBmib6C z{@m^1xBjS@annWN^yJTL6t~{E`m(I4scC^$bMDH@Eoa(N9<6$tvEKT6p7ufJ83wgN zfA9Ph32!af@lkNyp_FZ@Qyw2}GBs%Wr+nNfv#mGx^<+)!H{#mIU*3^@XxG^x!_EGw zNJCFcMN5rs_uY54e=&irp3$BSDpHT#~~d`WBfI~E%d|NhBy^Lt0$ z*Zr10XZ>B~|Ivs&Tc?CxE57?ELvO~ty7!fvjn!|S(D?M}(+g2GGyBP z*;9|Zb8KWzE_j-o5}s!nw_ww%X$Mxc9^vm$S-eVSGQ%%kdAE$Cde@ex2In)Sitc#J zJ;O$6-kC={S=LwkS`R!(*t2!&lyFO{o4;?*EQ{Xk@TzlGVZJK{8=QM#N_r6q*9Qi|UEYd#>F~hRZy~XigHJV{ z9oQH9M*pkixy0_Y7f&woycO?yxMqol^31#Jt8UxM#okpH1OZD!+0Dy$m>2K9yXVWN z)Ble4NT)phIs4JyZvL0={~OP_ylmUs{F;|frx)(#zi)j@b6bIu)18nhmbYFyny%E> zU#_RnR8TECb9VT|us2H;>$UH%i}H4JO})LzOPFK9`yDrZUZe+2ndg!8DD2y`o04X= zX39#l{2Nee=3R90w7h-NM| zUEAI z);Bg;PTae+k!POO$9CZ+&TDtq4RB{!*&fn80Cu0->d9?Y4`fos;nHrZV5|^ zwlgOD36}~Krd~O7Y~km-N(=av)%%XbZE61dw0G^SFzv8AKlsfI?&{gx*bsF~^3Gj9 zYY9EAPv00rMZ~8Dz2;O)`{APIGpF%ojB{0`x|{Kq>v`gmj0aoV+LDtJHnt0!7nxjK z$DE^I*u1={=ScpE!t0N|Fj$;8BX?jzr=d&4Ce5tpcLW8FU-*&Wb$Oqn?f$}ZuI^XO zUakI}n3?hJt9ha58^yhqH|oCXDJ7>13FoSB{&i&D@<105*mb^;^F?WC>7U0ppYMGB z&ib!-=}r52wexoEvikpMaoVoCJ2({%T=NTH<={Bb#=iY_3twC6c0nP(6{d6SiqEIb zxUZD&X<)XBaq_NRx889-zgF-_-9L50&iQXMSxx-S^DCs=!)~uxyIPu&F{1GC#~*Kt z+21By3!b*OeN(fjtjO~BD#lfe&g?Fmx9@p!;rFG$-LWD9))Or^GN{FEpFHc6&7^Hh zf^V4|IQ05c!h31||0fEZnw>d%-!z}qc=y3aDsf^}5wo+oqe zZ0Qt@U!U^)oC?q4#TBI@F`*$>Suf~Y@ho0*Ni^{;=@z*J+!} zAB%nZ)4s0Sc1K4}?6uT`M|$TUT=5_&$ZUD=L*rlfb5<-pC+tw*!SJKSPuZd+;gv?# z)_B?Nm-ks^W!c<#;~4Q!fbp-#?YDc{_MDaVj}*Jnzj5=j%lCB_ZrH)(UZ~0XR8FnW z^2pcZri(K>a(`SiwEoNo_Q=GrzGw$?p5`S>QYKBBWavBjjltN;J+U#RsK zedXrr_tgzou54*uxF`CsWkaNA;=bmE&ThsA_0pAgpVOtkS-A0aF50Is_nPvK+qc`M z8ExJ+N$b3T(qSGW*|Q68cxBADi&*VlP?}^?@tjr2HjVA^Zwn89pJgZNTefbWw5dq{ z@uOeK_7m=!*v{&G@$WC^nsdwEJed5L?{c4R-^R^uiOcd;_U^2{CFGaVGPUhel-0RA z?U~;tHo5SpE!f*}C4XDsjV+Da7@Ie2v#hmyzHXUNd%3~Ii;Pd6n9twspu~P8X|>LR zEx+0FK{>bM#P^uv=RaGu@f=prv~2a(-#_VyZuB4V;Fy?4@kgfVM(=!f>$Ru%?W=zm z-tjL@GmY6E;pU3SQ=`WOpimP380m4r!}iPv@K|Z|=IQE(A%7N%>_I zI9xuNw?IR=d)JFXA31UV`!DQ{^v*ff(ipJAzJ1oYZI9P2Sfn=NpztyS8@;v@D=ga7 zd=fnZSa0q;dwD7ArSdZ|X}+>fk1w-ZUCf*Py+nTV!Oqhh%34+|v#++<8qF&_{5#R| z#@)N;b{30Hocnso`x%)%ujHL0GDJ2iFEgk-WUz?&*4yRc;ACK_b$l)RUfZctL;sY# zJa75@&E^;K;>XWDN!gZryY2E#hY5GjU0E6I;W5LZu#ofgz8^yU%cFPCvVOK!rT8^l zR(o&Kiv=HfI5s^hwbD56pLY6R%qqSz{@EcZODEcA+5|s47CdLmtSL(6yHopmd~?3{ zq+dB9$-`$-a5X$&%C646t?Ry7Kj?2$Z98~4iDQez7k>-R`x`map6Xr8KeIsWL)hEI z<9w4hEV0+hHb~E1_bW%TMPOWzEX3 zFyCb-Z?YoU&#YU$f*ySMC+T!-yR~NE z^S2i_vj|8eJjly9uzL0X8ATzXKgGdyga`Y+%W@?X-?v z7M_C}zJJsg0|#32l59rXiV5`-JLWiivDO2nrJ_G2x(nD_eu{UV;B?vl7$l^0+-CmTXRf@uCOX{V*Sb&3mfk(-b>Fjlrr@UTe6y!P*SEyI)MHa@7MfwC z*4MCVZ_eFW-WObC^92P3Ez8zyEc`3~QU8sO_lto4N`jULXP8F*bDewbLCG)iuNB*3-A52>wW)UUbg3@JzK(7Nf-CqGfj5#hpj&NuV>Y=D0l51WBK@F z-P3nRY}A>l^}3|)-<$W5Re3h-c2Vc#)LC436H{s==6SK7lM_(5eP3?>-xrLxZ-y}( zp8lut|KG>wcYe5XbdJ%UDgWy-pRU@!-R>SJ81H)8zGzQbc>cvlAAap8w{umm{MHwn zD0~VO6tN~843m#d$d&4~eZ*e>t=9BF&MVLS&3E3{a{EcT`1$#M|F&fJ_RqhR_p9nw zh_7DlbHM3MhwTPQC;NYX{#m=xZ0d|<)7xfg6TAJsjc?AXI);-t9mEatL&23zrTl8uQ|2KddGPQ!JhpOmjC%N ziB*NC??}{i|68;Ae_ro?zj^N-%VodTe1BFy`F2cBXY$GT`;XMF2glU;OL@oHT=~Wj z(J`ZfmH%D|t2!_LVm>t|LBU@?_2@1XEk+2e=E<-v}m%s7h|^Xx5;_YxKr8R zkAFDCpZD}`Q{Ip79xg5}`^2mA9n58ytn+`Q?e4we?~~g#a#c@w^lbA*;{W7Vt>&+A zKkl7bWfcEQy!!;F=7GFio@>61QdWGoa}QOhJ5@O(eBLoX`M~Vs;`KY*nV;V|H23+n zkN+0yZ{E3S#+PLua%77*_gDThQwv-3u=)S*4jF$LW4#?c?Qt{CJ-D6sbn9K-hPj3I zbzS@8tULaMzW;nFdghhmJ`WGA&VR(;>^tq>qr1}#>MYuC$}#+!b8P*)yoB?g>OUX) zWaqR0fstPIhyEL<)<0h#E&abKntk5s!{_guJ+td<&5u|2PvpEf{$%s?g4grah03q{ z+U#Fkm=XNCsy=o9X8z#wJDZ~C&pFaio%d*Gt||NZm8#!#-tD>WwC;SBe*FW^HA}C5 z{L*K$@5kv_6<6Qqw~nt~C|=O-XE)Nb*hJe*D~`+j$Seew*9uFq*S^ zx=&I~iCF#a$IjO*6bN~$EIt+6E;rQxBD|KwK{utRkYOo`sg20d380) zKjRph7c@TJk#sUgtnan+j^%B4YB&C`S9@dj--OeKIPkOi_N!(sDHd2Uvo~3KcU6o-J{BGCB^*NbRYd62yfAY%z`|>{ymUjRA(x|U#?!>8a|6JGq>Uq!O@80?H zVVh`9A>Y%p(SDDgFuwm>mhP@Dn^iq4;uqV5iqpO}(=YvK>F*C0|8OLGf6B$o$v=)? z^WD*7;P>m~`I*U)=jZ3wH>A4uzW(>;w9Bf0AEVRe*)%?o?YvSNkbiUfY|YAV?_)|& zr|SIvx&OxfE5-SeGJdCY?Xx%E3-YcNVW*@4INM=6U z!yy(|FFW~+uTAOiy)~2WN4(zrw7TNW(%%~<-PyGd)Ll-T6Y+V$?7UZV;y5-4J_yd~ zoPFx;b)MylrP}Z7Hg(IGNBr`Aw60qJ(W8Z>Ykq&xo>yNkUEO?q)0cCrcjV2HJ^cLd zzBPZB7v8shUL5z|Yv0cbR{gp;ryA=n@A!N@yzu9SY45G0w(p-K{%>=$?ZM=TU#qou zrsXJ9X#eg=DNW-Bo*Ka;eF_rtV_Uk)1Ed|dymfG;6o*Q-Kd-}^J(-DUJYXTIjf z-A_M!^I!UHOLvUOv3KH8C@}h*?jE%7S8bR{YaT<^{{noCv0|Mu%YuG@tNH_qKDKK~GpH{1V;NA_zpvj3>;O1fKj z>fL`u@p#i_(fyI`+v@$d3ZC)w7Bg5`X5IfU&(eC9+QHb3{}{gZ>m{CKP5$}*e(;I| z=iZdvir=TleY{rOxb&36y_<7A|K0m*uu1On8g*;k%}<**3m!Zp$-MDxC!G0kl19}^sxBcgD;bp8$O$np%V(UHcaL%Lwq;*q9;L}{{i+tR zCW68HiUM2POqmm>o<7KZ?YrmRH2Y7o*NrvLpIdauW^N-h&xtIZw;6le&US6xJNXWy z_Z5a;?X#Y|J-_U0Pqtps=1(8$($iyHTwJPF3#%-M=IH8t{Dk}bvpYN3w&~yY?L5z} z^S<%!np^ip&M`8v8K);1h;~N**rsX2{6Ocy=FpunUz#tT>AdSuR(D#7;f?bQTg3@$ z^tVlX^7-YtHFwXSTFd8WooTUnt!B=)k_&aUdjG4Q$XA>_T>Gmy=;en5Ny8~OKc3V% zz3zDT^f_Pef0|YwD)=(&U*oR56Yjmqc<1@wZ^zw=4;y~Jb^mdnm+$}52Wypf-(orK zaIWr+{2fz!w(yU3L6^%m+kG_twqtqm<5K0n_pkDvah9LF?BuhvhyR|n39-F=Y2FH|^A)pj8t7|LYp!9k#c)UpSwacx2N2PX{Mm zJIzoqT~IV9f%DCZS}VbGjGOyP=dXME#aiss=Jxz&rEp!#Fg!7c3x-|uQFw`>q#)~Y?V>p*m2LsL}qN@upDr5mo^FO5!6 zxYx$Er+rPjfS|nplt72P#P9qT-=|Fvc(utO?MA|yDL-YxwVT^`4mqv#&lMCDoOt;4 zUdFrWvrI34d9-S+n!57zzoPFBfA5jmw4K$5N9S$rly4OuAEdsYF8}$}xoN+}`Hfzm zTx**7@5rsZ-*cbb**`J<{{H@#n~xb*KMGKrzh%N?|JkS4@!x;=(Erolw%{(0?HTF; z@-=T2mi*Sw{v5a8tbgmVh4;hO?Bnmr_jok>tLU7{Yy1|U=Ze_rXVq=_&2X;zL!y}2 zpKkTI7=PCYi$n{LnAsHubDDb>az5tB|Ehk`)3cEE*qN0+FVhp_9}AmsN^I<4J*>N7 z@6xp0w=YMYo4e-blLuFhPT%z6t87i^9g$7V$BO@M_Ak74&;HZqP40OAXRkjU`zkf@^Ntr=7$ZbMUCSpNU+*>CJ7DrVDJF<8?S6_2TkUzKkXSEa;{#Jiv-YyL{{ay3oW6XFqhu-)yVOx>tPw}{Oy#6*` zXX?!YMU19hJ}2qvyn6Yb@-4P@p?pWzB%RgP-&FZb|L4{C`qLY}hfjXmm3+!_deOHB zPIeV$6TO5F?7wH8V)fhL=^ky1^dF3NJKoEFEB(Q~n|qJynjg=rbt+%A-}(IA;aJU< zKAHUbwE5+7&f44s?mzcCy12MJx!|{E`Hu2w+S7YIzq*{Cb?)RvJNcQ+$(HGXHrJS| zZ^m3Wr|uE1_qzPb#rI1rb-F%UmQ3?F_v5GOpI@6Mx=8nay_H|j5N=z+t*;~N?Gjx0 zctW}N>w8NNFwWWjrKoPF#j>X?rc)-*3+~R`EG$#;#{OA%P5ev-H}CxN+1HoF+kZAV zeQVFJEtNW!+xHxLygpaG;-c@J^7CKkT-p9{eaH3>-gU*NnfL56?ywBMdn$JSj(JB7 ze^>l3-~RDIdt?Q}<|5Vqzpsc-@!vHu{oZf=__}Xq{;}eRKV1(CxL0LrQNHKI-u;!c z=g#ZY+4(YToxN_CuK(YO=l@Q#$&5I>dH=4xp?lwjP5)z5e($SHy!hAWS6;t=ur1sF*sfRK zZNAN)lf2Cj)FmyHp!|D& z&aaivH@Wd7oq18Abm!O=gJu=C@Cr3FW+0< zQ7vA{UH;+7$34Z$@r{(edY>Tej-}z^;U69h=>)%(h{|);u_vP93WfSiG`Fvi# zvT@ELkxQGe$@$!6dyuo@p+jJlckKMsv+MVpO8yIgtp#|`YWw0+WLR6wH)SLE1l6ok)`j%J<8S(*e-r) z{{IJUVS684__6QV{OG;c*ZW#tyfSg?Cs(=XpNsx8fhsKJWexWjHyiYZ&%5jXaGuO2 znO*GxPktY=4=5M8bX(_prF?s&8fa+bk{s(7z6#l&Ik#TLYbmL3Vq4zsu>0$b){^O$ zFK=-HfhB8|XHN)odBPGlCA!!kro7DWv)OvP_n+gZ%@4o)r5PvS#-Y;JizvNnK$FzlF;AK(X=8HoyLVMnKjqS{hmL} zkYs6bySzPK{t%P2z1qu&u8tEQFDgj`NG!RaxMKF z{CQXN(Wav&A7{DWd-1T(ncLj*^*`sNI*rBR^AE4+x>~by>jXdfY2UVO+`B37Le_k( z!%_L`OBI68M>*7NJzr_zcKc%Hzt`r6`rk>&2bcZwwQ99YPU0}QBa-*Gr!?|nZvWDb zjuVELwl=)eIlAWTF%HQ``#oH$EH|4;Uyghgud~-DVZX&9sV>jeS#>3{71^6TZ_V>u z%h{$n;ljSd5>q!!uyb4;v2$^U-rXAy^c0mXXLjw1$=YptLgLHJ61~sA-=;t95?R%^ z;q77B_GX{SyFMxB{8<2Y>${6p^Z!(M-IzbeC$#o+rA688il`E26&XUOeO)>Kj|dQ+mgfVpC|v0)5f&jUvZ#)kj(rtgW`Pec+h*>NnIa~$VAD<={dS}GGj(Jvr!nsCI#IaoifxhKDWf2b&-(xT zNE$&5Su7c!sED~8ZK5VRbt*vouzRRh3 zPV*JNuD!i=r_7XROD0a5)_Yj`aEtM|gq$6WK99C|s|U^BxN2iGy_(JZNpW3ov-SO%uRrCqiPoRq_Dj%5 z%6LOzY^(3X?&vrn_-a~%o|2Mnzp7H7UE|XfQS%@ApOO>!c@L&p70Rv25)iR( zA8RGrc>NBU@6|Hb)H!3<5Bj$1=VsD#kdW zs}^i6>-RN{Yhv7R)Hfw5flu=GwTFDNXKrv#o@u?e@9Ar!mCp;VyFJ$Bn!8(%mx;|U zG3jb!*y~xwi~F9wF1oS(oj0FLPs+792dCu!Z2Q8+&ujYjXioEjA2;XN6f2y&6EdkR z)bWUb+xeMorWY2R+rJAGxS&COOGQbRuieUPmK|8GzDd@NVc}mlqs$zgdz03RTrs_F zy1~NOGiJ8S&gCml2p#QcS;!)illJx5UlX%vhrq2wTlTa)i+yLq zf9~71iEZ0b=US?5z3|R*!Nxs{YqR3nZ(p1Fc12u56D#p}~N*KOaMeeV0MhFfK?x0J_9 zvCLq7yCz$qHh1O|ORWrpS05f6jEr>*O}#wt=Y6|`&ZHwhD%P+{M{ZyF(VOMdCymUA zBbk?-K;4!l-Xa%VU8*J@h&Xm`*2xw78ZErPPu`^4`A16M?L~l^Z`Xp1Y#~-&hQ=@5 z-G?H#G;8gzUekMm#V>Z!gWyL?_f?p8c2=*nl$hfalX^7d7mKs9#R-VnxWuSFEcRm$M zFKg~H5?5~bP0sq8SH#7oS$riR>cQ>)`yUH8wD6>!`m=EDsXeN!SJ@=fJ4EWDE8KOU%q? zZ_@m`%dCEFM@P+jP%ZyOiY+iX%}8(4q$z8EvhdD7Gbi}>M*T|jtF`I|d;AT5o_%=u zTK|m`aaDh z@1$a1bL7lJr$jxE|5YrUYpHhj&w0jz6SY=Cb8quazR)NE3$XaNDnP9GS6NN=ij8 z;IzT3ZRW4Kb9c~*6DtqQ4)^%@` z&3~}O?7<wldoHvqjeR?fMHGFIU|4%g{*vzb*95 z{XAuhP5On0)h8KL+PS?=&#`=9^`y{3s_o*g`YRhE`V8)szMGM-rKP0)?pFV~H~Exv zbS|g&EAJ>!mo`fcezxLhYMargDW4^t$8VSJ>)qeCey5o1^_M?(z2Un2_K>f_HwW$? z_jnSykF4v=adBDFZ6f6DvgCR}@T6_ibR|W5_ujoH#TC5o>1+S{&o8HHd+M#o=2Bu4 zEZlfQn@b~eSMCn$8DCqcSgiRXZ6vYVf2VGl2D9^=DI%d;IGxgb4OLCc*p3{3C~et0 z;UABzl>3ag0&l;~J~8L!;}_KhZ?-bF9Xxm?y*uH+ib5V9^8+Qp;eig%&Y5)CG`hI7 zB$PZaG?327FyQRyQ2CMYYK!1q^IPxbgZAg&wEudOFum{W!qR8AUTiq0xbE~igX~iptG8dwztAx4HWNej|AR+l4({vh z=-Bdnf;_W}%Mx)Tr5i<4lKVkA#$8K$h6lJnM^xg?4?JF= zlCGQ`WVF&Ob9wodC3fY^_p5|GB<$NVotq5rn1+Zg+o-77`z-L*+S|N`pOpnn+T3Wm zGScMSw6vhvTjxI6w^`CUTktTK`Nylje1fj8Icja$c+t2$Y5T4fYjx7j|B_uYz4G9_ zxyKJKDf{ncb~Al~K@HdDww)`jCU^y9$!<<_-*P20UHZ1R^&7*?Vwu@8Uw7u#-{#vb z+qd_P&%4uST3qLt@)=04xHJFAzDX;2zUThV=sVkXsaaR%)Wh|>|E=ck)Z2Y%N!5F+ zYcnTH+9%0eZfAY8@>J^gX|gV7XM3-xFBKG=sGOkUGpj1)|FQ0ll1YnKo!alw$9#Li zWQ*)w?MKd=2fg@zXHD|ij)XIhHcJNX>-wLko%Q*_&c`pUZTXI$DBtQY7HzOF(Q(FC zzN}Yw-G4ki(0Q`q+VO*8=ihvOF1X{f@U@hTO{Ri^mR7siV_lxKBnc#a587tGI&69jONz`-6sqe%YAt-?)^o?FWP3_f?0c2)_JMie;M!mK;3H^Ht}ME-o&8ZEZWgONIUNv1koW=TTV^EnlXrbjdg7>Xhl) zb54J6-@cH|J(cz9R#4CMl5N%3;5*F8=>`8p#W!XglVEd=SfO`DRk>7m{@(ALovgh7 zuI_eqc#_ce-}JTc!7j8*|;C{aPO}In>qs{41>@9}|mG;Y}bbJkr0Ok}FY867zn) zr|V*9{O9HE|Ick_)ph(c)m*&zcYgiBsr!EjTIbg`J`q-vuh8&~J<9bz3DkcS6tq=jzGQ+n0;_tL5J-l+J(moq^5KS*+ly>GYygPbv=GO?|R# z-NU`%_tSFy<}N!835b`9Rq+nnj~LWm^U#UR|9F4Pw`WqOD{p?0*?#wfnuSz@!hbH= z4F*3Ju~)n~-hA`_QR_V)(hM07ixu8X{r)-NK<%GL@sVqO9A7Ll=bv$&?cTorc@=YW z`+~lio^{QBSS!kpgj=uKxL0 z?e`Dg?!DW`>i`<`aB=B#)8~27EMaxR>+H2!-MtV0*=(I6cIDS}xml{yZmRblo%YMf z-{!yJ(YS=WY-LaXH~b9acf2xb{x;rYp~+RNPu|-(HMeisiQE>W=k3=GFV8w*{Qdv5 zr@jv>eqO(=@%OTPGMoI=lx=f^udY$ez8sz+tFytdwnsB3z?nZQt-*t zKB?&IbDNsypL5pd-nsWw`|^tVXNr1zs~F?|eS3ZEBC`@0e46{J_VOA@MHY7FSl`^+ z7jB8B@rs7#=`=4hDvyY`-1u?A-cP3YV&Nt6ZvFVI6qVqRz)||sU!}Ru#Dre4bEtx$pYvV71GHpl4oC#I& zHpZ`4tZsfVAwkE%x_N(p-^+xzxBoxuXbnklR2O5bJ6nuHG>b~uZ3d;{yt!tvqCVbBOE&2J^)_G}X#I{e6 zp01~|Cqp$pZ!PPbDbvCdzRW*yWS{PCX@fT@&v-xH{CmJ~&i~WLcYMC%sLOtIrvI;h zUOv$rioP%Jz5dD+wr1bzT#wYl*RmEppMU<3-M-wuCwDfhC!W1`o>U7e(=hoYdNZzZK7 zrB}7KFB&4ZP89$DiH})sPt)&zhBKEOdHd$v+CyU2eU<9|isyE>m&;Z6E~#SR-@QN9 z`=F(G;a%nLLSJ8sc{#ZipUOO3@bq^}TDhd@LFI@ali4@A)f~8$qdsx5-@`@R>_MBK z%9@4FYVfQq6Pr5Cbx!41ON+^yJ>q6NbzVRC%RDai^_AH>e}4Zi{Qsm?k<_mV1;pyz5ldW%2jM4tusp9v3cbsL9`ZZZPDDLS+`AZD#s0zjo@Bb2 z@>hSKw&BxBcEkDt-RX0_3fBo{E?uTF{fqznM_cRHFWI7b!t71O461|Iqh-*Cw8sA=G*_ z$>8aw=$VgppDFqD_Hnj{-ls>pzh>Frk3GEfdd$I0@491=jbEpvs(=0%fA7iK{G#38 zJ%519E~TO?JuRNWyKSwzIv6Zgt@_gqF0Yp`?_!Pwv#7E1m4ro=LrUovy^WXB4{6S^ zN>*@e`)>qEFB8vg{we;YCd@7FGmn3qrAT&gXJ%DKfym^^oBH_g|1n?v{dy9Uz^O;= z_a5|}xW41#y6=_`ax<4k-%u-hy0^T@??%{~>-LAjLwmDDAqH9o?KN0n{xN0aqpAF! zE17wu7yflK{@%m=^QruCf#UDXf7CC({onWQx!<$5_J3OM9;}Xd4H?=O6r8yDdNuQ| z?JZM6<3HX%H7()K#qgIlpT79Ul>N-v_v5lvR_!WzX*sXp@QsJ|M?j+c3CG-k?+dEC zuYG!}$Dg?Pxbc$8Kh@d`b?RO?+xoAD@!j*z6R`TEQ}^$+ zdga5j-z(p5P2chTljo7SMfU%He&E#W+PdX(+~f1|f1b&-`RtexZ~N2#UgiJTe_!7u z>%>~jSkSD^qBGHF#|N{z-{0#$z5jmi@!9Zyr)urz_{QwM4O;K1q@<+2OIT|`vROd* z`^E+ara#kV6<<&2uK4hMd%?K^cIkUnjnnP#bpGwB-tl{nBm4W>_Z>^$ue?+A+sUT$ z{pa)bwWsvd3NEgfd%DZ>+cPPieJ>d0qOHWMU$yV~@Fe(8ai!s5{k`+s*Gc*(tiA>f zg5L|i^A+az=V~l&XM3P~YWWK7?Jd#|&+LAsC3I%3P4)fcn!p!~4^Cf|yz~EyY=r0M zYUk`}jfrn|J?D$N`IO~B_g7b&UvGTpY)O#OSATmTw=?ydXY$6S`_2fTulLy~9> zugT(i&Twy1{?C$J%l7PBv$xO7|7Oxw%#fdHpwpGRPx230&L5~_w(=FZk97>zJ2ez2=ohDnN9;w-@%j>t#{IX}=v|V9}yXWny5c(b^Va;I)L+56F8e_ge??%(&2 zlIm0Kg=*$1>&t6o=XJhhd~@(dbZJw&fKZY{>SO3IE>qrs}|k$urH5JP)u4zB%oh!yC=##`>$4-szZebm#ITrGFQ&_C5R)Z+C3& zbH1$1)9~tc?S5MUXh1jKyWLzDV)N!-nJ(+|m?NeAcf7AGkJjLnJgd2!_wdyB#n*Rj zpK|s8zn0JS<&x!p3?~GhHkYD7Z0`8?R{k;7E`M{@tw`Kx=$+pQ{vCW=ksK(tT5T5x~Arn;~Dvw)2iuz zTjE`!R%)J9{d;+N#oPPZnr}}Dzk>wTl5is-HQ&(k+~tx-=KPM1+jsEPY5U#t{db#8 zpM9e9d|>F)colGT$-emX_KNzd1C8p%Uqy>wJg#o((OBjq+qZSughO7f#o$m9d}()o zx8l3G$*N_~Dr3GZ{y1ma2TA$bxn7!qJ#(t%#Lw_1{og%*^Wv{8FTrLiDa9^Qd?(AL zRQK;`OzlG^HNI}uo-D7=#y9r;$&LH3!&2$vmcA9WusTFTh&oE{E?3 zA!*YFb?T#u|MTDbE&ihO+Pd$5+G!QF2@0GF3M&M%mu}1mU9ltBT&#R$z)I<)t)g!> z9{rl}c42!~boRpIQY)IIyF+6ZKe(o>=Ww)3NWjzPSjW=_M<*eplRie5#T`@@Z@Crx zNdNKk&!6h!&zq({yIa2Q_s)CyqeE)a;nNM3Mm+Q=$t-j}{vt{Ks%gV!>S}ou8|5xC@_t*O8aq&OFZT>$4 z{G=jhO+GJu_Oo9_8sE+OykmKP^7a+|oB8vB>h<)?bM4s~7#Q9i>#=i`zxDmZo{#ze zjojZBC-19ycS*57{00MQQyx)>d(&m)#Yr9`*?BA z=Y9UqZ`oL!uQ(h1`H<@3+xZL(3=I1ZoUwJ3zhT-g`@hL1<#76^Y5Ob6*WIc3UHMb| z-{0LgOODO{JSSOxa<~8Aplf_*&YrmS^yjCY&!4>E-Z%AYuxF9yI+^|X=d2!Xv`ks= z|1|l3>2u90qYbxR_Wj#+{mGl`_cr45XS1tF-l>jTSNnGL=X=@a>YjSLzAW4GHFo`( z#d4n)?0LQ_KmGJJPy%@H{Old!FE_o5P8=-W^s0OQ$?|s{pH*h=dK>-oQfjtQ)dlCz z2Og?S-u`4(YWmYJpWpXlGROi7WMr)QnKe5kMGx>Z&UZ{s*3RS^n-iZ zCPgowbTD?)|HJb0kIR0tj@?rP+M>{u491dDic;?%%s{tmp5W z{|ugHsX3QJ*xK5ROeXw!!~LFtf#JjFw44R$uc!H>Wrx+h$+djm#d~?ZTCnt|#kZGD zI=Hv!$Lss^CiC6Z6*m8`a6N9j(fu8tKL7kTt^JAW@q6{Zmj7c9mXcv$X!yTbQu@W@ z?e``~=Xp=#S#$PNethlr`;78?{y(g|rY!!X?fgE|_3>4%c{i(m*ZfHQ{q*Q+Cwc-f~C!yqZ(ipQef1DSemoVS9G&^xjR1*JJ9Q zZnN-jE56UJdv4Fm?c13d7!KH`Jhyd}kD1Xd_kT%B&hL*`ZoU4rHGj>iV=H@qKHK^J z>{I^g(tlsxE`QdL8h^5MJ5T!l!}I1Xx37s?7g^128yA1-SloB6IXr&K z`~J7HnE9;D)>r(hoqT80-)9UA3%K^G`aZ4mXFuo?==sP->4%KUY4^ZfrE-f8)N(re?HDzEp=D*pHM!Jdy(^-tbD zXQ#+K^VE@9`Olo?_o=w=FF3j7E+YfOgL#Gp7bZ2^-qtz!K=1p>M*bV>yK`bE%g1cj zvX`B|kLgF~+W75xzc?5ec1T;l=lu15^U1H~Pj=l+S6(dK^)OyG;FfhDvVF9HZ z5dm;%;;?|3fx&^Xk&l6afpt^@RKSh~$!KC=U>MCGqb0*=nK+saMr(u7+F-Oc2pG)< z6lDX6d3HZatG;cXKl^C6xVmT9x|o^V`hPr@EnBv1EfWJn!_4K+SpH6ImzlM=&&EnS zY|V)-QSG896WyO(aIUZaWyHY1Fk_;Y-vxJf_s@UqYwGlN{n)(o!=Zi^&$c$U;xmTl z&u`!Nb^gsQnU}ZtGcYh5IAa9rDwO}QebU_AZ22%%J?-H;?#U|EZ#Jf@ZO=O?eg8{a zPj9cPXWIFBbA$bDb(Iev-uZEv^kfzD`!&Vqtg@?lzPhZ#9>q?vV zrT+a@8o4>mm(TjmMM)W%GvD`>zl|+pj_S?7XH(0F%Gp-}m*^=av+Sz1^6;Y}v9+&(zJIelhktzbe%J#29w?F##+ScvQ7IoWAPVTRDbaP8n^=xZz|GX-Eua)+`{YL8Z zeq7q~=c)RWT~oD-FRk`Fb>f7_q?D9v9(~sD`ink3*E@AL=Ch zK7Kqi(^#E9a+8YZru%ijQy(sB1)V@+Y-ToXwt2IAQ&f4?h zsQ$S*mc>Tt=jQDB;HrOe*8D#ztHb{rcou!V8vb-!@AjvX=WDLTZU-eU$;5W{Uw>FX zf4;I@ZsO;2zZ2Bdj!nMv&ugpkxr%f#`GSOVHlJ-HcYTTfe1Mt%%**sS^Ex{_RZbrH z;d0LQyL08K$@6Eia*N$5^=4pTxbgDshvhr^^X1O}_)#JDX4~zu&!P4)Q?KuPH|1^I zW;4UO>N)o_5B_1DIYZ)n+WRmz28M*Tn-3f9%*>{xp0=BsZvT4cO!M-%NhyDS@$UR` zX?^P9Hr~ju&GYw$<=)#ZjXiMrktCbV#;nVy&T2}%9tUA-PQ)i zJCDjTFw|9A|FH#i!VjDm22lf5#!AR|)LGSnh8o{kFf%io^YZcW#@hd7Vqjp{@R)~} z@2-JG`ShLJefEQf*xp!te!us&ZgaQTyN}V%hn?@wsS{*iVA%1zx2Gp&<9oa6`}qYa zDL=04eZTp<&O}g|X?^X)i4&sVtsgM%J}V_#d;3E9`nZ3+_iJA`vzOm3{TCRmzP+aS z^pR<$GiOP88m0eYXRH%_Jlot~o{`}|{+`Ch#@TJ{ZQ<{>6@1U;w|Kx_xE^#w5_SLp literal 0 HcmV?d00001 diff --git a/Chapter2/Flutter/mobileExampleApp.png b/Chapter2/Flutter/mobileExampleApp.png new file mode 100644 index 0000000000000000000000000000000000000000..83ed148e9503611d87eee5c9380c2762a899de4c GIT binary patch literal 63062 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

t)=4PB?*_M-~U~( za%*459KGXDPhIYRXDd`R>Eg$S$?5l2W$u|aaZ+``d5~We*)3up%g_Ip`rzTTOSb** zY!_YrdCY66TB_*t{6AkWhUeW|rJ@u$v439OWApx+^diPP1#_RzGdy-B|Jo}q$1Wv* zx$ct^#nmz5+J0*4X)}DoN)Pd;-+5XTv&N#b;CylLyvV?m(m=&lkz+sho~>YH*pYv7 z)Arr#YjbL5bUaE97BO7!6x|i@#(8fobF53sRu{FS%g;V{KY1V_KfXRZFRd`AWYJln zm3rrHq`!alD!04WFJ^mMc2&{2wbN#OTlZ|vnMGe+qwmUHkG;ykvHs%6huqiuTHnms z^8I`!mvT1Md~JQNc4XNKe(qxL@9(RAEzkeAx9Y!x%XDpj-RBE7WoRy4x;Aca zKv`8{S=GTBKT%1+&H2xRi!C>;`qpIiY(huc4CkQB1zUH$o3v~0^w2#^OZ1gz?kp^54Byn7qcPpvk&v$JmX(rJeCW=@;E^RwsA zOS_HFgkMaXI^)ipIqlyC13khd-@cl5S8jRjgpQ>-y3x{eg7)w|zgqtz(Z@0G*1Ftl zOIY+gZ~y=D{oLQ_|FeHyXLJrwY%kXNAew0wIj`=C_hj)dBS~HM?>684|Npyxr9ISC zT<+%QoD*L<7cajTu>17vsMq%@{7Y2L=0USLA6UiM>XPtyvi!H>)jMH}|W{ zmeRxbj{Mm2bB^z{y>svCPS^Gq4h*YG%qclk)6{kQ@vC>)^5CM`%kxZ#y7|35p*PJh z%$&PVO;z)<-Iegr>Xlpf9(-E1Of7Zk@)UR1V=E0aKhE9zb;d3z^Jy|C?eJ*B^m zB2G=?eH~{bG%3jM@5%btdh5H+olKgOZnNXEh;*)Jhi=`+o2TmQj+#E0-MZBVGzfC@ z@5fmkT*Y3?XIspeGC@vQG++Le@}k1$H*Vb6ux;5ir75@CvK!m~e#`qE5T6v2mC!Hn z$m{9L1BYv^=ks`qYjxlJ_F&ubd;fl@zdC$s7Plg!a?JCY{F5&V35%wiMIM)3{B7aA zXx*(FFLo-%XUVPKy?+1Yms0ufv-m12ql(Jn>z7|l;NmQD>NxgHnz`B5CB@X;#r>#c z@3Vrfk_->(7HFJm*z3NQD|pI&!@5hppYP7gP05L{jczfm`p3Pn0W8H$K^!eED$jG*?llnwn?R z8yDrWf0w)1^LhRvz8RO_29&>0-Fq`d)M-WeN3qGibJssA=qc1|y`m%L^z+T9<9ge> zjki_5UOZ87W0%rpnO6;GXN7iXq-@lXbapcdQ^c-biIOf7WLW|>b^zLhE7zT2dSGO&E_;236b9c@>`twHUTxEX!@~Cr1w5x66w)