OmniAICreator/Qiita-1.07M huggingface dataset:
https

```shell
sudo apt install -y certbot
```

很多文章推荐使用 snap 安装软件

```
sudo apt remove certbot

sudo apt install snapd
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
```

```
sudo certbot certonly -d abc.com # 不要启动 nginx，不要占用 80 端口，不要开启 proxy

Saving debug log to /var/log/letsencrypt/letsencrypt.log

How would you like to authenticate with the ACME CA?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: Apache Web Server plugin (apache)
2: Nginx Web Server plugin (nginx)
3: Spin up a temporary webserver (standalone)
4: Place files in webroot directory (webroot)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-4] then [enter] (press 'c' to cancel): 3
Requesting a certificate for abc.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/abc.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/abc.com/privkey.pem
This certificate expires on 2022-08-06.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
 * Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
 * Donating to EFF:                    https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

```

## nginx

```conf
server {
  listen 443 ssl;
  server_name abc.com def.com;
  root /var/www/html;
  index index.html index.htm index.nginx-debian.html;

  ssl_certificate /etc/letsencrypt/live/abc.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/abc.com/privkey.pem;

  # ssl 验证相关配置
  ssl_session_timeout  5m;    #缓存有效期
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; # 加密算法
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;    #安全链接可选的加密协议
  ssl_prefer_server_ciphers on;   #使用服务器端的首选算法

  location ^~/rpc/ { # 访问 abc.com/api/，实际访问的是 http://127.0.0.1:3000/
    proxy_set_header Host $host;
    proxy_set_header  X-Real-IP        $remote_addr;
    proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://127.0.0.1:3000/;
    # proxy_http_version 1.1; # ssl websocket
    # proxy_set_header Upgrade $http_upgrade; # ssl websocket
    # proxy_set_header Connection upgrade; # ssl websocket
  }
}

server {
  listen 80;
  server_name abc.com def.com;
  return 301 https://$server_name$request_uri; #访问 http 转发到 https
}
```

---

参考：

https://www.linode.com/docs/guides/enabling-https-using-certbot-with-nginx-on-ubuntu/

https://gist.github.com/soheilhy/8b94347ff8336d971ad0

https://diamondfsd.com/lets-encrytp-hand-https/

https://segmentfault.com/a/1190000022673232
[LiveView] phx_gen_authで認証したcurrent_userをLiveViewで取得する方法

前提： Mix taskを下記のように実行した

```
mix phx.gen.auth Accounts User users
```

###結論
mountするときに第二引数でsession情報を取得し、assignする

```:elixir
  @impl true
  def mount(_params, %{"user_token" => user_token}, socket) do
    {:ok, assign(socket, %{
      current_user: Accounts.get_user_by_session_token(user_token),
      ...
    })}
  end
```
Laravel 【入門】Policy URLを直接打ち込んでページに不正アクセスされるのを防ぐ！

# はじめに
ページのURLを知られると<font color="red">__他人の下書き記事にもアクセスできてしまいます。__</font>
例えばQiitaの記事編集画面のURL(下記URLの赤い部分)を打ち変えれば、他人の記事下書き編集画面にアクセスできてしまいます・・・と言いたいところですが、さすがにアクセス出来ないように処理されています。
このように不正な直リンクを防止するPolicyという機能があるので、実装方法をシンプルに紹介します。

