OmniAICreator/Qiita-1.07M huggingface dataset:
【AWS】Lambdaについて

今回はAWSのサーバレスサービスを利用したインフラの構築におけるセキュリティについて
記事を書いていこうと思います！
Lambdaにおけるセキュリティについてのみの投稿のため基本的な
Lambdaの実装方法については記載しないのであしからず。

# Lambdaとは
まず、基本的なことですがLambdaとはAWSが提供する
サーバーレスコンピューティングサービスです。
[前の記事](https://qiita.com/Yukimaru_Rutla/items/6325db36b7584b7d3730)ではEC2インスタンスを構築したネットワーク環境に配置して
管理していましたが、Lambdaは自前でアプリを動かすためのサーバーの構築や運用を
AWSに任せてクラウド上に作成したプログラムさえ置けば動かすことができる優れものです！
初めて触ったときは概念の理解がイメージしにくかったのですが触れば
とても便利なものと分かります。
EC2との用途の違いはLambdaはAPIを作成してバックエンド処理を行わせるのみで
画面などフロント処理はLambdaではできない点です。
フロント処理は別途サーバーに置くかCloudFrontとS3で配信し、
フロントからAPI Gateway→Lambda経由で呼び出して処理させるのがオーソドックスかと思います。

# サーバーレスにおけるセキュリティとは
前述で説明したようにサーバレスとはサーバーの構築・管理の一斉をクラウドサービスに
お任せできるため物理的な管理は不要になります。
また、Lambdaはほかのサービスをトリガーにして動かすのが基本のため
Lambdaのアクセス制御はリソースポリシーによって制御することになります。
図で説明するとこんなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522793/da0cdd7c-c5fe-45bf-7124-126d6a6ee14c.png)
API Gatewayからリクエストを受け付け、Lambda関数が実行され、
DynamoDBからレコードを取得するシステムを例にとりましたが、
リソースベースでアクセス制限をすることで意図しないサービスから勝手に
Lambdaが実行されないようになっています。

# デメリット
個人的に業務で使っていて不便だなと思ったのが、
LambdaのせいではないですがAPI Gatewayから呼び出す場合、
API Gatewayのリクエストが最大29秒までのため、
処理が重いと落ちるんですよね・・・
一応Step Functionを噛ませることで30秒以上かかっても
処理が終わるまで呼び出しをループさせることは可能ですが。
Djangoでテーブルを作成

# Djangoでワンパン！テーブルを作成する方法
今回も初心者の人、または僕自身のアウトプットのための記事です。
dbはデフォルトのsqlite3です。
三択のクイズアプリを作成する際のテーブルを考えます。

必要なテーブルは
・テーマ
・問題文
・選択肢

です。

## models
```
from django.db import models

# Create your models here.
class Theme(models.Model):
    theme_name = models.CharField(max_length=999)

    def __str__(self):
        return self.text

class Question(models.Model):
    theme = models.CharField(max_length=100)
    question_text = models.CharField(max_length=999)

    def __str__(self):
        return self.text

class Answer(models.Model):
    question = models.CharField(max_length=100)
    choice1 = models.CharField(max_length=255)
    choice2 = models.CharField(max_length=255)
    choice3 = models.CharField(max_length=255)

    def __str__(self):
        return self.text
```

## コマンド類
モデルの変更をデータベースに反映するためのマイグレーションを作成します。
python3 manage.py makemigrations [アプリ名]

```
python3 manage.py makemigrations quizWeb
```

マイグレーションをデータベースに適用します。
```
python3 manage.py migrate
```

## SQLite Viewer
拡張機能のSQLite Viewerをインストールするとdbが可視化でき開発がスムーズになります。
db.sqlite3というファイルがmanage.pyと同列に作成され、都度更新されます。
CloudWatch LogsのログをKinesi経由でS3に転送する

# この記事でやること
CloudWatchLogsへ出力されたログをKinesis Data Firehoseを使用してS3へ転送する仕組みを構築する。

こちらの記事の続きでやっていきます。

https://qiita.com/jun_aws/items/5e0d44067a0db0ccd664

# 前提
- CloudWatch Logsへログは転送済み
- Kinesis Data Firehoseを使用してログをS3に転送する
- CloudWatchLogsのサブスクリプションフィルターを設定する

# 実施手順
- ログ保管用バケットを作成
- Kinesis用IAMロールを作成する
- Kinesis Datafirehoseを作成
- CloudWatch Logsのサブスクリプションフィルターを作成&設定する
- S3にログが転送されているか確認する

## S3バケットの作成
以下バケットを作成しました。
設定はデフォルト設定にしています

![Screenshot 2023-09-24 at 17.21.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/98f45f21-b084-9901-7010-7f846bde3e37.png)

## IAMロールの作成

Kinesis用ロールの作成
- 信頼ポリシー：Kinesis(Firehose)
- 権限ポリシー：AmazonS3FullAccess


CloudWatch Logsサブスクリプションフィルター用ロールの作成

- 信頼ポリシー
```
{
  "Statement": {
    "Effect": "Allow",
    "Principal": { "Service": "logs.ap-northeast-1.amazonaws.com" },
    "Action": "sts:AssumeRole",
    "Condition": { 
         "StringLike": { 
             "aws:SourceArn": "arn:aws:logs:ap-northeast-1:123456789012:*"
         } 
     }
  }
}
```

- 権限ポリシー：AmazonKinesisFirehoseFullAccess

※本来であればカスタムポリシーを作成してアタッチするべきですが今回マネージドポリシーを使用します。


## Kinesis Data Firehoseを作成

以下設定で作成します

- ソース：Direct PUT
- 送信先：Amazon S3
- 送信先の設定：先ほど作成したS3を選択
- 詳細設定
    - IAMロール：先ほど作成したKinesis用ロールを選択

## サブスクリプションフィルターの設定

以下設定で作成します。

- 送信先アカウント：現在のアカウント 
- 配信ストリーム：先ほど作成したFirehose
- IAMロール：先ほど作成したサブスクリプションフィルター用のIAMロール
その他設定はデフォルト


CloudWatch Logsにテストイベントを送信したいと思います。

```
$ aws logs put-log-events --log-group-name [log-group-name] --log-stream-name [log-stream-name] --log-events timestamp=$(node -e 'console.log(Date.now())'),message="test log message from AWS CLI"
```

![Screenshot 2023-09-24 at 18.35.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/609ca5fc-08ae-d373-0d15-ea6917de9376.png)

オブジェクトが登録されているのでS3にログ転送されていることが確認できました。


今日はここまで。ありがとうございました！！
Webエンジニアのスタメンアプリ


# Webエンジニアのスタメンアプリ5選択

## はじめに

エンジニア4年目の私が、日々の業務で使っているアプリを紹介します。
私は普段、Webエンジニアとして、フロントエンドとバックエンドの両方を担当しています。

そんな私が業務効率を上げるために使っているアプリを5つ紹介します。

