OmniAICreator/Qiita-1.07M huggingface dataset:
シェル/コマンド/シェルスクリプトの関係性

# シェル/コマンド/シェルスクリプトの関係性

コンピューターを操作する際に、シェル、コマンド、シェルスクリプトは重要な役割を果たします。これらの要素は密接に関連しており、効率的なコンピュータ操作のためにはそれぞれの特徴と相互関係を理解することが重要です。

## シェルとは
シェルは、オペレーティングシステム（OS）に対してCLI（コマンドラインインターフェース）から指示を送るために使用されるプログラムです。ユーザーからのコマンドを解釈し、OSに命令を伝える役割を担います。

### シェルの特徴
- **コマンド解釈**: ユーザーから入力されたコマンドを解釈し、適切なアクションを実行します。
- **対話的操作**: ユーザーがリアルタイムでコマンドを入力し、フィードバックを受け取ることができます。

## コマンドとは
コマンドは、シェルを通じて実行されるCLI操作の手段です。これらはOSやシェルによって提供され、ファイル操作、プロセス管理、システム情報の取得など様々な操作を行うことができます。

### コマンドの役割
- **システム操作**: ファイルの作成、削除、移動などの基本操作を実行します。
- **プロセス管理**: 実行中のプロセスを監視し、制御することが可能です。

## シェルスクリプトとは
シェルスクリプト、またはバッチファイルは、一連のコマンドを組み合わせて作成されるスクリプトです。これにより、複数のコマンドを一度に実行し、繰り返しの作業を自動化することができます。

### シェルスクリプトの活用
- **自動化**: 定期的なバックアップ、システム監視などの作業を自動化します。
- **複合操作**: 複数のコマンドを組み合わせて、一つの複雑なタスクを実行します。

## シェル/コマンド/シェルスクリプトの相互関係
- **シェル**: コマンドを解釈し、実行する環境を提供します。
- **コマンド**: シェルを通じて実行される、個別の操作手順です。
- **シェルスクリプト**: 複数のコマンドを組み合わせて作成され、シェルを通じて実行されるスクリプトです。

## まとめ
シェル、コマンド、シェルスクリプトはそれぞれ独立した機能を持ちつつ、密接に連携しています。シェルはコマンドの実行環境を提供し、コマンドは個々の操作を実行する手段を提供します。シェルスクリプトはこれらのコマンドを組み合わせて複雑な操作を自動化し、効率的な作業を可能にします。この三つの要素の関係性を理解することで、コンピュータシステムの操作がよりスムーズになります。
開発規模とバグ数の話

# このページは何？
筆者の所属するPJで行っている「バグ分析」の取り組みから見えてきた
開発規模とバグ数に関する、興味深い傾向をお話するページです。


# 本題に入る前に
まず、所属するPJやQAチームはこんな感じです。
・スクラム（っぽい開発体制）を採用
・2週間で1スプリント
・各職掌の代表者でプランニングポーカーを行い、1ストーリーの大きさをストーリーptとして算出
・1スプリント内のストーリーptの合計を消化ptとして計測
・QAにて検出バグ数を計測

# いざ本題
半年ほど前、スプリント49終了後に検出バグ数を計測したところ、
普段よりかなり少ない数で着地していたことがわかりました。
QAチーム内でその理由について考察する中で、ほぼ同じ消化ptだった
過去スプリントと比較したところ、以下のようになっていました。

![31f24bd8-f5cc-42b2-af2b-5ae5e5ba53b0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984275/0f84d6c8-67d4-021a-43b0-02ec5b7d5a5b.png)


バグの少なかったスプリント49は実装ストーリー数が多く、最大ストーリーptが少ない。
つまり「小さいタスクを数多く消化していた」ことがわかりました。
逆に、バグが多かった49以外のスプリントは実装ストーリー数が少なく、最大ストーリーptが多い。つまり「1つのタスクが大きかった」とも言えます。

ここまでが約半年前の話です。

# あれから半年後...
上述の傾向を受けて、今はストーリーごとのバグ数を算出する仕組みを作り、
ストーリーptとバグ数の相関関係を掘り下げています。
ある程度データもたまってきたので、実際にその数字を分析してみました。


![2023-12-01_14h56_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984275/7686ff6d-9459-0c8c-3b31-12634e54dc37.png)



11pt以上、21pt以上のストーリーはサンプル数が少ないため、まだ振れ幅がありそうです。
しかしながら、10pt以下のストーリー全94件の平均バグ数が約1件と、
小さいストーリーほどバグが出づらい傾向にあることがわかり、
筆者のPJでは、10pt以下に抑えて開発するのがベストプラクティスの様です。
ただし、あくまでこれは「バグを出さないための」それであり
MVPやtestabilityを踏まえると、適切な粒度はまた変わってくるのかもしれません。
それはまた別の機会に考察してみたいと思います。


# まとめ
品質とは、ともすれば定性的になりがちですが、
体感していたものが定量化されることで、PJに提案する際の
エビデンスとして活用できるデータになったのではないかと思います。

バグの発生要因はストーリーptのみに限らないので、
規模を小さくすればバグが起きないとは一概には言い切れません。
ですが、このデータが1つの参考事例として様々なプロジェクトで活用いただければ幸いです。

～～～2024/01/19追記～～～～～
1/16のjasst nano #32にてLTをしました
https://speakerdeck.com/mixi_engineers/development-scale-and-number-of-bugs
robocopy活用の一例：更新のみコピー

## 本文

リリースパッケージを作成したら、新規ファイル追加する事が少ないが、既存ファイル更新は良くある場合、下記コマンドを利用すれば、便利になる。

```winbatch:RoboCopyサンプル
SET CP_SRC="C:\コピー元フォルダ"
SET CP_DST="C:\コピー先フォルダ"
robocopy %CP_SRC% %CP_DST% /MT:128 /E /XL /NP /LOG:D:\test.log
```

|オプション      |説明         |
|:--------------|:------------|
| ```/MT:128``` |スレッド128件|
| ```/E```      |サブフォルダ含む|
```/XL```       |コピー先ファイルファイルのみ更新|
```/NP /LOG```  |コンソールに出力しない、ログファイルに出力、効率になる|
エンジニア初心者におすすめしたいChrome拡張機能

:::note
社内のベテランエンジニアに「入れておくと便利なおすすめChrome拡張機能を教えてください！」と聞いて教えてもらった拡張機能をまとめてみました。
:::

# Web閲覧に関する拡張機能

## AutoPagerize

- Google検索等でページ送りが不要になる

https://chromewebstore.google.com/detail/autopagerize/igiofjhpmpihnifddepnpngfjhkfenbp?hl=ja

## FireShot

- 画面表示外の部分も含めたページ全体のスクショが撮りたいときに便利

https://chromewebstore.google.com/detail/ウェブページ全体をスクリーンショット-firesh/mcbpblocgmgfnpjjppndjkmgjaogfceg

## ゴシップサイトブロッカー

- 検索結果に表示したくないサイトを登録してブロックできる

https://chromewebstore.google.com/detail/ゴシップサイトブロッカー/mjojhcmecfehllhcjcbhkkpohadogplk?hl=ja

## Gmail Show Time

- Gmailのメール一覧で受信・送信時刻が表示されないのを解消するための拡張機能

https://chromewebstore.google.com/detail/gmail-show-time/jgjaapljoafhkohbnfigoekjgdfddnnn?hl=ja

# 技術情報を収集するための拡張機能

## daily.dev

- 自身が興味を持っている技術分野を登録することで、その分野にまつわる海外の記事を自動で収集してくれる

https://chromewebstore.google.com/detail/dailydev-the-homepage-dev/jlmpjdjjbgclbocgajdjefcidcncaied?pli=1

## Wappalyzer

- 閲覧しているサイトにどのような技術が用いられているかを特定し、まとめて表示する

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

# 生成AI系の拡張機能

## Sider

- ChatGPT・Claude・Bard等の生成AIをサイドバー形式で呼び出せる（無料登録の場合、1日に呼び出せる回数は30回まで）
- テキスト生成だけでなく、作曲や画像生成、PDFの読み込み等が手軽に実行可能

https://chromewebstore.google.com/detail/sider-chatgptサイドバー+視覚gpt/difoiogjjojoaoomphldepapgpbgkhkb?hl=ja

※Siderの公式サイト

https://sider.ai/ja/extensions/chatgpt-sidebar-for-chrome-edge-safari

## Perplexity

- 閲覧中のページの内容の要約がメインの機能
- 検索範囲をウェブ上、同一ドメイン上、閲覧中の記事のみの3種類に切り替えて質問が可能

https://chromewebstore.google.com/detail/perplexity-ai-companion/hlgbcneanomplepojfcnclggenpcoldo?hl=ja

※Perplexityのブラウザ版

https://www.perplexity.ai

# 英語・翻訳系の拡張機能

## Mouse Dictionary

- マウスカーソルをあてるだけで単語の意味が調べられる

https://chromewebstore.google.com/detail/mouse-dictionary/dnclbikcihnpjohihfcmmldgkjnebgnj?hl=ja

※製作者の方のQiitaの記事

https://qiita.com/wtetsu/items/c43232c6c44918e977c9

## DeepL翻訳

- 言わずと知れた高性能翻訳サービスのChrome拡張機能

https://chromewebstore.google.com/detail/deepl翻訳：読みながら、書きながら使える翻訳ツ/cofdbpoegempjloogbagkncekinflcnj?hl=ja

## Grammarly

