├── .gitmodules ├── Games.js_Hackathon.pdf ├── How_to_install_Swift5_on_Windows10.md ├── README.md ├── VirtualMachineGuide.md ├── homework ├── Swift-Домашно-1.md ├── Swift-Домашно-2.md └── assets │ ├── register.png │ ├── task1.png │ └── task1_template.png ├── lecture-notes ├── README.md └── spm-windows10-property-wrappers.md ├── projects ├── final.grades.md ├── final.projects.md ├── nine-mens-morris.md ├── rpg.md └── zombie-dice.md └── samples ├── closures.swift └── generics.swift /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "SwiftLectures"] 2 | path = SwiftLectures 3 | url = https://github.com/SwiftFMI/SwiftLectures.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /Games.js_Hackathon.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftFMI/swift_2019_2020/5ed6b6a8b8ce0ae8b6b82c3d67fe61e5ed82b03c/Games.js_Hackathon.pdf -------------------------------------------------------------------------------- /How_to_install_Swift5_on_Windows10.md: -------------------------------------------------------------------------------- 1 | # How to install Swift 5 on Windows? 2 | 3 | 1. Install Ubuntu shell. More info can be found [here](https://ubuntu.com/tutorials/tutorial-ubuntu-on-windows#1-overview). 4 | 2. Check which version of Ubuntu is running: 5 | * Open Ubuntu terminal and execute 6 | 7 | ```lsb_release -a``` 8 | 3. Download the correct version of Swift. Use the following command. 9 | >If you don't have `wget` you can install it with the following commnad `sudo apt-get install wget`. 10 | 11 | ```wget https://swift.org/builds/swift-5.1.4-release/ubuntu1804/swift-5.1.4-RELEASE/swift-5.1.4-RELEASE-ubuntu18.04.tar.gz``` 12 | > This link should be updated once a more recent version is released. 13 | 14 | 4. You have to extract the archive. 15 | 16 | ```tar -xvzf swift-5.1.4-RELEASE-ubuntu18.04.tar.gz ``` 17 | 18 | 5. You can rename the folder, so it can be easily accessed to `swift-5.1` for example 19 | 20 | ```mv swift-5.1.4-RELEASE-ubuntu18.04 swift-5.1``` 21 | 22 | At this point you will have `swift` installed on your Windows in your `Ubuntu` shell. To run it 23 | you have to use the full path to `swift` binary, which probably will be: 24 | ```~/swift-5.1/usr/bin/swift``` 25 | 26 | > For best results, you can try to merge the content of `swift-5.1` directory with the files in `/usr`. 27 | 28 | sudo cp -r ~/swift-5.1/usr / 29 | 30 | > If you do that, please use the correct `full` path in the next section, which should be `/usr/bin/sourcekit-lsp` and `/usr/bin`. 31 | 32 | # How to use VSCode to write and run easily swift? 33 | 34 | 1. You have to install VSCode from [here](https://code.visualstudio.com) 35 | 2. Open the `Ubuntu` shell and write 36 | 37 | code hello.swift 38 | 39 | __This will start `VSCode` in special mode called `WSL: Ubuntu`. You should install all extensions in that very mode!__ If the extensions are not installed in that mode, they can't be used from your `Ubuntu` shell. 40 | 3. This will open VSCode in special mode (WSL: Ubuntu) so it knows it has been started from the `Ubuntu` shell. 41 | 4. Install the following plugins: 42 | * ```SourceKit-LSP Visual Studio Code``` and configure it with correct values (my user is called `emil`, yours is probably something else): 43 | 44 | __In both options you need to add the full path.__ 45 | 46 | Server Path: /home/emil/swift-5.1/usr/bin/sourcekit-lsp 47 | Toolchain Path: /home/emil/swift-5.1/usr/bin 48 | 49 | [more info](https://github.com/apple/sourcekit-lsp/tree/master/Editors) 50 | 51 | 52 | * ```Code Runner``` and configure it with the following value in Execcutor Map By File Extension if you have installed swift toolchain in your home directory. (`code-runner.executorMapByFileExtension`). 53 | 54 | "code-runner.executorMap": { 55 | "swift": "/home/emil/swift-5.1/usr/bin/swift", 56 | } 57 | > Don't forget to update the full path to `swift` binary. 58 | 59 | You can use ```Ctrl + Alt + N``` to `Run` a file with `.swift` extension. 60 | 61 | ## FAQ 62 | 63 | When I try to run `swift` compiler I see some strange errors: 64 | 65 | 1. For example: 66 | 67 | 68 | /home/geoeg/swift-5.1/usr/bin/swift: error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory 69 | 70 | This ususally means that some libraries are not installed in your Ubuntu distribution (shell). You have to figure out which are the missing packages. Google can be your friend. In the example above you have to search for: `error while loading shared libraries: libatomic.so.1: cannot open shared object file: No such file or directory` and look for a solution that works. Here is one that works. (This will isntall libatomic1 package on your computer.) 71 | 72 | sudo apt-get update 73 | sudo apt-get install libatomic1 74 | 75 | Another similar problem: 76 | 77 | /home/ivanln/swift5.1/usr/bin/swift: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory 78 | 79 | Again - the best advice is to search for solution. One that might work from the results returned by Google: 80 | 81 | sudo ln -s /usr/lib/libtinfo.so /usr/lib/libtinfo.so.5 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift 5 2 | 3 | Това е `git` репозиторито, където ще качваме материалите за курса `"Програмиране със Swift"` към ФМИ през летния семестър на учебната 2019/2020. 4 | 5 | # Финални оценки 6 | 7 | Резултатите може да намерите [тук](projects/final.grades.md). Списъкът ще се обновява през следващите седмици. 8 | 9 | # Финален проект - предаване на решения до 15 юли 2020 10 | 11 | Моля, добавете информация за вашето решение [тук](https://forms.gle/1zk7MZkSBXDA26x46). 12 | 13 | Разпределението на финалните проекти може да намерите [тук](projects/final.projects.md). 14 | Повече информация за Swift Package Manager (SPM) може да намерите [тук](lecture-notes/spm-windows10-property-wrappers.md). 15 | 16 | __Моля всички въпроси относно финалните проекти да бъдат публикувани в github, за да може всички колеги да виждат отговорите.__ 17 | 18 | Финалните проекти можете да намерите [тук](projects). 19 | 20 | След попълването на следната [анкета](https://forms.gle/nMHV2AayJxpGpMmb6), ще направим индивидуално разпределение за всеки. Ако все още не сте го направили, моля регистриайте се сега, за да имате тостатъчно време за финалния проект. Списъкът с разпределението е обявен [тук](projects/final.projects.md). 21 | 22 | Решенията се предават като проект в github, който съдържа swift проект с библиотека или приложенеи, в зависимост от проекта. 23 | Ако имате въпроси може да ги задавате по email. Оставащите лекции (т.е. в четвъртък от 18:00) ще направим QA сесии, ако има студенти с въпроси, на обичайното място. 24 | 25 | # Домашно №2 - предаване на решения до 05 юни 2020 26 | 27 | Обявено е домашно №2. Може да го намерите [тук](homework/Swift-Домашно-2.md). 28 | 29 | # Домашно №1 - предаване на решения до 07 май 2020 30 | 31 | Обявено е домашно №1. Може да го намерите [тук](homework/Swift-Домашно-1.md). 32 | Решения предавате чрез системата [тук](https://swiftfmi.apposestudio.com). 33 | Моля, използвайте факултетните си номера и email-и които са активни. 34 | 35 | # Лекции, докато ФМИ не може да се посещатава 36 | 37 | 38 | [Програмиране със Swift: WWDC дискусия](https://youtu.be/mM4lNqBSzPU) на 22.06.2020 от 19:50. 39 | 40 | 41 | 42 | Предходни: 43 | [Програмиране със Swift: Финални проекти](https://youtu.be/sLOVEU53YX8) на 11.06.2020 от 18:10. 44 | [Програмиране със Swift: Финални проекти](https://youtu.be/l9W0gxpcobQ) на 04.06.2020 от 18:10. 45 | [Програмиране със Swift: Swift on the backend - Vapor](https://youtu.be/bi9dTAESvQA) на 28.05.2020 от 18:10. 46 | [Програмиране със Swift: SwiftPackageManager 2](https://youtu.be/eXbE7Mn-umg) на 21.05.2020 от 18:10. 47 | [Програмиране със Swift: SwiftPackageManager 1](https://youtu.be/qhT0b7D0TY4) на 15.05.2020 от 18:10. 48 | [Програмиране със Swift: Шаблони](https://youtu.be/vSIbhH9OYxE) на 23.04.2020 от 18:10. 49 | [Програмиране със Swift: Управление на памет](https://youtu.be/7yquCtt6fsw) на 16.04.2020 от 18:00. 50 | [Програмиране със Swift: Клоужъри (Closures)](https://youtu.be/h0G21LmUoPc) 51 | [Програмиране със Swift: Протоколи, Разширения, Изброени типове](https://youtu.be/_qTlOYqaYZ4) 52 | [Програмиране със Swift: Класове](https://youtu.be/uA78R2F39DQ) 53 | [Програмиране със Swift: Структори](https://youtu.be/EbAJvNI_-CM) 54 | 55 | Ще се опитаме да споделим видеа, в които разглеждаме материал от курса тук. За съжаление това отнема малко повече време и подготовка. 56 | 57 | # Hackaton 58 | 59 | За повече информация, може да разгледате следния [файл](Games.js_Hackathon.pdf) или да посетите следния [адрес](https://gamesjs.org/) 60 | 61 | # Лекции 62 | 63 | Всички лекции до момента може да намерите на следния [адрес](https://github.com/SwiftFMI/SwiftLectures/). 64 | 65 | > Лекциите ще бъдат преместени в ново репозитори и ще имаме директни линкове към тях. 66 | 67 | ## Как да инсталираме Swift компилатор на Windows 10? 68 | 69 | Повече информация може да намерите на следния [тук](How_to_install_Swift5_on_Windows10.md). 70 | 71 | ## Анкета 72 | 73 | На този [линк](https://forms.gle/L2RHjMDdicSm7t8t7) може да намерите кратка анкета, която е хубаво да бъде попълнена от всички студенти. Тя не е анонимна, но ще ни помогне да получим ясна представа за нивото на записалите курса и да подберем правилните задачи, които да разглеждаме през семестъра. 74 | 75 | ## За контакти 76 | 77 | За да се свържете с екипа по всякакви въпроси, може да пишете на: 78 | swift.fmi@gmail.com 79 | 80 | ## Други 81 | 82 | [Линк](https://github.com/SwiftFMI/swift_2018_2019) към предишното издание на курса и материалите свързани с него. 83 | 84 | ## Често задавани въпроси 85 | 86 | 1. Как ще протичат лекциите и семинара? 87 | 88 | > Лекциите и семинатите ще се провеждат всеки __четвъртък от 18:00 до 21:00 в зала 101 на ФМИ__. 89 | 90 | 2. Какво ще бъде оценяването? 91 | 92 | > Оценяването ще се състои от 3 домашни работи, които формират 30% от крайната оценка и два теста, които формират останалите 70%. 93 | 94 | > Без домашни, студентите няма да могат да завършат курса с отлична оценка. 95 | 96 | > Без тестове няма да могат да завършат успешно. 97 | 98 | 3. Какъв ще бъде изпита? 99 | 100 | > Курсът има два теста, като втория ще включва въпроси върху целия материл и ще играе ролята на финален изпит. Оценката се формира по следната формула : 101 | 102 | > `финална оценка` __=__ `средна оценка от домашни` * 0.3 __+__ `средна оценка от тестовете` * 0.7 , само ако `средна оценка от тестовете` __> 2__ 103 | 104 | 4. Курсът подходящ ли е за хора, които имат познания в обектно ориентираното програмиране, но с известни пропуски? 105 | > Това е правилното място за попълване на пропуските и затвърждаване на наученото в други курсове. 106 | 107 | 5. Какво ще научим то този курс? 108 | > Как да боравим с един мореден език. Ще се подготвим за платформено независима разработка на софтуер. Ще навлезем частично в отворения код. Ще повторим основни структури от данни и алгоритми. 109 | 110 | 6. Какво представляват семинарите? 111 | > Семинарите са практически упражнения, в които ще дискутираме определени задачи и тяхното решение. Ще разгледаме различни технологии и софтуерни решения. 112 | 113 | 7. Кога ще се проведат двата теста? 114 | > Единият е към средата на семестъра. Често е по време на лекциите. Вторият тест е в началото на сесията. 115 | 116 | 8. Кога ще бъдат обявени домашните? 117 | > Близко до датите от миналогодишния курс. Работата над всяко домашно е от 2 до 3 седмици. Последното домашно се предава последната седмица на семестъра. Датите ще бъдат обявени тук и къде трябва да публикувате решенията си. 118 | 119 | -------------------------------------------------------------------------------- /VirtualMachineGuide.md: -------------------------------------------------------------------------------- 1 | # Setup macOS Catalina virtual machine 2 | 3 | - check below for english version 4 | 5 | Инсталацията на виртуалната машина е тествана на компютър със следните характеристики: Windows 10 Home 64x, i5-7200U CPU 2,50GHz, 8GB RAM, 128GB SSD. Резултатът от инсталацията ще намерите [тук](https://drive.google.com/file/d/12JDjs8VFLUkUQuuCMhSs5BBLbrPr2HsD/view?usp=sharing). Преди да започнете с инсталирането на виртуалната машина бъдете сигурни, че имате достатъчно свободно място на вашния компютър. Подсигурете се поне със свободни 45-50 GB. 6 | 7 | ### Инсталация 8 | 9 | За да инсталирате Catalina macOS следвайте стъпките описани в тази [статия](https://www.intoguide.com/how-to-install-macos-catalina-on-vmware-on-windows-10-on-pc/). В нея е обяснено дейтайлно, как и какво да извъшите, за да инсталирате функционираща виртуална машина. Линк за сваляне на инсталационния файл на операционната система ще намерите също в статията. Следният списък съдържа решения на проблеми, които могат да възникнат по време или след инсталирането на виртуалната машина: 10 | * Ако при опциите за избор на операционна система не варира macOS, то ще ви е нужен unlocker, който може да откриете на следния [линк](https://github.com/paolo-projects/unlocker). 11 | * Ако след инсталацията и стартиране на виртуалната машина нямате активна интернет връзка, гледайте следното [видео](https://www.youtube.com/watch?v=H2j3nyl4muQ ) с решение на този проблем. 12 | * За да инсталирате Xcode, след като вече разполагате с фунцкионираща Catalina и интернет връзка, ще ви е нужен инсталационният файл на програмата. Той може да бъде свален от Apple App Store, но скоростта на сваляне през виртуалната машина е изключително ниска, затова може да свалите файла от [тук](https://developer.apple.com/download/more/). За това ще ви е нужна регистрация с Apple ID. Възможен начин за трансфериране на файла на виртуалната машина е преносима памет (usb stick), на който да го копирате. След като извадите и отново поставите стика в компютъра ви, трябва да изберете опция за прочитането му от предварително стартираната виртуална машина. Стартирайте файла и изчакайте инсталацията да достигне до своя край. 13 | * Възможно е картината на вашата виртуална машина да бъде с квадратна резолюция. За да се насладите на широкоекранна картина прочетете следния [пост](https://www.geekrar.com/how-to-fix-macos-catalina-screen-resolution-on-vmware/) с възможно решение на този проблем. 14 | 15 | Ако по време на инсталацията срешнете проблеми, които не са описани в тази статия, винаги може да потърсите в google. Със сигурност някой преди вас вече е срещнал този проблем, описал го е подобаващо и е получил възможни 2-3 решения. 16 | 17 | Приятно кодене на виртуалния ви mac! :) 18 | 19 | ### Installation 20 | 21 | The setup has beed tested at a computer with the following setup: Windows 10 Home 64x, i5-7200U CPU 2,50GHz, 8GB RAM, 128GB SSD. This is the [result](https://drive.google.com/file/d/12JDjs8VFLUkUQuuCMhSs5BBLbrPr2HsD/view?usp=sharing). Please be sure before begin the installation to have enought free space on your pc. You may need around 45-50 GB free space for a proper working macOS virtual machine. 22 | 23 | To install Catalina macOS follow this [guide](https://www.intoguide.com/how-to-install-macos-catalina-on-vmware-on-windows-10-on-pc/). It explains in detail what and how to do to setup a proper virtual machine. Download link for the 'Catalina OS' can be found also there. During or after the installation you may face some problems. The following list represents some useful links you may need to fix those: 24 | * The unlocker may be needed if "macOS" is not shown in the list of OS you have to chose from during the setup of the virtual machine. For the installation of the unlocker check this [link](https://github.com/paolo-projects/unlocker). 25 | * If there is any problem with the internet connection on the virtual machine check the following [video](https://www.youtube.com/watch?v=H2j3nyl4muQ ) with possible solution. 26 | * To install Xcode after you already have the virtual machine and its internet connection fixed you have to download it from the Apple App Store. The download speed on the virtual machine is very, very slow so you can download it on your windows machine and transfer it. You can find the DMGs or XIPs for Xcode and other development tools [here](https://developer.apple.com/download/more/) (requires Apple ID to login). You must login to have a valid session before downloading anything below. A way to transfer the Xcode installation file is to copy the file on usb stick. Then start the virtual machine and put back the stick and choose the option to read it on the virtual machine. Then just install Xcode. 27 | * Normally the screen has a square resolution and shows black bars on left and write (if you use wide-screen). To fix that check this [post](https://www.geekrar.com/how-to-fix-macos-catalina-screen-resolution-on-vmware/) with possible solution of the problem. 28 | 29 | If during the installation you face some problems that were not mentioned in this post, feel free to google the errors. You will definetely find someone that already faced the same problem and someone who gave them a possible solution. 30 | 31 | Enjoy coding on your new virtual mac! :) 32 | -------------------------------------------------------------------------------- /homework/Swift-Домашно-1.md: -------------------------------------------------------------------------------- 1 | ## Първото задание за самостоятелна домашна работа 2 | 3 | Решениятo на всяка задача ще трябва да качите в нашия портал на следния адрес - [http://swiftfmi.apposestudio.com/](http://swiftfmi.apposestudio.com/register) 4 | 5 | Всеки __ТРЯБВА__ да се регистрира с факултетния си номер. 6 | 7 | ![Как се регистрираме?](assets/register.png) 8 | 9 | За всяка задача, ще имате определена страница, където ще може да видите колко точки получавате. 10 | 11 | ![Как добавяме решение?](assets/task1.png) 12 | 13 | Трябва да свалите шаблона и да попълните решението в него. Не оставяйте ненужни `print` извиквания във вашето решение. Системата няма да може да оцени некоректни решения и ще покаже съответната икона. 14 | 15 | ![Как добавяме решение?](assets/task1_template.png) 16 | 17 | Ако имате някакви въпроси за системата, моля пишете на имейла за контакт. 18 | 19 | Крайният срок за качване на решенията е _07.05.2020_! 20 | 21 | 22 | ## Задачи: 23 | 24 | 1. Да се напише функция, която отпечатва всички достижими полета за определен брой ходове от начална позиция извърешние с шахматна фигура - кон, без повторение от зададено начално поле. Шахматната дъска има размер 8 х 8. 25 | Да се използва нотацията в шаха в матрица. Т.е. редовете са номерирани от `1` до `8`, а колоните от `a` до `h` 26 | 27 | Пример: 28 | 29 | Ако коня започва от поле `а1` и трябва да определим достижимите полета с един ход, тогава получваме списъка от `a1`, `b3` и `c2`. (наредбата няма значение) 30 | 31 | 32 | func traverce(start: String, moves: Int) -> [String] { 33 | //в резултата всяко поле трябва да е достижимо от началното за по-малко или поне moves хода 34 | } 35 | 36 | 2. Да се нaпише функция, която пресмята стойността на прост математически израз от вида по-долу, подаден като `String` използвайки рекурсия: 37 | 38 | __Скобите ще са винаги налични и изразът ще е коректен!__ 39 | 40 | Пример: 41 | 42 | ((23 + 6) * 2) 43 | 44 | Възможните операции са ```^(степенуване), *, /, +, - ```. 45 | 46 | func evaluate(expression: String) -> Double { 47 | //TODO: your implementation goes here 48 | } 49 | 50 | 3. Да се напише функция, която намира броят на различните пътища в лабиринт, зададен в двумерен масив (матрица). Ако няма път, да връща ```0```. 51 | 52 | _Препоръчително е да се използват помощни функции и структури._ 53 | 54 | Пример: 55 | 56 | ^ 0 0 0 0 0 0 1 57 | 0 1 1 1 1 1 0 0 58 | 0 0 0 0 0 1 # 1 59 | 0 1 1 1 0 1 0 0 60 | 0 1 0 1 0 0 0 1 61 | 0 0 0 1 0 1 0 * 62 | 63 | Извикването на функцията, трябва да връща: 64 | 65 | 1 66 | 67 | Където: 68 | 69 | 0 е проходимо поле 70 | 1 е непроходимо поле 71 | ^ е началната позиция 72 | * е крайната позиция 73 | # е непроходимо поле 74 | 75 | 76 | Примeрна функция: 77 | 78 | protocol Maze { 79 | init(raw: [[String]]) 80 | ... 81 | } 82 | 83 | func findPaths(maze: [[String]]) -> Int { 84 | //TODO: your implementation goes here 85 | } 86 | 87 | -------------------------------------------------------------------------------- /homework/Swift-Домашно-2.md: -------------------------------------------------------------------------------- 1 | ## Второ задание за самостоятелна домашна работа 2 | 3 | Решениятo на всяка задача ще трябва да качите в нашия портал на следния адрес - [http://swiftfmi.apposestudio.com/](http://swiftfmi.apposestudio.com/register) 4 | 5 | Всеки __ТРЯБВА__ да се регистрира с факултетния си номер. 6 | 7 | ![Как се регистрираме?](assets/register.png) 8 | 9 | За всяка задача, ще имате определена страница, където ще може да видите колко точки получавате. 10 | 11 | ![Как добавяме решение?](assets/task1.png) 12 | 13 | Трябва да свалите шаблона и да попълните решението в него. Не оставяйте ненужни `print` извиквания във вашето решение. Системата няма да може да оцени некоректни решения и ще покаже съответната икона. 14 | 15 | ![Как добавяме решение?](assets/task1_template.png) 16 | 17 | Ако имате някакви въпроси за системата, моля пишете на имейла за контакт. 18 | 19 | Крайният срок за качване на решенията е _05.06.2020_! 20 | 21 | 22 | ## Задачи: 23 | 24 | Дадени са следните протоколи (интерфейси): 25 | 26 | `Visual` 27 | 28 | ```swift 29 | protocol Visual { 30 | var text: String { get } 31 | func render() 32 | } 33 | ``` 34 | 35 | `VisualComponent` 36 | 37 | ```swift 38 | 39 | protocol VisualComponent { 40 | //минимално покриващ правоъгълник 41 | var boundingBox: Rect { get } 42 | var parent: VisualComponent? { get } 43 | func draw() 44 | } 45 | ``` 46 | `VisualGroup` 47 | 48 | ```swift 49 | protocol VisualGroup: VisualComponent { 50 | //броят деца 51 | var numChildren: Int { get } 52 | //списък от всички деца 53 | var children: [VisualComponent] { get } 54 | //добавяне на дете 55 | func add(child: VisualComponent) 56 | //премахване на дете 57 | func remove(child: VisualComponent) 58 | //премахване на дете от съответния индекс - 0 базиран 59 | func removeChild(at: Int) 60 | } 61 | ``` 62 | и следните помощни структури 63 | 64 | ```swift 65 | struct Point { 66 | var x: Double 67 | var y: Double 68 | } 69 | 70 | struct Rect { 71 | //top-left 72 | var top:Point 73 | var width: Double 74 | var height: Double 75 | 76 | init(x: Double, y: Double, width: Double, height: Double) { 77 | top = Point(x: x, y: y) 78 | self.width = width 79 | self.height = height 80 | } 81 | } 82 | ``` 83 | 1. Да се имплементират следните класове (или структури, _по избор_): 84 | * `Triangle: VisualComponent, Visual ` 85 | * коструктор `Trinagle(a: Point, b: Point, c: Point)` 86 | * `Rectangle: VisualComponent, Visual ` 87 | * коструктор `Rectangle(x: Int, y: Int, width: Int, height: Int)` 88 | * `Circle: VisualComponent, Visual ` 89 | * конструктор `Circle(x: Int, y:Int, r: Double)` 90 | * `Path: VisualComponent, Visual ` 91 | * конструктор `Path(points: [Point])` 92 | * `HGroup: VisualGroup, Visual ` 93 | * конструктор `HGroup()` 94 | * `VGroup: VisaulGroup, Visual ` 95 | * конструктор `VGroup()` 96 | 97 | 2. Да се напише функция, която намира най-малкия покриващ правоъгълник на `VisualComponent`. 98 | 99 | `func cover(root: VisualComponent?) -> Rect` 100 | 101 | Пример: 102 | 103 | Ако 104 | root = 105 | HGroup 106 | VGroup 107 | Circle (x:0, y:0, r:1) 108 | тогава 109 | cover(root: roоt) трябва да оцени до Rect(x: -1, y: 1, width: 2, height: 2) 110 | 111 | 3. Да се имплементира шаблонен свързан списък със съответния интерфейс. 112 | ```swift 113 | class List { 114 | var value: T 115 | var next: List? 116 | } 117 | 118 | extension List { 119 | subscript(index: Int) -> T? { 120 | //TODO: implementation 121 | } 122 | } 123 | 124 | extension List { 125 | var length: Int { 126 | //TODO: implementation 127 | } 128 | } 129 | 130 | extension List { 131 | func reverse() { 132 | //TODO: implementation 133 | } 134 | } 135 | ``` 136 | 4. Да се имплемнтира функция, която от списък от вложени списъци (може да решите задачата и за произволно ниво на влагане) генерира списък с всички елементи. 137 | 138 | ```swift 139 | extension List { 140 | func flatten() -> List { 141 | //TODO: implementation 142 | } 143 | } 144 | ``` 145 | Пример: 146 | ```swift 147 | List(List(2, 2), 21, List(3, List(5, 8))).flatten() 148 | 149 | List(2, 2, 21, 3, 5, 8) 150 | ``` 151 | 152 | ## Въпроси за системата за автоматично оценяване 153 | 154 | 1. Защо нямам оценка? 155 | 156 | > Вероятно кода, който сте предали не е .swift файл или самият той не може да се компилира. Възможно е да крашва и при подбраните от нас входни данни. 157 | 158 | Как да се справя с проблема? 159 | 160 | >Моля, пишете ни, ако не успявате да се справите с проблема. 161 | 162 | 2. Трябва ли решението да отпечатва нещо? 163 | 164 | > Решението **не** трябва да отпечатва нищо в конзолата, защото няма да може да бъде обработено от системата за автоматично оценяване. 165 | 166 | 3. Ако нямам оценка, това 0 точки ли означава? 167 | 168 | > **Не**. Когато системата не е успяла да Ви оцени, трябва да разгледаме решението Ви отделно. 169 | 170 | 4. Може ли да добавите примерен файл, който работи при качване в системата. 171 | 172 | > Да. В задачите има връзка към такъв. 173 | 174 | 5. Имам проблеми със ситемата, но не намирам логично обяснение. Какво да правя? 175 | 176 | > Пишете ни. Екипът работи над подобрение на текущата системата. 177 | 178 | 6. А кой е e-mail-a? 179 | 180 | > Трябва да го знаете вече. 181 | 182 | 7. Не трява ли задачите да са по-ясно дефинирани и да имаме повече примери, с които да тестваме. Системата не ме оценява правилно, а аз съм сигурен, че решението ми е супер вярно. Какво да правя? 183 | 184 | > Условията на задачите не са формални, за да позволят интерпретация. Ние смятаме, че свободата в интерпретацията ви подготвя по-добре за реалните задачи след този курс. Не получавате оценкта в системата, защото пропускате случаи от решението (често това са край случаи, но валидни) или защото сте намерили проблем в системата (по-малко вероятно, но възможно). Моля, свържете се с нас, за да ви помогнем с насоки. 185 | -------------------------------------------------------------------------------- /homework/assets/register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftFMI/swift_2019_2020/5ed6b6a8b8ce0ae8b6b82c3d67fe61e5ed82b03c/homework/assets/register.png -------------------------------------------------------------------------------- /homework/assets/task1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftFMI/swift_2019_2020/5ed6b6a8b8ce0ae8b6b82c3d67fe61e5ed82b03c/homework/assets/task1.png -------------------------------------------------------------------------------- /homework/assets/task1_template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SwiftFMI/swift_2019_2020/5ed6b6a8b8ce0ae8b6b82c3d67fe61e5ed82b03c/homework/assets/task1_template.png -------------------------------------------------------------------------------- /lecture-notes/README.md: -------------------------------------------------------------------------------- 1 | # Нови записки 2 | 3 | Тази част от репозиторито ще съхранява новите записки по материала, който разгледахме допълнително в курса. След като минат няколко редакции, лекциите ще бъдат добавени като допълнителни към основните лекции, които се разглеждат в курса "Програмиране със Swift". 4 | 5 | Новите записки са чернова. Може да съдържат грешки. Добре е да създавате "issue"-та в Github, за да можем да ги отстраним. 6 | 7 | Пул рекуести (Pull request/PR) с предложения и корекции са добре дошли! 8 | 9 | 10 | Екипът на Swift FMI -------------------------------------------------------------------------------- /lecture-notes/spm-windows10-property-wrappers.md: -------------------------------------------------------------------------------- 1 | # Swift Package Manager (SPM) 2 | 3 | ## Property wrappers - Обвивки 4 | 5 | Когато използваме пропъртита, които представляват състояние, много често имаме асоциирана логика, която се изпълнява всеки път при промяна в стойността им. 6 | 7 | Например, бихме могли да валидираме всяка нова стойност на базата на правила, да я трансформираме по някакъв начин или да нотифицираме наблюдатели, които следят за промяна в стойността. 8 | 9 | В тези ситуации на помощ идват Обвивките (Property wrappers), въведени със Swift 5.1. Позволяват ни да прикрепим и енкапсулираме тази логика директно към нашите пропъртита, което от своя страна означава нови възможности за преизползваемост и енкапсулация. 10 | 11 | Името подсказва, че това е тип, който обвива дадена стойност, добавяйки допълнителна логика. Може да се имплементира, използвайки структура (`struct`) или клас (`class`), които са анотирани с @propertyWrapper атрибута. Единственото изискване е всяка обвивка да има променлива/пропърти на име `wrappedValue`, което подсказва на Swift коя и каква стойност бива обвита/обгърната. 12 | 13 | ### Трансформация на стойности чрез обвивки 14 | ```swift 15 | @propertyWrapper 16 | struct Truncated { 17 | var value: Double 18 | let precision: Int 19 | 20 | init(wrappedValue value: Double, _ precision: Int) { 21 | self.value = value 22 | self.precision = precision 23 | } 24 | 25 | var wrappedValue: Double { 26 | get { value } 27 | set { value = truncated(newValue) } 28 | } 29 | 30 | private func truncated(_ value: Double) -> Double { 31 | guard precision > 0, precision < 16 else { return value } 32 | let divisor = pow(10.0, Double(precision)) 33 | return (value * divisor).rounded(.towardZero) / divisor 34 | } 35 | } 36 | 37 | @propertyWrapper 38 | struct Rounded { 39 | var value: Double 40 | let precision: Int 41 | 42 | init(wrappedValue value: Double, _ precision: Int) { 43 | self.value = value 44 | self.precision = precision 45 | } 46 | 47 | var wrappedValue: Double { 48 | get { value } 49 | set { value = truncated(newValue) } 50 | } 51 | 52 | private func rounded(_ value: Double) -> Double { 53 | guard precision > 0, precision < 16 else { return value } 54 | let divisor = pow(10.0, Double(precision)) 55 | return (value * divisor).rounded() / divisor 56 | } 57 | } 58 | ``` 59 | 60 | ### Ограничаване на стойности чрез Обвивки 61 | ```swift 62 | @propertyWrapper 63 | struct Clamping { 64 | var value: Value 65 | let range: ClosedRange 66 | 67 | init(initialValue value: Value, _ range: ClosedRange) { 68 | precondition(range.contains(value)) 69 | self.value = value 70 | self.range = range 71 | } 72 | 73 | var wrappedValue: Value { 74 | get { value } 75 | set { value = min(max(range.lowerBound, newValue), range.upperBound) } 76 | } 77 | } 78 | ``` 79 | Може да използваме `@Clamping`, за да гарантираме стойността на променлива, която представлява киселинност на разтвор в диапазона 0 – 14. 80 | 81 | ```swift 82 | struct Solution { 83 | @Clamping(0...14) var pH: Double = 7.0 84 | } 85 | 86 | let carbonicAcid = Solution(pH: 4.68) // 1 mM в нормални условия 87 | При стойности под 0 и над 14, стойността се променя 88 | 89 | let ultraAcid = Solution(pH: -1) 90 | ultraAcid.pH // 0 91 | ``` 92 | 93 | Може да използваме ги използваме, за да създаваме други Обвивки. Например `UnitInterval` използва `@Clamping`, за да ограничи стойностите между 0 и 1 (включително). 94 | ```swift 95 | @propertyWrapper 96 | struct UnitInterval { 97 | @Clamping(0...1) 98 | var wrappedValue: Value = .zero 99 | 100 | init(initialValue value: Value) { 101 | self.wrappedValue = value 102 | } 103 | } 104 | ``` 105 | 106 | Бихме могли да го използваме при създаване на RGB цветове, използвайки @UnitInterval Обвивката, за да ограничим интензитета на червено, зелено и сньо в проценти. 107 | 108 | ```swift 109 | struct RGB { 110 | @UnitInterval var red: Double 111 | @UnitInterval var green: Double 112 | @UnitInterval var blue: Double 113 | } 114 | 115 | let cornflowerBlue = RGB(red: 0.392, green: 0.584, blue: 0.929) //#6495ed - 39.0/255, 58.0/255, 93.0/255 116 | ``` 117 | 118 | ## Modules - Модули 119 | В Swift кодът се организира в модули. Всеки модул дефинира именно пространсто (namespace) и налага контрол на достъпа до всяка една част от кода извън модула. 120 | 121 | Една програма може да се състои само от един модул, но и може да внася/използва и други модули като зависимости. Освен системните модули Darwin в macOS или Glibc в Linux, повечето зависимости изискват свалянето на код и компилирането му, за да се използват. 122 | 123 | При отделянето на код, решаващ определен проблем в модул, той става преизползваем. Например модул, който предоставя функционалност за достъпване на интернет ресурси, който да се ползна едновременно в приложение за прогнозата за времето или приложение за споделяне на снимки. Използвайки модули от други програмисти, можем да спестим време и ресурси, вместо да имплементираме функционалността сами. 124 | 125 | ### Packages - Пакети 126 | Пакетите в Swift са сбор от сорс-код файлове и манифест файл. Манифестът, наречен Package.swift, дефинира името на пакета, неговото съдържание и зависимости чрез модула PackageDescription. 127 | 128 | Един пакет има една или повече програми/цели (targets), като всяка описва продукт и може да дефинира една или повече зависимости. 129 | 130 | ### Products - Продукти 131 | От една програма/цел (target) продуктът може да е библиотека или изпълнимо приложение. Библиотеката съдърга модул, който може да бъде влагам в друг Swift код, а изпълнимото приложение да се изпълнява от операционната система. 132 | 133 | ### Dependencies - Зависимости 134 | Зависимостите са модули, необходими за компилирането на кода в пакета. Зависимостта се съсоти от релативни или абсолютни пътища и URL-и към сорс-кода на пакета и набор от изисквания за версията му. Полята на мениджъра на пакети е да намали усилията, необходими за координирането на зависимостите чрез автоматизирано сваляне и компилиране на зависимостите в даден проект. Този процес е рекурсивен - една зависимост, сама по себе си, може да има други зависимости и т.н., оформяйки граф на зависимостите. Мениджърът на пакети сваля и компилира всичко необходимо, за да изпълни този граф. 135 | 136 | ### Какво е манифест на пакет? 137 | 138 | Това е файл, който описва пакета. Посредством този пакет, SPM може да намери всички необходими външни зависимости и да компилира успешно текущия модул. Това позволява създаването на сложни пакети и модули в тях, които използват множество външни пакети. 139 | 140 | ## Какви видове модули можем да правим със SPM? 141 | 142 | Чрез `package` командата можем да видим различните видове пакети (които имат поне един модул), които можем да създаваме със `SPM`. 143 | 144 | ```shell 145 | swift package init --help 146 | 147 | Резулта: 148 | OVERVIEW: Initialize a new package 149 | 150 | OPTIONS: 151 | --name Provide custom package name 152 | --type empty|library|executable|system-module|manifest 153 | ``` 154 | 155 | Ще разгледаме няколко от основните типове - библиотека, изпълним файл, празен пакет и техните основни характеристики. 156 | 157 | ### Пакет библиотека 158 | 159 | Това е пакет на Swift, който можем да използваме в други проекти. Този пакет има поне един модул, който може да дефинира различни типове от данни, функции и дори и по-сложен набор от интерфейси, класове, типове, т.е. Framework за разработка на софтуер. 160 | 161 | Можем да създадем пакет от тип библиотека със следната команда: 162 | 163 | > Не забравяйте да направите нова директория за съответния `swift` модул. Когато сте в тази директория, спокойно може да използвате следващите команди. 164 | >```shell 165 | >mkdir myLibrary 166 | >cd myLibrary 167 | >``` 168 | 169 | ```shell 170 | swift package init --name MySwiftLibrary --type library 171 | ``` 172 | 173 | Тази команда генерира следната структура от файлове и директории: 174 | 175 | ``` 176 | . 177 | ├── Package.swift - основен описател на пакета 178 | ├── README.md - файл, където можем да опишем проекта. 179 | │ Доста полезен, когато публикуваме проекта в github 180 | ├── Sources - тук се съхраняват всички модули 181 | │   └── MySwiftLibrary - директория с кода, 182 | │ │ който ще е част от съответния модул и пакет 183 | │   └── MySwiftLibrary.swift - примерен файл 184 | └── Tests - тук се съдържат тестовете към пакета. Те са в друг модул. 185 | ├── LinuxMain.swift - стартов файл, нужен за стартиране на тестовете под Linux. 186 | └── MySwiftLibraryTests 187 | ├── MySwiftLibraryTests.swift - Тестове за Linux 188 | └── XCTestManifests.swift - Тестове за macOS 189 | 190 | ``` 191 | 192 | Ето и съдържанието на `Package.swift` - така нарченият манифест или описател на нашия пакет. 193 | 194 | ```swift 195 | // swift-tools-version:5.2 196 | // The swift-tools-version declares the minimum version of Swift required to build this package. 197 | 198 | import PackageDescription 199 | 200 | let package = Package( 201 | name: "MySwiftLibrary", 202 | products: [ 203 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 204 | .library( 205 | name: "MySwiftLibrary", 206 | targets: ["MySwiftLibrary"]), 207 | ], 208 | dependencies: [ 209 | // Dependencies declare other packages that this package depends on. 210 | // .package(url: /* package url */, from: "1.0.0"), 211 | ], 212 | targets: [ 213 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 214 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 215 | .target( 216 | name: "MySwiftLibrary", 217 | dependencies: []), 218 | .testTarget( 219 | name: "MySwiftLibraryTests", 220 | dependencies: ["MySwiftLibrary"]), 221 | ] 222 | ) 223 | ``` 224 | 225 | Файлът започва с коментар, който определя версията на компилатора използван за създаването на пакета. Често, това е минималната версия, необходима за да може да се компилира успешно съответния модул. 226 | 227 | ```swift 228 | // swift-tools-version:5.2 229 | ``` 230 | В текущия случай е използвана версия 5.2.1 на `swift`. Следва стандартния импорт: 231 | `import PackageDescription` и после се създава константен `package`. 232 | 233 | Тя е от тип `Package`. Има си име `name`, коeто съвпада с избраното от нас по-рано - `MySwiftLibrary`. Има и следните три ключови елемента: 234 | 235 | 1. `products` - списък на продуктите - резултата, който ще се генерира след успешно компилиране на текущия пакет. В текущия случай това е библиотека, която може да се използва в други продукти или модули. 236 | 1. `dependencies` - списък на външните зависимости, които SPM трябва да изтегли, компилира и свърже с текущия пакет. Използва се кратка нотация за всяка зависимост с адрес (публичен или локален - от файловата система) и версия: 237 | ```swift 238 | .package(name: /*package-name*/, url: /* package url */, from: "1.0.0") 239 | ``` 240 | > Не забравяйте, че можете да създавате локални пакети и да ги свързвате по между си. Тогава трябва да иползвате адрес, който е валиден път във вашата файлова система. 241 | 242 | 1. `targets` - списък от таргети (продукти/ модули). Таргетите изграждат пакетите. Това са добре познатите ни модули. Можем да описваме и модули за тестове. 243 | Ето и текущия пример: 244 | 245 | ```swift 246 | .target( 247 | name: "MySwiftLibrary", 248 | dependencies: []), 249 | ``` 250 | Продуктът си има име, което съвпада с името на пакета (и директорията, където трябва да се съхранява кода на модула). Има и списък от имената на вънщни зависимости. Т.е. тук можем да добавим имената на външни зависимости, които сме добавил в предишната секция `dependencies`. 251 | 252 | Със следната команда можем да компилираме пакета: 253 | 254 | ``` 255 | swift build 256 | ``` 257 | 258 | За да публикуваме този пакет дори и локално, трябва да използваме git. Със следните команди, можем да създадем локално репозитори: 259 | 260 | ```shell 261 | git init 262 | git add . 263 | git commit -m "initial commit" 264 | git tag 1.0.0 265 | ``` 266 | 267 | `git init` - създава локално репозитори 268 | `git add .` - добавя всички файлове към repo-то. Тук се проверява, дали няма специални правила в `.gitignore` файла. Там са описани изключенията. Повече може да се прочете [тук](https://git-scm.com/docs/gitignore) 269 | `git commit -m "initial commit"` - съхраняване на добавените файлове в git 270 | `git tag 1.0.0` - публикуване на текущата версия на репото, като tag с име `1.0.0`. Важно е да имаме правилно именуван таг, защото SPM използва таговете, за да може да тегли правилната версия на всеки пакет при подготвяне на зависимостите. 271 | 272 | > Не забравяйте да маркирате всички типове данни (класове, структури, изброени типове, функции) с правилните нива на видимост. В случая, когато искате те да са достъпни в други пакети, тогава трябва да ползвате `public` или `open`. Повече за тях по-късно или може да прочете повече [тук](https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html). 273 | 274 | 275 | ### Изпълним пакет (конзолно приложение)? 276 | 277 | Това е модул, който позволява стартиране на модула от конзолата (терминала) на операционната система. Възможна е комуникация с операционната система чрез модулът отговорен за конзолните приложения. 278 | Отличава се с наличието на `main.swift`. Това е началната (входната) точка на този модул. След успешно компилиране, резултатът е изпълним файл, който може да бъде стартиран на съответната операционна система (Linux, macOS и дори Windows). 279 | 280 | Ето как можем да създадем такъв модул: 281 | 282 | > Трябва да сме сигурни, че можем да стартираме `swift package` в Ubuntu shell-a. Ако имаме проблеми или затруднения, може да разгледате допълнителния материал, който дава наюални насоки, как да инсталирате Swift toolchain на Windows използвайки Ubuntu shell. - [тук](https://github.com/SwiftFMI/swift_2019_2020/blob/master/How_to_install_Swift5_on_Windows10.md). 283 | 284 | > Преди да изпълните следващите команди, трябва да сте добавили `swift` компилатора в `PATH` променливата на оперционната система или да знаете пълния път до компилатора. 285 | 286 | > Не забравяйте да направите нова директория за съответния `swift` модул. Когато сте в тази директория, спокойно може да използвате следващите команди. 287 | >```shell 288 | >mkdir myApp 289 | >cd myApp 290 | >``` 291 | 292 | ```shell 293 | swift package init --name MySwiftApp --type executable 294 | ``` 295 | 296 | Тази команда генерира следната структура от файлове и директории: 297 | 298 | ``` 299 | . 300 | ├── Package.swift 301 | ├── README.md 302 | ├── Sources 303 | │   └── MySwiftApp 304 | │   └── main.swift - входна точка на изпълнимия модул 305 | └── Tests 306 | ├── LinuxMain.swift 307 | └── MySwiftAppTests 308 | ├── MySwiftAppTests.swift 309 | └── XCTestManifests.swift 310 | ``` 311 | 312 | ### Как да свържем двата пакета, които създадохме? 313 | 314 | Първо нека да редактираме `MySwiftLibrary`. Отваряме файла `myLibrary/Sources/MySwiftLibrary/MySwiftLibrary.swift`. 315 | 316 | Редактираме го както следва: 317 | 318 | ```swift 319 | public struct MySwiftLibrary { 320 | /// 321 | /// Public constructor 322 | /// 323 | public init(text: String = "") { 324 | self.text = text 325 | } 326 | 327 | /// Make this property public accessible 328 | public var text = "Hello, World!" 329 | 330 | public let version = "alpha-1" 331 | } 332 | ``` 333 | 334 | След това трябва да се добавят новите промени в git-a и да се създаде нов таг. Не забравяйте, че това е правилния начин за публикуване на нова версия, на пакета, която да може да се ползва от SPM. 335 | 336 | > Не е нужно да компилирате библиотеката, но е добре да знаете, че може да се компилира успешно и че работи правилно. 337 | 338 | Ето ги и нужните команди: 339 | ```shell 340 | git add . 341 | git commit -m "extend the library" 342 | git tag 1.0.2 343 | ``` 344 | На кратко - добавяне на новите промени. Публикуването им в локалното git repository и създаване на таг с име 1.0.2. 345 | 346 | Сега се прехвърляме в изпълнимия проект `MySwiftApp`. Тук отваряме манифеста `Package.swift` и го променяме както следва: 347 | 348 | ```swift 349 | // swift-tools-version:5.2 350 | // The swift-tools-version declares the minimum version of Swift required to build this package. 351 | 352 | import PackageDescription 353 | 354 | let package = Package( 355 | name: "MySwiftApp", 356 | dependencies: [ 357 | // свързване с библиотеката, която създадохме по-рано 358 | //! не забравяйте да коригирате пътя - url параметъра. Той зависи 359 | // от това къде сте създали съответно двата пакета на swift 360 | // в примера myLibrary и myApp се намират в обща директория 361 | //. 362 | //├── myApp 363 | //└── myLibrary 364 | .package(name: "MySwiftLibrary", url: "../myLibrary", from: "1.0.2"), 365 | ], 366 | targets: [ 367 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 368 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 369 | .target( 370 | name: "MySwiftApp", 371 | //тук добавяме името на външния пакет 372 | dependencies: ["MySwiftLibrary"]), 373 | .testTarget( 374 | name: "MySwiftAppTests", 375 | dependencies: ["MySwiftApp"]), 376 | ] 377 | ) 378 | ``` 379 | 380 | После отваряме `myApp/Sources/MySwiftApp/main.swift` и го редактираме както следва: 381 | 382 | ```swift 383 | import MySwiftLibrary 384 | 385 | let lib = MySwiftLibrary(text: "Hello from the library") 386 | 387 | print(lib.text) 388 | 389 | print(lib.version) 390 | 391 | ``` 392 | 393 | Запазваме промените и извикваме следната команда за стартиране на изпълнимия проект: 394 | 395 | ```shell 396 | swift run 397 | ``` 398 | 399 | SPM ще намери нашата библиотека. Ще потърси правилната версия, която е `1.0.2`. Това го обявихме още, когато редактирахме `Package.swift`. Ще свали кода й и ще я компилира. После ще се опита да компилира и текущия модул (target). След успешна компилация, ще опита да го стартира. 400 | 401 | Трябва да видите следния резултат на вашите екрани: 402 | 403 | ``` 404 | [7/7] Linking MySwiftApp 405 | Hello from the library 406 | alpha-1 407 | ``` 408 | 409 | Първият ред не е част от нашата програма, а е остатъчен резултат от изпълнените действия от SPM и Swift компилатора. 410 | 411 | > Къде можем да намерим изпълнимия файл? Понеже сме използвали swift да създаде debug версия (и ако изпозлваме Linux (shell)), тогава можем да намерим самото конзолно приложение на следното място `.build/x86_64-unknown-linux-gnu/debug/MySwiftApp`. 412 | 413 | > Със следната команда можем да създадем `release` версия: 414 | ``` 415 | swift build -c release 416 | ``` 417 | > И съответно приложението ще можем да намери тук `.build/release/MySwiftApp` и да го стартираме. Очаквано резултатът е същия. 418 | 419 | > Кратко резюме: До тук се научихме как да създаваме библиотека чрез `SPM`. Можем спокойно да добавяме различни класове, структури, функции, и други типове данни към нея и да публикуваме версии локално чрез `git`. (По-долу може да прочетете как да публикувате ваша библиотека написан на `swift` в `github`.) Също така, можем да създадем изпълнимо приложение, което да ползва външни пакети, публикувани локално на нашата файлова система или в публичното пространство (еднствената разлика е в `url`-a на пакета). 420 | 421 | ### Празен пакет 422 | 423 | Това е най-базовия модул. Той може да бъде използван и разширен в посока на вече познатите ни модули - библиотека или изпълним. 424 | 425 | Той има следната структура: 426 | 427 | ``` 428 | . 429 | ├── Package.swift 430 | ├── README.md 431 | ├── Sources 432 | └── Tests 433 | ``` 434 | 435 | Като няма допълнителни файлове. Също така липсват и основните елементи в `Package.swift` файла. Следва пример: 436 | 437 | ```swift 438 | // swift-tools-version:5.2 439 | // The swift-tools-version declares the minimum version of Swift required to build this package. 440 | 441 | import PackageDescription 442 | 443 | let package = Package( 444 | name: "MySwiftEmptyPackage", 445 | dependencies: [ 446 | // Dependencies declare other packages that this package depends on. 447 | // .package(url: /* package url */, from: "1.0.0"), 448 | ] 449 | ) 450 | ``` 451 | 452 | ## Как да публикуваме Swift пакет от локално git репо в github? 453 | 454 | Предполагаме, че вече имате github акаунт. Тогава трябва да създаде публично или частно repo от интерфейса на github. 455 | 456 | След това трябва да изпълните следните няколко git команди в основната директория на вашия пакет. Нека да приемем, че искаме да публикуваме `MySwiftLibrary` и всички версии. 457 | 458 | > Не забравяйте да промените пътя до вашето repo в следващите команди. Ако не го направите, ще видите съобщение за грешка от git. 459 | 460 | > Ако имате активиран 2FA (Two Factor Authentication - дву-факторна аутентикация) трябва да използвате или токен вместо вашата парола или частен ключ, за да може да къмитвате файлове в [github](https://help.github.com/en/github/authenticating-to-github/accessing-github-using-two-factor-authentication). 461 | 462 | ``` 463 | git remote add origin https://github.com/swiftfmi/MySwiftLibrary.git 464 | git push -u origin master 465 | git push origin --tags 466 | ``` 467 | Ако искате само определена версия, може да използвате следната команда. 468 | ``` 469 | git push origin 1.0.2 470 | ``` 471 | 472 | ## Какви команди можем да използваме? 473 | 474 | ### Swift 475 | 476 | ``` 477 | swift --help 478 | ``` 479 | 480 | ``` 481 | swift run 482 | ``` 483 | 484 | 485 | ``` 486 | swift build 487 | ``` 488 | 489 | ### SPM 490 | 491 | ``` 492 | swift package 493 | ``` 494 | 495 | TBD (Кратък списък на командите) 496 | ### Git 497 | 498 | ``` 499 | git -h 500 | ``` 501 | 502 | ``` 503 | git init 504 | ``` 505 | 506 | ``` 507 | git add file/to/be/added 508 | ``` 509 | 510 | ``` 511 | git commit -m "message" 512 | ``` 513 | 514 | ``` 515 | git push 516 | ``` 517 | > Само, ако има `origin` - външно репо, с което да се синхронизира. 518 | 519 | ## Как да си организираме проекта? 520 | 521 | Тук е добре да следваме следната добра практика. Приложението, което трябва да комуникира с операционната система, трябва да е минимално. Т.е. трябва всичко да е в различни модули и дори пакети, а изпълнимото приложение (модул) да използва другите модули като зависимости. Това ще позволи - по-високо ново на преизползване на кода. По-добра структура, която позволява минимално "триене" със спецификите на OS-a. Тези специфики, остават изолирани само в модула, който комуникира с OS-a. 522 | 523 | ## Нива на видимост на кода (повторение) 524 | 525 | Тук е добре да си припомним петте нива на видимост, които има Swift и да направим ясно разграничение, кога е добре да ползваме `open` и `public`. Няма да задълбаваме в нивата с по-малко ниво на видимост от `internal` понеже те нямат отношение към външните модули. 526 | 527 | Какво ни дава `public` - Видимост на типове и функции от други модули и приложения (същината на модула - API, който да се използва) 528 | Какво ни дава `open` - Възможност за наследяване и разширяване на класовете от модула. 529 | -------------------------------------------------------------------------------- /projects/final.grades.md: -------------------------------------------------------------------------------- 1 | Финални оценки 2 | 3 | Включват резлтататите от финалния проект и двете домашни през семестъра 4 | 5 | |фн|Оценка| 6 | |-----|--------------| 7 | |45221|6.00| 8 | |62125|5.00| 9 | |31492|6.00| 10 | |81422|5.00| 11 | |62275|6.00| 12 | |31488|4.00| 13 | |62369|4.00| 14 | |81739|4.50| 15 | |81693|6.00| 16 | |62012|6.00| 17 | |81770|4.00| 18 | |81894|4.00| 19 | |71871|4.50| 20 | |81423|5.25| 21 | |81255|-| 22 | |81623|6.00| 23 | |45253|5.95| 24 | |45421|-| 25 | |62162|5.75| 26 | |62240|5.50| 27 | |45256|4.00| 28 | |81400|-| 29 | |71684|5.00| 30 | |81620|5.75| 31 | |81579|6.00| 32 | |62181|3.50| 33 | |81547|6.00| 34 | |62182|5.50| 35 | |81656|-| 36 | |81752|5.00| 37 | |81748|5.00| 38 | |81764|6.00| 39 | |31366|-| 40 | |81740|-| 41 | |61900|4.50| 42 | |81485|5.00| 43 | |81519|5.00| 44 | |81478|-| 45 | |81461|5.00| 46 | |81589|5.50| 47 | |81695|4.00| 48 | |81598|4.50| 49 | |31482|3.00| 50 | |31496|-| 51 | |62220|6.00| 52 | |71755|-| 53 | |81738|6.00| 54 | |81514|-| 55 | |45137|5.25| 56 | |71768|-| 57 | |71765|-| 58 | |62202|-| 59 | |31496|-| 60 | |62137|-| 61 | |62096|5.50| 62 | |62160|-| 63 | |81619|5.75| 64 | |81606|-| 65 | |71634|3.25| 66 | |81795|6.00| 67 | |81712|6.00| 68 | |62187|5.00| 69 | |62148|-| 70 | |81677|5.00| 71 | |62238|-| 72 | |62163|5.50| 73 | |62152|-| 74 | |81833|-| 75 | |81394|6.00| 76 | |81567|5.75| 77 | |81574|5.00| 78 | |62120|-| 79 | |81736|-| 80 | -------------------------------------------------------------------------------- /projects/final.projects.md: -------------------------------------------------------------------------------- 1 | Разпределение на финалните проекти 2 | 3 | |фн|Проект| 4 | |-----|--------------| 5 | |45221|Проект - "Дама"| 6 | |62125|Проект - "Дама"| 7 | |31492|Проект - РПГ игра| 8 | |81422|Проект - РПГ игра| 9 | |62275|Проект - зарове| 10 | |31488|Проект - зарове| 11 | |62369|Проект - "Дама"| 12 | |81739|Проект - РПГ игра| 13 | |81693|Проект - зарове| 14 | |81693|Проект - зарове| 15 | |62012|Проект - "Дама"| 16 | |81770|Проект - "Дама"| 17 | |81894|Проект - РПГ игра| 18 | |71871|Проект - РПГ игра| 19 | |81423|Проект - зарове| 20 | |81255|Проект - РПГ игра| 21 | |81623|Проект - "Дама"| 22 | |45253|Проект - "Дама"| 23 | |45421|Проект - зарове| 24 | |62162|Проект - "Дама"| 25 | |62240|Проект - зарове| 26 | |45256|Проект - зарове| 27 | |81400|Проект - зарове| 28 | |71684|Проект - зарове| 29 | |81620|Проект - РПГ игра| 30 | |81579|Проект - "Дама"| 31 | |62181|Проект - РПГ игра| 32 | |81547|Проект - зарове| 33 | |62182|Проект - зарове| 34 | |81656|Проект - "Дама"| 35 | |81752|Проект - РПГ игра| 36 | |81748|Проект - РПГ игра| 37 | |81764|Проект - "Дама"| 38 | |81764|Проект - зарове| 39 | |31366|Проект - "Дама"| 40 | |81740|Проект - РПГ игра| 41 | |61900|Проект - "Дама"| 42 | |81485|Проект - "Дама"| 43 | |81519|Проект - зарове| 44 | |81478|Проект - зарове| 45 | |81461|Проект - РПГ игра| 46 | |81589|Проект - "Дама"| 47 | |81695|Проект - "Дама"| 48 | |81598|Проект - "Дама"| 49 | |31482|Проект - зарове| 50 | |31496|Проект - "Дама"| 51 | |62220|Проект - зарове| 52 | |71755|Проект - "Дама"| 53 | |81738|Проект - зарове| 54 | |81514|Проект - зарове| 55 | |45137|Проект - РПГ игра| 56 | |71768|Проект - зарове| 57 | |71765|Проект - "Дама"| 58 | |62202|Проект - зарове| 59 | |31496|Проект - РПГ игра| 60 | |62137|Проект - РПГ игра| 61 | |62096|Farkle Console Dice Game| 62 | |62160|Проект - "Дама"| 63 | |81619|Проект - РПГ игра| 64 | |81606|Проект - зарове| 65 | |71634|Проект - "Дама"| 66 | |81795|Проект - зарове| 67 | |81712|Проект - зарове| 68 | |62187|Проект - зарове| 69 | |62148|Проект - РПГ игра| 70 | |81677|Проект - "Дама"| 71 | |62238|Проект - "Дама"| 72 | |62163|Проект - "Дама"| 73 | |62152|Проект - "Дама"| 74 | |81833|Проект - зарове| 75 | |81394|Проект - РПГ игра| 76 | |81567|Проект - РПГ игра| 77 | |81574|Проект - "Дама"| 78 | -------------------------------------------------------------------------------- /projects/nine-mens-morris.md: -------------------------------------------------------------------------------- 1 | # Описание: 2 | Дама е игра, която се играе от двама играчи с пулове, като всеки от тях избира в началото свой цвят (единият играе с пулове в светъл цвят, а другият – в тъмен). Играчите разполагат с по девет пула, които последователно поставят на дъската на определените места. 3 | 4 | # Правила: 5 | Играта "Дама", позната още като "Коран", се играе от двама играчи на дъска с три квадрата един в друг със свързани среди на страните, като пресечните точки на линиите образуват 24 позиции за поставяне на пуловете. Всеки играч в началото има девет пула. 6 | 7 | #### 1. Поставяне на пуловете 8 | Играта започва върху празна дъска, на която играчите поставят пуловете си на свободни позиции, като се редуват. 9 | 10 | Ако играч успее да подреди три свои пула по една от правите линии на дъската, той има "дама" и премахва един от пуловете на противника. Премахнат пул не се поставя обратно на дъската. От направена "дама" не може да се премахва пул, освен в случай, че няма други свободни пулове. 11 | 12 | #### 2. Местене на пуловете 13 | След като играчите поставят всички свои пулове на дъската, започват да ги местят. Пул може да бъде преместен по линия на дъската до съседна свободна позиция. Ако играч не може да премести нито един свой пул, той губи играта. 14 | 15 | Както при поставянето, ако играч подреди "дама", той премахва един от пуловете на противника, като по възможност не разваля направена противникова "дама". Ако играч остане само с два пула, той вече не може да прави "дама" и да взема пулове на противника, при което губи играта. 16 | 17 | ### 3. Летене 18 | Ако играч остане само с три пула, той може да ги мести на всяка свободна позиция, не само на съседните. Това се нарича "летене" или "скачане". 19 | 20 | ### Общи 21 | 22 | Целта на играта е да се прави "дама", при което се взема по един пул на противника, докато той остане само с два пула, или да се затворят пуловете на противника, така че той да не може да мести. 23 | 24 | Добра стратегия е правенето на съседни "дами", при което с всяко местене на единия пул се затваря една от тях и се взема по един противников пул (както на схемата – с белите пулове - ○). 25 | 26 | ``` 27 | · - - - - - · - - - - - · 28 | | | | 29 | | · - - - · - - - ○ | 30 | | | | | | 31 | | | · - · - ● | | 32 | | | | | | | 33 | · - ○ - ○ ● - ○ - · 34 | | | | | | | 35 | | | · - · - ● | | 36 | | | | | | 37 | | ○ - - - ● - - - ○ | 38 | | | | 39 | · - - - - - ● - - - - - · 40 | ``` 41 | 42 | Характерно за играта "Дама" е простотата и бързината на подготовката. Дъската се прави лесно с картон, молив и линийка – чертаят се три квадрата един в друг, с разстояние 5 – 6 сантиметра и отсечки, свързващи средите на страните на квадратите. Може да се начертае и в пясъка на плажа. За пулове може да се ползват всякакви подръчни средства – пионки, копчета, камъчета, мидички – девет бели, плюс девет с друг цвят. 43 | 44 | # Интерфейс на играта: 45 | 46 | Така трябва да изглежда една празна дъска за игра на дама, която може да бъде лесно отпечатана в конзола. 47 | 48 | ``` 49 | ·-----------·-----------· 50 | | | | 51 | | ·-------·-------· | 52 | | | | | | 53 | | | ·---·---· | | 54 | | | | | | | 55 | ·---·---· ·---·---· 56 | | | | | | | 57 | | | ·---·---· | | 58 | | | | | | 59 | | ·-------·-------· | 60 | | | | 61 | ·-----------·-----------· 62 | ``` 63 | 64 | * Място, което **не** е заето от пул, се отбелязва с `·`; 65 | * Белите пулове се маркират със специалният символ: `○`; 66 | * Черните пулове се маркират с: `●`; 67 | * Хоризонталните линии, по които могат да се движат пуловете, се отбелязват с тирета `-`; 68 | * Вертикалните линии, по които могат да се движат пуловете, се отбелязват с: `|`. 69 | 70 | Белите и черните пулове заместват празните места при "поставяне" върху дъската. 71 | 72 | # Задачи по проект №1: 73 | Да се имплементирт: 74 | * Правилата на играта; 75 | * Поставяне по дъската ще се оцъществява чрез подаване на координати. Хоризонтално координатите могат да бъдат A, B, C, D, E, F или G. Съответно вертиналните позиции могат да бъдат 1, 2, 3, 4, 5, 6 или 7. Имайте предвид, че позиции като А2 са невалидни. За повече информация моля погледнете тази визуалицация на дъска с координати: 76 | 77 | ``` 78 | A B C D E F G 79 | 80 | 1 ·-----------·-----------· 81 | | | | 82 | 2 | ·-------·-------· | 83 | | | | | | 84 | 3 | | ·---·---· | | 85 | | | | | | | 86 | 4 ·---·---· ·---·---· 87 | | | | | | | 88 | 5 | | ·---·---· | | 89 | | | | | | 90 | 6 | ·-------·-------· | 91 | | | | 92 | 7 ·-----------·-----------· 93 | ``` 94 | 95 | * Местене на пул се осъществява чрез запис на два последователни координати. Пример: А1А4 (пул в горният ляв ъгъл се мести на дясно). 96 | * При появила се "дама", трябва да се поискат координати на пул на опонента за премахване; 97 | * Подаване на входящи координати към изпълнителят на проект №2; 98 | * Грешки при невалидно въведени данни; 99 | * Отпечатване на игровата дъска с позициите на пуловете в началото на играта и след всеки изигран ход; 100 | * Отпечатване на победител или равен при край на играта (играч не може да премести пул или някой от играчите остане с 2 пула). 101 | 102 | # Задачи по проект №2: 103 | Да се имплементира: 104 | * Запис на входящи координати (например А4 - поставяне на пул, А1А4 - местене на пул). Координатите трябва да бъдат подавани от изпълнителят на проект №1; 105 | * Подаване на координати за поставяне на пул или местенето на вече поставен. Подадените координати трябва да целят да се направи "дама" или да попречи създавенето на такава от противника, спрямо досегашните ходове от двете страни и правилата на играта; 106 | 107 | Източник правила: [Wikipedia](https://bg.wikipedia.org/wiki/%D0%94%D0%B0%D0%BC%D0%B0_%28%D0%B8%D0%B3%D1%80%D0%B0%29) 108 | -------------------------------------------------------------------------------- /projects/rpg.md: -------------------------------------------------------------------------------- 1 | # Final Project (Draft) 2 | Всеки стдудент работещ над този финален проект трябва да реализира поне два от модулите описани по-долу в собствено репозитори изпозлвайки Swift и знанията от курса. 3 | 4 | Трябва да спазите протоколите от основното репо предоставено от нас, за да е възможно "сглобяването" на различни модули в една работеща версия на игра. 5 | 6 | ## Да се напише модул за ролева игра: 7 | 8 | 9 | 1. Модул за генериране на карта 10 | 2. Модул за герои 11 | 3. Модул за битки 12 | 4. Модул за въоражаване 13 | 5. Модул за движение по картата и визуализация 14 | 15 | ## Идеята на играта. 16 | Играта може да се играе от максимум 4 играча на карта. Картата може да съдържа различни видове полета. 17 | Тя е 2д, но е възможно да има телепорти, което я прави непланарна. Т.е. един играч може да се премества 18 | до всички граничещи полета на дадено. Ако то е специално, тогава може да го ползва/активира, което го премества 19 | до "съседното" съответно поле на картата. 20 | Всеки играч се движи по картата и целта му е да отстрани останалите играчи. Т.е. да ги пребори в битка и да оцелее, ако се изправи в битка с герои от картата. 21 | Всеки играч може да прави един ход, в който той има определен брои точки енергия, която да изразходва за движение по картата или влизане в битка. Всяка битка отнема точно една точка енергия. Енергията на всеки ход се генерира от модула за движение по картата. 22 | Всеки герой започва със стандартно въоражение - т.е. едно оръжие характерно за него. В процесът на движение по картата може да събира нови оръжия или броня (armor). Оръжията и бронята трябва да допринасят за всяка битка. 23 | Всяка битка се провежда по ролеви модел, чрез редуване на протиниците. Първи е атакуващия герой, който е заплатил една точка енергия. Нападнатия герой не е нужно да заплаща енергия. 24 | Картата има възможност да се визуализира като 2д матрица с легенда (обяснение кое поле какво прави) 25 | Преди всеки ход, потребителя получава възможност за движение във всички възможни посоки 26 | * на горе 27 | * на дясно 28 | * на долу 29 | * на ляво 30 | * (влизане в битка, ако има друг герой на съответното поле) 31 | Героя не може да напуска пределите на картата. При невъзможен ход не се намалява енергията. 32 | 33 | ## Основна програма (псевдо код) 34 | 35 | 1. Избор на брой играчи. Минимум 2 броя. 36 | 1. Генериране на карта с определени брой размери на базата на броя играчи. 37 | 1. Докато има повече от един оцелял играч, изпълнявай ходове. 38 | * определи енергията за текущия играч 39 | * Текущия играч се мести по картата докато има енергия. 40 | * Потребителя контролира това като му се предоставя възможност за действие. 41 | * ако се въведе системна команда като `map` се визуализра картата 42 | 1. Следващия играч става текущ. 43 | 44 | ## Имеплементация 45 | 46 | Повече ингформация може да намерите [тук] (https://github.com/SwiftFMI/rpgcore). 47 | -------------------------------------------------------------------------------- /projects/zombie-dice.md: -------------------------------------------------------------------------------- 1 | # Описание: 2 | "Zombie Dice" е елементарна парти игра за 2-8 играчи - в нея играчите са зомби, което иска да изяде колкото се може повече мозъци. 3 | 4 | # Правила: 5 | За целта се теглят и хвърлят зарове, като играчите се опитват да избегнат символите с пушки, докато изяждат мозъците на недостатъчно бързите човеци. 6 | 7 | Заровете - 13 на брой, са потенциалните жертви. 8 | Играчите предизвикат късмета си, за да се доберат до повече мозъчна тъкан, като трябва да съобразят правилния момент да спрат да хвърлят зарове преди да бъдат уцелени от пушка и ходът им да приключи. 9 | 10 | Този, който първи събере всички 13 мозъка - печели играта. 11 | 12 | ### 1. Първоначална ръка 13 | В началото на хода, играчът тегли 3 зара и ги хвърля. 14 | 15 | #### 1.1. Точки 16 | Символът с мозък е една точка накрая на хода. 17 | 18 | #### 1.2. Повторно хвърляне 19 | Символът със стъпките позволява да се хвърли отново този конкретен зар. 20 | 21 | ### 1.3. Принудителен край на хода 22 | Символите с пушка са опасни, защото когато се съберат три от тях по време на един ход, то ходът приключва и не се печелят точки. 23 | 24 | ### 2. Допълнителни хвърляния 25 | След като се хвърлят трите зара, играчът решава дали иска да отчете точките до момента или да предизвика късмета си, като избере три нови зара, за да ги хвърли отново. 26 | 27 | ### Общи 28 | Целта на играта е да се съберат 13 точки и да се постигне баланс между риск и награда. 29 | 30 | Използваните символи за страните на заровете: 🧠 - точки, 👣 - повторно хвърляне, 💥 - пушка 31 | 32 | Заровете, от които се състои играта са 6-стенни и общо 13 на брой: 33 | 34 | 6 "зелени" - 3х🧠,2х👣,1х💥 35 | 36 | 4 "жълти" - 2х🧠, 2х👣, 2х💥 37 | 38 | 3 "червени" - 1х🧠, 2х👣, 3х💥 39 | 40 | # Интерфейс на играта: 41 | 42 | Играта е изцяло конзолна и всеки ход трябва да се отпечатват следните данни: 43 | 44 | ``` 45 | === 46 | Таблица с точките всички играчи 47 | Име на играч, който е на ход 48 | === 49 | Изтеглени зарове 50 | Резултат от заровете 51 | === 52 | Допълнителни тегления и хвърляния* 53 | Резултат от заровете 54 | === 55 | ``` 56 | 57 | # Изисквания 58 | Команда за стартиране на играта с настройка за брой и имена на играчите 59 | 60 | Команда за повторно хвърляне 61 | 62 | Команда за край на ход или теглене на още зарове 63 | 64 | Автоматичен край на играта и команда за повторна игра със същите параметри 65 | 66 | # Източници 67 | Източник правила: [Wikipedia](https://en.wikipedia.org/wiki/Zombie_Dice) 68 | 69 | Видео с правила: [Ozone](https://youtu.be/KwhU2PVec3k) 70 | -------------------------------------------------------------------------------- /samples/closures.swift: -------------------------------------------------------------------------------- 1 | //print("Hello Swift!") 2 | 3 | func sum(a first:Int, b second:Int) -> Int { 4 | return first + second 5 | } 6 | 7 | var f:(Int, Int) -> Int = sum 8 | 9 | // f = { (x, y) in 10 | // x * y 11 | // } 12 | f = { $0 * $1 } 13 | 14 | //print(sum(a: 1, b: 1)) 15 | print("Извикване през променлива от тип функция: \(f(2, 2))") 16 | 17 | func printMe(i: Int) { 18 | print("Print Me: \(i)") 19 | } 20 | 21 | func printMeFancy(i: Int) { 22 | print("Print Me =>> \(i) <<=") 23 | } 24 | 25 | func smartPrint(printFunction:(Int)->()) { 26 | let list = [1,2,3,4,5,6,7,8,9,10] 27 | 28 | for item in list { 29 | printFunction(item) 30 | } 31 | } 32 | //тук 33 | func smartPrint2(list:[Int]) { 34 | //тук 35 | func printMeNested(_ i:Int) { 36 | 37 | //тук 38 | print("Print Nested *** \(i) ***") 39 | } 40 | 41 | for item in list { 42 | printMeNested(item) 43 | } 44 | } 45 | 46 | 47 | 48 | // smartPrint(printFunction:printMe) 49 | // smartPrint(printFunction:printMeFancy) 50 | //smartPrint2(list:[1,2,3,4,5,6,7,8,9,10]) 51 | //printMeNested(17) 52 | 53 | 54 | // smartPrint(printFunction: { (a) -> () in 55 | // print(" *** \(a) ***") 56 | // } 57 | 58 | // smartPrint() {print(" *** \($0) ***")} 59 | 60 | 61 | // func createGen(start: Int, modify: @escaping (Int) -> Int ) -> ()->(Int) { 62 | 63 | // var myStart = start 64 | 65 | // return { 66 | // myStart = modify(myStart) 67 | // return myStart 68 | // } 69 | 70 | // } 71 | 72 | // var next = createGen(start: 0) { 73 | // $0 + 2 74 | // } 75 | 76 | // print(next()) //2 77 | // print(next()) //4 78 | // print(next()) //6 79 | // print(next()) //8 80 | 81 | 82 | // var handlers:[()->Void] = [] 83 | // //трябва да добавим атрибута @escaping иначе няма да се компилира 84 | // func escapingClosure(f: @escaping ()->Void) { 85 | // print("escapingClosure - start") 86 | // // handlers.append(f) 87 | // f() 88 | // print("escapingClosure - end") 89 | // } 90 | 91 | // handlers.append { 92 | // print("test") 93 | // } 94 | 95 | // escapingClosure { 96 | // print("test 2") 97 | // } 98 | 99 | // //активираме всички функции 100 | // for f in handlers { 101 | // f() 102 | // } 103 | 104 | 105 | // func someFunctionWithEscapingClosure(closure: @escaping () -> Void) { 106 | // closure() 107 | // } 108 | 109 | // func someFunctionWithNonescapingClosure(closure: () -> Void) { 110 | // closure() 111 | // } 112 | 113 | // class SomeClass { 114 | // var x = 10 115 | // func doSomething() { 116 | // someFunctionWithEscapingClosure { self.x = 100 } 117 | // someFunctionWithNonescapingClosure { x = 200 } 118 | // } 119 | // } 120 | 121 | // var someObject = SomeClass() 122 | // someObject.doSomething() 123 | 124 | 125 | func funcAutoclosure(pred: @autoclosure @escaping () -> Bool) { 126 | print("Begin") 127 | if pred() { 128 | print("It's true") 129 | } else { 130 | print("It's NОТ true") 131 | } 132 | } 133 | 134 | // funcAutoclosure(pred: 11 > 12) // It's NОТ true 135 | // funcAutoclosure(pred: { () -> Bool in 136 | // print("Execute!") 137 | // return 2 > 1 138 | // }() 139 | // ) 140 | 141 | //допълнителен пример 142 | func funcAutoclosureComplex(pred: @autoclosure () -> ()) { 143 | print("body of \(#function)") 144 | } 145 | 146 | 147 | func funcAutoclosureComplexVoid(pred:()) { 148 | print("body of \(#function)") 149 | } 150 | 151 | // funcAutoclosureComplex(pred: print("the function is wrapped in a closure and it's never called.")) 152 | 153 | // funcAutoclosureComplexVoid(pred: print("the function print() is called")) 154 | //Това е изходът от горния код: 155 | //body of funcAutoclosureComplex(pred:) 156 | //the function print() is called 157 | //body of funcAutoclosureComplexVoid(pred:) 158 | -------------------------------------------------------------------------------- /samples/generics.swift: -------------------------------------------------------------------------------- 1 | //print("Hello Generics!") 2 | 3 | // func sum(_ a:Int, _ b: Int) -> Int { 4 | // return a + b 5 | // } 6 | 7 | // func sum(_ a:String, _ b: String) -> String { 8 | // return a + b 9 | // } 10 | 11 | protocol Sumable { 12 | static func + (left: Self, right:Self) -> Self 13 | } 14 | 15 | func sum(_ a:T, _ b: T) -> T { 16 | let h: T 17 | h = a + b 18 | return h 19 | } 20 | 21 | extension String: Sumable { 22 | } 23 | extension Int: Sumable { 24 | } 25 | 26 | struct Vector1D { 27 | var x = 10 28 | } 29 | 30 | extension Vector1D: Sumable { 31 | static func + (left: Vector1D, right:Vector1D) -> Vector1D { 32 | return Vector1D(x: left.x + right.x) 33 | } 34 | } 35 | 36 | let vX = Vector1D() 37 | let vY = Vector1D(x: 10) 38 | let sumV = sum(vX, vY) 39 | 40 | print("Sum (Int): \(sum(5, 5))") 41 | print("Sum (String): \(sum("5", "5"))") 42 | print("Sum (Vector1D): \(sumV.x)") 43 | 44 | 45 | protocol CollectionEquatable { 46 | associatedtype Element 47 | var count:Int { get } 48 | subscript (i:Int) -> Element {get} 49 | } 50 | 51 | extension Array : CollectionEquatable {} 52 | 53 | class Queue:CollectionEquatable { 54 | var items:[Item] // Array == [Item] 55 | private var _count: Int 56 | 57 | init() { 58 | items = [] 59 | _count = 0 60 | } 61 | 62 | func insert(item:Item) { 63 | items.append(item) 64 | _count += 1 65 | } 66 | 67 | func get() -> Item? { 68 | if items.count > 0 { 69 | _count -= 1 70 | return items.removeFirst() 71 | } 72 | 73 | return nil 74 | } 75 | 76 | subscript (i:Int) -> Item { 77 | return items[i] 78 | } 79 | 80 | var count:Int { 81 | // return items.count 82 | return _count 83 | } 84 | } 85 | 86 | // Да напишем шаблонна функция, която сравнява две колекции, които могат да бъдат сравнявани по следните правила: 87 | 88 | // OK: Двете колекции трябва да имплментират протокола CollectionEquatable 89 | // OK: Да имат еднакъв брой елементи 90 | // Всеки елемент да е еднакъв на съответния елемент от другата колекция 91 | 92 | func isEqual(first: U, second: T) -> Bool where T.Element == U.Element, T.Element:Equatable { 93 | if first.count == second.count { 94 | let c = first.count 95 | for i in 1..() 109 | queue.insert(item: 1) 110 | queue.insert(item: 2) 111 | queue.insert(item: 3) 112 | 113 | 114 | print(isEqual(first: arr, second: queue)) 115 | 116 | 117 | var queueStrings = Queue() 118 | queueStrings.insert(item: "1") 119 | queueStrings.insert(item: "2") 120 | queueStrings.insert(item: "3") 121 | // не е възможно да се изпълни, защото сравянваме Int със String 122 | // print(isEqual(first: arr, second: queueStrings)) 123 | --------------------------------------------------------------------------------