OmniAICreator/Qiita-1.07M huggingface dataset:
PrismaのManytoManyのデータ紐付け方法で苦戦したのでメモ

## Schema
スキーマ自体はPrismaのドキュメントを見ながら作成
暗黙的と明示的な連携があるようだが、今回は明示的な連携を選択

https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations

```sql
model User {
  id        String  @id @default(cuid())
  name      String?
  email     String
  projects  ProjectsOnUsers[]
  createdAt DateTime  @default(now())
  updatetAt DateTime  @updatedAt
}

model Project {
  id        Int  @id @default(autoincrement())
  name      String
  users     ProjectsOnUsers[]
}

model ProjectsOnUsers {
  user        User    @relation(fields: [userId], references: [id])
  userId      String
  project     Project @relation(fields: [projectId], references: [id])
  projectId   Int
  assignedAt  DateTime  @default(now())
  assignedBy  String
  @@id([userId, projectId])
}
```


## UserとProjectを一括で作成
サンプルのQueryで記載されているのもこのパターン
これはそのままなので比較的簡単にできる。

```typescript
await prisma.user.create({ // UserのCreate
    data: {
      name: 'username', // CreateするUserの情報
      email: 'test@example.com', // CreateするUserの情報
      projects: {
        create: { // Relationテーブルを作成するのでCreate
          project: { 
            create: { // 紐付けるProjectをCreate
              name: 'sand Project', // CreateするProjectの情報
            },
          },
          assignedBy: 'takaho', // CreateするRelationの情報
        },
      },
    },
})
```

## 既に作成済みのUserに対して作成済みのProjectを紐付け
こちらがだいぶ苦戦したが、通るクエリがかけたタイミングでようやく理解
create部分が配列にしているがここは単体でも特に問題なく動く

```typescript
await prisma.user.update({
    where: { id: 'fuga' }, // Update対象ユーザー
    data: {
      projects: { // Relationを追加するのでUpdate対象
        create: [ // Relationを新規追加するのでcreate
          {
            project: {
              connect: { id: 1 }, // 既存Projectを紐づけるのでconnect
            },
            assignedBy: 'hage', // Relationの情報
          },
        ],
      },
    },
  })
```

## Userに紐づいたProjectのRelation解除
```typescript
await prisma.user.update({
    where: { id: 'cl8n7bioo0073zz1i9ozq2xhs' },
    data: {
      projects: {
        delete: {
          userId_projectId: {
            projectId: 10,
            userId: 'cl8n7bioo0073zz1i9ozq2xhs',
          },
        },
      },
    },
  })
```

## 既存Userに新規作成Projectを紐付け
```typescript
await prisma.user.update({

    where: { id: 'hogehoge' },
    data: {
      projects: {
        create: {
          project: {
            create: {
              name: 'New',
            },
          },
          assignedBy: 'hage',
        },
      },
    },
  })
```

## まとめ
この辺りを意識するとそこまで沼にハマらずに済むかも。

- どのレコードを作成するのかの意識
- 対象のレコードは既にあるのか作るのか
- テーブルの必須項目が抜けていないか
- 結構不整合データが発生できてしまう
- その場合にはWebUI上からも削除不可
- 何かしらのゴミリレーションが邪魔しているのでそれを消す
[bat][Tips] 忘れがちなカレントディレクトリの取得方法

```bat
cd %~dp0
```

 d 　--> ドライブ文字の指定
 p 　--> ファイル名以外のパス
%0 --> バッチファイル名
上記を組み合わせると、**%dp0 --> 実行されているファイルのパス**という意味になる

上記でイケそうな気がするが、フォルダ名に空白がある場合は自動的にパス自体を
ダブルクォーテーション(“)で囲む仕様となっている。
例えば、Windowsだと “C:\Program Files\sakura” といった具合に。
そんなお節介はいらないので、%とdの間に「~」を入れて " " を外してあげて純粋なパスにしてやる。
そして、cd %~dp0 で指定すると無事カレントディレクトリに移動できるというわけだ。
Rust 超入門 → 関数

### 関数
```
/// 関数の定義
fn 関数名 ( 変数 ) { 本体 }

/// 戻り値がある場合
fn 関数名 ( 変数 ) -> 戻り値データ型 { 本体 }
```


**一般関数**
```rust
fn main() {
    println!("main!");
    test_function();
}

fn test_function() {
    println!("test function.");
}

/// 実行結果：
/// main!
/// test function.
```

**引数ある関数**
```rust
fn main() {
    test_function(1, 2);
}

fn test_function(a: i32, b: i32) {
    println!("a+b={}", a + b );
}

/// 実行結果：
/// a+b=3
```

**戻り値ある関数**
```rust
fn main() {
    println!("1+2={}", test_function(1, 2));
}

fn test_function(a: i32, b: i32) -> i32{
    return a + b;
}

/// 実行結果：
/// 1+2=3
```

**ちょっとプラス　関数内の関数**
```rust
fn main() {
    fn test_function() -> i32{
       1 + 2  
    }
    println!("1+2={}", test_function());
}

///実行結果：
/// 1+2=3
```
Linux sysfs・カーネルパラメータ・modprobe・modinfoについて

●sysfs（「/sys」ディレクトリ）
デバイス関連の情報を扱うための擬似的なファイルシステム。ハードディスク上にファイルは存在せず、システムが起動する際にメモリ上に作成。
sysfsは、デバイスファイルを動的に管理するudevなど、デバイス情報を扱うユーティリティによって使用される。

■「/sys」ディレクトリ配下にある主なディレクトリ

・devices　デバイスの親子関係に関する情報
・bus/pci PCIデバイスに関する情報
・bus/usb USBデバイスに関する情報
・firmware ファームウェアに関する情報
・fs ファイルシステムに関する情報
・kernel カーネルに関する情報
・module モジュールに関する情報

※「/sys」ディレクトリ配下に格納されているファイルの多くはASCIIテキスト形式なので、catコマンドなどで内容を確認できる。

●カーネルパラメータ
カーネルの動作や細かな設定値を参照・変更するための仕組み。
基本的にはユーザが個別に設定を行わなくても自動で適切な設定が行われるが、任意の値を設定することもできます。

設定を実行時に参照・変更する方法としては、sysctlコマンドを使う方法と、/proc/sys 以下に存在するカーネルパラメータを操作するための仮想ファイルに対して読み書きを行う方法がある。
ビルド時に行うカーネルコンフィギュレーションとは異なり、（一部の例外項目を除いて）実行中に設定を変更することができ、設定内容は即座に反映。

■sysctl コマンドでカーネルパラメータの操作を行う

表示
sysctl カーネルパラメータ