1. [VSCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)
2. [Google Chrome](https://www.google.com/intl/ja_jp/chrome/)
3. [Postman](https://www.postman.com/)
4. [Notion](https://www.notion.so/)
5. [Gitmaind](https://www.gitmind.com/)

## 1. VSCode

VSCodeは、マイクロソフトが開発したオープンソースのコードエディタです。
エディタとしての機能はもちろん、拡張機能をインストールすることで、
様々な言語に対応した開発環境を構築することができます。

私はコードを書く際はもちろん、メモを取るときにもVSCodeを使っています。

VSCodeの拡張機能で特におすすめのものを紹介します。

### 1-1. Markdown All in One

Markdown All in Oneは、Markdownの記法をサポートする拡張機能です。
Markdown All in Oneをインストールすることで、
Markdownの記法を覚えていなくても、
コマンドを使うことで、Markdownの記法を簡単に入力することができます。

### 1-2. Git Graph

Git Graphは、Gitのブランチを可視化する拡張機能です。
Git Graphをインストールすることで、
VSCode上でGitのブランチを確認することができます。

### 1-3. GitLens

GitLensは、Gitの履歴を確認する拡張機能です。
GitLensをインストールすることで、
VSCode上でGitの履歴を確認することができます。


## 2. Google Chrome

言わずもがなですが、Google Chromeは、必須のアプリですね。
SafariやFirefoxなどのブラウザもありますが、なんだかんだで、Chromeが一番使いやすいです。

その理由の一つとして、Chromeの拡張機能が豊富であることが挙げられます。

なので、私が利用しているおすすめの拡張機能を紹介します。

### 2-1. Wappalyzer

https://chrome.google.com/webstore/detail/wappalyzer-technology-pro/gppongmhjkpfnbhagpmjfkannfbllamg

Wappalyzerは、Webサイトの技術を調べる拡張機能です。
Wappalyzerをインストールすることで、利用されているフレームワークや言語などを調べることができます。

### 2-2. JSON Viewer

https://chrome.google.com/webstore/detail/json-formatter/bcjindcccaagfpapjjmafapmmgkkhgoa

フロントエンド、バックエンドを担当しているに関わらず、Jsonを扱うことは多いと思います。

特にフォーマットされていない状態だと非常に見にくいですし、効率もかなり下がります。
JSON Viewerをインストールすることで、Jsonをフォーマットして見やすくできます。

### 2-3. Snap Color Picker

https://chrome.google.com/webstore/detail/snap-color-picker/mnaemggihfdlmbmcbpdkdofhigjgfmco

Snap Color Pickerは、Webサイトの色を調べる拡張機能です。
Snap Color Pickerをインストールすることで、Webサイトの色を調べることができます。

コーディンのレビューなどでカラーコードが適切に反映されているのかやワイヤーフレームの色を確認するのに便利です。

## 3. Postman

Postmanは、APIのテストを行うためのツールです。

Postmanを使うことで、APIのテストを行うことができます。
バックエンド開発はもちろん、フロントエンド開発でもAPIのテストは必要になります。

コードで書く前に簡単に構造の確認をしたいときや、バックエンドの開発を待たずにフロントエンドの開発を進めたいときに便利です。

## 4. Notion

Notionは、ノートを取るためのツールです。
ドキュメントの作成や技術的なメモを取るのに便利です。

Notionは、ブラウザ上で動作するので、どのデバイスからでもアクセスすることができます。


## 5. Gitmind

Gitmindは、マインドマップを作成するためのツールです。

要件定義のフェーズのときにかなり役に立ちます。
思考の整理や要件の整理をする際に、Gitmindを使うことで、情報の整理を用意に行いことができます。
また、マインドマップだけではなく、フローチャートやワイヤーフレームなども作成することができます。

## まとめ

以上、エンジニアが業務効率を上げるために使っているアプリを紹介しました。

エンジニアは、日々の業務で様々なツールを使います。
その中でも、私が特におすすめのツールを紹介しました。

ぜひ、参考にしてみてください。
JetBrains IDE でプロジェクトのバックアップは本当にとれてる？

## 対象者

JetBrainsのIDE（Pycharm PhpStorm WebStorm IntelliJ）を使用していて、プロジェクトフォルダのバックアップをとっているから問題なしと考えているあなた。
注：利用状況にもよりますが・・・

## 仕組み
あるべき姿としては、すべての設定がプロジェクトフォルダにあることです。しかしながら実際にはそうなっておらず、一部の設定情報はプロジェクトフォルダ外に保存されるようになっています。
JetBrainsのサポートにはこの件について「信じられないぐらい貧弱な設計」だと非難するコメントがされていました。


## プロジェクトフォルダのバックアップのみでは情報が失われるもの

主なものとして
・レイアウト（ツールウィンドウの配置など）
・ブックマーク
・AIアシスタントの履歴
などがあげられます。
※ちなみにスクラッチファイルは、全プロジェクトで共通（共有）になっています。

## 完全なバックアップとるには

・プロジェクトフォルダ
・システム構成フォルダ（の中から必要なファイルを選択※1）
をバックアップする必要があります。
※1 JetBrainsでも把握しきれていないようですので自己責任でお願いします。
参考：https://intellij-support.jetbrains.com/hc/en-us/community/posts/360007607519-Where-are-bookmarks-stored-How-do-I-keep-them-if-I-copy-the-script-file-elsewhere-How-do-I-add-them-to-version-control-


### 「システム構成フォルダ」とは

WindowsのWebStorm2023.2の場合は、以下のようになります。
C:\Users\ [username] \AppData\Roaming\JetBrains\WebStorm2023.2\

Macなどの方はこちらから確認してください。
https://intellij-support.jetbrains.com/hc/en-us/articles/206544519

### .idea/workspace.xml の役割

このファイルにある程度の設定情報が記載されているますが、実態はID管理され、システム構成フォルダ内のファイルを指す仕組みになっています。
このworkspace.xmlを削除してIDEを起動すれば、どういった情報がなくなっているか確認できると思います。※削除する前にバックアップを取っておきましょう。
もっと正確を期すなら、別端末へプロジェクトフォルダを持っていって実行するとよいでしょう（そういった環境があるのであればですが）。

## 結局なにをバックアップするか？

workspace情報としては、「システム構成フォルダ」内のworkspaceフォルダをバックアップするのがよいでしょう。
なお、これまでに作成（削除）したすべてのプロジェクトの設定が入っていますので、ピンポイントで設定ファイルをバックアップしたい場合は、.idea/workspace.xmlを解析して該当ファイルを探す必要があります。

グローバル設定としては、以下のものがあげられます。
「システム構成フォルダ」内のoptionsフォルダ内にあります。
ウィンドウ情報：window.state.xml
自分で設定保存したワークスペースレイアウト情報：window.layouts.xml

## 最後に一言

完全なバックアップを取るのは非常に難しく、またJetBrainsのサポート自体も把握しきれていないところが困ったものですね・・・
[Laravel] EloquentでのEager LoadingとN+1問題: first()メソッドの罠

# はじめに
現在、laravelを使ってWebアプリの開発をしております。
実務中にfirst()メソッドを使ってデータを取得する際に、インスタンスの内容が変更してしまう現象が起きてしまいました。
原因を調べてみると、Eager LoadingとN+1問題が関わっていることが判明しました。

その**Eager LoadingとN+1問題**を実例とともに簡単にまとめました。

#  目次

1.環境
2.実際に起こった現象
3.Eager Loadingとは？
4.N+1問題とは？
5.Eager Loadingを使った解決策
5.まとめ


# 1.環境
PHP 8.0.10 
Laravel Framework 8.83.25

# 2. 実際に起こった現象

下記のようにデータを取得しようとした時に起こりました。
```
$users = User::query()
    ->whereIn('id', $userIds)
    ->where('group_id', auth()->user()->group_id)
    ->get();
// ＄users①

$group = $users->first()->group;

// ＄users②
```

この場合に、＄users①のデータと＄users②のデータの内容が違っており、これ以降の機能がおかしくなってしまったのです。

調べてみるとEager Loadingが関係しているとのことでしたので、下記でまとめています。


# 3. Eager Loadingとは？
Eloquentモデルを使用してデータベースから複数のテーブルから取得したい時に、関連するモデルを**１度のクエリで取得することができる**テクニックです！

クエリの回数を減らすことができるため、パフォーマンスの向上のみならず「N＋1問題」の解消にもなります！

## 使い方
### with関数
１. モデルにリレーションを定義する
```
    public function group(){
        return $this->belongsTo(Group::class);
    }
```


２. データを取得するときにwith関数を使う
```
$users = Users::with('group')
    ->whereIn('id', $userIds)
    ->where('group_id', auth()->user()->group_id)
    ->get();
```



# 4. N+1問題とは？
先ほど、Eager Loadingのところでも少し出てきたN+1問題とはどういう現象かを簡単にご説明します。

関連した複数のモデルに紐づいたデータを取得する際に、**余分のクエリを走らせてしまい、少なからず表示速度等に悪影響を出してしまうこと**を言います。

例えば、顧客情報を取得する際に、それぞれの顧客に関連する注文情報を取得するためにN回のクエリが必要な場合、N+1問題が発生します。これにより、データベースへの負荷が高まり、アプリケーションの速度が低下します。

:::note info
この問題の構図
N+1問題を解消したい→→→→→→Eager Loadingで対応しよう！
:::



# 5.Eager Loadingを使った解決策
今まで記載してきたものを踏まえると下記のようにコードを直すとよさそうです。

```
$users = User::with('group')
    ->whereIn('id', $userIds)
    ->where('group_id', auth()->user()->group_id)
    ->get();
// ＄users①

$users = $users->first()->group;

// ＄users②
```
このように修正することで、＄users①と＄users②は同じデータになると思います！


# まとめ
この記事では、Laravel EloquentでのEager LoadingとN+1問題に焦点を当て、first()メソッドを通じて発生する問題とその解決策をまとめてみました。
Eager Loadingを適切に活用することで、パフォーマンスの向上につながる且つ難しくもないので積極的に活用してより良いアプリ開発をしていきたいですね。

ご清覧いただきありがとうございました！
フォームヘルパー　セレクト編

# 初学者の備忘録
初学者の備忘録です。今回は前に投稿したフォームヘルパー編で出てきたフォームの種類selectについて詳しく紹介していこうと思います。応用編です。


## selectとは
フォームを選択している状態だと選択フォームが表示されるフォームレイアウトのことです。

閉じている状態
![CE859C94-3E56-49BC-8986-94D07BA64741.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/4ba10f1e-827c-951e-6920-446bd725fe99.jpeg)

選択している状態
![85F92C8E-094E-4D60-B3CE-563845C93F3F.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/bf54b1ac-e682-c37c-1ce2-d9410ffdbeb0.jpeg)


## 一覧
対象Modelから対象カラムに保存されているデータを一覧表示させます。
```diff_ruby:view
<%= f.collection_select :area_id, Area.all, :id, :name, { include_blank: "地方を選択してください" }, { class: "form-control"} %>
```
上記のコードではAreaモデルからnameカラムの一覧データを表示しています。

日本語訳すると:area_idからArea.allで地方情報を全て持ってきて、idが実際のデータでnameが表示される表示名といった感じです。

collection_selectはフォームヘルパーメソッドの一つなのでform_withを使用する場合こちらのやり方をおすすめします。それとこの実装方法だと初期値も自分で設定してあげることができます。

mapを使用した別の実装方法もあります。下記のコードです。
```diff_ruby:view
<%#= f.select :area_id, Area.all.map{|a| [a.name, a.id]}, { prompt: "地方を選択してください" }, { class: "form-control" } %>
```
ですがmapのメリットをいかせてませんし、フォームヘルパーメソッドが使用できるのにこちらを実装する理由がないのであまり使用しません。（*初学者の意見です）

<details><summary>失敗したとこ</summary>

上記で説明で実装可能ですが、ここでは失敗してためになったことを残しておこうと思います。

collection_selectについてよく理解していなかった頃、selectフォームを実装して下記のコードを記述しました

```rb
<%= f.select :area_id, Area.all, { prompt: "地方を選択してください" }, { class: "form-control" } %>
```

上記のコードではArea.allからとってきたデータをIDで表示させる仕組みらしいです。なのでデータ表示が
![175908C9-48F1-412D-93E0-421D4F2BDC6A.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/f3f1dd8c-58f8-2922-9001-2bd720a504fe.jpeg)
このようになってしまいました。

IDで表示させるのではなくコレクションとして表示しなくてはならないのでcollection_selectを使用します。

</details>

一覧セレクトボックスの実装は以上となります。次はJavaScriptを使用してセレクトボックスの中身が変わる仕組みを実装していきます。


## JavaScript

Coming Soon
WPFのDataGridコントロールでIMEを無効にする

WPFのDataGridコントロールで`DataGridTextColumn`を使用しているときに、IMEを無効にしたい場合があります。
`DataGridTextColumn`のプロパティを調べても、それらしいプロパティが見当たりません。
以下のように、IMEを無効にしたい列の`DataGridTextColumn.EditingElementStyle`を指定することで、`TextBox`の`InputMethod.IsInputMethodEnabled`を設定することができ、IMEを無効にできます。

```xml
<DataGrid Name="grid">
    <DataGrid.Columns>
        <DataGridTextColumn Header="アイテム1"/>
        <DataGridTextColumn Header="アイテム2"/>
        <DataGridTextColumn Header="アイテム3" Width="*">
            <DataGridTextColumn.EditingElementStyle>
                <Style TargetType="TextBox">
                    <Setter Property="InputMethod.IsInputMethodEnabled" Value="False"/>
                </Style>
            </DataGridTextColumn.EditingElementStyle>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>
```
Android Studioのショートカットまとめ

Android Studioを使う上で、効率的に作業を進めるためのショートカットキーをいくつか紹介します。これらのショートカットを覚えることで、開発速度を大幅に向上させることができます。

--随時修正--

1. コード編集
1.1. 自動補完
Windows: Ctrl + Space
Mac: Cmd + Space
1.2. メソッドのリスト表示
Windows: Ctrl + O
Mac: Cmd + O
1.3. クイックドキュメント表示
Windows: Ctrl + Q
Mac: Cmd + J
2. ナビゲーション
2.1. 宣言箇所へジャンプ
Windows: Ctrl + B
Mac: Cmd + B
2.2. 最後の編集箇所に戻る
Windows: Ctrl + Alt + ←
Mac: Cmd + [
2.3. ファイル検索
Windows: Ctrl + Shift + N
3. リファクタリング
3.1. 名前変更
Windows: Shift + F6
Mac: Cmd + F6
3.2. サフェデリート（使用されていないコードの削除）
Windows: Alt + Delete
Mac: Cmd + Delete
4. 実行・デバッグ
4.1. アプリの実行
Windows: Shift + F10
Mac: Cmd + R
4.2. アプリのデバッグ
Windows: Shift + F9
Mac: Cmd + D
Astroで構造化データを使う方法


[Astro](https://astro.build/)で構造化データ（[JSON-LD](https://json-ld.org/)）を使う場合、単純な固定の文字列でよければ普通に書けます。

```html
<script type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "WebSite",
        .
        .
        .
    }
</script>
```

しかし、構造化データの中で変数を使いたい場合は、少し工夫する必要があります。変数をそのまま書こうとすると、変数名が出力されてしまいます。

## 構造化データの中で変数を使う方法

次のように書くことで、Astroで構造化データの中で変数を使えます。

※``.env``で``SITE_NAME``を定義しているとします。

```html
---
const schema = JSON.stringify({
    "@context": "https://schema.org",
    "@type": "WebSite",
    name: import.meta.env.SITE_NAME,
    url: Astro.site
});
---
<!-- 略 -->
<script type="application/ld+json" set:html={schema}></script>
```

簡単に解説します。

1. ``JSON.stringify()``で構造化データを文字列化する
2. ``script``タグの``set:html``に文字列化した構造化データを指定する

``set:html``属性を使うことで、構造化データがエスケープされるのを防げます。また、構造化データの文字列化については、``JSON.stringify()``の代わりにテンプレートリテラルを使うこともできます。

## 参考

- [🐛 BUG: Script Tags | type="application/ld+json" · Issue #3544 · withastro/astro](https://github.com/withastro/astro/issues/3544)
[jupyter / Python] localhost:8888 でアクセスしたら、真っ白な画面しか表示されない時の対策

# 事象

ここまでは行けるんだけど。

![スクリーンショット 2023-09-24 17.38.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/4fa63b80-db58-91e7-f450-e4f19200dc36.png)

正しいパスワードを入れても真っ白な画面になる。


![スクリーンショット 2023-09-24 17.39.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/14a3b672-e4af-e608-f7c1-10ea2672f28e.png)


ちなみに、画面が真っ白になった時は、Chromeの開発者ツールで以下のようなエラーが確認できた。

![スクリーンショット 2023-09-24 17.49.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/ce378eed-234e-5129-679d-83892bb6a6b3.png)

```
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'call')
    at v (bundle.js:1:516)
    at 7559 (880.bundle.js:1:10974)
    at v (bundle.js:1:516)
    at 60880 (880.bundle.js:1:324)
    at Function.v (bundle.js:1:516)
```


# 環境

- リモートマシンの UbuntuOS 上に
- Docker container で jupyter notebook を起動
- そこへ MacOS からリモートアクセスしている
- アクセス時には VPN を利用

という構成。

関係しそうなバージョン類を記載しておく。

||versionなど|
|:--|:--|
|Client PC OS|macOS Ventura 13.6|
|PC CPU|Apple M2|
|Remote Machine OS|Ubuntu 20.04.6 LTS|
|Docker|24.0.5, build ced0996|
|Python|3.8.10|
|jupyter|1.0.0|
|Google Chrome|116.0.5845.187（Official Build） （arm64）|


# 対策

## A: `127.0.0.1:8888` にアクセス

`localhost:8888` ではアクセスできなかったが、 `127.0.0.1:8888` にアクセスしたら今まで通り画面が開けた。

### 追記

`0.0.0.0:8888` でもアクセスできた。

## B: Chrome の場合、キャッシュを削除

jupyter のログに以下のような `302 POST /login?next=...` といったものが表示される場合は、

```bash
docker-python-1  | [I 2024-02-26 16:05:31.347 ServerApp] 302 POST /login?next=%2Ftree%3F (d88bdc9dacfb481da7a2bfd7e3887610@172.18.0.1) 4.74ms
```

以下の手順で Chrome などのキャッシュを削除しても良いかもしれない。


![スクリーンショット 2024-02-26 16.06.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/fff02a59-12d5-f20b-5639-440a22723d0a.png)

1. Chrome ブラウザの右上隅の3点ドットをクリック
1. 「設定」メニューを選択
1. サイドバーの「プライバシーとセキュリティ」を選択
1. 閲覧履歴データの削除をクリック

![スクリーンショット 2024-02-26 16.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327407/068e43e3-4997-792d-6f42-c880141cf782.png)

1. 「ダウンロード履歴」「Cookie と他のサイトデータ」「キャッシュされた画像とファイル」のチェックボックスが入った状態で「データを削除」をクリック。
1. 再度 jupyter にアクセス

私はこれで効果があった。
なぜかわからないが、「302 (リダイレクト)」が効いている状態だったのは、キャッシュが原因になっていた模様。


# 補足

昨日までは localhost でアクセスできたんだけどな。。。
最近 MacOS アップデートしたからそのせいかな。。。

関連しそうな記事は見つけて、以下に書かれている通りキャッシュも消したけど、効果はなかった。

https://discourse.jupyter.org/t/jupyter-notebook-7-in-chrome-on-macos-13-4/20769/3


# 参考記事

他にも以下のような記事がある。

https://qiita.com/TaroNakasendo/items/b03216c0e2b611f1823e
PHP: guzzlehttp/guzzle の使い方

次のページと同じことを Ubuntu 23.04 で行いました。
[PHP Http ClientのGuzzleパッケージを使う](https://reffect.co.jp/php/php-http-client-guzzle/)

## ライブラリーのインストール

```bash
composer require guzzlehttp/guzzle
```

作成された composer.json

```json:composer.json
{
    "require": {
        "guzzlehttp/guzzle": "^7.8"
    }
}
```

## テストプログラム

```php:check01.php
#! /usr/bin/php
<?php

require 'vendor/autoload.php';

use GuzzleHttp\Client;

$client = new Client();

$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/posts/1');

echo $response->getBody();

?>
```

実行結果

```text
$ ./check01.php 
{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
```

Httpie で同じリクエストを発行する

```text
$ http https://jsonplaceholder.typicode.com/posts/1
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Age: 5591
CF-Cache-Status: HIT
CF-RAY: 80b9bf0be94df583-NRT
Cache-Control: max-age=43200
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Sun, 24 Sep 2023 08:44:34 GMT
Etag: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"
Expires: -1
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
Pragma: no-cache
Report-To: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=q4EGse%2F7X%2FKbBpDTbGwWcY2%2B5dz%2Bn1cPOE7P31KLFzztbanJdUjgxHe8KIwVnkYQE%2FXFMCQzT54vUngzwkhrKBVcLAmw1txwShE4Ck23bDYTLiJGmRjUleDUOEzULFOkXRKq6tJAKec1PaSCWRB1Xqm2X%2FY2e4h8WsaR"}],"group":"cf-nel","max_age":604800}
Server: cloudflare
Transfer-Encoding: chunked
Vary: Origin, Accept-Encoding
Via: 1.1 vegur
X-Content-Type-Options: nosniff
X-Powered-By: Express
X-Ratelimit-Limit: 1000
X-Ratelimit-Remaining: 999
X-Ratelimit-Reset: 1691790101
alt-svc: h3=":443"; ma=86400

{
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "userId": 1
}
```

## 確認したバージョン

```text
$ php --version
PHP 8.1.12-1ubuntu4.3 (cli) (built: Aug 17 2023 17:37:48) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.12-1ubuntu4.3, Copyright (c), by Zend Technologies
```
cscの作法 その446

# 概要
cscの作法、調べてみた。
練習問題、やってみた。

# 練習問題
treeviewでjsonを表示せよ。

# 方針
- litjson使う。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/61e3b34f-b6e6-6238-5315-cd65e5b993d9.png)


# サンプルコード

```
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using System.Text;
using System.Data;
using System.Windows.Forms;
using System.Drawing;
using LitJson;

class FormMain: Form {
	private TreeView tv;
	FormMain() {
		Text = "treeview";
		Size = new Size(300, 300);
		tv = new TreeView();
		tv.Size = new Size(250, 220);
		string jsonFileName = "Emptyobject.json";
		string fileText = "";
		FileInfo fi = new FileInfo(jsonFileName);
		using (StreamReader sr = new StreamReader(fi.OpenRead(), Encoding.UTF8))
		{
			fileText = sr.ReadToEnd();
			LitJson.JsonData json = LitJson.JsonMapper.ToObject(fileText);
			TreeNode docNode = new TreeNode("json");
			foreach (KeyValuePair<string, JsonData> j1 in json)
			{
				switch (j1.Value.GetJsonType())
				{
				case JsonType.String:
				break;
				case JsonType.Array:
				break;
				case JsonType.Object:
					TreeNode docNode1 = new TreeNode(j1.Key);
					foreach (KeyValuePair<string, JsonData> j2 in j1.Value)
					{
						switch (j2.Value.GetJsonType())
						{
						case JsonType.String:
							docNode1.Nodes.Add(j2.Key);
						break;
						case JsonType.Array:
							docNode1.Nodes.Add(j2.Key);
						break;
						case JsonType.Object:
							TreeNode docNode2 = new TreeNode(j2.Key);
							docNode1.Nodes.Add(docNode2);
						break;
						default:
							Console.WriteLine(j2.Value.GetJsonType());
						break;
						}
					}
					docNode.Nodes.Add(docNode1);
				break;
				default:
					Console.WriteLine(j1.Value.GetJsonType());
				break;
				}
			}
			tv.Nodes.Add(docNode);
		}
		this.Controls.Add(tv);
	}
	[STAThread]
	public static void Main() {
		Application.EnableVisualStyles();
		Application.SetCompatibleTextRenderingDefault(false);
		Application.Run(new FormMain());
	}
}





```

以上。
フォームヘルパー実装（form_with）

# 初学者の備忘録
初学者の備忘録です。今回はForm_withヘルパー編


## フォームヘルパーとは
入力のためのフォームを作成するためにHTMLにはフォームタグというタグが存在する。
Railsのヘルパーメソッド「フォームヘルパー」を用いて、フォームタグを生成できる。
フォームヘルパーには３種類存在します。簡単に説明すると
・form_tag・・・入力フォームのレイアウトだけ作る
・form_for・・・form_withと内容はほとんど同じ。ただ、HTTPメソッドを定義してあげる必要があるのでアレンジができる
・form_with・・・form_forを楽に記述できるようにしたもの。HTTPメソッドを省略することができるが、ルーティングでonlyで囲めるような基本的なHTTPメソッドしか使えない。
になります。詳しくは[参考資料](https://pikawaka.com/rails/sub_category/form-helpers)をご確認ください。

今回はform_withを使用した入力フォームの実装方法になります

## 実装
それではfrm_withを使用した入力フォームを作成していきます。

【１】　基本
基本的なコードはこちらになります。
```ruby:view
<%= form_with model: 変数, url: 送信先, local: true do |f| %>
<% end %>
```
JavaScriptを使用しなくて、非同期にもしなくていい場合はlocal: trueは記述しなくていいです。

【２】　フォーム
form_withで囲むようにフォームの部品を囲んでいきます。基本的な書き方はこちらです。
```ruby:view
<%= form_with model: 変数, url: 送信先, local: true do |f| %>
  <div class="form-group">
    # 表示名
    <%= f.label :カラム名, '表示名' %>
    # 入力フォーム
    <%= f.フォーム部品 :カラム名 %>
  </div>
<% end %>
```
<div class="form-group">を使用することによって入力フォームと表示名をグループ化させています。
入力フォームのフォーム部品を変えることで様々な入力フォームに変更可能です。

![8E886D64-B5CB-4368-A1B9-8DF67C9B2C31.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/b1197776-18d7-6e37-9fd2-fa59a94c3eb5.jpeg)

必要に応じて変えましょう。

【３】　ヒント
入力フォームに時々ヒント情報が含まれている時がありますよね。それを実装してみたいと思います。
```ruby:view
<%= form_with model: 変数, url: 送信先, local: true do |f| %>
  <div class="form-group">
    # 表示名
    <%= f.label :カラム名, '表示名' %>
    # 入力フォーム
    <%= f.フォーム部品 :カラム名, placeholder: "ヒント" %>
  </div>
<% end %>
```
`placeholder:`を追加するだけでできますのでおすすめです。
<details><summary>おまけ</summary>

ちなみに私は下記のようなコードを基本に多少bootstrapでアレンジするくらいです。

```rb
<div class="form-group">
    <%= f.label :おまけ %>
    <%= f.text_field :sect, placeholder: "ヒント", class: "form-control" %>
</div>

<div>
    <%= f.submit "投稿", class: "btn btn-info btn-block mb-5" %>
</div>
```

上記のようなコードだと下記のような見た目になります。

![1E161646-7782-48E1-A456-57FDC7FF2092.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3503032/c50bd24d-e841-c9d9-a57e-74469c7ac520.jpeg)

</details>

【４】　コントローラー
次はコントローラーの記述をしていきます。私が実際に実装したコードを例として進めていきます。
```ruby:controllers
：
：

def new
    # 空の変数作成
    @place = Place.new
  end

  def create
    # 許可されたデータが変数に格納
    @place = Place.new(place_params)
    # 保存が成功した場合
    if @place.save
      # フラッシュメッセージを表示して詳細ページへ遷移
      redirect_to admin_place_path(@place), notice: "投稿されました"
    # それ以外の場合（失敗した場合）
    else
      # 新規投稿ページへ遷移
      render :new
    end
  end
：
：
```
この時にバリデーションを設定しておくと便利です。データが送られているのかどうかの判断がしやすくなるからです。

## 最後に
以上がform_withを使用した入力フォーム作成になります。
入力フォームの種類によっては苦戦したところもあるので、別枠で投稿していきたいです。それとフォームは新規投稿と編集で使うことが多いのですが、まとめて一つの部分テンプレートにもできるみたいなのでそれもまた整理ができたら投稿します。
それではお疲れ様でした。
JetpackCompose Textの１文字だけ色変える方法

JetpackComposeで途中の文字に対して違う色を設定する方法です。


# リファレンス
https://developer.android.com/jetpack/compose/text?hl=ja#multiple-styles


# コード

リファレンスの公式サンプルコードを、もう少しカラフルにしてみました。
```.kt
@Composable
fun MultipleStylesInText() {
    Text(
        buildAnnotatedString {
            withStyle(style = SpanStyle(color = Color.Green)) {
                append("H")
            }
            withStyle(style = SpanStyle(color = Color.Cyan)) {
                append("ello")
            }

            withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
                append("W")
            }
            withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Magenta)) {
                append("orld")
            }
        }
    )
}
```

![スクリーンショット 2023-09-24 17.26.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/92fa8ad1-6dde-28dc-57b2-809ef80ab778.png)

こんな感じになりました。
あまり使う場面は少ないかもしれませんが、いろいろできそうですね。
djangoでadminサイトへのリンクを動的に生成する方法

# まとめ
html 内で以下のようにリンクを作成すれば行ける.

```django
<a href="{% url 'admin:index' %}">
  管理サイト
</a>
```
### メモ
django でサイトを作成しているとき管理サイトへ移動したいとき予めボタンを作成しておいて簡単に移動できるようにしたかった. 
djangoでは/adminで管理サイトに移行されているがセキュリティの都合上urlをadmin以外に変更したほうが良い.
そのためなんのurlに変えたか分からなくなるため動的生成して簡単に移動できるようにしたかった
djangoは国内の利用者が少ないようで日本語で検索しても見当たらなかったためメモ代わりにまとめた

# 参考サイト
https://stackoverflow.com/questions/694477/getting-django-admin-url-for-an-object
AWS認定全冠(12冠)になったけどあんまり達成感はない。

2023年2月にMLSを受け、それがきっかけで月に1~2個のペースで他の認定資格を取り続け、9月にAWS認定全冠を達成しました。

![スクリーンショット 2023-09-24 17.12.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/7e578542-3e1b-8b76-79a4-47a6c8da0859.png)

資格取得に集中しすぎて仕事に影響が出ないよう、バランスを保つことに努めました。結果として、DBSやDOPなどの資格は業務に直接活かすことができ、非常に効率よく学習を進めることができました。AWS認定全冠はもはや珍しいことではありませんが、私の経験が皆さんの参考になれば幸いです。

# 私の経歴
エンジニア歴4年目。AI研究とインフラ再設計・構築を主に担当しており、アプリケーション開発(フロントエンド、バックエンド)もたまに行っています。
今の会社で働いてちょうど1年くらいになるのですが、前職までは主にモバイルアプリの開発をやっていました。
SQSやS3などの一部のAWSサービスを使うことはありましたが、本格的に利用し始めたのはここ4ヶ月間です。

この期間で多くのAWSサービスに触れ、豊富な経験を積むことができました。
EC2/IAM/VPC/VPC Endpoint/S3/ECS(Fargate)/ECR/Lambda/API Gateway/Route53/RDS/WAF/Config/GuardDuty/EventBridge/CloudTrail/CloudWatch/Amplify/Cognito/CodeCommit/CodeBuild/CodePipeline/Cost Explorer/Budgets/SNS/Systems Manager/SageMaker

# 全冠を目指した理由
会社が受験費用を負担してくれるなら、錯覚資産としてのコスパが高そうだと思ったからです。

今の会社に入ってからAI関連の業務を担当するようになり、また、福利厚生として資格試験の受験費用が会社から支給されるようになりました。これを機に、機械学習に関する知識を深めるためMLSの資格を取得しましたが、予想以上にスムーズに合格することができました。全冠取得により、一定の評価や認知が得られることは耳にしていたので、1資格を2〜3週間の勉強で取得できるのであれば全冠を目指す価値はあると考え、挑戦することにしました。

# 資格取得のスケジュール
以下が受験履歴です。
MLS~DASまでのSpecialty試験に連続で合格して、余裕ぶっこいてSOAを受けたら普通に落ちました。その他の試験は一発合格です。3~5月に人生の大きなイベントが続いたのですが、期間を空けずに試験を受け続けられたのがよかったです。
![スクリーンショット 2023-09-24 17.14.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/c541ed14-1658-abba-a7d2-6293f7286574.png)

# 学習ツール
学習はWEB問題集中心に行いました。問題集の解説が理解しにくい場合に参考書を利用することもありましたが、大部分は問題集を解くことに専念しました。参考書の説明も難解だった場合はChatGPTに質問していました。

最初の方に受けたMLS, SCS, DBS, DASに関してはTeck Stock(Cloud Licenseに名前が変わってる！)の問題集を使いました。しかし、Tech Stockのみの学習でSOAは落ちたので、CloudTechの問題集に切り替えました。CloudTechは、解説の質や問題の的中率が非常に高く、SOA, DVA, SAP, PAS, DOP, CLFについては、この問題集のみで学習しました。

ただ、CloudTechのANS問題集は本番の傾向に沿っていないと感じたため、Tech Stockと併用しました。結果として、ANSに関してはTech Stockの方がより適切な対策ができました。

多くのAWS認定合格者が「Black Beltの動画は必見」や「英語の資料も確認した方が良い」とアドバイスしていますが、私の経験から言うと、ANSを除けば、それほどまでに時間を割く必要はないと感じました。多くの人が仕事と並行して学習している中で、効率的な学習が最も重要です。問題集を完全にマスターし、試験内容が直接業務に関連する場合のみ、追加の学習をお勧めします。

https://cloud-license.com/

https://kws-cloud-tech.com/

# 手こずった試験
私が感じた試験の難易度は、以下の通りです。
ANS>>>>>SAP>=SCS>SOA>DOP>>SAA>DBS=DAS>MLS>DVA>CLF>PAS

ANSとSAPは高難易度で有名なのでそれなりに対策をした(ANSはそれでもギリギリ合格)のですが、SCSとCLFについては舐めてかかったら足元をすくわれかけ、SOAについては実際に足元をすくわれました。

特に、SCSとSOAでは、2択からの絞り込みが困難でした。また、CLFでは、「Well-Architected Frameworkのどの原則に当てはまるか？」といった、より抽象的な問題が出題されます。CLFの上位資格であるSAAやSAPをもっているからといって油断してかかると本当に足元をすくわれます(大事なことなので二回言った)。

# よかったこと
最も感じた利点は、実務への取り組みがよりスムーズになったことです。会社には、インフラに関する相談ができるメンバーがいなかったため、認定試験で習得した知識やChatGPTのサポートにより、作業の効率が大幅に向上しました。これにより、プロジェクトの進行速度を維持しつつ、より高度なタスクにも対応できるようになりました。
特に、運用、セキュリティ、データベース周りの業務をやっていったため、SCS、DBS、SOA、DVA、DOPの資格は、直接的に業務の質を向上させる助けとなりました。

# 勉強順
どの試験も2~3週間あれば受かるので、受験する順番はなんでもいいと思います。

私の場合、最初にMLSを取得し(SAAを取得したのはずっと前なので除く)、最後にCLFを取得するという、一般的ではない順番での受験となりましたが、これが特に非効率であったとは感じませんでした。各試験にはそれぞれの特性と要求される知識・スキルがあるので、自身の経験や得意分野に基づいて、受験順序を計画すればいいんじゃないでしょうか。

# さいごに
AWSのサービスやインフラ構築について、まだ理解していないことが多く、全冠を達成したとはいえ、大きな達成感は感じていません。全冠達成は一つの節目ではありますが、これからも学び続け、深い理解を目指していきたいと思います。
AWS DOP-C02に受かるために使ったもの

# 想定読者
* 既にある程度AWSの知識・経験があり、アウトプット中心で勉強をしようと思っている方
* 勉強のやり方、適切な期間、といった情報は求めていない方


# 使ったもの
## 模擬試験

私が使った模擬試験は以下になります。

* \[公式\] [AWS DOP-C02 試験問題サンプル](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-devops-pro/AWS-Certified-DevOps-Engineer-Professional_Sample-Questions.pdf)
* \[公式\] [AWS Skill Builder - AWS Certified DevOps Engineer - Professional Official Practice Question Set (DOP-C02 - Japanese)](https://explore.skillbuilder.aws/learn/course/external/view/elearning/117/exam-readiness-aws-certified-devops-engineer-professional-japanese)
* [Cloud License (旧TechStock)](https://cloud-license.com/)
* [Udemy - AWS Certified DevOps Engineer Professional Practice Exams](https://www.udemy.com/course/aws-certified-devops-engineer-professional-practice-exams-amazon-dop-c02/)

　なお、以降は上から順に、公式サンプル、Skill Builder、Cloud License、Udemy と表記することとします。

　私の独断と偏見に基づいた難易度のイメージは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253933/facccb83-8455-1f26-8608-b1fb273abcb1.png)



それぞれについて私が感じた _Pros_、_Cons_ を以下にまとめてみました。

|                    |  _Pros_ | _Cons_ |
| ------------------ | ---- | ---- |
| 公式サンプル  | ・公式ゆえ難易度・表現が本試験に近い   |・問題数が乏しい<br>・解説が最低限のため序盤は物足りない     |
| Skill Builder  | ・公式ゆえ難易度・表現が本試験に近い<br>・選択肢ごとに解説があり親切<br>・**苦手分野が把握しやすい** (\*1)<br>・設問ごとに回答時間がわかる |・問題数が乏しい  |
| Cloud License     | ・問題量が多くカバー範囲も広い<br>・本番の試験に難易度が近い(と感じた)<br>・設問ごとに回答時間がわかる(※模試モード)<br>・**復習のための機能が充実している** (\*2)  |・解説が不親切なものが一定数ある<br>・模擬試験モードで一時停止／再開ができない<br>・苦手分野の把握がしにくい   |
| Udemy |・解説が充実している<br>・試験の一時停止/再開ができる<br>・**苦手分野が把握しやすい** (\*1)(\*3)  |・**問題文が英語なので一手間必要** (\*4)<br>・難易度が高めなので解くタイミングに注意   |

\*1：分野ごとの正解率が見られるため、苦手分野が把握しやすいです。ちなみに分野とは公式の [試験ガイド](https://d1.awsstatic.com/ja_JP/training-and-certification/docs-devops-pro/AWS-Certified-DevOps-Engineer-Professional_Exam-Guide.pdf) に記載の6つの区分のことです。
\*2：通常モードと模擬試験モードがあり、通常モードでは1問ずつ解説が確認できます。設問をお気に入り登録して後でまとめて解き直したりもできます。
\*3：回答時に見直しマーク★をつけたものに絞って解説を確認することもできるので、「たぶん正解だけど解説読んでおきたいな」系の設問の見直しもしやすいです。
\*4：Chromeの全文翻訳を使えば概ね問題なく対応できました。問題文にスクリプトが出てくるとその中のプロパティ名まで翻訳されてしまったり、文中にプロパティ名が強調表記（{~問題文~} `AutoScalingRollingUpdate` {~問題文~} のような感じ）されているとそのプロパティ名がおかしな位置に表示されてしまうといったこともありますが、そこまで多くはなく私は気になりませんでした。

ちなみに、個人的には、
* 全ての選択肢についてその選択肢が正しい／間違っている理由が解説されていること
* 一回で回答する分量を自分で調節できること
の2つが特に重要なポイントに感じました。

## リファレンス
　模試の問題に過学習しないように知識補充のためのリファレンスもあった方が応用力がつきやすいと思います。私がリファレンスとして参照していたものは以下になります。
* AWS Black Belt
* [Tutorials Dojo](https://tutorialsdojo.com/) - AWS Cheat Sheets > Comparison of AWS Services

　以降は、上から順に、Black Belt、Tutorials Dojo と略称で表記します。私が感じた _Pros_、_Cons_ を以下に示します。

|                | Pros | Cons |
| -------------- | ---- | ---- |
| Black Belt |・構成がわかりやすい<br>・公式のため情報の信頼性・鮮度が高い |・試験で問われるポイントに沿っていないため、点数UPにつなげにくい|
| Tutorials Dojo |・試験で頻出の似てるサービス比較がまとまっていて点数UPにつなげやすい<br>・細かな仕様まで記載されている  |・構成や形式が統一されておらず読みにくい<br>・原文が英語で、翻訳しても表現が少しわかりにくい<br>・情報の信頼性・鮮度は怪しい|

Tutorials Dojoのチートシートは、`〇〇 vs ××` のように、似ているサービス同士をいろいろな観点で比較して表でまとめてくれているのですごく使えると思います。


# 最後に
　Solution Architect系よりも解きやすく感じました。それでいて実務にすぐ使える内容が多い印象なので、割とコスパ／タイパのいい試験なのではと思いました。
EC2(Ubuntu)にCloudWatch Logsエージェントを導入しログ出力するまで

# この記事でやること
EC2インスタンス(Ubuntu)にCloudWatch Logsエージェントを導入し、コンソール上でロググループを確認する。

# 実施手順
- EC2(Ubuntu)インスタンスを用意する(パブリックアクセス有効)
- EC2に適切なIAMロール作成&を割り当てる
- CloudWach Logsエージェントを導入する
- 設定ファイルを確認する
- AWSコンソール上でログ出力を確認する


## EC2(Ubuntu)インスタンスの用意
作成環境

まずはEC2インスタンスを用意します。
- VPC：192.168.0.0/16
- サブネット
    - パブリックサブネット：192.168.2.0/24
- AMI：Ubuntu Server LTS22.04
- セキュリティグループで22と443を開放しておく


作成成功、SSH接続ができることを確認しました。

![Screenshot 2023-09-23 at 17.12.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/d380b20b-aeb0-b713-2840-220d0b442231.png)


## IAMロールの作成&割り当て
IAMロールの作成と割り当てを行っていきます。

### ロールの作成
- アタッチするポリシー：CloudWatchLogsFullAccess
※本来であれば必要となる権限だけに絞り込むべきなのですが、今回はAWSマネージドポリシーを使用します。

EC2のコンソールから[アクション]→[セキュリティ]→[IAMロールの変更]で作成したロールをアタッチします。

## CloudWatch Logsエージェントのインストール

EC2インスタンスにSSH接続し以下コマンドを実行していきます。

```
$ sudo apt-get update

$ curl https://s3.amazonaws.com/aws-cloudwatch/downloads/latest/awslogs-agent-setup.py -O

$ sudo apt install python2 ※UbuntuにはPython2がデフォルトでインストールされていないため

$ sudo python2 ./awslogs-agent-setup.py --region ap-northeast-1
```

Step形式でインストールが進んでいきます。

全部で5Stepありますが、3StepまでEnterでOK。

```
Step 4 of 5: Configuring the CloudWatch Logs Agent ...
Path of log file to upload [/var/log/syslog]:
Destination Log Group name [/var/log/syslog]:ec2-cwlogs
```
CloudWatch Logsに送信するログデータとロググループ名を選択できます。
今回はデフォルト選択でいきますが、必要に応じてアプリケーションのログなども出力させることが可能です。
ロググループ名は今回は、cw-logsとしておきます.

```
Choose Log Stream name:
  1. Use EC2 instance id.
  2. Use hostname.
  3. Custom.
Enter choice [1]:
```
ログストリーム名をどうするか聞かれます。

```
Choose Log Event timestamp format:
  1. %b %d %H:%M:%S    (Dec 31 23:59:59)
  2. %d/%b/%Y:%H:%M:%S (10/Oct/2000:13:55:36)
  3. %Y-%m-%d %H:%M:%S (2008-09-08 11:52:54)
  4. Custom
Enter choice [1]:
```
ログの出力時間の形式をどうするか聞かれます。


```
Choose initial position of upload:
  1. From start of file.
  2. From end of file.
Enter choice [1]: 1
More log files to configure? [Y]:
```
データファイルのアップロード形式を聞かれます。(すべてのデータファイルか、新しく加えられたもののみか)
新たにログファイルを追加したい場合はY、ない場合はNoと入力しEnterを押下します。


## CloudWatch Logsの確認

ではコンソールを確認してみます。

![Screenshot 2023-09-24 at 16.22.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/a42fb1a5-423f-ae6c-1e91-a7f4a4b64530.png)

![Screenshot 2023-09-24 at 16.22.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/c4ef25c2-9bb2-1a02-bb3d-234115a4cde3.png)

![Screenshot 2023-09-24 at 17.01.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626370/68ba0c80-0561-8ebe-12d3-84f08f236eda.png)


無事CloudWatch Logsにsyslogが転送されていることが確認できました。


## 参考文献

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/QuickStartEC2Instance.html

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/AgentReference.html


今回はここまで。ありがとうございました！！
【Android】状態保存はSavedStateHandle.saveableが便利

# はじめに
AndroidにはActivityが破棄されるタイミングが存在します。
例えば、端末内のメモリーが圧迫されている状態などがそれに該当しますが、開発者設定でActivityを保持しない設定にした場合も同様の状態を再現することが可能です。
Activityが破棄されるとViewの状態はことごとく初期化され、文字を多く入力する画面などで発生すればユーザビリティが大きく低下するような問題が発生します。
その場合の対策としてSaveStateHandleが存在していると思いますが、このSaveStateHandleを便利に使用可能なsaveableを今回ご紹介したいと思います。

# 使用準備
まずsaveableを使用するためには以下を追加する必要があります。

```build.gradle
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
```
saveableは2.5.0で追加された機能になりますので、バージョンを指定する際は2.5.0以上を指定してください。

# saveable使用例
ライブラリを追加したらsaveableを使用可能な状態となります。
まず、saveableを使用しない場合のSaveStateHadleの実装例になります。

```SavedStateViewModel.kt
class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    val filteredData: LiveData<List<String>> =
        savedStateHandle.getLiveData<String>("query").switchMap { query ->
        repository.getFilteredData(query)
    }

    fun setQuery(query: String) {
        savedStateHandle["query"] = query
    }
}
```
これまでは上記のような形でKeyを指定し、状態を保持しています。
保持する情報が多ければ多いほどこのKeyの管理が煩わしいと感じるケースは少なくないと思います。

そこで、saveableの実装例は以下になります。

```SavedStateViewModel.kt
class SavedStateViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {

    val filteredData: List<String> by savedStateHandle.saveable {
        mutableStateOf>(emptyList())
    }

    fun setQuery(query: String) {
        withMutableSnapshot {
            filteredData = query
        }
    }
}
```
saveableを使用しない場合と比べ、煩わしいと感じていたKeyの指定がなくなり、値の保持に関する設定もシンプルになっています。
これまでの実装と比べ、直感的な実装で値を保持できるようになります。

ただし一点注意点として、2.5.０で追加されたばかりの機能なので現段階ではexperimentalな機能となります。
今後のこの機能に改修が入り、想定と違った動作をする場合がありますのでその点ご注意ください。

# さいごに
そろそろJetpack Composeの記事も上げていきたいところですね。
プログラミング初心者が強く認識すべき３大ロジック構造□[順次]◇[分岐]○[反復]＋[割込み]

# はじめに
プログラミング初心者が様々なことを大量に覚えようとする前にまず認識すべき重要な点についてまとめてみました。

## 対象読者
プログラミングに関心を持たれた超初心者または業務上やむなくプログラミングをしないといけない方（経験なし）

# プログラミングの３大ロジック構造とは
順次、分岐、反復の３つの制御構造（control structures）によって処理の流れを記述することを構造化プログラミングといいます。

**1．順次（sequence）** 部分プログラムを順々に実行する。
**2．分岐（bifurcation）** 条件式が導出した状態に従い、次に実行する部分プログラムを選択して分岐する。
**3．反復（repetition）** 条件式が導出した特定の状態の間、部分プログラムを繰り返し実行する。ループ処理。

今日のプログラミング言語は非常に煩雑な記述をコード記述者に要求します。そこには、同種のプログラミング言語であっても、構成されるライブラリ群一式フレームワークの違いによっても様々な「動かす」ための記述規約が異なった状態であります。プログラミング初心者の方はこの煩雑さに目を奪われてしまって、習得を断念してしまう場合があるかもしれません。

しかし、今日の手順的なコンピュータ言語によるソフトウェアの記述は、**どんなに複雑そうに見えても、これらの制御構造の組み合わせからなる**という点を強く認識しておくことは、複雑なアプリケーションを書くようになるためにも重要です。

# 初心者は要概念獲得　4つ目の制御構造[割込み]とは
そして、筆者は今日のウィンドウシステム上のアプリケーション、Webブラウザ上でHTMLと協調して動作することを想定しているWebアプリケーション（主にフロントエンド処理）が、イベント駆動型プログラミングとなっていることを鑑みて、４つ目の制御構造として[割込み]という概念も確実に消化理解することを推奨します。

**4．割込み（interrupt）** ある連続的な処理の流れの中で、ハードウェアやソフトウェアが発する信号・メッセージに応じて割り込んで処理する流れ

# Mermaidによる4大制御構造のフロー図
Mermaidで上記4大制御構造のフロー図を記述しました。これは基本形で、この基本構造の上に様々なバリエーションが存在しますが、まずはこの４つの構造を確実に理解しておくことが重要です。

## 順次
```mermaid
flowchart LR
    start(((開始))) --> A["手順1"]
    A --> B["手順2"]
    B --> C["手順3"]
    C --> stop(((終了)))
```
各手順の中には、分岐や反復が入れ子になっている場合があります。これらの入れ子構造により、複雑なアプリケーションが書かれていきます。
## 分岐
```mermaid
flowchart LR
    start(((開始))) --> A{"条件式"}
    A --> |true|B["手順1"]
    A --> |false|C["手順2"]
    B --> D{" "}
    C --> D
    D --> stop(((終了)))
```
分岐の数は3以上の場合があります。また、手順の中に分岐や反復が入れ子になっている場合があります。
## 反復
ループの表記は独自です。台形より〇が出現した方が直感的に認識しやすいかな派です。
```mermaid
flowchart LR
    start(((開始))) --> A(("反復指定"))
    A --> B["手順1"]
    B --> D{"打切<br/>条件式"}
    D --> |false|stop(((終了)))
    D --> |true|C["手順2"]
    C --> A
```
打切条件式による終了への分岐がない場合は無限ループです。打切条件式の位置により、バリエーションがあります。台形表記のループ記述では、反復回数が記述される場合があります。
## 割込み
いちおう割込領域とかはUMLの表現に従ってみました。要素の位置を細かく指定しきれず、開始の位置がちょっとヘンなのはご容赦ください。
```mermaid
flowchart LR
    start(((開始))) --> A
    subgraph "割込み領域"
    W>"割込み"]-->X["手順3"]
    B --> D{"打切<br/>条件式"}
    A(("反復指定")) --> B["手順1"]

    D --> |true|C["手順2"]
    C --> A
    end
    D --> |false|stop(((終了)))
    X --> stop2(((終了)))
```
この図の意味するところは、反復処理がぐるぐるやっているところに　＞割込み］というノードを起点に手順３が動作するということです。処理の流れ上、どこに割り込まれるのかが描きづらいので、UML上は「割込み領域」という範囲指定で表現しています。手順3に続く終了は本体処理の終了を意味せず、　＞割込み］を起点に開始された処理の終了を意味して書いています。


# おわりに
Qiitaユーザーでプログラミング講師の@codek2さんの記事[^1]　を拝読して、きっちり3大制御構造のチュートリアルのコンテンツを公開されていらっしゃったので、割込みとかどうですかね？的なコメントについて、いいかもですが、私の方になにか説明記事ありますかね？というリクエストをいただいたので、投稿してみました。

# 参考リンク
https://algo.jeita.or.jp/index.html

>アルゴロジックとは何ですか?
ゲーム感覚でプログラミングを体験するための「課題解決型ゲームソフト」です。プログラムに触れたことのない未経験者から上級者まで、プログラミングの基礎であるアルゴリズムの学習に楽しみながら取り組むことができ、プログラミング的思考力の育成に役立ちます。プログラムの3つの制御構造のうち、アルゴロジック1は、「順次処理」と「繰り返し処理」を、アルゴロジック2は、「順次処理」「繰り返し処理」「分岐処理」を実現しています。

[^1]: Qiita [誰でも役に立つ！はじめてのプログラミング（アルゴリズムとJava）](
https://qiita.com/codek2/items/98a54afd5485d0d9bc6e)　参照
ターミナルで使うコマンドを自作する方法

## ざっくり方法

1. コマンド作成
2. パスを通す
3. シンボリックリンクを作成

※Mac（ver. 13.2.1）を使用。

今回は作成例として、
`$ls`と間違えて`$ks`を実行した時、「ちがうよ、ksじゃなくてlsじゃないかな？」をメッセージを出力させる。

## 1.コマンドファイル作成

コマンドディレクトリ、ファイル作成。
```bash
$ cd ~/
$ mkdir command
$ cd command
$ touch ks
```

お返事シェルスクリプトを作成。
```bash
$vi ks

〜以下を記述〜
echo "I'm not a \"ks\". You're the \"KS\"!!"
echo "Did you mean \"ls\"?"
```

## 2.パスを通す

```bash
$ cd ~/
$ vi .zshrc
〜以下を追記〜
export PATH=$HOME/command:$PATH

$ echo $PATH　// /Users/ユーザー名/command が追加されているはず
```

## 3.シンボリックリンクを作成

```bash
$ sudo ln -s ~/command/ks /usr/local/bin
$ ls -la /usr/local/bin 　　　// 「ks -> /Users/ユーザー名/command/ks」 が登録されているはず
$ chmod 777 ~/command/ks
```

### 確認として、`$ks`を実行してみましょう！

```bash
$ ks
"I'm not a "ks". You're the "KS"!!"
Did you mean "ls"?
```

## **終わりに**

lsを実行しようとした時、ksと打ち間違えてしまうことありませんか？
いつも頑張ってくれているPCちゃんをカス呼ばわりするなんて、PCちゃんから怒られて当然ですよね。

**備忘録としてブログに詳しく書いています。** 
https://run-fish.com/%e3%82%bf%e3%83%bc%e3%83%9f%e3%83%8a%e3%83%ab%e3%81%a7%e4%bd%bf%e3%81%86%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%82%92%e8%87%aa%e4%bd%9c%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95/



## **参考**

https://qiita.com/saki-engineering/items/57956af61c191b0e3282

https://qiita.com/benzene/items/865506483377ad4128ee

→　$source ~/.zshrc でPATHが上書きでなく、追加してしまうので、一回クリアする方法
Laravel10に必要なPHP拡張機能の追加

## 1. PHP8.1以上であること

```bash
$ php -v
PHP 8.2.10 (cli) (built: Sep  2 2023 06:59:22) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.10, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.10, Copyright (c), by Zend Technologies
```

## 2. 各種拡張機能

下記の13個の拡張機能が必要とのこと

- Ctype PHP拡張
- cURL PHP拡張
- DOM PHP拡張
- Fileinfo PHP拡張
- Filter PHP拡張
- Hash PHP拡張
- Mbstring PHP拡張
- OpenSSL PHP拡張
- PCRE PHP拡張
- PDO PHP拡張
- Session PHP拡張
- Tokenizer PHP拡張
- XML PHP拡張

参考 [https://readouble.com/laravel/10.x/ja/deployment.html](https://readouble.com/laravel/10.x/ja/deployment.html)

**2-1. PHPで利用可能か確認する**

```bash
$ php -m | egrep -i 'ctype|curl|dom|fileinfo|filter|hash|mbstring|openssl|pcre|pdo|session|tokenizer|xml'
ctype
curl
fileinfo
filter
hash
libxml
openssl
pcre
PDO
random
session
tokenizer
```

「curl」「dom」「mbstring」「xml」が不足しているのでそれを追加する

**2-2. 「curl」「dom(xml)」「mbstring」「xml」が存在するか確認する**

```bash
$ apt search php | grep -i 'curl|mbstring|xml'
```

**2-3. 「curl」「dom(xml)」「mbstring」「xml」の追加**

```bash
$ sudo apt install php8.2-curl php8.2-mbstring php8.2-xml
```

**2-4. 2-2で実行したコマンドを再実行して必要な拡張機能が読み込まれているか確認**

```bash
$ php -m | egrep -i 'ctype|curl|dom|fileinfo|filter|hash|mbstring|openssl|pcre|pdo|session|tokenizer|xml'
ctype
curl
dom
fileinfo
filter
hash
libxml
mbstring
openssl
pcre
PDO
random
session
SimpleXML
tokenizer
xml
xmlreader
xmlwriter
```
AtCoder ABC321-A

AtCodeのビギナー用A問題をひたすら解いてます。
簡単なのでモチベーションあがります。
正解だったよっていうのを載せます！
そろそろBにもチャレンジしていこうと思ってます💦

# AtCoder Beginner Contest 321
https://atcoder.jp/contests/abc321/tasks/abc321_a

```
n=input()
lst=[x for x in n]  #入力をリストに変換
ans='Yes'           #最初にYesを設定（Noが出なかったらYesを出力したいから）
for i in range(len(n)-1):
    if lst[i]<=lst[i+1]: #リストの現在の要素が次の要素以下だったら
        ans='No'    #NOを出力
        break       #１回でもNoが出たらForを抜ける
print(ans)
```
wio terminal でアナログ信号入力(電圧値に変換)

## アナログ信号入力
wikiを見ても，電圧値に対してどんな数値が得られるのかわからなかったので，テストしてみました

ソースコードはwikiそのまま
```C++
void setup() {
    Serial.begin(115200);
    pinMode(A0, INPUT);
}
void loop() {
    int loudness = analogRead(A0);
    Serial.print("Loudness: ");
    Serial.println(loudness);
    delay(50);
}
```
適当なPINとアナログ信号入力用PINの`A0`をつないでみると，
* GND接続 : `loudness = 0`
* 3V3接続 : `loudness = 1023`
* 5V接続 : `loudness = 524`

となり，おそらく0~1023の間の数値として得られます．
また，3.3Vを超えるとオーバーフローするみたいです．

## 線形性の確認
5Vの入力値を，オーバーフローを考慮して `loudness = 524 + 1024`とすると，
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/e862b586-fce2-8a5c-1177-d4c29ce912a8.png)
線形になり，単純な変換で電圧値を得られそうです．
今回必要な電圧は3.3V以下だったので，とりあえず以下のような関数を作成しました．

```C++
double AIN2V(double AIN){
  // V is 0[V] <= V <= 3.3[V]
  // 3.3[V] -> AIN = 1023
  // 5.0[V] -> AIN = 524 = (1023 + 524) - 1023

  double V = 3.3/1023 * AIN;
  return V;
}
```
入力値`AIN`と電圧値`V`の関係は以下の通り．
```math
\begin{align}
3.3 : 1023 &= V : AIN \\
V &= \frac{3.3}{1023} \times AIN
\end{align}
```
## 電圧測定
最終的なソースコードは以下の通り．
```C++
double AIN2V(double AIN){
  // V is 0[V] <= V <= 3.3[V]
  // 3.3[V] -> AIN = 1023
  // 5.0[V] -> AIN = 524 = (1023 + 524) - 1023

  double V = 3.3/1023 * AIN;
  return V;
}

void setup() {
    Serial.begin(115200);
    pinMode(A0, INPUT);
}
void loop() {
    double loudness = analogRead(A0); //型を int から double に変えている
    double V = AIN2V(loudness);
    // serial output
    Serial.print("Loudness: ");
    Serial.println(loudness);
    Serial.print("V: ");
    Serial.println(V);
    delay(50);
}
```
適切に出力できています．
```
Loudness: 232.00
V: 0.75
```
## 参考文献
* PIN配列 : https://wiki.seeedstudio.com/Wio-Terminal-IO-Overview/
* アナログ信号入力 : https://wiki.seeedstudio.com/Wio-Terminal-IO-Analog/
素のDenoでchatGPT使うテンプレ

# 素のDenoでchatGPT使うぞー
pythonにもnode.jsにもopenaiのライブラリあるじゃん？でも、Denoにはないじゃん？
だからってそんな大したこともないようなことのためにDenoで非公式のを入れる気にもなれないじゃん？
そこで、一筆テンプレ書きました。jsonをパースする所は一寸不備あるかも！コールバック関数は適当ね。

出来ることがふえるよ！
やったね！

```ts
const key = "[API-Key]";

const getReply = () => {
  return fetch("https://api.openai.com/v1/chat/completions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${key}`,
    },
    body: JSON.stringify({
      model: "gpt-3.5-turbo",
      messages: [
        { role: "assistant", content: "Hellow!" },
        { role: "user", content: "How are you?" },
      ],
      stream: true,
    }),
  });
};

const getReplyText = async (reply: Promise<void>, callback) => {
  for await (const chunk of reply.body) {
    const data = new TextDecoder()
      .decode(chunk)
      .split("\n\n")
      .map((x) => {
        if (x.length === 0) return "";
        if (x.trim() === "data: [DONE]") return "";
        if (x[0] !== "[") {
          return Array(JSON.parse(x.trim().slice(5)))
            .filter((x) => x !== "")
            .map((x) => x["choices"][0]["delta"]["content"])
            .join("");
        }
      });
    callback(data.join(""));
  }
};

const main = async () => {
  getReplyText(await getReply(), (x) => {
    const encoder = new TextEncoder();
    Deno.stdout.writeSync(encoder.encode(x));
  });
};

main();
```
【HTML】Tableタグの意味

🌻Tableタグ

まずはタグの意味を覚えよう💡

💡tr（Table Row）※Row＝行
　テーブルの行数分だけこのタグが必要

💡th（Table Header）
　項目名、見出しを設定する

💡td（Table Data）
　内容、情報を設定する

これから数日間Tabelネタ続けます！
少しずつ復習しよう💪

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525847/5e8c4a09-d81d-9d79-761b-bd08289f6d84.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525847/8cf55d48-9c49-c043-dce4-ce37aa1a102e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525847/8c1200a5-0eb3-4dfc-b810-8af9a873a876.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525847/7d240741-0479-ead7-90a5-7d0a1e8e0024.png)
![uploading...0]()
Visual Tests and Networking参加レポート【TC39】

大阪で開催された**Visual Tests and Networking**に参加しました。レポートを書きます。
https://www.meetup.com/ja-JP/osaka-web-designers-and-developers-meetup/events/295693488/

クリスチャン・ウルブリッヒさんがチョコレートをドイツからお土産にくれました。アーモンドチョコとてもおいしかったです。
![PXL_20230923_090422731.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/9692239e-277a-8106-ec75-f5195bdc194e.jpeg)

# Practical Problems with Visual Testing

![PXL_20230923_080456848.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/b98bfed1-fc50-536f-edda-7bc3f204f613.jpeg)

ストーリーブックでコンポーネントを管理しているという話でした。コンポーネントのテストは、ブラウザごとFireFoxやChrome、Edgeでテストするのはフレイキーなのでやめましょうとおっしゃってました。もし、画像が数ピクセルずれてもテストしたいなら機械学習を駆使していきましょう。

とてもフロントエンドに役立つお話のないようでした。

# Traceroute and Networking

![PXL_20230923_095208921.MP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/6a0859ff-afe2-b0ea-b448-ce36d4d5744b.jpeg)

2つ目のお話は、トレイスルートのお話でした。非対称パスといってtracerouteしたときに常に同じ経路を通ってパケットが帰ってくるわけではないとのことでした。

![PXL_20230923_094505401.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/d8a70f66-b1f3-6be2-bbab-051a621c9bf0.jpeg)

ルーターの処理には２つあり、データプレーンとコントロールプレーンがあります。データプレーンはCPUで処理しないため、大変高速です。tracerouteをするとEcho Replyを返すためにCPUでTTLをデクリメントする処理をしないといけないです。もし、大量にtracerouteされるとCPUの使用率がいっぱいになります。ですのでパケットを返さないようにしたいです。

パケットを返さないとtracerouteで*になります。
Dockerでよく使うコマンドのメモ

# Dockerでよく使うコマンドのメモ #

- ネットワークリストの確認
    ```
    docker network list
    ```

- ネットワークの詳細確認
    ```
    docker network inspect {$ネットワーク}
    ```

- 使用していないコンテナの削除
    ```
    docker container prune
    ```

- イメージの確認
    ```
    docker images
    ```

- イメージの削除
    ```
    docker rmi {$image}
    ```

- ボリュームの確認
    ```
    docker volume ls
    ```

- コンテナのログ
    ```
    docker logs {$コンテナID}
    ```

- envの読み込み
    ```
    docker-compose --env-file {$envのパス}
    ```

- composeのバックグラウンド起動
    ```
    docker-compose up -d --build
    ```