1
0
Fork 0

2023-06-30

This commit is contained in:
Gennadiy 2023-12-17 07:53:27 +03:00
parent f4d80ac0a0
commit 6434e68250
37 changed files with 1042 additions and 0 deletions

3
.gitattributes vendored
View file

@ -0,0 +1,3 @@
README*.md linguist-language=HTML
draft/2023-06-05-round-robin.md linguist-language=Java
draft/2023-06-13-directory-tree.md linguist-language=Shell

2
.gitignore vendored
View file

@ -1,2 +1,4 @@
.idea
*.iml
.repo_*.sh
.token_*

46
DIRECTORY-TREE.md Normal file
View file

@ -0,0 +1,46 @@
## Дерево каталогов
<pre>
.
├─ <a href='bash_scripts'>bash_scripts</a>
│ ├─ <a href='bash_scripts/README.en.md'>README.en.md</a>
│ ├─ <a href='bash_scripts/README.md'>README.md</a>
│ ├─ <a href='bash_scripts/archive-common.sh'>archive-common.sh</a>
│ ├─ <a href='bash_scripts/archive-packages.sh'>archive-packages.sh</a>
│ ├─ <a href='bash_scripts/info-copy.sh'>info-copy.sh</a>
│ ├─ <a href='bash_scripts/info-domain.sh'>info-domain.sh</a>
│ ├─ <a href='bash_scripts/info-toggle.sh'>info-toggle.sh</a>
│ ├─ <a href='bash_scripts/repo-compose.sh'>repo-compose.sh</a>
│ ├─ <a href='bash_scripts/repo-gitea.tmpl.sh'>repo-gitea.tmpl.sh</a>
│ ├─ <a href='bash_scripts/repo-gitlab.tmpl.sh'>repo-gitlab.tmpl.sh</a>
│ ├─ <a href='bash_scripts/repo-local.tmpl.sh'>repo-local.tmpl.sh</a>
│ └─ <a href='bash_scripts/repo-update.sh'>repo-update.sh</a>
├─ <a href='draft'>draft</a>
│ ├─ <a href='draft/2023-06-05-round-robin.md'>2023-06-05-round-robin.md</a>
│ ├─ <a href='draft/2023-06-13-directory-tree.md'>2023-06-13-directory-tree.md</a>
│ └─ <a href='draft/README.md'>README.md</a>
├─ <a href='pictures'>pictures</a>
│ ├─ <a href='pictures/1.jpg'>1.jpg</a>
│ ├─ <a href='pictures/2.jpg'>2.jpg</a>
│ ├─ <a href='pictures/3.jpg'>3.jpg</a>
│ ├─ <a href='pictures/4.jpg'>4.jpg</a>
│ ├─ <a href='pictures/5.jpg'>5.jpg</a>
│ ├─ <a href='pictures/README.md'>README.md</a>
│ ├─ <a href='pictures/color-tomato-theme.jpg'>color-tomato-theme.jpg</a>
│ ├─ <a href='pictures/directory-tree1.jpg'>directory-tree1.jpg</a>
│ ├─ <a href='pictures/directory-tree2.jpg'>directory-tree2.jpg</a>
│ ├─ <a href='pictures/directory-tree3.jpg'>directory-tree3.jpg</a>
│ ├─ <a href='pictures/directory-tree4.jpg'>directory-tree4.jpg</a>
│ ├─ <a href='pictures/draft.jpg'>draft.jpg</a>
│ ├─ <a href='pictures/maintenance.jpg'>maintenance.jpg</a>
│ ├─ <a href='pictures/older-tomato-theme.jpg'>older-tomato-theme.jpg</a>
│ ├─ <a href='pictures/pictures.jpg'>pictures.jpg</a>
│ └─ <a href='pictures/pomodoro.jpg'>pomodoro.jpg</a>
├─ <a href='CONTRIBUTING.md'>CONTRIBUTING.md</a>
├─ <a href='DIRECTORY-TREE.md'>DIRECTORY-TREE.md</a>
├─ <a href='LICENSE.md'>LICENSE.md</a>
├─ <a href='OPEN_LICENSE.txt'>OPEN_LICENSE.txt</a>
├─ <a href='README.en.md'>README.en.md</a>
├─ <a href='README.md'>README.md</a>
└─ <a href='WIKI.md'>WIKI.md</a>
</pre>

78
README.en.md Normal file
View file