- スペルミスや文法ミスを自動で指摘してくれる

https://chromewebstore.google.com/detail/grammarly-grammar-checker/kbfnbcaeplbcioakkpcpgfkobkghlhen

# Amazon上で利用できる拡張機能

## サクラチェッカー

- Amazonに出品されている商品の信用度をチェック

https://chromewebstore.google.com/detail/sakura-check-linker/dmelpckhjikcpmppkcnjmjmedhjpjmce?hl=ja

## Keepa

- Amazonに出品されている商品のこれまでの価格推移を確認できる
- セール商品の値段が、本当に通常時よりも安くなっているのかを確認するのに便利

https://chromewebstore.google.com/detail/keepa-amazon-price-tracke/neebplgakaahbhdphmkckjjcegoiijjo?hl=ja
Fruition を使って Notion を独自ドメインで公開する

# Notion をブログにしたいぞ

Notion 便利ですよね。Notion がいかに便利かという話は今更なのでしませんが、個人ブログも Notion で書きたいなと思うぐらい便利だな〜と感じまして、どうにかブログにできないものかと思い「Notion ブログ」で検索してみたらば、出てきました。

https://udaa.jp/posts/super-notion-blog/

**「この記事これで終わりじゃん」** と思われそうですがこれだけではありません。

# Superが高い（と筆者は思う）
Super というサービスを利用する手順が書かれているのですが、このサービスは月額利用料が12ドルかかります。趣味の個人ブログに年間144ドル（＋ドメイン費用）は払えません。ということで「Notion ブログ 無料」で検索したらば、出てきました。

https://qiita.com/kazukimuta/items/31f8da3381a587263903

**「この記事これで終わりじゃん」** と思われそうですがこれだけではありません。

# Cloudflare の設定箇所に変更がある

これは2021年5月の記事なので2023年12月現在とは食い違っている箇所がありまして、ちょっとハマりました。手順の中でAレコードの `1.1.1.1` を設定する箇所ですが、代わりに `192.0.2.0` をプロキシとして追加する必要があります。CloudFlare 側の仕様が変更されたようです。

https://community.cloudflare.com/t/edge-ip-restricted-error-1034/348084/17

# 作ったブログはここ
https://mizunokura.me/

# 注意点
Fruition では以下の点について我慢する必要があるので注意しましょう。
- X（旧：Twitter）の埋め込みが使えない
    - 正確には使えるのだが、使うとiPhone版Facebookアプリの内部ブラウザで開いた際にクラッシュしてしまう。詳細は[こちら](https://mizunokura.me/Fruition-Notion-Facebook-61212cf98c8d4a31ae7229dc91d125a6)。
- Google にインデックスされない
    - 詳細は追ってないが、Notion側の制約？不明。Super等では対応しているらしい（使ったことない）。
    - 検索流入を重視している人にとっては致命的かもね。
- メタデータが展開されないことがある。

おしまい
スクリプト言語とコンパイル型言語の違いとは？

スクリプト言語とコンパイル型言語の違いについて

プログラミング言語には、スクリプト言語とコンパイル型言語の2つの主要なタイプがあります。これらの言語は、コードの実行方法や実行効率などにおいて大きな違いがあります。

まず、スクリプト言語は、コードを実行する際にソースコードを解析し、その場で解釈して実行します。一方で、コンパイル型言語は、ソースコードを事前にコンパイルして実行ファイルを生成し、その実行ファイルを実行することでプログラムを実行します。

さて、具体的な例を見てみましょう。以下のようなCのコードがあったとします。

```C
int func() {
  return -1;
}

void main() {
  func();
}
```

このコードをアセンブリコードに逆アセンブルすると、以下のような結果が得られます。

```assembly
*** <_func>:
100003f90: 55                           push    rbp
100003f91: 48 89 e5                     mov     rbp, rsp
100003f94: b8 ff ff ff ff               mov     eax, ***
100003f99: 5d                           pop     rbp
100003f9a: c3                           ret
100003f9b: 0f 1f 44 00 00               nop     dword ptr [rax + rax]

*** <_main>:
***: 55                           push    rbp
100003fa1: 48 89 e5                     mov     rbp, rsp
100003fa4: e8 e7 ff ff ff               call    0x100003f90 <_func>
100003fa9: 5d                           pop     rbp
100003faa: c3                           ret
```

この逆アセンブル結果からわかるように、コンパイル型言語でビルドされたバイナリは、元の関数名ではなく、関数のアドレスが指定されています。つまり、コンパイル型言語ではシンボル情報が容易には見ることができません。

また、C++のクラスの場合は、VTableと呼ばれる仕組みを使用して、継承したクラスのメソッド呼び出しを実現しています。さらに、Glib（GTK+）などのライブラリでは、アドレスの算出に独自のキャストが行われるなど、複雑な処理が行われています。

最後に、一言。Objective-Cは言語設計が無理や無駄な部分があるため、黒歴史として忘れ去られるべきです。その代わりに、Swiftを使用しましょう。Swiftは、クラスや関数の動的な呼び出しをサポートするなど、より現代的な言語設計が特徴です。

以上、スクリプト言語とコンパイル型言語の違いについてご紹介しました。どちらの言語も適切に選択して使用することで、効率的なプログラミングが可能となります。詳細な理解を深めることで、より良いプログラムを開発できるでしょう。

参考リンク：
- [C言語とは？基本文法や使い方を解説](https://www.suzuki.co.jp/car/swift/)
CLIやターミナルやシェルの用語意味と繋がり

# CLIやターミナルやシェルの用語意味と繋がり

コンピューターとのインタラクションには、様々な方法があります。コンソール、コマンドラインインターフェース（CLI）、コマンドライン、ターミナル、シェルなどの用語がありますが、これらは似ているようで異なる概念を指しています。これらの違いを正確に理解することは、効果的なコンピュータ操作の基礎となります。

## コンソールとは
コンソールは、コンピューターの物理的な操作インターフェースを指し、初期のコンピューターでは、キーボードやモニターがコンソールの役割を果たしていました。現在では、コンソールはコンピューター本体やサーバーに直接接続された入出力デバイスのことを指します。

### コンソールの主な機能
- **物理的な操作**: コンピューターの直接的な操作を可能にする。
- **トラブルシューティング**: システム問題の解決に使用される。

## CLI（コマンドラインインターフェース）とは
CLIは、テキストベースのユーザーインターフェースで、ユーザーがコマンドを入力してコンピューターと対話する方法を提供します。CLIは、プログラムの起動、ファイル操作などを行うことができ、グラフィカルインターフェースに比べて軽量で高速な操作が可能です。

### CLIの特徴
- **コマンド入力**: ユーザーが直接コマンドを入力し、システムと対話する。
- **高度な操作**: 複雑で詳細な操作が可能。

## コマンドラインとは
コマンドラインは、CLI内でユーザーがコマンドを入力する具体的な場所(行)を指します。コマンドラインを通じて、ユーザーはコンピューターシステムに対して直接指示を出すことができます。

### コマンドラインの役割
- **コマンドの実行**: システムに対して特定のコマンドを実行する。
- **応答の表示**: コマンドの実行結果を表示する。

## ターミナルとは
ターミナルは、コンソールの機能をソフトウェア的に実現したもので、ターミナルエミュレータとも呼ばれます。コンピューターのシェルにアクセスし、コマンドを実行するためのCLIインターフェースを提供します。

### ターミナルの利用
- **リモートアクセス**: リモートシステムにアクセスするために使用される。
- **多機能性**: 複数のシェルやタブを開くことができる。

## シェルとは
シェルは、ユーザーからのコマンドを解釈し、コンピューターのOSに命令を伝えるプログラムです。Bash、Zsh、Fishなど、様々なシェルが存在します。

### シェルの重要性
- **コマンド解釈**: ユーザーのコマンドを解釈し、適切なアクションを実行

する。
- **スクリプト実行**: 自動化されたタスクを実行するためのスクリプトをサポートする。

## まとめ
これらの要素はそれぞれ独自の役割を持ち、ユーザーとコンピューターシステムとの対話を可能にしています。コンソールは物理的なインターフェース、CLIとコマンドラインはコマンド入力の手段、ターミナルはソフトウェア的なCLI操作環境、シェルはコマンド解釈と実行の役割を持っています。これらの違いを理解することで、ユーザーはより効率的にコンピューターシステムと対話することができます。
EC2でApache周りを触って勉強になった話

会社で使用していたEC2がamazon linux1で2023年12月31日でEOLを迎えるので、それの移行対応をしていました。
その際に、apache周りを初めて触ってかなり手こずりましたが色々勉強になったので備忘録として残します。

# Apacheの起動
まずEC2にssh接続します。
apacheを停止し、
```
$apachectl -k stop
```
もう一度apacheを起動
```
$apachectl -k graceful
```
```:実行結果
Job for httpd.service failed because the control process exited with error code.
See "systemctl status httpd.service" and "journalctl -xeu httpd.service" for details.
```
が出ました。警告通り `systemctl status httpd.service` をしても特にわからなかったので、
```
$apachectl configtest
```
```:実行結果
AH00526: Syntax error on line 18 of /etc/httpd/conf.d/ssl.conf:
Invalid command 'SSLPassPhraseDialog', perhaps misspelled or defined by a module not included in the server configuration
```
上記の結果になった。

調べたところ　mod_ssl.so　があるか確認する必要があったので下記を実行。
```
$find /etc/httpd/modules/ -name mod_ssl.so
```
結果的に見つからなかったので、mod_sslをインストール
```
$dnf -y install mod_ssl
```
もう一度 `$find /etc/httpd/modules/ -name mod_ssl.so` を実行すると、ちゃんとインストールされてました。

```
$apachectl configtest
``` 
```:実行結果
AH00526: Syntax error on line 422 of /etc/httpd/conf/httpd.conf:
Invalid command 'MinSpareServers', perhaps misspelled or defined by a module not included in the server configuration
```
調べてみると、MinSpareServers はServer MPMがpreforkで使われるよとのこと。
そこで、Server MPM を確認してみる。
```
$apachectl -V
```
```:実行結果
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
```
amazon linux2023ではServer MPMがeventになっていたので、httpd.confの中に以下のように修正。
```
# MinSpareServers ←コメントアウト
```
もう一度確認。
```
$apachectl configtest
``` 
```:実行結果
AH00511: WARNING: MaxRequestWorkers of 4 is less than ThreadsPerChild of 25, increasing to 25. MaxRequestWorkers must be at least as large as the number of threads in a single server.
Syntax OK
```
ThreadsPerChild、ServerLimit、MaxRequestWorkersをhttpd.confの中に設定する。
```
こちらを追加
↓
<IfModule mpm_event_module>
    ThreadsPerChild 25
    ServerLimit 20
    MaxRequestWorkers 500
</IfModule>
```
もう一度確認
```
$apachectl configtest
```
```:実行結果
Syntax OK
```
やっと終わったので、apacheを再起動
```
$apachectl -k graceful
```
起動成功！！！



参考
https://qiita.com/marumasa/items/de2cbde0215fe8d20022
https://qiita.com/____easy/items/362d7e2c970afa1eb2bc
https://qiita.com/esparrago_b/items/4f368599aba1a059dbd1
千両箱と木の葉

PDFファイルを直接ダウンロードする方法
（ダウンロードリンクだとPDFを開いてしまうため
```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PDF Download Example</title>
</head>
<body>

<button onclick="downloadPDF()">Download PDF</button>

<script>
function downloadPDF() {
    // 相対パスを使用してPDFファイルを指定
    var pdfPath = 'path/to/your/file.pdf';

    // ダウンロード用のリンクを生成
    var link = document.createElement('a');
    
    // 現在のスクリプトが配置されているディレクトリを基準にした相対パス
    var scriptPath = document.currentScript.src;
    var basePath = scriptPath.substring(0, scriptPath.lastIndexOf('/') + 1);

    link.href = basePath + pdfPath;
    link.download = 'example.pdf'; // ダウンロード時のファイル名

    // ダウンロードリンクをクリック（自動でダウンロードが開始される）
    link.click();
}
</script>

</body>
</html>
```

```
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PDF Download Example</title>
</head>
<body>

<button onclick="downloadPDF()">Download PDF</button>

<script>
function downloadPDF() {
    // ダウンロード用のデータを生成（ここでは空のPDFファイルを用意）
    var data = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, /* ... */]);
    var blob = new Blob([data], { type: 'application/pdf' });

    // ダウンロード用のリンクを生成
    var link = document.createElement('a');
    link.href = window.URL.createObjectURL(blob);
    link.download = 'example.pdf'; // ダウンロード時のファイル名

    // ダウンロードリンクをクリック（自動でダウンロードが開始される）
    link.click();
}
</script>

</body>
</html>
ArduinoでLEDの輝度をPWM制御する方法

# はじめに
この記事は「[Applibot Advent Calendar 2023](https://qiita.com/advent-calendar/2023/applibot)」の5日目の記事になります。

# 概要
<!-- 発端や概要を記載 -->
ArduinoでLEDの輝度をPWM制御する方法と，その動作原理を簡単に解説します．

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [動作環境](#Chapter1)
1. [輝度を調節するコード](#Chapter2)
1. [PWM制御とは](#Chapter3)
1. [ArduinoにおけるPWM制御とLEDの輝度調節](#Chapter4)
1. [まとめ](#Chapter6)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 動作環境
- ELEGOO UNO R3 (Arduino UNO R3互換)

<a id="#Chapter2"></a>
# 輝度を調節するコード
出力50%で9番ピンを光らせるコードです．
```dutyRatio```の値を0〜100の間で変化させることで，LEDの輝度を調節できます．
```c:pwm.ino
const int pinNum = 9;
const int analogWriteStep = 255;
int dutyRatio = 50; //duty比[%]

void setup() {
    pinMode( pinNum, OUTPUT );
}

void loop() {
    int ledBrightness = analogWriteStep * dutyRatio / 100.0f;
    analogWrite( pinNum, ledBrightness );
}
```

<a id="#Chapter3"></a>
# PWM制御とは
PWMは```Pulse Width Modulation```の略で，日本語ではパルス幅変調と言います．
その名の通り，パルスの幅を調節する制御方法です．

Arduinoに搭載されているような，ONとOFFでしか出力を制御できないデジタル出力ポートであっても，ON時間とOFF時間の幅を変更することによって制御対象の出力を滑らかに制御することができます．従って，LEDの輝度調節以外ではモーターの出力制御などに使われたりします．
↓イメージ
![qiita_PWM概念図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1762997/769ad413-ebfc-68d5-9922-8cfde99ecadb.png)
全体のうちON時間が占める割合をDuty比といいます．上記コードはこのDutyを指定できるように書いています．

<a id="#Chapter4"></a>
# ArduinoにおけるPWM制御とLEDの輝度調節
上記コードでLEDの輝度調節をした際，人間の目には一定の明るさに見えますが，実際にはLEDは点滅しています．9番ピンから出力される電圧はON→OFF→ON...と高速で切り替わっていて，ArduinoではデフォルトでONとONの間が1ms(周波数が1kHz)に決められています．人間の目では1kHzの点滅を知覚することができないため一定の明るさで点灯しているように見えます．


<a id="#Chapter6"></a>
# まとめ
PWM制御を使うことで，ONとOFFのデジタル出力だけで任意の出力を得られる理由と，Arduinoでのプログラムの解説をしました．Duty比を自由に変更して，滑らかにLEDの明るさを変更できます．


「以上、[Applibot Advent Calendar 2023](https://qiita.com/advent-calendar/2023/applibot) 5日目の記事でした。」
Viteの最小限設定

## vite.config.tsを作成する
ルートディレクトリに作成する
```vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  ...
)}
```

## Sassを使用する

```sh
$ npm i --save-dev sass
```

## ベンダープレフィックスを使用する
```sh
$ npm i -D postcss autoprefixer
```
ルートディレクトリにpostcss.config.jsを作成して、以下を記述
```postcss.config.js
module.exports = {
  plugins: {
    autoprefixer: { grid: "autoplace" },
  },
}
```
## 画像を圧縮する
ビルド時に画像を適切なサイズに自動的に圧縮する。

```sh
$ npm i -D vite-plugin-imagemin
```
vite.config.tsに追記

```vite.config.ts
import viteImagemin from "vite-plugin-imagemin"

