OmniAICreator/Qiita-1.07M huggingface dataset:
pingのTTLとtracerouteによるOSの推定

pingの結果とパケットが経由したノード数を使うと宛先のホストのOSを推定できます。

パケットを返すときのTTLの値はOSごとに初期設定値が存在しています。

| OS | TTLの初期値 |
|:-|-:|
| Windows95,98 | 32 |
| macOS, Linux | 64 |
| Windows10 | 128 |
| Ciscoのルーター| 255 |

pingの結果のTTLの値は、パケットが経由したノードの数の分だけ減ったものです。
したがって、tracerouteでネットワーク経路上のノードを数えて、その分の数字を足せば、ホストが返すTTLの初期値が得られます。

**TTLの初期値 = pingのTTL + tracerouteの結果**

たとえば、「www.nap-camp.com」の場合、
```bash
% ping www.nap-camp.com                                       
PING www.nap-camp.com (104.26.0.222): 56 data bytes
64 bytes from 104.26.0.222: icmp_seq=0 ttl=57 time=16.373 ms
64 bytes from 104.26.0.222: icmp_seq=1 ttl=57 time=32.292 ms
```
pingのTTLは57です。

```bash
% sudo traceroute -I www.nap-camp.com 2>/dev/null
 1  **********  17.560 ms  11.259 ms  14.197 ms
 2  **********  13.711 ms  14.105 ms  23.191 ms
 3  **********  16.914 ms  12.282 ms  13.168 ms
 4  **********  14.846 ms  15.329 ms  12.712 ms
 5  **********  14.334 ms  14.588 ms  13.955 ms
 6  **********  13.709 ms  26.728 ms  15.511 ms
 7  **********  16.672 ms  14.195 ms  14.341 ms
 8  **********  17.095 ms  13.413 ms  11.246 ms
```
tracerouteの結果は8ですが、最初に表示されるノードが送信元のホストなので8-1=7が結果になります。

pingの結果とtracerouteの結果を式に当てはめると57+7=64となり、
結果は64なので「おそらくLinuxを使っているのではないか？」と推測できます。

:::note info
TTLの初期値は変更できるのであくまでおおよその分類です。
:::
Qiime2のdenoising作業でdada2に関するエラーが発生した際の対処法

# エラー発生
先日、今まで通りQiime2を使ってシーケンス後のデータを解析しようとしたところ、`qiime dada2 denoise-paired`関連コマンドを入力後以下のエラーが出てきました。

>Plugin error from dada2:
>An error was encountered while running DADA2 in R (return code 1), please >inspect stdout and stderr to learn more.
>See above for debug info.

この解決方法を探ろうとネットで検索しても明確な答えがなかったため、困っている人の参考になればと思い解決できた方法をまとめることにしました。

そもそもなぜこのようなエラーが出るようになったのかについては定かではありませんが、おそらくRまたはRStudioを更新したことが関係しているかもしれません。

# 解決方法
上記の赤字で出るエラーメッセージはほぼ参考にならず、なぜエラーになるのかについては上部に以下のように日本語で記載されていました。

>R version 4.2.1 (2022-06-23) 
 要求されたパッケージ Rcpp をロード中です 
 エラー: package or namespace load failed for ‘dada2’ in library.dynam(lib, package, package.lib):
  共有オブジェクト ‘reshape2.so’ を見付けることができません 
 実行が停止されました 

## 1.ターミナル上のRのアップデート
上記は最初のエラーメッセージでないため、Rのversionが違いますが、初めはR version 3.6.1(2019-)でした。Rに問題があると思い、ターミナル上のRのupdateをしました。
ターミナルで以下のコマンドを入力
```
R

install.packages('devtools') 　#すでにあれば不要

library(devtools)

install_github('andreacirilloac/updateR')

library(updateR)

updateR()　#パスワードを要求される
```
## 2.パッケージのインストール
上記の日本語のエラーメッセージのようにdada2を起動しようとしたけど共有オブジェクトが見つからないため先に進めないようです。
上記のエラーメッセージでは`'reshape2.so'`と記載されています。

これはターミナル上のRに`reshape2`というパッケージがインストールされていないため起こるエラーのようです。そのため、ターミナル上でRを起動したまま、パッケージをインストールしていきます。
```
install.packages("reshape2")
```

これで解決と思いきや次はまた別のパッケージが見つからないというエラーメッセージが出ます。dada2起動に必要な複数のパッケージがインストールされていないため、ターミナルを2ウィンドウ開いて、RとQiime2で同時進行させた方が早く済みます。毎回Rの起動とCRANサーバーの指定、シャットダウンをやらなくて済むからです。

パッケージの中には`install.packages(" ")`でインストールできないものもあります。
その場合はパッケージ名で検索してそのサイトからインストールしてください。

上記の方法で先に進むことができました。
【#35 エンジニア転職学習】HMAC

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

使用しているGoのUdemy教材後半部分である、
Webアプリ作成演習を学習していきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日もGoのWebapp作成講座を進めました。
以前飛ばしていたhmacとAPI認証コードを中心に進めました。

* **HMAC　<--Topics!**
* API認証

# HMAC
Haxh Based Message Authentication Codeの略。
公開鍵、秘密鍵、HASHを組み合わせることで、ハッカーが情報を解凍できないようにする暗号化技術の1つです。
##### メリット
* メッセージ等のデータ暗号化が可能
* 得られる情報の整合絵師チェック可能

##### 使用している教材はこちら↓


https://www.udemy.com/course/go-fintech/


# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
Tweepyの'API' object has no attribute 'me'

## はじめに
Tweepyのバージョンを4.10.0に上げたら怒られたメモ

## API.meの廃止

`AttributeError: 'API' object has no attribute 'me'`

実行したときにはAPI.meで例外が吐かれました。

