OmniAICreator/Qiita-1.07M huggingface dataset:
CodeでないほうのVisualStudioで、WSLを使ってC++のLinuxアプリを作る

まずはVisualStudio 2022をインストールします。

``` shell
winget install --id Microsoft.VisualStudio.2022.Community --force --override "--add Microsoft.VisualStudio.Workload.NativeCrossPlat --includeRecommended"
```

これはCommunity版の場合です。Professional版やEnterprise版を使いたい人は、適当に修正してください。

![2023-09-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/71e1cddd-c02b-4429-78c4-3fe0a0e54829.png)

なお「C++を使用したLinux及び埋め込み開発」のワークロードが必要になります。最初のコマンドラインに含まれています。上のVisualStudio Installerのイメージは、GUIから手動で設定したい人のための参考です。

次にWSLを設定します。

``` shell
wsl --install
wsl
```

``` shell
sudo apt update
sudo apt install g++ gdb make ninja-build rsync zip
```

![2023-09-25 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/cc3ea393-084b-f963-345d-6cc17ea83017.png)

新しいプロジェクトを作成します。ターゲットをLinuxにして、コンソールアプリケーションを作成してください。

![2023-09-25 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/46f32621-6843-d241-0715-a946c71ead78.png)

プロジェクトができました。しかしこれは、まだWSLでは動きません。

![スクリーンショット 2023-09-25 203059.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/4b858176-3635-2be8-0f21-b14b2662d118.png)

プロジェクトのプロパティから、プラットフォームツールセットをWSL2 GCC Toolsetにします。

.vcxprojファイルを直接編集して、プラットフォームツールセットをWSL2 GCC Toolsetにすることもできます。

``` xml
  <PropertyGroup>
    <PlatformToolset>WSL2_1_0</PlatformToolset>
  </PropertyGroup>
```