export default defineConfig({
  ...
   plugins: [
    vue(),
    viteImagemin({
      gifsicle: {
        optimizationLevel: 7,
        interlaced: false,
      },
      optipng: {
        optimizationLevel: 7,
      },
      mozjpeg: {
        quality: 80,
      },
      pngquant: {
        quality: [0.8, 0.9],
        speed: 4,
      },
      svgo: {
        plugins: [
          {
            name: 'removeViewBox',
          },
          {
            name: 'removeEmptyAttrs',
            active: false,
          },
        ],
      },
    }),
  ]
)}
```
optimizationLevelやqualityなどのプロパティの値を変更することで、圧縮率を設定できる。

## ソースマップを有効にする
```vite.config.ts
export default defineConfig({
  ...
  css : {
    devSourcemap: true
  }
)}
```

## サブディレクトリにビルドする場合
```vite.config.ts
import { defineConfig } from 'vite'

export default defineConfig({
  ...
  base: './'
)}

// もしくは、明示的にも指定可能
export default defineConfig({
  ...
  // /aboutにデプロイする場合
  base: '/about',
})
```
***

小さい規模のプロジェクトであれば、上記の設定だけで十分対応できる。
CentOS7.9 で h2o をソースビルドする

CentOS に h2o をインストールしよう。そういうとき、定石では `vi /etc/yum.repos.d/bintray-tatsushid-h2o-rpm.repo` するところだけど、執筆時点（2022年3月現在）ではこの手は使えない。リポジトリに指定する bintray が昨年5月の時点でサービス終了してしまっているのだ。

色々と検索してみたものの代替手段が見つからなかった。そこで、備忘録ついでに記事として残しておく。

# 環境

- OS：CentOS7.9（AWS EC2 AMI:ami-0ddea5e0f69c193a4）
- h2o：v2.2.6

必要なツールをインストールする。bison と ruby は mruby を使用する場合に必要。

```bash
sudo yum install wget gcc gcc-c++ bison ruby
```

# 手順
ソースコードの入手

```bash
cd /usr/local/src
sudo wget https://github.com/h2o/h2o/archive/refs/tags/v2.2.6.tar.gz
sudo tar -zxvf ./v2.2.6.tar.gz
cd ./h2o-2.2.6
```

以下を CMakeLists.txt の最下行に追記する。そうしなければ cmake 時に gnu99 を指定しなさいというエラーが返る。

```bash
sudo vi CMakeLists.txt
```

```bash
SET(CMAKE_C_FLAGS “-std=gnu99 -O2 -g ${CC_WARNING_FLAGS} ${CMAKE_C_FLAGS} -DH2O_ROOT=\“${CMAKE_INSTALL_PREFIX}\” -DH2O_CONFIG_PATH=\“${CMAKE_INSTALL_SYSCONFDIR}/h2o.conf\“”)
```

ビルド

```bash
sudo mkdir -p build
cd ./build
sudo cmake ..
sudo make
sudo make install
```

confを用意

```bash
sudo mkdir -p /etc/h2o/
sudo vi /etc/h2o/h2o.conf
```

service に追加（任意）

```bash
sudo vi /usr/lib/systemd/system/h2o.service
```

```bash
[Unit]
Description=H2O - the optimized HTTP/1, HTTP/2 server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=simple
ExecStart=/usr/local/bin/h2o -m master -c /etc/h2o/h2o.conf
ExecReload=/bin/kill -HUP ${MAINPID}
ExecStop=/bin/kill -TERM ${MAINPID}
PrivateTmp=true
LimitNOFILE=infinity

