OmniAICreator/Qiita-1.07M huggingface dataset:
フローの細かい話

#0. はじめに
こんにちは、つよっしーといいます。
今回、最大流問題について勉強したのでそのとき思った細かい問題について書きます。
ちなみに自分はAtcoder緑程度なので間違ってても叩かないでください :pray:
またこの記事では図やイラストなどはなく定義のみを書くので他にわかりやすい記事がたくさんあると思います。

#1. 最大流問題とは
最大流問題の定義は以下です。
$G=(V,E)$ を有向グラフとし各辺 $e \in E$ に対して容量 $c(e)>0$ が与えられているとする。また指定された2点$(s,t)$ を除いた頂点 $v \in V-\\{s,t\\}$ に対して流量保存則

```math
\sum_{ e \in E(\{v\},V-\{v\})} f(e) - \sum_{ e \in E(V-\{v\},\{v\})} f(e) = 0 
``` 

および任意の $e \in E$ に対し $f(e) \leq c(e) $ を満たす $f$ (フロー)を定める。その流量を

```math
val(f) = \sum_{ e \in E(\{s\},V-\{s\})} f(e) - \sum_{ e \in E(V-\{s\},\{s\})} f(e) 
``` 
とし、この流量 $val(f)$ を最大化する。また $E(X,Y)$ は $X$ から $Y$ へと向かう辺の集合である。

#2. カットとは
$V$ の分割 $(X,V-X)$ において $s \in X$ かつ $t \in V-X$ であるものを $V$ の s-tカットといい、容量を

```math
cap(X) = \sum_{ e \in E(X,V-X)} c(e)
``` 
で定める.

#3. 最小カット定理
流量 $val(f)$ の最大値と s-tカットの容量の最小値は一致する。
・証明の手順
(1) 任意の $f$ と任意の s-tカット $(X,V-X)$ に対して $val(f) \leq cap(X)$ が成り立つことを示す。
(2) $val(f)=cap(X)$ となる $f$ と $X$ が存在することを示す。 

#4. 本題
本題は最小カット定理の証明において出てくる次の式です。

任意の s-tカット $(X,V-X)$ に対して

```math
val(f) = \sum_{ e \in E(X,V-X)} f(e) - \sum_{ e \in E(V-X,X)} f(e)
``` 
が成り立つ。

**ほんまに？？？？？？**
いや感覚的にはそうなんだけれど自明じゃないと思う。なので今回は無理やりこれを示します。
また簡単のために 

```math
x(X,Y) = \sum_{ e \in E(X,Y)} f(e)
``` 
とし元の式を

```math
val(f) = x(X,V-X) - x(V-X,X)
``` 
としておきます。
証明の流れとしては流量保存則の式を変形するだけです。

#5. 上式の証明
まず $s$ ではない頂点 $u \in X$ に対して流量保存則を変形します。また $Y=V-X$ としています。

```math
\begin{align}
 x(\{u\},V-\{u\}) - x(V-\{u\},\{u\}) &= 0 \\
 x(\{u\},X-\{u\}) + x(\{u\},Y) - x(X-\{u\}, \{u\}) - x(Y, \{u\}) &= 0 \\
 x(X-\{u\}, \{u\}) - x(\{u\},X-\{u\}) &= x(\{u\},Y) - x(Y, \{u\})
\end{align}
``` 
となります。これを $s$ ではない $u$ に対してすべて足し合わせると

```math
\begin{align}
 \sum_{u \in X-\{s\}} x(X-\{u\}, \{u\}) - \sum_{u \in X-\{s\}} x(\{u\},X-\{u\}) &= \sum_{u \in X-\{s\}} x(\{u\},Y) - \sum_{u \in X-\{s\}} x(Y, \{u\})
\end{align}
``` 
となります。ここで流量の式を

```math
\begin{align}
 val(f) &= x(\{s\},V-\{s\}) - x(V-\{s\},\{s\}) \\
   &= x(\{s\},X-\{s\}) + x(\{s\},Y) - x(X-\{s\}, \{s\}) - x(Y, \{s\})
\end{align}
``` 

```math
\begin{align}
val(f) + x(X-\{s\}, \{s\}) - x(\{s\},X-\{s\}) = x(\{s\},Y) - x(Y, \{s\})
\end{align}
``` 
と変形して上式に足します。すると

```math
\begin{align}
val(f) + \sum_{u \in X} x(X-\{u\}, \{u\}) - \sum_{u \in X} x(\{u\},X-\{u\}) = \sum_{u \in X} x(\{u\},Y) - \sum_{u \in X} x(Y, \{u\})
\end{align}
``` 

となります。ここで右辺に注目するとこれは $x(X,V-X) - x(V-X,X)$となっていることがわかります。したがって

```math
\begin{align}
val(f) + \sum_{u \in X} x(X-\{u\}, \{u\}) - \sum_{u \in X} x(\{u\},X-\{u\}) = x(X,V-X) - x(V-X,X)
\end{align}
``` 
となります。また左辺の下記の式

```math
\begin{align}
\sum_{u \in X} x(X-\{u\}, \{u\}) - \sum_{u \in X} x(\{u\},X-\{u\})
\end{align}
``` 
については $0$ となります。なぜならこの式の左項は $X-\\{u\\}$ から $u$ へと向かう各辺のフローの和であり、右項は $u$ から $X-\\{u\\}$ へと向かう各辺のフローの和です。したがってこれらの差によって $X-\\{u\\}$ と $u$ 間の各辺のフローの値が打ち消しあうこととなります。以上より本題の式

```math
val(f) = x(X,V-X) - x(V-X,X)
``` 
が示せました！(もっと簡単に示せる方法があれば誰か教えてください:pray:)

#6. おわりに
今までフローはいまいちわかっていなかったので今回しっかりと勉強してみました。しかしこの記事には間違っているところも多数あると思うので参考程度に使用してください。また訂正すべき部分はお知らせください:pray:　今回はじめてQiitaの記事を書いてみましたが気が乗れば次もやろうと思います。
Cognito の Hosted UI 用にカスタムドメインを登録しようとした場合に手間取ったこと

# やりたいことと問題点

今回は FQDN: `test.auth.example.com` を Cognito の独自ドメインとして設定したい。

今回は `example.com` が Route 53 で使えるようになっており、`*.auth.example.com` の証明書が Certificate Manager (us-east-1) で有効になっている状態で作業を開始した。

Management Console で独自ドメインを設定しようとしたが、`Custom domain is not a valid subdomain` というエラーで設定ができない。 このエラーメッセージで検索すると以下のような記事が引っかかった。

https://qiita.com/afukuma/items/4074fda7fa158eb387a3

ということで、ここでは「ルートドメインにAレコードを登録する必要がある」ということで、`example.com` にAレコードを登録して再実施した。 しかし、問題は解決しなかった。

# 原因と解決策

今回登録する FQDN は `test.auth.example.com` なので、これは `auth.example.com` のサブドメインであり、この値がルートドメインである。 所有しているドメインの大本がルートドメインというわけではない。
そのため、`auth.example.com` にAレコードを登録（ここでは、利用しないので値は適当に `127.0.0.1` とした) して、再度独自ドメインの登録作業を実施すれば正常に登録できた。
テキストが入力されたらSaveボタンを有効にする方法(Swift)

現在オリジナルアプリのスケジュール機能を実装するために、基礎としてメモアプリを作成しています


※この記事ではセーブボタンの配置などについては触れません

###完成形
空欄だとSaveボタンが無効になり

<img width="413" alt="スクリーンショット 2017-12-01 0.09.34.png" src="https://i.gyazo.com/85e3b7b33bc2bcc94e395a334f22379e.png">

文字を入力すると有効になります
<img width="413" alt="スクリーンショット 2017-12-01 0.09.34.png" src="https://i.gyazo.com/d08b7cf808f9c353873bcf7efa8350e6.png">

###目次