![2023-09-25 (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/0c3fbf83-e7dc-2edd-761e-9804af92b7c9.png)

これで、Windowsアプリと同じようにデバッグできるようになりました。プログラムは実行時にWSL環境へデプロイされますので、実行前にコピーする手間はかかりません。

---

流行りのVisualStudio Codeではなく、VisualStudio 20xxで開発したいという人の多くは、ターゲット環境がウェブやメインフレームではなくて、組み込みLinuxである人が多いのではないかと思われます。

WSLでビルドしたバイナリを実機に持っていくと、以下のようなエラーが出て実行できないことがあります。

``` shell
./application: /lib64/libc.so.6: version `GLIBC_2.34' not found (required by ./application)
```

ターゲットマシンでビルドするか、ターゲットマシンのlibをアップグレードするのが、これの一般的な解決策になります。

しかしながら組み込み機器の開発においては、ターゲットマシン上でビルドしたりapt upgradeしたりすることが困難な場合があります。

そこでターゲットマシンのOSに合わせてWSLにインストールするディストリビューションをダウングレードします。具体的には、`wsl --install -d Ubuntu-20.04` のようにして、ディストリビューションとバージョンを明示的に指定してインストールします。

![スクリーンショット 2023-09-25 203200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568364/f9dc2aec-2d49-95ab-8d47-18f182a3f780.png)

デフォルトのディストリビューション以外のWSLでデバッグするには、プロジェクトのプロパティから「WSLのディストリビューション名」を明示的に指定します。
話題のChatGPTを使って、業務タスクを管理するWebアプリを作成

# ChatGPTに色々聞いて作ってみよう！！
こんにちは。Qiita記事4回目を書いています、IT初心者のkaneです。
これまで色々な初めてを経験し、プログラミングができない超初心者でも様々なプロトタイプが作成できるんだということがわかりました。

今回は、ChatGPTに色々聞いてみながら何かを作ってみようと思います。
これまで噂には聞いたことはあったのですが、使ってみたことはなかったので使ってみようと思います。

# 使用ツール
 - ChatGPT　https://chat.openai.com/
 - codepen　https://codepen.io
 
 # タスク管理を容易にできるツールを作成！
今回は、チームメンバーだけでなく仕事をする人であれば欠かすことのできない「タスク管理」を円滑にできるWebアプリを作成したいと思います。
これを作成したいと思った背景と実現したいことを下記に記載します。
 1. 現在はチームミーティング時に、各々エクセルで日別に管理表を作成し、Teamsで画面共有して、メンバー間で情報交換をしています。これを一つのフォーマットに統一しt、見やすさや管理のしやすさにつながるのではないかと考えたことが背景にあります。
 1. ペーパーレスの観点からTeamsで画面共有をするようになったので、Excelである必要もないため、必要な情報だけササっと入力したらある程度体裁を整えてくれるようにしてほしい
 1. 但し、まれに紙で印刷することもあるので、Web画面上で作成したものをExcelにエクスポートできる機能が欲しい 


上記をChatGPTを頼りに実装していきます！
私にはHTMLやJavaScriptの知識は皆無なので、自力でやろうとするとできてもWeb上でテキストボックス追加して、何か入力できるようにしてくらいの程度かと・・・


 # ChatGPTを使って、実装開始
 ### 今回実装したこと
CodePenで以下の動画で映し出しているところまでは実装できました。

 - PC画面上での動作
![Lesson4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491090/fb0241ef-1dd8-1d88-9a7e-212320e8ce7a.gif)

 -作成した画面の全体像
![2023-09-26 10.30のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491090/658ea871-4880-41fe-ce40-731e25d82ac6.jpeg)

:::note info
実装できたこと
1. タスクを入力するテキストボックス、カレンダーボックス、時計ボックスの配置
1. 入力したタスク情報を日別に一覧表示
1. 登録したタスクの削除機能
1. 登録したタスクの横にチェックボックスを配置し、進捗管理
:::
:::note alert
できなかったこと
1. Excelへのエクスポート。ChatGPTにも無理だよと言われました・・・
1. Excelが無理であれば、せめてCSVで出力できればと思いましたが、ボタン押下しても何も動作しない。。ただの何もしないボタンになってしまいました。
:::

 ### ChatGPTに聞いてみた

- ChatGPTへ依頼！そもそもどうやって依頼？？
今回、ソースを書くにあたって文法とかそういったものが全くわからないので、ChatGPTに何もかも頼りきりでした。
ChatGPTを活用するにあたってなるべく詳細にやりたいことを端折らずに書くことが大事であると、終盤になってやっと気づきました。

:::note warn
注意
詳細まで「仕様」を整理してからプロンプト（指示文書）を書いてあげましょう！
でないと、私のように何回もプロンプト書いて、戻ってきてを繰り返す無限ループに陥ります。
:::


- 超抽象的なプロンプトからスタート
うまくいかないことや私の伝え方が下手すぎるのもあり、冒頭のシンプルなツールを作るのに結構なやり取りを繰り広げました。
ちなみに一番最初に書いたプロンプトは、これだけ。
 ![2023-09-26 12.11のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491090/980d2ebc-91d1-d3fb-604e-cef7be8d7d5e.jpeg)

それでも最低限の機能を有した業務タスクアプリを作ってくれました。
この時点のツールを残しておけば良かったのですが、保存しておらず。。。

- 実際のChatGPTとのやり取りはこちらです。 
結構な量のやり取りなので、相当スクロールしないといけないのですが、根気強く会話しました。
なかなか時間短縮になった実感はあまりないのですが、自力で一からやっていたら、ただタスクを列挙するだけのWebアプリで挫折していたと思いますが、全くソースコードを書けない私でもここまで実装はできました。

https://chat.openai.com/share/6d34b4a6-f0a2-4204-8583-04e65da23930

# 使ってみての感想
実際に使ってみて、率直な感想で言うと、
「今のままでは実用性はまだないかな」と言うのが感想です。
やはり、Excelに落とせるようにしたいと言うのが前提で、それが実現できていないためです。
また、「保存」機能もないと使うのは厳しいなと言う感じがしました。
CodePen以外を使っての実現も検討が必要かと考えました。
近いうちにリベンジしたいと思います。

# 振り返り
ChatGPTを使って短時間で画期的なツールを作るつもりでしたが、冒頭のものを作るのでも結構時間を使ってしまいました。
但し、抽象的な指示でもある程度のものを作ってくれることはわかったので、事前に設計書のようなものを作れば、より高度のものが作れるということがわかりました。
今回は、行き当たりばったりで作成したので、かかった時間の割に精度の高いものが作れなかったので、事前に仕様をまとめるところから始めてみようと思います！
terraform -target=module.xxx コマンドで一部のモジュールだけ実行する

# tfファイルの例

```tf
module "s3_log" {
  source = "modules/s3"
}
```

この例であれば `s3_log` をコマンドで指定すれば良い

# コマンド例

```
terraform apply -target=module.s3_log
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
WordPressを"サーバーレス"PaaSで5分でAzureで立ち上げる

WordPress on App ServiceなるAzureで見慣れない機能が追加されていたのを発見。

![Wordpress onApp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/9f9c8a86-5b52-fea1-479b-abcfe9e2d1dd.png)

1年前よりAzureでWordPressをサーバーレスで立ち上げられるようになっていたようだが気づかずつい最近からFreeプランという検証用プランでWordPressを気軽に作成、検証が容易になったとのことなので作成してみた。Freeとか無料と書かれているプランがあるが制限がありそうなのでどこまで無料なのかは最新の情報を調べたほうがよさそうだ。すでにAzureを課金で利用中の場合、自動で作成されるAzure Database for MySQL B1msについては課金対象と書かれているしAzureから外に行くデータ転送量はかかるはずので注意が必要だ。

https://techcommunity.microsoft.com/t5/apps-on-azure-blog/announcing-public-preview-of-free-hosting-plan-for-wordpress-on/ba-p/3918254

![cloudwordpress7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/9d5707ff-8226-076e-dffa-e5ba0263c3a6.png)

![cloudwordpress1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/58b7d54a-9ffc-7f72-dde4-6f0a32677dfe.png)

![cloudwordpress2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/7860d8a9-6e2a-22a4-7a9a-821c7195f86d.png)

WordPress用のログインID、パスワードは作成時に指定するが、MySQLのデータベースログインID、パスワードは自動生成された。変えたい場合は自動作成後に個別に設定変更することになる。

作成が完了すると以下のような画面になる。App Service(出入口), MySQLとApp Service Plan(裏で動いている共有Linuxサーバー情報)が表示されるが事実上サーバーレス状態で裏で連携が取れているのでほとんど意識することはないだろう。

![cloudwordpress3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/b8f1b43c-764d-f94e-c48a-4f60c4a79def.png)

App Serviceで表示されているURLを開くとサンプルページが表示され、/wp-admin で管理者画面に入れる。

![cloudwordpress5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/f11dec68-ac7a-0370-ab28-96afe742a215.png)

![samplepage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/189fbad0-9f0f-5129-b38d-f1e6a794f2e6.png)

![cloudwordpress6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/17cd5e9a-4d34-7ee9-2eef-ced59c5edc94.png)

Azure利用者にとってはWordPress環境構築がずいぶんと楽になっている。

本番で運用する場合は相応の有償プランへ変更、
ゾーン冗長性の設定（Freeプランでは作成時に無効になっている）、
CDNやSSL証明書作成（AzureのCDN場合、カスタムドメインのSSL証明書が無料で作成できる方法もある）、ドメインDNS Aレコード宛先変更など追加作業が必要となるであろう。
Apple Silicon (M1, M2) Mac で x86 の Podman 環境を作成する


M1 Mac で 普通にPodmanをインストールしてイメージをPullしようとすると、「お使いのアーキテクチャでビルドされたイメージは存在しないよ。」というエラーメッセージが出てきて詰んでしまう。

```
$ podman image pull ibmcom/db2

...

no image found in manifest list for architecture arm64
```

## 準備

- `homebrew` で `podman`をインストール
    ```sh
    # brew install podman
    ```

## x86 の Podman 環境を作成

1. [Fedora CoreOS | The Fedora Project](https://fedoraproject.org/en/coreos/download/?tab=metal_virtualized&stream=stable&arch=x86_64#baremetal) の中のQEMU qcow2.xz をダウンロードする。 
    ![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/4f0355c7-c9a7-bf88-64b8-42221b889e3f.png)

2. (どこでもいいが) `~/images`フォルダに配置する。
    ![b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/0413b71b-b9b6-7ff9-e734-d1f2b44afd9e.png)

3. Podmanの machine として登録し、`intel`という名前をつける。
    ```sh
    # podman machine init --image-path ~/images/fedora-coreos-38.20230902.3.0-qemu.x86_64.qcow2.xz intel
    ```

4. 設定を編集
    
    ```sh
    # cd ~/.config/containers/podman/machine/qemu
    # cp intel.json{,.bk}
    # vi intel.json
    ```

    `aarch64`を`x86_64`に変更し、以下のキーワードを削除


    ```
    "-machine", "q35,accel=hvf:tcg",
    "-cpu", "host",
    "-accel", "hvf",
    "-accel", "tcg",
    "-drive", "file=/Users/{UserName}/.local/share/containers/podman/machine/qemu/intel_ovmf_vars.fd,if=pflash,format=raw"
    ```
    
    ![c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/7de585fd-4862-969c-cf66-7c9342e8bc1e.png)

5. デフォルトのマシンを切り替える。
    
    ```sh
    podman system connection default intel
    
    # 戻すときは
    podman system connection default podman-machine-default
    ```

6. マシンをスタート
    
    ```sh
    podman machine start intel
    ```

これで、x86 に切り替わったため、x86 でビルドされたイメージがpullされ、利用することができるようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75935/4604a717-8c9f-3e76-75eb-3db5ab22e5b2.png)

## 参考

-  [Running x86_64-based containers on Mac computers with an Apple silicon (M1) processor - IBM Developer](https://developer.ibm.com/tutorials/running-x86-64-containers-mac-silicon-m1/) 
-  [Running Problematic x86_64 Containers, such as MQ, using Podman on ARM (M1) Macs](https://community.ibm.com/community/user/integration/blogs/piers-walter/2022/07/28/running-x86-64-containers-such-as-mq-on-podman-on)
TypeScript + React にゼロからJest + React Testing Libraryを追加する

## 背景

React ComponentをPrivate Packageとして公開するにあたり、CRAやNextjsフレームワークを使用しなかったので、ゼロからテストを構築する必要がありました。


## Install

```bash
# 必要なパッケージは以下です。
npm i -D jest @types/jest jest-environment-js-dom @testing-library/react @testing-library/user-event @testing-library/jest-dom ts-jest 
```

それぞれ以下の役割があります。
*さえあれば、エラーが発生せずに`npm run test`が動作します。その他は実際のテストでほぼ確実に使用するであろう拡張ライブラリです。

- jest*
    テストフレームワーク。テスト実行、Coverage出力、Mockなど、テストに必要な基本かつ重要な処理をおこなってくれるコア部分です。

- @types/jest*
    TypeScriptでテストを記載します(xxx.test.ts or tsx)。Jestのみでは、TypeScriptファイルがJestが提供する変数名を認識してくれないので、追加します。

- jest-environment-js-dom*
    React Testing Libraryでは、Reactを通して最終的に表示されるUIを描画してくれます。その際に、Browser環境を模したものが必要となるため、追加します。
    
- @testing-library/react*
    Reactで描画するUIを表示してくれます。useEffectやuseStateなどで非同期的に変化するUIを的確に捉えるための`waitFor`などの超便利メソッドも用意されています。

- @testing-library/user-event
    イベント発火を行うライブラリです。

- @testing-library/jest-dom
    便利な拡張アサーションを提供してくれます。

- ts-jest*
    Jestがテスト実行する際に、TypeScript文法を理解する必要があります。このライブラリを用いることで、`ts`、`tsx`ファイルがcommonjs形式にトランスパイルされます。


## 設定

- jest.config.js

    テスト環境やトランスパイル設定を組み込みます。

```js:jest.config.js

/** @type {import('jest').Config} */
module.exports = {
  preset: 'ts-jest', // te-jestパッケージ
  testEnvironment: 'jsdom', // jest-environment-js-domパッケージ
  setupFilesAfterEnv: ['<rootDir>/src/tests/setup-jest.ts'] // setup-jest.tsファイルの位置
};

```

- setup-jest.ts
  `jest.config.js`で読み込むように設定したファイルです。これは、`@testing-library/jest-dom`を全テストで使用するために使用します。

```ts:setup-jest.ts
import '@testing-library/jest-dom';
```

## 補足

  - 絶対パスでImportしたい場合

```js:jest.config.js
  // ↑↑省略↑↑
  moduleDirectories: ['node_modules', __dirname],
```

- `{export { default as v1 } from './v1.js'`でエラーが発生した場合
    
    Jestと`uuid`で互換性エラーが発生しているので、以下のように解決できます。

    [詳細を知りたい方はこちら](https://github.com/uuidjs/uuid/issues/451)

```js:jest.config.js
  // ↑↑省略↑↑
moduleNameMapper: {
    uuid: require.resolve('uuid')
},
```
raspberry pi4にインストールするソフト

家にいるときWindowsマシンを他人が使うってことになったとき、タブレットが不調中なのでraspberry pi4 (RPi4)使うことにしたいです。なにをインストールしたらいいのか？記録してみました。アーキテクチャが`Arm64`なので、インストールに場合によっては苦労しそうです。

1. pandoc
1. ghostscript
1. gawk (おそらくterminalにpreinstalled)
1. marp-cli
1. muttmua
1. todo.txt-cli
1. gnuplot
1. julialang
1. git
1. inkscape
1. NN-SVG
1. mermaid.js

## 少しだけ環境構築進んだ

環境構築が進んだのでここに書かせていただきます。

### muttmua

7番目のmuttmuaのインストールができました。installationは簡単でapt-getつかえます

```
sudo apt-get install -y mutt
```


userディレクトリに、`.muttrc`, `.mutt_certificates`をおきます。

そのあと、`.mutt`というディレクトリつくります。その中に`aliases`というファイルをおきます。これは、メールアドレスリストです。

### docker

`docker`インストールについて、むずかしくないが、その後プルできるイメージが少ない印象。CPU=ARM64なのがネック？

### todo txt-cli

別のブログで記載しました。

## 文書執筆系

`pandoc`は、`Haskell`なので、`Arm64`の`GHC`がうまく入れればよさそう。これに関するのは、[ここ](https://qiita.com/mod_poppo/items/084455236e61e583176a)。

### pandoc

これについて、`wget`でインストールしました。うまくいきました。

`markdown`でレポートなど執筆して、pdfに出力したいのだが、`pandoc`の出力エンジンを`pdfroff`にすれば、`TeX`のインストールが回避できそう。`groff`, `gs`必要だけど。このあたりについてのちのち書く予定とします。`

### TeXは

overleaf.comで組版することとして、`groff`, `gs`やめました。

## 事務作業系

`microsoft office`が導入できないので、それに代わるものがないとならない。`MS Word`の代わりは、`pandoc`. `MS Excel`の代わりは `(g)awk`. `MS Powerpoint`の代わりは、`marp-cli`. `WebMail`は最近2FAになって、`Rpi4`のそれがあるのか疑問なので、`muttmua`? じつは現在`wsl`にも`muttmua`を導入してる。ちょこちょこメールチェックする分には便利。`todo.txt`ってもともとLinux用で、しかも`bash`で書かれていて、これも問題ないでしょう。

## プログラミング系

`julia`は、`Arm64`サポート宣言しているので、大丈夫そう。`archlinux` Wikipediaに[`gnu-plot` installer](https://archlinuxarm.org/packages/aarch64/gnuplot)あった。`git`は、[しらべてない](https://hitori-sekai.com/tool/raspberrypi-git-install/)けど、おそらく[大丈夫でしょう](https://archlinuxarm.org/packages/aarch64/git)。`docker`は、installation報告があるけど、前述のとおり、image側で対応してなかったらどうしよう？たまに数式変形したい衝動にかられるし、できれば、`sympy` or `Maxima`やりたい。

### gitインストール

gitできました。クローンとかプルとかできると うれしさがじんわり・・・

## ビジュアル系

`inkscape`を`RPi4`に導入したってブログがあった。`draw.io`でもいいような。これを機会に絵を描く時は、UMLや(`NN-SVG`)[https://github.com/alexlenail/NN-SVG]といったスクリプトから絵を発生させる系のものに限定するってのもいいかも。古くは、[graphviz](https://ja.wikipedia.org/wiki/Graphviz).



### 動画再生

これについて、ラズパイにはもともとVLCというのがプレインストールされてます。


## misc.

3 A出せるACアダプター/モバイルバッテリーがやってくれば実機で試せるのですが・・・

ブラウザから動画を見るのがツライからもしれない。そのときは[`yt-dlp`](https://archlinuxarm.org/packages/aarch64/yt-dlp)→`VLC`か？
せんせー、グラフェンってなに？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/2c47de5a-d81a-78f9-53c1-4d31d8398c36.png)

キーンコーンカーンコーン...
授業が始まります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/be1492ca-910f-2708-d0fa-8fcfcf14af73.png)

せんせー、グラフェンってなに？

# グラフェンとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194265/da229491-9c49-fb7a-a542-417180e256a7.png)

## グラフェンって何？

みんな、鉛筆で絵を描くことが好きだよね？鉛筆の芯を使って絵を描くとき、実はとても特別なものが出てきているんだよ。その名前は「グラフェン」だよ。

## どういうこと？

グラフェンは、鉛筆の芯にあるようなものだけど、ちょっと特別。とっても薄いペーパーみたいな形をしているんだけど、そのペーパーはとっても強くて、電気もよく流れるんだ。

## どうしてそれがすごいの？

グラフェンはとっても薄くて、電気がよく流れるので、電話やテレビ、おもちゃなどの新しい道具を作るのに役立つんだ。大人たちは、グラフェンを使って、もっとすごいものを作ろうとしているよ。

## だから、グラフェンってなに？

グラフェンは、とっても薄いけど強い特別なペーパーのようなもの。そして、このグラフェンを使って、いろんな新しいものを作ることができるんだよ。

# まとめ

このように、グラフェンはとってもすごい材料で、未来の道具やおもちゃをもっとすごくするために、大人たちは研究しているんだよ。
YOLO系のAIモデルに記載されているYOLO-s, YOLO-m, YOLO-lは何なのか？

## 結論
EfficientDetで用いられた `compound scaling`(複合スケーリング)におけるスケーリング原則にしたがって、アーキテクチャの層の深さとチャンネル数を変更した違いを表記したもの。

## 背景
YOLOXやYOLOv7の論文を見ているとYOLOX-sやYOLOX-mなどのモデルの表記が突然でてくる。
表を見ているとモデルのパラメーターが減っている違いなどがあるが、具体的な内容が知りたかった。

## 調査

### いつから表記されるようになったのか

YOLOv3やYOLOv4の論文ではこのような表記は存在しない。論文として残っているモノで初めて見られるのはYOLOXの論文である。YOLOXの論文中の2.2節にある`Modified CSPNet in YOLOv5`の項には以下の記載が見られる。

>We also follow its scaling rule to product YOLOXS, YOLOX-M, YOLOX-L, and YOLOX-X models. Compared to YOLOv5 in Tab. 3,

YOLOv5で導入された何かが影響していそうである

YOLOv5について調べてみようとしたが、論文が存在しない。仕方ないのでgithubの方で調べてみると以下の[issue](https://github.com/ultralytics/yolov5/issues/7152)内で以下の表記を見つけた。

>@Averen19 yes the YOLOv5 models are all compound-scaled variants of the same architecture. I did this following the EfficientDet compound scaling model, minus the image scaling.

どうやら 画像のリサイズ以外は EfficientDet における`compound scaling` に従っているようである。

### EfficientDetの compound scaling

EfficientDetについてを見ていく。
この論文ではモデルのスケールアップ（同一のアーキテクチャにおいて層の深さやチャンネル数を増やすことで精度向上を行うこと？）を効率化するために画像のサイズや層の深さ、チャンネル数を変化させるために単一のパラメーターを用いる方法を採用しているようである。

この手法をYOLOに導入することにより、YOLO-sなどの表記がなされるようになったようである。
x-line-signatureを検証可能な形式でAPI GatewayからSQSに送る

## はじめに
先日、LINEのwebhookをAPI Gatewayで作成し、SQSにシグネチャ、本文を送ろうとした時にかなり躓いたので、その時にやっとことをまとめようと思います。

## 概要
LINEで用いられているシグネチャであるx-line-signatureは、signatureと本文が一致しているかを検証するために使用されます。

今回はAPI GatewayからSQSにシグネチャを送信し、ポーリング先で検証を行うことが必要であったため、検証可能なメッセージのフォーマットでSQSに送る必要がありました。

しかし、JSON形式のオブジェクトは、キーの順序が保証されていないため、構造体などに変換すると順序が入れ替わってしまい、検証がうまくいかない可能性があります。

色々調査したところ、AWS Lambdaを使用してAPI Gatewayで受けたリクエストのシグネチャを検証する方法についての情報は多く見かけたのですが、SQSからのメッセージをポーリングした後に検証する方法についてはほとんどありませんでした。

## 話さないこと
・API Gateway、SQSの作成方法
・API GatewayからSQSにメッセージを送る設定方法
・具体的なシグネチャの検証方法

## LINEのwebhookで今回想定するデータ
LINEのWebhookから送られてくるデータは、以下のような構造であると仮定しています。
### x-line-signature
```
    "x-line-signature" : "signature"
```

### 本文
```json
{
    "body1" : "body1",
    "body2" : "body2"
}
```


## テンプレートマッピングの設定（失敗例1）
まず最初に、次のように本文をそのまま送るテンプレートマッピングを試みました。
```
Action=SendMessage&MessageBody={
	"signature": "$input.params().header.get('x-line-signature')",
	"body": $input.body
}
```
しかし、この方法ではbodyがオブジェクトとして認識され、構造体に変換した際に順序が入れ替わる可能性があります。結果として、SQSに送信されるメッセージの形式は次のようになる可能性があります。

```json
{
    "signature" : "signature"
    "body" : {
        "body2" : "body2",
        "body1" : "body1"
    }
}
```
この形式では、x-line-signatureの検証は失敗してしまいます。

## テンプレートマッピングの設定（失敗例2）
次に、bodyを文字列として送信しようと試みました。
```
Action=SendMessage&MessageBody={
	"signature": "$input.params().header.get('x-line-signature')",
	"body": "$input.body"
}
```
しかし、この方法ではbodyがオブジェクトとして認識され、文字列の中にダブルクォーテーションが使われることになります。

```json
{
    "signature" : "signature"
    "body" : "{
        "body1" : "body1",
        "body2" : "body2"
    }"
}
```
文字列の中にダブルクォーテーションが使われることになるので、この状態では当然エラーとなってしまいます。

## テンプレートマッピングの設定（成功例）
最後に、成功例として以下のテンプレートマッピングを試みました。
```
Action=SendMessage&MessageBody={
	"signature": "$input.params().header.get('x-line-signature')",
	"body": "$util.escapeJavaScript($input.body)"
}
```
この設定では、$util.escapeJavaScriptを使用してダブルクォーテーションをエスケープし、bodyを文字列として送信します。

```json
{
    "signature" : "signature"
    "body" : "{
        \"body1\" : \"body1\",
        \"body2\" : \"body2\"
    }"
}
```
これにより、構造体に変換する際にbodyが文字列として認識され、検証が可能となります。

## 最後に
API Gateway→Lambda→SQSの流れでLambdaでwebhookのシグネチャの検証を行う方法もありますが、わざわざLambdaを使うのももったいないですよね。ポーリング先で検証を行う環境があれば本記事の内容を参考にしてみてください。

ご覧いただきありがとうございました！
Power Query workout - 必要になるまで評価しないので、不要な評価をしないということができる

わかったようでわからない、結果が必要になるまで式を評価しないという動作。Lazy evaluation、遅延評価と訳されるのだけど、全体計算量を減らすなどクエリ評価の最適化にはとても重要な動作。 

必要になるまで式を評価しないので、不要な評価しないことができる。という評価戦略

# たとえば
このクエリは 5行3列のテーブルと評価される。
後続の処理があれば、その処理を含めた評価が行われる。5行3列として先行評価されるわけではない。
```text:Power Query
// Query1
let
    Source = Table.FromColumns(
        {
            List.Numbers(1, 5)
        },
        type table [Column1 = Int64.Type]
    ),
    AddedColumn2 = Table.AddColumn(
        Source, "Column2",
        each [Column1] + 10,
        Int64.Type
    ),
    AddedColumn3 = Table.AddColumn(
        AddedColumn2, "Column3",
        each [Column1] * 10,
        Int64.Type
    )
in
    AddedColumn3
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/a1a1f779-0a0a-1997-d558-a93852d67d8d.png)

Query1 を参照するクエリで列を選択したとき、
```text:Power Query
// Query1_A
let
    Source = Query1,
    RemovedOtherColumns = Table.SelectColumns(Source,{"Column1", "Column3"})
in
    RemovedOtherColumns
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/05b98aaa-bca3-f8bc-3b60-609828f9c0ea.png)
列 Column2 は必要がないので評価されない。Query1 のステップ AddedColumn2 で Column2 は追加しない動作になる。

Query1 を参照するクエリで行を選択したとき、
```text:Power Query
// Query1_B
let
    Source = Query1,
    FilteredRows = Table.SelectRows(Source, each ([Column1] = 3))
in
    FilteredRows
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/227d678e-9590-a5ff-3aa3-84925e336979.png)
Table.SelectRows の行を選択する条件 `[Column1] = 3` はすべての行で評価される。
`[Column1] = 3`が`true`になる行のみ、[Column2] と [Column3] は評価され、Query1 のステップ AddedColumn2 と AddedColumn3 で列が追加される動作。行を選択してから列を追加する動作と同じになる。

# 思ったこと🙄
この動作は "可能な限り" で "常に" ではない。なので、
ベストプラクティスは "できるだけ早いタイミングで不要な行もしくは列を除外すべき" ということだ。


# その他
https://powerbi.connpass.com/

- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
iTerm2でF16などのキーコードを無視したいとき

# 概要
最近自作キーボードを作ったので以下の記事を参考にMacに現在のレイヤーを表示するようにしました。
https://balatero.com/writings/qmk/add-visual-layer-indicator-for-qmk-to-mac-os/

ただ、レイヤー切り替え時に送信しているF16キーがiTermで悪さをしていたのでその対処法

# 対応
Profiles -> 　[利用しているProfile] ->　Keys -> KeyMappings からF16のコンビネーションを無効化するだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403521/dafb7912-547a-bd1a-ad3e-d9cda52773ae.png)

