OmniAICreator/Qiita-1.07M huggingface dataset:
【LinuC】LinuC-1 Exam 101 Version 10.0 受験記録

2023年が早くも1ヶ月過ぎてしまうそんな中、未だQiita投稿出来ていなかった・・・。
今回LinuC101試験を受験したので、それを早速ネタにしようと思います。

尚、受験の際に同意した受験者行動規範により、試験内容の開示、共有は禁止されていますので、試験に向けて行った準備とか感想とかを記していこうと思います。
## LinuCとは
LinuCレベル1 Version 10.0は、仮想環境を含むLinuxシステムの基本操作とシステム管理が行える技術者として、以下の知識と技術を持つことの裏付けとなります。

- 仮想マシンとコンテナを含むLinuxサーバーの構築と運用・管理ができる。
- クラウドのセキュリティを理解し、安全に運用できる。
- オープンソースの文化を理解し、業務に活用できる。

90分で問題数は60問の「101試験」と「102試験」の2試験に合格するとレベル1に認定されます。受験する順番はどちらからでも構いません。

※認定されるためには2試験（101試験と102試験）を5年以内に合格する必要があります。

https://linuc.org/linuc1/

## 本題

まず結果ですが、合格ライン480点に対して、666点で合格する事が出来ました。
（試験後に直ぐ結果を妻に伝えたら、「それオーメンやん、こわっ」と言われ悲しくなりました・・・）

ちなみにセクション毎の正答率はこんな感じで、まぁまぁ出来てるんちゃうかな。試験中の手応えと、それほど温度差はありませんでしたね。
![スクリーンショット 2023-01-28 17.53.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/4907c1de-c42d-975d-193e-439bd20a5309.png)
基本問題は選択式で、5~10問くらい記述式でコマンドを入力させるものが混じってきます。

準備期間は2週間程度で、学習は平日1時間、土日は3,4時間くらい休憩入れながら。トータルで20時間程度でしょうか。