- [Saveボタンを無効にする方法](https://qiita.com/programming_00/items/ddc6b09f5e76af1da30b#save%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%92%E7%84%A1%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
- [テキストフィールドに入力された値を検出する](https://qiita.com/programming_00/items/ddc6b09f5e76af1da30b#%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%81%AB%E5%85%A5%E5%8A%9B%E3%81%95%E3%82%8C%E3%81%9F%E5%80%A4%E3%82%92%E6%A4%9C%E5%87%BA%E3%81%99%E3%82%8B)

##Saveボタンを無効にする方法

まずは、Saveボタンを無効にします

記述する場所は[`override func viewDidLoad() `](https://qiita.com/programming_00/items/ed1dca1ca06c2f55500d#override%E3%81%AE%E8%A9%B3%E7%B4%B0)の部分です

`override func viewDidLoad() `の部分に`self.saveButton.isEnabled = false`を追記します

```ViewController.swift
override func viewDidLoad() {
    super.viewDidLoad()
    self.saveButton.isEnabled = false
}
```

`saveButton`に対して`isEnabled`で、ボタンを有効か無効にすることができます、なので今回は`false`にして無効にします

##テキストフィールドに入力された値を検出する
このままではセーブボタンが無効のままなので**テキストフィールド**に入力された場合、ボタンを有効にします
そのために、**テキストフィールド**に入力された値を検出する方法を解説します。

まず、**Main.Storyboard**にある`テキストフィールド`をコントロールキーを押しながらドラックアンドドロップをし、紐付けます。

```ViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        self.saveButton.isEnabled = false
    }
    _____________________
    //↑にドラックアンドドロップ
   
```
<img width="300" alt="スクリーンショット 2017-12-01 0.09.34.png" src="https://i.gyazo.com/00674a6d003f38260848ef5ef480b2b1.gif">
___
####ドラックアンドドロップをすると下のようなものが出てきます

<img width="300" alt="スクリーンショット 2017-12-01 0.09.34.png" src="https://i.gyazo.com/0949bb3173059ef0e42c78f04820c2a3.png">

それぞれ

**Connection（接続タイプ）**を`Action`

**Name（プロパティ名）**を`memoTextFieldChanged`

**Event（イベント）**を`Editing Changed`

にします。
___
####次に先ほど入力したmemoTextFieldChangedメソッドの処理を記述します

```ViewController.swift
1    override func viewDidLoad() {
2        super.viewDidLoad()
3        self.saveButton.isEnabled = false
4    }
5    @IBAction func memoTextFieldChanged(_ sender: Any) {
6        let memo = self.memoTextField.text ?? ""
7        self.saveButton.isEnabled = !memo.isEmpty
8    }
   
```
繰り返しになりますが、７行目の`isEnabled`がボタンを有効、無効にします。

６行目では、**テキストフィールド**が**nil**（**空**）か判断します。

７行目の**`isEmpty`**で**テキストフィールド**が**nil**の時は`false`
**nil**ではない時は`true`と判別し`saveButton`を有効にできます。

※memoの横に!がないとtrue、falseが逆になってしまいます。
vs2010でagauge その2

#概要

vs2010でagaugeやってみた。
vs2010のnugetは、動かないので、手動で登録した。

#agauge.dllを参照する。

参照設定を右クリックし、参照の追加、参照でファイルを指定する。

#ツールボックスにコンポーネントを追加する

ツールボックス上で右クリックし「タブの追加(A)」を選択します。
タブの名前に「agauge」と入力します。
作成した新しいタブを右クリックし、「アイテムの選択(I)...」を選択します。
［ツールボックスアイテムの選択］ダイアログの「.NET Framework コンポーネント」タブを選択します。
参照でファイルを指定する。

以上。
Ruby on Railsの環境が整うDockerfile

安易。
MariaDBとかは他コンテナで建てるものとします。

# Dockerfile
```Dockerfile
FROM node:lts-slim AS node
FROM ruby:3

COPY --from=node /opt/ /opt/
COPY --from=node /usr/local/lib/ /usr/local/lib/
COPY --from=node /usr/local/bin/ /usr/local/bin/

RUN apt update && apt upgrade -y && apt install -y g++

RUN gem install rails
```

# ちょっと説明
## マルチステージビルドする
NodeイメージからNodeインタプリタのあるディレクトリをごっそりを持ってくる。
Nodeの特定バージョンを入れようと思うとcurlでインストーラとってきて、スクリプト実行して、必要ならyarnを別で入れるなどちょっとめんどくさい。
でもマルチステージビルドならDocker Official ImageのNodeインタプリタを拾えるし、バージョン指定はイメージのタグを変えればいいだけなのでちょっと楽。

```Dockerfile
# Nodeインタプリタをとってくるイメージ
FROM node:lts-slim AS node

# 最後に書いたFROMがイメージのベースになる
FROM ruby:3

# インタプリタの含まれるディレクトリをコピー
COPY --from=node /opt/ /opt/
COPY --from=node /usr/local/lib/ /usr/local/lib/
COPY --from=node /usr/local/bin/ /usr/local/bin/

RUN apt update && apt upgrade -y && apt install -y vim g++ # <- Nodeの駆動にg++が必要
```

参考: [Multi-stage build でNode.jsのインストールをちょっぴり効率化する - アクトインディ開発者ブログ](https://tech.actindi.net/2019/06/20/084247)

## railsのインストール
グローバルにインストール。
あとは`docker run -it <image name> bash`とかしてコンテナ内で`rails new app`とかすると準備完了。

```
RUN gem install rails
```
stylesheetの個別割り当て方法

rails g をすると stylesheet 1つと、view(home,help,aboutとか)が任意数生成される。
それぞれのページで、共通するcssは少なからずあるだろうが、とは言え違う部分も多い。
それを1つのstylesheetに、「ここからはhelpページのcss」とか、「ここからはaboutページのcss」とか
自分でわかる様にコメントを挟んで分ける。
かつ、stylesheet内に同じクラスが存在してしまうと重複してしまうので、クラス名にも気を遣う。
例えば、「helppage-container」と、「aboutpage-container」とか・・・正直面倒臭いし、
多分誰もこんな事やってない気がする。
メモと言っておきながらどなたかアドバイスを頂けると助かります。

苦渋の解決策として・・・
https://keruuweb.com/rails-%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8Bcss%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B/
これならstylesheetは増えてしまうが、viewと１対１の関係にできそう。
rails の設計思想から外れてしまいそうだが・・・独学のど素人としては一旦これが単純明快。
慣れてきたらまた戻ってこよう！
Linuxのプロセスとは

#プロセスとは

動いているプログラムのこと。
確認するためのツールは、使用するOSによって異なる。

Windows　タスクマネージャー
Linux モニター
macOS　アクティビティモニター

#プロセスの生成
コンピューターでは、複数の処理が同時に行われており、その一つ一つの処理をプロセスとして管理されている。

ターミナルで、lsコマンドを使用するとき、lsコマンドが実行される。
この時、lsのプロセスが生成される。

シェルのプロセスは、ログイン後あるいはターミナルの起動と共に開始されて、ログアウトまたはターミナルを閉じるまでメモリに保持される。

#プロセスIDとは
プロセスには固有の番号が割り当てられる。それを**プロセスID**（PID）と呼ぶ。


#プロセスの確認方法（コマンド）
LinuxのプロセスはPSコマンドで調べることができる。

psコマンドで見ることができる情報は、以下。

|PID|TTY|TIME|CMD|
|---|---|---|---|
|プロセスID|ターミナルの一時的な名前|CPUの稼働時間|コマンド|


実際に実行してみると

```
$ ps
PID TTY     TIME CMD
7483 pts/1  00:00:00 zsh
9884 pts/1  00:00:00 ps
```

#tty

TTY:teletypewriterの略
古い歴史がある。
UNIX黎明期に大量に使われていた端末がテレタイプライター。
コンピュータからの出力は、現在のような画面ではなくて、長い紙に打ち出されていた。人間からの入力には、紙テープやタイプライターが使われていた。
この端末からttyという名称が来ている。

そして、現在では、ハードウェアだった端末をソフトウェアにしてしまったのが、端末エミュレータである。
例：GNOME terminal, Konsole, mltermなど。

端末を識別するために端末の1つ1つにpts/0のような一時的な名前が割り振られる。

psコマンド単体では、自分のプロセスのみ表示されるが、aをつけることですべてのプロセスを見ることができる。
すべてというのは、SSHで接続したターミナルのプロセスや、複数のターミナルを開いた状態で端末が仮想的に複数存在してるときのすべてのプロセスということである。

以下では、現在psコマンドを使った端末には、pts/0が割り当てられて、
他に開いている端末には、pts/1が割り当てられる

```
$ ps a
PID TTY     TIME CMD
3133 pts/0  00:00:00 zsh
9884 pts/0  00:00:00 ps
7483 pts/1  00:00:00 zsh

```

ターミナルをもっと開いていくと、pts/2, pts/3..とどんどん割り当てられていく。閉じると、割り当てが解除される。解除された名前は、次にターミナルが開かれたときにその名前が使われる。それは同じターミナルを示しているわけではなく、ただの識別するためのものである。

#psとシェルが別々に表示されているが違いは？

psを実行するとシェルとpsが表示されている。
それは、psがextarnal コマンドであるからである。

### internal command 
cd , source , fg など
シェルに組み込まれているコマンド。
シェルに組み込まれているので、新しいプロセスを生成せず実行されるので、実行速度がとても早い。

### External command 
ls , catなど
シェルに組み込まれていないコマンド。
そのコマンドは、呼ばれるたびに新しいプロセスを生成する。

internal コマンドが呼ばれるとシェルのタイムが加算される。
psを実行したときに、psも表示されるがこれはpsはextarnalコマンドであり、新しくプロセスが生成されているからであり、outputが出力される時には、プロセスが終了している。

internalかexternal か判別する方法は、typeコマンドを使用する。

```
$ type cat 
cat is /bin/cat

$ type cd
cd is a shell builtin
```

#internal コマンドのTIMEの変化を見てみる

internal コマンドが呼ばれるとシェルのタイムが加算される。基本的に起動してpsを実行すると0である。

そこで以下を実行すると

```
$ while 
do 
x=1
done
```

終了するときはctr+Cをおす。
そして、psコマンドで確認すると実行された時間だけzsh(シェル）のtimeが加算されている


```
$ ps
PID TTY     TIME CMD
7483 pts/1  00:00:02 zsh
9884 pts/1  00:00:00 ps
```

#external コマンドのプロセスの動きを見る

yesというコマンドがある。これは、プロセスが止まるまで（killされる）までyesを出力し続ける。今回は /dev/nullに出力し続ける。

* /dev/null に出力されるものはすべて破棄されて、何も表示されない。

## コマンドをバックグラウンドで実行する
コマンドを入力するとコマンドが終了するまで待たなければいけない。その間他のコマンドを打つことはできない。
しかし、時間がかかり他のコマンドを使いたい場合や、今回のようにプロセスを確認したい場合は&を使用することでバックグラウンドで実行することができる。

```
$ yes > /dev/null &
[1] 9880
```

これでバックグラウンドでプロセスID 9880として、yesコマンドが実行され続けている。
この状態でpsを確認してみると

```
$ ps
PID TTY     TIME CMD
7483 pts/1  00:00:00 zsh
9800 pts/1  00:00:50 yes
9884 pts/1  00:00:00 ps
```

yesコマンドのプロセスが生成されていて、50秒間実行されているということがわかる。

#プロセスを終了(kill)する

プロセスをコマンド終了させることができる。その時には、killコマンドを使う。
killの引数にはプロセスIDを渡す。
そのほかkillall　などある。


####参考
https://www.theunixschool.com/2012/09/ps-command-what-does-time-indicate.html?m=1
https://www.theunixschool.com/2012/03/internal-vs-external-commands.html
https://www.howtogeek.com/428174/what-is-a-tty-on-linux-and-how-to-use-the-tty-command/
https://www.atmarkit.co.jp/ait/articles/1706/23/news010.html
【Linux】OS、カーネル、ディストリビューション

# OSとは


- OS(オペレーティング・システム)は、ハードウェアとアプリケーションを仲介するソフトウェア
- 代表的なOSにはWindows,MacOS,UNIXがある
- LinuxもOSの一種　(※厳密にはカーネルの名称だが後述記載）

![OS-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004560/c2b2a2b6-7c94-afe0-db14-24df1e2eeb97.png)

OSがハードウェアとアプリケーションの間で、ハードウェアをコントロール、またはアプリケーションが動作する環境を提供する役割を担っている。

# カーネルとディストリビューション
### カーネルとは

- OSの中核部分のプログラム
- プログラムのプロセス管理、メモリ管理、ファイルシステム管理、ネットワーク管理、デバイス管理などを担当
- Linuxはカーネル部分の名称
- LinuxをOSの意味で用いることが多いので、「Linuxカーネル」「LinuxOS」と言うこともある

### ディストリビューションとは

- LinuxをOSとして使えるようにした配布形態のこと
- OSとしての機能を実現するため、カーネル以外にも、アプリが利用するソフトウェアライブラリ、GUI、コマンド、OSをコンピュータにインストールするためのインストーラ等が必要。それらを組み込み１つの製品としたもの
- ディストリビューションを構成するソフトウェアは、ほとんどがオープンソースソフトウェア

ディストリビューション構成例
![OS-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004560/06ded2d7-d7da-c104-192a-095c4f195faa.png)

### ディストリビューションの種類
ほとんどがオープンソースで構成されているため、企業が開発し有償で販売しているもの、コミュニティが開発し無償で提供されているものとさまざまなディストリビューションがある。

#### Red Hat系ディストリビューション

レッドハット社によって開発されたRed Hat Linuxをベースに開発されたもの。
企業システムとしても利用できる有償のRed Hat Enterprise Linux、
Red Hat Enterprise Linuxのソースコードを元に作られた無償のCentOS等がある。

- Fedora
- Red Hat Enterprise Linux
- CentOS 

#### Debian系ディストリビューション 
DebianProjectコミュニティが開発したDebian GNU/Linuxをベースとしたディストリビューション。

- Ubuntu
- Raspbian

#### その他
- Slackware
- openSUSE
WindowsServer2016にMariaDB+mroongaをサービスとしてインストールする

# 概要

WindowsServer2016上で全文検索([groonga](https://groonga.org/))付の[MariaDB](https://mariadb.com/kb/ja/mariadb/)を使いたかったので、[mroonga](https://mroonga.org/ja/)で提供されているzipファイルのバイナリを用いてインストールしたときの記録。
安易にデータディレクトリをd:\ドライブにしようとおもってハマったのと、サービス化にあたってあれこれしたので、そちらの対処記録ともいえる。

前提としているのは mroonga 11.0。
公式サイトのドキュメントに従い、msiパッケージでなくzip版をダウンロードしたものを利用する。
(通常はドキュメントにあるとおりmysqldを実行すれば問題なく動作する)

以下の記事を参考にしている。
- [MariaDB Community Server 10.4.11 - Installing on Windows 10](https://qiita.com/rubytomato@github/items/d7174c915756ec787412)
- [mariaDB10.0.21でmroongaを使ってみる](https://qiita.com/tentatsu/items/140ffc017219c2557461)
- [MySQLをWindowsサービスに登録する](https://www.dbonline.jp/mysql/install/index4.html)
- [Windows 版の MariaDB を ZIP パッケージからインストールしてみた](https://www.white-root.com/blog/1610936934)

## 準備

- mroonga入りmariadb (今回は mariadb-10.2.36-with-mroonga-11.00-winx64.zip を使用)
- mroongaのgithubより、[pluginをインストールするときのsql文](https://github.com/mroonga/mroonga/blob/master/data/install.sql.in)
- MySQLより[time_zone定義](https://dev.mysql.com/downloads/timezones.html)ファイル timezone_2021a_posix_sql.zip

## インストール

概ね [MariaDB Community Server 10.4.11 - Installing on Windows 10](https://qiita.com/rubytomato@github/items/d7174c915756ec787412) を参考にした。
コマンドプロンプトの操作は、インストール作業中は**「管理者として実行」**で利用する。

### mariadb+mroongaのzipファイルの展開

今回はシステムのインストール先を c:\opt\mariadb とし、データを d:\var\lib\mariadb\data という設定とする。
zipファイルを c:\opt\mariadb に展開。

### データディレクトリの初期化

```
c:\opt\mariadb\mariadb-10.2.36\bin\mysql_install_db.exe \
  --datadir=D:\var\lib\mariadb\data --password=<rootのパスワード>
```

このコマンド実行で、データディレクトリ内に`my.ini`ファイルが生成される。
元記事を参照しつつ、編集する。
注意事項としては上記作業でtimezoneの定義が消えるので、`default-time-zone`だけ**コメントアウトした状態**にしておく。

### 起動確認

編集した設定設定内容で起動できるか、コマンドライン上でサーバを起動してみる。
ここでエラーがでる場合は見直しておく。

```
mysqld.exe --defaults-file=D:\var\lib\mariadb\data\my.ini --console
```

### タイムゾーンデータのインポート

準備でダウンロードした `timezone_2021a_posix_sql.zip` の中身のsqlファイルを取り出しておく。
以下を実行する。

```
mysql.exe --defaults-file=D:\var\lib\mariadb\data\my.ini -u root -p -D mysql < timezone_posix.sql
```

エラーがなければ、特に表示なく終了する。
`my.ini` の中で先ほどコメントアウトした default-time-zone を有効にする。
再びmysqldを--consoleオプションで起動し、エラーがでないことを確かめる。

### mroongaプラグインの有効化

準備でダウンロードしておいた install.sql.in はMakeされる前の状態なので、手動で `@MRN_PLUGIN_SUFFIX@` を `.dll` に置換しておく。
あらたにコマンドプロンプトを起動し(さきほどの--consoleのmysqldを起動したまま)、以下を実行。

```
mysql.exe --defaults-file=D:\var\lib\mariadb\data\my.ini -u root -p  < install.sql
```
 
こちらもエラーが出ないことを確認する。mysqlを起動し、プラグインが有効化されたか確認。
mroongaが YES になっていること。

```
> show engines;
```

## サービスとして登録

起動していたmysqldは終了させる(`ctrl+c`で止められる)
以下のコマンドを実行。

```
mysqld  --defaults-file=D:\var\lib\mariadb\data\my.ini --install MariaDB
```

このコマンドでサービスが登録されるので、「コンピュータの管理」→「サービス」で確認することができる。
アンインストールについては以下のいずれかで行える。

```
mysqld --remove MariaDB

# or 

sc stop MariaDB
sc delete MariaDB
```

## 接続確認

上記設定群はローカル接続しか受け付けていないが、DataGripなりHeidiSQLなりで127.0.0.1:3306で接続できることを確認する。
必要に応じてbind設定する。

```
[mysqld]
#省略
bind-address = 0.0.0.0
```
【heroku】git push heroku masterのエラー

# はじめに
herokuで初めてデプロイを行いましたが、ターミナルでgit push heroku masterを実行したところエラーが発生してしまったので、対処法を記事に残しておきたいと思います。

## エラーの発生
```:ターミナル
git push heroku master
```

こちらのコマンドを実行したところ、以下のように「Failed to install gems via Bundler.」（上から１行目）と「error: failed to push some refs to〜」（1番最後の行）というエラーメッセージが出てしまいました。

```:ターミナル

〜省略〜

remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
remote:  !
remote:  ! ## Warning - The same version of this code has already been built: 620a93f164f06d54c43dc266f1589a3298f02e9a
remote:  !
remote:  ! We have detected that you have triggered a build from source code with version 620a93f164f06d54c43dc266f1589a3298f02e9a
remote:  ! at least twice. One common cause of this behavior is attempting to deploy code from a different branch.
remote:  !
remote:  ! If you are developing on a branch and deploying via git you must run
remote:  !
remote:  !     git push heroku <branchname>:main
remote:  !
remote:  ! This article goes into details on the behavior:
remote:  !   https://devcenter.heroku.com/articles/duplicate-build-version
remote: 
remote: Verifying deploy...
remote: 
remote: !	Push rejected to ●●.
remote: 
To https://git.heroku.com/●●.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/●●.git'
```

## 対処手順
最初に、現在入っているbundlerを削除します。

```:ターミナル
gem uninstall bundler
```
続けてbundlerのバージョン2.1.4を指定してインストールします。

```:ターミナル
gem install bundler -v '2.1.4'
```

次にやることはGemfile.lockを作り直しです。
テキストエディタから直接Gemfile.lockを削除し、ターミナルでbundle installを実行します。

```:ターミナル
bundle install
```

ここまでの変更をGitHubへ反映するため、GitHubを開き、commitとpushを行います。
そして再度git push heroku master実行してエラーが出なければ成功です。

```:ターミナル
git push heroku master
```
Shinyにおけるobserve()とreactive()の違い

# はじめに

リアクティブなプログラムを書く際に、observe() と reactive() の2つが利用できるのだが、違いがよくわからなかったため整理。 
 [Create a reactive observer](https://shiny.rstudio.com/reference/shiny/1.5.0/observe.html) と [Create a reactive expression](https://shiny.rstudio.com/reference/shiny/1.0.2/reactive.html) を参考にした。

# observe()

 [Create a reactive observer](https://shiny.rstudio.com/reference/shiny/1.5.0/observe.html) から以下抜粋。

> Details
An observer is like a reactive expression in that it can read reactive values and call reactive expressions, and will automatically re-execute when those dependencies change. But unlike reactive expressions, it doesn't yield a result and can't be used as an input to other reactive expressions. Thus, observers are only useful for their side effects (for example, performing I/O).

> Another contrast between reactive expressions and observers is their execution strategy. Reactive expressions use lazy evaluation; that is, when their dependencies change, they don't re-execute right away but rather wait until they are called by someone else. Indeed, if they are not called then they will never re-execute. In contrast, observers use eager evaluation; as soon as their dependencies change, they schedule themselves to re-execute.

> Starting with Shiny 0.10.0, observers are automatically destroyed by default when the domain that owns them ends (e.g. when a Shiny session ends).

- リアクティブな値を読み取り、リアクティブ式を実行する。またそれらの依存関係が変更されると__自動的に再実行__される。
- 返り値はないため、他のリアクティブ式への入力としては使用できない。（実行するのみ）
- オブザーバは依存関係が変更されるとすぐに、再実行する。（リアクティブ式は呼び出されるまで待機する）

# reactive()

 [Create a reactive expression](https://shiny.rstudio.com/reference/shiny/1.0.2/reactive.html) から以下抜粋。

> Details
Reactive expressions are expressions that can read reactive values and call other reactive expressions. Whenever a reactive value changes, any reactive expressions that depended on it are marked as "invalidated" and will automatically re-execute if necessary. If a reactive expression is marked as invalidated, any other reactive expressions that recently called it are also marked as invalidated. In this way, invalidations ripple through the expressions that depend on each other.

- リアクティブな値を読み取り、リアクティブ式を実行する。そららの依存関係は__必要に応じて再実行__される。


# observe() と reactive() の違い

基本的には__即時実行したいものは observe()__ で、__必要に応じて実行したいものは reactive()__ くらいの認識でよさそう。（間違っていそうなので、詳しい方ぜひコメントを。。。）
他にも observeEvent() や eventReactive()、bindEvent など違いがわからないものがたくさん。1つずつ理解しよう。
Netlifyで「Run `npm rebuild node-sass` to download the binding for your current environment.」が出る

Netlifyでデプロイした際にエラーが発生して一瞬だけ困ったのでメモ。

# 発生したこと
タイトルに書きましたが、nodeのバージョンアップをしたことでデプロイ時に「Run `npm rebuild node-sass` to download the binding for your current environment.」が発生しました。
ローカルでも発生していたので、`npm rebuild node-sass `を実行すれば問題が解消するのは解っていましたが、Netlifyでどうやって実行すれば？と頭を悩ませました。

```sh:エラーから抜粋
1:55:41 PM: ────────────────────────────────────────────────────────────────
1:55:41 PM:   1. Build command from Netlify app                             
1:55:41 PM: ────────────────────────────────────────────────────────────────
1:55:41 PM: ​
1:55:41 PM: $ npm run generate
1:55:41 PM: > osarai-club@1.0.0 generate
1:55:41 PM: > nuxt generate
1:55:43 PM: [warn] `router.scrollBehavior` property is deprecated in favor of using `~/app/router.scrollBehavior.js` file, learn more: https://nuxtjs.org/api/configuration-router#scrollbehavior
1:55:43 PM: [info] [@nuxt/content] Parsed 6 files in 0,6 seconds
1:56:10 PM: [fatal] Nuxt build error
1:56:10 PM:   ERROR in ./layouts/default.vue?vue&type=style&index=0&lang=scss& (./node_modules/css-loader/dist/cjs.js??ref--7-oneOf-1-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--7-oneOf-1-2!./node_modules/sass-loader/dist/cjs.js??ref--7-oneOf-1-3!./node_modules/@nuxt/components/dist/loader.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./layouts/default.vue?vue&type=style&index=0&lang=scss&)
1:56:10 PM:   Module Error (from ./node_modules/sass-loader/dist/cjs.js):
1:56:10 PM:   Missing binding node_modules/node-sass/vendor/linux-x64-88/binding.node
1:56:10 PM:   Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 15.x
1:56:10 PM:   Found bindings for the following environments:
1:56:10 PM:   - Linux 64-bit with Node.js 14.x
1:56:10 PM:   This usually happens because your environment has changed since running `npm install`.
1:56:10 PM:   Run `npm rebuild node-sass` to download the binding for your current environment.
```

# 解決方法
結論を先に書くと以下の対応で解決しました。
Netlifyの [deploy] -> [build & deploy] -> [Build settings] で build command を以下のように変更します。

```sh
npm rebuild node-sass && npm run generate
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140133/4639e25e-da9e-ddae-65a7-56a30005a4b2.png)

なお、デプロイが正常終了したことを確認したら、もう`npm rebuild node-sass`は不要なので元に戻しました。


# netlify cliでローカルからデプロイ
上記の方法を見つける前に以下のことも行ったのでついでに書いておきます。
参考サイトは以下になります。

* netlify cliをインストール、初期化<br>https://docs.netlify.com/cli/get-started/
* デプロイ<br>https://mottox2.com/posts/278

参考サイトにも記載されている通り、ローカルからデプロイする場合は以下の順番で実行します。

```
1.生成
npm run generate

2.デプロイ（draftがデプロイされて確認できます）
netlify deploy

3.本番デプロイ
netlify deploy --prod
```
Amazon Linux でのPHPバージョンアップ

## PHP7.2 から PHP7.4 にあげる

業務で使うことがあったので備忘録。

### 0.開発環境
- Amazon Linux 2
- PHP 7.23
- Apache/2.4.46

### 1. 旧バージョンのPHPと関連モジュールを削除

```
sudo yum -y remove php-*
```

### 2.php7.2を廃止

```
sudo amazon-linux-extras disable php7.2
```

### 3.php7.4を適用

```
sudo amazon-linux-extras enable php7.4
```

### 4.phpと関連モジュールの再インストール

```
sudo yum install  php php-devel php-mbstring php-pdo php-gd php-mysqlnd php-cli php-common php-xml php-fpm php-json
```

### 5.バージョン確認

```
$ php -v
// 7.4になっていれば成功
PHP 7.4.11 (cli) (built: Oct 21 2020 19:12:26) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
```

### 6.apache再起動

```
sudo systemctl restart httpd.service
```

以上
SQL データの並び替え,文字列の連結

こちらの記事では、私が学んだSQLについて記載しております。
自身の忘れないためのメモとしております。
間違っている部分もあるかもしれませんので、ご了承ください。

#order byを使用して並び順を指定する！ 

```
asc・・・昇順　　並び順の指定がなければ、ascになる
desc・・・降順

select * from テーブル名 order by カラム名 asc;　←ascを省略しても良い！

select * from テーブル名 order by カラム名 desc;
```

###複数の並び替え条件を指定する場合！

```
order byは、カンマ区切りで複数の並び替え条件を指定できる！
下記は、テーブル名のカラム名を降順に指定し、登録されたidの順番昇順になります。

select * from テーブル名 order by カラム名 desc, カラム名 asc;


例　ユーザー名を降順にし、そこから登録された順番に表記する場合
テーブル名　users  
カラム名　name , id

select * from users order by name desc, id asc;
　　　　　　　　　　　↑
zから始まる名前を並べ、且つ、登録の順番で表記する。
＊注意　アルファベットでのnameであれば並び替えの指定はできるが、日本語の文字列ではできない！!!
```

#四捨五入を行うには、roundを使用する！
記述方法　round(対象の数値,小数点の桁)

```
例
round(99.888,0)　=> 100
         ↑最初が０番目になります
round(99.888,1)　=> 99.9
          ↑小数点から２個目の位置
round(99.888,2)　=> 99.89
           ↑小数点から３個目の位置

実際の記述
select カラム名 * 1.1 from テーブル名; 

select round(カラム名 * 1.1 , 0) from テーブル名;
```

#文字列を連結させたい場合 concatを使用！


```
記述方法　concat(文字列１,文字列２,文字列３,,,,,,)
スペースを入れたい場合は、(' ')
                      ↑シングルクォーテーションの中にスペースを入れる！！

select concat('田中',' ','太郎','　様');  => 田中　太郎　様　と取得可能です
　　　　　　　　　　　　　↑スペース　　↑スペース　　　　　↑　　↑　スペースが開いた状態になる。

select concat(カラム名,カラム名) from テーブル名;
```

#日付と時刻の演算子
現在の日付・・・・・・current_date
現在の時刻・・・・・・current_timestamp
a日後の日付・・・・・current_date() + interval a day
a日前の日付・・・・・current_date() - interval a day
x時間後の時刻・・・・current_time() + interval x hour
x時間前の時刻・・・・current_time() - interval x hour
extract・・・・・・・・日付や時刻の特定部分まで取り出す

```
・記述例
select current_date();　　=>現在の日付
select current_timestamp(); =>現在の時刻
select current_date() + interval 5 day; 5日後
select current_date() - interval 5 day;　5日前
select current_time() + interval 12 hour;　12時間後
select current_time() - interval 12 hour;　12時間前
select * from テーブル名 where extract(year_month from カラム名) = ２０２１０３;　2020年3月全てのカラムデータ取得する　
select * from テーブル名 where extract(year from カラム名) = ２０２０;　2020年全てのカラムデータ取得する
select * from テーブル名 where extract(month from カラム名) = 1;　1月のカラムデータ全て取得する
```

##補足
####絶対値　absで取得する
数値の符号を考えず、ゼロからの距離の大きさを表す数値です。
・１００の絶対値は１００
・−１００の絶対値は１００
・０の絶対値は０

```
絶対値の記述
select abs(100);
select abs(-100);
select abs(0);
```
UIScrollViewにタップアクションを追加する


#はじめに
開発している最中に、UIScrollViewを実装する場面があったのですが
`touchesBeganメソッド`が使えないという事態に陥りました。

つまり、`タップに反応しなかった`んですね。

#原因
これは、そもそも`UIScrollViewはデフォルトでタップが認識されないようになっている`そうで
出来なくて当たり前なんですね。

ですがタップした時に処理を加えたい！！！

ということで解決方法をググって実装したら出来たので備忘録としてQiitaに残します。

#実装方法
下記のコードのように`UITapGestureRecognizer`を使って
自分のUIScrollViewに`タップアクションを追加`します。

```swift
@IBOutlet weak private var scrollView: UIScrollView!

let recognizer = UITapGestureRecognizer(target: self, action: #selector(tapAction))
// ジェスチャ認識に必要なタップ数
recognizer.numberOfTapsRequired = 1
// ジェスチャ認識のためにユーザーがタップする必要のある指の数
recognizer.numberOfTouchesRequired = 1
scrollView.addGestureRecognizer(recognizer)

// 自作メソッドを用意
@objc private func tapAction() {
    // 自分のscrollViewがタップされた時にしたい処理
    print("タップ！")
}
```
#おわりに
これだけで`タップ処理`を追加することが出来ます。

よかったら試してみて下さい！
Linuxコマンドについて

Linuxコマンドについての記事を書きたいと思う。


■Linuxコマンド
Linuxコマンドとは、PCへ操作を命令する為のコマンドのこと。ターミナルでは Linuxコマンドの入力でPCに様々な命令を与えることができる。

### カレントディレクトリの表示
現在のカレントディレクトリの確認方法はpwdコマンドを使用する。

■pwdコマンド
pwdコマンドはprint working directoryの略で、カレントディレクトリのパスを表示するコマンド。

### ファイルやディレクトリの一覧を表示
GUIのようにクリックしてファイルの中に何が入っているか確認できない、
そんな時は、lsコマンドを使用し中身を確認する。

■lsコマンド
lsコマンドはlist segmentsの略で、ディレクトリやファイルの一覧を表示するコマンド。
実行することで、カレントディレクトリの直下にあるディレクトリやファイルの名前が一覧で表示される。使い方はターミナルでlsと打ち込んでエンターキーを押すだけ。
また、lsの後に半角スペースを空けて、ディレクトリのパスを入力して実行すると、その指定したディレクトリの中身を一覧表示できる。

### カレントディレクトリの移動
ファイルからファイルへの移動をする際は、cdコマンドを使用する。

■cdコマンド
cdコマンドはchange directoryの略で、カレントディレクトリを移動するときに使う。使い方はターミナルでcd[移動したいディレクトリのパス]と打ち込んでエンターを押す。
また、cdだけ入力し実行した場合は、ホームディレクトリに移動する。

他にもコマンドはありますが、基本的なコマンドについて
簡単に書いてみた。
RxSwiftで簡単なPickerView作り 

RxSwiftでPickerが簡単に作れる


``` swift
import RxSwift

class ViewController: UIViewController {

    @IBOutlet private weak var label: UILabel!
    @IBOutlet private weak var textField: UITextField!
    private let pickerView: UIPickerView = UIPickerView()
    private let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupPicker()
        bind()
    }

    private func setupPicker() {
        textField.inputView = pickerView

        let toolbar = UIToolbar(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 50.0))
        let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
        let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: nil, action: nil)
     
        //完了ボタンを押した時の動作
        doneItem.rx.tap.asDriver()
            .drive(onNext: { [weak self] (_) in
                 self?.textField.endEditing(true)
            }).disposed(by: disposeBag)

        toolbar.setItems([space, doneItem], animated: true)
        textField.inputAccessoryView = toolbar
    }

    private func bind() {
        //Pickerの中に使いたい配列ーここでは1900年〜2021年を配列にしている
        let years = (1900 ..< 2021).map { "\($0)" + "年" }

        Observable.just(years)
            .bind(to: pickerView.rx.itemTitles) { _, year in
                return year
            }.disposed(by: disposeBag)

        pickerView.rx.modelSelected(String.self)
            .map { years in
                return years.first
            }
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)

        //Pickerの初期値ーここでは2000年にしている
        self.pickerView.selectRow(100, inComponent: 0, animated: true)
    }
}
```
【GitHub】SSH鍵を設定してターミナルから操作する話〜デスクトップに頼らない〜

### GitHubデスクトップでやっていたら苦労した話

gitコマンド覚えなきゃいけないんだよな〜と思いながら後回しにし続けてデスクトップアプリからの操作に頼っていました。
先日からTypeScriptの勉強を始めたのですが教材の中で実行されているコマンドが何を意味しているのかわけがわからず、自分が今何をしているのか全くわからないまま進めてエラーで詰まりました。
ターミナルからcloneを作成しようとしたところうまくいかず、エラー文を調べてみるとSSH鍵の認証ができていない様子。

```terminal
# コマンド
% ssh -T git@github.com

# 結果
git@github.com: Permission denied (publickey).
```
AWSにデプロイした時にssh鍵の設定をしたのは覚えていたのでそれでできるものだと思い込んでいました。
色々調べてみたところ新たにssh鍵を作成してgitに設定すればいけそうだったのでやってみました。

### ターミナルで操作

```terminal
# sshに移動
% cd ~/.ssh

# ssh鍵を生成
% ssh-keygen -t rsa

# 結果
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/****/.ssh/id_rsa):
/Users/****/.ssh/id_rsa already exists.
Overwrite (y/n)?

# ファイルが作成できているか確認
% ls

# ファイルが2つ作成されている
id_rsa		id_rsa.pub

# 公開鍵をコピーしておく
% pbcopy < ~/.ssh/id_rsa.pub
```

### GitHubにアクセス

[ssh鍵の設定ページ](https://github.com/settings/ssh)

**New SSH key**をクリックして先ほどコピーしたものを貼り付けて保存。


### できているかチェック

```terminal
# コマンド
% ssh -T git@github.com

# 結果
Enter passphrase for key '/Users/****/.ssh/id_rsa':

```

ここで毎回パスフレーズを聞かれてしまってなかなか鬱陶しかったので

```
# SSH鍵をssh-agentに登録（****にはターミナルの一番最初に表示されているユーザーネームを入力）
$ ssh-add /Users/****/.ssh/id_rsa

# 登録されていることを確認する
$ ssh-add -l

```


以上でクローンが作成できました。
SSH鍵が現在自分のページだと2つ表示されているのですが、最初に登録していたものはグレーになり、今回登録したものが緑色で表示されています。
なんだか嫌な予感が若干しており、AWSにデプロイするときにssh鍵が違うんだけど？的なことになりそうですがその時はその時でまた戦おうと思います。


### 参考にさせていただきました
@shizuma様
[GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)


@shinki_uei様
[GitのSSH鍵認証で毎回パスワードを要求される](https://qiita.com/shinki_uei/items/70f8f9ae50f1b9e24dce)

ありがとうございました。
Athena(Presto) × Redashで表示する数字にカンマを入れたり￥をつけたりしたい

## 解決したかった問題
Tableで表示するときはちゃんとしていても、pivotで表示したりデータをCSVとしてダウンロードしたら1,000,000が1000000に、1.12が1.122345323みたいになっていて見づらいため直して欲しいと言われた。

正規表現を避けてきたせいもあり、地味に時間かかったのでこのような問題に時間を取られたくない人の助けになればと思いましたので書き残します。

## 解決策
まず事前に、今回は全て数字をvarchar（文字）として出力するので、tableで表示する際はEdit visualizationからTypeをNumberからTextに変えてください。そうしないと0とかになります。

一応言っておきますが、cvとかcntとかamountとかのところはちゃんと入れ替えてくださいね。このままコピペしても動きません。

### ただカンマを入れる場合

```
regexp_replace(cast(MAX(cv) as varchar), '(\d)(?=(\d{3})+$)', '$1,')
```
### 小数点を切り捨ててカンマを入れる場合

```
regexp_replace(regexp_replace(cast(MAX(round(CAST(amount AS REAL) / cv)) as varchar), '\.\d{1,}', ''), '(\d)(?=(\d{3})+$)', '$1,') 
```

### ￥をつける場合
`'¥' || `だけ。非エンジニアも見るかもしれないので一応書きました。%つけたい時も同じようにできます。

```
'¥' || regexp_replace(cast(MAX(cv) as varchar), '(\d)(?=(\d{3})+$)', '$1,')
```

### 小数点第二位まで表示したい
こんな感じでやりました。

```
round(cast(cv as real) * 100 / cnt, 2)
```

## 正規表現解説
エンジニアじゃない人は見なくても良いと思います。
正規表現ってたまに使う時があるけどなんだかんだなんとかなるためちゃんと勉強するのを怠けてしまっていたのですが、反省。ちゃんと蓄積していきたい。

`(\d)(?=(\d{3})+$)`
後ろからみて、3つの数字が後に続く一つの数字がマッチする。この時マッチする数字は一つではなく複数の場合もある。
1000だと1がマッチする。1003000だと1と3がマッチする。
`\d`で一つの数字を表す。`(\d)`カッコをつけてグループ化する。グループ化することでグループ単位で処理することができる。↑の正規表現には2つのグループがあり、2つ目の引数内の$1は1つ目のグループを指定している。

例えば、↓の例では2つのグループを作成していて、`'(\d+)([ab]) '`にマッチした文字列の2つ目のグループ（$2で2つ目のグループを指定）に3cをつけるという意味になる。

```
SELECT regexp_replace('1a 2b 14m', '(\d+)([ab]) ', '3c$2 '); -- '3ca 3cb 14m'
```
https://prestodb.io/docs/current/functions/regexp.html より

ここまで読めば、最初分からなかったとしても↓の意味がすんなりと分かるのではないでしょうか。

```
regexp_replace(cast(MAX(cv) as varchar), '(\d)(?=(\d{3})+$)', '$1,')
```

`\.\d{1,}`
.は任意の1文字という正規表現の意味もあるので.を文字として扱うためにちゃんとエスケープする。{1,}は1文字以上。+と同等。\dは数字なので、`\.\d{1,}`は.12345などの小数点以下の数字を小数点を含めて全てマッチするという意味になる。
ここでは小数点以下を消したいのでマッチした部分を''と入れ替えることで実現している。

```
regexp_replace('1,22', '\.\d{1,}', '')
```

以上です。
【kintone】kintone UI Component v1でドロップダウンを作る

こんにちは！
今回は、`kintone UI Component v1` でドロップダウンを作ってみたいと思います。

# kintone UI Component v1 の準備
`JavaScript / CSSでカスタマイズ` に
kintone UI Component v1 のCDNを追加しておきます。

CDN : `https://unpkg.com/kintone-ui-component/umd/kuc.min.js`

# ひとりぼっちのドロップダウン

まずはドロップダウンを1つ設置して、
選択した文字列を、文字列(1行)フィールドに表示するというカスタマイズアプリを作ってみたいと思います。

## アプリの準備

スペースフィールドと文字列(1行)フィールドをフォームに配置します。

| フィールド種類 | フィールド名 | フィールドコード |
|:-:|:-:|:-:|
| スペース  |  -- | spDropdown  |
| 文字列(1行)  | ドロップダウンの叫び  | drText  |


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/af61b926-f9a8-cfaf-d946-1cfac8cccc76.png)

## JavaScript

新規追加＆編集画面表示のイベントでドロップダウンが動くようにします。

```js
kintone.events.on(
  ["app.record.create.show", "app.record.edit.show"],
  (event) => {
    // コードを書くところ

  }
);
```

### ドロップダウンを設置する

こちらを参考に、ドロップダウンを作成します。

https://kintone-ui-component.netlify.app/docs/components/desktop/dropdown

ドロップダウンの`items`に選択肢をセットするのがポイントです。
※valueだけでも良いみたいです。

```js
// ドロップダウンを設置するスペースフィールドの要素を取得
const spDropdown = kintone.app.record.getSpaceElement("spDropdown");
// ドロップダウンをつくる
const drHitokoto = new Kuc.Dropdown({
  label: "一言言いたいドロップダウン",
  requiredIcon: true,
  // items にはドロップダウンの中身を書く
  items: [
    { label: "あ！", value: "あ！" },
    { label: "おなかすいた", value: "おなかすいた" },
    { label: "こんにちは", value: "こんにちは" },
    { label: "いい天気ですね！", value: "いい天気ですね！" },
    { label: "最近肩が凝っています", value: "最近肩が凝っています" },
  ],
  visible: true,
  disabled: false,
});
// スペースフィールドにドロップダウンを置く
spDropdown.appendChild(drHitokoto);
```

### ドロップダウンを選択した時のイベント

ドロップダウンの **change** イベント発生時に、
ドロップダウンで選択した値を文字列(1行)フィールドにセットします。

```js
// ドロップダウンを選択したときのイベント
drHitokoto.addEventListener("change", () => {
  const r = kintone.app.record.get();
  // ドロップダウンで選択した値を文字列(1行)フィールド（フィールドコード：drText）にコピー
  r.record.drText.value = drHitokoto.value;
  kintone.app.record.set(r);
});
```

全体的なコードは以下です。

https://gist.github.com/juridon/4a6ba290bc273c97933c0e010c8f61b4


## 動作確認＆まとめ

このような動きになったでしょうか？？

![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/3bb3def4-0441-d9bf-1dd4-2544f621ac13.gif)

次回は連携するドロップダウン作ってみたいと思います。
[個人開発]Webイベントを開催できるアプリ作りました

#初めに
[crieit](https://crieit.net/)の「１週間でWebサービスを作るイベント」というのを見て作りました。

サービスURL↓
https://eventer-work.herokuapp.com/

![スクリーンショット 2021-03-26 145453.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/3eb66c4f-e9c5-bf07-2970-8ef232ad6f8a.png)

#概要
誰でもwebイベントを開催でき、参加できるサービスです。
最優秀賞と優秀賞を一つずつ設定できるようになってます。

#使用したgem ＆ 技術
rails6.1
ruby2.7
postgresql
heroku free

```
gem 'ridgepole'
gem 'slim-rails'
gem 'html2slim'
gem 'pry-rails'
gem 'devise'
gem 'kaminari'
gem 'activeadmin'
gem 'rack-attack'
gem 'rails-i18n'
gem 'devise-i18n'
gem 'devise-i18n-views'
gem 'carrierwave'
gem 'redcarpet'
gem "rouge"
```

# まとめ
今回のサービスは新しい技術は使ってないので、ハマったことも困ったこともありません。
ゆえに書くことが本当にないのでここで終わりにします。
内容が過去一薄いですが許してください。
Blueprintインストールメモ

マークダウンをhtmlに変換するaglioのインストールに失敗したためメモ

```sh
$ npm i -g aglio

EACCES: permission denied, mkdir './cache'
```
こんな感じのメッセージがでた。権限周り？。



#環境
```sh
$ cat /etc/*release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
Amazon Linux release 2 (Karoo)
```


#npmインストール
参考：https://qiita.com/rakuraku0615/items/dd5bcc1f8641c5bbb091

```sh
# リポジトリの取得
$ curl -sL https://rpm.nodesource.com/setup_8.x | sudo bash -

# nodejsのインストール
$ sudo yum install -y nodejs
```

#aglioインストール

```
#root権限でnpm install
$ sudo npm install -g aglio --unsafe-perm=true --allow-root

#変換してみる
$ aglio -i test.apib -o test.html
$ ls
test.apib  test.html
```
rootでnpm installができてないのが原因でした。完。
swiftでif文をスマートに書こう

if文の簡単なリファクタの話

変更前

``` swift
///ここのboolに通信とかで何かしらの真偽値が入る前提
let bool: Bool = .init()
var str: String = ""

if bool == true {
    str = "hoge"
} else {
    str = "hogehoge"
}
```

変更後

``` swift
let bool: Bool = .init()
var str: String = bool ? "hoge" : "hogehoge"
```
AWS Autoscaling

#Auto Scalingとは
希望する量と現在起動している台数(EC2インスタンスなど)の差を監視し、合致するようにリソース(EC2インスタンスなど)を増減する。

増減には3つのパターンがある
**①そのまま維持
②スケールアウト(希望する量＞現在起動中の台数)
③スケールイン（希望する量＜現在起動中の台数）**

![スクリーンショット 2021-03-26 14.12.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/e8806689-334e-5b2a-de54-9138643b8550.png)



#使用方法
**「サイズ維持」**
希望する台数は固定、台数減ると検知して減った分だけ台数追加する。
例）希望する台数が４台の場合、障害により１台減るとその差を検知して１台追加する。

![スクリーンショット 2021-03-26 14.21.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/3535afc1-ced5-66b2-36a8-cf4b9458fdf0.png)




**「手動スケーリング」**
希望する台数を手動で変更する。サイズの維持も引き続き行われる。

**「自動スケーリング」**
様々な条件に応じて希望する台数が動的に変化する。設定方法として様々なスケーリングポリシー(CPU使用率に応じてAutoScaling実行など)が提供されている。

![スクリーンショット 2021-03-26 14.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1096361/694b7b62-e806-c198-1fa7-73598dc0072e.png)



**「AutoScaling使用時のインスタンスの分散の特徴」**
使用できるアベイラビティゾーンで、均等にインスタンスを配置しようとする。
スケールアウトするときは、インスタンスが最も少ないアベイラビリティゾーンに新規起動する。

#スケーリングの種類
##**「動的スケーリング-ステップスケーリング-」**
１つのメトリクスに対して複数のスケーリング調整値を指定可能
細かい設定が可能
**ウォームアップ期間**：新しく起動したインスタンスがサービスを開始できるようになるまでに要する時間
**なぜ設定するのか？**
設定することで、スケールアウトの時に前のスケールアウトが終わっているかを判断してくれる。
デフォルト値は**300秒**

##**「動的スケーリング-ターゲット追跡スケーリング-」**
１つのメトリクスに対して、単に目標値を設定するのみ。
例）CPU使用率を40％に維持してほしいなど
目的値に満たすように自動的にリソースが調整される。
**スケールアウト用・スケールイン用のアラームが自動的に作成され、アラームがアラーム状態になった時にスケールされる。**

##**「予測スケーリング」**
２週間分のメトリクスを分析し、次の2日の今後の需要を予測
24時間ごとに、次の48時間の予測値を作成し、キャパシティの増減をスケジューリング
予測の基準時刻は0時

##**「スケジュールスケーリング」**
定期的なスケジュールを指定可能
最小キャパシティと最大キャパシティのいずれかあるいは、両方を指定可能



#オプションお勧め
**EC2でのスケーリングオプションのお勧め**
予測スケーリングで、大体のキャパシティ増減の事前準備
実際の負荷に対してターゲット追跡で補充する

**EC2以外でのスケーリングオプションお勧め**
ステップスケーリングおよびスケジュールスケーリング使用
【Rails】DockerでRails6起動時のエラー：An error occurred while installing mimemagic (0.3.9), and Bundler cannot continue.

個人メモです。

DockerでRubyのAlpineイメージを使って、Rails6を起動使用とした時に以下のエラーが発生。

```
An error occurred while installing mimemagic (0.3.9), and Bundler cannot continue.

Bundler could not find compatible versions for gem "mimemagic":
  In Gemfile:
    mimemagic (~> 0.4.0)

    rails (~> 6.0.3, >= 6.0.3.4) was resolved to 6.0.3.4, which depends on
      activestorage (= 6.0.3.4) was resolved to 6.0.3.4, which depends on
        marcel (~> 0.3.1) was resolved to 0.3.3, which depends on
          mimemagic (~> 0.3.2)
```

mimemagicというパッケージでエラーが発生している。


<br>
##対処法

RubyのAlpineイメージではなく、普通のRubyイメージを使う。

Dockerfileの`FROM ruby:3.0.0-alpine3.13`と`apk` の組み合わせを、`ruby3.0.0`と`apt-get`に変更。


```Dockerfile:dockerfile
FROM ruby:3.0.0

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client

# yamlをインストール
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn

RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

#コンテナ起動時に毎回実行される処理
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

#イメージからコンテナを作る（run）時に実行する処理
CMD ["rails", "server", "-b", "0.0.0.0"]
```
"If not"と"unless"の違いとは? 〜イングリッシュネイティブの本音〜

初めまして！プログラミング初学者のsawataです。

バックエンドエンジニアを目指して日々学習をしています。
日々学習を進める中で気になったことを調べては発信して行こうと思います！

# いきなりクイズ

```ruby
#1
if a =! b
end
#2
if not a == b
end
#3
unless a == b
end
```

上記のような条件分岐を使う場面。

この3つの選択肢の内、2つの条件式は同じ意味ですが、一つは仲間外れです。

さて、それは何番でしょうか？



(※正解は下にあります...)
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
    |
### 正解は...
```ruby
#1
if a =! b
end
```

### でした！



# 解説

わかりやすくするために文章で書いてみます。

```ruby
#1
if a =! b
```
if "a is not b" is true

```ruby
#2
if not a == b
```
if "a is b" is not true

```ruby
#3
unless a == b
```
if "a is b" is false

こうしてみると#2と#3の選択肢が同じことがわかりやすいですよね。
逆に、#1は二つの条件式の真反対を意味しています。

# 疑問の種

今日コードを書いている中で、この#1の条件式と#3の条件式が直感的に同じように感じました。

しかし実際、それぞれ記述してみたら、思うような動作が得られなかったので今回の記事を作ってみました。

ただここでもう一つ疑問が生まれました。。。

#### "if not" と "unless"は全く同じモノなのか？

"if not"と"unless"にもどこかニュアンスを感じたので、それについて調べていたら以下のディスカッションを発見。

https://github.com/rubocop-hq/ruby-style-guide/issues/329

英語のネイティブスピーカーの方々が、この二つの表現にどのような違いを感じているのか。について話されているでした！

内容のまとめとしては、

- **条件式の中身がfalseになると予測する場合は"unless"を、trueになると予測する場合は"if not"を使用する。**

- **"if not"を使う方が例外として条件式を立てているようで、自然に感じる。**

というような意見がありました！

# まとめ

結論、"if not"と"unless"はプログラム上では同じ役割を持っています。

ただこの二つの表現をうまく使い分けることで、自分以外の人(特にイングリッシュネイティブの方)からみたコードの可読性を高めることが出来るのではないのでしょうか...？

英文法にも詳しくなれるプログラミングってすごい。。。今日の学びです。
レインボー攻撃

#レインボー攻撃
ハッシュ値から、もとのデータ（パスワード）を割り出そうとする方法。<br>ハッシュ値はハッシュ関数から生成される戻り値のことで、データをハッシュ関数に入力すると<br>ランダムに値が主力される。<br>似た文字でも、ぜんぜん違う値になって、もとのデータを再現はできない。<br>なので、セキリュティにむいている。<br>ハッシュ関数にもいろいろな種類があるらしい。<br>
Windows10 でネイティブ IPv6 接続時で不要なインターフェイスを無効化

#お約束
全て管理者権限で実行する事😏
パワーシェルでも実行は可能

IPv6 過渡期で IPv4 環境しか広域網への接続が出来なかった頃（執筆時点でもネイティブが少数だが）トンネリング技術として幾つか存在しているが、デュアルスタック（IPv4とIPv6が双方で広域網に接続）環境では、その変換が通信速度低下に繋がっている（事もある）。

Windows のシェルコマンド netsh で制御可能なので、無効化と状態参照のワンライナーを書き記しておく。

* [Teredo](https://www.nic.ad.jp/ja/basics/terms/teredo.html)
* [ISATAP](https://www.nic.ad.jp/ja/newsletter/No37/0800.html)
* [6to4](https://www.nic.ad.jp/ja/newsletter/No37/0800.html)

この上記三つの仮想インターフェイスが Windows XP の頃から実装されていて条件が整うと各仮想インターフェイス経由で IPv6 の通信を開始する。
当然ネイティブでの通信が高速なのは当たり前（詳細は検索サイトからどうぞ）なので、無効化して高速な通信を確保する。

#Teredo インターフェイスの無効化
```text
# netsh int ter set sta dis
```
#Teredo インターフェイスの状態確認
```text
# netsh int ter sho sta
```
#ISATAP インターフェイスの無効化
```text
# netsh int isa set sta dis
```
#ISATAP インターフェイスの状態確認
```text
# netsh int isa sho sta
```
#6to4 インターフェイスの無効化
```text
# netsh int 6to set sta dis
```
#6to4 インターフェイスの状態確認
```text
# netsh int 6to sho sta
```

#おまけ
netsh のサブコマンドは頭三文字のみで省略可能

|省略形|全文|
|:--|:-------:|
|int|interface| 
|ter|teredo|
|sta|state|
|dis|disabled|
|sho|show|
|isa|isatap|
|6to|6to4|

[出典元](https://www.dell.com/support/kbdoc/ja-jp/000147546/%E3%82%A8%E3%83%A9%E3%83%BC-%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E8%A7%A3%E6%B1%BA-microsoft-teredo-tunneling-pseudo-interface-%E3%81%93%E3%81%AE%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E3%81%AF%E9%96%8B%E5%A7%8B%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93-%E3%82%B3%E3%83%BC%E3%83%8910)
記事投稿および書き方（初心者向け）

# はじめに

Qiitaはプログラミング学習関連のアウトプットをするのに最適です。
初心者の方が記事を投稿する際の書き方(Markdown記法）について
主に初心者の方が使用する頻度が高いと思われる記法を（私のアウトプットも含め）
分かりやすいようにまとめました。

:point_up: より詳細のMarkdown記法については[Markdown記法チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)を参照して頂けばと思います。


# Markdown記法の書き方


## 見出し

文頭に`「#」`を付けることで見出しができます。
見出しの大きさは、文頭の「#」の数で変更することができます。

>#見出し1
>\#見出し1
>###見出し3
>\##＃見出し3
>#####見出し5
>\#####見出し5


## 引用

文頭に`「>」`をつける。
「>」の数に応じて入れ子の表現ができます。
>引用1
>>引用2
>>>引用3


## リスト

文頭に`「*」`、`「-」`、`「+」`のいずれかを入れる。
要点をまとめる際に便利な方法です。

:raised_hand: `「*」`、`「-」`、`「+」`の後にはスペースが必要です。

* リスト1
- リスト2

数字を入れたい場合
文頭に`数字.`を入れる.

:raised_hand: `数字.`の後にはスペースが必要です。


1.
2.


## インラインコード表現

文字を`` `バッククオート` ``で囲むと`インラインコード`での表現ができます。


## コードを埋め込む

```` ```バッククオート（３つ）``` ````でコードを囲むと埋め込むことができます。

```
<h1>Hello World</h1>
```


## シンタックスハイライトを付ける

シンタックスハイライトとはコードに色を付けてあげることです。

```` ```バッククオート``` ````のすぐ後ろに`言語名`を入れるとシンタックスハイライトを付けれます。

```html
<h1>Hello World</h1>
```


## ファイル名を挿入する

```` ```バッククオート``` ````の後に`：ファイル名`を入れると表示できます。

``` :index.html
<h1>Hello World</h1>
```


## リンクの挿入

リンクの挿入は`[リンクテキスト]（URL）`と記載すると表示できます。

```:例
[Qiita](https://qiita.com/)
```

[Qiita](https://qiita.com/)


## 参考記事


* Qiita support
 *  [良い記事を書くためのガイドライン](https://help.qiita.com/ja/articles/qiita-question-guideline)
 
* Qiita内 記事
 * [Markdown記法チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
Next.jsでの実装上の注意点

# 概要
Next.jsを使ってフロントを実装した際に気になった（注意した）ものをまとめたものです。
用語の説明が多いですが、実際に実装した例も示しています。

# useStateについて（ステートフック）

状態を保持したい時に用いる。stateが作成されそれを変更することで動作に応じた状態が保存される

> フックとは関数コンポーネント内から React の機能に「接続する (hook into)」ための関数のことです。フックの名前は必ず use から始まり、他にもまだ説明していない様々なフックがあります。

## useStateを呼ぶと何が起こるのか

`state 変数`が宣言される

## 引数は？

一つだけ。stateの初期値。

## 何を返す？

`現在のstate`とそれを更新するための関数（これを通常、`set<stateの名前>`とする）

```jsx
const [count, setCount] = useState()
```

## state の呼び出し

クラス内で現在のカウント値を表示したい場合は`this.state.count`を呼び出す

関数内では直接`count`を使うことができる

## *分割代入について

reactでは`[]`を使うことで分割代入が可能になる

# map()関数について

配列の中身をいい感じに使えるようにする関数

# 関数の違い

reactには、`function()`とアロー関数（`() ⇒ {}`）の二つがある

[JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 - Qiita](https://qiita.com/suin/items/a44825d253d023e31e4d)

# 環境変数の導入

[Next.jsの環境変数設定まとめ - Qiita](https://qiita.com/KZ-taran/items/64cad61096cf45f18c24)

# React.FCについて

typescriptのチェックを活かす為に`React.VFC`の方がいい

[【TypeScript】React.VFCとは何ぞや - Qiita](https://qiita.com/tttocklll/items/c78aa33856ded870e843)

# コンポーネントの定義方法

[Reactでクラスコンポーネントより関数コンポーネントを使うべき理由5選](https://tyotto-good.com/blog/reaseons-to-use-function-component)

# マテリアルデザインについて
本パッケージはCSRを前提にしているためSSRの場合は`_app.js`と`_document.js`にCSSの設定を記述する必要がある。[実装例](https://github.com/mui-org/material-ui/tree/master/examples/nextjs/pages)

[React + Material-UIで管理画面を作成してみた | DevelopersIO](https://dev.classmethod.jp/articles/react-material-ui/)

[](https://fastcoding.jp/blog/all/webdesign/material-design3/)

# Import の中括弧について

[Reactで{}(curly bracket or 中括弧 or 波括弧)をimportで使う理由 - Qiita](https://qiita.com/taro_kawasaki/items/767dbe84b7eb58111eb3)

---

# preventDefaultについて（js）

本来作動する機能（onClickやonSubmit）を制限すること

[JavaScriptのpreventDefault()って難しくない？preventDefault()を使うための前提知識 - Qiita](https://qiita.com/tochiji/items/4e9e64cabc0a1cd7a1ae)

# useEffect

コンポーネントに副作用を与えるためのhooks

定義した関数コンポーネントが呼び出された時に実行される

第二引数の配列の中身がトリガー。空の配列の場合初回レンダリングのみ実行される

[useEffect完全ガイド](https://overreacted.io/ja/a-complete-guide-to-useeffect/)

# undefined と nullの違い

[null と undefined の違い - Qiita](https://qiita.com/shuhei/items/199281e07925d24059d5#:~:text=null%20%E3%81%AF%E4%BD%95%E3%81%8B%E3%82%92,%E3%81%9F%E3%81%A0%E4%BD%95%E3%82%82%E3%81%AA%E3%81%84%E7%8A%B6%E6%85%8B%E3%80%82)

# OGP実装

metaタグを追加すればいい。

[選ばれたのは Next.jsでした - Next.jsによるServer Side OGP ⽣成 / Next.js was chosen - Server Side OGP generation with Next.js](https://speakerdeck.com/line_developers/next-dot-js-was-chosen-server-side-ogp-generation-with-next-dot-js?slide=25)
cloudtrail と config の違い

## 勉強前イメージ

どっちも監査とかで使われるとかそんなイメージ

## 調査

### AWS CloudTrail とは

AWSサービスを記録し、いつ・だれが・何をしたのか を残すサービスで
AWSアカウントで発生したAPIコールの記録を行っています。
イベント履歴と証跡情報の2種類の項目のリソースの追跡を行うことができます

詳細は [こちら](https://qiita.com/miyuki_samitani/items/d2b3164fc99ee29a1ccd) をご確認ください

### AWS Config とは

AWSリソースの設定がモニタリングされ、構成情報の記録や監視を行ったりしてくれます。
リソースがガイドラインに沿っているかの確認や
リソースの変更をモニタリングして、変更があれば通知を行うなどしてくれます。

詳細は [こちら](https://qiita.com/miyuki_samitani/items/a19023d5e974c562a3bd) をご確認ください


### 違い

ざっくり簡単にいうと以下

- CloudTrail : `ユーザの操作に対して` モニタリングをし、不正なことが起こってないかを確認する
- Config : `リソースに対して` モニタリングをし、決定されたガイドラインに沿ってるかの確認を行う

## 勉強後イメージ

どっちもガイドラインやら監査やらに沿ってるかの確認してるなーとは思ってたけど確認する対象が違うのか。
cloudtrailはユーザの操作。 configはリソースに対して確認してるのか。

## 参考

- [AWS Config のよくある質問](https://aws.amazon.com/jp/config/faq/)
- [AWS Config でAWSリソースやソフトウェアの設定履歴を保存し、コンプライアンス対策やセキュリティの強化を！
](https://business.ntt-east.co.jp/content/cloudsolution/column-97.html#:~:text=AWS%20Config%E3%81%8C%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AE,%E3%82%92%E8%93%84%E7%A9%8D%E3%80%81%E6%A4%9C%E7%B4%A2%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82)
- [AWS Cloud TrailとAWS Configの違いは何ですか？](https://jp.quora.com/AWS-Cloud-Trail-to-AWS-Config-no-chigai-ha-nani-desu-ka)