2023-06-30
3
.gitattributes
vendored
|
@ -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
|
@ -1,2 +1,4 @@
|
|||
.idea
|
||||
*.iml
|
||||
.repo_*.sh
|
||||
.token_*
|
||||
|
|
46
DIRECTORY-TREE.md
Normal 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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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"
|
12
bash_scripts/archive-packages.sh
Executable 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
|
@ -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
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
#remote="git.org.ru"
|
||||
remote="hub.mos.ru"
|
||||
echo "Репозиторий: $remote"
|
16
bash_scripts/info-toggle.sh
Executable 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
|
@ -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
|
46
bash_scripts/repo-gitea.tmpl.sh
Normal 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")) мс."
|
87
bash_scripts/repo-gitlab.tmpl.sh
Normal 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")) мс."
|
37
bash_scripts/repo-local.tmpl.sh
Normal 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
|
@ -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")) мс."
|
285
draft/2023-06-05-round-robin.md
Normal 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>
|
||||
|
||||
---
|
75
draft/2023-06-13-directory-tree.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Дерево каталогов со ссылками
|
||||
|
||||
Напишем скрипт Bash для создания файла [`DIRECTORY-TREE.md`](../DIRECTORY-TREE.md) в корне репозитория со
|
||||
ссылками на его объекты. Будем использовать полученный файл для навигации по репозиторию в вёб-интерфейсе.
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<b>1.</b> Выполняем программу <code>tree</code> и получаем дерево каталогов в текстовом виде, где для
|
||||
каждогофайла указываем полный префикс пути Linux от корня репозитория. Папки выводим перед файлами и
|
||||
применяем буквенно-цифровую сортировку. Исключаем файлы и папки, которых не должно быть в репозитории.
|
||||
Полученное дерево помещаем в блок <code><pre></code> и добавляем заголовок.
|
||||
</summary>
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<b>2.</b> Для красоты, веточки-рамки у дерева box-drawing делаем короче. Для замены подстрок используем
|
||||
программу <code>sed</code> и регулярные выражения. Пробельные символы заменяем на пробелы. Пошагово
|
||||
формируем файл <code>DIRECTORY-TREE.md</code>.
|
||||
</summary>
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<b>3.</b> Далее выполняем программу <code>find</code> и получаем список файлов и каталогов Linux, сортируем
|
||||
этот список в обратном порядке от самого длинного пути до самого короткого, т. е. вложенные файлы будут перед
|
||||
их каталогами, чтобы не получилось заменить только часть пути. Затем обходим отсортированный список и заменяем
|
||||
в полученном дереве относительный путь Linux на относительную ссылку HTTP в теге <code><a></code> и именем
|
||||
файла в представлении ссылки.
|
||||
</summary>
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<b>4.</b> Получаем файл <code>DIRECTORY-TREE.md</code> для вёб-интерфейса репозитория — Markdown преобразованный в HTML.
|
||||
</summary>
|
||||
|
||||

|
||||
|
||||
</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
|
@ -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
After Width: | Height: | Size: 17 KiB |
BIN
pictures/2.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pictures/3.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pictures/4.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pictures/5.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
17
pictures/README.md
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
| Картинки / Аватарки для репозиториев |
|
||||
|-------------------------------------------------------------------------------------------------------------------------|
|
||||
| [color-tomato-theme](https://hub.mos.ru/golovin.gg/color-tomato-theme/blob/master/README.md) |
|
||||
| [](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) |
|
||||
| [](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) |
|
||||
| [](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) |
|
||||
| [](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) |
|
||||
| [](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/pictures/README.md) |
|
||||
| [pomodoro](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md) |
|
||||
| [](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) |
|
BIN
pictures/color-tomato-theme.jpg
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
pictures/directory-tree1.jpg
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
pictures/directory-tree2.jpg
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
pictures/directory-tree3.jpg
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
pictures/directory-tree4.jpg
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
pictures/draft.jpg
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
pictures/maintenance.jpg
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
pictures/older-tomato-theme.jpg
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
pictures/pictures.jpg
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
pictures/pomodoro.jpg
Normal file
After Width: | Height: | Size: 15 KiB |