@ -0,0 +1,78 @@
# [Pomodori](README.md)
Updated and once again rewritten variant of my old blog, new versions of old programs: volumetric
tetris, simple captcha and others — simplified site generating without obfuscation, lightweight
page design without JavaScript and open license RF instead of MIT — there are a lot of changes and
everywhere, but the essence remains the same — nothing has changed. Series of static websites
«Pomodori» — not to be bored and not to forget how to write programs, when there is no work.
### Content
Solutions to programming problems with errors and descriptions of solutions. Correction of errors
— is an additional task for C students and cheaters. All code is checked and works — it looks nice,
but such code cannot be used on the production server. Question for B students: find at least one
error. Question for A students: find *more* errors and write the *own* solution.
Constructive criticism and error descriptions can be sent over electronic mail — at least it is
interesting for me and useful for professional growth. Because, firstly, not all mistakes are made
intentionally and, secondly, not all of them — are mistakes.
- [pomodoro1](https://hub.mos.ru/pomodoro/1/blob/master/README.en.md) — Three-dimensional graphics in JavaScript.
- [pomodoro2](https://hub.mos.ru/pomodoro/2/blob/master/README.en.md) — Cartesian product, combinatorics.
- [pomodoro3](https://hub.mos.ru/pomodoro/3/blob/master/README.en.md) — Matrix multiplication, rotations.
- [pomodoro4](https://hub.mos.ru/pomodoro/4/blob/master/README.en.md) — Poetry. Humor.
- [pomodoro5](https://hub.mos.ru/pomodoro/5/blob/master/README.en.md) — Drawing pictures with text.
### Build
Previously, a custom Java program was used to generate a site from templates. After generating, the
obfuscation was performed for all classes, variables and functions of HTML, CSS and JS with a dictionary
substitution cipher. Code blocks were left without obfuscation, and syntax highlighting was performed on
the client. *Obusificator* — is a unique solution, no longer used.
Now the site is generated by Jekyll, the template language is Liquid, syntax
highlighting during build time, and the content of the pages is in Markdown format.
[Maintenance](bash_scripts/README.en.md)
is performed by Bash scripts. The thought does not leave me, that
I made a *senseless swap* — in general, nothing has changed.
### Design
Two design themes for Jekyll in the Liquid template language:
[«Color tomato»](https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.en.md)
was written earlier using AngularJS and Material, this was
the design of the previous version of my blog, then an
[«Older tomato»](https://hub.mos.ru/golovin.gg/older-tomato-theme/blob/master/README.en.md)
— lightweight single-color variant was written using only HTML and CSS, the appearance resembles
the default design theme on GitHub Pages. Both tomatoes supplement each other and are similar to
each other, commonalities and differences between them are marked in the list below.
- [x] Responsive layout.
- [x] User JS and CSS files in the head block of HTML pages.
- [x] SEO-markup using JSON-LD and Open Graph.
- [x] Switch between two languages and two tomato themes.
- [x] Map of site pages with their translations in XML format.
- [x] Simple 404 page for non-existing URLs.
- [x] Fonts: Roboto for text and JBMono for code blocks.
- [x] Tomatoes: PNG, JPG 120x120, SVG 64x64, ICO 32x32.
- [ ] Color selection during the build, green is the default color.
- [ ] Scroll-to-top button in Material style.
### License
Previously, I attached the MIT license to my projects on the Internet, but when the open license
RF appeared — I switched to it, promptly made minor changes to the text and supplemented it on my
own, though I am not a lawyer. The main meaning of the license remains the same — the program is
provided free of charge, but without any guarantees, and the author of the program is me.
- [OPEN_LICENSE.txt](OPEN_LICENSE.txt) — the main text of the license and an explanation
to it without changes, can be found on the Internet. I removed the extra spaces and space
characters out from it, so that the text looks more like text.
- [LICENSE.md](LICENSE.md) — supplementation from myself with a reference to the main text
of the license.
- [CONTRIBUTING.md](CONTRIBUTING.md) — description of the way, in which the project can be
contributed.
---
©Golovin G.G.,Code with comments,translation from Russian,2021-2023

77
README.md Normal file
View file

@ -0,0 +1,77 @@
# [Помидоры](README.en.md)
Обновлённый и ещё раз переписанный вариант моего старого блога, новые версии
старых программ: объёмный тетрис, простая капча и другие — упрощённая сборка
сайта без обфускации, облегчённое оформление страниц без JavaScript и открытая
лицензия РФ вместо MIT — изменений много и везде, но суть осталась прежней —
ничего не изменилось. Серия статических вёб-сайтов «Помидоры» — чтобы не скучать и
чтобы не забыть, как программы писать, когда работы нет.
### Содержание
Решения задач по программированию с ошибками и описания решений. Исправление ошибок — дополнительная
задача для троечников и любителей списывать. Весь код проверен и работает — выглядит красиво, но на
продуктовом сервере такой код использовать нельзя. Вопрос на четвёрку: найти хотя бы одну ошибку.
Вопрос на пятёрку: найти *больше* ошибок и написать *своё* решение.
Конструктивную критику и описания ошибок можно отправлять по электронной почте — как минимум мне
это интересно и полезно для профессионального роста. Потому что, во-первых, не все ошибки допущены
намеренно и, во-вторых, не все они — есть ошибки.
- [pomodoro1](https://hub.mos.ru/pomodoro/1/blob/master/README.md) — Трёхмерная графика на JavaScript.
- [pomodoro2](https://hub.mos.ru/pomodoro/2/blob/master/README.md) — Декартово произведение, комбинаторика.
- [pomodoro3](https://hub.mos.ru/pomodoro/3/blob/master/README.md) — Умножение матриц, повороты.
- [pomodoro4](https://hub.mos.ru/pomodoro/4/blob/master/README.md) — Поэзия. Юмор.
- [pomodoro5](https://hub.mos.ru/pomodoro/5/blob/master/README.md) — Рисуем картинки текстом.
### Сборка
Раньше сборку сайта из шаблонов выполняла кастомная программа на Java. После сборки выполнялась
обфускация для всех классов, переменных и функций HTML, CSS и JS шифром замены по словарю. Блоки
кода оставлялись без обфускации, а подсветка синтаксиса выполнялась на клиенте. *Обусификатор* —
уникальное решение, больше не используется.
Теперь сборку сайта выполняет Jekyll, язык шаблонов Liquid, подсветка
синтаксиса во время сборки, а содержание страниц в формате Markdown.
[Обслуживание](bash_scripts/README.md)
выполняется скриптами Bash. Меня не покидает мысль, что
я *поменял шило на мыло* — в целом ничего не изменилось.
### Оформление
Две темы оформления для Jekyll на языке шаблонов Liquid:
[«Цветной помидор»](https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.md)
был написан раньше с использованием AngularJS и Material, таким
было оформление предыдущей версии моего блога, затем был написан
[«Старый помидор»](https://hub.mos.ru/golovin.gg/older-tomato-theme/blob/master/README.md)
— облегчённый одноцветный вариант с использованием только HTML и CSS, внешний вид
напоминает тему оформления по умолчанию на GitHub Pages. Оба помидора дополняют друг
друга и похожи друг на друга, общие черты и различия между ними отмечены в списке ниже.
- [x] Адаптивная вёрстка или Responsive layout.
- [x] Файлы пользователя JS и CSS в блоке head страниц HTML.
- [x] SEO-разметка с использованием JSON-LD и Open Graph.
- [x] Переключение между двумя языками и помидорными темами.
- [x] Карта страниц сайта с их переводами в формате XML.
- [x] Простая страница 404 для несуществующих URL-адресов.
- [x] Шрифты: Roboto для текста и JBMono для блоков кода.
- [x] Помидоры: PNG, JPG 120x120, SVG 64x64, ICO 32x32.
- [ ] Выбор цвета во время сборки, зелёный цвет по умолчанию.
- [ ] Кнопка прокрутки вверх в стиле Material.
### Лицензия
Раньше к своим проектам в интернете прикладывал лицензию MIT, но когда появилась открытая
лицензия РФ — перешёл на неё, сразу внёс небольшие изменения в текст и дополнил от себя,
хотя я не юрист. Основной смысл лицензии остался прежним — программа предоставляется
бесплатно, но без каких-либо гарантий, и автор программы — это я.
- [OPEN_LICENSE.txt](OPEN_LICENSE.txt) — основной текст лицензии и пояснение к нему без
изменений, можно найти в интернете. Из него удалил лишние пробелы и пробельные символы,
чтобы текст был больше похож на текст.
- [LICENSE.md](LICENSE.md) — дополнение от себя с указанием ссылки на основной текст лицензии.
- [CONTRIBUTING.md](CONTRIBUTING.md) — описание способа, как можно содействовать проекту.
---
© Головин Г.Г., Код с комментариями,2021-2023

71
WIKI.md Normal file
View file

@ -0,0 +1,71 @@
<hr>
<details open>
<summary><h3>Содержание</h3></summary>
<hr>
1. Трёхмерная графика на JavaScript.
- [Объёмный тетрис](https://pomodoro1.mircloud.ru/ru/2023/01/21/volumetric-tetris.html) — 21.01.2023.
- [Вращаем пространственный крест](https://pomodoro1.mircloud.ru/ru/2023/01/15/spinning-spatial-cross.html) — 15.01.2023.
- [Вращаем куб в пространстве](https://pomodoro1.mircloud.ru/ru/2023/01/10/spinning-cube-in-space.html) — 10.01.2023.
- [Вращаем квадрат на плоскости](https://pomodoro1.mircloud.ru/ru/2023/01/05/spinning-square-on-plane.html) — 05.01.2023.
2. Декартово произведение, комбинаторика.
- [Декартово произведение в параллельных потоках](https://pomodoro2.mircloud.ru/ru/2021/10/04/cartesian-product-parallel-streams.html) — 04.10.2021.
- [Комбинации элементов последовательности](https://pomodoro2.mircloud.ru/ru/2021/09/20/combinations-of-sequence-elements.html) — 20.09.2021.
- [Комбинации элементов по столбцам](https://pomodoro2.mircloud.ru/ru/2021/09/13/combinations-by-columns.html) — 13.09.2021.
- [Треугольник Паскаля на Java](https://pomodoro2.mircloud.ru/ru/2021/09/09/pascals-triangle-in-java.html) — 09.09.2021.
- [Декартово произведение множеств](https://pomodoro2.mircloud.ru/ru/2021/09/06/cartesian-product-of-sets.html) — 06.09.2021.
3. Оптимизация умножения матриц.
- [Алгоритм Винограда — Штрассена](https://pomodoro3.mircloud.ru/ru/2022/02/10/winograd-strassen-algorithm.html) — 10.02.2022.
- [Умножение матриц в параллельных потоках](https://pomodoro3.mircloud.ru/ru/2022/02/08/matrix-multiplication-parallel-streams.html) — 08.02.2022.
- [Поворот матрицы на 180 градусов](https://pomodoro3.mircloud.ru/ru/2021/12/16/matrix-rotation-180-degrees.html) — 16.12.2021.
- [Поворот матрицы на 90 градусов](https://pomodoro3.mircloud.ru/ru/2021/12/12/matrix-rotation-90-degrees.html) — 12.12.2021.
- [Оптимизация умножения матриц](https://pomodoro3.mircloud.ru/ru/2021/12/09/optimizing-matrix-multiplication.html) — 09.12.2021.
4. Юмор. Поэзия.
- [Поэзия начала 20 века](https://pomodoro4.mircloud.ru/ru/2022/01/07/poetry-early-20th-century.html) — 07.01.2022.
- [История про лес, название утеряно](https://pomodoro4.mircloud.ru/ru/2022/01/05/forest-story-title-lost.html) — 05.01.2022.
5. Рисуем картинки на Java.
- [Генератор паролей](https://pomodoro5.mircloud.ru/ru/2023/06/19/password-generator.html) — 19.06.2023.
- [Рисуем сердечко в консоли](https://pomodoro5.mircloud.ru/ru/2023/03/08/drawing-heart-in-console.html) — 08.03.2023.
- [График функции в консоли](https://pomodoro5.mircloud.ru/ru/2023/02/05/function-graph-in-console.html) — 05.02.2023.
- [Рисуем простую капчу](https://pomodoro5.mircloud.ru/ru/2023/01/03/drawing-simple-captcha.html) — 03.01.2023.
</details>
<hr>
<details open>
<summary><h3>Content</h3></summary>
<hr>
1. Three-dimensional graphics in JavaScript.
- [Volumetric tetris](https://pomodoro1.mircloud.ru/en/2023/01/22/volumetric-tetris.html) — 22.01.2023.
- [Spinning spatial cross](https://pomodoro1.mircloud.ru/en/2023/01/16/spinning-spatial-cross.html) — 16.01.2023.
- [Spinning cube in space](https://pomodoro1.mircloud.ru/en/2023/01/11/spinning-cube-in-space.html) — 11.01.2023.
- [Spinning square on plane](https://pomodoro1.mircloud.ru/en/2023/01/06/spinning-square-on-plane.html) — 06.01.2023.
2. Cartesian product, combinatorics.
- [Cartesian product in parallel streams](https://pomodoro2.mircloud.ru/en/2021/10/05/cartesian-product-parallel-streams.html) — 05.10.2021.
- [Combinations of sequence elements](https://pomodoro2.mircloud.ru/en/2021/09/22/combinations-of-sequence-elements.html) — 22.09.2021.
- [Combinations of elements by columns](https://pomodoro2.mircloud.ru/en/2021/09/14/combinations-by-columns.html) — 14.09.2021.
- [Pascal's Triangle in Java](https://pomodoro2.mircloud.ru/en/2021/09/10/pascals-triangle-in-java.html) — 10.09.2021.
- [Cartesian product of sets](https://pomodoro2.mircloud.ru/en/2021/09/07/cartesian-product-of-sets.html) — 07.09.2021.
3. Optimizing matrix multiplication.
- [Winograd — Strassen algorithm](https://pomodoro3.mircloud.ru/en/2022/02/11/winograd-strassen-algorithm.html) — 11.02.2022.
- [Matrix multiplication in parallel streams](https://pomodoro3.mircloud.ru/en/2022/02/09/matrix-multiplication-parallel-streams.html) — 09.02.2022.
- [Matrix rotation 180 degrees](https://pomodoro3.mircloud.ru/en/2021/12/17/matrix-rotation-180-degrees.html) — 17.12.2021.
- [Matrix rotation 90 degrees](https://pomodoro3.mircloud.ru/en/2021/12/13/matrix-rotation-90-degrees.html) — 13.12.2021.
- [Optimizing matrix multiplication](https://pomodoro3.mircloud.ru/en/2021/12/10/optimizing-matrix-multiplication.html) — 10.12.2021.
4. Humor. Poetry.
- [Poetry early 20th century](https://pomodoro4.mircloud.ru/en/2022/01/08/poetry-early-20th-century.html) — 08.01.2022.
- [Forest story, title lost](https://pomodoro4.mircloud.ru/en/2022/01/06/forest-story-title-lost.html) — 06.01.2022.
5. Drawing images in Java.
- [Password generator](https://pomodoro5.mircloud.ru/en/2023/06/20/password-generator.html) — 20.06.2023.
- [Drawing heart in console](https://pomodoro5.mircloud.ru/en/2023/03/08/drawing-heart-in-console.html) — 08.03.2023.
- [Function graph in console](https://pomodoro5.mircloud.ru/en/2023/02/06/function-graph-in-console.html) — 06.02.2023.
- [Drawing simple captcha](https://pomodoro5.mircloud.ru/en/2023/01/04/drawing-simple-captcha.html) — 04.01.2023.
</details>
<hr>

36
bash_scripts/README.en.md Normal file
View file

@ -0,0 +1,36 @@
# [Maintenance](README.md)
Process automation for static websites [«Pomodori»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.en.md).
Creating archives, building websites, creating local and remote repositories for publishing.
| Bash scripts | Actions performed |
|:-------------------------------------------|:------------------------------------------------------------------------------------------------|
| [archive-common.sh](archive-common.sh) | Creating a common archive for the directories of projects on the current date. |
| [archive-packages.sh](archive-packages.sh) | Building websites, creating and copying archives for deployment. |
| [info-copy.sh](info-copy.sh) | Copying information files and building a tree in each of the directories of projects. |
| [**info-domain.sh**](info-domain.sh) | Used in other scripts. Setting the domain parameter of the remote repository. |
| [info-toggle.sh](info-toggle.sh) | Toggling the remote repository for cross-references in descriptions. |
| [**repo-compose.sh**](repo-compose.sh) | Setting parameters for templates and copying ready-made scripts to the directories of projects. |
| [repo-local.tmpl.sh](repo-local.tmpl.sh) | Script template without parameters to create a local repository. |
| [repo-gitea.tmpl.sh](repo-gitea.tmpl.sh) | Script template without parameters to create a remote repository gitea. |
| [repo-gitlab.tmpl.sh](repo-gitlab.tmpl.sh) | Script template without parameters to create a remote repository gitlab. |
| [**repo-update.sh**](repo-update.sh) | Executing scripts in parallel mode and creating repositories for the directories of projects. |
## Structure
Linear directory structure — all projects are located in one folder.
Scripts are launched from those directories, in which they are located.
<pre>
.
├─ <a href='https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.en.md'>color-tomato-theme</a> — Decoration
├─ <a href='https://hub.mos.ru/golovin.gg/older-tomato-theme/blob/master/README.en.md'>older-tomato-theme</a> — Decoration
├─ <a href='https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.en.md'>pomodoro</a> — Description
├─ <a href='https://hub.mos.ru/pomodoro/1/blob/master/README.en.md'>pomodoro1</a> — Website
├─ <a href='https://hub.mos.ru/pomodoro/2/blob/master/README.en.md'>pomodoro2</a> — Website
├─ <a href='https://hub.mos.ru/pomodoro/3/blob/master/README.en.md'>pomodoro3</a> — Website
├─ <a href='https://hub.mos.ru/pomodoro/4/blob/master/README.en.md'>pomodoro4</a> — Website
└─ <a href='https://hub.mos.ru/pomodoro/5/blob/master/README.en.md'>pomodoro5</a> — Website
</pre>

36
bash_scripts/README.md Normal file
View file

@ -0,0 +1,36 @@
# [Обслуживание](README.en.md)
Автоматизация процессов для статических вёб-сайтов [«Помидоры»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md).
Создание архивов, сборка вёб-сайтов, создание локальных и удалённых репозиториев для публикации.
| Скрипты Bash | Выполняемые действия |
|:-------------------------------------------|:------------------------------------------------------------------------------------------|
| [archive-common.sh](archive-common.sh) | Создание общего архива для каталогов проектов на текущую дату. |
| [archive-packages.sh](archive-packages.sh) | Сборка вёб-сайтов, создание и копирование архивов для развёртывания. |
| [info-copy.sh](info-copy.sh) | Копирование информационных файлов и построение дерева в каждом из каталогов проектов. |
| [**info-domain.sh**](info-domain.sh) | Используется в других скриптах. Установка параметра домена удалённого репозитория. |
| [info-toggle.sh](info-toggle.sh) | Переключение удалённого репозитория для перекрёстных ссылок в описаниях. |
| [**repo-compose.sh**](repo-compose.sh) | Установка параметров для шаблонов и копирование готовых скриптов в каталоги проектов. |
| [repo-local.tmpl.sh](repo-local.tmpl.sh) | Шаблон скрипта без параметров для создания локального репозитория. |
| [repo-gitea.tmpl.sh](repo-gitea.tmpl.sh) | Шаблон скрипта без параметров для создания удалённого репозитория gitea. |
| [repo-gitlab.tmpl.sh](repo-gitlab.tmpl.sh) | Шаблон скрипта без параметров для создания удалённого репозитория gitlab. |
| [**repo-update.sh**](repo-update.sh) | Выполнение скриптов в параллельном режиме и создание репозиториев для каталогов проектов. |
## Структура
Линейная структура каталогов — все проекты расположены в одной папке.
Скрипты запускаются из тех каталогов, в которых они расположены.
<pre>
.
├─ <a href='https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.md'>color-tomato-theme</a> — Оформление
├─ <a href='https://hub.mos.ru/golovin.gg/older-tomato-theme/blob/master/README.md'>older-tomato-theme</a> — Оформление
├─ <a href='https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md'>pomodoro</a> — Описание
├─ <a href='https://hub.mos.ru/pomodoro/1/blob/master/README.md'>pomodoro1</a> — Вёб-сайт
├─ <a href='https://hub.mos.ru/pomodoro/2/blob/master/README.md'>pomodoro2</a> — Вёб-сайт
├─ <a href='https://hub.mos.ru/pomodoro/3/blob/master/README.md'>pomodoro3</a> — Вёб-сайт
├─ <a href='https://hub.mos.ru/pomodoro/4/blob/master/README.md'>pomodoro4</a> — Вёб-сайт
└─ <a href='https://hub.mos.ru/pomodoro/5/blob/master/README.md'>pomodoro5</a> — Вёб-сайт
</pre>

7
bash_scripts/archive-common.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
echo "Создание общего архива для каталогов проектов на текущую дату."
cd ../..
filename="pomodoro-$(date '+%Y-%m-%d').zip"
rm -rf "$filename"
7z a -tzip -ssw -mx9 -r0 "$filename" ./* -xr!".idea" -xr!".git" -x!".token_*" \
-x!"*.iml" -x!"*.gem" -x!"*.lock" -x!"*.zip" -x!"_site*" -x!".repo_*.sh"

View file

@ -0,0 +1,12 @@
#!/bin/bash
echo "Сборка вёб-сайтов, создание и копирование архивов для развёртывания."
cd ..
milliseconds=$(date '+%s%3N')
for ((i = 1; i <= 5; i++)); do
echo "Обработка: pomodoro$i"
cd "../pomodoro$i" || continue
./build.sh
./package.sh
cp -uv "pomodoro$i.zip" ..
done
echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

26
bash_scripts/info-copy.sh Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
echo "Копирование информационных файлов и построение дерева в каждом из каталогов проектов."
cd ..
basedir=$(pwd)
milliseconds=$(date '+%s%3N')
find .. -mindepth 1 -maxdepth 1 -type d | sort -r | while read -r dir; do
echo "Обработка: $dir"
cd "$dir" || continue
if [ "${dir##*/}" != "${basedir##*/}" ]; then
cp -uv "$basedir"/CONTRIBUTING.md .
cp -uv "$basedir"/*LICENSE* .
fi
{
echo "## Дерево каталогов"
echo
echo "<pre>"
tree -nvf --dirsfirst -I "*.gem|*.lock|*.zip|_site*" --noreport
echo "</pre>"
} >DIRECTORY-TREE.md
sed -i -e "s/ / /g" -e "s/ / /g" -e "s/──/─/g" DIRECTORY-TREE.md
find . -mindepth 1 -type f,d -not -regex '.*\.\(gem\|lock\|zip\)\|.*/\(\.\|_site\).*' | sort -r | while read -r file; do
# echo "${dir#*/} => \\$file >> ${file#*/} >> ${file##*/}"
sed -i "s|\\$file|<a href='${file#*/}'>${file##*/}<\/a>|g" DIRECTORY-TREE.md
done
done
echo "Время выполнения: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

4
bash_scripts/info-domain.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
#remote="git.org.ru"
remote="hub.mos.ru"
echo "Репозиторий: $remote"

16
bash_scripts/info-toggle.sh Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
echo "Переключение удалённого репозитория для перекрёстных ссылок в описаниях."
source info-domain.sh || remote="git.org.ru"
cd ../..
find . -type f -name 'README*.md' -o -name '*.gemspec' | sort -r | while read -r file; do
echo "$remote => $file"
if [ "$remote" == "hub.mos.ru" ]; then
sed -i 's/git\.org\.ru/hub\.mos\.ru/g' "$file"
sed -i 's/GIT\.ORG\.RU/HUB\.MOS\.RU/g' "$file"
sed -i 's/src\/branch/blob/g' "$file"
else
sed -i 's/hub\.mos\.ru/git\.org\.ru/g' "$file"
sed -i 's/HUB\.MOS\.RU/GIT\.ORG\.RU/g' "$file"
sed -i 's/blob/src\/branch/g' "$file"
fi
done

69
bash_scripts/repo-compose.sh Executable file
View file

@ -0,0 +1,69 @@
#!/bin/bash
echo "Установка параметров для шаблонов и копирование готовых скриптов в каталоги проектов."
source info-domain.sh || remote="git.org.ru"
basedir=$(pwd)
cd ../..
find . -mindepth 1 -maxdepth 1 -type d | sort -r | while read -r dir; do
echo "Обработка: $dir"
if [ ! -f "$dir"/.gitignore ] || [ "$(grep -cx "\.repo_\*\.sh" "$dir"/.gitignore)" == 0 ]; then
echo ".repo_*.sh" >>"$dir"/.gitignore
echo "Обновлён файл .gitignore"
fi
owner="golovin.gg"
repo=${dir##*/}
description=""
type="usr"
wiki=""
if [[ "$dir" =~ "pomodoro" ]]; then
if [[ "$dir" =~ [[:digit:]] ]]; then
owner="pomodoro"
repo=${dir//[^[:digit:]]/}
type="org"
description="Вёб-сайт: https://${owner}${repo}.mircloud.ru"
else
if [ "$remote" == "hub.mos.ru" ]; then
wiki=$(uni2ascii -a U -qpsn "$dir"/WIKI.md)
else
wiki=$(basenc "$dir"/WIKI.md --base64)
fi
description="Серия статических вёб-сайтов / Содержание / Сборка / Оформление / Открытая лицензия РФ"
fi
elif [[ "$dir" =~ "color-tomato" ]]; then
description="Цветной помидор / Тема оформления Jekyll"
elif [[ "$dir" =~ "older-tomato" ]]; then
description="Старый помидор / Тема оформления Jekyll"
elif [[ "$dir" =~ "maintenance" ]]; then
description="Скрипты Bash / Обслуживание / Автоматизация процессов / Создание архивов / Сборка вёб-сайтов / "
description+="Копирование файлов / Построение дерева каталогов / Создание скриптов из шаблонов / "
description+="Шаблоны скриптов / Создание локальных и удалённых репозиториев"
elif [[ "$dir" =~ "draft" ]]; then
description="Черновик / Код с комментариями"
elif [[ "$dir" =~ "pictures" ]]; then
description="Картинки / Аватарки для репозиториев"
fi
{
echo "#!/bin/bash"
if [ "$remote" == "hub.mos.ru" ]; then
echo "user=\"golovin.gg\""
fi
echo "owner=\"$owner\""
echo "repo=\"$repo\""
echo "description=\"$description\""
echo "type=\"$type\""
echo "wiki=\"$wiki\""
if [ "$remote" == "hub.mos.ru" ]; then
echo "token=\"$(cat "$basedir/.token_hub_mos_ru")\""
cat "$basedir/repo-gitlab.tmpl.sh"
else
echo "token=\"$(cat "$basedir/.token_git_org_ru")\""
cat "$basedir/repo-gitea.tmpl.sh"
fi
} >"$dir"/.repo_remote.sh && chmod +x "$dir"/.repo_remote.sh
{
echo "#!/bin/bash"
echo "remote=\"$remote\""
echo "owner=\"$owner\""
echo "repo=\"$repo\""
cat "$basedir/repo-local.tmpl.sh"
} >"$dir"/.repo_local.sh && chmod +x "$dir"/.repo_local.sh
done

View file

@ -0,0 +1,46 @@
if [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$type" ]; then
echo "Не указаны обязательные параметры." && exit 2
fi
echo "Создание удалённого репозитория для текущего каталога."
seconds=2
milliseconds=$(date '+%s%3N')
echo "Удаление старого репозитория."
curl -X DELETE "https://git.org.ru/api/v1/repos/$owner/$repo" \
-H "accept: application/json" \
-H "Authorization: token $token" -i
echo "Ожидание $seconds с."
sleep $seconds
if [ "$type" == "org" ]; then
echo "Создание нового репозитория организации."
curl -X POST "https://git.org.ru/api/v1/orgs/$owner/repos" \
-H "accept: application/json" \
-H "Authorization: token $token" \
-H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\"}" -i
else
echo "Создание нового репозитория пользователя."
curl -X POST "https://git.org.ru/api/v1/user/repos" \
-H "accept: application/json" \
-H "Authorization: token $token" \
-H "Content-Type: application/json" -d "{ \"name\": \"$repo\", \"description\": \"$description\"}" -i
fi
echo "Ожидание $seconds с."
sleep $seconds
if [ "$wiki" ]; then
echo "Добавление страницы wiki в репозиторий."
curl -X POST "https://git.org.ru/api/v1/repos/$owner/$repo/wiki/new" \
-H "accept: application/json" \
-H "Authorization: token $token" \
-H "Content-Type: application/json" -d "{ \"content_base64\": \"$wiki\", \"title\": \"Home\"}" -i
echo "Ожидание $seconds с."
sleep $seconds
has_wiki=true
else
has_wiki=false
fi
echo "Изменение свойств репозитория / отключение ненужного."
curl -X PATCH "https://git.org.ru/api/v1/repos/$owner/$repo" \
-H "accept: application/json" \
-H "Authorization: token $token" \
-H "Content-Type: application/json" -d \
"{ \"has_wiki\": $has_wiki, \"has_issues\": false, \"has_projects\": false, \"has_pull_requests\": false}" -i
echo "Время создания удалённого репозитория: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

View file

@ -0,0 +1,87 @@
if [ -z "$token" ] || [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$description" ] || [ -z "$user" ] || [ -z "$type" ]; then
echo "Не указаны обязательные параметры." && exit 2
fi
echo "Создание удалённого репозитория для текущего каталога."
seconds=15
milliseconds=$(date '+%s%3N')
echo "Удаление старого репозитория."
curl -i -X DELETE "https://hub.mos.ru/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{\"permanently_remove\": \"true\", \"full_path\": \"$owner/$repo\"}"
echo
echo "Ожидание $seconds с."
sleep $seconds
echo "Создание нового репозитория пользователя."
curl -i -X POST "https://hub.mos.ru/api/v4/projects" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{\"name\": \"$repo\", \"description\": \"$description\"}"
echo
echo "Ожидание $seconds с."
sleep $seconds
if [ "$type" == "org" ]; then
echo "Перемещение репозитория в группу."
curl -i -X PUT "https://hub.mos.ru/api/v4/projects/$user%2F$repo/transfer?namespace=$owner" \
-H "PRIVATE-TOKEN: $token"
echo
echo "Ожидание $seconds с."
sleep $seconds
fi
if [ "$wiki" ]; then
echo "Добавление страницы wiki в репозиторий."
curl -i -X POST "https://hub.mos.ru/api/v4/projects/$owner%2F$repo/wikis" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{ \"content\": \"$wiki\", \"title\": \"Home\"}"
has_wiki="enabled"
echo
echo "Ожидание $seconds с."
sleep $seconds
else
has_wiki="disabled"
fi
echo "Изменение свойств репозитория / отключение ненужного."
curl -i -X PUT "https://hub.mos.ru/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \
-H "Content-Type: application/json" -d "{
\"emails_disabled\": \"true\",
\"issues_access_level\": \"disabled\",
\"merge_requests_access_level\": \"disabled\",
\"operations_access_level\": \"disabled\",
\"builds_access_level\": \"disabled\",
\"request_access_enabled\": \"false\",
\"keep_latest_artifact\": \"false\",
\"ci_forward_deployment_enabled\": \"false\",
\"ci_separated_caches\": \"false\",
\"ci_allow_fork_pipelines_to_run_in_parent_project\": \"false\",
\"jobs_enabled\": \"false\",
\"public_builds\": \"false\",
\"packages_enabled\": \"false\",
\"merge_requests_enabled\": \"false\",
\"issues_enabled\": \"false\",
\"lfs_enabled\": \"false\",
\"snippets_enabled\": \"false\",
\"container_registry_enabled\": \"false\",
\"wiki_access_level\": \"$has_wiki\",
\"container_registry_access_level\": \"disabled\",
\"security_and_compliance_access_level\": \"disabled\",
\"pages_access_level\": \"disabled\",
\"analytics_access_level\": \"disabled\",
\"forking_access_level\": \"disabled\",
\"releases_access_level\": \"disabled\",
\"requirements_access_level\": \"disabled\",
\"environments_access_level\": \"disabled\",
\"feature_flags_access_level\": \"private\",
\"infrastructure_access_level\": \"private\",
\"monitor_access_level\": \"disabled\",
\"snippets_access_level\": \"disabled\",
\"auto_devops_enabled\": \"false\",
\"shared_runners_enabled\": \"false\",
\"group_runners_enabled\": \"false\"}"
echo
echo "Ожидание $seconds с."
sleep $seconds
echo "Добавление аватарки для репозитория."
curl -i -X PUT "https://hub.mos.ru/api/v4/projects/$owner%2F$repo" \
-H "PRIVATE-TOKEN: $token" \
-F "avatar=@../pictures/pictures/$repo.jpg"
echo
echo "Время создания удалённого репозитория: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

View file

@ -0,0 +1,37 @@
if [ -z "$remote" ] || [ -z "$owner" ] || [ -z "$repo" ]; then
echo "Не указаны обязательные параметры." && exit 2
fi
echo "Создание локального репозитория, подключение к удалённому и передача данных."
milliseconds=$(date '+%s%3N')
rm -rf .git
git init -b master
git remote add "$remote" "git@$remote:$owner/$repo.git"
git add .git*
git commit -m "Инициализация / $repo"
git push -u "$remote" master
git add CONTRIBUTING.md
git add ./*LICENSE*
git commit -m "Открытая лицензия РФ"
git add DIRECTORY-TREE.md
git add README*
git commit -m "Описание проекта"
git add ./*.sh
git commit -m "Скрипты bash"
git add ./*.min.css
git add ./*.min.js
git add ./*.woff
git commit -m "Сторонние материалы"
git add ./*.bmp
git add ./*.gif
git add ./*.ico
git add ./*.jpg
git add ./*.png
git add ./*.svg
git commit -m "Картинки"
find . -type f -not -regex '.*\.\(gem\|zip\|lock\)\|.*/\(\.\|_site\).*' | sort -r | while read -r file; do
echo "Обработка: $file"
git add "$file"
git commit -m "${file#*/}"
done
git push -u "$remote" master
echo "Время создания локального репозитория: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

7
bash_scripts/repo-update.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
echo "Выполнение скриптов в параллельном режиме и создание репозиториев для каталогов проектов."
cd ..
milliseconds=$(date '+%s%3N')
find .. -mindepth 1 -maxdepth 1 -type d -printf \
'cd %h/%f && ./.repo_remote.sh >/dev/null && ./.repo_local.sh >/dev/null\0' | xargs -L1 -0 -P0 bash -c
echo "Общее время выполнения: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

View file

@ -0,0 +1,285 @@
# Циклический алгоритм распределения задач
*Round-robin (круглая лента)* алгоритм балансировки нагрузки вычислительной системы, распределение
задач по кругу между исполнителями. Есть ряд задач **m**, выполнение которых занимает равное время, и
ряд исполнителей **n**, равных по своим возможностям. Реализация алгоритма на Java 7 с использованием
одной карты `TreeMap` без внешних библиотек.
### Класс `CircularList<T>`
| Карта TreeMap | |
|---------------|-----------------------------------|
| key | `Integer` количество обращений. |
| value | `List<T>` список исполнителей. |
| Конструктор | |
|------------------------------|------------------------------------------------------|
| `CircularList(List<T> list)` | `list` список исполнителей, обязательный параметр. |
| Доступные методы | Возвращаемое значение |
|--------------------------|---------------------------------------------------------------------------------------|
| `getOne()` | `T`, первый элемент с наименьшим количеством обращений. |
| `getOne(List<T> filter)` | `T`, первый элемент с наименьшим количеством обращений, которого нет в списке отбора. |
| `getOne(T filterIn)` | `T`, указанный элемент независимо от количества обращений. |
| `status()`, `toString()` | `String`, текущее состояние карты. |
| Закрытый метод | |
|----------------|-----------------------------------------------------------------------------------|
| `reset()` | `void`, сбрасываем счётчики при достижении максимума `Integer` и обновляем карту. |
---
<details open>
<summary><h3 id="CircularList.java">CircularList.java</h3></summary>
```java
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
// распределение задач по кругу между исполнителями <T>
public class CircularList<T> {
// ключ количество обращений, значение список исполнителей
private final TreeMap<Integer, List<T>> elements = new TreeMap<>();
// list список исполнителей, обязательный параметр
public CircularList(List<T> list) {
if (list == null || list.size() == 0) return;
this.elements.put(0, new ArrayList<>(list));
}
// возвращаем первый элемент с наименьшим количеством обращений
public synchronized T getOne() {
// вынимаем из карты первую запись с наименьшим количеством обращений
Map.Entry<Integer, List<T>> entry = this.elements.pollFirstEntry();
Integer key = entry.getKey();
List<T> value = entry.getValue();
// вынимаем из списка первый элемент
T element = value.remove(0);
// если в списке ещё что-то осталось помещаем обратно в карту
if (value.size() > 0) this.elements.put(key, value);
// берём из карты следующий список с большим количеством обращений
List<T> newValue = this.elements.get(key + 1);
// если его нет создаём новый список
if (newValue == null) newValue = new ArrayList<>();
// добавляем текущий элемент
newValue.add(element);
// помещаем обновлённый список в карту
this.elements.put(key + 1, newValue);
// если достигнут максимум сбрасываем счётчики и обновляем карту
if (Integer.MAX_VALUE - key < 10) this.reset();
// возвращаем первый элемент с наименьшим количеством обращений
return element;
}
// возвращаем первый элемент с наименьшим количеством
// обращений, которого нет в списке отбора filter
public synchronized T getOne(List<T> filter) {
// некорректно задан фильтр отбор не применяется
if (filter == null || filter.size() == 0) return getOne();
Integer key = -1;
List<T> value;
T element = null;
// обходим записи карты
for (Map.Entry<Integer, List<T>> entry : this.elements.entrySet()) {
key = entry.getKey();
value = entry.getValue();
// обходим элементы списка
for (T el : value) {
// если элемента нет в фильтре
if (!filter.contains(el)) {
// элемент найден
element = el;
// удаляем элемент из списка
value.remove(el);
// если в списке ничего не осталось удаляем запись карты
if (value.size() == 0) this.elements.remove(key);
// выходим из цикла
break;
}
}
// если элемент найден выходим из цикла
if (element != null) break;
}
// если элемент не найден фильтр не применяется
if (element == null) return getOne();
// берём из карты следующий список с большим количеством обращений
List<T> newValue = this.elements.get(key + 1);
// если его нет создаём новый список
if (newValue == null) newValue = new ArrayList<>();
// добавляем текущий элемент
newValue.add(element);
// помещаем обновлённый список в карту
this.elements.put(key + 1, newValue);
// если достигнут максимум сбрасываем счётчики и обновляем карту
if (Integer.MAX_VALUE - key < 10) this.reset();
// возвращаем первый элемент с наименьшим количеством обращений
return element;
}
// возвращаем указанный элемент независимо от количества обращений
public synchronized T getOne(T filterIn) {
// некорректно задан фильтр отбор не применяется
if (filterIn == null) return getOne();
// обходим записи карты
for (Map.Entry<Integer, List<T>> entry : this.elements.entrySet()) {
Integer key = entry.getKey();
List<T> value = entry.getValue();
// обходим элементы списка
for (T element : value) {
// если элемент найден
if (filterIn.equals(element)) {
// удаляем этот элемент из списка
value.remove(element);
// если в списке ничего не осталось удаляем запись карты
if (value.size() == 0) this.elements.remove(key);
// берём из карты следующий список с большим количеством обращений
List<T> newValue = this.elements.get(key + 1);
// если его нет создаём новый список
if (newValue == null) newValue = new ArrayList<>();
// добавляем текущий элемент
newValue.add(element);
// помещаем обновлённый список в карту
this.elements.put(key + 1, newValue);
// если достигнут максимум сбрасываем счётчики и обновляем карту
if (Integer.MAX_VALUE - key < 10) this.reset();
// возвращаем отфильтрованный элемент
return element;
}
}
}
// если элемент не найден фильтр не применяется
return getOne();
}
// возвращаем текущее состояние карты
public synchronized String status() {
return elements.toString();
}
@Override
public synchronized String toString() {
return elements.toString();
}
// сбрасываем счётчики и обновляем карту
private synchronized void reset() {
List<T> newList = new ArrayList<>();
while (this.elements.size() > 0)
newList.addAll(this.elements.pollFirstEntry().getValue());
this.elements.put(0, newList);
}
}
```
</details>
---
<details>
<summary><h3 id="Test.java">Test.java</h3></summary>
```java
import java.util.Arrays;
import java.util.List;
// быстрое тестирование запускаем методы в одном потоке
class Test {
public static void main(String[] args) {
List<String> executors = Arrays.asList("A", "B", "C", "D");
CircularList<String> list = new CircularList<>(executors);
System.out.println(list);
// {0=[A, B, C, D]}
for (int i = 0; i < 10; i++)
System.out.print(list.getOne(Arrays.asList("A")) + " ");
// B C D B C D B C D B
System.out.println();
System.out.println(list.status());
// {0=[A], 3=[C, D], 4=[B]}
for (int i = 0; i < 3; i++)
System.out.print(list.getOne("D") + " ");
// D D D
System.out.println();
System.out.println(list.status());
// {0=[A], 3=[C], 4=[B], 6=[D]}
for (int i = 0; i < 14; i++)
System.out.print(list.getOne() + " ");
// A A A C A B C A B C A D B C
System.out.println();
System.out.println(list.status());
// {6=[A], 7=[D, B, C]}
}
}
```
</details>
---
<details>
<summary><h3 id="Test2.java">Test2.java</h3></summary>
```java
import java.util.Arrays;
import java.util.List;
// долгое тестирование запускаем методы в многопоточном режиме
class Test2 {
public static void main(String[] args) {
final List<String> executors = Arrays.asList("A", "B", "C", "D");
final CircularList<String> list = new CircularList<>(executors);
Runnable r1 = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
String test = list.getOne(Arrays.asList("A"));
if (!executors.contains(test))
System.out.println("Error!");
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 300; i++) {
String test = list.getOne("D");
if (!executors.contains(test))
System.out.println("Error!");
}
}
};
Runnable r3 = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1400; i++) {
String test = list.getOne();
if (!executors.contains(test))
System.out.println("Error!");
}
}
};
long time = System.currentTimeMillis();
for (int i = 0; i < 4000000; i++) {
new Thread(r1).start();
new Thread(r2).start();
new Thread(r3).start();
if (i % 1000000 == 0) {
System.out.print(list.status() + " :: ");
System.out.println(System.currentTimeMillis() - time);
}
}
System.out.print(list.status() + " == ");
System.out.println(System.currentTimeMillis() - time);
// {0=[D], 1=[B, C, A]} :: 3
// {674162345=[A], 674162346=[B, C], 674163331=[D]} :: 953920
// {1348883478=[A], 1348883589=[C], 1348883590=[B], 1348884772=[D]} :: 1912645
// {2024396005=[A], 2024396024=[B, C], 2024396481=[D]} :: 2878158
// {551625032=[A], 551625033=[B, C], 551625061=[D]} == 3847930
}
}
```
</details>
---

View file

@ -0,0 +1,75 @@
# Дерево каталогов со ссылками
Напишем скрипт Bash для создания файла [`DIRECTORY-TREE.md`](../DIRECTORY-TREE.md) в корне репозитория со
ссылками на его объекты. Будем использовать полученный файл для навигации по репозиторию в вёб-интерфейсе.
<details>
<summary>
<b>1.</b> Выполняем программу <code>tree</code> и получаем дерево каталогов в текстовом виде, где для
каждогофайла указываем полный префикс пути Linux от корня репозитория. Папки выводим перед файлами и
применяем буквенно-цифровую сортировку. Исключаем файлы и папки, которых не должно быть в репозитории.
Полученное дерево помещаем в блок <code>&lt;pre&gt;</code> и добавляем заголовок.
</summary>
![Дерево каталогов](../pictures/directory-tree1.jpg)
</details>
<details>
<summary>
<b>2.</b> Для красоты, веточки-рамки у дерева box-drawing делаем короче. Для замены подстрок используем
программу <code>sed</code> и регулярные выражения. Пробельные символы заменяем на пробелы. Пошагово
формируем файл <code>DIRECTORY-TREE.md</code>.
</summary>
![Дерево каталогов](../pictures/directory-tree2.jpg)
</details>
<details>
<summary>
<b>3.</b> Далее выполняем программу <code>find</code> и получаем список файлов и каталогов Linux, сортируем
этот список в обратном порядке от самого длинного пути до самого короткого, т. е. вложенные файлы будут перед
их каталогами, чтобы не получилось заменить только часть пути. Затем обходим отсортированный список и заменяем
в полученном дереве относительный путь Linux на относительную ссылку HTTP в теге <code>&lt;a&gt;</code> и именем
файла в представлении ссылки.
</summary>
![Дерево каталогов](../pictures/directory-tree3.jpg)
</details>
<details>
<summary>
<b>4.</b> Получаем файл <code>DIRECTORY-TREE.md</code> для вёб-интерфейса репозитория — Markdown преобразованный в HTML.
</summary>
![Дерево каталогов](../pictures/directory-tree4.jpg)
</details>
---
<details open>
<summary><h3 id="directory-tree.sh">directory-tree.sh</h3></summary>
```bash
#!/bin/bash
echo "Построение дерева каталогов со ссылками."
{
echo "## Дерево каталогов"
echo
echo "<pre>"
tree -nvf --dirsfirst -I "*.gem|*.lock|*.zip|_site*" --noreport
echo "</pre>"
} >DIRECTORY-TREE.md
sed -i -e "s/ / /g" -e "s/ / /g" -e "s/──/─/g" DIRECTORY-TREE.md
find . -mindepth 1 -type f,d -not -regex '.*\.\(gem\|lock\|zip\)\|.*/\(\.\|_site\).*' | sort -r | while read -r file; do
echo "Обработка: \\$file >> ${file#*/} >> ${file##*/}"
sed -i "s|\\$file|<a href='${file#*/}'>${file##*/}<\/a>|g" DIRECTORY-TREE.md
done
```
</details>
---

5
draft/README.md Normal file
View file

@ -0,0 +1,5 @@
| Черновик / Код с комментариями | | |
|-----------------------------------------------------------------------|------|------------|
| [Дерево каталогов со ссылками](2023-06-13-directory-tree.md) | Bash | 13.06.2023 |
| [Циклический алгоритм распределения задач](2023-06-05-round-robin.md) | Java | 05.06.2023 |

BIN
pictures/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
pictures/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
pictures/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
pictures/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
pictures/5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

17
pictures/README.md Normal file
View file

@ -0,0 +1,17 @@
| Картинки / Аватарки для репозиториев |
|-------------------------------------------------------------------------------------------------------------------------|
| [color-tomato-theme](https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.md) |
| [![color-tomato-theme](color-tomato-theme.jpg)](https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.md) |
| [draft](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/draft/README.md) |
| [![draft](draft.jpg)](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/draft/README.md) |
| [maintenance](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/bash_scripts/README.md) |
| [![maintenance](maintenance.jpg)](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/bash_scripts/README.md) |
| [older-tomato-theme](https://hub.mos.ru/golovin.gg/older-tomato-theme/blob/master/README.md) |
| [![older-tomato-theme](older-tomato-theme.jpg)](https://hub.mos.ru/golovin.gg/older-tomato-theme/blob/master/README.md) |
| [pictures](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/pictures/README.md) |
| [![pictures](pictures.jpg)](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/pictures/README.md) |
| [pomodoro](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md) |
| [![pomodoro](pomodoro.jpg)](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md) |
| [pomodoro[1-5]](https://hub.mos.ru/pomodoro) |
| [![pomodoro[1-5]](1.jpg)](https://hub.mos.ru/pomodoro) |

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
pictures/draft.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
pictures/maintenance.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
pictures/pictures.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
pictures/pomodoro.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB