OmniAICreator/Qiita-1.07M huggingface dataset:
静的ウェブサイトホスティングにCloudFrontを経由してアクセスしてみる

# 概要

本記事は [AWSでWebアプリを構築してみる](https://qiita.com/ti_and6id/items/9670ee60965a4d10bec7) シリーズの2回目の記事です。
前回の記事は[こちら](https://qiita.com/ti_and6id/items/fe652f89d8919052c91c)。

# 本記事で作成する構成

本記事では静的ウェブサイトホスティングにCloudFrontを経由してアクセスできるようにしてみます。
![AWS.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/cacc9846-2940-48ae-07af-58bd74e1d204.png)
ここでは図のようにS3でホスティングした静的ウェブサイトに直接アクセスすることと、CloudFrontを経由して間接的にアクセスすることの、２通りのアクセスが可能な状態になります。

# 静的ウェブサイトホスティングにCloudFrontを経由してアクセスしてみる

## 1. CloudFrontを構築する

1. マネジメントコンソールからCloudFrontを開き、「ディストリビューションを作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/01ac578d-e7f3-3fb9-8f0e-2d3e6af9ad08.png)

1. オリジンでは「オリジンドメイン」に[静的ウェブサイトホスティングにCloudFrontを経由してアクセスしてみる](https://qiita.com/ti_and6id/items/c257f9d011f84b97ac3e)で作成したS3バケットを選択し、Webサイトのエンドポイントを使用をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/05503af7-e7ce-83dd-6055-51b60f9a0996.png)

1. デフォルトのキャッシュビヘイビアでは「ビューワープロトコルポリシー」で「Redirect HTTP to HTTPS」を選択してHTTPをHTTPSにリダイレクトするようにして、さらに「許可されたHTTPメソッド」で「GET, HEAD」を選択してHTTPメソッドのGETとHEADのみ許可するようにする

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/ecc7c393-031a-589d-5b86-e6fe51251788.png)

1. 「ディストリビューションの作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/311df747-53b1-9eaa-36e2-8df595baefb1.png)

## 5. 静的ウェブサイトにアクセスする

1. 作成したディストリビューションの一般タブを開き、「ディストリビューションドメイン名」をコピーしてブラウザで開き、[静的ウェブサイトホスティングにCloudFrontを経由してアクセスしてみる](https://qiita.com/ti_and6id/items/c257f9d011f84b97ac3e)で作成した静的ウェブサイトにアクセスできることを確認する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/d3e3b91f-e09d-71bc-21eb-0c7bdde977b9.png)
静的ウェブサイトホスティングでホスティングしてみる

# 概要

本記事は [AWSでWebアプリを構築してみる](https://qiita.com/ti_and6id/items/9670ee60965a4d10bec7) シリーズの1回目の記事です。

# 本記事で作成する構成

本記事では静的ウェブサイトホスティングでアプリケーションコンテンツをホスティングします。
![AWS.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/5da46841-89a3-52cb-97d3-dd9c7cd71cf4.png)

# 静的ウェブサイトホスティングでホスティングしてみる

## 1. S3でバケットを作成する

1. マネジメントコンソールからS3を開き、「バケットを作成」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/b0b5361d-2b5b-c33c-a37e-8f4ad502e09e.png)

1. 「AWSリージョン」で任意のリージョンを選択し、「バケット名」に任意のバケット名を入力する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/a253f74b-37f8-3993-ff13-3cbf87ca4502.png)

1. 「オブジェクトの所有者」は「ACL無効（推奨）」を選択する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/a8af3536-6848-ac13-6a43-6c08c942293d.png)

1. 「このバケットのブロックパブリックアクセス設定」はすべての選択を解除し、オブジェクトを公開するように設定する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/fd29f50d-db08-4c10-a74d-0d076a5ac07c.png)

1. バケットを作成する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/3901885e-aa37-3f7d-ff89-a4039ba67618.png)

## 2. プロパティを更新する

1. 作成したバケットのプロパティタブを開き、「静的ウェブサイトホスティング（最下部にある）」の「編集」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/eb28e9cc-5daf-f446-cdf2-1d9c301194e5.png)

1. 「静的ウェブサイトホスティング」を有効にして、「ホスティングタイプ」で「静的ウェブサイトをホストする」を選択して、「インデックスドキュメント」を入力する（index.html）

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/ef014414-79f5-14f0-48a1-b031f25d1261.png)

## 3. アクセス許可を更新する

1. 作成したバケットのアクセス許可タブを開き、「バケットポリシー」の「編集」をクリック

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/7f913d60-4273-a02f-e089-8fe3a8e2c6f1.png)

1. バケットポリシーを編集する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/ab3931eb-633a-f3a8-8f62-b1c601b760be.png)

    ```
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "PublicReadGetObject",
                "Effect": "Allow",
                "Principal": "*",
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::バケット名/*"
            }
        ]
    }
    ```

## 4. コンテンツを配置する

1. ローカルPC上で以下のような内容のインデックスドキュメント（index.html）を作成する

    ```
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
        <title>My Website Home Page</title>
    </head>
    <body>
      <h1>Welcome to my website</h1>
      <p>Now hosted on Amazon S3!</p>
    </body>
    </html>
    ```
2. 作成したバケットのオブジェクトタブを開き、さきほど作成したインデックスドキュメントを（ルート直下に）アップロードする

## 5. 静的ウェブサイトにアクセスする

1. 作成したバケットのプロパティタブを開き、「静的ウェブサイトホスティング（最下部にある）」に記載されているバケットウェブサイトエンドポイントのリンクへアクセスし、無事ホスティングできていることを確認する

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/94e625da-6941-0512-d0ae-d36d943380c9.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/d3e3b91f-e09d-71bc-21eb-0c7bdde977b9.png)
AWSでWebアプリを構築してみる

# 概要
AWSでWebアプリを構築したときに小さなステップから少しずつアプリになっていくまでの過程を記録に残していきたいと思います。

# 構成
今回作成したWebアプリは以下のような構成で組んでみました。

![AWS.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3630916/93bf62cb-2f60-851b-1c0f-768309f08bb0.png)

Amplifyを使うとより簡単に構築できそうですが、今回は学習を兼ねてあえてAmplifyを使わずに構築してみます。

# 記事シリーズ

以下の記事で小さなステップから徐々にアプリになっていくまでの過程を記録していきます。

1. [静的ウェブサイトホスティングでホスティングしてみる](https://qiita.com/ti_and6id/items/fe652f89d8919052c91c)
1. [静的ウェブサイトホスティングにCloudFrontを経由してアクセスしてみる](https://qiita.com/ti_and6id/items/c257f9d011f84b97ac3e)
1. [静的ウェブサイトをCloudFront経由のアクセスしか許可しないようにしてみる](https://qiita.com/ti_and6id/items/e9ef9da23b3e33116f6b)
1. [CloudFrontのキャッシュ削除を自動化してみる](https://qiita.com/ti_and6id/items/d329ce5e9dc838563d7f)
1. [REST APIを作成してみる](https://qiita.com/ti_and6id/items/b5fd3eec7bf0a68ecc8c)
1. [REST APIをCloudFront経由のアクセスしか許可しないようにしてみる](https://qiita.com/ti_and6id/items/3cc12183659493d735d7)
1. [REST APIでDynamoDBからデータを取得してみる](https://qiita.com/ti_and6id/items/895520c5d987beadefcf)
1. [静的ウェブサイトからREST APIを呼び出してみる](https://qiita.com/ti_and6id/items/2175e4421cbada9a242a)
1. [静的ウェブサイトおよびREST APIを認証してから利用できるようにしてみる](https://qiita.com/ti_and6id/items/a78516138a6150045c42)
線形代数の学習備忘録（part1）

## はじめに
線形代数を学び始めたので、備忘録として簡単に定義や定理を自分の中で理解しやすいようにまとめてみました。

## 写像と変換の違い

- **写像**
  - ２つの集合X,Yにおいて、Xのどの要素にもYの要素が１つずつ対応しているとき、この対応をXからYへの写像という
- **変換**
    - 集合XからX自身への写像をX上の変換という

**一言メモ**
- 写像と変換の違いはどこに表れるかというと、行列のサイズにでてくる。変換はm×m行列のような正方行列で表され、写像はm×n行列のような行列で表される

## 線形写像
- **線形写像**
  - ベクトル空間からベクトル空間への写像のうち、線形性が崩れないもの
    - **階数**
      - f: V → WをK上の線形写像とするとき、Wの部分空間f(v)の次元をfの階数といい、rank(f)と記述する
      - rank f = dim f(V)
    - **核**
      - 零ベクトルだけからなるWの部分空間W = {0}の逆像f^{-1}をfの核といい、ker(f)と記述する
      - ker(f) = { v ∈ V | f(v) = 0 }
    - **単射**
      - 任意の　v、　v' ∈ Vについて、v ≠ v'ならばf(v) ≠ f(v')
      - dim V ≤ dim W
    - **全射**
      - 任意のw ∈ WについてW=f(v)となるv ∈ Vが少なくとも一つ存在する
      - dim V ≥ dim W
    - **同型写像**
      - fが全単射である写像のこと

**一言メモ**
- 核がなんだ、単射・全射がなんだと思われるが意外と重要な気がしている。Aを行列として、Ax＝bのxの解の自由度のだったり、Aには逆行列が存在するのか、次元はどうなのかを知る時に役立つ。
[AtCoder] プログラミング アルゴリズム メモ

AtCoderの問題解答に必要な プログラミング 及び アルゴリズム に関するメモ

# アルゴリズム

## 素数判定
https://algo-method.com/descriptions/93

## 探索 DFS 再帰 スタック
https://nashidos.hatenablog.com/entry/2020/01/04/234842

https://onlinejudge.u-aizu.ac.jp/courses/lesson/1/ALDS1/7/ALDS1_7_A

# プログラミング
## 入出力
https://wakabame.hatenablog.com/entry/2018/03/04/122756

## Git
https://note.nkmk.me/git-config-setting/

## VSCode
https://qiita.com/y-tsutsu/items/2ba96b16b220fb5913be
【Android】アプリ署名時の証明書情報を確認する

Androidアプリの署名時の証明書の情報（ハッシュ値など）を確認する方法を記載します。

# 環境

この記事の作業は、以下の環境で実施しました。

- macOS Ventura
- Android Studio Iguana 2023.2.1 Patch 1
- Android SDK Build-Tools 34.0.0
- OpenJDK 17 (OpenJDK Runtime Environment Corretto-17.0.10.7.1 (build 17.0.10+7-LTS))

# 署名の確認方法

## `apksigner`を使う

apksignerは、Android SDKに付属しているツールです。
v2以降のスキームを使用した署名がされている場合はこちらを使う必要があるようです。

インストールされているBuild-Toolsのバージョンによってパスは変わりますので適時置き換えてください。

```sh
$ ~/Library/Android/sdk/build-tools/34.0.0/apksigner verify --print-certs -v appfile.apk
```

## `keytool`を使う

keytoolはJavaに付属しているツールです。
v1のスキームが使用されている場合のみ使用できるようです。

```sh
$ keytool -printcert -jarfile appfile.apk
```

# 参考

- [apksigner - developer.android.com](https://developer.android.com/tools/apksigner)
- [keytoolコマンド - docs.oracle.com](https://docs.oracle.com/javase/jp/17/docs/specs/man/keytool.html)
- [apkの署名を確認しようとしてハマる - backport.net](https://backport.net/blog/2021/02/07/check_apk_signature/)
- [アプリへの署名 - source.android.com](https://source.android.com/docs/security/features/apksigning)
【Flutter】TextEditingController使い方ガイド

# はじめに
Flutterを始めてかれこれ3年目になるエンジニアです。
最近何かしらTextEditingControllerにお世話になっているので、まとめます。


## 1. TextEditingControllerとは？
`TextEditingController`は、`TextField`や`TextFormField`の状態を管理するためのコントローラーです。テキストの変更を監視し、特定のアクションを実行したり、プログラムからテキストを変更したりすることができます。

### 1.1 TextEditingControllerの生成
`TextEditingController`は、通常、ウィジェットの初期化時に生成され、ウィジェットのライフサイクルに応じて管理されます。以下は、その基本的な使い方です。

```dart
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _controller = TextEditingController();

  @override
  void dispose() {
    _controller.dispose(); // メモリリークを防ぐためにdisposeする
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("TextEditingController Example"),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: _controller,
            ),
            SizedBox(height: 16),
            ElevatedButton(
              onPressed: () {
                print(_controller.text); // 現在のテキストを取得
              },
              child: Text("Print Text"),
            ),
          ],
        ),
      ),
    );
  }
}
```

## 2. 基本的な操作
`TextEditingController`を使うと、テキストの取得、設定、およびテキストの変更リスナーの追加が可能です。

### 2.1 テキストの取得と設定
`TextEditingController`を使用して、現在のテキストを取得したり、設定したりできます。

```dart
final TextEditingController _controller = TextEditingController();

// テキストを取得
String currentText = _controller.text;

// テキストを設定
_controller.text = "新しいテキスト";
```

### 2.2 テキストの変更を監視する
テキストの変更を監視するために、`addListener`メソッドを使用して、リスナーを追加できます。

```dart
_controller.addListener(() {
  print("テキストが変更されました: ${_controller.text}");
});
```
## 3. メモリリークを防ぐための注意
`TextEditingController`は、使い終わったら`dispose`メソッドを呼び出して、メモリリークを防ぐようにしましょう。これは、ウィジェットのライフサイクル管理の一環です。

```dart
@override
void dispose() {
  _controller.dispose();
  super.dispose();
}
```

## 4. 結論
`TextEditingController`は、Flutterのテキスト入力を扱うための非常に強力なツールです。その基本的な使い方から、選択範囲やカーソル位置の操作まで、さまざまなシナリオに適用できます。メモリリークを防ぐために、ウィジェットのライフサイクルに合わせて適切に管理することが重要です。このガイドを参考に、Flutterのテキスト入力機能をより効果的に活用してください。
RLoginでサーバーへ接続する際に、秘密鍵を設定してもパスワードが求められて接続できなかった問題

# はじめに
業務でRLoginを使って開発サーバーへ接続する際に困ったのでまとめます。

# 問題
サーバーの接続情報としてホストとユーザーと秘密鍵を提供された状態でRLogin使って接続してくださいと指示。
→秘密鍵を設定してもパスワードが求められ、接続できない。

①Sever New Entry画面でホスト、ログインユーザーを入力し、「SSH認証鍵」から提供されたppkファイルを設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/a4de6b0b-1430-dcf5-cd37-8269684f8466.png)

②サーバーへ接続しようとするとパスワードが求められる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/1e23790e-80d0-df1c-0084-bcb9b9dd5120.png)



パスワードはないので（知らされてないだけかもしれないが）、時間切れで認証失敗。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/966ddad6-ac8e-8016-7461-e1fed3c792af.png)



# 解決方法

サーバー > プロトコル の「RSA2認証鍵の署名方式」をデフォルトから「SHA1」へ変更する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/7a9a93e8-78ab-4f32-f70a-7939ce971dc9.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457523/674e77a2-36c7-fb9f-9afe-0b1cc5ca7204.png)

無事接続できた。

# おわりに
認証方式をもうちょい勉強せにゃならん、と反省。
同じことで困っているどなたかの助けになると嬉しいです。
なでしこ3で「表示」の出力先を変更したい

ネットで検索しても、なかなか出てこなかったので。

# はじめに
日本語プログラミング言語である「なでしこ3」は、公式サイトに簡易エディタが存在します。

https://nadesi.com/doc3/index.php?%E3%81%AA%E3%81%A7%E3%81%97%E3%81%933%E7%B0%A1%E6%98%93%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF

この簡易エディタは大変便利で、なでしこ3初心者の方には、ぜひ使っていただきたいです。一方で、この簡易エディタは便利すぎて、「表示」という命令による出力も、下部のエリアに表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197285/f0e7c358-b93b-668a-01e4-0289327877ec.png)

これを、[HTMLに埋め込んだ際](https://nadesi.com/v3/doc/index.php?FAQ%2Fembed_html&show)にも、再現したい場合はどうすればいいのでしょうか。

# 解決方法
公式サイトで出来ているのなら、公式サイトのソースコードを見ればいいじゃないか、ということで中を覗いてみました。すると、`setFunc`を使って、中身を書き換えているようでした。そこで、以下のようなJavascriptコードを追加することで、任意の場所に「表示」結果を出力することができるようになります。

```JS:index.js
window.addEventListener("load", ()=>{
	navigator.nako3.setFunc("表示", [['と', 'を']], function (s) {
		document.getElementById("hogehoge").innerHTML+=(s.replace('&', '&amp;')
			.replace('>', '&gt;')
			.replace('<', '&lt;')
			.replace('\n', '<br>'))+"<br>";
	}, true);
	navigator.nako3.runNakoScript();
});

```

ただし、このコードを追加した際には、wnakoのランタイムを取り込む際、`https://nadesi.com/v3/cdn.php?v=3.5.2&f=release/wnako3.js`のように、`run`オプションを追加してはいけません。

# 参考文献

https://nadesi.com/v3/doc/index.php?html&show
(java silver)オーバーロード

## JavaSilverでメモしたところ備忘録として残しておこうと思います。

# オーバーロード
* 一つのクラス内に同じメソッド名で引数の型や数が違うメソッドを複数定義することができる。シグニチャ(メソッド名・引数の型・引数の数)の組み合わせで決められている
* 呼び出す側でメソッド名と引数の組み合わせで合うものがなければコンパイルエラー

:::note info
戻り値の型は違っていても呼び出せる
:::

:::note info
変数名だけが異なっている場合、戻り値だけが異なっている場合はコンパイルエラー
:::

## オーバーロードの際の型変換
* オーバーロードされた複数のメソッドと一致しない型の引数を渡した場合、そのメソッドを呼び出しているコードがコンパイラにより型変換され対応するメソッドを呼び出すように最適化される
* 配列はObjectクラスのサブクラスであるため配列をObject型で受け取るオーバーロードにより処理することは可能。Object型(参照)の集合を扱う配列とプリミティブ型(値)の集合を扱う配列は扱っている集合の種類に互換性がない

# オーバーロード
* 一つのクラス内に同じメソッド名で引数の型や数が違うメソッドを複数定義することができる。シグニチャ(メソッド名・引数の型・引数の数)の組み合わせで決められている
* 呼び出す側でメソッド名と引数の組み合わせで合うものがなければコンパイルエラー

:::note info
戻り値の型は違っていても呼び出せる
:::

:::note info
変数名だけが異なっている場合、戻り値だけが異なっている場合はコンパイルエラー
:::

## オーバーロードの際の型変換
* オーバーロードされた複数のメソッドと一致しない型の引数を渡した場合、そのメソッドを呼び出しているコードがコンパイラにより型変換され対応するメソッドを呼び出すように最適化される
* 配列はObjectクラスのサブクラスであるため配列をObject型で受け取るオーバーロードにより処理することは可能。Object型(参照)の集合を扱う配列とプリミティブ型(値)の集合を扱う配列は扱っている集合の種類に互換性がない

```java

public class Sample{
    public void test (Object val){
        System. out. println ("A");
    }
    public void test(long[] val){
        System.out.printin("B");
    }
    public void test (Object val){
        System. out. printin("C");
    }
}
public class Main{
    public static void main (String[] args) {
        new Sample(). test(new int[3])://"C"がしゅつりょくされる
    }
}

```
M2 チップの Mac で Linux を試したーい

## はじめに

Mac で Linux 環境を構築した際の備忘録になります。

様々な環境構築方法があると思いますが、今回は以下２パターンについて触れます。

- UTM を使う
- AWSのEC2でLinuxサーバを立ち上げる

もう一つ普及している環境構築方法として Virtual Box を利用するパターンがあると思いますが、Apple シリコン搭載の Mac コンピュータはインストールに一工夫必要そうだったので、今回は UTM を利用しました。

Virtual Box をどうしても使いたい方は、以下の記事がわかりやすかったので参考にしてみてください。
[Virtual BoxをMacBook Air(M1, 2020)にインストールしようとしたら、CPUアーキテクチャの違いで詰まったので学び直した](https://qiita.com/k21071/items/55f81bdfc22a02b425d3)

#### 対象読者

- MacでLinux環境を構築したい方

#### 動作環境

- macOS：14.4
- チップ：Apple M2
- メモリ：8 GB



## UTM を使う

> UTM is a full featured system emulator and virtual machine host for iOS and macOS. It is based off of QEMU. In short, it allows you to run Windows, Linux, and more on your Mac, iPhone, and iPad.

上記は [UTM Document](https://docs.getutm.app) から引用しました。
翻訳すると、UTMを使えば Mac、iPhone、iPad から Windows、Linux 環境を動かせるようです。

環境構築については、以下を参考に進めました。
[【Linux】UTMを用いてM1 MacBookにUbuntuの仮想化環境を構築する](https://envader.plus/article/66)

#### ざっくりとした手順

1. UTM をインストールする
    - [UTM 公式](https://docs.getutm.app/installation/macos/)から UTM.dmg をダウンロード
    - ダウンロードしたファイルを起動してアプリをインストールする
1. UTMを起動して、仮想マシンを作成する
    - オペレーティングシステムはLinuxを選択する
    - 仮想化エンジンの起動イメージは、[Ubuntuダウンロードサイト](https://ubuntu.com/download/server/arm) からインストールした ISO イメージを設定する
    - 仮想マシンのスペックは起動する PC に合わせて設定する
1. 仮想マシン上で Ubuntu をインストールする
    - マシンが起動したら「Try or Install Ubuntu Server」を選択
    - 表示された質問に回答しながら、Ubuntu の設定を進める
4. インストールが完了したら Ubuntu を起動する
    - Ubuntu をインストールする際に設定したユーザ名とパスワードを入力する
    - 「Welcome to Ubuntu」と表示されれば OK

これにより、ローカルで Linux 環境が動かせるようになりました。



## AWSのEC2でLinuxサーバを立ち上げる

ローカルにではなく、クラウド上にLinux環境を構築する方法もあります。

AWSアカウントの無料枠は1年なので、それを超えると利用料金が発生してしまうのは注意です。

環境構築手順については、 [チュートリアル: Amazon EC2 Linux インスタンスの開始方法](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/EC2_GetStarted.html) を参考にしています。

#### ざっくりとした手順

1. AWS コンソールに [サインイン](https://console.aws.amazon.com/console/home?sc_icampaign=adp_jp_header_v3_default_202205&sc_ichannel=ha&sc_icontent=awssm_10926&sc_iplace=cta&trk=ha_adp_jp_header_v3_default_202205) する
    - アカウントを持っていない方は [新しい AWS アカウントの作成](https://portal.aws.amazon.com/billing/signup#/start/email) から作成
1. EC2を立ち上げる
    - 検索バーで「EC2」を検索してクリック
    - 「インスタンスを起動」ボタンを押下してインスタンスを作成
        - 各設定は無料枠を選択する
        - 生成した秘密鍵はローカルの任意の場所に保管する
    - EC2インスタンス作成後、インスタンスの状態が「実行中」になっている
1. ターミナルから作成したEC2インスタンス（Linuxサーバ）にアクセスする
    - `chmod 400 [秘密キーまでのパス]` で秘密鍵ファイルの権限変更（ローカル上で実行）
    - `ssh -i [秘密キーまでのパス] [ec2-user@Linuxサーバのipアドレス]` でLinuxサーバにログイン（ローカル上で実行）
    - `sudo su -` で管理者権限でログイン（EC2インスタンス上で実行）
    - `passwd` でパスワード変更（EC2インスタンス上で実行）
    - `scp -i [秘密キーまでのパス] [送信するファイル] [ec2-user@Linuxサーバのipアドレス]:` でローカルからEC2インスタンスにファイルを送信する（ローカル上で実行）

これにより、ターミナル上で Linux 環境が動かせるようになりました。



## おわりに

Linux、これからいっぱい勉強するゾ :)
BAMファイルのMDタグについて

## BAMファイルのMDタグについて

### 概要

BAMファイルには、リファレンス配列に関連する情報を含む「MD」というタグが存在することがあります。MDタグについて調べた結果、英語のブログ「[MD Tags in BAM Files - vince buffalo](https://vincebuffalo.com/notes/2014/01/17/md-tags-in-bam-files.html)」で詳しい解説がされていました。

Vince Buffalo さん敬意を払いつつこの記事の内容を要約してQiita記事にまとめます。

### MDタグの役割

MDタグは、リファレンスを参照しなくてもSNPやインデルを特定できるように設計されています。特定のアラインメントのリファレンス情報を保持する。

### SNPの記録

例えば「10A3T0T10」というMDタグがあった場合、以下の3つのSNPが含まれる：

1. 11番目のリファレンス塩基はAです。
2. 15番目のリファレンス塩基はTです。
3. 16番目のリファレンス塩基もTです。（0は隣接した塩基をあらわします）

### 欠損

MDタグは欠損情報を保持します。例：「85^A16」では、85個のマッチ後にリファレンスがAである位置に欠損があり、その後16個のマッチが続きます。

### 挿入の扱い

挿入はMDタグに記録されません。例えばリード長が101で、「78M1I22M」というCIGAR文字列がある場合、CIGARは1つの塩基の挿入を表現していますがMDタグは単に「100」です。これはリファレンスの情報は失われていないからです。

### 複雑なケース

挿入がある場合、例えば「リードの長さ：101、CIGAR: 9M1I91M、MD: 48T42G8」のような場合、MDタグは挿入を無視してマッチ部分のみを表し、リード内で挿入された塩基はMDタグには反映されません。

49番目の塩基（リファレンスはT）は実際にはリードの50番目の塩基でです。ミスマッチしたTの上流に1塩基の挿入があります。もう1つのミスマッチ（リファレンスはG）についても同様で、MDタグによると48 + 1 + 42 + 1 = 92塩基目ですが、実際には93塩基目です。

### 考え方とツール

MDタグの解析のアプローチとしては、MDタグとCIGAR文字列を利用してリファレンス文字列を再構築し、それをもとにリードとの比較を行います。
また、`samtools calmd` コマンドを `-e` オプション付きで使用すると、塩基が `=` にマスキングされ検証が容易になります。

※こんな感じの表示が得られる

```
=A=======G==A======================C============C=====================
```

IGVによるリードの観察も有用です。

この記事は以上です。

なお、Vince Buffaloさんは、名著 Bioinformatics Data Skills の作者です。買おう。

https://www.oreilly.co.jp/books/9784873118635/
【ポエム】Win10/11でPowerShellスクリプト実行で少しハマった件、からのサーバーVDIポエム

# 経緯
普段Windows ServerをクライアントOSとして使っているので忘れていましたが（https://qiita.com/minoden_osaka/items/659847603b0bb36d5604 ）、
クライアントOSだと実行ポリシーを変更しないとPS1スクリプトを実行できないと言われ、少し沼にはまったので、備忘録としてメモ致します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/d9643c7b-5297-d47f-1364-e1066b664636.png)

# コマンド
```ChangeExecutionPolicy.ps1
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
```

# 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/5ae10c7c-1d18-47c1-c3a4-3c25b320c186.png)

# 問題が発生

しかし、作成したPS1ファイルをそのまま実行すると管理者権限がないため、アクセス権エラーとなってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/4b789d03-77a9-b810-e262-c7cc658b37a6.png)

ショートカットを作成して管理者権限をつけようとしてもグレーアウトしています。（原因不明。どなたか分かりましたら幸いです）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/e6833a33-b040-22d7-ca94-62afac6bd6fd.png)

# 対応策
仕方がないので、スタートメニューから素のPowerShellを管理者で実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/37442254-fb8f-3be5-ef63-a5e0875ba8fa.png)

実行ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790864/23cf6bf2-8dc5-c052-072c-38a529bae127.png)

# 水野晴〇氏のコメント
「いや～、クライアントOSって、ほんっとうに面倒ですね！！！」

# まとめ
・クライアントOSはPS1スクリプトの実行の制限が多い（RemoteSignedと管理者権限）
・サーバーOSの場合は、管理者権限があればこうした制約はないのでとても楽
・動作も安定していますし、余計なアプリや広告もないので（個人的には）メリットしかありません。

# ポエム
・いわゆるサーバーVDI（仮想デスクトップとしてWindows Serverを使う方法）は知る人ぞ知るコスト削減方法ですが、こうした管理上のちょっとしたメリットも多いのでおすすめです。https://www.oki.com/jp/case/2016/hyoshin.html
・管理用2ユーザーまでであればRDSライセンスなしで同時ログオンして使えます。3名以上で、普段の業務用で使う場合はRDSが必要になると思います。
・50名以下の中小企業であれば、VultrといったクラウドサービスでServer VDIを構築するのも面白いかもしれません。個人的にはAmazonやAzureより導入の敷居が低いと感じます。
・クライアントOSの管理コストを考えると、もう現場系の職場はiPad + Mirosoft365アプリメインで、Excelなどのデスクトップアプリを使うときだけServer VDIでいいのでは・・・？🤔
ABC350備忘録【C~D】

## はじめに
D問題のUnion-Findのコードは競プロの鉄則のgithubをもとに自作関数を含めて作成したと思うので、参考書籍として[競技プログラミングの鉄則](https://amzn.asia/d/0YYBWRp)を置いておきます。

## C - Sort
### 問題
https://atcoder.jp/contests/abc350/tasks/abc350_c
### 考えたこと
(index, 数値)で状態を格納しておき、indexと数値が異なるならば同じようになるよう交換するという操作を繰り返すということを行いました。操作の概念図は図1となります。

<img width=10%><img width=80% src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631672/007ff75b-8a81-28d9-ae24-7bf68c5d9a2e.png">

1ループでは終わらない時があるので、変更毎の数列は保存しておき、下記のtargetと等しくなるまでループ操作を続行させます。
```
target = [i + 1  for i in range(n)]
```
### ACコード
```c.py

n = int(input())
A = list(map(int, input().split()))

ans = []
target = [i + 1 for i in range(n)]
while True:
    for i in range(n):
        if i + 1 != A[i]:
            ans.append([i + 1, A[i]])
            Ai = A[i]
            A[i] = A[Ai - 1]
            A[Ai - 1] = Ai
    if A == target:
        break

print(len(ans))
for a in ans:
    a.sort()
    print(*a)
```

## D - New Friends
### 問題
https://atcoder.jp/contests/abc350/tasks/abc350_d
### 補足
少しグラフの用語を使っているので、基礎知識を知りたい方は[こちら](https://www.momoyama-usagi.com/entry/math-risan09#i-3)
### 考えたこと
今回の例では、各連結成分に対して最終的なグラフは完全グラフとなります。よって、各連結成分において、入力時のグラフと完全グラフで作成された補グラフの辺の数が操作の回数となります。
試しに以下の入力例を考えてみましょう。
入力例：
```
5 4
1 2
2 3
3 4
4 5
```
入力例から補グラフまでのは図2のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3631672/731ad2db-8ded-ab04-ef51-28b45460de62.png)

図から最終的なグラフは完全グラフとなっていることがわかります。
ここでも、一つの連結成分に注目してみます。点の数を$x_i$としたとき、完全グラフの辺の数は$x_i + x_i角形の対角線$です。さらに、$x_i$角形の対角線は$\frac{x_i(x_i -3)}{2}$と表されることと、入力時グラフの辺の数より、
```math
補グラフの辺の数 = x_i +  \frac{x_i(x_i -3)}{2} - 入力時グラフの辺の数
```
となります。これを各連結成分ごとに和をとれば答えとなります。
グラフの作成や辺の本数の数え上げについては、Union-Findを用いて実装しました。

### ACコード
```d.py
class UnionFind:
    def __init__(self, N: int) -> None:
        self.N = N
        self.par = [-1 for _ in range(N)]
        self.siz = [1 for _ in range(N)]

    def root(self, x: int) -> int:
        while True:
            if self.par[x] == -1:
                break
            x = self.par[x]
        return x

    def unite(self, u: int, v: int) -> None:
        RootU = self.root(u)
        RootV = self.root(v)
        if RootU != RootV:
            if self.siz[RootU] < self.siz[RootV]:
                self.par[RootU] = RootV
                self.siz[RootV] += self.siz[RootU]
            else:
                self.par[RootV] = RootU
                self.siz[RootU] += self.siz[RootV]

    def same(self, u: int, v: int) -> bool:
        # 同じ根かどうか
        return self.root(u) == self.root(v)

    def root_list(self) -> set:
        # 親のsetを取得
        return {self.root(i) for i in range(self.N)}

    def count_root_v(self) -> list:
        # 各根に対する頂点の数を求める
        count_v = [0] * self.N
        for i in range(self.N):
            count_v[self.root(i)] += 1
        return count_v


n, m = map(int, input().split())
if m == 0 or n <= 2:
    exit(print(0))

UF = UnionFind(n)
ans = 0
for _ in range(m):
    u, v = map(lambda x: int(x) - 1, input().split())
    UF.unite(u, v)
    ans -= 1  # あらかじめ引いておく

for i in UF.count_root_v():
    ans += i
    ans += i * (i - 3) // 2

print(ans)
```
ラズパイでＲＳ２３２Ｃ通信

ラズパイを使って、古いwindows用のUSB-シリアル変換装置を使ったら、案外簡単だったのでメモしておく。

用意する主なモノ
・ラズパイ
・USB-シリアル変換装置
変換装置のチップは案外幅広く対応しているのかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/d4ae4b7c-ab2a-6bf2-50a9-f72d7e83ec62.png)

windowsだと、ＯＳのアップデートで古い変換装置が使えなくなったりする。
Linux系だと**ドライバ不要**で利用できる。

参考

https://qiita.com/nannja/items/9d30a810b073a97a7ae5


## ラズパイとUSB-シリアル変換装置を接続
たいていドライバ不要なので、接続するだけ。
以下のコマンドでどこに接続されたか探してみる。
```
ls /dev | grep USB
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/3e5edda4-cae2-89d6-5f34-03f0b9b5c544.png)
複数台変換装置があると、接続順でttyUSB0が先で、次にttyUSB1が出来るようだ。

## 実装環境
python 3.11 と　pyserial
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/42c8006f-96c8-5b49-e4a3-835ef7e38045.png)

pyserialが入っていなければ
```
pip install pyserial
```
名前はpyserialなんだけど、importするときはserialなので注意。

### プログラム
稀な凡ミスですが、同一フォルダに serial.py などの名前でサンプルプログラムを書くと、importがpyserialではなくサンプルプログラムがインポートされてserial.Serialが無いって言われます。


```test.py
import serial # pyserialを読むけど、名前はserial
dev = "/dev/ttyUSB0"
rate = 9600
ser = serial.Serial(dev, rate, timeout=2)

def write_and_read(send):
    string = send
    string = string + "\r\n"  # LR+LFの意味
    string = string.encode('ascii') # 括弧内は空白でも良いかも
    ser.write(string)
    res = ser.readline()  
    res = res.decode()
    print (res)
    # return res
# 以下は今回利用したテスターのデータ要求コマンド
write_and_read(":FETCCNT?")
write_and_read(":FETCCNT2?")
```

デフォルトの設定は以下のとおりで、レート９６００、８ビット、パリティなし、ストップビット１，タイムアウトなし、制御無しなどとなっている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520250/3175dae6-9d2e-4310-8524-84cb4267c7d9.png)
https://pyserial.readthedocs.io/en/latest/pyserial_api.html

ドライバが無いと諦めていたUSB-シリアル変換装置や、測定機器が使えました。
950. Reveal Cards In Increasing Order の解き方メモ

https://leetcode.com/problems/reveal-cards-in-increasing-order/description/

次の手順を繰り返す。その結果、公開されたカードのが昇順にソートされているような山札を求めなさい。

1. 山札の一番上のカードを取り除き、そのカードを公開する
2. 山札にカードが残っているとき、山札の一番上のカードを山札の一番下に置く
3. 山札にカードが残っている場合、1.に戻る。そうでない場合、処理を停止する

問題を要約すると、おおよそ上記の通りになります。

---

たとえばABCDEFGの7枚の山札に対し、指定した手順を実施します。

|#  |山札   |公開されたカード|
|:-:|:------|:-------|
|1  |ABCDEFG|        |
|2  |CDEFGB |A       |
|3  |EFGBD  |AC      |
|4  |GBDF   |ACE     |
|5  |DFB    |ACEG    |
|6  |BF     |ACEGD   |
|7  |F      |ACEGDB  |
|8  |       |ACEGDBF |

最終結果ACEGDBFが昇順にソートされていればよいわけです。Example1を例に考えてみると、ACEGDBFと[2,3,5,7,11,13,17]がイコールになります。わかりやすくマッピングしたものが以下です。

|山札|Example1|
|:-:|:-:|
|A  |2  |
|B  |13 |
|C  |3  |
|D  |11 |
|E  |5  |
|F  |17 |
|G  |7  |

求めるのは山札ABCDEFGなので、Example1の答えは[2,13,3,11,5,17,7]になります。

---

上記の手順を要約するとおおよそ以下の通りになります

1. deckと同じ枚数の山札を作成し、指定された手順をシミュレーション
2. シミュレーション結果とソート済みのdeckをマッピングし、山札を再現する

これをそのまま実装すればよいです。

```rust
use std::collections::{HashMap, VecDeque};

impl Solution {
    pub fn deck_revealed_increasing(deck: Vec<i32>) -> Vec<i32>  {
        // deckと同じ枚数の山札を作成し、指定された手順をシミュレーション
        let simu_start = (0..deck.len()).collect::<Vec<_>>();
        let mut simu_deck = VecDeque::from_iter(&simu_start);
        let mut simu_cards = Vec::new();
        loop {
            simu_cards.push(simu_deck.pop_front().unwrap());
            if let Some(card) = simu_deck.pop_front() {
                simu_deck.push_back(card);
            } else {
                break;
            }
        }

        // シミュレーション結果とソート済みのdeckをマッピングし、山札を再現する
        let mut sorted_deck = deck;
        sorted_deck.sort();
        let mapper = simu_cards.iter().zip(sorted_deck).collect::<HashMap<_, _>>();
        simu_start.iter().map(|simu_card| mapper[&simu_card]).collect()
    }
}
```
【個人開発】ローマ字タイピング習得アプリ「しりとり画像ジェネレーター」の紹介（Rails, JavaScript）

# はじめに
はじめまして、Qiita初投稿です。
平（[@tairanobuhiko](https://twitter.com/tairanobuhiko)）と申します。
業界未経験からWeb業界への転職を目指し、効率的に学習することと高め合えるコミュニティを求めてプログラミングスクール（テックキャンプ）で学習を行なっています。

3月初頭から個人開発のオリジナルアプリを制作しましたので紹介したいと思います。

# アプリの概要
### アプリケーション名
**【しりとり画像ジェネレーター】**

URL

https://word-chain-image-generator.onrender.com/

GitHub

https://github.com/no215tyler/word_chain_image_generator

### アプリの特徴
- 「**<font color="greenyellow">ローマ字の学習も、タイピング練習もつまらない！</font>**」という課題をもった小学校低学年層のユーザーが楽しみながら学習できる環境を提供します


# 企画背景
- 私の長女がローマ字タイピングを苦手としており、習得のサポートできるようなアプリを開発したかったこと
- PCを扱うためには基本的なキーボードタイピングが必要で、子供に対して早いうちからキーボードタイピングを覚えさせることが大切だと考える親御さんが多くいること
- 2020年より小学生からラップトップ端末の貸与が一般化され幼少期からITリテラシーが求められる時代になったこと

これらの背景から、子供たちがローマ字入力タイピングを習得しやすく、楽しく学べる環境でITリテラシー向上のきっかけにしてほしいという狙いで企画、開発に至りました。

# 基本的な使い方
- しりとりの単語をタイピング入力します
- 単語を5つ以上つなげ、画像生成ボタンを押すとしりとりの要素を含む画像が生成されます
:::note info
どんな画像ができるかは毎回異なり、楽しみながらタイピング練習をする動機に繋がります。
:::

# 機能画面紹介
ゲストユーザーのまま利用可能です。
- ゲストユーザー
    - 自身で生成した過去作品の参照不可
    - 画像の削除不可
- 登録ユーザー
    - ユーザーに紐づく過去作品の参照が可能
    - ユーザーに紐づく画像の削除が可能



|トップ画面（画像生成例）|ギャラリーページ（作例ページ）|
|:-:|:-:|
|![8405ae3b83d61bff4643aea191b6018c.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584402/50b20da8-d354-891c-8d19-12ef1b24ae39.gif)|[![Image from Gyazo](https://i.gyazo.com/083ec0a8e7c906b62c1a601e96ecd49a.gif)](https://gyazo.com/083ec0a8e7c906b62c1a601e96ecd49a)|

|ユーザー詳細ページ|画像詳細ページ|
|:-:|:-:|
|[![Image from Gyazo](https://i.gyazo.com/d44d54fc60e5c1281f789e2fd0fcec7d.jpg)](https://gyazo.com/d44d54fc60e5c1281f789e2fd0fcec7d)|[![Image from Gyazo](https://i.gyazo.com/348131890aefc4a04011aba11dc223ca.gif)](https://gyazo.com/348131890aefc4a04011aba11dc223ca)|

|サインアップページ|ログインページ|
|:-:|:-:|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584402/94621721-d694-5ddc-9533-332a416347c4.png)|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584402/57826fb3-465b-fab0-7b2e-2cc567b3888d.png)|

# 技術スタック
|カテゴリ|技術内容|
|:-|:-|
|フロントエンド|HTML(ERB)/CSS<br>JavaScript<br>Tailwind CSS|
|バックエンド|Rails 7.0.8.1<br>PostgreSQL 14.10<br>|
|インフラ|Render|
|ファイルストレージ|AWS S3|
|API|StableDiffusion API（Hugging Face）<br>OpenAI API（DALL-E3）<br>GAS翻訳API（自作）<br>Twitter API<br>Tiny_URL（短縮URL生成）|
|バージョン管理|Git/GitHub|
|CI/CD|CI:GitHub Actions<br>CD:Render|
|ワイヤーフレーム<br>画面遷移図|Figma|
|ER図|Draw.io|
|アナリティクス|Google Analytics|

# こだわったポイント
### UI/UX
- レスポンシブ対応するために仮想キーボードを導入しました（娘も外出先やお風呂で遊んでます）
- ローマ字をすぐに確認できるようモーダル形式でローマ字表を実装しました
- 画像生成待ちの間にインジケーターの表示と待機音（SE）を鳴動させる仕様にし、待ち時間に対するUX向上に努めました

### バックエンドロジック
- 画像生成のリクエスト制限（429エラー）やサーバーエラー（500, 503）の対策として指数バックオフ方式（2秒〜32秒、最大5回）でリトライを行うロジックにしました
また、429エラーの場合は別の生成モデルのAPIへフォールバックする仕様とし、画像生成の安定性向上に努めました
- テストコード実装においてテストのたびに画像生成APIを叩く処理をエミュレートし外部APIによる依存を制御することでテストの安定性を向上させました

# さいごに
最初は`HTML/CSS`とはなんぞ？というレベル感でしたが、<font color="greenyellow">**誰かの課題解決にアプローチできるオリジナルアプリケーションを開発する！**</font>という目的意識を持って学習した甲斐もありここまで実装することができました。
使っていただいたり、フィードバックくださった全てのみなさまに感謝です！
小学校低学年のお子さまがいらっしゃる方はぜひ使ってみて感想くださるとたぶん泣いて喜びます！
今後も技術研鑽をつづけていきます！

https://twitter.com/tairanobuhiko
RailsのRestClientで日本語のクエリが送れない

# はじめに

RailsでAPIを叩く時になぜか日本語のクエリだけがうまくいかなかったのでまとめます

# 問題

検索機能を作成しており、キーワードを使って他のAPIを叩く実装をしていました

```rb
  def get_contract_by_keyword(keyword)
    return nil if company_name.blank?

    url = UserApi.protocol + "#{UserApi.host}:#{UserApi.port}/v1/contract?keyword=#{keyword}"
    p url

    begin
      res = RestClient.get(url)
      data = JSON.parse(res.body)
```

なぜか英語での検索はいけるのですが、日本語でAPIにリクエストがうまくいっていませんでした

# 解決方法

`RestClient`は以下のようにパラメーターを付与するようでした

```rb
  def get_contract_by_keyword(keyword)
    return nil if keyword.blank?

    url = UserApi.protocol + "#{UserApi.host}:#{UserApi.port}/v1/contract"
    p url

    begin
      res = RestClient.get(url, params: {keyword: keyword})
      data = JSON.parse(res.body)
```

おそらくurlには日本語が入ることがないのでエンコードされているようです

# おわりに

RestClientの仕様について調べたので早くかいけつできてよかったです

# 参考

https://nekorails.hatenablog.com/entry/2018/10/10/095842#GET-1
Rails:dokcer-compose upでバックのコンテナが立ち上がらなくなったMysql2::Error: Failed to open the referenced table 'users'の解決方法

RailsAPIモードでSAP化したdokcer-compose upで以下のようなエラーが出ました。
```
backend-1   | Mysql2::Error: Failed to open the referenced table 'users'
```
usersのdb:migrateがうまくいかなかったので、srart.shの
```
bundle exec rails db:create --trace
bundle exec rails db:migrate --trace
```
の記述をコメントアウトして、そもそもdb接続しなくてもバックのコンテナが立ち上がるように設定しました　。
バックのコンテナが無事起動したところで
```
docker-compose exec バックエンドの名前 /bin/bash

```
でバックエンドに入り、
```
rails db:migrate:status
```
でステータスを確認
```
rails db:rollback
```
でロールバックを行い
```
rails db:migrate
```
で詳しい詳細を吐き出しました。
その後はエラーに則って、db/migrateディレクトリのファイルのエラー箇所のコメントアウトをして再度migrateを実行、コメントアウトしたコードを再度元に戻してdb:migrateを実行し無事に解決しました。
後処理としてstart.shのコメントアウトを外しました。
```
# bundle exec rails db:create --trace
# bundle exec rails db:migrate --trace
```
あとは再ビルドしてupしたところで無事バックエンドの接続がうまくいきました。
いいね機能非同期化　リロードしないと反映されない

いいねの非同期化をしようとしたところ、
リロードしないといいねが反映されなくなってしまいました…
お手本通りしているはずなのにどうして！？
とコードを見返していると、気がつきました

```favorites_controller.rb
class FavoritesController < ApplicationController

  def create
    @book = Book.find(params[:book_id])
    favorite = current_user.favorites.new(book_id: @book.id)
    favorite.save
  end

  def destroy
    @book = Book.find(params[:book_id])
    favorite = current_user.favorites.find_by(book_id: @book.id)
    favorite.destroy
  end

end
```

そうなんです。favoriteがインスタンス変数でないのです。
最初いいね機能を実装した時はビューに渡す必要がなかったのですが、
今回、更新部分のjs.erbファイルに更新するためインスタンス変数に変更する必要がありました。

```favorites_controller.rb
class FavoritesController < ApplicationController

  def create
    @book = Book.find(params[:book_id])
    @favorite = current_user.favorites.new(book_id: @book.id)
    @favorite.save
  end

  def destroy
    @book = Book.find(params[:book_id])
    @favorite = current_user.favorites.find_by(book_id: @book.id)
    @favorite.destroy
  end

end
```

というわけで、全てのfavoriteを@favoriteに変えると無事非同期化できました！
【Docker】ポート番号がすでにあると言われた場合

## 問題
すでにそのポート番号はあるよと言われた場合
これ→port is already allocated
```
docker-compose up --build -d
↓
↓
エラー文
Error response from daemon: driver failed programming external connectivity on endpoint umarche-db (9f00569d16d49aa612387d7f1c675af9c6cc2bc7453db9dbb76caeae4ddfa6ae): Bind for 0.0.0.0:3306 failed: port is already allocated
```

## 解決方法
```
  db:
    container_name: umarche-db
    # Mac M1チップユーザー
    platform: linux/x86_64
    image: mysql:5.7
    # コンテナの環境変数を指定
    environment:
      MYSQL_ROOT_PASSWORD: root
      TZ: 'Asia/Tokyo'
    volumes:
      - ./db:/var/lib/mysql
    restart: always
    ↓⭐️ここ
    ports:
      // - 3306:3306
      - 13306:3306
```
回避策としてはhost側portを別のportにmappingする

この13306のところをprojectごとに変えれば Bind for 0.0.0.0:3306 failed: port is already allocated. は発生しなくなる

## 参考
https://qiita.com/skobaken/items/b89049064a2a45902fd5
基本のダイナミックルーティング

## 前提
Packet Tracer で学習しています。

## 構成
![スクリーンショット 2024-03-20 16.54.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2614417/5292d3d9-d79e-1e0d-de3a-74aa0ccb9931.png)

## やること
- R1からR3へのダイナミックルーティングを追加する

# 使用するコマンド
##### OSPF起動
**(config)#router ospf <プロセスID>**
プロセスIDは任意の数字(1~65,535を割り当てる。ネイバーと一致させる必要はない。

##### OSPFを有効にするインターフェースを指定する
**(config-router)#network <IPアドレス> <ワイルドカードマスク> area <エリアID>**
IPアドレスとワイルドカードマスクによって有効にするインターフェースを指定する。
エリアIDは有効にするインターフェースが所属するエリア番号を指定する。

#### 注意
network 0.0.0.0 255.255.255.255 area 0 にすると
どのIPアドレスの値でも含まれるため全てのインターフェースでOSPFが有効になる。
そのため予定外のインターフェースでもOSPFがゆうこいうになってしまう。

# 変更前 R1 ルーティングテーブル
R1自身のFastEthernet0/0と0/1しか存在しない。
```cisco_ios
R1#show ip route
(省略)
C    192.168.1.0/24 is directly connected, FastEthernet0/0
C    192.168.4.0/24 is directly connected, FastEthernet0/1
```
# R1 OSPFを起動する
```cisco_ios
R1#configure terminal 
Enter configuration commands, one per line.  End with CNTL/Z.
R1(config)#router ospf 1
R1(config-router)#network 192.168.1.0 0.0.0.255 area 0
R1(config-router)#network 192.168.4.0 0.0.0.255 area 0
R1(config-router)#exit
R1(config)#exit
R1#
```

## 変更後 R1 ルーティングテーブル
この時点では変化は見られない
理由は、隣接しているルータ(ネイバー)のOSPFが起動しておらず、情報のやり取りが行われていないため
```cisco_ios
R1#show ip route
(省略)
C    192.168.1.0/24 is directly connected, FastEthernet0/0
C    192.168.4.0/24 is directly connected, FastEthernet0/1
```


## 変更後 R1 running-config
**running-configにrouter ospf が追加されている**
```cisco_ios
R1#show running-config 
(省略)
router ospf 1
 log-adjacency-changes
 network 192.168.1.0 0.0.0.255 area 0
 network 192.168.4.0 0.0.0.255 area 0
```

## ネイバーであるR2のOSPFを有効化する
```cisco_ios
R2(config)#router ospf 1
R2(config-router)#network 192.168.1.0 0.0.0.255 area 0
R2(config-router)#network 192.168.2.0 0.0.0.255 area 0
```
## 変更後 R2 ルーティングテーブル
```cisco_ios
R2#show ip route 
(省略)
C    192.168.1.0/24 is directly connected, FastEthernet0/1
C    192.168.2.0/24 is directly connected, FastEthernet0/0
O    192.168.4.0/24 [110/2] via 192.168.1.1, 00:00:33, FastEthernet0/1
```
## 変更後 R2 running-config
```cisco_ios
R1#show running-config 
(省略)
router ospf 1
 log-adjacency-changes
 network 192.168.1.0 0.0.0.255 area 0
 network 192.168.2.0 0.0.0.255 area 0
```

## R2 OSPF有効後のR1 ルーティングテーブル
```cisco_ios
R1#show ip route 

C    192.168.1.0/24 is directly connected, FastEthernet0/0
O    192.168.2.0/24 [110/2] via 192.168.1.2, 00:03:53, FastEthernet0/0
C    192.168.4.0/24 is directly connected, FastEthernet0/1
```
R1から見て、192.168.2.0/24はR2の先にあるセグメントが登録された。
これでR1→R3(192.168.2.2)へ疎通が可能と思ったが、できなかった。

双方向でルーティングを設定しないと通信はできない！
同じ要領でR3、R4へルーティングを設定してようやく疎通できた。
AWS Fargate

## はじめに

この記事はAWS SAA試験勉強のための、AWS Fargateに関する知識のまとめです。

## AWS Fargateとは
Amazon ECSで動作する(と、よく書いてあるが、2019年12月よりEKSでも動作する)、コンテナ向けサーバーレスコンピューティングエンジン。

<font color="red">**Fargate起動タイプを選択して**</font>Amazon ECSクラスターを構成することができる。

## EC2との使い分け

- EC2は、特定の要件に応じて完全なカスタマイズが必要な場合や、特定のインフラストラクチャの管理が必要な場合に適している
- Fargateは、アプリケーションのスケーラビリティや管理の負担を軽減したい場合や、サーバーレスのアプローチを採用したい場合に適している

## 利用料金

タスクが実行されていない時は料金が発生しません。
プログラミングの原理原則

# はじめに
開発者としてプログラミングしていく中で、本記事にて紹介する原理原則を押さえておくことは非常に重要なことと感じたため、備忘録も兼ねて記載する。

## 1.DRY原則
### Don't Repeat Yourself
```
同じ内容のコードを複数箇所に記載しない。
抽象化や共通化を用いて極力除去すべきであるという原則。
```
## 2.KISS原則
### Keep It Simple, Stupid
```
シンプルなコードを書く。
自身だけでなく、誰が見てもすぐ理解できる状態をキープすべきであるという原則。
```
## 3.YAGNI原則
### You Aren't Going to Need It.
```
今必要なコードを書く。
あとで必要なコードは使われないことが大半であり、工数が無駄になる。
```
## 4.車輪の再発明
### 既にあるものを作る皮肉
```
共通化されている処理やライブラリにあるようなコードを自身で作ることはやめようという原則。
「車輪」を知らないは「知識不足」なので知ることから始めよう。
```
## 5.プログラマの３大美徳
### プログラマは「怠惰」「短気」「傲慢」であれ
```
「怠惰」
面倒・繰り返しの作業は自分でやらず、怠惰になれるようにプログラムで自動化すること。
そうすることで、全体の時間・労力が削減され、正確性も保証されます。
```
```
「短気」
コードが意図通りや効率的に働いていなかったら、短期になり、すぐに書き直すこと。
そうすることで、コードが常に正しく保たれます。
```
```
「傲慢」
誰に見せても恥ずかしくないコードを書き、責任を持つことで、仕事の成果について傲慢になること。
そうすることで、読みやすくシンプルなコードを保つことができます。
```
## 6. SOLID原則
### S (Single Responsibility)　単一責任の原則
```text:クラスは、単一の責任を持つべきだ。
この原則は、変更の結果としてバグが発生しても、他の無関係な動作に影響を与えないように、動作を分離することを目的としています。
```
### O (Open-Closed)　オープン・クローズドの原則
```text:クラスは、拡張にはオープンで、変更にはクローズドであるべきだ。
この原則は、クラスの既存の動作を変更することなく、クラスの動作を拡張することを目的としています。
これは、そのクラスが使用されている場所でバグが発生するのを避けるためです。
```
### L (Liskov Substitution)　リスコフの置換原則
```text:SがTのサブタイプである場合、プログラム内のT型のオブジェクトをS型のオブジェクトに置き換えても、そのプログラムの特性は何も変わらない。
この原則は、親クラスやその子クラスがエラーなしで同じ方法で使用できるように、一貫性を保つことを目的としています。
```
### I (Interface Segregation)　インターフェイス分離の原則
```text:クライアントが使用しないメソッドへの依存を、強制すべきではない。
この原則は、動作のセットをより小さく分割して、クラスが必要なもののみを実行することを目的としています。
```
### D (Dependency Inversion)　依存性逆転の原則
```text:上位モジュールは、下位モジュールに依存してはならない。どちらも抽象化に依存すべきだ。
この原則は、インターフェイスを導入することにより、上位レベルのクラスが下位レベルのクラスに依存するのを減らすことを目的としています。
```
## 7.OAOO原則
### Once And Only Once
```
同じコードを書かない。
DRY原則と同じ原則。
```
Azure Data Factory の Azure Databricks Delta Lake connector にて Unity Catalog を利用する方法

## 概要
Azure Data Factory（ADF）の Azure Databricks Delta Lake connector にて Unity Catalog を利用する方法を紹介します。ADF の UI ではカタログを選択することができませんが、クラスターの初期カタログの設定を変更することで UC を利用できるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/cc46f3ec-072e-6bec-1078-5517a25eea9b.png)

Azure Databricks Delta Lake connector では既存の汎用クラスターを利用することとなるため、Databricks のクラスターにて次のような設定を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/55d0a392-8be3-f819-af5c-fa22534f7c67.png)

Databricks Unity Catalog の２つのテーブルによりコピーアクティビティを実行したところ正常終了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/46512448-af34-715d-55e2-619c22c7cf5b.png)

本記事では、検証手順を紹介します。

## 検証手順

### 1. 事前準備

下記のリソースを作成して、それぞれの認証設定を実施する。

- Azure Data Factory
- Databricks
- Azure Storage （ADF 実行時のステージング用）

### 2. Databricks にてカタログ等を作成

nation_src テーブルにはデータがあり、 nation テーブルにはデータがない状態となっています。

```python
%sql
CREATE CATALOG IF NOT EXISTS adf_test_01;
CREATE SCHEMA IF NOT EXISTS adf_test_01.shcema_01;
CREATE OR REPLACE TABLE adf_test_01.shcema_01.nation_src
AS
SELECT
  *
  FROM
    samples.tpch.nation
;
CREATE OR REPLACE TABLE adf_test_01.shcema_01.nation
(
  n_nationkey integer
  ,n_name string
  ,n_regionkey integer
  ,n_comment string
)
;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/fce7f479-7d1c-4091-fc9b-c73df5c3a4ff.png)

```python
%sql
SELECT
  *
  FROM
    adf_test_01.shcema_01.nation
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6d630831-a784-0e62-f308-f136d261d9a2.png)

### 3. Databricks のクラスターにてデフォルトのカタログを変更

```text
spark.databricks.sql.initial.catalog.name adf_test_01
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/029bf5a8-4ad4-2bf1-b36f-1d77f9afdd02.png)

下記のコードを実行することで、デフォルトのカタログの確認が可能です。

```text
%sql
SELECT
  current_catalog()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/455c9e4f-a939-01dd-caad-127b73e214b2.png)

### 4. ADF にてnation_src テーブルをソース、 nation テーブルをシンクに設定したコピーアクティビティを含むパイプライを作成して実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/96045d24-3873-7823-d718-5f8f2410694f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0196d98a-18a7-1bdf-de1a-3c1eb1282c5b.png)

### 5. Databricks にてシンク先のテーブルにデータがあることを確認

```python
%sql
SELECT
  *
  FROM
    adf_test_01.shcema_01.nation
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a9aaafa3-9fd1-24e1-4c21-f126f61db681.png)

### 6. Databricks のカタログを削除

```python
%sql
DROP CATALOG IF EXISTS adf_test_01 CASCADE;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1a8d9560-e3aa-7efc-50c6-b7b8fbb4a9a4.png)
MongoDBを触ってみる

# 概要
MongoDBのインストールからCRUD操作の基本までをまとめました。

# インストール（Mac版）
https://www.mongodb.com/try/download/community

公式のインストールページにて、version、platform、Packageを選択後、インストール、解凍し任意の場所に配置する。

※今回は、version: `4.4.29`、platform: `macOS64`、Package: `tgz`をインストール後、
`/user/database`に配置し、パッケージを`mongodb`にリネームしました。

# dbディレクトリを作成
インストールした階層に`data/db`ディレクトリを作成します。
ここまでで下記の構成になっています。
```
/user
  └ database
      ├ mongodb
      │   └ bin
      │      ├ mongo
      │      ├ mongod
      │      └ mongos
      └ data
         └ db
```

# mongodを起動

mongodbを配置した場所へ移動し、ターミナルから下記を実行します。

```zsh
./mongodb/bin/mongod --dbpath ~/database/data/db  
```
ファイルが開けない旨のセキュリティエラーが出るので、macの`システム設定>プライバシーとセキュリティ>セキュリティ`から許可を実行します。

# mongoシェルを起動

```zsh
./mongodb/bin/mongo  
```
上記、mongodbの起動がうまくいっていないとエラーになります。
私の場合、`--dbpath`の指定をしていなくてエラーになっていました。

### 表示コマンド

```zsh
db #現在使用しているDB
show dbs #DB一覧を表示 
show collections #コレクション一覧を表示
```

### DBを作成（または使用するDBを指定）

```
use 【データベース名】
```

### Create（データの挿入）
```
db.【コレクション名】.insert(【配列またはオブジェクト】)
```

### Read（データの読み取り）
```
db.【コレクション名】.find()
```
クエリを渡すことで、特定の条件の検索も可能です。
完全一致はデータの`{key: value}`の形で渡します。

### Update（データの更新）
```
db.【コレクション名】.updateOne({　【検索対象のクエリ】　},　{$set: {　【置き換えるkey】：　【置き換え後のvalue】　}})
```
- 更新時は`$set:{}`を挟む必要があるので注意する
- 更新対象が複数ある場合は `updateMany()`を使う
- `＄currentDate: {lastModified: true}` とすることで更新時刻の設定が可能。※「lastModified」は任意のキーに変更可能

### Delete（データの削除）

```
db.【コレクション名】.deleteOne(【削除対象のクエリ】)
```

**注意: 以下のように空のオブジェクトを渡すとコレクションの全てのデータが削除されます。**
```
db.【コレクション名】.deleteMany({})
```

### 演算子
.find()などで対象を絞る際は[比較演算子](https://www.mongodb.com/docs/v4.4/reference/operator/query-comparison/)や[論理演算子](https://www.mongodb.com/docs/v4.4/reference/operator/query-logical/)を使用する事で、より柔軟な検索ができる。
例：`inventry`コレクションから`qty`が20より大きいものを検索
```
db.inventory.find( { qty: { $gt: 20 } } )
```
ejsでよく使う記法メモ

# ejsとは

EJSは、プレーンな JavaScriptを使用してHTMLマークアップを生成できるシンプルなテンプレート言語です。

https://ejs.co/

# 値をテンプレートに出力する
```html
<h1><%= 'hello world'.toUpperCase() %></h1>
<img src="<%= imgsrc %>">
```
`<%=`タグを使ってJavaScriptの値をHTMLに埋め込む事ができます。

# 制御フロー
```html
<% if (user) { %>
  <h2><%= user.name %></h2>
<% } %>

<ul>
  <% users.forEach(function(user){ %>
    <li><%= user.name %></li>
  <% }); %>
</ul>
```
if文やループなど出力を伴わないScriptは`<%`タグを使用します。

# インクルード
```html
<%- include('user/show', {user: user}); %>
```
共通部分をテンプレート化し、インクルードする事ができます。
第1引数にインクルードしたいファイル、第2引数に渡したいデータを記述します。
Prologでグローバル変数を定義する

## 概要

ドキュメントの[グローバル変数](https://www.swi-prolog.org/pldoc/man?section=gvar)の項目を読んだのでまとめる

## 使い方

### 値の設定

グローバル変数へ値を設定するには以下の述語を利用する。

- `b_setval` : blocking set value
- `nb_setval` : non-blocking set value
- `nb_linkval` : non-blocking link value

`b_setval`と`nb_setval`の違いは以下の通り。
`b_setval`は更新中に他スレッドからのアクセスがブロックされる(スレッドセーフ)
`nb_setval`は更新中に他スレッドからのアクセスを許可する

`nb_linkval`は`nb_setval`とほぼ同じ挙動であるが、値のコピーを作成しない。
具体的には以下のコードからわかるが、`nb_linkval`は値のコピーを作成しないので、`N = world`のスコープから外れると中身を参照できなくなる。

```prolog
demo_nb_linkval :-
        T = nice(N),
        (   N = world,
            nb_linkval(myvar1, T),  % 保存
            nb_setval(myvar2, T),   % 保存
            fail                    % 強制的に失敗させる
        ;   nb_getval(myvar1, V1),  % 失敗したのでこちらが実行される
            nb_getval(myvar2, V2),
            writeln(V1),            % nice(_27146) 引数の中身までは保存されない
            writeln(V2)             % nice(world)が保存される
        ).
```

### 値の取得

グローバル変数の値を取得するには以下の述語を利用する。

- `b_getval` : blocking get value
- `nb_getval` : non-blocking get value
- `nb_current` : non-blocking current value

`b_getval`と`nb_getval`の違いは値の設定と同様にBlockin/Non-Blockingの違いである。

`b_getval`, `nb_getval`と`nb_current`の違いは以下の通り。
`b_getval`, `nb_getval`は存在しない変数名を指定するとエラーになるが、`nb_current`は失敗(`false`)する。

```prolog
demo_getvalue :-
  b_setval(var1, 100),
  nb_getval(var1, X1),
  nb_current(var1, X2),
  writeln([X1, X2]),            % var1は存在するので両方とも取得可能
  (
    nb_current(var2, X3),       % var2は存在しないので失敗する
    writeln(X3)
    ; writeln('not found var2') % 失敗するのでこちらが実行される
  ),
  nb_getval(var2, X3).          % var2は存在しないのでエラーになる
```

### 値の削除

グローバル変数を削除する場合は以下の述語を利用する。
なおBlocking用の述語は用意されていないようである。

- `nb_delete` : non-blocking delete

## まとめ

最初はまとめるほどのことでも無いと思ったが、`nb_linkval`や`nb_current`などドキュメントを読んだだけでは挙動がわかりにくかったので、サンプルコードで挙動を確認しつつまとめてみました。
Expressでejsを設定する

# 概要

Express + ejsでの環境構築手順をまとめました。

# インストール

```terminal
npm i express ejs
```

# index.jsの設定（全体）

```javascript:index.js
const express = require('express');
const app = express();
const path = require('path');

// cssなど静的ファイルの配置場所を設定
app.use(express.static(path.join(__dirname, 'public')))

// node.jsの実行場所に関わらず、viewsが参照するディレクトリを設定する
app.set('views', path.join(__dirname, 'views'));
//　テンプレートにejsを使う設定
app.set('view engine', 'ejs');
// ルーティングを設定
app.get('/', (req, res) => {
    res.render('home')
})

// localhost:3000でサーバーを起動
app.listen(3000, ()=>{
    console.log('watching...')
})
```

# viewsディレクトリの設定

```javascript:index.js
app.set('views', path.join(__dirname, 'views'));
```

`app.set('views')` でviewディレクトリを設定。
デフォルトは`process.cwd() + '/views'`なのでルートディレクトリ以外からNode.jsを実行するとエラーになる。

https://expressjs.com/ja/4x/api.html#app.set

そこで`path.join(__dirname, 'views')`を設定することで、どこからNode.jsを実行してもエラーにならないようにしておく。

https://nodejs.org/api/path.html#pathjoinpaths

# 静的ファイルの参照先を設定

```javascript:index.js
app.use(express.static(path.join(__dirname, 'public')))
```
viewsと同様に`__dirname`を設定しておく。

# ルーティングの設定

第2引数にデータを渡すこともできる。動的なルーティングは以下のようにする。

```javascript
app.get('/post/:category', (req, res) => {
    const { category } = req.params;
    const data = { posts: [...] };
    res.render('category', { ...data });
});
```

# ejsファイルを作成
`views`ディレクトリに`home.ejs`を作成することで、`localhost:3000`でページが表示される。