- [20時間で【Linux】マスター！！基礎、シェルスクリプト、Docker基礎、ネットワーク 、セキュリティを体系的に解説](https://www.udemy.com/course/linuxlpic/)

学習のアプローチとして、まずはUdemyでざっくり試験範囲の概要を掴むところから。教材は上記を使用しました。全体では20時間ありますが、101試験範囲の解説だけであれば、約9時間なのでそこと必要そうなところを1.5倍速で1周しました。網羅的というより、実務寄り目線で最低限の解説をしてくれているので、各コマンドのオプションなどについては深堀の学習が別途必要になります。

- [ping-t.com](https://ping-t.com/)

定番のping-t.comの101問題集（新サイトver.）は無料なので活用させて頂きました。
![スクリーンショット 2023-01-28 18.31.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/ce16a96c-e44e-a0c6-f758-12e33239f924.png)
101試験の問題は現時点で657問あり、最終的にはレベルMAXの40になるまで解き続けました。ping-tの問題集にはまずヒット、コンボの概念があります。対象の問題に対して、正解でヒット、再度正解してコンボとなります。なのでヒットになっても、次に不正解だと再度正解してもコンボとはならないので、苦手な問題がこれで抽出出来ます。

あとこれは基本的なことですが、正解の選択肢を記憶するだけでなく、不正解の選択肢が何故違うのかを説明出来るレベルを目指します。全問題ヒットでレベル10、全問題コンボにしてレベル20、以降は模試という機能によるレベルアップを図ります。

![スクリーンショット 2023-01-28 18.37.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531606/387f7fdf-c669-3717-da6d-3dc1b58da81a.png)
模試とは文字通り、これまで解いてきた問題を試験形式で実際に解くことが出来る機能です。正答率80%を超えた回数、90%を超えた回数それぞれが10回超えるとレベル40に到達します。

最初は90%に壁があったのですが、それを打破するためにコマ問という機能を活用しました。コマ問は問題集と同じような問題を選択式ではなく、全て記述式で回答するものです。合格体験談を見ていると、このコマ問は難しいので、あまりやらなかったという声も結構見受けられましたが、結論コマ問は絶対にやった方が良いです。

理由としては模試を複数周回するより、単純に学習効率が良かったです。やはり実際にコマンドを手打ちすると記憶、理解スピードが段違いです。時間に余裕があるならば、全問正解出来るまで1周だけで良いのでやると自信になりますし、模試の正答率も上がるはずです。

対策としては以上で、あずき本などの書籍教材は不使用でした。諸説ありますが、個人の感想としてはpint-t模試で80%取れれば勝負出来るレベル、95%以上が安定してくれば勝ち確かもですね。

## まとめ
今年も資格学習は継続してやっていきたいと思っておりますので、来月中に102も取りにいきたいなあと思っております。年内にはレベル3までを目標で。

ちなみに、この短期間で受験しようと思ったきっかけが、[101試験の再受験無料キャンペーンの知らせ](https://linuc.org/campaign/202211.html)を見たからでした。（保険かけてました、すみません

今後受験を検討されている方は、ping-tで受験チケット（バウチャー）を1000円程度割引価格で購入することが出来るので、活用すると良きかと思います。
PHP ダウンロード＆インストール方法


PHPの公式ページからダウンロードします。

https://www.php.net/downloads
```
それぞれ、次のような基準で必要な物を選択すれば良いでしょう。

種類	選択すべきシーン
VS16 x86 Non Thread Safe	32bit版のWindowsを利用しており、WEBサーバーとして IIS を利用する場合。
VS16 x86 Thread Safe    32bit版のWindowsを利用しており、WEBサーバーとして Apache を利用する場合。
VS16 x64 Non Thread Safe	64bit版のWindowsを利用しており、WEBサーバーとして IIS を利用する場合。
VS16 x64 Thread Safe	64bit版のWindowsを利用しており、WEBサーバーとして Apache を利用する場合。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/395df7fc-fdf8-9505-5aba-03b11536587f.png)
ダウンロードして解凍します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/1cac5d93-f5a4-d1cd-791f-230d45624647.png)

Cドライブ直下に配置したフォルダ名をPHPに変更。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/8a5ed2a5-b46b-2b44-be9f-f202abbaffb0.png)

# Windowsの環境変数の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/cf189a75-60f8-5339-5ad2-ef3f74085631.png)
環境変数の「Path」に配置した PHP のフォルダを追加します。 「Path」を選択して「編集」をクリックして編集ダイアログを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/8ae7d42b-e677-f96b-e3f3-77ecc3093b0a.png)
# 動作確認
コマンドプロンプトに php -v と入力して実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/a7563c7b-8378-619c-c6ef-f6d301ec806e.png)
無事に PHP のバージョンは表示されたでしょうか？ これにて PHP のインストールは終了です。

# php.ini 最小限の修正
```php

// 変更前
; extension_dir = "ext"
date.timezone =
;extension=mbstring
;mbstring.language = Japanese

// 変更後
extension_dir = "C:\php\ext" //(ドライブ文字):\php\ext
date.timezone = "Asia/Tokyo"
extension=mbstring
mbstring.language = Japanese
```

# OpenSSLの有効化
・「VS16 x64 Non Thread Safe／VS16 x86 Non Thread Safe」WEBサーバーとして IIS をインストールして利用となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/fede40ce-6d61-1fab-6039-75bb39e7b66b.png)

php.ini-development：開発サーバ用のphp.iniのサンプルファイル
php.ini-production：公開サーバ用のphp.iniのサンプルファイル

必要に応じて、php.ini ファイルを作成して使用してください。

extension_dirを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/13e601b4-cd99-e8e3-0637-ad277140b550.png)

追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/4bb69e39-ef76-f2e4-d61f-ef902728677b.png)

php-m で確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/9beb8caf-cdc2-b157-dc46-5c4d0d3b2445.png)
LinuxのサーバにGUI接続する話

以前携わっていた案件でこのような要件があり、テスト環境では上手くいったのですがいざ構築してみるとなかなか上手くいかなかったので、そのトラブル内容も含め紹介します…！

まず前提条件として、OSをインストールする際にGUIインストールを行なっていない場合は、`gnome`を追加でインストールします。
```
dnf groupinstall "Server with GUI"
```
インストールされたことを確認します。
```
rpm -qa |grep gnome
```



## xrdpをインストールする
Linuxのサーバーにリモートデスクトップ接続するためのrpmです。
`xrdp`は、デフォルトのリポジトリではなく、`EPEL`という外部のリポジトリに含まれています。
インターネットに繋がっているのであれば、リポジトリごとインストールしても良いかもしれませんが、（ただし自己責任で。。）
`xrdp`しか使用しないので、`xrdp`のパッケージ単体を探してダウンロードするので良いと思います。
```
rpm -ivh xrdp-<version>.x86_64.rpm
```
インストールされたことを確認します。
```
rpm -qa |grep xrdp
```


## tigervncをインストールする
カーネルのバージョンによって多少パッケージが異なるようですが、RHEL8.2のメディアに入っている`tigervnc-server`と`tigervnc-server-minimal`の2つをインストールします。
```
rpm -ivh tigervnc-server-<version>.x86_64.rpm tigervnc-server-minimal-<version>.x86_64.rpm
 ```
インストールされたことを確認します。
```
rpm -qa |grep tigervnc
```

## xrdpを起動します
```
systemctl start xrdp
```
※サーバーの起動時に自動起動させたい場合は有効化もしておきましょう！

## firewallでxrdpが使用するポートを許可する
`xrdp`が使用するポートは<font color="red">3389</font>なので、firewalldの設定をしている場合はこちらのポートを許可します。
コマンドは、自分のサーバの設定に合わせて適宜変更してください！
```
firewall-cmd --add-port=3389/tcp --zone=<zone名> --permanent
firewall-cmd --reload
```
以上で設定は終わりです！
簡単ですよね…！



あとはWindows同士でRDPする時と同じ手順で、サーバのIPアドレスを入力して接続します。

すると、`xrdp`のログイン画面が出て来るので、ユーザ名とパスワードを入力して、Linuxサーバのデスクトップが表示されたら完了です！！




…のはずでしたが、
接続しても画面が真っ黒でデスクトップが表示されない事象が発生しました。

果たして原因は何なのか！？！？！？

次回、「漆黒の画面の謎」！！
絶対に見てください！！！笑
簡単にModelの配列をviewsに反映させる方法

LaravelでModelにある配列を呼び出す方法についての備忘録です。
カラムから紐づけるテーブルを新しく作る必要がない時などに使用できると思います。

### やりたいこと
- Modelにある配列をViewに渡し、int型のデータを任意の文字列に置き換える。


### モデルに配列を挿入
モデルに配列を追加します。

```php:Model
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Item extends Model
{
    use HasFactory;

    protected $fillable = ['name'];
    const TYPES = [
        0 => 'カジュアル',
        1 => 'モード',
        2 => 'キレイめ',
        3 => 'ナチュラル',
        4 => 'コンサバ',
    ];
}
```


### ViewにItemの定数を呼び出す
```php:view
   <td>{{App\Models\Item::TYPES[0]}}</td>
```
結果：'カジュアル'

### 実装例
Controllerから渡ってきた変数をForeachで繰り返しの処理をする時に使用できます。
例ではtypeカラムにあるint型のデータをモデルの配列で置き換えています。

```php:controller
  public function show(Request $request)
    {
        $items = Item::all();
        return view('item.show', compact('items'));
    }
```

```php:view
@foreach ($items as $item )
<tr>
   <td>{{App\Models\Item::TYPES[$item->type]}}</td>
</tr>
@endforeach
```

本来はカテゴリテーブルのような新しいテーブルを作った方が良いと思いますが、超簡単に実装できる方法の一つとしてはアリかな...
【時間の精度】タイマーや待機処理がなんか変だと思ったら


ちょっと待機時間を設けよう。処理の時間計測をしよう。  
そんなことはちょいちょいありますよね。  
しかし、そのタイマーがこっそり変な動きをしていることがあります。  
それはその機能の**精度**が原因です。

# ダメな例
[Sleep](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep)という、いかにもなWindows APIがあります。  
宣言は以下
```c++
void Sleep(
  [in] DWORD dwMilliseconds
);
```
引数に待機時間をミリ秒単位で指定できます。

## 実験
Sleepが何ミリ秒スリープできているか、確認してみます。
```c++
    for (int i = 0; i < 10; i++)
	{
		FILETIME startFileTime = { 0 };
		::GetSystemTimePreciseAsFileTime(&startFileTime);
		
		::Sleep(1);

		FILETIME endFileTime = { 0 };
		::GetSystemTimePreciseAsFileTime(&endFileTime);
		
		ULONG64 startTime = startFileTime.dwLowDateTime + ((ULONG64)startFileTime.dwHighDateTime << 16);
		ULONG64 endTime = endFileTime.dwLowDateTime + ((ULONG64)endFileTime.dwHighDateTime << 16);

		printf("%llu\r\n", endTime - startTime);
	}
```
10連続で、Sleepにかかった時間を計測して見ます。自分の環境では以下の結果となりました。
![スクリーンショット 2023-01-28 184546.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595099/6476cc3f-8162-4526-2bc3-460a108a52cc.png)
FileTimeは単位が100ナノ秒なので、ミリ秒に直すと4ms～15msが`Sleep(1);`にかかった時間ということになります。

# 回答
SleepのMSDNのページに回答はあります。  
システムクロックが一定間隔で行われ、そのtickをSleep時間のチェック基準としています。tickの発生間隔が長いほど、その精度が悪くなるということです。  
tickの頻度を上げるために[timeBeginPeriod]()というWindows APIが提供されています。
## 実験

```c++
for (int i = 0; i < 10; i++)
	{
		::timeBeginPeriod(1);
		FILETIME startFileTime = { 0 };
		::GetSystemTimePreciseAsFileTime(&startFileTime);
		
		::Sleep(1);

		FILETIME endFileTime = { 0 };
		::GetSystemTimePreciseAsFileTime(&endFileTime);
		::timeEndPeriod(1);

		ULONG64 startTime = startFileTime.dwLowDateTime + ((ULONG64)startFileTime.dwHighDateTime << 16);
		ULONG64 endTime = endFileTime.dwLowDateTime + ((ULONG64)endFileTime.dwHighDateTime << 16);

		printf("%llu\r\n", endTime - startTime);
	}
```
結果は以下
![スクリーンショット 2023-01-28 184554.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595099/b4808efc-bfd6-7c30-27be-2defef4c08d2.png)

1.5ms～1.9msになったので、大分マシになりましたね。

## 注意喚起
`timeBeginPeriod`を使っておけば良いというわけではありません。  
Sleepのページの注意書きにもある通り、システムクロック、システム電力使用量、スケジューラーに大きな影響を与えるためです。

# おまけ
`Sleep(0);`の場合は、タイマー精度を変更しなくても、ほぼ0msの待機になります。
`Sleep(0);`は0ms待機という目的で使われるわけではなく、別スレッドにタイムスライスを譲るという意味合いだからです。

## その他精度が低いやつ
* [GetTickCount64](https://learn.microsoft.com/ja-jp/windows/win32/api/sysinfoapi/nf-sysinfoapi-gettickcount64)
  * システムが開始されてから経過したミリ秒数を取得
* [timeGetTime](https://learn.microsoft.com/ja-jp/windows/win32/api/timeapi/nf-timeapi-timegettime)
  * システム時刻をミリ秒単位で取得

タイマーの結果がなんか変だな、と思った方の役に立てれば幸いです。  
用途によって、使い分けて行きましょう。
ファイルアクセスと例外処理

<h5>proになるJava 第12章<h5>

・多くのプログラムでは、データを外から受け取り、処理結果をプログラムの外に出力する必要があります。
　プログラムで想定してないデータがやってきた場合などに例外として対応する場合の処理を見ていきます。

ファイルへの保存を行います。

sample code
projava/Writefile.java

    package projava;

        import java.io.IOException;
        import java.nio.file.Files;
        import java.nio.file.Path;
        
        public class WriteFile {
            public static void main(String[] args) {
                var message = """
                        test
                        message
                        """;
                var p = Path.of("test.txt");
                Files.writeString(p, message);
            }
        }

Pathでファイル名を指定します。今回は「test.txt」という名前にします。

     var p = Path.of("test.txt");

Files.WriteStringメゾッドを使い、ファイルに文字列を保持します。
     
    Files.writeString(p, message);

最初の引数（p）が保存位置、２番目の引数（message）が書き込む文字列です。
実行するとsrcフォルダなどと同じ階層にtest.txtファイルができています。

ファイルを書き込んだので今度は読み込みます。

sample code 
projava/ReadFile.java

    package projava;

        import java.io.IOException;
        import java.nio.file.NoSuchFileException;
        import java.nio.file.Path;
        import java.nio.file.Files;
        
        
        
        public class ReadFile {
            public static void main(String[] args) throws IOException {
                var p = Path.of("test.txt");
                String s = Files.readString(p);
                System.out.println(s);
            }
        }

test.txtファイルを作成した状態で実行すると以下の様に表示されます。

    実行結果_________
    test
    message
    ________________

ファイルの内容を変更していると、その内容が反映されます。
ファイルの内容を文字列として読み込むときにはFiles.readStringメゾッドを使います。

    String s = Files.readString(p);

＿
<h5>例外について</h5>

例外は「プログラムを動かしたら正しく動作できなかった」ということを表す仕組みです。
例外について見ていきます。

ReadFileサンプルで読み込むファイル名を「test.txta」に変更して実行してみます。

    var p = Path.of("test.txta");

<strong>NoSuchFileException</strong>エラーになります。
ファイルが見つからなかった場合の処理を行います。

try句を使います。
例外が発生するかもしれない処理を「try{}」で囲んで、発生する例外についてcatch句で指定して処理します。

    try {
            var p = Path.of("test.txta");
            String s = Files.readString(p);
            System.out.println(s);
        } catch (NoSuchFileException e) {
            System.out.println("ファイルが見つかりません:" + e.getFile());
        }
＿

    try{
        例外が発生するかもしれない処理
    } catch (捕まえる例外１　　変数){
        例外の処理
    } catch (捕まえる例外2　　変数){
        例外の処理
    }...

今回はNoSuchFileExceptionに対処するので、catch句で指定しています。
発生した例外を「e」という変数で扱える様にしています。

    catch (NoSuchFileException e) {

例外NoSuchFileExceptionでは、getFileメゾッドで見つからなかったファイル名を
得ることが出来るので、ここで表示します。

    System.out.println("ファイルが見つかりません:" + e.getFile());

例外が発生してもしなくても行いたい処理がある場合には<strong>finallyブロック</strong>を書きます

    try{
        例外が発生するかもしれない処理
    } catch (捕まえる例外１　　変数){
        例外の処理
    } finally {
        例外が発生してもしなくても行われる処理
    }...

＿
【未経験2ヵ月目】現場アサインを確定させる(1ヶ月でTableau Desktop Specialistに合格した学習法)

 # はじめに
未経験から2ヶ月目になり、Tableauを使う現場にアサインするため、Tableau Desktop Specialistの資格を取得した(総学習時間:25h)ので、その備忘録になります。

# Tableau Desktop Specialistの勉強法＆試験申込み
記事を書こうかと思いましたが、[こちらのサイト](https://hanikoblog.com/%E3%80%90%E6%9C%AA%E7%B5%8C%E9%A8%93%E3%81%8B%E3%82%89%EF%BC%92%E3%83%B5%E6%9C%88%E3%81%A7%E5%8F%96%E5%BE%97%E3%80%91tableau-desktop-specialist%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E5%8B%89%E5%BC%B7/209/)と学習方法が同じだったので、割愛します(私の方針としてネット上に全く同じネタがあるものは書かないのでご了承下さい)。

2つだけ試験申込みについて補足します。
①試験受講はテストセンターがおすすめです（テストセンターでない場合は、自分でテストを受ける環境を作るという労力が発生します。試験監督も日本人でない可能性が上がります。）。
②手続きは英語であり、英語で住所を記入するのが大変でした。必要に応じて[住所表記変換サイト(日本語→英語)](https://kimini.jp/)を活用すると楽だと思います。
ActionView::MissingTemplate in Devise::Registrations#Newエラー

# エラー内容
`devise`を導入し、ユーザー新規登録画面とログイン画面を実装中のこと。
viewsファイルで`<% render %>`を用いて
部分テンプレートを呼び出そうとした際に発生。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929112/fa9c384b-6709-965c-5bb8-382fb97260c8.png)

現在の階層↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929112/26b3001b-1d71-caa1-93a3-13d2bbb8af27.png)


# 仮説

- 誤字脱字の確認 
- renderの呼び出し方法（階層位置の確認）

上記ではエラー解決に至らず。

[Qiita](https://qiita.com/pontarou194/items/47e130e9c7e08225f109)で調べたところ

~~~ruby
 <% render "shared/second-header" %>
~~~
部分の先頭に`devise`をつけることで解決。

~~~ruby
 <% render "devise/shared/second-header" %>
~~~
NanoPi NEO CoreのIPアドレスをLCDに表示させる

[前回](https://qiita.com/ps0139hk/items/d3793d73a4da7a00bfa6)はNanoPi NEO Core + Mini Shieldを使ってeMMCブートを行いました。

NanoPi NEO CoreのIPアドレスをLCDに表示させてみます。

構成としては以下の通りです。
- NanoPi NEO Core-LTS(8GB eMMC, ArmbianOS)
- Mini Shield
- LCD2USB Module([AliExpress](https://ja.aliexpress.com/i/4001084469943.html)で購入しました)

こちらはLCDモジュールを繋いだだけの状態
![IMG_3195.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547685/a220fe5a-4a7c-57f6-c9df-999245c19044.jpeg)



1.lcd4linuxをインストール
```
sudo apt-get install lcd4linux
```

2.lcd4linux.confを編集する
```
sudo vi /etc/lcd4linux.conf
```

lcd4linux.confは以下のように書き換える
```
Display LCD2USB {
    Driver 'LCD2USB'
    Size '16x2'
　　Port '/dev/bus/usb*'
}

Widget IPaddress {
    class  'Text'
    expression netinfo::ipaddr('eth0')
    prefix ''
    width 16
    align  'C'
    update 1000                        
}
 
Layout Default {
    Row1 {
        Col1 'IPaddress'
    }
}

Display 'LCD2USB'
Layout  'Default'
```
4.パーミッションを設定する
```
sudo chmod 600 lcd4linux.conf
chown root.root lcd4linux.conf
```
5.最後にlcd4linuxのプロセスを起動させましょう。
```
pkill lcd4linux
lcd4linux
```

はい、無事IPアドレスが表示されました！

![IMG_3196.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547685/c8282407-ad30-cce9-92c7-0e3620768060.jpeg)
Docker DBコンテナが立ち上がらんかった

# 概要

- DockerのDBコンテナが立ち上がらない問題が発生した。

# 問題までの経緯

1. docker-compose upで初回のコンテナビルドを実施した。
1. フロント用、バック用のコンテナは普通に起動した。

# 問題

- `$ docker ps`コマンドを使って調べてみるとDBのコンテナだけ起動していないことが分かった。

# 問題解決までの経緯

1. 一回下記方法でコンテナとイメージを削除した。
    1. `$ docker pa -a`でコンテナ一覧の出力
    1. `$ docker rm コンテナID`でフロント用、バック用、DB用のコンテナを削除
    1. `$ docker images`でイメージ一覧の出力
    1. `$ docker rmi イメージID`でフロント用、バック用、DB用のイメージを削除
1. もう一度各コンテナの起動を実施。
1. やはりDBコンテナだけ立ち上がらない。
1. Docker for Macのダッシュボードを開く。
1. 「Containers」から当該のコンテナを探し出し「再生ボタン」をクリックして起動を試みた。
1. 下記のようなエラーが出た。

    ```
    Could not open file '/var/log/mysql/mysql-error.log' for error logging: No such file or directory
    The designated data directory /var/lib/mysql/ is unusable. You can remove all files that the server added to it.
    Aborting
    ```

1. どうやらDBコンテナの`/var/log/mysql/`のmysql-error.logファイルに書き込めないっぽい。ディレクトリが存在しないか、権限が無いかのどちらかっぽい気がする。
1. 僭越ながらDBのDockerファイルに下記の様にディレクトリの作成と権限をMySQLユーザーにするように記載して、再度コンテナとイメージの削除を行い、もう一度各コンテナを再起動した。

    ```Dockerfile
    RUN mkdir /var/log/mysql
    RUN chown mysql:mysql /var/log/mysql
    ```

1. 問題は解決し、DBコンテナが正常に立ち上がった。
【TS】オブジェクトをマージする際の型定義はPartial<T>を使うと便利

# 結論 
オブジェクトをマージする際や上書きする際の型定義は`Partial<T>`を使うと便利です。

## どんな時に使えるの？
たとえば、[TSの公式ドキュメント(partialtype)](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype)が提供されているケースでは、`updateTodo`関数が、`Todo`型である`todo1`のオブジェクトに、更新対象の`todo2`のプロパティで上書きする場合が挙げられています。
```ts
interface Todo {
  title: string;
  description: string;
}
 
function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
  return { ...todo, ...fieldsToUpdate };
}
 
const todo1 = {
  title: "organize desk",
  description: "clear clutter",
};
 
const todo2 = updateTodo(todo1, {
  description: "throw out trash",
});
/** output: {
 * title: "organize desk",
 * description: "throw out trash",
 * }
**/
```

## さいごに
実際の開発現場では、`JS`の[スプレッド構文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax)を利用したマージ処理のときに結構使えるケースが多い、という所感です。
`Partial<T>`の他にも、`TS`がいろんなユーティリティタイプを提供しています。
[TSのutility-types](https://www.typescriptlang.org/docs/handbook/utility-types.html) ← 興味があったらぜひのぞいてみてくださいね～
RaspberryPiとVEML7700を試す

# Outline
 raspberryPiを使って明るさを得るために
 VEML7700モジュールを使って値を取得する。　
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483299/a7456302-373c-0cf5-7da9-53ad70e031c1.jpeg width=320>

# Hardware
* raspberry pi
* [STEMMA QT / Qwiic互換 VEML7700搭載 I2C 照度センサ](https://www.switch-science.com/products/8182)
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483299/1d54f74b-58eb-a2c6-b055-07f981126251.png width=320>

#  Installation of VEML7700 Library

```
sudo pip3 install adafruit-circuitpython-veml7700
```
# run
```
python3 veml7700_simpletest.py
```

# output
```py:veml7700_simpletest.py
Ambient light: 144
Ambient light: 99
Ambient light: 310
Ambient light: 310
Ambient light: 2432
Ambient light: 6025
Ambient light: 7135
Ambient light: 6812
Ambient light: 6888
Ambient light: 6882
```

# 仕様

センサ：照度
測定範囲：0~120 klx
ダイナミックレンジ：16 bit
解像度：0.0036 lx/ct

# 参考

* [STEMMA QT / Qwiic互換 VEML7700搭載 I2C 照度センサ](https://www.switch-science.com/products/8182)
* [Python & CircuitPython](https://learn.adafruit.com/adafruit-veml7700/python-circuitpython)
* [Adafruit_CircuitPython_VEML7700](https://github.com/adafruit/Adafruit_CircuitPython_VEML7700)
* [VEML7700 データシート](https://www.vishay.com/docs/84286/veml7700.pdf)
RaspberryPiとBME280で周辺環境(温度・湿度・気圧)を測定する

# Outline
BME280を搭載した小型の環境センサモジュールで、気圧、湿度、温度を簡単に測定することが可能です。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483299/fcc83982-5723-f2c9-73bb-81b769a79fe9.jpeg width=320>

# Hardware setup
* raspberry pi
* [BME280搭載 環境センサモジュール](https://www.switch-science.com/products/5862) 

| Raspberry-pi | 配線 | BME280 |
|:-----------|------------:|:------------:|
|01 3.3V        | <-> | VIN |
|03 SDA        | <-> | SDA |
|05 SCL        | <-> | SCL |
|09 GND        | <-> | GND |


# ディレクトリ構成
```
home/
├ qwiic_bme280.py #ライブラリ
├ bme280_ex1.py:簡易サンプル
├ bme280_ex4.py:sensor setup付き
├ bme280_ex5.py:
└ atmospheric_mp.py:マルチプロセス

```

# Installation
```
sudo pip install sparkfun-qwiic-bme280
```

# run
```
cd BME280_Atmospheric_Sensor
python3 bme280_ex1.py
```

# output sample
※より正確な測定値を得るためには校正が必要。

```py:bme280_ex1.py
Humidity:	47.022
Pressure:	122247.848
Altitude:	-5288.442
Temperature:	73.98

Humidity:	47.041
Pressure:	122444.332
Altitude:	-5334.506
Temperature:	73.89

```

```py:bme280_ex4.py
Humidity:	47.022
Pressure:	122247.848
Altitude:	-5288.442
Temperature:	73.98

Humidity:	47.041
Pressure:	122444.332
Altitude:	-5334.506
Temperature:	73.89

```

```py:bme280_ex5.py
SparkFun BME280 Sensor  Example 5

ID(0xD0): 0x60
Reset register(0xE0): 0x00
ctrl_meas(0xF4): 0x27
ctrl_hum(0xF2): 0x01

Displaying all regs:
0x08 0:0x96 0x70 0x89 0x52 0x0a 0x04 0x88 0x06 0xf0 0x6f 0x71 0x69 0x32 0x00 0x3e 0x8d 
0x09 0:0xda 0xd6 0xd0 0x0b 0x90 0x1e 0xd7 0xff 0xf9 0xff 0xac 0x26 0x0a 0xd8 0xbd 0x10 
0x0a 0:0x00 0x4b 0xf4 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x33 0x00 0x00 0xc0 
0x0b 0:0x00 0x54 0x00 0x00 0x00 0x00 0x60 0x02 0x00 0x01 0xff 0xff 0x1f 0x4e 0x08 0x00 
0x0c 0:0x00 0x40 0x27 0xff 0x00 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x0d 0:0x60 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
0x0e 0:0x00 0x74 0x01 0x00 0x12 0x28 0x03 0x1e 0xf0 0x41 0xff 0xff 0xff 0xff 0xff 0xff 
0x0f 0:0xff 0x00 0x01 0x0c 0x27 0x00 0x00 0x51 0xb6 0x00 0x81 0xcb 0x00 0x68 0x11 0x80 
Displaying concatenated calibration words:
dig_T1, uint16: 28656
dig_T2, int16: 26993
dig_T3, int16: 50
dig_P1, uint16: 36158
dig_P2, int16: 55002
dig_P3, int16: 3024
dig_P4, int16: 7824
dig_P5, int16: 65495
dig_P6, int16: 65529
dig_P7, int16: 9900
dig_P8, int16: 55306
dig_P9, int16: 4285
dig_H1, uint8: 75
dig_H2, int16: 372
dig_H3, uint8: 0
dig_H4, int16: 50
dig_H6, int8: 30
Humidity:	41.496
Pressure:	146789.895
Altitude:	-10627.602
Temperature:	74.35

Humidity:	41.807
Pressure:	121438.535
Altitude:	-5098.072
Temperature:	74.39

Humidity:	42.334
Pressure:	121353.621
Altitude:	-5078.039
Temperature:	74.37

```
以上

# 参考記事
* [購入 Qwiic - BME280搭載 環境センサモジュール](https://www.switch-science.com/products/5862) 
* [データシート](https://cdn.sparkfun.com/assets/e/7/3/b/1/BME280_Datasheet.pdf)
* [Qwiic_BME280_Py](https://github.com/sparkfun/Qwiic_BME280_Py)
* [SparkFun Atmospheric Sensor Breakout - BME280 (Qwiic)](https://github.com/sparkfun/Qwiic_Atmospheric_Sensor_Breakout_BME280)
* [ラズパイで温度湿度気圧を測る グラフ](https://qiita.com/hxbdy625/items/16b16a4ac3b89add0e36)
&. （ぼっち演算子）

# はじめに
ぼっち演算子をつけるべきか、つけないべきかよく迷うのでメモ

## ぼっち演算子
オブジェクトに対してとあるメソッドを呼び出した時
そのオブジェクトがnilでない場合・・・実行結果を返す
nilの場合・・・nilを返す


## 使い方
```オブジェクト&.メソッド```

## 迷いポイント
.&のまえのオブジェクトがnilの可能性がある場合につける

①userがnilの可能性がある場合・・・すべてのメソッドの前にぼっち演算子が必要
user&.infomation&.credit&.id

②userがnilの可能性がない場合・・・userのうしろにぼっち演算子は不要
user.infomation&.credit&.id

③userとuserに紐づくinfomationもnilの可能性がない場合・・・userとinfomationのうしろにぼっち演算子は不要
user.infomation.credit&.id

## まとめ
&. （ぼっち演算子）をつけるのは.&のまえのオブジェクトがnilの可能性がある場合のみ！！
※色々なところにつけると、コードを見た人がnilの可能性もあるのかと思い込んでしまうため

# 参考文献
- [Ruby ぼっち演算子について](https://qiita.com/yoshi_4/items/e987b698c1978d248cfc)
RaspberryPiとINA219で電流・電圧・電力を測定する

# Outline
 INA219を用いて電流電圧電力を測定する。
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483299/437b5a1b-488e-f0e6-dbf3-f507c2f7c241.jpeg width=320>


# Hardware setup
* raspberry pi
* [INA219 High Side DC Current Sensor Breakout - 26V ±3.2A Max - STEMMA QT](https://www.adafruit.com/product/904)

| Raspberry-pi | 配線 | INA219 |
|:-----------|------------:|:------------:|
|01 3.3V        | <-> | VIN |
|03 SDA        | <-> | SDA |
|05 SCL        | <-> | SCL |
|09 GND        | <-> | GND |


Vin+ : 電源側の＋端子
Vin- : 負荷側の＋端子

GNDの接続
　ラズパイのGNDと計測したい負荷のGNDを接続しておく。

※コード内のゲイン調整等はOFFにしておく。
<img src=https://user-images.githubusercontent.com/7821215/180698285-98207d9f-59d3-4b4b-9811-ebd85bc4fc48.JPG width=320><img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483299/5558622f-d549-e18c-572c-928b491a2e10.png width=320>


# ディレクトリ構成

```
home/Current_measure_INA219
├ current_ina219_mp.py  #マルチプロセス化
├ current_ina219_mp2.py  #マルチプロセス化+グラフ化
├ ina219_simpletest.py #Adafruit_CircuitPython_INA219 サンプルコード
└iv_test.py #ブログ掲載のコード
```


## install
```
sudo pip3 install pi-ina219
```

# run
```
cd Current_measure_INA219
python3 current_ina219_mp.py
```

# output sample

```py:current_ina219_mp.pyの出力
Voltage (VIN+) :  9.229   V
Voltage (VIN-) :  9.224   V
Shunt Voltage  :  0.00535 V
Shunt Current  :  0.0535  A
Power Calc.    :  0.49348 W
Power Register :  0.538   W

Voltage (VIN+) :  9.253   V
Voltage (VIN-) :  9.248   V
Shunt Voltage  :  0.00539 V
Shunt Current  :  0.0539  A
Power Calc.    :  0.49847 W
Power Register :  0.498   W
```
<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/483299/d313f812-2696-eb7a-8e89-14f68887eaf3.jpeg width=320>

以上

# 参考記事
* [RaspberryPI + INA219 を使って電圧、電流を測定する](https://nasuplant.blogspot.com/2019/08/raspberrypi-ina219.html)
* [Adafruit_CircuitPython_INA219](https://github.com/adafruit/Adafruit_CircuitPython_INA219)
* [電圧測定 (1): ina219 を使う](http://satemochi.blog.fc2.com/blog-entry-125.html)
* [INA219 電流センサーモジュール](http://7th-chord.jp/sara_tsukiyono/index.php?cl=rp&rp=200918)
* [M5StickCとINA219電流センサで太陽光パネルからバッテリへの充放電電流を測定する](https://zoe6120.com/2020/07/26/1556/)
* [ゆっくりラズパイ解説2020.09.18 電流計測モジュール INA219](http://7th-chord.jp/sara_tsukiyono/index.php?cl=rp&rp=200918)
* [RaspberryPI + INA219 を使って電圧、電流を測定する](https://nasuplant.blogspot.com/2019/08/raspberrypi-ina219.html)
* [adafruit-ina219-current-sensor-breakout](https://learn.adafruit.com/adafruit-ina219-current-sensor-breakout/python-circuitpython)
* [Adafruit_CircuitPython_INA219](https://github.com/adafruit/Adafruit_CircuitPython_INA219/blob/main/examples/ina219_simpletest.py)
* [回路図の例](https://tutorial.chirimen.org/pizero/esm-examples/ina219/index.html)
* [Ina219 Raspberrypai4B i2c address](https://forums.raspberrypi.com/viewtopic.php?p=2002563)
アドレスの指定 : ina219 = INA219(i2c_bus, addr=0x45)
* [INA219の使い方](https://qiita.com/kanade_k_1228/items/3234317e456a5999f663)
named-checkconfについて

●named-checkconf
BIND（named）の設定ファイルであるnamed.confの構文チェックを行うコマンド。
指定された設定ファイルの構文に誤りがないかチェック。
あくまで構文のチェックですので、設定の値が適切かどうか等、設定の中身に関するチェックは行いません。

コマンドの書式

named-checkconf [ファイル名]
※ファイル名を指定せずに実行した場合は「/etc/named.conf」をチェック
初めてRustを触った所感・調査結果

はじめに
======
普段はPythonでプログラムを書いているエンジニアですが、
Rustに興味があったため、軽く調べてみました。

Rustについて一番わかりやすい記事
======
https://qiita.com/elipmoc101/items/3c8b6d8332a9019e578c

Rustの凄さ
======
https://qiita.com/yamakona/items/2f0eb783378bac7253b4

>実際このなかにはたくさんの「aaaa」って文字がはいってるの
>だけど、１個だけ「test」って文字が入っちゃってて何行目にあるのかを知りたいよね
>標準のgrepとRust製のgrepで比較してみよう！
>1GBのデータから値を抜き出す速度の比較

>結果
>grep → 7.14s
>rg → 0.06s

→早すぎて笑った。
インタプリタ型のPythonで普段開発しているので、
コンパイラ型のRustはやはり強そう。

Rustを触ってみる
======
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021

・こちらのサイトにて、簡単な演算とか試せる。
・ガッチガチに文法が決められているので、なかなか実行できないが、
これだけ強固だと、Rustのコンセプト「安全性」を実感できる。


今後、Rustで開発したいもの(Webアプリ)
======
https://developers.cyberagent.co.jp/blog/archives/31110/

https://logmi.jp/tech/articles/326777

・文法とか細かいのは後ほど勉強する予定。
・フレームワークのことを、Rustだと「クレート」と呼ぶ。
・クレートで簡単なAPI Webアプリを作って、GET・POSTができることを試してから深く学んでいきたい。


最後に
======
・学びやすい、楽しく開発できるチュートリアルやサイトがあれば教えていただけると嬉しいです。
WSL2環境でsystemctlを使えるようにする方法

# 環境
OS：Oracle Linux 8.7

# 問題
WSL2環境内でSystemctlを使おうとすると、以下のエラーが発生する。
```
System has not been booted with systemd as init system (PID 1). Can't operate.
```

genieをインストールして問題を解決しようとしたが、なにせOSがUbuntuじゃないから、なんやかんやで上手くいかなかった。
私は英語も読めないし書いてある内容がさっぱり分からないので、とりあえず適当に調べて解決した物を備忘録として残しておく。

# 解決策
/etc/wsl.confを作成し、以下の内容を入力。
```conf
[boot]
systemd=true
```

再起動したらsystemctlが使えるようになった。
```
[root@THIS_IS_MYPC I_AM_USER]# systemctl status telnet.socket
● telnet.socket - Telnet Server Activation Socket
   Loaded: loaded (/usr/lib/systemd/system/telnet.socket; enabled; vendor preset: disabled)
   Active: active (listening) since Sat 2023-01-28 17:22:15 JST; 8min ago
     Docs: man:telnetd(8)
   Listen: [::]:23 (Stream)
 Accepted: 0; Connected: 0;
    Tasks: 0 (limit: 26213)
   Memory: 8.0K
   CGroup: /system.slice/telnet.socket

Jan 28 17:22:15 THIS_IS_MYPC systemd[1]: Listening on Telnet Server Activation Socket.
[root@THIS_IS_MYPC I_AM_USER]#
```

# 参考サイト
https://forest.watch.impress.co.jp/docs/news/1441775.html
Flutter ThemeDataにElevatedButtonのstyleを設定し共通のスタイルを使う

# はじめに
アプリ全体であるボタンのデザインを全て同じにしたい場合はよくあることかと。
そんな時に使える`ThemeData`の使い方を兼ねて、ElevatedButtonのstyleを統一したいと思います！:relieved:

# 同じコードを何度も書くのは避けたい。。
実際のアプリではボタン1つでもこれほどのコード量になったりします。。（これでも少ない方かも）
`ElevatedButton`は全て同じデザインなのに、何度も`style`を同じ内容で書いているとコードがどんどん肥大化していきます:sweat:


```dart
 SizedBox(
              width: _screenSize.width * 0.7,
              child: ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    final nameList = [
                      for (int i = 0; i < numberOfMember; i++)
                        _nameController[i].text
                    ];
                    ref.read(manNameProvider.notifier).state = nameList;
                    _moveStep(context);
                  }
                },
                style: ElevatedButton.styleFrom(
                  minimumSize: const Size(double.infinity, 50),
                  shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(20),
                  ),
                ),
                child: const Text('次へ'),
              ),
            ),
