Избор на проект

  1. Тук е темата, където да си предложите проект. Очакваме всеки от вас да напише тук описание на проекта, който иска да направи. Може да ви предложим някакви промени, а може да го приемем as-is.

    Ако търсите идеи, вижте ей тази тема във форумите: https://fmi.rust-lang.bg/topics/58. Чувствайте се свободни да пуснете тук нещо в подобен "калибър" като размер и сложност. Ок е да си изберете и тема, която другарче вече е избрало, стига да измислите някаква друга вариация, и, разбира се, да си я правите самостоятелно.

    Крайния срок за избор на тема е 12ти януари. След това ще имаме една седмица да обсъждаме с вас темата ви, да ви предложим библиотеки, информация, посоки. Затова е важно да сте готови дотогава -- до края на семестъра, всичко да е изговорено и решено! В трите лекции преди този срок ще ви водим лекции за конкретни библиотеки или фреймуърци, които можете да използвате в проектите си.

  2. EVE safe path

    Погледнато по най-простия начин, приложението би било просто решение на проблем за намиране на най-кратък път върху динамично генериран граф, който сравнително често си обновява теглата.

    Малко по-просторно обяснение: EVE Online е online игра в която пилотираш космически кораби. Светът на EVE се състои от много системи свързани една с друга посредством stargates (вече се вижда къде се заформя графа). Често обаче на тези порти, стоят играчи който искат да те взривят. Идеята на приложението е да използва API на играта и да ти покаже възможно най-краткия и сигурен път по който можеш да минеш (без да се включва възможността за използване на Wormholes).

    Какво би включвал проекта:

    • Комуникация с външен API
    • (Може би) имплементация на server който постоянно да fetch-ва kill-ове от zKillboard API и да ги групира по системи и локации в системите.
    • Динамично изграждане на графа на базата на информация взета от API-я.
    • Динамично изчисляване на теглата, на базата на информацията от сървъра, и намиране на "най-кратък" път.
    • Спестяването на много загубени кораби и валута.

    Притеснения

    • От лекцията с data structures, добих малко страх от мисълта за реализирането на подобни структури на Rust, затова най-вероятно ще се опитам да използвам Petgraph

    Други подобни проекти

    Eve gatecamp check - Намира път между две системи, по начина по който играта намира, без да се интересува дали има ще срещнеш проблеми по пътя и само подчертава системите в които е имало убийства на stargate-овете.

    Смятам да използвам serde и hyper, за парсването на API-a.


    ПП:

    На пръв поглед всичко изглеждаше приятно и лесно, но след като вече 2 часа се ровя из различни документации разбирам, че проекта би бил наистина забавен и ще използва няколко webservice-а предоставени от други играчи и разработчиците:

    • Official API - за изграждане на графа
    • ZKillboard RedisQ - за fetch-ване на "почти" всички kill-ове който се случват в играта, в реално време
    • Fuzzworks Celestials API - за намиране на най-близкия статичен обект по x, y, z, systemID, така че да мога да преценя дали e stargate

    В крайна сметка стана малко по-обемно от колкото първоначално предполагах, но може би бих могъл да се справя.


    Надявам се че идеята ще ви хареса и съм отворен към всякакви предложения. Весели празници!

  3. @Николай Изглежда супер като идея. Единственото, което и мен ме притеснява е да не стане твърде обемен. Обмисли го на нива -- какво е най-простото, което можеш да направиш, което пак ще бъде работещ, "complete" проект? След това продължи на следващото ниво. Ключовото е на всяка стъпка да имаш работещо, демонстрируемо приложение, за да не се озовеш с 5-6 полуработещи неща, които не са смислени като цяло.

    Basically, каквото опционално можеш да отрежеш за първата версия, отрежи го. "Minimum Viable Product" and all.

    Що се отнася до графите, имай предвид, че ако изграждаш графа from scratch от това, което ти дават API call-овете, и после просто го анализираш, този граф може би няма да има нужда да се променя в движение. Което значи, че вероятно не биха ти трябвали RefCell-ове, за да бърникаш из node-овете. Напълно ок е да ползваш библиотека, разбира се, просто предупреждавам, че стига да обмислиш дизайна на структурата, може да не се окаже толкова сложна, колкото те притеснява.

  4. Мини Git

    Описание

    Програмата ще представлява конзолно приложение, което изпълнява команди подобни ина Git командите в по - опростен вариант. Ще работи с repository - та, които ще се определят по папка в root директорията на репозиторито (init), в която ще има файлове съдържащи информация за репозиторито .

    Команди

    init - създава папка с необходими файлове за репозиторито

    commit - създава snapshot на директорията в момента, като запазва дърво от хешове отговарящи на файловете в директорията, както и друга информация като време на създаване и описание.

    log - показва информация за всички commit и от даденото репозитори (описание и време на създаване)

    status - показва разликите от състоянието на репозиторито в момента и състоянието от последният commit (HEAD).

    checkout - преместване на даден commit и зареждане на състоянието на директорията каквато е била в този момент.

    revert - премахва всички нови промени, които са направени след последият commit

    cherry-pick - по commit и реалативен път на файл за репозиторито, ако не съществува такъв файл го добава, иначе го презаписва.

    Особености

    Програмата ще работи с файлово-базирана база данни. Като съдържанието на всеки файл ще се пази в HashMap, като хеша ще ебазиран на съдържанието му. Тоест файлове с еднакво съдържание няма да се копират.

    Ще се опитам при checkout - триенето и добавянето на нови файлове да бъде парализирано и да се изпълнява от няколко нишки, за по - добра ефективност.

  5. @Мартин Готина идея, харесва ми. Вероятно можеш да използваш serde за съхраняване на state-а на VCS-а, макар че сигурно ще трябва да си дефинираш собствен процес на сериализация. Бих те посъветвал да експериментираш и с архивиране, gzip, bzip, нещо, което да компресира съдържанията на файловете, за да не се окажеш с дебела папка с история. Текста се компресира супер, и сигурно можеш да намериш пакети, които да ти дават компресията наготово.

    Един пакет, който може да ти е полезен, е walkdir, който е създаден като част от ripgrep tool-а. Ако разгледаш ripgrep, там можеш да намериш и паралелно обработване на файлове, което можеш да използваш за вдъхновение.

  6. VST Plugin

    Проектът ще представлява VST instrument plugin - (mono) синтезатор за различни аудио вълни. За целта ще използвам vst crate-a. Не съм се занимавал с audio програмиране преди, но ми е интересно и rust ми изглежда като подходящ език за тези цели.

    Features

    Смятам да имплементирам основните аудио вълни:

    • sine
    • square
    • sawtooth
    • triangle
    • някакви по-fancy вълни (евентуално)

    Освен това plugin-а ще разпознава нотите, които получава от VST Host-a, който го ползва (вълните ще имат различен pitch спрямо input-a).
    Някакви контроли за output-a, например:

    • volume
    • pitch
    • pan

    (В общия случай, ако плъгина е host-нат в DAW контролитете идват от него, но би било добре да ги добавя.)

    Ако остане време и не съм се прострелял в крака ще се опитам да добавя възможност за възпроизвеждане на повече от една нота едновременно (ще направя синтезатора полифоничен).

  7. @Емилиан Интересна идея за проект. Единственото, което ме притеснява е, че crate-а изглежда все още доста нестабилен и може да удариш на бъгове и/или на липсваща функционалност. Така като гледам, все пак си има някакви работещи плъгини в examples директорията, така че сигурно ще си ок, но е добре да огледаш документацията за какво има и какво му липсва, да не те изненада неприятно.

    Ако все още не си, опитай да имплементираш нещо супер, супер просто, колкото да видиш, че се компилира и работи както очакваш, пък през сесията можеш да започнеш истинския проект. Ако откриеш, че интеграцията с инструментите на crate-а е твърде тежка, може да решиш да pivot-неш темата си към нещо друго. Just in case, нали :).

  8. Rim

    Проектът е замислен като конзолен текстов редактор с много оригинално име. Вдъхновението ще е Vim, като ще се опитам да е по-малко интуитивен за начинаещи :D.

    Features

    Целта е да се докарат основните функции на един такъв редактор ( според мен ) - copy/paste функционалност, писане/четене от файлове, възможност за скачане по редове и колони лесно, undo/redo, някакъв status line с configurable информация, syntax highlighting за различни езици ( първо за Rust, разбира се ), възможност за изпълнение и интеграция с външни команди ( от терминала примерно ) като formatter-и например. Wild idea - ако успея искам да създам и някакъв прост configuration език ( или ако не остане време за език просто един config.json файл и сериализация ), който да управлява различни аспекти от редактора - например дали да са включени line numbers или не ( първото нещо, което научих как се прави във Vim :D ).

    Libraries

    Библиотеки, които мисля да използвам:

    • Termion - за raw mode на терминала и за манипулацията му in general
    • Ropey - за текстов буфер
    • Clipboard - за интеграция с clipboard-a на операционната система
    • Евентуално някоя parser combinator библиотека за config езика

    P.S.

    UI-а ще е сравнително прост, тъй като някакъв по-читав сигурно би ми отнел време колкото всичко останало взето заедно :)

  9. Растеризатор на truetype/opentype* шрифтове.

    Тъй като сега вече е ясно, че нямам достатъчно време да напиша оригинално планирания си проект (библиотека за gui, все пак ще дам детайли по долу за пълнота) искам да правя за проект една минимална самостоятелно работеща част от него, а именно това което е в заглавието.

    Какво точно ще представлява проекта?

    Всеки символ в един такъв шрифт се представя, като поредица от насочени и затворени съставни криви на Безие. Посоката им определя дали площтта вътре в тях е "запълнена" или "празна" (Най-вътрешните криви имат финалната дума за това каква да е площта вътре. Ако си представим един голям кръг насочен така, че площтта вътре да е черна и вътре по малък кръг с противоположна посока, ще получим буквата "О").

    Целта на библиотеката е да отваря един такъв .ttf файл и по unicode codepoint на някой символ да може да връща растерно (като поредица от пиксели) описание на този символ в избраната от потребителя резолюция (или "височина" на шрифта в пиксели).

    Как точно работи проекта?

    След като отворим дадения файл и парснем нужните данни според спецификацията е определим, кой пиксел от финалното изображение попада между "запълващ" контур. Най-хамалския начин това да се направи е да се провери всеки пискел със всеки компонент на контура и да се оцвети в съответния цвят, но разбира се това би било потресаващо бавно (и потресаващо грозно) и би създало aliasing (освен ако не използваме supersampling, тоест растеризиране в много висока резолюция и после смаляване, което обаче е прекалено скъпо за беден човек като мен :cry:).

    Има ли не малоумен начин за проверяване на оцветеност на точка и можем ли да намерим по-бюджетно щадящ начин за anti-aliasing от supersampling, като едновременно с това не е толкова сложен, че да не мога или да нямам време да го имплементирам? Ами за сега спекулирам, че следното би свършило работа:

    • Взимайки контурите ги превръщаме в поредиа от отсечки (ръбове), разделяйки кривите на Безие, използвайки частен случай на алгоритъма на De Casteljau, докато не надхвърлят някаква локална мярка за плоскост за съответната резолюция (тоест докато станат практически неразличими от прави) и след това заменяйки ги с отсечки.
    • Сега можем да апроксимираме лицето на оцветената площ която се съдържа във всеки пиксел (тук на него гледаме като на малко квадратче). Това може да се прави като съответно прибавяме площа на трапецоидите индуцирани от ръбовете, като спуснем хоризонтални прави от върховете на ръба до върховете на проекцията му по вертикалната координата (ръбовете с една от посоките ще са с положително лице (запълващи) а от другата с отрицателно). Накрая в зависимост от това каква част от лицето на пиксела е запълнено можем да изберем цвят между бялото и черното, по този начин използвайки естествен anti-aliasing по контурите. На пръв поглед пак изглежда, че имаме да вършим работа за всеки ръб и всеки пиксел, но с някой хитрости това може да се избегне:
      • Сортираме ръбовете по най-горен връх.
      • Итерирайки по редовете на растерната повърхност, пазим един масив от двойки числа (или два масива, но по начина ползваме един масив може да е по приятелски настроен към кеша, защото близките по индекс елементи от двата масива достъпваме в близко време) с големината на реда и масив от "активни" ръбове. Първото число в масива показва закритата площ в съответния пиксел, подмасива индуциран от вторите числа си го представяме като комулативна сума на площи закриващи всеки писек, т.е второто число казва, че всички пиксели нататък им се добавя тази площ, по този начин не трябва да обхождаме целия масив за всеки ръб а го правим само веднъж накрая преди да начертаем съответния ред от картинката. Масива от "активни ръбове" съдържа ръбовете, които имат отношение към съответния ред, т.е които закриват някаква площ в него
      • На всяка итерация премахваме ненужните ръбове от активния масив (тези на които най-долния им връх е над горната граница на текущия ред).
      • На всяка итерация "активираме" последователно ръбовете от нашия сортиран масив с ръбове, чиито най-горен връх започва под горната граница на текущия ред.
      • Смятаме лицата за всички активни в конкретната итерация ръбове.
      • Оцветяваме съответния ред според нашия масив с лицата.
      • Подготвяме оставащите активни ръбове за следващата стъпка. Тук се съдържат детайли свързани с смятането на лицата, което нарочно не илюстрирам защото има много технически детайли. Идеята е, че за да може по тънко да намираме разни пресичания на ръбовете с пиксели ги представяме в slope-intercept форма, но обратната функция (защото се оказва по удобно), като пазим допълнителна информация от къде почват и свършват тъй като са отсечки, а не прави и се оказва одобно да знаем къде всеки път пресичат горната стена на конкретния ред, което трябва да опресняваме.

    Какви външни библиотеки ще използвам?

    Нищо освен Ръст и стандартната библиотека на езика.

    До къде съм стигнал?

    Имам сравнително, количество код но тъй като все още има есенциална неимплементирана функционалност на растеризатора, както и разни бъгове не се чувствам самоуверен да покажа код.

    (Опционално) История на провалената ми оригинална идея.

    Оригиналната ми идея беше да напиша библиотека за графичен интерфейс. Типично тези библиотеки използват два вида API дизайна, immediate mode и retained mode.

    Най-общо казано, retained mode библиотеките (такива, като Qt и GTK+), поддържат интерфейс за деклариране на някакви widget-и, заедно с callback - и, които да се ипълняват при настъпването на някакво събитие свързано с дадения widget, след това програмиста дава контрола на програмата (или поне на една нишка от нея) на библиотеката и тя почва да следи за събития, чертае интерфейса и от време на време връща контрола на нишката на нашата програма като викне някой callback. Един чест недостатък на такива библиотеки е, че са оптимизирани за почти статичен интерфейс и не са подходящи за високоскоросни анимации или събития, които драстично променят интерфейса. Също така заради самия им API дизайн, често се пише екстремно количество boilerplate дори за тривиален код, също така не взаимодействат много чисто с други неща които биха искали да вземат контрол над дадена нишка (това обикновенно може да се получи ако искаме да рендърираме нещо по специално освен самия интерфейс, което и то обработва някакви асинхронни събития, прави някакви симулации и се опитва да чертае след това).

    За immediate mode библиотеките (такива като nuclear и dear-imgui ) специфичното е, че те не пазят състояние и не взимат постоянен контрол над нишката. Създаването на даден widget в конкретния кадър и проверката дали в текущия момент, в който се чертае кадарът е било настъпило даденото събитие свързано с widget-а обикновенно се извършва с едно извикване (разбира се всъщност повечето такива библиотеки кешират графичната репрезентация на всеки widget за текущия кадър и го изчертават (или дават на потребителя да го изчертае) накрая, но важното е че от гледна точка на създаването на widget-и няма никакво състояние). Тези библиотеки са доста удобни за силно динамичен интерфейс и за някой приложения може да са много приятни за работа но страдат и от сериозни недостатъци. Например тъй като няма никакво състояние и библиотеката предварително не знае какво трябва да изчертае за дадения кадър, не може да се специфицира предварително layout-a чрез някакъв markup language (каквото много от retained mode библиотеките поддържат) и също така не можем да говорим релативно за widget-ите поне в общия случай. Също така тъй като на всеки кадър целия UI се изчертава наново, въпреки че производителността може да е сравнително добра, ако се използва GPU (дори по-добра от някои от по-класическите retained mode библиотеки, тъй като често те могат да използват архаични технологии и да не се възползват от графичния процесор достатъчно) в крайна сметка се върши огромно количество излишна работа (което е излишен разход на енергия при мобилните устройства, за които издръжливостта на батерията е много важна). Също така за да са responsive се изисква да вървят с голям брой кадри в секунда.

    И сега в крайна сметка моята идея беше да направя експеримент, комбинирайки аспекти и от двете парадигми. Мислех си за нещо, което по интерфейс доста наподобява immediate mode, но вътрешно е повече като retained и пази сравнително много информация.

    Основните проблеми, които са свързани с направата на това нещо са освен, че е трудоемко само по себе си то би зависело от доста други неща. Например една такава библиотека трябва да може да работи с графичната среда на съответната система, както и да прима вход мишка/клавиатура и накрая да има някакъв начин да изобразява нещата (най-добре би било да разчитаме на GPU, вместо на старинни неща като Win32 GDI и примитивите за чертане на X, тоест ни трябва нещо като Vulkan, Direct3D или OpenGL).

    Тъй като исках библиотеката да е без външни зависимости, то би трябвало да имам някакъв начин да мога да използвам най-различни системни API-та от ръст. Това обаче не е толкова тривиално по някой причини. Ако исках да ползвам тези апита от C++ да речем, просто бих добавил съответните системни хедъри в сорса за да имам сигнатурите на функциите от апито и след това да свържа с съответната библиотека. Ако искам обаче да направя същото от ръст, чрез FFI, няма как да добавя съответните хедъри и трябва ръчно да наглася сигнатурите, това е свързано с ръчно деклариране на структури понякога имащи стотици полета, т.е имплементация на огромна част от самите хедъри в ръст, което е неприятно. Един възможен workaround на този проблем е като направя тънък wrapper на съответните библиотеки чрез C++, и опростя интерфейса (като например вместо тези огромни структури, функциите ми приемат void* към съответните структури, които C++ си заделя и трие при съответните извиквания и си ги каства без Ръст да знае кво се случва от вътре) и след това го експортна в ръст с FFI. Това пък изисква писане на много C++ код в Rust проект...

    В крайна сметка по едно време през ваканцията реших да потърся някакви компромисни варианти и все пак да пробвам да ползвам някои готови библиотеки.

    Например една добра библиотека за линукската част, която ще ми позволи да създавам прозорци и да следя за инпът докато той е фокусиран е x11 , която е гол binding на xlib, всичко е директно експортнато няма никакво рапване. Вътре в ръст човек може да си я рапне както му харесва. Самия xlib е тънка библиотека, която комуникира с X сървъра. Практически всички приложения ползват нея или XCB, никой не говори с X директно.

    За бекенда за чертаене смятах да ползвам vulkan (защото не харесвам OpenGL а Direct3D е Windows само). Една библиотека която видях е ash тя е тънък рапър, не е директен байндинг. Има някой ънсейф неща но като цяло са спазвани Ръст конвенциите и апито е попроменено. Например в стандартното C vulkan API, фунцкиите връщат код за грешка а резултата от тях го връщат в някакъв аргумент подаден като пойнтър. Също така много функции поемат като аргумент хендъли към разни неща отговарящи за някакъв контекст в апито. В ash съответно се възползват от методи и от Result, което редуцира броя на аргументите, които се подават на някой функции. Също така се ползват, конвенциите на именоване на ръст, т.е vkGetPhysicalDeviceQueueFamilyProperties се превръща в метод get_physical_device_queue_family_properties в ash. Това което не ми харесва обаче е че тази библиотека има много външни зависимости...

    Като цяло един проблем (от гледна точка на направата на проект за кратко време) с vulkan е, че не е много абстрактна. Например за създаване на тривиална "hello triangle" чрез vulkan в C++, трябват 1k+ реда код. Отделно за нетривиална програма, човек сам трябва да си имплементира алокатор за паметта на GPU-то, защото броя на алокациите през vulkan са силно лимитирани от драйвера ( нещо от сорта на 1k алокации макс дори на висок клас карти). Това, което човек прави е че обикновенно заделя големи парчета памет през апито и в неговата програма си ги разпределя за съответните буфери, които създава в графичната памет. Общо взето е много занимавка.

    През ваканцията пробвах да направя някакви неща в тази насока, но бързо разбрах, че началната ми идея няма как да се реализира, взимайки в предвид други проекти, които трябва да правя през семестъра. За това се надявам да одобрите горния проект, който съм предложил и изглежда по реалистичен.



    * Реално това, което формално се специфицира като truetype, opentype е различно от това, което хората имат в предвид под тези термини или това, което се съдържа в .otf .ttf файловете. Всъщност това, което хората най-често имат в предвид под ttf е true-type contained font. Това са различни видове шрифтове с приликата, че контейнера им спазва оригиналната ttf спецификация. Контурите вътре може да са най-различни ttf outlines, cff outlines, postscript outlines etc... (самите контури са математически различни и са пакетирани по заличен начин)... В .otf файловете обикновенно се слагат шрифтове с cff outlines (не винаги по някога са си стандартни ttf), а в .ttf най-често има ttf outlines, но може да има и всичко друго. В крайна сметка моята библиотека за сега работи с ttf outlines само. Tова всъщност покрива може би най-голяма част от често използваните шрифтове за това избрах да поддържам него вместо другите на първо време.

  10. @Георги Вероятно не е учудващо, че ми харесва идеята :). Ако случайно имаш достъп до Destroy All Software, тук има чудесен 30-минутен screencast с писане на много, много прост редактор: https://www.destroyallsoftware.com/screencasts/catalog/text-editor-from-scratch. Ще се опитам да покажа rust имплементация на кода в скрийнкаста, но не знам дали ще го вмъкнем до края на семестъра.

    Съветвам те да внимаваш със scope-а на опционалните неща, за които си мислиш. Syntax highlighting е нещо, което според мен подценяваш. Интеграция с външни команди или конфигурация мисля, че биха били по-лесни за подкарване. Ти си прецени, разбира се, важното според мен е да имаш нещо работещо на всяка фаза и да добавяш функционалности само една по една.

    @Михаил De Casteljau едно време съм имплементирал за рендериране на криви в opengl прозорец, звучи ми като нещо смислено за проект. Сигурно ще ти е по-трудничко с добавянето на оцветените площи, но изглежда имаш идея как ще стане. Все пак, ако удариш на някой практически проблем с оцветяването, само растеризация на кривите би била ок за мен, стига да е пакетирана смислено в някакъв usable command-line app с ясен input и output.

    Проекта е доста algorithm-heavy, така че бъди готов да обясняваш компонентите стъпка по стъпка, като за нас, които не сме запознати :). Таргетирай яснота повече, отколкото обем на обясненията.

  11. Console Farkle Dice Game

    Farkle е сравнително популярна игра със зарчета, на която съм отделил много игрово време като малък, та за това реших и проекта ми да е един от вариантите на играта.

    Как се играе?

    Farkle се играе от двама или повече играчи, където всеки играч следва своя ред и хвърля 6 на брой зарчета наведнъж. След всяко хвърляне едно или повече зарчета трябва да се "приберат" и се смятат точките, които те носят по стандартна схема (https://en.wikipedia.org/wiki/Farkle#Standard_scoring). След това играча трябва да реши дали да си прибави спечелените до сега точки и да даде реда на следващия играч, или да хвърля отново останалите му зарове. Ако играча е "прибрал" и шестте зара, той има право да хвърля отново всичките зарове. Ако никое от заровете не дава точки по схемата, играча има "farkle" и всичките точки спечелени през неговия ред се губят и реда се дава на следващия играч. Победител е този, който пръв достигне 10000 точки.

    Какво включва проекта?

    Проектът ми е конзолно приложение, което интерпретира горните правила. Включва начално меню, където може да се инициализира нова игра, да се покажат правилата, или да се излезе. Инициализирането на нова игра става като се въведе броя на играчите и техните имена. След успешно въвеждане на данните играта започва, където на всеки ред на всеки играч има инструкции какво трябва да направи дадения играч. При достигане на нужния брой точки от някой от играчите, конзолата извежда подобаващо съобщение.

    Реших да го направя конзолно, тъй като нямам достатъчно свободно време да се ровя за информация за GUI, а и нямам много опит с GUI разработка, въпреки че ще изглежда доста по-яко.

  12. @Стефан дори и терминален UI може да се направи приятен, няма нужда от fancy GUI работи :). Примерно, би могъл да рендерираш 6тте зарчета с unicode: ⚀ ⚁ ⚂ ⚃ ⚄ ⚅ (https://emojipedia.org/die-face-6/). Би могъл да направиш "хвърлянето" на зарчета като всеки един от 6тте цикли между произволни стойности примерно половин секунда, и накрая показва крайните стойности. Даже може да пуснеш и звук докато ги търкаляш :) (било то с rodio или просто с shell-out-ване).

    Разбира се, не знам дали unicode-а ще се рендерира добре в терминал (зависи от шрифтове и размерите им), така че все пак може да не е много удобно така. Просто давам интересни идеи, които може да обмислиш. Ако не unicode, може да рендерираш ascii-art зарове например:

    -----   -----   -----   -----   -----   ----- 
    |   |   |o  |   |o  |   |o o|   |o o|   |o o| 
    | o |   |   |   | o |   |   |   | o |   |o o| 
    |   |   |  o|   |  o|   |o o|   |o o|   |o o| 
    -----   -----   -----   -----   -----   ----- 
    

    Basically, постарай се user interface-а наистина да е удобен, дори да е конзолен. Помисли си за това как ще показваш точките, така че потребителите ясно да виждат къде са в класацията. Използвай конзолни цветове за изясняване на някакви неща. Покажи ясен интерфейс за избор на потребителя, в зависимост от това какво му се падне. Още звуци и големи съобщения за farkle, hot dice...

    Опционално, би могъл да дадеш опция и за AI опонент, или няколко такива. Примерно, може да има AI, който обича да рискува, и такъв, който е по-консервативен. Един random, etc. Може да сложиш опция за "бърза игра", без анимации и такива неща, между AI-та, и да видиш коя стратегия бие най-често :). Но това може би ще е прекалено много работа. Просто пускам идеи. Харесай си няколко feature-а, които искаш да имплементираш, и ги прави един по един.

  13. quiz-maker

    Идеята ми е да направя crate, който да съхранява и управлява въпроси за тестове със затворени отговори. Идеята е да може да се генерират множество варианти на базата на съществуващите въпроси. Тестовете също така ще могат да се export-нат в различни формати.

    Features

    Идеята е функционалностите да бъдат достъпни, както през програмен интерфейс, така и през конзолен (Rubygems предоставят това (adding-an-executable), ще потърся как може да стане нещо подобно с cargo).

    • Управление на категории (CRUD операции). Всеки въпрос ще се отнася към дадена категория.
    • Управление на въпроси (CRUD операции). Поддържане на въпроси с повече от един верен отговор, определяне на брой точки при верен отговор и т.н.
    • Търсене на въпроси по категории, описание и други параметри. Филтриране, сортиране.
    • Import-ване на въпроси от YAML/JSON формат.
    • Управление на repository-та. Repo-то ще бъде абстракция за съхранение на категории. Може да бъде на файлова система (в YAML/JSON формат) или в база данни.
    • Генериране на тест (в PDF/markdown формат). За всеки вариант въпросите и отговорите ще се разбъркват.
    • Генериране на "ключ" с верните отговори към всеки вариант.
    • Форматиране на въпросите, както и отговорите - bold, italic, блокове за код и картинки.

    Libraries

    Библиотеки, които най-вероятно ще ползвам на този етап:

  14. HTML to RSS reverse proxy

    Освновата ще е просто reverse proxy, което слуша за HTTP заявки от клиенти и при зададени URL и regex-и връща RSS feed от съдържанието на подадения URL. Ще имплементирам и някаква част от следните допълнителни функционалности:

    • възможност за подаване на xPath или CSS selector-и вместо regex
    • възможност за избиране дали output-а да бъде RSS, Atom, JSON и каквото още се сетя
    • кеширане на резултати, може би на 2 нива (HTML съдържание и RSS резултати)
    • rate limiting (т.е. дадено IP може да прави най-много X заявки за N минути)
    • възможност за филтриране и трансформиране на резултатите чрез определени параметри
    • configurable ограничаване на броя на връщани резултати, timeouts, максимална поддържана големина на връщания HTML и т.н.
    • възможност authentication (пр. с някакви tokens) и съответно за премахване или намаляване на част от възможните ограничения за authenticated users
    • поддръжка на HTTPS от rust сървъра
    • каквото още ми хрумне (отворен съм към предложения)
  15. Word Search Game

    Идеята на играта е да намериш колкото се може повече думи от дадената поредица от букви. Думите се търсят по колони, редове и диагонали от горе надолу и от долу нагоре, от ляво надясно и от дясно наляво. В началото е даден броят на всички думи, които можеш да намериш, и при всяка открита дума този брой се намалява, а думата се изписва отстрани. Имаш също и време, за което можеш да търсиш думите, така че като изтече, играта приключва и се извежда колко общо думи си открил. За реализирането на играта ще използвам библиотеката ggez.

  16. @Исмаил Звучи добре. Обикновено нещо такова би било webapp, но е ок да го направиш command-line, стига да има смислен интерфейс. Мисля, че ще ти е по-трудно като command-line app просто заради липсата на много инструменти за форми, рендериране и т.н., но пробвай. Ако не друго, предполагам, че output-а реално ще е генерирани файлове, а input-а ще е импортнати такива.

    Относно executable/library: Винаги можеш да имаш и lib.rs, и main.rs -- първото ще се extern crate-ва от библиотеки, а второто ще се използва за executable, който ще се инсталира в ~/.cargo/bin при извикване на cargo install и ще може да се вика.

    @Недялко Одобрявам. Говорихме за проекта, така че нямам какво друго да добавя.

    @Биляна Смислена идея. На първо четене, чудя се какво ще стане, ако някоя поредица от букви случайно генерират дума, която не е позната, но да кажем, че това е някакъв детайл, който можеш да измислиш. Погрижи се да направиш сравнително изпипан интерфейс -- някъде да се показва текущия резултат, времето, което ти остава. Погрижи се и да има достатъчно думи, че да има вариация между произволно избраните :). Няколко бонус неща, за които може да си помислиш:

    • Различни категории думи? Програмистки термини, най-честите N думи в английския или българския език, храна, градове...
    • Ниво на трудност? Може на края на играта да "качиш ниво" и да получиш по-голям grid, ако си познал всичките.
    • Питане на потребителя за име и запазване на резултата? Scoreboard?
    • Главно меню с "нова игра", "настройки", и т.н.?
  17. Search engine

    Основата ще е индексация на текст и интерактивно да се изпълняват дадени заявки. Още се колебая дали да е върху текст или по индентификатори в source code или json(засега съм по-скоро за първото).

    Допълнителни фукционалности(надявам се да имам време за колкото може повече о тях):

    • Persist-ване на индекса във файл, и зареждане upon boot: JSON, YAML, ctags-compatible tags, gzip-нати CSV-та...
    • Използане на по кеш-friendly структура за store-ване на индекса.
    • Подръжка на по-сложни заявки за търсене т.e. && и ||, може и с regex-и и да изполвам някоя готова библиотека за тях.
  18. Интерпретатор на подмножество на Prolog

    Интерпретаторът ще бъде за подмножество на SWI-Prolog. Езикът ще поддържа основно Хорнови клаузи (Horn clauses) (впоследствие мога да добавя числа, списъци, оператор =, cut и други благинки).

    Синтаксис

    Термове

    • константа - низ от числа и букви, започващ с малка буква
    • променлива - низ от числа и букви, започващ с главна буква
    • f(t1, ..., tn), където f е константа, а t1, ..., tn са термове.

    Допускания

    • факт - терм, завършващ на точка (например, term.)
    • цел - goal :- subgoal1, ..., subgoalN., където goal, subgoal1, ..., subgoalN са термове.

    Заявки

    Заявката ще има вида ?- term., където term е терм.

    Примерни програми

    Аритметика

    % Ще представяме числата по следния начин:
    % z - 0
    % succ(N) - N + 1
    
    % Събиране: plus(K, M, N) <=> K + M = N
    % 0 + N = N
    plus(z, N, N).
    
    plus(succ(K), M, succ(N)) :- plus(K, M, N).
    
    % Изваждане: minus(K, M, N) <=> K - M = N
    minus(K, M, N) :- plus(M, N, K).
    
    % Умножение: times(K, M, N) <=> K * M = N
    % 0 * N = 0
    times(z, N, z).
    
    % (K + 1) * M = K * M + M
    times(succ(K), M, N) :- times(K, M, P), plus(P, M, N).
    
    % Примерни заявки
    
    ?- times(succ(succ(succ(z))), succ(succ(z)), N).
    % N = succ(succ(succ(succ(succ(succ(z))))))
    % false.
    
    ?- plus(X, Y, succ(succ(succ(z)))).
    % X = z, Y = succ(succ(succ(z)))
    % X = succ(z), Y = succ(succ(z))
    % X = succ(succ(z)), Y = succ(z)
    % X = succ(succ(succ(z))), Y = z
    % false.
    

    Списъци

    % Ще представяме списъците по следния начин:
    % nil - празният списък
    % list(Head, Tail) - списък с глава Head и опашка Tail
    
    % конструиране на списък с глава H и опашка T
    cons(H, T, list(H, T)).
    
    head(H, list(H, _)).
    
    tail(T, list(_, T)).
    
    empty(e).
    
    % last(X, L) <=> X е последният елемент на списъка L
    last(X, list(X, e)).
    last(X, list(_, T)) :- last(X, T).
    
    % member(X, L) <=> X е елемент на списъка L
    member(X, list(X, _)).
    member(X, list(_, T)) :- member(X, T).
    
    % append(L1, L2, L) <=> L е конкатенацията на списъците L1 и L2
    append(e, L, L).
    append(list(H, T), L, list(H, TL)) :- append(T, L, TL).
    
  19. @Димитър Супер, звучи ми като готин проект. Ще си помисля някоя простичка програма, с която да го изтествам :)

    @Биляна Звучи добре. Помисли си обаче какви функционалности искаш да включиш. Текстово приключение може да се направи доста простичко с "иди нагоре в стая А, иди наляво в стая Б", добре ще е да вкараш и нещо по-така. Примерно:

    • Инвентория? Може да събираш мечове, ключове, храна, вода. Странни предмети, които като се комбинират, да решават някакви пъзели. (Твърде високо на някой рафт се намира ключа за следващата стая? Може би трябва да потърсиш стая с метла, която да можеш да вземеш и да се върнеш)
    • Битки с противници? Може тук-таме да изскочи някое grue и да имаш походова битка с него. Ако имаш инвентория, може да се екипираш. Или може да направиш като undertale и да търсиш начин мирно да решиш конфликта :)
    • Зареждане на карта от файл? Картата може спокойно да е един json със стаи, и за всяка стая да има описано коя е наляво, коя е надясно, какви предмети има, и т.н. Това би било доста удобно и за дебъгване, вероятно, така че така или иначе бих го препоръчал.
    • Произволно генериране на стаи? Това би променило играта доста, понеже значи, че по-трудно ще измислиш "тук има ключ, тук има врата". Но пък някаква произволност на противници или на предмети може да вдигне интереса.
    • Състояние на играча? Глад, жажда, умореност? Вместо "стаи", може областите да са дълбоко в някоя гора примерно, и да отнема часове обикаляне. И да трябва да търсиш вода и храна.

    Избери си, да речем, поне две от списъка, или пък си измисли 2-3 свои интересни добавки.

  20. Typical: Декларативна система за писане на типови системи

    От известно време имам една идея за създаване на прост framework за експериментиране с language development, който да е базиран на максимална декларативност и модулизираност.

    Целта ми е повечето пасове да може да се описват декларативно и да са swappable (с възможност за handler-и написани като код).

    Това вече е доста разработена територия откъм parsing: grammars, и вече съм имплементирал и такъв универсален dsl за генератори към различни езици. (Garbage collector-ите най-вероятно могат да са предварително написани с възможност за избор между тях).

    Основното оставащо парче от пъзела е type system, затова ще пробвам да направя нещо функциониращо в този проект. Още не съм избрал точния си план (досега съм пробвал с минимален pattern matching dsl: https://github.com/alehander42/roswell/blob/master/typechecker.nim#L99 и с директно прилагане на пролог: http://alehander42.me/prolog_type_systems), но ще помисля над него в следващите дни. Възможно е и да е по-близък до математическия запис на typing rules.

    Какво би включвал проекта

    DSL за дефиниране на типови системи с възможност за fallback към собствени функции Този DSL може да бъде базиран на macros или да е отделен миниезик, парсван от мой модул.

    Миниезик, който демонстрира как използва различни типови системи за себе си.

  21. @Александър Уф, малко късно изникваш, изненадващо. Но ок, имплементирай си проекта и ела на 17ти. Малко ми е абстрактен, така че се подготви с някакви добри примери.

  22. Ето ранен пример:

    if(Bool, T, T) =>               Void
    for(T, Sequence[T], Void) =>    Void
    decl(_, name, T) =>
      undefined(%scope, name),
      update(%scope, name, T),
      Void
    assign(name, T) =>
      unify(%scope[name], T),
      Void
    list(T..) =>                    List[T]
    dict(Pair[K, V]..) =>           Dict[K, V]
    pair(K, V) =>                   Pair[K, V]
    call(Function[FArgs, F], Args*) =>
      unify_all(FArgs, Args),
      F
    attr(Obj[field: F, _], field) =>
      F
    func(name, Args*, F, Void) =>
      update(%scope, name, Function[Args, F])
      %scope[name]
    label(name) =>                  %scope[name]
    
  23. Init система с поддръжка за управление на услуги (services)

    Идеята е да се напише програма, която да действа като процеса с PID 1 под Unix-базирани ОС (т.е. първият процес, който се стартира в системата, и който съществува до изключването ѝ). Освен това тя трябва да поддържа извършването на различни видове действия в дадени моменти по време на изпълнение на системата (например при стартирането или изключването ѝ), описани в т. нар. елементи (units).

    Мисля да използвам небезизвестната и донякъде (ahem, ahem) оспорвана система systemd като вдъхновение за дизайна, макар че не смятам да правя нейна реимплементация (т.е. не давам гаранция за съвместимост със systemd). Просто реших да почерпя някои идеи оттам.

    Основни възможности

    Списъкът не е изчерпателен. Освен това не гарантирам, че ще успея да имплементирам всичко от него.

    • Стартиране и спиране на програми (т. нар. услуги)
    • Събиране на логове от стартираните програми
    • Разрешаване и забраняване на услуги
    • Дефиниране на зависимости между услугите (т.е. коя от тях трябва да се стартира преди някоя друга)
    • Паралелно изпълнение на услуги
    • Стартиране на услуги при получаване на данни по мрежов сокет
    • Монтиране и демонтиране на файлови системи
    • Програми за контрол на базови системни настройки (име на хост, дата, локал, регистрации на потребители, различни мрежови настройки и т.н.)

    Елементи

    Това са базовите обекти, които се управляват от init системата. Чрез тях се представя по стандартизиран начин конкретен ресурс в системата.

    Основната идея на елементите е системата да е модулярна (т.е. всеки ресурс да може лесно да се раздели на отделни компоненти, които да се управляват от различни елементи, според различните аспекти на ресурса). Това улеснява работата с нея, тъй като позволява лесно разрешаване и забраняване на отделни ресурси, както и добавяне на нови такива, без да се променят базовите дефиниции.

    Елемент не е същото като услуга (всъщност услугите са вид елементи). Той може да представлява много повече неща: чрез него може да се направи абстракция както на услуги, така и на мрежови ресурси, устройства, файлови системи и т.н.

    Видове елементи

    Списъкът е примерен (т.е. може да се промени впоследствие). Пак не гарантирам, че ще успея да имплементирам всичко от него.

    • Услуга (service): елемент, който описва как се стартира/спира определена програма (например като демон).
    • Сокет (socket): елемент, който описва мрежов сокет, по който работи дадена услуга. Идеята е тя да се стартира чак когато някой клиент се върже по сокета.
    • Устройство (device)
    • Mount: елемент, който описва как се монтира определена файлова система.
    • Automount: mount, който се задейства автоматично.
    • Swap
    • Цел (target): метаелемент, който не описва какъвто и да е ресурс сам по себе си, но гарантира, че някакви други елементи са изпълнени, зависейки от тях.
    • Път (path)
    • Таймер (timer): елемент, който позволява изпълнението на дадено действие през определен интервал от време.
    • Моментна снимка (snapshot): елемент, който представлява определено предишно състояние на системата, до което тя може да се възстанови.
    • Slice
    • Scope
  24. @Радослав Супер, помисли си само как ще демонстрираш системата. Ако ще я пускаш като процес 1, сигурно няма да е много удобно да си рестартираш компютъра за целта, а и ако вземе да крашне, ще е трудничко :). Може би в някаква виртуалка?

    Also, струва ми се почти задължително да имаш и някакъв стабилен logging във файл, за да дебъгваш проблеми, това би било и нещо, което да помогне за демото -- ясната поредица от събития, които са се случили.

  25. @Андрей Ами да, мисля да го тествам във виртуална машина. Очевидно няма как да стане на development машината ;)

    Освен това задължително ще има някакъв вид логване. Вече за случаите, в които логовете няма да могат да помогнат, обмислям да ползвам remote debugging (gdb има протокол за това). Ще проуча допълнително как точно се случват нещата при такъв вид дебъгване.

  26. Image processing

    Заглавието си говори достатъчно добре. Функционалностите до момента, които съм избра са: edge detection, филтри(не се знае какви точно), image transformations, свиване/разпъване на изображението.(Приемам и други предложения :)) )

  27. Проект

    Tool за export/преобразуване/import(и не само) на данни от Influxdb.

    Реален проблем, който срещнах: Искам да прехвърля част от данните от staging в production с минимум усилия и логване на различи сървъри. Едно решение беше backup/restore. Restore в Influxdb изисква демона да бъде спрян. Ако базата е в production, то за да не се налага да правим това една идея е да използваме line протокола. Проблем се оказва това, че данните върнати при HTTP заявка не са във формат, който може да бъде изпратен чрез HTTP заявка, за да бъдат записани. Идеята на проекта е да автоматизира тази работа. Допълнителна функционалност, която може да имплементирам е import на данни от различни формати: csv, xls, json, etc. За да не се претоварва базата - throttling на заявките към нея.

    Проектът ще е доста прост REPL, в който команди като SHOW, SELECT и подобни се превръщат в HTTP заявка, изпращат се до базата и отговорът се показва на потребителят, a зад custom команди като EXPORT, IMPORT и подобни ще стои по-сложната логика в проекта.

    Библиотеки

    reqwest - за HTTP заявки

    json - за обработка на JSON

    Източници

    Influxdb Backup & restore Influxdb Line protocol

  28. @Йоанна Харно, малко мъгляво откъм конкретни алгоритми, май още не си дорешила, но да видим.

    Няколко неща, които можеш да добавиш:

    • Генериране на шум -- би било полезно за тестване на алгоритми, които махат шум, като разнообразните blur-ове и други филтри: http://homepages.inf.ed.ac.uk/rbf/HIPR2/noise.htm
    • Thresholding и промяна на хистограми: http://homepages.inf.ed.ac.uk/rbf/HIPR2/pntops.htm (за нормализиране на контраст, може да потърсиш конкретни снимки, с които да се получава добро демо)
    • Може да си харесаш някакви конкретни инстаграм филтри и да се помъчиш да ги имитираш: https://fieldguide.gizmodo.com/how-to-copy-your-favorite-instagram-filters-in-photosho-1793598957. Тук описват как да се получат нещата с Photoshop операции, които ще трябва да google-неш, за да разбереш как работят. Примерно, нали.

    Свиване и разпъване ми изглеждат твърде лесни, понеже image crate-а ги поддържа by default. Ако обаче напишеш програмата като command-line tool, който приема примерно поредица от команди с ясни параметри, това би било готино. Нещо като "crop-ни ми тази картинка до wallpaper, и ако е твърде тясна, добави черни ленти от двете страни".

    Ако е command-line tool с добър интерфейс, нямам проблеми даже да имплементираш най-простите алгоритми, които намериш. Ако предпочиташ да се занимаваш с алгоритмичната част, ок е просто да хардкодваш някакви трансформации в main-а, но тогава имплементирай някви яки неща :).

    @Иван Добре, това звучи смислено. Мисля, че имаше подобни tool-ове на ruby, но те по-скоро бяха за мигриране на данни между две SQL бази, и просто конвертираха нещата до yaml. Прецени си как ще организираш смислено демо, за да видим как се получава import/export-а.

Трябва да сте влезли в системата, за да може да отговаряте на теми.