　#　感想
ペースト時に謎の「S」が挿入されたりビープ音がうるさかったりで自作キーボードの利用をやめようかと思っていたので対処法があってよかった
ネットワーク上のデバイス名を知る方法

Raspberry Pi や Jetson Nano の IPアドレスを探そうとして、`arp -a`とかやってたけれど、どのIPがどの端末だったかなと、いつも困っていました。そういうときは`arp-scan`を使うと良さそうです。

Homebrew で以下のように入れられます。
```zsh
% brew install arp-scan
```

以下のように`grep`と併用すると、とても判りやすくて便利です。

```zsh
% sudo arp-scan 192.168.0.0/24 | grep Rasp
192.168.0.142   xx:xx:xx:xx:xx:xx       Raspberry Pi Foundation
192.168.0.167   xx:xx:xx:xx:xx:xx       Raspberry Pi Foundation
```
【Oracle DB】DATE型のカラムに日付をINSERTすると、ORA-01861: literal does not match format stringとなる

## やったこと

Goのdatabase/sqlパッケージを使用し、DATE型のカラムtest_dayに日付をINSERTした。

```go
query := INSERT INTO my_table(test_day) VALUES('1999-01-01')

db.ExecContext(ctx, query)
```

## エラー

ORA-01861: literal does not match format string