```

何かしらのメソッドなどをより少ないコードにするのは難しいですが、**ウィジェットの`style`を省略してコードを少なくするのは簡単なのでぜひやってみましょう！**

# ThemeDataを設定する

```dart:main.dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
          primarySwatch: Colors.blue,
          primaryColor: Colors.amber[300],
          elevatedButtonTheme: ElevatedButtonThemeData(
              style: ElevatedButton.styleFrom(
            backgroundColor: const Color.fromRGBO(239, 128, 125, 1),
            minimumSize: const Size(double.infinity, 50),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20),
            ),
          ))),
      home: const NumberMembersScreen(),
    );
  }
}
```

これで全ての`ElevatedButton`から`style`を省いでも同じデザインになります！

https://api.flutter.dev/flutter/material/ThemeData-class.html


`ThemeData`にはものすごい数のウィジェットのテーマを設定できるので、書き方がわからない場合（例えば`ElevatedButton`なら`ElevatedButtonThemeData`みたいな）はそのウィジェットのクラス名で検索してみると見つかります！

![Screenshot 2023-01-28 at 17.28.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/c17598f1-2c08-8b50-e3eb-dbd9952436bb.png)


これで少しはすっきりした見やすいコードになりましたかね？
getaddrinfo ENOTFOUND localhost   エラーの対処法

vue3でフロントを作っている最中にこのようなエラーが起きた

```
> @0.0.0 dev
> vite