[https://github.com/tweepy/tweepy/blob/master/docs/faq.rst#where-did-apime-go](https://github.com/tweepy/tweepy/blob/master/docs/faq.rst#where-did-apime-go)

faqにある通り3から4で廃止されたようです。代わりとして`API.verify_credentials`を使えばよいと書かれています。

```python
auth = tweepy.OAuth1UserHandler(
        CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET
)
api = tweepy.API(auth)
user = api.verify_credentials()
print(user.name, user.screen_name)
```
ノブ「わしゃM1 Mac（Apple Silicon）のDiscordでGoogle日本語入力が使いたいんじゃ〜」

どうも。
私はノブではないですが、ゆっくりしていってね。

## Google日本語入力はM1 Mac（Apple Silicon）に対応してない

M1 Mac（Apple Silicon）でGoogle日本語入力を使おうとすると、
一部のアプリケーションで急にMacOSデフォルトの日本語入力プログラムに変わってしまい、
Google日本語入力が使えなくなった（実際には切り替わってるだけ）という経験を持った人は多いかと思います。

私もそうでした。
DiscordもLINEも使えんのじゃ〜…

原因はGoogle日本語入力がまだM1 Mac（Apple Silicon）に対応していないためで、
現状だとRosseta経由で実行しており、先程挙げたような現象が起こるようです。

https://support.google.com/ime/japanese/answer/166752?hl=ja#zippy=%2Cmac

https://nishikiout.hatenablog.com/entry/2022/06/25/162406

## でも使えるようになった！

なので、仕方なくMacOSの日本語入力プログラムを使っていた最中…
ひょんなことからGoogle日本語入力の開発版を入れる機会があったのですが、
なんとこれでDiscordでもLINEでもGoogle日本語入力が使えるようになってました。

https://www.google.co.jp/ime/

_※開発版はページ下部のリンクからいけます_

## 快適なGoogle日本語入力ライフを（自己責任で）
M1 Macを買ったは良いものの、Google日本語入力使えなくなって悲しい思いをしていたのですが、
これで快適なGoogle日本語入力ライフを送ることができます。
ただし、開発版を使う場合は条件があるので、インストールは自己責任でしてくださいね。

（記載内容に間違いなどあったらご指摘お願いします）
#6　演算子,型変換

# 演算子
プログラム内での優先順位の順に紹介

### 1.インクリメント、デクリメント演算子
|演算子|意味|コード例|結果|
|:---:|:---:|---:|---:|
|++|1プラスする|i=1; i++;|i=2|
|--|1マイナスする|i=1; i--;|i=0|

### 2.算術演算子
|演算子|意味|コード例|結果|
|:---:|:---:|---:|---:|
|+|足し算|1+3|4
|-|引き算|10-4|6
|*|掛け算|5*3|15
|/|割り算|9/3|3
|%|割り算の余り|12%5|2

### 3.比較演算子
|演算子|意味|コード例|結果|
|:---:|:---:|---:|---:|
|==|左辺と右辺が等しい|①10/2 == 5 , ➁10/2 == 3|①true , ②false|
|!=|左辺と右辺が等しくない|➀2+4 != 6 , ➁2+4 != 5|➀false , ➁true|
|<|左辺は右辺未満|➀6 < 6 , ➁4 < 9|➀false , ➁true|
|>|左辺は右辺を超える|➀8 > 4 , ➁12 > 12|➀true , ➁false|
|<=|左辺は右辺以下|➀6 <= 6 , ➁6 <= 2|➀true , ➁false|
|>=|左辺は右辺以上|➀8 >= 14 , ➁12 >= 12|➀false , ➁true|

### 4.論理演算子
［条件式］__(論理演算子)__ ［条件式］という風につかう
条件式は "()"でかこむ
|演算子|意味|コード例|結果|
|:---:|:---:|---:|---:|
|&&|どちらの条件もtrueである| (3+5 == 8) && (2*10 == 20)|true
|\|\||どちらか片方のみtrueである|(12-8 >= 5) \|\| ( 3+6 !=4 )|true

|演算子|意味|コード例|結果|
|:---:|:---:|---:|---:|
|__!__ (条件式)|条件式の結果を反転させる|! (5+3 == 8)|false|

### 5.代入・複合演算子
|演算子|意味|コード例|結果|
|:---:|:---:|---:|---:|
|=|右辺を左辺に代入| i=4|iは4|
|+=|左辺の値+右辺の値|i=3; i += 4;| i=7|
|-=|左辺の値-右辺の値|i=6; i -= 4;|i=2|
|*=|左辺の値*右辺の値|i=8; i *= 4;|i=32|
|/=|左辺の値÷右辺の値|i=14; i /= 7;|i=2|
|%=|左辺の値÷右辺の値の余り|i=9; i %= 4;|i=1|
Firebase HostingにReactアプリをデプロイ

Firebase Hostingに[nextrollサイト](https://tech.nextroll.com/)の[クローン](https://ty-gcp1.web.app/)をdeployしたので手順のメモです。Reactです

Firebaseのインストール
```
npm install -g firebase-tools
```
Firebase Hostingの初期設定
```
cd mydir
firebase init hosting
```
```
Before we get started, keep in mind:

  * You are currently outside your home directory
  * You are initializing within an existing Firebase project directory

? Are you ready to proceed? Yes

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

i  Using project ty-gcp1 (ty-gcp1)

=== Hosting Setup

Your public directory is the folder (relative to your project directory) that
will contain Hosting assets to be uploaded with firebase deploy. If you
have a build process for your assets, use your build's output directory.

? What do you want to use as your public directory? build
? Configure as a single-page app (rewrite all urls to /index.html)? Yes
? Set up automatic builds and deploys with GitHub? No
? File public/index.html already exists. Overwrite? Yes

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

+  Firebase initialization complete!
```
ビルド
```
npm run build
```
デプロイ
```
firebase deploy
```
下記画像が出たらデプロイ成功
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2726391/1faf0384-64cc-ba8a-ddae-670ef51e0ba2.jpeg)

ページ再更新すれば自分のページが表示されます

# 参考
[Firebaseのつかいかた](https://qiita.com/kannkyo/items/c1afc8603f0b4565e661)
[今回作ったnextrollサイトのクローン](https://ty-gcp1.web.app/)
[ソース](https://github.com/gomagon/nextroll-clone)
.NET Blazor  Webアプリケーション構築① ~~いつものHello,world!~~


## はじめに
Blazor WebAssemblyは、C#言語を用いて、Webブラウザ上で実行可能なWebアプリケーションを構築するためのフレームワークです。このフレームワークを使えば、C#言語を使ってSPA（Single Page Application）を実現することができます。
この記事には、Blazor WebAssemblyフレームワークを使った商品のCRUD画面、ユーザ登録・ログイン画面を以下の要素に触れながら、実装していきたいと思います。
- Entity Framework のマイグレーション
- JWTのログイン認証
- .NET Blazorを使用したプライマリデータベースとしてのRedis
- .NET BlazorでCustom Validation Attributeの作成
- Pollyと.NET C#による障害処理
- 画像をbase64データに変換しDBに直接保存する方法
## セットアップ
Visual Studioを起動し、**Blazor Web Assemblyアプリ**を選択して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/7b895a84-1cc0-b6db-89ce-ab1225a11e3f.png)
プロジェクト名を入力し、次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/07c21552-5a01-78b9-9c82-27c1d8585567.png)
今回はJWTでの認証を実装する想定なので、認証情報はなしを選択。ホストサーバーにASPNETCOREを使用するので、チェックし、次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/9a000147-5dda-2a8e-d086-b11a5b8a84be.png)
Buildが完了ししたら、**デバッグなしで開始**を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/661f1c2b-9fd3-d8fd-4552-d14894d67360.png)
初期画面が表示されたらとりあえずOK
Client プロジェクトの LISTEN PORTは各々設定を確認して下さい。
C:\project\BlazorApp\BlazorApp\Client\Properties\launchSettings.json
https://localhost:7156
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738280/ed640b3c-df16-b99b-c68e-5f9e34539e03.png)


https://qiita.com/sharpman/items/dccc49501326ba4d5a20
buildspec.ymlでtaskdef.jsonにSecrets Manager値を引用させるように設定する

## ゴール

AWS CodePipeline で taskdef.json をアーティファクトとして CodeDeploy に渡す場合がある。
この taskdef.json を元にしてECSコンテナ用のタスクが作成されるわけだが、この時 AWS Secrets Manager で設定している機密データが参照されるよう、うまく下図のようにタスク定義内に環境変数として設定したい。

そうすると、APIのキーやDBのID/PWなど、そういった秘匿したい情報をコンテナ側のプログラムに引き渡すのに便利だ。

その設定をするコードスニペットをメモする。
（なお、本稿ではCodePipelineの設定などは割愛する。）

**（図）こんな感じに設定したい @ ECSタスク定義**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98745/abd0648f-db7e-b93b-b377-d19611bda2b3.png)


## Secrets Manager での設定について

任意のシークレットを作成して、キー（名前）と値の組み合わせを好きな個数保存しておく。
なお、このシークレットのARNは、後述されるが、後で使う。


## taskdef.json の準備

適宜構成情報を記述した taskdef.json を builspef.yml と同じディレクトリに用意しておく。[^sample4taskdef]

[^sample4taskdef]: AWSが公開している taskdef.json の[サンプル](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/example_task_definitions.html)


## builspef.yml 内での設定方法

やりたいことは taskdef.json 内の `containerDefinitions` の定義内に `secrets` という項目をまず生やす。そこへ `name` と `valueFrom` のペア値を配列で、必要な分だけ挿入する。そうすることでコンテナ作成時に Secrets Manager　から値が参照されて値がコンテナ内の環境変数として設定されるようになる。[^how2set]
なお、`name` がコンテナ内での環境変数名、 `valueFrom`が対象シークレットのキーのARNである。

この `containerDefinitions.secrets` への値の注入を buildspec.yml で定義する。
`jq` を活用する。
post_build フェーズあたりで設定するのが妥当かな。コードは次のとおり。

このコードによって、例えばシークレット内でキー名を `PIYOPIYO` として値を定義すると、コンテナの環境変数 `PIYOPIYO` が設定される。

