2023-06-30

This commit is contained in:
Gennadiy 2023-12-17 07:57:42 +03:00
parent 0adf594938
commit 2c7eefbb75
33 changed files with 2038 additions and 0 deletions

5
.gitattributes vendored
View file

@ -0,0 +1,5 @@
jekyll_site/ru/** linguist-language=Java
jekyll_site/en/** linguist-language=Java
jekyll_site/ru/2023/06/** linguist-language=JavaScript
jekyll_site/en/2023/06/** linguist-language=JavaScript

3
.gitignore vendored
View file

@ -1,2 +1,5 @@
.idea
*.iml
*.zip
_site*
.repo_*.sh

64
DIRECTORY-TREE.md Normal file
View file

@ -0,0 +1,64 @@
## Дерево каталогов
<pre>
.
├─ <a href='jekyll_site'>jekyll_site</a>
│ ├─ <a href='jekyll_site/_includes'>_includes</a>
│ │ ├─ <a href='jekyll_site/_includes/counters_body.html'>counters_body.html</a>
│ │ └─ <a href='jekyll_site/_includes/counters_head.html'>counters_head.html</a>
│ ├─ <a href='jekyll_site/css'>css</a>
│ │ └─ <a href='jekyll_site/css/pomodoro5.css'>pomodoro5.css</a>
│ ├─ <a href='jekyll_site/en'>en</a>
│ │ ├─ <a href='jekyll_site/en/2023'>2023</a>
│ │ │ ├─ <a href='jekyll_site/en/2023/01'>01</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/01/04'>04</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/01/04/drawing-simple-captcha.md'>drawing-simple-captcha.md</a>
│ │ │ ├─ <a href='jekyll_site/en/2023/02'>02</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/02/06'>06</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/02/06/function-graph-in-console.md'>function-graph-in-console.md</a>
│ │ │ ├─ <a href='jekyll_site/en/2023/03'>03</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/03/08'>08</a>
│ │ │ │ └─ <a href='jekyll_site/en/2023/03/08/drawing-heart-in-console.md'>drawing-heart-in-console.md</a>
│ │ │ └─ <a href='jekyll_site/en/2023/06'>06</a>
│ │ │ └─ <a href='jekyll_site/en/2023/06/20'>20</a>
│ │ │ └─ <a href='jekyll_site/en/2023/06/20/password-generator.md'>password-generator.md</a>
│ │ └─ <a href='jekyll_site/en/index.md'>index.md</a>
│ ├─ <a href='jekyll_site/img'>img</a>
│ │ ├─ <a href='jekyll_site/img/captcha.png'>captcha.png</a>
│ │ ├─ <a href='jekyll_site/img/circumference-equation.svg'>circumference-equation.svg</a>
│ │ ├─ <a href='jekyll_site/img/heart-graph.png'>heart-graph.png</a>
│ │ ├─ <a href='jekyll_site/img/heart-monospaced-plain-22.bmp'>heart-monospaced-plain-22.bmp</a>
│ │ ├─ <a href='jekyll_site/img/rhombus-equation.svg'>rhombus-equation.svg</a>
│ │ └─ <a href='jekyll_site/img/square-equations.svg'>square-equations.svg</a>
│ ├─ <a href='jekyll_site/js'>js</a>
│ │ └─ <a href='jekyll_site/js/password-generator.js'>password-generator.js</a>
│ ├─ <a href='jekyll_site/ru'>ru</a>
│ │ ├─ <a href='jekyll_site/ru/2023'>2023</a>
│ │ │ ├─ <a href='jekyll_site/ru/2023/01'>01</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/01/03'>03</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/01/03/drawing-simple-captcha.md'>drawing-simple-captcha.md</a>
│ │ │ ├─ <a href='jekyll_site/ru/2023/02'>02</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/02/05'>05</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/02/05/function-graph-in-console.md'>function-graph-in-console.md</a>
│ │ │ ├─ <a href='jekyll_site/ru/2023/03'>03</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/03/08'>08</a>
│ │ │ │ └─ <a href='jekyll_site/ru/2023/03/08/drawing-heart-in-console.md'>drawing-heart-in-console.md</a>
│ │ │ └─ <a href='jekyll_site/ru/2023/06'>06</a>
│ │ │ └─ <a href='jekyll_site/ru/2023/06/19'>19</a>
│ │ │ └─ <a href='jekyll_site/ru/2023/06/19/password-generator.md'>password-generator.md</a>
│ │ └─ <a href='jekyll_site/ru/index.md'>index.md</a>
│ ├─ <a href='jekyll_site/Gemfile_color'>Gemfile_color</a>
│ ├─ <a href='jekyll_site/Gemfile_older'>Gemfile_older</a>
│ ├─ <a href='jekyll_site/_config_color.yml'>_config_color.yml</a>
│ ├─ <a href='jekyll_site/_config_older.yml'>_config_older.yml</a>
│ └─ <a href='jekyll_site/robots.txt'>robots.txt</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='build.sh'>build.sh</a>
├─ <a href='package.sh'>package.sh</a>
└─ <a href='serve.sh'>serve.sh</a>
</pre>

16
README.en.md Normal file
View file

@ -0,0 +1,16 @@
## Website pages
- [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.
## [Source texts](README.md)
- Series of the static websites [«Pomodori»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.en.md).
- Used formats — Markdown, Liquid, YAML.
- Build tool — Jekyll with tomato design themes.
- Automation of processes — Bash scripts for command line.
- [build.sh](build.sh) — Building a site in two tomato themes and optimizing the results.
- [serve.sh](serve.sh) — Local deployment to verify the correctness of the build.
- [package.sh](package.sh) — Preparing an archive for subsequent deployment.

16
README.md Normal file
View file

@ -0,0 +1,16 @@
## Страницы вёб-сайта
- [Генератор паролей](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.
## [Исходные тексты](README.en.md)
- Серия статических вёб-сайтов [«Помидоры»](https://hub.mos.ru/golovin.gg/pomodoro/blob/master/README.md).
- Используемые форматы — Markdown, Liquid, YAML.
- Инструмент сборки — Jekyll с помидорными темами оформления.
- Автоматизация процессов — Bash скрипты для командной строки.
- [build.sh](build.sh) — Сборка сайта в двух помидорных темах и оптимизация результатов.
- [serve.sh](serve.sh) — Локальное развёртывание для проверки корректности сборки.
- [package.sh](package.sh) — Подготовка архива для последующего развёртывания.

54
build.sh Executable file
View file

@ -0,0 +1,54 @@
#!/bin/bash
echo "Сборка сайта в двух помидорных темах и оптимизация результатов."
milliseconds=$(date '+%s%3N')
rm -rf _site
rm -rf _site_older
rm -rf _site_color
echo "Сборка старого помидора."
mkdir -p _site_older
cp -r jekyll_site/_includes _site_older
cp -r jekyll_site/ru _site_older
cp -r jekyll_site/en _site_older
cp -r jekyll_site/ru/index.md _site_older
cp -r jekyll_site/_config_older.yml _site_older/_config.yml
cp -r jekyll_site/Gemfile_older _site_older/Gemfile
cd _site_older || exit
jekyll build
cp -r _site ..
cd ..
echo "Сборка цветного помидора."
mkdir -p _site_color
cp -r jekyll_site/_includes _site_color
cp -r jekyll_site/ru _site_color
cp -r jekyll_site/en _site_color
cp -r jekyll_site/ru/index.md _site_color
cp -r jekyll_site/_config_color.yml _site_color/_config.yml
cp -r jekyll_site/Gemfile_color _site_color/Gemfile
cd _site_color || exit
jekyll build
cp -r _site ../_site/color
cd ..
echo "Копирование без сборки."
cp -r jekyll_site/css _site
cp -r jekyll_site/img _site
cp -r jekyll_site/js _site
cp -r jekyll_site/robots.txt _site
echo "Оптимизация собранного контента."
cd _site || exit
cp -r assets/* .
rm -r assets
rm -r color/assets/favicon.ico
cp -r color/assets/* .
rm -r color/assets
rm -r color/404.html
find . -type f -name '*.html' | sort -r | while read -r file; do
sed -i 's/layout-padding=""/layout-padding/g' "$file"
sed -i 's/ class="language-plaintext highlighter-rouge"//g' "$file"
sed -i 's/ class="language-java highlighter-rouge"//g' "$file"
sed -i 's/ class="language-js highlighter-rouge"//g' "$file"
sed -i 's/<div><div class="highlight"><pre class="highlight">/<div class="highlight"><pre class="highlight">/g' "$file"
sed -i 's/<\/code><\/pre><\/div><\/div>/<\/code><\/pre><\/div>/g' "$file"
sed -i 's/<hr \/>/<hr>/g' "$file"
sed -i -r 's/<img(.+) \/>/<img\1>/g' "$file"
done
echo "Время выполнения сборки: $(("$(date '+%s%3N')" - "$milliseconds")) мс."

View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "jekyll"
gem "color-tomato-theme"

View file

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "jekyll"
gem "older-tomato-theme"

View file

@ -0,0 +1,20 @@
# site parameters
name: "Код с комментариями"
name_translated: "Code with comments"
url: "https://pomodoro5.mircloud.ru"
baseurl: "/color"
homepage_url: "https://git.org.ru/pomodoro/5"
homepage_name: "GIT.ORG.RU"
older_tomato_baseurl: ""
timezone: "Europe/Moscow"
author: "Головин Г.Г."
author_translated: "Golovin G.G."
translation_caption: "translation from Russian"
# build parameters
disable_disk_cache: true
theme: color-tomato-theme
defaults:
- scope:
path: ""
values:
layout: default

View file

@ -0,0 +1,20 @@
# site parameters
name: "Код с комментариями"
name_translated: "Code with comments"
url: "https://pomodoro5.mircloud.ru"
baseurl: ""
homepage_url: "https://git.org.ru/pomodoro/5"
homepage_name: "GIT.ORG.RU"
color_tomato_baseurl: "/color"
timezone: "Europe/Moscow"
author: "Головин Г.Г."
author_translated: "Golovin G.G."
translation_caption: "translation from Russian"
# build parameters
disable_disk_cache: true
theme: older-tomato-theme
defaults:
- scope:
path: ""
values:
layout: default

View file

@ -0,0 +1,2 @@
<noscript><div><img src="https://mc.yandex.ru/watch/91925585" style="position:absolute; left:-9999px;" alt=""></div></noscript>
<!-- /Yandex.Metrika counter -->

View file

@ -0,0 +1,16 @@
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-209134013-5"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-209134013-5');
</script>
<!-- Yandex.Metrika counter -->
<script>
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();for(var j=0;j<document.scripts.length;j++){if(document.scripts[j].src===r){return;}}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window,document,"script","https://mc.yandex.ru/metrika/tag.js","ym");
ym(91925585,"init",{clickmap:true,trackLinks:true,accurateTrackBounce:true,webvisor:true});
</script>

View file

@ -0,0 +1,8 @@
input {
font-size: 100%;
cursor: pointer;
}
md-content input {
color: #1b5e20;
}

View file

@ -0,0 +1,224 @@
---
title: Drawing simple captcha
description: Let's write an algorithm for displaying text as an image using the Java AWT library. Symbols and font can be any, but for this example we will use a...
sections: [Cryptography,Font rendering,Image rotation]
tags: [java,awt,graphics,image,picture,captcha]
canonical_url: /en/2023/01/04/drawing-simple-captcha.html
url_translated: /ru/2023/01/03/drawing-simple-captcha.html
title_translated: Рисуем простую капчу
date: 2023.01.04
lang: en
---
Let's write an algorithm for displaying text as an image using the Java AWT library. Symbols
and font can be any, but for this example we will use a combination of uppercase latin letters
and digits with the *Comic Sans* font we will draw a simple captcha for a website or blog.
{% include picture.html id="captcha.png" src="/img/captcha.png" alt="Drawing simple captcha" %}
We'll consider special characters, but we won't use them, because it will be difficult for the
user to guess them with such a text decoration. For example, the plus `+` is still possible
to guess, but the minus `-` or the underscore `_` is already with difficulty, and even if you
guess right, then to find these buttons with difficulty, especially on the phone. Therefore,
for captcha we'll use a combination of only capital latin letters and digits.
Rendering special characters in a monospaced font: [Drawing heart in console]({{ '/en/2023/03/08/drawing-heart-in-console.html#text-as-picture-and-picture-as-text' | relative_url }}).
## Algorithm description {#algorithm-description}
We prepare an array of symbols consisting of uppercase latin letters and numbers. Then bypass
this array and draw each symbol separately we get a picture. Then rotate the pictures
alternately by ±35 degrees we get an array of pictures with symbols. The second time we
bypass the array with pictures and collect a common image we attach pictures from left
to right, so that the next picture runs over the previous one by 40% of its width.
Why 35 degrees? If we take a larger angle, then it will be difficult for the user to solve
such a captcha. For example, the letters `N` and `Z` will be similar to each other. If we
take a smaller angle, then such a captcha will be easy to solve using machine text recognition.
The imposition of the next picture on the previous one by 40% of its width is necessary, so
that the symbols are located very close or slightly touch each other it also complicates
machine text recognition.
## Font rendering {#font-rendering}
When rendering the font, we will use *anti-aliasing*, otherwise the letters will have jagged
edges. Set the image with transparency support, color black, font *Comic Sans*.
```java
// converting a string with text into a picture with text
private static BufferedImage stringToImage(String str, Font font) {
// font rendering context
FontRenderContext ctx = new FontRenderContext(font.getTransform(), true, true);
// get the dimensions of the picture with text when rendering
Rectangle bnd = font.getStringBounds(str, ctx).getBounds();
// create a new image with transparency support
BufferedImage image = new BufferedImage(bnd.width, bnd.height, BufferedImage.TYPE_INT_ARGB);
// turn on the editing mode of the new image
Graphics2D graphics = image.createGraphics();
// font for rendering
graphics.setFont(font);
// color, that we'll draw with
graphics.setColor(Color.BLACK);
// apply font smoothing when rendering text
graphics.setRenderingHint( // anti-aliasing pixels along the shape border
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// draw a picture with text
graphics.drawString(str, bnd.x, -bnd.y);
// disable the editing mode
graphics.dispose();
// return a picture with text
return image;
}
```
## Image rotation {#image-rotation}
When rotating the image for smoothing, we will use *bilinear interpolation*, otherwise there
will be a lot of unnecessary artifacts along the image borders. On the way, we recalculate
the dimensions for the new image.
```java
// rotate the picture by a given angle and change its dimensions
private static BufferedImage rotateImage(BufferedImage image, double angle) {
// converting degrees to radians
double radian = Math.toRadians(angle);
double sin = Math.abs(Math.sin(radian));
double cos = Math.abs(Math.cos(radian));
// get the dimensions of the current image
int width = image.getWidth();
int height = image.getHeight();
// calculate the dimensions of the new image
int nWidth = (int) Math.floor(width * cos + height * sin);
int nHeight = (int) Math.floor(height * cos + width * sin);
// create a new image with transparency support
BufferedImage rotated = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_ARGB);
// turn on the editing mode of the new image
Graphics2D graphics = rotated.createGraphics();
// apply picture smoothing when rotating
graphics.setRenderingHint( // bilinear interpolation
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// shift the origin of the new image to its center
graphics.translate(nWidth / 2, nHeight / 2);
// rotate the new image with its coordinate system
graphics.rotate(radian);
// put the current image in the new one, so that their centers coincide
graphics.drawImage(image, -width / 2, -height / 2, null);
// disable the editing mode
graphics.dispose();
// return a new image
return rotated;
}
```
## Drawing simple captcha {#drawing-simple-captcha}
We bypass the array of symbols, draw and rotate each symbol separately, on the way calculate
the dimensions for the common image. Create a common image and after that once again bypass
the array of images and add them one by one from left to right to the common image. We return
a pair of objects: the text value of the captcha and the picture with symbols.
```java
// draw an array of symbols, rotate them and merge the results
private static Map.Entry<String, BufferedImage> drawSimpleCaptcha(String[] symbols)
throws IOException, FontFormatException {
Font font = Font // set the font file
.createFont(Font.TRUETYPE_FONT, new File("ComicSansMS.ttf"))
// set the font style and size
.deriveFont(Font.BOLD, 32);
// dimensions of the final image
int width = 0, height = 0;
// prepare an image array
BufferedImage[] images = new BufferedImage[symbols.length];
// bypass the array of symbols, get pictures and
// calculate the dimensions of the final image
for (int i = 0; i < symbols.length; i++) {
if (i % 2 == 0) // draw the symbols and rotate the images
images[i] = rotateImage(stringToImage(symbols[i], font), 35);
else
images[i] = rotateImage(stringToImage(symbols[i], font), -35);
// dimensions of the picture with the current symbol
int h = images[i].getHeight(), w = images[i].getWidth();
// height of the largest symbol
height = Math.max(height, h);
// we'll shift the next symbol by 40% of the previous one's width
if (i < symbols.length - 1)
width += w * 6 / 10; // take 60% of the current symbol's width
else // take the last symbol's width entirely
width += w;
}
// create a new image with transparency support
BufferedImage captcha = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// turn on the editing mode of the new image
Graphics2D graphics = captcha.createGraphics();
// bypass the array of images and add them to the common image from left to right
for (BufferedImage image : images) {
// draw the current symbol at the origin
graphics.drawImage(image, 0, 0, null);
// shift the origin by 60% of the current symbol's width
graphics.translate(image.getWidth() * 6 / 10, 0);
}
// disable the editing mode
graphics.dispose();
// pair of objects: the text value of the captcha and the picture with symbols
return Map.entry(String.join("", symbols), captcha);
}
```
{% capture collapsed_md %}
```java
// method for outer calls, returns a random combination of 5 symbols
public static Map.Entry<String, BufferedImage> drawSimpleCaptcha()
throws IOException, FontFormatException {
return drawSimpleCaptcha(5);
}
```
```java
// method for outer calls, string length required
public static Map.Entry<String, BufferedImage> drawSimpleCaptcha(int length)
throws IOException, FontFormatException {
// получаем случайную комбинацию символов указанной длины
String[] symbols = getRandomString(length);
return drawSimpleCaptcha(symbols);
}
```
```java
// get a random combination of uppercase latin letters and numbers
private static String[] getRandomString(int length) {
String[] symbols = new String[length];
Random random = new Random();
for (int i = 0; i < length; i++) {
// 26 capital letters and 10 digits
int rnd = random.nextInt(36);
if (rnd < 26) // letters [A..Z]
symbols[i] = Character.toString('A' + rnd);
else // digits [0..9]
symbols[i] = Character.toString('0' + rnd - 26);
}
return symbols;
}
```
{% endcapture %}
{%- include collapsed_block.html summary="Additional methods" content=collapsed_md -%}
## Testing and launching {#testing-n-launching}
The algorithm turned out to be universal it can render almost any string and in almost any
font, but with a long list of exceptions, related to unicode symbol ranges and font types. There
are many variants, testing takes a long time, and the simplified model suits me quite well.
To complete this example for visualization, let's draw a line: `SIMPLE+CAPTCHA+1+1`.
```java
// start the program and output the result
public static void main(String[] args) throws IOException, FontFormatException {
String[] symbols = "simple+captcha+1+1".toUpperCase().split("");
// Map.Entry<String, BufferedImage> captcha = drawSimpleCaptcha(18);
Map.Entry<String, BufferedImage> captcha = drawSimpleCaptcha(symbols);
// save image to file, text to console
ImageIO.write(captcha.getValue(), "png", new File("captcha.png"));
// System.out.println(captcha.getKey());
}
```
See the picture from this code above: [captcha.png](#captcha.png).

View file

@ -0,0 +1,147 @@
---
title: Function graph in console
description: Let's write an algorithm to output a graph of a function or a system of equations to the console in the form of text. We will use Java tools. For calculations.
sections: [Geometric figures,Text image]
tags: [java,math,fdlibm,console,rhombus,square,circumference,circle,text,image]
canonical_url: /en/2023/02/06/function-graph-in-console.html
url_translated: /ru/2023/02/05/function-graph-in-console.html
title_translated: График функции в консоли
date: 2023.02.06
lang: en
---
Let's write an algorithm to output a graph of a function or a system of equations to the console
in the form of text. We will use Java tools. For calculations, we will use the `Math` class, and
to bypass the range of coordinates, we will use two nested `for` loops. We draw in the console a
graph of a circle and graphs of a rhombus and a square inscribed in it.
Graph of a function with filling: [Drawing heart in console]({{ '/en/2023/03/08/drawing-heart-in-console.html' | relative_url }}).
### Equations of functions {#equations-of-functions}
We will check each point `(x,y)` from the output range of coordinates for belonging to function
graphs and output in accordance with this. We define the parameters of the functions and the
output range in advance before the start of bypass.
*Rhombus*.
{% include image_svg.html src="/img/rhombus-equation.svg"
style="width: 129.297pt; height: 14.944pt;"
alt="|x-a|+|y-b|=r." %}
*Square*.
{% include image_svg.html src="/img/square-equations.svg"
style="width: 167.599pt; height: 62.7502pt;"
alt="\begin{cases}|x-a|=c\land|y-b|\leqslant c,\\|y-b|=c\land|x-a|\leqslant c,\\c=r\times1/\sqrt2.\end{cases}" %}
*Circle*.
{% include image_svg.html src="/img/circumference-equation.svg"
style="width: 162.53pt; height: 17.9328pt;"
alt="\sqrt{(x-a)^2+(y-b)^2}=r." %}
*Parameters*.
`r` circle radius;
`(a,b)` figure center;
`c` half a side of a square.
### Mathematical operations {#mathematical-operations}
To perform *basic* mathematical operations, Java uses the `FdLibm` library *Freely Distributable
Math Library*. Most of the methods are implemented at the platform level to increase performance.
We will refer to them through the `Math` class.
For floating point calculations and rounding of results, we will use the methods of the `Math` class.
`abs(a)` absolute value of the argument `a`;
`pow(a,b)` raising the argument `a` to the power of the argument `b`;
`sqrt(a)` square root of the argument `a`;
`ceil(a)` rounding up the argument `a`;
`floor(a)` rounding down the argument `a`.
### Algorithm description {#algorithm-description}
We take a range of coordinates on the plane in such a way that the displayed figure completely fits
in the printing area. We bypass the selected range with two nested `for` loops: first along the `y`
axis and then along the `x` axis. We check each point for belonging to the graphs of functions and
output. For clarity, we also output the coordinate axes, the origin of coordinates and the center
of the figure.
```java
// radius, figure center, offset
int r=12, a=5, b=-1, gap=2;
// boundaries of the text image
int xMin=a-r-gap, xMax=a+r+gap;
int yMin=b-r-gap, yMax=b+r+gap;
// half a side of an inscribed square
double c = Math.ceil(r/Math.sqrt(2));
// output the title
System.out.println("Radius: "+r+"; center: 0("+a+","+b+").");
// output to the console line by line from left to right from top to bottom
for (int y = yMax; y >= yMin; y--) {
for (int x = xMin; x <= xMax; x++) {
// check each point for belonging to the graphs and output
if (Math.abs(x-a) + Math.abs(y-b) == r)
System.out.print("z "); // rhombus
else if (Math.abs(x-a) == c && Math.abs(y-b) <= c
|| Math.abs(y-b) == c && Math.abs(x-a) <= c)
System.out.print("* "); // square
else if (Math.floor(Math.sqrt(Math.pow(x-a,2)+Math.pow(y-b,2))) == r)
System.out.print("o "); // circle
else if (y == b && x == a)
System.out.print("0 "); // figure center
else if (y == 0 && x == 0)
System.out.print("+-"); // origin of coordinates
else if (y == 0) // abscissa axis (x)
System.out.print(x == xMax ? ">x" : "--");
else if (x == 0) // ordinate axis (y)
System.out.print(y == yMax ? "↑y" : "¦ ");
else // empty place
System.out.print(" ");
} // transition to a new line
System.out.println();
}
```
Text image in console.
```
Radius: 12; center: 0(5,-1).
y
¦
¦ o o o o z o o o o
o o z z o o
o o ¦ z z o o
* * * * * * z * * * * * z * * * * * *
o * ¦ z z * o
o * z z * o
o * z ¦ z * o
o * z ¦ z * o
o * z ¦ z * o
o z ¦ z o
o z * ¦ * z o
----o z --* ------+---------------------------* --z o -->x
z * ¦ 0 * z
o z * ¦ * z o
o z * ¦ * z o
o z ¦ z o
o * z ¦ z * o
o * z ¦ z * o
o * z ¦ z * o
o * z z * o
o * ¦ z z * o
* * * * * * z * * * * * z * * * * * *
o o ¦ z z o o
o o z z o o
¦ o o o o z o o o o
¦
¦
```

View file

@ -0,0 +1,304 @@
---
title: Drawing heart in console
description: Let's write two versions of the algorithm in Java to output a heart to the console in the form of a text image let's congratulate women on the eighth of...
sections: [Geometric figures,Font rendering,Text image]
tags: [java,awt,console,rhombus,circumference,circle,text,image,font]
canonical_url: /en/2023/03/08/drawing-heart-in-console.html
url_translated: /ru/2023/03/08/drawing-heart-in-console.html
title_translated: Рисуем сердечко в консоли
date: 2023.03.08
lang: en
---
Let's write two versions of the algorithm in Java to output a heart to the console in the form
of a text image let's congratulate women on the eighth of March. Let's draw a graph of the
function in the form of a heart and, in addition, draw the symbol *heart* in the form of a
picture, and output the picture as text console congratulations on the eighth of March.
## Heart shaped graph {#heart-shaped-graph}
Let's draw two half-circles and one half-rhombus, filled inside and outside. In the previous example,
we output a [function graph to console]({{ '/en/2023/02/06/function-graph-in-console.html' | relative_url }})
we take the formulas for the circle and for the rhombus from it, and in this example, to fill the
figure inside, in the formula instead of the *equals* sign we substitute the *less* sign, and to
fill the outside, on the contrary, the *greater* sign. There will be many conditions, unlike the
previous example.
Let's draw a picture for clarity.
{% include picture.html src="/img/heart-graph.png" background=true
alt="Heart shaped graph — is two half-circles and one half-rhombus"
caption="Two half-circles and one half-rhombus" %}
We output the upper part of the figure, the lower part of the figure, paint over in a
checkerboard pattern and output the coordinate axes. We get several text images that
look like this.
```
Radius: 5, in/out/axes: true/true/true.
· · · · · y · · · · ·
· · o o o o o · ¦ · o o o o o · ·
· o * * o · o * * o ·
· o * * * o ¦ o * * * o ·
o * * * * o * * * * o
· o * * * * * o * * * * * o ·
--o --* --* --* --* --+---* --* --* --* --o >x
· o * * * * ¦ * * * * o ·
· o * * * * * * * o ·
· · o * * * ¦ * * * o · ·
· · o * * * * * o · ·
· · · o * * ¦ * * o · · ·
· · · o * * * o · · ·
· · · · o * ¦ * o · · · ·
· · · · o * o · · · ·
· · · · · o ¦ o · · · · ·
· · · · · o · · · · ·
· · · · · · ¦ · · · · · ·
```
{% capture collapsed_md %}
```
Radius: 4, in/out/axes: false/true/false.
· · · · · · · · · ·
· o o o o o · o o o o o ·
· o o o o o o o o ·
o o o o o o o
· o o o ·
o o
· o o ·
· o o ·
· · o o · ·
· · o o · ·
· · · o o · · ·
· · · o o · · ·
· · · · o o · · · ·
· · · · o · · · ·
· · · · · · · · · ·
```
```
Radius: 3, in/out/axes: true/false/false.
o o o o o o
o * * o o * * o
o * * * o * * * o
o * * * * * o
o * * * * o
o * * * o
o * * o
o * o
o o
o
```
```
Radius: 2, in/out/axes: false/false/false.
o o o o o o
o o o
o o
o o
o o
o o
o
```
{% endcapture %}
{%- include collapsed_block.html summary="Full output" content=collapsed_md -%}
We bypass the coordinate range with two nested `for` loops: first along the `y` axis and then along
the `x` axis. We check each point for compliance with the conditions and output it. In the upper part
we draw two half-circles and optionally paint over them inside/outside. In the lower part we draw a
half-rhombus and also optionally paint over inside/outside.
```java
/**
* @param r radius
* @param gap offset
* @param in filling inside
* @param out filling outside
* @param axes coordinate axes
*/
public static void printHeartGraph(
int r, int gap, boolean in, boolean out, boolean axes) {
// boundaries of the text image
int xMax = 2*r+gap, xMin = -xMax;
int yMax = r+gap, yMin = -r-yMax;
System.out.println( // header with parameters
"Radius: "+r+", in/out/axes: "+in+"/"+out+"/"+axes+".");
// output to the console line by line from left to right from top to bottom
for (int y = yMax; y >= yMin; y--) {
for (int x = xMin; x <= xMax; x++) {
double[] circle = { // two circles left/right
Math.round(Math.sqrt(Math.pow(x+r,2)+Math.pow(y,2))), // left
Math.round(Math.sqrt(Math.pow(x-r,2)+Math.pow(y,2)))}; // right
int rhombus = Math.abs(x)+Math.abs(y); // rhombus
boolean inCh = in && (x+y)%2 == 0; // checkerboard pattern inside
boolean outCh = out && (x+y)%2 == 0; // checkerboard pattern outside
// check each point for compliance with the conditions and output it
if (axes && y == 0 && x == 0)
System.out.print("+-"); // origin of coordinates
else if (axes && y == 0 && x == xMax)
System.out.print(">x"); // maximum of abscissa axis (x)
else if (axes && x == 0 && y == yMax)
System.out.print("↑y"); // maximum of ordinate axis (y)
else if (y > 0 && (circle[0] == r || circle[1] == r))
System.out.print("o "); // two half circles, top
else if (y > 0 && inCh && (circle[0] < r || circle[1] < r))
System.out.print("* "); // top inside
else if (y > 0 && outCh && (circle[0] > r && circle[1] > r))
System.out.print("· "); // top outside
else if (y <= 0 && rhombus == 2*r)
System.out.print("o "); // half rhombus, bottom
else if (y <= 0 && inCh && rhombus < 2*r)
System.out.print("* "); // bottom inside
else if (y <= 0 && outCh && rhombus > 2*r)
System.out.print("· "); // bottom outside
else if (axes && y == 0)
System.out.print("--"); // abscissa axis (x)
else if (axes && x == 0)
System.out.print("¦ "); // ordinate axis (y)
else
System.out.print(" "); // empty space
} // transition to a new line
System.out.println();
}
}
```
```java
// execute the program and output the result
public static void main(String[] args) {
printHeartGraph(5, 1, true, true, true);
printHeartGraph(4, 1, false, true, false);
printHeartGraph(3, 0, true, false, false);
printHeartGraph(2, 0, false, false, false);
}
```
## Text as picture and picture as text {#text-as-picture-and-picture-as-text}
In the previous example we [drew a simple captcha]({{ '/en/2023/01/04/drawing-simple-captcha.html' | relative_url }})
we take the font rendering algorithm from it, only this time we draw a binary black-and-white
image in a monospaced font, we do not use anti-aliasing. The symbol *heart* in the form of a
picture looks like this.
{% include picture.html src="/img/heart-monospaced-plain-22.bmp"
alt="Symbol heart, monospaced font, plain, 22"
title="Symbol heart, monospaced font, plain, 22" %}
Since the character is in the middle of the line, half of the pixels in the resulting image are empty.
We bypass the pixels line by line and output only non-empty lines, that is the central part of the image.
```
Monospaced.plain, 22, symbols:
o o o
o o o o o o o
o o o o
o o o
o o o
o o
o o
o o
o o
o o
o o
o o
o o
o
```
{% capture collapsed_md %}
```
Monospaced.plain, 28, symbols:
o o
o o o o o o o o
o o o o
o o o o
o o o
o o o
o o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o
```
```
Monospaced.plain, 36, symbols:
o o o o o o o
o o o o o o o
o o o o
o o o o
o o o o
o o o
o o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
```
{% endcapture %}
{%- include collapsed_block.html summary="Full output" content=collapsed_md -%}
We draw a line of text as a black-and-white image, then iterate over the pixels of this image
and print them as text to the console line by line. We draw only the central part of the image
with text, do not display empty lines of pixels.
```java
// draw a text in the form of a picture and a picture in the form of a text
public static void printTextImage(String str, Font font) {
FontRenderContext ctx = // font rendering context
new FontRenderContext(font.getTransform(), false, false);
// get the dimensions of the picture with text when rendering
Rectangle bnd = font.getStringBounds(str, ctx).getBounds();
// create a new binary black-and-white image
BufferedImage image = new BufferedImage(
bnd.width, bnd.height, BufferedImage.TYPE_BYTE_BINARY);
// turn on the editing mode of the new image
Graphics2D graphics = image.createGraphics();
// font for rendering, do not use anti-aliasing
graphics.setFont(font);
// draw a picture with text
graphics.drawString(str, bnd.x, -bnd.y);
// disable the editing mode
graphics.dispose();
// output the header
System.out.println(
font.getFontName()+", "+font.getSize()+", symbols: "+str);
// bypass the pixels line by line and output non-empty lines
for (int y = 0; y < bnd.height; y++) {
StringBuilder line = new StringBuilder();
for (int x = 0; x < bnd.width; x++)
line.append(image.getRGB(x, y) == -1 ? "o " : " ");
// draw only non-empty lines
if (line.indexOf("o") != -1) System.out.println(line);
}
}
```
```java
// execute the program and output the result
public static void main(String[] args) {
printTextImage("", new Font(Font.MONOSPACED, Font.PLAIN, 22));
printTextImage("", new Font(Font.MONOSPACED, Font.PLAIN, 28));
printTextImage("", new Font(Font.MONOSPACED, Font.PLAIN, 36));
}
```
The last example uses the Java AWT library.
{% capture collapsed_md %}
```java
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
```
{% endcapture %}
{%- include collapsed_block.html summary="Required imports" content=collapsed_md -%}

View file

@ -0,0 +1,90 @@
---
title: Password generator
description: We write a program in JavaScript for the formation of random 20-symbol combinations of latin letters, numbers and special characters. There are 60 variants...
sections: [Cryptography,Random combinations]
tags: [javascript,text,symbols,letters,digits,characters,combinations]
scripts: [/js/password-generator.js]
styles: [/css/pomodoro5.css]
canonical_url: /en/2023/06/20/password-generator.html
url_translated: /ru/2023/06/19/password-generator.html
title_translated: Генератор паролей
date: 2023.06.20
lang: en
---
We write a program in JavaScript for the formation of random 20-symbol combinations of latin letters,
numbers and special characters. There are 60 variants to choose from 4 columns of 15 rows. First
character is always a letter, all characters in each combination go without repetitions. We will
generate passwords for web-sites in the browser.
<div>
<input type="button" value="Refresh" title="Refresh combinations" onclick="refresh()">
</div>
<div class="highlight">
<pre class="highlight">
<code id="combinations"></code>
</pre>
</div>
We use symbols in the range from `!` to `~` and their decimal codes from `33` to `126`.
{% capture collapsed_md %}
```
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 :
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
; < = > ? @ A B C D E F G H I J K L M N O P Q R S T
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
l m n o p q r s t u v w x y z { | } ~
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
```
{% endcapture %}
{%- include collapsed_block.html summary="Table of symbols" content=collapsed_md -%}
Three nested loops: by rows, by columns and by combinations. We get a random number character code
in the range `[33-126]`, then we check for compliance with the conditions and add to the combination.
First character is a letter, all characters in each combination go without repetitions. We escape
characters `&`, `>` and `<` for correct display in browser. We gather 15 lines, 4 combinations in
each line.
```js
// gathering combinations for the web-site
const generate = function() {
let text = "";
for (let row = 0; row < 15; row++) {
let line = "";
for (let col = 0; col < 4; col++) {
let combo = "";
for (let len = 0; len < 20; len = combo.length) {
const co = random("!".charCodeAt(0), "~".charCodeAt(0));
const ch = String.fromCharCode(co);
if (len == 0 && (ch >= "A" && ch <= "Z" || ch >= "a" && ch <= "z")
|| len > 0 && combo.indexOf(ch) < 0)
combo += ch;
}
line += escapeHTML(combo) + " ";
}
text += line + (row < 14 ? "\n" : "");
}
return text;
}
```
```js
// get a random number in a given range
const random = (min, max) => Math.round(min + (max-min) * Math.random());
// escape HTML special characters for correct display in the browser
const escapeHTML = (str) => str.replace("&", "&amp;").replace(">", "&gt;").replace("<", "&lt;");
// button on the page — refresh combinations
const refresh = () => document.getElementById("combinations").innerHTML = generate();
// after loading all parts of the page — refresh combinations
document.addEventListener("DOMContentLoaded", refresh);
```
I have been using this algorithm for a long time I have all passwords for web-sites generated by
this scheme, so I recommend it. The first version was written in Java, but for web-sites it turns
out easier in JavaScript, so as not to go far.

50
jekyll_site/en/index.md Normal file
View file

@ -0,0 +1,50 @@
---
title: Code with comments
description: Notes about programming with code snippets and comments. Problem solutions and solution descriptions.
sections: [Problem solutions and solution descriptions]
tags: [java,javascript,algorithms,implementation,text,fonts,combinations,images,pictures,cryptography]
canonical_url: /en/
url_translated: /ru/
title_translated: Код с комментариями
lang: en
---
{%- assign articles = "" | split: "" %}
{%- assign articles = articles | push: "Password generator" %}
{%- capture article_brief %}
We write a program in JavaScript for the formation of random 20-symbol combinations of latin letters,
numbers and special characters. There are 60 variants to choose from 4 columns of 15 rows. First
character is always a letter, all characters in each combination go without repetitions. We will
generate passwords for web-sites in the browser.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Drawing heart in console" %}
{%- capture article_brief %}
Let's write two versions of the algorithm in Java to output a heart to the console in the form
of a text image let's congratulate women on the eighth of March. Let's draw a graph of the
function in the form of a heart and, in addition, draw the symbol *heart* in the form of a
picture, and output the picture as text console congratulations on the eighth of March.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Function graph in console" %}
{%- capture article_brief %}
Let's write an algorithm to output a graph of a function or a system of equations to the console
in the form of text. We will use Java tools. For calculations, we will use the `Math` class, and
to bypass the range of coordinates, we will use two nested `for` loops. We draw in the console a
graph of a circle and graphs of a rhombus and a square inscribed in it.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Drawing simple captcha" %}
{%- capture article_brief %}
Let's write an algorithm for displaying text as an image using the Java AWT library. Symbols
and font can be any, but for this example we will use a combination of uppercase latin letters
and digits with the *Comic Sans* font we will draw a simple captcha for a website or blog.
We'll consider special characters, but we won't use them, because it will be difficult for the
user to guess them with such a text decoration. For example, the plus `+` is still possible
to guess, but the minus `-` or the underscore `_` is already with difficulty, and even if you
guess right, then to find these buttons with difficulty, especially on the phone. Therefore,
for captcha we'll use a combination of only capital latin letters and digits.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- include main_page.html articles = articles -%}

BIN
jekyll_site/img/captcha.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

View file

@ -0,0 +1,38 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="162.53pt" height="17.9328pt" viewBox="209.451 101.089 162.53 17.9328">
<defs>
<path d="M3.88543 2.90511C3.88543 2.86924 3.88543 2.84533 3.68219 2.64209C2.48667 1.43462 1.81719 -0.537983 1.81719 -2.97684C1.81719 -5.29614 2.37908 -7.29265 3.76588 -8.70336C3.88543 -8.81096 3.88543 -8.83487 3.88543 -8.87073C3.88543 -8.94247 3.82565 -8.96638 3.77783 -8.96638C3.62242 -8.96638 2.64209 -8.1056 2.05629 -6.934C1.44658 -5.72653 1.17161 -4.44732 1.17161 -2.97684C1.17161 -1.91283 1.33898 -0.490162 1.96065 0.789041C2.666 2.22366 3.64633 3.00075 3.77783 3.00075C3.82565 3.00075 3.88543 2.97684 3.88543 2.90511Z" id="g4-40"/>
<path d="M3.37136 -2.97684C3.37136 -3.88543 3.25181 -5.36787 2.58232 -6.75467C1.87696 -8.18929 0.896638 -8.96638 0.765131 -8.96638C0.71731 -8.96638 0.657534 -8.94247 0.657534 -8.87073C0.657534 -8.83487 0.657534 -8.81096 0.860772 -8.60772C2.05629 -7.40025 2.72578 -5.42765 2.72578 -2.98879C2.72578 -0.669489 2.16389 1.32702 0.777086 2.73773C0.657534 2.84533 0.657534 2.86924 0.657534 2.90511C0.657534 2.97684 0.71731 3.00075 0.765131 3.00075C0.920548 3.00075 1.90087 2.13998 2.48667 0.968369C3.09639 -0.251059 3.37136 -1.54222 3.37136 -2.97684Z" id="g4-41"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g4-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M5.06899 13.868C5.4396 13.868 5.45156 13.856 5.57111 13.6289L12.1106 -0.0239103C12.1943 -0.179328 12.1943 -0.203238 12.1943 -0.239103C12.1943 -0.37061 12.0986 -0.478207 11.9552 -0.478207C11.7998 -0.478207 11.7519 -0.37061 11.6922 -0.239103L5.52329 12.6247L2.97684 6.69489L1.31507 7.9741L1.4944 8.16538L2.34321 7.5198L5.06899 13.868Z" id="g0-112"/>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g1-0"/>
<path d="M2.24757 -1.6259C2.37509 -1.74545 2.70984 -2.00847 2.83736 -2.12005C3.33151 -2.57435 3.80174 -3.0127 3.80174 -3.73798C3.80174 -4.68643 3.00473 -5.30012 2.00847 -5.30012C1.05205 -5.30012 0.422416 -4.57484 0.422416 -3.8655C0.422416 -3.47497 0.73325 -3.41918 0.844832 -3.41918C1.0122 -3.41918 1.25928 -3.53873 1.25928 -3.84159C1.25928 -4.25604 0.860772 -4.25604 0.765131 -4.25604C0.996264 -4.83786 1.53026 -5.03711 1.9208 -5.03711C2.66202 -5.03711 3.04458 -4.40747 3.04458 -3.73798C3.04458 -2.90909 2.46276 -2.30336 1.52229 -1.33898L0.518057 -0.302864C0.422416 -0.215193 0.422416 -0.199253 0.422416 0H3.57061L3.80174 -1.42665H3.55467C3.53076 -1.26725 3.467 -0.868742 3.37136 -0.71731C3.32354 -0.653549 2.71781 -0.653549 2.59029 -0.653549H1.17161L2.24757 -1.6259Z" id="g3-50"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g2-58"/>
<path d="M3.59851 -1.42267C3.53873 -1.21943 3.53873 -1.19552 3.37136 -0.968369C3.10834 -0.633624 2.58232 -0.119552 2.02042 -0.119552C1.53026 -0.119552 1.25529 -0.561893 1.25529 -1.26725C1.25529 -1.92478 1.6259 -3.26376 1.85305 -3.76588C2.25953 -4.60274 2.82142 -5.03313 3.28767 -5.03313C4.07671 -5.03313 4.23213 -4.0528 4.23213 -3.95716C4.23213 -3.94521 4.19626 -3.78979 4.18431 -3.76588L3.59851 -1.42267ZM4.36364 -4.48319C4.23213 -4.79402 3.90934 -5.27223 3.28767 -5.27223C1.93674 -5.27223 0.478207 -3.52677 0.478207 -1.75741C0.478207 -0.573848 1.17161 0.119552 1.98456 0.119552C2.64209 0.119552 3.20399 -0.394521 3.53873 -0.789041C3.65828 -0.0836862 4.22017 0.119552 4.57883 0.119552S5.22441 -0.0956413 5.4396 -0.526027C5.63088 -0.932503 5.79826 -1.66177 5.79826 -1.70959C5.79826 -1.76936 5.75044 -1.81719 5.6787 -1.81719C5.57111 -1.81719 5.55915 -1.75741 5.51133 -1.57808C5.332 -0.872727 5.10486 -0.119552 4.61469 -0.119552C4.268 -0.119552 4.24408 -0.430386 4.24408 -0.669489C4.24408 -0.944458 4.27995 -1.07597 4.38755 -1.54222C4.47123 -1.8411 4.53101 -2.10411 4.62665 -2.45081C5.06899 -4.24408 5.17659 -4.67447 5.17659 -4.7462C5.17659 -4.91357 5.04508 -5.04508 4.86575 -5.04508C4.48319 -5.04508 4.38755 -4.62665 4.36364 -4.48319Z" id="g2-97"/>
<path d="M2.76164 -7.99801C2.7736 -8.04583 2.79751 -8.11756 2.79751 -8.17733C2.79751 -8.29689 2.67796 -8.29689 2.65405 -8.29689C2.64209 -8.29689 2.21171 -8.26102 1.99651 -8.23711C1.79328 -8.22516 1.61395 -8.20125 1.39875 -8.18929C1.11183 -8.16538 1.02814 -8.15342 1.02814 -7.93823C1.02814 -7.81868 1.1477 -7.81868 1.26725 -7.81868C1.87696 -7.81868 1.87696 -7.71108 1.87696 -7.59153C1.87696 -7.50785 1.78132 -7.16115 1.7335 -6.94595L1.44658 -5.79826C1.32702 -5.32005 0.645579 -2.60623 0.597758 -2.39103C0.537983 -2.09215 0.537983 -1.88892 0.537983 -1.7335C0.537983 -0.514072 1.21943 0.119552 1.99651 0.119552C3.38331 0.119552 4.81793 -1.66177 4.81793 -3.39527C4.81793 -4.49514 4.19626 -5.27223 3.29963 -5.27223C2.67796 -5.27223 2.11606 -4.75816 1.88892 -4.51905L2.76164 -7.99801ZM2.00847 -0.119552C1.6259 -0.119552 1.20747 -0.406476 1.20747 -1.33898C1.20747 -1.7335 1.24334 -1.96065 1.45853 -2.79751C1.4944 -2.95293 1.68568 -3.71806 1.7335 -3.87347C1.75741 -3.96912 2.46276 -5.03313 3.27572 -5.03313C3.80174 -5.03313 4.04085 -4.5071 4.04085 -3.88543C4.04085 -3.31158 3.7061 -1.96065 3.40722 -1.33898C3.10834 -0.6934 2.55841 -0.119552 2.00847 -0.119552Z" id="g2-98"/>
<path d="M4.65056 -4.88966C4.27995 -4.81793 4.08867 -4.55492 4.08867 -4.29191C4.08867 -4.00498 4.31582 -3.90934 4.48319 -3.90934C4.81793 -3.90934 5.0929 -4.19626 5.0929 -4.55492C5.0929 -4.93748 4.72229 -5.27223 4.12453 -5.27223C3.64633 -5.27223 3.09639 -5.05704 2.59427 -4.32777C2.51059 -4.96139 2.03238 -5.27223 1.55417 -5.27223C1.08792 -5.27223 0.848817 -4.91357 0.705355 -4.65056C0.502117 -4.22017 0.32279 -3.50286 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.812951 -4.33973 1.0401 -5.03313 1.51831 -5.03313C1.80523 -5.03313 1.88892 -4.82989 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.33898 0.119552 1.56613 0.0358655 1.63786 -0.203238C1.67372 -0.298879 2.11606 -2.10411 2.1878 -2.37908C2.24757 -2.64209 2.3193 -2.89315 2.37908 -3.15616C2.4269 -3.32354 2.47472 -3.51482 2.51059 -3.67024C2.54645 -3.77783 2.86924 -4.36364 3.16812 -4.62665C3.31158 -4.75816 3.62242 -5.03313 4.11258 -5.03313C4.30386 -5.03313 4.49514 -4.99726 4.65056 -4.88966Z" id="g2-114"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g2-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g2-121"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.25 0 0 1.25 0 0)">
<use x="167.561" xlink:href="#g0-112" y="81.349"/>
<rect height="0.478187" width="95.2263" x="179.516" y="80.8709"/>
<use x="179.516" xlink:href="#g4-40" y="92.1544"/>
<use x="184.051" xlink:href="#g2-120" y="92.1544"/>
<use x="193.335" xlink:href="#g1-0" y="92.1544"/>
<use x="205.256" xlink:href="#g2-97" y="92.1544"/>
<use x="211.378" xlink:href="#g4-41" y="92.1544"/>
<use x="215.913" xlink:href="#g3-50" y="88.7007"/>
<use x="223.302" xlink:href="#g4-43" y="92.1544"/>
<use x="235.029" xlink:href="#g4-40" y="92.1544"/>
<use x="239.565" xlink:href="#g2-121" y="92.1544"/>
<use x="248.337" xlink:href="#g1-0" y="92.1544"/>
<use x="260.257" xlink:href="#g2-98" y="92.1544"/>
<use x="265.216" xlink:href="#g4-41" y="92.1544"/>
<use x="269.751" xlink:href="#g3-50" y="88.7007"/>
<use x="278.063" xlink:href="#g4-61" y="92.1544"/>
<use x="290.455" xlink:href="#g2-114" y="92.1544"/>
<use x="295.385" xlink:href="#g2-58" y="92.1544"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

View file

@ -0,0 +1,31 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="129.297pt" height="14.944pt" viewBox="225.917 103.985 129.297 14.944">
<defs>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g0-0"/>
<path d="M1.90087 -8.53599C1.90087 -8.75118 1.90087 -8.96638 1.66177 -8.96638S1.42267 -8.75118 1.42267 -8.53599V2.55841C1.42267 2.7736 1.42267 2.98879 1.66177 2.98879S1.90087 2.7736 1.90087 2.55841V-8.53599Z" id="g0-106"/>
<path d="M4.77011 -2.76164H8.06974C8.23711 -2.76164 8.4523 -2.76164 8.4523 -2.97684C8.4523 -3.20399 8.24907 -3.20399 8.06974 -3.20399H4.77011V-6.50361C4.77011 -6.67098 4.77011 -6.88618 4.55492 -6.88618C4.32777 -6.88618 4.32777 -6.68294 4.32777 -6.50361V-3.20399H1.02814C0.860772 -3.20399 0.645579 -3.20399 0.645579 -2.98879C0.645579 -2.76164 0.848817 -2.76164 1.02814 -2.76164H4.32777V0.537983C4.32777 0.705355 4.32777 0.920548 4.54296 0.920548C4.77011 0.920548 4.77011 0.71731 4.77011 0.537983V-2.76164Z" id="g2-43"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g2-61"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g1-58"/>
<path d="M3.59851 -1.42267C3.53873 -1.21943 3.53873 -1.19552 3.37136 -0.968369C3.10834 -0.633624 2.58232 -0.119552 2.02042 -0.119552C1.53026 -0.119552 1.25529 -0.561893 1.25529 -1.26725C1.25529 -1.92478 1.6259 -3.26376 1.85305 -3.76588C2.25953 -4.60274 2.82142 -5.03313 3.28767 -5.03313C4.07671 -5.03313 4.23213 -4.0528 4.23213 -3.95716C4.23213 -3.94521 4.19626 -3.78979 4.18431 -3.76588L3.59851 -1.42267ZM4.36364 -4.48319C4.23213 -4.79402 3.90934 -5.27223 3.28767 -5.27223C1.93674 -5.27223 0.478207 -3.52677 0.478207 -1.75741C0.478207 -0.573848 1.17161 0.119552 1.98456 0.119552C2.64209 0.119552 3.20399 -0.394521 3.53873 -0.789041C3.65828 -0.0836862 4.22017 0.119552 4.57883 0.119552S5.22441 -0.0956413 5.4396 -0.526027C5.63088 -0.932503 5.79826 -1.66177 5.79826 -1.70959C5.79826 -1.76936 5.75044 -1.81719 5.6787 -1.81719C5.57111 -1.81719 5.55915 -1.75741 5.51133 -1.57808C5.332 -0.872727 5.10486 -0.119552 4.61469 -0.119552C4.268 -0.119552 4.24408 -0.430386 4.24408 -0.669489C4.24408 -0.944458 4.27995 -1.07597 4.38755 -1.54222C4.47123 -1.8411 4.53101 -2.10411 4.62665 -2.45081C5.06899 -4.24408 5.17659 -4.67447 5.17659 -4.7462C5.17659 -4.91357 5.04508 -5.04508 4.86575 -5.04508C4.48319 -5.04508 4.38755 -4.62665 4.36364 -4.48319Z" id="g1-97"/>
<path d="M2.76164 -7.99801C2.7736 -8.04583 2.79751 -8.11756 2.79751 -8.17733C2.79751 -8.29689 2.67796 -8.29689 2.65405 -8.29689C2.64209 -8.29689 2.21171 -8.26102 1.99651 -8.23711C1.79328 -8.22516 1.61395 -8.20125 1.39875 -8.18929C1.11183 -8.16538 1.02814 -8.15342 1.02814 -7.93823C1.02814 -7.81868 1.1477 -7.81868 1.26725 -7.81868C1.87696 -7.81868 1.87696 -7.71108 1.87696 -7.59153C1.87696 -7.50785 1.78132 -7.16115 1.7335 -6.94595L1.44658 -5.79826C1.32702 -5.32005 0.645579 -2.60623 0.597758 -2.39103C0.537983 -2.09215 0.537983 -1.88892 0.537983 -1.7335C0.537983 -0.514072 1.21943 0.119552 1.99651 0.119552C3.38331 0.119552 4.81793 -1.66177 4.81793 -3.39527C4.81793 -4.49514 4.19626 -5.27223 3.29963 -5.27223C2.67796 -5.27223 2.11606 -4.75816 1.88892 -4.51905L2.76164 -7.99801ZM2.00847 -0.119552C1.6259 -0.119552 1.20747 -0.406476 1.20747 -1.33898C1.20747 -1.7335 1.24334 -1.96065 1.45853 -2.79751C1.4944 -2.95293 1.68568 -3.71806 1.7335 -3.87347C1.75741 -3.96912 2.46276 -5.03313 3.27572 -5.03313C3.80174 -5.03313 4.04085 -4.5071 4.04085 -3.88543C4.04085 -3.31158 3.7061 -1.96065 3.40722 -1.33898C3.10834 -0.6934 2.55841 -0.119552 2.00847 -0.119552Z" id="g1-98"/>
<path d="M4.65056 -4.88966C4.27995 -4.81793 4.08867 -4.55492 4.08867 -4.29191C4.08867 -4.00498 4.31582 -3.90934 4.48319 -3.90934C4.81793 -3.90934 5.0929 -4.19626 5.0929 -4.55492C5.0929 -4.93748 4.72229 -5.27223 4.12453 -5.27223C3.64633 -5.27223 3.09639 -5.05704 2.59427 -4.32777C2.51059 -4.96139 2.03238 -5.27223 1.55417 -5.27223C1.08792 -5.27223 0.848817 -4.91357 0.705355 -4.65056C0.502117 -4.22017 0.32279 -3.50286 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.812951 -4.33973 1.0401 -5.03313 1.51831 -5.03313C1.80523 -5.03313 1.88892 -4.82989 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.33898 0.119552 1.56613 0.0358655 1.63786 -0.203238C1.67372 -0.298879 2.11606 -2.10411 2.1878 -2.37908C2.24757 -2.64209 2.3193 -2.89315 2.37908 -3.15616C2.4269 -3.32354 2.47472 -3.51482 2.51059 -3.67024C2.54645 -3.77783 2.86924 -4.36364 3.16812 -4.62665C3.31158 -4.75816 3.62242 -5.03313 4.11258 -5.03313C4.30386 -5.03313 4.49514 -4.99726 4.65056 -4.88966Z" id="g1-114"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g1-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g1-121"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.25 0 0 1.25 0 0)">
<use x="180.734" xlink:href="#g0-106" y="92.1544"/>
<use x="184.042" xlink:href="#g1-120" y="92.1544"/>
<use x="193.326" xlink:href="#g0-0" y="92.1544"/>
<use x="205.247" xlink:href="#g1-97" y="92.1544"/>
<use x="211.369" xlink:href="#g0-106" y="92.1544"/>
<use x="217.334" xlink:href="#g2-43" y="92.1544"/>
<use x="229.061" xlink:href="#g0-106" y="92.1544"/>
<use x="232.369" xlink:href="#g1-121" y="92.1544"/>
<use x="241.141" xlink:href="#g0-0" y="92.1544"/>
<use x="253.062" xlink:href="#g1-98" y="92.1544"/>
<use x="258.02" xlink:href="#g0-106" y="92.1544"/>
<use x="264.65" xlink:href="#g2-61" y="92.1544"/>
<use x="277.041" xlink:href="#g1-114" y="92.1544"/>
<use x="281.972" xlink:href="#g1-58" y="92.1544"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,76 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="167.599pt" height="62.7502pt" viewBox="198.755 99.5014 167.599 62.7502">
<defs>
<path d="M6.0254 5.41569C6.0254 4.43537 6.28842 2.15193 8.41644 0.645579C8.57186 0.526027 8.58381 0.514072 8.58381 0.298879C8.58381 0.0239103 8.57186 0.0119552 8.27298 0.0119552H8.08169C5.51133 1.39875 4.59078 3.65828 4.59078 5.41569V10.5564C4.59078 10.8672 4.60274 10.8792 4.92553 10.8792H5.69066C6.01345 10.8792 6.0254 10.8672 6.0254 10.5564V5.41569Z" id="g1-56"/>
<path d="M8.27298 10.7477C8.57186 10.7477 8.58381 10.7357 8.58381 10.4608C8.58381 10.2456 8.57186 10.2336 8.52403 10.1978C8.15342 9.92279 7.29265 9.31308 6.73076 8.2132C6.26451 7.30461 6.0254 6.38406 6.0254 5.34396V0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V5.34396C4.59078 7.11333 5.51133 9.37285 8.08169 10.7477H8.27298Z" id="g1-58"/>
<path d="M4.59078 21.3161C4.59078 21.6269 4.60274 21.6389 4.92553 21.6389H5.69066C6.01345 21.6389 6.0254 21.6269 6.0254 21.3161V16.271C6.0254 14.8244 5.41569 12.3856 2.73773 10.7597C5.4396 9.12179 6.0254 6.65903 6.0254 5.24832V0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V5.26027C4.59078 6.26451 4.37559 8.75118 2.17584 10.4249C2.04433 10.5325 2.03238 10.5445 2.03238 10.7597S2.04433 10.9868 2.17584 11.0944C2.48667 11.3335 3.31158 11.9671 3.88543 13.1746C4.35168 14.131 4.59078 15.195 4.59078 16.259V21.3161Z" id="g1-60"/>
<path d="M6.0254 0.203238C6.0254 -0.107597 6.01345 -0.119552 5.69066 -0.119552H4.92553C4.60274 -0.119552 4.59078 -0.107597 4.59078 0.203238V3.38331C4.59078 3.69415 4.60274 3.7061 4.92553 3.7061H5.69066C6.01345 3.7061 6.0254 3.69415 6.0254 3.38331V0.203238Z" id="g1-62"/>
<path d="M8.06974 -7.10137C8.2132 -7.1731 8.29689 -7.23288 8.29689 -7.36438S8.18929 -7.60349 8.05778 -7.60349C7.99801 -7.60349 7.89041 -7.55567 7.84259 -7.53176L1.23138 -4.41146C1.02814 -4.31582 0.992279 -4.23213 0.992279 -4.13649S1.0401 -3.95716 1.23138 -3.87347L7.84259 -0.765131C7.99801 -0.681445 8.02192 -0.681445 8.05778 -0.681445C8.18929 -0.681445 8.29689 -0.789041 8.29689 -0.920548C8.29689 -1.07597 8.18929 -1.12379 8.05778 -1.18356L1.79328 -4.13649L8.06974 -7.10137ZM7.84259 1.55417C7.99801 1.63786 8.02192 1.63786 8.05778 1.63786C8.18929 1.63786 8.29689 1.53026 8.29689 1.39875C8.29689 1.24334 8.18929 1.19552 8.05778 1.13574L1.45853 -1.9726C1.30311 -2.05629 1.2792 -2.05629 1.23138 -2.05629C1.08792 -2.05629 0.992279 -1.94869 0.992279 -1.81719C0.992279 -1.72154 1.0401 -1.63786 1.23138 -1.55417L7.84259 1.55417Z" id="g0-54"/>
<path d="M3.44309 -7.66326C3.44309 -7.93823 3.44309 -7.95019 3.20399 -7.95019C2.91706 -7.6274 2.3193 -7.18506 1.08792 -7.18506V-6.83836C1.36289 -6.83836 1.96065 -6.83836 2.61818 -7.14919V-0.920548C2.61818 -0.490162 2.58232 -0.3467 1.53026 -0.3467H1.15965V0C1.48244 -0.0239103 2.64209 -0.0239103 3.03661 -0.0239103S4.57883 -0.0239103 4.90162 0V-0.3467H4.53101C3.47895 -0.3467 3.44309 -0.490162 3.44309 -0.920548V-7.66326Z" id="g4-49"/>
<path d="M5.26027 -2.00847H4.99726C4.96139 -1.80523 4.86575 -1.1477 4.7462 -0.956413C4.66252 -0.848817 3.98107 -0.848817 3.62242 -0.848817H1.41071C1.7335 -1.12379 2.46276 -1.88892 2.7736 -2.17584C4.59078 -3.84956 5.26027 -4.47123 5.26027 -5.65479C5.26027 -7.02964 4.17235 -7.95019 2.78555 -7.95019S0.585803 -6.76663 0.585803 -5.73848C0.585803 -5.12877 1.11183 -5.12877 1.1477 -5.12877C1.39875 -5.12877 1.70959 -5.30809 1.70959 -5.69066C1.70959 -6.0254 1.48244 -6.25255 1.1477 -6.25255C1.0401 -6.25255 1.01619 -6.25255 0.980324 -6.2406C1.20747 -7.05355 1.85305 -7.60349 2.63014 -7.60349C3.64633 -7.60349 4.268 -6.75467 4.268 -5.65479C4.268 -4.63861 3.68219 -3.75392 3.00075 -2.98879L0.585803 -0.286924V0H4.94944L5.26027 -2.00847Z" id="g4-50"/>
<path d="M8.06974 -3.87347C8.23711 -3.87347 8.4523 -3.87347 8.4523 -4.08867C8.4523 -4.31582 8.24907 -4.31582 8.06974 -4.31582H1.02814C0.860772 -4.31582 0.645579 -4.31582 0.645579 -4.10062C0.645579 -3.87347 0.848817 -3.87347 1.02814 -3.87347H8.06974ZM8.06974 -1.64981C8.23711 -1.64981 8.4523 -1.64981 8.4523 -1.86501C8.4523 -2.09215 8.24907 -2.09215 8.06974 -2.09215H1.02814C0.860772 -2.09215 0.645579 -2.09215 0.645579 -1.87696C0.645579 -1.64981 0.848817 -1.64981 1.02814 -1.64981H8.06974Z" id="g4-61"/>
<path d="M2.19975 -0.573848C2.19975 -0.920548 1.91283 -1.15965 1.6259 -1.15965C1.2792 -1.15965 1.0401 -0.872727 1.0401 -0.585803C1.0401 -0.239103 1.32702 0 1.61395 0C1.96065 0 2.19975 -0.286924 2.19975 -0.573848Z" id="g3-58"/>
<path d="M2.33126 0.0478207C2.33126 -0.645579 2.10411 -1.15965 1.61395 -1.15965C1.23138 -1.15965 1.0401 -0.848817 1.0401 -0.585803S1.21943 0 1.6259 0C1.78132 0 1.91283 -0.0478207 2.02042 -0.155417C2.04433 -0.179328 2.05629 -0.179328 2.06824 -0.179328C2.09215 -0.179328 2.09215 -0.0119552 2.09215 0.0478207C2.09215 0.442341 2.02042 1.21943 1.32702 1.99651C1.19552 2.13998 1.19552 2.16389 1.19552 2.1878C1.19552 2.24757 1.25529 2.30735 1.31507 2.30735C1.41071 2.30735 2.33126 1.42267 2.33126 0.0478207Z" id="g3-59"/>
<path d="M5.12877 -8.52403C5.12877 -8.53599 5.2005 -8.71532 5.2005 -8.73923C5.2005 -8.88269 5.08095 -8.96638 4.98531 -8.96638C4.92553 -8.96638 4.81793 -8.96638 4.72229 -8.70336L0.71731 2.54645C0.71731 2.55841 0.645579 2.73773 0.645579 2.76164C0.645579 2.90511 0.765131 2.98879 0.860772 2.98879C0.932503 2.98879 1.0401 2.97684 1.12379 2.72578L5.12877 -8.52403Z" id="g3-61"/>
<path d="M3.59851 -1.42267C3.53873 -1.21943 3.53873 -1.19552 3.37136 -0.968369C3.10834 -0.633624 2.58232 -0.119552 2.02042 -0.119552C1.53026 -0.119552 1.25529 -0.561893 1.25529 -1.26725C1.25529 -1.92478 1.6259 -3.26376 1.85305 -3.76588C2.25953 -4.60274 2.82142 -5.03313 3.28767 -5.03313C4.07671 -5.03313 4.23213 -4.0528 4.23213 -3.95716C4.23213 -3.94521 4.19626 -3.78979 4.18431 -3.76588L3.59851 -1.42267ZM4.36364 -4.48319C4.23213 -4.79402 3.90934 -5.27223 3.28767 -5.27223C1.93674 -5.27223 0.478207 -3.52677 0.478207 -1.75741C0.478207 -0.573848 1.17161 0.119552 1.98456 0.119552C2.64209 0.119552 3.20399 -0.394521 3.53873 -0.789041C3.65828 -0.0836862 4.22017 0.119552 4.57883 0.119552S5.22441 -0.0956413 5.4396 -0.526027C5.63088 -0.932503 5.79826 -1.66177 5.79826 -1.70959C5.79826 -1.76936 5.75044 -1.81719 5.6787 -1.81719C5.57111 -1.81719 5.55915 -1.75741 5.51133 -1.57808C5.332 -0.872727 5.10486 -0.119552 4.61469 -0.119552C4.268 -0.119552 4.24408 -0.430386 4.24408 -0.669489C4.24408 -0.944458 4.27995 -1.07597 4.38755 -1.54222C4.47123 -1.8411 4.53101 -2.10411 4.62665 -2.45081C5.06899 -4.24408 5.17659 -4.67447 5.17659 -4.7462C5.17659 -4.91357 5.04508 -5.04508 4.86575 -5.04508C4.48319 -5.04508 4.38755 -4.62665 4.36364 -4.48319Z" id="g3-97"/>
<path d="M2.76164 -7.99801C2.7736 -8.04583 2.79751 -8.11756 2.79751 -8.17733C2.79751 -8.29689 2.67796 -8.29689 2.65405 -8.29689C2.64209 -8.29689 2.21171 -8.26102 1.99651 -8.23711C1.79328 -8.22516 1.61395 -8.20125 1.39875 -8.18929C1.11183 -8.16538 1.02814 -8.15342 1.02814 -7.93823C1.02814 -7.81868 1.1477 -7.81868 1.26725 -7.81868C1.87696 -7.81868 1.87696 -7.71108 1.87696 -7.59153C1.87696 -7.50785 1.78132 -7.16115 1.7335 -6.94595L1.44658 -5.79826C1.32702 -5.32005 0.645579 -2.60623 0.597758 -2.39103C0.537983 -2.09215 0.537983 -1.88892 0.537983 -1.7335C0.537983 -0.514072 1.21943 0.119552 1.99651 0.119552C3.38331 0.119552 4.81793 -1.66177 4.81793 -3.39527C4.81793 -4.49514 4.19626 -5.27223 3.29963 -5.27223C2.67796 -5.27223 2.11606 -4.75816 1.88892 -4.51905L2.76164 -7.99801ZM2.00847 -0.119552C1.6259 -0.119552 1.20747 -0.406476 1.20747 -1.33898C1.20747 -1.7335 1.24334 -1.96065 1.45853 -2.79751C1.4944 -2.95293 1.68568 -3.71806 1.7335 -3.87347C1.75741 -3.96912 2.46276 -5.03313 3.27572 -5.03313C3.80174 -5.03313 4.04085 -4.5071 4.04085 -3.88543C4.04085 -3.31158 3.7061 -1.96065 3.40722 -1.33898C3.10834 -0.6934 2.55841 -0.119552 2.00847 -0.119552Z" id="g3-98"/>
<path d="M4.67447 -4.49514C4.44732 -4.49514 4.33973 -4.49514 4.17235 -4.35168C4.10062 -4.29191 3.96912 -4.11258 3.96912 -3.9213C3.96912 -3.68219 4.14844 -3.53873 4.37559 -3.53873C4.66252 -3.53873 4.98531 -3.77783 4.98531 -4.25604C4.98531 -4.82989 4.43537 -5.27223 3.61046 -5.27223C2.04433 -5.27223 0.478207 -3.56264 0.478207 -1.86501C0.478207 -0.824907 1.12379 0.119552 2.34321 0.119552C3.96912 0.119552 4.99726 -1.1477 4.99726 -1.30311C4.99726 -1.37484 4.92553 -1.43462 4.87771 -1.43462C4.84184 -1.43462 4.82989 -1.42267 4.72229 -1.31507C3.95716 -0.298879 2.82142 -0.119552 2.36712 -0.119552C1.54222 -0.119552 1.2792 -0.836862 1.2792 -1.43462C1.2792 -1.85305 1.48244 -3.0127 1.91283 -3.82565C2.22366 -4.38755 2.86924 -5.03313 3.62242 -5.03313C3.77783 -5.03313 4.43537 -5.00922 4.67447 -4.49514Z" id="g3-99"/>
<path d="M4.65056 -4.88966C4.27995 -4.81793 4.08867 -4.55492 4.08867 -4.29191C4.08867 -4.00498 4.31582 -3.90934 4.48319 -3.90934C4.81793 -3.90934 5.0929 -4.19626 5.0929 -4.55492C5.0929 -4.93748 4.72229 -5.27223 4.12453 -5.27223C3.64633 -5.27223 3.09639 -5.05704 2.59427 -4.32777C2.51059 -4.96139 2.03238 -5.27223 1.55417 -5.27223C1.08792 -5.27223 0.848817 -4.91357 0.705355 -4.65056C0.502117 -4.22017 0.32279 -3.50286 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.549938 -3.33549 0.561893 -3.34745 0.633624 -3.62242C0.812951 -4.33973 1.0401 -5.03313 1.51831 -5.03313C1.80523 -5.03313 1.88892 -4.82989 1.88892 -4.48319C1.88892 -4.22017 1.76936 -3.75392 1.68568 -3.38331L1.35093 -2.09215C1.30311 -1.86501 1.17161 -1.32702 1.11183 -1.11183C1.02814 -0.800996 0.896638 -0.239103 0.896638 -0.179328C0.896638 -0.0119552 1.02814 0.119552 1.20747 0.119552C1.33898 0.119552 1.56613 0.0358655 1.63786 -0.203238C1.67372 -0.298879 2.11606 -2.10411 2.1878 -2.37908C2.24757 -2.64209 2.3193 -2.89315 2.37908 -3.15616C2.4269 -3.32354 2.47472 -3.51482 2.51059 -3.67024C2.54645 -3.77783 2.86924 -4.36364 3.16812 -4.62665C3.31158 -4.75816 3.62242 -5.03313 4.11258 -5.03313C4.30386 -5.03313 4.49514 -4.99726 4.65056 -4.88966Z" id="g3-114"/>
<path d="M5.66675 -4.87771C5.28418 -4.80598 5.14072 -4.51905 5.14072 -4.29191C5.14072 -4.00498 5.36787 -3.90934 5.53524 -3.90934C5.8939 -3.90934 6.14496 -4.22017 6.14496 -4.54296C6.14496 -5.04508 5.57111 -5.27223 5.06899 -5.27223C4.33973 -5.27223 3.93325 -4.55492 3.82565 -4.32777C3.55068 -5.22441 2.80946 -5.27223 2.59427 -5.27223C1.37484 -5.27223 0.729265 -3.7061 0.729265 -3.44309C0.729265 -3.39527 0.777086 -3.33549 0.860772 -3.33549C0.956413 -3.33549 0.980324 -3.40722 1.00423 -3.45504C1.41071 -4.78207 2.21171 -5.03313 2.55841 -5.03313C3.09639 -5.03313 3.20399 -4.53101 3.20399 -4.24408C3.20399 -3.98107 3.13225 -3.7061 2.98879 -3.13225L2.58232 -1.4944C2.40299 -0.777086 2.05629 -0.119552 1.42267 -0.119552C1.36289 -0.119552 1.06401 -0.119552 0.812951 -0.274969C1.24334 -0.358655 1.33898 -0.71731 1.33898 -0.860772C1.33898 -1.09988 1.15965 -1.24334 0.932503 -1.24334C0.645579 -1.24334 0.334745 -0.992279 0.334745 -0.609714C0.334745 -0.107597 0.896638 0.119552 1.41071 0.119552C1.98456 0.119552 2.39103 -0.334745 2.64209 -0.824907C2.83337 -0.119552 3.43113 0.119552 3.87347 0.119552C5.0929 0.119552 5.73848 -1.44658 5.73848 -1.70959C5.73848 -1.76936 5.69066 -1.81719 5.61893 -1.81719C5.51133 -1.81719 5.49938 -1.75741 5.46351 -1.66177C5.14072 -0.609714 4.44732 -0.119552 3.90934 -0.119552C3.49091 -0.119552 3.26376 -0.430386 3.26376 -0.920548C3.26376 -1.18356 3.31158 -1.37484 3.50286 -2.16389L3.9213 -3.78979C4.10062 -4.5071 4.5071 -5.03313 5.05704 -5.03313C5.08095 -5.03313 5.41569 -5.03313 5.66675 -4.87771Z" id="g3-120"/>
<path d="M3.14421 1.33898C2.82142 1.79328 2.35517 2.19975 1.76936 2.19975C1.6259 2.19975 1.05205 2.17584 0.872727 1.6259C0.908593 1.63786 0.968369 1.63786 0.992279 1.63786C1.35093 1.63786 1.59004 1.32702 1.59004 1.05205S1.36289 0.681445 1.18356 0.681445C0.992279 0.681445 0.573848 0.824907 0.573848 1.41071C0.573848 2.02042 1.08792 2.43885 1.76936 2.43885C2.96488 2.43885 4.17235 1.33898 4.5071 0.0119552L5.6787 -4.65056C5.69066 -4.71034 5.71457 -4.78207 5.71457 -4.8538C5.71457 -5.03313 5.57111 -5.15268 5.39178 -5.15268C5.28418 -5.15268 5.03313 -5.10486 4.93748 -4.7462L4.0528 -1.23138C3.99303 -1.01619 3.99303 -0.992279 3.89738 -0.860772C3.65828 -0.526027 3.26376 -0.119552 2.68991 -0.119552C2.02042 -0.119552 1.96065 -0.777086 1.96065 -1.09988C1.96065 -1.78132 2.28344 -2.70187 2.60623 -3.56264C2.73773 -3.90934 2.80946 -4.07671 2.80946 -4.31582C2.80946 -4.81793 2.45081 -5.27223 1.86501 -5.27223C0.765131 -5.27223 0.32279 -3.53873 0.32279 -3.44309C0.32279 -3.39527 0.37061 -3.33549 0.454296 -3.33549C0.561893 -3.33549 0.573848 -3.38331 0.621669 -3.55068C0.908593 -4.55492 1.36289 -5.03313 1.82914 -5.03313C1.93674 -5.03313 2.13998 -5.03313 2.13998 -4.63861C2.13998 -4.32777 2.00847 -3.98107 1.82914 -3.52677C1.24334 -1.96065 1.24334 -1.56613 1.24334 -1.2792C1.24334 -0.143462 2.05629 0.119552 2.65405 0.119552C3.00075 0.119552 3.43113 0.0119552 3.84956 -0.430386L3.86152 -0.418431C3.68219 0.286924 3.56264 0.753176 3.14421 1.33898Z" id="g3-121"/>
<path d="M7.87846 -2.74969C8.08169 -2.74969 8.29689 -2.74969 8.29689 -2.98879S8.08169 -3.2279 7.87846 -3.2279H1.41071C1.20747 -3.2279 0.992279 -3.2279 0.992279 -2.98879S1.20747 -2.74969 1.41071 -2.74969H7.87846Z" id="g2-0"/>
<path d="M4.65056 -3.32354L2.25953 -5.70262C2.11606 -5.84608 2.09215 -5.86999 1.99651 -5.86999C1.87696 -5.86999 1.75741 -5.76239 1.75741 -5.63088C1.75741 -5.5472 1.78132 -5.52329 1.91283 -5.39178L4.30386 -2.98879L1.91283 -0.585803C1.78132 -0.454296 1.75741 -0.430386 1.75741 -0.3467C1.75741 -0.215193 1.87696 -0.107597 1.99651 -0.107597C2.09215 -0.107597 2.11606 -0.131507 2.25953 -0.274969L4.63861 -2.65405L7.11333 -0.179328C7.13724 -0.167372 7.22092 -0.107597 7.29265 -0.107597C7.43611 -0.107597 7.53176 -0.215193 7.53176 -0.3467C7.53176 -0.37061 7.53176 -0.418431 7.49589 -0.478207C7.48394 -0.502117 5.58306 -2.37908 4.98531 -2.98879L7.1731 -5.17659C7.23288 -5.24832 7.4122 -5.40374 7.47198 -5.47547C7.48394 -5.49938 7.53176 -5.5472 7.53176 -5.63088C7.53176 -5.76239 7.43611 -5.86999 7.29265 -5.86999C7.19701 -5.86999 7.14919 -5.82217 7.01768 -5.69066L4.65056 -3.32354Z" id="g2-2"/>
<path d="M4.25604 -6.89813C4.1604 -7.10137 4.08867 -7.14919 3.98107 -7.14919C3.82565 -7.14919 3.78979 -7.0655 3.71806 -6.89813L0.74122 -0.215193C0.669489 -0.0597758 0.657534 -0.0358655 0.657534 0.0239103C0.657534 0.155417 0.765131 0.263014 0.896638 0.263014C0.980324 0.263014 1.07597 0.239103 1.17161 0.0119552L3.98107 -6.32428L6.79054 0.0119552C6.89813 0.263014 7.01768 0.263014 7.0655 0.263014C7.19701 0.263014 7.30461 0.155417 7.30461 0.0239103C7.30461 0 7.30461 -0.0239103 7.23288 -0.167372L4.25604 -6.89813Z" id="g2-94"/>
<path d="M1.90087 -8.53599C1.90087 -8.75118 1.90087 -8.96638 1.66177 -8.96638S1.42267 -8.75118 1.42267 -8.53599V2.55841C1.42267 2.7736 1.42267 2.98879 1.66177 2.98879S1.90087 2.7736 1.90087 2.55841V-8.53599Z" id="g2-106"/>
<path d="M4.65056 10.2217L2.54645 5.57111C2.46276 5.37983 2.40299 5.37983 2.36712 5.37983C2.35517 5.37983 2.29539 5.37983 2.16389 5.47547L1.02814 6.33624C0.872727 6.45579 0.872727 6.49166 0.872727 6.52752C0.872727 6.5873 0.908593 6.65903 0.992279 6.65903C1.06401 6.65903 1.26725 6.49166 1.39875 6.39601C1.47049 6.33624 1.64981 6.20473 1.78132 6.10909L4.13649 11.2857C4.22017 11.477 4.27995 11.477 4.38755 11.477C4.56687 11.477 4.60274 11.4052 4.68643 11.2379L10.1141 0C10.1978 -0.167372 10.1978 -0.215193 10.1978 -0.239103C10.1978 -0.358655 10.1021 -0.478207 9.95866 -0.478207C9.86301 -0.478207 9.77933 -0.418431 9.68369 -0.227148L4.65056 10.2217Z" id="g2-112"/>
</defs>
<g fill="#222" stroke="#222" style="fill: var(--color, #222); stroke: var(--color, #222);" stroke-width="0.3" transform="matrix(1.24 0 0 1.25 0 0)">
<use x="159.004" xlink:href="#g1-56" y="79.6011"/>
<use x="159.004" xlink:href="#g1-62" y="90.3609"/>
<use x="159.004" xlink:href="#g1-60" y="93.9475"/>
<use x="159.004" xlink:href="#g1-62" y="115.467"/>
<use x="159.004" xlink:href="#g1-58" y="119.054"/>
<use x="169.631" xlink:href="#g2-106" y="90.8393"/>
<use x="172.939" xlink:href="#g3-120" y="90.8393"/>
<use x="182.223" xlink:href="#g2-0" y="90.8393"/>
<use x="194.144" xlink:href="#g3-97" y="90.8393"/>
<use x="200.266" xlink:href="#g2-106" y="90.8393"/>
<use x="206.895" xlink:href="#g4-61" y="90.8393"/>
<use x="219.286" xlink:href="#g3-99" y="90.8393"/>
<use x="226.962" xlink:href="#g2-94" y="90.8393"/>
<use x="237.559" xlink:href="#g2-106" y="90.8393"/>
<use x="240.868" xlink:href="#g3-121" y="90.8393"/>
<use x="249.64" xlink:href="#g2-0" y="90.8393"/>
<use x="261.56" xlink:href="#g3-98" y="90.8393"/>
<use x="266.519" xlink:href="#g2-106" y="90.8393"/>
<use x="273.148" xlink:href="#g0-54" y="90.8393"/>
<use x="285.732" xlink:href="#g3-99" y="90.8393"/>
<use x="290.752" xlink:href="#g3-59" y="90.8393"/>
<use x="169.631" xlink:href="#g2-106" y="108.174"/>
<use x="172.939" xlink:href="#g3-121" y="108.174"/>
<use x="181.711" xlink:href="#g2-0" y="108.174"/>
<use x="193.632" xlink:href="#g3-98" y="108.174"/>
<use x="198.59" xlink:href="#g2-106" y="108.174"/>
<use x="205.219" xlink:href="#g4-61" y="108.174"/>
<use x="217.611" xlink:href="#g3-99" y="108.174"/>
<use x="225.287" xlink:href="#g2-94" y="108.174"/>
<use x="235.884" xlink:href="#g2-106" y="108.174"/>
<use x="239.192" xlink:href="#g3-120" y="108.174"/>
<use x="248.476" xlink:href="#g2-0" y="108.174"/>
<use x="260.397" xlink:href="#g3-97" y="108.174"/>
<use x="266.519" xlink:href="#g2-106" y="108.174"/>
<use x="273.148" xlink:href="#g0-54" y="108.174"/>
<use x="285.732" xlink:href="#g3-99" y="108.174"/>
<use x="290.752" xlink:href="#g3-59" y="108.174"/>
<use x="169.631" xlink:href="#g3-99" y="125.509"/>
<use x="177.971" xlink:href="#g4-61" y="125.509"/>
<use x="190.362" xlink:href="#g3-114" y="125.509"/>
<use x="198.6" xlink:href="#g2-2" y="125.509"/>
<use x="210.52" xlink:href="#g4-49" y="125.509"/>
<use x="216.351" xlink:href="#g3-61" y="125.509"/>
<use x="222.182" xlink:href="#g2-112" y="115.62"/>
<rect height="0.478187" width="5.85299" x="232.145" y="115.141"/>
<use x="232.145" xlink:href="#g4-50" y="125.509"/>
<use x="237.998" xlink:href="#g3-58" y="125.509"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View file

@ -0,0 +1,29 @@
// собираем комбинации для вёб-сайта
const generate = function() {
let text = "";
for (let row = 0; row < 15; row++) {
let line = "";
for (let col = 0; col < 4; col++) {
let combo = "";
for (let len = 0; len < 20; len = combo.length) {
const co = random("!".charCodeAt(0), "~".charCodeAt(0));
const ch = String.fromCharCode(co);
if (len == 0 && (ch >= "A" && ch <= "Z" || ch >= "a" && ch <= "z")
|| len > 0 && combo.indexOf(ch) < 0)
combo += ch;
}
line += escapeHTML(combo) + " ";
}
text += line + (row < 14 ? "\n" : "");
}
return text;
}
// получаем случайное число в заданном диапазоне
const random = (min, max) => Math.round(min + (max-min) * Math.random());
// экранируем спецсимволы HTML для корректного отображения в браузере
const escapeHTML = (str) => str.replace("&", "&amp;").replace(">", "&gt;").replace("<", "&lt;");
// кнопка обновить на странице — обновляем комбинации
const refresh = () => document.getElementById("combinations").innerHTML = generate();
// после загрузки всех частей страницы — обновляем комбинации
document.addEventListener("DOMContentLoaded", refresh);

7
jekyll_site/robots.txt Normal file
View file

@ -0,0 +1,7 @@
User-agent: *
Disallow: *404*
Sitemap: https://pomodoro5.mircloud.ru/pagesmap.xml
Sitemap: https://pomodoro5.mircloud.ru/color/pagesmap.xml
Host: https://pomodoro5.mircloud.ru

View file

@ -0,0 +1,223 @@
---
title: Рисуем простую капчу
description: Напишем алгоритм для отображения текста в виде картинки с использованием библиотеки Java AWT. Символы и шрифт могут быть любыми, но для этого примера будем...
sections: [Криптография,Отрисовка шрифта,Поворот изображения]
tags: [java,awt,графика,изображение,картинка,капча]
canonical_url: /ru/2023/01/03/drawing-simple-captcha.html
url_translated: /en/2023/01/04/drawing-simple-captcha.html
title_translated: Drawing simple captcha
date: 2023.01.03
---
Напишем алгоритм для отображения текста в виде картинки с использованием библиотеки Java AWT.
Символы и шрифт могут быть любыми, но для этого примера будем использовать комбинацию заглавных
латинских букв и цифр со шрифтом *Comic Sans* будем рисовать простую капчу для сайта или блога.
{% include picture.html id="captcha.png" src="/img/captcha.png" alt="Рисуем простую капчу" %}
Спецсимволы рассмотрим, но пользоваться ими не будем, потому что угадать их с таким оформлением
текста пользователю будет сложно. Например, плюс `+` угадать ещё можно, а вот минус `-` или
нижнее подчёркивание `_` уже с трудом, и даже если угадаешь, тогда найти эти кнопки с трудом,
особенно на телефоне. Поэтому для капчи будем использовать комбинацию только из заглавных
латинских букв и цифр.
Отрисовка спецсимволов моноширинным шрифтом: [Рисуем сердечко в консоли]({{ '/ru/2023/03/08/drawing-heart-in-console.html#text-as-picture-and-picture-as-text' | relative_url }}).
## Описание алгоритма {#algorithm-description}
Подготавливаем массив символов, состоящий из заглавных латинских букв и цифр. Затем обходим
этот массив и отрисовываем каждый символ отдельно получаем картинку. Затем поворачиваем
картинки поочерёдно на ±35 градусов получаем массив картинок с символами. Второй раз обходим
массив с картинками и собираем общее изображение присоединяем картинки слева направо таким
образом, чтобы последующая картинка наезжала на предыдущую на 40% её ширины.
Почему 35 градусов? Если взять угол больше, тогда пользователю будет сложно разгадать такую
капчу. Например, буквы `N` и `Z` будут похожи друг на друга. Если взять угол меньше, то такую
капчу будет легко разгадать с помощью машинного распознавания текста.
Наложение последующей картинки на предыдущую на 40% её ширины нужно, чтобы символы располагались
очень близко или слегка касались друг друга это также затрудняет машинное распознавание текста.
## Отрисовка шрифта {#font-rendering}
При отрисовке шрифта будем использовать сглаживание *anti-aliasing*, иначе буквы будут
с зазубренными краями. Устанавливаем изображение с поддержкой прозрачности, цвет чёрный,
шрифт *Comic Sans*.
```java
// преобразовываем строку с текстом в картинку с текстом
private static BufferedImage stringToImage(String str, Font font) {
// контекст отображения шрифта
FontRenderContext ctx = new FontRenderContext(font.getTransform(), true, true);
// получаем размеры картинки с текстом при отрисовке
Rectangle bnd = font.getStringBounds(str, ctx).getBounds();
// создаём новое изображение с поддержкой прозрачности
BufferedImage image = new BufferedImage(bnd.width, bnd.height, BufferedImage.TYPE_INT_ARGB);
// включаем режим редактирования нового изображения
Graphics2D graphics = image.createGraphics();
// шрифт для отрисовки
graphics.setFont(font);
// цвет, которым будем рисовать
graphics.setColor(Color.BLACK);
// применяем сглаживание шрифта при отрисовке текста
graphics.setRenderingHint( // сглаживание пикселей вдоль границы фигуры
RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// рисуем картинку с текстом
graphics.drawString(str, bnd.x, -bnd.y);
// отключаем режим редактирования
graphics.dispose();
// возвращаем картинку с текстом
return image;
}
```
## Поворот изображения {#image-rotation}
При повороте изображения для сглаживания будем использовать *билинейную интерполяцию*, иначе
будет много лишних артефактов по границам изображения. По дороге пересчитываем размеры для
нового изображения.
```java
// поворачиваем картинку на заданный угол и изменяем её размеры
private static BufferedImage rotateImage(BufferedImage image, double angle) {
// переводим градусы в радианы
double radian = Math.toRadians(angle);
double sin = Math.abs(Math.sin(radian));
double cos = Math.abs(Math.cos(radian));
// получаем размеры текущего изображения
int width = image.getWidth();
int height = image.getHeight();
// вычисляем размеры нового изображения
int nWidth = (int) Math.floor(width * cos + height * sin);
int nHeight = (int) Math.floor(height * cos + width * sin);
// создаём новое изображение с поддержкой прозрачности
BufferedImage rotated = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_ARGB);
// включаем режим редактирования нового изображения
Graphics2D graphics = rotated.createGraphics();
// применяем сглаживание изображения при повороте
graphics.setRenderingHint( // билинейная интерполяция
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// сдвигаем начало координат нового изображения в его центр
graphics.translate(nWidth / 2, nHeight / 2);
// поворачиваем новое изображение вместе с его системой координат
graphics.rotate(radian);
// помещаем текущее изображение в новое, чтобы их центры совпали
graphics.drawImage(image, -width / 2, -height / 2, null);
// отключаем режим редактирования
graphics.dispose();
// возвращаем новое изображение
return rotated;
}
```
## Рисуем простую капчу {#drawing-simple-captcha}
Обходим массив символов, отрисовываем и поворачиваем каждый символ в отдельности, по дороге
вычисляем размеры для общего изображения. Создаём общее изображение и после этого ещё раз
обходим массив картинок и дорисовываем их по одной слева направо к общему изображению.
Возвращаем пару объектов: текстовое значение капчи и картинку с символами.
```java
// отрисовываем массив символов, поворачиваем их и объединяем результаты
private static Map.Entry<String, BufferedImage> drawSimpleCaptcha(String[] symbols)
throws IOException, FontFormatException {
Font font = Font // устанавливаем файл шрифта
.createFont(Font.TRUETYPE_FONT, new File("ComicSansMS.ttf"))
// устанавливаем стиль и размер шрифта
.deriveFont(Font.BOLD, 32);
// размеры итогового изображения
int width = 0, height = 0;
// подготавливаем массив картинок
BufferedImage[] images = new BufferedImage[symbols.length];
// обходим массив символов, получаем картинки
// и вычисляем размеры итогового изображения
for (int i = 0; i < symbols.length; i++) {
if (i % 2 == 0) // отрисовываем символы и поворачиваем изображения
images[i] = rotateImage(stringToImage(symbols[i], font), 35);
else
images[i] = rotateImage(stringToImage(symbols[i], font), -35);
// размеры картинки с текущим символом
int h = images[i].getHeight(), w = images[i].getWidth();
// высота самого большого символа
height = Math.max(height, h);
// последующий символ будем сдвигать на 40% ширины предыдущего
if (i < symbols.length - 1)
width += w * 6 / 10; // берём 60% ширины текущего символа
else // ширину последнего символа берём целиком
width += w;
}
// создаём новое изображение с поддержкой прозрачности
BufferedImage captcha = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
// включаем режим редактирования нового изображения
Graphics2D graphics = captcha.createGraphics();
// обходим массив картинок и дорисовываем их к общему изображению слева направо
for (BufferedImage image : images) {
// отрисовываем текущий символ в начале координат
graphics.drawImage(image, 0, 0, null);
// сдвигаем начало координат на 60% ширины текущего символа
graphics.translate(image.getWidth() * 6 / 10, 0);
}
// отключаем режим редактирования
graphics.dispose();
// возвращаем пару объектов: текстовое значение капчи и картинку с символами
return Map.entry(String.join("", symbols), captcha);
}
```
{% capture collapsed_md %}
```java
// метод для внешних вызовов, возвращает случайную комбинацию из 5 символов
public static Map.Entry<String, BufferedImage> drawSimpleCaptcha()
throws IOException, FontFormatException {
return drawSimpleCaptcha(5);
}
```
```java
// метод для внешних вызовов, требуется указать длину строки
public static Map.Entry<String, BufferedImage> drawSimpleCaptcha(int length)
throws IOException, FontFormatException {
// получаем случайную комбинацию символов указанной длины
String[] symbols = getRandomString(length);
return drawSimpleCaptcha(symbols);
}
```
```java
// получаем случайную комбинацию заглавных латинских букв и цифр
private static String[] getRandomString(int length) {
String[] symbols = new String[length];
Random random = new Random();
for (int i = 0; i < length; i++) {
// 26 заглавных букв и 10 цифр
int rnd = random.nextInt(36);
if (rnd < 26) // буквы [A..Z]
symbols[i] = Character.toString('A' + rnd);
else // цифры [0..9]
symbols[i] = Character.toString('0' + rnd - 26);
}
return symbols;
}
```
{% endcapture %}
{%- include collapsed_block.html summary="Дополнительные методы" content=collapsed_md -%}
## Тестирование и запуск {#testing-n-launching}
Алгоритм получился универсальный отрисовать можно почти любую строку и почти любым шрифтом,
но с длинным списком исключений, связанных с диапазонами символов юникода и типами шрифтов.
Вариантов много, тестировать долго, а упрощенная модель меня вполне устраивает.
В завершение этого примера для визуализации нарисуем строку: `SIMPLE+CAPTCHA+1+1`.
```java
// запускаем программу и выводим результат
public static void main(String[] args) throws IOException, FontFormatException {
String[] symbols = "simple+captcha+1+1".toUpperCase().split("");
// Map.Entry<String, BufferedImage> captcha = drawSimpleCaptcha(18);
Map.Entry<String, BufferedImage> captcha = drawSimpleCaptcha(symbols);
// сохраняем картинку в файл, текст в консоль
ImageIO.write(captcha.getValue(), "png", new File("captcha.png"));
// System.out.println(captcha.getKey());
}
```
Картинку из этого кода см. выше: [captcha.png](#captcha.png).

View file

@ -0,0 +1,145 @@
---
title: График функции в консоли
description: Напишем алгоритм для вывода графика функции или системы уравнений в консоль в виде текста. Будем использовать средства Java. Для вычислений будем использовать.
sections: [Геометрические фигуры,Текстовое изображение]
tags: [java,math,fdlibm,консоль,ромб,квадрат,окружность,круг,текст,изображение]
canonical_url: /ru/2023/02/05/function-graph-in-console.html
url_translated: /en/2023/02/06/function-graph-in-console.html
title_translated: Function graph in console
date: 2023.02.05
---
Напишем алгоритм для вывода графика функции или системы уравнений в консоль в виде текста. Будем
использовать средства Java. Для вычислений будем использовать класс `Math`, а для обхода диапазона
координат два вложенных цикла `for`. Нарисуем в консоли график окружности и графики вписанных
в неё ромба и квадрата.
График функции с заполнением: [Рисуем сердечко в консоли]({{ '/ru/2023/03/08/drawing-heart-in-console.html' | relative_url }}).
### Уравнения функций {#equations-of-functions}
Каждую точку `(x,y)` из выводимого диапазона координат будем проверять на принадлежность графикам
функций и в соответствии с этим выводить. Параметры функций и выводимый диапазон определим заранее
перед началом обхода.
*Ромб*.
{% include image_svg.html src="/img/rhombus-equation.svg"
style="width: 129.297pt; height: 14.944pt;"
alt="|x-a|+|y-b|=r." %}
*Квадрат*.
{% include image_svg.html src="/img/square-equations.svg"
style="width: 167.599pt; height: 62.7502pt;"
alt="\begin{cases}|x-a|=c\land|y-b|\leqslant c,\\|y-b|=c\land|x-a|\leqslant c,\\c=r\times1/\sqrt2.\end{cases}" %}
*Окружность*.
{% include image_svg.html src="/img/circumference-equation.svg"
style="width: 162.53pt; height: 17.9328pt;"
alt="\sqrt{(x-a)^2+(y-b)^2}=r." %}
*Параметры*.
`r` радиус окружности;
`(a,b)` центр фигуры;
`c` половина стороны квадрата.
### Математические операции {#mathematical-operations}
Для выполнения *базовых* математических операций в Java используется библиотека `FdLibm`
*Свободно распространяемая математическая библиотека*. Большинство методов реализовано на уровне
платформы для увеличения производительности. Обращаться к ним будем через класс `Math`.
Для вычислений с плавающей точкой и округлений результатов будем использовать методы класса `Math`.
`abs(a)` абсолютное значение аргумента `a`;
`pow(a,b)` возведение аргумента `a` в степень `b`;
`sqrt(a)` квадратный корень из аргумента `a`;
`ceil(a)` округление аргумента `a` в бо́льшую сторону;
`floor(a)` округление аргумента `a` в ме́ньшую сторону.
### Описание алгоритма {#algorithm-description}
Берём диапазон координат на плоскости таким образом, чтобы выводимая фигура полностью помещалась
в печатаемой области. Обходим выбранный диапазон двумя вложенными циклами `for`: сначала по оси
`y` и затем по оси `x`. Каждую точку проверяем на принадлежность графикам функций и выводим. Для
наглядности также выводим координатные оси, начало координат и центр фигуры.
```java
// радиус, центр фигуры, отступ
int r=12, a=5, b=-1, gap=2;
// границы текстового изображения
int xMin=a-r-gap, xMax=a+r+gap;
int yMin=b-r-gap, yMax=b+r+gap;
// половина стороны вписанного квадрата
double c = Math.ceil(r/Math.sqrt(2));
// выводим заголовок
System.out.println("Радиус: "+r+"; центр: 0("+a+","+b+").");
// вывод в консоль построчно слева направо сверху вниз
for (int y = yMax; y >= yMin; y--) {
for (int x = xMin; x <= xMax; x++) {
// каждую точку проверяем на принадлежность графикам и выводим
if (Math.abs(x-a) + Math.abs(y-b) == r)
System.out.print("z "); // ромб
else if (Math.abs(x-a) == c && Math.abs(y-b) <= c
|| Math.abs(y-b) == c && Math.abs(x-a) <= c)
System.out.print("* "); // квадрат
else if (Math.floor(Math.sqrt(Math.pow(x-a,2)+Math.pow(y-b,2))) == r)
System.out.print("o "); // окружность
else if (y == b && x == a)
System.out.print("0 "); // центр фигуры
else if (y == 0 && x == 0)
System.out.print("+-"); // центр координат
else if (y == 0) // ось абсцисс (x)
System.out.print(x == xMax ? ">x" : "--");
else if (x == 0) // ось ординат (y)
System.out.print(y == yMax ? "↑y" : "¦ ");
else // пустое место
System.out.print(" ");
} // переход на новую строку
System.out.println();
}
```
Текстовое изображение в консоли.
```
Радиус: 12; центр: 0(5,-1).
y
¦
¦ o o o o z o o o o
o o z z o o
o o ¦ z z o o
* * * * * * z * * * * * z * * * * * *
o * ¦ z z * o
o * z z * o
o * z ¦ z * o
o * z ¦ z * o
o * z ¦ z * o
o z ¦ z o
o z * ¦ * z o
----o z --* ------+---------------------------* --z o -->x
z * ¦ 0 * z
o z * ¦ * z o
o z * ¦ * z o
o z ¦ z o
o * z ¦ z * o
o * z ¦ z * o
o * z ¦ z * o
o * z z * o
o * ¦ z z * o
* * * * * * z * * * * * z * * * * * *
o o ¦ z z o o
o o z z o o
¦ o o o o z o o o o
¦
¦
```

View file

@ -0,0 +1,300 @@
---
title: Рисуем сердечко в консоли
description: Напишем два варианта алгоритма на Java для вывода сердечка в консоль в форме текстового изображения поздравим женщин с восьмым марта. Нарисуем график...
sections: [Геометрические фигуры,Отрисовка шрифта,Текстовое изображение]
tags: [java,awt,консоль,ромб,окружность,круг,текст,изображение,шрифт]
canonical_url: /ru/2023/03/08/drawing-heart-in-console.html
url_translated: /en/2023/03/08/drawing-heart-in-console.html
title_translated: Drawing heart in console
date: 2023.03.08
---
Напишем два варианта алгоритма на Java для вывода сердечка в консоль в форме текстового
изображения поздравим женщин с восьмым марта. Нарисуем график функции в форме сердечка
и в дополнение нарисуем символ *сердечко* в форме картинки, а картинку выведем текстом
консольное поздравление с восьмым марта.
## График в форме сердечка {#heart-shaped-graph}
Нарисуем два полукруга и один полуромб, заполненные внутри и снаружи. В предыдущем примере мы выводили
[график функции в консоль]({{ '/ru/2023/02/05/function-graph-in-console.html' | relative_url }})
формулы для окружности и для ромба возьмём из него, а в этом примере для заполнения фигуры внутри,
в формуле вместо знака *равно* подставляем знак *меньше*, а для заполнения снаружи, наоборот, знак
*больше*. Условий получится много, в отличие от предыдущего примера.
Нарисуем картинку для наглядности.
{% include picture.html src="/img/heart-graph.png" background=true
alt="График в форме сердечка — это два полукруга и один полуромб"
caption="Два полукруга и один полуромб" %}
Выводим верхнюю часть фигуры, нижнюю часть фигуры, закрашиваем в шахматном порядке и выводим
координатные оси. Получаем несколько текстовых изображений, которые выглядят следующим образом.
```
Радиус: 5, внутри/снаружи/оси: true/true/true.
· · · · · y · · · · ·
· · o o o o o · ¦ · o o o o o · ·
· o * * o · o * * o ·
· o * * * o ¦ o * * * o ·
o * * * * o * * * * o
· o * * * * * o * * * * * o ·
--o --* --* --* --* --+---* --* --* --* --o >x
· o * * * * ¦ * * * * o ·
· o * * * * * * * o ·
· · o * * * ¦ * * * o · ·
· · o * * * * * o · ·
· · · o * * ¦ * * o · · ·
· · · o * * * o · · ·
· · · · o * ¦ * o · · · ·
· · · · o * o · · · ·
· · · · · o ¦ o · · · · ·
· · · · · o · · · · ·
· · · · · · ¦ · · · · · ·
```
{% capture collapsed_md %}
```
Радиус: 4, внутри/снаружи/оси: false/true/false.
· · · · · · · · · ·
· o o o o o · o o o o o ·
· o o o o o o o o ·
o o o o o o o
· o o o ·
o o
· o o ·
· o o ·
· · o o · ·
· · o o · ·
· · · o o · · ·
· · · o o · · ·
· · · · o o · · · ·
· · · · o · · · ·
· · · · · · · · · ·
```
```
Радиус: 3, внутри/снаружи/оси: true/false/false.
o o o o o o
o * * o o * * o
o * * * o * * * o
o * * * * * o
o * * * * o
o * * * o
o * * o
o * o
o o
o
```
```
Радиус: 2, внутри/снаружи/оси: false/false/false.
o o o o o o
o o o
o o
o o
o o
o o
o
```
{% endcapture %}
{%- include collapsed_block.html summary="Полный вывод" content=collapsed_md -%}
Обходим диапазон координат двумя вложенными циклами `for`: сначала по оси `y` и затем по оси `x`. Каждую
точку проверяем на соответствие условиям и выводим. В верхней части рисуем два полукруга и опционально
закрашиваем их внутри/снаружи. В нижней части рисуем полуромб и также опционально закрашиваем внутри/снаружи.
```java
/**
* @param r радиус
* @param gap отступ
* @param in заполнение внутри
* @param out заполнение снаружи
* @param axes координатные оси
*/
public static void printHeartGraph(
int r, int gap, boolean in, boolean out, boolean axes) {
// границы текстового изображения
int xMax = 2*r+gap, xMin = -xMax;
int yMax = r+gap, yMin = -r-yMax;
System.out.println( // заголовок с параметрами
"Радиус: "+r+", внутри/снаружи/оси: "+in+"/"+out+"/"+axes+".");
// вывод в консоль построчно слева направо сверху вниз
for (int y = yMax; y >= yMin; y--) {
for (int x = xMin; x <= xMax; x++) {
double[] circle = { // две окружности левая/правая
Math.round(Math.sqrt(Math.pow(x+r,2)+Math.pow(y,2))), // левая
Math.round(Math.sqrt(Math.pow(x-r,2)+Math.pow(y,2)))}; // правая
int rhombus = Math.abs(x)+Math.abs(y); // ромб
boolean inCh = in && (x+y)%2 == 0; // шахматный порядок внутри
boolean outCh = out && (x+y)%2 == 0; // шахматный порядок снаружи
// каждую точку проверяем на соответствие условиям и выводим
if (axes && y == 0 && x == 0)
System.out.print("+-"); // начало координат
else if (axes && y == 0 && x == xMax)
System.out.print(">x"); // максимум оси абсцисс (x)
else if (axes && x == 0 && y == yMax)
System.out.print("↑y"); // максимум оси ординат (y)
else if (y > 0 && (circle[0] == r || circle[1] == r))
System.out.print("o "); // два полукруга, верх
else if (y > 0 && inCh && (circle[0] < r || circle[1] < r))
System.out.print("* "); // верх внутри
else if (y > 0 && outCh && (circle[0] > r && circle[1] > r))
System.out.print("· "); // верх снаружи
else if (y <= 0 && rhombus == 2*r)
System.out.print("o "); // полуромб, низ
else if (y <= 0 && inCh && rhombus < 2*r)
System.out.print("* "); // низ внутри
else if (y <= 0 && outCh && rhombus > 2*r)
System.out.print("· "); // низ снаружи
else if (axes && y == 0)
System.out.print("--"); // ось абсцисс (x)
else if (axes && x == 0)
System.out.print("¦ "); // ось ординат (y)
else
System.out.print(" "); // пустое место
} // переход на новую строку
System.out.println();
}
}
```
```java
// запускаем программу и выводим результат
public static void main(String[] args) {
printHeartGraph(5, 1, true, true, true);
printHeartGraph(4, 1, false, true, false);
printHeartGraph(3, 0, true, false, false);
printHeartGraph(2, 0, false, false, false);
}
```
## Текст картинкой и картинка текстом {#text-as-picture-and-picture-as-text}
В предыдущем примере мы [рисовали простую капчу]({{ '/ru/2023/01/03/drawing-simple-captcha.html' | relative_url }})
алгоритм отрисовки шрифта возьмём из него, только на этот раз нарисуем бинарное чёрно-белое
изображение моноширинным шрифтом, сглаживание не используем. Символ *сердечко* в форме картинки
выглядит следующим образом.
{% include picture.html src="/img/heart-monospaced-plain-22.bmp"
alt="Символ сердечко, шрифт моноширинный, обычный, 22"
title="Символ сердечко, шрифт моноширинный, обычный, 22" %}
Поскольку символ находится в середине строки, то на полученном изображении половина пикселей пустые.
Обходим пиксели построчно и выводим только непустые строки, то есть центральную часть изображения.
```
Monospaced.plain, 22, символы:
o o o
o o o o o o o
o o o o
o o o
o o o
o o
o o
o o
o o
o o
o o
o o
o o
o
```
{% capture collapsed_md %}
```
Monospaced.plain, 28, символы:
o o
o o o o o o o o
o o o o
o o o o
o o o
o o o
o o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o
```
```
Monospaced.plain, 36, символы:
o o o o o o o
o o o o o o o
o o o o
o o o o
o o o o
o o o
o o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
o o
```
{% endcapture %}
{%- include collapsed_block.html summary="Полный вывод" content=collapsed_md -%}
Рисуем строку текста в виде чёрно-белого изображения, затем обходим пиксели этого изображения и
выводим их текстом в консоль построчно. Рисуем только центральную часть изображения с текстом,
пустые строки пикселей не выводим.
```java
// рисуем текст в форме картинки и картинку в форме текста
public static void printTextImage(String str, Font font) {
FontRenderContext ctx = // контекст отображения шрифта
new FontRenderContext(font.getTransform(), false, false);
// получаем размеры картинки с текстом при отрисовке
Rectangle bnd = font.getStringBounds(str, ctx).getBounds();
// создаём новое бинарное чёрно-белое изображение
BufferedImage image = new BufferedImage(
bnd.width, bnd.height, BufferedImage.TYPE_BYTE_BINARY);
// включаем режим редактирования нового изображения
Graphics2D graphics = image.createGraphics();
// шрифт для отрисовки, сглаживание не используем
graphics.setFont(font);
// рисуем картинку с текстом
graphics.drawString(str, bnd.x, -bnd.y);
// отключаем режим редактирования
graphics.dispose();
// выводим заголовок
System.out.println(
font.getFontName()+", "+font.getSize()+", символы: "+str);
// обходим пиксели построчно и выводим непустые строки
for (int y = 0; y < bnd.height; y++) {
StringBuilder line = new StringBuilder();
for (int x = 0; x < bnd.width; x++)
line.append(image.getRGB(x, y) == -1 ? "o " : " ");
// рисуем только непустые строки
if (line.indexOf("o") != -1) System.out.println(line);
}
}
```
```java
// запускаем программу и выводим результат
public static void main(String[] args) {
printTextImage("", new Font(Font.MONOSPACED, Font.PLAIN, 22));
printTextImage("", new Font(Font.MONOSPACED, Font.PLAIN, 28));
printTextImage("", new Font(Font.MONOSPACED, Font.PLAIN, 36));
}
```
В последнем примере используется библиотека Java AWT.
{% capture collapsed_md %}
```java
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.image.BufferedImage;
```
{% endcapture %}
{%- include collapsed_block.html summary="Необходимые импорты" content=collapsed_md -%}

View file

@ -0,0 +1,87 @@
---
title: Генератор паролей
description: Пишем программу на JavaScript для формирования случайных 20-значных комбинаций из латинских букв, цифр и спецсимволов. На выбор 60 вариантов 4 столбца по...
sections: [Криптография,Случайные комбинации]
tags: [javascript,текст,символы,буквы,цифры,знаки,комбинации]
scripts: [/js/password-generator.js]
styles: [/css/pomodoro5.css]
canonical_url: /ru/2023/06/19/password-generator.html
url_translated: /en/2023/06/20/password-generator.html
title_translated: Password generator
date: 2023.06.19
---
Пишем программу на JavaScript для формирования случайных 20-значных комбинаций из латинских букв, цифр и
спецсимволов. На выбор 60 вариантов 4 столбца по 15 строк. Первый символ всегда буква, все символы в
каждой комбинации идут без повторов. Будем генерировать пароли для вёб-сайтов в браузере.
<div>
<input type="button" value="Обновить" title="Обновить комбинации" onclick="refresh()">
</div>
<div class="highlight">
<pre class="highlight">
<code id="combinations"></code>
</pre>
</div>
Используем символы в диапазоне от `!` до `~` и их десятичные коды от `33` до `126`.
{% capture collapsed_md %}
```
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 :
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
; < = > ? @ A B C D E F G H I J K L M N O P Q R S T
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
l m n o p q r s t u v w x y z { | } ~
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
```
{% endcapture %}
{%- include collapsed_block.html summary="Таблица символов" content=collapsed_md -%}
Три вложенных цикла: по строкам, по колонкам и по комбинациям. Получаем случайное число код символа в
диапазоне `[33-126]`, затем проверяем на соответствие условиям и добавляем в комбинацию. Первый символ
буква, все символы в каждой комбинации идут без повторов. Экранируем символы `&`, `>` и `<` для
корректного отображения в браузере. Собираем 15 строк, в каждой строке по 4 комбинации.
```js
// собираем комбинации для вёб-сайта
const generate = function() {
let text = "";
for (let row = 0; row < 15; row++) {
let line = "";
for (let col = 0; col < 4; col++) {
let combo = "";
for (let len = 0; len < 20; len = combo.length) {
const co = random("!".charCodeAt(0), "~".charCodeAt(0));
const ch = String.fromCharCode(co);
if (len == 0 && (ch >= "A" && ch <= "Z" || ch >= "a" && ch <= "z")
|| len > 0 && combo.indexOf(ch) < 0)
combo += ch;
}
line += escapeHTML(combo) + " ";
}
text += line + (row < 14 ? "\n" : "");
}
return text;
}
```
```js
// получаем случайное число в заданном диапазоне
const random = (min, max) => Math.round(min + (max-min) * Math.random());
// экранируем спецсимволы HTML для корректного отображения в браузере
const escapeHTML = (str) => str.replace("&", "&amp;").replace(">", "&gt;").replace("<", "&lt;");
// кнопка обновить на странице — обновляем комбинации
const refresh = () => document.getElementById("combinations").innerHTML = generate();
// после загрузки всех частей страницы — обновляем комбинации
document.addEventListener("DOMContentLoaded", refresh);
```
Давно пользуюсь этим алгоритмом у меня все пароли для вёб-сайтов по этой схеме сгенерированы,
поэтому рекомендую. Первая версия была написана на Java, но для вёб-сайтов проще получается на
JavaScript, чтобы далеко не ходить.

48
jekyll_site/ru/index.md Normal file
View file

@ -0,0 +1,48 @@
---
title: Код с комментариями
description: Заметки на тему программирования с примерами кода и комментариями. Решения задач и описания решений.
sections: [Решения задач и описания решений]
tags: [java,javascript,алгоритмы,реализация,текст,шрифты,комбинации,изображения,картинки,криптография]
canonical_url: /
url_translated: /en/
title_translated: Code with comments
---
{%- assign articles = "" | split: "" %}
{%- assign articles = articles | push: "Генератор паролей" %}
{%- capture article_brief %}
Пишем программу на JavaScript для формирования случайных 20-значных комбинаций из латинских букв, цифр и
спецсимволов. На выбор 60 вариантов 4 столбца по 15 строк. Первый символ всегда буква, все символы в
каждой комбинации идут без повторов. Будем генерировать пароли для вёб-сайтов в браузере.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Рисуем сердечко в консоли" %}
{%- capture article_brief %}
Напишем два варианта алгоритма на Java для вывода сердечка в консоль в форме текстового
изображения поздравим женщин с восьмым марта. Нарисуем график функции в форме сердечка
и в дополнение нарисуем символ *сердечко* в форме картинки, а картинку выведем текстом
консольное поздравление с восьмым марта.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "График функции в консоли" %}
{%- capture article_brief %}
Напишем алгоритм для вывода графика функции или системы уравнений в консоль в виде текста. Будем
использовать средства Java. Для вычислений будем использовать класс `Math`, а для обхода диапазона
координат два вложенных цикла `for`. Нарисуем в консоли график окружности и графики вписанных
в неё ромба и квадрата.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- assign articles = articles | push: "Рисуем простую капчу" %}
{%- capture article_brief %}
Напишем алгоритм для отображения текста в виде картинки с использованием библиотеки Java AWT.
Символы и шрифт могут быть любыми, но для этого примера будем использовать комбинацию заглавных
латинских букв и цифр со шрифтом *Comic Sans* будем рисовать простую капчу для сайта или блога.
Спецсимволы рассмотрим, но пользоваться ими не будем, потому что угадать их с таким оформлением
текста пользователю будет сложно. Например, плюс `+` угадать ещё можно, а вот минус `-` или
нижнее подчёркивание `_` уже с трудом, и даже если угадаешь, тогда найти эти кнопки с трудом,
особенно на телефоне. Поэтому для капчи будем использовать комбинацию только из заглавных
латинских букв и цифр.
{%- endcapture %}
{%- assign articles = articles | push: article_brief %}
{%- include main_page.html articles = articles -%}

5
package.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/bash
echo "Подготовка архива для последующего развёртывания."
cd _site || exit
rm -rf ../pomodoro5.zip
7z a ../pomodoro5.zip ./*

4
serve.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
echo "Локальное развёртывание для проверки корректности сборки."
jekyll serve --skip-initial-build --disable-disk-cache --host localhost
echo "Адрес сервера: http://localhost:4000"