error when starting dev server:
Error: getaddrinfo ENOTFOUND localhost
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:internal/dns/promises:42:17) 
```

原因を探ってみると`/private/etc/hosts`のファイルがおかしいらしい。

```
127.0.0.1   localhost
```

を追加してみると直りました。

前に別プロジェクトでファイルをいじった時に消えていたみたいです。
1ヶ月前にファイルをいじったのに今エラーが出たのはなぜか気になりますが、わかり次第記載します。
C#の並列プログラミング

詳しくはここを読む：https://docs.microsoft.com/ja-jp/dotnet/standard/threading/
# プロセスとスレッド
プロセスは、OSから見た実行中のログラムのこと。一つのプロセスには、一つのメモリ空間が与えられる。つまり、プロセスの数だけメモリが割り当てられる。
スレッドは、OSがプロセッサの利用時間を割り当てる基本単位。プロセスの中にスレッドがあるイメージ。メモリを共有しているから、データの排他管理に気を付ける必要がある。
今回、「排他制御を非同期実行するために別スレッドで行う」ことと、「別プロセスを立ち上げてコマンド実行すること」の2つを行った。
前者は同じプロセスの中で実行できるが、後者はプログラムそのものが変わるので別プロセスとなる。

# 別プロセスを動かす
Processオブジェクトを作成して起動時の情報を設定し、Startし、WaitForExitで待機、終了したら破棄する。
<b>プロセスはDisposableメソッドであり、終了（Close）・破棄する（Dispose）必要がある。</b>
忘れがちなので、できるならUsingを使うのがいい。

# 非同期にタスクを実行する
タスクを非同期実行する場合、別スレッドで展開されることになる。
スレッドを終了させる際は、元スレッドに合流すればいい。
複数スレッドの状況をを管理するため、CancellationTokenオブジェクトなどを用いる。
https://docs.microsoft.com/ja-jp/dotnet/standard/threading/cancellation-in-managed-threads
（CancellationTokenもIDisposableメソッドなので、Dispose必須）

```C#:sample

