OmniAICreator/Qiita-1.07M huggingface dataset:
RailsのEnumについて便利な使い方を知ったのでメモ

## enumの基本的な使用方法

enumとは、「名前と対応する数値を紐づけて管理するもの」だと捉えています。
使用方法は、`app/models/users.rb`とかのファイルに以下のように定義するだけ。

例1

```ruby
  enum user_type: {
    admin: 1,
    nomal: 2,
    developer: 3
  }
```

例2

```ruby
  enum month: {
    january: 1, # 1月
    february: 2, # 2月
    march: 3,  # 3月
    april: 4,  # 4月
    may: 5, # 5月
    june: 6,  # 6月
    july: 7,  # 7月
    august: 8, # 8月
    september: 9, # 9月
    october: 10, # 10月
    november: 11, # 11月
    december: 12  # 12月
  }
```

この時、user_typeカラムやmonthカラムには`integer`型を指定してテーブルを作成しましょう。

ただ、このままではenumの恩恵は十分に受けられていませんね。。。

## 便利な使い方

自分が便利だと思っただけで、他の開発者の方々にとっては普通なのかもしれません。

### 該当データを取得できる

以下のユーザーが登録されていると仮定します。

```ruby
[#<User id: 1, username: "testuser01", name: "テストユーザー01", user_type: "admin">,
 #<User id: 2, username: "testuser02", name: "テストユーザー02", user_type: "developer">,
 #<User id: 3, username: "testuser03", name: "テストユーザー03", user_type: "normal">,
 #<User id: 4, username: "testuser04", name: "テストユーザー04", user_type: "developer">,
 #<User id: 5, username: "testuser05", name: "テストユーザー05", user_type: "admin">,
]
```

ユーザーテーブルからdeveloperのみを取り出したいときは、どのようにしますか？
よくやってしまうのは、以下のように`where`を使用した書き方でしょうか？

```ruby
User.where(user_type: "developer")
```

enumを使用していなければwhereでも良いですが、enumを使用すると以下のように書くことができます。

```ruby
# ユーザーテーブルから開発者ユーザーだけを取得
p User.developer

#=>
[#<User id: 2, username: "testuser02", name: "テストユーザー02", user_type: "developer">,
 #<User id: 4, username: "testuser04", name: "テストユーザー04", user_type: "developer">]


# ユーザーテーブルから管理者ユーザーだけを取得
p User.admin

#=>
[#<User id: 1, username: "testuser01", name: "テストユーザー01", user_type: "admin">,
 #<User id: 5, username: "testuser05", name: "テストユーザー05", user_type: "admin">]
```

### true or falseで値を返せる

ユーザーのタイプによって条件分岐させたい場合にも使えます。

```ruby
# 以下のユーザーが登録されていると仮定します。
#<User id: 1, created_at: "2023-08-25 15:00:00.000000000 +0900", updated_at: "2023-08-25 15:00:00.000000000 +0900", username: "testuser01", name: "テストユーザー01", user_type: "admin">

p User.find(1).admin?        #=> true
p User.find(1).normal?       #=> false

# deviseを導入している場合には、、、
p current_user.admin?        #=> true
```

## まとめ

enumを定義することで、冗長な表現を簡単に書くことができるようになりそうです。

個人的には`where`を使用せずにデータ取得が可能になる点については実装する時に時間短縮になるかなと思います。
電子工作メモ - 74HC193

# 74HC193

- 同期型 Up-Down カウンター
- ピン
  左下から反時計回りに、1-16

|Pin|端子名|用途|
|:--|:--|:--|
| 1| B|プリセット2桁|
| 2|QB|出力2桁|
| 3|QA|出力1桁|
| 4|COUNT DOWN|クロックダウン|
| 5|COUNT UP|クロックアップ|
| 6|QC|出力3桁|
| 7|QD|出力4桁|
| 8|G |グランド|
| 9|D|プリセット4桁|
|10|C|プリセット3桁|
|11|$\overline{LOAD}$|プリセット有効|
|12|$\overline{CARRY}$|桁上り（上位の桁のCPUに接続する）|
|13|$\overline{BORROW}$|桁下がり（上位の桁のCPDに接続する）|
|14|CLR|リセット|
|15|A|プリセット1桁|
|16|Vcc|電源5V|

|COUNT<br>UP|COUNT<br>DOWN|LOAD|CLR|用途|
|:--:|:--:|:--:|:--:|:--|
|x|x|x|H|リセット（値が0になる）|
|x|x|L|L|プリセット（初期値をセットする）|
|↑|H|H|L|カウントアップ|
|↓|H|H|L|何もしない|
|H|↑|H|L|カウントダウン|
|H|↓|H|L|何もしない|