## 対応

OracleDBのTO_DATE関数を使用する
明示的にDATE型に変換して日時データにする必要がある。

```go
query := INSERT INTO my_table(test_day) VALUES(TO_DATE('1999-01-01','YYYY-MM-DD'))

db.ExecContext(ctx, query)
```

こちらでも可能だが、時刻の指定はできず、時刻は常に00時00分00秒となる
（<font color="red">日付</font>リテラルであり、日時リテラルではない）

```go
query := INSERT INTO my_table(test_day) VALUES(DATE '1999-01-01')

db.ExecContext(ctx, query)
```
Grafana Tempo Structural operators

Grafana Tempo v2.2でStructural operatorsが追加されたのでユースケースを考えてみます

https://grafana.com/blog/2023/08/02/grafana-tempo-2.2-release-traceql-structural-operators-are-here/

- ユースケース1 「NATループバックの可能性のある通信を探す」

Kubernetesにはクラスタ内にあるDNSサーバが名前解決してServiceやPodへ通信する機能があります。Service間の通信はこちらを使うことでクラスタ外に出ずに通信することが出来るので通常はこちらを使うことになります。

https://kubernetes.io/ja/docs/concepts/services-networking/dns-pod-service/

しかし、意図せずクラスタ外のDNSで登録されたドメインを使った通信をアプリケーションが実装してしまうこともあるでしょう。この場合にパフォーマンス以外の問題としてNLBを前段においてインスタンスを登録している場合、トラフィック送信元IPをそのままターゲットに送信します。そうなることで送信元と送信先が同一IPとなってしまうことでNATループバック（ヘアピニング）が発生しリクエストがタイムアウトしてしまうことがあります。

https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#loopback-timeout

この例ではIstioを使っていてIngress Gatewaysをクラスタの入り口とした場合を考えます
とあるService Aから別のService Bに通信するときにservice-b.default.svc.cluster.local.と通信すべきところを外部ドメインのservice-b.example.comで通信してしまったとしています。

なんらかの方法でこのNATループバックが起きる可能性がある通信を検知したとします（eBPFなどでtcp監視してメトリクス送信してアラートで検知など）

そういった場合の調査でStructural operatorsを使うといいかもしれません

```
{.service.name="service-a.default"} >> {.service.name="istio-ingressgateway.istio-system"}
```

![スクリーンショット 2023-09-26 11.01.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10683/bc80e586-2bd4-e244-7721-da0974414b8b.png)


service-aが記録しているtraceのなかでistio-ingressgateway.istio-systemに通信しているものを洗い出します。その先がクラスタのServiceであればそれはNATループバックのリスクがある通信だということになります。

- ユースケース2 「とあるサービスでDBへの接続に時間がかかっているリクエストを調べる」

メトリクスでやることが適切なような気もしますが雑に調べるとすれば例えばこうです

```
{.service.name="service-a"} >> {.net.peer.name="db.example.com" && .db.operation = "CONNECT" && duration > 50ms}
```

先にDBのコネクトに時間がかかっているspanを検索してもいいのですが

```
{.net.peer.name="db.example.com" && .db.operation = "CONNECT" && duration > 50ms}
```

Structural operatorsが利用できるのであればServiceを特定することが出来ますね

## さいごに

Structural operatorsによって目的のトレースを取得するための選択肢が増えました

便利に使っていこうと思います
AWSのCloud9とGitHubをSSH接続する方法

### 今回の流れ
1. Cloud9上でSSH認証用の公開鍵を作る
1. 公開鍵をGitHubへ登録する
1. GitHubにて個人アクセストークンを発行する
1. 動作確認：GitHubからリポジトリをCloneする
1. 動作確認：テスト用ファイルをGitHubへpushする

## ステップ１ 
### Cloud9を立ち上げる
ここは本題ではないのであっさり行きます。

まずは AWS に登録し、ログインします。
次に AWS Cloud9 の開発環境を作成し、ターミナルを起動します。
ターミナルが起動できたら、以下のコマンドを入力して、Git のバージョンを確認します。

`git --version`
 

AWS Cloud9 には あらかじめ Git がインストールされているので、コマンドを実行すると 以下のように表示されます。これで Git が使える状態になっています。

## ステップ２

### Cloud9とGitHubを連携させます。

1. **Cloud9でsshキーを生成し、GitHubに登録**

    Cloud9とGitHubを連携させるには、Cloud9においてSSHキーを発行し、そのSSHキーをGitHubに登録する必要があります。
    
    まずはCloud9上のターミナルで以下のコマンドを実行し.sshディレクトリに移動します。

    `cd ~/.ssh`
    <br>


    次に以下のコマンドを実行してSSHキーを発行します。
    
    いくつか入力する場面がありますが、そのままenterを押していってください。

    `ssh-keygen`
    <br>

    SSHキーが発行できたらのコマンドを実行してSSHキーを表示させます。
    `cat id_rsa`
    `cat id_rsa.pub`
    <br>
    
    `ls -a`　隠しファイルを含むファイルを確認
    うまくいかない時は上記のコードを実行して行末のファイル名と自分のファイル名があってるか確認してください