public static void Main(){
 CancellationTokenSource source = null;
 try{
  source = new CancellationToken();
  Task.Run(() => {Do(source.token);}, source.Token);
  Task.Delay(1000);
  source.Cancel();
 }
 finally
 {
  source?.Cancel();
  source?.Dispose();
 }
}

private void Do(CancellationToken cancellationToken){
 while(cancellationToken.WaitHandle.WaitOne(waitMilliSec))
  {
   Console.WriteLine("a");
   if(cancellationToken.IsCancellRequested())
   {
    return;
   }
  }
}
```

# もっと詳しく
WaitHandleでのキャンセルトークンのリッスン
rails db:create 違うdevelopment生成

# はじめに

フリマアプリ作成時に`rails db:create`実行時に
アプリ名ではない`development`が作成されてしまうエラーが生じました。

# 仮説
調べたところ↓
https://prograshi.com/framework/rails/change-db-name/

`database.yml`での設定がおかしい様子。

~~~
development:
    database:○○○○○○_development

test:
    database:○○○○○○_test
~~~

と修正後
`bundle install`
`rails db:create`実行後

無事、解決できました。
Kotlinのinternalはどこからアクセス可能？

Kotlinの可視性修飾子である「internal」だが、公式ドキュメントを読んでもイマイチピンと来なかったので、
調べてみた。

# internalを公式ドキュメントから確認

Kotlinの[公式ドキュメント](https://dogwood008.github.io/kotlin-web-site-ja/docs/reference/visibility-modifiers.html)には以下のように記載されている
> internal として宣言すると、同じモジュール内のどこからでも見えます

ここで、モジュール内ってどの範囲？がわからなくなった。

# internalは自分のプロジェクト内部で使用可能

自分が所属するプロジェクト内で使用可能。
Android Studioでいうと、自分が開発しているアプリケーションのプロジェクト内部。
以下画像で言うところの、app配下でならinternalアクセス可能となる。
![スクリーンショット 2023-01-28 17.12.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317727/9e4eb9aa-682c-4071-e6a7-7f99c9f25b65.png)

詰まるところ、publicと非常に近いのではと思います。

# どのような場合に利用する？

internalは外部ライブラリには公開されません。
そのため、公開用のライブラリを構築中に、内部のみで利用するデータに対してinternalを利用するのが良いのではと思います。
【AWS】ELBのアクセスログを有効にする方法。S3バケットポリシーの編集で簡単2ステップで実施可能！

# 概要
* ELBのアクセスログを有効にする設定を行ったので、その方法を備忘を兼ねて残します。ネットで多くの方が記事にしてくれていますが、AWSの仕様が微妙に変わっているのもあり、ちょっと画面の操作も違ったので、それも兼ねて。
    * 参考記事：[Application Load Balancer のアクセスログを有効にする](https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/enable-access-logging.html)


# ①S3でバケットポリシーを付与する
* S3→バケットの作成→今回は名前を「sample-alb-log」とします。
* 作成後、アクセス許可のタブから「バケットポリシー」→「編集」をクリックしたら、以下のように必要な許可を付与します。
* ポリシーにおけるポイントは以下の二つだけです。
    * 「582318560864」のところはサービス側でELBを管理しているアカウントが入りますので、使用しているリージョンによって変わります。下記の場合はアジアパシフィック (東京)です。そのほかを使用の場合は、上記のAWS公式リンクにリストがあるので参照してください。
    * 「sample-alb-log/elb-logs」のところは「bucket name/prefix」となります。bucket nameは今回作成したバケットの名前、prefixはそのバケット内の下のディレクトリみたいなものです。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::582318560864:root"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::sample-alb-log/elb-logs/AWSLogs/*"
        }
    ]
}
```

