2023-06-30
This commit is contained in:
parent
0adf594938
commit
2c7eefbb75
33 changed files with 2038 additions and 0 deletions
5
.gitattributes
vendored
5
.gitattributes
vendored
|
@ -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
3
.gitignore
vendored
|
@ -1,2 +1,5 @@
|
|||
.idea
|
||||
*.iml
|
||||
*.zip
|
||||
_site*
|
||||
.repo_*.sh
|
||||
|
|
64
DIRECTORY-TREE.md
Normal file
64
DIRECTORY-TREE.md
Normal 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
16
README.en.md
Normal 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
16
README.md
Normal 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
54
build.sh
Executable 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")) мс."
|
3
jekyll_site/Gemfile_color
Normal file
3
jekyll_site/Gemfile_color
Normal file
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
gem "jekyll"
|
||||
gem "color-tomato-theme"
|
3
jekyll_site/Gemfile_older
Normal file
3
jekyll_site/Gemfile_older
Normal file
|
@ -0,0 +1,3 @@
|
|||
source "https://rubygems.org"
|
||||
gem "jekyll"
|
||||
gem "older-tomato-theme"
|
20
jekyll_site/_config_color.yml
Normal file
20
jekyll_site/_config_color.yml
Normal 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
|
20
jekyll_site/_config_older.yml
Normal file
20
jekyll_site/_config_older.yml
Normal 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
|
2
jekyll_site/_includes/counters_body.html
Normal file
2
jekyll_site/_includes/counters_body.html
Normal 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 -->
|
16
jekyll_site/_includes/counters_head.html
Normal file
16
jekyll_site/_includes/counters_head.html
Normal 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>
|
8
jekyll_site/css/pomodoro5.css
Normal file
8
jekyll_site/css/pomodoro5.css
Normal file
|
@ -0,0 +1,8 @@
|
|||
input {
|
||||
font-size: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
md-content input {
|
||||
color: #1b5e20;
|
||||
}
|
224
jekyll_site/en/2023/01/04/drawing-simple-captcha.md
Normal file
224
jekyll_site/en/2023/01/04/drawing-simple-captcha.md
Normal 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).
|
147
jekyll_site/en/2023/02/06/function-graph-in-console.md
Normal file
147
jekyll_site/en/2023/02/06/function-graph-in-console.md
Normal 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
|
||||
¦
|
||||
¦
|
||||
```
|
304
jekyll_site/en/2023/03/08/drawing-heart-in-console.md
Normal file
304
jekyll_site/en/2023/03/08/drawing-heart-in-console.md
Normal 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 -%}
|
90
jekyll_site/en/2023/06/20/password-generator.md
Normal file
90
jekyll_site/en/2023/06/20/password-generator.md
Normal 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("&", "&").replace(">", ">").replace("<", "<");
|
||||
// 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
50
jekyll_site/en/index.md
Normal 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
BIN
jekyll_site/img/captcha.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
38
jekyll_site/img/circumference-equation.svg
Normal file
38
jekyll_site/img/circumference-equation.svg
Normal 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 |
BIN
jekyll_site/img/heart-graph.png
Normal file
BIN
jekyll_site/img/heart-graph.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
jekyll_site/img/heart-monospaced-plain-22.bmp
Normal file
BIN
jekyll_site/img/heart-monospaced-plain-22.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 170 B |
31
jekyll_site/img/rhombus-equation.svg
Normal file
31
jekyll_site/img/rhombus-equation.svg
Normal 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 |
76
jekyll_site/img/square-equations.svg
Normal file
76
jekyll_site/img/square-equations.svg
Normal 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 |
29
jekyll_site/js/password-generator.js
Normal file
29
jekyll_site/js/password-generator.js
Normal 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("&", "&").replace(">", ">").replace("<", "<");
|
||||
// кнопка обновить на странице — обновляем комбинации
|
||||
const refresh = () => document.getElementById("combinations").innerHTML = generate();
|
||||
// после загрузки всех частей страницы — обновляем комбинации
|
||||
document.addEventListener("DOMContentLoaded", refresh);
|
7
jekyll_site/robots.txt
Normal file
7
jekyll_site/robots.txt
Normal 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
|
223
jekyll_site/ru/2023/01/03/drawing-simple-captcha.md
Normal file
223
jekyll_site/ru/2023/01/03/drawing-simple-captcha.md
Normal 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).
|
145
jekyll_site/ru/2023/02/05/function-graph-in-console.md
Normal file
145
jekyll_site/ru/2023/02/05/function-graph-in-console.md
Normal 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
|
||||
¦
|
||||
¦
|
||||
```
|
300
jekyll_site/ru/2023/03/08/drawing-heart-in-console.md
Normal file
300
jekyll_site/ru/2023/03/08/drawing-heart-in-console.md
Normal 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 -%}
|
87
jekyll_site/ru/2023/06/19/password-generator.md
Normal file
87
jekyll_site/ru/2023/06/19/password-generator.md
Normal 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("&", "&").replace(">", ">").replace("<", "<");
|
||||
// кнопка обновить на странице — обновляем комбинации
|
||||
const refresh = () => document.getElementById("combinations").innerHTML = generate();
|
||||
// после загрузки всех частей страницы — обновляем комбинации
|
||||
document.addEventListener("DOMContentLoaded", refresh);
|
||||
```
|
||||
|
||||
Давно пользуюсь этим алгоритмом — у меня все пароли для вёб-сайтов по этой схеме сгенерированы,
|
||||
поэтому рекомендую. Первая версия была написана на Java, но для вёб-сайтов проще получается на
|
||||
JavaScript, чтобы далеко не ходить.
|
48
jekyll_site/ru/index.md
Normal file
48
jekyll_site/ru/index.md
Normal 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
5
package.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
echo "Подготовка архива для последующего развёртывания."
|
||||
cd _site || exit
|
||||
rm -rf ../pomodoro5.zip
|
||||
7z a ../pomodoro5.zip ./*
|
4
serve.sh
Executable file
4
serve.sh
Executable file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
echo "Локальное развёртывание для проверки корректности сборки."
|
||||
jekyll serve --skip-initial-build --disable-disk-cache --host localhost
|
||||
echo "Адрес сервера: http://localhost:4000"
|
Loading…
Add table
Reference in a new issue