[Install]
WantedBy=multi-user.target
```

```bash
sudo systemctl start h2o
```

途中、cmake の段階で libvu のバージョンが古すぎたり、libwslay が見つからないというエラーが出るが、そのまま問題なく make; make install できた。もしかしたら何か起きるかもしれない。

ソースビルドなんていつぶりだろう。たまにやると、パッケージマネージャー（yum。8以降や streamでは dnf）様様だということがよくわかる。


# おわりに
「今更h2o？」「今更CentoOS7？」という感じもあるが、久々に Amazon Linux 2023 で環境構築しようとしたところ、h2o のインストールでこけてしまい、結局 nginx に置き換えたあと、むかし自前のブログに書いたこの記事を思い出したので移植しました。誰かの役に立てば嬉しいな。

おしまい
[AWS認定試験]Site to Site VPN 

## Site to Site VPN とは

AWS認定試験対策としては、構成図くらいが頭に入っていれば問題なさそう。

## 構成図
- 仮想プライベートゲートウェイ(Virtual Private Gateway)との接続
![スクリーンショット 2023-12-05 9.25.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/f5481ae3-3ea7-7f08-ab6a-40616522f2de.png)

- トランジットゲートウェイへの接続
AWS側の接続先をトランジットゲートウェイにすれば複数のVPCとの接続が可能
![スクリーンショット 2023-12-05 9.30.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/424f8643-9f7e-1b1a-6865-68ad6bac990a.png)

## 設定内容
VPCの機能として存在。
![スクリーンショット 2023-12-05 9.35.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/3148e0b0-5d94-da80-666b-d25597d61618.png)

### カスタマーゲートウェイ
![スクリーンショット 2023-12-05 9.38.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/178b64d5-d0b3-b85e-1898-318927dd04f3.png)

ユーザ側のカスタマーゲートウェイデバイスの情報を設定

### 仮想プライベートゲートウェイ
![スクリーンショット 2023-12-05 9.39.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/61f192c6-a991-cf76-90b6-dd6ad58b92d3.png)

### VPN接続
![スクリーンショット 2023-12-05 9.51.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/ee822485-5b50-583a-b95c-2ea73f03b2b6.png)

## VPNクラウドハブ
![スクリーンショット 2023-12-05 9.55.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586577/c4c0c2d4-c2c7-5678-f547-504032b39aee.png)

ユーザサイト側が複数あり相互に通信したいというユースケースでVPNクラウドハブが利用可能。



## 参照リンク
https://docs.aws.amazon.com/ja_jp/vpn/latest/s2svpn/VPC_VPN.html

https://docs.aws.amazon.com/ja_jp/vpn/latest/s2svpn/how_it_works.html

https://docs.aws.amazon.com/ja_jp/vpn/latest/s2svpn/site-site-architechtures.html
Databricks REST APIによるユーザーとグループの作成

DatabricksではREST APIで色々操作できます。ここでは、ユーザーとグループを作成してみます。

# ユーザーの作成

:::note info
**プレビュー**
本機能は[パブリックプレビュー](https://docs.databricks.com/release-notes/release-types.html)です。
:::

https://docs.databricks.com/api/workspace/users/create

なお、マニュアルに記載があるように、ワークスペースに追加されたユーザーはアカウントユーザーとしても追加されます。

> Creates a new user in the Databricks workspace. This new user will also be added to the Databricks account.

ワークスペース管理者のパーソナルアクセストークンを取得しておきます。

ターミナルで以下を実行します。

```sh
curl -v -X POST  "https://tydatabricks-tydb-test-environment.cloud.databricks.com/api/2.0/preview/scim/v2/Users" \
--header 'Authorization: Bearer [パーソナルアクセストークン]' \
--header 'Content-Type: application/json' \
--data-raw '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "takaaki.yayoi+test4@databricks.com",
    "name": {
        "familyName": "Yayoi",
        "givenName": "Takaaki"
    },
    "emails": [
        {
            "value": "takaaki.yayoi+test4@databricks.com",
            "type": "work"
        }
    ]
}' | jq
```

ワークスペースの管理画面でユーザーを確認できます。って、管理画面のレイアウトが変わってる…。
![Screenshot 2023-12-05 at 9.22.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/6b91b3f6-a3d9-9778-ab7c-a58798857096.png)

アカウントユーザーになっているのでアカウントコンソールでも確認できます。
![Screenshot 2023-12-05 at 9.23.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cdaae3ef-70ea-86c0-7593-cb216e1f9d7f.png)

また、招待メールが当該アドレスに送信されます。
![Screenshot 2023-12-05 at 9.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/be9512f7-d828-2cf2-3f51-cd6c5cc92aa7.png)

# グループの作成

こちらのAPIになります。

https://docs.databricks.com/api/workspace/groups/create

:::note info
**プレビュー**
本機能は[パブリックプレビュー](https://docs.databricks.com/release-notes/release-types.html)です。
:::

なお、ここで作成されるグループはワークスペース固有の[ワークスペースローカルグループ](https://docs.databricks.com/ja/administration-guide/users-groups/groups.html#difference-between-account-groups-and-workspace-local-groups)なので、アカウントコンソールには反映されません。

以下のコマンドを実行します。

```sh
curl -v -X POST  "https://tydatabricks-tydb-test-environment.cloud.databricks.com/api/2.0/preview/scim/v2/Groups" \
--header 'Authorization: Bearer [パーソナルアクセストークン]' \
--header 'Content-Type: application/json' \
--data-raw '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
    "displayName": "workspace_group"}' | jq
```

ワークスペースの管理画面でユーザーを確認できます。
![Screenshot 2023-12-05 at 9.27.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/c62f1512-ead8-0dc0-f1ef-0d79fba61d61.png)

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
useEffect useLayoutEffect useInsertionEffect３つのEffectの挙動を見る

## はじめに
Reactで開発を行うにあたって外部システムとの同期をエフェクトを通じて行います。
エフェクトの利用は`useEffect`が使われることが多く、次点で`useLayoutEffect`が使われると考えています。そして、CSS in JSのライブラリ開発などでは`useInsertionEffect`が利用されます。

この記事ではそれらのエフェクトを利用する3つのhooksについて見ていきます。

## useEffect
`useEffect`は以下のような型を持ちます。
```ts
declare const UNDEFINED_VOID_ONLY: unique symbol;
type Destructor = () => void | { [UNDEFINED_VOID_ONLY]: never };
type EffectCallback = () => void | Destructor;
type DependencyList = readonly unknown[];