## ステップ3
### 公開鍵をGitHubへ登録する

次にGitHub画面に行き、コピーしたSSHキーを登録していきます。

GitHub画面右上のアイコンボタンから「Settings」をクリックします。

その中の「SSH and GPG keys」を選択して、「New SSH keys」をクリックします。

Add new画面にて、各項目に従い以下のパラメータを記入します。
記入後、「Add SSH Key」ボタンをクリックします。
___
・Title：<任意のタイトルを記載して下さい>
・key：<コピーした公開鍵を貼り付けます>
___


## ステップ4
### GitHubにて個人アクセストークンを発行する
この 『個人アクセストークン』 もGitHubにて発行します。
以下の手順を実行して下さい。

1. GitHubを開きます。
GitHubのトップページにて、右上のプロフィールアイコンをクリックします。
プルダウンの中から「Settings」をクリックします。 ※ここまではSSHの時の手順と同じです

2. Settings画面にて、左ペイン「Developer settings」⇒「Personal access tokens」とクリックします。

3. Personal access tokensにて、画面右上の「Generate new token」をクリックします。

4. New personal access token画面にて、各項目に従い以下のパラメータを記入します。
記入後、「Generate token」ボタンをクリックします。
___
・**Note**：<任意のタイトルを記載して下さい>
・**Expiration**：<トークンの有効期限を指定します。任意の日数を指定下さい>
・**Select scopes**：<トークンのロール(権限)を指定します ※とりあえず全ての項目にチェックを付けて下さい>
___

トークン作成後にパスフレーズが表示されます。
こちらのパスフレーズは必ずどこかに保管しておいてください。
※ このパスフレーズが実質的なパスワードになります
<br>

## ステップ５
### 動作確認
**GitHub上のリモートリポジトリをCloud9の作業ディレクトリへCloneします。**
以下の手順を実行して下さい。

GitHubからリポジトリをCloneする

GitHubにて、push先のリポジトリのトップページを開きます。
画面右上の「Code」ボタンをクリックし、プルダウンにてClone URL(HTTPS)をコピーします。

Cloud9を開きます。
以下のコマンド操作を実行して下さい。

    ```
    ### 事前準備 ###
    # 作業用ディレクトリを作成し、移動する
    $ mkdir test_dir
    $ cd test_dir 
    
    ### git作業 ###
    # gitの初期設定
    $ git config --global user.name <GitHubに登録したユーザー名>
    $ git config --global user.email <Githubに登録したメールアドレス>
    
    # リモートリポジトリをCloneする
    $ git clone <GitURL(HTTPS)> 
    
    # リポジトリがコピーできているか確認する
    $ ls -ltr
    ・・・
    <リポジトリ名>
    ・・・
    ```

## ステップ６
### テスト用ファイルをGitHubへpushする
**テスト用ファイルを作成し、リモートリポジトリへのpushを行います。**
以下のコマンド操作を実行して下さい。

```
# Cloneしたリポジトリへ移動
$ cd <リポジトリ名>

# origin設定
$ git push -u origin main
Username for 'Git URL(HTTPS)': <GitHubのユーザー名>
Password for 'Git URL(HTTPS)': <GitHubにて作成した個人アクセストークンのパスフレーズ>

# テストファイルの作成
$ echo 'Hello World' > <ファイル名>

# テストファイルをステージング環境へ追加する
$ git add <ファイル名>

# ステージング環境にあるテストファイルをリモートリポジトリへコミットする
$ git commit -m "<コミットメッセージ>"

# コミットしたテストファイルを、リモートリポジトリへpushする
$ git push origin main
```

    

以上で、動作確認手順は完了となります。
<br>
<br>

### 参考にさせていただいたサイト様

インフラエンジニアによる技術提供ブログ！ chibinet
https://chibinfra-techblog.com/aws-cloud9-github-env-web-code/


アントレプレナー
https://kosuke-space.com/cloud9-github
[003] RC回路のステップ応答~畳み込み~

tex記法とMarkdown記法の練習を兼ねて，図2のRC回路のステップ応答を求めてみる．
```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
title {
  FontStyle normal
  FontColor black
  FontSize 20
}
</style>
title
<img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/615014/c28d160c-81c8-3283-8fad-9e0249660abc.png>
図2 RC回路
end title
@enduml
```


コンデンサ$C$に流れる電流$i(t)$は，
$$i(t)=C\frac{dv_o(t)}{dt}$$

と表される．
この式を使って，キルヒホッフの電圧則を表すと，

$$v_i(t)=RC\frac{dv_o(t)}{dt}+v_o(t)$$

$\mathcal{L}[v_i(t)]=V_i(s),\mathcal{L}[v_o(t)]=V_o(s)$として，両辺をラプラス変換すると，

$$V_i(s)=RC[sV_o(s)-v_o(0)]+V_o(s)$$

$v_o(0)=0$として，伝達関数$G(s)=V_o(s)/V_i(s)$を求めると，


$$G(s)=\frac{V_o(s)}{V_i(s)}=\frac{\frac{1}{RC}}{s+\frac{1}{RC}}$$

デルタ関数$\delta (t)$のラプラス変換は，
$$\mathcal{L}[\delta (t)]=1$$

$v_i(t)=\delta (t)$をRC回路へ入力したとき，$V_i(s)=\mathcal{L}[v_i (t)]=1$である．

出力電圧のラプラス変換は，
$$V_o(s)=G(s)V_i(s)$$

と表されるので，RC回路のインパルス応答$g(t)$は，

```math
\begin{align}
V_o(s)&=G(s)\\
v_o(t)&=\mathcal{L}^{-1}[V_o(s)]=\mathcal{L}^{-1}[G(s)]=g(t)\\
\therefore g(t)&=\mathcal{L}^{-1}[G(s)]
\end{align}
```
インパルス応答$g(t)$は伝達関数$G(s)$より．
$$g(t)=\mathcal{L}^{-1}[G(s)]=\frac{1}{RC}e^{-\frac{1}{RC}t}$$

と求められる．

任意の入力における応答はインパルス応答$g(t)$と入力との畳み込みで表すことができる．
RC回路にステップ関数$Eu(t)$を入力したときのステップ応答$v_o(t)$は，

```math
\begin{align}
v_o(t)&=\int^t_0 g(\tau)Eu(t-\tau)d\tau\\
&=E\int^t_0\frac{1}{RC}e^{-\frac{1}{RC}\tau}d\tau\\
&=\frac{E}{RC}\left[ -RC e^{-\frac{1}{RC}\tau}\right]^t_0\\
&=\frac{E}{RC}\left[ -RC e^{-\frac{1}{RC}t}+RC\right]\\
&=E\left(1-e^{-\frac{1}{RC}t}\right)
\end{align}
```

出力電流$i(t)$は出力電圧$v_o(t)$の時間微分より，
$$i(t)=C\frac{dv_o}{dt}=\frac{E}{R}e^{-\frac{1}{RC}t}$$

電圧$v_o(t)$と電流$i(t)$を再掲すると，

```math
\begin{align}
v_o(t)&=E\left(1-e^{-\frac{1}{RC}t}\right)\\
i(t)&=\frac{E}{R}e^{-\frac{1}{RC}t} 
\end{align}
```
Slack Appを使ってSlackのメッセージを取得してみた。

Slackのあるチャンネルのメッセージを全部取得してみました。

以下のページを参考にしました。

参考ページ1

https://lumitec.co.jp/hp/slack%E3%81%AE%E3%83%97%E3%83%A9%E3%82%A4%E3%83%99%E3%83%BC%E3%83%88%E3%83%81%E3%83%A3%E3%83%B3%E3%83%8D%E3%83%AB%E3%82%92%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E3%81%99%E3%82%8B/

参考ページ2

https://zenn.dev/nariakiiwatani/articles/8ed4a7bb0d5d0b

Slack AppとGoogleスプレッドシート(Apps Script)を使うやり方です。

１　「Slack App」を作成して設定し、トークンを取得。
２　（メッセージを取得したい）プライベートチャンネルのIDを取得する。
３　「Googleスプレッドシート」を準備して、実行。

(参考ページ2のコードはなぜかエラーが出て動かなかったので、参考ページ1のコードを利用しました)

また、参考ページ1のコードは、

>※尚、ブログの仕様上、プログラム内のダブルクォーテーションが「 “ 」になっているかと思いますが、そのままではエラーになってしまうため、適宜「半角のダブルクォーテーション」に変換してください‥！

ということだったので、「半角のダブルクォーテーション」に変換したコードをここに掲載します。
(Qiitaならそんな変換はされずに大丈夫のハズ・・・)