# ②ELBからアクセスログをオンに、S3を選択する
* EC2→ELB→対象のELBを選択→Attributesタブ→Edit→Monitoringの「Access logs」をオンにします。その下にあるS3 URIの右にある「Browse S3」ボタンから作成したS3である「sample-alb-log」を選択します。
* 上記で、設定は完了です。

# ③S3のオブジェクトからアクセスログをダウンロードする
* sample-alb-logのオブジェクトタブから、elb-logs/AWSLogsの順番で見ていきましょう。
* まずはELBAccessLogTestFileができていることを確認します。
* elasticloadbalancing/の下に日付ごとにアクセスログが生成されていることがわかります。
* ダウンロードして中身を見ると、ターゲットからのステータスコードやリクエストタイプ、クライアントのIPアドレスなどが分かります。

# テストファイルだけで、アクセスログが出てこないときは？
* AWSリソースのどこかで問題が起きている可能性があります。
* 例えば、ALBにアクセスが到達していない場合が考えられます。その場合、アクセスログはもちろん生成されません。ALBがPublic Subnetにあるか、インバウンドルールは正しいか、などを確認しましょう。
js-cookieの使い方【備忘録】


# 概要
バイト先のアプリ開発でデータを一時的に保存したいのですが、LocalStorageだと
なぜか動作しないという問題がありました。
そこで、LocalStorageのように半永久的に残るものではなく
期限付きで削除してくれるものを使いたいなぁとCookieを思い出したので使ってみました🔥

# 使い方
## 大まかな流れ
大体はLocalStorageを利用する時と同じです。
若干Cookieの特徴があるので、そこだけ使い方が変わるイメージになります！

### Cookieに保存する時
1. JSONに変換
1. Cookieにセット
    1. 期限、パスなどの設定

:::note warn
JSONに変換しない場合、`[object Object]`といった謎の形式になってしまい
オブジェクト形式のデータを読み込めなくなるためです。
（valueに複数の値がセットされている場合に “.” で繋ぐことにより値を取得できる性質を利用）
:::

### Cookieから読み出す時
1. Cookieから読み込み
1. `JSON.parse`で変換

## ライブラリの導入
インストールは以下のように行います。
```zsh
# npm
npm i js-cookie

# yarn
yarn add js-cookie
```

### TypeScript
TSを使っている方はこちらまで実行しましょう。
```zsh
# npm
npm i --save-dev @types/js-cookie
# yarn
yarn add -D @types/js-cookie
```

## Cookieに保存
まず、JSONに変換します
```javascript
const jsonData = JSON.stringify(value)
```
次にCookieにセットします。
```javascript
Cookies.set(key, jsonData)
```

>Default: Cookie is removed when the user closes the browser.
Githubより引用

`expires`オプションを指定しない場合、`-1`の値がセットされる仕様で、
ブラウザを閉じた時に使えなくなるので、ブラウザを閉じた後でも使えるようにしたい場合は
`expires`オプションを指定する必要があります。

### オプション
オプションはオブジェクトで定義されており
以下のような形式で利用できます。
```javascript
const options = {}
Cookies.set('name', 'value', options)
```

#### expires：有効期限

デフォルト値は-1で、利用したい日数で指定できます。
今回は1日だけ有効にしたいので、1としました。
```javascript
Cookies.set('name', 'value', { expires: 1 })
```

#### path：サイトのパス
デフォルト値は`/`でサイト全体で有効です。
`/post`でのみ有効にしたい場合は以下のように指定します。
また、下手なパスのCookie読み込みを許容しなくなるため、XSS攻撃の対策に有効です。
```javascript
Cookies.set('name', 'value', { path: '/post' })
```

:::note warn
ファイルの拡張子を含むパスは設定できないとあるため、`/post/index.html`の
ようなパスは設定できないことに注意してください。
:::

>This means one cannot set a path using window.location.pathname in case such pathname contains a filename like so: /check.html (or at least, such cookie cannot be read correctly).
引用元：Github

その他に、`domain`, `secure`, `sameSite`がありますが、少し長くなるので、
気になる方は本記事の下の方を見ていただけると助かります🙏


## Cookieから読み出す
以下のように使うことで、Cookieから取得できます。
```javascript
const data = Cookies.get(key)
return JSON.parse(data)
```


# その他
## 言語設定
Cookieの言語設定は以下のように設定できます。
今回は日本語を指定しています。
```javascript
Cookies.set('locale', 'ja-JP')
```