【qiitaの下書き記事のURL】
qiita.com/drafts/<font color="red">この部分</font>/edit

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [Policyファイル作成](#policyファイル作成)
2. [Policyファイル編集](#policyファイル編集)
3. [ControllerにPolicyを追加](#controllerにpolicyを追加)

<!-- 各チャプター -->
# Policyファイル作成
ArticlePolicyの部分は任意に変更して下さい。
今回はQiitaの記事なので、Article(記事)という名前のポリシーファイルを作成します。
※命名規則はアッパーキャメル

```
$ php artisan make:policy ArticlePolicy
```

# Policyファイル編集
app/Policies/ArticlePolicy.phpに移動します。
editArticleを追記し、その中に条件を記述します。この条件がtrueになるもののみ下書き記事にアクセスできる様にします。

```
<?php

namespace App\Policies;

// Articleモデルをuse宣言
use App\Models\Article;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;

class ArticlePolicy
{
    use HandlesAuthorization;

    /**
     * Create a new policy instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    // 下記追加
    public function editArticle(User $user, Article $article)
    {
        // ログインしているユーザーのid($user->id)と
           記事を書いたユーザー($article->user_id)のidが同じならture
        return $user->id === $article->user_id;
    }
}
```


# ControllerにPolicyを追加
PolicyのeditArticleがtrueの場合のみ、記事の下書きページに遷移できる様になります。
それ以外のユーザーはHTTPレスポンス403の画面に遷移する為、他人の記事に不正アクセス出来ません。

```
// ArticleController.php

public function edit(Article $article)
{
    // 下記追記
　　　　　　　　$this->authorize('editArticle', $article);
    return view('user.article.edit', ['article' => $article]);
}
```
ユーザ（グループ）・コマンド・引数（ファイル）を限定して、ルート権限（sudo）を可能にする

root権限が必要な作業があるが全機能開放が不可なので、ユーザ・コマンド・操作対象ファイルを限定してルート権限を委譲する。個人だと全委任でよいのだが、複数人が携わるPRJや、セキュリティ対策のため開発者がrootパスワードを知り得ない場合でも、root権限を限定して使用可能とするため。

# 基本的な考え方
+ ユーザ・グループ : ユーザに対し補助グループを割り当てて、補助グループに対してsudo設定をする。
+ sudoers : 利用者には、sudoコマンドを使用させるがsudo可能なコマンドを限定する

# 設定例
## ユーザ設定
- ユーザ「foo,bar」はすでに作成されている前提。
- 新たにグループ「SUDO1」を作成し、「foo,bar」の補助グループとして割り当てする。グループIDは5000とするが(-g 5000)任意設定可能。

```bash:
## グループ追加
# groupadd -g 5000 SUDO1
# getent group
	foo:x:1001:
	bar:x:1002:
	SUDO1:x:5000:
## ユーザに補助グループを割り当て
# usermod -a -G SUDO1 foo 
# usermod -a -G SUDO1 bar
# id foo; id bar
uid=1001(foo) gid=1001(foo) groups=1001(foo),5000(SUDO1)
uid=1002(bar) gid=1002(bar) groups=1002(bar),5000(SUDO1)

```

## sudoers
ローカルホストのシスログを解放するので

+ sudo可能なホストは「localhost」
+ sudo可能なコマンドは、コマンド＋引数で指定する
+ sudo可能なユーザは、グループで指定する

```bash:/etc/sudoers
Host_Alias H_LOCAL = localhost
Cmnd_Alias C_MESSAGES1 = /bin/view /var/log/messages*
Cmnd_Alias C_MESSAGES2 = /bin/cp   /var/log/messages*
Cmnd_Alias C_MESSAGES3 = /bin/tail -f /var/log/messages*

# who  where   = (as_whom)  what
%SUDO1 H_LOCAL = (ALL) NOPASSWD: C_MESSAGES1, C_MESSAGES2, C_MESSAGES3
```

+ %SUDO1 : グループ「SUDO1」に許可する
+ H_LOCAL : loalhostから
+ (ALL) NOPASSSWD: : どのユーザにでもsudo可能で、パスワード確認を省略する
+ C_MESSAGESxx : sudo可能なコマンドを指定する。Alias定義で引数を指定しているので、指定された引数意外の場合は許可されない。

[参考:sudoersの記法](https://qiita.com/progrhyme/items/6f936033b9d23efb1741)
[参考:sudo](https://xtech.nikkei.com/it/article/COLUMN/20071205/288862/)

# トレーサビリティ
ユーザfooが ``` sudo view /var/log/messages ```　を実行した時

``` bash:/var/log/secure
Nov  7 10:13:01 localhost sudo[13450]:     foo : TTY=pts/1 ; PWD=/home/admin ; USER=root ; COMMAND=/bin/view /var/log/messages
```
小ネタ／Flutter で AWS S3 へのアクセスに minio を使う

Flutter で AWS のサービス・リソースにアクセスするときに使うライブラリは、公式には Amplify Flutter に集約されてきており、S3 へのアクセスも **[amplify_storage_s3](https://pub.dev/packages/amplify_storage_s3)** を使うのがスタンダードです。

ただ、アプリケーションで内部的なデータバックアップ目的に S3 を使うなど、

 - Cognito の認証は必要ない
   - かといってゲストアクセス可能な状態では使いたくない
 - アクセスキー・シークレットアクセスキーで手軽に使いたい

というニーズには合いません。

そのような場合に使える Flutter のライブラリもいくつかあるようですが、今回は S3 互換ストレージとして有名な Minio の非公式クライアントライブラリ **[minio](https://pub.dev/packages/minio)**（3.0.0）を使ってみました。

※こちらのアプリケーションに組み込んで使っています。

 - **[hmatsu47/maptool](https://github.com/hmatsu47/maptool)（GitHub）**

# 使い方

ほぼサンプルページにあるとおりですが、東京リージョンの S3 バケットを使う場合は、

 - エンドポイントの指定を東京リージョンに合わせる
 - リージョンを指定する

必要があります。

※最初に試したとき、サンプルに書かれていなかったのでリージョンの指定を忘れていて時間を溶かしました。

- `pubspec.yaml`

```yaml:pubspec.yaml
dependencies:
  minio: ^3.0.0
```

## 初期化

```dart:初期化
import 'package:minio/io.dart';
import 'package:minio/minio.dart';

final minio = Minio(
    endPoint: 's3-ap-northeast-1.amazonaws.com',
    region: 'ap-northeast-1',
    accessKey: '【アクセスキー】',
    secretKey: '【シークレットアクセスキー】',
    useSSL: true,
  );
```

前述のとおり、エンドポイントとリージョンの指定がポイントです。

---
**2022/11/3 追記：**
`minio`の代わりに最新ライブラリに対応した`minio_new`が提供されるようになりました。

基本的な使い方に変更はありません。

- `pubspec.yaml`

```yaml:pubspec.yaml
dependencies:
  minio_new: ^1.0.1
```

- 初期化

```dart:初期化（import部分のみ）
import 'package:minio_new/io.dart';
import 'package:minio_new/minio.dart';
```
---

## アップロード

```dart:アップロード
    await minio.fPutObject('【S3バケット名】', '【S3オブジェクトキー名】', '【アップロードするファイルのパス名】');
```

## ダウンロード

```dart:ダウンロード
import 'dart:io';

    final stream = await minio.getObject('【S3バケット名】', '【S3オブジェクトキー名】');
    await stream.pipe(File('【ダウンロード先のファイルパス名】').openWrite());
```

ダウンロードは単純に`fGetObject()`ではできないようですね。

# その他

残念ながら現時点（3.0.0）では大阪リージョンには対応していないようなので（それ以前にソウルリージョンなども未対応）、大阪リージョンで使いたい場合はこのファイルの内容を書き換える必要がありそうです。

 - **[minio-dart/lib/src/minio_s3.dart](https://github.com/xtyxtyx/minio-dart/blob/master/lib/src/minio_s3.dart)**
【Rails】日本語に変換したcreated_atを配列にする

初学者のインプット内容の整理のための記事です。
'rails-i18n'gemを使ってモデルのcreated_atを日本語で配列としてインスタンス変数に保存する方法です。

参考にしたページ：
https://opiyotan.hatenablog.com/entry/rails_gem_i18n
https://teratail.com/questions/53958


#準備

```Gemfile.
#追加
gem 'rails-i18n'
```
```
bundle install
```

次にconfig/locales/ja.ymlを作成する。
rails-i18n/ja.yml at master · svenfuchs/rails-i18n · GitHub　の内容をそのファイルにコピペする。

#配列取得


```
#通常の実行結果
@items = @user.items.map{|item| item.created_at}
puts @items
=> 2021-11-07 21:09:50 +0900
   2021-11-07 21:07:41 +0900
   2021-11-03 21:43:22 +0900
   2021-11-03 21:43:19 +0900
```

```
#I18nを利用した実行結果
@items = @user.items.map{|item| I18n.l(item.created_at)}
puts @items
=> 2021年11月07日(日) 21時09分50秒 +0900
   2021年11月07日(日) 21時07分41秒 +0900
   2021年11月03日(水) 21時43分22秒 +0900
   2021年11月03日(水) 21時43分19秒 +0900
```
【CSS】リンクの下線を消す方法

　今回はCSSでリンクの下線を消す方法を解説していきたいと思います。
下記は何もスタイルを指定していない状態のリンクになります。ブラウザによって多少は異なりますが、青色で下線の付いたテキストになります。

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <a href="#">下線ありリンク</a>
　</body>
</html>
```
![下線ありリンク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646368/56690983-3225-1341-08a3-e503783a8ff0.png)

文字に下線を付けるスタイルはtext-decoration: underline;です。
リンクにはこのスタイルが自動で適用されていると考えてください。

#全てのページのリンクの下線を消す方法
　全てのページリンクの下線を消すには、すべてのaタグに対してtext-decoration:none; のCSSを指定しましょう。

```index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <a href="#">下線なしリンク</a>
　</body>
</html>
```

```style.css
a {
    text-decoration:none; 
}
```
![下線なしリンク.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646368/8740a686-d81a-6781-1fc4-4a5b8861904f.jpeg)

#マウスオーバーしたときのみ下線を表示する
　リンクの下線を消していると、リンクかどうかわからなくなってしまいます。
そのため、マウスオーバーしたときのみ下線を表示したい場合があります。カーソルが当たっている状態は:hover疑似クラスで指定できます。


```index.html
<a href="#">下線なしリンク(ホバーで下線表示あり)</a>
```

```style.css
a {
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}
```
「全てのリンクではなく、特定のリンクのみ設定を変えたい」という場合は、専用のclassやidを作成して設定しましょう。
QittaでMarkdownを使ってみる！

分からないことがあって検索すると出てくる、こういうブログのことを「技術ブログ」って言うらしいです。
IT技術的なことを勉強していこうかと思うのですが、覚えたことをすぐ忘れてしまうので、自分のメモ代わりにも学んだことを書いて行こうかなと思います。
さあ、書くぞ！って思ったんですが・・・
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2251471/198b66d9-fae7-2f99-28b0-e7f2088af302.png)
Markdown記法ってなんだ？？
というわけで、まずはMarkdown記法というものを勉強していこうと思います。


<details><summary>目次</summary>
[1.見出し](#1見出し)
[2.ページ内リンク](#2ページ内リンク)
[3.折りたたみ](#3折りたたみ)
[4.引用](#4引用)
[5.コード](#5コード)
[6.リンク](#6リンク)
[7.コードの挿入](#7コードの挿入)
[8.装飾文字とリスト](#8装飾文字とリスト)
[9.ほかのページを参考にする](#9ほかのページを参考にする)
</details>

#1.見出し
見出しの出し方です
>#見出し1
##見出し2
```markdown
#見出し1
##見出し2
```

#2.ページ内リンク
ページ内リンクです。目次に使おうと思います。
半角記号は-（ハイフン）と_（アンダーバー）以外
`!@#$%^&*()+|~=[]{};':",./<>?`は省略しないとうまくいかないので注意
>
目次: [2.目次](#2目次)
>
```markdown
目次: [2.目次](#2目次)
```

#3.折りたたみ
目次は邪魔なので折りたためるようにしたいです。
>
<details><summary>折りたたみ1</summary>
・目次: [2.目次](#2.目次)
</details>
>
```markdown
<details><summary>折りたたみ1</summary>
・目次: [2.目次](#2.目次)
</details>
```

#4.引用
引用に使うものらしいのですが、読みやすさのために使おうと思います。
>引用
>>引用の中に引用も書けます
>
```markdown
>引用
>>引用の中に引用も書けます
```

#5.コード
背景が黒くなります。「`」は「Shift+@」です。

>
```markdown
マークダウンのコードを記述します。
```
```markdown
```markdown
マークダウンのコードを記述します。
　```←先頭の空欄は要らないのですが、エスケープできないので…
```

#6.リンク
普通のリンクです。文字を指定しなくて良いならそのままでもリンクになりそうです。

>
https://qiita.com/Qiitta
[Qiita](https://qiita.com/Qiitta)
>
```md
https://qiita.com/Qiitta
[Qiita](https://qiita.com/Qiitta)
```

#7.コードの挿入
>`shift + @`で挟むとコードの挿入ができます。
>
```md
`shift + @`で挟むとコードの挿入ができます。
```

#8.装飾文字とリスト
`tab` + `-`でリストが一段下がりそうです。
装飾文字も色々あります。

>
- リスト
    - 色文字：<font color="Red">色文字</font>
    - 強調：*kyotyo*
    - 太字：**太字**
    - 強調+太字:***kyotyofutoji***
    - 打消し線：~~打消線~~
    
>水平線
***

>
```md
- リスト
    - 色文字：<font color="Red">色文字</font>
    - 強調：*kyotyo*
    - 太字：**太字**
    - 強調+太字:***kyotyofutoji***
    - 打消し線：~~打消線~~
水平線
***
```

#9.ほかのページを参考にする
良いなと思った記載の仕方があれば、
`ページのURL + .md`と打てば、マークダウンの記載方法で出力されるので、パクれそうです。
Unit Test/Integration Test/E2Eテストとは何かを勉強する

# ユニットテスト（Unit Test） 

- 別名：単体テスト
- クラスやメソッド単体の小さい範囲でテストすること
- 様々な部品が組み合わさって動くソフトウェアのテストとしては不十分
- ローカル環境で実施することが多い

https://www.slideshare.net/UnityTechnologiesJapan002/unite-tokyo-2019unity-test-runner


## メリット

- 1つ1つのテスト範囲が小さいので、素早く実行できる
    - バグを早く発見できる
- コード変更によるバグ混入を予防する
- コード変更が正しいか確認できる
- 再現率の低い条件を作りやすい

## 注意点

- テスト項目を増やすとバグ発見率は上がるが、その分コストもかかってしまう
    - どこまでやるか、ゴールを明確にする
- 適切なテストでないと、品質が上がることはない
    - 設計から間違えていたら意味がない
- 書けば終わりではない
    - 何度も実行することが重要
    - JenkinsなどのCIを用意して、自動でテストが実行される環境を構築しておくとよい
- ユニットテスト導入のコストは高い
    - 実装コストの2倍以上を見積もるべき
    - テストにおけるパターンを網羅するために様々な状況やテストデータを検討する必要がある
    - 運用保守体制も計画的に

https://dev.classmethod.jp/articles/10_errors_about_unit_testing/

## Unity でのユニットテストツール

- Unity Test Runner
    - Unityのテスト実行ツール
    - NUnit という.NET用テスティングフレームワークが使われている
    - EditMode, PlayMode のテスト実行環境がある

# インテグレーションテスト（Integration Test）

- 別名：結合テスト
- 他のクラスや外部モジュールと結合してテストすること
- 実際の環境に近いテスト環境で実行することが多い
- 機能間の連携や一連の機能が仕様書通りに正しく動作するか確認する
- 最下位のモジュールから上位に向かって順番にテストしていく方式を「ボトムアップテスト」
- 最上位のモジュールから下位に向かって順番にテストしていく方式を「トップダウンテスト」

https://www.testim.io/blog/end-to-end-testing-vs-integration-testing/

## メリット

- 機能間の連携や一連の機能が仕様書通りに正しく動作するか確認できる
- ユニットテストより高レベルのため、アプリケーション全体のテストガバレッジを向上させる傾向がある
- E2Eテストのような、より高いテストの基礎になる

## 注意点

- 本番環境に近い環境、データでテストする
- DBなどのデータを直接書き換えたりしない
    - 想定していないデータができることを防ぐ
    - アプリケーションの機能を使って変更する
- テストスケジュールに余裕をもたせる
    - 設計上のミスや単体テストのケース漏れなどがこの段階で発覚する可能性がある
    - 手戻りによる大きな時間ロスが発生する可能性がある

## Unity でのインテグレーションテストツール

- Scene ベースのテストは、Poco や AltUnityTester を検討するべき
    - どちらもUIテストができる、UIテストツール

https://baba-s.hatenablog.com/entry/2018/10/03/090000

https://www.slideshare.net/nowsprinting/altunitytester-gotandaunity-98287251

# E2Eテスト（End to End Test）

- システム全体を通してテストすること
- ユーザーと同じようにシステムを操作して、挙動が想定通りになっているか確認する
- アプリケーションの様々なシステムやレイヤーを検証できる

## メリット

- UIからデータベース層まで、すべて期待通りに動作していることを確認する
- エンドユーザーがバグを発見する前にバグを発見することが出来る
- アプリの全体的なテストカバレッジが向上する

## 注意点

- 様々な手法があるので、導入コスト・運用コストが高い
- メンテナンスが大変
    - 細かいUIのテストを実装し、ちょっとした文言変更、レイアウト変更でテストが失敗する
- テストの実行時間は長くなりがち
    - 並列実行などを検討する
    - どの領域をテストするか明確にしておく

https://commerce-engineer.rakuten.careers/entry/tech/0031

## Unity でのE2Eテストツール

- Airtest + Poco など

https://learning.unity3d.jp/6694/
【Node.js】Error: error:0308010C:digital envelope routines::unsupported【エラー】

##発端
https://ja.reactjs.org/docs/create-a-new-react-app.html#create-react-app
create-react-appしてnpm startを叩いても開発サーバーが起動しないというエラーにハマったのでメモ

##環境
macOS Catalina v10.15.6
Node.js v17.0.1

##エラー

```text
Starting the development server...

/Users/xxxx/xxxx/React_Practice/my-app/node_modules/react-scripts/scripts/start.js:19
  throw err;
  ^

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:67:19)
    at Object.createHash (node:crypto:130:10)
    at module.exports (/Users/xxxx/xxxx/React_Practice/my-app/node_modules/webpack/lib/util/createHash.js:135:53)
    at NormalModule._initBuildHash (/Users/xxxx/xxxx/React_Practice/my-app/node_modules/webpack/lib/NormalModule.js:417:16)
    at /Users/xxxx/xxxx/React_Practice/my-app/node_modules/webpack/lib/NormalModule.js:452:10
    at /Users/xxxx/xxxx/React_Practice/my-app/node_modules/webpack/lib/NormalModule.js:323:13
    at /Users/xxxx/xxxx/React_Practice/my-app/node_modules/loader-runner/lib/LoaderRunner.js:367:11
    at /Users/xxxx/xxxx/React_Practice/my-app/node_modules/loader-runner/lib/LoaderRunner.js:233:18
    at context.callback (/Users/xxxx/xxxx/React_Practice/my-app/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
    at /Users/xxxx/xxxx/React_Practice/my-app/node_modules/babel-loader/lib/index.js:59:103 {
  opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

Node.js v17.0.1
```

##原因
https://github.com/webpack/webpack/issues/14532
どうやらNode.jsの最新バージョン(2021/11/07時点 v17.0.1)が対応していなかったらしいです。

##対処法
Node.jsのバージョンを下げる。
推奨版(2021/11/07時点 v16.13.0)に切り替えて再度npm startしたら無事に開発サーバーが起動しました。めでたしめでたし。
【JavaScript】メールアドレスとパスワードでよくある正規表現を理解する

#はじめに
こんにちは。
こちらの記事では、メールアドレスとパスワードでよくある正規表現を理解する方法を記しています。
誤っている点がございましたらコメントいただけると幸いです。

##正規表現とは
正規表現について簡単に説明すると、特殊文字の組み合わせにより、使用したい文字を指定することができます。よく使われる場面は、郵便番号で数字とハイフン`-`を指定したり、今回のようにメールアドレスとパスワードのときに用いられます。

>参考記事：https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions

##前提
こちらの[前回の記事](https://qiita.com/YuStarrr/items/989deeb6e117278f6352)で正規表現を用いたのですが、理解を深められるよう、下記のメールアドレスとパスワードに関して解説していきます。

```javascript:
//メールアドレスの正規表現
/^[A-Za-z0-9]{1}[A-Za-z0-9_.-]*@{1}[A-Za-z0-9_.-]{1,}\.[A-Za-z0-9]{1,}$/

//パスワードの正規表現
/^(?=.*?[a-z])(?=.*?\d)[a-z\d]{8,20}$/i;
```
検索すれば正規表現の記事はたくさん出てきますが、今回使用するもののみ紹介したいと思います。

| 特殊文字 | 文字の簡単な説明 |
|:-:|:-:|
|  ^ | 先頭の文字と一致  |
| $  | 末尾の文字と一致  |
|  {1} | 直前の文字を1回一致  |
| {1,}  | 直前の文字を1回以上一致  |
|  {8,20} |  直前の文字を8回〜20回一致 |
| [A-Za-z0-9]  | 大英字または小英字または数字のいずれかと一致  |
| [_.-]  | アンダースコアまたはドットまたはハイフンのいずれかと一致  |
| *  |  直前の文字の0回以上一致 |
| \  |  直後の特殊文字を通常文字として認識（エスケープ） |
|  ? |  直前の文字0回か1回は一致 |
|  . | 改行文字を除外して1文字と一致  |
| \d  | 数字と一致  |
| i  |  大小英字を区別しない（末尾のオプション） |

>参考記事：https://qiita.com/iLLviA/items/b6bf680cd2408edd050f

###※追記（2021年11月8日現在）

| 特殊文字 | 文字の簡単な説明 |
|:-:|:-:|
|  + | 直前の文字の1回以上一致  |
| \w  |  大英字または小英字または数字またはアンダースコアのいずれかと一致 |

##解説
メールアドレス、パスワードの順に解説していきます。

###メールアドレスの正規表現
ポイントとしては、かっこの中で正規表現の特殊文字を指定していると思われるかもしれませんが、角かっこ`[]`内だと普通の文字として認識されます。また、バックスラッシュ`\`で特殊文字も普通の文字として認識されます。
もちろんメールアドレスなので、アットマーク`@`は１文字は必ず指定します。


```javascript:
/^                    // 正規表現の範囲宣言。
[A-Za-z0-9]{1}        // 大小英数字のうち、1回は一致させる。
[A-Za-z0-9_.-]*       // 大小英数字または記号の中で、0回以上一致させる。
@{1}                  // @を1回は一致させる。
[A-Za-z0-9_.-]{1,}    // 大小英数字または記号の中で、0回以上一致させる。
\.                    // .を文字として認識。
[A-Za-z0-9]{1,}       // 大小英数字のうち、1回以上は一致させる。
$/                    // 正規表現の範囲宣言。
```

###※追記（2021年11月8日現在）
コメントでご指摘をいただき、メールアドレスの正規表現は下記のように書き換えられるようです！
メールアドレスも、大小英字を区別する必要がないので`i`オプションを末尾に追加しました！

```javascript:
//メールアドレスの正規表現
/^[a-z\d][\w.-]*@[\w.-]+\.[a-z\d]+$/i
```

* `[0-9]`　→　`\d`
* `{1}`　→ `省略`
* `[A-Za-z0-9_]`　→ `\w`
* `{1,}` → `+`



###パスワードの正規表現
数字を表現するのに`[0-9]`ではなく`\d`を使用している。また、パスワードはセキュリティの観点から、英数字を含めて文字数範囲も指定している。

```javascript:script
/^                    // 正規表現の範囲宣言。
(?=.*?[a-z])          // 小英字を１文字以上含める。
(?=.*?\d)             // 数字を１文字以上含める。
[a-z\d]               // 小英数字１文字以上含める。
{8,20}                // ８文字以上、20文字以下。
$/i                   // 正規表現の範囲宣言と大小英字を区別しない。
```

<br>


#おわりに
ここまで正規表現について解説してみました。
自分の調べた範囲内での情報なので、よりいい方法があったら教えていただけると助かります！
以上、最後まで読んでいただきありがとうございました！
よければLGTMを押してくれると嬉しいです！
Ubuntu20.04でApache Jmeterをインストール

## 結論
普通にこっちがありました。

``` bash
sudo apt install jmeter
```
起動は下記コマンド実行のみ（GUIモードで立ち上がります）

```bash
jmeter
```

## 経緯
http://jmeter.apache.org/download_jmeter.cgi

ググると公式からダウンロードしてきて解凍して、といった記事がヒットしますが何故かサクッとできず、途中エラーメッセージで普通にaptで行けることを知りました。
こっちの方が簡単なので、似たような状況の方に届くといいなと思います。
[atcoder] ABC226 涙の反省記事

こんばんは。たゅと申します。

ABC226にpython3で参戦。

https://atcoder.jp/contests/abc226/tasks

三完で入茶させてクレメンスと息巻いていたところ、なんと__ABを通すのに40分+5ペナ__という最悪の事態に。

![2021-11-07 22.40のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623784/165efb71-830e-91fc-dede-ed5b7ec8485e.jpeg)


Cは推定茶色中盤diffだったので、むしろよく粘ったと自分では納得しています。しかし、ABでここまで詰まることは完全に想定外だったので、コンテスト中は狂いそうでした。

この悔しさをなんとかポジティブな方向に昇華するために、記事を書いております。

概要としては、
__ABC226のA,B問題について、python3で解説します。__
Cも後で解答を見て余裕があれば復習として追記したいと思います。

## A問題
https://atcoder.jp/contests/abc226/tasks/abc226_a

小数点第3位までの小数が与えられ、四捨五入する問題です。
これだけ見ると猿でも解けそうなのですが、__浮動小数点の問題（多分）__でまさかの2ペナ。デカい声を出してしまいました。

__roundを使うとなんかWAが出る__ので、適切に処理する必要があります。

__ポイントとして、入力はかならず`3.000`のような形でされるという制約があります。__
さらに、__X < 100の制約より、入力をstringとして受け取った場合のlengthは必ず5か6になります。__

このことを利用して、桁数でif文を分岐させ、それぞれ小数点第一位になる部分が5以上であるかどうかを判別し、四捨五入の実装を行います。

ACのコードはこちらです。

~~~python
X = input()

if len(X) == 6:
    if int(X[3]) >= 5:
        print(int(float(X))+1)
    else:
        print(int(float(X)))
else:
    if int(X[2]) >= 5:
        print(int(float(X))+1)
    else:
        print(int(float(X)))

~~~

printのところで`int(float(X))`のように書いていることに注意してください。
`int(X)`と書くとエラー出ます。

ホンマ狂うって〜〜〜〜〜〜〜

## B問題

https://atcoder.jp/contests/abc226/tasks/abc226_b

リストのリスト（こういうの二次元配列って言うんですよね？？？）を受け取り、ユニーク化する問題。
__普通にリストのリストを作って`set(list(li))`すると、`TypeError: unhashable type: 'list'`が出ます。__
__全探索も、`N <= 2 * 10 ** 5`の制約より、余裕でTLEします__。
よって、計算量的にOKかつエラーを吐かせない工夫をする必要があります
Bで計算量削減の問題出されるとはマジで思ってませんでした。。。

コンテスト中に対処法をググりました。

https://lanchesters.site/python-list-uniq/#2

こちらの記事の2の項を参考にしました。
要は、__「リストのリストをユニーク化することはできないよ！こういうことがしたいときは、タプルのリストに変換しよう！」__ということですね。

ACのコードはこちらです。

~~~python
N = int(input())
li = []

for i in range(N):
    sm_li = list(map(int, input().split()))
    li.append(sm_li)

li_t = list(map(tuple, li))

li_u = set(list(li_t))

print(len(li_u))

~~~

本質的に重要なのは以下の部分です。

~~~python
li_t = list(map(tuple, li))

li_u = set(list(li_t))
~~~

__一旦リストのリストをタプルのリストに変換してからユニーク化しましょう。__

## 自分のコンテスト結果

![2021-11-07 23.12のイメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623784/cf73b97d-0551-70a5-e33b-efe630451a71.jpeg)

耐えた〜〜〜〜〜〜〜〜〜〜〜〜

ほな、また......
AtCoder ABC226 挑戦！(Python)

ABC226、コンテスト8回目の挑戦です！
C問題が手も足も出ませんでした。。。解説を見ても何を言ってるのかまったくわからず、アルゴリズムの勉強が必要だと感じました。武器が足りない。

AtCoder Problemsを見ると、Difficulty=539となってて、今までのC問題が、300-400くらいだったのを考えると、やはり体感通り難しかった模様。(めちゃくちゃ難しいというレベルではないようだが) レートも、ABしか解いてないけど、20くらい上がってた。

```ruby:ABC225A
X=input()
from decimal import Decimal, ROUND_HALF_UP, ROUND_HALF_EVEN

print(Decimal(str(X)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
```
最初round()関数でやってたら、なぜかWA。
pythonのround()関数は、銀行丸めという方法なので、エラーが出た模様。

```ruby:ABC226B
N=int(input())

L_list=[]

#文字列として、それぞれを格納する。
for i in range(N):
    a=input().strip()
    L_list.append(a)
# print(L_list)

#L_listの中に、何種類のユニークなリストがあるか。
print(len(set(L_list)))
```
数列をL_listにリストで格納して、set()でユニークな要素の数を出力。この辺は、これまでに類題解いてるのでパッと解けるようにはなった。

問題のC問題については、全く方針が浮かばず、途中であきらめた。
サンプルケース自体は、後ろから必要な技の時間を足していけば、答えは出るのだが、サンプルケース以外のケース、
例えば、技4つの場合で、
4
1 0
1 1 1
1 1 2
1 1 3

などの場合に、
4つ目の技の時間+3つ目の技の時間に加えて、
3つ目の習得に必要な技
→上記だと技2

さらに、技2には、技1 が必要、、、
と考えていくと、連鎖的に、同じような処理を何回もしないといけなくて、どうやって実現できるのかがわからなかった。

完全に敗北しました。わかりやすい解説を探して勉強します。。。

お疲れさまでした。
M1 MacでAndroidエミュレーターを起動する

# はじめに

Flutterのアプリ開発をしようとしてめちゃくちゃハマりました。

## Flutterのチュートリアル

https://flutter.dev/docs/get-started/test-drive?tab=terminal

iOSはこれ見ながらやれば大丈夫です。

問題はAndroid

## 何が問題か

手順の途中で `flutter doctor` でそれぞれのプラットフォームが起動準備できているか確認します。

iOS であれば XCode, Android であれば Android Studioを事前にインストールしておきましょう。

しかし、AndroidについてSDKがないと怒られました。

## 解決策

SDKを手動で入れます。

まず、JDKを入れましょう。とりあえず brew で最新stableをインストールしましょう。

```sh
$ arch -arm64 brew install openjdk
```

次に sdkmanager と呼ばれる Android SDK用のCLIをインストールします。

https://developer.android.com/studio?utm_source=android-studio#command-tools

```sh
# 解凍したものを、~/Library/Android/sdk/cmdline-tools/latest に配置します
# ~/Library/Android/sdk/cmdline-tools/latest/bin へのパス通しも忘れずに
$ sdkmanager --list

# 上記の結果からインストールしたいものを選択してインストール
$ sdkmanager "*****"
```

ここでSDKのインストールまでは良かったのですが、Flutterでは`build-tools`が必要なのです。
これがインストールできない。

```sh
$ sdkmanager "build-tools:*.*.*"

Warning: Dependant package with key emulator not found!                         
Warning: Unable to compute a complete list of dependencies.
```

CLIだと原因が出ませんが、同様のコマンドをAndroid Studioで実行するとどうやらエミュレーターが事前に必要とのこと。

なので以下を実行してインストールします。

```sh
$ sdkmanager --channel=3 emulator
```

もう一度実行

```sh
$ sdkmanager "build-tools;*.*.*"
[=======================================] 100% Unzipping... android-Sv2/zipalign
```

これでいけるはず

```sh
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.3, on macOS 12.0.1 21A559 darwin-arm, locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 32.0.0-rc1)
    ! Some Android licenses not accepted.  To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.61.2)
[✓] Connected device (1 available)
```

ライセンスに同意して

```sh
$ flutter doctor --android-licenses
```

これで、、、

```sh
$ flutter doctor                   
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.3, on macOS 12.0.1 21A559 darwin-arm, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0-rc1)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.61.2)
[✓] Connected device (1 available)

• No issues found!
```

あとは公式ドキュメントの手順でエミュレーターを起動してプロジェクト作成すれば完了です。

長かった。。。3時間は溶けた。
LPIC Level1 5日目

#初めに

LPIC試験の勉強をしていて、勉強したものをまとめています。
ご指摘等ございましたらご教授下さい。


#シェル

##シェルの役割と基本を知ろう

コマンドを入力してEnterを押すと、コマンドが実行されて実行結果が表示されます。
コマンドの入力を受け、処理をして、結果を表示しているのがシェルです。
ユーザーが入力したコマンドをカーネルに実行させる翻訳者の役割です。
また、プロンプトを表示しているのもシェルです。

Linuxのシェルはbashです。psコマンドでシェルを確認できます。
システムで利用可能なシェルは/etc/shellsファイルで確認できます。

###標準入出力

Linuxで実行されるプログラムにはデフォルトで3つの出入り口があります。
まず、プログラムは標準入力からの入力を受けます。
そして、標準出力はプログラムの実行結果が、標準エラー出力はプログラムのエラー結果が
出力されます。しかし、シェルは入力元、出力先を切り替えることができます。

catコマンドを例に取ると、catコマンドは何も引数を指定しないと、
標準入力から受け取ったデータを標準出力に出力するという動作です。
Ctrl+Dで停止します。

###リダイレクト

リダイレクトはコマンドの標準出力を端末画面ではなく、
任意のファイルに切り替えることができます。

コマンド > ファイル名

例:date > today
これはdateコマンドの出力をtodayファイルで出力するという意味です。
todayファイルがないときは作成されます。
もう一度実行すると上書きされます。
末尾に追記するときは>の代わりに>>を使います。

標準エラー出力をリダイレクトするときは2>もしくは2>>を使います。

###パイプ

パイプ「|」を使うとあるコマンドの実行結果を別のコマンドで処理できます。
コマンド | コマンド

###メタキャラクタ

シェルにとって特別な意味を持つ文字をメタキャラクタと言います。

*は0文字以上の任意の文字列
?は任意の1文字
[]は[]内の任意の1文字
/はメタキャラクタの打ち消しです。

##シェルの便利な機能

###コマンド履歴

コマンドの履歴を活用するには↑を活用しましょう。
なお、historyコマンドを使うとコマンドの履歴の一覧を表示できます。

!履歴番号を実行すると履歴番号のコマンドが再度実行されます。

###ファイル名の補完

コマンドやファイル名のミスを防ぐためにTabキーを使いましょう。
補完する候補が複数ある時は、もう一度Tabキーを押すと候補一覧が表示されます。


###エイリアス

コマンドには別名を付けることができます。
別名をエイリアスと言います。エイリアスを付けると次のようにできます。
・よく使うコマンドに短縮名を付ける。
・コマンドとオプションをまとめて1つのコマンドのように使う。
・連続したコマンド処理を簡単に実行する。

aliasコマンドを付けます。
alias [別名[=コマンド]]

引数無しでaliasコマンドを実行すると、設定済みのエイリアスが表示されます。


###引用符

Linuxではスペースなどの文字はコマンドや引数の区切りで使われ、
特別な意味を持ちます。
例えば、alias la='ls -la'ですが、
これをalias la=ls -laにすると la=lsと-laに分かれてしまい
認識されなくなります。
なので、スペースの直前に/を置く方法もあります。

また、シングルクォーテーションは変数展開ができないが、
ダブルクォーテーションは変数展開ができます。

##シェル変数と環境変数

###変数の設定と確認

シェルが動作する上で必要となる様々な情報は変数に保存されます。
変数名=値
ただし、=の前後にスペースを入れないようにして下さい。
変数の内容はechoコマンドを使って確認できます。
変数名には$を付けます。

###1つのシェルの中だけで使える変数をシェル変数と言います。
他のシェルでも使える変数を環境変数と言います。

export [変数名[=値]]

設定されている環境変数を表示するには、printenvコマンドを実行します。
また、setコマンドを実行すると設定されているシェル変数と環境変数を表示します。

###コマンドとパス

コマンドには組み込みコマンドと外部コマンドがあります。
外部コマンドは、シェルの外部に同じ名前の実行プログラムとして保存されます。
whichコマンドを使うと、コマンドの実行ファイルがどこか確認できます。
例えば、dateコマンドは/usr/bin/dateにあると分かりました。
でも、毎回これを入力するのは手間です。なので、組み込みコマンドでなければ
シェルは変数PATHに格納されているディレクトリを検索し、コマンド名に一致するファイルを
実行します。これをコマンドサーチパスと言います。単にパスとも言います。

ディストリビューションの設定によって、一般ユーザーとrootユーザーとで
パスの内容を変更している場合があります。
コマンドが見つからなくても絶対パスなら実行できます。

#シェルスクリプト

##シェルスクリプトの基本

###シェルスクリプトとは?
シェルスクリプトを使えば、一連のコマンド操作を自動化し、効率的にLinuxを操作できます。
しかし、複数のコマンドを実行するのは手間です。
なので、シェルスクリプトを使います。拡張子は.shになります。

###シェルスクリプトの決まりごと

「#」があると、コメントになりますが、1行目は特別です。
1行目の#!はシェバンと言い、どのシェルでコマンドを実行するか指定する役割になります。

###シェルスクリプトの実行方法

1つ目の実行方法はbashコマンドです。
bash シェルスクリプトファイル名

2つ目はsourceコマンドの引数としてシェルスクリプトファイルを指定します。
source　シェルスクリプトファイル名

sourceの時はシェル変数をシェルスクリプト内で参照できる点です。
しかし、bashはシェルスクリプトはシェルスクリプトのものと判断しています。

3つ目はシェルスクリプトに実行権を移し、パスを指定します。
相対パスではエラーになってしまうので、必ず絶対パスにしましょう。
相対パスで表すときは、./のようにカレントディレクトリを指定しましょう。

##引数と終了ステータス

###引数の利用

コマンドと同じようにシェルスクリプトを実行するときにも引数を指定できます。
指定した引数は、シェルスクリプト内で利用できます。
これは「$1」という変数を使います。2つ目は「$2」です。

###終了ステータス

$?を使うと、終了ステータスを表します。これは実行が成功なら0,
失敗なら0以外の数値が出ます。
備忘録~今日学んだ配列関係の変数まとめ~

```
array_slice — 配列の一部を切り取る。
array_slice(array $array,int $offset,?int $length = null)
$input = array("a", "b", "c", "d", "e");

$output = array_slice($input, 2);      // "c", "d", "e" を返す。
$output = array_slice($input, -2, 1);  // "d" を返す。
$output = array_slice($input, 1,3); // "b", "c", "d" を返す。
$output = array_slice($input, 0, 3);   // "a", "b", "c" を返す。
```

```
array_chunk － 配列を分割する。

<?php
$input_array = array('a', 'b', 'c', 'd', 'e');
print_r(array_chunk($input_array, 2));
print_r(array_chunk($input_array, 2, true));
?>
//
Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )
    [1] => Array
        (
            [0] => c
            [1] => d
        )
    [2] => Array
        (
            [0] => e
        )
)

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )
    [1] => Array
        (
            [2] => c
            [3] => d
        )
    [2] => Array
        (
            [4] => e
        )
)
```

```
array_key_exists －配列から指定のキーがあるか探す。
array_key_exists($key, $array); arrayの中にkeyがあればtrue、無ければfalseを返す。
```

```
array_merge － ひとつまたは複数の配列をくっつける。
$array1 = array("color" => "red", 2, 4);
$array2 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
$result = array_merge($array1, $array2);
print_r($result);
?>
```

```
array_sum － 配列の値を足し合わせる。
array_sum($array);
```
GoとEC2で「Hello, World!」


## 追記
この記事を書き終わってから、他の方々の記事を検索してみたのですが、AWS SDK for Goを使うのが一般的みたいです。
https://aws.amazon.com/jp/sdk-for-go/

この記事では、EC2を手動で作って、GoのコードをコンパイルしたバイナリファイルをEC2にアップロードする方法です。よろしくお願いします。

## やりたいこと
GoとEC2を使って、ブラウザでHello, World!するだけです。
こちらの記事を大変参考にしました。
https://qiita.com/Dragon-taro/items/09a67b93093770348ce5

ローカルにGoは既にインストールされている前提です。
ちなみに、僕のGoのバージョンは1.16.6でした。

## Goアプリの作成
ファイル構成

```
.
└── main.go
```

```go:main.go
package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, "Hello, World!")
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}
```
## EC2の作成
以下、コンソール画面をポチポチしてEC2を作成する。

|項目|値|
|-|-|
|Amazonマシンイメージ|Amazon Linux2 AMI|
|インスタンスタイプ|t2.micro|
|ネットワーク|(デフォルト)|
|サブネット|優先順位なし(デフォルト)|
|自動割り当てパブリックIP|有効|
|EBSサイズ(GiB)|20|
|タグ|Name:app-ec2|

セキュリティグループ

|タイプ|プロトコル|ポート範囲|ソース|
|-|-|-|-|
|SSH|TCP|22|0.0.0.0/0|
|HTTP|TCP|80|0.0.0.0/0::/0|
|HTTPS|TCP|443|0.0.0.0/0::/0|

## ターミナル作業
以下、ターミナルで作業していきます。
xxxxx.pemは、キーペアのダウンロードした秘密鍵ファイル、
xxx.xxx.xxx.xxxは、EC2のパブリックIPv4アドレスです。
適宜読み替えてください。

```zsh:local
# 秘密鍵ファイルを移動、権限変更
$ mv ~/Downloads/xxxxx.pem ~/.ssh
$ chmod 700 ~/.ssh/xxxxx.pem

# linux形式でコンパイルする
$ GOOS=linux GOARCH=amd64 go build main.go

# ファイル転送モードでログイン
$ sftp -i ~/.ssh/xxxxxx.pem ec2-user@xxx.xxx.xxx.xxx
```

```zsh:ec2
# ec2へ、localのmainバイナリファイルを転送
$ put main
$ exit
```

```zsh:local
# sshでログイン
$ ssh -i ~/.ssh/xxxxxx.pem ec2-user@xxx.xxx.xxx.xxx
```

```zsh:ec2
# nginxをインストール
$ sudo amazon-linux-extras install nginx1.12

# nginx設定ファイルを編集
$ sudo vim /etc/nginx/nginx.conf
```

```conf:nginx.conf
http {
    server {
        location / {
            # 追記箇所
            proxy_pass    http://localhost:8080;
        }
    }
}
```

```zsh:ec2
# nginx起動
$ sudo service nginx start

# goアプリ起動
$ ./main```

xxx.xxx.xxx.xxxをブラウザで開くと、「Hello, World!」が見れるはず！
ご覧いただき、ありがとうございました！
SwiftUIでFirebaseのAuthenticationにてGoogleログインしたい

#はじめに#
SwiftUIでアプリを開発しようと開発を始めて、まずはログイン機能を実装しようしました。
FirebaseのAuthenticationでログインプロバイダにGoogleアカウントを使えば簡単にログイン機能を実装できるだろうと考えていました。
しかし、見事にハマってしまい数時間消費してしまったので備忘録を残しておきます。

#前提知識#

AuthentictionでログインプロバイダにGoogleを利用する場合Googleが用意している「Google Sign-In for iOS」を利用します。
「Google Sign-In for iOS」を利用すると以下のような見慣れた「Sign in with Google」ボタンとログイン画面を簡単に実装できます。(UIKitならば)
このログイン画面でGoogleアカウントの認証を行い、その認証情報を利用してさらにfirebaseにログインすると言う流れです。


「Sign in with Google」ボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/a9092f2a-b386-62a2-6375-bc61addf29f7.png)

Googleアカウントのログイン画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/a048531b-9f38-8a61-9601-96c2b4046e1f.png)




#はまった点#

FirebaseがGoogleアカウントの認証からFirebaseの認証まで詳しい手順を公開してくれています。

「iOS で Google ログインを使用して認証する」
https://firebase.google.com/docs/auth/ios/google-signin?hl=ja

しかし、「GoogleSignIn with SwiftUI」はUIKitにしか対応していないと言う問題があるようです。(2021年10月7日時点)
今回はUIKitではなくSwiftUIを利用したいので上記の手順どおりに実装することができませんでした。
そのため、ひたすらUIKitとSwiftUIの共存について闇雲に調べることになったのでした。

#解決策#
結果的にはとても参考になるソースがGithubにありましたのでご紹介します。

「GoogleSignIn6_SwiftUI」
https://github.com/paraches/GoogleSignIn6_SwiftUI

こちらがとても参考になりました。
ソース内に直書きされている「clientID」を自分のものに書き換えるように記載されていますが、
私の環境ではプロジェクト設定の中の「Info」→「URL Types」→「URL Schemes」も書き換える必要がありました。

このソースではGoogleの認証までしか行っていませんので、firebaseにログインするためにはさらに以下の手順の「2. Google ログインを実装する」の4の手順でcredentialを宣言するところ以降の手順が必要になります。

「iOS で Google ログインを使用して認証する」
https://firebase.google.com/docs/auth/ios/google-signin?hl=ja

#さいごに#
もともとFirebaseやswiftを使い慣れている方であればそんなに混乱しないのかもしれませんが、あまり慣れていない方は私と同様の混乱が生じると思います。「Sign in with Google」が正式にswiftUIでそのまま利用できる様になるまでですが、参考になればと思います。

「Google Sign-In for iOS」のGithubのレポジトリにおいてもswiftUI関連のサンプルソースのプルリクエストやissuesが上がっていますので近々対応することを期待しています。
https://github.com/google/GoogleSignIn-iOS/pulls
rails s が実行できない【エラー：LoadError(nokogiri), RuntimeError/ENOENT(webpacker)】【ターミナル再起動】

ターミナルで `rails s` を実行した際に起こったエラーたち

##環境
OS：macOS Monterey12.0.1
Rails：6.1.4.1(2021/11/07現在最新版)

:::note info
前提となる、Ruby(3.0.2), SQLite3(3.36.0), Node.js(16.13.0), Yarn(1.22.17), Homebrew(3.3.2), rbenv(1.2.0) はインストール済み(2021/11/07現在最新版)
:::

##まず最初に確認すべきこと
ターミナルで、
（作業したいディレクトリに移動した上で）`rbenv versions` や `ruby --version` を実行し、
今自分のディレクトリ内で動いている ruby の version が、
動かしたい version であるかどうかを確認する。

もし違うなら `rbenv local 3.0.2(動かしたい version)` で version を切り替え、
もう一度 `rails s` を実行してみる。

##問題１： nokogiriに関するエラー(LoadError)

```
cannot load such file -- nokogiri/nokogiri (LoadError)
　：
(省略)
　：
dlopen(/Library/Ruby/Gems/2.6.0/gems/nokogiri-1.12.5-x86_64-darwin/lib/nokogiri/2.6/nokogiri.bundle, 0x0009): tried: '/Library/Ruby/Gems/2.6.0/gems/nokogiri-1.12.5-x86_64-darwin/lib/nokogiri/2.6/nokogiri.bundle' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e')), '/usr/lib/nokogiri.bundle' (no such file) - /Library/Ruby/Gems/2.6.0/gems/nokogiri-1.12.5-x86_64-darwin/lib/nokogiri/2.6/nokogiri.bundle (LoadError)
```

##解決方法
nokogiriを再インストール

１. `gem uninstall nokogiri` でnokogiriを一旦アンインストール
２. Gemfileに `gem 'nokogiri', '~>1.12.5'` を記述
３. `nokogiri (1.11.1-arm64-darwin)` をGemfile.lockから削除
４. `gem install nokogiri` を実行

##問題２： webpackerに関するエラー(RuntimeError, ENOENT)

```
Webpacker configuration file not found /Users/<ユーザ名>/Programming/tweet/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/<ユーザ名>/Programming/tweet/config/webpacker.yml (RuntimeError)
　：
(省略)
　：
No such file or directory @ rb_sysopen - /Users/miyu/Programming/tweet/config/webpacker.yml (Errno::ENOENT)
```

##解決方法
言われている通りに、`rails webpacker:install` を実行

##問題３： ターミナルの再起動
ターミナルを再起動すると、実行できたはずの `rails s` が実行できなくなっていたり、railsやyarnやnokogiriなどをwhichコマンドで探すと見つからなかったり再起動前とは違う場所が表示されたりする問題

##解決方法： パスを通す
「パスを通す」とは、コンピュータに実行ファイルの在り処を教えてあげること
これにより、どこからでもその実行ファイルを呼び出せるようになる

####パスの通し方
ターミナルで以下の３つのコマンドを入力

:::note warn
ただし、【PATH=[実行ファイルの場所]:$PATH】
実行ファイルの場所は以下とは違う可能性があるため要確認
:::

```
$export PATH=/opt/homebrew/bin:$PATH
$export PATH=~/.npm-global/bin:$PATH
eval "$(rbenv init -)"
```

<details><summary>次回以降ターミナルを起動した際にパスを自動で通す方法<font color="DarkGray">（押すと詳細が開きます）</font></summary><div>

　ターミナルで `echo $SHELL` の実行結果が
 　`/bin/bash` なら `/User/<ユーザ名>/.bash_profile(隠しファイル)` を
 　`/bin/zsh` なら `/User/<ユーザ名>/.zshrc(隠しファイル)` をエディタで開いて、
　さきほどの３つのコマンドを記述する

　ちなみに、`.bash_profile` や `.zshrc` は、
　ターミナルを起動したときなどに(自動的に)中身を実行してくれるファイルなので、
　こうしておくと、次回以降ターミナルを起動した際に、自動的にパスを通してくれる
</div></details>
自動音声認識を試す（Google Speech, Amazon Transcribe）

## 音声ファイルを用意する
- iPhoneの「ボイスメモ」で録った音声をAirDropでMacに送る
- m4a から wav に変換する

```
afconvert -f WAVE -d LEI16 -c 1  XXXXX.m4a XXXXX.wav
```

## Google Speech-to-Text を試す
-  [マニュアル](https://cloud.google.com/speech-to-text/docs/async-recognize?hl=ja)を参考に [サンプルコード](https://github.com/googleapis/python-speech/tree/main/samples) を手元で動かす
- Cloud SDKはすでに入れている
- テスト用にGoogle Speech-to-Text を有効化した認証情報設定

```
export GOOGLE_APPLICATION_CREDENTIALS = XXXXX.json
```

- 音声ファイルをGCSにあげておく

```bash
gsutil cp XXXXX.wav gs://bucketsXXX/XXXXX.wav
```

- サンプルコードを手元に落とす

```bash
git clone https://github.com/googleapis/python-speech.git
```

- 仮想環境作成し必要なモジュール入れる

```bash
$ virtualenv env
$ source env/bin/activate
$ pip install -r requirements.txt
```

- サンプルコードに手を加え

```diff
-        sample_rate_hertz=16000,
-        language_code="en-US",
-        model=model,
+        sample_rate_hertz=48000,
+        language_code="ja-JP",
+        #model=model,
```

- GCS上の音声ファイルをテキスト化してみる

```bash
python transcribe_model_selection.py gs://bucketsXXX/XXXXX.wav > interview.txt
```



## Google Speech API を試す
- 非同期で処理

```
$ gcloud ml speech recognize-long-running 'gs://bucketsXXX/XXXXX.wav' --language-code='ja-JP' --sample-rate=48000 --async

Check operation [operations/XXXXXXXXXXXXX] for status.
{
  "name": "XXXXXXXXXXXXX"
}
```

- 下記コマンドで処理状況を確認。<br>
終わっていれば progressPercent が100になりresponseにテキストが返る

```
$ gcloud ml speech operations describe XXXXXXXXXXXXX


{
  "done": true,
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeMetadata",
    "lastUpdateTime": "2021-09-XXT09:15:37.404790Z",
    "progressPercent": 100,
    "startTime": "2021-09-XXT08:59:39.288851Z",
    "uri": "gs://bucketsXXX/XXXXX.wav"
  },
  "name": "XXXXXXXXXXXXX",
  "response": {
    "@type": "type.googleapis.com/google.cloud.speech.v1.LongRunningRecognizeResponse",
    "results": [
      {
        "alternatives": [
          {
            "confidence": 0.8462801,
            "transcript": "XXXXXXX"
          }
        ]
      },
      {
        "alternatives": [
          {
            "confidence": 0.9102794,
            "transcript": "XXXXXX"
          }
        ]
      },
・・・・・
}
```
- 結果は Google Speech-to-Text と同じようだ



## Amazon Transcribeを試す

- [チュートリアル](https://aws.amazon.com/jp/getting-started/hands-on/create-audio-transcript-transcribe/?sc_icampaign=acq_jp_getting-started-handson-202010-create-audio-transcript-transcribe&sc_language=jp&sc_icontent=awssm-6339&sc_iplace=ribbon&trk=ha_ribbon_acq_jp_getting-started-handson-202010-create-audio-transcript-transcribe)に沿って画面からアップロードするだけなので簡単<br>
処理完了後、結果はjsonでダウンロードできる
【Ubuntu】Terminalから映像ファイルをフルスクリーンで再生[totem]

## 環境
Ubuntu 20.04.3 LTS

## 結論

```
totem --fullscreen 'Filename.mp4'
```

## Totemとは
ubuntuにデフォルトで入っている映像再生ソフトウエア
通称「ビデオ」


https://ja.wikipedia.org/wiki/%E3%83%93%E3%83%87%E3%82%AA_(GNOME)

![Screenshot from 2021-11-03 14-20-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577794/699f4c4d-60f5-100a-0982-20008cca44ec.png)

## totem option 一覧
```
$ totem --help

Help Options:
  -h, --help                        Show help options
  --help-all                        Show all help options
  --help-gapplication               Show GApplication options
  --help-gtk                        Show GTK+ Options
  --help-gst                        Show GStreamer Options

Application Options:
  --play-pause                      Play/Pause
  --play                            Play
  --pause                           Pause
  --next                            Next
  --previous                        Previous
  --seek-fwd                        Seek Forwards
  --seek-bwd                        Seek Backwards
  --volume-up                       Volume Up
  --volume-down                     Volume Down
  --mute                            Mute sound
  --fullscreen                      Toggle Fullscreen
  --quit                            Quit
  --enqueue                         Enqueue
  --replace                         Replace
  --version                         Show version information and exit
  --display=DISPLAY                 X display to use
```

## おわりに
画像ファイルや動画ファイルを開くときは基本的に「xgd-open」コマンドを使用していました。ある時、動画を全画面で再生しようとした際に、xgd-open にオプションがほとんど無く、目的とする操作ができないことに気づき、ググりまくった苦い記憶があります。
ArduinoUnoとリレーモジュールで車側表示灯を制御しよう

東京メトロ 02系 車側表示灯を点灯させるの続きとして今回は車側表示灯をリレーモジュールを使用して制御します。
https://qiita.com/usashirou/items/2e85c1c2a7cbb2de0899
#リレーモジュール
初めに、リレーモジュールと言うのものを使用します。
Arduinoなどのマイコンで制御できる5Vで動作するものを選択します。
![DSC_0820 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/09b3bcb4-6ce4-7b43-edaa-d53e5f45cc45.jpeg)
#構成
今回はArduinoUnoとリレーモジュール、交流直流変換ボードを使用します。
直流100VのGNDをリレーモジュールに入れて、制御される出力端子を交流直流変換ボードのGNDに接続します。
ArduinoUnoの任意のデジタルピンとGNDと5Vをリレーモジュールに接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/2e940e50-2dc3-cd6d-6fc6-7e19fac0405f.png)
![DSC_0822 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/02896e89-0624-366e-a82e-5c57c2fafa0c.jpeg)
#テスト
初めに動作確認を行います。
リレーがキチンと駆動するかGPIOをHigh/Lowをさせてみます。
LOWにする事でリレーが駆動するようになっていました。
次に、直流100Vを印加して車側表示灯が点灯することを確認し、リレーで動作することを確認しましょう。
#実行プログラム
今回は2個のリレーが載っているリレーモジュールですのでどちらもコントロールできるプログラムにしました。
スイッチを押すことで起動するプログラムにしました。
車掌スイッチでコントロールする事も出来ますね。

```
void setup() {
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, INPUT_PULLUP);
  digitalWrite(6, HIGH);  
  digitalWrite(7, HIGH); 
}

void loop() {
    if (digitalRead(8) == LOW)
  {
    digitalWrite(6, LOW);  
    delay(2000); 
    digitalWrite(7, LOW);
  }
}
```
#動作の様子
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">BGM入り <a href="https://t.co/IZ73vatvrY">https://t.co/IZ73vatvrY</a> <a href="https://t.co/Ag21UZ0zCU">pic.twitter.com/Ag21UZ0zCU</a></p>&mdash; usashirou (@usashirou1) <a href="https://twitter.com/usashirou1/status/1457247155819728903?ref_src=twsrc%5Etfw">November 7, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<Java学習中>HelloWorldまでの流れ 

初投稿です。似たような記事はたくさんありますが、学習したことを備忘録や日記のような形でアウトプットしていきます。
間違った内容があればご指摘して頂けると幸いです。

環境はオンラインIDE(openjdk version "16.0.2")を使用しております。特に用意することもなくお手軽なので。



今日のところはタイトルにもある通り、Hello Worldを表示するだけです。

以下のコードで表示できました。

```java
public class Main{

    public static void main(String[] args) {      
        System.out.println("Hello World!");
    }
}
```

```text:実行結果
Hello World!
```


ここに至るまでに分かったことは、mainメソッドはJavaのエントリーポイント（処理の始まり）だということ。
mainメソッドには単語がズラリと並んでいて「なんだこれは」と思いネットで調べたところ、

・アクセス修飾子はpublic
・staticメソッドである
・メソッドの戻り値はvoidである
・メソッド名は“main”である(すべて小文字)
・メソッドの引数はStringの配列”のみ“である

この５つの条件をクリアしたmainメソッドがあって処理が始まるみたいですね。
個々の意味はまた後で調べてみるとして、とりあえずこれがないとまず動かないことは確かです。


続く　System.out.println("Hello World!");　は、（）の「""」ダブルクォーテーション内に入力された文字列を表示するという文です。
PrintIn（大文字のアイ）ではなくPrintln（小文字のエル）なんですね・・・。雰囲気的にIn(イン)かと思ってしまいました。


またPrintlnメソッドの他にPrintメソッドというのもありました。
どこが違うのかというと、Printlnは()の中身を表示して改行するという命令に対して、Printは改行せずに中身を表示するとのこと。

実際にPrintでやってみると

```java
public class Main{

    public static void main(String[] args) {      
        System.out.print("Hello World!");
        System.out.print("HelloWorld!");　　//一列に並ぶことの確認のため複数Hello World!を用意
        System.out.print("Hello World!");
    }
}
```
```text:実行結果
Hello World!HelloWorld!Hello World!
```

Printlnならば、Hello World!の後に改行されていくので実行結果は

```text:実行結果
Hello World!
HelloWorld!
Hello World!
```
となりました。



とりあえず今回の記事はこれまでとします。ありがとうございました！
何か間違いがありましたら、ツッコミをよろしくお願いします！
【Vue.js】イベントハンドラに引数を渡す、$event

#はじめに
こんにちは！
今回は【Vue.js】イベントハンドラに引数を渡す方法、$eventについてアウトプットしていきます！

#書き方・解説
前記事の`メソッドイベントハンドラ`の内容を例に解説していきます。

```HTML:HTML
<div id="app">
  <p>
    {{ message }}
  </p>
    <button v-on:click="clickHandler('Vue.ls!')">
    Click!
  </button>
</div>

```
```Vue.js
 var app = new Vue({
   el: "#app",
   data: {
     message: ''
   },
   methods: {
     clickHandler: function(message) {
       this.message = message
     }
   }
 })
```

動作としては、ボタンをクリックしたら`clickHandler`を呼び出す。その時に値(`Vue.js!`)を出す。
そしてそれを、`clickHandler: function(message)`の`(message)`の部分で引数として受け取ります。
それを`clickHandler: function(message)`内の処理として引数`message`をdataオプション内の`message:''`に`this.message`として代入している。なのでdataオプション内は`massage:'Vue.js!'`というふうになっている。それをテンプレート側の`{{ message }}`で表示させているということになる。

下画像のように、

![スクリーンショット 2021-10-25 22.01.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/d4a9f6ae-ae74-b784-49ee-353ed0a5c400.png)

クリックボタンをクリックすることで、

![スクリーンショット 2021-10-25 22.01.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/500cc7ca-f38a-aed6-fb24-aaddf04e0fa8.png)

`Vue.js!`と表示される処理になる。

#「補足」$eventの使い方
上記の場合では第１引数を`message`で使用してしまっているため、イベントオブジェクトを参照出来ないという課題が生じます。
この時、イベントオブジェクトを参照させたいというときは、`$event`を引数としてメソッドに渡す。

```HTML:HTML
<div id="app">
  <p>
    {{ message }}
  </p>
    <button v-on:click="clickHandler($event,'Vue.ls!')">
    Click!
  </button>
</div>
```

```Vue.js
 var app = new Vue({
   el: "#app",
   data: {
     message: ''
   },
   methods: {
     clickHandler: function($event,message) {
       this.message = message
       console.log($event)
     }
   }
 })
```

これでイベントオブジェクトと引数をイベントハンドラに渡して、利用できるようになります。
`console.log`はイベントオブジェクトの動作確認として使用しています。

以上、「補足」$eventの使い方でした。


#まとめ
このようにイベントハンドラに引数を渡し、処理を実行し、テンプレート側で出力させることが可能です！
イベントオブジェクトを参照出来ないという課題が生じるため、参照させたいときは`$event`を引数としてイベントハンドラに渡すことが推奨されます。


#最後に
今回はイベントハンドラに引数を渡す方法と$eventについてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
OCR認証のAPIが無料提供されたらしいので使ってみた

#はじめに
2021年6月にOCR（自動文字認識）のAPIが無償提供されたらしいので試しに使ってみた。

詳細と資料ダウンロードは下記の公式ページから。

https://ocr-ai.userlocal.jp/

<font color="DarkGray">本記事は個人的にAPIを検証した結果を載せたものであり、性能を批評するものではありません。</font>

#さっそく使ってみる
今回は読み込みの結果を知りたいだけなのでcurlコマンドを使用してAPIを呼び出してみた。
（AIPエンドポイント等の情報資料は公式サイトで個人情報等を入力してダウンロードしたので呼び出しの箇所は念のため本記事には載せていません）

まずは手始めにこちらから
![こんにちは.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259864/5625b9bb-e99b-a70c-4ac4-be9ae3186c07.png)
手書きしたものをスマホのカメラで撮影した画像を読ませてみます。

```
{
"status":"ok",
"text":"\u3053\u3093\u306b\u3061\u308f",
"candidates":[
  ["\u3053","\u3055","\u3054","\u30de","\u30b3"], 
  ["\u3093","\uff48","\u3048","\u03ba","\u4eba"],
  ["\u306b","[blank]","\u306f","\u305f","\u4ec1"],
  ["\u3061","5","\u53e4","\u03b6","\u65b9"],
  ["\u308f","\u308e","\u308c","\u306d","\u3086"]
]}
```
読み込み結果が文字化けしてますね。
jpコマンドで整形して表示させます。
>「jq」とは
>jsonを整形したり特定の値のみを抜き出して集計したりできるコマンド
>下記よりexeファイルをDLして使用可能
>https://stedolan.github.io/jq/

```
{
  "status": "ok",
  "text": "こんにちわ",
  "candidates": [
    [
      "こ",
      "さ",
      "ご",
      "マ",
      "コ"
    ],
    [
      "ん",
      "ｈ",
      "え",
      "κ",
      "人"
    ],
    [
      "に",
      "[blank]",
      "は",
      "た",
      "仁"
    ],
    [
      "ち",
      "5",
      "古",
      "ζ",
      "方"
    ],
    [
      "わ",
      "ゎ",
      "れ",
      "ね",
      "ゆ"
    ]
  ]
}
```
>"text": "こんにちわ"

ちゃんと読み込めてるみたいです。
"candidates"には各文字の候補だった文字が記載されています。

#いろいろなパターンを読ませてみる
手書き文字のクセにも対応しているとのことなのでいろんなパターンで読ませてみましょう。
![おはようございます.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259864/b63877d8-2129-8487-79bf-b0061378d6cb.png)
次は文字の間隔をばらばらにしてみました。
レスポンスの"candidates"を毎回表示していると長くて見づらいのでjqのオプションで"text"のみを切り出していきましょう。

```
"おはようございます"
```
間隔があっても問題なく読めるようです。
<br>
次はこちら
![スカイツリー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259864/5ef3d0bd-b503-3df3-0305-7871c2701101.png)
スカイツリーの住所です。
密度の高い漢字や数字、記号が混在しています。

```
"東京都墨田区押上は目に2"
```
漢字はほぼ問題なく読めていますね。
数字や記号に関しては

1丁　⇒は
1－　⇒に

となってしまっているようです。
「1」や「-」の書き方が雑なのでは？という気もしますが。
<br>
次は読ませることを気にせずに普段通り書いた文字になります。
![普段通り.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259864/3816f59e-5ec9-8ab1-f0ce-090488a6a3e1.png)

```
"だぶ汚い文字"
```
一つ目の「い」以外は完璧ですね。
「い」は小さすぎ＆書き方が悪すぎたんだと思います。
<br>
最後は個人的に最も驚いたパターン。
日本人以外には書き分け、読み分けが困難と言われている「ツシソンリ」です。
![ツシソンリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2259864/1f29c9cf-a26e-e793-b58e-094bfd42e69f.png)

```
"ツシソンり"
```
なんと認識しました。
「リ」が「り」になってはいますが、それは筆者の書き分けの問題もあるでしょうし、「ツシソンリ」の5パターンの差異自体は認識できたということになります。

#感想
いかがでしたでしょうか。
まだ完璧に読み込めない部分もありましたが、ディープラーニングAIを使用しているとのことなので今後さらなる認識率アップが見込めるのではないかと思います。

冒頭でも紹介しましたが、本APIは無償で提供されているものなので興味があれば公式サイトから資料をDLしてみてください。

https://ocr-ai.userlocal.jp/