```
var OAuthAccessToken = "取得したトークン";
var channelID = "取得したプライベートチャンネルのID";
function main() {
var fetchUrl = 'https://slack.com/api/conversations.history?channel=' + channelID + '&limit=1000';
const options = {
"headers": { 'Authorization': 'Bearer ' + OAuthAccessToken }
}
var res = UrlFetchApp.fetch(fetchUrl,options);
res = JSON.parse(res);

var messages = [];
do {
var newMessages = [];
res.messages.forEach(function (v) {
if('thread_ts' in v) {
var fetchUrl = 'https://slack.com/api/conversations.replies?channel=' + channelID + '&ts=' + v.thread_ts;
const options = {
"headers": { 'Authorization': 'Bearer ' + OAuthAccessToken }
}
var reply = UrlFetchApp.fetch(fetchUrl,options);
reply = JSON.parse(reply);
newMessages = newMessages.concat(reply.messages.reverse());
}
else {
newMessages.push(v);
}
});
newMessages = newMessages.map(function (v) {
return [
v.client_msg_id,
v.type,
v.text,
v.user,
v.ts,
v.reply_count || 0,
v.reply_users_count || 0,
];
});
messages = messages.concat(newMessages);
} while (res.has_more);

SpreadsheetApp
.getActiveSheet()
.getRange('A2:G' + (messages.length+1))
.setValues(messages.reverse());
}
```

このGoogleスプレッドシートのApps Scriptを実行すると、Slack Appからメッセージを取得してくれました！

![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/a7c6e9d5-f4bb-3e11-cda6-939bf550a622.png)
サーバーレス開発に関するセミナーを受講しました

# 受講するきっかけ
現在業務ではAWSインフラの構築を担当している。
基本的に構築するのはサーバー+DBという構成だが、今後クラウドネイティブな環境構築を求められるたとき、サーバーレスというのは欠かせない知識になるだろう。
その知識をつけるためにセミナーを受講する。

# API GatewayによるAPIの提供

##### 実現できること
・基幹APIへの安全なアクセス
・スモールスタート
・既存設備との疎結合な連携
・運用省力化
・APIポータル、カタログの構築
・API管理のルール整備を急ぐ

以下は構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1282600/76686d1a-1bfc-d456-cce2-7f722e8e9842.png)


##### サーバーレス利用で変わること
・アプリ部⾨主導でAWS のコントロールが可能
・サーバー、仮想マシンのメンテナンス（セキュリティパッチ等）の負荷軽減
・スモールスタートで必要な部分のみの調達がしやすい

##### 変わらないこと
・開発、運⽤の分離（アプリ部⾨が本番環境を気楽にさわれるようにしない）
・障害の基本的な運⽤は変わらない（障害切り分け、異常に気づける仕組みづくり）
・ドキュメントは整備する（運⽤部⾨への移管を⾒据えて）
・テスト⾃動化、CI/CD の検討（プロセスを取捨選択し、⾃動化対象決定）

# DevOpsのためのサーバーレス構築
サーバーレスで実現できること
・コストメリット
・運用効率化(省人化)
・スケーラビリティ
・BCPの向上

以下は構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1282600/3989699c-3439-a876-e29d-a0c6cba5ae50.png)

##### サーバーレス導入にあたっての課題や準備
• POC実績は最⼤の武器
　　- ステークホルダーへのこれ以上ない説得材料
　　- 実現できるかの不安払しょく（⾃⾝、対外ともに）
　　- POCサイクルを回し、⾃社としての、「現時点での正解」を⽬指す
• POCは内製体制の⽅がアプローチしやすい
　　- 最終的なアウトプット⽬標は定めるが、実際のアウトプットは流動的に積み上げ
　　- チームとしてのサーバーレス技術習熟度に応じたアウトプットを⽬指す
• AWSの各種リソースを最⼤限活⽤する
　　- 公開ドキュメントは、質・量ともにAWSは優秀。活⽤しない⼿はない
　　- AWSアーキテクトとの対話で、⾃組織のAWS理解を深める（本当にお世話になってます）
　　- ⾃⾝・⾃組織が頑張る姿勢が前提
• AWS認定資格の知識習得は重要
　　- AWSのサーバとサーバーレスの特徴や、⽬指す姿を語れるように
　　- 特にAWS SolutionsArchitect Associate
　　- AWSの経験なくとも、知識と実績で対応できます

# 所感
やはり現行の構成をそのまま持っていくよりも、サーバーレスにする際に考慮すべき点は多くなると感じた。
ただし実現できればメリットも多く、クラウドの利点を活かすことができるものである。
サーバーレスはクラウドネイティブな仕組みづくりに重要な要素であるため、今後も定期的に勉強を進め、また最新の情報のインプットも欠かさず行っていきたい。
モバイルファースト設計のJSの基本

本記事では、モバイルファーストの設計においてJavasciptを使ったレスポンシプテザインに注目し、パフォーマンスや保守性を考慮したコーディング手法について解説します。
JavaScriptを使ったレスポンシブデザインの基本として、パフォーマンスの確保、レスポンシブデザインに対応する、プログラムの保守性の確保の3点を取り上げ、それぞれについて具体的な説明やコード例を示します。

モバイルファーストの設計において、JavaScrptでレスポンシブデザインを実装する際には、以下のポイントに注意する必要があります。

①パフォーマンスの確保
﻿②レスポンシブデザインに対応する
﻿③プログラムの保守性の確保


①﻿パフォーマンスの確保 
Javascripは処理が重たく、モバイル端末ではパフォーマンスの問題が起こりやすくなります。そのため、処理の軽量化や、必要な処理だけを実行するようにするなど、パフォーマンスの確保に注意が必要です。
﻿②レスポンシプデザインに対応する 
JavaScriptでは、画面サイズに応じたレイアウトの変更や、ユーザーの端末環境に応じた処理の実行を行うことができます。そのため、レスポンシプデザインに対応するために、画面サイズの判定や条件分岐などを行う必要があります。
﻿③プログラムの保守性の確保 
JavaScriptはコードの行数が多くなりがちで、保守性の問題が起こりやすい言語です。そのため、可読性の高いコードの書き方や、コメントの活用、関数の分割など、保守性の確保に注意が必要です。


具体例
①の具体例
1. JavaScriptの最適化 
Javascriptのコードを最適化することで、処理の軽量化を図ることができます。具体的には、以下のような方法があります。
・変数のスコープを限定する
・変数や関数の名前を短くする（ただし、可読性が悪くならないように注意が必要）
﻿・ループ処理を極力避ける
・﻿関数の再帰呼び出しを避ける
・﻿関数内で同じ処理を何度も繰り返さないようにする

2. レスポンシブデザインの実装 
モバイル端末において、画面サイズが小さいためにレイアウトが前れたり、表示が崩れたりすることがあります。この問題を解決するために、レスポンシブデザインを実装することが重要です。具体的には、以下のような方法があります。
・メディアクエリを使用して、画面サイズに応じたスタイルを適用する
・﻿画像のサイズを自動で調整する

3. 不要な処理の削除 
JavaScriptによる処理が重い場合、不要な処理を削除することでパフォーマンスを向上させることができます。具体的には、以下のような方法があります。
・﻿ページ読み込み時に必要のない処理を遅延させる
・不要なライプラリやプラグインを削除する
・﻿キャッシュを使用して、同じ処理を何度も行わないようにする

以上のような処理を取り入れることで、Javascrpiによる処理の重さを軽減し、モバイル端末でも
快適なパフォーマンスを実現することができます。

②の具体例
1.画面サイズの判定
レスポンシプデザインでは、画面サイズに応じてレイアウトを変更する必要があります。そのため、画面サイズを判定する処量を行う必要があります。具体的には、以下のような方法があります。
・window.innerwidth プロパティを使用して、画面幅を取得する
・matchMediaメソッドを使用して、メディアクエリにマッチするかどうかを判定する
・﻿レイアウトをシンプルにする

【window.innerwidthを用いて画面幅を取得し、取得した幅に応じて処理を実行するコード例】
```
function checkWidth() {
    var windowWidth = window.innerWidth;

    if (windowWidth < 600) {
        //画面幅が609px以下の場合の処理
    ) else if (windowWidth < 1200) (
        //画面幅が1200px以下の場合の処理
    } else
        //画面幅が1290px以上の場合の処理
    }
}

window.addEventListener('resize', checkWidth);
```

2.条件分岐の実装
画面サイズに応じたレイアウトの変更や、ユーザーの端末環境に応じた処理の実行には、条件分岐が必要です。具体的には、以下のような方法があります。
・if文を使用して、条件分岐を実装する
・switch文を使用して、条件分岐を実装する
・三項演算子(条件演算子)を使用して、簡潔な条件分岐を実装するかどうかを判定する

【三項演算子(条件演算子)を使用したコード例】
```
var num = 12;
var result = num >= 10 ? "numは10より大きい":"numは10より小さい"
console.log(result);
```

3.イベントの取得 
レスポンシプデザインでは、ユーザーの端末環境に応じた処理の実行が必要な場合があります。そのため、ユーザーの操作に対するイベントの取得が必要です。具体的には、以下のような方法があります。
・addEventListenerメソッドを使用して、クリックやスクロールなどのイベントを取得する
・touchstartやtouchendなど、タッチ操作に対するイベントを取得する

画面サイズの判定や条件分岐を実装することで、画面サイズに応じたレイアウトの変更や、ユーザーの端末環境に応じた処理の実行を行うことができます。また、イベントの取得により、ユーザーの操作に応じた処理を実行することができます。

③の具体例

1. 可読性の高いコードの書き方 
コードの可読性を高めることで、保守性を向上させることができます。具体的には、以下のような方法があります。
﻿・インデントを揃える
・﻿変数や関数の名前をわかりやすくする
・﻿コードのブロックを{}で囲む
・﻿コメントを付ける（後述）