[^how2set]: 設定方法の[AWSドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/specifying-sensitive-data-secrets.html#secrets-envvar)


```yaml:builspec.yaml（抜粋）
  post_build:
    commands:
      - （...中略...）

      # Injecting secrets value from Secrets Manager
      - SECRETS='[]'
      - |
        for KEY in $(aws secretsmanager get-secret-value --region ap-northeast-1 --secret-id $BUILD_SECRETMANGER_ARN | jq -r ".SecretString" | jq -r ". | keys | @sh")
        do
            KEY=$(echo $KEY | tr -d "'")
            VALUEFROM="${BUILD_SECRETMANGER_ARN}:${KEY}::"
            NEW_ITEM=$(printf '{"name":"%s", "valueFrom":"%s"}' $KEY $VALUEFROM)
            SECRETS=$(echo $SECRETS | jq ".+[$NEW_ITEM]")
        done
      - cat taskdef.json | jq ".containerDefinitions[0].secrets=$SECRETS" > ./taksdef.json.tmp
      - mv taksdef.json.tmp taksdef.json
```

**（注釈）**

- ここで用いられている`BUILD_SECRETMANGER_ARN`は、対象のシークレットのARNを保持するビルド時の環境変数。CodeBuildの環境変数としてセットしておくと良いだろう。
- また、CodeBuildの実行ロールに`AmazonSSMReadOnlyAccess`を設定しておくのを忘れずに。


## その他

今回のやり方と同様の方法で、パラメータストアで設定した値を用いることもできる。[^aboutssmps]

[^aboutssmps]: Secrets Manager の値の中に改行を用いることはできないが、パラメータストアでは可能である。秘密鍵など改行がある値を用いる時など、うまく使い分けることになるだろう。


パラメータストアを用いる場合も Secrets Manager と同様のことをすれば良いが、この場合は `valueFrom` の値はARNではなくパラメータ自体の名前でも大丈夫だ。[^aboutssm]

[^aboutssm]: パラメータストアの場合はARNでも名前でも、[どちらを指定しても良い](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/specifying-sensitive-data-parameters.html#secrets-envvar-parameters)。


```yaml:builspec.yaml（抜粋その２：代入サンプル）
      - NEW_ITEM=$(printf '{"name":"%s", "valueFrom":"%s"}' "${注入したい環境変数名}" "${パラメータの名前}")
      - SECRETS=$(echo $SECRETS | jq ".+[$NEW_ITEM]")
```

（以上）
【ドライブの修正】fsck -fy が実行できない

# 環境

- macOS Monterey 12.4
- intel T2セキュリティチップあり Macbook Air 13inch

# 不具合

以下の不具合に悩まされていました。
- Spotlightでフォルダが検索できない。
- mds_store（Spotlighrのインデックスを作成するプロセス）が頻繁に暴走する。
- Finderのタグが一覧表示されない。

# ディスクのファイルシステムが破損していた

ディスクユーティティで各ディスクを下にある階層から一つずつFirstAidしていくことでディスクの検証&修正を行ってくれます。

すると、内蔵ディスク「Macintosh HD - Data」というボリュームでエラーが出ました。

![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2499119/4dd37e4e-9d21-811f-4e22-edd541738ca9.png)


```ruby
ファイルシステム検査の終了コードは8です。
ファイルシステムを検証または修正できませんでした。
操作が失敗しました。
```

ファイルシステムが破損していてるようです。
こうなるとシングルユーザーモードでFirstAidする必要があります。

# シングルユーザーモードであれこれ試してみる

:::note warn
注意！
最低限、データのバックアップを取ってから実行してください。
:::


### シングルユーザーモードで起動する方法
T2セキュリティチップの有無、intel、M1でやり方が異なります。詳しくは以下の記事を参考にしてください。
[macOSでシングルユーザーモードまたは詳細モードで起動する方法](https://helpgeeks.net/ja/macos%E3%81%A7%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%83%A2%E3%83%BC%E3%83%89%E3%81%BE%E3%81%9F%E3%81%AF%E8%A9%B3%E7%B4%B0%E3%83%A2%E3%83%BC%E3%83%89%E3%81%A7)

### FirstAidしてfsck -fyを実行するも...
シングルユーザーモードで起動（自分の環境だと⌘+Rを押しながら電源ON）して、ディスクユーティティを開いてFirstAidしてみるもまたもや修正できず。

シングルユーザーモードでターミナルを開いて`fsck`コマンドを実行するも、直らない。。（ターミナルの開き方は、ディスクユーティリティを終了して、メニューバーの「ユーティリティ」>「ターミナル」を選択）

```ruby
$ fsck -fy
warning: option -f is not implementing

```

大抵はこれで治るみたいですが、Montereyではできないのかも？

これで治らない場合はOSの再インストールをしなければいけません。データも初期化されてしまいます。そんなの嫌だ。

# 解決

いろいろ試してみたところ、シングルユーザーモードで以下のコマンドを実行することで直りました！APFSデータボリュームだったので`fsck_aptfs`を実行するべきだったようです。

```ruby
$ diskutil list # これで問題のあるディスクを見つける

$ diskutil unmountDisk force [対象ディスク] # ディスクをアンマウントする
$ fsck_aptfs -y [対象ディスク] # ディスクを検証&修正する
```

このような画面が表示されれば成功です。
![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2499119/ad1daa81-e70f-1cb6-d1d2-c9fb2fbdff9f.png)

# おわりに
上述の不具合はすべて解消されました。
再起動した後、Spotlightのメタデータを再構築しました（ものすごく時間かかります）。
```
# Spotlightインデックスの再構築
$ sudo mdutil -a -E 
```

ネット上に情報が少なかったので誰かのお役に立てば幸いです。
繰り返しになりますが、データのバックアップはお忘れなく！
初心者がリファクタリングに挑戦してみる#1-1

# 初めに
とりあえず入門書を一周終わらせたので、知識をものにするためにリファクタリングに挑戦することにしました。続くかはわかりませんが、第一弾です。
## 最初のコード
```java:test.java
import java.io.*;

class test
{
	public static void main(String[] args) throws IOException
	{
		
			BufferedReader br = new BufferedReader(new FileReader("test1.txt"));
			String [] story = new String [10];
			String str;

			for(int i=0; i<story.length; i++)
			{
				str = br.readLine();
				story[i] = str;
			}

			//ファイルは読み込んで、中の文字列を配列に格納した

			for(int i=0; i<6; i++)
			{
				System.out.println(story[i]);
			}

			BufferedReader ibr = new BufferedReader(new InputStreamReader(System.in));
			String str2 = ibr.readLine();
			int option = Integer.parseInt(str2);

			if(option == 1)
			{
				for(int i=6; i<8; i++)
				{
					System.out.println(story[i]);
				}
				System.out.println("おしまい");
			}
			else if(option == 2)
			{
				for(int i= 8; i<10; i++)
				{
					System.out.println(story[i]);
				}
				System.out.println("おしまい");
			}
			else
			{
				System.out.println("無効な選択肢です");
			}	
	}
}
```
これがtest.javaというファイルに書いたコードです。別ファイルの内容を読み込み、表示して、入力する選択肢に応じて続きの内容が異なる、というものです。

別ファイルであるtest1.txtの中身は以下の通りです。
*********
あなたは今急いで職場に向かっています。
しかしどうやら道に人が倒れているようです。
あなたはどうしますか？
選択肢１：助ける
選択肢２：助けない
選択肢の数字を入力してください
倒れていた人は職場のお偉いさんでした。
とても感謝され、昇進も決まりました。
あなたは倒れている人を見捨てて職場へ到着しました。
しかし、その人がどうなったかが気がかりで、いつもはしないミスを連発してしまい、怒られてしまいました。
**********************

またこれらのコードの実行結果を以下に示します。
+ 選択肢１を選んだ場合
あなたは今急いで職場に向かっています。
しかしどうやら道に人が倒れているようです。
あなたはどうしますか？
選択肢１：助ける
選択肢２：助けない
選択肢の数字を入力してください
1（これが入力した数字）
倒れていた人は職場のお偉いさんでした。
とても感謝され、昇進も決まりました。
おしまい

+ 選択肢２を選んだ場合
あなたは今急いで職場に向かっています。
しかしどうやら道に人が倒れているようです。
あなたはどうしますか？
選択肢１：助ける
選択肢２：助けない
選択肢の数字を入力してください
2（これが入力した数字）
あなたは倒れている人を見捨てて職場へ到着しました。
しかし、その人がどうなったかが気がかりで、いつもはしないミスを連発してしまい、怒られてしまいました。
おしまい

こんな感じです。
コード自体が簡単で短いので、リファクタリングしてもどうなるかはわかりませんが、とりあえずやってみます。
【備忘録】Pixhawkのサーボ出力から負荷を駆動する方法

ラジコンの受信機やCube Pilot(Pixhawkも含めます)が出力するPWM信号から電動系の負荷を駆動したい場合の考え方についてまとめます。

## サーボ出力を用いて負荷を動かすには？
Cube Pilotのサーボ出力はモータを駆動する為、PWMが出力される仕組みとなっています。
動かしたい負荷がDCなので、そのままでは負荷は動かすことは出来ません。  
DC負荷を動かす為、以下の様な対応を行ないます。

## 対応
1．自動走行用の出力以外の出力端子をGPIOに割り当てる
2．GPIO出力信号でリレーを動かす

### 1．出力端子をGPIOに割り当てる
リレーを出力する為には以下の設定を行ってください。

・リレーピン出力を有効にする
・リレー出力端子を割り当てる（最大6個まで）
・出力端子をGPIOに設定する

パラメータの設定
|パラメータ|設定値|備考|
|-|-|-|
|RELAY_DEFAULT|1|1に設定することでRELAY PIN 機能が有効となる<br>（設定後Autopilot再起動）|
|RELAY_PIN|以下参照||
|RELAY_PIN2|以下参照||
|RELAY_PIN3|以下参照||
|RELAY_PIN4|以下参照||
|RELAY_PIN5|以下参照||
|RELAY_PIN6|以下参照||
|SERVOxx_FUNCTION|-1|-1に設定することでGPIOが有効となる|

:::note
SERVOxx_FUNCTIONのxxの部分を出力したい端子に割り当てます 
:::

端子割り当て
|端子|割り当て|値|
|-|-|-|
|AUXOUT1|SERVO9|50|
|AUXOUT2|SERVO10|51|
|AUXOUT3|SERVO11|52|
|AUXOUT4|SERVO11|53|
|AUXOUT5|SERVO13|54|
|AUXOUT6|SERVO14|55|
|MainOut1|SERVO1|101|
|MainOut2|SERVO2|102|
|MainOut3|SERVO3|103|
|MainOut4|SERVO4|104|
|MainOut5|SERVO5|105|
|MainOut6|SERVO6|106|
|MainOut7|SERVO7|107|
|MainOut8|SERVO8|108|

:::note
MainOutの端子は走行用に使用していない端子を使用してください
:::

### 2．駆動回路を介してリレーを駆動させる 

<B>イメージ（12Vの負荷を動かす場合を想定）</B>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/d47f3440-7338-cd28-f5b4-8aa50f851014.png)

>補足
>3.3V出力でリレーのコイル電流が20mA程度のものであれば  
>2SC1815でリレーのドライブ回路が作成できます

## 参考
ArdupilotのリレーSWの項目に記載されています

https://ardupilot.org/rover/docs/common-relay.html?highlight=relay
MQTTブローカーmosquittoをDockerで利用する


# はじめに
MQTTのパフォーマンス検証をするのに色々苦労したので、MQTTブローカー（mosquitto）の設定ファイルなどを備忘録として残します。



## ディレクトリ構造

`docker-compose.yml`、`mosquitto.conf` 2つのファイルを下記のディレクトリ構造のように配置する

```
.
├── docker-compose.yml
├── mosquitto
    └── config
        └── mosquitto.conf
```

## ファイル

```docker-compose.yml
version: "3"
services:
  mqtt:
      image: eclipse-mosquitto
      container_name: mqtt
      expose:
        - 1883
      ports:
        - 1883:1883
      restart: unless-stopped
      volumes:
        - ./mosquitto/config:/mosquitto/config
```


```mosquitto.conf
set_tcp_nodelay true
listener 1883
allow_anonymous true
max_queued_messages 0
```

[補足]
- listener: ブローカーのポート番号？（これを設定しないと、ブローカーに接続できない）
- allow_anonymous: 認証なしでブローカーに接続する設定
- max_queued_messages: QOS=1,2にするとメッセージが欠損する問題の対応

## コマンド

```
docker-compose up
```

## 参考リンク
- https://thilake.medium.com/get-into-mqtt-in-2-minutes-python-docker-5d4e8b55cf1c
- https://hub.docker.com/_/eclipse-mosquitto
- 
## 終わりに
いろいろ調べて、MQTTのについて詳しくなった気がする（）
chrome 拡張 manifest v3 でアイコンクリック時に任意の html を開く

# 実現したいこと
- 開発した chrome 拡張のアイコンをクリックしたときに、指定した html ファイルを開く。
- 有名な拡張でいうと、[Talend API Tester](https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm?hl=ja) のような動きを実現したい。

![snap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/0d9b7b5a-cc38-c0e6-fb1c-7137da1b40e1.gif)


# なぜ書いたか？
- [v1 や v2 での解説記事](https://qiita.com/Silphire/items/949b22cba0610ec9f40b)はちらほらあるが、v3 はあまり見かけなかった。
- ハマりポイントがいくつかあったので備忘として書いておきたかった。

# 実装
### ディレクトリ構成
```
project
├ manifest.json
├ index.html
└ icon_clicked.js
```

### ソースコード
```manimfest.json
{
    "name": "my extension",
    "description": "my extension",
    "version": "1.0",
    "manifest_version": 3,
    "background": {
        "service_worker": "icon_clicked.js"
    },
    "action": {},
    "permissions": ["storage", "tabs"]
}
```
```icon_clicked.js
chrome.action.onClicked.addListener((tab) => {
  chrome.tabs.create({"url": "index.html" });
});
```
index.html は任意のものでOKです。

# ハマりポイント
### background では scripts ではなく service_worker を使う
```js:manifest.json
{
    ...
    "background": {
        "service_worker": "icon_clicked.js"
    },
    ...
}
```

v2 → v3 での変更点で、イベント系の処理を書いた js はこのように参照します。

https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/#manifest

### "action": {} を書いておく
```js:manifest.json
{
    ...
    "action": {},
    ...
}
```

これを書かないと、拡張を読み込むときに、下記のようなエラーになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474068/d9303958-0229-a74d-d3e6-9dba24da44b7.png)

```
Uncaught TypeError: Cannot read properties of undefined (reading 'onClicked')
```

### chrome.browserAction ではなく chrome.action を使う
```icon_clicked.js
chrome.action.onClicked.addListener((tab) => {
  chrome.tabs.create({"url": "index.html" });
});
```

古いサンプルでは、v2 の書き方である、`chrome.browserAction` が使われていることが多いです。 `chrome.action` が正しいです。


# 完了！
期待通り動きました！
これで chrome 拡張で SPA ウェブアプリライクなアプリを作れます！
ターミナルのインタープリターを使って文字列+連番を出したい！

# はじめに
仕事してて
```
hoge430,hoge431,hoge432,hoge433,hoge434,hoge435,hoge436,hoge437,hoge438,
```
みたいな文字列+連番みたいなのをぴゃぴゃっと出したいなーって思ったんですよ。使う用事があったんで。
で、こういうのってターミナルの各言語のインタープリターを使うとやれるんですけど、どうやったっけなー、と思いまして。
備忘録的な感じで。

# Ruby

まずはRubyです。Rubyがこういうの一番簡単に行けたイメージあったので。

```bash
$ ruby -e '(430..438).each{|i|print "hoge#{i.to_s},"}'
```

簡潔でいいですね。

ちなみにfor文使うとこうです。結局コレでも内部的には`each`が動いているんだそうです。

```bash
$ ruby -e 'for i in 430..438 do print "hoge#{i.to_s}," end'
```

@scivola さんからコメントで頂いたのですがこんな書き方もあるとのことです。`upto`初めて知った……
`_1`と書いてあるのは`Numbered Paramater`というもので、これはruby2.7以降でないと動かないです。

```bash
$ ruby -e '(430..438).each{ print "hoge#{_1}," }'  

$ ruby -e '430.upto(438){ print "hoge#{_1}," }'
```

@ttdoda さんから頂いたものをもとにこんな感じのものを。配列にしてガッチャンコ……！

```bash
ruby -e 'print (430..438).to_a.map{|i|"hoge#{i}"}.join(","), ","'
```

# Python

pythonはワンライナーだと一筋縄では行かないですね。rangeで指定するendは終わって欲しい数字の1つ後を指定します。

```bash
$ python3 -c 'for i in range(430,439):print(f"hoge{str(i)},")'
```

これだと結果がこうですね。

```
hoge430,
hoge431,
hoge432,
hoge433,
hoge434,
hoge435,
hoge436,
hoge437,
hoge438,
```

配列ガッチャンコパターンはこんな感じ。出力も想定通りでいい感じです。

```bash
$ python3 -c 'print(",".join(map(lambda i: f"hoge{i}", range(430,439))))'

hoge430,hoge431,hoge432,hoge433,hoge434,hoge435,hoge436,hoge437,hoge438
```

# PHP

我らがPHPはこんな感じですね。PHPでワンライナーやるのはやや心がもにょりますね。

```bash
$ php -r 'foreach(range(430,438) as $i){echo "hoge{$i},";}'
```

一瞬引っかかるのも微妙な気分を助長させますね。

配列にしてガッチャンコパターンだとこんな感じですかね。長い……

```bash
$ php -r 'echo implode("," ,array_map(fn($i) => "hoge{$i}", range(430,438)));'
```

# Node.js(JavaScript)

JSはrange的なものがないのでちょっと面倒です。無理くりrangeっぽいものをやろうとすると逆に長いのでfor文にしました。

```bash
node -e 'for(let i=430;i<439;i++)console.log(`hoge${i},`)'
```

出力はpythonのときと同じになります。

配列ガッチャンコパターンだとこんな感じ。range相当部分が不毛すぎる。。。ただ出力はいい感じですね。

```bash
node -p '((s, e) => [...Array((e - s) + 1).keys()].map((_, i) => s + i))(430, 438).map(j => `hoge${j}`).join(",")'

hoge430,hoge431,hoge432,hoge433,hoge434,hoge435,hoge436,hoge437,hoge438
```

# SHELL芸

そもそもインタープリター通さずともシェル芸人さんはシェルだけで行けるわけで

```
$ for i in {430..438}; do echo hoge$i,; done
```

fishでは動きません。bashとzshで動くことは確認しました。一番簡単で簡潔な気がする……

ちなみにこちらが昔書いたシェルの記事です。

https://qiita.com/layzy_glp/items/f2ca86c921d097346222

下のコメントで @ttdoda さんにもっとイカすやり方を教えてもらいました✨

```bash
$ echo hoge{430..438},|tr -d ' '
```

何だこれ、最強か？　さすがTera Termの中のお人やで……(ﾟＡﾟ;)ｺﾞｸﾘ

# おわりに

いかがでしたでしょうか。
多分こういう~~ワンライナー系だとrubyが一番手軽だと思うので、ruby学ぶのはいいことかもしれません。~~
やっぱSHELL芸最強〜〜〜！！
Rでigraphをインストールするときにエラー：libgfortran.so.4: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはあり ません

**この記事はメモ用です。**
**この記事が原因で問題がおきても責任は負いません。**

Rでigraphをインストールしようとしたら以下のようなエラーが出力されました：
```R
libgfortran.so.4: 共有オブジェクトファイルを開けません: そのようなファイルやディレクトリはあり ません
```
コンソールで以下を実行しインストールしなおしたら解決しました：
```console
sudo apt-get install -y libgfortran4
```

環境：
Ubuntu 20.04.4 LTS
R 4.2.0
【備忘録】Moving Baseline（GNSSを使った方位推定）の設定

CubePilotに内蔵された磁気コンパスは磁気干渉の影響により正確な方位を出しにくいという問題があります。
Ardupilotでは2つのUBloxF9P GNSSモジュールを使用して走行中の方位を推定するGPS for YAWという方法があり、この方法を用いることで磁気干渉に悩まされる可能性のあるコンパスが不要になります。
この方法はGPSにRTK修正がない場合でも機能します。

## 手順
1. ハードウェアの設定
2. パラメータの設定
3. コンパスの無効化
4. 動作確認

## 1.ハードウェアの設定
・2つのアンテナを水平方向に30cm離して配置する
・2つ目のGNSSモジュールをSerial4（GPS2）のポートに接続する
・2つのアンテナのロケーションを記録する（車体の中心からの距離）

## 2.パラメータの設定
Ardupilot Rover 4.2 における設定を記載します。
|パラメータ|値|備考|
|-|-|-|
|GPS_POS1_X|メモした値を記入|アンテナ1が車体の前後方向に対しどの位置にあるか指示します|
|GPS_POS1_Y|↑|アンテナ1が車体の左右方向に対しどの位置にあるか指示します|
|GPS_POS1_Z|↑|アンテナ1が車体の上下方向に対しどの位置にあるか指示します|
|GPS_POS2_X|↑|アンテナ2が車体の前後方向に対しどの位置にあるか指示します|
|GPS_POS2_Y|↑|アンテナ2が車体の左右方向に対しどの位置にあるか指示します|
|GPS_POS2_Z|↑|アンテナ2が車体の上下方向に対しどの位置にあるか指示します|
|GPS_AUTO_SWITCH|1||
|AHRS_EKF_TYPE|3|EKF3を使用する場合|
|EK2_ENABLE|0|EKF2を無効にする|
|EK3_ENABLE|1|EKF3を有効にする|
|EK3_SRC1_YAW|2|GPSに設定する|

※ 座標系については[こちら](https://qiita.com/Fumi_Saito/items/7a4c3e713bcf0fe56279)を参考にして下さい

## 3.コンパスの無効化
コンパスのチェックをすべて外す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1064722/d1afe73f-a7c2-8bcd-ab66-92dd5906ebf2.png)

## 4.動作確認
GNSSの受信状態が良好な場所に移動し以下が確認できればOKです。

・機体を目印となる方向に向けた時に目印と地上局に表示される方向が一致しているか？
・車両を回転させた時に方位が正しく更新されるか？

## 参考
https://ardupilot.org/rover/docs/common-gps-for-yaw.html#common-gps-for-yaw
日付データから年、月、日を抽出

# やること
- datetimeのインポート
- to_datetimeで文字列型を日付型に変換
- .dtで抽出

# コード
```python:title
import datetime

train_df["match_date"] = pd.to_datetime(train_df["match_date"])
train_df["year"] = train_df["match_date"].dt.year
train_df["month"] = train_df["match_date"].dt.month
train_df["day"] = train_df["match_date"].dt.day
```

# 参考にしたサイト
- [pythonの日付列の前処理を完全攻略する](https://qiita.com/Takemura-T/items/79b16313e45576bb6492)
- [【Python】日付型データから年・月・日を取り出す方法｜datetime](https://smart-hint.com/python/datetime-ymd/)
Vue3環境構築手順（簡易版）

# Vue3 install
https://v3.ja.vuejs.org/guide/installation.html#%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%8E%E3%83%BC%E3%83%88

# yarn install
https://qiita.com/suisui654/items/1b89446e03991c7c2c3d

# Sass install
https://cli.vuejs.org/guide/css.html

# Vue + Vite の場合のVuetify　install
https://qiita.com/kyonc5/items/bd7b9d887c81f1b6a598
ローカルCSVを読み込みDto作成

```
package design.controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TestYou {

	private void readLocalCsv() {
		try {
			// Fileル名称
			String fileName = "c:/csv/TestYou.csv";
			File file = new File(fileName);
			// File読み込み
			BufferedReader br = new BufferedReader(new FileReader(file));
			// Fileヘッダ
			boolean isHeader = true;
			//File行
			String line = null;
			// File行数
			Long lineCnt = 0L;
			// 1行ずつファイルを読み込み
			while((line = br.readLine()) != null) {
				// headerの場合読み飛ばし
				if(isHeader) {
					isHeader = false;
					continue;
				}
				lineCnt ++;
				// aa読み込んだ行をカンマで分割し配列に保持
				String[] readColumns = line.split(",",-1);
				System.out.println(readColumns.length);
				System.out.println(readColumns[0]);
			}
		} catch (FileNotFoundException e) {
			System.out.println("File Not Found");
		} catch (IOException e) {
			System.out.println("IOException");
		}
	}

}

```
CVPR 2022 と NIST と arXiv ～顔認証について～

CVPR 2022が気になったので、調べてみた。

>[CVPR 2022](https://cvpr2022.thecvf.com/)

論文の数は、8,161本。
中国：44.59%
米国：20.65%
日本： 1.50%
とのことです。

うーん。そんなものなのか。
日本からの論文って意外に少ないなと感じた。

でもって、NISTで、「Face Recognition Vendor Test (FRVT) Ongoing」の「FRVT 1:1」に行ってみる。

>[Face Recognition Vendor Test (FRVT) Ongoing](https://www.nist.gov/programs-projects/face-recognition-vendor-test-frvt-ongoing)

「Learn More」をクリックすると、サーチできるので、「N●●」とか「P●●●」とか入れてみると結果が出力される。「N●●」は顔認証で強いと聞いていたが、世界ランキングからするとそうでもない。

ちなみに、トップのほうのセンスタイムという企業を調べてみたらCVPR 2022において論文71本が採択されたとのこと。

>[センスタイムジャパン](https://www.sensetime.jp/)

arXivに行って、「Face Recognition」を検索してみた。

>[arXiv](https://arxiv.org/)

中国の論文が数多くヒットしますねぇ。

**日本の研究環境は、悪化しているのかなぁ。**
AWS　リソースの解放

今日、社内でAWSの環境構築の研修がありました。
VPCの設定、サブネットの設定、セキュリティグループの設定、EC2の設定、RDSの設定を行い、
最後にはリソースの解放まで行いました。
初めて環境構築を行い、リソースの解放のところで気づきがあったので、以下に記します。

# AWS　リソースの解放
VPCを削除すればその中のネットワークに属するEC2とRDS、他設定もろとも全て消えるのでは？
と思っていたのですが、そういうわけではないようです。
VPCは箱ではなく、紐のイメージで、EC2とRDSはそれぞれ個別に削除する必要がありました。

EC2は停止した状態で削除ができたのですが、RDSは起動した状態でないと削除ができず少し手間取りました。
なぜかはわかりません。
最後にVPCを削除したときに、一緒にサブネットの設定やセキュリティグループの設定が消えました。

会社での研修内容を振り返ってみました。
せっかく構築作業を行ったので、自宅でも試してみようかなと思います。
何かご指摘などありましたらコメントをお願いいたします。
専門学校生が応用情報技術者試験に合格した話

## はじめに
私は2022年4月に実施された春期情報処理技術者試験で、応用情報技術者に合格しました！！

内訳としては、**午前が73.75点 ・ 午後が69点** でした！

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918370/dcda7e89-ad7a-4876-aa74-e7a61a8c69e7.png)

今後、応用情報技術者を受ける方へ私の体験が参考になればいいかと思い、この合格体験記を書こうと思います。

## この記事の対象者
- 応用情報が気になっている方
- 基本情報に合格して次に取得する資格を探している方
- ITに興味がある学生の方

## 応用情報技術者とは？？
まず、応用情報技術者について説明したいと思います。
| | 問題数|時間|形式|合格ライン|
|---|---|---|---|---|
|午前|80問|150分|四肢択一|60%|
|午後|11問中 5問選択|150分|記述式|60%|

受験手数料：7,500円

> 1. 対象者像
    高度IT人材となるために必要な応用的知識・技能を持ち、高度IT人材としての方向性を確立したもの
> 2. 業務と役割
基本戦略立案又はITソリューション・製品・サービスを実現する業務に従事し、独力で次のいずれかの役割を果たす。
    (1). 需要者（企業経営、社会システム）が直面する課題に対して、情報技術を活用した戦略を立案する。
    (2). システム設計・開発を行い、又は汎用製品の最適組み合わせのよって、信頼性・生産性の高いシステムを構築する。また、その安定的なサービスを実現する。
[IPAサイトから引用](https://www.jitec.ipa.go.jp/1_11seido/ap.html)

#### 基本情報技術者との主な違い
基本情報技術者と主な違いは以下になります。
- CBTではなく、PBT形式
- 午後問題が記述式になる
- 1日の間に、午前問題と午後問題を行う


基本情報は、PC上で問題に解答していく形式でしたが、
応用情報になると、午前はマークシート形式、午後は記述式になります。

その他にも、基本情報では、午前問題・午後問題を別日に受験可能でしたが、応用情報では、1日の間に、午前問題と午後問題の2つの試験を受験することになります。


## 受験のきっかけ
受験しようと思ったきっかけは、以下の二つです。
- 基本情報技術者試験に合格したので、さらなるステップアップをしたい

- 基本情報の知識が残っているうちに応用情報の勉強を始めたい
という思いがあったので受験をすることにしました。

## 対策
### 勉強期間
応用情報以外にも並行して他の資格勉強をしていたので正確な値は確かではありませんが、勉強期間は、約3,4か月くらいでした。

### 午前問題対策
最初の **1.5か月程度** は午前勉強のみを行いました。
使用した教材はこちらです↓
- [応用情報技術者試験過去問道場](https://www.ap-siken.com/apkakomon.php)

言わずと知れた過去問道場ですね。
1問1問に詳細な解説が載っているので理解がはかどりました。
午前問題の対策についてはこれ以外使用していません。
**午前問題は直近2回を除いた過去10回分から約半分の問題が再利用されます。**
ですので、**80問中、40問程度が過去問** ということになります。
上記で紹介した過去問道場でも過去問出題率の統計を出しているのででよければご覧ください。
[統計情報](https://www.ap-siken.com/aptoukei.html)

### 午後問題対策

午後問題は、全11問から5問を選択して回答する形式になります。
|問題|分野|配点|
|---|---|---|
|問1|情報セキュリティ(必須)|20|
|問2|経営戦略|20|
|問3|プログラミング|20|
|問4|システムアーキテクチャ|20|
|問5|ネットワーク|20|
|問6|データベース|20|
|問7|組込みシステム開発|20|
|問8|情報システム開発|20|
|問9|プロジェクトマネジメント|20|
|問10|サービスマネジメント|20|
|問11|システム監査|20|

残りの2.5か月くらいは午後問題の対策に充てました。
使用した教材はこちらです↓
- [応用情報技術者試験過去問道場](https://www.ap-siken.com/apkakomon.php)
- [2022 応用情報技術者 午後問題の重点対策 (重点対策シリーズ)](https://www.amazon.co.jp/dp/486575251X/)
- [情報処理教科書 出るとこだけ！応用情報技術者［午後］](https://www.amazon.co.jp/dp/4798156507/)

過去問道場は午後問題にも対応していたのでとても重宝しました。
そのほか2冊についてですが、[2022 応用情報技術者 午後問題の重点対策 (重点対策シリーズ)](https://www.amazon.co.jp/dp/486575251X/)では、実際の過去問と詳しい解説が載っています。回答の記述の根拠はどこにあるかを示してくれたりしてくれていたので午後問題の解答能力はこの本を読んでかなり上がったと思います。

[情報処理教科書 出るとこだけ！応用情報技術者［午後］](https://www.amazon.co.jp/dp/4798156507/)では午後問題の効率的な解き方を紹介してくれています。例えば、「このような記述があったらこう書く！」みたいな感じで、問題文を読み込まなくても解けるようなテクニックを載せてくれています。午後問題は時間がかかるので身に着けてしまえばかなりの時短になります。実際に、データベースなどER図を見るだけで解けるよう問題が増えたのでとても時短に繋がったと思います。

ちなみにですが、私が選択した科目も載せておこうと思います。
- 情報セキュリティ
- データベース
- プロジェクトマネジメント
- サービスマネジメント
- システム監査



## まとめ
応用情報に合格したことで、自分の知識の幅も広がったと思いますし、自信にもつながってとてもいい体験にになりました。

今度は高度試験に向かって勉強を頑張っていきたいと思います！！
expressの古い資料を参考にする時の注意点

# はじめに
　node.jsのexpressの色々なプログラムを見比べている時、

```javascript
app.use(express.cookieParser());

app.use(cookieParser());
```

　と明らかに同じ目的を持ったメソッドを見かけました。
　さて、いったいどっちの方がいいのでしょうか。それともただのエイリアスなのか。
　気になったため調べてみると知らなかった上に割と知らないとめんどくさい情報だったため記事にしておきます。

　参考

https://expressjs.com/ja/guide/migrating-4.html

## 変更点
　express3からexpress4へのアップデートにあたって、**互換性のない**変更がなされたようです。
　以下はサイトに書かれた表の変更の一覧です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2647158/fd51f7c4-6f11-daca-43c8-03b07bf384b5.png)


　というようになっています。
　各モジュールの使用方法はサイトから参照しに行けます。
　またnpmによるモジュールのインストールが必要となっていますが、それは表の文字を入力するだけで可能です。

# 最後に
　つまり最初のcookieParserでいえばexpress.cookieParserは互換性がなく使えないということになりますね。
　こう、記事に書いてみれば伝えたいことは互換性がないという一言で終わってしまって困惑していますが、まぁこういうことがあってもいいでしょう。
基本情報（OSの仕事2）

https://qiita.com/jupippii/items/8de47bfce46d0638dd28

前回の続きです。

## OSによる操作性の向上
コンピュータを使うには、そのためのインタフェースが必要です。
OSでは **GUI(Graphical User Interface)** という、「画面にアイコンやボタンを表示して、それを視覚的に操作することで命令を伝える操作方式」を採用しています。

マウスや指などでぽちぽち操作できる画面ですね。
昔のパソコンはマウスがついておらず、キーボードのみで操作していたようです。

キーボードでしか操作できない画面は **CUI(キャラクタユーザインターフェイス)** と言います。

## API
この言葉抜きで仕事できないくらい絶対に聞くと思います。
API(Application Program Interface)の略です。
ソフトウェアからOSの機能を利用するための各種機能をアプリケーションから呼び出せる仕組みを用意しており、このために設けられたインターフェースのことです。

WEB業界でよく聞くAPIとは大概、WEB APIのことを指していると思います。
基本情報と少しそれますがWEB APIもまとめてみます。

## WEBAPI
ものすごくざっくりと書くと「WEB上で利用するAPI」です。
HTTP/HTTPSベースのAPIで異なるプログラミング言語（例えばRubyで書かれた地図アプリ）のデータをPHPで書かれた天気予報サイトのアプリケーションに連携することができます。

WEBでないAPIは例えばWindowsでは専用のドライバーがあるとしたら、MACでそのドライバーを使用することは難しいと思います。

API連携という言葉を聞きますが、「WEB APIの連携」と言い換えることができます。

今ではRESTの設計思想を使い、データの形式はJSONでアプリケーション間のやりとりをすることが多いかと思います。

基本情報にWEBAPIとRESTは出ないのと、深く書こうと思えばいくらでも書けるところなので本当に表面的なところだけ記述しておきます。

## RPA
人手不足の解消などを目的として、業務改革を進めるために活用されつつあるのがRPAです。
Robotic Process Automationの略です。

ハードウェア的な産業用ロボットなどではなく、コンピュータの中に閉じたソフトウェア的なロボットを指します。

機械化する前には工場では、工員が手作業で作業を行なっていました。それが産業用ロボットの登場で自動化が進み、生産性を飛躍的に向上させました。
同様の事象がソフトウェアの世界にも起こってきています。
## まとめ
仕事は機械に任せて遊びましょう。
.NETCoreで"shift_jis"を使用する

## はじめに

```C#
using (StreamWriter sw = new StreamWriter(filepath, false, Encoding.GetEncoding("shift_jis")))
{
    ...
}
```

.NETCoreで上記のようにEncoding.GetEncoding("shift_jis")を指定したところ、実行時にエラーが発生して、
（´-`）.｡oO(？？？)
となったので備忘録。
![s-jis_error.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275170/6dd356a4-fd17-9c82-0a39-5c0251d1ce99.png)
要するに、「"shift_jis"なんてしらないよ！」と怒られている。

## やること

```C#
// ここを追加
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using (StreamWriter sw = new StreamWriter(filepath, false, System.Text.Encoding.GetEncoding("shift_jis")))
{
　　...
}
```

この一文を追加することで使用可能となる。
ここでは.NETFrameworkでサポートされている全てのエンコードを取得している。

## おわりに
.NETCoreではサポートされているエンコーディングが限られているようです。
- [参考](https://docs.microsoft.com/ja-jp/dotnet/api/system.text.codepagesencodingprovider?view=net-6.0#remarks)
SpeackerDeckをリモートコントロールできないか実験


SpeackerDeckに上げたスライドを外部から制御できないかなと思い、ブリッジさせる制御を書けないか試してみました。

> https://speakerdeck.com/n0bisuke2/puroziekutohe-tun-dewebfalsewei-lai-wogan-zitemiyou-number-jsfes-number-projectfugu

CodePen上に埋め込みして試しています。

> ![スクリーンショット 2022-07-20 18.00.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/1801f8dd-75f1-6dd5-7063-34536d2feefb.png "スクリーンショット 2022-07-20 18.00.35.png")

試した際には`Copy javascript embed code`の方を選択しています。

## メニューを出す

`js-sd-player`というclassの箇所がスライド下部のホバーすると出てくる

```js
document.querySelector('.js-sd-player').classList.add('show-controls')
```

> ![](https://i.gyazo.com/fdfaeb1cd23f7dc67ab0ba4484412c5d.gif)

## ページ移動

メニューを出した状態（show-controlsクラスがついている状態）でアイコンをクリックさせます。`js-sd-player-next`と`js-sd-player-previous`のclassが付いてました。

> ![](https://i.gyazo.com/d043b4adbda576cb97473482ccb88dec.gif)

### 次のページ

```js
document.querySelector(`div.js-sd-player-next`).click()
```

### 一つ戻る

```js
document.querySelector(`div.js-sd-player-previous`).click()
```

## 所感

無事に動いたといえば動きました。

メニューを出した状態じゃないとうまく動かないのが今回ちょっとハマったところです。

本家のHTMLの構成が変われば使えなくなるのでちょっと試してみたくらいなやつですね。

そもそもSpeakerDeckのJS SDKみたいなものがあるといいんですけどないですかね......
AWS CDK synth or deploy時のFailed to bundle asset

私だけかもしれませんが、大分嵌ったので、メモを残します。

# 環境
Windows10 WSL2 (Ubuntu18.04)  
WLS2内でCDKのソースコードを保有してDockerコンテナへVolumeマウントしている状態。  
WSL2のファイルはローカルユーザーがオーナー(1000:1000)  
ファイル、ディレクトリのパーミッションはフルアクセスでコンテナのユーザーもRW可能な状態  

aws-lambda-nodejsのNodejsFunction()を利用しbuildingオプションのforceDockerBundlingはfalseを設定済.
(コンテナでビルドせずにローカルのesbuildを利用する設定)

# 問題事象
WSL2環境のDockerコンテナにAWS CDKをインストールして、コンテナのrootユーザーでcdkコマンドを実行するとこうなる事象に遭遇
```
$cdk synth
Error: Failed to bundle asset xxxxxxxxx/Code/Stage, bundle output is located at XXXXXXX
(省略)
Error: bash -c npx --no-install esbuild --bundle /xxxxxx/hoge.ts"
```

意味がわからないのでソースを見てみました。（やっぱり。わかりませんw）
[ここでエラーが発生する模様. asset-staging.ts#L446](https://github.com/aws/aws-cdk/blob/74318c7d22bfc00de9e005f68a0a6aaa58c7db39/packages/%40aws-cdk/core/lib/asset-staging.ts#L446)

もう少し辿ってみた。
[bundling.ts#L252](https://github.com/aws/aws-cdk/blob/74318c7d22bfc00de9e005f68a0a6aaa58c7db39/packages/%40aws-cdk/aws-lambda-nodejs/lib/bundling.ts#L252)

エラーメッセージから薄っすらわかっていましたが、コードを見てもやはりesbuildを実行しようとして失敗しているらしい。
エラーになったと思われるesbuildをコンテナのshellで実行すると正しく実行できる。
CDKコマンド内ではesbuildが失敗する。

> ファイルオーナー、パーミッションの問題じゃないハズ。。

摩訶不思議状態。

偶然、こんなコードがあることは確認しています。
```
asset-staging.ts#L446
      localBundling = options.local?.tryBundle(bundleDir, options);
      if (!localBundling) {
        let user: string;
        if (options.user) {
          user = options.user;
        } else { // Default to current user
          const userInfo = os.userInfo();
          user = userInfo.uid !== -1 // uid is -1 on Windows
            ? `${userInfo.uid}:${userInfo.gid}`
            : '1000:1000';
        }
```

> おそらく上記はなんの関係もない

あれ？やっぱりオーナー？？

> ズレてるけど、結果オーライw

# 解決
ファイル、ディレクトリのオーナーをrootにする。

これは未検証ですがcdk.outのパーミッションだけ変更すればよかったかもしれない。
突然コーディングをしてみたくなったのでやってみた。

## 初めに。
はい、タイトルのまんまです。
家で夏休みをのんびりと過ごしていたら、急に頭の中で西郷隆盛さんが現れて踊り出し、
「コーディング〜コーディング〜」と歌い出したので、コーディングをしたくなったという話です。

# 茶番ここまで。
とりあえず、2カラムのページを作ります。
なお、テーマカラーは`#72C3FA`です。

## 1.headerを作ってみる。
まずはheaderを作ってみます。

### html
```html
<!DOCTYPE html>
<html style="margin: 0;">
<head>
<title>header</title>
<link rel="stylesheet" href="reset.css">
</head>
<body style="margin: 0;">
  <header class="header">
    <p class="disc">サイトの説明文</p>
    <h1 class="title">サイト名</h1>
  </header>
</body>
</html>
```
はい、ここでポイントは```<link rel="stylesheet" href="reset.css">```です。
これは、リセットCSSと言ってブラウザ特有のCSSデザインを全て解除する役割を果たしています。

### CSS
```css
header{
  background-color: #72C3FA;
  height: 140px;
  margin: 0px;
  padding: 0px;
}
.disc{
  text-align: center;
  color: #FFFFFF;
  padding: 14px;
  font-size: 14px;
}
.title{
  text-align: center;
  color: #FFFFFF;
  font-size: 34px;
  margin:30px;
}
```

### 成果物
codepenにあげておきます。
https://codepen.io/railway-fun/pen/xxWqNxV
![F139B5C9-24D1-4667-8695-935FA0BF8CE3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740290/c9141870-7c7a-51f9-892b-e2c1198df0d0.jpeg)
実行するとこんな感じ。

## 2.footerを作ってみる。
次はサイトの一番下、footerを作ってみましょう。

### html
```html
  <footer class="footer">
    <div class="footer-site-name">
      サイト名
    </div>
    <div class="footer-spacer-1"></div>
    <div class="footer-credit">
      &copy; 2022 I-AM-RAILWAY-FAN.
    </div>
  </footer>
```

### css
```css
footer{
  background-color: #72C3FA;
  height: 90px;
  display: flex;
}
.footer-site-name{
  margin: 30px;
  width: 20%;
  color: #FFFFFF;
  font-size: 20px;
}
.footer-spacer-1{
  width: 30%;
}
.footer-credit{
  width: 50%;
  margin: 34px;
  text-align: right;
  color: #FFFFFF;
  font-size: 14px;
}
```
コードは先ほどのものに追記しちゃってください。

### 成果物
こちらもcodepenにあります。
https://codepen.io/railway-fun/pen/ZExKzgB
![B86A41FD-7F59-4071-B7CD-DCFE598826B1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740290/4b7802e0-8c2f-1e53-9963-649d7c5ab67f.jpeg)
実行するとこんな感じ。

## 3.bodyを2カラムにしてみる。
### html
```html
  <div class="body">
    <main class="main">
      春はあけぼの。やうやう白くなりゆく山際、少し明かりて、紫だちたる雲の細くたなびきたる。 
      夏は夜。月のころはさらなり、闇もなほ、蛍の多く飛びちがひたる。また、ただ一つ二つなど、ほのかにうち光て行くもをかし。雨など降るもをかし。 
      秋は夕暮れ。夕日の差して山の端いと近うなりたるに、烏の寝所へ行くとて、三つ四つ、二つ三つなど飛び急ぐさへあはれなり。まいて雁などの連ねたるが、いと小さく見ゆるは、いとをかし。日入り果てて、風の音、虫の音など、はた言ふべきにあらず。 
      冬はつとめて。雪の降りたるは言ふべきにもあらず、霜のいと白きも、またさらでもいと寒きに、火など急ぎおこして、炭持て渡るも、いとつきづきし。昼になりて、ぬるくゆるびもていけば、火桶の火も、白き灰がちになりてわろし。
    </main>
    <sub class="sub">
      a
    </sub>
  </div>
```

### CSS
```css
.body{
  display: flex;
  background-color: #f4f5f7;
}
.main{
  background-color: #FFFFFF;
  width: 70%;
  margin: 1%;
}
.sub{
  background-color: #FFFFFF;
  width: 28%;
  margin: 1%;
}
```

### 成果物
codepenに載せてます。
https://codepen.io/railway-fun/pen/NWYjWjx

## 組み合わせると...
これらを組み合わせると、こんな感じになります。
![ADAF3B98-AA3E-452D-8061-2311FB6308BE.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740290/e6064cee-53a9-eff7-feca-f18ffad0d6cd.jpeg)

次回からは管理画面を作ろうと思います。


## 追記
あ、メニュー作り忘れた。
[Watson Discovery] ファセットをグループ化して表示する

Watson Discovery の Content Miner で分析を行うとき、ファセットの数が多い場合にファセットをグループ化して見やすくする方法を紹介します。

# 環境
Watson Discovery Premium on Cloud の Content Mining Project

# 設定手順
:::note warn
ここで行う設定はブラウザに保存されるため、**他のユーザの分析画面には反映されません**のでご注意ください。
:::


### 1. [Facet analysis]の横にある[Edit]アイコン（鉛筆マーク）をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/01b96422-8540-48b6-9b98-d8da7e37cd79.png)

### 2. [Add a new group]をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/8643b68b-6c5a-3014-1538-b6607cd96028.png)


### 3. [New group]をクリックし、右側の[Label]欄にファセットグループとして表示する名称を入力します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/a406abfe-5716-ff81-b9a5-3beb76afc345.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/12df8ff8-057e-267f-0b49-3820e5dafdae.png)

### 4. [Edit]ボタンをクリックしてこのグループに含めるファセットを選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/b8971959-74d2-7d94-70dc-6a0d4b67424c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/4ec90bea-ebd6-f8bf-b30d-2140d10cba60.png)

### 5. [Apply]ボタンをクリックします

:::note info
[Add a sub group]をクリックするとさらに階層を設定できます
:::
:::note info
[Top][Bottom]のラジオボタンで、ファセットツリーの上部に表示するか下部に表示するかを指定できます
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/a1a85d28-2f1f-f0df-74b4-4593ed4258c6.png)

### 6. ファセットがグループ化されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/027c049d-06a5-dda9-93c2-c618322989cb.png)

設定手順は以上です。
IQKeyboardManagerを使用する際、特定の画面のみ機能を無効にする

IQKeyboardManagerはとても便利なライブラリですが、他UIライブラリとの相性が悪く思い通りに動作しないことがあります。

MessageKitというライブラリを使用した際に、IQKeyboardManagerの機能が有効だったためUI周りの挙動がうまく制御できませんでした。そこでIQKeyboardManagerのdisabledDistanceHandlingClassesを使用し特定の画面のみライブラリの機能が無効になるよう設定しました。
 

## AppDelegate  didFinishLaunchingWithOptions()内に無効化する処理を追加する

**IQKeyboardManager.shared.disabledDistanceHandlingClasses.append(xxx.self)**

```Swift
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        IQKeyboardManager.shared.enable = true
        IQKeyboardManager.shared.disabledDistanceHandlingClasses.append(xxx.self)
        return true
    }
```

簡単に特定の画面のみIQKeyboardManagerの機能を無効化できました。
他UI系ライブラリとバッティングする場合は状況に応じて無効化すると良さそうです。
お粗末さまでした。
Collectionを変更不可にする（Collections.unmodifiableXX）

MAPを使用する際、「Collections.unmodifiable使ってください」と指示があったのでどういうものなのか調べました。



## 実際に使用したコード例

```
    /**
     * テストマップ.
     */
    private static final Map<String, String> TEST_MAP =
            Collections.unmodifiableMap(new HashMap<String, String>() {
                {
                    put("MAP_KEY1", "MAP_VALUE1");
                    put("MAP_KEY2", "MAP_VALUE2");
                    put("MAP_KEY3", "MAP_VALUE3");
                    put("MAP_KEY4", "MAP_VALUE4");
                }
            });
```

## どういったときに使用する？
Map、Set、ListなどのCollectionを、変更不可なものとして扱うのに
Collections::unmodifiableXXX を使う方法があります。

add, put, remove などの、コレクションの追加、削除などを抑制する事ができます。

今回はMAPの値を変更したくなかったので、こちらを使用してくれと指示があったのだと理解しました。
今週の学び　第11回

# 今週の学び

jQueryなど

- $(this)
  - $(this)にしていないと上から id を取られるので、正しく作動しない場合がある

- 常に console.log する

- prev()
  - prev()のパラメータに絞りこみたいセレクタを指定することで、そのセレクタに一致する兄弟要素を対象にすることができる

その他業界用語など

- ブロックチェーン
  - 仮想通貨に使われる技術である。
    ブロックチェーンとは例えるなら、１つの巻物のような物で、その巻物に対してトランザクションデータを時系列順に取引履歴などを書き込むイメージである。
    さらに、従来の中央集権で１台のコンピュータが集中管理するのではなく、ユーザー同士が P2P(分散管理)する技術なので、ユーザー全員のパソコンの出力合計より、１台でそれを上回るパソコンは現状存在しないので改ざん耐性が高い。
- NFT

  - NFT とは「Non-Fungible Token」の略で、fungible は代替可能という意味。
    つまり NFT は『代替不可能なトークン』ということ
    NFT 登場前にはデジタルデータはコピー・複製することにより量産でき、希少価値が無かったが、そんなデジタルデータに唯一無二の価値を持たせたのが NFT である

- デジタルマーケティング
  - デジタルマーケティング（Digital Marketing）はデジタル技術を活用したマーケティング手法すべてを意味する
    デジタル技術を活用したマーケティングとは、たとえばインターネット、アプリ、デジタルサイネージ、IT 技術、AI 技術など、かなり広い領域にわたります。
    元々、欧米では「Web マーケティング」よりも「デジタルマーケティング」という言葉が主に使用されていた

# まとめ

コードの書き方も大事だが、業界で常識的な用語などもしっかり覚えていく
【メモ】JSFのタグ

JSFを触る機会があったときに思い出せるよう、よく使用したタグを軽くメモ。

# 基本
## ui:composition
```
<ui:composition></ui:composition>
```
大枠。xmlnsの指定やtemplateの読み込みができる。
```（例）
<ui:composition xmlns="http://www.xx.xxx/1234/xhtml"
	xmlns:ui="http://java.xx.com/jsf/facelets"
	xmlns:h="http://java.xx.com/jsf/html"
	xmlns:f="http://java.xx.com/jsf/core"
	template="/WEB-INF/templates/testTemplate.xhtml">

～html～

</ui:composition>
```


## f:metadata

```
<f:metadata></f:metadata>
```
タグ内でバインド変数を渡したり、イベント実行できる。

```xhtml:（例）
	<f:metadata>
		<ui:param name="TestBean" value="#{testController}"/>
		<ui:param name="bean" value="#{testController}"/>
		<f:event type="preRenderView" listener="#{testController.preRenderView}" />
	</f:metadata>
```
## ui:define

```
<ui:define></ui:define>
```
jsやcssを指定できる。メインもこのタグで指定する。
```xhtml:（例①jsの場合）
	<ui:define name="contents-js">
		<script type="text/javascript" src="#{request.contextPath}/resources/js/test.js" />
		<script type="text/javascript" src="#{request.contextPath}/resources/js/header.js" />
	</ui:define>
```

```xhtml:（例②cssの場合）
	<ui:define name="contents-css">
		<link type="text/css" rel="stylesheet" href="#{request.contextPath}/resources/css/test.css" />
	</ui:define>
```

```xhtml:（例③メインの場合）
	<ui:define name="content">
		～html～
	</ui:define>
```

# その他
## ui:repeat
```
<ui:repeat value="#{bean.testList}" var="row" varStatus="testStat"></ui:repeat>
```
タグ内繰り返し。

## ui:fragment
```
<ui:fragment rendered="#{testController.flg}">></ui:fragment>
```
フラグがtrue／falseによって表示させるか否か制御できる。
## h:inputHidden
```
<h:inputHidden id="testId" value="#{testController.id}"></h:inputHidden>
```
画面に表示させないが値をjsに渡したい／画面で保持したい項目を設定することができる。
[SwiftUI]TextFieldのテキスト入力監視処理のサンプル

`TextField`の入力に`Combine`の`CurrentValueSubject`を使用してその値の変更を購読するという方針で行きます。

### ViewModelの実装

```TextInputViewModel.swift
import Foundation
import Combine

@MainActor
class TextInputViewModel: ObservableObject {
    @Published var resultText: String = ""
    @Published var inputText = CurrentValueSubject<String, Never>("")

    private var cancellables = [AnyCancellable]()

    func subscribeInputText() {
        inputText
            .debounce(for: 1, scheduler: RunLoop.main)
            .removeDuplicates()
            .sink {[weak self] value in
                guard let self = self else { return }
                self.resultText = value
                // TODO: 検索候補の取得等
            }
            .store(in: &cancellables)
    }

}

```
- `.debounce(for: 1, scheduler: RunLoop.main)`
これで入力中の処理を1秒間遅延させて連続で値が流れないようにします。

- `.removeDuplicates()`
以前と同じ値を弾きます。

- `.sink`
でresultTextに直接Stringを渡していますが、本来なら検索処理だったり検索候補を取得などの処理をすることが考えられます。



### View側の実装
```TextInputView.swift
import SwiftUI

struct TextInputView: View {
    @StateObject var viewModel: TextInputViewModel

    var body: some View {
        VStack {
            TextField("placeholder", text: $viewModel.inputText.value)
            .padding()
            .border(.red, width: 1.0)
            .padding(.bottom, 20)
            Text(viewModel.resultText)
        }
        .padding()
        .onAppear {
            viewModel.subscribeInputText()
        }
    }
}

```
- `TextField("placeholder", text: $viewModel.inputText.value)`
ViewModelのCurrentValueSubjectをBindingします。

- `.padding().border(.red, width: 1.0)`
こちらは先にpaddingを入れることでボーダーの内部に隙間を入れています。

- `Text(viewModel.resultText)`
入力結果をそのまま表示するラベルです。

- `.onAppear `
ここで`viewModel.subscribeInputText()` `TextField`の`inputText`の監視を開始する関数を呼び出します。

## 結果
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678249/cd5b8008-0db0-dd4f-92d0-91b12d2715a4.gif" width="160">