Skip to main content

Petlja publishing system

Project description

PetljaPub - систем за дигиталне публикације из програмирања

Систем PetljaPub служи за креирање збирки задатака, уџбеника и других едукативних материјала за учење програмирања. Решења задатака се могу писати на различитим програмским језицима и омогућено је њихово превођење, покретање и аутоматско тестирање пре укључивања у публикацију (збирку или уџбеник). Публикације се граде укључивањем појединих задатака, њихових одабраних решења, као и пропратних текстова (најчешће прегледа теорије). Збирке је могуће креирати у формату PDF (спремне за штампу) путем коришћења система LaTeX и у формату HTML (спремне за објављивање на вебу).

Поставке задатака и објашњења решења пише се у формату MarkDown. Одабир задатака и текстова који ће бити укључени у збирку врши се кроз датотеку у формату YAML.

Инсталација и конфигурација (configure)

Систем је имплементиран у језику Python и доступан је преко PyPI (https://pypi.org/project/petljapub/). За коришћење система неохподно је да је на рачунару инсталиран Python, у верзији бар 3.7. На рачунарима на којима је инсталиран Python, систем PetljaPub се може инсталирати из командне линије командом:

pip install petljapub

Да би систем било могуће користити потребно је да је из командне линије доступан преводилац за C++ (било GNU преводилац g++, било Microsoft-ов преводилац cl), који подржава стандард C++ 14. Пожељно је да уз C++ буде доступан и неки преводилац за C# (било Microsoft-ов преводилац csc или dotnet, било Mono преводилац mono или mcs) и преводилац за C (на пример, GNU преводилац gcc). За припрему штампаних верзија збирке потребно је и да је инсталиран и из командне линије доступан систем Pandoc (https://pandoc.org/), а пожељно је да је инсталиран и систем LaTeX да би се аутоматски могла произвести и PDF верзија документа.

Након инсталације система PetljaPub потребно је конфигурисати га командом petljapub configure. Након успешне конфигурације добија се порука следећег типа.

INFO: ---------- checking python --------------------
INFO: Found python3 3.8.10
INFO: ---------- checking C++ compilers -------------
INFO: Found g++ 8.4.0
INFO: ---------- checking C compilers ---------------
INFO: Found gcc 8.4.0
INFO: ---------- checking C# compilers --------------
INFO: Found mono 6.8.0.123
INFO: ---------- checking pandoc --------------------
INFO: Found pandoc 2.11.0.4
INFO: ---------- checking LaTeX --------------------
INFO: Found LaTeX 3.14159265
INFO: Found LaTeX Make 4.67
INFO: ---------- Final report  ----------------------
INFO: Configuration writen in /home/user/.config/petljapub/conf.json

Ако неки компилатор није пронађен, систем ће пријавити упозорење, али ће моћи да се користи његова функционалност која се не односи на тај компилатор. Ако из командне линије није доступан компилатор за C++ систем ће пријавити фаталну грешку приликом конфигурације и неће моћи да се користи док се не инсталира и не подеси компилатор за C++ и систем поново не конфигурише (командом petljapub configure).

Још једна опција коју је пожељно конфигурисати је подразумевани језик који ће бити коришћен у датотекама које садрже описе задатака и решења. Конфигурација језика врши се командом petljapub set-language. На пример, командом

petljapub set-language sr-Cyrl

поставља се српски језик са ћириличким писмом. Тренутно су подржани:

  • енглески језик (en) који је подразумеван и користи се док се систем не конфигурише другачије,
  • српски језик, ћириличко писмо (sr-Cyrl),
  • српски језик, латиничко писмо (sr-Latn).

Након конфигурације, систем се покреће и користи из командне линије, командом petljapub којој се наводе одговарајући параметри. Команде за рад са појединачним задатком се по правилу позивају из директоријума тог задатка, док се команде за рад са целом збирком (колекцијом задатака) по правилу позивају из кореног директоријума збирке.

Команде за рад са појединачним задатком

Сваки задатак мора бити смештен у директоријуму чији је назив почиње са две цифре из којих иде размак, црта или подвлака (нпр. коректни називи су 01 zadatak, 34_zadatak или 58-zadatak).

Креирање задатка (new)

Након креирања директоријума задатка, рад на новом задатку се започиње позиционирањем унутар тог директоријума и издавањем команде petljapub new. Њоме се креирају "клице" свих датотека, које је даље потребно модификовати. Опис појединачних датотека дат је у наставку овог документа. Клице се генеришу у складу са подешеним језиком (видети команду petljapub set-language).

Превођење програма (compile)

Превођење програма врши се командом petljapub compile <lang> или скраћено petljapub c <lang>. У склопу команде је потребно задати и ознаку програмског језика <lang> (то су најчешће cpp за C++, cs за C#, py за Python или c за C), а опционо је могуће задати и редни број решења које се преводи (опцијом --sol <n>, скраћено -s <n>, где је <n> редни број решења). На пример.

  • petljapub compile cpp или petljapub c cpp преводе основно решење у језику cpp (решење {zadatak_id}.cpp).

  • petljapub c cs -s 1 преводи прво алтернативно решење у језику C# (решење {zadatak_id}-ex1.cs).

  • petljapub c c -s 3 преводи треће алтернативно решење у језику C (решење {zadatak_id}-ex3.c).

Покретање програма (run)

Покретање програма врши се командом petljapub run <lang> или скраћено petljapub r <lang>, при чему <lang> представља ознаку програмског језика. Ако програм није преведен пре покретања, аутоматски се врши његово превођење. Ако се не подеси другачије, покренути програм ради интерактивно тј. чита податке са стандардног улаза и исписује их на стандардни излаз. У склопу команде је потребно задати и ознаку програмског језика, а опционо је могуће задати и редни број решења које се покреће (опцијом --sol <n>, скраћено -s <n>). На пример:

  • petljapub run cpp или petljapub r cpp покреће основно решење у језику cpp (решење {zadatak_id}.cpp).

  • petljapub r cs -s 1 покреће прво алтернативно решење у језику C# (решење {zadatak_id}-ex1.cs).

  • petljapub r c -s 3 покреће треће алтернативно решење у језику C (решење {zadatak_id}-ex3.c).

Програм може бити покренут и тако да се улаз чита из неког од тест примера, при чему се излаз приказује на стандардном излазу. Тест-примери морају бити генерисани пре покретања програма (командом petljapub tests-gen). Покретање програма на појединачним тест-примерима врши се следећим параметрима команде run:

  • --testcase <n>, скраћено -t <n> или --generated <n>, скраћено -g <n>, при чему је <n> редни број тест-примера проузрокује да се програм изврши на задатом генерисаном тест-примеру.

  • --example <n>, скраћено -e <n>, при чему је <n> редни број тест-примера проузрокује да се програм изврши на задатом примеру који је издвојен из поставке задатка.

  • -crafted <n>, скраћено -c <n>, при чему је <n> редни број тест-примера проузрокује да се програм изврши на задатом примеру који је задат помоћу ручно креиране улазне датотеке.

На пример, petljapub r cpp -s 2 -e 1 извршава друго решење у језику C++ (задато датотеком {zadatak_id}-ex2.cpp) читајући улаз из првог тест-примера задатог у поставци задатка.

Генерисање тест-примера (tests-gen, tests-zip)

Тест-примери се генеришу командом petljapub tests-gen или скраћено petljapub tg.

Постоје три могуће врсте тест-примера:

  • тест-примери из текста задатка (очекивани улаз и излаз за сваки такав пример је описан у датотеци {zadatak_id}-st.md),

  • програмски генерисани тест-примери (генерисани C++ програмом датим у датотеци {zadatak_id}-tgen.cpp),

  • ручно направљени тест-примери (дати кроз колекцију *.in и евентуално *.out датотека у неком директоријуму)

Командом tests-gen се врши издвајање тест-примера из текста задатка, а затим и превођење и покретање генератора тест-примера. Очекивани резултат за сваки тест-пример се генерише коришћењем званичног решења у језику C++ (ако није преведено, оно се аутоматски преводи пре генерисања тест-примера). Ако генератор тест-примера (датотека {zadatak_id}-tgen.cpp) не постоји или је функција gen_tests празна, генерисање тест-примера се прескаче.

Ако се наведе параметар --crafted-dir <dir>, скраћено -c <dir>, где је <dir> путања неког директоријума, тада се све *.in датотеке из тог директоријума (најчешће ручно креиране) додатно уврштавају у колекцију званичних тест-примера. Ако уз неку *.in датотеку постоји и одговарајућа *.out датотека она се сматра очекиваним резултатом за тај улаз, а ако таква датотека не постоји, тада се очекивани резултат аутоматски генерише коришћењем званичног решења у језику C++ (ако није преведено, оно се аутоматски преводи пре генерисања тест-примера).

Сви тест-примери се смештају у директоријум _build/testcases.

Командом petljapub tests-zip, скраћено petljapub tz се сви тест-примери генеришу изнова и пакују се у архиву testcases.zip која се смешта у директоријум _build. Ако се наведе параметар --crafted-dir <dir>, скраћено -c <dir> у архиву се укључују и тест-примери смештени у наведеном директоријуму <dir>.

Тестирање програма (test, test-all)

Тестирање програма подразумева његово извршавање на тест-примерима, у оквиру задатог временског ограничења и поређење резултата са очекиваним.

Тестирање појединачних решења врши се командом petljapub test <lang> или скраћено petljapub t <lang>. У склопу команде је потребно задати и ознаку програмског језика <lang>, а опционо је могуће задати и редни број решења које се покреће (коришћењем параметра --sol <n>, скраћено -s <n>). На пример:

  • petljapub test cpp или petljapub t cpp тестира основно решење у језику cpp (решење {zadatak_id}.cpp).

  • petljapub t cs -s 1 тестира прво алтернативно решење у језику C# (решење {zadatak_id}-ex1.cs).

  • petljapub t c -s 3 тестира треће алтернативно решење у језику C (решење {zadatak_id}-ex3.c).

Решење се тестира на свим тест-примерима и приказује се извештај за сваку појединачу групу тест-примера (оних задатих у тексту задатка, оних који су аутоматски генерисани и оних који су ручно припремљени, ако такви постоје).

Додатне опције које се могу навести су:

  • --timeout <sec>, скраћено -t <sec> -- допуштено време извршавања програма у секундама (подразумевана вредност је један секунд)

  • --verbosity <level>, скраћено -v <level> -- ниво детаљности порука. Опција -v 4 приказује списак свих тест примера током тестирања, док се опцијом -v 5 приказују и очекивани и добијени излаз на свим тест-примерима на којима се они разликују.

  • --outputs, скраћено -o -- ако је ова опција наведена, чувају се излази програма који се тестира.

Могуће је покренути и тестирање појединачних тест-примера. Томе служе следећи додатни параметри:

  • --testcase <n>, скраћено -t <n> или --generated <n>, скраћено -g <n>, при чему је <n> редни број тест-примера проузрокује да се програм тестира на задатом генерисаном тест-примеру.

  • --example <n>, скраћено -e <n>, при чему је <n> редни број тест-примера проузрокује да се програм тестира на задатом примеру који је издвојен из поставке задатка.

  • -crafted <n>, скраћено -c <n>, при чему је <n> редни број тест-примера проузрокује да се програм тестира на задатом примеру који је задат помоћу ручно креиране улазне датотеке.

На пример, petljapub t cpp -s 2 -e 1 тестира друго решење у језику C++ (задато датотеком {zadatak_id}-ex2.cpp) на првом тест-примеру задатом у поставци задатка.

Командом petljapub test-all покреће се тестирање свих решења задатка. Да би се неко решење тестирало, мора бити наведено у заглављу формулације задатка (на почетку датотеке {zadatak_id}-st.md, у делу solutions).

Упоређивач (checker)

За поређење добијеног и очекиваног излаза се користи одговарајући упоређивач (checker). Ако другачије није наведено користи се подразумевани упоређивач који је имплемтиран у језику Python, уграђен у систем. Ако у директоријуму у који је инсталиран систем PetljaPub постоји програм под називом DefaultChecker.exe, он ће се користити за проверу свих задатака. Могуће је да постоји и упоређивач који је специфичан за конкретан задатак. Он се имплементира кроз C++ програм {zadatak_id}-check.cpp. Аргументи командне линије овако имплементираног упоређивача су следећи:

  • први аргумент argv[1] је датотека са излазом који се проверава

  • други аргумент argv[2] је датотека са очекиваним излазом

  • трећи аргумент argv[3] је датотека са улазним подацима

Ако је решење коректно упоређивач завршава рад са повратним кодом 0. У супротном повратни код мора да буе различит од 0.

Ако постоји, упоређивач специфичан за задатак се аутоматски преводи пре тестирања решења. Превођење упоређивача се може покренути и експлицитно, командом petljapub compile-checker.

Мерење времена извршавања (runtime)

Командом petljapub runtime приказују се времена извршавања на свим генерисаним тест-примерима. Команда може да прими и следеће параметре:

  • --timeout <sec>, скраћено -t <sec> -- временско ограничење за извршавање решења задатка у секундама (подразумевано ограничење је једна секунда).

  • --repeat <k>, скраћено -r <k> -- ради боље прецизности времена се одређују тако што се сваки програм покрене неколико пута и израчуна се средишње време. Параметром <k> се контролише број покретања сваког решења задатка (подразумевана вредност је 3).

  • --plot, скраћено -p -- времена се приказују у виду стубичастог графикона.

Подразумевано се приказују времена извршавања свих решења у свим програмским језицима. Параметрима --sol <n>, скраћено -s <n> и --lang <lang>, скраћено -l <lang> могуће је ограничити приказ само на неко решење и/или неке програмске језике.

HTML преглед (html-preview)

Командом petljapub html-preview гради се веб-страница која садржи поставку задатка, описе свих решења и њихове програмске кодове. Генерисана страница се чува у директоријуму _build под називом {zadatak_id}.html.

  • --css <css-file>, скраћено -c <css-file> - путања до CSS датотеке <css-file> која ће се укључити у сваки HTML (подразумевано се користи стил pandoc.css, који се дистрибуира уз PetljaPub).

  • --header <md-file>, скраћено -h <md-file> - путања до датотеке са заглављем које ће се укључити на почетак MarkDown датотеке, пре њеног превођења у HTML (нпр. header.md, која садржи LaTeX макрое коришћене у задацима, која се дистрибуира уз PetljaPub)

Напомена: за функционалност генерисања HTML-а потребно је да је инсталиран Pandoc и да је систем PetljaPub конфигурисан након тога -- након што се инсталира Pandoc, конфигурисање система PetljaPub је могуће поново покренути командом petljapub configure.

Команде за рад са публикацијама (збиркама, уџбеницима, ...)

Поред команди за рад са појединачним задацима, систем PetljaPub нуди и команде за рад са збиркама које представљају колекције текстова (прегледа теорије) и задатака. Свака збирка је одређена датотеком у формату YAML (опис формата ове датотеке дат је у наставку овог овог упуства).

Генерисање LaTeX збирке (yaml-tex)

Командом petljapub yaml-tex <yaml> <dst> генерише се збирка у формату LaTeX. Обавезни параметри команде су:

  • <yaml> - путања до YAML датотеке у којој је дата спецификација збирке.

  • <dst> - путања резултујуће датотеке (која може имати екстензију .md, .tex или .pdf)

Најважнији опциони параметри су:

  • --tasks-dir <dir>, скраћено -t <dir> -- путања до кореног директоријума <dir> у ком су смештени сви задаци (ако се не наведе, подразумева се директоријум у који је смештена задата yaml датотека).

  • --pub-dir <dir>, скраћено -p <dir> -- путања до кореног директоријума у ком су смештени сви пропратни текстови, најчешће прегледи теорије (ако се не наведе, подразумева се директоријум у који је смештена yaml датотека).

  • --header <md-file>, скраћено -h <md-file> -- путања до датотеке са заглављем које ће се укључити на почетак обједињене MarkDown датотеке, пре њеног превођења у LaTeX (подразумевано се укључује датотека header.md, која садржи LaTeX макрое коришћене у задацима и која се испоручује у склопу система PetljaPub)

  • --tex-template <tex-file>, скраћено -е <tex-file> -- шаблон LaTeX датотеке који ће се користити за збирку (подразумевано се користи датотека default.latex која се испоручује у склопу система PetljaPub)

  • --lat, скраћено -l -- ако је наведена ова опција, цела збирка се аутоматски преводи у латиницу

  • --babel, скраћено -b -- кроз ову опцију се наводи језик који се користи за интернационализацију (у LaTeX-у се користе пакети babel или polyglossia), ако је различит од енглеског. Вредности за српски језику су sr-Cyrl или sr-Latn. Осим у командној линији, језик се може спецификовати у YAML опису публикације.

Типичан пример коришћења ове команде је:

petljapub yaml-tex "_zadaci/02 Zbirka_2/zbirka.yml" "_pdf/zbirka.tex" -t "_zadaci/"

Генерисање HTML збирке (yaml-html)

Командом petljapub yaml-html <yaml> <dst> генерише се збирка у формату HTML. Обавезни параметри ове команде су:

  • <yaml> -- путања до YAML датотеке у којој је дата спецификација збирке.

  • <dst> -- назив директоријума или зип архиве у коју ће бити смештен резултат.

Најважнији опциони параметри су:

  • --tasks-dir <dir>, скраћено -t <dir> -- путања до кореног директоријума <dir> у ком су смештени сви задаци (ако се не наведе, подразумева се директоријум у који је смештена yaml датотека).

  • --pub-dir <dir>, скраћено -p <dir> -- путања до кореног директоријума у ком су смештени сви пропратни текстови, најчешће прегледи теорије (ако се не наведе, подразумева се директоријум у који је смештена наведена yaml датотека).

  • --css <css-file>, скраћено -c <css-file> -- путања до CSS датотеке која ће се укључити у сваки HTML (нпр. може се навести pandoc.css чиме се користи CSS датотека која је испоручена уз систем PetljaPub)

  • --header <md-file>, скраћено -h <md-file> -- путања до датотеке са заглављем које ће се укључити на почетак обједињене MarkDown датотеке, пре њеног превођења у LaTeX (подразумевано се укључује датотека header.md, која садржи LaTeX макрое коришћене у задацима и која се испоручује у склопу система PetljaPub)

  • --lat, скраћено -l -- ако је наведена ова опција, цела збирка се аутоматски преводи у латиницу

  • --babel, скраћено -b -- кроз ову опцију се наводи језик који се користи за интернационализацију (у LaTeX-у се користе пакети babel или polyglossia), ако је различит од енглеског. Вредности за српски језику су sr-Cyrl или sr-Lat. Осим у командној линији, језик се може спецификовати у YAML опису публикације.

Типичан пример коришћења ове команде је:

petljapub yaml-html "_zadaci/02 Zbirka_2/zbirka.yml" "_html/zbirka" -c "pandoc.css" -t "_zadaci/"

Тестирање целе збирке (yaml-test)

Командом petljapub yaml-test <yaml>, којој је аргумент <yaml> путатања до спецификације збирке у формату YAML, покреће се тестирање свих решења задатака наведених у задатој YAML датотеци. Извештај о тестирању сваког задатка се бележи унутар _build директоријума тог задатка. У наредним покретањима тестирања тестирају се само задаци који су измењени од претходног тестирања.

Статистике о збирци (yaml-stats)

Командом petljapub yaml-stats <yaml> приказују се основне статистике о самој збирци и репозиториујуму са задацима. За сваки задатак се приказује списак решења укључених у збирку, укупан број укључених задатака и решења, као и списак задатака који се налазе у репозиторијуму задатака, али нису укључени у збирку.

Формати датотека за опис задатака и збирки задатака

У овом документу се описују улазни формати датотека којима се описују делови збирки задатака. Обрадом ових датотека коришћењем система PetljaPub могуће је креирати збирке у формату PDF (спремну за штампу) и формату HTML (спремну за објављивање на вебу).

Сви задаци се задају тако да је могуће њихово аутоматско тестирање. То подразумева да се задаци решавају писањем програма са командно-линијским интерфејсом (конзолних апликација), да су у самој формулацији задатка прецизно описани формат улазних и излазних података, као и да је сваки задатак праћен тест-примерима који се користе за тестирање (задатак обично садржи програм који аутоматски генерише тест-примере). Задаци обавезно садрже једно или више решења и то најчешће у неколико програмских језика.

Појединачни задаци се могу груписати у збирке. Поред задатака, збирке могу да садрже и теоријске уводе, као и било какав други текстуални садржај наведен у засебним датотекама. Садржај збирке се одређује спецификацијом у формату YAML у којој се наводе датотеке које садрже текстуалне елементе збирке (најчешће теоријске уводе) као и задаци који се укључују у збирку. Сваки задатак може бити укључен и у неколико збирки. Исти задатак у збирку може бити укључен и више пута (обично се приликом сваког укључивања задатка у збирку бирају решења која ће бити приказана, па се исти задатак користи да у различитим поглављима збирке илуструје различите технике решавања истог проблема).

Описи појединачних задатака

Задаци се описују у формату MarkDown, док се метаподаци о задатку задају у формату YAML. Сваки задатак обавезно садржи наредне датотеке, све смештене у исти директоријум, које се аутоматски генеришу позивом команде petljapub new:

  • {zadatak_id}-st.md - овај документ садржи прецизно описану поставку задатка, описану у формату MarkDown. Спецификација садржи прецизан текст задатка, опис улазних података и опис излазних податка.
  • {zadatak_id}-sol.md - овај документ садржи прецизан опис решења задатка, такође у формату MarkDown.
  • {zadatak_id}.cpp - основно решење задатка у језику C++.
  • {zadatak_id}.cs - основно решење задатка у језику C#.
  • {zadatak_id}.py - основно решење задатка у језику Python 3.
  • {zadatak_id}-tgen.cpp - генератор тест примера написан у програмском језику C++ (уз помоћ библиотеке tgen.hpp, која је део инсталације система PetljaPub и може се снимити у текући директоријум наредбом petljapub tgen-hpp). Тест примери треба да буду што репрезентативнији и да покрију све карактеристичне случајеве у програму.

Сваки задатак може да садржи и додатна, алтернативна решења задатака. Они имају суфикс -ex1, -ex2, ... На пример:

  • {zadatak_id}-ex1.cpp - прво алтернативно решење задатка у језику C++.
  • {zadatak_id}-ex1.cs - прво алтернативно решење задатка у језику C#.
  • {zadatak_id}-ex1.py - прво алтернативно решење задатка у језику Python 3.

При том {zadatak_id} представља јединствени идентификатор задатка (сви задаци унутар целокупног репозиторијума свих задатака из којег се генеришу збирке морају имати различит јединствен идентификатор). Пожељно је да он буде написан малим словима, уз коришћење подвлаке за раздвајање речи (али то није неопходно).

Опис метаподатака о задатку и решењима

Метаподаци о задатку се уписују на почетак описа задатка у датотеци {zadatak_id}-st.md, у формату YAML. Почетно YAML заглавље је од пратећег Markdown описа раздвојено линијом која садржи текст ---.

title: Факторијели од 1 до n
timelimit: 0.074 # u sekundama
memlimit: 64 # u MB
owner: filipmaric # vlasnik je onaj ko radi na zadatku
origin:  # izvor odakle je zadatak preuzet (može ostati prazno)
tags: [] # dodatne oznake zadatka
status: KOMPLETAN
status-date: 2022-08-14

Основне ознаке су:

  • title - назив задатка;
  • timelimit - временско ограничење у секундама - попуњава се аутоматски, приликом калибрације збирке коришћењем пратеће софтверске инфраструктуре;
  • memlimit - меморијско ограничење у мегабајтима - попуњава се аутоматски, приликом калибрације збирке коришћењем пратеће софтверске инфраструктуре;
  • owner - власник тј. аутор задатка;
  • origin - извор одакле је задатак преузет (на пример, такмичење, нека друга збирка, неки грејдер, испит). Може остати празно, ако аутор не осећа потребу да наведе извор.
  • tags - додатне ознаке које се могу користити за претрагу задатака.

Након овога, потребно је навести списак свих решења задатка. На пример:

solutions:
   - name: ex0
     desc: "Инкрементално израчунавање на основу рекурентне везе"
     lang: [py, cpp, cs]
     tags: []
   - name: ex1
     desc: "Функција за израчунавање факторијела"
     lang: [py, cpp, cs]
     tags: []

Свако решење описано је следећим атрибутима:

  • name - ознака решења (ex0 за главно решење, а ex1, ex2 итд. за алтернативна);
  • desc - информативни опис решења;
  • lang - листа програмских језика у којима је то решење имплементирано;
  • tags - додатне ознаке решења (могу се користити за претрагу задатка).

Опис поставке задатка

Поставка задатка се описује у наредном формату (командом petljapub new генерише се -st.md датотека која садржи "клицу" задатка са оваквим садржајем):

Текст задатка.

## Улаз 

Опис формата улазних података.

## Излаз

Опис формата очекиваних излазних података.

## Пример

### Улаз

~~~
primer ulaznih podataka
~~~

### Излаз

~~~
primer izlaznih podataka
~~~

### Објашњење

Објашњење примера

Објашњење примера не мора бити наведено. Опис задатка може може садржати и већи број примера улаза и излаза.

Поднаслови морају да буду на језику који се користи приликом превођења у PDF или HTML формат (тај језик се наводи било у YAML опису публикације, било у командној линији, приликом превођења).

Опис решења задатака

Решења задатака су одређена програмским кодом у разним програмским језицима (датотекама .cpp, .cs, .py) и садржајем датотеке {zadatak_id}-sol.md описаним у формату Markdown. Та датотека садржи описе свих решења задатака (и главног и евентуалних алтернативних решења ex1, ex2 итд.). Унутар Markdown описа и унутар програмског кода решења задатка специјалним "магичним коментарима" врше се додатна семантичка обележавања садржаја. Коментари личе на коментаре у језику HTML, али се уместо две цртице користе три.

Описи сваког појединачног решења задатка задају се између коментара следећег облика:

<!--- sol:ex0 --->
...
<!--- sol:end --->

Главно решење је обележено са ex0 (иако датотеке са кодовима решења не садрже ту ознаку).

Делови описа решења карактериснични за одређени програмски језик обележавају се коментарима следећег облика:

<!--- lang:cpp --->
...
<!--- lang:end --->

Овим је обележен део описа специфичан за језик C++. Ознаке језика се поклапају са коришћеним екстензијама датотека са програмским кодом решења (cpp, cs, py, c, ...). Могуће је означити и делове описа заједничке за неколико програмских језика. На пример,

<!--- lang:c,cpp,cs --->
...
<!--- lang:end --->

Неки делови описа означавају се посебним семантичким ознакама, што омогућава да се прикажу на неки истакнути начин (у неком уоквиреном "боксу" тј. "диву"). За то се користи ознака div. На пример, наредним ознакама се означава део решења у ком се приказује пример извршавања програма.

<!--- div:example --->
...
<!--- div:end --->

Могуће је употребљавати ознаке са наредног списка (али уводити и нове ознаке, при чему је за њих потребно у CSS или LaTeX документима описати како се визуелно форматирају). На пример,

  • example - пример извршавања програма
  • note - споредна општа напомена
  • formal - формалан садржај (најчешће доказ коректности алгоритма)
  • complexity - анализа сложености израчунавања

Ради уштеде простора у збирку могу бити укључени само делови програмског кода решења, што се описује магичним коментарима у изворном коду. Коментари су једнолинијски. Линије изворног кода могу бити приказане или сакривене. Подразумевано су линије приказане. Коментаром -*- hide -*- прелази се у режим сакривања линија, а коментаром -*- show -*- у режим приказивања линија. Коментар -*- ellipsis -*- такође преводи у режим сакривања линија (као и -*- hide -*-), једино што се на излазу приказују три тачке. На пример, ако се програм обележи на следећи начин

// -*- hide -*-
#include <iostream>
#include <algorithm>

using namespace std;

// pretvara ugao dat u stepenima(s) i minutima (m) u
// ugao samo u minutima
int uMinute(int s, int m) {
  return s * 60  + m;
}

int main() {
// -*- show -*-
  // ucitavamo uglove u stepenima i minutima
  int ugao1_s, ugao1_m, ugao2_s, ugao2_m, ugao3_s, ugao3_m;
// -*- ellipsis -*-
  cin >> ugao1_s >> ugao1_m;
  cin >> ugao2_s >> ugao2_m;
  cin >> ugao3_s >> ugao3_m;

// -*- show -*-
  // pretvaramo ih u uglove date samo u minutima
  int ugao1 = uMinute(ugao1_s, ugao1_m);
  int ugao2 = uMinute(ugao2_s, ugao2_m);
  int ugao3 = uMinute(ugao3_s, ugao3_m);
// -*- hide -*-
}

у збирци ће бити приказано

  // ucitavamo uglove u stepenima i minutima
  int ugao1_s, ugao1_m, ugao2_s, ugao2_m, ugao3_s, ugao3_m;
  ...

  // pretvaramo ih u uglove date samo u minutima
  int ugao1 = uMinute(ugao1_s, ugao1_m);
  int ugao2 = uMinute(ugao2_s, ugao2_m);
  int ugao3 = uMinute(ugao3_s, ugao3_m);

Реферисање задатака

У поставкама и решењима задатака (датотекама {zadatak_id}-st.md и {zadatak_id}-sol.md) могуће је реферисати се на друге задатке. За реферисање се користи формат референци дефинисан формату MarkDown, при чему је уместо линка довољно навести само јединствени идентификатор задатка, док опис може остати празан. На пример

Ова техника је описана у задатку [](trening).

Приликом обраде збирке линкови се попуњавају одговарајућим путањама, а за текст везе се узима назив реферисаног задатка (прочитан из метаподатка title наведеног у датотеци {zadatak_id}-st.md).

Препоручује се да се линк експлицитно обележи, да би се изоставио уколико у збирку није укључен задатак на који се рефереше.

<!--- span:link --->
Ова техника је описана у задатку [](trening).
<!--- span:end --->

Уметање слика

У поставке и решења задатака (датотеке {zadatak_id}-st.md и {zadatak_id}-sol.md) могуће је укључити и слике. Слика мора бити сачувана у директоријум задатка, а укључује се коришћењем MarkDown описа следећег облика.

![Судоку](sudoku.png){width="200px"}

На овом месту се укључује слика sudoku.png, назив слике је Судоку, док је резултујућа ширина слике (у генерисаним PDF или HTML документима) 200 пиксела.

За нумерисање и реферисање слика користи се Pandoc филтер fignos. На пример, слика која има наслов на који се реферише се може унети на следећи начин.

![Судоку](sudoku.png){#fig:sudoku width="200px"}

Референца на слику се затим добија помоћу @fig:sudoku било где унутар Markdown описа странице на којој се слика налази.

Распоред задатка у структури директоријума

Сваки задатак смештен је у засебан директоријум, чије је име облика 00 {zadatak_id}. Име директоријума мора почети бројем записаним помоћу две цифре. Бројеви служе за једноставнији преглед директоријума унутар датотечког система и ни на који начин не утичу на редослед задатака у збирци.

Директоријуми са задацима могу бити на произвољан начин организовани унутар хијерархије поддиректоријума једно централног директоријума (зовемо га репозиторијум задатака), али је битно да се директоријуми са задацима не садрже поддиректоријуме (осим, помоћних, аутоматски генерисаних, попут директоријума _build који садржи извршиве кодове и тест-примере ). На пример, организација задатака унутар репозиторијума може бити следећа:

.
└── zadaci
    ├── 01 aritmetika
    │   ├── 01 cena
    │   └── 02 obim
    └── 02 iteracija
        ├── 01 zbir_brojeva
        └── 02 faktorijel

Опис збирке

Збирка представља колекцију задатака, која је обично допуњена пропратним текстом организованим у облику класичне збирке задатака (по главама и поглављима). Целокупни садржај збирке добија се спајањем садржаја већег броја датотека које садрже текст описан у формату Markdown. Неке од тих датотека су део део задатака (формулације и описи решења, као и изворни кодови решења), а неке се пишу посебно и представљају додатни изворни кôд збирке. У збирку се могу укључити и изворни кодови решења задатака (или њихови делови).

Спецификација датотека од којих се добија садржај збирке наводи се у формату YAML, у посебној датотеци. "Клица" такве датотеке се може добити наредбом

petljapub new-yaml <naziv>

Метаподаци

На почетку YAML спецификације наводе се одређени метаподаци. На пример,

title: Збирка задатака - основни ниво
authors: Фондација Петља
thumb: logo.png
short-description: >
   Збирка обухвата почетне нивое учења програмирања и припреме
   за такмичарско програмирање.
full-description: index.md
languages: [cpp]

Метаподаци се спецификују навођењем следећих атрибута:

  • title - одређује наслов збирке;
  • authors - одређује списак аутора;
  • thumb - одређује датотеку са сличицом која илуструје збирку. Путања до датотеке је релативна у односу на директоријум у ком се налази YAML спецификација.
  • short-description - кратак текстуални опис збирке;
  • full-description - дужи текстуални опис збирке. Уместо самог текста могуће је навести и путању до датотеке у формату MarkDown која садржи тај опис. Путања до датотеке је релативна у односу на директоријум у ком се налази YAML спецификација.
  • languages - програмски језик или списак програмских језика који се користе за приказ решења у збирци.

Садржај збирке

Датотеке које садрже делове садржаја збирке могу бити организоване унутар хијерархије директоријума смештене унутар једног кореног директоријума који садржи саму YAML спецификацију збирке (ту хијерархију директоријума називамо репозиторијум збирке). То може, али не мора бити идентична хијерархија као она у којој се налазе задаци (подсетимо се, они су смештени унутар директоријума који називамо репозиторијум задатака). Називи директоријума унутар репозиторијума збирке могу бити нумерисани, ради једноставније прегледа унутар датотечког система, међутим, то није обавезно. Редослед укључивања садржаја у збирку одређен је искључиво редоследом навођења унутар YAML спецификације и не зависи од евентуалне нумерације директоријума унутар репозиторијума збирке.

Подела садржаја збирке на главе и поглавља одређена је искључиво ознакама наслова унутар MarkDown датотека и никако не зависи од хијерархије директоријума у којима су те датотеке смештене.

Садржај збирке описује се YAML спецификацијом, у склопу атрибута content.

content:
  - .predgovor.md
  - 01 aritmetika:
     - 01 formule:
        - trening:
           print: full
        - ocene:
           print: full
           solution: [ex0, ex1]
           code: [ex1]
  - 02 iteracija:
     - 01 petlje:
        - brojevi_od_a_do_b:
           print: statement
        - while.md
        - ocene:
           print: full
           solution: [ex2]
           code: [ex2]

Хијерархијска организација унутар YAML спецификације одговара структури директоријума унутар репозиторијума збирке. Приликом обраде спецификације, за сваки наведени директоријум проверава се да ли садржи датотеку index.md и ако садржи, она се укључује у садржај збирке.

Поред индексних датотека наведених директоријума, у збирку је могуће укључити и друге *.md датотеке (као, на пример, predgovor.md или while.md у претходној спецификацији). Оне се морају налазити у репозиторијуму збирке, а путања до њих одређена је хијерархијом директоријума наведених у YAML спецификацији (на пример, predgovor.md налази се у кореном директоријуму, док ће путања до датотеке while.md бити 02 iteracija/01 petlje/while.md).

Ако назив *.md датотеке почиње карактером ., тада се то поглавље ненумерише (ово се обично користи за предговор, додатак и слично).

У збирку је могуће укључити и задатке, тако што се у YAML спецификацији наведе њихов јединствени идентификатор, уз додатни опис елемената задатка који се на том месту укључују у збирку. Подсетимо се, изворни кôд задатака (поставки и решења) се проналази у репозиторијуму задатака, који је потпуно независна хијерархија директоријума од репозиторијума збирке. Није забрањено да се те две хијерархије поклапају, тј. да задаци буду распоређени у истој хијерархији директоријума у којој је распоређен текстуални садржај збирке и која се наводи и у склопу YAML спецификације, али то не мора бити случај. Раздвајањем репозиторијума задатака од репозиторијума збирке, омогућава се да се исти задатак два пута укључи у исту збирку (у различитим поглављима се приказују различита решења), као и да се над истим репозиторијумум задатака изгради више различито организованих збирки.

Задатак (или део задатка) може бити уметнут и у неко поглавље збирке (било индексну датотеку index.md унутар неког директоријума, било неку другу Markdown датотеку наведену у YAML опису), коришћењем директиве task. На пример, на месту наредног коментара у некој Markdown датотеци наводи се целокупан текст и решење задатка чији је идентификатор sudoku.

<!---task
id: sudoku
print: full
--->

Наредним коментаром се постиже уметање само програмског кода основног решења, без стављања додатног наслова задатка.

<!---task
id: sudoku
print: code
solutions: [ex0]
no-title: True
--->

Претходна спецификација подразумева овакву организацију и садржај директоријума унутар репозиторијума збирке.

.
├── zbirka.yml
├── logo.png
├── index.md
├── 01 aritmetika
│   ├── index.md
│   └── 01 formule
│       └── index.md
└── 02 iteracija
    ├── index.md
    └── 01 petlje
        ├── index.md
        └── while.md

Zbirka ће бити добијена спајањем следећих датотека:

predgovor.md
01 aritmetika/index.md
01 aritmetika/01 formule/index.md
[zadatak trening, kompletan]
[zadatak ocene, opis rešenja ex0 i ex1, kod rešenja ex1]
02 iteracija/index.md
02 iteracija/01 petlje/index.md
[zadatak brojevi_od_a_do_b, samo postavka]
02 iteracija/01 petlje/while.md
[zadatak ocene, opis i kod rešenja ex2]

Задаци trening, ocene и brojevi_od_a_do_b налазе се у репозиторијуму задатака. Ако се не планира креирање више збирки над истим овим задацима, најприродније решење је да се репозиторијум задатака и репозиторијум збирке преклпају.

.
├── zbirka.yml
├── logo.png
├── index.md
├── 01 aritmetika
│   ├── index.md
│   └── 01 formule
│       ├── index.md
│       ├── 01 trening
│       └── 02 ocene
└── 02 iteracija
    ├── index.md
    └── 01 petlje
        ├── index.md
        ├── while.md
        └── 01 brojevi_od_a_do_b

Приметимо да се задатак ocene може укључити и у поглавље о петљама, иако је у хијерархији директоријума смештен само у поглавље о аритметици. То је могуће захваљујући томе што се задаци у репозиторијуму задатака проналазе на основу њиховог јединственог идентификатора, а не на основу путање одређене положајем унутар YAML спецификације.

Параметри укључивања задатака

Приликом укључивања задатка у збирку потребно је спецификовати делове задатка који се на том месту укључују.

  • Атрибут print одређује да ли се укључује само само поставка задатка (вредност statement), или и поставка и решење (вредност full).
  • Атрибут solutions одређује која ће се решења задатка укључити. Изостављањем вредности овог атрибута приказују се сва доступна решења.
  • Атрибут code одређује који програмски кôд ће бити укључен. Изостављањем овог атрибута приказују се програмски кодови за сва решења која су одређена атрибутом solutions (ако неко решење није укључено навођењем или изостављањем атрибута solutions, програмски кôд тог решења неће бити штампан иако се експлицитно наведе атрибутом code).
  • Атрибут no-io одређује да се из текста задатка изостави прецизан опис улаза и излаза и тест-примери.
  • Атрибут no-title одређује да се изостави назив задатка (што највише има смисла када се задатак умеће у неко поглавље збирке тј. Markdown датотеку помоћу магичног коментара task).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

petljapub-2.1.5.tar.gz (134.4 kB view details)

Uploaded Source

Built Distribution

petljapub-2.1.5-py3-none-any.whl (113.1 kB view details)

Uploaded Python 3

File details

Details for the file petljapub-2.1.5.tar.gz.

File metadata

  • Download URL: petljapub-2.1.5.tar.gz
  • Upload date:
  • Size: 134.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.8.10

File hashes

Hashes for petljapub-2.1.5.tar.gz
Algorithm Hash digest
SHA256 ab7e304c940093042fdfe0a1a98a8475a8529aecb295c639033a714a7326a7c0
MD5 f5ab82d9b46b2234d14b1f9024d766cb
BLAKE2b-256 cab61da23752ffe42dd03b9fe62e4be4a39cc7fc0b89c59a9cbc1ba9305870d2

See more details on using hashes here.

File details

Details for the file petljapub-2.1.5-py3-none-any.whl.

File metadata

  • Download URL: petljapub-2.1.5-py3-none-any.whl
  • Upload date:
  • Size: 113.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.8.10

File hashes

Hashes for petljapub-2.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 bc9c5b8e1420cd574f20f3703fdae3433293209b11db61d9f67586d4abf0d54e
MD5 4fccd154aa96c8803289eaa87f336245
BLAKE2b-256 3f173fb35825c14d42a1ad051b5c10deea6dfe8461ae7bb28a164b1a3cfa984b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page