2. コメントの活用
コードの中には、何をしているかわかりにくい部分もあります。そのため、コメントを活用することで、コードの意図を明確にすることができます。具体的には、以下のような方法があります。
﻿・コードの前に、何をする関数か、どのような引数を受け取るかを説明する
・﻿コードの中に、なぜその処理をする必要があるか、どのようなデータを扱っているかを説明する
・﻿コードの後に、何を返すのか、何を更新したのかを説明する

3.関数の分割
1つの関数が長くなりすぎると、コードの保守性が低下します。そのため、関数を複数の小さな関数に分割することで、コードを見やすくすることができます。具体的には、以下のような方法があります。
﻿・関数の役割を明確にする
・﻿1つの関数で何度も同じ処理をしないようにする
・﻿関数の引数と戻り値を明確にする

コードの可読性を高め、コメントを活用し、関数を分割することでコードの理解が容易になり、保守性を確保することができます。
VSCodeでマークダウンを書く時の設定_Markdown_Preview_Enhanced

# VSCodeでMarkdown_Preview_Enhancedを使用する時の設定等
たくさんの方の記事を参考に自分で設定しているのをメモとして。
日本語の公式
https://shd101wyy.github.io/markdown-preview-enhanced/#/ja-jp/

# フロントマスターでの設定
マークダウンの始めの所で設定するのをフロントマスターというよう。
- 上書き保存でhtml出力される
- toc目次の設定をする

```
---   
export_on_save:
  html: true
toc:
  depth_from: 1
  depth_to: 6
  ordered: true
---
```

# スタイルシートの設定
スタイルファイルを読み込むように本文へ追加
`@import "./.vscode/style.less"`
見出しの連番とか見た目を設定している

```cs
/* 見出しを自動採番する */
body {
  counter-reset: chapter;
}
h1 {
counter-reset: sub-chapter;
}
h2 {
counter-reset: section;
}
h3{
  counter-reset: sub-section;
}
h4{
  counter-reset: sub-sub-section;
}
h5{
  counter-reset: sub-sub-sub-section;
}

/* h1:before {
counter-increment: chapter;
content: counter(chapter) ". ";
}  */
h2:before {
counter-increment: sub-chapter;
content: counter(sub-chapter) ". ";
}
h3:before{
  counter-increment: section;
  content: counter(sub-chapter) "-" counter(section) ". ";    
}
h4:before{
  counter-increment: sub-section;
  content: counter(sub-chapter) "-" counter(section) "-" counter(sub-section) ". ";    
}
h5:before{
  counter-increment: sub-sub-section;
  content: counter(sub-chapter) "-" counter(section) "-" counter(sub-section) "-" counter(sub-sub-section) ". ";    
}
h6:before{
  counter-increment: sub-sub-sub-section;
  content: counter(sub-chapter) "-" counter(section) "-" counter(sub-section) "-" counter(sub-sub-section) "-" counter(sub-sub-sub-section) ". ";    
}

* {
font-family: "Meiryo UI";
margin:0;
padding:0;
}
h1 { 
  position: relative; padding: 0.5em; background: #7db4e6; font-weight: bolder;
  }
h2 { 
  position: relative; padding: 0.5em; 
  // background: #7db4e6;
  border-bottom: 8px solid #7db4e6;
   }
h3, h4, h5, h6 { 
  position: relative;
  border-bottom: 5px solid #7db4e6;
  }

.backcolor{
  background-color: #FFCC99;
}
```

# スクリプトの設定
スクリプトファイルを読み込むように本文へ追加
`@import "./.vscode/script.js"`
htmlを開いた時に、TOC目次を開いた状態にしたいので追加している

```js
window.onload = onLoad;
    function onLoad() {
      document.body.setAttribute('html-show-sidebar-toc', true)
    }
```

# 参考
- https://qiita.com/take_me/items/5ff5304b58d9feec21df
- https://qiita.com/bounoki/items/bbad6de9f000fe1c283d
- https://qiita.com/kumapo0313/items/a59df3d74a7eaaaf3137
- https://qiita.com/Yarakashi_Kikohshi/items/407f85ba2835d945dd5b
rails ユーザデータ削除方法(備忘録)

#### 登録したユーザーの削除

rails　consoleを起動

```ruby
User.all
```
を使い、現在の登録されているユーザを確認する。

#### id指定で削除
```ruby
User.find(id).destroy
```

- 再度、User.allをして消えたか確認する。
単体テスト