function useEffect(effect: EffectCallback, deps?: DependencyList): void;
```
第1引数はエフェクトの内容を記述する関数です。この関数はコンポーネントがブラウザに初めて描画された後に実行されます。
第2引数はエフェクトの実行タイミングを管理する引数です。第2引数に値を渡さなかった場合はコンポーネントがブラウザに描画されるたびに再実行されます。第2引数に配列を渡した場合は各レンダリング時にその値が変化するたびにブラウザに描画された後に実行されます。空の配列を渡した場合は初回のブラウザへの描画後のみ実行されます。

第1引数の関数の返り値は型の上ではvoidを返すようになっていますが、クリーアップ関数と呼ばれる関数を返すようにも記述できます。この関数は新たなエフェクトが実行される直前に実行されます。実行されるのは新しいエフェクトの内容ではなく、実行されたエフェクトで記述された関数が実行されます(ローカル変数などは実行された時のものをそのまま使います)。

### 例
ブラウザへの描画が完了されるたびに実行される
```ts
useEffect(() => {
  console.log(1);
});
```

ブラウザへの初回描画が完了されるときに実行される
```ts
useEffect(() => {
  console.log(1);
}, []);
```

`count`の更新後にブラウザへの描画された後に実行される
```ts
useEffect(() => {
  console.log(1);
}, [count]);
```

クリーンアップ関数の順番
```tsx
const Sample = () => {
  console.log('レンダリング時に実行される関数');
  useEffect(() => {
    console.log('ブラウザの描画後に実行される関数');
    () => {
      console.log('次のエフェクト実行時に実行される関数');
    };
  });
  return <></>;
};
```

## useLayoutEffect
関数の形は`useEffect`と同じですが、`useLayoutEffect`はエフェクト関数が描画される前に実行されます。

## useInsertionEffect
`useInsertionEffect`は`useLayoutEffect`よりも早いタイミングでエフェクトを発火させます。早いタイミングでエフェクトが発火されるので、DOM情報を`ref`経由で取得しようとしても、初回の実行では取得できていません。
そして、このhooksのエフェクト関数では状態の更新を行えないです。

## 比較
基本的には`useEffect`を利用することが推奨されているという前提であることに留意してください。
実行における順番は以下のようになっています。
![スクリーンショット 2023-12-04 22.46.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591069/081d876e-40a9-a947-0f5c-f19667625fa8.png)
`useInsertionEffect`は基本的にCSS in JSからの動的スタイル注入されるために存在します。`useInsertionEffect`という`useLayoutEffect`よりも早く実行されるhooksがあることでランタイム時の注入が間違ったタイミングで行われることよる遅延を防ぐことができます。間違ったタイミングとは他の`useLayoutEffect`の処理と注入のタイミングが同じになることです。

そして、`useEffect`と`useLayoutEffect`は実行のタイミングが画面への描画前後という違いを活かして活用されます。基本的には`useEffect`を利用します。実行されるエフェクトが描画に関わるものであった場合に`useEffect`を使うと画面に描画を行った後にエフェクトを実行して再度描画し直すような動きになるので、画面がチラつくことがあります。そのような場合は`useLayoutEffect`を用いてチラつきを抑制します。
【TailwindCSS初心者がハマる】TailwindCSSは動的にクラス名を生成できないよ

TailwindCSSを業務で書くようになって3ヶ月が経ちました。
TailwindCSSの私が「なんでだ？」となったポイントを1つ紹介します。

## TailwindCSSは動的にクラス名を生成できない

私のようなど素人がJavaScript的な感覚で書いてしまったダメな例です。

```javascript:ダメな例
const paragraph = ({ spacing }) => {
  return <p className={`ml-${spacing} mr-${spacing}`}></p>
}
```

公式サイトの「Dynamic values」という項目に書かれていますが、TailwindCSSが正しく検知されるためには、クラスは完全な文字列でなければならないとあります。

https://v2.tailwindcss.com/docs/just-in-time-mode#arbitrary-value-support

:::note warn
認識されないclass名はTailwindCSSの仕組みによってビルド時にパージされてしまいます。
するとStorybookにスタイルが反映されない事象が発生することになります…
:::

動的にclassを付与する方法は色々ありますが、プラグインなどを利用しない場合は以下のように書き換えることが可能かと思います。

```diff_javascript:修正版
const paragraph = ({ spacing }) => {
+  let spacingClass;
+  switch(spacing) {
+    case 'small':
+      spacingClass = 'ml-2 mr-2';
+      break;
+    case 'medium':
+      spacingClass = 'ml-4 mr-4';
+      break;
+    case 'large':
+     spacingClass = 'ml-8 mr-8';
+      break;
+    default:
+      spacingClass = '';
+  }
  return <p className={`ml-${spacing} mr-${spacing}`}></p>
}
```

修正前だと数字をpropsで受け渡す仕様でしたが、sizeをpropsで受け渡して`if`や`switch`を使って定義した変数に文字列としてclass名を代入します。

## 【TailwindCSSは動的にクラス名を生成できないよ】まとめ
TailwindCSSで動的にクラスを生成できないと言いましたが実はJITモードを利用することで実現することは可能です。

ただ、まだ安定していないためプライベートやデモで利用するのには問題ないと考えています。

:::note warn
ただ、プロジェクトで利用するのは気が引ける状態なので**現時点ではあえてできない**と表現しました。
:::

修正版だとコードが冗長的かつ読み辛く感じる方もいると思います。
そもそも動的にclassを利用する場合はCSS-in-JSを利用するかTailwindCSSの場合には`tailwind-variants`などのプラグインを利用することをオススメします。

`tailwind-variants`について紹介している記事もあるのでよろしければご一読ください！

https://qiita.com/tanimoto-hikari/items/3b2ccc23afd7ab9cd264

https://qiita.com/tanimoto-hikari/private/016f31b14b6eb2d4d943
VSCodeにGithub Copilotを入れたのにMarkdownファイルだけでCopilotが使えなかった時の解決方法

最近、CopilotのExtensionをVSCodeに追加して開発をするようになりました。通常のプログラムだけではなくjsonファイルのようなものでもCopilotはsuggestionが出てきて何かと便利に使えています。しかし、対応しているはずなのにMarkdownファイルではsuggestionが出てこなかったので、その解決方法を記載しました。

# 問題: MarkdownファイルでCopilotが有効化されない

タイトルの通り、VSCodeにGithub Copilotを入れ使い始めたところ、.pyや.tsx, .json等のファイルではCopilotが使えるのに、.mdファイルではCopilotがdisabledになって、VSCの右下にあるCopilotのアイコンがグレーになっていました。当然この状態ではMarkdownファイルに入力を始めてもsuggestionが出てきません。


![copilot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/05003fb8-251f-eaaf-01e3-00e68cd89665.png)


# 解決方法: CopilotのSettingsでMarkdownも有効化する

`[command] + ,` で設定画面を開き、検索窓に「`Copilot: Enable`」を入力すると、Copilotの設定が出てくるので、そこで`markdown`を`true`に設定するとMarkdownファイルでもCopilotが使えるようになります。

![copilot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86684/c654bf85-35ac-96c4-44c9-6b02d7aa7167.png)
【Ruby】pメソッドとputsメソッドの違い

# 【Ruby】pメソッドとputsメソッドの違い

Rubyにおける`p`メソッドと`puts`メソッドは、どちらも出力を行うメソッドですが、その振る舞いには重要な違いがあります。この記事では、これらのメソッドの特徴と違いを初心者にも分かりやすく解説します。

## pメソッドの特徴

`p`メソッドは、オブジェクトのデバッグ出力に適しています。具体的には以下の特徴があります。

### データ型を明示

`p`メソッドは、オブジェクトの型や内容を明示的に出力します。これにより、データの構造や型を正確に理解することができます。

### `inspect`メソッドの結果を出力

`p`メソッドは、内部的にオブジェクトの`inspect`メソッドを呼び出し、その結果を出力します。これにより、オブジェクトの内部表現を詳細に確認できます。

### 例

```ruby
p "hello"  # 出力："hello"
p 123      # 出力：123
p [1, 2, 3]  # 出力：[1, 2, 3]
```

## putsメソッドの特徴

`puts`メソッドは、より一般的な出力用途に使用されます。以下の特徴があります。

### 人間が読みやすい形式で出力

`puts`メソッドは、オブジェクトを人間が読みやすい形式で出力します。複雑なデータ構造を持つオブジェクトでも、簡潔に表示されます。

### 改行を自動で追加

`puts`メソッドは、出力の末尾に自動的に改行を追加します。これにより、複数の出力が行われる場合でも読みやすくなります。

### 例

```ruby
puts "hello"  # 出力：hello
puts 123      # 出力：123
puts [1, 2, 3]  # 出力：1 2 3 (各要素が改行で区切られる)
```

## pメソッドとputsメソッドの使い分け

- **デバッグ用途**: `p`メソッドは、オブジェクトの詳細な情報が必要なデバッグの際に適しています。データの型や構造を把握したい場合に使います。
- **一般的な出力**: `puts`メソッドは、ユーザーに情報を伝える一般的な出力に適しています。読みやすさを重視したい場合に使います。

## まとめ

Rubyの`p`メソッドと`puts`メソッドは、出力する内容や形式が異なります。`p`メソッドはオブジェクトの型や内容を詳細に表示し、デバッグに適しています。一方で`puts`メソッドは、人間が読みやすい形式で出力し、一般的な情報表示に向いています。プログラムの目的や必要に応じて、これらのメソッドを適切に選んで使い分けることが重要です。デバッグ時には`p`を活用してオブジェクトの詳細を確認し、ユーザー向けの出力や簡単な表示には`puts`を用いると良いでしょう。このように使い分けることで、Rubyプログラミングの効率と理解が深まります。
ふんわりCSS設計でダークモード対応に備える

ご存知でしょうか。
何を隠そうオレたちの[Qiitaではダークモードが使えます](https://blog.qiita.com/release-theme/)。

正直私はあまり関与していないのですが、長きに渡って運営されてきたサービスに[後付けでダークモード対応は間違いなくえぐいほど大変](https://qiita.com/xrxoxcxox/items/9fac826a2e1c8526aa50)です。

以下では、これから設計をはじめるケースで備えられるアレコレをメモしておきます。

# カラーパレットの設定

これからCSSの設計をはじめるなら**カラーパレットの設定はもはや必須**です。

さらにいえば以下のような[Material Design風の思想](https://m2.material.io/design/color/the-color-system.html#color-theme-creation)でやってしまうのがもっとも柔軟性というか、拡張性が高くなりそうな気がしています。

```scss
:root {
  // まず網羅的に色があって、
  --color-red-50: #ff0000;
  // ...
  // ...

  // 機能ごとに再代入されるやつ
  --color-text-error: var(--color-red-50);
  // ...
  // ...
}
```

なお、`--color-red-50`の部分が（多分）まさにMaterial Design的なんですが、今をときめく[Tailwindでもよく似たカラーパレットが採用されている](https://tailwindcss.com/docs/customizing-colors)そうです。

全然追えていないのでそのうちちゃんとみたい。

# ダークモード対応

カラーパレットができたらお馴染み`prefers-color-scheme: dark`でポチポチダークモードに対応していきます。

```scss
:root {
  --color-text-error: var(--color-red-50);
}

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;
    --color-text-error: var(--color-red-80);
  }
}
```

`color-scheme: dark;`はそのバリエーションがダークモードであることを明示できるプロパティで、指定することで**ブラウザごとのデフォルトのStyleをデフォルトのダークモードカラーに変更**してくれます（フォーム周りとかスクロールバーとか）。

# ダークモードの拡張

上記でシステムの設定に合わせた形でのダークモードが実現しました。
が、当然ゆくゆくはシステム設定に依存しない形での実装が望まれ、さらには「ライトモード」「ダークモード」「システム設定準拠」に発展すること請け合いです（iOSのそれ）。

下記では`<body data-theme="dark">`みたいになる感じで想定しています。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ZEwmgxO" data-user="moro" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/moro/pen/ZEwmgxO">
  CSS Design for Darkmode</a> by moro (<a href="https://codepen.io/moro">@moro</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


本当はスイッチ部分のJSとかも書きたい気持ちがありましたが、[諸事情](https://x.com/moro_is/status/1728219934558482526)によりすこぶる余裕がありません。ご容赦ください。

# さいごに

結論としては「**カラーパレットさえいい感じに作っておけばだいたい大丈夫！**」ではないかなと思います（勘）。
そのうち実際に実装することがあったら追記します……！

良いお年を！
codecamp第3章‐7　課題(中級)

## 変数$valueに代入されている値を「切り捨て」「切り上げ」「四捨五入」「小数点以下第三位四捨五入」した値を計算し表示するよう、以下のプログラムへ追記してください。

```php:
<?php
// $valueの値を定義
$value = 55.5555;