## オプション
### domain
デフォルトでは、Internet Explorer（下記参照）を除き、
クッキーが作成されたページのドメインまたはサブドメインにのみ表示されます。
例として、`site.com`でドメインをセットすると、以下のようになります。
```javascript
Cookies.set('name', 'value', { domain: 'subdomain.site.com' })
```

### secure
デフォルトでは、セキュアなプロトコルを必要としない（＝HTTPSでなくても動作する）設定で
true or falseで指定します。
```javascript
Cookies.set('name', 'value', { secure: true })
```

### sameSite
デフォルトでは特に指定されておらず、
ブラウザがクロスサイトリクエストと一緒にクッキーを送信するかどうかを
制御できるようになるオプションです。

```javascript
Cookies.set('name', 'value', { sameSite: 'strict' })
```

sameSite属性についてはこちらを見ると良いと思います！

https://e-words.jp/w/SameSite%E5%B1%9E%E6%80%A7.html

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Set-Cookie/SameSite

:::note
最近のブラウザでは、何も指定しなくても、"Lax "をデフォルト値としているものが増えています
:::

# 参考文献

https://qiita.com/pipiox/items/95554673ba3b078ac112

https://github.com/js-cookie/js-cookie

https://e-words.jp/w/SameSite%E5%B1%9E%E6%80%A7.html

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Set-Cookie/SameSite
Pythonで非同期投げっぱなしファイル書き出し

Pythonで２面バッファにロギングしつつ、非同期でファイルに書き出す処理を書いてみた。
Fire-and-forgetとちゅうらしい。いわゆるヤリ逃げされるタスク。

:::note info
動作仕様
①main()は100msec周期で「日付＋ダミーデータ」のCSVデータをバッファに書き込む。
②dataNumMax(100)個データがたまったらファイル書き出し関数(writeDataToFile)を非同期投げっぱなしで呼び出す。
writeDataToFile()は指定されたバッファをファイルに書き出す。
③main()はバッファの書き出し面を切り替える。
※ctrl-Cで抜けてください
※Python3.11です
:::

非同期で動いていることの確認に、writeDataToFile()にsleep()を入れてみる。
main()がバッファに書いている時間には影響しないことがわかる。

:::note info
ポイント
・非同期処理したい関数にはasyncなどの接頭辞は不要
・非同期で実行するAPIは
loop.run_in_executor(executor, func, *args)
なので関数引数は３つ目の引数に入れる。
:::

```asyncio_filewrite.py
import datetime
import asyncio
from time import sleep

# グローバルな２面のデータバッファ
DataBuffer1 = []
DataBuffer2 = []

# ログファイル出力数
logFileNum = 0

# 1ファイルあたりのデータ数
dataNumMax = 100

# 仮のファイル名
MACAddress = "12:34:56:78"

# 2面のデータバッファを指定してバッファ格納
def storeDataBuffer(buffNo, dataStr):
    if (buffNo == 0):
        DataBuffer1.append(dataStr)
    else:
        DataBuffer2.append(dataStr)

# 非同期で動かすがasyncは付けない
def writeDataToFile(targetBuffNo):
    print("start writeDataToFile" + str(targetBuffNo))

    # 例えばここにsleepを入れてもmain側はブロッキングされない(ログファイル上はつながる)
    # sleep(1)

    devName = MACAddress.replace(":", "")
    global logFileNum
    filename = devName + "-" + str(logFileNum) + ".csv"

    # 指定バッファをファイル書き込み
    f = open(filename, "w")
    if (targetBuffNo == 0):
        f.writelines(DataBuffer1)
        DataBuffer1.clear()
    else:
        f.writelines(DataBuffer2)
        DataBuffer2.clear()
    f.close()

    # ログファイル数を増やす
    logFileNum = logFileNum + 1

    print("finish writeDataToFile" + str(targetBuffNo))
 
# メイン関数
def main():
    print("start main.")

    dataNum = 0
    buffNo = 0

    while True:
        # 100ミリ秒待つ
        sleep(0.1) 

        # 日付情報とダミーデータでCSVのデータを作る
        dt_now = datetime.datetime.now()
        timestr = dt_now.strftime('%H:%M:%S.%f')
        testDataStr = timestr + ",123,456,789\n"
        storeDataBuffer(buffNo, testDataStr)
        dataNum = dataNum + 1

        # データ数が１ファイル分たまったら書き出し
        if (dataNum >= dataNumMax):
            # ファイルへ非同期で書き出す。関数の引数は3番目に
            loop = asyncio.get_event_loop()
            loop.run_in_executor(None, writeDataToFile, buffNo) # 投げっぱなし. fire and forget.

            print("main() called writeDataToFile().")

            # バッファの切り替え(書き込み面を保護するため２面トグル)
            dataNum = 0
            if (buffNo == 0):
                buffNo = 1
            else:
                buffNo = 0

if __name__ == '__main__':
    main()
```

雑念が多いのでシンプルに非同期のところだけ

```asyncio.py
import asyncio
from time import sleep

# 非同期で動かす関数
def writeDataToFile(arg1):
    sleep(arg1)

# メイン関数
def main():
    while True:
        # ループ処理

        # 非同期で呼び出す       
        loop.run_in_executor(None, writeDataToFile, 1) 
        # すぐ抜けてくる

if __name__ == '__main__':
    main()
SSM Agentの設定を変更する場合の注意点

# はじめに
以前の記事で紹介した「[SSM Agentの実行スクリプトを削除する方法](https://qiita.com/sakai00kou/items/f6e04760783b805d55d5)」の設定を`Ansible`で行った際、失敗してEC2インスタンスにログインできなくなったため、そうならないようにするための注意点・回避方法を紹介したいと思います。

# Session ManagerによるEC2インスタンスログイン
`Session Manager`を使ってEC2インスタンスに接続を行うと、セキュリティグループで`SSH`アクセスを許可しなくても接続できるため、`SSH`による接続は行わずに`Session Manager`で接続を行うようにしている方も多いかと思います。

私が作業を行ったシステムでも`SSH`は許可されておらず、`Session Manager`経由でしか接続できない環境でした。

ちなみに`Session Manager`でログインする場合、EC2インスタンス側で`Session Manager`で接続できるようにIAMロールの設定や`ssm-agent`のサービスを起動（最近はデフォルトで有効）しておけば以下コマンドを入力するか、マネジメントコンソール上から接続できます。

```bash:Session Managerによるログイン
aws ssm start-session --target [インスタンスID]
```

# 回避策
同じようなことが起こらないようにするために考えた2つの回避策を紹介します。

## 作業前にSession Managerにログインしておく
`ssm-agent`のサービスを再起動しても、元々`Session Manager`で接続しているコネクションは切断されないため、`ssm-agent`の設定変更作業を行う前に、何かあったときのために別のコネクションを維持しておけば復旧できます。

当然ログアウトしてしまったり、何も操作せず長い時間放置してタイムアウトで切れてしまうと接続できないため、注意しましょう。

## EC2シリアルコンソール機能を使ってログインする
いくつか条件や事前準備は必要ですが、対象のEC2インスタンスが`Nitro`インスタンスタイプの場合はEC2シリアルコンソールを使えば`ssm-agent`のサービスが停止してしまっている場合でも接続できます。

EC2シリアルコンソールについて詳しくは前回の記事に書かれています。

- [EC2シリアルコンソール接続を試す。](https://qiita.com/sakai00kou/items/9d1a474ae24ce6d2d242)

今回のような`ssm-agent`の設定変更時だけではなく、他の不具合で接続できなくなった場合でも対処できる可能性があるので、`Nitro`インスタンスを使用しているようであればいざというときのために設定しておくと良いと思います。

# おわりに
今回は許可されている他インスタンスから接続を行うことで無理やり対処しましたが、作業に対する注意力が足りなかったと反省しております。

繰り返さないよう意識を高めることも必要ですが、問題が発生した場合の回避策や事前の防止策を学ぶことで改善することも必要だと改めて感じました。
[本の紹介]理系でもバカは読め！　文系でも数式なしのPython x Excelで稼ぐ力を上げる！

# 本質をつかめ！
これまでに何冊も機械学習の本読んできたけど、結局、機械学習ってなんなのかわからないという人にとっては目から鱗の本だと思います。

タイタニックが、、、アヤメが、、、Kaggleがって言われてもなにがなんだかわからなくないですか？　少なくとも僕はこれまでわかってませんでした。

この本は、売上とか販売量とか予測とかなじみの深い話題を扱っているので頭に入ってきやすいと思います。　相関とか回帰係数とかそもそも何なのというレベルの人にはとても有用だと思い紹介しました。

# 注意：機械学習のプロ向けではありません。
この本では、折れ線グラフの書き方から始まり、重回帰分析、K-mean法までしか扱っていないのでそのレベル理解できてるよという人には逆に不要だと思います。

https://kanki-pub.co.jp/pub/book/details/9784761275280
【Swift】変数と定数の基本について

# はじめに

どうも、プログラミング学習中の*はるさん*です。
この記事ではSwiftの基本である「変数」と「定数」について説明していきます。
Swiftに限らず、多くのプログラミング言語でも使われている「変数」と「定数」
について自身が学んだことをアウトプットしていきます。


# 変数、定数とは？

変数と定数とはプログラム上で使用するプログラムの入れ物です。
定めた変数名、または定数名に値を入れて使用します。
この値は数値のことだけではなく、文字や別のプログラムの処理結果など
様々なものが入れられます。
この値を入れることをプログラミング用語では「値を代入する」と言います。
そして、varやletというキーワードを用いて変数や定数を決めることを
_「変数（定数）を宣言する」_
と言います。


# 記述方法

記述方法としては両方とも共通で
**キーワードvarに続けて変数名 = 値**
**キーワードletに続けて定数名 = 値**
となります。

実際にコードで書いてみます。ここでは
*「箱の色は赤です」*
と宣言します。

```swift
var boxCalor = red
let boxCalor = red
```


# 変数と定数の違い

先に述べた例でいくと変数と定数の内容に違いはありません。
しかし、コード上では後から内容を変更することもよくあります。
例えば、この箱の色を青に変更したいとします。
その場合変数はその名の通り変更が可能です。
しかし、定数は一度決めたら変更は不可能です。

```swift
// 変更可能
var boxCalor = blue