- [アップダウンカウンタの制作 基礎編](https://www.marutsu.co.jp/select/list/detail.php?id=149)
- [アップダウンカウンタの制作 実験編](https://www.marutsu.co.jp/select/list/detail.php?id=148)
- [アップダウンカウンタの制作 設計編](https://www.marutsu.co.jp/select/list/detail.php?id=147)
- [アップダウンカウンタの制作 制作編](https://www.marutsu.co.jp/select/list/detail.php?id=145)
HTTPプロトコルのバージョンについて

### HTTP/0.9
- 最初のHTTPプロトコルで、非常に基本的な機能しかありません。
- GETリクエストのみをサポート。
- レスポンスヘッダーがない。

### HTTP/1.0
- HTTPヘッダーの導入。
- GET、POST、HEADなどの追加のメソッドをサポート。
- キャッシング、コネクションの制御、MIMEタイプのサポート。

### HTTP/1.1
- パイプライニングと持続的なコネクション（Keep-Alive）をサポート。
- チャンク転送エンコーディング。
- より効率的なキャッシングと帯域幅の利用。
- 追加のHTTPメソッド（OPTIONS、PUT、DELETEなど）。
- ホストヘッダーの導入。

### HTTP/2
- マルチプレクシングと並列処理をサポート。
- ヘッダー圧縮。
- サーバープッシュのサポート。
- バイナリプロトコル。

### HTTP/3
- QUICプロトコルを使用。
- TCPではなくUDPを基盤とする。
- コネクションの確立が高速。
- パケットロスに対する改善。
git cloneでremote: Support for password authentication was removed on August 13, 2021.エラーが出た時の解消法

## 背景

久々に自分のリポジトリをgit cloneしようとしたら以下のエラーが出ました。

```
$ git clone https://github.com/{ユーザー名}}/{リポジトリ名}.git
Cloning into '{リポジトリ名}'...
remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/github.com/{ユーザー名}}/{リポジトリ名}.git
```

おや？認証方式が変わったとかっぽい？

ってことでググってみたところ、github上でtokenを発行しないといけないようです。

## 作業環境

|名称|型番・スペックなど|
|---|---|
|Operating System|Windows 10 Home 64-bit
|System Manufacturer|Dell Inc.
|System Model|XPS 8920
|Processor|Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz (8 CPUs), ~3.6GHz
|Memory|32768MB RAM|


## トークンの生成

右上の自分のアイコンをクリックし、下の方にある「Settings」ページへ進んでください

![111無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/5b39ce60-6086-23bf-32b7-d4197af46d1e.png)

次に左下の「Developer settings」をクリックしてください。

![222無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/c244c924-df88-44fd-7d80-9a6498d0568c.png)

「Developer settings」ページの左メニューの「Personal access tokens」をクリックし、「Tokens(classic)」を選択してください。

![333題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/26f585a4-1696-de0f-e6ca-1eca6e682529.png)


右上に「Generate new token」というメニューがあるので、そこの「Generate new token(classic)」を選択してください。

![666無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/29c67c0a-c756-bcfa-cb1e-adacfbf3f8ed.png)

出てくるメニューが多いですが、今回はひとまずシンプルに以下の丸が付いてるところだけ設定してしてください。
Expiationの期間は任意で、Select scopesは今回はrepoのみにしました。

![444無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/127005fe-db97-5ce3-e411-f2c86c4c0d5a.png)

<b>ここで、表示された必ずトークンをコピーして保存しておいてください。<b/>

これで生成して、最後git cloneをしてみましょう。

```
$ git clone https://github.com/{ユーザー名}}/{リポジトリ名}.git
Cloning into '{リポジトリ名}'...
remote: Enumerating objects: 21, done.
remote: Counting objects: 100% (21/21), done.
Receiving objects: 100% (21/21), done.13)Receiving objects:  71% (15/21)
remote: Compressing objects: 100% (13/13), done.
Resolving deltas: 100% (5/5), done.16 (delta 3), pack-reused 0
```

いけました！
この時、途中でトークンを入力するウィンドウが出てきました。そこにトークンを入力すればOKです。
git pullした後にgit logで自分のcommit履歴が確認出来なくなった

##### ブランチAを切って作業、別ブランチBに移動した後そこで変更分commit＆そのままリモートブランチをpullしコンフリクト発生の多重事故を起こしました。
##### 変更分commitしたしgit resetで元に戻せるよな！？の気持ちでいましたが、git logで確認すると己のコミット履歴は空の彼方でした。勿論ブランチAに戻っても元の姿なんてどこにもない。

## 解決方法

`git reflog`

で自分のコミット履歴を探す＆左端のIDをコピー

`git checkout [ID]`

で無事帰ってこれました。
OpsRamp ワークフローのSub Process (expanded)について

本記事では、OpsRamp ワークフローのSub Process (expanded)について説明します。

# 概要
Sub Processは、階層的なプロセスフローの設定を可能にします。Multi Instanceと組み合わせて使用することにより、より高度なプロセスフローを可能にします。
[Sub Process](https://docs.opsramp.com/solutions/remediation-automation/process-automation/process-definitions/processdef-reference/#sub-process-expanded)

![workflow.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/9ff3dcfb-4b1d-ebdc-44cb-57857c594a78.png)


# 注意点
Sub Processには、以下の注意点があります。
- 開始イベントには、none-startイベントのみ使用可能です。
- endイベントが必要になります。(Sub Process内で定義するプロセスフローを完結させる必要があります。)
- Sub Process内で定義された変数をMain Processで使用することができません。

# 使用例
下記記事を参照ください。
[OpsRamp ワークフローのParallel Multi Instanceについて](https://qiita.com/vistanet-kh/items/6f2e2d60a0797c73259f)


---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
共有 GPU メモリの検証コード

## Stable Diffusion WebUI AUTIMATIC1111 で共有メモリ
というコメントが GitHub に上がっているのをみて、
そもそも
Windows(WSL2)
\+ CUDA
\+ Python
\+ PyTorch
で共有メモリは確保できるのか？
そんな疑問から 30年ぶりぐらいにコードしてみた 元assembler屋です。

参考資料は以下です。2015年ぐらいに電子書籍で買ってたら、今(2023現在)古本がすごい値上がりしてますね。

参考文献
[CUDA C プロフェッショナル プログラミング
](https://book.impress.co.jp/books/1115101001)

### CUDA で GPU を確保
GPU のメモリを確保して、20秒後に開放する。
(が、しかし解放しない てきとーに Ctrl+C で終了してください)
gpumem01.cu
```c
#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

#define SIZE (1024 * 1024 * 1024)

__global__ void kernel(int *data, int *clockRate) {
  int idx = blockIdx.x * blockDim.x + threadIdx.x;
  data[idx] = idx;
  clock_t start = clock64();
  clock_t now;
  for (;;) {
    now = clock64();
    clock_t cycles = now > start ? now - start : now + (0xffffffff - start);
    int rate = *clockRate;
    double seconds = cycles / (double)rate;
    if (seconds >= 20) {
      break;
    }
  }
}

int main() {
  int *host_data;
  int *device_data;
  int *device_clockRate;
  size_t bytes = SIZE * sizeof(int);
  host_data = (int*)malloc(bytes);
  cudaMalloc(&device_data, bytes);
  cudaMalloc(&device_clockRate, sizeof(int));
  cudaDeviceProp prop;
  cudaGetDeviceProperties(&prop, 0);
  int clockRate = prop.clockRate;
  cudaMemcpy(device_clockRate, &clockRate, sizeof(int), cudaMemcpyHostToDevice);
  dim3 block(32);
  dim3 grid((SIZE + block.x - 1) / block.x);
  kernel<<<grid, block>>>(device_data, device_clockRate);
  cudaDeviceSynchronize();
  cudaMemcpy(host_data, device_data, bytes, cudaMemcpyDeviceToHost);
  for (int i = 0; i < SIZE; i++) {
    printf("%d ", host_data[i]);
    if ((i + 1) % 16 == 0) printf("\n");
  }
  printf("\n");
  free(host_data);
  cudaFree(device_data);
}
```
### CUDA で 共有メモリ 4GiB 確保して20秒後に開放する。
(なぜかちゃんと20秒がうごいて解放しる)
sheardmem_20sec.cu
```C
#include <stdio.h>
#include <cuda_runtime.h>
#include <unistd.h>

__global__ void kernel(int *array)
{
    // modify the array
}

int main()
{
    int *array;
    // allocate 1GB of unified memory
    cudaMallocManaged(&array, 1024*1024*1024*sizeof(int));
    // launch kernel to modify the array
    kernel<<<1, 1>>>(array);
    // synchronize device and host
    cudaDeviceSynchronize();
    // print the result
    printf("array[0] = %d\n", array[0]);
    // wait for 20 seconds
    printf("Waiting for 20 seconds...\n");
    sleep(20);
    // free the memory
    cudaFree(array);
}

```

### Python で確保
似たようなことをやる。
gpu02.py
```Python
f = open("test.txt", "w+b")

f.seek(2 * 1024 * 1024 * 1024 - 1) # 2GB - 1バイト
f.write(b"\x00")
f.flush()

import mmap
m = mmap.mmap(f.fileno(), 0)

m[0:4] = b"abcd"

print(m[0:4])

import torch # PyTorch ライブラリをインポートする
device = torch.device("cuda")
g = torch.cuda.HalfTensor(2 * 1024 * 1024 * 1024 // 2).to(device)

import time
time.sleep(20)
del g
m.close()
f.close()
```

以上。

参考文献
[CUDA C プロフェッショナル プログラミング
](https://book.impress.co.jp/books/1115101001)[YouTube 動画リンク](https://youtu.be/1Il2Tq3NsNQ)
unless は assert の代わりと思うとわかりやすい

# unlessはいつ、どう使う？
rubyには条件分岐のために `if` 式があります。（文ではない）

`if` 式は条件が真である場合をひっかけるときに使用するのは皆さんご存知の通りです。

```ruby
if (true_condition) {
  ...
}
```

`if` 式に対して `unless` 式も存在しており、条件が偽である場合をひっかけます。

```ruby
unless (false_condition) {
  ...
}
```

なので

```ruby
if (condition) {
  ...
}
```
と
```ruby
unless (!condition) {
  ...
}
```
は等価であり相互に書き換え可能です。

さて、この `if` 式と `unless` 式はどう使い分けをすれば良いでしょうか。
そのヒントがC言語の `assert` マクロにあります。

## C言語の assert マクロ
C言語には ANSI 標準の `assert` マクロがあって、式が `0`（偽）であった場合に処理をそこで終了する機能を持っています。

```C
int main(void)
{
  int a = 2, b = 5, c;
  
  c = a + b;
  assert(c == 7); // c が 7 ではなかったら終了
}
```

要は「絶対真になるはず」という条件を指定しておいて、万が一そうで無い状況が発生した場合に（異常終了という形で）検知できるようにするためのデバッグ用マクロです。

単純な仕組みながら、こんなはずではなかった。というバグを捉えるのに非常に有用なマクロです。

## unless は assert の代わりとして使うべし
ruby に `assert` はありませんが、 `unless` をその代わりと思うとその使い道がはっきりします。

先程の例をrubyのコードに書き換えてみましょう。

```ruby
def main
  a = 2, b = 5

  c = a + b
  raise AssertError unless(c == 7) # c が 7 ではなかったら終了
end
```

`unless` で真であるはずの `c == 7` という条件が満たされなかった場合に例外を raise します。

`if` にすると、条件式が反転しちゃいますね。条件式に否定が入るのは混乱の元なので避けたいところです。

```ruby
  raise AssertError if(c != 7) # c が 7 ではなかったら終了
```

`unless` は `assert` の代わりと考えるとこちらのほうがわかりやすいですよね。

## 実際の unless のわかりやすい使い方
メソッドやループの最初で（真であるべき）前提条件をチェックする（いわゆるガード節）ために使いましょう。

非常に恣意的な例ですが、メソッドの引数が偶数であることを期待している場合はこんな風に書けます。
```ruby
def even_only(n)
  return unless n.even? # 偶数じゃなかったら終了

  ...
end
```

ループの場合で、要素が偶数じゃなかった場合はスキップするという場合はこんな風に書けます。
```ruby
def process_even_only(ns)
  ns.each do |n|
    next unless n.even? # 偶数じゃなかったらスキップ

    ...
  end
end
```
（この場合は `ns.reject(&:even?).each` という書き方もありですが ）

もし、これを `if` で書くと
```ruby
  return if !n.even? # または n.odd? だけど、どちらもわかりずらい。
```
となってしまいます。わかりずらいですね。

## 上手に unless を導入しよう
全ての道具にはそれぞれ適切な使い方があります。
せっかくあるものは有効に活用していきたいものです。

もしチームの文化的に `unless` に慣れていなくて、いきなり使うのを躊躇するのであれば、意図をコメントとして追加しておくと良いでしょう。
Mermaidのススメ

僕は成果物を**Mermaid**で作ることが多いです。

Mermaidとは、フローチャートにガントチャート、シーケンス図、クラス図、状態遷移図やER図など、エンジニアがよく使う様々な図表をMarkdown記法で描けるライブラリです。
QiitaやGitHub、Notionも対応しているのでご存知の方は多いと思います。

例えば**シーケンス図**はこんな感じに描けます。
（ちなみにこれは、Amazon Kinesis Data Firehoseが受信し別のLambdaで変換されたCSVファイルを読んでAWSのDMSタスクで扱える形式に変換するところまでを描いてみたもの）

```mermaid
sequenceDiagram
participant SRC as S3 BUCKET<br>device-data
participant LF as lambda_function.py
participant CSV as csv_data.py
participant MD as models.py
participant SV as services.py
participant TGT as S3 BUCKET<br>sensor-data

SRC ->> +LF: ObjectCreated<br>/transform

Note over LF, CSV: sensor
LF ->> +CSV: get_as_sensor_data
CSV ->> CSV: convert
CSV -->> -LF: sensor_data

Note over LF, SV: foobar
LF ->> +CSV: get_as_foobar_data
CSV ->> +MD: sensor_no
MD ->> +SV: connection
SV ->> -MD: close
MD -->> -CSV: id, sensor
CSV -->> -LF: foobar_data
LF ->> TGT: Upload sensor_data {TARGET_OBJ_KEY}/YYYYMMDDHHMMSS.csv
LF ->> TGT: Upload foobar_data {TARGET_OBJ_KEY}/YYYYMMDDHHMMSS.csv
LF ->> -SV: commit
```

そしてこれが、上記シーケンス図のソースコードです。

```markdown:シーケンス図
sequenceDiagram
participant SRC as S3 BUCKET<br>device-data
participant LF as lambda_function.py
participant CSV as csv_data.py
participant MD as models.py
participant SV as services.py
participant TGT as S3 BUCKET<br>sensor-data

SRC ->> +LF: ObjectCreated<br>/transform

Note over LF, CSV: sensor
LF ->> +CSV: get_as_sensor_data
CSV ->> CSV: convert
CSV -->> -LF: sensor_data

Note over LF, SV: foobar
LF ->> +CSV: get_as_foobar_data
CSV ->> +MD: sensor_no
MD ->> +SV: connection
SV ->> -MD: close
MD -->> -CSV: id, sensor
CSV -->> -LF: foobar_data
LF ->> TGT: Upload sensor_data {TARGET_OBJ_KEY}/YYYYMMDDHHMMSS.csv
LF ->> TGT: Upload foobar_data {TARGET_OBJ_KEY}/YYYYMMDDHHMMSS.csv
LF ->> -SV: commit
```

**ガントチャート**だとこんな感じ。

```mermaid
gantt
dateFormat HH:mm
axisFormat %H:%M

section マイルストーン
開始 : milestone, m1, 09:00, 0min
終了 : milestone, m2, 18:00, 0min

section データ<br>バックアップ
移行前 : 09:00, 3h
移行後 : 14:00, 3h

section データ通信
停止 : 12:00, 1h

section アップデート
アップデート : 13:00, 1h

section クライアント
インストール : 13:00, 2h

section ストレージ
容量確認 : 13:00, 1h
必要に応じ過去データ削除 : 14:00, 1h

section foobar
接続先登録 : 15:00, 1h
通信確認 : 16:00, 1h

section 通信再開
稼働確認 : 17:00, 1h
```

上記ガントチャートのソースコードです。

```markdown:ガントチャート
gantt
dateFormat HH:mm
axisFormat %H:%M

section マイルストーン
開始 : milestone, m1, 09:00, 0min
終了 : milestone, m2, 18:00, 0min

section データ<br>バックアップ
移行前 : 09:00, 3h
移行後 : 14:00, 3h

section データ通信
停止 : 12:00, 1h

section アップデート
アップデート : 13:00, 1h

section クライアント
インストール : 13:00, 2h

section ストレージ
容量確認 : 13:00, 1h
必要に応じ過去データ削除 : 14:00, 1h

section foobar
接続先登録 : 15:00, 1h
通信確認 : 16:00, 1h

section 通信再開
稼働確認 : 17:00, 1h
```

見栄えはCSSでカスタマイズできるので、フローチャートを応用すればネットワーク構成図なんかも描けると思います。

最初はとっつきにくいかもしれませんが、慣れるとパワポやExcelで作図するより圧倒的に楽です。
ひな型というか基本形はChatGPTに指示してコード吐かせても良いと思います。
非IT企業で「ウチはOfficeしか認めん！」という状況なら、PNG画像で出力して貼り付ければ良いのではないでしょうか。（編集できないけど…）

Mermaidを扱えるソフトは沢山ありますが、僕はVSCodeのプラグイン [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid) を使っています。

大企業とかで勝手にソフトをインストールできない環境なら、ブラウザベース（Webサービス）で動くMermaidもあります。公式でも [Mermaid Live Editor](https://mermaid.live/) を提供しています。
LaravelのEloquentでwhereを使う方法

# whereとメソッドは
Laravelにおけるwhereメソッドとは、Eloquentクエリビルダを使って、データベース検索を行うものである。
作成したModelからwhereメソッドを使うことで、そのModelから検索することができる。

# 文法
第一引数：カラム名
第二引数：比較演算子
第三引数：カラムの値

例：
```index.php
Article::where('title', '=', 'test')->first();
```
How to establish an SSH connection via a proxy / 在 SSH 中使用 Socks 代理连接远程服务器

*转载自 https://www.cnblogs.com/liuxianshen/p/use-socks-proxy-connect-remote-server-in-ssh.html*

- 直接敲命令

`ssh -p 2022 -o ProxyCommand='ncat --proxy-type socks5 --proxy 127.0.0.1:7890 %h %p --proxy-auth test:123456' test2@192.168.0.233`

- ~/.ssh/config中添加配置

```
Host loli
  HostName 192.168.0.233
  Port 2022
  User test2
  IdentityFile ~/.ssh/id_rsa
  ProxyCommand ncat --proxy-type socks5 --proxy 127.0.0.1:7890 %h %p --proxy-auth test:123456

```
【flutter】Wrapを使って改行や折り返してContainerを表示したい

こんにちわ！
もう8月も終わりですね〜。僕は毎年夏になるとかき氷を食べるのですが、今年初めてマンゴーのかき氷を食べたのですが、美味しすぎて感動しました！(笑)皆さんは夏と言ったら何を食べますか！？(笑)
さて、今回はWrapを使って改行や折り返してContainerを表示する方法について紹介してまいります！
最後まで読んでいただけたら嬉しいです！！！

## 1,Wrapとは何か？
Flutterで使用されるWidgetの一つで、子Widgetを自動的に配置するためのものです。Wrapを使用すると、子Widgetが親Containerの幅を超えた場合でも、自動的に改行や折り返しが行われます。

<table>
  <caption>Wrapの特徴</caption>
  <thead>
    <tr>
      <th>特徴</th> <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> 自動折り返し </td> <td>子Widgetが親Containerの幅を超える場合、自動的に次の行に配置されます。</td>
  </tr>
<tr>
    <td>間隔の制御 </td> <td>Spacingパラメータを使用して、子Widget間の水平または垂直の間隔を調整できます。</td>
  </tr>
  <tr>
    <td> 配置の制御 </td> <td>Alignmentパラメータを使用して、子Widgetの配置を調整できます。</td>
  </tr>
</table>

## 2,Containerを作ろう！
複数のContainerを折り返して表示できるようにしたいので、6つ用意します。
今回はplayContainersというWidgetを作り、Containerの色とContainerの中の文字を変数として表示させました。
```php
 Column(
            children: [
              playContainers(Colors.red, "りんご"),
              playContainers(Colors.yellow, "バナナ"),
              playContainers(Colors.green, "メロン"),
              playContainers(Colors.purple, "ブドウ"),
              playContainers(Colors.orange, "オレンジ"),
              playContainers(Colors.pink, "モモ")
            ],
          ),
        )

```

![スクリーンショット 2023-08-30 14.50.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/0390b55d-c00a-abb0-5321-7145f8dfc049.png)

## 3,ColumnをWrapに変えて表示してみると、、、
```php
 Wrap(
          children: [
            playContainers(Colors.red, "りんご"),
            playContainers(Colors.yellow, "バナナ"),
            playContainers(Colors.green, "メロン"),
            playContainers(Colors.purple, "ブドウ"),
            playContainers(Colors.orange, "オレンジ"),
            playContainers(Colors.pink, "モモ")
          ],
        )
```
![スクリーンショット 2023-08-30 15.09.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/03ed2198-de17-643b-993d-bc18b30e5322.png)

### 感覚を調節すると、、、
```php
Wrap(
              spacing: 20.0, // 水平方向の間隔
              runSpacing: 15.0, // 垂直方向の間隔
              alignment: WrapAlignment.start, // 子ウィジェットの配置（デフォルトは左寄せ
              children: [
                playContainers(Colors.red, "りんご"),
                playContainers(Colors.yellow, "バナナ"),
                playContainers(Colors.green, "メロン"),
                playContainers(Colors.purple, "ブドウ"),
                playContainers(Colors.orange, "オレンジ"),
                playContainers(Colors.pink, "モモ")
              ],
            )
```
![スクリーンショット 2023-08-30 15.14.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/83d068bb-776f-3c17-9890-f31327c15e7d.png)
綺麗に表示されました！

## 終わりに
今回は、Wrapを使って改行や折り返してContainerを表示の方法について紹介させていただきました！
最後まで読んでいただきありがとうございました！
冷たいものの食べ過ぎには気をつけてください！（僕はかき氷を食べた翌日お腹壊しました、、、）
コピーライトのyearをJavaScriptを使用して自動で更新する方法

## コピーライトとは？

一度作成したらほとんど改訂されることのない資料とは違い、Webページは上書きによる更新が行われます。
発行年を入れることにより、「何年も更新されていない古いページだ」という印象を与えることを防ぎます。
そこで、手動で更新できるように取得できるようにしました。


##　記述方法の例

```コピーライト　
//HTML
<footer>
        &copy; <span class="year"></span> 373
</footer>

// 年取得 (JS)
const year = document.querySelector('.year');

const today = new Date();
const thisyear = today.getFullYear();
console.log(thisyear);


year.textContent = thisyear;
```


いかがでしょうか？
是非お試しください！
エディタ上でslim-lintのエラーを見えるようにした


## はじめに

普段slim-lintを使っていて、CIやlint-stagedよりも手前のタイミングでエラーを先に確認できるといいなと思い、efm-langserverを導入してslim-lintを動かせるようにしたので紹介します。

## efm-langserverについて

Language ServerがないリントツールやフォーマッタをLanguage Serverにできるツールです。

https://github.com/mattn/efm-langserver

https://mattn.kaoriya.net/software/lang/go/20190205190203.htm

インストールは、Homebrewだと以下のようにします。
詳しくは[README](https://github.com/mattn/efm-langserver#installation)を参照してください。

```
$ brew install efm-langserver
```

## slim-lintをefm-langserverで動かすための設定を追加する

Neovim, nvim-lspconfigでの設定例は以下です。

```lua:lsp.lua
local lspconfig = require('lspconfig')

lspconfig.efm.setup({
  init_options = { documentFormatting = true },
  settings = {
    languages = {
      slim = {
        lintCommand = "slim-lint --stdin-file-path ${INPUT}",
        lintStdin = true,
        lintFormats = { '%f:%l [%t] %m' },
      }
    }
  }
})
```

lintFormatsには、slim-lintの出力に合わせてVimの`errorformats`を設定します。

https://github.com/mattn/efm-langserver/blob/437c94a22d496fe0add798ad8a10ac76fb9e8df5/schema.md#21112-property-lint-formats

> Description: List of Vim errorformats to capture. See: https://vimhelp.org/quickfix.txt.html#errorformats. If this is not expressive enough, you can edit the lint-command to do some preprocessing, e.g. using sed or jq.
>
> efm-langserver uses a Go implementation to parse the errors, which comes with a CLI for quick testing: https://github.com/reviewdog/errorformat

また、efmls-configs-nvimを使うと、基本的な設定を簡単に行なえます。

https://github.com/creativenull/efmls-configs-nvim

efmls-configs-nvimを使った場合、以下のようになります。

```lua:lsp.lua
local lspconfig = require('lspconfig')
local slim_lint = require('efmls-configs.linters.slim_lint')

lspconfig.efm.setup({
  init_options = { documentFormatting = true },
  settings = {
    languages = {
      slim = { slim_lint },
    }
  }
})
```

実際に動かしてみると、こんな感じに表示できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/da267ef3-390d-f8ab-5471-bc8e9bfa5493.png)

## VSCodeでもエラーを見えるようにしたい

VSCodeの拡張機能に`efm-langserver-vscode`を使うとできます。

https://marketplace.visualstudio.com/items?itemName=Matts966.efm-langserver-vscode

`~/.config/efm-langserver/config.yaml`の設定は以下のようにします。

```yaml:~/.config/efm-langserver/config.yaml
version: 2
tools:
  slim_lint: &slim_lint
    lint-command: 'slim-lint --stdin-file-path ${INPUT}'
    lint-stdin: true
    lint-formats:
      - '%f:%l [%t] %m'
languages:
  slim:
    - <<: *slim_lint
```

実際に動かしてみると、こんな感じに表示できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/ec37d655-45fb-a792-aa16-cb235b19a009.png)

## さいごに

efm-langserverをさわってみて、ものすごく汎用的で便利だなと感じたので、他にも使えないか模索してみようと思います。
Postmanを使ったテストのテクニック


# はじめに

PostmanとはAPIのテストツールです。開発時の動作確認や自動テスト等で活用できます。
今回はPostmanのちょっとしたテクニックを紹介します。

# 目次

1. Postmanの使い方
1. コレクションの作成
1. リクエストの作成
1. 環境変数
1. 複雑な処理の委託

## Postmanの使い方

使い方について詳しくは説明しません。公式ドキュメントや他記事をご参照ください。
ここでは最低限の使い方について説明します。

### コレクションの作成

PostmanはAPIのリクエストについて定義して実行する事ができます。
コレクションとはそれらをまとめたものです。
また、APIについてテストシナリオがある場合、一連の流れをまとめたものとも捉えることできます。

実際の操作はPostmanの左側にあるCreate New Collectionを押下するだけです。
![コレクション作成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301212/77a93ae3-0316-9070-cbf3-c4045fd37f2e.png)

### リクエストの作成

さきほど作成したコレクションを右クリックするとAdd requestと出ます。
これを押下すると新しいリクエストについて追加する事ができます。

![リクエスト追加.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301212/87c27779-3c4e-f9a2-168b-2594046f278c.png)

### リクエスト送信

URLを入力してSendを押下するとHTTPリクエストが送信できます。
ここでは[httpbin](https://httpbin.org)に対して送ります。
![リクエスト送信.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301212/1a78c59b-e533-0cb4-c6dd-c958ea0d32e5.png)
画像下部でレスポンスボディが確認できます。

### 環境変数

Postmanには環境変数を定義する事ができます。用途は主に2つあります。
1つはテスト対象の切替です。例えばAPIのドメインを切り替えるのは、環境変数を利用すると楽に行えます。

![環境変数を追加.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301212/73bbd5f3-00ac-a597-8bce-c24c49b6ab03.png)
![環境変数を定義.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301212/d690317d-1847-c8b3-dc64-4ac1b9c1f3e5.png)
![環境変数を参照.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301212/7073a71a-5836-f953-5ed2-93f9dfa79ee2.png)

このように定義した環境変数は{{}}で囲むことでURLはもちろん、クエリパラメータやリクエストボディ等に利用できます。

もう1つはテストシナリオ中に発生した値の受け渡しです。

例えばレスポンスボディの値を環境変数に入れることで次のリクエストの実行のパラメータにする事ができます。

### 複雑な処理の委託

Postmanはリクエストを送る前と後でjavascriptを実行する事ができます。ただし、ライブラリを読み込ませて複雑な処理をすることはできません。さきほど説明した環境変数の操作やリクエストの実行結果のAssert程度です。
ただし、テストシナリオを自動化する中で、クライアント側で少し器用な処理が行えると便利なときがあります。これはローカルに委託先のサーバを作成する事で対応できる場合があります。今回はローカルでテストが自動化できれば要件を満たせたため問題はありませんでしたがCICDに組み込むなら検討が必要になることに注意してください。

非同期処理のAPIを実行して、数秒待機してから次のAPIを実行したい場合は、以下のように実現できます。

```js
const express = require('express');
const bodyParser = require('body-parser');

const app = express();
const PORT = 9999;

app.use(bodyParser.json());

app.post('/delay', (req, res) => {
    const { delayInSeconds } = req.body;

    if (typeof delayInSeconds !== 'number' || delayInSeconds <= 0) {
        return res.status(400).send('Invalid delay value');
    }

    setTimeout(() => {
        res.send(`Delayed for ${delayInSeconds} seconds!`);
    }, delayInSeconds * 1000);
});

const server = app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

process.on('SIGTERM', () => {
    console.log('Stopping server gracefully');
    server.close(() => {
      console.log('Server stopped');
      process.exit(0);
    });
  });
```

nodejsで簡単なサーバを構築します。nodeをインストールして実行しても良いですし、dockerで動かしても良いと思います。

`http://localhost:9999/delay` にPOSTリクエストを送ると指定された秒数待機してからレスポンスを返します。これをコレクションのリクエストの間に挟むことで実現できます。

## まとめ

今後はnewmanやdockerと合わせた自動テストについて紹介したいと思います。
めんどくさがりやな新卒未経験が基本情報技術者を取得した勉強方法

# はじめに
はじめまして。
この記事では、2023年四月に新卒でエンジニアになった果てしなくめんどくさがりやな自分が、新しくなった基本情報技術者試験をできるだけ効率よく取得しようと思い行った勉強方法を紹介したいと思います。

# こんな方におすすめ
* 新卒未経験エンジニア
* できるだけ勉強時間を少なく資格を取得したい
* 学んだものを何かしらの形でアウトプットしたい



# 基本情報技術者試験とは
基本情報技術者試験はIPAが行っている、ITエンジニアの登竜門とも呼ばれている国家試験ですね。
以下のサイトでは、
>ITエンジニアとしてキャリアをスタートするには、まず基本情報技術者試験から受験することをお勧めします。しっかりとした基礎を身に付けることにより、その後の応用力の幅が格段に広がります。

と記載されています。
駆け出しエンジニアにはもってこいの資格だと思います。

https://www.ipa.go.jp/shiken/kubun/fe.html
# 2023年4月の変更点
そんな基本情報技術者試験なのですが、2023年の四月に大きく試験内容が変更されました。
|　 |変更前  |変更後  |
|---|---|---|
|試験回数|年2回  |回数制限なし |
|時期  |上期/下期  |いつでも良い  |
|試験時間（午前）  |150分|90分  |
|試験時間（午後）  |150分|100分  |
|出題数(午前）|80/80  |60/60  |
|出題数(午後）|5/11  |20/20  |

1\. __試験の時期と回数__

今まで上期と下期の年に二回だったものが通年で試験会場に空きがあればいつでも受けれるようになりました。
これによって、試験日の融通が利くようになり勉強のスケジュールが立てやすくなりました。

2\. __試験難度__

午前問題は問題数と時間は変わりましたが、内容、難度はほとんど変わってないように感じます。しかし、午後問題は今まで150分で５問回答で、かなり複雑な問題だったのですが、**改定後は100分で20問になりそこまで難度の高くない小問集合のような形式**になりました。
**全体の難度的には易化**したと感じております。実際、合格率も2023年４月は56.4％で改定前の合格率20~30%に比べるとかなり上がっています。
試験を受けるなら今がチャンスですね。


# 勉強方法
1\. **試験の予約**

勉強ではないのですが、まず最初に試験の予約をしてしまいましょう。めんどくさがりは崖っぷちに立って始めて行動するので。それから、最初に予約し試験日を確定させたことでスケジュールが立てやすいといったメリットもあります。
ちなみに、予約したはいいけどほんとに受かる気がしない場合は日程の変更を、試験日三日前までなら行うことも可能です。

2\. **過去問道場を解きまくる**

ここからがやっと基本情報の勉強ですね。過去問道場とはその名前の通り、今までの基本情報技術者試験の過去問題がまとめてあるサイトです。午前試験の方は問題数は変更しましたが内容に大きな変更点はありません。
基本情報の試験の参考書はとても分厚くて参考書から勉強を始めようとすると無限に心が折れます。（過去に経験あり）
まずは、ゲーム感覚で過去問を解いていきましょう。
そこで**大事**なことは、
**・知っている単語を増やす。**
**・間違えた問題は解説を読み、復習をする。**
ことです。
これは何を勉強するときも言えることですね。基本情報は初学者からすると知らない単語が多すぎて訳が分からなくなりますが、まずは、見たことある単語を増やす、そして知っている単語を増やしていきましょう。
また過去問道場には間違えた問題をピックアップして出題してくれる機能があるので模擬試験を2~3回やったら一度復習するのが良いと思います。
模擬試験の正答率が70%を3回以上連続で超えるまではこれを繰り返しましょう。




[過去問道場おすすめの使い方]
過去問道場にアクセスし
①「模擬試験形式で出題」を選択
②「平成２１年以降から作成」を選択
③「選択肢をランダムに並べ替える」を選択
④「出題開始」を選択


3\. 基礎情報をインプットする

ここまできたら一度試験内容を網羅的にインプットしましょう。過去問道場で何度も問題を解いた分最初からインプットするよりも効率的に理解することができます。
ちなみに自分はUdemyを利用し、動画でインプットしました。参考書を買うよりも安いし、電車の中でも見れるのでお勧めです。

https://www.udemy.com/course/kihon_joho/


4\.午後問題（B問題）の対策をする

2と3をやったら午前問題の方はほぼ完璧です。
午後試験の問題は変更前から大きく変わりアルゴリズムの問題がほとんどで残りがセキュリティ系の問題になっています。
企業の研修でプログラミングを受講した方は過去問道場にある新制度サンプル問題を一周解くだけで対策は十分だと思います。
実際自分は二か月弱のエンジニアの研修を受け、サンプル問題を一周だけ解いて臨んだのですが、試験では８割とることができました。

プログラミングが完全に未経験の方には先ほどにも紹介したUdemyがおすすめです。自分はサンプル問題だけこれで説いたのですが、他にも一から丁寧に説明してくれています。

https://www.udemy.com/course/kihon_joho_b/


# まとめ

以上が自分の行った勉強方法でした。少しでも皆さんの参考になれば幸いです。
ありがとうございました。
ストリーミングとLLMの統合〜LangStream紹介

本稿では、生成AIのニーズのために新たに開発されたLangStreamプロジェクトを紹介します。

LangStreamにより、LLMアプリケーションの典型的な処理を、Apache Pulsarファンクションとして組み込むことが容易になり、LLMをリアルタイムイベント処理と組み合わせることが可能になります。また、後述のStarlight for Kafkaを用いることで、Kafkaクライアントとの組み合わせも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/3bbcb39c-9d66-edc0-8958-f1213b6398fc.png)


https://langstream.ai/

以下の記事は、LangStreamの公式ドキュメントの内容をソースとしています。

https://docs.langstream.ai/

## LangStreamとは何か?

LangStream は AI の導入を推進するオープンソース プロジェクトです。
LangStream プロジェクトは、**LLM(大規模言語モデル）のインテリジェンス**と**ストリーミング処理の機敏性**を組み合わせて、アプリケーションを作成します。
LangStream のアプリケーションは、メッセージ トピックを監視し、複数のステップを通じてデータを処理して、有用な生成 AI 結果を出力します。

LangStreamをつかうことで、チャットボットなどの生成 AI プロジェクトの開発に伴うオーバーヘッドを大幅に削減できます。例えば、開発者は、データの変更に応じてベクトル化するステップを持つ、**パイプライン**を宣言するアプリケーションを作成できます。また、ユーザーの質問を受け取り、それをベクトル化されたデータと比較し、コンテキスト化されたプロンプトを構築し、LLM に送信するアプリケーションを作成することもできます。

パイプラインの各ステップは**エージェント**に変換されます。エージェントは入力メッセージを受け取り、そのデータを処理し、結果を新しいメッセージとして出力します。処理は、データをすべて小文字に設定するという単純な場合もあれば、ラベル付きの値を削除する命令である場合もあります。あるいは、エンベディングモデルを使用してメッセージ データをエンベディングに変換する生成 AI用処理や、LLM にプロンプ​​トを送信して完了を受け取るなどの、より強力な処理を行うこともできます。

すべてのパイプラインには開始点と終了点があります。ストリーミング データのコンテキストでは、これは通常、**ソース**と**シンク**と呼ばれます。ソースは、データベース、別のメッセージ トピック、または開始点トピックのメッセージ データを生成する方法を知っているアプリケーションです。パイプラインには 1 つのソースまたは複数のソースを含めることができます。
LangStream はトランスポートにメッセージ ブローカーの**トピック**を使用します。
パイプラインがデータを正常に処理したら、それに対して何らかの処理を行う必要があります。こちらはシンクが使われているところです。ソースと同様に、シンクにもさまざまな形状があります。通常、シンクは処理されたデータをデータベースに保存します。パイプラインには 1 つのシンクを接続することも、複数のシンクを接続することもできます。


## 技術的特徴

- KubernetesやApache Kafkaなどの実証済みのテクノロジーを基盤に構築
- ChatGPTなどの LLM 、 HuggingFaceなどの推論 API 、 AstraDBなどのベクトル データベース、LangChainなどのエージェントとのインテグレーション
- シンプルな宣言型 YAML ファイルを使用して独自のリアルタイム AI アプリケーション パイプラインを作成
- イベント データ、セマンティック検索、データベース クエリなどを組み合わせて、リッチ コンテキストを含むプロンプトを生成するプロンプト テンプレート
- 非構造化データ (PDF、Word、HTML など) および構造化データの処理
- Kafka Connect シンクとソースを実行して外部システムとリアルタイムに統合
- 可観測性のための Prometheus メトリクスと Kubernetes ログ
TypeScriptコンパイラにおける`const`

# TypeScriptコンパイラにおける`const`

今回、const のコンパイルにおける特有な要素を紹介していきたいと思う。

まず、constの基本から始めよう：constとは再代入できない変数宣言である。これはTypeScriptもJavaScriptも変わらない。

しかし、constの再代入エラーの際に一つ注意すべき点がある。JavaScriptはインタプリタ型言語なので、再代入エラーは実行時に起き、例外処理の一環として`throw`される。

以下はMDNの[ドキュメント](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const)で使われる例：

``` js
const number = 42;

try {
  number = 99;
} catch (err) {
  console.log(err);
  // 型エラー: const `number'への無効な代入
}

console.log(number);
// 出力: 42
```

これに対し、TypeScriptはコンパイル型であるが故に実行前にエラーを報告する。実行前というと、VS Code ならば、エラーの赤い波線が挙げられる。

ちなみに、`const`と`let`宣言の処理は非常に似ているため、発生し得るエラー以外ほとんど何も変わらない。要は、かなり短い記事になる。

## 構文解析

ここでバインド以外の処理段階における`const`と`let`との唯一の違いを紹介する。

変数宣言のコンパイル手順をより詳しく知りたい方はぜひ[前回の記事](https://qiita.com/eloy/items/9d0d8227121a1dcbdf71)を参照してください。

### AST生成

AST生成にて、parser.ts で`parseVariableDeclarationList`で const のフラグをつけ、「こいつは const だよ」と伝える。

``` ts
switch (token()) {
    ...
    case SyntaxKind.ConstKeyword:
        flags |= NodeFlags.Const;
        break;
    ...
}
```


## constの仕組み

### バインド

バインドを担当する binder.ts には`symbolTable`（シンボルテーブル）というグローバル変数がある。
このテーブルは、ソースに現れるあらゆるシンボル（変数名・関数名・クラス名・型名・モジュール名など）を保管した上で、あるシンボルに対する全ての宣言も記録する。

バインド段階をより詳しく理解するために`declareSymbol`関数を見ていきましょう。

`declareSymbol`関数の働きを次のようにまとめることができる：

1. まず、現在評価している宣言における識別子はすでにシンボルテーブルにが存在しているかどうか判明
  2. なければ、新しいシンボルを生成
  3. 同じブロックに既存の宣言があれば、重複宣言エラーを報告
2. シンボルに今回の宣言を追加
3. シンボルを返す

これで`const`宣言と値を結合することができた。
今度は`const`ならではのエラーを紹介する。

### 再代入エラー

よほど純粋的なプログラミングを用いない限り、定数宣言において最もの簡単に起きるエラーは再代入エラーだろう：

``` ts
const x = 0;
...
x = 1;	// 再代入エラー
```

再代入エラーは型チェック中に起きる。`checkIdentifier`(checker.ts) で識別子を確かめる際、定数宣言にあたると判明される。

```
// const は読み取り専用データの一種
if (isReadonlySymbol(localOrExportSymbol)) {
    // この読み取り専用データは変数ならば、const だと断言できる
    if (localOrExportSymbol.flags & SymbolFlags.Variable) {
        error(node, Diagnostics.Cannot_assign_to_0_because_it_is_a_constant, symbolToString(symbol));
    }
    ...
```

右下の`Diagnostics.Cannot_assign_to_0_because_it_is_a_constant`が報告された、const 文法の誤用をチェックする。

### 未初期化エラー

``` ts
const x; // あれ？
```

`checkGrammarVariableDeclaration`(checker.ts)で`const`変数がちゃんと初期化されたか確認される。

``` ts
else if (!node.initializer) {
  ...
  case NodeFlags.Const:
    return grammarErrorOnNode(node, Diagnostics._0_declarations_must_be_initialized, "const");
  ...
}
```

以上、`const`特有のエラー紹介だった。

## まとめ

ご覧いただいたように、`const`と`let`のコンパイル手順はほぼ等しい。
値の代入の際に`const`特有のエラーも、実は二つしかないということだ。

## 参考資料

直接TypeScriptコンパイラのソースを参照したい方は以下のURLをご利用ください：

- parser.ts：`const`[フラグ](https://github.com/microsoft/TypeScript/blob/main/src/compiler/parser.ts#L7604-L7606)
- binder.ts：`declareSymbol`[関数](https://github.com/microsoft/TypeScript/blob/main/src/compiler/binder.ts#L748-L884)
- checker.ts：残念ながら、このファイルは5万行に及ぶせいでGitHubにて表示できない。ソースをご覧になりたい方はTypeScriptプロジェクトの[Get Started](https://github.com/microsoft/TypeScript/blob/main/CONTRIBUTING.md#get-started)セクションを参照し、TypeScriptをクローンしてください。
	-  `git clone`に`--depth=1`をつけるとダウンロード時間は大幅に減るのでぜひ、このオプションを使ってください。
【Flutter】PopupMenuButtonで画面遷移したいけど出来ない人へ。

# 今回作るもの
PopupMenuButton(以後ポップアップ)、PopupMenuItem(以後アイテム)を使い画面遷移するボタンを作ります。
私もそうでしたが、ポップアップで画面遷移する方法を解説している記事が少なく、実装する際に困ったのでここに書き留めておきます。
# まとめるもの
今回は以下の二つのボタンをポップアップにまとめていきます。
```dart
IconButton(
    onPressed: () {Navigator.push(context,
                    MaterialPageRoute(builder: (context) => const folder()));
    icon: const Icon(Icons.folder)),
IconButton(
    onPressed: () {Navigator.push(context,
                    MaterialPageRoute(builder: (context) => const Add()));
    icon: const Icon(Icons.add)),
```
# 結論
理解できる方は読みたくない思うので先に結論です。
解説を見たい方は下へどうぞ。
```dart
PopupMenuButton(
    itemBuilder: (context) {
        return [
            const PopupMenuItem(
                value: 1,
                child: Text("Folder"),
            ),
            const PopupMenuItem(
                value: 2,
                child: Text("Add"),
            ),
        ];
    },
    onSelected: (int value) {
        if (value == 1) {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => const Folder()));
        } else if (value == 2) {
            Navigator.push(context,
                MaterialPageRoute(builder: (context) => const Add()));
        }
    },
),
```
# 解説
このコードは、`PopupMenuButton`ウィジェットを使用してポップアップメニューを表示します。`PopupMenuButton`ウィジェットは、ボタンを押すとポップアップメニューが表示されるウィジェットです。

`itemBuilder`プロパティには、ポップアップメニューに表示するメニュー項目を返す関数を指定します。この関数は、コンテキストを受け取ります。コンテキストは、ウィジェットが表示されている画面に関する情報です。

このコードでは、`itemBuilder`プロパティに次の関数を指定しています。
```dart
return [
    const PopupMenuItem(
        value: 1,
        child: Text("Folder"),
    ),
    const PopupMenuItem(
        value: 2,
        child: Text("Add"),
    ),
];
```
この関数は、2つのメニュー項目を返します。1つ目のメニュー項目は、値が1で、テキストが`Folder`です。2つ目のメニュー項目は、値が2で、テキストが`Add`です。

`onSelected`プロパティには、メニュー項目を選択した際に呼び出される関数を指定します。この関数は、選択されたメニュー項目の値を受け取ります。

このコードでは、`onSelected`プロパティに次の関数を指定しています。
```dart
if (value == 1) {
    Navigator.push(context,
        MaterialPageRoute(builder: (context) => const Folder()));
} else if (value == 2) {
    Navigator.push(context,
        MaterialPageRoute(builder: (context) => const Add()));
}
```
この関数は、選択されたメニュー項目の値によって、次の処理を行います。

値が1の場合、`Folder()`を表示する画面に遷移します。
値が2の場合、`Add()`を表示する画面に遷移します。
以上の説明で、このコードの動作は理解していただけたと思います。
電子工作メモ - フリップフロップ

# フリップフロップ

データの記憶の機能を実現するもの

- $R$ : リセット
- $S$ : セット
- $Q$ : 出力
- $\overline{Q}$ : 反転出力

## 参考

- [【早わかり電子回路】順序回路とは？フリップフロップの種類と同期の方法を学ぶ](https://engineer-education.com/sequential-circuit_flip-flop/)

## 用語

- 順序回路     :現在の入力に加えて、過去の入力により出力を決定する論理回路
- 組み合わせ回路:

## 種類

- [RSフリップフロップ](#rsフリップフロップ)
- [JKフリップフロップ](#jkフリップフロップ)
- [Dフリップフロップ](#dフリップフロップ)
- [Tフリップフロップ](#tフリップフロップ)

### RSフリップフロップ

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4641/47126d0f-1a94-b97c-04c6-3c1d1a1a6ee1.jpeg">

- S=1, R=0 => S=0, R=0 で1がセットされる
- S=0, R=1 => S=0, R=0 で0がセットされる
- S=1, R=1 は使用禁止

|S|R|Q前|Q#前|Q後|Q#後|動作|
|:--|:--|:--|:--|:--|:--|:--|
|0|0|0|x|0|1|保持|保持|記憶保持|
|0|0|1|x|1|0|保持|保持|記憶保持|
|1|0|0|x|1|0|1|0|セット|
|1|0|1|x|1|0|1|0|セット|
|0|1|0|x|0|1|0|1|リセット|
|0|1|1|x|0|1|0|1|リセット|
|1|1|0|x|0|0|使用禁止|
|1|1|1|x|0|0|使用禁止|

### JKフリップフロップ

- [JKフリップフロップの真理値表や回路図を簡単に解説！](https://www.krrk0.com/jk-flip-flop/)

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4641/9bc2314b-ab24-f801-8bb1-9a44ab7cd9be.jpeg">

RSフリップフロップでは、S=1,R=1 が禁止動作だったが、これを"反転動作"する機能に変更したもの。

- J=0, K=0 のとき
  - Q=0 => S=0, R=0 => Q=0
  - Q=1 => S=0, R=0 => Q=1

- J=1, K=0 のとき
  - Q=0 => S=1, R=0 => Q=1
  - Q=1 => S=0, R=0 => Q=1

- J=0, K=1 のとき
  - Q=0 => S=0, R=0 => Q=0
  - Q=1 => S=0, R=1 => Q=0

- J=1, K=1 のとき
  - Q=0 => S=1, R=0 => Q=1
  - Q=1 => S=0, R=1 => Q=0

|J|K|Q前| |S|R| |Q|Q#|動作|
|:--|:--|:--|:--|:--|:--|:--|:--|:--|:--|
|0|0|0| |0|0| |0|1|記憶保持|
|0|0|1| |0|0| |1|0|記憶保持|
|1|0|0| |1|0| |1|0|セット|
|1|0|1| |0|0| |1|0|セット|
|0|1|0| |0|0| |0|1|リセット|
|0|1|1| |0|1| |0|1|リセット|
|1|1|0| |1|0| |1|0|反転|
|1|1|1| |0|1| |0|1|反転|

### Dフリップフロップ

- D=1 が入力されると、1を記憶しつつ、1を出力
- D=0 が入力されると、0を記憶しつつ、0を出力

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4641/42eff76c-be52-64e2-2317-4255e78c1c67.jpeg">

|D|Q前| |S|R| |Q|Q#|動作|
|:--|:--|:--|:--|:--|:--|:--|:--|:--|
|0|0| |0|1| |0|1|リセット|
|0|1| |0|1| |0|1|リセット|
|1|0| |1|0| |1|0|セット|
|1|1| |1|0| |1|0|セット|

### Tフリップフロップ

T=1 が入力されるたびに、$Q, \overline{Q}$ が反転する。

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4641/75ff8a4e-537e-7504-1b8a-f23610740b90.jpeg">

|T|Q前| |S|R| |Q|Q#|動作|
|:--|:--|:--|:--|:--|:--|:--|:--|:--|
|0|0| |0|0| |0|1|記憶保持|
|0|1| |0|0| |0|1|記憶保持|
|1|0| |1|0| |1|0|反転|
|1|1| |0|1| |0|1|反転|

## 使用例

- [アップダウンカウンタ](https://www.marutsu.co.jp/select/list/detail.php?id=149)

  - Tフリップフロップを多段にすることで、カウントアップ・カウントダウンができる。
  - 上段に接続する場合は、Q => T に接続する
  - T にはクロックを入力する
    - ポジティブエッジトリガはT入力が「L→H」に変化するタイミングで出力が変化
      => カウントダウンになる 
    - ネガティブエッジトリガはT入力が「H→L」に変化するタイミングで出力が変化
      => カウントアップになる 

  - Tフリップフロップは単体ではない？ので、Dフリップフロップを使う。
    - $\overline{Q}$ を D に接続することで実現できる。
goroutineで並行処理しない処理を作った話

# 初めに
goroutineといえばgolangで並行処理を実装するための言語機能ですが、それを使いあえて並行処理を行わず、Timeoutイベントを取るためだけに使ったコードをシェアします


# 背景
とあるDBサービスのデータをバックアップするために、そのDBサービスが提供するコマンドラインツールを使う必要がありました
ですが、いつまで経ってもレスポンスが返ってこないことがありました

その対応として、一定期間レスポンスが返ってこない場合に、中断しリトライするようにしました

なお、初めは全テーブル並行処理で実行したのですが、DBサービス側での制限があるようで安定したレスポンスが得られなかったので、１テーブルづつの実行に変更しました

```download.go
// download and return to channel
func worker(table string, dt string, ch chan Result) {

	err := exec.Command("コマンドラインツール",
		"-a", "aaa",
		"-b", "bbb").Run()
	if err != nil {
		zap.S().Errorf("%s: %v", table, err)
		ch<- Result{table: table, err: err}
		return
	}
	ch<- Result{table: table, err: nil}
}

func execDownload(tables []string, dt string) []string {
	// channel use only timeout event
	ch := make(chan Result, 1)
	var finTables []string

	// call go routine and download
	for _, table := range tables {
		go func(table string) {
			zap.S().Infof("Start: %s", table)
			worker(table, dt, ch)
		}(table)

		select {
		case result := <-ch:
			if result.err == nil {
				zap.S().Infof("Finish: %s", result.table)
				finTables = append(finTables, result.table)
			} else {
				zap.S().Errorf("Error: %s, %v", result.table, result.err)
			}
		case <-time.After(time.Minute * 3):
			zap.S().Info("TIMEOUT")
		}
	}

	return finTables
}
```
（業務に関連しそうな所は書き換えています）

main関数から、ダウンロード対象となるテーブルのスライスを渡してループし、go funcからworker関数でダウンロードコマンドを実行します
本来であれば全テーブル並行で動くところですが、channelの数を1つにしているため、ダウンロードが終了し、channelに戻り値を書き込まれるまでブロックされるので、１テーブルづつの実行となります

ダウンロードが成功したテーブルをmain関数に返し、未処理のテーブルのみをリトライするようにしています


# 補足
こういった処理はスクリプト系で書けば簡単に実装出来そうですが、ダウンロード以外にも必要な処理があり、それはnodeを必要としていました
nodeで実装しようとしましたが、nodeとTimeoutイベントがちょっと相性悪そうだったのと、コンテナでの実行が前提となっているため、nodeの上に新たに他のスクリプト環境を上乗せするのは、筋が悪いように思われました
このような理由で、1バイナリで完結するgolangで実装することにしました

# 終わりに
この記事が何方かのお役に立つと嬉しく思います
WSL2（Ubuntu etc.）にMongoDBを導入する

## 注意
私も初めてMongoDBをWSL2 Ubuntu（20.04 LTS）環境で使用するため、MongoDB自体についての知識が不足している。そのため、「このようにしたら動作する」、「このようにしたらエラーが解消される」といった操作と結果の対応関係のみを書くことに努める。

## インストール
[MongoDB公式ページ](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/#install-mongodb-community-edition)の以下の章を参照（Ubuntu以外のLinuxディストリビューションの場合は、対応するページを参照）。
- "Install MongoDB Community Edition"
- "Run MongoDB Community Edition"

## systemctl start mongod, mongod --dbpath, mongosh etc.
Mongo Shellを利用するためにmongoshコマンドを使うが、正常に起動しない場合がある。しかし、以下の2つの場合では正常な起動が確認された。尚、systemctlコマンドを使用するのは、systemdの場合であることに注意されたい（cf. [MongoDB公式ページ](https://www.mongodb.com/docs/manual/tutorial/install-mongodb-on-ubuntu/#run-mongodb-community-edition "systemd (systemctl) VS.
System V Init (service)")）。

<dl>
    <dt>パターンA</dt>
    <dd>1. sudo systemctl start mongod でサーバを起動する。</dd>
    <dd>2. sudo systemctl status mongod で起動を確認。</dd>
    <dd>3. mongosh コマンドを実行。</dd>
</dl>
<dl>
    <dt>パターンB</dt>
    <dd>1. sudo systemctl stop mongod でサーバを停止させる。</dd>
    <dd>2. sudo systemctl status mongod で停止を確認。</dd>
    <dd>3. sudo mongod --dbpath <任意のDirPath（e.g. ~/foo/data/db）></dd>
    <dd>4. プロンプトが帰ってこないため、ctrl+cなどで停止せず、もう1つターミナルを用意する。</dd>
    <dd>5. 新しいターミナルで mongosh コマンドを実行。</dd>
</dl>

:::note info
**パターンA**の場合、/var/lib/mongodb 配下にデータベースが作成され、**パターンB**の場合、任意のディレクトリ（e.g. ~/foo/data/db）配下にデータベースが作成される。これらは互いに干渉しない。
:::

:::note warn
**パターンA**においてデータベースがデフォルトで作成されるディレクトリは、/etc/mongod.conf に記載がある。これについては、MongoDB のインストール時に apt-get を用いたか否かなどにより、個人差が生じるようなので要確認。
:::

## よくあるエラーの対処
sudo systemctl status mongod などで、エラーメッセージが表示されることがある。その場合は、以下の方法（.sockのユーザパーミッション変更 or /tmp/mongodb-27017.sockの削除）で改善することがある。

https://stackoverflow.com/questions/72682205/impossibility-to-set-new-dbpath-in-mongodb

## その他参考ページ
https://zenn.dev/unemployed/articles/4eadf5b38cde2f#%E8%B5%B7%E5%8B%95

https://stackoverflow.com/questions/72682205/impossibility-to-set-new-dbpath-in-mongodb
PowerAutomateでUNION、そしてEXCEPT

皆さんPowerAutomateでいろいろワークフローを作成しているなかで、「なぜ PowerAutomate では `union()` 関数が使えるのに `except()` 関数が使えないのだろう？」と考えたことはないでしょうか？
私はあります。
そして「なぜ」は未だにわかりません。
それはそれとして・・・

# Problem

PowerAutomateでは、配列Aに配列Bの要素を加えた配列Cを作るのに `union()`関数を利用できる（ただし `unionAll()` ではなく`union()` なので、ユニークな要素の一覧になる）。
一方で、配列Aから配列Bの要素を除いた配列Cを作るのに 適当な関数は存在しない。

# Solution

存在しないものは仕方がないので、あとはどれだけシンプルに高速なフローを実現するか。
ループ（Apply to each）を使用するのは「シンプル」でも「高速」でもないので却下。
代わりに「アレイのフィルター処理」アクションを使用する：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/79d0ac31-8eeb-94dd-8008-50702b572714.png)

* 「差出人」（from）には 配列A を指定
* 条件式の左辺には 配列B を指定
* 条件式の演算子には 「次の値を含まない」を指定
* 条件式の右辺には 配列Aの要素、つまり `item()` を指定

配列Aに配列Bの要素を加えた配列Cを作るのであれば `union(arrayA, arrayB)` でこと足り、アクション（ステップ）を利用するまでもないのですが、配列Aから配列Bの要素を除いた配列Cを作ろうとするとそうは行きません。
残念です。。。
react-hook-formでsubmitボタンを条件付きで無効にするには？

formStateを使用し、モードをonChangeに設定すること

```typescript
 const { register, handleSubmit, formState } = useForm({
    mode: "onChange"
  });
```
そして送信ボタンを以下のようにすること
```typescript
<button disabled={!formState.isValid}/>
```

### 例
```typescript
const OtherForms: React.FC<{}> = () => {
  const { register, handleSubmit, errors, formState } = useForm<FormData>({
    mode: 'onChange'
  });

  const onSubmit = (data: FormData): void => console.log(data);

  return (
    <div>
      <h2>タイトル名</h2>
      <form onSubmit={handleSubmit(onSubmit)}>
        <textarea
          name='title'
          ref={register({ required: true, maxLength: 20 })}
        />
        {errors.title && '作者名は1文字以上、20文字以下でなければなりません。'}
        <h2>作者名</h2>
        <textarea
          name='author'
          ref={register({ required: true, maxLength: 20 })}
        />
        {errors.author && '作者名は1文字以上、20文字以下でなければなりません。'}
        <button disabled={!formState.isValid}>送信する</button>
      </form>
    </div>
  );
};

export default OtherForms;
```
【Swift】【本当にあった怖い話】外部モジュールのリポジトリが削除

# 目次
[1.外部モジュールが削除された？](#1-クロージャを関数の引数にして使用する)
[2.対処方法](#2-実例)
[3.おわりに](#3-おわりに)

# 1. 外部モジュールが削除された？
- 前提条件：外部モジュールの管理はpodファイル

開発しているアプリで外部モジュールをマージ作業している時のこと。
pod installを実行するとGitのアカウントのIDパスワードを聞かれるようになり、入力してみたところ、**リポジトリが見つかりません**とのエラーが、、
Gitのリンク先を見てみると404 Notfounds,,,

そう、消えていたのです。使用している外部モジュールが。

# 2. 対処方法
1. 代わりの外部モジュールを探す
    削除されたとなると仕方ないので、代わりのものを他のリポジトリから漁ってきます。
2. podファイルを書き換える
    以下のように参照しに行くgitのリポジトリを指定してあげる
     ~~~text:基本形
          pod '外部モジュール名', :git => 'リポジトリのURL', :branch => 'ブランチ名'
    ~~~

    ~~~swift:pod
          pod 'AES256CBC', :git => 'https://github.com/krzyzanowskim/AES256CBC', :branch => 'master'
    ~~~
3. pod installする
4. (もしエラーが出るのであれば)pod installで入ってきたモジュール名/swiftファイルの中身を今まで動作していたモジュール名.swiftファイルに置き換える

# 3. おわりに
今まで使用していた外部モジュールが削除されていた焦りましたが、代替リポジトリを見つけて少し手を加えてあげるだけで、対応できました！
**人は壁にぶち当たった時が一番成長する**ということで良しとします :smile: 

今回も本記事を読んでいただき誠にありがとうございました。
目指せ脱初学者！
プロトタイプオブジェクト

# はじめに
オブジェクトリテラルで空のオブジェクトを定義しただけなのに、toStringメソッドを呼び出せています。 このメソッドはどこに実装されているのでしょうか？

また、JavaScriptにはtoString以外にも、オブジェクトに自動的に実装されるメソッドがあります。 これらのオブジェクトに組み込まれたメソッドをビルトインメソッドと呼びます。

# Objectはすべての元
Objectには、他のArray、String、Functionなどのオブジェクトとは異なる特徴があります。 それは、他のオブジェクトはすべてObjectを継承しているという点です。

正確には、ほとんどすべてのオブジェクトはObject.prototypeプロパティに定義されたprototypeオブジェクトを継承しています。 prototypeオブジェクトとは、すべてのオブジェクトの作成時に自動的に追加される特殊なオブジェクトです。 Objectのprototypeオブジェクトは、すべてのオブジェクトから利用できるメソッドなどを提供するベースオブジェクトとも言えます。

![object-prototype.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3287606/74eb9089-b843-5cd0-dd0f-08894153ff1a.png)

具体的にどういうことかを見てみます。

先ほども登場したtoStringメソッドは、Objectのprototypeオブジェクトに定義があります。 次のように、Object.prototype.toStringメソッドの実装自体も参照できます。

Object.prototypeオブジェクトにtoStringメソッドの定義がある

``` 
console.log(typeof Object.prototype.toString);
```

このようなprototypeオブジェクトに組み込まれているメソッドはプロトタイプメソッドと呼ばれます。

# まとめ
プロトタイプオブジェクトはオブジェクトの作成時に自動的に作成される
ObjectのプロトタイプオブジェクトにはtoStringなどのプロトタイプメソッドが定義されている
ほとんどのオブジェクトはObject.prototypeを継承することでtoStringメソッドなどを呼び出せる
プロトタイプメソッドとインスタンスメソッドではインスタンスメソッドが優先される
プログラマとしての矜持

時折、ネット上で話題となるあるシーンはあります。

飛行機の中で赤ちゃんが泣いていて、
泣き声にイライラして怒鳴る大人と、戸惑う母親の光景。

こうした場面に対して、意見は二分されます。

一方で、「赤ちゃんは泣くのは当然のこと。怒鳴るべきではない」という意見。
そして、もう一方では、「みんな疲れている中、すぐに泣いてしまうような赤ちゃんを連れてくる母親にも問題がある」という意見。

そして、つい先日、この話を前の職場の社長に話す機会がありました。

その社長はこう言いました。

「これに関しては、飛行機会社自体が解決策を見つけるべき課題です。
　技術やプログラムを活用して対策を講じるべきですからね。」

私はこの話を聞いて、とても感銘を受け、
今の自分の、プログラマとしての矜持になっています。

プログラマとしてのやりがい、モチベが足りないなぁと思ったとき、
君がつくったコード１行１行が、誰かの"助け"になっていると思い描いてみてください。
少しは、プログラマ人生に明りが灯るのではないでしょうか。

※一部文章は、GPT-3.5 によって、校正されています。
【AWS】AWS認定資格はどちらから取得するべきか【CLF】【SAA】

## はじめに
本ページを開いて下さりありがとうございます。
こちらではAWSの認定資格を取得する際にクラウドプラクティショナー（以下CLF）とソリューションアーキテクト（以下SAA）のどちらから取るべきかの指針と、自分が触れたオススメの学習教材をまとめた記事になります。
どちらから取得すべきか迷っている方の判断の一助になれば幸いです。
## 筆者スペック
・Webエンジニア（6年目）
・CLF、SAA取得済み
## CLFから取るべき人
・クラウドやAWSに関する知識がゼロ
・各サービスを包括的に知りたい
・比較的学習に時間が取れる

<b>筆者所感</b>
CLFは出題問題の傾向的に各サービスの特徴とAWS Well-Architectedに関する設問が多く、クラウドやAWSの知識がない方が最初に取得するのに最適な資格です。
一方でCLFでの設問レベルだと業務では訳者不足なため、AWSで仕事したい場合はSAAを目指す必要があると思います。
筆者はひと月程度でCLFを取得しましたので、一ヶ月程度の学習時間が目安になるかと思います。
## CLFオススメ学習教材
| 教材名| 説明 |
|:-:|:-:|
|<a href="https://amzn.asia/d/3r1uxao" target="_blank">AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー</a>|いわゆる緑本です。CLFの概要を掴むのに最適です。<br />一方で試験で問われる一部サービスの記述がない、古い情報が載っているなどこれだけで対策ができない特徴もあるため、あくまで概要を掴むために使用するのが良いと思います。|
|<a href="https://www.udemy.com/share/101I2O3@zrFNXv7OBXfVvEnQTORgGsZJWZf9C2t5Z2pEOKnNmgA-rvDU951uKwvolmJbrIx2DQ==/">【2023年版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（6回分390問）</a>|対策問題として非常に質が良いです。こちらの問題集を周回し、分からない部分を重点的に対策するだけでもかなり合格に近づくと思います。<br>また、分からないサービス、理解しづらいサービスに関しては公式サイトを確認することで後々のSAA対策時に楽ができるかと思います。|
|<a href="https://www.udemy.com/share/101WKk3@XFn_ezPBzpL1rJbBB1jYRypFH9sgRVfkrAWvjzz0iApoQKXSbrRBZOHbKodTxmYXVA==/">【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座</a>|タイトル的にSAA向けの講座ですが、<b>筆者的には正直CLF対策時から使用すればよかったと後悔しています。</b><br>内容としてはAWSの主要サービスのハンズオン形式の講座になっており、手を動かして学べるためテキストベースの学習よりも知識がより定着しやすいです。<br>ただ量が多くかなり時間が掛かるので、倍速再生で受けるのがオススメです。|
## SAAから取るべき人
・ある程度AWSや他のクラウドサービスを触ったことがある
・AWSに関する業務経験がある
・直近でAWSに関する業務的な知識が求められる

<b>筆者所感</b>
SAAはユースケースから各サービスの組み合わせを選択する設問が中心なため、幅広い範囲から深い知識が問われ、完全にゼロベースからの学習だと厳しいかと思います。一方で過去に経験があるなど、知識の取っ掛かりがある人やAWSの業務予定がある人などはSAAから始めるべきかと思います。
実際の業務でもSAAの知識が必要最低限であるケースも多いので、AWSを用いて仕事したい人は最低でもSAA取得を目指すべきかと思います。
## SAAオススメ学習教材
| 教材名	 | 説明 |
|:-:|:-:|
|<a href="https://amzn.asia/d/fWNMjmI">AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版</a>|いわゆるオレンジ本です。CLFの緑本と同じく概要を掴むのに適しています。<br>以前のバージョンの試験を元に作成されているので、あくまで概要を知る程度に使うのが良いと思います。|
|<a href="https://mondai.ping-t.com/g">Ping-t</a>|無料で利用できる問題集サイトです。問題数も多く設定も細かくできるため、大変オススメです。<br>実試験ではこのサイト内で出てこない範囲からも出題されるため、出題範囲を確認しつつ利用するのがオススメです。|
|<a href="https://www.udemy.com/share/101rfM3@_JbZocx--ycu51O-7i182hQM_0LXKcYQzLnLJJr5rkhKBEgN8NqMtTTfdP_WssV4gA==/">【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）</a>|比較的難しい問題が揃っている問題集です。分からない部分は見直し、不明点を一個ずつ潰すのが良いと思います。<br>また5,6回目の高難度問題は触れなくても問題ないです。|
|<a href="https://www.udemy.com/share/101WKk3@XFn_ezPBzpL1rJbBB1jYRypFH9sgRVfkrAWvjzz0iApoQKXSbrRBZOHbKodTxmYXVA==/">【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座</a>|CLFの学習教材としても紹介した講座です。ハンズオン形式のため、テキストベースの学習とは違う形で学習できます。<br>全体を通そうとすると非常に時間が掛かるので、倍速再生がオススメです。|
## まとめ
・CLFはAWS等のクラウドサービスを触ったことがなく、学習時間が取れる人にオススメ
・SAAはAWSやクラウドサービスの業務経験等があったり、できるだけ早く最低限の知識を身につけたい人にオススメ
psql備忘録

# はじめに
よく使うpsqlコマンドのメモです。

# コマンド

```
#　ローカルログイン
$ psql -d 【DB名】 -U 【ユーザ名】
```
```
#　リモートログイン
$ psql -h 【ホスト】 -p 5432 -d 【DB名】 -U 【ユーザ名】
```
```
#　データベースを指定してバックアップ
$ psql -h 【ホスト】 -p 5432 -d 【DB名】 -U 【ユーザ名】 > 【BKファイル名】
```
```
#　データベース全体をバックアップ
$ pg_dumpall -f 【BKファイル名】
```
```
#　データベースのリストア
$  psql -h 【ホスト】 -p 5432 -d 【DB名】 -U 【ユーザ名】 < 【BKファイル名】

$  pg_restore -U 【ユーザ名】 -d 【DB名】 -f 【BKファイル名】
```