// 小数切り捨て値の処理を記述
$floor = floor($value);

// 小数切り上げの処理を記述
$ceil = ceil($value);

// 小数四捨五入の処理を記述
$round = round($value);

// 小数点以下第三位四捨五入の処理を記述
$round2 = round($value, 2);

?>

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>課題</title>
</head>

<body>
    <p>元の値:<?php print $value; ?> </p>
    <p>小数切り捨て:<?php print $floor; ?></p>
    <p>小数切り上げ:<?php print $ceil; ?> </p>
    <p>小数四捨五入:<?php print $round; ?> </p>
    <p>小数点第三位で四捨五入:<?php print $round2; ?> </p>
</body>

</html>
```

## 結果
元の値:55.5555

小数切り捨て:55

小数切り上げ:56

小数四捨五入:56

小数点第三位で四捨五入:55.56
codecamp第3章‐6　課題(初級)

## 「printf」という関数を使い、変数$intの値を5桁の数値として表示するよう、以下のプログラムへ追記してください。


```php:
<?php
 
// 表示する数字
$int = 315;
 
// 5桁の数字(00315)として表示
print sprintf('%05d', $int);
?>
```
Expert Onlineを活用した勉強会開催 & JAWS-UG金沢 2023ふりかえり

# JAWS-UG 金沢　2023 ふりかえり

今年は感染症騒動も落ち着いて、オフライン実施が復活でき、懇親会も復活し、オンラインで増えた仲間と実際に会うことができる！というとてもいい年になりました。

そして、今週末は [JAWS-UG金沢 x AWS Startup Community プレゼンツ『北陸でStartupをはじめよう・みつけよう』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/159890) の開催です。

# 実施

今年は12回開催しました！加藤個人としては #89 のLT大会がとても印象的です。なぜかというと、地元の大規模オンプレを抱える会社さんと、AWSから大村さんや営業の方もいらっしゃって盛り上がりました。

もうちょっと オンプレ + AWS についてガチでやっていこうかなあ。

[JAWS-UG金沢 #85 AWS Expert Online 『運用を効率化するためのAWS Systems Manager Automationの紹介』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/149754)

[JAWS-UG金沢 #86 meetup! & 2023年度企画会議 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/151757)

[JAWS-UG金沢 #87 AWS Expert Online 『大阪リージョン使えばいーじょん！、あたりまえーじょん！』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/152365)

[JAWS-UG金沢 #88 AWS Expert Online 『Amazon Connectで実現！いつでも繋がるコンタクトセンターのススメ』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/155824)

[JAWS-UG金沢 #89 LT大会 ここであえてオンプレについて - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/155825)

[JAWS-UG金沢 #90 AWS Expert Online 『AWS re:Inforce振り返り』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/159092)

[JAWS-UG金沢 #91 meetup! & 2023年度後半企画会議 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/160770)

[JAWS-UG金沢 #92 AWS Expert Online 『Amazon CloudWatch でできる n 個のこと』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/162655)

[JAWS-UG金沢 #93 Cloudformationハンズオン - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/160718)

[JAWS-UG金沢 #94 & Kanazawa.rb 『Ruby on Rails on App Runner ハンズオン』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/163630)

[JAWS-UG金沢 #95 AWS Expert Online 『「ちょっと待って！そのユースケース、サーバーレスで良くないですか？」』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/165316)

[JAWS-UG金沢 x AWS Startup Community プレゼンツ『北陸でStartupをはじめよう・みつけよう』 - JAWS-UG 金沢 | Doorkeeper](https://jawsug-kanazawa.doorkeeper.jp/events/159890)

# Expert Onlineを活用した勉強会開催のススメ

昔々、「地方は初心者向け、やってみた、ハンズオンは人気あるんですけど、深く使い込んでる人はいないんですよねー。そして専門支部と違ってきてりとの領域も違って、濃い話がなかなかできない」とAWS沼口さんに相談したところ、「じゃあオンラインでそういうのをやってみよう！」ということでExpert Onlineを手配していだきました。

「Expert Online」という名前からすると「ああ、感染症騒動もあったから、オンライン開催に移行した勉強会なのかな」という印象がありますが、実は違うのです！もう金沢支部では2019-01-30(もう4年も前！）から毎回受講＆受講後にzoomにて参加者オンラインミーティングをしています。

このオンラインミーティングは参加できる場所を制限していないため、金沢の勉強会に九州の方だって参加できます！実際、参加いただいていて、この感染症騒動があけて実際にJAWS-UGの全国規模イベントやAWS Summitなどでリアルミーティングもできました。

Expert OnlineはJAWS-UGのコアメンバー向けに開催情報は展開されています。

特に「うちの地元の支部、いわゆる休眠状態にあるんだけど一回やってみたいな」「ネタがないんだよな」って支部にはちょーオススメです。会議室とモバイルパソコンと回線があれば、みんなで受講するという勉強会を開催できます！ぜひ一度ご検討ください。
AI-102試験対策のまとめ「Smart Labelerによる迅速なタグ付け」

## はじめに
Azure AI Engineer Associate(AI-102)取得に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AI-102取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください
※勉強しながら投稿しているため、追加で学んだことがあれば随時投稿内容を更新します。

## 試験対策のまとめ
### Smart Labelerによる迅速なタグ付け
* Smart Labeler機能を使用することで、画像に対する推奨タグを生成可能  
⇒Custom Visionモデルのトレーニング時に、多数の画像に素早くタグ付けできる

#### **SmartLabeler使用の制限事項**
* トレーニングを始めたばかりの新しいタグについての提案は得られない  
⇒一度対象のタグを使ってトレーニングされている必要がある

#### **Smart Labeler使用手順**
1. すべてのトレーニング画像をCustom Visionプロジェクトにアップロード
1. データセットの一部にラベルを付け、タグごとに同じ数の画像を選択  
※後で提案を必要とするタグをすべて使用すること
1. トレーニングプロセスを開始
1. トレーニング完了後、「Untagged」ビューに移動
1. 左側ウィンドウの「Get suggested tags(推奨タグを取得)」を選択
1. 表示されるポップアップウィンドウで、候補として表示する画像の数を設定
1. 推奨タグを確認し、正しくないものは修正
1. トレーニングプロセスを再開
1. 提案の品質に満足するまで、前の手順を繰り返す

<br>

* 参考
    - https://learn.microsoft.com/ja-jp/azure/ai-services/custom-vision-service/suggested-tags


## 次の試験対策のまとめ
* **AI-102試験対策のまとめ「LUISにおけるエンティティの種類」**

https://qiita.com/fsd-jume/items/47ff61cfea9f07d3f5f4

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/65aba5d5514e023fd66d
IBM i アーキテクチャー：データベースファイルのストレージ書き出しタイミング（ページ・アウト、スワップ・アウト制御）

## IBM i (Db2 for i)のデータベースファイルをストレージに書き出すタイミング

データベースファイルのデータはシステムのRAS（Reliability, Availability, Serviceability)の要件を満たすために適切な時点でディスクに書き出す必要があります。
IBM i (Db2 for i）の場合、以下のタイミングでデータベーステーブル（PF）のストレージ装置への書き出しが発生します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/02db19ab-49f5-ce94-a518-198639187906.png)

1.データベースファイルをFULL CLOSEした時点（データベースファイルをSHAREしていない場合のCLOSE）
    ※参考にデータベースファイルをSHAREしている場合は以下のように全てのジョブで使用が終了した時点となります。
    
    ```
    　OPENDBF  FILE(XXX) OPNID(*FILE) TYPE(*PERM)
               :
            複数JOBでODB SHARE中
               :
      CLOF  OPENID(XXX)    <==ここで FULL CLOSE
    ```
  
 -----
2.データベーステーブルのFRCRATIOパラメーターに指定されたレコード数を更新・追加・削除した時点
　　　※OVRDBFコマンドで一時的にFRCRATIOパラメーターを変更した場合も含む
     ※FRCRATIO(*NONE)の場合はシステムがストレージへの書き出しタイミングを決定
     
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/7c2b022c-8272-73ff-34ec-708b9b556f08.png)
　　　※FRCRATIOパラメーターを小さくするとストレージへの物理I/Oが頻繁に発生することになり、アームビジー率を上昇させる＝I/Oパフォーマンスを劣化させる懸念があるので注意が必要です。
   
-----

3.＊CLSクラスでPRRGE(*YES)を指定しているジョブにおいて、ロングウェイトが発生した場合
　　　※これは個々のジョブのPAGに対する指定となります
     ※基本的には対話型ジョブで発生

-----

妥当な範囲のページングはシステムにとって必要なものであり、効率上の問題とはなりません。もちろんページングを実行中にも他のジョブは実行できます。

データベーステーブルは通常、その全レコードをメインメモリ上に置くことはできないので、データベースのデータへの参照はページングを引き起こします。
※例外としてはデータベーステーブル全てを展開可能なメインメモリの空きがあったときにSETOBJACCコマンドを実行すればテーブル全体をメインメモリ上に展開できます。

参考：オブジェクト・アクセスの設定（SETOBJACC）https://www.ibm.com/docs/ja/i/7.4?topic=ssw_ibm_i_74/cl/setobjacc.html
プロダクト開発における「学習のためのアウトプット」と「収益のためのアウトプット」

この記事は[MOSH Advent Calendar 2023](https://adventar.org/calendars/9548)の5日目の記事です。

プロダクティビティーチームの[@soartec-lab](https://github.com/soartec-lab)です。

アドベントカレンダー3週目です。

[前回の記事](https://qiita.com/SoarTec-lab/items/bbcfc4a5f02e01c248fe)では、リリースステージによる段階的なリリースにより、高速にプロダクト開発のフィードバックサイクルを回す考えについて書いてみました。

この記事ではリリースステージ毎に「今のアウトプットが何のためのアウトプットなのか」という目的を認識する事で適切なアウトプットを選択するヒントになる考えを紹介します。

## 学習のための開発と収益のための開発

書籍[プロダクトマネジメント](https://www.oreilly.co.jp//books/9784873119250/)内では

- 学習のためのアウトプット
- 収益のためのアウトプット

を分けて考えることが説明されています。

そこで、[プロダクト開発におけるフィードバックサイクルを加速させる為のリリースステージという考え方について](https://qiita.com/drafts/bbcfc4a5f02e01c248fe)で整理したリリースステージ毎にそれぞれ開発の目的を考えてみます。

| ステージ | ゴール | 実験の対象 | 方法 | プロダクトの提供 | プロダクト利用の制約 |
| --- | --- | --- | --- | --- | --- |
| 実験 | 問題を理解し解決する価値があるかどうかを判断する | 問題の調査とソリューションの探索 | プロダクションコードは書かない、オズの魔法使いやコンシェルジュなどの方法 | - | - |
| アルファ | ソリューションが顧客にとって望ましいかどうかを判断する | 最小限の機能または、適切なソリューションの実験 | プロダクションコードのリリース | 少数のユーザー | ユーザーの課題を解決できなかった場合は機能が変更されたり削除される可能性がある |
| ベータ | 技術的な観点からソリューションがスケーラブルであるか判断する | プロダクション運用が可能か技術的な検証 | プロダクションコードのリリース | アルファよりも多いが一部のユーザー。 | 技術的に不安定な場合に機能が変更されたり削除される可能性がある |
| GA | 一般公開 | - | プロダクトの一般公開 | すべてのユーザー | なし |

### 実験

実験は提供する価値の**学習のためのアウトプット**になります。
例えば、以下の様な方法を用いてプロダクションコードを書く前にユーザにとって解決する必要がある課題なのか見極めます。

- コンシェルジュ
- オズの魔法使い
- プロトタイピング
- コンセプトテスト
- ランディングページ

### アルファ

アルファでは実験によって得た課題をプロダクトで解決できるのかを検証する**学習のためのアウトプット**になります。

この段階ではまだ**収益のためのアウトプット**ではなく優先するのは学習なので、できる早く出来る限り早く検証を進めたいので、既存のプロダクトに影響を与えなければ短期的なスピードを優先させて品質を犠牲にすることも受け入れて良いと考えています。

うまくいかなかったものは破棄する前提で、**収益を生むためのアウトプットでは無い**ため、プロダクトとして価値が届けられることを確認してから持続的でスケール可能なやり方に変換すれば良いと考えています。

まさに技術的負債ではあるので、返済の計画を持った上で負債を借り入れ、プロダクトのステージが前に進んだら返却を行う技術面でのマネジメントが必要になります。

### ベータ

ベータ以降は、**収益のためのアウトプット**に目的が代わります。持続的でスケール可能なプロダクトにするための技術的な検証を含めた開発になります。
そのため、エンドユーザーが増えた場合のスケーラビリティーや、継続的な機能改善の為の内部品質が求められます。

### GA

GAでは新しい開発はありません。全てのユーザに向けて機能がリリースされている状況なので運用を通して適切にプロダクト価値が届けられているか、言い換えると、収益のためのアウトプットが目的通り収益を生んでいるかを確認します。

# まとめ

リリースステージ毎に「今のアウトプットが何のためのアウトプットなのか」という目的を認識する事で適切なアウトプットを選択するヒントになる考えを紹介しました。
今のステージがどこなのか、それにより適切なアウトプットは何なのかを認識することでプロダクトのアウトカムを最大化させる手助けなれば幸いです。

明日は、[まっすーさん](https://note.com/massyuu/)です！よろしくお願いします〜！
Excelよ。カンマで分割したいんじゃない、分割文字をカンマにしたいんだ。

## 言いたいこと
Excelで区切り文字をタブからカンマに変えたいとき、なぜ「実際の文字列をカンマで分割する」という操作をしなければいけないのか。分割文字をカンマに設定したいだけなのに。
逆に「文字列をカンマで分割した」場合、なぜ設定がカンマ区切りになってしまうのか。指定したセルをカンマで区切るという、今回限りの作業なのに。

## 背景
社内SEをやっているのですが、特定の機能でExcelダウンロードが重すぎるという問題に直面しました。オーナー部署しか使わない機能なのでCSVでの提供でもいいと思ったのですが、「前ゼロが消えてしまうからやめて」と言われました。対応案を考えたところ割とダサい対応案しか思い浮かばない。・・・誰かすてきな解決方法を知っている人いたらコメントください。

## 対応案
1\.「そんなん自分で何とかしろ」と突き返す
まあ無理。垂直タブとか入ってくるとITリテラシー高い人でもミスることありますし。

2\.Excelの機能でCSVを読み込み
毎回各列に対して書式設定するのは面倒。

3\.書式設定したテンプレートを用意しておいてそこにCSVを張り付けてもらう
区切り文字をカンマにする必要がある　**※この記事の本題**

## 本題
つまり区切り文字をカンマにする手順をオーナー部署に連携すればOK・・・・。と思いました。オモイマシタ。omoimasita。
#### 普段自分がやってた区切り文字の変更手順
1\.適当なセルに適当な文字列を入力する
2\.「データ」タブの「区切り位置」から区切り文字をカンマにする
3\.CSVをエディタで開く
4\.Excelに貼り付け
5\.適当なセルに適当な文字列を入力する
6\.「データ」タブの「区切り位置」から区切り文字をタブにする
7\.1,5で入力した値を消す

#### 圧倒的に手順の1,5,7が意味わからん！！！！！
普段から意味わからんと思ってたが、さすがに人にこれでやってくださいと伝えるのは辛い。納得感のない手順だとその手順覚えられないんですよね。あと、納得感のない手順を押し付けると「意味わからんけどやればいいんでしょ」となって、オーナー自身の「ITリテラシーを向上させてたい！」という意欲をそぐ気がする。

#### 対応案
案1\.CSVをエディタで開いた時にカンマをタブに変換する
・・・うん。ダブルクオテーション内のカンマも変換されちゃう。

案2\.CSV読み込みマクロを用意する
・・・え？今後CSV増えるたびに用意するの？

案3\.区切り位置を変えるタブ⇔カンマで切り替えるマクロを用意する
・・・え？え～と1～2と5～7をマクロにするからまずは適当なセルを見つけて適当な文字を入力しなきゃ。あっ、でもそこにオーナーが値入れてたら消えちゃうから作業用のシートを1つ作って適当に入力してから文字列を分割してシート削除して・・・。

## 結果
今回は案1で対応しようと思います。オーナーしか使わないので、カンマがタブに変換されるのは許容できるはず。（ダブルクオテーション区切りの中なので想定外にセルが分かれることはない。）

## 総論
「区切り文字をタブに設定、カンマに設定はショートカットキーでいっぱつ」にしてほしい！
けど無理だろうからうちで使っている基盤がTSVに対応してほしい。
paiza.ioでelixir その262

# 概要
paiza.ioでelixirやってみた。
streamでzundokoやってみた。

# 参考にしたページ

https://qiita.com/piacerex/items/4670f59d9f6d601fe2a8

# サンプルコード

```
defmodule Zundoko do
    def auto() do
        Stream.repeatedly(fn -> 
            ["ズン", "ドコ"] 
            |> Enum.random 
        end) 
        |> run
    end
    def run(input) do
        match = ["ズン", "ズン", "ズン", "ズン", "ドコ"]
        eol = "キ・ヨ・シ！"
        input
        |> Stream.transform([], fn x, acc -> 
            if List.last(acc) == eol do
                {:halt, nil}
            else
                if Enum.count(acc) < Enum.count(match) do
                    {[x], acc ++ [x]}
                else
                    if acc == match do
                        {[eol], acc ++ [eol]}
                    else
                        {[x], [x]}
                    end
                end
            end
        end)
        |> Enum.to_list
        |> IO.inspect
    end