// 変更不可能でエラーが出る
let boxCalor = blue
```

よって、コード上では値の変更があり得るものは変数で宣言します。
逆に変更することがないもの、あるいは変更されてはいけないものを
定数として宣言します。


# 終わりに

変数と定数の基本的な部分について説明しました。自分もまだまだ勉強中なので、
間違いがありましたらご指摘して頂けるとありがたいです。
この記事がプログラミング初学者の方にとってお役に立てれば幸いです。

# 参考著書
- [増補改訂第３版] SWIFT実践入門
PlatformIO の使い方

## インストール
Visual Studio Code をインストール
[Ubuntu: Visual Studio Code の使い方](https://qiita.com/ekzemplaro/items/2ff5ba009f9fc6699eb1)

PlatformIO をインストール
[PlatformIO のダウンロードからインストールの紹介](https://logikara.blog/install_platform/)

## プログラム
フォルダー構造

```text
$ tree project01/
project01/
├── include
│   └── README
├── lib
│   └── README
├── platformio.ini
├── src
│   └── morning.cpp
└── test
    └── README
```

```cpp:src/morning.cpp
// ---------------------------------------------------------------
/*
	morning.cpp

						Jan/28/2023
*/
// ---------------------------------------------------------------
#include <M5Core2.h>

int icount = 0;
// ---------------------------------------------------------------
void setup()
{
	M5.begin();
	M5.Lcd.setTextSize(4);
	M5.Lcd.println("Good Morning");
}

// ---------------------------------------------------------------
void loop()
{
	Serial.println("icount = " + String(icount));

	M5.Lcd.setCursor(5,60);
	M5.Lcd.println("icount = " + String(icount));
	delay(1000);
	icount++;
}

// ---------------------------------------------------------------
```

コンパイルして、M5Stack Core2 にアップロード、実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/9aa20bd0-bd5e-247a-c838-f56c73b48db6.png)

## 新しいプロジェクトの作成方法

Quick Access で + New Project を選びます。
![project_aa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/c08ab598-602d-4c72-481a-c87024a8f77c.png)

Project の情報を入力します。

```text
Name: project02
Board: M5Stack Core2
Framework: Arduino
```

![project_bb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/5d7049f6-791e-57e9-880b-cf9ecfc1ebe9.png)

次の場所に、

```text
/home/uchida/Documents/PlatformIO/Projects
```

Project が作成されます。
![project_cc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/77c68ded-2626-2bcc-62d5-c6a88b4c9df3.png)

次のようなフォルダーが作成されています。

```text
$ tree project02
project02
├── include
│   └── README
├── lib
│   └── README
├── platformio.ini
├── src
│   └── main.cpp
└── test
    └── README
```

src/main.cpp を改造します。

```cpp:src/main.cpp
#include <Arduino.h>

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}
```
RNNの基本

# はじめに
今回は時系列データを用いる際に使用する，Recurent Neural Network(RNN)についてまとめておきます．
最もシンプルなRNN，進化系のLSTM，LSTMを軽くしたGRUについて紹介します．

また，RNNへの入力形式についてもお話しできればと思います．
時系列データは画像等とは少し違ったデータ形式にして，入力しないといけません．
（はじめて実装するときに悩んだので，同じ悩みを抱える人の助けになればいいな:relieved:）

因みに，モデルの実装はPytorchだとnn.RNNと書くだけなので楽勝です．
（勿論中身を理解した方がいいですが）

# 目次
[1 RNN](#1-RNN)
[2 LSTM](#2-LSTM)
[3 GRU](#3-GRU)
[4 RNNへの入力形式](#4-RNNへの入力形式)

# 1 RNN
RNN（Recurent Neural Network）とは，時系列データを扱うDeep Neural Networkです．
RNNでは現在に対する過去の影響を考慮します．

時刻 (t) における状態を考えるとき，時刻 (t) の入力である入力 x(t) に加え，時刻 (t-1) の状態を表す h(t-1) を保持し，時刻 (t) に伝えます． 
t-1 には t-2 の情報が含まれているため， t にも t-2 の情報が含まれていることになります．このように再帰的に考えて，過去の情報が反映されているということで，Recurent な NN と呼ばれています．
![RNN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/f91a771a-1515-2d92-ceb9-b5c07dd0f122.png)

# 2 LSTM
しかし，シンプルなRNNには欠点があります．それは，長期的な依存関係を捉えられないことです．この問題を解決しているのがLSTMです．LSTMのモチベーションは以下の通りです．
- 過去の情報をネットワーク内に保持しておきたい
- 過去の情報を必要なタイミングで取得したい

LSTMはメモリーセル(ct)と呼ばれる状態を持ち，これに忘却ゲート (ft)，入力ゲート (it)，出力ゲート (ot) と呼ばれる情報の取捨選択機構を持っています．
- 忘却ゲート：メモリーセルに保持している情報をリセットするかを選択する．
- 入力ゲート：入力を取り込むか否かを選択し，セルの状態を更新する役．
- 出力ゲート：次の時刻にどの程度情報を伝えるかを選択する．

各ゲートでの情報の取捨選択は，シグモイド関数 (σ) によって行われます．シグモイド関数は [0,1] の値を出力し，0 であればゲートを通さず，1 であれば全て通します．
![LSTM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/6ca005c9-0922-368b-1c96-035eab93413c.png)


# 3 GRU
GRUはLSTMの精度はそのままで高速化したモデルです．といいつつもLSTMとGRUどちらの方が高い精度を出せるかはタスクやデータによってまちまちとのことなので，どちらも試して良い方のモデルを採用するのが良いでしょう．

因みに私がしていたタスクだと，パラメータ数が　RNN：LSTM：GRU＝１：４：３　になっていました．精度はほぼ同じでしたね．

# 4 RNNへの入力形式
RNNへの入力には，何時刻前までを予測に使いたいのかを決める必要があります．
私のしていた心電図タスクで考えてみたいと思います．（医療データは外部持ち出し:no_good_tone1:なので数値はでたらめです．）
![RNN1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/6b61838f-9677-7bd0-6959-05a312da4171.png)
Xをデータ，yをGroundTruth（正解ラベル）とすると，以下のようになると思います．
![RNN2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/d6fa563c-23ab-1abe-b696-82b899bf8748.png)
RNNへの入力形式は以下のようにします．3時刻を見るとすると，対象となる時刻，その1つ前，その2つ前を1セットにします．それに対して，対象時刻のラベルを予測するという形式になります．
![RNN3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/d192984d-4a21-ffa3-30e3-db4707fc24c8.png)


# 5 系列データのバリエーション
系列データには，入出力のパターンが複数あり，それぞれ”入力to出力”の形で呼ばれます．

- One to One
    - 入力も出力も固定サイズのベクトル．普通のNN．
- One to Many
    - 入力は固定サイズのベクトル，出力は系列．
- Many to One
    - 入力は系列，出力は固定サイズのベクトル．系列データのクラス分類など．
- Many to Many
    - 入力も出力も系列．言語翻訳など．


![diags.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120757/05840462-b03f-cd43-753a-1992973c7cd4.jpeg)
参照：[http://karpathy.github.io/2015/05/21/rnn-effectiveness/]()


# 6 高速化
## 6.1 処理の高速化（numba）
## 6.2 ネットワークの高速化（toch.jit，Julia）


# さいごに
随時追記予定です．
RNNはなんだか考えていると頭がこんがらがってきますね💦　いきなり実装じゃなくて一度データ形式等を考えてからコーディングをするとうまくいくと思います👍
私も学んでいる身なので，間違えている部分があれば教えてください🙇