変更
sysctl -w カーネルパラメータ=値
(-w オプションをつけなくても変更が行える環境もある）

一覧
sysctl -a



■仮想ファイル「/proc/sys」を使ってカーネルパラメータの操作を行う方法(kernel.shmmaxが対象パラメータと仮定)

表示
cat /proc/sys/kernel/shmmax

変更
echo ‘153’　> /proc/sys/kernel/shmmax

上記2つの方法は結果的に同じで、いずれも/proc/sys以下の値を一時的に置き換える。

※sysctlでの「.」が「/」に置き換えられた形式であることに注意。

※この2つの方法で設定した場合は、再起動時に設定が失われてしまう。
恒久的に（再起動後も）設定を有効にするためには、起動時に自動実行されるスクリプトを編集し、起動毎に設定したい値を変更する sysctl コマンドを実行するようにするか、/etc/sysctl.conf または /etc/sysctl.d ディレクトリ配下の設定ファイルに設定を記述。/etc/sysctl.d ディレクトリは、目的別に設定ファイルを分ける際などに使用

●modprobe の設定ファイルでは、各カーネルモジュールのデフォルトパラメータを指定したり（options）、カーネルモジュールに別名をつけたり（alias）、特定のカーネルモジュールのロード時・アンロード時に実行されるコマンドを設定したり（install, remove）できる

●modprobe

・-f 強制的に操作を行う
・—show-depends　指定したモジュールの依存関係を表示

●modinfo 

オプションをつけずに実行すると詳細情報（ファイル名、解説、作者、ライセンス、パラメータ）表示。

-d, --description（モジュールの説明）
-l, --license（モジュールのライセンス）
-n, --filename（モジュールのファイル名（パス））
-p, --parameters（モジュールがサポートしているパラメータ）

個別に指定して表示することも可能
Element-Plusコンポーネント内部のスタイルを変更したかった

Element-Plusを使用しているけど、コンポーネントのスタイルをプロダクトデザインに合わせて変更したい、、
そんな時に自分が試した方法を共有したいと思います。

※記事内のコードはSCSSで記述されていますので、ご了承ください

# 実装手順
結論から言いますと、Vueの機能であるDeep Selectorを使用すれば実現可能です！
まず、chromeのdevTool等を使用して、Element-Plusのコンポーネントで実際に生成されるHtmlを確認してみまししょう。
または、直接ソースを見られても良いと思います。
対象のタグに当たっているクラス名を発見できましたでしょうか？
![スクリーンショット 2022-09-29 23.36.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659774/9c14e826-c1b3-3537-a911-ac253d6555d4.png)

こんな具合です。
ちなみに、Element-Plusのコンポーネントのclassは、elなんちゃかのことがほとんどです(全てを確認したわけではないので、間違えていたら申し訳ありません、、)

それでは実際に、el-tabs__itemというクラスを指定して、スタイルを当てていきたいと思います。
Element-Plusのコンポーネントを呼び出しているコンポーネントに、以下のようなSCSSを記述します

#### :deepを使用する方法(2023年11月現在、v-deepは非推奨になっているようです。)
``` scss
:deep(.el-tabs__item) {
  width: 100%;
}
```

こんな感じでまとめて複数指定することも可能です。

``` scss
:deep {
    .el-tabs__header {
      margin-top: 0;
    }
    .el-tabs__item {
      background-color: #fff;
    }
  }
```

思い通りのスタイルになりましたか？

# まとめ
当たり前のことですが、Element-PlusのコンポーネントもVue.jsで記述されているので通常のコンポーネントと同じようにDeep Selectorが使用できます。
ですので、Vueのドキュメントに沿って扱えばある程度のカスタムが可能です。

コンポーネントライブラリに苦手意識を持っている方も多いかと思いますが、こんなこともできるんだよということで、開発の一助になれば幸いです。

もし間違っている点等ありましたら、ご指摘いただければ非常にうれしく思います！
S3バケットのバケットポリシーで「Principal: "*"」とすることの意味について

## はじめに

ある日、筆者が関わっているプロジェクトで「S3のバケットポリシーが設定できない」との投稿をグループチャット内で見つけました。プロジェクトの環境構築に携わる人だったので、その人にはIAMロールAdministratorAccessの権限が設定されていましたから、「バケットポリシーが設定できないはずはないよな」と思い、その人が何をしようとしていたのかを投稿内容から確認しました。仮にその人をAさんとしておきます。

なお、Principalを"*"とした場合は、そのS3バケットは誰にでも公開された状態となります。AWSにサインインしていない人にも公開されます。知っている人は知っていることだと思われますが、私は知らなかったことでした。

## その人はS3バケットのバケットポリシーでPrincipalを"*"としていたがっていた

Aさんのバケットポリシーを見ると、Principalが以下のように設定されていました。

```
Principal: "*"
```

試しに筆者（IAMロールAdministratorAccessの権限あり）が別のS3バケットを作り、そこで`Principal: "*"`としたバケットポリシーを設定しようとしたら、確かにバケットポリシーが設定できませんでした。これで、Aさんだけの問題ではないことに気が付きます。

それで、「S3バケットのPrincipalに"*"を設定するとは、一体どういう状況？ここはサービスやロール、ユーザーなどを明示的に指定するところなのではないのか？」と筆者は疑問に思いました。

## 試しにPrincipalに特定のサービスを指定してみたら、バケットポリシーが設定できた

IAMユーザーは必要な権限を持っているはずなので、そうなると怪しいのはバケットポリシーそのものであり、（筆者としては）見慣れない`Principal: "*"`が怪しいのではないかと考えました。それで、問題の切り分けのために以下のPrincipalを書いてみましたところ、バケットポリシーが設定できました。

```
"Principal": {
	"Service": "lambda.amazonaws.com"
}
```

これで、Principalの書き方に起因する問題だということが認識できました。

## 調査の結果、バケットポリシーでPrincipal:"*"を指定するということは「匿名アクセス許可を付与する」ことだと知る

今回の調査をするまで気が付かなかったのですが、バケットポリシーでPrincipal:"*"を指定すると、「匿名アクセス許可を付与する」、つまりバケットを誰でもアクセスできるようにする設定になるとのことでした。

「誰でも」の部分には、AWSにサインインしていない人も含まれます。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/s3-bucket-user-policy-specifying-principal-intro.html#s3-anonymous-permissions

明確な要件がない限り、S3バケットを誰にでも公開することはないはずなので、仕様を知らずに行っていたとしたら怖いことだと感じました。

## 筆者の前提

筆者としては、この件を調査する前の前提は以下のとおりです。

* S3バケットをパブリックで公開するような要件が今まで発生していなかった
* そのため、S3バケットをパブリックで公開する方法自体、認識していなかった

要件として発生したことがなかったので、筆者はこの件に関わるまでは、S3バケットをパブリックで公開する方法を調べたことはなかったという状態です。S3バケットの設定は常に「パブリックアクセスはオフ」としていて、またそのような設定になっていることを何度となく確認した上で使用している、という状態です。

よって、S3バケットをパブリック公開する要件が発生していた人には、当記事は当てはまらないことになります。

## 考察

どうやらAさんは、バケットポリシーでPrincipal:"*"を設定することがどういうことなのかを知らずに設定してたようです。「ワイルドカードで設定しておけば、設定が楽になる」ぐらいの感覚だったようです（AさんおよびAさんが関係する発言から判断）。

今回は、私自身で調べてみて、バケットポリシーでPrincipal:"*"を設定することの意味が理解できましたが、知らないということの恐ろしさも同時に再認識しました。
マイク入力音声をリアルタイムでFFTしてグラフ化する

# 初めに
　この記事はガチでコードだけを置いておこうというやつです。
　なので解説は行っていませんが悪しからず。

# コード

```python
import pyaudio
import matplotlib.pyplot as plot
import numpy as np

def audiostart():
    audio = pyaudio.PyAudio()
    stream = audio.open( format = pyaudio.paInt16,
        rate = 44100,
        channels = 1,
        input_device_index = 1,
        input = True,
        frames_per_buffer = 1024)
    return audio, stream

def audiostop(audio, stream):
    stream.stop_stream()
    stream.close()
    audio.terminate()

def read_plot_data(stream):
    data = stream.read(1024)
    ndarray  = np.frombuffer(data, dtype='int16')
    wave_y = np.fft.fft(ndarray)
    wave_y = np.abs(wave_y)
    plot.plot(wave_y)
    plot.draw()
    plot.pause(0.1)
    plot.cla()

if __name__ == '__main__':
    (audio,stream) = audiostart()
    while True:
        try:
            read_plot_data(stream)
        except KeyboardInterrupt:
            break
    audiostop(audio,stream)

```

# 参照
https://niyanmemo.com/335/

https://hellobreak.net/raspberry-pi-sound-fft-realtime/
Rust 超入門 → コメント

### Rustのコメント方式は　C・Javaとほぼ同じです。

```
// １行コメント

/* １行コメント */

/*
 *　複数行コメント
 *　複数行コメント
 *　複数行コメント
 */
```

説明文はよく以下のように書きます。
```
/// Title
/// 説明文
/// 説明文
/// 説明文
/// 説明文
///
```
エンコードタイプの一括置換（Shift_JIS to UTF-8）

## はじめに
備忘メモです。
必要になることは少ないですが、何度か調べなおしているので。

## どんな時に必要？
gitattributesの設定を忘れていたり、IDE設定が統一出来ていなかったりなどの原因で、異なるエンコードタイプが混在してしまった場合などに使います。

## 一括置換のやり方
nkfを使います。Windows環境の場合はWSLなどを使ってください。
コマンドの例を紹介します。

```bash
#!/bin/bash
IFS=$'\n'
array=find . -type f -name '*'
​
for a in $array; do
type=nkf -g $a
if [ $type = "Shift_JIS" ]; then
nkf -w $a
fi
done
```

上記の例では、nkfを使ってShift_JISをUTF-8に一括置換しています。
カスタイズポイントは以下でしょうか。
- findの対象
- 置換対象のエンコードタイプ
- 置換後のエンコードタイプ
Atomic Designについて勉強してみた⑤ (Pages, Templates)

今回は、Atomic Designの中でも一番大きい粒度であるPages・Templatesについて学んだことを書いていきたいと思います。

![atomic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659774/34aad404-0b67-0408-8753-e001f42e6cab.png)
出典元：https://atomicdesign.bradfrost.com/chapter-2/　

### Templates
最終的にレイアウトデザインを確認するためのコンポーネント。
Apiを叩いたりデータを流し込んだりせずに、空のまま定義する
Templatesがあることで、データとデザインの分離が可能になるので、テスト等が容易になる。

### Pages
ユーザーの目に触れる部分、実際にApiを叩いたりルーティングを行なってデータの流し込みを行う。
Templatesを埋め込む大枠として定義する。
自分たちのプロダクトでは、ここでAxiosでApiを叩いてサーバサイドからデータを取得し、Templates以下に流し込みを行っていました。

まとめると、PagesとTemplatesはデザインとデータ(実際のコンテンツ)の棲み分けを行うために存在しているということになります。

ちなみに急に科学用語でなくなる理由ですが、PagesとTemplatesに関しては開発者以外と会話する際に使用する部分と定義しているからだそうです。
科学用語と使い分けることでそこの棲み分けも明確にしています。

## 参考文献

- 五藤佑典, 「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」, 技術評論社, 2018

- Atomic Design by Brad Frost https://atomicdesign.bradfrost.com/
Atomic Designについて勉強してみた④ (Organisms)

今回はAtomic Designの要素の一つであるOrganismsについて学んだことを書いていきたいと思います。


# 概要
Organismsとは、Atomic Designの中で3番目に小さいコンポーネントです。
Molecules, Atomsを組み合わせ、**独立して存在できるコンポーネント**として定義します。
![atomic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659774/4ff088f4-85da-52a5-4c1e-dc0b7766c664.png)
出典元：https://atomicdesign.bradfrost.com/chapter-2/　

例を挙げてみます。
・ユーザー情報(名前・アイコン)
・本文
・いいね・リツイートボタン
・入力ボックス&送信ボタン
これらが集まると、「SNSの呟き表示」の機能を単体で提供するコンポーネントとなります。
このコンポーネントはどこにあろうと「SNSの呟き表示」の機能を失いません。つまり、独立して意味を持って存在できるコンポーネント(Organisms)になっているということです。

# Moleculesとの違いは?
独立して存在しうるか、そうではないかと言う部分だと思っています。
自分が参考にした書籍にも
> Molecules: 独立して存在できるコンポーネントではなく、他のコンポーネントのヘルパーとしての存在意義が強いコンポーネント
> Organisims: 独立して存在できるスタンドアローンなコンポーネント
出典元: 「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」


とあります。多くの場合は、こちらを基準にすれば分類は可能かと思います。
しかし、実際に開発をしているとどちらに分類するか迷うタイミングが多くあるかので、MoleculesとOrganisimsについては、開発時の基準作りを特に綿密に行う必要があります。

参考までに、私が担当しているプロダクトでは、
・ビジネス的な意味合いを持つコンポーネントかどうか
・ページ依存であるかそうではないか
の基準で分類していました。


## 参考文献

- 五藤佑典, 「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」, 技術評論社, 2018

- Atomic Design by Brad Frost https://atomicdesign.bradfrost.com/
Atomic Designについて勉強してみた③ (Molecules)

今回はAtomic Designの要素の一つであるMoleculesについて学んだことを書いていきたいと思います。
# 概要
Moleculesは、Atomic Designの5つの粒度において２番目に小さなコンポーネントで、
Atomsを、ユーザーの動機に答える機能の単位で組み合わせたものです。
![atomic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659774/0bb4fd86-f416-1c0e-87f7-b0473cdc71d3.png)
出典元：https://atomicdesign.bradfrost.com/chapter-2/　

例を挙げてみます。
・テキストボックス 
・ボタン
・テキスト
上記三つのAtomsがあったとします。
これらは単体では、具体的にどのような目的で使用するのか示されていません。
しかし、Moleculesとして組み合わせることにより、「検索フォーム」であることがわかり、言い換えると検索がしたいというユーザーの動機に答えたUIということになります。

# 注意点
Moleculesの作成の際には、以下のことに注意が必要です。
・ユーザーの動機に応えるものではあるが、ページ依存の機能は持たない汎用的なものとする。(ビジネスロジック的なものも記述しないほうが良いかと思います。)
・1つmoleculesに複数の機能を持たせない。コンポーネントの入れ替えや削除等がやりづらくなる。
私たちのチームでも、以上の基準で開発を行っていました。

## 参考文献

- 五藤佑典, 「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」, 技術評論社, 2018

- Atomic Design by Brad Frost https://atomicdesign.bradfrost.com/
Atomic Designについて勉強してみた② (Atoms)

今回は、Atomic designのとりわけ重要な要素であるAtomsについて書いていきたいと思います。

# 概要
Atomsとは、Atomic Designの5つの粒度の中でも、最小のコンポーネントです。
![atomic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659774/1bb02cf6-f065-4299-f89c-3194975ab68a.png)
出典元：https://atomicdesign.bradfrost.com/chapter-2/　

例としては
・テキスト
・ボタン
・テキストボックス
などが挙げられます。
これを組み合わせて、MoleculesやOrganismsなど、より大きいコンポーネントを作成していきます。
Atoms単体では、ユーザーの関心ごとに対しての機能は持ちません。
# 役割
再利用性の高いコンポーネントとしてAtomsを定義し、共通で使用することによってデザインの統一を行うことができます。
再利用性を高めるためには
・propsで要素を受け取れるようにしておく
・なるべく特定箇所依存のスタイルを指定しない
等が考えられます。
# 分割の基準
自分たちのプロジェクトでは、Element-Plus( https://element-plus.org/en-US/ )というコンポーネントライブラリを使用していたため、1つのAtomsに1つ以上のタグは書かない、という分け方をしていました。
他には、
・ビジネスロジックを書かない(emit等でアクションを親コンポーネントに受け渡しするだけ)
などの基準を設けるとわかりやすいかと思います。

Atomsを作る際に気をつけなければいけないのは、UIとして最低限の機能を失わせないことです。
テキストを例に挙げてみます。
「プログラミング」
という単語をこれ以上分割してしまうと、文字としては成立しますが、意味自体は失われてしまうはずです。
それと同じように、UIとしての意味が成立するように注意する必要があります。

## 参考文献

- 五藤佑典, 「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」, 技術評論社, 2018

- Atomic Design by Brad Frost https://atomicdesign.bradfrost.com/
障害対応に備えて戦う



## 始めに
障害対応で焦ってしまう事が多く、障害対応の流れと
出来うる備えについて書いてみました。

## 焦らないために
- 障害発生時のワークフローを意識しておく(まず、どこに報告すべきか)
- システム影響あり/なしの場合のエスカレ先を明確にしておく

## 障害の連絡を受けた場合
- 何が問題なのか
- 障害が発生する前後に何があったのか
- 事態の緊急度
- 初動での暫定対応を決める

## 再現性の確認
- 本番でしか発生しないのか(検品・開発でも確認可能か)
- 毎回発生するのか

## 原因特定
- ログ確認
- 構成要素を整理し、要素単位で問題の切り分けを行っていく
　（要素の例：DB,Blowser,API等）
- 調査しなくていい要素を消去法で消していく

## 二次災害を起こさないために
障害発生時に、応急手当を急ぐあまりオペミスをしてしまい二次災害が起こる可能性がある
(本番のDBデータを誤って更新 or 削除してしまったり 、誤ってバッチを起動させたりとか・・・)

><例>
・本番環境での操作時にダブルチェックを行う
・事前にコマンド、操作方法等を書き出す(必要であればレビューをしてもらう)
・dry-runで実行できないか検討する
・検品環境で確認できないか検討する

## 再発防止策の検討
- 根本原因が判明したら同じ障害が発生しない様、再発防止策を検討する
　→未然防止策(未然に発生する事を防ぐ)
　→再発後防止策(再発した場合の防止策)

><例>
未然防止策
　・リリース時のチェックリストを作成する
　・テストに障害が発生した時のパターンを盛り込む
再発後防止策
　・監視ツールを利用しエラーや障害を検知できる様にしておく

## 教訓としてまとめる
コンフル等で共有できる様にする
><例>
問題：障害事例の内容
原因：問題を引き起こした要因の分析結果
対策：問題の原因を取り除き再発を防止する為の方法
効果：対策の実施によって得られた効果

## 最後に
再発防止策としてこういう事例があった！とか、もっとこういう観点があるよ！
というのがあれば教えてください！

↓また、IPAのサイトで障害事例による教訓が展開されていたので興味がある方はご覧になってみてください。
#### 参考文書
https://www.ipa.go.jp/sec/reports/20160229.html

https://www.ipa.go.jp/sec/system/lesson.html

https://qiita.com/zaru/items/edb49d8d2a2a6981789a
GO言語で、確保した配列に、Mapデータからデータ入力する方法

# 前置き
SQLの汎用性があるプログラムを自作中にSQLからデータを読み取る際に、読み取ったデータを配列に変換させる際で汎用性プログラムが作れないか試してみたので、記録する・

## 説明など
構造体を作ったり操作するためにreflect関数というだいぶ便利なものがあるのでデバッガと組み合わせていろいろと試していた。
ポインタ操作がかなりめんどくさいけど、一つづつ調整していくと出来上がるものができたからだいぶ楽になった。


## 実装プログラム

```golang:main.go
package main

import (
	"fmt"
	"reflect"
)

func mapToStruct(s map[string]interface{}, i interface{}) {

	sv := reflect.ValueOf(i)
	if sv.Type().Kind() != reflect.Pointer {
		fmt.Println(sv.Type().Kind())
		return
	}
	if len(s) == 0 {
		return
	}
	ii := sv.Elem().Interface()
	tStruct := reflect.TypeOf(ii).Elem()
	vStruct := reflect.New(tStruct)
	ckStruct := reflect.TypeOf(vStruct.Elem().Interface())
	for i := 0; i < ckStruct.NumField(); i++ {
		f := ckStruct.Field(i)
		v := vStruct.Elem().FieldByName(f.Name)
		ss := s[f.Name]
		switch f.Type.Kind() {
		case reflect.Int & reflect.TypeOf(ss).Kind():
			v.SetInt(int64(ss.(int)))
		case reflect.String & reflect.TypeOf(ss).Kind():
			v.SetString(ss.(string))
		}
	}
	out := vStruct.Elem()
	v := sv.Elem()
	v.Set(reflect.Append(v, out))

}

type User struct {
	Name string
	Age  int
}

func main() {
	strmap := map[string]interface{}{
		"Name": "bsg",
		"Age":  10,
	}
	strmap2 := map[string]interface{}{
		"Name": "bsg1",
		"Age":  "10",
	}
	str := []User{}
	mapToStruct(strmap, &str)
	mapToStruct(strmap2, &str)
	fmt.Println(str)
}
```

この関数を実行すると以下の通り帰ってくる
```bash
[{bsg 10} {bsg1 0}]
```
結果的に、名前に対応したmapの型を合わせないと配列に設定して追加しないし特別なエラーが発生ないことも確認できた。

## まとめ
reflect関数とinterfaceの型を組み合わせることで、だいぶ汎用性がある配列を作る関数プログラムができた。
これから、SQLの汎用プログラム作成に役に立つだろう
Azure Log Analytics で KQL を用いて、サクッと時系列グラフを作ってみる 1 (列分割)

# 1.はじめに
Log Analytics ワークスペースや Microsoft Sentinel を用いて、時系列グラフを作成しようとしたところ、意外にこれといったドキュメントが無かったので、備忘録で残しておきます。
方法としては幾つかの方法がありますが、今回は一番簡単な列分割でキーを指定する方法をご紹介します。

# 2.やりたいこと
Log Analytics ワークスペースから Kusto Query (KQL) を用いてサクッと時系列グラフを作りたい。
時系列に任意のキーを集計表示して比較したい。
- X軸に時間
- Y軸に集計値（特定のキー毎に集計する）

こんなイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/88fe106d-ed51-601d-2321-a4b24ca77333.png)

# 3.やってみる
``summarize``演算子と``render``演算子がポイントになります。
Log Analytics ワークスペースは Microsoft のデモ環境が提供されていますので、以下リンクから試してみてください。
[Azure Log Analytics デモ環境](https://ms.portal.azure.com/#view/Microsoft_Azure_Monitoring_Logs/DemoLogsBlade)

# 4.ポイント
## 4.1 summarize を用いて、時間軸(TimeGenerated)、Y軸の分割キー（Strings）、集計カウントでまとめる
KQL だと以下の部分になります。count()で1時間毎の集計を行う際に HTTP ステータスコードのキー ``scStatus`` でグループ化しています。
```
| summarize count() by bin(TimeGenerated, 1h) , scStatus
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/d418747f-88aa-bfed-9d68-13e038e83b21.png)

## 4.2 render で timechart を指定する
一目見た際に、何のグラフで何を比較しているのか、タイトルなどを用いると分かりやすいです。
```
| render timechart with(title="W3C IIS Log group by HTTP Status", ytitle="Counts")
```

# 5.サンプル例
## 5.1 W3C IIS ログで、ステータスコード毎に時系列チャートを作成する
参考:W3Cログフォーマット

https://learn.microsoft.com/ja-jp/windows/win32/http/w3c-logging

```sql
W3CIISLog 
| where TimeGenerated >ago(14d)
| summarize count() by bin(TimeGenerated, 1h) , scStatus
| render timechart with(title="W3C IIS Log group by HTTP Status", ytitle="Counts")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/0fb346ea-b1cb-6239-4423-cb72dfacc8b4.png)

## 5.2 Windows セキュリティイベントで EventID 毎に時系列チャートを作成する
参考：Windows EventID 

https://www.windows-security.org/windows-event-ids

```sql
SecurityEvent
| where TimeGenerated > ago (14d)
| summarize count() by bin(TimeGenerated, 1h) , tostring(EventID)
| render timechart with(title="SecurityEvent by EventID", ytitle="Counts")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653790/27614c5d-0ff7-75f4-cc0b-a6eb54cd67ab.png)

## 補足
- Azure Monitor Agent(AMA) / Log Analytics Agent(MMA) から取り込まれる Windows Security Event では、なぜか EventID が数値型(int)なので、``tostring``関数で Strings 型に変換する必要があります。
- 分割に用いるキーが多すぎる場合は、``where`` 条件でフィルターすると良いでしょう（ ``where EventID in (4624,4625)`` など）

# 6. まとめ
Azure Monitor を用いてログを貯めている方は多いと思いますが、時系列チャートを作るテクニックがあまり紹介されていないので、簡単な手順としてまとめてみました。どなたかの参考になれば幸いです。

＊本稿は、個人の見解に基づいた内容であり、所属する会社の公式見解ではありません。また、いかなる保証を与えるものでもありません。正式な情報は、各製品の販売元にご確認ください。
Atomic Designについて勉強してみた① (概要)

Atomic Designについて、「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」を購読して勉強&実務で得た知識の整理しました。
そこで、いくつかの記事に分けて備忘録も兼ねてまとめていきたいと思います。
今回は概要Atomic Designの概要です。

# 前提知識：コンポーネントベースのUI開発について
UIを部品ごとに分けて設計する手法のことです。
## 導入する利点は？？
#### 開発者目線
・テストがしやすい。部品ごとに品質の担保が可能。
・部品の再利用性が高まる。
・コンポーネント間は疎結合の状態になるので、実装の影響範囲を絞ることができる。思わぬバグなどの回避
・並行して開発が可能なため開発速度を向上できる
#### ユーザー目線
・共通の部品で画面が構成されるため、利用方法が理解しやすい。

個人的には、コンポーネント間が疎結合になることがかなり助かっています。(実装時に気にする箇所が少なくなりますし、バグ発生原因の特定も容易になります。)
それでは、本題のAtomic Designについて見てみます。


# Atomic Designとは
コンポネートベースでの開発のフレームワークです。
アメリカのWEB DesignerであるBrad Frost氏が提唱しました。
UIをどのような単位で分割すれば良いか示してくれます。

Atomic Designでは、UIを５つのレイヤーに分割します。(それぞれのレイヤーの具体的な説明は別記事で行います。)
・Atoms(原子)
最小のコンポーネント(ボタンなど)
・Molecules(分子)
ユーザーの動機に答え、具体的な役割を持たせたコンポーネント(検索フォームなど)
・Organisms(有機体)
独立して機能が成立するコンポーネント
・Templates(テンプレート)
・Pages(ページ)

![atomic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659774/f1bb9e81-3381-db53-cf0a-24a51f9d9f6e.png)
出典元：https://atomicdesign.bradfrost.com/chapter-2/　

この図を見ると、Atomsが集まってMoleculesが構成され、Molecules&Atomsが集まってOrganismsができる、といった階層構造になっていることがわかるかと思います。

階層化することにより、
・上位の階層の変更が下位のコンポーネントに影響を与えることがない(気にする影響範囲が少ない)
・UIデザインのどこに問題があるかが顕在化しやすい(ボタンに問題があるのか、ページの構成に問題があるか、など)
といったメリットを享受できます。

また基本的なルールとして
「小さなコンポーネントが大きなコンポーネントを含まない」という依存の方向性
が存在します。Moleculesの中にOrganismsは含まない、といった具合です。

Atomic Designではコンポーネントの簡単な分類方針のみが示されているので、具体的な部分は自分たちで決める必要があります。
私の担当するプロダクトでも、導入初期段階はチーム内で方針をすり合わせながら細かいルールを設定していきました。
ここのルール作りを詳細にやればやるほど、後の開発で悩む時間が減り、効率的だと感じました。

# Atomic Designで開発するときに役立つツール
### Story Book
https://storybook.js.org/
こちらは、コンポーネントを整理しカタログ化できるツールです。
開発中にどのようなコンポーネントがあったか忘れてしまうor把握していないことで余計なコンポーネントを作成してしまったり、コンポーネントの確認に時間を使ってしますことはよくあります。Story Bookを使用することでコンポーネントの見た目と概要を即座に確認できるので、そのような事態を防ぐことができるほか、開発スピードの向上にもつながります。

# まとめ
今回はAtomic Designの概要についてまとめてみました。別記事でもう少し深ぼって書いて行きたいと思っています！

## 参考文献

- 五藤佑典, 「Atomic Design ～堅牢で使いやすいUIを効率良く設計する」, 技術評論社, 2018

- Atomic Design by Brad Frost https://atomicdesign.bradfrost.com/
ラズパイのローカルIPアドレスを確認する

久しぶりにラズパイを操作したときに、VNC接続ができなかった時のメモです。

# 環境
OS: windows 10.0
raspberry pi zero

# 試みたこと
## 1.SSH接続をする。
パワーシェルからSSH接続をしました。

```
ssh ユーザー名@raspberrypi.local
```
## 2.ifconfig コマンドで調べる
```ipconfig```と入力すると、インターフェースの情報を見ることができます。wi-fiでラズパイに接続している場合は、wlan0 の inet の隣に書いてある xxx.xxx.xxx.xxx の部分が Raspberry Pi の IP アドレスになります。
```
ifconfig
```

これでVNC接続を復帰することができました。よかった。また、[PCからラズパイへVNC接続する。](https://qiita.com/yutaka_m/items/02672f75d5b62801c85b)方法については、こちらにまとめていますので、ご参考になれば幸いです。
auひかりで時々特定サイトがつながらない問題に遭遇してしまう

<H1>症状</H1>
GoogleやYoutubeはつながるのにYahoo!にはつながらない。そんな症状に遭遇します。これはIPV6アドレスでアクセスができるウェブサイトへはアクセスできるのに、IPV4アドレスでしかアクセスできないウェブサイトへは接続できない（DNSエラー）となるような症状の一例です。
今回auひかりに切り替えた結果遭遇した問題を簡単にまとめていきます。
<H1>原因</H1>
突然接続不可能になるとき、いくつか目につくことがあります。例えばWindowsのネットワークの接続が完了しない（イーサネットの識別中の表示が出たまま）というようなことや、ipconfigで確認するとIPV4アドレスが提供されていない状態が見えます。
これは、auひかりで提供しているHGW(Home GateWay)のDHCPサーバーが正しくDHCP情報を配布しないことに起因しています。

<H1>対処法</H1>
いくつか対処法があるので列挙します。

- IPV4アドレスを固定する。MACアドレスに応じてIPV4アドレスを固定で付与するようにすると今のところ問題が回避できています。
- クライアント側でIPV4アドレスを固定で指定する。HGWのDHCPサーバーを使用しなければ問題が回避できます。
- HGWとは別にDHCPサーバーを設ける（ルーターを別途追加で接続する）方法もありますが、ルーターとHGW間でこの問題が起きてしまうとダメなので、その点を考慮して、上２つの回避策をルーターに適用しておく必要があります。また、必ずしも多段ルーターとして稼働させることが必要なのではなく、DHCPサーバーを立てるだけの目的で使用するものです。
- 効果のほどは未確認ですが、DHCPサーバーのIPV4アドレス範囲を変更しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/831262/4b2c3652-b1df-3d7d-9678-8d816aff7522.png)
PowerAutomate: 実行履歴が見やすく機能向上されました

# 背景
大量の実行履歴の中から、目的のものを探す場合面倒だなぁと感じてたら、いつの間にか探しやすくなってたので紹介まで

# 概要
実行履歴画面で、表示列の編集が追加されてます。

で、この表示列、Trigger-Outputs に依存しているので、Trigger 毎に識別できるフィルターとして使えます

日本語版
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/57d782ee-67aa-176f-1f77-47205f39d436.png)

英語版
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/63fdc664-5ccf-df24-f729-2a68b50f79ae.png)

# 具体例
## トリガー: [新しいチャネル メッセージが追加されたとき](https://learn.microsoft.com/ja-jp/connectors/teams/#%E6%96%B0%E3%81%97%E3%81%84%E3%83%81%E3%83%A3%E3%83%8D%E3%83%AB-%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%8C%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9F%E3%81%A8%E3%81%8D)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/b987c882-6dec-75fe-07ae-25878e8978eb.png)

このトリガーの場合、subject を表示させることで、スレッド件名が見えるので、分かりやすくなりますね。


実際の投稿との比較
Message ID も表示されてて意外に便利そう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/49ead9bb-1cfb-0713-a504-e516bc07a7d3.png)


::: note
 Message ID の確認は以下のやり方
:::
https://qiita.com/baku2san/items/3756201744e0886912d1

# あとがき
これで開発が捗りますね。
会社で Graph API の管理者権限が欲しい・・
Flaskアプリケーションのセッション問題

Flaskでアプリケーションを作っていて、ちょっとはまったのでメモ。

## 複数のFlaskアプリケーション

Flask でセッションを使うには、
```Python
app = Flask(__name__)
app.config['SECRET_KEY'] = b'適当なキー文字列'
```
と設定するのは周知の通り。

たとえば、Flask のアプリケーションを2つ稼働しているとして、
どちらもセッション情報を使う（たとえばログイン情報を保持しておくとか）場合。
同じブラウザの別タグで、それぞれのアプリケーションを開いて、タブを切り替えたりしていると、片方のセッションが消えてしまう現象が発生する。
FlaskはCookie にセッション情報を保存するが、デフォルトだと、"session" という名前になる。
![cookie1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882462/d690a5c8-0f80-d15f-42df-e2de92226281.png)

アプリケーション1つなら問題ないが、2つの場合、同じ"session" という名前でCookie に書き込まれるので、後から開いた方のセッション情報で、前の情報が上書きされてしまうことになる。

これを回避するためには、cookie に保存するときの名前を設定する。
```Python
app.config['SESSION_COOKIE_NAME'] = 'hogehogeApp01_Cookie_name'
```
もちろん、それぞれのアプリケーションで名前は変えておく。
![cookie2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882462/96fc8faf-8b1e-cea9-40e3-876269161ef3.png)
設定した名前でCookie が保存されるので、上書きされることがなくなる。

## iPhone 対応
本番稼働直前の最後のテストで、iPhone で試していて発覚した問題。
FlaskがSession情報をCookieに保存するのは前述の通りだが、デフォルトだとiPhone にはCookieが保存されなかった。
どうやらiPhoneではサードパーティクッキーとして認識されると、そのCookie をさくっと削除してしまうらしい。
いろいろ試した結果、
```Python
app.config['SESSION_COOKIE_SECURE'] = True
app.config['SESSION_COOKIE_SAMESITE'] = 'None'
```
この2つを追加したところ、iPhoneにもCookie が保存されるようになった。
ちなみに、
app.config['SESSION_COOKIE_SAMESITE'] = None
ではなく、
app.config['SESSION_COOKIE_SAMESITE'] = 'None'
と文字列で設定しないとNG。
eclipse警告"assignment to variable xxx has no effect"についての覚書き

ええと、入門者向けテストにありがちなクイズだと思いますが、以下のJavaコードがあった時、aが増えないステートメントはA～Fのどれでしょうか。
```java
public class IncTest {
	static int a;
	static int b;
	public static void main(String[] args) {
		a++;      //A
		a=a++;    //B
		a=(a+=1); //C
		a=a+1;    //D
		a=++a;    //E
		b=a++;    //F
		System.out.println(a);
		System.out.println(b);
	}
}
```
正解はBですね。Javaの仕様では、上記のうちBの文a=a++;のみ、aのインクリメントが意味を持ちません。後置インクリメントa++は代入操作の後に行われることになっていますが、代入先もaなので、インクリメント前の値でアサインが完了してしまい、文の判定としてはインクリメント前のaに戻される（もともとのaが残る）ことになります。上記の実行結果は以下。

```
5
4
```

ただですね、ちょっと似たコードをeclipseで書いたとき、その警告文で少し戸惑ったんですよ。eclipseバージョンは2022-6(4.24.0)です。下記キャプチャのように、"assignment to variable a has no effect"の警告が、意味のないはずの文B(a=a++;)ではなく、E(a=++a;)の文の方に出てきたからです。
![eclipseWarning2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2866483/a13bd308-5aa4-e963-42d8-e56d1322171e.png)
先に言っておくと、これは正しい仕様です。それでも、「え、no effectなのはE(a=++a;)ではなくてB(a=a++;)の方なのでは・・・」と気になって確認したので、メモとして記事を残しておきます。

まず、この警告メッセージ、「変数への代入(アサインメント)の効果が無い」と言っているのであって、その文(ステートメント)に効果が無いと言っているわけではありません。代入に意味があるか、それ無しで結果が同じかがポイントなわけです。Eのa=++a;は、++a;と同じように1増える。つまり「a=」は無意味なので警告が出る。逆に、Bのa=a++;は、a++;と同じではない。文は結果としてaを変えないが、代入にはインクリメントを無効化する効果がある。なので、Bは警告が出ないのが正しい。・・・いや、考えたらその通りなんですけどね。詳しい方は「当たり前だろ」と思ってるかもしれません。

いちおう、eclipseの気持ちを確認するために、以下のように書き換えてみました。

```java
public class IncTest {
	static int a;
	static int b;
	static volatile int c;
	public int d;
	IncTest(int d) {
		a++;      //A
		a=a++;    //B
		a=(a+=1); //C
		a=a+1;    //D
		a=++a;    //E
		b=a++;    //F
		c=++c;    //G
		d=d;      //H
		this.d=d; //I
	}
}
```

eclipseの言いたいことは、volatile宣言した変数cを見ると、更に明確になります。上記のうち、G(c=++c;)はE(a=++a;)と同じ前置インクリメント後の代入なのに警告が出ません。代入操作（c=と書くこと）に、コンパイラにとってのキャッシュ制御上の意味がある(かもしれない)からです。「=」が無駄なら警告が出るし、何らかのエフェクトがあれば出ないという基準が再確認できます。なお、このvolatile宣言時の規定については、2010年頃にeclipse仕様が修正される前の掲示板のやりとり(BUG 310264)を確認することができました。

https://bugs.eclipse.org/bugs/show_bug.cgi?id=310264

また、上記コード、mainメソッドではなく引数:int dのコンストラクタに書き換えているのですが、H(d=d;)とI(this.d=d;)についてはどうでしょうか。当然のように、Hには警告が出てくれました。恐らくですが、この警告のメインターゲットは、このthis.d=d;をd=d;と誤って書いてしまうケースなのではないでしょうか。割と起こりえるミスなので、やはり、この警告の存在自体は助かります。逆に、私が勝手に混乱していたB(a=a++;)とE(a=++a;)のようなコードは、冒頭のクイズ問題のような例外的ケースでしか書くことがないでしょう。


今回は、少し検索すれば出てくるような内容なので、ちょっとネタとしては微妙だったかもしれません。ただ、volatileの話と警告の意義(this抜け防止)を含めて書くと意味があるかもと思ったので・・・。以上、覚書きでした。
Pythonによる日付処理

SageMakerからデータベースにクエリを投げる際にデータ年月日やテーブル名に日付を指定する必要が多々ある。
その際に目当てのテーブル名や日付のカラムの形式、データ期間の指定において、日付を変数化して操作したい場合があるため、備忘メモとしてここにまとめる。

## 形式の変換（日付型→文字列型）
```python
from datetime import date

TARGET_DATE = date(2022, 9, 29)
print(type(TARGET_DATE))
print(TARGET_DATE)
```
`<class 'datetime.date'>`
`2022-09-29`

```python
# 形式の変換（文字列）
Ymd = TARGET_DATE.strftime('%Y%m%d')
hyphen = TARGET_DATE.strftime('%Y-%m-%d')
slash = TARGET_DATE.strftime('%Y/%m/%d')
Ym = TARGET_DATE.strftime('%Y%m')

print(type(Ymd), Ymd)
print(type(hyphen), hyphen)
print(type(slash), slash)
print(type(Ym), Ym)
```
`<class 'str'> 20220929`
`<class 'str'> 2022-09-29`
`<class 'str'> 2022/09/29`
`<class 'str'> 202209`

## 形式の変換（文字列型→日付型）
```python
# 文字列型から日付型に変換
str_TARGET_DATE = '2022-09-29'
print(type(str_TARGET_DATE))
print(str_TARGET_DATE)
```
`<class 'str'>`
`2022-09-29`

```python
from datetime import datetime

date_TARGET_DATE = datetime.strptime(str_TARGET_DATE, '%Y-%m-%d').date()
print(type(date_TARGET_DATE))
print(date_TARGET_DATE)
```
`<class 'datetime.date'>`
`2022-09-29`

## 形式の変換（数値型→日付型）
```python
# 数値型から日付型に変換
int_TARGET_DATE = 20220929
print(type(int_TARGET_DATE))
print(int_TARGET_DATE)
```
`<class 'int'>`
`20220929`

```python
from datetime import datetime

date_TARGET_DATE = datetime.strptime(str(int_TARGET_DATE), '%Y%m%d').date()
print(type(date_TARGET_DATE))
print(date_TARGET_DATE)
```
`<class 'datetime.date'>`
`2022-09-29`

## 日付の加算・減算
```python
# 日付の加算・減算(日単位)
from datetime import date
from datetime import timedelta

today = date(2022, 9, 29)
tomorrow = today + timedelta(days=1)
yesterday = today - timedelta(days=1)

print(yesterday)
print(today)
print(tomorrow)
```
`2022-09-28`
`2022-09-29`
`2022-09-30`

```python
# 日付の加算・減算(月単位)
from datetime import date
from dateutil.relativedelta import relativedelta

today = date(2022, 9, 29)
next_month = today + relativedelta(months=1)
last_month = today - relativedelta(months=1)

print(last_month)
print(today)
print(next_month)
```
`2022-08-29`
`2022-09-29`
`2022-10-29`

## 日付の置換
```python
# 日付の置換(当月の月初日・月末日を取得)
from datetime import date

today = date(2022, 9, 29)
this_month_first_day = today.replace(day=1)
this_month_last_day = today.replace(day=1) + relativedelta(months=1) - timedelta(days=1)

print(this_month_first_day)
print(today)
print(this_month_last_day)
```
`2022-09-01`
`2022-09-29`
`2022-09-30`
「LEGO 部品を利用した回転型倒立振子のレシピを公開！」のまとめ



# <font color="#0070C0">レシピはこちら</font>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2552191/142e0ad8-e4ec-52b2-58d3-4c068b5770d0.png)


:::note info
<b><font color="#0070C0">LEGO 部品を利用した回転型倒立振子のレシピを公開！</font></b>
* [第 1 回：組み立て](https://qiita.com/Carter/items/6027bcb12dc7740e8dc3)
* [第 2 回：電子工作](https://qiita.com/Carter/items/ecad7ee7b8ea76c87c33)
* [第 3 回：運動方程式 ― MATLAB / Symbolic Math Toolbox](https://qiita.com/Carter/items/b4b77305f6a634a08468)
* [第 4 回：パラメータ同定 ― MATLAB / Simulink](https://qiita.com/Carter/items/80a1ed5d09f9dc420871)
* 第 5 回：現代制御 ― MATLAB / Simulink　…… <font color="#E84746">未完成</font>
* 第 6 回：アドバンスト制御 ― MATLAB / Simulink　…… <font color="#E84746">未完成</font>

<b>おまけ</b>
* [Simulink の分岐処理を利用して『回転型 LEGO 倒立振子』を振り上げ安定化！](https://qiita.com/Carter/items/db4bb11ead93ea3a1d42)


<b>補足</b>
*  [【補足説明】Simulink Support Package for Arduino Hardware と RASPLib をインストールして MinSegShield を動かしてみる](https://qiita.com/Carter/items/cc7faa5084aa4a69f4e7)
* [【補足説明】Simulink Support Package for Arduino Hardware で DC モータを動かしてみる](https://qiita.com/Carter/items/1c5f3ec49dbaa87bba79)
:::



# <font color="#0070C0">YouTube 動画はこちら</font>

[YouTube 「かーたー」チャンネル](https://www.youtube.com/channel/UCQxZZypRXCsvALuvmWy68jw)

https://youtu.be/MfhpdYHZtJ0
インタラクションコストについて

## はじめに
 UIデザインについて勉強したなかで「インタラクションコスト」というものを学んだので記事にしようと思います。
## インタラクションコストとは
 インタラクションコストとはインターフェースの操作を通してユーザーにかかる「身体的負荷」と「認知負荷」を合わせたものです。例えば、ボタンの位置が押しにくい場所にあれば
身体的負荷は大きくなり、読みにくい文章に対しては認知負荷は高くなります。いいインターフェースを作るにはこのインタラクションコストをいかに減らすことができるかが重要です。

## 身体的負荷と認知負荷
 身体的負荷と認知負荷のどちらを優先的に軽減するべきか、シチュエーションによって変わってきます。利用頻度が多い場面では身体的負荷の軽減を優先的に、利用頻度が低い場面では認知負荷の軽減を優先的にすべきです。
 ユーザーはよく使う機能に対して学習を重ねることで認知負荷がかからないようになっていきますが、身体的負荷は常に一定です。そのため利用頻度の多い場面では身体的負荷を減らした方がインタラクションコストは少なく済みます。一方、新規登録など1回くらいしか使われないものであれば、身体的負荷よりも認知負荷の軽減を優先させるべきです。そういった場面では使いやすさよりも分かりやすさの方が重要であるということです。

## インタラクションコストを下げる方法
 インタラクションコストを下げる方法はサービスによって様々ありますが、使いやすいサービスには共通してインタラクションコストを下げる要素があるようです。それは「シンプル」、「一貫性」、「共通概念」です。
「シンプル」にすること、つまり重要なものの優先度をあげて他を削ることで、意図が明快になりユーザーの認知負荷を下げます。またサービスのデザインに「一貫性」をもたせることで、ユーザーの学習コストが抑えられます。そして、全世界の「共通概念」に則ったデザイン（検索は虫眼鏡アイコンなど）にすることでも学習コストが抑えられます。


## おわりに
今後はインタラクションコストの軽減を意識したUIデザインを行なっていきたいです。

## 参考
https://www.amazon.co.jp/UI%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E5%BF%85%E6%90%BA-%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%AE%E8%A8%AD%E8%A8%88%E3%81%A8%E6%94%B9%E5%96%84%E3%82%92%E6%88%90%E5%8A%9F%E3%81%95%E3%81%9B%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AB-%E5%8E%9F%E7%94%B0-%E7%A7%80%E5%8F%B8/dp/4798169625
Rust 超入門 → Hello World!

### 初めてのRustファイル

```hello_world.ts
fn main() {
    println!("Hello, world!");
}
```

**ファイルをビルド**
```bash
# rustc hello_world.rs
# ls
hello_world  hello_world.rs
```

**ファイル実行**
```bash
# ./hello_world 
Hello, world!
```
【Java】IntelliJ IDEAで環境変数を設定する方法

# はじめに
今回は、環境変数の設定について調べたことをまとめます。

※おことわり※
基本的に学習内容のアウトプットです。
初学者であるため、間違い等あればご指摘いただけますと嬉しいです。

# この記事の目的
以下内容のアウトプット

- IntelliJ IDEAで環境変数を設定する方法
- application.propertiesでシステム環境変数を扱う方法

# 開発環境
- Java 17.0.4.1
- Spring Boot 2.7.4
- IntelliJ IDEA

# この記事の内容
1. 前提
2. 環境変数を設定する
3. application.propertiesの記述を変更する

# 1. 前提
リモートリポジトリにプッシュするため、`application.properties`の以下内容を環境変数に置き換えたい。

```application.properties
# 現状
spring.datasource.url = データベースのURL
spring.datasource.username = ユーザー名
spring.datasource.password = パスワード

# この形にしたい
spring.datasource.url=${SPRING_DATASOURCE_URL}
spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
```

# 2. IntelliJ IDEAで環境変数を設定する
以下手順で、環境変数を設定します。

① 実行(Run)タブから、`実行構成の編集...`を選択
[![Image from Gyazo](https://i.gyazo.com/ca1dbfc87d48f5b59927456f1636efd5.png)](https://gyazo.com/ca1dbfc87d48f5b59927456f1636efd5)

② 環境変数を記述し、`適用・OK`をクリック
```Java
//例
HOGE=設定したい内容

//複数ある時
HOGE=xxx; HUGA=xxx

//今回
SPRING_DATASOURCE_PASSWORD=xxx; SPRING_DATASOURCE_USERNAME=xxx; SPRING_DATASOURCE_URL=xxx
```
[![Image from Gyazo](https://i.gyazo.com/d06b68a2fa8df4de15635f5a7b6d66d1.png)](https://gyazo.com/d06b68a2fa8df4de15635f5a7b6d66d1)

# 2. application.propertiesでシステム環境変数を扱う方法
先ほど設定した環境変数を、application.propertiesで扱うための記述を行います。

```application.properties
spring.datasource.url=${SPRING_DATASOURCE_URL}
spring.datasource.username=${SPRING_DATASOURCE_USERNAME}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
```

アプリケーションを再実行し、今まで通り動いたら成功です。

# 参考

https://www.twilio.com/blog/set-up-env-variables-intellij-idea-java-jp

https://qiita.com/turn-take/items/75975d15625c3a750000
レーマー符号 (Lehmer code)

## レーマー符号とは

[レーマー符号](https://ja.wikipedia.org/wiki/%E3%83%AC%E3%83%BC%E3%83%9E%E3%83%BC%E7%AC%A6%E5%8F%B7)とは、並べ替えを符号化する方法の一つ。普通並べ替えを表すのには、シーケンス番号の列を使ったりするが、それだと基の列との差分の大きさがわかりにくい。レーマー符号だと、それがわかりやすい、ということらしい。

レーマー符号は、次のように定義される。 


``` math
L(\sigma )=(L(\sigma )_{1},\ldots ,L(\sigma )_{n})\quad \text{where} \quad L(\sigma )_{i}=\#\{j>i:\sigma _{j}<\sigma _{i}\}
```

ここで $L(\sigma)\_{i}$ は $\sigma\_{i+1},\ldots,\sigma\_{n}$ のうち $\sigma\_{i}$よりも小さいものの個数である。と言われてもよくわからん。。

日本語のWikipediaにはエンコード、デコードの方法が書かれていないが、[英語版](https://en.wikipedia.org/wiki/Lehmer_code)を見ると、割に簡単な再帰で書ける事がわかる。Pythonで書くとこんな感じ。


``` python
def lehmer(input):
    if len(input) > 1:
        head = input[0]
        rest = input[1:]
        rest = [r-1 if r>head else r for r in rest]
        return [head] + lehmer(rest)
    else:
        return input
```

デコードも同様に再帰で書ける。

``` python
def lehmer_decode(input):
    if len(input) > 1:
        head = input[0]
        rest = lehmer_decode(input[1:])
        rest = [r+1 if r >= head else r for r in rest]
        return [head] + rest
    else:
        return input
```


## 例

試してみよう。identity projection は0の列になる。

``` python
>>> lehmer([0,1,2,3,4,5,6])
[0, 0, 0, 0, 0, 0, 0]
>>> lehmer_decode([0,0,0,0,0,0,0])
[0, 1, 2, 3, 4, 5, 6]
```

6だけが一番前に行った列`[6,0,1,2,3,4,5]`を考えてみよう。これはアイテムごとに比較すると、もとの列と一致している点はどこにもないが、列としては一つずれているだけだ。レーマー符号にすると次のようになる。

``` python
>>> lehmer([6,0,1,2,3,4,5])
[6, 0, 0, 0, 0, 0, 0]
```

これだと最初に大きくずれたあとは正しく並んでいることがわかる。
AWS ECSのEC2＋サービスの検出でサービス間通信できなくて苦しんでいる人へ

# 症状

AWS ECSでサービス間通信（＝コンテナ間通信）をするためにサービスの検出（サービスディスカバリ）を設定したけど、上手く通信してくれない。

# 状況

* ECSでクラスターを作る時、あるいはタスク定義を作るときに、EC2タイプを選んだ。
* ローカルではコンテナ間通信できているのにアップしたらできないのは何で？
* タスク定義するとき、「ネットワークモード？何それ？適当にDefaultとかでいいでしょ」

みたいな状況。

通信できなさすぎて何度もクラスターとかタスク定義とかサービスとか作り直して、もう細かいことを説明しなくても大体分かる人向け。

# 原因

タスク定義を作成するときのネットワークモードを`awsvpc`以外にしていると、サービスディスカバリはDNS（＝Route 53）に`A`レコードではなく、`SRV`レコードを作る。

> サービスタスク定義が bridge または host ネットワークモードを使用する場合、SRV レコードのみがサポートされる DNS レコードタイプです。各サービスタスクの SRV レコードを作成します。SRV レコードのコンテナ名とコンテナポートの組み合わせをタスク定義から指定する必要があります。
[サービス検出 \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service-discovery.html) の中ほどより

だから、SRVレコードから上手くIPを引っ張ってくるような作り方をしないと、ただ単に問い合わせしただけでは解決してくれない。

例：[ECS Service Discoveryを試してみる \- Qiita](https://qiita.com/atsumjp/items/7c4c8640629f9eff4827)
（IPを見つけるためにDNSレコードを手動で辿って行っている。アプリで自動化するならそんな感じの対策が必要と思われる。）

ネットワークモードを`awsvpc`にすると、

> サービスタスク定義が awsvpc ネットワークモードを使用する場合、各サービスタスクに A または SRV レコードを自由に組み合わせて作成できます。SRV レコードを使用する場合、ポートが必要です。
[サービス検出 \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service-discovery.html) の中ほどより

ということで、サービスを作成するときの「サービスの検出」で`A`レコードが選べるようになるからそれを選ぶと普通に一発で名前解決をして通信できるようになる。

ちなみに、クラスターを作る時とタスク定義を作るときにデータプレーンとしてFargateを指定するように作っていくと、ネットワークモードは勝手に`awsvpc`になるので、サービス作るときに「サービスの検出」で自然と`A`レコードが選べるようになるってわけ。

# よく考えたら・・・

「サービスディスカバリやってみた」的な記事はほぼ全部Fargate使ってるから、「ほら、簡単でしょう？」みたいなことしか書いていない。

自分は「EC2の方が実体が見えて分かり良いでしょ！」みたいに考えて勝手にEC2タイプで進んでしまったので、なぜ自分はできないのか気づくのに時間がかかった。

同じように苦しむ人が成仏できますように・・・

# その他

↓ここにコンテナ間通信のやり方を3通り書いてくれている。
[VPC 内の Amazon ECS サービス間のネットワーキング \- Amazon Elastic Container Service](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/bestpracticesguide/networking-connecting-services.html)
【Bash】リダイレクト一覧

```bash
# 入力
command < file   # ファイルの内容をコマンドの標準入力に渡す

command >&2      # 標準出力を標準エラー出力にリダイレクト

command > file   # ファイル新規作成または上書き

command >> file  # ファイル新規作成または追記

command 2> file  # 標準エラー出力をファイルにリダイレクト(新規作成または上書き)

command &> file      # 標準出力/エラー出力を同一ファイルにリダイレクト
command > file 2>&1  # 同上
command &>> file     # 標準出力/エラー出力を同一ファイルに追加書き込み
command >> file 2>&1 # 同上

command > file1 2> file2   # 標準出力,エラー出力を別々のファイルにリダイレクト
command >> file1 2>> file2 # 標準出力,エラー出力を別々のファイルに追加書き込み
```
Laravelのsave()を行ったが、データベースにデータが登録されなかった話

laravelのコントローラーで、エラーが発生していないのにデータベースへの登録ができない状況が発生しました。非常に単純なミスなので、同じ過ちをしないように備忘録として残しておきます。

## ■原因
DB::beginTransaction();を行った後、try{}内でsave()を行った後、
DB::commit();をしていなかったから。

## ■諸現象
実際にどのような状況になるのかというと、
①Laravel.logにはエラーは吐かれない→正常
②Laravel.logにSQL文を表示させると、きちんとinsert()がされていることを確認できる→正常
③axios通信の場合、201createdがresponse.statusとして返却される→正常
④axios通信の場合、response.dataとして、登録したデータを取得することができる→正常
⑤データベースのidが飛ばされる
　例：id=1のデータ→データベースに登録済
　　　id=2のデータ→上記原因により、データベースに登録されない現象が発生
　　　id=3のデータ→データベースに正常に登録できた
例の場合は、データベースを確認するとid=1、id=3のデータしか確認できず、
idが飛ばされる現象が発生→おかしい

このような状況となる。
Laravelについての不勉強とエラーが発生しないことにより、原因の特定が遅れた。

## ■原因特定方法
### ①データの代入に問題（変数名が違う、型が違うなど）があるのか？
```userController.php

$user = new User();
DB::beginTransaction();
try{
$user->name = $request->name;
//age以外では、データベースへの登録ができるかどうか確認する
//$user->age = $request->age;
$user->place = $request->place;
$user->save();
} catch (\Exception $exception){
            DB::rollback();
            throw $exception;
        }
```
変数のミス、代入時のミスはあるあるなので、まずは一つずつ間違っていないか確認。
上記のように、一つずつ代入する値を入れ替えていき、問題個所を特定しようとした。
しかし、どのパターンで試してもデータベースへの登録ができず、変数の代入に問題があるわけではないことが判明する。

### ②try catchを外してデータベースの登録ができるか確認

```userController.php

$user = new User();
//例外処理を行わず、そのままデータベースへ登録する
//DB::beginTransaction();
//try{
$user->name = $request->name;
$user->age = $request->age;
$user->place = $request->place;
$user->save();
//} catch (\Exception $exception){
//            DB::rollback();
//            throw $exception;
//        }
```
②を行うと、データベースへの登録ができたため、トランザクション処理に原因があると判明し、原因特定に至る

### ③トランザクション処理を修正し、正常にデータベースへの登録ができることを確認
```userController.php

$user = new User();
DB::beginTransaction();
try{
$user->name = $request->name;
$user->age = $request->age;
$user->place = $request->place;
$user->save();
//DB::commit();を書き忘れていたため、加筆
DB::commit();
} catch (\Exception $exception){
            DB::rollback();
            throw $exception;
        }
```
AWSのアカウントを分けるか迷ったとき

先日エンジニア間の雑談で話題になった件をフローチャートにしてみました。

![aws_multi_accountr_dis_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570665/8e255488-07ac-63fd-0a4e-f9150e2f3d86.png)

異論や細かい理由はいくつでもつけられるので、もろもろすっ飛ばして書いています。

アカウント分離統合の傾向としてベンチャー企業では複数の環境をアカウント１つで運用していることが多く、SIerや大企業だと分けていることが多い感じです。
他にもパラメータは多数ありそうですが、ざっくりと考える材料に如何でしょうか。

この理由についてサーベイしていると、下記が参考になりました。
併せてお読みください。

https://qiita.com/morih90/items/190e52285a3fd615601d
https://qiita.com/14kw/items/46a0054d90a4f5d779c4
https://qiita.com/ooooouchi/items/1aa44f4781252f4191b3
はじめてFlutterイベントを主催した話

# はじめに
こんにちは！ヨシカワです！
2022年9月25日にはじめて主催したFlutterイベント「サンプルを使って学ぶFlutter」を開催しました。
今回は、ポートフォリオの意味も込めて、大変だったこと、楽しかったこと、改善すべきだと思ったことを書きたいと思います。

# 目次
[主催したイベントについて](#主催したイベントについて)
[大変だったこと](#大変だったこと)
[楽しかったこと、うれしかったこと](#楽しかったこと、うれしかったこと)
[改善すべきだと思ったこと](#改善すべきだと思ったこと)
[おわりに](#おわりに)

# 主催したイベントについて
## イベント名「サンプルを使って学ぶFlutter」
「サンプルを使って学ぶFlutter」は、Flutterプロジェクトを立ち上げた時に表示されるサンプルプログラムの軽い解説と、それをすこーしだけ書き換えて自己紹介アプリを作る！！というハンズオンです。

最終的に下の動画のようなアプリができます。

![ezgif.com-gif-maker.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1877808/e2567dcb-d4ce-f845-ccf0-d7d68bfbca59.gif)

この記事ではコード等の具体的な説明は省きます。あくまで、「イベントを主催したよー」っていう話なので...。
「[おわりに](#おわりに)」に当日使った資料のリンクを張っていますので気になる方は是非ご覧ください！
# 大変だったこと
大変だったことはズバリ「感覚で覚えていたことの言語化」です。
まず、自分がイベントで話したいこと、伝えたいことを頭の中で整理します。そして、その頭の中で整理したことを適宜、図を使いながら参加者にわかりやすく伝えられるようにスライド資料をまとめます。
 
**でも、これがいざやってみると難しい！！**

自分の頭の中ではなんとなくわかっているんだけど感覚で覚えてしまっていて言語化が難しいところがたくさんありました。
例えば、mainAxisAlignmentとか...。
mainAxisAlignmentは親ウィジェットの並び方向（主軸）の真ん中に配置するんですけど、今までは「あ〜これを配置したら不思議と真ん中に配置されるんだなー」って感じに覚えてて具体的にどのように配置されるのか覚えていませんでした。

でも、このイベントの資料作りを通して、今まで自分が感覚で覚えてしまっていたことを具体的にまとめて言語化できたのでとても良い経験だったなと思ってます。

# 楽しかったこと、うれしかったこと
楽しかったことは「参加者の皆さんとのコミュニケーション」です。イベントを主催するのが初めてで緊張しまくっていた私ですが、皆さんが温かく接していただいたおかげでだんだんと緊張がほぐれ、気持ちよく解説ができて楽しく参加者の皆さんとコミュニケーションをとることができました！

うれしかったことは「参加者の皆さんをハンズオンのゴールまで導けたこと」です。このハンズオンではやはり幾つかのアクシデントが発生しました。エミュレータが起動しない問題だったり、どんなコードを書くかド忘れしてしまったり...。
それでも、時間が進むにつれ着実にゴールに近づいていき、最終的に5分ほど時間が押してしまいましたが参加者の皆さんをゴールに導くことができました！

# 改善すべきだと思ったこと
今後またイベントを主催するにあたって、改善すべきだと思うところは「時間がかかる工程をしっかり把握する」です。
イベントを進行するにあたって一番グダッてしまった時が、エミュレータを起動する時です。なぜエミュレータを起動する時なのかというと、今回参加者の皆さんには事前にFlutterの環境構築をお願いしていましたが、Android Studioでエミュレータを作成するところまでは指示していませんでした。
Android StudioはまずDevice Managerで使用するエミュレータを作成しなければなりません。しかし、それを事前にお願いしていなかったとするとエミュレータを起動する際に作成の工程が必要になります。さらに、その作成の工程がかなり時間がかかるので、それを待っているようではハンズオンの時間を押してしまいます。

なので今後、イベントを主催する際には時間がかかる工程をしっかりリサーチし、当日グダってしまわないように参加者の皆さんに「環境構築において時間がかかる工程とリサーチし、事前にお願いする」ようにしようと思いました。
# おわりに 
ここまで読んでいただきありがとうございました！

このイベントで、大変だったこと、楽しかったこと、嬉しかったこと、改善すべきだと思ったことが自分自身の成長につながったことを実感しました！。

最後に、このイベントの資料をSpeaker Deckにアップロードしましたので、気になる方は[こちら][link-1]から是非ご覧ください！

[link-1]: https://speakerdeck.com/yoshikawa0918/sanpuruwoshi-tutexue-buflutter-zi-liao
Fire TV Stick (第3世代)を買ったのでTokyofm (東京FM)を聞く( ブラウザ radiko )(いろいろしたいので)


x ここは、東京近郊
x なぜか　radiko の　位置情報が間違っていた。


目的
とりあえず　らじぉ　を聞く


いろいろ
Fire TV Stickで「ちょうしにのって」いろいろすると
理由も告げずロックアウトされるそうなので
アマゾンが想定された範囲のいろいろをする
「良い子」にてっしないとな
全て閉鎖環境で非公開でやる分には、いいのかな
やっぱだめか
「開発」ならOKなのかもしれないが　めんどい
「ユーザー」が想定される範囲でGO


1. PCのGoogle Chrome から　radiko 地域判定について に　移動


https://radiko.jp/contact3


2. 申請後しばらく待つ　朝に申請して夕方には、東京に変わっていた。

3. PCのGoogle Chrome で確認する


Fire TV Stickでの作業


1. マイアプリ・ゲームからinternetを選択

2. 検索で「radiko」と入力

3. デスクトップモードにする 

4. いろいろ頑張る　わすれた

5. radikoのホームページで東京FMを聴く

6. 聞けたのでおわり



![o_con829.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/62844580-f003-0c79-725e-01880c9231b0.jpeg)


![o_con830.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/37a76557-8a88-0178-5fe5-0c61f221c09e.jpeg)


![o_con831.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d12c34e2-716b-60b4-cc98-68009f084fa5.jpeg)
なぜAndroidのdpは4の倍数がいいのか

# 背景
Androidは様々なスクリーンサイズ、画素数の端末が販売されています。その一つ一つに合わせてレイアウトのデザインを作り込むのは大変です。
例えば100ピクセルの画像を画面に表示するようなデザインの場合、以下のような問題が出てきます。

- 端末のピクセルの画面サイズに合わせて画像を拡大縮小させる必要がある
- 端末によるピクセル密度が異なることもあるため、同じピクセルサイズの画面でも物理的なサイズが違うため、見え方も違う

そのため、Androidではdp, spという画面サイズや解像度に捉われることなく扱うことを目的とした抽象的な単位を提供しています。

# ピクセル密度とそれに対応した区分
Androidではdpiという「1インチあたりどれだけのピクセルが入っているか」の大きさによって端末の種類を区分けしています。
|汎用密度|倍率|説明|
|---|---|---|
|ldpi|x0.75|低密度（ldpi）画面（～120dpi）に適用するリソース|
|mdpi|x1|中密度（mdpi）の画面（～160dpi）に適用するリソース（基準密度）|
|hdpi|x1.5|	高密度（hdpi）画面（～240dpi）に適用するリソース|
|xhdpi|x2|超高密度（xhdpi）画面（～320dpi）に適用するリソース|
|xxhdpi|x3|超超高密度（xxhdpi）画面（～480dpi）に適用するリソース|
|xxxhdpi|x4|超超超高密度（xxxhdpi）の画面（～640dpi）用のリソース|

参考:https://developer.android.com/training/multiscreen/screendensities#TaskProvideAltBmp

表ではわかりにくいかもしれませんが、もしもレイアウトに1dpと指定した場合、実際のpx単位のサイズは以下になります。
|汎用密度|dp|px|
|---|---|---|
|ldpi|1|0.75|
|mdpi|1|1|
|hdpi|1|1.5|
|xhdpi|1|2|
|xxhdpi|1|3|
|xxxhdpi|1|4|

0.75px? 1.5px? 

# 「4の倍数」について
上記表からldpiとhdpiはかなり中途半端なpxサイズになってしまうのがわかるかと思います。
そこで、x0.75とx1.5という中途半端な倍率でも整数表示させるために登場したのがdpを「4の倍数」で指定するというものです。
dpを4の倍数で指定することで、各dpiの値は以下になります。

|汎用密度|dp倍率|px倍率|
|---|---|---|
|ldpi|x4|x3|
|mdpi|x4|x4|
|hdpi|x4|x6|
|xhdpi|x4|x8|
|xxhdpi|x4|x12|
|xxxhdpi|x4|x16|

よって4の倍数を指定することでpxは常に整数が指定されるため、実際の端末でもきれいに表示させることができるようになります。

レイアウトデザインでサイズ指定をする際にはぜひ4の倍数に気をつけてみましょう。
コスパ最強のWindows,Mac両方にも対応したBluetoothメカニカルキーボード買ってみた。（Logicool SIGNATURE K855シリーズ）

## この記事の対象者
- 最近Windows💻からMacに切り替えた人。
- メカニカルキーボード使いたいがお金💰がない人
- とりあえずメカニカルキーボード、デビューしたい人
- キーボード費用抑えたい人
- 複数のデバイスを切り替えながら作業する人
## キーボードの紹介
今回僕が実際に購入したのは、このキーボードです。

[Logicool SIGNATURE K855BG](https://amzn.asia/d/dnGKIy5)
![7141n9-NK9L._AC_SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/2901d16e-835f-8384-63d9-67777c6427b4.jpeg)
カラーは他にも3色あるみたいです。
[Logicool SIGNATURE K855RO　ローズ](https://amzn.asia/d/hRwXo1j)
![61mlc8UkO6L._AC_SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/50a8a19c-06cf-0e26-ce07-93a83b8eaf3d.jpeg)
[Logicool SIGNATURE K855GR　ブラック](https://amzn.asia/d/bUHRetD)
![61+UZzbF8AL._AC_SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/c824148e-a75d-0339-bd71-a34d63b97ecf.jpeg)
[Logicool SIGNATURE K855OW　オフホワイト](https://amzn.asia/d/bAYoxA8)
![61IEam7NCPL._AC_SL1500_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/ec5b4d50-5a24-c0f9-a427-f0c13258bc0c.jpeg)

## キーボード購入したらオススメしたいアプリ

2つあります。

1つ目は
[Logi OPTIONS +](https://www.logicool.co.jp/ja-jp/software/logi-options-plus.html#supported-keyboards)
![スクリーンショット 2022-09-29 18.57.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/8adb733c-da06-2287-7580-5c4f98b9d8b7.png)
- **できることその1**
↑こんな感じでショートカットキーを独自で設定したり、電池残量🪫が減ってきた時に通知してくれるようです。
- **できることその2**
僕は使ってないんですが、EASY -Switchで、複数のデバイスを登録でき、Fn +F1,F2,F3,で瞬時にキーボードを使いたいデバイスに切り替えることができます。
![スクリーンショット 2022-09-29 18.59.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/5b2868ef-2cbb-5899-d1f1-1f5f4373aa3f.png)

- **注意点**
キーボードのデフォルトだと、いつもFn押しながらボリュームなどを調整していたのに、押さなくても音量調節などができる状態

**つまり**は、F7押したのにカタカナに変更されない！！！F10押したのに半角にならない！！！**などとデフォルトで設定されていたので**

Fn押しながらに慣れている人は、設定タブの**F1、F2などのキーを標準ファンクションキー**として使用にチェック入れることをお勧めします。

2つ目は
[Logi OPTIONS +](https://karabiner-elements.pqrs.org/)
インストール方法は[こちら](https://karabiner-elements.pqrs.org/)参照しました。

んでこれなに？怪しい。と思ったんですがかなり便利でした。
- 自分で独自のキーバインドを設定できます。
- もうひとつは、作業スペース少なくて、キーボ置けない！！！
↑を解決してくれます。![スクリーンショット 2022-09-29 19.16.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882420/4c7838d3-dd95-0657-9032-df8b6863ac4c.png)

左端の**Devices>AdvancedにBluetooth**でキーボード繋ぐと↑のように表示されます。

Logi K855のところを画像のようにONにするとなんと

***MACBOOKにキーボードをこのLOGICOOLキーボードが繋がっている間は、
自動でMAC側のキーボードを無効化（使えないように）してくれます！！！***


是非作業スペースない方はお勧めなのでやってみてください！！！

MAC側のキーボード使いたくなったらBluetooth接続を切るだけ！！
※たまに、切った直後だと、MACキーボード反応しないことがありますが、
その時は、一旦Bluetoothに再接続して、切り直してみてください！

## 最後に
このキーボード使っての感想

- 打ちやすい（軽い）
- タイピングの音がいい感じ（気に触る人は嫌いなのかな。。）
- なによりデザインとコンパクトさがいい。

おすすめできるメカニカルキーボードだと思います〜
以上また何か新しい発見があれば、Quiitaに書いていこうと思います〜