今回はZIOの単体テストを見ていきます。
バックエンド編の[zio-http](https://qiita.com/wc_sangen/private/63d3d3957245b90d2012)で作成した``ApplicationService.postTest``が正しい値を返すことを確認するテストを行いたいと思います。

# セットアップ

ZIOによる単体テストを行うために以下を``build.sbt``へ追加します。

```scala:build.sbt
lazy val root = (project in file("."))
(中略)
    libraryDependencies += "dev.zio" %% "zio-http" % "3.0.0-RC2",
    libraryDependencies ++= Seq(
      "dev.zio" %% "zio-test"          % "2.0.17" % Test,
      "dev.zio" %% "zio-test-sbt"      % "2.0.17" % Test,
      "dev.zio" %% "zio-test-magnolia" % "2.0.17" % Test
    ),
    testFrameworks +=
      new TestFramework("zio.test.sbt.ZTestFramework")
  )

```

# テストコード

テストコードについてはプロジェクトルートから``src/test/scala``配下に配置します。
今回以下のファイル名と内容で配置します。

```scala:TrainingSpec.scala
object TrainingSpec extends ZIOSpecDefault {
  def spec: Spec[Any, Throwable] = suite("単体テストトレーニング")(
    test("「postTest」が正しい値を返す") {
      for {
        test <- ZIO.succeed("test")
        uri  <- ZIO.fromEither(URL.decode("http://localhost:8080/postTest"))
        req <- ZIO.attempt(
          Request
            .default(
              Method.POST,
              uri,
              Body.fromString(
                s"userName=$test"
              )
            )
        )
        res <- ApplicationService.postTest(req)
        bodyString <- res.body.asString
      } yield assertTrue(bodyString == s"あなたの名前は${test}です。")
    }.provide(ApplicationServiceImpl.layer, Client.default)
  )
}
```

これを``sbt test``で実行するとテストが成功することが確かめられると思います。
また、IntelliJに[ZIOプラグイン](https://qiita.com/wc_sangen/private/cc713cbad4bb604a345d#%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97)を導入されている方は以下の画像の赤枠のボタンからも実行でき、確認できるかと思います。
![zio_plugin_test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1492601/d0a58ea1-31f5-d730-c4fe-0d9f218b2863.png)

詳細部分について見ていきます。

## ``ZIOSpecDefault``の継承
これまでのZIOプログラムの実行の際には``ZIOAppDefault``を継承して実行してきましたが、単体テストの場合には``ZIOSpecDefault ``を継承します。

## テスト項目設定
テスト項目の設定については``suite``関数、``test``関数で行います。
``suite``関数がテスト項目のグルーピングを担い、``test``関数が個々のテストを表しています。
``test``関数内にテストコードを書きます。

## 実処理部分

実処理部分については``TestController``から``ApplicationService.postTest``関数が呼び出される場合自動的に``Request``が作成され、引数として渡されますが、今回の場合は自動的には渡されないため、実際の``Request``インタスタンスを模したものを作成し、代わりに渡しています。

## アサーション

最終的なレスポンスボディの値が正しいものであるかの判定を``assertTrue``関数で行っています。

### DI

また、依存するオブジェクトについてDIを行う必要があるため、こちらについても通常の場合と同様に``provide``関数によりDIを行っています。

# 終わりに
今回はZIOの単体テストについて見てきました。
今回の記事で終わりです。
ご意見、ご感想、誤っているところなどありましたらお気軽にご連絡頂ければ幸いです。
それでは失礼します。

前章:[Middlewareについて](https://qiita.com/wc_sangen/private/4bece28969a6a87ff9e0)

# 演習
1. 今回の単体テストの例について実際に動かし、挙動を確かめてください。
    - 解答例は以下になります。
https://github.com/hatuda/zio-practice/tree/CHAPTER9
個人開発でサービスを作りました

### [個人開発]Naiseiを作りました


リンク：　[Naisei](https://www.fr-next.com/)



##### こんなサービス🚀

日々の**感情、思考、行動**について深く考えるためのサービスです。

あなたが日々感じたこと、考えたこと、取り組んだこと何でも自由に書いてください。

AIがあなたの**感情を分析**します。

分析結果を見て新たな発見があるかもしれません。



##### そもそもNaiseiって何？🧘

Naiseiというのは漢字で「**内省**」、英語で「**Reflection**」と書きます。
自分自身や自分の感情、思考、行動について深く考えることを指す言葉です。Naiseiは、**自己理解を深めたり、個人の成長や発展を促進するために行われる思考や行動のプロセス**です。

この行為は、**過去の経験や選択に対する反省や分析**、または**将来の目標や価値観についての深い洞察を得るため**に行います。



#### なぜ作ったか・誰向けのものか(誰向けのものではないか)

現代社会、絶え間ないレコメンドに自分自身と向き合う時間が取れているでしょうか？
今、あなたがしていることは本当に自分の意思で決めているでしょうか？

人間は社会的な生き物ですから無意識にも目の前のコンテンツがあれば興味を示しそれを閲覧するのではないでしょうか?

ほとんどの場合、そのように社会的に生きていけば何も問題はないでしょう。今が「とても充実していて楽しい」と感じている方には不要なサービスです。



幸福感と自己決定における研究では自己決定指標が高いほど人生における幸福感は高いというデータがあります。
また、幸福度とセルフケア意識・行動についての研究ではセルフケアに対しての実施ルーティンが多いことや日々の記録をとっている人ほど幸福度が高い傾向にあるというデータもあります。


**つまり、自分で主体的に考え生きていくことは人生にとって前向きな影響を与えます。**
**多くの方に前向きな人生を送ってもらいたいと願い、その一歩になればと思いこのサービスを作りました。**



### 使った技術
フレームワーク
* [Next.js](https://nextjs.org/)(v13.5.2)


ORM
* [Prisma](https://www.prisma.io/)

データベース
* [supabase](https://supabase.com/)


認証機能
* [clerk](https://clerk.com/docs/components/authentication/sign-in?utm_source=www.google.com&utm_medium=referral&utm_campaign=none)

その他主要パッケージ
* [lxical](https://lexical.dev/)(テキストエディタ)
* [rechartjs](https://recharts.org/en-US/)(グラフ・チャート)
* [react-day-picker](https://reactdatepicker.com/)(カレンダー)
* [OpenAIAPI](https://platform.openai.com/docs/introduction)(感情分析)
* [stripe](https://stripe.com/jp)(決済)
SpringBootにおいて、@ValidatedでNGの時だけ処理が行われずにエラー画面が表示される

# 環境
| 名称 | バージョン |
|:-:|:-:|
| Spring Boot | 3.1.4 |

# 問題
以下のようなControllerメソッドを作った。
```Controller.java
@GetMapping(value = SEARCH_URL)
public String showSearchPage(@Validated @ModelAttribute SearchConditionsForm form, Model model, BindingResult bindingResult) {
	if (bindingResult.hasErrors()) {
		System.out.print("nyan");
	}
	return SEARCH_PAGE;
}
```

Viewから渡されたデータの入力チェックがNGの時、「Nyan」がコンソール出力されずにエラー画面が表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613109/6f4538d1-3ccd-fe45-b587-995d87710225.png)

# 解決方法
引数BindingResultは、＠Validatedを付けて入力チェックをする引数の次に定義しなければならない。
```Controller.java
// ×
// public String showSearchPage(@Validated @ModelAttribute SearchConditionsForm form, Model model, BindingResult bindingResult) {
public String showSearchPage(@Validated @ModelAttribute SearchConditionsForm form, BindingResult bindingResult, Model model) {
	if (bindingResult.hasErrors()) {
		System.out.print("nyan");
	}
	return SEARCH_PAGE;
}
```
「継続的デリバリーのソフトウェア工学」まとめ

## ソフトウェア開発における２つのパフォーマンス指標
### 安定性
行った作業の品質についての指標。
***「これによって自分たちが作るソフトウェアの品質は高くなるか」***
1. 変更失敗率（Change Failure Rate）
    変更によってプロセスの特定の地点でエラーが発生した割合
1. エラー修復時間（Recovery Failure Time）
    プロセスの特定の位置で起きたエラーから修復までにかかった時間

### スループット
動作するソフトウェアという形でチームがアイデアをユーザーに送り届ける能力についての指標。
***「これによって品質の高いソフトウェアを作る作業効率は上がるか」***
1. リードタイム（Lead Time）
    「アイデア」を「動作するソフトウェア」に変える一行の変更にどれだけ時間がかかっているか。開発プロセスの効率性の指標。
1. デプロイ頻度（Frequency）
    変更はどれくらいの頻度で本番環境にデプロイされているか。変更ペースの指標。

## ソフトウェア工学における2つの最重要スキル
### 学びのエキスパート
科学的な論理的思考スタイルを実践的に活用する。
具体的な行動様式は以下5つ。
1. 反復的な作業
1. 早くて高品質なフィードバック
1. 漸進的な仕事の進め方
1. 実験主義的であること
1. 経験主義的であること

### 複雑さ管理のエキスパート
システムの複雑さに圧倒されないように、問題を切り分けながら複雑さを管理する。
具体的な要素は以下5つ。
1. モジュラー性
1. 凝縮度（一体性）
1. 関心の分離
1. 情報隠蔽/抽象化
1. カップリング

## 反復的な作業
アジャイル開発における中心的な概念でもあるイテレーションについて。
ウォーターフォール的アプローチでは「十分に考えれば/仕事をすれば、最初から正しい結果が得られる」という前提からスタートする。この前提が成り立つことが滅多にないので、多くのウォーターフォール開発プロジェクトは苦戦を強いられることになる。
一方でアジャイル的アプローチでは「私たちは間違うことを避けられない」という前提からスタートする。そこで、失敗を許容可能な小サイズの仕事を実施してはフィードバックを受け、修正するというサイクルを繰り返す（学びのサイクル）。
この哲学はシステム開発に限らず、あらゆる仕事において役に立つものだと思う。
>科学者は無知と疑いと不確実性を嫌というほど経験している。この経験こそ、何よりも重要なものだと私は思う。　ー　リチャードファインマン

## フィードバック
「私たちは間違うことを避けられない」という前提に立つので、間違いを早く検知するためのフィードバックを重要視する。
「フィードバックを重要視する」とは、開発テクニックの話（例：開発環境にリファクタリングツールを導入する）にとどまらず、アーキテクチャにまで好影響を与える観点である。
高品質なフィードバックを早く得られる仕組みを整えることによって、"フェイルファスト（早い段階で失敗せよ）"な開発プロセスを実現できる。

## 漸進主義
「私たちは間違うことを避けられない」という前提に立つので、間違えた時の爆発半径を最小限にとどめるために、少数の大きくてリスキーなステップではなく、多数の小さなステップで前進することを常に追求する。
問題の一つの部分を解くことを目的として、問題を小さな部分に分割する。そのメリットとして、個々のコンポーネントは単純になり、与えられた課題の解決に専念できるようになる。さらに個々のコンポーネントはテストしやすく、短期間でデプロイできるようになる。
理解の深まりと共に、後からコードを書き換え考え方を改める自由を確保できるように仕事を進めることは、工学として優れた仕事の基礎である。
Conoha オブジェクトストレージ: 一覧の取得

参考ページ
[コンテナ情報取得 - ObjectStorage API v1](https://www.conoha.jp/docs/swift-show_container_details_and_list_objects.php)

こちらで取得した token を使います。
[Conoha オブジェクトストレージ: 認証トークンの取得](https://qiita.com/ekzemplaro/items/9e1db6906b163392a275)

## Object Storage Service のエンドポイントを調べる
ject Storage Service のエンドポイントを調べる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/07fb4bc4-8ba1-b7c3-4f4d-8e5c37970258.png)


## コンテナーの一覧

```bash
URL="https://object-storage.tyo2.conoha.io/v1/nc_487727e3921d44e3bfe7ebb337bf085e"
#
TOKEN="sample00d88246078f2bexample788f7"
#
http $URL "X-Auth-Token: "$TOKEN
```

## コンテナーのファイル一覧 テキストで取得

```bash
URL="https://object-storage.tyo2.conoha.io/v1/nc_487727e3921d44e3bfe7ebb337bf085e"
#
TOKEN="sample00d88246078f2bexample788f7"
#
http $URL"/container_aaa" "X-Auth-Token: "$TOKEN > list02.txt
```

## コンテナーの一覧　JSON で取得

```bash
URL="https://object-storage.tyo2.conoha.io/v1/nc_487727e3921d44e3bfe7ebb337bf085e"
#
TOKEN="sample00d88246078f2bexample788f7"
#
http $URL"/container_aaa" "Accept: application/json" "X-Auth-Token: "$TOKEN > list02.json
```
【Ruby】puts / print / p / pp の違い 【チェリー本を読んで】

## はじめに
今回の記事は過去に「プロを目指す人のためのRuby入門」を読んで、勉強になった・意識していなかった
部分を備忘録的にまとめています。

`puts` `print`　`p` `pp` のメソッドについてどれも出力に使用するものですが、
どれも挙動が少し違います

## それで、puts / print / p / pp の違いは何なの？
**結論**

| メソッド | 出力後の改行 | 配列の表示 | 呼び出すメソッド | 戻り値 | 対象者 |
|:-:|:-:|:-:|:-:|:-:|:-:|
| puts | あり | 要素ごとに改行 | to_s | nil | 一般ユーザ |
| print  | なし | 改行しない | to_s | nil | 一般ユーザ |
| p | あり | 改行しない | inspect | 引数のオブジェクト | 開発者 |
| pp | あり | 見やすく整形 | inspect | 引数のオブジェクト | 開発者|

挙動として、上記の図のようになります！
因みに `pp` の見やすく整形は配列だけではなく、ハッシュ等の大きく複雑なものも見やすく整形されます。

## まとめ
Rubyを触ったばかりの時は自分も、あまり意識せずに出力することが多々ありました。

使い分けとしては、`puts`は改行したい時に使用して、`print`は改行せずに出力する際に使用します。
また、`p`はオブジェクトの内容をそのまま出力する際に使用し、`pp`はより詳細な情報（インデントや改行）も含めて表示したい場合に使用します。

今回の記事が参考になれば幸いです。

## 参照
https://www.amazon.co.jp/o/ASIN/4297124378