end


Zundoko.auto()


```

# 実行結果

```
["ドコ", "ドコ", "ドコ", "ドコ", "ズン", "ドコ", "ドコ", "ズン",
 "ドコ", "ズン", "ドコ", "ズン", "ドコ", "ドコ", "ズン", "ズン",
 "ズン", "ズン", "ズン", "ドコ", "キ・ヨ・シ！"]
```

# 成果物

https://paiza.io/projects/Ov1-YY6u1swlq3zIygPneA?language=elixir


以上。
【SQL・DB設計】忘れそうなポイント

`Happiness Chain Advent Calendar 2023` 5日目の記事です。

https://adventar.org/calendars/9414/

『スッキリわかるSQL入門』『達人に学ぶDB設計 徹底指南書』やYouTubeでSQL・データベース設計ついて学習したので、内容をまとめてみました。基本的なことは本や動画を見たらわかるため、本記事では個人的に重要と感じあとから見返したいときに本や動画のどこに書いてあったか忘れてしまったときのためにまとめます。

# 『スッキリわかるSQL入門』
# 5章 式と関数
## 5.1 式と演算子 p147
- DBMSは1行ずつ処理をしている
    - 1回の処理でDBMSがすべての行を見ているわけではない
## 5.3 様々な関数 p154
- 関数の呼び出しも1行ずつ行っている

# 第6章 集計とグループ化
## 6.2 集計関数の使い方 p181
- COUNT(*)はNULLの行も含めてカウント
- COUNT(列)はNULLの行を含めずにカウント

## 6.3 集計に関する4つの注意点 p185
- 結果表はn行m列の形にならないとだめ
    - 凸凹な結果表はNG、きれいな四角形じゃないとダメ


## 6.5 集計テーブルの活用
- 大量のデータを扱う場合に使う
- 集計処理を行い結果を集計テーブルに格納する
- 集計結果が必要な場合は既に格納されているデータを利用する

### メリット
- 大量のデータから集計結果を取得する場合長い時間がかかるが、集計テーブルに事前に登録しているとすぐに取り出せる

### デメリット
- 格納されているデータは集計時のものであり時間経過に伴い古くなるので、定期的に集計処理を再実行する必要がある

# 『達人に学ぶDB設計 徹底指南書』
## 第３章 論理設計と正規化 〜なぜテーブルは分割する必要があるのか
### 3-2 テーブルの構成要素
- 縦方向が列(カラム)
    - Columnと書いたときに`C`の右に縦棒を１本足すと穴ができるので縦
- 横方向が行(レコード）
    - Recordと書いたときに`R`の下に横棒を１本足すと穴ができるので横

:::note info
参考
[ひと目でわかる行列（Row ・ Column）の方向の覚え方 - Λlisue's blog](https://lambdalisue.hatenablog.com/entry/2013/07/18/134507)
記事では行をRowと呼んでいますが、『達人に学ぶDB設計 徹底指南書』ではレコードと読んでいますのでこちらに合わせました。
:::

- 可能な限りデータはNULLにしない
    - いろんな問題を引き起こす可能性があるため
- CHECK制約はいくつでも使用できるが、複数列にまたがった使用はできない
    - `A列 > B列`など

### 3-4 第1正規形
- (主)キーがNULLを含むのはNG
    - 主キー列にはDBMS側でNOT NULL制約が付加される
    - NULLになりそうな場合はテーブルをわけるなどして対処する

## 第5章 論理設計とパフォーマンス 〜正規化の欠点と非正規化
### 5-1 正規化の功罪
- 結合はコストの高い操作
    - 結合するテーブル数やそのレコード数が多いほど処理時間がかかる
- 著者個人の立場としては「**非正規化は許さない**」
    - 非正規化は他の手段を使ってもパフォーマンス向上が見込めない場合の最後の手段
    - 正規化すればするほど望ましい
    - ハードウェアの高性能化やマテリアライズド・ビューといったDBMSの機能により、非正規化を行わないでいいケースも増えている(『スッキリわかるSQL入門』p415)

## 第6章 データベースとパフォーマンス
### 6-2 インデックス設計
- ソートはかなりコストが高い処理
    - ソート時はDBMS内部の専用メモリに一時的にデータを保持するため


## 第7章 論理設計のバッドノウハウ
### 7-2 ❎非スカラ値
- データは意味を崩さない範囲でなるべく分割して保存するべき
    - 分割したものを結合するのは簡単だが逆は難しいから
        - `山田太郎`なら`山田`と`太郎`
        - `hoge@test.com`なら`hoge`と`test.com`

### 7-3 ❎ダブルミーニング
- テーブルや列や意味は**変数ではない**ので変更不可
    - 今まで体重を格納していた列に「やっぱり年齢を入れよう」というのはNG
    - 列を追加するなどして対処する


# 小学生でもわかるデータベース設計入門。実際に設計しながら基礎を学ぼう - YouTube[^1]
### ER図 1:02:42
- 1対多のときの1の方は、横棒1個でも2個でもいい


[^1]: https://youtu.be/Yg546Zua39A
VSCodeでSalesforceのSOQLをいい感じに作成・実行確認する


## 前書き

仕事で、TeamSpiritのAPIでデータを取得して社内で持っているデータと突き合わせ、
なんやかんやする機会がありました。

その時、初めてSalesforceのAPIを使用しようとして、なかなか手こずったので
同じような人の参考になればと思います。

Salesforceから提供されているデータの具体的な内容を[Salesforce Object Query Language (SOQL)](https://developer.salesforce.com/docs/atlas.ja-jp.soql_sosl.meta/soql_sosl/sforce_api_calls_soql.htm)で確認する手段として[Workbench](https://workbench.developerforce.com/)がありますが、
そのWorkbenchで「VS CodeにSOQL Builderがあるから試して！」的なことが書いてあったので、
そちらを試すことにしました。

## 試した環境

- Windows 10 Pro

## 準備（前提）

- VSCodeはインストール済
- TeamSpiritのSandboxが使えるようになっている

## VSCodeの拡張機能をインストール

- Salesforce CLI Integration
- Salesforce Extension Pack
- SOQL

## SQOL用のプロジェクトを作る

Ctrl + Shift + Pでコマンドパレットを表示。

1. 「SFDX: マニフェストファイルを使用してプロジェクトを作成」を実行。
![SFDXコマンド_プロジェクト生成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622772/10bda60c-63f3-466f-bd7f-4725506305de.png)
2. 「標準 標準のプロジェクトテンプレート」を実行。
3. プロジェクト名を入力して、「参加」を選択。

## 認証

1. 「SFDX: 組織を認証」を実行。
![SFDXコマンド_組織を認証.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622772/e65f474a-ec84-073c-10f4-8c9e2cc15d94.png)
2. `Sandbox`を選択。
3. 組織のエイリアスを入力。（エイリアスはSandboxにログインすると確認できます）
4. ブラウザが起動しアカウント認証画面が表示されるので、ユーザー名とパスワードを入力してSandboxにログイン。
5. 成功したらブラウザを閉じる。
6. VSCodeに成功メッセージが表示されていることを確認する。
![SOQL組織認証成功.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622772/738dc038-c071-de03-235d-4ee4312f6c52.png)


## SOQLファイルを作る

scripts > soql に適当な名前のsoqlファイルを作る
![SOQLプロジェクト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622772/4694e7f3-a373-8e65-5d39-db4b3080edbc.png)

## ビルダーを起動

エディタ右上のアイコンからビルダーを起動します。
![SOQL実行コード_ビルダー起動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622772/714d961d-43b5-a223-8d45-c64f6c8fb421.png)

テーブルやカラムを選択して、`Run Query`ボタンでSOQLを実行し、実行結果を表で確認することができます。
![SOQL実行画面_モザイク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622772/ad7be3f8-2b47-a781-7aac-2507315145de.png)

カラム定義は、Sandboxの`設定`→`オブジェクトマネージャー`から確認することができます。
プルリクエストのレビューでコンフリクトした時の対処法

## 対処法
※すでにコンフリクトを起こしている状態でも下記のコマンドでコンフリクトごと巻き戻ります。

:::note warn
レビューしていたブランチのローカルでの差分（（HEAD、インデックス、作業ディレクトリ）は消えるので一応注意！
:::

```
$ git fetch origin レビューしていたブランチ名
$ git reset --hard origin/レビューしていたブランチ名

```

## 上記を使う時の状況...
・一度PR（プルリクエスト）をレビューし、修正依頼を出していること
・実装担当者が修正差分をforce pushしていること
・↑に気づかず修正が完了したと思い、最新のリモートリモートブランチからpullしてくると、コンフリクトを起こしていること
・実装者とレビュワー以外に影響が出る人がいないこと（※レビューしていたブランチを使っているのが実装者のみであれば問題無し）
・レビューにのみ必要なブランチなのでレビューしていたブランチでのローカルの差分が巻き戻っても問題無いこと

## 私自身が使った時の経緯
正しく「上記を使う時の状況...」の時でした笑
前の開発ではあまりforce pushを使う人がいなかったので、エンジニアとしてちょっと慣れてきた時に最近遭遇したため、初見は腰抜かすほど焦りました...笑（実装者に迷惑をかけていないかとヒヤヒヤでした）
ただ、Gitって知れば知るほど便利ですよね〜！

以上。
皆様も良いエンジニアライフを！！